Annotation of embedaddon/confuse/src/lexer.l, revision 1.1.1.1
1.1 misho 1: %{
2: /*
3: * Copyright (c) 2002,2003,2007 Martin Hedenfalk <martin@bzero.se>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #ifdef HAVE_CONFIG_H
19: # include <config.h>
20: #endif
21:
22: #include <assert.h>
23:
24: #ifdef HAVE_STRING_H
25: # include <string.h>
26: #endif
27: #include "confuse.h"
28:
29: #include <errno.h>
30:
31: #if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
32: # include <libintl.h>
33: # define _(str) dgettext(PACKAGE, str)
34: #else
35: # define _(str) str
36: #endif
37: #define N_(str) str
38:
39: /*
40: * Prevent compilation of static input() function in generated code
41: * This function is never used but GCC 4.3 will warn about it.
42: */
43: #define YY_NO_INPUT
44:
45: typedef char * YYSTYPE;
46: extern YYSTYPE cfg_yylval;
47:
48: #define YY_DECL int cfg_yylex ( cfg_t *cfg )
49:
50: /* temporary buffer for the quoted strings scanner
51: */
52: char *cfg_qstring = NULL;
53: static unsigned int qstring_index = 0;
54: static unsigned int qstring_len = 0;
55: static void qputc(char ch);
56: #define CFG_QSTRING_BUFSIZ 32
57:
58: #define MAX_INCLUDE_DEPTH 10
59: struct {
60: YY_BUFFER_STATE state;
61: char *filename;
62: unsigned int line;
63: } cfg_include_stack[MAX_INCLUDE_DEPTH];
64: int cfg_include_stack_ptr = 0;
65:
66: static YY_BUFFER_STATE pre_string_scan_state = 0;
67: static YY_BUFFER_STATE string_scan_state = 0;
68:
69: %}
70:
71: %option noyywrap
72:
73: /* start conditions
74: */
75: %x comment
76: %x dq_str
77: %x sq_str
78:
79: %%
80:
81: [ \t]+ /* eat up whitespace */
82:
83: \n cfg->line++; /* keep track of line number */
84:
85: ("#"|"//")[^\n]* /* eat up one-line comments */
86:
87: /* special keywords/symbols
88: */
89: "{" { cfg_yylval = yytext; return '{'; }
90: "}" { cfg_yylval = yytext; return '}'; }
91: "(" { cfg_yylval = yytext; return '('; }
92: ")" { cfg_yylval = yytext; return ')'; }
93: "=" { cfg_yylval = yytext; return '='; }
94: "+=" { cfg_yylval = yytext; return '+'; }
95: "," { cfg_yylval = yytext; return ','; }
96:
97: /* handle multi-line C-style comments
98: */
99: "/*" BEGIN(comment);
100: <comment>[^*\n]* /* eat anything that's not a '*' */
101: <comment>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
102: <comment>\n cfg->line++;
103: <comment>"*"+"/" BEGIN(INITIAL);
104:
105: /* handle C-style strings
106: */
107: "\"" {
108: qstring_index = 0;
109: BEGIN(dq_str);
110: }
111: <dq_str>\" { /* saw closing quote - all done */
112: BEGIN(INITIAL);
113: qputc('\0');
114: cfg_yylval = cfg_qstring;
115: return CFGT_STR;
116: }
117: <dq_str>$\{[^}]*\} { /* environment variable substitution */
118: char *var;
119: char *e;
120: yytext[strlen(yytext) - 1] = 0;
121: e = strchr(yytext+2, ':');
122: if(e && e[1] == '-')
123: *e = 0;
124: else
125: e = 0;
126: var = getenv(yytext+2);
127: if(!var && e)
128: var = e+2;
129: while(var && *var)
130: qputc(*var++);
131: }
132: <dq_str>\n {
133: qputc('\n');
134: cfg->line++;
135: }
136: <dq_str>\\\n { /* allow continuing on next line */
137: /* no-op */
138: cfg->line++;
139: }
140: <dq_str>\\[0-7]{1,3} { /* octal escape sequence */
141: unsigned int result;
142: sscanf(yytext + 1, "%o", &result);
143: if(result > 0xFF) {
144: cfg_error(cfg, _("invalid octal number '%s'"), yytext);
145: return 0;
146: }
147: qputc(result);
148: }
149: <dq_str>\\[0-9]+ {
150: cfg_error(cfg, _("bad escape sequence '%s'"), yytext);
151: return 0;
152: }
153: <dq_str>"\\x"[0-9A-Fa-f]{1,2} { /* hexadecimal escape sequence */
154: unsigned int result;
155: sscanf(yytext + 2, "%x", &result);
156: qputc(result);
157: }
158: <dq_str>\\n {
159: qputc('\n');
160: }
161: <dq_str>\\r {
162: qputc('\r');
163: }
164: <dq_str>\\b {
165: qputc('\b');
166: }
167: <dq_str>\\f {
168: qputc('\f');
169: }
170: <dq_str>\\a {
171: qputc('\007');
172: }
173: <dq_str>\\e {
174: qputc('\033');
175: }
176: <dq_str>\\t {
177: qputc('\t');
178: }
179: <dq_str>\\v {
180: qputc('\v');
181: }
182: <dq_str>\\. {
183: qputc(yytext[1]);
184: }
185: <dq_str>[^\\\"\n]+ {
186: char *yptr = yytext;
187: while(*yptr) {
188: qputc(*yptr++);
189: }
190: }
191:
192: /* single-quoted string ('...') */
193: "\'" {
194: qstring_index = 0;
195: BEGIN(sq_str);
196: }
197: <sq_str>\' { /* saw closing quote - all done */
198: BEGIN(INITIAL);
199: qputc('\0');
200: cfg_yylval = cfg_qstring;
201: return CFGT_STR;
202: }
203: <sq_str>\n {
204: qputc('\n');
205: cfg->line++;
206: }
207: <sq_str>\\\n { /* allow continuing on next line */
208: /* no-op */
209: cfg->line++;
210: }
211: <sq_str>\\[\\\'] {
212: qputc(yytext[1]);
213: }
214: <sq_str>\\[^\\\'] {
215: qputc(yytext[0]);
216: qputc(yytext[1]);
217: }
218: <sq_str>[^\\\'\n]+ {
219: char *cp = yytext;
220: while(*cp != '\0') {
221: qputc(*cp++);
222: }
223: }
224: <sq_str><<EOF>> {
225: cfg_error(cfg, _("unterminated string constant"));
226: return 0;
227: }
228:
229: <<EOF>> {
230: if (cfg_include_stack_ptr <= 0)
231: {
232: return EOF;
233: }
234: else
235: {
236: yy_delete_buffer( YY_CURRENT_BUFFER );
237: fclose(cfg_yyin);
238: cfg_yyin = 0;
239: --cfg_include_stack_ptr;
240: yy_switch_to_buffer(
241: cfg_include_stack[cfg_include_stack_ptr].state );
242: free(cfg->filename);
243: cfg->filename = cfg_include_stack[cfg_include_stack_ptr].filename;
244: cfg->line = cfg_include_stack[cfg_include_stack_ptr].line;
245: }
246: }
247:
248: $\{[^}]*\} {
249: char *var;
250: char *e;
251: yytext[strlen(yytext) - 1] = 0;
252: e = strchr(yytext+2, ':');
253: if(e && e[1] == '-')
254: *e = 0;
255: else
256: e = 0;
257: var = getenv(yytext+2);
258: if(!var && e)
259: var = e+2;
260: if(!var)
261: var = "";
262: cfg_yylval = var;
263: return CFGT_STR;
264: }
265:
266: /* an unquoted string
267: * a slash can't be followed by another slash (c++
268: * comment) or an asterisk (C multi-line comment)
269: */
270: (\/[^ #\"\'\t\n\r={}()+,\/*]|[^ #\"\'\t\n\r={}()+,\*])+ {
271: cfg_yylval = yytext;
272: return CFGT_STR;
273: }
274:
275: . /* eat any non-matching characters */
276:
277: %%
278:
279: void cfg_dummy_function(void)
280: {
281: /* please compiler :-)
282: * otherwise "defined but not used" warning
283: */
284: yyunput(0, 0);
285: }
286:
287: int cfg_lexer_include(cfg_t *cfg, const char *filename)
288: {
289: char *xfilename;
290:
291: if(cfg_include_stack_ptr >= MAX_INCLUDE_DEPTH) {
292: cfg_error(cfg, _("includes nested too deeply"));
293: return 1;
294: }
295:
296: cfg_include_stack[cfg_include_stack_ptr].state = YY_CURRENT_BUFFER;
297: cfg_include_stack[cfg_include_stack_ptr].filename = cfg->filename;
298: cfg_include_stack[cfg_include_stack_ptr].line = cfg->line;
299: cfg_include_stack_ptr++;
300:
301: xfilename = cfg_tilde_expand(filename);
302:
303: cfg_yyin = fopen(xfilename, "r");
304:
305: if(!cfg_yyin) {
306: cfg_error(cfg, "%s: %s", xfilename, strerror(errno));
307: free(xfilename);
308: return 1;
309: }
310:
311: cfg->filename = xfilename;
312: cfg->line = 1;
313:
314: yy_switch_to_buffer(yy_create_buffer(cfg_yyin, YY_BUF_SIZE));
315: return 0;
316: }
317:
318: /* write a character to the quoted string buffer, and reallocate as
319: * necessary
320: */
321: static void qputc(char ch)
322: {
323: if(qstring_index >= qstring_len) {
324: qstring_len += CFG_QSTRING_BUFSIZ;
325: cfg_qstring = (char *)realloc(cfg_qstring, qstring_len);
326: assert(cfg_qstring);
327: memset(cfg_qstring + qstring_index, 0, CFG_QSTRING_BUFSIZ);
328: }
329: cfg_qstring[qstring_index++] = ch;
330: }
331:
332: void cfg_scan_string_begin(const char *buf)
333: {
334: pre_string_scan_state = YY_CURRENT_BUFFER;
335:
336: /* yy_scan_string does a yy_switch_to_buffer call for us
337: */
338: string_scan_state = yy_scan_string(buf);
339: }
340:
341: void cfg_scan_string_end(void)
342: {
343: /* restore to previous state
344: */
345: yy_delete_buffer(string_scan_state);
346: if (pre_string_scan_state)
347: yy_switch_to_buffer(pre_string_scan_state);
348: free(cfg_qstring);
349: cfg_qstring = 0;
350: qstring_index = qstring_len = 0;
351: string_scan_state = 0;
352: }
353:
354: static YY_BUFFER_STATE pre_fp_scan_state;
355: static YY_BUFFER_STATE fp_scan_state;
356:
357: void cfg_scan_fp_begin(FILE *fp)
358: {
359: pre_fp_scan_state = YY_CURRENT_BUFFER;
360: fp_scan_state = yy_create_buffer(fp, YY_BUF_SIZE);
361: yy_switch_to_buffer(fp_scan_state);
362: }
363:
364: void cfg_scan_fp_end(void)
365: {
366: /* restore to previous state
367: */
368: yy_delete_buffer(fp_scan_state);
369: if(pre_fp_scan_state)
370: yy_switch_to_buffer(pre_fp_scan_state);
371: free(cfg_qstring);
372: cfg_qstring = 0;
373: qstring_index = qstring_len = 0;
374: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>