282 lines
7.4 KiB
C
282 lines
7.4 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2013 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include <errno.h>
|
|
#include "gtm_string.h"
|
|
#include "gtm_stdio.h"
|
|
#include "gtm_time.h"
|
|
#include "gtm_stat.h"
|
|
#include "gtm_unistd.h"
|
|
|
|
#include "compiler.h"
|
|
#include "parse_file.h"
|
|
#include "error.h"
|
|
#include "io.h"
|
|
#include "io_params.h"
|
|
#include "eintr_wrappers.h"
|
|
#include "op.h"
|
|
#include "source_file.h"
|
|
#include "zroutines.h"
|
|
#include "gtmio.h"
|
|
#include "iotimer.h"
|
|
#include "cmd_qlf.h"
|
|
#include "min_max.h"
|
|
#include "cli.h"
|
|
#include "have_crit.h"
|
|
|
|
GBLREF unsigned short source_name_len;
|
|
GBLREF unsigned char source_file_name[];
|
|
GBLREF char rev_time_buf[];
|
|
GBLREF mident routine_name, module_name, int_module_name;
|
|
GBLREF unsigned char *source_buffer;
|
|
GBLREF int4 dollar_zcstatus;
|
|
GBLREF io_pair io_curr_device;
|
|
GBLREF char object_file_name[];
|
|
GBLREF short object_name_len;
|
|
GBLREF int object_file_des;
|
|
GBLREF command_qualifier cmd_qlf;
|
|
|
|
static bool tt_so_do_once;
|
|
static io_pair compile_src_dev;
|
|
static io_pair dev_in_use; /* before opening source file */
|
|
static io_pair tmp_list_dev; /* before reading source file */
|
|
/* it equal to dev_in_use if list file not open */
|
|
static readonly unsigned char open_params_list[] =
|
|
{
|
|
(unsigned char)iop_readonly,
|
|
(unsigned char)iop_m,
|
|
(unsigned char)iop_eol
|
|
};
|
|
|
|
error_def(ERR_ASSERT);
|
|
error_def(ERR_ERRORSUMMARY);
|
|
error_def(ERR_FILENOTFND);
|
|
error_def(ERR_FILEPARSE);
|
|
error_def(ERR_GTMASSERT);
|
|
error_def(ERR_GTMASSERT2);
|
|
error_def(ERR_GTMCHECK);
|
|
error_def(ERR_MEMORY);
|
|
error_def(ERR_OBJFILERR);
|
|
error_def(ERR_SRCFILERR);
|
|
error_def(ERR_STACKOFLOW);
|
|
|
|
void compile_source_file(unsigned short flen, char *faddr, boolean_t MFtIsReqd)
|
|
{
|
|
plength plen;
|
|
mval fstr, ret;
|
|
int i;
|
|
unsigned char *p;
|
|
int rc;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
if (MAX_FBUFF < flen)
|
|
{
|
|
dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, flen, faddr);
|
|
TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
|
|
} else
|
|
{
|
|
object_file_des = FD_INVALID;
|
|
fstr.mvtype = MV_STR;
|
|
fstr.str.addr = faddr;
|
|
fstr.str.len = flen;
|
|
ESTABLISH(source_ch);
|
|
tt_so_do_once = FALSE;
|
|
for (i = 0 ; ; i++)
|
|
{
|
|
plen.p.pint = op_fnzsearch(&fstr, 0, &ret);
|
|
if (!ret.str.len)
|
|
{
|
|
if (!i)
|
|
{
|
|
dec_err(VARLSTCNT(4) ERR_FILENOTFND, 2, fstr.str.len, fstr.str.addr);
|
|
TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
|
|
}
|
|
break;
|
|
}
|
|
assert(ret.mvtype == MV_STR);
|
|
assert(ret.str.len <= MAX_FBUFF);
|
|
source_name_len = ret.str.len;
|
|
memcpy(source_file_name, ret.str.addr, source_name_len);
|
|
source_file_name[source_name_len] = 0;
|
|
p = &source_file_name[plen.p.pblk.b_dir];
|
|
if ((plen.p.pblk.b_dir >= SIZEOF("/dev/") - 1) && !MEMCMP_LIT(source_file_name, "/dev/"))
|
|
tt_so_do_once = TRUE;
|
|
else if (MFtIsReqd && (plen.p.pblk.b_ext != 2 || ('M' != p[plen.p.pblk.b_name + 1]
|
|
&& 'm' != p[plen.p.pblk.b_name + 1])))
|
|
{ /* M filetype is required but not present */
|
|
dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, source_name_len, source_file_name);
|
|
TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
|
|
continue;
|
|
}
|
|
if (compiler_startup())
|
|
TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
|
|
if (FD_INVALID != object_file_des)
|
|
{
|
|
CLOSEFILE_RESET(object_file_des, rc); /* resets "object_file_des" to FD_INVALID */
|
|
if (-1 == rc)
|
|
rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
|
|
}
|
|
if (tt_so_do_once)
|
|
break;
|
|
}
|
|
REVERT;
|
|
}
|
|
}
|
|
|
|
|
|
CONDITION_HANDLER(source_ch)
|
|
{
|
|
int dummy1, dummy2;
|
|
|
|
START_CH;
|
|
if (DUMP)
|
|
{
|
|
NEXTCH;
|
|
}
|
|
zsrch_clr(0);
|
|
TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
|
|
UNWIND(dummy1, dummy2);
|
|
}
|
|
|
|
|
|
bool open_source_file (void)
|
|
{
|
|
mstr fstr;
|
|
int status, n;
|
|
parse_blk pblk;
|
|
char *p, buff[MAX_FBUFF + 1];
|
|
time_t clock;
|
|
struct stat statbuf;
|
|
mval val;
|
|
mval pars;
|
|
unsigned short clen;
|
|
|
|
memset(&pblk, 0, SIZEOF(pblk));
|
|
pblk.buffer = buff;
|
|
pblk.buff_size = MAX_FBUFF;
|
|
pblk.fop = F_SYNTAXO;
|
|
fstr.addr = (char *)source_file_name;
|
|
fstr.len = source_name_len;
|
|
status = parse_file(&fstr, &pblk);
|
|
if (!(status & 1))
|
|
rts_error(VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status);
|
|
pars.mvtype = MV_STR;
|
|
pars.str.len = SIZEOF(open_params_list);
|
|
pars.str.addr = (char *)open_params_list;
|
|
val.mvtype = MV_STR;
|
|
val.str.len = source_name_len;
|
|
val.str.addr = (char *)source_file_name;
|
|
op_open(&val, &pars, 0, 0);
|
|
dev_in_use = io_curr_device; /* save list file info in use if it is opened */
|
|
op_use(&val, &pars);
|
|
compile_src_dev = io_curr_device;
|
|
if (tt_so_do_once)
|
|
{
|
|
clock = time(0);
|
|
p = "MDEFAULT";
|
|
n = STR_LIT_LEN("MDEFAULT");
|
|
} else
|
|
{
|
|
STAT_FILE((char *)source_file_name, &statbuf, status);
|
|
assert(status == 0);
|
|
clock = statbuf.st_mtime;
|
|
p = pblk.l_name;
|
|
n = pblk.b_name;
|
|
if (n > MAX_MIDENT_LEN)
|
|
n = MAX_MIDENT_LEN;
|
|
}
|
|
/* routine_name is the internal name of the routine (with '%' translated to '_') which can be
|
|
* different from module_name if the NAMEOFRTN parm is used (by trigger compilation code).
|
|
* module_name is the external file name of the module (file.m, file.o).
|
|
* int_module_name is the external symbol that gets exposed (in the GTM context) and is normally
|
|
* the same as module_name except when NAMEOFRTN is specified in which case it takes on the
|
|
* untranslated value of routine_name.
|
|
*/
|
|
memcpy(module_name.addr, p, n);
|
|
module_name.len = n;
|
|
if (!(cmd_qlf.qlf & CQ_NAMEOFRTN))
|
|
{
|
|
memcpy(routine_name.addr, p, n);
|
|
routine_name.len = n;
|
|
} else
|
|
{ /* Routine name specified */
|
|
clen = MAX_MIDENT_LEN;
|
|
cli_get_str("NAMEOFRTN", routine_name.addr, &clen);
|
|
routine_name.len = MIN(clen, MAX_MIDENT_LEN);
|
|
cmd_qlf.qlf &= ~CQ_NAMEOFRTN; /* Can only be used for first module in list */
|
|
}
|
|
memcpy(int_module_name.addr, routine_name.addr, routine_name.len);
|
|
int_module_name.len = routine_name.len;
|
|
if ('_' == *routine_name.addr)
|
|
routine_name.addr[0] = '%';
|
|
GTM_CTIME(p, &clock);
|
|
memcpy(rev_time_buf, p + 4, REV_TIME_BUFF_LEN);
|
|
io_curr_device = dev_in_use; /* set it back to make open_list_file save the device */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return:
|
|
* length of line read
|
|
*/
|
|
int4 read_source_file (void)
|
|
{
|
|
unsigned char *cp;
|
|
mval val;
|
|
|
|
errno = 0;
|
|
tmp_list_dev = io_curr_device;
|
|
io_curr_device = compile_src_dev;
|
|
ESTABLISH_RET(read_source_ch, -1);
|
|
op_readfl(&val, MAX_SRCLINE, NO_M_TIMEOUT);
|
|
REVERT;
|
|
memcpy((char *)source_buffer, val.str.addr, val.str.len);
|
|
cp = source_buffer + val.str.len;
|
|
*cp = '\0';
|
|
/* if there is a newline charactor (end of a line) */
|
|
if (!(io_curr_device.in->dollar.x))
|
|
*(cp+1) = '\0';
|
|
if ( FALSE != io_curr_device.in->dollar.zeof )
|
|
return -1;
|
|
io_curr_device = tmp_list_dev; /* restore list file after reading if it's opened */
|
|
return (int4)(cp - source_buffer); /* var.str.len */
|
|
}
|
|
|
|
CONDITION_HANDLER(read_source_ch)
|
|
{
|
|
int dummy1, dummy2;
|
|
|
|
START_CH;
|
|
UNWIND(dummy1, dummy2);
|
|
}
|
|
|
|
void close_source_file (void)
|
|
{
|
|
mval val;
|
|
mval pars;
|
|
unsigned char no_param;
|
|
|
|
no_param = (unsigned char)iop_eol;
|
|
pars.mvtype = MV_STR;
|
|
pars.str.len = SIZEOF(no_param);
|
|
pars.str.addr = (char *)&no_param;
|
|
val.mvtype = MV_STR;
|
|
val.str.len = source_name_len;
|
|
val.str.addr = (char *)source_file_name;
|
|
op_close(&val, &pars);
|
|
io_curr_device = tmp_list_dev; /* not dev_in_use to make sure list file works */
|
|
return;
|
|
}
|