static int getop2(char *s) { int c; /* skip the white space */ while (isspace(c = *s = mygetchar()) && c != '\n') ; s[1] = '\0'; if (!isdigit(c) && !issign(c) && c != '.') { return c; } /* scan the char after the sign */ if (issign(c)) { if (isdigit(c = mygetchar())) { *++s = c; } else { myungetc(c); return *s; } } /* scan for the integral part */ while (isdigit(c = mygetchar())) { *++s = c; } /* not a digit, is it a decimal point? */ if (c == '.') { *++s = c; /* scan for the floating part */ while (isdigit(c = mygetchar())) { *++s = c; } } if (c != EOF) { myungetc(c); } *++s = '\0'; return NUMBER; }
// output the result in *pa, return the status static int getint(double *pa) { int c; // skip the space for (c = mygetc(); isspace(c) && c != EOF; c = mygetc()); if (c == EOF) return EOF; // not a number if (!isdigit(c) && c != '+' && c != '-') return 0; int sign; sign = 1; if (c == '+' || c == '-') { if (c == '-') sign = -1; // have '+' or '-', but not a number if (isspace(c = mygetc()) || c == EOF) { *pa = 0; if (c != EOF) myungetc(c); return c; } } // is a number *pa = 0; for (; isdigit(c) && c != EOF; c = mygetc()) { //printf("%c\n", c); //getchar(); *pa = *pa * 10 + (c - '0'); //printf("%d\n", *pa); } // the fraction if (c == '.') { double fac; for (fac = 0.1, c = mygetc(); isdigit(c) && c != EOF; c = mygetc(), fac /= 10.0) { *pa += (c - '0') * fac; } } *pa *= sign; if (c != EOF) myungetc(c); return c; }
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; }
/* 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; }
static void parse_token(struct token *t) { int c; while (isspace(c = mygetc()) && (c != '\n')) continue; retry: if (isdigit(c)) { t->type = NUM; t->u.num.start = c - '0'; while (isdigit(c = mygetc())) t->u.num.start = t->u.num.start * 10 + c - '0'; t->u.num.end = t->u.num.start; t->u.num.step = 1; if (c == '-') { t->u.num.end = 0; while (isdigit(c = mygetc())) t->u.num.end = t->u.num.end * 10 + c - '0'; if (t->u.num.end < t->u.num.start) parse_err("bad range %u-%u", t->u.num.start, t->u.num.end); } if (c == '/') { t->u.num.step = 0; while (isdigit(c = mygetc())) t->u.num.step = t->u.num.step * 10 + c - '0'; } myungetc(c); } else if (c == '"') { char *p = t->u.str; t->type = STR; while ((c = mygetc()) != '"') { if ((c == '\n') || (c == '\r') || (c == EOF)) parse_err("unexpected newline or end-of-file in string"); *p++ = c; if ((p - t->u.str) >= (sizeof(t->u.str)-1)) parse_err("string too long"); } *p = '\0'; } else if (isalpha(c)) { char *p = t->u.str; t->type = STR; *p++ = c; while (isalnum(c = mygetc()) || (c == '_')) { *p++ = c; if ((p - t->u.str) >= (sizeof(t->u.str)-1)) parse_err("string too long"); } *p = '\0'; myungetc(c); } else if (c == '\\') { /* ignore EOL at line break */ while (isspace(c = mygetc()) && (c != '\n')) continue; if (c != '\n') parse_err("expected newline after backslash"); while (isspace(c = mygetc()) && (c != '\n')) continue; goto retry; } else if (c == '#') { /* ignore until EOL */ while (((c = mygetc()) != EOF) && (c != '\n')) continue; goto retry; } else if ((c == EOF) || (c == '\n')) { t->type = EOL; t->u.ch = c; } else { t->type = CHR; t->u.ch = c; } }