char rcsid_lex[] = "$Id$"; #include #include #include #include "b.h" #include "fe.h" #include "gram.tab.h" static char buf[BUFSIZ]; static int yyline = 1; typedef int (*ReadFn) ARGS((void)); static char *StrCopy ARGS((char *)); static int code_get ARGS((void)); static int simple_get ARGS((void)); static void ReadCharString ARGS((ReadFn, int)); static void ReadCodeBlock ARGS((void)); static void ReadOldComment ARGS((ReadFn)); static char * StrCopy(s) char *s; { char *t = (char *)zalloc(strlen(s) + 1); strcpy(t,s); return t; } static int simple_get() { int ch; if ((ch = getchar()) == '\n') { yyline++; } return ch; } static int code_get() { int ch; if ((ch = getchar()) == '\n') { yyline++; } if (ch != EOF) { fputc(ch, outfile); } return ch; } void yypurge() { while (code_get() != EOF) ; } static void ReadCharString(rdfn, which) ReadFn rdfn; int which; { int ch; int backslash = 0; int firstline = yyline; while ((ch = rdfn()) != EOF) { if (ch == which && !backslash) { return; } if (ch == '\\' && !backslash) { backslash = 1; } else { backslash = 0; } } yyerror1("Unexpected EOF in string on line "); fprintf(stderr, "%d\n", firstline); exit(1); } static void ReadOldComment(rdfn) ReadFn rdfn; { /* will not work for comments delimiter in string */ int ch; int starred = 0; int firstline = yyline; while ((ch = rdfn()) != EOF) { if (ch == '*') { starred = 1; } else if (ch == '/' && starred) { return; } else { starred = 0; } } yyerror1("Unexpected EOF in comment on line "); fprintf(stderr, "%d\n", firstline); exit(1); } static void ReadCodeBlock() { int ch; int firstline = yyline; while ((ch = getchar()) != EOF) { if (ch == '%') { ch = getchar(); if (ch != '}') { yyerror("bad %%"); } return; } fputc(ch, outfile); if (ch == '\n') { yyline++; } if (ch == '"' || ch == '\'') { ReadCharString(code_get, ch); } else if (ch == '/') { ch = getchar(); if (ch == '*') { fputc(ch, outfile); ReadOldComment(code_get); continue; } else { ungetc(ch, stdin); } } } yyerror1("Unclosed block of C code started on line "); fprintf(stderr, "%d\n", firstline); exit(1); } static int done; void yyfinished() { done = 1; } int yylex() { int ch; char *ptr = buf; if (done) return 0; while ((ch = getchar()) != EOF) { switch (ch) { case ' ': case '\f': case '\t': continue; case '\n': yyline++; continue; case '(': case ')': case ',': case ':': case ';': case '=': return(ch); case '/': ch = getchar(); if (ch == '*') { ReadOldComment(simple_get); continue; } else { ungetc(ch, stdin); yyerror("illegal char /"); continue; } case '%': ch = getchar(); switch (ch) { case '%': return (K_PPERCENT); case '{': ReadCodeBlock(); continue; case 's': case 'g': case 't': do { if (ptr >= &buf[BUFSIZ]) { yyerror("ID too long"); return(ERROR); } else { *ptr++ = ch; } ch = getchar(); } while (isalpha(ch) || isdigit(ch) || ch == '_'); ungetc(ch, stdin); *ptr = '\0'; if (!strcmp(buf, "term")) return K_TERM; if (!strcmp(buf, "start")) return K_START; if (!strcmp(buf, "gram")) return K_GRAM; yyerror("illegal character after %%"); continue; default: yyerror("illegal character after %%"); continue; } default: if (isalpha(ch) ) { do { if (ptr >= &buf[BUFSIZ]) { yyerror("ID too long"); return(ERROR); } else { *ptr++ = ch; } ch = getchar(); } while (isalpha(ch) || isdigit(ch) || ch == '_'); ungetc(ch, stdin); *ptr = '\0'; yylval.y_string = StrCopy(buf); return(ID); } if (isdigit(ch)) { int val=0; do { val *= 10; val += (ch - '0'); ch = getchar(); } while (isdigit(ch)); ungetc(ch, stdin); yylval.y_int = val; return(INT); } yyerror1("illegal char "); fprintf(stderr, "(\\%03o)\n", ch); exit(1); } } return(0); } void yyerror1(const char *str) { fprintf(stderr, "line %d: %s", yyline, str); } void yyerror(const char *str) { yyerror1(str); fprintf(stderr, "\n"); exit(1); }