summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-01 18:13:32 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-05-03 18:23:16 (GMT)
commit24ec67c9f6375d34d88e79981ed8abbe15a78169 (patch) (unidiff)
tree6e68b1b409b10b48581422df05cfac9caedb0af2
parentda56e338d346e358de864d18ca42f574305d8dfc (diff)
downloadgrecs-24ec67c9f6375d34d88e79981ed8abbe15a78169.tar.gz
grecs-24ec67c9f6375d34d88e79981ed8abbe15a78169.tar.bz2
Reindent all, except wordsplit, which is shared with MU.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/Makefile.am2
-rw-r--r--src/format.c269
-rw-r--r--src/grecs-gram.y1086
-rw-r--r--src/grecs-lex.l579
-rw-r--r--src/grecs.h180
-rw-r--r--src/list.c177
-rw-r--r--src/preproc.c1050
-rw-r--r--src/text.c36
8 files changed, 1631 insertions, 1748 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2f35f52..759716b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ EXTRA_DIST=grecs-gram.h $(PP_SETUP_FILE)
32 32
33INCLUDES = -I$(srcdir) @GRECS_INCLUDES@ 33INCLUDES = -I$(srcdir) @GRECS_INCLUDES@
34AM_YFLAGS = -dtv 34AM_YFLAGS = -dtv
35AM_LFLAGS = -dvp 35AM_LFLAGS = -d
36# Use a modified ylwrap implementation that understands the --prefix option. 36# Use a modified ylwrap implementation that understands the --prefix option.
37YLWRAP = $(top_srcdir)/$(grex_topdir)grecs/build-aux/ylwrap --prefix yy_grecs 37YLWRAP = $(top_srcdir)/$(grex_topdir)grecs/build-aux/ylwrap --prefix yy_grecs
38 38
diff --git a/src/format.c b/src/format.c
index a1aa67d..fc6c8d6 100644
--- a/src/format.c
+++ b/src/format.c
@@ -26,164 +26,159 @@
26const char * 26const char *
27grecs_data_type_string (enum grecs_data_type type) 27grecs_data_type_string (enum grecs_data_type type)
28{ 28{
29 switch (type) 29 switch (type) {
30 { 30 case grecs_type_void:
31 case grecs_type_void: 31 return "void";
32 return "void";
33 32
34 case grecs_type_string: 33 case grecs_type_string:
35 return "string"; 34 return "string";
36 35
37 case grecs_type_short: 36 case grecs_type_short:
38 case grecs_type_ushort: 37 case grecs_type_ushort:
39 case grecs_type_int: 38 case grecs_type_int:
40 case grecs_type_uint: 39 case grecs_type_uint:
41 case grecs_type_long: 40 case grecs_type_long:
42 case grecs_type_ulong: 41 case grecs_type_ulong:
43 case grecs_type_size: 42 case grecs_type_size:
44 /*FIXME case grecs_type_off:*/ 43 /*FIXME case grecs_type_off:*/
45 return "number"; 44 return "number";
46 45
47 case grecs_type_time: 46 case grecs_type_time:
48 return "time"; 47 return "time";
49 48
50 case grecs_type_bool: 49 case grecs_type_bool:
51 return "boolean"; 50 return "boolean";
52 51
53 case grecs_type_ipv4: 52 case grecs_type_ipv4:
54 return "IPv4"; 53 return "IPv4";
55 54
56 case grecs_type_cidr: 55 case grecs_type_cidr:
57 return "CIDR"; 56 return "CIDR";
58 57
59 case grecs_type_host: 58 case grecs_type_host:
60 return "hostname"; 59 return "hostname";
61 60
62 case grecs_type_sockaddr: 61 case grecs_type_sockaddr:
63 return "sock-addr"; 62 return "sock-addr";
64 63
65 case grecs_type_section: 64 case grecs_type_section:
66 return "section"; 65 return "section";
67 } 66 }
68 return "UNKNOWN?"; 67 return "UNKNOWN?";
69} 68}
70 69
71static void 70static void
72format_level (FILE *stream, unsigned level) 71format_level(FILE *stream, unsigned level)
73{ 72{
74 while (level--) 73 while (level--)
75 fprintf (stream, " "); 74 fprintf(stream, " ");
76} 75}
77 76
78void 77void
79grecs_format_docstring (FILE *stream, const char *docstring, unsigned level) 78grecs_format_docstring(FILE *stream, const char *docstring, unsigned level)
80{ 79{
81 size_t len = strlen (docstring); 80 size_t len = strlen(docstring);
82 int width = 78 - level * 2; 81 int width = 78 - level * 2;
83 82
84 if (width < 0) 83 if (width < 0) {
85 { 84 width = 78;
86 width = 78; 85 level = 0;
87 level = 0;
88 }
89
90 while (len)
91 {
92 size_t seglen;
93 const char *p;
94
95 for (seglen = 0, p = docstring; p < docstring + width && *p; p++)
96 {
97 if (*p == '\n')
98 {
99 seglen = p - docstring;
100 break;
101 }
102 if (isspace (*p))
103 seglen = p - docstring;
104 } 86 }
105 if (seglen == 0 || *p == 0) 87
106 seglen = p - docstring; 88 while (len) {
107 89 size_t seglen;
108 format_level (stream, level); 90 const char *p;
109 fprintf (stream, "# "); 91
110 fwrite (docstring, seglen, 1, stream); 92 for (seglen = 0, p = docstring; p < docstring + width && *p;
111 fputc ('\n', stream); 93 p++) {
112 len -= seglen; 94 if (*p == '\n') {
113 docstring += seglen; 95 seglen = p - docstring;
114 if (*docstring == '\n') 96 break;
115 { 97 }
116 docstring++; 98 if (isspace(*p))
117 len--; 99 seglen = p - docstring;
100 }
101 if (seglen == 0 || *p == 0)
102 seglen = p - docstring;
103
104 format_level(stream, level);
105 fprintf(stream, "# ");
106 fwrite(docstring, seglen, 1, stream);
107 fputc('\n', stream);
108 len -= seglen;
109 docstring += seglen;
110 if (*docstring == '\n') {
111 docstring++;
112 len--;
113 } else
114 while (*docstring && isspace(*docstring)) {
115 docstring++;
116 len--;
117 }
118 } 118 }
119 else
120 while (*docstring && isspace (*docstring))
121 {
122 docstring++;
123 len--;
124 }
125 }
126} 119}
127 120
128void 121void
129grecs_format_simple_statement (FILE *stream, struct grecs_keyword *kwp, 122grecs_format_simple_statement(FILE *stream, struct grecs_keyword *kwp,
130 unsigned level) 123 unsigned level)
131{ 124{
132 const char *argstr; 125 const char *argstr;
133 126
134 if (kwp->docstring) 127 if (kwp->docstring)
135 grecs_format_docstring (stream, kwp->docstring, level); 128 grecs_format_docstring(stream, kwp->docstring, level);
136 format_level (stream, level); 129 format_level(stream, level);
137 130
138 if (kwp->argname) 131 if (kwp->argname)
139 argstr = kwp->argname; 132 argstr = kwp->argname;
140 else 133 else
141 argstr = N_("arg"); 134 argstr = N_("arg");
142 135
143 if (strchr ("<[", argstr[0])) 136 if (strchr("<[", argstr[0]))
144 fprintf (stream, "%s %s;\n", kwp->ident, gettext (argstr)); 137 fprintf(stream, "%s %s;\n", kwp->ident, gettext(argstr));
145 else if (strchr (argstr, ':')) 138 else if (strchr (argstr, ':'))
146 fprintf (stream, "%s <%s>;\n", kwp->ident, gettext (argstr)); 139 fprintf (stream, "%s <%s>;\n", kwp->ident, gettext(argstr));
147 else 140 else {
148 { 141 fprintf(stream, "%s <%s: ", kwp->ident, gettext(argstr));
149 fprintf (stream, "%s <%s: ", kwp->ident, gettext (argstr)); 142 if (GRECS_IS_LIST(kwp->type))
150 if (GRECS_IS_LIST (kwp->type)) 143 fprintf(stream, "list of %s",
151 fprintf (stream, "list of %s", 144 gettext(grecs_data_type_string(
152 gettext (grecs_data_type_string (GRECS_TYPE (kwp->type)))); 145 GRECS_TYPE (kwp->type))));
153 else 146 else
154 fprintf (stream, "%s", gettext (grecs_data_type_string (kwp->type))); 147 fprintf(stream, "%s",
155 fprintf (stream, ">;\n"); 148 gettext(grecs_data_type_string(kwp->type)));
156 } 149 fprintf(stream, ">;\n");
150 }
157} 151}
158 152
159void 153void
160grecs_format_block_statement (FILE *stream, struct grecs_keyword *kwp, 154grecs_format_block_statement(FILE *stream, struct grecs_keyword *kwp,
161 unsigned level) 155 unsigned level)
162{ 156{
163 if (kwp->docstring) 157 if (kwp->docstring)
164 grecs_format_docstring (stream, kwp->docstring, level); 158 grecs_format_docstring(stream, kwp->docstring, level);
165 format_level (stream, level); 159 format_level(stream, level);
166 fprintf (stream, "%s", kwp->ident); 160 fprintf(stream, "%s", kwp->ident);
167 if (kwp->argname) 161 if (kwp->argname)
168 fprintf (stream, " <%s>", gettext (kwp->argname)); 162 fprintf(stream, " <%s>", gettext(kwp->argname));
169 fprintf (stream, " {\n"); 163 fprintf(stream, " {\n");
170 grecs_format_statement_array (stream, kwp->kwd, 0, level + 1); 164 grecs_format_statement_array(stream, kwp->kwd, 0, level + 1);
171 format_level (stream, level); 165 format_level(stream, level);
172 fprintf (stream, "}\n"); 166 fprintf(stream, "}\n");
173} 167}
174 168
175void 169void
176grecs_format_statement_array (FILE *stream, struct grecs_keyword *kwp, 170grecs_format_statement_array(FILE *stream, struct grecs_keyword *kwp,
177 unsigned n, 171 unsigned n,
178 unsigned level) 172 unsigned level)
179{ 173{
180 for (; kwp->ident; kwp++, n++) 174 for (; kwp->ident; kwp++, n++) {
181 { 175 if (n)
182 if (n) 176 fputc('\n', stream);
183 fputc ('\n', stream); 177 if (kwp->type == grecs_type_section)
184 if (kwp->type == grecs_type_section) 178 grecs_format_block_statement(stream, kwp, level);
185 grecs_format_block_statement (stream, kwp, level); 179 else
186 else 180 grecs_format_simple_statement(stream, kwp, level);
187 grecs_format_simple_statement (stream, kwp, level); 181 }
188 }
189} 182}
183
184
diff --git a/src/grecs-gram.y b/src/grecs-gram.y
index 0edea13..f65e2dd 100644
--- a/src/grecs-gram.y
+++ b/src/grecs-gram.y
@@ -47,13 +47,13 @@ int grecs_error_count;
47 47
48int grecs_default_port = 0; 48int grecs_default_port = 0;
49 49
50static void *target_ptr (struct grecs_keyword *kwp, char *base); 50static void *target_ptr(struct grecs_keyword *kwp, char *base);
51static void stmt_begin (struct grecs_keyword *kwp, grecs_value_t tag); 51static void stmt_begin(struct grecs_keyword *kwp, grecs_value_t tag);
52static void stmt_end (struct grecs_keyword *kwp); 52static void stmt_end(struct grecs_keyword *kwp);
53static struct grecs_keyword *find_keyword (const char *ident); 53static struct grecs_keyword *find_keyword(const char *ident);
54 54
55static void process_ident (struct grecs_keyword *kwp, grecs_value_t *value); 55static void process_ident(struct grecs_keyword *kwp, grecs_value_t *value);
56static struct grecs_list *simple_list_create (int dispose); 56static struct grecs_list *simple_list_create(int dispose);
57%} 57%}
58 58
59%union { 59%union {
@@ -85,80 +85,79 @@ stmt : simple
85 85
86simple : ident vallist ';' 86simple : ident vallist ';'
87 { 87 {
88 process_ident($1, &$2); 88 process_ident($1, &$2);
89 } 89 }
90 ; 90 ;
91 91
92block : ident tag { stmt_begin($<kw>1, $<value>2); } '{' stmtlist '}' opt_sc 92block : ident tag { stmt_begin($<kw>1, $<value>2); } '{' stmtlist '}' opt_sc
93 { 93 {
94 stmt_end($1); 94 stmt_end($1);
95 } 95 }
96 ; 96 ;
97 97
98ident : IDENT 98ident : IDENT
99 { 99 {
100 $$ = find_keyword($1); 100 $$ = find_keyword($1);
101 if (!$$) 101 if (!$$)
102 grecs_error(&grecs_current_locus, 0, _("Unknown keyword")); 102 grecs_error(&grecs_current_locus, 0,
103 _("Unknown keyword"));
103 } 104 }
104 ; 105 ;
105 106
106tag : /* empty */ 107tag : /* empty */
107 { 108 {
108 $$.type = GRECS_TYPE_STRING; 109 $$.type = GRECS_TYPE_STRING;
109 $$.v.string = NULL; 110 $$.v.string = NULL;
110 } 111 }
111 | value 112 | value
112 ; 113 ;
113 114
114vallist : vlist 115vallist : vlist
115 { 116 {
116 size_t n; 117 size_t n;
117 118
118 if ((n = grecs_list_size ($1)) == 1) 119 if ((n = grecs_list_size($1)) == 1) {
119 { 120 $$ = *(grecs_value_t *)grecs_list_index($1, 0);
120 $$ = *(grecs_value_t *)grecs_list_index ($1, 0); 121 } else {
121 } 122 size_t i;
122 else 123 struct grecs_list_entry *ep;
123 {
124 size_t i;
125 struct grecs_list_entry *ep;
126 124
127 $$.type = GRECS_TYPE_ARRAY; 125 $$.type = GRECS_TYPE_ARRAY;
128 $$.v.arg.c = n; 126 $$.v.arg.c = n;
129 $$.v.arg.v = grecs_malloc (n * sizeof ($$.v.arg.v[0])); 127 $$.v.arg.v = grecs_malloc(n *
130 for (i = 0, ep = $1->head; ep; i++, ep = ep->next) 128 sizeof($$.v.arg.v[0]));
131 $$.v.arg.v[i] = *(grecs_value_t *)ep->data; 129 for (i = 0, ep = $1->head; ep; i++, ep = ep->next)
132 } 130 $$.v.arg.v[i] = *(grecs_value_t *)ep->data;
133 grecs_list_free ($1); 131 }
132 grecs_list_free($1);
134 } 133 }
135 ; 134 ;
136 135
137vlist : value 136vlist : value
138 { 137 {
139 $$ = simple_list_create (0); 138 $$ = simple_list_create(0);
140 grecs_list_append ($$, grecs_value_dup (&$1)); 139 grecs_list_append($$, grecs_value_dup(&$1));
141 } 140 }
142 | vlist value 141 | vlist value
143 { 142 {
144 grecs_list_append ($1, grecs_value_dup (&$2)); 143 grecs_list_append($1, grecs_value_dup(&$2));
145 } 144 }
146 ; 145 ;
147 146
148value : string 147value : string
149 { 148 {
150 $$.type = GRECS_TYPE_STRING; 149 $$.type = GRECS_TYPE_STRING;
151 $$.v.string = $1; 150 $$.v.string = $1;
152 } 151 }
153 | list 152 | list
154 { 153 {
155 $$.type = GRECS_TYPE_LIST; 154 $$.type = GRECS_TYPE_LIST;
156 $$.v.list = $1; 155 $$.v.list = $1;
157 } 156 }
158 | MSTRING 157 | MSTRING
159 { 158 {
160 $$.type = GRECS_TYPE_STRING; 159 $$.type = GRECS_TYPE_STRING;
161 $$.v.string = $1; 160 $$.v.string = $1;
162 } 161 }
163 ; 162 ;
164 163
@@ -169,52 +168,52 @@ string : STRING
169 168
170slist : slist0 169slist : slist0
171 { 170 {
172 struct grecs_list_entry *ep; 171 struct grecs_list_entry *ep;
173 const void *p; 172 const void *p;
174 173
175 grecs_line_begin (); 174 grecs_line_begin();
176 for (ep = $1->head; ep; ep = ep->next) 175 for (ep = $1->head; ep; ep = ep->next)
177 grecs_line_add (ep->data, strlen (ep->data)); 176 grecs_line_add(ep->data, strlen(ep->data));
178 $$ = grecs_line_finish (); 177 $$ = grecs_line_finish();
179 grecs_list_free ($1); 178 grecs_list_free($1);
180 } 179 }
181 ; 180 ;
182 181
183slist0 : QSTRING 182slist0 : QSTRING
184 { 183 {
185 $$ = simple_list_create (0); 184 $$ = simple_list_create(0);
186 grecs_list_append ($$, $1); 185 grecs_list_append($$, $1);
187 } 186 }
188 | slist0 QSTRING 187 | slist0 QSTRING
189 { 188 {
190 grecs_list_append ($1, $2); 189 grecs_list_append($1, $2);
191 $$ = $1; 190 $$ = $1;
192 } 191 }
193 ; 192 ;
194 193
195list : '(' ')' 194list : '(' ')'
196 { 195 {
197 $$ = NULL; 196 $$ = NULL;
198 } 197 }
199 | '(' values ')' 198 | '(' values ')'
200 { 199 {
201 $$ = $2; 200 $$ = $2;
202 } 201 }
203 | '(' values ',' ')' 202 | '(' values ',' ')'
204 { 203 {
205 $$ = $2; 204 $$ = $2;
206 } 205 }
207 ; 206 ;
208 207
209values : value 208values : value
210 { 209 {
211 $$ = simple_list_create (0); 210 $$ = simple_list_create(0);
212 grecs_list_append ($$, grecs_value_dup (&$1)); 211 grecs_list_append($$, grecs_value_dup(&$1));
213 } 212 }
214 | values ',' value 213 | values ',' value
215 { 214 {
216 grecs_list_append ($1, grecs_value_dup (&$3)); 215 grecs_list_append($1, grecs_value_dup(&$3));
217 $$ = $1; 216 $$ = $1;
218 } 217 }
219 ; 218 ;
220 219
@@ -227,380 +226,356 @@ opt_sc : /* empty */
227int 226int
228yyerror(char *s) 227yyerror(char *s)
229{ 228{
230 grecs_error (&grecs_current_locus, 0, "%s", s); 229 grecs_error(&grecs_current_locus, 0, "%s", s);
231 return 0; 230 return 0;
232} 231}
233 232
234static void 233static void
235listel_dispose (void *el) 234listel_dispose(void *el)
236{ 235{
237 free (el); 236 free(el);
238} 237}
239 238
240static struct grecs_list * 239static struct grecs_list *
241simple_list_create (int dispose) 240simple_list_create(int dispose)
242{ 241{
243 struct grecs_list *lp = grecs_list_create (); 242 struct grecs_list *lp = grecs_list_create();
244 if (dispose) 243 if (dispose)
245 lp->free_entry = listel_dispose; 244 lp->free_entry = listel_dispose;
246 return lp; 245 return lp;
247} 246}
248 247
249int 248int
250grecs_vasprintf (char **pbuf, size_t *psize, const char *fmt, va_list ap) 249grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap)
251{ 250{
252 char *buf = *pbuf; 251 char *buf = *pbuf;
253 size_t buflen = *psize; 252 size_t buflen = *psize;
254 int rc = 0; 253 int rc = 0;
255 254
256 if (!buf) 255 if (!buf) {
257 { 256 if (buflen == 0)
258 if (buflen == 0) 257 buflen = 512; /* Initial allocation */
259 buflen = 512; /* Initial allocation */
260 258
261 buf = calloc (1, buflen); 259 buf = calloc(1, buflen);
262 if (buf == NULL) 260 if (buf == NULL)
263 return ENOMEM; 261 return ENOMEM;
264 }
265
266 for (;;)
267 {
268 ssize_t n = vsnprintf (buf, buflen, fmt, ap);
269 if (n < 0 || n >= buflen || !memchr (buf, '\0', n + 1))
270 {
271 char *newbuf;
272 size_t newlen = buflen * 2;
273 if (newlen < buflen)
274 {
275 rc = ENOMEM;
276 break;
277 }
278 newbuf = realloc (buf, newlen);
279 if (newbuf == NULL)
280 {
281 rc = ENOMEM;
282 break;
283 }
284 buflen = newlen;
285 buf = newbuf;
286 } 262 }
287 else 263
288 break; 264 for (;;) {
289 } 265 ssize_t n = vsnprintf(buf, buflen, fmt, ap);
290 266 if (n < 0 || n >= buflen || !memchr(buf, '\0', n + 1)) {
291 if (rc) 267 char *newbuf;
292 { 268 size_t newlen = buflen * 2;
293 if (!*pbuf) 269 if (newlen < buflen) {
294 { 270 rc = ENOMEM;
295 /* We made first allocation, now free it */ 271 break;
296 free (buf); 272 }
297 buf = NULL; 273 newbuf = realloc(buf, newlen);
298 buflen = 0; 274 if (newbuf == NULL) {
275 rc = ENOMEM;
276 break;
277 }
278 buflen = newlen;
279 buf = newbuf;
280 } else
281 break;
299 } 282 }
300 }
301 283
302 *pbuf = buf; 284 if (rc) {
303 *psize = buflen; 285 if (!*pbuf) {
304 return rc; 286 /* We made first allocation, now free it */
287 free(buf);
288 buf = NULL;
289 buflen = 0;
290 }
291 }
292
293 *pbuf = buf;
294 *psize = buflen;
295 return rc;
305} 296}
306 297
307int 298int
308grecs_asprintf (char **pbuf, size_t *psize, const char *fmt, ...) 299grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...)
309{ 300{
310 int rc; 301 int rc;
311 va_list ap; 302 va_list ap;
312 303
313 va_start (ap, fmt); 304 va_start(ap, fmt);
314 rc = grecs_vasprintf (pbuf, psize, fmt, ap); 305 rc = grecs_vasprintf(pbuf, psize, fmt, ap);
315 va_end (ap); 306 va_end(ap);
316 return rc; 307 return rc;
317} 308}
318 309
319void 310void
320grecs_warning (grecs_locus_t *locus, int errcode, const char *fmt, ...) 311grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
321{ 312{
322 va_list ap; 313 va_list ap;
323 char *buf = NULL; 314 char *buf = NULL;
324 size_t size = 0; 315 size_t size = 0;
325 316
326 va_start (ap, fmt); 317 va_start(ap, fmt);
327 if (grecs_vasprintf (&buf, &size, fmt, ap)) 318 if (grecs_vasprintf(&buf, &size, fmt, ap))
328 grecs_alloc_die (); 319 grecs_alloc_die();
329 va_end (ap); 320 va_end(ap);
330 grecs_print_diag (locus, 0, errcode, buf); 321 grecs_print_diag(locus, 0, errcode, buf);
331 free(buf); 322 free(buf);
332} 323}
333 324
334void 325void
335grecs_error (grecs_locus_t *locus, int errcode, const char *fmt, ...) 326grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...)
336{ 327{
337 va_list ap; 328 va_list ap;
338 char *buf = NULL; 329 char *buf = NULL;
339 size_t size = 0; 330 size_t size = 0;
340 331
341 va_start (ap, fmt); 332 va_start(ap, fmt);
342 if (grecs_vasprintf (&buf, &size, fmt, ap)) 333 if (grecs_vasprintf(&buf, &size, fmt, ap))
343 grecs_alloc_die (); 334 grecs_alloc_die();
344 va_end (ap); 335 va_end(ap);
345 grecs_print_diag (locus, 1, errcode, buf); 336 grecs_print_diag(locus, 1, errcode, buf);
346 free (buf); 337 free(buf);
347 grecs_error_count++; 338 grecs_error_count++;
348} 339}
349 340
350void 341void
351grecs_set_keywords (struct grecs_keyword *kwd) 342grecs_set_keywords(struct grecs_keyword *kwd)
352{ 343{
353 config_keywords.kwd = kwd; 344 config_keywords.kwd = kwd;
354} 345}
355 346
356int 347int
357grecs_parse (const char *name) 348grecs_parse(const char *name)
358{ 349{
359 int rc; 350 int rc;
360 if (grecs_lex_begin (name)) 351 if (grecs_lex_begin(name))
361 return 1; 352 return 1;
362 cursect = &config_keywords; 353 cursect = &config_keywords;
363 if (sections) 354 if (sections) {
364 { 355 grecs_list_free(sections);
365 grecs_list_free (sections); 356 sections = NULL;
366 sections = NULL; 357 }
367 } 358 rc = yyparse();
368 rc = yyparse (); 359 grecs_lex_end();
369 grecs_lex_end (); 360 if (grecs_error_count)
370 if (grecs_error_count) 361 rc = 1;
371 rc = 1; 362 return rc;
372 return rc;
373} 363}
374 364
375void 365void
376grecs_gram_trace (int n) 366grecs_gram_trace(int n)
377{ 367{
378 yydebug = n; 368 yydebug = n;
379} 369}
380 370
381 371
382 372
383static void * 373static void *
384target_ptr (struct grecs_keyword *kwp, char *base) 374target_ptr(struct grecs_keyword *kwp, char *base)
385{ 375{
386 if (kwp->varptr) 376 if (kwp->varptr)
387 base = (char*) kwp->varptr + kwp->offset; 377 base = (char*) kwp->varptr + kwp->offset;
388 else if (base) 378 else if (base)
389 base += kwp->offset; 379 base += kwp->offset;
390 380
391 return base; 381 return base;
392} 382}
393 383
394static int 384static int
395fake_callback (enum grecs_callback_command cmd, 385fake_callback(enum grecs_callback_command cmd,
396 grecs_locus_t *locus, 386 grecs_locus_t *locus,
397 void *varptr, 387 void *varptr,
398 grecs_value_t *value, 388 grecs_value_t *value,
399 void *cb_data) 389 void *cb_data)
400{ 390{
401 return 0; 391 return 0;
402} 392}
403 393
404static struct grecs_keyword fake = { 394static struct grecs_keyword fake = {
405 "*", 395 "*",
406 NULL, 396 NULL,
407 NULL, 397 NULL,
408 grecs_type_void, 398 grecs_type_void,
409 NULL, 399 NULL,
410 0, 400 0,
411 fake_callback, 401 fake_callback,
412 NULL, 402 NULL,
413 &fake 403 &fake
414}; 404};
415 405
416static void 406static void
417stmt_begin (struct grecs_keyword *kwp, grecs_value_t tag) 407stmt_begin(struct grecs_keyword *kwp, grecs_value_t tag)
418{ 408{
419 void *target; 409 void *target;
420 410
421 if (!sections) 411 if (!sections)
422 sections = grecs_list_create (); 412 sections = grecs_list_create();
423 grecs_list_push (sections, cursect); 413 grecs_list_push(sections, cursect);
424 if (kwp) 414 if (kwp) {
425 { 415 target = target_ptr(kwp, CURRENT_BASE);
426 target = target_ptr (kwp, CURRENT_BASE); 416 cursect = kwp;
427 cursect = kwp; 417 if (kwp->callback &&
428 if (kwp->callback && kwp->callback (grecs_callback_section_begin, 418 kwp->callback(grecs_callback_section_begin,
429 &grecs_current_locus, /* FIXME */ 419 &grecs_current_locus, /* FIXME */
430 target, 420 target,
431 &tag, 421 &tag,
432 &kwp->callback_data)) 422 &kwp->callback_data))
433 cursect = &fake; 423 cursect = &fake;
434 } 424 } else
435 else 425 /* install "ignore-all" section */
436 /* install "ignore-all" section */ 426 cursect = kwp;
437 cursect = kwp;
438} 427}
439 428
440static void 429static void
441stmt_end (struct grecs_keyword *kwp) 430stmt_end(struct grecs_keyword *kwp)
442{ 431{
443 grecs_callback_fn callback = NULL; 432 grecs_callback_fn callback = NULL;
444 void *dataptr = NULL; 433 void *dataptr = NULL;
445 434
446 if (cursect && cursect->callback) 435 if (cursect && cursect->callback) {
447 { 436 callback = cursect->callback;
448 callback = cursect->callback; 437 dataptr = &cursect->callback_data;
449 dataptr = &cursect->callback_data; 438 }
450 }
451
452 cursect = (struct grecs_keyword *) grecs_list_pop (sections);
453 if (!cursect)
454 abort ();
455 if (callback)
456 callback (grecs_callback_section_end,
457 &grecs_current_locus, /* FIXME */
458 kwp ? target_ptr (kwp, CURRENT_BASE) : NULL,
459 NULL,
460 dataptr);
461 439
440 cursect = (struct grecs_keyword *) grecs_list_pop(sections);
441 if (!cursect)
442 abort();
443 if (callback)
444 callback(grecs_callback_section_end,
445 &grecs_current_locus, /* FIXME */
446 kwp ? target_ptr(kwp, CURRENT_BASE) : NULL,
447 NULL,
448 dataptr);
462} 449}
463 450
464static struct grecs_keyword * 451static struct grecs_keyword *
465find_keyword (const char *ident) 452find_keyword(const char *ident)
466{ 453{
467 struct grecs_keyword *kwp; 454 struct grecs_keyword *kwp;
468 455
469 if (cursect && cursect != &fake) 456 if (cursect && cursect != &fake) {
470 { 457 for (kwp = cursect->kwd; kwp->ident; kwp++)
471 for (kwp = cursect->kwd; kwp->ident; kwp++) 458 if (strcmp(kwp->ident, ident) == 0)
472 if (strcmp (kwp->ident, ident) == 0) 459 return kwp;
473 return kwp; 460 } else {
474 } 461 return &fake;
475 else 462 }
476 { 463 return NULL;
477 return &fake;
478 }
479 return NULL;
480} 464}
481 465
482static int 466static int
483string_to_bool (const char *string, int *pval, grecs_locus_t *locus) 467string_to_bool(const char *string, int *pval, grecs_locus_t *locus)
484{ 468{
485 if (strcmp (string, "yes") == 0 469 if (strcmp(string, "yes") == 0
486 || strcmp (string, "true") == 0 470 || strcmp(string, "true") == 0
487 || strcmp (string, "t") == 0 471 || strcmp(string, "t") == 0
488 || strcmp (string, "1") == 0) 472 || strcmp(string, "1") == 0)
489 *pval = 1; 473 *pval = 1;
490 else if (strcmp (string, "no") == 0 474 else if (strcmp(string, "no") == 0
491 || strcmp (string, "false") == 0 475 || strcmp(string, "false") == 0
492 || strcmp (string, "nil") == 0 476 || strcmp(string, "nil") == 0
493 || strcmp (string, "0") == 0) 477 || strcmp(string, "0") == 0)
494 *pval = 0; 478 *pval = 0;
495 else 479 else {
496 { 480 grecs_error(locus, 0,
497 grecs_error (locus, 0, _("%s: not a valid boolean value"), string); 481 _("%s: not a valid boolean value"),
498 return 1; 482 string);
499 } 483 return 1;
500 return 0; 484 }
485 return 0;
501} 486}
502 487
503static int 488static int
504string_to_host (struct in_addr *in, const char *string, grecs_locus_t *locus) 489string_to_host(struct in_addr *in, const char *string, grecs_locus_t *locus)
505{ 490{
506 if (inet_aton (string, in) == 0) 491 if (inet_aton(string, in) == 0) {
507 { 492 struct hostent *hp;
508 struct hostent *hp; 493
509 494 hp = gethostbyname(string);
510 hp = gethostbyname (string); 495 if (hp == NULL)
511 if (hp == NULL) 496 return 1;
512 return 1; 497 memcpy(in, hp->h_addr, sizeof(struct in_addr));
513 memcpy (in, hp->h_addr, sizeof (struct in_addr)); 498 }
514 } 499 return 0;
515 return 0;
516} 500}
517 501
518static int 502static int
519string_to_sockaddr (struct grecs_sockaddr *sp, const char *string, 503string_to_sockaddr(struct grecs_sockaddr *sp, const char *string,
520 grecs_locus_t *locus) 504 grecs_locus_t *locus)
521{ 505{
522 if (string[0] == '/') 506 if (string[0] == '/') {
523 { 507 struct sockaddr_un s_un;
524 struct sockaddr_un s_un; 508 if (strlen(string) >= sizeof(s_un.sun_path)) {
525 if (strlen (string) >= sizeof (s_un.sun_path)) 509 grecs_error(locus, 0,
526 { 510 _("%s: UNIX socket name too long"),
527 grecs_error (locus, 0, _("%s: UNIX socket name too long"), string); 511 string);
528 return 1; 512 return 1;
529 }
530 s_un.sun_family = AF_UNIX;
531 strcpy (s_un.sun_path, string);
532 sp->len = sizeof (s_un);
533 sp->sa = grecs_malloc (sp->len);
534 memcpy (sp->sa, &s_un, sp->len);
535 }
536 else
537 {
538 char *p = strchr (string, ':');
539 size_t len;
540 struct sockaddr_in sa;
541
542 sa.sin_family = AF_INET;
543 if (p)
544 len = p - string;
545 else
546 len = strlen (string);
547
548 if (len == 0)
549 sa.sin_addr.s_addr = INADDR_ANY;
550 else
551 {
552 char *host = grecs_malloc (len + 1);
553 memcpy (host, string, len);
554 host[len] = 0;
555
556 if (string_to_host (&sa.sin_addr, host, locus))
557 {
558 grecs_error (locus, 0,
559 _("%s: not a valid IP address or hostname"),
560 host);
561 free (host);
562 return 1;
563 }
564 free (host);
565 }
566
567 if (p)
568 {
569 struct servent *serv;
570
571 p++;
572 serv = getservbyname (p, "tcp");
573 if (serv != NULL)
574 sa.sin_port = serv->s_port;
575 else
576 {
577 unsigned long l;
578 char *q;
579
580 /* Not in services, maybe a number? */
581 l = strtoul (p, &q, 0);
582
583 if (*q || l > USHRT_MAX)
584 {
585 grecs_error (locus, 0,
586 _("%s: not a valid port number"), p);
587 return 1;
588 } 513 }
589 sa.sin_port = htons (l); 514 s_un.sun_family = AF_UNIX;
590 } 515 strcpy(s_un.sun_path, string);
591 } 516 sp->len = sizeof(s_un);
592 else if (grecs_default_port) 517 sp->sa = grecs_malloc(sp->len);
593 sa.sin_port = grecs_default_port; 518 memcpy(sp->sa, &s_un, sp->len);
594 else 519 } else {
595 { 520 char *p = strchr(string, ':');
596 grecs_error (locus, 0, _("missing port number")); 521 size_t len;
597 return 1; 522 struct sockaddr_in sa;
523
524 sa.sin_family = AF_INET;
525 if (p)
526 len = p - string;
527 else
528 len = strlen(string);
529
530 if (len == 0)
531 sa.sin_addr.s_addr = INADDR_ANY;
532 else {
533 char *host = grecs_malloc(len + 1);
534 memcpy(host, string, len);
535 host[len] = 0;
536
537 if (string_to_host(&sa.sin_addr, host, locus)) {
538 grecs_error(locus, 0,
539 _("%s: not a valid IP address or hostname"),
540 host);
541 free(host);
542 return 1;
543 }
544 free(host);
545 }
546
547 if (p) {
548 struct servent *serv;
549
550 p++;
551 serv = getservbyname(p, "tcp");
552 if (serv != NULL)
553 sa.sin_port = serv->s_port;
554 else {
555 unsigned long l;
556 char *q;
557
558 /* Not in services, maybe a number? */
559 l = strtoul(p, &q, 0);
560
561 if (*q || l > USHRT_MAX) {
562 grecs_error(locus, 0,
563 _("%s: not a valid port number"), p);
564 return 1;
565 }
566 sa.sin_port = htons(l);
567 }
568 } else if (grecs_default_port)
569 sa.sin_port = grecs_default_port;
570 else {
571 grecs_error(locus, 0, _("missing port number"));
572 return 1;
573 }
574 sp->len = sizeof(sa);
575 sp->sa = grecs_malloc(sp->len);
576 memcpy(sp->sa, &sa, sp->len);
598 } 577 }
599 sp->len = sizeof (sa); 578 return 0;
600 sp->sa = grecs_malloc (sp->len);
601 memcpy (sp->sa, &sa, sp->len);
602 }
603 return 0;
604} 579}
605 580
606 581
@@ -612,15 +587,15 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
612/* The maximum and minimum values for the integer type T. These 587/* The maximum and minimum values for the integer type T. These
613 macros have undefined behavior if T is signed and has padding bits. */ 588 macros have undefined behavior if T is signed and has padding bits. */
614# define TYPE_MINIMUM(t) \ 589# define TYPE_MINIMUM(t) \
615 ((t) (! TYPE_SIGNED (t) \ 590 ((t) (! TYPE_SIGNED(t) \
616 ? (t) 0 \ 591 ? (t) 0 \
617 : TYPE_SIGNED_MAGNITUDE (t) \ 592 : TYPE_SIGNED_MAGNITUDE(t) \
618 ? ~ (t) 0 \ 593 ? ~ (t) 0 \
619 : ~ TYPE_MAXIMUM (t))) 594 : ~ TYPE_MAXIMUM(t)))
620# define TYPE_MAXIMUM(t) \ 595# define TYPE_MAXIMUM(t) \
621 ((t) (! TYPE_SIGNED (t) \ 596 ((t) (! TYPE_SIGNED(t) \
622 ? (t) -1 \ 597 ? (t) -1 \
623 : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) 598 : ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
624# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) 599# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
625 600
626 601
@@ -642,12 +617,12 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
642 break; \ 617 break; \
643 if (x <= sum) \ 618 if (x <= sum) \
644 { \ 619 { \
645 grecs_error (loc, 0, _("numeric overflow")); \ 620 grecs_error(loc, 0, _("numeric overflow")); \
646 return 1; \ 621 return 1; \
647 } \ 622 } \
648 else if (limit && x > limit) \ 623 else if (limit && x > limit) \
649 { \ 624 { \
650 grecs_error (loc, 0, _("value out of allowed range"));\ 625 grecs_error(loc, 0, _("value out of allowed range"));\
651 return 1; \ 626 return 1; \
652 } \ 627 } \
653 sum = x; \ 628 sum = x; \
@@ -672,17 +647,17 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
672 base = 8; \ 647 base = 8; \
673 } else \ 648 } else \
674 base = 10; \ 649 base = 10; \
675 STRTONUM (s, type, base, res, limit, loc); \ 650 STRTONUM(s, type, base, res, limit, loc); \
676 } 651 }
677 652
678 #define GETUNUM(str, type, res, loc) \ 653 #define GETUNUM(str, type, res, loc) \
679 { \ 654 { \
680 type tmpres; \ 655 type tmpres; \
681 const char *s = str; \ 656 const char *s = str; \
682 STRxTONUM (s, type, tmpres, 0, loc); \ 657 STRxTONUM(s, type, tmpres, 0, loc); \
683 if (*s) \ 658 if (*s) \
684 { \ 659 { \
685 grecs_error (loc, 0, _("not a number (stopped near `%s')"),\ 660 grecs_error(loc, 0, _("not a number (stopped near `%s')"),\
686 s); \ 661 s); \
687 return 1; \ 662 return 1; \
688 } \ 663 } \
@@ -700,16 +675,16 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
700 { \ 675 { \
701 sign = 1; \ 676 sign = 1; \
702 s++; \ 677 s++; \
703 limit = TYPE_MINIMUM (type); \ 678 limit = TYPE_MINIMUM(type); \
704 limit = - limit; \ 679 limit = - limit; \
705 } \ 680 } \
706 else \ 681 else \
707 { \ 682 { \
708 sign = 0; \ 683 sign = 0; \
709 limit = TYPE_MAXIMUM (type); \ 684 limit = TYPE_MAXIMUM(type); \
710 } \ 685 } \
711 \ 686 \
712 STRxTONUM (s, unsigned type, tmpres, limit, loc); \ 687 STRxTONUM(s, unsigned type, tmpres, limit, loc); \
713 if (*s) \ 688 if (*s) \
714 { \ 689 { \
715 grecs_error(loc, 0, _("not a number (stopped near `%s')"), s);\ 690 grecs_error(loc, 0, _("not a number (stopped near `%s')"), s);\
@@ -720,111 +695,111 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
720 695
721 696
722int 697int
723grecs_string_convert (void *target, enum grecs_data_type type, 698grecs_string_convert(void *target, enum grecs_data_type type,
724 const char *string, grecs_locus_t *locus) 699 const char *string, grecs_locus_t *locus)
725{ 700{
726 switch (type) 701 switch (type) {
727 { 702 case grecs_type_void:
728 case grecs_type_void: 703 abort();
729 abort ();
730
731 case grecs_type_string:
732 *(const char**)target = string;
733 break;
734 704
735 case grecs_type_short: 705 case grecs_type_string:
736 GETUNUM (string, short, *(short*)target, locus); 706 *(const char**)target = string;
737 break; 707 break;
738 708
739 case grecs_type_ushort: 709 case grecs_type_short:
740 GETUNUM (string, unsigned short, *(unsigned short*)target, locus); 710 GETUNUM(string, short, *(short*)target, locus);
741 break; 711 break;
742 712
743 case grecs_type_bool: 713 case grecs_type_ushort:
744 return string_to_bool (string, (int*)target, locus); 714 GETUNUM(string, unsigned short, *(unsigned short*)target, locus);
715 break;
745 716
746 case grecs_type_int: 717 case grecs_type_bool:
747 GETSNUM (string, int, *(int*)target, locus); 718 return string_to_bool(string, (int*)target, locus);
748 break;
749 719
750 case grecs_type_uint: 720 case grecs_type_int:
751 GETUNUM (string, unsigned int, *(unsigned int*)target, locus); 721 GETSNUM(string, int, *(int*)target, locus);
752 break; 722 break;
753 723
754 case grecs_type_long: 724 case grecs_type_uint:
755 GETSNUM (string, long, *(long*)target, locus); 725 GETUNUM(string, unsigned int, *(unsigned int*)target, locus);
756 break; 726 break;
727
728 case grecs_type_long:
729 GETSNUM(string, long, *(long*)target, locus);
730 break;
757 731
758 case grecs_type_ulong: 732 case grecs_type_ulong:
759 GETUNUM (string, unsigned long, *(unsigned long*)target, locus); 733 GETUNUM(string, unsigned long, *(unsigned long*)target, locus);
760 break; 734 break;
761 735
762 case grecs_type_size: 736 case grecs_type_size:
763 GETUNUM (string, size_t, *(size_t*)target, locus); 737 GETUNUM(string, size_t, *(size_t*)target, locus);
764 break; 738 break;
765 /*FIXME 739 /*FIXME
766 case grecs_type_off: 740 case grecs_type_off:
767 GETSNUM (string, off_t, *(off_t*)target, locus); 741 GETSNUM(string, off_t, *(off_t*)target, locus);
768 break; 742 break;
769 */ 743 */
770 case grecs_type_time: 744 case grecs_type_time:
771 /*FIXME: Use getdate */ 745 /*FIXME: Use getdate */
772 GETUNUM (string, time_t, *(time_t*)target, locus); 746 GETUNUM(string, time_t, *(time_t*)target, locus);
773 break; 747 break;
774 748
775 case grecs_type_ipv4: 749 case grecs_type_ipv4:
776 if (inet_aton (string, (struct in_addr *)target)) 750 if (inet_aton(string, (struct in_addr *)target)) {
777 { 751 grecs_error(locus, 0, _("%s: not a valid IP address"),
778 grecs_error (locus, 0, _("%s: not a valid IP address"), string); 752 string);
779 return 1; 753 return 1;
780 }
781 break;
782
783 case grecs_type_host:
784 if (string_to_host ((struct in_addr *)target, string, locus))
785 {
786 grecs_error (locus, 0,
787 _("%s: not a valid IP address or hostname"), string);
788 return 1;
789 } 754 }
790 break; 755 break;
756
757 case grecs_type_host:
758 if (string_to_host((struct in_addr *)target, string, locus)) {
759 grecs_error(locus, 0,
760 _("%s: not a valid IP address or hostname"),
761 string);
762 return 1;
763 }
764 break;
791 765
792 case grecs_type_sockaddr: 766 case grecs_type_sockaddr:
793 return string_to_sockaddr ((struct grecs_sockaddr *)target, string, 767 return string_to_sockaddr((struct grecs_sockaddr *)target, string,
794 locus); 768 locus);
795 769
796 /* FIXME: */ 770 /* FIXME: */
797 case grecs_type_cidr: 771 case grecs_type_cidr:
798 grecs_error (locus, 0, _("INTERNAL ERROR at %s:%d"), __FILE__, __LINE__); 772 grecs_error(locus, 0,
799 abort(); 773 _("INTERNAL ERROR at %s:%d"), __FILE__, __LINE__);
774 abort();
800 775
801 case grecs_type_section: 776 case grecs_type_section:
802 grecs_error (locus, 0, 777 grecs_error(locus, 0,
803 _("invalid use of block statement")); 778 _("invalid use of block statement"));
804 return 1; 779 return 1;
805 } 780 }
806 return 0; 781 return 0;
807} 782}
808 783
809struct grecs_prop 784struct grecs_prop
810{ 785{
811 size_t size; 786 size_t size;
812 int (*cmp) (const void *, const void *); 787 int (*cmp)(const void *, const void *);
813}; 788};
814 789
815static int 790static int
816string_cmp (const void *elt1, const void *elt2) 791string_cmp(const void *elt1, const void *elt2)
817{ 792{
818 return strcmp ((const char *)elt1, (const char *)elt2); 793 return strcmp((const char *)elt1,(const char *)elt2);
819} 794}
820 795
821#define __grecs_name_cat__(a,b) a ## b 796#define __grecs_name_cat__(a,b) a ## b
822#define NUMCMP(type) __grecs_name_cat__(type,_cmp) 797#define NUMCMP(type) __grecs_name_cat__(type,_cmp)
823 #define __DECL_NUMCMP(type,ctype) \ 798 #define __DECL_NUMCMP(type,ctype) \
824 static int \ 799 static int \
825 NUMCMP(type) (const void *elt1, const void *elt2)\ 800 NUMCMP(type)(const void *elt1, const void *elt2)\
826 { \ 801 { \
827 return memcmp (elt1, elt2, sizeof (ctype)); \ 802 return memcmp(elt1, elt2, sizeof(ctype)); \
828 } 803 }
829#define DECL_NUMCMP(type) __DECL_NUMCMP(type,type) 804#define DECL_NUMCMP(type) __DECL_NUMCMP(type,type)
830 805
@@ -838,151 +813,140 @@ __DECL_NUMCMP(in_addr, struct in_addr)
838__DECL_NUMCMP(grecs_sockaddr, struct grecs_sockaddr) 813__DECL_NUMCMP(grecs_sockaddr, struct grecs_sockaddr)
839 814
840struct grecs_prop grecs_prop_tab[] = { 815struct grecs_prop grecs_prop_tab[] = {
841 { 0, NULL }, /* grecs_type_void */ 816 { 0, NULL }, /* grecs_type_void */
842 { sizeof (char*), string_cmp }, /* grecs_type_string */ 817 { sizeof(char*), string_cmp }, /* grecs_type_string */
843 { sizeof (short), NUMCMP (short) }, /* grecs_type_short */ 818 { sizeof(short), NUMCMP(short) }, /* grecs_type_short */
844 { sizeof (unsigned short), NUMCMP (short) }, /* grecs_type_ushort */ 819 { sizeof(unsigned short), NUMCMP(short) }, /* grecs_type_ushort */
845 { sizeof (int), NUMCMP (int) }, /* grecs_type_int */ 820 { sizeof(int), NUMCMP(int) }, /* grecs_type_int */
846 { sizeof (unsigned int), NUMCMP (int) }, /* grecs_type_uint */ 821 { sizeof(unsigned int), NUMCMP(int) }, /* grecs_type_uint */
847 { sizeof (long), NUMCMP (long) }, /* grecs_type_long */ 822 { sizeof(long), NUMCMP(long) }, /* grecs_type_long */
848 { sizeof (unsigned long), NUMCMP (long) }, /* grecs_type_ulong */ 823 { sizeof(unsigned long), NUMCMP(long) }, /* grecs_type_ulong */
849 { sizeof (size_t), NUMCMP (size_t) }, /* grecs_type_size */ 824 { sizeof(size_t), NUMCMP(size_t) }, /* grecs_type_size */
850#if 0 825#if 0
851 FIXME 826 FIXME
852 { sizeof (off_t), NUMCMP (off_t) }, /* grecs_type_off */ 827 { sizeof(off_t), NUMCMP(off_t) }, /* grecs_type_off */
853#endif 828#endif
854 { sizeof (time_t), NUMCMP (time_t) }, /* grecs_type_time */ 829 { sizeof(time_t), NUMCMP(time_t) }, /* grecs_type_time */
855 { sizeof (int), NUMCMP (int) }, /* grecs_type_bool */ 830 { sizeof(int), NUMCMP(int) }, /* grecs_type_bool */
856 { sizeof (struct in_addr), NUMCMP (in_addr) }, /* grecs_type_ipv4 */ 831 { sizeof(struct in_addr), NUMCMP(in_addr) }, /* grecs_type_ipv4 */
857 { 0, NULL }, /* FIXME: grecs_type_cidr */ 832 { 0, NULL }, /* FIXME: grecs_type_cidr */
858 { sizeof (struct in_addr), NUMCMP (in_addr) }, /* grecs_type_host */ 833 { sizeof(struct in_addr), NUMCMP(in_addr) }, /* grecs_type_host */
859 { sizeof (struct grecs_sockaddr), NUMCMP (grecs_sockaddr) }, 834 { sizeof(struct grecs_sockaddr), NUMCMP(grecs_sockaddr) },
860 /* grecs_type_sockaddr */ 835 /* grecs_type_sockaddr */
861 { 0, NULL } /* grecs_type_section */ 836 { 0, NULL } /* grecs_type_section */
862}; 837};
863#define grecs_prop_count \ 838#define grecs_prop_count \
864 (sizeof (grecs_prop_tab) / sizeof (grecs_prop_tab[0])) 839 (sizeof(grecs_prop_tab) / sizeof(grecs_prop_tab[0]))
865 840
866void 841void
867grecs_process_ident (struct grecs_keyword *kwp, grecs_value_t *value, 842grecs_process_ident(struct grecs_keyword *kwp, grecs_value_t *value,
868 void *base, grecs_locus_t *locus) 843 void *base, grecs_locus_t *locus)
869{ 844{
870 void *target; 845 void *target;
871 846
872 if (!kwp) 847 if (!kwp)
873 return; 848 return;
874 849
875 target = target_ptr (kwp, (char *) base); 850 target = target_ptr(kwp, (char *) base);
876 851
877 if (kwp->callback) 852 if (kwp->callback)
878 kwp->callback (grecs_callback_set_value, 853 kwp->callback(grecs_callback_set_value,
879 locus, 854 locus,
880 target, 855 target,
881 value, 856 value,
882 &kwp->callback_data); 857 &kwp->callback_data);
883 else if (value->type == GRECS_TYPE_ARRAY) 858 else if (value->type == GRECS_TYPE_ARRAY) {
884 { 859 grecs_error(locus, 0,
885 grecs_error (locus, 0, 860 _("too many arguments to `%s'; missing semicolon?"),
886 _("too many arguments to `%s'; missing semicolon?"), 861 kwp->ident);
887 kwp->ident); 862 return;
888 return; 863 } else if (value->type == GRECS_TYPE_LIST) {
889 } 864 if (GRECS_IS_LIST(kwp->type)) {
890 else if (value->type == GRECS_TYPE_LIST) 865 struct grecs_list_entry *ep;
891 { 866 enum grecs_data_type type = GRECS_TYPE(kwp->type);
892 if (GRECS_IS_LIST (kwp->type)) 867 int num = 1;
893 { 868 struct grecs_list *list;
894 struct grecs_list_entry *ep; 869 size_t size;
895 enum grecs_data_type type = GRECS_TYPE (kwp->type); 870
896 int num = 1; 871 if (type >= grecs_prop_count
897 struct grecs_list *list; 872 || (size = grecs_prop_tab[type].size) == 0) {
898 size_t size; 873 grecs_error(locus, 0,
899 874 _("INTERNAL ERROR at %s:%d: "
900 if (type >= grecs_prop_count 875 "unhandled data type %d"),
901 || (size = grecs_prop_tab[type].size) == 0) 876 __FILE__, __LINE__, type);
902 { 877 abort();
903 grecs_error (locus, 0, 878 }
904 _("INTERNAL ERROR at %s:%d: " 879
905 "unhandled data type %d"), 880 list = grecs_list_create();
906 __FILE__, __LINE__, type); 881 list->cmp = grecs_prop_tab[type].cmp;
907 abort (); 882
908 } 883 for (ep = value->v.list->head; ep; ep = ep->next) {
909 884 const grecs_value_t *vp = ep->data;
910 list = grecs_list_create (); 885
911 list->cmp = grecs_prop_tab[type].cmp; 886 if (vp->type != GRECS_TYPE_STRING)
912 887 grecs_error(locus, 0,
913 for (ep = value->v.list->head; ep; ep = ep->next)
914 {
915 const grecs_value_t *vp = ep->data;
916
917 if (vp->type != GRECS_TYPE_STRING)
918 grecs_error (locus, 0,
919 _("%s: incompatible data type in list item #%d"), 888 _("%s: incompatible data type in list item #%d"),
920 kwp->ident, num); 889 kwp->ident, num);
921 else if (type == grecs_type_string) 890 else if (type == grecs_type_string)
922 grecs_list_append (list, (void*) vp->v.string); 891 grecs_list_append(list,
923 else 892 (void*) vp->v.string);
924 { 893 else {
925 void *ptr = grecs_malloc (size); 894 void *ptr = grecs_malloc(size);
926 if (grecs_string_convert (ptr, type, vp->v.string, 895 if (grecs_string_convert(ptr,
927 locus) == 0) 896 type,
928 grecs_list_append (list, ptr); 897 vp->v.string,
929 else 898 locus) == 0)
930 free (ptr); 899 grecs_list_append(list, ptr);
900 else
901 free(ptr);
902 }
903 }
904 *(struct grecs_list**)target = list;
905 } else {
906 grecs_error(locus, 0,
907 _("incompatible data type for `%s'"),
908 kwp->ident);
909 return;
931 } 910 }
932 } 911 } else if (GRECS_IS_LIST(kwp->type)) {
933 *(struct grecs_list**)target = list; 912 struct grecs_list *list;
934 } 913 enum grecs_data_type type = GRECS_TYPE(kwp->type);
935 else 914 size_t size;
936 { 915 void *ptr;
937 grecs_error (locus, 0,
938 _("incompatible data type for `%s'"),
939 kwp->ident);
940 return;
941 }
942 }
943 else if (GRECS_IS_LIST (kwp->type))
944 {
945 struct grecs_list *list;
946 enum grecs_data_type type = GRECS_TYPE (kwp->type);
947 size_t size;
948 void *ptr;
949 916
950 if (type >= grecs_prop_count 917 if (type >= grecs_prop_count
951 || (size = grecs_prop_tab[type].size) == 0) 918 || (size = grecs_prop_tab[type].size) == 0) {
952 { 919 grecs_error(locus, 0,
953 grecs_error (locus, 0, 920 _("INTERNAL ERROR at %s:%d: unhandled data type %d"),
954 _("INTERNAL ERROR at %s:%d: unhandled data type %d"), 921 __FILE__, __LINE__, type);
955 __FILE__, __LINE__, type); 922 abort();
956 abort(); 923 }
957 } 924
958 925 list = grecs_list_create();
959 list = grecs_list_create (); 926 list->cmp = grecs_prop_tab[type].cmp;
960 list->cmp = grecs_prop_tab[type].cmp; 927 list->free_entry = listel_dispose;
961 list->free_entry = listel_dispose; 928 if (type == grecs_type_string)
962 if (type == grecs_type_string) 929 grecs_list_append(list, value->v.string);
963 grecs_list_append (list, value->v.string); 930 else {
964 else 931 ptr = grecs_malloc(size);
965 { 932 if (grecs_string_convert(ptr, type, value->v.string, locus)) {
966 ptr = grecs_malloc (size); 933 free(ptr);
967 if (grecs_string_convert (ptr, type, value->v.string, locus)) 934 grecs_list_free(list);
968 { 935 return;
969 free (ptr); 936 }
970 grecs_list_free (list); 937 grecs_list_append(list, ptr);
971 return; 938 }
972 } 939 *(struct grecs_list**)target = list;
973 grecs_list_append (list, ptr); 940 } else
974 } 941 grecs_string_convert(target, GRECS_TYPE(kwp->type),
975 *(struct grecs_list**)target = list; 942 value->v.string,
976 } 943 locus);
977 else
978 grecs_string_convert (target, GRECS_TYPE (kwp->type), value->v.string,
979 locus);
980} 944}
981 945
982static void 946static void
983process_ident (struct grecs_keyword *kwp, grecs_value_t *value) 947process_ident(struct grecs_keyword *kwp, grecs_value_t *value)
984{ 948{
985 grecs_process_ident (kwp, value, CURRENT_BASE, &grecs_current_locus); 949 grecs_process_ident(kwp, value, CURRENT_BASE, &grecs_current_locus);
986} 950}
987 951
988 952
diff --git a/src/grecs-lex.l b/src/grecs-lex.l
index baf85de..9c01e0d 100644
--- a/src/grecs-lex.l
+++ b/src/grecs-lex.l
@@ -34,7 +34,7 @@
34static char *multiline_delimiter; 34static char *multiline_delimiter;
35static size_t multiline_delimiter_len; 35static size_t multiline_delimiter_len;
36static int multiline_unescape; /* Unescape here-document contents */ 36static int multiline_unescape; /* Unescape here-document contents */
37static int (*char_to_strip) (char); /* Strip matching characters of each 37static int (*char_to_strip)(char); /* Strip matching characters of each
38 here-document line */ 38 here-document line */
39 39
40grecs_locus_t grecs_current_locus; /* Input file location */ 40grecs_locus_t grecs_current_locus; /* Input file location */
@@ -50,26 +50,26 @@ static size_t xlines;
50static struct grecs_list *line_acc; 50static struct grecs_list *line_acc;
51static struct grecs_list *string_list; 51static struct grecs_list *string_list;
52 52
53static void multiline_begin (char *); 53static void multiline_begin(char *);
54static void multiline_add (char *); 54static void multiline_add(char *);
55static char *multiline_strip_tabs (char *text); 55static char *multiline_strip_tabs(char *text);
56static void line_add_unescape_last (char *text, size_t len); 56static void line_add_unescape_last(char *text, size_t len);
57static int ident (void); 57static int ident(void);
58static int isemptystr (int off); 58static int isemptystr(int off);
59 59
60static void parse_line (char *text, grecs_locus_t *ploc, size_t *pxlines); 60static void parse_line(char *text, grecs_locus_t *ploc, size_t *pxlines);
61static void parse_line_cpp (char *text, grecs_locus_t *ploc, size_t *pxlines); 61static void parse_line_cpp(char *text, grecs_locus_t *ploc, size_t *pxlines);
62 62
63#undef YY_INPUT 63#undef YY_INPUT
64 #define YY_INPUT(buf,result,max_size) \ 64 #define YY_INPUT(buf,result,max_size) \
65 do \ 65 do \
66 { \ 66 { \
67 if (grecs_preprocessor) \ 67 if (grecs_preprocessor) \
68 result = fread (buf, 1, max_size, yyin); \ 68 result = fread(buf, 1, max_size, yyin); \
69 else \ 69 else \
70 result = grecs_preproc_fill_buffer(buf, max_size); \ 70 result = grecs_preproc_fill_buffer(buf, max_size); \
71 } \ 71 } \
72 while (0) 72 while(0)
73 73
74%} 74%}
75 75
@@ -82,16 +82,16 @@ P [1-9][0-9]*
82 82
83%% 83%%
84 /* C-style comments */ 84 /* C-style comments */
85"/*" BEGIN (COMMENT); 85"/*" BEGIN(COMMENT);
86<COMMENT>[^*\n]* /* eat anything that's not a '*' */ 86<COMMENT>[^*\n]* /* eat anything that's not a '*' */
87<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ 87<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
88<COMMENT>\n ++grecs_current_locus.line; 88<COMMENT>\n ++grecs_current_locus.line;
89<COMMENT>"*"+"/" BEGIN (INITIAL); 89<COMMENT>"*"+"/" BEGIN(INITIAL);
90 /* Line directive */ 90 /* Line directive */
91^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { parse_line_cpp (yytext, 91^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { parse_line_cpp(yytext,
92 &grecs_current_locus, 92 &grecs_current_locus,
93 &xlines); } 93 &xlines); }
94^[ \t]*#[ \t]*line[ \t].*\n { parse_line (yytext, &grecs_current_locus, 94^[ \t]*#[ \t]*line[ \t].*\n { parse_line(yytext, &grecs_current_locus,
95 &xlines); } 95 &xlines); }
96 /* End-of-line comments */ 96 /* End-of-line comments */
97#.*\n { grecs_current_locus.line++; } 97#.*\n { grecs_current_locus.line++; }
@@ -99,27 +99,27 @@ P [1-9][0-9]*
99"//".*\n { grecs_current_locus.line++; } 99"//".*\n { grecs_current_locus.line++; }
100"//".* /* end-of-file comment */; 100"//".* /* end-of-file comment */;
101 /* Identifiers */ 101 /* Identifiers */
102<INITIAL>{ID} return ident (); 102<INITIAL>{ID} return ident();
103 /* Strings */ 103 /* Strings */
104[a-zA-Z0-9_\.\*/:@-]+ { grecs_line_begin (); 104[a-zA-Z0-9_\.\*/:@-]+ { grecs_line_begin();
105 grecs_line_add (yytext, yyleng); 105 grecs_line_add(yytext, yyleng);
106 yylval.string = grecs_line_finish (); 106 yylval.string = grecs_line_finish();
107 return STRING; } 107 return STRING; }
108 /* Quoted strings */ 108 /* Quoted strings */
109\"[^\\"\n]*\" { grecs_line_begin (); 109\"[^\\"\n]*\" { grecs_line_begin();
110 grecs_line_add (yytext + 1, yyleng - 2); 110 grecs_line_add(yytext + 1, yyleng - 2);
111 yylval.string = grecs_line_finish (); 111 yylval.string = grecs_line_finish();
112 return QSTRING; } 112 return QSTRING; }
113\"[^\\"\n]*\\. | 113\"[^\\"\n]*\\. |
114\"[^\\"\n]*\\\n { BEGIN (STR); 114\"[^\\"\n]*\\\n { BEGIN(STR);
115 grecs_line_begin (); 115 grecs_line_begin();
116 line_add_unescape_last (yytext + 1, yyleng - 1); } 116 line_add_unescape_last(yytext + 1, yyleng - 1); }
117<STR>[^\\"\n]*\\. | 117<STR>[^\\"\n]*\\. |
118<STR>\"[^\\"\n]*\\\n { line_add_unescape_last (yytext, yyleng); } 118<STR>\"[^\\"\n]*\\\n { line_add_unescape_last(yytext, yyleng); }
119<STR>[^\\"\n]*\" { BEGIN(INITIAL); 119<STR>[^\\"\n]*\" { BEGIN(INITIAL);
120 if (yyleng > 1) 120 if (yyleng > 1)
121 grecs_line_add (yytext, yyleng - 1); 121 grecs_line_add(yytext, yyleng - 1);
122 yylval.string = grecs_line_finish (); 122 yylval.string = grecs_line_finish();
123 return QSTRING; } 123 return QSTRING; }
124 /* Multiline strings */ 124 /* Multiline strings */
125"<<"(-" "?)?\\?{ID}[ \t]*#.*\n | 125"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
@@ -128,402 +128,375 @@ P [1-9][0-9]*
128"<<"(-" "?)?\"{ID}\"[ \t]*#.*\n | 128"<<"(-" "?)?\"{ID}\"[ \t]*#.*\n |
129"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n | 129"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n |
130"<<"(-" "?)?\"{ID}\"[ \t]*\n { 130"<<"(-" "?)?\"{ID}\"[ \t]*\n {
131 BEGIN (ML); 131 BEGIN(ML);
132 multiline_begin (yytext+2); 132 multiline_begin(yytext+2);
133 grecs_current_locus.line++; } 133 grecs_current_locus.line++; }
134 /* Ignore m4 line statements */ 134 /* Ignore m4 line statements */
135<ML>^"#line ".*\n { grecs_current_locus.line++; } 135<ML>^"#line ".*\n { grecs_current_locus.line++; }
136<ML>.*\n { char *p = multiline_strip_tabs (yytext); 136<ML>.*\n { char *p = multiline_strip_tabs(yytext);
137 137
138 if (!strncmp (p, multiline_delimiter, multiline_delimiter_len) 138 if (!strncmp(p, multiline_delimiter, multiline_delimiter_len)
139 && isemptystr (p + multiline_delimiter_len - yytext)) 139 && isemptystr(p + multiline_delimiter_len - yytext)) {
140 { 140 free(multiline_delimiter);
141 free (multiline_delimiter); 141 multiline_delimiter = NULL;
142 multiline_delimiter = NULL; 142 BEGIN(INITIAL);
143 BEGIN (INITIAL); 143 yylval.string = grecs_line_finish();
144 yylval.string = grecs_line_finish (); 144 return MSTRING;
145 return MSTRING; 145 }
146 }
147 grecs_current_locus.line++; 146 grecs_current_locus.line++;
148 multiline_add (p); } 147 multiline_add(p); }
149{WS} ; 148{WS} ;
150 /* Other tokens */ 149 /* Other tokens */
151\n { grecs_current_locus.line++; } 150\n { grecs_current_locus.line++; }
152[,;{}()] return yytext[0]; 151[,;{}()] return yytext[0];
153. { if (isascii (yytext[0]) && isprint (yytext[0])) 152. { if (isascii(yytext[0]) && isprint(yytext[0]))
154 grecs_error (&grecs_current_locus, 0, _("stray character %c"), yytext[0]); 153 grecs_error(&grecs_current_locus, 0,
154 _("stray character %c"), yytext[0]);
155 else 155 else
156 grecs_error (&grecs_current_locus, 0, _("stray character \\%03o"), 156 grecs_error(&grecs_current_locus, 0, _("stray character \\%03o"),
157 (unsigned char) yytext[0]); } 157 (unsigned char) yytext[0]); }
158%% 158%%
159 159
160pid_t grecs_preproc_pid; 160pid_t grecs_preproc_pid;
161 161
162int 162int
163yywrap () 163yywrap()
164{ 164{
165 if (yyin) 165 if (yyin)
166 grecs_preproc_extrn_shutdown (grecs_preproc_pid); 166 grecs_preproc_extrn_shutdown(grecs_preproc_pid);
167 else 167 else
168 grecs_preproc_done (); 168 grecs_preproc_done();
169 grecs_current_locus.file = NULL; 169 grecs_current_locus.file = NULL;
170 return 1; 170 return 1;
171} 171}
172 172
173static void 173static void
174line_acc_free_entry (void *ptr) 174line_acc_free_entry(void *ptr)
175{ 175{
176 free (ptr); 176 free(ptr);
177} 177}
178 178
179int 179int
180grecs_lex_begin (const char *name) 180grecs_lex_begin(const char *name)
181{ 181{
182 if (yy_flex_debug > 0) 182 if (yy_flex_debug > 0)
183 yy_flex_debug = 0; 183 yy_flex_debug = 0;
184 184
185 line_acc = grecs_list_create (); 185 line_acc = grecs_list_create();
186 line_acc->free_entry = line_acc_free_entry; 186 line_acc->free_entry = line_acc_free_entry;
187 string_list = grecs_list_create (); 187 string_list = grecs_list_create();
188
189 if (grecs_preprocessor)
190 {
191 int fd;
192 188
193 fd = open (name, O_RDONLY); 189 if (grecs_preprocessor) {
194 if (fd == -1) 190 int fd;
195 { 191
196 grecs_error (NULL, errno, _("Cannot open `%s'"), name); 192 fd = open(name, O_RDONLY);
197 return 1; 193 if (fd == -1) {
198 } 194 grecs_error(NULL, errno, _("Cannot open `%s'"), name);
199 close (fd); 195 return 1;
200 196 }
201 yyin = grecs_preproc_extrn_start (name, &grecs_preproc_pid); 197 close(fd);
202 if (!yyin) 198
203 { 199 yyin = grecs_preproc_extrn_start(name, &grecs_preproc_pid);
204 grecs_error (NULL, errno, 200 if (!yyin) {
205 _("Unable to start external preprocessor `%s'"), 201 grecs_error(NULL, errno,
206 grecs_preprocessor); 202 _("Unable to start external preprocessor `%s'"),
207 return 1; 203 grecs_preprocessor);
208 } 204 return 1;
209 } 205 }
210 else 206 } else
211 return grecs_preproc_init (name); 207 return grecs_preproc_init(name);
212 208
213 return 0; 209 return 0;
214} 210}
215 211
216void 212void
217grecs_lex_end () 213grecs_lex_end()
218{ 214{
219} 215}
220 216
221static int 217static int
222isemptystr (int off) 218isemptystr(int off)
223{ 219{
224 for (; yytext[off] && isspace (yytext[off]); off++) 220 for (; yytext[off] && isspace(yytext[off]); off++)
225 ; 221 ;
226 if (yytext[off] == ';') 222 if (yytext[off] == ';') {
227 { 223 int i;
228 int i; 224 for (i = off + 1; yytext[i]; i++)
229 for (i = off + 1; yytext[i]; i++) 225 if (!isspace(yytext[i]))
230 if (!isspace (yytext[i])) 226 return 0;
231 return 0; 227 yyless(off);
232 yyless (off); 228 return 1;
233 return 1; 229 }
234 } 230 return yytext[off] == 0;
235 return yytext[off] == 0;
236} 231}
237 232
238char * 233char *
239multiline_strip_tabs (char *text) 234multiline_strip_tabs(char *text)
240{ 235{
241 if (char_to_strip) 236 if (char_to_strip)
242 for (; *text && char_to_strip (*text); text++) 237 for (; *text && char_to_strip(*text); text++)
243 ; 238 ;
244 return text; 239 return text;
245} 240}
246 241
247static int 242static int
248unquote_char (int c) 243unquote_char(int c)
249{ 244{
250 static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; 245 static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
251 246
252 char *p; 247 char *p;
253 248
254 for (p = quote_transtab; *p; p += 2) 249 for (p = quote_transtab; *p; p += 2) {
255 { 250 if (*p == c)
256 if (*p == c) 251 return p[1];
257 return p[1]; 252 }
258 } 253 return -1;
259 return -1;
260} 254}
261 255
262struct line_acc_entry 256struct line_acc_entry
263{ 257{
264 size_t size; 258 size_t size;
265}; 259};
266#define line_acc_ptr(entry) (char*)(entry + 1) 260#define line_acc_ptr(entry) (char*)(entry + 1)
267 261
268static void 262static void
269line_acc_add_string (const char *str, size_t len) 263line_acc_add_string(const char *str, size_t len)
270{ 264{
271 struct line_acc_entry *ent = grecs_malloc (sizeof (*ent) + len + 1); 265 struct line_acc_entry *ent = grecs_malloc(sizeof(*ent) + len + 1);
272 char *p = line_acc_ptr (ent); 266 char *p = line_acc_ptr(ent);
273 memcpy (p, str, len); 267 memcpy(p, str, len);
274 p[len] = 0; 268 p[len] = 0;
275 ent->size = len; 269 ent->size = len;
276 grecs_list_append (line_acc, ent); 270 grecs_list_append(line_acc, ent);
277} 271}
278 272
279static void 273static void
280line_acc_add_char (int c) 274line_acc_add_char(int c)
281{ 275{
282 char t = c; 276 char t = c;
283 line_acc_add_string (&t, 1); 277 line_acc_add_string(&t, 1);
284} 278}
285 279
286static void 280static void
287list_acc_unescape_char (int c) 281list_acc_unescape_char(int c)
288{ 282{
289 if (c != '\n') 283 if (c != '\n') {
290 { 284 int t = unquote_char(c);
291 int t = unquote_char (c); 285 if (t != -1)
292 if (t != -1) 286 line_acc_add_char(t);
293 line_acc_add_char (t); 287 else {
294 else 288 grecs_warning(&grecs_current_locus, 0,
295 { 289 _("unknown escape sequence '\\%c'"),
296 grecs_warning(&grecs_current_locus, 0, 290 c);
297 _("unknown escape sequence '\\%c'"), 291 line_acc_add_char(c);
298 c); 292 }
299 line_acc_add_char (c);
300 } 293 }
301 }
302} 294}
303 295
304void 296void
305grecs_line_add (const char *text, size_t len) 297grecs_line_add(const char *text, size_t len)
306{ 298{
307 line_acc_add_string (text, len); 299 line_acc_add_string(text, len);
308} 300}
309 301
310/* Same, but unescapes the last character from yytext */ 302/* Same, but unescapes the last character from yytext */
311static void 303static void
312line_add_unescape_last (char *text, size_t len) 304line_add_unescape_last(char *text, size_t len)
313{ 305{
314 line_acc_add_string (text, len - 2); 306 line_acc_add_string(text, len - 2);
315 list_acc_unescape_char (text[len - 1]); 307 list_acc_unescape_char(text[len - 1]);
316} 308}
317 309
318static void 310static void
319multiline_add (char *s) 311multiline_add(char *s)
320{ 312{
321 if (multiline_unescape) 313 if (multiline_unescape) {
322 { 314 for (; *s; s++){
323 for (; *s; s++) 315 if (*s == '\\') {
324 { 316 list_acc_unescape_char(s[1]);
325 if (*s == '\\') 317 ++s;
326 { 318 } else
327 list_acc_unescape_char (s[1]); 319 line_acc_add_char(*s);
328 ++s; 320 }
329 } 321 } else
330 else 322 grecs_line_add(s, strlen(s));
331 line_acc_add_char (*s);
332 }
333 }
334 else
335 grecs_line_add (s, strlen (s));
336} 323}
337 324
338void 325void
339grecs_line_begin () 326grecs_line_begin()
340{ 327{
341 /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */ 328 /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */
342} 329}
343 330
344static int 331static int
345is_tab (char c) 332is_tab(char c)
346{ 333{
347 return c == '\t'; 334 return c == '\t';
348} 335}
349 336
350static int 337static int
351is_ws (char c) 338is_ws(char c)
352{ 339{
353 return c == '\t' || c == ' '; 340 return c == '\t' || c == ' ';
354} 341}
355 342
356void 343void
357multiline_begin (char *p) 344multiline_begin(char *p)
358{ 345{
359 if (*p == '-') 346 if (*p == '-') {
360 { 347 if (*++p == ' ') {
361 if (*++p == ' ') 348 char_to_strip = is_ws;
362 { 349 p++;
363 char_to_strip = is_ws; 350 } else
364 p++; 351 char_to_strip = is_tab;
365 } 352 } else
366 else 353 char_to_strip = NULL;
367 char_to_strip = is_tab; 354 if (*p == '\\') {
368 } 355 p++;
369 else 356 multiline_unescape = 0;
370 char_to_strip = NULL; 357 } else if (*p == '"') {
371 if (*p == '\\') 358 char *q;
372 {
373 p++;
374 multiline_unescape = 0;
375 }
376 else if (*p == '"')
377 {
378 char *q;
379 359
380 p++; 360 p++;
381 multiline_unescape = 0; 361 multiline_unescape = 0;
382 q = strchr (p, '"'); 362 q = strchr(p, '"');
383 multiline_delimiter_len = q - p; 363 multiline_delimiter_len = q - p;
384 } 364 } else {
385 else 365 multiline_delimiter_len = strcspn(p, " \t");
386 { 366 multiline_unescape = 1;
387 multiline_delimiter_len = strcspn (p, " \t"); 367 }
388 multiline_unescape = 1; 368
389 } 369 /* Remove trailing newline */
390 370 multiline_delimiter_len--;
391 /* Remove trailing newline */ 371 multiline_delimiter = grecs_malloc(multiline_delimiter_len + 1);
392 multiline_delimiter_len--; 372 memcpy(multiline_delimiter, p, multiline_delimiter_len);
393 multiline_delimiter = grecs_malloc (multiline_delimiter_len + 1); 373 multiline_delimiter[multiline_delimiter_len] = 0;
394 memcpy (multiline_delimiter, p, multiline_delimiter_len); 374 grecs_line_begin();
395 multiline_delimiter[multiline_delimiter_len] = 0;
396 grecs_line_begin ();
397} 375}
398 376
399char * 377char *
400grecs_line_finish () 378grecs_line_finish()
401{ 379{
402 struct grecs_list_entry *ep; 380 struct grecs_list_entry *ep;
403 size_t size = 0; 381 size_t size = 0;
404 char *str, *p; 382 char *str, *p;
405 383
406 for (ep = line_acc->head; ep; ep = ep->next) 384 for (ep = line_acc->head; ep; ep = ep->next) {
407 { 385 struct line_acc_entry *ent = ep->data;
408 struct line_acc_entry *ent = ep->data; 386 size += ent->size;
409 size += ent->size; 387 }
410 } 388
411 389 str = grecs_malloc(size + 1);
412 str = grecs_malloc (size + 1); 390 grecs_list_append(string_list, str);
413 grecs_list_append (string_list, str); 391 for (ep = line_acc->head, p = str; ep; ep = ep->next) {
414 for (ep = line_acc->head, p = str; ep; ep = ep->next) 392 struct line_acc_entry *ent = ep->data;
415 { 393 char *str = line_acc_ptr(ent);
416 struct line_acc_entry *ent = ep->data; 394 memcpy(p, str, ent->size);
417 char *str = line_acc_ptr (ent); 395 p += ent->size;
418 memcpy (p, str, ent->size); 396 }
419 p += ent->size; 397 *p = 0;
420 } 398 grecs_list_clear(line_acc);
421 *p = 0; 399 return str;
422 grecs_list_clear (line_acc);
423 return str;
424} 400}
425 401
426static int 402static int
427ident () 403ident()
428{ 404{
429 char *p; 405 char *p;
430 char *str; 406 char *str;
431 size_t len; 407 size_t len;
432 408
433 for (p = yytext; *p && isspace (*p); p++) 409 for (p = yytext; *p && isspace(*p); p++)
434 ; 410 ;
435 411
436 len = strlen (p); 412 len = strlen(p);
437 str = grecs_malloc (len + 1); 413 str = grecs_malloc(len + 1);
438 strcpy (str, p); 414 strcpy(str, p);
439 grecs_list_append (string_list, str); 415 grecs_list_append(string_list, str);
440 yylval.string = str; 416 yylval.string = str;
441 return IDENT; 417 return IDENT;
442} 418}
443 419
444void 420void
445grecs_lex_trace (int n) 421grecs_lex_trace(int n)
446{ 422{
447 yy_flex_debug = -n; 423 yy_flex_debug = -n;
448} 424}
449 425
450grecs_value_t * 426grecs_value_t *
451grecs_value_dup (grecs_value_t *input) 427grecs_value_dup(grecs_value_t *input)
452{ 428{
453 grecs_value_t *ptr = grecs_malloc (sizeof (*ptr)); 429 grecs_value_t *ptr = grecs_malloc(sizeof(*ptr));
454 grecs_list_append (string_list, ptr); 430 grecs_list_append(string_list, ptr);
455 *ptr = *input; 431 *ptr = *input;
456 return ptr; 432 return ptr;
457} 433}
458 434
459 435
460static int 436static int
461assign_locus (grecs_locus_t *ploc, char *name, char *line, size_t *pxlines) 437assign_locus(grecs_locus_t *ploc, char *name, char *line, size_t *pxlines)
462{ 438{
463 char *p; 439 char *p;
464 440
465 if (name) 441 if (name) {
466 { 442 if (pxlines && (!ploc->file || strcmp(name, ploc->file)))
467 if (pxlines && (!ploc->file || strcmp(name, ploc->file))) 443 *pxlines = 0;
468 *pxlines = 0; 444 ploc->file = grecs_install_text(name);
469 ploc->file = grecs_install_text (name); 445 }
470 } 446 ploc->line = strtoul(line, &p, 10) - (pxlines ? *pxlines : 0);
471 ploc->line = strtoul (line, &p, 10) - (pxlines ? *pxlines : 0); 447 return *p != 0;
472 return *p != 0;
473} 448}
474 449
475static void 450static void
476parse_line (char *text, grecs_locus_t *ploc, size_t *pxlines) 451parse_line(char *text, grecs_locus_t *ploc, size_t *pxlines)
477{ 452{
478 int rc = 1; 453 int rc = 1;
479 struct wordsplit ws; 454 struct wordsplit ws;
480 455
481 if (wordsplit (text, &ws, WRDSF_DEFFLAGS)) 456 if (wordsplit(text, &ws, WRDSF_DEFFLAGS))
482 grecs_error (ploc, 0, _("cannot parse #line line")); 457 grecs_error(ploc, 0, _("cannot parse #line line"));
483 else 458 else {
484 { 459 if (ws.ws_wordc == 2)
485 if (ws.ws_wordc == 2) 460 rc = assign_locus(ploc, NULL,
486 rc = assign_locus (ploc, NULL, ws.ws_wordv[1], pxlines); 461 ws.ws_wordv[1], pxlines);
487 else if (ws.ws_wordc == 3) 462 else if (ws.ws_wordc == 3)
488 rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines); 463 rc = assign_locus(ploc, ws.ws_wordv[2],
489 else if (ws.ws_wordc == 4) 464 ws.ws_wordv[1], pxlines);
490 { 465 else if (ws.ws_wordc == 4) {
491 rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], 0); 466 rc = assign_locus(ploc, ws.ws_wordv[2],
492 if (rc == 0) 467 ws.ws_wordv[1], 0);
493 { 468 if (rc == 0) {
494 char *p; 469 char *p;
495 unsigned long x = strtoul (ws.ws_wordv[3], &p, 10); 470 unsigned long x = strtoul(ws.ws_wordv[3],
496 rc = *p != 0; 471 &p, 10);
497 if (rc == 0) 472 rc = *p != 0;
498 *pxlines = x; 473 if (rc == 0)
499 } 474 *pxlines = x;
500 } 475 }
501 else 476 } else
502 grecs_error (ploc, 0, _("invalid #line statement")); 477 grecs_error(ploc, 0, _("invalid #line statement"));
503 478
504 if (rc) 479 if (rc)
505 grecs_error (ploc, 0, _("malformed #line statement")); 480 grecs_error(ploc, 0, _("malformed #line statement"));
506 wordsplit_free (&ws); 481 wordsplit_free(&ws);
507 } 482 }
508} 483}
509 484
510static void 485static void
511parse_line_cpp (char *text, grecs_locus_t *ploc, size_t *pxlines) 486parse_line_cpp(char *text, grecs_locus_t *ploc, size_t *pxlines)
512{ 487{
513 struct wordsplit ws; 488 struct wordsplit ws;
514 489
515 if (wordsplit (text, &ws, WRDSF_DEFFLAGS)) 490 if (wordsplit(text, &ws, WRDSF_DEFFLAGS)) {
516 { 491 grecs_error(ploc, 0, _("cannot parse #line line"));
517 grecs_error (ploc, 0, _("cannot parse #line line")); 492 return;
518 return; 493 } else if (ws.ws_wordc < 3)
519 } 494 grecs_error(ploc, 0, _("invalid #line statement"));
520 else if (ws.ws_wordc < 3) 495 else {
521 grecs_error (ploc, 0, _("invalid #line statement")); 496 if (assign_locus(ploc, ws.ws_wordv[2],
522 else 497 ws.ws_wordv[1], pxlines))
523 { 498 grecs_error(ploc, 0, _("malformed #line statement"));
524 if (assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines)) 499 }
525 grecs_error (ploc, 0, _("malformed #line statement")); 500 wordsplit_free(&ws);
526 }
527 wordsplit_free (&ws);
528} 501}
529 502
diff --git a/src/grecs.h b/src/grecs.h
index ec98979..5769736 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -28,37 +28,37 @@
28# endif 28# endif
29#endif 29#endif
30#ifndef _ 30#ifndef _
31# define _(msgid) gettext (msgid) 31# define _(msgid) gettext(msgid)
32#endif 32#endif
33#ifndef N_ 33#ifndef N_
34# define N_(s) s 34# define N_(s) s
35#endif 35#endif
36 36
37typedef struct { 37typedef struct {
38 char *file; 38 char *file;
39 int line; 39 int line;
40} grecs_locus_t; 40} grecs_locus_t;
41 41
42extern grecs_locus_t grecs_locus; 42extern grecs_locus_t grecs_locus;
43 43
44enum grecs_data_type { 44enum grecs_data_type {
45 grecs_type_void, 45 grecs_type_void,
46 grecs_type_string, 46 grecs_type_string,
47 grecs_type_short, 47 grecs_type_short,
48 grecs_type_ushort, 48 grecs_type_ushort,
49 grecs_type_int, 49 grecs_type_int,
50 grecs_type_uint, 50 grecs_type_uint,
51 grecs_type_long, 51 grecs_type_long,
52 grecs_type_ulong, 52 grecs_type_ulong,
53 grecs_type_size, 53 grecs_type_size,
54/* grecs_type_off,*/ 54/* grecs_type_off,*/
55 grecs_type_time, 55 grecs_type_time,
56 grecs_type_bool, 56 grecs_type_bool,
57 grecs_type_ipv4, 57 grecs_type_ipv4,
58 grecs_type_cidr, 58 grecs_type_cidr,
59 grecs_type_host, 59 grecs_type_host,
60 grecs_type_sockaddr, 60 grecs_type_sockaddr,
61 grecs_type_section 61 grecs_type_section
62}; 62};
63 63
64#define GRECS_LIST 0x8000 64#define GRECS_LIST 0x8000
@@ -67,9 +67,9 @@ enum grecs_data_type {
67#define GRECS_IS_LIST(c) ((c) & GRECS_LIST) 67#define GRECS_IS_LIST(c) ((c) & GRECS_LIST)
68 68
69enum grecs_callback_command { 69enum grecs_callback_command {
70 grecs_callback_section_begin, 70 grecs_callback_section_begin,
71 grecs_callback_section_end, 71 grecs_callback_section_end,
72 grecs_callback_set_value 72 grecs_callback_set_value
73}; 73};
74 74
75#define GRECS_TYPE_STRING 0 75#define GRECS_TYPE_STRING 0
@@ -89,45 +89,45 @@ struct grecs_list {
89}; 89};
90 90
91typedef struct grecs_value { 91typedef struct grecs_value {
92 int type; 92 int type;
93 union { 93 union {
94 struct grecs_list *list; 94 struct grecs_list *list;
95 const char *string; 95 const char *string;
96 struct { 96 struct {
97 size_t c; 97 size_t c;
98 struct grecs_value *v; 98 struct grecs_value *v;
99 } arg; 99 } arg;
100 } v; 100 } v;
101} grecs_value_t; 101} grecs_value_t;
102 102
103typedef int (*grecs_callback_fn) ( 103typedef int (*grecs_callback_fn)(
104 enum grecs_callback_command cmd, 104 enum grecs_callback_command cmd,
105 grecs_locus_t * /* locus */, 105 grecs_locus_t * /* locus */,
106 void * /* varptr */, 106 void * /* varptr */,
107 grecs_value_t * /* value */, 107 grecs_value_t * /* value */,
108 void * /* cb_data */ 108 void * /* cb_data */
109 ); 109 );
110 110
111struct grecs_keyword { 111struct grecs_keyword {
112 const char *ident; 112 const char *ident;
113 const char *argname; 113 const char *argname;
114 const char *docstring; 114 const char *docstring;
115 enum grecs_data_type type; 115 enum grecs_data_type type;
116 void *varptr; 116 void *varptr;
117 size_t offset; 117 size_t offset;
118 grecs_callback_fn callback; 118 grecs_callback_fn callback;
119 void *callback_data; 119 void *callback_data;
120 struct grecs_keyword *kwd; 120 struct grecs_keyword *kwd;
121}; 121};
122 122
123struct grecs_sockaddr { 123struct grecs_sockaddr {
124 int len; 124 int len;
125 struct sockaddr *sa; 125 struct sockaddr *sa;
126}; 126};
127 127
128extern void *(*grecs_malloc_fun)(size_t size); 128extern void *(*grecs_malloc_fun)(size_t size);
129extern void *(*grecs_realloc_fun)(void *ptr, size_t size); 129extern void *(*grecs_realloc_fun)(void *ptr, size_t size);
130extern void (*grecs_alloc_die_fun) (void); 130extern void (*grecs_alloc_die_fun)(void);
131 131
132void *grecs_malloc(size_t size); 132void *grecs_malloc(size_t size);
133void *grecs_zalloc(size_t size); 133void *grecs_zalloc(size_t size);
@@ -146,22 +146,22 @@ void grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...)
146 __attribute__ ((__format__ (__printf__, 3, 4))); 146 __attribute__ ((__format__ (__printf__, 3, 4)));
147void grecs_set_keywords(struct grecs_keyword *kwd); 147void grecs_set_keywords(struct grecs_keyword *kwd);
148void grecs_gram_trace(int n); 148void grecs_gram_trace(int n);
149void grecs_lex_trace (int n); 149void grecs_lex_trace(int n);
150 150
151int grecs_lex_begin(const char*); 151int grecs_lex_begin(const char*);
152void grecs_lex_end(void); 152void grecs_lex_end(void);
153int grecs_parse (const char *name); 153int grecs_parse(const char *name);
154 154
155void grecs_line_begin (void); 155void grecs_line_begin(void);
156void grecs_line_add (const char *text, size_t len); 156void grecs_line_add(const char *text, size_t len);
157char *grecs_line_finish (void); 157char *grecs_line_finish(void);
158 158
159extern int grecs_string_convert (void *target, enum grecs_data_type type, 159extern int grecs_string_convert(void *target, enum grecs_data_type type,
160 const char *string, grecs_locus_t *locus); 160 const char *string, grecs_locus_t *locus);
161extern void grecs_process_ident (struct grecs_keyword *kwp, 161extern void grecs_process_ident(struct grecs_keyword *kwp,
162 grecs_value_t *value, 162 grecs_value_t *value,
163 void *base, 163 void *base,
164 grecs_locus_t *locus); 164 grecs_locus_t *locus);
165 165
166extern grecs_locus_t grecs_current_locus; 166extern grecs_locus_t grecs_current_locus;
167extern int grecs_error_count; 167extern int grecs_error_count;
@@ -169,48 +169,48 @@ extern int grecs_default_port;
169 169
170extern const char *grecs_preprocessor; 170extern const char *grecs_preprocessor;
171extern int grecs_log_to_stderr; 171extern int grecs_log_to_stderr;
172extern void (*grecs_log_setup_hook) (); 172extern void (*grecs_log_setup_hook)();
173 173
174size_t grecs_preproc_fill_buffer (char *buf, size_t size); 174size_t grecs_preproc_fill_buffer(char *buf, size_t size);
175void grecs_preproc_add_include_dir (char *dir); 175void grecs_preproc_add_include_dir(char *dir);
176int grecs_preproc_init (const char *name); 176int grecs_preproc_init(const char *name);
177void grecs_preproc_done (void); 177void grecs_preproc_done(void);
178int grecs_preproc_run (const char *config_file, const char *extpp); 178int grecs_preproc_run(const char *config_file, const char *extpp);
179 179
180FILE *grecs_preproc_extrn_start (const char *file, pid_t *ppid); 180FILE *grecs_preproc_extrn_start(const char *file, pid_t *ppid);
181void grecs_preproc_extrn_shutdown (pid_t pid); 181void grecs_preproc_extrn_shutdown(pid_t pid);
182 182
183char *grecs_install_text (const char *str); 183char *grecs_install_text(const char *str);
184void grecs_destroy_text (void); 184void grecs_destroy_text(void);
185 185
186void grecs_include_path_setup (const char *dir, ...); 186void grecs_include_path_setup(const char *dir, ...);
187void grecs_include_path_setup_v (char **dirs); 187void grecs_include_path_setup_v(char **dirs);
188 188
189const char *grecs_data_type_string (enum grecs_data_type type); 189const char *grecs_data_type_string(enum grecs_data_type type);
190void grecs_format_docstring (FILE *stream, const char *docstring, 190void grecs_format_docstring(FILE *stream, const char *docstring,
191 unsigned level); 191 unsigned level);
192void grecs_format_simple_statement (FILE *stream, struct grecs_keyword *kwp, 192void grecs_format_simple_statement(FILE *stream, struct grecs_keyword *kwp,
193 unsigned level); 193 unsigned level);
194void grecs_format_block_statement (FILE *stream, struct grecs_keyword *kwp, 194void grecs_format_block_statement(FILE *stream, struct grecs_keyword *kwp,
195 unsigned level); 195 unsigned level);
196void grecs_format_statement_array (FILE *stream, struct grecs_keyword *kwp, 196void grecs_format_statement_array(FILE *stream, struct grecs_keyword *kwp,
197 unsigned n, 197 unsigned n,
198 unsigned level); 198 unsigned level);
199 199
200 200
201struct grecs_list *grecs_list_create (void); 201struct grecs_list *grecs_list_create(void);
202size_t grecs_list_size (struct grecs_list *lp); 202size_t grecs_list_size(struct grecs_list *lp);
203void grecs_list_append (struct grecs_list *lp, void *val); 203void grecs_list_append(struct grecs_list *lp, void *val);
204void grecs_list_push (struct grecs_list *lp, void *val); 204void grecs_list_push(struct grecs_list *lp, void *val);
205void *grecs_list_pop (struct grecs_list *lp); 205void *grecs_list_pop(struct grecs_list *lp);
206void *grecs_list_locate (struct grecs_list *lp, void *data); 206void *grecs_list_locate(struct grecs_list *lp, void *data);
207void *grecs_list_index (struct grecs_list *lp, size_t idx); 207void *grecs_list_index(struct grecs_list *lp, size_t idx);
208void *grecs_list_remove_tail (struct grecs_list *lp); 208void *grecs_list_remove_tail(struct grecs_list *lp);
209void grecs_list_clear (struct grecs_list *lp); 209void grecs_list_clear(struct grecs_list *lp);
210void grecs_list_free (struct grecs_list *lp); 210void grecs_list_free(struct grecs_list *lp);
211 211
212int grecs_vasprintf (char **pbuf, size_t *psize, const char *fmt, va_list ap); 212int grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap);
213int grecs_asprintf (char **pbuf, size_t *psize, const char *fmt, ...); 213int grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...);
214 214
215struct grecs_symtab; 215struct grecs_symtab;
216 216
diff --git a/src/list.c b/src/list.c
index 4a5d3f6..7d7f934 100644
--- a/src/list.c
+++ b/src/list.c
@@ -23,139 +23,132 @@
23#include <string.h> 23#include <string.h>
24 24
25struct grecs_list * 25struct grecs_list *
26grecs_list_create () 26grecs_list_create()
27{ 27{
28 struct grecs_list *lp = grecs_malloc (sizeof (*lp)); 28 struct grecs_list *lp = grecs_malloc(sizeof(*lp));
29 memset (lp, 0, sizeof (*lp)); 29 memset(lp, 0, sizeof(*lp));
30 return lp; 30 return lp;
31} 31}
32 32
33size_t 33size_t
34grecs_list_size (struct grecs_list *lp) 34grecs_list_size(struct grecs_list *lp)
35{ 35{
36 return lp ? lp->count : 0; 36 return lp ? lp->count : 0;
37} 37}
38 38
39void 39void
40grecs_list_append (struct grecs_list *lp, void *val) 40grecs_list_append(struct grecs_list *lp, void *val)
41{ 41{
42 struct grecs_list_entry *ep = grecs_malloc (sizeof (*ep)); 42 struct grecs_list_entry *ep = grecs_malloc(sizeof(*ep));
43 ep->data = val; 43 ep->data = val;
44 ep->next = NULL; 44 ep->next = NULL;
45 if (lp->tail) 45 if (lp->tail)
46 lp->tail->next = ep; 46 lp->tail->next = ep;
47 else 47 else
48 lp->head = ep; 48 lp->head = ep;
49 lp->tail = ep; 49 lp->tail = ep;
50 lp->count++; 50 lp->count++;
51} 51}
52 52
53void 53void
54grecs_list_push (struct grecs_list *lp, void *val) 54grecs_list_push(struct grecs_list *lp, void *val)
55{ 55{
56 struct grecs_list_entry *ep = grecs_malloc (sizeof (*ep)); 56 struct grecs_list_entry *ep = grecs_malloc(sizeof(*ep));
57 ep->data = val; 57 ep->data = val;
58 ep->next = lp->head; 58 ep->next = lp->head;
59 lp->head = ep; 59 lp->head = ep;
60 lp->count++; 60 lp->count++;
61} 61}
62 62
63void * 63void *
64grecs_list_pop (struct grecs_list *lp) 64grecs_list_pop(struct grecs_list *lp)
65{ 65{
66 void *data; 66 void *data;
67 struct grecs_list_entry *ep = lp->head; 67 struct grecs_list_entry *ep = lp->head;
68 if (ep) 68 if (ep){
69 { 69 data = ep->data;
70 data = ep->data; 70 lp->head = ep->next;
71 lp->head = ep->next; 71 if (!lp->head)
72 if (!lp->head) 72 lp->tail = NULL;
73 lp->tail = NULL; 73 lp->count--;
74 lp->count--; 74 free (ep);
75 free (ep); 75 } else
76 } 76 data = NULL;
77 else 77 return data;
78 data = NULL;
79 return data;
80} 78}
81 79
82void 80void
83grecs_list_clear (struct grecs_list *lp) 81grecs_list_clear(struct grecs_list *lp)
84{ 82{
85 struct grecs_list_entry *ep = lp->head; 83 struct grecs_list_entry *ep = lp->head;
86 84
87 while (ep) 85 while (ep) {
88 { 86 struct grecs_list_entry *next = ep->next;
89 struct grecs_list_entry *next = ep->next; 87 if (lp->free_entry)
90 if (lp->free_entry) 88 lp->free_entry(ep->data);
91 lp->free_entry (ep->data); 89 free(ep);
92 free (ep); 90 ep = next;
93 ep = next; 91 }
94 } 92 lp->head = lp->tail = NULL;
95 lp->head = lp->tail = NULL; 93 lp->count = 0;
96 lp->count = 0;
97} 94}
98 95
99void 96void
100grecs_list_free (struct grecs_list *lp) 97grecs_list_free(struct grecs_list *lp)
101{ 98{
102 grecs_list_clear (lp); 99 grecs_list_clear(lp);
103 free (lp); 100 free(lp);
104} 101}
105 102
106static int 103static int
107_ptrcmp (const void *a, const void *b) 104_ptrcmp(const void *a, const void *b)
108{ 105{
109 return a != b; 106 return a != b;
110} 107}
111 108
112void * 109void *
113grecs_list_locate (struct grecs_list *lp, void *data) 110grecs_list_locate(struct grecs_list *lp, void *data)
114{ 111{
115 struct grecs_list_entry *ep; 112 struct grecs_list_entry *ep;
116 int (*cmp)(const void *, const void *) = lp->cmp ? lp->cmp : _ptrcmp; 113 int (*cmp)(const void *, const void *) = lp->cmp ? lp->cmp : _ptrcmp;
117 114
118 for (ep = lp->head; ep; ep = ep->next) 115 for (ep = lp->head; ep; ep = ep->next) {
119 { 116 if (cmp(ep->data, data) == 0)
120 if (cmp (ep->data, data) == 0) 117 return ep->data;
121 return ep->data; 118 }
122 } 119 return NULL;
123 return NULL;
124} 120}
125 121
126void * 122void *
127grecs_list_index (struct grecs_list *lp, size_t idx) 123grecs_list_index(struct grecs_list *lp, size_t idx)
128{ 124{
129 struct grecs_list_entry *ep; 125 struct grecs_list_entry *ep;
130 126
131 for (ep = lp->head; ep && idx; ep = ep->next, idx--) 127 for (ep = lp->head; ep && idx; ep = ep->next, idx--)
132 ; 128 ;
133 return ep ? ep->data : NULL; 129 return ep ? ep->data : NULL;
134} 130}
135 131
136void * 132void *
137grecs_list_remove_tail (struct grecs_list *lp) 133grecs_list_remove_tail(struct grecs_list *lp)
138{ 134{
139 void *data; 135 void *data;
140 136
141 if (!lp->head) 137 if (!lp->head)
142 return NULL; 138 return NULL;
143 data = lp->tail; 139 data = lp->tail;
144 if (lp->head == lp->tail) 140 if (lp->head == lp->tail) {
145 { 141 free(lp->tail);
146 free (lp->tail); 142 lp->head = lp->tail = NULL;
147 lp->head = lp->tail = NULL; 143 lp->count = 0;
148 lp->count = 0; 144 } else {
149 } 145 struct grecs_list_entry *ep;
150 else
151 {
152 struct grecs_list_entry *ep;
153 146
154 for (ep = lp->head; ep->next != lp->tail; ep = ep->next) 147 for (ep = lp->head; ep->next != lp->tail; ep = ep->next)
155 ; 148 ;
156 free (lp->tail); 149 free(lp->tail);
157 ep->next = NULL; 150 ep->next = NULL;
158 lp->tail = ep; 151 lp->tail = ep;
159 } 152 }
160 return data; 153 return data;
161} 154}
diff --git a/src/preproc.c b/src/preproc.c
index 7ea9442..06924c1 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -34,20 +34,18 @@
34int grecs_log_to_stderr = 1; 34int grecs_log_to_stderr = 1;
35void (*grecs_log_setup_hook) () = NULL; 35void (*grecs_log_setup_hook) () = NULL;
36 36
37struct input_file_ident 37struct input_file_ident {
38{ 38 ino_t i_node;
39 ino_t i_node; 39 dev_t device;
40 dev_t device;
41}; 40};
42 41
43struct buffer_ctx 42struct buffer_ctx {
44{ 43 struct buffer_ctx *prev;/* Pointer to previous context */
45 struct buffer_ctx *prev;/* Pointer to previous context */ 44 grecs_locus_t locus; /* Current input location */
46 grecs_locus_t locus; /* Current input location */ 45 size_t namelen; /* Length of the file name */
47 size_t namelen; /* Length of the file name */ 46 size_t xlines; /* Number of #line directives output so far */
48 size_t xlines; /* Number of #line directives output so far */ 47 struct input_file_ident id;
49 struct input_file_ident id; 48 FILE *infile;
50 FILE *infile;
51}; 49};
52 50
53extern int yy_grecs_flex_debug; 51extern int yy_grecs_flex_debug;
@@ -69,669 +67,629 @@ static int pop_source (void);
69static int parse_include (const char *text, int once); 67static int parse_include (const char *text, int once);
70 68
71static ssize_t 69static ssize_t
72pp_getline (char **pbuf, size_t *psize, FILE *fp) 70pp_getline(char **pbuf, size_t *psize, FILE *fp)
73{ 71{
74 char *buf = *pbuf; 72 char *buf = *pbuf;
75 size_t size = *psize; 73 size_t size = *psize;
76 ssize_t off = 0; 74 ssize_t off = 0;
77 75
78 do 76 do {
79 { 77 if (off == size - 1) {
80 size_t len; 78 if (!buf) {
81 79 size = 1;
82 if (off == size - 1) 80 buf = grecs_malloc(size);
83 { 81 } else {
84 if (!buf) 82 size_t nsize = 2 * size;
85 { 83 if (nsize < size)
86 size = 1; 84 grecs_alloc_die();
87 buf = grecs_malloc (size); 85 buf = grecs_realloc(buf, nsize);
88 } 86 size = nsize;
89 else 87 }
90 { 88 }
91 size_t nsize = 2 * size; 89 if (!fgets(buf + off, size - off, fp)) {
92 if (nsize < size) 90 if (off == 0)
93 grecs_alloc_die (); 91 off = -1;
94 buf = grecs_realloc (buf, nsize); 92 break;
95 size = nsize; 93 }
96 } 94 off += strlen(buf + off);
97 }
98 if (!fgets (buf + off, size - off, fp))
99 {
100 if (off == 0)
101 off = -1;
102 break;
103 } 95 }
104 off += strlen (buf + off); 96 while (buf[off - 1] != '\n');
105 }
106 while (buf[off - 1] != '\n');
107 97
108 *pbuf = buf; 98 *pbuf = buf;
109 *psize = size; 99 *psize = size;
110 return off; 100 return off;
111} 101}
112 102
113
114static void 103static void
115putback (const char *str) 104putback(const char *str)
116{ 105{
117 size_t len; 106 size_t len;
118 107
119 if (!*str) 108 if (!*str)
120 return; 109 return;
121 len = strlen (str) + 1; 110 len = strlen(str) + 1;
122 if (len > putback_max) 111 if (len > putback_max) {
123 { 112 putback_max = len;
124 putback_max = len; 113 putback_buffer = grecs_realloc(putback_buffer, putback_max);
125 putback_buffer = grecs_realloc (putback_buffer, putback_max); 114 }
126 } 115 strcpy(putback_buffer, str);
127 strcpy (putback_buffer, str); 116 putback_size = len - 1;
128 putback_size = len - 1;
129} 117}
130 118
131static void 119static void
132pp_line_stmt () 120pp_line_stmt()
133{ 121{
134 size_t ls_size; 122 size_t ls_size;
135 size_t pb_size; 123 size_t pb_size;
136 124
137 if (grecs_asprintf (&linebufbase, &linebufsize, "#line %lu \"%s\" %lu\n", 125 if (grecs_asprintf(&linebufbase, &linebufsize,
138 (unsigned long) LOCUS.line, 126 "#line %lu \"%s\" %lu\n",
139 LOCUS.file, (unsigned long) context_stack->xlines)) 127 (unsigned long) LOCUS.line,
140 grecs_alloc_die (); 128 LOCUS.file, (unsigned long) context_stack->xlines))
141 129 grecs_alloc_die();
142 ls_size = strlen (linebufbase); 130
143 pb_size = putback_size + ls_size + 1; 131 ls_size = strlen(linebufbase);
144 132 pb_size = putback_size + ls_size + 1;
145 if (pb_size > putback_max) 133
146 { 134 if (pb_size > putback_max) {
147 putback_max = pb_size; 135 putback_max = pb_size;
148 putback_buffer = grecs_realloc (putback_buffer, putback_max); 136 putback_buffer = grecs_realloc(putback_buffer, putback_max);
149 } 137 }
150 138
151 context_stack->xlines++; 139 context_stack->xlines++;
152 strcpy (putback_buffer + putback_size, linebufbase); 140 strcpy(putback_buffer + putback_size, linebufbase);
153 putback_size += ls_size; 141 putback_size += ls_size;
154} 142}
155 143
156 #define STRMATCH(p, len, s) (len >= sizeof(s) \ 144 #define STRMATCH(p, len, s) (len >= sizeof(s) \
157 && memcmp (p, s, sizeof(s) - 1) == 0 \ 145 && memcmp(p, s, sizeof(s) - 1) == 0 \
158 && isspace(p[sizeof(s) - 1])) 146 && isspace(p[sizeof(s) - 1]))
159 147
160static int 148static int
161next_line () 149next_line()
162{ 150{
163 ssize_t rc; 151 ssize_t rc;
164 152
165 do 153 do {
166 { 154 if (putback_size) {
167 if (putback_size) 155 if (putback_size + 1 > bufsize) {
168 { 156 bufsize = putback_size + 1;
169 if (putback_size + 1 > bufsize) 157 linebuf = grecs_realloc(linebuf, bufsize);
170 { 158 }
171 bufsize = putback_size + 1; 159 strcpy(linebuf, putback_buffer);
172 linebuf = grecs_realloc (linebuf, bufsize); 160 rc = putback_size;
173 } 161 putback_size = 0;
174 strcpy (linebuf, putback_buffer); 162 }
175 rc = putback_size; 163 else if (!context_stack)
176 putback_size = 0; 164 return 0;
177 } 165 else
178 else if (!context_stack) 166 rc = pp_getline(&linebuf, &bufsize, INFILE);
179 return 0; 167 } while (rc == -1 && pop_source() == 0);
180 else 168 return rc;
181 rc = pp_getline (&linebuf, &bufsize, INFILE);
182 }
183 while (rc == -1 && pop_source () == 0);
184 return rc;
185} 169}
186 170
187size_t 171size_t
188grecs_preproc_fill_buffer (char *buf, size_t size) 172grecs_preproc_fill_buffer(char *buf, size_t size)
189{ 173{
190 size_t bufsize = size; 174 size_t bufsize = size;
191 175
192 while (next_line () > 0) 176 while (next_line() > 0) {
193 { 177 char *p;
194 char *p; 178 size_t len;
195 size_t len; 179 int is_line = 0;
196 int is_line = 0; 180
197 181 for (p = linebuf; *p && isspace(*p); p++)
198 for (p = linebuf; *p && isspace (*p); p++) 182 ;
199 ; 183 if (*p == '#') {
200 if (*p == '#') 184 size_t l;
201 { 185 for (p++; *p && isspace(*p); p++)
202 size_t l; 186 ;
203 for (p++; *p && isspace (*p); p++) 187 l = strlen(p);
204 ; 188 if (STRMATCH(p, l, "include_once")) {
205 l = strlen (p); 189 if (parse_include(linebuf, 1))
206 if (STRMATCH (p, l, "include_once")) 190 putback("/*include_once*/\n");
207 { 191 continue;
208 if (parse_include (linebuf, 1)) 192 } else if (STRMATCH(p, l, "include")) {
209 putback ("/*include_once*/\n"); 193 if (parse_include(linebuf, 0))
210 continue; 194 putback("/*include*/\n");
211 } 195 continue;
212 else if (STRMATCH (p, l, "include")) 196 } else if (STRMATCH(p, l, "line"))
213 { 197 is_line = 1;
214 if (parse_include (linebuf, 0)) 198 }
215 putback ("/*include*/\n");
216 continue;
217 }
218 else if (STRMATCH (p, l, "line"))
219 is_line = 1;
220 }
221
222 len = strlen (linebuf);
223
224 if (len > size)
225 len = size;
226 199
227 memcpy (buf, linebuf, len); 200 len = strlen(linebuf);
228 buf += len; 201
229 size -= len; 202 if (len > size)
203 len = size;
204
205 memcpy(buf, linebuf, len);
206 buf += len;
207 size -= len;
208
209 if (size == 0) {
210 putback(linebuf + len);
211 break;
212 }
230 213
231 if (size == 0) 214 if (!is_line && len > 0 && linebuf[len - 1] == '\n')
232 { 215 LOCUS.line++;
233 putback (linebuf + len);
234 break;
235 } 216 }
236 217 return bufsize - size;
237 if (!is_line && len > 0 && linebuf[len - 1] == '\n')
238 LOCUS.line++;
239 }
240 return bufsize - size;
241} 218}
242 219
243#define STAT_ID_EQ(st,id) ((id).i_node == (st).st_ino \ 220#define STAT_ID_EQ(st,id) ((id).i_node == (st).st_ino \
244 && (id).device == (st).st_dev) 221 && (id).device == (st).st_dev)
245 222
246static struct buffer_ctx * 223static struct buffer_ctx *
247ctx_lookup (struct stat *st) 224ctx_lookup(struct stat *st)
248{ 225{
249 struct buffer_ctx *ctx; 226 struct buffer_ctx *ctx;
250 227
251 if (!context_stack) 228 if (!context_stack)
252 return NULL; 229 return NULL;
253 230
254 for (ctx = context_stack->prev; ctx; ctx = ctx->prev) 231 for (ctx = context_stack->prev; ctx; ctx = ctx->prev)
255 if (STAT_ID_EQ (*st, ctx->id)) 232 if (STAT_ID_EQ(*st, ctx->id))
256 break; 233 break;
257 return ctx; 234 return ctx;
258} 235}
259 236
260const char *grecs_preprocessor = NULL; 237const char *grecs_preprocessor = NULL;
261static struct grecs_list *include_path; 238static struct grecs_list *include_path;
262static struct grecs_list *std_include_path; 239static struct grecs_list *std_include_path;
263 240
264struct file_data 241struct file_data {
265{ 242 const char *name;
266 const char *name; 243 size_t namelen;
267 size_t namelen; 244 char *buf;
268 char *buf; 245 size_t buflen;
269 size_t buflen; 246 int found;
270 int found;
271}; 247};
272 248
273static int 249static int
274pp_list_find (struct grecs_list *list, struct file_data *dptr) 250pp_list_find(struct grecs_list *list, struct file_data *dptr)
275{ 251{
276 struct grecs_list_entry *ep; 252 struct grecs_list_entry *ep;
277 253
278 for (ep = list->head; !dptr->found && ep; ep = ep->next) 254 for (ep = list->head; !dptr->found && ep; ep = ep->next) {
279 { 255 const char *dir = ep->data;
280 const char *dir = ep->data; 256 size_t size = strlen (dir) + 1 + dptr->namelen + 1;
281 size_t size = strlen (dir) + 1 + dptr->namelen + 1; 257 if (size > dptr->buflen) {
282 if (size > dptr->buflen) 258 dptr->buflen = size;
283 { 259 dptr->buf = grecs_realloc(dptr->buf, dptr->buflen);
284 dptr->buflen = size; 260 }
285 dptr->buf = grecs_realloc (dptr->buf, dptr->buflen); 261 strcpy(dptr->buf, dir);
262 strcat(dptr->buf, "/");
263 strcat(dptr->buf, dptr->name);
264 dptr->found = access(dptr->buf, F_OK) == 0;
286 } 265 }
287 strcpy (dptr->buf, dir); 266 return dptr->found;
288 strcat (dptr->buf, "/"); 267}
289 strcat (dptr->buf, dptr->name); 268
290 dptr->found = access (dptr->buf, F_OK) == 0; 269static void
291 } 270incl_free(void *data)
292 return dptr->found; 271{
272 free(data);
293} 273}
294 274
295void 275void
296grecs_include_path_setup_v (char **dirs) 276grecs_include_path_setup_v(char **dirs)
297{ 277{
298 if (!include_path) 278 if (!include_path) {
299 include_path = grecs_list_create (); 279 include_path = grecs_list_create();
300 std_include_path = grecs_list_create (); 280 include_path->free_entry = incl_free;
301 if (dirs) 281 }
302 { 282 std_include_path = grecs_list_create();
303 int i; 283 std_include_path->free_entry = incl_free;
304 for (i = 0; dirs[i]; i++) 284 if (dirs) {
305 /* FIXME: Element never freed */ 285 int i;
306 grecs_list_append (std_include_path, grecs_strdup (dirs[i])); 286 for (i = 0; dirs[i]; i++)
307 } 287 /* FIXME: Element never freed */
288 grecs_list_append(std_include_path,
289 grecs_strdup(dirs[i]));
290 }
308} 291}
309 292
310void 293void
311grecs_include_path_setup (const char *dir, ...) 294grecs_include_path_setup(const char *dir, ...)
312{ 295{
313 const char *p; 296 const char *p;
314 char **argv = NULL; 297 char **argv = NULL;
315 size_t argc = 0; 298 size_t argc = 0;
316 size_t argi = 0; 299 size_t argi = 0;
317 va_list ap; 300 va_list ap;
318 301
319 va_start (ap, dir); 302 va_start(ap, dir);
320 p = dir; 303 p = dir;
321 while (1) 304 while (1) {
322 { 305 if (argi == argc) {
323 if (argi == argc) 306 if (argc == 0)
324 { 307 argc = 16;
325 if (argc == 0) 308 else
326 argc = 16; 309 argc += 16;
327 else 310 argv = grecs_realloc(argv, argc * sizeof(argv[0]));
328 argc += 16; 311 }
329 argv = grecs_realloc (argv, argc * sizeof (argv[0])); 312 argv[argi++] = (char*) p;
313 if (!p)
314 break;
315 p = va_arg(ap, const char*);
330 } 316 }
331 argv[argi++] = (char*) p; 317 grecs_include_path_setup_v(argv);
332 if (!p) 318 free(argv);
333 break; 319 va_end(ap);
334 p = va_arg (ap, const char*);
335 }
336 grecs_include_path_setup_v (argv);
337 free (argv);
338 va_end (ap);
339} 320}
340 321
341void 322void
342grecs_preproc_add_include_dir (char *dir) 323grecs_preproc_add_include_dir(char *dir)
343{ 324{
344 if (!include_path) 325 if (!include_path) {
345 include_path = grecs_list_create (); 326 include_path = grecs_list_create();
346 grecs_list_append (include_path, dir); 327 include_path->free_entry = incl_free;
328 }
329 grecs_list_append(include_path, grecs_strdup(dir));
347} 330}
348 331
349static struct grecs_symtab *incl_sources; 332static struct grecs_symtab *incl_sources;
350 333
351/* Calculate the hash of a struct input_file_ident. */ 334/* Calculate the hash of a struct input_file_ident. */
352static unsigned 335static unsigned
353incl_hasher (void *data, unsigned long n_buckets) 336incl_hasher(void *data, unsigned long n_buckets)
354{ 337{
355 const struct input_file_ident *id = data; 338 const struct input_file_ident *id = data;
356 return (id->i_node + id->device) % n_buckets; 339 return (id->i_node + id->device) % n_buckets;
357} 340}
358 341
359/* Compare two input_file_idents for equality. */ 342/* Compare two input_file_idents for equality. */
360static int 343static int
361incl_compare (void const *data1, void const *data2) 344incl_compare(void const *data1, void const *data2)
362{ 345{
363 const struct input_file_ident *id1 = data1; 346 const struct input_file_ident *id1 = data1;
364 const struct input_file_ident *id2 = data2; 347 const struct input_file_ident *id2 = data2;
365 return !(id1->device == id2->device && id1->i_node == id2->i_node); 348 return !(id1->device == id2->device && id1->i_node == id2->i_node);
366}
367
368static void
369incl_free (void *data)
370{
371 free (data);
372} 349}
373 350
374static int 351static int
375source_lookup (struct stat *st) 352source_lookup(struct stat *st)
376{ 353{
377 struct input_file_ident key; 354 struct input_file_ident key;
378 int install = 1; 355 int install = 1;
379
380 if (!incl_sources)
381 {
382 incl_sources = grecs_symtab_create(sizeof (struct input_file_ident),
383 incl_hasher,
384 incl_compare,
385 NULL,
386 NULL,/*FIXME: alloc*/
387 NULL);
388 if (!incl_sources)
389 grecs_alloc_die ();
390 }
391 356
392 key.i_node = st->st_ino; 357 if (!incl_sources) {
393 key.device = st->st_dev; 358 incl_sources = grecs_symtab_create(
394 if (!grecs_symtab_lookup_or_install(incl_sources, &key, &install)) 359 sizeof(struct input_file_ident),
395 grecs_alloc_die (); 360 incl_hasher,
396 return !install; 361 incl_compare,
362 NULL,
363 NULL,/*FIXME: alloc*/
364 NULL);
365 if (!incl_sources)
366 grecs_alloc_die();
367 }
368
369 key.i_node = st->st_ino;
370 key.device = st->st_dev;
371 if (!grecs_symtab_lookup_or_install(incl_sources, &key, &install))
372 grecs_alloc_die();
373 return !install;
397} 374}
398 375
399 376
400static int 377static int
401push_source (const char *name, int once) 378push_source(const char *name, int once)
402{ 379{
403 FILE *fp; 380 FILE *fp;
404 struct buffer_ctx *ctx; 381 struct buffer_ctx *ctx;
405 struct stat st; 382 struct stat st;
406 int rc = stat (name, &st); 383 int rc = stat(name, &st);
407 384
408 if (context_stack) 385 if (context_stack) {
409 { 386 if (rc) {
410 if (rc) 387 grecs_error(&LOCUS, errno,
411 { 388 _("Cannot stat `%s'"), name);
412 grecs_error (&LOCUS, errno, _("Cannot stat `%s'"), name); 389 return 1;
413 return 1; 390 }
414 }
415 391
416 if (LOCUS.file && STAT_ID_EQ (st, context_stack->id)) 392 if (LOCUS.file && STAT_ID_EQ(st, context_stack->id)) {
417 { 393 grecs_error(&LOCUS, 0, _("Recursive inclusion"));
418 grecs_error (&LOCUS, 0, _("Recursive inclusion")); 394 return 1;
419 return 1; 395 }
396
397 if ((ctx = ctx_lookup(&st))) {
398 grecs_error(&LOCUS, 0, _("Recursive inclusion"));
399 if (ctx->prev)
400 grecs_error(&ctx->prev->locus, 0,
401 _("`%s' already included here"),
402 name);
403 else
404 grecs_error(&LOCUS, 0,
405 _("`%s' already included at top level"),
406 name);
407 return 1;
408 }
409 } else if (rc) {
410 grecs_error(NULL, errno, _("Cannot stat `%s'"), name);
411 return 1;
420 } 412 }
421 413
422 if ((ctx = ctx_lookup (&st))) 414 if (once && source_lookup(&st))
423 { 415 return -1;
424 grecs_error (&LOCUS, 0, _("Recursive inclusion")); 416
425 if (ctx->prev) 417 fp = fopen(name, "r");
426 grecs_error (&ctx->prev->locus, 0, 418 if (!fp) {
427 _("`%s' already included here"), name); 419 grecs_error(&LOCUS, errno, _("Cannot open `%s'"), name);
428 else 420 return 1;
429 grecs_error (&LOCUS, 0,
430 _("`%s' already included at top level"), name);
431 return 1;
432 } 421 }
433 }
434 else if (rc)
435 {
436 grecs_error (NULL, errno, _("Cannot stat `%s'"), name);
437 return 1;
438 }
439
440 if (once && source_lookup (&st))
441 return -1;
442
443 fp = fopen (name, "r");
444 if (!fp)
445 {
446 grecs_error (&LOCUS, errno, _("Cannot open `%s'"), name);
447 return 1;
448 }
449
450 /* Push current context */
451 ctx = grecs_malloc (sizeof (*ctx));
452 ctx->locus.file = grecs_install_text (name);
453 ctx->locus.line = 1;
454 ctx->xlines = 0;
455 ctx->namelen = strlen (ctx->locus.file);
456 ctx->id.i_node = st.st_ino;
457 ctx->id.device = st.st_dev;
458 ctx->infile = fp;
459 ctx->prev = context_stack;
460 context_stack = ctx;
461
462 if (yy_grecs_flex_debug)
463 fprintf (stderr, "Processing file `%s'\n", name);
464
465 pp_line_stmt ();
466
467 return 0;
468}
469 422
470static int 423 /* Push current context */
471pop_source () 424 ctx = grecs_malloc(sizeof(*ctx));
472{ 425 ctx->locus.file = grecs_install_text(name);
473 struct buffer_ctx *ctx; 426 ctx->locus.line = 1;
427 ctx->xlines = 0;
428 ctx->namelen = strlen(ctx->locus.file);
429 ctx->id.i_node = st.st_ino;
430 ctx->id.device = st.st_dev;
431 ctx->infile = fp;
432 ctx->prev = context_stack;
433 context_stack = ctx;
474 434
475 if (!context_stack) 435 if (yy_grecs_flex_debug)
476 return 1; 436 fprintf (stderr, "Processing file `%s'\n", name);
477 437
478 fclose (INFILE); 438 pp_line_stmt();
479 439
480 /* Restore previous context */ 440 return 0;
481 ctx = context_stack->prev; 441}
482 free (context_stack);
483 context_stack = ctx;
484 442
485 if (!context_stack) 443static int
486 { 444pop_source()
487 if (yy_grecs_flex_debug) 445{
488 fprintf (stderr, "End of input\n"); 446 struct buffer_ctx *ctx;
489 return 1; 447
490 } 448 if (!context_stack)
449 return 1;
450
451 fclose(INFILE);
452
453 /* Restore previous context */
454 ctx = context_stack->prev;
455 free(context_stack);
456 context_stack = ctx;
457
458 if (!context_stack) {
459 if (yy_grecs_flex_debug)
460 fprintf (stderr, "End of input\n");
461 return 1;
462 }
491 463
492 LOCUS.line++; 464 LOCUS.line++;
493 465
494 if (yy_grecs_flex_debug) 466 if (yy_grecs_flex_debug)
495 fprintf (stderr, "Resuming file `%s' at line %lu\n", 467 fprintf (stderr, "Resuming file `%s' at line %lu\n",
496 LOCUS.file, (unsigned long) LOCUS.line); 468 LOCUS.file, (unsigned long) LOCUS.line);
497 469
498 pp_line_stmt (); 470 pp_line_stmt();
499 471
500 return 0; 472 return 0;
501} 473}
502 474
503static int 475static int
504try_file (const char *name, int allow_cwd, int err_not_found, char **newp) 476try_file(const char *name, int allow_cwd, int err_not_found, char **newp)
505{ 477{
506 static char *cwd = "."; 478 static char *cwd = ".";
507 struct file_data fd; 479 struct file_data fd;
508 480
509 fd.name = name; 481 fd.name = name;
510 fd.namelen = strlen (name); 482 fd.namelen = strlen(name);
511 fd.buf = NULL; 483 fd.buf = NULL;
512 fd.buflen = 0; 484 fd.buflen = 0;
513 fd.found = 0; 485 fd.found = 0;
514 486
515 if (!include_path) 487 if (!include_path)
516 grecs_include_path_setup (NULL); 488 grecs_include_path_setup(NULL);
517 if (allow_cwd) 489 if (allow_cwd) {
518 { 490 grecs_list_append(include_path, cwd);
519 grecs_list_append (include_path, cwd); 491 pp_list_find(include_path, &fd);
520 pp_list_find (include_path, &fd); 492 grecs_list_remove_tail(include_path);
521 grecs_list_remove_tail (include_path); 493 } else
522 } 494 pp_list_find(include_path, &fd);
523 else 495
524 pp_list_find (include_path, &fd); 496 if (!fd.found) {
525 497 pp_list_find(std_include_path, &fd);
526 if (!fd.found) 498
527 { 499 if (!fd.found && err_not_found) {
528 pp_list_find (std_include_path, &fd); 500 grecs_error(&LOCUS, 0,
529 501 _("%s: No such file or directory"), name);
530 if (!fd.found && err_not_found) 502 *newp = NULL;
531 { 503 }
532 grecs_error (&LOCUS, 0, _("%s: No such file or directory"), name);
533 *newp = NULL;
534 } 504 }
535 } 505 if (fd.found)
536 if (fd.found) 506 *newp = fd.buf;
537 *newp = fd.buf; 507 return fd.found;
538 return fd.found;
539} 508}
540 509
541static int 510static int
542parse_include (const char *text, int once) 511parse_include(const char *text, int once)
543{ 512{
544 struct wordsplit ws; 513 struct wordsplit ws;
545 char *tmp = NULL; 514 char *tmp = NULL;
546 char *p = NULL; 515 char *p = NULL;
547 int rc = 1; 516 int rc = 1;
548 517
549 if (wordsplit (text, &ws, WRDSF_DEFFLAGS)) 518 if (wordsplit(text, &ws, WRDSF_DEFFLAGS))
550 grecs_error (&LOCUS, 0, _("Cannot parse include line")); 519 grecs_error(&LOCUS, 0, _("Cannot parse include line"));
551 else if (ws.ws_wordc != 2) 520 else if (ws.ws_wordc != 2) {
552 { 521 wordsplit_free(&ws);
553 wordsplit_free (&ws); 522 grecs_error(&LOCUS, 0, _("invalid include statement"));
554 grecs_error (&LOCUS, 0, _("invalid include statement")); 523 } else {
555 } 524 size_t len;
556 else 525 int allow_cwd;
557 { 526
558 size_t len; 527 p = ws.ws_wordv[1];
559 int allow_cwd; 528 len = strlen (p);
560 529
561 p = ws.ws_wordv[1]; 530 if (p[0] == '<' && p[len - 1] == '>') {
562 len = strlen (p); 531 allow_cwd = 0;
563 532 p[len - 1] = 0;
564 if (p[0] == '<' && p[len - 1] == '>') 533 p++;
565 { 534 }
566 allow_cwd = 0; 535 else
567 p[len - 1] = 0; 536 allow_cwd = 1;
568 p++; 537
538 if (p[0] != '/' && try_file(p, allow_cwd, 1, &tmp))
539 p = tmp;
569 } 540 }
570 else
571 allow_cwd = 1;
572
573 if (p[0] != '/' && try_file (p, allow_cwd, 1, &tmp))
574 p = tmp;
575 }
576 541
577 if (p) 542 if (p)
578 rc = push_source (p, once); 543 rc = push_source(p, once);
579 free (tmp); 544 free(tmp);
580 wordsplit_free (&ws); 545 wordsplit_free(&ws);
581 return rc; 546 return rc;
582} 547}
583 548
584int 549int
585grecs_preproc_init (const char *name) 550grecs_preproc_init(const char *name)
586{ 551{
587 return push_source (name, 0); 552 return push_source(name, 0);
588} 553}
589 554
590void 555void
591grecs_preproc_done () 556grecs_preproc_done()
592{ 557{
593 grecs_symtab_free (incl_sources); 558 grecs_symtab_free(incl_sources);
594 free (linebuf); 559 free(linebuf);
595 free (putback_buffer); 560 free(putback_buffer);
596 free (linebufbase); 561 free(linebufbase);
597} 562}
598 563
599int 564int
600grecs_preproc_run (const char *config_file, const char *extpp) 565grecs_preproc_run(const char *config_file, const char *extpp)
601{ 566{
602 size_t i; 567 size_t i;
603 char buffer[512]; 568 char buffer[512];
604 569
605 if (grecs_preproc_init (config_file)) 570 if (grecs_preproc_init(config_file))
606 return 1; 571 return 1;
607 if (extpp) 572 if (extpp) {
608 { 573 FILE *outfile;
609 FILE *outfile; 574 char *setup_file;
610 char *setup_file; 575 char *cmd = NULL;
611 char *cmd; 576
612 577 if (try_file("pp-setup", 1, 0, &setup_file)) {
613 if (try_file ("pp-setup", 1, 0, &setup_file)) 578 size_t size = 0;
614 { 579 if (grecs_asprintf(&cmd, &size,
615 asprintf (&cmd, "%s %s -", extpp, setup_file); 580 "%s %s -", extpp, setup_file))
616 free (setup_file); 581 grecs_alloc_die();
617 } 582 free(setup_file);
618 else 583 } else
619 cmd = grecs_strdup (extpp); 584 cmd = grecs_strdup (extpp);
620 /*FIXME_DEBUG_F1 (2, "Running preprocessor: `%s'", cmd);*/ 585 /*FIXME_DEBUG_F1 (2, "Running preprocessor: `%s'", cmd);*/
621 outfile = popen