diff --git a/libcob/ChangeLog b/libcob/ChangeLog index 28d53051f..fd9e693a5 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,16 @@ +2023-06-01 Simon Sobisch + + * fileio.c: minor refactoring for SORT related functions, + mostly reducing scope of variables + * fileio.c (cob_file_sort_using): early exit for errors during OPEN + * fileio.c (cob_file_sort_giving): one-time setting of WRITE options + after OPEN instead of doing it before every WRITE + * fileio.c (cob_file_sort_giving): don't try to WRITE to or CLOSE files + where OPEN OUTPUT was not successful + * fileio.c (cob_file_sort_giving): skip GIVING file on WRITE errors, + early exit if no GIVING file left + 2023-05-30 Simon Sobisch * numeric.c (check_overflow_and_set_sign): disable "cleanup" of diff --git a/libcob/fileio.c b/libcob/fileio.c index 4e3e5b858..5700709a2 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -7774,8 +7774,8 @@ static int sort_cmps (const unsigned char *s1, const unsigned char *s2, const size_t size, const unsigned char *col) { - size_t i; - int ret; + size_t i; + int ret; if (unlikely (col)) { for (i = 0; i < size; ++i) { @@ -7796,9 +7796,7 @@ sort_cmps (const unsigned char *s1, const unsigned char *s2, const size_t size, static COB_INLINE void unique_copy (unsigned char *s1, const unsigned char *s2) { - size_t size; - - size = sizeof (size_t); + size_t size = sizeof (size_t); do { *s1++ = *s2++; } while (--size); @@ -7807,16 +7805,15 @@ unique_copy (unsigned char *s1, const unsigned char *s2) static int cob_file_sort_compare (struct cobitem *k1, struct cobitem *k2, void *pointer) { - cob_file *f; + cob_file *f = pointer; size_t i; size_t u1; size_t u2; - int cmp; - cob_field f1; - cob_field f2; - f = pointer; for (i = 0; i < f->nkeys; ++i) { + int cmp; + cob_field f1; + cob_field f2; f1 = f2 = *(f->keys[i].field); f1.data = k1->item + f->keys[i].offset; f2.data = k2->item + f->keys[i].offset; @@ -7857,7 +7854,6 @@ static struct cobitem * cob_new_item (struct cobsort *hp, const size_t size) { struct cobitem *q; - struct sort_mem_struct *s; COB_UNUSED (size); @@ -7871,6 +7867,7 @@ cob_new_item (struct cobsort *hp, const size_t size) return (void *)q; } if (unlikely ((hp->mem_used + hp->alloc_size) > hp->mem_size)) { + struct sort_mem_struct *s; s = cob_fast_malloc (sizeof (struct sort_mem_struct)); s->mem_ptr = cob_fast_malloc (hp->chunk_size); s->next = hp->mem_base; @@ -7895,9 +7892,9 @@ cob_new_item (struct cobsort *hp, const size_t size) FILE * cob_create_tmpfile (const char *ext) { - FILE *fp; - char *filename; - int fd; + FILE *fp; + char *filename; + int fd; filename = cob_malloc ((size_t)COB_FILE_BUFF); cob_temp_name (filename, ext); @@ -7943,37 +7940,35 @@ cob_get_sort_tempfile (struct cobsort *hp, const int n) static int cob_sort_queues (struct cobsort *hp) { - struct cobitem *q; - int source; - int destination; - int move; - int n; - int end_of_block[2]; + int source = 0; - source = 0; while (hp->queue[source + 1].count != 0) { - destination = source ^ 2; + int destination = source ^ 2; hp->queue[destination].first = NULL; hp->queue[destination].count = 0; hp->queue[destination + 1].first = NULL; hp->queue[destination + 1].count = 0; for (;;) { + int end_of_block[2]; end_of_block[0] = hp->queue[source].count == 0; end_of_block[1] = hp->queue[source + 1].count == 0; if (end_of_block[0] && end_of_block[1]) { break; } while (!end_of_block[0] || !end_of_block[1]) { + struct cobitem *q; + int move; if (end_of_block[0]) { move = 1; } else if (end_of_block[1]) { move = 0; } else { - n = cob_file_sort_compare + const int res + = cob_file_sort_compare (hp->queue[source].first, hp->queue[source + 1].first, hp->pointer); - move = n < 0 ? 0 : 1; + move = res < 0 ? 0 : 1; } q = hp->queue[source + move].first; if (q->end_of_block) { @@ -8002,9 +7997,8 @@ cob_sort_queues (struct cobsort *hp) static int cob_read_item (struct cobsort *hp, const int n) { - FILE *fp; + FILE *fp = hp->file[n].fp; - fp = hp->file[n].fp; if (getc (fp) != 0) { hp->queue[n].first->end_of_block = 1; } else { @@ -8022,12 +8016,10 @@ cob_read_item (struct cobsort *hp, const int n) static int cob_write_block (struct cobsort *hp, const int n) { - struct cobitem *q; - FILE *fp; + FILE *fp = hp->file[hp->destination_file].fp; - fp = hp->file[hp->destination_file].fp; for (;;) { - q = hp->queue[n].first; + struct cobitem *q = hp->queue[n].first; if (q == NULL) { break; } @@ -8054,15 +8046,11 @@ cob_write_block (struct cobsort *hp, const int n) static void cob_copy_check (cob_file *to, cob_file *from) { - unsigned char *toptr; - unsigned char *fromptr; - size_t tosize; - size_t fromsize; + unsigned char *toptr = to->record->data; + unsigned char *fromptr = from->record->data; + const size_t tosize = to->record->size; + const size_t fromsize = from->record->size; - toptr = to->record->data; - fromptr = from->record->data; - tosize = to->record->size; - fromsize = from->record->size; if (unlikely (tosize > fromsize)) { memcpy (toptr, fromptr, fromsize); memset (toptr + fromsize, ' ', tosize - fromsize); @@ -8074,15 +8062,10 @@ cob_copy_check (cob_file *to, cob_file *from) static int cob_file_sort_process (struct cobsort *hp) { - int i; - int source; - int destination; - int n; - int move; - int res; + const int n = cob_sort_queues (hp); + int source; hp->retrieving = 1; - n = cob_sort_queues (hp); #if 0 /* RXWRXW - Cannot be true */ /* LCOV_EXCL_START */ if (unlikely (n < 0)) { @@ -8099,10 +8082,13 @@ cob_file_sort_process (struct cobsort *hp) return COBSORTFILEERR; } /* LCOV_EXCL_STOP */ - for (i = 0; i < 4; ++i) { - hp->queue[i].first = hp->empty; - hp->empty = hp->empty->next; - hp->queue[i].first->next = NULL; + { + int i; + for (i = 0; i < 4; ++i) { + hp->queue[i].first = hp->empty; + hp->empty = hp->empty->next; + hp->queue[i].first->next = NULL; + } } rewind (hp->file[0].fp); rewind (hp->file[1].fp); @@ -8116,7 +8102,7 @@ cob_file_sort_process (struct cobsort *hp) /* LCOV_EXCL_STOP */ source = 0; while (hp->file[source].count > 1) { - destination = source ^ 2; + int destination = source ^ 2; hp->file[destination].count = 0; hp->file[destination + 1].count = 0; while (hp->file[source].count > 0) { @@ -8134,14 +8120,16 @@ cob_file_sort_process (struct cobsort *hp) } else { hp->queue[source + 1].first->end_of_block = 1; } - while (!hp->queue[source].first->end_of_block || - !hp->queue[source + 1].first->end_of_block) { + while (!hp->queue[source].first->end_of_block + || !hp->queue[source + 1].first->end_of_block) { + int move; if (hp->queue[source].first->end_of_block) { move = 1; } else if (hp->queue[source + 1].first->end_of_block) { move = 0; } else { - res = cob_file_sort_compare + const int res + = cob_file_sort_compare (hp->queue[source].first, hp->queue[source + 1].first, hp->pointer); @@ -8190,12 +8178,11 @@ cob_file_sort_process (struct cobsort *hp) static int cob_file_sort_submit (cob_file *f, const unsigned char *p) { - struct cobsort *hp; + struct cobsort *hp = f->file; struct cobitem *q; struct queue_struct *z; - int n; + int n; - hp = f->file; if (unlikely (!hp)) { return COBSORTNOTOPEN; } @@ -8249,14 +8236,9 @@ cob_file_sort_submit (cob_file *f, const unsigned char *p) static int cob_file_sort_retrieve (cob_file *f, unsigned char *p) { - struct cobsort *hp; - struct cobitem *next; - struct queue_struct *z; - int move; - int source; - int res; + struct cobsort *hp = f->file; + int res; - hp = f->file; if (unlikely (!hp)) { return COBSORTNOTOPEN; } @@ -8267,7 +8249,8 @@ cob_file_sort_retrieve (cob_file *f, unsigned char *p) } } if (unlikely (hp->files_used)) { - source = hp->retrieval_queue; + int source = hp->retrieval_queue; + int move; if (hp->queue[source].first->end_of_block) { if (hp->queue[source + 1].first->end_of_block) { return COBSORTEND; @@ -8288,7 +8271,8 @@ cob_file_sort_retrieve (cob_file *f, unsigned char *p) } /* LCOV_EXCL_STOP */ } else { - z = &hp->queue[hp->retrieval_queue]; + struct queue_struct *z = &hp->queue[hp->retrieval_queue]; + struct cobitem *next; if (z->first == NULL) { return COBSORTEND; } @@ -8301,79 +8285,7 @@ cob_file_sort_retrieve (cob_file *f, unsigned char *p) return 0; } -void -cob_file_sort_using (cob_file *sort_file, cob_file *data_file) -{ - int ret; - - cob_open (data_file, COB_OPEN_INPUT, 0, NULL); - for (;;) { - cob_read_next (data_file, NULL, COB_READ_NEXT); - if (data_file->file_status[0] != '0') { - break; - } - cob_copy_check (sort_file, data_file); - ret = cob_file_sort_submit (sort_file, sort_file->record->data); - if (ret) { - break; - } - } - cob_close (data_file, NULL, COB_CLOSE_NORMAL, 0); -} - -void -cob_file_sort_giving (cob_file *sort_file, const size_t varcnt, ...) -{ - cob_file **fbase; - struct cobsort *hp; - size_t i; - int ret; - int opt; - va_list args; - - fbase = cob_malloc (varcnt * sizeof (cob_file *)); - va_start (args, varcnt); - for (i = 0; i < varcnt; ++i) { - fbase[i] = va_arg (args, cob_file *); - } - va_end (args); - for (i = 0; i < varcnt; ++i) { - cob_open (fbase[i], COB_OPEN_OUTPUT, 0, NULL); - } - for (;;) { - ret = cob_file_sort_retrieve (sort_file, sort_file->record->data); - if (ret) { - if (ret == COBSORTEND) { - sort_file->file_status[0] = '1'; - sort_file->file_status[1] = '0'; - } else { - hp = sort_file->file; - if (hp->sort_return) { - *(int *)(hp->sort_return) = 16; - } - sort_file->file_status[0] = '3'; - sort_file->file_status[1] = '0'; - } - break; - } - for (i = 0; i < varcnt; ++i) { - if (COB_FILE_SPECIAL (fbase[i]) || - fbase[i]->organization == COB_ORG_LINE_SEQUENTIAL) { - opt = COB_WRITE_BEFORE | COB_WRITE_LINES | 1; - } else { - opt = 0; - } - fbase[i]->record->size = fbase[i]->record_max; - cob_copy_check (fbase[i], sort_file); - cob_write (fbase[i], fbase[i]->record, opt, NULL, 0); - } - } - for (i = 0; i < varcnt; ++i) { - cob_close (fbase[i], NULL, COB_CLOSE_NORMAL, 0); - } - cob_free (fbase); -} - +/* SORT: initial setup with adding sort definitions to sort file 'f' */ void cob_file_sort_init (cob_file *f, const unsigned int nkeys, const unsigned char *collating_sequence, @@ -8421,6 +8333,7 @@ cob_file_sort_init (cob_file *f, const unsigned int nkeys, save_status (f, fnstatus, COB_STATUS_00_SUCCESS); } +/* SORT: add key definition to internal sort file 'f' */ void cob_file_sort_init_key (cob_file *f, cob_field *field, const int flag, const unsigned int offset) @@ -8431,16 +8344,143 @@ cob_file_sort_init_key (cob_file *f, cob_field *field, const int flag, f->nkeys++; } +/* SORT: add all records from GIVING file 'data_file' to 'sort_file' */ +void +cob_file_sort_using (cob_file *sort_file, cob_file *data_file) +{ + /* FIXME: on each error the approprate USAGE AFTER EXCEPTION/ERROR must be called; + with ISO COBOL2023 this could also mean a local PERFORM WITH EXCEPTION HANDLING; + and for MF/IBM the check for sort_return == 16 when coming back to stop the SORT! */ + int ret; + + cob_open (data_file, COB_OPEN_INPUT, 0, NULL); + if (data_file->file_status[0] != '0') { + return; + } + for (;;) { + cob_read_next (data_file, NULL, COB_READ_NEXT); + if (data_file->file_status[0] != '0') { + break; + } + cob_copy_check (sort_file, data_file); + ret = cob_file_sort_submit (sort_file, sort_file->record->data); + if (ret) { + break; + } + } + cob_close (data_file, NULL, COB_CLOSE_NORMAL, 0); +} + +/* SORT: WRITE all records from 'sort_file' to all passed USING files */ +void +cob_file_sort_giving (cob_file *sort_file, const size_t varcnt, ...) +{ + /* FIXME: on each error the approprate USAGE AFTER EXCEPTION/ERROR must be called; + with ISO COBOL2023 this could also mean a local PERFORM WITH EXCEPTION HANDLING; + and for MF/IBM the check for sort_return == 16 when coming back to stop the SORT! */ + + struct cobsort *hp = sort_file->file; + cob_file **fbase; + size_t i; + va_list args; + int *opt; + int ret; + + /* setup temporary arrays, OPEN OUTPUT all GIVING files and get write option */ + fbase = cob_malloc (varcnt * sizeof (cob_file *)); + opt = cob_malloc (varcnt * sizeof (int)); + va_start (args, varcnt); + for (i = 0; i < varcnt; ++i) { + cob_file *using_file = fbase[i] = va_arg (args, cob_file *); + cob_open (using_file, COB_OPEN_OUTPUT, 0, NULL); + if (using_file->file_status[0] == '0') { + if (COB_FILE_SPECIAL (using_file) + || using_file->organization == COB_ORG_LINE_SEQUENTIAL) { + opt[i] = COB_WRITE_BEFORE | COB_WRITE_LINES | 1; + } else { + opt[i] = 0; + } + } else { + opt[i] = -1; + } + } + va_end (args); + + /* retrieve all records, WRITE each to every GIVING file */ + for (;;) { + /* retrieve next record to write, stop AT END / error */ + ret = cob_file_sort_retrieve (sort_file, sort_file->record->data); + if (ret) { + if (ret == COBSORTEND) { + sort_file->file_status[0] = '1'; + sort_file->file_status[1] = '0'; + } else { + if (hp->sort_return) { + *(int *)(hp->sort_return) = 16; + } + sort_file->file_status[0] = '3'; + sort_file->file_status[1] = '0'; + } + break; + } + + /* WRITE record to all GIVING files */ + for (i = 0; i < varcnt; ++i) { + cob_file *using_file = fbase[i]; + /* skip files which got a permanent error before */ + if (opt[i] < 0) { + continue; + } + using_file->record->size = using_file->record_max; + cob_copy_check (using_file, sort_file); + cob_write (using_file, using_file->record, opt[i], NULL, 0); + /* stop writing to this file if we got a permanent write error; + note: other files are still written to; therefore + SORT-RETURN 16 (early exit) is NOT set here */ + if (using_file->file_status[0] == '3') { + int j; + opt[i] = -2; + /* early exit if no GIVING file left */ + for (j = 0; j < varcnt; ++j) { + if (opt[i] >= 0) { + break; + } + } + if (j == varcnt) { + break; + } + } + } + if (i != varcnt) { + break; + } + } + + /* all records processed - CLOSE all GIVING files */ + for (i = 0; i < varcnt; ++i) { + cob_file *using_file = fbase[i]; + /* skip files not opened */ + if (opt[i] == -1) { + continue; + } + cob_close (using_file, NULL, COB_CLOSE_NORMAL, 0); + } + + /* cleanup temporary arrays */ + cob_free (opt); + cob_free (fbase); +} + +/* SORT: close of internal sort file 'f' and deallocation + of temporary storage */ void cob_file_sort_close (cob_file *f) { - struct cobsort *hp; + struct cobsort *hp = f->file; cob_field *fnstatus; size_t i; - fnstatus = NULL; - hp = f->file; - if (likely(hp)) { + if (likely (hp)) { fnstatus = hp->fnstatus; cob_free_list (hp); for (i = 0; i < 4; ++i) { @@ -8449,6 +8489,8 @@ cob_file_sort_close (cob_file *f) } } cob_free (hp); + } else { + fnstatus = NULL; } if (f->keys) { cob_free (f->keys); @@ -8460,14 +8502,14 @@ cob_file_sort_close (cob_file *f) void cob_file_release (cob_file *f) { - struct cobsort *hp; + struct cobsort *hp = f->file; cob_field *fnstatus; int ret; - fnstatus = NULL; - hp = f->file; if (likely(hp)) { fnstatus = hp->fnstatus; + } else { + fnstatus = NULL; } ret = cob_file_sort_submit (f, f->record->data); if (!ret) { @@ -8483,14 +8525,14 @@ cob_file_release (cob_file *f) void cob_file_return (cob_file *f) { - struct cobsort *hp; + struct cobsort *hp = f->file; cob_field *fnstatus; int ret; - fnstatus = NULL; - hp = f->file; if (likely(hp)) { fnstatus = hp->fnstatus; + } else { + fnstatus = NULL; } ret = cob_file_sort_retrieve (f, f->record->data); switch (ret) {