Remove advertising header from man pages.
[dragonfly.git] / lib / libevtr / ktrfmt.y
blob357ded50e5142b399cff6aeee35b1eabf54f5a3c
1 %{
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>
10 #include "evtr.h"
11 #include "tok.h"
12 #include "ktrfmt.tab.h"
13 #include "internal.h"
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;
25 int __ktrfmtlex(YYSTYPE *);
26 #define __ktrfmt_lex __ktrfmtlex
28 void __ktrfmt_error (struct ktrfmt_parse_ctx *, const char *);
30 static void do_parse_err(struct ktrfmt_parse_ctx *, const char *, ...)
31 __printflike(2, 3);
33 static
34 void
35 do_parse_err(struct ktrfmt_parse_ctx *ctx, const char *fmt, ...)
37 va_list ap;
39 va_start(ap, fmt);
40 vsnprintf(ctx->errbuf, ctx->errbufsz, fmt, ap);
41 va_end(ap);
42 ctx->err = !0;
45 #define parse_err(fmt, ...) \
46 do { \
47 do_parse_err(ctx, fmt, ##__VA_ARGS__); \
48 YYABORT; \
49 } while (0)
51 static
52 struct evtr_variable *
53 evtr_var_new(const char *name)
55 struct evtr_variable *var;
57 var = calloc(1, sizeof(*var));
58 if (var) {
59 if (!(var->name = strdup(name))) {
60 free(var);
61 return NULL;
63 var->val.type = EVTR_VAL_NIL;
65 return var;
69 * XXX: should be reentrant
71 static
72 char *
73 uniq_varname(void)
75 static long serno;
76 static char buf[100];
78 serno++;
79 snprintf(buf, sizeof(buf), "@%ld", serno);
80 return &buf[0];
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)
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;
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;
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;
125 symtab_insert(ctx->symtab, var->name, var);
126 } else {
127 do_parse_err(ctx, "out of memory");
129 } else {
130 var = (struct evtr_variable *)ret;
132 if (!var) {
133 fprintf(stderr, "no var!\n");
134 return !0;
135 /* XXX */
137 *_var = var;
138 return 0;
143 %verbose
144 %error-verbose
145 %debug
146 %name-prefix "__ktrfmt_"
147 %define api.pure
148 %parse-param{struct ktrfmt_parse_ctx *ctx}
150 %union {
151 struct token *tok;
152 struct evtr_variable *var;
153 struct evtr_variable_value *val;
154 void *na;
157 %token<tok> TOK_ID
158 %token<tok> TOK_CTOR
159 %token<tok> TOK_INT
160 %token<tok> TOK_STR
162 %token<na> TOK_EQ
163 %token<na> TOK_LEFT_BRACK
164 %token<na> TOK_RIGHT_BRACK
165 %token<na> TOK_DOT
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
178 input: stmt
180 stmt: unary_expr {
181 ctx->var = $1;
183 | expr
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);
196 $$ = var;
197 tok_free($1);
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");
209 $$ = var;
210 tok_free($1);
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;
222 | constant ctor_args {
223 TAILQ_INSERT_HEAD(&$2->val.ctor.args, &$1->val, link);
224 $$ = $2;
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;
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:
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");
277 printd(PARSE, "creating var %s\n", $1->str);
278 symtab_insert(ctx->symtab, $1->str, var);
280 $$ = var;
281 tok_free($1);
283 | constant {
284 $$ = $1;
287 postfix_expr: postfix_expr TOK_LEFT_BRACK postfix_expr TOK_RIGHT_BRACK {
288 evtr_var_t var;
290 if (index_hash(ctx, $1->name, &$3->val, &var))
291 YYABORT;
292 $$ = var;
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;
302 if (index_hash(ctx, $1->name, &tmp->val, &var))
303 YYABORT;
304 tok_free($3);
305 $$ = var;
307 | primary_expr {
308 $$ = $1;
311 unary_expr: postfix_expr {
312 $$ = $1;
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;
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;
330 expr: assign_expr {
331 $$ = $1;
337 void * __ktrfmt_scan_string(const char *);
338 void __ktrfmt_delete_buffer(void *);
340 void
341 __ktrfmt_error (struct ktrfmt_parse_ctx *ctx, const char *s)
343 do_parse_err(ctx, s);
347 parse_string(evtr_event_t ev, struct symtab *symtab, const char *str,
348 char *errbuf, size_t errbufsz)
350 void *bufstate;
351 int ret;
352 struct ktrfmt_parse_ctx ctx;
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);
365 return ret;
369 parse_var(const char *str, struct symtab *symtab, struct evtr_variable **var,
370 char *errbuf, size_t errbufsz)
372 void *bufstate;
373 int ret;
374 struct ktrfmt_parse_ctx ctx;
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);
388 *var = ctx.var;
389 return ret;