home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / XRF / XRF1.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  9KB  |  218 lines

  1. /*
  2.  *                      ***************
  3.  *                      * X R F 1 . C *
  4.  *                      ***************
  5.  *
  6.  * Lexical processing for C xref'er. Sifts through C source code
  7.  * and pulls out the identifiers. Recognizes reserved words and
  8.  * disregards them. Returns non-zero integer (true) if an id was
  9.  * successfully moved into 'idbuf', zero (false) if end-of-line
  10.  * was reached. I took care to test the C compiler's reaction to
  11.  * Formfeeds with respect to line numbers, and made sure the line
  12.  * numbers assigned by xrf act the same.
  13.  *
  14.  * Version V1.3          9-May-80
  15.  * Version V1.4        10-Jul-80 MM    Allow $ in identifiers, bummed code
  16.  * Version V1.5        21-Jul-80 MM    Dropped newline from ctime()
  17.  * Version V1.6        22-Jul-80 MM    '.' is not an alpha char.
  18.  * Version V1.7         4-Jan-85 MC    MDOS version
  19.  * Version V1.8         8-Jan-85 MC    Allow for 8-bit characters and 
  20.  *                                      Preprocessor commands.
  21.  * Version V1.9        12-Jan-85 MC    Identify Function calls in key and
  22.  *                                      return fixed length Symbol
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include "xrf.h"
  27.  
  28. #define A 1             /* Alpha character */
  29. #define C 2             /* Start of comment possibly */
  30. #define F 3             /* Function Parameter start delimiter */
  31. #define L 4             /* Literal delimiter */
  32. #define N 5             /* Numeric character */
  33. #define P 6             /* Preprocessor Command */
  34. #define S 7             /* Space character */
  35. #define Z 9             /* End of string */
  36.  
  37. #define NRW  28          /* # reserved words */
  38. #define NRPW 7           /* # preprocessor words */
  39.  
  40. static int cmtflg = 0;    /* Comment flag */
  41.  
  42. static char ctype[] = {         /* Character action lookup */
  43.                         Z,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 00 - 0F*/
  44.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 10 - 1F*/
  45.                         S,0,L,P,A,0,0,L,F,0,0,0,0,0,0,C,    /* 20 - 2F*/
  46.                         N,N,N,N,N,N,N,N,N,N,0,0,0,0,0,0,    /* 30 - 3F*/
  47.                         0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,    /* 40 - 4F*/
  48.                         A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,A,    /* 50 - 5F*/
  49.                         0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,    /* 60 - 6F*/
  50.                         A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,0,    /* 70 - 7F*/
  51.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 80 - 8F*/
  52.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 90 - 9F*/
  53.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* A0 - AF*/
  54.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* B0 - BF*/
  55.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* C0 - CF*/
  56.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* D0 - DF*/
  57.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* E0 - EF*/
  58.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0     /* F0 - FF*/
  59.                       };
  60.  
  61. static char *reswrd[NRW] = {
  62.                         "auto", "break", "case", "char",
  63.                         "continue", "default", "do", "double",
  64.                         "else", "entry", "extern", "float",
  65.                         "for", "goto", "if", "int",
  66.                         "long", "register", "return", "short",
  67.                         "sizeof", "static", "struct", "switch",
  68.                         "typedef", "union", "unsigned", "while"
  69.                         };
  70. static char *respre[NRPW] = {
  71.                         "#define","#else","#if","#ifdef",
  72.                         "#ifndef","#include",""
  73.                         };
  74.  
  75.  
  76.  
  77. /*
  78.  * Scan off a non reserved identifier. Put it into 'idbuf'.
  79.  * Returns +1 if successful, 0 if end-of-line was reached.
  80.  *
  81.  */
  82.  
  83. getid()                         /* Get an identifier into idbuf */
  84. {
  85.    register char *p ;                   /* Fast scan pointer */
  86.    register char *i ;                   /* Fast id buf pointer */
  87.    register int c;                      /* Dispatch code */
  88.    register int s;                      /* start Dispatch code */
  89.    char ch;                             /* temp char hold */
  90.    char *fixup();                       /* returns updated scan pointer*/
  91.  
  92.    p = scanp;                           /* Init fast pointers */
  93.    i = idbuf;
  94.  
  95.    while ((c = *p) != 0){                /* Scan till end of string */
  96.  
  97.       if(c == '\014'){                   /* If formfeed, */
  98.          c = *p = ' ';                  /* Convert to harmless blank */
  99.          if(prnflg)newpage();           /* Force new page */
  100.          }
  101.  
  102.       if (cmtflg){                       /* If comment flag is on */
  103.          while(*p && *p++ != '*');    /* Scan to '*' or end of string */
  104.          if(*p == '/')                  /* If we found end of comment */
  105.             cmtflg = 0;                 /* Turn off comment flag */
  106.          continue;                      /* and recycle */
  107.          }
  108.  
  109.       switch(s=ctype[c]){            /* Dispatch on the type */
  110.          case P:                        /* Start of an Preprocessor command */
  111.          case A:                        /* Start of an identifier */
  112.             i = idbuf;                  /* Reset the id buffer pointer */
  113.             do
  114.                if( i < &idbuf[symbolsize] ) /* Copy into idbuf */
  115.                   *i++ = *p++;
  116.                else                     /* Unless it gets full */
  117.                   p++;
  118.             while( (c=ctype[*p]) == A || c == N ); /* While alphanumeric */
  119.  
  120.             while( i < &idbuf[NCPS] )    /* Pad idbuf with nulls to maxlen*/
  121.                *i++ = '\0';
  122.             if(s==A)                     /* if Symbol */
  123.                if(nonres(idbuf)){          /* If it's not a reserved word */
  124.                    scanp = fixup(p);       /* Update the scan pointer */
  125.                    return (1);             /* Return with stretched success */
  126.                    }
  127.             if(s==P)                     /* if Preprocesor command */
  128.                switch(findpr(idbuf)){
  129.                    case 5: while(*p&&ctype[*p]==S)p++;
  130.                            for(ch=*p++;*p&&*p!=ch;p++);
  131.                            break;          /* #include - lose name string*/
  132.                    }
  133.             break;                      /* End of identifier processing */
  134.  
  135.          case N:                        /* Scan by a number string */
  136.             do p++; while( (c=ctype[*p]) == N || c == A );
  137.             break;
  138.  
  139.          case L:                        /* Scan by a literal */
  140.         while (*++p != c && *p) {    /* Scan to the matching trailing */
  141.         if (*p == '\\') p++;    /* Quote, ignoring backslash quoted */
  142.         }                /* Characters.  If not at the end */
  143.         if (*p) p++;        /* Of the line, skip to the char. */
  144.             break;            /* Following the trailing quote */
  145.  
  146.          case C:
  147.             if(*++p == '*')             /* Start a comment */
  148.               cmtflg = 1;               /* by setting comment flag */
  149.             break;
  150.  
  151.          default:                       /* Otherwise just scan it off */
  152.             p++;
  153.             break;
  154.          }                              /* End of switch statement */
  155.  
  156.       }                         /* If we exit here, end-of line. */
  157.    return(0);                   /* Return with failure indication */
  158. }
  159.  
  160.  
  161.  
  162. /*
  163.  * Search for reserved word. Return true (1) if NOT reserved word.
  164.  * Uses binary search.
  165.  */
  166.  
  167. nonres( bufp )                  /* Test if not reserved word */
  168. char *bufp;
  169.  
  170.    {
  171.    register int low ;           /* Low pointer index */
  172.    register int mid ;           /* Mid ... */
  173.    register int hi  ;           /* hi ...  */
  174.  
  175.    int cond;                    /* Condition from strcmp */
  176.  
  177.    low = 0;
  178.    hi  = NRW-1;
  179.  
  180.    while (low <= hi)
  181.       {
  182.       mid = (low + hi) / 2;
  183.       if((cond = strcmp(bufp, reswrd[mid])) < 0)
  184.          hi = mid - 1;
  185.       else if (cond > 0)
  186.          low = mid + 1;
  187.       else
  188.          return(0);             /* False, it IS reserved */
  189.       }
  190.    return(1);                   /* True, it's NOT reserved */
  191.    }
  192.  
  193. /* find preprocessor command in table & return its position */
  194. /* as an identifier                                         */
  195. findpr(kp)
  196. char *kp;
  197. { int i;
  198.   for(i=0;strcmp(kp,respre[i]);i++);
  199.   return i;
  200. }
  201.  
  202. /* make variable length <idbuf> a fixed length [CPS] key  */
  203. /* The last two chars are () if procedure, else blank     */
  204. /* return updated line buffer ptr <p>                     */
  205.  
  206.  
  207. char *fixup(p)
  208. char *p;                  /* curr pointer */
  209. {  char *cp=idbuf;
  210.  
  211.    while(*cp)*cp++;              /*find end of symbol */
  212.    while(ctype[*p]==S)p++;        /*get next I/P non-space (not EOL) */
  213.    if(ctype[*p]==F){*cp++='(';*cp++=')';} /*if funct parameter start, flag */
  214.    while(cp<&idbuf[CPS])*cp++=' ';        /*pad symbol with spaces */
  215.    *cp='\0';                              /* failsafe*/
  216.    return p;
  217. }
  218.