--- src/usr.bin/make/parse.c 2005/04/01 00:48:59 1.63 +++ src/usr.bin/make/parse.c 2005/04/01 01:12:55 1.64 @@ -80,6 +80,7 @@ * Parse_MainName Returns a Lst of the main target to create. */ +#include #include #include #include @@ -106,7 +107,7 @@ #include "var.h" /* - * These values are returned by ParseEOF to tell Parse_File whether to + * These values are returned by ParsePopInput to tell Parse_File whether to * CONTINUE parsing, i.e. it had only reached the end of an include file, * or if it's DONE. */ @@ -127,10 +128,23 @@ static int fatals = 0; */ static GNode *mainNode; -IFile curFile; /* current makefile */ +/* + * Definitions for handling #include specifications + */ +struct IFile { + char *fname; /* name of previous file */ + int lineno; /* saved line number */ + FILE *F; /* the open stream */ + char *str; /* the string when parsing a string */ + char *ptr; /* the current pointer when parsing a string */ + TAILQ_ENTRY(IFile) link;/* stack the files */ +}; /* stack of IFiles generated by * #includes */ -static Lst includes = Lst_Initializer(includes); +static TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes); + +/* access current file */ +#define CURFILE (TAILQ_FIRST(&includes)) /* list of directories for "..." includes */ struct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath); @@ -227,8 +241,6 @@ static struct { { ".WAIT", Wait, 0 }, }; -static int ParseEOF(int); - /*- *---------------------------------------------------------------------- * ParseFindKeyword -- @@ -286,7 +298,7 @@ Parse_Error(int type, const char *fmt, . va_list ap; va_start(ap, fmt); - fprintf(stderr, "\"%s\", line %d: ", curFile.fname, curFile.lineno); + fprintf(stderr, "\"%s\", line %d: ", CURFILE->fname, CURFILE->lineno); if (type == PARSE_WARNING) fprintf(stderr, "warning: "); vfprintf(stderr, fmt, ap); @@ -297,6 +309,81 @@ Parse_Error(int type, const char *fmt, . fatals += 1; } +/** + * ParsePushInput + * + * Push a new input source onto the input stack. If ptr is NULL + * the fullname is used to fopen the file. If it is not NULL, + * ptr is assumed to point to the string to be parsed. If opening the + * file fails, the fullname is freed. + */ +static void +ParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno) +{ + struct IFile *nf; + + nf = emalloc(sizeof(*nf)); + nf->fname = fullname; + nf->lineno = lineno; + + if (ptr == NULL) { + /* the input source is a file */ + if ((nf->F = fp) == NULL) { + nf->F = fopen(fullname, "r"); + if (nf->F == NULL) { + Parse_Error(PARSE_FATAL, "Cannot open %s", + fullname); + free(fullname); + free(nf); + return; + } + } + nf->str = nf->ptr = NULL; + Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); + } else { + nf->str = nf->ptr = ptr; + nf->F = NULL; + } + TAILQ_INSERT_HEAD(&includes, nf, link); +} + +/** + * ParsePopInput + * Called when EOF is reached in the current file. If we were reading + * an include file, the includes stack is popped and things set up + * to go back to reading the previous file at the previous location. + * + * Results: + * CONTINUE if there's more to do. DONE if not. + * + * Side Effects: + * The old curFile.F is closed. The includes list is shortened. + * curFile.lineno, curFile.F, and curFile.fname are changed if + * CONTINUE is returned. + */ +static int +ParsePopInput(void) +{ + struct IFile *ifile; /* the state on the top of the includes stack */ + + assert(!TAILQ_EMPTY(&includes)); + + ifile = TAILQ_FIRST(&includes); + TAILQ_REMOVE(&includes, ifile, link); + + free(ifile->fname); + if (ifile->F != NULL) { + fclose(ifile->F); + Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); + } + if (ifile->str != NULL) { + free(ifile->str); + } + free(ifile); + + return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE); +} + /*- *--------------------------------------------------------------------- * ParseLinkSrc -- @@ -1549,15 +1636,13 @@ ParseDoWarning(char *warnmsg) * None * * Side Effects: - * A structure is added to the includes Lst and readProc, curFile.lineno, - * curFile.fname and curFile.F are altered for the new file + * A structure is added to the includes Lst and readProc. *--------------------------------------------------------------------- */ static void ParseDoInclude(char *file) { char *fullname; /* full pathname of file */ - IFile *oldFile; /* state associated with current file */ char endc; /* the character which ends the file spec */ char *cp; /* current position in file spec */ Boolean isSystem; /* TRUE if makefile is a system makefile */ @@ -1626,7 +1711,7 @@ ParseDoInclude(char *file) char *prefEnd, *Fname; /* Make a temporary copy of this, to be safe. */ - Fname = estrdup(curFile.fname); + Fname = estrdup(CURFILE->fname); prefEnd = strrchr(Fname, '/'); if (prefEnd != (char *)NULL) { @@ -1684,37 +1769,11 @@ ParseDoInclude(char *file) free(file); /* - * Once we find the absolute path to the file, we get to save all the - * state from the current file before we can start reading this - * include file. The state is stored in an IFile structure which - * is placed on a list with other IFile structures. The list makes - * a very nice stack to track how we got here... - */ - oldFile = emalloc(sizeof(IFile)); - memcpy(oldFile, &curFile, sizeof(IFile)); - - Lst_AtFront(&includes, oldFile); - - /* - * Once the previous state has been saved, we can get down to reading - * the new file. We set up the name of the file to be the absolute + * We set up the name of the file to be the absolute * name of the include file so error messages refer to the right - * place. Naturally enough, we start reading at line number 0. + * place. */ - curFile.fname = fullname; - curFile.lineno = 0; - - curFile.F = fopen(fullname, "r"); - curFile.p = NULL; - if (curFile.F == NULL) { - Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); - /* - * Pop to previous file - */ - ParseEOF(0); - } else { - Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); - } + ParsePushInput(fullname, NULL, NULL, 0); } /*- @@ -1733,20 +1792,10 @@ ParseDoInclude(char *file) void Parse_FromString(char *str, int lineno) { - IFile *oldFile; /* state associated with this file */ DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); - oldFile = emalloc(sizeof(IFile)); - memcpy(oldFile, &curFile, sizeof(IFile)); - - Lst_AtFront(&includes, oldFile); - - curFile.F = NULL; - curFile.p = emalloc(sizeof(PTR)); - curFile.p->str = curFile.p->ptr = str; - curFile.lineno = lineno; - curFile.fname = estrdup(curFile.fname); + ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno); } #ifdef SYSVINCLUDE @@ -1770,7 +1819,6 @@ static void ParseTraditionalInclude(char *file) { char *fullname; /* full pathname of file */ - IFile *oldFile; /* state associated with current file */ char *cp; /* current position in file spec */ Buffer *buf; @@ -1829,83 +1877,16 @@ ParseTraditionalInclude(char *file) /* XXXHB free(file) */ /* - * Once we find the absolute path to the file, we get to save all the - * state from the current file before we can start reading this - * include file. The state is stored in an IFile structure which - * is placed on a list with other IFile structures. The list makes - * a very nice stack to track how we got here... - */ - oldFile = emalloc(sizeof(IFile)); - memcpy(oldFile, &curFile, sizeof(IFile)); - - Lst_AtFront(&includes, oldFile); - - /* - * Once the previous state has been saved, we can get down to reading - * the new file. We set up the name of the file to be the absolute + * We set up the name of the file to be the absolute * name of the include file so error messages refer to the right - * place. Naturally enough, we start reading at line number 0. + * place. */ - curFile.fname = fullname; - curFile.lineno = 0; - - curFile.F = fopen(fullname, "r"); - curFile.p = NULL; - if (curFile.F == NULL) { - Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); - /* - * Pop to previous file - */ - ParseEOF(1); - } else { - Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); - } + ParsePushInput(fullname, NULL, NULL, 0); } #endif /*- *--------------------------------------------------------------------- - * ParseEOF -- - * Called when EOF is reached in the current file. If we were reading - * an include file, the includes stack is popped and things set up - * to go back to reading the previous file at the previous location. - * - * Results: - * CONTINUE if there's more to do. DONE if not. - * - * Side Effects: - * The old curFile.F is closed. The includes list is shortened. - * curFile.lineno, curFile.F, and curFile.fname are changed if - * CONTINUE is returned. - *--------------------------------------------------------------------- - */ -static int -ParseEOF(int opened) -{ - IFile *ifile; /* the state on the top of the includes stack */ - - if (Lst_IsEmpty(&includes)) { - Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); - return (DONE); - } - - ifile = Lst_DeQueue(&includes); - free(curFile.fname); - if (opened && curFile.F) { - fclose(curFile.F); - Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); - } - if (curFile.p) { - free(curFile.p->str); - free(curFile.p); - } - memcpy(&curFile, ifile, sizeof(IFile)); - free(ifile); - return (CONTINUE); -} - -/*- - *--------------------------------------------------------------------- * ParseReadc -- * Read a character from the current file * @@ -1919,11 +1900,12 @@ static int ParseReadc(void) { - if (curFile.F) - return (fgetc(curFile.F)); + if (CURFILE->F != NULL) + return (fgetc(CURFILE->F)); + + if (CURFILE->str != NULL && *CURFILE->ptr != '\0') + return (*CURFILE->ptr++); - if (curFile.p && *curFile.p->ptr) - return (*curFile.p->ptr++); return (EOF); } @@ -1943,12 +1925,12 @@ static void ParseUnreadc(int c) { - if (curFile.F) { - ungetc(c, curFile.F); + if (CURFILE->F != NULL) { + ungetc(c, CURFILE->F); return; } - if (curFile.p) { - *--(curFile.p->ptr) = c; + if (CURFILE->str != NULL) { + *--(CURFILE->ptr) = c; return; } } @@ -1987,7 +1969,7 @@ ParseSkipLine(int skip, int keep_newline Buf_AddByte(buf, (Byte)c); else Buf_ReplaceLastByte(buf, (Byte)' '); - curFile.lineno++; + CURFILE->lineno++; while ((c = ParseReadc()) == ' ' || c == '\t') continue; @@ -2007,7 +1989,7 @@ ParseSkipLine(int skip, int keep_newline return (NULL); } - curFile.lineno++; + CURFILE->lineno++; Buf_AddByte(buf, (Byte)'\0'); line = Buf_Data(buf); } while (skip == 1 && line[0] != '.'); @@ -2066,7 +2048,7 @@ ParseReadLine(void) ignComment = ignDepOp = TRUE; break; } else if (c == '\n') { - curFile.lineno++; + CURFILE->lineno++; } else if (c == '#') { ParseUnreadc(c); break; @@ -2097,7 +2079,7 @@ ParseReadLine(void) * it will be recognized as a newline in the * code below this... */ - curFile.lineno++; + CURFILE->lineno++; lastc = ' '; while ((c = ParseReadc()) == ' ' || c == '\t') { continue; @@ -2215,7 +2197,7 @@ ParseReadLine(void) lastc = c; } line_read: - curFile.lineno++; + CURFILE->lineno++; if (lastc != '\0') { Buf_AddByte(buf, (Byte)lastc); @@ -2243,7 +2225,7 @@ ParseReadLine(void) * The line might be a conditional. Ask the * conditional module about it and act accordingly */ - switch (Cond_Eval(line)) { + switch (Cond_Eval(line, CURFILE->lineno)) { case COND_SKIP: /* * Skip to next conditional that evaluates to @@ -2252,7 +2234,9 @@ ParseReadLine(void) do { free(line); line = ParseSkipLine(1, 0); - } while (line && Cond_Eval(line) != COND_PARSE); + } while (line && + Cond_Eval(line, CURFILE->lineno) != + COND_PARSE); if (line == NULL) break; /*FALLTHRU*/ @@ -2266,7 +2250,7 @@ ParseReadLine(void) if (For_Eval(line)) { int ok; free(line); - lineno = curFile.lineno; + lineno = CURFILE->lineno; do { /* * Skip after the matching end @@ -2347,19 +2331,16 @@ ParseFinishLine(void) *--------------------------------------------------------------------- */ void -Parse_File(char *name, FILE *stream) +Parse_File(const char *name, FILE *stream) { char *cp; /* pointer into the line */ char *line; /* the line we're working on */ Buffer *buf; inLine = FALSE; - curFile.fname = name; - curFile.F = stream; - curFile.lineno = 0; fatals = 0; - Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL); + ParsePushInput(estrdup(name), stream, NULL, 0); do { while ((line = ParseReadLine()) != NULL) { @@ -2510,7 +2491,7 @@ Parse_File(char *name, FILE *stream) /* * Reached EOF, but it may be just EOF of an include file... */ - } while (ParseEOF(1) == CONTINUE); + } while (ParsePopInput() == CONTINUE); ParseFinishLine();