date and time created 88/12/16 11:12:32 by bostic
[unix-history] / usr / src / usr.sbin / config / config.y
index a3e0193..038e94e 100644 (file)
+%union {
+       char    *str;
+       int     val;
+       struct  file_list *file;
+       struct  idlst *lst;
+}
+
+%token AND
+%token ANY
+%token ARGS
+%token AT
+%token COMMA
+%token CONFIG
+%token CONTROLLER
+%token CPU
+%token CSR
+%token DEVICE
+%token DISK
+%token DRIVE
+%token DST
+%token DUMPS
+%token EQUALS
+%token FLAGS
+%token HZ
+%token IDENT
 %token MACHINE
 %token MACHINE
-%token CPU IDENT CONFIG ANY DEVICE UBA MBA NEXUS CSR DRIVE VECTOR OPTIONS
-%token CONTROLLER PSEUDO_DEVICE FLAGS ID SEMICOLON NUMBER FPNUMBER TRACE
-%token DISK SLAVE AT HZ TIMEZONE DST MAXUSERS
-%token MASTER PRIORITY COMMA MINUS EQUALS
+%token MAJOR
+%token MASTER
+%token MAXUSERS
+%token MINOR
+%token MINUS
+%token NEXUS
+%token ON
+%token OPTIONS
+%token MAKEOPTIONS
+%token PRIORITY
+%token PSEUDO_DEVICE
+%token ROOT
+%token SEMICOLON
+%token SIZE
+%token SLAVE
+%token SWAP
+%token TIMEZONE
+%token TRACE
+%token VECTOR
+
+%token <str>   ID
+%token <val>   NUMBER
+%token <val>   FPNUMBER
+
+%type  <str>   Save_id
+%type  <str>   Opt_value
+%type  <str>   Dev
+%type  <lst>   Id_list
+%type  <val>   optional_size
+%type  <str>   device_name
+%type  <val>   major_minor
+%type  <val>   arg_device_spec
+%type  <val>   root_device_spec
+%type  <val>   dump_device_spec
+%type  <file>  swap_device_spec
+
 %{
 
 %{
 
-/*     config.y        1.15    82/10/24        */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)config.y    5.8 (Berkeley) %G%
+ */
 
 #include "config.h"
 
 #include "config.h"
+#include <ctype.h>
 #include <stdio.h>
 
 struct device cur;
 struct device *curp = 0;
 char   *temp_id;
 char   *val_id;
 #include <stdio.h>
 
 struct device cur;
 struct device *curp = 0;
 char   *temp_id;
 char   *val_id;
+char   *malloc();
 
 %}
 %%
 Configuration:
        Many_specs
 
 %}
 %%
 Configuration:
        Many_specs
-       ;
+               = { verifysystemspecs(); }
+               ;
 
 Many_specs:
        Many_specs Spec
 
 Many_specs:
        Many_specs Spec
-       |
-       ;
+               |
+       /* lambda */
+               ;
 
 Spec:
 
 Spec:
-       Device_spec SEMICOLON  = { newdev(&cur); } |
-       Config_spec SEMICOLON |
-       TRACE SEMICOLON = { do_trace = ! do_trace; } |
-       SEMICOLON |
+       Device_spec SEMICOLON
+             = { newdev(&cur); } |
+       Config_spec SEMICOLON
+               |
+       TRACE SEMICOLON
+             = { do_trace = !do_trace; } |
+       SEMICOLON
+               |
        error SEMICOLON
        error SEMICOLON
-       ;
+               ;
 
 Config_spec:
 
 Config_spec:
-       MACHINE Save_id = {
+       MACHINE Save_id
+           = {
                if (!strcmp($2, "vax")) {
                        machine = MACHINE_VAX;
                        machinename = "vax";
                if (!strcmp($2, "vax")) {
                        machine = MACHINE_VAX;
                        machinename = "vax";
-               } else if (!strcmp($2, "sun")) {
-                       machine = MACHINE_SUN;
-                       machinename = "sun";
+               } else if (!strcmp($2, "tahoe")) {
+                       machine = MACHINE_TAHOE;
+                       machinename = "tahoe";
                } else
                        yyerror("Unknown machine type");
                } else
                        yyerror("Unknown machine type");
-               } |
-       CPU Save_id = {
-                   struct cputype *cp = malloc(sizeof (struct cputype));
-                   cp->cpu_name = ns($2);
-                   cp->cpu_next = cputype;
-                   cputype = cp;
-                   free(temp_id);
-                   } |
-       OPTIONS Opt_list |
-       IDENT ID = { ident = ns($2); } |
-       CONFIG Save_id ID = { mkconf(temp_id, $3); free(temp_id); } |
-       HZ NUMBER = {
-               yyerror("HZ specification obsolete; delete");
-               hz = 60;
-               } |
-       TIMEZONE NUMBER = { timezone = 60 * $2; check_tz(); } |
-       TIMEZONE NUMBER DST = { timezone = 60 * $2; dst = 1; check_tz(); } |
-       TIMEZONE FPNUMBER = { timezone = $2; check_tz(); } |
-       TIMEZONE FPNUMBER DST = { timezone = $2; dst = 1; check_tz(); } |
-       TIMEZONE MINUS NUMBER =
-           { timezone = -60 * $3; check_tz(); } |
-       TIMEZONE MINUS NUMBER DST =
-           { timezone = -60 * $3; dst = 1; check_tz(); } |
-       TIMEZONE MINUS FPNUMBER =
-           { timezone = -$3; check_tz(); } |
-       TIMEZONE MINUS FPNUMBER DST =
-           { timezone = -$3; dst = 1; check_tz(); } |
-       MAXUSERS NUMBER = { maxusers = $2; }
+             } |
+       CPU Save_id
+             = {
+               struct cputype *cp =
+                   (struct cputype *)malloc(sizeof (struct cputype));
+               cp->cpu_name = ns($2);
+               cp->cpu_next = cputype;
+               cputype = cp;
+               free(temp_id);
+             } |
+       OPTIONS Opt_list
+               |
+       MAKEOPTIONS Mkopt_list
+               |
+       IDENT ID
+             = { ident = ns($2); } |
+       System_spec
+               |
+       HZ NUMBER
+             = { yyerror("HZ specification obsolete; delete"); } |
+       TIMEZONE NUMBER
+             = { timezone = 60 * $2; check_tz(); } |
+       TIMEZONE NUMBER DST NUMBER
+             = { timezone = 60 * $2; dst = $4; check_tz(); } |
+       TIMEZONE NUMBER DST
+             = { timezone = 60 * $2; dst = 1; check_tz(); } |
+       TIMEZONE FPNUMBER
+             = { timezone = $2; check_tz(); } |
+       TIMEZONE FPNUMBER DST NUMBER
+             = { timezone = $2; dst = $4; check_tz(); } |
+       TIMEZONE FPNUMBER DST
+             = { timezone = $2; dst = 1; check_tz(); } |
+       TIMEZONE MINUS NUMBER
+             = { timezone = -60 * $3; check_tz(); } |
+       TIMEZONE MINUS NUMBER DST NUMBER
+             = { timezone = -60 * $3; dst = $5; check_tz(); } |
+       TIMEZONE MINUS NUMBER DST
+             = { timezone = -60 * $3; dst = 1; check_tz(); } |
+       TIMEZONE MINUS FPNUMBER
+             = { timezone = -$3; check_tz(); } |
+       TIMEZONE MINUS FPNUMBER DST NUMBER
+             = { timezone = -$3; dst = $5; check_tz(); } |
+       TIMEZONE MINUS FPNUMBER DST
+             = { timezone = -$3; dst = 1; check_tz(); } |
+       MAXUSERS NUMBER
+             = { maxusers = $2; };
+
+System_spec:
+         System_id System_parameter_list
+               = { checksystemspec(*confp); }
+       ;
+               
+System_id:
+         CONFIG Save_id
+               = { mkconf($2); }
+       ;
+
+System_parameter_list:
+         System_parameter_list System_parameter
+       | System_parameter
+       ;
+
+System_parameter:
+         swap_spec
+       | root_spec
+       | dump_spec
+       | arg_spec
+       ;
+       
+swap_spec:
+         SWAP optional_on swap_device_list
+       ;
+       
+swap_device_list:
+         swap_device_list AND swap_device
+       | swap_device
+       ;
+       
+swap_device:
+         swap_device_spec optional_size
+             = { mkswap(*confp, $1, $2); }
+       ;
+
+swap_device_spec:
+         device_name
+               = {
+                       struct file_list *fl = newswap();
+
+                       if (eq($1, "generic"))
+                               fl->f_fn = $1;
+                       else {
+                               fl->f_swapdev = nametodev($1, 0, 'b');
+                               fl->f_fn = devtoname(fl->f_swapdev);
+                       }
+                       $$ = fl;
+               }
+       | major_minor
+               = {
+                       struct file_list *fl = newswap();
+
+                       fl->f_swapdev = $1;
+                       fl->f_fn = devtoname($1);
+                       $$ = fl;
+               }
+       ;
+
+root_spec:
+         ROOT optional_on root_device_spec
+               = {
+                       struct file_list *fl = *confp;
+
+                       if (fl && fl->f_rootdev != NODEV)
+                               yyerror("extraneous root device specification");
+                       else
+                               fl->f_rootdev = $3;
+               }
+       ;
+
+root_device_spec:
+         device_name
+               = { $$ = nametodev($1, 0, 'a'); }
+       | major_minor
+       ;
+
+dump_spec:
+         DUMPS optional_on dump_device_spec
+               = {
+                       struct file_list *fl = *confp;
+
+                       if (fl && fl->f_dumpdev != NODEV)
+                               yyerror("extraneous dump device specification");
+                       else
+                               fl->f_dumpdev = $3;
+               }
+
+       ;
+
+dump_device_spec:
+         device_name
+               = { $$ = nametodev($1, 0, 'b'); }
+       | major_minor
+       ;
+
+arg_spec:
+         ARGS optional_on arg_device_spec
+               = {
+                       struct file_list *fl = *confp;
+
+                       if (fl && fl->f_argdev != NODEV)
+                               yyerror("extraneous arg device specification");
+                       else
+                               fl->f_argdev = $3;
+               }
+       ;
+
+arg_device_spec:
+         device_name
+               = { $$ = nametodev($1, 0, 'b'); }
+       | major_minor
+       ;
+
+major_minor:
+         MAJOR NUMBER MINOR NUMBER
+               = { $$ = makedev($2, $4); }
+       ;
+
+optional_on:
+         ON
+       | /* empty */
+       ;
+
+optional_size:
+         SIZE NUMBER
+             = { $$ = $2; }
+       | /* empty */
+             = { $$ = 0; }
+       ;
+
+device_name:
+         Save_id
+               = { $$ = $1; }
+       | Save_id NUMBER
+               = {
+                       char buf[80];
+
+                       (void) sprintf(buf, "%s%d", $1, $2);
+                       $$ = ns(buf); free($1);
+               }
+       | Save_id NUMBER ID
+               = {
+                       char buf[80];
+
+                       (void) sprintf(buf, "%s%d%s", $1, $2, $3);
+                       $$ = ns(buf); free($1);
+               }
        ;
 
 Opt_list:
        ;
 
 Opt_list:
-       Opt_list COMMA Option |
+       Opt_list COMMA Option
+               |
        Option
        Option
-       ;
+               ;
 
 Option:
 
 Option:
-       Save_id = {
-                   struct opt *op = malloc(sizeof (struct opt));
-                   op->op_name = ns($1);
-                   op->op_next = opt;
-                   op->op_value = 0;
-                   opt = op;
-                   free(temp_id);
-       } |
-       Save_id EQUALS Opt_value = {
-                   struct opt *op = malloc(sizeof (struct opt));
-                   op->op_name = ns($1);
-                   op->op_next = opt;
-                   op->op_value = ns($3);
-                   opt = op;
-                   free(temp_id);
-                   free(val_id);
-       }
-       ;
+       Save_id
+             = {
+               struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+               op->op_name = ns($1);
+               op->op_next = opt;
+               op->op_value = 0;
+               opt = op;
+               free(temp_id);
+             } |
+       Save_id EQUALS Opt_value
+             = {
+               struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+               op->op_name = ns($1);
+               op->op_next = opt;
+               op->op_value = ns($3);
+               opt = op;
+               free(temp_id);
+               free(val_id);
+             } ;
 
 Opt_value:
 
 Opt_value:
-       ID = { $$ = val_id = ns($1); } |
-       NUMBER = { char nb[16]; sprintf(nb, "%d", $1); $$ = val_id = ns(nb); }
-       ;
+       ID
+             = { $$ = val_id = ns($1); } |
+       NUMBER
+             = {
+               char nb[16];
+               (void) sprintf(nb, "%d", $1);
+               $$ = val_id = ns(nb);
+             } ;
 
 
 Save_id:
 
 
 Save_id:
-       ID = { $$ = temp_id = ns($1); }
+       ID
+             = { $$ = temp_id = ns($1); }
        ;
 
        ;
 
+Mkopt_list:
+       Mkopt_list COMMA Mkoption
+               |
+       Mkoption
+               ;
+
+Mkoption:
+       Save_id EQUALS Opt_value
+             = {
+               struct opt *op = (struct opt *)malloc(sizeof (struct opt));
+               op->op_name = ns($1);
+               op->op_next = mkopt;
+               op->op_value = ns($3);
+               mkopt = op;
+               free(temp_id);
+               free(val_id);
+             } ;
+
 Dev:
 Dev:
-       UBA  = { $$ = ns("uba"); } |
-       MBA  = { $$ = ns("mba"); } |
-       ID = { $$ = ns($1); }
+       ID
+             = { $$ = ns($1); }
        ;
 
 Device_spec:
        ;
 
 Device_spec:
-       DEVICE Dev_name Dev_info Int_spec = {  cur.d_type = DEVICE; } |
-       MASTER Dev_name Dev_info Int_spec = {  cur.d_type = MASTER; } |
-       DISK Dev_name Dev_info Int_spec =
-                               {  cur.d_dk = 1; cur.d_type = DEVICE; } |
-       CONTROLLER Dev_name Dev_info Int_spec = {  cur.d_type = CONTROLLER; } |
-       PSEUDO_DEVICE Init_dev Dev = {
-                       cur.d_name = $3;
-                       cur.d_type = PSEUDO_DEVICE;
-                 } |
-       PSEUDO_DEVICE Init_dev Dev NUMBER = {
-                       cur.d_name = $3;
-                       cur.d_type = PSEUDO_DEVICE;
-                       cur.d_slave = $4;
-               }
-       ;
+       DEVICE Dev_name Dev_info Int_spec
+             = { cur.d_type = DEVICE; } |
+       MASTER Dev_name Dev_info Int_spec
+             = { cur.d_type = MASTER; } |
+       DISK Dev_name Dev_info Int_spec
+             = { cur.d_dk = 1; cur.d_type = DEVICE; } |
+       CONTROLLER Dev_name Dev_info Int_spec
+             = { cur.d_type = CONTROLLER; } |
+       PSEUDO_DEVICE Init_dev Dev
+             = {
+               cur.d_name = $3;
+               cur.d_type = PSEUDO_DEVICE;
+               } |
+       PSEUDO_DEVICE Init_dev Dev NUMBER
+             = {
+               cur.d_name = $3;
+               cur.d_type = PSEUDO_DEVICE;
+               cur.d_slave = $4;
+               };
 
 Dev_name:
 
 Dev_name:
-       Init_dev Dev NUMBER =   {
-                       cur.d_name = $2;
-                       if (eq($2, "mba"))
-                           seen_mba = 1;
-                       else if (eq($2, "uba"))
-                           seen_uba = 1;
-                       cur.d_unit = $3;
-               }
-       ;
+       Init_dev Dev NUMBER
+             = {
+               cur.d_name = $2;
+               if (eq($2, "mba"))
+                       seen_mba = 1;
+               else if (eq($2, "uba"))
+                       seen_uba = 1;
+               else if (eq($2, "vba"))
+                       seen_vba = 1;
+               cur.d_unit = $3;
+               };
 
 Init_dev:
 
 Init_dev:
-       = { init_dev(&cur); }
-       ;
+       /* lambda */
+             = { init_dev(&cur); };
 
 Dev_info:
        Con_info Info_list
 
 Dev_info:
        Con_info Info_list
-       |
-       ;
+               |
+       /* lambda */
+               ;
 
 Con_info:
 
 Con_info:
-       AT Dev NUMBER = {
-               if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba"))
-                       yyerror(sprintf(errbuf,
-                               "%s must be connected to a nexus", cur.d_name));
+       AT Dev NUMBER
+             = {
+               if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
+                       (void) sprintf(errbuf,
+                               "%s must be connected to a nexus", cur.d_name);
+                       yyerror(errbuf);
+               }
                cur.d_conn = connect($2, $3);
                cur.d_conn = connect($2, $3);
-       } |
-       AT NEXUS NUMBER = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; }
-       ;
+               } |
+       AT NEXUS NUMBER
+             = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; };
     
 Info_list:
        Info_list Info
     
 Info_list:
        Info_list Info
-       |
-       ;
+               |
+       /* lambda */
+               ;
 
 Info:
 
 Info:
-       CSR NUMBER = { cur.d_addr = $2; } |
-       DRIVE NUMBER = { cur.d_drive = $2; } |
-       SLAVE NUMBER =
-       {
-               if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS
-                   && cur.d_conn->d_type == MASTER)
+       CSR NUMBER
+             = { cur.d_addr = $2; } |
+       DRIVE NUMBER
+             = { cur.d_drive = $2; } |
+       SLAVE NUMBER
+             = {
+               if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS &&
+                   cur.d_conn->d_type == MASTER)
                        cur.d_slave = $2;
                else
                        yyerror("can't specify slave--not to master");
                        cur.d_slave = $2;
                else
                        yyerror("can't specify slave--not to master");
-       } |
-       FLAGS NUMBER = { cur.d_flags = $2; }
-       ;
+               } |
+       FLAGS NUMBER
+             = { cur.d_flags = $2; };
 
 Int_spec:
 
 Int_spec:
-       VECTOR Id_list = { cur.d_vec = $2; } |
-       PRIORITY NUMBER = { cur.d_pri = $2; } |
-       ;
+       VECTOR Id_list
+             = { cur.d_vec = $2; } |
+       PRIORITY NUMBER
+             = { cur.d_pri = $2; } |
+       /* lambda */
+               ;
 
 Id_list:
 
 Id_list:
-       Save_id =
-           { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
-             a->id = $1; a->id_next = 0; $$ = a; } |
+       Save_id
+             = {
+               struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
+               a->id = $1; a->id_next = 0; $$ = a;
+               } |
        Save_id Id_list =
        Save_id Id_list =
-           { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
-             a->id = $1; a->id_next = $2; $$ = a; } ;
+               {
+               struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
+               a->id = $1; a->id_next = $2; $$ = a;
+               };
+
 %%
 
 yyerror(s)
        char *s;
 {
 
 %%
 
 yyerror(s)
        char *s;
 {
 
-       fprintf(stderr, "config: %s at line %d\n", s, yyline);
+       fprintf(stderr, "config: line %d: %s\n", yyline + 1, s);
 }
 
 /*
 }
 
 /*
@@ -211,9 +507,9 @@ ns(str)
 {
        register char *cp;
 
 {
        register char *cp;
 
-       cp = malloc(strlen(str)+1);
-       strcpy(cp, str);
-       return cp;
+       cp = malloc((unsigned)(strlen(str)+1));
+       (void) strcpy(cp, str);
+       return (cp);
 }
 
 /*
 }
 
 /*
@@ -226,6 +522,7 @@ newdev(dp)
 
        np = (struct device *) malloc(sizeof *np);
        *np = *dp;
 
        np = (struct device *) malloc(sizeof *np);
        *np = *dp;
+       np->d_next = 0;
        if (curp == 0)
                dtab = np;
        else
        if (curp == 0)
                dtab = np;
        else
@@ -236,19 +533,77 @@ newdev(dp)
 /*
  * note that a configuration should be made
  */
 /*
  * note that a configuration should be made
  */
-mkconf(dev, sysname)
-       char *dev, *sysname;
+mkconf(sysname)
+       char *sysname;
 {
 {
-       register struct file_list *fl;
+       register struct file_list *fl, **flp;
 
        fl = (struct file_list *) malloc(sizeof *fl);
 
        fl = (struct file_list *) malloc(sizeof *fl);
-       fl->f_fn = ns(dev);
-       fl->f_needs = ns(sysname);
-       if (confp == 0)
-               conf_list = fl;
+       fl->f_type = SYSTEMSPEC;
+       fl->f_needs = sysname;
+       fl->f_rootdev = NODEV;
+       fl->f_argdev = NODEV;
+       fl->f_dumpdev = NODEV;
+       fl->f_fn = 0;
+       fl->f_next = 0;
+       for (flp = confp; *flp; flp = &(*flp)->f_next)
+               ;
+       *flp = fl;
+       confp = flp;
+}
+
+struct file_list *
+newswap()
+{
+       struct file_list *fl = (struct file_list *)malloc(sizeof (*fl));
+
+       fl->f_type = SWAPSPEC;
+       fl->f_next = 0;
+       fl->f_swapdev = NODEV;
+       fl->f_swapsize = 0;
+       fl->f_needs = 0;
+       fl->f_fn = 0;
+       return (fl);
+}
+
+/*
+ * Add a swap device to the system's configuration
+ */
+mkswap(system, fl, size)
+       struct file_list *system, *fl;
+       int size;
+{
+       register struct file_list **flp;
+       char name[80];
+
+       if (system == 0 || system->f_type != SYSTEMSPEC) {
+               yyerror("\"swap\" spec precedes \"config\" specification");
+               return;
+       }
+       if (size < 0) {
+               yyerror("illegal swap partition size");
+               return;
+       }
+       /*
+        * Append swap description to the end of the list.
+        */
+       flp = &system->f_next;
+       for (; *flp && (*flp)->f_type == SWAPSPEC; flp = &(*flp)->f_next)
+               ;
+       fl->f_next = *flp;
+       *flp = fl;
+       fl->f_swapsize = size;
+       /*
+        * If first swap device for this system,
+        * set up f_fn field to insure swap
+        * files are created with unique names.
+        */
+       if (system->f_fn)
+               return;
+       if (eq(fl->f_fn, "generic"))
+               system->f_fn = ns(fl->f_fn);
        else
        else
-               confp->f_next = fl;
-       confp = fl;
+               system->f_fn = ns(system->f_needs);
 }
 
 /*
 }
 
 /*
@@ -269,13 +624,15 @@ connect(dev, num)
                if ((num != dp->d_unit) || !eq(dev, dp->d_name))
                        continue;
                if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
                if ((num != dp->d_unit) || !eq(dev, dp->d_name))
                        continue;
                if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
-                       yyerror(sprintf(errbuf,
-                           "%s connected to non-controller", dev));
+                       (void) sprintf(errbuf,
+                           "%s connected to non-controller", dev);
+                       yyerror(errbuf);
                        return (0);
                }
                return (dp);
        }
                        return (0);
                }
                return (dp);
        }
-       yyerror(sprintf(errbuf, "%s %d not defined", dev, num));
+       (void) sprintf(errbuf, "%s %d not defined", dev, num);
+       yyerror(errbuf);
        return (0);
 }
 
        return (0);
 }
 
@@ -297,7 +654,8 @@ huhcon(dev)
                if (eq(dp->d_name, dev))
                        break;
        if (dp == 0) {
                if (eq(dp->d_name, dev))
                        break;
        if (dp == 0) {
-               yyerror(sprintf(errbuf, "no %s's to wildcard", dev));
+               (void) sprintf(errbuf, "no %s's to wildcard", dev);
+               yyerror(errbuf);
                return (0);
        }
        oldtype = dp->d_type;
                return (0);
        }
        oldtype = dp->d_type;
@@ -361,15 +719,16 @@ check_nexus(dev, num)
        switch (machine) {
 
        case MACHINE_VAX:
        switch (machine) {
 
        case MACHINE_VAX:
-               if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba"))
-                       yyerror("only uba's and mba's should be connected to the nexus");
+               if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba") &&
+                   !eq(dev->d_name, "bi"))
+                       yyerror("only uba's, mba's, and bi's should be connected to the nexus");
                if (num != QUES)
                        yyerror("can't give specific nexus numbers");
                break;
 
                if (num != QUES)
                        yyerror("can't give specific nexus numbers");
                break;
 
-       case MACHINE_SUN:
-               if (!eq(dev->d_name, "mb"))
-                       yyerror("only mb's should be connected to the nexus");
+       case MACHINE_TAHOE:
+               if (!eq(dev->d_name, "vba")) 
+                       yyerror("only vba's should be connected to the nexus");
                break;
        }
 }
                break;
        }
 }
@@ -385,3 +744,176 @@ check_tz()
        else
                hadtz = 1;
 }
        else
                hadtz = 1;
 }
+
+/*
+ * Check system specification and apply defaulting
+ * rules on root, argument, dump, and swap devices.
+ */
+checksystemspec(fl)
+       register struct file_list *fl;
+{
+       char buf[BUFSIZ];
+       register struct file_list *swap;
+       int generic;
+
+       if (fl == 0 || fl->f_type != SYSTEMSPEC) {
+               yyerror("internal error, bad system specification");
+               exit(1);
+       }
+       swap = fl->f_next;
+       generic = swap && swap->f_type == SWAPSPEC && eq(swap->f_fn, "generic");
+       if (fl->f_rootdev == NODEV && !generic) {
+               yyerror("no root device specified");
+               exit(1);
+       }
+       /*
+        * Default swap area to be in 'b' partition of root's
+        * device.  If root specified to be other than on 'a'
+        * partition, give warning, something probably amiss.
+        */
+       if (swap == 0 || swap->f_type != SWAPSPEC) {
+               dev_t dev;
+
+               swap = newswap();
+               dev = fl->f_rootdev;
+               if (minor(dev) & 07) {
+                       (void) sprintf(buf, 
+"Warning, swap defaulted to 'b' partition with root on '%c' partition",
+                               (minor(dev) & 07) + 'a');
+                       yyerror(buf);
+               }
+               swap->f_swapdev =
+                  makedev(major(dev), (minor(dev) &~ 07) | ('b' - 'a'));
+               swap->f_fn = devtoname(swap->f_swapdev);
+               mkswap(fl, swap, 0);
+       }
+       /*
+        * Make sure a generic swap isn't specified, along with
+        * other stuff (user must really be confused).
+        */
+       if (generic) {
+               if (fl->f_rootdev != NODEV)
+                       yyerror("root device specified with generic swap");
+               if (fl->f_argdev != NODEV)
+                       yyerror("arg device specified with generic swap");
+               if (fl->f_dumpdev != NODEV)
+                       yyerror("dump device specified with generic swap");
+               return;
+       }
+       /*
+        * Default argument device and check for oddball arrangements.
+        */
+       if (fl->f_argdev == NODEV)
+               fl->f_argdev = swap->f_swapdev;
+       if (fl->f_argdev != swap->f_swapdev)
+               yyerror("Warning, arg device different than primary swap");
+       /*
+        * Default dump device and warn if place is not a
+        * swap area or the argument device partition.
+        */
+       if (fl->f_dumpdev == NODEV)
+               fl->f_dumpdev = swap->f_swapdev;
+       if (fl->f_dumpdev != swap->f_swapdev && fl->f_dumpdev != fl->f_argdev) {
+               struct file_list *p = swap->f_next;
+
+               for (; p && p->f_type == SWAPSPEC; p = p->f_next)
+                       if (fl->f_dumpdev == p->f_swapdev)
+                               return;
+               (void) sprintf(buf, "Warning, orphaned dump device, %s",
+                       "do you know what you're doing");
+               yyerror(buf);
+       }
+}
+
+/*
+ * Verify all devices specified in the system specification
+ * are present in the device specifications.
+ */
+verifysystemspecs()
+{
+       register struct file_list *fl;
+       dev_t checked[50], *verifyswap();
+       register dev_t *pchecked = checked;
+
+       for (fl = conf_list; fl; fl = fl->f_next) {
+               if (fl->f_type != SYSTEMSPEC)
+                       continue;
+               if (!finddev(fl->f_rootdev))
+                       deverror(fl->f_needs, "root");
+               *pchecked++ = fl->f_rootdev;
+               pchecked = verifyswap(fl->f_next, checked, pchecked);
+#define        samedev(dev1, dev2) \
+       ((minor(dev1) &~ 07) != (minor(dev2) &~ 07))
+               if (!alreadychecked(fl->f_dumpdev, checked, pchecked)) {
+                       if (!finddev(fl->f_dumpdev))
+                               deverror(fl->f_needs, "dump");
+                       *pchecked++ = fl->f_dumpdev;
+               }
+               if (!alreadychecked(fl->f_argdev, checked, pchecked)) {
+                       if (!finddev(fl->f_argdev))
+                               deverror(fl->f_needs, "arg");
+                       *pchecked++ = fl->f_argdev;
+               }
+       }
+}
+
+/*
+ * Do as above, but for swap devices.
+ */
+dev_t *
+verifyswap(fl, checked, pchecked)
+       register struct file_list *fl;
+       dev_t checked[];
+       register dev_t *pchecked;
+{
+
+       for (;fl && fl->f_type == SWAPSPEC; fl = fl->f_next) {
+               if (eq(fl->f_fn, "generic"))
+                       continue;
+               if (alreadychecked(fl->f_swapdev, checked, pchecked))
+                       continue;
+               if (!finddev(fl->f_swapdev))
+                       fprintf(stderr,
+                          "config: swap device %s not configured", fl->f_fn);
+               *pchecked++ = fl->f_swapdev;
+       }
+       return (pchecked);
+}
+
+/*
+ * Has a device already been checked
+ * for it's existence in the configuration?
+ */
+alreadychecked(dev, list, last)
+       dev_t dev, list[];
+       register dev_t *last;
+{
+       register dev_t *p;
+
+       for (p = list; p < last; p++)
+               if (samedev(*p, dev))
+                       return (1);
+       return (0);
+}
+
+deverror(systemname, devtype)
+       char *systemname, *devtype;
+{
+
+       fprintf(stderr, "config: %s: %s device not configured\n",
+               systemname, devtype);
+}
+
+/*
+ * Look for the device in the list of
+ * configured hardware devices.  Must
+ * take into account stuff wildcarded.
+ */
+/*ARGSUSED*/
+finddev(dev)
+       dev_t dev;
+{
+
+       /* punt on this right now */
+       return (1);
+}