root/lm-sensors/branches/scanner-opt-branch/lib/conf-lex.l @ 4146

Revision 4146, 6.7 KB (checked in by mmh, 7 years ago)

This patch is a minor but easy optimization: slurp up the trailing whitespace
that must follow a label in the same rule.

  • 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
30static int buffer_count;
31static int buffer_max;
32static char *buffer;
33
34char sensors_lex_error[100];
35
36int 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
65BLANK           [ \f\t\v]
66
67IDCHAR          [[:alnum:]_]
68
69 /* Note: `10', `10.4' and `.4' are valid, `10.' is not */
70
71FLOAT   [[:digit:]]*\.?[[:digit:]]+
72
73 /* Only positive whole numbers are recognized here */
74
75NUM     0|([1-9][[:digit:]]*)
76
77 /* Only number between 1 and 255, octally represented. */
78
79OCTESC          (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 /* Keywords must be followed by whitespace - eat that too */
109
110"label"{BLANK}+ {
111                  sensors_yylval.line = sensors_yylineno;
112                  BEGIN(MIDDLE);
113                  return LABEL;
114                }
115
116"set"{BLANK}+   {
117                  sensors_yylval.line = sensors_yylineno;
118                  BEGIN(MIDDLE);
119                  return SET;
120                }
121
122"compute"{BLANK}+ {
123                  sensors_yylval.line = sensors_yylineno;
124                  BEGIN(MIDDLE);
125                  return COMPUTE;
126                }
127
128"bus"{BLANK}+   {
129                  sensors_yylval.line = sensors_yylineno;
130                  BEGIN(MIDDLE);
131                  return BUS;
132                }
133
134"chip"{BLANK}+  {
135                  sensors_yylval.line = sensors_yylineno;
136                  BEGIN(MIDDLE);
137                  return CHIP;
138                }
139
140"ignore"{BLANK}+ {
141                  sensors_yylval.line = sensors_yylineno;
142                  BEGIN(MIDDLE);
143                  return IGNORE;
144                }
145
146 /* Anything else at the beginning of a line is an error */
147
148.               {
149                  yymore();
150                  BEGIN(ERR);
151                }
152}
153
154 /*
155  * STATE: ERROR
156  */
157
158<ERR>{
159
160.*(\n)?         {
161                  BEGIN(INITIAL);
162                  strcpy(sensors_lex_error,"Invalid keyword");
163                  return ERROR;
164                }
165}
166
167 /*
168  * STATE: MIDDLE
169  */
170
171<MIDDLE>{
172
173{BLANK}+        ; /* eat as many blanks as possible at once */
174
175\n              { /* newline here sends EOL token to parser */
176                  BEGIN(INITIAL);
177                  sensors_yylineno++;
178                  return EOL;
179                }
180
181<<EOF>>         { /* EOF here sends EOL token to parser also */
182                  BEGIN(INITIAL);
183                  return EOL;
184                }
185
186\\{BLANK}*\n    { /* eat an escaped newline with no state change */
187                  sensors_yylineno++;
188                }
189
190 /* comments */
191
192#.*             ; /* eat the rest of the line after comment char */
193
194#.*\n           { /* eat the rest of the line after comment char */
195                  BEGIN(INITIAL);
196                  sensors_yylineno++;
197                  return EOL;
198                }
199
200 /* A number */
201
202{FLOAT}         {
203                  sensors_yylval.value = atof(sensors_yytext);
204                  return FLOAT;
205                }
206
207 /* Some operators */
208
209"+"             return '+';
210"-"             return '-';
211"*"             return '*';
212"/"             return '/';
213"("             return '(';
214")"             return ')';
215","             return ',';
216"@"             return '@';
217"^"             return '^';
218"`"             return '`';
219
220 /* Quoted string */
221
222\"              {
223                  buffer_malloc();
224                  BEGIN(STRING);
225                }
226
227 /* A normal, unquoted identifier */
228
229{IDCHAR}+       {
230                  sensors_yylval.name = strdup(sensors_yytext);
231                  if (! sensors_yylval.name)
232                    sensors_fatal_error("conf-lex.l",
233                                        "Allocating a new string");
234                 
235                  return NAME;
236                }
237
238 /* anything else is bogus */
239
240.               {
241                  yymore();
242                  BEGIN(ERR);
243                }
244}
245
246 /*
247  * STATE: STRING
248  */
249
250<STRING>{
251
252 /* Oops, newline while in a string is not good */
253
254\n              |
255\\\n            {
256                  buffer_add_char("\0");
257                  strcpy(sensors_lex_error,"No matching double quote");
258                  buffer_free();
259                  BEGIN(INITIAL);
260                  return ERROR;
261                }
262
263 /* At the end */
264
265\"              {
266                  buffer_add_char("\0");
267                  sensors_yylval.name = strdup(buffer);
268                  if (! sensors_yylval.name)
269                    sensors_fatal_error("conf-lex.l",
270                                        "Allocating a new string");
271                  buffer_free();
272                  BEGIN(MIDDLE);
273                  return NAME;
274                }
275
276\\a             {
277                  buffer_add_char("\a");
278                }
279
280\\b             {
281                  buffer_add_char("\b");
282                }
283
284\\f             {
285                  buffer_add_char("\f");
286                }
287
288\\n             {
289                  buffer_add_char("\n");
290                }
291
292\\r             {
293                  buffer_add_char("\r");
294                }
295
296\\t             {
297                  buffer_add_char("\t");
298                }
299
300\\v             {
301                  buffer_add_char("\v");
302                }
303
304 /* We can't support \0, this would cause havoc! */
305
306\\{OCTESC}      {
307                  int res;
308                  sscanf(sensors_yytext+1,"%o",&res);
309                  buffer_add_char(&res);
310                }
311
312 /* Other escapes: just copy the character behind the slash */
313
314\\.             {
315                  buffer_add_char(&sensors_yytext[1]);
316                }
317
318 /* Anything else */
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
Note: See TracBrowser for help on using the browser.