118 lines
2.6 KiB
C
118 lines
2.6 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2011 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 "gtm_string.h"
|
|
|
|
#include "stringpool.h"
|
|
#include "io.h"
|
|
#include <stdarg.h>
|
|
#include "op.h"
|
|
|
|
#define LIMITCHECK(x, xmax) \
|
|
if ((x) > (xmax)) \
|
|
{ \
|
|
overflow = TRUE; \
|
|
break; \
|
|
}
|
|
|
|
GBLREF spdesc stringpool;
|
|
GBLREF io_pair io_curr_device;
|
|
|
|
error_def(ERR_CTLMNEMAXLEN);
|
|
|
|
void op_iocontrol(UNIX_ONLY_COMMA(int4 n) mval *vparg, ...)
|
|
{
|
|
va_list var;
|
|
mval *vp;
|
|
VMS_ONLY(int n;)
|
|
int count, m;
|
|
unsigned char *cp, *cq, *cpmax;
|
|
boolean_t overflow;
|
|
int length;
|
|
mstr val;
|
|
|
|
VAR_START(var, vparg);
|
|
VMS_ONLY(va_count(n);)
|
|
assert(0 < n);
|
|
MV_FORCE_STR(vparg);
|
|
for (count = 1; count < n; count++)
|
|
{
|
|
vp = va_arg(var, mval *);
|
|
MV_FORCE_STR(vp);
|
|
}
|
|
va_end(var);
|
|
/* Format of generated argument is:
|
|
* if n=1 KEYWORD
|
|
* if n>1 KEYWORD(PAR1,PAR2,...PARx)
|
|
*/
|
|
VAR_START(var, vparg);
|
|
vp = vparg;
|
|
ENSURE_STP_FREE_SPACE(MAX_DEVCTL_LENGTH + 1); /* Plus 1 to allow for null terminator char sockets need */
|
|
/* Note in this calculation, cpmax is the true maximum value for cp so cp can be equal to but not greater than cpmax */
|
|
cpmax = stringpool.free + MAX_DEVCTL_LENGTH;
|
|
overflow = FALSE;
|
|
for (cp = stringpool.free, count = 0 ; count < n; count++)
|
|
{
|
|
if (0 < count)
|
|
{
|
|
vp = va_arg(var, mval *);
|
|
*cp++ = (1 == count) ? '(' : ',';
|
|
LIMITCHECK(cp, cpmax);
|
|
}
|
|
if (MV_IS_CANONICAL(vp))
|
|
{
|
|
m = (int)vp->str.len;
|
|
LIMITCHECK((cp + m), cpmax); /* Check before move for multiple chars */
|
|
memcpy(cp, vp->str.addr, m);
|
|
cp += m;
|
|
} else
|
|
{
|
|
if (0 < count)
|
|
{
|
|
*cp++ = '"';
|
|
LIMITCHECK(cp, cpmax);
|
|
}
|
|
for (m = 0, cq = (unsigned char *)vp->str.addr, length = (int)vp->str.len; m < length; m++)
|
|
{
|
|
if ('"' == *cq)
|
|
{
|
|
*cp++ = '"';
|
|
LIMITCHECK(cp, cpmax);
|
|
}
|
|
*cp++ = *cq++;
|
|
LIMITCHECK(cp, cpmax);
|
|
}
|
|
if (0 < count)
|
|
{
|
|
*cp++ = '"';
|
|
LIMITCHECK(cp, cpmax);
|
|
}
|
|
}
|
|
}
|
|
va_end(var);
|
|
if ((1 < count) && !overflow)
|
|
{
|
|
*cp++ = ')';
|
|
if (cp > cpmax)
|
|
overflow = TRUE;
|
|
}
|
|
if (overflow)
|
|
rts_error(VARLSTCNT(1) ERR_CTLMNEMAXLEN);
|
|
assert(cp <= cpmax);
|
|
val.len = INTCAST(cp - stringpool.free);
|
|
assert(val.len <= MAX_DEVCTL_LENGTH);
|
|
val.addr = (char *)stringpool.free;
|
|
(*io_curr_device.out->disp_ptr->iocontrol)(&val);
|
|
return;
|
|
}
|