123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856 |
- #define VARMAC 0x80
- long
- getnsn(void)
- {
- long n;
- int c;
- c = getnsc();
- if(c < '0' || c > '9')
- return -1;
- n = 0;
- while(c >= '0' && c <= '9') {
- n = n*10 + c-'0';
- c = getc();
- }
- unget(c);
- return n;
- }
- Sym*
- getsym(void)
- {
- int c;
- char *cp;
- c = getnsc();
- if(!isalpha(c) && c != '_') {
- unget(c);
- return S;
- }
- for(cp = symb;;) {
- if(cp <= symb+NSYMB-4)
- *cp++ = c;
- c = getc();
- if(isalnum(c) || c == '_')
- continue;
- unget(c);
- break;
- }
- *cp = 0;
- if(cp > symb+NSYMB-4)
- yyerror("symbol too large: %s", symb);
- return lookup();
- }
- Sym*
- getsymdots(int *dots)
- {
- int c;
- Sym *s;
- s = getsym();
- if(s != S)
- return s;
- c = getnsc();
- if(c != '.'){
- unget(c);
- return S;
- }
- if(getc() != '.' || getc() != '.')
- yyerror("bad dots in macro");
- *dots = 1;
- return slookup("__VA_ARGS__");
- }
- int
- getcom(void)
- {
- int c;
- for(;;) {
- c = getnsc();
- if(c != '/')
- break;
- c = getc();
- if(c == '/') {
- while(c != '\n')
- c = getc();
- break;
- }
- if(c != '*')
- break;
- c = getc();
- for(;;) {
- if(c == '*') {
- c = getc();
- if(c != '/')
- continue;
- c = getc();
- break;
- }
- if(c == '\n') {
- yyerror("comment across newline");
- break;
- }
- c = getc();
- }
- if(c == '\n')
- break;
- }
- return c;
- }
- void
- dodefine(char *cp)
- {
- Sym *s;
- char *p;
- long l;
- strcpy(symb, cp);
- p = strchr(symb, '=');
- if(p) {
- *p++ = 0;
- s = lookup();
- l = strlen(p) + 2; /* +1 null, +1 nargs */
- while(l & 3)
- l++;
- while(nhunk < l)
- gethunk();
- *hunk = 0;
- strcpy(hunk+1, p);
- s->macro = hunk;
- hunk += l;
- nhunk -= l;
- } else {
- s = lookup();
- s->macro = "\0001"; /* \000 is nargs */
- }
- if(debug['m'])
- print("#define (-D) %s %s\n", s->name, s->macro+1);
- }
- struct
- {
- char *macname;
- void (*macf)(void);
- } mactab[] =
- {
- "ifdef", 0, /* macif(0) */
- "ifndef", 0, /* macif(1) */
- "else", 0, /* macif(2) */
- "line", maclin,
- "define", macdef,
- "include", macinc,
- "undef", macund,
- "pragma", macprag,
- "endif", macend,
- 0
- };
- void
- domacro(void)
- {
- int i;
- Sym *s;
- s = getsym();
- if(s == S)
- s = slookup("endif");
- for(i=0; mactab[i].macname; i++)
- if(strcmp(s->name, mactab[i].macname) == 0) {
- if(mactab[i].macf)
- (*mactab[i].macf)();
- else
- macif(i);
- return;
- }
- yyerror("unknown #: %s", s->name);
- macend();
- }
- void
- macund(void)
- {
- Sym *s;
- s = getsym();
- macend();
- if(s == S) {
- yyerror("syntax in #undef");
- return;
- }
- s->macro = 0;
- }
- #define NARG 25
- void
- macdef(void)
- {
- Sym *s, *a;
- char *args[NARG], *np, *base;
- int n, i, c, len, dots;
- int ischr;
- s = getsym();
- if(s == S)
- goto bad;
- if(s->macro)
- yyerror("macro redefined: %s", s->name);
- c = getc();
- n = -1;
- dots = 0;
- if(c == '(') {
- n++;
- c = getnsc();
- if(c != ')') {
- unget(c);
- for(;;) {
- a = getsymdots(&dots);
- if(a == S)
- goto bad;
- if(n >= NARG) {
- yyerror("too many arguments in #define: %s", s->name);
- goto bad;
- }
- args[n++] = a->name;
- c = getnsc();
- if(c == ')')
- break;
- if(c != ',' || dots)
- goto bad;
- }
- }
- c = getc();
- }
- if(isspace(c))
- if(c != '\n')
- c = getnsc();
- base = hunk;
- len = 1;
- ischr = 0;
- for(;;) {
- if(isalpha(c) || c == '_') {
- np = symb;
- *np++ = c;
- c = getc();
- while(isalnum(c) || c == '_') {
- *np++ = c;
- c = getc();
- }
- *np = 0;
- for(i=0; i<n; i++)
- if(strcmp(symb, args[i]) == 0)
- break;
- if(i >= n) {
- i = strlen(symb);
- base = allocn(base, len, i);
- memcpy(base+len, symb, i);
- len += i;
- continue;
- }
- base = allocn(base, len, 2);
- base[len++] = '#';
- base[len++] = 'a' + i;
- continue;
- }
- if(ischr){
- if(c == '\\'){
- base = allocn(base, len, 1);
- base[len++] = c;
- c = getc();
- }else if(c == ischr)
- ischr = 0;
- }else{
- if(c == '"' || c == '\''){
- base = allocn(base, len, 1);
- base[len++] = c;
- ischr = c;
- c = getc();
- continue;
- }
- if(c == '/') {
- c = getc();
- if(c == '/'){
- c = getc();
- for(;;) {
- if(c == '\n')
- break;
- c = getc();
- }
- continue;
- }
- if(c == '*'){
- c = getc();
- for(;;) {
- if(c == '*') {
- c = getc();
- if(c != '/')
- continue;
- c = getc();
- break;
- }
- if(c == '\n') {
- yyerror("comment and newline in define: %s", s->name);
- break;
- }
- c = getc();
- }
- continue;
- }
- base = allocn(base, len, 1);
- base[len++] = '/';
- continue;
- }
- }
- if(c == '\\') {
- c = getc();
- if(c == '\n') {
- c = getc();
- continue;
- }
- else if(c == '\r') {
- c = getc();
- if(c == '\n') {
- c = getc();
- continue;
- }
- }
- base = allocn(base, len, 1);
- base[len++] = '\\';
- continue;
- }
- if(c == '\n')
- break;
- if(c == '#')
- if(n > 0) {
- base = allocn(base, len, 1);
- base[len++] = c;
- }
- base = allocn(base, len, 1);
- base[len++] = c;
- c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
- if(c == '\n')
- lineno++;
- if(c == -1) {
- yyerror("eof in a macro: %s", s->name);
- break;
- }
- }
- do {
- base = allocn(base, len, 1);
- base[len++] = 0;
- } while(len & 3);
- *base = n+1;
- if(dots)
- *base |= VARMAC;
- s->macro = base;
- if(debug['m'])
- print("#define %s %s\n", s->name, s->macro+1);
- return;
- bad:
- if(s == S)
- yyerror("syntax in #define");
- else
- yyerror("syntax in #define: %s", s->name);
- macend();
- }
- void
- macexpand(Sym *s, char *b)
- {
- char buf[2000];
- int n, l, c, nargs;
- char *arg[NARG], *cp, *ob, *ecp, dots;
- ob = b;
- if(*s->macro == 0) {
- strcpy(b, s->macro+1);
- if(debug['m'])
- print("#expand %s %s\n", s->name, ob);
- return;
- }
-
- nargs = (char)(*s->macro & ~VARMAC) - 1;
- dots = *s->macro & VARMAC;
- c = getnsc();
- if(c != '(')
- goto bad;
- n = 0;
- c = getc();
- if(c != ')') {
- unget(c);
- l = 0;
- cp = buf;
- ecp = cp + sizeof(buf)-4;
- arg[n++] = cp;
- for(;;) {
- if(cp >= ecp)
- goto toobig;
- c = getc();
- if(c == '"')
- for(;;) {
- if(cp >= ecp)
- goto toobig;
- *cp++ = c;
- c = getc();
- if(c == '\\') {
- *cp++ = c;
- c = getc();
- continue;
- }
- if(c == '\n')
- goto bad;
- if(c == '"')
- break;
- }
- if(c == '\'')
- for(;;) {
- if(cp >= ecp)
- goto toobig;
- *cp++ = c;
- c = getc();
- if(c == '\\') {
- *cp++ = c;
- c = getc();
- continue;
- }
- if(c == '\n')
- goto bad;
- if(c == '\'')
- break;
- }
- if(c == '/') {
- c = getc();
- switch(c) {
- case '*':
- for(;;) {
- c = getc();
- if(c == '*') {
- c = getc();
- if(c == '/')
- break;
- }
- }
- *cp++ = ' ';
- continue;
- case '/':
- while((c = getc()) != '\n')
- ;
- break;
- default:
- unget(c);
- c = '/';
- }
- }
- if(l == 0) {
- if(c == ',') {
- if(n == nargs && dots) {
- *cp++ = ',';
- continue;
- }
- *cp++ = 0;
- arg[n++] = cp;
- if(n > nargs)
- break;
- continue;
- }
- if(c == ')')
- break;
- }
- if(c == '\n')
- c = ' ';
- *cp++ = c;
- if(c == '(')
- l++;
- if(c == ')')
- l--;
- }
- *cp = 0;
- }
- if(n != nargs) {
- yyerror("argument mismatch expanding: %s", s->name);
- *b = 0;
- return;
- }
- cp = s->macro+1;
- for(;;) {
- c = *cp++;
- if(c == '\n')
- c = ' ';
- if(c != '#') {
- *b++ = c;
- if(c == 0)
- break;
- continue;
- }
- c = *cp++;
- if(c == 0)
- goto bad;
- if(c == '#') {
- *b++ = c;
- continue;
- }
- c -= 'a';
- if(c < 0 || c >= n)
- continue;
- strcpy(b, arg[c]);
- b += strlen(arg[c]);
- }
- *b = 0;
- if(debug['m'])
- print("#expand %s %s\n", s->name, ob);
- return;
- bad:
- yyerror("syntax in macro expansion: %s", s->name);
- *b = 0;
- return;
- toobig:
- yyerror("too much text in macro expansion: %s", s->name);
- *b = 0;
- }
- void
- macinc(void)
- {
- int c0, c, i, f;
- char str[STRINGSZ], *hp;
- c0 = getnsc();
- if(c0 != '"') {
- c = c0;
- if(c0 != '<')
- goto bad;
- c0 = '>';
- }
- for(hp = str;;) {
- c = getc();
- if(c == c0)
- break;
- if(c == '\n')
- goto bad;
- *hp++ = c;
- }
- *hp = 0;
- c = getcom();
- if(c != '\n')
- goto bad;
- f = -1;
- for(i=0; i<ninclude; i++) {
- if(i == 0 && c0 == '>')
- continue;
- strcpy(symb, include[i]);
- strcat(symb, "/");
- if(strcmp(symb, "./") == 0)
- symb[0] = 0;
- strcat(symb, str);
- f = open(symb, 0);
- if(f >= 0)
- break;
- }
- if(f < 0)
- strcpy(symb, str);
- c = strlen(symb) + 1;
- while(c & 3)
- c++;
- while(nhunk < c)
- gethunk();
- hp = hunk;
- memcpy(hunk, symb, c);
- nhunk -= c;
- hunk += c;
- newio();
- pushio();
- newfile(hp, f);
- return;
- bad:
- unget(c);
- yyerror("syntax in #include");
- macend();
- }
- void
- maclin(void)
- {
- char *cp;
- int c;
- long n;
- n = getnsn();
- c = getc();
- if(n < 0)
- goto bad;
- for(;;) {
- if(c == ' ' || c == '\t') {
- c = getc();
- continue;
- }
- if(c == '"')
- break;
- if(c == '\n') {
- strcpy(symb, "<noname>");
- goto nn;
- }
- goto bad;
- }
- cp = symb;
- for(;;) {
- c = getc();
- if(c == '"')
- break;
- *cp++ = c;
- }
- *cp = 0;
- c = getcom();
- if(c != '\n')
- goto bad;
- nn:
- c = strlen(symb) + 1;
- while(c & 3)
- c++;
- while(nhunk < c)
- gethunk();
- cp = hunk;
- memcpy(hunk, symb, c);
- nhunk -= c;
- hunk += c;
- linehist(cp, n);
- return;
- bad:
- unget(c);
- yyerror("syntax in #line");
- macend();
- }
- void
- macif(int f)
- {
- int c, l, bol;
- Sym *s;
- if(f == 2)
- goto skip;
- s = getsym();
- if(s == S)
- goto bad;
- if(getcom() != '\n')
- goto bad;
- if((s->macro != 0) ^ f)
- return;
- skip:
- bol = 1;
- l = 0;
- for(;;) {
- c = getc();
- if(c != '#') {
- if(!isspace(c))
- bol = 0;
- if(c == '\n')
- bol = 1;
- continue;
- }
- if(!bol)
- continue;
- s = getsym();
- if(s == S)
- continue;
- if(strcmp(s->name, "endif") == 0) {
- if(l) {
- l--;
- continue;
- }
- macend();
- return;
- }
- if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
- l++;
- continue;
- }
- if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
- macend();
- return;
- }
- }
- bad:
- yyerror("syntax in #if(n)def");
- macend();
- }
- void
- macprag(void)
- {
- Sym *s;
- int c0, c;
- char *hp;
- Hist *h;
- s = getsym();
- if(s && strcmp(s->name, "lib") == 0)
- goto praglib;
- if(s && strcmp(s->name, "pack") == 0) {
- pragpack();
- return;
- }
- if(s && strcmp(s->name, "fpround") == 0) {
- pragfpround();
- return;
- }
- if(s && strcmp(s->name, "profile") == 0) {
- pragprofile();
- return;
- }
- if(s && strcmp(s->name, "varargck") == 0) {
- pragvararg();
- return;
- }
- if(s && strcmp(s->name, "incomplete") == 0) {
- pragincomplete();
- return;
- }
- while(getnsc() != '\n')
- ;
- return;
- praglib:
- c0 = getnsc();
- if(c0 != '"') {
- c = c0;
- if(c0 != '<')
- goto bad;
- c0 = '>';
- }
- for(hp = symb;;) {
- c = getc();
- if(c == c0)
- break;
- if(c == '\n')
- goto bad;
- *hp++ = c;
- }
- *hp = 0;
- c = getcom();
- if(c != '\n')
- goto bad;
- /*
- * put pragma-line in as a funny history
- */
- c = strlen(symb) + 1;
- while(c & 3)
- c++;
- while(nhunk < c)
- gethunk();
- hp = hunk;
- memcpy(hunk, symb, c);
- nhunk -= c;
- hunk += c;
- h = alloc(sizeof(Hist));
- h->name = hp;
- h->line = lineno;
- h->offset = -1;
- h->link = H;
- if(ehist == H) {
- hist = h;
- ehist = h;
- return;
- }
- ehist->link = h;
- ehist = h;
- return;
- bad:
- unget(c);
- yyerror("syntax in #pragma lib");
- macend();
- }
- void
- macend(void)
- {
- int c;
- for(;;) {
- c = getnsc();
- if(c < 0 || c == '\n')
- return;
- }
- }
- void
- linehist(char *f, int offset)
- {
- Hist *h;
- /*
- * overwrite the last #line directive if
- * no alloc has happened since the last one
- */
- if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
- if(f && ehist->name && strcmp(f, ehist->name) == 0) {
- ehist->line = lineno;
- ehist->offset = offset;
- return;
- }
- if(debug['f'])
- if(f) {
- if(offset)
- print("%4ld: %s (#line %d)\n", lineno, f, offset);
- else
- print("%4ld: %s\n", lineno, f);
- } else
- print("%4ld: <pop>\n", lineno);
- newflag = 0;
- h = alloc(sizeof(Hist));
- h->name = f;
- h->line = lineno;
- h->offset = offset;
- h->link = H;
- if(ehist == H) {
- hist = h;
- ehist = h;
- return;
- }
- ehist->link = h;
- ehist = h;
- }
- void
- gethunk(void)
- {
- char *h;
- long nh;
- nh = NHUNK;
- if(thunk >= 10L*NHUNK)
- nh = 10L*NHUNK;
- h = (char*)mysbrk(nh);
- if(h == (char*)-1) {
- yyerror("out of memory");
- errorexit();
- }
- hunk = h;
- nhunk = nh;
- thunk += nh;
- }
|