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