From ce076814049fa4ad6209c49eec6f3160aaf0d95a Mon Sep 17 00:00:00 2001 From: aet Date: Thu, 20 Nov 2003 14:15:32 +0000 Subject: [PATCH] - Add new hand written replacement for the lex parser by Jamie Honan, not much tested yet. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1618 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/scconf/internal.h | 1 + src/scconf/parse.c | 11 ++- src/scconf/sclex.c | 195 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 src/scconf/sclex.c diff --git a/src/scconf/internal.h b/src/scconf/internal.h index d265a105..e7db8e7c 100644 --- a/src/scconf/internal.h +++ b/src/scconf/internal.h @@ -46,6 +46,7 @@ typedef struct _scconf_parser { unsigned int error:1; unsigned int warnings:1; + char emesg[256]; } scconf_parser; extern int scconf_lex_parse(scconf_parser * parser, const char *filename); diff --git a/src/scconf/parse.c b/src/scconf/parse.c index 270930c1..203f0a1f 100644 --- a/src/scconf/parse.c +++ b/src/scconf/parse.c @@ -53,7 +53,7 @@ static void scconf_parse_error(scconf_parser * parser, const char *error) /* FIXME: save the error somewhere */ parser->error = 1; - fprintf(stderr, "Line %d: %s\n", parser->line, error); + snprintf(parser->emesg, sizeof(parser->emesg), "Line %d: %s\n", parser->line, error); } static void scconf_parse_error_not_expect(scconf_parser * parser, @@ -62,7 +62,7 @@ static void scconf_parse_error_not_expect(scconf_parser * parser, /* FIXME: save the error somewhere */ parser->error = 1; - fprintf(stderr, "Line %d: not expecting '%s'\n", parser->line, token); + snprintf(parser->emesg, sizeof(parser->emesg), "Line %d: not expecting '%s'\n", parser->line, token); } static void scconf_parse_warning_expect(scconf_parser * parser, const char *token) @@ -70,7 +70,8 @@ static void scconf_parse_warning_expect(scconf_parser * parser, const char *toke /* FIXME: save the warnings somewhere */ parser->warnings = 1; - fprintf(stderr, "Line %d: missing '%s', ignoring\n", + snprintf(parser->emesg, sizeof(parser->emesg), + "Line %d: missing '%s', ignoring\n", parser->line, token); } @@ -350,7 +351,9 @@ void scconf_parse_token(scconf_parser * parser, int token_type, const char *toke scconf_parse_reset_state(parser); break; default: - fprintf(stderr, "scconf_parse_token: shouldn't happen\n"); + snprintf(parser->emesg, sizeof(parser->emesg), + "Line %d: bad token ignoring\n", + parser->line); } break; } diff --git a/src/scconf/sclex.c b/src/scconf/sclex.c new file mode 100644 index 00000000..97fe6499 --- /dev/null +++ b/src/scconf/sclex.c @@ -0,0 +1,195 @@ +/* + * $Id$ + * + * Copyright (C) 2003 + * Jamie Honan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include "scconf.h" +#include "internal.h" + +typedef struct { + char *buf; + size_t bufmax; + size_t bufcur; + int saved_char; + const char *saved_string; + FILE *fp; +} BUFHAN; + +static void buf_init(BUFHAN * bp, FILE * fp, const char *saved_string) +{ + bp->fp = fp; + bp->saved_char = 0; + bp->buf = malloc(256); + bp->bufmax = 256; + bp->bufcur = 0; + bp->buf[0] = '\0'; + bp->saved_string = saved_string; +} + +static void buf_addch(BUFHAN * bp, char ch) +{ + if (bp->bufcur >= bp->bufmax) { + bp->bufmax += 256; + bp->buf = realloc(bp->buf, bp->bufmax); + } +#if 0 + printf("pushback %c\n", ch); +#endif + bp->buf[bp->bufcur++] = ch; + bp->buf[bp->bufcur] = '\0'; +} + +static int buf_nextch(BUFHAN * bp) +{ + int saved; + + if (bp->saved_char) { + saved = bp->saved_char; + bp->saved_char = 0; + return saved; + } + if (bp->saved_string) { + if (*(bp->saved_string) == '\0') + return EOF; + saved = (unsigned char) (*(bp->saved_string++)); + return saved; + } else { + saved = fgetc(bp->fp); + return saved; + } +} + +static void buf_finished(BUFHAN * bp) +{ + if (bp->buf) { + free(bp->buf); + bp->buf = NULL; + } +} + +static void buf_eat_till(BUFHAN * bp, char start, char *end) +{ + int i; + + if (start) { + buf_addch(bp, start); + } + while (1) { + i = buf_nextch(bp); + if (i == EOF) + return; + if (strchr(end, i)) { + bp->saved_char = i; + return; + } + buf_addch(bp, (char) i); + } +} + +static void buf_zero(BUFHAN * bp) +{ + bp->bufcur = 0; + bp->buf[0] = '\0'; +} + +static int scconf_lex_engine(scconf_parser * parser, BUFHAN * bp) +{ + int this_char; + + while (1) { + switch (this_char = buf_nextch(bp)) { + case '#': + /* comment till end of line */ + buf_eat_till(bp, '#', "\n"); + scconf_parse_token(parser, TOKEN_TYPE_COMMENT, bp->buf); + buf_zero(bp); + continue; + case '\n': + scconf_parse_token(parser, TOKEN_TYPE_NEWLINE, NULL); + continue; + case ' ': + case '\t': + /* eat up whitespace */ + continue; + case ',': + case '{': + case '}': + case '=': + case ';': + buf_addch(bp, (char) this_char); + scconf_parse_token(parser, TOKEN_TYPE_PUNCT, bp->buf); + buf_zero(bp); + continue; + case '"': + buf_eat_till(bp, (char) this_char, "\"\n"); + buf_addch(bp, (char) buf_nextch(bp)); + scconf_parse_token(parser, TOKEN_TYPE_STRING, bp->buf); + buf_zero(bp); + continue; + case EOF: + break; + default: + buf_eat_till(bp, (char) this_char, ";, \t\n"); + scconf_parse_token(parser, TOKEN_TYPE_STRING, bp->buf); + buf_zero(bp); + continue; + } + break; + } + buf_finished(bp); + return 1; +} + +int scconf_lex_parse(scconf_parser * parser, const char *filename) +{ + FILE *fp; + BUFHAN bhan; + int ret; + + fp = fopen(filename, "r"); + if (!fp) { + parser->error = 1; + snprintf(parser->emesg, sizeof(parser->emesg), + "File %s can't be opened\n", filename); + return -1; + } + buf_init(&bhan, fp, (char *) NULL); + ret = scconf_lex_engine(parser, &bhan); + fclose(fp); + return ret; +} + +int scconf_lex_parse_string(scconf_parser * parser, const char *string) +{ + BUFHAN bhan; + int ret; + + buf_init(&bhan, (FILE *) NULL, string); + ret = scconf_lex_engine(parser, &bhan); + return ret; +}