diff --git a/cobc/ChangeLog b/cobc/ChangeLog index c538b71f4..065eb13e9 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,4 +1,19 @@ +2022-03-10 Simon Sobisch + + * pplex.l (next_word_is_comment_paragraph_name): extracted from (ppinput) + * pplex.l (get_word): new function to extract word and use in + (is_condition_directive_clause, next_word_is_comment_paragraph_name) + * reserved.c, scanner.l, tree.h: renamed cb_memcpy_upper to + cb_memcpy_upper, as it does not follow strncpy rules + * reserved.c (cb_strcasecmp) streamlined from glibc implementation + * reserved.c, cobc.h: exported cb_strcasecmp + * cobc.c, parser.y, ppparse.y, typeck.c: replaced locale-aware + strcasecmp with cb_strcasecmp where possible + * cobc.c, codegen.c, field.c, help.c, parser.y, pplex.l, ppparse.y, + scanner.l, tree.c, cobc.h: cleanup of header inclusion (stdio.h, + string.h, strings.h) + 2022-03-03 Simon Sobisch * ppparse.y (ppp_set_value): parse MicroFocus style $SET (numlit); @@ -242,7 +257,7 @@ 2021-09-02 Simon Sobisch * reserved.c (cb_toupper): extracted and used in different places - * reserved.c (cb_strncpy_upper), tree.h: renamed + exported function + * reserved.c (cb_memcpy_upper), tree.h: renamed + exported function * scanner.l (copy_word_in_quotes, copy_two_words_in_quotes): internally upper-case when handling reserved word adjustment * reserved.c (is_invalid_word): word checks extended, cobc does not diff --git a/cobc/cobc.c b/cobc/cobc.c index ff52e9a24..693b4b453 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -31,6 +31,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include #include @@ -1733,13 +1736,13 @@ ec_duped (struct cb_text_list *ec_list, struct cb_text_list *ec, struct cb_text_list *ec_dupchk; /* TO-DO: Is duplication a problem? */ - /* TO-DO: Does this algo work? */ + /* TO-DO: Does this algo work? At least add a testcase... */ for (ec_dupchk = ec_list; ec_dupchk; ec_dupchk = ec_dupchk->next) { if (ec_dupchk == ec) { return 0; } if (ec_dupchk->text - && !strcasecmp(ec->text, ec_dupchk->text)) { + && !cb_strcasecmp(ec->text, ec_dupchk->text)) { cb_error_x (loc, _("duplicate exception '%s'"), CB_EXCEPTION_NAME (ec_idx)); ec_dupchk = NULL; @@ -2649,7 +2652,7 @@ cobc_def_dump_opts (const char *opt, const int on) int dump_to_set; cb_old_trace = 0; /* Use new methods */ - if (!strcasecmp (opt, "ALL")) { + if (!cb_strcasecmp (opt, "ALL")) { if (on) { cb_flag_dump = COB_DUMP_ALL; } else { @@ -2665,19 +2668,19 @@ cobc_def_dump_opts (const char *opt, const int on) } dump_to_set = 0; while (q) { - if (!strcasecmp (q, "FD")) { + if (!cb_strcasecmp (q, "FD")) { dump_to_set |= COB_DUMP_FD; - } else if (!strcasecmp (q, "WS")) { + } else if (!cb_strcasecmp (q, "WS")) { dump_to_set |= COB_DUMP_WS; - } else if (!strcasecmp (q, "LS")) { + } else if (!cb_strcasecmp (q, "LS")) { dump_to_set |= COB_DUMP_LS; - } else if (!strcasecmp (q, "RD")) { + } else if (!cb_strcasecmp (q, "RD")) { dump_to_set |= COB_DUMP_RD; - } else if (!strcasecmp (q, "SD")) { + } else if (!cb_strcasecmp (q, "SD")) { dump_to_set |= COB_DUMP_SD; - } else if (!strcasecmp (q, "SC")) { + } else if (!cb_strcasecmp (q, "SC")) { dump_to_set |= COB_DUMP_SC; - } else if (!strcasecmp (q, "LO")) { + } else if (!cb_strcasecmp (q, "LO")) { dump_to_set |= COB_DUMP_LO; } else { cobc_err_exit (_("option requires one of 'ALL', 'FD', 'WS', 'LS', " @@ -2701,7 +2704,7 @@ cobc_deciph_funcs (const char *opt) char *p; char *q; - if (!strcasecmp (opt, "ALL")) { + if (!cb_strcasecmp (opt, "ALL")) { cb_flag_functions_all = 1; return; } @@ -2780,7 +2783,7 @@ file_basename (const char *filename, const char *strip_ext) endp = startp; } if (endp > startp - && (!strip_ext || strcasecmp (endp, strip_ext) == 0)) { + && (!strip_ext || cb_strcasecmp (endp, strip_ext) == 0)) { len = endp - startp; } else { len = strlen (startp); @@ -2821,16 +2824,16 @@ set_compile_level_from_file_extension (const char *filename) ext = file_extension (filename); - if (strcasecmp (ext, "i") == 0) { + if (cb_strcasecmp (ext, "i") == 0) { cb_compile_level = CB_LEVEL_PREPROCESS; - } else if (strcasecmp (ext, "c") == 0) { + } else if (cb_strcasecmp (ext, "c") == 0) { cb_compile_level = CB_LEVEL_TRANSLATE; save_c_src = 1; - } else if (strcasecmp (ext, "s") == 0 || strcasecmp (ext, "asm") == 0) { + } else if (cb_strcasecmp (ext, "s") == 0 || cb_strcasecmp (ext, "asm") == 0) { cb_compile_level = CB_LEVEL_COMPILE; - } else if (strcasecmp (ext, COB_OBJECT_EXT) == 0) { + } else if (cb_strcasecmp (ext, COB_OBJECT_EXT) == 0) { cb_compile_level = CB_LEVEL_ASSEMBLE; - } else if (strcasecmp (ext, COB_MODULE_EXT) == 0 && !cobc_flag_main) { + } else if (cb_strcasecmp (ext, COB_MODULE_EXT) == 0 && !cobc_flag_main) { if (cobc_flag_library) { cb_compile_level = CB_LEVEL_LIBRARY; } else { @@ -3430,7 +3433,7 @@ process_command_line (const int argc, char **argv) if (strlen (cob_optarg) > 64U) { cobc_err_exit (COBC_INV_PAR, "-D"); } - if (!strcasecmp (cob_optarg, "ebug")) { + if (!cb_strcasecmp (cob_optarg, "ebug")) { cobc_err_msg (_("warning: assuming '%s' is a DEFINE - did you intend to use -debug?"), cob_optarg); } @@ -3490,8 +3493,8 @@ process_command_line (const int argc, char **argv) cobc_err_exit (COBC_INV_PAR, "-l"); } #ifdef _MSC_VER - /* note: strcasecmp because of possible different specified extension */ - if (!strcasecmp (file_extension (cob_optarg), "lib")) { + /* note: cb_strcasecmp because of likely compilation on FAT/NTFS */ + if (!cb_strcasecmp (file_extension (cob_optarg), "lib")) { COBC_ADD_STR (cobc_libs, " \"", cob_optarg, "\""); } else { COBC_ADD_STR (cobc_libs, " \"", cob_optarg, ".lib\""); @@ -3551,9 +3554,9 @@ process_command_line (const int argc, char **argv) case 3: /* -fsign= : Specify display sign */ - if (!strcasecmp (cob_optarg, "EBCDIC")) { + if (!cb_strcasecmp (cob_optarg, "EBCDIC")) { cb_ebcdic_sign = 1; - } else if (!strcasecmp (cob_optarg, "ASCII")) { + } else if (!cb_strcasecmp (cob_optarg, "ASCII")) { cb_ebcdic_sign = 0; } else { cobc_err_exit (COBC_INV_PAR, "-fsign"); @@ -3562,9 +3565,9 @@ process_command_line (const int argc, char **argv) case 4: /* -ffold-copy= : COPY fold case */ - if (!strcasecmp (cob_optarg, "UPPER")) { + if (!cb_strcasecmp (cob_optarg, "UPPER")) { cb_fold_copy = COB_FOLD_UPPER; - } else if (!strcasecmp (cob_optarg, "LOWER")) { + } else if (!cb_strcasecmp (cob_optarg, "LOWER")) { cb_fold_copy = COB_FOLD_LOWER; } else { cobc_err_exit (COBC_INV_PAR, "-ffold-copy"); @@ -3573,9 +3576,9 @@ process_command_line (const int argc, char **argv) case 5: /* -ffold-call= : CALL/PROG-ID fold case */ - if (!strcasecmp (cob_optarg, "UPPER")) { + if (!cb_strcasecmp (cob_optarg, "UPPER")) { cb_fold_call = COB_FOLD_UPPER; - } else if (!strcasecmp (cob_optarg, "LOWER")) { + } else if (!cb_strcasecmp (cob_optarg, "LOWER")) { cb_fold_call = COB_FOLD_LOWER; } else { cobc_err_exit (COBC_INV_PAR, "-ffold-call"); @@ -4034,10 +4037,10 @@ process_filename (const char *filename) extension = file_extension (filename); /* set source file for possible error message */ cb_source_file = filename; - /* note: strcasecmp because of possible compilation on FAT/NTFS */ - if (strcasecmp (extension, "lib") - && strcasecmp (extension, "a") - && strcasecmp (extension, COB_OBJECT_EXT)) { + /* note: cb_strcasecmp because of possible compilation on FAT/NTFS */ + if (cb_strcasecmp (extension, "lib") + && cb_strcasecmp (extension, "a") + && cb_strcasecmp (extension, COB_OBJECT_EXT)) { if (cobc_check_valid_name (fbasename, FILE_BASE_NAME)) { return NULL; } @@ -4064,11 +4067,11 @@ process_filename (const char *filename) /* Already preprocessed */ fn->need_preprocess = 0; } else - if (strcasecmp (extension, "c") == 0 + if (cb_strcasecmp (extension, "c") == 0 #if defined(_WIN32) - || strcasecmp (extension, "asm") == 0 + || cb_strcasecmp (extension, "asm") == 0 #endif - || strcasecmp (extension, "s") == 0) { + || cb_strcasecmp (extension, "s") == 0) { /* Already compiled */ fn->need_preprocess = 0; fn->need_translate = 0; @@ -4077,15 +4080,15 @@ process_filename (const char *filename) #if defined(__OS400__) extension[0] == 0 #else - strcasecmp (extension, COB_OBJECT_EXT) == 0 + cb_strcasecmp (extension, COB_OBJECT_EXT) == 0 #if defined(_WIN32) - || strcasecmp (extension, "lib") == 0 + || cb_strcasecmp (extension, "lib") == 0 #endif #if !defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) - || strcasecmp (extension, "a") == 0 - || strcasecmp (extension, "so") == 0 - || strcasecmp (extension, "dylib") == 0 - || strcasecmp (extension, "sl") == 0 + || cb_strcasecmp (extension, "a") == 0 + || cb_strcasecmp (extension, "so") == 0 + || cb_strcasecmp (extension, "dylib") == 0 + || cb_strcasecmp (extension, "sl") == 0 #endif #endif ) { @@ -4442,7 +4445,7 @@ process_run (const char *name) /* strip period + COB_MODULE_EXT if specified */ if (output_name && curr_size < cobc_buffer_size) { buffer = file_extension (output_name); - if (!strcasecmp (buffer, COB_MODULE_EXT)) { + if (!cb_strcasecmp (buffer, COB_MODULE_EXT)) { *(cobc_buffer + curr_size - strlen (buffer) - 1) = 0; } } @@ -4453,7 +4456,7 @@ process_run (const char *name) 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] && strcasecmp (buffer, exe_ext)) { + if (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); } else { @@ -4461,7 +4464,7 @@ process_run (const char *name) SLASH_CHAR, name); } } else { - if (COB_EXE_EXT[0] && strcasecmp (buffer, exe_ext)) { + if (COB_EXE_EXT[0] && cb_strcasecmp (buffer, exe_ext)) { curr_size = snprintf (cobc_buffer, cobc_buffer_size, "%s%s", name, COB_EXE_EXT); } else { @@ -7217,15 +7220,15 @@ print_replace_main (struct list_files *cfile, FILE *fd, /* Check whether we're given a COPY or REPLACE statement. */ to_ptr = get_next_token (cmp_line, ttoken, tterm); - is_copy_line = !strcasecmp (ttoken, "COPY"); - is_replace_line = !strcasecmp (ttoken, "REPLACE"); + is_copy_line = !cb_strcasecmp (ttoken, "COPY"); + is_replace_line = !cb_strcasecmp (ttoken, "REPLACE"); if (is_replace_line && to_ptr) { #if 0 to_ptr = get_next_token (to_ptr, ttoken, tterm); #else (void)get_next_token (to_ptr, ttoken, tterm); #endif - is_replace_off = !strcasecmp (ttoken, "OFF"); + is_replace_off = !cb_strcasecmp (ttoken, "OFF"); } /* @@ -8280,7 +8283,7 @@ process_link (struct filename *l) cobc_chk_buff_size (strlen (COB_STRIP_CMD) + 4 + strlen (name) + strlen (COB_EXE_EXT)); /* only add COB_EXE_EXT if it is not specified */ exe_name = file_extension (name); - if (strcasecmp (exe_name, exe_ext)) { + if (cb_strcasecmp (exe_name, exe_ext)) { sprintf (cobc_buffer, "%s \"%s%s\"", COB_STRIP_CMD, name, COB_EXE_EXT); } else { @@ -8397,13 +8400,13 @@ set_cobc_defaults (void) /* Different styles for warning/error messages */ p = cobc_getenv ("COB_MSG_FORMAT"); #if defined (_MSC_VER) - if (p && strcasecmp (p, "GCC") == 0) { + if (p && cb_strcasecmp (p, "GCC") == 0) { cb_msg_style = CB_MSG_STYLE_GCC; } else { cb_msg_style = CB_MSG_STYLE_MSC; } #else - if (p && strcasecmp (p, "MSC") == 0) { + if (p && cb_strcasecmp (p, "MSC") == 0) { cb_msg_style = CB_MSG_STYLE_MSC; } else { cb_msg_style = CB_MSG_STYLE_GCC; diff --git a/cobc/cobc.h b/cobc/cobc.h index e1604c25b..164a2d1cf 100644 --- a/cobc/cobc.h +++ b/cobc/cobc.h @@ -23,14 +23,12 @@ #ifndef CB_COBC_H #define CB_COBC_H -#include +/* inclusion of common.h to get type definitions and some macros + TODO: move those out of common.h to a second installed header + and include that here */ #ifdef HAVE_UNISTD_H #include #endif -#ifdef HAVE_STRINGS_H -#include -#endif - #include "../libcob/common.h" #ifdef ENABLE_NLS @@ -694,4 +692,6 @@ extern void activate_intrinsic (const char *, const char *, const int); extern void deactivate_system_name (const char *, const char *, const int); extern void activate_system_name (const char *, const char *, const int); +extern int cb_strcasecmp (const void *, const void *); + #endif /* CB_COBC_H */ diff --git a/cobc/codegen.c b/cobc/codegen.c index 5f43b2486..401565248 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -27,6 +27,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include #include diff --git a/cobc/field.c b/cobc/field.c index a0c83848d..bc1195697 100644 --- a/cobc/field.c +++ b/cobc/field.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include diff --git a/cobc/help.c b/cobc/help.c index e07054e92..89c4fa88f 100644 --- a/cobc/help.c +++ b/cobc/help.c @@ -22,6 +22,7 @@ #include "config.h" #include +#include #include "cobc.h" diff --git a/cobc/parser.y b/cobc/parser.y index 300755706..ac5a1ff32 100644 --- a/cobc/parser.y +++ b/cobc/parser.y @@ -1,5 +1,5 @@ /* - Copyright (C) 2001-2012, 2014-2021 Free Software Foundation, Inc. + Copyright (C) 2001-2012, 2014-2022 Free Software Foundation, Inc. Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart @@ -29,7 +29,11 @@ #include "config.h" #include +#include #include +#ifdef HAVE_STRINGS_H +#include +#endif #define COB_IN_PARSER 1 #include "cobc.h" @@ -4203,11 +4207,11 @@ mnemonic_choices: CB_CHAIN_PAIR (current_program->mnemonic_spec_list, $3, save_tree); /* remove non-standard context-sensitive words when identical to mnemonic */ - if (strcasecmp (CB_NAME($3), "EXTERN" ) == 0 || - strcasecmp (CB_NAME($3), "STDCALL") == 0 || - strcasecmp (CB_NAME($3), "STATIC" ) == 0 || - strcasecmp (CB_NAME($3), "C" ) == 0 || - strcasecmp (CB_NAME($3), "PASCAL" ) == 0) { + if (cb_strcasecmp (CB_NAME($3), "EXTERN" ) == 0 + || cb_strcasecmp (CB_NAME($3), "STDCALL") == 0 + || cb_strcasecmp (CB_NAME($3), "STATIC" ) == 0 + || cb_strcasecmp (CB_NAME($3), "C" ) == 0 + || cb_strcasecmp (CB_NAME($3), "PASCAL" ) == 0) { remove_context_sensitivity (CB_NAME($3), CB_CS_CALL); } } diff --git a/cobc/pplex.l b/cobc/pplex.l index 40759ff54..80bec3f8f 100644 --- a/cobc/pplex.l +++ b/cobc/pplex.l @@ -83,6 +83,10 @@ static int ppwrap (void) { #include #include #include +#include +#ifdef HAVE_STRINGS_H +#include +#endif #define COB_IN_PPLEX 1 #include "cobc.h" @@ -1519,25 +1523,84 @@ switch_to_buffer (const int line, const char *file, const YY_BUFFER_STATE buffer yy_switch_to_buffer (buffer); } +static COB_INLINE COB_A_INLINE int +is_cobol_word_char (const char c) +{ + return c == '-' || c == '_' || isalnum (c); +} + +static char * +get_word (const char *str, char *word_buff) +{ + char *ret = NULL; + if (str) { + int length = COB_MAX_WORDLEN + 1; + while (*str == ' ' || *str == ',' || *str == ';') { + ++str; + } + ret = word_buff; + while (is_cobol_word_char(*str) + && length--) { + *word_buff++ = toupper((unsigned char)*str++); + } + if (length != 0) { + *word_buff = 0; + } else { + ret = NULL; + } + } + return ret; +} + static int is_condition_directive_clause (const char *buff) { - while (buff && !isalpha ((unsigned char)(*buff))) { - ++buff; + char word_buff[COB_MAX_WORDLEN + 1]; + char *p; + if (buff[0] == '$') { + buff++; + } else if (buff[0] == '>' && buff[1] == '>') { + buff += 2; + } + p = get_word (buff, word_buff); + + if (p == NULL) { + return 0; } - return buff && (strncasecmp (buff, "END", 3) == 0 - || strncasecmp (buff, "IF", 2) == 0 - || strncasecmp (buff, "ELSE", 4) == 0 - || strncasecmp (buff, "ELIF", 4) == 0 - || strncasecmp (buff, "EVALUATE", 8) == 0 - || strncasecmp (buff, "WHEN", 4) == 0); + return (strcmp (p, "IF") == 0 + || strcmp (p, "ELSE") == 0 + || strcmp (p, "END-IF") == 0 + || strcmp (p, "ELIF") == 0 + || strcmp (p, "END") == 0 + || strcmp (p, "EVALUATE") == 0 + || strcmp (p, "WHEN") == 0) + || strcmp (p, "END-EVALUATE") == 0; } static int -is_cobol_word_char (const char c) +next_word_is_comment_paragraph_name (const char *buff) { - return c == '-' || c == '_' || isalnum (c); + char word_buff[COB_MAX_WORDLEN + 1]; + const char *p = get_word (buff, word_buff); + + if (!p) { + return 0; + } + if (strcmp (p, "AUTHOR") == 0 + || strcmp (p, "DATE-WRITTEN") == 0 + || strcmp (p, "DATE-MODIFIED") == 0 + || strcmp (p, "DATE-COMPILED") == 0 + || strcmp (p, "INSTALLATION") == 0 + || strcmp (p, "REMARKS") == 0 + || strcmp (p, "SECURITY") == 0) { + if (cb_comment_paragraphs != CB_IGNORE) { + /* check so we get warnings / errors, but leave result unchanged */ + cb_plex_verify (newline_count, cb_comment_paragraphs, p); + return 1; + } + } + return 0; } @@ -1559,7 +1622,6 @@ ppinput (char *buff, const size_t max_size) int n; int coln; struct list_skip *skip; - const char *paragraph_name; /* check that we actually have input to process (isn't the case if something went wrong beforehand) */ @@ -1666,8 +1728,8 @@ start: if (buff[n - 1] != '\n') { /* FIXME: cb_source_line is one too low when CB_FORMAT_FREE is used - [but only during ppinput() in pplex.l ?] - Workaround for now: - Temporary newline_count + 1 + [but only during ppinput() in pplex.l ?] + Workaround for now: Temporary newline_count + 1 */ if (cb_source_format == CB_FORMAT_FREE) { if (line_overflow == 0) { @@ -1735,7 +1797,7 @@ start: /* Show warning if it is not whitespace (postponed after checking for comments by setting line_overflow to first column that leads to - "source text too long") + "source text too long") */ if (cb_warn_opt_val[cb_warn_column_overflow] && line_overflow == 0) { for (coln = cb_text_column; coln < n; ++coln) { @@ -1756,11 +1818,11 @@ start: } memset (buff, ' ', (size_t)6); - /* Note we allow directive lines to start at column 7 */ + /* Note we allow directive lines to start at column 7 */ bp = &buff[6]; - /* Special case: acucomment must be checked here as we'd pass comments - as directives otherwise */ + /* Special case: acucomment must be checked here as we'd pass comments + as directives otherwise */ if (cb_flag_acucomment && buff[6] == '$') { buff[6] = '*'; } @@ -1786,7 +1848,7 @@ start: } } if (ipchar && (!plex_skip_input - || is_condition_directive_clause (bp))) { + || is_condition_directive_clause (bp))) { /* Directive - pass complete line with NL to ppparse */ if (newline_count) { /* Move including NL and NULL byte */ @@ -1820,34 +1882,11 @@ start: /* Check that line isn't start of ID DIVISION comment paragraph. */ - if (comment_allowed) { - if (!strncasecmp (bp, "AUTHOR", 6)) { - paragraph_name = "AUTHOR"; - } else if (!strncasecmp (bp, "DATE-WRITTEN", 12)) { - paragraph_name = "DATE-WRITTEN"; - } else if (!strncasecmp (bp, "DATE-MODIFIED", 13)) { - paragraph_name = "DATE-MODIFIED"; - } else if (!strncasecmp (bp, "DATE-COMPILED", 13)) { - paragraph_name = "DATE-COMPILED"; - } else if (!strncasecmp (bp, "INSTALLATION", 12)) { - paragraph_name = "INSTALLATION"; - } else if (!strncasecmp (bp, "REMARKS", 7)) { - paragraph_name = "REMARKS"; - } else if (!strncasecmp (bp, "SECURITY", 8)) { - paragraph_name = "SECURITY"; - } else { - paragraph_name = NULL; - } - - if (paragraph_name - && !is_cobol_word_char (bp[strlen (paragraph_name)])) { - cb_plex_verify (newline_count, cb_comment_paragraphs, - paragraph_name); - /* Skip comments until the end of line. */ - within_comment = 1; - ++newline_count; - goto start; - } + if (comment_allowed && next_word_is_comment_paragraph_name (bp)) { + /* Skip comments until the end of line. */ + within_comment = 1; + ++newline_count; + goto start; } /* Return when free format (no floating comments removed!) */ diff --git a/cobc/ppparse.y b/cobc/ppparse.y index 51cefd749..07ecf1f4a 100644 --- a/cobc/ppparse.y +++ b/cobc/ppparse.y @@ -38,6 +38,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #define COB_IN_PPPARSE 1 @@ -406,7 +409,7 @@ static unsigned int ppp_search_comp_vars (const char *name) { #undef CB_PARSE_DEF -#define CB_PARSE_DEF(x,z) if (!strcasecmp (name, x)) return (z); +#define CB_PARSE_DEF(x,z) if (!cb_strcasecmp (name, x)) return (z); #include "ppparse.def" #undef CB_PARSE_DEF cb_warning (COBC_WARN_FILLER, _("compiler flag '%s' unknown"), name); @@ -837,9 +840,9 @@ set_choice: size = strlen (p) - 1; p[size] = '\0'; - if (!strcasecmp (p, "EXTERNAL")) { + if (!cb_strcasecmp (p, "EXTERNAL")) { fprintf (ppout, "#ASSIGN %d\n", (int)CB_ASSIGN_EXT_FILE_NAME_REQUIRED); - } else if (!strcasecmp (p, "DYNAMIC")) { + } else if (!cb_strcasecmp (p, "DYNAMIC")) { fprintf (ppout, "#ASSIGN %d\n", (int)CB_ASSIGN_VARIABLE_DEFAULT); } else { ppp_error_invalid_option ("ASSIGN", p); @@ -879,9 +882,9 @@ set_choice: size = strlen (p) - 1; p[size] = '\0'; - if (!strcasecmp (p, "BINARY")) { + if (!cb_strcasecmp (p, "BINARY")) { cb_binary_comp_1 = 1; - } else if (!strcasecmp (p, "FLOAT")) { + } else if (!cb_strcasecmp (p, "FLOAT")) { cb_binary_comp_1 = 0; } else { ppp_error_invalid_option ("COMP1", p); @@ -897,11 +900,11 @@ set_choice: size = strlen (p) - 1; p[size] = '\0'; - if (!strcasecmp (p, "XML")) { + if (!cb_strcasecmp (p, "XML")) { cb_dpc_in_data = CB_DPC_IN_XML; - } else if (!strcasecmp (p, "JSON")) { + } else if (!cb_strcasecmp (p, "JSON")) { cb_dpc_in_data = CB_DPC_IN_JSON; - } else if (!strcasecmp (p, "ALL")) { + } else if (!cb_strcasecmp (p, "ALL")) { cb_dpc_in_data = CB_DPC_IN_ALL; } else { ppp_error_invalid_option ("DPC-IN-DATA", p); @@ -917,9 +920,9 @@ set_choice: size = strlen (p) - 1; p[size] = '\0'; - if (!strcasecmp (p, "UPPER")) { + if (!cb_strcasecmp (p, "UPPER")) { cb_fold_copy = COB_FOLD_UPPER; - } else if (!strcasecmp (p, "LOWER")) { + } else if (!cb_strcasecmp (p, "LOWER")) { cb_fold_copy = COB_FOLD_LOWER; } else { ppp_error_invalid_option ("FOLD-COPY-NAME", p); @@ -992,12 +995,12 @@ set_choice: size = strlen (p) - 1; p[size] = '\0'; - if (!strcasecmp (p, "FIXED")) { + if (!cb_strcasecmp (p, "FIXED")) { cb_source_format = CB_FORMAT_FIXED; cb_text_column = cb_config_text_column; - } else if (!strcasecmp (p, "FREE")) { + } else if (!cb_strcasecmp (p, "FREE")) { cb_source_format = CB_FORMAT_FREE; - } else if (!strcasecmp (p, "VARIABLE")) { + } else if (!cb_strcasecmp (p, "VARIABLE")) { cb_source_format = CB_FORMAT_FIXED; /* This value matches most MF Visual COBOL 4.0 version. */ cb_text_column = 250; diff --git a/cobc/reserved.c b/cobc/reserved.c index 31ee2182a..ab6407d22 100644 --- a/cobc/reserved.c +++ b/cobc/reserved.c @@ -3893,29 +3893,28 @@ cb_toupper (unsigned char c) } /* comparisions _for reserved words_ */ -static int + +/* Compare S1 and S2, ignoring case (only a-z converted, no locales), + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or greater than S2. */ +int cb_strcasecmp (const void *s1, const void *s2) { - const unsigned char *p1; - const unsigned char *p2; - unsigned char c1; - unsigned char c2; + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + int result; - p1 = (const unsigned char *)s1; - p2 = (const unsigned char *)s2; - - for (;;) { - c1 = cb_toupper (*p1++); - c2 = cb_toupper (*p2++); + if (p1 == p2) { + return 0; + } - if (c1 != c2) { - return c1 < c2 ? -1 : 1; - } - if (!c1) { + while ((result = cb_toupper (*p1) - cb_toupper (*p2++)) == 0) { + if (*p1++ == '\0') { break; } } - return 0; + + return result; } static int @@ -3999,7 +3998,7 @@ has_context_sensitive_indicator (const char *word, const size_t size) uppercased, to dest. We use cob_lower_tab instead of toupper for efficiency. */ void -cb_strncpy_upper (char *dest, const char * source, size_t len) +cb_memcpy_upper (char *dest, const char *source, size_t len) { while (len--) { *dest++ = cb_toupper(*source++); @@ -4017,15 +4016,19 @@ cb_strupr (char *s) { } #endif +/* allocate OUT_STR with given SIZE and trailing zero + and copy an upper-case version of memory at WORD into it */ static void allocate_upper_case_str (const char *word, const size_t size, char ** const out_str) { *out_str = cobc_main_malloc (size + 1U); - cb_strncpy_upper (*out_str, word, size); + cb_memcpy_upper (*out_str, word, size); (*out_str)[size] = '\0'; } - +/* allocate OUT_STR with given SIZE and trailing zero + and copy an upper-case version of memory at WORD into it; + if the position SIZE contains an asterisk don't copy that */ static void allocate_upper_case_str_removing_asterisk (const char *word, const size_t size, char ** const out_str) @@ -4103,7 +4106,7 @@ static struct cobc_reserved * search_reserved_list (const char * const word, const int needs_uppercasing, const struct cobc_reserved * const list, size_t list_len) { - static char upper_word[43]; + static char upper_word[COB_MAX_WORDLEN + 1]; size_t word_len; const char *sought_word; struct cobc_reserved to_find; @@ -4115,7 +4118,7 @@ search_reserved_list (const char * const word, const int needs_uppercasing, } /* copy including terminating byte */ - cb_strncpy_upper (upper_word, word, word_len); + cb_memcpy_upper (upper_word, word, word_len); sought_word = upper_word; } else { sought_word = word; @@ -4730,7 +4733,7 @@ add_reserved_word (const char *word, const char *fname, const int line) if (word_len > sizeof (upper_word)) { return; } - cb_strncpy_upper (upper_word, word, word_len); + cb_memcpy_upper (upper_word, word, word_len); add_amendment (upper_word, fname, line, 1); } @@ -4749,7 +4752,7 @@ remove_reserved_word (const char *word, const char *fname, const int line) if (word_len > sizeof (upper_word)) { return; } - cb_strncpy_upper (upper_word, word, word_len); + cb_memcpy_upper (upper_word, word, word_len); remove_reserved_word_internal(upper_word, fname, word_len); add_amendment (upper_word, fname, line, 0); @@ -4876,7 +4879,7 @@ lookup_intrinsic (const char *name, const int checkimpl) } /* copy including terminating byte */ - cb_strncpy_upper (upper_name, name, name_len + 1); + cb_memcpy_upper (upper_name, name, name_len + 1); cbp = bsearch (upper_name, function_list, NUM_INTRINSICS, sizeof (struct cb_intrinsic_table), intrinsic_comp); @@ -5015,7 +5018,7 @@ lookup_register (const char *name, const int checkimpl) } /* copy including terminating byte */ - cb_strncpy_upper (upper_name, name, name_len + 1); + cb_memcpy_upper (upper_name, name, name_len + 1); return lookup_register_internal (upper_name, checkimpl); } @@ -5059,7 +5062,7 @@ add_register (const char *name_and_definition, const char *fname, const int line return; } /* copy including terminating byte */ - cb_strncpy_upper (upper_name, name, name_len + 1); + cb_memcpy_upper (upper_name, name, name_len + 1); special_register = lookup_register_internal (upper_name, 1); if (!special_register) { diff --git a/cobc/scanner.l b/cobc/scanner.l index 71ee8af50..fc2ce7534 100644 --- a/cobc/scanner.l +++ b/cobc/scanner.l @@ -85,6 +85,11 @@ static int yywrap (void) { #include #include +#include +#ifdef HAVE_STRINGS_H +#include +#endif + #ifdef HAVE_UNISTD_H #include #else @@ -2290,7 +2295,7 @@ copy_word_in_quotes (char ** const word) word_str = strtok (NULL, "\n"); word_len = strlen (word_str) - 2; *word = cobc_malloc (word_len + 1); - cb_strncpy_upper (*word, word_str + 1, word_len); + cb_memcpy_upper (*word, word_str + 1, word_len); cobc_free (text); } @@ -2316,12 +2321,12 @@ copy_two_words_in_quotes (char ** const word1, char ** const word2) word1_str = strtok (NULL, " "); word_len = strlen (word1_str) - 2; *word1 = cobc_malloc (word_len + 1); - cb_strncpy_upper (*word1, word1_str + 1, word_len); + cb_memcpy_upper (*word1, word1_str + 1, word_len); word2_str = strtok (NULL, "\n"); word_len = strlen (word2_str) - 2; *word2 = cobc_malloc (word_len + 1); - cb_strncpy_upper (*word2, word2_str + 1, word_len); + cb_memcpy_upper (*word2, word2_str + 1, word_len); cobc_free (text); } diff --git a/cobc/tree.c b/cobc/tree.c index d3eed4f38..7ada279ed 100644 --- a/cobc/tree.c +++ b/cobc/tree.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include #ifndef LLONG_MAX diff --git a/cobc/tree.h b/cobc/tree.h index 4b5271421..70dcbff1f 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -2072,7 +2072,7 @@ extern void cb_list_exceptions (void); extern void cb_list_registers (void); extern void cb_list_system_routines (void); extern int cb_list_map (cb_tree (*) (cb_tree), cb_tree); -extern void cb_strncpy_upper (char *, const char * const, size_t); +extern void cb_memcpy_upper (char *, const char * const, size_t); /* error.c */ extern cb_tree get_cb_error_node (void); diff --git a/cobc/typeck.c b/cobc/typeck.c index 349c455ab..9e2605799 100644 --- a/cobc/typeck.c +++ b/cobc/typeck.c @@ -1678,43 +1678,43 @@ cb_build_single_register (const char *name, const char *definition) /* registers that are currently created elsewhere TODO: move them here */ /* FIXME: LENGTH OF (must have different results depending on compiler configuration) */ - if (!strcasecmp (name, "ADDRESS OF") - || !strcasecmp (name, "LENGTH OF") - || !strcasecmp (name, "COB-CRT-STATUS") - || !strcasecmp (name, "DEBUG-ITEM")) { + if (!cb_strcasecmp (name, "ADDRESS OF") + || !cb_strcasecmp (name, "LENGTH OF") + || !cb_strcasecmp (name, "COB-CRT-STATUS") + || !cb_strcasecmp (name, "DEBUG-ITEM")) { return; } /* registers that need a special handling / internal registration */ - if (!strcasecmp (name, "JSON-CODE")) { + if (!cb_strcasecmp (name, "JSON-CODE")) { cb_build_register_json_code (name, definition); return; } - if (!strcasecmp (name, "RETURN-CODE")) { + if (!cb_strcasecmp (name, "RETURN-CODE")) { cb_build_register_return_code (name, definition); return; } - if (!strcasecmp (name, "SORT-RETURN")) { + if (!cb_strcasecmp (name, "SORT-RETURN")) { cb_build_register_sort_return (name, definition); return; } - if (!strcasecmp (name, "NUMBER-OF-CALL-PARAMETERS")) { + if (!cb_strcasecmp (name, "NUMBER-OF-CALL-PARAMETERS")) { cb_build_register_number_parameters (name, definition); return; } - if (!strcasecmp (name, "WHEN-COMPILED")) { + if (!cb_strcasecmp (name, "WHEN-COMPILED")) { cb_build_register_when_compiled (name, definition); return; } - if (!strcasecmp (name, "XML-CODE")) { + if (!cb_strcasecmp (name, "XML-CODE")) { cb_build_register_xml_code (name, definition); return; } /* "normal" registers */ - if (!strcasecmp (name, "TALLY") - || !strcasecmp (name, "LIN") - || !strcasecmp (name, "COL")) { + if (!cb_strcasecmp (name, "TALLY") + || !cb_strcasecmp (name, "LIN") + || !cb_strcasecmp (name, "COL")) { cb_build_generic_register (name, definition, NULL); return; } diff --git a/libcob/common.c b/libcob/common.c index 2337f2755..9b7ed10f8 100644 --- a/libcob/common.c +++ b/libcob/common.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include #include