xref: /illumos-gate/usr/src/cmd/fm/fminject/common/inj_grammar.y (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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, Version 1.0 only
7  * (the "License").  You may not use this file except in compliance
8  * with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * FMA Event Injector language parser
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <limits.h>
36 
37 #include <inj.h>
38 #include <inj_err.h>
39 #include <inj_event.h>
40 #include <inj_hash.h>
41 #include <inj_lex.h>
42 
43 %}
44 
45 %union {
46 	inj_decl_t *l_decl;
47 	inj_declmem_t *l_declmem;
48 	inj_defn_t *l_defn;
49 	inj_defnmem_t *l_defnmem;
50 	inj_cmd_t *l_command;
51 	inj_randelem_t *l_randelem;
52 
53 	inj_hash_t *l_hash;
54 
55 	char *l_string;
56 	uint_t l_number;
57 	hrtime_t l_hrtime;
58 }
59 
60 %type	<l_decl>	decl_memlist
61 %type	<l_declmem>	decl_mem
62 %type	<l_declmem>	decl_baremem
63 %type	<l_declmem>	decl_mem_intr
64 %type	<l_number>	decl_intr_type
65 %type	<l_number>	decl_arraydim
66 %type	<l_declmem>	decl_mem_cplx
67 %type	<l_hash>	decl_enumlist
68 
69 %type	<l_defn>	defn_memlist
70 %type	<l_defnmem>	defn_memvals
71 %type	<l_defnmem>	defn_val
72 
73 %type	<l_command>	command
74 %type	<l_command>	cmd_repeatable
75 %type	<l_randelem>	rand_problist
76 %type	<l_randelem>	rand_element
77 
78 %type	<l_defn>	defined_event
79 %type	<l_number>	number
80 %type	<l_hrtime>	hrtime
81 
82 %token	INJ_TOK_EVDEF
83 %token	INJ_TOK_FMRIDEF
84 %token	INJ_TOK_AUTHDEF
85 %token	INJ_TOK_LISTDEF
86 
87 %token	INJ_TOK_INT8
88 %token	INJ_TOK_INT16
89 %token	INJ_TOK_INT32
90 %token	INJ_TOK_INT64
91 %token	INJ_TOK_UINT8
92 %token	INJ_TOK_UINT16
93 %token	INJ_TOK_UINT32
94 %token	INJ_TOK_UINT64
95 %token	INJ_TOK_BOOLEAN
96 %token	INJ_TOK_STRING
97 %token	INJ_TOK_ENUM
98 
99 %token	INJ_TOK_EVENT
100 %token	INJ_TOK_FMRI
101 %token	INJ_TOK_AUTH
102 %token	INJ_TOK_LIST
103 
104 %token	INJ_TOK_ADDHRT
105 %token	INJ_TOK_ENDHRT
106 %token	INJ_TOK_SLEEP
107 %token	INJ_TOK_REPEAT
108 %token	INJ_TOK_RANDOMIZE
109 
110 %token	<l_string> INJ_TOK_IDENT
111 %token	<l_string> INJ_TOK_FMACLASS
112 %token	<l_string> INJ_TOK_IMM
113 %token	<l_string> INJ_TOK_QSTRING
114 
115 %%
116 
117 statement_list:	/* EMPTY */
118 	|	statement_list statement ';'
119 	;
120 
121 statement:	decl
122 	|	defn
123 	|	command {
124 			if ($1 != NULL)
125 				inj_cmds_add($1);
126 		}
127 	;
128 
129 /*
130  * Event, FMRI, Authority, and list declarations
131  */
132 
133 decl:		INJ_TOK_EVDEF INJ_TOK_FMACLASS '{' decl_memlist '}' {
134 			if ($4 != NULL)
135 				inj_decl_finish($4, $2, ITEMTYPE_EVENT);
136 		}
137 	|	INJ_TOK_FMRIDEF INJ_TOK_IDENT '{' decl_memlist '}' {
138 			if ($4 != NULL)
139 				inj_decl_finish($4, $2, ITEMTYPE_FMRI);
140 		}
141 	|	INJ_TOK_AUTHDEF INJ_TOK_IDENT '{' decl_memlist '}' {
142 			if ($4 != NULL)
143 				inj_decl_finish($4, $2, ITEMTYPE_AUTH);
144 		}
145 	|	INJ_TOK_LISTDEF INJ_TOK_IDENT '{' decl_memlist '}' {
146 			if ($4 != NULL)
147 				inj_decl_finish($4, $2, ITEMTYPE_LIST);
148 		}
149 	;
150 
151 decl_memlist:	/* EMPTY */	{ $$ = NULL; }
152 	|	decl_memlist decl_mem ';' {
153 			if ($2 == NULL) {
154 				$$ = $1;
155 			} else if ($1 == NULL) {
156 				$$ = inj_decl_create($2);
157 			} else {
158 				inj_decl_addmem($1, $2);
159 				$$ = $1;
160 			}
161 		}
162 	;
163 
164 decl_mem:	decl_baremem
165 	|	decl_baremem decl_arraydim {
166 			if ($1 != NULL)
167 				inj_decl_mem_make_array($1, $2);
168 			$$ = $1;
169 		}
170 	;
171 
172 decl_baremem:	decl_mem_intr
173 	|	decl_mem_cplx
174 	;
175 
176 decl_mem_intr:	decl_intr_type INJ_TOK_IDENT {
177 			$$ = inj_decl_mem_create($2, $1);
178 		}
179 	;
180 
181 decl_intr_type:	INJ_TOK_INT8		{ $$ = MEMTYPE_INT8; }
182 	|	INJ_TOK_INT16		{ $$ = MEMTYPE_INT16; }
183 	|	INJ_TOK_INT32		{ $$ = MEMTYPE_INT32; }
184 	|	INJ_TOK_INT64		{ $$ = MEMTYPE_INT64; }
185 	|	INJ_TOK_UINT8		{ $$ = MEMTYPE_UINT8; }
186 	|	INJ_TOK_UINT16		{ $$ = MEMTYPE_UINT16; }
187 	|	INJ_TOK_UINT32		{ $$ = MEMTYPE_UINT32; }
188 	|	INJ_TOK_UINT64		{ $$ = MEMTYPE_UINT64; }
189 	|	INJ_TOK_BOOLEAN		{ $$ = MEMTYPE_BOOL; }
190 	|	INJ_TOK_STRING		{ $$ = MEMTYPE_STRING; }
191 	;
192 
193 decl_arraydim:	'[' number ']' {
194 			$$ = $2;
195 		}
196 	|	'[' ']' {
197 			$$ = 0;
198 		}
199 	;
200 
201 decl_mem_cplx:	INJ_TOK_ENUM INJ_TOK_IDENT '{' decl_enumlist '}' {
202 			$$ = inj_decl_mem_create_enum($2, $4);
203 		}
204 	|	INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT {
205 			$$ = inj_decl_mem_create_defined($3, $2,
206 			    ITEMTYPE_EVENT);
207 		}
208 	|	INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT {
209 			$$ = inj_decl_mem_create_defined($3, $2,
210 			    ITEMTYPE_FMRI);
211 		}
212 	|	INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT {
213 			$$ = inj_decl_mem_create_defined($3, $2,
214 			    ITEMTYPE_AUTH);
215 		}
216 	|	INJ_TOK_LIST INJ_TOK_IDENT INJ_TOK_IDENT {
217 			$$ = inj_decl_mem_create_defined($3, $2,
218 			    ITEMTYPE_LIST);
219 		}
220 	;
221 
222 decl_enumlist:	INJ_TOK_IDENT {
223 			$$ = inj_zalloc(sizeof (inj_hash_t));
224 			inj_strhash_create($$);
225 
226 			inj_strhash_insert($$, $1, 1);
227 		}
228 	|	decl_enumlist ',' INJ_TOK_IDENT {
229 			if (inj_strhash_lookup($1, $3) != NULL)
230 				yyerror("duplicate enum value \"%s\"", $3);
231 			else
232 				inj_strhash_insert($1, $3, 1);
233 			$$ = $1;
234 		}
235 	;
236 
237 /*
238  * Event, FMRI, Authority, and list definitions
239  */
240 
241 defn:		INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT '='
242 		    '{' defn_memlist '}' {
243 			inj_defn_finish($6, $2, $3, ITEMTYPE_EVENT);
244 			inj_strfree($2);
245 		}
246 	|	INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT '='
247 		    '{' defn_memlist '}' {
248 			inj_defn_finish($6, $2, $3, ITEMTYPE_FMRI);
249 			inj_strfree($2);
250 		}
251 	|	INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT '='
252 		    '{' defn_memlist '}' {
253 			inj_defn_finish($6, $2, $3, ITEMTYPE_AUTH);
254 			inj_strfree($2);
255 		}
256 	;
257 
258 defn_memlist:	defn_memvals {
259 			$$ = inj_defn_create($1);
260 		}
261 	|	defn_memlist ',' defn_memvals {
262 			inj_defn_addmem($1, $3);
263 			$$ = $1;
264 		}
265 	;
266 
267 defn_memvals:	defn_val
268 	|	INJ_TOK_EVENT INJ_TOK_FMACLASS {
269 			$$ = inj_defn_mem_create($2, DEFNMEM_EVENT);
270 		}
271 	|	INJ_TOK_FMRI INJ_TOK_IDENT {
272 			$$ = inj_defn_mem_create($2, DEFNMEM_FMRI);
273 		}
274 	|	INJ_TOK_AUTH INJ_TOK_IDENT {
275 			$$ = inj_defn_mem_create($2, DEFNMEM_AUTH);
276 		}
277 	|	'[' defn_memlist ']' {
278 			$$ = inj_defn_mem_create_list($2, DEFNMEM_ARRAY);
279 		}
280 	|	'{' defn_memlist '}' {
281 			$$ = inj_defn_mem_create_list($2, DEFNMEM_LIST);
282 		}
283 	;
284 
285 defn_val:	INJ_TOK_IMM {
286 			$$ = inj_defn_mem_create($1, DEFNMEM_IMM);
287 		}
288 	|	INJ_TOK_IDENT {
289 			$$ = inj_defn_mem_create($1, DEFNMEM_IDENT);
290 		}
291 	|	INJ_TOK_QSTRING {
292 			$$ = inj_defn_mem_create($1, DEFNMEM_QSTRING);
293 		}
294 	;
295 
296 /*
297  * Commands
298  */
299 
300 command:	cmd_repeatable
301 	|	INJ_TOK_ADDHRT hrtime { $$ = inj_cmd_addhrt($2); }
302 	|	INJ_TOK_ENDHRT { $$ = inj_cmd_endhrt(); }
303 	|	INJ_TOK_SLEEP number { $$ = inj_cmd_sleep($2); }
304 	|	INJ_TOK_REPEAT number cmd_repeatable {
305 			$$ = ($3 == NULL ? NULL : inj_cmd_repeat($3, $2));
306 		}
307 	;
308 
309 cmd_repeatable:	defined_event {
310 			$$ = ($1 == NULL ? NULL : inj_cmd_send($1));
311 		}
312 	|	INJ_TOK_RANDOMIZE '{' rand_problist '}' {
313 			$$ = ($3 == NULL ? NULL : inj_cmd_rand($3));
314 		}
315 	;
316 
317 rand_problist:	rand_element
318 	|	rand_problist ',' rand_element {
319 			$$ = ($1 == NULL || $3 == NULL) ?
320 			    NULL : inj_rand_add($1, $3);
321 		}
322 	;
323 
324 rand_element:	'{' defined_event ',' number '}' {
325 			$$ = ($2 == NULL ? NULL : inj_rand_create($2, $4));
326 		}
327 	;
328 
329 defined_event:	INJ_TOK_IDENT {
330 			inj_defn_t *ev;
331 
332 			if ((ev = inj_defn_lookup($1, MEMTYPE_EVENT)) ==
333 			    NULL) {
334 				yyerror("unknown event \"%s\"\n", $1);
335 				$$ = NULL;
336 			} else
337 				$$ = ev;
338 		}
339 
340 number:		INJ_TOK_IMM {
341 			u_longlong_t val;
342 
343 			if (inj_strtoull($1, 32, &val) < 0) {
344 				yyerror("invalid number");
345 				$$ = 0;
346 			} else
347 				$$ = (uint32_t)val;
348 		}
349 
350 hrtime:		INJ_TOK_IMM INJ_TOK_IDENT {
351 			longlong_t val;
352 
353 			if (inj_strtoll($1, 64, &val) < 0 ||
354 			    inj_strtime(&val, $2) < 0) {
355 				yyerror("invalid time");
356 				$$ = 0;
357 			} else
358 				$$ = val;
359 		}
360 
361 %%
362 
363 inj_list_t *
364 inj_program_read(const char *file)
365 {
366 	if (strcmp(file, "-") == 0) {
367 		yyin = stdin;
368 		yyinname = "stdin";
369 	} else {
370 		if ((yyin = fopen(file, "r")) == NULL)
371 			die("failed to open %s", file);
372 
373 		yyinname = strrchr(file, '/');
374 		if (yyinname != NULL)
375 			yyinname++;
376 		else
377 			yyinname = file;
378 	}
379 
380 	yyreset();
381 	(void) yyparse();
382 
383 	if (yyin != stdin)
384 		(void) fclose(yyin);
385 
386 	if (yynerrors != 0) {
387 		die("parsing failed - %d error%s\n", yynerrors,
388 		    (yynerrors > 1 ? "s" : ""));
389 	}
390 
391 	return (inj_cmds_get());
392 }
393