Name alx-0003r3 - Add directives #def and #enddef Category New directives. Author Alejandro Colomar Cc: Martin Uecker Cc: Joseph Myers Cc: Javier Múgica Cc: Ori Bernstein Cc: Christopher Bazley History r0 (2025-03-10): - Pick stuff from n1410. r1 (2025-03-11): - Fix typos. - Only allow conditional (and null) preprocessing directives within a replacement body. - Update wording regarding nesting with if sections. - Update wording that refers to replacement lists. Thanks to Joseph for the feedback that led to r1. r2 (2025-03-14): - Disallow all preprocessing directives within a replacement group. Make it equivalent to #define except for not needing the escape characters to use multiple source lines. This is the minimal feature, which makes sure we don't add an underdeveloped feature, but rather a scoped one. r3 (2025-03-19): - Define replacement-group directly in terms of pp-tokens, not in terms of replacement-list. Description One thing that gets in the way when writing and sharing macros is writing (and updating) the trailing \ at the end of each line. Multi-line macros could be defined with an end delimiter instead. That would also make syntax highlighting nicer. Here's the proposed syntax: #def foo(x) do { bar(x); baz(x); while (0) #enddef Proposed wording Based on N3467. 6.10.1 Preprocessing directives :: General @@ Syntax, p1 group-part: if-section + def-section control-line text-line # non-directive @@ p1, after endif-line +def-section: + def-line replacement-group(opt) enddef-line + +def-line: + # def identifier new-line + # def identifier lparen identifier-list(opt) ) new-line + # def identifier lparen ... ) new-line + # def identifier lparen identifier-list , ... ) new-line + +replacement-group: + pp-tokens(opt) new-line + replacement-group pp-tokens(opt) new-line + +enddef-line: + # enddef new-line 6.10.2 Conditional inclusion @@ Constraints, p4 (that is, if it is predefined or if it has been the subject of -a #define +a #define or #def preprocessing directive without an intervening #undef directive with the same subject identifier), 6.10.3 Source file inclusion s/replacement list/& or group/g 6.10.4 Binary resource inclusion s/replacement list/& or group/g 6.10.5.1 Macro replacement :: General @@ Constraints, p1 -Two replacement lists +Two replacement lists or groups are identical @@ p2 shall not be redefined -by another #define preprocessing directive +by another #define or #def preprocessing directive unless the second definition is an object-like macro definition -and the two replacement lists +and the two replacement lists or groups are identical. ... shall not be redefined -by another #define preprocessing directive +by another #define or #def preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, -and the two replacement lists +and the two replacement lists or groups are identical. @@ p5 The identifiers __VA_ARGS__ and __VA_OPT__ shall occur only in -the replacement-list +the replacement list or group of a function-like macro @@ Semantics, p7 The identifier immediately following the -define +define or def is called the macro name. ... Any white-space characters preceding or following -the replacement list +the replacement list or group of preprocessing tokens are not considered part of the replacement list or group for either form of macro. @@ p9 A preprocessing directive of the form # define identifier replacement-list new-line + # def identifier new-line ... to be replaced by -the replacement list +the replacement list or group of preprocessing tokens that constitute the remainder of the directive. -The replacement list +The replacement list or group is then rescanned for more macro names as specified later in this subclause. @@ p10 A preprocessing directive of the form # define identifier lparen identifier-list(opt) ) replacement-list new-line # define identifier lparen ... ) replacement-list new-line # define identifier lparen identifier-list , ... ) replacement-list new-line + # def identifier lparen identifier-list(opt) ) new-line + # def identifier lparen ... ) new-line + # def identifier lparen identifier-list , ... ) new-line ... until the new-line character -that terminates the #define preprocessing directive. +that terminates the #define preprocessing directive, +or until the enddef line +that terminates the #def preprocessing directive. Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by -the replacement list +the replacement list or group in the definition (an invocation of the macro). 6.10.5.2 Macro replacement :: Argument substitution s/replacement list/& or group/g 6.10.5.3 Macro replacement :: The # operator @@ Constraints, p1 Each # preprocessing token -in the replacement list +in the replacement list or group for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list. @@ Semantics, p2 If, -in the replacement list, +in the replacement list or group, a parameter is immediately preceded by a # preprocessing token, 6.10.5.4 Macro replacement :: The ## operator s/replacement list/& or group/g 6.10.5.5 Macro replacement :: Rescanning and further replacement s/replacement list/& or group/g 6.10.6 Line control s/replacement list/& or group/g 6.10.10.1 Predefined macro names :: General @@ p2 shall be the subject of -a #define or a #undef +a #define, #def, or #undef preprocessing directive. 7.28 Type-generic math @@ p14 (NOTE) - #define cbrt(X) \ - _Generic((X), \ - long double: _Roundwise_cbrtl, \ - default: _Roundwise_cbrt, \ - float: _Roundwise_cbrtf \ - )(X) + #def cbrt(X) + _Generic((X), + long double: _Roundwise_cbrtl, + default: _Roundwise_cbrt, + float: _Roundwise_cbrtf + )(X) + #enddef J.1 Unspecified behavior s/replacement list/& or group/g