/* **************************************************************** * Analisa uma Linha de Controle * **************************************************************** */ void directive (void) { SYMTB *sp, **link_place; MAJOR maj; char *cp, c; /* * Convenção da STACK: * 'U': é indefinido, e nunca foi definido * 'N': é indefinido, mas já foi definido * 'D': é definido */ if ((maj = scan ()) == EOL) { skipline (); return; } if (maj != ID || !TYPE (sp, token.l_name, S_KEYWORD)) { err_msg ( ERRO, TOKMARK, "Esperava uma diretiva de préprocessamento" ); skipline (); return; } switch (sp->s_index) { case DEFINE: if (falselevel == 0) dodefine (); break; case UNDEF: if (falselevel == 0) doundef (); break; case INCLUDE: if (falselevel == 0) { doinclude (); return; } break; case IF: if (falselevel == 0) { if (expression ()) { *stackp++ = 'D'; putoutnl (); } else { *stackp++ = 'U'; falselevel++; } /* * A análise de expressões já processou * o fim de linha. Não devemos avançar mais. */ return; } else { *stackp++ = 'U'; falselevel++; } break; case IFDEF: if (scan () != ID) { err_msg (ERRO, TOKMARK, "Esperava um identificador"); *stackp++ = 'D'; break; } if (TYPE (sp, token.l_name, S_MACRO)) { *stackp++ = 'D'; if (falselevel == 0) putoutnl (); } else { *stackp++ = 'U'; falselevel++; } break; case IFNDEF: if (scan () != ID) { err_msg (ERRO, TOKMARK, "Esperava um identificador"); *stackp++ = 'D'; break; } if (!TYPE (sp, token.l_name, S_MACRO)) { *stackp++ = 'D'; if (falselevel == 0) putoutnl (); } else { *stackp++ = 'U'; falselevel++; } break; case ELIF: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"elif\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (stackp[-1]) { case 'U': if (falselevel == 1) { if (expression ()) { stackp[-1] = 'D'; falselevel--; /* == 0 */ putlineno (lineno); } else { /* Nada faz */ } return; } else { /* Nada faz */ } break; case 'N': /* Nada faz */ break; case 'D': stackp[-1] = 'N'; falselevel++; putoutnl (); break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[-1] ); } break; case ELSE: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"else\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (stackp[-1]) { case 'U': stackp[-1] = 'D'; if (--falselevel == 0) putlineno (lineno + 1); break; case 'N': /* Nada faz */ break; case 'D': stackp[-1] = 'U'; falselevel++; break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[-1] ); } break; case ENDIF: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"endif\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (*--stackp) { case 'U': case 'N': if (--falselevel == 0) putlineno (lineno + 1); break; case 'D': putoutnl (); break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[0] ); } break; case ERROR: if (falselevel == 0) { const char *msg; for (cp = (char *)nextp; CATEG (cp) == SEPAR; cp++) /* vazio */; msg = cp; while (*cp != '\n' && (*cp != '/' || cp[1] != '*')) cp++; c = *cp; *cp = '\0'; err_msg (ERRO, NOMARK, msg); *cp = c; nextp = msg; putoutnl (); } break; case PRAGMA: if (falselevel == 0) dopragma (); break; case LINE: if (falselevel == 0) { if (scan () != ICTE) { err_msg ( ERRO, TOKMARK, "Esperava uma constante" ); }; lineno = token.l_ival - 1; if (scan () == STR) { srcname = token.l_begin + 1; ((char *)token.l_end)[0] = '\0'; scan (); } return; } break; default: err_msg ( COMP, TOKMARK, "Erro no s_index para diretivas" ); } /* end switch (sp->s_index) */ skipline (); } /* end directive */
int prep (void) /* Check for preprocessor commands */ { int b, c; char *ln; ln = line; while (*(++ln) == '#' || *ln == ' ') /* locate first directive character */ ; if ( ! *ln) /* NULL directive */ return (killine ()); /* fprintf(stderr,"prep - line=%s\n",ln); */ if (strcmp2 (ln, "if ") || strcmp2 (ln, "ifdef ") || strcmp2 (ln, "ifndef ")) { /* fprintf(stderr,"prep - calling doif(%s)\n",ln); */ doif (ln); return (killine ()); } if (strcmp2 (ln, "else")) { doelse (); return (killine ()); } if (strcmp2 (ln, "endif")) { doendif (); return (killine ()); } if (strcmp2 (ln, "elif ")) { doelif (ln); return (killine ()); } if (procsw) { if (strcmp2 (ln, "define ")) { c = getident (ln, 7) + 2; /* get end of identifier */ splittok (ln, c); /* tokenize rest of line */ dodefine (strlen (line), &ln[7] - line); /* store #define info */ /* fprintf(stderr,"PREP (after dodef): line=|%s|\n",line); */ tstdupdef (); /* Check for def duplication and fix */ return (killine ()); /* Discard #define line */ } if (strcmp2 (ln, "include ")) { doinclude (&ln[8]); /* open include file */ return (killine ()); /* Discard #include line */ } if (strcmp2 (ln, "undef ")) { /* fprintf(stderr,"prep - undef found %s\n",ln); */ doundef (&ln[6]); /* remove undef identifier from def table */ /* fprintf(stderr,"prep - doundef done\n"); */ return (killine ()); /* Discard #undef line */ } if (strcmp2 (ln, "error ")) { fprintf (stderr, "User error - %s\n", &ln[6]); /* print error */ return (killine ()); /* Discard #error line */ } if (strcmp2 (ln, "asm")) { for (;;) /* send all following lines through for assembler */ { getln (0); if (eflag) break; if (findstr (1, line, "#endasm")) break; if (cflag) puts ("#2"); else printf ("#pragma asm "); printf ("%s\n", line); } if (eflag && cflag) /* error only in Microware mode (no #endasm) */ doerr (18, 1); return (killine ()); } if (strcmp2 (ln, "pragma ")) { dopragma (ln + 7); return (killine ()); } if (strcmp2 (ln, "line ")) { doline (ln + 5); return (killine ()); } doerr (17, 1); /* Illegal preprocessor directive */ return (killine ()); } }
int yylex() { int c; int nextc; char *ptr = Tok; char *eptr = &Tok[MAXTOK]; const char *cptr; int startline; int val; static int bol = 1; /* true if we're at beginning of line */ for (;;) { while (Fp == NULL) { char ibuf[80]; if (*Files == NULL) return (record(EOF, NULL)); Fileopened = stable(*Files++); #ifdef ESC sprintf(Tok, "%s %s %s %s", Cpp, Cppstdargs, Cppargs, Fileopened); if ((Fp = popen(Tok, "r")) == NULL) out(O_DIE|O_SYS, "%s", Tok); #else Fp = eftread_fopen(Fileopened, ibuf, sizeof (ibuf)); #endif /* ESC */ Line = 1; bol = 1; /* add name to stats for visibility */ if (Fp != NULL) { static int fnum; char nbuf[100]; struct filestats *nfs = MALLOC(sizeof (*nfs)); (void) sprintf(nbuf, "lex.file%d", fnum); nfs->stats = stats_new_string(nbuf, "", 0); stats_string_set(nfs->stats, Fileopened); if (ibuf[0] != '\0') { (void) sprintf(nbuf, "lex.file%d-ident", fnum); nfs->idstats = stats_new_string(nbuf, "", 0); stats_string_set(nfs->idstats, ibuf); } else { nfs->idstats = NULL; } nfs->next = Fstats; Fstats = nfs; fnum++; } } switch (c = getc(Fp)) { case '#': /* enforce that we're at beginning of line */ if (!bol) return (record(c, NULL)); while ((c = getc(Fp)) != EOF && (c == ' ' || c == '\t')) ; if (!isdigit(c)) { /* * three cases here: * #pragma * #ident * #something-we-don't-understand * anything we don't expect we just ignore. */ *ptr++ = c; while ((c = getc(Fp)) != EOF && isalnum(c)) if (ptr < eptr - 1) *ptr++ = c; *ptr++ = '\0'; if (strcmp(Tok, "pragma") == 0) { /* skip white space */ while ((c = getc(Fp)) != EOF && (c == ' ' || c == '\t')) ; if (c == EOF || c == '\n') outfl(O_DIE, File, Line, "bad #pragma"); /* pull in next token */ ptr = Tok; *ptr++ = c; while ((c = getc(Fp)) != EOF && !isspace(c)) if (ptr < eptr - 1) *ptr++ = c; *ptr++ = '\0'; (void) ungetc(c, Fp); dopragma(Tok); } else if (strcmp(Tok, "ident") == 0) doident(); } else { /* handle file & line info from cpp */ Line = 0; do { if (!isdigit(c)) break; Line = Line * 10 + c - '0'; } while ((c = getc(Fp)) != EOF); Line--; /* newline will increment it */ while (c != EOF && isspace(c)) c = getc(Fp); if (c != '"') outfl(O_DIE, File, Line, "bad # statement (file name)"); while ((c = getc(Fp)) != EOF && c != '"') if (ptr < eptr - 1) *ptr++ = c; *ptr++ = '\0'; if (c != '"') outfl(O_DIE, File, Line, "bad # statement (quotes)"); File = stable(Tok); } /* skip the rest of the cpp line */ while ((c = getc(Fp)) != EOF && c != '\n' && c != '\r') ; if (c == EOF) return (record(c, NULL)); else (void) ungetc(c, Fp); ptr = Tok; break; case EOF: closefile(); continue; case '\n': Line++; bol = 1; break; case '\r': case ' ': case '\t': bol = 0; break; case '/': bol = 0; /* comment handling */ if ((nextc = getc(Fp)) == EOF) outfl(O_DIE, File, Line, "unexpected EOF"); else if (nextc == '*') { startline = Line; while ((c = getc(Fp)) != EOF) { if (c == '\n') Line++; else if (c == '*' && (((c = getc(Fp)) == EOF) || (c == '/'))) break; } if (c == EOF) { outfl(O_DIE, File, Line, "end of comment not seen " "(started on line %d)", startline); } } else { /* wasn't a comment, return the '/' token */ (void) ungetc(nextc, Fp); return (record(c, NULL)); } break; case '"': { int prevc; bol = 0; prevc = '\0'; /* quoted string handling */ startline = Line; for (;;) { c = getc(Fp); if (c == EOF) outfl(O_DIE, File, Line, "end of string not seen " "(started on line %d)", startline); else if (c == '\n') Line++; else if (c == '"' && prevc != '\\') break; else if (ptr < eptr) *ptr++ = c; prevc = c; } if (ptr >= eptr) out(O_DIE, File, Line, "string too long"); *ptr++ = '\0'; return (record(QUOTE, stable(Tok))); } case '&': bol = 0; /* && */ if ((nextc = getc(Fp)) == '&') return (record(AND, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '|': bol = 0; /* || */ if ((nextc = getc(Fp)) == '|') return (record(OR, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '!': bol = 0; /* ! or != */ if ((nextc = getc(Fp)) == '=') return (record(NE, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '=': bol = 0; /* == */ if ((nextc = getc(Fp)) == '=') return (record(EQ, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '-': bol = 0; /* -> */ if ((nextc = getc(Fp)) == '>') return (record(ARROW, stable(Tok))); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '<': bol = 0; if ((nextc = getc(Fp)) == '=') /* <= */ return (record(LE, NULL)); else if (nextc == '<') /* << */ return (record(LSHIFT, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; case '>': bol = 0; if ((nextc = getc(Fp)) == '=') /* >= */ return (record(GE, NULL)); else if (nextc == '>') /* >> */ return (record(RSHIFT, NULL)); else { (void) ungetc(nextc, Fp); return (record(c, NULL)); } /*NOTREACHED*/ break; default: bol = 0; if (isdigit(c)) { int base; /* collect rest of number */ if (c == '0') { *ptr++ = c; if ((c = getc(Fp)) == EOF) { *ptr++ = '\0'; return (record(NUMBER, stable(Tok))); } else if (c == 'x' || c == 'X') { *ptr++ = c; base = 16; } else { (void) ungetc(c, Fp); base = 8; } } else { *ptr++ = c; base = 10; } while ((c = getc(Fp)) != EOF) { if (ptr >= eptr) out(O_DIE, File, Line, "number too long"); switch (base) { case 16: if (c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') { *ptr++ = c; continue; } /*FALLTHRU*/ case 10: if (c >= '8' && c <= '9') { *ptr++ = c; continue; } /*FALLTHRU*/ case 8: if (c >= '0' && c <= '7') { *ptr++ = c; continue; } /* not valid for this base */ *ptr++ = '\0'; (void) ungetc(c, Fp); return (record(NUMBER, stable(Tok))); } } *ptr++ = '\0'; return (record(NUMBER, stable(Tok))); } else if (isalpha(c)) { /* collect identifier */ *ptr++ = c; for (;;) { c = getc(Fp); if ((isalnum(c) || c == '_') && ptr < eptr) *ptr++ = c; else { (void) ungetc(c, Fp); break; } } if (ptr >= eptr) out(O_DIE, File, Line, "identifier too long"); *ptr++ = '\0'; cptr = stable(Tok); if (val = lex_s2i_lut_lookup(Rwordslut, cptr)) { return (record(val, cptr)); } return (record(ID, cptr)); } else return (record(c, NULL)); } /*NOTREACHED*/ } }