Reworked the fix to print the useful line number on error in

the .for loop:

- Replaced four global variables in parse.c with one.
- Made Parse_FromString() accept the "lineno" as an argument.
- Fixed line numbering when there are escaped newlines in the
  body of the .for loop.

Adopted from:	NetBSD
This commit is contained in:
Ruslan Ermilov 2004-03-10 21:51:06 +00:00
parent 39a78f8cf4
commit 30b800de8e
3 changed files with 79 additions and 89 deletions

View File

@ -81,6 +81,7 @@ typedef struct _For {
Buffer buf; /* Unexpanded buffer */
char* var; /* Index name */
Lst lst; /* List of variables */
int lineno; /* Line # */
} For;
static int ForExec(void *, void *);
@ -254,7 +255,7 @@ ForExec(void *namep, void *argp)
Var_Set(arg->var, name, VAR_GLOBAL);
DEBUGF(FOR, ("--- %s = %s\n", arg->var, name));
Parse_FromString(Var_Subst(arg->var, (char *) Buf_GetAll(arg->buf, &len),
VAR_GLOBAL, FALSE));
VAR_GLOBAL, FALSE), arg->lineno);
Var_Delete(arg->var, VAR_GLOBAL);
return 0;
@ -275,7 +276,7 @@ ForExec(void *namep, void *argp)
*-----------------------------------------------------------------------
*/
void
For_Run(void)
For_Run(int lineno)
{
For arg;
@ -284,6 +285,7 @@ For_Run(void)
arg.var = forVar;
arg.buf = forBuf;
arg.lst = forLst;
arg.lineno = lineno;
forVar = NULL;
forBuf = NULL;
forLst = NULL;

View File

@ -59,7 +59,7 @@ void Cond_End(void);
/* for.c */
int For_Eval(char *);
void For_Run(void);
void For_Run(int);
/* main.c */
void Main_ParseArgLine(char *);
@ -86,7 +86,7 @@ void Parse_AddIncludeDir(char *);
void Parse_File(char *, FILE *);
void Parse_Init(void);
void Parse_End(void);
void Parse_FromString(char *);
void Parse_FromString(char *, int);
Lst Parse_MainName(void);
/* str.c */

View File

@ -55,9 +55,9 @@ __FBSDID("$FreeBSD$");
* those for the #include <...> are kept in the 'sysIncPath' Lst. The
* targets currently being defined are kept in the 'targets' Lst.
*
* The variables 'fname' and 'lineno' are used to track the name
* of the current file and the line number in that file so that error
* messages can be more meaningful.
* The variables 'curFile.fname' and 'curFile.lineno' are used to track
* the name of the current file and the line number in that file so that
* error messages can be more meaningful.
*
* Interface:
* Parse_Init Initialization function which must be
@ -110,13 +110,6 @@ typedef struct {
char *ptr;
} PTR;
static char *fname; /* name of current file (for errors) */
static int lineno; /* line number in current file */
static int savedlineno; /* saved line number */
static FILE *curFILE = NULL; /* current makefile */
static PTR *curPTR = NULL; /* current makefile */
static int fatals = 0;
static GNode *mainNode; /* The main target to create. This is the
@ -132,6 +125,8 @@ typedef struct IFile {
PTR * p; /* the char pointer */
} IFile;
static IFile curFile;
static Lst includes; /* stack of IFiles generated by
* #includes */
Lst parseIncPath; /* list of directories for "..." includes */
@ -251,7 +246,7 @@ static void ParseTraditionalInclude(char *);
#endif
static int ParseEOF(int);
static char *ParseReadLine(void);
static char *ParseSkipLine(int);
static char *ParseSkipLine(int, int);
static void ParseFinishLine(void);
/*-
@ -311,7 +306,8 @@ Parse_Error(int type, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
(void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
(void)fprintf(stderr, "\"%s\", line %d: ",
curFile.fname, curFile.lineno);
if (type == PARSE_WARNING)
(void)fprintf(stderr, "warning: ");
(void)vfprintf(stderr, fmt, ap);
@ -1576,7 +1572,8 @@ ParseDoError(char *errmsg)
errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
/* use fprintf/exit instead of Parse_Error to terminate immediately */
fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg);
fprintf(stderr, "\"%s\", line %d: %s\n",
curFile.fname, curFile.lineno, errmsg);
exit(1);
}
@ -1594,8 +1591,8 @@ ParseDoError(char *errmsg)
* None
*
* Side Effects:
* A structure is added to the includes Lst and readProc, lineno,
* fname and curFILE are altered for the new file
* A structure is added to the includes Lst and readProc, curFile.lineno,
* curFile.fname and curFile.F are altered for the new file
*---------------------------------------------------------------------
*/
static void
@ -1670,7 +1667,7 @@ ParseDoInclude (char *file)
char *prefEnd, *Fname;
/* Make a temporary copy of this, to be safe. */
Fname = estrdup(fname);
Fname = estrdup(curFile.fname);
prefEnd = strrchr (Fname, '/');
if (prefEnd != (char *)NULL) {
@ -1732,11 +1729,7 @@ ParseDoInclude (char *file)
* a very nice stack to track how we got here...
*/
oldFile = (IFile *) emalloc (sizeof (IFile));
oldFile->fname = fname;
oldFile->F = curFILE;
oldFile->p = curPTR;
oldFile->lineno = lineno;
memcpy(oldFile, &curFile, sizeof (IFile));
(void) Lst_AtFront (includes, (void *)oldFile);
@ -1746,12 +1739,12 @@ ParseDoInclude (char *file)
* name of the include file so error messages refer to the right
* place. Naturally enough, we start reading at line number 0.
*/
fname = fullname;
lineno = 0;
curFile.fname = fullname;
curFile.lineno = 0;
curFILE = fopen (fullname, "r");
curPTR = NULL;
if (curFILE == (FILE * ) NULL) {
curFile.F = fopen (fullname, "r");
curFile.p = NULL;
if (curFile.F == (FILE * ) NULL) {
Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
/*
* Pop to previous file
@ -1771,30 +1764,27 @@ ParseDoInclude (char *file)
* None
*
* Side Effects:
* A structure is added to the includes Lst and readProc, lineno,
* fname and curFILE are altered for the new file
* A structure is added to the includes Lst and readProc, curFile.lineno,
* curFile.fname and curFile.F are altered for the new file
*---------------------------------------------------------------------
*/
void
Parse_FromString(char *str)
Parse_FromString(char *str, int lineno)
{
IFile *oldFile; /* state associated with this file */
DEBUGF(FOR, ("%s\n----\n", str));
DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
oldFile = (IFile *) emalloc (sizeof (IFile));
oldFile->lineno = lineno;
oldFile->fname = fname;
oldFile->F = curFILE;
oldFile->p = curPTR;
memcpy(oldFile, &curFile, sizeof (IFile));
(void) Lst_AtFront (includes, (void *)oldFile);
curFILE = NULL;
curPTR = (PTR *) emalloc (sizeof (PTR));
curPTR->str = curPTR->ptr = str;
lineno = savedlineno;
fname = estrdup(fname);
curFile.F = NULL;
curFile.p = (PTR *) emalloc (sizeof (PTR));
curFile.p->str = curFile.p->ptr = str;
curFile.lineno = lineno;
curFile.fname = estrdup(curFile.fname);
}
@ -1811,8 +1801,8 @@ Parse_FromString(char *str)
* None
*
* Side Effects:
* A structure is added to the includes Lst and readProc, lineno,
* fname and curFILE are altered for the new file
* A structure is added to the includes Lst and readProc, curFile.lineno,
* curFile.fname and curFile.F are altered for the new file
*---------------------------------------------------------------------
*/
static void
@ -1881,11 +1871,7 @@ ParseTraditionalInclude (char *file)
* a very nice stack to track how we got here...
*/
oldFile = (IFile *) emalloc (sizeof (IFile));
oldFile->fname = fname;
oldFile->F = curFILE;
oldFile->p = curPTR;
oldFile->lineno = lineno;
memcpy(oldFile, &curFile, sizeof (IFile));
(void) Lst_AtFront (includes, (void *)oldFile);
@ -1895,12 +1881,12 @@ ParseTraditionalInclude (char *file)
* name of the include file so error messages refer to the right
* place. Naturally enough, we start reading at line number 0.
*/
fname = fullname;
lineno = 0;
curFile.fname = fullname;
curFile.lineno = 0;
curFILE = fopen (fullname, "r");
curPTR = NULL;
if (curFILE == (FILE * ) NULL) {
curFile.F = fopen (fullname, "r");
curFile.p = NULL;
if (curFile.F == (FILE * ) NULL) {
Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
/*
* Pop to previous file
@ -1921,8 +1907,9 @@ ParseTraditionalInclude (char *file)
* CONTINUE if there's more to do. DONE if not.
*
* Side Effects:
* The old curFILE, is closed. The includes list is shortened.
* lineno, curFILE, and fname are changed if CONTINUE is returned.
* 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
@ -1935,17 +1922,14 @@ ParseEOF (int opened)
}
ifile = (IFile *) Lst_DeQueue (includes);
free (fname);
fname = ifile->fname;
lineno = ifile->lineno;
if (opened && curFILE)
(void) fclose (curFILE);
if (curPTR) {
free(curPTR->str);
free(curPTR);
free (curFile.fname);
if (opened && curFile.F)
(void) fclose (curFile.F);
if (curFile.p) {
free(curFile.p->str);
free(curFile.p);
}
curFILE = ifile->F;
curPTR = ifile->p;
memcpy(&curFile, ifile, sizeof (IFile));
free (ifile);
return (CONTINUE);
}
@ -1964,11 +1948,11 @@ ParseEOF (int opened)
static int
ParseReadc(void)
{
if (curFILE)
return fgetc(curFILE);
if (curFile.F)
return fgetc(curFile.F);
if (curPTR && *curPTR->ptr)
return *curPTR->ptr++;
if (curFile.p && *curFile.p->ptr)
return *curFile.p->ptr++;
return EOF;
}
@ -1987,12 +1971,12 @@ ParseReadc(void)
static void
ParseUnreadc(int c)
{
if (curFILE) {
ungetc(c, curFILE);
if (curFile.F) {
ungetc(c, curFile.F);
return;
}
if (curPTR) {
*--(curPTR->ptr) = c;
if (curFile.p) {
*--(curFile.p->ptr) = c;
return;
}
}
@ -2003,7 +1987,7 @@ ParseUnreadc(int c)
* ignore such lines.
*/
static char *
ParseSkipLine(int skip)
ParseSkipLine(int skip, int keep_newline)
{
char *line;
int c, lastc, lineLength = 0;
@ -2018,8 +2002,11 @@ ParseSkipLine(int skip)
while (((c = ParseReadc()) != '\n' || lastc == '\\')
&& c != EOF) {
if (c == '\n') {
Buf_ReplaceLastByte(buf, (Byte)' ');
lineno++;
if (keep_newline)
Buf_AddByte(buf, (Byte)c);
else
Buf_ReplaceLastByte(buf, (Byte)' ');
curFile.lineno++;
while ((c = ParseReadc()) == ' ' || c == '\t')
continue;
@ -2038,7 +2025,7 @@ ParseSkipLine(int skip)
return((char *)NULL);
}
lineno++;
curFile.lineno++;
Buf_AddByte(buf, (Byte)'\0');
line = (char *)Buf_GetAll(buf, &lineLength);
} while (skip == 1 && line[0] != '.');
@ -2079,6 +2066,7 @@ ParseReadLine (void)
char *line; /* Result */
char *ep; /* to strip trailing blanks */
int lineLength; /* Length of result */
int lineno; /* Saved line # */
semiNL = FALSE;
ignDepOp = FALSE;
@ -2098,7 +2086,7 @@ ParseReadLine (void)
ignComment = ignDepOp = TRUE;
break;
} else if (c == '\n') {
lineno++;
curFile.lineno++;
} else if (c == '#') {
ParseUnreadc(c);
break;
@ -2128,7 +2116,7 @@ ParseReadLine (void)
* semi-colon and semiNL is TRUE, it will be recognized as a
* newline in the code below this...
*/
lineno++;
curFile.lineno++;
lastc = ' ';
while ((c = ParseReadc ()) == ' ' || c == '\t') {
continue;
@ -2229,7 +2217,7 @@ ParseReadLine (void)
}
line_read:
lineno++;
curFile.lineno++;
if (lastc != '\0') {
Buf_AddByte (buf, (Byte)lastc);
@ -2265,7 +2253,7 @@ ParseReadLine (void)
*/
do {
free (line);
line = ParseSkipLine(1);
line = ParseSkipLine(1, 0);
} while (line && Cond_Eval(line) != COND_PARSE);
if (line == NULL)
break;
@ -2278,12 +2266,12 @@ ParseReadLine (void)
if (For_Eval(line)) {
int ok;
free(line);
savedlineno = lineno;
lineno = curFile.lineno;
do {
/*
* Skip after the matching end
*/
line = ParseSkipLine(0);
line = ParseSkipLine(0, 1);
if (line == NULL) {
Parse_Error (PARSE_FATAL,
"Unexpected end of file in for loop.\n");
@ -2294,7 +2282,7 @@ ParseReadLine (void)
}
while (ok);
if (line != NULL)
For_Run();
For_Run(lineno);
line = ParseReadLine();
}
break;
@ -2359,9 +2347,9 @@ Parse_File(char *name, FILE *stream)
*line; /* the line we're working on */
inLine = FALSE;
fname = name;
curFILE = stream;
lineno = 0;
curFile.fname = name;
curFile.F = stream;
curFile.lineno = 0;
fatals = 0;
do {