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 /* 28 * FMA Event Injector language parser 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <limits.h> 34 35 #include <inj.h> 36 #include <inj_err.h> 37 #include <inj_event.h> 38 #include <inj_hash.h> 39 #include <inj_lex.h> 40 41 %} 42 43 %union { 44 inj_decl_t *l_decl; 45 inj_declmem_t *l_declmem; 46 inj_defn_t *l_defn; 47 inj_defnmem_t *l_defnmem; 48 inj_cmd_t *l_command; 49 inj_randelem_t *l_randelem; 50 51 inj_hash_t *l_hash; 52 53 char *l_string; 54 uint_t l_number; 55 hrtime_t l_hrtime; 56 } 57 58 %type <l_decl> decl_memlist 59 %type <l_declmem> decl_mem 60 %type <l_declmem> decl_baremem 61 %type <l_declmem> decl_mem_intr 62 %type <l_number> decl_intr_type 63 %type <l_number> decl_arraydim 64 %type <l_declmem> decl_mem_cplx 65 %type <l_hash> decl_enumlist 66 67 %type <l_defn> defn_memlist 68 %type <l_defnmem> defn_memvals 69 %type <l_defnmem> defn_val 70 71 %type <l_command> command 72 %type <l_command> cmd_repeatable 73 %type <l_randelem> rand_problist 74 %type <l_randelem> rand_element 75 76 %type <l_defn> defined_event 77 %type <l_number> number 78 %type <l_hrtime> hrtime 79 80 %token INJ_TOK_EVDEF 81 %token INJ_TOK_FMRIDEF 82 %token INJ_TOK_AUTHDEF 83 %token INJ_TOK_LISTDEF 84 85 %token INJ_TOK_INT8 86 %token INJ_TOK_INT16 87 %token INJ_TOK_INT32 88 %token INJ_TOK_INT64 89 %token INJ_TOK_UINT8 90 %token INJ_TOK_UINT16 91 %token INJ_TOK_UINT32 92 %token INJ_TOK_UINT64 93 %token INJ_TOK_BOOLEAN 94 %token INJ_TOK_STRING 95 %token INJ_TOK_ENUM 96 97 %token INJ_TOK_EVENT 98 %token INJ_TOK_FMRI 99 %token INJ_TOK_AUTH 100 %token INJ_TOK_LIST 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, and list 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 | INJ_TOK_LISTDEF INJ_TOK_IDENT '{' decl_memlist '}' { 144 if ($4 != NULL) 145 inj_decl_finish($4, $2, ITEMTYPE_LIST); 146 } 147 ; 148 149 decl_memlist: /* EMPTY */ { $$ = NULL; } 150 | decl_memlist decl_mem ';' { 151 if ($2 == NULL) { 152 $$ = $1; 153 } else if ($1 == NULL) { 154 $$ = inj_decl_create($2); 155 } else { 156 inj_decl_addmem($1, $2); 157 $$ = $1; 158 } 159 } 160 ; 161 162 decl_mem: decl_baremem 163 | decl_baremem decl_arraydim { 164 if ($1 != NULL) 165 inj_decl_mem_make_array($1, $2); 166 $$ = $1; 167 } 168 ; 169 170 decl_baremem: decl_mem_intr 171 | decl_mem_cplx 172 ; 173 174 decl_mem_intr: decl_intr_type INJ_TOK_IDENT { 175 $$ = inj_decl_mem_create($2, $1); 176 } 177 ; 178 179 decl_intr_type: INJ_TOK_INT8 { $$ = MEMTYPE_INT8; } 180 | INJ_TOK_INT16 { $$ = MEMTYPE_INT16; } 181 | INJ_TOK_INT32 { $$ = MEMTYPE_INT32; } 182 | INJ_TOK_INT64 { $$ = MEMTYPE_INT64; } 183 | INJ_TOK_UINT8 { $$ = MEMTYPE_UINT8; } 184 | INJ_TOK_UINT16 { $$ = MEMTYPE_UINT16; } 185 | INJ_TOK_UINT32 { $$ = MEMTYPE_UINT32; } 186 | INJ_TOK_UINT64 { $$ = MEMTYPE_UINT64; } 187 | INJ_TOK_BOOLEAN { $$ = MEMTYPE_BOOL; } 188 | INJ_TOK_STRING { $$ = MEMTYPE_STRING; } 189 ; 190 191 decl_arraydim: '[' number ']' { 192 $$ = $2; 193 } 194 | '[' ']' { 195 $$ = 0; 196 } 197 ; 198 199 decl_mem_cplx: INJ_TOK_ENUM INJ_TOK_IDENT '{' decl_enumlist '}' { 200 $$ = inj_decl_mem_create_enum($2, $4); 201 } 202 | INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT { 203 $$ = inj_decl_mem_create_defined($3, $2, 204 ITEMTYPE_EVENT); 205 } 206 | INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT { 207 $$ = inj_decl_mem_create_defined($3, $2, 208 ITEMTYPE_FMRI); 209 } 210 | INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT { 211 $$ = inj_decl_mem_create_defined($3, $2, 212 ITEMTYPE_AUTH); 213 } 214 | INJ_TOK_LIST INJ_TOK_IDENT INJ_TOK_IDENT { 215 $$ = inj_decl_mem_create_defined($3, $2, 216 ITEMTYPE_LIST); 217 } 218 ; 219 220 decl_enumlist: INJ_TOK_IDENT { 221 $$ = inj_zalloc(sizeof (inj_hash_t)); 222 inj_strhash_create($$); 223 224 inj_strhash_insert($$, $1, 1); 225 } 226 | decl_enumlist ',' INJ_TOK_IDENT { 227 if (inj_strhash_lookup($1, $3) != NULL) 228 yyerror("duplicate enum value \"%s\"", $3); 229 else 230 inj_strhash_insert($1, $3, 1); 231 $$ = $1; 232 } 233 ; 234 235 /* 236 * Event, FMRI, Authority, and list definitions 237 */ 238 239 defn: INJ_TOK_EVENT INJ_TOK_FMACLASS INJ_TOK_IDENT '=' 240 '{' defn_memlist '}' { 241 inj_defn_finish($6, $2, $3, ITEMTYPE_EVENT); 242 inj_strfree($2); 243 } 244 | INJ_TOK_FMRI INJ_TOK_IDENT INJ_TOK_IDENT '=' 245 '{' defn_memlist '}' { 246 inj_defn_finish($6, $2, $3, ITEMTYPE_FMRI); 247 inj_strfree($2); 248 } 249 | INJ_TOK_AUTH INJ_TOK_IDENT INJ_TOK_IDENT '=' 250 '{' defn_memlist '}' { 251 inj_defn_finish($6, $2, $3, ITEMTYPE_AUTH); 252 inj_strfree($2); 253 } 254 ; 255 256 defn_memlist: defn_memvals { 257 $$ = inj_defn_create($1); 258 } 259 | defn_memlist ',' defn_memvals { 260 inj_defn_addmem($1, $3); 261 $$ = $1; 262 } 263 ; 264 265 defn_memvals: defn_val 266 | INJ_TOK_EVENT INJ_TOK_FMACLASS { 267 $$ = inj_defn_mem_create($2, DEFNMEM_EVENT); 268 } 269 | INJ_TOK_FMRI INJ_TOK_IDENT { 270 $$ = inj_defn_mem_create($2, DEFNMEM_FMRI); 271 } 272 | INJ_TOK_AUTH INJ_TOK_IDENT { 273 $$ = inj_defn_mem_create($2, DEFNMEM_AUTH); 274 } 275 | '[' defn_memlist ']' { 276 $$ = inj_defn_mem_create_list($2, DEFNMEM_ARRAY); 277 } 278 | '{' defn_memlist '}' { 279 $$ = inj_defn_mem_create_list($2, DEFNMEM_LIST); 280 } 281 ; 282 283 defn_val: INJ_TOK_IMM { 284 $$ = inj_defn_mem_create($1, DEFNMEM_IMM); 285 } 286 | INJ_TOK_IDENT { 287 $$ = inj_defn_mem_create($1, DEFNMEM_IDENT); 288 } 289 | INJ_TOK_QSTRING { 290 $$ = inj_defn_mem_create($1, DEFNMEM_QSTRING); 291 } 292 ; 293 294 /* 295 * Commands 296 */ 297 298 command: cmd_repeatable 299 | INJ_TOK_ADDHRT hrtime { $$ = inj_cmd_addhrt($2); } 300 | INJ_TOK_ENDHRT { $$ = inj_cmd_endhrt(); } 301 | INJ_TOK_SLEEP number { $$ = inj_cmd_sleep($2); } 302 | INJ_TOK_REPEAT number cmd_repeatable { 303 $$ = ($3 == NULL ? NULL : inj_cmd_repeat($3, $2)); 304 } 305 ; 306 307 cmd_repeatable: defined_event { 308 $$ = ($1 == NULL ? NULL : inj_cmd_send($1)); 309 } 310 | INJ_TOK_RANDOMIZE '{' rand_problist '}' { 311 $$ = ($3 == NULL ? NULL : inj_cmd_rand($3)); 312 } 313 ; 314 315 rand_problist: rand_element 316 | rand_problist ',' rand_element { 317 $$ = ($1 == NULL || $3 == NULL) ? 318 NULL : inj_rand_add($1, $3); 319 } 320 ; 321 322 rand_element: '{' defined_event ',' number '}' { 323 $$ = ($2 == NULL ? NULL : inj_rand_create($2, $4)); 324 } 325 ; 326 327 defined_event: INJ_TOK_IDENT { 328 inj_defn_t *ev; 329 330 if ((ev = inj_defn_lookup($1, MEMTYPE_EVENT)) == 331 NULL) { 332 yyerror("unknown event \"%s\"\n", $1); 333 $$ = NULL; 334 } else 335 $$ = ev; 336 } 337 338 number: INJ_TOK_IMM { 339 u_longlong_t val; 340 341 if (inj_strtoull($1, 32, &val) < 0) { 342 yyerror("invalid number"); 343 $$ = 0; 344 } else 345 $$ = (uint32_t)val; 346 } 347 348 hrtime: INJ_TOK_IMM INJ_TOK_IDENT { 349 longlong_t val; 350 351 if (inj_strtoll($1, 64, &val) < 0 || 352 inj_strtime(&val, $2) < 0) { 353 yyerror("invalid time"); 354 $$ = 0; 355 } else 356 $$ = val; 357 } 358 359 %% 360 361 inj_list_t * 362 inj_program_read(const char *file) 363 { 364 if (strcmp(file, "-") == 0) { 365 yyin = stdin; 366 yyinname = "stdin"; 367 } else { 368 if ((yyin = fopen(file, "r")) == NULL) 369 die("failed to open %s", file); 370 371 yyinname = strrchr(file, '/'); 372 if (yyinname != NULL) 373 yyinname++; 374 else 375 yyinname = file; 376 } 377 378 yyreset(); 379 (void) yyparse(); 380 381 if (yyin != stdin) 382 (void) fclose(yyin); 383 384 if (yynerrors != 0) { 385 die("parsing failed - %d error%s\n", yynerrors, 386 (yynerrors > 1 ? "s" : "")); 387 } 388 389 return (inj_cmds_get()); 390 } 391