1 %{ 2 3 #include <assert.h> 4 #include <errno.h> 5 #include <stdarg.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/queue.h> 9 10 #include "evtr.h" 11 #include "tok.h" 12 #include "ktrfmt.tab.h" 13 #include "internal.h" 14 15 struct ktrfmt_parse_ctx { 16 struct symtab *symtab; 17 struct evtr_variable *var; 18 struct evtr_variable_value *val; 19 evtr_event_t ev; 20 char *errbuf; 21 size_t errbufsz; 22 int err; 23 }; 24 25 int __ktrfmtlex(YYSTYPE *); 26 #define __ktrfmt_lex __ktrfmtlex 27 28 void __ktrfmt_error (struct ktrfmt_parse_ctx *, const char *); 29 30 static void do_parse_err(struct ktrfmt_parse_ctx *, const char *, ...) 31 __printflike(2, 3); 32 33 static 34 void 35 do_parse_err(struct ktrfmt_parse_ctx *ctx, const char *fmt, ...) 36 { 37 va_list ap; 38 39 va_start(ap, fmt); 40 vsnprintf(ctx->errbuf, ctx->errbufsz, fmt, ap); 41 va_end(ap); 42 ctx->err = !0; 43 } 44 45 #define parse_err(fmt, ...) \ 46 do { \ 47 do_parse_err(ctx, fmt, ##__VA_ARGS__); \ 48 YYABORT; \ 49 } while (0) 50 51 static 52 struct evtr_variable * 53 evtr_var_new(const char *name) 54 { 55 struct evtr_variable *var; 56 57 var = calloc(1, sizeof(*var)); 58 if (var) { 59 if (!(var->name = strdup(name))) { 60 free(var); 61 return NULL; 62 } 63 var->val.type = EVTR_VAL_NIL; 64 } 65 return var; 66 } 67 68 /* 69 * XXX: should be reentrant 70 */ 71 static 72 char * 73 uniq_varname(void) 74 { 75 static long serno; 76 static char buf[100]; 77 78 serno++; 79 snprintf(buf, sizeof(buf), "@%ld", serno); 80 return &buf[0]; 81 } 82 83 static 84 int 85 index_hash(struct ktrfmt_parse_ctx *ctx, const char *hashname, 86 evtr_variable_value_t val, evtr_var_t *_var) 87 { 88 evtr_var_t hsh, var; 89 uintptr_t ret, key; 90 hsh = symtab_find(ctx->symtab, hashname); 91 if (hsh->val.type == EVTR_VAL_NIL) { 92 /* it's probably the first time we see this "variable" */ 93 printd(PARSE, "creating hash for %s\n", hsh->name); 94 hsh->val.type = EVTR_VAL_HASH; 95 hsh->val.hashtab = hash_new(); 96 } else if (hsh->val.type != EVTR_VAL_HASH) { 97 printd(PARSE, "trying to use type %d as hash\n", hsh->val.type); 98 return !0; 99 } 100 if (val->type == EVTR_VAL_INT) { 101 key = val->num; 102 printd(PARSE, "looking up %s[%jd] in %p\n", hsh->name, 103 val->num, hsh->val.hashtab); 104 } else if (val->type == EVTR_VAL_STR) { 105 key = (uintptr_t)val->str; 106 printd(PARSE, "looking up %s[\"%s\"] in %p\n", hsh->name, 107 val->str, hsh->val.hashtab); 108 } else { 109 do_parse_err(ctx, "trying to index hash '%s' with " 110 "non-supported value", hashname); 111 return !0; 112 } 113 114 if (hash_find(hsh->val.hashtab, key, &ret)) { 115 printd(PARSE, "didn't find it\n"); 116 var = evtr_var_new(uniq_varname()); 117 if (var) { 118 printd(PARSE, "inserting it as %s\n", var->name); 119 if (!hash_insert(hsh->val.hashtab, key, 120 (uintptr_t)var)) { 121 do_parse_err(ctx, "can't insert temporary " 122 "variable into hash\n"); 123 return !0; 124 } 125 symtab_insert(ctx->symtab, var->name, var); 126 } else { 127 do_parse_err(ctx, "out of memory"); 128 } 129 } else { 130 var = (struct evtr_variable *)ret; 131 } 132 if (!var) { 133 fprintf(stderr, "no var!\n"); 134 return !0; 135 /* XXX */ 136 } 137 *_var = var; 138 return 0; 139 } 140 141 %} 142 143 %verbose 144 %error-verbose 145 %debug 146 %name-prefix "__ktrfmt_" 147 %define api.pure 148 %parse-param{struct ktrfmt_parse_ctx *ctx} 149 150 %union { 151 struct token *tok; 152 struct evtr_variable *var; 153 struct evtr_variable_value *val; 154 void *na; 155 } 156 157 %token<tok> TOK_ID 158 %token<tok> TOK_CTOR 159 %token<tok> TOK_INT 160 %token<tok> TOK_STR 161 162 %token<na> TOK_EQ 163 %token<na> TOK_LEFT_BRACK 164 %token<na> TOK_RIGHT_BRACK 165 %token<na> TOK_DOT 166 167 %type<var> constant 168 %type<var> ctor_args 169 %type<var> construct_expr 170 %type<var> primary_expr 171 %type<var> postfix_expr 172 %type<var> unary_expr 173 %type<na> assign_expr 174 %type<na> expr 175 176 %% 177 178 input: stmt 179 180 stmt: unary_expr { 181 ctx->var = $1; 182 } 183 | expr 184 ; 185 constant: TOK_INT { 186 evtr_var_t var; 187 if (!$1->str) 188 parse_err("out of memory"); 189 var = evtr_var_new(uniq_varname()); 190 var->val.type = EVTR_VAL_INT; 191 errno = 0; 192 var->val.num = strtoll($1->str, NULL, 0); 193 if (errno) { 194 parse_err("Can't parse numeric constant '%s'", $1->str); 195 } 196 $$ = var; 197 tok_free($1); 198 } 199 | TOK_STR { 200 evtr_var_t var; 201 if (!$1->str) 202 parse_err("out of memory"); 203 var = evtr_var_new(uniq_varname()); 204 var->val.type = EVTR_VAL_STR; 205 var->val.str = $1->str; 206 if (!var->val.str) { 207 parse_err("out of memory"); 208 } 209 $$ = var; 210 tok_free($1); 211 } 212 ; 213 ctor_args: constant { 214 evtr_var_t ctor; 215 ctor = evtr_var_new(uniq_varname()); 216 ctor->val.type = EVTR_VAL_CTOR; 217 ctor->val.ctor.name = NULL; 218 TAILQ_INIT(&ctor->val.ctor.args); 219 TAILQ_INSERT_HEAD(&ctor->val.ctor.args, &$1->val, link); 220 $$ = ctor; 221 } 222 | constant ctor_args { 223 TAILQ_INSERT_HEAD(&$2->val.ctor.args, &$1->val, link); 224 $$ = $2; 225 } 226 ; 227 construct_expr: TOK_CTOR { 228 evtr_var_t var; 229 if (!$1->str) 230 parse_err("out of memory"); 231 printd(PARSE, "TOK_CTOR\n"); 232 printd(PARSE, "tok: %p, str = %p\n", $1, $1->str); 233 var = evtr_var_new(uniq_varname()); 234 var->val.type = EVTR_VAL_CTOR; 235 var->val.ctor.name = $1->str; 236 TAILQ_INIT(&var->val.ctor.args); 237 tok_free($1); 238 $$ = var; 239 } 240 | TOK_CTOR ctor_args { 241 evtr_variable_value_t val; 242 if (!$1->str) 243 parse_err("out of memory"); 244 printd(PARSE, "TOK_CTOR\n"); 245 printd(PARSE, "tok: %p, str = %p\n", $1, $1->str); 246 $2->val.ctor.name = $1->str; 247 $$ = $2; 248 printd(PARSE, "CTOR: %s\n", $1->str); 249 TAILQ_FOREACH(val, &$2->val.ctor.args, link) { 250 switch (val->type) { 251 case EVTR_VAL_INT: 252 printd(PARSE, "\t%jd\n", val->num); 253 break; 254 case EVTR_VAL_STR: 255 printd(PARSE, "\t\"%s\"\n", val->str); 256 break; 257 case EVTR_VAL_NIL: 258 assert(!"can't get here"); 259 default: 260 ; 261 } 262 } 263 } 264 ; 265 primary_expr: TOK_ID { 266 evtr_var_t var; 267 if (!$1->str) 268 parse_err("out of memory"); 269 printd(PARSE, "TOK_ID\n"); 270 printd(PARSE, "tok: %p, str = %p\n", $1, $1->str); 271 var = symtab_find(ctx->symtab, $1->str); 272 if (!var) { 273 if (!(var = evtr_var_new($1->str))) { 274 tok_free($1); 275 parse_err("out of memory"); 276 } 277 printd(PARSE, "creating var %s\n", $1->str); 278 symtab_insert(ctx->symtab, $1->str, var); 279 } 280 $$ = var; 281 tok_free($1); 282 } 283 | constant { 284 $$ = $1; 285 } 286 ; 287 postfix_expr: postfix_expr TOK_LEFT_BRACK postfix_expr TOK_RIGHT_BRACK { 288 evtr_var_t var; 289 290 if (index_hash(ctx, $1->name, &$3->val, &var)) 291 YYABORT; 292 $$ = var; 293 } 294 | postfix_expr TOK_DOT TOK_ID { 295 evtr_var_t var, tmp; 296 if (!$3->str) 297 parse_err("out of memory"); 298 tmp = evtr_var_new(uniq_varname()); 299 tmp->val.type = EVTR_VAL_STR; 300 tmp->val.str = $3->str; 301 302 if (index_hash(ctx, $1->name, &tmp->val, &var)) 303 YYABORT; 304 tok_free($3); 305 $$ = var; 306 } 307 | primary_expr { 308 $$ = $1; 309 } 310 ; 311 unary_expr: postfix_expr { 312 $$ = $1; 313 } 314 ; 315 assign_expr: unary_expr TOK_EQ constant { 316 $1->val = $3->val; 317 ctx->ev->type = EVTR_TYPE_STMT; 318 ctx->ev->stmt.var = $1; 319 ctx->ev->stmt.val = &$3->val; 320 ctx->ev->stmt.op = EVTR_OP_SET; 321 } 322 | unary_expr TOK_EQ construct_expr { 323 $1->val = $3->val; 324 ctx->ev->type = EVTR_TYPE_STMT; 325 ctx->ev->stmt.var = $1; 326 ctx->ev->stmt.val = &$3->val; 327 ctx->ev->stmt.op = EVTR_OP_SET; 328 } 329 ; 330 expr: assign_expr { 331 $$ = $1; 332 } 333 ; 334 335 %% 336 337 void * __ktrfmt_scan_string(const char *); 338 void __ktrfmt_delete_buffer(void *); 339 340 void 341 __ktrfmt_error (struct ktrfmt_parse_ctx *ctx, const char *s) 342 { 343 do_parse_err(ctx, s); 344 } 345 346 int 347 parse_string(evtr_event_t ev, struct symtab *symtab, const char *str, 348 char *errbuf, size_t errbufsz) 349 { 350 void *bufstate; 351 int ret; 352 struct ktrfmt_parse_ctx ctx; 353 354 printd(PARSE, "parsing \"%s\"\n", str); 355 ctx.ev = ev; 356 ctx.symtab = symtab; 357 ctx.errbuf = errbuf; 358 ctx.errbuf[0] = '\0'; 359 ctx.errbufsz = errbufsz; 360 ctx.err = 0; 361 bufstate = __ktrfmt_scan_string(str); 362 ret = __ktrfmt_parse(&ctx); 363 __ktrfmt_delete_buffer(bufstate); 364 365 return ret; 366 } 367 368 int 369 parse_var(const char *str, struct symtab *symtab, struct evtr_variable **var, 370 char *errbuf, size_t errbufsz) 371 { 372 void *bufstate; 373 int ret; 374 struct ktrfmt_parse_ctx ctx; 375 376 printd(PARSE, "parsing \"%s\"\n", str); 377 ctx.ev = NULL; 378 ctx.symtab = symtab; 379 ctx.var = NULL; 380 ctx.errbuf = errbuf; 381 ctx.errbuf[0] = '\0'; 382 ctx.errbufsz = errbufsz; 383 ctx.err = 0; 384 bufstate = __ktrfmt_scan_string(str); 385 ret = __ktrfmt_parse(&ctx); 386 __ktrfmt_delete_buffer(bufstate); 387 388 *var = ctx.var; 389 return ret; 390 } 391