#define VARMAC 0x80 longgetnsn(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 != '_' && c < Runeself) { unget(c); return S; } for(cp = symb;;) { if(cp <= symb+NSYMB-4) *cp++ = c; c = getc(); if(isalnum(c) || c == '_' || c >= Runeself) 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__");} intgetcom(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;} voiddodefine(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}; voiddomacro(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();} voidmacund(void){ Sym *s; s = getsym(); macend(); if(s == S) { yyerror("syntax in #undef"); return; } s->macro = 0;} #define NARG 25voidmacdef(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();} voidmacexpand(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;Lines 1–500 of 856. Load more
#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 != '_' && c < Runeself) { unget(c); return S; } for(cp = symb;;) { if(cp <= symb+NSYMB-4) *cp++ = c; c = getc(); if(isalnum(c) || c == '_' || c >= Runeself) 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;