| 1 | %token TOK_STRING |
| 2 | %token TOK_NUMBER |
| 3 | %token TOK_KEY |
| 4 | |
| 5 | %start input |
| 6 | |
| 7 | %{ |
| 8 | #include <stdio.h> |
| 9 | #include <stdlib.h> |
| 10 | #include <string.h> |
| 11 | /* Bison stupidly redeclares malloc/free unless they are #defined |
| 12 | * (or a bunch of madder conditions) */ |
| 13 | #ifndef malloc |
| 14 | # define malloc malloc |
| 15 | # define free free |
| 16 | #endif |
| 17 | #include "secnet.h" |
| 18 | #include "conffile_internal.h" |
| 19 | #include "conffile.yy.h" |
| 20 | #include "util.h" |
| 21 | #define YYERROR_VERBOSE |
| 22 | |
| 23 | static struct p_node *node(uint32_t type, struct p_node *l, struct p_node *r); |
| 24 | |
| 25 | static struct p_node *result; |
| 26 | |
| 27 | static void yyerror(const char *s); |
| 28 | |
| 29 | %} |
| 30 | |
| 31 | %% |
| 32 | |
| 33 | input: assignments { result = $1; $$=result; } |
| 34 | ; |
| 35 | |
| 36 | assignments: assignments assignment { $$=node(T_ALIST, $2, $1); } |
| 37 | | assignment { $$=node(T_ALIST, $1, NULL); } |
| 38 | ; |
| 39 | |
| 40 | searchpath: /* empty */ { $$ = NULL; } |
| 41 | | '<' list '>' { $$ = $2; } |
| 42 | ; |
| 43 | |
| 44 | dict: searchpath '{' assignments '}' |
| 45 | { $$ = node(T_DICT, $3, $1); } |
| 46 | | searchpath '{' '}' { $$ = node(T_DICT, NULL, $1); } |
| 47 | ; |
| 48 | |
| 49 | path: '/' pathelements { $$ = node(T_ABSPATH, NULL, $2); } |
| 50 | | pathelements { $$ = node(T_RELPATH, NULL, $1); } |
| 51 | ; |
| 52 | |
| 53 | pathelements: pathelements '/' TOK_KEY { $$ = node(T_PATHELEM, $3, $1); } |
| 54 | | TOK_KEY { $$ = node(T_PATHELEM, $1, NULL); } |
| 55 | ; |
| 56 | |
| 57 | exec: item '(' list ')' { $$ = node(T_EXEC, $1, $3); } |
| 58 | | item '(' ')' { $$ = node(T_EXEC, $1, NULL); } |
| 59 | | item dict |
| 60 | { $$ = node(T_EXEC, $1, node(T_LISTITEM, $2, NULL)); } |
| 61 | ; |
| 62 | |
| 63 | list: list ',' item { $$ = node(T_LISTITEM, $3, $1); } |
| 64 | | item { $$ = node(T_LISTITEM, $1, NULL); } |
| 65 | ; |
| 66 | |
| 67 | assignment: TOK_KEY '=' list ';' { $$ = node(T_ASSIGNMENT, $1, $3); } |
| 68 | | TOK_KEY list ';' { $$ = node(T_ASSIGNMENT, $1, $2); } |
| 69 | | error ';' { $$ = node(T_ERROR, NULL, NULL); } |
| 70 | | error '}' { $$ = node(T_ERROR, NULL, NULL); } |
| 71 | | error ')' { $$ = node(T_ERROR, NULL, NULL); } |
| 72 | ; |
| 73 | |
| 74 | item: TOK_STRING |
| 75 | | TOK_NUMBER |
| 76 | | path |
| 77 | | dict |
| 78 | | exec |
| 79 | ; |
| 80 | |
| 81 | %% |
| 82 | |
| 83 | static void yyerror(const char *s) |
| 84 | { |
| 85 | Message(M_FATAL,"config file %s line %d: %s\n",config_file, |
| 86 | config_lineno,s); |
| 87 | } |
| 88 | |
| 89 | struct p_node *parse_conffile(FILE *conffile) |
| 90 | { |
| 91 | yyin=conffile; |
| 92 | if (yyparse()!=0) { |
| 93 | fatal("Configuration file parsing failed\n"); |
| 94 | } |
| 95 | if (yynerrs>0) { |
| 96 | fatal("%d error%s encountered in configuration file\n", |
| 97 | yynerrs,yynerrs==1?"":"s"); |
| 98 | } |
| 99 | return result; |
| 100 | } |
| 101 | |
| 102 | static struct p_node *node(uint32_t type, struct p_node *l, struct p_node *r) |
| 103 | { |
| 104 | struct p_node *rv; |
| 105 | |
| 106 | rv=safe_malloc(sizeof(*rv),"p_node"); |
| 107 | rv->type=type; |
| 108 | rv->loc.file=config_file; |
| 109 | rv->loc.line=config_lineno; |
| 110 | rv->l=l; |
| 111 | rv->r=r; |
| 112 | return rv; |
| 113 | } |