use a different approach to the $"…" problem:

take the states that may open a string, only permit them by virtue of
moving the code out of Subst: to handle $+" and $+' at all; then add
S[Q]BRACE to that

side benefits:
• clearer, cleaner code flow
• smaller code
• better “business logic” ☺
• defuses one heavy use of duff’s device a bit
This commit is contained in:
tg 2013-02-17 06:05:02 +00:00
parent b684a7c6bd
commit e21a2166f7
1 changed files with 24 additions and 30 deletions

54
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.180 2013/02/17 05:40:16 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.181 2013/02/17 06:05:02 tg Exp $");
/*
* states while lexing word
@ -348,6 +348,22 @@ yylex(int cf)
*wp++ = OQUOTE;
PUSH_STATE(SDQUOTE);
break;
case '$':
/*
* processing of dollar sign belongs into
* Subst, except for those which can open
* a string: $'' and $""
*/
subst_dollar_ex:
c = getsc();
switch (c) {
case '"':
goto open_sdquote;
case '\'':
goto open_sequote;
default:
goto SubstS;
}
default:
goto Subst;
}
@ -382,8 +398,8 @@ yylex(int cf)
}
break;
case '$':
subst_dollar:
c = getsc();
SubstS:
if (c == '(') /*)*/ {
c = getsc();
if (c == '(') /*)*/ {
@ -504,30 +520,9 @@ yylex(int cf)
*wp++ = '\0';
*wp++ = CSUBST;
*wp++ = 'X';
} else if (c == '\'' || c == '"') {
switch (state) {
/*
* states in which $''/$"" are
* invalid; still not too sure about
* which must be included/excluded
*/
case SWORD:
case SDQUOTE:
goto DNQUOTE;
}
if (c == '"')
goto DEQUOTE;
/* c == '\'' */
*wp++ = OQUOTE;
ignore_backslash_newline++;
PUSH_STATE(SEQUOTE);
statep->ls_bool = false;
break;
} else {
DNQUOTE:
*wp++ = CHAR;
*wp++ = '$';
DEQUOTE:
ungetsc(c);
}
break;
@ -705,7 +700,7 @@ yylex(int cf)
if (c == '"')
goto open_sdquote;
else if (c == '$')
goto subst_dollar;
goto subst_dollar_ex;
else if (c == '`')
goto subst_gravis;
else if (c != /*{*/ '}')
@ -816,16 +811,15 @@ yylex(int cf)
*wp++ = c;
}
break;
case '\'':
goto open_ssquote;
case '$':
if ((c2 = getsc()) == '\'') {
PUSH_STATE(SEQUOTE);
statep->ls_bool = false;
if (0)
/* FALLTHROUGH */
case '\'':
PUSH_STATE(SSQUOTE);
open_sequote:
*wp++ = OQUOTE;
ignore_backslash_newline++;
PUSH_STATE(SEQUOTE);
statep->ls_bool = false;
break;
} else if (c2 == '"') {
/* FALLTHROUGH */