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

Revision 4123, 6.6 KB (checked in by mmh, 7 years ago)

Remove %option yylineno and add/modify rules to count lines explicitly;
this is a performance win. Tweak some other rules for potential speedups
also (e.g. use {BLANK}+ in place of {BLANK} to eat as much whitespace as
possible in a single shot).

This is all straight out of the Performance section of the Flex manual.

  • 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 /*
58  * States. 'Normal' states STRING and MIDDLE share some rules;
59  * other states have only their own rules
60  */
61
62%s MIDDLE
63%x STRING
64%x ERR
65
66 /* Any whitespace-like character */
67
68BLANK           [ \f\t\v]
69
70IDCHAR          [[:alnum:]_]
71
72 /* Note: `10', `10.4' and `.4' are valid, `10.' is not */
73
74FLOAT   [[:digit:]]*\.?[[:digit:]]+
75
76 /* Only positive whole numbers are recognized here */
77
78NUM     0|([1-9][[:digit:]]*)
79
80 /* Only number between 1 and 255, octally represented. */
81
82OCTESC          (1[0-7]{0,2})|([2-7][0-7]?)|(0[1-7][0-7]?)|(00[1-7])
83
84
85%%
86
87
88<MIDDLE>\n      { /* newline here sends EOL token to parser */
89                  BEGIN(INITIAL);
90                  sensors_yylineno++;
91                  return EOL;
92                }
93
94<MIDDLE><<EOF>> { /* EOF here sends EOL token to parser also */
95                  BEGIN(INITIAL);
96                  return EOL;
97                }
98
99{BLANK}+ ;        /* eat as many blanks as possible at once */
100
101{BLANK}*\n      { /* eat a bare newline (possibly preceded by blanks) */
102                  sensors_yylineno++;
103                }
104
105<MIDDLE>\\{BLANK}*\n { /* eat an escaped newline with no state change */
106                  sensors_yylineno++;
107                }
108
109<MIDDLE>#.*     ; /* eat the rest of the line after comment char */
110
111<MIDDLE>#.*\n   { /* eat the rest of the line after comment char */
112                  BEGIN(INITIAL);
113                  sensors_yylineno++;
114                  return EOL;
115                }
116
117#.*             ; /* eat the rest of the line after comment char */
118
119#.*\n           { /* eat the rest of the line after comment char */
120                  sensors_yylineno++;
121                }
122
123 /* Some keywords at the beginning of lines */
124
125<INITIAL>"label" {
126                  sensors_yylval.line = sensors_yylineno;
127                  BEGIN(MIDDLE);
128                  return LABEL;
129                }
130
131<INITIAL>"set"  {
132                  sensors_yylval.line = sensors_yylineno;
133                  BEGIN(MIDDLE);
134                  return SET;
135                }
136
137<INITIAL>"compute" {
138                  sensors_yylval.line = sensors_yylineno;
139                  BEGIN(MIDDLE);
140                  return COMPUTE;
141                }
142
143<INITIAL>"bus"  {
144                  sensors_yylval.line = sensors_yylineno;
145                  BEGIN(MIDDLE);
146                  return BUS;
147                }
148
149<INITIAL>"chip" {
150                  sensors_yylval.line = sensors_yylineno;
151                  BEGIN(MIDDLE);
152                  return CHIP;
153                }
154<INITIAL>"ignore" {
155                  sensors_yylval.line = sensors_yylineno;
156                  BEGIN(MIDDLE);
157                  return IGNORE;
158                }
159
160 /* Anything else at the beginning of a line is an error */
161
162<INITIAL>.      {
163                  yymore();
164                  BEGIN(ERR);
165                }
166
167<ERR>[^\n]*\n   {
168                  BEGIN(INITIAL);
169                  strcpy(sensors_lex_error,"Invalid keyword");
170                  return ERROR;
171                }
172
173 /* A number */
174
175<MIDDLE>{FLOAT} {
176                  sensors_yylval.value = atof(sensors_yytext);
177                  return FLOAT;
178                }
179
180 /* Some operators */
181
182<MIDDLE>"+"     return '+';
183<MIDDLE>"-"     return '-';
184<MIDDLE>"*"     return '*';
185<MIDDLE>"/"     return '/';
186<MIDDLE>"("     return '(';
187<MIDDLE>")"     return ')';
188<MIDDLE>","     return ',';
189<MIDDLE>"@"     return '@';
190<MIDDLE>"^"     return '^';
191<MIDDLE>"`"     return '`';
192
193 /* Quoted string */
194
195<MIDDLE>\"      {
196                  buffer_malloc();
197                  BEGIN(STRING);
198                }
199
200 /* Oops, newline while in a string is not good */
201
202<STRING>\n      |
203<STRING>\\\n    {
204                  buffer_add_char("\0");
205                  strcpy(sensors_lex_error,"No matching double quote");
206                  buffer_free();
207                  BEGIN(INITIAL);
208                  return ERROR;
209                }
210
211 /* At the end */
212
213<STRING>\"      {
214                  buffer_add_char("\0");
215                  sensors_yylval.name = strdup(buffer);
216                  if (! sensors_yylval.name)
217                    sensors_fatal_error("conf-lex.l",
218                                        "Allocating a new string");
219                  buffer_free();
220                  BEGIN(MIDDLE);
221                  return NAME;
222                }
223
224<STRING>\\a     {
225                  buffer_add_char("\a");
226                }
227
228<STRING>\\b     {
229                  buffer_add_char("\b");
230                }
231
232<STRING>\\f     {
233                  buffer_add_char("\f");
234                }
235
236<STRING>\\n     {
237                  buffer_add_char("\n");
238                }
239
240<STRING>\\r     {
241                  buffer_add_char("\r");
242                }
243
244<STRING>\\t     {
245                  buffer_add_char("\t");
246                }
247
248<STRING>\\v     {
249                  buffer_add_char("\v");
250                }
251
252 /* We can't support \0, this would cause havoc! */
253
254<STRING>\\{OCTESC} {
255                  int res;
256                  sscanf(sensors_yytext+1,"%o",&res);
257                  buffer_add_char(&res);
258                }
259
260 /* Other escapes: just copy the character behind the slash */
261
262<STRING>\\.     {
263                  buffer_add_char(&sensors_yytext[1]);
264                }
265
266 /* Anything else */
267
268<STRING>[^\\\n\"]+ {
269                  buffer_add_string(sensors_yytext);
270                }
271
272 /* A normal, unquoted identifier */
273
274<MIDDLE>{IDCHAR}+ {
275                  sensors_yylval.name = strdup(sensors_yytext);
276                  if (! sensors_yylval.name)
277                    sensors_fatal_error("conf-lex.l",
278                                        "Allocating a new string");
279                 
280                  return NAME;
281                }
282
283%%
284
285/*
286        Do the buffer handling manually.  This allows us to scan as many
287        config files as we need to, while cleaning up properly after each
288        one.  The "BEGIN(0)" line ensures that we start in the default state,
289        even if e.g. the previous config file was syntactically broken.
290
291        Returns 0 if successful, !0 otherwise.
292*/
293
294static YY_BUFFER_STATE scan_buf = (YY_BUFFER_STATE)0;
295
296int sensors_scanner_init(FILE *input)
297{
298        BEGIN(0);
299        if (!(scan_buf = sensors_yy_create_buffer(input, YY_BUF_SIZE)))
300                return -1;
301
302        sensors_yy_switch_to_buffer(scan_buf);
303        sensors_yylineno = 1;
304        return 0;
305}
306
307void sensors_scanner_exit(void)
308{
309        sensors_yy_delete_buffer(scan_buf);
310        scan_buf = (YY_BUFFER_STATE)0;
311}
312
Note: See TracBrowser for help on using the browser.