6252 lines
153 KiB
C
6252 lines
153 KiB
C
/*
|
|
* Copyright (C) 2005, David Essex, Rildo Pragana.
|
|
* Copyright (C) 2003, Rildo Pragana, Bernard Giroud.
|
|
* Copyright (C) 2002, 2001, 2000, 1999, Rildo Pragana, Jim Noeth,
|
|
* David Essex, Glen Colbert, Andrew Cameron.
|
|
* Copyright (C) 1993, 1991 Rildo Pragana.
|
|
*
|
|
* This program 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 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program 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 this software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
* Assembler Code Generator for Cobol Compiler
|
|
*/
|
|
|
|
#include "htconfig.h"
|
|
#include "htversion.h"
|
|
#include "htcoboly.h"
|
|
#include "htcoblib.h"
|
|
#include "htglobals.h"
|
|
#include "mwindows.h"
|
|
|
|
//unsigned int gen_move_first(struct sym *sy, unsigned int loc, unsigned int size, unsigned int *idx); // walter 13-12-05
|
|
void gen_loaddesc2(struct sym *sy, int variable_length);
|
|
|
|
int pgm_segment = 0; /* # of program in source file */
|
|
int screen_io_enable = 0; /* use screen routines or not for accept/display */
|
|
|
|
int decimal_comma = 0; /* decimal char 1 = ',' ; 0 ='.' */
|
|
#define decimal_char() (decimal_comma ? ',' : '.')
|
|
|
|
char currency_symbol = '$';
|
|
char sch_convert_buf[512];
|
|
|
|
struct sym *screen_status_field = NULL; /* variable of crt status */
|
|
struct sym *cursor_field = NULL; /* variable of cursor */
|
|
struct lit *program_name_literal = NULL; /* literal thar holds the program name */
|
|
|
|
int stabs_on_sw = 0;
|
|
|
|
extern struct lextab literal;
|
|
extern int yydebug;
|
|
extern struct sym *curr_file;
|
|
|
|
struct sym *curr_paragr = NULL, *curr_section = NULL;
|
|
struct sym *curr_field;
|
|
short curr_call_mode = 0;
|
|
short curr_call_convention = 0;
|
|
unsigned stack_offset = 0; /* offset for variables on the stack */
|
|
/*#define SAVED_EBX_OFFSET 4*/ /* relative to %ebp */
|
|
unsigned stack_plus = 0;
|
|
unsigned global_offset = 4; /* offset for global variables (DATA) */
|
|
/*unsigned file_offset=0;*/
|
|
unsigned literal_offset = 0;
|
|
unsigned data_offset = 0;
|
|
/*#define data_offset global_offset*/
|
|
unsigned linkage_offset = 0;
|
|
unsigned using_offset = 8;
|
|
/* tmpvar_offset: for storage of temporary variables,
|
|
with space reclaimed after the current instruction*/
|
|
unsigned tmpvar_offset = 0;
|
|
unsigned tmpvar_max = 0;
|
|
|
|
unsigned last_lineno = 0;
|
|
short at_procedure = 0;
|
|
short refmod_slots = 0;
|
|
static char name_buf[MAXNAMEBUF];
|
|
|
|
struct lit *spe_lit_ZE = NULL; /* figurative constant ZERO */
|
|
struct lit *spe_lit_SP = NULL; /* figurative constant SPACE */
|
|
struct lit *spe_lit_LV = NULL; /* figurative constant LOW-VALUE */
|
|
struct lit *spe_lit_HV = NULL; /* figurative constant HIGH-VALUE */
|
|
struct lit *spe_lit_QU = NULL; /* figurative constant QUOTE */
|
|
static char init_ctype; /* hold homogenous type */
|
|
static short init_val; /* hold homogenous value */
|
|
static struct init_str_tab *istrp;
|
|
static unsigned curr_01_location; /* hold current root father when set_field_location */
|
|
|
|
struct list *expr_list = NULL;
|
|
struct list *files_list = NULL;
|
|
struct list *disp_list = NULL;
|
|
struct parm_list *parameter_list = NULL;
|
|
struct list *fields_list = NULL;
|
|
struct list *last_field = NULL;
|
|
struct index_to_table_list *index2table = NULL;
|
|
struct named_sect *named_sect_list = NULL;
|
|
struct list *switches_list = NULL;
|
|
struct list *vars_list = NULL;
|
|
short next_available_sec_no = SEC_FIRST_NAMED;
|
|
short default_sec_no = SEC_WORKING;
|
|
short curr_sec_no = SEC_WORKING;
|
|
|
|
struct parm_list *chaining_list = NULL; /* chaining variables */
|
|
|
|
int screen_label = 0;
|
|
int para_label = 0;
|
|
int block_label = 0;
|
|
int line_label = 0;
|
|
int paragr_num = 1;
|
|
int loc_label = 1;
|
|
unsigned char picture[100]; /* for max 50 signs and counts */
|
|
int picix, piccnt, decimals, sign, v_flag, n_flag, digits, pscale;
|
|
int filler_num = 1;
|
|
int active[37];
|
|
int at_linkage = 0;
|
|
int stackframe_cnt = 0;
|
|
int inner_stack_size = 0;
|
|
#if !defined(__WINDOWS__)
|
|
char program_id[120] = "main";
|
|
char *pgm_label = "main";
|
|
#else
|
|
char program_id[120] = "_main";
|
|
char *pgm_label = "_main";
|
|
#endif
|
|
int initial_flag = 0;
|
|
struct list *report_list = NULL;
|
|
static int need_desc_length_cleanup = 0;
|
|
extern int stabs_started;
|
|
|
|
|
|
extern int main_flag; /* Does it have an main entry point */
|
|
extern int main_entry_flag; /* Specify main entry point */
|
|
extern char main_entry_buf[]; /* main entry point name */
|
|
|
|
int module_flag = 1; /* All (sub)programs are modules (routines) */
|
|
int nested_flag = 0; /* Is this program nested inside another program */
|
|
int has_linkage = 0; /* Has linkage section ? */
|
|
/*
|
|
** Symbol table management routines
|
|
*/
|
|
|
|
struct sym *vartab[ HASHLEN ] = {NULL};
|
|
struct sym *labtab[ HASHLEN ] = {NULL};
|
|
struct lit *littab[ HASHLEN ] = {NULL};
|
|
|
|
int
|
|
hash(char *s)
|
|
{
|
|
int val;
|
|
for (val = 0; *s != '\0';)
|
|
val += (unsigned char) toupper(*s++); // walter coloquei (unsigned char)
|
|
return ( val % HASHLEN);
|
|
}
|
|
|
|
char *
|
|
savename(char *s)
|
|
{
|
|
char *ap;
|
|
if ((ap = (char *) malloc(strlen(s) + 1)) != NULL)
|
|
strcpy(ap, s);
|
|
return ( ap);
|
|
}
|
|
|
|
char *
|
|
upcase(char *s, char *buf)
|
|
{
|
|
char *t;
|
|
int n = SYMBUF_SIZE - 1;
|
|
t = buf;
|
|
while (*s && n--)
|
|
{
|
|
*t++ = toupper(*s++);
|
|
}
|
|
if (n <= 0)
|
|
{
|
|
yyerror("Too large symbol");
|
|
}
|
|
*t = 0;
|
|
return buf;
|
|
}
|
|
|
|
void
|
|
update_xreflist(struct sym *as)
|
|
{
|
|
if ((as->xrefs.pos > 0) &&
|
|
(as->xrefs.lineno[as->xrefs.pos - 1] == source_lineno))
|
|
return;
|
|
|
|
if (as->xrefs.size <= as->xrefs.pos)
|
|
{
|
|
as->xrefs.size += 10;
|
|
as->xrefs.lineno = realloc(as->xrefs.lineno, sizeof (int) * as->xrefs.size);
|
|
}
|
|
as->xrefs.lineno[as->xrefs.pos] = source_lineno;
|
|
as->xrefs.pos++;
|
|
}
|
|
|
|
struct sym *
|
|
lookup(char *s, int tab)
|
|
{
|
|
char sbuf[SYMBUF_SIZE];
|
|
if (tab == SYTB_LIT)
|
|
{ /* literals tab */
|
|
struct lit *as;
|
|
for (as = littab[ hash(s) ]; as != NULL; as = as->next)
|
|
if (strcmp(s, as->name) == 0)
|
|
return ( (struct sym *) as);
|
|
return ( NULL);
|
|
}
|
|
else
|
|
{
|
|
struct sym *as;
|
|
s = upcase(s, sbuf);
|
|
if (tab == SYTB_VAR)
|
|
as = vartab[ hash(s) ];
|
|
else
|
|
as = labtab[ hash(s) ];
|
|
for (; as != NULL; as = as->next)
|
|
if (strcmp(s, as->name) == 0)
|
|
return ( as);
|
|
return ( NULL);
|
|
}
|
|
}
|
|
|
|
struct sym *
|
|
install(char *name, int tab, int cloning)
|
|
{
|
|
char sbuf[SYMBUF_SIZE];
|
|
struct sym *clone;
|
|
struct sym *as;
|
|
struct lit *al;
|
|
int val;
|
|
|
|
if (tab == SYTB_LIT)
|
|
{
|
|
al = (struct lit *) malloc(sizeof (struct lit));
|
|
if (al == NULL)
|
|
return NULL;
|
|
if ((al->name = savename(name)) == NULL)
|
|
return NULL;
|
|
val = hash(al->name);
|
|
al->next = littab[ val ];
|
|
littab[ val ] = al;
|
|
al->type = 0;
|
|
al->all = 0;
|
|
al->litflag = 1;
|
|
al->nick = NULL;
|
|
al->len = strlen(name);
|
|
return ( (struct sym *) al);
|
|
}
|
|
else
|
|
{
|
|
name = upcase(name, sbuf);
|
|
if ((as = lookup(name, tab)) == NULL)
|
|
{
|
|
as = (struct sym *) malloc(sizeof (struct sym));
|
|
memset(as, 0, sizeof (struct sym));
|
|
if (as == NULL)
|
|
return NULL;
|
|
if ((as->name = savename(name)) == NULL)
|
|
return NULL;
|
|
val = hash(as->name);
|
|
if (tab == SYTB_VAR)
|
|
{
|
|
/* fprintf(stderr,"install: creating %s -> 0x%x\n",as->name,as); */
|
|
as->next = vartab[ val ];
|
|
vartab[ val ] = as;
|
|
}
|
|
else
|
|
{
|
|
as->next = labtab[ val ];
|
|
labtab[ val ] = as;
|
|
}
|
|
as->type = 0;
|
|
as->flags.is_pointer = 0;
|
|
as->flags.just_r = 0;
|
|
as->flags.separate_sign = 0;
|
|
as->flags.leading_sign = 0;
|
|
as->flags.blank = 0;
|
|
as->flags.sync = 0;
|
|
as->slack = 0;
|
|
as->pscale = 0;
|
|
as->defined = 0;
|
|
as->value = as->sort_data = NULL;
|
|
as->linkage_flg = 0;
|
|
as->litflag = 0;
|
|
as->scr = NULL;
|
|
as->clone = as->parent = NULL;
|
|
as->son = NULL;
|
|
as->occurs = NULL;
|
|
as->xrefs.size = 1;
|
|
as->xrefs.pos = 0;
|
|
as->xrefs.lineno = malloc(sizeof (int));
|
|
as->xrefs.lineno[0] = 0;
|
|
}
|
|
else if ((cloning && (as->defined == 1)) || (cloning == 2))
|
|
{
|
|
/* install clone (cloning==2 -> force) */
|
|
/* fprintf(stderr,"install: cloning %s -> 0x%x\n",as->name,as); */
|
|
clone = (struct sym *) malloc(sizeof (struct sym));
|
|
memset(clone, 0, sizeof (struct sym));
|
|
if (clone == NULL)
|
|
return NULL;
|
|
clone->name = as->name;
|
|
clone->type = 0;
|
|
clone->flags.is_pointer = 0;
|
|
clone->flags.just_r = 0;
|
|
clone->flags.separate_sign = 0;
|
|
clone->flags.leading_sign = 0;
|
|
clone->flags.blank = 0;
|
|
clone->flags.sync = 0;
|
|
clone->slack = 0;
|
|
clone->pscale = 0;
|
|
clone->defined = 0;
|
|
clone->value = as->sort_data = NULL;
|
|
clone->linkage_flg = 0;
|
|
clone->litflag = 0;
|
|
clone->scr = NULL;
|
|
clone->parent = NULL;
|
|
clone->occurs = NULL;
|
|
clone->clone = as->clone;
|
|
as->clone = clone;
|
|
as = clone;
|
|
}
|
|
return ( as);
|
|
}
|
|
}
|
|
|
|
struct lit *
|
|
install_lit(char *name, int length, int all)
|
|
{
|
|
struct lit *al;
|
|
int val;
|
|
|
|
/* if length was not given, take the length from the name string */
|
|
if (length == 0)
|
|
{
|
|
length = strlen(name);
|
|
}
|
|
al = (struct lit *) malloc(sizeof (struct lit));
|
|
if (al == NULL)
|
|
return NULL;
|
|
/* it is safer to null terminate it, so alloc one char more */
|
|
al->name = malloc(length + 1);
|
|
if (al->name == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
memcpy(al->name, name, length);
|
|
*(al->name + length) = 0;
|
|
|
|
val = hash(al->name);
|
|
al->next = littab[ val ];
|
|
littab[ val ] = al;
|
|
al->type = 0;
|
|
al->all = all;
|
|
al->litflag = 1;
|
|
al->nick = NULL;
|
|
al->len = length;
|
|
return al;
|
|
}
|
|
|
|
struct sym *
|
|
lookup_label(struct sym *sy, struct sym *parent)
|
|
{
|
|
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr, "lookup_label: %s", sy->name);
|
|
#endif
|
|
#endif
|
|
while (sy->clone && (sy->parent != parent))
|
|
sy = sy->clone;
|
|
if (sy->parent == parent)
|
|
{
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
if (sy->parent != NULL)
|
|
fprintf(stderr, " found -> %s\n", sy->parent->name);
|
|
else
|
|
fprintf(stderr, " found\n");
|
|
#endif
|
|
#endif
|
|
return sy;
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr, " not found\n");
|
|
#endif
|
|
#endif
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
struct sym *
|
|
lookup_variable(struct sym *sy, struct sym *parent)
|
|
{
|
|
struct sym *tmp;
|
|
/* sy = lookup(sy->name,SYTB_VAR); */
|
|
if (parent->litflag == 2)
|
|
{
|
|
parent = (struct sym *) ((struct vref *) parent)->sym;
|
|
}
|
|
while (1)
|
|
{
|
|
tmp = sy;
|
|
while (tmp && tmp->parent != parent)
|
|
tmp = tmp->parent;
|
|
if (tmp && tmp->parent == parent)
|
|
break;
|
|
if (sy->clone == NULL)
|
|
break;
|
|
sy = sy->clone;
|
|
}
|
|
return sy;
|
|
}
|
|
|
|
struct sym *
|
|
lookup_parent(struct sym *sy, struct sym *parent)
|
|
{
|
|
struct sym *tmp;
|
|
if (parent->litflag == 2)
|
|
{
|
|
parent = (struct sym *) ((struct vref *) parent)->sym;
|
|
}
|
|
while (sy)
|
|
{
|
|
tmp = sy;
|
|
while (tmp && tmp->parent != parent)
|
|
tmp = tmp->parent;
|
|
if (tmp && tmp->parent == parent)
|
|
break;
|
|
sy = sy->clone;
|
|
}
|
|
return sy;
|
|
}
|
|
|
|
struct sym *
|
|
lookup_for_redefines(struct sym *sy)
|
|
{
|
|
struct sym *tmp;
|
|
if (curr_field->parent == NULL)
|
|
{
|
|
tmp = lookup(sy->name, SYTB_VAR);
|
|
}
|
|
else
|
|
{
|
|
tmp = lookup_variable(sy, curr_field->parent);
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
void
|
|
clear_symtab()
|
|
{
|
|
struct sym *sy, *sy1, *tmp;
|
|
/* struct lit *lt,*lt1,*ltmp; */
|
|
int i;
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy1 = vartab[i]; sy1 != NULL;)
|
|
{
|
|
for (sy = sy1->clone; sy;)
|
|
{
|
|
if (sy)
|
|
{
|
|
tmp = sy;
|
|
sy = sy->clone;
|
|
free(tmp);
|
|
}
|
|
}
|
|
tmp = sy1;
|
|
sy1 = sy1->next;
|
|
free(tmp);
|
|
}
|
|
vartab[i] = NULL;
|
|
}
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy1 = labtab[i]; sy1 != NULL;)
|
|
{
|
|
for (sy = sy1->clone; sy;)
|
|
{
|
|
if (sy)
|
|
{
|
|
tmp = sy;
|
|
sy = sy->clone;
|
|
free(tmp);
|
|
}
|
|
}
|
|
tmp = sy1;
|
|
sy1 = sy1->next;
|
|
free(tmp);
|
|
}
|
|
labtab[i] = NULL;
|
|
}
|
|
/*for (i=0;i<HASHLEN;i++) {
|
|
for (lt1=littab[i];lt1!=NULL;) {
|
|
ltmp = lt1;
|
|
lt1 = lt1->next;
|
|
free(ltmp);
|
|
}
|
|
littab[i] = NULL;
|
|
}*/
|
|
}
|
|
|
|
/* clear_offset() is called when starting a new program segment */
|
|
void
|
|
clear_offsets()
|
|
{
|
|
stack_offset = 0;
|
|
global_offset = 4;
|
|
literal_offset = 0;
|
|
data_offset = 0;
|
|
linkage_offset = 0;
|
|
using_offset = 8;
|
|
refmod_slots = 0;
|
|
free_list(fields_list);
|
|
fields_list = NULL;
|
|
free_list(files_list);
|
|
files_list = NULL;
|
|
/* clear all current paragraphs/sections and fields */
|
|
curr_paragr = NULL;
|
|
curr_section = NULL;
|
|
curr_field = NULL;
|
|
/* free tmpvar storage */
|
|
tmpvar_offset = 0;
|
|
tmpvar_max = 0;
|
|
stabs_started = 0;
|
|
}
|
|
|
|
/*** we need this because the literal string is already stored ***/
|
|
char
|
|
sign_to_char(int digit)
|
|
{
|
|
char cDigit;
|
|
if (!digit)
|
|
cDigit = '}';
|
|
else if (digit == 0x80)
|
|
cDigit = '{';
|
|
else if (digit > 0)
|
|
cDigit = (char) ('A' + digit - 1);
|
|
else
|
|
cDigit = (char) ('J' - digit - 1);
|
|
return cDigit;
|
|
}
|
|
|
|
void
|
|
invert_literal_sign(struct lit *sy)
|
|
{
|
|
char *s = sy->name;
|
|
int off = strlen(sy->name) - 1;
|
|
s[off] = sign_to_char(-(s[off] - '0'));
|
|
}
|
|
|
|
void
|
|
check_decimal_point(struct lit *lit)
|
|
{
|
|
char *s = lit->name;
|
|
if ((decimal_comma && strchr(s, '.')) ||
|
|
(!decimal_comma && strchr(s, ',')))
|
|
{
|
|
yyerror("wrong decimal point character in numeric literal");
|
|
}
|
|
}
|
|
|
|
int
|
|
is_variable(struct sym *sy)
|
|
{
|
|
int r = 0;
|
|
if (sy->litflag == 0)
|
|
{
|
|
switch (sy->type)
|
|
{
|
|
case '8': /* 88 field */
|
|
case DTYPE_DISPLAY: /* numeric */
|
|
case DTYPE_ALPHA: /* alpha */
|
|
case DTYPE_BININT: /* binary (comp/computational) */
|
|
case DTYPE_PACKED: /* compacted (comp-3/comptational-3) */
|
|
case DTYPE_ACCEPT_DISPLAY: /* screen data */
|
|
case DTYPE_EDITED: /* edited */
|
|
case DTYPE_GROUP: /* group */
|
|
case DTYPE_FLOAT: /* float(comp-1 4 bytes) / double(comp-2 8 bytes) */
|
|
case DTYPE_ALPHANUMERIC: /* alphanum */
|
|
r = 1;
|
|
break;
|
|
default:
|
|
r = 0;
|
|
break;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
int
|
|
is_subscripted(struct sym *sy)
|
|
{
|
|
if (sy->occurs_flg) /* the item itself "occurs" */
|
|
return 1;
|
|
while (sy->parent != NULL)
|
|
{ /* some parenr "occurs" */
|
|
sy = sy->parent;
|
|
if (sy->occurs_flg)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
adjust_linkage_vars(int start_offset)
|
|
{
|
|
struct sym *sy, *sy1;
|
|
int i;
|
|
int offset = start_offset;
|
|
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy1 = vartab[i]; sy1 != NULL; sy1 = sy1->next)
|
|
{
|
|
for (sy = sy1; sy; sy = sy->clone)
|
|
{
|
|
if (sy->parent == NULL && sy->linkage_flg == 1)
|
|
{
|
|
sy->linkage_flg = -offset;
|
|
offset += 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
* Put a field to its initial value.
|
|
* It can be a value specified by 'value' or an initialization value
|
|
* If it is a group field, initialize all the fields under it.
|
|
*/
|
|
static void
|
|
set_initial_value(struct sym *sy)
|
|
{
|
|
int j, nb_fields;
|
|
struct init_str init_templ;
|
|
|
|
if (sy->redefines) return;
|
|
#ifdef DEBUG_COMPILER
|
|
if (sy->value)
|
|
fprintf(o_src, "# initial value to field '%s' = '%s' \n",
|
|
sy->name, sy->value->name);
|
|
else
|
|
fprintf(o_src, "# initial value to field '%s', INITIALIZED \n",
|
|
sy->name);
|
|
#endif
|
|
/* Initialize a non-group field */
|
|
if (sy->level == 77 || (sy->level == 1 && sy->son == NULL))
|
|
{
|
|
if (sy->value)
|
|
gen_move_init((struct sym *) sy->value, sy); /* initial value */
|
|
else
|
|
gen_initialize(sy, 0); /* initialize at spaces or 0 */
|
|
return;
|
|
}
|
|
|
|
/* Initialize a group to zero or blank */
|
|
init_ctype = ' ';
|
|
init_val = -1;
|
|
nb_fields = get_nb_fields(sy, 1);
|
|
if (init_ctype != '&' && init_ctype != ' ' && init_val > 1)
|
|
{
|
|
gen_init_str(sy, init_ctype, symlen(sy));
|
|
return;
|
|
}
|
|
|
|
/* Initialize a group's fields one by one */
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# istrp = malloc(%d) nb_fields = %d\n",
|
|
nb_fields * sizeof (init_templ), nb_fields);
|
|
#endif
|
|
istrp = malloc(nb_fields * sizeof (init_templ));
|
|
build_init_str(sy, nb_fields);
|
|
for (j = 0; j < nb_fields; j++)
|
|
{
|
|
if (istrp->ent[j].value != NULL)
|
|
{
|
|
unsigned saved_loc = istrp->ent[j].sy->location;
|
|
istrp->ent[j].sy->location = istrp->ent[j].location;
|
|
gen_move_init((struct sym *) istrp->ent[j].sy->value
|
|
, istrp->ent[j].sy);
|
|
istrp->ent[j].sy->location = saved_loc;
|
|
}
|
|
}
|
|
free(istrp);
|
|
istrp = NULL;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Initialize all the variables at the beginig of the program
|
|
*/
|
|
void
|
|
do_init_val()
|
|
{
|
|
struct sym *sy, *sy1, *v;
|
|
int i;
|
|
char typ;
|
|
for (i = 0; i < HASHLEN; i++)
|
|
for (sy1 = vartab[i]; sy1 != NULL; sy1 = sy1->next)
|
|
for (sy = sy1; sy != NULL; sy = sy->clone)
|
|
if (sy->type != 'F' && sy->type != '8' &&
|
|
sy->type != 'K' && sy->type != 'J')
|
|
{
|
|
v = sy;
|
|
typ = v->type;
|
|
if (typ == 'F' || typ == 'R' || typ == 'K' || typ == 'J'
|
|
|| typ == '8')
|
|
continue;
|
|
/* Here only work with level 1 and 77 */
|
|
if (v->level != 1 && v->level != 77) continue;
|
|
/* Don't initialize fields in linkage */
|
|
if (v->linkage_flg) continue;
|
|
|
|
set_initial_value(v);
|
|
}
|
|
}
|
|
|
|
void
|
|
save_field_in_list(struct sym *sy)
|
|
{
|
|
struct list *list;
|
|
if (fields_list == NULL)
|
|
{
|
|
list = (struct list *) malloc(sizeof (struct list));
|
|
last_field = fields_list = list;
|
|
list->next = NULL;
|
|
list->var = sy;
|
|
}
|
|
else
|
|
{
|
|
list = (struct list *) malloc(sizeof (struct list));
|
|
list->var = sy;
|
|
list->next = NULL;
|
|
last_field->next = list;
|
|
last_field = list;
|
|
}
|
|
}
|
|
|
|
void
|
|
save_literal(struct lit *v, int type)
|
|
{
|
|
char *s;
|
|
char *dp;
|
|
int piclen;
|
|
/* if (v->type) return; */ /* already saved */
|
|
s = v->name;
|
|
piclen = 3; /* assume 'X'-only literal */
|
|
if ((type == DTYPE_DISPLAY) && (*(v->name + v->len - 1) > '9'))
|
|
{
|
|
piclen += 2; /* we need space for the sign picture char */
|
|
}
|
|
if (type != DTYPE_ALPHANUMERIC && (dp = strchr(s, decimal_char())) != NULL)
|
|
{
|
|
piclen += 4; /* reserve space for 'V' and decimal part */
|
|
v->decimals = v->len - (int) (dp - s) - 1;
|
|
}
|
|
else v->decimals = 0;
|
|
/* v->pscale=0; */
|
|
if (type == DTYPE_ALPHANUMERIC && v->len > 255)
|
|
{
|
|
piclen += (v->len / 255)*2;
|
|
}
|
|
v->type = type;
|
|
/****** save literal in fields list for later *******/
|
|
save_field_in_list((struct sym *) v);
|
|
/******** save address of const string ************/
|
|
v->location = literal_offset;
|
|
v->sec_no = SEC_CONST;
|
|
if (v->decimals)
|
|
literal_offset += v->len;
|
|
/* it's already one chr larger (decimal point) */
|
|
else
|
|
literal_offset += v->len + 1;
|
|
/******** save address of field descriptor ********/
|
|
v->descriptor = literal_offset;
|
|
literal_offset += HTG_fld_desc_len + piclen;
|
|
/* printf("save_literal: name=%s, type=%c, offset=%x, piclen=%d\n",
|
|
v->name, v->type, v->descriptor, piclen); */
|
|
}
|
|
|
|
void
|
|
save_named_sect(struct sym *sy)
|
|
{
|
|
/*char *s;
|
|
char *dp;*/
|
|
struct named_sect *nsp;
|
|
nsp = (struct named_sect *) malloc(sizeof (struct named_sect));
|
|
sy->flags.external = 1;
|
|
nsp->sec_no = next_available_sec_no++;
|
|
/* nsp->os_name = sy->name; walter...why these ??? */
|
|
nsp->os_name = (char *) malloc(strlen(nsp->os_name) + 1);
|
|
strcpy(nsp->os_name, sy->name);
|
|
chg_underline(nsp->os_name);
|
|
nsp->next = named_sect_list;
|
|
named_sect_list = nsp;
|
|
curr_sec_no = nsp->sec_no;
|
|
sy->sec_no = curr_sec_no;
|
|
}
|
|
|
|
struct lit *
|
|
save_special_literal(char val, char picc, char *nick)
|
|
{
|
|
struct lit *v;
|
|
v = (struct lit *) install(nick, SYTB_LIT, 0);
|
|
if (v->type) return NULL; /* already saved */
|
|
v->decimals = 0;
|
|
/* v->pscale=0; */
|
|
v->type = picc;
|
|
v->nick = (char *) malloc(2);
|
|
v->nick[0] = val;
|
|
v->nick[1] = 0;
|
|
v->len = 1;
|
|
v->all = 0;
|
|
save_field_in_list((struct sym *) v);
|
|
v->location = literal_offset;
|
|
v->sec_no = SEC_CONST;
|
|
literal_offset += 2; /* we have only 1-char special literals */
|
|
v->descriptor = literal_offset;
|
|
literal_offset += (HTG_fld_desc_len + 3);
|
|
return v;
|
|
}
|
|
|
|
void
|
|
define_switch_field(struct sym *sy, struct sym *sy2)
|
|
{
|
|
|
|
curr_field = NULL;
|
|
define_field(77, sy);
|
|
curr_field->len = 2;
|
|
curr_field->type = DTYPE_BININT;
|
|
curr_field->decimals = 0;
|
|
picture[0] = '9';
|
|
picture[1] = 4;
|
|
picture[2] = 0;
|
|
curr_field->ix_desc = sy2;
|
|
update_field(curr_field);
|
|
sy2->defined = 1; /* switch number is implicitly defined */
|
|
switches_list = insert_list(switches_list, sy);
|
|
}
|
|
|
|
struct lit *
|
|
define_num_lit(int value)
|
|
{
|
|
char tblmax[21];
|
|
struct lit *v;
|
|
|
|
sprintf(tblmax, "%d", value);
|
|
v = (struct lit *) install(tblmax, SYTB_LIT, 0);
|
|
save_literal(v, DTYPE_DISPLAY);
|
|
return v;
|
|
}
|
|
|
|
void
|
|
save_switch_value(struct sym *sy, int value)
|
|
{
|
|
struct lit *v;
|
|
|
|
v = define_num_lit(value);
|
|
define_field(88, sy);
|
|
sy->value = v;
|
|
sy->value2 = v;
|
|
}
|
|
|
|
void
|
|
put_disp_list(struct sym *sy)
|
|
{
|
|
struct list *list, *tmp;
|
|
#if 0
|
|
if ((!(sy->defined)) && (sy->litflag != 1))
|
|
{
|
|
yyerror("variable %s not defined", sy->name);
|
|
}
|
|
#endif
|
|
/* fprintf(o_src,"# put_disp_list: %s\n",sy->name); */
|
|
list = (struct list *) malloc(sizeof (struct list));
|
|
list->var = sy;
|
|
list->next = NULL;
|
|
if (disp_list == NULL)
|
|
disp_list = list;
|
|
else
|
|
{
|
|
tmp = disp_list;
|
|
while (tmp->next != NULL) tmp = tmp->next;
|
|
tmp->next = list;
|
|
}
|
|
}
|
|
|
|
int
|
|
pic_digits(struct sym *sy, char target)
|
|
{
|
|
char *p = NULL;
|
|
int len = 0;
|
|
if (sy == NULL)
|
|
return 0;
|
|
if (sy->litflag)
|
|
{
|
|
len = strlen(sy->name);
|
|
if (strchr(sy->name, decimal_char())) len--;
|
|
if (strchr(sy->name, '+')) len--;
|
|
if (strchr(sy->name, '-')) len--;
|
|
/* printf("pic_digits: %s -> %d\n",sy->name,len); */
|
|
return len;
|
|
}
|
|
else
|
|
{
|
|
p = sy->picstr;
|
|
while (*p)
|
|
{
|
|
if (*p++ == target)
|
|
{
|
|
len += *p++;
|
|
}
|
|
else
|
|
p++;
|
|
}
|
|
}
|
|
/* printf("pic_digits: %s -> %d\n",sy->name,len); */
|
|
return len;
|
|
}
|
|
|
|
/* Return the maximum length which might be occupied by a corresponding value */
|
|
int
|
|
get_max_edt_len(struct sym * sy)
|
|
{
|
|
int plen;
|
|
/*walter*/
|
|
if (sy->type == DTYPE_BININT)
|
|
return (sy->len * 3);
|
|
/*fimwalter*/
|
|
if (sy->type == DTYPE_ALPHANUMERIC || sy->type == DTYPE_ALPHA ||
|
|
sy->type == DTYPE_EDITED || sy->type == DTYPE_GROUP ||
|
|
sy->type == DTYPE_ALPHANUMERICL || sy->type == DTYPE_ACCEPT_DISPLAY)
|
|
{
|
|
plen = sy->len;
|
|
}
|
|
else
|
|
{
|
|
plen = pic_digits(sy, '9');
|
|
if (sy->picstr[0] == 'S') plen++;
|
|
if (sy->decimals > 0) plen++;
|
|
if (sy->pscale != 0) plen = plen + abs(sy->pscale);
|
|
}
|
|
return plen;
|
|
}
|
|
|
|
int
|
|
query_comp_len(struct sym * sy)
|
|
{
|
|
int plen;
|
|
// char target = '9';
|
|
|
|
if (sy->stype == 'X')
|
|
{
|
|
// target = 'X';
|
|
plen = pic_digits(sy, 'X');
|
|
/* for the time being, picture is altered just before output
|
|
in htcobemt.c */
|
|
/* strcpy(sy->picstr,"9\xa"); */ /* max picture for 4 bytes */
|
|
return plen;
|
|
}
|
|
else
|
|
{
|
|
if ((plen = pic_digits(sy, '9')) <= 2)
|
|
return 1;
|
|
if (plen <= 4)
|
|
return 2;
|
|
if (plen <= 9)
|
|
return 4;
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
int
|
|
symlen(struct sym *sy)
|
|
{
|
|
/*int plen;*/
|
|
if (sy->type == DTYPE_PACKED)
|
|
return sy->len / 2 + 1;
|
|
else if (sy->litflag == 1)
|
|
return ((struct lit *) sy)->len;
|
|
return sy->len;
|
|
}
|
|
|
|
/* Returns the minimum number of 9 to hold a complete value */
|
|
int
|
|
sym_min_pic(struct sym *sy)
|
|
{
|
|
|
|
if (sy->type != DTYPE_BININT)
|
|
return sy->len;
|
|
if (sy->stype != 'X')
|
|
return pic_digits(sy, '9');
|
|
switch (symlen(sy))
|
|
{
|
|
case 1: return 3;
|
|
case 2: return 5;
|
|
case 4: return 10;
|
|
case 8: return 19;
|
|
}
|
|
return pic_digits(sy, '9');
|
|
}
|
|
|
|
void
|
|
add_alternate_key(struct sym *sy, int duplicates)
|
|
{
|
|
struct sym *f = curr_file;
|
|
struct alternate_list *alt, *new;
|
|
alt = (struct alternate_list *) f->alternate;
|
|
new = malloc(sizeof (struct alternate_list));
|
|
new->next = alt;
|
|
new->key = sy;
|
|
new->duplicates = duplicates;
|
|
f->alternate = (struct sym *) new;
|
|
}
|
|
|
|
struct list *
|
|
insert_list(struct list *l, void *item)
|
|
{
|
|
struct list *tmp;
|
|
if (l == NULL)
|
|
{
|
|
l = malloc(sizeof (struct list));
|
|
l->var = item;
|
|
l->next = NULL;
|
|
}
|
|
else
|
|
{
|
|
for (tmp = l; tmp->next != NULL; tmp = tmp->next);
|
|
tmp->next = malloc(sizeof (struct list));
|
|
tmp->next->var = item;
|
|
tmp->next->next = NULL;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
struct gvar_list *
|
|
gvar_list_append(struct gvar_list *l, struct sym *item, int linenum)
|
|
{
|
|
struct gvar_list *tmp;
|
|
|
|
if (l == NULL)
|
|
{
|
|
tmp = malloc(sizeof (struct gvar_list));
|
|
l = tmp;
|
|
}
|
|
else
|
|
{
|
|
for (tmp = l; tmp->next != NULL; tmp = tmp->next);
|
|
tmp->next = malloc(sizeof (struct gvar_list));
|
|
tmp = tmp->next;
|
|
}
|
|
tmp->u.sym = item;
|
|
tmp->attribute = linenum;
|
|
tmp->next = NULL;
|
|
|
|
return l;
|
|
}
|
|
|
|
void
|
|
sort_keys_append(struct sym *fname, struct gvar_list *l)
|
|
{
|
|
struct gvar_list *gvar_w1, *gvar_w2;
|
|
struct sym *sym_wk;
|
|
|
|
for (gvar_w1 = l; gvar_w1 != NULL; gvar_w1 = gvar_w1->next)
|
|
{
|
|
for (gvar_w2 = gvar_w1->u.gvar; gvar_w2 != NULL; gvar_w2 = gvar_w2->next)
|
|
{
|
|
sym_wk = gvar_w2->u.sym;
|
|
sym_wk->direction = gvar_w1->attribute;
|
|
sym_wk->sort_data = fname->sort_data;
|
|
/* fname->sort_data = sym_wk; */
|
|
fname->sort_data = (void *) sym_wk;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct gvar_list *
|
|
sort_key_list_create(struct gvar_list *item, int atrbt)
|
|
{
|
|
struct gvar_list *l;
|
|
|
|
l = malloc(sizeof (struct gvar_list));
|
|
l->u.gvar = item;
|
|
l->attribute = atrbt;
|
|
l->next = NULL;
|
|
|
|
return l;
|
|
}
|
|
|
|
struct gvar_list *
|
|
sort_keys_list_append(struct gvar_list *l, struct gvar_list *item)
|
|
{
|
|
struct gvar_list *tmp;
|
|
|
|
if (l == NULL)
|
|
{
|
|
l = item;
|
|
}
|
|
else
|
|
{
|
|
for (tmp = l; tmp->next != NULL; tmp = tmp->next);
|
|
tmp->next = item;
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
void
|
|
free_list(struct list *l)
|
|
{
|
|
struct list *tmp;
|
|
while (l != NULL)
|
|
{
|
|
tmp = l->next;
|
|
free(l);
|
|
l = tmp;
|
|
}
|
|
l = NULL;
|
|
}
|
|
|
|
void
|
|
mark_decl_list(struct list *l)
|
|
{
|
|
struct list *tmp;
|
|
while (l != NULL)
|
|
{
|
|
((struct sym *) l->var)->refmod_redef.declarative = curr_section;
|
|
tmp = l->next;
|
|
free(l);
|
|
l = tmp;
|
|
}
|
|
}
|
|
|
|
struct scr_info *
|
|
alloc_scr_info()
|
|
{
|
|
struct scr_info *new;
|
|
struct scr_info *parent_info = NULL;
|
|
|
|
if (curr_field && curr_field->parent)
|
|
parent_info = curr_field->parent->scr;
|
|
|
|
new = malloc(sizeof (struct scr_info));
|
|
new->attr = 0;
|
|
new->line = 0;
|
|
new->column = 0;
|
|
new->foreground = NULL;
|
|
new->background = NULL;
|
|
new->color = NULL;
|
|
new->line_var = NULL;
|
|
new->column_var = NULL;
|
|
new->from = NULL;
|
|
new->to = NULL;
|
|
new->line_sign = 0;
|
|
new->column_sign = 0;
|
|
new->size = NULL;
|
|
|
|
if (parent_info) /* If exists copy information from parent field */
|
|
{
|
|
new->attr = parent_info->attr;
|
|
new->foreground = parent_info->foreground;
|
|
new->background = parent_info->background;
|
|
new->color = parent_info->color;
|
|
/* new->line = parent_info->line; */
|
|
/* new->column = parent_info->column; */
|
|
/* new->line_var = parent_info->line_var; */
|
|
/* new->column_var = parent_info->column_var; */
|
|
/* new->line_sign = parent_info->line_sign; */
|
|
/* new->column_sign = parent_info->column_sign; */
|
|
}
|
|
if (parent_info && curr_field->parent->son != curr_field)
|
|
{
|
|
new->line = new->column = 0;
|
|
new->line_var = new->column_var = NULL;
|
|
new->line_sign = new->column_sign = 0;
|
|
}
|
|
return new;
|
|
}
|
|
|
|
struct inspect_before_after *
|
|
alloc_inspect_before_after(struct inspect_before_after *ba,
|
|
int before_after, struct sym *var)
|
|
{
|
|
if (ba == NULL)
|
|
{
|
|
ba = malloc(sizeof (struct inspect_before_after));
|
|
ba->before = ba->after = NULL;
|
|
}
|
|
if (before_after == 1)
|
|
{ /* before given */
|
|
if (ba->before)
|
|
{
|
|
yyerror("only one BEFORE phrase can be given");
|
|
}
|
|
else
|
|
{
|
|
ba->before = var;
|
|
}
|
|
}
|
|
else if (before_after == 2)
|
|
{ /* after given */
|
|
if (ba->after)
|
|
{
|
|
yyerror("only one AFTER phrase can be given");
|
|
}
|
|
else
|
|
{
|
|
ba->after = var;
|
|
}
|
|
}
|
|
return ba;
|
|
}
|
|
|
|
struct converting_struct *
|
|
alloc_converting_struct(struct sym *fromvar, struct sym *tovar,
|
|
struct inspect_before_after *ba)
|
|
{
|
|
struct converting_struct *new;
|
|
new = malloc(sizeof (struct converting_struct));
|
|
new->fromvar = fromvar;
|
|
new->tovar = tovar;
|
|
new->before_after = ba;
|
|
return new;
|
|
}
|
|
|
|
struct tallying_list *
|
|
alloc_tallying_list(struct tallying_list *tl, struct sym *count,
|
|
struct tallying_for_list *tfl)
|
|
{
|
|
struct tallying_list *new;
|
|
new = malloc(sizeof (struct tallying_list));
|
|
new->next = tl;
|
|
new->tflist = tfl;
|
|
new->count = count;
|
|
return new;
|
|
}
|
|
|
|
struct tallying_for_list *
|
|
alloc_tallying_for_list(struct tallying_for_list *tfl, int options,
|
|
struct sym *forvar, struct inspect_before_after *ba)
|
|
{
|
|
struct tallying_for_list *new;
|
|
new = malloc(sizeof (struct tallying_for_list));
|
|
new->next = tfl;
|
|
new->options = options;
|
|
new->forvar = forvar;
|
|
new->before_after = ba;
|
|
return new;
|
|
}
|
|
|
|
struct replacing_list *
|
|
alloc_replacing_list(struct replacing_list *rl, int options,
|
|
struct replacing_by_list *rbl, struct sym *byvar,
|
|
struct inspect_before_after *ba)
|
|
{
|
|
|
|
struct replacing_list *new;
|
|
new = malloc(sizeof (struct replacing_list));
|
|
new->next = rl;
|
|
new->options = options;
|
|
new->replbylist = rbl;
|
|
new->byvar = byvar;
|
|
new->before_after = ba;
|
|
return new;
|
|
}
|
|
|
|
struct replacing_by_list *
|
|
alloc_replacing_by_list(struct replacing_by_list *rbl,
|
|
struct sym *replvar, struct sym *byvar,
|
|
struct inspect_before_after *ba)
|
|
{
|
|
struct replacing_by_list *new;
|
|
new = malloc(sizeof (struct replacing_by_list));
|
|
new->next = rbl;
|
|
new->replvar = replvar;
|
|
new->byvar = byvar;
|
|
new->before_after = ba;
|
|
return new;
|
|
}
|
|
|
|
struct unstring_delimited *
|
|
alloc_unstring_delimited(short int all, struct sym *var)
|
|
{
|
|
struct unstring_delimited *ud;
|
|
ud = malloc(sizeof (struct unstring_delimited));
|
|
ud->next = NULL;
|
|
ud->var = var;
|
|
ud->all = all;
|
|
return ud;
|
|
}
|
|
|
|
struct unstring_destinations *
|
|
alloc_unstring_dest(struct sym *var, struct sym *delim, struct sym *count)
|
|
{
|
|
struct unstring_destinations *ud;
|
|
ud = malloc(sizeof (struct unstring_destinations));
|
|
ud->next = NULL;
|
|
ud->var = var;
|
|
ud->delim = delim;
|
|
ud->count = count;
|
|
return ud;
|
|
}
|
|
|
|
struct string_from *
|
|
alloc_string_from(struct sym *var, struct sym *delim)
|
|
{
|
|
struct string_from *sf;
|
|
sf = malloc(sizeof (struct string_from));
|
|
sf->next = NULL;
|
|
sf->var = var;
|
|
sf->delim = delim;
|
|
return sf;
|
|
}
|
|
|
|
void
|
|
gen_unstring(struct sym *var, struct unstring_delimited *delim,
|
|
struct unstring_destinations *dest, struct sym *ptr,
|
|
struct sym *tally)
|
|
{
|
|
|
|
struct unstring_destinations *dest1;
|
|
struct unstring_delimited *delim1;
|
|
|
|
fprintf(o_src, "# UNSTRING %s\n", var->name);
|
|
gen_loadvar((struct sym *) NULL); /* mark the end of destinations */
|
|
while (dest)
|
|
{
|
|
gen_loadvar(dest->count);
|
|
gen_loadvar(dest->delim);
|
|
gen_loadvar(dest->var);
|
|
dest1 = dest;
|
|
dest = dest->next;
|
|
free(dest1);
|
|
}
|
|
gen_loadvar((struct sym *) NULL); /* mark the end of delimiters */
|
|
while (delim)
|
|
{
|
|
push_immed(delim->all); /* push "all" flag */
|
|
gen_loadvar(delim->var);
|
|
delim1 = delim;
|
|
delim = delim->next;
|
|
free(delim1);
|
|
}
|
|
gen_loadvar(tally);
|
|
gen_loadvar(ptr);
|
|
gen_loadvar(var);
|
|
asm_call("tcob_unstring");
|
|
}
|
|
|
|
void
|
|
gen_stringcmd(struct string_from *sf, struct sym *sy, struct sym *ptr)
|
|
{
|
|
struct string_from *sf1;
|
|
fprintf(o_src, "# STRING into %s\n", sy->name);
|
|
gen_loadvar((struct sym *) NULL); /* mark the end of variables */
|
|
/* DELIMITED BY SIZE implied at end of source list */
|
|
if (sf && (sf->delim == (struct sym *) - 1))
|
|
sf->delim = (struct sym *) NULL;
|
|
/* Load the string_from source list */
|
|
while (sf)
|
|
{
|
|
gen_loadvar(sf->delim);
|
|
gen_loadvar(sf->var);
|
|
sf1 = sf;
|
|
sf = sf->next;
|
|
/* Delimiter of -1 means use previous delimiter */
|
|
if (sf && (sf->delim == (struct sym *) - 1))
|
|
sf->delim = sf1->delim;
|
|
free(sf1);
|
|
}
|
|
gen_loadvar(ptr);
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_stringcmd");
|
|
}
|
|
|
|
/* walter acrescentei cor */
|
|
static
|
|
void
|
|
gen_display_screen_item(struct sym *sy, int main, int color)
|
|
{
|
|
struct sym *tmp, *var = sy;
|
|
struct list *tmpl;
|
|
|
|
if (var->litflag == 2 || var->litflag == 4)
|
|
{
|
|
var = ((struct vref *) var)->sym;
|
|
if (var->litflag == 2)
|
|
var = ((struct vref *) var)->sym;
|
|
}
|
|
if ((!(var->defined)) && (var->litflag != 1))
|
|
{
|
|
yyerror("variable %s not defined", var->name);
|
|
}
|
|
if (main)
|
|
{
|
|
fprintf(o_src, "# Screen Section: %s\n", var->name);
|
|
}
|
|
if (var->son == NULL)
|
|
{
|
|
fprintf(o_src, "# Screen Field: %s\n", var->name);
|
|
gen_call_scr_process(var);
|
|
}
|
|
else
|
|
{
|
|
for (tmp = var->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
gen_display_screen_item(tmp, 0, color);
|
|
}
|
|
}
|
|
if (main)
|
|
{
|
|
asm_call("tcob_display_screen");
|
|
if (disp_list->next)
|
|
{
|
|
yyerror("we do not handle more than one screen");
|
|
}
|
|
tmpl = disp_list;
|
|
disp_list = disp_list->next;
|
|
free(tmpl);
|
|
}
|
|
}
|
|
|
|
/* walter acrescentei cor */
|
|
void
|
|
gen_display_screen(int nl, int color)
|
|
{
|
|
gen_display_line(1, nl, color);
|
|
}
|
|
|
|
/* walter acrescentei cor */
|
|
void
|
|
gen_display_line(int dupon, int nl, int color)
|
|
{
|
|
struct list *tmp;
|
|
/*int len;*/
|
|
int dspflags;
|
|
int first = 1;
|
|
struct sym *sy;
|
|
if (disp_list)
|
|
{
|
|
/* separate screen displays from display of regular variables */
|
|
sy = (struct sym *) disp_list->var;
|
|
if (disp_list && sy->litflag != 1)
|
|
{
|
|
if (sy->litflag != 4 && sy->litflag != 2 && sy->scr)
|
|
{
|
|
gen_display_screen_item(disp_list->var, 1, color);
|
|
return;
|
|
}
|
|
}
|
|
/* continue w/a regular variable display */
|
|
if (nl & SCR_ERASE_EOL)
|
|
{
|
|
if (screen_io_enable == 0)
|
|
{
|
|
push_immed(dupon);
|
|
asm_call("tcob_display_erase");
|
|
}
|
|
}
|
|
}
|
|
|
|
while (disp_list)
|
|
{
|
|
sy = disp_list->var;
|
|
|
|
if ((!(sy->defined)) && (sy->litflag == 0))
|
|
{
|
|
yyerror("variable %s not defined,%d", sy->name, sy->litflag);
|
|
}
|
|
|
|
if (screen_io_enable == 0)
|
|
{
|
|
push_immed(dupon);
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_display");
|
|
}
|
|
else
|
|
{
|
|
dspflags = nl;
|
|
if (first)
|
|
{
|
|
first = 0;
|
|
}
|
|
else
|
|
{
|
|
dspflags &= ~2; /* avoid erasing from now on */
|
|
}
|
|
if (disp_list->next != NULL)
|
|
{
|
|
dspflags |= 1; /* allow newline only at the last item */
|
|
}
|
|
push_immed(color); /* walter */
|
|
push_immed(dspflags);
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_display_curses");
|
|
}
|
|
tmp = disp_list;
|
|
disp_list = disp_list->next;
|
|
free(tmp);
|
|
tmp = NULL;
|
|
}
|
|
if (!(nl & SCR_NO_ADVANCING))
|
|
{
|
|
if (screen_io_enable == 0)
|
|
{
|
|
push_immed(dupon);
|
|
asm_call("tcob_newline");
|
|
}
|
|
}
|
|
stabs_line();
|
|
}
|
|
|
|
/*
|
|
* Call the function to set the display or accept position
|
|
*/
|
|
void
|
|
gen_gotoxy_expr()
|
|
{
|
|
stackframe_cnt += 16; /* eliminate the coords expressions */
|
|
asm_call("tcob_goxy_expr");
|
|
}
|
|
|
|
void
|
|
gen_gotox_expr()
|
|
{
|
|
stackframe_cnt += 8; /* eliminate the coord expressions */
|
|
asm_call("tcob_gox_expr");
|
|
}
|
|
|
|
void
|
|
gen_gotoy_expr()
|
|
{
|
|
stackframe_cnt += 8; /* eliminate the coord expressions */
|
|
asm_call("tcob_goy_expr");
|
|
}
|
|
|
|
/* walter
|
|
main sempre 1, o unico caso que e 0 e qdo usa recursividade
|
|
echo 0 - stop literal (forcado) e qdo vem do parse traz valor
|
|
acrescentei color */
|
|
void
|
|
gen_accept(struct sym *sy, int echo, int main, int color)
|
|
{
|
|
struct sym *tmp, *var = sy;
|
|
int not_screen_mask = SCR_ERASE_EOL | SCR_ERASE_EOS | SCR_NO_ADVANCING;
|
|
|
|
if ((echo & not_screen_mask) != echo)
|
|
{ /* determine if the options require curses */
|
|
screen_io_enable = 1;
|
|
HTG_prg_uses_term = 1;
|
|
}
|
|
|
|
|
|
if (var->litflag == 2 || var->litflag == 4)
|
|
{
|
|
var = ((struct vref *) var)->sym;
|
|
if (var->litflag == 2)
|
|
{
|
|
var = ((struct vref *) var)->sym;
|
|
}
|
|
}
|
|
|
|
if (sy->litflag == 4)
|
|
{
|
|
echo |= SCR_IS_REFMOD;
|
|
}
|
|
|
|
if (var->scr)
|
|
{ /* screen or screen-item accept */
|
|
if (main)
|
|
{
|
|
fprintf(o_src, "# Screen Section: %s\n",
|
|
var->name);
|
|
}
|
|
if (var->son == NULL)
|
|
{
|
|
fprintf(o_src, "# Screen Field: %s\n",
|
|
var->name);
|
|
gen_call_scr_process(var);
|
|
}
|
|
else
|
|
{
|
|
for (tmp = var->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
gen_accept(tmp, echo, 0, color);
|
|
}
|
|
}
|
|
if (main)
|
|
asm_call("tcob_accept_screen");
|
|
}
|
|
else
|
|
{
|
|
push_immed(color); /* walter */
|
|
push_immed(echo);
|
|
/* why this? Why not the standard code generating
|
|
function, gen_loaddesc()??? */
|
|
/*fprintf(o_src,"\tmovl\t$c_base%d+%u, %%eax\n",
|
|
pgm_segment,var->descriptor);
|
|
push_eax();*/
|
|
gen_loaddesc2(sy, 1);
|
|
/* this work better with the original symbol (sy),
|
|
because it will be interpreted as a refmod
|
|
or subscripted variable. */
|
|
/* gen_loadloc( var ); */
|
|
gen_loadloc(sy);
|
|
if (screen_io_enable == 0)
|
|
asm_call("tcob_accept_std");
|
|
else
|
|
asm_call("tcob_accept_curses");
|
|
}
|
|
stabs_line();
|
|
}
|
|
|
|
void
|
|
gen_accept_from_chron(struct sym *sy, int date_fmt, int is_yyyy)
|
|
{
|
|
push_immed(is_yyyy);
|
|
push_immed(date_fmt);
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_accept_chron");
|
|
}
|
|
|
|
void
|
|
gen_accept_from_inkey(struct sym *sy)
|
|
{
|
|
gen_loadloc(sy);
|
|
asm_call("tcob_accept_inkey");
|
|
}
|
|
|
|
/* walter */
|
|
void
|
|
gen_accept_from_escapekey(struct sym *sy)
|
|
{
|
|
gen_loadloc(sy);
|
|
asm_call("tcob_accept_escapekey");
|
|
}
|
|
|
|
void
|
|
gen_accept_from_cmdline(struct sym *sy)
|
|
{
|
|
|
|
struct sym *sy1;
|
|
|
|
gen_loadvar(sy);
|
|
/*
|
|
fprintf(o_src,"\tmovl\t12(%%ebp), %%eax\n");
|
|
push_eax();
|
|
fprintf(o_src,"\tmovl\t8(%%ebp), %%eax\n");
|
|
push_eax();
|
|
*/
|
|
asm_call("tcob_accept_cmd_line");
|
|
|
|
/* Set RETURN-CODE with the value returned by
|
|
* the "accept_cmd_line" function, which is stored
|
|
* in register %eax
|
|
*/
|
|
|
|
if ((sy1 = lookup(SVAR_RETURN_CODE, SYTB_VAR)) != NULL)
|
|
{
|
|
if (sy1->sec_no == SEC_STACK)
|
|
{
|
|
fprintf(o_src, "\tleal\t-%d(%%ebp), %%edx\n", sy1->location);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "\tleal\tw_base%d+%d, %%edx\n",
|
|
pgm_segment, sy1->location);
|
|
}
|
|
fprintf(o_src, "\tmovl\t%%eax, (%%edx)\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_accept_env_var(struct sym *sy, struct lit *v)
|
|
{
|
|
|
|
struct sym *sy1, *sy2;
|
|
|
|
sy1 = (struct sym *) v;
|
|
|
|
/* gen_loadloc( sy ); */
|
|
/* fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",sy->descriptor); */
|
|
/* push_eax(); */
|
|
|
|
gen_loadloc(sy1);
|
|
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_accept_env_var");
|
|
|
|
/* Set RETURN-CODE with the value returned by
|
|
* the "accept_env_var" function, which is stored
|
|
* in register %eax
|
|
*/
|
|
|
|
if ((sy2 = lookup(SVAR_RETURN_CODE, SYTB_VAR)) != NULL)
|
|
{
|
|
if (sy2->sec_no == SEC_STACK)
|
|
{
|
|
fprintf(o_src, "\tleal\t-%d(%%ebp), %%edx\n", sy2->location);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "\tleal\tw_base%d+%d, %%edx\n",
|
|
pgm_segment, sy2->location);
|
|
}
|
|
fprintf(o_src, "\tmovl\t%%eax, (%%edx)\n");
|
|
}
|
|
|
|
/* void save_literal( struct lit *v, int type ) */
|
|
/* currency_symbol = $<lval>4->name[0]; */
|
|
/* char *name; */ /* name (value) of literal */
|
|
/* gen_loadloc( sy ); */
|
|
/* gen_loaddesc( sy ); */
|
|
|
|
}
|
|
|
|
/******** structure allocation for perform info(s) ***********/
|
|
|
|
struct perf_info *
|
|
create_perf_info(struct sym *sy1, struct sym *sy2, unsigned long lj, unsigned long le)
|
|
{
|
|
struct perf_info *rf;
|
|
rf = malloc(sizeof (struct perf_info));
|
|
rf->pname1 = sy1;
|
|
rf->pname2 = sy2;
|
|
rf->ljmp = lj;
|
|
rf->lend = le;
|
|
return rf;
|
|
}
|
|
|
|
struct perform_info *
|
|
create_perform_info(void)
|
|
{
|
|
struct perform_info *rf;
|
|
rf = malloc(sizeof (struct perform_info));
|
|
rf->pf[0] = NULL;
|
|
rf->pf[1] = NULL;
|
|
rf->pf[2] = NULL;
|
|
rf->pf[3] = NULL;
|
|
rf->pf[4] = NULL;
|
|
rf->pf[5] = NULL;
|
|
return rf;
|
|
}
|
|
|
|
char *
|
|
check_perform_variables(struct sym *sy1, struct perform_info *pi1)
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
j = 0;
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
if (pi1->pf[i] != NULL)
|
|
{
|
|
j++;
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace: check_perform_variables: var(%d:%d) '%s'\n",
|
|
i, j, pi1->pf[i]->pname2->name);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < j; i++)
|
|
{
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace: check_perform_variables: var1='%s' var2(%d)='%s'\n",
|
|
sy1->name,
|
|
i, pi1->pf[i]->pname2->name);
|
|
#endif
|
|
#endif
|
|
if (strcmp(sy1->name, pi1->pf[i]->pname2->name) == 0)
|
|
{
|
|
return sy1->name;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < j; i++)
|
|
{
|
|
for (k = i + 1; k < j; k++)
|
|
{
|
|
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace: check_perform_variables: var1(%d)='%s' var2(%d)='%s'\n",
|
|
i, pi1->pf[i]->pname2->name,
|
|
k, pi1->pf[k]->pname2->name);
|
|
#endif
|
|
#endif
|
|
if (strcmp(pi1->pf[i]->pname2->name, pi1->pf[k]->pname2->name) == 0)
|
|
{
|
|
return pi1->pf[i]->pname2->name;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/******** structure allocation for math verbs variables ***********/
|
|
|
|
struct expr *
|
|
create_expr(char op, struct expr *left, struct expr *right)
|
|
{
|
|
struct expr *e = malloc(sizeof (struct expr));
|
|
struct list *list = (struct list *) malloc(sizeof (struct list));
|
|
e->litflag = 5;
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#create_expr: [0x%x] %c ", (int) e, op);
|
|
if (left->litflag < 2)
|
|
{
|
|
fprintf(o_src, "%s ", ((struct sym *) left)->name);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "0x%x ", (int) left);
|
|
}
|
|
if (right->litflag < 2)
|
|
{
|
|
fprintf(o_src, "%s\n", ((struct sym *) right)->name);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "0x%x\n", (int) right);
|
|
}
|
|
#endif
|
|
e->op = op;
|
|
e->left = left;
|
|
e->right = right;
|
|
expr_list = list;
|
|
list->next = NULL;
|
|
list->var = e;
|
|
return e;
|
|
}
|
|
|
|
void
|
|
free_expr(struct expr *e)
|
|
{
|
|
if ((e != NULL) && (e->litflag == 5))
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#free_expr: %c (%d,%d) ", e->op,
|
|
e->left->litflag, e->right->litflag);
|
|
if (e->left->litflag < 2)
|
|
{
|
|
fprintf(o_src, "%s ", ((struct sym *) e->left)->name);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "0x%x ", (int) e->left);
|
|
}
|
|
if (e->right->litflag < 2)
|
|
{
|
|
fprintf(o_src, "%s\n", ((struct sym *) e->right)->name);
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "0x%x\n", (int) e->right);
|
|
}
|
|
#endif
|
|
free_expr(e->right);
|
|
free_expr(e->left);
|
|
free(e);
|
|
}
|
|
e = NULL;
|
|
}
|
|
|
|
void
|
|
free_expr_list()
|
|
{
|
|
struct list *list;
|
|
struct expr *e;
|
|
for (list = expr_list; list != NULL; list = list->next)
|
|
{
|
|
e = (struct expr *) list->var;
|
|
free_expr(e);
|
|
}
|
|
expr_list = NULL;
|
|
}
|
|
|
|
struct math_var *
|
|
create_mathvar_info(struct math_var *mv, struct sym *sy, unsigned int opt)
|
|
{
|
|
|
|
struct math_var *rf, *tmp1, *tmp2;
|
|
|
|
/* if (is_numeric_sy(sy) == 0) {
|
|
yyerror("invalid (non numeric) variable or literal \'%s\' used in arithmetic verb", sy->name);
|
|
return mv;
|
|
}
|
|
*/
|
|
rf = malloc(sizeof (struct math_var));
|
|
rf->sname = sy;
|
|
/* rf->rounded = opt; */
|
|
rf->opts = opt;
|
|
rf->next = NULL;
|
|
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace : create_mathvar_info 0: sy->name=%s;\n",
|
|
sy->name);
|
|
fprintf(stderr,
|
|
"debug trace : create_mathvar_info 1: rf->sname->name=%s;\n",
|
|
rf->sname->name);
|
|
#endif
|
|
#endif
|
|
|
|
if (mv == NULL)
|
|
{
|
|
tmp2 = rf;
|
|
tmp1 = rf;
|
|
}
|
|
else
|
|
{
|
|
tmp1 = mv;
|
|
tmp2 = mv;
|
|
while (tmp1->next != NULL)
|
|
{
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace : create_mathvar_info 2: tmp1->sname->name=%s;\n",
|
|
tmp1->sname->name);
|
|
#endif
|
|
#endif
|
|
tmp1 = tmp1->next;
|
|
}
|
|
tmp1->next = rf;
|
|
}
|
|
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace : create_mathvar_info 3: tmp1->sname->name=%s;\n",
|
|
tmp1->sname->name);
|
|
#endif
|
|
#endif
|
|
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
tmp1 = tmp2;
|
|
while (tmp1 != NULL)
|
|
{
|
|
fprintf(stderr,
|
|
"debug trace : create_mathvar_info 4: tmp1->sname->name=%s;\n",
|
|
tmp1->sname->name);
|
|
tmp1 = tmp1->next;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return tmp2;
|
|
}
|
|
|
|
void
|
|
delete_mathvar_info(struct math_var *mv)
|
|
{
|
|
|
|
struct math_var *tmp1, *tmp2;
|
|
|
|
tmp1 = mv;
|
|
while (tmp1 != NULL)
|
|
{
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(stderr,
|
|
"debug trace : delete_mathvar_info 1: tmp1->sname->name=%s;\n",
|
|
tmp1->sname->name);
|
|
#endif
|
|
#endif
|
|
tmp2 = tmp1->next;
|
|
tmp1->next = NULL;
|
|
tmp1->sname = NULL;
|
|
free(tmp1);
|
|
tmp1 = tmp2;
|
|
}
|
|
}
|
|
|
|
struct invalid_key_element *
|
|
gen_before_invalid_key()
|
|
{
|
|
struct invalid_key_element *p = malloc(sizeof (struct invalid_key_element));
|
|
p->lbl1 = loc_label++;
|
|
p->lbl2 = loc_label++;
|
|
p->lbl3 = loc_label++;
|
|
gen_jmplabel(p->lbl1);
|
|
gen_dstlabel(p->lbl2);
|
|
return p;
|
|
}
|
|
|
|
struct invalid_key_element *
|
|
gen_after_invalid_key(struct invalid_key_element *p)
|
|
{
|
|
gen_jmplabel(p->lbl3);
|
|
return p;
|
|
}
|
|
|
|
struct invalid_keys *
|
|
gen_invalid_keys(struct invalid_key_element *p1, struct invalid_key_element *p2)
|
|
{
|
|
struct invalid_keys *p = malloc(sizeof (struct invalid_keys));
|
|
p->invalid_key = p1;
|
|
p->not_invalid_key = p2;
|
|
if (p1) gen_dstlabel(p1->lbl1);
|
|
if (p2) gen_dstlabel(p2->lbl1);
|
|
return p;
|
|
}
|
|
|
|
/******** functions to generate math verbs ***********/
|
|
|
|
void
|
|
gen_add(struct sym *s1, struct sym *s2, int rnd)
|
|
{
|
|
push_immed(rnd);
|
|
gen_loadvar(s2);
|
|
gen_loadvar(s1);
|
|
asm_call("tcob_add");
|
|
}
|
|
|
|
void
|
|
gen_subtract(struct sym *s1, struct sym *s2, int rnd)
|
|
{
|
|
push_immed(rnd);
|
|
gen_loadvar(s2);
|
|
gen_loadvar(s1);
|
|
asm_call("tcob_subtract");
|
|
}
|
|
|
|
void
|
|
gen_multiply(struct sym *s1, struct sym *s2, struct sym *s3, int rnd)
|
|
{
|
|
push_immed(rnd);
|
|
gen_loadvar(s3);
|
|
gen_loadvar(s2);
|
|
gen_loadvar(s1);
|
|
asm_call("tcob_multiply");
|
|
}
|
|
|
|
void
|
|
gen_compute1(struct math_var *vl1, struct sym *sy1)
|
|
{
|
|
push_expr(sy1);
|
|
while (vl1->next != NULL)
|
|
{
|
|
assign_expr(vl1->sname, vl1->opts, '0');
|
|
vl1 = vl1->next;
|
|
}
|
|
assign_expr(vl1->sname, vl1->opts, '1');
|
|
|
|
}
|
|
|
|
void
|
|
gen_compute2(struct math_var *vl1, struct sym *sy1, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
|
|
gen_dstlabel(v1->lbl4); /* generate bypass jump label */
|
|
push_expr(sy1);
|
|
while (vl1->next != NULL)
|
|
{
|
|
assign_expr(vl1->sname, opts, '0');
|
|
math_on_size_error3(v1);
|
|
vl1 = vl1->next;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_add1(struct math_var *vl0, struct math_var *vl2, struct math_ose *v1)
|
|
{
|
|
struct math_var *vl1;
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
while (vl2 != NULL)
|
|
{
|
|
push_expr(vl2->sname);
|
|
vl1 = vl0;
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
add_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
math_on_size_error5(v1);
|
|
|
|
}
|
|
|
|
void
|
|
gen_add2(struct math_var *vl1, struct math_var *vl2, struct sym *sy1, struct math_ose *v1)
|
|
{
|
|
int i = 0;
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4); /* generate bypass jump label */
|
|
}
|
|
if (sy1 != NULL)
|
|
{
|
|
push_expr(sy1);
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
add_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
push_expr(vl1->sname);
|
|
vl1 = vl1->next;
|
|
i = 1;
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
add_expr();
|
|
vl1 = vl1->next;
|
|
i++;
|
|
}
|
|
if (i < 2)
|
|
{
|
|
yyerror("At least 2 variables and/or numeric literals required in ADD statement");
|
|
}
|
|
}
|
|
while (vl2->next != NULL)
|
|
{
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '0');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_add3(struct math_var *vl0, struct math_var *vl2, struct math_ose *v1)
|
|
{
|
|
struct math_var *vl1;
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
while (vl2 != NULL)
|
|
{
|
|
push_expr(vl2->sname);
|
|
vl1 = vl0;
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
add_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
gen_subtract1(struct math_var *vl0, struct math_var *vl2, struct math_ose *v1)
|
|
{
|
|
struct math_var *vl1;
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
while (vl2 != NULL)
|
|
{
|
|
push_expr(vl2->sname);
|
|
vl1 = vl0;
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
subtract_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_subtract2(struct math_var *vl1, struct math_var *vl2, struct sym *sy1, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
push_expr(sy1);
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
subtract_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
while (vl2->next != NULL)
|
|
{
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '0');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_subtract3(struct math_var *vl0, struct math_var *vl2, struct math_ose *v1)
|
|
{
|
|
struct math_var *vl1;
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
while (vl2 != NULL)
|
|
{
|
|
push_expr(vl2->sname);
|
|
vl1 = vl0;
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
subtract_expr();
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl2->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl2->opts;
|
|
}
|
|
assign_expr(vl2->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl2 = vl2->next;
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_multiply1(struct math_var *vl1, struct sym *sy1, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
while (vl1->next != NULL)
|
|
{
|
|
push_expr(sy1);
|
|
push_expr(vl1->sname);
|
|
multiply_expr();
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl1 = vl1->next;
|
|
}
|
|
push_expr(sy1);
|
|
push_expr(vl1->sname);
|
|
multiply_expr();
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_multiply2(struct math_var *vl1, struct sym *sy1, struct sym *sy2, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
push_expr(sy1);
|
|
push_expr(sy2);
|
|
multiply_expr();
|
|
while (vl1->next != NULL)
|
|
{
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '0');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_divide1(struct math_var *vl1, struct sym *sy1, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
while (vl1 != NULL)
|
|
{
|
|
push_expr(vl1->sname);
|
|
push_expr(sy1);
|
|
divide_expr();
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl1 = vl1->next;
|
|
}
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_divide2(struct math_var *vl1, struct sym *sy1, struct sym *sy2, struct math_ose *v1)
|
|
{
|
|
/* option flags: 1=rounded, 2=on_size_error */
|
|
int opts;
|
|
|
|
/* ON SIZE ERROR option only */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
push_expr(sy1);
|
|
push_expr(sy2);
|
|
divide_expr();
|
|
while (vl1->next != NULL)
|
|
{
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '0');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
vl1 = vl1->next;
|
|
}
|
|
if (v1 != NULL)
|
|
{
|
|
opts = vl1->opts | MATH_OPT_ON_SIZE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
opts = vl1->opts;
|
|
}
|
|
assign_expr(vl1->sname, opts, '1');
|
|
/* ON SIZE ERROR option only */
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
void
|
|
gen_divide4(struct sym *s1, struct sym *s2, struct sym *s3, struct sym *s4, int rnd, struct math_ose *v1)
|
|
{
|
|
|
|
/* [NOT]ON SIZE ERROR option */
|
|
if (v1 != NULL)
|
|
{
|
|
/* generate bypass jump */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
push_immed(rnd);
|
|
gen_loadvar(s4);
|
|
gen_loadvar(s3);
|
|
gen_loadvar(s2);
|
|
gen_loadvar(s1);
|
|
asm_call("tcob_divide1");
|
|
math_on_size_error3(v1);
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
/******** functions for subscripted var manipulation ***********/
|
|
struct vref *
|
|
create_subscripted_var(struct sym * sy, struct vref *subs)
|
|
{
|
|
struct vref *ref;
|
|
ref = malloc(sizeof (struct vref));
|
|
ref->litflag = 2;
|
|
ref->sym = sy;
|
|
ref->next = subs;
|
|
return ref;
|
|
}
|
|
|
|
struct vref *
|
|
create_subscript(struct sym *sy)
|
|
{
|
|
struct vref *ref;
|
|
ref = malloc(sizeof (struct vref));
|
|
ref->litflag = ','; /* the end of subscript is here */
|
|
ref->sym = sy; /* this is the actual variable */
|
|
ref->next = NULL;
|
|
return ref;
|
|
}
|
|
|
|
struct vref *
|
|
add_subscript_item(struct vref *subs, char op, struct sym *item)
|
|
{
|
|
struct vref *ref, *tmp;
|
|
ref = malloc(sizeof (struct vref));
|
|
tmp = subs;
|
|
while (tmp->next) tmp = tmp->next;
|
|
tmp->next = ref;
|
|
ref->litflag = ',';
|
|
ref->sym = item;
|
|
ref->next = NULL;
|
|
tmp->litflag = op;
|
|
return subs;
|
|
}
|
|
|
|
struct vref *
|
|
add_subscript(struct vref *ref, struct vref *subs)
|
|
{
|
|
struct vref *tmp;
|
|
tmp = subs;
|
|
while (tmp->next) tmp = tmp->next;
|
|
tmp->next = ref;
|
|
return subs;
|
|
}
|
|
|
|
int
|
|
check_subscripts(struct sym *subs)
|
|
{
|
|
struct vref *ref;
|
|
struct sym *sy;
|
|
sy = ((struct vref *) subs)->sym;
|
|
for (ref = (struct vref *) subs; ref; ref = ref->next)
|
|
{
|
|
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#check_subscripts: symbol: %s, op: '%c'\n",
|
|
((struct sym *) ref->sym)->name,
|
|
ref->litflag == 2 ? 2 : ref->litflag);
|
|
#endif
|
|
|
|
if (ref->litflag == ',')
|
|
{
|
|
while (sy && !sy->occurs_flg)
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#check_subscripts: symbol: %s\n",
|
|
sy->name);
|
|
#endif
|
|
sy = sy->parent;
|
|
}
|
|
if (!sy)
|
|
{
|
|
hterror(102, 4, "check_subscripts: no parent found");
|
|
return 0; /* excess subscripts, error */
|
|
}
|
|
sy = sy->parent;
|
|
}
|
|
}
|
|
while (sy && !sy->occurs_flg) /* any other subscripts needed ? */
|
|
sy = sy->parent;
|
|
return (sy == NULL) ? 1 : 0;
|
|
}
|
|
|
|
void
|
|
create_occurs_info(int min, int max, struct sym *depend)
|
|
{
|
|
curr_field->occurs = (struct occurs *) malloc(sizeof (struct occurs));
|
|
curr_field->occurs->min = min;
|
|
curr_field->occurs->max = max;
|
|
curr_field->occurs->depend = depend;
|
|
curr_field->times = max;
|
|
curr_field->occurs_flg++;
|
|
}
|
|
|
|
/******** functions for refmoded var manipulation ***********/
|
|
struct refmod *
|
|
create_refmoded_var(struct sym * sy, struct sym *syoff, struct sym *sylen)
|
|
{
|
|
struct refmod *ref;
|
|
ref = malloc(sizeof (struct refmod));
|
|
ref->litflag = 4;
|
|
ref->sym = sy;
|
|
ref->off = syoff;
|
|
ref->len = sylen;
|
|
ref->slot = refmod_slots++;
|
|
return ref;
|
|
}
|
|
|
|
int
|
|
check_refmods(struct sym *var)
|
|
{
|
|
struct refmod *ref = (struct refmod *) var;
|
|
struct sym *sy = ref->sym;
|
|
|
|
if (sy->litflag == 2) sy = ((struct vref *) sy)->sym;
|
|
|
|
return (sy == NULL) ? 1 : 0;
|
|
}
|
|
|
|
struct sym *
|
|
get_variable_item(struct sym *sy)
|
|
{
|
|
struct sym *son, *item;
|
|
if (sy->litflag != 0)
|
|
return NULL;
|
|
if (sy->occurs != NULL)
|
|
return sy;
|
|
for (son = sy->son; son != NULL; son = son->brother)
|
|
{
|
|
if ((item = get_variable_item(son)))
|
|
return item;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
adjust_desc_length(struct sym *sy)
|
|
{
|
|
int stack_save = stackframe_cnt;
|
|
struct sym *item;
|
|
stackframe_cnt = 0;
|
|
item = get_variable_item(sy);
|
|
/* push_immed(0); */
|
|
gen_temp_storage(sizeof (struct fld_desc));
|
|
gen_loaddesc1(item, 0);
|
|
gen_loaddesc1(sy, 0);
|
|
push_immed(item->occurs->max);
|
|
push_immed(item->occurs->min);
|
|
gen_loadvar(item->occurs->depend);
|
|
asm_call("tcob_adjust_length");
|
|
stackframe_cnt = stack_save;
|
|
need_desc_length_cleanup = 1;
|
|
}
|
|
|
|
void
|
|
gen_loadloc(struct sym *sy_p)
|
|
{
|
|
loadloc_to_eax(sy_p);
|
|
push_eax();
|
|
}
|
|
|
|
void
|
|
gen_loaddesc(struct sym *sy)
|
|
{
|
|
gen_loaddesc1(sy, 1);
|
|
}
|
|
|
|
void
|
|
gen_loadvar(struct sym *sy)
|
|
{
|
|
struct sym *var;
|
|
if (sy == NULL)
|
|
{
|
|
push_immed(0);
|
|
}
|
|
else
|
|
{
|
|
var = sy;
|
|
if (var->litflag == 2 || var->litflag == 4)
|
|
{
|
|
var = ((struct vref *) var)->sym;
|
|
if (var->litflag == 2)
|
|
var = ((struct vref *) var)->sym;
|
|
}
|
|
if (!HTG_libcob)
|
|
gen_loadloc(sy);
|
|
gen_loaddesc(sy);
|
|
}
|
|
}
|
|
|
|
int
|
|
is_numeric_sy(struct sym *sy)
|
|
{
|
|
char type;
|
|
if (sy->litflag == 2)
|
|
{ /* subscripted ? */
|
|
sy = ((struct vref *) sy)->sym;
|
|
}
|
|
type = sy->type;
|
|
if ((type == DTYPE_DISPLAY) || (type == DTYPE_BININT)
|
|
|| (type == DTYPE_PACKED) || (type == DTYPE_FLOAT))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
is_numeric_dest_sy(struct sym *sy)
|
|
{
|
|
char type;
|
|
if (sy->litflag == 2)
|
|
{ /* subscripted ? */
|
|
sy = ((struct vref *) sy)->sym;
|
|
}
|
|
type = sy->type;
|
|
if ((type == DTYPE_DISPLAY)
|
|
|| (type == DTYPE_BININT)
|
|
|| (type == DTYPE_PACKED)
|
|
|| (type == DTYPE_FLOAT)
|
|
|| (type == DTYPE_EDITED))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
gen_class_check(struct sym *sy, int class)
|
|
{
|
|
int invert = 0;
|
|
class &= ~(COND_UNARY | COND_CLASS);
|
|
if (class & 4)
|
|
{ /* was it inverted (NOT) ? */
|
|
class ^= 7;
|
|
invert++;
|
|
}
|
|
if (class == CLASS_NUMERIC)
|
|
{
|
|
/*if (!sy || is_numeric_sy(sy)) {
|
|
*/
|
|
if (sy) /* don't save already pushed variable */
|
|
gen_loadvar(sy);
|
|
else
|
|
stackframe_cnt += 8;
|
|
asm_call("tcob_check_numeric");
|
|
fprintf(o_src, "\tand\t%%eax,%%eax\n");
|
|
/*}
|
|
else {
|
|
yyerror("invalid NUMERIC class check");
|
|
}*/
|
|
}
|
|
else
|
|
{
|
|
/* from now on, only alphabetic tests are allowed */
|
|
/*if (is_numeric_sy(sy)) {
|
|
yyerror("invalid ALPHABETIC class check");
|
|
}*/
|
|
gen_loadvar(sy);
|
|
switch (class)
|
|
{
|
|
case CLASS_ALPHABETIC:
|
|
asm_call("tcob_check_alphabetic");
|
|
break;
|
|
case CLASS_ALPHABETIC_UPPER:
|
|
asm_call("tcob_check_upper");
|
|
break;
|
|
case CLASS_ALPHABETIC_LOWER:
|
|
asm_call("tcob_check_lower");
|
|
break;
|
|
default:
|
|
yyerror("unknown class condition");
|
|
break;
|
|
}
|
|
fprintf(o_src, "\tand\t%%eax,%%eax\n");
|
|
}
|
|
if (invert)
|
|
gen_not();
|
|
}
|
|
|
|
void
|
|
gen_inspect(struct sym *var, void *list, int operation)
|
|
{
|
|
/*struct inspect_before_after *ba,*ba1;*/
|
|
struct tallying_list *tl, *tl1;
|
|
struct tallying_for_list *tfl, *tfl1;
|
|
struct replacing_list *rl, *rl1;
|
|
struct replacing_by_list *rbl, *rbl1;
|
|
struct converting_struct *cv;
|
|
|
|
if (!operation)
|
|
{
|
|
if (!list) return;
|
|
fprintf(o_src, "# INSPECT TALLYING %s\n", var->name);
|
|
gen_loadvar((struct sym *) NULL);
|
|
tl = (struct tallying_list *) list;
|
|
while (tl)
|
|
{
|
|
tfl = tl->tflist;
|
|
push_immed(0);
|
|
while (tfl)
|
|
{
|
|
gen_loadvar(tfl->before_after->after);
|
|
gen_loadvar(tfl->before_after->before);
|
|
if (tfl->options != INSPECT_CHARACTERS)
|
|
{
|
|
gen_loadvar(tfl->forvar);
|
|
}
|
|
push_immed(tfl->options);
|
|
free(tfl->before_after);
|
|
tfl1 = tfl;
|
|
tfl = tfl->next;
|
|
free(tfl1);
|
|
}
|
|
gen_loadvar(tl->count);
|
|
tl1 = tl;
|
|
tl = tl->next;
|
|
free(tl1);
|
|
tl1 = NULL;
|
|
}
|
|
gen_loadvar(var);
|
|
asm_call("tcob_inspect_tallying");
|
|
}
|
|
else if (operation == 1)
|
|
{
|
|
if (!list) return;
|
|
fprintf(o_src, "# INSPECT REPLACING %s\n", var->name);
|
|
rl = (struct replacing_list *) list;
|
|
push_immed(0);
|
|
while (rl)
|
|
{
|
|
if (rl->options == INSPECT_CHARACTERS)
|
|
{
|
|
gen_loadvar(rl->before_after->after);
|
|
gen_loadvar(rl->before_after->before);
|
|
gen_loadvar(rl->byvar);
|
|
push_immed(rl->options);
|
|
}
|
|
else
|
|
{
|
|
rbl = rl->replbylist;
|
|
while (rbl)
|
|
{
|
|
gen_loadvar(rbl->before_after->after);
|
|
gen_loadvar(rbl->before_after->before);
|
|
gen_loadvar(rbl->byvar);
|
|
gen_loadvar(rbl->replvar);
|
|
free(rbl->before_after);
|
|
rbl1 = rbl;
|
|
rbl = rbl->next;
|
|
free(rbl1);
|
|
push_immed(rl->options);
|
|
}
|
|
}
|
|
rl1 = rl;
|
|
rl = rl->next;
|
|
free(rl1);
|
|
rl1 = NULL;
|
|
}
|
|
gen_loadvar(var);
|
|
asm_call("tcob_inspect_replacing");
|
|
}
|
|
else
|
|
{
|
|
fprintf(o_src, "# INSPECT CONVERTING %s\n", var->name);
|
|
cv = (struct converting_struct *) list;
|
|
gen_loadvar(cv->before_after->after);
|
|
gen_loadvar(cv->before_after->before);
|
|
gen_loadvar(cv->tovar);
|
|
gen_loadvar(cv->fromvar);
|
|
gen_loadvar(var);
|
|
asm_call("tcob_inspect_converting");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_tcob_proto1(struct sym *sy)
|
|
{
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_proto1");
|
|
}
|
|
|
|
void
|
|
gen_tcob_proto2(struct sym *sy1, struct sym *sy2)
|
|
{
|
|
gen_loadvar(sy2);
|
|
gen_loadvar(sy1);
|
|
asm_call("tcob_proto2");
|
|
}
|
|
|
|
void
|
|
gen_moves(struct sym *sy_src, struct gvar_list *gsylst)
|
|
{
|
|
struct gvar_list *sy_dst;
|
|
|
|
for (sy_dst = gsylst; sy_dst->next != NULL; sy_dst = sy_dst->next)
|
|
{
|
|
gen_move(sy_src, sy_dst->u.sym);
|
|
}
|
|
gen_move(sy_src, sy_dst->u.sym);
|
|
}
|
|
|
|
void
|
|
gen_move(struct sym *sy_src, struct sym *sy_dst)
|
|
{
|
|
long tmplabel = 0;
|
|
struct sym *var;
|
|
|
|
#ifdef DEBUG_COMPILER
|
|
{
|
|
struct sym *esys = sy_src, *esyd = sy_dst;
|
|
if (esys->litflag == 4)
|
|
esys = ((struct refmod *) esys)->sym;
|
|
if (esyd->litflag == 4)
|
|
esyd = ((struct refmod *) esyd)->sym;
|
|
fprintf(o_src, "# MOVE %s --> ", sch_convert(esys->name));
|
|
fprintf(o_src, " %s\n", sch_convert(esyd->name));
|
|
}
|
|
#endif
|
|
/* Make sure BLANK test is done on a sym struct, and not a vref struct */
|
|
var = sy_dst;
|
|
if (var->litflag == 2 || var->litflag == 4)
|
|
{
|
|
var = ((struct vref *) var)->sym;
|
|
if (var->litflag == 2)
|
|
var = ((struct vref *) var)->sym;
|
|
}
|
|
/* A blank when zero field is treated here instead of the RTS */
|
|
if (var->flags.blank)
|
|
{
|
|
tmplabel = loc_label++;
|
|
gen_compare(sy_src, EQUAL, (struct sym *) spe_lit_ZE);
|
|
fprintf(o_src, "\tjnz\t.L%ld\n", tmplabel);
|
|
gen_loadvar(sy_dst);
|
|
gen_loadvar((struct sym *) spe_lit_SP);
|
|
asm_call("tcob_move_x_x");
|
|
gen_jmplabel(tmplabel + 1);
|
|
fprintf(o_src, ".L%ld:\n", tmplabel);
|
|
}
|
|
/* default move */
|
|
gen_loadvar(sy_dst);
|
|
gen_loadvar(sy_src);
|
|
/* an initial value of a literal X field into an numeric edited field
|
|
should move straight instead of going thru an edition */
|
|
/* if (sy_src->type == DTYPE_ALPHANUMERIC && sy_dst->type == DTYPE_EDITED) {
|
|
asm_call("tcob_move_x_x");
|
|
}
|
|
else { */
|
|
RTL_CALL("move");
|
|
/* } */
|
|
#ifdef TODO
|
|
if (sy_src->type == DTYPE_ALPHANUMERIC && sy_dst->type == DTYPE_EDITED)
|
|
{
|
|
asm_call("tcob_move_x_x");
|
|
}
|
|
else
|
|
{
|
|
asm_call("tcob_move");
|
|
}
|
|
#endif
|
|
if (tmplabel)
|
|
{
|
|
tmplabel = loc_label++;
|
|
fprintf(o_src, ".L%ld:\n", tmplabel);
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_movelength(struct sym *sy1, struct sym *sy2)
|
|
{
|
|
if (sy1->litflag == 1)
|
|
{
|
|
push_immed(((struct lit *) sy1)->len);
|
|
}
|
|
else
|
|
{
|
|
push_immed(sy1->len);
|
|
}
|
|
gen_loadvar(sy2);
|
|
asm_call("tcob_assign_int");
|
|
}
|
|
|
|
void
|
|
gen_move_init(struct sym *sy_src, struct sym *sy_dst)
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
{
|
|
struct sym *esys = sy_src, *esyd = sy_dst;
|
|
fprintf(o_src, "# MOVE_INIT %s --> ", sch_convert(esys->name));
|
|
fprintf(o_src, " %s\n", sch_convert(esyd->name));
|
|
}
|
|
#endif
|
|
/* default move */
|
|
gen_loadvar(sy_dst);
|
|
gen_loadvar(sy_src);
|
|
/* an initial value of a literal X field into an numeric edited field
|
|
should move straight instead of going thru an edition */
|
|
if (sy_src->type == DTYPE_ALPHANUMERIC && sy_dst->type == DTYPE_EDITED)
|
|
{
|
|
asm_call("tcob_move_x_x");
|
|
}
|
|
else
|
|
{
|
|
RTL_CALL("move");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_movecorr(struct sym *sy1, struct sym *sy2)
|
|
{
|
|
struct sym *t1, *t2;
|
|
if (sy1->litflag || sy2->litflag)
|
|
{
|
|
yyerror("sorry we don't handle this case yet!");
|
|
return;
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# MOVE CORR %s --> %s\n", sy1->name, sy2->name);
|
|
#endif
|
|
t1 = sy1->son;
|
|
/* repeat for all sons of sy1 */
|
|
while (t1 != NULL)
|
|
{
|
|
if (!t1->redefines && t1->times == 1)
|
|
{
|
|
t2 = sy2->son;
|
|
/* repeat for all sons of sy2 */
|
|
while (t2 != NULL)
|
|
{
|
|
if (!t2->redefines && t2->times == 1)
|
|
{
|
|
if (strcmp(t1->name, t2->name) == 0)
|
|
{
|
|
if ((t1->type != DTYPE_GROUP)
|
|
|| (t2->type != DTYPE_GROUP))
|
|
{
|
|
gen_move(t1, t2);
|
|
}
|
|
else
|
|
{
|
|
gen_movecorr(t1, t2);
|
|
}
|
|
}
|
|
}
|
|
t2 = t2->brother;
|
|
}
|
|
}
|
|
t1 = t1->brother;
|
|
}
|
|
}
|
|
|
|
struct sym *
|
|
define_label(struct sym *lab, int lab_type,
|
|
struct sym *parent, int parent_type)
|
|
{
|
|
|
|
struct sym *tlab = lab;
|
|
struct lit *tlit;
|
|
struct sym *tparent;
|
|
|
|
if (parent == NULL)
|
|
{
|
|
tparent = curr_section;
|
|
}
|
|
else
|
|
{
|
|
tparent = parent;
|
|
}
|
|
if (lab_type == 1)
|
|
{
|
|
tlit = (struct lit *) lab;
|
|
tlab = install(tlit->name, SYTB_LAB, 0);
|
|
}
|
|
else
|
|
{
|
|
tlab = lab;
|
|
}
|
|
|
|
if (tlab->defined == 0)
|
|
{
|
|
tlab->defined = 2;
|
|
tlab->parent = tparent;
|
|
}
|
|
else
|
|
{
|
|
if (parent_type == 1)
|
|
{
|
|
tlit = (struct lit *) parent;
|
|
tlab = install(tlit->name, SYTB_LAB, 0);
|
|
}
|
|
if ((tlab = lookup_label(tlab, tparent)) == NULL)
|
|
{
|
|
tlab = install(tlab->name, SYTB_LAB, 2);
|
|
tlab->defined = 2;
|
|
tlab->parent = tparent;
|
|
}
|
|
}
|
|
return tlab;
|
|
}
|
|
|
|
void
|
|
gen_addcorr(struct sym *sy1, struct sym *sy2, int rnd)
|
|
{
|
|
struct sym *t1, *t2;
|
|
if (sy1->litflag || sy2->litflag)
|
|
{
|
|
yyerror("sorry we don't handle this case yet!");
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# ADD CORR %s --> %s\n", sy1->name, sy2->name);
|
|
#endif
|
|
t1 = sy1->son;
|
|
/* repeat for all sons of sy1 */
|
|
while (t1 != NULL)
|
|
{
|
|
if (!t1->redefines && t1->times == 1)
|
|
{
|
|
t2 = sy2->son;
|
|
/* repeat for all sons of sy2 */
|
|
while (t2 != NULL)
|
|
{
|
|
if (!t2->redefines && t2->times == 1)
|
|
{
|
|
if (strcmp(t1->name, t2->name) == 0)
|
|
{
|
|
if ((t1->type != DTYPE_GROUP)
|
|
&& (t2->type != DTYPE_GROUP))
|
|
{
|
|
gen_add(t1, t2, rnd);
|
|
}
|
|
else
|
|
{
|
|
gen_addcorr(t1, t2, rnd);
|
|
}
|
|
}
|
|
}
|
|
t2 = t2->brother;
|
|
}
|
|
}
|
|
t1 = t1->brother;
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_addcorr1(struct math_var *mv1, struct math_var *mv2, int rnd, struct math_ose
|
|
*v1)
|
|
{
|
|
struct sym *sy1, *sy2;
|
|
struct sym *t1, *t2;
|
|
struct math_var *tmv1, *tmv2;
|
|
static int addcorr_level = 0;
|
|
|
|
if (mv1->sname->litflag || mv2->sname->litflag)
|
|
{
|
|
yyerror("sorry we don't handle this case yet!");
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# ADD CORR %s --> %s, lv %d\n",
|
|
mv1->sname->name, mv2->sname->name, addcorr_level);
|
|
#endif
|
|
/* ON SIZE ERROR option only */
|
|
if (addcorr_level == 0 && v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
addcorr_level++;
|
|
sy1 = mv1->sname;
|
|
sy2 = mv2->sname;
|
|
t1 = sy1->son;
|
|
/* repeat for all sons of sy1 */
|
|
while (t1 != NULL)
|
|
{
|
|
if (!t1->redefines && t1->times == 1)
|
|
{
|
|
t2 = sy2->son;
|
|
/* repeat for all sons of sy2 */
|
|
while (t2 != NULL)
|
|
{
|
|
if (!t2->redefines && t2->times == 1)
|
|
{
|
|
if (strcmp(t1->name, t2->name) == 0)
|
|
{
|
|
tmv1 = create_mathvar_info(NULL, t1, 0);
|
|
tmv2 = create_mathvar_info(NULL, t2, 0);
|
|
if ((t1->type != DTYPE_GROUP)
|
|
&& (t2->type != DTYPE_GROUP))
|
|
{
|
|
gen_add3(tmv1, tmv2, v1);
|
|
}
|
|
else
|
|
{
|
|
gen_addcorr1(tmv1, tmv2, rnd, v1);
|
|
}
|
|
delete_mathvar_info(tmv1);
|
|
delete_mathvar_info(tmv2);
|
|
}
|
|
}
|
|
t2 = t2->brother;
|
|
}
|
|
}
|
|
t1 = t1->brother;
|
|
}
|
|
addcorr_level--;
|
|
if (addcorr_level == 0)
|
|
{
|
|
math_on_size_error5(v1);
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
gen_subtractcorr(struct sym *sy1, struct sym *sy2, int rnd)
|
|
{
|
|
struct sym *t1, *t2;
|
|
if (sy1->litflag || sy2->litflag)
|
|
{
|
|
yyerror("sorry we don't handle this case yet!");
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# SUB CORR %s --> %s\n", sy1->name, sy2->name);
|
|
#endif
|
|
t1 = sy1->son;
|
|
/* repeat for all sons of sy1 */
|
|
while (t1 != NULL)
|
|
{
|
|
if (!t1->redefines && t1->times == 1)
|
|
{
|
|
t2 = sy2->son;
|
|
/* repeat for all sons of sy2 */
|
|
while (t2 != NULL)
|
|
{
|
|
if (!t2->redefines && t2->times == 1)
|
|
{
|
|
if (strcmp(t1->name, t2->name) == 0)
|
|
{
|
|
if ((t1->type != DTYPE_GROUP)
|
|
&& (t2->type != DTYPE_GROUP))
|
|
{
|
|
gen_subtract(t1, t2, rnd);
|
|
}
|
|
else
|
|
{
|
|
gen_subtractcorr(t1, t2, rnd);
|
|
}
|
|
}
|
|
}
|
|
t2 = t2->brother;
|
|
}
|
|
}
|
|
t1 = t1->brother;
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_subtractcorr1(struct math_var *mv1, struct math_var *mv2, int rnd,
|
|
struct math_ose *v1)
|
|
{
|
|
struct sym *sy1, *sy2;
|
|
struct sym *t1, *t2;
|
|
struct math_var *tmv1, *tmv2;
|
|
static int subcorr_level = 0;
|
|
|
|
if (mv1->sname->litflag || mv2->sname->litflag)
|
|
{
|
|
yyerror("sorry we don't handle this case yet!");
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# SUB CORR %s --> %s, lv %d\n",
|
|
mv1->sname->name, mv2->sname->name, subcorr_level);
|
|
#endif
|
|
/* ON SIZE ERROR option only */
|
|
if (subcorr_level == 0 && v1 != NULL)
|
|
{
|
|
/* generate bypass jump label */
|
|
gen_dstlabel(v1->lbl4);
|
|
}
|
|
subcorr_level++;
|
|
sy1 = mv1->sname;
|
|
sy2 = mv2->sname;
|
|
t1 = sy1->son;
|
|
/* repeat for all sons of sy1 */
|
|
while (t1 != NULL)
|
|
{
|
|
if (!t1->redefines && t1->times == 1)
|
|
{
|
|
t2 = sy2->son;
|
|
/* repeat for all sons of sy2 */
|
|
while (t2 != NULL)
|
|
{
|
|
if (!t2->redefines && t2->times == 1)
|
|
{
|
|
if (strcmp(t1->name, t2->name) == 0)
|
|
{
|
|
tmv1 = create_mathvar_info(NULL, t1, 0);
|
|
tmv2 = create_mathvar_info(NULL, t2, 0);
|
|
if ((t1->type != DTYPE_GROUP)
|
|
&& (t2->type != DTYPE_GROUP))
|
|
{
|
|
gen_subtract3(tmv1, tmv2, v1);
|
|
}
|
|
else
|
|
{
|
|
gen_subtractcorr1(tmv1, tmv2, rnd, v1);
|
|
delete_mathvar_info(tmv1);
|
|
delete_mathvar_info(tmv2);
|
|
}
|
|
}
|
|
}
|
|
t2 = t2->brother;
|
|
}
|
|
}
|
|
t1 = t1->brother;
|
|
}
|
|
subcorr_level--;
|
|
if (subcorr_level == 0)
|
|
{
|
|
math_on_size_error5(v1);
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_set_complex(struct sym *idx, int which, struct sym * var)
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# set complex %s to %s\n", idx ? idx->name : "(null)",
|
|
var ? var->name : "(null)");
|
|
#endif
|
|
switch (which)
|
|
{
|
|
case SET_TO: /* just move this value */
|
|
gen_move(idx, var);
|
|
break;
|
|
case SET_UP_BY: /* we need to add this value to the index */
|
|
gen_add(idx, (struct sym *) define_num_lit(1), 0);
|
|
break;
|
|
case SET_DOWN_BY:
|
|
gen_subtract(idx, (struct sym *) define_num_lit(1), 0);
|
|
break;
|
|
default:
|
|
yyerror("SET option unavailable");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_set_list(struct list *idx, int which, struct sym *var,
|
|
int adrof_idx, int adrof_var)
|
|
{
|
|
struct sym * svar;
|
|
|
|
while (idx != NULL)
|
|
{
|
|
svar = idx->var;
|
|
fprintf(o_src, "# SET %s \n", svar->name);
|
|
gen_set(idx->var, which, var, adrof_idx, adrof_var);
|
|
idx = idx->next;
|
|
}
|
|
vars_list = NULL;
|
|
}
|
|
|
|
/******* short-circuit conditional evaluators ********/
|
|
int
|
|
gen_evaluate_start()
|
|
{
|
|
int i = loc_label++;
|
|
fprintf(o_src, "# EVALUATE statement\n");
|
|
return i;
|
|
}
|
|
|
|
int
|
|
subject_set_size(struct selsubject *ssbj)
|
|
{
|
|
int size = 0;
|
|
while (ssbj != NULL)
|
|
{
|
|
size++;
|
|
ssbj = ssbj->next;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int
|
|
selection_object_size(int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case SOBJ_EXPR:
|
|
case SOBJ_NEGEXPR:
|
|
return 8;
|
|
case SOBJ_RANGE:
|
|
case SOBJ_NEGRANGE:
|
|
return 16;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
selection_subject_type(int level, struct selsubject *ssbj)
|
|
{
|
|
while (level--)
|
|
{
|
|
ssbj = ssbj->next;
|
|
}
|
|
return ssbj->type;
|
|
}
|
|
|
|
void
|
|
gen_perform(struct sym *sy)
|
|
{
|
|
gen_perform_thru(sy, sy);
|
|
}
|
|
|
|
void
|
|
set_usage(struct sym *sy, int usage)
|
|
{
|
|
sy->stype = ' ';
|
|
switch (usage)
|
|
{
|
|
case USAGE_COMP1:
|
|
sy->len = 4;
|
|
sy->decimals = 7;
|
|
sy->type = 'U';
|
|
sy->sign = 1;
|
|
/* default picture is 14 digits "S9(7)V9(7)" */
|
|
strcpy((char *) picture, "S\x01\x39\x07\x56\x01\x39\x07");
|
|
break;
|
|
case USAGE_COMP2:
|
|
sy->len = 8;
|
|
sy->decimals = 15;
|
|
sy->type = 'U';
|
|
sy->sign = 1;
|
|
/* default picture is 30 digits "S9(15)V9(15)" */
|
|
strcpy((char *) picture, "S\x01\x39\x0f\x56\x01\x39\x0f");
|
|
break;
|
|
case USAGE_COMP3:
|
|
sy->type = 'C';
|
|
break;
|
|
case USAGE_COMP:
|
|
sy->stype = 'B';
|
|
/* field length computed by query_comp_length() */
|
|
sy->len = 0;
|
|
sy->type = 'B'; /* binary field */
|
|
break;
|
|
case USAGE_COMP5:
|
|
sy->stype = '5';
|
|
sy->len = 0;
|
|
sy->type = 'B'; /* binary field */
|
|
break;
|
|
case USAGE_COMPX:
|
|
sy->stype = 'X';
|
|
sy->len = 0;
|
|
sy->type = 'B'; /* binary field */
|
|
break;
|
|
case USAGE_POINTER: /* POINTER */
|
|
sy->len = 4;
|
|
sy->decimals = 0;
|
|
sy->type = 'B'; /* pointers are binary fields */
|
|
/* pointer default picture: "9(10)" */
|
|
strcpy((char *) picture, "9\x0a");
|
|
sy->flags.is_pointer = 1;
|
|
break;
|
|
case USAGE_BINARY_CHAR:
|
|
sy->len = 1;
|
|
sy->type = 'B';
|
|
break;
|
|
case USAGE_BINARY_SHORT:
|
|
sy->len = 2;
|
|
sy->type = 'B';
|
|
break;
|
|
case USAGE_BINARY_LONG:
|
|
sy->len = 4;
|
|
sy->type = 'B';
|
|
break;
|
|
case USAGE_BINARY_DOUBLE:
|
|
sy->len = 8;
|
|
sy->type = 'B';
|
|
break;
|
|
case USAGE_INDEX:
|
|
sy->len = 4;
|
|
sy->type = 'B';
|
|
sy->decimals = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_picture(void)
|
|
{
|
|
if (curr_field->type != DTYPE_GROUP)
|
|
{
|
|
curr_field->picstr = (char *) malloc(strlen((char *) picture) + 1);
|
|
strcpy(curr_field->picstr, (char *) picture);
|
|
}
|
|
}
|
|
|
|
int
|
|
save_pic_char(char c, int i)
|
|
{
|
|
char c1 = (char) toupper(c);
|
|
unsigned int n;
|
|
|
|
switch (c1)
|
|
{
|
|
case 'A':
|
|
piccnt += i;
|
|
if (curr_field->type != DTYPE_ALPHANUMERIC
|
|
&& curr_field->type != DTYPE_EDITED)
|
|
curr_field->type = DTYPE_ALPHA;
|
|
break;
|
|
case 'X':
|
|
piccnt += i;
|
|
if (curr_field->type == DTYPE_DISPLAY)
|
|
curr_field->type = DTYPE_ALPHANUMERIC;
|
|
break;
|
|
case 'Z':
|
|
curr_field->type = DTYPE_EDITED;
|
|
case '9':
|
|
piccnt += i;
|
|
if (v_flag) decimals += i;
|
|
n_flag = 1;
|
|
break;
|
|
case 'V':
|
|
if (v_flag)
|
|
yyerror("invalid picture: V already given");
|
|
v_flag = 1;
|
|
break;
|
|
case 'P':
|
|
piccnt += i;
|
|
if (!n_flag)
|
|
v_flag = 1; /* implicit V just before the first P */
|
|
if (v_flag)
|
|
{
|
|
decimals += i;
|
|
pscale += i;
|
|
}
|
|
else
|
|
pscale -= i;
|
|
break;
|
|
case 'S':
|
|
sign = 1;
|
|
break;
|
|
case '.':
|
|
case ',':
|
|
case '0':
|
|
case 'B':
|
|
case '/':
|
|
case '+':
|
|
case '-':
|
|
case '*':
|
|
case 'C':
|
|
case 'R':
|
|
case 'D':
|
|
curr_field->type = DTYPE_EDITED;
|
|
piccnt += i;
|
|
break;
|
|
default:
|
|
if (c1 == currency_symbol)
|
|
{
|
|
curr_field->type = DTYPE_EDITED;
|
|
piccnt += i;
|
|
break;
|
|
}
|
|
else
|
|
return 0;
|
|
} /* switch(c1) */
|
|
|
|
if (picture[picix] == 0)
|
|
{ /* first char in PIC string? */
|
|
picture[picix] = c1;
|
|
picture[picix + 1] = 0;
|
|
}
|
|
if (((char) picture[picix] != c1) || (picture[picix + 1] == 255))
|
|
{
|
|
picix += 2;
|
|
picture[picix] = c1;
|
|
picture[picix + 1] = 0;
|
|
}
|
|
for (n = i + picture[picix + 1]; n > 255; n -= 255)
|
|
{
|
|
picture[picix + 1] = 255;
|
|
picture[picix + 2] = picture[picix];
|
|
picix += 2;
|
|
}
|
|
picture[picix + 1] = n;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
define_special_fields()
|
|
{
|
|
|
|
struct sym *sy, *tmp;
|
|
struct lit *ly;
|
|
|
|
sy = install(SVAR_RETURN_CODE, SYTB_VAR, 0);
|
|
spe_lit_SP = save_special_literal(' ', 'X', "%SPACES%");
|
|
spe_lit_LV = save_special_literal('\0', 'X', "%LOW-VALUES%");
|
|
spe_lit_HV = save_special_literal('\xff', 'X', "%HIGH-VALUES%");
|
|
spe_lit_ZE = save_special_literal('0', '9', "%ZEROS%");
|
|
spe_lit_QU = save_special_literal('"', 'X', "%QUOTES%");
|
|
spe_lit_SP->all = 1;
|
|
spe_lit_LV->all = 1;
|
|
spe_lit_HV->all = 1;
|
|
spe_lit_ZE->all = 1;
|
|
spe_lit_QU->all = 1;
|
|
|
|
ly = spe_lit_ZE;
|
|
|
|
/* sy->len=5; */
|
|
sy->len = 4;
|
|
sy->decimals = 0;
|
|
sy->pscale = 0;
|
|
sy->level = 1;
|
|
sy->defined = 1;
|
|
sy->type = DTYPE_BININT; /* assume numeric "usage is comp" item */
|
|
sy->redefines = NULL;
|
|
sy->linkage_flg = at_linkage;
|
|
sy->sec_no = SEC_RETURN_CODE;
|
|
sy->times = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->flags.just_r = 0;
|
|
sy->flags.separate_sign = 0;
|
|
sy->flags.leading_sign = 0;
|
|
sy->flags.blank = 0;
|
|
sy->flags.value = 1;
|
|
sy->son = sy->brother = NULL;
|
|
picture[0] = 'S';
|
|
picture[1] = 1;
|
|
picture[2] = '9';
|
|
picture[3] = 6;
|
|
picture[4] = 0;
|
|
tmp = curr_field;
|
|
curr_field = sy;
|
|
|
|
curr_field->value = ly;
|
|
curr_field->value2 = ly;
|
|
|
|
update_field(curr_field);
|
|
close_fields();
|
|
curr_field = tmp;
|
|
|
|
tmp = NULL;
|
|
ly = NULL;
|
|
|
|
}
|
|
|
|
/*
|
|
* Define a temp field of the desired type and desired lenght
|
|
*/
|
|
struct sym *
|
|
define_temp_field(char desired_type, int desired_len)
|
|
{
|
|
struct sym *sy, *tmp;
|
|
/* fprintf(stderr,"begin define temp %c\n",desired_type); */
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#define_temp_field:%c,%d,SO:%d\n",
|
|
desired_type, desired_len, stack_offset);
|
|
#endif
|
|
sy = malloc(sizeof (struct sym));
|
|
memset(sy, 0, sizeof (struct sym));
|
|
sy->litflag = 0;
|
|
sy->name = "%noname%";
|
|
sy->len = desired_len;
|
|
sy->decimals = 0; /* suppose no decimals yet */
|
|
sy->pscale = 0;
|
|
sy->level = 1;
|
|
sy->type = desired_type;
|
|
sy->redefines = NULL;
|
|
sy->parent = NULL;
|
|
sy->linkage_flg = 0;
|
|
sy->sec_no = SEC_DATA; /* not optimal; should be in stack */
|
|
/* sy->sec_no=SEC_STACK; */
|
|
sy->times = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->occurs = NULL;
|
|
sy->flags.just_r = 0;
|
|
sy->flags.separate_sign = 0;
|
|
sy->flags.leading_sign = 0;
|
|
sy->flags.blank = 0;
|
|
sy->son = sy->brother = NULL;
|
|
switch (desired_type)
|
|
{
|
|
case DTYPE_ALPHANUMERIC:
|
|
picture[0] = 'X';
|
|
picture[1] = (char) sy->len; /* this make the max 255 */
|
|
picture[2] = 0;
|
|
break;
|
|
case DTYPE_BININT: /* Make it signed */
|
|
picture[0] = 'S';
|
|
picture[1] = 1;
|
|
picture[2] = '9';
|
|
picture[3] = 9;
|
|
picture[4] = 0;
|
|
break;
|
|
default:
|
|
picture[0] = '9';
|
|
picture[1] = (char) sy->len; /* this make the max 255 */
|
|
picture[2] = 0;
|
|
break;
|
|
}
|
|
tmp = curr_field;
|
|
curr_field = sy;
|
|
|
|
piccnt = sy->len;
|
|
update_field(curr_field);
|
|
close_fields();
|
|
curr_field = tmp;
|
|
tmp = NULL;
|
|
|
|
/* fprintf(stderr,"end define_temp_field: %c\n",desired_type); */
|
|
return sy;
|
|
}
|
|
|
|
int
|
|
define_implicit_field(struct sym *sy, struct sym *sykey, int idxlen)
|
|
{
|
|
int i = 1, /*m=0, d,*/ r = 0;
|
|
struct sym *tmp = NULL;
|
|
char tmp_picture[3];
|
|
struct index_to_table_list *i2t;
|
|
|
|
/* Fix me:
|
|
* This is a fix to ensure that indexes are defined as int (4 bytes)
|
|
* For some reason if defined otherwise (1, 2 bytes) the search all
|
|
* will not work.
|
|
*/
|
|
|
|
#if 0
|
|
for (i = 1; i < idxlen; i = i * 10)
|
|
{
|
|
m++;
|
|
}
|
|
d = idxlen;
|
|
while (d != 0)
|
|
{
|
|
m++;
|
|
i = i * 10;
|
|
d = idxlen / i;
|
|
}
|
|
#endif
|
|
|
|
/* Fix me:
|
|
* This is a fix to ensure that indexes are defined as int (4 bytes)
|
|
*/
|
|
/* sy->len=m; */
|
|
sy->len = 4;
|
|
|
|
sy->decimals = 0; /* suppose no decimals yet */
|
|
sy->pscale = 0;
|
|
sy->level = 1;
|
|
sy->type = DTYPE_BININT; /* assume numeric "usage is comp" item */
|
|
sy->redefines = NULL;
|
|
sy->linkage_flg = 0; /* should not go in the linkage section, never! */
|
|
/* sy->sec_no=SEC_STACK; */
|
|
sy->sec_no = default_sec_no;
|
|
sy->times = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->son = sy->brother = NULL;
|
|
sy->flags.is_pointer = 0;
|
|
sy->flags.blank = 0;
|
|
|
|
memcpy(tmp_picture, picture, 3);
|
|
picture[0] = '9';
|
|
|
|
/* Fix me:
|
|
* This is a fix to ensure that indexes are defined as int (4 bytes)
|
|
*/
|
|
/* picture[1] = (char)m; */
|
|
picture[1] = (char) 8;
|
|
picture[2] = 0;
|
|
tmp = curr_field;
|
|
curr_field = sy;
|
|
update_field(curr_field);
|
|
close_fields();
|
|
curr_field = tmp;
|
|
memcpy(picture, tmp_picture, 3);
|
|
tmp = NULL;
|
|
|
|
i2t = malloc(sizeof (struct index_to_table_list));
|
|
if (i2t == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
i2t->next = NULL;
|
|
|
|
i = strlen(sy->name);
|
|
i2t->idxname = malloc(i + 1);
|
|
if (i2t->idxname == NULL)
|
|
{
|
|
free(i2t);
|
|
i2t = NULL;
|
|
return 0;
|
|
}
|
|
strcpy(i2t->idxname, sy->name);
|
|
|
|
i = strlen(curr_field->name);
|
|
i2t->tablename = malloc(i + 1);
|
|
if (i2t->tablename == NULL)
|
|
{
|
|
free(i2t->idxname);
|
|
free(i2t);
|
|
i2t = NULL;
|
|
return 0;
|
|
}
|
|
strcpy(i2t->tablename, curr_field->name);
|
|
|
|
i2t->seq = '0'; /* no sort sequence is yet defined for the table */
|
|
i2t->keyname = NULL;
|
|
if (sykey != NULL)
|
|
{
|
|
|
|
if (sykey->level == -1)
|
|
{
|
|
i2t->seq = '1';
|
|
}
|
|
|
|
if (sykey->level == -2)
|
|
{
|
|
i2t->seq = '2';
|
|
}
|
|
|
|
i = strlen(sykey->name);
|
|
i2t->keyname = malloc(i + 1);
|
|
if (i2t->keyname == NULL)
|
|
{
|
|
free(i2t->idxname);
|
|
free(i2t->tablename);
|
|
free(i2t);
|
|
return 0;
|
|
}
|
|
strcpy(i2t->keyname, sykey->name);
|
|
}
|
|
|
|
if (index2table == NULL)
|
|
{
|
|
index2table = i2t;
|
|
}
|
|
else
|
|
{
|
|
i2t->next = index2table;
|
|
index2table = i2t;
|
|
}
|
|
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#trace (define_implicit_field): index '%s' table '%s' tablekey '%s' sequence '%c'\n",
|
|
i2t->idxname,
|
|
i2t->tablename,
|
|
i2t->keyname,
|
|
i2t->seq
|
|
);
|
|
#endif
|
|
|
|
i2t = NULL;
|
|
|
|
return r;
|
|
}
|
|
|
|
struct sym*
|
|
determine_table_index_name(struct sym *sy)
|
|
{
|
|
struct sym *rsy = NULL;
|
|
struct index_to_table_list *i2t;
|
|
|
|
i2t = index2table;
|
|
while (i2t != NULL)
|
|
{
|
|
if (strcmp(i2t->tablename, sy->name) == 0)
|
|
{
|
|
rsy = lookup(i2t->idxname, SYTB_VAR);
|
|
i2t = NULL;
|
|
}
|
|
else
|
|
{
|
|
i2t = i2t->next;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG_COMPILER
|
|
if (rsy == NULL)
|
|
{
|
|
fprintf(o_src, "#trace (determine_table_index_name): table name '%s' index name '(NULL)'\n",
|
|
sy->name
|
|
);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "trace (determine_table_index_name): table name '%s' index name '%s'\n",
|
|
sy->name,
|
|
rsy->name
|
|
);
|
|
}
|
|
#endif
|
|
return rsy;
|
|
}
|
|
|
|
/* walter
|
|
verify if the variable is in the occurs */
|
|
int
|
|
in_occurs(struct sym *syfield)
|
|
{
|
|
struct sym *sy;
|
|
|
|
sy = syfield;
|
|
while (sy && sy->occurs_flg == 0)
|
|
{
|
|
sy = sy->parent;
|
|
}
|
|
if (!sy) return 0;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
define_field(int level, struct sym *sy)
|
|
{
|
|
struct sym *tmp;
|
|
struct sym *tmp1 = sy;
|
|
struct sym *tmp2;
|
|
|
|
if (sy == NULL)
|
|
{
|
|
sy = malloc(sizeof (struct sym));
|
|
sy->name = "%noname%";
|
|
}
|
|
if (level == 88)
|
|
{
|
|
sy->type = '8';
|
|
sy->defined = 1;
|
|
sy->len = 0;
|
|
sy->decimals = 0;
|
|
sy->pscale = 0;
|
|
sy->level = level;
|
|
sy->linkage_flg = at_linkage;
|
|
sy->sec_no = 0;
|
|
sy->times = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->flags.just_r = 0;
|
|
sy->flags.separate_sign = 0;
|
|
sy->flags.leading_sign = 0;
|
|
sy->flags.blank = 0;
|
|
sy->son = sy->brother = NULL;
|
|
if (curr_field->level == 88)
|
|
{
|
|
curr_field->brother = sy;
|
|
sy->parent = curr_field->parent;
|
|
}
|
|
else
|
|
sy->parent = curr_field;
|
|
curr_field = sy;
|
|
check_fields(sy);
|
|
return;
|
|
}
|
|
if (level == 1 || level == 77 || level == 66)
|
|
curr_sec_no = default_sec_no;
|
|
sy->len = 0;
|
|
sy->decimals = 0; /* suppose no decimals yet */
|
|
sy->pscale = 0;
|
|
sy->level = level;
|
|
sy->redefines = NULL;
|
|
sy->linkage_flg = at_linkage;
|
|
sy->sec_no = (at_linkage ? SEC_ARGS : curr_sec_no);
|
|
sy->times = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->flags.just_r = 0;
|
|
sy->flags.blank = 0;
|
|
sy->son = sy->brother = NULL;
|
|
sy->picstr = NULL;
|
|
|
|
/* Determine location in hierarchy */
|
|
tmp = curr_field;
|
|
if (tmp && ((level == 1) || (level == 77) || (level == 66)))
|
|
close_fields();
|
|
if (!tmp && (level > 1) && (level < 49))
|
|
{
|
|
yyerror("data field hierarchy broken");
|
|
}
|
|
if (level != 77 && level != 66)
|
|
{
|
|
while (tmp != NULL && tmp->level > level)
|
|
{
|
|
tmp1 = tmp;
|
|
tmp = tmp->parent;
|
|
}
|
|
if (tmp == NULL)
|
|
sy->parent = NULL;
|
|
else if (tmp->level < level)
|
|
{
|
|
sy->parent = tmp;
|
|
if (tmp->son == NULL)
|
|
tmp->son = sy;
|
|
/*else
|
|
yyerror("malformed data hierarchy");*/
|
|
else
|
|
{
|
|
tmp1->brother = sy;
|
|
sy->parent = tmp;
|
|
sy->level = tmp1->level;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tmp->brother = sy;
|
|
sy->parent = tmp->parent;
|
|
}
|
|
}
|
|
|
|
/* is it already defined ? */
|
|
if ((tmp2 = lookup(sy->name, SYTB_VAR)) != NULL)
|
|
{
|
|
if (tmp2 != sy && tmp2->parent == NULL && sy->parent == NULL)
|
|
yyerror("Variable %s already defined", tmp2->name);
|
|
}
|
|
|
|
/* Set initial values of inheritable fields */
|
|
if (sy->parent)
|
|
{
|
|
struct sym *syp = sy->parent;
|
|
sy->type = syp->type;
|
|
sy->flags.separate_sign = syp->flags.separate_sign;
|
|
sy->flags.leading_sign = syp->flags.leading_sign;
|
|
}
|
|
else
|
|
{
|
|
sy->type = DTYPE_DISPLAY;
|
|
sy->flags.separate_sign = 0;
|
|
sy->flags.leading_sign = 0;
|
|
}
|
|
|
|
curr_field = sy;
|
|
}
|
|
|
|
void
|
|
update_renames_field(struct sym *sy1, struct sym *sy2)
|
|
{
|
|
struct sym *sy = curr_field;
|
|
|
|
sy->son = NULL;
|
|
sy->parent = sy1->parent;
|
|
sy->redefines = sy1;
|
|
if (sy2 == NULL)
|
|
{
|
|
sy->type = sy1->type;
|
|
sy->location = sy1->location;
|
|
sy->len = sy1->len;
|
|
if (sy1->type == DTYPE_GROUP)
|
|
{
|
|
sy->pic = 0;
|
|
sy->descriptor = literal_offset;
|
|
literal_offset += FLD_DESC_SIZE0;
|
|
}
|
|
else
|
|
{
|
|
/* We should really reuse the original descriptor */
|
|
/* sy->descriptor = sy1->descriptor; */
|
|
sy->picstr = sy1->picstr;
|
|
sy->descriptor = literal_offset;
|
|
literal_offset += FLD_DESC_SIZE1;
|
|
sy->pic = literal_offset;
|
|
literal_offset += (strlen(sy1->picstr) + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sy->type = DTYPE_GROUP;
|
|
sy->location = sy1->location;
|
|
sy->len = sy2->location - sy1->location + sy2->len;
|
|
sy->pic = 0;
|
|
sy->descriptor = literal_offset;
|
|
literal_offset += FLD_DESC_SIZE0;
|
|
}
|
|
save_field_in_list(sy);
|
|
curr_field = NULL; /* so that close_fields won't be invoked */
|
|
}
|
|
|
|
struct sym *
|
|
alloc_filler(void)
|
|
{
|
|
char s[15];
|
|
struct sym *sy;
|
|
sprintf(s, "FIL$%05d", filler_num++);
|
|
sy = install(s, SYTB_VAR, 0);
|
|
sy->defined = 1;
|
|
return sy;
|
|
}
|
|
|
|
struct selsubject *
|
|
save_sel_subject(int type, struct selsubject *ssubj, struct sym *sy)
|
|
{
|
|
struct selsubject *tmp = malloc(sizeof (struct selsubject));
|
|
struct selsubject *tmp1;
|
|
tmp->type = type;
|
|
tmp->var = sy;
|
|
tmp->next = NULL;
|
|
if (ssubj != NULL)
|
|
{
|
|
tmp1 = ssubj;
|
|
while (tmp1->next)
|
|
tmp1 = tmp1->next;
|
|
tmp1->next = tmp;
|
|
return ssubj;
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
void
|
|
compute_subject_set_size(struct selsubject *ssbj)
|
|
{
|
|
int stack_adjust = 0;
|
|
while (ssbj != NULL)
|
|
{
|
|
if (ssbj->type == SSUBJ_EXPR)
|
|
{
|
|
stack_adjust += 8;
|
|
}
|
|
else if (ssbj->type == SSUBJ_COND)
|
|
{
|
|
stack_adjust += 4;
|
|
}
|
|
ssbj = ssbj->next;
|
|
}
|
|
inner_stack_size += stack_adjust;
|
|
}
|
|
|
|
void
|
|
release_sel_subject(int label, struct selsubject *ssbj)
|
|
{
|
|
struct selsubject *tmp;
|
|
int stack_adjust = 0;
|
|
fprintf(o_src, ".L%d:\t# EVALUATE end\n", label);
|
|
while (ssbj != NULL)
|
|
{
|
|
if (ssbj->type == SSUBJ_EXPR)
|
|
{
|
|
stack_adjust += 8;
|
|
}
|
|
else if (ssbj->type == SSUBJ_COND)
|
|
{
|
|
stack_adjust += 4;
|
|
}
|
|
tmp = ssbj;
|
|
ssbj = ssbj->next;
|
|
free(tmp);
|
|
}
|
|
if (stack_adjust)
|
|
fprintf(o_src, "\taddl\t$%d, %%esp\n", stack_adjust);
|
|
/* we're leaving this level of stack frame */
|
|
inner_stack_size -= stack_adjust;
|
|
}
|
|
|
|
int
|
|
check_fields(struct sym *sy)
|
|
{
|
|
struct sym *tmp;
|
|
// int len;
|
|
int elen;
|
|
char *p; /* walter */
|
|
int sylen, i, isd; /* walter */
|
|
|
|
/* Only fields that are signed, class numeric, and usage DISPLAY may
|
|
* leave the sign flags on. */
|
|
if ((sy->type != DTYPE_DISPLAY) || (sy->picstr[0] != 'S'))
|
|
{
|
|
sy->flags.separate_sign = 0;
|
|
sy->flags.leading_sign = 0;
|
|
}
|
|
/* Recursively check children */
|
|
if (sy->son != NULL)
|
|
{
|
|
// len = 0;
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
check_fields(tmp);
|
|
}
|
|
}
|
|
/*
|
|
These tests are done in YACC
|
|
|
|
if (sy->type == DTYPE_DISPLAY && sy->len > 18) {
|
|
yyerror("Maximum elementary numeric item size of %s > 18 digits exceeded", sy->name);
|
|
}
|
|
if (sy->type == DTYPE_ALPHANUMERIC && sy->len > 12750)
|
|
yyerror("Maximum elementary alphanumeric item size of %s > 12750 exceeded", sy->name);
|
|
*/
|
|
if (sy->level == 88)
|
|
{
|
|
if (sy->parent->len == 0)
|
|
yyerror("Parent variable of 88 has no storage");
|
|
}
|
|
if (sy->value != NULL)
|
|
{
|
|
sylen = sy->value->len; /* walter */
|
|
switch (sy->type)
|
|
{ /* test if numbers initiates with 0 and correct the error below walter */
|
|
case DTYPE_DISPLAY:
|
|
case DTYPE_BININT:
|
|
case DTYPE_PACKED:
|
|
case DTYPE_EDITED:
|
|
case DTYPE_FLOAT:
|
|
p = sy->value->name;
|
|
i = sylen;
|
|
sylen = 0;
|
|
isd = 0;
|
|
while (i)
|
|
{
|
|
switch (*p++)
|
|
{
|
|
case '0': if (isd) sylen++;
|
|
break;
|
|
default: sylen++;
|
|
isd = 1;
|
|
break;
|
|
}
|
|
i--;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (sylen > (elen = get_max_edt_len(sy)))
|
|
{
|
|
HTG_temporary_severity = 4;
|
|
yyerror("Value (length %d) of symbol %s is greater than it's picture (%d)", sylen, sy->name, elen);
|
|
HTG_temporary_severity = 8;
|
|
}
|
|
if (sy->value->type == DTYPE_ALPHANUMERIC &&
|
|
(sy->type == DTYPE_DISPLAY || sy->type == DTYPE_BININT))
|
|
if (!sy->flags.blank)
|
|
yyerror("Invalid value type for symbol %s", sy->name);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
set_field_value_sw(struct sym *sy, int times)
|
|
{
|
|
struct sym *tmp;
|
|
unsigned int res;
|
|
|
|
struct
|
|
{
|
|
unsigned int v : 1, sv : 1, tmpv : 1, tmpsv : 1;
|
|
} f;
|
|
|
|
f.v = 0;
|
|
f.sv = 0;
|
|
if (sy->son != NULL)
|
|
{
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
res = set_field_value_sw(tmp, times);
|
|
f.v = f.v || res;
|
|
}
|
|
}
|
|
sy->flags.value = f.v = f.v || sy->value != NULL;
|
|
sy->flags.spec_value = f.sv = f.v;
|
|
|
|
/* fprintf(stderr,"set_field_value_sw: %s -> %d,%d\n",sy->name,f.v,f.sv); */
|
|
/* return f.v*2 + f.sv; */
|
|
return f.v;
|
|
}
|
|
|
|
int
|
|
set_field_length(struct sym *sy, int times)
|
|
{
|
|
struct sym *tmp;
|
|
int len, tmplen;
|
|
if (sy->son != NULL)
|
|
{
|
|
len = 0;
|
|
sy->type = DTYPE_GROUP;
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
tmplen = tmp->times * set_field_length(tmp, times);
|
|
if (tmp->redefines == NULL)
|
|
len += tmplen;
|
|
}
|
|
sy->len = len;
|
|
}
|
|
len = symlen(sy) + sy->slack;
|
|
/* fprintf(stderr,"set_field_length: %s -> %d\n",sy->name,len*times); */
|
|
return len * times;
|
|
}
|
|
|
|
unsigned
|
|
field_alignment(struct sym *sy, unsigned location)
|
|
{
|
|
unsigned slack_bytes = 0, mod_loc;
|
|
|
|
if (sy->flags.sync == 0) return 0;
|
|
switch (sy->type)
|
|
{
|
|
case DTYPE_BININT:
|
|
mod_loc = (location - curr_01_location) % symlen(sy);
|
|
slack_bytes = (mod_loc == 0 ? 0 : symlen(sy) - mod_loc);
|
|
break;
|
|
}
|
|
#if 0
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#fa: %d, %d, %d, %d, %d\n", curr_01_location, location, symlen(sy), mod_loc, slack_bytes);
|
|
#endif
|
|
#endif
|
|
return slack_bytes;
|
|
}
|
|
|
|
void
|
|
set_field_location(struct sym *sy, unsigned location)
|
|
{
|
|
struct sym *tmp;
|
|
|
|
/* fprintf(stderr,"set_field_location: %s -> %d\n",sy->name,location); */
|
|
if (sy->level == 1) curr_01_location = location;
|
|
/********* allocate field descriptor *************/
|
|
sy->descriptor = literal_offset;
|
|
if (HTG_libcob)
|
|
{
|
|
literal_offset += (sy->type == DTYPE_GROUP ? CFLD_DESC_SIZE0 : CFLD_DESC_SIZE1);
|
|
}
|
|
else
|
|
{
|
|
literal_offset += (sy->type == DTYPE_GROUP ? FLD_DESC_SIZE0 : FLD_DESC_SIZE1);
|
|
}
|
|
/********* generate picture for field ************/
|
|
if (sy->type != DTYPE_GROUP)
|
|
{
|
|
sy->pic = literal_offset;
|
|
literal_offset += (strlen(sy->picstr) + 1);
|
|
}
|
|
else
|
|
sy->decimals = sy->pic = 0;
|
|
save_field_in_list(sy);
|
|
if (sy->redefines != NULL)
|
|
{
|
|
location = sy->redefines->location;
|
|
sy->slack = 0;
|
|
sy->flags.in_redefinition = 1;
|
|
}
|
|
else
|
|
{
|
|
sy->slack = field_alignment(sy, location);
|
|
location += sy->slack;
|
|
sy->flags.in_redefinition = 0;
|
|
}
|
|
if (sy->parent != NULL && sy->parent->flags.in_redefinition) sy->flags.in_redefinition = 1;
|
|
sy->location = location;
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
set_field_location(tmp, location);
|
|
if (tmp->redefines == NULL)
|
|
{
|
|
if (tmp->sec_no == SEC_STACK)
|
|
{
|
|
location -= (symlen(tmp) + tmp->slack) * tmp->times;
|
|
/* negative for it's at the stack */
|
|
}
|
|
else
|
|
{
|
|
location += (symlen(tmp) + tmp->slack) * tmp->times;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
scr_set_column(struct scr_info *si, struct sym *sy, int plus_minus)
|
|
{
|
|
int val;
|
|
si->column = 0;
|
|
si->column_var = NULL;
|
|
si->column_sign = plus_minus;
|
|
if (sy->litflag == 1)
|
|
{
|
|
si->column_var = NULL;
|
|
val = atoi(sy->name);
|
|
if (val == 0)
|
|
yyerror("line could not be 0");
|
|
si->column = val;
|
|
}
|
|
else
|
|
{
|
|
if (!(sy->defined))
|
|
yyerror("variable not defined %s ", sy->name);
|
|
if (sy->type == DTYPE_ALPHANUMERIC)
|
|
yyerror("variable %s must be numeric", sy->name);
|
|
si->column_var = sy;
|
|
}
|
|
}
|
|
|
|
void
|
|
scr_set_line(struct scr_info *si, struct sym *sy, int plus_minus)
|
|
{
|
|
int val;
|
|
si->line = 0;
|
|
si->line_var = NULL;
|
|
si->line_sign = plus_minus;
|
|
if (sy->litflag == 1)
|
|
{
|
|
si->line_var = NULL;
|
|
val = atoi(sy->name);
|
|
if (val == 0)
|
|
yyerror("line could not be 0");
|
|
si->line = val;
|
|
}
|
|
else
|
|
{
|
|
if (!(sy->defined))
|
|
yyerror("variable not defined %s ", sy->name);
|
|
if (sy->type == DTYPE_ALPHANUMERIC)
|
|
yyerror("variable %s must be numeric", sy->name);
|
|
|
|
si->line_var = sy;
|
|
}
|
|
}
|
|
|
|
/*void scr_push_display_position(struct lit *lit)*/
|
|
void
|
|
scr_push_display_position(struct sym *sy)
|
|
{
|
|
int len = 0, pos, lin, col;
|
|
struct lit *literal;
|
|
|
|
if (sy->litflag)
|
|
{
|
|
/* is a literal */
|
|
literal = (struct lit *) sy;
|
|
len = strlen(literal->name);
|
|
switch (len)
|
|
{
|
|
case 4:
|
|
pos = atoi(literal->name);
|
|
lin = pos / 100;
|
|
col = pos - (100 * lin);
|
|
push_immed(lin);
|
|
push_immed(col);
|
|
asm_call("tcob_goxy");
|
|
break;
|
|
case 6:
|
|
pos = atoi(literal->name);
|
|
lin = pos / 1000;
|
|
col = pos - (1000 * lin);
|
|
push_immed(lin);
|
|
push_immed(col);
|
|
asm_call("tcob_goxy");
|
|
break;
|
|
default:
|
|
yyerror("DISPLAY AT must be followed by a 4 digits or 6 digits integer");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* is a variable */
|
|
switch (sy->len)
|
|
{
|
|
case 4:
|
|
push_immed(4);
|
|
gen_loadloc(sy);
|
|
asm_call("tcob_goxy_variable");
|
|
break;
|
|
case 6:
|
|
push_immed(6);
|
|
gen_loadloc(sy);
|
|
asm_call("tcob_goxy_variable");
|
|
break;
|
|
default:
|
|
yyerror("DISPLAY AT must be followed by a 4 digits or 6 digits variable");
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/*************** report section ******************/
|
|
|
|
void
|
|
save_report(struct sym *rep, struct sym *file)
|
|
{
|
|
struct rd *rd = (struct rd *) rep;
|
|
struct list *item = malloc(sizeof (struct list));
|
|
item->var = rd;
|
|
item->next = report_list;
|
|
report_list = item;
|
|
rd->file = file;
|
|
rd->type = 'W';
|
|
rd->controls = rd->items = NULL;
|
|
rd->page_limit = 66;
|
|
rd->heading = 1;
|
|
rd->footing = 66;
|
|
rd->first_detail = rd->last_detail = 1;
|
|
}
|
|
|
|
void
|
|
update_report_field(struct sym *sy)
|
|
{
|
|
update_field(curr_field);
|
|
sy->type = 'Q';
|
|
}
|
|
|
|
void
|
|
update_screen_field(struct sym *sy, struct scr_info *si)
|
|
{
|
|
struct sym *tmp;
|
|
char *pic;
|
|
update_field(curr_field);
|
|
sy->type = DTYPE_ACCEPT_DISPLAY;
|
|
sy->scr = si;
|
|
si->label = screen_label++;
|
|
/* if picture is empty (implicit filler), and there is a
|
|
value declared, create its picture from value literal. */
|
|
|
|
if (*(sy->picstr) == 0 && sy->value != NULL)
|
|
{
|
|
tmp = (struct sym *) sy->value;
|
|
pic = sy->picstr = malloc(3);
|
|
*pic++ = 'X';
|
|
*pic++ = strlen(tmp->name);
|
|
*pic = 0;
|
|
sy->len = strlen(tmp->name);
|
|
}
|
|
}
|
|
|
|
void
|
|
update_field(struct sym *sy)
|
|
{
|
|
if (sy->level != 88 && sy->level != 66)
|
|
{
|
|
gen_picture();
|
|
}
|
|
/* printf("upd_flds:symbol: %s, %d, piccnt: %d, %d\n", sy->name,
|
|
sy->len, piccnt,pscale); */
|
|
/* Physical sizes for BINARY and FLOAT types are not (generally)
|
|
* affected by the PICTURE. */
|
|
if ((sy->type != DTYPE_BININT)
|
|
&& (sy->type != DTYPE_FLOAT))
|
|
{
|
|
if (piccnt == 1 && abs(pscale) == 1)
|
|
sy->len = 1; /* only one P in the picture */
|
|
else
|
|
sy->len = piccnt - abs(pscale);
|
|
}
|
|
/* SIGN IS ... SEPARATE only affects field length when class is numeric,
|
|
* usage is DISPLAY, and field is signed. However, sign flags must be
|
|
* temporarily retained in case this is a group item. */
|
|
if ((sy->type == DTYPE_DISPLAY)
|
|
&& (sy->picstr[0] == 'S')
|
|
&& (sy->flags.separate_sign))
|
|
{
|
|
sy->len++;
|
|
}
|
|
/* fprintf(stderr,"symbol: %s, piccnt: %d, %d\n", sy->name,
|
|
piccnt,pscale); */
|
|
/* update COMP field length (but not BINARY-<something>) */
|
|
if ((sy->type == DTYPE_BININT)
|
|
&& (sy->len == 0))
|
|
{
|
|
sy->len = query_comp_len(sy);
|
|
}
|
|
}
|
|
|
|
void
|
|
close_fields(void)
|
|
{
|
|
struct sym *sy;
|
|
int saved_length;
|
|
int ns_offset = 0;
|
|
if (curr_field == NULL) return;
|
|
/* printf("close: %s, %d\n", curr_field->name, curr_field->len); */
|
|
/********** locate level 01 field **************/
|
|
for (sy = curr_field; sy->parent != NULL; sy = sy->parent);
|
|
if (sy->level != 1 && sy->level != 77 && sy->level != 66)
|
|
{
|
|
yyerror("field not subordinate to any other: %s", sy->name);
|
|
}
|
|
/********** propagate value flags *************/
|
|
sy->flags.spec_value = set_field_value_sw(sy, 1);
|
|
/********** update length of fields *************/
|
|
if (sy->linkage_flg)
|
|
{
|
|
linkage_offset += (set_field_length(sy, 1) * sy->times);
|
|
set_field_location(sy, linkage_offset);
|
|
}
|
|
else if (sy->sec_no == SEC_DATA)
|
|
{
|
|
saved_length = (set_field_length(sy, 1) * sy->times);
|
|
set_field_location(sy, data_offset);
|
|
data_offset += saved_length;
|
|
}
|
|
else if (sy->sec_no >= SEC_FIRST_NAMED)
|
|
{
|
|
saved_length = (set_field_length(sy, 1) * sy->times);
|
|
set_field_location(sy, ns_offset);
|
|
ns_offset += saved_length;
|
|
}
|
|
else
|
|
{
|
|
stack_offset += (set_field_length(sy, 1) * sy->times);
|
|
set_field_location(sy, stack_offset);
|
|
}
|
|
check_fields(sy);
|
|
curr_field = NULL;
|
|
}
|
|
|
|
/*int
|
|
show_labels() {
|
|
struct sym *sy,*sy1,*sy2;
|
|
int i,j=0;
|
|
FILE *f;
|
|
f = fopen("show.labels","w");
|
|
for (i=0;i<HASHLEN;i++) {
|
|
for (sy=labtab[i];sy!=NULL;sy=sy->next) {
|
|
if (sy->type == 'f') continue;
|
|
sy1 = sy;
|
|
while (sy1) {
|
|
fprintf(f,"Label: %s, defined: %d, type: %c, parent: %s\n",
|
|
sy1->name, sy1->defined, sy1->type,
|
|
sy1->parent ? sy1->parent->name : "(NULL)");
|
|
j++;
|
|
sy1=sy1->clone;
|
|
}
|
|
}
|
|
}
|
|
fclose(f);
|
|
return j;
|
|
}*/
|
|
|
|
char *
|
|
var_name(struct sym *sy)
|
|
{
|
|
unsigned int n;
|
|
n = MAXNAMEBUF;
|
|
strcpy(name_buf, "");
|
|
while (n > strlen(sy->name) + 4)
|
|
{
|
|
if (n < MAXNAMEBUF)
|
|
strcat(name_buf, " OF ");
|
|
strcat(name_buf, sy->name);
|
|
n -= strlen(sy->name) + 4;
|
|
if ((lookup(sy->name, SYTB_VAR)->clone == NULL)
|
|
|| (sy->parent == NULL))
|
|
break;
|
|
sy = sy->parent;
|
|
}
|
|
return name_buf;
|
|
}
|
|
|
|
/* save variable values, including 88-var range/values list */
|
|
void
|
|
set_variable_values(struct lit *v1, struct lit *v2)
|
|
{
|
|
struct vrange /**vr,*/*new;
|
|
if (curr_field->value == NULL)
|
|
{
|
|
curr_field->refmod_redef.vr = NULL;
|
|
curr_field->value = v1;
|
|
curr_field->value2 = v2;
|
|
curr_field->flags.value = 1;
|
|
curr_field->flags.spec_value = 1;
|
|
}
|
|
else
|
|
{
|
|
new = malloc(sizeof (struct vrange));
|
|
new->value = v1;
|
|
new->value2 = v2;
|
|
/* spec_value is not used for 88 */
|
|
new->next = curr_field->refmod_redef.vr;
|
|
curr_field->refmod_redef.vr = new;
|
|
}
|
|
}
|
|
|
|
void
|
|
assign_expr(struct sym *sy, int opt, char end)
|
|
{
|
|
push_immed(opt);
|
|
gen_loadvar(sy);
|
|
if (end == '1')
|
|
{
|
|
stackframe_cnt += sizeof (double); /* value to be poped too */
|
|
}
|
|
asm_call("tcob_assign_double");
|
|
}
|
|
|
|
int
|
|
push_expr(struct sym *sy)
|
|
{
|
|
int retcode;
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "##### push_expr begin\n");
|
|
#endif
|
|
retcode = push_subexpr(sy);
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "##### push_expr end\n");
|
|
#endif
|
|
return retcode;
|
|
}
|
|
|
|
void
|
|
alloc_file_entry(struct sym *f)
|
|
{
|
|
f->record = stack_offset;
|
|
f->sort_file = 0;
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# Allocate space for file '%s' Stack Addr: %d\n",
|
|
f->name, stack_offset);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** define a file, but don't generate code yet.
|
|
** (will be done later at dump_fdesc())
|
|
*/
|
|
void
|
|
gen_fdesc(struct sym *f, struct sym *r)
|
|
{
|
|
int len;
|
|
struct list *list, *templist;
|
|
struct alternate_list *alt;
|
|
list = (struct list *) malloc(sizeof (struct list));
|
|
|
|
if (files_list == NULL)
|
|
{
|
|
files_list = list;
|
|
}
|
|
else
|
|
{
|
|
templist = files_list;
|
|
while (templist->next != NULL)
|
|
{
|
|
templist = templist->next;
|
|
}
|
|
templist->next = list;
|
|
}
|
|
list->var = f;
|
|
list->next = NULL;
|
|
|
|
f->recordsym = r;
|
|
while (r != NULL)
|
|
{
|
|
r->ix_desc = f;
|
|
r = r->redefines;
|
|
}
|
|
len = sizeof (struct file_desc) - 10; /* suppose without indexes */
|
|
/* f->location = file_offset; */
|
|
if (f->organization == 1)
|
|
{ /* indexed file */
|
|
len += 10 + 2;
|
|
/* 10 -> remaining of struct file_desc (only for indexed files)
|
|
2 --> size of terminating "word -1| */
|
|
/* now count each alternate description size */
|
|
alt = (struct alternate_list *) f->alternate;
|
|
while (alt)
|
|
{
|
|
len += sizeof (struct altkey_desc);
|
|
alt = alt->next;
|
|
}
|
|
}
|
|
f->fdesc = global_offset;
|
|
global_offset += len;
|
|
/* file_offset += len; */
|
|
}
|
|
|
|
void
|
|
gen_status(struct sym *f)
|
|
{
|
|
|
|
if (f->parent)
|
|
{
|
|
push_eax();
|
|
gen_loadloc(f->parent);
|
|
asm_call("tcob_save_status");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_perform_decl(struct sym *f)
|
|
{
|
|
struct sym *decl_sym = f->refmod_redef.declarative;
|
|
int tmplabel;
|
|
|
|
if (decl_sym)
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# decl: on %s\n", decl_sym->name);
|
|
#endif
|
|
tmplabel = gen_check_zero();
|
|
gen_perform(decl_sym);
|
|
gen_dstlabel(tmplabel);
|
|
}
|
|
}
|
|
|
|
/****** sort statement related functions *******/
|
|
struct sortfile_node *
|
|
alloc_sortfile_node(struct sym *sy)
|
|
{
|
|
struct sortfile_node *sn;
|
|
if (sy->type != 'F')
|
|
{
|
|
yyerror("only files can be found here");
|
|
return NULL;
|
|
}
|
|
sn = malloc(sizeof (struct sortfile_node));
|
|
sn ->next = NULL;
|
|
sn->sy = sy;
|
|
return sn;
|
|
}
|
|
|
|
struct sym *
|
|
create_status_register(char *name)
|
|
{
|
|
struct sym *sy;
|
|
char pic[] = {'9', 2, 0};
|
|
sy = install(name, SYTB_VAR, 0);
|
|
if (sy->type) return sy; /* it already exists */
|
|
sy->type = DTYPE_DISPLAY;
|
|
sy->picstr = malloc(strlen(pic) + 1);
|
|
strcpy(sy->picstr, pic);
|
|
sy->defined = 1;
|
|
sy->occurs_flg = 0;
|
|
sy->times = 1;
|
|
sy->len = 2;
|
|
sy->son = sy->brother = NULL;
|
|
sy->linkage_flg = 0;
|
|
sy->sec_no = SEC_DATA;
|
|
sy->location = data_offset;
|
|
data_offset += 2;
|
|
sy->descriptor = literal_offset;
|
|
literal_offset += FLD_DESC_SIZE1;
|
|
sy->pic = literal_offset;
|
|
literal_offset += strlen(pic) + 1;
|
|
save_field_in_list(sy);
|
|
return sy;
|
|
}
|
|
|
|
void
|
|
gen_sort_using(struct sym *f, struct sortfile_node *sn)
|
|
{
|
|
struct sym *vstatus = create_status_register("SORT-RETURN");
|
|
gen_save_sort_fields(f, NULL);
|
|
push_immed(0);
|
|
while (sn)
|
|
{
|
|
gen_loadloc(sn->sy->filenamevar);
|
|
gen_save_filedesc(sn->sy);
|
|
sn = sn->next;
|
|
}
|
|
asm_call("tcob_sort_using");
|
|
/* save status returned by operation */
|
|
push_eax();
|
|
gen_loadloc(vstatus);
|
|
asm_call("tcob_save_status");
|
|
}
|
|
|
|
void
|
|
gen_sort_giving(struct sym *f, struct sortfile_node *sn)
|
|
{
|
|
struct sym *vstatus = create_status_register("SORT-RETURN");
|
|
gen_save_sort_fields(f, NULL);
|
|
push_immed(0);
|
|
while (sn)
|
|
{
|
|
gen_loadloc(sn->sy->filenamevar);
|
|
gen_save_filedesc(sn->sy);
|
|
sn = sn->next;
|
|
}
|
|
asm_call("tcob_sort_giving");
|
|
/* save status returned by operation */
|
|
push_eax();
|
|
gen_loadloc(vstatus);
|
|
asm_call("tcob_save_status");
|
|
}
|
|
|
|
void
|
|
gen_sort(struct sym *f)
|
|
{
|
|
struct sym *datafld;
|
|
if ((f->recordsym))
|
|
{
|
|
gen_loadloc(f->filenamevar);
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_sort_open");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
gen_close_sort(f);
|
|
}
|
|
else
|
|
{ /* walter */
|
|
push_immed(0);
|
|
if (f->sort_data)
|
|
{
|
|
datafld = (struct sym *) f->sort_data;
|
|
while (datafld != NULL)
|
|
{
|
|
gen_loadloc(datafld); /* value of field */
|
|
push_immed((int) datafld->direction);
|
|
gen_loaddesc2(datafld, 1); /* field struct */
|
|
datafld = (struct sym *) (datafld->sort_data);
|
|
if (datafld == (struct sym *) f->sort_data)
|
|
datafld = NULL;
|
|
}
|
|
}
|
|
if (f->occurs)
|
|
{
|
|
gen_loaddesc(f->occurs->depend); /* depending on */
|
|
gen_loadloc(f->occurs->depend);
|
|
push_immed((int) f->occurs->max); /* occurs n times */
|
|
push_immed((int) f->occurs->min); /* occurs initial times */
|
|
}
|
|
else
|
|
{
|
|
push_immed(0);
|
|
push_immed(0);
|
|
push_immed((int) f->times); /* occurs n times */
|
|
push_immed(1); /* occurs initial times */
|
|
}
|
|
push_immed((int) f->len);
|
|
gen_loadloc(f);
|
|
gen_loaddesc2(f, 1);
|
|
asm_call("tcob_sort_mem");
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_open(int mode, struct sym *f)
|
|
{
|
|
push_immed(mode);
|
|
gen_loadloc(f->filenamevar);
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_open");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_close_sort(struct sym *f)
|
|
{
|
|
struct sym *sortf;
|
|
/********** allocate memory for SORT descriptor ***********/
|
|
save_field_in_list(f);
|
|
f->descriptor = literal_offset;
|
|
sortf = (struct sym *) (f->sort_data);
|
|
while (sortf != NULL)
|
|
{
|
|
literal_offset += 2;
|
|
sortf = (struct sym *) (sortf->sort_data);
|
|
}
|
|
literal_offset++;
|
|
}
|
|
|
|
void
|
|
gen_close(struct sym *f)
|
|
{
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_close");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_return_stmt(struct sym *f, struct sym *buf)
|
|
{
|
|
gen_save_filevar(f, buf);
|
|
asm_call("tcob_sort_return");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
int
|
|
gen_reads(struct sym *f, struct sym *buf, struct sym *key,
|
|
int next_prev, int sel, int withlock)
|
|
{
|
|
int r = 0;
|
|
int t_next_prev = next_prev;
|
|
/* NOTE:
|
|
* While this is functional, it requires to be updated to trap more syntax errors
|
|
*/
|
|
|
|
if (f->type != 'F')
|
|
{
|
|
yyerror("invalid variable \'%s\', file name expected", f->name);
|
|
r++;
|
|
return r;
|
|
}
|
|
|
|
#if 0
|
|
/* READ w/o [NOT] AT END or [NOT] INVALID KEY clauses */
|
|
if (sel == 0)
|
|
{
|
|
if ((next_prev != 0) && (key != NULL))
|
|
{
|
|
yyerror("invalid clause NEXT found in READ statement with KEY IS data-name option");
|
|
r++;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
/* READ with [NOT] AT END clauses */
|
|
if (sel == 1)
|
|
{
|
|
}
|
|
|
|
/* READ with [NOT] INVALID KEY clauses */
|
|
if (sel == 2)
|
|
{
|
|
if (next_prev != 0)
|
|
{
|
|
yyerror("invalid clause NEXT found in READ statement with INVALID KEY option");
|
|
r++;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
/* RETURN w/o [NOT] AT END clauses */
|
|
if (sel == 4)
|
|
{
|
|
}
|
|
|
|
/* RETURN with [NOT] AT END clauses */
|
|
if (sel == 5)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
if (r == 0)
|
|
{
|
|
/* fprintf(stderr, "sel %d, np %d\n", sel, next_prev); */
|
|
if (f->access_mode == ACC_SEQUENTIAL &&
|
|
f->sort_file == 1)
|
|
{
|
|
gen_return_stmt(f, buf);
|
|
return r;
|
|
}
|
|
if ((f->access_mode == ACC_SEQUENTIAL || f->access_mode == ACCEV_SEQUENTIAL) &&
|
|
f->organization != ORG_LINESEQUENTIAL)
|
|
{
|
|
if (t_next_prev == 0) t_next_prev = 1;
|
|
gen_read_next(f, buf, t_next_prev, withlock);
|
|
return r;
|
|
}
|
|
if ((sel > -1) && (sel < 4))
|
|
{
|
|
/* if (sel == 1) t_next_prev = 1; */ /* AT END implies read next */
|
|
if (t_next_prev > 0
|
|
&& (f->organization == ORG_INDEXED || f->organization == ORG_RELATIVE)
|
|
&& (f->access_mode == ACC_DYNAMIC || f->access_mode == ACC_SEQUENTIAL || f->access_mode == ACCEV_SEQUENTIAL
|
|
|| f->access_mode == ACCEV_DYNAMIC)
|
|
)
|
|
{
|
|
gen_read_next(f, buf, t_next_prev, withlock);
|
|
}
|
|
else
|
|
{
|
|
gen_read(f, buf, key, withlock);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (f->organization != ORG_SEQUENTIAL)
|
|
gen_read_next(f, buf, next_prev, withlock);
|
|
else
|
|
gen_return_stmt(f, buf);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void
|
|
gen_unlock(struct sym *f)
|
|
{
|
|
if (f->type != 'F')
|
|
{
|
|
yyerror("invalid variable \'%s\', file expected", f->name);
|
|
return;
|
|
}
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_unlock");
|
|
}
|
|
|
|
void
|
|
gen_read(struct sym *f, struct sym *buf, struct sym *key,
|
|
int withlock)
|
|
{
|
|
struct rec_varying *rv = (struct rec_varying *) f->rec_varying;
|
|
/* gen_check_varying(f); */
|
|
if (f->organization == ORG_RELATIVE)
|
|
{
|
|
/*gen_loadloc( f->ix_desc );
|
|
fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",
|
|
f->ix_desc->descriptor);
|
|
push_eax();*/
|
|
gen_loadvar(f->ix_desc);
|
|
asm_call("tcob_get_index");
|
|
push_eax();
|
|
}
|
|
if (f->organization == ORG_INDEXED)
|
|
{
|
|
gen_loadvar(key);
|
|
}
|
|
/* pass the desc/address of reclen, if VARYING ... */
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
gen_save_filevar(f, buf);
|
|
if (withlock == 1)
|
|
asm_call1("tcob_setlock");
|
|
else
|
|
if (withlock == 2)
|
|
asm_call1("tcob_ignorelock");
|
|
asm_call("tcob_read");
|
|
gen_status(f);
|
|
/* gen_perform_decl(f); */ /* must be generated after At End or Invalid Key */
|
|
}
|
|
|
|
void
|
|
gen_read_next(struct sym *f, struct sym *buf, int next_prev,
|
|
int withlock)
|
|
{
|
|
struct rec_varying *rv = (struct rec_varying *) f->rec_varying;
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
gen_save_filevar(f, buf);
|
|
if (next_prev == 1)
|
|
{
|
|
if (withlock == 1)
|
|
asm_call1("tcob_setlock");
|
|
else
|
|
if (withlock == 2)
|
|
asm_call1("tcob_ignorelock");
|
|
asm_call("tcob_read_next");
|
|
}
|
|
else
|
|
{
|
|
if (withlock == 1)
|
|
asm_call1("tcob_setlock");
|
|
else
|
|
if (withlock == 2)
|
|
asm_call1("tcob_ignorelock");
|
|
asm_call("tcob_read_prev");
|
|
}
|
|
gen_status(f);
|
|
/* gen_perform_decl(f); */ /* must be generated after At End or Invalid Key */
|
|
}
|
|
|
|
void
|
|
gen_release(struct sym *r, struct sym *buf)
|
|
{
|
|
struct sym *f;
|
|
f = r->ix_desc;
|
|
if (buf != NULL)
|
|
{
|
|
gen_move(buf, r);
|
|
}
|
|
gen_save_sort_fields(f, buf);
|
|
asm_call("tcob_sort_release");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_write(struct sym *r, struct sym *advar, struct sym *buf, int opt)
|
|
{
|
|
struct sym *f = r->ix_desc;
|
|
struct rec_varying *rv = (struct rec_varying *) f->rec_varying;
|
|
gen_check_varying(f);
|
|
if (opt)
|
|
{
|
|
if (buf != NULL)
|
|
{
|
|
gen_move(buf, r);
|
|
}
|
|
if (advar != NULL)
|
|
gen_loadvar(advar);
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
push_immed(opt);
|
|
|
|
/* gen_save_filevar( f,buf ); */
|
|
/* Is this code correct ??? It works but ... */
|
|
gen_save_filevar(f, r);
|
|
|
|
asm_call("tcob_write_adv");
|
|
|
|
#if 0
|
|
/* This code does not work !!! */
|
|
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
push_immed(opt);
|
|
gen_save_filevar(f, buf);
|
|
if (buf == NULL)
|
|
asm_call("tcob_write_adv");
|
|
else
|
|
{
|
|
gen_move(buf, r);
|
|
/* asm_call("tcob_write_adv_from"); */
|
|
asm_call("tcob_write_adv");
|
|
}
|
|
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (f->organization == ORG_RELATIVE)
|
|
{
|
|
/*gen_loadloc( f->ix_desc );
|
|
fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",
|
|
f->ix_desc->descriptor);
|
|
push_eax();*/
|
|
gen_loadvar(f->ix_desc);
|
|
asm_call("tcob_get_index");
|
|
push_eax();
|
|
}
|
|
/* Handle Write From by moving the data and then setting Buf to NULL
|
|
* only if it is not a relative record.
|
|
*/
|
|
if ((buf != NULL) && (f->organization != ORG_RELATIVE))
|
|
{
|
|
gen_move(buf, r);
|
|
buf = NULL;
|
|
}
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
gen_save_filevar(f, buf);
|
|
asm_call("tcob_write");
|
|
}
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_rewrite(struct sym *r, struct sym *buf)
|
|
{
|
|
struct sym *f = r->ix_desc;
|
|
struct rec_varying *rv = (struct rec_varying *) f->rec_varying;
|
|
gen_check_varying(f);
|
|
if (f->organization == ORG_RELATIVE)
|
|
{
|
|
/*gen_loadloc( f->ix_desc );
|
|
fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",
|
|
f->ix_desc->descriptor);
|
|
push_eax();*/
|
|
gen_loadvar(f->ix_desc);
|
|
asm_call("tcob_get_index");
|
|
push_eax();
|
|
}
|
|
if (rv != NULL)
|
|
gen_loadvar(rv->reclen);
|
|
else
|
|
gen_loadvar(NULL);
|
|
gen_save_filevar(f, buf);
|
|
asm_call("tcob_rewrite");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_start(struct sym *f, int cond, struct sym *key)
|
|
{
|
|
gen_check_varying(f);
|
|
if (f->organization == ORG_RELATIVE)
|
|
{
|
|
/*gen_loadloc( f->ix_desc );
|
|
fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",
|
|
f->ix_desc->descriptor);
|
|
push_eax();*/
|
|
gen_loadvar(f->ix_desc);
|
|
asm_call("tcob_get_index");
|
|
push_eax();
|
|
}
|
|
else
|
|
{
|
|
gen_loadvar(key);
|
|
}
|
|
push_immed(cond);
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_start");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
gen_delete(struct sym *f)
|
|
{
|
|
gen_check_varying(f);
|
|
if (f->organization == ORG_RELATIVE)
|
|
{
|
|
/*gen_loadloc( f->ix_desc );
|
|
fprintf(o_src,"\tmovl\t$c_base+%u, %%eax\n",
|
|
f->ix_desc->descriptor);
|
|
push_eax();*/
|
|
gen_loadvar(f->ix_desc);
|
|
asm_call("tcob_get_index");
|
|
push_eax();
|
|
}
|
|
gen_save_filevar(f, NULL);
|
|
asm_call("tcob_delete");
|
|
gen_status(f);
|
|
gen_perform_decl(f);
|
|
}
|
|
|
|
void
|
|
set_rec_varying_info(struct sym *f, struct lit *lmin,
|
|
struct lit *lmax, struct sym *reclen)
|
|
{
|
|
struct rec_varying *rv = malloc(sizeof (struct rec_varying));
|
|
f->rec_varying = (char *) rv;
|
|
rv->lmin = lmin;
|
|
rv->lmax = lmax;
|
|
rv->reclen = reclen;
|
|
}
|
|
|
|
void
|
|
gen_check_varying(struct sym *f)
|
|
{
|
|
struct rec_varying *rv = (struct rec_varying *) f->rec_varying;
|
|
if (rv != NULL)
|
|
{
|
|
gen_loadvar(rv->reclen);
|
|
gen_loadvar((struct sym *) rv->lmax);
|
|
gen_loadvar((struct sym *) rv->lmin);
|
|
gen_save_filedesc(f);
|
|
asm_call("tcob_check_varying");
|
|
}
|
|
}
|
|
|
|
int
|
|
get_switch_number(struct sym *sy)
|
|
{
|
|
return (sy->name[2] - '0');
|
|
}
|
|
|
|
void
|
|
gen_get_switches()
|
|
{
|
|
struct list *l = switches_list;
|
|
struct sym *svar;
|
|
|
|
while (l != NULL)
|
|
{
|
|
svar = l->var;
|
|
push_immed(get_switch_number(svar->ix_desc));
|
|
gen_loadvar(svar);
|
|
asm_call("tcob_get_switch");
|
|
l = l-> next;
|
|
}
|
|
}
|
|
|
|
void
|
|
gen_set_switch(struct sym *var, struct sym *sy)
|
|
{
|
|
|
|
gen_move(var, sy);
|
|
push_immed(get_switch_number(sy->ix_desc));
|
|
gen_loadvar(sy);
|
|
asm_call("tcob_set_switch");
|
|
|
|
}
|
|
|
|
struct list *
|
|
chain_var(struct sym *sy)
|
|
{
|
|
vars_list = insert_list(vars_list, sy);
|
|
return vars_list;
|
|
}
|
|
|
|
void
|
|
gen_push_using(struct sym *sy)
|
|
{
|
|
struct parm_list *list;
|
|
if (sy->type == 'F')
|
|
yyerror("file could not be used as parameter in a CALL");
|
|
list = (struct parm_list *) malloc(sizeof (struct parm_list));
|
|
list->var = (void *) sy;
|
|
list->next = parameter_list;
|
|
list->location = 0;
|
|
list->sec_no = 0;
|
|
parameter_list = list;
|
|
}
|
|
|
|
void
|
|
gen_save_usings(struct gvar_list *gsylst)
|
|
{
|
|
struct gvar_list *gl;
|
|
|
|
for (gl = gsylst; gl->next != NULL; gl = gl->next)
|
|
{
|
|
gen_save_using(gl->u.sym);
|
|
}
|
|
gen_save_using(gl->u.sym);
|
|
}
|
|
|
|
void
|
|
gen_save_using(struct sym *sy)
|
|
{
|
|
sy->linkage_flg = using_offset;
|
|
using_offset += 4;
|
|
}
|
|
|
|
void
|
|
gen_save_chainings(struct gvar_list *gsylst)
|
|
{
|
|
struct gvar_list *gl;
|
|
|
|
for (gl = gsylst; gl->next != NULL; gl = gl->next)
|
|
{
|
|
gen_save_chaining(gl->u.sym);
|
|
}
|
|
gen_save_chaining(gl->u.sym);
|
|
}
|
|
|
|
void
|
|
gen_save_chaining(struct sym *sy)
|
|
{
|
|
struct parm_list *list;
|
|
if (sy->type == 'F')
|
|
yyerror("only variables could be used as parameter in CHAINING");
|
|
list = (struct parm_list *) malloc(sizeof (struct parm_list));
|
|
list->var = (void *) sy;
|
|
list->next = chaining_list;
|
|
list->location = 0;
|
|
list->sec_no = 0;
|
|
chaining_list = list;
|
|
}
|
|
|
|
void
|
|
gen_chain(struct sym *v, int stack_size, int exceplabel)
|
|
{
|
|
|
|
struct parm_list *list, *tmp;
|
|
struct sym *cp;
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "#chain %s\n", v->name);
|
|
#endif
|
|
push_immed(0);
|
|
for (list = parameter_list; list != NULL; list = tmp)
|
|
{
|
|
cp = (struct sym *) list->var;
|
|
gen_loadvar(cp);
|
|
tmp = list->next;
|
|
free(list);
|
|
}
|
|
parameter_list = NULL;
|
|
gen_loadvar(v);
|
|
asm_call("tcob_chain");
|
|
|
|
}
|
|
|
|
short
|
|
get_std_val(struct sym *sy)
|
|
{
|
|
if (sy->value == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (sy->value == spe_lit_ZE)
|
|
{
|
|
return 2;
|
|
}
|
|
else if (sy->value == spe_lit_SP)
|
|
{
|
|
return 3;
|
|
}
|
|
else if (sy->value == spe_lit_LV)
|
|
{
|
|
return 4;
|
|
}
|
|
else if (sy->value == spe_lit_HV)
|
|
{
|
|
return 5;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Count the number of items under the field sy
|
|
* if (sw_val) ???
|
|
*/
|
|
int
|
|
get_nb_fields(struct sym *sy_org, int sw_val)
|
|
{
|
|
struct sym *tmp;
|
|
int nb_fields = 1, tmpnf;
|
|
char ftype;
|
|
short val;
|
|
/* walter 13-12-05 */
|
|
// char ftype = sy->type;
|
|
struct sym *sy;
|
|
int oc;
|
|
|
|
sy = sy_org;
|
|
oc = 0;
|
|
if (sy->litflag == 2)
|
|
{
|
|
oc = 1;
|
|
sy = ((struct vref *) sy)->sym;
|
|
if (sy->litflag == 2)
|
|
sy = ((struct vref *) sy)->sym;
|
|
}
|
|
/* fim walter */
|
|
ftype = sy->type;
|
|
|
|
if (sy->type == DTYPE_GROUP)
|
|
{
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
tmpnf = get_nb_fields(tmp, sw_val);
|
|
|
|
if (tmp->redefines == NULL)
|
|
nb_fields += tmpnf;
|
|
}
|
|
/* if(oc) // walter 13-12-05
|
|
return nb_fields;*/
|
|
}
|
|
else
|
|
{
|
|
/* Packed fields are presently considered non-homogenous */
|
|
if (ftype == DTYPE_PACKED) ftype = '&';
|
|
if (ftype == DTYPE_DISPLAY && sy->picstr[0] == 'S') ftype = '&';
|
|
if (init_ctype == ' ') init_ctype = ftype;
|
|
if (ftype != init_ctype && init_ctype != '&')
|
|
init_ctype = '&';
|
|
if (sw_val)
|
|
{
|
|
val = get_std_val(sy);
|
|
if (init_val == -1) init_val = val;
|
|
if (ftype == init_ctype && init_ctype != '&' &&
|
|
val != init_val)
|
|
init_ctype = '&';
|
|
}
|
|
}
|
|
if (oc) return nb_fields;
|
|
else
|
|
return nb_fields * sy->times;
|
|
}
|
|
|
|
/*
|
|
* sy : field
|
|
* initp : 0
|
|
* init_loc : initial location
|
|
* nb_fields : number of fields
|
|
*/
|
|
static int
|
|
_build_init_str(struct sym *sy, int initp,
|
|
unsigned *init_loc, int nb_fields,
|
|
struct sym *fsy, struct vref *ref)
|
|
{ // walter 13-12-05
|
|
char mem_warn[] = "**** WARNING invading end of malloced memory";
|
|
struct sym *tmp;
|
|
int stidx = -1, endidx = -1;
|
|
int i, j;
|
|
struct sym *sy_org = NULL; //walter 13-12-05
|
|
struct vref *refa; // walter 13-12-05
|
|
|
|
if (initp >= nb_fields)
|
|
{
|
|
fprintf(stderr, "%s, f,sym: %s\n", mem_warn, sy->name);
|
|
return initp;
|
|
}
|
|
// walter 13-12-05
|
|
if (ref)
|
|
{
|
|
sy_org = malloc(sizeof (struct sym));
|
|
refa = (struct vref *) sy_org;
|
|
//sy_org=(struct sym*)create_subscripted_var( sy, ref );
|
|
refa->litflag = 2;
|
|
refa->sym = sy;
|
|
refa->next = ref->next;
|
|
//create_subscripted_var( struct sym * sy, struct vref *subs )
|
|
}
|
|
else
|
|
sy_org = sy;
|
|
// fim walter
|
|
|
|
stidx = initp;
|
|
istrp->ent[initp].sy = sy_org; // walter 13-12-05
|
|
istrp->ent[initp].type = sy->type;
|
|
istrp->ent[initp].value = sy->value;
|
|
istrp->ent[initp].len = symlen(sy);
|
|
istrp->ent[initp].location = *init_loc;
|
|
if (sy->type != DTYPE_GROUP)
|
|
{
|
|
*init_loc += istrp->ent[initp].len;
|
|
}
|
|
initp++;
|
|
if (sy->type == DTYPE_GROUP)
|
|
{
|
|
for (tmp = sy->son; tmp != NULL; tmp = tmp->brother)
|
|
{
|
|
if (tmp->redefines == NULL)
|
|
initp = _build_init_str(tmp, initp, init_loc, nb_fields, fsy, ref); // walter 13-12-05
|
|
}
|
|
}
|
|
endidx = initp;
|
|
if (ref && fsy && fsy == sy) // only for these ocorrency walter 13-12-05
|
|
return initp;
|
|
|
|
for (i = 1; i < sy->times; i++)
|
|
{
|
|
if (initp >= nb_fields)
|
|
{
|
|
fprintf(stderr, "%s, i,sym: %s\n", mem_warn, sy->name);
|
|
break;
|
|
}
|
|
for (j = stidx; j < endidx; j++)
|
|
{
|
|
if (initp >= nb_fields)
|
|
{
|
|
fprintf(stderr, "%s, j,sym: %s\n", mem_warn, sy->name);
|
|
break;
|
|
}
|
|
istrp->ent[initp].sy = istrp->ent[j].sy;
|
|
istrp->ent[initp].type = istrp->ent[j].type;
|
|
istrp->ent[initp].value = istrp->ent[j].value;
|
|
istrp->ent[initp].len = istrp->ent[j].len;
|
|
istrp->ent[initp].location = *init_loc;
|
|
if (istrp->ent[j].type != DTYPE_GROUP)
|
|
*init_loc += istrp->ent[initp].len;
|
|
initp++;
|
|
}
|
|
}
|
|
|
|
return initp;
|
|
}
|
|
|
|
int
|
|
build_init_str(struct sym *sy_org, int nb_fields)
|
|
{
|
|
unsigned init_loc;
|
|
/* walter 13-12-05 */
|
|
struct sym *sy = NULL, *ref = NULL;
|
|
struct vref *ref1 = NULL;
|
|
int i;
|
|
|
|
sy = sy_org;
|
|
init_loc = sy->location;
|
|
i = 0;
|
|
if (sy->litflag == 2)
|
|
{
|
|
ref1 = ((struct vref *) sy);
|
|
ref = ((struct vref *) sy)->next->sym;
|
|
sy = ((struct vref *) sy)->sym;
|
|
if (sy->litflag == 2)
|
|
sy = ((struct vref *) sy)->sym;
|
|
if (ref->litflag == 1)
|
|
{ // index by literal
|
|
i = atoi(ref->name);
|
|
init_loc = ((i - 1) * sy->len) + sy->location;
|
|
ref = NULL;
|
|
}
|
|
}
|
|
/* fim walter */
|
|
return _build_init_str(sy, 0, &init_loc, nb_fields, sy, ref1);
|
|
}
|
|
|
|
void
|
|
gen_from_init_str(int nb_fields)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nb_fields; i++)
|
|
{
|
|
unsigned temp_loc = istrp->ent[i].sy->location;
|
|
istrp->ent[i].sy->location = istrp->ent[i].location;
|
|
gen_init_str(istrp->ent[i].sy, istrp->ent[i].type, istrp->ent[i].len);
|
|
istrp->ent[i].sy->location = temp_loc;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize field 'sy' of type 'init_ctype' and of length 'len'
|
|
*
|
|
*/
|
|
void
|
|
gen_init_str(struct sym *sy, char init_ctype, int len)
|
|
{
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# init_str %s, type %c, len %d, loc %d\n", sy->name, init_ctype, len, sy->location);
|
|
#endif
|
|
|
|
switch (init_ctype)
|
|
{
|
|
case DTYPE_DISPLAY:
|
|
case DTYPE_PACKED:
|
|
if (sy->value != NULL)
|
|
gen_move_init((struct sym *) sy->value, sy); /* initial value */
|
|
else
|
|
gen_move((struct sym *) spe_lit_ZE, sy);
|
|
break;
|
|
|
|
case DTYPE_BININT:
|
|
if (sy->type == DTYPE_BININT)
|
|
{
|
|
if (sy->value != NULL)
|
|
gen_move_init((struct sym *) sy->value, sy); /* initial value */
|
|
else
|
|
gen_move((struct sym *) spe_lit_ZE, sy);
|
|
}
|
|
else
|
|
{
|
|
if (sy->value != NULL)
|
|
gen_move_init((struct sym *) sy->value, sy); /* initial value */
|
|
else
|
|
gen_move((struct sym *) spe_lit_LV, sy);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (sy->value != NULL)
|
|
gen_move_init((struct sym *) sy->value, sy); /* initial value */
|
|
else
|
|
gen_move((struct sym *) spe_lit_SP, sy);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Generate an initialize field
|
|
*
|
|
*/
|
|
void
|
|
gen_initializes(struct gvar_list *gsylst)
|
|
{
|
|
struct gvar_list *gl;
|
|
|
|
for (gl = gsylst; gl->next != NULL; gl = gl->next)
|
|
{
|
|
gen_initialize(gl->u.sym, 1);
|
|
}
|
|
gen_initialize(gl->u.sym, 1);
|
|
}
|
|
|
|
/* walter 13-12-05
|
|
void gen_initializes_verb(struct gvar_list *gsylst, struct lit *init_alphab, struct lit *init_alpha, struct lit *init_alphaedt, struct lit *init_num, struct lit *init_numedt) {
|
|
struct gvar_list *gl;
|
|
unsigned int idx=0;
|
|
|
|
for(gl=gsylst; gl->next!=NULL; gl=gl->next) {
|
|
gen_move_first(gl->u.sym, 0, 0, &idx);
|
|
}
|
|
gen_move_first(gl->u.sym, 0, 0, &idx);
|
|
return;
|
|
}
|
|
|
|
unsigned int gen_move_first(struct sym *sy, unsigned int loc, unsigned int size, unsigned int *idx) {
|
|
struct sym *var, *tmp, *cop, *ref;
|
|
int subs, i, ntimes, bSign=0;
|
|
unsigned char cDigit;
|
|
char *valor;
|
|
unsigned int loc_cop=0;
|
|
|
|
if(sy==NULL) return loc;
|
|
var=sy; // Make sure BLANK test is done on a sym struct, and not a vref struct
|
|
// litflag
|
|
// 1-literal
|
|
// 2-variable
|
|
// 4-refmod
|
|
// 5-expr
|
|
// ,-end of subscripted
|
|
// + - -subscript arith
|
|
//
|
|
if(var->litflag==4 || var->litflag==2 || var->litflag==4) {
|
|
gen_subscripted( (struct vref *)var );
|
|
// ref=((struct vref *)var)->next->sym;
|
|
// valor=ref->name;
|
|
// if(!ref->litflag)
|
|
// valor=ref->value->name;
|
|
// integer's name is just it's value in ascii
|
|
// if(*valor!='%') { // eca
|
|
// for(i=0; (cDigit = valor[i]); i++) {
|
|
// if(cDigit=='}') {
|
|
// cDigit=0;
|
|
// } else if(cDigit=='{') {
|
|
// cDigit=0;
|
|
// bSign=1;
|
|
// } else if((cDigit>='A') && (cDigit<='I')) {
|
|
// cDigit-='A'-1;
|
|
// } else if ((cDigit>='J') && (cDigit<='R')) {
|
|
// cDigit-='J'-1;
|
|
// bSign=1;
|
|
// } else if(isdigit(cDigit)){
|
|
// cDigit-='0';
|
|
// } else
|
|
// cDigit=0;
|
|
// *idx=(*idx * 10) + cDigit;
|
|
// }
|
|
// }
|
|
var=((struct vref *)var)->sym;
|
|
if(var->litflag==2)
|
|
var=((struct vref *)var)->sym;
|
|
}
|
|
|
|
if(var->flags.external) return loc;
|
|
if(var->type == DTYPE_GROUP) {
|
|
if(loc==0) loc=var->location;
|
|
ntimes=var->times;
|
|
if(*idx) ntimes=1;
|
|
do {
|
|
tmp=var->son;
|
|
while(tmp!=NULL) {
|
|
if(tmp->redefines) {
|
|
loc=gen_move_first(tmp, tmp->location, var->len, idx);
|
|
} else {
|
|
loc=gen_move_first(tmp, loc, var->len, idx);
|
|
}
|
|
tmp=tmp->brother;
|
|
}
|
|
ntimes--;
|
|
} while(ntimes);
|
|
return loc;
|
|
} else {
|
|
if(loc==0) {
|
|
loc=var->location;
|
|
ntimes=var->times;
|
|
}
|
|
}
|
|
cop = malloc(sizeof(struct sym));
|
|
memcpy(cop, var, sizeof(struct sym));
|
|
if(*idx) (*idx)--;
|
|
while(*idx) {
|
|
loc+=size;
|
|
(*idx)--;
|
|
}
|
|
i = cop->times;
|
|
while(i--) {
|
|
cop->location=loc;
|
|
gen_init_str(cop, cop->type, 1);
|
|
loc += cop->len;
|
|
}
|
|
free(cop);
|
|
return loc;
|
|
}
|
|
fim walter */
|
|
|
|
void
|
|
gen_initialize(struct sym *sy_start, int from_initializes)
|
|
{
|
|
/*struct sym *sy;*/
|
|
int nb_fields;
|
|
struct init_str init_templ;
|
|
/* Possible optimization:
|
|
* 1) Compress the init sequence to reduce the number
|
|
* of elementary moves.
|
|
*/
|
|
if (sy_start == NULL) return;
|
|
if (sy_start->flags.external && !from_initializes) return; // walter 13-12-05
|
|
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# INITIALIZE %s, type %c\n", sy_start->name, sy_start->type);
|
|
#endif
|
|
init_ctype = ' ';
|
|
nb_fields = get_nb_fields(sy_start, 0);
|
|
if (init_ctype != '&' && init_ctype != ' ')
|
|
{
|
|
gen_init_str(sy_start, init_ctype, symlen(sy_start));
|
|
return;
|
|
}
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# (2) istrp = malloc(%d) nb_fields = %d\n",
|
|
nb_fields * sizeof (init_templ), nb_fields);
|
|
#endif
|
|
istrp = malloc(nb_fields * sizeof (init_templ));
|
|
build_init_str(sy_start, nb_fields);
|
|
gen_from_init_str(nb_fields);
|
|
free(istrp);
|
|
istrp = NULL;
|
|
#ifdef DEBUG_COMPILER
|
|
fprintf(o_src, "# END_INITIALIZE\n");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Cancel statement
|
|
* The parameter is the field or literal containing the name of the routine to cancel
|
|
* if the parameter is NULL, a is a CACNEL ALL
|
|
*/
|
|
|
|
void
|
|
gen_cancel(struct sym *routine_name)
|
|
{
|
|
if (routine_name)
|
|
{
|
|
gen_loadvar(routine_name);
|
|
asm_call("tcob_cancel");
|
|
}
|
|
else
|
|
{
|
|
asm_call("tcob_cancel_all");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GOBACK statement.
|
|
* If is a module generate EXIT PROGRAM, else STOP RUN
|
|
*/
|
|
void
|
|
gen_goback()
|
|
{
|
|
if (module_flag) /* If is a module generate EXIT PROGRAM, else STOP RUN */
|
|
gen_exit(1);
|
|
else
|
|
gen_stoprun();
|
|
}
|
|
|
|
/* ok nao achei nenhuma referencia para esta funcao
|
|
void mark_actives( int first, int last ) {
|
|
int i;
|
|
if (last<first) last=first;
|
|
if (first<0 || first>36) first=0;
|
|
if (last<0 || last>36) last=0;
|
|
for (i=first;i<=last;i++) active[i]=1;
|
|
}
|
|
|
|
ok
|
|
used with qsort
|
|
return: strncmp from *z1 and *z2
|
|
see man qsort for more explanation */
|
|
int
|
|
sort_exref_compare(const void *z1, const void *z2)
|
|
{
|
|
char ss1[256], ss2[256];
|
|
|
|
strncpy(ss1, var_name(*(struct sym **) z1), sizeof (ss1));
|
|
strncpy(ss2, var_name(*(struct sym **) z2), sizeof (ss2));
|
|
return strncmp(ss1, ss2, sizeof (ss1));
|
|
}
|
|
|
|
void
|
|
dump_symbols()
|
|
{
|
|
int i, j, k, arsize, slen;
|
|
struct sym *sy, *sy1, **sytable;
|
|
char t, *s, *str1, sa1[256];
|
|
|
|
if (!HTG_list_flag)
|
|
return;
|
|
|
|
fprintf(o_lst,
|
|
"\n=======================================================================");
|
|
fprintf(o_lst, "\n\nSymbols of module:%20.20s\n", pgm_label);
|
|
fprintf(o_lst, "--------------------------------------\n");
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
/* for (sy=labtab[i];sy!=NULL;sy=sy->next) { */
|
|
for (sy = vartab[i]; sy != NULL; sy = sy->next)
|
|
{
|
|
t = sy->type;
|
|
sy1 = sy;
|
|
while (sy1)
|
|
{
|
|
/* check if any variables (excluding intrinsic functions)
|
|
are undefined */
|
|
if ((sy1->defined == 0) && (sy->type == 0))
|
|
{
|
|
yyerror("Declared but undefined variable \'%s\' found.", sy1->name);
|
|
/* fprintf(stderr, "Undefined variable \'%s\', defined=%d, type=%c, line=%d;\n",
|
|
sy1->name, sy1->defined, sy1->type, sy1->xrefs.lineno[0]); */
|
|
}
|
|
#if 0
|
|
else
|
|
{
|
|
fprintf(stderr, "Defined variable \'%s\', defined=%d, type=%c, line=%d;\n",
|
|
sy1->name, sy1->defined, sy1->type, sy1->xrefs.lineno[0]);
|
|
}
|
|
#endif
|
|
sy1 = sy1->clone;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!HTG_list_flag)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/* Determine size of tree */
|
|
for (i = 0, j = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy1 = vartab[i]; sy1 != NULL; sy1 = sy1->next)
|
|
{
|
|
for (sy = sy1; sy; sy = sy->clone)
|
|
{
|
|
if (sy->xrefs.lineno[0] != 0)
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
arsize = j;
|
|
|
|
/* Allocate sort array */
|
|
sytable = (struct sym**) malloc(sizeof (struct sym *) * (arsize));
|
|
|
|
/* Initialize sort array from hash tree */
|
|
for (i = 0, j = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy1 = vartab[i]; sy1 != NULL; sy1 = sy1->next)
|
|
{
|
|
for (sy = sy1; sy; sy = sy->clone)
|
|
{
|
|
if (sy->xrefs.lineno[0] != 0)
|
|
{
|
|
sytable[j] = sy;
|
|
str1 = var_name(sytable[j]);
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Sort array using the quick sort function */
|
|
qsort(sytable, arsize, sizeof (struct sym *), sort_exref_compare);
|
|
|
|
if (HTG_xref_flag)
|
|
{
|
|
|
|
fprintf(o_lst, "\n---------------------------------------------------- Cross Refrence Listing --------------------------------------------------------\n\n");
|
|
fprintf(o_lst, "Variable Symbol ( Qualifiers ) Locations\n");
|
|
fprintf(o_lst, "-----------------------------------------+------------------------------------------------------------------------------------------\n");
|
|
for (i = 0; i < arsize; i++)
|
|
{
|
|
sy = sytable[i];
|
|
if (sy->xrefs.lineno[0] != 0)
|
|
{
|
|
s = var_name(sy);
|
|
|
|
strcpy(sa1, "");
|
|
j = 0;
|
|
k = 0;
|
|
slen = strlen(s);
|
|
if (slen > 40)
|
|
{
|
|
for (j = 0; j < (slen - 40); j = j + k)
|
|
{
|
|
str1 = strstr(s + j, " OF ");
|
|
k = strlen(str1 + 4);
|
|
k = slen - j - k;
|
|
strncpy(sa1, s + j, k);
|
|
sa1[k] = '\0';
|
|
fprintf(o_lst, "%-40s\n", sa1);
|
|
}
|
|
strcpy(sa1, s + j);
|
|
}
|
|
else
|
|
{
|
|
strcpy(sa1, s);
|
|
}
|
|
fprintf(o_lst, "%-40s ", sa1);
|
|
|
|
for (j = 0; j < sy->xrefs.pos; j++)
|
|
{
|
|
if ((j % 8 == 0) && (j > 0))
|
|
{
|
|
fprintf(o_lst, "\n%-40s ", "");
|
|
}
|
|
fprintf(o_lst, "%06d ", sy->xrefs.lineno[j]);
|
|
}
|
|
fprintf(o_lst, "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!HTG_list_flag)
|
|
{
|
|
return;
|
|
}
|
|
|
|
fprintf(o_lst, "\n---------------------------------------------------------------+-----------------\n");
|
|
fprintf(o_lst, "Symbol ( Variables ) Type Level Len Dec Mul | Desc Loc Pic S\n");
|
|
fprintf(o_lst, "---------------------------------------------------------------+-----------------\n");
|
|
for (i = 0; i < arsize; i++)
|
|
{
|
|
sy = sytable[i];
|
|
s = var_name(sy);
|
|
|
|
strcpy(sa1, "");
|
|
j = 0;
|
|
k = 0;
|
|
slen = strlen(s);
|
|
if (slen > 40)
|
|
{
|
|
for (j = 0; j < (slen - 40); j = j + k)
|
|
{
|
|
str1 = strstr(s + j, " OF ");
|
|
k = strlen(str1 + 4);
|
|
k = slen - j - k;
|
|
strncpy(sa1, s + j, k);
|
|
sa1[k] = '\0';
|
|
fprintf(o_lst, "%-40s\n", sa1);
|
|
}
|
|
strcpy(sa1, s + j);
|
|
}
|
|
else
|
|
{
|
|
strcpy(sa1, s);
|
|
}
|
|
|
|
fprintf(o_lst,
|
|
"%-40s%4c%1c%3d %5d %3d %3d%c| %04X %04X%c%04X %1d\n",
|
|
sa1,
|
|
/* sy->type, */
|
|
sy->type ? sy->type : '0',
|
|
sy->flags.just_r ? 'R' : ' ',
|
|
sy->level,
|
|
sy->len,
|
|
sy->decimals,
|
|
sy->times,
|
|
sy->occurs_flg ? '*' : ' ',
|
|
sy->descriptor,
|
|
sy->location,
|
|
sy->linkage_flg ? '*' : ' ',
|
|
sy->pic,
|
|
sy->sec_no);
|
|
}
|
|
fprintf(o_lst, "\n\n");
|
|
|
|
|
|
fprintf(o_lst, "\n-----------------------------------------------\n");
|
|
fprintf(o_lst, "Symbol ( 88-condition ) Variable tested");
|
|
fprintf(o_lst, "\n-----------------------------------------------\n");
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy = vartab[i]; sy != NULL; sy = sy->next)
|
|
{
|
|
t = sy->type;
|
|
if (t == '8')
|
|
fprintf(o_lst, "%22.22s %22.22s\n",
|
|
sy->name,
|
|
sy->parent->name);
|
|
}
|
|
}
|
|
|
|
fprintf(o_lst,
|
|
"\n-----------------------------------------------------------------------\n");
|
|
fprintf(o_lst, "%s%s%s",
|
|
" Paragraph ",
|
|
" Section ", " Type");
|
|
fprintf(o_lst,
|
|
"\n-----------------------------------------------------------------------\n");
|
|
for (i = 0; i < HASHLEN; i++)
|
|
{
|
|
for (sy = labtab[i]; sy != NULL; sy = sy->next)
|
|
{
|
|
t = sy->type;
|
|
sy1 = sy;
|
|
while (sy1)
|
|
{
|
|
if ((sy1->type == 'P') || (sy1->type == 'S'))
|
|
{
|
|
fprintf(o_lst, "%32.32s %32.32s %c\n",
|
|
(sy1->type == 'P') ? sy1->name : "",
|
|
(sy1->type == 'S') ? sy1->name :
|
|
(sy1->parent ? sy1->parent->name : ""),
|
|
sy1->type);
|
|
}
|
|
sy1 = sy1->clone;
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(o_lst, "\n\nTinyCOBOL compile audit summary:\n");
|
|
fprintf(o_lst, "Total lines compiled : %4d\n", source_lineno);
|
|
fprintf(o_lst, "Total number of warnings : %4d\n", wrncnt);
|
|
fprintf(o_lst, "Total number of errors found : %4d\n", errcnt);
|
|
|
|
}
|
|
|
|
/* ok
|
|
search for "-" caracter in *s and replace it with _
|
|
enter: char *
|
|
return: void */
|
|
void
|
|
chg_underline(char *s)
|
|
{
|
|
char *s1;
|
|
s1 = s; /* walter */
|
|
while (*s1)
|
|
{
|
|
if (*s1 == '-') *s1 = '_';
|
|
s1++;
|
|
}
|
|
/* while ((s1=strchr(s,'-'))!=NULL) *s1='_'; */
|
|
}
|
|
|
|
void
|
|
gen_enter_runelement(int type)
|
|
{
|
|
/* this should be cleaned if we are going to load it */
|
|
fprintf(o_src, "\tmovl\t$s_base%d+0, %%eax\n", pgm_segment);
|
|
push_eax();
|
|
push_immed(type);
|
|
push_immed(program_name_literal->len);
|
|
loadloc_to_eax((struct sym *) program_name_literal);
|
|
push_eax();
|
|
asm_call("tcob_enter_runelement");
|
|
}
|
|
/* end of HTCOBGEN.C */
|