usr.bin/make 2nd try: Improve diagnostics for .if-.else.endif

Max Okumoto okumoto at ucsd.edu
Wed Dec 1 05:24:24 PST 2004


Lost from last mega patch.

				Max
---------------------
PatchSet 351
Date: 2004/07/20 08:42:06
Author: harti
Log:
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 at xxxxxxxxxxxxxxxxx>

Members: 
	cond.c:1.27->1.28 
	make.h:1.23->1.24 
	parse.c:1.55->1.56 

Index: cond.c
===================================================================
RCS file: /usr/home/okumoto/Work/make/fbsd-cvs/src/usr.bin/make/cond.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- cond.c	7 Sep 2003 02:16:10 -0000	1.27
+++ cond.c	20 Jul 2004 07:42:06 -0000	1.28
@@ -133,8 +133,10 @@
 #define	MAXIF		30	  /* greatest depth of #if'ing */
 
 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  	  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
 					 * lines */
 
@@ -1047,8 +1049,10 @@
     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;
@@ -1109,6 +1113,7 @@
 		return (COND_INVALID);
 	    } else if (skipIfLevel == 0) {
 		value = !condStack[condTop];
+		lineno = condLineno[condTop];
 	    } else {
 		return (COND_SKIP);
 	    }
@@ -1130,6 +1135,7 @@
 		 * undefined, for which there's an enclosing ifdef that
 		 * we're skipping...
 		 */
+	        skipIfLineno[skipIfLevel - 1] = lineno;
 		return(COND_SKIP);
 	    }
 	} else if (skipLine) {
@@ -1137,6 +1143,7 @@
 	     * Don't even try to evaluate a conditional that's not an else if
 	     * we're skipping things...
 	     */
+	    skipIfLineno[skipIfLevel] = lineno;
 	    skipIfLevel += 1;
 	    return(COND_SKIP);
 	}
@@ -1202,6 +1209,7 @@
 	return (COND_INVALID);
     } else {
 	condStack[condTop] = value;
+	condLineno[condTop] = lineno;
 	skipLine = !value;
 	return (value ? COND_PARSE : COND_SKIP);
     }
@@ -1223,9 +1231,20 @@
 void
 Cond_End(void)
 {
+    int level;
+
     if (condTop != MAXIF) {
-	Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop,
-		    MAXIF-condTop == 1 ? "" : "s");
+	Parse_Error(PARSE_FATAL, "%d open conditional%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;
 }
Index: make.h
===================================================================
RCS file: /usr/home/okumoto/Work/make/fbsd-cvs/src/usr.bin/make/make.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- make.h	10 Oct 2002 19:27:48 -0000	1.23
+++ make.h	20 Jul 2004 07:42:06 -0000	1.24
@@ -141,6 +141,21 @@
 				 * but the Suff module) */
 } 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
  * communicating to other parts of the program the way in which a target
@@ -273,6 +288,7 @@
 				 * make(...) statements */
 extern Lst     	dirSearchPath; 	/* The list of directories to search when
 				 * looking for targets */
+extern IFile	curFile;	/* current makefile */
 extern Lst	parseIncPath;	/* The list of directories to search when
 				 * looking for includes */
 
Index: parse.c
===================================================================
RCS file: /usr/home/okumoto/Work/make/fbsd-cvs/src/usr.bin/make/parse.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- parse.c	2 Jul 2004 12:30:28 -0000	1.55
+++ parse.c	20 Jul 2004 07:42:06 -0000	1.56
@@ -105,27 +105,13 @@
 static Lst     	    targCmds;	/* command lines for targets */
 static Boolean	    inLine;	/* true if currently in a dependency
 				 * line or its commands */
-typedef struct {
-    char *str;
-    char *ptr;
-} PTR;
-
 static int	    fatals = 0;
 
 static GNode	    *mainNode;	/* The main target to create. This is the
 				 * first target on the first dependency
 				 * 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
 				 * #includes */
---------------------
PatchSet 352
Date: 2004/07/22 12:12:01
Author: harti
Log:
Fix handling of comments on .elif lines. The patch given in a followup
to the PR failed, because the line skipping function is actually called
from two places in the code to do quite different things (this should
be two functions probably): in a false .if to skip to the next line
beginning with a dot and to collect .for loops. In the seconds case we
should not skip comments, because they are actually harder to handle than
we need for the .if case and should defer this to the main code.

PR:		bin/25627
Submitted by:	Seth Kingsley (original patch)

Members: 
	parse.c:1.56->1.57 

Index: parse.c
===================================================================
RCS file: /usr/home/okumoto/Work/make/fbsd-cvs/src/usr.bin/make/parse.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -r1.56 -r1.57
--- parse.c	20 Jul 2004 07:42:06 -0000	1.56
+++ parse.c	22 Jul 2004 11:12:01 -0000	1.57
@@ -2021,6 +2021,13 @@
 
         while (((c = ParseReadc()) != '\n' || lastc == '\\')
                && c != EOF) {
+            if (skip && c == '#' && lastc != '\\') {
+		/* let a comment be terminated even by an escaped \n.
+		 * This is consistent to comment handling in ParseReadLine */
+                while ((c = ParseReadc()) != '\n' && c != EOF)
+		    ;
+		break;
+	    }
             if (c == '\n') {
                 if (keep_newline)
                     Buf_AddByte(buf, (Byte)c);




More information about the Submit mailing list