commit 59bd8201dc0f5ed31146ae2c9cff06b89e94cfc8 (tree) parent 17093e1dd89497b76c97a83917f0d7e4513f7f88 Author: fardragon <michaldrozd@protonmail.ch> Date: Thu, 4 Jun 2026 16:24:13 +0000 Restore cmake tests. Merge standalone/cmakedefine and standalone/config_header. Diffstat:
27 files changed, 581 insertions(+), 365 deletions(-)
diff --git a/test/standalone/build.zig.zon b/test/standalone/build.zig.zon @@ -141,9 +141,6 @@ .strip_struct_init = .{ .path = "strip_struct_init", }, - .cmakedefine = .{ - .path = "cmakedefine", - }, .zerolength_check = .{ .path = "zerolength_check", }, diff --git a/test/standalone/cmakedefine/build.zig b/test/standalone/cmakedefine/build.zig @@ -1,104 +0,0 @@ -const std = @import("std"); -const ConfigHeader = std.Build.Step.ConfigHeader; - -pub fn build(b: *std.Build) void { - const config_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("config.h.in") }, - .include_path = "config.h", - }, - .{ - .noval = null, - .trueval = true, - .falseval = false, - .zeroval = 0, - .oneval = 1, - .tenval = 10, - .stringval = "test", - - .boolnoval = {}, - .booltrueval = true, - .boolfalseval = false, - .boolzeroval = 0, - .booloneval = 1, - .booltenval = 10, - .boolstringval = "test", - }, - ); - - const pwd_sh = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("pwd.sh.in") }, - .include_path = "pwd.sh", - }, - .{ .DIR = "${PWD}" }, - ); - - const sigil_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("sigil.h.in") }, - .include_path = "sigil.h", - }, - .{}, - ); - - const stack_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("stack.h.in") }, - .include_path = "stack.h", - }, - .{ - .UNDERSCORE = "_", - .NEST_UNDERSCORE_PROXY = "UNDERSCORE", - .NEST_PROXY = "NEST_UNDERSCORE_PROXY", - }, - ); - - const wrapper_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("wrapper.h.in") }, - .include_path = "wrapper.h", - }, - .{ - .DOLLAR = "$", - .TEXT = "TRAP", - - .STRING = "TEXT", - .STRING_AT = "@STRING@", - .STRING_CURLY = "{STRING}", - .STRING_VAR = "${STRING}", - }, - ); - - const check_exe = b.addExecutable(.{ - .name = "check", - .root_module = b.createModule(.{ - .target = b.graph.host, - .root_source_file = b.path("check.zig"), - }), - }); - - const test_step = b.step("test", "Test it"); - b.default_step = test_step; - test_step.dependOn(addCheck(b, check_exe, config_header)); - test_step.dependOn(addCheck(b, check_exe, pwd_sh)); - test_step.dependOn(addCheck(b, check_exe, sigil_header)); - test_step.dependOn(addCheck(b, check_exe, stack_header)); - test_step.dependOn(addCheck(b, check_exe, wrapper_header)); -} - -fn addCheck( - b: *std.Build, - check_exe: *std.Build.Step.Compile, - ch: *ConfigHeader, -) *std.Build.Step { - // We expect `ch.include_path` to only be a basename to infer where the expected output is. - std.debug.assert(std.fs.path.dirname(ch.include_path) == null); - const expected_path = b.fmt("expected_{s}", .{ch.include_path}); - - const run_check = b.addRunArtifact(check_exe); - run_check.addFileArg(ch.getOutputFile()); - run_check.addFileArg(b.path(expected_path)); - - return &run_check.step; -} diff --git a/test/standalone/cmakedefine/check.zig b/test/standalone/cmakedefine/check.zig @@ -1,26 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -pub fn main(init: std.process.Init) !void { - const arena = init.arena.allocator(); - const io = init.io; - const args = try init.minimal.args.toSlice(arena); - - if (args.len != 3) return error.BadUsage; - const actual_path = args[1]; - const expected_path = args[2]; - - const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024)); - const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024)); - - // The actual output starts with a comment which we should strip out before comparing. - const comment_str = "/* This file was generated by ConfigHeader using the Zig Build System. */\n"; - if (!std.mem.startsWith(u8, actual, comment_str)) { - return error.MissingOrMalformedComment; - } - const actual_without_comment = actual[comment_str.len..]; - - if (builtin.os.tag == .windows) return; // https://codeberg.org/ziglang/zig/issues/30138 - - try std.testing.expectEqualStrings(expected, actual_without_comment); -} diff --git a/test/standalone/cmakedefine/expected_config.h b/test/standalone/cmakedefine/expected_config.h @@ -1,147 +0,0 @@ -// cmakedefine -// undefined -/* #undef noval */ - -// 1 -#define trueval 1 - -// undefined -/* #undef falseval */ - -// undefined -/* #undef zeroval */ - -// 1 -#define oneval 1 - -// 1 -#define tenval 1 - -// 1 -#define stringval 1 - -// whitespace test - #define stringval 1 - #define stringval 1 - - -// cmakedefine01 -// 0 -#define boolnoval 0 - -// 1 -#define booltrueval 1 - -// 0 -#define boolfalseval 0 - -// 0 -#define boolzeroval 0 - -// 1 -#define booloneval 1 - -// 1 -#define booltenval 1 - -// 1 -#define boolstringval 1 - - -// @ substition - -// no substition -// - -// no substition -// - -// no substition -// . - -// 1 -// 1 - -// 0 -// 0 - -// 10 -// 10 - -// 0.1 -// 0.1 - -// 0 -// 0 - -// 1 -// 1 - -// 10 -// 10 - -// 01 -// 01 - -// 0.10 -// 0.10 - -// test -// test - -// testtest -// testtest - -// test.test -// test.test - -// test10 -// test10 - -// no substition -// - -// no substition -// - -// no substition -// . - -// 1 -// 1 - -// 0 -// 0 - -// 10 -// 10 - -// 0.1 -// 0.1 - -// 0 -// 0 - -// 1 -// 1 - -// 10 -// 10 - -// 01 -// 01 - -// 0.10 -// 0.10 - -// test -// test - -// testtest -// testtest - -// test.test -// test.test - -// test10 -// test10 diff --git a/test/standalone/cmakedefine/expected_pwd.sh b/test/standalone/cmakedefine/expected_pwd.sh @@ -1 +0,0 @@ -echo ${PWD} diff --git a/test/standalone/cmakedefine/expected_stack.h b/test/standalone/cmakedefine/expected_stack.h @@ -1,3 +0,0 @@ -#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY - -#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY diff --git a/test/standalone/cmakedefine/expected_wrapper.h b/test/standalone/cmakedefine/expected_wrapper.h @@ -1,30 +0,0 @@ -// becomes TEXT -#define TEXT -#define TEXT - -// becomes `at`TEXT`at` -#define @TEXT@ -#define @TEXT@ - -// becomes TRAP -#define TRAP - -// becomes `dollar sign`{STRING} -#define ${STRING} -#define ${STRING} - -// becomes `dollar sign`{STRING} -#define ${STRING} -#define ${STRING} - -// becomes `dollar sign`{TEXT} -#define ${TEXT} -#define ${TEXT} - -// becomes `at`STRING`at` -#define @STRING@ -#define @STRING@ - -#define \@STRING_VAR\@ -#define \${STRING} -#define $\{STRING_VAR} diff --git a/test/standalone/cmakedefine/sigil.h.in b/test/standalone/cmakedefine/sigil.h.in @@ -1,4 +0,0 @@ -#define AT @ -#define ATAT @@ -#define ATATAT @@@ -#define ATATATAT @@@@ diff --git a/test/standalone/config_header/autoconf_undef/config.h b/test/standalone/config_header/autoconf_undef/config.h @@ -0,0 +1,23 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +/* Some Comment */ + +int foo(); + +/* #undef SOME_NO */ +#define SOME_TRUE 1 +#define SOME_FALSE 0 +#define SOME_ZERO 0 +#define SOME_ONE 1 +#define SOME_TEN 10 +#define SOME_ENUM foo +#define SOME_ENUM_LITERAL test +#define SOME_STRING "test" + +// Used twice +#define SOME_TRUE 1 + +/* #undef PREFIX_SPACE */ +/* #undef PREFIX_TAB */ +/* #undef POSTFIX_SPACE */ +/* #undef POSTFIX_TAB */ +// TODO: unexpected newline is being added here diff --git a/test/standalone/config_header/autoconf_undef/config.h.in b/test/standalone/config_header/autoconf_undef/config.h.in @@ -0,0 +1,22 @@ +/* Some Comment */ + +int foo(); + +#undef SOME_NO +#undef SOME_TRUE +#undef SOME_FALSE +#undef SOME_ZERO +#undef SOME_ONE +#undef SOME_TEN +#undef SOME_ENUM +#undef SOME_ENUM_LITERAL +#undef SOME_STRING + +// Used twice +#undef SOME_TRUE + +#undef PREFIX_SPACE +#undef PREFIX_TAB +#undef POSTFIX_SPACE +#undef POSTFIX_TAB +// TODO: unexpected newline is being added here +\ No newline at end of file diff --git a/test/standalone/config_header/build.zig b/test/standalone/config_header/build.zig @@ -5,7 +5,9 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const config_header = b.addConfigHeader( - .{ .style = .{ .autoconf_undef = b.path("config.h.in") } }, + .{ .style = .{ + .autoconf_undef = b.path("autoconf_undef/config.h.in"), + } }, .{ .SOME_NO = null, .SOME_TRUE = true, @@ -23,8 +25,9 @@ pub fn build(b: *std.Build) void { .POSTFIX_TAB = null, }, ); - - const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ .expected_exact = @embedFile("config.h") }); + const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ + .expected_exact = @embedFile("autoconf_undef/config.h"), + }); const config_header_autoconf_at = b.addConfigHeader( .{ .style = .{ @@ -46,4 +49,137 @@ pub fn build(b: *std.Build) void { test_step.dependOn(&check_config_header.step); test_step.dependOn(&check_config_header_autoconf_at.step); + addCmakeChecks(b, test_step); +} + +fn addCmakeChecks(b: *std.Build, test_step: *std.Build.Step) void { + const config_header = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/config.h.in") }, + .include_path = "config.h", + }, + .{ + .noval = null, + .trueval = true, + .falseval = false, + .zeroval = 0, + .oneval = 1, + .tenval = 10, + .stringval = "test", + + .boolnoval = {}, + .booltrueval = true, + .boolfalseval = false, + .boolzeroval = 0, + .booloneval = 1, + .booltenval = 10, + .boolstringval = "test", + }, + ); + const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/expected_config.h"), + }); + test_step.dependOn(&check_config_header.step); + + const pwd_sh = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/pwd.sh.in") }, + .include_path = "pwd.sh", + }, + .{ .DIR = "${PWD}" }, + ); + const check_pwd_sh = b.addCheckFile(pwd_sh.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/expected_pwd.sh"), + }); + test_step.dependOn(&check_pwd_sh.step); + + const sigil_header = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/sigil.h.in") }, + .include_path = "sigil.h", + }, + .{}, + ); + const check_sigil_header = b.addCheckFile(sigil_header.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/expected_sigil.h"), + }); + test_step.dependOn(&check_sigil_header.step); + + const stack_header = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/stack.h.in") }, + .include_path = "stack.h", + }, + .{ + .UNDERSCORE = "_", + .NEST_UNDERSCORE_PROXY = "UNDERSCORE", + .NEST_PROXY = "NEST_UNDERSCORE_PROXY", + }, + ); + const check_stack_header = b.addCheckFile(stack_header.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/expected_stack.h"), + }); + test_step.dependOn(&check_stack_header.step); + + const wrapper_header = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/wrapper.h.in") }, + .include_path = "wrapper.h", + }, + .{ + .DOLLAR = "$", + .TEXT = "TRAP", + + .STRING = "TEXT", + .STRING_AT = "@STRING@", + .STRING_CURLY = "{STRING}", + .STRING_VAR = "${STRING}", + }, + ); + const check_wrapper_header = b.addCheckFile(wrapper_header.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/expected_wrapper.h"), + }); + test_step.dependOn(&check_wrapper_header.step); + + const config_header_cmake = b.addConfigHeader( + .{ .style = .{ + .cmake = b.path("cmake/cmake.txt.in"), + } }, + .{ + .undef = null, + .defined = {}, + .true = true, + .false = false, + .int = 42, + .ident = "value", + .string = "text", + }, + ); + const check_config_header_cmake = b.addCheckFile(config_header_cmake.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/cmake.txt"), + }); + test_step.dependOn(&check_config_header_cmake.step); + + const config_header_cmake_edge_cases = b.addConfigHeader( + .{ .style = .{ + .cmake = b.path("cmake/cmake_edge_cases.txt.in"), + } }, + .{ + // .at = "@", + // .trueval = true, + .dollar = "$", + .underscore = "_", + .string = "text", + .string_proxy = "string", + .string_at = "@string@", + .string_curly = "{string}", + .string_var = "${string}", + .nest_underscore_proxy = "underscore", + .nest_proxy = "nest_underscore_proxy", + }, + ); + const check_config_header_cmake_edge_cases = b.addCheckFile(config_header_cmake_edge_cases.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/cmake_edge_cases.txt"), + }); + test_step.dependOn(&check_config_header_cmake_edge_cases.step); } diff --git a/test/standalone/config_header/cmake/cmake.txt b/test/standalone/config_header/cmake/cmake.txt @@ -0,0 +1,66 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// empty strings are preserved + +// line with misc content is preserved +no substitution + +// empty @ sigils are preserved +@ +@@ +@@@ +@@@@ + +// simple substitution + + + + +1 +1 +0 +0 +42 +42 +value +value +text +text + +// double packed substitution +texttext +texttext + +// triple packed substitution +text42text +text42text +text42text +text42text + +// double separated substitution +42.42 +42.42 + +// triple separated substitution +42.1.42 +42.1.42 +42.1.42 +42.1.42 + +// misc prefix is preserved +false is 0 +false is 0 + +// misc suffix is preserved +1 is true +1 is true + +// surrounding content is preserved +what is 6*7? 42! +what is 6*7? 42! + +// incomplete key is preserved +@undef +${undef +{undef} +undef@ +undef} diff --git a/test/standalone/config_header/cmake/cmake.txt.in b/test/standalone/config_header/cmake/cmake.txt.in @@ -0,0 +1,65 @@ +// empty strings are preserved + +// line with misc content is preserved +no substitution + +// empty @ sigils are preserved +@ +@@ +@@@ +@@@@ + +// simple substitution +@undef@ +${undef} +@defined@ +${defined} +@true@ +${true} +@false@ +${false} +@int@ +${int} +@ident@ +${ident} +@string@ +${string} + +// double packed substitution +@string@@string@ +${string}${string} + +// triple packed substitution +@string@@int@@string@ +@string@${int}@string@ +${string}@int@${string} +${string}${int}${string} + +// double separated substitution +@int@.@int@ +${int}.${int} + +// triple separated substitution +@int@.@true@.@int@ +@int@.${true}.@int@ +${int}.@true@.${int} +${int}.${true}.${int} + +// misc prefix is preserved +false is @false@ +false is ${false} + +// misc suffix is preserved +@true@ is true +${true} is true + +// surrounding content is preserved +what is 6*7? @int@! +what is 6*7? ${int}! + +// incomplete key is preserved +@undef +${undef +{undef} +undef@ +undef} diff --git a/test/standalone/config_header/cmake/cmake_edge_cases.txt b/test/standalone/config_header/cmake/cmake_edge_cases.txt @@ -0,0 +1,38 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// empty lines are preserved + +// @-substition tests +// @-vars resolved only when they wrap valid characters, otherwise considered literals +@text@ +@text@ + +// at-vars are resolved inside curly-vars +text + +// expanded variables are considered strings after expansion +@string@ +@string@ +${string} +${string} +${string} +${string} +${text} +${text} +${text} + +// nested expanded variables are expanded from the inside out +string +string + +// nested vars are only expanded when curly braces are closed +nest_underscore_proxy +nest_underscore_proxy + +// backslash is an invalid character for @ lookup +\@string\@ + +// backslash is preserved, but doesn't affect $curly-braces variable expansion +\text + +// backslash breaks $curly-braces opening bracket identification +$\{string} diff --git a/test/standalone/config_header/cmake/cmake_edge_cases.txt.in b/test/standalone/config_header/cmake/cmake_edge_cases.txt.in @@ -0,0 +1,37 @@ +// empty lines are preserved + +// @-substition tests +// @-vars resolved only when they wrap valid characters, otherwise considered literals +@@string@@ +@${string}@ + +// at-vars are resolved inside curly-vars +${@string_proxy@} + +// expanded variables are considered strings after expansion +@string_at@ +${string_at} +$@string_curly@ +$${string_curly} +${string_var} +@string_var@ +${dollar}{${string}} +@dollar@{${string}} +@dollar@{@string@} + +// nested expanded variables are expanded from the inside out +${string${underscore}proxy} +${string@underscore@proxy} + +// nested vars are only expanded when curly braces are closed +${nest${underscore}proxy} +${nest${${nest_underscore${underscore}proxy}}proxy} + +// backslash is an invalid character for @ lookup +\@string\@ + +// backslash is preserved, but doesn't affect $curly-braces variable expansion +\${string} + +// backslash breaks $curly-braces opening bracket identification +$\{string} diff --git a/test/standalone/cmakedefine/config.h.in b/test/standalone/config_header/cmake/config.h.in diff --git a/test/standalone/config_header/cmake/expected_config.h b/test/standalone/config_header/cmake/expected_config.h @@ -0,0 +1,148 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// cmakedefine +// undefined +/* #undef noval */ + +// 1 +#define trueval 1 + +// undefined +/* #undef falseval */ + +// undefined +/* #undef zeroval */ + +// 1 +#define oneval 1 + +// 1 +#define tenval 1 + +// 1 +#define stringval 1 + +// whitespace test + #define stringval 1 + #define stringval 1 + + +// cmakedefine01 +// 0 +#define boolnoval 0 + +// 1 +#define booltrueval 1 + +// 0 +#define boolfalseval 0 + +// 0 +#define boolzeroval 0 + +// 1 +#define booloneval 1 + +// 1 +#define booltenval 1 + +// 1 +#define boolstringval 1 + + +// @ substition + +// no substition +// + +// no substition +// + +// no substition +// . + +// 1 +// 1 + +// 0 +// 0 + +// 10 +// 10 + +// 0.1 +// 0.1 + +// 0 +// 0 + +// 1 +// 1 + +// 10 +// 10 + +// 01 +// 01 + +// 0.10 +// 0.10 + +// test +// test + +// testtest +// testtest + +// test.test +// test.test + +// test10 +// test10 + +// no substition +// + +// no substition +// + +// no substition +// . + +// 1 +// 1 + +// 0 +// 0 + +// 10 +// 10 + +// 0.1 +// 0.1 + +// 0 +// 0 + +// 1 +// 1 + +// 10 +// 10 + +// 01 +// 01 + +// 0.10 +// 0.10 + +// test +// test + +// testtest +// testtest + +// test.test +// test.test + +// test10 +// test10 diff --git a/test/standalone/config_header/cmake/expected_pwd.sh b/test/standalone/config_header/cmake/expected_pwd.sh @@ -0,0 +1,2 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +echo ${PWD} diff --git a/test/standalone/config_header/cmake/expected_sigil.h b/test/standalone/config_header/cmake/expected_sigil.h @@ -0,0 +1,5 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +#define AT @ +#define ATAT @@ +#define ATATAT @@@ +#define ATATATAT @@@@ diff --git a/test/standalone/config_header/cmake/expected_stack.h b/test/standalone/config_header/cmake/expected_stack.h @@ -0,0 +1,4 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY + +#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY diff --git a/test/standalone/config_header/cmake/expected_wrapper.h b/test/standalone/config_header/cmake/expected_wrapper.h @@ -0,0 +1,31 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// becomes TEXT +#define TEXT +#define TEXT + +// becomes `at`TEXT`at` +#define @TEXT@ +#define @TEXT@ + +// becomes TRAP +#define TRAP + +// becomes `dollar sign`{STRING} +#define ${STRING} +#define ${STRING} + +// becomes `dollar sign`{STRING} +#define ${STRING} +#define ${STRING} + +// becomes `dollar sign`{TEXT} +#define ${TEXT} +#define ${TEXT} + +// becomes `at`STRING`at` +#define @STRING@ +#define @STRING@ + +#define \@STRING_VAR\@ +#define \${STRING} +#define $\{STRING_VAR} diff --git a/test/standalone/cmakedefine/pwd.sh.in b/test/standalone/config_header/cmake/pwd.sh.in diff --git a/test/standalone/cmakedefine/expected_sigil.h b/test/standalone/config_header/cmake/sigil.h.in diff --git a/test/standalone/cmakedefine/stack.h.in b/test/standalone/config_header/cmake/stack.h.in diff --git a/test/standalone/cmakedefine/wrapper.h.in b/test/standalone/config_header/cmake/wrapper.h.in diff --git a/test/standalone/config_header/config.h b/test/standalone/config_header/config.h @@ -1,23 +0,0 @@ -/* This file was generated by ConfigHeader using the Zig Build System. */ -/* Some Comment */ - -int foo(); - -/* #undef SOME_NO */ -#define SOME_TRUE 1 -#define SOME_FALSE 0 -#define SOME_ZERO 0 -#define SOME_ONE 1 -#define SOME_TEN 10 -#define SOME_ENUM foo -#define SOME_ENUM_LITERAL test -#define SOME_STRING "test" - -// Used twice -#define SOME_TRUE 1 - -/* #undef PREFIX_SPACE */ -/* #undef PREFIX_TAB */ -/* #undef POSTFIX_SPACE */ -/* #undef POSTFIX_TAB */ - diff --git a/test/standalone/config_header/config.h.in b/test/standalone/config_header/config.h.in @@ -1,21 +0,0 @@ -/* Some Comment */ - -int foo(); - -#undef SOME_NO -#undef SOME_TRUE -#undef SOME_FALSE -#undef SOME_ZERO -#undef SOME_ONE -#undef SOME_TEN -#undef SOME_ENUM -#undef SOME_ENUM_LITERAL -#undef SOME_STRING - -// Used twice -#undef SOME_TRUE - -#undef PREFIX_SPACE -#undef PREFIX_TAB -#undef POSTFIX_SPACE -#undef POSTFIX_TAB