.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 1989-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VNI02C$
.tt 2 $$$
.tt 3 $$Form$2000-01-04$
***********************************************************
.nf

.nf

.nf

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

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo


.fo


.fo
.nf
.sp
Module  :       Form
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp ; .cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp ; .cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp ; .cp 3
Author  : FrankS
.sp
.cp 3
Created : 1990-06-12
.sp
.cp 3
Version : 1993-05-13
.sp
.cp 3
Release :      Date : 2000-01-04
.sp
Release :      Date : 2000-01-04
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
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
.oc _/1
.CM -lll-
Code    :
/* PRETTY */

/*      vni02c                                                            */
/*                                                                        */
/*************************************************************
***                                                        ***
*** sql.cpc: Programm zum interaktiven Abarbeiten von      ***
***          SQL-Kommandos.                                ***
***                                                        ***
*** Modul:   form.c                                        ***
***                                                        ***
*** Benoetigte Files: sql.cpc                              ***
***                   argument.c                           ***
***                   form.c                               ***
***                   sql.h                                ***
***                                                        ***
*** Autor:   Detlef Engelbrecht                            ***
***                                                        ***
*** Datum:   12.06.1990                                    ***
***                                                        ***
*************************************************************/
/*==========================================================================*/
#include <malloc.h>
#include "hsp78_0.h"

extern char ergebnistab[];

void formnumber(char *date, char* form, char *separator, char *nulldarst,
		int length, int frac, int nullvalue);
void formint(int *zahl, int length, int nwert, char *dezimal, char *sepa, char *nvalue);
void formdatum(char *string, char *form, int nwert, char *sepa, char *nvalue);
void formbyte(char *string, int length, int nwert, char *sepa, char *nvalue);
void formdoublebyte(char *string, int length, int nwert, char *sepa, char *nvalue);
void formASCIIstring(char *string, int length, int nwert, char *sepa, char *nvalue);
void formchar(char *string, int length, int nwert, char *sepa, char *nvalue);
int getnumlength(int length, char *form, int frac);
void reformdate(char *string);
void reformtime(char *string);
void checkusername(char *name);
int analysestmnt(char *string);
char *getfrom(char *quelle, char *ziel, int art);

/*==========================================================================*/

/* Formatierte Ausgabe von Datum und Zeit */
void formdatum(char *string, char *form, int nwert, char *sepa, char *nvalue)
{
    int datum, i, j, anzahl, length, ind;
    char datstring[3][5], *ptr1, *ptr2;
    char rc[11];

    length=strlen(form);
    if (nwert<0)
	printf("%-*.*s%s",length,length,nvalue,sepa);
    else
    {
        strcpy(rc,form);
        datum=atoi(string)/10000;
        sprintf(datstring[0],"%04d",datum);
        datum=atoi(string)/100-datum*100;
        sprintf(datstring[1],"%02d",datum);
        datum=atoi(string)%100;
        sprintf(datstring[2],"%02d",datum);

	ind = 0;
        for (j=0;j<3;j++)
        {
	    if (j) datum=2;
	    else datum=4;
	    for (ptr1=form,i=0;*ptr1 && *ptr1!='.';ptr1++,i++);
            if (!form[i]) continue;
            for (ptr2=ptr1,anzahl=0;*ptr2=='.';ptr2++) anzahl++;
            strncpy(rc+ind,datstring[j]+datum-anzahl,anzahl);
	    ind += anzahl+1;
	    form = ++ptr2;
        }
	printf("%s%s",rc,sepa);
    }
}

/*==========================================================================*/

/* Darstellung von Bytewerten */
void formbyte(char *string, int length, int nwert, char *sepa, char *nvalue)
{
    --length;
    if (nwert < 0)
    {
	length *= 2;
	printf("%-*.*s%s",length,length,nvalue,sepa);
    }
    else
    {
        int i;
        unsigned char *ptr;

        for (ptr=(unsigned char *)string,i=0;i<length;i++,ptr++)
            printf("%02X",*ptr);
        printf("%s",sepa);
    }
}

/*==========================================================================*/

/* Darstellung von Doublebytewerten */
void formdoublebyte(char *string, int length, int nwert, char *sepa, char *nvalue)
{
    --length;
    if (nwert < 0)
    {
	length *= 2;
	printf("%-*.*s%s",length,length,nvalue,sepa);
    }
    else
    {
        int i;
        unsigned char *ptr;

        for (ptr=(unsigned char *)string,i=0;i<length;i++,ptr++)
            printf("%02X",*ptr);
        printf("%s",sepa);
    }
}

void formASCIIstring(char *string, int length, int nwert, char *sepa, char *nvalue)
{
  if (nwert < 0) {
    length *= 2;
    printf ("%-*.*s%s", length, length, nvalue, sepa);
  } else {
    unsigned int destBytes, srcBytes;
    tsp78ConversionResult res;
    char *buf;
    if ((buf = (char *) malloc (length)) == 0) {
      printf ("Error: malloc failed.\n");
      return;
    }
    res = sp78convertString (sp77encodingAscii,
			     buf,
			     length,
			     &destBytes,
			     TRUE,
			     sp77encodingUCS2Native,
			     string,
			     length-1,
			     &srcBytes);
    if (res == sp78_Ok) {
      printf ("%.*s", destBytes, buf);
    } else {
      int i;
      unsigned char *ptr;

      --length;
      for (ptr=(unsigned char *)string,i=0;i<length;i++,ptr++) {
	if (ptr+1 && *ptr == 0 && *(ptr+1) == 0)
	  break;
	printf("%02X",*ptr);
      }
    }
    printf("%s",sepa); 
    if (buf) free (buf);
  }
  memset (string, 0, length);
}

/*==========================================================================*/

/* Darstellung von Charactern */
void formchar(char *string, int length, int nwert, char *sepa, char *nvalue)
{
    --length;
    if (nwert < 0) printf("%-*.*s%s",length,length,nvalue,sepa);
    else printf("%-*.*s%s",length,length,string,sepa);
}

/*==========================================================================*/

/* Darstellung von Integern */
void formint(int *zahl, int length, int nwert, char *dezimal, char *sepa, char *nvalue)
{
    char tmp[40];
    int korr, tmplength;

    if (nwert < 0) *tmp = '\0';
    else sprintf(tmp,"%d",*zahl);
    formnumber(tmp,dezimal,sepa,nvalue,length,0,nwert);
}

/*==========================================================================*/

/* Tatsaechliche Formatierung von Nichtexponentialzahlen */
void formnumber(char *date, char* form, char *separator, char *nulldarst,
		int length, int frac, int nullvalue)
{
    register char *ptrq, *ptrz;
    char fract[40], tmp[40], ausstring[40];
    int korr, blank, vorzeichen;


    /* Laenge um Fraclaenge bereinigen */
    length -= frac;

    /* Zusaetzliche Stellen fuer Vorkommastellenaufbereitung
       beruecksichtigen */
    length = getnumlength(length,form,frac);

    if (nullvalue < 0)
	printf("%*.*s%s",length+frac,length+frac,nulldarst,separator);
    else
    {
	/* Gibt es Nachkommastellen ? */
        if ((ptrq=strchr(date,'.')))
        {
	    /* Nachkommastellen sichern und mit Nullen
	       auf die Fraclaenge auffuellen */
	    strcpy(fract,ptrq);
	    *ptrq='\0';
	    for (ptrq=fract+1,korr=0;korr<frac;ptrq++,korr++)
		if (!isdigit(*ptrq)) *ptrq='0';
	    *ptrq='\0';
        }
        else *fract='\0';

	/* Negatives Vorzeichen ? */
        if (*date == '-') vorzeichen=1;
        else vorzeichen=0;

	/* Wird keine Vorkommastellenaufbereitung gewuenscht ? */
        if (*form == 'N') strcpy(ausstring,date+vorzeichen);
        else
        {
	    /* Vorkommastellenaufbereitung */
	    ptrq = date+vorzeichen;
	    ptrz = ausstring;
	    if ((korr=strlen(ptrq)%3))
	    {
	        memcpy(ausstring,ptrq,korr);
	        ptrq += korr;
	        ptrz += korr;
	        *ptrz++ = ' ';
	    }
	    while (*ptrq)
	    {
	        memcpy(ptrz,ptrq,3);
	        ptrz += 3;
	        *ptrz++ = ' ';
	        ptrq += 3;
	    }
	    *(--ptrz) = '\0';
        }

	/* Zahl wieder zusammensetzen und Darstellung einfuegen */
        if (*fract) strcat(ausstring,fract);
        for (ptrq=ausstring;*ptrq;ptrq++)
        {
	    if (*ptrq == '.') *ptrq = form[1];
	    else if (*ptrq == ' ') *ptrq = *form;
        }

	/* Zeichenkette auf Gesamtlaenge expandieren und
	   Vorzeichen wieder rein */
        sprintf(tmp,"%*.*s",length+frac,length+frac,ausstring);
        if (vorzeichen)
        {
            for (ptrq=tmp;*ptrq==' ';ptrq++);
            *(--ptrq) = '-';
        }
        printf("%s%s",tmp,separator);
    }
}

/*==========================================================================*/

/* Berechnung der Laenge inklusive der Tausenderpunkte,
   des Vorzeichens und des Dezimalpunktes bei numerische
   Werten */
int getnumlength(int length, char *form, int frac)
{
    int korr, laenge;

    laenge = length;

    if (*form != 'N')
    {
        korr = 0;
        if (!(laenge % 3)) korr++;
        laenge += (laenge/3-korr);
    }

    /* Minus beruecksichtigen */
    laenge++;

    /* Dezimalpunkt beruecksichtigen */
    if (frac) laenge++;
    return(laenge);
}

/*==========================================================================*/

void reformdate(char *string)
{
    char *ptr;

    /* Y und J auf 0, M auf 1, D und T auf 2 setzen */
    for(ptr=string;*ptr;ptr++)
    {
	switch(*ptr)
	{
	case 'y':
	case 'Y':
	case 'j':
	case 'J':
	    *ptr = '0';
	    break;
	case 'm':
	case 'M':
	    *ptr = '1';
	    break;
	case 'd':
	case 'D':
	case 't':
	case 'T':
	    *ptr = '2';
	    break;
	default:
	    if (isdigit(*ptr)) *ptr = '.';
	}
    }
}

/*==========================================================================*/

void reformtime(char *string)
{
    char *ptr;

    /* H auf 0, M auf 1, S auf 2 setzen */
    for(ptr=string;*ptr;ptr++)
    {
	switch(*ptr)
	{
	case 'h':
	case 'H':
            *ptr='0';
	    break;
	case 'm':
	case 'M':
            *ptr='1';
	    break;
	case 's':
	case 'S':
            *ptr='2';
	    break;
        default:
	    if (isdigit(*ptr)) *ptr = '.';
	}
    }
}

/*==========================================================================*/

void checkusername(char *name)
{
    register char *ptr;

    /* generelle Umsetzung in Grossbuchstaben
       ===> klein geschriebene Usernamen funktionieren nicht
       Abhilfe ist erst moeglich wenn der Precompiler
       connects fuer 'kleingeschriebene' User zulaesst */
    for (ptr=name;*ptr;ptr++)
	if (islower(*ptr)) *ptr=_toupper(*ptr);
}

/*==========================================================================*/

int analysestmnt(char *string)
{
    char *getfrom();
    char *ptr, befehl[1000], flag=0;
    char *ptr_1, *tmp_ptr, *from_ptr;
    int length, blankflag, art, i, pos;

    *ergebnistab = '\0'; /* Resulttable auf Default */

    /* fuehrende Blanks eleminieren */
    for (ptr=string;isspace(*ptr);ptr++);
    strcpy(string,ptr);

    /* anhaengende Blanks eleminieren */
    for (ptr=string+strlen(string)-1;
	ptr >= string && (isspace(*ptr) || *ptr=='\n' );ptr--)
	*ptr = '\0';

    if (!*string) return(0);

    /* Normalerweise Variable Befehl benutzen (Laenge < 1000),
       sonst Speicher allokieren */
    length = strlen(string);
    length++;
    if (length > 1000)
    {
	/* Falls kein Speicher allokiert werden kann - c'est
	   la guerre */
        if (!(ptr=(char *)malloc(length))) return(-1);
	flag=1;
    }
    else ptr=befehl;

    /* Nur ein Blank zwischen jedem Argument des Kommandos */
    for (ptr_1=string,tmp_ptr=ptr,blankflag=0;*ptr_1;ptr_1++)
    {
	if (isspace(*ptr_1))
	{
	    if (blankflag) continue;
	    *tmp_ptr++ = ' ';
	    blankflag=1;
	}
	else
	{
	    /* rausoptimieren von ' ' vor ,() und = */
	    if (tmp_ptr > ptr &&
	       (*ptr_1 == ',' || *ptr_1 == ')'
	       || *ptr_1 == '(' || *ptr_1 == '=')
	       && *(tmp_ptr-1) == ' ') *(tmp_ptr-1) = *ptr_1;
	    else
	       if (islower(*ptr_1)) *tmp_ptr++ = _toupper(*ptr_1);
	       else *tmp_ptr++ = *ptr_1;
	    blankflag=0;
	}
    }
    *tmp_ptr = '\0';
    /* rausoptimieren von ' ' nach ,() und = */
    for (tmp_ptr=ptr;*tmp_ptr;tmp_ptr++)
    {
	if ((*tmp_ptr == ',' || *tmp_ptr == ')'
	    || *tmp_ptr == '(' || *tmp_ptr == '=')
	    && *(tmp_ptr+1) == ' ')
	{
            strcpy(tmp_ptr+1,tmp_ptr+2);
	    tmp_ptr--;
	}
    }

    /* Position merken */
    tmp_ptr = ptr;
    art = ANYSQL;

    /* Welche Art von DB-Call wird gewuenscht ? */
    /* select */
    if (!strncmp(tmp_ptr,"SELECT ",7) || !strncmp(tmp_ptr,"SELECT(",7))
    {
	tmp_ptr+=6; /* select direct */
	if (!strncmp(tmp_ptr," DIRECT ",8)
	   || !strncmp(tmp_ptr," DIRECT(",8)
	   || !strncmp(tmp_ptr," NEXT ",6)
	   || !strncmp(tmp_ptr," NEXT(",6)
	   || !strncmp(tmp_ptr," PREV ",6)
	   || !strncmp(tmp_ptr," PREV(",6)
	   || !strncmp(tmp_ptr," FIRST ",7)
	   || !strncmp(tmp_ptr," FIRST(",7)
	   || !strncmp(tmp_ptr," LAST ",6)
	   || !strncmp(tmp_ptr," LAST(",6))
	{
            art=SELDIRECT;
	    from_ptr=getfrom(string,ptr,1); /* from finden */
	    if (from_ptr)
	    {
		pos = from_ptr-ptr;
		strcpy(ptr,string+pos);
		*(string+pos) = '\0';
		/* Platzhalter reinschreiben */
		for (i=0;i<255;i++)
		    if (i) strcat(string,",?");
		    else strcat(string,"into ?");
		strcat(string," ");
		strcat(string,ptr);
	    }
	}
	else
	{

	    from_ptr=getfrom(string,ptr,0); /* from finden */
	    if (from_ptr)
	    {
		/* Dinge nach from interessieren nicht */
		*from_ptr='\0';
		
		/* Suche nach '(' */
		for (ptr_1=tmp_ptr;*ptr_1;ptr_1++)
		    if (*ptr_1 == '(') break;
		if (*ptr_1) /* Da was ein '(' */
		{
		    *ptr_1 = '\0';
		    /* war da auch ein Blank vor dem Wort ? */
		    if (*tmp_ptr == ' ')
		    {
			tmp_ptr++;
			/* Wenn nicht distinct, all, avg, min, max,
			   dann kann es nur ein Ergebnismengenname
			   sein (wie vermutet wird) */
			if (!strncmp(tmp_ptr,"ALL ",4))
			   tmp_ptr += 4;
			if (!strncmp(tmp_ptr,"DISTINCT ",9))
			   tmp_ptr += 9;
	                if (strcmp(tmp_ptr,"DISTINCT")
	                   && strcmp(tmp_ptr,"ALL")
	                   && strcmp(tmp_ptr,"AVG")
	                   && strcmp(tmp_ptr,"SUM")
	                   && strcmp(tmp_ptr,"MIN")
	                   && strcmp(tmp_ptr,"MAX")
	                   && strcmp(tmp_ptr,"COUNT")
	                   && strcmp(tmp_ptr,"TRUNC")
	                   && strcmp(tmp_ptr,"ROUND")
	                   && strcmp(tmp_ptr,"ABS")
	                   && strcmp(tmp_ptr,"INDEX")
	                   && strcmp(tmp_ptr,"LENGTH")
			   && strcmp(tmp_ptr,"TRIM")
	                   && strcmp(tmp_ptr,"NUM")
	                   && strcmp(tmp_ptr,"FIXED")
	                   && strcmp(tmp_ptr,"ADDDATE")
	                   && strcmp(tmp_ptr,"DAYOFYEAR")
	                   && strcmp(tmp_ptr,"SUBDATE")
	                   && strcmp(tmp_ptr,"DATEDIFF")
	                   && strcmp(tmp_ptr,"DAYOFWEEK")
	                   && strcmp(tmp_ptr,"WEEKOFYEAR")
	                   && strcmp(tmp_ptr,"DAYOFYEAR")
	                   && strcmp(tmp_ptr,"MAKEDATE")
	                   && strcmp(tmp_ptr,"ADDTIME")
	                   && strcmp(tmp_ptr,"SUBTIME")
	                   && strcmp(tmp_ptr,"TIMEDIFF")
	                   && strcmp(tmp_ptr,"MAKETIME"))
			{
	                    /* Jetzt kann noch ein '='  oder ','
			       dahinter sein, dann ist es auch keine
			       Ergebnistabelle */
			    for (ptr=tmp_ptr,blankflag=1;*ptr;ptr++)
				if (*ptr == '=' || *ptr == ',')
				{
				    blankflag=0;
				    break;
				}
			    if (blankflag)
			    {
                                strncpy(ergebnistab,tmp_ptr,18);
			        ergebnistab[18] = '\0';
			    }
			}
		    }
		}
		art = SELECTNORMAL;
            }
	}
    }
    else
    {
	/* show */
	if (!strncmp(tmp_ptr,"SHOW ",5) || !strncmp(tmp_ptr,"SHOW(",5))
	{
	    art=SELECTNORMAL;
	    tmp_ptr += 4;
	    /* Hier koennte ein Ergebnisname sein */
	    if (*tmp_ptr == '(')
	    {
                for (ptr_1=tmp_ptr;*ptr_1;ptr_1++)
		    if (*ptr_1 == ' ') break;
		    else if (*ptr_1 == ')')
		    {
			tmp_ptr++;
			*ptr_1 = '\0';
			strcpy(ergebnistab,tmp_ptr);
		    }
	    }
	    else strcpy(ergebnistab,"SHOW");
	}
	else if (!strcmp(tmp_ptr,"COMMIT WORK RELEASE")) art=FETCH;
	else if (!strcmp(tmp_ptr,"COMMIT WORK")) art=COMMITWORK;
	else if (!strcmp(tmp_ptr,"ROLLBACK WORK RELEASE")) art=FETCH;
	else if (!strcmp(tmp_ptr,"ROLLBACK WORK")) art=ROLLBACKWORK;
	else if (!strcmp(tmp_ptr,"EXIT")) art=EXIT;
	else if (!strcmp(tmp_ptr,"QUIT")) art=EXIT;
	else if (!strncmp(tmp_ptr,"FETCH",5)) art=FETCH;
	else if (*tmp_ptr == '!') art=SHELLCOM;
    }
	
    if (flag)
    {
	free(ptr);
	flag=0;
    }
    return(art);
}

/*==========================================================================*/

/* suche nach Auftreten von from in select statement */
char *getfrom(char *quelle, char *ziel, int art)
{
    char *ptrq, *ptrz;

    if (art)
        for (ptrq=quelle,ptrz=ziel;*ptrq;ptrq++,ptrz++)
	    if (isspace(*ptrq)) *ptrz=' ';
	    else if (islower(*ptrq)) *ptrz=_toupper(*ptrq);
	         else *ptrz = *ptrq;

    for (ptrz=ziel+1;*ptrz;ptrz++)
    {
	if (!strncmp(ptrz,"FROM",4)
	    && (*(ptrz-1)==' ' || *(ptrz-1)==')')
	    && (*(ptrz+4)==' ' || *(ptrz+4)=='(')) return(ptrz);
    }
    return(0);
}

.CM *-END-* code ----------------------------------------
.sp 2
***********************************************************
*-PRETTY-*  statements    :        xxxx
*-PRETTY-*  lines of code :        yyyy
*-PRETTY-*  lines in file :        zzzz
.pa
