root/lm-sensors/trunk/lib/conf-lex.l @ 5637

Revision 5637, 7.4 KB (checked in by khali, 4 years ago)

Fix memory leak in scanner when using flex 2.5.9 or later.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1%{
2/*
3    conf-lex.l - Part of libsensors, a Linux library for reading sensor data.
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your 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
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19    MA 02110-1301 USA.
20*/
21
22#include <stdlib.h>
23#include <string.h>
24
25#include "general.h"
26#include "data.h"
27#include "conf-parse.h"
28#include "error.h"
29#include "scanner.h"
30
31static int buffer_count;
32static int buffer_max;
33static char *buffer;
34
35char sensors_lex_error[100];
36
37int sensors_yylineno;
38
39#define buffer_malloc() sensors_malloc_array(&buffer,&buffer_count,\
40                                             &buffer_max,1)
41#define buffer_free() sensors_free_array(&buffer,&buffer_count,\
42                                         &buffer_max)
43#define buffer_add_char(c) sensors_add_array_el(c,&buffer,\
44                                                &buffer_count,\
45                                                &buffer_max,1)
46#define buffer_add_string(s) sensors_add_array_els(s,strlen(s),\
47                                                   &buffer, \
48                                                   &buffer_count,&buffer_max,1)
49
50%}
51
52 /* Scanner for configuration files */
53
54%option nodefault
55%option noyywrap
56%option nounput
57
58 /* All states are exclusive */
59
60%x MIDDLE
61%x STRING
62%x ERR
63
64 /* Any whitespace-like character */
65
66BLANK           [ \f\r\t\v]
67
68IDCHAR          [[:alnum:]_]
69
70 /* Note: `10', `10.4' and `.4' are valid, `10.' is not */
71
72FLOAT   [[:digit:]]*\.?[[:digit:]]+
73
74 /* Only positive whole numbers are recognized here */
75
76NUM     0|([1-9][[:digit:]]*)
77
78
79%%
80
81 /*
82  * STATE: INITIAL
83  */
84
85<INITIAL>{
86
87<<EOF>>         { /* EOF from this state terminates */
88                  return 0;
89                }
90
91{BLANK}+        ; /* eat as many blanks as possible at once */
92
93{BLANK}*\n      { /* eat a bare newline (possibly preceded by blanks) */
94                  sensors_yylineno++;
95                }
96
97 /* comments */
98
99#.*             ; /* eat the rest of the line after comment char */
100
101#.*\n           { /* eat the rest of the line after comment char */
102                  sensors_yylineno++;
103                }
104
105 /*
106  * Keywords must be followed by whitespace - eat that too.
107  * If there isn't trailing whitespace, we still need to
108  * accept it as lexically correct (even though the parser
109  * will reject it anyway.)
110  */
111
112label{BLANK}*   {
113                  sensors_yylval.line = sensors_yylineno;
114                  BEGIN(MIDDLE);
115                  return LABEL;
116                }
117
118set{BLANK}*     {
119                  sensors_yylval.line = sensors_yylineno;
120                  BEGIN(MIDDLE);
121                  return SET;
122                }
123
124compute{BLANK}* {
125                  sensors_yylval.line = sensors_yylineno;
126                  BEGIN(MIDDLE);
127                  return COMPUTE;
128                }
129
130bus{BLANK}*     {
131                  sensors_yylval.line = sensors_yylineno;
132                  BEGIN(MIDDLE);
133                  return BUS;
134                }
135
136chip{BLANK}*    {
137                  sensors_yylval.line = sensors_yylineno;
138                  BEGIN(MIDDLE);
139                  return CHIP;
140                }
141
142ignore{BLANK}*  {
143                  sensors_yylval.line = sensors_yylineno;
144                  BEGIN(MIDDLE);
145                  return IGNORE;
146                }
147
148 /* Anything else at the beginning of a line is an error */
149
150[a-z]+          |
151.               {
152                  BEGIN(ERR);
153                  strcpy(sensors_lex_error,"Invalid keyword");
154                  return ERROR;
155                }
156}
157
158 /*
159  * STATE: ERROR
160  */
161
162<ERR>{
163
164.*              ; /* eat whatever is left on this line */
165
166\n              {
167                  BEGIN(INITIAL);
168                  sensors_yylineno++;
169                  return EOL;
170                }
171}
172
173 /*
174  * STATE: MIDDLE
175  */
176
177<MIDDLE>{
178
179{BLANK}+        ; /* eat as many blanks as possible at once */
180
181\n              { /* newline here sends EOL token to parser */
182                  BEGIN(INITIAL);
183                  sensors_yylineno++;
184                  return EOL;
185                }
186
187<<EOF>>         { /* EOF here sends EOL token to parser also */
188                  BEGIN(INITIAL);
189                  return EOL;
190                }
191
192\\{BLANK}*\n    { /* eat an escaped newline with no state change */
193                  sensors_yylineno++;
194                }
195
196 /* comments */
197
198#.*             ; /* eat the rest of the line after comment char */
199
200#.*\n           { /* eat the rest of the line after comment char */
201                  BEGIN(INITIAL);
202                  sensors_yylineno++;
203                  return EOL;
204                }
205
206 /* A number */
207
208{FLOAT}         {
209                  sensors_yylval.value = atof(sensors_yytext);
210                  return FLOAT;
211                }
212
213 /* Some operators */
214
215"+"             return '+';
216"-"             return '-';
217"*"             return '*';
218"/"             return '/';
219"("             return '(';
220")"             return ')';
221","             return ',';
222"@"             return '@';
223"^"             return '^';
224"`"             return '`';
225
226 /* Quoted string */
227
228\"              {
229                  buffer_malloc();
230                  BEGIN(STRING);
231                }
232
233 /* A normal, unquoted identifier */
234
235{IDCHAR}+       {
236                  sensors_yylval.name = strdup(sensors_yytext);
237                  if (! sensors_yylval.name)
238                    sensors_fatal_error("conf-lex.l",
239                                        "Allocating a new string");
240                 
241                  return NAME;
242                }
243
244 /* anything else is bogus */
245
246.               |
247[[:digit:]]*\.  |
248\\{BLANK}*      {
249                  BEGIN(ERR);
250                  return ERROR;
251                }
252}
253
254 /*
255  * STATE: STRING
256  */
257
258<STRING>{
259
260 /* Oops, newline or EOF while in a string is not good */
261
262\n              |
263\\\n            {
264                  buffer_add_char("\0");
265                  strcpy(sensors_lex_error,
266                        "No matching double quote.");
267                  buffer_free();
268                  yyless(0);
269                  BEGIN(ERR);
270                  return ERROR;
271                }
272
273<<EOF>>         {
274                  strcpy(sensors_lex_error,
275                        "Reached end-of-file without a matching double quote.");
276                  buffer_free();
277                  BEGIN(MIDDLE);
278                  return ERROR;
279                }
280
281 /* At the end */
282
283\"\"            {
284                  buffer_add_char("\0");
285                  strcpy(sensors_lex_error,
286                        "Quoted strings must be separated by whitespace.");
287                  buffer_free();
288                  BEGIN(ERR);
289                  return ERROR;
290                }
291               
292\"              {
293                  buffer_add_char("\0");
294                  sensors_yylval.name = strdup(buffer);
295                  if (! sensors_yylval.name)
296                    sensors_fatal_error("conf-lex.l",
297                                        "Allocating a new string");
298                  buffer_free();
299                  BEGIN(MIDDLE);
300                  return NAME;
301                }
302
303\\a             buffer_add_char("\a");
304\\b             buffer_add_char("\b");
305\\f             buffer_add_char("\f");
306\\n             buffer_add_char("\n");
307\\r             buffer_add_char("\r");
308\\t             buffer_add_char("\t");
309\\v             buffer_add_char("\v");
310
311 /* Other escapes: just copy the character behind the slash */
312
313\\.             {
314                  buffer_add_char(&sensors_yytext[1]);
315                }
316
317 /* Anything else (including a bare '\' which may be followed by EOF) */
318
319\\              |
320[^\\\n\"]+      {
321                  buffer_add_string(sensors_yytext);
322                }
323}
324
325%%
326
327/*
328        Do the buffer handling manually.  This allows us to scan as many
329        config files as we need to, while cleaning up properly after each
330        one.  The "BEGIN(0)" line ensures that we start in the default state,
331        even if e.g. the previous config file was syntactically broken.
332
333        Returns 0 if successful, !0 otherwise.
334*/
335
336static YY_BUFFER_STATE scan_buf = (YY_BUFFER_STATE)0;
337
338int sensors_scanner_init(FILE *input)
339{
340        BEGIN(0);
341        if (!(scan_buf = sensors_yy_create_buffer(input, YY_BUF_SIZE)))
342                return -1;
343
344        sensors_yy_switch_to_buffer(scan_buf);
345        sensors_yylineno = 1;
346        return 0;
347}
348
349void sensors_scanner_exit(void)
350{
351        sensors_yy_delete_buffer(scan_buf);
352        scan_buf = (YY_BUFFER_STATE)0;
353
354/* As of flex 2.5.9, yylex_destroy() must be called when done with the
355   scaller, otherwise we'll leak memory. */
356#if defined(YY_FLEX_MAJOR_VERSION) && defined(YY_FLEX_MINOR_VERSION) && defined(YY_FLEX_SUBMINOR_VERSION)
357#if YY_FLEX_MAJOR_VERSION > 2 || \
358    (YY_FLEX_MAJOR_VERSION == 2 && (YY_FLEX_MINOR_VERSION > 5 || \
359                                    (YY_FLEX_MINOR_VERSION == 5 && YY_FLEX_SUBMINOR_VERSION >= 9)))
360        sensors_yylex_destroy();
361#endif
362#endif
363}
364
Note: See TracBrowser for help on using the browser.