summaryrefslogtreecommitdiff
path: root/tests/usr.bin/indent/lsym_preprocessing.c
blob: 06a00fe42a5c8b8330be1debfdc276c4d66d7db0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/* $NetBSD: lsym_preprocessing.c,v 1.15 2023/06/16 23:19:01 rillig Exp $ */

/*
 * Tests for the token lsym_preprocessing, which represents a '#' that starts
 * a preprocessing line.
 *
 * #define
 * #ifdef
 * #include
 * #line
 * #pragma
 *
 * The whole preprocessing line is processed separately from the main source
 * code, without much tokenizing or parsing.
 */

// TODO: test '#' in the middle of a non-preprocessing line
// TODO: test stringify '#'
// TODO: test token paste '##'

//indent input
// TODO: add input
//indent end

//indent run-equals-input


/*
 * Whitespace in the following preprocessing directives is preserved.
 */
//indent input
#define space ' '		/* the 'define' is followed by a space */
#define	tab '\t'		/* the 'define' is followed by a tab */
#if   0				/* 3 spaces */
#elif		0		/* 2 tabs */
#elif	0	>	1	/* tabs between the tokens */
#endif
//indent end

//indent run-equals-input

// TODO: #define unfinished_string "...
// TODO: #define unfinished_char '...
// TODO: # 123 "file.h"
// TODO: backslash-newline
// TODO: block comment
// TODO: line comment


//indent input
#include <system-header.h>
#include "local-header.h"
//indent end

//indent run-equals-input


/*
 * Nested conditional compilation.
 */
//indent input
#if 0
#else
#endif

#if 0 /* if comment */
#else /* else comment */
#endif /* endif comment */

#if 0 /* outer if comment */
#  if nested /* inner if comment */
#  else /* inner else comment */
#  endif /* inner endif comment */
#endif /* outer endif comment */
//indent end

//indent run-equals-input


//indent input
#define multi_line_definition /* first line
 * middle
 * final line
 */ actual_value
//indent end

//indent run-equals-input


/*
 * Before indent.c 1.129 from 2021-10-08, indent mistakenly interpreted quotes
 * in comments as starting a string literal. The '"' in the comment started a
 * string, the next '"' finished the string, and the following '/' '*' was
 * interpreted as the beginning of a comment. This comment lasted until the
 * next '*' '/', which in this test is another preprocessor directive, solely
 * for symmetry.
 *
 * The effect was that the extra space after d2 was not formatted, as that
 * line was considered part of the comment.
 */
//indent input
#define comment_in_string_literal "/* no comment "
int this_is_an_ordinary_line_again;

int d1 ;
#define confuse_d /*"*/ "/*"
int d2 ;
#define resolve_d "*/"
int d3 ;

int s1 ;
#define confuse_s /*'*/ '/*'
int s2 ;
#define resolve_s '*/'
int s3 ;
//indent end

//indent run
#define comment_in_string_literal "/* no comment "
int		this_is_an_ordinary_line_again;

int		d1;
#define confuse_d /*"*/ "/*"
int		d2;
#define resolve_d "*/"
int		d3;

int		s1;
#define confuse_s /*'*/ '/*'
int		s2;
#define resolve_s '*/'
int		s3;
//indent end


/*
 * A preprocessing directive inside an expression keeps the state about
 * whether the next operator is unary or binary.
 */
//indent input
int binary_plus = 3
#define intermediate 1
	+4;
int unary_plus =
#define intermediate 1
	+ 4;
//indent end

//indent run
int		binary_plus = 3
#define intermediate 1
+ 4;
int		unary_plus =
#define intermediate 1
+4;
//indent end


/*
 * Before io.c 1.135 from 2021-11-26, indent fixed malformed preprocessing
 * lines that had arguments even though they shouldn't. It is not the task of
 * an indenter to fix code, that's what a linter is for.
 */
//indent input
#if 0
#elif 1
#else if 3
#endif 0
//indent end

//indent run-equals-input


/*
 * Existing comments are indented just like code comments.
 *
 * This means that the above wrong preprocessing lines (#else with argument)
 * need to be fed through indent twice until they become stable. Since
 * compilers issue warnings about these invalid lines, not much code still has
 * these, making this automatic fix an edge case.
 */
//indent input
#if 0		/* comment */
#else		/* comment */
#endif		/* comment */

#if 0/* comment */
#else/* comment */
#endif/* comment */
//indent end

//indent run-equals-input


/*
 * Multi-line comments in preprocessing lines.
 */
//indent input
#define eol_comment		// EOL

#define no_wrap_comment		/* line 1
				 * line 2
				 * line 3
				 */

#define fixed_comment		/*- line 1
				 * line 2
				 * line 3
				 */

#define two_comments /* 1 */ /* 2 */ /*3*/
#define three_comments		/* first */ /* second */ /*third*/
//indent end

//indent run-equals-input


/*
 * Do not touch multi-line macro definitions.
 */
//indent input
#define do_once(stmt)		\
do {				\
	stmt;			\
} while (/* constant condition */ false)
//indent end

//indent run-equals-input


/*
 * The 'INDENT OFF' state is global, it does not depend on the preprocessing
 * directives, otherwise the declarations for 'on' and 'after' would be moved
 * to column 1.
 */
//indent input
int first_line;
	int before;
#if 0
/*INDENT OFF*/
	int off;
#else
	int on;
#endif
	int after;
//indent end

//indent run -di0
int first_line;
int before;
#if 0
/*INDENT OFF*/
	int off;
#else
	int on;
#endif
	int after;
//indent end


/*
 * Before 2023-06-14, indent was limited to 5 levels of conditional compilation
 * directives.
 */
//indent input
#if 1
#if 2
#if 3
#if 4
#if 5
#if 6
#endif 6
#endif 5
#endif 4
#endif 3
#endif 2
#endif 1
//indent end

//indent run-equals-input


/*
 * Unrecognized and unmatched preprocessing directives are preserved.
 */
//indent input
#else
#elif 0
#elifdef var
#endif

#unknown
# 3 "file.c"
//indent end

//indent run
#else
#elif 0
#elifdef var
#endif

#unknown
# 3 "file.c"
// exit 1
// error: Standard Input:1: Unmatched #else
// error: Standard Input:2: Unmatched #elif
// error: Standard Input:3: Unmatched #elifdef
// error: Standard Input:4: Unmatched #endif
//indent end


/*
 * The '#' can only occur at the beginning of a line, therefore indent does not
 * care when it occurs in the middle of a line.
 */
//indent input
int no = #;
//indent end

//indent run -di0
int no =
#;
//indent end


/*
 * Preprocessing directives may be indented; indent moves them to the beginning
 * of a line.
 */
//indent input
#if 0
	#if 1 \
	 || 2
	#endif
#endif
//indent end

//indent run
#if 0
#if 1 \
	 || 2
#endif
#endif
//indent end