/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* $Id$ */ /* PREPROCESSOR DRIVER */ #include #include #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; extern char *sprint(); void Xflush() { sys_write(STDOUT, _obuf, OBUFSIZE); } 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; static char *SkipComment(char *op, int *lineno); void preprocess(char *fn); void do_pragma() { int size = ITEXTSIZE; char *cur_line = Malloc((unsigned)size); char *c_ptr = cur_line; int c = GetChar(); int delim = 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; size += ITEXTSIZE; } if (delim) { if (c == delim) { delim = 0; } else if (c == '\\') { *c_ptr++ = c; c = GetChar(); if (c == '\n') break; } } else if (c == '\'' || c == '"') { delim = c; } else if (c == '/') { if ((c = GetChar()) != '*' || InputLevel) { *c_ptr++ = '/'; } else { skipcomment(); continue; } } *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))); } if (delim) { error("unclosed opening %c", delim); } 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++; } char Xbuf[256]; void preprocess(char *fn) { int c; char *op = _obuf; char *ob = &_obuf[OBUFSIZE]; 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() op--; while (op >= _obuf && (*op == ' ' || *op == '\t')) op--; op++; echo('\n') if (!options['P']) { /* Generate a line directive communicating the source filename */ 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']) { \ char *p = Xbuf; \ sprint(Xbuf, "%s %d \"%s\"\n", \ LINE_PREFIX, \ (int)LineNumber, \ FileName); \ op--; \ while (op >= _obuf \ && (class(*(unsigned char *)op) == STSKIP \ || *op == '\n')) op--; \ op++; \ newline(); \ while (*p) { \ echo(*p++); \ } \ } \ } for (;;) { LineNumber++; lineno++; startline = 1; c = GetChar(); while (startline) { /* first flush the saved pragma's */ if (pragma_nr) { int i = 0; int LiNo = LineNumber; char *FiNam = FileName; while (i < pragma_nr) { 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(); do_line_dir(lineno, fn); 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: newline(); break; case STSTR: case STCHAR: { 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]; char *tg = &buf[0]; char *maxpos = &buf[idfsize]; 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(char *op, int *lineno) { char *ob = &_obuf[OBUFSIZE]; 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; }