>From f89a50238de62b73d9fc44ee7226461650ab119d Tue 18 Feb 2025 04:19:13 PM EST From: "James K. Lowden" <jklow...@symas.com> Date: Tue 18 Feb 2025 04:19:13 PM EST Subject: [PATCH] COBOL 11/14 84K lhd: libgcobol header files
libgcobol/ChangeLog * /charmaps.h: New file. * /common-defs.h: New file. * /ec.h: New file. * /exceptl.h: New file. * /gcobolio.h: New file. * /gfileio.h: New file. * /gmath.h: New file. * /io.h: New file. * /libgcobol.h: New file. * /valconv.h: New file. --- libgcobol/charmaps.h | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/common-defs.h | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/ec.h | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/exceptl.h | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/gcobolio.h | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/gfileio.h | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/gmath.h | ++++++++++++++++++++++++++++++++++++++- libgcobol/io.h | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/libgcobol.h | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- libgcobol/valconv.h | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 2017 insertions(+), 10 deletions(-) diff --git a/libgcobol/charmaps.h b/libgcobol/charmaps.h new file mode 100644 index 00000000000..64270c6f08c --- /dev/null +++ b/libgcobol/charmaps.h @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CHARMAPS_H +#define CHARMAPS_H + +#include <unistd.h> + +/* There are four distinct codeset domains in the COBOL compiler. + * + * First is the codeset of the console. Established by looking at what + * setlocale() reports, this can be either UTF-8 or some ASCII based code + * page. (We assume CP1252). Data coming from the console or the system, + * ACCEPT statements; redirected console input, getenv() and other system + * calls are in the "console" domain. + * + * Second is the internal single-byte-coded codeset of the data, in memory, + * being manipulated by the generated code of the cobol executable. The actual + * codeset of "internal" is either EBCDIC (in the form of Code Page 1140 or + * ASCII (Code Page 1252) + * + * Third is the C++ source code of the GCOBOL compiler; this comment is + * in that environment. We neither know, nor care, if this code is encoded in + * in UTF-8 (as is probable, in these enlighted days of 2022) or something like + * Code Page1252. We are going to regard it as "ascii" under the + * assumption that there is no reason for any character in the compiler's + * source code to have a code point outside of the plain vanilla 0x20 through + * 0x7F range. + * + * Fourth is the "raw" COBOL source code that is the input to the GCOBOL + * compiler. This domain can be either UTF-8 or something like CodePage1252. + * Which encoding is relevant; The literal string MOVE "<euro>1234" is seven + * bytes long in UTF-8, and five bytes long in CP1252. We start with an + * assumption that it is UTF-8 and switch to CP1252 upon encountering a byte + * sequence with values above 0x80 that can't be UTF-8. We have provision for + * forcing it to be one or the other. Codepoints in that domain are referenced + * as "raw". Codepoint in the "raw" domain don't last long; they are be + * converted to either "ascii" or "internal" early on, as necessary. + */ + + +/* Notes on character codesets: + + This library is implemented to handle "native" codesets of either ASCII (in + the form of a single-byte-coded codeset like code page 1252) or EBCDIC (in + the form of a single-byte-coded codeset like code page 1140). + + This C/C++ source code, however, is assumed to be an ASCII-based codeset, + so that a character constant like a space is assumed to encode as 0x20. + + Furthermore, we assume that the codeset of the COBOL source code being + compiled is also ASCII-based, even if it is actually UTF-8. Said another + way, characters encoded between zero and 127 are regarded as ASCII. + + This means that we are not going to try to compile EBCDIC COBOL source code; + any such will have to be externally converted to ASCII before feeding it + through this compiler on an ASCII based Linux system. + + This situation is rife for confusion here in the source code for the + library. + + To help reduce that confusion, we are going to eschew character constants + in the C/C++ source code. Instead, we use symbolic versions. In general, + "source_space" means 0x20, while "internal_space" will be either 0x20 + when using the ASCII-based native codeset, or it will be 0x40 when using + the EBCDIC-based native codeset. + + Maintaining one's sanity while learning and working with this C/C++ code + will require a firm grip on context. You'll have to keep track of whether + the character is being used to analyze the ASCII-based COBOL source, or + whether the character in question is part of the native COBOL cobol data + that is being analyzed or generated. + + For example, when a PICTURE string has in it a source_nine, the generated + result in the variable is based on character_zero. + + Stay alert! */ + + +extern bool __gg__ebcdic_codeset_in_use; +#define internal_is_ebcdic (__gg__ebcdic_codeset_in_use) + +extern unsigned short const *__gg__internal_codeset_map; + +#define NULLCH ('\0') +#define DEGENERATE_HIGH_VALUE 0xFF +#define DEGENERATE_LOW_VALUE 0x00 + +#define ascii_A ((uint8_t)('A')) +#define ascii_B ((uint8_t)('B')) +#define ascii_C ((uint8_t)('C')) +#define ascii_D ((uint8_t)('D')) +#define ascii_E ((uint8_t)('E')) +#define ascii_F ((uint8_t)('F')) +#define ascii_G ((uint8_t)('G')) +#define ascii_H ((uint8_t)('H')) +#define ascii_I ((uint8_t)('I')) +#define ascii_J ((uint8_t)('J')) +#define ascii_K ((uint8_t)('K')) +#define ascii_L ((uint8_t)('L')) +#define ascii_M ((uint8_t)('M')) +#define ascii_N ((uint8_t)('N')) +#define ascii_O ((uint8_t)('O')) +#define ascii_P ((uint8_t)('P')) +#define ascii_Q ((uint8_t)('Q')) +#define ascii_R ((uint8_t)('R')) +#define ascii_S ((uint8_t)('S')) +#define ascii_T ((uint8_t)('T')) +#define ascii_U ((uint8_t)('U')) +#define ascii_V ((uint8_t)('V')) +#define ascii_W ((uint8_t)('W')) +#define ascii_X ((uint8_t)('X')) +#define ascii_Y ((uint8_t)('Y')) +#define ascii_Z ((uint8_t)('Z')) +#define ascii_a ((uint8_t)('a')) +#define ascii_b ((uint8_t)('b')) +#define ascii_c ((uint8_t)('c')) +#define ascii_d ((uint8_t)('d')) +#define ascii_e ((uint8_t)('e')) +#define ascii_f ((uint8_t)('f')) +#define ascii_g ((uint8_t)('g')) +#define ascii_h ((uint8_t)('h')) +#define ascii_i ((uint8_t)('i')) +#define ascii_j ((uint8_t)('j')) +#define ascii_k ((uint8_t)('k')) +#define ascii_l ((uint8_t)('l')) +#define ascii_m ((uint8_t)('m')) +#define ascii_n ((uint8_t)('n')) +#define ascii_o ((uint8_t)('o')) +#define ascii_p ((uint8_t)('p')) +#define ascii_q ((uint8_t)('q')) +#define ascii_r ((uint8_t)('r')) +#define ascii_s ((uint8_t)('s')) +#define ascii_t ((uint8_t)('t')) +#define ascii_u ((uint8_t)('u')) +#define ascii_v ((uint8_t)('v')) +#define ascii_w ((uint8_t)('w')) +#define ascii_x ((uint8_t)('x')) +#define ascii_y ((uint8_t)('y')) +#define ascii_z ((uint8_t)('z')) +#define ascii_space ((uint8_t)(' ')) +#define ascii_zero ((uint8_t)('0')) +#define ascii_0 ((uint8_t)('0')) +#define ascii_1 ((uint8_t)('1')) +#define ascii_2 ((uint8_t)('2')) +#define ascii_3 ((uint8_t)('3')) +#define ascii_4 ((uint8_t)('4')) +#define ascii_5 ((uint8_t)('5')) +#define ascii_6 ((uint8_t)('6')) +#define ascii_7 ((uint8_t)('7')) +#define ascii_8 ((uint8_t)('8')) +#define ascii_9 ((uint8_t)('9')) +#define ascii_nine ((uint8_t)('9')) +#define ascii_period ((uint8_t)('.')) +#define ascii_colon ((uint8_t)(':')) +#define ascii_comma ((uint8_t)(',')) +#define ascii_dquote ((uint8_t)('"')) +#define ascii_oparen ((uint8_t)('(')) +#define ascii_caret ((uint8_t)('^')) +#define ascii_slash ((uint8_t)('/')) +#define ascii_plus ((uint8_t)('+')) +#define ascii_minus ((uint8_t)('-')) +#define ascii_hyphen ((uint8_t)('-')) +#define ascii_underscore ((uint8_t)('_')) +#define ascii_asterisk ((uint8_t)('*')) +#define ascii_query ((uint8_t)('?')) +#define ascii_cr ((uint8_t)('\r')) +#define ascii_ff ((uint8_t)('\f')) +#define ascii_newline ((uint8_t)('\n')) +#define ascii_return ((uint8_t)('\r')) + +#define internal_space ((uint8_t)__gg__internal_codeset_map[ascii_space]) +#define internal_zero ((uint8_t)__gg__internal_codeset_map[ascii_zero]) +#define internal_period ((uint8_t)__gg__internal_codeset_map[ascii_period]) +#define internal_comma ((uint8_t)__gg__internal_codeset_map[ascii_comma]) +#define internal_dquote ((uint8_t)__gg__internal_codeset_map[ascii_dquote]) +#define internal_asterisk ((uint8_t)__gg__internal_codeset_map[ascii_asterisk]) +#define internal_plus ((uint8_t)__gg__internal_codeset_map[ascii_plus]) +#define internal_minus ((uint8_t)__gg__internal_codeset_map[ascii_minus]) +#define internal_cr ((uint8_t)__gg__internal_codeset_map[ascii_cr]) +#define internal_ff ((uint8_t)__gg__internal_codeset_map[ascii_ff]) +#define internal_newline ((uint8_t)__gg__internal_codeset_map[ascii_newline]) +#define internal_return ((uint8_t)__gg__internal_codeset_map[ascii_return]) +#define internal_0 ((uint8_t)__gg__internal_codeset_map[ascii_0]) +#define internal_1 ((uint8_t)__gg__internal_codeset_map[ascii_1]) +#define internal_2 ((uint8_t)__gg__internal_codeset_map[ascii_2]) +#define internal_3 ((uint8_t)__gg__internal_codeset_map[ascii_3]) +#define internal_4 ((uint8_t)__gg__internal_codeset_map[ascii_4]) +#define internal_5 ((uint8_t)__gg__internal_codeset_map[ascii_5]) +#define internal_6 ((uint8_t)__gg__internal_codeset_map[ascii_6]) +#define internal_7 ((uint8_t)__gg__internal_codeset_map[ascii_7]) +#define internal_8 ((uint8_t)__gg__internal_codeset_map[ascii_8]) +#define internal_9 ((uint8_t)__gg__internal_codeset_map[ascii_9]) +#define internal_colon ((uint8_t)__gg__internal_codeset_map[ascii_colon]) +#define internal_query ((uint8_t)__gg__internal_codeset_map[ascii_query]) +#define internal_A ((uint8_t)__gg__internal_codeset_map[ascii_A]) +#define internal_B ((uint8_t)__gg__internal_codeset_map[ascii_B]) +#define internal_C ((uint8_t)__gg__internal_codeset_map[ascii_C]) +#define internal_D ((uint8_t)__gg__internal_codeset_map[ascii_D]) +#define internal_E ((uint8_t)__gg__internal_codeset_map[ascii_E]) +#define internal_F ((uint8_t)__gg__internal_codeset_map[ascii_F]) +#define internal_G ((uint8_t)__gg__internal_codeset_map[ascii_G]) +#define internal_H ((uint8_t)__gg__internal_codeset_map[ascii_H]) +#define internal_I ((uint8_t)__gg__internal_codeset_map[ascii_I]) +#define internal_J ((uint8_t)__gg__internal_codeset_map[ascii_J]) +#define internal_K ((uint8_t)__gg__internal_codeset_map[ascii_K]) +#define internal_L ((uint8_t)__gg__internal_codeset_map[ascii_L]) +#define internal_M ((uint8_t)__gg__internal_codeset_map[ascii_M]) +#define internal_N ((uint8_t)__gg__internal_codeset_map[ascii_N]) +#define internal_O ((uint8_t)__gg__internal_codeset_map[ascii_O]) +#define internal_P ((uint8_t)__gg__internal_codeset_map[ascii_P]) +#define internal_Q ((uint8_t)__gg__internal_codeset_map[ascii_Q]) +#define internal_R ((uint8_t)__gg__internal_codeset_map[ascii_R]) +#define internal_S ((uint8_t)__gg__internal_codeset_map[ascii_S]) +#define internal_T ((uint8_t)__gg__internal_codeset_map[ascii_T]) +#define internal_U ((uint8_t)__gg__internal_codeset_map[ascii_U]) +#define internal_V ((uint8_t)__gg__internal_codeset_map[ascii_V]) +#define internal_W ((uint8_t)__gg__internal_codeset_map[ascii_W]) +#define internal_X ((uint8_t)__gg__internal_codeset_map[ascii_X]) +#define internal_Y ((uint8_t)__gg__internal_codeset_map[ascii_Y]) +#define internal_Z ((uint8_t)__gg__internal_codeset_map[ascii_Z]) +#define internal_a ((uint8_t)__gg__internal_codeset_map[ascii_a]) +#define internal_b ((uint8_t)__gg__internal_codeset_map[ascii_b]) +#define internal_c ((uint8_t)__gg__internal_codeset_map[ascii_c]) +#define internal_d ((uint8_t)__gg__internal_codeset_map[ascii_d]) +#define internal_e ((uint8_t)__gg__internal_codeset_map[ascii_e]) +#define internal_f ((uint8_t)__gg__internal_codeset_map[ascii_f]) +#define internal_g ((uint8_t)__gg__internal_codeset_map[ascii_g]) +#define internal_h ((uint8_t)__gg__internal_codeset_map[ascii_h]) +#define internal_i ((uint8_t)__gg__internal_codeset_map[ascii_i]) +#define internal_j ((uint8_t)__gg__internal_codeset_map[ascii_j]) +#define internal_k ((uint8_t)__gg__internal_codeset_map[ascii_k]) +#define internal_l ((uint8_t)__gg__internal_codeset_map[ascii_l]) +#define internal_m ((uint8_t)__gg__internal_codeset_map[ascii_m]) +#define internal_n ((uint8_t)__gg__internal_codeset_map[ascii_n]) +#define internal_o ((uint8_t)__gg__internal_codeset_map[ascii_o]) +#define internal_p ((uint8_t)__gg__internal_codeset_map[ascii_p]) +#define internal_q ((uint8_t)__gg__internal_codeset_map[ascii_q]) +#define internal_r ((uint8_t)__gg__internal_codeset_map[ascii_r]) +#define internal_s ((uint8_t)__gg__internal_codeset_map[ascii_s]) +#define internal_t ((uint8_t)__gg__internal_codeset_map[ascii_t]) +#define internal_u ((uint8_t)__gg__internal_codeset_map[ascii_u]) +#define internal_v ((uint8_t)__gg__internal_codeset_map[ascii_v]) +#define internal_w ((uint8_t)__gg__internal_codeset_map[ascii_w]) +#define internal_x ((uint8_t)__gg__internal_codeset_map[ascii_x]) +#define internal_y ((uint8_t)__gg__internal_codeset_map[ascii_y]) +#define internal_z ((uint8_t)__gg__internal_codeset_map[ascii_z]) + + +enum text_device_t + { + td_default_e, + td_sourcecode_e, + td_console_e, + }; + +enum text_codeset_t + { + cs_default_e, + cs_utf8_e, + cs_cp1252_e, + cs_cp1140_e + }; + + +extern unsigned char __gg__data_space[1] ; +extern unsigned char __gg__data_low_values[1] ; +extern unsigned char __gg__data_zeros[1] ; +extern unsigned char __gg__data_high_values[1] ; +extern unsigned char __gg__data_quotes[1] ; +extern unsigned char __gg__data_upsi_0[2] ; +extern unsigned char __gg__data_return_code[2] ; + +// These are the various hardcoded tables used for conversions. +extern const unsigned short __gg__one_to_one_values[256]; +extern const unsigned short __gg__cp1252_to_cp1140_values[256]; +extern const unsigned short __gg__cp1140_to_cp1252_values[256]; + +// These are the two standard collations. +extern const unsigned short __gg__cp1252_to_ebcdic_collation[256]; +extern const unsigned short __gg__ebcdic_to_cp1252_collation[256]; + +// As described above, we have a number of operations we need to accomplish. But +// the actual routines are dependent on whether EBCDIC or ASCII is in use. We +// implement that by having a function pointer for each function; those pointers +// are established when the __gg__ebcdic_codeset_in_use variable is established. + +// These routines convert a single ASCII character to either ASCII or EBCDIC + +extern "C" +char __gg__ascii_to_ascii_chr(char ch); +extern "C" +char __gg__ascii_to_ebcdic_chr(char ch); +extern "C" +char (*__gg__ascii_to_internal_chr)(char); +#define ascii_to_internal(a) ((*__gg__ascii_to_internal_chr)(a)) + +extern "C" +void __gg__ascii_to_ascii(char *str, size_t length); +extern "C" +void __gg__ascii_to_ebcdic(char *str, size_t length); +extern "C" +void (*__gg__ascii_to_internal_str)(char *str, size_t length); +#define ascii_to_internal_str(a, b) ((*__gg__ascii_to_internal_str)((a), (b))) + +extern "C" +char *__gg__raw_to_ascii(char **dest, size_t *dest_size, const char *str, size_t length); +extern "C" +char *__gg__raw_to_ebcdic(char **dest, size_t *dest_size, const char *in, size_t length); +extern "C" +char *(*__gg__raw_to_internal)(char **dest, size_t *dest_length, const char *in, size_t length); +#define raw_to_internal(a, b, c, d) ((*__gg__raw_to_internal)((a), (b), (c), (d))) + +extern "C" +char *__gg__ascii_to_console(char **dest, size_t *dest_size, char const * const str, const size_t length); +extern "C" +char *__gg__ebcdic_to_console(char **dest, size_t *dest_size, char const * const str, const size_t length); +extern "C" +char *(*__gg__internal_to_console_cm)(char **dest, size_t *dest_size, const char *in, size_t length); +#define internal_to_console(a, b, c, d) ((*__gg__internal_to_console_cm)((a), (b), (c), (d))) + +extern "C" +void __gg__console_to_ascii(char * const str, size_t length); +extern "C" +void __gg__console_to_ebcdic(char * const str, size_t length); +extern "C" +void (*__gg__console_to_internal_cm)(char * const str, size_t length); +#define console_to_internal(a, b) ((*__gg__console_to_internal_cm)((a), (b))) + +extern "C" +void __gg__ebcdic_to_ascii(char *str, const size_t length); +extern "C" +void (*__gg__internal_to_ascii)(char *str, size_t length); +#define internal_to_ascii(a, b) ((*__gg__internal_to_ascii)((a), (b))) + +extern "C" void __gg__set_internal_codeset(int use_ebcdic); + +extern "C" +void __gg__text_conversion_override(text_device_t device, + text_codeset_t codeset); + +#endif \ No newline at end of file diff --git a/libgcobol/common-defs.h b/libgcobol/common-defs.h new file mode 100644 index 00000000000..ebb4e8bd806 --- /dev/null +++ b/libgcobol/common-defs.h @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef COMMON_DEFS_H_ +#define COMMON_DEFS_H_ + +#include <stdint.h> +#include <list> + +#define COUNT_OF(X) (sizeof(X) / sizeof(X[0])) + +// This constant establishes the maximum number of digits in a fixed point +// number. We are using 37 digits as a maximum because a full-size 37-digit +// number (10**37) takes 123 bits, and a full-size 38-digit number (10**38) +// takes 127 bits. By using a maximum of 37, that gives us an additional digit +// of headroom in order to accomplish rounding. + +// You should keep in mind that the _Float128 binary floating point numbers that +// we use can reliably reproduce numbers of 33 decimal digits when going to +// binary and back. + +#define MAX_FIXED_POINT_DIGITS (37) + +// COBOL tables can have up to seven subscripts +#define MAXIMUM_TABLE_DIMENSIONS 7 + +// This bit gets turned on in the first or last byte (depending on the leading_e attribute +// phrase) of a NumericDisplay to indicate that the value is negative. + +// When running the EBCDIC character set, the meaning of this bit is flipped, +// because an EBCDIC zero is 0xF0, while ASCII is 0x30 +#define NUMERIC_DISPLAY_SIGN_BIT 0x40 + +#define LEVEL01 (1) +#define LEVEL49 (49) +#define LEVEL77 (77) + +// In the __gg__move_literala() call, we piggyback this bit onto the +// cbl_round_t parameter, just to cut down on the number of parameters passed +#define REFER_ALL_BIT 0x80 + + +/* + * User-defined names in IBM COBOL can have at most 30 characters. + * For DBCS, the maximum is 14. + * + * Per ISO/IEC 1989:2023(E), 8.3.2 COBOL words, + * "A COBOL word is a character-string of not more than 63 characters" + */ +typedef char cbl_name_t[64]; + +// Note that the field_type enum is duplicated in the source code for the +// COBOL-aware GDB, and so any changes here (or there) have to be reflected +// there (or here) + +// Note further that if this list changes, then the valid_move() matrix has to +// change as will. Currently that matrix is in util.cc. + +enum cbl_field_type_t { + FldInvalid, // uninitialized + FldGroup, + FldAlphanumeric, // For X(n). + FldNumericBinary, // For 999v9 comp big-endian, 1 to 16 bytes + FldFloat, // 4-, 8-, and 16-byte floating point. See ieeedec_e and big_endian_e flags + FldPacked, // For 999v9 comp-3 internal decimal, packed decimal representation; + FldNumericBin5, // For 999v9 comp-5 little-endian, 1 to 16 bytes. (Native binary) + FldNumericDisplay, // For 999v9 one decimal character per byte + FldNumericEdited, // For 999.9 PIC BPVZ90/,.+-CRDB*cs; must have one of B/Z0,.*+-CRDBcs + FldAlphaEdited, // PIC AX9B0/; must have at least one A or X, and at least one B0/ + FldLiteralA, // Alphanumeric literal + FldLiteralN, // Numeric literal + FldClass, + FldConditional, // Target for parser_relop() + FldForward, + FldIndex, + FldSwitch, + FldDisplay, + FldPointer, + FldBlob, +}; + + +/* BINARY, COMP, COMPUTATIONAL, COMP-4, COMPUTATIONAL-4 are the same: + * Storage, by default, is big-endian. + * PIC 9(1 to 4) is 2 bytes + * PIC 9(5 to 9) is 4 bytes + * PIC 9(10 to 18) is 8 bytes + * PIC 9(19-37) is 16 bytes + * COMP-1, COMPUTATIONAL-1 + * 4-byte floating point (single) + * COMP-2, COMPUTATIONAL-2 + * 8-byte floating point (double) + * PACKED-DECIMAL, COMP-3, COMPUTATIONAL-3 + * Packed decimal. Final nybble is 0xF for unsigned numbers. For signable + * values, it is 0xD for negative, and 0xC for non-negative + * COMP-5, COMPUTATIONAL-5 + * Native binary. The maximum number of digits is implied by + * the 2, 4, or 8 bytes of data storage. By "native", little-endian + * is implied on Intel processors. + */ + +/* + * Enumerated bit mask of variable attributes. + * A field as either left- or right-justified. + * A field is padded (in the unjustified direction) either with 0 or SPC. + * (But maybe the fill character should just be an explicit character.) + */ +enum cbl_field_attr_t : size_t { + none_e = 0x0000000000, + figconst_1_e = 0x0000000001, // This needs to be 1 - don't change the position + figconst_2_e = 0x0000000002, // This needs to be 2 + figconst_4_e = 0x0000000004, // This needs to be 4 + rjust_e = 0x0000000008, // justify right + ljust_e = 0x0000000010, // justify left + zeros_e = 0x0000000020, // zero fill + signable_e = 0x0000000040, + constant_e = 0x0000000080, // pre-assigned constant + function_e = 0x0000000100, + quoted_e = 0x0000000200, + filler_e = 0x0000000400, + _spare_e = 0x0000000800, // + intermediate_e = 0x0000001000, // Compiler-defined temporary variable + embiggened_e = 0x0000002000, // redefined numeric made 64-bit by USAGE POINTER + all_alpha_e = 0x0000004000, // FldAlphanumeric, but all A's + all_x_e = 0x0000008000, // picture is all X's + all_ax_e = 0x000000a000, // picture is all A's or all X's + prog_ptr_e = 0x0000010000, // FUNCTION-POINTER or PROGRAM-POINTER + scaled_e = 0x0000020000, + refmod_e = 0x0000040000, // Runtime; indicates a refmod is active + based_e = 0x0000080000, // pointer capacity, for ADDRESS OF or ALLOCATE + any_length_e = 0x0000100000, // inferred length of linkage in nested program + global_e = 0x0000200000, // field has global scope + external_e = 0x0000400000, // field has external scope + blank_zero_e = 0x0000800000, // BLANK WHEN ZERO + // data division uses 2 low bits of high byte + linkage_e = 0x0001000000, // field is in linkage section + local_e = 0x0002000000, // field is in local section + leading_e = 0x0004000000, // leading sign (signable_e alone means trailing) + separate_e = 0x0008000000, // separate sign + envar_e = 0x0010000000, // names an environment variable + dnu_1_e = 0x0020000000, // unused: this attribute bit is available + bool_encoded_e = 0x0040000000, // data.initial is a boolean string + hex_encoded_e = 0x0080000000, // data.initial is a hex-encoded string + depends_on_e = 0x0100000000, // A group hierachy contains a DEPENDING_ON + initialized_e = 0x0200000000, // Don't call parser_initialize from parser_symbol_add + has_value_e = 0x0400000000, // Flag to hierarchical descendents to ignore .initial + ieeedec_e = 0x0800000000, // Indicates a FldFloat is IEEE 754 decimal, rather than binary + big_endian_e = 0x1000000000, // Indicates a value is big-endian + same_as_e = 0x2000000000, // Field produced by SAME AS (cannot take new members) + record_key_e = 0x4000000000, + typedef_e = 0x8000000000, // IS TYPEDEF + strongdef_e = typedef_e + intermediate_e, // STRONG TYPEDEF (not temporary) +}; +enum cbl_figconst_t + { + normal_value_e = 0, // This one must be zero + low_value_e = 1, // The order is important, because + null_value_e = 2, + zero_value_e = 3, // at times we compare, for example, low_value_e to + space_value_e = 4, + quote_value_e = 5, // + high_value_e = 6, // high_value_e to determine that low is less than high + }; +#define FIGCONST_MASK (figconst_1_e|figconst_2_e|figconst_4_e) +#define DATASECT_MASK (linkage_e | local_e) + +enum cbl_file_org_t { + file_disorganized_e, + file_sequential_e, + file_line_sequential_e, + file_indexed_e, + file_relative_e, +}; + +enum cbl_file_access_t { + file_inaccessible_e, + file_access_seq_e, + file_access_rnd_e, + file_access_dyn_e, +}; + +enum cbl_file_mode_t { + file_mode_none_e, + file_mode_input_e = 'r', + file_mode_output_e = 'w', + file_mode_extend_e = 'a', + file_mode_io_e = '+', +}; + +enum cbl_round_t { + away_from_zero_e, + nearest_toward_zero_e, + toward_greater_e, + toward_lesser_e, + nearest_away_from_zero_e, + nearest_even_e, + prohibited_e, + truncation_e, +}; + +#define RELOP_START 0 +enum relop_t { + lt_op = RELOP_START, + le_op, + eq_op, + ne_op, + ge_op, + gt_op, +}; + +#define LOGOP_START 100 +enum logop_t { + not_op = LOGOP_START, + and_op, + or_op, + xor_op, + xnor_op, + true_op, + false_op, +}; + +#define SETOP_START 200 +enum setop_t { + is_op = SETOP_START, +}; + +enum bitop_t { + bit_set_op, // set bit on + bit_clear_op, // set bit off + bit_on_op, // true if bit is on + bit_off_op, // true if bit is off + bit_and_op, + bit_or_op, + bit_xor_op, +}; + +enum file_close_how_t { + file_close_no_how_e = 0x00, + file_close_removal_e = 0x01, + file_close_no_rewind_e = 0x02, + file_close_with_lock_e = 0x04, + file_close_reel_unit_e = 0x08, +}; + +enum cbl_compute_error_code_t { + compute_error_none = 0x0000, + compute_error_truncate = 0x0001, + compute_error_divide_by_zero = 0x0002, + compute_error_exp_zero_by_zero = 0x0004, + compute_error_exp_zero_by_minus = 0x0008, + compute_error_exp_minus_by_frac = 0x0010, + compute_error_overflow = 0x0020, + compute_error_underflow = 0x0040, +}; + +enum cbl_arith_format_t { + not_expected_e, + no_giving_e, giving_e, + corresponding_e }; + +enum cbl_encoding_t { + ASCII_e, // STANDARD-1 (in caps to avoid conflict with ascii_e in libgcobol.cc) + iso646_e, // STANDARD-2 + EBCDIC_e, // NATIVE or EBCDIC + custom_encoding_e, +}; + +enum cbl_truncation_mode { + trunc_std_e, + trunc_opt_e, + trunc_bin_e, +}; + +enum cbl_inspect_bound_t { + bound_characters_e, + bound_all_e, + bound_first_e, + bound_leading_e, + bound_trailing_e, +}; + +// a SPECIAL-NAME +enum special_name_t { + SYSIN_e, SYSIPT_e, SYSOUT_e, + SYSLIST_e, SYSLST_e, + SYSPUNCH_e, SYSPCH_e, + CONSOLE_e, + C01_e, C02_e, C03_e, C04_e, C05_e, C06_e, + C07_e, C08_e, C09_e, C10_e, C11_e, C12_e, + CSP_e, + S01_e, S02_e, S03_e, S04_e, S05_e, + AFP_5A_e, + STDIN_e, STDOUT_e, STDERR_e, SYSERR_e, + ARG_NUM_e, ARG_VALUE_e, ENV_NAME_e, ENV_VALUE_e, +}; + +enum classify_t { + ClassInvalidType, + ClassNumericType, + ClassAlphabeticType, + ClassLowerType, + ClassUpperType, + ClassDbcsType, + ClassKanjiType, +}; + +static inline const char * +classify_str( enum classify_t classify ) { + switch(classify) { + case ClassInvalidType: return "ClassInvalidType"; + case ClassNumericType: return "ClassNumericType"; + case ClassAlphabeticType: return "ClassAlphabeticType"; + case ClassLowerType: return "ClassLowerType"; + case ClassUpperType: return "ClassUpperType"; + case ClassDbcsType: return "ClassDbcsType"; + case ClassKanjiType: return "ClassKanjiType"; + }; + return "(unknown classification)"; +} + +static inline const char * +cbl_file_mode_str( cbl_file_mode_t mode ) { + switch(mode) { + case file_mode_none_e: return "file_mode_none_e"; + case file_mode_input_e: return "file_mode_input_e: 'r'"; + case file_mode_output_e: return "file_mode_output_e: 'w'"; + case file_mode_io_e: return "file_mode_io_e: '+'"; + case file_mode_extend_e: return "file_mode_extend_e: 'a'"; + } + return "???"; +}; + +enum module_type_t { + module_activating_e, + module_current_e, + module_nested_e, + module_stack_e, + module_toplevel_e, +}; + + +static inline bool +ec_cmp( ec_type_t raised, ec_type_t mask ) +{ + if( raised == mask ) return true; + + // Do not match on only the low byte. + if( 0 < (~EC_ALL_E & static_cast<uint32_t>(mask)) ) return false; + + return 0 != ( static_cast<uint32_t>(raised) + & + static_cast<uint32_t>(mask) ); +} + +struct cbl_enabled_exception_t { + bool enabled, location; + ec_type_t ec; + size_t file; + + cbl_enabled_exception_t() + : enabled(false) + , location(false) + , ec(ec_none_e) + , file(0) + {} + + cbl_enabled_exception_t( bool enabled, bool location, + ec_type_t ec, size_t file = 0 ) + : enabled(enabled) + , location(location) + , ec(ec) + , file(file) + {} + + // sort by ec and file, not enablement + bool operator<( const cbl_enabled_exception_t& that ) const { + if( ec == that.ec ) return file < that.file; + return ec < that.ec; + } + // match on ec and file, not enablement + bool operator==( const cbl_enabled_exception_t& that ) const { + return ec == that.ec && file == that.file; + } +}; + + +class cbl_enabled_exceptions_array_t; + +class cbl_enabled_exceptions_t : protected std::set<cbl_enabled_exception_t> +{ + friend cbl_enabled_exceptions_array_t; + void apply( const cbl_enabled_exception_t& elem ) { + auto inserted = insert( elem ); + if( ! inserted.second ) { + erase(inserted.first); + insert(elem); + } + } + + public: + bool turn_on_off( bool enabled, bool location, ec_type_t type, + std::set<size_t> files ); + + const cbl_enabled_exception_t * match( ec_type_t type, size_t file = 0 ); + + void dump() const; + + void clear() { std::set<cbl_enabled_exception_t>::clear(); } + + bool empty() const { return std::set<cbl_enabled_exception_t>::empty(); } + size_t size() const { return std::set<cbl_enabled_exception_t>::size(); } + + cbl_enabled_exceptions_t& operator=( const cbl_enabled_exceptions_t& that ) { + std::set<cbl_enabled_exception_t>& self(*this); + self = that; + return *this; + } +}; + +extern cbl_enabled_exceptions_t enabled_exceptions; + +/* + * This class is passed to the runtime function evaluating the raised exception. + * It is constructed in genapi.cc from the compile-time table. + */ +struct cbl_enabled_exceptions_array_t { + size_t nec; + cbl_enabled_exception_t *ecs; + + cbl_enabled_exceptions_array_t( size_t nec, cbl_enabled_exception_t *ecs ) + : nec(nec), ecs(ecs) {} + + cbl_enabled_exceptions_array_t( const cbl_enabled_exceptions_t& input = + cbl_enabled_exceptions_t() ) + : nec(input.size()) + , ecs(NULL) + { + if( ! input.empty() ) { + ecs = new cbl_enabled_exception_t[nec]; + std::copy(input.begin(), input.end(), ecs); + } + } + + cbl_enabled_exceptions_array_t& + operator=( const cbl_enabled_exceptions_array_t& input); + + + bool match( ec_type_t ec, size_t file = 0 ) const; + + size_t nbytes() const { return nec * sizeof(ecs[0]); } +}; + +template <typename T> +T enabled_exception_match( T beg, T end, ec_type_t type, size_t file ) { + cbl_enabled_exception_t input( true, true, // don't matter + type, file ); + auto output = std::find(beg, end, input); + if( output == end ) { + output = std::find_if( beg, end, // match any file + [ec = type]( const cbl_enabled_exception_t& elem ) { + return + elem.file == 0 && + ec_cmp(ec, elem.ec); } ); + } + return output; +} + + + +#endif diff --git a/libgcobol/ec.h b/libgcobol/ec.h new file mode 100644 index 00000000000..1e3f7cfa7ea --- /dev/null +++ b/libgcobol/ec.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _CBL_EC_H_ +#define _CBL_EC_H_ + +#include <set> +#include <assert.h> + +#define EC_ALL_E 0xFFFFFF00 + +enum ec_type_t { + ec_none_e = 0x00000000, + ec_all_e = EC_ALL_E, // 0xFFFFFF00 + + ec_argument_e = 0x00000100, + ec_argument_function_e, + ec_argument_imp_e, + ec_argument_imp_command_e, + ec_argument_imp_environment_e, + + ec_bound_e = 0x00000200, + ec_bound_func_ret_value_e, + ec_bound_imp_e, + ec_bound_odo_e, + ec_bound_overflow_e, + ec_bound_ptr_e, + ec_bound_ref_mod_e, + ec_bound_set_e, + ec_bound_subscript_e, + ec_bound_table_limit_e, + + ec_data_e = 0x00000400, + ec_data_conversion_e, + ec_data_imp_e, + ec_data_incompatible_e, + ec_data_not_finite_e, + ec_data_overflow_e, + ec_data_ptr_null_e, + + ec_external_e = 0x00000800, + ec_external_data_mismatch_e, + ec_external_file_mismatch_e, + ec_external_format_conflict_e, + + ec_flow_e = 0x00001000, + ec_flow_global_exit_e, + ec_flow_global_goback_e, + ec_flow_imp_e, + ec_flow_release_e, + ec_flow_report_e, + ec_flow_return_e, + ec_flow_search_e, + ec_flow_use_e, + + ec_function_e = 0x00002000, + ec_function_not_found_e, + ec_function_ptr_invalid_e, + ec_function_ptr_null_e, + + ec_io_e = 0x00004000, + ec_io_at_end_e, + ec_io_invalid_key_e, + ec_io_permanent_error_e, + ec_io_logic_error_e, + ec_io_record_operation_e, + ec_io_file_sharing_e, + ec_io_record_content_e, + ec_io_imp_e, + ec_io_eop_e, + ec_io_eop_overflow_e, + ec_io_linage_e, + + ec_imp_e = 0x00008000, + ec_imp_suffix_e, + + ec_locale_e = 0x00010000, + ec_locale_imp_e, + ec_locale_incompatible_e, + ec_locale_invalid_e, + ec_locale_invalid_ptr_e, + ec_locale_missing_e, + ec_locale_size_e, + + ec_oo_e = 0x00020000, + ec_oo_arg_omitted_e, + ec_oo_conformance_e, + ec_oo_exception_e, + ec_oo_imp_e, + ec_oo_method_e, + ec_oo_null_e, + ec_oo_resource_e, + ec_oo_universal_e, + + ec_order_e = 0x00040000, + ec_order_imp_e, + ec_order_not_supported_e, + + ec_overflow_e = 0x00080000, + ec_overflow_imp_e, + ec_overflow_string_e, + ec_overflow_unstring_e, + + ec_program_e = 0x00100000, + ec_program_arg_mismatch_e, + ec_program_arg_omitted_e, + ec_program_cancel_active_e, + ec_program_imp_e, + ec_program_not_found_e, + ec_program_ptr_null_e, + ec_program_recursive_call_e, + ec_program_resources_e, + + ec_raising_e = 0x00200000, + ec_raising_imp_e, + ec_raising_not_specified_e, + + ec_range_e = 0x00400000, + ec_range_imp_e, + ec_range_index_e, + ec_range_inspect_size_e, + ec_range_invalid_e, + ec_range_perform_varying_e, + ec_range_ptr_e, + ec_range_search_index_e, + ec_range_search_no_match_e, + + ec_report_e = 0x00800000, + ec_report_active_e, + ec_report_column_overlap_e, + ec_report_file_mode_e, + ec_report_imp_e, + ec_report_inactive_e, + ec_report_line_overlap_e, + ec_report_not_terminated_e, + ec_report_page_limit_e, + ec_report_page_width_e, + ec_report_sum_size_e, + ec_report_varying_e, + + ec_screen_e = 0x01000000, + ec_screen_field_overlap_e, + ec_screen_imp_e, + ec_screen_item_truncated_e, + ec_screen_line_number_e, + ec_screen_starting_column_e, + + ec_size_e = 0x02000000, + ec_size_address_e, + ec_size_exponentiation_e, + ec_size_imp_e, + ec_size_overflow_e, + ec_size_truncation_e, + ec_size_underflow_e, + ec_size_zero_divide_e, + + ec_sort_merge_e = 0x04000000, + ec_sort_merge_active_e, + ec_sort_merge_file_open_e, + ec_sort_merge_imp_e, + ec_sort_merge_release_e, + ec_sort_merge_return_e, + ec_sort_merge_sequence_e, + + ec_storage_e = 0x08000000, + ec_storage_imp_e, + ec_storage_not_alloc_e, + ec_storage_not_avail_e, + + ec_user_e = 0x10000000, + ec_user_suffix_e, + + ec_validate_e = 0x20000000, + ec_validate_content_e, + ec_validate_format_e, + ec_validate_imp_e, + ec_validate_relation_e, + ec_validate_varying_e, + + ec_continue_e = 0x30000000, + ec_continue_less_than_zero, +}; + + +#endif diff --git a/libgcobol/exceptl.h b/libgcobol/exceptl.h new file mode 100644 index 00000000000..35809034f4f --- /dev/null +++ b/libgcobol/exceptl.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _CBL_EXCEPTC_H_ +#define _CBL_EXCEPTC_H_ + +/* This file contains declarations needed by the libgcobol compilation. Some + of the information here is required by the gcc/cobol compilation, and so it + is safe to include in those files. */ + +static const ec_type_t simon_says_important[] = { + ec_argument_function_e, + ec_bound_odo_e, + ec_bound_ref_mod_e, + ec_bound_subscript_e, + ec_data_incompatible_e, + ec_data_ptr_null_e, + ec_size_overflow_e, + ec_size_exponentiation_e, + ec_size_truncation_e, + ec_size_zero_divide_e, + ec_program_not_found_e, + ec_program_recursive_call_e, + ec_program_arg_mismatch_e, +}; + +enum ec_disposition_t { + ec_category_none_e, + ec_category_fatal_e, + ec_category_nonfatal_e, + ec_category_implementor_e, + + // unimplemented equivalents + uc_category_none_e = 0x80 + ec_category_none_e, + uc_category_fatal_e = 0x80 + ec_category_fatal_e, + uc_category_nonfatal_e = 0x80 + ec_category_nonfatal_e, + uc_category_implementor_e = 0x80 + ec_category_implementor_e, +}; + +struct ec_descr_t { + ec_type_t type; + ec_disposition_t disposition; + const cbl_name_t name; + const char *description; + + bool operator==( ec_type_t type ) const { + return this->type == type; + } +}; + +extern ec_type_t ec_type_of( const cbl_name_t name ); + +extern ec_descr_t __gg__exception_table[]; +extern ec_descr_t *__gg__exception_table_end; + +/* Inventory of exceptions: + In except.hc::__gg__exception_table, unimplemented ECs have a uc_ disposition. + + ec_function_argument_e ACOS + ANNUITY + ASIN + LOG + LOG10 + PRESENT-VALUE + SQRT + + ec_sort_merge_file_open_e FILE MERGE + + ec_bound_subscript_e table subscript not an integer + table subscript less than 1 + table subscript greater than occurs + + ec_bound_ref_mod_e refmod start not an integer + refmod start less than 1 + refmod start greater than variable size + refmod length not an integer + refmod length less than 1 + refmod start+length exceeds variable size + + ec_bound_odo_e DEPENDING not an integer + DEPENDING greater than occurs upper limit + DEPENDING less than occurs lower limit + subscript greater than DEPENDING for sending item + + ec_size_zero_divide_e For both fixed-point and floating-point division + + ec_size_truncation + ec_size_exponentiation + + */ + +// SymException +struct cbl_exception_t { + size_t program, file; + ec_type_t type; + cbl_file_mode_t mode; +}; + + +struct cbl_declarative_t { + enum { files_max = 16 }; + size_t section; // implies program + bool global; + ec_type_t type; + uint32_t nfile, files[files_max]; + cbl_file_mode_t mode; + + cbl_declarative_t( cbl_file_mode_t mode = file_mode_none_e ) + : section(0), global(false), type(ec_none_e) + , nfile(0) + , mode(mode) + { + std::fill(files, files + COUNT_OF(files), 0); + } + cbl_declarative_t( ec_type_t type ) + : section(0), global(false), type(type) + , nfile(0) + , mode(file_mode_none_e) + { + std::fill(files, files + COUNT_OF(files), 0); + } + + cbl_declarative_t( size_t section, ec_type_t type, + const std::list<size_t>& files, + cbl_file_mode_t mode, bool global = false ) + : section(section), global(global), type(type) + , nfile(files.size()) + , mode(mode) + { + assert( files.size() <= COUNT_OF(this->files) ); + std::fill(this->files, this->files + COUNT_OF(this->files), 0); + if( nfile > 0 ) { + std::copy( files.begin(), files.end(), this->files ); + } + } + cbl_declarative_t( const cbl_declarative_t& that ) + : section(that.section), global(that.global), type(that.type) + , nfile(that.nfile) + , mode(that.mode) + { + std::fill(files, files + COUNT_OF(files), 0); + if( nfile > 0 ) { + std::copy( that.files, that.files + nfile, this->files ); + } + } + + /* + * Sort file names before file modes, and file modes before non-IO. + */ + bool operator<( const cbl_declarative_t& that ) const { + // file name declaratives first, in section order + if( nfile != 0 ) { + if( that.nfile != 0 ) return section < that.section; + return true; + } + // file mode declaratives between file name declaratives and non-IO + if( mode != file_mode_none_e ) { + if( that.nfile != 0 ) return false; + if( that.mode == file_mode_none_e ) return true; + return section < that.section; + } + // all others by section, after names and modes + if( that.nfile != 0 ) return false; + if( that.mode != file_mode_none_e ) return false; + return section < that.section; + } + + // TRUE if there are no files to match, or the provided file is in the list. + bool match_file( size_t file ) const { + static const auto pend = files + nfile; + + return nfile == 0 || pend != std::find(files, files + nfile, file); + } + + // USE Format 1 names a file mode, or at least one file, and not an EC. + bool is_format_1() const { + assert(type != ec_none_e || nfile > 0 || mode != file_mode_none_e); + return nfile > 0 || mode != file_mode_none_e; + } +}; + + +/* + * ec_status_t represents the runtime exception condition status for + * any statement. Prior to execution, the generated code + * clears "type", and sets "source_file" and "lineno". + * + * If the statement includes some kind of ON ERROR + * clause, the generated code sets "handled" to the exception type + * handled by that clause, else it sets "handled" to ec_none_e. + * + * Post-execution, the generated code sets "type" to the appropriate + * exception, if any. The match-exception logic compares any raised + * exception to the set of declaratives, and returns a symbol-table + * index to the matching declarative, if any. + */ +class ec_status_t { + char msg[132]; +public: + ec_type_t type, handled; + cbl_name_t statement; // e.g., "ADD" + size_t lineno; + const char *source_file; + + ec_status_t() + : type(ec_none_e) + , handled(ec_none_e) + , lineno(0) + , source_file(NULL) + { + msg[0] = statement[0] = '\0'; + } + + ec_status_t& update(); + ec_status_t& enable( unsigned int mask ); + + const char * exception_location() { + snprintf(msg, sizeof(msg), "%s:%zu: '%s'", source_file, lineno, statement); + return msg; + } + ec_type_t unhandled() const { + return ec_type_t(static_cast<unsigned int>(type) + & + ~static_cast<unsigned int>(handled)); + } +}; + +#endif diff --git a/libgcobol/gcobolio.h b/libgcobol/gcobolio.h new file mode 100644 index 00000000000..061f24f309d --- /dev/null +++ b/libgcobol/gcobolio.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GCOBOLIO_H_ +#define GCOBOLIO_H_ + +#include <stdio.h> +#include <map> +#include <unordered_map> +#include <vector> + +typedef struct cblc_field_t + { + // This structure must match the code in structs.cc + unsigned char *data; // The runtime data. There is no null terminator + size_t capacity; // The size of "data" + size_t allocated; // The number of bytes available for capacity + size_t offset; // Offset from our ancestor (see note below) + char *name; // The null-terminated name of this variable + char *picture; // The null-terminated picture string. + char *initial; // The null_terminated initial value + struct cblc_field_t *parent;// This field's immediate parent field + size_t occurs_lower; // non-zero for a table + size_t occurs_upper; // non-zero for a table + size_t attr; // See cbl_field_attr_t + signed char type; // A one-byte copy of cbl_field_type_t + signed char level; // This variable's level in the naming heirarchy + signed char digits; // Digits specified in PIC string; e.g. 5 for 99v999 + signed char rdigits; // Digits to the right of the decimal point. 3 for 99v999 + int dummy; // GCC seems to want an even number of 32-bit values + } cblc_field_t; + +/* + * Implementation details + */ + +class supplemental_t; + +enum cblc_file_prior_op_t + { + file_op_none, + file_op_open, + file_op_start, + file_op_read, + file_op_write, + file_op_rewrite, + file_op_delete, + file_op_close, + }; + +/* end implementation details */ + +typedef struct cblc_file_t + { + // This structure must match the code in structs.cc + char *name; // This is the name of the structure; might be the name of an environment variable + char *filename; // The name of the file to be opened + FILE *file_pointer; // The FILE *pointer + cblc_field_t *default_record; // The record_area + size_t record_area_min; // The size of the smallest 01 record in the FD + size_t record_area_max; // The size of the largest 01 record in the FD + cblc_field_t **keys; // For relative and indexed files. The first is the primary key. Null-terminated. + int *key_numbers; // One per key -- each key has a number. This table is key_number + 1 + int *uniques; // One per key + cblc_field_t *password; // + cblc_field_t *status; // This must exist, and is the cbl_field_t version of io_status + cblc_field_t *user_status; // This might exist, and is another copy See 2014 standard, section 9.1.12 + cblc_field_t *vsam_status; // + cblc_field_t *record_length; // + supplemental_t *supplemental; // + void *implementation; // reserved for any implementation + size_t reserve; // From I-O section RESERVE clause + long prior_read_location; // Location of immediately preceding successful read + cbl_file_org_t org; // from ORGANIZATION clause + cbl_file_access_t access; // from ACCESS MODE clause + int mode_char; // 'r', 'w', '+', or 'a' from FILE OPEN statement + int errnum; // most recent errno; can't reuse "errno" as the name + file_status_t io_status; // See 2014 standard, section 9.1.12 + int padding; // Actually a char + int delimiter; // ends a record; defaults to '\n'. + int flags; // cblc_file_flags_t + int recent_char; // This is the most recent char sent to the file + int recent_key; + cblc_file_prior_op_t prior_op; // run-time type is INT + int dummy; + } cblc_file_t; + +#endif diff --git a/libgcobol/gfileio.h b/libgcobol/gfileio.h new file mode 100644 index 00000000000..e70d84fc91e --- /dev/null +++ b/libgcobol/gfileio.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GFILEIO_H_ +#define GFILEIO_H_ + +extern "C" +{ +void __gg__handle_error(const char *function, const char *msg); + +void __gg__file_open( cblc_file_t *file, + char *filename, + int mode_char, + int is_quoted); + +void __gg__file_reopen(cblc_file_t *file, int mode_char); + +void __gg__file_close( cblc_file_t *file, int how ); + +void __gg__file_read( cblc_file_t *file, + int where); + +void __gg__file_write( cblc_file_t *file, + unsigned char *location, + size_t length, + int after, + int lines, + int is_random ); +} + +#endif \ No newline at end of file diff --git a/libgcobol/gmath.h b/libgcobol/gmath.h new file mode 100644 index 00000000000..9aa8f635f4a --- /dev/null +++ b/libgcobol/gmath.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GMATH_H_ +#define GMATH_H_ + +extern "C" +{ + +} + +#endif \ No newline at end of file diff --git a/libgcobol/io.h b/libgcobol/io.h new file mode 100644 index 00000000000..0c89ad6d0c9 --- /dev/null +++ b/libgcobol/io.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * File status key values and meanings + * 0 Successful completion + * 0 No further information + * 2 Duplicate key READ + * 4 Short/long READ + * 5 OPEN optional file unavailable + * 7 Not a tape + * 1 At-end condition + * 0 Sequential READ EOF + * 4 Relative record too big + * 2 Invalid key condition + * 1 Sequence error + * 2 Duplicate key WRITE + * 3 Record not found + * 4 Sequential WRITE EOF + * 3 Permanent error + * 0 No further information + * 1 Filename inconsistent with operating system + * 4 Boundary violation + * 5 OPEN nonoptional file unavailable + * 7 OPEN EACCES + * 8 OPEN file previously closed with lock + * 9 OPEN wrong file type + * 4 Logic error condition + * 1 OPEN file already open + * 2 CLOSE file not open + * 3 REWRITE without prior READ + * 4 REWRITE/WRITE boundary violation + * 6 READ after failed READ + * 7 File not open for READ + * 8 File not open for WRITE + * 9 File not open for DELETE/REWRITE + * 9 Implementor-defined + * 0 VSAM/QSAM close on wrong thread + * 1 VSAM password failure + * 2 Logic error + * 3 Resource unavailable + * 5 Incomplete file information + * 6 VSAM no DD statement + * 7 VSAM File integrity verified + * 8 OPEN invalid environment variable contents + */ + +#ifndef IO_H_ +#define IO_H_ + +enum file_high_t { + FhSuccess = 0, + FhAtEnd = 1, + FhInvKey = 2, + FhOsError = 3, + FhLogicError = 4, + FhImplementor = 9, +}; + +enum file_status_t { + FsSuccess = FhSuccess, + FsDupRead = (FhSuccess * 10) + 2, // First digit is 0 + FsRecordLength= (FhSuccess * 10) + 4, + FsUnavail = (FhSuccess * 10) + 5, + FsNotaTape = (FhSuccess * 10) + 7, + + FsEofSeq = (FhAtEnd * 10) + 0, // First digit is 1 + FsEofRel = (FhAtEnd * 10) + 4, + + FsKeySeq = (FhInvKey * 10) + 1, // First digit is 2 + FsDupWrite = (FhInvKey * 10) + 2, + FsNotFound = (FhInvKey * 10) + 3, + FsEofWrite = (FhInvKey * 10) + 4, + + FsOsError = (FhOsError * 10) + 0, // First digit is 3 + FsNameError = (FhOsError * 10) + 1, + FsBoundary = (FhOsError * 10) + 4, + FsNoFile = (FhOsError * 10) + 5, + FsNoAccess = (FhOsError * 10) + 7, + FsCloseLock = (FhOsError * 10) + 8, + FsWrongType = (FhOsError * 10) + 9, + + FsLogicErr = (FhLogicError * 10) + 0, // First digit is 4 + FsIsOpen = (FhLogicError * 10) + 1, + FsCloseNotOpen= (FhLogicError * 10) + 2, + FsNoRead = (FhLogicError * 10) + 3, + FsBoundWrite = (FhLogicError * 10) + 4, + FsReadError = (FhLogicError * 10) + 6, + FsReadNotOpen = (FhLogicError * 10) + 7, + FsNoWrite = (FhLogicError * 10) + 8, + FsNoDelete = (FhLogicError * 10) + 9, + + FsWrongThread = (FhImplementor * 10) + 0, // First digit is 9 + FsPassword = (FhImplementor * 10) + 1, + FsLogicOther = (FhImplementor * 10) + 2, + FsNoResource = (FhImplementor * 10) + 3, + FsIncomplete = (FhImplementor * 10) + 5, + FsNoDD = (FhImplementor * 10) + 6, + FsVsamOK = (FhImplementor * 10) + 7, + FsBadEnvVar = (FhImplementor * 10) + 8, + + FsErrno = (1000000) // This means "map errno to one of the above errors" +}; + +#define FhNotOkay FsEofSeq // Values less than 10 mean the data are valid + +extern "C" file_status_t __gg__file_status_word(enum file_status_t status, + int error_number); + +#endif diff --git a/libgcobol/libgcobol.h b/libgcobol/libgcobol.h new file mode 100644 index 00000000000..bd9446adf60 --- /dev/null +++ b/libgcobol/libgcobol.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef LIBGCOBOL_H_ +#define LIBGCOBOL_H_ + +#include <stdio.h> + +#include <map> +#include <unordered_map> +#include <vector> + +#define MIN_FIELD_BLOCK_SIZE (16) + +// RUNTIME structures *must* match the ones created in structs.c and initialized +// and used in genapi.c. It's actually not all that important to emphasize that +// fact, since the compiled executable will crash and burn quickly if they don't +// match precisely. + +// Note that it must match the same structure in the GDB-COBOL debugger + +#define A_ZILLION (1000000) // Absurdly large number for __gg__call_parameter_count + +// These bits are used for the "call flags" of arithmetic operations +#define ON_SIZE_ERROR 0x01 +#define REMAINDER_PRESENT 0x02 + +/* 'offset' is overloaded for FldAlphanumeric/temporary/intermediate variables + * For such variables, offset is a copy of the initial capacity. This is in + * support of the FUNCTION TRIM function, which both needs to be able to + * reduce the capacity of the target variable, and then to reset it back to + * the original value + */ + +enum substitute_flags_t + { + substitute_anycase_e = 1, + substitute_first_e = 2, // first and last are mutually exclusive + substitute_last_e = 4, + }; + +enum cblc_file_flags_t + { + file_flag_optional_e = 0x00001, + file_flag_existed_e = 0x00002, + file_name_quoted_e = 0x00004, + file_flag_initialized_e = 0x00008, + }; + +// For indexed files, there can be one or more indexes, one per key. +// Each index is one or more fields. + +struct file_hole_t + { + long location; + size_t size; + }; + +struct file_index_t + { + std::multimap<std::vector<unsigned char>, long> key_to_position; + std::multimap<std::vector<unsigned char>, long>::iterator current_iterator; + std::multimap<std::vector<unsigned char>, long>::iterator ending_iterator; + }; + +class supplemental_t + { + public: + std::vector<file_hole_t> holes; + std::vector<file_index_t> indexes; + std::vector<int> uniques; + }; + +struct cblc_subscript_t + { + cblc_field_t *field; // That's what it usually is: + unsigned int type; // When type is FldLiteralN, field is a pointer to __int128 + }; + +#define REFER_T_ALL_FLAGS_MASK 0x0FF // We allow for seven subscripts +#define REFER_T_MOVE_ALL 0x100 // This is the move_all flag +#define REFER_T_ADDRESS_OF 0x200 // This is the address_of flag + +struct cblc_declarative_t + { + int format; + int culprit; //declarative_culprit_t + int nfiles; + }; + +/* According to the standard, the first digit of the file operation status + register is interpreted like this: + + EC-I-O-AT-END '1' + EC-I-O-INVALID-KEY '2' + EC-I-O-PERMANENT-ERROR '3' + EC-I-O-LOGIC-ERROR '4' + EC-I-O-RECORD-OPERATION '5' + EC-I-O-FILE-SHARING '6' + EC-I-O-IMP '9' + +When the tens digit is '0', there are a number of conditions for +successful completion. See section 9.1.12.1 + + 00 unqualified success + 02 duplicate key detected + 04 the data read were either too short or too long + 05 the operator couldn't find the tape + 07 somebody tried to rewind the card reader. + +For now, I am going to treat the io_status as an integer 00 through 99. I +anticipate mostly returning + 00 for ordinary success, + 04 for a mismatched record size + 10 for an end-of-file + +*/ + +// This global variable is constantly being updated with the yylineno. This is +// useful for creating error messages, and for handling EXCEPTION_CONDITIONS +extern int __gg__exception_code; +extern int __gg__exception_line_number; +extern int __gg__exception_file_status; +extern const char *__gg__exception_file_name; +extern const char *__gg__exception_statement; +extern const char *__gg__exception_source_file; +extern const char *__gg__exception_program_id; +extern const char *__gg__exception_section; +extern const char *__gg__exception_paragraph; + +extern "C" void __gg__set_exception_code( ec_type_t ec, + int from_raise_statement=0); + +extern int * __gg__fourplet_flags; + +extern cblc_field_t ** __gg__treeplet_1f; +extern size_t * __gg__treeplet_1o; +extern size_t * __gg__treeplet_1s; +extern cblc_field_t ** __gg__treeplet_2f; +extern size_t * __gg__treeplet_2o; +extern size_t * __gg__treeplet_2s; +extern cblc_field_t ** __gg__treeplet_3f; +extern size_t * __gg__treeplet_3o; +extern size_t * __gg__treeplet_3s; +extern cblc_field_t ** __gg__treeplet_4f; +extern size_t * __gg__treeplet_4o; +extern size_t * __gg__treeplet_4s; + +#if 1 + static inline + void exception_raise(ec_type_t ec_code) { __gg__set_exception_code(ec_code); } +#else +# define exception_raise(ec_code)do{__gg__set_exception_code(ec_code);}while(0); +#endif + +extern "C" __int128 __gg__power_of_ten(int n); + +extern "C" __int128 __gg__dirty_to_binary_source( const char *dirty, + int length, + int *rdigits); +extern "C" __int128 __gg__dirty_to_binary_internal( const char *dirty, + int length, + int *rdigits); +extern "C" __int128 __gg__binary_value_from_field( int *rdigits, + cblc_field_t *var); +extern "C" int __gg__compare_2( cblc_field_t *left_side, + unsigned char *left_location, + size_t left_length, + int left_attr, + bool left_all, + bool left_address_of, + cblc_field_t *right_side, + unsigned char *right_location, + size_t right_length, + int right_attr, + bool right_all, + bool right_address_of, + int second_time_through); +extern "C" void __gg__int128_to_field(cblc_field_t *tgt, + __int128 value, + int source_rdigits, + enum cbl_round_t rounded, + int *compute_error); +extern "C" void __gg__float128_to_field(cblc_field_t *tgt, + _Float128 value, + enum cbl_round_t rounded, + int *compute_error); +extern "C" void __gg__int128_to_qualified_field(cblc_field_t *tgt, + size_t offset, + size_t length, + __int128 value, + int source_rdigits, + enum cbl_round_t rounded, + int *compute_error); +extern "C" void __gg__float128_to_qualified_field(cblc_field_t *tgt, + size_t tgt_offset, + _Float128 value, + enum cbl_round_t rounded, + int *compute_error); + +extern "C" void __gg__double_to_target( cblc_field_t *tgt, + double tgt_value, + cbl_round_t rounded); +extern "C" char __gg__get_decimal_separator(); +extern "C" char __gg__get_decimal_point(); +extern "C" char * __gg__get_default_currency_string(); + +extern "C" void __gg__clock_gettime(clockid_t clk_id, struct timespec *tp); +extern "C" _Float128 __gg__float128_from_location(cblc_field_t *var, + unsigned char *location); +extern "C" void __gg__adjust_dest_size(cblc_field_t *dest, size_t ncount); +#define MINIMUM_ALLOCATION_SIZE 16 +extern "C" void __gg__realloc_if_necessary( char **dest, + size_t *dest_size, + size_t new_size); +extern "C" void __gg__set_exception_file(cblc_file_t *file); +extern "C" void __gg__internal_to_console_in_place(char *loc, size_t length); +extern "C" __int128 __gg__binary_value_from_qualified_field(int *rdigits, + cblc_field_t *var, + size_t offset, + size_t size); +extern "C" _Float128 __gg__float128_from_qualified_field(cblc_field_t *field, + size_t offset, + size_t size); +extern "C" __int128 __gg__integer_from_qualified_field(cblc_field_t *var, + size_t var_offset, + size_t var_size); +void __gg__abort(const char *msg); + + +#endif diff --git a/libgcobol/valconv.h b/libgcobol/valconv.h new file mode 100644 index 00000000000..d907e6f70ee --- /dev/null +++ b/libgcobol/valconv.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021-2025 Symas Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the Symas Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VALCONV_H +#define __VALCONV_H + +extern int __gg__decimal_point ; +extern int __gg__decimal_separator ; +extern int __gg__quote_character ; +extern int __gg__low_value_character ; +extern int __gg__high_value_character ; +extern char **__gg__currency_signs ; +extern int __gg__default_currency_sign; +extern char *__gg__ct_currency_signs[256]; // Compile-time currency signs + + +// All "ordinals" are zero-based ordinals. The COBOL spec's ordinal values +// for ordinary ASCII/EBCDIC ranger from 1 to 256, so we call them zero through +// 255. We use unsigned ints so that when an custom alphabet is described, we +// can make every unmentioned character have an ordinal greater than the final +// ordinal of the custom list. +struct alphabet_state + { + unsigned short collation[256]; + unsigned char low_char; + unsigned char high_char; + }; + +extern std::unordered_map<size_t, alphabet_state> __gg__alphabet_states; + +extern "C" + { + void __gg__realloc_if_necessary(char **dest, size_t *dest_size, size_t new_size); + void __gg__alphabet_create(cbl_encoding_t encoding, + size_t alphabet_index, + unsigned char *alphabet, + int low_char, + int high_char ); + bool __gg__string_to_numeric_edited(char * const dest, + char *source, // ASCII + int rdigits, + int is_negative, + const char *picture); + void __gg__string_to_alpha_edited(char *dest, + char *source, + int slength, + char *picture); + void __gg__currency_sign_init(); + void __gg__currency_sign(int symbol, const char *sign); + void __gg__remove_trailing_zeroes(char *p); + } + +#endif