Commit eaea5ade authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

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/14253Reviewed-by: 's avatarRob Pike <r@golang.org>
parent 13e06d89
......@@ -136,10 +136,11 @@ func (in *Input) hash() bool {
in.expectText("expected identifier after '#'")
}
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.
switch in.Stack.Text() {
case "else", "endif", "line":
case "else", "endif", "ifdef", "ifndef", "line":
// Press on.
default:
return false
......@@ -360,7 +361,9 @@ func (in *Input) collectArgument(macro *Macro) ([]Token, ScanToken) {
func (in *Input) ifdef(truth bool) {
name := in.macroName()
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
}
in.ifdefStack = append(in.ifdefStack, truth)
......@@ -372,7 +375,9 @@ func (in *Input) else_() {
if len(in.ifdefStack) == 0 {
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.
......
......@@ -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",
},
{
"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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment