home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / TOOLS2.ZIP / CTAGS.C < prev    next >
C/C++ Source or Header  |  1988-03-25  |  6KB  |  324 lines

  1. /**
  2.  
  3.     CTAGS.C
  4.     
  5.     Unix-style CTAGS utility for MS OS/2 and MS DOS 3.X.
  6.  
  7. **/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. /**
  15.  
  16.     Constants and Types
  17.  
  18. **/
  19.  
  20. #ifdef TRUE
  21. #undef TRUE
  22. #endif
  23. #ifdef FALSE
  24. #undef FALSE
  25. #endif
  26.  
  27. #define TRUE        1
  28. #define FALSE        0
  29. #define MAXLINE        256
  30. #define MAXNAME        31
  31.  
  32. /**
  33.  
  34.     Static Variables
  35.  
  36. **/
  37.  
  38. static int nLevel ;        /* nesting level */
  39. static char szLine[MAXLINE] ;    /* line read from file */
  40. static char *szCur ;        /* current position in buffer */
  41. static FILE *pTags ;        /* TAGS file pointer */
  42.  
  43. /**
  44.  
  45.     SkipComment()
  46.     
  47.     Skip from the current point in the file to the next end of comment
  48.     line characters. This function should be called with the current
  49.     line in the buffer szLine, and the current point in the    buffer
  50.     pointed to by szCur.
  51.     
  52.     If the end of the comment is found in szLine, szCur will point to 
  53.     the character after the comment in szLine, and the function will
  54.     return TRUE.
  55.     
  56.     If the end of the comment is not found in the buffer, the function
  57.     will return FALSE.
  58.  
  59. **/
  60.  
  61. int SkipComment()
  62. {
  63.     int bGotStar = FALSE ;        /* TRUE if we have '*' */
  64.  
  65.     while ( *szCur )
  66.     {
  67.         switch( *szCur )
  68.         {
  69.         case '/':        /* end of comment? */
  70.             if ( bGotStar )
  71.             {
  72.                 ++szCur ;
  73.                 return TRUE;
  74.             }
  75.             break ;
  76.         case '*':        /* set star flag */
  77.             bGotStar = TRUE ;
  78.             break ;
  79.         default:
  80.             bGotStar = FALSE ;
  81.         }
  82.         ++szCur ;
  83.     }
  84.     return FALSE ;
  85. }
  86.  
  87. /**
  88.  
  89.     SkipUntil()
  90.     
  91.     Skip from the current point in the file to the end of a quoted
  92.     string. This function should be called with the current    line in 
  93.     the buffer szLine, and the current point in the    buffer pointed
  94.     to by szCur.
  95.     
  96.     If the end of the string is found in szLine, szCur will point to 
  97.     the character after the string in szLine, and the function will
  98.     return TRUE.
  99.     
  100.     If the end of the string is not found in the buffer, the function
  101.     will return FALSE.
  102.  
  103. **/
  104.  
  105. int SkipUntil( cBreak )
  106. int cBreak ;            /* break character */
  107. {
  108.     int bSkipNext = FALSE ;        /* TRUE if we have '\' */
  109.     
  110.     while ( *(++szCur) )
  111.     {
  112.         if ( *szCur == (char)cBreak && ! bSkipNext  )
  113.         {
  114.             ++szCur ;
  115.             return TRUE;
  116.         }
  117.         else switch( *szCur )
  118.         {
  119.         case '\\':        /* set escaping flag */
  120.             bSkipNext = ! bSkipNext ;
  121.             break ;
  122.         default:
  123.             bSkipNext = FALSE ;
  124.         }
  125.     }
  126.     return FALSE ;
  127. }
  128.  
  129. /**
  130.  
  131.     ProcessDecl() - process a function declaration
  132.  
  133.     This routine will determine whether the line in the buffer is
  134.     the start of a function or a forward reference.  It will make
  135.     its determination by whether it encounters a newline ,semicolon,
  136.     or comma after the function declaration.
  137.  
  138. **/
  139.  
  140. void ProcessDecl( szFile )
  141. char *szFile ;
  142. {
  143.     char szFuncName[MAXNAME] ;
  144.     char *szTmp ;
  145.     int nLength ;
  146.     int nParenLevel = 0 ;
  147.     
  148.     /*--- check to see if prototype or declaration ---*/
  149.     szTmp = szCur ;
  150.     while ( *szTmp )
  151.     {
  152.         if ( *szTmp == '\n' )
  153.         {
  154.             /*--- back up to find the function name ---*/
  155.             *szTmp = '\0' ;    
  156.             szTmp = szCur - 1 ;
  157.  
  158.             while ( isspace( *szTmp ) )
  159.                 --szTmp ;
  160.             while ( !isspace(*szTmp) && szTmp >= szLine && 
  161.                             *szTmp != '*' )
  162.                 --szTmp ;
  163.             ++szTmp ;
  164.             nLength = (szCur - szTmp) ;
  165.             strncpy( szFuncName, szTmp, nLength ) ;
  166.             szFuncName[nLength] = '\0' ; 
  167.             fprintf( pTags, "%s \t%s \t^", szFuncName, szFile) ;
  168.             szTmp = szLine ;
  169.             while ( *szTmp )
  170.             {
  171.                 /* 'escape' special GREP chars */
  172.                 if ( strchr("\\^$.:*+[]", *szTmp) )
  173.                     putc( '\\', pTags ) ;
  174.                 putc( *szTmp++, pTags ) ;
  175.             }
  176.             fprintf( pTags, "$\n" ) ;
  177.             break ;
  178.         }
  179.         else if ( *szTmp == ')' )
  180.         {
  181.             nParenLevel-- ;
  182.             ++szTmp ;
  183.         }
  184.         else if ( *szTmp == '(' )
  185.         {
  186.             nParenLevel++ ;
  187.             ++szTmp ;
  188.         }
  189.         else if ( *szTmp == ',' )
  190.         {
  191.             if ( nParenLevel == 0 )
  192.                 break ;
  193.             ++szTmp ;
  194.         }
  195.         else if ( *szTmp == ';' )
  196.             break ;
  197.         else
  198.             ++szTmp ;
  199.     }
  200. }
  201.  
  202. /**
  203.  
  204.     FindDecls()
  205.     
  206.     Find a C declaration.
  207.  
  208. **/
  209.  
  210. void FindDecls( szFile )
  211. char *szFile ;
  212. {
  213.     FILE *fp ;
  214.     int bComment = FALSE ;
  215.     int Done = FALSE ;
  216.     
  217.     if ( (fp = fopen(szFile, "rt")) == NULL )
  218.     {
  219.         fprintf( stderr, "Unable to open input file %s.\n", szFile ) ;
  220.         return ;
  221.     }
  222.     
  223.     while ( ! feof(fp) )
  224.     {
  225.         fgets( szLine, MAXLINE-1, fp ) ;
  226.         
  227.         szCur = szLine ;
  228.         Done = FALSE ;
  229.         
  230.         while ( ! Done )
  231.         {
  232.             switch ( *szCur )
  233.             {
  234.             case '\n':    /* end of string */
  235.             case '\0':
  236.                 Done = TRUE ;
  237.                 break ;
  238.             case '/':    /* set comment flag */
  239.                 bComment = TRUE ;
  240.                 break ;
  241.             case '*':
  242.                 if ( bComment )
  243.                 {
  244.                     while ( ! SkipComment() && ! feof(fp) )
  245.                     {
  246.                         szCur = szLine ;
  247.                         fgets( szLine, MAXLINE-1, fp ) ;
  248.                     }
  249.                 }
  250.                 bComment = FALSE ;
  251.                 break ;
  252.             case '\"':    /* process double quoted string */
  253.                 bComment = FALSE ;
  254.                 while ( ! SkipUntil('\"') && ! feof(fp) ) 
  255.                 {
  256.                     fgets( szLine, MAXLINE-1, fp ) ;
  257.                     szCur = szLine ;
  258.                 }
  259.                 break ;
  260.             case '\'':    /* process single quoted constant */
  261.                 bComment = FALSE ;
  262.                 while ( ! SkipUntil('\'') && ! feof(fp) ) 
  263.                 {
  264.                     fgets( szLine, MAXLINE-1, fp ) ;
  265.                     szCur = szLine ;
  266.                 }
  267.                 break ;
  268.             case '{':
  269.                 bComment = FALSE ;
  270.                 ++nLevel ;
  271.                 break ;
  272.             case '}':
  273.                 bComment = FALSE ;
  274.                 --nLevel ;
  275.                 break ;
  276.             case '(':    /* start of function call */
  277.                 if ( nLevel == 0 )
  278.                     ProcessDecl( szFile ) ;
  279.                 break ;
  280.             }
  281.             ++szCur ;
  282.         }
  283.     }
  284.     fclose( fp ) ;
  285. }
  286.  
  287. /**
  288.  
  289.     Main Routine
  290.  
  291. **/
  292.  
  293. void main( argc, argv )
  294. int argc ;
  295. char *argv[] ;
  296. {
  297.     int count ;
  298.     
  299.     fprintf( stderr, "CTAGS - C file tag utility\n" ) ;
  300.     fprintf( stderr, "Copyright (c)1988 Computer Aided Planning, Inc.\n" ) ;
  301.     fprintf( stderr, "All Rights Reserved\n\n" ) ;
  302.     
  303.     if ( argc < 2 )
  304.     {
  305.         fprintf( stderr, "Usage: CTAGS file [file...]\n" ) ;
  306.         exit(1) ;
  307.     }
  308.     
  309.     if ( (pTags = fopen("TAGS", "wt")) == NULL )
  310.     {
  311.         fprintf( stderr, "Unable to open output file TAGS\n" ) ;
  312.         exit(1) ;
  313.     }
  314.     
  315.     count = 1 ;
  316.     while ( count < argc )
  317.     {
  318.         nLevel = 0 ;
  319.         FindDecls( argv[count++] ) ;
  320.     }
  321.         
  322.     fclose( pTags ) ;
  323. }
  324.