/*

    ========== licence begin  GPL
    Copyright (c) 2005 SAP AG

    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
    of the License, 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 program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

*/
&ifdef DEBUG
&else
#line 85 "vpc31c"
&endif

#include <string.h>
#include <memory.h>
#include "vpc31.h"
#include "gmt90.h"
#include "vpc11c.h"

static const tsp00_Int2 p31outlen = 72;
static tsp00_Int2 p31lastout = 0;
static int p31quostat = 0, p31squstat = 0;
static const char p31delim [] = "\011 !#%^&*()-+=~[]\\|;:'\"{},.<>/?";

#define CVNDEF 32
#define CVNREF 7
#define CDCLGEN 2
#define CPDECL 6

static struct
{
	char *vndef [CVNDEF], *vnref [CVNREF], *dclgen [CDCLGEN],
		*pdecl [CPDECL];
} p31vcode;

tpcCode p31code;

static void p31initvcode (tpc_globals *pc)
{
	int i;
	char **c;

	c = p31vcode.vndef;
	for (i = 0; i < CVNDEF; i++)
		c [i] = "";
	c [0] = "/*VARARGS*/ static void sqlc";
	if (pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_cansi_F > 0)
	{
		c [ 1] = " (long va1ix, long cnt, char* p)";
		c [13] = " (long va1ix, long va2ix, long va3ix, long cnt,"
			" char* p)";
		c [22] = " (long va1ix, long va2ix, long va3ix, long cnt,"
			" void *p)";
		c [23] = " (long va1ix, long va1ix1, void *p)";
	}
	else
	{
		c [ 1] = " (va1ix, cnt, p)";
		c [ 2] = "long va1ix, cnt; char* p;";
		c [13] = " (va1ix, va2ix, va3ix, cnt, p)";
		c [14] = "long va1ix, va2ix, va3ix, cnt; char* p;";
		c [22] = c [13];
		c [23] = " (va1ix, va1ix1, p)";
		c [24] = "long va1ix, va2ix, va3ix, cnt; double *p;";
		c [25] = "long va1ix, va1ix1; double *p;";
	}
	c [ 3] = "q";
	c [ 4] = "{";
	c [ 5] = "long i; char* pi = p;";
	c [ 6] = "for (i = 0; i < cnt; i++) {";
	c [ 7] = "va1ix = va1ix +";
	c [ 8] = "sqlva1 [va1ix + i - 1].sc.va1indva2 = (short) va2ix;";
	c [ 9] = "sqlva1 [va1ix + i - 1].sc.va1indva3 = (short) va3ix;";
	c [10] = "sqlva1 [va1ix + i - 1].sc.va1addr = pi, pi += sizeof (q);";
	c [11] = "}";
	c [12] = "sqlva1 [va1ix + i - 1].sc.va1indi = SQLVASC;";
	c [15] = "sqlva1 [va1ix + i - 1].cm.va1offs = (long)((char*)pi-(char*)0), pi += sizeof (q);";
	c [17] = "struct sqlp";
	c [19] = "/*VARARGS*/ static void sqlv";
	c [20] = "o = pi + ((char*) &q.";
	c [21] = " - (char*) &q);";
	c [26] = "sqlva1 [va1ix + i - 1].sc.va1indi = SQLVACM;";
	c [27] = "long i; char *pi = (char*) p;";
	c [28] = "pi += sizeof (q);";
	c [29] = "char* o;";
	c [30] = "o = pi + ((char*) q.";
	c [31] = "typedef";

	c = p31vcode.vnref;
	for (i = 0; i < CVNREF; i++)
		c [i] = "";
	c [ 0] = "sqlc";
	c [ 1] = "sqlv";
	c [ 2] = "sqls(sqlva1,";
	c [ 3] = "sqlr(sqlva1,";
	c [ 4] = "(va1ix,";
	c [ 5] = "(";
	c [ 6] = ",(long)sqlsizeofR(";

	c = p31vcode.dclgen;
	for (i = 0; i < CDCLGEN; i++)
		c [i] = "";
	c [ 0] = "typedef ";
	c [ 1] = "struct ";

	c = p31vcode.pdecl;
	for (i = 0; i < CPDECL; i++)
		c [i] = "";
	c [ 0] = "struct";
	c [ 1] = "{";
	c [ 2] = "} ";
	c [ 3] = "VARCHD(sqlp";
	c [ 4] = "VARCHD1(sqlp";
	c [ 5] = "VARCHD4(sqlp";
}

void p31initcode (tpc_globals *pc)
{
	static const int MAXCODE = sizeof (p31code) / sizeof (char*);
	static char EMPTY [] = "";
	int i;
	char **c;

	c = (char**) &p31code;
	for (i = 0; i < MAXCODE; i++)
		c [i] = EMPTY;

	c = p31code.dynparameter;
	c [0] = (pc->sqlca.sqldbmode == CPR_KIND_INTERNAL) ?
		"#define sql_sqldb 0" :
		(pc->sqlca.sqldbmode == CPR_KIND_DB2) ?
		"#define sql_db2 0" :
		(pc->sqlca.sqldbmode == CPR_KIND_ORACLE ||
		pc->sqlca.sqldbmode ==  CPR_KIND_SAPR3)  ?
		"#define sql_oracle 0" :
		"#define sql_default 0";
	if (pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_extern_F == 0)
	{
		c [1] = "#define sqlcap sqlca";
		c [2] = "#define sqlextern 0";
	}
	else
		c [1] = "#define sqlcap (&sqlca)";
   	if (pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_unicode_F)
		c [3] = "#define SAPDBwithUNICODE";
	c [ 4] = "#define sqlpamax ";
	c [ 5] = "#define sqlsamax ";
	c [ 6] = "#define sqlkamax ";
	c [ 7] = "#define sqlprmax ";
	c [ 8] = "#define sqlstmax ";
	c [ 9] = "#define sqlstm1 ";
	c [10] = "#define sqldimax ";
	c [11] = "#define sqlnamax ";
	c [12] = "#define sqlopmax ";
	c [13] = "#define sqldamax ";
	c [14] = "#define sqlva1mx ";
	c [15] = "#define sqlva2mx ";
	c [16] = "#define sqlva3mx ";
	c [17] = "";
	c [18] = "";
	c [19] = "#define sqlfamx ";
	c [20] = "#define sqlfnmx ";
	c [21] = "#define sqlatmx ";
	c [22] = "#define sqlcumx ";
&if $OS = VMS
	c [23] = "#include \"ccsqlinc\"";
&else
&if $OS = BS2000
	c [23] = "#include <ccsqlinc>";
&else
	c [23] = "#include <cpc.h>";
&endif
&endif
&ifdef DEBUG
&else
#line 247 "vpc31c"
&endif

	c = p31code.bsqlstart;
	c [ 0] = (pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_extern_F == 0) ?
		"static void sqlstart(sqlcap) sqlcatype *sqlcap;{" :
		"static void sqlstart() {";
	c [ 1] = "SQLCPCCHECK(sqlcap,sqlxap,sqlstcip,sqlextip,";
	c [ 2] = "if(sqlxap->xainit == 0) {";
	c [ 3] = "sqlxap->sqlv1p = sqlva1; sqlxap->sqlv1e = sqlva1+sqlva1mx;";
	c [ 4] = "sqlxap->sqlv2p = sqlva2; sqlxap->sqlv2e = sqlva2+sqlva2mx;";
	c [ 5] = "sqlxap->sqlv3p = sqlva3; sqlxap->sqlv3e = sqlva3+sqlva3mx;";
	c [ 6] = "sqlpa = sqlcdynp(SQLENUMA(sqlxa, sqlpap), sqlxap, sqlpamax);";
	c [ 7] = "sqlka = sqlcdynp(SQLENUMA(sqlxa, sqlkap), sqlxap, sqlkamax);";
	c [ 8] = "sqlpr = sqlcdynp(SQLENUMA(sqlxa, sqlprp), sqlxap, sqlprmax);";
	c [ 9] = "sqlst = sqlcdynp(SQLENUMA(sqlxa, sqlstp), sqlxap, sqlstmax);";
	c [10] = "sqlfa = sqlcdynp(SQLENUMA(sqlxa, sqlfap), sqlxap, sqlfamx);";
	c [13] = "";
	c [14] = "";
	c [15] = "";
	c [16] = "";
	c [17] = "";
	if (pc->sqlca.sqldbmode == CPR_KIND_INTERNAL)
		c [18] = "sqccdam(sqlcap,&sqlda);";
	c [19] = "sqlfn = sqlcdynp(SQLENUMA(sqlxa, sqlfnp), sqlxap, sqlfnmx);";
	c [20] = "sqlor = sqlcdynp(SQLENUMA(sqlxa, sqlorp), sqlxap, sqlkamax);";
	c [21] = "sqlat = sqlcdynp(SQLENUMA(sqlxa, sqlatp), sqlxap, sqlatmx);";
	c [22] = "sqlcu = sqlcdynp(SQLENUMA(sqlxa, sqlcup), sqlxap, sqlcumx);";

	c = p31code.esqlstart;
	c [0] = "sqlcisol(sqlcap, ";
	c [1] = "sqlCPCEndInit(sqlcap, sqlxap, sqlctoR(\"@(#)";
	c [2] = "}}";

	c = p31code.sqlstart;
	c [ 0] = (pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_extern_F == 0) ?
		"{ sqlstart(sqlcap);" : "{ sqlstart();";

	c = p31code.whenever;
	c [0] = "} else ";
	c [1] = "sqccstp(sqlcap,sqlxap);";
	c [2] = "exit(0);";
	c [3] = "if(sqlcap->sqlcode == 0) {";
	c [4] = (pc->sqlca.sqldbmode == CPR_KIND_ORACLE ||
		pc->sqlca.sqldbmode ==  CPR_KIND_SAPR3)  ?
		"if(sqlcap->sqlwarn [0] == 'W') {" :
		"if(sqlcap->sqlwarn0 == 'W') {";
	c [5] = "}";
	c [6] = "if(sqlcap->sqlcode == 100 || sqlcap->sqlcode == 1403) {";
	c [7] = "if(sqlcap->sqlcode > 100 && sqlcap->sqlcode != 1403) {";
	c [8] = "if(sqlcap->sqlcode <  0) {";
	c [9] = c [5];

	c = p31code.va2bind;
	c [0] = "sqccv2b(sqlva2,";

	c = p31code.va3bind;
	c [0] = "sqccv3b(sqlva3,";

	c = p31code.cabind;
	c [0] = "sqcccab(sqlcap,";

	c = p31code.xabind;
	c [0] = "sqccxab(sqlxap,";

	c = p31code.pabind;
	c [0] = "sqccpab(sqlpa,";

	c = p31code.kabind;
	c [0] = "sqcckab(sqlor,sqlka,";

	c = p31code.prbind;
	c [0] = "sqlCPCPrBind(sqlpr,";

	c = p31code.stbind;
	c [0] = "sqlCPCStBind(sqlcap, sqlxap,";
	c [1] = "sqlCPCLocalBind(sqlcap, sqlxap,";

	c = p31code.sdbind;
	c [0] = "sqccsdb(sqlsd,";

	c = p31code.atbind;
	c [0] = "sqccatb(sqlat,";

	c = p31code.cancel;
	c [0] = "sqcccan(sqlcap,sqlxap,";

	c = p31code.version;
	c [0] = "sqccver(sqlcap,sqlxap,";

	c = p31code.fnbind;
	c [0] = "sqccfnb(sqlfn,";

	c = p31code.daaddr;
	c [0] = "sqccdaa(sqlcap,&sqlda);";
	c [1] = "sqccdaa(sqlcap,";

	c = p31code.sqlstm;
	c [0] = "sqlCPCTryExecute(sqlcap,sqlxap,";
	c [2] = "if(sqlxap->xacmdinit == sqlIsTrue) {";
	c [3] = "sqlCPCExecute(sqlcap,sqlxap, ";

	c = p31code.trace;
	c [0] = "sqcctrs(sqlcap,";
	c [1] = "}";

	c = p31code.trcline;
	c [0] = "sqlCPCTraceLine(sqlcap,sqlxap,";
	c [1] = "}";

	c = p31code.Option;
	c [0] = "sqlCPCOption(sqlcap,sqlxap,";
	c [1] = "}";

	c = p31code.modtrace;
	c [0] = "sqccmts(sqlcap,";

	c = p31code.macro;
	c [0] = "sqccmab(sqlcap,sqlxap,";
	c [1] = "}";

	c = p31code.prepare;
	c [0] = "sqlCPCPrepare(sqlcap,sqlxap,";

	c = p31code.describe;
	c [0] = "sqlCPCDescribe(sqlcap,sqlxap,";

	c = p31code.open;
	c [0] = "sqlCPCOpen(sqlcap,sqlxap,";

	c = p31code.declare;
	c [0] = "sqlCPCDeclare(sqlcap,sqlxap,";

	c = p31code.immediateexecute;
	c [0] = "sqlCPCExecDirect(sqlcap,sqlxap,";

	c = p31code.command;
	c [0] = "sqcccmd(sqlcap,sqlxap,";

	c = p31code.dbsname;
	c [0] = "sqlCPCGaBind(sqlcap,sqlxap,";
	c [1] = "}";

	c = p31code.nolog;
	c [0] = "sqlCPCNoLog(sqlcap,sqlxap,";
	c [1] = "}";

	c = p31code.reconnect;
	c [0] = "sqccrcn(sqlcap,";

	c = p31code.exit;
	c [0] = "sqccexi(sqlcap,sqlxap);";

	p31initvcode (pc);
}

static void p31quotest (tpc_globals *pc)
{
	char *tstchr = pc->pcOutLine.lline;
	tsp00_Int2 *len = &pc->pcOutLine.llen;
	char *endchr = pc->pcOutLine.lline + *len - 1;
	int esc = 0;

	for (; tstchr <= endchr; tstchr++)
		if (esc)
			esc = 0;
		else if (*tstchr == CPR_BACKSLASH)
			esc = 1;
		else if (*tstchr == CPR_DQUOSYM)
		{
			if (!p31squstat)
				p31quostat = !p31quostat;
		}
		else if (*tstchr == CPR_QUOTSYM)
		{
			if (!p31quostat)
				p31squstat = !p31squstat;
		}
	if (p31quostat || p31squstat)
	{
		if (*len > 0)
		{
			if (p31quostat && *endchr == CPR_DQUOSYM)
				p31quostat = 0;
			else if (p31squstat && *endchr == CPR_QUOTSYM)
				p31squstat = 0;
			if (*len > 1)
				do
					--endchr, --(*len);
				while (*len > 1 && *endchr == CPR_BACKSLASH);
			if (*endchr == CPR_BACKSLASH)
				*len = 2;
		}
		*(endchr + 1) = CPR_BACKSLASH;
	}
}

void p31outcnt (tpc_globals *pc)
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	char *partbuf = pc->pccmdpart.partbufp;
	char *line = pc->pcOutLine.lline;
	tsp00_Int2 *len = &pc->pcOutLine.llen;

	if (*syposacc <= 0)
		return;
	partbuf [pc->pccmdpart.part1len - 1] = ' ';
	while (*syposacc < pc->pccmdpart.part1len)
	{
		char *firstchr = partbuf + *syposacc - 1;
		if (pc->pccmdpart.part1len - *syposacc > p31outlen - p31lastout)
		{
			char *tstchr = firstchr + p31outlen - p31lastout;
			*len = p31outlen;
			while (strchr (p31delim, *tstchr--) == 0 &&
				*len > p31lastout)
				(*len)--;
			if (*len == 0)
				*len = p31outlen;
			memcpy (line + p31lastout, firstchr,
				*len - p31lastout);
			p31quotest (pc);
		}
		else
		{
			*len = (tsp00_Int2) (pc->pccmdpart.part1len -
				*syposacc + p31lastout);
			memcpy (line + p31lastout, firstchr,
				*len - p31lastout);
		}
		*syposacc += *len - p31lastout;
		p31lastout = (tsp00_Int2)
			((*syposacc < pc->pccmdpart.part1len) ? 0 : *len);
		if (p31lastout == 0)
		{
			char *tstchr;
			if (p31quostat || p31squstat)
				(*len)++;
			tstchr = line + *len - 1;
			while (*len > 1 && *tstchr-- == ' ')
				(*len)--;
			p11vfwrite (pc, pc->pcCodeInd, line, *len);
		}
	}
}

void p31quocnt (tpc_globals *pc)
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	char *partbuf = pc->pccmdpart.partbufp;
	char *firstchr = partbuf + *syposacc - 1;
	char *line = pc->pcOutLine.lline;
	tsp00_Int2 *len = &pc->pcOutLine.llen;
	tsp00_Int2 lpos = p31lastout + (tsp00_Int2) 1, lend = lpos;

	if (*syposacc <= 0)
		return;
	while (*syposacc < pc->pccmdpart.part1len)
	{
		tsp00_Int4 le;
		*len = ((le = pc->pccmdpart.part1len - *syposacc + p31lastout)
			> p31outlen) ? p31outlen : (tsp00_Int2) le;
		if (lpos > lend)
			lpos = 1;
		lend = *len;
		while (lpos <= lend)
		{
			if ((*firstchr == CPR_DQUOSYM ||
				*firstchr == CPR_BACKSLASH) && lpos< p31outlen)
			{
				line [lpos++ - 1] = CPR_BACKSLASH;
				if (lpos == p31outlen)
					lend = lpos - (tsp00_Int2) 1;
				else
				{
					line [lpos++ -1] = *firstchr++;
					(*syposacc)++;
					if (lend < p31outlen)
						lend++;
					if (lpos > lend && *syposacc <
						pc->pccmdpart.part1len)
					{
						line [lpos - 1]= CPR_BACKSLASH;
						lend = lpos++;
					}
				}
			}
			else
			{
				if (lpos == p31outlen)
					line [lpos - 1] = CPR_BACKSLASH;
				else
				{
					line [lpos - 1] = *firstchr++;
					(*syposacc)++;
				}
				lpos++;
			}
		}
		*len = lend;
		p31lastout = (tsp00_Int2)
			((*syposacc < pc->pccmdpart.part1len) ? 0 : *len);
		if (p31lastout == 0)
		{
			char *tstchr = line + *len - 1;
			p31quostat = 1;
			while (*tstchr-- == ' ' && *len > 1)
				(*len)--;
			p11vfwrite (pc, pc->pcCodeInd, line, *len);
		}
	}
}

void p31outstmt (tpc_globals *pc)
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	char *partbuf = pc->pccmdpart.partbufp;
	char *firstchr = partbuf + *syposacc - 1;
	char *line = pc->pcOutLine.lline;
	tsp00_Int2 *len = &pc->pcOutLine.llen;

	if (*syposacc <= 0)
		return;
	if (p31lastout > 0)
	{
		char *tstchr = line + p31lastout - 1;
		*len = p31lastout;
		p31quotest (pc);
		while (*tstchr-- == ' ' && *len > 1)
			(*len)--;
		p11vfwrite (pc, pc->pcCodeInd, line, *len);
		p31lastout = 0;
	}
	partbuf [pc->pccmdpart.part1len - 1] = ' ';
	if (pc->pccmdpart.part1len - *syposacc >= p31outlen)
	{
		char *tstchr = firstchr + p31outlen;
		*len = p31outlen;
		while (strchr (p31delim, *tstchr--) == 0 && *len > 0)
			(*len)--;
		if (*len == 0)
			*len = p31outlen;
		memcpy (line, firstchr, *len);
		p31quotest (pc);
		p31lastout = 0;
	}
	else
	{
		*len = (tsp00_Int2) (pc->pccmdpart.part1len - *syposacc);
		memcpy (line, firstchr, *len);
		p31lastout = *len;
	}
	if (*len > 0)
	{
		*syposacc += *len;
		if (p31lastout == 0)
		{
			char *tstchr;
			if (p31quostat || p31squstat)
				(*len)++;
			tstchr = line + *len - 1;
			while (*tstchr-- == ' ' && *len > 1)
				(*len)--;
			p11vfwrite (pc, pc->pcCodeInd, line, *len);
			p31outcnt (pc);
		}
	}
}

void p31vnref (tpc_globals *pc, tsp00_Int4 varix, tsp00_Int4 typix, tsp00_Int4 va1ix,
	int offs, int plen, char *pnam)
{
	static const int srcc1 = 0, srcv1 = 1, srcs1 = 2, srcr1 = 3,
		srcc2 = 4, src2 = 5, srcs3 = 6;
	const char *cast = "(long)";
	char **code = p31vcode.vnref;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp + *part1len;
	tpc_symtab *st = &pc->pcSymtab;
	tpc_varent *vt = st->vartablep + varix - 1;
	tpc_typent *tt = st->typtablep + typix - 1;
	sqlva1en *v1 = pc->sqlxa.sqlv1p + va1ix - 1;
	tsp00_Int2 cnt;
	tsp00_Int4 savlen;
	int npar, src;
	tsp00_Int4 par [4];

	savlen = *part1len;
	*syposacc = savlen + 1;
	if (plen == 0)
	{
		strcpy (partbuf, code [srcc1]);
		cnt = 1;
		while (tt->ar.tyIndi == CPR_VARRAY)
		{
			cnt *= tt->ar.tyDim;
			typix = tt->ar.tyTypIx;
			tt = st->typtablep + typix - 1;
		}
		if (vt->vastrix > 0)
		{
			npar = 0;
			src = srcc2;
		}
		else
		{
			npar = 1;
			par [0] = va1ix;
			src = src2;
		}
		if (tt->st.tyIndi == CPR_VSTRUCT)
			npar++;
		else
		{
			npar += 3;
			par [npar - 3] = v1->cm.va1indva2;
			par [npar - 2] = v1->cm.va1indva3;
		}
		par [npar - 1] = cnt;
		p13intcat (partbuf, "", 1, &typix);
		strcat (partbuf, code [src]);
		p13intcat (partbuf, cast, npar, par);
		if (offs)
			strcat (partbuf, ",o");
		else
			strcat (partbuf, ",0L");
	}
	else if (tt->sc.tyPtr > 0)
	{
		if (tt->st.tyIndi == CPR_VSTRUCT || tt->ar.tyIndi == CPR_VARRAY)
		{
			npar = 3;
			par [0] = v1->pt.va1ix;
			par [1] = pc->sqlxa.sqlv1p [par [0] - 1].st.va1ix;
			par [2] = vt->vacnt;
			*part1len = savlen;
			p31vnref (pc, varix, typix, par [1], 0, 0, pnam);
			strcpy (partbuf, code [srcs1]);
			p13intcat (partbuf, cast, npar, par);
			strcat (partbuf, code [srcs3]);
			strcat (partbuf, "*");
			strncat (partbuf, pnam, plen);
			strcat (partbuf, "),");
			strncat (partbuf, pnam, plen);
			strcat (partbuf, ");");
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*syposacc = savlen + 1;
		}
		else
		{
			*part1len = savlen;
			p31vnref (pc, varix, typix, v1->pt.va1ix, 0, 0, pnam);
		}
		npar = 2;
		par [0] = va1ix;
		par [1] = v1->pt.va1ix;
		strcpy (partbuf, code [srcr1]);
		p13intcat (partbuf, cast, npar, par);
		strcat (partbuf, ",&");
		strncat (partbuf, pnam, plen);
	}
	else if (tt->st.tyIndi == CPR_VSTRUCT || tt->ar.tyIndi == CPR_VARRAY)
	{
		npar = 3;
		par [0] = va1ix;
		par [1] = v1->st.va1ix;
		par [2] = vt->vacnt;
		*part1len = savlen;
		p31vnref (pc, varix, typix, par [1], 0, 0, pnam);
		strcpy (partbuf, code [srcs1]);
		p13intcat (partbuf, cast, npar, par);
		strcat (partbuf, code [srcs3]);
		strncat (partbuf, pnam, plen);
		strcat (partbuf, "),");
		if (tt->ar.tyIndi != CPR_VARRAY)
			strcat (partbuf, "&");
		strncat (partbuf, pnam, plen);
	}
	else
	{
		strcpy (partbuf, code [srcv1]);
		npar = 4;
		par [0] = va1ix;
		par [1] = v1->cm.va1indva2;
		par [2] = v1->cm.va1indva3;
		par [3] = 1;
		p13intcat (partbuf, "", 1, &typix);
		strcat (partbuf, code [src2]);
		p13intcat (partbuf, cast, npar, par);
		strcat (partbuf, ",");
		if (tt->sc.tyIndi != CPR_VCHARC && tt->sc.tyIndi != CPR_VCHARZ
		    && tt->sc.tyIndi != CPR_VRAW
			&& tt->sc.tyIndi != CPR_VFILEC &&
			tt->sc.tyIndi != CPR_VUNICODEC)
			strcat (partbuf, "&");
		strncat (partbuf, pnam, plen);
	}
	strcat (partbuf, ");");
	*part1len = strlen (partbuf) + *syposacc;
	p31outstmt (pc);
	p31outstmt (pc);
	*part1len = savlen;
	*syposacc = savlen + 1;
}

static void p31typcpy (char *buf, int tyindi, tsp00_Int4 tylen)
{
	switch (tyindi)
	{
&	if $OS not in [WIN32]
&	ifdef BIT64
	case CPR_VINT:
		strcpy (buf, "int");
		break;
	case CPR_VUNSIGNED:
		strcpy (buf, "unsigned int");
		break;
&	endif
&	endif
&	ifdef DEBUG
&	else
#line 760 "vpc31c"
&	endif
	case CPR_VLONG:
		strcpy (buf, "long");
		break;
	case CPR_VSHORT:
		strcpy (buf, "short");
		break;
	case CPR_VUNSLONG:
		strcpy (buf, "unsigned long");
		break;
	case CPR_VUNSSHORT:
		strcpy (buf, "unsigned short");
		break;
	case CPR_VDOUBLE:
		strcpy (buf, "double");
		break;
	case CPR_VFLOAT:
		strcpy (buf, "float");
		break;
	case CPR_VCHAR:
	case CPR_VCHARC:
	case CPR_VCHARZ:
	case CPR_VFILEC:
	case CPR_VRAW:
	case CPR_VUNICODE:
	case CPR_VUNICODEC:
		strcpy (buf, "char");
		break;
	case CPR_VDECIMAL:
		strcpy (buf, "decimal");
		p13intcat (buf, "", 1, &tylen);
		break;
	case CPR_VSTRING:
		strcpy (buf, "VARCHS(");
		p13intcat (buf, "", 1, &tylen);
		strcat (buf, ")");
		break;
	case CPR_VSTRING1:
		strcpy (buf, "VARCHS1(");
		p13intcat (buf, "", 1, &tylen);
		strcat (buf, ")");
		break;
	case CPR_VSTRING4:
		strcpy (buf, "VARCHS4(");
		p13intcat (buf, "", 1, &tylen);
		strcat (buf, ")");
		break;
	case CPR_VABAPHANDLE:
		strcpy (buf, "SQLStreamDesc");
		break;
	case CPR_VLONGDESC:
		strcpy (buf, "SQLLongDesc");
		break;
        case CPR_VUCS2:
                strcpy (buf, "SQLUCS2");
                break;
        case CPR_VUTF16:
                strcpy (buf, "SQLUTF16");
                break;
	default:
		strcpy (buf, "UNKNOWN");
	}
	strcat (buf, " ");
}

static void p31pdecl (tpc_globals *pc, tsp00_Int4 typix, tsp00_Int4 savlen,
	tsp00_Int2 *tindi, tsp00_Int4 *tlen)
{
	static unsigned int lev = 0;
	static const int src1 = 0, src2 = 1, src3 = 2, src4 = 3, src5 = 4,
		src6 = 5;
	char **code = p31vcode.pdecl;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp + savlen;
	tpc_symtab *st = &pc->pcSymtab;
	tpc_typent *tt = st->typtablep + typix - 1;
	tsp00_Int2 i;
	int srcv;

	lev++;
	*tindi = tt->sc.tyIndi;
	*tlen = (*tindi == CPR_VCHARC || *tindi == CPR_VCHARZ ||
		 *tindi == CPR_VRAW ||
		tt->sc.tyIndi == CPR_VFILEC || tt->sc.tyIndi == CPR_VUNICODEC)
		? tt->sc.tySize :
		(*tindi == CPR_VSTRING) ? (srcv = src4, tt->sc.tySize - 2) :
		(*tindi == CPR_VSTRING1) ? (srcv = src5, tt->sc.tySize - 1) :
		(*tindi == CPR_VSTRING4) ? (srcv = src6, tt->sc.tySize - 4) :
		(*tindi != CPR_VARRAY && *tindi != CPR_VSTRUCT) ?
		tt->sc.tyDigit : 0;
	*syposacc = savlen + 1;
	if (*tindi == CPR_VSTRUCT)
	{
		strcpy (partbuf, code [src2]);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		p31outstmt (pc);
		for (i = 0; i < tt->st.tyCmCnt; i++)
		{
			tsp00_Int2 varix =
				pc->pcSymtab.cmpindexp[tt->st.tyCmpIx + i -1];
			tpc_varent *vt = pc->pcSymtab.vartablep + varix - 1;
			tsp00_Int2 typix1 = vt->vatypix;
			tsp00_Int2 typix2 = typix1;
			tpc_typent *tt1 = st->typtablep + typix1 - 1;
			tpc_typent *tt2 = tt1;
			tsp00_Int2 tindi1;
			tsp00_Int4 tlen1;

			while (tt2->ar.tyIndi == CPR_VARRAY)
			{
				typix2 = tt2->ar.tyTypIx;
				tt2 = st->typtablep + typix2 - 1;
			}
			if (tt2->st.tyIndi == CPR_VSTRUCT)
			{
				*syposacc = savlen + 1;
				strcpy (partbuf, code [src1]);
				*part1len = strlen (partbuf) + *syposacc;
				p31outstmt (pc);
			}
			p31pdecl (pc, typix2, savlen, &tindi1, &tlen1);
			if (tt2->sc.tyPtr > 0)
				strcat (partbuf, "*");
			strncat (partbuf, (const char *) vt->vaname,
				 vt->vanaml);
			strcat (partbuf, " ");
			while (tt1->ar.tyIndi == CPR_VARRAY)
			{
				strcat (partbuf, "[");
				p13intcat (partbuf, "", 1, &tt1->ar.tyDim);
				strcat (partbuf, "]");
				typix1 = tt1->ar.tyTypIx;
				tt1 = st->typtablep + typix1 - 1;
			}
			if ((tindi1 == CPR_VCHARC || tindi1 == CPR_VCHARZ ||
			      tindi1 == CPR_VRAW ||
				tt->sc.tyIndi == CPR_VFILEC ||
				tt->sc.tyIndi == CPR_VUNICODEC)
				&& tt2->sc.tyPtr == 0)
			{
				strcat (partbuf, "[");
				p13intcat (partbuf, "", 1, &tlen1);
				strcat (partbuf, "]");
			}
			strcat (partbuf, ";");
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			p31outstmt (pc);
		}
		*syposacc = savlen + 1;
		strcpy (partbuf, code [src3]);
	}
	else if (lev == 1 && (*tindi == CPR_VSTRING || *tindi == CPR_VSTRING1
		|| *tindi == CPR_VSTRING4))
	{
		strcpy (partbuf, code [srcv]);
		p13intcat (partbuf, "", 1, &typix);
		strcat (partbuf, ",");
		if (tt->sc.tySize == 0)
			strcat (partbuf, "1");
		else
			p13intcat (partbuf, "", 1, tlen);
		strcat (partbuf, ") ");
	}
	else
		p31typcpy (partbuf, *tindi, *tlen);
	lev--;
}

void p31vndef (tpc_globals *pc, tsp00_Int4 typix)
{
	static const int srcc1 = 0, srcs2 = 1, srcc2 = 13, srcs3 = 2,
		srcc3 = 14, srcv1 = 19, srcv2 = 22, srcv3 = 24, src4 = 4,
		srcs5 = 17, srcs6 = 7, srcv6 = 3, srcv7 = 31;
	const char *cast = "(long)";
	char **code = p31vcode.vndef;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp + *part1len;
	tpc_symtab *st = &pc->pcSymtab;
	tpc_typent *tt = st->typtablep + typix - 1;
	int i, src [8];
	const int nsrc = sizeof (src) / sizeof (int);
	tsp00_Int2 ref, tindi;
	tsp00_Int4 savlen, savacc;
	tsp00_Int4 tlen;

	ref = (tsp00_Int2) (tt->sc.tyRef % 4);
	if (ref == 0)
		return;

	src [1] = 6;
	src [6] = 11;
	src [7] = 11;
	tt->sc.tyRef += 3 * ref;
	savlen = *part1len;
	savacc = *syposacc;
	*syposacc = savlen + 1;
	if (tt->st.tyIndi == CPR_VSTRUCT)
	{
		src [0] = 5;
		src [2] = 29;
		src [4] = 21;
		src [5] = 28;
		strcpy (partbuf, code [srcc1]);
		p13intcat (partbuf, "", 1, &typix);
		strcat (partbuf, code [srcs2]);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		*syposacc = savlen + 1;
		strcpy (partbuf, code [srcs3]);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		*syposacc = savlen + 1;
		strcpy (partbuf, code [src4]);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		*syposacc = savlen + 1;
		strcpy (partbuf, code [srcs5]);
		p13intcat (partbuf, "", 1, &typix);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		p31pdecl (pc, typix, savlen, &tindi, &tlen);
		strcat (partbuf, code [srcv6]);
		strcat (partbuf, ";");
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		for (i = 0; i < 3; i++)
		{
			*syposacc = savlen + 1;
			strcpy (partbuf, code [src [i]]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
		}
		for (i = 0; i < tt->st.tyCmCnt; i++)
		{
			tsp00_Int2 varix =
				pc->pcSymtab.cmpindexp[tt->st.tyCmpIx + i -1];
			tpc_varent *vt = pc->pcSymtab.vartablep + varix - 1;
			tpc_typent *tt = st->typtablep + vt->vatypix - 1;
			tsp00_Int4 cnt = vt->vacnt;

			src [3] = (tt->ar.tyIndi == CPR_VARRAY ||
				tt->sc.tyIndi == CPR_VCHARC ||
				tt->sc.tyIndi == CPR_VCHARZ ||
				tt->sc.tyIndi == CPR_VRAW ||
				tt->sc.tyIndi == CPR_VFILEC ||
				tt->sc.tyIndi == CPR_VUNICODEC) ? 30 : 20;
			*syposacc = savlen + 1;
			strcpy (partbuf, code [src [3]]);
			strncat (partbuf, (const char *) vt->vaname,
				 vt->vanaml);
			strcat (partbuf, code [src [4]]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*part1len = savlen;
			p31vnref (pc, varix, vt->vatypix, vt->vasqlix, 1, 0,
				"");
			*syposacc = savlen + 1;
			strcpy (partbuf, code [srcs6]);
			p13intcat (partbuf, "", 1, &cnt);
			strcat (partbuf, ";");
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
		}
		for (i = 5; i < 8; i++)
		{
			*syposacc = savlen + 1;
			strcpy (partbuf, code [src [i]]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
		}
		p31outstmt (pc);
	}
	else
	{
		src [3] = 8;
		src [4] = 9;
		if (ref % 2 == 1)
		{
			src [0] = 27;
			src [2] = 12;
			src [5] = 10;
			*syposacc = savlen + 1;
			strcpy (partbuf, code [srcv1]);
			p13intcat (partbuf, "", 1, &typix);
			strcat (partbuf, code [srcv2]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*syposacc = savlen + 1;
			strcpy (partbuf, code [srcv3]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*syposacc = savlen + 1;
			strcpy (partbuf, code [src4]);
			strcat (partbuf, code [srcv7]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			p31pdecl (pc, typix, savlen, &tindi, &tlen);
			strcat (partbuf, code [srcv6]);
			if ((tindi == CPR_VCHARC || tindi == CPR_VCHARZ ||
			     tindi == CPR_VRAW ||
				tt->sc.tyIndi == CPR_VFILEC ||
				tt->sc.tyIndi == CPR_VUNICODEC)
				&& tt->sc.tyPtr == 0)
			{
				strcat (partbuf, "[");
				p13intcat (partbuf, "", 1, &tlen);
				strcat (partbuf, "]");
			}
			strcat (partbuf, ";");
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			for (i = 0; i < nsrc; i++)
			{
				*syposacc = savlen + 1;
				strcpy (partbuf, code [src [i]]);
				*part1len = strlen (partbuf) + *syposacc;
				p31outstmt (pc);
			}
			p31outstmt (pc);
		}
		if (ref / 2 == 1)
		{
			src [0] =  5;
			src [2] = 26;
			src [5] = 15;
			*syposacc = savlen + 1;
			strcpy (partbuf, code [srcc1]);
			p13intcat (partbuf, "", 1, &typix);
			strcat (partbuf, code [srcc2]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*syposacc = savlen + 1;
			strcpy (partbuf, code [srcc3]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			*syposacc = savlen + 1;
			strcpy (partbuf, code [src4]);
			strcat (partbuf, code [srcv7]);
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			p31pdecl (pc, typix, savlen, &tindi, &tlen);
			strcat (partbuf, code [srcv6]);
			if ((tindi == CPR_VCHARC || tindi == CPR_VRAW ||
				tt->sc.tyIndi == CPR_VFILEC ||
				tt->sc.tyIndi == CPR_VUNICODEC)
				&& tt->sc.tyPtr == 0)
			{
				strcat (partbuf, "[");
				p13intcat (partbuf, "", 1, &tlen);
				strcat (partbuf, "]");
			}
			strcat (partbuf, ";");
			*part1len = strlen (partbuf) + *syposacc;
			p31outstmt (pc);
			for (i = 0; i < nsrc; i++)
			{
				*syposacc = savlen + 1;
				strcpy (partbuf, code [src [i]]);
				*part1len = strlen (partbuf) + *syposacc;
				p31outstmt (pc);
			}
			p31outstmt (pc);
		}
	}
	*part1len = savlen;
	*syposacc = savacc;
}

void p31dclgen (tpc_globals *pc, tsp00_Int4 typix)
{
	static const int src1 = 0, src2 = 1;
	char **code = p31vcode.dclgen;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp;
	tpc_dclgen  *dcl = &pc->pcDclgen;

	tsp00_Int2 tindi;
	tsp00_Int4 tlen;
	int i, nent;

	nent = (dcl->indclause == cpr_is_true) ? 2 : 1;
	for (i = 0; i < nent; i++)
	{
		tpc_dclclause *cl = &dcl->clause [i];

		*syposacc = 1;
		strcpy (partbuf, "");
		if (dcl->asclause == CPC_AS_TYPE)
			strcat (partbuf, code [src1]);
		strcat (partbuf, code [src2]);
		if (dcl->asclause == CPC_AS_STRUCT)
			strncat (partbuf, (const char *) cl->dclattr,
				 cl->dclattrl);
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		p31pdecl (pc, typix - i, 0, &tindi, &tlen);
		if (dcl->asclause == CPC_AS_TYPE || dcl->asclause == CPC_AS_VAR)
			strncat (partbuf, (const char *) cl->dclattr,
				 cl->dclattrl);
		strcat (partbuf, ";");
		*part1len = strlen (partbuf) + *syposacc;
		p31outstmt (pc);
		p31outstmt (pc);
	}
}

void p31comment (tpc_globals *pc)
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp + *part1len;
	tsp00_Int4 savlen = *part1len;

	*syposacc = savlen + 1;
	strcpy (partbuf, "/*");
	*part1len = strlen (partbuf) + *syposacc;
	p31outstmt (pc);
	*syposacc = 1;
	*part1len = savlen;
	p31outstmt (pc);
	*syposacc = savlen + 1;
	strcpy (partbuf, "*/");
	*part1len = strlen (partbuf) + *syposacc;
	p31outstmt (pc);
	p31outstmt (pc);
	*part1len = savlen;
}

void p31excomment (tpc_globals *pc)
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp + *part1len;
	tsp00_Int4 savlen = *part1len;

	*syposacc = savlen + 1;
	strcpy (partbuf, "/* ");
	switch (pc->pcAn.ancomtyp)
	{
	case cpr_com_sql:
		strcat (partbuf, "EXEC SQL");
		break;
	case cpr_com_command:
		strcat (partbuf, "EXEC COMMAND");
		break;
	case cpr_com_empty:
		break;
	default:
		strcat (partbuf, "EXEC SQL");
	}
	*part1len = strlen (partbuf) + *syposacc;
	p31outstmt (pc);
	*syposacc = 1;
	*part1len = savlen;
	p31outstmt (pc);
	*syposacc = savlen + 1;
	strcpy (partbuf, "*/");
	*part1len = strlen (partbuf) + *syposacc;
	p31outstmt (pc);
	p31outstmt (pc);
	*part1len = savlen;
}
