Import from http://svn.freenode.net/ircd-seven/private/beu/seven (r196).
[seven-1.x.git] / src / ircd_lexer.l
blob87aba6cdaaeec6e9ef03d3daca055a553acc6a64
1 /* src/ircd_lexer.l
2  *
3  *  This program is free software; you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation; either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
16  *  USA
17  *
18  * $Id: ircd_lexer.l 26 2006-09-20 18:02:06Z spb $
19  */
21 %option case-insensitive
22 %option noyywrap
23 %option nounput
26 #include <sys/types.h>
27 #include <sys/stat.h>
29 #include <netinet/in.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <limits.h>
35 #define WE_ARE_MEMORY_C
37 #include "stdinc.h"
38 #include "ircd_defs.h"
39 #include "common.h"
40 #include "config.h"
41 #include "s_log.h"
42 #include "s_conf.h"
43 #include "newconf.h"
45 #include "y.tab.h"
47 int yylex(void);
49 /* here to fixup gcc 3.3 errors */
50 int yyget_lineno(void);
51 FILE *yyget_in(void);
52 FILE *yyget_out(void);
53 int yyget_leng(void);
54 char *yyget_text(void);
55 void yyset_lineno(int  line_number);
56 void yyset_in(FILE *  in_str);
57 void yyset_out(FILE *  out_str);
58 int yyget_debug(void);
59 void yyset_debug(int  bdebug);
60 int yylex_destroy(void);
63 #define MAX_INCLUDE_DEPTH 10
65 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
66 int include_stack_ptr=0;
67 int lineno = 1;
68 void ccomment(void);
69 void cinclude(void);
70 void hashcomment(void);
71 int ieof(void);
72 int lineno_stack[MAX_INCLUDE_DEPTH];
73 char conffile_stack[MAX_INCLUDE_DEPTH][IRCD_BUFSIZE];
74 char conffilebuf[IRCD_BUFSIZE+1];
75 char *current_file = conffilebuf;
77 FILE *inc_fbfile_in[MAX_INCLUDE_DEPTH];
79 char linebuf[512];
81 #undef YY_INPUT
83 #define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg)
85 #define YY_INPUT(buf,result,max_size) \
86   if (!(result = conf_fgets(buf, max_size, conf_fbfile_in))) \
87     YY_FATAL_ERROR("input in flex scanner failed"); 
90 ws        [ \t]*
91 digit     [0-9]
92 comment   #.*
93 qstring   \"[^\"\n]*[\"\n]
94 string    [a-zA-Z_\~][a-zA-Z0-9_]*
95 include   \.include{ws}(\<.*\>|\".*\")
98 {include}       { cinclude(); }
99 "/*"            { ccomment(); }
100 \n.*            { strcpy(linebuf, yytext+1); lineno++; yyless(1); }
102 {ws}            ;
103 {comment}       { hashcomment(); }
105 {digit}+        { yylval.number = atoi(yytext); return NUMBER; }
107 {qstring}       {
108                   if(yytext[yyleng-2] == '\\')
109                     {
110                       yyless(yyleng-1); /* return last quote */
111                       yymore();         /* append next string */
112                     }
113                   else
114                     {
115                       strcpy(yylval.string, yytext + 1);
116                       if(yylval.string[yyleng-2] != '"')
117                         ilog(L_MAIN, "Unterminated character string");
118                       else
119                         {
120                           int i,j;
121                           yylval.string[yyleng-2] = '\0'; /* remove close
122                                                            *  quote 
123                                                            */
124                           
125                           for (j=i=0 ;yylval.string[i] != '\0'; i++,j++)
126                             {
127                               if (yylval.string[i] != '\\')
128                                 {
129                                   yylval.string[j] = yylval.string[i];
130                                 }
131                               else
132                                 {
133                                   i++;
134                                   if (yylval.string[i] == '\0') /* XXX 
135                                                                  * should not
136                                                                  * happen
137                                                                  */
138                                     {
139                                       ilog(L_MAIN,
140                                            "Unterminated character string");
141                                       break;
142                                     }
143                                   yylval.string[j] = yylval.string[i];
144                                 }
145                             }
146                           yylval.string[j] = '\0';
147                           return QSTRING;
148                         }
149                     }
150                 }
153 loadmodule      { return LOADMODULE; }
154 {string}        { 
155                   strcpy(yylval.string, yytext);
156                   yylval.string[yyleng] = '\0';
157                   return STRING;
158                 }
160 \.\.            { return TWODOTS; }
161 .               { return yytext[0]; }
162 <<EOF>>         { if (ieof()) yyterminate(); }
165 /* C-comment ignoring routine -kre*/
166 void ccomment()
168   int c;
169   
170   /* log(L_NOTICE, "got comment"); */
171   while (1)
172     {
173       while ((c = input()) != '*' && c != EOF)
174         if (c == '\n') ++lineno;
175       if (c == '*')
176         {
177           while ((c = input()) == '*');
178           if (c == '/') 
179             break;
180         }
181       if (c == EOF)
182         {
183           YY_FATAL_ERROR("EOF in comment");
184           /* XXX hack alert this disables
185            * the stupid unused function warning
186            * gcc generates
187            */
188           yy_fatal_error("EOF in comment");
189           break;
190         }
191     }
194 void cinclude(void)
196   char *c;
197   if ((c = strchr(yytext, '<')) == NULL)
198     *strchr(c = strchr(yytext, '"') + 1, '"') = 0;
199   else
200     *strchr(++c, '>') = 0;
202   /* do stacking and co. */ 
203   if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
204     conf_report_error("Includes nested too deep (max is %d)", MAX_INCLUDE_DEPTH);
205   else
206   {
207     FILE *tmp_fbfile_in;
208     
209     tmp_fbfile_in = fopen(c, "r");
210     
211     if (tmp_fbfile_in == NULL)
212     {
213       /* if its not found in PREFIX, look in ETCPATH */
214       char fnamebuf[IRCD_BUFSIZE];
216       snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", ETCPATH, c);
217       tmp_fbfile_in = fopen(fnamebuf, "r");
219       /* wasnt found there either.. error. */
220       if(tmp_fbfile_in == NULL)
221       {
222         conf_report_error("Include %s: %s.", c, strerror(errno));
223         return;
224       }
225     }
226     lineno_stack[include_stack_ptr] = lineno;
227     lineno = 1;
228     inc_fbfile_in[include_stack_ptr] = conf_fbfile_in;
229     strcpy(conffile_stack[include_stack_ptr], c);
230     current_file = conffile_stack[include_stack_ptr];
231     include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
232     conf_fbfile_in = tmp_fbfile_in;
233     yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
234   }
237 int ieof(void)
239   if (include_stack_ptr)
240     fclose(conf_fbfile_in);
241   if (--include_stack_ptr < 0)
242   {
243     /* We will now exit the lexer - restore init values if we get /rehash
244      * later and reenter lexer -kre */
245     include_stack_ptr = 0;
246     lineno = 1;
247     return 1;
248   }
249   /* switch buffer */
250   yy_delete_buffer(YY_CURRENT_BUFFER);
251   lineno = lineno_stack[include_stack_ptr];
252   conf_fbfile_in = inc_fbfile_in[include_stack_ptr];
254   if(include_stack_ptr)
255     current_file = conffile_stack[include_stack_ptr];
256   else
257     current_file = conffilebuf;
259   yy_switch_to_buffer(include_stack[include_stack_ptr]);
260   return 0;
263 /* #-comment style, look for #include */
264 #define INCLUDE "#include"
266 void hashcomment(void)
268   if (strlen(yytext) < sizeof(INCLUDE) - 1)
269     return;
271   if (!strncasecmp(yytext, INCLUDE, sizeof(INCLUDE) - 1))
272       yyerror("You probably meant '.include', skipping");