487 lines
20 KiB
C
Executable File
487 lines
20 KiB
C
Executable File
/******************************************************************************
|
|
*
|
|
* 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));
|
|
|