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