#
/*
 *
 *
 * The  information  in  this  document  is  subject  to  change
 * without  notice  and  should not be construed as a commitment
 * by Digital Equipment Corporation or by DECUS.
 * 
 * Neither Digital Equipment Corporation, DECUS, nor the authors
 * assume any responsibility for the use or reliability of  this
 * document or the described software.
 * 
 * 	Copyright (C) 1980, DECUS
 * 
 * 
 * General permission to copy or modify, but not for profit,  is
 * hereby  granted,  provided that the above copyright notice is
 * included and reference made to  the  fact  that  reproduction
 * privileges were granted by DECUS.
 *
 */

/*
 *                      ***************
 *                      * X R F 1 . C *
 *                      ***************
 *
 * Lexical processing for C xref'er. Sifts through C source code
 * and pulls out the identifiers. Recognizes reserved words and
 * disregards them. Returns non-zero integer (true) if an id was
 * successfully moved into 'idbuf', zero (false) if end-of-line
 * was reached. I took care to test the C compiler's reaction to
 * Formfeeds with respect to line numbers, and made sure the line
 * numbers assigned by xrf act the same.
 *
 * Version V1.3          9-May-80
 * Version V1.4		10-Jul-80 MM	Allow $ in identifiers, bummed code
 * Version V1.5		21-Jul-80 MM	Dropped newline from ctime()
 * Version V1.6		22-Jul-80 MM	'.' is not an alpha char.
 */

#include <stdio.h>
#include "xrf.h"

#define A 1             /* Alpha character */
#define C 2             /* Start of comment possibly */
#define L 3             /* Literal delimiter */
#define N 4             /* Numeric character */
#define Z 5             /* End of string */

#define NRW 28          /* # reserved words */

static int cmtflg= 0;            /* Comment flag */

static char ctype[] = {         /* Character action lookup */
                        Z,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                        0,0,L,0,A,0,0,L,0,0,0,0,0,0,0,C,
                        N,N,N,N,N,N,N,N,N,N,0,0,0,0,0,0,
                        0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,
                        A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,A,
                        0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,
                        A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,0
                      };


static char *reswrd[NRW] = {
                        "auto", "break", "case", "char",
                        "continue", "default", "do", "double",
                        "else", "entry", "extern", "float",
                        "for", "goto", "if", "int",
                        "long", "register", "return", "short",
                        "sizeof", "static", "struct", "switch",
                        "typedef", "union", "unsigned", "while"
                        };





/*

 * Scan off a non reserved identifier. Put it into 'idbuf'.

 * Returns +1 if successful, 0 if end-of-line was reached.

 *

 */



getid()                         /* Get an identifier into idbuf */



   {

   register char *p ;                   /* Fast scan pointer */

   register char *i ;                   /* Fast id buf pointer */

   register int c;                      /* Dispatch code */



   p = scanp;                           /* Init fast pointers */

   i = idbuf;



   while ((c = *p) != 0)                /* Scan till end of string */

      {



      if(c == '\014')                   /* If formfeed, */

         {

         c = *p = ' ';                  /* Convert to harmless blank */

         newpage();                     /* Force new page */

         }



      if (cmtflg)                       /* If comment flag is on */

         {

         while(*p && *p++ != '*');	/* Scan to '*' or end of string */

         if(*p == '/')                  /* If we found end of comment */

            cmtflg = 0;                 /* Turn off comment flag */

         continue;                      /* and recycle */

         }



      switch(ctype[c])			/* Dispatch on the type */

         {

         case A:                        /* Start of an identifier */

            i = idbuf;                  /* Reset the id buffer pointer */

            do

               if( i < &idbuf[NCPS] )   /* Copy into idbuf */

                  *i++ = *p++;

               else                     /* Unless it gets full */

                  p++;

            while( (c=ctype[*p]) == A || c == N ); /* While alphanumeric */



            while( i < &idbuf[NCPS] )   /* Pad idbuf with nulls */

               *i++ = '\0';

            if(nonres(idbuf))           /* If it's not a reserved word */

               {

               scanp = p;               /* Update the scan pointer */

               return (1);              /* Return with success */

               }

            break;                      /* End of identifier processing */



         case N:                        /* Scan by a number string */

            do p++; while( (c=ctype[*p]) == N || c == A );

            break;



         case L:                        /* Scan by a literal */

	    while (*++p != c && *p) {	/* Scan to the matching trailing */

		if (*p == '\\') p++;	/* Quote, ignoring backslash quoted */

	    }				/* Characters.  If not at the end */

	    if (*p) p++;		/* Of the line, skip to the char. */

            break;			/* Following the trailing quote */



         case C:

            if(*++p == '*')             /* Start a comment */

              cmtflg = 1;               /* by setting comment flag */

            break;



         default:                       /* Otherwise just scan it off */

            p++;

            break;

         }                              /* End of switch statement */



      }                         /* If we exit here, end-of line. */

   return(0);                   /* Return with failure indication */

   }








/*

 * Search for reserved word. Return true (1) if NOT reserved word.

 * Uses binary search.

 */





nonres( bufp )                  /* Test if not reserved word */

char *bufp;



   {

   register int low ;           /* Low pointer index */

   register int mid ;           /* Mid ... */

   register int hi  ;           /* hi ...  */



   int cond;                    /* Condition from strcmp */



   low = 0;

   hi  = NRW-1;



   while (low <= hi)

      {

      mid = (low + hi) / 2;

      if((cond = strcmp(bufp, reswrd[mid])) < 0)

         hi = mid - 1;

      else if (cond > 0)

         low = mid + 1;

      else

         return(0);             /* False, it IS reserved */

      }

   return(1);                   /* True, it's NOT reserved */

   }



