Stricter typing of productions. The cntl
production allows for empty lists (e.g. %<{reply-to}%?{from}%>). Enable debugging when MHFORMAT_DEBUG environment variable is set. (yylex): Skip whitespace after the function name. (branch_fixup): The produced jump offset was wrong. Fixed. (mh_code_builtin): Fixed passing of escape arguments.
Showing
1 changed file
with
35 additions
and
9 deletions
... | @@ -35,7 +35,7 @@ static size_t mh_code_string (char *string); | ... | @@ -35,7 +35,7 @@ static size_t mh_code_string (char *string); |
35 | static size_t mh_code_number (int num); | 35 | static size_t mh_code_number (int num); |
36 | static size_t mh_code_builtin (mh_builtin_t *bp, int argtype); | 36 | static size_t mh_code_builtin (mh_builtin_t *bp, int argtype); |
37 | static void branch_fixup (size_t pc, size_t tgt); | 37 | static void branch_fixup (size_t pc, size_t tgt); |
38 | 38 | ||
39 | /* Lexical tie-ins */ | 39 | /* Lexical tie-ins */ |
40 | static int in_escape; /* Set when inside an escape sequence */ | 40 | static int in_escape; /* Set when inside an escape sequence */ |
41 | static int want_function; /* Set when expecting function name */ | 41 | static int want_function; /* Set when expecting function name */ |
... | @@ -61,12 +61,15 @@ static int want_function; /* Set when expecting function name */ | ... | @@ -61,12 +61,15 @@ static int want_function; /* Set when expecting function name */ |
61 | %token BOGUS | 61 | %token BOGUS |
62 | %type <type> cond_expr component funcall item argument escape literal | 62 | %type <type> cond_expr component funcall item argument escape literal |
63 | %type <elif_list> elif_part elif_list fi | 63 | %type <elif_list> elif_part elif_list fi |
64 | %type <pc> cond end else elif else_part | 64 | %type <pc> cond end else elif else_part zlist list pitem |
65 | %type <builtin> function | 65 | %type <builtin> function |
66 | 66 | ||
67 | %% | 67 | %% |
68 | 68 | ||
69 | input : list | 69 | input : list |
70 | { | ||
71 | /* nothing: to shut bison up */ | ||
72 | } | ||
70 | ; | 73 | ; |
71 | 74 | ||
72 | list : pitem | 75 | list : pitem |
... | @@ -94,6 +97,7 @@ pitem : item | ... | @@ -94,6 +97,7 @@ pitem : item |
94 | yyerror ("UNEXPECTED item TYPE"); | 97 | yyerror ("UNEXPECTED item TYPE"); |
95 | abort (); | 98 | abort (); |
96 | } | 99 | } |
100 | $$ = pc; | ||
97 | } | 101 | } |
98 | ; | 102 | ; |
99 | 103 | ||
... | @@ -211,8 +215,8 @@ argument : /* empty */ | ... | @@ -211,8 +215,8 @@ argument : /* empty */ |
211 | | escape | 215 | | escape |
212 | ; | 216 | ; |
213 | 217 | ||
214 | /* 1 2 3 4 5 6 7 */ | 218 | /* 1 2 3 4 5 6 7 */ |
215 | cntl : if cond list end elif_part else_part fi | 219 | cntl : if cond zlist end elif_part else_part fi |
216 | { | 220 | { |
217 | size_t start_pc = 0, end_pc = 0; | 221 | size_t start_pc = 0, end_pc = 0; |
218 | 222 | ||
... | @@ -244,6 +248,13 @@ cntl : if cond list end elif_part else_part fi | ... | @@ -244,6 +248,13 @@ cntl : if cond list end elif_part else_part fi |
244 | } | 248 | } |
245 | ; | 249 | ; |
246 | 250 | ||
251 | zlist : /* empty */ | ||
252 | { | ||
253 | $$ = pc; | ||
254 | } | ||
255 | | list | ||
256 | ; | ||
257 | |||
247 | if : IF | 258 | if : IF |
248 | { | 259 | { |
249 | in_escape++; | 260 | in_escape++; |
... | @@ -305,13 +316,13 @@ elif_part : /* empty */ | ... | @@ -305,13 +316,13 @@ elif_part : /* empty */ |
305 | } | 316 | } |
306 | ; | 317 | ; |
307 | 318 | ||
308 | elif_list : elif cond list | 319 | elif_list : elif cond zlist |
309 | { | 320 | { |
310 | $$.cond = $1; | 321 | $$.cond = $1; |
311 | MHI_NUM(format.prog[$2]) = pc - $2 + 2; | 322 | MHI_NUM(format.prog[$2]) = pc - $2 + 2; |
312 | $$.end = 0; | 323 | $$.end = 0; |
313 | } | 324 | } |
314 | | elif_list end elif cond list | 325 | | elif_list end elif cond zlist |
315 | { | 326 | { |
316 | MHI_NUM(format.prog[$4]) = pc - $4 + 2; | 327 | MHI_NUM(format.prog[$4]) = pc - $4 + 2; |
317 | $$.cond = $1.cond; | 328 | $$.cond = $1.cond; |
... | @@ -356,6 +367,8 @@ static int backslash(int c); | ... | @@ -356,6 +367,8 @@ static int backslash(int c); |
356 | int | 367 | int |
357 | yylex () | 368 | yylex () |
358 | { | 369 | { |
370 | if (yydebug) | ||
371 | fprintf (stderr, "[lex at %10.10s]\n", curp); | ||
359 | if (*curp == '%') | 372 | if (*curp == '%') |
360 | { | 373 | { |
361 | curp++; | 374 | curp++; |
... | @@ -458,6 +471,8 @@ yylex () | ... | @@ -458,6 +471,8 @@ yylex () |
458 | { | 471 | { |
459 | curp -= rest; | 472 | curp -= rest; |
460 | yylval.builtin = bp; | 473 | yylval.builtin = bp; |
474 | while (*curp && isspace(*curp)) | ||
475 | curp++; | ||
461 | return FUNCTION; | 476 | return FUNCTION; |
462 | } | 477 | } |
463 | } | 478 | } |
... | @@ -469,7 +484,10 @@ int | ... | @@ -469,7 +484,10 @@ int |
469 | mh_format_parse (char *format_str, mh_format_t *fmt) | 484 | mh_format_parse (char *format_str, mh_format_t *fmt) |
470 | { | 485 | { |
471 | int rc; | 486 | int rc; |
472 | 487 | char *p = getenv ("MHFORMAT_DEBUG"); | |
488 | |||
489 | if (p) | ||
490 | yydebug = 1; | ||
473 | start = curp = format_str; | 491 | start = curp = format_str; |
474 | obstack_init (&stack); | 492 | obstack_init (&stack); |
475 | format.progsize = 0; | 493 | format.progsize = 0; |
... | @@ -512,7 +530,7 @@ branch_fixup (size_t epc, size_t tgt) | ... | @@ -512,7 +530,7 @@ branch_fixup (size_t epc, size_t tgt) |
512 | if (!prev) | 530 | if (!prev) |
513 | return; | 531 | return; |
514 | branch_fixup (prev, tgt); | 532 | branch_fixup (prev, tgt); |
515 | MHI_NUM(format.prog[prev]) = tgt - prev - 1; | 533 | MHI_NUM(format.prog[prev]) = tgt - prev; |
516 | } | 534 | } |
517 | 535 | ||
518 | 536 | ||
... | @@ -587,9 +605,14 @@ mh_code_builtin (mh_builtin_t *bp, int argtype) | ... | @@ -587,9 +605,14 @@ mh_code_builtin (mh_builtin_t *bp, int argtype) |
587 | case mhtype_num: | 605 | case mhtype_num: |
588 | mh_code_op (mhop_num_to_arg); | 606 | mh_code_op (mhop_num_to_arg); |
589 | break; | 607 | break; |
608 | |||
590 | case mhtype_str: | 609 | case mhtype_str: |
591 | mh_code_op (mhop_str_to_arg); | 610 | /* mhtype_none means that the argument was an escape, |
611 | which has left its string value (if any) in the | ||
612 | arg_str register. Therefore, there's no need to | ||
613 | code mhop_str_to_arg */ | ||
592 | break; | 614 | break; |
615 | |||
593 | default: | 616 | default: |
594 | yyerror ("UNKNOWN ARGTYPE"); | 617 | yyerror ("UNKNOWN ARGTYPE"); |
595 | abort (); | 618 | abort (); |
... | @@ -608,15 +631,18 @@ mh_code_builtin (mh_builtin_t *bp, int argtype) | ... | @@ -608,15 +631,18 @@ mh_code_builtin (mh_builtin_t *bp, int argtype) |
608 | case mhtype_none: | 631 | case mhtype_none: |
609 | mh_error ("extra arguments to %s", bp->name); | 632 | mh_error ("extra arguments to %s", bp->name); |
610 | return 0; | 633 | return 0; |
634 | |||
611 | case mhtype_num: | 635 | case mhtype_num: |
612 | mh_code_op (mhop_str_to_num); | 636 | mh_code_op (mhop_str_to_num); |
613 | break; | 637 | break; |
638 | |||
614 | case mhtype_str: | 639 | case mhtype_str: |
615 | mh_code_op (mhop_num_to_str); | 640 | mh_code_op (mhop_num_to_str); |
616 | break; | 641 | break; |
617 | } | 642 | } |
618 | } | 643 | } |
619 | } | 644 | } |
645 | |||
620 | mh_code_op (mhop_call); | 646 | mh_code_op (mhop_call); |
621 | MHI_BUILTIN(instr) = bp->fun; | 647 | MHI_BUILTIN(instr) = bp->fun; |
622 | mh_code (&instr); | 648 | mh_code (&instr); | ... | ... |
-
Please register or sign in to post a comment