diff options
author | James K. Lowden <jklowden@symas.com> | 2025-03-06 16:25:09 -0500 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2025-03-11 07:48:21 +0100 |
commit | 3c5ed996ac94a15bc2929155f2c69cc85eef89f7 (patch) | |
tree | c365f6e25814ca3e88ae3fed34ca7a327a016540 /gcc/cobol/structs.cc | |
parent | a0754187274a36443707eab5506ae53ab1d71ad2 (diff) | |
download | gcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.zip gcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.tar.gz gcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.tar.bz2 |
COBOL: Frontend
gcc/cobol/
* LICENSE: New file.
* Make-lang.in: New file.
* config-lang.in: New file.
* lang.opt: New file.
* lang.opt.urls: New file.
* cbldiag.h: New file.
* cdfval.h: New file.
* cobol-system.h: New file.
* copybook.h: New file.
* dts.h: New file.
* exceptg.h: New file.
* gengen.h: New file.
* genmath.h: New file.
* genutil.h: New file.
* inspect.h: New file.
* lang-specs.h: New file.
* lexio.h: New file.
* parse_ante.h: New file.
* parse_util.h: New file.
* scan_ante.h: New file.
* scan_post.h: New file.
* show_parse.h: New file.
* structs.h: New file.
* symbols.h: New file.
* token_names.h: New file.
* util.h: New file.
* cdf-copy.cc: New file.
* lexio.cc: New file.
* scan.l: New file.
* parse.y: New file.
* genapi.cc: New file.
* genapi.h: New file.
* gengen.cc: New file.
* genmath.cc: New file.
* genutil.cc: New file.
* cdf.y: New file.
* cobol1.cc: New file.
* convert.cc: New file.
* except.cc: New file.
* gcobolspec.cc: New file.
* structs.cc: New file.
* symbols.cc: New file.
* symfind.cc: New file.
* util.cc: New file.
* gcobc: New file.
* gcobol.1: New file.
* gcobol.3: New file.
* help.gen: New file.
* udf/stored-char-length.cbl: New file.
Diffstat (limited to 'gcc/cobol/structs.cc')
-rw-r--r-- | gcc/cobol/structs.cc | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/gcc/cobol/structs.cc b/gcc/cobol/structs.cc new file mode 100644 index 0000000..bf98d1f --- /dev/null +++ b/gcc/cobol/structs.cc @@ -0,0 +1,333 @@ +/* + * 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. + */ + /* This module exists in support of genapi.c + + It creates the declarations for structures that are implemented in the + the libgcobol run-time library. These are type_decls; the analog in the + C world would be that these are typedefs: + + typedef struct XXX_ + { + .... + } XXX; + + These functions don't, on their own, allocate any storage. That gets done + when the type_decl is handed to the build_decl routine, which creates + a var_decl. And that gets added to the GENERIC tree when the var_decl + is turned into a decl_expr by build1() and then the decl_expr is added + to the current statement list. + + Your best bet is to simply emulate the code here to create the type_decl + for each structure, and then just use gg_declare_variable() to create the + storage when you need it. + + Learning from the code in genapi.c is your best bet. + + */ + +#include "cobol-system.h" +#include "coretypes.h" +#include "tree.h" +#define HOWEVER_GCC_DEFINES_TREE 1 +#include "ec.h" +#include "common-defs.h" +#include "util.h" +#include "cbldiag.h" +#include "symbols.h" +#include "gengen.h" + +tree +var_decl_node_p_of( cbl_field_t *var ) + { + if( var->var_decl_node ) + { + return gg_get_address_of(var->var_decl_node); + } + else + { + return null_pointer_node; + } + } + +// These routines return references, rather than values. So, in cases +// like MOVE TABLE(a) TO TABLE (b), you need to gg_assign the returned +// value elsewhere, rather than use them directly, because the second +// refer_qualification calculation will overwrite the first. + +tree +member(tree var, const char *member_name) + { + return gg_struct_field_ref(var, member_name); + } + +tree +member(cbl_field_t *var, const char *member_name) + { + return gg_struct_field_ref(var->var_decl_node, member_name); + } + +tree +member(cbl_file_t *var, const char *member_name) + { + return gg_struct_field_ref(var->var_decl_node, member_name); + } + +void +member(tree var, const char *member_name, int value) + { + gg_assign( member(var, member_name), + build_int_cst_type(INT, value) ); + } + +void +member(tree var, const char *member_name, tree value) + { + gg_assign( member(var, member_name), + value ); + } + +void +member(cbl_field_t *var, const char *member_name, tree value) + { + gg_assign( member(var->var_decl_node, member_name), + value ); + } + +tree +member2(tree var, const char *member_name, const char *submember) + { + tree level1 = member(var, member_name); + return member(level1, submember ); + } + +void +member2(tree var, const char *member_name, const char *submember, int value) + { + tree level1 = member(var, member_name); + tree level2 = member(level1, submember ); + gg_assign(level2, build_int_cst_type(INT, value) ); + } + +void +member2(tree var, const char *member_name, const char *submember, tree value) + { + tree level1 = member(var, member_name); + tree level2 = member(level1, submember ); + gg_assign(level2, value); + } + +void +member3(tree var, const char *mem, const char *sub2, const char *sub3, tree value) + { + tree level1 = member(var, mem); + tree level2 = member(level1, sub2 ); + tree level3 = member(level2, sub3 ); + gg_assign(level3, value); + } + +tree cblc_field_type_node; +tree cblc_field_p_type_node; +tree cblc_field_pp_type_node; +tree cblc_file_type_node; +tree cblc_file_p_type_node; +tree cblc_goto_type_node; +tree cblc_int128_type_node; + +// The following functions return type_decl nodes for the various structures + +static tree +create_cblc_field_t() + { + /* + typedef struct cblc_field_t + { + 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 + 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 + } cblc_field_t; + */ + tree retval = NULL_TREE; + retval = gg_get_filelevel_struct_type_decl( "cblc_field_t", + 16, + UCHAR_P, "data", + SIZE_T, "capacity", + SIZE_T, "allocated", + SIZE_T, "offset", + CHAR_P, "name", + CHAR_P, "picture", + CHAR_P, "initial", + CHAR_P, "parent", + SIZE_T, "occurs_lower", + SIZE_T, "occurs_upper", + SIZE_T, "attr", + SCHAR, "type", + SCHAR, "level", + SCHAR, "digits", + SCHAR, "rdigits", + INT, "dummy"); // Needed to make it an even number of 32-bit ints + retval = TREE_TYPE(retval); + + return retval; + } + +static tree +create_cblc_file_t() + { + // When doing FILE I/O, you need the cblc_file_t structure + + /* +typedef struct cblc_file_t + { + 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; + int dummy // We need an even number of INT + } cblc_file_t; + */ + + tree retval = NULL_TREE; + retval = gg_get_filelevel_struct_type_decl( "cblc_file_t", + 30, + CHAR_P, "name", + CHAR_P, "filename", + FILE_P, "file_pointer", + cblc_field_p_type_node, "default_record", + SIZE_T, "record_area_min", + SIZE_T, "record_area_max", + build_pointer_type(cblc_field_p_type_node), "keys", + build_pointer_type(INT),"key_numbers", + build_pointer_type(INT),"uniques", + cblc_field_p_type_node, "password", + cblc_field_p_type_node, "status", + cblc_field_p_type_node, "user_status", + cblc_field_p_type_node, "vsam_status", + cblc_field_p_type_node, "record_length", + VOID_P, "supplemental", + VOID_P, "implementation", + SIZE_T, "reserve", + LONG, "prior_read_location", + INT, "org", + INT, "access", + INT, "mode_char", + INT, "errnum", + INT, "io_status", + INT, "padding", + INT, "delimiter", + INT, "flags", + INT, "recent_char", + INT, "recent_key", + INT, "prior_op", + INT, "dummy"); + retval = TREE_TYPE(retval); + return retval; + } + +static tree +create_cblc_int128_t() + { + /* + // GCC-13 can't initialize __int64 variables, which is something we need to + // be able to do. So, I created this union. The array can be initialized, + // and thus we do an end run around the problem. Annoying, but not fatally + // so. + + typedef union cblc_int128_t + { + unsigned char array16[16]; + __uint128 uval128; + __int128 sval128; + } cblc_int128_t; + */ + tree retval = NULL_TREE; + tree array_type = build_array_type_nelts(UCHAR, 16); + retval = gg_get_filelevel_union_type_decl( + "cblc_int128_t", + 3, + array_type, "array16" , + UINT128, "uval128" , + INT128, "sval128" ); + retval = TREE_TYPE(retval); + return retval; + } + +void +create_our_type_nodes() + { + static bool just_once = true; + if( just_once ) + { + just_once = false; + cblc_field_type_node = create_cblc_field_t(); + cblc_field_p_type_node = build_pointer_type(cblc_field_type_node); + cblc_field_pp_type_node = build_pointer_type(cblc_field_p_type_node); + cblc_file_type_node = create_cblc_file_t(); + cblc_file_p_type_node = build_pointer_type(cblc_file_type_node); + cblc_int128_type_node = create_cblc_int128_t(); + } + } + |