diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 4704f1c09..ab7a0dd9a 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -2,20 +2,20 @@ 2023-07-05 Fabrice Le Fessant * replace.c: rewrite the code for preprocessing with a two-phase - algorithm. The first phase performs COPY REPLACING on the stream - of tokens, while the second phase perform REPLACE on the resulting - stream of tokens. This rewriting is closer to the COBOL standard - and fixes bug #831 partially. + algorithm. The first phase performs COPY REPLACING on the stream + of tokens, while the second phase perform REPLACE on the resulting + stream of tokens. This rewriting is closer to the COBOL standard + and fixes bug #831 partially. 2023-07-02 Fabrice Le Fessant * pplex.l/replace.c: move the preprocessing code performing - COPY REPLACING and REPLACE from pplex.l to replace.c + COPY REPLACING and REPLACE from pplex.l to replace.c 2023-07-02 Fabrice Le Fessant * pplex.l (ppecho, ppecho_direct): replace alt_space by passing a - second equivalent token + second equivalent token 2023-07-05 Fabrice Le Fessant @@ -97,8 +97,8 @@ * typeck.c (cb_build_expr): remove cb_ prefix from static functions and comment algorithm - Bugs #875 V IS ZERO AND, #880 error compiling abbreviated conditions - and #887 error compiling parenthesized relation + Bugs #875 V IS ZERO AND, #880 error compiling abbreviated conditions + and #887 error compiling parenthesized relation * typeck.c (cb_build_expr): additional generate 'invalid conditional expression' error", translate NOT comparison to inversed comparison * typeck.c (cb_build_expr), tree.c (cb_build_binary_op): give more diff --git a/cobc/pplex.l b/cobc/pplex.l index 52206e82c..d966a90ad 100644 --- a/cobc/pplex.l +++ b/cobc/pplex.l @@ -92,7 +92,6 @@ static int ppwrap (void) { #include "cobc.h" #include "tree.h" #include "ppparse.h" -#include "replace.h" #ifdef _WIN32 #include /* for access */ @@ -1970,6 +1969,11 @@ next_word_is_comment_paragraph_name (const char *buff) return 1; } +static COB_INLINE COB_A_INLINE int +is_space_or_nl (const char c) +{ + return c == ' ' || c == '\n'; +} /* FIXME: try to optimize as this function used 25-10% (according to callgrind) of the complete time spent in a sample run with diff --git a/cobc/replace.c b/cobc/replace.c index 4d7bd5f89..42e44f80a 100644 --- a/cobc/replace.c +++ b/cobc/replace.c @@ -38,10 +38,6 @@ #include "cobc.h" #include "tree.h" -#include "replace.h" - -#define TRUE 1 -#define FALSE 0 /* This is an implementation of the *two* phases of COPY-REPLACING and REPLACE on a stream of tokens: the stream of tokens generated by the @@ -54,9 +50,9 @@ been applied. The general entry point is `add_text_to_replace(stream, prequeue, - token)`, it adds `token` to `stream`, `prequeue` is TRUE if the + token)`, it adds `token` to `stream`, `prequeue` is 1 if the token should not be treated immediately (because it may be merged - with other following tokens if they are of the same kind), FALSE + with other following tokens if they are of the same kind), 0 otherwise. Initially, `pp_echo()` in `pplex.l` will use @@ -153,14 +149,14 @@ struct cb_replacement_state { char depth_buffer[MAX_DEPTH+1]; #define DEPTH depth_buffer + ( MAX_DEPTH-depth ) -#else // DEBUG_REPLACE_TRACE +#else /* DEBUG_REPLACE_TRACE */ #define WITH_DEPTH #define DEPTH #define INIT_DEPTH #define MORE_DEPTH -#endif // DEBUG_REPLACE_TRACE +#endif /* DEBUG_REPLACE_TRACE */ #ifdef DEBUG_REPLACE @@ -168,27 +164,36 @@ char depth_buffer[MAX_DEPTH+1]; #define MAX_TEXT_LIST_STRING 10000 char text_list_string[MAX_TEXT_LIST_STRING]; -static -char * string_of_list(const struct cb_text_list *list) -{ - int pos = 1; - text_list_string[0] = '['; - - for(; list != NULL; list = list->next){ - size_t len = strlen(list->text); - text_list_string[pos++] = '"'; - memcpy( text_list_string + pos, list->text, len ); - pos += len; - text_list_string[pos++] = '"'; - text_list_string[pos++] = ','; - text_list_string[pos++] = ' '; - } - - text_list_string[pos] = ']'; - text_list_string[pos+1]=0; - return text_list_string; +/* In debugging mode only, stores a list of text/tokens into a + preallocated string for easy display */ +#define STRING_OF_LIST(kind) \ +static \ +char * string_of_##kind##_list(const struct cb_##kind##_list *list) \ +{ \ + int pos = 1; \ + text_list_string[0] = '['; \ + \ + for(; list != NULL; list = list->next){ \ + size_t len = strlen(list->text); \ + text_list_string[pos++] = '"'; \ + memcpy( text_list_string + pos, list->text, len ); \ + pos += len; \ + text_list_string[pos++] = '"'; \ + text_list_string[pos++] = ','; \ + text_list_string[pos++] = ' '; \ + } \ + \ + text_list_string[pos] = ']'; \ + text_list_string[pos+1]=0; \ + return text_list_string; \ } -#endif // DEBUG_REPLACE + +/* string_of_token_list (...) */ +STRING_OF_LIST(token) +/* string_of_text_list (...) */ +STRING_OF_LIST(text) + +#endif /* DEBUG_REPLACE */ /* global state */ static struct cb_replacement_state * replace_repls; @@ -222,7 +227,7 @@ token_list_add (WITH_DEPTH struct cb_token_list *list, { #ifdef DEBUG_REPLACE_TRACE fprintf(stderr, "%stoken_list_add(%s,'%s')\n", - DEPTH, string_of_list(list), text); + DEPTH, string_of_token_list(list), text); #endif struct cb_token_list *p; @@ -286,7 +291,7 @@ void ppecho_switch_text_list (WITH_DEPTH struct cb_replacement_state *repls, { #ifdef DEBUG_REPLACE_TRACE fprintf(stderr, "%sppecho_switch_text_list(%s, %s)\n", - DEPTH, repls->name, string_of_list(p)); + DEPTH, repls->name, string_of_text_list(p)); #endif for (;p;p=p->next){ @@ -301,7 +306,7 @@ void ppecho_switch_token_list (WITH_DEPTH struct cb_replacement_state *repls, { #ifdef DEBUG_REPLACE_TRACE fprintf(stderr, "%sppecho_switch_token_list(%s, %s)\n", - DEPTH, repls->name, string_of_list(p)); + DEPTH, repls->name, string_of_token_list(p)); #endif for (;p;p=p->next){ @@ -316,18 +321,18 @@ int is_leading_or_trailing (WITH_DEPTH int leading, int strict) { - size_t src_len = strlen (src_text); - size_t text_len = strlen(text); + const size_t src_len = strlen (src_text); + const size_t text_len = strlen(text); int result ; if( text_len > src_len || ( !strict && text_len == src_len ) ){ int pos = leading ? 0 : text_len - src_len ; if( strncasecmp (src_text, text+pos, src_len) ){ - result = FALSE; + result = 0; } else { - result = TRUE; + result = 1; } } else { - result = FALSE; + result = 0; } #ifdef DEBUG_REPLACE_TRACE fprintf(stderr, @@ -453,6 +458,12 @@ void check_replace (WITH_DEPTH struct cb_replacement_state* repls, } } +static COB_INLINE COB_A_INLINE int +is_space_or_nl (const char c) +{ + return c == ' ' || c == '\n'; +} + /* `check_replace_all( repls, new_text, texts, src, replace_list )`: * checks whether a particular replacement is possible on the current * list of texts. @@ -474,11 +485,11 @@ void check_replace_all (WITH_DEPTH fprintf(stderr, "%scheck_replace_all(%s,", DEPTH, repls->name); fprintf(stderr, "%s new_text = %s,\n", DEPTH, - string_of_list(new_text)); + string_of_text_list(new_text)); fprintf(stderr, "%s texts = %s,\n", DEPTH, - string_of_list(texts)); + string_of_token_list(texts)); fprintf(stderr, "%s src = %s,\n", DEPTH, - string_of_list(src)); + string_of_text_list(src)); fprintf(stderr, "%s)\n", DEPTH); #endif @@ -608,15 +619,15 @@ int is_word (WITH_DEPTH const char* s){ } else { #ifdef DEBUG_REPLACE_TRACE - fprintf(stderr, "%sis_word('%s') -> FALSE\n", DEPTH, s); + fprintf(stderr, "%sis_word('%s') -> 0\n", DEPTH, s); #endif - return FALSE; + return 0; } } #ifdef DEBUG_REPLACE_TRACE - fprintf(stderr, "%sis_word('%s') -> TRUE\n", DEPTH, s); + fprintf(stderr, "%sis_word('%s') -> 1\n", DEPTH, s); #endif - return TRUE; + return 1; } static void add_text_to_replace (WITH_DEPTH struct cb_replacement_state *repls, @@ -649,7 +660,7 @@ static void add_text_to_replace (WITH_DEPTH struct cb_replacement_state *repls, if( repls->text_prequeue == NULL ){ /* not a word, and empty prequeue, * just perform replacements */ - add_text_to_replace(MORE_DEPTH repls, FALSE, text, token); + add_text_to_replace(MORE_DEPTH repls, 0, text, token); } else { /* not a word, one word in the * prequeue, flush the word from the @@ -658,9 +669,9 @@ static void add_text_to_replace (WITH_DEPTH struct cb_replacement_state *repls, const char* pretext = repls->text_prequeue; repls->text_prequeue = NULL; add_text_to_replace(MORE_DEPTH repls, - FALSE, pretext, NULL); + 0, pretext, NULL); add_text_to_replace(MORE_DEPTH repls, - FALSE, text, token); + 0, text, token); } } } @@ -684,7 +695,7 @@ static void add_text_to_replace (WITH_DEPTH struct cb_replacement_state *repls, } /* pass a text to the replace stream (called from the copy-replacing - stream). Use prequeue = TRUE so that texts of the same kind are + stream). Use prequeue = 1 so that texts of the same kind are merged into a single text. */ static void ppecho_replace (WITH_DEPTH const char *text, const char *token) @@ -692,11 +703,11 @@ static void ppecho_replace (WITH_DEPTH const char *text, const char *token) #ifdef DEBUG_REPLACE fprintf(stderr, "%sppecho_replace('%s')\n", DEPTH, text); #endif - add_text_to_replace(MORE_DEPTH replace_repls, TRUE, text, token); + add_text_to_replace(MORE_DEPTH replace_repls, 1, text, token); } /* pass a text to the copy-replacing stream (called from ppecho() in - pplex.l). Use prequeue = FALSE as texts of the same kind from the + pplex.l). Use prequeue = 0 as texts of the same kind from the source file should not be merged. */ void cb_ppecho_copy_replace (const char *text, const char *token) @@ -704,7 +715,7 @@ void cb_ppecho_copy_replace (const char *text, const char *token) #ifdef DEBUG_REPLACE fprintf(stderr, "cb_ppecho_copy_replace('%s')\n", text); #endif - add_text_to_replace(INIT_DEPTH copy_repls, FALSE, text, token); + add_text_to_replace(INIT_DEPTH copy_repls, 0, text, token); } @@ -790,11 +801,11 @@ void cb_set_copy_replacing_list (struct cb_replace_list *list) for(;list != NULL; list=list->next){ fprintf(stderr, " repl = {\n"); fprintf(stderr, " src = %s\n", - string_of_list(list->src->text_list)); + string_of_text_list(list->src->text_list)); fprintf(stderr, " leading = %d\n", list->src->lead_trail); fprintf(stderr, " new_text = %s\n", - string_of_list(list->new_text)); + string_of_text_list(list->new_text)); fprintf(stderr, " };\n"); } fprintf(stderr, " )\n"); diff --git a/cobc/replace.h b/cobc/replace.h deleted file mode 100644 index 25d02c78d..000000000 --- a/cobc/replace.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2023-2023 Free Software Foundation, Inc. - Written by 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 . -*/ - -#ifndef CB_REPLACE_H -#define CB_REPLACE_H - -// defined in pplex.l -extern void cb_ppecho_direct (const char *text, const char *token ); -extern struct cb_text_list *cb_pp_text_list_add (struct cb_text_list *, - const char *, const size_t); - -extern void cb_ppecho_copy_replace (const char *text, const char *token ); -extern void cb_free_replace (void); - -/* For COPY-REPLACING */ -extern void cb_set_copy_replacing_list (struct cb_replace_list *list); -extern struct cb_replace_list * cb_get_copy_replacing_list (void); - -extern void -cb_set_print_replace_list (struct cb_replace_list *); - -static COB_INLINE COB_A_INLINE int -is_space_or_nl (const char c) -{ - return c == ' ' || c == '\n'; -} - -#endif // CB_REPLACE_H diff --git a/cobc/tree.h b/cobc/tree.h index 829726890..5edbbe317 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -2572,6 +2572,21 @@ extern cb_tree cobc_tree_cast_check (const cb_tree, const char *, const int, const enum cb_tag); #endif +/* pplex.l */ +extern void cb_ppecho_direct (const char *text, const char *token ); +extern struct cb_text_list *cb_pp_text_list_add (struct cb_text_list *, + const char *, const size_t); +/* replace.c */ +extern void cb_ppecho_copy_replace (const char *text, const char *token ); +extern void cb_free_replace (void); + +/* For COPY-REPLACING */ +extern void cb_set_copy_replacing_list (struct cb_replace_list *list); +extern struct cb_replace_list * cb_get_copy_replacing_list (void); + +extern void +cb_set_print_replace_list (struct cb_replace_list *); + /* codeoptim.c */ extern void cob_gen_optim (const enum cb_optim);