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