From b5ff89770d31ed6b22bf897a08ed3ef706d7357f Mon Sep 17 00:00:00 2001 From: Bob Dubner <rdubner@symas.com> Date: Sat, 20 Apr 2024 17:21:39 -0400 Subject: [PATCH] Added very_true_register() and very_false_register(); tested true_op and false_op --- gcc/cobol/failures/.gitignore | 1 + gcc/cobol/genapi.cc | 150 ++++++++++++++++++++++++++++------ gcc/cobol/genutil.cc | 5 ++ gcc/cobol/symbols.cc | 13 ++- gcc/cobol/symbols.h | 2 + libgcobol/libgcobol.cc | 22 ++--- 6 files changed, 155 insertions(+), 38 deletions(-) diff --git a/gcc/cobol/failures/.gitignore b/gcc/cobol/failures/.gitignore index b58c7495295e..d2b80300e0aa 100644 --- a/gcc/cobol/failures/.gitignore +++ b/gcc/cobol/failures/.gitignore @@ -10,3 +10,4 @@ dump.txt *.html XXXXX* REPORTT +simon/ diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc index b372e9c635cd..656cfc3c3a20 100644 --- a/gcc/cobol/genapi.cc +++ b/gcc/cobol/genapi.cc @@ -563,12 +563,12 @@ get_class_condition_string(cbl_field_t *var) { // Since the first.name is a single character, we can do this as // a single-character pair. - + // Keep in mind that the single character might be a two-byte UTF-8 // codepoint uint8_t ch1 = domain->first.name[0]; uint8_t ch2 = domain->last.name[0]; - + gcc_assert(strlen(domain->first.name) <= 2); gcc_assert(strlen(domain->last.name) <= 2); @@ -1984,7 +1984,7 @@ cobol_compare( tree return_int, // It is the case that data.initial is in the original form seen // in the source code, which means that even in EBCDIC mode the // characters are in the "raw" state. - + static size_t buffer_size = 0; static char *buffer = NULL; raw_to_internal(&buffer, @@ -2785,7 +2785,7 @@ parser_goto( cbl_refer_t value_ref, size_t narg, cbl_label_t *labels[] ) // the other two, because it just has to jump from here to the entry point // of the paragraph [or section] Analyze(); - + SHOW_PARSE { SHOW_PARSE_HEADER @@ -4003,7 +4003,7 @@ parser_accept_envar( struct cbl_refer_t refer, struct cbl_refer_t envar ) tree env_length; refer_fill_dest(refer); - + if( envar.field->type == FldLiteralA ) { char *buffer = get_literal_string(envar.field); @@ -4812,7 +4812,7 @@ parser_assign( size_t nC, cbl_num_result_t *C, IF( gg_bitwise_and( compute_error->structs.compute_error->compute_error_code, build_int_cst_type(INT, - compute_error_exp_minus_by_frac + compute_error_exp_minus_by_frac | compute_error_divide_by_zero)), ne_op, integer_zero_node ) @@ -5250,7 +5250,7 @@ parser_exit(void) // The byte array to be returned is in returning, which is a local // variable on the stack. We need to make a copy of it to avoid the // error of returning a pointer to data on the stack. - + tree array_type = build_array_type_nelts(UCHAR, current_function->returning->data.capacity); tree retval = gg_define_variable(array_type, vs_static); @@ -5642,7 +5642,7 @@ parser_division(cbl_division_t division, IF( globals_are_initialized, eq_op, integer_zero_node ) { // one-time initialization happens here - + // We need to establish the initial value of the UPSI-1 switch register // We are using IBM's conventions: // https://www.ibm.com/docs/en/zvse/6.2?topic=SSB27H_6.2.0/fa2sf_communicate_appl_progs_via_job_control.html @@ -5962,6 +5962,12 @@ parser_logop( struct cbl_field_t *tgt, SHOW_PARSE_FIELD(" ", tgt) SHOW_PARSE_TEXT(" will be set to TRUE ") } + else if( logop == false_op) + { + SHOW_PARSE_HEADER + SHOW_PARSE_FIELD(" ", tgt) + SHOW_PARSE_TEXT(" will be set to FALSE ") + } else { SHOW_PARSE_HEADER @@ -5973,13 +5979,27 @@ parser_logop( struct cbl_field_t *tgt, } SHOW_PARSE_TEXT(" ") SHOW_PARSE_TEXT( cbl_logop_str(logop) ) - SHOW_PARSE_FIELD(" ", b) + if( b ) + { + SHOW_PARSE_FIELD(" ", b) + } } SHOW_PARSE_END } CHECK_FIELD(tgt); - CHECK_FIELD(b); + switch(logop) + { + case and_op: + case or_op: + case xor_op: + case xnor_op: + case not_op: + CHECK_FIELD(b); + break; + default: + break; + } TRACE1 { @@ -5994,15 +6014,24 @@ parser_logop( struct cbl_field_t *tgt, TRACE1_FIELD("operand A: ", a, ""); } TRACE1_INDENT - TRACE1_FIELD("operand B: ", b, ""); + if( b ) + { + TRACE1_FIELD("operand B: ", b, ""); + } TRACE1_END } } - // Make sure the variables are okay: - if( a ) + switch(logop) { - CHECK_FIELD(a); + case and_op: + case or_op: + case xor_op: + case xnor_op: + CHECK_FIELD(a); + break; + default: + break; } // This routine takes two conditionals and a logical operator. From those, @@ -6022,7 +6051,7 @@ parser_logop( struct cbl_field_t *tgt, a->name, cobol_location().first_line); gcc_assert(false); } - if( b->type != FldConditional ) + if( b && b->type != FldConditional ) { warnx("parser_logop() was called with variable %s on line %d" ", which is not a FldConditional\n", @@ -8828,7 +8857,7 @@ parser_inspect_replacing( cbl_refer_t identifier_1, { if( pcbl_refers[i].field && pcbl_refers[i].field->type == FldLiteralN ) { - fprintf(stderr, "INSPECT field %s shouldn't be a FldLiteralN\n", + fprintf(stderr, "INSPECT field %s shouldn't be a FldLiteralN\n", pcbl_refers[i].field->name); gcc_assert(false); } @@ -11076,7 +11105,7 @@ parser_call( cbl_refer_t name, switch( crv ) { - case by_default_e: + case by_default_e: assert(false); break; @@ -11241,7 +11270,7 @@ parser_call( cbl_refer_t name, build_int_cst_type(INT, narg)); refer_fill_source(name); - tree unmangled_name = gg_define_char_star(); + tree unmangled_name = gg_define_char_star(); gg_assign(unmangled_name, gg_call_expr( CHAR_P, "__gg__name_not_mangled", 1, @@ -12432,13 +12461,70 @@ parser_file_stash( struct cbl_file_t *file ) static void hijack_for_development(const char *funcname) { + /* + + To make sure that things like global symbols and whatnot get initialized, you + should probably create a source file that looks like this: + + identification division. + program-id. prog. + procedure division. + call "dubner". + end program prog. + identification division. + program-id. dubner. + procedure division. + goback. + end program dubner. + + The first program will cause all of the parser_enter_program() and + parser_division(procedure_div_e) stuff to be initialized. The second program, + named "dubner", will be hijacked and bring you here. */ + // Assume that funcname is lowercase with no hyphens enter_program_common(funcname, funcname); + parser_display_literal("You have been hijacked by a program named \"dubner\""); // It is at this point we can forcibly lay down code gg_insert_into_assembler("# HIJACKED DUBNER CODE START"); +#if 1 + cbl_field_t cond = {}; + cond.type = FldConditional; + strcpy(cond.name, "_hijacked"); + cond.var_decl_node = gg_define_variable(BOOL); + + parser_logop(&cond, NULL, true_op, NULL); + parser_if(&cond); + parser_display_literal("It is TRUE"); + parser_else(); + parser_display_literal("It is FALSE"); + parser_fi(); + + parser_logop(&cond, NULL, false_op, NULL); + parser_if(&cond); + parser_display_literal("It is TRUE"); + parser_else(); + parser_display_literal("It is FALSE"); + parser_fi(); + + cbl_field_t *very_true = cbl_field_of(symbol_at(very_true_register())); + cbl_field_t *very_false = cbl_field_of(symbol_at(very_false_register())); + + parser_if(very_true); + parser_display_literal("It is TRUE"); + parser_else(); + parser_display_literal("It is FALSE"); + parser_fi(); + + parser_if(very_false); + parser_display_literal("It is TRUE"); + parser_else(); + parser_display_literal("It is FALSE"); + parser_fi(); + gg_insert_into_assembler("# HIJACKED DUBNER CODE END"); +#endif } static void @@ -13812,7 +13898,7 @@ move_helper(cbl_refer_t destref, } } - int rounded_parameter = rounded + int rounded_parameter = rounded | ((sourceref.all || figconst ) ? REFER_ALL_BIT : 0); gg_assign(size_error, @@ -14462,7 +14548,7 @@ actually_create_the_static_field( cbl_field_t *new_var, // SIZE_T, "capacity", CONSTRUCTOR_APPEND_ELT( CONSTRUCTOR_ELTS(constr), next_field, - build_int_cst_type( SIZE_T, + build_int_cst_type( SIZE_T, new_var->data.capacity) ); next_field = TREE_CHAIN(next_field); @@ -14471,14 +14557,14 @@ actually_create_the_static_field( cbl_field_t *new_var, { CONSTRUCTOR_APPEND_ELT( CONSTRUCTOR_ELTS(constr), next_field, - build_int_cst_type( SIZE_T, + build_int_cst_type( SIZE_T, new_var->data.capacity) ); } else { CONSTRUCTOR_APPEND_ELT( CONSTRUCTOR_ELTS(constr), next_field, - build_int_cst_type( SIZE_T, + build_int_cst_type( SIZE_T, 0) ); } @@ -14637,6 +14723,17 @@ psa_global(cbl_field_t *new_var) fprintf(stderr, " };\n"); } + if( strcmp(new_var->name, "_VERY_TRUE") == 0 ) + { + new_var->var_decl_node = boolean_true_node; + return; + } + if( strcmp(new_var->name, "_VERY_FALSE") == 0 ) + { + new_var->var_decl_node = boolean_false_node; + return; + } + // global variables already have a cblc_field_t defined in constants.cc strcpy(ach, "__gg__"); @@ -14770,7 +14867,7 @@ psa_new_var_decl(cbl_field_t *new_var, const char *external_record_base) new_var->name, inter_count++); } - else if( new_var->attr & temporary_e + else if( new_var->attr & temporary_e && !is_literal(new_var) ) { static int temp_count = 1; @@ -14794,7 +14891,7 @@ psa_new_var_decl(cbl_field_t *new_var, const char *external_record_base) base_name, vs_external); } - else if( new_var->attr & (temporary_e | intermediate_e) + else if( new_var->attr & (temporary_e | intermediate_e) && new_var->type != FldLiteralA && new_var->type != FldLiteralN ) { @@ -14950,10 +15047,11 @@ parser_symbol_add(struct cbl_field_t *new_var ) { gg_assign(new_var->var_decl_node, boolean_false_node); } - + return; } + if( !(new_var->attr & initialized_e) ) { cbl_field_type_t incoming_type = new_var->type; @@ -15367,7 +15465,7 @@ parser_symbol_add(struct cbl_field_t *new_var ) if( bytes_to_allocate ) { - if( new_var->attr & (temporary_e | intermediate_e) + if( new_var->attr & (temporary_e | intermediate_e) && new_var->type != FldLiteralN && new_var->type != FldLiteralA ) { diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc index 38b3ef5be05c..c0be6cfba5ad 100644 --- a/gcc/cobol/genutil.cc +++ b/gcc/cobol/genutil.cc @@ -2479,6 +2479,11 @@ refer_fill_internal(cbl_refer_t &refer, refer_type_t refer_type) // This routine establishes the qualifed .qual_data and .qual_size values // from the original .data and .capacity values + if( refer.field->type == FldConditional ) + { + gcc_assert(false); + } + gg_assign(member(refer.refer_decl_node, "qual_data"), member(refer.field->var_decl_node, "data")); if( refer.field->attr & (intermediate_e | any_length_e) ) diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index d02a01c3dc11..9e4af26aa7b1 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -72,7 +72,8 @@ static struct symbol_table_t { size_t capacity, nelem; size_t first_program, procedures; struct { - size_t file_status, linage_counter, return_code, exception_condition; + size_t file_status, linage_counter, return_code, + exception_condition, very_true, very_false; } registers; struct symbol_elem_t *elems; @@ -179,6 +180,8 @@ static char decimal_point = '.'; size_t file_status_register() { return symbols.registers.file_status; } size_t return_code_register() { return symbols.registers.return_code; } +size_t very_true_register() { return symbols.registers.very_true; } +size_t very_false_register() { return symbols.registers.very_false; } size_t ec_register() { return symbols.registers.exception_condition; } cbl_refer_t * @@ -2114,6 +2117,12 @@ symbol_table_init(void) { "QUOTES", 0, {1,1,0,0, "\"\0\xFF", NULL, { NULL }, { NULL } }, NULL }, { 0, FldPointer, FldPointer, constq , 0, 0, 0, nonarray, 0, "NULLS", 0, {8,8,0,0, zeroes_for_null_pointer, NULL, { NULL }, { NULL } }, NULL }, + // These last two don't require actual storage; they get BOOL var_decl_node + // in parser_symbol_add() + { 0, FldConditional, FldInvalid, constant_e , 0, 0, 0, nonarray, 0, + "_VERY_TRUE", 0, {1,1,0,0, "", NULL, { NULL }, { NULL } }, NULL }, + { 0, FldConditional, FldInvalid, constant_e , 0, 0, 0, nonarray, 0, + "_VERY_FALSE", 0, {1,1,0,0, "", NULL, { NULL }, { NULL } }, NULL }, }; for( struct cbl_field_t *f = constants; f < constants + COUNT_OF(constants); f++ ) { @@ -2198,6 +2207,8 @@ symbol_table_init(void) { "LINAGE-COUNTER")); symbols.registers.file_status = symbol_index(symbol_field(0,0, "_FILE_STATUS")); symbols.registers.return_code = symbol_index(symbol_field(0,0, "RETURN-CODE")); + symbols.registers.very_true = symbol_index(symbol_field(0,0, "_VERY_TRUE")); + symbols.registers.very_false = symbol_index(symbol_field(0,0, "_VERY_FALSE")); if( getenv(__func__) ) symbols_dump(0, true); } diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index c4acbfae0e63..aff38a8eaa3e 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -2186,6 +2186,8 @@ size_t symbol_field_capacity( const cbl_field_t *field ); size_t file_status_register(); size_t return_code_register(); +size_t very_true_register(); +size_t very_false_register(); size_t ec_register(); static inline size_t upsi_register() { diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index 2d49468f287c..1777d1bdea96 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -2757,7 +2757,7 @@ format_for_display_internal(char **dest, memset(buffer, internal_0, new_length); char *p = buffer; char *s = *dest; - if( ((*dest)[0]&0xFF) < internal_0 + if( ((*dest)[0]&0xFF) < internal_0 || ((*dest)[0]&0xFF) > internal_9 ) { *p++ = (*dest)[0]; @@ -3989,8 +3989,8 @@ __gg__initialize_variable(cblc_refer_t *var_ref, // Make a copy of the field pointer we're working with as a convenience: cblc_field_t *var = var_ref->field; - if( var_ref->field->data == NULL - && var_ref->field->attr & (temporary_e | intermediate_e) + if( var_ref->field->data == NULL + && var_ref->field->attr & (temporary_e | intermediate_e) && var_ref->field->type != FldLiteralA && var_ref->field->type != FldLiteralN ) { @@ -4311,7 +4311,7 @@ __gg__initialize_variable(cblc_refer_t *var_ref, // See the comment up above about suppressing and restoring // BLANK WHEN ZERO during initialization. var->attr |= (save_the_attribute&blank_zero_e); - } + }//initial static void alpha_to_alpha_move_from_location(cblc_refer_t *dest, @@ -5178,7 +5178,7 @@ __gg__move_literala(struct cblc_refer_t *dest, case FldGroup: case FldAlphanumeric: { - alpha_to_alpha_move_from_location(dest, str, strlen, move_all); + alpha_to_alpha_move_from_location(dest, str, strlen, move_all); break; } @@ -5283,7 +5283,7 @@ __gg__move_literala(struct cblc_refer_t *dest, if( !moved ) { - fprintf(stderr, "%s() %s:%d -- We were unable to do a move to " + fprintf(stderr, "%s() %s:%d -- We were unable to do a move to " "type %d\n", __func__, __FILE__, __LINE__, dest->field->type); @@ -7719,7 +7719,7 @@ is_numeric_display_numeric(cblc_refer_t *str) // all remaining characters are supposed to be zero through nine while( digits < digits_e ) { - if( (unsigned char)(*digits)<internal_0 + if( (unsigned char)(*digits)<internal_0 || (unsigned char)(*digits)>internal_9 ) { retval = 0; @@ -7811,7 +7811,7 @@ is_alpha_a_number(cblc_refer_t *str) int retval = 1; for( size_t i=0; i<str->qual_size; i++ ) { - if( (unsigned char)str->qual_data[i] < internal_0 + if( (unsigned char)str->qual_data[i] < internal_0 || (unsigned char)str->qual_data[i] > internal_9 ) { retval = 0; @@ -7889,7 +7889,7 @@ __gg__classify( classify_t type, cblc_refer_t *str) } // If necessary, this could be sped up with the creation of // appropriate mapping tables. - + // The oddball construction of this if() statement is a consequence of // EBCDIC. Because of peculiarities going all the back to the encoding // of characters on IBM cards, where it wasn't a good idea to have too @@ -9670,7 +9670,7 @@ __gg__parameter_count_push( char *called_function, // __gg__parameter_count_pop called_functions.push_back(called_function); parameter_counts.push_back(parameter_count); - + int *plengths = (int *)malloc(parameter_count); memcpy(plengths, parameter_lengths, parameter_count * sizeof(int)); parameter_lengthss.push_back(plengths); @@ -9766,7 +9766,7 @@ find_in_dirs(const char *dirs, char *unmangled_name, char *mangled_name) break; } size_t len = strlen(entry->d_name); - if( len > 3 + if( len > 3 && entry->d_name[len-3] == '.' && entry->d_name[len-2] == 's' && entry->d_name[len-1] == 'o' -- GitLab