1 %{
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <assert.h>
28 #include <string.h>
29 #include <libintl.h>
30 #include "zonecfg.h"
31 #include "zonecfg_grammar.tab.h"
32
33 /*
34 * This constant defines the number of entries added to unclaimed_tokens[]
35 * when it runs out of space.
36 */
37 #define UNCLAIMED_TOKENS_BUFFER_GROWTH 4
38
39 /*
40 * Invariants:
41 *
42 * unclaimed_tokens == NULL IFF unclaimed_tokens_size == 0
43 * unclaimed_tokens_size == 0 IFF num_unclaimed_tokens == 0
44 */
45 static char **unclaimed_tokens; /* TOKENs produced by Lex (see below) */
46 /* but not claimed by YACC reduction */
47 /* rules */
48 static unsigned int unclaimed_tokens_size; /* size of unclaimed_tokens */
49 static unsigned int num_unclaimed_tokens; /* number of unclaimed TOKENs */
50
51 int lex_lineno = 1; /* line number for error reporting */
52 static int state = INITIAL;
53 extern boolean_t cmd_file_mode;
54 extern boolean_t saw_error;
55 extern void yyerror(char *s);
56
57 static char *create_token(char *s);
58 %}
59
60 %a 8000
61 %p 5000
62 %e 2000
63 %n 1000
64 %o 13000
65
66 %{
67 /*
68 * The three states below are for tokens, lists and complex property values.
69 * Note that simple property values are a subset of tokens.
70 */
71 %}
72 %s TSTATE
73 %s LSTATE
74 %s CSTATE
75 %%
76
77 <INITIAL>"#"[^\n]* { }
78
79 <INITIAL>add {
80 BEGIN TSTATE;
81 state = TSTATE;
82 return ADD;
83 }
84
85 <INITIAL>cancel {
86 BEGIN TSTATE;
87 state = TSTATE;
88 return CANCEL;
89 }
90
91 <INITIAL>commit {
92 BEGIN TSTATE;
93 state = TSTATE;
94 return COMMIT;
95 }
96
97 <INITIAL>create {
98 BEGIN TSTATE;
99 state = TSTATE;
100 return CREATE;
101 }
102
103 <INITIAL>delete {
104 BEGIN TSTATE;
105 state = TSTATE;
106 return DELETE;
107 }
108
109 <INITIAL>end {
110 BEGIN TSTATE;
111 state = TSTATE;
112 return END;
113 }
114
115 <INITIAL>exit {
116 BEGIN TSTATE;
117 state = TSTATE;
118 return EXIT;
119 }
120
121 <INITIAL>export {
122 BEGIN TSTATE;
123 state = TSTATE;
124 return EXPORT;
125 }
126
127 <INITIAL>"?"|help {
128 BEGIN TSTATE;
129 state = TSTATE;
130 return HELP;
131 }
132
133 <INITIAL>info {
134 BEGIN TSTATE;
135 state = TSTATE;
136 return INFO;
137 }
138
139 <INITIAL>remove {
140 BEGIN TSTATE;
141 state = TSTATE;
142 return REMOVE;
143 }
144
145 <INITIAL>revert {
146 BEGIN TSTATE;
147 state = TSTATE;
148 return REVERT;
149 }
150
151 <INITIAL>select {
152 BEGIN TSTATE;
153 state = TSTATE;
154 return SELECT;
155 }
156
157 <INITIAL>set {
158 BEGIN TSTATE;
159 state = TSTATE;
160 return SET;
161 }
162
163 <INITIAL>clear {
164 BEGIN TSTATE;
165 state = TSTATE;
166 return CLEAR;
167 }
168
169 <INITIAL>verify {
170 BEGIN TSTATE;
171 state = TSTATE;
172 return VERIFY;
173 }
174
175 <TSTATE>net { return NET; }
176
177 <TSTATE>fs { return FS; }
178
179 <TSTATE>device { return DEVICE; }
180
181 <TSTATE>rctl { return RCTL; }
182
183 <TSTATE>attr { return ATTR; }
184
185 <TSTATE>admin { return ADMIN; }
186
187 <TSTATE>zonename { return ZONENAME; }
188 <CSTATE>zonename { return ZONENAME; }
189
190 <TSTATE>dataset { return DATASET; }
191
192 <TSTATE>dedicated-cpu { return PSET; }
193
194 <TSTATE>capped-cpu { return PCAP; }
195
196 <TSTATE>capped-memory { return MCAP; }
197
198 <TSTATE>zonepath { return ZONEPATH; }
199 <CSTATE>zonepath { return ZONEPATH; }
200
201 <TSTATE>brand { return BRAND; }
202 <CSTATE>brand { return BRAND; }
203
204 <TSTATE>autoboot { return AUTOBOOT; }
205 <CSTATE>autoboot { return AUTOBOOT; }
206
207 <TSTATE>ip-type { return IPTYPE; }
208 <CSTATE>ip-type { return IPTYPE; }
209
210 <TSTATE>pool { return POOL; }
211 <CSTATE>pool { return POOL; }
212
213 <TSTATE>limitpriv { return LIMITPRIV; }
214 <CSTATE>limitpriv { return LIMITPRIV; }
215
216 <TSTATE>bootargs { return BOOTARGS; }
217 <CSTATE>bootargs { return BOOTARGS; }
218
219 <TSTATE>type { return TYPE; }
220 <CSTATE>type { return TYPE; }
221
222 <TSTATE>value { return VALUE; }
223 <CSTATE>value { return VALUE; }
224
225 <TSTATE>options { return OPTIONS; }
226 <CSTATE>options { return OPTIONS; }
227
228 <TSTATE>allowed-address { return ALLOWED_ADDRESS; }
229 <CSTATE>allowed-address { return ALLOWED_ADDRESS; }
230
231 <TSTATE>address { return ADDRESS; }
232 <CSTATE>address { return ADDRESS; }
233
234 <TSTATE>physical { return PHYSICAL; }
235 <CSTATE>physical { return PHYSICAL; }
236
237 <TSTATE>defrouter { return DEFROUTER; }
238 <CSTATE>defrouter { return DEFROUTER; }
239
240 <TSTATE>mac-addr { return MAC; }
241 <CSTATE>mac-addr { return MAC; }
242
243 <TSTATE>vlan-id { return VLANID; }
244 <CSTATE>vlan-id { return VLANID; }
245
246 <TSTATE>global-nic { return GNIC; }
247 <CSTATE>global-nic { return GNIC; }
248
249 <TSTATE>property { return NPROP; }
250 <CSTATE>property { return NPROP; }
251
252 <TSTATE>dir { return DIR; }
253 <CSTATE>dir { return DIR; }
254
255 <TSTATE>special { return SPECIAL; }
256 <CSTATE>special { return SPECIAL; }
257
258 <TSTATE>raw { return RAW; }
259 <CSTATE>raw { return RAW; }
260
261 <TSTATE>name { return NAME; }
262 <CSTATE>name { return NAME; }
263
264 <TSTATE>match { return MATCH; }
265 <CSTATE>match { return MATCH; }
266
267 <TSTATE>priv { return PRIV; }
268 <CSTATE>priv { return PRIV; }
269
270 <TSTATE>limit { return LIMIT; }
271 <CSTATE>limit { return LIMIT; }
272
273 <TSTATE>action { return ACTION; }
274 <CSTATE>action { return ACTION; }
275
276 <TSTATE>ncpus { return NCPUS; }
277 <CSTATE>ncpus { return NCPUS; }
278
279 <TSTATE>locked { return LOCKED; }
280 <CSTATE>locked { return LOCKED; }
281
282 <TSTATE>swap { return SWAP; }
283 <CSTATE>swap { return SWAP; }
284
285 <TSTATE>importance { return IMPORTANCE; }
286 <CSTATE>importance { return IMPORTANCE; }
287
288 <TSTATE>cpu-shares { return SHARES; }
289 <CSTATE>cpu-shares { return SHARES; }
290
291 <TSTATE>max-lwps { return MAXLWPS; }
292 <CSTATE>max-lwps { return MAXLWPS; }
293
294 <TSTATE>max-processes { return MAXPROCS; }
295 <CSTATE>max-processes { return MAXPROCS; }
296
297 <TSTATE>max-shm-memory { return MAXSHMMEM; }
298 <CSTATE>max-shm-memory { return MAXSHMMEM; }
299
300 <TSTATE>max-shm-ids { return MAXSHMIDS; }
301 <CSTATE>max-shm-ids { return MAXSHMIDS; }
302
303 <TSTATE>max-msg-ids { return MAXMSGIDS; }
304 <CSTATE>max-msg-ids { return MAXMSGIDS; }
305
306 <TSTATE>max-sem-ids { return MAXSEMIDS; }
307 <CSTATE>max-sem-ids { return MAXSEMIDS; }
308
309 <TSTATE>scheduling-class { return SCHED; }
310 <CSTATE>scheduling-class { return SCHED; }
311
312 <TSTATE>hostid { return HOSTID; }
313 <CSTATE>hostid { return HOSTID; }
314
315 <TSTATE>user { return USER; }
316 <CSTATE>user { return USER; }
317
318 <TSTATE>auths { return AUTHS; }
319 <CSTATE>auths { return AUTHS; }
320
321 <TSTATE>fs-allowed { return FS_ALLOWED; }
322 <CSTATE>fs-allowed { return FS_ALLOWED; }
323
324 <TSTATE>= { return EQUAL; }
325 <LSTATE>= { return EQUAL; }
326 <CSTATE>= { return EQUAL; }
327
328 <TSTATE>"[" {
329 BEGIN LSTATE;
330 state = LSTATE;
331 return OPEN_SQ_BRACKET;
332 }
333
334 <LSTATE>"]" {
335 BEGIN TSTATE;
336 state = TSTATE;
337 return CLOSE_SQ_BRACKET;
338 }
339
340 <TSTATE>"(" {
341 BEGIN CSTATE;
342 return OPEN_PAREN;
343 }
344
345 <LSTATE>"(" {
346 BEGIN CSTATE;
347 return OPEN_PAREN;
348 }
349
350 <CSTATE>")" {
351 BEGIN state;
352 return CLOSE_PAREN;
353 }
354
355 <LSTATE>"," { return COMMA; }
356 <CSTATE>"," { return COMMA; }
357
358 <TSTATE>[^ \t\n\";=\[\]\(\)]+ {
359 yylval.strval = create_token(yytext);
360 return TOKEN;
361 }
362
363 <LSTATE>[^ \t\n\",;=\[\]\(\)]+ {
364 yylval.strval = create_token(yytext);
365 return TOKEN;
366 }
367
368 <CSTATE>[^ \t\n\",;=\(\)]+ {
369 yylval.strval = create_token(yytext);
370 return TOKEN;
371 }
372
373 <CSTATE>\"[^\"\n]*[\"\n] {
374 yylval.strval = create_token(yytext + 1);
375 if (yylval.strval[yyleng - 2] == '"')
376 yylval.strval[yyleng - 2] = 0;
377 return TOKEN;
378 }
379
380 <TSTATE>\"[^\"\n]*[\"\n] {
381 yylval.strval = create_token(yytext + 1);
382 if (yylval.strval[yyleng - 2] == '"')
383 yylval.strval[yyleng - 2] = 0;
384 return TOKEN;
385 }
386
387 <LSTATE>\"[^\"\n]*[\"\n] {
388 yylval.strval = create_token(yytext + 1);
389 if (yylval.strval[yyleng - 2] == '"')
390 yylval.strval[yyleng - 2] = 0;
391 return TOKEN;
392 }
393
394 ";" {
395 BEGIN INITIAL;
396 return (yytext[0]);
397 }
398
399 \n {
400 lex_lineno++;
401 BEGIN INITIAL;
402 return (yytext[0]);
403 }
404
405 [ \t] ; /* Ignore whitespace */
406
407 . {
408 return (yytext[0]);
409 }
410
411 %%
412
413 /*
414 * Assert that there are no unclaimed tokens. This function enforces the
415 * invariants mentioned at the top of this file.
416 */
417 void
418 assert_no_unclaimed_tokens(void)
419 {
420 assert(num_unclaimed_tokens == 0);
421 assert(unclaimed_tokens == NULL);
422 assert(unclaimed_tokens_size == 0);
423 }
424
425 /*
426 * Claim the specified unclaimed TOKEN. YACC reduction rules that
427 * use TOKENs should invoke this function immediately before freeing the TOKENs
428 * or adding them to data structures that will be cleaned up when the YACC
429 * parser finishes or encounters errors. Reduction rules should only claim the
430 * TOKENs that they use.
431 *
432 * This function returns its argument but does not free its memory.
433 */
434 char *
435 claim_token(char *token)
436 {
437 unsigned int index;
438
439 /*
440 * Find the token in the list of unclaimed tokens.
441 */
442 assert(num_unclaimed_tokens > 0);
443 for (index = 0; index < num_unclaimed_tokens; index++) {
444 if (unclaimed_tokens[index] == token)
445 break;
446 }
447
448 /*
449 * Abort if we didn't find the token.
450 */
451 assert(index != num_unclaimed_tokens);
452
453 /*
454 * Replace the token with the last unclaimed token.
455 */
456 num_unclaimed_tokens--;
457 unclaimed_tokens[index] = unclaimed_tokens[num_unclaimed_tokens];
458
459 /*
460 * Delete the list of unclaimed tokens if it's empty.
461 */
462 if (num_unclaimed_tokens == 0) {
463 free(unclaimed_tokens);
464 unclaimed_tokens = NULL;
465 unclaimed_tokens_size = 0;
466 }
467
468 return (token);
469 }
470
471 /*
472 * Free all unclaimed TOKENs. This should only be invoked when the YACC
473 * parser encounters errors.
474 */
475 static void
476 free_tokens(void)
477 {
478 if (unclaimed_tokens != NULL) {
479 while (num_unclaimed_tokens > 0)
480 free(unclaimed_tokens[--num_unclaimed_tokens]);
481 free(unclaimed_tokens);
482 unclaimed_tokens = NULL;
483 unclaimed_tokens_size = 0;
484 }
485 assert_no_unclaimed_tokens();
486 }
487
488 /*
489 * Create a TOKEN from the specified string. The TOKEN is merely a duplicate
490 * of the specified string. TOKENs must be claimed by the YACC reduction rules
491 * that use them; see claim_token() above.
492 */
493 char *
494 create_token(char *s)
495 {
496 char *result;
497
498 if ((result = strdup(s)) == NULL) {
499 yyerror("Out of memory");
500 exit(Z_ERR);
501 }
502
503 /*
504 * Add the new TOKEN to the list of unclaimed TOKENs. The list might
505 * have to be resized.
506 *
507 * Reduction rules should claim TOKENs via claim_token() (see above).
508 */
509 if (num_unclaimed_tokens == unclaimed_tokens_size) {
510 char **new_unclaimed_tokens;
511
512 unclaimed_tokens_size += UNCLAIMED_TOKENS_BUFFER_GROWTH;
513 new_unclaimed_tokens = (char **)realloc(unclaimed_tokens,
514 unclaimed_tokens_size * sizeof (char *));
515 if (new_unclaimed_tokens == NULL) {
516 yyerror("Out of memory");
517 free(result);
518 exit(Z_ERR);
519 }
520 unclaimed_tokens = new_unclaimed_tokens;
521 }
522 unclaimed_tokens[num_unclaimed_tokens] = result;
523 num_unclaimed_tokens++;
524 return (result);
525 }
526
527 void
528 yyerror(char *s)
529 {
530 /*
531 * Ensure that we won't leak unclaimed tokens.
532 */
533 free_tokens();
534
535 /* feof(yyin) is not an error; anything else is, so we set saw_error */
536 if (yytext[0] == '\0') {
537 if (!feof(yyin)) {
538 saw_error = B_TRUE;
539 (void) fprintf(stderr, gettext("%s, token expected\n"),
540 s);
541 }
542 return;
543 }
544
545 saw_error = B_TRUE;
546 if (cmd_file_mode)
547 (void) fprintf(stderr, gettext("%s on line %d at '%s'\n"), s,
548 lex_lineno, (yytext[0] == '\n') ? "\\n" : yytext);
549 else
550 (void) fprintf(stderr, gettext("%s at '%s'\n"), s,
551 (yytext[0] == '\n') ? "\\n" : yytext);
552 usage(B_FALSE, HELP_SUBCMDS);
553 }