From 7fafce3c1890d59a7404383b70ed7cd068088b27 Mon Sep 17 00:00:00 2001 From: Fabrice Le Fessant Date: Tue, 17 Oct 2023 23:41:08 +0200 Subject: [PATCH 1/2] Add a settings file to configure cobc at runtime New --settings=FILE can be used to configure flags that are normally set at compile time. These settings can be used typically to create cross-compilers by retargetting an existing compiler. Also add a setting to make the compiler relocatable, i.e. compute paths of include, share, etc. relative to cobc's location. --- cobc/Makefile.am | 2 +- cobc/cobc.c | 122 ++++----- cobc/cobc.h | 14 ++ cobc/codegen.c | 297 +++++++++++----------- cobc/settings.c | 446 +++++++++++++++++++++++++++++++++ cobc/settings.def | 621 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 9 + 7 files changed, 1303 insertions(+), 208 deletions(-) create mode 100644 cobc/settings.c create mode 100644 cobc/settings.def diff --git a/cobc/Makefile.am b/cobc/Makefile.am index 444987fc6..991739ab2 100644 --- a/cobc/Makefile.am +++ b/cobc/Makefile.am @@ -23,7 +23,7 @@ bin_PROGRAMS = cobc cobc_SOURCES = cobc.c cobc.h ppparse.y pplex.c parser.y scanner.c config.c \ reserved.c error.c tree.c tree.h field.c typeck.c codegen.c help.c \ config.def flag.def warning.def codeoptim.def ppparse.def \ - codeoptim.c replace.c + codeoptim.c replace.c settings.c settings.def #cobc_SOURCES = cobc.c cobc.h ppparse.y pplex.l parser.y scanner.l config.c diff --git a/cobc/cobc.c b/cobc/cobc.c index b3a52303c..5d17bfb5b 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -106,6 +106,7 @@ enum compile_level { #define CB_FLAG_GETOPT_EBCDIC_TABLE 14 #define CB_FLAG_GETOPT_DEFAULT_COLSEQ 15 #define CB_FLAG_MEMORY_CHECK 16 +#define CB_FLAG_GETOPT_SETTINGS 17 /* Info display limits */ @@ -369,13 +370,7 @@ static struct cobc_mem_struct *cobc_plexmem_base = NULL; static const char *cobc_cc; /* C compiler */ static char *cobc_cflags; /* C compiler flags */ -#ifdef COB_DEBUG_FLAGS static const char *cobc_debug_flags; /* C debgging flags */ -#else -#ifndef _MSC_VER -#error missing definition of COB_DEBUG_FLAGS -#endif -#endif static char *cobc_libs; /* -l... */ static char *cobc_lib_paths; /* -L... */ @@ -395,11 +390,7 @@ static size_t cobc_libs_len; static size_t cobc_lib_paths_len; static size_t cobc_include_len; static size_t cobc_ldflags_len; -#ifdef COB_EXPORT_DYN -static size_t cobc_export_dyn_len; -#else -#define cobc_export_dyn_len 0 -#endif +static size_t cobc_export_dyn_len = 0; #ifdef COB_SHARED_OPT static size_t cobc_shared_opt_len; #else @@ -592,6 +583,7 @@ static const struct option long_options[] = { {"O2", CB_NO_ARG, NULL, '2'}, {"O3", CB_NO_ARG, NULL, '3'}, {"Os", CB_NO_ARG, NULL, 's'}, + {"settings", CB_OP_ARG, NULL, CB_FLAG_GETOPT_SETTINGS}, {"save-temps", CB_OP_ARG, NULL, '_'}, {"std", CB_RQ_ARG, NULL, '$'}, {"conf", CB_RQ_ARG, NULL, '&'}, @@ -1008,7 +1000,6 @@ cobc_strdup (const char *dupstr) return p; } -#if defined (_WIN32) || defined (__CYGWIN__) static char * cobc_stradd_dup (const char *str1, const char *str2) { @@ -1028,7 +1019,6 @@ cobc_stradd_dup (const char *str1, const char *str2) memcpy (p + m, str2, n); return p; } -#endif void * cobc_realloc (void *prevptr, const size_t size) @@ -2641,8 +2631,8 @@ cobc_print_info (void) cobc_var_print ("LDFLAGS", COB_BLD_LDFLAGS, 0); putchar ('\n'); puts (_("GnuCOBOL information")); - cobc_var_and_envvar_print ("COB_CC", COB_CC); - cobc_var_and_envvar_print ("COB_CFLAGS", COB_CFLAGS); + cobc_var_and_envvar_print ("COB_CC", cb_setting_COB_CC); + cobc_var_and_envvar_print ("COB_CFLAGS", cb_setting_COB_CFLAGS); #ifndef _MSC_VER if (verbose_output) { #ifdef COB_STRIP_CMD @@ -2652,12 +2642,12 @@ cobc_print_info (void) #endif cobc_var_print ("COB_STRIP_CMD", strip_cmd, 0); } - cobc_var_and_envvar_print ("COB_DEBUG_FLAGS", COB_DEBUG_FLAGS); + cobc_var_and_envvar_print ("COB_DEBUG_FLAGS", cb_setting_COB_DEBUG_FLAGS); #endif cobc_var_and_envvar_print ("COB_LDFLAGS", COB_LDFLAGS); cobc_var_and_envvar_print ("COB_LIBS", COB_LIBS); - cobc_var_and_envvar_print ("COB_CONFIG_DIR", COB_CONFIG_DIR); - cobc_var_and_envvar_print ("COB_COPY_DIR", COB_COPY_DIR); + cobc_var_and_envvar_print ("COB_CONFIG_DIR", cb_setting_COB_CONFIG_DIR); + cobc_var_and_envvar_print ("COB_COPY_DIR", cb_setting_COB_COPY_DIR); if ((s = getenv ("COBCPY")) != NULL && *s) { cobc_var_print ("COBCPY", s, 1); } @@ -2672,10 +2662,10 @@ cobc_print_info (void) } cobc_var_print ("COB_OBJECT_EXT", COB_OBJECT_EXT, 0); cobc_var_print ("COB_MODULE_EXT", COB_MODULE_EXT, 0); - if (!verbose_output && COB_EXE_EXT[0] == '.') { - cobc_var_print ("COB_EXE_EXT", &COB_EXE_EXT[1], 0); + if (!verbose_output && cb_setting_COB_EXE_EXT[0] == '.') { + cobc_var_print ("COB_EXE_EXT", &cb_setting_COB_EXE_EXT[1], 0); } else { - cobc_var_print ("COB_EXE_EXT", COB_EXE_EXT, 0); + cobc_var_print ("COB_EXE_EXT", cb_setting_COB_EXE_EXT, 0); } if ((s = getenv ("SOURCE_DATE_EPOCH")) != NULL) { /* reading and validating + setting print version */ @@ -3010,6 +3000,9 @@ process_command_line (const int argc, char **argv) int conf_ret = 0; int error_all_warnings = 0; + const char* settings_file ; + + settings_file = cob_getenv_direct ("COBC_SETTINGS"); #if defined (_WIN32) || defined (__DJGPP__) if (!getenv ("POSIXLY_CORRECT")) { @@ -3256,9 +3249,9 @@ process_command_line (const int argc, char **argv) cb_flag_c_line_directives = 1; cb_flag_c_labels = 1; #endif -#ifdef COB_DEBUG_FLAGS - COBC_ADD_STR (cobc_cflags, " ", cobc_debug_flags, NULL); -#endif + if (!cb_setting_COB_DEBUG_FLAGS[0]){ + COBC_ADD_STR (cobc_cflags, " ", cobc_debug_flags, NULL); + } break; case 'd': @@ -3270,6 +3263,14 @@ process_command_line (const int argc, char **argv) cobc_wants_debug = 1; break; + case CB_FLAG_GETOPT_SETTINGS: /* 17 */ + /* We must load these settings before loading + * the dialect configuration */ + if (cob_optarg){ + settings_file = cobc_strdup (cob_optarg); + } + break; + case 8: /* -fdump= : Add sections for dump code generation */ cobc_def_dump_opts (cob_optarg, 1); @@ -3290,6 +3291,8 @@ process_command_line (const int argc, char **argv) } } + cb_settings_load (settings_file); + if (verbose_output >= 1) { cobc_print_shortversion (); } @@ -3871,6 +3874,13 @@ process_command_line (const int argc, char **argv) } break; + case CB_FLAG_GETOPT_SETTINGS: /* 17 */ + if (!cob_optarg){ + cb_settings_print (); + exit (0); + } + break; + case CB_FLAG_GETOPT_NO_EC: /* 12 */ /* -fno-ec= : COBOL exception-name, e.g. EC-BOUND-OVERFLOW */ if (cobc_deciph_ec (cob_optarg, 0)) { @@ -4628,11 +4638,11 @@ resolve_name_from_cobc (const char *cobc_path) as we may be called with/without it */ for (i = cobc_path_length - cobc_name_length; i >= 0; i--) { if (!strncasecmp (cobc_real_name, cobc_path + i, cobc_name_length)) { - const size_t cobcrun_name_length = strlen (COBCRUN_NAME); + const size_t cobcrun_name_length = strlen (cb_setting_COBCRUN_NAME); size_t length = cobc_path_length - cobc_name_length + cobcrun_name_length + 1; cobcrun_path_malloced = cobc_malloc (length); memcpy (cobcrun_path_malloced, cobc_path, i); - memcpy (cobcrun_path_malloced + i, COBCRUN_NAME, cobcrun_name_length); + memcpy (cobcrun_path_malloced + i, cb_setting_COBCRUN_NAME, cobcrun_name_length); length = cobc_path_length - i - cobc_name_length + 1; memcpy (cobcrun_path_malloced + i + cobcrun_name_length, cobc_path + i + cobc_name_length, length); break; @@ -4702,7 +4712,11 @@ process_run (const char *name) if (cobcrun_path_malloced) { cobcrun_path = cobcrun_path_malloced; } else { - cobcrun_path = COBCRUN_NAME COB_EXE_EXT; + cobcrun_path_malloced = + cobc_stradd_dup ( + cb_setting_COBCRUN_NAME, + cb_setting_COB_EXE_EXT); + cobcrun_path = cobcrun_path_malloced ; } if (cobc_path_malloced) { cobc_free (cobc_path_malloced); @@ -4726,22 +4740,22 @@ process_run (const char *name) } } else { /* executable */ /* only add COB_EXE_EXT if it is not specified */ - const char *exe_ext = COB_EXE_EXT; + const char *exe_ext = cb_setting_COB_EXE_EXT; exe_ext++; /* drop the "." */ buffer = file_extension (name); /* only prefix with ./ if there is no directory portion in name */ if (strchr (name, SLASH_CHAR) == NULL) { - if (COB_EXE_EXT[0] && cb_strcasecmp (buffer, exe_ext)) { + if (cb_setting_COB_EXE_EXT[0] && cb_strcasecmp (buffer, exe_ext)) { curr_size = snprintf (cobc_buffer, cobc_buffer_size, ".%c%s%s", - SLASH_CHAR, name, COB_EXE_EXT); + SLASH_CHAR, name, cb_setting_COB_EXE_EXT); } else { curr_size = snprintf (cobc_buffer, cobc_buffer_size, ".%c%s", SLASH_CHAR, name); } } else { - if (COB_EXE_EXT[0] && cb_strcasecmp (buffer, exe_ext)) { + if (cb_setting_COB_EXE_EXT[0] && cb_strcasecmp (buffer, exe_ext)) { curr_size = snprintf (cobc_buffer, cobc_buffer_size, "%s%s", - name, COB_EXE_EXT); + name, cb_setting_COB_EXE_EXT); } else { curr_size = snprintf (cobc_buffer, cobc_buffer_size, "%s", name); @@ -5026,7 +5040,7 @@ process_filtered (const char *cmd, struct filename *fn) /* building search_patterns */ if (output_name) { if (cobc_flag_main) { - output_name_temp = file_basename (output_name, COB_EXE_EXT); + output_name_temp = file_basename (output_name, cb_setting_COB_EXE_EXT); } else if (cb_compile_level == CB_LEVEL_ASSEMBLE) { output_name_temp = file_basename (output_name, "." COB_OBJECT_EXT); } else { @@ -8334,12 +8348,12 @@ process_module_direct (struct filename *fn) #ifdef __WATCOMC__ sprintf (cobc_buffer, "%s %s %s %s %s %s -fe=\"%s\" \"%s\" %s %s %s", cobc_cc, cobc_cflags, cobc_include, COB_SHARED_OPT, - COB_PIC_FLAGS, COB_EXPORT_DYN, name, + COB_PIC_FLAGS, cb_setting_COB_EXPORT_DYN, name, fn->translate, cobc_ldflags, cobc_lib_paths, cobc_libs); #else sprintf (cobc_buffer, "%s %s %s %s %s %s -o \"%s\" \"%s\" %s %s %s", cobc_cc, cobc_cflags, cobc_include, COB_SHARED_OPT, - COB_PIC_FLAGS, COB_EXPORT_DYN, name, + COB_PIC_FLAGS, cb_setting_COB_EXPORT_DYN, name, fn->translate, cobc_ldflags, cobc_lib_paths, cobc_libs); #endif ret = process (cobc_buffer); @@ -8442,11 +8456,11 @@ process_module (struct filename *fn) #ifndef _MSC_VER #ifdef __WATCOMC__ sprintf (cobc_buffer, "%s %s %s %s -fe=\"%s\" \"%s\" %s %s %s", - cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, COB_EXPORT_DYN, + cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, cb_setting_COB_EXPORT_DYN, name, fn->object, cobc_ldflags, cobc_lib_paths, cobc_libs); #else sprintf (cobc_buffer, "%s %s %s %s -o \"%s\" \"%s\" %s %s %s", - cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, COB_EXPORT_DYN, + cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, cb_setting_COB_EXPORT_DYN, name, fn->object, cobc_ldflags, cobc_lib_paths, cobc_libs); #endif ret = process (cobc_buffer); @@ -8556,12 +8570,12 @@ process_library (struct filename *l) #ifdef __WATCOMC__ sprintf (cobc_buffer, "%s %s %s %s -fe=\"%s\" %s %s %s %s", cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, - COB_EXPORT_DYN, name, cobc_objects_buffer, + cb_setting_COB_EXPORT_DYN, name, cobc_objects_buffer, cobc_ldflags, cobc_lib_paths, cobc_libs); #else sprintf (cobc_buffer, "%s %s %s %s -o \"%s\" %s %s %s %s", cobc_cc, COB_SHARED_OPT, COB_PIC_FLAGS, - COB_EXPORT_DYN, name, cobc_objects_buffer, + cb_setting_COB_EXPORT_DYN, name, cobc_objects_buffer, cobc_ldflags, cobc_lib_paths, cobc_libs); #endif ret = process (cobc_buffer); @@ -8658,7 +8672,7 @@ process_link (struct filename *l) } } #if defined (_WIN32) || defined (__CYGWIN__) - exe_name = cobc_stradd_dup (name, COB_EXE_EXT); + exe_name = cobc_stradd_dup (name, cb_setting_COB_EXE_EXT); #ifndef _MSC_VER name = exe_name; #endif @@ -8678,11 +8692,11 @@ process_link (struct filename *l) #ifndef _MSC_VER #ifdef __WATCOMC__ sprintf (cobc_buffer, "%s %s -fe=\"%s\" %s %s %s %s", - cobc_cc, COB_EXPORT_DYN, name, cobc_objects_buffer, + cobc_cc, cb_setting_COB_EXPORT_DYN, name, cobc_objects_buffer, cobc_ldflags, cobc_lib_paths, cobc_libs); #else sprintf (cobc_buffer, "%s %s -o \"%s\" %s %s %s %s", - cobc_cc, COB_EXPORT_DYN, name, cobc_objects_buffer, + cobc_cc, cb_setting_COB_EXPORT_DYN, name, cobc_objects_buffer, cobc_ldflags, cobc_lib_paths, cobc_libs); #endif ret = process (cobc_buffer); @@ -8690,23 +8704,23 @@ process_link (struct filename *l) #ifdef __hpux if (ret == 0) { sprintf (cobc_buffer, "chatr -s +s enable \"%s%s\" 1>/dev/null 2>&1", - name, COB_EXE_EXT); + name, cb_setting_COB_EXE_EXT); process (cobc_buffer); } #endif #ifdef COB_STRIP_CMD if (strip_output && ret == 0) { - const char *exe_ext = COB_EXE_EXT; + const char *exe_ext = cb_setting_COB_EXE_EXT; if (*exe_ext) { exe_ext++; /* drop the "." */ } - cobc_chk_buff_size (strlen (COB_STRIP_CMD) + 4 + strlen (name) + strlen (COB_EXE_EXT)); + cobc_chk_buff_size (strlen (COB_STRIP_CMD) + 4 + strlen (name) + strlen (cb_setting_COB_EXE_EXT)); /* only add COB_EXE_EXT if it is not specified */ exe_name = file_extension (name); if (cb_strcasecmp (exe_name, exe_ext)) { sprintf (cobc_buffer, "%s \"%s%s\"", - COB_STRIP_CMD, name, COB_EXE_EXT); + COB_STRIP_CMD, name, cb_setting_COB_EXE_EXT); } else { sprintf (cobc_buffer, "%s \"%s\"", COB_STRIP_CMD, name); @@ -8768,19 +8782,19 @@ set_cobc_defaults (void) cobc_cc = cobc_getenv_path ("COB_CC"); if (cobc_cc == NULL ) { - cobc_cc = COB_CC; + cobc_cc = cb_setting_COB_CC; } cob_config_dir = cobc_getenv_path ("COB_CONFIG_DIR"); if (cob_config_dir == NULL) { - cob_config_dir = COB_CONFIG_DIR; + cob_config_dir = cb_setting_COB_CONFIG_DIR; } p = cobc_getenv ("COB_CFLAGS"); if (p) { COBC_ADD_STR (cobc_cflags, p, NULL, NULL); } else { - COBC_ADD_STR (cobc_cflags, COB_CFLAGS, NULL, NULL); + COBC_ADD_STR (cobc_cflags, cb_setting_COB_CFLAGS, NULL, NULL); } p = cobc_getenv ("COB_LDFLAGS"); @@ -8790,14 +8804,12 @@ set_cobc_defaults (void) COBC_ADD_STR (cobc_ldflags, COB_LDFLAGS, NULL, NULL); } -#ifdef COB_DEBUG_FLAGS p = cobc_getenv ("COB_DEBUG_FLAGS"); if (p && *p) { cobc_debug_flags = (const char *)p; } else { - cobc_debug_flags = COB_DEBUG_FLAGS; + cobc_debug_flags = cb_setting_COB_DEBUG_FLAGS; } -#endif p = cobc_getenv ("COB_LIBS"); if (p) { @@ -8928,9 +8940,7 @@ finish_setup_compiler_env (void) #ifdef COB_PIC_FLAGS cobc_pic_flags_len = strlen (COB_PIC_FLAGS); #endif -#ifdef COB_EXPORT_DYN - cobc_export_dyn_len = strlen (COB_EXPORT_DYN); -#endif + cobc_export_dyn_len = strlen (cb_setting_COB_EXPORT_DYN); cobc_ldflags_len = strlen (cobc_ldflags); cobc_lib_paths_len = strlen (cobc_lib_paths); cobc_libs_len = strlen (cobc_libs); @@ -9043,7 +9053,7 @@ finish_setup_internal_env (void) process_env_copy_path ("COBCPY"); /* Add default COB_COPY_DIR directory */ - CB_TEXT_LIST_CHK (cb_include_list, COB_COPY_DIR); + CB_TEXT_LIST_CHK (cb_include_list, cb_setting_COB_COPY_DIR); } static int diff --git a/cobc/cobc.h b/cobc/cobc.h index 73f3d7a23..ea6634b34 100644 --- a/cobc/cobc.h +++ b/cobc/cobc.h @@ -684,4 +684,18 @@ extern int cb_strcasecmp (const void *, const void *); extern unsigned char cb_toupper (const unsigned char); extern unsigned char cb_tolower (const unsigned char); +/* settings.c */ + +#define STRING_SETTING(help,name) \ + extern const char* cb_setting_##name; + +#define BOOL_SETTING(help,name) \ + extern int cb_setting_##name; + +#include "settings.def" +#undef STRING_SETTING +#undef BOOL_SETTING +extern void cb_settings_print (void); +extern void cb_settings_load (const char* filename); + #endif /* CB_COBC_H */ diff --git a/cobc/codegen.c b/cobc/codegen.c index f32391606..e92354ca8 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -38,22 +38,19 @@ #include "cobc.h" #include "tree.h" -#ifdef HAVE_ATTRIBUTE_ALIGNED #define COB_ALIGN " __attribute__((aligned))" +#define COB_ALIGN_DECL_8 ( cb_setting_WIN32 ? "__declspec(align(8)) " : "" ) +#define COB_ALIGN_ATTR_8 ( cb_setting_ARM ? " __align(8)" : "" ) + +#ifdef HAVE_ATTRIBUTE_ALIGNED #define ALIGN_KNOWN #else /*#if defined(_MSC_VER) || defined(__ORANGEC__)*/ #if defined(_WIN32) -#define COB_ALIGN_DECL_8 "__declspec(align(8)) " #define ALIGN_KNOWN -#else -#define COB_ALIGN_DECL_8 "" #endif #if defined(__arm__) -#define COB_ALIGN_ATTR_8 " __align(8)" #define ALIGN_KNOWN -#else -#define COB_ALIGN_ATTR_8 "" #endif #if defined(__SUNPRO_C) /* Insert #pragma align 8 (varname) */ @@ -1757,14 +1754,6 @@ output_standard_includes (struct cb_program *prog) { struct cb_program *p; -#if defined (HAVE_GMP_H) - #define MATH_INCLUDE "#include " -#elif defined (HAVE_MPIR_H) - #define MATH_INCLUDE "#include " -#else -#error either HAVE_GMP_H or HAVE_MPIR_H needs to be defined -#endif - #if !defined (_GNU_SOURCE) && defined (_XOPEN_SOURCE_EXTENDED) output_line ("#ifndef\t_XOPEN_SOURCE_EXTENDED"); output_line ("#define\t_XOPEN_SOURCE_EXTENDED 1"); @@ -1788,7 +1777,16 @@ output_standard_includes (struct cb_program *prog) then include appropriate header */ for (p = prog; p; p = p->next_program) { if (p->decimal_index_max || p->flag_decimal_comp) { - output_line (MATH_INCLUDE); + if ( cb_setting_HAVE_GMP_H ){ + output_line ("#include "); + } else + if ( cb_setting_HAVE_MPIR_H){ + output_line ("#include "); + } else { + /* We could move such tests directly into a + post-validation phase of settings.c */ + cobc_err_exit ("either HAVE_GMP_H or HAVE_MPIR_H needs to be defined"); + } break; } } @@ -2093,14 +2091,14 @@ output_local_base_cache (void) if (fld->index_type != CB_INT_INDEX) { output_local ("static "); } -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_local ("cob_u8_t %s%d_fence_pre[8]%s;\n", - CB_PREFIX_BASE, fld->id, COB_ALIGN); -#else - output_local ("%scob_u8_t%s %s%d_fence_pre[8];\n", - COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, - CB_PREFIX_BASE, fld->id); -#endif + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED){ + output_local ("cob_u8_t %s%d_fence_pre[8]%s;\n", + CB_PREFIX_BASE, fld->id, COB_ALIGN); + } else { + output_local ("%scob_u8_t%s %s%d_fence_pre[8];\n", + COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, + CB_PREFIX_BASE, fld->id); + } optimize_defs[COB_CHK_MEMORYFENCE] = 1; /* note: we explicit do _not_ initialize it directly as that will more likely lead to a non-consecutive memory layout, @@ -2113,29 +2111,29 @@ output_local_base_cache (void) output_local ("static int %s%d;", CB_PREFIX_BASE, fld->id); } else if( !(fld->report_flag & COB_REPORT_REF_EMITTED)) { -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_local ("static cob_u8_t %s%d[%d]%s;", - CB_PREFIX_BASE, fld->id, - fld->memory_size, COB_ALIGN); -#else - output_local ("static %scob_u8_t%s %s%d[%d];", - COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, CB_PREFIX_BASE, - fld->id, fld->memory_size); -#endif + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED) { + output_local ("static cob_u8_t %s%d[%d]%s;", + CB_PREFIX_BASE, fld->id, + fld->memory_size, COB_ALIGN); + } else { + output_local ("static %scob_u8_t%s %s%d[%d];", + COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, CB_PREFIX_BASE, + fld->id, fld->memory_size); + } } output_local ("\t/* %s */\n", fld->name); if (fld->flag_used_in_call) { if (fld->index_type != CB_INT_INDEX) { output_local ("static "); } -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_local ("cob_u8_t %s%d_fence_post[8]%s;\n", - CB_PREFIX_BASE, fld->id, COB_ALIGN); -#else - output_local ("%scob_u8_t%s %s%d_fence_post[8];\n", - COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, - CB_PREFIX_BASE, fld->id); -#endif + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED){ + output_local ("cob_u8_t %s%d_fence_post[8]%s;\n", + CB_PREFIX_BASE, fld->id, COB_ALIGN); + } else { + output_local ("%scob_u8_t%s %s%d_fence_post[8];\n", + COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, + CB_PREFIX_BASE, fld->id); + } } } @@ -2164,17 +2162,17 @@ output_nonlocal_base_cache (void) } if (fld->flag_used_in_call) { -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_storage ("static cob_u8_t %s%d_fence_pre[8]%s;\n", - CB_PREFIX_BASE, fld->id, COB_ALIGN); -#else + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED){ + output_storage ("static cob_u8_t %s%d_fence_pre[8]%s;\n", + CB_PREFIX_BASE, fld->id, COB_ALIGN); + } else { #if defined(COB_ALIGN_PRAGMA_8) output_storage ("#pragma align 8 (%s%d_fence_pre)\n", CB_PREFIX_BASE, fld->id); #endif output_storage ("static %scob_u8_t%s %s%d_fence_pre[8];\n", COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, CB_PREFIX_BASE, fld->id); -#endif + } optimize_defs[COB_CHK_MEMORYFENCE] = 1; /* note: we explicit do _not_ initialize it directly as that will more likely lead to a non-consecutive memory layout, @@ -2184,32 +2182,32 @@ output_nonlocal_base_cache (void) output_storage ("static int %s%d;", CB_PREFIX_BASE, fld->id); } else { -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_storage ("static cob_u8_t %s%d[%d]%s;", - CB_PREFIX_BASE, fld->id, - fld->memory_size, COB_ALIGN); -#else + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED){ + output_storage ("static cob_u8_t %s%d[%d]%s;", + CB_PREFIX_BASE, fld->id, + fld->memory_size, COB_ALIGN); + } else { #if defined(COB_ALIGN_PRAGMA_8) - output_storage ("#pragma align 8 (%s%d)\n", CB_PREFIX_BASE, fld->id); -#endif - output_storage ("static %scob_u8_t%s %s%d[%d];", - COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, CB_PREFIX_BASE, - fld->id, fld->memory_size); + output_storage ("#pragma align 8 (%s%d)\n", CB_PREFIX_BASE, fld->id); #endif + output_storage ("static %scob_u8_t%s %s%d[%d];", + COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, CB_PREFIX_BASE, + fld->id, fld->memory_size); + } } output_storage ("\t/* %s */\n", fld->name); if (fld->flag_used_in_call) { -#ifdef HAVE_ATTRIBUTE_ALIGNED - output_storage ("static cob_u8_t %s%d_fence_post[8]%s;\n", - CB_PREFIX_BASE, fld->id, COB_ALIGN); -#else + if (cb_setting_HAVE_ATTRIBUTE_ALIGNED){ + output_storage ("static cob_u8_t %s%d_fence_post[8]%s;\n", + CB_PREFIX_BASE, fld->id, COB_ALIGN); + } else { #if defined(COB_ALIGN_PRAGMA_8) - output_storage ("#pragma align 8 (%s%d_fence_post)\n", CB_PREFIX_BASE, fld->id); -#endif - output_storage ("static %scob_u8_t%s %s%d_fence_post[8];\n", - COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, - CB_PREFIX_BASE, fld->id); + output_storage ("#pragma align 8 (%s%d_fence_post)\n", CB_PREFIX_BASE, fld->id); #endif + output_storage ("static %scob_u8_t%s %s%d_fence_post[8];\n", + COB_ALIGN_DECL_8, COB_ALIGN_ATTR_8, + CB_PREFIX_BASE, fld->id); + } } } @@ -2854,19 +2852,19 @@ output_integer (cb_tree x) output (")"); } else { output ("("); -#ifdef COB_NON_ALIGNED - if (CB_TREE_TAG (p->x) == CB_TAG_REFERENCE - && p->x != cb_null) { - const struct cb_field *f = cb_code_field (p->x); - /* typecast is required on Sun because pointer - * arithmetic is not allowed on (void *) - */ - if (f->usage == CB_USAGE_POINTER - || f->usage == CB_USAGE_PROGRAM_POINTER) { - output ("(cob_u8_ptr)"); + if (cb_setting_COB_NON_ALIGNED){ + if (CB_TREE_TAG (p->x) == CB_TAG_REFERENCE + && p->x != cb_null) { + const struct cb_field *f = cb_code_field (p->x); + /* typecast is required on Sun because pointer + * arithmetic is not allowed on (void *) + */ + if (f->usage == CB_USAGE_POINTER + || f->usage == CB_USAGE_PROGRAM_POINTER) { + output ("(cob_u8_ptr)"); + } } } -#endif output_integer (p->x); if (p->op == 'a') output (" & "); @@ -2880,19 +2878,19 @@ output_integer (cb_tree x) output (" >> "); else output (" %c ", p->op); -#ifdef COB_NON_ALIGNED - if (CB_TREE_TAG (p->y) == CB_TAG_REFERENCE - && p->y != cb_null) { - const struct cb_field *f = cb_code_field (p->y); - /* typecast is required on Sun because pointer - * arithmetic is not allowed on (void *) - */ - if (f->usage == CB_USAGE_POINTER - || f->usage == CB_USAGE_PROGRAM_POINTER) { - output ("(cob_u8_ptr)"); + if (cb_setting_COB_NON_ALIGNED){ + if (CB_TREE_TAG (p->y) == CB_TAG_REFERENCE + && p->y != cb_null) { + const struct cb_field *f = cb_code_field (p->y); + /* typecast is required on Sun because pointer + * arithmetic is not allowed on (void *) + */ + if (f->usage == CB_USAGE_POINTER + || f->usage == CB_USAGE_PROGRAM_POINTER) { + output ("(cob_u8_ptr)"); + } } } -#endif output_integer (p->y); output (")"); } @@ -2951,15 +2949,15 @@ output_integer (cb_tree x) case CB_USAGE_POINTER: case CB_USAGE_PROGRAM_POINTER: -#ifdef COB_NON_ALIGNED - output ("(cob_get_pointer ("); - output_data (x); - output ("))"); -#else - output ("(*(unsigned char **) ("); - output_data (x); - output ("))"); -#endif + if (cb_setting_COB_NON_ALIGNED){ + output ("(cob_get_pointer ("); + output_data (x); + output ("))"); + } else { + output ("(*(unsigned char **) ("); + output_data (x); + output ("))"); + } return; case CB_USAGE_DISPLAY: @@ -3237,15 +3235,15 @@ output_long_integer (cb_tree x) case CB_USAGE_POINTER: case CB_USAGE_PROGRAM_POINTER: -#ifdef COB_NON_ALIGNED - output ("(cob_get_pointer ("); - output_data (x); - output ("))"); -#else - output ("(*(unsigned char **) ("); - output_data (x); - output ("))"); -#endif + if (cb_setting_COB_NON_ALIGNED){ + output ("(cob_get_pointer ("); + output_data (x); + output ("))"); + } else { + output ("(*(unsigned char **) ("); + output_data (x); + output ("))"); + } return; case CB_USAGE_BINARY: @@ -6577,15 +6575,14 @@ output_call (struct cb_call *p) } output_line ("int ret;"); } -#ifdef COB_NON_ALIGNED - else { - if (!need_brace) { - need_brace = 1; - output_block_open (); + else + if (cb_setting_COB_NON_ALIGNED){ + if (!need_brace) { + need_brace = 1; + output_block_open (); + } + output_line ("void *temptr;"); } - output_line ("void *temptr;"); - } -#endif } if (CB_REFERENCE_P (p->name) @@ -12487,17 +12484,15 @@ output_internal_function (struct cb_program *prog, cb_tree parameter_list) output_newline (); /* Check matching version */ -#if !defined (HAVE_ATTRIBUTE_CONSTRUCTOR) -#ifdef _WIN32 - if (prog->flag_main) /* otherwise we generate that in DllMain*/ -#else - if (!prog->nested_level) -#endif - { + if (!cb_setting_HAVE_ATTRIBUTE_CONSTRUCTOR && + ( + (cb_setting_WIN32 && prog->flag_main) /* otherwise we generate that in DllMain*/ + || + (!cb_setting_WIN32 && !prog->nested_level) + )){ output_line ("cob_check_version (COB_SOURCE_FILE, COB_PACKAGE_VERSION, COB_PATCH_LEVEL);"); output_newline (); } -#endif /* Resolve user functions */ for (clp = func_call_cache; clp; clp = clp->next) { @@ -12866,11 +12861,11 @@ output_function_entry_function (struct cb_program *prog, cb_tree entry, output ("cob_field **cob_fret, const int cob_pam"); #endif } else { -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(__clang__) - if (!prog->nested_level) { - output ("__declspec(dllexport) "); + if (cb_setting_WIN32 || ( cb_setting_CYGWIN && !cb_setting_CLANG) ){ + if (!prog->nested_level) { + output ("__declspec(dllexport) "); + } } -#endif output ("cob_field\t\t*%s (", entry_name); output ("cob_field **, const int"); } @@ -13122,7 +13117,7 @@ output_entry_function (struct cb_program *prog, cb_tree entry, output_newline (); output_block_open (); - + if (!cb_sticky_linkage && (entry_convention & CB_CONV_COBOL)) { /* By value pointer fields */ @@ -13329,7 +13324,7 @@ output_entry_function (struct cb_program *prog, cb_tree entry, } } } - + if (!cb_sticky_linkage && (entry_convention & CB_CONV_COBOL)) { for (l2 = using_list; l2; l2 = CB_CHAIN (l2)) { @@ -13469,15 +13464,15 @@ output_function_prototypes (struct cb_program *prog) cp->program_id); } output_newline (); -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(__clang__) - for (l = cp->entry_list; l; l = CB_CHAIN (l)) { - const char *entry_name = CB_LABEL (CB_PURPOSE (l))->name; - if (0 == strcmp (entry_name, cp->program_id)) { - continue; + if (cb_setting_WIN32 || ( cb_setting_CYGWIN && !cb_setting_CLANG ) ){ + for (l = cp->entry_list; l; l = CB_CHAIN (l)) { + const char *entry_name = CB_LABEL (CB_PURPOSE (l))->name; + if (0 == strcmp (entry_name, cp->program_id)) { + continue; + } + output_entry_function (cp, l, cp->parameter_list, 0); } - output_entry_function (cp, l, cp->parameter_list, 0); } -#endif } else { /* Output implementation of other program wrapper. */ if (likely(cp->prog_type == COB_MODULE_TYPE_PROGRAM)) { @@ -13724,26 +13719,26 @@ codegen_init (struct cb_program *prog, const char *translate_name) /* Check matching version via constructor attribute / DllMain */ static void output_so_load_version_check (struct cb_program *prog) { -#if defined (HAVE_ATTRIBUTE_CONSTRUCTOR) - output_line ("static void gc_module_so_init () __attribute__ ((constructor));"); - output_line ("static void gc_module_so_init ()"); - output_block_open (); - output_line ("cob_check_version (COB_SOURCE_FILE, COB_PACKAGE_VERSION, COB_PATCH_LEVEL);"); - output_block_close (); - output_newline (); -#elif defined (_WIN32) - if (!prog->flag_main) { - output_line ("#include \"windows.h\""); - output_line ("BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);"); - output_line ("BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)"); + if (cb_setting_HAVE_ATTRIBUTE_CONSTRUCTOR){ + output_line ("static void gc_module_so_init () __attribute__ ((constructor));"); + output_line ("static void gc_module_so_init ()"); output_block_open (); - output_line ("if (fdwReason == DLL_PROCESS_ATTACH)"); - output_line ("\tcob_check_version (COB_SOURCE_FILE, COB_PACKAGE_VERSION, COB_PATCH_LEVEL);"); - output_line ("return TRUE;"); + output_line ("cob_check_version (COB_SOURCE_FILE, COB_PACKAGE_VERSION, COB_PATCH_LEVEL);"); output_block_close (); output_newline (); - } -#endif + } else + if (cb_setting_WIN32 && + !prog->flag_main) { + output_line ("#include \"windows.h\""); + output_line ("BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);"); + output_line ("BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)"); + output_block_open (); + output_line ("if (fdwReason == DLL_PROCESS_ATTACH)"); + output_line ("\tcob_check_version (COB_SOURCE_FILE, COB_PACKAGE_VERSION, COB_PATCH_LEVEL);"); + output_line ("return TRUE;"); + output_block_close (); + output_newline (); + } } void diff --git a/cobc/settings.c b/cobc/settings.c new file mode 100644 index 000000000..30cd649be --- /dev/null +++ b/cobc/settings.c @@ -0,0 +1,446 @@ +/* + Copyright (C) 2001-2023 Free Software Foundation, Inc. + + Authors: + Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Brian Tiffin, + Edward Hart, Dave Pitts, Fabrice Le Fessant + + This file is part of GnuCOBOL. + + The GnuCOBOL compiler 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. + + GnuCOBOL 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 GnuCOBOL. If not, see . +*/ + +#include "tarstamp.h" +#include "config.h" + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include +#include + +#include "cobc.h" +#include "tree.h" + +/* +Settings are used to override GnuCOBOL host config, i.e. parameters +that are used to adapt GnuCOBOL to the system running it. By default, +these parameters are guessed at compilation time. However, it happens +that we want to change them at runtime: + +- For relocation, i.e. to install GnuCOBOL in a different directory + from the one in which it was supposed to be. + +- For retargetting, i.e. to target a different C compiler or linker + that the one that was detected at compile time. + +Use `gnucobol --settings` to output the current settings. The output +can be copied into a file, that will later be read by GnuCOBOL: + +``` +$ gnucobol --settings > gnucobol.settings +$ gnucobol --settings=gnucobol.settings +``` + +You can then modify any option within the file. + +A file containing these settings can be specified in 3 different ways, +the first working way in this order will be used: + +* Use of the argument `--settings=FILE` +* Use of the environment variable `COBC_SETTINGS` +* Use of `../etc/gnucobol/gnucobol.settings` from the directory + containing the `cobc` executable + +If a file is specified, an error while loading the file is fatal. + +Once the settings have been loaded, a few variables can be modified if +the `COBC_IS_RELOCATABLE` setting is set to 1. This setting can also +be overwritten by setting the `COBC_IS_RELOCATABLE` environment +variable. In this case, the following variables are modified +relatively to the directory containing `cobc` (`$bindir`): + +* `COB_CFLAGS`: `-I $bindir/../include` is added in front +* `COB_CONFIG_DIR`: set to `$bindir/../share/gnucobol/config` +* `COB_COPY_DIR`: set to `$bindir/../share/gnucobol/copy` +* `COB_LIBRARY_PATH`: set to `$bindir/../lib/gnucobol` +* `COB_LIBS`: `-L$bindir/../lib` is added in front + + */ + +#ifndef COB_DEBUG_FLAGS +#ifdef _MSC_VER +#define COB_DEBUG_FLAGS "" +#else +#error missing definition of COB_DEBUG_FLAGS +#endif +#endif + +/* For all boolean options, we must force their existence */ +#ifdef _MSC_VER +#define MSC_VER 1 +#else +#define MSC_VER 0 +#endif + +#ifdef __CYGWIN__ +#define CYGWIN 1 +#else +#define CYGWIN 0 +#endif + +#ifdef __clang__ +#define CLANG 1 +#else +#define CLANG 0 +#endif + +#ifdef _WIN32 +#define WIN32 1 +#else +#define WIN32 0 +#endif + +#ifdef __WATCOMC__ +#define WATCOMC 1 +#else +#define WATCOMC 0 +#endif + +#ifdef __BORLANDC__ +#define BORLANDC 1 +#else +#define BORLANDC 0 +#endif + +#ifdef __arm__ +#define ARM 1 +#else +#define ARM 0 +#endif + +#ifdef COB_NON_ALIGNED +#define COB_NON_ALIGNED 1 +#else +#define COB_NON_ALIGNED 0 +#endif + + + +#ifndef COBC_IS_RELOCATABLE +#define COBC_IS_RELOCATABLE 0 +#endif + +#ifndef HAVE_ATTRIBUTE_ALIGNED +#define HAVE_ATTRIBUTE_ALIGNED 0 +#endif + +#ifndef HAVE_GMP_H +#define HAVE_GMP_H 0 +#endif + +#ifndef HAVE_MPIR_H +#define HAVE_MPIR_H 0 +#endif + +#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR +#define HAVE_ATTRIBUTE_CONSTRUCTOR 0 +#endif + +#define STRING_SETTING(help,name) \ + const char* cb_setting_##name = name; +#define BOOL_SETTING(help,name) \ + int cb_setting_##name = name; +#include "settings.def" +#undef STRING_SETTING +#undef BOOL_SETTING + +/* string settings */ + +struct cb_string_setting { + const char* name ; + const char* help ; + const char** value ; +}; + +static struct cb_string_setting string_settings[] = { +#define STRING_SETTING(help,name) \ + { #name, help, &cb_setting_##name }, +#define BOOL_SETTING(help,name) +#include "settings.def" +#undef STRING_SETTING +#undef BOOL_SETTING + { NULL, NULL, NULL } +}; + +/* boolean settings */ + +struct cb_bool_setting { + const char* name ; + const char* help ; + int* value ; +}; + +static struct cb_bool_setting bool_settings[] = { +#define STRING_SETTING(help,name) +#define BOOL_SETTING(help,name) \ + { #name, help, &cb_setting_##name }, +#include "settings.def" +#undef STRING_SETTING +#undef BOOL_SETTING + { NULL, NULL, NULL } +}; + + +/* Could be put in a generic library, with cobc_strdup, etc. */ +static char* +cobc_concat (const char *s1, const char *s2, const char *s3, const char *s4) +{ + size_t calcsize = 1; + char* s; + + if (!s1) { + return NULL; + } + + calcsize += strlen (s1) + + ( s2 ? strlen (s2) : 0 ) + + ( s3 ? strlen (s3) : 0 ) + + ( s4 ? strlen (s4) : 0 ) + 1; + + /* LCOV_EXCL_START */ + if (calcsize >= 131072) { + /* Arbitrary limit */ + cobc_err_exit (_("parameter buffer size exceeded")); + } + /* LCOV_EXCL_STOP */ + s = cobc_malloc (calcsize); + strcat (s, s1); + if (s2) { + strcat (s, s2); + } + if (s3) { + strcat (s, s3); + } + if (s4) { + strcat (s, s4); + } + return s; +} + + +static char * cobc_executable_name(void) +{ + char name[COB_NORMAL_BUFF]; +#if defined(__linux__) + struct stat st; + int retcode; + + retcode = readlink("/proc/self/exe", name, COB_NORMAL_MAX); + if (retcode == -1 || retcode == COB_NORMAL_MAX) { + return NULL; + } + name[retcode] = 0; + /* Make sure that the contents of /proc/self/exe is a regular file. + (Old Linux kernels return an inode number instead.) */ + if (stat(name, &st) == -1 || ! S_ISREG(st.st_mode)) { + return NULL; + } + return cobc_strdup (name); + +#elif defined(__APPLE__) + unsigned int namelen; + + namelen = COB_NORMAL_MAX; + if (_NSGetExecutablePath(name, &namelen) == 0) { + return name; + } + return NULL; + +#else + return NULL; + +#endif +} + + + +void cb_settings_print (void) +{ + printf ("# Current settings:\n"); + +#define STRING_SETTING(help,name) \ + printf ( "\n# %s\n", help); \ + printf ( #name": %s\n", cb_setting_##name); +#define BOOL_SETTING(help,name) \ + printf ( "\n# %s\n", help); \ + printf ( #name": %s\n", cb_setting_##name ? "1" : "0"); +#include "settings.def" +#undef STRING_SETTING +#undef BOOL_SETTING + + printf ("\n"); +} + +static void really_load_settings (const char *filename){ + char buff[COB_SMALL_BUFF]; + int line ; + char *value; + char *cp; + FILE *fp; + struct cb_string_setting *ss = string_settings; + struct cb_bool_setting *bs = bool_settings; + + fp = fopen (filename, "r"); + if (fp == NULL) { + cobc_err_exit ("%s: %s", filename, cb_get_strerror ()); + } + + line = 0; + while (fgets (buff, COB_SMALL_MAX, fp)) { + line++; + value = NULL; + cp = buff; + if (*cp == '#') continue; + while (*cp != 0 && *cp != '\r' && *cp != '\n') + { + if (!value && *cp == ':' && cp[1] == ' '){ + *cp = 0; + cp += 2; + value = cp; + } else { + cp++; + } + } + *cp = 0; + if (*buff == 0 && (!value || *value == 0)) continue; + if (!value){ + cobc_err_exit ("%s:%d: invalid setting format", + filename, line); + } + + /* For now, we start with a linear search. In the future, + we could require the options to be sorted at their + definition and use a dichotomy for faster lookup. */ + + while (ss->name){ + if (!strcmp(ss->name, buff)){ + *(ss->value) = cobc_strdup (value); + break; + } + ss++; + } + if (ss->name) continue; + + + while (bs->name){ + if (!strcmp(bs->name, buff)){ + if ( value[0] == '0' && value[1] == 0 ){ + *(bs->value) = 0; + break; + } + if ( value[0] == '1' && value[1] == 0 ){ + *(bs->value) = 1; + break; + } + cobc_err_exit ("%s:%d: wrong value '%s' for '%s', must be '0' or '1'", + filename, line, value, buff); + } + bs++; + } + if (bs->name) continue; + + cobc_err_exit ("%s:%d: setting '%s' does not exist", + filename, line, buff); + } + fclose (fp); +} + + +void cb_settings_load (const char* filename) +{ + char *cobc_dirname = cobc_executable_name (); + + if (cobc_dirname){ + int len = strlen(cobc_dirname); + while (len>0){ + if (cobc_dirname[len-1] == '/' || cobc_dirname[len-1] == '\\') break; + len--; + } + cobc_dirname[len] = 0; + } + + if (!filename){ + /* If no settings filename is provided by argument or + by env variable, let's check if there is a file + relative to the binary position. */ + struct stat st; + filename = cobc_concat (cobc_dirname, + "../etc/gnucobol/gnucobol.settings", + NULL, NULL); + if (!filename || stat(filename, &st) == -1 || ! S_ISREG(st.st_mode)) { + filename = NULL; + } + } + + if (filename){ + really_load_settings (filename); + } + + if (cob_getenv_direct ("COBC_IS_RELOCATABLE")) + cb_setting_COBC_IS_RELOCATABLE = 1; + if (cb_setting_COBC_IS_RELOCATABLE){ + const char* prefix = + cobc_concat (cobc_dirname, "..", NULL, NULL); + const char* prefix_include = + cb_setting_MSC_VER ? + "/I \"" : + cb_setting_WATCOMC ? + "-i\"" : + "-I\""; + const char* prefix_lib = + cb_setting_MSC_VER ? + "/LIBPATH:\"" : + "-L\""; + + cb_setting_COB_CFLAGS = + cobc_concat (prefix_include, + prefix, + "/include\" ", + cb_setting_COB_CFLAGS); + cb_setting_COB_CONFIG_DIR = + cobc_concat (prefix, "/share/gnucobol/config", NULL, NULL); + cb_setting_COB_COPY_DIR = + cobc_concat (prefix, "/share/gnucobol/copy", NULL, NULL); + cb_setting_COB_LIBRARY_PATH = + cobc_concat (prefix, "/lib/gnucobol", NULL, NULL); + cb_setting_COB_LIBS = + cobc_concat (prefix_lib, + prefix, + "/lib\" ", + cb_setting_COB_LIBS); + } +} diff --git a/cobc/settings.def b/cobc/settings.def new file mode 100644 index 000000000..e2d784bc6 --- /dev/null +++ b/cobc/settings.def @@ -0,0 +1,621 @@ + +STRING_SETTING ( +"executable name for module runner", + COBCRUN_NAME ) + +STRING_SETTING ( +"compiler used by cobc", + COB_CC ) + +STRING_SETTING ( +"compiler flags passed to compiler by cobc", + COB_CFLAGS ) + +STRING_SETTING ( +"default search path for copybooks", + COB_CONFIG_DIR ) + +STRING_SETTING ( +"default search path for configuration files", + COB_COPY_DIR ) + +STRING_SETTING ( +"Compile/link option for debugging", + COB_DEBUG_FLAGS ) + +STRING_SETTING ( +"executable extension", +COB_EXE_EXT ) + +STRING_SETTING ( +"compile/link option for exporting symbols", + COB_EXPORT_DYN ) + +/* check done until here */ + +STRING_SETTING ( +"linker flags passed to linker by cobc", + COB_LDFLAGS ) + +STRING_SETTING ( +"default search path for extra modules", + COB_LIBRARY_PATH ) + +STRING_SETTING ( +"libraries passed to linker by cobc", + COB_LIBS ) + +STRING_SETTING ( +"module extension", + COB_MODULE_EXT ) + +STRING_SETTING ( +"object extension", + COB_OBJECT_EXT ) + +STRING_SETTING ( +"compile/link option for PIC code", + COB_PIC_FLAGS ) + +STRING_SETTING ( +"compile/link option for shared code", + COB_SHARED_OPT ) + +STRING_SETTING ( +"strip command", + COB_STRIP_CMD ) + +/* just to test BOOL_SETTING */ + +BOOL_SETTING ( +"has __attribute__((aligned))", +HAVE_ATTRIBUTE_ALIGNED ) + +BOOL_SETTING ( +"has __attribute__((constructor))", + HAVE_ATTRIBUTE_CONSTRUCTOR ) + +BOOL_SETTING ( +"compute paths relative to compiler binary path", +COBC_IS_RELOCATABLE ) + +BOOL_SETTING ( +"define to 1 if you have the header file.", + HAVE_GMP_H ) + +BOOL_SETTING ( +"define to 1 if you have the header file.", + HAVE_MPIR_H ) + +BOOL_SETTING ( +"code is expected to run on Windows platforms", + WIN32 ) + +BOOL_SETTING ( +"code is expected to run on Cygwin", + CYGWIN ) + +BOOL_SETTING ( +"use Microsoft C Compiler", +MSC_VER ) + +BOOL_SETTING ( +"use Borland C Compiler", +BORLANDC ) + +BOOL_SETTING ( +"use Watcom C Compiler", +WATCOMC ) + +BOOL_SETTING ( +"compiler is Clang based", + CLANG ) + +BOOL_SETTING ( +"arch is arm", + ARM ) + +BOOL_SETTING ( +"Support for non aligned structures", + COB_NON_ALIGNED ) + + + +#if 0 + +/* long int is 32 bits */ +/* #undef COB_32_BIT_LONG */ + +/* Pointers are longer than 32 bits */ +#define COB_64_BIT_POINTER 1 + +/* Compilation of computed gotos works */ +#define COB_COMPUTED_GOTO 1 + +/* Enable internal logging (Developers only!) */ +/* #undef COB_DEBUG_LOG */ + +/* Enable experimental code (Developers only!) */ +/* #undef COB_EXPERIMENTAL */ + +/* Keyword for inline */ +#define COB_KEYWORD_INLINE __inline + +/* long int is long long */ +#define COB_LI_IS_LL 1 + +/* Can not dlopen self */ +/* #undef COB_NO_SELFOPEN */ + +/* Enable minimum parameter check for system libraries */ +/* #undef COB_PARAM_CHECK */ + +/* Enable extra checks within the compiler (Developers only!) */ +#define COB_TREE_DEBUG 1 + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#define ENABLE_NLS 1 + +/* Has __attribute__((aligned)) */ +#define HAVE_ATTRIBUTE_ALIGNED 1 + +/* Has __attribute__((pure)) */ +#define HAVE_ATTRIBUTE_PURE 1 + +/* Define to 1 if you have the `canonicalize_file_name' function. */ +#define HAVE_CANONICALIZE_FILE_NAME 1 + +/* Define to 1 if you have the Mac OS X function + CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CJSON_CJSON_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CJSON_H 1 + +/* Has clock_gettime function and CLOCK_REALTIME */ +#define HAVE_CLOCK_GETTIME 1 + +/* curses has color_set function */ +#define HAVE_COLOR_SET 1 + +/* curses provides function to free all memory */ +#define HAVE_CURSES_FREEALL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CURSES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DB_H 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you + don't. */ +#define HAVE_DECL_FDATASYNC 1 + +/* Define to 1 if you have the declaration of `fmemopen', and to 0 if you + don't. */ +#define HAVE_DECL_FMEMOPEN 1 + +/* curses has define_key function */ +#define HAVE_DEFINE_KEY 1 + +/* Has designated initializers */ +#define HAVE_DESIGNATED_INITS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DISAM_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fdatasync' function. */ +#define HAVE_FDATASYNC 1 + +/* Declaration of finite function in ieeefp.h instead of math.h */ +/* #undef HAVE_FINITE_IEEEFP_H */ + +/* Define to 1 if you have the `flockfile' function. */ +#define HAVE_FLOCKFILE 1 + +/* Define to 1 if you have the `fmemopen' function. */ +#define HAVE_FMEMOPEN 1 + +/* Define to 1 if you have the `getexecname' function. */ +/* #undef HAVE_GETEXECNAME */ + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* curses has has_mouse function */ +#define HAVE_HAS_MOUSE 1 + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ISAM_H */ + +/* Has isfinite function */ +#define HAVE_ISFINITE 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_JSON_C_JSON_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_JSON_H */ + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define to 1 if you have the `posix4' library (-lposix4). */ +/* #undef HAVE_LIBPOSIX4 */ + +/* Define to 1 if you have the `rt' library (-lrt). */ +/* #undef HAVE_LIBRT */ + +/* Define to 1 if you have the `localeconv' function. */ +#define HAVE_LOCALECONV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LTDL_H */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MINIX_CONFIG_H */ + +/* curses has mouseinterval function */ +#define HAVE_MOUSEINTERVAL 1 + +/* curses has mousemask function and mmask_t definition */ +#define HAVE_MOUSEMASK 1 + +/* Do we have mp_get_memory_functions in GMP/MPIR */ +#define HAVE_MP_GET_MEMORY_FUNCTIONS 1 + +/* Has nanosleep function */ +#define HAVE_NANO_SLEEP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSESW_CURSES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NCURSESW_NCURSES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_CURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_NCURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PDCURSES_H */ + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the `raise' function. */ +#define HAVE_RAISE 1 + +/* Define to 1 if you have the `readlink' function. */ +#define HAVE_READLINK 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* curses has resize_term function */ +#define HAVE_RESIZE_TERM 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcoll' function. */ +#define HAVE_STRCOLL 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Has timezone variable */ +#define HAVE_TIMEZONE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* ncurses has use_legacy_coding function */ +#define HAVE_USE_LEGACY_CODING 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VBISAM_H */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_XCURSES_CURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_XCURSES_H */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Define maximum parameters for CALL */ +#define MAX_CALL_FIELD_PARAMS 192 + +/* Define a patch level (numeric, max. 8 digits) */ +#define PATCH_LEVEL 0 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long int', as computed by sizeof. */ +#define SIZEOF_LONG_INT 8 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Use system dynamic loader */ +#define USE_LIBDL 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# define _HPUX_ALT_XOPEN_SOCKET_API 1 +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +/* # undef _MINIX */ +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# define _OPENBSD_SOURCE 1 +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +/* # undef _POSIX_SOURCE */ +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +/* # undef _POSIX_1_SOURCE */ +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# define __STDC_WANT_IEC_60559_BFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# define __STDC_WANT_IEC_60559_DFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# define __STDC_WANT_LIB_EXT2__ 1 +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# define __STDC_WANT_MATH_SPEC_FUNCS__ 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +/* # undef _XOPEN_SOURCE */ +#endif + + +/* Use CISAM as INDEXED handler */ +/* #undef WITH_CISAM */ + +/* Use cJSON library/source as JSON handler */ +#define WITH_CJSON 1 + +/* curses library for extended SCREEN I/O */ +#define WITH_CURSES "ncursesw" + +/* Use Berkeley DB library as INDEXED handler */ +#define WITH_DB 1 + +/* Use DISAM as INDEXED handler */ +/* #undef WITH_DISAM */ + +/* Compile with obsolete external INDEXED handler */ +/* #undef WITH_INDEX_EXTFH */ + +/* JSON handler */ +#define WITH_JSON "cjson" + +/* Use JSON-C library as JSON handler */ +/* #undef WITH_JSON_C */ + +/* Math multiple precision library */ +/* #undef WITH_MATH */ + +/* Compile with obsolete external SEQ/RAN handler */ +/* #undef WITH_SEQRA_EXTFH */ + +/* Define variable sequential file format */ +#define WITH_VARSEQ 0 + +/* Use VBISAM as INDEXED handler */ +/* #undef WITH_VBISAM */ + +/* Use libxml2 as XML handler */ +#define WITH_XML2 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Define to 1 if on HPUX. */ +#ifndef _XOPEN_SOURCE_EXTENDED +/* # undef _XOPEN_SOURCE_EXTENDED */ +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +#endif diff --git a/configure.ac b/configure.ac index 477f877ce..9efe3fab2 100644 --- a/configure.ac +++ b/configure.ac @@ -134,6 +134,7 @@ AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) # used for bindt dnl Autoheader templates AH_TEMPLATE([COB_DEBUG_LOG], [Enable internal logging (Developers only!)]) AH_TEMPLATE([COB_EXPERIMENTAL], [Enable experimental code (Developers only!)]) +AH_TEMPLATE([COBC_IS_RELOCATABLE], [Enable path relocation from binary path]) AH_TEMPLATE([COB_TREE_DEBUG], [Enable extra checks within the compiler (Developers only!)]) AH_TEMPLATE([COB_PARAM_CHECK], [Enable minimum parameter check for system libraries]) AH_TEMPLATE([PATCH_LEVEL], [Define a patch level (numeric, max. 8 digits)]) @@ -219,6 +220,14 @@ AC_ARG_ENABLE([experimental], fi], []) +AC_ARG_ENABLE([relocatable], + [AS_HELP_STRING([--enable-relocatable], + [(GnuCOBOL) Enable relocation of paths from binary location])], + [if test "$enable_relocatable" = yes; then + AC_DEFINE([COBC_IS_RELOCATABLE], [1]) + fi], + []) + AC_ARG_ENABLE([cobc-internal-checks], [AS_HELP_STRING([--enable-cobc-internal-checks], [(GnuCOBOL) Enable extra checks within the compiler (Developers only!)])], From ebc7f789b277a36fc244f927553d9f3121cfbb28 Mon Sep 17 00:00:00 2001 From: Fabrice Le Fessant Date: Wed, 18 Oct 2023 11:59:50 +0200 Subject: [PATCH 2/2] xxx --- cobc/codegen.c | 31 ++++++++++++++----------------- cobc/ppparse.y | 9 ++------- cobc/settings.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ cobc/settings.def | 23 ++++++++++++++++++++++- cobc/typeck.c | 24 ++++++++++++------------ 5 files changed, 97 insertions(+), 37 deletions(-) diff --git a/cobc/codegen.c b/cobc/codegen.c index e92354ca8..fc622e8a6 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -1754,22 +1754,22 @@ output_standard_includes (struct cb_program *prog) { struct cb_program *p; -#if !defined (_GNU_SOURCE) && defined (_XOPEN_SOURCE_EXTENDED) - output_line ("#ifndef\t_XOPEN_SOURCE_EXTENDED"); - output_line ("#define\t_XOPEN_SOURCE_EXTENDED 1"); - output_line ("#endif"); -#endif + if (cb_setting_XOPEN_SOURCE_EXTENDED){ + output_line ("#ifndef\t_XOPEN_SOURCE_EXTENDED"); + output_line ("#define\t_XOPEN_SOURCE_EXTENDED 1"); + output_line ("#endif"); + } #if 0 /* Simon: why should we include that? */ output_line ("#include "); #endif output_line ("#include /* for memcpy, memcmp and friends */"); -#ifdef WORDS_BIGENDIAN - output_line ("#define WORDS_BIGENDIAN 1"); -#endif -#ifdef COB_KEYWORD_INLINE - output_line ("#define COB_KEYWORD_INLINE %s", - CB_XSTRINGIFY(COB_KEYWORD_INLINE)); -#endif + if (cb_setting_WORDS_BIGENDIAN){ + output_line ("#define WORDS_BIGENDIAN 1"); + } + if (cb_setting_COB_INLINE_KEYWORD){ + output_line ("#define COB_KEYWORD_INLINE %s", + cb_setting_COB_INLINE_KEYWORD); + } if (cb_flag_winmain) { output_line ("#include "); } @@ -6523,15 +6523,12 @@ output_call (struct cb_call *p) ret_ptr = 1; } -#ifdef _WIN32 - if (p->convention & CB_CONV_STDCALL) { + if (cb_setting_WIN32 && + (p->convention & CB_CONV_STDCALL) ) { convention = "_std"; } else { convention = ""; } -#else - convention = ""; -#endif /* System routine entry points */ if (p->is_system) { diff --git a/cobc/ppparse.y b/cobc/ppparse.y index 76b3c9a58..7ca6a2336 100644 --- a/cobc/ppparse.y +++ b/cobc/ppparse.y @@ -582,15 +582,10 @@ ppparse_clear_vars (const struct cb_define_struct *p) "SIGN", "'ASCII'", 0); } -#ifdef WORDS_BIGENDIAN ppp_setvar_list = ppp_define_add (ppp_setvar_list, "ENDIAN", - "'BIG'", 0); -#else - ppp_setvar_list = ppp_define_add (ppp_setvar_list, - "ENDIAN", - "'LITTLE'", 0); -#endif + cb_setting_WORDS_BIGENDIAN ? "'BIG'" : "'LITTLE'", + 0); #if ' ' == 0x20 ppp_setvar_list = ppp_define_add (ppp_setvar_list, "CHARSET", diff --git a/cobc/settings.c b/cobc/settings.c index 30cd649be..10c53e66c 100644 --- a/cobc/settings.c +++ b/cobc/settings.c @@ -89,6 +89,38 @@ relatively to the directory containing `cobc` (`$bindir`): * `COB_LIBRARY_PATH`: set to `$bindir/../lib/gnucobol` * `COB_LIBS`: `-L$bindir/../lib` is added in front +TODO in codegen.c: +* COB_ALIGN_PRAGMA_8 +* USE_INT_HEX +* COB_NON_ALIGNED +* COB_SHORT_BORK +* COB_EBCDIC_MACHINE +* GEN_CHAR_AS_UINT +* GEN_SINGLE_MEMCPY +* NO_INIT_SOURCE_LOC +* COB_64_BIT_POINTER +* COB_TREE_DEBUG +* COBC_HAS_CUTOFF_FLAG + +TODO in typeck.c: +* COB_EBCDIC_MACHINE +* COB_NON_ALIGNED +* COB_SHORT_BORK +* COB_ALLOW_UNALIGNED +* COB_64_BIT_POINTER +* WITH_EXTENDED_SCREENIO +* WIN32 +* WITH_XML2 + +TODO in parser.y: +* COB_EBCDIC_MACHINE +* COB_32_BIT_LONG + +TODO in ppparse.y: +* #if ' ' == 0x20 +* #elif ' ' == 0x40 + + */ #ifndef COB_DEBUG_FLAGS @@ -148,6 +180,17 @@ relatively to the directory containing `cobc` (`$bindir`): #define COB_NON_ALIGNED 0 #endif +#if !defined (_GNU_SOURCE) && defined (_XOPEN_SOURCE_EXTENDED) +#define XOPEN_SOURCE_EXTENDED 1 +#else +#define XOPEN_SOURCE_EXTENDED 0 +#endif + +#ifdef COB_KEYWORD_INLINE +#define COB_INLINE_KEYWORD CB_XSTRINGIFY(COB_KEYWORD_INLINE) +#else +#define COB_INLINE_KEYWORD NULL +#endif #ifndef COBC_IS_RELOCATABLE @@ -166,6 +209,10 @@ relatively to the directory containing `cobc` (`$bindir`): #define HAVE_MPIR_H 0 #endif +#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 0 +#endif + #ifndef HAVE_ATTRIBUTE_CONSTRUCTOR #define HAVE_ATTRIBUTE_CONSTRUCTOR 0 #endif diff --git a/cobc/settings.def b/cobc/settings.def index e2d784bc6..a293b3193 100644 --- a/cobc/settings.def +++ b/cobc/settings.def @@ -1,4 +1,12 @@ +/* All these settings must belong to these two categories: + - Settings that modify the way other commands are called (paths, options, etc.) + - Settings that modify the way the C code is generated + + We are not interested by compile time defines from config.h that only + modify the code of cobc, but have no impact on its runtime behavior. + */ + STRING_SETTING ( "executable name for module runner", COBCRUN_NAME ) @@ -65,7 +73,12 @@ STRING_SETTING ( "strip command", COB_STRIP_CMD ) -/* just to test BOOL_SETTING */ +STRING_SETTING ( +"need keyword for inline", + COB_INLINE_KEYWORD ) + + + BOOL_SETTING ( "has __attribute__((aligned))", @@ -119,6 +132,14 @@ BOOL_SETTING ( "Support for non aligned structures", COB_NON_ALIGNED ) +BOOL_SETTING ( +"XOPEN_SOURCE_EXTENDED is needed", + XOPEN_SOURCE_EXTENDED ) + +BOOL_SETTING ( +"set to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel).", + WORDS_BIGENDIAN ) + #if 0 diff --git a/cobc/typeck.c b/cobc/typeck.c index ddc3f567a..97e0dfe48 100644 --- a/cobc/typeck.c +++ b/cobc/typeck.c @@ -551,18 +551,18 @@ cb_is_integer_field (struct cb_field *f) if (f->usage == CB_USAGE_BINARY && cb_binary_truncate) return 0; -#ifdef WORDS_BIGENDIAN - if (f->usage != CB_USAGE_COMP_5 - && f->usage != CB_USAGE_DISPLAY - && f->usage != CB_USAGE_BINARY - && f->usage != CB_USAGE_COMP_X) - return 0; -#else - if (f->usage != CB_USAGE_COMP_5 - && f->usage != CB_USAGE_BINARY - && f->usage != CB_USAGE_DISPLAY) - return 0; -#endif + if (cb_setting_WORDS_BIGENDIAN){ + if (f->usage != CB_USAGE_COMP_5 + && f->usage != CB_USAGE_DISPLAY + && f->usage != CB_USAGE_BINARY + && f->usage != CB_USAGE_COMP_X) + return 0; + } else { + if (f->usage != CB_USAGE_COMP_5 + && f->usage != CB_USAGE_BINARY + && f->usage != CB_USAGE_DISPLAY) + return 0; + } if (f->storage == CB_STORAGE_WORKING #ifdef COB_SHORT_BORK && (f->size == 4 || f->size == 8 || f->size == 1)