From 1ba2da0536c4fb3f6067f1fce896eca8eb211f6d Mon Sep 17 00:00:00 2001 From: sbelondr Date: Tue, 7 Mar 2023 09:32:25 +0100 Subject: [PATCH 01/10] add fix for the tickets #831 and #863 --- cobc/ChangeLog | 7 + cobc/cobc.c | 1344 ++++++++++------------- cobc/codegen.c | 15 + cobc/tree.h | 11 + tests/ChangeLog | 7 + tests/testsuite.src/listings.at | 210 +++- tests/testsuite.src/run_reportwriter.at | 45 + 7 files changed, 898 insertions(+), 741 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index c13d4c6dc..8715395b0 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,4 +1,11 @@ +2023-03-07 Samuel Belondrade + + * codegen.c (output_report_control): add a loop to check if the variable + exist (bug: #863) + * cobc.c, tree.h : rewrite partialy the copy replacing in listing + mode (bug: #831) + 2023-02-21 Simon Sobisch * codegen.c, flag.def [COBC_HAS_CUTOFF_FLAG]: fix compile errors, diff --git a/cobc/cobc.c b/cobc/cobc.c index 0183804ce..fd12ea362 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6237,58 +6237,6 @@ get_next_nonspace (char * pos) return pos; } -/* - Find next token after bp, copy it to token and copy the token terminator to - term. Return pointer to the character after the terminator. -*/ -static char * -get_next_token (char *bp, char *token, char *term) -{ - char *token_start = token; - int in_string = 0; - - /* Repeat until a token is found */ - do { - bp = get_next_nonspace (bp); - - term[0] = '\0'; - term[1] = '\0'; - if (*bp == '\0') { - return NULL; - } - - /* Copy characters into token until a terminator is found. */ - while (*bp) { - /* Return character strings as a single token */ - if (*bp == '"' || *bp == '\'') { - in_string = !in_string; - *token++ = *bp++; - if (!in_string) { - if (isspace ((unsigned char)*bp) || *bp == ',' || *bp == '.' || *bp == ';') { - term[0] = *bp++; - } - break; - } - continue; - } - if (in_string) { - *token++ = *bp++; - continue; - } - if (*bp == '.' && isdigit((unsigned char)*(bp + 1))) { - ; - } else if (isspace ((unsigned char)*bp) || *bp == ',' || *bp == '.' || *bp == ';') { - term[0] = *bp++; - break; - } - *token++ = *bp++; - } - *token = '\0'; - } while (*token_start == '\0' && *term != '\0'); - - return bp; -} - static void terminate_str_at_first_of_char (const char c, char * const str) { @@ -6520,12 +6468,16 @@ static void print_fixed_line (const int line_num, char pch, char *line) { int i; - int len = strlen (line); + int len; const int max_chars_on_line = cb_listing_wide ? 112 : 72; const char *format_str; const int indicator = cobc_get_indicator (); const int text_column = cobc_get_text_column (); + if (!line) { + return ; + } + len = strlen (line); if (line[indicator] == '&') { line[indicator] = '-'; pch = '+'; @@ -6548,6 +6500,110 @@ print_fixed_line (const int line_num, char pch, char *line) } } +static int +is_quotes_char (char c, int quotes[2]) +{ + if (c == '\'') { + quotes[0] = !quotes[0]; + } + else if (c == '"') { + quotes[1] = !quotes[1]; + } else { + return 0; + } + return 1; +} + +#define NOT_TOO_LONG(idx,last_print_idx) \ + !((idx - last_print_idx + margin_b) >= (max_chars_on_line)) + +static void +print_multiple_fixed_line (const int line_num, char pch, char *line) +{ + int i = 0; + int start = 0; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; + char dst[max_chars_on_line + 1]; + int quotes[2] = {0, 0}; + int margin_b = cobc_get_margin_b (1); + int indicator = cobc_get_indicator (); + int last_word; + + bzero (dst, max_chars_on_line + 1); + memset (dst, ' ', margin_b); + + // skip space + while (isspace (line[i])) + ++i; + start = i; + last_word = -1; + + while (line[i]) + { + // loop space + while (line[i] && isspace (line[i]) && NOT_TOO_LONG (i, start)) { + ++i; + } + last_word = i; + // loop chars + if (NOT_TOO_LONG (i, start)) { + while (line[i] && !is_quotes_char (line[i], quotes) && !isspace (line[i])) { + ++i; + } + } + // check quotes + if (line[i] && NOT_TOO_LONG (i, start) && (quotes[0] || quotes[1])) { + last_word = i; + ++i; + while (line[i] && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { + ++i; + } + ++i; + } + // print line + if (!NOT_TOO_LONG (i, start)) { + if (last_word == -1) { + last_word = i; + } + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + start = last_word; + last_word = -1; + bzero (dst, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } else { + last_word = i; + } + } + // print last line + if (start < i) { + strncpy (dst + margin_b, line + start, i - start); + dst[margin_b + i - start] = 0; + print_fixed_line (line_num, pch, dst); + } +} + +#undef NOT_TOO_LONG + +static void +print_fixed_line_mode (const int line_num, char pch, char *line) +{ + int i = 0; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; + + if (strlen(line) <= max_chars_on_line) { + while (isspace (*(line + i))) { + i++; + } + print_fixed_line (line_num, pch, line); + } + else { + print_multiple_fixed_line (line_num, pch, line); + } +} + static void print_free_line (const int line_num, char pch, char *line) { @@ -6619,8 +6675,10 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) struct list_skip *skip; int do_print; int on_off; + char pch; do_print = cfile->listing_on; + if (line_has_listing_directive (line, cfile->source_format, &on_off)) { cfile->listing_on = on_off; /* always print the directive itself */ @@ -6638,7 +6696,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) } if (do_print) { - char pch = in_copy ? 'C' : ' '; + pch = in_copy ? 'C' : ' '; for (skip = cfile->skip_head; skip; skip = skip->next) { if (skip->skipline == line_num) { pch = 'X'; @@ -6648,7 +6706,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) (void)terminate_str_at_first_trailing_space (line); if (CB_SF_FIXED (cfile->source_format)) { - print_fixed_line (line_num, pch, line); + print_fixed_line_mode (line_num, pch, line); } else { print_free_line (line_num, pch, line); } @@ -6689,10 +6747,14 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], int in_string = 0; int last_col = cobc_get_text_column (); int last_nonspace; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; cmp_line[0] = 0; + bzero (cmp_line, CB_LINE_LENGTH + 2); /* Collapse pline into a string of tokens separated by spaces */ + last_nonspace = last_col; + i = 0; for (line_idx = first_idx; line_idx < last_idx; line_idx++) { if (!fixed) { last_col = strlen (pline[line_idx]) - 1; @@ -6703,16 +6765,24 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], isspace ((unsigned char)pline[line_idx][last_nonspace]) && last_nonspace > first_col; last_nonspace--); /* Go to first non-space character */ - for (i = first_col; (i <= last_nonspace) && isspace ((unsigned char)pline[line_idx][i]); i++); - - /* Copy chars between the first and last non-space characters */ + i = 0; while (i <= last_nonspace) { if (isspace ((unsigned char)pline[line_idx][i])) { RET_IF_OVERFLOW (cmp_line[out_pos++] = ' '); - for (i++; (i <= last_nonspace) && isspace ((unsigned char)pline[line_idx][i]); i++); - if (i > last_nonspace) { - break; - } + i++; + } else { + break ; + } + } + last_nonspace += first_col + 1; + if (fixed && last_nonspace > max_chars_on_line) { + last_nonspace = max_chars_on_line; + } + /* Copy chars between the first and last non-space characters */ + while (i < last_nonspace) { + if (isspace ((unsigned char)pline[line_idx][i])) { + RET_IF_OVERFLOW (cmp_line[out_pos++] = ' '); + i++; } else if (pline[line_idx][i] == '"') { /* Merge multi-part strings into one string, @@ -6726,14 +6796,14 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], in_string = 1; } - for (; (i <= last_nonspace) && (pline[line_idx][i] != '"'); ) { + for (; (i < last_nonspace) && (pline[line_idx][i] != '"'); ) { RET_IF_OVERFLOW (cmp_line[out_pos++] = pline[line_idx][i++]); } if (pline[line_idx][i] == '"') { RET_IF_OVERFLOW (cmp_line[out_pos++] = pline[line_idx][i++]); in_string = 0; } - if (i > last_nonspace) { + if (i > last_nonspace - 1) { break; } } else { @@ -6750,32 +6820,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], #undef RET_IF_OVERFLOW -/* - Add adjust to each line number less than line_num (if appropriate) in cfile's - copy, replace and error lists. -*/ -static void -adjust_line_numbers (struct list_files *cfile, int line_num, int adjust) -{ - struct list_files *cur; - struct list_replace *rep; - struct list_error *err; - - for (cur = cfile->copy_head; cur; cur = cur->next) { - cur->copy_line += adjust; - } - - for (rep = cfile->replace_head; rep; rep = rep->next) { - if (rep->firstline > line_num) { - rep->firstline += adjust; - } - } - - for (err = cfile->err_head; err; err = err->next) { - err->line += adjust; - } -} - static COB_INLINE COB_A_INLINE int is_debug_line (char *line, int fixed, int acudebug) { @@ -6802,32 +6846,6 @@ is_comment_line (char *line, int fixed) } } -static int -is_continuation_line (char *line, int fixed) -{ - int i; - - if (line == NULL || line[0] == 0) { - return 0; - } - if (fixed) { - /* check for "-" in indicator column */ - if (line [cobc_get_indicator ()] == '-') { - return 1; - } - } else { - /* check for "&" as last character */ - /* CHECKME: does this work with inline comments after "&"? */ - i = strlen (line) - 1; - while (i && isspace ((unsigned char)line[i])) i--; - if (line[i] == '&') { - return 1; - } - } - - return 0; -} - static void abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) { @@ -6838,526 +6856,329 @@ abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int l } } -static void -make_new_continuation_line (const char *cfile_name, char *pline[CB_READ_AHEAD], - int * const pline_cnt, int line_num) -{ - const int margin_a = cobc_get_margin_a (1); - const int indicator = cobc_get_indicator (); - const int sequence_col = cobc_get_text_column (); - abort_if_too_many_continuation_lines (*pline_cnt + 1, cfile_name, - line_num); - if (pline[*pline_cnt + 1] == NULL) { - pline[*pline_cnt + 1] = cobc_malloc (CB_LINE_LENGTH + 2); +/* + strncpy with skip multiple space for the listing mode + in_copy = margin_a for the margin + if is new string line replace don't skip the spaces +*/ +static int +strncpy_listing (char *dst, char *src, int n, int first, int in_copy, int is_new) +{ + int i = 0; + const int margin_a = cobc_get_margin_a (1); + int cnt_space = 0; + int j = 0; + + while (i < n && src[i]) { + cnt_space = 0; + while (i + cnt_space < n && src[i + cnt_space] && isspace (src[i + cnt_space])) + cnt_space++; + if (cnt_space > 0) { + if ((first && i == 0) || !src[i]) { + if (in_copy && i == 0) { + memset (dst + j, ' ', margin_a); + j += margin_a; + } else { + memset (dst + j, ' ', cnt_space); + j += cnt_space; + } + } else if (is_new) { + memset (dst + j, ' ', cnt_space); + j += cnt_space; + } else { + dst[j++] = ' '; + } + } + i += cnt_space; + while (i < n && src[i] && !isspace (src[i])) { + dst[j++] = src[i]; + i++; + } } - strcpy (pline[*pline_cnt + 1], pline[*pline_cnt]); - strcpy (pline[*pline_cnt], pline[*pline_cnt - 1]); - memset (&pline[*pline_cnt][margin_a], ' ', - sequence_col - margin_a); - pline[*pline_cnt][indicator] = '&'; - - (*pline_cnt)++; + dst[j] = 0; + return j; } +/* Replace line by the new value for the listing mode */ static void -add_token_over_multiple_lines (const char *cfile_name, - char *pline[CB_READ_AHEAD], - int * const pline_cnt, - const int line_num, - const char *new_token, - const int first_col, - int new_token_len, - int * const out_line, - int * const out_col) -{ - int tok_char = 0; - const int sequence_col = cobc_get_text_column (); - -#ifdef DEBUG_REPLACE - fprintf (stdout, " new_token_len = %d\n", new_token_len); -#endif - - while (new_token_len) { - /* Copy the token one character at a time. */ - pline[*out_line][(*out_col)++] = new_token[tok_char++]; - new_token_len--; - - /* - Move to the next line when reach the end of the current one. - */ - if (*out_col == sequence_col) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " NEW pline[%2d] = %s\n", - *out_line, pline[*out_line]); -#endif - - *out_col = first_col; - (*out_line)++; +replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_replace *lr, int pos, int fixed, int in_copy) +{ + char *dst; + int len_new_line; + int sz_old_line = 0; + int len_to; + int len_end_line; + int last_cpy = 0; + int first = 1; + t_line_file *bck_line = line_file; - /* - Allocate a new out_line if we are on the last - out_line. - */ - if (*out_line == *pline_cnt) { - make_new_continuation_line (cfile_name, pline, - pline_cnt, line_num); - } + // calculation the len char + len_to = strlen (lr->to); + while (line_file && line_file != data_replace.lastline_replace) + { + if (data_replace.firstline_replace == line_file) { + sz_old_line += pos; } + line_file = line_file->next; } + len_end_line = strlen (line_file->line + data_replace.last_char); + sz_old_line += len_end_line; + len_new_line = pos + len_to + len_end_line + 1; + dst = cobc_malloc (len_new_line); + line_file = bck_line; - pline[*out_line][(*out_col)++] = ' '; -} - -static void -reflow_replaced_fixed_format_text (const char *cfile_name, char *pline[CB_READ_AHEAD], - int * const pline_cnt, const int line_num, - char *newline, int first_col, const int last) -{ - int first_nonspace; - char *new_line_ptr; - char *new_token; - char token_terminator[2]; - int out_col; - int out_line; - int force_next_line; - int new_token_len; - const int margin_b = cobc_get_margin_b (1); - const int indicator = cobc_get_indicator (); - const int sequence_col = cobc_get_text_column (); - - new_token = cobc_malloc (strlen(newline) + 2); - new_line_ptr = get_next_token (newline, new_token, token_terminator); + // copy first line + if (pos > 0) { + last_cpy = strncpy_listing (dst, line_file->line, pos, first, in_copy, 0); + first = 0; + } + // copy new str + last_cpy += strncpy_listing (dst + last_cpy, lr->to, len_to, first, in_copy, 1); + first = 0; + while (line_file && line_file != data_replace.lastline_replace) { + line_file = line_file->next; + } + // copy end line + if (line_file && len_end_line > 0) { + strncpy_listing (dst + last_cpy, line_file->line + data_replace.last_char, len_end_line, first, in_copy, 0); + } - /* - Start adding tokens from margin B or the first non-space character. - */ - for (first_nonspace = first_col; - (first_nonspace < last) - && isspace ((unsigned char)(pline[0][first_nonspace])); - first_nonspace++); - if (first_nonspace >= margin_b) { - first_col = margin_b; - } - - /* For each line, */ - for (out_line = 0; out_line < *pline_cnt; out_line++) { - force_next_line = 0; - out_col = first_col; - - /* Add as many token as possible to the current line. */ - while (new_line_ptr && !force_next_line) { - new_token_len = strlen (new_token); - if (new_token_len >= (sequence_col - first_col)) { - /* - If the new token does not fit on this line, - reflow it onto the next line. - */ - add_token_over_multiple_lines (cfile_name, pline, pline_cnt, line_num, - new_token, first_col, new_token_len, - &out_line, &out_col); - } else if ((out_col + 2 + new_token_len) < last) { - /* - If the new token *and* its terminator fits, - copy it all onto the current line. - */ - strcpy (&pline[out_line][out_col], new_token); - out_col += strlen (new_token); + // stock result in the first line + line_file = bck_line; + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = dst; - if (token_terminator[0]) { - pline[out_line][out_col++] = token_terminator[0]; - } else { - pline[out_line][out_col++] = ' '; - } - if (token_terminator[0] == '.') { - pline[out_line][out_col++] = ' '; - } - } else { - force_next_line = 1; - make_new_continuation_line (cfile_name, pline, - pline_cnt, line_num); - continue; + // free other line if it's multi replace line + if (line_file != data_replace.lastline_replace) { + line_file = line_file->next; + do { + if (!is_comment_line (line_file->line, fixed)) + { + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line[0] = ' '; + line_file->line[1] = 0; + } + line_file = line_file->next; + } while (line_file && line_file != data_replace.lastline_replace); + if (line_file && line_file->next) { + if (!is_comment_line (line_file->line, fixed)) + { + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line[0] = ' '; + line_file->line[1] = 0; } - new_line_ptr = get_next_token (new_line_ptr, new_token, token_terminator); } - - if (out_col == first_col) { - pline[out_line][indicator] = ' '; - } - while (out_col < last) { - pline[out_line][out_col++] = ' '; - } - -#ifdef DEBUG_REPLACE - fprintf (stdout, " NEW pline[%2d] = %s\n", out_line, pline[out_line]); -#endif + line_file = bck_line; } - cobc_free (new_token); } -static void -reflow_replaced_free_format_text (char *pline[CB_READ_AHEAD], - const int pline_cnt, char *newline, - const int first_col) +static int +condition_leading (char *line, int start) { - char *new_line_ptr; - char *new_token; - char token_terminator[2]; - int i; - int j; - - new_token = cobc_malloc (strlen(newline) + 2); - new_line_ptr = get_next_token (newline, new_token, token_terminator); - - for (i = 0; i < pline_cnt; i++) { - /* - Terminate the line at null or the first non-space character. - */ - for (j = first_col; pline[i][j] == ' '; j++); - pline[i][j] = '\0'; - - /* - If the text has not been copied yet, copy it to the start of - the line. - */ - while (new_line_ptr) { - /* TO-DO: Replace with strncat? */ - strcat (pline[i], new_token); - strcat (pline[i], token_terminator); - j++; - new_line_ptr = get_next_token (new_line_ptr, new_token, - token_terminator); - } + if (start == 0 || isspace (line[start - 1])) + return 1; + return 0; +} - if (j == first_col) { - strcat (pline[i], " "); - } +static int +condition_trailing (char *line, int end) +{ + if (end == (int)strlen (line) - 1 || isspace (line[end])) { + return 1; } - cobc_free (new_token); + return 0; } static int -reflow_replaced_text (const char *cfile_name, char *pline[CB_READ_AHEAD], - int pline_cnt, int line_num, char *newline, int first_col, - int last_col, int fixed) +check_mode_trail_lead (t_data_replace data_replace, struct list_replace *lr, int start, int end) { - if (fixed) { - reflow_replaced_fixed_format_text (cfile_name, pline, - &pline_cnt, line_num, - newline, first_col, - last_col); - } else { - reflow_replaced_free_format_text (pline, pline_cnt, newline, - first_col); + if (lr->lead_trail == CB_REPLACE_TRAILING) { + return condition_trailing (data_replace.lastline_replace->line, end); } - - return pline_cnt; + return condition_leading (data_replace.firstline_replace->line, start); } -/* TODO: Modularise! */ - static int -print_replace_text (struct list_files *cfile, FILE *fd, - struct list_replace *rep, char *pline[CB_READ_AHEAD], - int pline_cnt, int line_num) -{ - char *rfp = rep->from; - char *from_ptr; - char *to_ptr; - char *newline; - const int fixed = CB_SF_FIXED (cfile->source_format); - const int acudebug = (cfile->source_format == CB_FORMAT_ACUTERM); - int first_col = fixed ? cobc_get_margin_a (1) : 0; - int last; - int multi_token; - int match = 0; - int eof = 0; - int submatch = 0; - int seccount = 0; - int overread = 0; - int tokmatch = 0; - int subword = 0; - int strictmatch = 0; - size_t ttix, ttlen, from_token_len; - size_t newlinelen; - char lterm[2]; - char fterm[2]; - char ftoken[CB_LINE_LENGTH + 2]; - char tterm[2]; - char ttoken[CB_LINE_LENGTH + 2]; - char cmp_line[CB_LINE_LENGTH + 2]; - char from_line[CB_LINE_LENGTH + 2] = { 0 }; - - if (is_comment_line (pline[0], fixed)) { - return pline_cnt; +compare_char (char a, char b, int is_simple_quote) +{ + if (!is_simple_quote) { + return a == b; } + return tolower (a) == tolower (b); +} - /* Trim the string to search and replace */ - (void)terminate_str_at_first_trailing_space (rfp); - while (*rfp && isspace ((unsigned char)(*rfp))) { - rfp++; - } - multi_token = (strchr (rfp, ' ') != NULL); +static t_data_replace +init_data_replace(void) +{ + t_data_replace new_data_replace; -#ifdef DEBUG_REPLACE - fprintf (stdout, "print_replace_text: line_num = %d", line_num); - fprintf (stdout, ", multi_token = %s, fixed = %s\n", - multi_token ? "TRUE" : "FALSE", fixed ? "TRUE" : "FALSE"); - fprintf (stdout, " pline_cnt = %d\n", pline_cnt); - for (int i = 0; i < pline_cnt; i++) { - fprintf (stdout, " pline[%2d]: %s\n", i, pline[i]); - } - fprintf (stdout, - " rep: first = %d, last = %d, lead_trail = %d, strict = %d\n", - rep->firstline, rep->lastline, rep->lead_trail, - rep->strict_partial); - fprintf (stdout, " fromlen: %lu\n", strlen(rfp)); - fprintf (stdout, " from: '%80.80s'\n", rfp); - fprintf (stdout, " tolen: %lu\n", strlen(rep->to)); - fprintf (stdout, " to: '%80.80s'\n", rep->to); -#endif - - newlinelen = CB_LINE_LENGTH+2; - newline = cobc_malloc (newlinelen); - - last = compare_prepare (cmp_line, pline, 0, pline_cnt, first_col, fixed); - - newline[0] = 0; - if (multi_token) { - /* - Attempt to match the source text from the beginning of each - line (continuing the match to the next line if need be). If a - match is found, output the line to newline with the match - replaced. - */ + new_data_replace.last_char = -1; + new_data_replace.firstline_replace = NULL; + new_data_replace.lastline_replace = NULL; + return new_data_replace; +} - strcpy (from_line, rfp); - from_ptr = get_next_token (from_line, ftoken, fterm); - force_next_line: - to_ptr = get_next_token (cmp_line, ttoken, tterm); +static t_data_replace +search_strstr (t_line_file *line_file, int line, struct list_replace *lr, + int start, int fixed) +{ + const int is_simple_quote = lr->from[0] == '\''; + t_line_file *line_start = line_file; + t_data_replace data_replace = init_data_replace(); + int i = start; + int j = 0; - /* - Read tokens until the match is complete or until a match - fails. - */ - while (to_ptr && from_ptr) { - if (!strcasecmp (ttoken, ftoken)) { - /* - Mark two tokens as matched, then read next - pair. - */ - submatch = 1; - if (fterm[0] == tterm[0]) { - lterm[0] = 0; - } else { - lterm[0] = tterm[0]; + while (lr->from[j] && isspace (lr->from[j])) { + ++j; + } + while (line_file && line_file->line && line_file->line[i]) { + if (is_comment_line (line_file->line, fixed)) { + ++line; + line_file = line_file->next; + i = 0; + continue ; + } + while (line_file->line[i] && lr->from[j] \ + && ((isspace (line_file->line[i]) || isspace (lr->from[j])) \ + || compare_char (line_file->line[i], lr->from[j], is_simple_quote))) { + if (isspace (line_file->line[i]) || isspace (lr->from[j])) { + while (line_file->line[i] && isspace (line_file->line[i])) { + ++i; } - lterm[1] = tterm[1]; - to_ptr = get_next_token (to_ptr, ttoken, tterm); - from_ptr = get_next_token (from_ptr, ftoken, fterm); - } else { - /* Discard partial match. */ - if (seccount == 0) { - if ((strlen (newline) + strlen (ttoken) + strlen (tterm)) >= newlinelen) { - newlinelen += strlen (ttoken) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, ttoken); - strcat (newline, tterm); + while (lr->from[j] && isspace (lr->from[j])) { + ++j; } - submatch = 0; - - /* Start matching from beginning of from_line again. */ - strcpy (from_line, rfp); - from_ptr = get_next_token (from_line, ftoken, fterm); - to_ptr = get_next_token (to_ptr, ttoken, tterm); - break; + } else { + ++i; + ++j; } } - if (!from_ptr && submatch) { - /* - If the match is complete, output the match's - replacement. - */ - match = 1; - if ((strlen (newline) + strlen (rep->to) + strlen (lterm)) >= newlinelen) { - newlinelen += strlen (rep->to) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, rep->to); - strcat (newline, lterm); - if (to_ptr) { - if ((strlen (newline) + strlen (ttoken) + strlen (to_ptr)) >= newlinelen) { - newlinelen += strlen (ttoken) + strlen (to_ptr) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, ttoken); - strcat (newline, tterm); - strcat (newline, to_ptr); - } - } else if (!to_ptr && submatch) { - /* - If we run out of chars from the original source, get - more. - */ - -#ifdef DEBUG_REPLACE - fprintf (stdout, " submatch = TRUE\n"); -#endif - if (eof) { - cobc_free (newline); - return pline_cnt; - } - - /* - Overwrite the current line if it is a comment or debug - line. - */ - if (is_comment_line (pline[pline_cnt], fixed)) { - adjust_line_numbers (cfile, line_num, -1); - overread = 1; + if (!line_file->line[i] && j > 0) { + while (lr->from[j] && isspace (lr->from[j])) { + ++j; } - if (is_debug_line (pline[pline_cnt], fixed, acudebug)) { - adjust_line_numbers (cfile, line_num, -1); - overread = 1; - } - - /* - Read lines until we find a non-comment, non-debug - line. - */ - next_rec: - if (!is_comment_line (pline[pline_cnt], fixed)) { - pline_cnt++; - } - abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); - if (get_next_listing_line (fd, &pline[pline_cnt], fixed) < 0) { - pline[pline_cnt][0] = 0; - eof = 1; - } - if (is_debug_line (pline[pline_cnt], fixed, acudebug) - || is_comment_line (pline[pline_cnt], fixed)) { - adjust_line_numbers (cfile, line_num, -1); - goto next_rec; - } -#ifdef DEBUG_REPLACE - fprintf (stdout, " pline[%2d]: %s\n", pline_cnt - 1, - pline[pline_cnt - 1]); -#endif - line_num++; - seccount++; - if (overread) { - overread = 0; - goto next_rec; - } - last = compare_prepare (cmp_line, pline, pline_cnt - 1, pline_cnt, - first_col, fixed); - strcat (newline, " "); - goto force_next_line; } - } else { - strcpy (from_line, rfp); -#if 0 - from_ptr = get_next_token (from_line, ftoken, fterm); -#else - (void) get_next_token (from_line, ftoken, fterm); -#endif - if (ftoken[0] == ':' || ftoken[0] == '(') { - subword = 1; - } - from_token_len = strlen (ftoken); - - /* - For each token in cmp_line, try to match it with the token in - from_line. - */ - for (to_ptr = get_next_token (cmp_line, ttoken, tterm); to_ptr; - to_ptr = get_next_token (to_ptr, ttoken, tterm)) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " tterm = '%s', ttoken = '%s', ftoken = '%s'\n", - tterm, ttoken, ftoken); -#endif - ttlen = strlen (ttoken); - ttix = 0; - if (rep->lead_trail == CB_REPLACE_LEADING) { - subword = 1; - strictmatch = rep->strict_partial; - } else if (rep->lead_trail == CB_REPLACE_TRAILING) { - if (ttlen >= from_token_len) { - subword = 1; - strictmatch = rep->strict_partial; - ttix = ttlen - from_token_len; - ttlen = ttix; - } + if (j > 0 && !lr->from[j]) { + data_replace.firstline_replace = line_start; + data_replace.lastline_replace = line_file; + if (!check_mode_trail_lead (data_replace, lr, start, i)) { + break ; } - if (subword) { - /* When strictmatch, length of word must be - strictly greater than matched token: */ - tokmatch = (!strictmatch || ttlen > from_token_len) - && !strncasecmp (&ttoken[ttix], ftoken, from_token_len); - } else { - tokmatch = !strcasecmp (ttoken, ftoken); - } - if (tokmatch) { - if ((strlen (newline) + strlen (ttoken) + strlen (rep->to)) >= newlinelen) { - newlinelen += strlen (ttoken) + strlen (rep->to) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - if (subword) { - if (rep->lead_trail == CB_REPLACE_LEADING) { - strcat (newline, rep->to); - strcat (newline, &ttoken[from_token_len]); - } else if (rep->lead_trail == CB_REPLACE_TRAILING) { - strncat (newline, ttoken, ttlen); - strcat (newline, rep->to); - } else { - strcat (newline, rep->to); - } - } else { - strcat (newline, rep->to); - } - match = 1; - } else { - if ((strlen (newline) + strlen (ttoken) + strlen (tterm)) >= newlinelen) { - newlinelen += strlen (ttoken) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); + if (lr->from[0] == ':' || lr->from[0] == '(') { + while (line_file->line[i] && !isspace (line_file->line[i])) { + ++i; } - strcat (newline, ttoken); } - strcat (newline, tterm); - } - } + data_replace.last_char = i; - if (match) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " match = TRUE\n newline = %s\n", newline); -#endif - pline_cnt = reflow_replaced_text (cfile->name, pline, pline_cnt, - line_num, newline, first_col, - last, fixed); + return data_replace; + } + if (!line_file->line[i] && j > 0) { + line_file = line_file->next; + i = 0; + } else if (line_file->line[i] && line_file->line[i] != lr->from[j]) { + break ; + } } - - cobc_free (newline); - return pline_cnt; + // no match + return data_replace; } -static void -remove_replace_entries_before_line (struct list_files *cfile, const int line_num) +/* return new line_num */ +static int +search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, int pline_cnt, int line_num, \ + int fixed, int in_copy) { + int j; + int i; + int tmp_i; + int tmp_j; + int match; + int lastline_line_num; + int quotes[2] = {0, 0}; struct list_replace *rep; - - while (cfile->replace_head - && cfile->replace_head->firstline < line_num) { + t_data_replace data_replace; + + j = 0; + i = line_num; + lastline_line_num = line_num; + + int deb_line = -1; + // loop char + while (line_file->line && line_file->line[j]) { + deb_line++; + // skip the spaces in the start file + while (line_file->line[j] && isspace (line_file->line[j])) { + j++; + } + if (!line_file->line[j]) { + break ; + } + // loop list replace rep = cfile->replace_head; - cfile->replace_head = rep->next; + match = 0; + is_quotes_char (line_file->line[j], quotes); + while (rep && line_file->line[j]) { + if ((!quotes[0] && !quotes[1]) || rep->from[0] == '\'' || rep->from[0] == '"') { + data_replace = search_strstr (line_file, i, rep, j, fixed); + // Match + if (data_replace.last_char != -1) + { + // count quotes all lines except the last line + tmp_j = j; + tmp_i = i; + t_line_file *bck_line = line_file; + while (line_file && line_file != data_replace.lastline_replace) { + while (line_file->line[++j]) { + is_quotes_char (line_file->line[j], quotes); + } + ++i; + line_file = line_file->next; + j = -1; + } + lastline_line_num = i; + // and count quotes in the last line + while (++j <= data_replace.last_char) { + is_quotes_char (line_file->line[j], quotes); + } + j = tmp_j; - if (rep->from) { - cobc_free (rep->from); + if (rep->strict_partial) { + ++j; + while (line_file->line[j] && !isspace (line_file->line[j])) { + ++j; + } + if (j - 1 == tmp_j) { + rep = rep->next; + continue; + } + j = tmp_j; + } + i = tmp_i; + line_file = bck_line; + // stock first line in tmp and clean other line in the multiple line replace + replace_value (line_file, data_replace, rep, j, fixed, in_copy); + + line_file = data_replace.firstline_replace; + j = data_replace.last_char; + while(line_file->line[j] && !isspace (line_file->line[j])) { + ++j; + } + match = 1; + } + } + rep = rep->next; } - if (rep->to) { - cobc_free (rep->to); + if (!match) { + j++; } - cobc_free (rep); } + return lastline_line_num - line_num + 1; } static void @@ -7393,6 +7214,43 @@ cleanup_copybook_reference (struct list_files *cur) cobc_free (cur); } +static +char *get_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (isspace (str[i])) { + ++i; + } + if (str + i) { + return str + i; + } + return NULL; +} + +static +char *get_next_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (!isspace (str[i])) { + ++i; + } + while (isspace (str[i])) { + ++i; + } + if (str + i) { + return str + i; + } + return NULL; +} + /* TO-DO: Modularise! */ /* @@ -7401,48 +7259,31 @@ cleanup_copybook_reference (struct list_files *cur) */ static int print_replace_main (struct list_files *cfile, FILE *fd, - char *pline[CB_READ_AHEAD], int pline_cnt, int line_num) + t_line_file *line_file, int pline_cnt, int line_num) { - static int active_replace_stmt = 0; - char *to_ptr; + char *ptr; + int is_copy_line; + int is_replace_line; + int is_replace_off = 0; struct list_replace *rep; - struct list_files *cur; - int i; - const int fixed = CB_SF_FIXED (cfile->source_format); - const int first_col = fixed ? cobc_get_margin_a (1) : 0; - int is_copy_line; - int is_replace_line; - int is_replace_off = 0; - char tterm[2] = { '\0' }; - char ttoken[CB_LINE_LENGTH + 2] = { '\0' }; - char cmp_line[CB_LINE_LENGTH + 2] = { '\0' }; - - if (is_comment_line (pline[0], ! CB_SF_FREE (cfile->source_format))) { + static int active_replace_stmt = 0; + const int fixed = (cfile->source_format == CB_FORMAT_FIXED); + + if (is_comment_line (line_file->line, cfile->source_format != CB_FORMAT_FREE)) { return pline_cnt; } -#ifdef DEBUG_REPLACE - fprintf (stdout, "print_replace_main: line_num = %d\n", line_num); - fprintf (stdout, " pline_cnt = %d\n", pline_cnt); - for (i = 0; i < pline_cnt; i++) { - fprintf (stdout, " pline[%2d]: %s\n", i, pline[i]); + rep = cfile->replace_head; + if (!rep) { + return pline_cnt; } -#endif - - compare_prepare (cmp_line, pline, 0, pline_cnt, first_col, - ! CB_SF_FREE (cfile->source_format)); - /* Check whether we're given a COPY or REPLACE statement. */ - to_ptr = get_next_token (cmp_line, ttoken, tterm); - 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 = !cb_strcasecmp (ttoken, "OFF"); + ptr = get_word (line_file->line); + is_copy_line = !strncmp (ptr, "COPY", strlen("COPY")); + is_replace_line = !strncmp (ptr, "REPLACE", strlen("REPLACE")); + if (is_replace_line && ptr) { + ptr = get_next_word (ptr); + is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); } /* @@ -7467,14 +7308,9 @@ print_replace_main (struct list_files *cfile, FILE *fd, } else if (active_replace_stmt) { if (is_replace_line && is_replace_off) { active_replace_stmt = 0; - remove_replace_entries_before_line (cfile, line_num); } else if (is_copy_line) { if (cfile->copy_head) { - /* List all lines read so far and then discard them. */ - for (i = 0; i < pline_cnt; i++) { - print_line (cfile, pline[i], line_num + i, 0); - pline[i][0] = 0; - } + struct list_files *cur; cur = cfile->copy_head; @@ -7486,26 +7322,93 @@ print_replace_main (struct list_files *cfile, FILE *fd, deep_copy_list_replace (rep, cur); } } - print_program (cur, 1); - - /* Delete the copybook reference when done */ - cfile->copy_head = cur->next; - cleanup_copybook_reference (cur); } } else { - /* Print text with replacements */ - for (rep = cfile->replace_head; - rep && rep->firstline < line_num; - rep = rep->next) { - pline_cnt = print_replace_text (cfile, fd, rep, pline, - pline_cnt, line_num); + while (rep) { + if (line_num >= rep->firstline - 1 && line_num <= rep->lastline - 1) { + return pline_cnt; + } + rep = rep->next; } + pline_cnt = search_and_apply_replacement (cfile, line_file, pline_cnt, line_num, fixed, 0); } } - return pline_cnt; } + +static int +print_program_code_apply (struct list_files *cfile, int fixed, int in_copy, + int *pline_cnt, int *i, int *line_num, int lines_read, t_line_file *line_file, \ + int *line_replace, FILE *fd + ) +{ + struct list_replace *rep; + + *pline_cnt = 1; + + if (!line_file->line) { + return lines_read; + } + + /* handling for preprocessed directives */ + if (line_file->line[0] == '#') { + /* Set line number as specified by #line directive. */ + if (!strncmp (line_file->line, "#line ", 6)) { + *line_num = atoi (&line_file->line[6]); + /* CHECKME: read the filename if given, too */ + } + lines_read = -1; + return -1; + } + /* Perform text replacement on the lines. */ + if (!in_copy) { + *pline_cnt = print_replace_main (cfile, fd, line_file, *pline_cnt, + *i); + } else if (cfile->replace_head) { + *pline_cnt = search_and_apply_replacement (cfile, line_file, *pline_cnt, *i, fixed, in_copy); + } + + /* Print each line except the last. */ + for (int idx = *i; idx < *i + (*pline_cnt) && line_file; idx++) { + if (line_file->line) { + print_line (cfile, line_file->line, *line_num, in_copy); + lines_read++; + } + line_file = line_file->next; + } + + /* Output copybooks which are COPY'd at the current line */ + if (cfile->copy_head + && cfile->copy_head->copy_line == *line_num) { + struct list_files *cur = cfile->copy_head; + /* Add the current text replacements to the copybook */ + for (rep = cfile->replace_head; rep && in_copy; + rep = rep->next) { + deep_copy_list_replace (rep, cur); + } + print_program (cur, 1); + /* Delete the copybook reference when done */ + cfile->copy_head = cur->next; + cleanup_copybook_reference (cur); + } + return lines_read; +} + +static t_line_file +*add_new_line(t_line_file *last, char *str) +{ + if (!last) { + last = cobc_malloc (sizeof (t_line_file)); + } else { + last->next = cobc_malloc (sizeof (t_line_file)); + last = last->next; + } + last->line = strdup (str); + last->next = NULL; + return last; +} + /* Print the listing for the file in cfile, with copybooks expanded and after text has been REPLACE'd. @@ -7517,58 +7420,21 @@ static void print_program_code (struct list_files *cfile, int in_copy) { FILE *fd = NULL; - struct list_replace *rep; - struct list_files *cur; struct list_error *err; int i; int line_num = 1; + int line_replace = 0; const int fixed = CB_SF_FIXED (cfile->source_format); - const int indicator = cobc_get_indicator (); int eof = 0; int pline_cnt = 0; char *pline[CB_READ_AHEAD] = { NULL }; int lines_read; + t_line_file *line_file = NULL; + t_line_file *head_line_file = NULL; + int cnt_line = -1; cfile->listing_on = 1; -#ifdef DEBUG_REPLACE - struct list_skip *skip; - - fprintf (stdout, "print_program_code: in_copy = %s\n", - in_copy ? "YES" : "NO"); - fprintf (stdout, " name: %s\n", cfile->name); - fprintf (stdout, " copy_line: %d\n", cfile->copy_line); - for (i = 0, cur = cfile->copy_head; cur; i++, cur = cur->next) { - if (i == 0) { - fprintf (stdout, " copy_books: \n"); - } - fprintf (stdout, " name[%d]: %s\n", i, cur->name); - fprintf (stdout, " line[%d]: %d\n", i, cur->copy_line); - } - for (i = 0, rep = cfile->replace_head; rep; i++, rep = rep->next) { - if (i == 0) { - fprintf (stdout, " replace_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, rep->firstline); - fprintf (stdout, " from[%d]:%lu: '%80.80s'\n", i, strlen(rep->from), rep->from); - fprintf (stdout, " to [%d]:%lu: '%80.80s'\n", i, strlen(rep->to), rep->to); - } - for (i = 0, err = cfile->err_head; err; i++, err = err->next) { - if (i == 0) { - fprintf (stdout, " error_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, err->line); - fprintf (stdout, " pref[%d]: '%s'\n", i, err->prefix); - fprintf (stdout, " msg [%d]: '%s'\n", i, err->msg); - } - for (i = 0, skip = cfile->skip_head; skip; i++, skip = skip->next) { - if (i == 0) { - fprintf (stdout, " skip_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, skip->skipline); - } -#endif - if (cfile->name) { fd = fopen (cfile->name, "r"); } @@ -7580,79 +7446,79 @@ print_program_code (struct list_files *cfile, int in_copy) if (get_next_listing_line (fd, &pline[pline_cnt + 1], fixed) < 0) { eof = 1; } - pline_cnt++; - lines_read = 0; - - /* Collect all adjacent continuation lines */ - if (is_continuation_line (pline[fixed ? pline_cnt : pline_cnt - 1], - ! CB_SF_FREE (cfile->source_format))) { - continue; - } - /* handling for preprocessed directives */ - if (pline[0][0] == '#') { - /* Set line number as specified by #line directive. */ - if (!strncmp (pline[0], "#line ", 6)) { - line_num = atoi (&pline[0][6]); - /* CHECKME: read the filename if given, too */ - } - lines_read = -1; - } - - /* Perform text replacement on the lines. */ - if (!in_copy) { - pline_cnt = print_replace_main (cfile, fd, pline, pline_cnt, - line_num); - } else if (cfile->replace_head) { - rep = cfile->replace_head; - while (rep) { - pline_cnt = print_replace_text (cfile, fd, rep, pline, - pline_cnt, line_num); - rep = rep->next; - } - } - - /* Print each line except the last. */ - for (i = 0; i < pline_cnt; i++) { - if (pline[i][0]) { - if (fixed && pline[i][indicator] == '&') { - print_line (cfile, pline[i], line_num, in_copy); - } else { - print_line (cfile, pline[i], line_num + i, in_copy); - lines_read++; - } - } - } - - /* Output copybooks which are COPY'd at the current line */ - if (cfile->copy_head - && cfile->copy_head->copy_line == line_num) { - - cur = cfile->copy_head; - - /* Add the current text replacements to the copybook */ - for (rep = cfile->replace_head; rep && in_copy; - rep = rep->next) { - deep_copy_list_replace (rep, cur); - } - print_program (cur, 1); - - /* Delete the copybook reference when done */ - cfile->copy_head = cur->next; - cleanup_copybook_reference (cur); + ++pline_cnt; + char cmp_line[CB_LINE_LENGTH + 2]; + int first_col = fixed ? cobc_get_margin_a (1) : 0; + compare_prepare (cmp_line, pline, 0, 1, first_col, fixed); + line_file = add_new_line(line_file, cmp_line); + if (!head_line_file) { + head_line_file = line_file; } + ++line_replace; + ++cnt_line; /* Delete all but the last line. */ strcpy (pline[0], pline[pline_cnt]); for (i = 1; i < pline_cnt + 1; i++) { + // abort_if_too_many_continuation_lines (i, cfile->name, line_num); ajouter par moi le 02/11 ne fonctionne pas memset (pline[i], 0, CB_LINE_LENGTH); } - line_num += lines_read; pline_cnt = 0; if (pline[0][0] == 0) { eof = 1; } } while (!eof); + + line_num = 1; + i = 0; + pline_cnt = 0; + line_file = head_line_file; + + char space[2] = {' ', 0}; + // search replacement and print + while (i < line_replace) { + pline_cnt++; + lines_read = 0; + // if line is empty, just print + if (!line_file->line || strcmp (line_file->line, "") == 0) { + print_line (cfile, space, line_num, in_copy); + line_file = line_file->next; + i++; + line_num++; + continue ; + } + + // search replacement + lines_read = print_program_code_apply (cfile, fixed, in_copy, &pline_cnt, \ + &i, &line_num, lines_read, line_file, &line_replace, fd); + + if (lines_read > 0) { + // if edit is current don't print + line_num += lines_read; + i += lines_read; + while (line_file && lines_read > 0) { + line_file = line_file->next; + lines_read--; + } + } else { + print_line (cfile, line_file->line, line_num, in_copy); + line_file = line_file->next; + i++; + } + pline_cnt = 0; + } + + line_file = head_line_file; + // free pline_replace + t_line_file *next; + while (line_file) { + cobc_free (line_file->line); + line_file->line = NULL; + next = line_file->next; + cobc_free(line_file); + line_file = next; + } } fclose (fd); diff --git a/cobc/codegen.c b/cobc/codegen.c index 5a0edec92..5f7989562 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -9681,6 +9681,21 @@ output_report_control (struct cb_report *p, int id, cb_tree ctl, cb_tree nx) if(nx) { output_report_control(p, id, nx, CB_CHAIN(nx)); } + bfound = 0; + for(i= p->num_lines-1; i >= 0; i--) { + if(p->line_ids[i]->report_control) { + struct cb_field *c = cb_code_field (p->line_ids[i]->report_control); + if(c == s) { + bfound = 1; + break; + } + } + } + if (!bfound) { + ctl = NULL; + p->controls = NULL; + return ; + } output_local("/* Report %s: CONTROL %s */\n",p->name,s->name); prvid = 0; for(i = 0; i < p->num_lines; i++) { diff --git a/cobc/tree.h b/cobc/tree.h index c0645b3f8..7ecb5b501 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -1651,6 +1651,17 @@ struct list_error { char *msg; /* Error Message text */ }; +typedef struct s_line_file { + char *line; + struct s_line_file *next; +} t_line_file; + +typedef struct s_data_replace { + t_line_file *firstline_replace; + t_line_file *lastline_replace; + int last_char; +} t_data_replace; + /* List of REPLACE text blocks */ struct list_replace { struct list_replace *next; diff --git a/tests/ChangeLog b/tests/ChangeLog index 6b6332498..7e904e5d1 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,11 @@ +2023-03-07 Samuel Belondrade + + * testsuite.src/run_reportwriter.at: add test if the variable exist + for report section (bug: #863) + * testsuite.src/listing.at: add test for the copy replacing in + listing mode (bug: #831) + 2023-02-21 Fabrice Le Fessant * testsuite.src/syn_literals.at: move syntax checks on literals diff --git a/tests/testsuite.src/listings.at b/tests/testsuite.src/listings.at index f6befbaa4..012b007c5 100644 --- a/tests/testsuite.src/listings.at +++ b/tests/testsuite.src/listings.at @@ -294,7 +294,31 @@ AT_CLEANUP AT_SETUP([COPY replacement with partial match]) AT_KEYWORDS([listing copy]) -AT_XFAIL_IF([true]) + +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy.inc" REPLACING ==TEST-VAR== BY ==TEST-AVR== +000008 == 02 TEST-EE == BY == 02 TEST-FF ==. +000001C +000002C 02 TEST-AVR PIC X(2) VALUE "OK". +000003C 02 TEST-CC PIC X(4) VALUE "OK 2". +000009 PROCEDURE DIVISION. +000010 DISPLAY TEST-AVR. +000011 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". @@ -323,7 +347,42 @@ AT_CLEANUP AT_SETUP([COPY replacement with multiple partial matches]) AT_KEYWORDS([listing copy]) -AT_XFAIL_IF([true]) + +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy.inc" REPLACING +000008 LEADING ==TEST-VAR== BY ==TEST-AVR== +000009 == 02 TEST-OK == BY == 02 TEST-KO == +000010 ==TEST-CC== BY ==TEST-DD== +000011 == 02 TEST-EE == BY == 02 TEST-FF == +000012 == PIC == BY == pic ==. +000001C +000002C 02 TEST-AVR pic X(2) VALUE "OK". +000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". +000004C 02 TEST-DD pic X(4) VALUE "OK 2". +000005C 02 TEST-KO pic X(4) VALUE "OK 3". +000006C 02 TEST-FF pic X(4) VALUE "OK 4". +000013 PROCEDURE DIVISION. +000014 DISPLAY TEST-AVR. +000015 DISPLAY TEST-AVR-BIS. +000016 DISPLAY TEST-KO. +000017 DISPLAY TEST-DD. +000018 DISPLAY TEST-FF. +000019 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". @@ -388,6 +447,42 @@ AT_DATA([prog2.cob], [ STOP RUN. ]) +AT_DATA([expected2.lst], +[GnuCOBOL V.R.P prog2.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog2. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy2.inc" +000008 REPLACING LEADING ==TEST-VAR== BY ==TEST-AVR== +000009 == 02 TEST-OK == BY == 02 TEST-KO == +000010 == TEST-CC == BY == TEST-DD == +000011 == 02 TEST-EE == BY == 02 TEST-FF == +000012 == PIC == BY == pic ==. +000001C +000002C 02 TEST-AVR pic X(2) VALUE "OK". +000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". +000004C 02 TEST-DD pic X(4) VALUE "OK 2". +000005C 02 TEST-KO pic X(4) VALUE "OK 3". +000006C 02 TEST-FF pic X(4) VALUE "OK 4". +000013 PROCEDURE DIVISION. +000014 DISPLAY TEST-AVR. +000015 DISPLAY TEST-AVR-BIS. +000016 DISPLAY TEST-KO. +000017 DISPLAY TEST-DD. +000018 DISPLAY TEST-FF. +000019 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + AT_CHECK([$COMPILE_ONLY -t prog2.lst -tlines=0 prog2.cob], [0], [], []) AT_CHECK([$UNIFY_LISTING prog2.lst prog2.lis once], [0], [], []) AT_CHECK([diff expected2.lst prog2.lis], [0], [], []) @@ -422,6 +517,42 @@ AT_DATA([prog3.cob], [ STOP RUN. ]) +AT_DATA([expected3.lst], +[GnuCOBOL V.R.P prog3.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog3. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy3.inc" +000008 REPLACING LEADING ==TEST-VAR== BY ==TEST-AVR== +000009 == 02 TEST-OK == BY == 02 TEST-KO == +000010 ==TEST-CC== BY ==TEST-DD== +000011 == 02 TEST-EE == BY == 02 TEST-FF == +000012 == PIC == BY == pic ==. +000001C +000002C 02 TEST-AVR PIC X(2) VALUE "OK". +000003C 02 TEST-AVR-BIS PIC X(6) VALUE "OK BIS". +000004C 02 TEST-DD pic X(4) VALUE "OK 2". +000005C 02 TEST-KO pic X(4) VALUE "OK 3". +000006C 02 TEST-FF pic X(4) VALUE "OK 4". +000013 PROCEDURE DIVISION. +000014 DISPLAY TEST-AVR. +000015 DISPLAY TEST-AVR-BIS. +000016 DISPLAY TEST-KO. +000017 DISPLAY TEST-DD. +000018 DISPLAY TEST-FF. +000019 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + AT_CHECK([$COMPILE_ONLY -t prog3.lst -tlines=0 prog3.cob], [0], [], []) AT_CHECK([$UNIFY_LISTING prog3.lst prog3.lis once], [0], [], []) AT_CHECK([diff expected3.lst prog3.lis], [0], [], []) @@ -429,6 +560,81 @@ AT_CHECK([diff expected3.lst prog3.lis], [0], [], []) AT_CLEANUP +AT_SETUP([Multiple replacement]) +AT_KEYWORDS([listing symbols]) + +AT_DATA([copy.inc], [ + 01 A1000B-AA. + 03 A1000B2-BB PIC X(5). + 03 A1000B2-CC PIC X(5). + 03 A1000B2-DD PIC X(5). + 03 A1000B2-EE PIC X(5). + 03 A1000B2-FF PIC X(5). + 03 A1000B2-GG PIC X(5). +]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLO-WORLD. + DATA DIVISION. + WORKING-STORAGE SECTION. + COPY "copy.inc" REPLACING LEADING ==A1000B== BY ==B2000B== + == 03 A1000B2-CC PIC X(5). + 03 A1000B2-DD PIC X(5). + 03 A1000B2-EE PIC X(5). == + BY == 03 B2000B2-CC1 PIC X(5). + 03 B2000B2-DD1 PIC X(5). + 03 B2000B2-EE PIC X(5). + 03 B2000B2-TEST PIC 9(1). + 03 B2000B2-TEST2 PIC X(1). ==. + PROCEDURE DIVISION. + DISPLAY 'Hello, world'. + STOP RUN. +]) + +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. HELLO-WORLD. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 COPY "copy.inc" REPLACING LEADING ==A1000B== BY ==B2000B== +000007 == 03 A1000B2-CC PIC X(5). +000008 03 A1000B2-DD PIC X(5). +000009 03 A1000B2-EE PIC X(5). == +000010 BY == 03 B2000B2-CC1 PIC X(5). +000011 03 B2000B2-DD1 PIC X(5). +000012 03 B2000B2-EE PIC X(5). +000013 03 B2000B2-TEST PIC 9(1). +000014 03 B2000B2-TEST2 PIC X(1). ==. +000001C +000002C 01 B2000B-AA. +000003C 03 B2000B2-BB PIC X(5). +000004C 03 B2000B2-CC1 PIC X(5). 03 B2000B2-DD1 PIC X(5). 03 +000004+ - B2000B2-EE PIC X(5). 03 B2000B2-TEST PIC 9(1). 03 +000004+ - B2000B2-TEST2 PIC X(1). +000004C +000004C +000007C 03 B2000B2-FF PIC X(5). +000008C 03 B2000B2-GG PIC X(5). +000015 PROCEDURE DIVISION. +000016 DISPLAY 'Hello, world'. +000017 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + +AT_CHECK([$COMPILE_ONLY -t prog.lst -tlines=0 prog.cob], [0], [], []) +AT_CHECK([$UNIFY_LISTING prog.lst prog.lis once], [0], [], []) +AT_CHECK([diff expected.lst prog.lis], [0], [], []) + +AT_CLEANUP AT_SETUP([COPY replacement order]) AT_KEYWORDS([listing symbols]) diff --git a/tests/testsuite.src/run_reportwriter.at b/tests/testsuite.src/run_reportwriter.at index 2ff781a44..707220749 100644 --- a/tests/testsuite.src/run_reportwriter.at +++ b/tests/testsuite.src/run_reportwriter.at @@ -9626,3 +9626,48 @@ BEFORE FINAL - SHOULD DISPLAY AT_CLEANUP +AT_SETUP([Check if the variable is referenced in the report]) +AT_KEYWORDS([report]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. MAIN. + ENVIRONMENT DIVISION. + CONFIGURATION SECTION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT A_1 ASSIGN TO EXTERNAL A_1. + SELECT A_2 ASSIGN TO EXTERNAL A_2. + DATA DIVISION. + FILE SECTION. + FD A_1. + COPY test. + FD A_2 REPORT ETAT. + WORKING-STORAGE SECTION. + REPORT SECTION. + RD ETAT + CONTROL FINAL ERROR-1 ERROR-2 + PAGE LIMIT 66. + PROCEDURE DIVISION. + STOP RUN. +]) + +AT_DATA([test.cpy], [ + 01 TEST-01. + 03 TEST-03. + 88 TEST-88 VALUE "0000000". + 09 ERROR-1. + 88 E-TEST-1 VALUE "111". + 10 E-TEST-10 PIC 9(3). + 03 E-TEST-03. + 04 E-TEST-04. + 05 FILLER PIC X(21). + 88 E-TEST-2 VALUE " SM". + 03 E-TEST-2-03. + 09 ERROR-2 PIC 9(3). +]) + +AT_CHECK([$COMPILE prog.cob], [0], [], []) + +AT_CLEANUP + From bd52a863937fe14556cb491015cf808b94a7acbf Mon Sep 17 00:00:00 2001 From: sbelondr Date: Wed, 26 Apr 2023 17:43:26 +0200 Subject: [PATCH 02/10] remove patch #863 and fix bug listing in last test --- cobc/ChangeLog | 4 +- cobc/cobc.c | 362 +++++++++++++++--------- cobc/codegen.c | 15 - tests/ChangeLog | 6 +- tests/testsuite.src/run_reportwriter.at | 45 --- 5 files changed, 227 insertions(+), 205 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 8715395b0..75dc22d02 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,8 +1,6 @@ -2023-03-07 Samuel Belondrade +2023-04-26 Samuel Belondrade - * codegen.c (output_report_control): add a loop to check if the variable - exist (bug: #863) * cobc.c, tree.h : rewrite partialy the copy replacing in listing mode (bug: #831) diff --git a/cobc/cobc.c b/cobc/cobc.c index fd12ea362..18afcc9ec 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6464,6 +6464,89 @@ line_has_listing_statement (char *line, const enum cb_format source_format) return 1; } +static char * +get_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (str[i] && isspace (str[i])) { + ++i; + } + if (str[i]) { + return str + i; + } + return NULL; +} + +static char * +get_next_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (str[i] && !isspace (str[i])) { + ++i; + } + while (str[i] && isspace (str[i])) { + ++i; + } + if (str[i]) { + return str + i; + } + return NULL; +} + + +static COB_INLINE COB_A_INLINE int +is_debug_line (char *line, int fixed, int acudebug) +{ + if (line == NULL || line[0] == 0) { + return 0; + } + return !cb_flag_debugging_line + && ((fixed && line[cobc_get_indicator ()] == 'D') + || (!fixed && (acudebug + ? !strncasecmp (line, "\\D", 2) + : !strncasecmp (line, "D ", 2)))); +} + +static COB_INLINE COB_A_INLINE int +is_comment_line (char *line, int fixed) +{ + if (line == NULL || line[0] == 0) { + return 0; + } else { + const int indicator = cobc_get_indicator (); + return fixed + ? line[indicator] == '*' || line[indicator] == '/' + : !strncmp (line, "*>", 2); + } +} + +static void +abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) +{ + if (pline_cnt >= CB_READ_AHEAD) { + cobc_err_msg (_("%s:%d: too many continuation lines"), + filename, line_num); + cobc_abort_terminate (0); + } +} + +static void +cleanup_copybook_reference (struct list_files *cur) +{ + if (cur->name) { + cobc_free ((void *)cur->name); + } + cobc_free (cur); +} + static void print_fixed_line (const int line_num, char pch, char *line) { @@ -6529,10 +6612,10 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) int indicator = cobc_get_indicator (); int last_word; - bzero (dst, max_chars_on_line + 1); + memset (dst, 0, max_chars_on_line + 1); memset (dst, ' ', margin_b); - // skip space + /* skip space */ while (isspace (line[i])) ++i; start = i; @@ -6540,36 +6623,58 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) while (line[i]) { - // loop space - while (line[i] && isspace (line[i]) && NOT_TOO_LONG (i, start)) { + /* loop space */ + while (line[i] && isspace (line[i]) && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { ++i; } last_word = i; - // loop chars - if (NOT_TOO_LONG (i, start)) { - while (line[i] && !is_quotes_char (line[i], quotes) && !isspace (line[i])) { + /* loop chars */ + if (NOT_TOO_LONG (i, start) && !is_quotes_char (line[i], quotes)) { + while (line[i] && !isspace (line[i]) && !is_quotes_char (line[i], quotes)) { ++i; } } - // check quotes + /* check quotes */ if (line[i] && NOT_TOO_LONG (i, start) && (quotes[0] || quotes[1])) { last_word = i; ++i; - while (line[i] && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { + while (line[i] && !is_quotes_char (line[i], quotes) ) { ++i; } ++i; + if (i - last_word > max_chars_on_line) { + last_word = i; + } } - // print line + /* print line */ if (!NOT_TOO_LONG (i, start)) { if (last_word == -1) { last_word = i; } - strncpy (dst + margin_b, line + start, last_word - start); - print_fixed_line (line_num, pch, dst); + if (last_word - start > max_chars_on_line - margin_b) { + while (last_word - start > max_chars_on_line - margin_b) { + strncpy (dst + margin_b, line + start, max_chars_on_line - margin_b); + dst[max_chars_on_line] = 0; + + print_fixed_line (line_num, pch, dst); + start += max_chars_on_line - margin_b; + memset (dst, 0, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } + if (last_word - start > 0) { + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + } + } else { + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + + } start = last_word; last_word = -1; - bzero (dst, max_chars_on_line + 1); + memset (dst, 0, max_chars_on_line + 1); margin_b = cobc_get_margin_b (1); memset (dst, ' ', margin_b); dst[indicator] = '&'; @@ -6577,11 +6682,24 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) last_word = i; } } - // print last line + /* print last line */ if (start < i) { - strncpy (dst + margin_b, line + start, i - start); - dst[margin_b + i - start] = 0; - print_fixed_line (line_num, pch, dst); + while (i - start > max_chars_on_line - margin_b) { + strncpy (dst + margin_b, line + start, max_chars_on_line - margin_b); + dst[max_chars_on_line] = 0; + print_fixed_line (line_num, pch, dst); + + start += max_chars_on_line - margin_b; + memset (dst, 0, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } + if (start < i) { + strncpy (dst + margin_b, line + start, i - start); + dst[margin_b + i - start] = 0; + print_fixed_line (line_num, pch, dst); + } } } @@ -6593,7 +6711,7 @@ print_fixed_line_mode (const int line_num, char pch, char *line) int i = 0; const int max_chars_on_line = cb_listing_wide ? 112 : 72; - if (strlen(line) <= max_chars_on_line) { + if (strlen (line) <= max_chars_on_line) { while (isspace (*(line + i))) { i++; } @@ -6675,7 +6793,6 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) struct list_skip *skip; int do_print; int on_off; - char pch; do_print = cfile->listing_on; @@ -6696,7 +6813,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) } if (do_print) { - pch = in_copy ? 'C' : ' '; + char pch = in_copy ? 'C' : ' '; for (skip = cfile->skip_head; skip; skip = skip->next) { if (skip->skipline == line_num) { pch = 'X'; @@ -6749,9 +6866,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], int last_nonspace; const int max_chars_on_line = cb_listing_wide ? 112 : 72; - cmp_line[0] = 0; - bzero (cmp_line, CB_LINE_LENGTH + 2); - /* Collapse pline into a string of tokens separated by spaces */ last_nonspace = last_col; i = 0; @@ -6820,42 +6934,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], #undef RET_IF_OVERFLOW -static COB_INLINE COB_A_INLINE int -is_debug_line (char *line, int fixed, int acudebug) -{ - if (line == NULL || line[0] == 0) { - return 0; - } - return !cb_flag_debugging_line - && ((fixed && line[cobc_get_indicator ()] == 'D') - || (!fixed && (acudebug - ? !strncasecmp (line, "\\D", 2) - : !strncasecmp (line, "D ", 2)))); -} - -static COB_INLINE COB_A_INLINE int -is_comment_line (char *line, int fixed) -{ - if (line == NULL || line[0] == 0) { - return 0; - } else { - const int indicator = cobc_get_indicator (); - return fixed - ? line[indicator] == '*' || line[indicator] == '/' - : !strncmp (line, "*>", 2); - } -} - -static void -abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) -{ - if (pline_cnt >= CB_READ_AHEAD) { - cobc_err_msg (_("%s:%d: too many continuation lines"), - filename, line_num); - cobc_abort_terminate (0); - } -} - /* strncpy with skip multiple space for the listing mode in_copy = margin_a for the margin @@ -6912,7 +6990,7 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ int first = 1; t_line_file *bck_line = line_file; - // calculation the len char + /* calculation the len char */ len_to = strlen (lr->to); while (line_file && line_file != data_replace.lastline_replace) { @@ -6927,29 +7005,29 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ dst = cobc_malloc (len_new_line); line_file = bck_line; - // copy first line + /* copy the first line */ if (pos > 0) { last_cpy = strncpy_listing (dst, line_file->line, pos, first, in_copy, 0); first = 0; } - // copy new str + /* copy the new str */ last_cpy += strncpy_listing (dst + last_cpy, lr->to, len_to, first, in_copy, 1); first = 0; while (line_file && line_file != data_replace.lastline_replace) { line_file = line_file->next; } - // copy end line + /* copy the end line */ if (line_file && len_end_line > 0) { strncpy_listing (dst + last_cpy, line_file->line + data_replace.last_char, len_end_line, first, in_copy, 0); } - // stock result in the first line + /* stock the result in the first line */ line_file = bck_line; cobc_free (line_file->line); line_file->line = NULL; line_file->line = dst; - // free other line if it's multi replace line + /* free the other line if it's a multi replace of line */ if (line_file != data_replace.lastline_replace) { line_file = line_file->next; do { @@ -6957,7 +7035,7 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ { cobc_free (line_file->line); line_file->line = NULL; - line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line = cobc_malloc (sizeof(char *) * 2); line_file->line[0] = ' '; line_file->line[1] = 0; } @@ -6968,7 +7046,7 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ { cobc_free (line_file->line); line_file->line = NULL; - line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line = cobc_malloc (sizeof(char *) * 2); line_file->line[0] = ' '; line_file->line[1] = 0; } @@ -7029,7 +7107,7 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, { const int is_simple_quote = lr->from[0] == '\''; t_line_file *line_start = line_file; - t_data_replace data_replace = init_data_replace(); + t_data_replace data_replace = init_data_replace (); int i = start; int j = 0; @@ -7085,7 +7163,7 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, break ; } } - // no match + /* no match */ return data_replace; } @@ -7109,30 +7187,31 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, lastline_line_num = line_num; int deb_line = -1; - // loop char + /* loop char */ while (line_file->line && line_file->line[j]) { deb_line++; - // skip the spaces in the start file + /* skip the spaces in the start file */ while (line_file->line[j] && isspace (line_file->line[j])) { j++; } if (!line_file->line[j]) { break ; } - // loop list replace + /* loop list replace */ rep = cfile->replace_head; match = 0; is_quotes_char (line_file->line[j], quotes); while (rep && line_file->line[j]) { if ((!quotes[0] && !quotes[1]) || rep->from[0] == '\'' || rep->from[0] == '"') { data_replace = search_strstr (line_file, i, rep, j, fixed); - // Match + /* Match */ if (data_replace.last_char != -1) { - // count quotes all lines except the last line + /* count quotes all lines except the last line */ tmp_j = j; tmp_i = i; t_line_file *bck_line = line_file; + while (line_file && line_file != data_replace.lastline_replace) { while (line_file->line[++j]) { is_quotes_char (line_file->line[j], quotes); @@ -7142,7 +7221,7 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, j = -1; } lastline_line_num = i; - // and count quotes in the last line + /* and count quotes in the last line */ while (++j <= data_replace.last_char) { is_quotes_char (line_file->line[j], quotes); } @@ -7161,7 +7240,7 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, } i = tmp_i; line_file = bck_line; - // stock first line in tmp and clean other line in the multiple line replace + /* stock first line in tmp and clean other line in the multiple line replace */ replace_value (line_file, data_replace, rep, j, fixed, in_copy); line_file = data_replace.firstline_replace; @@ -7205,53 +7284,6 @@ deep_copy_list_replace (struct list_replace *src, struct list_files *dst_file) dst_file->replace_tail = copy; } -static void -cleanup_copybook_reference (struct list_files *cur) -{ - if (cur->name) { - cobc_free ((void *)cur->name); - } - cobc_free (cur); -} - -static -char *get_word (char *str) -{ - int i = 0; - - if (!str) { - return NULL; - } - while (isspace (str[i])) { - ++i; - } - if (str + i) { - return str + i; - } - return NULL; -} - -static -char *get_next_word (char *str) -{ - int i = 0; - - if (!str) { - return NULL; - } - while (!isspace (str[i])) { - ++i; - } - while (isspace (str[i])) { - ++i; - } - if (str + i) { - return str + i; - } - return NULL; -} - - /* TO-DO: Modularise! */ /* Applies active REPLACE statements to the source lines in pline. Returns the @@ -7272,18 +7304,21 @@ print_replace_main (struct list_files *cfile, FILE *fd, if (is_comment_line (line_file->line, cfile->source_format != CB_FORMAT_FREE)) { return pline_cnt; } + ptr = get_word (line_file->line); rep = cfile->replace_head; - if (!rep) { + if (!rep || !ptr) { return pline_cnt; } - ptr = get_word (line_file->line); is_copy_line = !strncmp (ptr, "COPY", strlen("COPY")); is_replace_line = !strncmp (ptr, "REPLACE", strlen("REPLACE")); + if (is_replace_line && ptr) { ptr = get_next_word (ptr); - is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); + if (ptr) { + is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); + } } /* @@ -7395,8 +7430,8 @@ print_program_code_apply (struct list_files *cfile, int fixed, int in_copy, return lines_read; } -static t_line_file -*add_new_line(t_line_file *last, char *str) +static t_line_file * +add_new_line(t_line_file *last, char *str) { if (!last) { last = cobc_malloc (sizeof (t_line_file)); @@ -7409,6 +7444,48 @@ static t_line_file return last; } +/* find the last line of replace */ +static void +search_end_replace (t_line_file *line_file, struct list_files *cfile) +{ + const int sz_equal = 2; + const int start_replace = cfile->copy_head->copy_line; + int idx_line; + + for (idx_line = 1; idx_line < start_replace && line_file; idx_line++) { + line_file = line_file->next; + } + + while (line_file) { + if (line_file->line) { + char *value = line_file->line; + while ((value = strstr (value, "=="))) { + int j = sz_equal; + t_line_file *head = line_file; + int is_not_here = 0; + + while (line_file && !is_not_here) { + while (value[j]) { + if (value[j] == '.') { + cfile->copy_head->copy_line = idx_line; + return ; + } else if (!isspace (value[j])) { + is_not_here = 1; + break ; + } + ++j; + } + line_file = line_file->next; + } + line_file = head; + value = value + sz_equal; + } + } + ++idx_line; + line_file = line_file->next; + } +} + /* Print the listing for the file in cfile, with copybooks expanded and after text has been REPLACE'd. @@ -7447,20 +7524,23 @@ print_program_code (struct list_files *cfile, int in_copy) eof = 1; } ++pline_cnt; + char cmp_line[CB_LINE_LENGTH + 2]; int first_col = fixed ? cobc_get_margin_a (1) : 0; + + memset (cmp_line, 0, CB_LINE_LENGTH + 2); compare_prepare (cmp_line, pline, 0, 1, first_col, fixed); - line_file = add_new_line(line_file, cmp_line); + line_file = add_new_line (line_file, cmp_line); if (!head_line_file) { head_line_file = line_file; } + ++line_replace; ++cnt_line; /* Delete all but the last line. */ strcpy (pline[0], pline[pline_cnt]); for (i = 1; i < pline_cnt + 1; i++) { - // abort_if_too_many_continuation_lines (i, cfile->name, line_num); ajouter par moi le 02/11 ne fonctionne pas memset (pline[i], 0, CB_LINE_LENGTH); } @@ -7470,17 +7550,22 @@ print_program_code (struct list_files *cfile, int in_copy) } } while (!eof); + if (cfile->copy_head) { + line_file = head_line_file; + search_end_replace (line_file, cfile); + } + line_file = head_line_file; + line_num = 1; i = 0; pline_cnt = 0; - line_file = head_line_file; char space[2] = {' ', 0}; - // search replacement and print + /* search replacement and print */ while (i < line_replace) { pline_cnt++; lines_read = 0; - // if line is empty, just print + /* if line is empty, just print */ if (!line_file->line || strcmp (line_file->line, "") == 0) { print_line (cfile, space, line_num, in_copy); line_file = line_file->next; @@ -7489,12 +7574,12 @@ print_program_code (struct list_files *cfile, int in_copy) continue ; } - // search replacement + /* search replacement */ lines_read = print_program_code_apply (cfile, fixed, in_copy, &pline_cnt, \ &i, &line_num, lines_read, line_file, &line_replace, fd); if (lines_read > 0) { - // if edit is current don't print + /* if edit is current don't print */ line_num += lines_read; i += lines_read; while (line_file && lines_read > 0) { @@ -7508,15 +7593,16 @@ print_program_code (struct list_files *cfile, int in_copy) } pline_cnt = 0; } - line_file = head_line_file; - // free pline_replace + + /* free pline_replace */ t_line_file *next; + while (line_file) { cobc_free (line_file->line); line_file->line = NULL; next = line_file->next; - cobc_free(line_file); + cobc_free (line_file); line_file = next; } } diff --git a/cobc/codegen.c b/cobc/codegen.c index 5f7989562..5a0edec92 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -9681,21 +9681,6 @@ output_report_control (struct cb_report *p, int id, cb_tree ctl, cb_tree nx) if(nx) { output_report_control(p, id, nx, CB_CHAIN(nx)); } - bfound = 0; - for(i= p->num_lines-1; i >= 0; i--) { - if(p->line_ids[i]->report_control) { - struct cb_field *c = cb_code_field (p->line_ids[i]->report_control); - if(c == s) { - bfound = 1; - break; - } - } - } - if (!bfound) { - ctl = NULL; - p->controls = NULL; - return ; - } output_local("/* Report %s: CONTROL %s */\n",p->name,s->name); prvid = 0; for(i = 0; i < p->num_lines; i++) { diff --git a/tests/ChangeLog b/tests/ChangeLog index 7e904e5d1..9f5507e35 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,8 +1,6 @@ -2023-03-07 Samuel Belondrade +2023-04-26 Samuel Belondrade - * testsuite.src/run_reportwriter.at: add test if the variable exist - for report section (bug: #863) * testsuite.src/listing.at: add test for the copy replacing in listing mode (bug: #831) @@ -760,7 +758,7 @@ * testsuite.src/*.at: Added check for cobc's exit code and stderr where missing -2014-14-04 Philipp Böhme +2014-14-04 Philipp B�hme * testsuite.src/run_extensions.at: Added tests for getopt. diff --git a/tests/testsuite.src/run_reportwriter.at b/tests/testsuite.src/run_reportwriter.at index 707220749..2ff781a44 100644 --- a/tests/testsuite.src/run_reportwriter.at +++ b/tests/testsuite.src/run_reportwriter.at @@ -9626,48 +9626,3 @@ BEFORE FINAL - SHOULD DISPLAY AT_CLEANUP -AT_SETUP([Check if the variable is referenced in the report]) -AT_KEYWORDS([report]) - -AT_DATA([prog.cob], [ - IDENTIFICATION DIVISION. - PROGRAM-ID. MAIN. - ENVIRONMENT DIVISION. - CONFIGURATION SECTION. - INPUT-OUTPUT SECTION. - FILE-CONTROL. - SELECT A_1 ASSIGN TO EXTERNAL A_1. - SELECT A_2 ASSIGN TO EXTERNAL A_2. - DATA DIVISION. - FILE SECTION. - FD A_1. - COPY test. - FD A_2 REPORT ETAT. - WORKING-STORAGE SECTION. - REPORT SECTION. - RD ETAT - CONTROL FINAL ERROR-1 ERROR-2 - PAGE LIMIT 66. - PROCEDURE DIVISION. - STOP RUN. -]) - -AT_DATA([test.cpy], [ - 01 TEST-01. - 03 TEST-03. - 88 TEST-88 VALUE "0000000". - 09 ERROR-1. - 88 E-TEST-1 VALUE "111". - 10 E-TEST-10 PIC 9(3). - 03 E-TEST-03. - 04 E-TEST-04. - 05 FILLER PIC X(21). - 88 E-TEST-2 VALUE " SM". - 03 E-TEST-2-03. - 09 ERROR-2 PIC 9(3). -]) - -AT_CHECK([$COMPILE prog.cob], [0], [], []) - -AT_CLEANUP - From 8bc8b6c363caf37f7dea093d7de0c009e1470457 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Wed, 28 Jun 2023 16:39:54 +0200 Subject: [PATCH 03/10] fix syntax and delete a check --- cobc/ChangeLog | 1 - cobc/cobc.c | 39 ++++++++++++++++++++++++--------------- cobc/tree.h | 11 ----------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 2c6c5dae2..b7a81af2d 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -190,7 +190,6 @@ * typeck.c (cb_build_move_literal): optimized output for literals to fields with BLANK WHEN ZERO and SIGN LEADING - 2023-04-26 Samuel Belondrade * cobc.c, tree.h : rewrite partialy the copy replacing in listing diff --git a/cobc/cobc.c b/cobc/cobc.c index 4296c414e..196c93a7e 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -289,6 +289,16 @@ cob_u32_t optimize_defs[COB_OPTIM_MAX] = { 0 }; int cb_flag_alt_ebcdic = 0; +typedef struct s_line_file { + char *line; + struct s_line_file *next; +} t_line_file; + +typedef struct s_data_replace { + t_line_file *firstline_replace; + t_line_file *lastline_replace; + int last_char; +} t_data_replace; /* Basic memory structure */ struct cobc_mem_struct { @@ -6489,7 +6499,7 @@ get_word (char *str) if (!str) { return NULL; } - while (str[i] && isspace (str[i])) { + while (str[i] && (isspace (str[i]) || str[i] == ',' || str[i] == '.' || str[i] == ';')) { ++i; } if (str[i]) { @@ -6509,7 +6519,7 @@ get_next_word (char *str) while (str[i] && !isspace (str[i])) { ++i; } - while (str[i] && isspace (str[i])) { + while (str[i] && (isspace (str[i]) || str[i] == ',' || str[i] == '.' || str[i] == ';')) { ++i; } if (str[i]) { @@ -6545,7 +6555,7 @@ is_comment_line (char *line, int fixed) } } -static void +static COB_INLINE COB_A_INLINE void abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) { if (pline_cnt >= CB_READ_AHEAD) { @@ -6555,7 +6565,7 @@ abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int l } } -static void +static COB_INLINE COB_A_INLINE void cleanup_copybook_reference (struct list_files *cur) { if (cur->name) { @@ -6574,9 +6584,6 @@ print_fixed_line (const int line_num, char pch, char *line) const int indicator = cobc_get_indicator (); const int text_column = cobc_get_text_column (); - if (!line) { - return ; - } len = strlen (line); if (line[indicator] == '&') { line[indicator] = '-'; @@ -7198,12 +7205,12 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, int quotes[2] = {0, 0}; struct list_replace *rep; t_data_replace data_replace; + int deb_line = -1; j = 0; i = line_num; lastline_line_num = line_num; - int deb_line = -1; /* loop char */ while (line_file->line && line_file->line[j]) { deb_line++; @@ -7225,9 +7232,10 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, if (data_replace.last_char != -1) { /* count quotes all lines except the last line */ + t_line_file *bck_line = line_file; + tmp_j = j; tmp_i = i; - t_line_file *bck_line = line_file; while (line_file && line_file != data_replace.lastline_replace) { while (line_file->line[++j]) { @@ -7535,16 +7543,19 @@ print_program_code (struct list_files *cfile, int in_copy) if (fd != NULL) { abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); if (get_next_listing_line (fd, &pline[pline_cnt], fixed) >= 0) { + char space[2] = {' ', 0}; + t_line_file *next; + do { + char cmp_line[CB_LINE_LENGTH + 2]; + int first_col = fixed ? cobc_get_margin_a (1) : 0; + abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); if (get_next_listing_line (fd, &pline[pline_cnt + 1], fixed) < 0) { eof = 1; } ++pline_cnt; - char cmp_line[CB_LINE_LENGTH + 2]; - int first_col = fixed ? cobc_get_margin_a (1) : 0; - memset (cmp_line, 0, CB_LINE_LENGTH + 2); compare_prepare (cmp_line, pline, 0, 1, first_col, fixed); line_file = add_new_line (line_file, cmp_line); @@ -7571,13 +7582,13 @@ print_program_code (struct list_files *cfile, int in_copy) line_file = head_line_file; search_end_replace (line_file, cfile); } + line_file = head_line_file; line_num = 1; i = 0; pline_cnt = 0; - char space[2] = {' ', 0}; /* search replacement and print */ while (i < line_replace) { pline_cnt++; @@ -7613,8 +7624,6 @@ print_program_code (struct list_files *cfile, int in_copy) line_file = head_line_file; /* free pline_replace */ - t_line_file *next; - while (line_file) { cobc_free (line_file->line); line_file->line = NULL; diff --git a/cobc/tree.h b/cobc/tree.h index 7eb93621f..df31751a5 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -1656,17 +1656,6 @@ struct list_error { char *msg; /* Error Message text */ }; -typedef struct s_line_file { - char *line; - struct s_line_file *next; -} t_line_file; - -typedef struct s_data_replace { - t_line_file *firstline_replace; - t_line_file *lastline_replace; - int last_char; -} t_data_replace; - /* List of REPLACE text blocks */ struct list_replace { struct list_replace *next; From dafd128f9295e6223351f74afcc980264f5d8895 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Thu, 20 Jul 2023 15:11:44 +0200 Subject: [PATCH 04/10] edit function check simple and double quotes --- cobc/cobc.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index 196c93a7e..e257a8a05 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6608,13 +6608,13 @@ print_fixed_line (const int line_num, char pch, char *line) } static int -is_quotes_char (char c, int quotes[2]) +is_quotes_char (char c, int *simple_quote, int *double_quote) { if (c == '\'') { - quotes[0] = !quotes[0]; + *simple_quote = !(*simple_quote); } else if (c == '"') { - quotes[1] = !quotes[1]; + *double_quote = !(*double_quote); } else { return 0; } @@ -6631,7 +6631,8 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) int start = 0; const int max_chars_on_line = cb_listing_wide ? 112 : 72; char dst[max_chars_on_line + 1]; - int quotes[2] = {0, 0}; + int simple_quote = 0; + int double_quote = 0; int margin_b = cobc_get_margin_b (1); int indicator = cobc_get_indicator (); int last_word; @@ -6648,21 +6649,21 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) while (line[i]) { /* loop space */ - while (line[i] && isspace (line[i]) && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { + while (line[i] && isspace (line[i]) && !is_quotes_char (line[i], &simple_quote, &double_quote) && NOT_TOO_LONG (i, start)) { ++i; } last_word = i; /* loop chars */ - if (NOT_TOO_LONG (i, start) && !is_quotes_char (line[i], quotes)) { - while (line[i] && !isspace (line[i]) && !is_quotes_char (line[i], quotes)) { + if (NOT_TOO_LONG (i, start) && !is_quotes_char (line[i], &simple_quote, &double_quote)) { + while (line[i] && !isspace (line[i]) && !is_quotes_char (line[i], &simple_quote, &double_quote)) { ++i; } } /* check quotes */ - if (line[i] && NOT_TOO_LONG (i, start) && (quotes[0] || quotes[1])) { + if (line[i] && NOT_TOO_LONG (i, start) && (simple_quote || double_quote)) { last_word = i; ++i; - while (line[i] && !is_quotes_char (line[i], quotes) ) { + while (line[i] && !is_quotes_char (line[i], &simple_quote, &double_quote) ) { ++i; } ++i; @@ -7202,7 +7203,8 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, int tmp_j; int match; int lastline_line_num; - int quotes[2] = {0, 0}; + int simple_quote = 0; + int double_quote = 0; struct list_replace *rep; t_data_replace data_replace; int deb_line = -1; @@ -7224,9 +7226,9 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, /* loop list replace */ rep = cfile->replace_head; match = 0; - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); while (rep && line_file->line[j]) { - if ((!quotes[0] && !quotes[1]) || rep->from[0] == '\'' || rep->from[0] == '"') { + if ((!simple_quote && !double_quote) || rep->from[0] == '\'' || rep->from[0] == '"') { data_replace = search_strstr (line_file, i, rep, j, fixed); /* Match */ if (data_replace.last_char != -1) @@ -7239,7 +7241,7 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, while (line_file && line_file != data_replace.lastline_replace) { while (line_file->line[++j]) { - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); } ++i; line_file = line_file->next; @@ -7248,7 +7250,7 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, lastline_line_num = i; /* and count quotes in the last line */ while (++j <= data_replace.last_char) { - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); } j = tmp_j; From 43d0968f364c00669e4fe10bcf2e124bfa1fe8aa Mon Sep 17 00:00:00 2001 From: sbelondr Date: Thu, 20 Jul 2023 16:14:36 +0200 Subject: [PATCH 05/10] fix conflit --- cobc/ChangeLog | 5 + cobc/cobc.c | 1344 ++++++++++------------- cobc/codegen.c | 15 + cobc/tree.h | 11 + tests/ChangeLog | 5 + tests/testsuite.src/listings.at | 136 +++ tests/testsuite.src/run_reportwriter.at | 45 + 7 files changed, 822 insertions(+), 739 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 8fd95b8c6..a353788df 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,4 +1,9 @@ +2023-07-20 Samuel Belondrade + + * cobc.c : rewrite partialy the copy replacing in listing + mode (bug: #831) + 2023-07-11 Fabrice Le Fessant * parser.y: fix code generation for OPEN/CLOSE with multiple diff --git a/cobc/cobc.c b/cobc/cobc.c index 4bb9768a1..d6a0d1a8e 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6401,58 +6401,6 @@ get_next_nonspace (char * pos) return pos; } -/* - Find next token after bp, copy it to token and copy the token terminator to - term. Return pointer to the character after the terminator. -*/ -static char * -get_next_token (char *bp, char *token, char *term) -{ - char *token_start = token; - int in_string = 0; - - /* Repeat until a token is found */ - do { - bp = get_next_nonspace (bp); - - term[0] = '\0'; - term[1] = '\0'; - if (*bp == '\0') { - return NULL; - } - - /* Copy characters into token until a terminator is found. */ - while (*bp) { - /* Return character strings as a single token */ - if (*bp == '"' || *bp == '\'') { - in_string = !in_string; - *token++ = *bp++; - if (!in_string) { - if (isspace ((unsigned char)*bp) || *bp == ',' || *bp == '.' || *bp == ';') { - term[0] = *bp++; - } - break; - } - continue; - } - if (in_string) { - *token++ = *bp++; - continue; - } - if (*bp == '.' && isdigit((unsigned char)*(bp + 1))) { - ; - } else if (isspace ((unsigned char)*bp) || *bp == ',' || *bp == '.' || *bp == ';') { - term[0] = *bp++; - break; - } - *token++ = *bp++; - } - *token = '\0'; - } while (*token_start == '\0' && *term != '\0'); - - return bp; -} - static void terminate_str_at_first_of_char (const char c, char * const str) { @@ -6684,12 +6632,16 @@ static void print_fixed_line (const int line_num, char pch, char *line) { int i; - int len = strlen (line); + int len; const int max_chars_on_line = cb_listing_wide ? 112 : 72; const char *format_str; const int indicator = cobc_get_indicator (); const int text_column = cobc_get_text_column (); + if (!line) { + return ; + } + len = strlen (line); if (line[indicator] == '&') { line[indicator] = '-'; pch = '+'; @@ -6712,6 +6664,110 @@ print_fixed_line (const int line_num, char pch, char *line) } } +static int +is_quotes_char (char c, int quotes[2]) +{ + if (c == '\'') { + quotes[0] = !quotes[0]; + } + else if (c == '"') { + quotes[1] = !quotes[1]; + } else { + return 0; + } + return 1; +} + +#define NOT_TOO_LONG(idx,last_print_idx) \ + !((idx - last_print_idx + margin_b) >= (max_chars_on_line)) + +static void +print_multiple_fixed_line (const int line_num, char pch, char *line) +{ + int i = 0; + int start = 0; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; + char dst[max_chars_on_line + 1]; + int quotes[2] = {0, 0}; + int margin_b = cobc_get_margin_b (1); + int indicator = cobc_get_indicator (); + int last_word; + + bzero (dst, max_chars_on_line + 1); + memset (dst, ' ', margin_b); + + // skip space + while (isspace (line[i])) + ++i; + start = i; + last_word = -1; + + while (line[i]) + { + // loop space + while (line[i] && isspace (line[i]) && NOT_TOO_LONG (i, start)) { + ++i; + } + last_word = i; + // loop chars + if (NOT_TOO_LONG (i, start)) { + while (line[i] && !is_quotes_char (line[i], quotes) && !isspace (line[i])) { + ++i; + } + } + // check quotes + if (line[i] && NOT_TOO_LONG (i, start) && (quotes[0] || quotes[1])) { + last_word = i; + ++i; + while (line[i] && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { + ++i; + } + ++i; + } + // print line + if (!NOT_TOO_LONG (i, start)) { + if (last_word == -1) { + last_word = i; + } + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + start = last_word; + last_word = -1; + bzero (dst, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } else { + last_word = i; + } + } + // print last line + if (start < i) { + strncpy (dst + margin_b, line + start, i - start); + dst[margin_b + i - start] = 0; + print_fixed_line (line_num, pch, dst); + } +} + +#undef NOT_TOO_LONG + +static void +print_fixed_line_mode (const int line_num, char pch, char *line) +{ + int i = 0; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; + + if (strlen(line) <= max_chars_on_line) { + while (isspace (*(line + i))) { + i++; + } + print_fixed_line (line_num, pch, line); + } + else { + print_multiple_fixed_line (line_num, pch, line); + } +} + static void print_free_line (const int line_num, char pch, char *line) { @@ -6783,8 +6839,10 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) struct list_skip *skip; int do_print; int on_off; + char pch; do_print = cfile->listing_on; + if (line_has_listing_directive (line, cfile->source_format, &on_off)) { cfile->listing_on = on_off; /* always print the directive itself */ @@ -6802,7 +6860,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) } if (do_print) { - char pch = in_copy ? 'C' : ' '; + pch = in_copy ? 'C' : ' '; for (skip = cfile->skip_head; skip; skip = skip->next) { if (skip->skipline == line_num) { pch = 'X'; @@ -6812,7 +6870,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) (void)terminate_str_at_first_trailing_space (line); if (CB_SF_FIXED (cfile->source_format)) { - print_fixed_line (line_num, pch, line); + print_fixed_line_mode (line_num, pch, line); } else { print_free_line (line_num, pch, line); } @@ -6853,10 +6911,14 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], int in_string = 0; int last_col = cobc_get_text_column (); int last_nonspace; + const int max_chars_on_line = cb_listing_wide ? 112 : 72; cmp_line[0] = 0; + bzero (cmp_line, CB_LINE_LENGTH + 2); /* Collapse pline into a string of tokens separated by spaces */ + last_nonspace = last_col; + i = 0; for (line_idx = first_idx; line_idx < last_idx; line_idx++) { if (!fixed) { last_col = strlen (pline[line_idx]) - 1; @@ -6867,16 +6929,24 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], isspace ((unsigned char)pline[line_idx][last_nonspace]) && last_nonspace > first_col; last_nonspace--); /* Go to first non-space character */ - for (i = first_col; (i <= last_nonspace) && isspace ((unsigned char)pline[line_idx][i]); i++); - - /* Copy chars between the first and last non-space characters */ + i = 0; while (i <= last_nonspace) { if (isspace ((unsigned char)pline[line_idx][i])) { RET_IF_OVERFLOW (cmp_line[out_pos++] = ' '); - for (i++; (i <= last_nonspace) && isspace ((unsigned char)pline[line_idx][i]); i++); - if (i > last_nonspace) { - break; - } + i++; + } else { + break ; + } + } + last_nonspace += first_col + 1; + if (fixed && last_nonspace > max_chars_on_line) { + last_nonspace = max_chars_on_line; + } + /* Copy chars between the first and last non-space characters */ + while (i < last_nonspace) { + if (isspace ((unsigned char)pline[line_idx][i])) { + RET_IF_OVERFLOW (cmp_line[out_pos++] = ' '); + i++; } else if (pline[line_idx][i] == '"') { /* Merge multi-part strings into one string, @@ -6890,14 +6960,14 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], in_string = 1; } - for (; (i <= last_nonspace) && (pline[line_idx][i] != '"'); ) { + for (; (i < last_nonspace) && (pline[line_idx][i] != '"'); ) { RET_IF_OVERFLOW (cmp_line[out_pos++] = pline[line_idx][i++]); } if (pline[line_idx][i] == '"') { RET_IF_OVERFLOW (cmp_line[out_pos++] = pline[line_idx][i++]); in_string = 0; } - if (i > last_nonspace) { + if (i > last_nonspace - 1) { break; } } else { @@ -6914,32 +6984,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], #undef RET_IF_OVERFLOW -/* - Add adjust to each line number less than line_num (if appropriate) in cfile's - copy, replace and error lists. -*/ -static void -adjust_line_numbers (struct list_files *cfile, int line_num, int adjust) -{ - struct list_files *cur; - struct list_replace *rep; - struct list_error *err; - - for (cur = cfile->copy_head; cur; cur = cur->next) { - cur->copy_line += adjust; - } - - for (rep = cfile->replace_head; rep; rep = rep->next) { - if (rep->firstline > line_num) { - rep->firstline += adjust; - } - } - - for (err = cfile->err_head; err; err = err->next) { - err->line += adjust; - } -} - static COB_INLINE COB_A_INLINE int is_debug_line (char *line, int fixed, int acudebug) { @@ -6966,32 +7010,6 @@ is_comment_line (char *line, int fixed) } } -static int -is_continuation_line (char *line, int fixed) -{ - int i; - - if (line == NULL || line[0] == 0) { - return 0; - } - if (fixed) { - /* check for "-" in indicator column */ - if (line [cobc_get_indicator ()] == '-') { - return 1; - } - } else { - /* check for "&" as last character */ - /* CHECKME: does this work with inline comments after "&"? */ - i = strlen (line) - 1; - while (i && isspace ((unsigned char)line[i])) i--; - if (line[i] == '&') { - return 1; - } - } - - return 0; -} - static void abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) { @@ -7002,526 +7020,329 @@ abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int l } } -static void -make_new_continuation_line (const char *cfile_name, char *pline[CB_READ_AHEAD], - int * const pline_cnt, int line_num) -{ - const int margin_a = cobc_get_margin_a (1); - const int indicator = cobc_get_indicator (); - const int sequence_col = cobc_get_text_column (); - abort_if_too_many_continuation_lines (*pline_cnt + 1, cfile_name, - line_num); - if (pline[*pline_cnt + 1] == NULL) { - pline[*pline_cnt + 1] = cobc_malloc (CB_LINE_LENGTH + 2); +/* + strncpy with skip multiple space for the listing mode + in_copy = margin_a for the margin + if is new string line replace don't skip the spaces +*/ +static int +strncpy_listing (char *dst, char *src, int n, int first, int in_copy, int is_new) +{ + int i = 0; + const int margin_a = cobc_get_margin_a (1); + int cnt_space = 0; + int j = 0; + + while (i < n && src[i]) { + cnt_space = 0; + while (i + cnt_space < n && src[i + cnt_space] && isspace (src[i + cnt_space])) + cnt_space++; + if (cnt_space > 0) { + if ((first && i == 0) || !src[i]) { + if (in_copy && i == 0) { + memset (dst + j, ' ', margin_a); + j += margin_a; + } else { + memset (dst + j, ' ', cnt_space); + j += cnt_space; + } + } else if (is_new) { + memset (dst + j, ' ', cnt_space); + j += cnt_space; + } else { + dst[j++] = ' '; + } + } + i += cnt_space; + while (i < n && src[i] && !isspace (src[i])) { + dst[j++] = src[i]; + i++; + } } - strcpy (pline[*pline_cnt + 1], pline[*pline_cnt]); - strcpy (pline[*pline_cnt], pline[*pline_cnt - 1]); - memset (&pline[*pline_cnt][margin_a], ' ', - sequence_col - margin_a); - pline[*pline_cnt][indicator] = '&'; - - (*pline_cnt)++; + dst[j] = 0; + return j; } +/* Replace line by the new value for the listing mode */ static void -add_token_over_multiple_lines (const char *cfile_name, - char *pline[CB_READ_AHEAD], - int * const pline_cnt, - const int line_num, - const char *new_token, - const int first_col, - int new_token_len, - int * const out_line, - int * const out_col) -{ - int tok_char = 0; - const int sequence_col = cobc_get_text_column (); - -#ifdef DEBUG_REPLACE - fprintf (stdout, " new_token_len = %d\n", new_token_len); -#endif - - while (new_token_len) { - /* Copy the token one character at a time. */ - pline[*out_line][(*out_col)++] = new_token[tok_char++]; - new_token_len--; - - /* - Move to the next line when reach the end of the current one. - */ - if (*out_col == sequence_col) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " NEW pline[%2d] = %s\n", - *out_line, pline[*out_line]); -#endif - - *out_col = first_col; - (*out_line)++; +replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_replace *lr, int pos, int fixed, int in_copy) +{ + char *dst; + int len_new_line; + int sz_old_line = 0; + int len_to; + int len_end_line; + int last_cpy = 0; + int first = 1; + t_line_file *bck_line = line_file; - /* - Allocate a new out_line if we are on the last - out_line. - */ - if (*out_line == *pline_cnt) { - make_new_continuation_line (cfile_name, pline, - pline_cnt, line_num); - } + // calculation the len char + len_to = strlen (lr->to); + while (line_file && line_file != data_replace.lastline_replace) + { + if (data_replace.firstline_replace == line_file) { + sz_old_line += pos; } + line_file = line_file->next; } + len_end_line = strlen (line_file->line + data_replace.last_char); + sz_old_line += len_end_line; + len_new_line = pos + len_to + len_end_line + 1; + dst = cobc_malloc (len_new_line); + line_file = bck_line; - pline[*out_line][(*out_col)++] = ' '; -} - -static void -reflow_replaced_fixed_format_text (const char *cfile_name, char *pline[CB_READ_AHEAD], - int * const pline_cnt, const int line_num, - char *newline, int first_col, const int last) -{ - int first_nonspace; - char *new_line_ptr; - char *new_token; - char token_terminator[2]; - int out_col; - int out_line; - int force_next_line; - int new_token_len; - const int margin_b = cobc_get_margin_b (1); - const int indicator = cobc_get_indicator (); - const int sequence_col = cobc_get_text_column (); - - new_token = cobc_malloc (strlen(newline) + 2); - new_line_ptr = get_next_token (newline, new_token, token_terminator); + // copy first line + if (pos > 0) { + last_cpy = strncpy_listing (dst, line_file->line, pos, first, in_copy, 0); + first = 0; + } + // copy new str + last_cpy += strncpy_listing (dst + last_cpy, lr->to, len_to, first, in_copy, 1); + first = 0; + while (line_file && line_file != data_replace.lastline_replace) { + line_file = line_file->next; + } + // copy end line + if (line_file && len_end_line > 0) { + strncpy_listing (dst + last_cpy, line_file->line + data_replace.last_char, len_end_line, first, in_copy, 0); + } - /* - Start adding tokens from margin B or the first non-space character. - */ - for (first_nonspace = first_col; - (first_nonspace < last) - && isspace ((unsigned char)(pline[0][first_nonspace])); - first_nonspace++); - if (first_nonspace >= margin_b) { - first_col = margin_b; - } - - /* For each line, */ - for (out_line = 0; out_line < *pline_cnt; out_line++) { - force_next_line = 0; - out_col = first_col; - - /* Add as many token as possible to the current line. */ - while (new_line_ptr && !force_next_line) { - new_token_len = strlen (new_token); - if (new_token_len >= (sequence_col - first_col)) { - /* - If the new token does not fit on this line, - reflow it onto the next line. - */ - add_token_over_multiple_lines (cfile_name, pline, pline_cnt, line_num, - new_token, first_col, new_token_len, - &out_line, &out_col); - } else if ((out_col + 2 + new_token_len) < last) { - /* - If the new token *and* its terminator fits, - copy it all onto the current line. - */ - strcpy (&pline[out_line][out_col], new_token); - out_col += strlen (new_token); + // stock result in the first line + line_file = bck_line; + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = dst; - if (token_terminator[0]) { - pline[out_line][out_col++] = token_terminator[0]; - } else { - pline[out_line][out_col++] = ' '; - } - if (token_terminator[0] == '.') { - pline[out_line][out_col++] = ' '; - } - } else { - force_next_line = 1; - make_new_continuation_line (cfile_name, pline, - pline_cnt, line_num); - continue; + // free other line if it's multi replace line + if (line_file != data_replace.lastline_replace) { + line_file = line_file->next; + do { + if (!is_comment_line (line_file->line, fixed)) + { + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line[0] = ' '; + line_file->line[1] = 0; + } + line_file = line_file->next; + } while (line_file && line_file != data_replace.lastline_replace); + if (line_file && line_file->next) { + if (!is_comment_line (line_file->line, fixed)) + { + cobc_free (line_file->line); + line_file->line = NULL; + line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line[0] = ' '; + line_file->line[1] = 0; } - new_line_ptr = get_next_token (new_line_ptr, new_token, token_terminator); } - - if (out_col == first_col) { - pline[out_line][indicator] = ' '; - } - while (out_col < last) { - pline[out_line][out_col++] = ' '; - } - -#ifdef DEBUG_REPLACE - fprintf (stdout, " NEW pline[%2d] = %s\n", out_line, pline[out_line]); -#endif + line_file = bck_line; } - cobc_free (new_token); } -static void -reflow_replaced_free_format_text (char *pline[CB_READ_AHEAD], - const int pline_cnt, char *newline, - const int first_col) +static int +condition_leading (char *line, int start) { - char *new_line_ptr; - char *new_token; - char token_terminator[2]; - int i; - int j; - - new_token = cobc_malloc (strlen(newline) + 2); - new_line_ptr = get_next_token (newline, new_token, token_terminator); - - for (i = 0; i < pline_cnt; i++) { - /* - Terminate the line at null or the first non-space character. - */ - for (j = first_col; pline[i][j] == ' '; j++); - pline[i][j] = '\0'; - - /* - If the text has not been copied yet, copy it to the start of - the line. - */ - while (new_line_ptr) { - /* TO-DO: Replace with strncat? */ - strcat (pline[i], new_token); - strcat (pline[i], token_terminator); - j++; - new_line_ptr = get_next_token (new_line_ptr, new_token, - token_terminator); - } + if (start == 0 || isspace (line[start - 1])) + return 1; + return 0; +} - if (j == first_col) { - strcat (pline[i], " "); - } +static int +condition_trailing (char *line, int end) +{ + if (end == (int)strlen (line) - 1 || isspace (line[end])) { + return 1; } - cobc_free (new_token); + return 0; } static int -reflow_replaced_text (const char *cfile_name, char *pline[CB_READ_AHEAD], - int pline_cnt, int line_num, char *newline, int first_col, - int last_col, int fixed) +check_mode_trail_lead (t_data_replace data_replace, struct list_replace *lr, int start, int end) { - if (fixed) { - reflow_replaced_fixed_format_text (cfile_name, pline, - &pline_cnt, line_num, - newline, first_col, - last_col); - } else { - reflow_replaced_free_format_text (pline, pline_cnt, newline, - first_col); + if (lr->lead_trail == CB_REPLACE_TRAILING) { + return condition_trailing (data_replace.lastline_replace->line, end); } - - return pline_cnt; + return condition_leading (data_replace.firstline_replace->line, start); } -/* TODO: Modularise! */ - static int -print_replace_text (struct list_files *cfile, FILE *fd, - struct list_replace *rep, char *pline[CB_READ_AHEAD], - int pline_cnt, int line_num) -{ - char *rfp = rep->from; - char *from_ptr; - char *to_ptr; - char *newline; - const int fixed = CB_SF_FIXED (cfile->source_format); - const int acudebug = (cfile->source_format == CB_FORMAT_ACUTERM); - int first_col = fixed ? cobc_get_margin_a (1) : 0; - int last; - int multi_token; - int match = 0; - int eof = 0; - int submatch = 0; - int seccount = 0; - int overread = 0; - int tokmatch = 0; - int subword = 0; - int strictmatch = 0; - size_t ttix, ttlen, from_token_len; - size_t newlinelen; - char lterm[2]; - char fterm[2]; - char ftoken[CB_LINE_LENGTH + 2]; - char tterm[2]; - char ttoken[CB_LINE_LENGTH + 2]; - char cmp_line[CB_LINE_LENGTH + 2]; - char from_line[CB_LINE_LENGTH + 2] = { 0 }; - - if (is_comment_line (pline[0], fixed)) { - return pline_cnt; +compare_char (char a, char b, int is_simple_quote) +{ + if (!is_simple_quote) { + return a == b; } + return tolower (a) == tolower (b); +} - /* Trim the string to search and replace */ - (void)terminate_str_at_first_trailing_space (rfp); - while (*rfp && isspace ((unsigned char)(*rfp))) { - rfp++; - } - multi_token = (strchr (rfp, ' ') != NULL); +static t_data_replace +init_data_replace(void) +{ + t_data_replace new_data_replace; -#ifdef DEBUG_REPLACE - fprintf (stdout, "print_replace_text: line_num = %d", line_num); - fprintf (stdout, ", multi_token = %s, fixed = %s\n", - multi_token ? "TRUE" : "FALSE", fixed ? "TRUE" : "FALSE"); - fprintf (stdout, " pline_cnt = %d\n", pline_cnt); - for (int i = 0; i < pline_cnt; i++) { - fprintf (stdout, " pline[%2d]: %s\n", i, pline[i]); - } - fprintf (stdout, - " rep: first = %d, last = %d, lead_trail = %d, strict = %d\n", - rep->firstline, rep->lastline, rep->lead_trail, - rep->strict_partial); - fprintf (stdout, " fromlen: %lu\n", strlen(rfp)); - fprintf (stdout, " from: '%80.80s'\n", rfp); - fprintf (stdout, " tolen: %lu\n", strlen(rep->to)); - fprintf (stdout, " to: '%80.80s'\n", rep->to); -#endif - - newlinelen = CB_LINE_LENGTH+2; - newline = cobc_malloc (newlinelen); - - last = compare_prepare (cmp_line, pline, 0, pline_cnt, first_col, fixed); - - newline[0] = 0; - if (multi_token) { - /* - Attempt to match the source text from the beginning of each - line (continuing the match to the next line if need be). If a - match is found, output the line to newline with the match - replaced. - */ + new_data_replace.last_char = -1; + new_data_replace.firstline_replace = NULL; + new_data_replace.lastline_replace = NULL; + return new_data_replace; +} - strcpy (from_line, rfp); - from_ptr = get_next_token (from_line, ftoken, fterm); - force_next_line: - to_ptr = get_next_token (cmp_line, ttoken, tterm); +static t_data_replace +search_strstr (t_line_file *line_file, int line, struct list_replace *lr, + int start, int fixed) +{ + const int is_simple_quote = lr->from[0] == '\''; + t_line_file *line_start = line_file; + t_data_replace data_replace = init_data_replace(); + int i = start; + int j = 0; - /* - Read tokens until the match is complete or until a match - fails. - */ - while (to_ptr && from_ptr) { - if (!strcasecmp (ttoken, ftoken)) { - /* - Mark two tokens as matched, then read next - pair. - */ - submatch = 1; - if (fterm[0] == tterm[0]) { - lterm[0] = 0; - } else { - lterm[0] = tterm[0]; + while (lr->from[j] && isspace (lr->from[j])) { + ++j; + } + while (line_file && line_file->line && line_file->line[i]) { + if (is_comment_line (line_file->line, fixed)) { + ++line; + line_file = line_file->next; + i = 0; + continue ; + } + while (line_file->line[i] && lr->from[j] \ + && ((isspace (line_file->line[i]) || isspace (lr->from[j])) \ + || compare_char (line_file->line[i], lr->from[j], is_simple_quote))) { + if (isspace (line_file->line[i]) || isspace (lr->from[j])) { + while (line_file->line[i] && isspace (line_file->line[i])) { + ++i; } - lterm[1] = tterm[1]; - to_ptr = get_next_token (to_ptr, ttoken, tterm); - from_ptr = get_next_token (from_ptr, ftoken, fterm); - } else { - /* Discard partial match. */ - if (seccount == 0) { - if ((strlen (newline) + strlen (ttoken) + strlen (tterm)) >= newlinelen) { - newlinelen += strlen (ttoken) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, ttoken); - strcat (newline, tterm); + while (lr->from[j] && isspace (lr->from[j])) { + ++j; } - submatch = 0; - - /* Start matching from beginning of from_line again. */ - strcpy (from_line, rfp); - from_ptr = get_next_token (from_line, ftoken, fterm); - to_ptr = get_next_token (to_ptr, ttoken, tterm); - break; + } else { + ++i; + ++j; } } - if (!from_ptr && submatch) { - /* - If the match is complete, output the match's - replacement. - */ - match = 1; - if ((strlen (newline) + strlen (rep->to) + strlen (lterm)) >= newlinelen) { - newlinelen += strlen (rep->to) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, rep->to); - strcat (newline, lterm); - if (to_ptr) { - if ((strlen (newline) + strlen (ttoken) + strlen (to_ptr)) >= newlinelen) { - newlinelen += strlen (ttoken) + strlen (to_ptr) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - strcat (newline, ttoken); - strcat (newline, tterm); - strcat (newline, to_ptr); - } - } else if (!to_ptr && submatch) { - /* - If we run out of chars from the original source, get - more. - */ - -#ifdef DEBUG_REPLACE - fprintf (stdout, " submatch = TRUE\n"); -#endif - if (eof) { - cobc_free (newline); - return pline_cnt; - } - - /* - Overwrite the current line if it is a comment or debug - line. - */ - if (is_comment_line (pline[pline_cnt], fixed)) { - adjust_line_numbers (cfile, line_num, -1); - overread = 1; + if (!line_file->line[i] && j > 0) { + while (lr->from[j] && isspace (lr->from[j])) { + ++j; } - if (is_debug_line (pline[pline_cnt], fixed, acudebug)) { - adjust_line_numbers (cfile, line_num, -1); - overread = 1; - } - - /* - Read lines until we find a non-comment, non-debug - line. - */ - next_rec: - if (!is_comment_line (pline[pline_cnt], fixed)) { - pline_cnt++; - } - abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); - if (get_next_listing_line (fd, &pline[pline_cnt], fixed) < 0) { - pline[pline_cnt][0] = 0; - eof = 1; - } - if (is_debug_line (pline[pline_cnt], fixed, acudebug) - || is_comment_line (pline[pline_cnt], fixed)) { - adjust_line_numbers (cfile, line_num, -1); - goto next_rec; - } -#ifdef DEBUG_REPLACE - fprintf (stdout, " pline[%2d]: %s\n", pline_cnt - 1, - pline[pline_cnt - 1]); -#endif - line_num++; - seccount++; - if (overread) { - overread = 0; - goto next_rec; - } - last = compare_prepare (cmp_line, pline, pline_cnt - 1, pline_cnt, - first_col, fixed); - strcat (newline, " "); - goto force_next_line; } - } else { - strcpy (from_line, rfp); -#if 0 - from_ptr = get_next_token (from_line, ftoken, fterm); -#else - (void) get_next_token (from_line, ftoken, fterm); -#endif - if (ftoken[0] == ':' || ftoken[0] == '(') { - subword = 1; - } - from_token_len = strlen (ftoken); - - /* - For each token in cmp_line, try to match it with the token in - from_line. - */ - for (to_ptr = get_next_token (cmp_line, ttoken, tterm); to_ptr; - to_ptr = get_next_token (to_ptr, ttoken, tterm)) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " tterm = '%s', ttoken = '%s', ftoken = '%s'\n", - tterm, ttoken, ftoken); -#endif - ttlen = strlen (ttoken); - ttix = 0; - if (rep->lead_trail == CB_REPLACE_LEADING) { - subword = 1; - strictmatch = rep->strict_partial; - } else if (rep->lead_trail == CB_REPLACE_TRAILING) { - if (ttlen >= from_token_len) { - subword = 1; - strictmatch = rep->strict_partial; - ttix = ttlen - from_token_len; - ttlen = ttix; - } + if (j > 0 && !lr->from[j]) { + data_replace.firstline_replace = line_start; + data_replace.lastline_replace = line_file; + if (!check_mode_trail_lead (data_replace, lr, start, i)) { + break ; } - if (subword) { - /* When strictmatch, length of word must be - strictly greater than matched token: */ - tokmatch = (!strictmatch || ttlen > from_token_len) - && !strncasecmp (&ttoken[ttix], ftoken, from_token_len); - } else { - tokmatch = !strcasecmp (ttoken, ftoken); - } - if (tokmatch) { - if ((strlen (newline) + strlen (ttoken) + strlen (rep->to)) >= newlinelen) { - newlinelen += strlen (ttoken) + strlen (rep->to) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); - } - if (subword) { - if (rep->lead_trail == CB_REPLACE_LEADING) { - strcat (newline, rep->to); - strcat (newline, &ttoken[from_token_len]); - } else if (rep->lead_trail == CB_REPLACE_TRAILING) { - strncat (newline, ttoken, ttlen); - strcat (newline, rep->to); - } else { - strcat (newline, rep->to); - } - } else { - strcat (newline, rep->to); - } - match = 1; - } else { - if ((strlen (newline) + strlen (ttoken) + strlen (tterm)) >= newlinelen) { - newlinelen += strlen (ttoken) + CB_LINE_LENGTH; - newline = cobc_realloc (newline, newlinelen); + if (lr->from[0] == ':' || lr->from[0] == '(') { + while (line_file->line[i] && !isspace (line_file->line[i])) { + ++i; } - strcat (newline, ttoken); } - strcat (newline, tterm); - } - } + data_replace.last_char = i; - if (match) { -#ifdef DEBUG_REPLACE - fprintf (stdout, " match = TRUE\n newline = %s\n", newline); -#endif - pline_cnt = reflow_replaced_text (cfile->name, pline, pline_cnt, - line_num, newline, first_col, - last, fixed); + return data_replace; + } + if (!line_file->line[i] && j > 0) { + line_file = line_file->next; + i = 0; + } else if (line_file->line[i] && line_file->line[i] != lr->from[j]) { + break ; + } } - - cobc_free (newline); - return pline_cnt; + // no match + return data_replace; } -static void -remove_replace_entries_before_line (struct list_files *cfile, const int line_num) +/* return new line_num */ +static int +search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, int pline_cnt, int line_num, \ + int fixed, int in_copy) { + int j; + int i; + int tmp_i; + int tmp_j; + int match; + int lastline_line_num; + int quotes[2] = {0, 0}; struct list_replace *rep; - - while (cfile->replace_head - && cfile->replace_head->firstline < line_num) { + t_data_replace data_replace; + + j = 0; + i = line_num; + lastline_line_num = line_num; + + int deb_line = -1; + // loop char + while (line_file->line && line_file->line[j]) { + deb_line++; + // skip the spaces in the start file + while (line_file->line[j] && isspace (line_file->line[j])) { + j++; + } + if (!line_file->line[j]) { + break ; + } + // loop list replace rep = cfile->replace_head; - cfile->replace_head = rep->next; + match = 0; + is_quotes_char (line_file->line[j], quotes); + while (rep && line_file->line[j]) { + if ((!quotes[0] && !quotes[1]) || rep->from[0] == '\'' || rep->from[0] == '"') { + data_replace = search_strstr (line_file, i, rep, j, fixed); + // Match + if (data_replace.last_char != -1) + { + // count quotes all lines except the last line + tmp_j = j; + tmp_i = i; + t_line_file *bck_line = line_file; + while (line_file && line_file != data_replace.lastline_replace) { + while (line_file->line[++j]) { + is_quotes_char (line_file->line[j], quotes); + } + ++i; + line_file = line_file->next; + j = -1; + } + lastline_line_num = i; + // and count quotes in the last line + while (++j <= data_replace.last_char) { + is_quotes_char (line_file->line[j], quotes); + } + j = tmp_j; - if (rep->from) { - cobc_free (rep->from); + if (rep->strict_partial) { + ++j; + while (line_file->line[j] && !isspace (line_file->line[j])) { + ++j; + } + if (j - 1 == tmp_j) { + rep = rep->next; + continue; + } + j = tmp_j; + } + i = tmp_i; + line_file = bck_line; + // stock first line in tmp and clean other line in the multiple line replace + replace_value (line_file, data_replace, rep, j, fixed, in_copy); + + line_file = data_replace.firstline_replace; + j = data_replace.last_char; + while(line_file->line[j] && !isspace (line_file->line[j])) { + ++j; + } + match = 1; + } + } + rep = rep->next; } - if (rep->to) { - cobc_free (rep->to); + if (!match) { + j++; } - cobc_free (rep); } + return lastline_line_num - line_num + 1; } static void @@ -7557,6 +7378,43 @@ cleanup_copybook_reference (struct list_files *cur) cobc_free (cur); } +static +char *get_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (isspace (str[i])) { + ++i; + } + if (str + i) { + return str + i; + } + return NULL; +} + +static +char *get_next_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (!isspace (str[i])) { + ++i; + } + while (isspace (str[i])) { + ++i; + } + if (str + i) { + return str + i; + } + return NULL; +} + /* TO-DO: Modularise! */ /* @@ -7565,48 +7423,31 @@ cleanup_copybook_reference (struct list_files *cur) */ static int print_replace_main (struct list_files *cfile, FILE *fd, - char *pline[CB_READ_AHEAD], int pline_cnt, int line_num) + t_line_file *line_file, int pline_cnt, int line_num) { - static int active_replace_stmt = 0; - char *to_ptr; + char *ptr; + int is_copy_line; + int is_replace_line; + int is_replace_off = 0; struct list_replace *rep; - struct list_files *cur; - int i; - const int fixed = CB_SF_FIXED (cfile->source_format); - const int first_col = fixed ? cobc_get_margin_a (1) : 0; - int is_copy_line; - int is_replace_line; - int is_replace_off = 0; - char tterm[2] = { '\0' }; - char ttoken[CB_LINE_LENGTH + 2] = { '\0' }; - char cmp_line[CB_LINE_LENGTH + 2] = { '\0' }; - - if (is_comment_line (pline[0], ! CB_SF_FREE (cfile->source_format))) { + static int active_replace_stmt = 0; + const int fixed = (cfile->source_format == CB_FORMAT_FIXED); + + if (is_comment_line (line_file->line, cfile->source_format != CB_FORMAT_FREE)) { return pline_cnt; } -#ifdef DEBUG_REPLACE - fprintf (stdout, "print_replace_main: line_num = %d\n", line_num); - fprintf (stdout, " pline_cnt = %d\n", pline_cnt); - for (i = 0; i < pline_cnt; i++) { - fprintf (stdout, " pline[%2d]: %s\n", i, pline[i]); + rep = cfile->replace_head; + if (!rep) { + return pline_cnt; } -#endif - - compare_prepare (cmp_line, pline, 0, pline_cnt, first_col, - ! CB_SF_FREE (cfile->source_format)); - /* Check whether we're given a COPY or REPLACE statement. */ - to_ptr = get_next_token (cmp_line, ttoken, tterm); - 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 = !cb_strcasecmp (ttoken, "OFF"); + ptr = get_word (line_file->line); + is_copy_line = !strncmp (ptr, "COPY", strlen("COPY")); + is_replace_line = !strncmp (ptr, "REPLACE", strlen("REPLACE")); + if (is_replace_line && ptr) { + ptr = get_next_word (ptr); + is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); } /* @@ -7631,14 +7472,9 @@ print_replace_main (struct list_files *cfile, FILE *fd, } else if (active_replace_stmt) { if (is_replace_line && is_replace_off) { active_replace_stmt = 0; - remove_replace_entries_before_line (cfile, line_num); } else if (is_copy_line) { if (cfile->copy_head) { - /* List all lines read so far and then discard them. */ - for (i = 0; i < pline_cnt; i++) { - print_line (cfile, pline[i], line_num + i, 0); - pline[i][0] = 0; - } + struct list_files *cur; cur = cfile->copy_head; @@ -7650,26 +7486,93 @@ print_replace_main (struct list_files *cfile, FILE *fd, deep_copy_list_replace (rep, cur); } } - print_program (cur, 1); - - /* Delete the copybook reference when done */ - cfile->copy_head = cur->next; - cleanup_copybook_reference (cur); } } else { - /* Print text with replacements */ - for (rep = cfile->replace_head; - rep && rep->firstline < line_num; - rep = rep->next) { - pline_cnt = print_replace_text (cfile, fd, rep, pline, - pline_cnt, line_num); + while (rep) { + if (line_num >= rep->firstline - 1 && line_num <= rep->lastline - 1) { + return pline_cnt; + } + rep = rep->next; } + pline_cnt = search_and_apply_replacement (cfile, line_file, pline_cnt, line_num, fixed, 0); } } - return pline_cnt; } + +static int +print_program_code_apply (struct list_files *cfile, int fixed, int in_copy, + int *pline_cnt, int *i, int *line_num, int lines_read, t_line_file *line_file, \ + int *line_replace, FILE *fd + ) +{ + struct list_replace *rep; + + *pline_cnt = 1; + + if (!line_file->line) { + return lines_read; + } + + /* handling for preprocessed directives */ + if (line_file->line[0] == '#') { + /* Set line number as specified by #line directive. */ + if (!strncmp (line_file->line, "#line ", 6)) { + *line_num = atoi (&line_file->line[6]); + /* CHECKME: read the filename if given, too */ + } + lines_read = -1; + return -1; + } + /* Perform text replacement on the lines. */ + if (!in_copy) { + *pline_cnt = print_replace_main (cfile, fd, line_file, *pline_cnt, + *i); + } else if (cfile->replace_head) { + *pline_cnt = search_and_apply_replacement (cfile, line_file, *pline_cnt, *i, fixed, in_copy); + } + + /* Print each line except the last. */ + for (int idx = *i; idx < *i + (*pline_cnt) && line_file; idx++) { + if (line_file->line) { + print_line (cfile, line_file->line, *line_num, in_copy); + lines_read++; + } + line_file = line_file->next; + } + + /* Output copybooks which are COPY'd at the current line */ + if (cfile->copy_head + && cfile->copy_head->copy_line == *line_num) { + struct list_files *cur = cfile->copy_head; + /* Add the current text replacements to the copybook */ + for (rep = cfile->replace_head; rep && in_copy; + rep = rep->next) { + deep_copy_list_replace (rep, cur); + } + print_program (cur, 1); + /* Delete the copybook reference when done */ + cfile->copy_head = cur->next; + cleanup_copybook_reference (cur); + } + return lines_read; +} + +static t_line_file +*add_new_line(t_line_file *last, char *str) +{ + if (!last) { + last = cobc_malloc (sizeof (t_line_file)); + } else { + last->next = cobc_malloc (sizeof (t_line_file)); + last = last->next; + } + last->line = strdup (str); + last->next = NULL; + return last; +} + /* Print the listing for the file in cfile, with copybooks expanded and after text has been REPLACE'd. @@ -7681,58 +7584,21 @@ static void print_program_code (struct list_files *cfile, int in_copy) { FILE *fd = NULL; - struct list_replace *rep; - struct list_files *cur; struct list_error *err; int i; int line_num = 1; + int line_replace = 0; const int fixed = CB_SF_FIXED (cfile->source_format); - const int indicator = cobc_get_indicator (); int eof = 0; int pline_cnt = 0; char *pline[CB_READ_AHEAD] = { NULL }; int lines_read; + t_line_file *line_file = NULL; + t_line_file *head_line_file = NULL; + int cnt_line = -1; cfile->listing_on = 1; -#ifdef DEBUG_REPLACE - struct list_skip *skip; - - fprintf (stdout, "print_program_code: in_copy = %s\n", - in_copy ? "YES" : "NO"); - fprintf (stdout, " name: %s\n", cfile->name); - fprintf (stdout, " copy_line: %d\n", cfile->copy_line); - for (i = 0, cur = cfile->copy_head; cur; i++, cur = cur->next) { - if (i == 0) { - fprintf (stdout, " copy_books: \n"); - } - fprintf (stdout, " name[%d]: %s\n", i, cur->name); - fprintf (stdout, " line[%d]: %d\n", i, cur->copy_line); - } - for (i = 0, rep = cfile->replace_head; rep; i++, rep = rep->next) { - if (i == 0) { - fprintf (stdout, " replace_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, rep->firstline); - fprintf (stdout, " from[%d]:%lu: '%80.80s'\n", i, strlen(rep->from), rep->from); - fprintf (stdout, " to [%d]:%lu: '%80.80s'\n", i, strlen(rep->to), rep->to); - } - for (i = 0, err = cfile->err_head; err; i++, err = err->next) { - if (i == 0) { - fprintf (stdout, " error_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, err->line); - fprintf (stdout, " pref[%d]: '%s'\n", i, err->prefix); - fprintf (stdout, " msg [%d]: '%s'\n", i, err->msg); - } - for (i = 0, skip = cfile->skip_head; skip; i++, skip = skip->next) { - if (i == 0) { - fprintf (stdout, " skip_list: \n"); - } - fprintf (stdout, " line[%d]: %d\n", i, skip->skipline); - } -#endif - if (cfile->name) { fd = fopen (cfile->name, "r"); } @@ -7744,79 +7610,79 @@ print_program_code (struct list_files *cfile, int in_copy) if (get_next_listing_line (fd, &pline[pline_cnt + 1], fixed) < 0) { eof = 1; } - pline_cnt++; - lines_read = 0; - - /* Collect all adjacent continuation lines */ - if (is_continuation_line (pline[fixed ? pline_cnt : pline_cnt - 1], - ! CB_SF_FREE (cfile->source_format))) { - continue; - } - /* handling for preprocessed directives */ - if (pline[0][0] == '#') { - /* Set line number as specified by #line directive. */ - if (!strncmp (pline[0], "#line ", 6)) { - line_num = atoi (&pline[0][6]); - /* CHECKME: read the filename if given, too */ - } - lines_read = -1; - } - - /* Perform text replacement on the lines. */ - if (!in_copy) { - pline_cnt = print_replace_main (cfile, fd, pline, pline_cnt, - line_num); - } else if (cfile->replace_head) { - rep = cfile->replace_head; - while (rep) { - pline_cnt = print_replace_text (cfile, fd, rep, pline, - pline_cnt, line_num); - rep = rep->next; - } - } - - /* Print each line except the last. */ - for (i = 0; i < pline_cnt; i++) { - if (pline[i][0]) { - if (fixed && pline[i][indicator] == '&') { - print_line (cfile, pline[i], line_num, in_copy); - } else { - print_line (cfile, pline[i], line_num + i, in_copy); - lines_read++; - } - } - } - - /* Output copybooks which are COPY'd at the current line */ - if (cfile->copy_head - && cfile->copy_head->copy_line == line_num) { - - cur = cfile->copy_head; - - /* Add the current text replacements to the copybook */ - for (rep = cfile->replace_head; rep && in_copy; - rep = rep->next) { - deep_copy_list_replace (rep, cur); - } - print_program (cur, 1); - - /* Delete the copybook reference when done */ - cfile->copy_head = cur->next; - cleanup_copybook_reference (cur); + ++pline_cnt; + char cmp_line[CB_LINE_LENGTH + 2]; + int first_col = fixed ? cobc_get_margin_a (1) : 0; + compare_prepare (cmp_line, pline, 0, 1, first_col, fixed); + line_file = add_new_line(line_file, cmp_line); + if (!head_line_file) { + head_line_file = line_file; } + ++line_replace; + ++cnt_line; /* Delete all but the last line. */ strcpy (pline[0], pline[pline_cnt]); for (i = 1; i < pline_cnt + 1; i++) { + // abort_if_too_many_continuation_lines (i, cfile->name, line_num); ajouter par moi le 02/11 ne fonctionne pas memset (pline[i], 0, CB_LINE_LENGTH); } - line_num += lines_read; pline_cnt = 0; if (pline[0][0] == 0) { eof = 1; } } while (!eof); + + line_num = 1; + i = 0; + pline_cnt = 0; + line_file = head_line_file; + + char space[2] = {' ', 0}; + // search replacement and print + while (i < line_replace) { + pline_cnt++; + lines_read = 0; + // if line is empty, just print + if (!line_file->line || strcmp (line_file->line, "") == 0) { + print_line (cfile, space, line_num, in_copy); + line_file = line_file->next; + i++; + line_num++; + continue ; + } + + // search replacement + lines_read = print_program_code_apply (cfile, fixed, in_copy, &pline_cnt, \ + &i, &line_num, lines_read, line_file, &line_replace, fd); + + if (lines_read > 0) { + // if edit is current don't print + line_num += lines_read; + i += lines_read; + while (line_file && lines_read > 0) { + line_file = line_file->next; + lines_read--; + } + } else { + print_line (cfile, line_file->line, line_num, in_copy); + line_file = line_file->next; + i++; + } + pline_cnt = 0; + } + + line_file = head_line_file; + // free pline_replace + t_line_file *next; + while (line_file) { + cobc_free (line_file->line); + line_file->line = NULL; + next = line_file->next; + cobc_free(line_file); + line_file = next; + } } fclose (fd); diff --git a/cobc/codegen.c b/cobc/codegen.c index 61b3ee4b6..a59e5c733 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -9887,6 +9887,21 @@ output_report_control (struct cb_report *p, int id, cb_tree ctl, cb_tree nx) if(nx) { output_report_control(p, id, nx, CB_CHAIN(nx)); } + bfound = 0; + for(i= p->num_lines-1; i >= 0; i--) { + if(p->line_ids[i]->report_control) { + struct cb_field *c = cb_code_field (p->line_ids[i]->report_control); + if(c == s) { + bfound = 1; + break; + } + } + } + if (!bfound) { + ctl = NULL; + p->controls = NULL; + return ; + } output_local("/* Report %s: CONTROL %s */\n",p->name,s->name); prvid = 0; for(i = 0; i < p->num_lines; i++) { diff --git a/cobc/tree.h b/cobc/tree.h index 3649e42ae..dfc4226e1 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -1658,6 +1658,17 @@ struct list_error { char *msg; /* Error Message text */ }; +typedef struct s_line_file { + char *line; + struct s_line_file *next; +} t_line_file; + +typedef struct s_data_replace { + t_line_file *firstline_replace; + t_line_file *lastline_replace; + int last_char; +} t_data_replace; + /* List of REPLACE text blocks */ struct list_replace { struct list_replace *next; diff --git a/tests/ChangeLog b/tests/ChangeLog index aa1608f63..c32bac7da 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,9 @@ +2023-07-20 Samuel Belondrade + + * testsuite.src/listing.at: add test for the copy replacing in + listing mode (bug: #831) + 2023-07-10 Simon Sobisch * atlocal_win: updated to current atlocal.in diff --git a/tests/testsuite.src/listings.at b/tests/testsuite.src/listings.at index 90d1a0e0c..762ab92e0 100644 --- a/tests/testsuite.src/listings.at +++ b/tests/testsuite.src/listings.at @@ -269,6 +269,31 @@ AT_CLEANUP AT_SETUP([COPY replacement with partial match]) AT_KEYWORDS([listing copy]) +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy.inc" REPLACING ==TEST-VAR== BY ==TEST-AVR== +000008 == 02 TEST-EE == BY == 02 TEST-FF ==. +000001C +000002C 02 TEST-AVR PIC X(2) VALUE "OK". +000003C 02 TEST-CC PIC X(4) VALUE "OK 2". +000009 PROCEDURE DIVISION. +000010 DISPLAY TEST-AVR. +000011 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". 02 TEST-CC PIC X(4) VALUE "OK 2". @@ -318,6 +343,42 @@ AT_CLEANUP AT_SETUP([COPY replacement with multiple partial matches]) AT_KEYWORDS([listing copy]) +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. prog. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 01 GET-VALUE. +000007 COPY "copy.inc" REPLACING +000008 LEADING ==TEST-VAR== BY ==TEST-AVR== +000009 == 02 TEST-OK == BY == 02 TEST-KO == +000010 ==TEST-CC== BY ==TEST-DD== +000011 == 02 TEST-EE == BY == 02 TEST-FF == +000012 == PIC == BY == pic ==. +000001C +000002C 02 TEST-AVR pic X(2) VALUE "OK". +000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". +000004C 02 TEST-DD pic X(4) VALUE "OK 2". +000005C 02 TEST-KO pic X(4) VALUE "OK 3". +000006C 02 TEST-FF pic X(4) VALUE "OK 4". +000013 PROCEDURE DIVISION. +000014 DISPLAY TEST-AVR. +000015 DISPLAY TEST-AVR-BIS. +000016 DISPLAY TEST-KO. +000017 DISPLAY TEST-DD. +000018 DISPLAY TEST-FF. +000019 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". 02 TEST-VAR-BIS PIC X(6) VALUE "OK BIS". @@ -513,6 +574,81 @@ LINE PG/LN A...B............................................................ AT_CLEANUP +AT_SETUP([Multiple replacement]) +AT_KEYWORDS([listing symbols]) + +AT_DATA([copy.inc], [ + 01 A1000B-AA. + 03 A1000B2-BB PIC X(5). + 03 A1000B2-CC PIC X(5). + 03 A1000B2-DD PIC X(5). + 03 A1000B2-EE PIC X(5). + 03 A1000B2-FF PIC X(5). + 03 A1000B2-GG PIC X(5). +]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLO-WORLD. + DATA DIVISION. + WORKING-STORAGE SECTION. + COPY "copy.inc" REPLACING LEADING ==A1000B== BY ==B2000B== + == 03 A1000B2-CC PIC X(5). + 03 A1000B2-DD PIC X(5). + 03 A1000B2-EE PIC X(5). == + BY == 03 B2000B2-CC1 PIC X(5). + 03 B2000B2-DD1 PIC X(5). + 03 B2000B2-EE PIC X(5). + 03 B2000B2-TEST PIC 9(1). + 03 B2000B2-TEST2 PIC X(1). ==. + PROCEDURE DIVISION. + DISPLAY 'Hello, world'. + STOP RUN. +]) + +AT_DATA([expected.lst], +[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY + +LINE PG/LN A...B............................................................ + +000001 +000002 IDENTIFICATION DIVISION. +000003 PROGRAM-ID. HELLO-WORLD. +000004 DATA DIVISION. +000005 WORKING-STORAGE SECTION. +000006 COPY "copy.inc" REPLACING LEADING ==A1000B== BY ==B2000B== +000007 == 03 A1000B2-CC PIC X(5). +000008 03 A1000B2-DD PIC X(5). +000009 03 A1000B2-EE PIC X(5). == +000010 BY == 03 B2000B2-CC1 PIC X(5). +000011 03 B2000B2-DD1 PIC X(5). +000012 03 B2000B2-EE PIC X(5). +000013 03 B2000B2-TEST PIC 9(1). +000014 03 B2000B2-TEST2 PIC X(1). ==. +000001C +000002C 01 B2000B-AA. +000003C 03 B2000B2-BB PIC X(5). +000004C 03 B2000B2-CC1 PIC X(5). 03 B2000B2-DD1 PIC X(5). 03 +000004+ - B2000B2-EE PIC X(5). 03 B2000B2-TEST PIC 9(1). 03 +000004+ - B2000B2-TEST2 PIC X(1). +000004C +000004C +000007C 03 B2000B2-FF PIC X(5). +000008C 03 B2000B2-GG PIC X(5). +000015 PROCEDURE DIVISION. +000016 DISPLAY 'Hello, world'. +000017 STOP RUN. + + +0 warnings in compilation group +0 errors in compilation group +]) + +AT_CHECK([$COMPILE_ONLY -t prog.lst -tlines=0 prog.cob], [0], [], []) +AT_CHECK([$UNIFY_LISTING prog.lst prog.lis once], [0], [], []) +AT_CHECK([diff expected.lst prog.lis], [0], [], []) + +AT_CLEANUP AT_SETUP([COPY replacement order]) AT_KEYWORDS([listing symbols]) diff --git a/tests/testsuite.src/run_reportwriter.at b/tests/testsuite.src/run_reportwriter.at index 2ff781a44..707220749 100644 --- a/tests/testsuite.src/run_reportwriter.at +++ b/tests/testsuite.src/run_reportwriter.at @@ -9626,3 +9626,48 @@ BEFORE FINAL - SHOULD DISPLAY AT_CLEANUP +AT_SETUP([Check if the variable is referenced in the report]) +AT_KEYWORDS([report]) + +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. MAIN. + ENVIRONMENT DIVISION. + CONFIGURATION SECTION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT A_1 ASSIGN TO EXTERNAL A_1. + SELECT A_2 ASSIGN TO EXTERNAL A_2. + DATA DIVISION. + FILE SECTION. + FD A_1. + COPY test. + FD A_2 REPORT ETAT. + WORKING-STORAGE SECTION. + REPORT SECTION. + RD ETAT + CONTROL FINAL ERROR-1 ERROR-2 + PAGE LIMIT 66. + PROCEDURE DIVISION. + STOP RUN. +]) + +AT_DATA([test.cpy], [ + 01 TEST-01. + 03 TEST-03. + 88 TEST-88 VALUE "0000000". + 09 ERROR-1. + 88 E-TEST-1 VALUE "111". + 10 E-TEST-10 PIC 9(3). + 03 E-TEST-03. + 04 E-TEST-04. + 05 FILLER PIC X(21). + 88 E-TEST-2 VALUE " SM". + 03 E-TEST-2-03. + 09 ERROR-2 PIC 9(3). +]) + +AT_CHECK([$COMPILE prog.cob], [0], [], []) + +AT_CLEANUP + From 67e9554e94b0e7845537c730f185b0c7725ae767 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Fri, 21 Jul 2023 14:53:57 +0200 Subject: [PATCH 06/10] fix error in the listing mode --- cobc/cobc.c | 270 ++++++++++++++++++++++---------- cobc/tree.h | 11 -- tests/testsuite.src/listings.at | 2 +- tests/testsuite.src/syn_copy.at | 12 +- 4 files changed, 193 insertions(+), 102 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index d6a0d1a8e..201930661 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -78,6 +78,17 @@ struct strcache { void *val; }; +typedef struct s_line_file { + char *line; + struct s_line_file *next; +} t_line_file; + +typedef struct s_data_replace { + t_line_file *firstline_replace; + t_line_file *lastline_replace; + int last_char; +} t_data_replace; + /* Compile level */ enum compile_level { CB_LEVEL_UNSET = 0, @@ -6638,9 +6649,6 @@ print_fixed_line (const int line_num, char pch, char *line) const int indicator = cobc_get_indicator (); const int text_column = cobc_get_text_column (); - if (!line) { - return ; - } len = strlen (line); if (line[indicator] == '&') { line[indicator] = '-'; @@ -6665,13 +6673,13 @@ print_fixed_line (const int line_num, char pch, char *line) } static int -is_quotes_char (char c, int quotes[2]) +is_quotes_char (char c, int *simple_quote, int *double_quote) { if (c == '\'') { - quotes[0] = !quotes[0]; + *simple_quote = !(*simple_quote); } else if (c == '"') { - quotes[1] = !quotes[1]; + *double_quote = !(*double_quote); } else { return 0; } @@ -6688,15 +6696,16 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) int start = 0; const int max_chars_on_line = cb_listing_wide ? 112 : 72; char dst[max_chars_on_line + 1]; - int quotes[2] = {0, 0}; + int simple_quote = 0; + int double_quote = 0; int margin_b = cobc_get_margin_b (1); int indicator = cobc_get_indicator (); int last_word; - bzero (dst, max_chars_on_line + 1); + memset (dst, 0, max_chars_on_line + 1); memset (dst, ' ', margin_b); - // skip space + /* skip space */ while (isspace (line[i])) ++i; start = i; @@ -6704,36 +6713,58 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) while (line[i]) { - // loop space - while (line[i] && isspace (line[i]) && NOT_TOO_LONG (i, start)) { + /* loop space */ + while (line[i] && isspace (line[i]) && !is_quotes_char (line[i], &simple_quote, &double_quote) && NOT_TOO_LONG (i, start)) { ++i; } last_word = i; - // loop chars - if (NOT_TOO_LONG (i, start)) { - while (line[i] && !is_quotes_char (line[i], quotes) && !isspace (line[i])) { + /* loop chars */ + if (NOT_TOO_LONG (i, start) && !is_quotes_char (line[i], &simple_quote, &double_quote)) { + while (line[i] && !isspace (line[i]) && !is_quotes_char (line[i], &simple_quote, &double_quote)) { ++i; } } - // check quotes - if (line[i] && NOT_TOO_LONG (i, start) && (quotes[0] || quotes[1])) { + /* check quotes */ + if (line[i] && NOT_TOO_LONG (i, start) && (simple_quote || double_quote)) { last_word = i; ++i; - while (line[i] && !is_quotes_char (line[i], quotes) && NOT_TOO_LONG (i, start)) { + while (line[i] && !is_quotes_char (line[i], &simple_quote, &double_quote) ) { ++i; } ++i; + if (i - last_word > max_chars_on_line) { + last_word = i; + } } - // print line + /* print line */ if (!NOT_TOO_LONG (i, start)) { if (last_word == -1) { last_word = i; } - strncpy (dst + margin_b, line + start, last_word - start); - print_fixed_line (line_num, pch, dst); + if (last_word - start > max_chars_on_line - margin_b) { + while (last_word - start > max_chars_on_line - margin_b) { + strncpy (dst + margin_b, line + start, max_chars_on_line - margin_b); + dst[max_chars_on_line] = 0; + + print_fixed_line (line_num, pch, dst); + start += max_chars_on_line - margin_b; + memset (dst, 0, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } + if (last_word - start > 0) { + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + } + } else { + strncpy (dst + margin_b, line + start, last_word - start); + print_fixed_line (line_num, pch, dst); + + } start = last_word; last_word = -1; - bzero (dst, max_chars_on_line + 1); + memset (dst, 0, max_chars_on_line + 1); margin_b = cobc_get_margin_b (1); memset (dst, ' ', margin_b); dst[indicator] = '&'; @@ -6741,11 +6772,24 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) last_word = i; } } - // print last line + /* print last line */ if (start < i) { - strncpy (dst + margin_b, line + start, i - start); - dst[margin_b + i - start] = 0; - print_fixed_line (line_num, pch, dst); + while (i - start > max_chars_on_line - margin_b) { + strncpy (dst + margin_b, line + start, max_chars_on_line - margin_b); + dst[max_chars_on_line] = 0; + print_fixed_line (line_num, pch, dst); + + start += max_chars_on_line - margin_b; + memset (dst, 0, max_chars_on_line + 1); + margin_b = cobc_get_margin_b (1); + memset (dst, ' ', margin_b); + dst[indicator] = '&'; + } + if (start < i) { + strncpy (dst + margin_b, line + start, i - start); + dst[margin_b + i - start] = 0; + print_fixed_line (line_num, pch, dst); + } } } @@ -6757,7 +6801,7 @@ print_fixed_line_mode (const int line_num, char pch, char *line) int i = 0; const int max_chars_on_line = cb_listing_wide ? 112 : 72; - if (strlen(line) <= max_chars_on_line) { + if (strlen (line) <= max_chars_on_line) { while (isspace (*(line + i))) { i++; } @@ -6839,7 +6883,6 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) struct list_skip *skip; int do_print; int on_off; - char pch; do_print = cfile->listing_on; @@ -6860,7 +6903,7 @@ print_line (struct list_files *cfile, char *line, int line_num, int in_copy) } if (do_print) { - pch = in_copy ? 'C' : ' '; + char pch = in_copy ? 'C' : ' '; for (skip = cfile->skip_head; skip; skip = skip->next) { if (skip->skipline == line_num) { pch = 'X'; @@ -6913,9 +6956,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], int last_nonspace; const int max_chars_on_line = cb_listing_wide ? 112 : 72; - cmp_line[0] = 0; - bzero (cmp_line, CB_LINE_LENGTH + 2); - /* Collapse pline into a string of tokens separated by spaces */ last_nonspace = last_col; i = 0; @@ -7010,7 +7050,7 @@ is_comment_line (char *line, int fixed) } } -static void +static COB_INLINE COB_A_INLINE void abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) { if (pline_cnt >= CB_READ_AHEAD) { @@ -7064,7 +7104,7 @@ strncpy_listing (char *dst, char *src, int n, int first, int in_copy, int is_new } /* Replace line by the new value for the listing mode */ -static void +static int replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_replace *lr, int pos, int fixed, int in_copy) { char *dst; @@ -7075,8 +7115,9 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ int last_cpy = 0; int first = 1; t_line_file *bck_line = line_file; + int stock_new_last_char; - // calculation the len char + /* calculation the len char */ len_to = strlen (lr->to); while (line_file && line_file != data_replace.lastline_replace) { @@ -7091,29 +7132,30 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ dst = cobc_malloc (len_new_line); line_file = bck_line; - // copy first line + /* copy the first line */ if (pos > 0) { last_cpy = strncpy_listing (dst, line_file->line, pos, first, in_copy, 0); first = 0; } - // copy new str + /* copy the new str */ last_cpy += strncpy_listing (dst + last_cpy, lr->to, len_to, first, in_copy, 1); + stock_new_last_char = last_cpy; first = 0; while (line_file && line_file != data_replace.lastline_replace) { line_file = line_file->next; } - // copy end line + /* copy the end line */ if (line_file && len_end_line > 0) { strncpy_listing (dst + last_cpy, line_file->line + data_replace.last_char, len_end_line, first, in_copy, 0); } - // stock result in the first line + /* stock the result in the first line */ line_file = bck_line; cobc_free (line_file->line); line_file->line = NULL; line_file->line = dst; - // free other line if it's multi replace line + /* free the other line if it's a multi replace of line */ if (line_file != data_replace.lastline_replace) { line_file = line_file->next; do { @@ -7121,7 +7163,7 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ { cobc_free (line_file->line); line_file->line = NULL; - line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line = cobc_malloc (sizeof(char *) * 2); line_file->line[0] = ' '; line_file->line[1] = 0; } @@ -7132,19 +7174,20 @@ replace_value (t_line_file *line_file, t_data_replace data_replace, struct list_ { cobc_free (line_file->line); line_file->line = NULL; - line_file->line = cobc_malloc(sizeof(char *) * 2); + line_file->line = cobc_malloc (sizeof(char *) * 2); line_file->line[0] = ' '; line_file->line[1] = 0; } } line_file = bck_line; } + return stock_new_last_char; } static int condition_leading (char *line, int start) { - if (start == 0 || isspace (line[start - 1])) + if (start == 0 || (isspace (line[start - 1]) || isspace (line[start]))) return 1; return 0; } @@ -7193,13 +7236,10 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, { const int is_simple_quote = lr->from[0] == '\''; t_line_file *line_start = line_file; - t_data_replace data_replace = init_data_replace(); + t_data_replace data_replace = init_data_replace (); int i = start; int j = 0; - while (lr->from[j] && isspace (lr->from[j])) { - ++j; - } while (line_file && line_file->line && line_file->line[i]) { if (is_comment_line (line_file->line, fixed)) { ++line; @@ -7222,6 +7262,7 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, ++j; } } + if (!line_file->line[i] && j > 0) { while (lr->from[j] && isspace (lr->from[j])) { ++j; @@ -7233,6 +7274,7 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, if (!check_mode_trail_lead (data_replace, lr, start, i)) { break ; } + if (lr->from[0] == ':' || lr->from[0] == '(') { while (line_file->line[i] && !isspace (line_file->line[i])) { ++i; @@ -7249,7 +7291,7 @@ search_strstr (t_line_file *line_file, int line, struct list_replace *lr, break ; } } - // no match + /* no match */ return data_replace; } @@ -7258,57 +7300,61 @@ static int search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, int pline_cnt, int line_num, \ int fixed, int in_copy) { - int j; + int j; int i; int tmp_i; int tmp_j; - int match; - int lastline_line_num; - int quotes[2] = {0, 0}; + int match; + int lastline_line_num; + int simple_quote = 0; + int double_quote = 0; struct list_replace *rep; t_data_replace data_replace; + int deb_line = -1; j = 0; i = line_num; lastline_line_num = line_num; - int deb_line = -1; - // loop char + /* loop char */ while (line_file->line && line_file->line[j]) { deb_line++; - // skip the spaces in the start file + /* skip the spaces in the start file */ while (line_file->line[j] && isspace (line_file->line[j])) { j++; } if (!line_file->line[j]) { break ; } - // loop list replace + /* loop list replace */ rep = cfile->replace_head; match = 0; - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); while (rep && line_file->line[j]) { - if ((!quotes[0] && !quotes[1]) || rep->from[0] == '\'' || rep->from[0] == '"') { + if ((!simple_quote && !double_quote) || rep->from[0] == '\'' || rep->from[0] == '"') { data_replace = search_strstr (line_file, i, rep, j, fixed); - // Match + /* Match */ if (data_replace.last_char != -1) { - // count quotes all lines except the last line + /* count quotes all lines except the last line */ + t_line_file *bck_line = line_file; + int stock_new_last_char; + tmp_j = j; tmp_i = i; - t_line_file *bck_line = line_file; + while (line_file && line_file != data_replace.lastline_replace) { while (line_file->line[++j]) { - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); } ++i; line_file = line_file->next; j = -1; } lastline_line_num = i; - // and count quotes in the last line + /* and count quotes in the last line */ while (++j <= data_replace.last_char) { - is_quotes_char (line_file->line[j], quotes); + is_quotes_char (line_file->line[j], &simple_quote, &double_quote); } j = tmp_j; @@ -7325,8 +7371,9 @@ search_and_apply_replacement (struct list_files *cfile, t_line_file *line_file, } i = tmp_i; line_file = bck_line; - // stock first line in tmp and clean other line in the multiple line replace - replace_value (line_file, data_replace, rep, j, fixed, in_copy); + /* stock first line in tmp and clean other line in the multiple line replace */ + stock_new_last_char = replace_value (line_file, data_replace, rep, j, fixed, in_copy); + data_replace.last_char = stock_new_last_char - 1; line_file = data_replace.firstline_replace; j = data_replace.last_char; @@ -7369,7 +7416,7 @@ deep_copy_list_replace (struct list_replace *src, struct list_files *dst_file) dst_file->replace_tail = copy; } -static void +static COB_INLINE COB_A_INLINE void cleanup_copybook_reference (struct list_files *cur) { if (cur->name) { @@ -7436,18 +7483,21 @@ print_replace_main (struct list_files *cfile, FILE *fd, if (is_comment_line (line_file->line, cfile->source_format != CB_FORMAT_FREE)) { return pline_cnt; } + ptr = get_word (line_file->line); rep = cfile->replace_head; - if (!rep) { + if (!rep || !ptr) { return pline_cnt; } - ptr = get_word (line_file->line); is_copy_line = !strncmp (ptr, "COPY", strlen("COPY")); is_replace_line = !strncmp (ptr, "REPLACE", strlen("REPLACE")); + if (is_replace_line && ptr) { ptr = get_next_word (ptr); - is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); + if (ptr) { + is_replace_off = !strncmp (ptr, "OFF", strlen("OFF")); + } } /* @@ -7559,8 +7609,8 @@ print_program_code_apply (struct list_files *cfile, int fixed, int in_copy, return lines_read; } -static t_line_file -*add_new_line(t_line_file *last, char *str) +static t_line_file * +add_new_line(t_line_file *last, char *str) { if (!last) { last = cobc_malloc (sizeof (t_line_file)); @@ -7573,6 +7623,48 @@ static t_line_file return last; } +/* find the last line of replace */ +static void +search_end_replace (t_line_file *line_file, struct list_files *cfile) +{ + const int sz_equal = 2; + const int start_replace = cfile->copy_head->copy_line; + int idx_line; + + for (idx_line = 1; idx_line < start_replace && line_file; idx_line++) { + line_file = line_file->next; + } + + while (line_file) { + if (line_file->line) { + char *value = line_file->line; + while ((value = strstr (value, "=="))) { + int j = sz_equal; + t_line_file *head = line_file; + int is_not_here = 0; + + while (line_file && !is_not_here) { + while (value[j]) { + if (value[j] == '.') { + cfile->copy_head->copy_line = idx_line; + return ; + } else if (!isspace (value[j])) { + is_not_here = 1; + break ; + } + ++j; + } + line_file = line_file->next; + } + line_file = head; + value = value + sz_equal; + } + } + ++idx_line; + line_file = line_file->next; + } +} + /* Print the listing for the file in cfile, with copybooks expanded and after text has been REPLACE'd. @@ -7605,26 +7697,32 @@ print_program_code (struct list_files *cfile, int in_copy) if (fd != NULL) { abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); if (get_next_listing_line (fd, &pline[pline_cnt], fixed) >= 0) { + char space[2] = {' ', 0}; + t_line_file *next; + do { + char cmp_line[CB_LINE_LENGTH + 2]; + int first_col = fixed ? cobc_get_margin_a (1) : 0; + abort_if_too_many_continuation_lines (pline_cnt, cfile->name, line_num); if (get_next_listing_line (fd, &pline[pline_cnt + 1], fixed) < 0) { eof = 1; } ++pline_cnt; - char cmp_line[CB_LINE_LENGTH + 2]; - int first_col = fixed ? cobc_get_margin_a (1) : 0; + + memset (cmp_line, 0, CB_LINE_LENGTH + 2); compare_prepare (cmp_line, pline, 0, 1, first_col, fixed); - line_file = add_new_line(line_file, cmp_line); + line_file = add_new_line (line_file, cmp_line); if (!head_line_file) { head_line_file = line_file; } + ++line_replace; ++cnt_line; /* Delete all but the last line. */ strcpy (pline[0], pline[pline_cnt]); for (i = 1; i < pline_cnt + 1; i++) { - // abort_if_too_many_continuation_lines (i, cfile->name, line_num); ajouter par moi le 02/11 ne fonctionne pas memset (pline[i], 0, CB_LINE_LENGTH); } @@ -7634,17 +7732,22 @@ print_program_code (struct list_files *cfile, int in_copy) } } while (!eof); + if (cfile->copy_head) { + line_file = head_line_file; + search_end_replace (line_file, cfile); + } + + line_file = head_line_file; + line_num = 1; i = 0; pline_cnt = 0; - line_file = head_line_file; - char space[2] = {' ', 0}; - // search replacement and print + /* search replacement and print */ while (i < line_replace) { pline_cnt++; lines_read = 0; - // if line is empty, just print + /* if line is empty, just print */ if (!line_file->line || strcmp (line_file->line, "") == 0) { print_line (cfile, space, line_num, in_copy); line_file = line_file->next; @@ -7653,12 +7756,12 @@ print_program_code (struct list_files *cfile, int in_copy) continue ; } - // search replacement + /* search replacement */ lines_read = print_program_code_apply (cfile, fixed, in_copy, &pline_cnt, \ &i, &line_num, lines_read, line_file, &line_replace, fd); if (lines_read > 0) { - // if edit is current don't print + /* if edit is current don't print */ line_num += lines_read; i += lines_read; while (line_file && lines_read > 0) { @@ -7674,13 +7777,12 @@ print_program_code (struct list_files *cfile, int in_copy) } line_file = head_line_file; - // free pline_replace - t_line_file *next; + /* free pline_replace */ while (line_file) { cobc_free (line_file->line); line_file->line = NULL; next = line_file->next; - cobc_free(line_file); + cobc_free (line_file); line_file = next; } } diff --git a/cobc/tree.h b/cobc/tree.h index dfc4226e1..3649e42ae 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -1658,17 +1658,6 @@ struct list_error { char *msg; /* Error Message text */ }; -typedef struct s_line_file { - char *line; - struct s_line_file *next; -} t_line_file; - -typedef struct s_data_replace { - t_line_file *firstline_replace; - t_line_file *lastline_replace; - int last_char; -} t_data_replace; - /* List of REPLACE text blocks */ struct list_replace { struct list_replace *next; diff --git a/tests/testsuite.src/listings.at b/tests/testsuite.src/listings.at index 762ab92e0..e23f54b82 100644 --- a/tests/testsuite.src/listings.at +++ b/tests/testsuite.src/listings.at @@ -554,7 +554,7 @@ LINE PG/LN A...B............................................................ 000012 == PIC == BY == pic ==. 000001C 000002C 02 TEST-AVR pic X(2) VALUE "OK". -000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". +000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". 000004C 02 TEST-DD pic X(4) VALUE "OK 2". 000005C 02 TEST-KO pic X(4) VALUE "OK 3". 000006C 02 TEST-FF pic X(4) VALUE "OK 4". diff --git a/tests/testsuite.src/syn_copy.at b/tests/testsuite.src/syn_copy.at index 0ac0784b2..39c062d32 100644 --- a/tests/testsuite.src/syn_copy.at +++ b/tests/testsuite.src/syn_copy.at @@ -977,14 +977,14 @@ LINE PG/LN A...B............................................................ 000005 WORKING-STORAGE SECTION. 000006 REPLACE ==VAR-COLON== BY ==VAR-COMMA==. 000007 COPY "copy.inc" +000008 REPLACING ==:TEST:== BY ==COLON==. 000001C 000002C 01 VAR-:TEST: PIC X(2) VALUE "OK". -000007 REPLACING ==:TEST:== BY ==COLON==. -000008 PROCEDURE DIVISION. -000009 DISPLAY VAR-COMMA NO ADVANCING -000010 END-DISPLAY. -000011 STOP RUN. -000012 REPLACE OFF. +000009 PROCEDURE DIVISION. +000010 DISPLAY VAR-COMMA NO ADVANCING +000011 END-DISPLAY. +000012 STOP RUN. +000013 REPLACE OFF. 0 warnings in compilation group From edcae73bb58d62294a709401b766fa7c2191a132 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Wed, 26 Apr 2023 17:43:26 +0200 Subject: [PATCH 07/10] remove patch #863 and fix bug listing in last test --- cobc/cobc.c | 168 ++++++++++++------------ cobc/codegen.c | 15 --- tests/testsuite.src/run_reportwriter.at | 45 ------- 3 files changed, 83 insertions(+), 145 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index 201930661..da12f8c63 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6639,6 +6639,89 @@ line_has_listing_statement (char *line, const enum cb_format source_format) return 1; } +static char * +get_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (str[i] && isspace (str[i])) { + ++i; + } + if (str[i]) { + return str + i; + } + return NULL; +} + +static char * +get_next_word (char *str) +{ + int i = 0; + + if (!str) { + return NULL; + } + while (str[i] && !isspace (str[i])) { + ++i; + } + while (str[i] && isspace (str[i])) { + ++i; + } + if (str[i]) { + return str + i; + } + return NULL; +} + + +static COB_INLINE COB_A_INLINE int +is_debug_line (char *line, int fixed, int acudebug) +{ + if (line == NULL || line[0] == 0) { + return 0; + } + return !cb_flag_debugging_line + && ((fixed && line[cobc_get_indicator ()] == 'D') + || (!fixed && (acudebug + ? !strncasecmp (line, "\\D", 2) + : !strncasecmp (line, "D ", 2)))); +} + +static COB_INLINE COB_A_INLINE int +is_comment_line (char *line, int fixed) +{ + if (line == NULL || line[0] == 0) { + return 0; + } else { + const int indicator = cobc_get_indicator (); + return fixed + ? line[indicator] == '*' || line[indicator] == '/' + : !strncmp (line, "*>", 2); + } +} + +static COB_INLINE COB_A_INLINE void +abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) +{ + if (pline_cnt >= CB_READ_AHEAD) { + cobc_err_msg (_("%s:%d: too many continuation lines"), + filename, line_num); + cobc_abort_terminate (0); + } +} + +static COB_INLINE COB_A_INLINE void +cleanup_copybook_reference (struct list_files *cur) +{ + if (cur->name) { + cobc_free ((void *)cur->name); + } + cobc_free (cur); +} + static void print_fixed_line (const int line_num, char pch, char *line) { @@ -7024,42 +7107,6 @@ compare_prepare (char *cmp_line, char *pline[CB_READ_AHEAD], #undef RET_IF_OVERFLOW -static COB_INLINE COB_A_INLINE int -is_debug_line (char *line, int fixed, int acudebug) -{ - if (line == NULL || line[0] == 0) { - return 0; - } - return !cb_flag_debugging_line - && ((fixed && line[cobc_get_indicator ()] == 'D') - || (!fixed && (acudebug - ? !strncasecmp (line, "\\D", 2) - : !strncasecmp (line, "D ", 2)))); -} - -static COB_INLINE COB_A_INLINE int -is_comment_line (char *line, int fixed) -{ - if (line == NULL || line[0] == 0) { - return 0; - } else { - const int indicator = cobc_get_indicator (); - return fixed - ? line[indicator] == '*' || line[indicator] == '/' - : !strncmp (line, "*>", 2); - } -} - -static COB_INLINE COB_A_INLINE void -abort_if_too_many_continuation_lines (int pline_cnt, const char *filename, int line_num) -{ - if (pline_cnt >= CB_READ_AHEAD) { - cobc_err_msg (_("%s:%d: too many continuation lines"), - filename, line_num); - cobc_abort_terminate (0); - } -} - /* strncpy with skip multiple space for the listing mode in_copy = margin_a for the margin @@ -7416,53 +7463,6 @@ deep_copy_list_replace (struct list_replace *src, struct list_files *dst_file) dst_file->replace_tail = copy; } -static COB_INLINE COB_A_INLINE void -cleanup_copybook_reference (struct list_files *cur) -{ - if (cur->name) { - cobc_free ((void *)cur->name); - } - cobc_free (cur); -} - -static -char *get_word (char *str) -{ - int i = 0; - - if (!str) { - return NULL; - } - while (isspace (str[i])) { - ++i; - } - if (str + i) { - return str + i; - } - return NULL; -} - -static -char *get_next_word (char *str) -{ - int i = 0; - - if (!str) { - return NULL; - } - while (!isspace (str[i])) { - ++i; - } - while (isspace (str[i])) { - ++i; - } - if (str + i) { - return str + i; - } - return NULL; -} - - /* TO-DO: Modularise! */ /* Applies active REPLACE statements to the source lines in pline. Returns the @@ -7736,7 +7736,6 @@ print_program_code (struct list_files *cfile, int in_copy) line_file = head_line_file; search_end_replace (line_file, cfile); } - line_file = head_line_file; line_num = 1; @@ -7775,7 +7774,6 @@ print_program_code (struct list_files *cfile, int in_copy) } pline_cnt = 0; } - line_file = head_line_file; /* free pline_replace */ while (line_file) { diff --git a/cobc/codegen.c b/cobc/codegen.c index a59e5c733..61b3ee4b6 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -9887,21 +9887,6 @@ output_report_control (struct cb_report *p, int id, cb_tree ctl, cb_tree nx) if(nx) { output_report_control(p, id, nx, CB_CHAIN(nx)); } - bfound = 0; - for(i= p->num_lines-1; i >= 0; i--) { - if(p->line_ids[i]->report_control) { - struct cb_field *c = cb_code_field (p->line_ids[i]->report_control); - if(c == s) { - bfound = 1; - break; - } - } - } - if (!bfound) { - ctl = NULL; - p->controls = NULL; - return ; - } output_local("/* Report %s: CONTROL %s */\n",p->name,s->name); prvid = 0; for(i = 0; i < p->num_lines; i++) { diff --git a/tests/testsuite.src/run_reportwriter.at b/tests/testsuite.src/run_reportwriter.at index 707220749..2ff781a44 100644 --- a/tests/testsuite.src/run_reportwriter.at +++ b/tests/testsuite.src/run_reportwriter.at @@ -9626,48 +9626,3 @@ BEFORE FINAL - SHOULD DISPLAY AT_CLEANUP -AT_SETUP([Check if the variable is referenced in the report]) -AT_KEYWORDS([report]) - -AT_DATA([prog.cob], [ - IDENTIFICATION DIVISION. - PROGRAM-ID. MAIN. - ENVIRONMENT DIVISION. - CONFIGURATION SECTION. - INPUT-OUTPUT SECTION. - FILE-CONTROL. - SELECT A_1 ASSIGN TO EXTERNAL A_1. - SELECT A_2 ASSIGN TO EXTERNAL A_2. - DATA DIVISION. - FILE SECTION. - FD A_1. - COPY test. - FD A_2 REPORT ETAT. - WORKING-STORAGE SECTION. - REPORT SECTION. - RD ETAT - CONTROL FINAL ERROR-1 ERROR-2 - PAGE LIMIT 66. - PROCEDURE DIVISION. - STOP RUN. -]) - -AT_DATA([test.cpy], [ - 01 TEST-01. - 03 TEST-03. - 88 TEST-88 VALUE "0000000". - 09 ERROR-1. - 88 E-TEST-1 VALUE "111". - 10 E-TEST-10 PIC 9(3). - 03 E-TEST-03. - 04 E-TEST-04. - 05 FILLER PIC X(21). - 88 E-TEST-2 VALUE " SM". - 03 E-TEST-2-03. - 09 ERROR-2 PIC 9(3). -]) - -AT_CHECK([$COMPILE prog.cob], [0], [], []) - -AT_CLEANUP - From e20cf1ca461acc906b90ec587442bfde125dec1d Mon Sep 17 00:00:00 2001 From: sbelondr Date: Wed, 28 Jun 2023 16:39:54 +0200 Subject: [PATCH 08/10] fix syntax and delete a check --- cobc/cobc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index da12f8c63..52479690b 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -321,6 +321,16 @@ cob_u32_t optimize_defs[COB_OPTIM_MAX] = { 0 }; int cb_flag_alt_ebcdic = 0; +typedef struct s_line_file { + char *line; + struct s_line_file *next; +} t_line_file; + +typedef struct s_data_replace { + t_line_file *firstline_replace; + t_line_file *lastline_replace; + int last_char; +} t_data_replace; /* Basic memory structure */ struct cobc_mem_struct { @@ -6647,7 +6657,7 @@ get_word (char *str) if (!str) { return NULL; } - while (str[i] && isspace (str[i])) { + while (str[i] && (isspace (str[i]) || str[i] == ',' || str[i] == '.' || str[i] == ';')) { ++i; } if (str[i]) { @@ -6667,7 +6677,7 @@ get_next_word (char *str) while (str[i] && !isspace (str[i])) { ++i; } - while (str[i] && isspace (str[i])) { + while (str[i] && (isspace (str[i]) || str[i] == ',' || str[i] == '.' || str[i] == ';')) { ++i; } if (str[i]) { @@ -7736,6 +7746,7 @@ print_program_code (struct list_files *cfile, int in_copy) line_file = head_line_file; search_end_replace (line_file, cfile); } + line_file = head_line_file; line_num = 1; From f669da3ca81b49a7c2f422c23e4c90d1b1040eb3 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Thu, 20 Jul 2023 15:11:44 +0200 Subject: [PATCH 09/10] edit function check simple and double quotes --- cobc/cobc.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index 52479690b..d142103d2 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -78,17 +78,6 @@ struct strcache { void *val; }; -typedef struct s_line_file { - char *line; - struct s_line_file *next; -} t_line_file; - -typedef struct s_data_replace { - t_line_file *firstline_replace; - t_line_file *lastline_replace; - int last_char; -} t_data_replace; - /* Compile level */ enum compile_level { CB_LEVEL_UNSET = 0, From 2bd81c1b6fdfb8a0d02d63b7157d482989147af8 Mon Sep 17 00:00:00 2001 From: sbelondr Date: Thu, 7 Sep 2023 16:06:01 +0200 Subject: [PATCH 10/10] add comment and remove expected.lst in the tests --- cobc/cobc.c | 6 ++- tests/testsuite.src/listings.at | 72 ++------------------------------- 2 files changed, 9 insertions(+), 69 deletions(-) diff --git a/cobc/cobc.c b/cobc/cobc.c index 208597669..1b270f24c 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -6783,6 +6783,10 @@ print_fixed_line (const int line_num, char pch, char *line) } } +/* + Set simple_quote to 1 if the character is a simple quote otherwise set to 0 and the same for the double quote. + Return 1 if the simple_quote or double_quote change otherwise it returns 0 +*/ static int is_quotes_char (char c, int *simple_quote, int *double_quote) { @@ -6825,7 +6829,7 @@ print_multiple_fixed_line (const int line_num, char pch, char *line) while (line[i]) { /* loop space */ - while (line[i] && isspace (line[i]) && !is_quotes_char (line[i], &simple_quote, &double_quote) && NOT_TOO_LONG (i, start)) { + while (line[i] && isspace (line[i]) && NOT_TOO_LONG (i, start)) { ++i; } last_word = i; diff --git a/tests/testsuite.src/listings.at b/tests/testsuite.src/listings.at index e23f54b82..c88560585 100644 --- a/tests/testsuite.src/listings.at +++ b/tests/testsuite.src/listings.at @@ -269,31 +269,6 @@ AT_CLEANUP AT_SETUP([COPY replacement with partial match]) AT_KEYWORDS([listing copy]) -AT_DATA([expected.lst], -[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY - -LINE PG/LN A...B............................................................ - -000001 -000002 IDENTIFICATION DIVISION. -000003 PROGRAM-ID. prog. -000004 DATA DIVISION. -000005 WORKING-STORAGE SECTION. -000006 01 GET-VALUE. -000007 COPY "copy.inc" REPLACING ==TEST-VAR== BY ==TEST-AVR== -000008 == 02 TEST-EE == BY == 02 TEST-FF ==. -000001C -000002C 02 TEST-AVR PIC X(2) VALUE "OK". -000003C 02 TEST-CC PIC X(4) VALUE "OK 2". -000009 PROCEDURE DIVISION. -000010 DISPLAY TEST-AVR. -000011 STOP RUN. - - -0 warnings in compilation group -0 errors in compilation group -]) - AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". 02 TEST-CC PIC X(4) VALUE "OK 2". @@ -343,42 +318,6 @@ AT_CLEANUP AT_SETUP([COPY replacement with multiple partial matches]) AT_KEYWORDS([listing copy]) -AT_DATA([expected.lst], -[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY - -LINE PG/LN A...B............................................................ - -000001 -000002 IDENTIFICATION DIVISION. -000003 PROGRAM-ID. prog. -000004 DATA DIVISION. -000005 WORKING-STORAGE SECTION. -000006 01 GET-VALUE. -000007 COPY "copy.inc" REPLACING -000008 LEADING ==TEST-VAR== BY ==TEST-AVR== -000009 == 02 TEST-OK == BY == 02 TEST-KO == -000010 ==TEST-CC== BY ==TEST-DD== -000011 == 02 TEST-EE == BY == 02 TEST-FF == -000012 == PIC == BY == pic ==. -000001C -000002C 02 TEST-AVR pic X(2) VALUE "OK". -000003C 02 TEST-AVR-BIS pic X(6) VALUE "OK BIS". -000004C 02 TEST-DD pic X(4) VALUE "OK 2". -000005C 02 TEST-KO pic X(4) VALUE "OK 3". -000006C 02 TEST-FF pic X(4) VALUE "OK 4". -000013 PROCEDURE DIVISION. -000014 DISPLAY TEST-AVR. -000015 DISPLAY TEST-AVR-BIS. -000016 DISPLAY TEST-KO. -000017 DISPLAY TEST-DD. -000018 DISPLAY TEST-FF. -000019 STOP RUN. - - -0 warnings in compilation group -0 errors in compilation group -]) - AT_DATA([copy.inc], [ 02 TEST-VAR PIC X(2) VALUE "OK". 02 TEST-VAR-BIS PIC X(6) VALUE "OK BIS". @@ -606,8 +545,8 @@ AT_DATA([prog.cob], [ STOP RUN. ]) -AT_DATA([expected.lst], -[GnuCOBOL V.R.P prog.cob DDD MMM dd HH:MM:SS YYYY +AT_CHECK([$COMPILE_LISTING0 -t- -tlines=0 prog.cob], [0], +[GnuCOBOL V.R.P prog.cob LINE PG/LN A...B............................................................ @@ -642,11 +581,8 @@ LINE PG/LN A...B............................................................ 0 warnings in compilation group 0 errors in compilation group -]) - -AT_CHECK([$COMPILE_ONLY -t prog.lst -tlines=0 prog.cob], [0], [], []) -AT_CHECK([$UNIFY_LISTING prog.lst prog.lis once], [0], [], []) -AT_CHECK([diff expected.lst prog.lis], [0], [], []) +], +[]) AT_CLEANUP