xref: /netbsd-src/tests/usr.bin/indent/lsym_preprocessing.c (revision 95820b5370230cc0c1b63cb504d714d2aa7f7b4a)
1*95820b53Srillig /* $NetBSD: lsym_preprocessing.c,v 1.15 2023/06/16 23:19:01 rillig Exp $ */
29ae26de1Srillig 
39ae26de1Srillig /*
49ae26de1Srillig  * Tests for the token lsym_preprocessing, which represents a '#' that starts
59ae26de1Srillig  * a preprocessing line.
69ae26de1Srillig  *
7b60cb68fSrillig  * #define
8b60cb68fSrillig  * #ifdef
9b60cb68fSrillig  * #include
10b60cb68fSrillig  * #line
11b60cb68fSrillig  * #pragma
12b60cb68fSrillig  *
139ae26de1Srillig  * The whole preprocessing line is processed separately from the main source
149ae26de1Srillig  * code, without much tokenizing or parsing.
159ae26de1Srillig  */
169ae26de1Srillig 
179ae26de1Srillig // TODO: test '#' in the middle of a non-preprocessing line
189ae26de1Srillig // TODO: test stringify '#'
199ae26de1Srillig // TODO: test token paste '##'
209ae26de1Srillig 
2147306038Srillig //indent input
229ae26de1Srillig // TODO: add input
2347306038Srillig //indent end
249ae26de1Srillig 
2547306038Srillig //indent run-equals-input
2695e11159Srillig 
2795e11159Srillig 
2895e11159Srillig /*
2995e11159Srillig  * Whitespace in the following preprocessing directives is preserved.
3095e11159Srillig  */
3147306038Srillig //indent input
3295e11159Srillig #define space ' '		/* the 'define' is followed by a space */
3395e11159Srillig #define	tab '\t'		/* the 'define' is followed by a tab */
3495e11159Srillig #if   0				/* 3 spaces */
3595e11159Srillig #elif		0		/* 2 tabs */
3695e11159Srillig #elif	0	>	1	/* tabs between the tokens */
3795e11159Srillig #endif
3847306038Srillig //indent end
3995e11159Srillig 
4047306038Srillig //indent run-equals-input
4195e11159Srillig 
4295e11159Srillig // TODO: #define unfinished_string "...
4395e11159Srillig // TODO: #define unfinished_char '...
4495e11159Srillig // TODO: # 123 "file.h"
4595e11159Srillig // TODO: backslash-newline
4695e11159Srillig // TODO: block comment
4795e11159Srillig // TODO: line comment
48b60cb68fSrillig 
49b60cb68fSrillig 
50b60cb68fSrillig //indent input
51b60cb68fSrillig #include <system-header.h>
52b60cb68fSrillig #include "local-header.h"
53b60cb68fSrillig //indent end
54b60cb68fSrillig 
55b60cb68fSrillig //indent run-equals-input
56b60cb68fSrillig 
57b60cb68fSrillig 
58b60cb68fSrillig /*
59b60cb68fSrillig  * Nested conditional compilation.
60b60cb68fSrillig  */
61b60cb68fSrillig //indent input
62b60cb68fSrillig #if 0
63b60cb68fSrillig #else
64b60cb68fSrillig #endif
65b60cb68fSrillig 
66b60cb68fSrillig #if 0 /* if comment */
67b60cb68fSrillig #else /* else comment */
68b60cb68fSrillig #endif /* endif comment */
69b60cb68fSrillig 
70b60cb68fSrillig #if 0 /* outer if comment */
71b60cb68fSrillig #  if nested /* inner if comment */
72b60cb68fSrillig #  else /* inner else comment */
73b60cb68fSrillig #  endif /* inner endif comment */
74b60cb68fSrillig #endif /* outer endif comment */
75b60cb68fSrillig //indent end
76b60cb68fSrillig 
7738caea9bSrillig //indent run-equals-input
78b60cb68fSrillig 
79b60cb68fSrillig 
80b60cb68fSrillig //indent input
81b60cb68fSrillig #define multi_line_definition /* first line
82b60cb68fSrillig  * middle
83b60cb68fSrillig  * final line
84b60cb68fSrillig  */ actual_value
85b60cb68fSrillig //indent end
86b60cb68fSrillig 
87b60cb68fSrillig //indent run-equals-input
88b60cb68fSrillig 
89b60cb68fSrillig 
90b60cb68fSrillig /*
91b60cb68fSrillig  * Before indent.c 1.129 from 2021-10-08, indent mistakenly interpreted quotes
92b60cb68fSrillig  * in comments as starting a string literal. The '"' in the comment started a
93b60cb68fSrillig  * string, the next '"' finished the string, and the following '/' '*' was
94b60cb68fSrillig  * interpreted as the beginning of a comment. This comment lasted until the
95b60cb68fSrillig  * next '*' '/', which in this test is another preprocessor directive, solely
96b60cb68fSrillig  * for symmetry.
97b60cb68fSrillig  *
98b60cb68fSrillig  * The effect was that the extra space after d2 was not formatted, as that
99b60cb68fSrillig  * line was considered part of the comment.
100b60cb68fSrillig  */
101b60cb68fSrillig //indent input
102b60cb68fSrillig #define comment_in_string_literal "/* no comment "
103b60cb68fSrillig int this_is_an_ordinary_line_again;
104b60cb68fSrillig 
105b60cb68fSrillig int d1 ;
106b60cb68fSrillig #define confuse_d /*"*/ "/*"
107b60cb68fSrillig int d2 ;
108b60cb68fSrillig #define resolve_d "*/"
109b60cb68fSrillig int d3 ;
110b60cb68fSrillig 
111b60cb68fSrillig int s1 ;
112b60cb68fSrillig #define confuse_s /*'*/ '/*'
113b60cb68fSrillig int s2 ;
114b60cb68fSrillig #define resolve_s '*/'
115b60cb68fSrillig int s3 ;
116b60cb68fSrillig //indent end
117b60cb68fSrillig 
118b60cb68fSrillig //indent run
119b60cb68fSrillig #define comment_in_string_literal "/* no comment "
120b60cb68fSrillig int		this_is_an_ordinary_line_again;
121b60cb68fSrillig 
122b60cb68fSrillig int		d1;
123b60cb68fSrillig #define confuse_d /*"*/ "/*"
124b60cb68fSrillig int		d2;
125b60cb68fSrillig #define resolve_d "*/"
126b60cb68fSrillig int		d3;
127b60cb68fSrillig 
128b60cb68fSrillig int		s1;
129b60cb68fSrillig #define confuse_s /*'*/ '/*'
130b60cb68fSrillig int		s2;
131b60cb68fSrillig #define resolve_s '*/'
132b60cb68fSrillig int		s3;
133b60cb68fSrillig //indent end
134b60cb68fSrillig 
135b60cb68fSrillig 
136b60cb68fSrillig /*
137b60cb68fSrillig  * A preprocessing directive inside an expression keeps the state about
138b60cb68fSrillig  * whether the next operator is unary or binary.
139b60cb68fSrillig  */
140b60cb68fSrillig //indent input
141b60cb68fSrillig int binary_plus = 3
142b60cb68fSrillig #define intermediate 1
143b60cb68fSrillig 	+4;
144b60cb68fSrillig int unary_plus =
145b60cb68fSrillig #define intermediate 1
146b60cb68fSrillig 	+ 4;
147b60cb68fSrillig //indent end
148b60cb68fSrillig 
149b60cb68fSrillig //indent run
150b60cb68fSrillig int		binary_plus = 3
151b60cb68fSrillig #define intermediate 1
152b60cb68fSrillig + 4;
153b60cb68fSrillig int		unary_plus =
154b60cb68fSrillig #define intermediate 1
155b60cb68fSrillig +4;
156b60cb68fSrillig //indent end
157b60cb68fSrillig 
158b60cb68fSrillig 
159b60cb68fSrillig /*
160b60cb68fSrillig  * Before io.c 1.135 from 2021-11-26, indent fixed malformed preprocessing
161b60cb68fSrillig  * lines that had arguments even though they shouldn't. It is not the task of
162b60cb68fSrillig  * an indenter to fix code, that's what a linter is for.
163b60cb68fSrillig  */
164b60cb68fSrillig //indent input
165b60cb68fSrillig #if 0
166b60cb68fSrillig #elif 1
167b60cb68fSrillig #else if 3
168b60cb68fSrillig #endif 0
169b60cb68fSrillig //indent end
170b60cb68fSrillig 
171b60cb68fSrillig //indent run-equals-input
172b60cb68fSrillig 
173b60cb68fSrillig 
174b60cb68fSrillig /*
175b60cb68fSrillig  * Existing comments are indented just like code comments.
176b60cb68fSrillig  *
177b60cb68fSrillig  * This means that the above wrong preprocessing lines (#else with argument)
178b60cb68fSrillig  * need to be fed through indent twice until they become stable. Since
179b60cb68fSrillig  * compilers issue warnings about these invalid lines, not much code still has
180b60cb68fSrillig  * these, making this automatic fix an edge case.
181b60cb68fSrillig  */
182b60cb68fSrillig //indent input
183b60cb68fSrillig #if 0		/* comment */
184b60cb68fSrillig #else		/* comment */
185b60cb68fSrillig #endif		/* comment */
186b60cb68fSrillig 
187b60cb68fSrillig #if 0/* comment */
188b60cb68fSrillig #else/* comment */
189b60cb68fSrillig #endif/* comment */
190b60cb68fSrillig //indent end
191b60cb68fSrillig 
192d5678748Srillig //indent run-equals-input
1935300eef1Srillig 
1945300eef1Srillig 
1955300eef1Srillig /*
1965300eef1Srillig  * Multi-line comments in preprocessing lines.
1975300eef1Srillig  */
1985300eef1Srillig //indent input
1995300eef1Srillig #define eol_comment		// EOL
2005300eef1Srillig 
201d5678748Srillig #define no_wrap_comment		/* line 1
2025300eef1Srillig 				 * line 2
2035300eef1Srillig 				 * line 3
2045300eef1Srillig 				 */
2055300eef1Srillig 
2065300eef1Srillig #define fixed_comment		/*- line 1
2075300eef1Srillig 				 * line 2
2085300eef1Srillig 				 * line 3
2095300eef1Srillig 				 */
210bacb7fc4Srillig 
211bacb7fc4Srillig #define two_comments /* 1 */ /* 2 */ /*3*/
212bacb7fc4Srillig #define three_comments		/* first */ /* second */ /*third*/
2135300eef1Srillig //indent end
2145300eef1Srillig 
215d5678748Srillig //indent run-equals-input
216bacb7fc4Srillig 
217bacb7fc4Srillig 
218bacb7fc4Srillig /*
219bacb7fc4Srillig  * Do not touch multi-line macro definitions.
220bacb7fc4Srillig  */
221bacb7fc4Srillig //indent input
222bacb7fc4Srillig #define do_once(stmt)		\
223bacb7fc4Srillig do {				\
224bacb7fc4Srillig 	stmt;			\
225bacb7fc4Srillig } while (/* constant condition */ false)
226bacb7fc4Srillig //indent end
227bacb7fc4Srillig 
228bacb7fc4Srillig //indent run-equals-input
22946afda16Srillig 
23046afda16Srillig 
23146afda16Srillig /*
23246afda16Srillig  * The 'INDENT OFF' state is global, it does not depend on the preprocessing
23346afda16Srillig  * directives, otherwise the declarations for 'on' and 'after' would be moved
23446afda16Srillig  * to column 1.
23546afda16Srillig  */
23646afda16Srillig //indent input
23746afda16Srillig int first_line;
23846afda16Srillig 	int before;
23946afda16Srillig #if 0
24046afda16Srillig /*INDENT OFF*/
24146afda16Srillig 	int off;
24246afda16Srillig #else
24346afda16Srillig 	int on;
24446afda16Srillig #endif
24546afda16Srillig 	int after;
24646afda16Srillig //indent end
24746afda16Srillig 
24846afda16Srillig //indent run -di0
24946afda16Srillig int first_line;
25046afda16Srillig int before;
25146afda16Srillig #if 0
25246afda16Srillig /*INDENT OFF*/
25346afda16Srillig 	int off;
25446afda16Srillig #else
25546afda16Srillig 	int on;
25646afda16Srillig #endif
25746afda16Srillig 	int after;
25846afda16Srillig //indent end
259d2103f1cSrillig 
260d2103f1cSrillig 
261d2103f1cSrillig /*
262d2103f1cSrillig  * Before 2023-06-14, indent was limited to 5 levels of conditional compilation
263d2103f1cSrillig  * directives.
264d2103f1cSrillig  */
265d2103f1cSrillig //indent input
266d2103f1cSrillig #if 1
267d2103f1cSrillig #if 2
268d2103f1cSrillig #if 3
269d2103f1cSrillig #if 4
270d2103f1cSrillig #if 5
271d2103f1cSrillig #if 6
272d2103f1cSrillig #endif 6
273d2103f1cSrillig #endif 5
274d2103f1cSrillig #endif 4
275d2103f1cSrillig #endif 3
276d2103f1cSrillig #endif 2
277d2103f1cSrillig #endif 1
278d2103f1cSrillig //indent end
279d2103f1cSrillig 
280d2103f1cSrillig //indent run-equals-input
281d2103f1cSrillig 
282d2103f1cSrillig 
283d2103f1cSrillig /*
284d2103f1cSrillig  * Unrecognized and unmatched preprocessing directives are preserved.
285d2103f1cSrillig  */
286d2103f1cSrillig //indent input
287d2103f1cSrillig #else
288d2103f1cSrillig #elif 0
289d2103f1cSrillig #elifdef var
290d2103f1cSrillig #endif
291d2103f1cSrillig 
292d2103f1cSrillig #unknown
293d2103f1cSrillig # 3 "file.c"
294d2103f1cSrillig //indent end
295d2103f1cSrillig 
296d2103f1cSrillig //indent run
297d2103f1cSrillig #else
298d2103f1cSrillig #elif 0
299d2103f1cSrillig #elifdef var
300d2103f1cSrillig #endif
301d2103f1cSrillig 
302d2103f1cSrillig #unknown
303d2103f1cSrillig # 3 "file.c"
304*95820b53Srillig // exit 1
305*95820b53Srillig // error: Standard Input:1: Unmatched #else
306*95820b53Srillig // error: Standard Input:2: Unmatched #elif
307*95820b53Srillig // error: Standard Input:3: Unmatched #elifdef
308*95820b53Srillig // error: Standard Input:4: Unmatched #endif
309d2103f1cSrillig //indent end
310940b8500Srillig 
311940b8500Srillig 
312940b8500Srillig /*
313940b8500Srillig  * The '#' can only occur at the beginning of a line, therefore indent does not
314940b8500Srillig  * care when it occurs in the middle of a line.
315940b8500Srillig  */
316940b8500Srillig //indent input
317940b8500Srillig int no = #;
318940b8500Srillig //indent end
319940b8500Srillig 
320940b8500Srillig //indent run -di0
321940b8500Srillig int no =
322940b8500Srillig #;
323940b8500Srillig //indent end
324940b8500Srillig 
325940b8500Srillig 
326940b8500Srillig /*
327940b8500Srillig  * Preprocessing directives may be indented; indent moves them to the beginning
328940b8500Srillig  * of a line.
329940b8500Srillig  */
330940b8500Srillig //indent input
331940b8500Srillig #if 0
332940b8500Srillig 	#if 1 \
333940b8500Srillig 	 || 2
334940b8500Srillig 	#endif
335940b8500Srillig #endif
336940b8500Srillig //indent end
337940b8500Srillig 
338940b8500Srillig //indent run
339940b8500Srillig #if 0
340940b8500Srillig #if 1 \
341940b8500Srillig 	 || 2
342940b8500Srillig #endif
343940b8500Srillig #endif
344940b8500Srillig //indent end
345