1
0
mirror of https://github.com/golang/go synced 2024-11-23 20:00:04 -07:00

cmd/asm: fix handling of nested #if[n]defs

The lexer needs to process all #if[n]defs, even those found when processing is
disabled by a preceding failed conditional, or the first #endif in something
like:

    #ifdef <undefined>
    #ifdef whatever
    #endif
    #endif

terminates the first #ifdef and the second causes an error. And then the
processing of the inner #ifdefs needs to ignore their argument when they are
disabled by an outer failed condition.

Change-Id: Iba259498f1e16042f5b7580b9c000bb0599733d0
Reviewed-on: https://go-review.googlesource.com/14253
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Michael Hudson-Doyle 2015-09-03 22:49:18 +12:00
parent 13e06d89c3
commit eaea5ade2b
2 changed files with 115 additions and 4 deletions

View File

@ -136,10 +136,11 @@ func (in *Input) hash() bool {
in.expectText("expected identifier after '#'") in.expectText("expected identifier after '#'")
} }
if !in.enabled() { if !in.enabled() {
// Can only start including again if we are at #else or #endif. // Can only start including again if we are at #else or #endif but also
// need to keep track of nested #if[n]defs.
// We let #line through because it might affect errors. // We let #line through because it might affect errors.
switch in.Stack.Text() { switch in.Stack.Text() {
case "else", "endif", "line": case "else", "endif", "ifdef", "ifndef", "line":
// Press on. // Press on.
default: default:
return false return false
@ -360,7 +361,9 @@ func (in *Input) collectArgument(macro *Macro) ([]Token, ScanToken) {
func (in *Input) ifdef(truth bool) { func (in *Input) ifdef(truth bool) {
name := in.macroName() name := in.macroName()
in.expectNewline("#if[n]def") in.expectNewline("#if[n]def")
if _, defined := in.macros[name]; !defined { if !in.enabled() {
truth = false
} else if _, defined := in.macros[name]; !defined {
truth = !truth truth = !truth
} }
in.ifdefStack = append(in.ifdefStack, truth) in.ifdefStack = append(in.ifdefStack, truth)
@ -372,7 +375,9 @@ func (in *Input) else_() {
if len(in.ifdefStack) == 0 { if len(in.ifdefStack) == 0 {
in.Error("unmatched #else") in.Error("unmatched #else")
} }
in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1] if len(in.ifdefStack) == 1 || in.ifdefStack[len(in.ifdefStack)-2] {
in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1]
}
} }
// #endif processing. // #endif processing.

View File

@ -120,6 +120,112 @@ var lexTests = []lexTest{
), ),
"\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n", "\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n",
}, },
{
"taken #ifdef",
lines(
"#define A",
"#ifdef A",
"#define B 1234",
"#endif",
"B",
),
"1234.\n",
},
{
"not taken #ifdef",
lines(
"#ifdef A",
"#define B 1234",
"#endif",
"B",
),
"B.\n",
},
{
"taken #ifdef with else",
lines(
"#define A",
"#ifdef A",
"#define B 1234",
"#else",
"#define B 5678",
"#endif",
"B",
),
"1234.\n",
},
{
"not taken #ifdef with else",
lines(
"#ifdef A",
"#define B 1234",
"#else",
"#define B 5678",
"#endif",
"B",
),
"5678.\n",
},
{
"nested taken/taken #ifdef",
lines(
"#define A",
"#define B",
"#ifdef A",
"#ifdef B",
"#define C 1234",
"#else",
"#define C 5678",
"#endif",
"#endif",
"C",
),
"1234.\n",
},
{
"nested taken/not-taken #ifdef",
lines(
"#define A",
"#ifdef A",
"#ifdef B",
"#define C 1234",
"#else",
"#define C 5678",
"#endif",
"#endif",
"C",
),
"5678.\n",
},
{
"nested not-taken/would-be-taken #ifdef",
lines(
"#define B",
"#ifdef A",
"#ifdef B",
"#define C 1234",
"#else",
"#define C 5678",
"#endif",
"#endif",
"C",
),
"C.\n",
},
{
"nested not-taken/not-taken #ifdef",
lines(
"#ifdef A",
"#ifdef B",
"#define C 1234",
"#else",
"#define C 5678",
"#endif",
"#endif",
"C",
),
"C.\n",
},
} }
func TestLex(t *testing.T) { func TestLex(t *testing.T) {