Make the structure for handling the input stack local to the parse

module. The only module accessing it (the current line number) was the
condition module, so pass the current line number as a function argument.
Centralize the pushing of new input sources into one function
ParsePushInput() and rename the function handling the popping from ParseEOF()
to ParsePopInput(). Make the entire thing a little bit clearer, by holding
the current input source in the top element of the stack instead of
using extra variables for this. Use a type-safe intrusive list for the
input stack.
This commit is contained in:
Hartmut Brandt 2005-03-30 15:18:58 +00:00
parent f43eb6f83b
commit ba467ce430
5 changed files with 127 additions and 165 deletions

View File

@ -1034,16 +1034,14 @@ CondE(Boolean doEval)
*-----------------------------------------------------------------------
*/
int
Cond_Eval(char *line)
Cond_Eval(char *line, int lineno)
{
struct If *ifp;
Boolean isElse;
Boolean value = FALSE;
int level; /* Level at which to report errors. */
int lineno;
level = PARSE_FATAL;
lineno = curFile.lineno;
for (line++; *line == ' ' || *line == '\t'; line++) {
continue;

View File

@ -48,7 +48,7 @@
#define COND_SKIP 1 /* Skip the next lines */
#define COND_INVALID 2 /* Not a conditional statement */
int Cond_Eval(char *);
int Cond_Eval(char *, int);
void Cond_End(void);
#endif /* cond_h_6e96ad7c */

View File

@ -51,7 +51,6 @@
#include "sprite.h"
struct GNode;
struct IFile;
struct Path;
/*
@ -63,8 +62,6 @@ extern Lst create;
/* The list of directories to search when looking for targets */
extern struct Path dirSearchPath;
extern struct IFile curFile; /* current makefile */
/* The list of directories to search when looking for includes */
extern struct Path parseIncPath;

View File

@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
* Parse_MainName Returns a Lst of the main target to create.
*/
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
@ -107,7 +108,7 @@ __FBSDID("$FreeBSD$");
#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.
*/
@ -128,10 +129,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);
@ -228,8 +242,6 @@ static struct {
{ ".WAIT", Wait, 0 },
};
static int ParseEOF(int);
/*-
*----------------------------------------------------------------------
* ParseFindKeyword --
@ -287,7 +299,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);
@ -298,6 +310,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 --
@ -1536,15 +1623,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 */
@ -1613,7 +1698,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) {
@ -1671,37 +1756,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);
}
/*-
@ -1720,20 +1779,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
@ -1757,7 +1806,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;
@ -1816,81 +1864,14 @@ 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 --
@ -1906,11 +1887,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);
}
@ -1930,12 +1912,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;
}
}
@ -1974,7 +1956,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;
@ -1994,7 +1976,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] != '.');
@ -2053,7 +2035,7 @@ ParseReadLine(void)
ignComment = ignDepOp = TRUE;
break;
} else if (c == '\n') {
curFile.lineno++;
CURFILE->lineno++;
} else if (c == '#') {
ParseUnreadc(c);
break;
@ -2084,7 +2066,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;
@ -2202,7 +2184,7 @@ ParseReadLine(void)
lastc = c;
}
line_read:
curFile.lineno++;
CURFILE->lineno++;
if (lastc != '\0') {
Buf_AddByte(buf, (Byte)lastc);
@ -2230,7 +2212,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
@ -2239,7 +2221,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*/
@ -2253,7 +2237,7 @@ ParseReadLine(void)
if (For_Eval(line)) {
int ok;
free(line);
lineno = curFile.lineno;
lineno = CURFILE->lineno;
do {
/*
* Skip after the matching end
@ -2334,19 +2318,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) {
@ -2507,7 +2488,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();

View File

@ -48,26 +48,12 @@
struct GNode;
struct Lst;
/*
* Definitions for handling #include specifications
*/
typedef struct {
char *str;
char *ptr;
} PTR;
typedef struct IFile {
char *fname; /* name of previous file */
int lineno; /* saved line number */
FILE *F; /* the open stream */
PTR *p; /* the char pointer */
} IFile;
void Parse_Error(int, const char *, ...);
Boolean Parse_AnyExport(void);
Boolean Parse_IsVar(char *);
void Parse_DoVar(char *, struct GNode *);
void Parse_AddIncludeDir(char *);
void Parse_File(char *, FILE *);
void Parse_File(const char *, FILE *);
void Parse_Init(void);
void Parse_FromString(char *, int);
void Parse_MainName(struct Lst *);