/****************************************************************************** * * INFO/BASIC de-compiler main include file * * Module %M% Version %I% Date %H% * * (c) Copyright 1998 Ardent Software Inc. - All Rights Reserved * This is unpublished proprietary source code of Ardent Software Inc. * The copyright notice above does not evidence any actual or intended * publication of such source code. * ******************************************************************************* * * Maintenence log - insert most recent change descriptions at top * * Date.... GTAR# WHO Description......................................... * 10/14/98 23801 SAP Change copyrights. * 07/14/94 14444 NDP Removed __MODULE__ and __SCCSID__ definitions. * 06/23/94 14421 PGW Initial implementation * ******************************************************************************/ /* * This is the header file for the INFO/BASIC de-compiler, defining the * major data structures, global variables, and procedure declarations. */ /*********************************************************************** * * Macros and constants * ***********************************************************************/ /* * The following 'proto' macro allows the defining of function prototypes * such that the code still compiles for non-prototype supporting compilers. * Example usage of the macro for printf is: * void printf proto((char *, ...)); * Note: The usage of the double parenthesis is necessary! */ #ifdef __STDC__ #define proto(args) args /* for prototypers */ #else #define proto(args) () /* for non-prototypers */ #endif #define TEXT_MARK '\373' #define SUBVALUE_MARK '\374' #define VALUE_MARK '\375' #define FIELD_MARK '\376' #define ITEM_MARK '\377' /* Real_Char is a macro to convert a PRIMOS char (found in object files) to a printable ASCII char. */ #define Real_Char(x) (((char)(x)) ^ 0x80) /* Limits */ #define MAXSTRING 258 /* Maximum size of a string literal */ #define MAXNAME 1024 /* Maximum length of a file name */ /* Is there an ANSI form? */ #define MAX_OBJECT_SIZE 65536 /* Maximum size of object code */ #define MAXSOURCE 2048 /* Maximum source line length */ #define MAX_OPCODE_ARGS 8 /* Maximum stack args to opcode */ #define MAX_DATE_STRING 64 /* Maximum length of date string */ #define MAX_COMMONS 256 /* Maximum number of COMMON areas */ #define MAX_INTEGER_TEXT 20 /* Max length of integer constant */ #define MAX_CALL_ARGS 256 /* Maximum args to CALL */ #define OP_STORE_OPCODE 5 /* Value of STORE opcode */ #define OP_RETURN_OPCODE 10 /* Value of RETURN opcode */ #define OP_BRLFALS_OPCODE 39 /* Value of BRLFALS opcode */ #define OP_BRLTRUE_OPCODE 48 /* Value of BRLTRUE opcode */ #define OP_LDVAR_OPCODE 94 /* Value of LDVAR opcode */ #define OP_EXTENDED_OPCODE 95 /* prefix byte for extended opcodes */ #define OP_LOCATE_OPCODE 7 /* Value of LOCATE opcode (after 95) */ #define OP_CONSTANT_BASE 99 /* value for "Load constant zero" */ #define OP_LDVAR_LIMIT 128 /* Start of "load variable" opcodes */ #define OP_45_LIMIT 11 /* Maximum OP45 extension */ #define OP_95_LIMIT 178 /* Maximum OP95 extension */ #define QUOTE_CHAR '"' /* Used for string constants */ /* This is the value for the sign bit in a 3-byte signed number */ #define ADDRESS_SIGN_VALUE 0x800000 /* This is the value for the sign bit in a 4-byte signed number */ #define LONG_SIGN_VALUE 0x80000000 /* Fields in the variable header data */ #define VAR_HDR_PATH 0 #define VAR_HDR_PI_REV 1 #define VAR_HDR_IB_REV 2 #define VAR_HDR_USER 3 #define VAR_HDR_DATETIME 4 #define VAR_HDR_COPYRIGHT 5 #define VAR_HDR_SERIAL 6 #define VAR_HDR_COMMENTS 7 /* Number of fields to be extracted */ #define VAR_HDR_FIELDS 8 /* Bits in the options word of the INFO/BASIC header */ /* (extracted from ib_options.h in the PI/open source) */ #define BRIEF_OPTION 0x00000001 #define CASE_OPTION 0x00000002 #define DEBUGGING_OPTION 0x00000004 #define DETAIL_OPTION 0x00000008 #define INTERNAL_DEBUGGING_OPTION 0x00000010 #define ITYPE_OPTION 0x00000020 #define IXREF_OPTION 0x00000040 #define LISTING_OPTION 0x00000080 #define OBJECT_OPTION 0x00000100 #define OPTIMIZE_OPTION 0x00000200 #define PRIME_OPTION 0x00000400 /* Option bit with value 0x00000800 not used */ #define IB_REALITY_OPTION 0x00001000 #define IB_SMA_OPTION 0x00002000 #define VERSION_OPTION 0x00004000 #define XREF_OPTION 0x00008000 #define NO_WARNINGS_OPTION 0x00010000 #define MONITOR_OPTION 0x00020000 #define CMAN_OPTION 0x00040000 #define SMA_COMMON_OPTION 0x00080000 #define IB_RAW_INPUT_OPTION 0x00100000 #define IB_RAW_OUTPUT_OPTION 0x00200000 #define IB_SMA_SEQ_OPTION 0x00400000 #define IB_SMA_FOR_NEXT_OPTION 0x00800000 #define IB_SMA_READ_ELSE_OPTION 0x01000000 #define IB_SMA_HEADING_OPTION 0x02000000 /* Options bits for INPUT opcodes */ /* The first three are used by both INPUTOP and INPUTAT */ #define INPUT_UNDERSCORE_OPTION 1 #define INPUT_COLON_OPTION 2 #define INPUT_PRIME_OPTION 4 /* This one is only used by INPUTOP */ #define INPUT_KEYIN_OPTION 8 /* These are only used by INPUTAT */ #define INPUT_DISPLAY_OPTION 8 #define INPUT_FORMAT_OPTION 16 #define INPUT_ELSE_OPTION 32 #define INPUT_THEN_OPTION 64 /*********************************************************************** * Status codes ***********************************************************************/ #define DC_INVALID_OPCODE 1001 /* Invalid opcode */ #define DC_UNSUPPORTED_OPCODE 1002 /* Unsupported opcode */ #define DC_INVALID_INDXARY 1003 /* INDXARY without array name */ #define DC_DIMCOM_ERROR 1004 /* DIMCOM: missing variable */ #define DC_BRLNERR 1005 /* Unexpected BRLNERR */ #define DC_MISSING_TARGET 1006 /* No target for branch */ #define DC_MEMORY 1007 /* Out of memory */ #define DC_DIMLCL_ERROR 1008 /* DIMLCL: missing variable */ #define DC_READL_ERROR 1009 /* READL: missing lock type */ #define DC_RSTACK_UNDERFLOW 1010 /* rstack exhausted */ #define DC_INVALID_COMMON 1011 /* Invalid COMMON reference */ #define DC_INVALID_RSTACK 1012 /* Invalid rstack entry */ #define DC_INVALID_SELIND 1013 /* SELECTINDEX: invalid type */ #define DC_READNX2_ERROR 1014 /* READNX2: invalid arg count */ #define DC_INVALID_INPUTOP 1015 /* INPUTOP: invalid options */ #define DC_INVALID_INPUTAT 1016 /* INPUTAT: invalid options */ #define DC_INVALID_DEVSYS 1017 /* Invalid DEVSYS reference */ #define DC_INVALID_ONERR 1018 /* ONERR/store with arg not 0 */ #define DC_ERROR_IFEXPR 1019 /* IF-expr with no text */ #define DC_DUPLICATE 1020 /* Unexpected DUP */ #define DC_MISSING_STORE 1021 /* Expected STORE missing */ #define DC_DEVSYS_FORBIDDEN 1022 /* COMMON /DEVSYS/ not allowed */ #define DC_STORE_STACK 1023 /* STORE left entry on stack */ #define DC_STMT_STACK 1024 /* Statement left entry on stack */ #define DC_MISSING_LDVAR 1025 /* Expected LDVAR missing */ #define DC_INVALID_SMA 1026 /* Invalid use of SMA opcode */ #define DC_DIMICOM_ERROR 1027 /* DIMICOM: argument error */ #define DC_MISSING_SUBR 1028 /* CALL: no subroutine reference */ #define DC_RESOLVE_ERROR 1029 /* pop_stack_and_resolve error */ /* Command line errors */ #define DC_OPT_NOFILE 2001 /* No input file given */ #define DC_OPT_UNKNOWN 2002 /* Unknown option */ #define DC_OPT_INVALID 2003 /* Invalid option */ #define DC_OPT_SYNTAX 2004 /* Too many non-hyphen words */ #define DC_OPT_ARGKEY 2005 /* Invalid argument key */ /*********************************************************************** * * Typedefs and structures * ***********************************************************************/ /* The p_file structure is used to read through the object file, keeping track of the current byte value and byte position. Procedures to manipulate it are found in pfile.c */ struct p_file { FILE *pf; int byte; long count; }; extern struct p_file p1; /* program object (IRUN) file */ /* The ib_header_data structure holds data obtained from the object file header. */ struct ib_header_data { int version; int program_type; long object_size; long obj_header_size; unsigned long options_word; char * var_hdr_data[VAR_HDR_FIELDS]; unsigned int nargs; unsigned int nvars; unsigned int symof; unsigned int linof; }; extern struct ib_header_data header_data; /* Information about each COMMON area defined in a program is held * in a COMMON_TYPE structure. This is of variable size, since * it holds information about each variable within the common area. */ typedef struct pi_common_elt_str PI_COMMON_ELEMENT; struct pi_common_elt_str { int dims; /* Number of dimensions */ char * rows; /* Number of rows; NULL = scalar */ char * cols; /* Number of columns; NULL = 1-dim */ }; typedef struct sma_common_elt_str SMA_COMMON_ELEMENT; struct sma_common_elt_str { unsigned int var_no; /* Local variable referencing this array */ unsigned int rows; /* Number of rows */ unsigned int cols; /* Number of columns; 0 = 1-dim */ }; typedef struct common_element_str COMMON_ELEMENT; struct common_element_str { char * name; /* Variable name */ int type; /* 1 = SMA-style array */ union { PI_COMMON_ELEMENT pi; SMA_COMMON_ELEMENT sma; } data; }; typedef struct common_str COMMON_TYPE, *COMMON_PTR; struct common_str { unsigned int var_no; /* Variable number in this program */ char name[10]; /* COMMON area name */ unsigned int size; /* Size (number of elements) */ COMMON_ELEMENT elt[1]; /* Data for each element */ }; extern COMMON_PTR common_list[]; /* In order to de-compile expressions, the program keeps a symbolic * stack which parallels the run-time stack movements that occur when * a program is executed. Each element of the stack is not a value, * but holds information about the sub-expression that it corresponds to. * In most cases, this is the text of the sub-expressions, plus a * priority used to determine whether parentheses are needed. * These are operator precedence values: higher number means a lower * priority operator. */ /* Rstack entry types */ #define RS_NONE 0 /* Not complete yet */ #define RS_TEXT 1 /* Sub-expression text */ #define RS_LOCAL 2 /* Local variable reference */ #define RS_COMMON 3 /* COMMON variable reference */ #define RS_INTEGER 4 /* Integer constant */ #define RS_SUBROUTINE 5 /* Subroutine link (DSUBR) */ /* Text entry */ typedef struct rstack_text_str RSTACK_TEXT_TYPE; struct rstack_text_str { int priority; /* operator precedence of this entry */ char * text; /* expression text */ }; /* Local variable entry */ typedef struct rstack_local_str RSTACK_LOCAL_TYPE; struct rstack_local_str { unsigned int var_no; /* variable number */ }; /* COMMON variable entry */ typedef struct rstack_common_str RSTACK_COMMON_TYPE; struct rstack_common_str { unsigned int common_no; /* COMMON number */ unsigned int offset; /* Offset within COMMON */ }; /* Integer constant entry */ typedef struct rstack_integer_str RSTACK_INTEGER_TYPE; struct rstack_integer_str { long value; /* constant value */ }; /* Subroutine entry */ typedef struct rstack_subroutine_str RSTACK_SUBROUTINE_TYPE; struct rstack_subroutine_str { char * text; /* subroutine reference */ }; typedef struct rstack_str RSTACK_TYPE, *RSTACK_PTR; struct rstack_str { RSTACK_PTR previous; /* pointer to stack element below this */ int type; /* Type of entry */ int duplicate; /* Has been duplicated by DUP opcode */ union { RSTACK_TEXT_TYPE expr; RSTACK_LOCAL_TYPE local; RSTACK_COMMON_TYPE common; RSTACK_INTEGER_TYPE integer; RSTACK_SUBROUTINE_TYPE subr; } data; }; extern RSTACK_PTR rstack_top; /* top of stack, i.e. newest entry */ /* As de-compilation proceeds, lines of generated output are held in * a linked list of output_line structures. For each line, we also * hold the offset in the object file where the code for that line * starts. This allows us to identify and mark the target line for * each branch opcode. */ typedef struct output_line_str OUTPUT_LINE_TYPE, *OUTPUT_LINE_PTR; struct output_line_str { OUTPUT_LINE_PTR next; /* Link to next line */ OUTPUT_LINE_PTR previous; /* Link to previous line */ union { char * text; /* Text of line */ COMMON_PTR common; /* COMMON data area */ } line; long offset; /* Start pos. in object code */ int level; /* Logical indentation level */ int branch; /* Used as a branch target */ int type; /* Text or other */ }; /* Most lines are held as text, but some are incomplete, e.g. * those for COMMON areas. The 'type' field identifies which, * taking on the values below: */ #define OL_EMPTY 0 /* Line not created yet */ #define OL_TEXT 1 /* Normal text line */ #define OL_COMMON 2 /* COMMON declaration */ extern OUTPUT_LINE_PTR output_first; /* First line of output */ extern OUTPUT_LINE_PTR output_last; /* Last line of output */ /* The target offsets for forward branches are held in a sorted linked * linked list of PENDING_BRANCH structures. */ typedef struct pending_branch_str PENDING_BRANCH_TYPE, *PENDING_BRANCH_PTR; struct pending_branch_str { PENDING_BRANCH_PTR next; /* Link to next in list */ long offset; /* Offset that occurs as branch target */ }; extern PENDING_BRANCH_PTR pending_branch_first; /* Control structures are handled by a stack of level_str structures. * Each one contains state indicators relating to ON ERROR clauses, * LOCKED clauses, and other clauses, as well as the offset of the * end of the current part of the control structure. * * State values are as follows: */ #define NOT_ACTIVE 0 /* Applies all indicators */ /* * Values for "ON ERROR" status */ #define ONERR_START 1 /* 'ONERR' opcode seen */ #define ONERR_IO_SEEN 2 /* I/O opcode seen, BRLNERR expected */ #define ONERR_GOING 3 /* In "ON ERROR" clause */ /* * Values for "LOCKED" status */ #define LOCKED_START 1 /* 'LDIOOPT' opcode seen */ #define LOCKED_IO_SEEN 2 /* I/O opcode seen, LOCKED expected */ #define LOCKED_BRL1 3 /* First BRLFALS seen */ #define LOCKED_GOING 4 /* In "LOCKED" clause */ #define LOCKED_RECLOCK 5 /* Seen RECORDLOCK statement */ /* * Values for other clause status */ #define CTL_START 1 /* Expecting "THEN" */ #define CTL_THEN_GOING 2 /* In "THEN" clause */ #define CTL_ELSE_GOING 3 /* In "ELSE" clause */ #define CTL_FOR_START 4 /* Seen "FORINIT", expecting "FORTST" */ #define CTL_FOR_GOING 5 /* In "FOR/NEXT" loop */ #define CTL_FILELOCK 6 /* Expecting fake "THEN" */ #define CTL_ELSE_EXPR 7 /* In "ELSE" part of conditional expression */ typedef struct level_str LEVEL_TYPE, *LEVEL_PTR; struct level_str { LEVEL_PTR previous; /* Link to level below this one */ int depth; /* Nesting depth */ int onerr; /* ON ERROR status */ int locked; /* LOCKED status */ int ctl; /* other control status */ int needelse; /* This THEN needs an ELSE */ unsigned int for_top; /* FOR-loop top-of-loop address */ unsigned int end_offset; /* End of current structure */ }; extern LEVEL_PTR level_base; /* base of level stack, i.e. 1st entry */ extern LEVEL_PTR level_top; /* top of level stack, i.e. last entry */ extern LEVEL_TYPE cur_status; /* Current situation */ /* The number of dimensions associated with each local variable * is held in the local_dims array; */ extern int * local_dims; /* For each call to a user-defined function, a separate DEFFUN * is created. These are held in a separate linked list and * written out at the beginning of the generated output. */ typedef struct deffun_line_str DEFFUN_LINE_TYPE, *DEFFUN_LINE_PTR; struct deffun_line_str { DEFFUN_LINE_PTR next; /* Link to next line */ DEFFUN_LINE_PTR previous; /* Link to previous line */ char * text; /* Text of line */ }; extern DEFFUN_LINE_PTR deffun_first; /* Start of DEFFUN list */ extern DEFFUN_LINE_PTR deffun_last; /* End of DEFFUN list */ /* saved_capture_variable holds the argument to !SMA.CAPTURING, * for use by EXECUTE */ extern char * saved_capture_variable; /* using_names indicates whether or not original names are being * used for local variables. */ extern int using_names; /*********************************************************************** * * Procedure declarations * ***********************************************************************/ /* Routines to handle the 'pfile' structure */ long get_paddr proto((struct p_file *pfile)); int get_pchar proto((struct p_file *pfile)); unsigned long get_plong proto((struct p_file *pfile)); unsigned int get_pshort proto((struct p_file *pfile)); int open_pfile proto((struct p_file *pfile, char *pfile_name)); int seek_pfile proto((struct p_file *pfile, long where)); int size_pfile proto((struct p_file *pfile, long * size_output)); /* Date/time conversion routines */ int get_date proto((char *buf, long date_value)); int get_time proto((char *buf, long time_value)); /* Template expander */ char * expand_template proto(( char * xtmplptr, /* Pointer to template */ char * xidptr, /* Pointer to message id */ char * xargptr /* Pointer to argument list */ )); /* @-variable lookup */ char * get_at_var proto((unsigned int devsys_offset)); /* Output of $OPTIONS lines */ void write_dollar_options proto((FILE * outfile, unsigned long opt_word)); /* Generated-subroutine lookup */ int gs_lookup proto((char **arg_vector, int *is_special)); /* Table of local-variable names */ int load_variable_names proto((long where)); char * get_local_var_name proto((unsigned int local_var_no)); char * get_common_var_name proto((COMMON_PTR cp, unsigned int common_offset)); void generate_unique proto((char * new_name));