-rw-r--r-- | gconf/gconf-lex.l | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/gconf/gconf-lex.l b/gconf/gconf-lex.l deleted file mode 100644 index 1379640..0000000 --- a/gconf/gconf-lex.l +++ b/dev/null | |||
@@ -1,476 +0,0 @@ | |||
1 | /* gconf - General purpose configuration parser. -*- c -*- */ | ||
2 | %{ | ||
3 | /* gconf - General purpose configuration parser. | ||
4 | Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 3 of the License, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License along | ||
17 | with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | #include <gconf.h> | ||
23 | #include <gconf-gram.h> | ||
24 | #include <unistd.h> | ||
25 | #include <fcntl.h> | ||
26 | #include <ctype.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <errno.h> | ||
29 | |||
30 | #define obstack_chunk_alloc malloc | ||
31 | #define obstack_chunk_free free | ||
32 | #include <obstack.h> | ||
33 | #include <xalloc.h> | ||
34 | #include <wordsplit.h> | ||
35 | |||
36 | #if ENABLE_NLS | ||
37 | # include "gettext.h" | ||
38 | # define _(msgid) gettext (msgid) | ||
39 | #else | ||
40 | # define _(msgid) msgid | ||
41 | #endif | ||
42 | |||
43 | static char *multiline_delimiter; | ||
44 | static size_t multiline_delimiter_len; | ||
45 | static int multiline_unescape; /* Unescape here-document contents */ | ||
46 | static int (*char_to_strip) (char); /* Strip matching characters of each | ||
47 | here-document line */ | ||
48 | |||
49 | gconf_locus_t gconf_current_locus; /* Input file location */ | ||
50 | /* Line correction. Equals to the number of #line directives inserted into | ||
51 | the input by the preprocessor instance. The external preprocessor, if | ||
52 | any, counts these as input lines and therefore the line numbers in *its* | ||
53 | #line directives are offset by the value of XLINES. | ||
54 | |||
55 | Uff, running two preprocessors is confusing... | ||
56 | */ | ||
57 | static size_t xlines; | ||
58 | static struct obstack stk; | ||
59 | |||
60 | static void multiline_begin (char *); | ||
61 | static void multiline_add (char *); | ||
62 | static char *multiline_strip_tabs (char *text); | ||
63 | static void line_add_unescape_last (char *text, size_t len); | ||
64 | static int ident (void); | ||
65 | static int isemptystr (int off); | ||
66 | |||
67 | static void parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines); | ||
68 | static void parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines); | ||
69 | |||
70 | #undef YY_INPUT | ||
71 | #define YY_INPUT(buf,result,max_size) \ | ||
72 | do \ | ||
73 | { \ | ||
74 | if (gconf_preprocessor) \ | ||
75 | result = fread (buf, 1, max_size, yyin); \ | ||
76 | else \ | ||
77 | result = gconf_preproc_fill_buffer(buf, max_size); \ | ||
78 | } \ | ||
79 | while (0) | ||
80 | |||
81 | %} | ||
82 | |||
83 | |||
84 | %x COMMENT ML STR | ||
85 | |||
86 | WS [ \t\f][ \t\f]* | ||
87 | ID [a-zA-Z_][a-zA-Z_0-9-]+ | ||
88 | P [1-9][0-9]* | ||
89 | |||
90 | %% | ||
91 | /* C-style comments */ | ||
92 | "/*" BEGIN (COMMENT); | ||
93 | <COMMENT>[^*\n]* /* eat anything that's not a '*' */ | ||
94 | <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ | ||
95 | <COMMENT>\n ++gconf_current_locus.line; | ||
96 | <COMMENT>"*"+"/" BEGIN (INITIAL); | ||
97 | /* Line directive */ | ||
98 | ^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { parse_line_cpp (yytext, | ||
99 | &gconf_current_locus, | ||
100 | &xlines); } | ||
101 | ^[ \t]*#[ \t]*line[ \t].*\n { parse_line (yytext, &gconf_current_locus, | ||
102 | &xlines); } | ||
103 | /* End-of-line comments */ | ||
104 | #.*\n { gconf_current_locus.line++; } | ||
105 | #.* /* end-of-file comment */; | ||
106 | "//".*\n { gconf_current_locus.line++; } | ||
107 | "//".* /* end-of-file comment */; | ||
108 | /* Identifiers */ | ||
109 | <INITIAL>{ID} return ident (); | ||
110 | /* Strings */ | ||
111 | [a-zA-Z0-9_\.\*/:@-]+ { gconf_line_begin (); | ||
112 | gconf_line_add (yytext, yyleng); | ||
113 | yylval.string = gconf_line_finish (); | ||
114 | return STRING; } | ||
115 | /* Quoted strings */ | ||
116 | \"[^\\"\n]*\" { gconf_line_begin (); | ||
117 | gconf_line_add (yytext + 1, yyleng - 2); | ||
118 | yylval.string = gconf_line_finish (); | ||
119 | return QSTRING; } | ||
120 | \"[^\\"\n]*\\. | | ||
121 | \"[^\\"\n]*\\\n { BEGIN (STR); | ||
122 | gconf_line_begin (); | ||
123 | line_add_unescape_last (yytext + 1, yyleng - 1); } | ||
124 | <STR>[^\\"\n]*\\. | | ||
125 | <STR>\"[^\\"\n]*\\\n { line_add_unescape_last (yytext, yyleng); } | ||
126 | <STR>[^\\"\n]*\" { BEGIN(INITIAL); | ||
127 | if (yyleng > 1) | ||
128 | gconf_line_add (yytext, yyleng - 1); | ||
129 | yylval.string = gconf_line_finish (); | ||
130 | return QSTRING; } | ||
131 | /* Multiline strings */ | ||
132 | "<<"(-" "?)?\\?{ID}[ \t]*#.*\n | | ||
133 | "<<"(-" "?)?\\?{ID}[ \t]*"//".*\n | | ||
134 | "<<"(-" "?)?\\?{ID}[ \t]*\n | | ||
135 | "<<"(-" "?)?\"{ID}\"[ \t]*#.*\n | | ||
136 | "<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n | | ||
137 | "<<"(-" "?)?\"{ID}\"[ \t]*\n { | ||
138 | BEGIN (ML); | ||
139 | multiline_begin (yytext+2); | ||
140 | gconf_current_locus.line++; } | ||
141 | /* Ignore m4 line statements */ | ||
142 | <ML>^"#line ".*\n { gconf_current_locus.line++; } | ||
143 | <ML>.*\n { char *p = multiline_strip_tabs (yytext); | ||
144 | |||
145 | if (!strncmp (p, multiline_delimiter, multiline_delimiter_len) | ||
146 | && isemptystr (p + multiline_delimiter_len - yytext)) | ||
147 | { | ||
148 | free (multiline_delimiter); | ||
149 | multiline_delimiter = NULL; | ||
150 | BEGIN (INITIAL); | ||
151 | yylval.string = gconf_line_finish (); | ||
152 | return MSTRING; | ||
153 | } | ||
154 | gconf_current_locus.line++; | ||
155 | multiline_add (p); } | ||
156 | {WS} ; | ||
157 | /* Other tokens */ | ||
158 | \n { gconf_current_locus.line++; } | ||
159 | [,;{}()] return yytext[0]; | ||
160 | . { if (isascii (yytext[0]) && isprint (yytext[0])) | ||
161 | gconf_error (&gconf_current_locus, 0, _("stray character %c"), yytext[0]); | ||
162 | else | ||
163 | gconf_error (&gconf_current_locus, 0, _("stray character \\%03o"), | ||
164 | (unsigned char) yytext[0]); } | ||
165 | %% | ||
166 | |||
167 | pid_t gconf_preproc_pid; | ||
168 | |||
169 | int | ||
170 | yywrap () | ||
171 | { | ||
172 | if (yyin) | ||
173 | gconf_preproc_extrn_shutdown (gconf_preproc_pid); | ||
174 | else | ||
175 | gconf_preproc_done (); | ||
176 | gconf_current_locus.file = NULL; | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | int | ||
181 | gconf_lex_begin (const char *name) | ||
182 | { | ||
183 | if (yy_flex_debug > 0) | ||
184 | yy_flex_debug = 0; | ||
185 | obstack_init (&stk); | ||
186 | if (gconf_preprocessor) | ||
187 | { | ||
188 | int fd; | ||
189 | |||
190 | fd = open (name, O_RDONLY); | ||
191 | if (fd == -1) | ||
192 | { | ||
193 | gconf_error (NULL, errno, _("Cannot open `%s'"), name); | ||
194 | return 1; | ||
195 | } | ||
196 | close (fd); | ||
197 | |||
198 | yyin = gconf_preproc_extrn_start (name, &gconf_preproc_pid); | ||
199 | if (!yyin) | ||
200 | { | ||
201 | gconf_error (NULL, errno, | ||
202 | _("Unable to start external preprocessor `%s'"), | ||
203 | gconf_preprocessor); | ||
204 | return 1; | ||
205 | } | ||
206 | } | ||
207 | else | ||
208 | return gconf_preproc_init (name); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | void | ||
214 | gconf_lex_end () | ||
215 | { | ||
216 | } | ||
217 | |||
218 | static int | ||
219 | isemptystr (int off) | ||
220 | { | ||
221 | for (; yytext[off] && isspace (yytext[off]); off++) | ||
222 | ; | ||
223 | if (yytext[off] == ';') | ||
224 | { | ||
225 | int i; | ||
226 | for (i = off + 1; yytext[i]; i++) | ||
227 | if (!isspace (yytext[i])) | ||
228 | return 0; | ||
229 | yyless (off); | ||
230 | return 1; | ||
231 | } | ||
232 | return yytext[off] == 0; | ||
233 | } | ||
234 | |||
235 | char * | ||
236 | multiline_strip_tabs (char *text) | ||
237 | { | ||
238 | if (char_to_strip) | ||
239 | for (; *text && char_to_strip (*text); text++) | ||
240 | ; | ||
241 | return text; | ||
242 | } | ||
243 | |||
244 | static int | ||
245 | unquote_char (int c) | ||
246 | { | ||
247 | static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t"; | ||
248 | |||
249 | char *p; | ||
250 | |||
251 | for (p = quote_transtab; *p; p += 2) | ||
252 | { | ||
253 | if (*p == c) | ||
254 | return p[1]; | ||
255 | } | ||
256 | return -1; | ||
257 | } | ||
258 | |||
259 | static void | ||
260 | unescape_to_obstack (int c) | ||
261 | { | ||
262 | if (c != '\n') | ||
263 | { | ||
264 | int t = unquote_char (c); | ||
265 | if (t != -1) | ||
266 | obstack_1grow (&stk, t); | ||
267 | else | ||
268 | { | ||
269 | gconf_warning(&gconf_current_locus, 0, | ||
270 | _("unknown escape sequence '\\%c'"), | ||
271 | c); | ||
272 | obstack_1grow (&stk, c); | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | void | ||
278 | gconf_line_add (const char *text, size_t len) | ||
279 | { | ||
280 | obstack_grow (&stk, text, len); | ||
281 | } | ||
282 | |||
283 | /* Same, but unescapes the last character from yytext */ | ||
284 | static void | ||
285 | line_add_unescape_last (char *text, size_t len) | ||
286 | { | ||
287 | obstack_grow (&stk, text, len - 2); | ||
288 | unescape_to_obstack (text[len - 1]); | ||
289 | } | ||
290 | |||
291 | static void | ||
292 | multiline_add (char *s) | ||
293 | { | ||
294 | if (multiline_unescape) | ||
295 | { | ||
296 | for (; *s; s++) | ||
297 | { | ||
298 | if (*s == '\\') | ||
299 | { | ||
300 | unescape_to_obstack (s[1]); | ||
301 | ++s; | ||
302 | } | ||
303 | else | ||
304 | obstack_1grow (&stk, *s); | ||
305 | } | ||
306 | } | ||
307 | else | ||
308 | gconf_line_add (s, strlen (s)); | ||
309 | } | ||
310 | |||
311 | void | ||
312 | gconf_line_begin () | ||
313 | { | ||
314 | /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */ | ||
315 | } | ||
316 | |||
317 | static int | ||
318 | is_tab (char c) | ||
319 | { | ||
320 | return c == '\t'; | ||
321 | } | ||
322 | |||
323 | static int | ||
324 | is_ws (char c) | ||
325 | { | ||
326 | return c == '\t' || c == ' '; | ||
327 | } | ||
328 | |||
329 | void | ||
330 | multiline_begin (char *p) | ||
331 | { | ||
332 | if (*p == '-') | ||
333 | { | ||
334 | if (*++p == ' ') | ||
335 | { | ||
336 | char_to_strip = is_ws; | ||
337 | p++; | ||
338 | } | ||
339 | else | ||
340 | char_to_strip = is_tab; | ||
341 | } | ||
342 | else | ||
343 | char_to_strip = NULL; | ||
344 | if (*p == '\\') | ||
345 | { | ||
346 | p++; | ||
347 | multiline_unescape = 0; | ||
348 | } | ||
349 | else if (*p == '"') | ||
350 | { | ||
351 | char *q; | ||
352 | |||
353 | p++; | ||
354 | multiline_unescape = 0; | ||
355 | q = strchr (p, '"'); | ||
356 | multiline_delimiter_len = q - p; | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | multiline_delimiter_len = strcspn (p, " \t"); | ||
361 | multiline_unescape = 1; | ||
362 | } | ||
363 | |||
364 | /* Remove trailing newline */ | ||
365 | multiline_delimiter_len--; | ||
366 | multiline_delimiter = xmalloc (multiline_delimiter_len + 1); | ||
367 | memcpy (multiline_delimiter, p, multiline_delimiter_len); | ||
368 | multiline_delimiter[multiline_delimiter_len] = 0; | ||
369 | gconf_line_begin (); | ||
370 | } | ||
371 | |||
372 | char * | ||
373 | gconf_line_finish () | ||
374 | { | ||
375 | obstack_1grow (&stk, 0); | ||
376 | return obstack_finish (&stk); | ||
377 | } | ||
378 | |||
379 | static int | ||
380 | ident () | ||
381 | { | ||
382 | char *p; | ||
383 | |||
384 | for (p = yytext; *p && isspace (*p); p++) | ||
385 | ; | ||
386 | obstack_grow (&stk, p, strlen (p)); | ||
387 | obstack_1grow (&stk, 0); | ||
388 | yylval.string = obstack_finish (&stk); | ||
389 | return IDENT; | ||
390 | } | ||
391 | |||
392 | void | ||
393 | gconf_lex_trace (int n) | ||
394 | { | ||
395 | yy_flex_debug = -n; | ||
396 | } | ||
397 | |||
398 | gconf_value_t * | ||
399 | gconf_value_dup(gconf_value_t *input) | ||
400 | { | ||
401 | gconf_value_t *ptr = obstack_alloc (&stk, sizeof (*ptr)); | ||
402 | *ptr = *input; | ||
403 | return ptr; | ||
404 | } | ||
405 | |||
406 | |||
407 | static int | ||
408 | assign_locus (gconf_locus_t *ploc, char *name, char *line, size_t *pxlines) | ||
409 | { | ||
410 | char *p; | ||
411 | |||
412 | if (name) | ||
413 | { | ||
414 | if (pxlines && (!ploc->file || strcmp(name, ploc->file))) | ||
415 | *pxlines = 0; | ||
416 | ploc->file = gconf_install_text (name); | ||
417 | } | ||
418 | ploc->line = strtoul (line, &p, 10) - (pxlines ? *pxlines : 0); | ||
419 | return *p != 0; | ||
420 | } | ||
421 | |||
422 | static void | ||
423 | parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines) | ||
424 | { | ||
425 | int rc = 1; | ||
426 | struct wordsplit ws; | ||
427 | |||
428 | if (wordsplit (text, &ws, WRDSF_DEFFLAGS)) | ||
429 | gconf_error (ploc, 0, _("cannot parse #line line")); | ||
430 | else | ||
431 | { | ||
432 | if (ws.ws_wordc == 2) | ||
433 | rc = assign_locus (ploc, NULL, ws.ws_wordv[1], pxlines); | ||
434 | else if (ws.ws_wordc == 3) | ||
435 | rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines); | ||
436 | else if (ws.ws_wordc == 4) | ||
437 | { | ||
438 | rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], 0); | ||
439 | if (rc == 0) | ||
440 | { | ||
441 | char *p; | ||
442 | unsigned long x = strtoul (ws.ws_wordv[3], &p, 10); | ||
443 | rc = *p != 0; | ||
444 | if (rc == 0) | ||
445 | *pxlines = x; | ||
446 | } | ||
447 | } | ||
448 | else | ||
449 | gconf_error (ploc, 0, _("invalid #line statement")); | ||
450 | |||
451 | if (rc) | ||
452 | gconf_error (ploc, 0, _("malformed #line statement")); | ||
453 | wordsplit_free (&ws); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static void | ||
458 | parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines) | ||
459 | { | ||
460 | struct wordsplit ws; | ||
461 | |||
462 | if (wordsplit (text, &ws, WRDSF_DEFFLAGS)) | ||
463 | { | ||
464 | gconf_error (ploc, 0, _("cannot parse #line line")); | ||
465 | return; | ||
466 | } | ||
467 | else if (ws.ws_wordc < 3) | ||
468 | gconf_error (ploc, 0, _("invalid #line statement")); | ||
469 | else | ||
470 | { | ||
471 | if (assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines)) | ||
472 | gconf_error (ploc, 0, _("malformed #line statement")); | ||
473 | } | ||
474 | wordsplit_free (&ws); | ||
475 | } | ||
476 | |||