11.15Srillig/* $NetBSD: lsym_preprocessing.c,v 1.15 2023/06/16 23:19:01 rillig Exp $ */
21.1Srillig
31.1Srillig/*
41.1Srillig * Tests for the token lsym_preprocessing, which represents a '#' that starts
51.1Srillig * a preprocessing line.
61.1Srillig *
71.5Srillig * #define
81.5Srillig * #ifdef
91.5Srillig * #include
101.5Srillig * #line
111.5Srillig * #pragma
121.5Srillig *
131.1Srillig * The whole preprocessing line is processed separately from the main source
141.1Srillig * code, without much tokenizing or parsing.
151.1Srillig */
161.1Srillig
171.1Srillig// TODO: test '#' in the middle of a non-preprocessing line
181.1Srillig// TODO: test stringify '#'
191.1Srillig// TODO: test token paste '##'
201.1Srillig
211.4Srillig//indent input
221.1Srillig// TODO: add input
231.4Srillig//indent end
241.1Srillig
251.4Srillig//indent run-equals-input
261.2Srillig
271.2Srillig
281.2Srillig/*
291.2Srillig * Whitespace in the following preprocessing directives is preserved.
301.2Srillig */
311.4Srillig//indent input
321.2Srillig#define space ' '		/* the 'define' is followed by a space */
331.2Srillig#define	tab '\t'		/* the 'define' is followed by a tab */
341.2Srillig#if   0				/* 3 spaces */
351.2Srillig#elif		0		/* 2 tabs */
361.2Srillig#elif	0	>	1	/* tabs between the tokens */
371.2Srillig#endif
381.4Srillig//indent end
391.2Srillig
401.4Srillig//indent run-equals-input
411.2Srillig
421.2Srillig// TODO: #define unfinished_string "...
431.2Srillig// TODO: #define unfinished_char '...
441.2Srillig// TODO: # 123 "file.h"
451.2Srillig// TODO: backslash-newline
461.2Srillig// TODO: block comment
471.2Srillig// TODO: line comment
481.5Srillig
491.5Srillig
501.5Srillig//indent input
511.5Srillig#include <system-header.h>
521.5Srillig#include "local-header.h"
531.5Srillig//indent end
541.5Srillig
551.5Srillig//indent run-equals-input
561.5Srillig
571.5Srillig
581.5Srillig/*
591.5Srillig * Nested conditional compilation.
601.5Srillig */
611.5Srillig//indent input
621.5Srillig#if 0
631.5Srillig#else
641.5Srillig#endif
651.5Srillig
661.5Srillig#if 0 /* if comment */
671.5Srillig#else /* else comment */
681.5Srillig#endif /* endif comment */
691.5Srillig
701.5Srillig#if 0 /* outer if comment */
711.5Srillig#  if nested /* inner if comment */
721.5Srillig#  else /* inner else comment */
731.5Srillig#  endif /* inner endif comment */
741.5Srillig#endif /* outer endif comment */
751.5Srillig//indent end
761.5Srillig
771.10Srillig//indent run-equals-input
781.5Srillig
791.5Srillig
801.5Srillig//indent input
811.5Srillig#define multi_line_definition /* first line
821.5Srillig * middle
831.5Srillig * final line
841.5Srillig */ actual_value
851.5Srillig//indent end
861.5Srillig
871.5Srillig//indent run-equals-input
881.5Srillig
891.5Srillig
901.5Srillig/*
911.5Srillig * Before indent.c 1.129 from 2021-10-08, indent mistakenly interpreted quotes
921.5Srillig * in comments as starting a string literal. The '"' in the comment started a
931.5Srillig * string, the next '"' finished the string, and the following '/' '*' was
941.5Srillig * interpreted as the beginning of a comment. This comment lasted until the
951.5Srillig * next '*' '/', which in this test is another preprocessor directive, solely
961.5Srillig * for symmetry.
971.5Srillig *
981.5Srillig * The effect was that the extra space after d2 was not formatted, as that
991.5Srillig * line was considered part of the comment.
1001.5Srillig */
1011.5Srillig//indent input
1021.5Srillig#define comment_in_string_literal "/* no comment "
1031.5Srilligint this_is_an_ordinary_line_again;
1041.5Srillig
1051.5Srilligint d1 ;
1061.5Srillig#define confuse_d /*"*/ "/*"
1071.5Srilligint d2 ;
1081.5Srillig#define resolve_d "*/"
1091.5Srilligint d3 ;
1101.5Srillig
1111.5Srilligint s1 ;
1121.5Srillig#define confuse_s /*'*/ '/*'
1131.5Srilligint s2 ;
1141.5Srillig#define resolve_s '*/'
1151.5Srilligint s3 ;
1161.5Srillig//indent end
1171.5Srillig
1181.5Srillig//indent run
1191.5Srillig#define comment_in_string_literal "/* no comment "
1201.5Srilligint		this_is_an_ordinary_line_again;
1211.5Srillig
1221.5Srilligint		d1;
1231.5Srillig#define confuse_d /*"*/ "/*"
1241.5Srilligint		d2;
1251.5Srillig#define resolve_d "*/"
1261.5Srilligint		d3;
1271.5Srillig
1281.5Srilligint		s1;
1291.5Srillig#define confuse_s /*'*/ '/*'
1301.5Srilligint		s2;
1311.5Srillig#define resolve_s '*/'
1321.5Srilligint		s3;
1331.5Srillig//indent end
1341.5Srillig
1351.5Srillig
1361.5Srillig/*
1371.5Srillig * A preprocessing directive inside an expression keeps the state about
1381.5Srillig * whether the next operator is unary or binary.
1391.5Srillig */
1401.5Srillig//indent input
1411.5Srilligint binary_plus = 3
1421.5Srillig#define intermediate 1
1431.5Srillig	+4;
1441.5Srilligint unary_plus =
1451.5Srillig#define intermediate 1
1461.5Srillig	+ 4;
1471.5Srillig//indent end
1481.5Srillig
1491.5Srillig//indent run
1501.5Srilligint		binary_plus = 3
1511.5Srillig#define intermediate 1
1521.5Srillig+ 4;
1531.5Srilligint		unary_plus =
1541.5Srillig#define intermediate 1
1551.5Srillig+4;
1561.5Srillig//indent end
1571.5Srillig
1581.5Srillig
1591.5Srillig/*
1601.5Srillig * Before io.c 1.135 from 2021-11-26, indent fixed malformed preprocessing
1611.5Srillig * lines that had arguments even though they shouldn't. It is not the task of
1621.5Srillig * an indenter to fix code, that's what a linter is for.
1631.5Srillig */
1641.5Srillig//indent input
1651.5Srillig#if 0
1661.5Srillig#elif 1
1671.5Srillig#else if 3
1681.5Srillig#endif 0
1691.5Srillig//indent end
1701.5Srillig
1711.5Srillig//indent run-equals-input
1721.5Srillig
1731.5Srillig
1741.5Srillig/*
1751.5Srillig * Existing comments are indented just like code comments.
1761.5Srillig *
1771.5Srillig * This means that the above wrong preprocessing lines (#else with argument)
1781.5Srillig * need to be fed through indent twice until they become stable. Since
1791.5Srillig * compilers issue warnings about these invalid lines, not much code still has
1801.5Srillig * these, making this automatic fix an edge case.
1811.5Srillig */
1821.5Srillig//indent input
1831.5Srillig#if 0		/* comment */
1841.5Srillig#else		/* comment */
1851.5Srillig#endif		/* comment */
1861.5Srillig
1871.5Srillig#if 0/* comment */
1881.5Srillig#else/* comment */
1891.5Srillig#endif/* comment */
1901.5Srillig//indent end
1911.5Srillig
1921.8Srillig//indent run-equals-input
1931.6Srillig
1941.6Srillig
1951.6Srillig/*
1961.6Srillig * Multi-line comments in preprocessing lines.
1971.6Srillig */
1981.6Srillig//indent input
1991.6Srillig#define eol_comment		// EOL
2001.6Srillig
2011.8Srillig#define no_wrap_comment		/* line 1
2021.6Srillig				 * line 2
2031.6Srillig				 * line 3
2041.6Srillig				 */
2051.6Srillig
2061.6Srillig#define fixed_comment		/*- line 1
2071.6Srillig				 * line 2
2081.6Srillig				 * line 3
2091.6Srillig				 */
2101.7Srillig
2111.7Srillig#define two_comments /* 1 */ /* 2 */ /*3*/
2121.7Srillig#define three_comments		/* first */ /* second */ /*third*/
2131.6Srillig//indent end
2141.6Srillig
2151.8Srillig//indent run-equals-input
2161.7Srillig
2171.7Srillig
2181.7Srillig/*
2191.7Srillig * Do not touch multi-line macro definitions.
2201.7Srillig */
2211.7Srillig//indent input
2221.7Srillig#define do_once(stmt)		\
2231.7Srilligdo {				\
2241.7Srillig	stmt;			\
2251.7Srillig} while (/* constant condition */ false)
2261.6Srillig//indent end
2271.7Srillig
2281.7Srillig//indent run-equals-input
2291.9Srillig
2301.9Srillig
2311.9Srillig/*
2321.9Srillig * The 'INDENT OFF' state is global, it does not depend on the preprocessing
2331.9Srillig * directives, otherwise the declarations for 'on' and 'after' would be moved
2341.9Srillig * to column 1.
2351.9Srillig */
2361.9Srillig//indent input
2371.9Srilligint first_line;
2381.9Srillig	int before;
2391.9Srillig#if 0
2401.9Srillig/*INDENT OFF*/
2411.9Srillig	int off;
2421.9Srillig#else
2431.9Srillig	int on;
2441.9Srillig#endif
2451.9Srillig	int after;
2461.9Srillig//indent end
2471.9Srillig
2481.9Srillig//indent run -di0
2491.9Srilligint first_line;
2501.9Srilligint before;
2511.9Srillig#if 0
2521.9Srillig/*INDENT OFF*/
2531.9Srillig	int off;
2541.9Srillig#else
2551.9Srillig	int on;
2561.9Srillig#endif
2571.9Srillig	int after;
2581.9Srillig//indent end
2591.11Srillig
2601.11Srillig
2611.11Srillig/*
2621.11Srillig * Before 2023-06-14, indent was limited to 5 levels of conditional compilation
2631.11Srillig * directives.
2641.11Srillig */
2651.11Srillig//indent input
2661.11Srillig#if 1
2671.11Srillig#if 2
2681.11Srillig#if 3
2691.11Srillig#if 4
2701.11Srillig#if 5
2711.11Srillig#if 6
2721.11Srillig#endif 6
2731.11Srillig#endif 5
2741.11Srillig#endif 4
2751.11Srillig#endif 3
2761.11Srillig#endif 2
2771.11Srillig#endif 1
2781.11Srillig//indent end
2791.11Srillig
2801.11Srillig//indent run-equals-input
2811.11Srillig
2821.11Srillig
2831.11Srillig/*
2841.11Srillig * Unrecognized and unmatched preprocessing directives are preserved.
2851.11Srillig */
2861.11Srillig//indent input
2871.11Srillig#else
2881.11Srillig#elif 0
2891.11Srillig#elifdef var
2901.11Srillig#endif
2911.11Srillig
2921.11Srillig#unknown
2931.11Srillig# 3 "file.c"
2941.11Srillig//indent end
2951.11Srillig
2961.11Srillig//indent run
2971.11Srillig#else
2981.11Srillig#elif 0
2991.11Srillig#elifdef var
3001.11Srillig#endif
3011.11Srillig
3021.11Srillig#unknown
3031.11Srillig# 3 "file.c"
3041.15Srillig// exit 1
3051.15Srillig// error: Standard Input:1: Unmatched #else
3061.15Srillig// error: Standard Input:2: Unmatched #elif
3071.15Srillig// error: Standard Input:3: Unmatched #elifdef
3081.15Srillig// error: Standard Input:4: Unmatched #endif
3091.11Srillig//indent end
3101.14Srillig
3111.14Srillig
3121.14Srillig/*
3131.14Srillig * The '#' can only occur at the beginning of a line, therefore indent does not
3141.14Srillig * care when it occurs in the middle of a line.
3151.14Srillig */
3161.14Srillig//indent input
3171.14Srilligint no = #;
3181.14Srillig//indent end
3191.14Srillig
3201.14Srillig//indent run -di0
3211.14Srilligint no =
3221.14Srillig#;
3231.14Srillig//indent end
3241.14Srillig
3251.14Srillig
3261.14Srillig/*
3271.14Srillig * Preprocessing directives may be indented; indent moves them to the beginning
3281.14Srillig * of a line.
3291.14Srillig */
3301.14Srillig//indent input
3311.14Srillig#if 0
3321.14Srillig	#if 1 \
3331.14Srillig	 || 2
3341.14Srillig	#endif
3351.14Srillig#endif
3361.14Srillig//indent end
3371.14Srillig
3381.14Srillig//indent run
3391.14Srillig#if 0
3401.14Srillig#if 1 \
3411.14Srillig	 || 2
3421.14Srillig#endif
3431.14Srillig#endif
3441.14Srillig//indent end
345