├── .clang-format ├── .gitattributes ├── .gitignore ├── .vs ├── tpp.sln ├── tpp.vcxproj ├── tpp.vcxproj.filters └── tpp.vcxproj.user ├── LICENSE ├── README.md ├── make.sh ├── samples ├── advanced │ ├── Makefile │ ├── README.md │ ├── input.c │ ├── main.c │ ├── my-custom-tpp-defs.h │ ├── mywrapper-for-tpp.c │ └── mywrapper-for-tpp.h └── simple │ ├── Makefile │ ├── README.md │ ├── input.c │ └── main.c ├── src ├── frontend.c ├── tpp-backwards-compatibility.h ├── tpp-defs.inl ├── tpp-gcc-defs.inl ├── tpp.c └── tpp.h └── test ├── _runall.sh ├── arguments_as_macro.h ├── clone_linefeed.h ├── count_tokens.h ├── cxx_comments_in_macro.h ├── define_directives.h ├── directives_in_macros.h ├── directives_start_of_line.h ├── double_counter.h ├── glue.h ├── has_include.h ├── include ├── def.h └── test.h ├── include_path.h ├── inner └── test.h ├── macro-argument-whitespace.h ├── macro_call_conv.h ├── macro_escape_lf.h ├── null_directive.h ├── pound_xclaim.h ├── prevent_macro_expansion.h ├── push_pop_macro.h ├── quotes_in_error.h ├── self_redef.h ├── stdc_6.10.3.5_5.h ├── stdc_6.10.3.5_6.h ├── stdc_6.10.3.5_7.h ├── stdc_6.10.3.5_9.h ├── stdc_6.10.3_5+6.h ├── strings_in_expressions.h ├── tpp_exec.h ├── traditional_macros.h ├── undef_current_macro.h ├── undef_macro_cexpr.h ├── user_error.h ├── varargs_empty.h ├── varargs_named.h ├── varargs_va_comma.h ├── varargs_va_nargs.h └── varargs_va_opt.h /.clang-format: -------------------------------------------------------------------------------- 1 | 2 | # Find stuff that this format defines incorrectly: 3 | # REPLACE: "(?<=(|un)likely) \(", "(" 4 | # - Spaces after [un]likely (caused by 'SpaceBeforeParens: ControlStatements'), 5 | # though with LLVM9, the produced formatting was waaay worse than this :) 6 | # REPLACE: "}[ \t]*\n[ \t]+(?=\bEXCEPT\b)" --> "} " 7 | # - EXCEPT on a new line 8 | # FIND: "\t/\*[^\n]*\n [ ]+\*" 9 | # - Block-comments that need to be re-aligned 10 | # 11 | # Really though: there needs to be a simple directive to perform 12 | # finalizing regex-based text replacement on otherwise already 13 | # formatted source code: 14 | # >> RegexReplacements: 15 | # >> - Regex: '(?<=(|un)likely) \(' 16 | # >> Replacement: '(' 17 | # >> - Regex: '}[ \t]*\n[ \t]+(?=\bEXCEPT\b)' 18 | # >> Replacement: '} ' 19 | 20 | AccessModifierOffset: -4 21 | AlignAfterOpenBracket: Align 22 | AlignConsecutiveAssignments: true 23 | # AlignConsecutiveBitFields: true 24 | AlignConsecutiveDeclarations: false 25 | AlignConsecutiveMacros: true 26 | AlignEscapedNewlines: Left 27 | AlignOperands: true 28 | AlignTrailingComments: true 29 | AllowAllArgumentsOnNextLine: false 30 | AllowAllConstructorInitializersOnNextLine: false 31 | AllowAllParametersOfDeclarationOnNextLine: false 32 | AllowShortBlocksOnASingleLine: false 33 | AllowShortCaseLabelsOnASingleLine: true 34 | # AllowShortEnumsOnASingleLine: false 35 | AllowShortFunctionsOnASingleLine: Empty 36 | AllowShortIfStatementsOnASingleLine: Never 37 | AllowShortLambdasOnASingleLine: All 38 | AllowShortLoopsOnASingleLine: false 39 | AlwaysBreakAfterReturnType: None 40 | AlwaysBreakBeforeMultilineStrings: false 41 | AlwaysBreakTemplateDeclarations: No 42 | BinPackArguments: true 43 | BinPackParameters: true 44 | ExperimentalAutoDetectBinPacking: true 45 | BraceWrapping: 46 | AfterCaseLabel: false 47 | AfterClass: false 48 | AfterControlStatement: false 49 | AfterEnum: false 50 | AfterFunction: false 51 | AfterNamespace: false 52 | AfterObjCDeclaration: false 53 | AfterStruct: false 54 | AfterUnion: false 55 | AfterExternBlock: false 56 | BeforeCatch: false 57 | BeforeElse: false 58 | # BeforeLambdaBody: false 59 | # BeforeWhile: false 60 | IndentBraces: false 61 | SplitEmptyFunction: false 62 | SplitEmptyRecord: false 63 | SplitEmptyNamespace: false 64 | BreakAfterJavaFieldAnnotations: true 65 | BreakBeforeBinaryOperators: None 66 | BreakBeforeBraces: Custom 67 | BreakBeforeTernaryOperators: true 68 | BreakConstructorInitializers: BeforeComma 69 | BreakInheritanceList: BeforeComma 70 | BreakStringLiterals: false 71 | ColumnLimit: 0 72 | CommentPragmas: '^\[\[\[' 73 | CompactNamespaces: false 74 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 75 | ConstructorInitializerIndentWidth: 4 76 | ContinuationIndentWidth: 0 77 | Cpp11BracedListStyle: false 78 | DeriveLineEnding: true 79 | DerivePointerAlignment: false 80 | DisableFormat: false 81 | ExperimentalAutoDetectBinPacking: false 82 | FixNamespaceComments: false 83 | IndentCaseLabels: false 84 | IndentGotoLabels: false 85 | IndentPPDirectives: None 86 | IndentWidth: 4 87 | IndentWrappedFunctionNames: false 88 | JavaScriptQuotes: Leave 89 | JavaScriptWrapImports: true 90 | KeepEmptyLinesAtTheStartOfBlocks: true 91 | MaxEmptyLinesToKeep: 8 92 | NamespaceIndentation: None 93 | ObjCBinPackProtocolList: Auto 94 | ObjCBlockIndentWidth: 1 95 | ObjCSpaceAfterProperty: false 96 | ObjCSpaceBeforeProtocolList: false 97 | PenaltyBreakAssignment: 1 98 | PenaltyBreakBeforeFirstCallParameter: 1 99 | PenaltyBreakComment: 1 100 | PenaltyBreakFirstLessLess: 1 101 | PenaltyBreakString: 0 102 | PenaltyBreakTemplateDeclaration: 1 103 | PenaltyExcessCharacter: 1 104 | PenaltyReturnTypeOnItsOwnLine: 1 105 | PointerAlignment: Right 106 | ReflowComments: true 107 | SortIncludes: true 108 | SortUsingDeclarations: true 109 | SpaceAfterCStyleCast: false 110 | SpaceAfterLogicalNot: false 111 | SpaceAfterTemplateKeyword: false 112 | SpaceBeforeAssignmentOperators: true 113 | SpaceBeforeCpp11BracedList: true 114 | SpaceBeforeCtorInitializerColon: false 115 | SpaceBeforeInheritanceColon: false 116 | SpaceBeforeParens: ControlStatements 117 | SpaceBeforeRangeBasedForLoopColon: false 118 | SpaceInEmptyBlock: true 119 | SpaceInEmptyParentheses: false 120 | SpacesBeforeTrailingComments: 1 121 | SpacesInAngles: false 122 | SpacesInCStyleCastParentheses: false 123 | SpacesInConditionalStatement: false 124 | SpacesInContainerLiterals: false 125 | SpacesInParentheses: false 126 | SpacesInSquareBrackets: false 127 | Standard: Cpp03 128 | TabWidth: 4 129 | UseCRLF: false 130 | UseTab: ForIndentation 131 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * -crlf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | build/* 3 | lib/* 4 | .vs/*.sdf 5 | .vs/*.suo 6 | .vs/*.opensdf 7 | .vs/.vs/ 8 | *.exe 9 | *.dat 10 | *.VC.db 11 | *.VC.opendb 12 | -------------------------------------------------------------------------------- /.vs/tpp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tpp", "tpp.vcxproj", "{86D226C5-EF62-4562-AC06-E6A753DFA7CF}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {86D226C5-EF62-4562-AC06-E6A753DFA7CF}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {86D226C5-EF62-4562-AC06-E6A753DFA7CF}.Debug|Win32.Build.0 = Debug|Win32 16 | {86D226C5-EF62-4562-AC06-E6A753DFA7CF}.Release|Win32.ActiveCfg = Release|Win32 17 | {86D226C5-EF62-4562-AC06-E6A753DFA7CF}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /.vs/tpp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {86D226C5-EF62-4562-AC06-E6A753DFA7CF} 27 | tpp 28 | 10.0.17763.0 29 | 30 | 31 | 32 | Application 33 | true 34 | v141 35 | MultiByte 36 | 37 | 38 | Application 39 | false 40 | v141 41 | true 42 | MultiByte 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | $(ProjectDir)..\bin\ 56 | $(IncludePath) 57 | AllRules.ruleset 58 | $(ProjectDir)..\build\$(Configuration)\ 59 | 60 | 61 | $(IncludePath) 62 | $(ProjectDir)..\bin\ 63 | AllRules.ruleset 64 | $(ProjectDir)..\build\$(Configuration)\ 65 | 66 | 67 | 68 | Level4 69 | Disabled 70 | true 71 | false 72 | CompileAsCpp 73 | %(PreprocessorDefinitions) 74 | 75 | 76 | true 77 | 78 | 79 | 80 | 81 | Level4 82 | Full 83 | true 84 | true 85 | true 86 | CompileAsCpp 87 | NDEBUG;%(PreprocessorDefinitions) 88 | Speed 89 | AnySuitable 90 | 91 | 92 | true 93 | true 94 | true 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /.vs/tpp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {cda78eda-b19b-4d47-8417-c11383d571ff} 6 | 7 | 8 | 9 | 10 | src 11 | 12 | 13 | src 14 | 15 | 16 | 17 | 18 | src 19 | 20 | 21 | src 22 | 23 | 24 | 25 | 26 | src 27 | 28 | 29 | src 30 | 31 | 32 | -------------------------------------------------------------------------------- /.vs/tpp.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --tok -o out.c ..\bin\input.c 5 | WindowsLocalDebugger 6 | $(ProjectDir)..\bin\ 7 | 8 | 9 | --tok -o out.c ..\bin\input.c 10 | WindowsLocalDebugger 11 | $(ProjectDir)..\bin\ 12 | 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ZLIB LICENSE (https://en.wikipedia.org/wiki/Zlib_License) 2 | 3 | Copyright (c) 2017-2023 Griefer@Work 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgement (see the following) in the product 16 | documentation is required: 17 | Portions Copyright (c) 2017-2023 Griefer@Work 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 3. This notice may not be removed or altered from any source distribution. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tpp - Tiny PreProcessor 2 | 3 | TPP is a tiny (single source file) C Preprocessor, meant as a low-level backend for compilers of C and C-like languages, whilst implementing pretty much all preprocessor extensions supported by other compilers, ontop of a large number of its own (tpp-specific) extensions. 4 | 5 | ### Usage 6 | 7 | TPP is designed to be used in 1 of 2 ways: 8 | 9 | - As a back-end for writing C and C-like compilers with all of the work needed for dealing with macros, directives, warnings, and preprocessor-related pragmas already taken care of. 10 | For this purpose, TPP is meant to be included statically as part of another project's source tree. 11 | - For samples on how this can be done, look in `/samples` 12 | 13 | - As a standalone Preprocessor (similar to GNU's `cpp` utility). 14 | For this purpose, you may build `src/frontend.c` to produce the commandline utility 15 | 16 | 17 | ### Features 18 | 19 | - TPP operates without any intermediate buffers, in that it is capable of preprocessing/tokenizing text in real-time from stream-like input sources: 20 | 21 | ```sh 22 | cat file.c | tpp 23 | ``` 24 | 25 | The above command can be used to preprocess text, without any need for any intermediate buffers (beyond what is needed for a single token) before TPP will start producing output. 26 | 27 | This means that TPP will be able to parse input, and print preprocessed output in real-time, without needing to wait for you to close a PIPE, or reach the end of its input file, first. 28 | 29 | In a sense, this can be compared to python's interactive commandline, which allows it to execute code as you write it. So while an interactive C commandline ~~is probably impossible~~ [is possible](https://github.com/GrieferAtWork/dcc), an interactive C preprocessor ~~most definitely isn't~~ obviously is, too. - Because that's what TPP is. 30 | 31 | - Invocation of the TPP frontend is also designed to be usable by other utilities via the `--pp` switch, which, rather than producing preprocessed output, will emit individual tokens seperated by `'\0'`-characters, allowing you to leave all of the tokenization to tpp, and do the processing yourself in a seperate process. 32 | 33 | 34 | ### Preprocessor Extensions 35 | 36 | All extensions can be hard enabled/disabled when building tpp, or soft-enabled/disabled via `#pragma extension("-fname")` / `#pragma extension("-fno-name")` directives. 37 | 38 | Supported extensions can be tested for with `__has_known_extension("name")`, and supported+enabled extensions with `__has_extension("name")`. In turn, `__has_known_extension` and `__has_extension` can be tested for with `#ifdef`. 39 | 40 | - Trigraphs (`??*`) 41 | - Digraphs (`<%` is `{`, etc...) 42 | - STDC `__VA_ARGS__` (`#define printf(...) fprintf(stderr, __VA_ARGS__)`) 43 | - GCC-style varargs macros (`#define printf(format...) fprintf(stderr, format)`) 44 | - GCC-style va-comma (`#define printf(format, ...) fprintf(stderr, format, ##__VA_ARGS__)`) 45 | - GCC-style if-else in expressions (`#if foo ?: bar`; same as `#if foo ? foo : bar`) 46 | - c++20 `__VA_OPT__` (`#define printf(format, ...) fprintf(stderr, format __VA_OPT__(,) __VA_ARGS__)`) 47 | - `'\e'` escape codes in strings and characters (for ASCII `ESC`, iow: `'\x1b'`) 48 | - Binary literals (`0b00101010`) 49 | - MSVC's `__pragma(foo)` built-in function-like directive/macro 50 | - STDC's `_Pragma("foo")` built-in function-like directive/macro 51 | - GCC-style `#warning My Message Here` directives 52 | - GCC-style `#include_next ` directives 53 | - OBJc-style `#import ` directives 54 | - `#ident` and `#sccs` directives (true origin unknown; accepted by some ancient compilers for placing comments into `.o`-files) 55 | - STDC magic macros `__FILE__`, `__LINE__`, `__TIME__` and `__DATE__` 56 | - Magic macro `__BASE_FILE__` 57 | - Magic macros `__INCLUDE_LEVEL__` and `__INCLUDE_DEPTH__` 58 | - Magic macro `__COUNTER__` 59 | - Magic macro `__TIMESTAMP__` 60 | - Magic macro `__COLUMN__` (tpp-specific; like `__LINE__`, but the current column-position) 61 | - STDC-compliant preprocessor `#if`-expressions 62 | - All STDC-required preprocessor directives (`#define`, `#undef`, `#if`, `#ifdef`, `#ifndef`, `#elif`, `#else`, `#endif`, `#include`, `#pragma`, `#error`) 63 | - Clang-style feature test macros: 64 | - `__has_include()` 65 | - `__has_include_next()` 66 | - `__is_identifier()`, `__is_deprecated()`, `__is_poisoned()` 67 | - `__has_attribute()`, `__has_builtin()`, ... 68 | - `__is_builtin_identifier()` (tpp-specific) 69 | - `__has_extension()`, `__has_known_extension()` (tpp-specific) 70 | - `__has_warning()`, `__has_known_warning()` (tpp-specific) 71 | - Treat `#!`-directives as comments (i.e. `#!/bin/tpp` is treated as a comment) 72 | - Treat `$` as a character, which may thus appear in an identifier 73 | - Preprocessor assertions (no; not those from ``..., but this): 74 | - `#assert cpu(mycpu)` 75 | - `#unassert cpu(yourcpu)` 76 | - `#if #cpu(mycpu)` 77 | - Multi-char character literals (e.g. `#if 'abc' == 6513249`) 78 | - `__VA_COMMA__` (tpp-specific extension) 79 | - `#define printf(format, ...) fprintf(stderr, format __VA_COMMA__ __VA_ARGS__)` 80 | - Expands to `,` when `__VA_ARGS__` are non-empty and `/**/` when empty. 81 | - Essentially the same as `__VA_OPT__(,)` 82 | - `__VA_NARGS__` (tpp-specific extension) 83 | - Expands to the decimal representation of the # of arguments in `__VA_ARGS__` 84 | - Useful for overloading macros by argument count 85 | 86 | ```c 87 | #define min_1(a) a 88 | #define min_2(a, b) ((a) < (b) ? (a) : (b)) 89 | #define min_3(a, b, c) min_2(min_2(a, b), c) 90 | #define min(...) min_##__VA_NARGS__(__VA_ARGS__) 91 | ``` 92 | - Optional support for traditional macro expansion rules (disabled by default, can be enabled temporarily via `#pragma extension`) 93 | - ```c 94 | #define CAT(a,b) a ## b 95 | #define STR(x) #x 96 | #pragma extension(push, "-ftraditional-macro") 97 | #define T_CAT(a, b) a/**/b 98 | #define T_STR(x) "x" 99 | #pragma extension(pop) 100 | CAT(10, 20) // 1020 101 | STR(10) // "10" 102 | T_CAT(10, 20) // 1020 103 | T_STR(10) // "10" 104 | ``` 105 | - Test for with `#if __has_known_extension("traditional-macro")` 106 | - Alternative parenthesis for macro definitions (tpp-specific extension): 107 | - Allow use of: 108 | - `#define foo(a,b) ...` 109 | - `#define foo[a,b] ...` 110 | - `#define foo{a,b} ...` 111 | - `#define foo ...` 112 | - In other words: define macros that use tokens other than `(...)`-pairs for arguments 113 | - Test for with `#if __has_extension("alternative-macro-parenthesis")` 114 | - Self-recursive macros (tpp-specific extension): 115 | - STDC specifies that macros that try to expand to themselves should not be allowed to do so when this happens 116 | - TPP has an optional extension to relax this rule for function-like macros defined while this extension is active 117 | - Such function-like macros are allowed to expand to themselves, so-long as arguments passed during expansion differ from all other invocations of the same macro along the macro-expansion call-stack 118 | - Test for with `#if __has_known_extension("macro-recursion")` 119 | - Enable/disable with `#pragma extension("-fmacro-recursion")` and `#pragma extension("-fno-macro-recursion")` 120 | - Whitespace-sensitivity (tpp-specific extension): 121 | - STDC specifies that whitespace should be stripped around macro bodies. - However, some programming languages are whitespace sensitive, meaning that the removal of whitespace in such cincumstances may alter program behavior. 122 | - For this purpose, TPP has an option to keep whitespace if necessary. 123 | - Test for with `#if __has_extension("macro-argument-whitespace")` 124 | - Allow select operations on string literals in preprocessor expressions (tpp-specific extension): 125 | - `#if "FOO" != "BAR"` 126 | - `#if "FOO"[0] == 'F'` 127 | - `#if "FOO"[1:] == "OO"` 128 | - `#if #"FOO" == 3` 129 | - Test for with `#if __has_extension("strings-in-expressions")` 130 | - Allow for GCC-style `__builtin_*` function calls in preprocessor expressions (tpp-specific extension): 131 | - `#if __builtin_ffs(0x100) == 9` 132 | - Test for with `#if __has_extension("builtins-in-expressions")` 133 | - Allow for `#@` as a replacement for `#` to convert macro arguments into character literals, rather than strings: 134 | - ```c 135 | #define STR(x) #x 136 | #define CHR(x) #@x 137 | STR(f) // "f" 138 | CHR(f) // 'f' 139 | ``` 140 | - Test for with `#if __has_extension("charize-macro-argument")` 141 | - Prevent in-place expansion of macro arguments during macro-function-expansion (tpp-specific extension) (s.a. `/test/pound_xclaim.h`) 142 | - Test for with `#if __has_extension("dont-expand-macro-argument")` 143 | - Logical Xor operators (`A ^^ B`; same as `!!(A) ^ !!(B)`) (tpp-specific extension) 144 | - Precise date/time macros (tpp-specific extension): 145 | - `__DATE_DAY__`, `__DATE_WDAY__`, `__DATE_YDAY__`, `__DATE_MONTH__`, `__DATE_YEAR__` 146 | - `__TIME_SEC__`, `__TIME_MIN__`, `__TIME_HOUR__` 147 | - Test for with `#ifdef ` 148 | - Evaluate preprocessor expressions, and expand to their decimal/string representation (tpp-specific extension): 149 | - For example: `__TPP_EVAL(10 + 20)` would expand to exactly 1 token `30` 150 | - Highly useful because you can do stuff like: 151 | 152 | ```c 153 | #define CAT2(a, b) a##b 154 | #define CAT(a, b) CAT2(a, b) 155 | #define ISLESS_0 more than 156 | #define ISLESS_1 less than 157 | #define SELECT(n) CAT(ISLESS_, __TPP_EVAL(n < 10)) 158 | SELECT(7) // Expands to `less than' 159 | SELECT(10) // Expands to `more than' 160 | ``` 161 | - Can also be combined with `"strings-in-expressions"` to operate on strings: 162 | 163 | ```c 164 | __TPP_EVAL("foobar"[3:]) // Expands to "bar" 165 | ``` 166 | - Test for with `#ifdef __TPP_EVAL` 167 | - Generate unique IDs for a given keyword/name (that remain unchanged when re-compiling the same file without altering its contents) (tpp-specific extension): 168 | - For example, `__TPP_UNIQUE(foo)` expands to a unique decimal integer that will remain the same for `foo` within the entire input (though not necessarily within other files that may be preprocessed seperately) 169 | - Test for with `#ifdef __TPP_UNIQUE` 170 | - Load the contents of a #include-file into a string (tpp-specific extension): 171 | - For example, `__TPP_LOAD_FILE("file.c")` will expand to the the contents of `file.c`, contained in, and escaped as a `"string"` 172 | - Test for with `#ifdef __TPP_LOAD_FILE` 173 | - An arbitrary number of `__COUNTER__`-like counters (tpp-specific extension): 174 | - For example, each time `__TPP_COUNTER(foo)` is encountered, it will expand to 1 greater than its previous expansion (starting at `0`) 175 | - Similar behavior is also possible with `__COUNTER__`, however using `__TPP_COUNTER`, you can have an arbitrary number of counters operating independent of each other. 176 | - Test for with `#ifdef __TPP_COUNTER` 177 | - Random number generation (tpp-specific extension): 178 | - Generate a random number in `[0,hi)` with `__TPP_RANDOM(hi)` 179 | - Generate a random number in `[lo,hi)` with `__TPP_RANDOM(lo, hi)` 180 | - Test for with `#ifdef __TPP_RANDOM` 181 | - Re-interprete the contents of a string token as input text (tpp-specific extension): 182 | - ```c 183 | #define foo 42 184 | __TPP_STR_DECOMPILE("foo bar") // Expands to `42 bar' 185 | ``` 186 | - Test for with `#ifdef __TPP_STR_DECOMPILE` 187 | - Pack together a string token from the ASCII codes of its individual characters (tpp-specific extension): 188 | - For example, `__TPP_STR_PACK(0x48, 0x65, 0x6c, 0x6c, 0x6f)` expands to `"Hello"` 189 | - Test for with `#ifdef __TPP_STR_PACK` 190 | - More extensions exist, but I feel those are not important enough to document here 191 | - Most notably, supported `#pragma` directives, such as `#pragma once`, `#pragma push_macro()`, etc... 192 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CFLAGS="" 4 | 5 | # I told you this is a ~tiny~ preprocessor. 6 | # >> No dependencies other than libc & only 2 source files. 7 | gcc $CFLAGS -o tpp src/frontend.c src/tpp.c 8 | 9 | # NOTE: TPP Also recognizes a few compiler options. 10 | # All options begin with 'TPP_CONFIG_*' and must either 11 | # be predefined as '0' or '1' to override their behavior. 12 | # When not defined at all, they will default to the values 13 | # specified below. 14 | # 15 | # - TPP_CONFIG_DEBUG: DEFAULT: 1 16 | # Enable debug mode and internaly assertions. 17 | # This option is enabled by default and helps 18 | # detect internal problems with TPP. 19 | # 20 | # - TPP_CONFIG_ONELEXER: DEFAULT: 1 21 | # Configure TPP to only use one lexer globally. 22 | # When disabled, a global pointer 'TPPLexer_Current' 23 | # can be overwritten to set the currently used 24 | # lexer, allowing you to set up your own synchronization 25 | # when attempting to use multiple lexers between 26 | # different threads. 27 | # When disabled, only one lexer 'TPPLexer_Global' 28 | # is made available and used, and 'TPPLexer_Current' is 29 | # defined as a macro simply referring to 'TPPLexer_Global', 30 | # as well as lacking the ability of being overwritable. 31 | # In both cases, the used TPP lexer must be initialized 32 | # before being used first, as well as be finalized after 33 | # you're doing, which can easily be achieved using 34 | # 'TPP_INITIALIZE()' and 'TPP_FINALIZE()', which 35 | # will always perform the necessary steps to setup 36 | # and initialize the/a-new global lexer. 37 | # 38 | # - TPP_CONFIG_EXPORT: DEFAULT: 0 39 | # May be used to have TPP export its public functions 40 | # from a shared library, thus allowing you to create 41 | # and link it as a .dll or .so library. 42 | # 43 | # - TPP_CONFIG_MINMACRO: DEFAULT: 0 44 | # Configure TPP never to define builtin macros such 45 | # as '__SIZEOF_POINTER__' or '__INT32_C', essentially 46 | # forcing it to always behave as though '-undef' 47 | # was passed on the commandline. 48 | # 49 | -------------------------------------------------------------------------------- /samples/advanced/Makefile: -------------------------------------------------------------------------------- 1 | 2 | a.out: main.c ../../src/tpp.h ../../src/tpp.c mywrapper-for-tpp.h mywrapper-for-tpp.c my-custom-tpp-defs.h 3 | gcc -o a.out main.c mywrapper-for-tpp.c 4 | 5 | a.exe: main.c ../../src/tpp.h ../../src/tpp.c mywrapper-for-tpp.h mywrapper-for-tpp.c my-custom-tpp-defs.h 6 | gcc -o a.exe main.c mywrapper-for-tpp.c 7 | -------------------------------------------------------------------------------- /samples/advanced/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Running this sample 3 | 4 | ```sh 5 | make a.out # or "a.exe" on windows 6 | ./a.out 7 | ``` 8 | -------------------------------------------------------------------------------- /samples/advanced/input.c: -------------------------------------------------------------------------------- 1 | 2 | #pragma message "It's working!" 3 | 4 | #define foo(a, b) a+b+a+b 5 | 6 | printf("x = %d", foo(10, MY_MACRO) == __TPP_EVAL(foo(10, MY_MACRO))); 7 | #ifdef __MY_PREDEFINED_MACRO__ 8 | IS PREDEFINED 9 | #endif 10 | #if __has_extension("-fawesome") 11 | awesome 12 | #endif 13 | 14 | #if __is_builtin_identifier(async) 15 | Its-a-builtin! 16 | #endif 17 | 18 | #if __is_builtin_identifier(not_async) 19 | #error "This one wasn't defined in 'my-custom-tpp-defs.h', so it shouldn't be a builtin" 20 | #endif 21 | 22 | /*Expected output (token IDs may differ): 23 | 24 | It's working! 25 | input.c:6:1: 814: 'printf' 26 | input.c:6:7: 40: '(' 27 | input.c:6:8: 34: '"x = %d"' 28 | input.c:6:16: 44: ',' 29 | input.c:6:35: 48: '10' [in macro 'foo' at input.c:4:19] 30 | input.c:6:35: 43: '+' [in macro 'foo' at input.c:4:20] 31 | input.c:6:35: 48: '42' [in macro 'foo' at input.c:4:21] 32 | input.c:6:35: 43: '+' [in macro 'foo' at input.c:4:22] 33 | input.c:6:35: 48: '10' [in macro 'foo' at input.c:4:23] 34 | input.c:6:35: 43: '+' [in macro 'foo' at input.c:4:24] 35 | input.c:6:35: 48: '42' [in macro 'foo' at input.c:4:25] 36 | input.c:6:36: 258: '==' 37 | input.c:6:68: 48: '104' 38 | input.c:6:68: 41: ')' 39 | input.c:6:69: 59: ';' 40 | input.c:8:1: 815: 'IS' 41 | input.c:8:4: 816: 'PREDEFINED' 42 | input.c:11:1: 817: 'awesome' 43 | input.c:15:1: 818: 'Its' 44 | input.c:15:4: 45: '-' 45 | input.c:15:5: 812: 'a' 46 | input.c:15:6: 45: '-' 47 | input.c:15:7: 819: 'builtin' 48 | input.c:15:14: 33: '!' 49 | 50 | */ 51 | -------------------------------------------------------------------------------- /samples/advanced/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include "mywrapper-for-tpp.h" 3 | /**/ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #define ERROR_HANDLING fatal(__LINE__) 11 | static void fatal(int line) { 12 | /* Should probably do "TPP_FINALIZE()", unless error was caused by "TPP_INITIALIZE()" */ 13 | fprintf(stderr, "%d: something went horribly wrong\n", line); 14 | exit(1); 15 | } 16 | 17 | 18 | int main() { 19 | /* Initialization */ 20 | if (!TPP_INITIALIZE()) 21 | ERROR_HANDLING; 22 | 23 | /* Configure `TPPLexer_Current' to your liking */ 24 | // TPPLexer_Current->l_flags = ...; 25 | // TPPLexer_Current->l_extokens = ...; 26 | 27 | /* -DMY_MACRO=42 */ 28 | char const *name = "MY_MACRO"; 29 | char const *val = "42"; 30 | if (!TPPLexer_Define(name, strlen(name), val, strlen(val), 31 | TPPLEXER_DEFINE_FLAG_NONE)) 32 | ERROR_HANDLING; 33 | 34 | /* -I/usr/include */ 35 | char incpath[] = "/usr/include"; // Must be writable; use strdup() when in doubt 36 | if (!TPPLexer_AddIncludePath(incpath, strlen(incpath))) 37 | ERROR_HANDLING; 38 | 39 | /* Push an initial file onto the #include-stack */ 40 | char const *filename = "input.c"; 41 | struct TPPFile *file = TPPLexer_OpenFile(TPPLEXER_OPENFILE_MODE_NORMAL | 42 | TPPLEXER_OPENFILE_FLAG_CONSTNAME, 43 | (char *)filename, strlen(filename), 44 | NULL); 45 | if (!file) 46 | ERROR_HANDLING; 47 | TPPLexer_PushFile(file); 48 | 49 | /* Process input one token at a time. 50 | * Hint: emission of certain tokens depends on `TPPLEXER_FLAG_WANT*' and `TPPLEXER_TOKEN_*' */ 51 | while (TPPLexer_Yield() > 0) { 52 | int id = TPPLexer_Current->l_token.t_id; 53 | char *tokstr = TPPLexer_Current->l_token.t_begin; 54 | size_t toklen = (size_t)(TPPLexer_Current->l_token.t_end - tokstr); 55 | struct TPPLCInfo lc; 56 | struct TPPFile *f = TPPLexer_Textfile(); 57 | struct TPPFile *current = TPPLexer_GetFile(); 58 | char *f_ptr = current == f ? tokstr : f->f_pos; 59 | TPPFile_LCAt(f, &lc, f_ptr); 60 | printf("%s:%d:%d: %d: '%.*s'", TPPFile_Filename(f, NULL), 61 | (int)lc.lc_line + 1, (int)lc.lc_col + 1, 62 | id, (int)toklen, tokstr); 63 | if (current != f) { 64 | struct TPPFile *mac = current; 65 | while (mac != f && mac->f_kind != TPPFILE_KIND_MACRO) 66 | mac = mac->f_prev; 67 | if (mac != f) { 68 | struct TPPLCInfo mac_lc; 69 | TPPFile_LCAt(mac, &mac_lc, current == mac ? tokstr : mac->f_pos); 70 | printf(" [in macro '%.*s' at %s:%d:%d]", 71 | (int)mac->f_namesize, mac->f_name, TPPFile_Filename(mac, NULL), 72 | (int)mac_lc.lc_line + 1, (int)mac_lc.lc_col + 1); 73 | } 74 | } 75 | putchar('\n'); 76 | } 77 | 78 | /* Check if something went wrong (stuff like `#error' directives, or syntax errors) */ 79 | if ((TPPLexer_Current->l_flags & TPPLEXER_FLAG_ERROR) || 80 | (TPPLexer_Current->l_errorcount != 0)) 81 | ERROR_HANDLING; 82 | 83 | /* Cleanup the lexer (must be called after successful a `TPPLexer_Init()') */ 84 | TPP_FINALIZE(); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /samples/advanced/my-custom-tpp-defs.h: -------------------------------------------------------------------------------- 1 | /* Custom keywords (but be careful not to re-define ones already defined by TPP) 2 | * When parsed, you can check for these keywords like: 3 | * >> switch (TPPLexer_Current->l_token.t_id) { 4 | * >> case KWD_async: 5 | * >> ...; 6 | * >> break; 7 | * >> case KWD_function: 8 | * >> ...; 9 | * >> break; 10 | * >> } 11 | * */ 12 | DEF_K(async) 13 | DEF_K(function) 14 | DEF_K(def) 15 | DEF_K(awesome_keyword) 16 | 17 | /* These you would probably replace with something else... */ 18 | #define should_be_defined 1 19 | #define enabled_by_default 1 20 | 21 | /* A pre-defined macro (as in `#ifdef __MY_PREDEFINED_MACRO__') 22 | * This should be used for stuff like `__GNUC__' or `__cplusplus', etc... */ 23 | PREDEFINED_MACRO_IF(__MY_PREDEFINED_MACRO__, "42", should_be_defined ? 1 : 0) 24 | 25 | /* Custom warnings groups. (see "tpp-defs.inl" for the default groups) 26 | * Warnings can be enabled/disabled on a per-group basis by parsed text: 27 | * >> #pragma warning("-Wmygroup") // Enable 28 | * >> #pragma warning("-Wno-mygroup") // Disable 29 | * >> #pragma GCC diagnostic error "-Wmygroup" 30 | * >> #pragma GCC diagnostic warning "-Wmygroup" 31 | * >> #pragma GCC diagnostic ignored "-Wmygroup" 32 | */ 33 | WGROUP(WG_MYGROUP, "mygroup", WSTATE_FATAL) // Warnings controlled by "-Wmygroup" / "-Wno-mygroup" / ... 34 | 35 | /* Custom warnings. 36 | * Your compiler would trigger this like (note: it's a varargs function): 37 | * >> if (!TPPLexer_Warn(W_MYWARNING, "first variable argument")) 38 | * >> HANDLE_AS_CRITICAL_ERROR; 39 | * >> TRY_TO_CONTINUE_COMPILING; 40 | */ 41 | DEF_WARNING(W_MYWARNING, (WG_MYGROUP, WG_SYNTAX), WSTATE_ERROR, { 42 | char *mesg = ARG(char *); 43 | WARNF("My warning handler: %s", mesg); 44 | }) 45 | 46 | /* Custom extension. Input code can enable/disable this by: 47 | * >> #pragma extension("-fawesome") // Turn on 48 | * >> #pragma extension("-fno-awesome") // Turn off 49 | * Your compiler can check if it's enabled with `TPPLexer_HasExtension(EXT_AWESOME)' */ 50 | EXTENSION(EXT_AWESOME, "awesome", enabled_by_default ? 1 : 0) 51 | -------------------------------------------------------------------------------- /samples/advanced/mywrapper-for-tpp.c: -------------------------------------------------------------------------------- 1 | #define TPP_USERDEFS "../samples/advanced/my-custom-tpp-defs.h" 2 | #include "../../src/tpp.c" 3 | -------------------------------------------------------------------------------- /samples/advanced/mywrapper-for-tpp.h: -------------------------------------------------------------------------------- 1 | #define TPP_USERDEFS "../samples/advanced/my-custom-tpp-defs.h" 2 | #include "../../src/tpp.h" 3 | -------------------------------------------------------------------------------- /samples/simple/Makefile: -------------------------------------------------------------------------------- 1 | 2 | a.out: main.c ../../src/tpp.h ../../src/tpp.c 3 | gcc -o a.out main.c ../../src/tpp.c 4 | 5 | a.exe: main.c ../../src/tpp.h ../../src/tpp.c 6 | gcc -o a.exe main.c ../../src/tpp.c 7 | -------------------------------------------------------------------------------- /samples/simple/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Running this sample 3 | 4 | ```sh 5 | make a.out # or "a.exe" on windows 6 | ./a.out 7 | ``` 8 | -------------------------------------------------------------------------------- /samples/simple/input.c: -------------------------------------------------------------------------------- 1 | 2 | #pragma message "It's working!" 3 | 4 | #define foo(a, b) a+b+a+b 5 | 6 | printf("x = %d", foo(10, MY_MACRO) == __TPP_EVAL(foo(10, MY_MACRO))); 7 | 8 | /*Expected output (token IDs may differ): 9 | 10 | It's working! 11 | token: 806: 'printf' 12 | token: 40: '(' 13 | token: 34: '"x = %d"' 14 | token: 44: ',' 15 | token: 48: '10' 16 | token: 43: '+' 17 | token: 48: '42' 18 | token: 43: '+' 19 | token: 48: '10' 20 | token: 43: '+' 21 | token: 48: '42' 22 | token: 258: '==' 23 | token: 48: '104' 24 | token: 41: ')' 25 | token: 59: ';' 26 | 27 | */ 28 | -------------------------------------------------------------------------------- /samples/simple/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../../src/tpp.h" 3 | /**/ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #define ERROR_HANDLING fatal(__LINE__) 11 | static void fatal(int line) { 12 | /* Should probably do "TPP_FINALIZE()", unless error was caused by "TPP_INITIALIZE()" */ 13 | fprintf(stderr, "%d: something went horribly wrong\n", line); 14 | exit(1); 15 | } 16 | 17 | 18 | int main() { 19 | /* Initialization */ 20 | if (!TPP_INITIALIZE()) 21 | ERROR_HANDLING; 22 | 23 | /* Configure `TPPLexer_Current' to your liking */ 24 | // TPPLexer_Current->l_flags = ...; 25 | // TPPLexer_Current->l_extokens = ...; 26 | 27 | /* -DMY_MACRO=42 */ 28 | char const *name = "MY_MACRO"; 29 | char const *val = "42"; 30 | if (!TPPLexer_Define(name, strlen(name), val, strlen(val), 31 | TPPLEXER_DEFINE_FLAG_NONE)) 32 | ERROR_HANDLING; 33 | 34 | /* -I/usr/include */ 35 | char incpath[] = "/usr/include"; // Must be writable; use strdup() when in doubt 36 | if (!TPPLexer_AddIncludePath(incpath, strlen(incpath))) 37 | ERROR_HANDLING; 38 | 39 | /* Push an initial file onto the #include-stack */ 40 | char const *filename = "input.c"; 41 | struct TPPFile *file = TPPLexer_OpenFile(TPPLEXER_OPENFILE_MODE_NORMAL | 42 | TPPLEXER_OPENFILE_FLAG_CONSTNAME, 43 | (char *)filename, strlen(filename), 44 | NULL); 45 | if (!file) 46 | ERROR_HANDLING; 47 | TPPLexer_PushFile(file); 48 | 49 | /* Process input one token at a time. 50 | * Hint: emission of certain tokens depends on `TPPLEXER_FLAG_WANT*' and `TPPLEXER_TOKEN_*' */ 51 | while (TPPLexer_Yield() > 0) { 52 | int id = TPPLexer_Current->l_token.t_id; 53 | char *tokstr = TPPLexer_Current->l_token.t_begin; 54 | size_t toklen = (size_t)(TPPLexer_Current->l_token.t_end - tokstr); 55 | printf("token: %d: '%.*s'\n", id, (int)toklen, tokstr); 56 | } 57 | 58 | /* Check if something went wrong (stuff like `#error' directives, or syntax errors) */ 59 | if ((TPPLexer_Current->l_flags & TPPLEXER_FLAG_ERROR) || 60 | (TPPLexer_Current->l_errorcount != 0)) 61 | ERROR_HANDLING; 62 | 63 | /* Cleanup the lexer (must be called after successful a `TPPLexer_Init()') */ 64 | TPP_FINALIZE(); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /src/frontend.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #define TPP(x) x /* Global namespace. */ 21 | #define _CRT_SECURE_NO_WARNINGS 22 | #define _CRT_NONSTDC_NO_WARNINGS 23 | #define _CRT_OBSOLETE_NO_DEPRECATE 24 | 25 | #if defined(_MSC_VER) && defined(_DEBUG) 26 | /* Make use of MSVC's builtin memory leak detector. */ 27 | #define _CRTDBG_MAP_ALLOC 28 | #include 29 | #include 30 | #endif 31 | 32 | #include "tpp.h" 33 | #include 34 | #include 35 | #include 36 | 37 | #ifdef _WIN32 38 | #include 39 | #else /* _WIN32 */ 40 | #include 41 | #include 42 | #endif /* !_WIN32 */ 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif /* __cplusplus */ 47 | 48 | #define STR2(x) #x 49 | #define STR(x) STR2(x) 50 | #if defined(_MSC_FULL_VER) && defined(__cplusplus) 51 | # define TPP_COMPILER "VC++ " STR(_MSC_FULL_VER) 52 | #elif defined(_MSC_FULL_VER) 53 | # define TPP_COMPILER "VC " STR(_MSC_FULL_VER) 54 | #elif defined(__clang__) && defined(__cplusplus) 55 | # define TPP_COMPILER "clang++ " STR(__clang__) 56 | #elif defined(__clang__) 57 | # define TPP_COMPILER "clang " STR(__clang__) 58 | #elif defined(__GNUC__) && defined(__cplusplus) 59 | # define TPP_COMPILER "g++ " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) 60 | #elif defined(__GNUC__) 61 | # define TPP_COMPILER "gcc " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) 62 | #elif defined(__TINYC__) 63 | # define TPP_COMPILER "tcc " STR(__TINYC__) 64 | #elif defined(__cplusplus) 65 | # define TPP_COMPILER "Unknown c++ compiler" 66 | #else 67 | # define TPP_COMPILER "Unknown c compiler" 68 | #endif 69 | 70 | 71 | #define OUTLINE_MODE_NONE 0 72 | #define OUTLINE_MODE_TOK 1 /* Outline with [...] */ 73 | #define OUTLINE_MODE_ZERO 2 /* Separate with `\0' */ 74 | static int outline_tokens = OUTLINE_MODE_NONE; 75 | static int no_magic_tokens = 1; /*< Disable ~magic~ tokens for small line-shifts to prevent a #line being emit. */ 76 | static int line_directives = 2; /*< Enable #line directives being emit. */ 77 | static int decode_tokens = 1; /*< Decode stuff like escape sequences and trigraphs before writing to out. */ 78 | static uint32_t base_flags; /*< Base set of lexer flags. */ 79 | 80 | #ifdef _WIN32 81 | static TPP(stream_t) stdout_handle; 82 | #define write(fd, p, s) (void)WriteFile(fd, p, s, NULL, NULL) 83 | #else /* _WIN32 */ 84 | #define stdout_handle STDOUT_FILENO 85 | #endif /* !_WIN32 */ 86 | 87 | /* We prefer using unbuffered I/O to not create 88 | * bottlenecks when running in immediate mode. 89 | * Also: Window's libc does some weird $h1t to linefeeds, 90 | * inserting a magic '\r' character before every '\n`... 91 | * (You can probably turn that off, but I'm not even gonna bother) */ 92 | #define out_write(p, s) write(stdout_handle, p, s) 93 | 94 | static ptrdiff_t 95 | out_printer(void *closure, char const *buf, size_t bufsize) { 96 | (void)closure; 97 | out_write(buf, bufsize * sizeof(char)); 98 | return 0; 99 | } 100 | 101 | static int is_at_linefeed; 102 | static int current_line; 103 | 104 | void put_line(void) { 105 | static char const *last_filename = NULL; 106 | size_t filename_size; 107 | char const *filename_text; 108 | struct TPPFile *f; 109 | int line; 110 | char buffer[16]; 111 | if (!line_directives) 112 | return; 113 | f = TPPLexer_Textfile(); 114 | if (TPPLexer_Current->l_token.t_file == f) { 115 | /* Try to use the start of the current token. 116 | * NOTE: Something like `f->f_oldpos' would be more 117 | * appropriate to use, but we don't track that... */ 118 | line = TPPFile_LineAt(f, TPPLexer_Current->l_token.t_begin); 119 | } else { 120 | /* Fallback: Use the current position within the file. */ 121 | line = TPPFile_LineAt(f, f->f_pos); 122 | } 123 | filename_text = TPPFile_Filename(f, &filename_size); 124 | if (current_line == line && last_filename == filename_text) 125 | return; 126 | if (outline_tokens != OUTLINE_MODE_ZERO && !no_magic_tokens && 127 | last_filename == filename_text && current_line <= line - 1 && 128 | current_line >= line - 2) { 129 | /* Optimization: For smaller line-offsets of less than 2, it is usually 130 | * easier to simply emit the linefeeds individually. 131 | * WARNING: We can't do this in ZERO-mode though, as in this mode linefeeds 132 | * must only be emit when they actually exist 133 | */ 134 | size_t offset = line - current_line; 135 | current_line = line; 136 | if (outline_tokens == OUTLINE_MODE_TOK) { 137 | out_write("[\n][\n]", (offset * 3) * sizeof(char)); 138 | } else { 139 | out_write("\n\n", offset * sizeof(char)); 140 | } 141 | return; 142 | } 143 | if (!is_at_linefeed) 144 | out_write("\n", sizeof(char)); 145 | current_line = line; 146 | if (line_directives == 2) { 147 | out_write("# ", 2 * sizeof(char)); 148 | } else { 149 | out_write("#line ", 6 * sizeof(char)); 150 | } 151 | out_write(buffer, (TPP_Itos(buffer, (TPP(tint_t))(line + 1)) - buffer) * sizeof(char)); 152 | if (last_filename != filename_text) { 153 | char *quote_buffer; 154 | size_t quote_size; 155 | last_filename = filename_text; 156 | out_write(" \"", 2); 157 | quote_size = TPP_SizeofEscape(filename_text, filename_size); 158 | quote_buffer = (char *)malloc(quote_size * sizeof(char)); 159 | if (quote_buffer) { 160 | TPP_Escape(quote_buffer, filename_text, filename_size); 161 | out_write(quote_buffer, quote_size * sizeof(char)); 162 | free(quote_buffer); 163 | } 164 | out_write(outline_tokens == OUTLINE_MODE_ZERO 165 | ? "\"\0" 166 | : "\"\n", 167 | 2 * sizeof(char)); 168 | } else { 169 | out_write(outline_tokens == OUTLINE_MODE_ZERO 170 | ? "\0" 171 | : "\n", 172 | sizeof(char)); 173 | } 174 | is_at_linefeed = 1; 175 | } 176 | 177 | TPP_LOCAL size_t get_file_offset(char *p) { 178 | struct TPPFile *f = TPPLexer_Current->l_token.t_file; 179 | size_t result = p - f->f_begin; 180 | if (f->f_kind == TPPFILE_KIND_TEXT) { 181 | result += (f->f_textfile.f_rdata - f->f_text->s_size); 182 | } 183 | return result; 184 | } 185 | 186 | TPP_LOCAL int 187 | count_linefeeds(char const *iter, char const *end) { 188 | int result = 0; 189 | while (iter != end) { 190 | if (*iter == '\r') { 191 | if (iter != end - 1 && 192 | iter[1] == '\n') 193 | ++iter; 194 | ++result; 195 | } else if (*iter == '\n') { 196 | ++result; 197 | } 198 | ++iter; 199 | } 200 | return result; 201 | } 202 | 203 | static char const version[] = 204 | "tpp version " STR(TPP_API_VERSION) "/" STR(TPP_PREPROCESSOR_VERSION) " - New Tiny PreProcessor - " 205 | "Copyright (C) 2017 Griefer@Work " 206 | "[" 207 | #if TPP_CONFIG_DEBUG 208 | "DEBUG|" 209 | #endif /* TPP_CONFIG_DEBUG */ 210 | #if TPP_CONFIG_ONELEXER 211 | "ONE|" 212 | #endif /* TPP_CONFIG_ONELEXER */ 213 | #ifdef __TPP_VERSION__ 214 | "TPP " STR(__TPP_VERSION__) "|" 215 | #endif 216 | TPP_COMPILER 217 | #if defined(__TIME__) && defined(__DATE__) 218 | "|" __TIME__ " " __DATE__ 219 | #endif 220 | "]\n\n"; 221 | 222 | struct tpp_extension { 223 | int e_flag; 224 | char const *e_name; 225 | size_t e_size; 226 | }; 227 | extern struct tpp_extension const tpp_extensions[]; 228 | extern char const *const wgroup_names[TPP(WG_COUNT) + 1]; 229 | 230 | void usage(char *appname, char *subject) { 231 | if (subject) { 232 | if (!strcmp(subject, "extensions")) { 233 | struct tpp_extension const *iter; 234 | for (iter = tpp_extensions; iter->e_name; ++iter) { 235 | fprintf(stderr, "-f%s%s\n", TPPLexer_HasExtension(iter - tpp_extensions) ? "" : "no-", iter->e_name); 236 | } 237 | } else if (!strcmp(subject, "warnings")) { 238 | char const *const *iter; 239 | #define getstate(wid) \ 240 | (TPP(wstate_t))((TPPLexer_Current->l_warnings.w_curstate->ws_state[(wid) / (8 / TPP_WARNING_BITS)] >> \ 241 | (((wid) % (8 / TPP_WARNING_BITS)) * TPP_WARNING_BITS)) & \ 242 | 3) 243 | for (iter = wgroup_names; *iter; ++iter) { 244 | fprintf(stderr, "-W%s%s\n", 245 | getstate(iter - wgroup_names) == TPP(WSTATE_DISABLE) ? "no-" 246 | : "", 247 | *iter); 248 | } 249 | #undef getstate 250 | } else { 251 | fprintf(stderr, "Unknown subject: %s\n", subject); 252 | } 253 | return; 254 | } 255 | fprintf(stderr, "Usage: %s [options...] [-o outfile] [infile]\n" 256 | " %s [options...] [-o outfile] -i string...\n" 257 | "options:\n" 258 | #define INDENT "\t" 259 | INDENT "-o Redirect output to a given file (defauls to STDOUT).\n" 260 | INDENT "-i Preprocess the remained of the commandline\n" 261 | INDENT "-Idir Adds `dir' to the list of #include <...> paths\n" 262 | INDENT "-Dsym[=val=1] Defines `sym' as `val'\n" 263 | INDENT "-Usym Undefine a previously defined symbol `sym'\n" 264 | INDENT "-Apred=answer Define an assertion `pred' as `answer'\n" 265 | INDENT "-A-pred[=answer] Delete `answer' or all assertions previously made about `pred'\n" 266 | INDENT "-P Disable emission of #line adjustment directives (Default: on).\n" 267 | INDENT "-M Instead of emitting preprocessor output, emit a make-style list of dependencies.\n" 268 | INDENT "-MM Similar to `-M', but don't include system headers.\n" 269 | INDENT "-MD Like `-M', but don't disable preprocessing.\n" 270 | INDENT "-MMD Like `-MD', but don't disable preprocessing.\n" 271 | INDENT "-MG Disable preprocessing, but include missing files as dependencies, assuming they will be generated.\n" 272 | INDENT "-MP Emit dummy targets for every dependency.\n" 273 | INDENT "-MF Enable dependency tracking and emit its output to , but also preprocess regularly.\n" 274 | INDENT "-MT Specify the target object name used within the generated make dependency.\n" 275 | INDENT "-MQ Same as `-MT', but escape characters special to make, such as `$'.\n" 276 | INDENT "-trigraphs Enable recognition of trigraph character sequences.\n" 277 | INDENT "-traditional[-cpp] Enable recognition of traditional tokens & macros (Default: off).\n" 278 | INDENT "-undef Disable all builtin macros.\n" 279 | INDENT "--tok Outline all tokens using the [...] notation (Default: off).\n" 280 | INDENT "--pp Enable preprocess-mode, which emits all tokens separated by `\\0'-bytes.\n" 281 | INDENT " Enabling this option also disabled SPACE and LF tokens, though\n" 282 | INDENT " they can be re-enabled using the -spc and -lf switches.\n" 283 | INDENT "-ftabstop=width Set the width of tab characters used by __COLUMN__ and in warning/error messages (Default: " STR(TPPLEXER_DEFAULT_TABSIZE) ")\n" 284 | INDENT "-f[no-]spc Configure emission of SPACE tokens (Default: on).\n" 285 | INDENT "-f[no-]lf Configure emission of LF tokens (Default: on).\n" 286 | INDENT "-f[no-]comments Configure emission of COMMENT tokens (Default: off).\n" 287 | INDENT "-f[no-]magiclf Enable/Disable magic linefeeds sometimes used in place of #line (Default: off).\n" 288 | INDENT "-f[no-]longstring Enable/Disable string continuation between lines (Default: off).\n" 289 | INDENT "-f[(cpp|no)-]line Enable/Disable emission of #line directives (Default: cpp-compatible).\n" 290 | INDENT "-f[no-]decode Enable/Disable decoding of di/tri-graphs, as well as escaped linefeeds in output (Default: on).\n" 291 | INDENT "-f[no-]unify-pragma Unify all unknown pragmas to use the preprocessor-directive syntax before re-emission (Default: on).\n" 292 | INDENT "-f[no-] Enable/Disable a given `extension' (s.a.: `--help extensions').\n" 293 | INDENT "-W[no-] Enable/Disable a given `warning' group (s.a.: `--help warnings').\n" 294 | INDENT "--name Set the name used for __FILE__ by INFILE (Useful when INFILE is stdin).\n" 295 | INDENT "--help [subject] Display this help and exit.\n" 296 | INDENT " When specified, subject may be one of {extensions|warnings}\n" 297 | INDENT "--version Display version information and exit.\n" 298 | #ifdef _WIN32 299 | INDENT "--message-format={msvc|gcc} Set the format for error message (Default: msvc).\n" 300 | #else /* _WIN32 */ 301 | INDENT "--message-format={msvc|gcc} Set the format for error message (Default: gcc).\n" 302 | #endif /* !_WIN32 */ 303 | "infile:\n" 304 | INDENT "- When not specified or set to `-', use STDIN as input\n" 305 | INDENT " The name of a file to preprocess, as well as the default value for `--name'\n", 306 | appname, appname); 307 | #undef INDENT 308 | } 309 | 310 | static /*ref*/ struct TPPString * 311 | merge_argv_str(int argc, char **argv) { 312 | struct TPPString *result; 313 | char **iter, **end, *dest; 314 | size_t total_size; 315 | if (!argc) 316 | return TPPString_New("", 0); 317 | total_size = argc - 1; /* All arguments are separated by ` '. */ 318 | end = (iter = argv) + argc; 319 | for (; iter != end; ++iter) 320 | total_size += strlen(*iter); 321 | result = TPPString_NewSized(total_size); 322 | if (!result) 323 | return NULL; 324 | dest = result->s_text; 325 | for (iter = argv; iter != end; ++iter) { 326 | size_t len = strlen(*iter); 327 | memcpy(dest, *iter, len * sizeof(char)); 328 | dest += len; 329 | *dest++ = ' '; 330 | } 331 | return result; 332 | } 333 | 334 | static /*ref*/ struct TPPFile * 335 | merge_argv(int argc, char **argv) { 336 | struct TPPString *argv_string; 337 | struct TPPFile *result; 338 | argv_string = merge_argv_str(argc, argv); 339 | if (!argv_string) 340 | return NULL; 341 | result = (struct TPPFile *)malloc(TPPFILE_SIZEOF_TEXT); 342 | if (!result) 343 | goto err_argv_string; 344 | result->f_refcnt = 1; 345 | result->f_kind = TPPFILE_KIND_TEXT; 346 | result->f_prev = NULL; 347 | result->f_name = strdup(""); 348 | if (!result->f_name) 349 | goto err_r; 350 | result->f_namesize = 13; 351 | #if __SIZEOF_POINTER__ == 8 352 | result->f_namehash = 12182544704004658106ull; 353 | #else /* __SIZEOF_POINTER__ == 8 */ 354 | result->f_namehash = 3330511802ul; 355 | #endif /* __SIZEOF_POINTER__ != 8 */ 356 | result->f_text = argv_string; /* Inherit reference. */ 357 | result->f_begin = argv_string->s_text; 358 | result->f_end = argv_string->s_text + argv_string->s_size; 359 | result->f_pos = argv_string->s_text; 360 | result->f_textfile.f_cacheentry = NULL; 361 | result->f_textfile.f_usedname = NULL; 362 | result->f_textfile.f_lineoff = 0; 363 | result->f_textfile.f_stream = TPP_STREAM_INVALID; 364 | result->f_textfile.f_ownedstream = TPP_STREAM_INVALID; 365 | result->f_textfile.f_guard = NULL; 366 | result->f_textfile.f_cacheinc = 0; 367 | result->f_textfile.f_rdata = argv_string->s_size; 368 | result->f_textfile.f_prefixdel = '\0'; 369 | result->f_textfile.f_flags = TPP_TEXTFILE_FLAG_NOGUARD; 370 | result->f_textfile.f_newguard = NULL; 371 | return result; 372 | err_r: 373 | free(result); 374 | err_argv_string: 375 | TPPString_Decref(argv_string); 376 | return NULL; 377 | } 378 | 379 | static struct TPPFile *last_token_file; 380 | static char *last_token_end; 381 | size_t file_offset; 382 | static void pp_print(char const *buf, size_t bufsize) { 383 | if (outline_tokens == OUTLINE_MODE_TOK) 384 | out_write("[", sizeof(char)); 385 | out_write(buf, bufsize * sizeof(char)); 386 | switch (outline_tokens) { 387 | 388 | case OUTLINE_MODE_ZERO: 389 | out_write("\0", sizeof(char)); 390 | is_at_linefeed = 1; 391 | break; 392 | case OUTLINE_MODE_TOK: 393 | out_write("]", sizeof(char)); 394 | /* FALLTHRU */ 395 | default: 396 | is_at_linefeed = 0; 397 | break; 398 | } 399 | } 400 | static void pp_emit_raw(void) { 401 | last_token_file = TPPLexer_Current->l_token.t_file; 402 | last_token_end = TPPLexer_Current->l_token.t_end; 403 | file_offset = get_file_offset(last_token_end); 404 | if (outline_tokens == OUTLINE_MODE_TOK) 405 | out_write("[", sizeof(char)); 406 | if (decode_tokens) { 407 | TPP_PrintToken(&out_printer, NULL); 408 | if (TPPLexer_Current->l_token.t_id == '\n') 409 | ++current_line; 410 | } else { 411 | out_write(TPPLexer_Current->l_token.t_begin, 412 | (size_t)(TPPLexer_Current->l_token.t_end - 413 | TPPLexer_Current->l_token.t_begin) * 414 | sizeof(char)); 415 | /* Track what we expect the current line number to be, 416 | * which is them compared to the actual line number. */ 417 | current_line += count_linefeeds(TPPLexer_Current->l_token.t_begin, 418 | TPPLexer_Current->l_token.t_end); 419 | } 420 | switch (outline_tokens) { 421 | 422 | case OUTLINE_MODE_ZERO: 423 | out_write("\0", sizeof(char)); 424 | is_at_linefeed = 1; 425 | break; 426 | 427 | case OUTLINE_MODE_TOK: 428 | out_write("]", sizeof(char)); 429 | is_at_linefeed = 0; 430 | break; 431 | 432 | default: 433 | is_at_linefeed = last_token_end[-1] == '\n' || 434 | last_token_end[-1] == '\r'; 435 | break; 436 | } 437 | } 438 | static void pp_emit(void) { 439 | if (last_token_file != TPPLexer_Current->l_token.t_file || 440 | (last_token_end != TPPLexer_Current->l_token.t_begin && 441 | file_offset != get_file_offset(TPPLexer_Current->l_token.t_begin))) { 442 | /* The file changed, or there is a difference in the in-file position 443 | * between the end of the last token and the start of this one. 444 | * >> In any case, we must update the #line offset. */ 445 | put_line(); 446 | } 447 | pp_emit_raw(); 448 | } 449 | 450 | static void pp_normal(void) { 451 | /* Initial values to simulate the last token 452 | * ending where the first file starts. */ 453 | last_token_file = NULL; // infile; /* Force a line directive at the first token. */ 454 | last_token_end = TPPLexer_Current->l_token.t_file->f_begin; 455 | file_offset = 0; 456 | current_line = 0; 457 | is_at_linefeed = 1; 458 | while (TPPLexer_Yield() > 0) 459 | pp_emit(); 460 | if (outline_tokens == OUTLINE_MODE_ZERO) { 461 | out_write("\0", sizeof(char)); 462 | } 463 | } 464 | 465 | static TPP(stream_t) dep_outfile = TPP_STREAM_INVALID; 466 | static int dep_nonsystem_only = 0; 467 | static int dep_emit_dummy = 0; 468 | static void write_filename(TPP(stream_t) fd, char const *p, size_t s) { 469 | /* TODO: Escape special characters, such as ` ' or `\\' */ 470 | write(fd, p, s * sizeof(char)); 471 | } 472 | 473 | static void write_filename_makeescape(TPP(stream_t) fd, char const *p, size_t s) { 474 | /* TODO: Escape special characters, such as `$' */ 475 | write_filename(fd, p, s); 476 | } 477 | 478 | static size_t curline_length = 0; 479 | static void pp_depprint(char *filename, size_t filename_size) { 480 | #define DEP_MAX_LINELENGTH 70 481 | if (dep_outfile == TPP_STREAM_INVALID) 482 | return; 483 | if ((curline_length += (filename_size + 1)) >= DEP_MAX_LINELENGTH) { 484 | write(dep_outfile, " \\\n\t", 4 * sizeof(char)); 485 | curline_length = 0; 486 | } else { 487 | write(dep_outfile, " ", 1 * sizeof(char)); 488 | } 489 | write_filename(dep_outfile, filename, filename_size); 490 | } 491 | 492 | static char **dep_filenamev = NULL; 493 | static size_t dep_filenamec = 0; 494 | static size_t dep_filenamea = 0; 495 | static int pp_add_dep_filename(char const *filename, size_t filename_size) { 496 | char *filename_copy, **new_vec; 497 | if (!dep_emit_dummy || dep_outfile == TPP_STREAM_INVALID) 498 | return 1; 499 | filename_copy = (char *)malloc((filename_size + 1) * sizeof(char)); 500 | if (!filename_copy) 501 | return 0; 502 | memcpy(filename_copy, filename, filename_size * sizeof(char)); 503 | filename_copy[filename_size] = '\0'; 504 | new_vec = dep_filenamev; 505 | if (dep_filenamea == dep_filenamec) { 506 | size_t new_alloc = dep_filenamea ? dep_filenamea * 2 : 2; 507 | new_vec = (char **)realloc(new_vec, new_alloc * sizeof(char *)); 508 | if (!new_vec) { 509 | free(filename_copy); 510 | return 0; 511 | } 512 | dep_filenamev = new_vec; 513 | dep_filenamea = new_alloc; 514 | } 515 | new_vec[dep_filenamec++] = filename_copy; 516 | return 1; 517 | } 518 | 519 | static void pp_emit_dummy_targets(void) { 520 | char **iter, **end, *filename; 521 | end = (iter = dep_filenamev) + dep_filenamec; 522 | if (dep_outfile == TPP_STREAM_INVALID) 523 | dep_emit_dummy = 0; 524 | for (; iter != end; ++iter) { 525 | filename = *iter; 526 | if (dep_emit_dummy) { 527 | write(dep_outfile, "\n\n", 2 * sizeof(char)); 528 | write_filename(dep_outfile, filename, strlen(filename)); 529 | write(dep_outfile, ":", sizeof(char)); 530 | } 531 | free(filename); 532 | } 533 | free(dep_filenamev); 534 | dep_filenamev = NULL; 535 | dep_filenamec = 0; 536 | dep_filenamea = 0; 537 | if (dep_outfile != TPP_STREAM_INVALID) { 538 | write(dep_outfile, "\n", 1 * sizeof(char)); 539 | } 540 | } 541 | 542 | 543 | static int pp_depcallback(struct TPPFile *file, int is_system_header) { 544 | /* Don't emit entries for system header if we`re not supposed to. */ 545 | if (is_system_header && dep_nonsystem_only) 546 | return 1; 547 | if (!pp_add_dep_filename(file->f_name, file->f_namesize)) 548 | return 0; 549 | pp_depprint(file->f_name, file->f_namesize); 550 | return 1; 551 | } 552 | 553 | 554 | static struct TPPFile *TPPCALL 555 | pp_depunknown(int mode, char *__restrict filename, 556 | size_t filename_size, 557 | struct TPPKeyword **pkeyword_entry) { 558 | (void)mode; 559 | (void)pkeyword_entry; 560 | if (!pp_add_dep_filename(filename, filename_size)) 561 | TPPLexer_SetErr(); 562 | pp_depprint(filename, filename_size); 563 | return NULL; 564 | } 565 | 566 | static int dep_escapetarget = 0; /* Escape characters special to make from `dep_targetname'. */ 567 | static char *dep_targetname = NULL; 568 | static int pp_depfirst(struct TPPFile *file) { 569 | char *used_filename, *filename_extension, old; 570 | if (dep_outfile == TPP_STREAM_INVALID) 571 | return 1; 572 | used_filename = file->f_name; 573 | if (dep_targetname) { 574 | dep_escapetarget 575 | ? write_filename_makeescape(dep_outfile, dep_targetname, strlen(dep_targetname)) 576 | : write_filename(dep_outfile, dep_targetname, strlen(dep_targetname)); 577 | } else { 578 | filename_extension = strrchr(used_filename, '.'); 579 | if (!filename_extension) { 580 | size_t filename_size = file->f_namesize; 581 | used_filename = (char *)malloc((filename_size + 2) * sizeof(char)); 582 | if (!used_filename) 583 | return 0; 584 | memcpy(used_filename, file->f_name, filename_size * sizeof(char)); 585 | filename_extension = used_filename + filename_size; 586 | *filename_extension = '.'; 587 | } 588 | old = filename_extension[1], filename_extension[1] = 'o'; 589 | write_filename_makeescape(dep_outfile, used_filename, ((filename_extension - used_filename) + 2)); 590 | filename_extension[1] = old; 591 | if (used_filename != file->f_name) 592 | free(used_filename); 593 | } 594 | write(dep_outfile, ":", 1 * sizeof(char)); 595 | pp_depprint(file->f_name, file->f_namesize); 596 | return 1; 597 | } 598 | 599 | static void pp_deponly(void) { 600 | /* fallback: Use stdout as output file for dependencies if no other file was set. 601 | * HINT: stdout may have previously been redirected with the '-o' option. */ 602 | if (dep_outfile == TPP_STREAM_INVALID) 603 | dep_outfile = stdout_handle; 604 | TPPLexer_Current->l_callbacks.c_parse_pragma = NULL; 605 | while (TPPLexer_Yield() > 0) 606 | ; 607 | } 608 | 609 | static int reemit_pragma(void) { 610 | #define PRAGMA_COPYMASK \ 611 | (TPPLEXER_FLAG_WANTCOMMENTS | \ 612 | TPPLEXER_FLAG_WANTSPACE | \ 613 | TPPLEXER_FLAG_WANTLF) 614 | if (!is_at_linefeed && outline_tokens != OUTLINE_MODE_NONE) 615 | pp_print("\n", 1), ++current_line; 616 | pp_print("#", 1); 617 | pp_print("pragma", 6); 618 | if (base_flags & TPPLEXER_FLAG_WANTSPACE) 619 | pp_print(" ", 1); 620 | TPPLexer_Current->l_flags &= ~(PRAGMA_COPYMASK); 621 | TPPLexer_Current->l_flags |= (base_flags & PRAGMA_COPYMASK); 622 | do { 623 | pp_emit_raw(); 624 | } while (TPPLexer_Yield() > 0); 625 | pp_print("\n", 1); 626 | ++current_line; 627 | is_at_linefeed = 1; 628 | last_token_file = NULL; 629 | last_token_end = NULL; 630 | return 1; 631 | } 632 | 633 | 634 | #ifdef _WIN32 635 | #define close_stream CloseHandle 636 | #else /* _WIN32 */ 637 | #define close_stream close 638 | #endif /* !_WIN32 */ 639 | 640 | static TPP(stream_t) open_out_file(char const *filename) { 641 | TPP(stream_t) 642 | result; 643 | if (!strcmp(filename, "-")) 644 | return stdout_handle; 645 | #ifdef _WIN32 646 | result = CreateFileA(filename, GENERIC_WRITE, 647 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 648 | NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 649 | if (!result) 650 | result = TPP_STREAM_INVALID; 651 | #else /* _WIN32 */ 652 | result = open(filename, O_CREAT | O_WRONLY, 0644); 653 | #endif /* !_WIN32 */ 654 | if (result == TPP_STREAM_INVALID) { 655 | fprintf(stderr, "Failed to create output file: \"%s\"\n", filename); 656 | fflush(stderr); 657 | _exit(1); 658 | } 659 | return result; 660 | } 661 | 662 | #define PPMODE_NORMAL 0 663 | #define PPMODE_DEPENDENCY 1 664 | int main(int argc, char *argv[]) { 665 | struct TPPFile *infile; 666 | int result = 0; 667 | int pp_mode = PPMODE_NORMAL; 668 | char *output_filename = NULL, *appname, *firstname = NULL; 669 | #ifdef _WIN32 670 | stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); 671 | #endif /* _WIN32 */ 672 | if (!TPP_INITIALIZE()) 673 | return 1; 674 | if (argc) 675 | appname = argv[0], --argc, ++argv; 676 | else { 677 | appname = "tpp"; 678 | } 679 | TPPLexer_Current->l_callbacks.c_parse_pragma = &reemit_pragma; 680 | TPPLexer_Current->l_flags |= (TPPLEXER_FLAG_WANTSPACE | 681 | TPPLEXER_FLAG_WANTLF | 682 | #ifdef _WIN32 683 | TPPLEXER_FLAG_MSVC_MESSAGEFORMAT | 684 | #endif /* _WIN32 */ 685 | TPPLEXER_FLAG_TERMINATE_STRING_LF); 686 | #if 1 687 | #define BACKWARDS(x) x /* Backwards-compatibility with old TPP */ 688 | #else 689 | #define BACKWARDS(x) /* nothing */ 690 | #endif 691 | while (argc && (argv[0][0] == '-' BACKWARDS(|| argv[0][0] == '/'))) { 692 | char *arg = argv[0] + 1; 693 | /* TODO: Look at the arguments `cpp' can take and try to implement them all (or most). 694 | * >> This new version of TPP is meant as a drop-in replacement for cpp! */ 695 | if (!strcmp(arg, "-tok") 696 | BACKWARDS(|| !strcmp(arg, "tok")) 697 | BACKWARDS(|| !strcmp(arg, "-tokens"))) { 698 | outline_tokens = OUTLINE_MODE_TOK; 699 | } else if (!strcmp(arg, "fspc")) { 700 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_WANTSPACE; 701 | } else if (!strcmp(arg, "fno-spc")) { 702 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_WANTSPACE); 703 | } else if (!strcmp(arg, "flf")) { 704 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_WANTLF; 705 | } else if (!strcmp(arg, "fno-lf")) { 706 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_WANTLF); 707 | } else if (!strcmp(arg, "fcomments")) { 708 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_WANTCOMMENTS; 709 | } else if (!strcmp(arg, "fno-comments")) { 710 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_WANTCOMMENTS); 711 | } else if (!strcmp(arg, "fmagiclf")) { 712 | no_magic_tokens = 0; 713 | } else if (!strcmp(arg, "fno-magiclf")) { 714 | no_magic_tokens = 1; 715 | } else if (!strcmp(arg, "fdecode")) { 716 | decode_tokens = 1; 717 | } else if (!strcmp(arg, "fno-decode")) { 718 | decode_tokens = 0; 719 | } else if (!strcmp(arg, "flongstring")) { 720 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_TERMINATE_STRING_LF); 721 | } else if (!strcmp(arg, "fno-longstring")) { 722 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_TERMINATE_STRING_LF; 723 | } else if (!strcmp(arg, "funify-pragma")) { 724 | TPPLexer_Current->l_callbacks.c_parse_pragma = &reemit_pragma; 725 | } else if (!strcmp(arg, "fno-unify-pragma")) { 726 | TPPLexer_Current->l_callbacks.c_parse_pragma = NULL; 727 | } else if (!strcmp(arg, "fline")) { 728 | line_directives = 1; 729 | } else if (!strcmp(arg, "fno-line") BACKWARDS(|| !strcmp(arg, "no-line"))) { 730 | line_directives = 0; 731 | } else if (!strcmp(arg, "fcpp-line")) { 732 | line_directives = 2; 733 | } else if (!memcmp(arg, "ftabstop=", 9 * sizeof(char))) { 734 | TPPLexer_Current->l_tabsize = (size_t)atol(arg + 9); 735 | } else if (!strcmp(arg, "trigraphs")) { 736 | TPPLexer_EnableExtension(EXT_TRIGRAPHS); 737 | } else if (!strcmp(arg, "traditional") || 738 | !strcmp(arg, "traditional-cpp")) { 739 | TPPLexer_EnableExtension(EXT_TRADITIONAL_MACRO); 740 | TPPLexer_Current->l_extokens |= TPPLEXER_TOKEN_EQUALBINOP; 741 | } else if (!strcmp(arg, "Werror")) { 742 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_WERROR; 743 | } 744 | #if !TPP_CONFIG_MINMACRO 745 | else if (!strcmp(arg, "undef")) { 746 | TPPLexer_DisableExtension(EXT_CPU_MACROS); 747 | TPPLexer_DisableExtension(EXT_SYSTEM_MACROS); 748 | TPPLexer_DisableExtension(EXT_UTILITY_MACROS); 749 | } 750 | #else /* !TPP_CONFIG_MINMACRO */ 751 | else if (!strcmp(arg, "undef")) { 752 | } 753 | #endif /* TPP_CONFIG_MINMACRO */ 754 | else if (!strcmp(arg, "P")) { 755 | line_directives = 0; 756 | } else if (!strcmp(arg, "M") || 757 | !strcmp(arg, "MM")) { 758 | /* Switch to dependency-only mode. */ 759 | pp_mode = PPMODE_DEPENDENCY; 760 | /* Change the output file to stdout. */ 761 | if (dep_outfile == TPP_STREAM_INVALID) 762 | dep_outfile = stdout_handle; 763 | /* Check if we`re supposed to include system-headeres. */ 764 | dep_nonsystem_only = !strcmp(arg, "MM"); 765 | } else if (!strcmp(arg, "MD") || 766 | !strcmp(arg, "MMD")) { 767 | /* Change the output file to stdout. */ 768 | if (dep_outfile == TPP_STREAM_INVALID) 769 | dep_outfile = stdout_handle; 770 | /* Check if we`re supposed to include system-headeres. */ 771 | dep_nonsystem_only = !strcmp(arg, "MMD"); 772 | } else if (!strcmp(arg, "MG")) { 773 | /* Setup an unknown-file handler, assuming generated headers. */ 774 | TPPLexer_Current->l_callbacks.c_unknown_file = &pp_depunknown; 775 | /* Disable file-not-found warnings (We`re assuming generated headers). */ 776 | TPPLexer_SetWarning(TPP(W_FILE_NOT_FOUND), TPP(WSTATE_DISABLE)); 777 | /* Switch to dependency-only mode. */ 778 | pp_mode = PPMODE_DEPENDENCY; 779 | } else if (!strcmp(arg, "MP")) { 780 | dep_emit_dummy = 1; /* Emit a dummy target for every dependency. */ 781 | } else if (!strcmp(arg, "MF")) { 782 | if (argc > 1) { 783 | /* Close a previously opened dependency output stream. */ 784 | if (dep_outfile != TPP_STREAM_INVALID && dep_outfile != stdout_handle) 785 | close_stream(dep_outfile); 786 | dep_outfile = open_out_file(argv[1]); 787 | ++argv; 788 | --argc; 789 | } 790 | } else if (!strcmp(arg, "MT") || /* Specify a custom target name for dependencies. */ 791 | !strcmp(arg, "MQ")) { 792 | if (argc > 1) { 793 | dep_targetname = argv[1]; 794 | ++argv; 795 | --argc; 796 | } 797 | dep_escapetarget = !strcmp(arg, "MQ"); 798 | } else if (!strcmp(arg, "o") BACKWARDS(|| !strcmp(arg, "-out"))) { 799 | if (argc > 1) { 800 | output_filename = argv[1]; 801 | ++argv; 802 | --argc; 803 | } 804 | } else if (!strcmp(arg, "-name")) { 805 | if (argc > 1) { 806 | firstname = argv[1]; 807 | ++argv; 808 | --argc; 809 | } 810 | } else if (!strcmp(arg, "-message-format=gcc")) { 811 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_MSVC_MESSAGEFORMAT); 812 | } else if (!strcmp(arg, "-message-format=msvc")) { 813 | TPPLexer_Current->l_flags |= TPPLEXER_FLAG_MSVC_MESSAGEFORMAT; 814 | } else if (!strcmp(arg, "-help") BACKWARDS(|| !strcmp(arg, "h") || !strcmp(arg, "?"))) { 815 | usage(appname, argc > 1 && argv[1][0] != '-' ? argv[1] : NULL), _exit(2); 816 | } else if (!strcmp(arg, "-version") BACKWARDS(|| !strcmp(arg, "v"))) { 817 | fwrite(version, sizeof(char), sizeof(version) / sizeof(char) - 1, stderr), _exit(2); 818 | } else if (!strcmp(arg, "i") BACKWARDS(|| !strcmp(arg, "-in"))) { 819 | if (argc) { 820 | --argc; 821 | ++argv; 822 | } 823 | infile = merge_argv(argc, argv); 824 | goto use_infile; 825 | } else if (!strcmp(arg, "-pp")) { 826 | /* Intermediate preprocessor mode: 827 | * - Very useful for invoking tpp from another 828 | * application to really just tokenize a file. 829 | * - Emit tokens separated by `\0'-characters 830 | * - Don't emit whitespace, or linefeeds. 831 | */ 832 | TPPLexer_Current->l_flags &= ~(TPPLEXER_FLAG_WANTSPACE | 833 | TPPLEXER_FLAG_WANTLF); 834 | outline_tokens = OUTLINE_MODE_ZERO; 835 | } else if (*arg == 'I') { 836 | ++arg; 837 | BACKWARDS(add_inc:) 838 | if (!*arg && argc > 1) 839 | arg = argv[1], ++argv, --argc; 840 | if (!TPPLexer_AddIncludePath(arg, strlen(arg))) 841 | _exit(1); 842 | } else if (*arg == 'D') { 843 | char *val; 844 | ++arg; 845 | BACKWARDS(add_def:) 846 | if (!*arg && argc > 1) 847 | arg = argv[1], ++argv, --argc; 848 | val = strchr(arg, '='); 849 | if (val) 850 | *val++ = '\0'; 851 | else { 852 | val = "1"; 853 | } 854 | if (!TPPLexer_Define(arg, strlen(arg), val, strlen(val), 855 | TPPLEXER_DEFINE_FLAG_BUILTIN)) 856 | _exit(1); 857 | } else if (*arg == 'U') { 858 | if (!*++arg && argc > 1) 859 | arg = argv[1], ++argv, --argc; 860 | TPPLexer_Undef(arg, strlen(arg)); 861 | } else if (*arg == 'A') { 862 | int add = 1; 863 | char *val; 864 | if (!*++arg && argc > 1) 865 | arg = argv[1], ++argv, --argc; 866 | if (*arg == '-') 867 | ++arg, add = 0; 868 | val = strchr(arg, '='); 869 | if (val) 870 | *val++ = '\0'; 871 | else if (add) { 872 | goto noopt; 873 | } 874 | if (add) 875 | TPPLexer_AddAssert(arg, strlen(arg), val, strlen(val)); 876 | else { 877 | TPPLexer_DelAssert(arg, strlen(arg), val, val ? strlen(val) : 0); 878 | } 879 | } else if (*arg == 'f') { 880 | int enable = 1; 881 | ++arg; /* Set an extension. */ 882 | if (!memcmp(arg, "no-", 3)) 883 | arg += 3, enable = 0; 884 | if (!TPPLexer_SetExtension(arg, enable)) 885 | goto noopt; 886 | } else if (*arg == 'W') { 887 | TPP(wstate_t) 888 | state = TPP(WSTATE_ERROR); 889 | ++arg; /* Set an extension. */ 890 | if (!memcmp(arg, "no-", 3)) 891 | arg += 3, state = TPP(WSTATE_DISABLE); 892 | if (!TPPLexer_SetWarnings(arg, state)) 893 | goto noopt; 894 | } 895 | BACKWARDS(else if (!memcmp(arg, "-Inc", 4)) { 896 | arg += 4; 897 | goto add_inc; 898 | }) 899 | BACKWARDS(else if (!memcmp(arg, "-Def", 4)) { 900 | arg += 4; 901 | goto add_def; 902 | }) 903 | else { 904 | noopt: 905 | fprintf(stderr, 906 | "Unknown option: \"%s\"\n" 907 | "See '%s --help' for more help\n", 908 | arg - 1, appname); 909 | _exit(1); 910 | } 911 | --argc, ++argv; 912 | } 913 | if (output_filename && strcmp(output_filename, "-")) { 914 | TPP(stream_t) 915 | newout = open_out_file(output_filename); 916 | if (dep_outfile == stdout_handle) 917 | dep_outfile = newout; 918 | #ifdef _WIN32 919 | stdout_handle = newout; 920 | #else /* _WIN32 */ 921 | dup2(STDOUT_FILENO, newout); 922 | #endif /* !_WIN32 */ 923 | } 924 | if (argc && strcmp(argv[0], "-") != 0) { 925 | infile = TPPLexer_OpenFile(TPPLEXER_OPENFILE_MODE_NORMAL | 926 | TPPLEXER_OPENFILE_FLAG_NOCASEWARN, 927 | argv[0], strlen(argv[0]), NULL); 928 | if (infile) 929 | TPPFile_Incref(infile); 930 | if (infile && firstname) { 931 | infile->f_textfile.f_usedname = TPPString_New(firstname, strlen(firstname)); 932 | if (!infile->f_textfile.f_usedname) 933 | _exit(1); 934 | } 935 | if (!infile) 936 | fprintf(stderr, "File not found: \"%s\"\n", argv[0]); 937 | } else { 938 | /* Fallback: Use stdin as input stream. */ 939 | if (!firstname) 940 | firstname = ""; 941 | #ifdef _WIN32 942 | infile = TPPFile_OpenStream(GetStdHandle(STD_INPUT_HANDLE), firstname); 943 | #else /* _WIN32 */ 944 | infile = TPPFile_OpenStream(STDIN_FILENO, firstname); 945 | #endif /* !_WIN32 */ 946 | } 947 | use_infile: 948 | if (!infile) 949 | goto err1; 950 | TPPLexer_PushFileInherited(infile); 951 | TPPLexer_Current->l_callbacks.c_new_textfile = &pp_depcallback; 952 | if (!pp_depfirst(infile)) 953 | goto err1; 954 | base_flags = TPPLexer_Current->l_flags; 955 | switch (pp_mode) { 956 | 957 | case PPMODE_DEPENDENCY: 958 | pp_deponly(); 959 | break; 960 | 961 | default: 962 | pp_normal(); 963 | break; 964 | } 965 | pp_emit_dummy_targets(); 966 | /* Check if something went wrong. */ 967 | if ((TPPLexer_Current->l_flags & TPPLEXER_FLAG_ERROR) || 968 | (TPPLexer_Current->l_errorcount != 0)) 969 | result = 1; 970 | end: 971 | TPP_FINALIZE(); 972 | #ifdef _CRTDBG_MAP_ALLOC 973 | _CrtDumpMemoryLeaks(); 974 | #endif /* _CRTDBG_MAP_ALLOC */ 975 | return result; 976 | err1: 977 | result = 1; 978 | goto end; 979 | } 980 | 981 | #ifdef __cplusplus 982 | } 983 | #endif /* __cplusplus */ 984 | -------------------------------------------------------------------------------- /src/tpp-backwards-compatibility.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2025 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2025 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #ifndef GUARD_TPP_BACKWARDS_COMPATIBILITY_H 21 | #define GUARD_TPP_BACKWARDS_COMPATIBILITY_H 1 22 | 23 | #ifndef TPP 24 | #define TPP(x) TPP_##x 25 | #endif /* !TPP */ 26 | 27 | #include "tpp.h" 28 | 29 | /* NOTE: This header is completely optional and only required 30 | * for backwards compatibility with the old TPP. */ 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif /* __cplusplus */ 35 | 36 | /* Old token names. */ 37 | #define TPP_TOK_EOF TPP(TOK_EOF) 38 | #define TPP_TOK_SPACE TPP(TOK_SPACE) 39 | #define TPP_TOK_LF TPP(TOK_LF) 40 | #define TPP_TOK_INT TPP(TOK_INT) 41 | #define TPP_TOK_FLOAT TPP(TOK_FLOAT) 42 | #define TPP_TOK_COMMENT TPP(TOK_COMMENT) 43 | #define TPP_TOK_CHR TPP(TOK_CHAR) 44 | #define TPP_TOK_STR TPP(TOK_STRING) 45 | #define TPP_TOK_ASSIGN TPP(TOK_ASSIGN) 46 | #define TPP_TOK_CMP_LO TPP(TOK_LOWER) 47 | #define TPP_TOK_CMP_GR TPP(TOK_GREATER) 48 | #define TPP_TOK_QUESTION TPP(TOK_QUESTION) 49 | #define TPP_TOK_COLLON TPP(TOK_COLON) 50 | #define TPP_TOK_ADD TPP(TOK_ADD) 51 | #define TPP_TOK_SUB TPP(TOK_SUB) 52 | #define TPP_TOK_MUL TPP(TOK_MUL) 53 | #define TPP_TOK_DIV TPP(TOK_DIV) 54 | #define TPP_TOK_MOD TPP(TOK_MOD) 55 | #define TPP_TOK_DOT TPP(TOK_DOT) 56 | #define TPP_TOK_COMMA TPP(TOK_COMMA) 57 | #define TPP_TOK_SEMICOLON TPP(TOK_SEMICOLON) 58 | #define TPP_TOK_HASH TPP(TOK_HASH) 59 | #define TPP_TOK_LPAREN TPP(TOK_LPAREN) 60 | #define TPP_TOK_RPAREN TPP(TOK_RPAREN) 61 | #define TPP_TOK_LBRACKET TPP(TOK_LBRACKET) 62 | #define TPP_TOK_RBRACKET TPP(TOK_RBRACKET) 63 | #define TPP_TOK_LBRACE TPP(TOK_LBRACE) 64 | #define TPP_TOK_RBRACE TPP(TOK_RBRACE) 65 | #define TPP_TOK_TILDE TPP(TOK_TILDE) 66 | #define TPP_TOK_AT TPP(TOK_AT) 67 | #define TPP_TOK_BIN_AND TPP(TOK_AND) 68 | #define TPP_TOK_BIN_OR TPP(TOK_OR) 69 | #define TPP_TOK_BIN_XOR TPP(TOK_XOR) 70 | #define TPP_TOK_EXCLAIM TPP(TOK_NOT) 71 | #define TPP_TOK_CMP_LE TPP(TOK_LOWER_EQUAL) 72 | #define TPP_TOK_CMP_EQ TPP(TOK_EQUAL) 73 | #define TPP_TOK_CMP_NE TPP(TOK_NOT_EQUAL) 74 | #define TPP_TOK_CMP_GE TPP(TOK_GREATER_EQUAL) 75 | #define TPP_TOK_ADD_ASSIGN TPP(TOK_ADD_EQUAL) 76 | #define TPP_TOK_SUB_ASSIGN TPP(TOK_SUB_EQUAL) 77 | #define TPP_TOK_MUL_ASSIGN TPP(TOK_MUL_EQUAL) 78 | #define TPP_TOK_DIV_ASSIGN TPP(TOK_DIV_EQUAL) 79 | #define TPP_TOK_MOD_ASSIGN TPP(TOK_MOD_EQUAL) 80 | #define TPP_TOK_SHL TPP(TOK_SHL) 81 | #define TPP_TOK_SHR TPP(TOK_SHR) 82 | #define TPP_TOK_SHL_ASSIGN TPP(TOK_SHL_EQUAL) 83 | #define TPP_TOK_SHR_ASSIGN TPP(TOK_SHR_EQUAL) 84 | #define TPP_TOK_DOTS TPP(TOK_DOTS) 85 | #define TPP_TOK_GLUE TPP(TOK_GLUE) 86 | #define TPP_TOK_BIN_AND_ASSIGN TPP(TOK_AND_EQUAL) 87 | #define TPP_TOK_BIN_OR_ASSIGN TPP(TOK_OR_EQUAL) 88 | #define TPP_TOK_BIN_XOR_ASSIGN TPP(TOK_XOR_EQUAL) 89 | #define TPP_TOK_LAND TPP(TOK_LAND) 90 | #define TPP_TOK_LOR TPP(TOK_LOR) 91 | #define TPP_TOK_INC TPP(TOK_INC) 92 | #define TPP_TOK_DEC TPP(TOK_DEC) 93 | #define TPP_TOK_POW TPP(TOK_POW) 94 | #define TPP_TOK_POW_ASSIGN TPP(TOK_POW_EQUAL) 95 | #define TPP_TOK_LXOR TPP(TOK_LXOR) 96 | #define TPP_TOK_TILDE_TILDE TPP(TOK_TILDE_TILDE) 97 | #define TPP_TOK_ARROW TPP(TOK_ARROW) 98 | #define TPP_TOK_COLLON_ASSIGN TPP(TOK_COLON_EQUAL) 99 | #define TPP_TOK_COLLON_COLLON TPP(TOK_COLON_COLON) 100 | #define TPP_TOK_IDENT_START TPP(TOK_KEYWORD_BEGIN) 101 | 102 | typedef TPP(tok_t) TPPTokenID; 103 | #define TPPTokenID_IS_KEYWORD TPP_ISKEYWORD 104 | #define TPPTokenID_IS_USER_KEYWORD TPP_ISUSERKEYWORD 105 | #define TPPTokenID_IS_INT(id) ((id) == TPP_TOK_INT || (id) == TPP_TOK_CHR) 106 | 107 | typedef TPP(tint_t) TPPInteger; 108 | typedef TPP(tint_t) TPPUInteger; 109 | typedef TPP(tint_t) TPPCounter; 110 | typedef size_t TPPKeywordHash; 111 | 112 | #define TPPMacroCallingConvention_PAREN 0 113 | #define TPPMacroCallingConvention_BRACKET 1 114 | #define TPPMacroCallingConvention_BRACE 2 115 | #define TPPMacroCallingConvention_ANGLE 3 116 | 117 | #define TPPKeywordFlag_NONE 0x00 118 | #define TPPKeywordFlag_HAS_ATTRIBUTE 0x01 119 | #define TPPKeywordFlag_HAS_BUILTIN 0x02 120 | #define TPPKeywordFlag_HAS_CPP_ATTRIBUTE 0x04 121 | #define TPPKeywordFlag_HAS_DECLSPEC_ATTRIBUTE 0x08 122 | #define TPPKeywordFlag_HAS_EXTENSION 0x10 123 | #define TPPKeywordFlag_HAS_FEATURE 0x20 124 | #define TPPKeywordFlag_IS_DEPRECATED 0x40 125 | 126 | # define TPPLexer_FLAG_NONE TPPLEXER_FLAG_NONE 127 | # define TPPLexer_FLAG_WANT_LF TPPLEXER_FLAG_WANTLF 128 | # define TPPLexer_FLAG_WANT_SPC TPPLEXER_FLAG_WANTSPACE 129 | # define TPPLexer_FLAG_NO_MACROS TPPLEXER_FLAG_NO_MACROS 130 | # define TPPLexer_FLAG_NO_DIRECTIVES TPPLEXER_FLAG_NO_DIRECTIVES 131 | # define TPPLexer_FLAG_ASM_COMMENTS TPPLEXER_FLAG_ASM_COMMENTS 132 | # define TPPLexer_FLAG_ONE_FILE TPPLEXER_FLAG_NO_POP_ON_EOF 133 | //#define TPPLexer_FLAG_ONE_REAL_FILE TPPLEXER_FLAG_NO_POP_ON_EOF 134 | # define TPPLexer_FLAG_INC_STRING TPPLEXER_FLAG_INCLUDESTRING 135 | # define TPPLexer_FLAG_RAND_INIT TPPLEXER_FLAG_RANDOM_INITIALIZED 136 | # define TPPLexer_FLAG_NO_DEPRECATED TPPLEXER_FLAG_NO_DEPRECATED 137 | # define TPPLexer_FLAG_TOK_COMMENTS TPPLEXER_FLAG_WANTCOMMENTS 138 | 139 | 140 | 141 | # define f_refcnt f_refcnt 142 | # define f_prev f_prev 143 | # define f_name f_name 144 | # define f_new_name f_textfile.f_usedname->s_text 145 | # define f_ref_file f_macro.m_deffile 146 | //#define f_ref_file_off f_macro.m_defline 147 | # define f_line_offset f_textfile.f_lineoff 148 | # define f_iter f_pos 149 | # define f_end f_end 150 | # define f_data f_text->s_text 151 | typedef struct TPPFile TPPFileObject; 152 | 153 | # define tk_id t_id 154 | # define tk_file t_file 155 | //#define tk_file_off ... 156 | # define tk_str_file t_file 157 | # define tk_str_begin t_begin 158 | # define tk_str_end t_end 159 | typedef struct TPPToken TPPTokenObject; 160 | 161 | # define he_next k_next 162 | # define he_id k_id 163 | # define he_flags k_rare->kr_flags 164 | # define he_counter k_rare->kr_counter 165 | # define he_raw_hash k_hash 166 | # define he_str_len k_size 167 | # define he_str k_name 168 | typedef struct TPPKeyword TPPKeywordListHashEntryObject; 169 | 170 | //#define kl_next km_entryc 171 | # define kl_hash_alloc km_bucketc 172 | # define kl_hash km_bucketv 173 | typedef struct TPPKeywordMap TPPKeywordListObject; 174 | 175 | # define a_name ai_id 176 | # define a_references ai_ins_exp 177 | # define a_quote_references ai_ins_str 178 | #define TPPMacroArgument TPP(arginfo_t) 179 | 180 | 181 | //typedef ... TPPMacroObject; /* Replaced by `TPPFile'. */ 182 | //typedef ... TPPMacroListObject; /* Merged with `TPPKeywordMap'. */ 183 | 184 | 185 | # define il_size il_pathc 186 | //#define il_paths il_pathv 187 | typedef struct TPPIncludeList TPPIncludeListObject; 188 | 189 | 190 | # define e_value iss_mode 191 | //#define e_token ... 192 | typedef struct TPPIfdefStackSlot TPPIfdefStackEntryObject; 193 | 194 | #define s_size is_slotc 195 | #define s_alloc is_slota 196 | #define s_stack is_slotv 197 | typedef struct TPPIfdefStack TPPIfdefStackObject; 198 | 199 | //typedef ... TPPIncludeCacheEntry; /* Merged with `TPPKeyword'. */ 200 | //typedef ... TPPIncludeCacheObject; /* Merged with `TPPKeywordMap'. */ 201 | 202 | #define wc_prev ws_prev 203 | #define wc_warnings ws_state 204 | typedef struct TPPWarningState TPPWarningsFrameObject; 205 | 206 | #define w_top w_curstate 207 | typedef struct TPPWarnings TPPWarningsObject; 208 | 209 | 210 | # define l_files l_token.t_file 211 | # define l_keywords l_keywords 212 | # define l_flags l_flags 213 | # define l_macros l_keywords 214 | //#define l_include_list ... 215 | # define l_sys_include_list l_syspaths 216 | # define l_ifdef_stack l_ifdef 217 | # define l_include_cache l_keywords 218 | //#define l_one_file_rec ... 219 | # define l_warnings l_warnings 220 | # define l_counter l_counter 221 | typedef struct TPPLexer TPPLexerObject; 222 | 223 | #define TPPLexer_FastDefine(self, name, code) \ 224 | (assert(TPPLexer_Current == (self)), \ 225 | TPPLexer_Define(name, strlen(name), code, strlen(code)) \ 226 | ? 0 \ 227 | : -1) 228 | 229 | #ifdef __cplusplus 230 | } 231 | #endif /* __cplusplus */ 232 | 233 | #endif /* !GUARD_TPP_BACKWARDS_COMPATIBILITY_H */ 234 | -------------------------------------------------------------------------------- /src/tpp-gcc-defs.inl: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2025 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2025 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | 21 | #define TPP_PRIVATE_PP_CAT2(a, b) a##b 22 | #define TPP_PRIVATE_PP_CAT3(a, b, c) a##b##c 23 | #define TPP_PP_CAT2(a, b) TPP_PRIVATE_PP_CAT2(a, b) 24 | #define TPP_PP_CAT3(a, b, c) TPP_PRIVATE_PP_CAT3(a, b, c) 25 | 26 | /* CPU-specific predefined macros. */ 27 | #if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) 28 | PREDEFINED_MACRO_IF(__alpha__, HAS(EXT_CPU_MACROS), "1") 29 | #endif 30 | 31 | #if defined(__amd64__) || defined(__amd64) || \ 32 | defined(__x86_64__) || defined(__x86_64) || \ 33 | defined(_M_X64) || defined(_M_AMD64) 34 | PREDEFINED_MACRO_IF(__x86_64__, HAS(EXT_CPU_MACROS), "1") 35 | #endif 36 | 37 | #if defined(__TARGET_ARCH_ARM) 38 | #define TPP_ARM_VERSION __TARGET_ARCH_ARM 39 | #elif defined(_M_ARM) 40 | #define TPP_ARM_VERSION _M_ARM 41 | #elif defined(__ARM_ARCH_8__) 42 | #define TPP_ARM_VERSION 8 43 | #elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ 44 | defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ 45 | defined(__ARM_ARCH_7S__) 46 | #define TPP_ARM_VERSION 7 47 | #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ 48 | defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ 49 | defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) 50 | #define TPP_ARM_VERSION 6 51 | #elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) || \ 52 | defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) || \ 53 | defined(__ARM_ARCH_5TEJ__) 54 | #define TPP_ARM_VERSION 5 55 | #elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T) 56 | #define TPP_ARM_VERSION 4 57 | #elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__) 58 | #define TPP_ARM_VERSION 3 59 | #elif defined(__ARM_ARCH_2__) 60 | #define TPP_ARM_VERSION 2 61 | #elif defined(__arm__) || defined(__arm) || defined(_ARM) || defined(__ARM_ARCH_1__) 62 | #define TPP_ARM_VERSION 1 63 | #endif 64 | #ifdef TPP_ARM_VERSION 65 | PREDEFINED_MACRO_IF(__arm__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_ARM_VERSION)) 66 | #if TPP_ARM_VERSION == 8 67 | PREDEFINED_MACRO_IF(__ARM_ARCH_8__, HAS(EXT_CPU_MACROS), "1") 68 | #elif TPP_ARM_VERSION == 7 69 | PREDEFINED_MACRO_IF(__ARM_ARCH_7__, HAS(EXT_CPU_MACROS), "1") 70 | #elif TPP_ARM_VERSION == 6 71 | #ifdef __ARM_ARCH_6T2__ 72 | PREDEFINED_MACRO_IF(__ARM_ARCH_6T2__, HAS(EXT_CPU_MACROS), "1") 73 | #else 74 | PREDEFINED_MACRO_IF(__ARM_ARCH_6__, HAS(EXT_CPU_MACROS), "1") 75 | #endif 76 | #elif TPP_ARM_VERSION == 5 77 | #if defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) 78 | PREDEFINED_MACRO_IF(__ARM_ARCH_5T__, HAS(EXT_CPU_MACROS), "1") 79 | #else 80 | PREDEFINED_MACRO_IF(__ARM_ARCH_5__, HAS(EXT_CPU_MACROS), "1") 81 | #endif 82 | #elif TPP_ARM_VERSION == 4 83 | PREDEFINED_MACRO_IF(__ARM_ARCH_4T__, HAS(EXT_CPU_MACROS), "1") 84 | #elif TPP_ARM_VERSION == 3 85 | PREDEFINED_MACRO_IF(__ARM_ARCH_3__, HAS(EXT_CPU_MACROS), "1") 86 | #elif TPP_ARM_VERSION == 2 87 | PREDEFINED_MACRO_IF(__ARM_ARCH_2__, HAS(EXT_CPU_MACROS), "1") 88 | #else 89 | PREDEFINED_MACRO_IF(__ARM_ARCH_1__, HAS(EXT_CPU_MACROS), "1") 90 | #endif 91 | #if defined(__TARGET_ARCH_THUMB) 92 | PREDEFINED_MACRO_IF(__thumb__, HAS(EXT_CPU_MACROS), TPP_PP_STR(__TARGET_ARCH_THUMB)) 93 | #elif defined(_M_ARMT) 94 | PREDEFINED_MACRO_IF(__thumb__, HAS(EXT_CPU_MACROS), TPP_PP_STR(_M_ARM)) 95 | #elif defined(__thumb__) 96 | PREDEFINED_MACRO_IF(__thumb__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_ARM_VERSION)) 97 | #endif 98 | #undef TPP_ARM_VERSION 99 | #endif 100 | 101 | #ifdef __aarch64__ 102 | PREDEFINED_MACRO_IF(__aarch64__, HAS(EXT_CPU_MACROS), "1") 103 | #endif /* __aarch64__ */ 104 | 105 | #if defined(__bfin) || defined(__BFIN__) 106 | PREDEFINED_MACRO_IF(__bfin, HAS(EXT_CPU_MACROS), "1") 107 | #endif /* __bfin || __BFIN__ */ 108 | 109 | #ifdef __C67__ 110 | PREDEFINED_MACRO_IF(__C67__, HAS(EXT_CPU_MACROS), "1") 111 | #endif /* __C67__ */ 112 | 113 | #ifdef __convex__ 114 | PREDEFINED_MACRO_IF(__convex__, HAS(EXT_CPU_MACROS), "1") 115 | #ifdef __convex_c1__ 116 | PREDEFINED_MACRO_IF(__convex_c1__, HAS(EXT_CPU_MACROS), "1") 117 | #endif /* __convex_c1__ */ 118 | #ifdef __convex_c2__ 119 | PREDEFINED_MACRO_IF(__convex_c2__, HAS(EXT_CPU_MACROS), "1") 120 | #endif /* __convex_c2__ */ 121 | #ifdef __convex_c32__ 122 | PREDEFINED_MACRO_IF(__convex_c32__, HAS(EXT_CPU_MACROS), "1") 123 | #endif /* __convex_c32__ */ 124 | #ifdef __convex_c34__ 125 | PREDEFINED_MACRO_IF(__convex_c34__, HAS(EXT_CPU_MACROS), "1") 126 | #endif /* __convex_c34__ */ 127 | #ifdef __convex_c38__ 128 | PREDEFINED_MACRO_IF(__convex_c38__, HAS(EXT_CPU_MACROS), "1") 129 | #endif /* __convex_c38__ */ 130 | #endif /* __convex__ */ 131 | 132 | #ifdef __epiphany__ 133 | PREDEFINED_MACRO_IF(__epiphany__, HAS(EXT_CPU_MACROS), "1") 134 | #endif /* __epiphany__ */ 135 | 136 | #if defined(__hppa__) || defined(__HPPA__) || defined(__hppa) 137 | PREDEFINED_MACRO_IF(__hppa__, HAS(EXT_CPU_MACROS), "1") 138 | #endif /* __hppa__ || __HPPA__ || __hppa */ 139 | 140 | #if defined(__I86__) 141 | #define TPP_I386_VERSION (__I86__ * 100) 142 | #elif defined(_M_IX86) 143 | #define TPP_I386_VERSION _M_IX86 144 | #elif defined(__i686__) || defined(__i686) || defined(i686) 145 | #define TPP_I386_VERSION 600 146 | #elif defined(__i586__) || defined(__i586) || defined(i586) 147 | #define TPP_I386_VERSION 500 148 | #elif defined(__i486__) || defined(__i486) || defined(i486) 149 | #define TPP_I386_VERSION 400 150 | #elif defined(__i386__) || defined(__i386) || defined(i386) || \ 151 | defined(__X86__) || defined(_X86_) || \ 152 | defined(__THW_INTEL__) || defined(__INTEL__) 153 | #define TPP_I386_VERSION 300 154 | #endif 155 | #ifdef TPP_I386_VERSION 156 | #if TPP_I386_VERSION >= 600 157 | PREDEFINED_MACRO_IF(__i686__, HAS(EXT_CPU_MACROS), "1") 158 | #endif 159 | #if TPP_I386_VERSION >= 500 160 | PREDEFINED_MACRO_IF(__i586__, HAS(EXT_CPU_MACROS), "1") 161 | #endif 162 | #if TPP_I386_VERSION >= 400 163 | PREDEFINED_MACRO_IF(__i486__, HAS(EXT_CPU_MACROS), "1") 164 | #endif 165 | #if TPP_I386_VERSION >= 300 166 | PREDEFINED_MACRO_IF(__i386__, HAS(EXT_CPU_MACROS), "1") 167 | #endif 168 | #undef TPP_I386_VERSION 169 | #endif /* TPP_I386_VERSION */ 170 | 171 | #if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \ 172 | defined(__ia64) || defined(_M_IA64) || defined(__itanium__) 173 | PREDEFINED_MACRO_IF(__ia64__, HAS(EXT_CPU_MACROS), "1") 174 | #endif /* __ia64__ || _IA64 || __IA64__ || __ia64 || _M_IA64 || __itanium__ */ 175 | 176 | #if defined(__mc68060__) || defined(__mc68060) || defined(mc68060) 177 | #define TPP_M64K_VERSION 68060 178 | #elif defined(__mc68040__) || defined(__mc68040) || defined(mc68040) 179 | #define TPP_M64K_VERSION 68040 180 | #elif defined(__mc68030__) || defined(__mc68030) || defined(mc68030) 181 | #define TPP_M64K_VERSION 68030 182 | #elif defined(__mc68020__) || defined(__mc68020) || defined(mc68020) 183 | #define TPP_M64K_VERSION 68020 184 | #elif defined(__mc68010__) || defined(__mc68010) || defined(mc68010) 185 | #define TPP_M64K_VERSION 68010 186 | #elif defined(__mc68000__) || defined(__mc68000) || defined(mc68000) || \ 187 | defined(__MC68000__) || defined(M68000) || defined(__MC68K__) 188 | #define TPP_M64K_VERSION 68000 189 | #endif 190 | #ifdef TPP_M64K_VERSION 191 | PREDEFINED_MACRO_IF(__m68k__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_M64K_VERSION)) 192 | PREDEFINED_KWD_MACRO_IF(TPP_PP_CAT3(KWD___mc, TPP_M64K_VERSION, __), 193 | "__mc" TPP_PP_STR(TPP_M64K_VERSION) "__", 194 | HAS(EXT_CPU_MACROS), "1") 195 | #undef TPP_M64K_VERSION 196 | #endif /* TPP_M64K_VERSION */ 197 | 198 | #if defined(__mips) 199 | #define TPP_MIPS_VERSION __mips 200 | #elif defined(__MIPS_ISA4__) 201 | #define TPP_MIPS_VERSION 4 202 | #elif defined(__MIPS_ISA3__) 203 | #define TPP_MIPS_VERSION 3 204 | #elif defined(__MIPS_ISA2__) 205 | #define TPP_MIPS_VERSION 2 206 | #elif defined(_MIPS_ISA) 207 | #if defined(_MIPS_ISA_MIPS4) && _MIPS_ISA == _MIPS_ISA_MIPS4 208 | #define TPP_MIPS_VERSION 4 209 | #elif defined(_MIPS_ISA_MIPS3) && _MIPS_ISA == _MIPS_ISA_MIPS3 210 | #define TPP_MIPS_VERSION 3 211 | #elif defined(_MIPS_ISA_MIPS2) && _MIPS_ISA == _MIPS_ISA_MIPS2 212 | #define TPP_MIPS_VERSION 2 213 | #else 214 | #define TPP_MIPS_VERSION 1 215 | #endif 216 | #elif defined(__mips__) 217 | #define TPP_MIPS_VERSION __mips__ 218 | #elif defined(__MIPS__) 219 | #define TPP_MIPS_VERSION 1 220 | #endif 221 | 222 | #ifdef TPP_MIPS_VERSION 223 | PREDEFINED_MACRO_IF(__mips__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_MIPS_VERSION)) 224 | PREDEFINED_MACRO_IF(__mips, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_MIPS_VERSION)) 225 | #undef TPP_MIPS_VERSION 226 | #endif /* TPP_MIPS_VERSION */ 227 | 228 | #ifdef _M_PPC 229 | #define TPP_POWERPC_VERSION _M_PPC 230 | #elif defined(__ppc604__) 231 | #define TPP_POWERPC_VERSION 604 232 | #elif defined(__ppc603__) 233 | #define TPP_POWERPC_VERSION 603 234 | #elif defined(__ppc601__) 235 | #define TPP_POWERPC_VERSION 601 236 | #elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || \ 237 | defined(__POWERPC__) || defined(__ppc__) || defined(__ppc64__) || \ 238 | defined(__PPC__) || defined(__PPC64__) || defined(_ARCH_PPC) || \ 239 | defined(_ARCH_PPC64) || defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || \ 240 | defined(_XENON) || defined(__ppc) 241 | #if defined(_ARCH_620) 242 | #define TPP_POWERPC_VERSION 620 243 | #elif defined(_ARCH_604) 244 | #define TPP_POWERPC_VERSION 604 245 | #elif defined(_ARCH_603) 246 | #define TPP_POWERPC_VERSION 603 247 | #elif defined(_ARCH_601) 248 | #define TPP_POWERPC_VERSION 601 249 | #elif defined(_ARCH_450) 250 | #define TPP_POWERPC_VERSION 450 251 | #else 252 | #define TPP_POWERPC_VERSION 440 253 | #endif 254 | #endif 255 | 256 | #ifdef TPP_POWERPC_VERSION 257 | PREDEFINED_MACRO_IF(__powerpc__, HAS(EXT_CPU_MACROS), 258 | TPP_PP_STR(TPP_POWERPC_VERSION)) 259 | PREDEFINED_KWDMACRO_IF(TPP_PP_CAT3(KWD___ppc, TPP_POWERPC_VERSION, __), 260 | "__ppc" TPP_PP_STR(TPP_POWERPC_VERSION) "__", 261 | HAS(EXT_CPU_MACROS), "1") 262 | #undef TPP_POWERPC_VERSION 263 | #endif /* TPP_POWERPC_VERSION */ 264 | 265 | #ifdef pyr 266 | PREDEFINED_MACRO_IF(pyr, HAS(EXT_CPU_MACROS), TPP_PP_STR(pyr)) 267 | #endif /* pyr */ 268 | 269 | 270 | #if defined(__sparc_v9__) || defined(__sparcv9) 271 | #define TPP_SPARC_VERSION 9 272 | #elif defined(__sparc_v8__) || defined(__sparcv8) 273 | #define TPP_SPARC_VERSION 8 274 | #elif defined(__sparc__) || defined(__sparc) 275 | #define TPP_SPARC_VERSION 1 276 | #endif 277 | 278 | #ifdef TPP_SPARC_VERSION 279 | PREDEFINED_MACRO_IF(__sparc__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_SPARC_VERSION)) 280 | #if TPP_SPARC_VERSION == 9 281 | PREDEFINED_MACRO_IF(__sparc_v9__, HAS(EXT_CPU_MACROS), "1") 282 | #elif TPP_SPARC_VERSION == 8 283 | PREDEFINED_MACRO_IF(__sparc_v8__, HAS(EXT_CPU_MACROS), "1") 284 | #endif 285 | #undef TPP_SPARC_VERSION 286 | #endif /* TPP_SPARC_VERSION */ 287 | 288 | #if defined(__SH5__) || defined(__sh5__) 289 | #define TPP_SUPERH_VERSION 5 290 | #elif defined(__SH4__) || defined(__sh4__) 291 | #define TPP_SUPERH_VERSION 4 292 | #elif defined(__SH3__) || defined(__sh3__) 293 | #define TPP_SUPERH_VERSION 3 294 | #elif defined(__SH2__) || defined(__sh2__) 295 | #define TPP_SUPERH_VERSION 2 296 | #elif defined(__SH1__) || defined(__sh1__) || defined(__sh__) 297 | #define TPP_SUPERH_VERSION 1 298 | #endif 299 | 300 | #ifdef TPP_SUPERH_VERSION 301 | PREDEFINED_MACRO_IF(__sh__, HAS(EXT_CPU_MACROS), TPP_PP_STR(TPP_SUPERH_VERSION)) 302 | PREDEFINED_KWDMACRO_IF(TPP_PP_CAT3(KWD___sh, TPP_SUPERH_VERSION, __), 303 | "__sh" TPP_PP_STR(TPP_SUPERH_VERSION) "__", 304 | HAS(EXT_CPU_MACROS), "1") 305 | #undef TPP_SUPERH_VERSION 306 | #endif /* TPP_SUPERH_VERSION */ 307 | 308 | #if defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__) 309 | PREDEFINED_MACRO_IF(__s390x__, HAS(EXT_CPU_MACROS), "1") 310 | #endif /* __s390x__ || __zarch__ || __SYSC_ZARCH__ */ 311 | #if defined(__370__) || defined(__THW_370__) || defined(__s390__) 312 | PREDEFINED_MACRO_IF(__370__, HAS(EXT_CPU_MACROS), "1") 313 | #endif /* __370__ || __THW_370__ || __s390__ */ 314 | 315 | /* System-specific predefined macros. */ 316 | #ifdef __APPLE__ 317 | PREDEFINED_MACRO_IF(__APPLE__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__APPLE__)) 318 | #endif /* __APPLE__ */ 319 | #ifdef __MACH__ 320 | PREDEFINED_MACRO_IF(__MACH__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MACH__)) 321 | #endif /* __MACH__ */ 322 | #ifdef __ANDROID__ 323 | PREDEFINED_MACRO_IF(__ANDROID__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__ANDROID__)) 324 | #elif defined(__ANDROID) 325 | PREDEFINED_MACRO_IF(__ANDROID__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__ANDROID)) 326 | #elif defined(__android__) 327 | PREDEFINED_MACRO_IF(__ANDROID__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__android__)) 328 | #elif defined(__android) 329 | PREDEFINED_MACRO_IF(__ANDROID__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__android)) 330 | #endif 331 | #ifdef __amigaos__ 332 | PREDEFINED_MACRO_IF(__amigaos__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__amigaos__)) 333 | #elif defined(AMIGA) 334 | PREDEFINED_MACRO_IF(__amigaos__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(AMIGA)) 335 | #endif 336 | #if defined(__bg__) || defined(__bgq__) || defined(__THW_BLUEGENE__) || defined(__TOS_BGQ__) 337 | PREDEFINED_MACRO_IF(__bg__, HAS(EXT_SYSTEM_MACROS), "1") 338 | #endif /* __bg__ || __bgq__ || __THW_BLUEGENE__ || __TOS_BGQ__ */ 339 | #ifdef __bgq__ 340 | PREDEFINED_MACRO_IF(__bgq__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__bgq__)) 341 | #elif defined(__TOS_BGQ__) 342 | PREDEFINED_MACRO_IF(__bgq__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__TOS_BGQ__)) 343 | #endif 344 | #ifdef __FreeBSD__ 345 | PREDEFINED_MACRO_IF(__FreeBSD__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__FreeBSD__)) 346 | #endif /* __FreeBSD__ */ 347 | #ifdef __NetBSD__ 348 | PREDEFINED_MACRO_IF(__NetBSD__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__NetBSD__)) 349 | #endif /* __NetBSD__ */ 350 | #ifdef __OpenBSD__ 351 | PREDEFINED_MACRO_IF(__OpenBSD__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__OpenBSD__)) 352 | #endif /* __OpenBSD__ */ 353 | #ifdef __bsdi__ 354 | PREDEFINED_MACRO_IF(__bsdi__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__bsdi__)) 355 | #endif /* __bsdi__ */ 356 | #ifdef __CYGWIN__ 357 | #define TPP_PLATFORM_NOT_WINDOWS 358 | PREDEFINED_MACRO_IF(__CYGWIN__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__CYGWIN__)) 359 | #elif defined(__MINGW32__) 360 | #define TPP_PLATFORM_NOT_WINDOWS 361 | PREDEFINED_MACRO_IF(__MINGW32__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MINGW32__)) 362 | PREDEFINED_MACRO_IF(__CYGWIN__, HAS(EXT_SYSTEM_MACROS), "1") /* Prefer cygwin! */ 363 | #endif 364 | #ifdef DGUX 365 | PREDEFINED_MACRO_IF(__dgux__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(DGUX)) 366 | #elif defined(__DGUX__) 367 | PREDEFINED_MACRO_IF(__dgux__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__DGUX__)) 368 | #elif defined(__dgux__) 369 | PREDEFINED_MACRO_IF(__dgux__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__dgux__)) 370 | #endif 371 | #ifdef __DragonFly__ 372 | PREDEFINED_MACRO_IF(__DragonFly__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__DragonFly__)) 373 | #endif /* __DragonFly__ */ 374 | #ifdef __ECOS 375 | PREDEFINED_MACRO_IF(__ECOS, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__ECOS)) 376 | #endif /* __ECOS */ 377 | #ifdef __EMX__ 378 | PREDEFINED_MACRO_IF(__EMX__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__EMX__)) 379 | #endif /* __EMX__ */ 380 | #ifdef __hiuxmpp 381 | PREDEFINED_MACRO_IF(__hiuxmpp, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__hiuxmpp)) 382 | #endif /* __hiuxmpp */ 383 | #ifdef _hpux 384 | PREDEFINED_MACRO_IF(__hpux, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_hpux)) 385 | #elif defined(hpux) 386 | PREDEFINED_MACRO_IF(__hpux, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(hpux)) 387 | #elif defined(__hpux) 388 | PREDEFINED_MACRO_IF(__hpux, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__hpux)) 389 | #endif 390 | #ifdef sgi 391 | PREDEFINED_MACRO_IF(__sgi, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(sgi)) 392 | #elif defined(__sgi) 393 | PREDEFINED_MACRO_IF(__sgi, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__sgi)) 394 | #endif 395 | #if defined(__linux__) || defined(__linux) || defined(linux) 396 | PREDEFINED_MACRO_IF(__linux__, HAS(EXT_SYSTEM_MACROS), "1") 397 | #endif /* __linux__ || __linux || linux */ 398 | #ifdef __Lynx__ 399 | PREDEFINED_MACRO_IF(__Lynx__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__Lynx__)) 400 | #endif /* __Lynx__ */ 401 | #ifdef __OS9000 402 | PREDEFINED_MACRO_IF(__OS9000, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__OS9000)) 403 | #elif defined(_OSK) 404 | PREDEFINED_MACRO_IF(__OS9000, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_OSK)) 405 | #endif 406 | #ifdef __minix 407 | PREDEFINED_MACRO_IF(__minix, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__minix)) 408 | #endif /* __minix */ 409 | #ifdef __MORPHOS__ 410 | PREDEFINED_MACRO_IF(__MORPHOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MORPHOS__)) 411 | #endif /* __MORPHOS__ */ 412 | #ifdef __mpeix 413 | PREDEFINED_MACRO_IF(__mpeix, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__mpeix)) 414 | #elif defined(mpeix) 415 | PREDEFINED_MACRO_IF(__mpeix, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(mpeix)) 416 | #endif 417 | #ifdef __MSDOS__ 418 | PREDEFINED_MACRO_IF(__MSDOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MSDOS__)) 419 | #elif defined(MSDOS) 420 | PREDEFINED_MACRO_IF(__MSDOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(MSDOS)) 421 | #elif defined(_MSDOS) 422 | PREDEFINED_MACRO_IF(__MSDOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_MSDOS)) 423 | #elif defined(__DOS__) 424 | PREDEFINED_MACRO_IF(__MSDOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__DOS__)) 425 | #endif 426 | #ifdef __TANDEM 427 | PREDEFINED_MACRO_IF(__TANDEM, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__TANDEM)) 428 | #endif /* __TANDEM */ 429 | #ifdef __MACOS__ 430 | PREDEFINED_MACRO_IF(__MACOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MACOS__)) 431 | #endif /* __MACOS__ */ 432 | #ifdef __MACOSX__ 433 | PREDEFINED_MACRO_IF(__MACOSX__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MACOSX__)) 434 | #endif /* __MACOSX__ */ 435 | #ifdef __nucleus__ 436 | PREDEFINED_MACRO_IF(__nucleus__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__nucleus__)) 437 | #endif /* __nucleus__ */ 438 | #ifdef OS2 439 | PREDEFINED_MACRO_IF(__OS2__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(OS2)) 440 | #elif defined(_OS2) 441 | PREDEFINED_MACRO_IF(__OS2__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_OS2)) 442 | #elif defined(__OS2__) 443 | PREDEFINED_MACRO_IF(__OS2__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__OS2__)) 444 | #elif defined(__TOS_OS2__) 445 | PREDEFINED_MACRO_IF(__OS2__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__TOS_OS2__)) 446 | #endif 447 | #ifdef __palmos__ 448 | PREDEFINED_MACRO_IF(__palmos__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__palmos__)) 449 | #endif /* __palmos__ */ 450 | #ifdef EPLAN9 451 | PREDEFINED_MACRO_IF(EPLAN9, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(EPLAN9)) 452 | #endif /* EPLAN9 */ 453 | #ifdef __QNX__ 454 | PREDEFINED_MACRO_IF(__QNX__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__QNX__)) 455 | #endif /* __QNX__ */ 456 | #ifdef __QNXNTO__ 457 | PREDEFINED_MACRO_IF(__QNXNTO__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__QNXNTO__)) 458 | #endif /* __QNXNTO__ */ 459 | #ifdef sinux 460 | PREDEFINED_MACRO_IF(sinux, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(sinux)) 461 | #endif /* sinux */ 462 | #ifdef sun 463 | PREDEFINED_MACRO_IF(__sun, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(sun)) 464 | #elif defined(__sun) 465 | PREDEFINED_MACRO_IF(__sun, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__sun)) 466 | #endif 467 | #ifdef __VOS__ 468 | PREDEFINED_MACRO_IF(__VOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__VOS__)) 469 | #endif /* __VOS__ */ 470 | #if defined(__sysv__) || defined(__SVR4) || \ 471 | defined(__svr4__) || defined(_SYSTYPE_SVR4) 472 | PREDEFINED_MACRO_IF(__sysv__, HAS(EXT_SYSTEM_MACROS), "1") 473 | PREDEFINED_MACRO_IF(__svr4__, HAS(EXT_SYSTEM_MACROS), "1") 474 | #endif 475 | #ifdef __SYLLABLE__ 476 | PREDEFINED_MACRO_IF(__SYLLABLE__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__SYLLABLE__)) 477 | #endif /* __SYLLABLE__ */ 478 | #ifdef __SYMBIAN32__ 479 | PREDEFINED_MACRO_IF(__SYMBIAN32__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__SYMBIAN32__)) 480 | #endif /* __SYMBIAN32__ */ 481 | #ifdef __osf__ 482 | PREDEFINED_MACRO_IF(__osf__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__osf__)) 483 | #elif defined(__osf) 484 | PREDEFINED_MACRO_IF(__osf__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__osf)) 485 | #endif 486 | #ifdef __ultrix__ 487 | PREDEFINED_MACRO_IF(__ultrix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__ultrix__)) 488 | #elif defined(__ultrix) 489 | PREDEFINED_MACRO_IF(__ultrix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__ultrix)) 490 | #elif defined(ultrix) 491 | PREDEFINED_MACRO_IF(__ultrix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(ultrix)) 492 | #elif (defined(__unix__) || defined(__unix) || defined(unix)) && \ 493 | (defined(__vax__) || defined(__vax) || defined(vax)) 494 | PREDEFINED_MACRO_IF(__ultrix__, HAS(EXT_SYSTEM_MACROS), "1") 495 | #endif 496 | #ifdef _UNICOS 497 | PREDEFINED_MACRO_IF(_UNICOS, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_UNICOS)) 498 | #endif /* _UNICOS */ 499 | #ifdef __crayx1 500 | PREDEFINED_MACRO_IF(__crayx1, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__crayx1)) 501 | #elif defined(_CRAY) 502 | PREDEFINED_MACRO_IF(__crayx1, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_CRAY)) 503 | #endif 504 | #if defined(__unix__) 505 | PREDEFINED_MACRO_IF(__unix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__unix__)) 506 | #elif defined(__unix) 507 | PREDEFINED_MACRO_IF(__unix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__unix)) 508 | #elif defined(unix) 509 | PREDEFINED_MACRO_IF(__unix__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(unix)) 510 | #elif defined(__ANDROID__) || defined(__ANDROID) || \ 511 | defined(__android__) || defined(__android) || \ 512 | defined(__linux__) || defined(__linux) || defined(linux) || \ 513 | defined(__MACOS__) || defined(__MACOSX__) || defined(__POSIX__) 514 | PREDEFINED_MACRO_IF(__unix__, HAS(EXT_SYSTEM_MACROS), "1") 515 | #endif 516 | #ifdef __VMS 517 | PREDEFINED_MACRO_IF(__VMS, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__VMS)) 518 | #elif defined(VMS) 519 | PREDEFINED_MACRO_IF(__VMS, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(VMS)) 520 | #endif 521 | #ifdef __VMS_VER 522 | PREDEFINED_MACRO_IF(__VMS_VER, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__VMS_VER)) 523 | #endif /* __VMS_VER */ 524 | #ifdef __vxworks 525 | PREDEFINED_MACRO_IF(__vxworks, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__vxworks)) 526 | #elif defined(__VXWORKS__) 527 | PREDEFINED_MACRO_IF(__vxworks, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__VXWORKS__)) 528 | #endif 529 | #ifndef TPP_PLATFORM_NOT_WINDOWS 530 | #ifdef __WINDOWS__ 531 | #define TPP_PLATFORM_WINDOWS 532 | PREDEFINED_MACRO_IF(__WINDOWS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__WINDOWS__)) 533 | #elif defined(_WIN16) || defined(WIN16) || \ 534 | defined(_WIN32) || defined(WIN32) || \ 535 | defined(_WIN64) || defined(WIN64) || \ 536 | defined(__WIN32__) || defined(__TOS_WIN__) 537 | #define TPP_PLATFORM_WINDOWS 538 | PREDEFINED_MACRO_IF(__WINDOWS__, HAS(EXT_SYSTEM_MACROS), "1") 539 | #elif defined(_WIN32_WCE) || defined(WIN32_WCE) 540 | PREDEFINED_MACRO_IF(__WINDOWS__, HAS(EXT_SYSTEM_MACROS), "1") 541 | #endif 542 | #ifdef _WIN32 543 | PREDEFINED_MACRO_IF(_WIN32, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_WIN32)) 544 | #elif defined(WIN32) 545 | PREDEFINED_MACRO_IF(_WIN32, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(WIN32)) 546 | #elif defined(__WIN32__) 547 | PREDEFINED_MACRO_IF(_WIN32, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__WIN32__)) 548 | #elif defined(TPP_PLATFORM_WINDOWS) && __SIZEOF_POINTER__ >= 4 549 | PREDEFINED_MACRO_IF(_WIN32, HAS(EXT_SYSTEM_MACROS), "1") 550 | #endif 551 | #ifdef _WIN64 552 | PREDEFINED_MACRO_IF(_WIN64, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_WIN64)) 553 | #elif defined(WIN64) 554 | PREDEFINED_MACRO_IF(_WIN64, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(WIN64)) 555 | #elif defined(TPP_PLATFORM_WINDOWS) && __SIZEOF_POINTER__ == 8 556 | PREDEFINED_MACRO_IF(_WIN64, HAS(EXT_SYSTEM_MACROS), "1") 557 | #endif 558 | #ifdef _WIN16 559 | PREDEFINED_MACRO_IF(_WIN16, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_WIN16)) 560 | #elif defined(WIN16) 561 | PREDEFINED_MACRO_IF(_WIN16, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(WIN16)) 562 | #elif defined(TPP_PLATFORM_WINDOWS) && __SIZEOF_POINTER__ == 2 563 | PREDEFINED_MACRO_IF(_WIN16, HAS(EXT_SYSTEM_MACROS), "1") 564 | #endif 565 | #ifdef _WIN32_WCE 566 | PREDEFINED_MACRO_IF(_WIN32_WCE, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(_WIN32_WCE)) 567 | #elif defined(WIN32_WCE) 568 | PREDEFINED_MACRO_IF(_WIN32_WCE, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(WIN32_WCE)) 569 | #endif 570 | #ifdef TPP_PLATFORM_WINDOWS 571 | #undef TPP_PLATFORM_WINDOWS 572 | #endif /* TPP_PLATFORM_WINDOWS */ 573 | #endif /* !TPP_PLATFORM_NOT_WINDOWS */ 574 | #ifdef __MVS__ 575 | PREDEFINED_MACRO_IF(__MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MVS__)) 576 | #ifdef __HOS_MVS__ 577 | PREDEFINED_MACRO_IF(__HOS_MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__HOS_MVS__)) 578 | #else 579 | PREDEFINED_MACRO_IF(__HOS_MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__MVS__)) 580 | #endif 581 | #elif defined(__HOS_MVS__) 582 | PREDEFINED_MACRO_IF(__MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__HOS_MVS__)) 583 | PREDEFINED_MACRO_IF(__HOS_MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__HOS_MVS__)) 584 | #endif 585 | #ifdef __TOS_MVS__ 586 | PREDEFINED_MACRO_IF(__TOS_MVS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__TOS_MVS__)) 587 | #endif /* __TOS_MVS__ */ 588 | #ifdef __KOS__ /* ~smirks~ */ 589 | PREDEFINED_MACRO_IF(__KOS__, HAS(EXT_SYSTEM_MACROS), TPP_PP_STR(__KOS__)) 590 | #endif /* __KOS__ */ 591 | 592 | 593 | /* Utility predefined macros. */ 594 | #ifndef TPP_UTILITY_MACROS_DEFINED 595 | #define TPP_UTILITY_MACROS_DEFINED 596 | #ifndef TPP_MSCV_OR_GCC 597 | #ifdef _MSC_VER 598 | #define TPP_MSCV_OR_GCC(msvc, gcc) msvc 599 | #else /* _MSC_VER */ 600 | #define TPP_MSCV_OR_GCC(msvc, gcc) gcc 601 | #endif /* !_MSC_VER */ 602 | #endif /* !TPP_MSCV_OR_GCC */ 603 | #ifndef __INT8_TYPE__ 604 | #define __INT8_TYPE__ TPP_MSCV_OR_GCC(__int8, signed char) 605 | #endif /* !__INT8_TYPE__ */ 606 | #ifndef __UINT8_TYPE__ 607 | #define __UINT8_TYPE__ unsigned TPP_MSCV_OR_GCC(__int8, char) 608 | #endif /* !__UINT8_TYPE__ */ 609 | #ifndef __INT16_TYPE__ 610 | #define __INT16_TYPE__ TPP_MSCV_OR_GCC(__int16, short) 611 | #endif /* !__INT16_TYPE__ */ 612 | #ifndef __UINT16_TYPE__ 613 | #define __UINT16_TYPE__ unsigned TPP_MSCV_OR_GCC(__int16, short) 614 | #endif /* !__UINT16_TYPE__ */ 615 | #ifndef __INT32_TYPE__ 616 | #define __INT32_TYPE__ TPP_MSCV_OR_GCC(__int32, int) 617 | #endif /* !__INT32_TYPE__ */ 618 | #ifndef __UINT32_TYPE__ 619 | #define __UINT32_TYPE__ unsigned TPP_MSCV_OR_GCC(__int32, int) 620 | #endif /* !__UINT32_TYPE__ */ 621 | #ifndef __INT64_TYPE__ 622 | #define __INT64_TYPE__ TPP_MSCV_OR_GCC(__int64, long long) 623 | #endif /* !__INT64_TYPE__ */ 624 | #ifndef __UINT64_TYPE__ 625 | #define __UINT64_TYPE__ unsigned TPP_MSCV_OR_GCC(__int64, long long) 626 | #endif /* !__UINT64_TYPE__ */ 627 | #define TPP_MUL8_1 8 628 | #define TPP_MUL8_2 16 629 | #define TPP_MUL8_4 32 630 | #define TPP_MUL8_8 64 631 | #define TPP_MUL8_16 128 632 | #define TPP_MUL8(x) TPP_PRIVATE_PP_CAT2(TPP_MUL8_, x) 633 | #define TPP_INTTYPE_1 __INT8_TYPE__ 634 | #define TPP_INTTYPE_2 __INT16_TYPE__ 635 | #define TPP_INTTYPE_4 __INT32_TYPE__ 636 | #define TPP_INTTYPE_8 __INT64_TYPE__ 637 | #define TPP_UINTTYPE_1 __UINT8_TYPE__ 638 | #define TPP_UINTTYPE_2 __UINT16_TYPE__ 639 | #define TPP_UINTTYPE_4 __UINT32_TYPE__ 640 | #define TPP_UINTTYPE_8 __UINT64_TYPE__ 641 | #define TPP_INTTYPE(n) TPP_PRIVATE_PP_CAT2(TPP_INTTYPE_, n) 642 | #define TPP_UINTTYPE(n) TPP_PRIVATE_PP_CAT2(TPP_UINTTYPE_, n) 643 | #ifndef __SIZEOF_INT__ 644 | #define __SIZEOF_INT__ 4 645 | #endif /* !__SIZEOF_INT__ */ 646 | #ifndef __SIZEOF_LONG__ 647 | #if defined(_WIN16) || defined(WIN16) || \ 648 | defined(_WIN32) || defined(WIN32) || \ 649 | defined(_WIN64) || defined(WIN64) 650 | #define __SIZEOF_LONG__ 4 651 | #else 652 | #define __SIZEOF_LONG__ __SIZEOF_POINTER__ 653 | #endif 654 | #endif 655 | #ifndef __SIZEOF_LONG_LONG__ 656 | #define __SIZEOF_LONG_LONG__ 8 657 | #endif /* __SIZEOF_LONG_LONG__ */ 658 | #ifndef __SIZEOF_SHORT__ 659 | #define __SIZEOF_SHORT__ 2 660 | #endif /* __SIZEOF_SHORT__ */ 661 | #ifndef __SIZEOF_FLOAT__ 662 | #define __SIZEOF_FLOAT__ 4 663 | #endif /* __SIZEOF_FLOAT__ */ 664 | #ifndef __SIZEOF_DOUBLE__ 665 | #define __SIZEOF_DOUBLE__ 8 666 | #endif /* __SIZEOF_DOUBLE__ */ 667 | #ifndef __SIZEOF_LONG_DOUBLE__ 668 | #ifdef _MSC_VER 669 | #define __SIZEOF_LONG_DOUBLE__ 8 670 | #elif defined(__C67__) || defined(__i386__) || \ 671 | defined(__i386) || defined(i386) 672 | #define __SIZEOF_LONG_DOUBLE__ 12 673 | #elif defined(__X86_64__) 674 | #define __SIZEOF_LONG_DOUBLE__ 16 675 | #else 676 | #define __SIZEOF_LONG_DOUBLE__ 8 677 | #endif 678 | #endif /* !__SIZEOF_LONG_DOUBLE__ */ 679 | #ifndef __SIZEOF_SIZE_T__ 680 | #define __SIZEOF_SIZE_T__ __SIZEOF_POINTER__ 681 | #endif /* !__SIZEOF_SIZE_T__ */ 682 | #ifndef __SIZEOF_WCHAR_T__ 683 | #if defined(_WIN16) || defined(WIN16) || \ 684 | defined(_WIN32) || defined(WIN32) || \ 685 | defined(_WIN64) || defined(WIN64) 686 | #define __SIZEOF_WCHAR_T__ 2 687 | #else 688 | #define __SIZEOF_WCHAR_T__ 4 689 | #endif 690 | #endif /* !__SIZEOF_WCHAR_T__ */ 691 | #ifndef __SIZEOF_WINT_T__ 692 | #define __SIZEOF_WINT_T__ __SIZEOF_INT__ 693 | #endif /* !__SIZEOF_WINT_T__ */ 694 | #ifndef __SIZEOF_PTRDIFF_T__ 695 | #define __SIZEOF_PTRDIFF_T__ __SIZEOF_POINTER__ 696 | #endif /* !__SIZEOF_PTRDIFF_T__ */ 697 | #ifndef __SCHAR_WIDTH__ 698 | #define __SCHAR_WIDTH__ 8 699 | #endif /* !__SCHAR_WIDTH__ */ 700 | #ifndef __SHRT_WIDTH__ 701 | #define __SHRT_WIDTH__ TPP_MUL8(__SIZEOF_SHORT__) 702 | #endif /* !__SHRT_WIDTH__ */ 703 | #ifndef __INT_WIDTH__ 704 | #define __INT_WIDTH__ TPP_MUL8(__SIZEOF_INT__) 705 | #endif /* !__INT_WIDTH__ */ 706 | #ifndef __LONG_WIDTH__ 707 | #define __LONG_WIDTH__ TPP_MUL8(__SIZEOF_LONG__) 708 | #endif /* !__LONG_WIDTH__ */ 709 | #ifndef __LONG_LONG_WIDTH__ 710 | #define __LONG_LONG_WIDTH__ TPP_MUL8(__SIZEOF_LONG_LONG__) 711 | #endif /* !__LONG_LONG_WIDTH__ */ 712 | #ifndef __PTRDIFF_WIDTH__ 713 | #define __PTRDIFF_WIDTH__ TPP_MUL8(__SIZEOF_PTRDIFF_T__) 714 | #endif /* !__PTRDIFF_WIDTH__ */ 715 | #ifndef __SIG_ATOMIC_WIDTH__ 716 | #define __SIG_ATOMIC_WIDTH__ TPP_MUL8(__SIZEOF_INT__) 717 | #endif /* !__SIG_ATOMIC_WIDTH__ */ 718 | #ifndef __SIZE_WIDTH__ 719 | #define __SIZE_WIDTH__ TPP_MUL8(__SIZEOF_SIZE_T__) 720 | #endif /* !__SIZE_WIDTH__ */ 721 | #ifndef __WCHAR_WIDTH__ 722 | #define __WCHAR_WIDTH__ TPP_MUL8(__SIZEOF_WCHAR_T__) 723 | #endif /* !__WCHAR_WIDTH__ */ 724 | #ifndef __WINT_WIDTH__ 725 | #define __WINT_WIDTH__ TPP_MUL8(__SIZEOF_WINT_T__) 726 | #endif /* !__WINT_WIDTH__ */ 727 | #ifndef __INT_LEAST8_WIDTH__ 728 | #define __INT_LEAST8_WIDTH__ 8 729 | #endif /* !__INT_LEAST8_WIDTH__ */ 730 | #ifndef __INT_LEAST16_WIDTH__ 731 | #define __INT_LEAST16_WIDTH__ 16 732 | #endif /* !__INT_LEAST16_WIDTH__ */ 733 | #ifndef __INT_LEAST32_WIDTH__ 734 | #define __INT_LEAST32_WIDTH__ 32 735 | #endif /* !__INT_LEAST32_WIDTH__ */ 736 | #ifndef __INT_LEAST64_WIDTH__ 737 | #define __INT_LEAST64_WIDTH__ 64 738 | #endif /* !__INT_LEAST64_WIDTH__ */ 739 | #ifndef __INT_FAST8_WIDTH__ 740 | #define __INT_FAST8_WIDTH__ 8 741 | #endif /* !__INT_FAST8_WIDTH__ */ 742 | #ifndef __INT_FAST16_WIDTH__ 743 | #define __INT_FAST16_WIDTH__ 16 744 | #endif /* !__INT_FAST16_WIDTH__ */ 745 | #ifndef __INT_FAST32_WIDTH__ 746 | #define __INT_FAST32_WIDTH__ 32 747 | #endif /* !__INT_FAST32_WIDTH__ */ 748 | #ifndef __INT_FAST64_WIDTH__ 749 | #define __INT_FAST64_WIDTH__ 64 750 | #endif /* !__INT_FAST64_WIDTH__ */ 751 | #ifndef __INTPTR_WIDTH__ 752 | #define __INTPTR_WIDTH__ TPP_MUL8(__SIZEOF_POINTER__) 753 | #endif /* !__INTPTR_WIDTH__ */ 754 | #ifndef __INTMAX_WIDTH__ 755 | #define __INTMAX_WIDTH__ 64 756 | #endif /* !__INTMAX_WIDTH__ */ 757 | 758 | #ifndef __SIZE_TYPE__ 759 | #define __SIZE_TYPE__ TPP_UINTTYPE(__SIZEOF_POINTER__) 760 | #endif /* !__SIZE_TYPE__ */ 761 | #ifndef __PTRDIFF_TYPE__ 762 | #define __PTRDIFF_TYPE__ TPP_INTTYPE(__SIZEOF_POINTER__) 763 | #endif /* !__PTRDIFF_TYPE__ */ 764 | #ifndef __WCHAR_TYPE__ 765 | #define __WCHAR_TYPE__ wchar_t 766 | #endif /* !__WCHAR_TYPE__ */ 767 | #ifndef __WINT_TYPE__ 768 | #define __WINT_TYPE__ int 769 | #endif /* !__WINT_TYPE__ */ 770 | #ifndef __INTMAX_TYPE__ 771 | #define __INTMAX_TYPE__ __INT64_TYPE__ 772 | #endif /* !__INTMAX_TYPE__ */ 773 | #ifndef __UINTMAX_TYPE__ 774 | #define __UINTMAX_TYPE__ __UINT64_TYPE__ 775 | #endif /* !__UINTMAX_TYPE__ */ 776 | #ifndef __SIG_ATOMIC_TYPE__ 777 | #define __SIG_ATOMIC_TYPE__ int 778 | #endif /* !__SIG_ATOMIC_TYPE__ */ 779 | #ifndef __INT_LEAST8_TYPE__ 780 | #define __INT_LEAST8_TYPE__ __INT8_TYPE__ 781 | #endif /* !__INT_LEAST8_TYPE__ */ 782 | #ifndef __INT_LEAST16_TYPE__ 783 | #define __INT_LEAST16_TYPE__ __INT16_TYPE__ 784 | #endif /* !__INT_LEAST16_TYPE__ */ 785 | #ifndef __INT_LEAST32_TYPE__ 786 | #define __INT_LEAST32_TYPE__ __INT32_TYPE__ 787 | #endif /* !__INT_LEAST32_TYPE__ */ 788 | #ifndef __INT_LEAST64_TYPE__ 789 | #define __INT_LEAST64_TYPE__ __INT64_TYPE__ 790 | #endif /* !__INT_LEAST64_TYPE__ */ 791 | #ifndef __UINT_LEAST8_TYPE__ 792 | #define __UINT_LEAST8_TYPE__ __UINT8_TYPE__ 793 | #endif /* !__UINT_LEAST8_TYPE__ */ 794 | #ifndef __UINT_LEAST16_TYPE__ 795 | #define __UINT_LEAST16_TYPE__ __UINT16_TYPE__ 796 | #endif /* !__UINT_LEAST16_TYPE__ */ 797 | #ifndef __UINT_LEAST32_TYPE__ 798 | #define __UINT_LEAST32_TYPE__ __UINT32_TYPE__ 799 | #endif /* !__UINT_LEAST32_TYPE__ */ 800 | #ifndef __UINT_LEAST64_TYPE__ 801 | #define __UINT_LEAST64_TYPE__ __UINT64_TYPE__ 802 | #endif /* !__UINT_LEAST64_TYPE__ */ 803 | #ifndef __INT_FAST8_TYPE__ 804 | #define __INT_FAST8_TYPE__ __INT8_TYPE__ 805 | #endif /* !__INT_FAST8_TYPE__ */ 806 | #ifndef __INT_FAST16_TYPE__ 807 | #define __INT_FAST16_TYPE__ __INT16_TYPE__ 808 | #endif /* !__INT_FAST16_TYPE__ */ 809 | #ifndef __INT_FAST32_TYPE__ 810 | #define __INT_FAST32_TYPE__ __INT32_TYPE__ 811 | #endif /* !__INT_FAST32_TYPE__ */ 812 | #ifndef __INT_FAST64_TYPE__ 813 | #define __INT_FAST64_TYPE__ __INT64_TYPE__ 814 | #endif /* !__INT_FAST64_TYPE__ */ 815 | #ifndef __UINT_FAST8_TYPE__ 816 | #define __UINT_FAST8_TYPE__ __UINT8_TYPE__ 817 | #endif /* !__UINT_FAST8_TYPE__ */ 818 | #ifndef __UINT_FAST16_TYPE__ 819 | #define __UINT_FAST16_TYPE__ __UINT16_TYPE__ 820 | #endif /* !__UINT_FAST16_TYPE__ */ 821 | #ifndef __UINT_FAST32_TYPE__ 822 | #define __UINT_FAST32_TYPE__ __UINT32_TYPE__ 823 | #endif /* !__UINT_FAST32_TYPE__ */ 824 | #ifndef __UINT_FAST64_TYPE__ 825 | #define __UINT_FAST64_TYPE__ __UINT64_TYPE__ 826 | #endif /* !__UINT_FAST64_TYPE__ */ 827 | #ifndef __INTPTR_TYPE__ 828 | #define __INTPTR_TYPE__ __PTRDIFF_TYPE__ 829 | #endif /* !__INTPTR_TYPE__ */ 830 | #ifndef __UINTPTR_TYPE__ 831 | #define __UINTPTR_TYPE__ __SIZE_TYPE__ 832 | #endif /* !__UINTPTR_TYPE__ */ 833 | #endif /* !TPP_UTILITY_MACROS_DEFINED */ 834 | 835 | #if (defined(__LP64__) || defined(_LP64)) || \ 836 | (__SIZEOF_INT__ == 4 && __SIZEOF_LONG__ == 8 && __SIZEOF_POINTER__ == 8) 837 | PREDEFINED_MACRO_IF(__LP64__, HAS(EXT_SYSTEM_MACROS), "1") 838 | #endif 839 | 840 | PREDEFINED_MACRO_IF(__BYTE_ORDER__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(TPP_BYTEORDER)) 841 | #ifdef __FLOAT_WORD_ORDER__ 842 | PREDEFINED_MACRO_IF(__FLOAT_WORD_ORDER__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__FLOAT_WORD_ORDER__)) 843 | #else /* __FLOAT_WORD_ORDER__ */ 844 | PREDEFINED_MACRO_IF(__FLOAT_WORD_ORDER__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(TPP_BYTEORDER)) 845 | #endif /* !__FLOAT_WORD_ORDER__ */ 846 | PREDEFINED_MACRO_IF(__ORDER_LITTLE_ENDIAN__, HAS(EXT_UTILITY_MACROS), "1234") 847 | PREDEFINED_MACRO_IF(__ORDER_BIG_ENDIAN__, HAS(EXT_UTILITY_MACROS), "4321") 848 | PREDEFINED_MACRO_IF(__ORDER_PDP_ENDIAN__, HAS(EXT_UTILITY_MACROS), "3412") 849 | 850 | PREDEFINED_MACRO_IF(__SIZEOF_INT__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_INT__)) 851 | PREDEFINED_MACRO_IF(__SIZEOF_LONG__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_LONG__)) 852 | PREDEFINED_MACRO_IF(__SIZEOF_LONG_LONG__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_LONG_LONG__)) 853 | PREDEFINED_MACRO_IF(__SIZEOF_SHORT__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_SHORT__)) 854 | PREDEFINED_MACRO_IF(__SIZEOF_POINTER__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_POINTER__)) 855 | PREDEFINED_MACRO_IF(__SIZEOF_FLOAT__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_FLOAT__)) 856 | PREDEFINED_MACRO_IF(__SIZEOF_DOUBLE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_DOUBLE__)) 857 | PREDEFINED_MACRO_IF(__SIZEOF_LONG_DOUBLE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_LONG_DOUBLE__)) 858 | PREDEFINED_MACRO_IF(__SIZEOF_SIZE_T__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_SIZE_T__)) 859 | PREDEFINED_MACRO_IF(__SIZEOF_WCHAR_T__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_WCHAR_T__)) 860 | PREDEFINED_MACRO_IF(__SIZEOF_WINT_T__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_WINT_T__)) 861 | PREDEFINED_MACRO_IF(__SIZEOF_PTRDIFF_T__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZEOF_PTRDIFF_T__)) 862 | 863 | PREDEFINED_MACRO_IF(__SCHAR_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SCHAR_WIDTH__)) 864 | PREDEFINED_MACRO_IF(__SHRT_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SHRT_WIDTH__)) 865 | PREDEFINED_MACRO_IF(__INT_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_WIDTH__)) 866 | PREDEFINED_MACRO_IF(__LONG_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__LONG_WIDTH__)) 867 | PREDEFINED_MACRO_IF(__LONG_LONG_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__LONG_LONG_WIDTH__)) 868 | PREDEFINED_MACRO_IF(__PTRDIFF_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__PTRDIFF_WIDTH__)) 869 | PREDEFINED_MACRO_IF(__SIG_ATOMIC_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIG_ATOMIC_WIDTH__)) 870 | PREDEFINED_MACRO_IF(__SIZE_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZE_WIDTH__)) 871 | PREDEFINED_MACRO_IF(__WCHAR_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__WCHAR_WIDTH__)) 872 | PREDEFINED_MACRO_IF(__WINT_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__WINT_WIDTH__)) 873 | PREDEFINED_MACRO_IF(__INT_LEAST8_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST8_WIDTH__)) 874 | PREDEFINED_MACRO_IF(__INT_LEAST16_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST16_WIDTH__)) 875 | PREDEFINED_MACRO_IF(__INT_LEAST32_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST32_WIDTH__)) 876 | PREDEFINED_MACRO_IF(__INT_LEAST64_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST64_WIDTH__)) 877 | PREDEFINED_MACRO_IF(__INT_FAST8_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST8_WIDTH__)) 878 | PREDEFINED_MACRO_IF(__INT_FAST16_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST16_WIDTH__)) 879 | PREDEFINED_MACRO_IF(__INT_FAST32_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST32_WIDTH__)) 880 | PREDEFINED_MACRO_IF(__INT_FAST64_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST64_WIDTH__)) 881 | PREDEFINED_MACRO_IF(__INTPTR_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INTPTR_WIDTH__)) 882 | PREDEFINED_MACRO_IF(__INTMAX_WIDTH__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INTMAX_WIDTH__)) 883 | 884 | PREDEFINED_MACRO_IF(__SIZE_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIZE_TYPE__)) 885 | PREDEFINED_MACRO_IF(__PTRDIFF_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__PTRDIFF_TYPE__)) 886 | PREDEFINED_MACRO_IF(__WCHAR_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__WCHAR_TYPE__)) 887 | PREDEFINED_MACRO_IF(__WINT_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__WINT_TYPE__)) 888 | PREDEFINED_MACRO_IF(__INTMAX_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INTMAX_TYPE__)) 889 | PREDEFINED_MACRO_IF(__UINTMAX_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINTMAX_TYPE__)) 890 | PREDEFINED_MACRO_IF(__SIG_ATOMIC_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__SIG_ATOMIC_TYPE__)) 891 | PREDEFINED_MACRO_IF(__INT8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT8_TYPE__)) 892 | PREDEFINED_MACRO_IF(__INT16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT16_TYPE__)) 893 | PREDEFINED_MACRO_IF(__INT32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT32_TYPE__)) 894 | PREDEFINED_MACRO_IF(__INT64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT64_TYPE__)) 895 | PREDEFINED_MACRO_IF(__UINT8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT8_TYPE__)) 896 | PREDEFINED_MACRO_IF(__UINT16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT16_TYPE__)) 897 | PREDEFINED_MACRO_IF(__UINT32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT32_TYPE__)) 898 | PREDEFINED_MACRO_IF(__UINT64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT64_TYPE__)) 899 | PREDEFINED_MACRO_IF(__INT_LEAST8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST8_TYPE__)) 900 | PREDEFINED_MACRO_IF(__INT_LEAST16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST16_TYPE__)) 901 | PREDEFINED_MACRO_IF(__INT_LEAST32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST32_TYPE__)) 902 | PREDEFINED_MACRO_IF(__INT_LEAST64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_LEAST64_TYPE__)) 903 | PREDEFINED_MACRO_IF(__UINT_LEAST8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_LEAST8_TYPE__)) 904 | PREDEFINED_MACRO_IF(__UINT_LEAST16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_LEAST16_TYPE__)) 905 | PREDEFINED_MACRO_IF(__UINT_LEAST32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_LEAST32_TYPE__)) 906 | PREDEFINED_MACRO_IF(__UINT_LEAST64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_LEAST64_TYPE__)) 907 | PREDEFINED_MACRO_IF(__INT_FAST8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST8_TYPE__)) 908 | PREDEFINED_MACRO_IF(__INT_FAST16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST16_TYPE__)) 909 | PREDEFINED_MACRO_IF(__INT_FAST32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST32_TYPE__)) 910 | PREDEFINED_MACRO_IF(__INT_FAST64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INT_FAST64_TYPE__)) 911 | PREDEFINED_MACRO_IF(__UINT_FAST8_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_FAST8_TYPE__)) 912 | PREDEFINED_MACRO_IF(__UINT_FAST16_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_FAST16_TYPE__)) 913 | PREDEFINED_MACRO_IF(__UINT_FAST32_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_FAST32_TYPE__)) 914 | PREDEFINED_MACRO_IF(__UINT_FAST64_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINT_FAST64_TYPE__)) 915 | PREDEFINED_MACRO_IF(__INTPTR_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__INTPTR_TYPE__)) 916 | PREDEFINED_MACRO_IF(__UINTPTR_TYPE__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__UINTPTR_TYPE__)) 917 | 918 | #ifdef __CHAR_BIT__ 919 | PREDEFINED_MACRO_IF(__CHAR_BIT__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__CHAR_BIT__)) 920 | #elif defined(CHAR_BIT) 921 | PREDEFINED_MACRO_IF(__CHAR_BIT__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(CHAR_BIT)) 922 | #else 923 | PREDEFINED_MACRO_IF(__CHAR_BIT__, HAS(EXT_UTILITY_MACROS), "8") 924 | #endif 925 | 926 | PREDEFINED_MACRO_IF(__SCHAR_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(SCHAR_MAX)) 927 | PREDEFINED_MACRO_IF(__WCHAR_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(WCHAR_MAX)) 928 | PREDEFINED_MACRO_IF(__SHRT_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(SHRT_MAX)) 929 | PREDEFINED_MACRO_IF(__INT_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_MAX)) 930 | PREDEFINED_MACRO_IF(__LONG_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(LONG_MAX)) 931 | #ifdef __LONG_LONG_MAX__ 932 | PREDEFINED_MACRO_IF(__LONG_LONG_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(__LONG_LONG_MAX__)) 933 | #elif defined(LONG_LONG_MAX) 934 | PREDEFINED_MACRO_IF(__LONG_LONG_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(LONG_LONG_MAX)) 935 | #else 936 | PREDEFINED_MACRO_IF(__LONG_LONG_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(LLONG_MAX)) 937 | #endif 938 | PREDEFINED_MACRO_IF(__WINT_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(WINT_MAX)) 939 | PREDEFINED_MACRO_IF(__SIZE_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(SIZE_MAX)) 940 | PREDEFINED_MACRO_IF(__PTRDIFF_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(PTRDIFF_MAX)) 941 | PREDEFINED_MACRO_IF(__INTMAX_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INTMAX_MAX)) 942 | PREDEFINED_MACRO_IF(__UINTMAX_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINTMAX_MAX)) 943 | PREDEFINED_MACRO_IF(__SIG_ATOMIC_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(SIG_ATOMIC_MAX)) 944 | PREDEFINED_MACRO_IF(__INT8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT8_MAX)) 945 | PREDEFINED_MACRO_IF(__INT16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT16_MAX)) 946 | PREDEFINED_MACRO_IF(__INT32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT32_MAX)) 947 | PREDEFINED_MACRO_IF(__INT64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT64_MAX)) 948 | PREDEFINED_MACRO_IF(__UINT8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT8_MAX)) 949 | PREDEFINED_MACRO_IF(__UINT16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT16_MAX)) 950 | PREDEFINED_MACRO_IF(__UINT32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT32_MAX)) 951 | PREDEFINED_MACRO_IF(__UINT64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT64_MAX)) 952 | PREDEFINED_MACRO_IF(__INT_LEAST8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_LEAST8_MAX)) 953 | PREDEFINED_MACRO_IF(__INT_LEAST16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_LEAST16_MAX)) 954 | PREDEFINED_MACRO_IF(__INT_LEAST32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_LEAST32_MAX)) 955 | PREDEFINED_MACRO_IF(__INT_LEAST64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_LEAST64_MAX)) 956 | PREDEFINED_MACRO_IF(__UINT_LEAST8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_LEAST8_MAX)) 957 | PREDEFINED_MACRO_IF(__UINT_LEAST16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_LEAST16_MAX)) 958 | PREDEFINED_MACRO_IF(__UINT_LEAST32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_LEAST32_MAX)) 959 | PREDEFINED_MACRO_IF(__UINT_LEAST64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_LEAST64_MAX)) 960 | PREDEFINED_MACRO_IF(__INT_FAST8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_FAST8_MAX)) 961 | PREDEFINED_MACRO_IF(__INT_FAST16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_FAST16_MAX)) 962 | PREDEFINED_MACRO_IF(__INT_FAST32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_FAST32_MAX)) 963 | PREDEFINED_MACRO_IF(__INT_FAST64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INT_FAST64_MAX)) 964 | PREDEFINED_MACRO_IF(__UINT_FAST8_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_FAST8_MAX)) 965 | PREDEFINED_MACRO_IF(__UINT_FAST16_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_FAST16_MAX)) 966 | PREDEFINED_MACRO_IF(__UINT_FAST32_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_FAST32_MAX)) 967 | PREDEFINED_MACRO_IF(__UINT_FAST64_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINT_FAST64_MAX)) 968 | PREDEFINED_MACRO_IF(__INTPTR_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(INTPTR_MAX)) 969 | PREDEFINED_MACRO_IF(__UINTPTR_MAX__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(UINTPTR_MAX)) 970 | PREDEFINED_MACRO_IF(__WCHAR_MIN__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(WCHAR_MIN)) 971 | PREDEFINED_MACRO_IF(__WINT_MIN__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(WINT_MIN)) 972 | PREDEFINED_MACRO_IF(__SIG_ATOMIC_MIN__, HAS(EXT_UTILITY_MACROS), TPP_PP_STR(SIG_ATOMIC_MIN)) 973 | 974 | DEF_M_IF(__INT8_C, HAS(EXT_UTILITY_MACROS)) 975 | DEF_M_IF(__INT16_C, HAS(EXT_UTILITY_MACROS)) 976 | DEF_M_IF(__INT32_C, HAS(EXT_UTILITY_MACROS)) 977 | DEF_M_IF(__INT64_C, HAS(EXT_UTILITY_MACROS)) 978 | DEF_M_IF(__UINT8_C, HAS(EXT_UTILITY_MACROS)) 979 | DEF_M_IF(__UINT16_C, HAS(EXT_UTILITY_MACROS)) 980 | DEF_M_IF(__UINT32_C, HAS(EXT_UTILITY_MACROS)) 981 | DEF_M_IF(__UINT64_C, HAS(EXT_UTILITY_MACROS)) 982 | DEF_M_IF(__INTMAX_C, HAS(EXT_UTILITY_MACROS)) 983 | DEF_M_IF(__UINTMAX_C, HAS(EXT_UTILITY_MACROS)) 984 | 985 | PREDEFINED_MACRO_IF(__CHAR_UNSIGNED__, 986 | HAS(EXT_UTILITY_MACROS) && (TPPLexer_Current->l_flags & TPPLEXER_FLAG_CHAR_UNSIGNED), "1") 987 | PREDEFINED_MACRO_IF(__WCHAR_UNSIGNED__, HAS(EXT_UTILITY_MACROS), "1") /* xxx: flag? */ 988 | 989 | #undef TPP_PP_CAT3 990 | #undef TPP_PP_CAT2 991 | #undef TPP_PRIVATE_PP_CAT3 992 | #undef TPP_PRIVATE_PP_CAT2 993 | -------------------------------------------------------------------------------- /test/_runall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$(readlink -f "$0")")/.." 4 | TPP="$(pwd)/bin/tpp" 5 | if [[ -f "${TPP}.exe" ]]; then TPP="${TPP}.exe"; fi 6 | TPP="$TPP -P -Werror" 7 | 8 | # testFile 9 | testFile() { 10 | echo "Running: $TPP -fno-spc -fno-lf $1" 11 | $TPP -fno-spc -fno-lf "$1" || { 12 | error="$?" 13 | echo "Command failed: '$TPP -fno-spc -fno-lf $1' -> '$error'" 14 | exit $error 15 | } 16 | echo "Running: $TPP $1" 17 | $TPP "$1" > /dev/null || { 18 | error="$?" 19 | echo "Command failed: '$TPP $1' -> '$error'" 20 | exit $error 21 | } 22 | } 23 | 24 | cd "test" 25 | for file in *.h; do 26 | testFile "$file" 27 | done 28 | 29 | # This test requires some special care as it relates to relative includes 30 | cd inner 31 | testFile "test.h" 32 | cd .. 33 | -------------------------------------------------------------------------------- /test/arguments_as_macro.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define args 10,20,30 23 | #define func(a,b,c) a+b+c 24 | 25 | #pragma warning("-Wmacros") 26 | #if !__has_warning("-Wmacros") 27 | #error "Should now be enabled" 28 | #endif 29 | #pragma warning("-Wsup-macros") 30 | #if __has_warning("-Wmacros") 31 | #error "Should now be suppressed (once)" 32 | #endif 33 | 34 | /* E0105("-Wmacros"): Not enough enough arguments for `func' */ 35 | /* NOTE: Expands to: 36 | * >> [func][(][args][)] 37 | * >> [args][+][][+][] 38 | * >> [10][,][20][,][30][+][+] */ 39 | TEST_EXPANDS(func(args), "10,20,30++") 40 | 41 | #if !__has_warning("-Wmacros") 42 | #error "Should have been triggered" 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /test/clone_linefeed.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // Copy Line-feeds 23 | 24 | #define clone(...) __VA_ARGS__ __VA_ARGS__ 25 | TEST_EXPANDS( 26 | clone({ 27 | int x = 42; 28 | }) 29 | , "{\n int x = 42;\n} {\n int x = 42;\n}") 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/count_tokens.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | TEST_EXPANDS(__TPP_COUNT_TOKENS(""), "0") 23 | TEST_EXPANDS(__TPP_COUNT_TOKENS("foo"), "1") 24 | TEST_EXPANDS(__TPP_COUNT_TOKENS("foo+"), "2") 25 | TEST_EXPANDS(__TPP_COUNT_TOKENS("foo[]"), "3") 26 | -------------------------------------------------------------------------------- /test/cxx_comments_in_macro.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define foo(a) [a] // Comment 23 | 24 | #define expand2(x) x 25 | #define expand(x) expand2(x) 26 | 27 | //FIXME:TEST_EXPANDS(expand(foo(10)), "[10]") 28 | 29 | -------------------------------------------------------------------------------- /test/define_directives.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define define undef 23 | 24 | TEST_EXPANDS(FOOBAR, "FOOBAR") 25 | #define FOOBAR 42 26 | TEST_EXPANDS(FOOBAR, "42") 27 | TEST_EXPANDS(define FOOBAR 42, "undef 42 42") 28 | #undef FOOBAR 29 | #undef define 30 | TEST_EXPANDS(define FOOBAR 42, "define FOOBAR 42") 31 | 32 | -------------------------------------------------------------------------------- /test/directives_in_macros.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* Preprocessor blocks within macro arguments */ 23 | 24 | TEST_EXPANDS( 25 | #if 0 26 | Stuff in the middle 27 | #endif 28 | , "") 29 | 30 | TEST_EXPANDS( 31 | #if 1 32 | Stuff in the middle 33 | #endif 34 | , "Stuff in the middle") 35 | 36 | #define NARGS(...) __VA_NARGS__ 37 | 38 | TEST_EXPANDS(NARGS( 39 | #if 0 40 | a 41 | #endif 42 | ), "1") 43 | 44 | TEST_EXPANDS(NARGS( 45 | #if 0 46 | a 47 | #endif 48 | b 49 | ), "1") 50 | 51 | TEST_EXPANDS(NARGS( 52 | b 53 | #if 0 54 | a 55 | #endif 56 | ), "1") 57 | 58 | TEST_EXPANDS(NARGS( 59 | #if 1 60 | a 61 | #endif 62 | ), "1") 63 | 64 | #define EAT(...) __pragma(tpp_exec(#__VA_ARGS__)) 65 | #define EXPAND_HIDDEN(a, b) EAT(a, b) 66 | 67 | PRAGMA_WARNING_PUSH_SUPPRESS("syntax") 68 | EXPAND_HIDDEN( 69 | a 70 | #if 0 /* E0032("-Wsyntax"): #if without #endif */ 71 | , 72 | PRAGMA_WARNING_POP_SUPPRESS("syntax") 73 | PRAGMA_WARNING_PUSH_SUPPRESS("syntax") /* Supress again for 2nd syntax error */ 74 | #endif /* E0033("-Wsyntax"): #endif without #if */ 75 | b 76 | ) 77 | PRAGMA_WARNING_POP_SUPPRESS("syntax") 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /test/directives_start_of_line.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // ISO/IEC 9899:201x - 6.10 - 8 23 | 24 | #define EMPTY 25 | TEST_EXPANDS( 26 | EMPTY # include // Expands to [#][include][<][file][.][h][>] 27 | , "# include ") 28 | 29 | #undef EMPTY 30 | TEST_EXPANDS( 31 | EMPTY # include // Expands to [EMPTY][#][include][<][file][.][h][>] 32 | , "EMPTY # include ") 33 | 34 | -------------------------------------------------------------------------------- /test/double_counter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | 23 | /* Make sure that macro-arguments who's representation differs 24 | * every time they are expanded (such as __COUNTER__) are only 25 | * expanded _ONCE_ when used multiple times within the same 26 | * function-like macro */ 27 | #define SAME(x) TEST_ASSERT(x == x) 28 | SAME(__COUNTER__) 29 | 30 | /* Still make sure that `__COUNTER__' changes every time, though... */ 31 | TEST_ASSERT(__COUNTER__ != __COUNTER__) 32 | -------------------------------------------------------------------------------- /test/glue.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #if 0 23 | #define hash_hash # ## # 24 | #else 25 | // NOTE: NON-Standard: 26 | // - TPP only allows macro function 27 | // arguments as operands for the ## operator: 28 | // ## 29 | // - and must both be a keyword (or number, if __TPP_VERSION__ >= 102) 30 | // - or must be a macro function argument 31 | #define GLUE(a,b) a ## b 32 | #define hash_hash GLUE(#,#) 33 | #endif 34 | #define mkstr(a) # a 35 | #define in_between(a) mkstr(a) 36 | #define join(c, d) in_between(c hash_hash d) 37 | 38 | TEST_EXPANDS(char p[] = join(x, y);, "char p[] = \"x ## y\";") 39 | 40 | 41 | -------------------------------------------------------------------------------- /test/has_include.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define DOUBLE_ASSERT(x) TEST_ASSERT(x) TEST_ASSERT(x) 23 | 24 | TEST_ASSERT(__has_include("has_include.h")) 25 | TEST_ASSERT(__has_include("has_include.h")) 26 | TEST_ASSERT(!__has_include("NOPE")) 27 | TEST_ASSERT(!__has_include("./NOPE.h")) 28 | TEST_ASSERT(__has_include("./has_include.h")) 29 | TEST_ASSERT(__has_include("../test/has_include.h")) 30 | TEST_ASSERT(__has_include("does_exist/../has_include.h")) 31 | DOUBLE_ASSERT(!__has_include("./NOPE.h")) 32 | DOUBLE_ASSERT(__has_include("./has_include.h")) 33 | -------------------------------------------------------------------------------- /test/include/def.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | 21 | #define ITS_A_SECRET "no it isn't" 22 | 23 | -------------------------------------------------------------------------------- /test/include/test.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | 21 | #define TEST_STR2(...) #__VA_ARGS__ 22 | #define TEST_STR(...) TEST_STR2(__VA_ARGS__) 23 | #ifndef __pragma 24 | #define __pragma(...) _Pragma(TEST_STR2(__VA_ARGS__)) 25 | #endif /* !__pragma */ 26 | #define TEST_PRINT(...) __pragma(message(__VA_ARGS__)) 27 | 28 | #define _TEST_ASSERT_0(msg) __pragma(error(__FILE__ "(" TEST_STR(__LINE__) ") : Assertion failed: '" msg "'")) 29 | #define _TEST_ASSERT_1(msg) /* Success */ 30 | #define _TEST_ASSERT2(expr, msg) _TEST_ASSERT_##expr(msg) 31 | #define _TEST_ASSERT(expr, msg) _TEST_ASSERT2(expr, msg) 32 | #define TEST_ASSERT(expr) _TEST_ASSERT(__TPP_EVAL(!!(expr)), #expr) 33 | 34 | #define TEST_EXPANDS(text, to) \ 35 | TEST_PRINT("\tTesting: expands: " #to) \ 36 | _TEST_ASSERT(__TPP_EVAL(TEST_STR2(text) == to), "\n\tWanted: " #to "\n\tGot: " TEST_STR(TEST_STR2(text))) 37 | 38 | #define PRAGMA_WARNING_PUSH_SUPPRESS(name) \ 39 | __pragma(warning(push, "-W" name)) \ 40 | TEST_ASSERT(__has_warning("-W" name)) \ 41 | __pragma(warning("-Wsup-" name)) \ 42 | TEST_ASSERT(!__has_warning("-W" name)) 43 | #define PRAGMA_WARNING_POP_SUPPRESS(name) \ 44 | TEST_ASSERT(__has_warning("-W" name)) \ 45 | __pragma(warning(pop)) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /test/include_path.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #pragma once 23 | 24 | #ifdef WAS_HERE 25 | #error "Shouldn't have gotten here more than once!" 26 | #endif 27 | #define WAS_HERE 28 | 29 | /* include ourselves with some really abstract path. 30 | * #pragma once will prevent infinite recursion */ 31 | #include "include_path.h" 32 | #include "./include_path.h" 33 | 34 | //FIXME:#include "./../test/include_path.h" 35 | //FIXME:#include "./../test/include_path.h" 36 | //FIXME:#include "./../test/./missing_folder/../include_path.h" 37 | -------------------------------------------------------------------------------- /test/inner/test.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | 21 | #ifdef ITS_A_SECRET 22 | #error "How?" 23 | #endif 24 | 25 | #include "../../test/include/def.h" 26 | 27 | #ifndef ITS_A_SECRET 28 | #error "Wrong file included?" 29 | #endif 30 | #undef ITS_A_SECRET 31 | 32 | #include "./../../test/include/def.h" 33 | 34 | #ifndef ITS_A_SECRET 35 | #error "Wrong file included?" 36 | #endif 37 | -------------------------------------------------------------------------------- /test/macro-argument-whitespace.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* Test the effects of the "macro-argument-whitespace" extension. */ 23 | 24 | #define STR1(x) #x 25 | #pragma extension(push, "-fmacro-argument-whitespace") 26 | #define STR2(x) #x 27 | #pragma extension(pop) 28 | 29 | TEST_EXPANDS(STR1(foo), "\"foo\"") 30 | TEST_EXPANDS(STR1( foo ), "\"foo\"") 31 | TEST_EXPANDS(STR2(foo), "\"foo\"") 32 | TEST_EXPANDS(STR2( foo ), "\" foo \"") 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/macro_call_conv.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // Macro calling conventions 23 | 24 | #define angle +x- 25 | #define brace{x} +x- 26 | #define bracket[x] +x- 27 | #define paren(x) +x- // Original (Unchanged) 28 | 29 | TEST_EXPANDS(angle<<>>, "+<>-") 30 | //angle<<<>> // ERROR: EOF in macro argument list 31 | TEST_EXPANDS(angle<{<}>, "+{<}-") 32 | TEST_EXPANDS(angle<[<]>, "+[<]-") 33 | TEST_EXPANDS(angle<(<)>, "+(<)-") 34 | TEST_EXPANDS(angle<{>}>, "+{>}-") 35 | TEST_EXPANDS(angle<[>]>, "+[>]-") 36 | TEST_EXPANDS(angle<(>)>, "+(>)-") 37 | //brace{<{>} // ERROR: EOF in macro argument list 38 | //brace{{{}} // ERROR: EOF in macro argument list 39 | TEST_EXPANDS(brace{[{]}, "+[{]-") 40 | TEST_EXPANDS(brace{({)}, "+({)-") 41 | TEST_EXPANDS(brace{[}]}, "+[}]-") 42 | TEST_EXPANDS(brace{(})}, "+(})-") 43 | //bracket[<[>] // ERROR: EOF in macro argument list 44 | //bracket[{[}] // ERROR: EOF in macro argument list 45 | //bracket[[[]] // ERROR: EOF in macro argument list 46 | TEST_EXPANDS(bracket[([)], "+([)-") 47 | TEST_EXPANDS(bracket[(])], "+(])-") 48 | //paren(<(>) // ERROR: EOF in macro argument list 49 | //paren({(}) // ERROR: EOF in macro argument list 50 | //paren([(]) // ERROR: EOF in macro argument list 51 | //paren((()) // ERROR: EOF in macro argument list 52 | 53 | #define map_node struct{K key; T value;} 54 | #define point struct{T x; T y;} 55 | TEST_EXPANDS(point> x;, "struct{struct{int x; int y;} x; struct{int x; int y;} y;} x;") 56 | TEST_EXPANDS((map_node e;), "(struct{std::string key; int value;} e;)") 57 | 58 | #define __TPP_ARGS(...) (__VA_ARGS__)) 59 | #define static_cast<...> ((__VA_ARGS__)__TPP_ARGS 60 | 61 | TEST_EXPANDS(int x = static_cast(100l);, "int x = ((int)(100l));") 62 | 63 | -------------------------------------------------------------------------------- /test/macro_escape_lf.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // Test 18: Macros with escaped line feeds 23 | 24 | #define macro \ 25 | code... \ 26 | /**/ 27 | #define func(a,b,c) \ 28 | a + b + c \ 29 | /**/ 30 | 31 | TEST_EXPANDS(macro,"code...") 32 | TEST_EXPANDS(func(10,20,30),"10 + 20 + 30") 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/null_directive.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | # 23 | # 24 | # 25 | # /* Some Null directives */ 26 | # // Some Null directives 27 | # 28 | # 29 | # 30 | 31 | # 32 | #! Also this type of NULL-directive (for Hash-Bang compatibility) 33 | # 34 | 35 | -------------------------------------------------------------------------------- /test/pound_xclaim.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define STR(x) #x 23 | #define WARP0(x) STR(x) 24 | #define WARP1(x) STR(#!x) 25 | 26 | #define FOO 42 27 | 28 | TEST_EXPANDS(WARP0(FOO), "\"42\"") 29 | TEST_EXPANDS(WARP1(FOO), "\"FOO\"") 30 | 31 | -------------------------------------------------------------------------------- /test/prevent_macro_expansion.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // Prevent macro expansion 23 | 24 | #define PREVENT_EXP_KWD 25 | #define PREVENT_EXP_FNC() 26 | #define min(a,b) ((a) < (b) ? (a) : (b)) 27 | 28 | TEST_EXPANDS(int min PREVENT_EXP_KWD (int,int);, "int min (int,int);") 29 | TEST_EXPANDS(int min PREVENT_EXP_FNC() (int,int);, "int min (int,int);") 30 | 31 | TEST_EXPANDS(int min(int,int);, "int ((int) < (int) ? (int) : (int));") 32 | -------------------------------------------------------------------------------- /test/push_pop_macro.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // #pragma push_macro 23 | 24 | TEST_EXPANDS(int *a = new int();, "int *a = new int();") 25 | #define new __debug_new 26 | TEST_EXPANDS(int *b = new int();, "int *b = __debug_new int();") 27 | #pragma push_macro("new") 28 | #undef new 29 | #define new __alt_default_new 30 | TEST_EXPANDS(int *c = new int();, "int *c = __alt_default_new int();") 31 | #pragma pop_macro("new") 32 | TEST_EXPANDS(int *d = new int();, "int *d = __debug_new int();") 33 | TEST_EXPANDS(int *e = new int();, "int *e = __debug_new int();") 34 | #undef new 35 | TEST_EXPANDS(int *f = new int();, "int *f = new int();") 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /test/quotes_in_error.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | TEST_EXPANDS(BEFORE, "BEFORE") 23 | 24 | #if 0 25 | 26 | #error An incomplete " in a disabled #error directive 27 | #error An incomplete ' in a disabled #error directive 28 | #error An incomplete """ in a disabled #error directive 29 | #error An incomplete ''' in a disabled #error directive 30 | 31 | #else 32 | 33 | #pragma warning(push, "-Wno-user") /* Hide warnings */ 34 | #warning An incomplete " in an enabled #warning directive 35 | #warning An incomplete " in an enabled #warning directive 36 | #warning An incomplete " in an enabled #warning directive 37 | #warning An incomplete ' in an enabled #warning directive 38 | #warning An incomplete ' in an enabled #warning directive 39 | #warning An incomplete ' in an enabled #warning directive 40 | #warning An incomplete ' in an enabled #warning directive 41 | #pragma warning(pop) 42 | 43 | #endif 44 | 45 | TEST_EXPANDS(AFTER, "AFTER") 46 | -------------------------------------------------------------------------------- /test/self_redef.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define REDEF(m, b) __pragma(tpp_exec("#undef " #m "\n#define " #m " " #b)) 23 | #define Word w1 24 | #define w1 REDEF(Word, w2)Hello 25 | #define w2 REDEF(Word, w3)There 26 | #define w3 REDEF(Word, w4)Good 27 | #define w4 REDEF(Word, w1)Sir! 28 | 29 | TEST_EXPANDS(Word Word Word Word, "Hello There Good Sir!") 30 | TEST_EXPANDS(Word, "Hello") 31 | TEST_EXPANDS(Word, "There") 32 | TEST_EXPANDS(Word, "Good") 33 | TEST_EXPANDS(Word, "Sir!") 34 | TEST_EXPANDS(Word Word, "Hello There") 35 | TEST_EXPANDS(Word Word, "Good Sir!") 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/stdc_6.10.3.5_5.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // ISO/IEC 9899:201x - 6.10.3.5 - 5 23 | 24 | #define x 3 25 | #define f(a) f(x * (a)) 26 | #undef x 27 | #define x 2 28 | #define g f 29 | #define z z[0] 30 | #define h g(~ 31 | #define m(a) a(w) 32 | #define w 0,1 33 | #define t(a) a 34 | #define p() int 35 | #define q(x) x 36 | #define r(x,y) x ## y 37 | #define str(x) # x 38 | 39 | /* z gets expanded multiple times (see "pp_fixme.h") */ 40 | TEST_EXPANDS(f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);, 41 | "f(2 * (y+1)) + f(2 * (f(2 * (z[0][0][0])))) % f(2 * (2 * (0))) + t(1);") 42 | 43 | /* EOF in macro argument list (see "pp_unsupported.h") */ 44 | //TEST_EXPANDS(g(x+(3,4)-w) | h 5) & m, "f(2 * (2+(3,4)-0,1)) | f(2 * (~)) 5") 45 | 46 | TEST_EXPANDS((f)^m(m);, "(f)^m(0,1);") 47 | 48 | TEST_EXPANDS((p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };), 49 | "(int i[] = { 1, 23, 4, 5, };)") 50 | TEST_EXPANDS((char c[2][6] = { str(hello), str() };), 51 | "(char c[2][6] = { \"hello\", \"\" };)") 52 | 53 | -------------------------------------------------------------------------------- /test/stdc_6.10.3.5_6.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* ISO/IEC 9899:201x - 6.10.3.5 - 6 */ 23 | 24 | 25 | #define str(s) # s 26 | #define xstr(s) str(s) 27 | #define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ 28 | x##s,x##t) 29 | #define INCFILE(n) vers ## n 30 | #define glue(a, b) a ## b 31 | #define xglue(a, b) glue(a, b) 32 | #define HIGHLOW "hello" 33 | #define LOW LOW ", world" 34 | TEST_EXPANDS(debug(1, 2);, "printf(\"x\" \"1\" \"= %d, x\" \"2\" \"= %s\", \\\nx1,x2);") 35 | TEST_EXPANDS(fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away 36 | == 0) str(: @\n), s);, 37 | "fputs(\"strncmp(\\\"abc\\\\0d\\\", \\\"abc\\\", " 38 | "\\\'\\\\4\\\') // this goes away\\n== 0\" \": @\\\\n\", s);") 39 | 40 | #pragma warning(push) 41 | #pragma warning(disable:15) /* File not found */ 42 | TEST_EXPANDS(xstr(INCFILE(2).h), "\"vers2.h\"") 43 | #include xstr(INCFILE(2).h) 44 | #pragma warning(pop) 45 | 46 | TEST_EXPANDS(glue(HIGH, LOW);, "\"hello\";") 47 | TEST_EXPANDS(xglue(HIGH, LOW), "\"hello\" \", world\"") 48 | 49 | 50 | -------------------------------------------------------------------------------- /test/stdc_6.10.3.5_7.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // ISO/IEC 9899:201x - 6.10.3.5 - 7 23 | 24 | #define t(x,y,z) x ## y ## z 25 | TEST_EXPANDS((int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };), 26 | "(int j[] = { 123, 45, 67, 89, 10, 11, 12, };)") 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/stdc_6.10.3.5_9.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // ISO/IEC 9899:201x - 6.10.3.5 - 9 23 | 24 | #define debug(...) fprintf(stderr, __VA_ARGS__) 25 | #define debug2(...) fprintf(stderr, ##__VA_ARGS__) 26 | #define showlist(...) puts(#__VA_ARGS__) 27 | #define report(test, ...) ((test)?puts(#test):\ 28 | printf(__VA_ARGS__)) 29 | TEST_EXPANDS(debug();, "fprintf(stderr, );") 30 | TEST_EXPANDS(debug2();, "fprintf(stderr);") 31 | TEST_EXPANDS(debug("Flag");, "fprintf(stderr, \"Flag\");") 32 | TEST_EXPANDS(debug2("Flag");, "fprintf(stderr,\"Flag\");") 33 | TEST_EXPANDS(debug("X = %d\n", x);, "fprintf(stderr, \"X = %d\\n\", x);") 34 | TEST_EXPANDS(showlist(The first, second, and third items.);, "puts(\"The first, second, and third items.\");") 35 | TEST_EXPANDS(report(x>y, "x is %d but y is %d", x, y);, "((x>y)?puts(\"x>y\"): printf(\"x is %d but y is %d\", x, y));") 36 | 37 | -------------------------------------------------------------------------------- /test/stdc_6.10.3_5+6.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // ISO/IEC 9899:201x - 6.10.3 - 5 + 6 23 | 24 | // ISO/IEC 9899:201x - 6.10.3 - 5 25 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 26 | #define VARARGS(__VA_ARGS__) __VA_ARGS__ /* Warning: __VA_ARGS__ used as argument name */ 27 | PRAGMA_WARNING_POP_SUPPRESS("macros") 28 | TEST_EXPANDS(VARARGS(foo), "foo") 29 | #undef VARARGS 30 | 31 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 32 | #define VARARGS(__VA_COMMA__) __VA_COMMA__ /* Warning: __VA_COMMA__ used as argument name */ 33 | PRAGMA_WARNING_POP_SUPPRESS("macros") 34 | TEST_EXPANDS(VARARGS(foo), "foo") 35 | #undef VARARGS 36 | 37 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 38 | #define VARARGS(__VA_OPT__) __VA_OPT__ /* Warning: __VA_OPT__ used as argument name */ 39 | PRAGMA_WARNING_POP_SUPPRESS("macros") 40 | TEST_EXPANDS(VARARGS(foo), "foo") 41 | #undef VARARGS 42 | 43 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 44 | #define VARARGS(__VA_NARGS__) __VA_NARGS__ /* Warning: __VA_NARGS__ used as argument name */ 45 | PRAGMA_WARNING_POP_SUPPRESS("macros") 46 | TEST_EXPANDS(VARARGS(foo), "foo") 47 | #undef VARARGS 48 | 49 | // ISO/IEC 9899:201x - 6.10.3 - 6 50 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 51 | #define ARG_NAMES(a,b,c,a) a+b+c+a /* Warning: Parameter name "a" reused */ 52 | PRAGMA_WARNING_POP_SUPPRESS("macros") 53 | TEST_EXPANDS(ARG_NAMES(10,20,30), "10+20+30+10") 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /test/strings_in_expressions.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* TPP Allows for use of strings in #if directives (as well as `__TPP_EVAL') */ 23 | TEST_EXPANDS(__TPP_EVAL('F'), "70") 24 | TEST_EXPANDS(__TPP_EVAL("FOO"[0]), "70") 25 | TEST_EXPANDS(__TPP_EVAL("FOO"[0:]), "\"FOO\"") 26 | TEST_EXPANDS(__TPP_EVAL("FOO"[1:]), "\"OO\"") 27 | TEST_EXPANDS(__TPP_EVAL("FOO"[0:1]), "\"F\"") 28 | TEST_EXPANDS(__TPP_EVAL("FOO"[0:2]), "\"FO\"") 29 | TEST_EXPANDS(__TPP_EVAL("FOO"[0:-1]), "\"FO\"") 30 | TEST_EXPANDS(__TPP_EVAL("FOO"[:-1]), "\"FO\"") 31 | TEST_EXPANDS(__TPP_EVAL("FOO"[1:-1]), "\"O\"") 32 | TEST_EXPANDS(__TPP_EVAL("FOO" == "BAR"), "0") 33 | TEST_EXPANDS(__TPP_EVAL("FOO" != "BAR"), "1") 34 | TEST_EXPANDS(__TPP_EVAL("FOO" == "FOO"), "1") 35 | TEST_EXPANDS(__TPP_EVAL("FOO" == "foo"), "0") 36 | 37 | /* TPP Also allows for use of GCC-style __builtin_* functions 38 | * in #if directives. (and therefor also in `__TPP_EVAL') */ 39 | TEST_EXPANDS(__TPP_EVAL(__builtin_strcmp("FOO", "foo") < 0), "1") 40 | TEST_EXPANDS(__TPP_EVAL(__builtin_strcmp("FOO", "foo") > 0), "0") 41 | TEST_EXPANDS(__TPP_EVAL(__builtin_strcmp("foo", "FOO") < 0), "0") 42 | TEST_EXPANDS(__TPP_EVAL(__builtin_strcmp("foo", "FOO") > 0), "1") 43 | TEST_EXPANDS(__TPP_EVAL(__builtin_strcasecmp("FOO", "foo")), "0") 44 | 45 | TEST_EXPANDS(__TPP_EVAL(__builtin_ffs(0x123)), "1") 46 | TEST_EXPANDS(__TPP_EVAL(__builtin_ffs(0x100)), "9") 47 | 48 | /* Multi-char character literals. */ 49 | TEST_EXPANDS(__TPP_EVAL('a'), "97") 50 | TEST_EXPANDS(__TPP_EVAL('ab'), "25185") 51 | TEST_EXPANDS(__TPP_EVAL('abc'), "6513249") 52 | 53 | 54 | #define CAT2(a, b) a##b 55 | #define CAT(a, b) CAT2(a, b) 56 | #define ISLESS_0 more than 57 | #define ISLESS_1 less than 58 | #define SELECT(n) CAT(ISLESS_, __TPP_EVAL(n < 10)) 59 | TEST_EXPANDS(SELECT(7), "less than") 60 | TEST_EXPANDS(SELECT(10), "more than") 61 | 62 | TEST_EXPANDS(__TPP_STR_PACK(0x48, 0x65, 0x6c, 0x6c, 0x6f), "\"Hello\"") 63 | -------------------------------------------------------------------------------- /test/tpp_exec.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* TPP Includes a builtin `#pragma tpp_exec("foo")' that can be used 23 | * to run preprocessor text whilst discarding all produced output. 24 | * 25 | * Using this, macros are able to (re-)define other macros, or even 26 | * themselves! */ 27 | 28 | 29 | /* Use __pragma(tpp_exec()) to delete a macro while it's being expanded. 30 | * This used to fail due to a problem relating to recursive parenthesis 31 | * tracking failing to skip the trailing `)' in `__pragma(tpp_exec(...))' */ 32 | #define foo(x) x 33 | TEST_EXPANDS(foo(10 __pragma(tpp_exec("#undef foo")) 20), "10 20") 34 | TEST_EXPANDS(foo(10 __pragma(tpp_exec("#undef foo")) 20), "foo(10 20)") 35 | TEST_EXPANDS(foo(10 __pragma(tpp_exec("#undef foo")) 20), "foo(10 20)") 36 | TEST_EXPANDS(foo(10 __pragma(tpp_exec("#undef foo")) 20), "foo(10 20)") 37 | 38 | #define foo(x) x 39 | TEST_EXPANDS(foo(10 _Pragma("tpp_exec(\"#undef foo\")") 20), "10 20") 40 | TEST_EXPANDS(foo(10 _Pragma("tpp_exec(\"#undef foo\")") 20), "foo(10 20)") 41 | TEST_EXPANDS(foo(10 _Pragma("tpp_exec(\"#undef foo\")") 20), "foo(10 20)") 42 | TEST_EXPANDS(foo(10 _Pragma("tpp_exec(\"#undef foo\")") 20), "foo(10 20)") 43 | 44 | 45 | #define HACK_COUNTER_VALUE 0 46 | #define STR2(x) #x 47 | #define STR(x) STR2(x) 48 | #define HACK_COUNTER \ 49 | HACK_COUNTER_VALUE \ 50 | __pragma(tpp_exec( \ 51 | "#undef HACK_COUNTER_VALUE\n" \ 52 | "#define HACK_COUNTER_VALUE " STR(__TPP_EVAL(HACK_COUNTER_VALUE + 1)) "\n" \ 53 | )) 54 | 55 | TEST_EXPANDS(HACK_COUNTER_VALUE, "0") 56 | TEST_EXPANDS(HACK_COUNTER_VALUE, "0") 57 | TEST_EXPANDS(HACK_COUNTER, "0") 58 | TEST_EXPANDS(HACK_COUNTER, "1") 59 | TEST_EXPANDS(HACK_COUNTER, "2") 60 | TEST_EXPANDS(HACK_COUNTER, "3") 61 | TEST_EXPANDS(HACK_COUNTER_VALUE, "4") 62 | 63 | /* When `HACK_COUNTER' isn't actually expanded, then the tpp_exec 64 | * code mustn't get executed (since it's skipped in its entirety). 65 | * Assert this fact! */ 66 | #define HIDE(x) 67 | HIDE(HACK_COUNTER) 68 | HIDE(HACK_COUNTER) 69 | HIDE(HACK_COUNTER) 70 | 71 | TEST_EXPANDS(HACK_COUNTER_VALUE, "4") 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /test/traditional_macros.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define CAT(a,b) a ## b 23 | #define STR(x) #x 24 | 25 | /* Enabling "-ftraditional-macro" alters macro definitions 26 | * to follow more ~traditional~ expansion rules. */ 27 | #pragma extension(push, "-ftraditional-macro") 28 | #define T_CAT(a, b) a/**/b 29 | #define T_STR(x) "x" 30 | #pragma extension(pop) 31 | 32 | #define N_CAT(a, b) a/**/b 33 | #define N_STR(x) "x" 34 | 35 | TEST_EXPANDS(CAT(10, 20), "1020") 36 | TEST_EXPANDS(STR(10), "\"10\"") 37 | TEST_EXPANDS(T_CAT(10, 20), "1020") 38 | TEST_EXPANDS(T_STR(10), "\"10\"") 39 | TEST_EXPANDS(N_CAT(10, 20), "10/**/20") 40 | TEST_EXPANDS(N_STR(10), "\"x\"") 41 | -------------------------------------------------------------------------------- /test/undef_current_macro.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* This used to cause TPP to crash, but has since been fixed */ 23 | #define foo(x) x 24 | foo(__pragma(tpp_exec("#undef foo\n"))) 25 | -------------------------------------------------------------------------------- /test/undef_macro_cexpr.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // #undef macro in constant expression 23 | 24 | #pragma warning("-Wundef") 25 | 26 | #undef FOOBAR 27 | PRAGMA_WARNING_PUSH_SUPPRESS("undef") 28 | #if FOOBAR // WARNING: Unexpected token "FOOBAR" replaced with "0" 29 | #endif 30 | PRAGMA_WARNING_POP_SUPPRESS("undef") 31 | 32 | #if defined(FOOBAR2) && never // Shouldn't result in a warning 33 | #endif 34 | #if 0 && ladidadida // Shouldn't result in a warning 35 | #endif 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/user_error.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | /* Both #warning and #error directives should produce -Wuser warnings. 23 | * Note that despite the name, `#error' still produces a warning, only 24 | * that this warning is normally set-up to be fatal, whilst #warning 25 | * is normally set-up to be non-fatal. */ 26 | PRAGMA_WARNING_PUSH_SUPPRESS("user") 27 | #warning User Warning 28 | PRAGMA_WARNING_POP_SUPPRESS("user") 29 | 30 | PRAGMA_WARNING_PUSH_SUPPRESS("user") 31 | #error User Error 32 | PRAGMA_WARNING_POP_SUPPRESS("user") 33 | 34 | -------------------------------------------------------------------------------- /test/varargs_empty.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define foo(a, ...) a(__VA_ARGS__) 23 | 24 | TEST_EXPANDS(foo(), "()") 25 | TEST_EXPANDS(foo( ), "()") 26 | TEST_EXPANDS(foo(func), "func()") 27 | TEST_EXPANDS(foo(func,), "func()") 28 | TEST_EXPANDS(foo(func, ), "func()") 29 | TEST_EXPANDS(foo(func,b), "func(b)") 30 | TEST_EXPANDS(foo(func, b ), "func(b)") 31 | 32 | -------------------------------------------------------------------------------- /test/varargs_named.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // named_va_args 23 | 24 | #define named_varargs(args...) args 25 | TEST_EXPANDS(named_varargs(),"") 26 | TEST_EXPANDS(named_varargs(,),",") 27 | TEST_EXPANDS(named_varargs(10),"10") 28 | TEST_EXPANDS(named_varargs(10,20),"10,20") 29 | -------------------------------------------------------------------------------- /test/varargs_va_comma.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | // Function-style macro calling and argument count 23 | 24 | #define arg0() - 25 | #define arg1(a) a 26 | #define arg2(a,b) a##b 27 | #define varg0(...) __VA_ARGS__ 28 | #define varg1(a,...) a##__VA_ARGS__ 29 | #define varg2(a,b,...) a##b##__VA_ARGS__ 30 | #define vcarg0(...) __VA_COMMA__ __VA_ARGS__ __VA_COMMA__ 31 | #define vcarg1(a,...) __VA_COMMA__ a##__VA_ARGS__ __VA_COMMA__ 32 | #define vcarg2(a,b,...) __VA_COMMA__ a##b##__VA_ARGS__ __VA_COMMA__ 33 | 34 | // NOTE: Space tokens [ ] are not included in the expansion comments 35 | TEST_EXPANDS(arg0(),"-") // OK 36 | 37 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 38 | TEST_EXPANDS(arg0(a),"-") // WARNING: Invalid argument count (expected 0) 39 | PRAGMA_WARNING_POP_SUPPRESS("macros") 40 | 41 | TEST_EXPANDS(arg1(),"") // OK 42 | TEST_EXPANDS(arg1(a),"a") // OK 43 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 44 | TEST_EXPANDS(arg1(a,b),"a,b") // WARNING: Invalid argument count (expected 1) 45 | PRAGMA_WARNING_POP_SUPPRESS("macros") 46 | 47 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 48 | TEST_EXPANDS(arg1(,),",") // WARNING: Invalid argument count (expected 1) 49 | PRAGMA_WARNING_POP_SUPPRESS("macros") 50 | 51 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 52 | TEST_EXPANDS(arg2(a),"a") // WARNING: Invalid argument count (expected 2) 53 | PRAGMA_WARNING_POP_SUPPRESS("macros") 54 | 55 | TEST_EXPANDS(arg2(a,),"a") // OK 56 | TEST_EXPANDS(arg2(,),"") // OK 57 | TEST_EXPANDS(arg2(a,b),"ab") // OK 58 | 59 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 60 | TEST_EXPANDS(arg2(,,),",") // WARNING: Invalid argument count (expected 2) 61 | PRAGMA_WARNING_POP_SUPPRESS("macros") 62 | 63 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 64 | TEST_EXPANDS(arg2(a,b,c),"ab,c") // WARNING: Invalid argument count (expected 2) 65 | PRAGMA_WARNING_POP_SUPPRESS("macros") 66 | 67 | TEST_EXPANDS(varg0(),"") // OK 68 | TEST_EXPANDS(varg0(a),"a") // OK 69 | TEST_EXPANDS(varg0(a,),"a,") // OK 70 | TEST_EXPANDS(varg0(,),",") // OK 71 | TEST_EXPANDS(varg0(a,b),"a,b") // OK 72 | TEST_EXPANDS(vcarg0(),"") // OK 73 | TEST_EXPANDS(vcarg0(a),", a ,") // OK 74 | TEST_EXPANDS(vcarg0(a,),", a, ,") // OK 75 | TEST_EXPANDS(vcarg0(,),", , ,") // OK 76 | TEST_EXPANDS(vcarg0(a,b),", a,b ,") // OK 77 | TEST_EXPANDS(varg1(),"") // OK 78 | TEST_EXPANDS(varg1(a),"a") // OK 79 | TEST_EXPANDS(varg1(a,),"a") // OK 80 | TEST_EXPANDS(varg1(,),"") // OK 81 | TEST_EXPANDS(varg1(a,b),"ab") // OK 82 | TEST_EXPANDS(vcarg1(),"") // OK 83 | TEST_EXPANDS(vcarg1(a),"a") // OK 84 | TEST_EXPANDS(vcarg1(a,),"a") // OK 85 | TEST_EXPANDS(vcarg1(,),"") // OK 86 | TEST_EXPANDS(vcarg1(a,b),", ab ,") // OK 87 | 88 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 89 | TEST_EXPANDS(varg2(a),"a") // WARNING: Invalid argument count (expected >= 2) 90 | PRAGMA_WARNING_POP_SUPPRESS("macros") 91 | 92 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 93 | TEST_EXPANDS(varg2(),"") // WARNING: Invalid argument count (expected >= 2) 94 | PRAGMA_WARNING_POP_SUPPRESS("macros") 95 | 96 | TEST_EXPANDS(varg2(a,),"a") // OK 97 | TEST_EXPANDS(varg2(,),"") // OK 98 | TEST_EXPANDS(varg2(a,b),"ab") // OK 99 | 100 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 101 | TEST_EXPANDS(vcarg2(),"") // WARNING: Invalid argument count (expected >= 2) 102 | PRAGMA_WARNING_POP_SUPPRESS("macros") 103 | 104 | PRAGMA_WARNING_PUSH_SUPPRESS("macros") 105 | TEST_EXPANDS(vcarg2(a),"a") // WARNING: Invalid argument count (expected >= 2) 106 | PRAGMA_WARNING_POP_SUPPRESS("macros") 107 | 108 | TEST_EXPANDS(vcarg2(a,),"a") // OK 109 | TEST_EXPANDS(vcarg2(,),"") // OK 110 | TEST_EXPANDS(vcarg2(a,b),"ab") // OK 111 | 112 | -------------------------------------------------------------------------------- /test/varargs_va_nargs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define nargs(...) __VA_NARGS__ 23 | 24 | /* __VA_NARGS__ expands to the decimal repr of the # of variadic arguments */ 25 | TEST_EXPANDS(nargs(), "0") 26 | TEST_EXPANDS(nargs( ), "0") 27 | TEST_EXPANDS(nargs(~), "1") 28 | TEST_EXPANDS(nargs(,), "2") 29 | TEST_EXPANDS(nargs(a,), "2") 30 | TEST_EXPANDS(nargs(a,b), "2") 31 | 32 | 33 | /* Using __VA_NARGS__, you can _very_ easily overload macros by argument count! */ 34 | #define myfunc_0() no arguments 35 | #define myfunc_1(a) first argument is 36 | #define myfunc_2(a, b) first argument: ; and second is 37 | #define myfunc(...) myfunc_##__VA_NARGS__(__VA_ARGS__) 38 | 39 | TEST_EXPANDS(myfunc(), "no arguments") 40 | TEST_EXPANDS(myfunc( ), "no arguments") 41 | TEST_EXPANDS(myfunc("Hello"), "first argument is <\"Hello\">") 42 | TEST_EXPANDS(myfunc("Hello", "World"), "first argument: <\"Hello\">; and second is <\"World\">") 43 | 44 | #define nargs1(a, ...) a __VA_NARGS__ 45 | TEST_EXPANDS(nargs1(), "0") 46 | TEST_EXPANDS(nargs1( ), "0") 47 | TEST_EXPANDS(nargs1(~), "~ 0") 48 | TEST_EXPANDS(nargs1(,), "0") 49 | TEST_EXPANDS(nargs1(, ), "0") 50 | TEST_EXPANDS(nargs1(a,), "a 0") 51 | TEST_EXPANDS(nargs1(a,b), "a 1") 52 | 53 | -------------------------------------------------------------------------------- /test/varargs_va_opt.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017-2023 Griefer@Work * 2 | * * 3 | * This software is provided 'as-is', without any express or implied * 4 | * warranty. In no event will the authors be held liable for any damages * 5 | * arising from the use of this software. * 6 | * * 7 | * Permission is granted to anyone to use this software for any purpose, * 8 | * including commercial applications, and to alter it and redistribute it * 9 | * freely, subject to the following restrictions: * 10 | * * 11 | * 1. The origin of this software must not be misrepresented; you must not * 12 | * claim that you wrote the original software. If you use this software * 13 | * in a product, an acknowledgement (see the following) in the product * 14 | * documentation is required: * 15 | * Portions Copyright (c) 2017-2023 Griefer@Work * 16 | * 2. Altered source versions must be plainly marked as such, and must not be * 17 | * misrepresented as being the original software. * 18 | * 3. This notice may not be removed or altered from any source distribution. * 19 | */ 20 | #include "include/test.h" 21 | 22 | #define foo(...) a __VA_OPT__ (b) c 23 | 24 | TEST_EXPANDS(foo(), "a c") 25 | TEST_EXPANDS(foo( ), "a c") 26 | TEST_EXPANDS(foo(a), "a b c") 27 | 28 | --------------------------------------------------------------------------------