# Copyright © 2020-2021, 2023-2024 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . AT_BANNER([C declarations]) # _SIMPLE_DECL_ARG([n], [list]) # _SIMPLE_DECL_ARG([n1 n2], [list]) # # Select one element (indexed from 1) from the given quoted list of quoted # elements, either one or two elements may be indicated; in the two index form, # element n1 is selected unless it is blank, in which case element n2 is used. # # The expansion of this macro is followed by a newline. m4_define([_SIMPLE_DECL_ARG], [m4_default(m4_map_args_w([$1], [m4_argn(], [, $2)], [,])) ]) # SIMPLE_DECLS_EXPLAIN([arg], [arg...]) # # Generate tests to validate correct parsing and output of each specification # argument. The arguments are quoted list of quoted items, with the first # item of each list being the C declaration or type name to be explained. # # The expected output is the fourth item of the list, or, if that is empty, # the second item in the list (this allows the same lists to be used for # both SIMPLE_DECLS_DECLARE and SIMPLE_DECLS_EXPLAIN even in case of # various equivalent syntactic forms) # # The items should be related to each other as the user-visible test group # name is determined only by the first argument. m4_define([SIMPLE_DECLS_EXPLAIN], [AT_SETUP([Explain "]m4_car($1)["m4_ifnblank([$2], [ etc.])]) AT_DATA([test.dat], [m4_map_args([explain m4_curry([_SIMPLE_DECL_ARG], [1])], $@)]) AT_DATA([expout], [m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [4 2])], $@)]) AT_CHECK([cdecl99 -f test.dat], [0], [expout]) AT_CLEANUP]) # SIMPLE_DECLS_DECLARE([arg], [arg ...]) # # Similar to SIMPLE_DECLS_EXPLAIN, except in the opposite direction. The # arguments are quoted lists of quoted items, with the second item of each # list being the input query. # # The expected output is the third item of the list, or, if that is empty, # the first item in the list (this allows the same lists to be used for # both SIMPLE_DECLS_DECLARE and SIMPLE_DECLS_EXPLAIN even in the case # of various equivalent syntactic forsm) # # The items should be related to each other as the user-visible test group # name is determined only by the first argument. m4_define([SIMPLE_DECLS_DECLARE], [AT_SETUP([Declare "]m4_car($1)["m4_ifnblank([$2], [ etc.])]) AT_DATA([test.dat], [m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [2])], $@)]) AT_DATA([expout], [m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [3 1])], $@)]) AT_CHECK([cdecl99 -f test.dat], [0], [expout]) AT_CLEANUP]) # SIMPLE_DECLS_SIMPLIFY([arg], [arg ...]) # # Generate tests to validate the expected operation of the "simplify" # command. The arguments are a quoted list of quoted items, with the # first item of each list being the input declaration and the second # item being the expected simplified output. # # The items should be related to each other as the user-visible test # 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]) # SIMPLE_DECLS(arg, [arg ...]) m4_define([SIMPLE_DECLS], [SIMPLE_DECLS_EXPLAIN($@) SIMPLE_DECLS_DECLARE($@)]) SIMPLE_DECLS( [[int **], [type pointer to pointer to int]], [[int **x], [declare x as pointer to pointer to int]]) SIMPLE_DECLS( [[int (*x)], [declare x as pointer to int], [int *x]], [[int (*)], [type pointer to int], [int *]]) SIMPLE_DECLS( [[int (x*)], [type function (pointer to x) returning int], [int (x *)]]) SIMPLE_DECLS( [[int (x)()], [declare x as function returning int], [int x()]]) # Check that function reduction does not occur in english parses SIMPLE_DECLS( [[int (x)], [type function (x) returning int], [], [declare x as int]]) SIMPLE_DECLS( [[[int x[]]], [declare x as array of int]], [[[int []]], [type array of int]]) SIMPLE_DECLS( [[[int x[n]]], [declare x as variable-length array n of int]], [[[int x[*]]], [declare x as variable-length array of int]], [[[int [n]]], [type variable-length array n of int]], [[[int [*]]], [type variable-length array of int]]) SIMPLE_DECLS( [[int f(a, b)], [declare f as function (a, b) returning int]], [[int f(int, b)], [declare f as function (int, b) returning int]], [[int f(a, int)], [declare f as function (a, int) returning int]], [[int (a, b)], [type function (a, b) returning int]], [[int (int, b)], [type function (int, b) returning int]], [[int (a, int)], [type function (a, int) returning int]]) SIMPLE_DECLS( [[int f(a, b, ...)], [declare f as function (a, b, ...) returning int]], [[int f(int, b, ...)], [declare f as function (int, b, ...) returning int]], [[int f(a, int, ...)], [declare f as function (a, int, ...) returning int]], [[int (a, b, ...)], [type function (a, b, ...) returning int]], [[int (int, b, ...)], [type function (int, b, ...) returning int]], [[int (a, int, ...)], [type function (a, int, ...) returning int]]) SIMPLE_DECLS( [[[int f(int (*)[])]], [declare f as function (pointer to array of int) returning int]], [[[int f(int (*)[][1])]], [declare f as function (pointer to array of array 1 of int) returning int]], [[[int f(int (*)())]], [declare f as function (pointer to function returning int) returning int]], [[[int f(a (*)[])]], [declare f as function (pointer to array of a) returning int]], [[[int f(a (*)[][1])]], [declare f as function (pointer to array of array 1 of a) returning int]], [[[int f(a (*)())]], [declare f as function (pointer to function returning a) returning int]], [[[int (int (*)[])]], [type function (pointer to array of int) returning int]], [[[int (int (*)[][1])]], [type function (pointer to array of array 1 of int) returning int]], [[[int (int (*)())]], [type function (pointer to function returning int) returning int]], [[[int (a (*)[])]], [type function (pointer to array of a) returning int]], [[[int (a (*)[][1])]], [type function (pointer to array of array 1 of a) returning int]], [[[int (a (*)())]], [type function (pointer to function returning a) returning int]]) SIMPLE_DECLS_EXPLAIN( [[[int f(int ([]))]], [declare f as function (array of int) returning int], [[int f(int [])]]], [[[int f(a ([]))]], [declare f as function (array of a) returning int], [[int f(a [])]]], [[[int f(int (()))]], [declare f as function (function returning int) returning int], [[int f(int ())]]], [[[int f(a (()))]], [declare f as function (function returning a) returning int], [[int f(a ())]]], [[[int (int ([]))]], [type function (array of int) returning int], [[int (int [])]]], [[[int (a ([]))]], [type function (array of a) returning int], [[int (a [])]]], [[[int (int (()))]], [type function (function returning int) returning int], [[int (int ())]]], [[[int (a (()))]], [type function (function returning a) returning int], [[int (a ())]]]) SIMPLE_DECLS_EXPLAIN( [[int ((int))], [type function (int) returning int], [int (int)]], [[int (x(int))], [declare x as function (int) returning int], [int x(int)]], [[int (())], [type function returning int], [int ()]]) SIMPLE_DECLS_EXPLAIN( [[int (x())], [declare x as function returning int], [int x()]], [[int ((x)())], [declare x as function returning int], [int x()]]) # Test that english-only keywords are not rejected as idenfitiers in C mode. SIMPLE_DECLS_EXPLAIN( [[[of array[]]], [declare array as array of of]], [[[returning as(function)]], [declare as as function (function) returning returning]], [[[pointer *declare]], [declare declare as pointer to pointer]], [[[type to]], [declare to as type]]) # Test the explain command with multiple declarators, which produces # multiple lines of English output. SIMPLE_DECLS_EXPLAIN( [[int x, y], [m4_n([declare x as int])declare y as int]]) # Check output spacing around qualified pointers SIMPLE_DECLS_DECLARE( [[[int (* const)[]]], [type const pointer to array of int]], [[[int (* volatile const)()]], [type volatile const pointer to function returning int]], [[[int (int * restrict const)]], [type function (restrict const pointer to int) returning int]], [[[int * const x]], [declare x as const pointer to int]], [[[int * volatile * restrict x]], [declare x as restrict pointer to volatile pointer to int]]) # Test the simplify command with multiple declarators. This is the only # command in cdecl99 which will print a single C declaration with more than # one full declarator. SIMPLE_DECLS_SIMPLIFY( [[int x, y], [int x, y]], [[int (x), ((y))], [int x, y]])