static int llex (LexState *ls, SemInfo *seminfo) { luaZ_resetbuffer(ls->buff); for (;;) { switch (ls->current) { case '\n': case '\r': { /* line breaks */ inclinenumber(ls); break; } case ' ': case '\f': case '\t': case '\v': { /* spaces */ next(ls); break; } case '-': { /* '-' or '--' (comment) */ next(ls); if (ls->current != '-') return '-'; /* else is a comment */ next(ls); if (ls->current == '[') { /* long comment? */ int sep = skip_sep(ls); luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ if (sep >= 0) { read_long_string(ls, NULL, sep); /* skip long comment */ luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ break; } } /* else short comment */ while (!currIsNewline(ls) && ls->current != EOZ) next(ls); /* skip until end of line (or end of file) */ break; } case '[': { /* long string or simply '[' */ int sep = skip_sep(ls); if (sep >= 0) { read_long_string(ls, seminfo, sep); return TK_STRING; } else if (sep != -1) /* '[=...' missing second bracket */ lexerror(ls, "invalid long string delimiter", TK_STRING); return '['; } case '=': { next(ls); if (check_next1(ls, '=')) return TK_EQ; else return '='; } case '<': { next(ls); if (check_next1(ls, '=')) return TK_LE; else if (check_next1(ls, '<')) return TK_SHL; else return '<'; } case '>': { next(ls); if (check_next1(ls, '=')) return TK_GE; else if (check_next1(ls, '>')) return TK_SHR; else return '>'; } case '/': { next(ls); if (check_next1(ls, '/')) return TK_IDIV; else return '/'; } case '~': { next(ls); if (check_next1(ls, '=')) return TK_NE; else return '~'; } case ':': { next(ls); if (check_next1(ls, ':')) return TK_DBCOLON; else return ':'; } case '"': case '\'': { /* short literal strings */ read_string(ls, ls->current, seminfo); return TK_STRING; } case '.': { /* '.', '..', '...', or number */ save_and_next(ls); if (check_next1(ls, '.')) { if (check_next1(ls, '.')) return TK_DOTS; /* '...' */ else return TK_CONCAT; /* '..' */ } else if (!lisdigit(ls->current)) return '.'; else return read_numeral(ls, seminfo); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { return read_numeral(ls, seminfo); } case EOZ: { return TK_EOS; } default: { if (lislalpha(ls->current)) { /* identifier or reserved word? */ TString *ts; do { save_and_next(ls); } while (lislalnum(ls->current)); ts = luaX_newstring(ls, luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff)); seminfo->ts = ts; if (isreserved(ts)) /* reserved word? */ return ts->extra - 1 + FIRST_RESERVED; else { return TK_NAME; } } else { /* single-char tokens (+ - / ...) */ int c = ls->current; next(ls); return c; } } } } }
l_noret luaX_syntaxerror (LexState *ls, const char *msg) { lexerror(ls, msg, ls->t.token); }
int yylex(void) { int ch; for(;;) { ch = getchar(); switch( ch ) { case EOF: return 0; case '\n': ++yylineno; continue; case '\t': case ' ': continue; case '{': do { ch = getchar(); } while( ch != '}' && ch != EOF ); continue; case ':': /* ASSIGN or COLON */ ch = getchar(); switch( ch ) { case '=': return lex_log_token(T_ASSIGN); default: ungetc(ch, stdin); return lex_log_token(T_COLON); } case ',': return lex_log_token(T_COMMA); case '.': /* RCON or DOT */ ch = getchar(); ungetc(ch, stdin); if( isdigit(ch) ) return lex_log_token(lex_number('.')); else return lex_log_token(T_DOT); case '[': return lex_log_token(T_LBRACK); case ']': return lex_log_token(T_RBRACK); case '(': return lex_log_token(T_LPAREN); case ')': return lex_log_token(T_RPAREN); case '<': /* NE, LE, or LT */ ch = getchar(); switch( ch ) { case '>': return lex_log_token(T_NE); case '=': return lex_log_token(T_LE); default: ungetc(ch, stdin); return lex_log_token(T_LT); } case '=': return lex_log_token(T_EQ); case '>': /* GE or GT */ ch = getchar(); switch( ch ) { case '=': return lex_log_token(T_GE); default: ungetc(ch, stdin); return lex_log_token(T_GT); } case '-': return lex_log_token(T_MINUS); case '*': return lex_log_token(T_MUL); case '+': return lex_log_token(T_PLUS); case '/': return lex_log_token(T_RDIV); case ';': return lex_log_token(T_SEMI); case '&': return lex_log_token(T_AMPER); case '^': return lex_log_token(T_CARET); default: if( isalpha(ch) || ch == '_' ) return lex_log_token(lex_alpha_ident(ch)); else if( isdigit(ch) ) return lex_log_token(lex_number(ch)); else lexerror("Illegal character %03o", ch); } } }
static void read_string (LexState *ls, int del, SemInfo *seminfo) { save_and_next(ls); /* keep delimiter (for error messages) */ while (ls->current != del) { switch (ls->current) { case EOZ: lexerror(ls, "unfinished string", TK_EOS); break; /* to avoid warnings */ case '\n': case '\r': lexerror(ls, "unfinished string", TK_STRING); break; /* to avoid warnings */ case '\\': { /* escape sequences */ int c; /* final character to be saved */ save_and_next(ls); /* keep '\\' for error messages */ switch (ls->current) { case 'a': c = '\a'; goto read_save; case 'b': c = '\b'; goto read_save; case 'f': c = '\f'; goto read_save; case 'n': c = '\n'; goto read_save; case 'r': c = '\r'; goto read_save; case 't': c = '\t'; goto read_save; case 'v': c = '\v'; goto read_save; case 'x': c = readhexaesc(ls); goto read_save; case 'u': utf8esc(ls); goto no_save; case '\n': case '\r': inclinenumber(ls); c = '\n'; goto only_save; case '\\': case '\"': case '\'': c = ls->current; goto read_save; case EOZ: goto no_save; /* will raise an error next loop */ case 'z': { /* zap following span of spaces */ luaZ_buffremove(ls->buff, 1); /* remove '\\' */ next(ls); /* skip the 'z' */ while (lisspace(ls->current)) { if (currIsNewline(ls)) inclinenumber(ls); else next(ls); } goto no_save; } default: { esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); c = readdecesc(ls); /* digital escape '\ddd' */ goto only_save; } } read_save: next(ls); /* go through */ only_save: luaZ_buffremove(ls->buff, 1); /* remove '\\' */ save(ls, c); /* go through */ no_save: break; } default: save_and_next(ls); } } save_and_next(ls); /* skip delimiter */ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, luaZ_bufflen(ls->buff) - 2); }
int handle_include(char *name, int ignore_errors) { char *p; char buf[1024]; FILE *f; struct incstate *is; int delim; if (*name != '"' && *name != '<') { struct defn *d; if ((d = lookup_define(name)) && d->nargs == -1) { char *q; q = d->exps; while (isspace(*q)) q++; return handle_include(q, ignore_errors); } else { if (!ignore_errors) lexerror("Missing leading \" or < in #include"); return 0; } } delim = *name++ == '"' ? '"' : '>'; for (p = name; *p && *p != delim; p++) ; if (!*p) { if (!ignore_errors) lexerror("Missing trailing \" or > in #include"); return 0; } if (strlen(name) > sizeof(buf) - 100) { if (!ignore_errors) lexerror("Include name too long."); return 0; } *p = 0; if ((f = inc_open(buf, sizeof(buf), name)) == NULL) { if (!ignore_errors) { lexerror("Cannot #include %s\n", name); } return 0; } is = (struct incstate *)xalloc(sizeof(struct incstate)); is->yyin = yyin; is->line = current_line; is->file = current_file; is->incfnum = current_incfile; is->slast = slast; is->lastchar = lastchar; is->next = inctop; is->pragma_strict_types = pragma_strict_types; if (nbuf) { memcpy(is->outp = (char *)xalloc(nbuf + 1), outp, nbuf); is->nbuf = nbuf; nbuf = 0; outp = defbuf + DEFMAX; } else { is->nbuf = 0; is->outp = NULL; } pragma_strict_types = 0; inctop = is; current_line = 1; current_file = xalloc(strlen(buf)+1); current_incfile = ++num_incfiles; (void)strcpy(current_file, buf); slast = lastchar = '\n'; yyin = f; incdepth++; return 1; }
static int yylex1(void) { register char *yyp; register int c; register int c1, c2; for (;;) { if (lex_fatal) { return -1; } switch(c = mygetc()) { case EOF: if (inctop) { struct incstate *p; p = inctop; (void)fclose(yyin); /*(void)fprintf(stderr, "popping to %s\n", p->file);*/ free(current_file); nexpands = 0; current_file = p->file; current_line = p->line + 1; current_incfile = p->incfnum; pragma_strict_types = p->pragma_strict_types; yyin = p->yyin; slast = p->slast; lastchar = p->lastchar; inctop = p->next; if (p->nbuf) { nbuf = p->nbuf; outp = defbuf + DEFMAX - nbuf; memcpy(outp, p->outp, nbuf); free((char *)p->outp); } else { nbuf = 0; outp = defbuf + DEFMAX; } store_line_number_info(current_incfile, current_line); incdepth--; free((char *)p); break; } if (iftop) { struct ifstate *p = iftop; lexerror(p->state == EXPECT_ENDIF ? "Missing #endif" : "Missing #else"); while (iftop) { p = iftop; iftop = p->next; free((char *)p); } } return -1; case '\n': { nexpands=0; store_line_number_info(current_incfile, current_line); current_line++; total_lines++; } /* FALLTHROUGH */ case ' ': case '\t': case '\f': case '\v': break; case '+': TRY('+', F_INC); TRY('=', F_ADD_EQ); return c; case '-': TRY('>', F_ARROW); TRY('-', F_DEC); TRY('=', F_SUB_EQ); return c; case '&': TRY('&', F_LAND); TRY('=', F_AND_EQ); return c; case '|': TRY('|', F_LOR); TRY('=', F_OR_EQ); return c; case '^': TRY('=', F_XOR_EQ); return c; case '<': if (gobble('<')) { TRY('=', F_LSH_EQ); return F_LSH; } TRY('=', F_LE); return c; case '>': if (gobble('>')) { TRY('=', F_RSH_EQ); return F_RSH; } TRY('=', F_GE); return c; case '*': TRY('=', F_MULT_EQ); return c; case '%': TRY('=', F_MOD_EQ); return F_MOD; case '/': if (gobble('*')) { skip_comment(); break; } else if (gobble('/')) { skip_comment2(); break; } TRY('=', F_DIV_EQ); return c; case '=': TRY('=', F_EQ); return c; case ';': case '(': case ')': case ',': case '{': case '}': case '~': case '[': case ']': case '?': case '@': return c; case '!': TRY('=', F_NE); return F_NOT; case ':': TRY(':', F_COLON_COLON); return ':'; case '.': if (gobble('.')) { if (gobble('.')) return F_VARARG; else return F_RANGE; } return c; case '#': if (lastchar == '\n') { char *ssp = 0; int quote; yyp = yytext; do { c = mygetc(); } while (isspace(c)); for (quote = 0;;) { if (c == '"') quote ^= 1; /*gc - handle comments cpp-like! 1.6.91 @@@*/ while (!quote && c == '/') { if (gobble('*')) { skip_comment(); c = mygetc(); } else break; } if (!ssp && isspace(c)) ssp = yyp; if (c == '\n' || c == EOF) break; SAVEC; c = mygetc(); } if (ssp) { *ssp++ = 0; while (isspace(*ssp)) ssp++; } else { ssp = yyp; } *yyp = 0; if (strcmp("define", yytext) == 0) { handle_define(ssp); } else if (strcmp("if", yytext) == 0) { #if 0 short int nega=0; /*@@@ allow #if !VAR gc 1.6.91*/ if (*ssp=='!'){ ssp++; nega=1;} if (isdigit(*ssp)) { char *p; long l; l = strtol(ssp, &p, 10); while (isspace(*p)) p++; if (*p) lexerror("Condition too complex in #if"); else handle_cond(nega ? !(int)l : (int)l); } else if (isalunum(*ssp)) { char *p = ssp; while (isalunum(*p)) p++; if (*p) { *p++ = 0; while (isspace(*p)) p++; } if (*p) lexerror("Condition too complex in #if"); else { struct defn *d; d = lookup_define(ssp); if (d) { handle_cond(nega ? !atoi(d->exps) : atoi(d->exps));/* a hack! */ } else { handle_cond(nega?1:0); /* cpp-like gc*/ } } } else lexerror("Condition too complex in #if"); #else int cond; myungetc(0); add_input(ssp); cond = cond_get_exp(0); if (mygetc()) { lexerror("Condition too complex in #if"); while (mygetc()) ; } else handle_cond(cond); #endif } else if (strcmp("ifdef", yytext) == 0) { deltrail(ssp); handle_cond(lookup_define(ssp) != 0); } else if (strcmp("ifndef", yytext) == 0) { deltrail(ssp); handle_cond(lookup_define(ssp) == 0); } else if (strcmp("else", yytext) == 0) { if (iftop && iftop->state == EXPECT_ELSE) { struct ifstate *p = iftop; /*(void)fprintf(stderr, "found else\n");*/ iftop = p->next; free((char *)p); (void)skip_to("endif", (char *)0); store_line_number_info(current_incfile, current_line); current_line++; total_lines++; } else { lexerror("Unexpected #else"); } } else if (strcmp("endif", yytext) == 0) { if (iftop && (iftop->state == EXPECT_ENDIF || iftop->state == EXPECT_ELSE)) { struct ifstate *p = iftop; /*(void)fprintf(stderr, "found endif\n");*/ iftop = p->next; free((char *)p); } else { lexerror("Unexpected #endif"); } } else if (strcmp("undef", yytext) == 0) { struct defn *d; deltrail(ssp); if ((d = lookup_define(ssp)) != NULL ) d->undef++; } else if (strcmp("echo", yytext) == 0) { (void)fprintf(stderr, "%s\n", ssp); } else if (strcmp("include", yytext) == 0) { /*(void)fprintf(stderr, "including %s\n", ssp); */ handle_include(ssp, 0); } else if (strcmp("pragma", yytext) == 0) { deltrail(ssp); handle_pragma(ssp); } else if (strcmp("error", yytext) == 0) { handle_exception(ERROR, ssp); } else if (strcmp("warning", yytext) == 0) { handle_exception(WARNING, ssp); } else { lexerror("Unrecognised # directive"); } myungetc('\n'); break; } else goto badlex; case '\'': yylval.number = mygetc(); if (yylval.number == '\\') { int tmp = mygetc(); switch (tmp) { case 'n': yylval.number = '\n'; break; case 't': yylval.number = '\t'; break; case 'b': yylval.number = '\b'; break; case 'a': yylval.number = '\a'; break; case 'v': yylval.number = '\v'; break; case '\'': case '\\': case '"': yylval.number = tmp; break; default: lexwarning("Bad character escape sequence"); yylval.number = tmp; break; } } if (!gobble('\'')) lexerror("Illegal character constant"); return F_NUMBER; case '"': yyp = yytext; *yyp++ = c; for (;;) { c = mygetc(); if (c == EOF) { lexerror("End of file in string"); return string("\"\""); } else if (c == '\n') { lexerror("Newline in string"); return string("\"\""); } SAVEC; if (c == '"') break; if (c == '\\') { c = mygetc(); if ( c == '\n' ) { yyp--; store_line_number_info(current_incfile, current_line); current_line++; total_lines++; } else if ( c == EOF ) { /* some operating systems give EOF only once */ myungetc(c); } else *yyp++ = c; } } *yyp = 0; return string(yytext); case '0': c = mygetc(); if ( c == 'X' || c == 'x' || c == 'o') { char *endptr; long long value; int base = 16; if (c == 'o') base = 8; yyp = yytext; for (;;) { c = mygetc(); if (!isxdigit(c)) break; SAVEC; } myungetc(c); *yyp = '\0'; value = strtoll(yytext, &endptr, base); if (*endptr != '\0') { fprintf(stderr, "%s\n", yytext); lexwarning("Invalid digits in octal number number"); } return number(value); } myungetc(c); c = '0'; /* FALLTHROUGH */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': yyp = yytext; *yyp++ = c; for (;;) { c = mygetc(); if (!isdigit(c)) break; SAVEC; } if (c == '.') { if (isdigit(c1 = mygetc())) { SAVEC; c = c1; SAVEC; for (c = mygetc(); isdigit(c); c = mygetc()) SAVEC; if (c == 'e' || c == 'E') { c1 = mygetc(); if (c1 == '-' || c1 == '+') { c2 = mygetc(); if (isdigit(c2)) { SAVEC; c = c1; SAVEC; c = c2; SAVEC; for (c = mygetc(); isdigit(c); c = mygetc()) SAVEC; } else { myungetc(c2); myungetc(c1); } } else if (isdigit(c1)) { SAVEC; c = c1; SAVEC; for (c = mygetc(); isdigit(c); c = mygetc()) SAVEC; } else myungetc(c1); } myungetc(c); *yyp = 0; return real(strtod(yytext, NULL)); } myungetc(c1); } myungetc(c); *yyp = 0; if (*yytext == '0') { /* OCTALS */ char *endptr; long long value; value = strtoll(yytext, &endptr, 010); if (*endptr != '\0') lexwarning("Invalid digits in octal number"); if (value != 0) lexwarning("Obsolete octal format used. Use 0o111 syntax"); return number(value); } return number(atoll(yytext)); default: if (isalpha(c) || c == '_') { int r; yyp = yytext; *yyp++ = c; for (;;) { c = mygetc(); if (!isalunum(c)) break; SAVEC; } *yyp = 0; myungetc(c); if (!expand_define()) { r = lookup_resword(yytext); if (r >= 0) { return r; } else return ident(yytext); } break; } goto badlex; } } badlex: { lexerror("Illegal character (hex %02x) '%c'", c, c); return ' '; } }
static int cond_get_exp(int priority) { int c; int value, value2, x; do c = exgetc(); while (isspace(c)); if (c == '(') { value = cond_get_exp(0); do c = exgetc(); while (isspace(c)); if (c != ')') { lexerror("bracket not paired in #if"); if (!c) myungetc('\0'); } } else if (ispunct(c)) { x = (_optab-' ')[c]; if (!x) { lexerror("illegal character in #if"); return 0; } value = cond_get_exp(12); switch ( optab2[x-1] ) { case BNOT : value = ~value; break; case LNOT : value = !value; break; case UMINUS: value = -value; break; case UPLUS : value = value; break; default : lexerror("illegal unary operator in #if"); return 0; } } else { int base; if (!isdigit(c)) { if (!c) { lexerror("missing expression in #if"); myungetc('\0'); } else lexerror("illegal character in #if"); return 0; } value = 0; if (c!='0') base = 10; else { c = mygetc(); if ( c == 'x' || c == 'X' ) { base = 16; c = mygetc(); } else base=8; } for (;;) { if ( isdigit(c) ) x = -'0'; else if (isupper(c)) x = -'A' + 10; else if (islower(c)) x = -'a' + 10; else break; x += c; if (x > base) break; value = value*base + x; c = mygetc(); } myungetc(c); } for (;;) { do c = exgetc(); while (isspace(c)); if (!ispunct(c)) break; x = (_optab-' ')[c]; if (!x) break; value2 = mygetc(); for (;;x += 3) { if (!optab2[x]) { myungetc(value2); if (!optab2[x + 1]) { lexerror("illegal operator use in #if"); return 0; } break; } if (value2 == optab2[x]) break; } if (priority >= optab2[x + 2]) { if (optab2[x]) myungetc(value2); break; } value2 = cond_get_exp(optab2[x + 2]); switch ( optab2[x + 1] ) { case MULT : value *= value2; break; case DIV : value /= value2; break; case MOD : value %= value2; break; case BPLUS : value += value2; break; case BMINUS : value -= value2; break; case LSHIFT : value <<= value2; break; case RSHIFT : value = (unsigned)value >> value2; break; case LESS : value = value < value2; break; case LEQ : value = value <= value2; break; case GREAT : value = value > value2; break; case GEQ : value = value >= value2; break; case EQ : value = value == value2; break; case NEQ : value = value != value2; break; case BAND : value &= value2; break; case XOR : value ^= value2; break; case BOR : value |= value2; break; case LAND : value = value && value2; break; case LOR : value = value || value2; break; case QMARK : do c = exgetc(); while (isspace(c)); if (c != ':') { lexerror("'?' without ':' in #if"); myungetc(c); return 0; } if (value) { (void)cond_get_exp(1); value = value2; } else value = cond_get_exp(1); break; } } myungetc(c); return value; }
static int skip_to(char *token, char *atoken) { char b[20], *p; int c; int nest; for (nest = 0;;) { c = mygetc(); if (c == '#') { do { c = mygetc(); } while (isspace(c)); for (p = b; c != '\n' && c != EOF; ) { if (p < b+sizeof b-1) *p++ = c; c = mygetc(); } *p++ = 0; for (p = b; *p && !isspace(*p); p++) ; *p = 0; /*(void)fprintf(stderr, "skip checks %s\n", b);*/ if (strcmp(b, "if") == 0 || strcmp(b, "ifdef") == 0 || strcmp(b, "ifndef") == 0) { nest++; } else if (nest > 0) { if (strcmp(b, "endif") == 0) nest--; } else { if (strcmp(b, token) == 0) return 1; else if (atoken && strcmp(b, atoken) == 0) return 0; } } else { /*(void)fprintf(stderr, "skipping (%d) %c", c, c);*/ while (c != '\n' && c != EOF) { c = mygetc(); /*(void)fprintf(stderr, "%c", c);*/ } if (c == EOF) { lexerror("Unexpected end of file while skipping"); return 1; } } store_line_number_info(current_incfile, current_line); current_line++; total_lines++; } }
/* Stuff to evaluate expression. I havn't really checked it. /LA ** Written by "J\"orn Rennecke" <*****@*****.**> */ static int exgetc(void) { register char c, *yyp; c = mygetc(); while (isalpha(c) || c == '_') { yyp = yytext; do { SAVEC; c = mygetc(); } while (isalunum(c)); myungetc(c); *yyp = '\0'; if (strcmp(yytext, "defined") == 0) { /* handle the defined "function" in #if */ do c = mygetc(); while (isspace(c)); if (c != '(') { lexerror("Missing ( in defined"); continue; } do c = mygetc(); while (isspace(c)); yyp = yytext; while (isalunum(c)) { SAVEC; c = mygetc(); } *yyp = '\0'; while (isspace(c)) c = mygetc(); if (c != ')') { lexerror("Missing ) in defined"); continue; } /* Skip whitespace */ do c = mygetc(); while (isspace(c)); myungetc(c); if (lookup_define(yytext)) add_input(" 1 "); else add_input(" 0 "); } else { if (!expand_define()) add_input(" 0 "); } c = mygetc(); } return c; }
/* Check if yytext is a macro and expand if it is. */ static int expand_define(void) { struct defn *p; char expbuf[DEFMAX]; char *args[NARGS]; char buf[DEFMAX]; char *q, *e, *b; if (nexpands++ > EXPANDMAX) { lexerror("Too many macro expansions"); return 0; } p = lookup_define(yytext); if (!p) { return 0; } if (p->nargs == -1) { add_input(p->exps); } else { int c, parcnt = 0, dquote = 0, squote = 0; int n; SKIPW; if (c != '(') { lexerror("Missing '(' in macro call"); return 0; } SKIPW; if (c == ')') n = 0; else { q = expbuf; args[0] = q; for (n = 0; n < NARGS; ) { switch(c) { case '"': if (!squote) dquote ^= 1; break; case '\'': if (!dquote) squote ^= 1; break; case '(': if (!squote && !dquote) parcnt++; break; case ')': if (!squote && !dquote) parcnt--; break; case '\\': if (squote || dquote) { *q++ = c; c = mygetc();} break; case '\n': if (squote || dquote) { lexerror("Newline in string"); return 0; } break; } if (c == ',' && !parcnt && !dquote && !squote) { *q++ = 0; args[++n] = q; } else if (parcnt < 0) { *q++ = 0; n++; break; } else { if (c == EOF) { lexerror("Unexpected end of file"); return 0; } if (q >= expbuf + DEFMAX - 5) { lexerror("Macro argument overflow"); return 0; } else { *q++ = c; } } if (!squote && ! dquote) c = cmygetc(); else c = mygetc(); } if (n == NARGS) { lexerror("Maximum macro argument count exceeded"); return 0; } } if (n != p->nargs) { lexerror("Wrong number of macro arguments"); return 0; } /* Do expansion */ b = buf; e = p->exps; while (*e) { if (*e == MARKS) { if (*++e == MARKS) *b++ = *e++; else { for (q = args[*e++ - MARKS - 1]; *q; ) { *b++ = *q++; if (b >= buf+DEFMAX) { lexerror("Macro expansion overflow"); return 0; } } } } else { *b++ = *e++; if (b >= buf+DEFMAX) { lexerror("Macro expansion overflow"); return 0; } } } *b++ = 0; add_input(buf); } return 1; }
static void handle_define(char *yyt) { char namebuf[NSIZE]; char args[NARGS][NSIZE]; char mtext[MLEN]; char *p, *q; p = yyt; (void)strcat(p, " "); q = namebuf; GETALPHA(p, q, namebuf+NSIZE-1); if (*p == '(') { /* if "function macro" */ int arg; int inid; char *ids = 0; p++; /* skip '(' */ SKIPWHITE; if (*p == ')') { arg = 0; } else { for (arg = 0; arg < NARGS; ) { q = args[arg]; GETALPHA(p, q, args[arg] + NSIZE - 1); arg++; SKIPWHITE; if (*p == ')') break; if (*p++ != ',') { lexerror("Missing ',' in #define parameter list"); return; } SKIPWHITE; } if (arg == NARGS) { lexerror("Too many macro arguments"); return; } } p++; /* skip ')' */ for (inid = 0, q = mtext; *p; ) { if (isalunum(*p)) { if (!inid) { inid++; ids = p; } } else { if (inid) { size_t l, idlen = p - ids; int n; for (n = 0; n < arg; n++) { l = strlen(args[n]); if (l == idlen && strncmp(args[n], ids, l) == 0) { q -= idlen; *q++ = MARKS; *q++ = n+MARKS+1; break; } } inid = 0; } } *q = *p; if (*p++ == MARKS) *++q = MARKS; if (q < mtext + MLEN - 2) q++; else { lexerror("Macro text too long"); return; } if (!*p && p[-2] == '\\') { q -= 2; refill(); p = yytext; } } *--q = 0; add_define(namebuf, arg, mtext); } else { for (q = mtext; *p; ) { *q = *p++; if (q < mtext + MLEN - 2) q++; else { lexerror("Macro text too long"); return; } if (!*p && p[-2] == '\\') { q -= 2; refill(); p = yytext; } } *--q = 0; add_define(namebuf, -1, mtext); } return; }
void parseerror(int messagenr) { lexerror(); if(messagenr < 1 || messagenr > maxparseerrormessage) messagenr = 0; error(parseerrormessage[messagenr]); }
static void process_ucpp_token(struct ucpp_token *tok) { int *dummyptr = n_xmalloc(sizeof *dummyptr); static struct input_file infile; #if 0 NONE, /* whitespace */ NEWLINE, /* newline */ COMMENT, /* comment */ BUNCH, /* non-C characters */ PRAGMA, /* a #pragma directive */ CONTEXT, /* new file or #line */ SHARP, /* # */ DSHARP, /* ## */ OPT_NONE, /* optional space to separate tokens in text output */ DIGRAPH_TOKENS, /* there begin digraph tokens */ /* for DIG_*, do not change order, unless checking undig() in cpp.c */ DIG_LBRK, /* <: */ DIG_RBRK, /* :> */ DIG_LBRA, /* <% */ DIG_RBRA, /* %> */ DIG_SHARP, /* %: */ DIG_DSHARP, /* %:%: */ DIGRAPH_TOKENS_END, /* digraph tokens end here */ LAST_MEANINGFUL_TOKEN, /* reserved words will go there */ MACROARG, /* special token for representing macro arguments */ #endif switch (tok->type) { case LPAR: /* ( */ case RPAR: /* ) */ store_token(&toklist, dummyptr, tok->type == LPAR? TOK_PAREN_OPEN : TOK_PAREN_CLOSE, lineno, NULL); break; case LBRA: /* { */ case RBRA: /* } */ store_token(&toklist, dummyptr, tok->type == LBRA? TOK_COMP_OPEN: TOK_COMP_CLOSE, lineno, NULL); break; case LBRK: /* [ */ case RBRK: /* ] */ store_token(&toklist, dummyptr, tok->type == LBRK? TOK_ARRAY_OPEN : TOK_ARRAY_CLOSE, lineno, NULL); break; case SEMIC: /* ; */ store_token(&toklist, dummyptr, TOK_SEMICOLON, lineno, NULL); break; case STRING: { struct ty_string *tmpstr; char *str_value = tok->name; int is_wide_char = 0; if (*str_value == 'L') { /* Wide character string */ ++str_value; is_wide_char = 1; } set_input_file_buffer(&infile, str_value+1); /* +1 to skip opening " */ tmpstr = get_string_literal(&infile, is_wide_char); /* not wide char?? */ store_token(&toklist, tmpstr, TOK_STRING_LITERAL, lineno, NULL); break; } case NAME: { /* identifier */ char *ident; set_input_file_buffer(&infile, tok->name+1); ident = get_identifier(*tok->name, &infile); if (ident != NULL) { store_token(&toklist, ident, TOK_IDENTIFIER, lineno, n_xstrdup(tok->name)); } break; } case CHAR: { int err = 0; int is_wide_char = 0; char *str_value = tok->name; int tmpi; if (*str_value == 'L') { /* Wide character string */ ++str_value; is_wide_char = 1; } set_input_file_buffer(&infile, str_value+1); tmpi = get_char_literal(&infile, &err); /* XXX cross-comp */ if (!err) { int char_type; /* * Character literals are really treated * like integer constants */ int *tmpip = zalloc_buf(Z_CEXPR_BUF); /*n_xmalloc(16);*/ /* XXX */ if (tmpip == NULL) { perror("malloc"); exit(EXIT_FAILURE); } *tmpip = tmpi; if (is_wide_char) { char_type = backend->get_wchar_t()->code; /* * The assignment above assumes int, * i.e. 32bit on all supported * platforms */ assert(backend->get_sizeof_type( backend->get_wchar_t(), NULL) == 4); } else { char_type = TY_INT; } store_token(&toklist, tmpip, char_type, lineno, n_xstrdup(tok->name)); } is_wide_char = 0; break; } case NUMBER: { struct num *n; set_input_file_buffer(&infile, tok->name+1); n = get_num_literal(*tok->name, &infile); if (n != NULL) { store_token(&toklist, n->value, n->type, lineno, n_xstrdup(tok->name)); } else { lexerror("Couldn't read numeric literal"); } break; } case MDOTS: { int *tmp = n_xmalloc(sizeof *tmp); *tmp = 0; store_token(&toklist, tmp, TOK_ELLIPSIS, lineno, NULL); break; } case SLASH: /* / */ case ASSLASH: /* /= */ case MINUS: /* - */ case MMINUS: /* -- */ case ASMINUS: /* -= */ case ARROW: /* -> */ case PLUS: /* + */ case PPLUS: /* ++ */ case ASPLUS: /* += */ case LT: /* < */ case LEQ: /* <= */ case LSH: /* << */ case ASLSH: /* <<= */ case GT: /* > */ case GEQ: /* >= */ case RSH: /* >> */ case ASRSH: /* >>= */ case ASGN: /* = */ case SAME: /* == */ #ifdef CAST_OP case CAST: /* => */ #endif case NOT: /* ~ */ case NEQ: /* != */ case AND: /* & */ case LAND: /* && */ case ASAND: /* &= */ case OR: /* | */ case LOR: /* || */ case ASOR: /* |= */ case PCT: /* % */ case ASPCT: /* %= */ case STAR: /* * */ case ASSTAR: /* *= */ case CIRC: /* ^ */ case ASCIRC: /* ^= */ case LNOT: /* ! */ case COMMA: /* , */ case QUEST: /* ? */ case COLON: /* : */ case DOT: /* . */ case UPLUS: /* unary + */ case UMINUS: /* unary - */ { int *opval = n_xmalloc(sizeof *opval); char *optext = operators_name[tok->type]; set_input_file_buffer(&infile, optext+1); *opval = get_operator(*optext, &infile, &optext); /* XXX cross-comp */ if (*opval == -1) { lexerror("Invalid operator `%s'", optext); free(opval); } else { store_token(&toklist, opval, TOK_OPERATOR, lineno, tok->name); } break; } default: printf("Unhandled token, type %d, value %s\n", tok->type, tok->name? tok->name: "?"); break; } return NULL; }