-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathcvconf.y
180 lines (156 loc) · 4.47 KB
/
cvconf.y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "chaosvpn.h"
extern struct config *globalconfig; /* private from config.c */
extern int yyerror(char*);
extern int yylex (void);
static char* catandfree(char*, char*, int, int);
static char* concatias(int, char*, int);
static struct settings_list_entry* list_mkientry(int);
static struct settings_list_entry* list_mksentry(const char*);
static struct settings_list* list_add_elem(struct settings_list*, struct settings_list_entry*);
static struct settings_list* list_allocate(void);
extern int yylineno;
%}
%union {
int ival;
float fval;
char* sval;
void* pval;
bool bval;
struct settings_list* lval;
struct settings_list_entry* eval;
}
%token <pval> KEYWORD_S
%token <pval> KEYWORD_I
%token <pval> KEYWORD_F
%token <pval> KEYWORD_L
%token <pval> KEYWORD_B
%token <sval> STRING
%token <ival> INTVAL
%token <bval> BOOLVAL
%token <bval> YESNOVAL
%token <fval> FLOATVAL
%token <sval> ASSIGNMENT
%token <sval> SEPARATOR
%token <sval> STRINGMARKER
%token <pval> LISTOPEN
%token <pval> LISTSEP
%token <pval> LISTCLOSE
%type <sval> string
%type <lval> list
%type <eval> listentry
%%
parser: { } config
config:
| setting SEPARATOR config
;
setting: KEYWORD_I ASSIGNMENT INTVAL { *((int*)$1) = $3; }
| KEYWORD_B ASSIGNMENT BOOLVAL { *((bool*)$1) = $3; }
| KEYWORD_B ASSIGNMENT YESNOVAL { *((bool*)$1) = $3; }
| KEYWORD_B ASSIGNMENT INTVAL { *((bool*)$1) = $3; }
| KEYWORD_F ASSIGNMENT FLOATVAL { *((float*)$1) = $3; }
| KEYWORD_S ASSIGNMENT STRINGMARKER string STRINGMARKER { if (*(char**)$1) {free(*(char**)$1);} *((char**)$1) = $4; }
| KEYWORD_L ASSIGNMENT LISTOPEN list { *((struct settings_list**)$1) = $4; }
;
listentry: INTVAL { $$ = list_mkientry($1); }
| STRINGMARKER string STRINGMARKER { $$ = list_mksentry($2); }
list: listentry LISTCLOSE { $$ = list_add_elem(list_allocate(), $1); }
| listentry LISTSEP list { $$ = list_add_elem($3, $1); }
| LISTCLOSE { $$ = list_allocate(); }
;
string: { $$ = strdup(""); /* ugly */ }
| KEYWORD_S string {
if (*(char**)$1 == NULL) {
log_err("error: access to uninitialized configuration variable in line %d", yylineno);
exit(1);
}
$$ = catandfree(*(char**)$1, $2, 0, 1);
};
| KEYWORD_I string { $$ = concatias(*(int*)$1, $2, 1); };
| STRING string { $$ = catandfree($1, $2, 1, 1); }
;
%%
static struct settings_list*
list_allocate(void)
{
struct settings_list* sl = (struct settings_list*)
malloc(sizeof(struct settings_list));
if (sl == NULL) exit(111);
memset(sl, 0, sizeof(struct settings_list));
INIT_LIST_HEAD(&sl->list);
return sl;
}
static struct settings_list_entry*
list_mkientry(int i)
{
struct settings_list_entry* entry;
entry = malloc(sizeof(struct settings_list_entry));
if (entry == NULL) exit(111);
memset(entry, 0, sizeof(struct settings_list_entry));
entry->etype = LIST_INTEGER;
entry->evalue.i = i;
return entry;
}
static struct settings_list_entry*
list_mksentry(const char *s)
{
struct settings_list_entry* entry;
entry = malloc(sizeof(struct settings_list_entry));
if (entry == NULL) exit(111);
memset(entry, 0, sizeof(struct settings_list_entry));
entry->etype = LIST_STRING;
entry->evalue.s = strdup(s);
return entry;
}
static struct settings_list*
list_add_elem(struct settings_list* list, struct settings_list_entry* item)
{
struct settings_list* listitem;
listitem = (struct settings_list*) malloc(sizeof(struct settings_list));
if (listitem == NULL) exit(111);
memset(listitem, 0, sizeof(struct settings_list));
listitem->e = item;
list_add(&listitem->list, &list->list);
return list;
}
int
yyerror(char* msg)
{
log_err("parse error: %s in line %d", msg, yylineno);
exit(1);
}
static char*
concatias(int i, char* s, int frees)
{
char* buf;
size_t sl;
size_t tl;
sl = strlen(s);
tl = sl + 20;
buf = malloc(sl + tl);
if (!buf) exit(111);
snprintf(buf, sl + tl, "%d%s", i, s);
if (frees) free(s);
return buf;
}
static char*
catandfree(char* s1, char* s2, int frees1, int frees2)
{
size_t newlen;
size_t l1, l2;
char* buf;
l1 = strlen(s1);
l2 = strlen(s2);
newlen = l1 + l2 + 1;
buf = malloc(newlen);
if(!buf) exit(111);
memcpy(buf, s1, l1);
memcpy(buf + l1, s2, l2);
buf[newlen - 1] = 0;
if (frees1) free(s1);
if (frees2) free(s2);
return buf;
}