propagator/pcmcia/lex_config.l
2004-01-20 18:32:43 +00:00

270 lines
6.3 KiB
Plaintext

/* Special state for handling include files */
%x src
%{
/*
* lex_config.l 1.49 2002/10/07 16:39:21
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#undef src
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#ifdef HAS_WORDEXP
#include <wordexp.h>
#else
#include <glob.h>
#endif
#define src 1
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include "yacc_config.h"
/* For assembling nice error messages */
char *current_file;
int current_lineno;
static int lex_number(char *s);
static int lex_string(char *s);
static void do_source(char *fn);
static int do_eof(void);
%}
int [0-9]+
hex 0x[0-9a-fA-F]+
str \"([^"]|\\.)*\"
%%
source[ \t]+ BEGIN(src); return SOURCE;
<src>[^\n]+ do_source(yytext); BEGIN(INITIAL);
<<EOF>> if (do_eof()) yyterminate();
\n current_lineno++;
[ \t]* /* skip */ ;
[ ]*[#;].* /* skip */ ;
anonymous return ANONYMOUS;
bind return BIND;
cis return CIS;
card return CARD;
class return CLASS;
default return DEFAULT;
device return DEVICE;
dtype return DTYPE;
exclude return EXCLUDE;
function return FUNCTION;
include return INCLUDE;
irq return IRQ_NO;
jedec return JEDEC;
manfid return MANFID;
memory return MEMORY;
module return MODULE;
mtd return MTD;
needs_mtd return NEEDS_MTD;
opts return OPTS;
pci return PCI;
port return PORT;
region return REGION;
reserve return RESERVE;
to return TO;
tuple return TUPLE;
version return VERSION;
memory_card return lex_number("1");
serial_port return lex_number("2");
parallel_port return lex_number("3");
fixed_disk return lex_number("4");
video_adapter return lex_number("5");
network_adapter return lex_number("6");
aims_card return lex_number("7");
scsi_adapter return lex_number("8");
{int} return lex_number(yytext);
{hex} return lex_number(yytext);
{str} return lex_string(yytext);
. return yytext[0];
%%
#ifndef yywrap
int yywrap() { return 1; }
#endif
/*======================================================================
Stuff to parse basic data types
======================================================================*/
static int lex_number(char *s)
{
yylval.num = strtoul(s, NULL, 0);
return NUMBER;
}
static int lex_string(char *s)
{
int n = strlen(s);
yylval.str = malloc(n-1);
strncpy(yylval.str, s+1, n-2);
yylval.str[n-2] = '\0';
return STRING;
}
/*======================================================================
Code to support nesting of configuration files
======================================================================*/
#define MAX_SOURCE_DEPTH 4
struct source_stack {
YY_BUFFER_STATE buffer;
char *filename;
int lineno, fileno;
FILE *file;
#ifdef HAS_WORDEXP
wordexp_t word;
#else
glob_t glob;
#endif
} source_stack[MAX_SOURCE_DEPTH];
static int source_stack_ptr = 0;
static int parse_env = 0;
static int get_glob(void)
{
struct source_stack *s = &source_stack[source_stack_ptr];
#ifdef HAS_WORDEXP
while (s->fileno < s->word.we_wordc) {
char *fn = s->word.we_wordv[s->fileno];
#else
while (s->fileno < s->glob.gl_pathc) {
char *fn = s->glob.gl_pathv[s->fileno];
#endif
s->file = fopen(fn, "r");
if (s->file == NULL) {
if (strpbrk(fn, "?*[") == NULL)
syslog(LOG_INFO, "could not open '%s': %m", fn);
s->fileno++;
} else {
current_lineno = 1;
current_file = strdup(fn);
yy_switch_to_buffer(yy_create_buffer(s->file, YY_BUF_SIZE));
source_stack_ptr++;
s->fileno++;
return 0;
}
}
return -1;
}
static void do_source(char *fn)
{
struct source_stack *s = &source_stack[source_stack_ptr];
if (source_stack_ptr >= MAX_SOURCE_DEPTH) {
syslog(LOG_INFO, "source depth limit exceeded");
return;
}
#ifdef HAS_WORDEXP
wordexp(fn, &s->word, 0);
#else
glob(fn, GLOB_NOCHECK, NULL, &s->glob);
#endif
s->fileno = 0;
s->buffer = YY_CURRENT_BUFFER;
s->lineno = current_lineno;
s->filename = current_file;
get_glob();
}
static int do_eof(void)
{
struct source_stack *s = &source_stack[--source_stack_ptr];
if (source_stack_ptr < 0) {
if (parse_env == 0) {
char *t = getenv("PCMCIA_OPTS");
if (t == NULL) return -1;
parse_env = 1;
source_stack_ptr = 0;
current_file = "PCMCIA_OPTS";
current_lineno = 1;
yy_scan_string(t);
return 0;
} else
return -1;
}
fclose(s->file);
free(current_file);
yy_delete_buffer(YY_CURRENT_BUFFER);
if (get_glob() != 0) {
yy_switch_to_buffer(s->buffer);
current_lineno = s->lineno;
current_file = s->filename;
}
return 0;
}
/*======================================================================
The main entry point... returns -1 if the file can't be accessed.
======================================================================*/
int parse_configfile(char *fn)
{
FILE *f;
f = fopen(fn, "r");
if (!f) {
syslog(LOG_INFO, "could not open '%s': %m", fn);
return -1;
}
current_lineno = 1;
current_file = fn;
source_stack_ptr = 0;
yyrestart(f);
yyparse();
fclose(f);
return 0;
}