/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* $Header$ */ /* PREPROCESSOR DRIVER */ #include #include #include "input.h" #include "obufsize.h" #include "arith.h" #include "LLlex.h" #include "class.h" #include "macro.h" #include "idf.h" #include "idfsize.h" #include "bits.h" #include "ln_prefix.h" #include "textsize.h" char _obuf[OBUFSIZE]; #ifdef DOBITS char bits[128]; #endif extern int InputLevel; Xflush() { sys_write(STDOUT, _obuf, OBUFSIZE); } static char *SkipComment(); extern char options[]; /* #pragma directives are saved here and passed to the compiler later on. */ struct prag_info { int pr_linnr; char *pr_fil; char *pr_text; }; static struct prag_info *pragma_tab; static int pragma_nr; do_pragma() { register int size = ITEXTSIZE; char *cur_line = Malloc(size); register char *c_ptr = cur_line; register int c = GetChar(); *c_ptr = '\0'; while(c != '\n') { if (c_ptr + 1 - cur_line == size) { cur_line = Realloc(cur_line, (unsigned)(size += ITEXTSIZE)); c_ptr = cur_line + size - 1; } *c_ptr++ = c; c = GetChar(); } *c_ptr = '\0'; if (!pragma_nr) { pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info)); } else { pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab , (unsigned)(sizeof(struct prag_info) * (pragma_nr+1))); } pragma_tab[pragma_nr].pr_linnr = LineNumber; pragma_tab[pragma_nr].pr_fil = FileName; pragma_tab[pragma_nr].pr_text = cur_line; pragma_nr++; LineNumber++; } preprocess(fn) char *fn; { register int c; register char *op = _obuf; register char *ob = &_obuf[OBUFSIZE]; char Xbuf[256]; int lineno = 0; int startline; #define flush(X) (sys_write(STDOUT,_obuf,X)) #define echo(ch) if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch); #define newline() echo('\n') if (!options['P']) { /* Generate a line directive communicating the source filename */ register char *p = Xbuf; sprint(p, "%s 1 \"%s\"\n", LINE_PREFIX, FileName); while (*p) { echo(*p++); } } #define do_line_dir(lineno, fn) \ if (lineno != LineNumber || fn != FileName) { \ fn = FileName; \ lineno = LineNumber; \ if (! options['P']) { \ register char *p = Xbuf; \ \ sprint(p, "%s %d \"%s\"\n", \ LINE_PREFIX, \ LineNumber, \ FileName); \ while (*p) { \ echo(*p++); \ } \ } \ } for (;;) { LineNumber++; lineno++; startline = 1; c = GetChar(); while (startline) { /* first flush the saved pragma's */ if (pragma_nr) { register int i = 0; int LiNo = LineNumber; char *FiNam = FileName; while (i < pragma_nr) { register char *c_ptr = "#pragma"; LineNumber = pragma_tab[i].pr_linnr; FileName = pragma_tab[i].pr_fil; do_line_dir(lineno, fn); while (*c_ptr) { echo(*c_ptr++); } c_ptr = pragma_tab[i].pr_text; while (*c_ptr) { echo(*c_ptr++); } newline(); lineno++; free(pragma_tab[i].pr_text); i++; } free((char *) pragma_tab); pragma_tab = (struct prag_info *)0; pragma_nr = 0; LineNumber = LiNo; FileName = FiNam; do_line_dir(lineno, fn); } while (class(c) == STSKIP || c == '/') { if (c == '/') { if (!InputLevel) { c = GetChar(); if (c == '*') { op = SkipComment(op, &lineno); if (!op) return; if (!options['C']) { echo(' '); } c = GetChar(); continue; } UnGetChar(); c = '/'; } break; } echo(c); c = GetChar(); } if (c == '#') { domacro(); lineno++; newline(); c = GetChar(); } else startline = 0; } do_line_dir(lineno, fn); for (;;) { /* illegal character */ if (c & 0200) { if (c == EOI) { newline(); flush((int)(op-_obuf)); return; } fatal("non-ascii character read"); } /* comments */ if (c == '/' && !InputLevel) { c = GetChar(); if (c == '*') { op = SkipComment(op, &lineno); if (!op) return; if (!options['C']) { echo(' '); } c = GetChar(); continue; } echo('/'); continue; } /* switch on character */ switch(class(c)) { case STNL: echo(c); break; case STSTR: case STCHAR: { register int stopc = c; int escaped; do { escaped = 0; echo(c); c = GetChar(); if (c == '\n') { /* the compiler will complain */ break; } else if (c == EOI) { newline(); flush((int)(op-_obuf)); return; } if (c == '\\') { echo(c); c = GetChar(); if (c == '\n') { ++LineNumber; lineno++; } else escaped = 1; } } while (escaped || c != stopc); echo(c); if (c == '\n') break; /* Don't eat # */ c = GetChar(); continue; } case STNUM: /* The following code is quit ugly. This because * ..3 == . .3 , whereas ...3 == ... 3 */ echo(c); if (c == '.') { c = GetChar(); if (c == '.') { if ((c = GetChar()) == '.') { echo('.'); echo('.'); c = GetChar(); continue; } UnGetChar(); c = '.'; continue; } else if (!is_dig(c)) { continue; } else { echo(c); } } c = GetChar(); while (in_idf(c) || c == '.') { echo(c); if (c == 'e' || c == 'E') { c = GetChar(); if (c == '+' || c == '-') { echo(c); c = GetChar(); } } else c = GetChar(); } continue; case STELL: c = GetChar(); UnGetChar(); if (c == '"' || c == '\'') { echo('L'); continue; } c = 'L'; case STIDF: { extern int idfsize; /* ??? */ char buf[IDFSIZE + 1]; register char *tg = &buf[0]; register char *maxpos = &buf[idfsize]; register struct idf *idef; int NoExpandNext = 0; #define tstmac(bx) if (!(bits[c] & bx)) goto nomac #define cpy *tg++ = c #define load c = GetChar(); if (!in_idf(c)) goto endidf /* unstack macro's when allowed. */ if (Unstacked) EnableMacros(); if (c == NOEXPM) { NoExpandNext = 1; c = GetChar(); } #ifdef DOBITS cpy; tstmac(bit0); load; cpy; tstmac(bit1); load; cpy; tstmac(bit2); load; cpy; tstmac(bit3); load; cpy; tstmac(bit4); load; cpy; tstmac(bit5); load; cpy; tstmac(bit6); load; cpy; tstmac(bit7); load; #endif for(;;) { if (tg < maxpos) { cpy; } load; } endidf: if (c != EOF) UnGetChar(); *tg = '\0'; /* mark the end of the identifier */ if ((idef = findidf(buf)) && idef->id_macro && ReplaceMacros && !NoExpandNext) { if (replace(idef)) { echo(' '); c = GetChar(); continue; } tg = buf; while (*tg) { echo(*tg++); } c = GetChar(); if (in_idf(c)) { echo(' '); } continue; } nomac: *tg = '\0'; tg = buf; while (*tg) { echo(*tg++); } c = GetChar(); while (in_idf(c)) { echo(c); c = GetChar(); } continue; } case STMSPEC: if (InputLevel) { echo(' '); /* seperate tokens */ c = GetChar(); continue; } /* else fallthrough */ default: echo(c); c = GetChar(); continue; } break; } } /*NOTREACHED*/ } static char * SkipComment(op, lineno) char *op; int *lineno; { char *ob = &_obuf[OBUFSIZE]; register int c, oldc = '\0'; NoUnstack++; if (options['C']) { echo('/'); echo('*'); } c = GetChar(); for(;;) { if (c == EOI) { newline(); flush((int)(op - _obuf)); op = 0; break; } if (options['C']) { echo(c); } if (c == '\n') { ++LineNumber; ++*lineno; if (!options['C']) { echo(c); } } if (c == '*') { c = GetChar(); if (c == '/') { if (options['C']) { echo(c); } break; /* for(;;) */ } else if (oldc == '/') { warning("comment inside comment ?"); } oldc = '*'; } else { oldc = c; c = GetChar(); } } NoUnstack--; return op; }