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
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)
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.
),
"\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) {