From 710f053fbd7c65a3e8cfa051f8a2fdb92ebeeec8 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Wed, 2 Oct 2024 22:26:37 +0000 Subject: [PATCH 01/10] testsuite update for special cases tests: atlocal.in, atlocal_win: allow overriding COB_CC during tests --- tests/ChangeLog | 4 ++++ tests/atlocal.in | 11 +++++++++-- tests/atlocal_win | 14 ++++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/ChangeLog b/tests/ChangeLog index a15ae66df..b99d0ba74 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,8 @@ +2024-10-02 Simon Sobisch + + * atlocal.in, atlocal_win: allow overriding COB_CC during tests + 2024-09-09 Simon Sobisch * run_prog_manual.sh.in: adding testrunner tmux as alternative diff --git a/tests/atlocal.in b/tests/atlocal.in index 68cb4ba1c..d2f0a4429 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -185,6 +185,7 @@ _unset_option () { -a "$1" != "COB_COPY_DIR" \ -a "$1" != "COB_RUNTIME_CONFIG" \ -a "$1" != "COB_LIBRARY_PATH" \ + -a "$1" != "COB_CC" \ -a "$1" != "COB_CFLAGS" \ -a "$1" != "COB_LIBS" \ -a "$1" != "COB_UNIX_LF" \ @@ -295,8 +296,11 @@ COB_STACKTRACE=0 export COB_STACKTRACE -# different flags checked in the testsuite +# different variables used in the testsuite if test "$GNUCOBOL_TEST_LOCAL" != "1"; then + if test "$COB_CC" = ""; then + COB_CC="@COB_CC@" + fi COB_OBJECT_EXT="@COB_OBJECT_EXT@" COB_EXE_EXT="@COB_EXE_EXT@" COB_MODULE_EXT="@COB_MODULE_EXT@" @@ -308,6 +312,9 @@ if test "$GNUCOBOL_TEST_LOCAL" != "1"; then COB_HAS_CURSES="@COB_HAS_CURSES@" else + if test "$COB_CC" = ""; then + COB_CC="$($GREP COBC_CC info.out | cut -d: -f2 | cut -b2-)" + fi COB_OBJECT_EXT="$($GREP COB_OBJECT_EXT info.out | cut -d: -f2 | cut -b2-)" COB_EXE_EXT="$($GREP COB_EXE_EXT info.out | cut -d: -f2 | cut -b2-)" COB_MODULE_EXT="$($GREP COB_MODULE_EXT info.out | cut -d: -f2 | cut -b2-)" @@ -379,7 +386,7 @@ rm -rf info.out # NIST tests (tests/cobol85) are executed in a separate perl process with a new environment --> export needed export COB_HAS_ISAM COB_HAS_XML2 COB_HAS_JSON COB_HAS_CURSES COB_HAS_64_BIT_POINTER export COBC COBCRUN COBCRUN_DIRECT RUN_PROG_MANUAL -export COB_OBJECT_EXT COB_EXE_EXT COB_MODULE_EXT +export COB_CC COB_OBJECT_EXT COB_EXE_EXT COB_MODULE_EXT # to ensure that no external DB_HOME is polluted: unset DB_HOME="" && export DB_HOME diff --git a/tests/atlocal_win b/tests/atlocal_win index b6dec388f..8cf1e85cf 100644 --- a/tests/atlocal_win +++ b/tests/atlocal_win @@ -27,7 +27,10 @@ TEMPLATE="${abs_srcdir}/testsuite.src" COB_SRC_PATH="$(cd ${abs_srcdir}/.. ; pwd)" -COB_WIN_BUILDPATH="$COB_SRC_PATH/build_windows/x64/Debug" + +if test "${COB_WIN_BUILDPATH}" = ""; then + COB_WIN_BUILDPATH="$COB_SRC_PATH/build_windows/x64/Debug" +fi COBC="cobc.exe" COBCRUN="cobcrun.exe" @@ -74,6 +77,7 @@ _unset_option () { -a "$1" != "COB_COPY_DIR" \ -a "$1" != "COB_RUNTIME_CONFIG" \ -a "$1" != "COB_LIBRARY_PATH" \ + -a "$1" != "COB_CC" \ -a "$1" != "COB_CFLAGS" \ -a "$1" != "COB_LIBS" \ -a "$1" != "COB_UNIX_LF" \ @@ -164,9 +168,11 @@ export COB_STACKTRACE COB_MSG_FORMAT=GCC export COB_MSG_FORMAT -# different flags checked in the testsuite +# different variables used in the testsuite # note: kept intended to ease merge from atlocal.in - + if test "$COB_CC" = ""; then + COB_CC="$($GREP COBC_CC info.out | cut -d: -f2 | cut -b2-)" + fi COB_OBJECT_EXT="$($GREP COB_OBJECT_EXT info.out | cut -d: -f2 | cut -b2-)" COB_EXE_EXT=".exe" COB_MODULE_EXT="dll" @@ -238,7 +244,7 @@ rm -rf info.out # NIST tests (tests/cobol85) are executed in a separate perl process with a new environment --> export needed export COB_HAS_ISAM COB_HAS_XML2 COB_HAS_JSON COB_HAS_CURSES COB_HAS_64_BIT_POINTER export COBC COBCRUN COBCRUN_DIRECT RUN_PROG_MANUAL -export COB_OBJECT_EXT COB_EXE_EXT COB_MODULE_EXT +export COB_CC COB_OBJECT_EXT COB_EXE_EXT COB_MODULE_EXT # to ensure that no external DB_HOME is polluted: unset DB_HOME="" && export DB_HOME From 3f7c44b6f51605eda7da480388f8ae2efdd92811 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Wed, 2 Oct 2024 22:31:52 +0000 Subject: [PATCH 02/10] improve stdin compilation cobc: * pplex.l (output_line_directive): extracted from other places and extended to output compile from stdin as * codegen.c (output_cobol_info): output compile from stdin as --- cobc/ChangeLog | 6 ++++++ cobc/codegen.c | 19 ++++++++++++++----- cobc/pplex.l | 17 ++++++++++++++--- tests/testsuite.src/used_binaries.at | 4 ++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 3d38e0246..58895a50a 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,4 +1,10 @@ +2024-10-02 Simon Sobisch + + * pplex.l (output_line_directive): extracted from other places and + extended to output compile from stdin as + * codegen.c (output_cobol_info): output compile from stdin as + 2024-10-01 Nicolas Berthier * tree.c (validate_indexed_key_field): warn about ignored collating diff --git a/cobc/codegen.c b/cobc/codegen.c index d3bcc2fc7..c46d67f24 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -5354,7 +5354,11 @@ output_initialize_to_default (struct cb_field *f, cb_tree x) static void output_c_info (void) { - /* note: output name is already escaped for C string */ + /* note: output name is already escaped for C string; + output name cannot be COB_DASH as we generate the headers "on the fly" and + would have to place everything into temporary files (which would have a name) + and after we're finished cat those to stdout; or adjust to first generate the + headers (in memory) and output them instead of the #include */ output ("#line %d \"%s\"", output_line_number + 1, output_name); output_newline (); } @@ -5364,12 +5368,17 @@ output_cobol_info (cb_tree x) { const char *p = x->source_file; output ("#line %d \"", x->source_line); + + if (strcmp (p, COB_DASH)) { /* escape COBOL file name for C string */ - while (*p) { - if (*p == '\\') { - output ("%c",'\\'); + while (*p) { + if (*p == '\\') { + output ("%c", '\\'); + } + output ("%c", *p++); } - output ("%c",*p++); + } else { + output (""); } output ("\""); output_newline (); diff --git a/cobc/pplex.l b/cobc/pplex.l index c3bbafbc9..303f34ec3 100644 --- a/cobc/pplex.l +++ b/cobc/pplex.l @@ -1616,6 +1616,16 @@ cb_copy_find_file (char *name, int has_ext) return NULL; } +static COB_INLINE COB_A_INLINE void +output_line_directive (FILE *stream) +{ + if (strcmp (cb_source_file, COB_DASH)) { + fprintf (yyout, "#line %d \"%s\"\n", cb_source_line, cb_source_file); + } else { + fprintf (yyout, "#line %d \"\"\n", cb_source_line); + } +} + static COB_INLINE COB_A_INLINE void output_pending_newlines (FILE *stream) { @@ -1624,7 +1634,7 @@ output_pending_newlines (FILE *stream) long comment blocks, for example from EXEC SQL preparsers), so generate source directive from the already adjusted static vars instead of spitting out possibly hundreds of empty lines */ - fprintf (stream, "\n#line %d \"%s\"\n", cb_source_line, cb_source_file); + output_line_directive (stream); echo_newline = 0; } else { while (echo_newline > 1) { @@ -1756,7 +1766,7 @@ ppcopy (const char *name, const char *lib, struct cb_replace_list *replace_list) /* On COPY, open error restore old file */ cb_current_file = old_list_file; - fprintf (yyout, "#line %d \"%s\"\n", cb_source_line, cb_source_file); + output_line_directive (yyout); return -1; } @@ -2120,7 +2130,8 @@ switch_to_buffer (const int line, const char *file, const YY_BUFFER_STATE buffer /* Reset file/line */ cb_source_line = line; cb_source_file = file; - fprintf (yyout, "#line %d \"%s\"\n", line, file); + + output_line_directive (yyout); /* Switch buffer */ yy_switch_to_buffer (buffer); } diff --git a/tests/testsuite.src/used_binaries.at b/tests/testsuite.src/used_binaries.at index 5a4ddf77f..4dabfc80c 100644 --- a/tests/testsuite.src/used_binaries.at +++ b/tests/testsuite.src/used_binaries.at @@ -948,6 +948,10 @@ AT_CHECK([cat prog.cob | $COMPILE -], [0], [], [], ) AT_CHECK([$COBCRUN_DIRECT ./a.out], [0], [], []) +AT_CHECK([echo "program-id.test." | $COMPILE_MODULE -free -E -], [0], +[#line 1 "" +program-id.test. +], []) AT_CLEANUP From 88937849b8607f9f9b20a605d7f2bf65e9ed7427 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Wed, 2 Oct 2024 23:08:13 +0000 Subject: [PATCH 03/10] new options for configure for customized version string / bug report URL * configure.ac, NEWS: adjusted * bin/cobcrun: * (cobcrun_print_version): build and package data only shown in verbose mode; PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) * (cobcrun_print_usage): handle PACKAGE_BUGREPORT_URL as alternative to mailing list, now resolved by PACKAGE_BUGREPORT * cobc: * cobc.c (cobc_print_version, cobc_print_shortversion, process_command_line): build and package data only shown in verbose mode which does not output the verbose "process" calls by default; PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) * help.c (cobc_print_usage): handle PACKAGE_BUGREPORT_URL as alternative to mailing list, now resolved by PACKAGE_BUGREPORT * libcob/common.c (print_version): PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) --- ChangeLog | 5 ++++ NEWS | 7 +++++ bin/ChangeLog | 10 ++++++- bin/cobcrun.c | 78 ++++++++++++++++++++++++++++-------------------- cobc/ChangeLog | 24 +++++++++------ cobc/cobc.c | 31 ++++++++++++------- cobc/help.c | 14 ++++++--- configure.ac | 46 ++++++++++++++++++++++++++++ libcob/ChangeLog | 5 ++++ libcob/common.c | 13 ++++---- 10 files changed, 170 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab1e792a6..d790fe60a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ +2024-10-02 Simon Sobisch + + * configure.ac: new options --with-pkgversion=PKG and --with-bugurl=URL + see NEWS, currently only used in version and help output + 2024-09-29 Simon Sobisch * configure.ac: drop COB_LI_IS_LL in favor of existing COB_32_BIT_LONG diff --git a/NEWS b/NEWS index c87619496..306f35115 100644 --- a/NEWS +++ b/NEWS @@ -94,6 +94,13 @@ NEWS - user visible changes -*- outline -*- this is used for character encoding support, which otherwise is only provided partially +** configure now accepts --with-bugurl=URL which can be used to output a link + to an external or local URL (like file://) instead of the bug mailing list + +** configure now accepts --with-pkgversion=PKG which can be used to customize + the version output with a free-standing string (like revision number or + package manager version) + ** use the "default" -shared flag to build dynamic libraries on macOS so as to fix testuite issues with recent macOS versions diff --git a/bin/ChangeLog b/bin/ChangeLog index 69bc366d7..8f456551a 100644 --- a/bin/ChangeLog +++ b/bin/ChangeLog @@ -1,4 +1,12 @@ +2024-10-02 Simon Sobisch + + * cobcrun.c (cobcrun_print_version): build and package data only + shown in verbose mode; + PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) + * cobcrun.c (cobcrun_print_usage): handle PACKAGE_BUGREPORT_URL as + alternative to mailing list, now resolved by PACKAGE_BUGREPORT + 2023-07-24 Simon Sobisch * cob-config.in: prevent warning to use datadir, but not datarootdir; @@ -291,7 +299,7 @@ then you can switch easily. -Copyright 2004-2008,2010,2012,2014-2023 Free Software Foundation, Inc. +Copyright 2004-2008,2010,2012,2014-2024 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. diff --git a/bin/cobcrun.c b/bin/cobcrun.c index cf4992f57..386ffd800 100644 --- a/bin/cobcrun.c +++ b/bin/cobcrun.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004-2012, 2014-2023 Free Software Foundation, Inc. + Copyright (C) 2004-2012, 2014-2024 Free Software Foundation, Inc. Written by Roger While, Simon Sobisch, Brian Tiffin This file is part of GnuCOBOL. @@ -70,43 +70,47 @@ static const struct option long_options[] = { /** - * Display cobcrun build and version date + * Display cobcrun version info, optional with build and version date */ static void cobcrun_print_version (void) { - char cob_build_stamp[COB_MINI_BUFF]; - char month[64]; - int status, day, year; - - /* Set up build time stamp */ - memset (cob_build_stamp, 0, (size_t)COB_MINI_BUFF); - memset (month, 0, sizeof(month)); - day = 0; - year = 0; - status = sscanf (__DATE__, "%63s %d %d", month, &day, &year); - /* LCOV_EXCL_START */ - if (status != 3) { - snprintf (cob_build_stamp, (size_t)COB_MINI_MAX, - "%s %s", __DATE__, __TIME__); - /* LCOV_EXCL_STOP */ - } else { - snprintf (cob_build_stamp, (size_t)COB_MINI_MAX, - "%s %2.2d %4.4d %s", month, day, year, __TIME__); - } - - printf ("cobcrun (%s) %s.%d\n", PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL); - puts ("Copyright (C) 2023 Free Software Foundation, Inc."); - printf (_("License GPLv3+: GNU GPL version 3 or later <%s>"), "https://gnu.org/licenses/gpl.html"); + printf ("cobcrun (%s) %s.%d\n", + PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL); + puts ("Copyright (C) 2024 Free Software Foundation, Inc."); + printf (_("License GPLv3+: GNU GPL version 3 or later <%s>"), + "https://gnu.org/licenses/gpl.html"); putchar ('\n'); puts (_("This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.")); - printf (_("Written by %s"), "Roger While, Simon Sobisch, Brian Tiffin"); putchar ('\n'); - printf (_("Built %s"), cob_build_stamp); - putchar ('\n'); - printf (_("Packaged %s"), COB_TAR_DATE); + printf (_("Written by %s"), "Roger While, Simon Sobisch, Brian Tiffin"); putchar ('\n'); + if (verbose_output) { + char cob_build_stamp[COB_MINI_BUFF]; + char month[64]; + int status, day, year; + + /* Set up build time stamp */ + memset (cob_build_stamp, 0, (size_t)COB_MINI_BUFF); + memset (month, 0, sizeof(month)); + day = 0; + year = 0; + status = sscanf (__DATE__, "%63s %d %d", month, &day, &year); + /* LCOV_EXCL_START */ + if (status != 3) { + snprintf (cob_build_stamp, (size_t)COB_MINI_MAX, + "%s %s", __DATE__, __TIME__); + /* LCOV_EXCL_STOP */ + } else { + snprintf (cob_build_stamp, (size_t)COB_MINI_MAX, + "%s %2.2d %4.4d %s", month, day, year, __TIME__); + } + printf (_("Built %s"), cob_build_stamp); + putchar ('\n'); + printf (_("Packaged %s"), COB_TAR_DATE); + putchar ('\n'); + } } /** @@ -140,12 +144,20 @@ cobcrun_print_usage (char * prog) " and any basename to the module preload list\n" " (COB_LIBRARY_PATH and/or COB_PRELOAD)")); putchar ('\n'); - printf (_("Report bugs to: %s\n" - "or (preferably) use the issue tracker via the home page."), "bug-gnucobol@gnu.org"); +#ifndef PACKAGE_BUGREPORT_URL + printf (_("Report bugs to: %s\n" + "or (preferably) use the issue tracker via the home page."), + PACKAGE_BUGREPORT); putchar ('\n'); - printf (_("GnuCOBOL home page: <%s>"), "https://www.gnu.org/software/gnucobol/"); +#else + puts (_("For bug reporting instructions, please see:")); + printf ("%s.\n", PACKAGE_BUGREPORT_URL); +#endif + printf (_("GnuCOBOL home page: <%s>"), + "https://www.gnu.org/software/gnucobol/"); putchar ('\n'); - printf (_("General help using GNU software: <%s>"), "https://www.gnu.org/gethelp/"); + printf (_("General help using GNU software: <%s>"), + "https://www.gnu.org/gethelp/"); putchar ('\n'); } diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 58895a50a..c69bbf3a6 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -4,6 +4,12 @@ * pplex.l (output_line_directive): extracted from other places and extended to output compile from stdin as * codegen.c (output_cobol_info): output compile from stdin as + * cobc.c (cobc_print_version, cobc_print_shortversion, + process_command_line): build and package data only shown in verbose mode + which does not output the verbose "process" calls by default; + PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) + * help.c (cobc_print_usage): handle PACKAGE_BUGREPORT_URL as + alternative to mailing list, now resolved by PACKAGE_BUGREPORT 2024-10-01 Nicolas Berthier @@ -1336,7 +1342,7 @@ * codegen.c (output_perform_call): use statement reference to generate separate comment for PERFORM procedure or USE procedure * flag.def, codegen.c: new -fsection-exit-check - (cb_flag_section_exit_check) and -fimplicit-goback-check + (cb_flag_section_exit_check) and -fimplicit-goback-check (cb_flag_implicit_goback_check) * tree.h (cb_progam), parser.y (perform_procedure): add and set perform_thru_list for internal checks @@ -2385,7 +2391,7 @@ 2021-01-25 Simon Sobisch - * reserved.c: fixed context attribute of acu-extension POS + * reserved.c: fixed context attribute of acu-extension POS * parser.y, reserved.c, tree.h, cobc.h: added acu-extension MOVE WITH CONVERSION as PENDING @@ -2416,7 +2422,7 @@ * field.c, pplex.l, tree.c, typeck.c: fixed warning option querying enum instead of actual value via cb_warn_opt_val - + 2020-12-09 Ron Norman * cobc.c: now calls cob_get_sig_name from common.c to get signal name @@ -2432,7 +2438,7 @@ * typeck.c (syntax_check_ml_gen_name_list): additional parameter is_xml to distinguish between XML and JSON generation (messages, possible rules) * typeck.c (syntax_check_ml_gen_name_list): check of NAME ... IS OMITTED - + 2020-12-17 Simon Sobisch bug #571 revised: @@ -2661,7 +2667,7 @@ 2020-10-12 Ron Norman * typeck.c: Flag internal variables with 'flag_real_binary' - * codegen.c: Emit USAGE INDEX and internal binary variables + * codegen.c: Emit USAGE INDEX and internal binary variables as COB_TYPE_NUMERIC_COMP5 2020-10-06 Simon Sobisch @@ -3143,8 +3149,8 @@ 2020-02-10 Ron Norman - * cobc.c, cobc.h, codegen.c, help.c, warning.def: - Add new define CB_ERRWARNDEF + * cobc.c, cobc.h, codegen.c, help.c, warning.def: + Add new define CB_ERRWARNDEF 2020-02-05 Ron Norman @@ -3313,7 +3319,7 @@ 2019-09-15 Ron Norman * cobc.h: For HPUX set COB_ALLOW_UNALIGNED as undefined - * typeck.c: Emit ADD/SUBTRACT shortcut for COMP-5 only + * typeck.c: Emit ADD/SUBTRACT shortcut for COMP-5 only if COB_ALLOW_UNALIGNED defined * tree.h: Revert 'lock_mode' back to an 'int' * codegen.c: Changes for 'lock_mode' being an 'int' @@ -7335,7 +7341,7 @@ 2015-04-27 Ron Norman * config.c: don't store configuration values additional to the setting - + 2015-04-14 Ron Norman * cobc.c codegen.c common.h tree.h parser.y typeck.c: diff --git a/cobc/cobc.c b/cobc/cobc.c index 915353ed4..8fe0d93c0 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -2535,27 +2535,31 @@ cobc_sig_handler (int sig) static void cobc_print_version (void) { - printf ("cobc (%s) %s.%d\n", PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL); + printf ("cobc %s%s.%d\n", PKGVERSION, PACKAGE_VERSION, PATCH_LEVEL); puts ("Copyright (C) 2024 Free Software Foundation, Inc."); printf (_("License GPLv3+: GNU GPL version 3 or later <%s>"), "https://gnu.org/licenses/gpl.html"); putchar ('\n'); puts (_("This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.")); - printf (_("Written by %s"), "Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart"); - putchar ('\n'); - printf (_("Built %s"), cb_cobc_build_stamp); putchar ('\n'); - printf (_("Packaged %s"), COB_TAR_DATE); - putchar ('\n'); - printf ("%s %s", _("C version"), GC_C_VERSION_PRF GC_C_VERSION); + printf (_("Written by %s"), "Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart"); putchar ('\n'); + if (verbose_output) { + putchar ('\n'); + printf (_("Built %s"), cb_cobc_build_stamp); + putchar ('\n'); + printf (_("Packaged %s"), COB_TAR_DATE); + putchar ('\n'); + printf ("%s %s", _("C version"), GC_C_VERSION_PRF GC_C_VERSION); + putchar ('\n'); + } } static void cobc_print_shortversion (void) { - printf ("cobc (%s) %s.%d\n", - PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL); + printf ("cobc %s%s.%d\n", + PKGVERSION, PACKAGE_VERSION, PATCH_LEVEL); printf (_("Built %s"), cb_cobc_build_stamp); putchar ('\t'); printf (_("Packaged %s"), COB_TAR_DATE); @@ -3189,7 +3193,10 @@ process_command_line (const int argc, char **argv) /* --version */ cobc_print_version (); if (verbose_output) { - puts ("\n"); + /* temporarily reduce verbosity for not necessarily showing the process */ + const int verbose_output_sav = verbose_output--; + + putchar ('\n'); fflush (stdout); #ifdef _MSC_VER process ("cl.exe"); @@ -3203,7 +3210,8 @@ process_command_line (const int argc, char **argv) snprintf (cobc_buffer, cobc_buffer_size, "%s --version", cobc_cc); #endif #if (defined(__GNUC__) && !defined(__INTEL_COMPILER)) - if (verbose_output > 2) { + if (verbose_output > 1) { + verbose_output--; snprintf (cobc_buffer, cobc_buffer_size, "%s -v", cobc_cc); } #endif @@ -3212,6 +3220,7 @@ process_command_line (const int argc, char **argv) cobc_free (cobc_buffer); cobc_buffer = NULL; #endif + verbose_output = verbose_output_sav; } cobc_early_exit (EXIT_SUCCESS); diff --git a/cobc/help.c b/cobc/help.c index 53077416f..bb1ee3127 100644 --- a/cobc/help.c +++ b/cobc/help.c @@ -44,14 +44,20 @@ cobc_print_usage (char * prog) cobc_print_usage_dialect (); - putchar ('\n'); +#ifndef PACKAGE_BUGREPORT_URL printf (_("Report bugs to: %s\n" "or (preferably) use the issue tracker via the home page."), - "bug-gnucobol@gnu.org"); + PACKAGE_BUGREPORT); putchar ('\n'); - printf (_("GnuCOBOL home page: <%s>"), "https://www.gnu.org/software/gnucobol/"); +#else + puts (_("For bug reporting instructions, please see:")); + printf ("%s.\n", PACKAGE_BUGREPORT_URL); +#endif + printf (_("GnuCOBOL home page: <%s>"), + "https://www.gnu.org/software/gnucobol/"); putchar ('\n'); - printf (_("General help using GNU software: <%s>"), "https://www.gnu.org/gethelp/"); + printf (_("General help using GNU software: <%s>"), + "https://www.gnu.org/gethelp/"); putchar ('\n'); } diff --git a/configure.ac b/configure.ac index b7a516ab0..126e2a363 100644 --- a/configure.ac +++ b/configure.ac @@ -37,9 +37,11 @@ AC_REVISION([GnuCOBOL snapshot $Revision$]) AC_COPYRIGHT([This file is part of GnuCOBOL. Copyright (C) 2001-2012, 2014-2024 Free Software Foundation, Inc. + Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart ]) + AC_CONFIG_SRCDIR([libcob.h]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_TESTDIR([tests]) @@ -58,6 +60,50 @@ AC_CONFIG_FILES([tests/atlocal], [chmod +x tests/atlocal]) AC_CONFIG_FILES([tests/run_prog_manual.sh], [chmod +x tests/run_prog_manual.sh]) +dnl Support the --with-pkgversion configure option, +dnl inspired from GCC's ACX_PKGVERSION. +AC_ARG_WITH([pkgversion], + [AS_HELP_STRING([--with-pkgversion=PKG], + [Use PKG in the version string in place of "$PACKAGE_NAME"])], + [case "$withval" in + yes) AC_MSG_ERROR([package version not specified]) ;; + no) PKGVERSION= ;; + *) PKGVERSION="($withval) " ;; + esac], + [PKGVERSION="($PACKAGE_NAME) "]) + +# AC_SUBST(PKGVERSION) +AC_DEFINE_UNQUOTED([PKGVERSION], ["$PKGVERSION"], [PKG version string]) + + +dnl Support the --with-bugurl configure option, +dnl inspired from GCC's ACX_BUGURL. +AC_ARG_WITH([bugurl], + [AS_HELP_STRING([--with-bugurl=URL], + [Direct users to URL to report a bug, instead of mailing list])], + [case "$withval" in + yes) AC_MSG_ERROR([bug URL not specified]) ;; + no) BUGURL= ;; + *) BUGURL="$withval" ;; + esac], + [ # BUGURL="$PACKAGE_BUGREPORT" + ]) + + case ${BUGURL} in + "") + # REPORT_BUGS_TO= + # REPORT_BUGS_TEXI= + ;; + *) + AC_DEFINE_UNQUOTED([PACKAGE_BUGREPORT_URL], ["<$BUGURL>"], [Bug URL instead of mailing list]) + # REPORT_BUGS_TO="<$BUGURL>" + # REPORT_BUGS_TEXI=@uref{`echo "$BUGURL" | sed 's/@/@@/g'`} + ;; + esac; + # AC_SUBST(REPORT_BUGS_TO) + # AC_SUBST(REPORT_BUGS_TEXI) + + # In general: don't export/setenv but pass as option to configure # this has the benefit that re-runs will take the same and "sudo" # or later "make" (possibly as different user) will use the same diff --git a/libcob/ChangeLog b/libcob/ChangeLog index 9056a9101..551dd80aa 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,9 @@ +2024-10-02 Simon Sobisch + + * common.c (print_version): PACKAGE_NAME may now be overwritten + by PKGVERSION (new configure option) + 2024-09-29 Simon Sobisch * numeric.c, common.c (print_info_detailed): drop COB_LI_IS_LL diff --git a/libcob/common.c b/libcob/common.c index c6a83ac25..c028b91b5 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -9681,14 +9681,17 @@ print_version (void) set_cob_build_stamp (cob_build_stamp); - printf ("libcob (%s) %s.%d\n", - PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL); - puts ("Copyright (C) 2023 Free Software Foundation, Inc."); - printf (_("License LGPLv3+: GNU LGPL version 3 or later <%s>"), "https://gnu.org/licenses/lgpl.html"); + printf ("libcob %s%s.%d\n", + PKGVERSION, PACKAGE_VERSION, PATCH_LEVEL); + puts ("Copyright (C) 2024 Free Software Foundation, Inc."); + printf (_("License LGPLv3+: GNU LGPL version 3 or later <%s>"), + "https://gnu.org/licenses/lgpl.html"); putchar ('\n'); puts (_("This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.")); - printf (_("Written by %s"), "Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart"); + putchar ('\n'); + printf (_("Written by %s"), "Keisuke Nishida, Roger While, " + "Ron Norman, Simon Sobisch, Edward Hart"); putchar ('\n'); /* TRANSLATORS: This msgid is intended as the "Packaged" msgid, %s expands to date and time */ From c53ae5f803518dc7a0e1e88ee08ac060e423ca1b Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Wed, 2 Oct 2024 23:21:53 +0000 Subject: [PATCH 04/10] signal handler updates * cobc/cobc.c (cobc_sig_handler): skip abort message for SIGPIPE * libcob/common.c: * (cob_sig_handler): fixed early exit from signal handler in case of errors during write to stderr, adjusted macros accordingly * (cob_sig_handler): flush stdout+stderr for fixed set of signals where this is known to work * (cob_reg_sighnd): if signal handler is enabled from outside the COBOL runtime (like via cobc), do the initialization of the internal signal text table (was empty before) * (cob_sig_handler): early exit for SIGPIPE without output if signal handler is used without any COBOL modules active (like via cobc) * (cob_sig_handler): fixed coding error that led to missing output of catched signal name added tests for signal handling, these may need to be skipped because of not being completely portable --- cobc/ChangeLog | 1 + cobc/cobc.c | 11 +-- libcob/ChangeLog | 11 +++ libcob/common.c | 104 ++++++++++++++++++++------- tests/testsuite.src/used_binaries.at | 86 ++++++++++++++++++++++ 5 files changed, 182 insertions(+), 31 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index c69bbf3a6..8c5853b8e 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -10,6 +10,7 @@ PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) * help.c (cobc_print_usage): handle PACKAGE_BUGREPORT_URL as alternative to mailing list, now resolved by PACKAGE_BUGREPORT + * cobc.c (cobc_sig_handler): skip abort message for SIGPIPE 2024-10-01 Nicolas Berthier diff --git a/cobc/cobc.c b/cobc/cobc.c index 8fe0d93c0..de9c1d6f1 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -2502,7 +2502,13 @@ cobc_sig_handler (int sig) int ret = 0; #endif - cobc_abort_msg (); +#ifdef SIGPIPE + if (sig == SIGPIPE) ret = 1; +#endif + + if (!ret) { + cobc_abort_msg (); + } #if defined (SIGINT) || defined (SIGQUIT) || defined (SIGTERM) || defined (SIGPIPE) #ifdef SIGINT if (sig == SIGINT) ret = 1; @@ -2513,9 +2519,6 @@ cobc_sig_handler (int sig) #ifdef SIGTERM if (sig == SIGTERM) ret = 1; #endif -#ifdef SIGPIPE - if (sig == SIGPIPE) ret = 1; -#endif /* LCOV_EXCL_START */ if (!ret) { diff --git a/libcob/ChangeLog b/libcob/ChangeLog index 551dd80aa..b5a148c41 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -3,6 +3,17 @@ * common.c (print_version): PACKAGE_NAME may now be overwritten by PKGVERSION (new configure option) + * common.c (cob_sig_handler): fixed early exit from signal handler + in case of errors during write to stderr, adjusted macros accordingly + * common.c (cob_sig_handler): flush stdout+stderr for fixed set of signals + where this is known to work + * common.c (cob_reg_sighnd): if signal handler is enabled from outside the + COBOL runtime (like via cobc), do the initialization of the internal signal + text table (was empty before) + * common.c (cob_sig_handler): early exit for SIGPIPE without output if + signal handler is used without any COBOL modules active (like via cobc) + * common.c (cob_sig_handler): fixed coding error that led to missing output + of catched signal name 2024-09-29 Simon Sobisch diff --git a/libcob/common.c b/libcob/common.c index c028b91b5..bf82f5eec 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -1021,15 +1021,29 @@ set_source_location (const char **file, unsigned int *line) } /* write integer to stderr using fixed buffer */ +#define write_to_stderr_or_true_int(i) \ + (write (STDERR_FILENO, ss_itoa_buf, ss_itoa_u10 (i)) == -1) #define write_to_stderr_or_return_int(i) \ - if (write (STDERR_FILENO, ss_itoa_buf, ss_itoa_u10 (i)) == -1) return + if (write_to_stderr_or_true_int (i)) return +#define write_to_stderr_until_error_int(i, err) \ + if (!err) err = write_to_stderr_or_true_int (i) + /* write char array (constant C string) to stderr */ +#define write_to_stderr_or_true_arr(ch_arr) \ + (write (STDERR_FILENO, ch_arr, sizeof (ch_arr) - 1) == -1) #define write_to_stderr_or_return_arr(ch_arr) \ - if (write (STDERR_FILENO, ch_arr, sizeof (ch_arr) - 1) == -1) return + if (write_to_stderr_or_true_arr (ch_arr)) return +#define write_to_stderr_until_error_arr(ch_arr,err) \ + if (!err) err = write_to_stderr_or_true_arr (ch_arr) + /* write string to stderr, byte count computed with strlen, str is evaluated twice */ +#define write_to_stderr_or_true_str(str) \ + (write (STDERR_FILENO, str, strlen (str)) == -1) #define write_to_stderr_or_return_str(str) \ - if (write (STDERR_FILENO, str, strlen (str)) == -1) return + if (write_to_stderr_or_true_str (str)) return +#define write_to_stderr_until_error_str(str,err) \ + if (!err) err = write_to_stderr_or_true_str (str) /* write integer to fileno using fixed buffer */ #define write_or_return_int(fileno,i) \ @@ -1114,6 +1128,7 @@ cob_sig_handler (int sig) const char *msg; char signal_text[COB_MINI_BUFF] = { 0 }; size_t str_len; + int write_err = 0; #if defined (HAVE_SIGACTION) && !defined (SA_RESETHAND) struct sigaction sa; @@ -1131,11 +1146,38 @@ cob_sig_handler (int sig) sig_is_handled = 1; #endif -#if 0 /* We do not generally flush whatever we may have in our streams - as stdio is not signal-safe; - we _may_ do this if not SIGSEGV/SIGBUS/SIGABRT */ - fflush (stdout); - fflush (stderr); + + /* We do not generally flush whatever we may have in our streams + as stdio is not signal-safe; + we _may_ do this if not SIGSEGV/SIGBUS/SIGABRT (but as we don't know + if all of those are defined we only flush on a positive list)*/ + switch (sig) { + case -1: +#ifdef SIGPIPE + case SIGPIPE: +#endif +#ifdef SIGTERM + case SIGTERM: +#endif +#ifdef SIGINT + case SIGINT: +#endif +#ifdef SIGHUP + case SIGHUP: +#endif + fflush (stderr); + fflush (stdout); + break; + default: + break; + } + +#ifdef SIGPIPE + /* early exit for non-active COBOL runtime */ + if (sig == SIGPIPE + && !cob_initialized) { + goto exit_handler; + } #endif signal_name = cob_get_sig_name (sig); @@ -1143,9 +1185,9 @@ cob_sig_handler (int sig) if (signal_name == signals[NUM_SIGNALS].shortname) { /* not translated as it is a very unlikely error case */ signal_name = signals[NUM_SIGNALS].description; /* translated unknown */ - write_to_stderr_or_return_arr ("\ncob_sig_handler caught not handled signal: "); - write_to_stderr_or_return_int (sig); - write_to_stderr_or_return_arr ("\n"); + write_to_stderr_until_error_arr ("\ncob_sig_handler caught not handled signal: ", write_err); + write_to_stderr_until_error_int (sig, write_err); + write_to_stderr_until_error_arr ("\n", write_err); } /* LCOV_EXCL_STOP */ @@ -1182,29 +1224,33 @@ cob_sig_handler (int sig) #endif cob_exit_screen (); - write_to_stderr_or_return_arr ("\n"); - cob_get_source_line (); - output_source_location (); + write_to_stderr_until_error_arr ("\n", write_err); + if (!write_err) { + cob_get_source_line (); + output_source_location (); - msg = cob_get_sig_description (sig); - write_to_stderr_or_return_str (msg); + msg = cob_get_sig_description (sig); + write_to_stderr_until_error_str (msg, write_err); + } - /* setup "signal %s" */ - str_len = strlen (signal_msgid); - memcpy (signal_text, signal_msgid, str_len++); - signal_text[str_len] = ' '; - memcpy (signal_text + str_len, signal_name, strlen (signal_name)); + if (!write_err) { + /* setup "signal %s" */ + str_len = strlen (signal_msgid); + memcpy (signal_text, signal_msgid, str_len); + signal_text[str_len++] = ' '; + memcpy (signal_text + str_len, signal_name, strlen (signal_name)); - write_to_stderr_or_return_arr (" ("); - write_to_stderr_or_return_str (signal_text); - write_to_stderr_or_return_arr (")\n\n"); + write_to_stderr_until_error_arr (" (", write_err); + write_to_stderr_until_error_str (signal_text, write_err); + write_to_stderr_until_error_arr (")\n\n", write_err); + } if (cob_initialized) { if (abort_reason[0] == 0) { memcpy (abort_reason, signal_text, COB_MINI_BUFF); #if 0 /* Is there a use in this message ?*/ - write_to_stderr_or_return_str (abnormal_termination_msgid); - write_to_stderr_or_return_arr ("\n"); + write_to_stderr_until_error_str (abnormal_termination_msgid, write_err); + write_to_stderr_until_error_arr ("\n", write_err); #endif } } @@ -1235,6 +1281,7 @@ cob_sig_handler (int sig) break; } +exit_handler: /* call external signal handler if registered */ if (cob_ext_sighdl != NULL) { (*cob_ext_sighdl) (sig); @@ -3842,6 +3889,7 @@ cob_reg_sighnd (void (*sighnd) (int)) { if (!cob_initialized) { cob_set_signal (); + cob_init_sig_descriptions (); } cob_ext_sighdl = sighnd; } @@ -8832,7 +8880,6 @@ cob_runtime_warning_external (const char *caller_name, const int cob_reference, if (!cobsetptr->cob_display_warn) { return; } - if (!(caller_name && *caller_name)) caller_name = "unknown caller"; /* Prefix */ if (cob_reference) { @@ -8843,7 +8890,10 @@ cob_runtime_warning_external (const char *caller_name, const int cob_reference, } else { fprintf (stderr, "libcob: "); } + fprintf (stderr, _("warning: ")); + + if (!(caller_name && *caller_name)) caller_name = "unknown caller"; fprintf (stderr, "%s: ", caller_name); /* Body */ diff --git a/tests/testsuite.src/used_binaries.at b/tests/testsuite.src/used_binaries.at index 4dabfc80c..0e200a960 100644 --- a/tests/testsuite.src/used_binaries.at +++ b/tests/testsuite.src/used_binaries.at @@ -1356,3 +1356,89 @@ AT_CHECK([$GREP 'sub/copy/PROC.cpy' prog.d], [0], [ignore], [], [ AT_CLEANUP +AT_SETUP([signal handling SIGPIPE cobc]) +AT_KEYWORDS([runmisc]) + +# the runtime is not initialized, so we get out without any error message in libcob +# and we also don't raise anything in cobc either +AT_CHECK([$COBC --help | head], [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([signal handling SIGPIPE in COBOL]) +AT_KEYWORDS([runmisc]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + PROCEDURE DIVISION. + 00. DISPLAY '1'. DISPLAY '2'. DISPLAY '3'. DISPLAY '4'. + DISPLAY '5'. DISPLAY '6'. DISPLAY '7'. DISPLAY '8'. + EX. STOP RUN. +]) + +AT_CHECK([$COMPILE prog.cob], [0], [], []) +AT_CHECK([$COBCRUN_DIRECT ./prog| head -n 2], [0], +[1 +2 +], []) + +AT_CLEANUP + + +AT_SETUP([signal handling SIGTERM in COBOL]) +AT_KEYWORDS([runmisc stack stacktrace]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. 'prog'. + PROCEDURE DIVISION. + 00. DISPLAY '1'. + CALL 'wait'. DISPLAY '2'. + EX. STOP RUN. + END PROGRAM 'prog'. + IDENTIFICATION DIVISION. + PROGRAM-ID. 'wait'. + PROCEDURE DIVISION. + 00. PERFORM DO-WAIT. + EX. GOBACK. + DO-WAIT. CONTINUE AFTER 10 SECONDS. + END PROGRAM 'wait'. +]) + +AT_CHECK([$COMPILE prog.cob], [0], [], []) + +# note: the stack trace, while enabled per default, is globally disabled in the testsuite +AT_CHECK([$COBCRUN_DIRECT ./prog & cobpid=$! +sleep 6 +kill -15 $cobpid], [0], +[1 +], +[ +prog.cob:14: termination (signal SIGTERM) + +]) +AT_CHECK([COB_STACKTRACE=1 $COBCRUN_DIRECT ./prog a "b c" & cobpid=$! +sleep 6 +kill -15 $cobpid], [0], +[1 +], +[ +prog.cob:14: termination (signal SIGTERM) + + + Last statement of "wait" was CONTINUE AFTER + DO-WAIT at prog.cob:14 + 00 at prog.cob:12 + ENTRY wait at prog.cob:12 + Last statement of "prog" was CALL + 00 at prog.cob:6 + ENTRY prog at prog.cob:5 + Started by ./prog + a + b c +]) + +AT_CLEANUP + From 929b403b68ffedce147598f57eff79dc02590d6f Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Thu, 3 Oct 2024 00:08:33 +0000 Subject: [PATCH 05/10] fix [r5349] missing PKGVERSION for build_windows --- build_windows/config.h.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build_windows/config.h.in b/build_windows/config.h.in index d7294dc64..44343b870 100644 --- a/build_windows/config.h.in +++ b/build_windows/config.h.in @@ -768,6 +768,9 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_XCURSES_H */ +/* Define as const if the declaration of iconv() needs const. */ +/* #undef ICONV_CONST */ + /* Define to the sub-directory where libtool stores uninstalled libraries. */ /* #undef LT_OBJDIR */ @@ -780,6 +783,9 @@ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-gnucobol@gnu.org" +/* Bug URL instead of mailing list */ +/* #undef PACKAGE_BUGREPORT_URL */ + /* Define to the full name of this package. */ #define PACKAGE_NAME "GnuCOBOL" @@ -798,6 +804,9 @@ /* Define a patch level (numeric, max. 8 digits) */ #define PATCH_LEVEL COB_NUM_TAR_DATE +/* PKG version string */ +#define PKGVERSION "(" PACKAGE_NAME ") " + // Use \ to escape things, for example \\ for using in paths // Use \" for paths with spaces From 3f897122aacdd6610c14117b28442013a4574cde Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Fri, 4 Oct 2024 15:32:44 +0000 Subject: [PATCH 06/10] signal and stack handling update libcob: * common.c (cob_sig_handler): moved call of cob_exit_screen_from_signal from ss_terminate_routines here instead of calling cob_exit_screen * common.c (cob_sig_handler, cob_stack_trace_internal, cob_runtime_warning_ss): now using an internal buffer to output data instead of potentially hundreds of small direct writes, output the complete buffer when half-full oir at the end * common.c (get_source_location): renamed from output_source_location, now writing to a specified buffer, returning the length, instead of direct write to stderr * common.c (output_procedure_stack_entry): use buffer instead of direct write to stderr, now returning the length * common.c (write_until_fail, strcat_to_buf, intcat_to_buff): new helper functions * common.c (cob_sig_handler): moved call of cob_exit_screen_from_signal from ss_terminate_routines here instead of calling cob_exit_screen * common.c (cob_runtime_warning_ss), coblocal.h, fileio.c (cob_exit_fileio_msg_only): changed signature, now returning nonzero if write to stderr wasn't sucessfull * common.c (cob_runtime_warning, cob_runtime_warning_external): use all buffered io again additional: libcob/common.c (cob_load_config_file): fix format truncation warning by explicit checking for it --- libcob/ChangeLog | 27 +++ libcob/coblocal.h | 2 +- libcob/common.c | 435 +++++++++++++++++++++++++--------------------- libcob/fileio.c | 11 +- 4 files changed, 275 insertions(+), 200 deletions(-) diff --git a/libcob/ChangeLog b/libcob/ChangeLog index b5a148c41..8b440116e 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,29 @@ +2024-10-04 Simon Sobisch + + * common.c (cob_sig_handler): moved call of cob_exit_screen_from_signal + from ss_terminate_routines here instead of calling cob_exit_screen + * common.c (cob_sig_handler, cob_stack_trace_internal, + cob_runtime_warning_ss): now using an internal buffer to output data + instead of potentially hundreds of small direct writes, output the + complete buffer when half-full oir at the end + * common.c (get_source_location): renamed from output_source_location, + now writing to a specified buffer, returning the length, instead of + direct write to stderr + * common.c (output_procedure_stack_entry): use buffer instead of direct + write to stderr, now returning the length + * common.c (write_until_fail, strcat_to_buf, intcat_to_buff): new helper + functions + * common.c (cob_sig_handler): moved call of cob_exit_screen_from_signal + from ss_terminate_routines here instead of calling cob_exit_screen + * common.c (cob_runtime_warning_ss), coblocal.h, + fileio.c (cob_exit_fileio_msg_only): changed signature, now returning + nonzero if write to stderr wasn't sucessfull + * common.c (cob_runtime_warning, cob_runtime_warning_external): + use all buffered io again + * common.c (cob_load_config_file): fix format truncation warning by + explicit checking for it + 2024-10-02 Simon Sobisch * common.c (print_version): PACKAGE_NAME may now be overwritten @@ -61,6 +86,8 @@ * common.h, common.c (cob_cleanup_thread): fix declaration * common.c: drop includes found in coblocal.h * common.c (cob_alloc_module): changed type and name of cob_mod_ptr + * common.h, coblocal.h: added pragma once for better supporting clangd + in single-file mode 2024-08-06 Simon Sobisch diff --git a/libcob/coblocal.h b/libcob/coblocal.h index 11eaf23fd..a8b8e2c6c 100644 --- a/libcob/coblocal.h +++ b/libcob/coblocal.h @@ -577,7 +577,7 @@ COB_HIDDEN char *cob_int_to_formatted_bytestring (int, char*); COB_HIDDEN char *cob_strcat (char*, char*, int); COB_HIDDEN char *cob_strjoin (char**, int, char*); -COB_HIDDEN void cob_runtime_warning_ss (const char *, const char *); +COB_HIDDEN int cob_runtime_warning_ss (const char *, const char *); DECLNORET COB_HIDDEN void cob_hard_failure (void) COB_A_NORETURN; diff --git a/libcob/common.c b/libcob/common.c index bf82f5eec..cfc30f39f 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -18,6 +18,7 @@ along with GnuCOBOL. If not, see . */ +#include "libcob/common.h" #include "tarstamp.h" #include "config.h" @@ -800,7 +801,6 @@ ss_terminate_routines (void) return; } cob_exit_fileio_msg_only (); - cob_exit_screen_from_signal(1); if (COB_MODULE_PTR && abort_reason[0] != 0) { if (cobsetptr->cob_stacktrace) { @@ -824,7 +824,7 @@ cob_terminate_routines (void) } fflush (stderr); - cob_prof_end(); + cob_prof_end (); cob_exit_fileio_msg_only (); if (COB_MODULE_PTR && abort_reason[0] != 0) { @@ -1020,66 +1020,59 @@ set_source_location (const char **file, unsigned int *line) } } -/* write integer to stderr using fixed buffer */ -#define write_to_stderr_or_true_int(i) \ - (write (STDERR_FILENO, ss_itoa_buf, ss_itoa_u10 (i)) == -1) -#define write_to_stderr_or_return_int(i) \ - if (write_to_stderr_or_true_int (i)) return -#define write_to_stderr_until_error_int(i, err) \ - if (!err) err = write_to_stderr_or_true_int (i) - -/* write char array (constant C string) to stderr */ -#define write_to_stderr_or_true_arr(ch_arr) \ - (write (STDERR_FILENO, ch_arr, sizeof (ch_arr) - 1) == -1) -#define write_to_stderr_or_return_arr(ch_arr) \ - if (write_to_stderr_or_true_arr (ch_arr)) return -#define write_to_stderr_until_error_arr(ch_arr,err) \ - if (!err) err = write_to_stderr_or_true_arr (ch_arr) - -/* write string to stderr, byte count computed with strlen, - str is evaluated twice */ -#define write_to_stderr_or_true_str(str) \ - (write (STDERR_FILENO, str, strlen (str)) == -1) -#define write_to_stderr_or_return_str(str) \ - if (write_to_stderr_or_true_str (str)) return -#define write_to_stderr_until_error_str(str,err) \ - if (!err) err = write_to_stderr_or_true_str (str) - -/* write integer to fileno using fixed buffer */ -#define write_or_return_int(fileno,i) \ - if (write (fileno, ss_itoa_buf, ss_itoa_u10 (i)) == -1) return -/* write char array (constant C string) to fileno */ -#define write_or_return_arr(fileno, ch_arr) \ - if (write (fileno, ch_arr, sizeof (ch_arr) - 1) == -1) return -/* write string to fileno, byte count computed with strlen, - str is evaluated twice */ -#define write_or_return_str(fileno,str) \ - if (write (fileno, str, strlen (str)) == -1) return - -#if 0 /* unused */ -/* write buffer with given byte count to stderr */ -#define write_to_stderr_or_return_buf(buff,count) \ - if (write (STDERR_FILENO, buff, count) == -1) return -/* write buffer with given byte count to fileno */ -#define write_or_return_buf(fileno,buff,count) \ - if (write (fileno, buff, count) == -1) return -#endif +/* writes data to fd, returns either the initial size or -1 in case of error */ +static COB_INLINE cob_s64_t +write_until_fail (int fd, const void *data, size_t size) +{ + register cob_s64_t size_to_write = size; + while (size_to_write > 0) { + long bytes_written = write (fd, data, (size_t)size_to_write); + if (bytes_written == -1) { + return 1; + } + data += bytes_written; + size_to_write -= bytes_written; -static void -output_source_location (void) + } + return size; +} + +static COB_INLINE COB_A_INLINE size_t +strcat_to_buff (char *buff, const char *str) +{ + const size_t len = strlen (str); + memcpy (buff, str, len); + return len; +} + +static COB_INLINE COB_A_INLINE size_t +intcat_to_buff (char *buff, const int num) +{ + ss_itoa_u10 (num); + return strcat_to_buff (buff, ss_itoa_buf); +} + +/* stores source location into buff, returns size written (without trailing NUL) */ +static size_t +get_source_location (char *buff) { const char *source_file; unsigned int source_line; + size_t pos = 0; + set_source_location (&source_file, &source_line); if (source_file) { - write_to_stderr_or_return_str (source_file); + pos += strcat_to_buff (buff, source_file); if (source_line) { - write_to_stderr_or_return_arr (":"); - write_to_stderr_or_return_int ((int)source_line); + buff[pos++] = ':'; + pos += intcat_to_buff (buff + pos, source_line); } - write_to_stderr_or_return_arr (": "); + buff[pos++] = ':'; + buff[pos++] = ' '; } + buff[pos] = 0; + return pos; } static int @@ -1124,11 +1117,11 @@ create_dumpfile (void) static void cob_sig_handler (int sig) { + char buff [COB_MEDIUM_BUFF]; + char signal_text[COB_MINI_BUFF]; const char *signal_name; const char *msg; - char signal_text[COB_MINI_BUFF] = { 0 }; - size_t str_len; - int write_err = 0; + size_t pos = 0; #if defined (HAVE_SIGACTION) && !defined (SA_RESETHAND) struct sigaction sa; @@ -1184,10 +1177,10 @@ cob_sig_handler (int sig) /* LCOV_EXCL_START */ if (signal_name == signals[NUM_SIGNALS].shortname) { /* not translated as it is a very unlikely error case */ + pos += strcat_to_buff (buff + pos, "\n" "cob_sig_handler caught not handled signal: "); + pos += intcat_to_buff (buff + pos, sig); + buff[pos++] = '\n'; signal_name = signals[NUM_SIGNALS].description; /* translated unknown */ - write_to_stderr_until_error_arr ("\ncob_sig_handler caught not handled signal: ", write_err); - write_to_stderr_until_error_int (sig, write_err); - write_to_stderr_until_error_arr ("\n", write_err); } /* LCOV_EXCL_STOP */ @@ -1222,38 +1215,44 @@ cob_sig_handler (int sig) #else (void)signal (sig, SIG_DFL); #endif - cob_exit_screen (); + cob_exit_screen_from_signal (1); - write_to_stderr_until_error_arr ("\n", write_err); - if (!write_err) { - cob_get_source_line (); - output_source_location (); + buff[pos++] = '\n'; - msg = cob_get_sig_description (sig); - write_to_stderr_until_error_str (msg, write_err); - } + /* buffer: "prog.cob:1: " */ + pos += get_source_location (buff + pos); + /* buffer: "signal desc" */ + msg = cob_get_sig_description (sig); + pos += strcat_to_buff (buff + pos, msg); + /* setup "signal %s" (for output and abort reason) */ + { - if (!write_err) { - /* setup "signal %s" */ - str_len = strlen (signal_msgid); + const size_t str_len = strlen (signal_msgid); memcpy (signal_text, signal_msgid, str_len); - signal_text[str_len++] = ' '; - memcpy (signal_text + str_len, signal_name, strlen (signal_name)); - - write_to_stderr_until_error_arr (" (", write_err); - write_to_stderr_until_error_str (signal_text, write_err); - write_to_stderr_until_error_arr (")\n\n", write_err); + signal_text[str_len] = ' '; + strcpy (signal_text + str_len + 1, signal_name); } + /* buffer: " (signal %s)" */ + buff[pos++] = ' '; + buff[pos++] = '('; + pos += strcat_to_buff (buff + pos, signal_text); + buff[pos++] = ')'; + + buff[pos++] = '\n'; + buff[pos++] = '\n'; + if (cob_initialized) { if (abort_reason[0] == 0) { memcpy (abort_reason, signal_text, COB_MINI_BUFF); #if 0 /* Is there a use in this message ?*/ - write_to_stderr_until_error_str (abnormal_termination_msgid, write_err); - write_to_stderr_until_error_arr ("\n", write_err); + pos += strcat_to_buff (buff + pos, abnormal_termination_msgid); + buff[pos++] = '\n'; #endif } } + buff[pos] = 0; + write_until_fail (STDERR_FILENO, buff, pos); /* early coredump if requested would be nice, but that is not signal-safe so do SIGABRT later... */ @@ -8698,8 +8697,8 @@ cob_load_config_file (const char *config_file, int isoptional) size = strlen (buff); if (size != 0 && buff[size] == SLASH_CHAR) buff[--size] = 0; if (size != 0) { - snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", buff, SLASH_CHAR, - config_file); + snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", + buff, SLASH_CHAR, config_file); if (access (filename, F_OK) == 0) { /* and prefixed file exist */ config_file = filename; /* Prefix last directory */ } else { @@ -8709,15 +8708,17 @@ cob_load_config_file (const char *config_file, int isoptional) } if (filename[0] == 0) { /* check for COB_CONFIG_DIR (use default if not in environment) */ + int size; penv = getenv ("COB_CONFIG_DIR"); if (penv != NULL) { - snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", + size = snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", penv, SLASH_CHAR, config_file); } else { - snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", + size = snprintf (filename, (size_t)COB_FILE_MAX, "%s%c%s", COB_CONFIG_DIR, SLASH_CHAR, config_file); } - if (access (filename, F_OK) == 0) { /* and prefixed file exist */ + if (size > 0 && size < COB_FILE_MAX + && access (filename, F_OK) == 0) { /* and prefixed file exist */ config_file = filename; /* Prefix COB_CONFIG_DIR */ } } @@ -8882,15 +8883,13 @@ cob_runtime_warning_external (const char *caller_name, const int cob_reference, } /* Prefix */ + fprintf (stderr, "libcob: "); if (cob_reference) { - fflush (stderr); /* necessary as we write afterwards */ - write_to_stderr_or_return_arr ("libcob: "); + char buff[COB_MINI_BUFF]; cob_get_source_line (); - output_source_location (); - } else { - fprintf (stderr, "libcob: "); - } - + get_source_location (buff); + fprintf (stderr, "%s", buff); + } fprintf (stderr, _("warning: ")); if (!(caller_name && *caller_name)) caller_name = "unknown caller"; @@ -8906,26 +8905,34 @@ cob_runtime_warning_external (const char *caller_name, const int cob_reference, fflush (stderr); } -void +/* output non-buffered (signal-async-safe) runtime warning, + returning 1 if write to stderr was not sucessfull */ +int cob_runtime_warning_ss (const char *msg, const char *addition) { - if (cobsetptr && !cobsetptr->cob_display_warn) { - return; - } + if (!cobsetptr + || cobsetptr->cob_display_warn) { + char buff[COB_MEDIUM_BUFF]; + size_t pos = 0; - /* Prefix */ - write_to_stderr_or_return_arr ("libcob: "); - output_source_location (); - write_to_stderr_or_return_str (warning_msgid); + /* Prefix */ + pos += strcat_to_buff (buff, "libcob: "); + pos += get_source_location (buff + pos); + pos += strcat_to_buff (buff + pos, warning_msgid); - /* Body */ - write_to_stderr_or_return_str (msg); - if (addition) { - write_to_stderr_or_return_str (addition); - } + /* Body */ + pos += strcat_to_buff (buff + pos, msg); + if (addition) { + pos += strcat_to_buff (buff + pos, addition); + } - /* Postfix */ - write_to_stderr_or_return_arr ("\n"); + /* Postfix */ + buff[pos++] = '\n'; + buff[pos] = 0; + + return (write_until_fail (STDERR_FILENO, buff, pos) == -1); + } + return 0; } void @@ -8937,14 +8944,16 @@ cob_runtime_warning (const char *fmt, ...) return; } - fflush (stderr); /* necessary as we write afterwards */ /* Prefix */ - write_to_stderr_or_return_arr ("libcob: "); - cob_get_source_line (); - output_source_location (); - - fprintf (stderr, _("warning: ")); /* back to stdio */ + fprintf (stderr, "libcob: "); + { + char buff[COB_MINI_BUFF]; + cob_get_source_line (); + get_source_location (buff); + fprintf (stderr, "%s", buff); + } + fprintf (stderr, _("warning: ")); /* Body */ va_start (args, fmt); @@ -10232,9 +10241,9 @@ void cob_set_main_argv0 (const int argc, char **argv) int i; #ifdef _WIN32 - s = cob_malloc ((size_t)COB_LARGE_BUFF); - i = GetModuleFileNameA (NULL, s, COB_LARGE_MAX); - if (i > 0 && i < COB_LARGE_BUFF) { + s = cob_malloc ((size_t)COB_MEDIUM_BUFF); + i = GetModuleFileNameA (NULL, s, COB_MEDIUM_MAX); + if (i > 0 && i < COB_MEDIUM_BUFF) { cobglobptr->cob_main_argv0 = cob_strdup (s); cob_free (s); return; @@ -10252,9 +10261,9 @@ void cob_set_main_argv0 (const int argc, char **argv) path = NULL; } if (path) { - s = cob_malloc ((size_t)COB_LARGE_BUFF); - i = (int)readlink (path, s, (size_t)COB_LARGE_MAX); - if (i > 0 && i < COB_LARGE_BUFF) { + s = cob_malloc ((size_t)COB_MEDIUM_BUFF); + i = (int)readlink (path, s, (size_t)COB_MEDIUM_MAX); + if (i > 0 && i < COB_MEDIUM_BUFF) { s[i] = 0; cobglobptr->cob_main_argv0 = cob_strdup (s); cob_free (s); @@ -10268,7 +10277,7 @@ void cob_set_main_argv0 (const int argc, char **argv) path = getexecname (); if (path) { #ifdef HAVE_REALPATH - s = cob_malloc ((size_t)COB_LARGE_BUFF); + s = cob_malloc ((size_t)COB_MEDIUM_BUFF); if (realpath (path, s) != NULL) { cobglobptr->cob_main_argv0 = cob_strdup (s); } else { @@ -10607,37 +10616,45 @@ cob_backtrace (void *target, int count) dump_trace_started ^= DUMP_TRACE_ACTIVE_TRACE; } -/* internal output the procedure stack entry to the given target */ -static void -output_procedure_stack_entry (const int file_no, +/* internal output the procedure stack entry to the given buffer, + returns the written length */ +static size_t +output_procedure_stack_entry (char *buff, const char *section, const char *paragraph, const char *source_file, const unsigned int source_line) { + size_t pos = 0; if (!section && !paragraph) { - return; + return 0; } - write_or_return_arr (file_no, "\n\t"); + + buff[pos++] = '\n'; + buff[pos++] = '\t'; if (section && paragraph) { - write_or_return_str (file_no, paragraph); - write_or_return_arr (file_no, " OF "); - write_or_return_str (file_no, section); + pos += strcat_to_buff (buff + pos, paragraph); + pos += strcat_to_buff (buff + pos, " OF "); + pos += strcat_to_buff (buff + pos, section); } else { if (section) { - write_or_return_str (file_no, section); + pos += strcat_to_buff (buff + pos, section); } else { - write_or_return_str (file_no, paragraph); + pos += strcat_to_buff (buff + pos, paragraph); } } - write_or_return_arr (file_no, " at "); - write_or_return_str (file_no, source_file); - write_or_return_arr (file_no, ":"); - write_or_return_int (file_no, (int)source_line); + pos += strcat_to_buff (buff + pos, " at "); + pos += strcat_to_buff (buff + pos, source_file); + buff[pos++] = ':'; + pos += intcat_to_buff (buff + pos, (int)source_line); + buff[pos] = '0'; + return pos; } /* internal output the COBOL-view of the stacktrace to the given target */ void cob_stack_trace_internal (FILE *target, int verbose, int count) { + char buff[COB_MEDIUM_BUFF]; + size_t pos = 0; cob_module *mod; int first_entry = 0; int i, k; @@ -10670,7 +10687,7 @@ cob_stack_trace_internal (FILE *target, int verbose, int count) } if (verbose) { - write_or_return_arr (file_no, "\n"); + buff[pos++] = '\n'; } k = 0; for (mod = COB_MODULE_PTR, i = 0; mod; mod = mod->next, i++) { @@ -10680,64 +10697,71 @@ cob_stack_trace_internal (FILE *target, int verbose, int count) if (count > 0 && count == i) { break; } - write_or_return_arr (file_no, " "); + buff[pos++] = ' '; if (mod->module_stmt != 0 && mod->module_sources) { const unsigned int source_file_num = COB_GET_FILE_NUM (mod->module_stmt); const unsigned int source_line = COB_GET_LINE_NUM (mod->module_stmt); const char *source_file = mod->module_sources[source_file_num]; if (!verbose) { - write_or_return_str (file_no, mod->module_name); - write_or_return_arr (file_no, " at "); - write_or_return_str (file_no, source_file); - write_or_return_arr (file_no, ":"); - write_or_return_int (file_no, (int)source_line); + pos += strcat_to_buff (buff + pos, mod->module_name); + pos += strcat_to_buff (buff + pos, " at "); + pos += strcat_to_buff (buff + pos, source_file); + buff[pos++] = ':'; + pos += intcat_to_buff (buff + pos, (int)source_line); } else if (mod->statement == STMT_UNKNOWN && !mod->section_name && !mod->paragraph_name) { /* GC 3.1 output, now used for "no source location / no trace" case */ - write_or_return_arr (file_no, "Last statement of "); + pos += strcat_to_buff (buff + pos, "Last statement of "); if (mod->module_type == COB_MODULE_TYPE_FUNCTION) { - write_or_return_arr (file_no, "FUNCTION "); + pos += strcat_to_buff (buff + pos, "FUNCTION "); } - write_or_return_arr (file_no, "\""); - write_or_return_str (file_no, mod->module_name); - write_or_return_arr (file_no, "\" was at line "); - write_or_return_int (file_no, (int)source_line); - write_or_return_arr (file_no, " of "); - write_or_return_str (file_no, source_file); + buff[pos++] = '"'; + pos += strcat_to_buff (buff + pos, mod->module_name); + pos += strcat_to_buff (buff + pos, "\" was at line "); + pos += intcat_to_buff (buff + pos, (int)source_line); + pos += strcat_to_buff (buff + pos, " of "); + pos += strcat_to_buff (buff + pos, source_file); } else if (!mod->section_name && !mod->paragraph_name) { /* special case: there _would_ be data, but there's no procedure defined in the program */ - write_or_return_arr (file_no, "Last statement of "); + pos += strcat_to_buff (buff + pos, "Last statement of "); if (mod->module_type == COB_MODULE_TYPE_FUNCTION) { - write_or_return_arr (file_no, "FUNCTION "); + pos += strcat_to_buff (buff + pos, "FUNCTION "); } - write_or_return_arr (file_no, "\""); - write_or_return_str (file_no, mod->module_name); - write_or_return_arr (file_no, "\" was "); - write_or_return_str (file_no, cob_statement_name[mod->statement]); - write_or_return_arr (file_no, " at line "); - write_or_return_int (file_no, (int)source_line); - write_or_return_arr (file_no, " of "); - write_or_return_str (file_no, source_file); + buff[pos++] = '"'; + pos += strcat_to_buff (buff + pos, mod->module_name); + pos += strcat_to_buff (buff + pos, "\" was "); + pos += strcat_to_buff (buff + pos, cob_statement_name[mod->statement]); + pos += strcat_to_buff (buff + pos, " at line "); + pos += intcat_to_buff (buff + pos, (int)source_line); + pos += strcat_to_buff (buff + pos, " of "); + pos += strcat_to_buff (buff + pos, source_file); } else { /* common case when compiled with runtime checks enabled: statement and procedure known - the later is printed from the stack entry with the source location by the following call */ - write_or_return_arr (file_no, "Last statement of "); + pos += strcat_to_buff (buff + pos, "Last statement of "); if (mod->module_type == COB_MODULE_TYPE_FUNCTION) { - write_or_return_arr (file_no, "FUNCTION "); + pos += strcat_to_buff (buff + pos, "FUNCTION "); } - write_or_return_arr (file_no, "\""); - write_or_return_str (file_no, mod->module_name); - write_or_return_arr (file_no, "\" was "); - write_or_return_str (file_no, cob_statement_name[mod->statement]); + buff[pos++] = '"'; + pos += strcat_to_buff (buff + pos, mod->module_name); + pos += strcat_to_buff (buff + pos, "\" was "); + pos += strcat_to_buff (buff + pos, cob_statement_name[mod->statement]); } - output_procedure_stack_entry (file_no, mod->section_name, mod->paragraph_name, + pos += output_procedure_stack_entry (buff + pos, + mod->section_name, mod->paragraph_name, source_file, source_line); + if (pos > COB_MEDIUM_MAX - COB_FILE_MAX) { + if (write_until_fail (file_no, buff, pos) == -1) { + return; + } + pos = 0; + } if (mod->frame_ptr) { struct cob_frame_ext *perform_ptr = mod->frame_ptr; int frame_max = 512; /* max from -fstack-size */ @@ -10748,71 +10772,92 @@ cob_stack_trace_internal (FILE *target, int verbose, int count) if (perform_ptr->section_name) { /* marker for "root frame" - at ENTRY */ if (perform_ptr->section_name[0] == 0) { - write_or_return_arr (file_no, "\n\tENTRY "); - write_or_return_str (file_no, perform_ptr->paragraph_name); - write_or_return_arr (file_no, " at "); - write_or_return_str (file_no, ffile); - write_or_return_arr (file_no, ":"); - write_or_return_int (file_no, (int)fline); + pos += strcat_to_buff (buff + pos, "\n\t" "ENTRY "); + pos += strcat_to_buff (buff + pos, perform_ptr->paragraph_name); + pos += strcat_to_buff (buff + pos, " at "); + pos += strcat_to_buff (buff + pos, ffile); + buff[pos++] = ':'; + pos += intcat_to_buff (buff + pos, (int)fline); break; } } - output_procedure_stack_entry (file_no, + pos += output_procedure_stack_entry (buff + pos, perform_ptr->section_name, perform_ptr->paragraph_name, ffile, fline); + if (pos > COB_MEDIUM_MAX - COB_FILE_MAX) { + if (write_until_fail (file_no, buff, pos) == -1) { + return; + } + pos = 0; + } perform_ptr--; } } } else { if (verbose) { - write_or_return_arr (file_no, "Last statement of "); + pos += strcat_to_buff (buff + pos, "Last statement of "); if (mod->module_type == COB_MODULE_TYPE_FUNCTION) { - write_or_return_arr (file_no, "FUNCTION "); + pos += strcat_to_buff (buff + pos, "FUNCTION "); } - write_or_return_arr (file_no, "\""); - write_or_return_str (file_no, mod->module_name); + buff[pos++] = '"'; + pos += strcat_to_buff (buff + pos, mod->module_name); if (mod->statement != STMT_UNKNOWN) { - write_or_return_arr (file_no, "\" was "); - write_or_return_str (file_no, cob_statement_name[mod->statement]); + pos += strcat_to_buff (buff + pos, "\" was "); + pos += strcat_to_buff (buff + pos, cob_statement_name[mod->statement]); } else { - write_or_return_arr (file_no, "\" unknown"); + pos += strcat_to_buff (buff + pos, "\" unknown"); } } else { - write_or_return_str (file_no, mod->module_name); - write_or_return_arr (file_no, " at unknown"); + pos += strcat_to_buff (buff + pos, mod->module_name); + pos += strcat_to_buff (buff + pos, " at unknown"); } } - write_or_return_arr (file_no, "\n"); + buff[pos++] = '\n'; if (mod->next == mod) { /* not translated as highly unexpected */ - write_or_return_arr (file_no, "FIXME: recursive mod (stack trace)\n"); + pos += strcat_to_buff (buff + pos, + "FIXME: recursive mod (stack trace)" "\n"); break; } if (k++ == MAX_MODULE_ITERS) { /* not translated as highly unexpected */ - write_or_return_arr (file_no, - "max module iterations exceeded, possible broken chain\n"); + pos += strcat_to_buff (buff + pos, + "max module iterations exceeded, possible broken chain" "\n"); break; } } if (mod) { - write_or_return_arr (file_no, " "); - write_or_return_str (file_no, more_stack_frames_msgid); - write_or_return_arr (file_no, "\n"); + buff[pos++] = ' '; + pos += strcat_to_buff (buff + pos, more_stack_frames_msgid); + buff[pos++] = '\n'; + } + if (pos > COB_MEDIUM_MAX - COB_FILE_MAX) { + if (write_until_fail (file_no, buff, pos) == -1) { + return; + } + pos = 0; } if (verbose && cob_argc != 0) { - size_t ia; - write_or_return_arr (file_no, " Started by "); - write_or_return_str (file_no, cob_argv[0]); - write_or_return_arr (file_no, "\n"); - for (ia = 1; ia < (size_t)cob_argc; ++ia) { - write_or_return_arr (file_no, "\t"); - write_or_return_str (file_no, cob_argv[ia]); - write_or_return_arr (file_no, "\n"); + const unsigned int ia_max = (unsigned int)cob_argc; + unsigned int ia; + pos += strcat_to_buff (buff + pos, " Started by "); + pos += strcat_to_buff (buff + pos, cob_argv[0]); + buff[pos++] = '\n'; + for (ia = 1; ia < ia_max; ++ia) { + buff[pos++] = '\t'; + pos += strcat_to_buff (buff + pos, cob_argv[ia]); + buff[pos++] = '\n'; + if (pos > COB_MEDIUM_MAX - COB_FILE_MAX) { + if (write_until_fail (file_no, buff, pos) == -1) { + return; + } + pos = 0; + } } } + write_until_fail (file_no, buff, pos); } FILE * @@ -10923,6 +10968,7 @@ cob_dump_module (char *reason) fputc ('\n', fp); fprintf (fp, _("Module dump due to %s"), reason); fputc ('\n', fp); + fflush (fp); } if (fp != stdout) { /* was already sent to stderr before this function was called, @@ -10933,7 +10979,6 @@ cob_dump_module (char *reason) dump_trace_started ^= DUMP_TRACE_ACTIVE_TRACE; } } - fflush (stdout); } else { fflush (stderr); } diff --git a/libcob/fileio.c b/libcob/fileio.c index f5bbc61cf..936c42f24 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -20,6 +20,7 @@ #include "config.h" +#include "libcob/common.h" #define _LFS64_LARGEFILE 1 #define _LFS64_STDIO 1 @@ -8768,7 +8769,6 @@ cob_get_filename_print (cob_file* file, const int show_resolved_name) cobsetpr-values with type ENV_PATH or ENV_STR like bdb_home and cob_file_path are taken care in cob_exit_common()! */ - const char *implicit_close_of_msgid = NULL; void @@ -8777,7 +8777,8 @@ cob_exit_fileio_msg_only (void) struct file_list *l; static int output_done = 0; - if (output_done) { + if (output_done + || (cobsetptr && !cobsetptr->cob_display_warn)) { return; } output_done = 1; @@ -8788,8 +8789,10 @@ cob_exit_fileio_msg_only (void) && l->file->open_mode != COB_OPEN_LOCKED && !l->file->flag_nonexistent && !COB_FILE_SPECIAL (l->file)) { - cob_runtime_warning_ss (implicit_close_of_msgid, - cob_get_filename_print (l->file, 0)); + if (cob_runtime_warning_ss (implicit_close_of_msgid, + cob_get_filename_print (l->file, 0))) { + return; + } } } } From ca09f172185ffbfa821a01030c9a873e26d8dff1 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Fri, 4 Oct 2024 15:38:31 +0000 Subject: [PATCH 07/10] minor testuite update to drop user-reported warnings from compiler/linker --- tests/testsuite.src/listings.at | 10 ++- tests/testsuite.src/run_file.at | 8 +- tests/testsuite.src/run_misc.at | 125 +++++++++++++++------------ tests/testsuite.src/syn_functions.at | 5 +- 4 files changed, 85 insertions(+), 63 deletions(-) diff --git a/tests/testsuite.src/listings.at b/tests/testsuite.src/listings.at index 2a2fb68a6..26d90b67e 100644 --- a/tests/testsuite.src/listings.at +++ b/tests/testsuite.src/listings.at @@ -6913,7 +6913,8 @@ AT_CLEANUP AT_SETUP([Long concatenated literal]) AT_KEYWORDS([listing overflow]) -AT_DATA([prog.cob], [ +# extra quoting here as we received a bug report of something adding a leading ( +AT_DATA([prog.cob], [[ >>SOURCE FORMAT IS FREE ID DIVISION. PROGRAM-ID. ED000MAIN IS INITIAL. @@ -6935,10 +6936,11 @@ WORKING-STORAGE SECTION. "1234567890123456789012". PROCEDURE DIVISION. EXIT. -]) +]]) +# extra quoting here as we received a bug report of something adding a leading ( AT_CHECK([$COMPILE_LISTING0 -t- prog.cob], [0], -[GnuCOBOL V.R.P prog.cob +[[GnuCOBOL V.R.P prog.cob LINE PG/LN A...B............................................................ @@ -6980,7 +6982,7 @@ LINE PG/LN A...B............................................................ 0 warnings in compilation group 0 errors in compilation group -]) +]]) AT_CLEANUP diff --git a/tests/testsuite.src/run_file.at b/tests/testsuite.src/run_file.at index 2aed60f08..f7fbbfe8c 100644 --- a/tests/testsuite.src/run_file.at +++ b/tests/testsuite.src/run_file.at @@ -9102,7 +9102,6 @@ TSTFH (unsigned char *opCodep, FCD3 *fcd) static char * /* Return Text name of function */ txtOpCode(int opCode) { - static char tmp[32]; switch (opCode) { case OP_OPEN_INPUT: return "OPEN_IN"; case OP_OPEN_OUTPUT: return "OPEN_OUT"; @@ -9154,8 +9153,11 @@ txtOpCode(int opCode) case OP_WRITE_AFTER_TAB: return "WRITE_AFTER_TAB"; case OP_WRITE_AFTER_PAGE: return "WRITE_AFTER_PAGE"; } - sprintf(tmp, "Func 0x%02X:", opCode); - return tmp; + { + static char wrk[20]; + snprintf (wrk, sizeof(wrk), "Func 0x%02X", opCode); + return wrk; + } } ]]) diff --git a/tests/testsuite.src/run_misc.at b/tests/testsuite.src/run_misc.at index 914a8f4a1..cd7cf27e6 100644 --- a/tests/testsuite.src/run_misc.at +++ b/tests/testsuite.src/run_misc.at @@ -11866,7 +11866,6 @@ AT_DATA([cmod.c], [[ static char * getType (int type, int byvalue) { - static char wrk[24]; switch (type) { #if 1 case COB_TYPE_GROUP: return "Group"; @@ -11897,28 +11896,30 @@ getType (int type, int byvalue) case COB_TYPE_NATIONAL: return "N"; #endif } - sprintf (wrk,"Type %04X",type); - return wrk; + { + static char wrk[20]; + snprintf (wrk, sizeof(wrk), "Type 0x%04X", type); + return wrk; + } } COB_EXT_EXPORT int CAPI (void *p1, ...) { - int k,nargs,type,digits,scale,size,sign,byvalue; - cob_s64_t val = 0; - char *str; - char wrk[80],pic[30]; /* note: maximum _theoretical_ size */ + char wrk[80], pic[30]; /* note: maximum _theoretical_ size */ + const int nargs = cob_get_num_params(); + int k; + cob_s64_t val = 0; - nargs = cob_get_num_params(); printf ("CAPI called with %d parameters\n",nargs); - fflush(stdout); + fflush (stdout); for (k=1; k <= nargs; k++) { - type = cob_get_param_type (k); - digits = cob_get_param_digits (k); - scale = cob_get_param_scale (k); - size = cob_get_param_size (k); - sign = cob_get_param_sign (k); - byvalue = cob_get_param_constant(k); + int type = cob_get_param_type (k); + int digits = cob_get_param_digits (k); + int scale = cob_get_param_scale (k); + int size = cob_get_param_size (k); + int sign = cob_get_param_sign (k); + int byvalue = cob_get_param_constant(k); printf (" %d: %-8s ", k, getType (type, byvalue)); if (byvalue) { printf ("BY VALUE "); @@ -11926,27 +11927,31 @@ CAPI (void *p1, ...) printf ("BY REFERENCE "); } if (type == COB_TYPE_ALPHANUMERIC) { - sprintf (pic, "X(%d)", size); - str = cob_get_picx_param (k, NULL, 0); + char *str = cob_get_picx_param (k, NULL, 0); + snprintf (pic, sizeof(pic), "X(%d)", size); printf ("%-11s '%s'", pic, str); cob_free ((void*)str); cob_put_picx_param (k, "Bye!"); } else if (type == COB_TYPE_NATIONAL) { - sprintf (pic, "N(%d)", size); /* FIXME */ + snprintf (pic, sizeof(pic), "N(%d)", size); /* FIXME */ printf ("exchange of national data is not supported yet"); } else if (type == COB_TYPE_GROUP) { - sprintf (pic, "(%d)", size); - str = cob_get_grp_param (k, NULL, 0); + char *str = cob_get_grp_param (k, NULL, 0); + snprintf (pic, sizeof(pic), "(%d)", size); printf ("%-11s '%.*s'", pic, size, str); cob_free ((void*)str); - memset (wrk,' ',sizeof(wrk)); - memcpy (wrk,"Bye-Bye Birdie!",15); + memset (wrk, ' ',sizeof(wrk)); + memcpy (wrk, "Bye-Bye Birdie!", 15); cob_put_grp_param (k, wrk, sizeof(wrk)); } else if (type == COB_TYPE_NUMERIC_EDITED) { if (scale > 0) { - sprintf (pic,"%s9(%d)V9(%d)",sign?"S":"",digits-scale,scale); + snprintf (pic, sizeof(pic), "%s9(%d)V9(%d)", + sign ? "S":"", + digits - scale, scale); } else { - sprintf (pic,"%s9(%d)",sign?"S":"",digits-scale); + snprintf (pic, sizeof(pic), "%s9(%d)", + sign ? "S":"", + digits - scale); } val = cob_get_s64_param (k); printf ("%-11s %lld ",pic,val); @@ -11957,9 +11962,13 @@ CAPI (void *p1, ...) printf (" to %.*s",size,wrk); } else { if(scale > 0) { - sprintf (pic,"%s9(%d)V9(%d)",sign?"S":"",digits-scale,scale); + snprintf (pic, sizeof(pic), "%s9(%d)V9(%d)", + sign ? "S":"", + digits - scale, scale); } else { - sprintf (pic,"%s9(%d)",sign?"S":"",digits-scale); + snprintf (pic, sizeof(pic), "%s9(%d)", + sign ? "S":"", + digits - scale); } val = cob_get_s64_param (k); printf ("%-11s %lld", pic, val); @@ -12046,7 +12055,7 @@ AT_CLEANUP AT_SETUP([C-API (field based)]) -AT_KEYWORDS([runmisc CALL api]) +AT_KEYWORDS([runmisc CALL api field]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -12102,7 +12111,6 @@ AT_DATA([cmod.c], [[ static char * getType (int type, int byvalue) { - static char wrk[24]; switch (type) { #if 1 case COB_TYPE_GROUP: return "Group"; @@ -12133,73 +12141,82 @@ getType (int type, int byvalue) case COB_TYPE_NATIONAL: return "N"; #endif } - sprintf (wrk,"Type %04X",type); - return wrk; + { + static char wrk[20]; + snprintf (wrk, sizeof(wrk), "Type 0x%04X", type); + return wrk; + } } COB_EXT_EXPORT int CAPI (void *p1, ...) { - int k,nargs,type,digits,scale,size,sign,byvalue; - cob_s64_t val; - char *str; - char wrk[80],pic[30]; /* note: maximum _theoretical_ size */ + char wrk[80],pic[30]; /* note: maximum _theoretical_ size */ + const int nargs = cob_get_num_params(); + int k; - nargs = cob_get_num_params(); printf ("CAPI called with %d parameters\n",nargs); - fflush(stdout); + fflush (stdout); for (k=1; k <= nargs; k++) { cob_field *fld = cob_get_param_field (k, "CAPI"); - type = cob_get_field_type (fld); - digits = cob_get_field_digits (fld); - scale = cob_get_field_scale (fld); - size = cob_get_field_size (fld); - sign = cob_get_field_sign (fld); - byvalue = cob_get_field_constant (fld); + char *str = (char *) cob_get_field_str_buffered (fld); + int type = cob_get_field_type (fld); + int digits = cob_get_field_digits (fld); + int scale = cob_get_field_scale (fld); + int size = cob_get_field_size (fld); + int sign = cob_get_field_sign (fld); + int byvalue = cob_get_field_constant (fld); printf (" %d: %-8s ", k, getType (type, byvalue)); if (byvalue) { printf ("BY VALUE "); } else { printf ("BY REFERENCE "); } - str = (char *) cob_get_field_str_buffered (fld); if (type == COB_TYPE_ALPHANUMERIC) { - sprintf (pic, "X(%d)", size); + snprintf (pic, sizeof(pic), "X(%d)", size); printf ("%-11s '%s'", pic, str); cob_put_field_str (fld, "Bye!"); } else if (type == COB_TYPE_NATIONAL) { - sprintf (pic,"N(%d)",size); /* FIXME */ + snprintf (pic, sizeof(pic), "N(%d)", size); /* FIXME */ printf ("exchange of national data is not supported yet"); } else if (type == COB_TYPE_GROUP) { - sprintf (pic,"(%d)",size); + snprintf (pic, sizeof(pic), "(%d)",size); printf ("%-11s '%.*s'",pic,size,str); cob_put_field_str (fld, "Bye-Bye Birdie!"); } else if (type == COB_TYPE_NUMERIC_EDITED) { + cob_s64_t val = cob_get_s64_param (k); if (scale > 0) { - sprintf (pic,"%s9(%d)V9(%d)",sign?"S":"",digits-scale,scale); + snprintf (pic, sizeof(pic), "%s9(%d)V9(%d)", + sign ? "S":"", + digits - scale, scale); } else { - sprintf (pic,"%s9(%d)",sign?"S":"",digits-scale); + snprintf (pic, sizeof(pic), "%s9(%d)", + sign ? "S":"", + digits - scale); } printf ("%-11s %s ",pic,str); - val = cob_get_s64_param (k); val = val + 130; val = -val; cob_put_s64_param (k, val); str = (char *) cob_get_field_str (fld, wrk, 78); printf (" to %.*s",size,wrk); } else { + cob_s64_t val = cob_get_s64_param (k); if(scale > 0) { - sprintf (pic,"%s9(%d)V9(%d)",sign?"S":"",digits-scale,scale); + snprintf (pic, sizeof(pic), "%s9(%d)V9(%d)", + sign ? "S":"", + digits - scale, scale); } else { - sprintf (pic,"%s9(%d)",sign?"S":"",digits-scale); + snprintf (pic, sizeof(pic), "%s9(%d)", + sign ? "S":"", + digits - scale); } printf ("%-11s %s", pic, str); - val = cob_get_s64_param (k); - sprintf (wrk, "%lld", val + 3); + snprintf (wrk, sizeof(wrk), "%lld", val + 3); cob_put_field_str (fld, wrk); } printf (";\n"); - fflush(stdout); + fflush (stdout); } return 0; } diff --git a/tests/testsuite.src/syn_functions.at b/tests/testsuite.src/syn_functions.at index 53735c571..27f3e2773 100644 --- a/tests/testsuite.src/syn_functions.at +++ b/tests/testsuite.src/syn_functions.at @@ -582,10 +582,11 @@ AT_DATA([prog.cob], [ . ]) +# extra quoting here as we received a bug report of something adding a leading ( AT_CHECK([$COMPILE -Wno-pending prog.cob], [1], [], -[prog.cob:7: error: syntax error, unexpected Literal, expecting PHYSICAL or ) +[[prog.cob:7: error: syntax error, unexpected Literal, expecting PHYSICAL or ) prog.cob:8: error: a non-numeric literal is expected here prog.cob:9: error: a non-numeric literal is expected here -]) +]]) AT_CLEANUP From ef11be499f4c6f2a3f6907443d54590e1db6f659 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Fri, 4 Oct 2024 15:53:21 +0000 Subject: [PATCH 08/10] fix previous commit --- libcob/common.c | 1 - libcob/fileio.c | 1 - 2 files changed, 2 deletions(-) diff --git a/libcob/common.c b/libcob/common.c index cfc30f39f..828762145 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -18,7 +18,6 @@ along with GnuCOBOL. If not, see . */ -#include "libcob/common.h" #include "tarstamp.h" #include "config.h" diff --git a/libcob/fileio.c b/libcob/fileio.c index 936c42f24..509623452 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -20,7 +20,6 @@ #include "config.h" -#include "libcob/common.h" #define _LFS64_LARGEFILE 1 #define _LFS64_STDIO 1 From 83ec07716d30732e050c0b6b96ecf5b462045e21 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Fri, 4 Oct 2024 18:42:50 +0000 Subject: [PATCH 09/10] portability fix for last commits --- libcob/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcob/common.c b/libcob/common.c index 828762145..00c5d9a40 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -1021,7 +1021,7 @@ set_source_location (const char **file, unsigned int *line) /* writes data to fd, returns either the initial size or -1 in case of error */ static COB_INLINE cob_s64_t -write_until_fail (int fd, const void *data, size_t size) +write_until_fail (int fd, const char *data, size_t size) { register cob_s64_t size_to_write = size; while (size_to_write > 0) { From b583a357302ad882fd2ac6565f823d9750b46e37 Mon Sep 17 00:00:00 2001 From: sf-mensch Date: Tue, 8 Oct 2024 23:37:24 +0000 Subject: [PATCH 10/10] build and test updates * configure: check expected json-c header first * tests: * atlocal.in, atlocal_win: export new definition COB_ON_WINDOWS to allow the testsuite skipping/failing tests - and applied it to used_binaries.at * run_prog_manual.sh.in: fix extranous $COBCRUN for all test runners * run_prog_manual.sh.in (xterm): use all parameters, not only the first * build_windows/set_env_vs_dist: supporting space-included paths (not recommended) --- build_windows/ChangeLog.txt | 8 ++++++-- build_windows/set_env_vs_x64.cmd | 4 ++-- build_windows/set_env_vs_x64.dist.tmpl.cmd | 4 ++-- build_windows/set_env_vs_x86.cmd | 4 ++-- build_windows/set_env_vs_x86.dist.tmpl.cmd | 2 +- configure.ac | 2 +- tests/ChangeLog | 7 +++++++ tests/atlocal.in | 18 +++++++++++++----- tests/atlocal_win | 3 +++ tests/run_prog_manual.sh.in | 8 ++++---- tests/testsuite.src/used_binaries.at | 12 ++++++++---- 11 files changed, 49 insertions(+), 23 deletions(-) diff --git a/build_windows/ChangeLog.txt b/build_windows/ChangeLog.txt index a4b7b78dc..9eba7e07d 100644 --- a/build_windows/ChangeLog.txt +++ b/build_windows/ChangeLog.txt @@ -1,4 +1,8 @@ +2024-10-07 Simon Sobisch + + * set_env_vs_dist: supporting space-included paths (not recommended) + 2024-05-15 Simon Sobisch * makedist.cmd: cater for new different library names @@ -315,7 +319,7 @@ * update for subfolder vc10 -2014-07-07 Philipp Böhme +2014-07-07 Philipp B�hme * minor bugfix (tpyos) for subfolder vc12 @@ -326,7 +330,7 @@ * updated all project files * added subfolder vc11 -2014-06-20 Philipp Böhme +2014-06-20 Philipp B�hme * added project files - subfolders: vc7, vc8, vc9, vc10, vc12 (original project files and resource files version_cobc.rc, diff --git a/build_windows/set_env_vs_x64.cmd b/build_windows/set_env_vs_x64.cmd index 4fde7ca57..4c905c9f3 100644 --- a/build_windows/set_env_vs_x64.cmd +++ b/build_windows/set_env_vs_x64.cmd @@ -1,4 +1,4 @@ -:: Copyright (C) 2014-2020 Free Software Foundation, Inc. +:: Copyright (C) 2014-2020,2024 Free Software Foundation, Inc. :: Written by Simon Sobisch, Edward Hart :: :: This file is part of GnuCOBOL. @@ -36,4 +36,4 @@ if %errorlevel% equ 0 ( set "stay_open=x" ) -call %~dp0gcvsvars.cmd %* +call "%~dp0gcvsvars.cmd" %* diff --git a/build_windows/set_env_vs_x64.dist.tmpl.cmd b/build_windows/set_env_vs_x64.dist.tmpl.cmd index 6c5dd8e68..31afef62b 100644 --- a/build_windows/set_env_vs_x64.dist.tmpl.cmd +++ b/build_windows/set_env_vs_x64.dist.tmpl.cmd @@ -1,4 +1,4 @@ -:: Copyright (C) 2014-2020 Free Software Foundation, Inc. +:: Copyright (C) 2014-2020,2024 Free Software Foundation, Inc. :: Written by Simon Sobisch, Edward Hart :: :: This file is part of GnuCOBOL. @@ -36,4 +36,4 @@ if %errorlevel% equ 0 ( set "stay_open=x" ) -call %~dp0gcvsvars.cmd %* +call "%~dp0gcvsvars.cmd" %* diff --git a/build_windows/set_env_vs_x86.cmd b/build_windows/set_env_vs_x86.cmd index c80706ba6..8fc7e2007 100644 --- a/build_windows/set_env_vs_x86.cmd +++ b/build_windows/set_env_vs_x86.cmd @@ -1,4 +1,4 @@ -:: Copyright (C) 2014-2020 Free Software Foundation, Inc. +:: Copyright (C) 2014-2020,2024 Free Software Foundation, Inc. :: Written by Simon Sobisch, Edward Hart :: :: This file is part of GnuCOBOL. @@ -39,4 +39,4 @@ if %errorlevel% equ 0 ( set "stay_open=x" ) -call %~dp0gcvsvars.cmd %* +call "%~dp0gcvsvars.cmd" %* diff --git a/build_windows/set_env_vs_x86.dist.tmpl.cmd b/build_windows/set_env_vs_x86.dist.tmpl.cmd index e8e01d7f6..4a160b87d 100644 --- a/build_windows/set_env_vs_x86.dist.tmpl.cmd +++ b/build_windows/set_env_vs_x86.dist.tmpl.cmd @@ -36,4 +36,4 @@ if %errorlevel% equ 0 ( set "stay_open=x" ) -call %~dp0gcvsvars.cmd %* +call "%~dp0gcvsvars.cmd" %* diff --git a/configure.ac b/configure.ac index 126e2a363..703d359b2 100644 --- a/configure.ac +++ b/configure.ac @@ -1222,7 +1222,7 @@ AS_IF([test "$USE_JSON" = "json-c" -o "$USE_JSON" = check], [ JSON_C_LIBS="-ljson-c" fi LIBS="$LIBS $LIBCOB_LIBS_extern $JSON_C_LIBS" - AC_CHECK_HEADERS([json.h json-c/json.h], [break], + AC_CHECK_HEADERS([json-c/json.h json.h], [break], [if test "$with_json" = "json-c"; then AC_MSG_ERROR([header for libjson-c is required for --with-json=json-c, you may adjust JSON_C_CFLAGS]) else diff --git a/tests/ChangeLog b/tests/ChangeLog index b99d0ba74..29e095b7f 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,11 @@ +2024-10-05 Simon Sobisch + + * atlocal.in, atlocal_win: export new definition COB_ON_WINDOWS + to allow the testsuite skipping/failing tests + * run_prog_manual.sh.in: fix extranous $COBCRUN for all test runners + * run_prog_manual.sh.in (xterm): use all parameters, not only the first + 2024-10-02 Simon Sobisch * atlocal.in, atlocal_win: allow overriding COB_CC during tests diff --git a/tests/atlocal.in b/tests/atlocal.in index d2f0a4429..254e08e59 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -225,11 +225,19 @@ set_utf8_locale () { } # ensure we don't execute windows paths within programs generated by cygwin -# by passing a hint -if test "$OSTYPE" = "cygwin"; then - COB_ON_CYGWIN=1 - export COB_ON_CYGWIN -fi +# by passing a hint and to (not) skip some tests that are portable in all +# environments but Windows +case "$OSTYPE" in + msys*|win* ) + # Windows but not Cygwin + COB_ON_WINDOWS=yes + export COB_ON_WINDOWS + ;; + cygwin* ) + COB_ON_CYGWIN=yes + export COB_ON_CYGWIN + ;; +esac # Fix for testcases where cobc translates path to win32 equivalents if test "x$MSYSTEM" != "x"; then diff --git a/tests/atlocal_win b/tests/atlocal_win index 8cf1e85cf..3cdb892d4 100644 --- a/tests/atlocal_win +++ b/tests/atlocal_win @@ -125,6 +125,9 @@ set_utf8_locale () { # Note: we explicit do not set COB_ON_CYGWIN here, # as this is file is about running non-cygwin binaries + # Windows but not Cygwin + COB_ON_WINDOWS=1 + export COB_ON_WINDOWS # Fix for testcases where cobc uses win32 paths internally PATHSEP=";" diff --git a/tests/run_prog_manual.sh.in b/tests/run_prog_manual.sh.in index aad4f79f2..dd063596e 100755 --- a/tests/run_prog_manual.sh.in +++ b/tests/run_prog_manual.sh.in @@ -69,7 +69,7 @@ TITLE="GnuCOBOL Manual Test Run - $DESC" _test_with_xterm () { xterm -T "$TITLE" \ -fa 'Liberation Mono' -fs 14 \ - -e "sh -c \"(\$COBCRUN_DIRECT $1 2>./syserr.log && echo \$? > ./result) || echo 1 > ./result\"" + -e "sh -c \"(\$* 2>./syserr.log && echo \$? > ./result) || echo 1 > ./result\"" } @@ -92,7 +92,7 @@ _test_with_screen () { fi # run actual test in screen session screen -S "GCTESTS" -X title "$TITLE" - screen -S "GCTESTS" -X exec ... sh -c "cd \"$PWD\" && ($COBCRUN_DIRECT $* 2>./syserr.log && echo $? > ./result) || echo 1 > ./result" + screen -S "GCTESTS" -X exec ... sh -c "cd \"$PWD\" && ($* 2>./syserr.log && echo $? > ./result) || echo 1 > ./result" } _attach_to_screen () { test -d "$SCREENDIR" && (screen -r "GCTESTS" ; true) && exit @@ -119,7 +119,7 @@ _test_with_tmux () { fi # run actual test in screen session tmux rename-window -t "=GCTESTS:0" "$TITLE" - tmux send-keys -t "=GCTESTS:0" "sh -c \"cd \\\"$PWD\\\" && ($COBCRUN_DIRECT $* 2>./syserr.log && echo $? > ./result) || echo 1 > ./result; echo\"" C-m + tmux send-keys -t "=GCTESTS:0" "sh -c \"cd \\\"$PWD\\\" && ($* 2>./syserr.log && echo $? > ./result) || echo 1 > ./result; echo\"" C-m } _attach_to_tmux () { tmux attach -t "=GCTESTS:0" @@ -133,7 +133,7 @@ _kill_tmux () { _test_with_cmd () { # run cmd to start a detached cmd (via cmd's start), and execute the tests there, # to work around quoting issues we create a sub-cmd - echo "$COBCRUN_DIRECT $(echo $* | tr '/' '\\') 2>syserr.log & echo !errorlevel! >result" > run_manual.cmd + echo "$(echo $* | tr '/' '\\') 2>syserr.log & echo !errorlevel! >result" > run_manual.cmd cmd.exe /c "start \"$TITLE\" /wait cmd /v:on /c run_manual.cmd" #if test -f ./syserr.log; then # dos2unix -q ./syserr.log diff --git a/tests/testsuite.src/used_binaries.at b/tests/testsuite.src/used_binaries.at index 0e200a960..405c48d0f 100644 --- a/tests/testsuite.src/used_binaries.at +++ b/tests/testsuite.src/used_binaries.at @@ -359,9 +359,8 @@ AT_CLEANUP AT_SETUP([temporary path invalid]) AT_KEYWORDS([cobc runmisc]) -# Note: may be either removed completely as there was a report about -# this test "failing" - or skipped as this very often fails for -# WIN32 builds +# Note: we skip this as it often fails for WIN32 builds but sometimes works +AT_SKIP_IF([test "$COB_ON_WINDOWS" = "yes"]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1379,7 +1378,7 @@ AT_DATA([prog.cob], [ ]) AT_CHECK([$COMPILE prog.cob], [0], [], []) -AT_CHECK([$COBCRUN_DIRECT ./prog| head -n 2], [0], +AT_CHECK([$COBCRUN_DIRECT ./prog | head -n 2], [0], [1 2 ], []) @@ -1390,6 +1389,11 @@ AT_CLEANUP AT_SETUP([signal handling SIGTERM in COBOL]) AT_KEYWORDS([runmisc stack stacktrace]) +# this is portable in all posix environments, but not on Win32; +# note: cygwin-compiled programs handle cygwin-sent SIGTERM as expected +# CTRL+C does raise a SIGINT, but only when executed from "within" the program +AT_XFAIL_IF([test "$COB_ON_WINDOWS" = "yes"]) + AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. PROGRAM-ID. 'prog'.