indent: allow more than 5 levels of #if/#endif

This commit is contained in:
rillig 2023-06-14 10:26:00 +00:00
parent b520fe89c4
commit d2103f1c62
3 changed files with 71 additions and 64 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: lsym_preprocessing.c,v 1.10 2023/05/13 08:33:39 rillig Exp $ */
/* $NetBSD: lsym_preprocessing.c,v 1.11 2023/06/14 10:26:00 rillig Exp $ */
/*
* Tests for the token lsym_preprocessing, which represents a '#' that starts
@ -256,3 +256,55 @@ int before;
#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
error: Standard Input:1: Unmatched #else
error: Standard Input:2: Unmatched #elif
// $ TODO: '#elifdef' instead of '#elif'
error: Standard Input:3: Unmatched #elif
error: Standard Input:4: Unmatched #endif
#else
#elif 0
#elifdef var
#endif
#unknown
# 3 "file.c"
exit 1
//indent end

View File

@ -1,5 +1,5 @@
#! /bin/sh
# $NetBSD: t_errors.sh,v 1.35 2023/06/10 17:35:41 rillig Exp $
# $NetBSD: t_errors.sh,v 1.36 2023/06/14 10:26:00 rillig Exp $
#
# Copyright (c) 2021 The NetBSD Foundation, Inc.
# All rights reserved.
@ -348,54 +348,6 @@ unexpected_closing_brace_decl_body()
cat code.c
}
atf_test_case 'preprocessing_overflow'
preprocessing_overflow_body()
{
cat <<-\EOF > code.c
#if 1
#if 2
#if 3
#if 4
#if 5
#if 6
#endif 6
#endif 5
#endif 4
#endif 3
#endif 2
#endif 1
#endif too much
EOF
cat <<-\EOF > stderr.exp
error: code.c:6: #if stack overflow
error: code.c:12: Unmatched #endif
error: code.c:13: Unmatched #endif
EOF
atf_check -s 'exit:1' \
-e 'file:stderr.exp' \
"$indent" code.c
}
atf_test_case 'preprocessing_unrecognized'
preprocessing_unrecognized_body()
{
cat <<-\EOF > code.c
#unknown
# 3 "file.c"
#elif 3
#else
EOF
cat <<-\EOF > stderr.exp
error: code.c:3: Unmatched #elif
error: code.c:4: Unmatched #else
EOF
atf_check -s 'exit:1' \
-e 'file:stderr.exp' \
"$indent" code.c
}
atf_test_case 'unbalanced_parentheses'
unbalanced_parentheses_body()
{
@ -544,8 +496,6 @@ atf_init_test_cases()
atf_add_test_case 'unexpected_end_of_file'
atf_add_test_case 'unexpected_closing_brace_top_level'
atf_add_test_case 'unexpected_closing_brace_decl'
atf_add_test_case 'preprocessing_overflow'
atf_add_test_case 'preprocessing_unrecognized'
atf_add_test_case 'unbalanced_parentheses'
atf_add_test_case 'gcc_statement_expression'
atf_add_test_case 'crash_comment_after_controlling_expression'

View File

@ -1,4 +1,4 @@
/* $NetBSD: indent.c,v 1.359 2023/06/14 08:36:51 rillig Exp $ */
/* $NetBSD: indent.c,v 1.360 2023/06/14 10:26:00 rillig Exp $ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: indent.c,v 1.359 2023/06/14 08:36:51 rillig Exp $");
__RCSID("$NetBSD: indent.c,v 1.360 2023/06/14 10:26:00 rillig Exp $");
#include <sys/param.h>
#include <err.h>
@ -82,8 +82,11 @@ bool found_err;
bool had_eof;
int line_no = 1;
static int ifdef_level;
static struct parser_state state_stack[5];
static struct {
struct parser_state *item;
size_t len;
size_t cap;
} ifdef;
FILE *input;
FILE *output;
@ -456,24 +459,26 @@ process_preprocessing(void)
dir_len++;
if (dir_len >= 2 && memcmp(dir, "if", 2) == 0) {
if ((size_t)ifdef_level < array_length(state_stack))
state_stack[ifdef_level++] = ps;
else
diag(1, "#if stack overflow");
if (ifdef.len >= ifdef.cap) {
ifdef.cap += 5;
ifdef.item = nonnull(realloc(ifdef.item,
sizeof(ifdef.item[0]) * ifdef.cap));
}
ifdef.item[ifdef.len++] = ps;
out.line_kind = lk_if;
} else if (dir_len >= 2 && memcmp(dir, "el", 2) == 0) {
if (ifdef_level <= 0)
if (ifdef.len == 0)
diag(1, dir[2] == 'i'
? "Unmatched #elif" : "Unmatched #else");
else
ps = state_stack[ifdef_level - 1];
ps = ifdef.item[ifdef.len - 1];
} else if (dir_len == 5 && memcmp(dir, "endif", 5) == 0) {
if (ifdef_level <= 0)
if (ifdef.len == 0)
diag(1, "Unmatched #endif");
else
ifdef_level--;
ifdef.len--;
out.line_kind = lk_endif;
}
}