version 1.9, 2015/07/22 20:15:24 |
version 1.10, 2015/07/24 06:36:42 |
|
|
}; |
}; |
const char *str; |
const char *str; |
}; |
}; |
|
int lineno; |
|
int colno; |
} yystype; |
} yystype; |
#define YYSTYPE yystype |
#define YYSTYPE yystype |
|
|
|
|
|
|
struct rule **rules; |
struct rule **rules; |
int nrules, maxrules; |
int nrules, maxrules; |
|
int parse_errors = 0; |
|
|
void yyerror(const char *, ...); |
void yyerror(const char *, ...); |
int yylex(void); |
int yylex(void); |
|
|
grammar: /* empty */ |
grammar: /* empty */ |
| grammar '\n' |
| grammar '\n' |
| grammar rule '\n' |
| grammar rule '\n' |
|
| error '\n' |
; |
; |
|
|
rule: action ident target cmd { |
rule: action ident target cmd { |
|
|
$$.options = $1.options | $2.options; |
$$.options = $1.options | $2.options; |
$$.envlist = $1.envlist; |
$$.envlist = $1.envlist; |
if ($2.envlist) { |
if ($2.envlist) { |
if ($$.envlist) |
if ($$.envlist) { |
errx(1, "can't have two keepenv sections"); |
yyerror("can't have two keepenv sections"); |
else |
YYERROR; |
|
} else |
$$.envlist = $2.envlist; |
$$.envlist = $2.envlist; |
} |
} |
} ; |
} ; |
|
|
va_list va; |
va_list va; |
|
|
va_start(va, fmt); |
va_start(va, fmt); |
verrx(1, fmt, va); |
vfprintf(stderr, fmt, va); |
|
va_end(va); |
|
fprintf(stderr, " at line %d\n", yylval.lineno + 1); |
|
parse_errors++; |
} |
} |
|
|
struct keyword { |
struct keyword { |
|
|
int |
int |
yylex(void) |
yylex(void) |
{ |
{ |
static int colno = 1, lineno = 1; |
|
|
|
char buf[1024], *ebuf, *p, *str; |
char buf[1024], *ebuf, *p, *str; |
int i, c, quotes = 0, escape = 0, qpos = 0, nonkw = 0; |
int i, c, quotes = 0, escape = 0, qpos = -1, nonkw = 0; |
|
|
p = buf; |
p = buf; |
ebuf = buf + sizeof(buf); |
ebuf = buf + sizeof(buf); |
|
|
repeat: |
repeat: |
/* skip whitespace first */ |
/* skip whitespace first */ |
for (c = getc(yyfp); c == ' ' || c == '\t'; c = getc(yyfp)) |
for (c = getc(yyfp); c == ' ' || c == '\t'; c = getc(yyfp)) |
colno++; |
yylval.colno++; |
|
|
/* check for special one-character constructions */ |
/* check for special one-character constructions */ |
switch (c) { |
switch (c) { |
case '\n': |
case '\n': |
colno = 1; |
yylval.colno = 0; |
lineno++; |
yylval.lineno++; |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case '{': |
case '{': |
case '}': |
case '}': |
|
|
while ((c = getc(yyfp)) != '\n') |
while ((c = getc(yyfp)) != '\n') |
if (c == EOF) |
if (c == EOF) |
return 0; |
return 0; |
colno = 1; |
yylval.colno = 0; |
lineno++; |
yylval.lineno++; |
return c; |
return c; |
case EOF: |
case EOF: |
return 0; |
return 0; |
} |
} |
|
|
/* parsing next word */ |
/* parsing next word */ |
for (;; c = getc(yyfp), colno++) { |
for (;; c = getc(yyfp), yylval.colno++) { |
switch (c) { |
switch (c) { |
case '\0': |
case '\0': |
yyerror("unallowed character NUL at " |
yyerror("unallowed character NUL in column %d", yylval.colno + 1); |
"line %d, column %d", lineno, colno); |
|
escape = 0; |
escape = 0; |
continue; |
continue; |
case '\\': |
case '\\': |
|
|
break; |
break; |
case '\n': |
case '\n': |
if (quotes) |
if (quotes) |
yyerror("unterminated quotes at line %d, column %d", |
yyerror("unterminated quotes in column %d", |
lineno, qpos); |
qpos + 1); |
if (escape) { |
if (escape) { |
nonkw = 1; |
nonkw = 1; |
escape = 0; |
escape = 0; |
|
|
goto eow; |
goto eow; |
case EOF: |
case EOF: |
if (escape) |
if (escape) |
yyerror("unterminated escape at line %d, column %d", |
yyerror("unterminated escape in column %d", |
lineno, colno - 1); |
yylval.colno); |
if (quotes) |
if (quotes) |
yyerror("unterminated quotes at line %d, column %d", |
yyerror("unterminated quotes in column %d", |
lineno, qpos); |
qpos + 1); |
|
goto eow; |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case '{': |
case '{': |
case '}': |
case '}': |
|
|
quotes = !quotes; |
quotes = !quotes; |
if (quotes) { |
if (quotes) { |
nonkw = 1; |
nonkw = 1; |
qpos = colno; |
qpos = yylval.colno; |
} |
} |
continue; |
continue; |
} |
} |
} |
} |
*p++ = c; |
*p++ = c; |
if (p == ebuf) |
if (p == ebuf) |
yyerror("too long line %d", lineno); |
yyerror("too long line"); |
escape = 0; |
escape = 0; |
} |
} |
|
|
|
|
*/ |
*/ |
if (c == EOF) |
if (c == EOF) |
return 0; |
return 0; |
else if (!qpos) /* accept, e.g., empty args: cmd foo args "" */ |
else if (qpos == -1) /* accept, e.g., empty args: cmd foo args "" */ |
goto repeat; |
goto repeat; |
} |
} |
if (!nonkw) { |
if (!nonkw) { |