%option nostdinit noyywrap never-interactive full ecs
-%option 8bit nodefault perf-report perf-report
-%option noinput
-%x COMMAND HELP STRING PARAM
+%option 8bit nodefault yylineno
+%x COMMAND HELP STRING PARAM ASSIGN_VAL
%{
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
+#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "lkc.h"
+#define YY_DECL static int yylex1(void)
+
#define START_STRSIZE 16
static struct {
int lineno;
} current_pos;
+static int prev_token = T_EOL;
static char *text;
static int text_size, text_asize;
static int last_ts, first_ts;
+static char *expand_token(const char *in, size_t n);
+static void append_expanded_string(const char *in);
static void zconf_endhelp(void);
static void zconf_endfile(void);
{
fprintf(stderr,
"%s:%d:warning: ignoring unsupported character '%c'\n",
- zconf_curname(), zconf_lineno(), chr);
+ current_file->name, yylineno, chr);
}
%}
[ \t]*#.*\n |
[ \t]*\n {
- current_file->lineno++;
return T_EOL;
}
[ \t]*#.*
-
-
-[ \t]+ {
- BEGIN(COMMAND);
-}
-
. {
unput(yytext[0]);
BEGIN(COMMAND);
<COMMAND>{
{n}+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
- BEGIN(PARAM);
current_pos.file = current_file;
- current_pos.lineno = current_file->lineno;
+ current_pos.lineno = yylineno;
if (id && id->flags & TF_COMMAND) {
+ BEGIN(PARAM);
yylval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
yylval.string = text;
- return T_WORD;
+ return T_VARIABLE;
}
+ ({n}|$)+ {
+ /* this token includes at least one '$' */
+ yylval.string = expand_token(yytext, yyleng);
+ if (strlen(yylval.string))
+ return T_VARIABLE;
+ free(yylval.string);
+ }
+ "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
+ ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
+ "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
+ [[:blank:]]+
. warn_ignored_character(*yytext);
\n {
BEGIN(INITIAL);
- current_file->lineno++;
return T_EOL;
}
}
+<ASSIGN_VAL>{
+ [^[:blank:]\n]+.* {
+ alloc_string(yytext, yyleng);
+ yylval.string = text;
+ return T_ASSIGN_VAL;
+ }
+ \n { BEGIN(INITIAL); return T_EOL; }
+ .
+}
+
<PARAM>{
"&&" return T_AND;
"||" return T_OR;
new_string();
BEGIN(STRING);
}
- \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ \n BEGIN(INITIAL); return T_EOL;
({n}|[/.])+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) {
yylval.string = text;
return T_WORD;
}
+ ({n}|[/.$])+ {
+ /* this token includes at least one '$' */
+ yylval.string = expand_token(yytext, yyleng);
+ if (strlen(yylval.string))
+ return T_WORD;
+ free(yylval.string);
+ }
#.* /* comment */
- \\\n current_file->lineno++;
+ \\\n ;
[[:blank:]]+
. warn_ignored_character(*yytext);
- <<EOF>> {
- BEGIN(INITIAL);
- }
}
<STRING>{
- [^'"\\\n]+/\n {
- append_string(yytext, yyleng);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
- [^'"\\\n]+ {
+ "$".* append_expanded_string(yytext);
+ [^$'"\\\n]+ {
append_string(yytext, yyleng);
}
- \\.?/\n {
- append_string(yytext + 1, yyleng - 1);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
\\.? {
append_string(yytext + 1, yyleng - 1);
}
fprintf(stderr,
"%s:%d:warning: multi-line strings not supported\n",
zconf_curname(), zconf_lineno());
- current_file->lineno++;
+ unput('\n');
BEGIN(INITIAL);
- return T_EOL;
+ yylval.string = text;
+ return T_WORD_QUOTE;
}
<<EOF>> {
BEGIN(INITIAL);
+ yylval.string = text;
+ return T_WORD_QUOTE;
}
}
}
}
[ \t]*\n/[^ \t\n] {
- current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
}
[ \t]*\n {
- current_file->lineno++;
append_string("\n", 1);
}
[^ \t\n].* {
}
<<EOF>> {
+ BEGIN(INITIAL);
+
+ if (prev_token != T_EOL && prev_token != T_HELPTEXT)
+ fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
+ current_file->name, yylineno);
+
if (current_file) {
zconf_endfile();
return T_EOL;
}
%%
+
+/* second stage lexer */
+int yylex(void)
+{
+ int token;
+
+repeat:
+ token = yylex1();
+
+ /* Do not pass unneeded T_EOL to the parser. */
+ if ((prev_token == T_EOL || prev_token == T_HELPTEXT) && token == T_EOL)
+ goto repeat;
+
+ prev_token = token;
+
+ return token;
+}
+
+static char *expand_token(const char *in, size_t n)
+{
+ char *out;
+ int c;
+ char c2;
+ const char *rest, *end;
+
+ new_string();
+ append_string(in, n);
+
+ /* get the whole line because we do not know the end of token. */
+ while ((c = input()) != EOF) {
+ if (c == '\n') {
+ unput(c);
+ break;
+ }
+ c2 = c;
+ append_string(&c2, 1);
+ }
+
+ rest = text;
+ out = expand_one_token(&rest);
+
+ /* push back unused characters to the input stream */
+ end = rest + strlen(rest);
+ while (end > rest)
+ unput(*--end);
+
+ free(text);
+
+ return out;
+}
+
+static void append_expanded_string(const char *str)
+{
+ const char *end;
+ char *res;
+
+ str++;
+
+ res = expand_dollar(&str);
+
+ /* push back unused characters to the input stream */
+ end = str + strlen(str);
+ while (end > str)
+ unput(*--end);
+
+ append_string(res, strlen(res));
+
+ free(res);
+}
+
void zconf_starthelp(void)
{
new_string();
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
- current_file->lineno = 1;
+ yylineno = 1;
}
void zconf_nextfile(const char *name)
buf->parent = current_buf;
current_buf = buf;
+ current_file->lineno = yylineno;
file->parent = current_file;
for (iter = current_file; iter; iter = iter->parent) {
}
}
- file->lineno = 1;
+ yylineno = 1;
current_file = file;
}
struct buffer *parent;
current_file = current_file->parent;
+ if (current_file)
+ yylineno = current_file->lineno;
parent = current_buf->parent;
if (parent) {