1 %{ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratories. 15 * 16 * %sccs.include.redist.c% 17 * 18 * @(#)gram.y 8.1 (Berkeley) 06/06/93 19 */ 20 21 #include <sys/param.h> 22 #include <ctype.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include "config.h" 26 #include "sem.h" 27 28 #define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x") 29 30 #define stop(s) error(s), exit(1) 31 32 int include __P((const char *, int)); 33 void yyerror __P((const char *)); 34 int yylex __P((void)); 35 extern const char *lastfile; 36 37 static struct config conf; /* at most one active at a time */ 38 39 /* the following is used to recover nvlist space after errors */ 40 static struct nvlist *alloc[1000]; 41 static int adepth; 42 #define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i)) 43 #define new_n(n) new0(n, NULL, NULL, 0) 44 #define new_ns(n, s) new0(n, s, NULL, 0) 45 #define new_si(s, i) new0(NULL, s, NULL, i) 46 #define new_nsi(n,s,i) new0(n, s, NULL, i) 47 #define new_np(n, p) new0(n, NULL, p, 0) 48 #define new_s(s) new0(NULL, s, NULL, 0) 49 #define new_p(p) new0(NULL, NULL, p, 0) 50 51 static void cleanup __P((void)); 52 static void setmachine __P((const char *)); 53 54 %} 55 56 %union { 57 struct attr *attr; 58 struct devbase *devb; 59 struct nvlist *list; 60 const char *str; 61 int val; 62 } 63 64 %token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE 65 %token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MINOR 66 %token ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR 67 %token <val> FFLAG NUMBER 68 %token <str> PATHNAME WORD 69 70 %type <list> fopts 71 %type <val> fflgs 72 %type <str> rule 73 %type <attr> attr 74 %type <devb> devbase 75 %type <list> atlist interface_opt 76 %type <str> atname 77 %type <list> loclist_opt loclist locdef 78 %type <str> locdefault 79 %type <list> veclist_opt veclist 80 %type <list> attrs_opt attrs 81 %type <list> locators locator 82 %type <list> swapdev_list dev_spec 83 %type <str> device_instance 84 %type <str> attachment 85 %type <str> value 86 %type <val> major_minor signed_number npseudo 87 %type <val> flags_opt 88 89 %% 90 91 /* 92 * A configuration consists of a machine type, followed by the machine 93 * definition files (via the include() mechanism), followed by the 94 * configuration specification(s) proper. In effect, this is two 95 * separate grammars, with some shared terminals and nonterminals. 96 */ 97 Configuration: 98 hdrs machine_spec /* "machine foo" from machine descr. */ 99 dev_defs dev_eof /* ../../conf/devices */ 100 dev_defs dev_eof /* devices.foo */ 101 specs; /* rest of machine description */ 102 103 hdrs: 104 hdrs hdr | 105 /* empty */; 106 107 hdr: 108 include | 109 '\n'; 110 111 machine_spec: 112 XMACHINE WORD = { setmachine($2); } | 113 error = { stop("cannot proceed without machine specifier"); }; 114 115 dev_eof: 116 ENDFILE = { enddefs(lastfile); checkfiles(); }; 117 118 119 120 /* 121 * Various nonterminals shared between the grammars. 122 */ 123 file: 124 XFILE PATHNAME fopts fflgs rule = { addfile($2, $3, $4, $5); }; 125 126 /* order of options is important, must use right recursion */ 127 fopts: 128 WORD fopts = { ($$ = new_n($1))->nv_next = $2; } | 129 /* empty */ = { $$ = NULL; }; 130 131 fflgs: 132 fflgs FFLAG = { $$ = $1 | $2; } | 133 /* empty */ = { $$ = 0; }; 134 135 rule: 136 COMPILE_WITH WORD = { $$ = $2; } | 137 /* empty */ = { $$ = NULL; }; 138 139 include: 140 INCLUDE WORD = { (void)include($2, '\n'); }; 141 142 /* 143 * The machine definitions grammar. 144 */ 145 dev_defs: 146 dev_defs dev_def | 147 /* empty */; 148 149 dev_def: 150 one_def '\n' = { adepth = 0; } | 151 '\n' | 152 error '\n' = { cleanup(); }; 153 154 one_def: 155 file | 156 /* include | */ 157 DEFINE WORD interface_opt = { (void)defattr($2, $3); } | 158 DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt 159 = { defdev($2, 0, $4, $5, $6, $7); } | 160 MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } | 161 PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } | 162 MAJOR '{' majorlist '}'; 163 164 atlist: 165 atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } | 166 atname = { $$ = new_n($1); }; 167 168 atname: 169 WORD = { $$ = $1; } | 170 ROOT = { $$ = NULL; }; 171 172 veclist_opt: 173 VECTOR veclist = { $$ = $2; } | 174 /* empty */ = { $$ = NULL; }; 175 176 /* veclist order matters, must use right recursion */ 177 veclist: 178 WORD veclist = { ($$ = new_n($1))->nv_next = $2; } | 179 WORD = { $$ = new_n($1); }; 180 181 devbase: 182 WORD = { $$ = getdevbase($1); }; 183 184 interface_opt: 185 '{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } | 186 /* empty */ = { $$ = NULL; }; 187 188 loclist_opt: 189 loclist = { $$ = $1; } | 190 /* empty */ = { $$ = NULL; }; 191 192 /* loclist order matters, must use right recursion */ 193 loclist: 194 locdef ',' loclist = { ($$ = $1)->nv_next = $3; } | 195 locdef = { $$ = $1; }; 196 197 /* "[ WORD locdefault ]" syntax may be unnecessary... */ 198 locdef: 199 WORD locdefault = { $$ = new_nsi($1, $2, 0); } | 200 WORD = { $$ = new_nsi($1, NULL, 0); } | 201 '[' WORD locdefault ']' = { $$ = new_nsi($2, $3, 1); }; 202 203 locdefault: 204 '=' value = { $$ = $2; }; 205 206 value: 207 WORD = { $$ = $1; } | 208 signed_number = { char bf[40]; 209 (void)sprintf(bf, FORMAT($1), $1); 210 $$ = intern(bf); }; 211 212 signed_number: 213 NUMBER = { $$ = $1; } | 214 '-' NUMBER = { $$ = -$2; }; 215 216 attrs_opt: 217 ':' attrs = { $$ = $2; } | 218 /* empty */ = { $$ = NULL; }; 219 220 attrs: 221 attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } | 222 attr = { $$ = new_p($1); }; 223 224 attr: 225 WORD = { $$ = getattr($1); }; 226 227 majorlist: 228 majorlist ',' majordef | 229 majordef; 230 231 majordef: 232 devbase '=' NUMBER = { setmajor($1, $3); }; 233 234 235 236 /* 237 * The configuration grammar. 238 */ 239 specs: 240 specs spec | 241 /* empty */; 242 243 spec: 244 config_spec '\n' = { adepth = 0; } | 245 '\n' | 246 error '\n' = { cleanup(); }; 247 248 config_spec: 249 file | 250 include | 251 OPTIONS opt_list | 252 MAKEOPTIONS mkopt_list | 253 MAXUSERS NUMBER = { setmaxusers($2); } | 254 CONFIG conf sysparam_list = { addconf(&conf); } | 255 PSEUDO_DEVICE WORD npseudo = { addpseudo($2, $3); } | 256 device_instance AT attachment locators flags_opt 257 = { adddev($1, $3, $4, $5); }; 258 259 mkopt_list: 260 mkopt_list ',' mkoption | 261 mkoption; 262 263 mkoption: 264 WORD '=' value = { addmkoption($1, $3); } 265 266 opt_list: 267 opt_list ',' option | 268 option; 269 270 option: 271 WORD = { addoption($1, NULL); } | 272 WORD '=' value = { addoption($1, $3); }; 273 274 conf: 275 WORD = { conf.cf_name = $1; 276 conf.cf_lineno = currentline(); 277 conf.cf_root = NULL; 278 conf.cf_swap = NULL; 279 conf.cf_dump = NULL; }; 280 281 sysparam_list: 282 sysparam_list sysparam | 283 sysparam; 284 285 sysparam: 286 ROOT on_opt dev_spec = { setconf(&conf.cf_root, "root", $3); } | 287 SWAP on_opt swapdev_list = { setconf(&conf.cf_swap, "swap", $3); } | 288 DUMPS on_opt dev_spec = { setconf(&conf.cf_dump, "dumps", $3); }; 289 290 swapdev_list: 291 dev_spec AND swapdev_list = { ($$ = $1)->nv_next = $3; } | 292 dev_spec = { $$ = $1; }; 293 294 dev_spec: 295 WORD = { $$ = new_si($1, NODEV); } | 296 major_minor = { $$ = new_si(NULL, $1); }; 297 298 major_minor: 299 MAJOR NUMBER MINOR NUMBER = { $$ = makedev($2, $4); }; 300 301 on_opt: 302 ON | /* empty */; 303 304 npseudo: 305 NUMBER = { $$ = $1; } | 306 /* empty */ = { $$ = 1; }; 307 308 device_instance: 309 WORD '*' = { $$ = starref($1); } | 310 WORD = { $$ = $1; }; 311 312 attachment: 313 ROOT = { $$ = NULL; } | 314 WORD '?' = { $$ = wildref($1); } | 315 WORD '*' = { $$ = starref($1); } | 316 WORD = { $$ = $1; }; 317 318 locators: 319 locators locator = { ($$ = $2)->nv_next = $1; } | 320 /* empty */ = { $$ = NULL; }; 321 322 locator: 323 WORD value = { $$ = new_ns($1, $2); } | 324 WORD '?' = { $$ = new_ns($1, NULL); }; 325 326 flags_opt: 327 FLAGS NUMBER = { $$ = $2; } | 328 /* empty */ = { $$ = 0; }; 329 330 %% 331 332 void 333 yyerror(s) 334 const char *s; 335 { 336 337 error("%s", s); 338 } 339 340 /* 341 * Cleanup procedure after syntax error: release any nvlists 342 * allocated during parsing the current line. 343 */ 344 static void 345 cleanup() 346 { 347 register struct nvlist **np; 348 register int i; 349 350 for (np = alloc, i = adepth; --i >= 0; np++) 351 nvfree(*np); 352 adepth = 0; 353 } 354 355 static void 356 setmachine(mch) 357 const char *mch; 358 { 359 char buf[MAXPATHLEN]; 360 361 machine = mch; 362 (void)sprintf(buf, "files.%s", mch); 363 if (include(buf, ENDFILE) || 364 include("../../conf/files.newconf", ENDFILE)) 365 exit(1); 366 } 367