ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/lexer.l
Revision: 669
Committed: Sun Jun 11 15:36:16 2006 UTC (20 years, 1 month ago) by michael
File size: 6786 byte(s)
Log Message:
- lexer.l: added proper support for quotes in strings.
  Cleaned up C comment style handling.
  Added support for C++ comments.

File Contents

# User Rev Content
1 adx 89 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * lexer.l: A set of rules for flex.
4     *
5     * Copyright (C) 2003 by Piotr Nizynski, Advanced IRC Services Project
6     * Copyright (C) 2005 by the Hybrid Development Team.
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21     * USA
22     *
23     * $Id: conf_lexer.l,v 1.5 2003/10/14 16:18:56 adx Exp $
24     */
25    
26     %option case-insensitive
27     %option noyywrap
28     %option nounput
29 michael 669 %option never-interactive
30 adx 89
31 michael 669 %x IN_COMMENT
32    
33 adx 89 %{
34    
35     #include "stdinc.h"
36 adx 179 #include "conf/conf.h"
37 adx 89 #include "y.tab.h"
38    
39     int conf_include_sptr = 0;
40    
41     #undef YY_INPUT
42     #define YY_INPUT(buf, res, siz) res = conf_yy_input(buf, siz)
43     /* flex's default is to print a message and exit(0) */
44     #define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg)
45    
46     #define MAX_INCLUDE_DEPTH 10
47    
48 michael 669 static YY_BUFFER_STATE conf_include_yystack[MAX_INCLUDE_DEPTH];
49 adx 89 struct ConfParserContext conf_include_ctxstack[MAX_INCLUDE_DEPTH];
50    
51     static void conf_include(void);
52     static int conf_eof(void);
53     static int conf_yy_fatal_error(const char *msg)
54     {
55 michael 669 return 0;
56 adx 89 }
57    
58     %}
59    
60 michael 669 WS [ \t]*
61     DIGIT [[:digit:]]+
62     INCLUDE \.include{WS}(\<.*\>|\".*\")
63     COMMENT ("//"|"#").*
64     qstring \"[^\"\n]*[\"\n]
65     IDENTIFIER [a-zA-Z_][a-zA-Z0-9_:]*
66 adx 89
67     %%
68    
69 michael 669 "/*" { BEGIN IN_COMMENT; }
70     <IN_COMMENT>"*/" { BEGIN INITIAL; }
71     <IN_COMMENT>. ; /* eat everything but a newline */
72     <IN_COMMENT>\n { ++conf_curctx.lineno; }
73     <IN_COMMENT><<EOF>> { BEGIN INITIAL; if (conf_eof()) yyterminate(); }
74 adx 89
75 michael 669 {INCLUDE} { conf_include(); }
76     \n.* { ++conf_curctx.lineno;
77     strlcpy(conf_linebuf, yytext + 1, CONF_BUFSIZE);
78     yyless(1);
79     }
80     {WS} ;
81     {COMMENT} ;
82     {DIGIT} { yylval.number = atoi(yytext); return NUMBER; }
83     {qstring} {
84     if (yytext[yyleng - 2] == '\\')
85 adx 475 {
86 michael 669 yyless(yyleng - 1); /* return last quote */
87     yymore(); /* append next string */
88 adx 475 }
89 michael 669 else
90     {
91     yylval.string = yytext + 1;
92    
93     if (yylval.string[yyleng - 2] != '"')
94     ilog(L_ERROR, "Unterminated character string");
95     else
96     {
97     int i = 0, j = 0;
98    
99     yylval.string[yyleng - 2] = '\0'; /* remove close quote */
100    
101     for (; yylval.string[i]; ++i, ++j)
102     {
103     if (yylval.string[i] == '\\')
104     {
105     if (yylval.string[++i] == '\0')
106     {
107     ilog(L_ERROR, "Unterminated character string");
108     break;
109     }
110     }
111    
112     yylval.string[j] = yylval.string[i];
113     }
114    
115     yylval.string[j] = '\0';
116     return QSTRING;
117     }
118     }
119 adx 475 }
120 michael 669
121 adx 475 b { return BYTES; }
122     byte { return BYTES; }
123     bytes { return BYTES; }
124     d { return DAYS; }
125     day { return DAYS; }
126     days { return DAYS; }
127 adx 89 false { yylval.number = 0; return BOOL; }
128 adx 475 h { return HOURS; }
129 adx 89 hour { return HOURS; }
130     hours { return HOURS; }
131 adx 475 kb { return KBYTES; }
132 adx 89 kbyte { return KBYTES; }
133     kbytes { return KBYTES; }
134     kilobyte { return KBYTES; }
135     kilobytes { return KBYTES; }
136 adx 475 mb { return MBYTES; }
137 adx 89 mbyte { return MBYTES; }
138     mbytes { return MBYTES; }
139     megabyte { return MBYTES; }
140     megabytes { return MBYTES; }
141 adx 475 m { return MINUTES; }
142     min { return MINUTES; }
143 adx 89 mins { return MINUTES; }
144     minute { return MINUTES; }
145     minutes { return MINUTES; }
146 adx 475 no { yylval.number = 0; return BOOL; }
147     off { yylval.number = 0; return BOOL; }
148     on { yylval.number = 1; return BOOL; }
149     s { return SECONDS; }
150     sec { return SECONDS; }
151 adx 89 secs { return SECONDS; }
152     second { return SECONDS; }
153     seconds { return SECONDS; }
154     true { yylval.number = 1; return BOOL; }
155 adx 475 w { return WEEKS; }
156 adx 89 week { return WEEKS; }
157     weeks { return WEEKS; }
158 adx 475 yes { yylval.number = 1; return BOOL; }
159 michael 669 {IDENTIFIER} { yylval.string = yytext; return IDENTIFIER; }
160 adx 475 . { return yytext[0]; }
161 adx 89 <<EOF>> { if (conf_eof()) yyterminate(); }
162    
163     %%
164    
165     /*
166     * conf_include()
167     *
168     * Enters a new configuration file.
169     *
170     * inputs: none
171     * output: none
172     */
173     static void
174     conf_include(void)
175     {
176     char *fname, *buf;
177     FBFILE *f;
178    
179     if (conf_include_sptr == MAX_INCLUDE_DEPTH)
180     {
181     yyerror("includes nested too deep");
182     return;
183     }
184    
185     if ((fname = strchr(yytext, '"')) == NULL)
186     *strchr(fname = strchr(yytext, '<') + 1, '>') = '\0';
187     else
188     *strchr(++fname, '"') = '\0';
189    
190     if (fname[0] == '/')
191     f = fbopen(fname, "r");
192     else
193     {
194     buf = MyMalloc(strlen(ETCPATH) + 1 + strlen(fname) + 1);
195     sprintf(buf, "%s/%s", ETCPATH, fname);
196     f = fbopen(buf, "r");
197     MyFree(buf);
198     }
199    
200     if (f == NULL)
201     {
202     yyerror("cannot open file to include");
203     return;
204     }
205    
206     /* save current state */
207     memcpy(&conf_include_ctxstack[conf_include_sptr], &conf_curctx,
208     sizeof(struct ConfParserContext));
209     conf_include_yystack[conf_include_sptr++] = YY_CURRENT_BUFFER;
210    
211     /* switch lexer context */
212     conf_linebuf[0] = '\0';
213     conf_curctx.f = f;
214     DupString(conf_curctx.filename, fname);
215     conf_curctx.lineno = 1;
216     yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
217     }
218    
219     /*
220     * conf_eof()
221     *
222     * Ends processing of a configuration file.
223     *
224     * inputs: none
225     * output: 1 if the parser should be exited, 0 otherwise
226     */
227     static int
228     conf_eof(void)
229     {
230     if (conf_include_sptr == 0)
231     return 1;
232    
233     /* destroy current buffer */
234     yy_delete_buffer(YY_CURRENT_BUFFER);
235     fbclose(conf_curctx.f);
236    
237     /* restore old context */
238     conf_linebuf[0] = '\0';
239     memcpy(&conf_curctx, &conf_include_ctxstack[--conf_include_sptr],
240     sizeof(struct ConfParserContext));
241     yy_switch_to_buffer(conf_include_yystack[conf_include_sptr]);
242    
243     return 0;
244     yy_fatal_error(NULL); /* use it somewhere to avoid the warning */
245     }