void undefine (const char *symbol, struct inclist *file) { register struct symtab **ptr; struct inclist *srcfile; while ((ptr = isdefined (symbol, file, &srcfile)) != NULL) { srcfile->i_ndefs--; for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++) *ptr = ptr[1]; } }
/* * return the next definition you see */ definition * get_definition (void) { definition *defp; token tok; defp = ALLOC (definition); get_token (&tok); switch (tok.kind) { case TOK_STRUCT: def_struct (defp); break; case TOK_UNION: def_union (defp); break; case TOK_TYPEDEF: def_typedef (defp); break; case TOK_ENUM: def_enum (defp); break; case TOK_PROGRAM: def_program (defp); break; case TOK_CONST: def_const (defp); break; case TOK_EOF: free (defp); return (NULL); default: error ("definition keyword expected"); } scan (TOK_SEMICOLON, &tok); isdefined (defp); return (defp); }
/* * Decide what type of # directive this line is. */ int deftype (char *line, struct filepointer *filep, struct inclist *file_red, struct inclist *file, int parse_it) { register char *p; char *directive, savechar; register int ret; /* Parse the directive... */ directive = line + 1; while (*directive == ' ' || *directive == '\t') directive++; p = directive; while (*p >= 'a' && *p <= 'z') p++; savechar = *p; *p = '\0'; ret = match (directive, directives); *p = savechar; /* If we don't recognize this compiler directive or we happen to just be gobbling up text while waiting for an #endif or #elif or #else in the case of an #elif we must check the zero_value and return an ELIF or an ELIFFALSE. */ if (ret == ELIF && !parse_it) { while (*p == ' ' || *p == '\t') p++; /* parse an expression. */ debug (0, ("%s, line %d: #elif %s ", file->i_file, filep->f_line, p)); ret = zero_value (p, filep, file_red); if (ret != IF) { debug (0, ("false...\n")); if (ret == IFFALSE) return (ELIFFALSE); else return (ELIFGUESSFALSE); } else { debug (0, ("true...\n")); return (ELIF); } } if (ret < 0 || !parse_it) return (ret); /* now decide how to parse the directive, and do it. */ while (*p == ' ' || *p == '\t') p++; switch (ret) { case IF: /* parse an expression. */ ret = zero_value (p, filep, file_red); debug (0, ("%s, line %d: %s #if %s\n", file->i_file, filep->f_line, ret ? "false" : "true", p)); break; case IFDEF: case IFNDEF: debug (0, ("%s, line %d: #%s %s\n", file->i_file, filep->f_line, directives[ret], p)); case UNDEF: /* separate the name of a single symbol. */ while (isalnum (*p) || *p == '_') *line++ = *p++; *line = '\0'; break; case INCLUDE: debug (2, ("%s, line %d: #include %s\n", file->i_file, filep->f_line, p)); /* Support ANSI macro substitution */ { struct symtab **sym = isdefined (p, file_red, NULL); while (sym) { p = (char *)(*sym)->s_value; debug (3, ("%s : #includes SYMBOL %s = %s\n", file->i_incstring, (*sym)->s_name, (*sym)->s_value)); /* mark file as having included a 'soft include' */ file->i_flags |= INCLUDED_SYM; sym = isdefined (p, file_red, NULL); } } /* Separate the name of the include file. */ while (*p && *p != '"' && *p != '<') p++; if (!*p) return (-2); if (*p++ == '"') { ret = INCLUDEDOT; while (*p && *p != '"') *line++ = *p++; } else while (*p && *p != '>') *line++ = *p++; *line = '\0'; break; case DEFINE: /* copy the definition back to the beginning of the line. */ strcpy (line, p); break; case ELSE: case ENDIF: case ELIF: case PRAGMA: case ERROR: case IDENT: case SCCS: case EJECT: case WARNING: debug (0, ("%s, line %d: #%s\n", file->i_file, filep->f_line, directives[ret])); /* nothing to do. */ break; } return (ret); }
int find_includes (struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, bool failOK) { register char *line; register int type; bool recfailOK; while ((line = getline (filep))) { switch (type = deftype (line, filep, file_red, file, true)) { case IF: doif: type = find_includes (filep, file, file_red, recursion + 1, failOK); while ((type == ELIF) || (type == ELIFFALSE) || (type == ELIFGUESSFALSE)) type = gobble (filep, file, file_red); if (type == ELSE) gobble (filep, file, file_red); break; case IFFALSE: case IFGUESSFALSE: doiffalse: if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) recfailOK = true; else recfailOK = failOK; type = gobble (filep, file, file_red); if (type == ELSE) find_includes (filep, file, file_red, recursion + 1, recfailOK); else if (type == ELIF) goto doif; else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) goto doiffalse; break; case IFDEF: case IFNDEF: if ((type == IFDEF && isdefined (line, file_red, NULL)) || (type == IFNDEF && !isdefined (line, file_red, NULL))) { debug (1, (type == IFNDEF ? "line %d: %s !def'd in %s via %s%s\n" : "", filep->f_line, line, file->i_file, file_red->i_file, ": doit")); type = find_includes (filep, file, file_red, recursion + 1, failOK); while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) type = gobble (filep, file, file_red); if (type == ELSE) gobble (filep, file, file_red); } else { debug (1, (type == IFDEF ? "line %d: %s !def'd in %s via %s%s\n" : "", filep->f_line, line, file->i_file, file_red->i_file, ": gobble")); type = gobble (filep, file, file_red); if (type == ELSE) find_includes (filep, file, file_red, recursion + 1, failOK); else if (type == ELIF) goto doif; else if (type == ELIFFALSE || type == ELIFGUESSFALSE) goto doiffalse; } break; case ELSE: case ELIFFALSE: case ELIFGUESSFALSE: case ELIF: if (!recursion) gobble (filep, file, file_red); case ENDIF: if (recursion) return (type); case DEFINE: define (line, file); break; case UNDEF: if (!*line) { warning ("%s, line %d: incomplete undef == \"%s\"\n", file->i_file, filep->f_line, line); display_included (file_red, file); break; } undefine (line, file_red); break; case INCLUDE: add_include (filep, file, file_red, line, false, failOK); break; case INCLUDEDOT: add_include (filep, file, file_red, line, true, failOK); break; case ERROR: case WARNING: warning ("%s: %d: %s\n", file->i_file, filep->f_line, line); display_included (file_red, file); break; case PRAGMA: case IDENT: case SCCS: case EJECT: break; case -1: warning ("%s", file_red->i_file); if (file_red != file) warning1 (" (reading %s)", file->i_file); warning1 (", line %d: unknown directive == \"%s\"\n", filep->f_line, line); break; case -2: warning ("%s", file_red->i_file); if (file_red != file) warning1 (" (reading %s)", file->i_file); warning1 (", line %d: incomplete include == \"%s\"\n", filep->f_line, line); break; } } file->i_flags |= FINISHED; return (-1); }
int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK) { struct inclist *inclistp; char **includedirsp; register char *line; register int type; boolean recfailOK; while ((line = getnextline(filep))) { switch(type = deftype(line, filep, file_red, file, TRUE)) { case IF: doif: type = find_includes(filep, file, file_red, recursion+1, failOK); while ((type == ELIF) || (type == ELIFFALSE) || (type == ELIFGUESSFALSE)) type = gobble(filep, file, file_red); if (type == ELSE) gobble(filep, file, file_red); break; case IFFALSE: case IFGUESSFALSE: doiffalse: if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) recfailOK = TRUE; else recfailOK = failOK; type = gobble(filep, file, file_red); if (type == ELSE) find_includes(filep, file, file_red, recursion+1, recfailOK); else if (type == ELIF) goto doif; else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) goto doiffalse; break; case IFDEF: case IFNDEF: { int isdef = (isdefined(line, file_red, NULL) != NULL); if (type == IFNDEF) isdef = !isdef; if (isdef) { debug(1,(type == IFNDEF ? "line %d: %s !def'd in %s via %s%s\n" : "", filep->f_line, line, file->i_file, file_red->i_file, ": doit")); type = find_includes(filep, file, file_red, recursion+1, failOK); while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) type = gobble(filep, file, file_red); if (type == ELSE) gobble(filep, file, file_red); } else { debug(1,(type == IFDEF ? "line %d: %s !def'd in %s via %s%s\n" : "", filep->f_line, line, file->i_file, file_red->i_file, ": gobble")); type = gobble(filep, file, file_red); if (type == ELSE) find_includes(filep, file, file_red, recursion+1, failOK); else if (type == ELIF) goto doif; else if (type == ELIFFALSE || type == ELIFGUESSFALSE) goto doiffalse; } } break; case ELSE: case ELIFFALSE: case ELIFGUESSFALSE: case ELIF: if (!recursion) gobble(filep, file, file_red); case ENDIF: if (recursion) return(type); case DEFINE: define(line, file); break; case UNDEF: if (!*line) { warning("%s", file_red->i_file); if (file_red != file) warning1(" (reading %s)", file->i_file); warning1(", line %d: incomplete undef == \"%s\"\n", filep->f_line, line); break; } undefine(line, file_red); break; case INCLUDE: case INCLUDEDOT: case INCLUDENEXT: case INCLUDENEXTDOT: inclistp = inclistnext; includedirsp = includedirsnext; debug(2,("%s, reading %s, includes %s\n", file_red->i_file, file->i_file, line)); add_include(filep, file, file_red, line, type, failOK); inclistnext = inclistp; includedirsnext = includedirsp; break; case ERROR: case WARNING: warning("%s", file_red->i_file); if (file_red != file) warning1(" (reading %s)", file->i_file); warning1(", line %d: %s\n", filep->f_line, line); break; case PRAGMA: case IDENT: case SCCS: case EJECT: break; case -1: warning("%s", file_red->i_file); if (file_red != file) warning1(" (reading %s)", file->i_file); warning1(", line %d: unknown directive == \"%s\"\n", filep->f_line, line); break; case -2: warning("%s", file_red->i_file); if (file_red != file) warning1(" (reading %s)", file->i_file); warning1(", line %d: incomplete include == \"%s\"\n", filep->f_line, line); break; } } file->i_flags |= FINISHED; debug(2,("finished with %s\n", file->i_file)); return(-1); }