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