Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/old/kc/cc3.c
There are no other files named cc3.c in the archive.
/* cc3.c -- Preprocessor   (C) 1981  K. Chen */

#define	    sc extern
#include    "cc.h"

/* struct SYMBOL *findsym(); */

/* ---------------------------------------------- */
/*	get next character from input source      */
/* ---------------------------------------------- */

nextc()
{
  int i;

  if (maclevel) {		/* non-zero macro-level */
      if (i = *macptr++) {	/*   => macro expansion */
          if (i < 7) {		/*      => arguments    */
	      mac[maclevel].mptr = macptr;
	      macptr = mac[maclevel++].marg[i-1];
	      return nextc();
	  }
	  return ch = i;
      }
      if (--maclevel) {
	  macptr = mac[maclevel].mptr;
      }
      return ch = nextc();
  }

  if ((i = getc(in)) == '#' && ch == '\n')
      return preprocess();

  switch (i) {
  case EOF:
      if (level-- > 0) {
          in = inc[level].cptr;
          line = inc[level].cline;
	  page = inc[level].cpage;
          strcpy(input, inc[level].cname);
          ch = '\n';
	  erptr = errlin;
	  *erptr = 0;
          return ch = nextc();
      }
      eof = 1;
      return ch = 0;
  case '\n':
      line++;
      tline++;
      erptr = errlin;
      *erptr = 0;
      break;
  case 014:
      line = 1;
      page++;
      erptr = errlin;
      *erptr = 0;
      break;
  default:
      *erptr++ = i;
  }
  return ch = i;
}


/* ----------------------------------------------------- */
/*	push a character back into the input source      */
/* ----------------------------------------------------- */

pushc(c)
{
  if (c == '\n') {
      line--;
      tline--;
  }
  if (maclevel)
      macptr--;
  else 
      ungetc(c, in);
}


/* ------------------------------- */
/*	service a # statement      */
/* ------------------------------- */

preprocess()
{
  int i;
  char s[_IDSIZE];

  do i = nextc(); while (i == ' ' || i == '\t');

  if (map[i] != IDENT) {
      error(EIDENT);
      flushline(i);   
  }
  else {
      switch (getstring(s, i)) {
      case 4:
           if (!strcmp(s,"else")) celse();
	   else {
               error(EMACRO, s);
	       flushline(0);
	   }
	   break;
      case 5:
           if (!strcmp(s,"endif")) cendif(); else
           if (!strcmp(s,"ifdef")) cifdef(0); else
           if (!strcmp(s,"undef")) undefine();
	   else {
               error(EMACRO, s);
	       flushline(0);
	   }
	   break;
      case 6:
           if (!strcmp(s,"define")) {
	       if (ncond < 0 || nelse < 0) flushline(0); else define(); 
	   } else
           if (!strcmp(s,"ifndef")) cifdef(1);
	   else {
               error(EMACRO, s);
	       flushline(0);
	   }
	   break;
      case 7:
           if (!strcmp(s,"include")) include();
	   else {
               error(EMACRO, s);
	       flushline(0);
	   }
	   break;
      default:
           error(EMACRO, s);
	   flushline(0);
      }
  }
  return ch = '\n';
}


/* ----------------------- */
/*	#define macro      */
/* ----------------------- */

define()
{
  int    i, nargs;
  char   s[16], heap[100], *t, *args[7], *u;
  struct SYMBOL *creatsym(), *sym;

  nextc();
  skipblanks();
  if (map[ch] == IDENT) {
      getstring (s, ch);
      if ((sym=findsym(s)) != NULL && sym->sclass != SMACRO) {
          error (EDSYMB, s);
	  flushline(ch);
	  return;
      }
      if (sym == NULL) sym = creatsym(s);
      sym->smptr = cpool;
      sym->sclass = SMACRO;
      sym->svalue = 0;
      nextc();

      nargs = 0;
      if (ch == '(') {
	  t = heap;
          while (1) {
	      nextc();
	      skipblanks();
	      if (map[ch] != IDENT) {
	          nargs = 0;
	          error (EARG);
	          break;
	      }
	      args[nargs] = t;
	      getstring (u=s, ch);
	      while (*t++ = *u++) ;
	      nargs++;
	      nextc();
	      skipblanks();
	      if (ch != ',') break;
          }
          if (ch != ')') error (EARGEND);
	  else nextc();
      }
      sym->svalue = nargs;
      skipblanks();
      while (!eof && ch != '\n') {
          if (ch == '\\') {
              nextc();
	      if (ch != '\n') {
	          *cpool++ = '\\';
	          *cpool++ = ch;
	      }
          }
  	  else {
	      if (nargs && map[ch] == IDENT) {
		  getstring(s, ch);
		  for (i=0 ; i < nargs ; i++) {
		      if (strcmp(args[i], s) == 0) {
			  *cpool++ = i + 1;
			  break;
		      }
		  }
	          if (i >= nargs) {
		      t = s;
		      while (*t) *cpool++ = *t++;
		  }
	      }
	      else *cpool++ = ch;
	  }
	  nextc();
      }
      *cpool++ = ' ';
      *cpool++ = '\0';
  }
  else error (EIDENT);
  flushline(ch);
}

/* ---------------------- */
/*	#ifdef macro      */
/* ---------------------- */

cifdef(doit)
{
  int    yes;
  char   s[16];
  struct SYMBOL *sym;

  nextc();
  if (ncond) error(ECONTROL);
  skipblanks();
  if (map[ch] == IDENT) {
      getstring (s, ch);
      yes = ((sym=findsym(s)) == NULL || sym->sclass != SMACRO);
      if (!doit) yes = (yes) ? 0 : 1;
  }
  else {
      error (EIDENT);
      yes = 0;
  }
  flushline(ch);
  ncond = 1;  

  if (yes) return;	/* expand */

  ncond = -1;
  while (1) {
      if (ncond == 0 || eof) return;
      nextc();
      flushline(ch);
  }
}

/* ---------------------- */
/*      #else macro       */
/* ---------------------- */

celse()
{
  if (!ncond) error(ECONTROL);
  nelse = ncond;
  ncond = 0;
  if (ncond == 1) {
      while (1) {
          if (nelse == 0 || eof) return;
          nextc();
          flushline(ch);
      }
  }
}

/* ---------------------- */
/*	#endif macro      */
/* ---------------------- */

cendif()
{
  if (!ncond && !nelse) error(ECONTROL);
  ncond = nelse = 0;
}

/* ------------------------ */
/*	#include macro      */
/* ------------------------ */

include()
{
  char f[_FILSIZ];
  FILE *fp, *fopen();
  string s, t;

  skipblanks();
  s = f;
  switch (ch) {
  case '"': 
       nextc();
       while (ch != '"') {
           if (ch == '\n' || eof) {
	       if (eof) earlyend();
               error(EXFILE, f);
   	       return;
           }
           *s++ = ch;
           nextc();
       }
       break;
  case '<': 
       t = sprefix;
       while (*t) *s++ = *t++;
       nextc();
       while (ch != '>') {
           if (ch == '\n' || eof) {
	       if (eof) earlyend();
               error(EXFILE, f);
   	       return;
           }
           *s++ = ch;
           nextc();
       }
       t = spstfix;
       while (*t) *s++ = *t++;
       break;

  default:
       if (eof) earlyend();
       else {
           error(EXFILE);
	   flushline(0);
	   return;
       }
  }
  *s = 0;
  flushline(ch);
  fp = fopen(f, "r");
  if (fp == NULL) {		/* unsuccessful open */
      error(EFILE, f);
      return;
  }
  strcpy(inc[level].cname, input);	/* save old context */
  inc[level].cptr = in;
  inc[level].cline = line;
  inc[level].cpage = page;

  level++;				/* create new context */
  strcpy(input, f);
  in = fp;
  line = 1;
  page = 1;
}


/* ------------------------- */
/*	#undefine macro      */
/* ------------------------- */

undefine()
{
  char   s[16];
  struct SYMBOL *sym;

  nextc();
  skipblanks();
  if (map[ch] == IDENT) {
      getstring (s, ch);
      if ((sym=findsym(s)) != NULL) {
          if (sym->sclass != SMACRO)
              error (ENOTMAC);
	  else
	      symcpy(sym->sname, "*");
      }
      else error(EUNDEF,s);
      flushline(0);
      return;
  }
  error(EIDENT);
  flushline(ch);
}


/* ----------------------------------------------- */
/*	flushes input until the next \n or EOF     */
/* ----------------------------------------------- */

flushline(i)
{
  ch = i;
  while (ch != '\n') nextc();
}


/* --------------------------------------- */
/*	get a string from input source     */
/* --------------------------------------- */

getstring(s, c)
string s;
{
  int m, n;

  n = 0;
  do {
      *s++ = c;
      n++;
      m = map[c = nextc()];
  } while (m == IDENT || m == CONST);
  pushc(c);
  *s = 0;
  return n;
}


/* ------------------------------ */
/*	skip blanks and tabs      */
/* ------------------------------ */

skipblanks()
{
  while (ch == ' ' || ch == '\t') nextc();
}


/* ------------------------ */
/*	unexpected eof      */
/* ------------------------ */

earlyend()
{
  error(EEOF);
  exit(1);
}