aboutsummaryrefslogtreecommitdiff
path: root/gconf/gconf-lex.l
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-16 01:30:44 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-02-16 01:37:24 +0200
commit5000c56d29cf616c8df80f8ec9a19682769f512e (patch)
treed2cc46fda9e8905bdd2fb81bffdaf3a58898be53 /gconf/gconf-lex.l
parenta72cd5987c404080f18ba40bdc4c06811493ab1c (diff)
downloadwydawca-5000c56d29cf616c8df80f8ec9a19682769f512e.tar.gz
wydawca-5000c56d29cf616c8df80f8ec9a19682769f512e.tar.bz2
Rewrite configuration parser, drop dependency on GSC
* bootstrap: Replaced with a modified version from gnulib. * configure.ac: Bump version to 1.9.90 (--without-preprocessor): New option Require Mailutils 2.0 (AC_CONFIG_FILES): Remove lib, add gconf * gconf/: New directory. Contains general-purpose configuration file parser, distilled from Dico and Mailutils. * src/Makefile.am (wydawca_SOURCES): Add interval.c * src/pp-setup, src/update-2.0.awk: New files. * src/config.c: Full rewrite. * src/exec.c (start_prog): Use getdtablesize unconditionally. * src/mail.c: Keep templates in a hash table. Template references begin with a single @ * src/process.c, src/triplet.c, src/verify.c: Reflect changes to struct directory_pair * src/wydawca.c: Change configuration parsing. * src/wydawca.h (enum access_method_id): New constants (struct directory_pair): Replace four access methods with an array. * Makefile.am (SUBDIRS): Remove lib, add gconf * .gitignore, NEWS, doc/.gitignore, src/.gitignore
Diffstat (limited to 'gconf/gconf-lex.l')
-rw-r--r--gconf/gconf-lex.l479
1 files changed, 479 insertions, 0 deletions
diff --git a/gconf/gconf-lex.l b/gconf/gconf-lex.l
new file mode 100644
index 0000000..1cdaada
--- /dev/null
+++ b/gconf/gconf-lex.l
@@ -0,0 +1,479 @@
+/* gconf - General purpose configuration parser. -*- c -*- */
+%{
+/* gconf - General purpose configuration parser.
+ Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <gconf.h>
+#include <gconf-gram.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include <obstack.h>
+#include <xalloc.h>
+#include <argcv.h>
+
+#if ENABLE_NLS
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#else
+# define _(msgid) msgid
+#endif
+
+static char *multiline_delimiter;
+static size_t multiline_delimiter_len;
+static int multiline_unescape; /* Unescape here-document contents */
+static int (*char_to_strip) (char); /* Strip matching characters of each
+ here-document line */
+
+gconf_locus_t gconf_current_locus; /* Input file location */
+/* Line correction. Equals to the number of #line directives inserted into
+ the input by the preprocessor instance. The external preprocessor, if
+ any, counts these as input lines and therefore the line numbers in *its*
+ #line directives are offset by the value of XLINES.
+
+ Uff, running two preprocessors is confusing...
+*/
+static size_t xlines;
+static struct obstack stk;
+
+static void multiline_begin (char *);
+static void multiline_add (char *);
+static char *multiline_strip_tabs (char *text);
+static void line_add_unescape_last (char *text, size_t len);
+static int ident (void);
+static int isemptystr (int off);
+
+static void parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines);
+static void parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines);
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ do \
+ { \
+ if (gconf_preprocessor) \
+ result = fread (buf, 1, max_size, yyin); \
+ else \
+ result = gconf_preproc_fill_buffer(buf, max_size); \
+ } \
+ while (0)
+
+%}
+
+
+%x COMMENT ML STR
+
+WS [ \t\f][ \t\f]*
+ID [a-zA-Z_][a-zA-Z_0-9-]+
+P [1-9][0-9]*
+
+%%
+ /* C-style comments */
+"/*" BEGIN (COMMENT);
+<COMMENT>[^*\n]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
+<COMMENT>\n ++gconf_current_locus.line;
+<COMMENT>"*"+"/" BEGIN (INITIAL);
+ /* Line directive */
+^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { parse_line_cpp (yytext,
+ &gconf_current_locus,
+ &xlines); }
+^[ \t]*#[ \t]*line[ \t].*\n { parse_line (yytext, &gconf_current_locus,
+ &xlines); }
+ /* End-of-line comments */
+#.*\n { gconf_current_locus.line++; }
+#.* /* end-of-file comment */;
+"//".*\n { gconf_current_locus.line++; }
+"//".* /* end-of-file comment */;
+ /* Identifiers */
+<INITIAL>{ID} return ident ();
+ /* Strings */
+[a-zA-Z0-9_\.\*/:@-]+ { gconf_line_begin ();
+ gconf_line_add (yytext, yyleng);
+ yylval.string = gconf_line_finish ();
+ return STRING; }
+ /* Quoted strings */
+\"[^\\"\n]*\" { gconf_line_begin ();
+ gconf_line_add (yytext + 1, yyleng - 2);
+ yylval.string = gconf_line_finish ();
+ return QSTRING; }
+\"[^\\"\n]*\\. |
+\"[^\\"\n]*\\\n { BEGIN (STR);
+ gconf_line_begin ();
+ line_add_unescape_last (yytext + 1, yyleng - 1); }
+<STR>[^\\"\n]*\\. |
+<STR>\"[^\\"\n]*\\\n { line_add_unescape_last (yytext, yyleng); }
+<STR>[^\\"\n]*\" { BEGIN(INITIAL);
+ if (yyleng > 1)
+ gconf_line_add (yytext, yyleng - 1);
+ yylval.string = gconf_line_finish ();
+ return QSTRING; }
+ /* Multiline strings */
+"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
+"<<"(-" "?)?\\?{ID}[ \t]*"//".*\n |
+"<<"(-" "?)?\\?{ID}[ \t]*\n |
+"<<"(-" "?)?\"{ID}\"[ \t]*#.*\n |
+"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n |
+"<<"(-" "?)?\"{ID}\"[ \t]*\n {
+ BEGIN (ML);
+ multiline_begin (yytext+2);
+ gconf_current_locus.line++; }
+ /* Ignore m4 line statements */
+<ML>^"#line ".*\n { gconf_current_locus.line++; }
+<ML>.*\n { char *p = multiline_strip_tabs (yytext);
+
+ if (!strncmp (p, multiline_delimiter, multiline_delimiter_len)
+ && isemptystr (p + multiline_delimiter_len - yytext))
+ {
+ free (multiline_delimiter);
+ multiline_delimiter = NULL;
+ BEGIN (INITIAL);
+ yylval.string = gconf_line_finish ();
+ return MSTRING;
+ }
+ gconf_current_locus.line++;
+ multiline_add (p); }
+{WS} ;
+ /* Other tokens */
+\n { gconf_current_locus.line++; }
+[,;{}()] return yytext[0];
+. { if (isascii (yytext[0]) && isprint (yytext[0]))
+ gconf_error (&gconf_current_locus, 0, _("stray character %c"), yytext[0]);
+ else
+ gconf_error (&gconf_current_locus, 0, _("stray character \\%03o"),
+ (unsigned char) yytext[0]); }
+%%
+
+pid_t gconf_preproc_pid;
+
+int
+yywrap ()
+{
+ if (yyin)
+ gconf_preproc_extrn_shutdown (gconf_preproc_pid);
+ else
+ gconf_preproc_done ();
+ gconf_current_locus.file = NULL;
+ return 1;
+}
+
+int
+gconf_lex_begin (const char *name)
+{
+ if (yy_flex_debug > 0)
+ yy_flex_debug = 0;
+ obstack_init (&stk);
+ if (gconf_preprocessor)
+ {
+ int fd;
+
+ fd = open (name, O_RDONLY);
+ if (fd == -1)
+ {
+ gconf_error (NULL, errno, _("Cannot open `%s'"), name);
+ return 1;
+ }
+ close (fd);
+
+ yyin = gconf_preproc_extrn_start (name, &gconf_preproc_pid);
+ if (!yyin)
+ {
+ gconf_error (NULL, errno,
+ _("Unable to start external preprocessor `%s'"),
+ gconf_preprocessor);
+ return 1;
+ }
+ }
+ else
+ return gconf_preproc_init (name);
+
+ return 0;
+}
+
+void
+gconf_lex_end ()
+{
+}
+
+static int
+isemptystr (int off)
+{
+ for (; yytext[off] && isspace (yytext[off]); off++)
+ ;
+ if (yytext[off] == ';')
+ {
+ int i;
+ for (i = off + 1; yytext[i]; i++)
+ if (!isspace (yytext[i]))
+ return 0;
+ yyless (off);
+ return 1;
+ }
+ return yytext[off] == 0;
+}
+
+char *
+multiline_strip_tabs (char *text)
+{
+ if (char_to_strip)
+ for (; *text && char_to_strip (*text); text++)
+ ;
+ return text;
+}
+
+static int
+unquote_char (int c)
+{
+ static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
+
+ char *p;
+
+ for (p = quote_transtab; *p; p += 2)
+ {
+ if (*p == c)
+ return p[1];
+ }
+ return -1;
+}
+
+static void
+unescape_to_obstack (int c)
+{
+ if (c != '\n')
+ {
+ int t = unquote_char (c);
+ if (t != -1)
+ obstack_1grow (&stk, t);
+ else
+ {
+ gconf_warning(&gconf_current_locus, 0,
+ _("unknown escape sequence '\\%c'"),
+ c);
+ obstack_1grow (&stk, c);
+ }
+ }
+}
+
+void
+gconf_line_add (const char *text, size_t len)
+{
+ obstack_grow (&stk, text, len);
+}
+
+/* Same, but unescapes the last character from yytext */
+static void
+line_add_unescape_last (char *text, size_t len)
+{
+ obstack_grow (&stk, text, len - 2);
+ unescape_to_obstack (text[len - 1]);
+}
+
+static void
+multiline_add (char *s)
+{
+ if (multiline_unescape)
+ {
+ for (; *s; s++)
+ {
+ if (*s == '\\')
+ {
+ unescape_to_obstack (s[1]);
+ ++s;
+ }
+ else
+ obstack_1grow (&stk, *s);
+ }
+ }
+ else
+ gconf_line_add (s, strlen (s));
+}
+
+void
+gconf_line_begin ()
+{
+ /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */
+}
+
+static int
+is_tab (char c)
+{
+ return c == '\t';
+}
+
+static int
+is_ws (char c)
+{
+ return c == '\t' || c == ' ';
+}
+
+void
+multiline_begin (char *p)
+{
+ if (*p == '-')
+ {
+ if (*++p == ' ')
+ {
+ char_to_strip = is_ws;
+ p++;
+ }
+ else
+ char_to_strip = is_tab;
+ }
+ else
+ char_to_strip = NULL;
+ if (*p == '\\')
+ {
+ p++;
+ multiline_unescape = 0;
+ }
+ else if (*p == '"')
+ {
+ char *q;
+
+ p++;
+ multiline_unescape = 0;
+ q = strchr (p, '"');
+ multiline_delimiter_len = q - p;
+ }
+ else
+ {
+ multiline_delimiter_len = strcspn (p, " \t");
+ multiline_unescape = 1;
+ }
+
+ /* Remove trailing newline */
+ multiline_delimiter_len--;
+ multiline_delimiter = xmalloc (multiline_delimiter_len + 1);
+ memcpy (multiline_delimiter, p, multiline_delimiter_len);
+ multiline_delimiter[multiline_delimiter_len] = 0;
+ gconf_line_begin ();
+}
+
+char *
+gconf_line_finish ()
+{
+ obstack_1grow (&stk, 0);
+ return obstack_finish (&stk);
+}
+
+static int
+ident ()
+{
+ char *p;
+
+ for (p = yytext; *p && isspace (*p); p++)
+ ;
+ obstack_grow (&stk, p, strlen (p));
+ obstack_1grow (&stk, 0);
+ yylval.string = obstack_finish (&stk);
+ return IDENT;
+}
+
+void
+gconf_lex_trace (int n)
+{
+ yy_flex_debug = -n;
+}
+
+gconf_value_t *
+gconf_value_dup(gconf_value_t *input)
+{
+ gconf_value_t *ptr = obstack_alloc (&stk, sizeof (*ptr));
+ *ptr = *input;
+ return ptr;
+}
+
+
+static int
+assign_locus (gconf_locus_t *ploc, char *name, char *line, size_t *pxlines)
+{
+ char *p;
+
+ if (name)
+ {
+ if (pxlines && (!ploc->file || strcmp(name, ploc->file)))
+ *pxlines = 0;
+ ploc->file = gconf_install_text (name);
+ }
+ ploc->line = strtoul (line, &p, 10) - (pxlines ? *pxlines : 0);
+ return *p != 0;
+}
+
+static void
+parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines)
+{
+ int rc = 1;
+ int argc;
+ char **argv;
+
+ while (*text && isspace (*text))
+ text++;
+ text++;
+
+ if (argcv_get (text, "", NULL, &argc, &argv))
+ gconf_error (ploc, 0, _("cannot parse #line line"));
+ else
+ {
+ if (argc == 2)
+ rc = assign_locus (ploc, NULL, argv[1], pxlines);
+ else if (argc == 3)
+ rc = assign_locus (ploc, argv[2], argv[1], pxlines);
+ else if (argc == 4)
+ {
+ rc = assign_locus (ploc, argv[2], argv[1], 0);
+ if (rc == 0)
+ {
+ char *p;
+ unsigned long x = strtoul (argv[3], &p, 10);
+ rc = *p != 0;
+ if (rc == 0)
+ *pxlines = x;
+ }
+ }
+ else
+ gconf_error (ploc, 0, _("invalid #line statement"));
+
+ if (rc)
+ gconf_error (ploc, 0, _("malformed #line statement"));
+ }
+ argcv_free (argc, argv);
+}
+
+static void
+parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines)
+{
+ int argc;
+ char **argv;
+
+ if (argcv_get (text, "", NULL, &argc, &argv))
+ gconf_error (ploc, 0, _("cannot parse #line line"));
+ else if (argc < 3)
+ gconf_error (ploc, 0, _("invalid #line statement"));
+ else
+ {
+ if (assign_locus (ploc, argv[2], argv[1], pxlines))
+ gconf_error (ploc, 0, _("malformed #line statement"));
+ }
+ argcv_free (argc, argv);
+}
+

Return to:

Send suggestions and report system problems to the System administrator.