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 2004 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 86 %token INJ_TOK_INT8 87 %token INJ_TOK_INT16 88 %token INJ_TOK_INT32 89 %token INJ_TOK_INT64 90 %token INJ_TOK_UINT8 91 %token INJ_TOK_UINT16 92 %token INJ_TOK_UINT32 93 %token INJ_TOK_UINT64 94 %token INJ_TOK_BOOLEAN 95 %token INJ_TOK_STRING 96 %token INJ_TOK_ENUM 97 98 %token INJ_TOK_EVENT 99 %token INJ_TOK_FMRI 100 %token INJ_TOK_AUTH 101 102 %token INJ_TOK_ADDHRT 103 %token INJ_TOK_ENDHRT 104 %token INJ_TOK_SLEEP 105 %token INJ_TOK_REPEAT 106 %token INJ_TOK_RANDOMIZE 107 108 %token <l_string> INJ_TOK_IDENT 109 %token <l_string> INJ_TOK_FMACLASS 110 %token <l_string> INJ_TOK_IMM 111 %token <l_string> INJ_TOK_QSTRING 112 113 %% 114 115 statement_list: /* EMPTY */ 116 | statement_list statement ';' 117 ; 118 119 statement: decl 120 | defn 121 | command { 122 if ($1 != NULL) 123 inj_cmds_add($1); 124 } 125 ; 126 127 /* 128 * Event, FMRI, Authority declarations 129 */ 130 131 decl: INJ_TOK_EVDEF INJ_TOK_FMACLASS '{' decl_memlist '}' { 132 if ($4 != NULL) 133 inj_decl_finish($4, $2, ITEMTYPE_EVENT); 134 } 135 | INJ_TOK_FMRIDEF INJ_TOK_IDENT '{' decl_memlist '}' { 136 if ($4 != NULL) 137 inj_decl_finish($4, $2, ITEMTYPE_FMRI); 138 } 139 | INJ_TOK_AUTHDEF INJ_TOK_IDENT '{' decl_memlist '}' { 140 if ($4 != NULL) 141 inj_decl_finish($4, $2, ITEMTYPE_AUTH); 142 } 143 ; 144 145 decl_memlist: /* EMPTY */ { $$ = NULL; } 146 | decl_memlist decl_mem ';' { 147 if ($2 == NULL) { 148 $$ = $1; 149 } else if ($1 == NULL) { 150 $$ = inj_decl_create($2); 151 } else { 152 inj_decl_addmem($1, $2); 153 $$ = $1; 154 } 155 } 156 ; 157 158 decl_mem: decl_baremem 159 | decl_baremem decl_arraydim { 160 if ($1 != NULL) 161 inj_decl_mem_make_array($1, $2); 162 $$ = $1; 163 } 164 ; 165 166 decl_baremem: decl_mem_intr 167 | decl_mem_cplx 168 ; 169 170 decl_mem_intr: decl_intr_type INJ_TOK_IDENT { 171 $$ = inj_decl_mem_create($2, $1); 172 } 173 ; 174 175 decl_intr_type: INJ_TOK_INT8 { $$ = MEMTYPE_INT8; } 176 | INJ_TOK_INT16 { $$ = MEMTYPE_INT16; } 177 | INJ_TOK_INT32 { $$ = MEMTYPE_INT32; } 178 | INJ_TOK_INT64 { $$ = MEMTYPE_INT64; } 179 | INJ_TOK_UINT8 { $$ = MEMTYPE_UINT8; } 180 | INJ_TOK_UINT16 { $$ = MEMTYPE_UINT16; } 181 | INJ_TOK_UINT32 { $$ = MEMTYPE_UINT32; } 182 | INJ_TOK_UINT64 { $$ = MEMTYPE_UINT64; } 183 | INJ_TOK_BOOLEAN { $$ = MEMTYPE_BOOL; } 184 | INJ_TOK_STRING { $$ = MEMTYPE_STRING; } 185 ; 186 187 decl_arraydim: '[' number ']' { 188 $$ = $2; 189 } 190 | '[' ']' { 191 $$ = 0; 192 } 193 ; 194 195 decl_mem_cplx: INJ_TOK_ENUM INJ_TOK_IDENT '{' decl_enumlist '}' { 196 $$ = inj_decl_mem_create_enum($2, $4); 197 } 198 | INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT { 199 $$ = inj_decl_mem_create_defined($3, $2, 200 ITEMTYPE_EVENT); 201 } 202 | INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT { 203 $$ = inj_decl_mem_create_defined($3, $2, 204 ITEMTYPE_FMRI); 205 } 206 | INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT { 207 $$ = inj_decl_mem_create_defined($3, $2, 208 ITEMTYPE_AUTH); 209 } 210 ; 211 212 decl_enumlist: INJ_TOK_IDENT { 213 $$ = inj_zalloc(sizeof (inj_hash_t)); 214 inj_strhash_create($$); 215 216 inj_strhash_insert($$, $1, 1); 217 } 218 | decl_enumlist ',' INJ_TOK_IDENT { 219 if (inj_strhash_lookup($1, $3) != NULL) 220 yyerror("duplicate enum value \"%s\"", $3); 221 else 222 inj_strhash_insert($1, $3, 1); 223 $$ = $1; 224 } 225 ; 226 227 /* 228 * Event, FMRI, Authority definitions 229 */ 230 231 defn: INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT '=' 232 '{' defn_memlist '}' { 233 inj_defn_finish($6, $2, $3, ITEMTYPE_EVENT); 234 inj_strfree($2); 235 } 236 | INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT '=' 237 '{' defn_memlist '}' { 238 inj_defn_finish($6, $2, $3, ITEMTYPE_FMRI); 239 inj_strfree($2); 240 } 241 | INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT '=' 242 '{' defn_memlist '}' { 243 inj_defn_finish($6, $2, $3, ITEMTYPE_AUTH); 244 inj_strfree($2); 245 } 246 ; 247 248 defn_memlist: defn_memvals { 249 $$ = inj_defn_create($1); 250 } 251 | defn_memlist ',' defn_memvals { 252 inj_defn_addmem($1, $3); 253 $$ = $1; 254 } 255 ; 256 257 defn_memvals: defn_val 258 | INJ_TOK_EVENT INJ_TOK_FMACLASS { 259 $$ = inj_defn_mem_create($2, DEFNMEM_EVENT); 260 } 261 | INJ_TOK_FMRI INJ_TOK_IDENT { 262 $$ = inj_defn_mem_create($2, DEFNMEM_FMRI); 263 } 264 | INJ_TOK_AUTH INJ_TOK_IDENT { 265 $$ = inj_defn_mem_create($2, DEFNMEM_AUTH); 266 } 267 | '[' defn_memlist ']' { 268 $$ = inj_defn_mem_create_list($2, DEFNMEM_ARRAY); 269 } 270 | '{' defn_memlist '}' { 271 $$ = inj_defn_mem_create_list($2, DEFNMEM_SUBLIST); 272 } 273 ; 274 275 defn_val: INJ_TOK_IMM { 276 $$ = inj_defn_mem_create($1, DEFNMEM_IMM); 277 } 278 | INJ_TOK_IDENT { 279 $$ = inj_defn_mem_create($1, DEFNMEM_IDENT); 280 } 281 | INJ_TOK_QSTRING { 282 $$ = inj_defn_mem_create($1, DEFNMEM_QSTRING); 283 } 284 ; 285 286 /* 287 * Commands 288 */ 289 290 command: cmd_repeatable 291 | INJ_TOK_ADDHRT hrtime { $$ = inj_cmd_addhrt($2); } 292 | INJ_TOK_ENDHRT { $$ = inj_cmd_endhrt(); } 293 | INJ_TOK_SLEEP number { $$ = inj_cmd_sleep($2); } 294 | INJ_TOK_REPEAT number cmd_repeatable { 295 $$ = ($3 == NULL ? NULL : inj_cmd_repeat($3, $2)); 296 } 297 ; 298 299 cmd_repeatable: defined_event { 300 $$ = ($1 == NULL ? NULL : inj_cmd_send($1)); 301 } 302 | INJ_TOK_RANDOMIZE '{' rand_problist '}' { 303 $$ = ($3 == NULL ? NULL : inj_cmd_rand($3)); 304 } 305 ; 306 307 rand_problist: rand_element 308 | rand_problist ',' rand_element { 309 $$ = ($1 == NULL || $3 == NULL) ? 310 NULL : inj_rand_add($1, $3); 311 } 312 ; 313 314 rand_element: '{' defined_event ',' number '}' { 315 $$ = ($2 == NULL ? NULL : inj_rand_create($2, $4)); 316 } 317 ; 318 319 defined_event: INJ_TOK_IDENT { 320 inj_defn_t *ev; 321 322 if ((ev = inj_defn_lookup($1, MEMTYPE_EVENT)) == 323 NULL) { 324 yyerror("unknown event \"%s\"\n", $1); 325 $$ = NULL; 326 } else 327 $$ = ev; 328 } 329 330 number: INJ_TOK_IMM { 331 u_longlong_t val; 332 333 if (inj_strtoull($1, 32, &val) < 0) { 334 yyerror("invalid number"); 335 $$ = 0; 336 } else 337 $$ = (uint32_t)val; 338 } 339 340 hrtime: INJ_TOK_IMM INJ_TOK_IDENT { 341 longlong_t val; 342 343 if (inj_strtoll($1, 64, &val) < 0 || 344 inj_strtime(&val, $2) < 0) { 345 yyerror("invalid time"); 346 $$ = 0; 347 } else 348 $$ = val; 349 } 350 351 %% 352 353 inj_list_t * 354 inj_program_read(const char *file) 355 { 356 if (strcmp(file, "-") == 0) { 357 yyin = stdin; 358 yyinname = "stdin"; 359 } else { 360 if ((yyin = fopen(file, "r")) == NULL) 361 die("failed to open %s", file); 362 363 if ((yyinname = strrchr(file, '/')) == NULL) 364 yyinname = file; 365 } 366 367 yyreset(); 368 (void) yyparse(); 369 370 if (yyin != stdin) 371 (void) fclose(yyin); 372 373 if (yynerrors != 0) { 374 die("parsing failed - %d error%s\n", yynerrors, 375 (yynerrors > 1 ? "s" : "")); 376 } 377 378 return (inj_cmds_get()); 379 } 380