Module Name:    src
Committed By:   rillig
Date:           Mon Sep 14 19:59:47 UTC 2020

Modified Files:
        src/usr.bin/make: parse.c
        src/usr.bin/make/unit-tests: include-main.exp include-sub.mk

Log Message:
make(1): describe how Parse_Error might print stack traces

In deeply nested include chains and .for loops this may be a useful
feature.  It's a little tricky to generate an intuitive stack trace,
though not impossible.  This explanation also serves as a detailed
documentation about how the .include and .for directives are
implemented.


To generate a diff of this commit:
cvs rdiff -u -r1.318 -r1.319 src/usr.bin/make/parse.c
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/include-main.exp
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/include-sub.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.318 src/usr.bin/make/parse.c:1.319
--- src/usr.bin/make/parse.c:1.318	Mon Sep 14 18:21:26 2020
+++ src/usr.bin/make/parse.c	Mon Sep 14 19:59:47 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.318 2020/09/14 18:21:26 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.319 2020/09/14 19:59:47 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.318 2020/09/14 18:21:26 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.319 2020/09/14 19:59:47 rillig Exp $");
 
 /* types and constants */
 
@@ -245,9 +245,46 @@ static int fatals = 0;
 /* current file being read */
 static IFile *curFile;
 
-/* The current file from the command line (at the bottom of the stack) and
- * further up all the files that are currently being read due to nested
- * .include or .for directives. */
+/* The include chain of makefiles that leads to curFile.  At the bottom of
+ * the stack is the top-level makefile from the command line, and on top of
+ * this file, there are the included files or .for loops, up to but excluding
+ * curFile.
+ *
+ * This data could be used to print stack traces on parse errors.  As of
+ * 2020-09-14, this is not done though.  It seems quite simple to print the
+ * tuples (fname:lineno:fromForLoop), from top to bottom.  This simple idea is
+ * made complicated by the fact that the .for loops also use this stack for
+ * storing information.
+ *
+ * The lineno fields of the IFiles with fromForLoop == TRUE look confusing,
+ * which is demonstrated by the test 'include-main.mk'.  They seem sorted
+ * backwards since they tell the number of completely parsed lines, which for
+ * a .for loop is right after the terminating .endfor.  To compensate for this
+ * confusion, there is another field first_lineno pointing at the start of the
+ * .for loop, 1-based for human consumption.
+ *
+ * To make the stack trace intuitive, the entry below the first .for loop must
+ * be ignored completely since neither its lineno nor its first_lineno is
+ * useful.  Instead, the topmost .for loop needs to be printed twice, once
+ * with its first_lineno and once with its lineno.
+ *
+ * As of 2020-09-15, using the above rules, the stack trace for the .info line
+ * in include-subsub.mk would be:
+ *
+ *	curFile:	include-subsub.mk:4
+ *			(lineno, from an .include)
+ *	includes[4]:	include-sub.mk:32
+ *			(lineno, from a .for loop below an .include)
+ *	includes[4]:	include-sub.mk:31
+ *			(first_lineno, from a .for loop, lineno == 32)
+ *	includes[3]:	include-sub.mk:30
+ *			(first_lineno, from a .for loop, lineno == 33)
+ *	includes[2]:	include-sub.mk:29
+ *			(first_lineno, from a .for loop, lineno == 34)
+ *	includes[1]:	include-sub.mk:35
+ *			(not printed since it is below a .for loop)
+ *	includes[0]:	include-main.mk:27
+ */
 static Stack /* of *IFile */ includes;
 
 /* include paths (lists of directories) */

Index: src/usr.bin/make/unit-tests/include-main.exp
diff -u src/usr.bin/make/unit-tests/include-main.exp:1.4 src/usr.bin/make/unit-tests/include-main.exp:1.5
--- src/usr.bin/make/unit-tests/include-main.exp:1.4	Sat Sep  5 18:18:05 2020
+++ src/usr.bin/make/unit-tests/include-main.exp	Mon Sep 14 19:59:47 2020
@@ -3,8 +3,8 @@ make: "include-main.mk" line 21: main-be
 make: "include-sub.mk" line 4: sub-before-ok
 make: "include-sub.mk" line 14: sub-before-for-ok
 make: "include-subsub.mk" line 4: subsub-ok
-make: "include-sub.mk" line 23: sub-after-ok
-make: "include-sub.mk" line 30: sub-after-for-ok
+make: "include-sub.mk" line 38: sub-after-ok
+make: "include-sub.mk" line 45: sub-after-for-ok
 make: "include-main.mk" line 30: main-after-ok
 make: "include-main.mk" line 37: main-after-for-ok
 exit status 0

Index: src/usr.bin/make/unit-tests/include-sub.mk
diff -u src/usr.bin/make/unit-tests/include-sub.mk:1.3 src/usr.bin/make/unit-tests/include-sub.mk:1.4
--- src/usr.bin/make/unit-tests/include-sub.mk:1.3	Sat Sep  5 18:13:47 2020
+++ src/usr.bin/make/unit-tests/include-sub.mk	Mon Sep 14 19:59:47 2020
@@ -1,4 +1,4 @@
-# $NetBSD: include-sub.mk,v 1.3 2020/09/05 18:13:47 rillig Exp $
+# $NetBSD: include-sub.mk,v 1.4 2020/09/14 19:59:47 rillig Exp $
 
 .if ${.INCLUDEDFROMFILE} == "include-main.mk"
 .  info sub-before-ok
@@ -17,7 +17,22 @@
 .  endif
 .endfor
 
+# To see the variable 'includes' in action:
+#
+# Breakpoints:
+#	Parse_File		at "Stack_Push(&includes, curFile)"
+#	ParseMessage		at entry
+# Watches:
+#	((const IFile *[10])(*includes.items))
+#	*curFile
+
+.for i in deeply
+.  for i in nested
+.    for i in include
 .include "include-subsub.mk"
+.    endfor
+.  endfor
+.endfor
 
 .if ${.INCLUDEDFROMFILE} == "include-main.mk"
 .  info sub-after-ok

Reply via email to