Module Name:    src
Committed By:   martin
Date:           Mon Mar  9 15:22:21 UTC 2020

Modified Files:
        src/usr.bin/config [netbsd-9]: TODO defs.h files.c gram.y main.c scan.l
            sem.c util.c

Log Message:
Pull up the following, requested by christos in ticket #776:

        usr.bin/config/TODO                             up to 1.32
        usr.bin/config/defs.h                           up to 1.105
        usr.bin/config/files.c                          up to 1.37
        usr.bin/config/gram.y                           up to 1.55
        usr.bin/config/main.c                           up to 1.99
        usr.bin/config/scan.l                           up to 1.30
        usr.bin/config/sem.c                            up to 1.84
        usr.bin/config/util.c                           up to 1.21

config(1): fix issue with incorrect handling of elifdef statements.


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.31.18.1 src/usr.bin/config/TODO
cvs rdiff -u -r1.104 -r1.104.2.1 src/usr.bin/config/defs.h
cvs rdiff -u -r1.36 -r1.36.16.1 src/usr.bin/config/files.c
cvs rdiff -u -r1.54 -r1.54.16.1 src/usr.bin/config/gram.y
cvs rdiff -u -r1.98 -r1.98.2.1 src/usr.bin/config/main.c
cvs rdiff -u -r1.26 -r1.26.16.1 src/usr.bin/config/scan.l
cvs rdiff -u -r1.83 -r1.83.4.1 src/usr.bin/config/sem.c
cvs rdiff -u -r1.20 -r1.20.18.1 src/usr.bin/config/util.c

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/config/TODO
diff -u src/usr.bin/config/TODO:1.31 src/usr.bin/config/TODO:1.31.18.1
--- src/usr.bin/config/TODO:1.31	Sun Nov 22 01:20:36 2015
+++ src/usr.bin/config/TODO	Mon Mar  9 15:22:21 2020
@@ -259,7 +259,7 @@ o Control ELF sections using linker scri
 		     *.ko --->      *.ro	Modular MI linkage
 		     *.ro --->      *.kmod	Modular MD linkage
 
-  Genric MI linkage is for processing MI linkage that can be applied generally.
+  Generic MI linkage is for processing MI linkage that can be applied generally.
   Data section alignment (.data.read_mostly and .data.cacheline_aligned) is
   processed here.
 

Index: src/usr.bin/config/defs.h
diff -u src/usr.bin/config/defs.h:1.104 src/usr.bin/config/defs.h:1.104.2.1
--- src/usr.bin/config/defs.h:1.104	Mon Aug 27 16:04:45 2018
+++ src/usr.bin/config/defs.h	Mon Mar  9 15:22:21 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: defs.h,v 1.104 2018/08/27 16:04:45 riastradh Exp $	*/
+/*	$NetBSD: defs.h,v 1.104.2.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -110,6 +110,10 @@ extern const char *progname;
 #define CONFIG_VERSION		20180827
 #define CONFIG_MINVERSION	0
 
+struct where {
+	const char *w_srcfile;		/* file name where we are defined */
+	u_short	w_srcline;		/* line number where we are defined */
+};
 /*
  * Name/value lists.  Values can be strings or pointers and/or can carry
  * integers.  The names can be NULL, resulting in simple value lists.
@@ -123,6 +127,7 @@ struct nvlist {
 	int		nv_ifunit;		/* XXX XXX XXX */
 	int		nv_flags;
 #define	NV_DEPENDED	1
+	struct where	nv_where;
 };
 
 /*
@@ -131,10 +136,10 @@ struct nvlist {
 struct config {
 	TAILQ_ENTRY(config) cf_next;
 	const char *cf_name;		/* "netbsd" */
-	int	cf_lineno;		/* source line */
 	const char *cf_fstype;		/* file system type */
 	struct	nvlist *cf_root;	/* "root on ra0a" */
 	struct	nvlist *cf_dump;	/* "dumps on ra0b" */
+	struct where	cf_where;
 };
 
 /*
@@ -147,6 +152,7 @@ struct defoptlist {
 	const char *dl_lintvalue;
 	int dl_obsolete;
 	struct nvlist *dl_depends;
+	struct where	dl_where;
 };
 
 struct files;
@@ -199,6 +205,7 @@ struct attr {
 
 	/* "device class" */
 	const char *a_devclass;		/* device class described */
+	struct where a_where;
 };
 
 /*
@@ -277,8 +284,7 @@ struct devbase {
 	struct	deva *d_ahead;		/* first attachment, if any */
 	struct	deva **d_app;		/* used for tacking on attachments */
 	struct	attr *d_classattr;	/* device class attribute (if any) */
-	const char *d_srcfile;		/* file name where we are defined */
-	u_short	d_srcline;		/* line number where we are defined */
+	struct	where d_where;
 };
 
 struct deva {
@@ -291,8 +297,7 @@ struct deva {
 	struct	attrlist *d_attrs;	/* attributes, if any */
 	struct	devi *d_ihead;		/* first instance, if any */
 	struct	devi **d_ipp;		/* used for tacking on more instances */
-	const char *d_srcfile;		/* file name where we are defined */
-	u_short	d_srcline;		/* line number where we are defined */
+	struct	where d_where;
 };
 
 /*
@@ -319,8 +324,6 @@ struct devi {
 	struct	deva *i_atdeva;
 	const char **i_locs;	/* locators (as given by pspec's iattr) */
 	int	i_cfflags;	/* flags from config line */
-	int	i_lineno;	/* line # in config, for later errors */
-	const char *i_srcfile;	/* file it appears in */
 	int	i_level;	/* position between negated instances */
 	int	i_active;
 #define	DEVI_ORPHAN	0	/* instance has no active parent */
@@ -333,7 +336,7 @@ struct devi {
 	short	i_collapsed;	/* set => this alias no longer needed */
 	u_short	i_cfindex;	/* our index in cfdata */
 	int	i_locoff;	/* offset in locators.vec */
-
+	struct	where i_where;
 };
 /* special units */
 #define	STAR	(-1)		/* unit number for, e.g., "sd*" */
@@ -346,8 +349,7 @@ struct devi {
 struct files {
 	TAILQ_ENTRY(files) fi_next;
 	TAILQ_ENTRY(files) fi_snext;	/* per-suffix list */
-	const char *fi_srcfile;	/* the name of the "files" file that got us */
-	u_short	fi_srcline;	/* and the line number */
+	struct	where fi_where;
 	u_char fi_flags;	/* as below */
 	const char *fi_tail;	/* name, i.e., strrchr(fi_path, '/') + 1 */
 	const char *fi_base;	/* tail minus ".c" (or whatever) */
@@ -418,13 +420,12 @@ struct prefix {
  */
 struct devm {
 	TAILQ_ENTRY(devm) dm_next;
-	const char	*dm_srcfile;	/* the name of the "majors" file */
-	u_short		dm_srcline;	/* the line number */
 	const char	*dm_name;	/* [bc]devsw name */
 	devmajor_t	dm_cmajor;	/* character major */
 	devmajor_t	dm_bmajor;	/* block major */
 	struct condexpr	*dm_opts;	/* options */
 	struct nvlist	*dm_devnodes;	/* information on /dev nodes */
+	struct where dm_where;
 };
 
 /*
@@ -581,7 +582,7 @@ void	deloption(const char *, int);
 void	delfsoption(const char *, int);
 void	delmkoption(const char *, int);
 int	devbase_has_instances(struct devbase *, int);
-int	is_declared_option(const char *);
+struct where *find_declared_option(const char *);
 int	deva_has_instances(struct deva *, int);
 void	setupdirs(void);
 void	fixmaxusers(void);
@@ -594,7 +595,7 @@ const char *strtolower(const char *);
 #define OPT_DEFFLAG(n)	(dlhash_lookup(defflagtab, (n)) != NULL)
 #define OPT_DEFPARAM(n)	(dlhash_lookup(defparamtab, (n)) != NULL)
 #define OPT_OBSOLETE(n)	(dlhash_lookup(obsopttab, (n)) != NULL)
-#define DEFINED_OPTION(n) (is_declared_option((n)))
+#define DEFINED_OPTION(n) (find_declared_option((n)))
 
 /* main.c */
 void	logconfig_include(FILE *, const char *);

Index: src/usr.bin/config/files.c
diff -u src/usr.bin/config/files.c:1.36 src/usr.bin/config/files.c:1.36.16.1
--- src/usr.bin/config/files.c:1.36	Fri Sep  9 21:09:11 2016
+++ src/usr.bin/config/files.c	Mon Mar  9 15:22:21 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: files.c,v 1.36 2016/09/09 21:09:11 christos Exp $	*/
+/*	$NetBSD: files.c,v 1.36.16.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: files.c,v 1.36 2016/09/09 21:09:11 christos Exp $");
+__RCSID("$NetBSD: files.c,v 1.36.16.1 2020/03/09 15:22:21 martin Exp $");
 
 #include <sys/param.h>
 #include <assert.h>
@@ -158,19 +158,19 @@ addfile(const char *path, struct condexp
 		 * options for specific files.
 		 */
 		if (rule != NULL && optx == NULL && flags == 0 &&
-		    yyfile != fi->fi_srcfile) {
+		    yyfile != fi->fi_where.w_srcfile) {
 			fi->fi_mkrule = rule;
 			return;
 		}
 		cfgerror("duplicate file %s", path);
-		cfgxerror(fi->fi_srcfile, fi->fi_srcline,
+		cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
 		    "here is the original definition");
 		goto bad;
 	}
 	memcpy(base, tail, baselen);
 	base[baselen] = '\0';
-	fi->fi_srcfile = yyfile;
-	fi->fi_srcline = currentline();
+	fi->fi_where.w_srcfile = yyfile;
+	fi->fi_where.w_srcline = currentline();
 	fi->fi_flags = flags;
 	fi->fi_path = path;
 	fi->fi_tail = tail;
@@ -204,7 +204,7 @@ addfile(const char *path, struct condexp
 		TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
 		break;
 	default:
-		cfgxerror(fi->fi_srcfile, fi->fi_srcline,
+		cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
 		    "unknown suffix");
 		break;
 	}
@@ -262,7 +262,7 @@ checkaux(const char *name, void *context
 	struct files *fi = context;
 
 	if (ht_lookup(devbasetab, name) == NULL) {
-		cfgxerror(fi->fi_srcfile, fi->fi_srcline,
+		cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
 		    "`%s' is not a countable device",
 		    name);
 		/* keep fixfiles() from complaining again */
@@ -356,10 +356,10 @@ fixfiles(void)
 				ofi->fi_flags &= (u_char)~FI_SEL;
 				ofi->fi_flags |= FI_HIDDEN;
 			} else {
-				cfgxerror(fi->fi_srcfile, fi->fi_srcline,
+				cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
 				    "object file collision on %s.o, from %s",
 				    fi->fi_base, fi->fi_path);
-				cfgxerror(ofi->fi_srcfile, ofi->fi_srcline,
+				cfgxerror(ofi->fi_where.w_srcfile, ofi->fi_where.w_srcline,
 				    "here is the previous file: %s",
 				    ofi->fi_path);
 				err = 1;
@@ -412,22 +412,25 @@ fixdevsw(void)
 		if (res != NULL) {
 			if (res->dm_cmajor != dm->dm_cmajor ||
 			    res->dm_bmajor != dm->dm_bmajor) {
-				cfgxerror(res->dm_srcfile, res->dm_srcline,
-					"device-major '%s' "
-					"block %d, char %d redefined"
-					" at %s:%d as block %d, char %d",
-					res->dm_name,
-					res->dm_bmajor, res->dm_cmajor,
-					dm->dm_srcfile, dm->dm_srcline,
-					dm->dm_bmajor, dm->dm_cmajor);
+				cfgxerror(res->dm_where.w_srcfile,
+				    res->dm_where.w_srcline,
+				    "device-major '%s' "
+				    "block %d, char %d redefined"
+				    " at %s:%d as block %d, char %d",
+				    res->dm_name,
+				    res->dm_bmajor, res->dm_cmajor,
+				    dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
+				    dm->dm_bmajor, dm->dm_cmajor);
 			} else {
-				cfgxerror(res->dm_srcfile, res->dm_srcline,
-					"device-major '%s' "
-					"(block %d, char %d) duplicated"
-					" at %s:%d",
-					dm->dm_name, dm->dm_bmajor,
-					dm->dm_cmajor,
-					dm->dm_srcfile, dm->dm_srcline);
+				cfgxerror(res->dm_where.w_srcfile,
+				    res->dm_where.w_srcline,
+				    "device-major '%s' "
+				    "(block %d, char %d) duplicated"
+				    " at %s:%d",
+				    dm->dm_name, dm->dm_bmajor,
+				    dm->dm_cmajor,
+				    dm->dm_where.w_srcfile,
+				    dm->dm_where.w_srcline);
 			}
 			error = 1;
 			goto out;
@@ -443,15 +446,16 @@ fixdevsw(void)
 
 		if (dm->dm_cmajor != NODEVMAJOR) {
 			if (ht_lookup(cdevmtab, intern(dm->dm_name)) != NULL) {
-				cfgxerror(dm->dm_srcfile, dm->dm_srcline,
-				       "device-major of character device '%s' "
-				       "is already defined", dm->dm_name);
+				cfgxerror(dm->dm_where.w_srcfile,
+				    dm->dm_where.w_srcline,
+				   "device-major of character device '%s' "
+				   "is already defined", dm->dm_name);
 				error = 1;
 				goto out;
 			}
 			(void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_cmajor);
 			if (ht_lookup(cdevmtab, intern(mstr)) != NULL) {
-				cfgxerror(dm->dm_srcfile, dm->dm_srcline,
+				cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
 				       "device-major of character major '%d' "
 				       "is already defined", dm->dm_cmajor);
 				error = 1;
@@ -465,7 +469,7 @@ fixdevsw(void)
 		}
 		if (dm->dm_bmajor != NODEVMAJOR) {
 			if (ht_lookup(bdevmtab, intern(dm->dm_name)) != NULL) {
-				cfgxerror(dm->dm_srcfile, dm->dm_srcline,
+				cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
 				       "device-major of block device '%s' "
 				       "is already defined", dm->dm_name);
 				error = 1;
@@ -473,7 +477,7 @@ fixdevsw(void)
 			}
 			(void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_bmajor);
 			if (ht_lookup(bdevmtab, intern(mstr)) != NULL) {
-				cfgxerror(dm->dm_srcfile, dm->dm_srcline,
+				cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
 				       "device-major of block major '%d' "
 				       "is already defined", dm->dm_bmajor);
 				error = 1;

Index: src/usr.bin/config/gram.y
diff -u src/usr.bin/config/gram.y:1.54 src/usr.bin/config/gram.y:1.54.16.1
--- src/usr.bin/config/gram.y:1.54	Sun Aug  7 10:37:24 2016
+++ src/usr.bin/config/gram.y	Mon Mar  9 15:22:21 2020
@@ -1,5 +1,5 @@
 %{
-/*	$NetBSD: gram.y,v 1.54 2016/08/07 10:37:24 christos Exp $	*/
+/*	$NetBSD: gram.y,v 1.54.16.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: gram.y,v 1.54 2016/08/07 10:37:24 christos Exp $");
+__RCSID("$NetBSD: gram.y,v 1.54.16.1 2020/03/09 15:22:21 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -898,7 +898,7 @@ no_option:
 conf:
 	WORD				{
 		conf.cf_name = $1;
-		conf.cf_lineno = currentline();
+		conf.cf_where.w_srcline = currentline();
 		conf.cf_fstype = NULL;
 		conf.cf_root = NULL;
 		conf.cf_dump = NULL;

Index: src/usr.bin/config/main.c
diff -u src/usr.bin/config/main.c:1.98 src/usr.bin/config/main.c:1.98.2.1
--- src/usr.bin/config/main.c:1.98	Mon Dec 24 02:07:44 2018
+++ src/usr.bin/config/main.c	Mon Mar  9 15:22:21 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.98 2018/12/24 02:07:44 christos Exp $	*/
+/*	$NetBSD: main.c,v 1.98.2.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: main.c,v 1.98 2018/12/24 02:07:44 christos Exp $");
+__RCSID("$NetBSD: main.c,v 1.98.2.1 2020/03/09 15:22:21 martin Exp $");
 
 #ifndef MAKE_BOOTSTRAP
 #include <sys/cdefs.h>
@@ -756,7 +756,7 @@ check_dependencies(const char *thing, st
 		} else if (OPT_OBSOLETE(dep->nv_name)) {
 			cfgerror("option `%s' dependency `%s' "
 			    "is obsolete", thing, dep->nv_name);
-		} else if (!is_declared_option(dep->nv_name)) {
+		} else if (!find_declared_option(dep->nv_name)) {
 			cfgerror("option `%s' dependency `%s' "
 			    "is an unknown option",
 			    thing, dep->nv_name);
@@ -786,14 +786,16 @@ void
 deffilesystem(struct nvlist *fses, struct nvlist *deps)
 {
 	struct nvlist *nv;
+	struct where *w;
 
 	/*
 	 * Mark these options as ones to skip when creating the Makefile.
 	 */
 	for (nv = fses; nv != NULL; nv = nv->nv_next) {
-		if (DEFINED_OPTION(nv->nv_name)) {
-			cfgerror("file system or option `%s' already defined",
-			    nv->nv_name);
+		if ((w = DEFINED_OPTION(nv->nv_name)) != NULL) {
+			cfgerror("file system or option `%s' already defined"
+			    " at %s:%hu", nv->nv_name, w->w_srcfile,
+			    w->w_srcline);
 			return;
 		}
 
@@ -878,8 +880,8 @@ find_declared_fs_option(const char *name
  * Like find_declared_option but doesn't return what it finds, so it
  * can search both the various kinds of options and also filesystems.
  */
-int
-is_declared_option(const char *name)
+struct where *
+find_declared_option(const char *name)
 {
 	struct defoptlist *option = NULL;
 	struct nvlist *fs;
@@ -887,13 +889,13 @@ is_declared_option(const char *name)
 	if ((option = dlhash_lookup(defopttab, name)) != NULL ||
 	    (option = dlhash_lookup(defparamtab, name)) != NULL ||
 	    (option = dlhash_lookup(defflagtab, name)) != NULL) {
-		return 1;
+		return &option->dl_where;
 	}
 	if ((fs = nvhash_lookup(deffstab, name)) != NULL) {
-		return 1;
+		return &fs->nv_where;
 	}
 
-	return 0;
+	return NULL;
 }
 
 /*
@@ -908,6 +910,7 @@ defopt(struct dlhash *ht, const char *fn
 {
 	struct defoptlist *dl, *nextdl, *olddl;
 	const char *name;
+	struct where *w;
 	char buf[500];
 
 	if (fname != NULL && badfilename(fname)) {
@@ -930,15 +933,17 @@ defopt(struct dlhash *ht, const char *fn
 		}
 
 		/* An option name can be declared at most once. */
-		if (DEFINED_OPTION(dl->dl_name)) {
-			cfgerror("file system or option `%s' already defined",
-			    dl->dl_name);
+		if ((w = DEFINED_OPTION(dl->dl_name)) != NULL) {
+			cfgerror("file system or option `%s' already defined"
+			    " at %s:%hu", dl->dl_name, w->w_srcfile,
+			    w->w_srcline);
 			return;
 		}
 
 		if (dlhash_insert(ht, dl->dl_name, dl)) {
-			cfgerror("file system or option `%s' already defined",
-			    dl->dl_name);
+			cfgerror("file system or option `%s' already defined"
+			    " at %s:%hu", dl->dl_name, dl->dl_where.w_srcfile,
+			    dl->dl_where.w_srcline);
 			return;
 		}
 
@@ -1379,8 +1384,8 @@ cfcrosscheck(struct config *cf, const ch
 				goto loop;
 		}
 		(void)fprintf(stderr,
-		    "%s:%d: %s says %s on %s, but there's no %s\n",
-		    conffile, cf->cf_lineno,
+		    "%s:%hu: %s says %s on %s, but there's no %s\n",
+		    conffile, cf->cf_where.w_srcline,
 		    cf->cf_name, what, nv->nv_str, nv->nv_str);
 		errs++;
  loop:

Index: src/usr.bin/config/scan.l
diff -u src/usr.bin/config/scan.l:1.26 src/usr.bin/config/scan.l:1.26.16.1
--- src/usr.bin/config/scan.l:1.26	Sun Aug  7 10:37:24 2016
+++ src/usr.bin/config/scan.l	Mon Mar  9 15:22:21 2020
@@ -1,5 +1,5 @@
 %{
-/*	$NetBSD: scan.l,v 1.26 2016/08/07 10:37:24 christos Exp $	*/
+/*	$NetBSD: scan.l,v 1.26.16.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: scan.l,v 1.26 2016/08/07 10:37:24 christos Exp $");
+__RCSID("$NetBSD: scan.l,v 1.26.16.1 2020/03/09 15:22:21 martin Exp $");
 
 #include <sys/param.h>
 #include <errno.h>
@@ -62,46 +62,53 @@ int	yyline;
 const char *yyfile;
 const char *lastfile;
 char curinclpath[PATH_MAX];
-int ifdefstate = -1;
-int st;
+uint64_t ifdefstate;
+int	 ifdefshift = -1;
+
+/*
+ * The state is represented by 3 bits.
+ */
+#define IDS_MATCH	1ll
+#define IDS_ELIF	2ll
+#define	IDS_ELSE	4ll
+
+#define IDS_BITS	7
+#define IDS_SHIFT	3
+
+#define IDS_ISMATCH(st) (((st) & IDS_MATCH) != 0)
 #define IDS_PARENT_DISABLED \
-    ((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1))
-#define IDS_MAX_DEPTH		362797056 /* 6^11 */
-/* States for ifdefstate:
-
-  0  -> matched ifdef
-  1  -> unmatched ifdef
-  2  -> matched elifdef
-  3  -> unmatched elifdef
-  4  -> matched else
-  5  -> unmatched else
-
-  Upon "ifdef", add one and multiply by 6.
-  Upon "endif", divide by 6, remove 1.
-
-  ifdef -> MATCH => continue
-           MISMATCH => set to 1
-  elifdef -> if (!1) -> MISMATCH
-             MATCH => set to 2
-             MISMATCH => if (2 || 3) set to 3, else set to 1
-  else -> if (1) -> MATCH
-          MATCH => set to 4
-          MISMATCH => set to 5
-
-  in each case, if parent & 1 == 1, MISMATCH
-*/
- 
+	(ifdefshift > 0 && !IDS_ISMATCH(ifdefstate >> IDS_SHIFT))
+#define IDS_MAX_DEPTH	21 /* 64 / 3 */
+
+#ifdef IDS_DEBUG
+# define IDS_PRINT(s, st, x) \
+	do { \
+		for (int i = 0; i < ifdefshift + 1; i++) \
+			fprintf(stderr, " "); \
+		printf("%s%s [%d,%d,%d] %#" PRIx64 "\n", x, # s, \
+		    IDS_PARENT_DISABLED, IDS_ISMATCH(st), getcurifdef(), \
+		    ifdefstate); \
+	} while (/*CONSTCOND*/0)
+#else
+# define IDS_PRINT(s, st, x) __nothing
+#endif
+
+#define IDS_ENTER(s, st) \
+	IDS_PRINT(s, st, ">")
+#define IDS_EXIT(s, st) \
+	IDS_PRINT(s, st, "<")
+
 /*
  * Data for returning to previous files from include files.
  */
 struct incl {
 	struct	incl *in_prev;	/* previous includes in effect, if any */
 	YY_BUFFER_STATE in_buf;	/* previous lex state */
-	const char *in_fname;	/* previous file name */
-	int	in_lineno;	/* previous line number */
+	struct where in_where;
 	int	in_ateof;	/* token to insert at EOF */
 	int	in_interesting;	/* previous value for "interesting" */
-	int	in_ifdefstate;	/* conditional level */
+	uint64_t	in_ifdefstate;	/* conditional level */
+	int	in_ifdefshift;	/* conditional level */
 };
 static struct incl *incl;
 static int endinclude(void);
@@ -118,6 +125,7 @@ QCHARS	\"(\\.|[^\\"])*\" 
 WORD	[A-Za-z_][-A-Za-z_0-9]*
 FILENAME	({PATH}|{QCHARS})
 RESTOFLINE	[ \t]*(#[^\n]*)?\n
+WS	^[ \t]*
 
 %x	IGNORED
 
@@ -180,98 +188,101 @@ with		return WITH;
 \+=		return PLUSEQ;
 :=		return COLONEQ;
 
-<*>ifdef[ \t]+{WORD}{RESTOFLINE} {
-		ifdefstate = (ifdefstate + 1) * 6;
-		if (ifdefstate >= IDS_MAX_DEPTH) {
+<*>{WS}ifdef[ \t]+{WORD}{RESTOFLINE} {
+		ifdefstate <<= IDS_SHIFT;
+		if (++ifdefshift >= IDS_MAX_DEPTH) {
 			yyerror("too many levels of conditional");
 		}
-		if (!IDS_PARENT_DISABLED && getcurifdef()) {
-			BEGIN(INITIAL);
-		} else {
-			ifdefstate++;
+		IDS_ENTER(ifdef, 0);
+		if (IDS_PARENT_DISABLED || !getcurifdef()) {
 			BEGIN(IGNORED);
+		} else {
+			ifdefstate |= IDS_MATCH;
+			BEGIN(INITIAL);
 		}
+		IDS_EXIT(ifdef, 0);
 		yyline++;
 	}
 
-<*>ifndef[ \t]+{WORD}{RESTOFLINE} {
-		ifdefstate = (ifdefstate + 1) * 6;
-		if (ifdefstate >= IDS_MAX_DEPTH) {
+<*>{WS}ifndef[ \t]+{WORD}{RESTOFLINE} {
+		ifdefstate <<= IDS_SHIFT;
+		if (++ifdefshift >= IDS_MAX_DEPTH) {
 			yyerror("too many levels of conditional");
 		}
-		if (!IDS_PARENT_DISABLED && !getcurifdef()) {
-			BEGIN(INITIAL);
-		} else {
-			ifdefstate++;
+		IDS_ENTER(ifndef, 0);
+		if (IDS_PARENT_DISABLED || getcurifdef()) {
 			BEGIN(IGNORED);
+		} else {
+			ifdefstate |= IDS_MATCH;
+			BEGIN(INITIAL);
 		}
+		IDS_EXIT(ifndef, 0);
 		yyline++;
 	}
 
 
-<*>elifdef[ \t]+{WORD}{RESTOFLINE} {
-		st = ifdefstate % 6;
-		if (ifdefstate < 0 || st > 3) {
+<*>{WS}elifdef[ \t]+{WORD}{RESTOFLINE} {
+		int st = ifdefstate & IDS_BITS;
+		IDS_ENTER(elifdef, st);
+		if (ifdefshift == -1 || (st & IDS_ELSE) != 0) {
 			yyerror("mismatched elifdef");
 		}
-		if (IDS_PARENT_DISABLED ||
-		    st != 1 || !getcurifdef()) {
-			if (st == 2 || st == 3) {
-				ifdefstate += 3 - st;
-			} else {
-				ifdefstate += 1 - st;
-			}
+		if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || !getcurifdef()) {
 			BEGIN(IGNORED);
 		} else {
-			ifdefstate++;
+			ifdefstate |= IDS_MATCH;
 			BEGIN(INITIAL);
 		}
+		ifdefstate |= IDS_ELIF;
+		IDS_EXIT(elifdef, st);
 		yyline++;
 	}
 
-<*>elifndef[ \t]+{WORD}{RESTOFLINE} {
-		st = ifdefstate % 6;
-		if (ifdefstate < 0 || st > 3) {
+<*>{WS}elifndef[ \t]+{WORD}{RESTOFLINE} {
+		int st = ifdefstate & IDS_BITS;
+		IDS_ENTER(elifndef, st);
+		if (ifdefshift == -1 || (st & IDS_ELSE) != 0) {
 			yyerror("mismatched elifndef");
 		}
-		if (IDS_PARENT_DISABLED ||
-		    st != 1 || getcurifdef()) {
-			if (st == 2 || st == 3) {
-				ifdefstate += 3 - st;
-			} else {
-				ifdefstate += 1 - st;
-			}
+		if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || getcurifdef()) {
 			BEGIN(IGNORED);
 		} else {
-			ifdefstate++;
+			ifdefstate |= IDS_MATCH;
 			BEGIN(INITIAL);
 		}
+		ifdefstate |= IDS_ELIF;
+		IDS_EXIT(elifndef, st);
 		yyline++;
 	}
 
-<*>else{RESTOFLINE} {
-		st = ifdefstate % 6;
-		if (ifdefstate < 0 || st > 3) {
+<*>{WS}else{RESTOFLINE} {
+		int st = ifdefstate & IDS_BITS;
+		IDS_ENTER(else, st);
+		if (ifdefshift == -1 || (st & IDS_ELSE) != 0) {
 			yyerror("mismatched else");
 		}
-		if (!IDS_PARENT_DISABLED && (st == 1)) {
-			ifdefstate += 3;
-			BEGIN(INITIAL);
-		} else {
-			ifdefstate += 5 - st;
+		if (IDS_PARENT_DISABLED || IDS_ISMATCH(st)) {
 			BEGIN(IGNORED);
+		} else {
+			ifdefstate |= IDS_MATCH;
+			BEGIN(INITIAL);
 		}
+		ifdefstate |= IDS_ELSE;
+		IDS_ENTER(else, st);
 		yyline++;
 	}
 
-<*>endif{RESTOFLINE} {
-		if (ifdefstate < 0) {
+<*>{WS}endif{RESTOFLINE} {
+		IDS_ENTER(endif, 0);
+		if (ifdefshift == -1) {
 			yyerror("mismatched endif");
 		}
 		if (!IDS_PARENT_DISABLED) {
 			BEGIN(INITIAL);
 		}
-		ifdefstate = (ifdefstate/6) - 1;
+		IDS_EXIT(endif, 0);
+		ifdefshift--;
+		ifdefstate >>= IDS_SHIFT;
 		yyline++;
 	}
 
@@ -370,7 +381,7 @@ package[ \t]+{FILENAME}{RESTOFLINE}	{
 [ \t]+	{ /* ignored (white space) */; }
 .	{ return yytext[0]; }
 <*><<EOF>> {
-		if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) {
+		if (ifdefshift > (incl == NULL ? -1 : incl->in_ifdefshift)) {
 			yyerror("reached EOF while looking for endif");
 		}
 		if (incl == NULL)
@@ -526,11 +537,12 @@ include(const char *fname, int ateof, in
 	in = ecalloc(1, sizeof *in);
 	in->in_prev = incl;
 	in->in_buf = YY_CURRENT_BUFFER;
-	in->in_fname = yyfile;
-	in->in_lineno = yyline;
+	in->in_where.w_srcfile = yyfile;
+	in->in_where.w_srcline = (u_short)yyline;
 	in->in_ateof = ateof;
 	in->in_interesting = interesting;
 	in->in_ifdefstate = ifdefstate;
+	in->in_ifdefshift = ifdefshift;
 	interesting = direct & interesting;
 	if (interesting)
 		logconfig_include(fp, fname);
@@ -597,10 +609,12 @@ endinclude(void)
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	(void)fclose(yyin);
 	yy_switch_to_buffer(in->in_buf);
-	yyfile = in->in_fname;
-	yyline = in->in_lineno;
+	yyfile = in->in_where.w_srcfile;
+	yyline = in->in_where.w_srcline;
 	ateof  = in->in_ateof;
 	interesting = in->in_interesting;
+	ifdefstate = in->in_ifdefstate;
+	ifdefshift = in->in_ifdefshift;
 	free(in);
 
 	includedepth--;

Index: src/usr.bin/config/sem.c
diff -u src/usr.bin/config/sem.c:1.83 src/usr.bin/config/sem.c:1.83.4.1
--- src/usr.bin/config/sem.c:1.83	Mon Apr  9 17:46:56 2018
+++ src/usr.bin/config/sem.c	Mon Mar  9 15:22:21 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: sem.c,v 1.83 2018/04/09 17:46:56 christos Exp $	*/
+/*	$NetBSD: sem.c,v 1.83.4.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: sem.c,v 1.83 2018/04/09 17:46:56 christos Exp $");
+__RCSID("$NetBSD: sem.c,v 1.83.4.1 2020/03/09 15:22:21 martin Exp $");
 
 #include <sys/param.h>
 #include <ctype.h>
@@ -276,17 +276,24 @@ setdefmaxusers(int min, int def, int max
 	}
 }
 
+static const char *maxusers_srcfile;
+static u_short maxusers_srcline;
+
 void
 setmaxusers(int n)
 {
 
 	if (maxusers == n) {
-		cfgerror("duplicate maxusers parameter");
+		cfgerror("duplicate maxusers parameter at %s:%hu",
+		    maxusers_srcfile, maxusers_srcline);
 		return;
 	}
 	if (vflag && maxusers != 0)
-		cfgwarn("warning: maxusers already defined");
+		cfgwarn("warning: maxusers already defined at %s:%hu",
+		    maxusers_srcfile, maxusers_srcline);
 	maxusers = n;
+	maxusers_srcfile = yyfile;
+	maxusers_srcline = currentline();
 	if (n < minmaxusers) {
 		cfgerror("warning: minimum of %d maxusers assumed",
 		    minmaxusers);
@@ -338,7 +345,8 @@ defattr(const char *name, struct loclist
 	struct attrlist *al;
 
 	if (getrefattr(name, &a)) {
-		cfgerror("attribute `%s' already defined", name);
+		cfgerror("attribute `%s' already defined at %s:%hu", name,
+		    a->a_where.w_srcfile, a->a_where.w_srcline);
 		loclist_destroy(locs);
 		return (1);
 	}
@@ -380,6 +388,8 @@ mkattr(const char *name)
 		return NULL;
 	}
 	a->a_name = name;
+	a->a_where.w_srcfile = yyfile;
+	a->a_where.w_srcline = currentline();
 	TAILQ_INIT(&a->a_files);
 	CFGDBG(3, "attr `%s' allocated", name);
 
@@ -510,7 +520,7 @@ defdev(struct devbase *dev, struct locli
 		goto bad;
 	if (dev->d_isdef) {
 		cfgerror("redefinition of `%s' (previously defined at %s:%d)",
-		    dev->d_name, dev->d_srcfile, dev->d_srcline);
+		    dev->d_name, dev->d_where.w_srcfile, dev->d_where.w_srcline);
 		goto bad;
 	}
 
@@ -625,8 +635,8 @@ getdevbase(const char *name)
 		dev->d_ahead = NULL;
 		dev->d_app = &dev->d_ahead;
 		dev->d_umax = 0;
-		dev->d_srcfile = yyfile;
-		dev->d_srcline = currentline();
+		dev->d_where.w_srcfile = yyfile;
+		dev->d_where.w_srcline = currentline();
 		TAILQ_INSERT_TAIL(&allbases, dev, d_next);
 		if (ht_insert(devbasetab, name, dev))
 			panic("%s: Can't insert %s", __func__, name);
@@ -659,7 +669,7 @@ defdevattach(struct deva *deva, struct d
 	}
 	if (deva->d_isdef) {
 		cfgerror("redefinition of `%s' (previously defined at %s:%d)",
-		    deva->d_name, deva->d_srcfile, deva->d_srcline);
+		    deva->d_name, deva->d_where.w_srcfile, deva->d_where.w_srcline);
 		goto bad;
 	}
 	if (dev->d_ispseudo) {
@@ -768,8 +778,8 @@ getdevattach(const char *name)
 		deva->d_attrs = NULL;
 		deva->d_ihead = NULL;
 		deva->d_ipp = &deva->d_ihead;
-		deva->d_srcfile = yyfile;
-		deva->d_srcline = currentline();
+		deva->d_where.w_srcfile = yyfile;
+		deva->d_where.w_srcline = currentline();
 		TAILQ_INSERT_TAIL(&alldevas, deva, d_next);
 		if (ht_insert(devatab, name, deva))
 			panic("%s: Can't insert %s", __func__, name);
@@ -1039,13 +1049,18 @@ addconf(struct config *cf0)
 	const char *name;
 
 	name = cf0->cf_name;
+	if ((cf = ht_lookup(cfhashtab, name)) != NULL) {
+		cfgerror("configuration `%s' already defined %s:%hu", name,
+			cf->cf_where.w_srcfile, cf->cf_where.w_srcline);
+		goto bad;
+	}
 	cf = ecalloc(1, sizeof *cf);
 	if (ht_insert(cfhashtab, name, cf)) {
-		cfgerror("configuration `%s' already defined", name);
 		free(cf);
-		goto bad;
 	}
 	*cf = *cf0;
+	cf->cf_where.w_srcfile = yyfile;
+	cf->cf_where.w_srcline = currentline();
 
 	/*
 	 * Resolve the root device.
@@ -1157,11 +1172,13 @@ newdevi(const char *name, int unit, stru
 	i->i_atdeva = NULL;
 	i->i_locs = NULL;
 	i->i_cfflags = 0;
-	i->i_lineno = currentline();
-	i->i_srcfile = yyfile;
+	i->i_where.w_srcline = currentline();
+	i->i_where.w_srcfile = yyfile;
 	i->i_active = DEVI_ORPHAN; /* Proper analysis comes later */
 	i->i_level = devilevel;
 	i->i_pseudoroot = 0;
+	i->i_where.w_srcfile = yyfile;
+	i->i_where.w_srcline = currentline();
 	if (unit >= d->d_umax)
 		d->d_umax = unit + 1;
 	return (i);
@@ -1796,8 +1813,9 @@ addpseudo(const char *name, int number)
 		cfgerror("%s is a real device, not a pseudo-device", name);
 		return;
 	}
-	if (ht_lookup(devitab, name) != NULL) {
-		cfgerror("`%s' already defined", name);
+	if ((i = ht_lookup(devitab, name)) != NULL) {
+		cfgerror("`%s' already defined at %s:%hu", name,
+		    i->i_where.w_srcfile, i->i_where.w_srcline);
 		return;
 	}
 	i = newdevi(name, number - 1, d);	/* foo 16 => "foo0..foo15" */
@@ -1855,8 +1873,8 @@ adddevm(const char *name, devmajor_t cma
 	}
 
 	dm = ecalloc(1, sizeof(*dm));
-	dm->dm_srcfile = yyfile;
-	dm->dm_srcline = currentline();
+	dm->dm_where.w_srcfile = yyfile;
+	dm->dm_where.w_srcline = currentline();
 	dm->dm_name = name;
 	dm->dm_cmajor = cmajor;
 	dm->dm_bmajor = bmajor;
@@ -1890,11 +1908,11 @@ fixdevis(void)
 			p = i->i_pspec;
 			msg = p == NULL ? "no parent" :
 			    (p->p_atunit == WILD ? "nothing matching" : "no");
-			cfgxerror(i->i_srcfile, i->i_lineno,
+			cfgxerror(i->i_where.w_srcfile, i->i_where.w_srcline,
 			    "`%s at %s' is orphaned (%s `%s' found)", 
 			    i->i_name, i->i_at, msg, i->i_at);
 		} else if (vflag && i->i_active == DEVI_IGNORED)
-			cfgxwarn(i->i_srcfile, i->i_lineno, "ignoring "
+			cfgxwarn(i->i_where.w_srcfile, i->i_where.w_srcline, "ignoring "
 			    "explicitly orphaned instance `%s at %s'",
 			    i->i_name, i->i_at);
 	}

Index: src/usr.bin/config/util.c
diff -u src/usr.bin/config/util.c:1.20 src/usr.bin/config/util.c:1.20.18.1
--- src/usr.bin/config/util.c:1.20	Tue Sep  1 13:42:48 2015
+++ src/usr.bin/config/util.c	Mon Mar  9 15:22:21 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: util.c,v 1.20 2015/09/01 13:42:48 uebayasi Exp $	*/
+/*	$NetBSD: util.c,v 1.20.18.1 2020/03/09 15:22:21 martin Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.20 2015/09/01 13:42:48 uebayasi Exp $");
+__RCSID("$NetBSD: util.c,v 1.20.18.1 2020/03/09 15:22:21 martin Exp $");
 
 #include <sys/types.h>
 #include <assert.h>
@@ -58,6 +58,8 @@ __RCSID("$NetBSD: util.c,v 1.20 2015/09/
 #include <err.h>
 #include "defs.h"
 
+extern const char *yyfile;
+
 static void cfgvxerror(const char *, int, const char *, va_list)
 	     __printflike(3, 0);
 static void cfgvxdbg(const char *, int, const char *, va_list)
@@ -198,6 +200,8 @@ newnv(const char *name, const char *str,
 	nv->nv_str = str;
 	nv->nv_ptr = ptr;
 	nv->nv_num = i;
+	nv->nv_where.w_srcfile = yyfile;
+	nv->nv_where.w_srcline = currentline();
 	return nv;
 }
 
@@ -255,6 +259,8 @@ defoptlist_create(const char *name, cons
 	dl->dl_lintvalue = lintval;
 	dl->dl_obsolete = 0;
 	dl->dl_depends = NULL;
+	dl->dl_where.w_srcfile = yyfile;
+	dl->dl_where.w_srcline = currentline();
 	return dl;
 }
 

Reply via email to