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

Revision 5135, 7.4 kB (checked in by mmh, 9 months ago)

Bugfix: add carriage return ('\r') to the BLANK character class.
This closes ticket #2284.

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