From d5c6a2e654422894c528cda52e951739a6b66ae6 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Fri, 28 Jul 2023 00:22:11 -0400 Subject: [PATCH] libcdecl: Fix output regression with multiple declarators. It turns out that the cdecl99 program implemented the simplify command using the undocumented behaviour of calling cdecl_declare with NULL specifiers to output just the declarator part. Recent changes to the library partially broke that usage by printing an extra space in this case. This went unnoticed as the simplify command is only lightly tested and nothing checks its behaviour with multiple declarators. Fortunately it is very easy to restore the old behaviour in the library, and to add a test case to verify this behaviour. --- src/declare.c | 6 ++++-- tests/decl-good.at | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/declare.c b/src/declare.c index 0ee9640..119d2b2 100644 --- a/src/declare.c +++ b/src/declare.c @@ -30,9 +30,11 @@ declare_declarator(struct output_state *dst, struct cdecl_declarator *d); static void declare_decl(struct output_state *dst, struct cdecl *decl) { - cdecl__emit_specs(dst, decl->specifiers, -1); + const char *sep; + + sep = cdecl__emit_specs(dst, decl->specifiers, -1); if (decl->declarators->type != CDECL_DECL_NULL) - cdecl__emit(dst, " "); + cdecl__emit(dst, sep); declare_declarator(dst, decl->declarators); } diff --git a/tests/decl-good.at b/tests/decl-good.at index 79cc6f9..df570c8 100644 --- a/tests/decl-good.at +++ b/tests/decl-good.at @@ -69,6 +69,24 @@ AT_DATA([expout], AT_CHECK([cdecl99 -f test.dat], [0], [expout]) AT_CLEANUP]) +dnl SIMPLE_DECLS_SIMPLIFY([arg], [arg ...]) +dnl +dnl Generate tests to validate the expected operation of the "simplify" +dnl command. The arguments are a quoted list of quoted items, with the +dnl first item of each list being the input declaration and the second +dnl item being the expected simplified output. +dnl +dnl The items should be related to each other as the user-visible test +dnl group name is determined only by the first argument. +m4_define([SIMPLE_DECLS_SIMPLIFY], +[AT_SETUP([Simplify "m4_car($1)"m4_ifnblank([$2], [ etc.])]) +AT_DATA([test.dat], +[m4_map_args([simplify m4_curry([_SIMPLE_DECL_ARG], [1])], $@)]) +AT_DATA([expout], +[m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [2])], $@)]) +AT_CHECK([cdecl99 -f test.dat], [0], [expout]) +AT_CLEANUP]) + dnl SIMPLE_DECLS(arg, [arg ...]) m4_define([SIMPLE_DECLS], [SIMPLE_DECLS_EXPLAIN($@) @@ -118,3 +136,15 @@ SIMPLE_DECLS_EXPLAIN( [declare as as function (function) returning returning]], [[pointer *declare], [declare declare as pointer to pointer]], [[type to], [declare to as type]]) + +dnl Test the explain command with multiple declarators, which produces +dnl multiple lines of English output. +SIMPLE_DECLS_EXPLAIN( + [[int x, y], [m4_n([declare x as int])declare y as int]]) + +dnl Test the simplify command with multiple declarators. This is the only +dnl command in cdecl99 which will print a single C declaration with more than +dnl one full declarator. +SIMPLE_DECLS_SIMPLIFY( + [[int x, y], [int x, y]], + [[int (x), ((y))], [int x, y]]) -- 2.43.2