Improve make's diagnostic of mistmatched .if-.endif. This patch is

slightly different from the patch in the PR. The problem is, that
make handles .if clauses inside false .if clauses simply by
counting them - it doesn't put them onto the conditional stack, nor even
parses them so we need an extra line number stack for these ifs.

PR:		bin/61257
Submitted by:	Mikhail Teterin <mi@aldan.algebra.com>
This commit is contained in:
harti 2004-07-20 07:42:06 +00:00
parent 9d4a4d9654
commit 0b6943c93f
3 changed files with 38 additions and 17 deletions

View File

@ -133,8 +133,10 @@ static Token condPushBack=None; /* Single push-back token used in
#define MAXIF 30 /* greatest depth of #if'ing */ #define MAXIF 30 /* greatest depth of #if'ing */
static Boolean condStack[MAXIF]; /* Stack of conditionals's values */ static Boolean condStack[MAXIF]; /* Stack of conditionals's values */
static int condLineno[MAXIF]; /* Line numbers of the opening .if */
static int condTop = MAXIF; /* Top-most conditional */ static int condTop = MAXIF; /* Top-most conditional */
static int skipIfLevel=0; /* Depth of skipped conditionals */ static int skipIfLevel=0; /* Depth of skipped conditionals */
static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */
static Boolean skipLine = FALSE; /* Whether the parse module is skipping static Boolean skipLine = FALSE; /* Whether the parse module is skipping
* lines */ * lines */
@ -1047,8 +1049,10 @@ Cond_Eval (char *line)
Boolean isElse; Boolean isElse;
Boolean value = FALSE; Boolean value = FALSE;
int level; /* Level at which to report errors. */ int level; /* Level at which to report errors. */
int lineno;
level = PARSE_FATAL; level = PARSE_FATAL;
lineno = curFile.lineno;
for (line++; *line == ' ' || *line == '\t'; line++) { for (line++; *line == ' ' || *line == '\t'; line++) {
continue; continue;
@ -1109,6 +1113,7 @@ Cond_Eval (char *line)
return (COND_INVALID); return (COND_INVALID);
} else if (skipIfLevel == 0) { } else if (skipIfLevel == 0) {
value = !condStack[condTop]; value = !condStack[condTop];
lineno = condLineno[condTop];
} else { } else {
return (COND_SKIP); return (COND_SKIP);
} }
@ -1130,6 +1135,7 @@ Cond_Eval (char *line)
* undefined, for which there's an enclosing ifdef that * undefined, for which there's an enclosing ifdef that
* we're skipping... * we're skipping...
*/ */
skipIfLineno[skipIfLevel - 1] = lineno;
return(COND_SKIP); return(COND_SKIP);
} }
} else if (skipLine) { } else if (skipLine) {
@ -1137,6 +1143,7 @@ Cond_Eval (char *line)
* Don't even try to evaluate a conditional that's not an else if * Don't even try to evaluate a conditional that's not an else if
* we're skipping things... * we're skipping things...
*/ */
skipIfLineno[skipIfLevel] = lineno;
skipIfLevel += 1; skipIfLevel += 1;
return(COND_SKIP); return(COND_SKIP);
} }
@ -1202,6 +1209,7 @@ Cond_Eval (char *line)
return (COND_INVALID); return (COND_INVALID);
} else { } else {
condStack[condTop] = value; condStack[condTop] = value;
condLineno[condTop] = lineno;
skipLine = !value; skipLine = !value;
return (value ? COND_PARSE : COND_SKIP); return (value ? COND_PARSE : COND_SKIP);
} }
@ -1223,9 +1231,20 @@ Cond_Eval (char *line)
void void
Cond_End(void) Cond_End(void)
{ {
int level;
if (condTop != MAXIF) { if (condTop != MAXIF) {
Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop, Parse_Error(PARSE_FATAL, "%d open conditional%s:",
MAXIF-condTop == 1 ? "" : "s"); MAXIF - condTop + skipIfLevel,
MAXIF - condTop + skipIfLevel== 1 ? "" : "s");
for (level = skipIfLevel; level > 0; level--)
Parse_Error(PARSE_FATAL, "\t%*sat line %d (skipped)",
MAXIF - condTop + level + 1, "", skipIfLineno[level - 1]);
for (level = condTop; level < MAXIF; level++)
Parse_Error(PARSE_FATAL, "\t%*sat line %d "
"(evaluated to %s)", MAXIF - level + skipIfLevel, "",
condLineno[level], condStack[level] ? "true" : "false");
} }
condTop = MAXIF; condTop = MAXIF;
} }

View File

@ -141,6 +141,21 @@ typedef struct GNode {
* but the Suff module) */ * but the Suff module) */
} GNode; } GNode;
/*
* 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;
/* /*
* The OP_ constants are used when parsing a dependency line as a way of * The OP_ constants are used when parsing a dependency line as a way of
* communicating to other parts of the program the way in which a target * communicating to other parts of the program the way in which a target
@ -273,6 +288,7 @@ extern Lst create; /* The list of target names specified on the
* make(...) statements */ * make(...) statements */
extern Lst dirSearchPath; /* The list of directories to search when extern Lst dirSearchPath; /* The list of directories to search when
* looking for targets */ * looking for targets */
extern IFile curFile; /* current makefile */
extern Lst parseIncPath; /* The list of directories to search when extern Lst parseIncPath; /* The list of directories to search when
* looking for includes */ * looking for includes */

View File

@ -105,27 +105,13 @@ static Lst targets; /* targets we're working on */
static Lst targCmds; /* command lines for targets */ static Lst targCmds; /* command lines for targets */
static Boolean inLine; /* true if currently in a dependency static Boolean inLine; /* true if currently in a dependency
* line or its commands */ * line or its commands */
typedef struct {
char *str;
char *ptr;
} PTR;
static int fatals = 0; static int fatals = 0;
static GNode *mainNode; /* The main target to create. This is the static GNode *mainNode; /* The main target to create. This is the
* first target on the first dependency * first target on the first dependency
* line in the first makefile */ * line in the first makefile */
/*
* Definitions for handling #include specifications
*/
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;
static IFile curFile; IFile curFile; /* current makefile */
static Lst includes; /* stack of IFiles generated by static Lst includes; /* stack of IFiles generated by
* #includes */ * #includes */