Subject: kern/3833: changes to config for productization
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mcr@sandelman.ottawa.on.ca>
List: netbsd-bugs
Date: 07/07/1997 17:30:10
>Number:         3833
>Category:       kern
>Synopsis:       config will look in original cwd for Makefile.ARCH + friends
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Jul  7 07:35:00 1997
>Last-Modified:
>Originator:     Michael Richardson
>Organization:
Sandelman Software Works Corp.
>Release:        1.2E
>Environment:
	
System: NetBSD katto.ssh.fi 1.2 NetBSD 1.2 (SSH-XT) #2: Wed Feb 12 21:53:15 EET 1997 snabb@taulu.ssh.fi:/m/taulu/1/src/NetBSD-1.2/sys/arch/i386/compile/SSH-XT i386

>Description:
        To allow non-invasive changes to source tree (for productization), it
	would be nice to allow config to find a local Makefile.ARCH, and also
	to look for a files.CONFIG in the cwd.

	Also included are patches to allow files.* to have "library" directives
	so that entire .a files can be included.

	An updated man page is promised.

	It would be nice to see this in 1.3.

>How-To-Repeat:
	
>Fix:
*** /src/src/usr.sbin/config/mkmakefile.c	Mon Feb  3 14:26:03 1997
--- mkmakefile.c	Mon Jul  7 17:18:31 1997
***************
*** 76,90 ****
  	register int (*fn) __P((FILE *));
  	register char *ifname;
  	char line[BUFSIZ], buf[200];
  
! 	(void)sprintf(buf, "arch/%s/conf/Makefile.%s", machine, machine);
! 	ifname = sourcepath(buf);
! 	if ((ifp = fopen(ifname, "r")) == NULL) {
! 		(void)fprintf(stderr, "config: cannot read %s: %s\n",
! 		    ifname, strerror(errno));
! 		free(ifname);
! 		return (1);
  	}
  	if ((ofp = fopen("Makefile", "w")) == NULL) {
  		(void)fprintf(stderr, "config: cannot write Makefile: %s\n",
  		    strerror(errno));
--- 76,98 ----
  	register int (*fn) __P((FILE *));
  	register char *ifname;
  	char line[BUFSIZ], buf[200];
+ 	extern char origdir[];
  
! 	/* see if we have a local Makefile: MCR */
! 	(void)sprintf(buf, "%s/Makefile.%s", origdir, machine);
! 	
! 	if((ifp = fopen(buf, "r")) == NULL) {
! 	  /* no, look for it in traditional place */
! 	  (void)sprintf(buf, "arch/%s/conf/Makefile.%s", machine, machine);
! 	  ifname = sourcepath(buf);
! 	  if ((ifp = fopen(ifname, "r")) == NULL) {
! 	    (void)fprintf(stderr, "config: cannot read %s: %s\n",
! 			  ifname, strerror(errno));
! 	    free(ifname);
! 	    return (1);
! 	  }
  	}
+ 	
  	if ((ofp = fopen("Makefile", "w")) == NULL) {
  		(void)fprintf(stderr, "config: cannot write Makefile: %s\n",
  		    strerror(errno));
***************
*** 219,224 ****
--- 227,233 ----
  	register FILE *fp;
  {
  	register struct files *fi;
+ 	register struct libraries *li;
  	register int lpos, len, sp;
  
  	if (fputs("OBJS=", fp) < 0)
***************
*** 240,245 ****
--- 249,271 ----
  		lpos += len + 1;
  		sp = ' ';
  	}
+ 
+ 	for (li = alllibs; li != NULL; li = li->li_next) {
+ 		if ((li->li_flags & FI_SEL) == 0)
+ 			continue;
+ 		len = strlen(li->li_path);
+ 		if (lpos + len > 72) {
+ 			if (fputs(" \\\n", fp) < 0)
+ 				return (1);
+ 			sp = '\t';
+ 			lpos = 7;
+ 		}
+ 		if (fprintf(fp, "%c%s", sp, li->li_path) < 0)
+ 			return (1);
+ 		lpos += len + 1;
+ 		sp = ' ';
+ 	}
+ 
  	if (putc('\n', fp) < 0)
  		return (1);
  	return (0);


*** /src/src/usr.sbin/config/gram.y	Fri Jun 13 14:30:04 1997
--- gram.y	Tue Jun 24 19:18:27 1997
***************
*** 1,5 ****
  %{
! /*	$NetBSD: gram.y,v 1.15 1997/06/12 15:03:09 mrg Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
--- 1,5 ----
  %{
! /*	$NetBSD: gram.y,v 1.14 1997/02/02 21:12:32 thorpej Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
***************
*** 55,60 ****
--- 55,61 ----
  #include "config.h"
  #include "sem.h"
  
+ #define YYDEBUG 1
  #define	FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x")
  
  #define	stop(s)	error(s), exit(1)
***************
*** 100,108 ****
  }
  
  %token	AND AT ATTACH BUILD COMPILE_WITH CONFIG DEFINE DEFOPT DEVICE DUMPS
! %token	ENDFILE XFILE FILE_SYSTEM FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS
  %token	MAXUSERS MAXPARTITIONS MINOR ON OPTIONS PSEUDO_DEVICE ROOT SOURCE
! %token	TYPE WITH NEEDS_COUNT NEEDS_FLAG
  %token	<val> NUMBER
  %token	<str> PATHNAME WORD
  
--- 101,109 ----
  }
  
  %token	AND AT ATTACH BUILD COMPILE_WITH CONFIG DEFINE DEFOPT DEVICE DUMPS
! %token	ENDFILE XFILE XLIBRARY FILE_SYSTEM FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS
  %token	MAXUSERS MAXPARTITIONS MINOR ON OPTIONS PSEUDO_DEVICE ROOT SOURCE
! %token	SWAP TYPE WITH NEEDS_COUNT NEEDS_FLAG
  %token	<val> NUMBER
  %token	<str> PATHNAME WORD
  
***************
*** 122,128 ****
  %type	<str>	locdefault
  %type	<list>	attrs_opt attrs
  %type	<list>	locators locator
! %type	<list>	dev_spec
  %type	<str>	device_instance
  %type	<str>	attachment
  %type	<str>	value
--- 123,129 ----
  %type	<str>	locdefault
  %type	<list>	attrs_opt attrs
  %type	<list>	locators locator
! %type	<list>	swapdev_list dev_spec
  %type	<str>	device_instance
  %type	<str>	attachment
  %type	<str>	value
***************
*** 146,151 ****
--- 147,153 ----
  	dev_defs dev_eof		/* sys/conf/files */
  	dev_defs dev_eof		/* sys/arch/${MACHINE_ARCH}/... */
  	dev_defs dev_eof		/* sys/arch/${MACHINE}/... */
+ 	dev_defs dev_eof		/* possible files.CONFIG */
  					{ check_maxpart(); }
  	specs;				/* rest of machine description */
  
***************
*** 173,178 ****
--- 175,183 ----
  file:
  	XFILE PATHNAME fopts fflgs rule	{ addfile($2, $3, $4, $5); };
  
+ library:
+ 	XLIBRARY PATHNAME fopts fflgs 	{ addlibrary($2, $3, $4); };
+ 
  /* order of options is important, must use right recursion */
  fopts:
  	fexpr				{ $$ = $1; } |
***************
*** 218,223 ****
--- 223,229 ----
  
  one_def:
  	file |
+ 	library |
  	include |
  	DEFINE WORD interface_opt	{ (void)defattr($2, $3); } |
  	DEFOPT WORD			{ defoption($2); } |
***************
*** 310,315 ****
--- 316,322 ----
  
  config_spec:
  	file |
+ 	library |
  	include |
  	FILE_SYSTEM fs_list |
  	OPTIONS opt_list |
***************
*** 348,353 ****
--- 355,361 ----
  					    conf.cf_lineno = currentline();
  					    conf.cf_fstype = NULL;
  					    conf.cf_root = NULL;
+ 					    conf.cf_swap = NULL;
  					    conf.cf_dump = NULL; };
  
  root_spec:
***************
*** 367,374 ****
--- 375,387 ----
  	/* empty */;
  
  sysparam:
+ 	SWAP on_opt swapdev_list { setconf(&conf.cf_swap, "swap", $3); } |
  	DUMPS on_opt dev_spec	 { setconf(&conf.cf_dump, "dumps", $3); };
  
+ swapdev_list:
+ 	dev_spec AND swapdev_list	{ ($$ = $1)->nv_next = $3; } |
+ 	dev_spec			{ $$ = $1; };
+ 
  dev_spec:
  	'?'				{ $$ = new_si(intern("?"), NODEV); } |
  	WORD				{ $$ = new_si($1, NODEV); } |
***************
*** 436,445 ****
--- 449,491 ----
  	const char *mcharch;
  {
  	char buf[MAXPATHLEN];
+ 	const char *last_component;
+ 	char        configpath[MAXPATHLEN];
+ 	extern  char origdir[];
  
  	machine = mch;
  	machinearch = mcharch;
  
+ 	configpath[0]='\0';
+ 	last_component=strrchr(conffile, '/');
+ 	if(last_component)
+ 	  {
+ 	    strncat(configpath, conffile, last_component-conffile);
+ 	    /* advance past / */
+ 	    last_component++;
+ 	  }
+ 	else
+ 	  {
+ 	    last_component = conffile;
+ 	    strncat(configpath, origdir, sizeof(configpath));
+ 	  }
+ 	
+ 
+ 	(void)snprintf(buf, MAXPATHLEN, "%s/files.%s", configpath, last_component);
+ 	printf("looking for %s (%s)\n", buf, getwd(NULL));
+ 	
+ 	if(access(buf, F_OK) == 0)
+ 	  {
+ 	    printf("got %s\n", buf);
+ 	    if (include(buf, ENDFILE) != 0)
+ 	      exit(1);
+ 	  }
+ 	else
+ 	  {
+ 	    if(include(_PATH_DEVNULL, ENDFILE) != 0)
+ 	      exit(1);
+ 	  }
+ 
  	(void)sprintf(buf, "arch/%s/conf/files.%s", machine, machine);
  	if (include(buf, ENDFILE) != 0)
  		exit(1);
***************
*** 449,459 ****
--- 495,507 ----
  		    machinearch, machinearch);
  	else
  		strcpy(buf, _PATH_DEVNULL);
+ 
  	if (include(buf, ENDFILE) != 0)
  		exit(1);
  
  	if (include("conf/files", ENDFILE) != 0)
  		exit(1);
+ 
  }
  
  static void

*** /src/src/usr.sbin/config/main.c	Fri Jun 13 14:30:04 1997
--- main.c	Mon Apr 14 07:27:13 1997
***************
*** 1,4 ****
! /*	$NetBSD: main.c,v 1.24 1997/06/12 15:03:10 mrg Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
--- 1,4 ----
! /*	$NetBSD: main.c,v 1.22 1997/02/02 21:12:33 thorpej Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
***************
*** 60,66 ****
  #include <string.h>
  #include <unistd.h>
  #include "config.h"
- #include "sem.h"
  
  int	firstfile __P((const char *));
  int	yyparse __P((void));
--- 60,65 ----
***************
*** 83,88 ****
--- 82,89 ----
  static int hasparent __P((struct devi *));
  static int cfcrosscheck __P((struct config *, const char *, struct nvlist *));
  
+ char origdir[MAXPATHLEN];
+ 
  int
  main(argc, argv)
  	int argc;
***************
*** 91,101 ****
  	register char *p;
  	const char *last_component;
  	int pflag, ch;
  
  	pflag = 0;
! 	while ((ch = getopt(argc, argv, "gpb:s:")) != EOF) {
  		switch (ch) {
  
  		case 'g':
  			/*
  			 * In addition to DEBUG, you probably wanted to
--- 92,107 ----
  	register char *p;
  	const char *last_component;
  	int pflag, ch;
+ 	extern int yydebug;
  
  	pflag = 0;
! 	while ((ch = getopt(argc, argv, "gpb:s:D")) != EOF) {
  		switch (ch) {
  
+ 		case 'D':
+ 			yydebug++;
+ 			break;
+ 
  		case 'g':
  			/*
  			 * In addition to DEBUG, you probably wanted to
***************
*** 144,149 ****
--- 150,158 ----
  		exit(1);
  	}
  	conffile = (argc == 1) ? argv[0] : "CONFIG";
+ 
+ 	getcwd(origdir, sizeof(origdir));
+ 	
  	if (firstfile(conffile)) {
  		(void)fprintf(stderr, "config: cannot read %s: %s\n",
  		    conffile, strerror(errno));
***************
*** 201,206 ****
--- 210,220 ----
  		stop();
  
  	/*
+ 	 * fix up libraries */
+ 	if(fixlibraries())
+ 	  stop();
+ 
+ 	/*
  	 * Perform cross-checking.
  	 */
  	if (maxusers == 0) {
***************
*** 493,499 ****
  {
  	register struct devbase *dev;
  	register struct devi *pd;
! 	int errs, devunit;
  
  	if (maxpartitions <= 0)
  		panic("cfcrosscheck");
--- 507,513 ----
  {
  	register struct devbase *dev;
  	register struct devi *pd;
! 	int errs, devminor;
  
  	if (maxpartitions <= 0)
  		panic("cfcrosscheck");
***************
*** 504,521 ****
  		dev = ht_lookup(devbasetab, nv->nv_name);
  		if (dev == NULL)
  			panic("cfcrosscheck(%s)", nv->nv_name);
! 		if (has_attr(dev->d_attrs, s_ifnet))
! 			devunit = nv->nv_ifunit;	/* XXX XXX XXX */
! 		else
! 			devunit = minor(nv->nv_int) / maxpartitions;
! 		if (devbase_has_instances(dev, devunit))
  			continue;
  		if (devbase_has_instances(dev, STAR) &&
! 		    devunit >= dev->d_umax)
  			continue;
  		for (pd = allpseudo; pd != NULL; pd = pd->i_next)
! 			if (pd->i_base == dev && devunit < dev->d_umax &&
! 			    devunit >= 0)
  				goto loop;
  		(void)fprintf(stderr,
  		    "%s%d: %s says %s on %s, but there's no %s\n",
--- 518,532 ----
  		dev = ht_lookup(devbasetab, nv->nv_name);
  		if (dev == NULL)
  			panic("cfcrosscheck(%s)", nv->nv_name);
! 		devminor = minor(nv->nv_int) / maxpartitions;
! 		if (devbase_has_instances(dev, devminor))
  			continue;
  		if (devbase_has_instances(dev, STAR) &&
! 		    devminor >= dev->d_umax)
  			continue;
  		for (pd = allpseudo; pd != NULL; pd = pd->i_next)
! 			if (pd->i_base == dev && devminor < dev->d_umax &&
! 			    devminor >= 0)
  				goto loop;
  		(void)fprintf(stderr,
  		    "%s%d: %s says %s on %s, but there's no %s\n",
***************
*** 530,536 ****
  /*
   * Cross-check the configuration: make sure that each target device
   * or attribute (`at foo[0*?]') names at least one real device.  Also
!  * see that the root and dump devices for all configurations are there.
   */
  int
  crosscheck()
--- 541,548 ----
  /*
   * Cross-check the configuration: make sure that each target device
   * or attribute (`at foo[0*?]') names at least one real device.  Also
!  * see that the root, swap, and dump devices for all configurations
!  * are there.
   */
  int
  crosscheck()
***************
*** 556,563 ****
  		errs++;
  	}
  	for (cf = allcf; cf != NULL; cf = cf->cf_next) {
! 		if (cf->cf_root != NULL) {	/* i.e., not root on ? */
  			errs += cfcrosscheck(cf, "root", cf->cf_root);
  			errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
  		}
  	}
--- 568,576 ----
  		errs++;
  	}
  	for (cf = allcf; cf != NULL; cf = cf->cf_next) {
! 		if (cf->cf_root != NULL) {	/* i.e., not swap generic */
  			errs += cfcrosscheck(cf, "root", cf->cf_root);
+ 			errs += cfcrosscheck(cf, "swap", cf->cf_swap);
  			errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
  		}
  	}
*** /src/src/usr.sbin/config/config.h	Mon May 26 15:00:35 1997
--- config.h	Mon Apr 14 07:27:10 1997
***************
*** 1,4 ****
! /*	$NetBSD: config.h,v 1.32 1997/05/25 18:42:54 thorpej Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
--- 1,4 ----
! /*	$NetBSD: config.h,v 1.31 1997/03/14 00:14:09 jtk Exp $	*/
  
  /*
   * Copyright (c) 1992, 1993
***************
*** 90,96 ****
  #define	nv_str	nv_un.un_str
  #define	nv_ptr	nv_un.un_ptr
  	int	nv_int;
- 	int	nv_ifunit;		/* XXX XXX XXX */
  };
  
  /*
--- 90,95 ----
***************
*** 255,260 ****
--- 254,280 ----
  #define	FI_HIDDEN	0x08	/* obscured by other(s), base names overlap */
  
  /*
+  * Libraries.  This provides a way to pull in a bunch of files without
+  * having to compile them seperately. This is only useful for libraries
+  * that are either entirely self-contained and have no options, or
+  * for that one is unable compile conveniently.
+  *
+  * Note: libraries are always local to the compile directory.
+  *
+  */
+ struct libraries {
+ 	struct	libraries *li_next; /* linked list */
+ 	const char *li_srcfile;	    /* the name of the "files" file that got us */
+ 	u_short	li_srcline;	    /* and the line number */
+ 	u_char	li_flags;	    /* as below */
+ 	char	li_lastc;	    /* last char from path */
+ 	const char *li_path;	    /* full file path */
+ 	struct  nvlist *li_optx;    /* options expression */
+ 	struct  nvlist *li_optf;    /* flattened version of above, if needed */
+ 	const char *fi_mkrule;	    /* special make rule, if any */
+ };
+ 
+ /*
   * Hash tables look up name=value pairs.  The pointer value of the name
   * is assumed to be constant forever; this can be arranged by interning
   * the name.  (This is fairly convenient since our lexer does this for
***************
*** 297,302 ****
--- 317,323 ----
  int	npseudo;		/* number of pseudo's */
  
  struct	files *allfiles;	/* list of all kernel source files */
+ struct  libraries *alllibs;     /* list of all kernel libraries */
  
  struct	devi **packed;		/* arrayified table for packed devi's */
  int	npacked;		/* size of packed table, <= ndevi */
***************
*** 315,320 ****
--- 336,342 ----
  void	checkfiles __P((void));
  int	fixfiles __P((void));	/* finalize */
  void	addfile __P((const char *, struct nvlist *, int, const char *));
+ void	addlibrary __P((const char *, struct nvlist *, int));
  
  /* hash.c */
  struct	hashtab *ht_new __P((void));
*** /src/src/usr.sbin/config/files.c	Fri Nov  8 14:23:32 1996
--- files.c	Mon Apr 14 07:27:11 1997
***************
*** 65,70 ****
--- 65,72 ----
  static struct files **nextfile;
  static struct files **unchecked;
  
+ static struct libraries **nextlibrary;
+ 
  static int	checkaux __P((const char *, void *));
  static int	fixcount __P((const char *, void *));
  static int	fixfsel __P((const char *, void *));
***************
*** 81,86 ****
--- 83,89 ----
  	pathtab = ht_new();
  	nextfile = &allfiles;
  	unchecked = &allfiles;
+ 	nextlibrary = &alllibs;
  }
  
  static void
***************
*** 164,169 ****
--- 167,223 ----
  	expr_free(optx);
  }
  
+ void
+ addlibrary(path, optx, flags)
+ 	const char *path;
+ 	struct nvlist *optx;
+ 	int flags;
+ {
+ 	struct libraries *li;
+ 	const char *dotp, *tail;
+ 	size_t baselen;
+ 	int needc, needf;
+ 
+ 	/* check various errors */
+ 	needc = flags & FI_NEEDSCOUNT;
+ 	needf = flags & FI_NEEDSFLAG;
+ 	if (needc) {
+ 	  error("libraries can not take counts");
+ 	  goto bad;
+ 	}
+ 	
+ 	if (optx == NULL && needf) {
+ 		error("nothing to flag for %s", path);
+ 		goto bad;
+ 	}
+ 
+ 	/*
+ 	 * Commit this file to memory.  We will decide later whether it
+ 	 * will be used after all.
+ 	 */
+ 	li = emalloc(sizeof *li);
+ 	if (ht_insert(pathtab, path, li)) {
+ 		free(li);
+ 		if ((li = ht_lookup(pathtab, path)) == NULL)
+ 			panic("addfile: ht_lookup(%s)", path);
+ 		error("duplicate file %s", path);
+ 		xerror(li->li_srcfile, li->li_srcline,
+ 		    "here is the original definition");
+ 	}
+ 	li->li_next = NULL;
+ 	li->li_srcfile = yyfile;
+ 	li->li_srcline = currentline();
+ 	li->li_flags = flags;
+ 	li->li_path = path;
+ 	li->li_optx = optx;
+ 	li->li_optf = NULL;
+ 	*nextlibrary = li;
+ 	nextlibrary = &li->li_next;
+ 	return;
+ bad:
+ 	expr_free(optx);
+ }
+ 
  /*
   * We have finished reading some "files" file, either ../../conf/files
   * or ./files.$machine.  Make sure that everything that is flagged as
***************
*** 261,266 ****
--- 315,354 ----
  			}
  		}
  		fi->fi_flags |= FI_SEL;
+ 	}
+ 	return (err);
+ }
+ 
+ /*
+  * We have finished reading everything.  Tack the libraries down: calculate
+  * selection.  
+  */
+ int
+ fixlibraries()
+ {
+ 	register struct libraries *li, *oli;
+ 	struct nvlist *flathead, **flatp;
+ 	int err, sel;
+ 
+ 	err = 0;
+ 	for (li = alllibs; li != NULL; li = li->li_next) {
+ 		/* Skip files that generated counted-device complaints. */
+ 		if (li->li_flags & FI_HIDDEN)
+ 			continue;
+ 		if (li->li_optx != NULL) {
+ 			/* Optional: see if it is to be included. */
+ 			flathead = NULL;
+ 			flatp = &flathead;
+ 			sel = expr_eval(li->li_optx,
+ 			    li->li_flags & FI_NEEDSFLAG ? fixfsel :
+ 			    fixsel,
+ 			    &flatp);
+ 			li->li_optf = flathead;
+ 			if (!sel)
+ 				continue;
+ 		}
+ 
+ 		li->li_flags |= FI_SEL;
  	}
  	return (err);
  }
>Audit-Trail:
>Unformatted: