|
Packit |
53d5b6 |
%{
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
conf-lex.l - Part of libsensors, a Linux library for reading sensor data.
|
|
Packit |
53d5b6 |
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
This library is free software; you can redistribute it and/or
|
|
Packit |
53d5b6 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
53d5b6 |
License as published by the Free Software Foundation; either
|
|
Packit |
53d5b6 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
53d5b6 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
53d5b6 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
53d5b6 |
GNU Lesser General Public License for more details.
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
You should have received a copy of the GNU General Public License
|
|
Packit |
53d5b6 |
along with this program; if not, write to the Free Software
|
|
Packit |
53d5b6 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
Packit |
53d5b6 |
MA 02110-1301 USA.
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#include <stdlib.h>
|
|
Packit |
53d5b6 |
#include <string.h>
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#include "general.h"
|
|
Packit |
53d5b6 |
#include "data.h"
|
|
Packit |
53d5b6 |
#include "conf-parse.h"
|
|
Packit |
53d5b6 |
#include "error.h"
|
|
Packit |
53d5b6 |
#include "scanner.h"
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
static int buffer_count;
|
|
Packit |
53d5b6 |
static int buffer_max;
|
|
Packit |
53d5b6 |
static char *buffer;
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
char sensors_lex_error[100];
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
const char *sensors_yyfilename;
|
|
Packit |
53d5b6 |
int sensors_yylineno;
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#define buffer_malloc() sensors_malloc_array(&buffer,&buffer_count,\
|
|
Packit |
53d5b6 |
&buffer_max,1)
|
|
Packit |
53d5b6 |
#define buffer_free() sensors_free_array(&buffer,&buffer_count,\
|
|
Packit |
53d5b6 |
&buffer_max)
|
|
Packit |
53d5b6 |
#define buffer_add_char(c) sensors_add_array_el(c,&buffer,\
|
|
Packit |
53d5b6 |
&buffer_count,\
|
|
Packit |
53d5b6 |
&buffer_max,1)
|
|
Packit |
53d5b6 |
#define buffer_add_string(s) sensors_add_array_els(s,strlen(s),\
|
|
Packit |
53d5b6 |
&buffer, \
|
|
Packit |
53d5b6 |
&buffer_count,&buffer_max,1)
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
%}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Scanner for configuration files */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
%option nodefault
|
|
Packit |
53d5b6 |
%option noyywrap
|
|
Packit |
53d5b6 |
%option nounput
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* All states are exclusive */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
%x MIDDLE
|
|
Packit |
53d5b6 |
%x STRING
|
|
Packit |
53d5b6 |
%x ERR
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Any whitespace-like character */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
BLANK [ \f\r\t\v]
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
IDCHAR [[:alnum:]_]
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Note: `10', `10.4' and `.4' are valid, `10.' is not */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
FLOAT [[:digit:]]*\.?[[:digit:]]+
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Only positive whole numbers are recognized here */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
NUM 0|([1-9][[:digit:]]*)
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
%%
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
* STATE: INITIAL
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<INITIAL>{
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<<EOF>> { /* EOF from this state terminates */
|
|
Packit |
53d5b6 |
return 0;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
{BLANK}+ ; /* eat as many blanks as possible at once */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
{BLANK}*\n { /* eat a bare newline (possibly preceded by blanks) */
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* comments */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#.* ; /* eat the rest of the line after comment char */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#.*\n { /* eat the rest of the line after comment char */
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
* Keywords must be followed by whitespace - eat that too.
|
|
Packit |
53d5b6 |
* If there isn't trailing whitespace, we still need to
|
|
Packit |
53d5b6 |
* accept it as lexically correct (even though the parser
|
|
Packit |
53d5b6 |
* will reject it anyway.)
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
label{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return LABEL;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
set{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return SET;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
compute{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return COMPUTE;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
bus{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return BUS;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
chip{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return CHIP;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
ignore{BLANK}* {
|
|
Packit |
53d5b6 |
sensors_yylval.line.filename = sensors_yyfilename;
|
|
Packit |
53d5b6 |
sensors_yylval.line.lineno = sensors_yylineno;
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return IGNORE;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Anything else at the beginning of a line is an error */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
[a-z]+ |
|
|
Packit |
53d5b6 |
. {
|
|
Packit |
53d5b6 |
BEGIN(ERR);
|
|
Packit |
53d5b6 |
strcpy(sensors_lex_error,"Invalid keyword");
|
|
Packit |
53d5b6 |
return ERROR;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
* STATE: ERROR
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<ERR>{
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
.* ; /* eat whatever is left on this line */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\n {
|
|
Packit |
53d5b6 |
BEGIN(INITIAL);
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
return EOL;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
* STATE: MIDDLE
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<MIDDLE>{
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
{BLANK}+ ; /* eat as many blanks as possible at once */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\n { /* newline here sends EOL token to parser */
|
|
Packit |
53d5b6 |
BEGIN(INITIAL);
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
return EOL;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<<EOF>> { /* EOF here sends EOL token to parser also */
|
|
Packit |
53d5b6 |
BEGIN(INITIAL);
|
|
Packit |
53d5b6 |
return EOL;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\\{BLANK}*\n { /* eat an escaped newline with no state change */
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* comments */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#.* ; /* eat the rest of the line after comment char */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
#.*\n { /* eat the rest of the line after comment char */
|
|
Packit |
53d5b6 |
BEGIN(INITIAL);
|
|
Packit |
53d5b6 |
sensors_yylineno++;
|
|
Packit |
53d5b6 |
return EOL;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* A number */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
{FLOAT} {
|
|
Packit |
53d5b6 |
sensors_yylval.value = atof(sensors_yytext);
|
|
Packit |
53d5b6 |
return FLOAT;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Some operators */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
"+" return '+';
|
|
Packit |
53d5b6 |
"-" return '-';
|
|
Packit |
53d5b6 |
"*" return '*';
|
|
Packit |
53d5b6 |
"/" return '/';
|
|
Packit |
53d5b6 |
"(" return '(';
|
|
Packit |
53d5b6 |
")" return ')';
|
|
Packit |
53d5b6 |
"," return ',';
|
|
Packit |
53d5b6 |
"@" return '@';
|
|
Packit |
53d5b6 |
"^" return '^';
|
|
Packit |
53d5b6 |
"`" return '`';
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Quoted string */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\" {
|
|
Packit |
53d5b6 |
buffer_malloc();
|
|
Packit |
53d5b6 |
BEGIN(STRING);
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* A normal, unquoted identifier */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
{IDCHAR}+ {
|
|
Packit |
53d5b6 |
sensors_yylval.name = strdup(sensors_yytext);
|
|
Packit |
53d5b6 |
if (! sensors_yylval.name)
|
|
Packit |
53d5b6 |
sensors_fatal_error("conf-lex.l",
|
|
Packit |
53d5b6 |
"Allocating a new string");
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
return NAME;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* anything else is bogus */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
. |
|
|
Packit |
53d5b6 |
[[:digit:]]*\. |
|
|
Packit |
53d5b6 |
\\{BLANK}* {
|
|
Packit |
53d5b6 |
BEGIN(ERR);
|
|
Packit |
53d5b6 |
return ERROR;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
* STATE: STRING
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<STRING>{
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Oops, newline or EOF while in a string is not good */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\n |
|
|
Packit |
53d5b6 |
\\\n {
|
|
Packit |
53d5b6 |
buffer_add_char("\0");
|
|
Packit |
53d5b6 |
strcpy(sensors_lex_error,
|
|
Packit |
53d5b6 |
"No matching double quote.");
|
|
Packit |
53d5b6 |
buffer_free();
|
|
Packit |
53d5b6 |
yyless(0);
|
|
Packit |
53d5b6 |
BEGIN(ERR);
|
|
Packit |
53d5b6 |
return ERROR;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
<<EOF>> {
|
|
Packit |
53d5b6 |
strcpy(sensors_lex_error,
|
|
Packit |
53d5b6 |
"Reached end-of-file without a matching double quote.");
|
|
Packit |
53d5b6 |
buffer_free();
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return ERROR;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* At the end */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\"\" {
|
|
Packit |
53d5b6 |
buffer_add_char("\0");
|
|
Packit |
53d5b6 |
strcpy(sensors_lex_error,
|
|
Packit |
53d5b6 |
"Quoted strings must be separated by whitespace.");
|
|
Packit |
53d5b6 |
buffer_free();
|
|
Packit |
53d5b6 |
BEGIN(ERR);
|
|
Packit |
53d5b6 |
return ERROR;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\" {
|
|
Packit |
53d5b6 |
buffer_add_char("\0");
|
|
Packit |
53d5b6 |
sensors_yylval.name = strdup(buffer);
|
|
Packit |
53d5b6 |
if (! sensors_yylval.name)
|
|
Packit |
53d5b6 |
sensors_fatal_error("conf-lex.l",
|
|
Packit |
53d5b6 |
"Allocating a new string");
|
|
Packit |
53d5b6 |
buffer_free();
|
|
Packit |
53d5b6 |
BEGIN(MIDDLE);
|
|
Packit |
53d5b6 |
return NAME;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\\a buffer_add_char("\a");
|
|
Packit |
53d5b6 |
\\b buffer_add_char("\b");
|
|
Packit |
53d5b6 |
\\f buffer_add_char("\f");
|
|
Packit |
53d5b6 |
\\n buffer_add_char("\n");
|
|
Packit |
53d5b6 |
\\r buffer_add_char("\r");
|
|
Packit |
53d5b6 |
\\t buffer_add_char("\t");
|
|
Packit |
53d5b6 |
\\v buffer_add_char("\v");
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Other escapes: just copy the character behind the slash */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\\. {
|
|
Packit |
53d5b6 |
buffer_add_char(&sensors_yytext[1]);
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* Anything else (including a bare '\' which may be followed by EOF) */
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
\\ |
|
|
Packit |
53d5b6 |
[^\\\n\"]+ {
|
|
Packit |
53d5b6 |
buffer_add_string(sensors_yytext);
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
%%
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/*
|
|
Packit |
53d5b6 |
Do the buffer handling manually. This allows us to scan as many
|
|
Packit |
53d5b6 |
config files as we need to, while cleaning up properly after each
|
|
Packit |
53d5b6 |
one. The "BEGIN(0)" line ensures that we start in the default state,
|
|
Packit |
53d5b6 |
even if e.g. the previous config file was syntactically broken.
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
Returns 0 if successful, !0 otherwise.
|
|
Packit |
53d5b6 |
*/
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
static YY_BUFFER_STATE scan_buf = (YY_BUFFER_STATE)0;
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
int sensors_scanner_init(FILE *input, const char *filename)
|
|
Packit |
53d5b6 |
{
|
|
Packit |
53d5b6 |
BEGIN(0);
|
|
Packit |
53d5b6 |
if (!(scan_buf = sensors_yy_create_buffer(input, YY_BUF_SIZE)))
|
|
Packit |
53d5b6 |
return -1;
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
sensors_yy_switch_to_buffer(scan_buf);
|
|
Packit |
53d5b6 |
sensors_yyfilename = filename;
|
|
Packit |
53d5b6 |
sensors_yylineno = 1;
|
|
Packit |
53d5b6 |
return 0;
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
void sensors_scanner_exit(void)
|
|
Packit |
53d5b6 |
{
|
|
Packit |
53d5b6 |
sensors_yy_delete_buffer(scan_buf);
|
|
Packit |
53d5b6 |
scan_buf = (YY_BUFFER_STATE)0;
|
|
Packit |
53d5b6 |
|
|
Packit |
53d5b6 |
/* As of flex 2.5.9, yylex_destroy() must be called when done with the
|
|
Packit |
53d5b6 |
scaller, otherwise we'll leak memory. */
|
|
Packit |
53d5b6 |
#if defined(YY_FLEX_MAJOR_VERSION) && defined(YY_FLEX_MINOR_VERSION) && defined(YY_FLEX_SUBMINOR_VERSION)
|
|
Packit |
53d5b6 |
#if YY_FLEX_MAJOR_VERSION > 2 || \
|
|
Packit |
53d5b6 |
(YY_FLEX_MAJOR_VERSION == 2 && (YY_FLEX_MINOR_VERSION > 5 || \
|
|
Packit |
53d5b6 |
(YY_FLEX_MINOR_VERSION == 5 && YY_FLEX_SUBMINOR_VERSION >= 9)))
|
|
Packit |
53d5b6 |
sensors_yylex_destroy();
|
|
Packit |
53d5b6 |
#endif
|
|
Packit |
53d5b6 |
#endif
|
|
Packit |
53d5b6 |
}
|
|
Packit |
53d5b6 |
|