bin/61257: improvement to make(1)'s diagnostic of mismatched
.if-.endif
Mikhail Teterin
mi at aldan.algebra.com
Mon Jan 12 07:30:29 PST 2004
>Number: 61257
>Category: bin
>Synopsis: improvement to make(1)'s diagnostic of mismatched .if-.endif
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Jan 12 07:30:11 PST 2004
>Closed-Date:
>Last-Modified:
>Originator: Mikhail Teterin
>Release: FreeBSD 5.2-CURRENT i386
>Organization:
Virtual Estates, Inc.
>Environment:
System: FreeBSD aldan.algebra.com 5.2-CURRENT FreeBSD 5.2-CURRENT #6: Tue Jan 6 09:55:21 EST 2004 root at aldan.algebra.com:/ccd/obj/ccd/src/sys/DEBUG i386
>Description:
When make finds a mismatch in a Makefile's .if-.else-.endif
tree, the reported error does not help resolve the problem
much, because it only contains the last line.
The included patch keeps the line numbers of the .if-s on
the same stack, where the current version keeps just the
results of the evaluations of conditionals. In case of a
mismatch it makes a neat, indented printout of the stack.
Interestingly, this does not use any more of the make's
memory. The stack used to consist of booleans (which are,
in fact, ints). It now consists of ints using only one
bit (positive/negative) to represent the boolean (as the
maker intended it to be), leaving the other 31 bits to
hold the line number.
The only potential problem I can see with the patch, is that
it exposes the lineno, which was previously static to parse.c,
to the rest of the program. I don't think, this is a big
deal, however.
>How-To-Repeat:
Consider the following buggy makefile:
.if 1
A=a
.else
B=b
The current make will report only:
"Makefile", line 4: 1 open conditional
My version will say:
"Makefile", line 4: 1 open conditional:
"Makefile", line 4: at line 1 (evaluated to true)
The benefits are more apparent with hairier makefiles, such
the bsd.* and those of some ports.
>Fix:
The patch below tested with many buildworlds on several of
my machines:
Index: cond.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/cond.c,v
retrieving revision 1.27
diff -U2 -r1.27 cond.c
--- cond.c 7 Sep 2003 02:16:10 -0000 1.27
+++ cond.c 12 Jan 2004 15:05:21 -0000
@@ -133,5 +133,5 @@
#define MAXIF 30 /* greatest depth of #if'ing */
-static Boolean condStack[MAXIF]; /* Stack of conditionals's values */
+static int condStack[MAXIF]; /* Stack of conditionals's values */
static int condTop = MAXIF; /* Top-most conditional */
static int skipIfLevel=0; /* Depth of skipped conditionals */
@@ -1046,7 +1046,8 @@
struct If *ifp;
Boolean isElse;
- Boolean value = FALSE;
+ int value;
int level; /* Level at which to report errors. */
+ value = -lineno;
level = PARSE_FATAL;
@@ -1109,5 +1110,5 @@
return (COND_INVALID);
} else if (skipIfLevel == 0) {
- value = !condStack[condTop];
+ value = -condStack[condTop];
} else {
return (COND_SKIP);
@@ -1160,5 +1161,5 @@
case True:
if (CondToken(TRUE) == EndOfFile) {
- value = TRUE;
+ value = lineno;
break;
}
@@ -1167,5 +1168,5 @@
case False:
if (CondToken(TRUE) == EndOfFile) {
- value = FALSE;
+ value = -lineno;
break;
}
@@ -1182,5 +1183,5 @@
if (!isElse) {
condTop -= 1;
- } else if ((skipIfLevel != 0) || condStack[condTop]) {
+ } else if ((skipIfLevel != 0) || condStack[condTop] > 0) {
/*
* If this is an else-type conditional, it should only take effect
@@ -1203,6 +1204,6 @@
} else {
condStack[condTop] = value;
- skipLine = !value;
- return (value ? COND_PARSE : COND_SKIP);
+ skipLine = value < 0;
+ return (value > 0 ? COND_PARSE : COND_SKIP);
}
}
@@ -1225,6 +1226,17 @@
{
if (condTop != MAXIF) {
- Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop,
+ int level;
+ char spaces[MAXIF];
+ Parse_Error(PARSE_FATAL, "%d open conditional%s:", MAXIF-condTop,
MAXIF-condTop == 1 ? "" : "s");
+ memset(spaces, ' ', sizeof(spaces));
+ for (level = condTop; level < MAXIF; level++) {
+ if (condStack[level] < 0)
+ Parse_Error(PARSE_FATAL, "\t%.*sat line %d "
+ "(evaluated to false)", MAXIF - level, spaces, -condStack[level]);
+ else
+ Parse_Error(PARSE_FATAL, "\t%.*sat line %d "
+ "(evaluated to true)", MAXIF - level, spaces, condStack[level]);
+ }
}
condTop = MAXIF;
Index: make.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/make.h,v
retrieving revision 1.23
diff -U2 -r1.23 make.h
--- make.h 10 Oct 2002 19:27:48 -0000 1.23
+++ make.h 12 Jan 2004 15:05:24 -0000
@@ -274,4 +274,5 @@
extern Lst dirSearchPath; /* The list of directories to search when
* looking for targets */
+extern int lineno; /* line number in current file */
extern Lst parseIncPath; /* The list of directories to search when
* looking for includes */
Index: parse.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/make/parse.c,v
retrieving revision 1.50
diff -U2 -r1.50 parse.c
--- parse.c 28 Nov 2002 12:47:56 -0000 1.50
+++ parse.c 12 Jan 2004 15:05:37 -0000
@@ -112,5 +112,5 @@
static char *fname; /* name of current file (for errors) */
-static int lineno; /* line number in current file */
+int lineno; /* line number in current file */
static FILE *curFILE = NULL; /* current makefile */
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list