.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2004 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VPC32C$
.tt 2 $$$
.tt 3 $$Declare Section Parsing$2000-11-30$
********************************************************
.nf

.nf


    ========== licence begin  GPL
    Copyright (c) 2000-2004 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

.fo


.fo
Module  :
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
Define  :

&ifdef DEBUG
&else
#line 23 "vpc32c"
&endif

void p32nextsymbol (tpc_globals *pc, char *partbuf, tsp00_Int4 buflen);
void p32itab (tpc_globals *pc);
void p32push (tpc_globals *pc);
void p32pop (tpc_globals *pc);
void p32vamax (tsp00_Int2 *va1max);
void p32toplevel (tsp00_Int2 *varix);
void p32fansi (tpc_globals *pc, BOOLEAN *indecl);
void p32typequ (tpc_globals *pc);
void p32varequ (tpc_globals *pc);
void p32dclgen (tpc_globals *pc, tsp00_Int2 *typix);
void p32section (tpc_globals *pc);

.CM *-END-* define --------------------------------------
Use     :
 
.CM *-END-* use -----------------------------------------
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : 
.sp
.cp 3
Created : 1994-05-17
.sp
.cp 3
Version : 1994-05-17
.sp
.cp 3
Release :      Date : 2000-11-30
Specification:
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.sp
.CM -lll-
Code    :
/*PRETTY*/
&ifdef DEBUG
#include <stdio.h>
&else
#line 87 "vpc32c"
&endif

#include "vpr04Long.h"
#include "vpi00c.h"
#include "precom/abaphndl.h"

#include <string.h>
#include <memory.h>
#include <ctype.h>
#define ALPH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"
#define NUMERIC "0123456789"

static const char p32alpha [] = ALPH; /* Alpha - Zeichenvorrat */
static const char p32num [] = NUMERIC; /* Numerischer Zeichenvorrat */
static const char p32alnum [] = ALPH NUMERIC; /* Alphanumerischer Zeichenvorrat */
static const char p32space [] = "\011 "; /* Leerzeichen und Tabulator */
static const char p32delim [] = "\011 !#%^&*()-+=~[]\\|;:'\"{},.<>/?";
                                /* C - Begrenzer */
static const char p32sqldelim [] = "\011 !#%&*()-+=;:'\",.<>/?";
                                   /* Sql - Begrenzer */

enum p32keyind {ck_tchar = 1 , ckAuto, ckChar, ckConst, ckDecimal,
	ckDefine, ckDouble, ckExtern, ckFloat, ckInt,
	ckLong, ckLpstr, ckLptstr, ckLpwstr, ckRaw,
	ckReference, ckRegister, ckShort, ckSqlfile, ckSqlLongDesc,
	ckSqlStreamDesc, ckSqlUCS2, ckSqlUTF16, ckStatic,
	ckStruct, ckTchar, ckTypedef, ckUnsigned, ckVarchar,
	ckVolatile, ckWchar, ckWchar_t};

     /* Symbolische Indizierung der Schluesselworttabelle fr Symbol-
        expansion (Hostvariablen-Typen). Die Reihenfolge mu der Reihen-
        folge von p32ckw entsprechend. NULL bedeutet: "Nehme Wert aus p32ckw"*/
static const char *p32ckwOut [] = 
	{
    	NULL, NULL, "CHAR", NULL, NULL,
		NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, 
		NULL, NULL,			
		NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL
	}; /* Schluesselworttabelle fr Codeexpansion*/

    /* Symbolische Indizierung der Schluesselworttabelle fr Symbol-
       erkennung, fr effective binre Suche alphabetisch sortiert 
       einfgen*/
static const char *p32ckw [] = 
	{
		"_tchar", "auto", "char", "const", "decimal",
		"define", "double", "extern", "float", "int",
		"long", "lpstr", "lptstr", "lpwstr", "raw",
		"reference", "register", "short", "sqlfile", "sqllongdesc", 
		"sqlstream", "sqlucs2", "sqlutf16", "static",
		"struct", "tchar", "typedef", "unsigned", "varchar",
		"volatile", "wchar", "wchar_t"
	}; /* Schluesselworttabelle fr Hostvariablentyperkennung*/

	/* longest string must fit to tsp00_Lname */
static const char p32ckm [] = 
	{
		-1,  1,  0,  1,  0,
	 	 1,  1,  1,  1,  1,
	 	 1, -1, -1, -1,  0,
	 	 0,  1,  1,  0,  0,
	 	 0,  0,  0, 1,
	 	 1, -1,  1,  1,  0,
	 	 1, -1, -1
	 	 }; /* Zur Schluesselworttabelle korrespondierendes Array zur Kennzeichnung
	   		   der Schreibweise der Schluesselwoerter. 
	   		   Case sensitivity: 1 means lower case, 
	   		                    -1 means upper case and
	                             0 means case insensitive */

&ifdef DEBUG
&else
#line 127 "vpc32c"
&endif

static const int p32mxckw = sizeof (p32ckw) / sizeof (char*);

typedef struct
{
	tsp00_Lname tname;  /* Typname */
	tsp00_Int2 tntypix; /* Verweis (beginnend mit 1) in die Typtabelle */
	tsp00_Int2 tnconst; /* von null verschieden ("true") fuer konstante Typen */
}
p32tynent; /* Eintrag der Typnamentabelle */

#define p32mxtyne 100

static struct
{
	long tynCnt, tynBot, tagCnt, tagBot; /* obere und untere Grenzen fuer die
	Eintraege in die Typnamen - und Tag - Tabellen */
	p32tynent *tyntab, *tagtab; /* Typnamen - und Tag - Tabellen */
}
p32symtab; /* Symboltabelle, die nur vpc32c benutzt wird */

static struct sqlmdesc p32tyntabd =
	{0, 0, sizeof (p32tynent), p32mxtyne, (void**) &p32symtab.tyntab};
        /* Descriptor fuer p03dynalloc der Typnamen - Tabelle */

static struct sqlmdesc p32tagtabd =
	{0, 0, sizeof (p32tynent), p32mxtyne, (void**) &p32symtab.tagtab};
						/* Schwachsinn fuer ALPHA */
        /* Descriptor fuer p03dynalloc der Tag - Tabelle */

static struct sqlmdesc p32vartabled =
	{0, 0, sizeof (tpc_varent), MXPC_VARENT, 0};
        /* Descriptor fuer p03dynalloc der Variablentabelle
	   apc.pcSymtab.vartablep */

static struct sqlmdesc p32typtabled =
	{0, 0, sizeof (tpc_typent), MXPC_TYPENT, 0};
        /* Descriptor fuer p03dynalloc der Typtabelle
	   apc.pcSymtab.typtablep */

static struct sqlmdesc p32cmpindexd =
	{0, 0, sizeof (tpc_cmpent), MXPC_VARENT, 0};
        /* Descriptor fuer p03dynalloc der Tabelle der Strukturkomponenten
	   apc.pcSymtab.cmpindexp */

static struct sqlmdesc p32constd =
	{0, 0, sizeof (tpc_const_entry), MXPC_CONST_SEC, 0};
        /* Descriptor fuer p03dynalloc der Konstantentabelle
	   apc.pcCse.csec */

#define p32mxcsta 50

typedef struct
{
	tsp00_Int2 sNest, sBid, sVarcnt; /* gepushte Nesting Level, Block ID, */
	long sTyncnt, sTagcnt; /* pc->pcSymtab.varCnt, p32symtab.tynCnt und
				  p32symtab.tagCnt */
}
p32stent; /* Variablenstack - Entry */

static struct
{
	tsp00_Int2 stp, nest, mxBid; /* Stack Pointer, Nesting Level und hoechste
				      Block ID */
	p32stent *ste; /* Datenbereich des Variablenstack */
}
p32sta = {-1, -1, 0}; /* Stack - Struktur */

static struct sqlmdesc p32sted =
	{0, 0, sizeof (p32stent), p32mxcsta + 1, (void**) &p32sta.ste};
						/* Schwachsinn fuer ALPHA */
        /* Descriptor fuer p03dynalloc des Variablenstack */

static tsp00_Int2 p32va1max, p32bid = 0; /*sqlxa.sqlv1p Maximum (s. p32vamax) und
					maximale Block ID*/

static void p32trigraph (tpc_globals *pc, tsp00_Int4 buflen, char *equchar)
/*
Erkennung von Trigraphen als Ersatzsymbole fuer C - Sonderzeichen.
Hilfsprogramm des Scanners p32nextsymbol.

Parameter:
buflen      gibt die aktuelle Zeichenzahl in pc->pccmdpart.partbufp an.
equchar     Rueckgabeparameter, der das zu einem Trigraphen aequivalente
            Sonderzeichen oder, falls kein Trigraph erkannt wurde, das
            Eingabezeichen enthaelt.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	char *partbuf = pc->pccmdpart.partbufp;
	char *tstchar = partbuf + *syposacc - 1;
	BOOLEAN trigraph = TRUE;
	
	*equchar = *tstchar;
	
	if (pc->pcAn.ancomtyp != cpr_com_empty || 
		*syposacc >= buflen - 1 ||
		tstchar [0] != '?' || tstchar [1] != '?')
		return;
	
	switch (tstchar [2])
	{
	case '(':
		*equchar = CPR_LEFTIND_PAR; break;
	case ')':
		*equchar = CPR_RIGHTIND_PAR; break;
	case '<':
		*equchar = CPR_CBEGIN_PAR; break;
	case '>':
		*equchar = CPR_CEND_PAR; break;
	case '/':
		*equchar = CPR_BACKSLASH; break;
	case '!':
		*equchar = '|'; break;
	case '\'':
		*equchar = '^'; break;
	case '-':
		*equchar = '~'; break;
	case '=':
		*equchar = '#'; break;
	default:
		trigraph = FALSE;
	}
	if (trigraph)
	{
		tsp00_Int2 istat;
		p11getchar (pc, 0, partbuf, &buflen, &istat);
		p11getchar (pc, 0, partbuf, &buflen, &istat);
	}
}

static void p32getchar (tpc_globals *pc, tsp00_Int4 *buflen)
/*
C - spezifische Uebertragung eines Eingabezeichens nach pc->pccmdpart.partbufp.
C -, C++ - und SQL - Kommentare werden entfernt, ebenso Zeilenumbrueche.
Ein Zeilenumbruch wird durch ein Leerzeichen ersetzt, falls die Zeile nicht auf
einen C - Delimiter endet. Bei Zeilenende wird die Zeile mit p11vfwrite in die
Ausgabe uebertragen, falls sie nicht Bestandteil einer SQL - Anweisung oder
einer Deklaration innerhalb einer Declare Section ist.
Bei Uebertragung eines Semikolons als Anweisungsterminator wird eine SQL -
Anweisung als Kommentar mit p31excomment in die Ausgabe uebertragen, falls
die entsprechende Precompiler - Option gesetzt wurde.
Das Lesen des Eingabezeichens erfolgt durch p11getchar, das die urspruenglich
zeilenorientierte Eingabe (virtuelles File - Interface) in eine zeichenorientierte
Eingabe umsetzt.

Parameter:
buflen      enthaelt die aktuelle Zeichenzahl in pc->pccmdpart.partbufp und
            gibt den veraenderten Wert zurueck.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp;
	char *tstchar = partbuf + *syposacc - 1;
	tsp00_Int2 *comtyp = &pc->pcAn.ancomtyp;
	BOOLEAN nextchar = TRUE;
	tsp00_Int2 istat = p11chOk;
	
	if (*comtyp != cpr_com_empty && *comtyp != cpr_com_opt)
		if (tstchar [1] == '-' && ((*syposacc < *buflen - 1) ?
			tstchar [2] == '-' : 0))
		{
			tsp00_Int4 pos = *syposacc;
			nextchar = FALSE;
			do
				p11getchar (pc, 0, partbuf, buflen, &istat);
			while (istat != p11chEol && istat != p11chEof);
			if (strchr (p32delim, tstchar [0]) == 0)
			{
				*syposacc = pos + 1;
				tstchar [1] = ' ';
			}
			else
				*syposacc = pos;
			*buflen = *syposacc;
		}
	if (nextchar)
	  if (pc->pcComment == FALSE)
		if (tstchar [0] == '/' && ((*syposacc < *buflen) ?
			tstchar [1] == '/' : 0))
		{
			tsp00_Int4 pos = *syposacc - 1;
			BOOLEAN delim = (BOOLEAN) ((pos == 0) ? TRUE : 
			     strchr (p32delim, tstchar [-1]) == 0);
			nextchar = FALSE;
			do
				p11getchar (pc, 0, partbuf, buflen, &istat);
			while (istat != p11chEol && istat != p11chEof);
			if (delim)
			{
				*syposacc = pos + 1;
				tstchar [0] = ' ';
			}
			else
				*syposacc = pos;
			*buflen = *syposacc;
		}
	if (nextchar)
		p11getchar (pc, 0, partbuf, buflen, &istat);
	if (istat == p11chEof)
		(*syposacc)++;
	else if (istat == p11chEol)
	{
		if (!pc->pcSqlCom)
		{
			tsp00_Int2 len;
			p11gout (&len);
			if (len > 0)
				p11vfwrite (pc, pc->pcCodeInd,
					pc->pcOutLine.lline, len);
		}
		if (*buflen > 0)
			(*syposacc)++;
		do
			p11getchar (pc, 0, partbuf, buflen, &istat);
		while (istat == p11chEol);
	}
	tstchar = partbuf + *syposacc - 1;
	if (*syposacc == *buflen &&
		strchr (p32delim, *tstchar) == 0)
		p11aspace (pc, partbuf, buflen);
	if (*tstchar == ';')
	{
		if ((pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_comment_F) &&
			*comtyp != cpr_com_empty)
		{
			tsp00_Int4 pos = *sypos;
			*part1len = *syposacc;
			p31excomment (pc);
			*sypos = pos;
			*syposacc = *part1len;
		}
		*tstchar = CPR_NULLCHAR;
	}
	pc->pcInpEof = (BOOLEAN) (istat == p11chEof);
}

static void p32qgetch (tpc_globals *pc, tsp00_Int4 *buflen, char *equchar)
/*
C - spezifische Uebertragung eines Eingabezeichens innerhalb einer durch
" oder ' gequoteten Zeichenfolge nach pc->pccmdpart.partbufp.
Das Zeichen \ wird am Zeilenende als Fortsetzungszeichen erkannt.
Parameter:
buflen      enthaelt die aktuelle Zeichenzahl in pc->pccmdpart.partbufp und
            gibt den veraenderten Wert zurueck.
equchar     Rueckgabeparameter, der das den uebertragenen Zeichen nach
            Behandlung mit p32trigraph aequivalente Zeichen enthaelt.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	char *partbuf = pc->pccmdpart.partbufp;
	tsp00_Int2 istat;
	
	p11getchar (pc, 0, partbuf, buflen, &istat);
	p32trigraph (pc, *buflen, equchar);
	if (istat == p11chEol || istat == p11chEof)
	{
		(*syposacc)++;
		if (!pc->pcSqlCom)
		{
			tsp00_Int2 len;
			p11gout (&len);
			if (len > 0)
				p11vfwrite (pc, pc->pcCodeInd,
					pc->pcOutLine.lline, len);
		}
	}
	else if (*equchar == CPR_BACKSLASH)
	{
		p11getchar (pc, 0, partbuf, buflen, &istat);
		if (istat == p11chEol)
		{
			if (!pc->pcSqlCom)
			{
				tsp00_Int2 len;
				p11gout (&len);
				if (len > 0)
					p11vfwrite (pc, pc->pcCodeInd,
						pc->pcOutLine.lline, len);
			}
			p11getchar (pc, 0, partbuf, buflen, &istat);
			if (istat == p11chEol || istat == p11chEof)
				(*syposacc)++;
			else
				(*syposacc)--;
		}
	}
	pc->pcInpEof = (BOOLEAN) (istat == p11chEof);
}

static void p32rmspace (tpc_globals *pc)
/*
Zusammenfassung einer Folge von Leerzeichen und Tabulatoren des Eingabestroms
zu einem einzigen Leerzeichen in pc->pccmdpart.partbufp.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 pos = *syposacc + 1;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp;
	tsp00_Int2 *comtyp = &pc->pcAn.ancomtyp;
	char *tstchar;
	
	while ((tstchar = strchr (p32space, partbuf [*syposacc - 1])) ?
		*tstchar != CPR_NULLCHAR : 0)
		p32getchar (pc, part1len);
	if (*syposacc > pos)
	{
		partbuf [pos - 1] = partbuf [*syposacc - 1];
		if (partbuf [*syposacc - 1] != CPR_NULLCHAR)
			if (*syposacc < *part1len - 1)
			{
				p11rsbuf (pc, part1len);
				*syposacc = pos + 1;
				p32getchar (pc, part1len);
			}
			else if (*syposacc < *part1len)
			{
				partbuf [pos] = partbuf [*syposacc];
				p32getchar (pc, part1len);
				*part1len = pos + 1;
			}
			else
				*part1len = pos;
		*syposacc = pos;
	}
}

void p32nextsymbol (tpc_globals *pc, char *buf, tsp00_Int4 buflen)
/*
C - spezifische lexikalische Analyse des Eingabestroms. Die Zeichenfolge
der Eingabe wird zu Token zusammengefasst, deren Beschreibung in der
Struktur pc->pcScan erfolgt. Die von Zeilenumbruechen, Kommentaren und
ueberfluessigen Leerzeichen befreite Eingabe wird in pc->pccmdpart.partbuf
zur Verfuegung gestellt. Diese Puffer enthaelt maximal eine Anweisung (Text
zwischen zwei Semikolons).
Die Struktur pc->pcScan enthaelt die Komponenten symb, sylen, sypos und syposacc:
symb        erhaelt einen der Werte des Aufzaehlungstyps tpc_csymboltypes.
            Dieser enthaelt ein Symbol fuer jedes fuer die Analyse relevantes
	    Token, wie z.B CPR_S_IDENTIFIER oder CPR_S_COMMA. Das spezielle
	    Token CPR_S_EOF wird gesetzt, wenn ein Semikolon als Ende einer
	    Anweisung erkannt wurde, das Token CPR_S_BUFEOF, wenn das Ende
	    der Eingabe erreicht wurde, ohne ein Semikolon zu finden.
sylen       gibt die Zeichenzahl des aktuellen Token an.
sypos       gibt die Anfangsposition des aktuellen Token in pc->pccmdpart.partbuf
            an (die Zaehlung beginnt bei eins).
syposacc    gibt an, bis zu welcher Position die Analyse durchgefuehrt ist.
            Es gilt stets die Gleichung sylen = syposacc - sypos.

Parameter:
buf         Dummies, die nur aus Kompatibilitaetsgruenden mit dem allgemeinen
buflen      Scanner p10nextsymbol existieren. Dies ist erforderlich, weil beide
            Funktionen als Parameter derselben Precompiler - Funktionen auftreten
            koennen.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tsp00_Int2 *comtyp = &pc->pcAn.ancomtyp;
	char *tstchar;
	char equchar;
	BOOLEAN *comment = &pc->pcComment;

	buf;
	buflen;
	M90TRACE(M90_TR_ENTRY, "p32nextsymbol ", 0);
	if (pc->pcInpEof)
	{
		*symb = CPC_CS_BUFEOF;
		return;
	}
	if (*symb == CPC_CS_EOF)
	{
		p11rsbuf (pc, part1len);
		p32getchar (pc, part1len);
	}
	else if (*symb == CPC_CS_BUFEOF)
	{
		BOOLEAN empty =
			(BOOLEAN) (partbuf [*syposacc - 1] == CPR_NULLCHAR);
		p11rsbuf (pc, part1len);
		if (empty)
		{
			partbuf [*syposacc - 1] = CPR_NULLCHAR;
			*part1len = *syposacc;
		}
		else
			p32getchar (pc, part1len);
	}
	partbuf [*part1len] = CPR_NULLCHAR;
	do
	{
		p32rmspace (pc);
		if (pc->pcInpEof)
			*part1len = *syposacc - 1;
		*comment = FALSE;
		if ((*syposacc < *part1len) ?
			partbuf [*syposacc - 1] == '/' &&
			partbuf [*syposacc] == '*': 0)
		{
			tsp00_Int4 pos = *syposacc;
			tsp00_Int2 com = *comtyp;
			int endstring;
			*comtyp = cpr_com_empty;
			*comment = TRUE;
			partbuf [*syposacc - 1] = ' ';
			p32getchar (pc, part1len);
			do
			{
				p32getchar (pc, part1len);
				endstring = pc->pcInpEof;
				if ((!endstring) ? (*syposacc < *part1len) ?
					partbuf [*syposacc - 1] == '*' &&
					partbuf [*syposacc] == '/': 0 : 0)
				{
					endstring = TRUE;
					p32getchar (pc, part1len);
				}
			}
			while (!endstring);
			*comtyp = com;
			endstring = (*syposacc < *part1len) ?
				partbuf [*syposacc] == ' ' : 1;
			p11rsbuf (pc, part1len);
			*syposacc = (endstring) ? pos : pos + 1;
			if (pos > 1 && partbuf [pos - 2] == ' ')
				(*syposacc)--;
			p32getchar (pc, part1len);
		}
		partbuf [*part1len] = CPR_NULLCHAR;
	}
	while (!pc->pcInpEof && *comment);
	*sypos = *syposacc;
	if ((tstchar = strchr (p32alpha, partbuf [*syposacc - 1])) ?
		*tstchar != CPR_NULLCHAR : 0)
	{
		do
			p32getchar (pc, part1len);
		while ((tstchar = strchr (p32alnum, partbuf [*syposacc -1])) ?
			*tstchar != CPR_NULLCHAR : 0);
		*symb = (tsp00_Int2) (
			(strchr (p32delim, partbuf [*syposacc - 1])) ?
			CPC_CS_IDENTIFIER : CPC_CS_UNKNOWN);
	}
	else if ((tstchar = strchr (p32num, partbuf [*syposacc - 1])) ?
		*tstchar != CPR_NULLCHAR : 0)
	{
		do
			p32getchar (pc, part1len);
		while ((tstchar = strchr (p32num, partbuf [*syposacc -1])) ?
			*tstchar != CPR_NULLCHAR : 0);
		*symb = (tsp00_Int2) (
			(strchr (p32delim, partbuf [*syposacc - 1])) ?
			CPC_CS_UNSIGNED : CPC_CS_UNKNOWN);
	}
	else
	{
		BOOLEAN endstring;
		p32trigraph (pc, *part1len, &equchar);
		switch (equchar)
		{
		case CPR_NULLCHAR:
			if (*syposacc > *part1len)
			{
				*symb = CPC_CS_BUFEOF;
				*part1len = *syposacc - 1;
			}
			else
			{
				*symb = CPC_CS_EOF;
				*part1len = *syposacc;
			}
			break;
		case '(':
			*symb = CPC_CS_LEFTPAR;
			break;
		case ')':
			*symb = CPC_CS_RIGHTPAR;
			break;
		case CPR_LEFTIND_PAR:
			*symb = CPC_CS_LEFTBRK;
			break;
		case CPR_RIGHTIND_PAR:
			*symb = CPC_CS_RIGHTBRK;
			break;
		case CPR_CBEGIN_PAR:
			*symb = CPC_CS_LEFTBRC;
			break;
		case CPR_CEND_PAR:
			*symb = CPC_CS_RIGHTBRC;
			break;
		case ',':
			*symb = CPC_CS_COMMA;
			break;
		case '=':
			*symb = CPC_CS_EQUAL;
			break;
		case '*':
			*symb = CPC_CS_ASTERISK;
			break;
		case ':':
			*symb = CPC_CS_COLON;
			break;
		case '.':
			*symb = CPC_CS_PERIOD;
			break;
		case '>':
			*symb = CPC_CS_GREATER;
			break;
		case '#':
			*symb = CPC_CS_PREPCOM;
			break;
		case '%':
			*symb = CPC_CS_MACRO;
			break;
		case '-':
			*symb = CPC_CS_MINUS;
			break;
		case '/':
			*symb = CPC_CS_DIVIDE;
			break;
		case '"':
			do
			{
				p32qgetch (pc, part1len, &equchar);
				endstring = (BOOLEAN) (*syposacc > *part1len);
				if (endstring)
					*symb = CPC_CS_BUFEOF;
				else if (equchar == '"')
				{
					if (partbuf [*syposacc] != '"')
					{
						endstring = TRUE;
						*symb = CPC_CS_STRING;
					}
					else
						p32qgetch (pc, part1len,
							&equchar);
				}
			}
			while (!endstring);
			break;
		case CPR_QUOTSYM:
			do
			{
				p32qgetch (pc, part1len, &equchar);
				endstring = (BOOLEAN) (*syposacc > *part1len);
				if (endstring)
					*symb = CPC_CS_BUFEOF;
				else if (equchar == CPR_QUOTSYM)
				{
					if (partbuf [*syposacc] != CPR_QUOTSYM)
					{
						endstring = TRUE;
						*symb = CPC_CS_CHAR;
					}
					else
						p32qgetch (pc, part1len,
							&equchar);
				}
			}
			while (!endstring);
			break;
		default:
			do
				p32getchar (pc, part1len);
			while (!strchr (p32sqldelim, partbuf [*syposacc -1]));
			*symb = CPC_CS_UNKNOWN;
		}
		if (*symb != CPC_CS_EOF && *symb != CPC_CS_BUFEOF &&
			*symb != CPC_CS_UNKNOWN)
			p32getchar (pc, part1len);
		if (*comtyp != cpr_com_empty && *symb == CPC_CS_COLON)
		{
			p32rmspace (pc);
			if (pc->pcInpEof)
				*part1len = *syposacc - 1;
			if ((tstchar =
				strchr (p32alpha, partbuf [*syposacc - 1])) ?
				*tstchar != CPR_NULLCHAR : 0)
			{
				do
					p32getchar (pc, part1len);
				while ((tstchar =
				strchr (p32alnum, partbuf [*syposacc -1])) ?
					*tstchar != CPR_NULLCHAR : 0);
				*symb = (tsp00_Int2) (
				(strchr (p32delim, partbuf [*syposacc - 1])) ?
					CPC_CS_PARAMETER : CPC_CS_UNKNOWN);

			}
		}
	}
	*sylen = *syposacc - *sypos;
	M90TRACE(M90_TR_SWORD, "sylen     ",sylen);
	M90TRACE(M90_TR_SWORD, "sypos     ",sypos);
	M90TRACE(M90_TR_SWORD, "syposacc  ",syposacc);
	M90TRACE(M90_TR_SWORD, "symb      ",symb);
	M90TRACE(M90_TR_EXIT , "p32nextsymbol ", 0);
}

static void p32getkeyword (tpc_globals *pc, int *index)
/*
C - spezifische Schluesselworterkennung. Alle Schluesselwoerter stehen in
Kleinschreibung und in aufsteigender Folge geordnet in dem Array p32ckw.
Das durch sypos und sylen in pc->pccmdpart.partbufp bestimmte Token wird
zunaechst in Kleinschreibung gewandelt und in binaerer Suche mit den
Schluesselwoertern des Array verglichen. Wurde Uebereinstimmung gefunden,
werden drei Faelle unterschieden, die durch das korrespondierende Array
p32ckm festgelegt sind: Ist der Wert des entsprechenden Elementes von
p32ckm positiv, muss exakte Uebereinstimmung (case sensitivity) vorliegen,
um das Token als Schluesselwort zu erkennen (z.B. "int"). Ist er negativ,
darf das Token nur Grossbuchstaben enthalten (z.B. "_TCHAR"). Ist er dagegen
null, ist die Schreibweise gleichgueltig (z.B. "VARCHAR", "VarChar" oder
"varchar").

Parameter:
index       gibt den Index (beginnend mit eins) in p32ckw des erkannten
            Schluesselwortes (symbolischer Wert des Aufzaehlungstyps
	    p32keyind) zurueck, oder null, falls kein Schluesselwort
	    erkannt wurde.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	char *partbuf = pc->pccmdpart.partbufp + *sypos - 1;
	int i, j, k, cmp;
	tsp00_Lname syname;

	M90TRACE(M90_TR_ENTRY, "p32getkeyword ", 0);
	M90TRACEBUF("partbuf ", partbuf, 1 , 20); 
	*index = 0;

	if (*sylen > sizeof(tsp00_Name))
		return;

	for (i = 0; i < *sylen; i++)
		syname [i] = (char) tolower (partbuf [i]);
	syname [*sylen] = '\0';
	i = 0;
	j = p32mxckw - 1;
	do
	{
		k = (i + j) / 2;
		cmp = strcmp (p32ckw [k], (const char *) syname);
		if (cmp == 0)
		{
			i = j + 1;
			*index = k + 1;
		}
		else if (cmp < 0)
			i = k + 1;
		else
			j = k - 1;
	}
	while (i <= j);
	if (*index && strncmp (p32ckw [k], partbuf, *sylen))
	  if (p32ckm [k] > 0)
	    *index = 0;
	  else if (p32ckm [k] < 0) {
	    for (i = 0; i < *sylen; i++)
	      if (isalpha (partbuf [i]))
		if (islower (partbuf [i])) {
		  *index = 0;
		  break;
		}
	  }
	  else
	    /* Wenn spezieller Ausgabewert in p32ckwOut gesetzt,
	       sonst default aus Symboltabelle p32ckw nehmen*/
	    if(p32ckwOut [k])
	    {
	    	memcpy (partbuf, p32ckwOut [k], *sylen);
	    }
	    else
	    {
	    	memcpy (partbuf, p32ckw [k], *sylen);
	    }
	    
	if (pc->sqlca.sqldbmode != CPR_KIND_ORACLE &&
		pc->sqlca.sqldbmode != CPR_KIND_SAPR3 &&
		pc->sqlca.sqlrap->rasqlansi == CPR_KIND_ANSI &&
		*index == ckVarchar)
	{
		char *newid = "char   ";
		memcpy (partbuf, newid, *sylen);
		*sylen -= 3;
		*syposacc -= 3;
		*index = ckChar;
	}
	if (pc->sqlca.sqldbmode != CPR_KIND_ORACLE &&
		pc->sqlca.sqldbmode != CPR_KIND_SAPR3 && *index == ckRaw)
		*index = 0;
	M90TRACE(M90_TR_SWORD, "pcscan.sylen ",&pc->pcScan.sylen);
	M90TRACE(M90_TR_SWORD, "index        ", index);
	M90TRACE(M90_TR_EXIT, "p32getkeyword ", 0);
}

static void p32getorat (tpc_globals *pc, short *orat)
/*
Bestimmung der ORACLE - Typkennung aus einer verbalen Beschreibung des Typs,
wie sie in der Syntax der EXEC SQL TYPE - Anweisung vorkommt. Die verbale
Beschreibung erfolgt durch ein oder zwei Schluesselwoerter aus dem Array
tnam1. Zwei Schluesselwoerter sind genau dann noetig, wenn das erste "long"
ist. Die als zweiter Bestandteil in Frage kommenden Schluesselwoerter sind
nochmals in tnam2 aufgelistet.

Parameter:
orat        gibt die ORACLE - Typkennung als ganze, nichtnegative Zahl
            zurueck, oder -1, falls keine zulaessige Typbeschreibung
	    erkannt wurde.
*/
{
	typedef char *nament;
	static const nament tnam1 [] = {"char", "charz", "date", "decimal",
		"display", "integer", "float", "long", "mlslabel", "number",
		"raw", "rowid", "string", "unsigned", "varchar", "varchar2",
		"varnum", "varraw"};
	static const nament tnam2 [] = {"raw", "varchar", "varraw"};
	static const short T1 [] = {SQL_ORA_CHAR, SQL_ORA_CHARZ,
		SQL_ORA_INTERNDATE, SQL_ORA_PACKEDDECIMAL, SQL_ORA_DISPLAY,
		SQL_ORA_FIXEDPOINTINTEGER, SQL_ORA_FLOATPOINT, SQL_ORA_LONG,
		SQL_ORA_MLSLABEL, SQL_ORA_NUMBER, SQL_ORA_RAW, SQL_ORA_ROWID,
		SQL_ORA_NULLTERMINATEDSTRING, SQL_ORA_UNSIGNED,
		SQL_ORA_VARCHAR, SQL_ORA_VARCHAR2, SQL_ORA_VARNUM,
		SQL_ORA_VARRAW};
	static const short T2 [] = {SQL_ORA_LONGRAW, SQL_ORA_LONGVARCHAR,
		SQL_ORA_LONGVARRAW};
	static const nament *tnam [] = {tnam1, tnam2};
	static const short *T [] = {T1, T2};
	static const int ntnam [] = {sizeof (tnam1) / sizeof (char*),
		sizeof (tnam2) / sizeof (char*)};

	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	char *partbuf = pc->pccmdpart.partbufp;
	int i, j, k, cmp, l, index;
	tsp00_Lname syname;

	*orat = -1;
	l = 0;
	
	do
	{
		const nament *tn = tnam [l];
		
		if (*sylen > sizeof(tsp00_Name))
			return;

		index = -1;

		for (i = 0; i < *sylen; i++)
			syname [i] = (char) tolower (partbuf [*sypos + i -1]);
		syname [*sylen] = '\0';
		i = 0;
		j = ntnam [l] - 1;
		do
		{
			k = (i + j) / 2;
			cmp = strcmp (tn [k], (const char *) syname);
			if (cmp == 0)
			{
				i = j + 1;
				index = k;
			}
			else if (cmp < 0)
				i = k + 1;
			else
				j = k - 1;
		}
		while (i <= j);
		if (index >= 0)
		{
			*orat = T [l] [index];
			p32nextsymbol (pc, partbuf, *part1len);
		}
	}
	while (++l < 2 && *orat == SQL_ORA_LONG && *symb== CPC_CS_IDENTIFIER);
}

void p32itab (tpc_globals *pc)
/* Initialisieren der Typnamentabelle p32symtab.tyntab und der Typtabelle
pc->pcsymtab.typtablep mit den C - Grunddatentypen. Als interner Typname
wird eine Zeichenfolge verwendet, die mit "#" beginnt und anschliessend
aus den jeweils ersten Buchstaben der zur Beschreibung des jeweiligen Typs
erforderlichen Schluesselwoerter besteht (z.B. "#li" fuer long int).
*/
{
	p32tynent *tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	p32tynent *tyn0;
	tpc_typent *tyt;
	tpc_typent *tyt0;

	p32vartabled.descElemPtr = (void**) &pc->pcSymtab.vartablep;
	p32typtabled.descElemPtr = (void**) &pc->pcSymtab.typtablep;
	p32cmpindexd.descElemPtr = (void**) &pc->pcSymtab.cmpindexp;
	p32constd.descElemPtr = (void**) &pc->pcCse.csec;
				/* Schwachsinn fuer ALPHA */
	M90TRACE(M90_TR_ENTRY, "p32itab  ", 0);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#l ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VLONG;
	tyt->sc.tyDigit = CPR_LLONG;
	tyt->sc.tySize = sizeof (long);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	memcpy (tyn->tname, "#li", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#s ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VSHORT;
	tyt->sc.tyDigit = CPR_LSHORT;
	tyt->sc.tySize = sizeof (short);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	memcpy (tyn->tname, "#si", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#i ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VINT;
	tyt->sc.tyDigit = CPR_LINT;
	tyt->sc.tySize = sizeof (int);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#lu", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUNSLONG;
	tyt->sc.tyDigit = CPR_LUNSLONG;
	tyt->sc.tySize = sizeof (long);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#su", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUNSSHORT;
	tyt->sc.tyDigit = CPR_LUNSSHORT;
	tyt->sc.tySize = sizeof (short);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#u ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUNSIGNED;
	tyt->sc.tyDigit = CPR_LUNSIGNED;
	tyt->sc.tySize = sizeof (int);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#c ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VCHAR;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 1;
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	memcpy (tyn->tname, "#uc", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;

	/* SQLFILE */
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#n ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VFILE;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 1;
	tyt->sc.tyFrac = 0;

	/* SqlStreamDesc */
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#p ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VABAPHANDLE;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = sizeof(SQL_LC_StreamParm);
	tyt->sc.tyFrac = 0;

	/* SqlLongDesc */
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#b ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VLONGDESC;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = sizeof(sqllongdesc);
	tyt->sc.tyFrac = 0;

	/* SQLUCS2 */
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#a ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUCS2;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 2;
	tyt->sc.tyFrac = 0;

	/* SQLUTF16 */
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#e ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUTF16;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 2;
	tyt->sc.tyFrac = 0;

	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#x ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUNICODE;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 1;
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#y ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VCHARC;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 0;
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#z ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VUNICODEC;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 0;
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#r ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VRAWC;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = 1;
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#v ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VSTRINGC;
	tyt->sc.tyDigit = 0;
	tyt->sc.tySize = sizeof (VARCHD(sqldummy, 1));
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#lf", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VDOUBLE;
	tyt->sc.tyDigit = CPR_LDOUBLE;
	tyt->sc.tySize = sizeof (double);
	tyt->sc.tyFrac = 0;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	memcpy (tyn->tname, "#d ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyn = (p32tynent*) p03dynalloc (&p32tyntabd);
	tyt = (tpc_typent*) p03dynalloc (&p32typtabled);
	memcpy (tyn->tname, "#f ", 3);
	memset (&tyn->tname [3], ' ', sizeof (tyn->tname) - 3);
	tyn->tntypix = (tsp00_Int2) p32typtabled.descNelem;
	tyt->sc.tyIndi = CPR_VFLOAT;
	tyt->sc.tyDigit = CPR_LFLOAT;
	tyt->sc.tySize = sizeof (float);
	tyt->sc.tyFrac = 0;
	p32symtab.tynCnt = p32tyntabd.descNelem;
	pc->pcSymtab.typCnt = (tsp00_Int2) p32typtabled.descNelem;
	tyn0 = p32symtab.tyntab;
	while (tyn > tyn0)
		(tyn--)->tnconst = 0;
	tyn->tnconst = 0;
	tyt0 = pc->pcSymtab.typtablep;
	while (tyt > tyt0)
	{
		tyt->sc.tyRef = 0;
		(tyt--)->sc.tyPtr = 0;
	}
	tyt->sc.tyRef = 0;
	tyt->sc.tyPtr = 0;
	p32symtab.tynBot = 0;
	p32symtab.tagCnt = 0;
	p32symtab.tagBot = 0;
	pc->pcSymtab.cmpCnt = 0;
	pc->pcSymtab.varCnt = 0;
	pc->pcSymtab.varBot = 0;
	M90TRACE(M90_TR_EXIT, "p32itab  ", 0);
}

static int p32kwcpy (char* s, int index)
/* Kopieren des durch den Parameter index bestimmten Schluesselwortes in
den Parameter s. Das Nullbyte am Ende wird durch ein Leerzeichen ersetzt.
*/
{
	int l;
	strcpy (s, p32ckw [index - 1]);
	s [l = strlen (s)] = ' ';
	return ++l;
}

static void p32sVarbot (tpc_globals *pc)
/*
Die Anzahl der nicht bei der Namenssuche zu beruecksichtigenden Eintraege
am Anfang der Tabelle der Variablen - Namen wird auf den auf dem Stack
gespeicherten Wert gesetzt. Hierdurch werden alle Namen, die in den
aktuellen Block umfassenden Bloecken definiert wurden von der Suche nach
doppelt vorhandenen Eintraegen ausgenommen.
*/
{
	if (p32sta.stp >= 0)
		pc->pcSymtab.varBot = p32sta.ste [p32sta.stp].sVarcnt;
}

static void p32sTynbot ()
/*
Die Anzahl der nicht bei der Namenssuche zu beruecksichtigenden Eintraege
am Anfang der Tabelle der typedef - Namen wird auf den auf dem Stack
gespeicherten Wert gesetzt. Hierdurch werden alle Namen, die in den
aktuellen Block umfassenden Bloecken definiert wurden von der Suche nach
doppelt vorhandenen Eintraegen ausgenommen.
*/
{
	if (p32sta.stp >= 0)
		p32symtab.tynBot = p32sta.ste [p32sta.stp].sTyncnt;
}

static void p32sTagbot ()
/*
Die Anzahl der nicht bei der Namenssuche zu beruecksichtigenden Eintraege
am Anfang der Tabelle der structure tags wird auf den auf dem Stack
gespeicherten Wert gesetzt. Hierdurch werden alle Namen, die in den
aktuellen Block umfassenden Bloecken definiert wurden von der Suche nach
doppelt vorhandenen Eintraegen ausgenommen.
*/
{
	if (p32sta.stp >= 0)
		p32symtab.tagBot = p32sta.ste [p32sta.stp].sTagcnt;
}

static void p32rVarbot (tpc_globals *pc)
/*
Bei der Namenssuche in der Tabelle der Variablen - Namen sollen alle Eintraege,
auch die aus uebergeordneten Bloecken stammenden, beruecksichtigt werden.
*/
{
	pc->pcSymtab.varBot = 0;
}

static void p32rTynbot ()
/*
Bei der Namenssuche in der Tabelle der typedef - Namen sollen alle Eintraege,
auch die aus uebergeordneten Bloecken stammenden, beruecksichtigt werden.
*/
{
	p32symtab.tynBot = 0;
}

static void p32rTagbot ()
/*
Bei der Namenssuche in der Tabelle der structure tags sollen alle Eintraege,
auch die aus uebergeordneten Bloecken stammenden, beruecksichtigt werden.
*/
{
	p32symtab.tagBot = 0;
}

static int p32tyntyp (int index)
/*
Konvertierung eines Index der Tabelle der typedef - Namen in einen Index der
Typtabelle pc->pcSymtab.typtablep.

Parameter:
index       bezeichnet den Index des Eintrags p32symtab.tyntab [index - 1].
*/
{
	return (index > 0) ? p32symtab.tyntab [index - 1].tntypix : 0;
}

static int p32tagtyp (int index)
/*
Konvertierung eines Index der Tabelle der structure tags in einen Index der
Typtabelle pc->pcSymtab.typtablep.

Parameter:
index       bezeichnet den Index des Eintrags p32symtab.tagtab [index - 1].
*/
{
	return (index > 0) ? p32symtab.tagtab [index - 1].tntypix : 0;
}

static void p32tnindex (int cnt, int bot, const p32tynent *tab,
	const char *tna, tsp00_Int2 *tnc, tsp00_Int2 *index)
/*
Suche in einer Tabelle des Typs p32tynent nach einem eingetragenen Namen.
Die Tabelle wird von hinten (beginnend beim hoechsten Index) durchsucht und
der Index des zuerst gefundenen Eintrags zurueckgegeben.

Parameter:
cnt         Anzahl der vorhanden Eintraege der Tabelle tab.
bot         Anzahl der Eintraege im vorderen Teil der Tabelle (beginnend
            beim niedrigsten Index), die bei der Suche nicht beruecksichtigt
	    werden sollen.
tab         Tabelle, die durchsucht wird.
tna         Name, nach dem in tab [i].tname gesucht wird.
tnc         gibt den Wert tab [index - 1].tnconst zurueck, falls ein Eintrag
            gefunden wurde. Er ist genau dann von null verschieden ("true"),
	    wenn der Eintrag einen konstanten Typ (Variablen dieses Typs
	    duerfen keine Werte zugewiesen werden) bezeichnet.
index       gibt den Index des gefundenen Eintrags tab [index - 1].tname == tna
            zurueck, oder null, falls kein Eintrag gefunden wurde.
*/
{
	*index = 0;
	
	if (cnt == 0)
		return;
	else
	{
		const p32tynent *t = &tab [cnt -1], *t0 = &tab [bot];

		while (t >= t0)
		{
			if (memcmp (tna, t->tname, sizeof (t->tname)) == 0)
			{
				*index = (tsp00_Int2) (t - t0 + 1);
				*tnc = t->tnconst;
				t = t0;
			}
			t--;
		}

	}
}

static void p32tynindex (const char *tna, tsp00_Int2 *tnc,
	tsp00_Int2 *index)
/*
p32tnindex (s. dort), spezialisiert auf die Tabelle p32symtab.tyntab der
typedef - Namen.
*/
{
	p32tnindex (p32symtab.tynCnt, p32symtab.tynBot, p32symtab.tyntab,
		tna, tnc, index);
}

static void p32tagindex (const char *tna, tsp00_Int2 *tnc,
	tsp00_Int2 *index)
/*
p32tnindex (s. dort), spezialisiert auf die Tabelle p32symtab.tagtab der
structure tags.
*/
{
	p32tnindex (p32symtab.tagCnt, p32symtab.tagBot, p32symtab.tagtab,
		tna, tnc, index);
}

static void p32newtyn (tpc_globals *pc, int typeind, int typix,
	int consttype, int constspec, const char* tna)
/*
Eintrag eines neuen Typs in die Tabelle der typedef - Namen. Mit p32tnindex
wird nach einem vorhandenen Eintrag gleichen Namens im gleichen Block gesucht
und gegebenenfalls ein Fehler gemeldet.

Parameter:
typeind     bezeichnet den Index des Eintrags pc->pcSymtab.typtablep [typeind - 1]
            des definierenden Typs.
typix       bezeichnet den Index des Eintrags pc->pcSymtab.typtablep [typeind - 1]
            des definierten Typs (Rueckgabeparameter von p32declist).
consttype   ist genau dann von null verschieden, wenn der definierende Typ ein
            konstanter Typ ist (Variablen dieses Typs duerfen keine Werte
	    zugewiesen werden).
constspec   ist ckConst, falls die typedef - Deklaration den const - Specifier
            enthaelt, nichtpositiv sonst.
tna         bezeichnet den typedef - Namen
*/
{
	tsp00_Int2 tnc, index;
	
	p32tnindex (p32symtab.tynCnt, p32symtab.tynBot, p32symtab.tyntab,
		tna, &tnc, &index);
	if (index > 0)
		p11precomerror (pc, CPC_DUPLICATE_TYPEDEF);
	if (pc->pcError == CPC_PRE_OK)
	{
		p32tynent *t = (p32tynent*) p03dynalloc (&p32tyntabd);
		p32symtab.tynCnt++;
		memcpy (t->tname, tna, sizeof (t->tname));
		t->tntypix = (tsp00_Int2) typix;
		t->tnconst = (tsp00_Int2) ((consttype > 0 || (constspec > 0 &&
			pc->pcSymtab.typtablep [typeind - 1].sc.tyPtr <= 0)) ?
			CPC_CCONST : 0);
	}
}

static void p32newtag (tpc_globals *pc, int typix, const char* tna,
	int constspec)
/*
Eintrag eines neuen Tags in die Tabelle der structure tags. Mit p32tnindex
wird nach einem vorhandenen Eintrag gleichen Namens im gleichen Block gesucht
und gegebenenfalls ein Fehler gemeldet.

Parameter:
typix       bezeichnet den Index des Eintrags pc->pcSymtab.typtablep [typeind - 1]
            des definierten Typs.
tna         bezeichnet den structure tag.
constspec   ist ckConst, falls die structure - Definition den const - Specifier
            enthaelt, nichtpositiv sonst.
*/
{
	tsp00_Int2 tnc, index;
	
	p32tnindex (p32symtab.tagCnt, p32symtab.tagBot, p32symtab.tagtab,
		tna, &tnc, &index);
	if (index > 0)
		p11precomerror (pc, CPC_DUPLICATE_TYPEDEF);
	if (pc->pcError == CPC_PRE_OK)
	{
		p32tynent *t = (p32tynent*) p03dynalloc (&p32tagtabd);
		p32symtab.tagCnt++;
		memcpy (t->tname, tna, sizeof (t->tname));
		t->tntypix = (tsp00_Int2) typix;
		t->tnconst = (tsp00_Int2) (constspec > 0);
	}
}

void p32vamax (tsp00_Int2 *va1max)
/*
Rueckgabe der Anzahl der in der Variablentabelle sqlxa.sqlv1p vorhandenen Eintraege.
Diese kann groesser sein als der von pc->pcSqlva.va1cnt angenommene Wert, da
letzterer vom Zustand des Variablen - Stack abhaengt und mit jeder Pop - Operation
abnimmt (die im gerade verlassen Block deklarierten Variablen werden geloescht).
Fuer die Dimensionierung der Variablentabelle zur Laufzeit ist jedoch ihre maximale
Ausdehnung massgebend.
Zur Erzeugung von sqlxa.sqlva1p aus den Symboltabellen in pc->pcSymtab s. vpc19c.

Parameter:
va1max      Rueckgabeparameter.
*/
{
	*va1max = p32va1max;
}

void p32toplevel (tsp00_Int2 *varix)
/*
Rueckgabe der Anzahl der in der Variablentabelle pc->pcSymtab.vartablep vorhandenen
Top Level - Eintraege, d.s. diejenigen Eintraege, die Variablen der Speicherklassen
static oder extern und dem Scope "File" entsprechen.

Parameter:
varix       Rueckgabeparameter.
*/
{
	*varix = (tsp00_Int2) ((p32sta.stp >= 0) ? p32sta.ste [0].sVarcnt : 0);
}

void p32push (tpc_globals *pc)
/*
Push - Operation des Variablen - Stack bei Block - Eintritt (ein { wurde gefunden).
Die aktuellen Zaehlerstaende der benoetigten Symboltabellen werden auf dem Stack
festgehalten und der Stack Pointer erhoeht.
*/
{
	tpc_symtab *symt = &pc->pcSymtab;
	tpc_pc_sqlva *sqlva = &pc->pcSqlva;
	p32stent *ste = p32sta.ste + p32sta.stp;
	int newlayer;
	
	p32sta.nest++;
	newlayer = p32sta.stp < 0;
	if (!newlayer)
		newlayer = symt->varCnt > ste->sVarcnt ||
			p32symtab.tynCnt > ste->sTyncnt ||
			p32symtab.tagCnt > ste->sTagcnt;
	if (newlayer)
	{
		p32sta.stp++;
		ste = (p32stent*) p03dynalloc (&p32sted);
		ste->sVarcnt = symt->varCnt;
		ste->sTyncnt = p32symtab.tynCnt;
		ste->sTagcnt = p32symtab.tagCnt;
		ste->sNest = p32sta.nest;
		ste->sBid = p32bid;
		p32bid = ++p32sta.mxBid;
	}
}

void p32pop (tpc_globals *pc)
/*
Pop - Operation des Variablen - Stack bei Block - Austritt (ein } wurde gefunden).
Die Zaehler der Symboltabellen werden auf die zuletzt "gepushten" Werte zurueck-
gesetzt und somit alle dem gerade verlassenen Block entsprechenden Eintraege
geloescht.
*/
{
	tpc_symtab *symt = &pc->pcSymtab;
	tpc_pc_sqlva *sqlva = &pc->pcSqlva;
	p32stent *ste = p32sta.ste + p32sta.stp;
	
	if (p32sta.stp < 0)
		return;
	
	if (sqlva->va1cnt > p32va1max)
		p32va1max = sqlva->va1cnt;
	symt->varCnt = ste->sVarcnt;
	p32vartabled.descNelem = ste->sVarcnt;
	p32symtab.tynCnt = p32tyntabd.descNelem = ste->sTyncnt;
	p32symtab.tagCnt = p32tagtabd.descNelem = ste->sTagcnt;
	p32bid = ste->sBid;
	if (ste->sNest == p32sta.nest)
	{
		p32sta.stp--;
		p32sted.descNelem--;
	}
	p32sta.nest--;	
}

static int p32basetype (tpc_globals *pc, tsp00_Lname typename,
	int *storclspec, int *typespec, int *constspec)
/*
Die Funktion liefert einen von null verschiedenen Wert ("true"), wenn die
Type Specifier einer Deklaration einen Grunddatentyp ergeben, anderenfalls
null ("false").
Grunddatentypen sind (unsigned) char, double, float, (unsigned) (short / long) int
und die vom Precompiler interpretierten Pseudotypen _tchar, lpstr, lptstr, lpwstr,
raw, tchar, wchar und wchar_t.

Rueckgabeparameter:
typename    gibt einen internen Typnamen der Tabelle p32symtab.tyntab zurueck,
            falls ein Grunddatentyp gefunden wurde und ist sonst undefiniert.
	    Der interne Typname eines Grunddatentyps ist kein Identifier und
	    unterscheidet sich somit von allen Typedef - Namen (s. p32itab).
storclspec  gibt einen Wert des Aufzaehlungstyps p32keyind zurueck, der eine
            gefundene Storage Class bezeichnet, oder einen nichtpositiven Wert,
	    falls keine Storage Class gefunden wurde.
typespec    gibt einen Wert des Aufzaehlungstyps p32keyind zurueck, der einen
            gefundenen Type Specifier bezeichnet. Dieser Wert ist auch definiert,
	    falls kein Grunddatentyp gefunden wurde.
constspec   gibt den Wert ckConst des Aufzaehlungstyps p32keyind zurueck, falls
            der Type Specifier const gefunden wurde, anderenfalls einen
	    nichtpositiven Wert.
*/
{
	enum SPEC {sto = 0, len, typ, uns, con};
	int spec [con + 1];
	int keyind, i;
	int basespec, bast, err;
	
	M90TRACE(M90_TR_ENTRY, "p32basetype  ", 0);
	p32getkeyword (pc, &keyind);
	M90TRACE(M90_TR_SWORD, "keyind       ", &keyind);
	for (i = sto; i <= con; i++)
		spec [i] = -p32mxckw;
	basespec = TRUE;
	while (basespec)
	{
		switch (keyind)
		{
		case ckExtern:
		case ckStatic:
		case ckAuto:
		case ckTypedef:
		case ckRegister:
			spec [sto] += p32mxckw + keyind;
			break;
		case ckShort:
		case ckLong:
			spec [len] += p32mxckw + keyind;
			break;
		case ckInt:
		case ckChar:
		case ckRaw:
		case ckVarchar:
		case ckFloat:
		case ckDouble:
		case ckSqlfile:
		case ckSqlStreamDesc:
		case ckSqlLongDesc:
                case ckSqlUCS2:
                case ckSqlUTF16:
		case ck_tchar:
		case ckTchar:
		case ckWchar:
		case ckWchar_t:
		case ckLptstr:
		case ckLpstr:
		case ckLpwstr:
			spec [typ] += p32mxckw + keyind;
			break;
		case ckUnsigned:
			spec [uns] += p32mxckw + keyind;
			break;
		case ckConst:
			spec [con] += p32mxckw + keyind;
			break;
		case ckVolatile:
			break;
		default:
			basespec = FALSE;
		}
		if (basespec)
		{
			p32nextsymbol (pc, pc->pccmdpart.partbufp,
				pc->pccmdpart.part1len);
			p32getkeyword (pc, &keyind);
			M90TRACE(M90_TR_SWORD, "keyind b     ", &keyind);
		}
	}
	err = FALSE;
	for (i = sto; i <= con; i++)
		err = err || spec [i] > p32mxckw;
	err = err || (spec [len] > 0 && (spec [typ] == ckChar ||
		spec [typ] == ckRaw || spec [typ] == ckVarchar ||
		spec [typ] == ckDouble || spec [typ] == ckSqlfile ||
					 spec [typ] == ckSqlStreamDesc ||
					 spec [typ] == ckSqlLongDesc ||
                spec [typ] == ckSqlUCS2 || spec [typ] == ckSqlUTF16 ||
		spec [typ] == ck_tchar || spec [typ] == ckTchar ||
		spec [typ] == ckWchar || spec [typ] == ckLptstr ||
		spec [typ] == ckLpstr || spec [typ] == ckLpwstr)) ||
		(spec [len] == ckShort && spec [typ] == ckFloat) ||
		(spec [uns] > 0 && (spec [typ] == ckRaw ||
		spec [typ] == ckVarchar || spec [typ] == ckFloat
		|| spec [typ] == ckDouble || spec [typ] == ckSqlfile));
	if (spec [sto] == ckRegister)
		p11precomerror (pc, CPC_STORAGE_CLASS_NOT_ALLOWED);
	if (err)
		p11precomerror (pc, CPC_INVALID_DATATYPE);
	bast = spec [len] > 0 || spec [typ] > 0 || spec [uns] > 0 ||
		pc->pcError != CPC_PRE_OK;
	*storclspec = (spec [sto] > p32mxckw) ? 0 : spec [sto];
	*constspec = (spec [con] > 0) ? ckConst : 0;
	memset (typename, ' ', sizeof (tsp00_Lname));
	if (bast)
	{
		typename [0] = '#';
		i = 1;
		if (spec [len] == ckShort)
			typename [i++] = 's';
		else if (spec [len] == ckLong)
			typename [i++] = 'l';
		if (spec [uns] == ckUnsigned)
		{
			typename [i++] = 'u';
			if (spec [typ] == ckChar)
				typename [i] = 'c';
		}
		else
			switch (spec [typ])
			{
			case ckInt:
				typename [i] = 'i';
				break;
			case ckChar:
				typename [i] = 'c';
				break;
			case ckRaw:
				typename [i] = 'r';
				break;
			case ckVarchar:
				typename [i] = 'v';
				break;
			case ckFloat:
				typename [i] = 'f';
				break;
			case ckDouble:
				typename [i] = 'd';
				break;
			case ckSqlfile:
				typename [i] = 'n';
				break;
			case ckSqlStreamDesc:
				typename [i] = 'p';
				break;
			case ckSqlLongDesc:
				typename [i] = 'b';
				break;
                        case ckSqlUCS2:
                                typename [i] = 'a';
                                break;
                        case ckSqlUTF16:
                                typename [i] = 'e';
                                break;
			case ckTchar:
				typename [i] = (char)((pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_unicode_F) ?
					'x' : 'c');
				break;
			case ck_tchar:
				typename [i] = (char)((pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_unicode_F) ?
					'x' : 'c');
				break;
			case ckLptstr:
				typename [i] = (char)((pc->pcOpts.variant.C_sp4co_sql_precompiler.opt_unicode_F) ?
					'z' : 'y');
				break;
			case ckWchar:
				typename [i] = 'x';
				break;
			case ckLpstr:
				typename [i] = 'y';
				break;
			case ckLpwstr:
				typename [i] = 'z';
				break;
			case ckWchar_t:
				typename [i] = 'x';
				break;
			}
		*typespec = (spec [typ] > p32mxckw) ? 0 : spec [typ];
	}
	else
		*typespec = keyind;
	M90TRACE(M90_TR_SWORD, "keyind       ", &keyind);
	M90TRACE(M90_TR_SWORD, "typespec     ", typespec);
	M90TRACEBUF("typename", typename, 1 , 20); 
	M90TRACE(M90_TR_EXIT, "p32basetype  ", 0);
	return bast;
}

static void p32skpinit (tpc_globals *pc, BOOLEAN *error)
/*
Ueberspringen des Initializers einer Variablendeklaration. Dieser muss erkannt
werden, ist aber inhaltlich ohne Bedeutung. Um das naechste Komma als Trennzeichen
in der Liste der Deklaratoren zu finden, muss eine eventuell vorhandene Schachtelung
von { ... } Paaren beruecksichtigt werden.
*/
{
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	int parcnt1, parcnt2;
	
	*error = FALSE;
	if (*symb == CPC_CS_LEFTBRC)
	{
		parcnt1 = 0;
		do
			switch (*symb)
			{
			case CPC_CS_LEFTBRC:
				parcnt1++;
				p32nextsymbol (pc, partbuf, *part1len);
				break;
			case CPC_CS_RIGHTBRC:
				parcnt1--;
				p32nextsymbol (pc, partbuf, *part1len);
				break;
			default:
				{
					parcnt2 = 0;
					do
					{
						switch (*symb)
						{
						case CPC_CS_LEFTBRC:
							parcnt2++;
							break;
						case CPC_CS_RIGHTBRC:
							parcnt2--;
							break;
						}
						p32nextsymbol (pc, partbuf,
							*part1len);
					}
					while (parcnt2 > 0 &&
						*symb != CPC_CS_EOF &&
						*symb != CPC_CS_BUFEOF);
					*error = (BOOLEAN) (parcnt2 != 0);
				}
			}
		while (parcnt1 > 0 && *symb != CPC_CS_EOF &&
			*symb != CPC_CS_BUFEOF && !*error);
		*error = (BOOLEAN) (*error || parcnt1 > 0);
	}
	else
		while (*symb != CPC_CS_COMMA && *symb != CPC_CS_EOF &&
			*symb != CPC_CS_BUFEOF)
		{
			parcnt2 = 0;
			do
			{
				switch (*symb)
				{
				case CPC_CS_LEFTBRC:
					parcnt2++;
					break;
				case CPC_CS_RIGHTBRC:
					parcnt2--;
					break;
				}
				p32nextsymbol (pc, partbuf,
					*part1len);
			}
			while (parcnt2 > 0 && *symb != CPC_CS_EOF &&
				*symb != CPC_CS_BUFEOF);
			*error = (BOOLEAN) (parcnt2 != 0);
		}
}

static void p32mexpand (tpc_globals *pc)
/*
Erzeugung der dem Pseudotyp Varchar entsprechenden Macro - Aufrufe im Ausgabestrom.
Die Macro - Definitionen VARCHS, VARCHD, VARCHR, usw. befinden sich in vpi00c.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tsp00_Int2 symbsav = *symb;
	tsp00_Int4 len;
	tsp00_Int4 syposav = *syposacc;
	tsp00_Int4 pos = *part1len + 1;
	int p, l, basetype, typespec, storclspec, constspec;
	tsp00_Lname expname;
	
	M90TRACE(M90_TR_ENTRY, "p32mexpand   ", 0);
	*symb = CPR_S_UNKNOWN;
	p32nextsymbol (pc, partbuf, *part1len);
	len = *part1len;
	p = *sypos - 1;
	basetype = p32basetype (pc, expname, &storclspec, &typespec,
		&constspec);
	if (!basetype)
		while (typespec == ckStruct)
		{
			l = *syposacc - 1 - p;
			if (pos + l >= MXPR_PARTBUF)
				p11precomerror (pc, CPC_BUFFER_OVERFLOW);
			else
				memcpy (partbuf + pos, partbuf + p, l);
			pos += l;
			p = *syposacc - 1;
			p32nextsymbol (pc, partbuf, *part1len);
			if (*symb != CPC_CS_EOF)
			{
				l = *syposacc - 1 - p;
				if (pos + l >= MXPR_PARTBUF)
					p11precomerror (pc, CPC_BUFFER_OVERFLOW);
				else
					memcpy (partbuf + pos, partbuf +p, l);
				pos += l;
			}
			if (*symb == CPC_CS_IDENTIFIER)
			{
				p = *syposacc - 1;
				p32nextsymbol (pc, partbuf, *part1len);
				if (*symb != CPC_CS_EOF)
				{
					l = *syposacc - 1 - p;
					if (pos + l >= MXPR_PARTBUF)
						p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
					else
						memcpy (partbuf + pos,
							partbuf + p, l);
					pos += l;
				}
			}
			if (*symb == CPC_CS_LEFTBRC)
			{
				p = *syposacc - 1;
				p32nextsymbol (pc, partbuf, *part1len);
				basetype = p32basetype (pc, expname,
					&storclspec, &typespec, &constspec);
			}
			else
				typespec = 0;
		}
	if (basetype && typespec == ckVarchar)
	{
		static const char VARCHS [] = "VARCHS(";
		static const int LVARCHS = sizeof (VARCHS) - 1;
		int expl, p1, l1, ptr;
		BOOLEAN error;
		
		syposav = *part1len + 2;
		p = 0;
		if (storclspec > 0)
			p = p32kwcpy ((char *) expname, storclspec);
		memcpy (expname + p, VARCHS, LVARCHS);
		expl = p + LVARCHS;
		p1 = 0;
		while (*symb != CPC_CS_EOF)
		{
			p = *sypos - 1;
			l = *sylen;
			l1 = 0;
			ptr = (*symb == CPC_CS_ASTERISK);
			if (ptr)
				p32nextsymbol (pc, partbuf, *part1len);
			while (*symb != CPC_CS_EQUAL && *symb != CPC_CS_COMMA &&
				*symb != CPC_CS_EOF)
			{
				p32nextsymbol (pc, partbuf, *part1len);
				if (*symb == CPC_CS_LEFTBRK)
				{
					l = *sypos - 1 - p;
					p32nextsymbol (pc, partbuf,
						*part1len);
					p1 = *sypos - 1;
					l1 = *sylen;
					p32nextsymbol (pc, partbuf,
						*part1len);
				}
				else if (*symb == CPC_CS_EQUAL ||
					*symb == CPC_CS_COMMA ||
					*symb == CPC_CS_EOF)
				{
					if (pos + expl >= MXPR_PARTBUF)
						p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
					else
						memcpy (partbuf + pos,
							expname, expl);
					pos += expl;
					if (ptr)
					{
						l = *sypos - 1 - p;
						if (pos + 1 >= MXPR_PARTBUF)
							p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
						else
							partbuf [pos] = '1';
						pos++;
					}
					else
					{
						if (pos + l1 >= MXPR_PARTBUF)
							p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
						else
							memcpy (partbuf + pos,
							partbuf + p1, l1);
						pos += l1;
					}
					if (pos + 1 >= MXPR_PARTBUF)
						p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
					else
						partbuf [pos] = ')';
					pos++;
					if (pos + l >= MXPR_PARTBUF)
						p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
					else
						memcpy (partbuf + pos,
							partbuf + p, l);
					pos += l;
				}
				else
				{
					if (pos + *sylen >= MXPR_PARTBUF)
						p11precomerror (pc,
							CPC_BUFFER_OVERFLOW);
					else
						memcpy (partbuf + pos,
							partbuf + *sypos,
							*sylen);
					pos += *sylen;
				}
			}
			if (*symb == CPC_CS_EQUAL)
			{
				p = *sypos - 1;
				p32nextsymbol (pc, partbuf, *part1len);
				p32skpinit (pc, &error);
				l = *sypos - 1 - p;
				if (pos + l >= MXPR_PARTBUF)
					p11precomerror (pc, CPC_BUFFER_OVERFLOW);
				else
					memcpy (partbuf + pos, partbuf + p,
						l);
				pos += l;
			}
			if (*symb == CPC_CS_COMMA)
			{
				if (pos + 1 >= MXPR_PARTBUF)
					p11precomerror (pc, CPC_BUFFER_OVERFLOW);
				else
					partbuf [pos] = ';';
				pos++;
				p32nextsymbol (pc, partbuf, *part1len);
			}
		}
		len = pos + 1;
	}
	*syposacc = syposav;
	*part1len = len;
	if (*part1len - *syposacc > 1 || partbuf [*syposacc - 1] != ' ')
	{
		partbuf [*part1len - 1] = ';';
		(*part1len)++;
	}
	p31outstmt (pc);
	p31outstmt (pc);
	*symb = symbsav;
	M90TRACE(M90_TR_EXIT, "p32mexpand   ", 0);
}

static void p32declist (tpc_globals *pc, int initpossible, int typixin,
	tsp00_Lname decname, tsp00_Int4 *decnl, tsp00_Int2 *typixout)
/*
Analyse des naechsten Deklarators in der Liste der Deklaratoren einer Deklaration.
Zulaessig ist folgende Syntax:
<decl list>  ::= <init decl> |
                 <decl list>, <init decl>
<init decl>  ::= <declarator> |
                 <declarator> = <initializer>
<declarator> ::= <identifier> |
                 <array decl> |
                 <pointer>
<array decl> ::= <declarator> [unsigned integer]
<pointer>    ::= *<declarator>
Runde Klammern sind nicht zugelassen. Der resultierende Typ darf kein "pointer
to array" sein. Initializer werden, falls vorhanden und zulaessig, ignoriert.
Aus den Type Specifiers der Deklaration, aus denen sich typixin ergibt, und dem
Deklarator wird der resultierende Typ gebildet und, falls noch nicht vorhanden,
in die Typtabelle pc->pcSymtab.typtablep eingetragen.

Parameter:
initpossible ist genau dann von null verschieden ("true"), wenn Initializer
             zulaessig sind, d.h. fuer Variablen- und Typdeklarationen, nicht
	     aber in Field Lists einer struct - Deklaration.
typixin      ist ein Index in die Typtabelle, der sich aus den Type Specifiers
             der Deklaration ergeben hat (z.B. aus dem Rueckgabeparameter
	     typename von p32basetype).
decname      gibt den deklarierten Identifier zurueck.
decnl        gibt die Anzahl der Zeichen des Identifiers an.
typixout     gibt den aus typixin und dem Deklarator resultierenden Index in
             die Typtabelle zurueck. Hierbei kann es sich um denselben Index,
	     einen anderen bestehenden oder den eines Neueintrags handeln.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	BOOLEAN error = FALSE;

	tsp00_Int2 typix, typix1, indi;
	tsp00_Int4 len;
	tsp00_Int2 dig;
	int keyind;
	long val = 0;
	
	if (*symb == CPC_CS_ASTERISK)
	{
		tpc_typent *tt = pc->pcSymtab.typtablep + typixin - 1;
		if (tt->sc.tyPtr > 0 || tt->sc.tyIndi == CPR_VARRAY ||
			tt->sc.tyIndi == CPR_VCHARC ||
			tt->sc.tyIndi == CPR_VFILEC ||
			tt->sc.tyIndi == CPR_VUNICODEC ||
			tt->sc.tyIndi == CPR_VRAW)
			p11precomerror (pc, CPC_INVALID_DECLARATOR);
		else if (tt->sc.tyIndi == CPR_VSTRUCT)
			p19ptrindex (pc, tt->sc.tyIndi, 0, tt->st.tyCmpIx, 0,
				&typix);
		else
		{
			switch (tt->sc.tyIndi)
			{
			case CPR_VCHAR:
				indi = CPR_VCHARC;
				len = 0;
				dig = 0;
				break;
			case CPR_VFILE:
				indi = CPR_VFILEC;
				len = 0;
				dig = 0;
				break;
			case CPR_VUNICODE:
				indi = CPR_VUNICODEC;
				len = 0;
				dig = 0;
				break;
			case CPR_VUCS2:
				indi = CPR_VUCS2;
				len = 0;
				dig = 0;
				break;
			case CPR_VUTF16:
				indi = CPR_VUTF16;
				len = 0;
				dig = 0;
				break;
			case CPR_VSTRINGC:
				indi = CPR_VSTRING;
				len = 0;
				dig = 0;
				break;
			case CPR_VRAWC:
				p11precomerror (pc, CPC_INVALID_DECLARATOR);
				break;
			default:
				indi = tt->sc.tyIndi;
				len = tt->sc.tySize;
				dig = tt->sc.tyDigit;
			}
			p19ptrindex (pc, indi, len, dig, tt->sc.tyFrac,
				&typix);
		}
		if (pc->pcError == CPC_PRE_OK)
			if (typix > 0)
				typixin = typix;
			else
			{
				tpc_typent *ttn = (tpc_typent*)
					p03dynalloc (&p32typtabled);
				pc->pcSymtab.typCnt++;
				memcpy (ttn, tt, sizeof (tpc_typent));
				typixin = pc->pcSymtab.typCnt;
				ttn->sc.tyRef = 0;
				ttn->sc.tyPtr = 1;
				ttn->sc.tyDigit = 0;
				switch (ttn->sc.tyIndi)
				{
				case CPR_VCHAR:
					ttn->sc.tyIndi = CPR_VCHARC;
					ttn->sc.tySize = 0;
					break;
				case CPR_VFILE:
					ttn->sc.tyIndi = CPR_VFILEC;
					ttn->sc.tySize = 0;
					break;
				case CPR_VUNICODE:
					ttn->sc.tyIndi = CPR_VUNICODEC;
					ttn->sc.tySize = 0;
					break;
				case CPR_VUCS2:
					ttn->sc.tyIndi = CPR_VUCS2;
					ttn->sc.tySize = 0;
					break;
				case CPR_VUTF16:
					ttn->sc.tyIndi = CPR_VUTF16;
					ttn->sc.tySize = 0;
					break;
				case CPR_VRAWC:
					ttn->sc.tyIndi = CPR_VRAW;
					ttn->sc.tySize = 0;
					break;
				case CPR_VSTRINGC:
					ttn->sc.tyIndi = CPR_VSTRING;
					ttn->sc.tySize = 0;
				}
			}
		p32nextsymbol (pc, partbuf, *part1len);
		p32getkeyword (pc, &keyind);
		if (keyind == ckConst)
			p32nextsymbol (pc, partbuf, *part1len);
	}
	if (*symb != CPC_CS_IDENTIFIER)
	{
		p11precomerror (pc, CPC_INVALID_DECLARATOR);
		return;
	}
	if (pc->sqlca.sqlrap->rasqlansi == CPR_KIND_ANSI)
	{
		if ((*sylen == 7 && memcmp ("SQLCODE", partbuf + *sypos - 1,
			*sylen) == 0) || (*sylen == 8 &&
			memcmp ("SQLSTATE", partbuf + *sypos -1, *sylen)
			== 0))
			partbuf [*syposacc - 2] = '_';
	}
	*decnl = *sylen;
	if (*decnl > sizeof (tsp00_Lname))
		p11precomerror (pc, CPC_INVALID_DECLARATOR);
	else
	{
		memcpy (decname, partbuf + *sypos - 1, *decnl);
		if (*decnl < sizeof (tsp00_Lname))
			memset (decname + *decnl, ' ',
				sizeof (tsp00_Lname) - *decnl);
	}
	typix = pc->pcSymtab.typCnt;
	*typixout = (tsp00_Int2) typixin;
	p32nextsymbol (pc, partbuf, *part1len);
	while (*symb == CPC_CS_LEFTBRK)
	{
		p32nextsymbol (pc, partbuf, *part1len);
		if (*symb == CPC_CS_UNSIGNED)
		{
			char fmt [20];
			tsp00_Int4 vlen = sizeof (fmt) - 4;
			if (*sylen > vlen)
				p11precomerror (pc, CPC_CONST_TOO_LARGE);
			else
			{
				sprintf (fmt, "%%%dld", *sylen);
				sscanf (partbuf + *sypos - 1, fmt, &val);
			}
		}
		else if (*symb ==CPC_CS_IDENTIFIER)
		{
			tsp00_Lname constname;
			int index;
			if (*sylen > sizeof (tsp00_Lname))
				p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
			else
			{
				memcpy (constname, partbuf + *sypos - 1,
					*sylen);
				if (*sylen < sizeof (tsp00_Lname))
					memset (constname + *sylen, ' ',
						sizeof (tsp00_Lname) - *sylen);
				p19scname (pc, constname, &index);
				if (index > 0)
					val = pc->pcCse.csec[index -1].cwert;
				else
					p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
			}
		}
		else
			p11precomerror (pc, CPC_INVALID_DECLARATOR);
		p32nextsymbol (pc, partbuf, *part1len);
		if (*symb != CPC_CS_RIGHTBRK)
			p11precomerror (pc, CPC_INVALID_DECLARATOR);
		else
		{
			if (val == 0)
				p11precomerror (pc, CPC_INVALID_DECLARATOR);
			p32nextsymbol (pc, partbuf, *part1len);
		}
		if (pc->pcError == CPC_PRE_OK)
		{
			tpc_typent *tt = pc->pcSymtab.typtablep + typixin - 1;
			tpc_typent *ttn =
				(tpc_typent*) p03dynalloc (&p32typtabled);
			typix++;
			ttn->ar.tyIndi = CPR_VARRAY;
			ttn->ar.tyDim = (tsp00_Int4) val;
			ttn->ar.tyFix = 0;
			ttn->ar.tyTypIx = typix + (tsp00_Int2) 1;
			ttn->ar.tyRef = 0;
			ttn->ar.tyPtr = (tsp00_Int2) ((tt->sc.tyPtr) ? -1 : 0);
		}
	}
	if (initpossible && *symb == CPC_CS_EQUAL)
	{
		p32nextsymbol (pc, partbuf, *part1len);
		p32skpinit (pc, &error);
	}
	if (*symb == CPC_CS_COMMA)
		p32nextsymbol (pc, partbuf, *part1len);
	else if (*symb != CPC_CS_EOF || error)
		p11precomerror (pc, CPC_INVALID_DECLARATOR);
	if (pc->pcError != CPC_PRE_OK)
		*typixout = 0;
	else
	{
		if (typix > pc->pcSymtab.typCnt)
		{
			tpc_typent *tt = pc->pcSymtab.typtablep + typixin - 1;
			tpc_typent *ttn = pc->pcSymtab.typtablep + typix - 1;
			*typixout = (tsp00_Int2) (pc->pcSymtab.typCnt + 1);
			if (tt->sc.tyIndi != CPR_VCHAR &&
				tt->sc.tyIndi != CPR_VFILE &&
				tt->sc.tyIndi != CPR_VUNICODE &&
				tt->sc.tyIndi != CPR_VUCS2 &&
				tt->sc.tyIndi != CPR_VUTF16 &&
				tt->sc.tyIndi != CPR_VRAWC &&
				tt->sc.tyIndi != CPR_VSTRINGC)
				ttn->ar.tyTypIx = (tsp00_Int2) typixin;
			else
			{
				p19typindex (pc, (tt->sc.tyIndi == CPR_VCHAR)?
					CPR_VCHARC :
					(tt->sc.tyIndi == CPR_VFILE) ?
					CPR_VFILEC :
					(tt->sc.tyIndi == CPR_VUNICODE) ?
					CPR_VUNICODEC :
					(tt->sc.tyIndi == CPR_VUCS2) ?
					CPR_VUCS2 :
					(tt->sc.tyIndi == CPR_VUTF16) ?
					CPR_VUTF16 :
					(tt->sc.tyIndi == CPR_VSTRINGC) ?
					CPR_VSTRING : CPR_VRAW,
					(tt->sc.tyIndi == CPR_VSTRINGC) ?
					((val + 3)/2)*2 :
					(tt->sc.tyIndi == CPR_VUNICODE) ?
					2 * val : val, 0, 0, &typix1);
				if (typix1 > 0)
				{
					typix--;
					p32typtabled.descNelem--;
					if (typix > pc->pcSymtab.typCnt)
						pc->pcSymtab.typtablep
							[typix - 1].
							ar.tyTypIx = typix1;
					else
						*typixout = typix1;
				}
				else
				{
					ttn->sc.tyIndi = (tsp00_Int2) (
						(tt->sc.tyIndi == CPR_VCHAR) ?
						CPR_VCHARC :
						(tt->sc.tyIndi == CPR_VFILE) ?
						CPR_VFILEC :
						(tt->sc.tyIndi ==CPR_VUNICODE)
						? CPR_VUNICODEC :
						(tt->sc.tyIndi ==CPR_VUCS2)
						? CPR_VUCS2 :
						(tt->sc.tyIndi ==CPR_VUTF16)
						? CPR_VUTF16 :
						(tt->sc.tyIndi ==CPR_VSTRINGC)
						? CPR_VSTRING : CPR_VRAW);
					ttn->sc.tySize = (tsp00_Int4)  (
						(tt->sc.tyIndi ==CPR_VSTRINGC)
						? ((val + 3)/2)*2 :
						(tt->sc.tyIndi ==CPR_VUNICODE)
						? 2 * val : val);
					ttn->sc.tyDigit = (tsp00_Int2) val;
					ttn->sc.tyFrac =
					ttn->sc.tyRef =
					ttn->sc.tyPtr = 0;
				}
				
			}
			pc->pcSymtab.typCnt = typix;
		}
		if (pc->pcSymtab.typtablep [*typixout - 1].sc.tyIndi ==
			CPR_VSTRINGC)
			p11precomerror (pc, CPC_INVALID_DECLARATOR);
	}
}

static void p32decimal (tpc_globals *pc, const char *typename,
	int *typeind, int constspec)
/* Eintrag eines mit Hilfe des Decimal - Pseudotyp - Deklarators erzeugten
neuen Typs in die Tabelle pc->pcSymtab.typtablep. Falls ein Tag vorhanden
ist, wird dieser mit p32newtag eingetragen.

Parameter:
typename    Tag - Name oder Leerzeichen, falls nicht vorhanden.
typeind     gibt den Index des Typs (beginnend bei 1) in pc->pcSymtab.typtablep
            zurueck.
constspec   ist ckConst, falls die Decimal - De den const - Specifier
            enthaelt, nichtpositiv sonst.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tsp00_Int2 len, scale;
	
	len = 5;
	scale = 0;
	if (*symb == CPC_CS_UNSIGNED || *symb == CPC_CS_IDENTIFIER)
	{
		if (*symb == CPC_CS_UNSIGNED)
		{
			char fmt [20];
			tsp00_Int4 vlen = sizeof (fmt) - 4;
			long val;
			if (*sylen > vlen)
				p11precomerror (pc, CPC_CONST_TOO_LARGE);
			else
			{
				sprintf (fmt, "%%%dld", *sylen);
				sscanf (partbuf + *sypos - 1, fmt, &val);
				len = (tsp00_Int2) val;
				if ((long) len != val)
					p11precomerror (pc, CPC_CONST_TOO_LARGE);
			}
		}
		else
		{
			tsp00_Lname constname;
			int index;
			if (*sylen > sizeof (tsp00_Lname))
				p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
			else
			{
				memcpy (constname, partbuf + *sypos - 1,
					*sylen);
				if (*sylen < sizeof (tsp00_Lname))
					memset (constname + *sylen, ' ',
						sizeof (tsp00_Lname) - *sylen);
				p19scname (pc, constname, &index);
				if (index > 0)
					len = pc->pcCse.csec[index -1].cwert;
				else
					p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
			}
		}
		p32nextsymbol (pc, partbuf, *part1len);
		if (*symb == CPC_CS_COMMA)
		{
			p32nextsymbol (pc, partbuf, *part1len);
			if (*symb == CPC_CS_UNSIGNED)
			{
				char fmt [20];
				tsp00_Int4 vlen = sizeof (fmt) - 4;
				long val;
				if (*sylen > vlen)
					p11precomerror (pc, CPC_CONST_TOO_LARGE);
				else
				{
					sprintf (fmt, "%%%dld", *sylen);
					sscanf (partbuf + *sypos - 1, fmt,
						&val);
					scale = (tsp00_Int2) val;
					if ((long) scale != val)
						p11precomerror (pc,
							CPC_CONST_TOO_LARGE);
				}
			}
			else if (*symb == CPC_CS_IDENTIFIER)
			{
				tsp00_Lname constname;
				int index;
				if (*sylen > sizeof (tsp00_Lname))
					p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
				else
				{
					memcpy (constname,
						partbuf + *sypos - 1, *sylen);
					if (*sylen < sizeof (tsp00_Lname))
						memset (constname + *sylen,
							' ',
							sizeof (tsp00_Lname) -
							*sylen);
						p19scname (pc, constname,
							&index);
						if (index > 0)
							scale =
							pc->pcCse.
							csec[index -1].cwert;
						else
							p11precomerror (pc,
							CPC_UNKNOWN_CONSTNAME);
				}
			}
			else
				p11precomerror (pc, CPC_INVALID_DATATYPE);
			p32nextsymbol (pc, partbuf, *part1len);
		}
	}
	if (*symb != CPC_CS_RIGHTBRC || len >= 16 || (long) scale >= len)
		p11precomerror (pc, CPC_INVALID_DATATYPE);
	else
	{
		tsp00_Int2 typix;
		tsp00_Int4 size = len / 2 + 1;
		p19typindex (pc, CPR_VDECIMAL, size, len, scale, &typix);
		*typeind = typix;
		if (*typeind == 0)
		{
			tpc_typent *ttn =
				(tpc_typent*) p03dynalloc (&p32typtabled);
			pc->pcSymtab.typCnt++;
			*typeind = pc->pcSymtab.typCnt;
			ttn->sc.tyRef = 0;
			ttn->sc.tyPtr = 0;
			ttn->sc.tyIndi = CPR_VDECIMAL;
			ttn->sc.tySize = size;
			ttn->sc.tyDigit = len;
			ttn->sc.tyFrac = scale;
		}
		if (typename [0] != ' ')
			p32newtag (pc, *typeind, typename, constspec);
	}
}

static void p32typedef (tpc_globals *pc, int typeind, int consttype,
	int constspec)
/*
Eintrag der in einer typedef - Deklaration definierten Typnamen in die Tabelle
p32symtab.tyntab. Hierzu findet p32declist den naechsten Deklarator in der
Liste der Deklaratoren, bis diese vollstaendig abgearbeitet ist, und p32newtyn
nimmt den zugehoerigen Eintrag vor.

Parameter:
typeind     bezeichnet den Index des Eintrags pc->pcSymtab.typtablep [typeind - 1]
            des sich aus den Type Specifiers der Deklaration ergebenden
	    definierenden Typs.
consttype   ist genau dann von null verschieden, wenn der definierende Typ ein
            konstanter Typ ist (Variablen dieses Typs duerfen keine Werte
	    zugewiesen werden).
constspec   ist ckConst, falls die typedef - Deklaration den const - Specifier
            enthaelt, nichtpositiv sonst.
*/
{
	tsp00_Int2 *symb = &pc->pcScan.symb;
	tsp00_Int4 newnl;
	tsp00_Int2 typix;
	tsp00_Lname newname;

	if (typeind == 0)
		p11precomerror (pc, CPC_UNKNOWN_TYPENAME);
	while ((*symb == CPC_CS_IDENTIFIER || *symb == CPC_CS_ASTERISK) &&
		pc->pcError == CPC_PRE_OK)
	{
		p32declist (pc, FALSE, typeind, newname, &newnl, &typix);
		p32newtyn (pc, typeind, typix, consttype, constspec, 
			   (char *) newname);
	}
	if (*symb != CPC_CS_EOF)
		p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
}

static void p32vardef (tpc_globals *pc, int strind, int typeind,
	int consttype, int constspec)
/*
Eintrag eines deklarierten Variablennamens und des Verweises auf die zugehoerige
Typinformation in die Variablentabelle pc->pcSymtab.vartablep. Feldnamen aus
struct - Deklarationen werden hier ebenfalls eingetragen und als solche
gekennzeichnet (vastrix > 0).

Parameter:
strind      ist genau dann von null verschieden ("true"), wenn ein Feldname einer
            Struktur (struct - Deklaration) eingetragen werden soll. Dieser Wert
	    wird in das Feld vastrix der Variablentabelle eingetragen.
typeind     bezeichnet den Index des Eintrags pc->pcSymtab.typtablep [typeind - 1]
            des sich aus den Type Specifiers der Deklaration ergebenden
	    definierenden Typs.
consttype   ist genau dann von null verschieden, wenn der definierende Typ ein
            konstanter Typ ist (Variablen dieses Typs duerfen keine Werte
	    zugewiesen werden).
constspec   ist ckConst, falls die typedef - Deklaration den const - Specifier
            enthaelt, nichtpositiv sonst.
*/
{
	tsp00_Int2 *symb = &pc->pcScan.symb;
	tsp00_Int4 newnl;
	tsp00_Int2 ind, typix;
	int initpossible;
	tsp00_Lname newname;
	
	initpossible = (strind == 0 &&
		(pc->sqlca.sqldbmode == CPR_KIND_ORACLE ||
		pc->sqlca.sqldbmode == CPR_KIND_SAPR3 ||
		pc->sqlca.sqlrap->rasqlansi != CPR_KIND_ANSI));
	if (typeind == 0)
		p11precomerror (pc, CPC_UNKNOWN_TYPENAME);
	while ((*symb == CPC_CS_IDENTIFIER || *symb == CPC_CS_ASTERISK) &&
		pc->pcError == CPC_PRE_OK)
	{
		p32declist (pc, initpossible, typeind, newname, &newnl,
			&typix);
		if (strind == 0)
		{
			p19varindex (pc, (char *) newname, 0, &ind);
			if (ind > 0)
				p11precomerror (pc, CPC_DUPLICATE_VARDEF);
		}
		if (pc->pcError == CPC_PRE_OK)
		{
			tpc_varent *vt =
				(tpc_varent*) p03dynalloc (&p32vartabled);
			pc->pcSymtab.varCnt++;
			memcpy (vt->vaname, newname, sizeof (tsp00_Lname));
			vt->vanaml = (tsp00_Int2) newnl;
			vt->vastrix = (tsp00_Int2) strind;
			vt->vatypix = typix;
			vt->vasqlix = 0;
			vt->vacnt = 0;
			vt->vablockid = p32bid;
			vt->vaglobl = (tsp00_Int2) ((consttype > 0 ||
				(constspec > 0 &&
			pc->pcSymtab.typtablep [typeind - 1].sc.tyPtr <= 0)) ?
				CPC_CCONST : 0);
		}
	}
	if (*symb != CPC_CS_EOF)
		p11precomerror (pc, CPC_INVALID_VAR_DEFINITION);
}

void p32typequ (tpc_globals *pc)
/* Analyse der ORACLE - EXEC SQL TYPE - Anweisung.
Der ORACLE - Typ wird mit p32getorat bestimmt und mit p03orat auf den
aequivalenten internen Typ abgebildet. Anschliessend wird jeweils ein
neuer Eintrag in p32symtab.tyntab und pc->pcSymtab.typtablep vorgenommen.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tpc_typent *ttn;
	tsp00_Lname equname;
	tsp00_Int2 tnc, typix = 0;
	tsp00_Int2 tyindi, tydigit, tyfrac, typtr = 0;
	tsp00_Int4 len [2] = {-1, -1};
	tsp00_Int4 siz;
	int i;
	short orat = -1;

	p32nextsymbol (pc, partbuf, *part1len);
	if (*symb != CPC_CS_IDENTIFIER || *sylen > sizeof (tsp00_Lname))
		p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
	else
	{
		memcpy (equname, partbuf + *sypos - 1, *sylen);
		if (*sylen < sizeof (tsp00_Lname))
			memset (equname + *sylen, ' ',
				sizeof (tsp00_Lname) - *sylen);
		p32tynindex ((char *) equname, &tnc, &typix);
	}
	if (*symb != CPC_CS_EOF)
		p32nextsymbol (pc, partbuf, *part1len);
	if (*symb != CPC_CS_EOF)
		p32nextsymbol (pc, partbuf, *part1len);
	if (*symb == CPC_CS_IDENTIFIER)
		p32getorat (pc, &orat);
	if (*symb == CPC_CS_LEFTPAR)
	{
		for (i = 0; i < 2; i++)
		{
			p32nextsymbol (pc, partbuf, *part1len);
			if (*symb == CPC_CS_UNSIGNED)
			{
				char fmt [20];
				tsp00_Int4 vlen = sizeof (fmt) - 4;
				long val;
				if (*sylen > vlen)
					p11precomerror (pc,
						CPC_CONST_TOO_LARGE);
				else
				{
					sprintf (fmt, "%%%dld", *sylen);
					sscanf (partbuf + *sypos - 1, fmt,
						&val);
					len [i] = (tsp00_Int4) val;
					if ((long) len [i] != val)
						p11precomerror (pc,
							CPC_CONST_TOO_LARGE);
				}
				p32nextsymbol (pc, partbuf, *part1len);
			}
		}
		if (*symb != CPC_CS_EOF)
			p32nextsymbol (pc, partbuf, *part1len);
	}
	if (pc->pcError == CPC_PRE_OK)
	{
		switch (orat)
		{
		case SQL_ORA_VARNUM:
			len [0] = -1;
			siz = 23;
			break;
		case SQL_ORA_INTERNDATE:
			len [0] = -1;
			siz = 7;
			break;
		default:
			siz = len [0];
		}
		if (siz < 0)
		{
			p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
			siz = 0;
		}
		p04OraTypes2Internal (orat, siz, &tyindi, 0);
		switch (tyindi)
		{
		case CPR_VDECIMAL:
			tydigit = (tsp00_Int2) ((len [0] < 0) ? 0 : len [0]);
			tyfrac = (tsp00_Int2) ((len [1] < 0) ? 0 : len [1]);
			siz = tydigit / 2 + 1;
			if ((tsp00_Int4) tydigit != len [0] ||
				(tsp00_Int4) tyfrac != len [1] && tyfrac != 0)
				p11precomerror (pc,
					CPC_INVALID_TYPE_DEFINITION);
			break;
		case CPR_VSTRING:
			if (len [0] >= 0)
				siz = ((len [0] + 3) / 2) * 2;
			tydigit = (tsp00_Int2) (siz - 2);
			tyfrac = 0;
			break;
		case CPR_VSTRING1:
			if (len [0] >= 0)
				siz = len [0] + 1;
			tydigit = (tsp00_Int2) (siz - 1);
			tyfrac = 0;
			break;
		case CPR_VSTRING4:
			if (len [0] >= 0)
				siz = ((len [0] + 7) / 4) * 4;
			tydigit = (tsp00_Int2) (siz - 4);
			tyfrac = 0;
			break;
		case -1:
			p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
			break;
		default:
			tydigit = 0;
			tyfrac = 0;
		}
	}
	if (*symb == CPC_CS_IDENTIFIER)
	{
		int keyind;
		p32getkeyword (pc, &keyind);
		if (keyind == ckReference)
		{
			typtr = 1;
			p32nextsymbol (pc, partbuf, *part1len);
		}
		else
			p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
	}
	if (*symb != CPC_CS_EOF && pc->pcError == CPC_PRE_OK)
		p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
	if (pc->pcError == CPC_PRE_OK)
	{
		if (typix == 0)
		{
			p32tynent *t = (p32tynent*) p03dynalloc (&p32tyntabd);
			ttn = (tpc_typent*) p03dynalloc (&p32typtabled);
			pc->pcSymtab.typCnt++;
			p32symtab.tynCnt++;
			memcpy (t->tname, equname, sizeof (tsp00_Lname));
			t->tntypix = pc->pcSymtab.typCnt;
			t->tnconst = 0;
		}
		else
			ttn = pc->pcSymtab.typtablep + typix - 1;
		ttn->sc.tyRef = 0;
		ttn->sc.tyPtr = typtr;
		ttn->sc.tyIndi = tyindi;
		ttn->sc.tySize = siz;
		ttn->sc.tyDigit = tydigit;
		ttn->sc.tyFrac = tyfrac;
	}
}

void p32varequ (tpc_globals *pc)
/* Analyse der ORACLE - EXEC SQL VAR - Anweisung.
Der in der Anweisung verwendete Variablen - Identifier muss zuvor deklariert
worden sein. Ein entsprechender Eintrag in pc->pcSymtab.vartablep wird mit
p19varindex gesucht. Der ORACLE - Typ wird mit p32getorat bestimmt und mit
p03orat auf den aequivalenten internen Typ abgebildet. Anschliessend wird
ein neuer Eintrag in pc->pcSymtab.typtablep vorgenommen und der Typ - Verweis
in dem gefundenen Variableneintrag entsprechend abgeaendert.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tpc_typent *tt;
	tpc_varent *vt;
	tsp00_Lname equname;
	tsp00_Int2 varix = 0, typix = 0;
	tsp00_Int2 tyindi, tydigit, tyfrac;
	tsp00_Int4 len [2] = {-1, -1};
	tsp00_Int4 siz;
	int i;
	short orat = -1;

	p32nextsymbol (pc, partbuf, *part1len);
	if (*symb != CPC_CS_IDENTIFIER || *sylen > sizeof (tsp00_Lname))
		p11precomerror (pc, CPC_INVALID_VAR_DEFINITION);
	else
	{
		memcpy (equname, partbuf + *sypos - 1, *sylen);
		if (*sylen < sizeof (tsp00_Lname))
			memset (equname + *sylen, ' ',
				sizeof (tsp00_Lname) - *sylen);
		p19varindex (pc, (char *) equname, 0, &varix);
		if (varix == 0)
			p11precomerror (pc, CPC_UNKNOWN_PARAMETERNAME);
		else
		{
			vt = pc->pcSymtab.vartablep + varix - 1;
			tt = pc->pcSymtab.typtablep + vt->vatypix - 1;
		}
	}
	if (*symb != CPC_CS_EOF)
		p32nextsymbol (pc, partbuf, *part1len);
	if (*symb != CPC_CS_EOF)
		p32nextsymbol (pc, partbuf, *part1len);
	if (*symb == CPC_CS_IDENTIFIER)
		p32getorat (pc, &orat);
	if (*symb != CPC_CS_EOF)
	{
		for (i = 0; i < 2; i++)
		{
			p32nextsymbol (pc, partbuf, *part1len);
			if (*symb == CPC_CS_UNSIGNED)
			{
				char fmt [20];
				tsp00_Int4 vlen = sizeof (fmt) - 4;
				long val;
				if (*sylen > vlen)
					p11precomerror (pc,
						CPC_CONST_TOO_LARGE);
				else
				{
					sprintf (fmt, "%%%dld", *sylen);
					sscanf (partbuf + *sypos - 1, fmt,
						&val);
					len [i] = (tsp00_Int4) val;
					if ((long) len [i] != val)
						p11precomerror (pc,
							CPC_CONST_TOO_LARGE);
				}
				p32nextsymbol (pc, partbuf, *part1len);
			}
		}
		if (*symb != CPC_CS_EOF)
			p32nextsymbol (pc, partbuf, *part1len);
	}
	if (pc->pcError == CPC_PRE_OK)
	{
		switch (orat)
		{
		case SQL_ORA_VARNUM:
			len [0] = -1;
			siz = 23;
			break;
		case SQL_ORA_INTERNDATE:
			len [0] = -1;
			siz = 7;
			break;
		default:
			siz = len [0];
		}
		if (siz < 0)
		{
			if (tt->st.tyIndi == CPR_VSTRUCT ||
				tt->ar.tyIndi == CPR_VARRAY)
			{
				p11precomerror (pc,
					CPC_INVALID_VAR_DEFINITION);
				siz = 0;
			}
			else
				siz = tt->sc.tySize;
		}
		p04OraTypes2Internal (orat, siz, &tyindi, 0);
		switch (tyindi)
		{
		case CPR_VDECIMAL:
			tydigit = (tsp00_Int2) ((len [0] < 0) ? 0 : len [0]);
			tyfrac = (tsp00_Int2) ((len [1] < 0) ? 0 : len [1]);
			siz = tydigit / 2 + 1;
			if ((tsp00_Int4) tydigit != len [0] ||
				(tsp00_Int4) tyfrac != len [1] && tyfrac != 0)
				p11precomerror (pc,
					CPC_INVALID_VAR_DEFINITION);
			break;
		case CPR_VSTRING:
			if (len [0] >= 0)
				siz = ((len [0] + 3) / 2) * 2;
			tydigit = (tsp00_Int2) (siz - 2);
			tyfrac = 0;
			break;
		case CPR_VSTRING1:
			if (len [0] >= 0)
				siz = len [0] + 1;
			tydigit = (tsp00_Int2) (siz - 1);
			tyfrac = 0;
			break;
		case CPR_VSTRING4:
			if (len [0] >= 0)
				siz = ((len [0] + 7) / 4) * 4;
			tydigit = (tsp00_Int2) (siz - 4);
			tyfrac = 0;
			break;
		case -1:
			p11precomerror (pc, CPC_INVALID_VAR_DEFINITION);
			break;
		default:
			tydigit = 0;
			tyfrac = 0;
		}
	}
	if (*symb != CPC_CS_EOF && pc->pcError == CPC_PRE_OK)
		p11precomerror (pc, CPC_INVALID_VAR_DEFINITION);
	if (pc->pcError == CPC_PRE_OK)
	{
		p19typindex (pc, tyindi, siz, tydigit, tyfrac, &typix);
		if (typix == 0)
		{
			tpc_typent *ttn =
				(tpc_typent*) p03dynalloc (&p32typtabled);
			pc->pcSymtab.typCnt++;
			typix = pc->pcSymtab.typCnt;
			ttn->sc.tyRef = 0;
			ttn->sc.tyPtr = 0;
			ttn->sc.tyIndi = tyindi;
			ttn->sc.tySize = siz;
			ttn->sc.tyDigit = tydigit;
			ttn->sc.tyFrac = tyfrac;
		}
		vt->vatypix = typix;
	}
}

static void p32prepcomline (tpc_globals *pc)
/*
Eine zulaessige Preprocessor - Anweisung (Macrodefinition) hat die Syntax:
   <preprocessor statement> ::= #define <name> <definition>
   <name> ::= <identifier>
   <definition> ::= <identifier> |
                    <unsigned integer>
Ist <definition> eine natuerliche Zahl (<unsigned integer>), wird ein neuer
Eintrag in der Konstantentabelle pc->pcCse.csec vorgenommen. <name> wird
hierbei an cname und <definition> an cwert zugewiesen.
Ist <definition> ein <identifier>, wird in der Konstantentabelle nach einem
Eintrag gesucht, dessen Feld cname gleich ist (vorhandene Definition von
<identifier>). Dann wird ein neuer Eintrag, dessen cname auf <name> und
dessen cwert auf den cwert des gefundenen Eintrags gesetzt wird, erzeugt.
Alle anderen Situationen fuehren zu Fehlerausgaengen.
Die Konstantentabelle wird ueber den Deskriptor p32constd dynamisch verwaltet
(s. p03dynalloc).
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tpc_const_entry *ct = (tpc_const_entry*) p03dynalloc (&p32constd);
	int keyind, inddef, indnew;
	tsp00_Lname cnamdef;
	
	p32getkeyword (pc, &keyind);
	if (keyind != ckDefine)
	{
		p11precomerror (pc, CPC_INVALID_CPREP_COMMAND);
		return;
	}
	p32nextsymbol (pc, partbuf, *part1len);
	if (*symb != CPC_CS_IDENTIFIER)
	{
		p11precomerror (pc, CPC_CONST_DECLARE_WRONG);
		return;
	}
	if (*sylen > sizeof (tsp00_Lname))
	{
		p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
		return;
	}
	indnew = pc->pcCse.ccnt + 1;
	memcpy (ct->cname, partbuf + *sypos - 1, *sylen);
	if (*sylen < sizeof (tsp00_Lname))
		memset (ct->cname + *sylen, ' ', sizeof (tsp00_Lname) - *sylen);
	p32nextsymbol (pc, partbuf, *part1len);
	if (*symb == CPC_CS_UNSIGNED)
	{
		char fmt [20];
		tsp00_Int4 vlen = sizeof (fmt) - 4;
		long val;
		if (*sylen > vlen)
			p11precomerror (pc, CPC_CONST_TOO_LARGE);
		else
		{
			sprintf (fmt, "%%%dld", *sylen);
			sscanf (partbuf + *sypos - 1, fmt,
				&val);
			ct->cwert = (tsp00_Int2) val;
			if ((long) ct->cwert != val)
				p11precomerror (pc, CPC_CONST_TOO_LARGE);
		}
	}
	else if (*symb == CPC_CS_IDENTIFIER)
	{
		if (*sylen > sizeof (tsp00_Lname))
			p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
		else
		{
			memcpy (cnamdef, partbuf + *sypos - 1, *sylen);
			if (*sylen < sizeof (tsp00_Lname))
				memset (cnamdef + *sylen, ' ',
					sizeof (tsp00_Lname) - *sylen);
			p19scname (pc, cnamdef, &inddef);
			if (inddef > 0)
				ct->cwert = pc->pcCse.csec[inddef -1].cwert;
			else
				p11precomerror (pc, CPC_UNKNOWN_CONSTNAME);
		}
	}
	else
		p11precomerror (pc, CPC_CONST_DECLARE_WRONG);
	if (pc->pcError == CPC_PRE_OK)
		pc->pcCse.ccnt = (tsp00_Int2) indnew;
	else
		p32constd.descNelem--;
}

void p32fansi (tpc_globals *pc, BOOLEAN *indecl)
/*
Entfernen von Deklarationen von SQLCODE und SQLSTATE ausserhalb von
Declare Sections im ANSI - Modus.
ANSI - Testprogramme verlangen diese Deklarationen. Beide Symbole
muessen jedoch in vpi00c als Makros in Abhaengigkeit von sqlca -
Komponenten definiert werden, um in Referenzen die gewuenschten
Werte zu erhalten.

Parameter:
indecl      ist genau dann von null verschieden ("true"), wenn eine
            der "verdaechtigen" Deklarationen (long oder char) gefunden
	    wurde.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	
	if (*indecl)
	{
		if (*symb == CPC_CS_IDENTIFIER)
		{
			if (*sylen == 7 &&
				memcmp ("SQLCODE", partbuf + *sypos - 1,
				*sylen) == 0)
				p11rsout ();
			else if (*sylen == 8 &&
				memcmp ("SQLSTATE", partbuf + *sypos -1,
				*sylen) == 0)
			{
				p32nextsymbol (pc, partbuf, *part1len);
				if (*symb == CPC_CS_LEFTBRK)
				{
					p32nextsymbol (pc, partbuf,*part1len);
					p32nextsymbol (pc, partbuf,*part1len);
					if (*symb == CPC_CS_RIGHTBRK)
						p11rsout ();
				}
			}
		}
		else if (*symb == CPC_CS_EOF)
			*indecl = FALSE;
	}
	else
	{
		int i;
		p32getkeyword (pc, &i);
		*indecl = (BOOLEAN) (i == ckLong || i == ckChar);
	}
		
}

static void p32datova (tpc_globals *pc)
{
	sqldatype *da = (sqldatype*) pc->sqlca.sqlcxap->xasqldap;
	sqlvartype *var0 = da->sqlvar;
	sqlvartype *varn = da->sqlvar + da->sqln - 1;
	sqlvartype *var;
	tpc_cmpent *cmp0, *cmpn, *cmp;
	tpc_typent *ttn;
	tsp00_Int2 tindi, tdigit, tfrac, typix;
	tsp00_Int4 tsize;
	char *ptr;
	
	for (var = var0; var <= varn; var++)
	{
		tpc_varent *vt = (tpc_varent*) p03dynalloc (&p32vartabled);
		*((tpc_cmpent*) p03dynalloc (&p32cmpindexd)) =
			++pc->pcSymtab.varCnt;
		vt->vasqlix = 0;
		vt->vacnt = 0;
		vt->vaglobl = 0;
		vt->vablockid = p32bid;
		vt->vanaml = (tsp00_Int2) (((ptr = (char*)
			memchr (var->colname, ' ', sizeof (tsp00_Name))) == 0) ?
			sizeof (tsp00_Name) : ptr - (char *)var->colname);
		memcpy (vt->vaname, var->colname, sizeof (tsp00_Name));
		memset (vt->vaname + sizeof (tsp00_Name), ' ',
			sizeof (tsp00_Lname) - sizeof (tsp00_Name));
		switch (var->coltype)
		{
		case sqlfixed:
		case sqlsmallint:
		case sqlinteger:
			if (var->colfrac == 0)
			{
				if (var->collength > CPR_NUMBLEN_INT2)
				{
					tindi = CPR_VINT4;
					tdigit = CPR_NUMBLEN_INT4;
					tsize = 4;
				}
				else
				{
					tindi = CPR_VINT2;
					tdigit = CPR_NUMBLEN_INT2;
					tsize = 2;
				}
				tfrac = 0;
			}
			else
			{
				if (var->collength > CPR_NUMBLEN_R4)
				{
					tindi = CPR_VREAL8;
					tdigit = CPR_NUMBLEN_R8;
					tsize = 8;
				}
				else
				{
					tindi = CPR_VREAL4;
					tdigit = CPR_NUMBLEN_R4;
					tsize = 4;
				}
				tfrac = -1;
			}
			break;
		case sqlfloat:
		case sqlexpr:
			if (var->collength > CPR_NUMBLEN_R4)
			{
				tindi = CPR_VREAL8;
				tdigit = CPR_NUMBLEN_R8;
				tsize = 8;
			}
			else
			{
				tindi = CPR_VREAL4;
				tdigit = CPR_NUMBLEN_R4;
				tsize = 4;
			}
			tfrac = -1;
			break;
		case sqlchar:
		case sqlbyte:
		case sqldate:
		case sqltime:
		case sqltimestamp:
		case sqlvarchar:
		case sqlboolean:
		case sqlunicode:
			tindi = CPR_VCHARC;
			tsize = var->collength + 1;
			tdigit =
			tfrac = 0;
			break;
		case sqllong:
		case sqllongbyte:
		case sqloldlongchar:
		case sqloldlongbyte:
		case sqloldlonguni:
			tindi = CPR_VCHARC;
			tsize = sqlint2max;
			tdigit =
			tfrac = 0;
			break;
		case sqldbebcdic:
			tindi = CPR_VCHARC;
			tsize = 2 * var->collength + 1;
			tdigit =
			tfrac = 0;
			break;
		default:
			tindi = CPR_VNONE;
			tsize = 0;
			tdigit =
			tfrac = 0;
		}
		p19typindex (pc, tindi, tsize, tdigit, tfrac, &typix);
		if (typix == 0)
		{
			ttn = (tpc_typent*) p03dynalloc (&p32typtabled);
			typix = ++pc->pcSymtab.typCnt;
			ttn->sc.tyIndi = tindi;
			ttn->sc.tySize = tsize;
			ttn->sc.tyDigit = tdigit;
			ttn->sc.tyFrac = tfrac;
			ttn->sc.tyRef = 0;
			ttn->sc.tyPtr = 0;
		}
		vt->vatypix = typix;
	}
	if (pc->pcDclgen.indclause == cpr_is_true)
	{
		for (var = var0; var <= varn; var++)
		{
			tpc_varent *vt =
				(tpc_varent*) p03dynalloc (&p32vartabled);
			*((tpc_cmpent*) p03dynalloc (&p32cmpindexd)) =
				++pc->pcSymtab.varCnt;
			vt->vasqlix = 0;
			vt->vacnt = 0;
			vt->vaglobl = 0;
			vt->vablockid = p32bid;
			vt->vanaml = (tsp00_Int2) (((ptr = (char*)
				memchr (var->colname, ' ', sizeof (tsp00_Name)))
				== 0) ? sizeof (tsp00_Name) + 1 :
				ptr - (char *)var->colname + 1);
			vt->vaname [0] = 'I';
			memcpy (vt->vaname + 1, var->colname,
				sizeof (tsp00_Name));
			memset (vt->vaname + sizeof (tsp00_Name) + 1, ' ',
				sizeof (tsp00_Lname) - sizeof (tsp00_Name) - 1);
			p19typindex (pc, CPR_VINT2, 2, CPR_NUMBLEN_INT2, 0, &typix);
			if (typix == 0)
			{
				ttn = (tpc_typent*)
					p03dynalloc (&p32typtabled);
				typix = ++pc->pcSymtab.typCnt;
				ttn->sc.tyIndi = CPR_VINT2;
				ttn->sc.tySize = 2;
				ttn->sc.tyDigit = CPR_NUMBLEN_INT2;
				ttn->sc.tyFrac = 0;
				ttn->sc.tyRef = 0;
				ttn->sc.tyPtr = 0;
			}
			vt->vatypix = typix;
		}
		ttn = (tpc_typent*) p03dynalloc (&p32typtabled);
		typix = ++pc->pcSymtab.typCnt;
		cmp0 = pc->pcSymtab.cmpindexp + pc->pcSymtab.cmpCnt +
			da->sqln;
		cmpn = pc->pcSymtab.cmpindexp + pc->pcSymtab.cmpCnt +
			2 * da->sqln - 1;
		for (cmp = cmp0; cmp <= cmpn; cmp++)
			pc->pcSymtab.vartablep [*cmp - 1].vastrix = typix;
		ttn->st.tyIndi = CPR_VSTRUCT;
		ttn->st.tyCmpIx = pc->pcSymtab.cmpCnt + da->sqln +
			(tsp00_Int2) 1;
		ttn->st.tyCmCnt = da->sqln;
		ttn->st.tyRef = 0;
		ttn->st.tyPtr = 0;
	}
	ttn = (tpc_typent*) p03dynalloc (&p32typtabled);
	typix = ++pc->pcSymtab.typCnt;
	cmp0 = pc->pcSymtab.cmpindexp + pc->pcSymtab.cmpCnt;
	cmpn = pc->pcSymtab.cmpindexp + pc->pcSymtab.cmpCnt + da->sqln - 1;
	for (cmp = cmp0; cmp <= cmpn; cmp++)
		pc->pcSymtab.vartablep [*cmp - 1].vastrix = typix;
	ttn->st.tyIndi = CPR_VSTRUCT;
	ttn->st.tyCmpIx = pc->pcSymtab.cmpCnt + (tsp00_Int2) 1;
	ttn->st.tyCmCnt = da->sqln;
	ttn->st.tyRef = 0;
	ttn->st.tyPtr = 0;
	pc->pcSymtab.cmpCnt += da->sqln;
	if (pc->pcDclgen.indclause == cpr_is_true)
		pc->pcSymtab.cmpCnt += da->sqln;
}

void p32dclgen (tpc_globals *pc, tsp00_Int2 *typix)
/*
Analyse der EXEC SQL INCLUDE ... TABLE ... - Anweisung.
Je nach Art der AS - Klausel wird ein Eintrag in die Typnamen -, Variablen -
oder Tag - Tabelle und, falls die IND - Klausel angegeben ist, ein weiterer
Eintrag fuer den Indikator vorgenommen.

Parameter:
typix       gibt den Index (mit 1 beginnend) in pc->pcSymtab.typtablep, der
            die durch die Datenbanktabelle definierte Struktur beschreibt,
	    zurueck.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	tpc_dclgen *dgen = &pc->pcDclgen;
	int i, nent;
	tsp00_Lname nam;
	
	nent = (dgen->indclause == cpr_is_true) ? 2 : 1;
	p32datova (pc);
	*typix = pc->pcSymtab.typCnt;
	for (i = 0; i < nent; i++)
	{
		tpc_dclclause *cl = &dgen->clause [i];
		memcpy (partbuf, cl->dclattr, cl->dclattrl);
		*syposacc = 1;
		*symb = CPC_CS_UNKNOWN;
		*part1len = cl->dclattrl + 1;
		partbuf [cl->dclattrl] = '\0';
		p32nextsymbol (pc, partbuf, *part1len);
		switch (dgen->asclause)
		{
		case CPC_AS_VAR:
			p32sVarbot (pc);
			p32vardef (pc, 0, *typix - i, 0, 0);
			p32rVarbot (pc);
			break;
		case CPC_AS_TYPE:
			p32sTynbot ();
			p32typedef (pc, *typix - i, 0, 0);
			p32rTynbot ();
			break;
		case CPC_AS_STRUCT:
			if (*symb != CPC_CS_IDENTIFIER ||
				*sylen > sizeof (tsp00_Lname))
				p11precomerror (pc, CPC_INVALID_DECLARATOR);
			else
			{
				memcpy (nam, partbuf + *sypos - 1, *sylen);
				if (*sylen < sizeof (tsp00_Lname))
					memset (nam + *sylen, ' ',
						sizeof (tsp00_Lname) - *sylen);
				p32newtag (pc, *typix - i, (char *) nam, 0);
			}
			break;
		}
	}
}

static void p32strudef (tpc_globals *pc,  tsp00_Lname typename, int constspec,
	int *typeind, tsp00_Int4 *syposav, tsp00_Int2 *symbsav);
/*
Forward - Deklaration von p32strudef.
*/

static void p32declaration (tpc_globals *pc, int strind,
	tsp00_Int2 *varind, tsp00_Int4 *syposav, tsp00_Int2 *symbsav)
/*
Eine zulaesssige Deklaration hat die Syntax:
   <declaration> ::= <decl spec> <decl list>
   <decl spec>   ::= <stor class> |
                     <type spec> |
		     <decl spec> <stor class> |
		     <decl spec> <type spec>
   <stor class>  ::= auto |
                     extern |
		     static |
		     typedef
   <type spec>   ::= <base type> |
                     <stru spec> |
		     <dcml spec> |
		     <type id>
   <stru spec>   ::= <stru def> |
                     <stru ref>
   <dcml spec>   ::= <dcml def> |
                     <dcml ref>
   <stru def>    ::= struct {field list} |
                     struct <tag id> {field list}
   <stru ref>    ::= struct <tag id>
   <dcml def>    ::= decimal {<dcml len>} |
                     decimal <tag id> {<dcml len}
   <dcml ref>    ::= decimal <tag id>
   <field list>  ::= <declaration>; |
                     <field list> <declaration>;
   <dcml len>    ::= <length> |
                     <length> , <scale> |
		     <empty>
   <length>      ::= <int par>
   <scale>       ::= <int par>
   <int par>     ::= <identifier> |
                     <unsigned integer>
   <type id>     ::= <identifier>
   <tag id>      ::= <identifier>
   <empty>       ::=
Den Zweigen der Produktionen entsprechen Unterprogramme. Verzweigt wird nach
Vergleich des naechsten Tokens des Eingabestroms.
p32basetype ermittelt zuerst, ob ein Grunddatentyp vorliegt und liefert als
Rueckgabeparameter verschiedene Token fuer die weiteren Entscheidungen.
p32strudef behandelt den Zweig <stru def>. Zur Analyse der <field list> wird
p32declaration rekursiv aufgerufen, entsprechend der Rekursion in den Produktionen
von <field list>.
p32decimal schliesslich behandelt den Zweig <dcml def>.
Falls <stru ref> oder <dcml ref> vorliegen, ermittelt p32tagindex, ob bereits
eine entspechende Definition mit dem gleichen <tag id> vorliegt.
Falls ein Type Identifier gefunden wurde, ermittelt p32tynindex, ob bereits
ein typedef - Eintrag mit dem gleichen <type id> vorliegt.
Zum Schluss wird <decl list> durch p32vardef oder, falls die ermittelte storage
class typedef war (Rueckgabe von p32basetype), p32typedef analysiert und das
Ergebnis in die entsprechenden Tabellen eingetragen.

Parameter:
strind      Eingabeparameter, der angibt ob es sich um den Aufruf der obersten
            Stufe (0) oder einen rekursiven Aufruf (1) von p32declaration handelt
varind      Rueckgabeparameter, der den Index in pc->pcSymtab.vartablep, der der
            ersten in <decl list> deklarierten Variablen entspricht, angibt.
	    Dieser unterscheidet sich i. A. von dem Wert, den pc->pcSymtab.varCnt
	    vor dem aktuellen Aufruf von p32declaration hatte, da die Deklarationen
	    aus <field list> in dieselbe Tabelle eingetragen werden.
syposav und
symbsav     Rueckgabeparameter, die geretteten Werten von sypos und symb (s.
            p32nextsymbol) entsprechen, und fuer die Code-Erzeugung benoetigt
	    werden.
*/
{
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	int typespec, typeind, storclspec, constspec;
	tsp00_Int4 sypos1;
	tsp00_Int2 tnc, ind;
	tsp00_Lname typename;
	
	*varind = pc->pcSymtab.varCnt;
	if (p32basetype (pc, typename, &storclspec, &typespec, &constspec))
	{
		if (pc->pcError == CPC_PRE_OK)
		{
			p32tynindex ((char *) typename, &tnc, &ind);
			typeind = p32tyntyp (ind);
			if (storclspec == ckTypedef)
			{
				p32sTynbot ();
				p32typedef (pc, typeind, tnc, constspec);
				p32rTynbot ();
			}
			else
			{
				p32sVarbot (pc);
				p32vardef (pc, strind, typeind, tnc,
					constspec);
				p32rVarbot (pc);
			}
		}
	}
	else if (typespec == ckStruct || typespec == ckDecimal)
	{
		sypos1 = *sypos + *sylen;
		p32nextsymbol (pc, partbuf, *part1len);
		if (*symb == CPC_CS_IDENTIFIER && *sylen <= sizeof (tsp00_Lname))
		{
			memcpy (typename, partbuf + *sypos - 1, *sylen);
			if (*sylen < sizeof (tsp00_Lname))
				memset (typename + *sylen, ' ',
					sizeof (tsp00_Lname) - *sylen);
			p32nextsymbol (pc, partbuf, *part1len);
		}
		else
			typename [0] = ' ';
		if (*symb == CPC_CS_LEFTBRC)
		{
			if (typename [0] != ' ')
			{
				p32sTagbot ();
				p32tagindex ((char *) typename, &tnc, &ind);
				p32rTagbot ();
				if (ind > 0)
				{
					p11precomerror (pc, CPC_DUPLICATE_TYPEDEF);
					typename [0] = ' ';
				}
			}
			p32nextsymbol (pc, partbuf, *part1len);
			if (typespec == ckStruct)
				p32strudef (pc, typename, constspec, &typeind,
					syposav, symbsav);
			else if (typespec == ckDecimal)
				p32decimal (pc, (char *) typename, &typeind,
					constspec);
			if (pc->pcError != CPC_PRE_OK)
				typeind = 0;
			else
				tnc = 0;
			p32nextsymbol (pc, partbuf, *part1len);
		}
		else if (typename [0] != ' ')
		{
			p32tagindex ((char *) typename, &tnc, &ind);
			typeind = p32tagtyp (ind);
			if (typeind > 0)
			{
				tpc_typent *tt = pc->pcSymtab.typtablep +
					typeind - 1;
				if ((typespec == ckStruct && tt->sc.tyIndi !=
					CPR_VSTRUCT) || (typespec == ckDecimal
					&& tt->sc.tyIndi != CPR_VDECIMAL))
					typeind = 0;
			}
		}
		else
			p11precomerror (pc, CPC_INVALID_DATATYPE);
		if (typeind > 0 && typespec == ckDecimal)
			if (*symb == CPC_CS_EOF)
				memset (partbuf, ' ', *sypos - 1);
			else
				
			{
				int ls =
				sprintf (partbuf + sypos1 - 1, "%d", pc->
					pcSymtab.typtablep [typeind - 1].sc.
					tyDigit);
				memset (partbuf + sypos1 + ls - 1, ' ',
					*sypos - sypos1 - ls);
			}
		*varind = pc->pcSymtab.varCnt;
		if (storclspec == ckTypedef)
		{
			p32sTynbot ();
			p32typedef (pc, typeind, tnc, constspec);
			p32rTynbot ();
		}
		else
		{
			p32sVarbot (pc);
			p32vardef (pc, strind, typeind, tnc, constspec);
			p32rVarbot (pc);
		}
	}
	else if (*symb == CPC_CS_IDENTIFIER)
	{
		if (*sylen <= sizeof (tsp00_Lname))
		{
			memcpy (typename, partbuf + *sypos - 1, *sylen);
			if (*sylen < sizeof (tsp00_Lname))
				memset (typename + *sylen, ' ',
					sizeof (tsp00_Lname) - *sylen);
		}
		else
			typename [0] = ' ';
		p32tynindex ((char *) typename, &tnc, &ind);
		typeind = p32tyntyp (ind);
		p32nextsymbol (pc, partbuf, *part1len);
		if (storclspec == ckTypedef)
		{
			p32sTynbot ();
			p32typedef (pc, typeind, tnc, constspec);
			p32rTynbot ();
		}
		else
		{
			p32sVarbot (pc);
			p32vardef (pc, strind, typeind, tnc, constspec);
			p32rVarbot (pc);
		}
	}
	else
		p11precomerror (pc, CPC_INVALID_DATATYPE);
}

static void p32strudef (tpc_globals *pc,  tsp00_Lname typename, int constspec,
	int *typeind, tsp00_Int4 *syposav, tsp00_Int2 *symbsav)\
/*
Analyse der Komponentendeklarationen einer Strukturdefinition.
Diese erfolgt durch rekursiven Aufruf von p32declaration, wobei der Parameter
strind auf 1 gesetzt ist. Durch Eintrag dieses Wertes in die Variablentabelle
pc->pcSymtabe.vartablep lassen sich hier eigetragene Strukturkomponenten von
echten Varibaleneintraegen unterscheiden.

Parameter:
typename    enthaelt den Tag - Namen, falls angegeben, sonst ein Leerzeichen.
constspec   ist ckConst, falls die Strukturdeklaration den const - Specifier
            enthaelt, nichtpositiv sonst.
typeind     gibt den Index des definierten Struktur - Typs (beginnend bei 1)
            in pc->pcSymtab.typtablep zurueck.
syposav und
symbsav     Rueckgabeparameter, die geretteten Werten von sypos und symb (s.
            p32nextsymbol) entsprechen, und fuer die Code-Erzeugung benoetigt
	    werden.
*/
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
	int ptr = FALSE, error = FALSE;
	tsp00_Int2 tmpcnt = 0;
	tsp00_Int2 tmpindex [256];
	static const int maxcmpord = sizeof (tmpindex) / sizeof (tsp00_Int2);
	tsp00_Int2 typix, varix, cnt, i;
	do
	{
		p32declaration (pc, 1, &varix, syposav, symbsav);
		if (pc->pcError == CPC_PRE_OK)
		{
			cnt = pc->pcSymtab.varCnt - varix;
			if ((int) (tmpcnt + cnt) > maxcmpord)
				p11precomerror (pc, CPC_TOO_MANY_TYPE_DECLARED);
			else
			{
				for (i = 0; i < cnt; i++)
				{
					tmpindex [tmpcnt + i] = varix + i;
					if (pc->pcSymtab.typtablep [
						pc->pcSymtab.vartablep [
						varix + i].vatypix - 1].sc.
						tyPtr != 0)
					{
						ptr = TRUE;
						p11precomerror (pc,
						CPC_PTR_COMP_NOT_ALLOWED);
					}
				}
				tmpcnt += cnt;
			}
		}
		if (pc->pcError != CPC_PRE_OK)
			error = TRUE;
		pc->pcError = CPC_PRE_OK;
		*syposacc = *syposav;
		p32mexpand (pc);
		p11rsbuf (pc, part1len);
		p32nextsymbol (pc, partbuf, *part1len);
		*syposav = *sypos;
		*symbsav = *symb;
		if (pc->pcInpEof && pc->pcInpInd == CPC_INCLUDEFILE)
		{
			p11rchar (pc, part1len);
			pc->pcInpInd = CPC_INPUTFILE;
			pc->pcInpEof = FALSE;
		}
	}
	while (*symb != CPC_CS_RIGHTBRC && !pc->pcInpEof);
	typix = pc->pcSymtab.typCnt + (tsp00_Int2) 1;
	if (*symb != CPC_CS_RIGHTBRC)
		p11precomerror (pc, CPC_INVALID_DATATYPE);
	if (error)
		p11precomerror (pc, CPC_INVALID_TYPE_DEFINITION);
	if (pc->pcError == CPC_PRE_OK)
	{
		tpc_typent *tt = (tpc_typent*) p03dynalloc (&p32typtabled);
		pc->pcSymtab.typCnt = typix;
		tt->st.tyIndi = CPR_VSTRUCT;
		tt->st.tyCmCnt = 0;
		tt->st.tyRef = 0;
		tt->st.tyCmpIx = pc->pcSymtab.cmpCnt + (tsp00_Int2) 1;
		tt->st.tyVacnt = 0;
		tt->st.tyPtr = (tsp00_Int2) ((ptr) ? -1 : 0);
		for (i = 0; i < tmpcnt; i++)
		{
			*((tpc_cmpent*) p03dynalloc (&p32cmpindexd)) =
				tmpindex [i] + (tsp00_Int2) 1;
			pc->pcSymtab.vartablep [tmpindex [i]].vastrix 
				= typix;
		}
		for (i = 1; i < tmpcnt; i++)
		{
			tt->st.tyCmCnt = i;
			p19varindex (pc, (char *)
				pc->pcSymtab.vartablep [tmpindex [i]].vaname,
				typix, &varix);
			if (varix > 0)
				p11precomerror (pc, CPC_DUPLICATE_FIELDDEF);
		}
		tt->st.tyCmCnt = tmpcnt;
		pc->pcSymtab.cmpCnt += tmpcnt;
		*typeind = typix;
	}
	if (pc->pcError != CPC_PRE_OK)
	{
		pc->pcSymtab.typCnt = typix - (tsp00_Int2) 1;
		p32typtabled.descNelem = typix - (tsp00_Int2) 1;
		typeind = 0;
	}
	else if (typename [0] != ' ')
		p32newtag (pc, typix, (char *) typename, constspec);
}

void p32section (tpc_globals *pc)
/*
Syntaxanalayse einer in der Declare Section zulaessigen Anweisung.
Die Funktion entspricht dem Startsymbol einer LL (1) - Grammatik:
   <section> ::= <declaration>; |
                 <preprocessor statement> <section>
*/
                
{
	tsp00_Int4 *syposacc = &pc->pcScan.syposacc;
	tsp00_Int4 *sypos = &pc->pcScan.sypos;
	tsp00_Int4 *sylen = &pc->pcScan.sylen;
	tsp00_Int2 *symb = &pc->pcScan.symb;
	char *partbuf = pc->pccmdpart.partbufp;
        tsp00_Int4 *part1len = &pc->pccmdpart.part1len;
        tsp00_Int4 *part2len = &pc->pccmdpart.part2len;
	int keyind, decl;
	tsp00_Int4 syposav, pos;
	tsp00_Int2 symbsav;
	tsp00_Int2 varix;
	
	while (*symb == CPC_CS_PREPCOM && pc->pcError == CPC_PRE_OK)
	{
		syposav = *sypos;
		p32nextsymbol (pc, partbuf, *part1len);
		p32prepcomline (pc);
		*part2len = *part1len;
		*part1len = *syposacc;
		*syposacc = syposav;
		syposav = *sypos;
		p31outstmt (pc);
		p31outstmt (pc);
		*sypos = syposav;
		*syposacc = *part1len;
		*part1len = *part2len;
		p32nextsymbol (pc, partbuf, *part1len);
	}
	if (pc->pcError == CPC_PRE_OK && *symb == CPC_CS_IDENTIFIER)
	{
		syposav = *sypos;
		symbsav = *symb;
		p10getkeyword (pc, partbuf, &keyind);
		decl = TRUE;
		if (keyind == cpc_i_exec)
		{
			pos = *sypos;
			p32nextsymbol (pc, partbuf, *part1len);
			p10getkeyword (pc, partbuf, &keyind);
			*syposacc = pos;
			if (keyind == cpc_i_sql)
				decl = FALSE;
			else
				p32nextsymbol (pc, partbuf, *part1len);
		}
		if (decl)
		{
			p32declaration (pc, 0, &varix, &syposav, &symbsav);
			if (symbsav != CPC_CS_EOF)
			{
				*syposacc = syposav;
				p32mexpand (pc);
			}
		}
	}
	else if (*symb != CPC_CS_EOF && *symb != CPC_CS_BUFEOF && !pc->pcInpEof)
		p11precomerror (pc, CPC_INVALID_STMT_IN_SECTION);
}

.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :       0000
*-PRETTY-*  lines of code :       0000        PRETTY  9.01 
*-PRETTY-*  lines in file :       0000         2001-04-01 
.PA 

