diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 8fd95b8c6..6113100e5 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -1,4 +1,14 @@ +2023-07-15 Fabrice Le Fessant + + * cobc.c, output_tree.c: new options to dump the AST in text format: + --output-tree=, and --output-tree-flags=. Format is + either OCaml (for files with .ml extension) or JSON. Flags are + '+/-' for enable/disable, 'c' for cb_common, 'l' for locations, + 't' for types, 'p' for pointers, 'i' for indentation, 'n' for + newlines, 'A' for all infos. COB_OUTPUT_TREE_FLAGS env variable + can also be used to set the flags. + 2023-07-11 Fabrice Le Fessant * parser.y: fix code generation for OPEN/CLOSE with multiple diff --git a/cobc/Makefile.am b/cobc/Makefile.am index 444987fc6..198fda8e7 100644 --- a/cobc/Makefile.am +++ b/cobc/Makefile.am @@ -23,7 +23,7 @@ bin_PROGRAMS = cobc cobc_SOURCES = cobc.c cobc.h ppparse.y pplex.c parser.y scanner.c config.c \ reserved.c error.c tree.c tree.h field.c typeck.c codegen.c help.c \ config.def flag.def warning.def codeoptim.def ppparse.def \ - codeoptim.c replace.c + codeoptim.c replace.c output_tree.c #cobc_SOURCES = cobc.c cobc.h ppparse.y pplex.l parser.y scanner.l config.c diff --git a/cobc/cobc.c b/cobc/cobc.c index 4bb9768a1..f45bf8374 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -106,7 +106,8 @@ enum compile_level { #define CB_FLAG_GETOPT_EBCDIC_TABLE 14 #define CB_FLAG_GETOPT_DEFAULT_COLSEQ 15 #define CB_FLAG_MEMORY_CHECK 16 - +#define CB_FLAG_OUTPUT_TREE 17 +#define CB_FLAG_OUTPUT_TREE_FLAGS 18 /* Info display limits */ #define CB_IMSG_SIZE 24 @@ -444,6 +445,8 @@ static int save_all_src = 0; static signed int save_c_src = 0; static signed int verbose_output = 0; static int cb_coverage_enabled = 0; +static char* output_tree_to_file = NULL; +static char* output_tree_flags = NULL; static int cob_optimize = 0; @@ -608,6 +611,8 @@ static const struct option long_options[] = { {"MT", CB_RQ_ARG, NULL, '!'}, {"MF", CB_RQ_ARG, NULL, '@'}, {"coverage", CB_NO_ARG, &cb_coverage_enabled, 1}, + {"output-tree", CB_RQ_ARG, NULL, CB_FLAG_OUTPUT_TREE}, + {"output-tree-flags", CB_RQ_ARG, NULL, CB_FLAG_OUTPUT_TREE_FLAGS}, {"P", CB_OP_ARG, NULL, 'P'}, {"Xref", CB_NO_ARG, NULL, 'X'}, {"use-extfh", CB_RQ_ARG, NULL, 9}, /* this is used by COBOL-IT; Same is -fcallfh= */ @@ -3638,6 +3643,22 @@ process_command_line (const int argc, char **argv) } break; + case CB_FLAG_OUTPUT_TREE: + if (output_tree_to_file) + cobc_main_free (output_tree_to_file); + output_tree_to_file = cobc_main_strdup (cob_optarg); + break; + + case CB_FLAG_OUTPUT_TREE_FLAGS: + if (output_tree_flags){ + char* old = output_tree_flags; + output_tree_flags = cobc_main_stradd_dup(output_tree_flags, cob_optarg); + cobc_main_free (old); + } else { + output_tree_flags = cobc_main_strdup (cob_optarg); + } + break; + case '@': /* -MF */ cb_depend_file = fopen (cob_optarg, "w"); @@ -8079,6 +8100,9 @@ process_translate (struct filename *fn) } } + if (output_tree_to_file) + cb_output_tree_to_file (current_program, output_tree_to_file, output_tree_flags); + /* Translate to C */ codegen (current_program, fn->translate); diff --git a/cobc/codegen.c b/cobc/codegen.c index 61b3ee4b6..57ab17027 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -13722,6 +13722,7 @@ codegen_internal (struct cb_program *prog, const int subsequent_call) } } + /* output the procedure division code */ output_internal_function (prog, prog->parameter_list); if (!prog->next_program) { diff --git a/cobc/help.c b/cobc/help.c index 4f4dda32b..d1ec9a23d 100644 --- a/cobc/help.c +++ b/cobc/help.c @@ -123,6 +123,7 @@ cobc_print_usage_common_options (void) puts (_(" -A add to the C compile phase")); puts (_(" -Q add to the C link phase")); puts (_(" --coverage instrument generated binaries for coverage")); + puts (_(" --output-tree= output the AST to for debugging")); puts (_(" --conf= user-defined dialect configuration; see -std")); puts (_(" --list-reserved display reserved words")); puts (_(" --list-intrinsics display intrinsic functions")); diff --git a/cobc/output_tree.c b/cobc/output_tree.c new file mode 100644 index 000000000..0daadb451 --- /dev/null +++ b/cobc/output_tree.c @@ -0,0 +1,2122 @@ +/* + Copyright (C) 2001-2023 Free Software Foundation, Inc. + Written by Keisuke Nishida, Roger While, Simon Sobisch, Ron Norman, + Edward Hart, Fabrice Le Fessant + + This file is part of GnuCOBOL. + + The GnuCOBOL compiler is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + GnuCOBOL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GnuCOBOL. If not, see . +*/ + + +#include "config.h" + +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include + +#include "cobc.h" +#include "../libcob/coblocal.h" +#include "tree.h" + +#define INDENT_STEP 3 +#define MAX_INDENT 200 + +/* used to create the indentation spaces */ +static char space_buffer[INDENT_STEP*MAX_INDENT+1]; + +/* used to know if we have already encountered a pointer */ +static void *pointer_buffer[MAX_INDENT]; + +/* used to know if we need a record/list internal delimiter */ +static void *nfields_buffer[MAX_INDENT]; + +/* current indentation */ +static int indent = 0; + +/* field descriptor of tree output */ +static FILE* fd = NULL; + +static const int max_spaces = INDENT_STEP * MAX_INDENT; + +/* flag: whether we should print cb_tree_common header */ +int cb_output_tree_with_common = 0; + +/* flag: whether we should print locations, only in with_common=1 mode */ +int cb_output_tree_with_loc = 0; + +/* flag: whether we should print types */ +int cb_output_tree_with_type = 0; + +/* flag: whether we should add a field with record pointer address */ +int cb_output_tree_with_pointer = 0; + +/* flag: whether we should indent the file */ +int cb_output_tree_with_indent = 1; + +/* flag: whether we should print newlines in the file */ +int cb_output_tree_with_newlines = 1; + +static void indent_init (void) +{ + int i; + for (i=0; i< max_spaces; i++) space_buffer[i] = ' '; + space_buffer[max_spaces] = 0; +} + +static void output_indent (void) +{ + if (cb_output_tree_with_indent && cb_output_tree_with_newlines){ + int nspaces = INDENT_STEP * indent; + if (nspaces > max_spaces) nspaces = max_spaces; + fprintf (fd, "%s", space_buffer + max_spaces - nspaces); + } +} + +static const char* newline(void) +{ + if (cb_output_tree_with_newlines) return "\n"; + return ""; +} + +static int known_pointer (void* x) +{ + int i ; + for (i=0; i filename && *arg != '.' ) arg--; + + if (!strcasecmp(arg, ".ml")){ + /* OCaml format. Suitable to load inside the OCaml + interpreter for automated processing. + + If you change the format of type in format_header, you should also + modify the format_date variable. + */ + + fmt.format_header = "\n" + "type t =\n" + "| NULL\n" + "| INT of int\n" + "| CHAR of char\n" + "| STRING of string\n" + "| CONSTR of string * t\n" + "| LIST of t list\n" + "| RECORD of ( string * t) list\n" + "| POINTER of int64\n" + "| FLAGS of string list\n" + "let format_date = \"GNUCOBOL-2023-07-15\"\n" + "\n" + "let tree =\n" + ; + + fmt.format_trailer = "\n" + "let () =\n" + " let oc = open_out_bin \"tree.cbb\" in\n" + " output_value oc ( format_date : string );\n" + " output_value oc ( tree : t);\n" + " close_out oc\n" + "\n"; + fmt.format_begin_field = "\""; + fmt.format_end_field = "\", "; + + fmt.format_begin_record = "RECORD ["; + fmt.format_delim_record = ";" ; + fmt.format_last_delim_record = ";"; + fmt.format_end_record = "]"; + + fmt.format_begin_list = "LIST ["; + fmt.format_delim_list = ";"; + fmt.format_last_delim_list = ";"; + fmt.format_end_list = "]"; + + fmt.format_null = "NULL"; + fmt.format_begin_constr = "CONSTR (\""; + fmt.format_delim_constr = "\", "; + fmt.format_end_constr = ")"; + fmt.format_begin_pointer = "POINTER "; + fmt.format_end_pointer = "L"; + fmt.format_begin_char = "CHAR '"; + fmt.format_end_char = "'"; + fmt.format_begin_string = "STRING \""; + fmt.format_end_string = "\""; + fmt.format_begin_int = "INT "; + fmt.format_end_int = ""; + + fmt.format_begin_flags = "FLAGS ["; + fmt.format_begin_flag = "\""; + fmt.format_end_flag = "\";"; + fmt.format_end_flags = "]"; + + cb_output_tree_with_common = 1; + cb_output_tree_with_loc = 1; + cb_output_tree_with_type = 1; + cb_output_tree_with_pointer = 1; + cb_output_tree_with_indent = 1; + cb_output_tree_with_newlines = 1; + + return; + } + + /* Default is to use JSON */ + /* Standard JSON format. Tests validated by jsonlint-php. */ + + fmt.format_header = ""; + fmt.format_trailer = ""; + + fmt.format_begin_field = "\""; + fmt.format_end_field = "\": "; + + fmt.format_begin_record = "{"; + fmt.format_delim_record = ","; + fmt.format_last_delim_record = ""; + fmt.format_end_record = "}"; + + fmt.format_begin_list = "["; + fmt.format_delim_list = ","; + fmt.format_last_delim_list = ""; + fmt.format_end_list = "]"; + + fmt.format_begin_flags = "["; + fmt.format_begin_flag = "\""; + fmt.format_end_flag = "\","; + fmt.format_end_flags = " NULL]"; + + fmt.format_null = "null"; + fmt.format_begin_constr = "{ \"type_\": \""; + fmt.format_delim_constr = "\", \"value_\": "; + fmt.format_end_constr = " }"; + fmt.format_begin_pointer = "\" "; + fmt.format_end_pointer = "\""; + fmt.format_begin_char = "\""; + fmt.format_end_char = "\""; + fmt.format_begin_string = "\""; + fmt.format_end_string = "\""; + fmt.format_begin_int = ""; + fmt.format_end_int = ""; +} + +static +void set_flags (const char* flags) +{ + int sign = 1; + int i; + int len = strlen(flags); + + for(i=0; i< len; i++){ + switch(flags[i]){ + case '+': sign = 1; break; + case '-': sign = 0; break; + case 'c': + cb_output_tree_with_common = sign; + break; + case 'l': + cb_output_tree_with_loc = sign; + if (cb_output_tree_with_loc){ + cb_output_tree_with_common = 1; + } + break; + case 't': + cb_output_tree_with_type = sign; + break; + case 'p': + cb_output_tree_with_pointer = sign; + break; + case 'i': + cb_output_tree_with_indent = sign; + if (cb_output_tree_with_indent) + cb_output_tree_with_newlines = 1; + break; + case 'n': + cb_output_tree_with_newlines = sign; + if (!cb_output_tree_with_newlines) + cb_output_tree_with_indent = 0; + break; + case 'A': + cb_output_tree_with_loc = sign; + cb_output_tree_with_common = sign; + cb_output_tree_with_type = sign; + cb_output_tree_with_pointer = sign; + cb_output_tree_with_indent = 1-sign; + cb_output_tree_with_newlines = 1-sign; + break; + default: + cobc_err_exit ("--output-tree-flags: unknown flag '%c', expecting '+-cltpinA'", flags[i]); + } + } +} + +#define FIELD_SET(field_name) \ + output_sequence_delim (fmt.format_delim_record); \ + output_indent(); \ + fprintf (fd, "%s%s%s", fmt.format_begin_field, #field_name, fmt.format_end_field); \ + fflush (fd); \ + +#define FIELD(struct_name, field_name) \ + if ( x -> field_name ){ \ + FIELD_SET(field_name); \ + output_##struct_name ( x -> field_name ); \ + fflush (fd); \ + } + +#define FIELD_INLINE(struct_name, field_name) \ + FIELD_SET(field_name); \ + output_##struct_name ( & x -> field_name ); \ + fflush (fd); + + +#define FIELD_INLINE_TODO(struct_name, field_name) \ + FIELD_SET(field_name); \ + output_constr_string ("TODO", #struct_name); \ + fflush (fd); + +#define FIELD_TODO(struct_name, field_name) \ + if ( x -> field_name ){ \ + FIELD_INLINE_TODO (struct_name, field_name); \ + } + +#define FIELD_STOP(struct_name, field_name) \ + if ( x -> field_name ){ \ + FIELD_SET(field_name); \ + output_constr_pointer ("STOP", x); \ + fflush (fd); \ + } + +#define BEGIN_COMMON_RECORD() \ + fprintf (fd, "%s", fmt.format_begin_record); \ + nfields_buffer[indent] = 0; \ + indent++ + +#define END_RECORD() \ + output_sequence_end (fmt.format_last_delim_record); \ + indent--; \ + output_indent(); \ + fprintf (fd, "%s", fmt.format_end_record) + +#define BEGIN_RECORD(struct_name) \ + if (!x) { fprintf (fd, "%s", fmt.format_null); return; } \ + BEGIN_COMMON_RECORD (); \ + if (cb_output_tree_with_type){ \ + FIELD_SET(type_); \ + output_string (#struct_name); \ + } \ + if (cb_output_tree_with_pointer){ \ + FIELD_SET(address_); \ + output_pointer (x); \ + } \ + if (known_pointer(x)) { \ + FIELD_SET(ellipsis_); \ + output_int (1); \ + END_RECORD (); \ + return; \ + } + +#define BEGIN_TREE_RECORD(struct_name) \ + BEGIN_RECORD(struct_name); \ + FIELD_INLINE (cb_tree_common, common) + +#define END_LIST() \ + output_sequence_end (fmt.format_last_delim_record); \ + indent--; \ + output_indent (); \ + fprintf (fd, "%s", fmt.format_end_list) + +#define BEGIN_LIST() \ + fprintf (fd, "%s", fmt.format_begin_list); \ + if (!x) { fprintf(fd, "%s", fmt.format_end_list); return; } \ + nfields_buffer[indent] = 0; \ + indent++ + +#define LIST_ELEM(struct_name, elem) \ + output_sequence_delim (fmt.format_delim_list); \ + output_indent(); \ + output_##struct_name (elem); + +static void output_cb_tree (cb_tree x); +static void output_cb_field (struct cb_field *x); +static void output_cb_label (struct cb_label *x); +static void output_cb_file (struct cb_file *x); +static void output_cb_cd (struct cb_cd *x); +static void output_cb_report (struct cb_report *x); + +static +void output_sequence_delim (const char *delim) +{ + if (nfields_buffer[indent-1]) + fprintf (fd, "%s%s", delim, newline()); + else + fprintf (fd, "%s", newline()); + nfields_buffer[indent-1]++; +} + +static +void output_sequence_end (const char *delim) +{ + if (nfields_buffer[indent-1]) + fprintf (fd, "%s%s", delim, newline()); + else + fprintf (fd, "%s", newline()); +} + +static +void output_int (int x) +{ + fprintf (fd, "%s%d%s", fmt.format_begin_int, x, fmt.format_end_int); +} + +static +void output_uint (unsigned int x) +{ + fprintf (fd, "%s%d%s", fmt.format_begin_int, x, fmt.format_end_int); +} + +static +void output_cob_u32_t (cob_u32_t x) +{ + fprintf (fd, "%s%d%s", fmt.format_begin_int, x, fmt.format_end_int); +} + +static +void output_size_t (size_t x) +{ + fprintf (fd, "%s%lu%s", fmt.format_begin_int, x, fmt.format_end_int); +} + +static +void output_uchar (unsigned char x) +{ + fprintf (fd, "%s%c%s", fmt.format_begin_char, x, fmt.format_end_char); +} + +static +void output_string (const char* x) +{ + if (x){ + fprintf (fd, "%s%s%s", fmt.format_begin_string, x, fmt.format_end_string); + } else { + fprintf (fd, "%s", fmt.format_null); + } +} + +static +void output_constr_string (const char* type, const char* value) +{ + if (cb_output_tree_with_common){ + fprintf (fd, "%s%s%s", fmt.format_begin_constr, type, fmt.format_delim_constr); + output_string (value); + fprintf (fd, "%s", fmt.format_end_constr); + } else { + output_string (value); + } +} + +static +void output_pointer (void* x) +{ + fprintf (fd, "%s%p%s", fmt.format_begin_pointer, x, fmt.format_end_pointer); +} + +static +void output_constr_pointer (const char* type, void* value) +{ + if (cb_output_tree_with_pointer){ + fprintf (fd, "%s%s%s", fmt.format_begin_constr, type, fmt.format_delim_constr); + output_pointer (value); + fprintf (fd, "%s", fmt.format_end_constr); + } else { + output_string (type); + } +} + +static +void output_ustring (const unsigned char* x) +{ + if (x){ + fprintf (fd, "%s%s%s", fmt.format_begin_string, x, fmt.format_end_string); + } else { + fprintf (fd, "%s", fmt.format_null); + } +} + +static +void output_cb_tag (enum cb_tag x) +{ + output_constr_string ("cb_tag", cb_enum_explain (x)); +} + +static +void output_cb_category (enum cb_category x) +{ + const char* s = "CB_CATEGORY_UNKNOWN"; + switch (x){ + case CB_CATEGORY_UNKNOWN: break; + case CB_CATEGORY_ALPHABETIC: s = "CATEGORY_ALPHABETIC"; break; + case CB_CATEGORY_ALPHANUMERIC: s = "CATEGORY_ALPHANUMERIC"; break; + case CB_CATEGORY_ALPHANUMERIC_EDITED: s = "CATEGORY_ALPHANUMERIC_EDITED"; break; + case CB_CATEGORY_BOOLEAN: s = "CATEGORY_BOOLEAN"; break; + case CB_CATEGORY_INDEX: s = "CATEGORY_INDEX"; break; + case CB_CATEGORY_NATIONAL: s = "CATEGORY_NATIONAL"; break; + case CB_CATEGORY_NATIONAL_EDITED: s = "CATEGORY_NATIONAL_EDITED"; break; + case CB_CATEGORY_NUMERIC: s = "CATEGORY_NUMERIC"; break; + case CB_CATEGORY_NUMERIC_EDITED: s = "CATEGORY_NUMERIC_EDITED"; break; + case CB_CATEGORY_OBJECT_REFERENCE: s = "CATEGORY_OBJECT_REFERENCE"; break; + case CB_CATEGORY_DATA_POINTER: s = "CATEGORY_DATA_POINTER"; break; + case CB_CATEGORY_PROGRAM_POINTER: s = "CATEGORY_PROGRAM_POINTER"; break; + case CB_CATEGORY_FLOATING_EDITED: s = "CATEGORY_FLOATING_EDITED"; break; + case CB_CATEGORY_ERROR: s = "CATEGORY_ERROR"; break; + } + + output_constr_string ("cb_category", s); +} + +#if 0 +const char* cb_explain_class (enum cb_class x) +{ + switch (x){ + case CB_CLASS_UNKNOWN: return "CLASS_UNKNOWN"; /* 0 */ + case CB_CLASS_ALPHABETIC: return "CLASS_ALPHABETIC"; /* 1 */ + case CB_CLASS_ALPHANUMERIC: return "CLASS_ALPHANUMERIC"; /* 2 */ + case CB_CLASS_BOOLEAN: return "CLASS_BOOLEAN"; /* 3 */ + case CB_CLASS_INDEX: return "CLASS_INDEX"; /* 4 */ + case CB_CLASS_NATIONAL: return "CLASS_NATIONAL"; /* 5 */ + case CB_CLASS_NUMERIC: return "CLASS_NUMERIC"; /* 6 */ + case CB_CLASS_OBJECT: return "CLASS_OBJECT"; /* 7 */ + case CB_CLASS_POINTER: return "CLASS_POINTER"; /* 8 */ + } + return "CB_CLASS_UNKNOWN"; +} +#endif + +/* Storage sections */ +static +const char* string_of_cb_storage (enum cb_storage x) +{ + switch (x){ + case CB_STORAGE_CONSTANT: return "CB_STORAGE_CONSTANT"; /* Constants */ + case CB_STORAGE_FILE: return "STORAGE_FILE"; /* FILE SECTION */ + case CB_STORAGE_WORKING: return "STORAGE_WORKING"; /* WORKING-STORAGE SECTION */ + case CB_STORAGE_LOCAL: return "STORAGE_LOCAL"; /* LOCAL-STORAGE SECTION */ + case CB_STORAGE_LINKAGE: return "STORAGE_LINKAGE"; /* LINKAGE SECTION */ + case CB_STORAGE_SCREEN: return "STORAGE_SCREEN"; /* SCREEN SECTION */ + case CB_STORAGE_REPORT: return "STORAGE_REPORT"; /* REPORT SECTION */ + case CB_STORAGE_COMMUNICATION: return "STORAGE_COMMUNICATION"; /* COMMUNICATION SECTION */ + } + return "CB_STORAGE_UNKNOWN"; +} + +static +void output_cb_storage (enum cb_storage x) +{ + output_constr_string ( "cb_storage", string_of_cb_storage (x)); +} + +static +const char* string_of_cob_statement (enum cob_statement x) +{ + switch (x){ + case STMT_UNKNOWN: return "STMT_UNKNOWN"; +#define COB_STATEMENT(stmt, string) case stmt: return string; +#include "../libcob/statement.def" /* located and installed next to common.h */ + case STMT_MAX_ENTRY: return "STMT_MAX_ENTRY"; + } + return "COB_STATEMENT_UNKNOWN"; +} + +static +void output_cob_statement (enum cob_statement x) +{ + output_constr_string ( "cob_statement", string_of_cob_statement (x)); +} + + +static +const char* string_of_cb_usage (enum cb_usage x) +{ + switch (x){ + case CB_USAGE_BINARY: return "CB_USAGE_BINARY"; /* 0 */ + case CB_USAGE_BIT: return "USAGE_BIT"; /* 1 */ + case CB_USAGE_COMP_5: return "USAGE_COMP_5"; /* 2 */ + case CB_USAGE_COMP_X: return "USAGE_COMP_X"; /* 3 */ + case CB_USAGE_DISPLAY: return "USAGE_DISPLAY"; /* 4 */ + case CB_USAGE_FLOAT: return "USAGE_FLOAT"; /* 5 */ + case CB_USAGE_DOUBLE: return "USAGE_DOUBLE"; /* 6 */ + case CB_USAGE_INDEX: return "USAGE_INDEX"; /* 7 */ + case CB_USAGE_NATIONAL: return "USAGE_NATIONAL"; /* 8 */ + case CB_USAGE_OBJECT: return "USAGE_OBJECT"; /* 9 */ + case CB_USAGE_PACKED: return "USAGE_PACKED"; /* 10 */ + case CB_USAGE_POINTER: return "USAGE_POINTER"; /* 11 */ + case CB_USAGE_LENGTH: return "USAGE_LENGTH"; /* 12 */ + case CB_USAGE_PROGRAM_POINTER: return "USAGE_PROGRAM_POINTER"; /* 13 */ + case CB_USAGE_UNSIGNED_CHAR: return "USAGE_UNSIGNED_CHAR"; /* 14 */ + case CB_USAGE_SIGNED_CHAR: return "USAGE_SIGNED_CHAR"; /* 15 */ + case CB_USAGE_UNSIGNED_SHORT: return "USAGE_UNSIGNED_SHORT"; /* 16 */ + case CB_USAGE_SIGNED_SHORT: return "USAGE_SIGNED_SHORT"; /* 17 */ + case CB_USAGE_UNSIGNED_INT: return "USAGE_UNSIGNED_INT"; /* 18 */ + case CB_USAGE_SIGNED_INT: return "USAGE_SIGNED_INT"; /* 19 */ + case CB_USAGE_UNSIGNED_LONG: return "USAGE_UNSIGNED_LONG"; /* 20 */ + case CB_USAGE_SIGNED_LONG: return "USAGE_SIGNED_LONG"; /* 21 */ + case CB_USAGE_COMP_6: return "USAGE_COMP_6"; /* 22 */ + case CB_USAGE_FP_DEC64: return "USAGE_FP_DEC64"; /* 23 */ + case CB_USAGE_FP_DEC128: return "USAGE_FP_DEC128"; /* 24 */ + case CB_USAGE_FP_BIN32: return "USAGE_FP_BIN32"; /* 25 */ + case CB_USAGE_FP_BIN64: return "USAGE_FP_BIN64"; /* 26 */ + case CB_USAGE_FP_BIN128: return "USAGE_FP_BIN128"; /* 27 */ + case CB_USAGE_LONG_DOUBLE: return "USAGE_LONG_DOUBLE"; /* 28 */ + case CB_USAGE_HNDL: return "USAGE_HNDL"; /* 29 */ + case CB_USAGE_HNDL_WINDOW: return "USAGE_HNDL_WINDOW"; /* 30 */ + case CB_USAGE_HNDL_SUBWINDOW: return "USAGE_HNDL_SUBWINDOW"; /* 31 */ + case CB_USAGE_HNDL_FONT: return "USAGE_HNDL_FONT"; /* 32 */ + case CB_USAGE_HNDL_THREAD: return "USAGE_HNDL_THREAD"; /* 33 */ + case CB_USAGE_HNDL_MENU: return "USAGE_HNDL_MENU"; /* 34 */ + case CB_USAGE_HNDL_VARIANT: return "USAGE_HNDL_VARIANT"; /* 35 */ + case CB_USAGE_HNDL_LM: return "USAGE_HNDL_LM"; /* 36 */ + case CB_USAGE_COMP_N: return "USAGE_COMP_N"; /* 37 */ + case CB_USAGE_ERROR: return "USAGE_ERROR"; + } + return "CB_USAGE_UNKNOWN"; +} + +static +void output_cb_usage (enum cb_usage x) +{ + output_constr_string ( "cb_usage", string_of_cb_usage (x)); +} + + +static +const char* string_of_cb_cast_type (enum cb_cast_type x) +{ + switch (x){ + case CB_CAST_INTEGER: return "CAST_INTEGER"; /* 0 */ + case CB_CAST_NEGATIVE_INTEGER: return "CAST_NEGATIVE_INTEGER"; /* 1 */ + case CB_CAST_LONG_INT: return "CAST_LONG_INT"; /* 2 */ + case CB_CAST_NEGATIVE_LONG_INT: return "CAST_NEGATIVE_LONG_INT"; /* 3 */ + case CB_CAST_ADDRESS: return "CAST_ADDRESS"; /* 4 */ + case CB_CAST_ADDR_OF_ADDR: return "CAST_ADDR_OF_ADDR"; /* 5 */ + case CB_CAST_LENGTH: return "CAST_LENGTH"; /* 6 */ + case CB_CAST_PROGRAM_POINTER: return "CAST_PROGRAM_POINTER"; /* 7 */ + } + return "CB_CAST_UNKNWON"; +} + +static +void output_cb_cast_type (enum cb_cast_type x) +{ + output_constr_string ( "cb_cast_type", string_of_cb_cast_type (x)); +} + +#if 0 + +static +const char* string_of_cb_intr_enum (enum cb_intr_enum x) +{ + switch (x){ + case CB_INTR_ABS: return "INTR_ABS"; + case CB_INTR_ACOS: return "INTR_ACOS"; + case CB_INTR_ANNUITY: return "INTR_ANNUITY"; + case CB_INTR_ASIN: return "INTR_ASIN"; + case CB_INTR_ATAN: return "INTR_ATAN"; + case CB_INTR_BASECONVERT: return "INTR_BASECONVERT"; + case CB_INTR_BIT_OF: return "INTR_BIT_OF"; + case CB_INTR_BIT_TO_CHAR: return "INTR_BIT_TO_CHAR"; + case CB_INTR_BOOLEAN_OF_INTEGER: return "INTR_BOOLEAN_OF_INTEGER"; + case CB_INTR_BYTE_LENGTH: return "INTR_BYTE_LENGTH"; + case CB_INTR_CHAR: return "INTR_CHAR"; + case CB_INTR_CHAR_NATIONAL: return "INTR_CHAR_NATIONAL"; + case CB_INTR_COMBINED_DATETIME: return "INTR_COMBINED_DATETIME"; + case CB_INTR_CONCATENATE: return "INTR_CONCATENATE"; + case CB_INTR_CONTENT_LENGTH: return "INTR_CONTENT_LENGTH"; + case CB_INTR_CONTENT_OF: return "INTR_CONTENT_OF"; + case CB_INTR_CONVERT: return "INTR_CONVERT"; + case CB_INTR_COS: return "INTR_COS"; + case CB_INTR_CURRENCY_SYMBOL: return "INTR_CURRENCY_SYMBOL"; + case CB_INTR_CURRENT_DATE: return "INTR_CURRENT_DATE"; + case CB_INTR_DATE_OF_INTEGER: return "INTR_DATE_OF_INTEGER"; + case CB_INTR_DATE_TO_YYYYMMDD: return "INTR_DATE_TO_YYYYMMDD"; + case CB_INTR_DAY_OF_INTEGER: return "INTR_DAY_OF_INTEGER"; + case CB_INTR_DAY_TO_YYYYDDD: return "INTR_DAY_TO_YYYYDDD"; + case CB_INTR_DISPLAY_OF: return "INTR_DISPLAY_OF"; + case CB_INTR_E: return "INTR_E"; + case CB_INTR_EXCEPTION_FILE: return "INTR_EXCEPTION_FILE"; + case CB_INTR_EXCEPTION_FILE_N: return "INTR_EXCEPTION_FILE_N"; + case CB_INTR_EXCEPTION_LOCATION: return "INTR_EXCEPTION_LOCATION"; + case CB_INTR_EXCEPTION_LOCATION_N: return "INTR_EXCEPTION_LOCATION_N"; + case CB_INTR_EXCEPTION_STATEMENT: return "INTR_EXCEPTION_STATEMENT"; + case CB_INTR_EXCEPTION_STATUS: return "INTR_EXCEPTION_STATUS"; + case CB_INTR_EXP: return "INTR_EXP"; + case CB_INTR_EXP10: return "INTR_EXP10"; + case CB_INTR_FACTORIAL: return "INTR_FACTORIAL"; + case CB_INTR_FIND_STRING: return "INTR_FIND_STRING"; + case CB_INTR_FORMATTED_CURRENT_DATE: return "INTR_FORMATTED_CURRENT_DATE"; + case CB_INTR_FORMATTED_DATE: return "INTR_FORMATTED_DATE"; + case CB_INTR_FORMATTED_DATETIME: return "INTR_FORMATTED_DATETIME"; + case CB_INTR_FORMATTED_TIME: return "INTR_FORMATTED_TIME"; + case CB_INTR_FRACTION_PART: return "INTR_FRACTION_PART"; + case CB_INTR_HEX_OF: return "INTR_HEX_OF"; + case CB_INTR_HEX_TO_CHAR: return "INTR_HEX_TO_CHAR"; + case CB_INTR_HIGHEST_ALGEBRAIC: return "INTR_HIGHEST_ALGEBRAIC"; + case CB_INTR_INTEGER: return "INTR_INTEGER"; + case CB_INTR_INTEGER_OF_BOOLEAN: return "INTR_INTEGER_OF_BOOLEAN"; + case CB_INTR_INTEGER_OF_DATE: return "INTR_INTEGER_OF_DATE"; + case CB_INTR_INTEGER_OF_DAY: return "INTR_INTEGER_OF_DAY"; + case CB_INTR_INTEGER_OF_FORMATTED_DATE: return "INTR_INTEGER_OF_FORMATTED_DATE"; + case CB_INTR_INTEGER_PART: return "INTR_INTEGER_PART"; + case CB_INTR_LENGTH: return "INTR_LENGTH"; + case CB_INTR_LOCALE_COMPARE: return "INTR_LOCALE_COMPARE"; + case CB_INTR_LOCALE_DATE: return "INTR_LOCALE_DATE"; + case CB_INTR_LOCALE_TIME: return "INTR_LOCALE_TIME"; + case CB_INTR_LOCALE_TIME_FROM_SECS: return "INTR_LOCALE_TIME_FROM_SECS"; + case CB_INTR_LOG: return "INTR_LOG"; + case CB_INTR_LOG10: return "INTR_LOG10"; + case CB_INTR_LOWER_CASE: return "INTR_LOWER_CASE"; + case CB_INTR_LOWEST_ALGEBRAIC: return "INTR_LOWEST_ALGEBRAIC"; + case CB_INTR_MAX: return "INTR_MAX"; + case CB_INTR_MEAN: return "INTR_MEAN"; + case CB_INTR_MEDIAN: return "INTR_MEDIAN"; + case CB_INTR_MIDRANGE: return "INTR_MIDRANGE"; + case CB_INTR_MIN: return "INTR_MIN"; + case CB_INTR_MOD: return "INTR_MOD"; + case CB_INTR_MODULE_CALLER_ID: return "INTR_MODULE_CALLER_ID"; + case CB_INTR_MODULE_DATE: return "INTR_MODULE_DATE"; + case CB_INTR_MODULE_FORMATTED_DATE: return "INTR_MODULE_FORMATTED_DATE"; + case CB_INTR_MODULE_ID: return "INTR_MODULE_ID"; + case CB_INTR_MODULE_NAME: return "INTR_MODULE_NAME"; + case CB_INTR_MODULE_PATH: return "INTR_MODULE_PATH"; + case CB_INTR_MODULE_SOURCE: return "INTR_MODULE_SOURCE"; + case CB_INTR_MODULE_TIME: return "INTR_MODULE_TIME"; + case CB_INTR_MON_DECIMAL_POINT: return "INTR_MON_DECIMAL_POINT"; + case CB_INTR_MON_THOUSANDS_SEP: return "INTR_MON_THOUSANDS_SEP"; + case CB_INTR_NATIONAL_OF: return "INTR_NATIONAL_OF"; + case CB_INTR_NUM_DECIMAL_POINT: return "INTR_NUM_DECIMAL_POINT"; + case CB_INTR_NUM_THOUSANDS_SEP: return "INTR_NUM_THOUSANDS_SEP"; + case CB_INTR_NUMVAL: return "INTR_NUMVAL"; + case CB_INTR_NUMVAL_C: return "INTR_NUMVAL_C"; + case CB_INTR_NUMVAL_F: return "INTR_NUMVAL_F"; + case CB_INTR_ORD: return "INTR_ORD"; + case CB_INTR_ORD_MAX: return "INTR_ORD_MAX"; + case CB_INTR_ORD_MIN: return "INTR_ORD_MIN"; + case CB_INTR_PI: return "INTR_PI"; + case CB_INTR_PRESENT_VALUE: return "INTR_PRESENT_VALUE"; + case CB_INTR_RANDOM: return "INTR_RANDOM"; + case CB_INTR_RANGE: return "INTR_RANGE"; + case CB_INTR_REM: return "INTR_REM"; + case CB_INTR_REVERSE: return "INTR_REVERSE"; + case CB_INTR_SECONDS_FROM_FORMATTED_TIME: return "INTR_SECONDS_FROM_FORMATTED_TIME"; + case CB_INTR_SECONDS_PAST_MIDNIGHT: return "INTR_SECONDS_PAST_MIDNIGHT"; + case CB_INTR_SIGN: return "INTR_SIGN"; + case CB_INTR_SIN: return "INTR_SIN"; + case CB_INTR_SQRT: return "INTR_SQRT"; + case CB_INTR_STANDARD_COMPARE: return "INTR_STANDARD_COMPARE"; + case CB_INTR_STANDARD_DEVIATION: return "INTR_STANDARD_DEVIATION"; + case CB_INTR_STORED_CHAR_LENGTH: return "INTR_STORED_CHAR_LENGTH"; + case CB_INTR_SUBSTITUTE: return "INTR_SUBSTITUTE"; + case CB_INTR_SUBSTITUTE_CASE: return "INTR_SUBSTITUTE_CASE"; + case CB_INTR_SUM: return "INTR_SUM"; + case CB_INTR_TAN: return "INTR_TAN"; + case CB_INTR_TEST_DATE_YYYYMMDD: return "INTR_TEST_DATE_YYYYMMDD"; + case CB_INTR_TEST_DAY_YYYYDDD: return "INTR_TEST_DAY_YYYYDDD"; + case CB_INTR_TEST_FORMATTED_DATETIME: return "INTR_TEST_FORMATTED_DATETIME"; + case CB_INTR_TEST_NUMVAL: return "INTR_TEST_NUMVAL"; + case CB_INTR_TEST_NUMVAL_C: return "INTR_TEST_NUMVAL_C"; + case CB_INTR_TEST_NUMVAL_F: return "INTR_TEST_NUMVAL_F"; + case CB_INTR_TRIM: return "INTR_TRIM"; + case CB_INTR_UPPER_CASE: return "INTR_UPPER_CASE"; + case CB_INTR_USER_FUNCTION: return "INTR_USER_FUNCTION"; + case CB_INTR_VARIANCE: return "INTR_VARIANCE"; + case CB_INTR_WHEN_COMPILED: return "INTR_WHEN_COMPILED"; + case CB_INTR_YEAR_TO_YYYY: return "INTR_YEAR_TO_YYYY"; + } + return "CB_INTR_ENUM_UNKNOWN"; +} + +static +void output_cb_intr_enum (enum cb_intr_enum x) +{ + output_constr_string ( "cb_intr_enum", string_of_cb_intr_enum (x)); +} +#endif + +static +const char* string_of_cb_perform_type (enum cb_perform_type x) +{ + switch (x){ + case CB_PERFORM_EXIT: return "PERFORM_EXIT"; + case CB_PERFORM_ONCE: return "PERFORM_ONCE"; + case CB_PERFORM_TIMES: return "PERFORM_TIMES"; + case CB_PERFORM_UNTIL: return "PERFORM_UNTIL"; + case CB_PERFORM_FOREVER: return "PERFORM_FOREVER"; + } + return "CB_PERFORM_UNKNOWN"; +} + +static +void output_cb_perform_type (enum cb_perform_type x) +{ + output_constr_string ( "cb_perform_type", string_of_cb_perform_type (x)); +} + +static +const char* string_of_cb_index_type (enum cb_index_type x) +{ + switch (x){ + case CB_NORMAL_INDEX: return "NORMAL_INDEX"; + case CB_INT_INDEX: return "INT_INDEX"; + case CB_STATIC_INT_INDEX: return "STATIC_INT_INDEX"; + case CB_STATIC_INT_VARYING: return "STATIC_INT_VARYING"; + } + return "CB_INDEX_TYPE_UNKNOWN"; +} + +static +void output_cb_index_type (enum cb_index_type x) +{ + output_constr_string ( "cb_index_type", string_of_cb_index_type (x)); +} + + +static +void output_cb_trees (cb_tree* x) +{ + int i; + BEGIN_LIST (); + for (i=0; x[i] != NULL; i++){ + LIST_ELEM(cb_tree, x[i]); + } + END_LIST (); +} + +static +void output_cb_tree_common (struct cb_tree_common *x) +{ + if (cb_output_tree_with_common){ + BEGIN_COMMON_RECORD (); + FIELD (cb_tag, tag); + FIELD (cb_category, category); + if (cb_output_tree_with_loc) { + FIELD (string, source_file); + FIELD (int,source_line); + FIELD (int,source_column); + } + END_RECORD (); + } else { + output_cb_tag (x->tag); + } +} + +static +const char* string_of_cb_ml_type (enum cb_ml_type x) +{ + switch(x){ + case CB_ML_ATTRIBUTE: return "CB_ML_ATTRIBUTE"; + case CB_ML_ELEMENT: return "CB_ML_ELEMENT"; + case CB_ML_CONTENT: return "CB_ML_CONTENT"; + case CB_ML_ANY_TYPE: return "CB_ML_ANY_TYPE"; + } + return "CB_ML_TYPE_UNKNOWN"; +} + +static +void output_cb_ml_type (enum cb_ml_type x) +{ + output_constr_string ("cb_ml_type", string_of_cb_ml_type(x)); +} + +static +void output_cb_ml_generate_tree (struct cb_ml_generate_tree *x) +{ + BEGIN_TREE_RECORD (cb_ml_generate_tree); + /* Name of the ML element to generate */ + FIELD (cb_tree, name); + /* The type of the ML element to generate */ + FIELD (cb_ml_type, type); + /* The content of the ML element to generate */ + FIELD (cb_tree, value); + /* The condition under which generation of the element is suppressed */ + FIELD (cb_tree, suppress_cond); + /* ID for this struct when output */ + FIELD (int, id); + /* Attributes for this element */ + FIELD (cb_ml_generate_tree, attrs); + /* Parent ML element */ + FIELD (cb_ml_generate_tree, parent); + /* Children ML elements */ + FIELD (cb_ml_generate_tree, children); + /* Preceding ML elements */ + FIELD_STOP (cb_ml_generate_tree, prev_sibling); + /* Following ML elements */ + FIELD_STOP (cb_ml_generate_tree *, sibling); + END_RECORD (); +} + +static +void output_cb_program (struct cb_program *x) +{ + BEGIN_TREE_RECORD (cb_program); + + FIELD_STOP (struct cb_program*, next_program_ordered); /* Nested/contained + when cb_correct_program_order is set */ + + FIELD (string, program_name); /* Internal program-name */ + FIELD (string, program_id); /* Demangled external PROGRAM-ID */ + FIELD (string, source_name); /* Source name */ + FIELD (string, orig_program_id); /* Original external PROGRAM-ID */ + + FIELD_TODO (struct cb_word **, word_table); /* Name hash table */ + FIELD_TODO (struct local_filename*, local_include); /* Local include info */ + FIELD_TODO (struct nested_list*, nested_prog_list); /* Callable contained */ + FIELD_TODO (struct nested_list*, common_prog_list); /* COMMON contained */ + + FIELD (cb_tree, entry_list); /* Entry point list */ + FIELD (cb_tree, entry_list_goto); /* Special Entry point list */ + FIELD (cb_tree, file_list); /* File list */ + FIELD (cb_tree, cd_list); /* CD list */ + FIELD (cb_tree, exec_list); /* Executable statements */ + FIELD (cb_tree, label_list); /* Label list */ + FIELD (cb_tree, reference_list); /* Reference list */ + FIELD (cb_tree, alphabet_name_list); /* ALPHABET list */ + FIELD (cb_tree, symbolic_char_list); /* SYMBOLIC list */ + FIELD (cb_tree, class_name_list); /* CLASS list */ + FIELD (cb_tree, schema_name_list); /* XML-SCHEMA list */ + FIELD (cb_tree, parameter_list); /* USING parameters */ + FIELD (cb_tree, locale_list); /* LOCALE list */ + FIELD (cb_tree, global_list); /* GLOBAL list */ + FIELD (cb_tree, report_list); /* REPORT list */ + FIELD (cb_tree, perform_thru_list); /* list of PERFORM THRU */ + FIELD (cb_tree, alter_list); /* ALTER list */ + FIELD (cb_tree, debug_list); /* DEBUG ref list */ + FIELD (cb_tree, cb_return_code); /* RETURN-CODE */ + FIELD (cb_tree, cb_sort_return); /* SORT-RETURN */ + FIELD (cb_tree, cb_call_params); /* Number of CALL params */ + FIELD (cb_tree, mnemonic_spec_list); /* MNEMONIC spec */ + FIELD (cb_tree, class_spec_list); /* CLASS spec */ + FIELD (cb_tree, interface_spec_list); /* INTERFACE spec */ + FIELD (cb_tree, function_spec_list); /* FUNCTION spec */ + FIELD (cb_tree, user_spec_list); /* User FUNCTION spec */ + FIELD (cb_tree, program_spec_list); /* PROGRAM spec */ + FIELD (cb_tree, property_spec_list); /* PROPERTY spec */ + + FIELD_TODO (struct cb_alter_id *, alter_gotos); /* ALTER ids */ + + FIELD (cb_field, working_storage); /* WORKING-STORAGE */ + FIELD (cb_field, local_storage); /* LOCAL-STORAGE */ + FIELD (cb_field, linkage_storage); /* LINKAGE */ + FIELD (cb_field, screen_storage); /* SCREEN */ + FIELD (cb_field, report_storage); /* REPORT */ + FIELD (cb_tree, local_file_list); /* Local files */ + FIELD (cb_tree, global_file_list); /* Global files */ + + FIELD_INLINE_TODO (struct handler_struct [5], global_handler); /* Global handlers */ + + FIELD (cb_tree, collating_sequence); /* COLLATING */ + FIELD (cb_tree, collating_sequence_n); /* COLLATING FOR NATIONAL*/ + FIELD (cb_tree, classification); /* CLASSIFICATION */ + FIELD (cb_tree, apply_commit); /* APPLY COMMIT file- and data-items */ + FIELD (cb_tree, cursor_pos); /* CURSOR */ + FIELD (cb_tree, crt_status); /* CRT STATUS */ + FIELD (cb_field, xml_code); /* XML-CODE */ + FIELD (cb_field, xml_event); /* XML-EVENT */ + FIELD (cb_field, xml_information); /* XML-INFORMATION */ + FIELD (cb_field, xml_namespace); /* XML-NAMESPACE */ + FIELD (cb_field, xml_nnamespace); /* XML-NNAMESPACE */ + FIELD (cb_field, xml_namespace_prefix); /* XML-NAMESPACE-PREFIX */ + FIELD (cb_field, xml_nnamespace_prefix); /* XML-NNAMESPACE-PREFIX */ + FIELD (cb_field, xml_ntext); /* XML-NTEXT */ + FIELD (cb_field, xml_text); /* XML-TEXT */ + FIELD (cb_field, json_code); /* JSON-CODE */ + FIELD (cb_field, json_status); /* JSON-STATUS */ + FIELD (cb_tree, returning); /* RETURNING */ + + FIELD (cb_label, all_procedure); /* DEBUGGING */ + FIELD_INLINE_TODO (struct cb_call_xref, call_xref); /* CALL Xref list */ + FIELD (cb_ml_generate_tree, ml_trees); /* XML GENERATE trees */ + + FIELD (string, extfh); /* CALLFH for this program */ + + FIELD (int,last_source_line); /* Line of (implicit) END PROGRAM/FUNCTION */ + + + FIELD (int, loop_counter); /* Loop counters */ + FIELD (uint, decimal_index); /* cob_decimal count of this program */ + FIELD (uint, decimal_index_max); /* program group's max cob_decimal */ + FIELD (int, nested_level); /* Nested program level */ + FIELD (uint, num_proc_params); /* PROC DIV params */ + FIELD (int, toplev_count); /* Top level source count */ + FIELD (uint, max_call_param); /* Max params */ + + FIELD (uchar, decimal_point); /* '.' or ',' */ + FIELD (uchar, currency_symbol); /* '$' or user-specified */ + FIELD (uchar, numeric_separator); /* ',' or '.' */ + + FIELD_TODO (enum cob_module_type, prog_type); /* Program type (program = 0, function = 1) */ + FIELD (cb_tree, entry_convention); /* ENTRY convention / PROCEDURE convention */ + + FIELD (uint, flag_main ); /* Gen main function */ + FIELD (uint, flag_common ); /* COMMON PROGRAM */ + FIELD (uint, flag_initial ); /* INITIAL PROGRAM */ + FIELD (uint, flag_recursive ); /* RECURSIVE PROGRAM */ + FIELD (uint, flag_screen ); /* Have SCREEN SECTION */ + FIELD (uint, flag_validated ); /* End program validate */ + FIELD (uint, flag_chained ); /* PROCEDURE CHAINING */ + FIELD (uint, flag_global_use ); /* USE GLOBAL */ + + FIELD (uint, flag_gen_error ); /* Gen error routine */ + FIELD (uint, flag_file_global); /* Global FD */ + FIELD (uint, flag_has_external); /* Has EXTERNAL */ + FIELD (uint, flag_segments ); /* Has segments */ + FIELD (uint, flag_trailing_separate); /* TRAILING SEPARATE */ + FIELD (uint, flag_console_is_crt); /* CONSOLE IS CRT */ + FIELD (uint, flag_debugging ); /* DEBUGGING MODE */ + FIELD (uint, flag_gen_debug ); /* DEBUGGING MODE */ + + FIELD (uint, flag_save_exception); /* Save exception code */ + FIELD (uint, flag_report ); /* Have REPORT SECTION */ + FIELD (uint, flag_void ); /* void return for subprogram */ + FIELD (uint, flag_decimal_comp); /* program group has decimal computations */ + FIELD (uint, flag_prototype ); /* Is a prototype */ + + FIELD (cb_program, next_program); + END_RECORD (); +} + +static +void output_cb_list (struct cb_list* x) +{ + BEGIN_LIST (); + for (; x; x = (struct cb_list*) x->chain) { + output_sequence_delim (fmt.format_delim_list); + output_indent (); + if (x->purpose || x->sizes){ + BEGIN_RECORD(cb_list); + FIELD (cb_tree, purpose); + FIELD (int, sizes); + FIELD (cb_tree, value); + END_RECORD (); + } else { + output_cb_tree (x->value); + } + } + END_LIST (); +} + +static +void output_cb_direct (struct cb_direct *x) +{ + BEGIN_TREE_RECORD (cb_direct); + FIELD (string, line); /* Line redirect */ + FIELD (int, flag_is_direct); /* Is directed */ + FIELD (int, flag_new_line); /* Need new line */ + END_RECORD (); +} + +static +void output_cb_const (struct cb_const *x) +{ + BEGIN_TREE_RECORD (cb_const); + FIELD (string, val); /* Constant value */ + END_RECORD (); +} + +static +void output_cb_debug (struct cb_debug *x) +{ + BEGIN_TREE_RECORD (cb_debug); + FIELD (cb_tree, target); /* Target for debug */ + FIELD (string, value); /* Value for debug */ + FIELD (cb_tree, fld); /* Reference */ + FIELD (size_t, size); /* Size if relevant */ + END_RECORD (); +} + +static +void output_cb_debug_call (struct cb_debug_call *x) +{ + BEGIN_TREE_RECORD (cb_debug_call); + FIELD (cb_label, target); /* Target label */ + END_RECORD (); +} + +static +void output_cb_integer (struct cb_integer *x) +{ + BEGIN_TREE_RECORD (cb_integer); + FIELD (int, val); /* Integer value */ +#ifdef USE_INT_HEX + /* Simon: using this increases the struct and we + *should* pass the flags as constants in any case... */ + FIELD (uint, hexval); /* Output hex value */ +#endif + END_RECORD (); +} + +static +void output_cb_string (struct cb_string *x) +{ + BEGIN_TREE_RECORD (cb_string); + FIELD (ustring, data); /* Data */ + FIELD (size_t, size); /* Data size */ + END_RECORD (); +} + +static +void output_cb_alphabet_name (struct cb_alphabet_name *x) +{ + BEGIN_TREE_RECORD (cb_alphabet_name); + FIELD (string, name); /* Original name */ + FIELD (string, cname); /* Name used in C */ + FIELD (cb_tree, custom_list); /* Custom ALPHABET / LOCALE reference */ + FIELD (uint, alphabet_target); /* ALPHANUMERIC or NATIONAL */ + FIELD (uint, alphabet_type); /* ALPHABET type */ + FIELD (int, low_val_char); /* LOW-VALUE */ + FIELD (int, high_val_char); /* HIGH-VALUE */ + FIELD_INLINE_TODO (int[256], values); /* Collating values */ + FIELD_INLINE_TODO (int[256], alphachr); /* Actual values */ + END_RECORD (); +} + +static +void output_cb_class_name (struct cb_class_name *x) +{ + BEGIN_TREE_RECORD (cb_class_name); + FIELD (string, name); /* Original name */ + FIELD (string, cname); /* Name used in C */ + FIELD (cb_tree, list); /* List of CLASS definitions */ + END_RECORD (); +} + +static +void output_cb_locale_name (struct cb_locale_name *x) +{ + BEGIN_TREE_RECORD (cb_locale_name); + FIELD (string, name); /* Original name */ + FIELD (string, cname); /* Name used in C */ + FIELD (cb_tree, list); /* List of locale definitions */ + END_RECORD (); +} + +static +void output_cb_system_name (struct cb_system_name *x) +{ + BEGIN_TREE_RECORD (cb_system_name); + FIELD (cb_tree, value); /* System value */ + FIELD_TODO (enum cb_system_name_category, category); /* System category */ + FIELD (int, token); /* Device attributes */ + END_RECORD (); +} + +static +void output_cb_schema_name (struct cb_schema_name *x) +{ + BEGIN_TREE_RECORD (cb_schema_name); + FIELD (string, name); /* Original name */ + FIELD (string, data); /* file name */ + END_RECORD (); +} + +static +void output_cb_literal (struct cb_literal *x) +{ + BEGIN_TREE_RECORD (cb_literal); + FIELD (ustring, data); /* Literal data */ + FIELD (cob_u32_t, size); /* Literal size */ + FIELD (int, scale); /* Numeric scale */ + FIELD (cob_u32_t, llit); /* 'L' literal */ + FIELD (int, sign); /* unsigned: 0 negative: -1 positive: 1 */ + FIELD (int, all); /* ALL */ + END_RECORD (); +} + + +static +void output_cb_decimal (struct cb_decimal *x) +{ + BEGIN_TREE_RECORD (cb_decimal); + FIELD (uint, id); /* ID for this decimal */ + END_RECORD (); +} + + +static +void output_cb_picture (struct cb_picture *x) +{ + BEGIN_TREE_RECORD (cb_picture); + FIELD (string, orig); /* Original picture string */ + FIELD_TODO (cob_pic_symbol*, str); /* Picture string */ + FIELD (int, size); /* Byte size */ + FIELD (int, lenstr); /* Length of picture string */ + FIELD (cb_category, category); /* Field category */ + FIELD (cob_u32_t, digits); /* Number of digit places */ + FIELD (int, scale); /* 1/10^scale */ +#if 0 /* currently unused */ + FIELD (cob_u32_t, real_digits); /* Real number of digits */ +#endif + FIELD (cob_u32_t, have_sign); /* Have 'S' */ + FIELD (uint, flag_is_calculated); /* is calculated */ + FIELD (uint, variable_length); /* Starts with 'L' */ + END_RECORD (); +} + +static +void output_cb_vary (struct cb_vary *x) +{ + BEGIN_TREE_RECORD (cb_vary); + FIELD (cb_tree, var); /* Variable name being VARYed */ + FIELD (cb_tree, from); /* Starting value */ + FIELD (cb_tree, by); /* Increment value */ + END_RECORD (); +} + + +static +void output_cb_table_values (struct cb_table_values *x) +{ + BEGIN_TREE_RECORD (cb_table_values); + FIELD (cb_tree, values); /* list of literals*/ + FIELD (cb_tree, from); /* NULL or list of subscripts start */ + FIELD (cb_tree, to); /* NULL or list of subscripts stop */ + FIELD (cb_tree, repeat_times); /* NULL or integer to repeat the values, + or cb_null for "repeat to end" */ + END_RECORD (); +} + +static +void output_cb_key_component (struct cb_key_component *x) +{ + BEGIN_RECORD (cb_key_component); + FIELD (cb_tree, component); + FIELD (cb_key_component, next); + END_RECORD (); +} + +static +void output_cb_alt_key (struct cb_alt_key *x) +{ + BEGIN_RECORD (cb_alt_key); + FIELD (cb_tree, key); /* Key item */ + FIELD (cb_tree, password); /* Password item */ + FIELD (cb_tree, collating_sequence_key); /* COLLATING */ + FIELD (int, duplicates); /* DUPLICATES */ + FIELD (int, offset); /* Offset from start */ + FIELD (int, tf_suppress); /* !0 for SUPPRESS */ + FIELD (int, char_suppress); /* character to test for suppress */ + FIELD (cb_key_component, component_list); /* List of fields making up key */ + FIELD (cb_alt_key, next); + END_RECORD (); +} + +#define BEGIN_FLAGS() \ + fprintf (fd, "%s", fmt.format_begin_flags) +#define FLAG(flag) \ + if (x & flag){ fprintf (fd, "%s%s%s", fmt.format_begin_flag, #flag, fmt.format_end_flag); } +#define END_FLAGS() \ + fprintf (fd, "%s", fmt.format_end_flags) + +static void output_cob_flags_t (cob_flags_t x) +{ + BEGIN_FLAGS (); + FLAG(COB_SCREEN_LINE_PLUS); + FLAG(COB_SCREEN_LINE_MINUS); + FLAG(COB_SCREEN_COLUMN_PLUS); + FLAG(COB_SCREEN_COLUMN_MINUS); + FLAG(COB_SCREEN_AUTO); + FLAG(COB_SCREEN_BELL); + FLAG(COB_SCREEN_BLANK_LINE); + FLAG(COB_SCREEN_BLANK_SCREEN); + FLAG(COB_SCREEN_BLINK); + FLAG(COB_SCREEN_ERASE_EOL); + FLAG(COB_SCREEN_ERASE_EOS); + FLAG(COB_SCREEN_FULL); + FLAG(COB_SCREEN_HIGHLIGHT); + FLAG(COB_SCREEN_LOWLIGHT); + FLAG(COB_SCREEN_REQUIRED); + FLAG(COB_SCREEN_REVERSE); + FLAG(COB_SCREEN_SECURE); + FLAG(COB_SCREEN_UNDERLINE); + FLAG(COB_SCREEN_OVERLINE); + FLAG(COB_SCREEN_PROMPT); + FLAG(COB_SCREEN_UPDATE); + FLAG(COB_SCREEN_INPUT); + FLAG(COB_SCREEN_SCROLL_DOWN); + FLAG(COB_SCREEN_INITIAL); + FLAG(COB_SCREEN_NO_ECHO); + FLAG(COB_SCREEN_LEFTLINE); + FLAG(COB_SCREEN_NO_DISP); + FLAG(COB_SCREEN_EMULATE_NL); + FLAG(COB_SCREEN_UPPER); + FLAG(COB_SCREEN_LOWER); + FLAG(COB_SCREEN_CONV); + FLAG(COB_SCREEN_GRAPHICS); + FLAG(COB_SCREEN_RIGHTLINE); + FLAG(COB_SCREEN_TAB); + FLAG(COB_SCREEN_NO_UPDATE); + FLAG(COB_SCREEN_SCROLL_UP); + FLAG(COB_SCREEN_GRID); + END_FLAGS(); +} + + +static +void output_cb_field (struct cb_field *x) +{ + BEGIN_TREE_RECORD (cb_field); + FIELD (string, name); /* Original name */ + FIELD (string, ename); /* Externalized name */ + FIELD (cb_tree, depending); /* OCCURS ... DEPENDING ON */ + FIELD (cb_tree, values); /* VALUES, in the simple case: direct value; + for level 78 _can_ be a list (expression), + for level 88 and RW be either a list or direct value, + for VALUES ARE (table-format) a list of table_values */ + FIELD (cb_tree, false_88); /* 88 FALSE clause */ + FIELD (cb_tree, index_list); /* INDEXED BY */ + FIELD (cb_tree, external_form_identifier); /* target of IDENTIFIED BY + (CGI template) */ + + FIELD (cb_field, parent); /* Upper level field (if any) */ + + FIELD (cb_field, children); /* Top of lower level fields */ + FIELD (cb_field, validation); /* First level 88 field (if any) */ + FIELD_STOP (cb_field, sister); /* Fields at the same level */ + FIELD (cb_field, redefines); /* REDEFINES or RENAMES */ + FIELD (cb_field, rename_thru); /* RENAMES THRU */ + FIELD (cb_field, index_qual); /* INDEXED BY qualifier */ + FIELD (cb_file, file); /* FD section file name */ + FIELD (cb_cd, cd); /* CD name */ + FIELD_TODO (cb_key, keys); /* SEARCH key */ + FIELD (cb_picture, pic); /* PICTURE */ + FIELD (cb_field, vsize); /* Variable size cache */ + FIELD (cb_label, debug_section); /* DEBUG section */ + FIELD (cb_report, report); /* RD section report name */ + + FIELD_INLINE_TODO (cb_xref, xref); /* xref elements */ + + FIELD (cb_tree, screen_line); /* LINE */ + FIELD (cb_tree, screen_column); /* COLUMN */ + FIELD (cb_tree, screen_from); /* TO and USING */ + FIELD (cb_tree, screen_to); /* FROM and USING */ + FIELD (cb_tree, screen_foreg); /* FOREGROUND */ + FIELD (cb_tree, screen_backg); /* BACKGROUND */ + FIELD (cb_tree, screen_prompt); /* PROMPT */ + FIELD (cb_tree, screen_control); /* CONTROL identifier (variable named attributes) */ + FIELD (cb_tree, screen_color); /* COLOR identifier (variable bit-shifted attributes) */ + FIELD (cb_tree, report_source); /* SOURCE field */ + FIELD (cb_tree, report_from); /* SOURCE field subscripted; so MOVE to report_source */ + FIELD (cb_tree, report_sum_counter);/* SUM counter */ + FIELD (cb_tree, report_sum_list);/* SUM field(s) */ + FIELD (cb_tree, report_sum_upon);/* SUM ... UPON detailname */ + FIELD (cb_tree, report_reset); /* RESET ON field */ + FIELD (cb_tree, report_control); /* CONTROL identifier */ + FIELD (cb_tree, report_when); /* PRESENT WHEN condition */ + FIELD (cb_tree, report_column_list);/* List of Column Numbers */ + /* note: the following rw-specific fields are only set for parsing, no codegen in 3.x yet */ + FIELD (cb_tree, report_vary_list);/* VARYING identifier with FROM arith + BY arith */ +#if 0 /* items from 4.x */ + FIELD (string, report_source_txt); /* SOURCE as text string */ + FIELD (string, report_field_name); /* Name used for this REPORT field */ + FIELD (cb_field, report_field_from); /* 'field' used as SOURCE */ + FIELD (int, report_field_offset); + FIELD (int, report_field_size); +#endif + FIELD (cb_tree, same_as); /* SAME AS data-name (points to field) */ + FIELD (cb_tree, external_definition); /* by SAME AS / LIKE data-name or + by type-name (points to field) */ + FIELD (cb_tree, like_modifier); /* set for LIKE, may contain a length modifier */ + + FIELD (int, id); /* Field id */ + FIELD (int, size); /* Field size */ + FIELD (int, level); /* Level number */ + FIELD (int, memory_size); /* Memory size */ + FIELD (int, offset); /* Byte offset from 01 level */ + FIELD (int, occurs_min); /* OCCURS */ + FIELD (int, occurs_max); /* OCCURS [... TO] */ + FIELD (int, indexes); /* Indices count (OCCURS) */ + + FIELD (int, count); /* Reference count */ + FIELD (int, mem_offset); /* Memory offset */ + FIELD (int, nkeys); /* Number of keys */ + FIELD (int, param_num); /* CHAINING param number */ + FIELD (cob_flags_t, screen_flag); /* Flags used in SCREEN SECTION */ + FIELD (int, report_flag); /* Flags used in REPORT SECTION */ + FIELD (int, report_line); /* LINE */ + FIELD (int, report_column); /* COLUMN (first value) */ + FIELD (int, report_num_col); /* Number of COLUMNs defined */ + FIELD (int, report_decl_id); /* Label id of USE FOR REPORTING */ +#if 0 /* items from 4.x */ + FIELD (int, report_source_id); /* Label id of MOVE SOURCE values */ +#endif + FIELD (int, step_count); /* STEP in REPORT */ + FIELD (int, next_group_line); /* NEXT GROUP [PLUS] line */ + FIELD (uint, vaddr); /* Variable address cache */ + FIELD (uint, odo_level); /* ODO level (0 = no ODO item) + could be direct ODO (check via depending) + or via subordinate) */ + FIELD (cb_index_type, index_type); /* Type of generated index */ + + FIELD (cb_storage, storage); /* Storage section */ + FIELD (cb_usage, usage); /* USAGE */ + + /* Flags */ + FIELD (uint, flag_base); /* Has memory allocation */ + FIELD (uint, flag_external); /* EXTERNAL */ + FIELD (uint, flag_local_storage); /* LOCAL storage */ + FIELD (uint, flag_is_global); /* Is GLOBAL */ + + FIELD (uint, flag_local ); /* Has local scope */ + FIELD (uint, flag_occurs); /* OCCURS */ + FIELD (uint, flag_sign_clause); /* Any SIGN clause */ + FIELD (uint, flag_sign_separate); /* SIGN IS SEPARATE */ + FIELD (uint, flag_sign_leading); /* SIGN IS LEADING */ + FIELD (uint, flag_blank_zero); /* BLANK WHEN ZERO */ + FIELD (uint, flag_justified); /* JUSTIFIED RIGHT */ + FIELD (uint, flag_binary_swap); /* Binary byteswap */ + + FIELD (uint, flag_real_binary); /* BINARY-CHAR/SHORT/LONG/DOUBLE */ + FIELD (uint, flag_is_pointer); /* Is POINTER */ + FIELD (uint, flag_item_78 ); /* Is a constant by 78 level, + 01 CONSTANT or SYMBOLIC CONSTANT */ + FIELD (uint, flag_any_length); /* Is ANY LENGTH */ + FIELD (uint, flag_item_based); /* Is BASED */ + FIELD (uint, flag_is_external_form ); /* Is EXTERNAL-FORM */ + FIELD (uint, flag_filler); /* Implicit/explicit filler */ + FIELD (uint, flag_synchronized); /* SYNCHRONIZED */ + + FIELD (uint, flag_invalid); /* Is broken */ + FIELD (uint, flag_field ); /* Has been internally cached */ + FIELD (uint, flag_chained); /* CHAINING item */ + FIELD (uint, flag_anylen_done); /* ANY LENGTH is set up */ + FIELD (uint, flag_is_verified); /* Has been verified */ + FIELD (uint, flag_is_c_long); /* Is BINARY-C-LONG */ + FIELD (uint, flag_is_pdiv_parm); /* Is PROC DIV USING */ + FIELD (uint, flag_is_pdiv_opt); /* Is PROC DIV USING OPTIONAL */ + + FIELD (uint, flag_indexed_by); /* INDEXED BY item */ + FIELD (uint, flag_local_alloced); /* LOCAL storage is allocated */ + FIELD (uint, flag_no_init); /* No initialize unless used */ + FIELD (uint, flag_vsize_done); /* Variable size cached */ + FIELD (uint, flag_vaddr_done); /* Variable address cached */ + FIELD (uint, flag_odo_relative); /* complex-odo: item address depends + on size of a different (ODO) item */ + FIELD (uint, flag_field_debug); /* DEBUGGING */ + FIELD (uint, flag_all_debug); /* DEBUGGING */ + + FIELD (uint, flag_no_field); /* SCREEN/REPORT dummy field */ + FIELD (uint, flag_any_numeric); /* Is ANY NUMERIC */ + FIELD (uint, flag_is_returning); /* Is RETURNING item */ + FIELD (uint, flag_unbounded); /* OCCURS UNBOUNDED */ + FIELD (uint, flag_comp_1); /* Is USAGE COMP-1 */ + FIELD (uint, flag_volatile); /* VOLATILE */ + FIELD (uint, flag_constant); /* Is 01 AS CONSTANT */ + FIELD (uint, flag_internal_constant); /* Is an internally generated CONSTANT */ + + FIELD (uint, flag_used_in_call ); /* Is used in CALL (only set for level 01/77), + currently not set for EXTERNAL item or when in LOCAL-STORAGE / LINKAGE */ + FIELD (uint, flag_sync_left ); /* SYNCHRONIZED LEFT */ + FIELD (uint, flag_sync_right ); /* SYNCHRONIZED RIGHT */ + FIELD (uint, flag_internal_register); /* Is an internally generated register */ + FIELD (uint, flag_is_typedef ); /* TYPEDEF */ + FIELD (uint, flag_picture_l ); /* Is USAGE PICTURE L */ + END_RECORD (); +} + + +static +void output_cb_label (struct cb_label *x) +{ + BEGIN_TREE_RECORD (cb_label); + FIELD (string, name); /* Name */ + FIELD (string, orig_name); /* Original name */ + FIELD (cb_label, section); /* Parent SECTION */ + FIELD (cb_label, debug_section); /* DEBUG SECTION */ + FIELD_TODO (struct cb_para_label*, para_label); /* SECTION Paragraphs */ + FIELD_INLINE_TODO (struct cb_xref, xref); /* xref elements */ + FIELD (cb_tree, exit_label); /* EXIT label */ + FIELD_TODO (struct cb_alter_id*, alter_gotos); /* ALTER ids */ + FIELD (int, id); /* Unique id */ + FIELD (int, section_id); /* SECTION id */ + FIELD (int, segment); /* Segment number */ + + FIELD (uint, flag_section ); /* Section */ + FIELD (uint, flag_entry ); /* Entry */ + FIELD (uint, flag_begin ); /* Begin label */ + FIELD (uint, flag_return ); /* End label */ + FIELD (uint, flag_real_label ); /* Is real label */ + FIELD (uint, flag_global ); /* GLOBAL */ + FIELD (uint, flag_declarative_exit); /* Final EXIT */ + FIELD (uint, flag_declaratives); /* DECLARATIVES */ + + FIELD (uint, flag_fatal_check); /* Fatal check */ + FIELD (uint, flag_dummy_section); /* Dummy MAIN */ + FIELD (uint, flag_dummy_paragraph); /* Dummy MAIN */ + FIELD (uint, flag_dummy_exit ); /* Dummy EXIT */ + FIELD (uint, flag_next_sentence); /* NEXT SENTENCE */ + FIELD (uint, flag_default_handler); /* Error handler */ + FIELD (uint, flag_statement ); /* Has statement */ + FIELD (uint, flag_first_is_goto); /* 1st is GO TO */ + + FIELD (uint, flag_alter ); /* ALTER code */ + FIELD (uint, flag_debugging_mode); /* DEBUGGING MODE */ + FIELD (uint, flag_is_debug_sect); /* DEBUGGING sect */ + FIELD (uint, flag_skip_label ); /* Skip label gen */ + FIELD (uint, flag_entry_for_goto); /* is ENTRY FOR GO TO */ + END_RECORD (); +} + +static +void output_cb_file (struct cb_file *x) +{ + BEGIN_TREE_RECORD (cb_file); + FIELD (string, name); /* Original name */ + FIELD (string, cname); /* Name used in C */ + /* SELECT */ + FIELD (cb_tree, assign); /* ASSIGN */ + FIELD (cb_tree, file_status); /* FILE STATUS */ + FIELD (cb_tree, sharing); /* SHARING */ + FIELD (cb_tree, key); /* Primary RECORD KEY */ + FIELD (cb_tree, password); /* Password item for file or primary key */ + FIELD (cb_key_component, component_list); /* List of fields making up primary key */ + FIELD (cb_alt_key, alt_key_list); /* ALTERNATE RECORD KEY */ + FIELD (cb_tree, collating_sequence_key); /* COLLATING */ + FIELD (cb_tree, collating_sequence); /* COLLATING */ + FIELD (cb_tree, collating_sequence_n); /* COLLATING FOR NATIONAL*/ + FIELD (cb_tree, collating_sequence_keys); /* list of postponed COLLATING OF */ + /* FD/SD */ + FIELD (cb_tree, description_entry); /* FD / SD entry rerference for warnings + errors */ + FIELD (cb_field, record); /* Record descriptions */ + FIELD (cb_tree, record_depending); /* RECORD DEPENDING */ + FIELD (cb_tree, reports); /* REPORTS */ + FIELD (cb_tree, linage); /* LINAGE */ + FIELD (cb_tree, linage_ctr); /* LINAGE COUNTER */ + FIELD (cb_tree, latfoot); /* LINAGE FOOTING */ + FIELD (cb_tree, lattop); /* LINAGE TOP */ + FIELD (cb_tree, latbot); /* LINAGE BOTTOM */ + FIELD (cb_tree, extfh); /* EXTFH module to call for I/O */ + FIELD (cb_label, handler); /* Error handler */ + FIELD_STOP (cb_program, handler_prog); /* Prog where defined */ + FIELD (cb_label, debug_section); /* DEBUG SECTION */ + FIELD (cb_alphabet_name, code_set); /* CODE-SET */ + FIELD (cb_list, code_set_items); /* CODE-SET FOR items */ + FIELD_INLINE_TODO (struct cb_xref, xref); /* xref elements */ + FIELD (int, record_min); /* RECORD CONTAINS */ + FIELD (int, record_max); /* RECORD CONTAINS */ + FIELD (int, optional); /* OPTIONAL */ + FIELD_TODO (enum cob_file_org, organization); /* ORGANIZATION */ + FIELD_TODO (enum cob_file_access_mode, access_mode); /* ACCESS MODE */ + FIELD (int, lock_mode); /* LOCK MODE */ + FIELD (int, special); /* Special file */ + FIELD (int, same_clause); /* SAME clause */ + FIELD_TODO (enum cb_assign_type, assign_type); /* How to interpret ASSIGN clause */ + FIELD (uint, flag_finalized); /* Is finalized */ + FIELD (uint, flag_external); /* Is EXTERNAL */ + FIELD (uint, flag_ext_assign); /* ASSIGN EXTERNAL */ + FIELD (uint, flag_fileid); /* ASSIGN DISK */ + FIELD (uint, flag_global); /* Is GLOBAL */ + FIELD (uint, flag_fl_debug); /* DEBUGGING */ + FIELD (uint, flag_line_adv); /* LINE ADVANCING */ + FIELD (uint, flag_delimiter); /* RECORD DELIMITER */ + FIELD (uint, flag_report); /* Used by REPORT */ + /* Implied RECORD VARYING limits need checking */ + FIELD (uint, flag_check_record_varying_limits); + /* Whether the file's ASSIGN is like "ASSIGN word", not "ASSIGN + EXTERNAL/DYNAMIC/USING/... word" */ + FIELD (uint, flag_assign_no_keyword ); + /* Exceptions enabled for file */ + FIELD_TODO (struct cb_exception*, exception_table); + END_RECORD (); +} + + +static +void output_cb_cd (struct cb_cd *x) +{ + BEGIN_TREE_RECORD (cb_cd); + FIELD (string, name); /* Name */ + FIELD (cb_field, record); /* Record descriptions */ + FIELD (cb_label, debug_section); /* DEBUG section */ + FIELD (int, flag_field_debug); /* DEBUGGING */ + END_RECORD (); +} + + + +static +void output_cb_reference (struct cb_reference *x) +{ + BEGIN_TREE_RECORD (cb_reference); + FIELD (cb_tree, chain); /* Next qualified name */ + FIELD (cb_tree, value); /* Item referred to */ + FIELD (cb_tree, subs); /* List of subscripts */ + FIELD (cb_tree, offset); /* Reference mod offset */ + FIELD (cb_tree, length); /* Reference mod length */ + FIELD (cb_tree, check); /* Runtime checks */ + FIELD (cob_statement, statement); /* statement that uses this reference */ + FIELD_TODO (struct cb_word*, word); /* Pointer to word list */ + FIELD (cb_label, section); /* Current section */ + FIELD (cb_label, paragraph); /* Current paragraph */ + FIELD (cb_label, debug_section); /* Debug section */ + FIELD (size_t, hashval); /* Hash value of name */ + FIELD (uint, flag_receiving); /* Reference target */ + FIELD (uint, flag_all); /* ALL */ + FIELD (uint, flag_in_decl); /* In DECLARATIVE */ + FIELD (uint, flag_alter_code); /* Needs ALTER code */ + FIELD (uint, flag_debug_code); /* Needs DEBUG code */ + FIELD (uint, flag_all_debug); /* Needs ALL DEBUG code */ + FIELD (uint, flag_target); /* DEBUG item is target */ + FIELD (uint, flag_optional); /* Definition optional */ + FIELD (uint, flag_ignored); /* Part of ignored code */ + FIELD (uint, flag_filler_ref); /* Ref to FILLER */ + FIELD (uint, flag_duped); /* Duplicate name */ + END_RECORD (); +} + +static +const char* string_of_cb_binary_op_flag (enum cb_binary_op_flag x) +{ + switch(x){ + case BOP_RESOLVE_AS_INTEGER: return "BOP_RESOLVE_AS_INTEGER"; + case BOP_OPERANDS_SWAPPED: return "BOP_OPERANDS_SWAPPED"; + } + return "CB_BINARY_OP_FLAG_UNKNOWN"; +} + +static +void output_cb_binary_op_flag (enum cb_binary_op_flag x) +{ + output_constr_string ("cb_binary_op_flag", string_of_cb_binary_op_flag(x)); +} + +static +const char* string_of_cb_binary_op_op (enum cb_binary_op_op x) +{ + switch(x){ + case BOP_INVALID: return "BOP_INVALID"; + case BOP_PLUS: return "BOP_PLUS"; + case BOP_MINUS: return "BOP_MINUS"; + case BOP_MULT: return "BOP_MULT"; + case BOP_DIV: return "BOP_DIV"; + case BOP_POW: return "BOP_POW"; + case BOP_EQ: return "BOP_EQ"; + case BOP_GT: return "BOP_GT"; + case BOP_LT: return "BOP_LT"; + case BOP_LE: return "BOP_LE"; + case BOP_GE: return "BOP_GE"; + case BOP_NE: return "BOP_NE"; + case BOP_NOT: return "BOP_NOT"; + case BOP_AND: return "BOP_AND"; + case BOP_OR: return "BOP_OR"; + case BOP_PARENS: return "BOP_PARENS"; + case BOP_BITWISE_NOT: return "BOP_BITWISE_NOT"; + case BOP_BITWISE_AND: return "BOP_BITWISE_AND"; + case BOP_BITWISE_OR: return "BOP_BITWISE_OR"; + case BOP_BITWISE_XOR: return "BOP_BITWISE_XOR"; + case BOP_SHIFT_L: return "BOP_SHIFT_L"; + case BOP_SHIFT_R: return "BOP_SHIFT_R"; + case BOP_SHIFT_LC: return "BOP_SHIFT_LC"; + case BOP_SHIFT_RC: return "BOP_SHIFT_RC"; + } + return "CB_BINARY_OP_OP_UNKNOWN"; +} + +static +void output_cb_binary_op_op (enum cb_binary_op_op x) +{ + output_constr_string ("cb_binary_op_op", string_of_cb_binary_op_op(x)); +} + +static +void output_cb_binary_op (struct cb_binary_op *x) +{ + BEGIN_TREE_RECORD (cb_binary_op); + FIELD (cb_tree, x); /* LHS */ + FIELD (cb_tree, y); /* RHS */ + FIELD (cb_binary_op_op, op); /* Operation */ + FIELD (cb_binary_op_flag, flag); /* Special usage */ + END_RECORD (); +} + + + +static +void output_cb_funcall (struct cb_funcall *x) +{ + BEGIN_TREE_RECORD (cb_funcall); + FIELD (string, name); /* Function name */ + FIELD (cb_trees, argv); /* Function arguments */ + FIELD (int, argc); /* Number of arguments */ + FIELD (int, varcnt); /* Variable argument count */ + FIELD (uint, screenptr); /* SCREEN usage */ + FIELD (uint, nolitcast); /* No cast for literals */ + END_RECORD (); +} + + +static +void output_cb_cast (struct cb_cast *x) +{ + BEGIN_TREE_RECORD (cb_cast); + FIELD (cb_tree, val); + FIELD (cb_cast_type, cast_type); + END_RECORD (); +} + +static +void output_cb_assign (struct cb_assign *x) +{ + BEGIN_TREE_RECORD (cb_assign); + FIELD (cb_tree, var); + FIELD (cb_tree, val); + END_RECORD (); +} + +static +void output_cb_intrinsic (struct cb_intrinsic *x) +{ + BEGIN_TREE_RECORD (cb_intrinsic); + FIELD (cb_tree, name); /* INTRINSIC name */ + FIELD (cb_tree, args); /* Arguments */ + FIELD (cb_tree, intr_field); /* Field to use */ + FIELD_TODO (struct cb_intrinsic_table*, intr_tab); /* Table pointer */ + FIELD (cb_tree, offset); /* Reference mod */ + FIELD (cb_tree, length); /* Reference mod */ + FIELD (int, isuser); /* User function */ + END_RECORD (); +} + + +static +void output_cb_initialize (struct cb_initialize *x) +{ + BEGIN_TREE_RECORD (cb_initialize); + FIELD (cb_tree, var); /* Field */ + FIELD (cb_tree, val); /* ALL (cb_true) or category (cb_int) TO VALUE */ + FIELD (cb_tree, rep); /* Replacing */ + FIELD (cob_statement, statement); /* INITIALIZE statement */ + FIELD (uchar, flag_default); /* Default */ + FIELD (uchar, flag_no_filler_init); /* No FILLER initialize */ + FIELD (uchar, padding); /* Padding */ + END_RECORD (); +} + + +static +void output_cb_search (struct cb_search *x) +{ + BEGIN_TREE_RECORD (cb_search); + FIELD (cb_tree, table); /* Reference to table name */ + FIELD (cb_tree, var); /* VARYING field */ + FIELD (cb_tree, at_end); /* AT END (pair of position and statements) */ + FIELD (cb_tree, whens); /* WHEN (conditions and statements) + [for not SEARCH ALL: list of those] */ + FIELD (int, flag_all); /* SEARCH ALL */ + END_RECORD (); +} + + +static +void output_cb_xml_parse (struct cb_xml_parse *x) +{ + BEGIN_TREE_RECORD (cb_xml_parse); + FIELD (cb_tree, data); /* XML data (field identifier) */ + FIELD (cb_tree, proc); /* PROCESSING PROCEDURE (internally as PERFORM ...) */ + FIELD (cb_tree, encoding); /* ENCODING codepage (optional) */ + FIELD (cb_tree, validating); /* VALIDATING source (optional) */ + FIELD (int, returning_national); /* RETURNING NATIONAL */ + END_RECORD (); +} + +static +void output_cb_call (struct cb_call *x) +{ + BEGIN_TREE_RECORD (cb_call); + FIELD (cb_tree, name); /* CALL name */ + FIELD (cb_tree, args); /* Arguments */ + FIELD (cb_tree, stmt1); /* ON EXCEPTION */ + FIELD (cb_tree, stmt2); /* NOT ON EXCEPTION */ + FIELD (cb_tree, call_returning); /* RETURNING */ + FIELD (cob_u32_t, is_system); /* System call */ + FIELD (int, convention); /* CALL convention */ + END_RECORD (); +} + +static +void output_cb_cancel (struct cb_cancel *x) +{ + BEGIN_TREE_RECORD (cb_cancel); + FIELD (cb_tree, target); /* CANCEL target(s) */ + END_RECORD (); +} + +static +void output_cb_alter (struct cb_alter *x) +{ + BEGIN_TREE_RECORD (cb_alter); + FIELD (cb_tree, source); /* ALTER source paragraph */ + FIELD (cb_tree, target); /* ALTER target GO TO paragraph */ + END_RECORD (); +} + +static +void output_cb_goto (struct cb_goto *x) +{ + BEGIN_TREE_RECORD (cb_goto); + FIELD (cb_tree, target); /* Procedure name(s) */ + FIELD (cb_tree, depending); /* DEPENDING */ + END_RECORD (); +} + +static +void output_cb_if (struct cb_if *x) +{ + BEGIN_TREE_RECORD (cb_if); + FIELD (cb_tree, test); /* Condition */ + FIELD (cb_tree, stmt1); /* Statement list */ + FIELD (cb_tree, stmt2); /* ELSE/WHEN statement list */ + FIELD (cob_statement, statement); /* statement IF/WHEN/PRESENT WHEN */ + END_RECORD (); +} + +static +void output_cb_perform_varying (struct cb_perform_varying *x) +{ + BEGIN_TREE_RECORD (cb_perform_varying); + FIELD (cb_tree, name); /* VARYING item */ + FIELD (cb_tree, from); /* FROM */ + FIELD (cb_tree, step); /* Increment */ + FIELD (cb_tree, until); /* UNTIL */ + END_RECORD (); +} + +static +void output_cb_perform (struct cb_perform *x) +{ + BEGIN_TREE_RECORD (cb_perform); + FIELD (cb_tree, test); /* Condition */ + FIELD (cb_tree, body); /* Statements */ + FIELD (cb_tree, data); /* TIMES or procedure */ + FIELD (cb_tree, varying); /* VARYING */ + FIELD (cb_tree, exit_label); /* Implicit exit label */ + FIELD (cb_tree, cycle_label); /* EXIT PERFORM CYCLE */ + FIELD (cb_perform_type, perform_type); /* Perform type */ + END_RECORD (); +} + +static +void output_cb_statement (struct cb_statement *x) +{ + BEGIN_TREE_RECORD (cb_statement); + + FIELD (cob_statement, statement); /* Statement */ + FIELD (cb_tree, body); /* Statement body */ + FIELD (cb_tree, file); /* File reference */ + FIELD (cb_tree, ex_handler); /* Exception handler */ + FIELD (cb_tree, not_ex_handler); /* Exception handler */ + FIELD (cb_tree, handler3); /* INTO clause */ + FIELD (cb_tree, null_check); /* NULL check */ + FIELD (cb_tree, debug_check); /* Field DEBUG */ + FIELD (cb_tree, debug_nodups); /* Field DEBUG dups */ + FIELD_TODO (struct cb_attr_struct*, attr_ptr); /* Attributes */ + FIELD_TODO (enum cb_handler_type,handler_type); /* Handler type */ + FIELD (uint, flag_no_based); /* Check BASED */ + FIELD (uint, flag_in_debug); /* In DEBUGGING */ + FIELD (uint, flag_callback); /* DEBUG Callback */ + FIELD (uint, flag_implicit); /* Is an implicit statement */ + END_RECORD (); +} + + +static +void output_cb_continue (struct cb_continue *x) +{ + BEGIN_TREE_RECORD (cb_continue); + END_RECORD (); +} + + +static +void output_cb_set_attr (struct cb_set_attr *x) +{ + BEGIN_TREE_RECORD (cb_set_attr); + FIELD (cb_field, fld); + FIELD (cob_flags_t, val_on); + FIELD (cob_flags_t, val_off); + END_RECORD (); +} + +static +void output_cb_report (struct cb_report *x) +{ + BEGIN_TREE_RECORD (cb_report); + FIELD (string, name); /* Original name */ + FIELD (string, cname); /* Name used in C */ + FIELD (cb_file, file); /* File */ + FIELD (cb_tree, line_counter); /* LINE-COUNTER */ + FIELD (cb_tree, page_counter); /* PAGE-COUNTER */ + FIELD (cb_tree, code_clause); /* CODE */ + FIELD (cb_tree, controls); /* CONTROLS */ + FIELD (cb_tree, t_lines); /* PAGE LIMIT LINES */ + FIELD (cb_tree, t_columns); /* PAGE LIMIT COLUMNS */ + FIELD (cb_tree, t_heading); /* HEADING */ + FIELD (cb_tree, t_first_detail); /* FIRST DE */ + FIELD (cb_tree, t_last_control); /* LAST CH */ + FIELD (cb_tree, t_last_detail); /* LAST DE */ + FIELD (cb_tree, t_footing); /* FOOTING */ + FIELD (int, lines); /* PAGE LIMIT LINES */ + FIELD (int, columns); /* PAGE LIMIT COLUMNS */ + FIELD (int, heading); /* HEADING */ + FIELD (int, first_detail); /* FIRST DE */ + FIELD (int, last_control); /* LAST CH */ + FIELD (int, last_detail); /* LAST DE */ + FIELD (int, footing); /* FOOTING */ + FIELD (cb_field, records); /* First record definition of report */ + FIELD (int, num_lines); /* Number of Lines defined */ + if (x->num_lines>0){ + int i; + FIELD_SET(num_lines); + BEGIN_LIST(); + for (i=0; inum_lines; i++){ + LIST_ELEM (cb_field, x->line_ids[i]); + } + END_LIST(); + } + FIELD (int, num_sums); /* Number of SUM counters defined */ + if (x->num_sums>0){ + int i; + FIELD_SET(sums); + BEGIN_LIST(); + for (i=0; inum_sums; i++){ + LIST_ELEM (cb_field, x->sums[i]); + } + END_LIST(); + } + FIELD (int, rcsz); /* Longest record */ + FIELD (int, id); /* unique id for this report */ + FIELD (uint, control_final);/* CONTROL FINAL declared */ + FIELD (uint, global); /* IS GLOBAL declared */ + FIELD (uint, has_declarative);/* Has Declaratives Code to be executed */ + FIELD (uint, has_detail); /* Has DETAIL line */ + FIELD (uint, has_source_move);/* Has Code to MOVE SOURCE values */ + FIELD (uint, was_checked); + END_RECORD (); +} + +static +void output_cb_prototype (struct cb_prototype *x) +{ + BEGIN_TREE_RECORD (cb_prototype); + /* Name of prototype in the REPOSITORY */ + FIELD (string, name); + /* External name of the prototype/definition */ + FIELD (string, ext_name); + FIELD_TODO (enum cob_module_type, type); + END_RECORD (); +} + +static +const char* string_of_cb_ml_suppress_target (enum cb_ml_suppress_target x) +{ + switch (x){ + case CB_ML_SUPPRESS_IDENTIFIER: return "CB_ML_SUPPRESS_IDENTIFIER"; + case CB_ML_SUPPRESS_ALL: return "CB_ML_SUPPRESS_ALL"; + case CB_ML_SUPPRESS_TYPE: return "CB_ML_SUPPRESS_TYPE"; + } + return "CB_ML_SUPPRESS_TARGET_UNKNOWN"; +} + +static +void output_cb_ml_suppress_target (enum cb_ml_suppress_target x) +{ + output_constr_string ( "cb_ml_suppress_target", string_of_cb_ml_suppress_target (x)); +} + + +static +const char* string_of_cb_ml_suppress_category (enum cb_ml_suppress_category x) +{ + switch (x){ + case CB_ML_SUPPRESS_CAT_NUMERIC: return "CB_ML_SUPPRESS_CAT_NUMERIC"; + case CB_ML_SUPPRESS_CAT_NONNUMERIC: return "CB_ML_SUPPRESS_CAT_NONNUMERIC"; + case CB_ML_SUPPRESS_CAT_ANY: return "CB_ML_SUPPRESS_CAT_ANY"; + } + return "CB_ML_SUPPRESS_CATEGORY_UNKNOWN"; +} + +static +void output_cb_ml_suppress_category (enum cb_ml_suppress_category x) +{ + output_constr_string ( "cb_ml_suppress_category", string_of_cb_ml_suppress_category (x)); +} + + +static +void output_cb_ml_suppress_clause (struct cb_ml_suppress_clause *x) +{ + BEGIN_TREE_RECORD (cb_ml_suppress_clause); + /* What thing(s) the SUPPRESS clause applies to */ + FIELD (cb_ml_suppress_target, target); + /* If the target is IDENTIFIER, then the item targetted */ + FIELD (cb_tree, identifier); + /* What values the thing(s) should have to be SUPPRESSed */ + FIELD (cb_tree, when_list); + /* If the target is TYPE, then the type of ML elements to apply to */ + FIELD (cb_ml_type, ml_type); + /* If the target is TYPE, then the categories of items (of ML type + ml_type) to apply to */ + FIELD (cb_ml_suppress_category, category); + END_RECORD (); +} + +static +void output_cb_ml_suppress_checks (struct cb_ml_suppress_checks *x) +{ + BEGIN_TREE_RECORD (cb_ml_suppress_checks); + FIELD (cb_ml_generate_tree, tree); + END_RECORD (); +} + +static +void output_cb_tree (cb_tree x) +{ + if (!x) { fprintf (fd, "NULL"); return; } + switch (x -> tag){ + case CB_TAG_CONST: output_cb_const ( CB_CONST(x) ); break; /* Constant value */ + case CB_TAG_INTEGER: output_cb_integer ( CB_INTEGER(x) ); break; /* Integer constant */ + case CB_TAG_STRING: output_cb_string ( CB_STRING(x) ); break; /* String constant */ + case CB_TAG_ALPHABET_NAME: output_cb_alphabet_name ( CB_ALPHABET_NAME(x) ); break; /* Alphabet-name */ + case CB_TAG_CLASS_NAME: output_cb_class_name ( CB_CLASS_NAME(x) ); break; /* Class-name */ + case CB_TAG_LOCALE_NAME: output_cb_locale_name ( CB_LOCALE_NAME(x) ); break; /* Locale-name */ + case CB_TAG_SYSTEM_NAME: output_cb_system_name ( CB_SYSTEM_NAME(x) ); break; /* System-name */ + case CB_TAG_SCHEMA_NAME: output_cb_schema_name ( CB_SCHEMA_NAME(x) ); break; /* xml-schema-name */ + case CB_TAG_LITERAL: output_cb_literal ( CB_LITERAL(x) ); break; /* Numeric/alphanumeric literal */ + case CB_TAG_DECIMAL: output_cb_decimal ( CB_DECIMAL(x) ); break; /* Decimal number */ + case CB_TAG_FIELD: output_cb_field ( CB_FIELD(x) ); break; /* User-defined variable */ + case CB_TAG_FILE: output_cb_file ( CB_FILE(x) ); break; /* File description */ + case CB_TAG_REPORT: output_cb_report ( CB_REPORT(x) ); break; /* Report description */ + case CB_TAG_CD: output_cb_cd ( CB_CD(x) ); break; /* Communication description */ + /* Expressions */ + case CB_TAG_REFERENCE: output_cb_reference ( CB_REFERENCE(x) ); break; + case CB_TAG_BINARY_OP: output_cb_binary_op ( CB_BINARY_OP(x) ); break; /* Binary operation */ + case CB_TAG_FUNCALL: output_cb_funcall ( CB_FUNCALL(x) ); break; /* Run-time function call */ + case CB_TAG_CAST: output_cb_cast ( CB_CAST(x) ); break; /* Type cast */ + case CB_TAG_INTRINSIC: output_cb_intrinsic ( CB_INTRINSIC(x) ); break; /* Intrinsic function */ + /* Statements */ + case CB_TAG_LABEL: output_cb_label ( CB_LABEL(x) ); break; /* Label statement */ + case CB_TAG_ASSIGN: output_cb_assign ( CB_ASSIGN(x) ); break; /* Assignment statement */ + case CB_TAG_INITIALIZE: output_cb_initialize ( CB_INITIALIZE(x) ); break; /* INITIALIZE statement */ + case CB_TAG_SEARCH: output_cb_search ( CB_SEARCH(x) ); break; /* SEARCH statement */ + case CB_TAG_CALL: output_cb_call ( CB_CALL(x) ); break; /* CALL statement */ + case CB_TAG_GOTO: output_cb_goto ( CB_GOTO(x) ); break; /* GO TO statement */ + case CB_TAG_IF: output_cb_if ( CB_IF(x) ); break; /* IF statement / WHEN clause / PRESENT WHEN clause */ + case CB_TAG_PERFORM: output_cb_perform ( CB_PERFORM(x) ); break; /* PERFORM statement */ + case CB_TAG_STATEMENT: output_cb_statement ( CB_STATEMENT(x) ); break; /* General statement */ + case CB_TAG_CONTINUE: output_cb_continue ( CB_CONTINUE(x) ); break; /* CONTINUE statement */ + case CB_TAG_CANCEL: output_cb_cancel ( CB_CANCEL(x) ); break; /* CANCEL statement */ + case CB_TAG_ALTER: output_cb_alter ( CB_ALTER(x) ); break; /* ALTER statement */ + case CB_TAG_SET_ATTR: output_cb_set_attr ( CB_SET_ATTR(x) ); break; /* SET ATTRIBUTE statement */ + case CB_TAG_XML_PARSE: output_cb_xml_parse ( CB_XML_PARSE(x) ); break; /* XML PARSE statement */ + /* Miscellaneous */ + case CB_TAG_PERFORM_VARYING: output_cb_perform_varying ( CB_PERFORM_VARYING(x) ); break; /* PERFORM VARYING parameter */ + case CB_TAG_PICTURE: output_cb_picture ( CB_PICTURE(x) ); break; /* PICTURE clause */ + case CB_TAG_LIST: output_cb_list ( CB_LIST (x) ); break; /* List */ + case CB_TAG_DIRECT: output_cb_direct ( CB_DIRECT(x) ); break; /* Code output or comment */ + case CB_TAG_DEBUG: output_cb_debug ( CB_DEBUG(x) ); break; /* Debug item set */ + case CB_TAG_DEBUG_CALL: output_cb_debug_call ( CB_DEBUG_CALL(x) ); break; /* Debug callback */ + case CB_TAG_PROGRAM: output_cb_program ( CB_PROGRAM(x) ); break; /* Program */ + case CB_TAG_PROTOTYPE: output_cb_prototype ( CB_PROTOTYPE(x) ); break; /* Prototype */ + case CB_TAG_DECIMAL_LITERAL: output_cb_decimal ( CB_DECIMAL_LITERAL(x) ); break; /* Decimal Literal */ + /* TODO: check this one */ + case CB_TAG_REPORT_LINE: output_cb_tree_common ( x ); break; /* Report line description */ + case CB_TAG_ML_SUPPRESS: output_cb_ml_suppress_clause ( CB_ML_SUPPRESS(x) ); break; /* JSON/XML GENERATE SUPPRESS clause */ + case CB_TAG_ML_TREE: output_cb_ml_generate_tree ( CB_ML_TREE(x) ); break; /* JSON/XML GENERATE output tree */ + case CB_TAG_ML_SUPPRESS_CHECKS: output_cb_ml_suppress_checks ( CB_ML_SUPPRESS_CHECKS(x) ); break; /* JSON/XML GENERATE SUPPRESS checks */ + case CB_TAG_VARY: output_cb_vary ( CB_VARY(x) ); break; /* Report line description */ + case CB_TAG_TAB_VALS: output_cb_table_values (CB_TAB_VALS(x)); break; /* VALUE entries in table-format */ + + } +} + +void cb_output_tree_to_file (struct cb_program *prog, const char *filename, const char* flags) +{ + char *env; + + set_format_by_file_ext (filename); + + env = getenv ("COB_OUTPUT_TREE_FLAGS"); + if (env) set_flags (env); + if (flags) set_flags (flags); + + indent_init (); + fd = fopen (filename, "w"); + if (!fd){ + cb_perror (0, "cobc: %s: %s", filename, cb_get_strerror ()); + } + + fprintf (fd, "%s", fmt.format_header); + output_cb_program (prog); + fprintf (fd, "%s", fmt.format_trailer); + + fclose (fd); + fprintf (stderr, "File \"%s\" generated\n", filename); +} diff --git a/cobc/tree.h b/cobc/tree.h index 3649e42ae..0a8663b37 100644 --- a/cobc/tree.h +++ b/cobc/tree.h @@ -2569,6 +2569,10 @@ extern cb_tree cb_build_xml_parse (cb_tree, cb_tree, extern void cb_emit_json_generate (cb_tree, cb_tree, cb_tree, cb_tree, cb_tree); +extern void cb_output_tree_to_file (struct cb_program *prog, + const char *filename, + const char *flags); + #ifdef COB_TREE_DEBUG extern cb_tree cobc_tree_cast_check (const cb_tree, const char *, const int, const enum cb_tag);