%{ /* MeTA1 configuration lexer for Pies. Copyright (C) 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, 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 . */ /* This file implements a lexical analyzer for MeTA1 main configuration file. */ #include "pies.h" #include "meta1gram.h" #include "meta1lex.h" grecs_locus_t meta1_locus; size_t meta1_error_count; struct obstack meta1_stk; int meta1_stk_init; char *meta1_queue_dir; #define yylval meta1lval %} %x COMMENT STR X [0-9a-fA-F] %% /* C-style comments */ "/*" BEGIN (COMMENT); [^*\n]* /* eat anything that's not a '*' */ "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ \n ++meta1_locus.line; "*"+"/" BEGIN (INITIAL); /* End-of-line comments */ #.*\n { meta1_locus.line++; } #.* /* end-of-file comment */; /* Number */ 0[xX]{X}+ | 0[0-7]+ | [1-9][0-9]+ { meta1_line_begin (); meta1_line_add (yytext, yyleng); yylval.string = meta1_line_finish (); return META1_NUMBER; } /* Identifiers (unquoted strings) */ [a-zA-Z0-9_\./:\*-]+ { meta1_line_begin (); meta1_line_add (yytext, yyleng); yylval.string = meta1_line_finish (); return META1_IDENT; } /* Quoted strings */ \"[^\\"\n]*\" { meta1_line_begin (); meta1_line_add (yytext + 1, yyleng - 2); yylval.string = meta1_line_finish (); return META1_STRING; } \"[^\\"\n]*\\x{X}{1,2} { BEGIN(STR); meta1_line_begin (); meta1_line_add_unescape_hex (yytext + 1, yyleng - 1); } \"[^\\"\n]*\\. { BEGIN(STR); meta1_line_begin (); meta1_line_add_unescape_last (yytext + 1, yyleng - 1); } [^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); } [^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); } [^\\"\n]*\" { BEGIN (INITIAL); if (yyleng > 1) meta1_line_add (yytext, yyleng - 1); yylval.string = meta1_line_finish (); return META1_STRING; } [^\\"\n]*\n { BEGIN (INITIAL); meta1_parse_error (_("newline in a string")); meta1_line_add (yytext, yyleng - 1); yylval.string = meta1_line_finish (); return META1_STRING; } /* Other tokens */ [ \t\f][ \t\f]* ; \n { meta1_locus.line++; } [,;{}=] return yytext[0]; . { if (isascii (yytext[0]) && isprint (yytext[0])) meta1_parse_error (_("stray character %c"), yytext[0]); else meta1_parse_error (_("stray character \\%03o"), (unsigned char) yytext[0]); } %% int yywrap () { return 1; } void meta1_line_add (const char *text, size_t len) { obstack_grow (&meta1_stk, text, len); } static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; static int unescape_char (int c) { char *p; for (p = quote_transtab; *p; p += 2) { if (*p == c) return p[1]; } return c; } static void unescape_to_line (int c) { char t; if (c == 'v') t = '\v'; else { t = unescape_char (c); if (t == c && t != '\\' && t != '\"') meta1_parse_error (_("unknown escape sequence '\\%c'"), c); } obstack_1grow (&meta1_stk, t); } void meta1_line_add_unescape_last (const char *text, size_t len) { obstack_grow (&meta1_stk, text, len - 2); unescape_to_line (text[len - 1]); } void meta1_line_add_unescape_hex (const char *text, size_t len) { for (; text[len-1] != 'x' && len > 0; len--) ; obstack_grow (&meta1_stk, text, len - 2); obstack_1grow (&meta1_stk, (char) strtoul (text + len, NULL, 16)); } void meta1_line_begin () { if (!meta1_stk_init) { obstack_init (&meta1_stk); meta1_stk_init = 1; } } char * meta1_line_finish () { obstack_1grow (&meta1_stk, 0); return obstack_finish (&meta1_stk); } char * meta1_string (const char *str, size_t len) { meta1_line_begin (); meta1_line_add (str, len); return meta1_line_finish (); } void meta1_parse_error (const char *fmt, ...) { va_list ap; logmsg_printf (LOG_ERR, "%s:%lu: ", meta1_locus.file, (unsigned long) meta1_locus.line); va_start (ap, fmt); logmsg_vprintf (LOG_ERR, fmt, ap); va_end (ap); logmsg_printf (LOG_ERR, "\n"); meta1_error_count++; } void meta1_lexer_set_debug () { char *p = getenv ("META1_DEBUG_LEX"); yy_flex_debug = p && (*p - '0') > 0; } /* Parse MeTA1 configuration file `name'. Populate `meta1_parse_tree' with the parse tree. */ int meta1_config_parse (const char *name) { int rc; FILE *fp; fp = fopen (name, "r"); if (!fp) { logmsg (LOG_ERR, _("%s: cannot open file: %s"), name, strerror (errno)); return 1; } meta1_locus.file = meta1_string (name, strlen (name)); meta1_locus.line = 1; meta1_lexer_set_debug (); meta1_parser_set_debug (); yyrestart (fp); rc = meta1parse (); fclose (fp); if (meta1_error_count) rc = 1; return rc; }