gram.y revision 1.3 1 %{
2 /* $NetBSD: gram.y,v 1.3 2005/09/30 22:51:46 cube Exp $ */
3
4 /*
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This software was developed by the Computer Systems Engineering group
9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10 * contributed to Berkeley.
11 *
12 * All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by the University of
15 * California, Lawrence Berkeley Laboratories.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * from: @(#)gram.y 8.1 (Berkeley) 6/6/93
42 */
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <ctype.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <errno.h>
51 #include "defs.h"
52 #include "sem.h"
53
54 #define FORMAT(n) (((n).fmt == 8 && (n).val != 0) ? "0%llo" : \
55 ((n).fmt == 16) ? "0x%llx" : "%lld")
56
57 #define stop(s) error(s), exit(1)
58
59 static struct config conf; /* at most one active at a time */
60
61 /* the following is used to recover nvlist space after errors */
62 static struct nvlist *alloc[1000];
63 static int adepth;
64 #define new0(n,s,p,i,x) (alloc[adepth++] = newnv(n, s, p, i, x))
65 #define new_n(n) new0(n, NULL, NULL, 0, NULL)
66 #define new_nx(n, x) new0(n, NULL, NULL, 0, x)
67 #define new_ns(n, s) new0(n, s, NULL, 0, NULL)
68 #define new_si(s, i) new0(NULL, s, NULL, i, NULL)
69 #define new_nsi(n,s,i) new0(n, s, NULL, i, NULL)
70 #define new_np(n, p) new0(n, NULL, p, 0, NULL)
71 #define new_s(s) new0(NULL, s, NULL, 0, NULL)
72 #define new_p(p) new0(NULL, NULL, p, 0, NULL)
73 #define new_px(p, x) new0(NULL, NULL, p, 0, x)
74 #define new_sx(s, x) new0(NULL, s, NULL, 0, x)
75
76 #define fx_atom(s) new0(s, NULL, NULL, FX_ATOM, NULL)
77 #define fx_not(e) new0(NULL, NULL, NULL, FX_NOT, e)
78 #define fx_and(e1, e2) new0(NULL, NULL, e1, FX_AND, e2)
79 #define fx_or(e1, e2) new0(NULL, NULL, e1, FX_OR, e2)
80
81 static void cleanup(void);
82 static void setmachine(const char *, const char *, struct nvlist *);
83 static void check_maxpart(void);
84
85 static void app(struct nvlist *, struct nvlist *);
86
87 static struct nvlist *mk_nsis(const char *, int, struct nvlist *, int);
88 static struct nvlist *mk_ns(const char *, struct nvlist *);
89
90 %}
91
92 %union {
93 struct attr *attr;
94 struct devbase *devb;
95 struct deva *deva;
96 struct nvlist *list;
97 const char *str;
98 struct numconst num;
99 int64_t val;
100 }
101
102 %token AND AT ATTACH
103 %token BLOCK BUILD
104 %token CHAR COMPILE_WITH CONFIG
105 %token DEFFS DEFINE DEFOPT DEFPARAM DEFFLAG DEFPSEUDO DEVICE DEVCLASS DUMPS
106 %token DEVICE_MAJOR
107 %token ENDFILE
108 %token XFILE FILE_SYSTEM FLAGS
109 %token IDENT
110 %token XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS MINOR
111 %token NEEDS_COUNT NEEDS_FLAG NO
112 %token XOBJECT ON OPTIONS
113 %token PACKAGE PLUSEQ PREFIX PSEUDO_DEVICE
114 %token ROOT
115 %token SOURCE
116 %token TYPE
117 %token WITH
118 %token <num> NUMBER
119 %token <str> PATHNAME QSTRING WORD EMPTY
120 %token ENDDEFS
121
122 %left '|'
123 %left '&'
124
125 %type <list> fopts fexpr fatom
126 %type <str> fs_spec
127 %type <val> fflgs fflag oflgs oflag
128 %type <str> rule
129 %type <attr> attr
130 %type <devb> devbase
131 %type <deva> devattach_opt
132 %type <list> atlist interface_opt
133 %type <str> atname
134 %type <list> loclist_opt loclist locdef
135 %type <str> locdefault
136 %type <list> values locdefaults
137 %type <list> attrs_opt attrs
138 %type <list> locators locator
139 %type <list> dev_spec
140 %type <str> device_instance
141 %type <str> attachment
142 %type <str> value
143 %type <val> major_minor npseudo
144 %type <num> signed_number
145 %type <val> flags_opt
146 %type <str> deffs
147 %type <list> deffses
148 %type <str> fsoptfile_opt
149 %type <str> defopt
150 %type <list> defopts
151 %type <str> optdep
152 %type <list> optdeps
153 %type <list> defoptdeps
154 %type <str> optfile_opt
155 %type <list> subarches_opt subarches
156 %type <str> filename stringvalue locname mkvarname
157 %type <val> device_major_block device_major_char
158
159 %%
160
161 /*
162 * A configuration consists of a machine type, followed by the machine
163 * definition files (via the include() mechanism), followed by the
164 * configuration specification(s) proper. In effect, this is two
165 * separate grammars, with some shared terminals and nonterminals.
166 * Note that we do not have sufficient keywords to enforce any order
167 * between elements of "topthings" without introducing shift/reduce
168 * conflicts. Instead, check order requirements in the C code.
169 */
170 Configuration:
171 topthings /* dirspecs, include "std.arch" */
172 machine_spec /* "machine foo" from machine descr. */
173 dev_defs ENDDEFS /* all machine definition files */
174 { check_maxpart(); }
175 specs; /* rest of machine description */
176
177 topthings:
178 topthings topthing |
179 /* empty */;
180
181 topthing:
182 SOURCE filename '\n' { if (!srcdir) srcdir = $2; } |
183 BUILD filename '\n' { if (!builddir) builddir = $2; } |
184 '\n';
185
186 machine_spec:
187 XMACHINE WORD '\n' { setmachine($2,NULL,NULL); } |
188 XMACHINE WORD WORD subarches_opt '\n' { setmachine($2,$3,$4); } |
189 error { stop("cannot proceed without machine specifier"); };
190
191 subarches_opt:
192 subarches |
193 /* empty */ { $$ = NULL; };
194
195 subarches:
196 subarches WORD { $$ = new_nx($2, $1); } |
197 WORD { $$ = new_n($1); };
198
199 /*
200 * Various nonterminals shared between the grammars.
201 */
202 file:
203 XFILE filename fopts fflgs rule { addfile($2, $3, $4, $5); };
204
205 object:
206 XOBJECT filename fopts oflgs { addobject($2, $3, $4); };
207
208 device_major:
209 DEVICE_MAJOR WORD device_major_char device_major_block fopts
210 { adddevm($2, $3, $4, $5); };
211
212 device_major_block:
213 BLOCK NUMBER { $$ = $2.val; } |
214 /* empty */ { $$ = -1; };
215
216 device_major_char:
217 CHAR NUMBER { $$ = $2.val; } |
218 /* empty */ { $$ = -1; };
219
220 /* order of options is important, must use right recursion */
221 fopts:
222 fexpr { $$ = $1; } |
223 /* empty */ { $$ = NULL; };
224
225 fexpr:
226 fatom { $$ = $1; } |
227 '!' fatom { $$ = fx_not($2); } |
228 fexpr '&' fexpr { $$ = fx_and($1, $3); } |
229 fexpr '|' fexpr { $$ = fx_or($1, $3); } |
230 '(' fexpr ')' { $$ = $2; };
231
232 fatom:
233 WORD { $$ = fx_atom($1); };
234
235 fflgs:
236 fflgs fflag { $$ = $1 | $2; } |
237 /* empty */ { $$ = 0; };
238
239 fflag:
240 NEEDS_COUNT { $$ = FI_NEEDSCOUNT; } |
241 NEEDS_FLAG { $$ = FI_NEEDSFLAG; };
242
243 oflgs:
244 oflgs oflag { $$ = $1 | $2; } |
245 /* empty */ { $$ = 0; };
246
247 oflag:
248 NEEDS_FLAG { $$ = OI_NEEDSFLAG; };
249
250 rule:
251 COMPILE_WITH stringvalue { $$ = $2; } |
252 /* empty */ { $$ = NULL; };
253
254 prefix:
255 PREFIX filename { prefix_push($2); } |
256 PREFIX { prefix_pop(); };
257
258 /*
259 * The machine definitions grammar.
260 */
261 dev_defs:
262 dev_defs dev_def |
263 dev_defs ENDFILE { enddefs(); checkfiles(); } |
264 /* empty */;
265
266 dev_def:
267 one_def '\n' { adepth = 0; } |
268 '\n' |
269 error '\n' { cleanup(); };
270
271 one_def:
272 file |
273 object |
274 device_major { do_devsw = 1; } |
275 prefix |
276 DEVCLASS WORD { (void)defattr($2, NULL, NULL, 1); } |
277 DEFFS fsoptfile_opt deffses { deffilesystem($2, $3); } |
278 DEFINE WORD interface_opt attrs_opt
279 { (void)defattr($2, $3, $4, 0); } |
280 DEFOPT optfile_opt defopts defoptdeps
281 { defoption($2, $3, $4); } |
282 DEFFLAG optfile_opt defopts defoptdeps
283 { defflag($2, $3, $4); } |
284 DEFPARAM optfile_opt defopts defoptdeps
285 { defparam($2, $3, $4); } |
286 DEVICE devbase interface_opt attrs_opt
287 { defdev($2, $3, $4, 0); } |
288 ATTACH devbase AT atlist devattach_opt attrs_opt
289 { defdevattach($5, $2, $4, $6); } |
290 MAXPARTITIONS NUMBER { maxpartitions = $2.val; } |
291 MAXUSERS NUMBER NUMBER NUMBER { setdefmaxusers($2.val, $3.val, $4.val); } |
292 MAKEOPTIONS condmkopt_list |
293 DEFPSEUDO devbase interface_opt attrs_opt
294 { defdev($2, $3, $4, 1); } |
295 MAJOR '{' majorlist '}';
296
297 atlist:
298 atlist ',' atname { $$ = new_nx($3, $1); } |
299 atname { $$ = new_n($1); };
300
301 atname:
302 WORD { $$ = $1; } |
303 ROOT { $$ = NULL; };
304
305 deffses:
306 deffses deffs { $$ = new_nx($2, $1); } |
307 deffs { $$ = new_n($1); };
308
309 deffs:
310 WORD { $$ = $1; };
311
312 defoptdeps:
313 ':' optdeps { $$ = $2; } |
314 /* empty */ { $$ = NULL; };
315
316 optdeps:
317 optdeps ',' optdep { $$ = new_nx($3, $1); } |
318 optdep { $$ = new_n($1); };
319
320 optdep:
321 WORD { $$ = $1; };
322
323 defopts:
324 defopts defopt { $$ = new_nx($2, $1); } |
325 defopt { $$ = new_n($1); };
326
327 defopt:
328 WORD { $$ = $1; };
329
330 devbase:
331 WORD { $$ = getdevbase($1); };
332
333 devattach_opt:
334 WITH WORD { $$ = getdevattach($2); } |
335 /* empty */ { $$ = NULL; };
336
337 interface_opt:
338 '{' loclist_opt '}' { $$ = new_nx("", $2); } |
339 /* empty */ { $$ = NULL; };
340
341 loclist_opt:
342 loclist { $$ = $1; } |
343 /* empty */ { $$ = NULL; };
344
345 /* loclist order matters, must use right recursion */
346 loclist:
347 locdef ',' loclist { $$ = $1; app($1, $3); } |
348 locdef { $$ = $1; };
349
350 /* "[ WORD locdefault ]" syntax may be unnecessary... */
351 locdef:
352 locname locdefault { $$ = new_nsi($1, $2, 0); } |
353 locname { $$ = new_nsi($1, NULL, 0); } |
354 '[' locname locdefault ']' { $$ = new_nsi($2, $3, 1); } |
355 locname '[' NUMBER ']' { $$ = mk_nsis($1, $3.val, NULL, 0); } |
356 locname '[' NUMBER ']' locdefaults
357 { $$ = mk_nsis($1, $3.val, $5, 0); } |
358 '[' locname '[' NUMBER ']' locdefaults ']'
359 { $$ = mk_nsis($2, $4.val, $6, 1); };
360
361 locname:
362 WORD { $$ = $1; } |
363 QSTRING { $$ = $1; };
364
365 locdefault:
366 '=' value { $$ = $2; };
367
368 locdefaults:
369 '=' '{' values '}' { $$ = $3; };
370
371 fsoptfile_opt:
372 filename { $$ = $1; } |
373 /* empty */ { $$ = NULL; };
374
375 optfile_opt:
376 filename { $$ = $1; } |
377 /* empty */ { $$ = NULL; };
378
379 filename:
380 QSTRING { $$ = $1; } |
381 PATHNAME { $$ = $1; };
382
383 value:
384 QSTRING { $$ = $1; } |
385 WORD { $$ = $1; } |
386 EMPTY { $$ = $1; } |
387 signed_number { char bf[40];
388 (void)snprintf(bf, sizeof(bf),
389 FORMAT($1), (long long)$1.val);
390 $$ = intern(bf); };
391
392 stringvalue:
393 QSTRING { $$ = $1; } |
394 WORD { $$ = $1; };
395
396 values:
397 value ',' values { $$ = new_sx($1, $3); } |
398 value { $$ = new_s($1); };
399
400 signed_number:
401 NUMBER { $$ = $1; } |
402 '-' NUMBER { $$.fmt = $2.fmt; $$.val = -$2.val; };
403
404 attrs_opt:
405 ':' attrs { $$ = $2; } |
406 /* empty */ { $$ = NULL; };
407
408 attrs:
409 attrs ',' attr { $$ = new_px($3, $1); } |
410 attr { $$ = new_p($1); };
411
412 attr:
413 WORD { $$ = getattr($1); };
414
415 majorlist:
416 majorlist ',' majordef |
417 majordef;
418
419 majordef:
420 devbase '=' NUMBER { setmajor($1, $3.val); };
421
422
423 /*
424 * The configuration grammar.
425 */
426 specs:
427 specs spec |
428 /* empty */;
429
430 spec:
431 config_spec '\n' { adepth = 0; } |
432 '\n' |
433 error '\n' { cleanup(); };
434
435 config_spec:
436 one_def |
437 NO FILE_SYSTEM no_fs_list |
438 FILE_SYSTEM fs_list |
439 NO MAKEOPTIONS no_mkopt_list |
440 MAKEOPTIONS mkopt_list |
441 NO OPTIONS no_opt_list |
442 OPTIONS opt_list |
443 MAXUSERS NUMBER { setmaxusers($2.val); } |
444 IDENT stringvalue { setident($2); } |
445 CONFIG conf root_spec sysparam_list
446 { addconf(&conf); } |
447 NO PSEUDO_DEVICE WORD { delpseudo($3); } |
448 PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } |
449 NO device_instance AT attachment
450 { deldevi($2, $4); } |
451 NO DEVICE AT attachment { deldeva($4); } |
452 NO device_instance { deldev($2); } |
453 device_instance AT attachment locators flags_opt
454 { adddev($1, $3, $4, $5); };
455
456 fs_list:
457 fs_list ',' fsoption |
458 fsoption;
459
460 fsoption:
461 WORD { addfsoption($1); };
462
463 no_fs_list:
464 no_fs_list ',' no_fsoption |
465 no_fsoption;
466
467 no_fsoption:
468 WORD { delfsoption($1); };
469
470 mkopt_list:
471 mkopt_list ',' mkoption |
472 mkoption;
473
474 mkvarname:
475 QSTRING { $$ = $1; } |
476 WORD { $$ = $1; };
477
478 mkoption:
479 mkvarname '=' value { addmkoption($1, $3); } |
480 mkvarname PLUSEQ value { appendmkoption($1, $3); };
481
482 condmkopt_list:
483 condmkopt_list ',' condmkoption |
484 condmkoption;
485
486 condmkoption:
487 WORD mkvarname PLUSEQ value { appendcondmkoption($1, $2, $4); };
488
489 no_mkopt_list:
490 no_mkopt_list ',' no_mkoption |
491 no_mkoption;
492
493 no_mkoption:
494 WORD { delmkoption($1); }
495
496 opt_list:
497 opt_list ',' option |
498 option;
499
500 option:
501 WORD { addoption($1, NULL); } |
502 WORD '=' value { addoption($1, $3); };
503
504 no_opt_list:
505 no_opt_list ',' no_option |
506 no_option;
507
508 no_option:
509 WORD { deloption($1); };
510
511 conf:
512 WORD { conf.cf_name = $1;
513 conf.cf_lineno = currentline();
514 conf.cf_fstype = NULL;
515 conf.cf_root = NULL;
516 conf.cf_dump = NULL; };
517
518 root_spec:
519 ROOT on_opt dev_spec fs_spec_opt
520 { setconf(&conf.cf_root, "root", $3); };
521
522 fs_spec_opt:
523 TYPE fs_spec { setfstype(&conf.cf_fstype, $2); } |
524 /* empty */;
525
526 fs_spec:
527 '?' { $$ = intern("?"); } |
528 WORD { $$ = $1; };
529
530 sysparam_list:
531 sysparam_list sysparam |
532 /* empty */;
533
534 sysparam:
535 DUMPS on_opt dev_spec { setconf(&conf.cf_dump, "dumps", $3); };
536
537 dev_spec:
538 '?' { $$ = new_si(intern("?"), NODEV); } |
539 WORD { $$ = new_si($1, NODEV); } |
540 major_minor { $$ = new_si(NULL, $1); };
541
542 major_minor:
543 MAJOR NUMBER MINOR NUMBER { $$ = makedev($2.val, $4.val); };
544
545 on_opt:
546 ON | /* empty */;
547
548 npseudo:
549 NUMBER { $$ = $1.val; } |
550 /* empty */ { $$ = 1; };
551
552 device_instance:
553 WORD '*' { $$ = starref($1); } |
554 WORD { $$ = $1; };
555
556 attachment:
557 ROOT { $$ = NULL; } |
558 WORD '?' { $$ = wildref($1); } |
559 WORD { $$ = $1; };
560
561 locators:
562 locators locator { $$ = $2; app($2, $1); } |
563 /* empty */ { $$ = NULL; };
564
565 locator:
566 WORD values { $$ = mk_ns($1, $2); } |
567 WORD '?' { $$ = new_ns($1, NULL); };
568
569 flags_opt:
570 FLAGS NUMBER { $$ = $2.val; } |
571 /* empty */ { $$ = 0; };
572
573 %%
574
575 void
576 yyerror(const char *s)
577 {
578
579 error("%s", s);
580 }
581
582 /*
583 * Cleanup procedure after syntax error: release any nvlists
584 * allocated during parsing the current line.
585 */
586 static void
587 cleanup(void)
588 {
589 struct nvlist **np;
590 int i;
591
592 for (np = alloc, i = adepth; --i >= 0; np++)
593 nvfree(*np);
594 adepth = 0;
595 }
596
597 static void
598 setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches)
599 {
600 char buf[MAXPATHLEN];
601 struct nvlist *nv;
602
603 machine = mch;
604 machinearch = mcharch;
605 machinesubarches = mchsubarches;
606
607 /*
608 * Set up the file inclusion stack. This empty include tells
609 * the parser there are no more device definitions coming.
610 */
611 strlcpy(buf, _PATH_DEVNULL, sizeof(buf));
612 if (include(buf, ENDDEFS, 0, 0) != 0)
613 exit(1);
614
615 /* Include arch/${MACHINE}/conf/files.${MACHINE} */
616 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
617 machine, machine);
618 if (include(buf, ENDFILE, 0, 0) != 0)
619 exit(1);
620
621 /* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */
622 for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
623 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
624 nv->nv_name, nv->nv_name);
625 if (include(buf, ENDFILE, 0, 0) != 0)
626 exit(1);
627 }
628
629 /* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */
630 if (machinearch != NULL)
631 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
632 machinearch, machinearch);
633 else
634 strlcpy(buf, _PATH_DEVNULL, sizeof(buf));
635 if (include(buf, ENDFILE, 0, 0) != 0)
636 exit(1);
637
638 /*
639 * Include the global conf/files. As the last thing
640 * pushed on the stack, it will be processed first.
641 */
642 if (include("conf/files", ENDFILE, 0, 0) != 0)
643 exit(1);
644
645 oktopackage = 1;
646 }
647
648 static void
649 check_maxpart(void)
650 {
651
652 if (maxpartitions <= 0) {
653 stop("cannot proceed without maxpartitions specifier");
654 }
655 }
656
657 static void
658 app(struct nvlist *p, struct nvlist *q)
659 {
660 while (p->nv_next)
661 p = p->nv_next;
662 p->nv_next = q;
663 }
664
665 static struct nvlist *
666 mk_nsis(const char *name, int count, struct nvlist *adefs, int opt)
667 {
668 struct nvlist *defs = adefs;
669 struct nvlist **p;
670 char buf[200];
671 int i;
672
673 if (count <= 0) {
674 fprintf(stderr, "config: array with <= 0 size: %s\n", name);
675 exit(1);
676 }
677 p = &defs;
678 for(i = 0; i < count; i++) {
679 if (*p == NULL)
680 *p = new_s("0");
681 snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i);
682 (*p)->nv_name = i == 0 ? name : intern(buf);
683 (*p)->nv_int = i > 0 || opt;
684 p = &(*p)->nv_next;
685 }
686 *p = 0;
687 return defs;
688 }
689
690
691 static struct nvlist *
692 mk_ns(const char *name, struct nvlist *vals)
693 {
694 struct nvlist *p;
695 char buf[200];
696 int i;
697
698 for(i = 0, p = vals; p; i++, p = p->nv_next) {
699 snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i);
700 p->nv_name = i == 0 ? name : intern(buf);
701 }
702 return vals;
703 }
704
705