.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2002-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VPA04GC$
.tt 2 $$$
.TT 3 $Burkhard Diesing$CONVERSION FROM SQLDA$2001-06-26$
***********************************************************
.nf

.nf

    ========== licence begin  GPL
    Copyright (c) 2002-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
Module  :
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
Define  :

.CM *-END-* define --------------------------------------
Use     :
.CM *-END-* use -----------------------------------------
Synonym :
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : Burkhard Diesing
.sp
.cp 3
Created : 08-31-1993
.sp
.cp 3
Version : 1994-04-25
.sp
.cp 3
Release :  7.3    Date : 2001-06-26
.sp
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
.CM -lll-
Code    :
#ifdef DEBUG
#line 64 "vpa04gc" 
#endif
#include <stdlib.h>
#include <time.h>

#include "vpa00global.h"
#include "vpa50Env.h"
#include "vpa40DBC.h"
#include "vpa60Stmt.h"
#include "hsp77.h"
#include "hsp78_0.h"
#include "livecachetypes.h"

tsp81_CodePage   pa04gCodePage = {"WINDOWS-1252",
                                  {0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
                                   0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
                                   0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
                                   0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
                                   0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
                                   0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
                                   0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
                                   0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
                                   0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
                                   0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
                                   0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
                                   0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
                                   0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
                                   0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
                                   0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
                                   0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
                                   0x20AC,0x0081,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
                                   0x02C6,0x2030,0x0160,0x2039,0x0152,0x008D,0x017D,0x008F,
                                   0x0090,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
                                   0x02DC,0x2122,0x0161,0x203A,0x0153,0x009D,0x017E,0x0178,
                                   0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
                                   0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
                                   0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
                                   0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,
                                   0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,
                                   0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,
                                   0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,
                                   0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF,
                                   0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,
                                   0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF,
                                   0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,
                                   0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF}
                                 };
#define PRECOMREL30

#define PA01_SYMB_UNKNOWN 0
#define PA01_SYMB_QUOTED  1

/* PTS 1102741 */
#define PA04CLEN(c_len_ptr, c_ptr, real_c_len) (SQLINTEGER)\
/*if*/((c_len_ptr) ? \
    /*if*/((*c_len_ptr == SQL_NTS) ? \
        /*if*/((c_ptr) ? \
            API_STRLEN(c_ptr) \
        /*else*/: \
           0 /*(SDWORD)SQL_NULL_DATA*/) \
    /*else*/: \
        /*if*/((c_ptr) ? \
            /*if*/((*c_len_ptr == SQL_DEFAULT_PARAM) ? \
                real_c_len \
            /*else*/: \
                *c_len_ptr) \
        /*else*/: \
            0 /*SQL_NULL_DATA*/)) \
/*else*/: \
    /*if*/((c_ptr) ? \
         API_STRLEN(c_ptr) \
    /*else*/: \
         0 /*(SDWORD)SQL_NULL_DATA*/))

/* analog to PA04CLEN for wide strings (length in bytes!) */
#define PA04CLENW(c_len_ptr, c_ptr, real_c_len)  \
(SQLINTEGER)( \
/*if*/((c_len_ptr) ? \
    /*if*/((*c_len_ptr == SQL_NTS) ? \
        /*if*/((c_ptr) ? \
           sizeof(tsp81_UCS2Char) * \
           sp81UCS2strlen ((tsp81_UCS2Char*) c_ptr) \
        /*else*/: \
           0 /*(SDWORD)SQL_NULL_DATA*/) \
    /*else*/: \
        /*if*/((c_ptr) ? \
            /*if*/((*c_len_ptr == SQL_DEFAULT_PARAM) ? \
                real_c_len \
            /*else*/: \
                *c_len_ptr) \
        /*else*/: \
            0 /*SQL_NULL_DATA*/)) \
/*else*/: \
    /*if*/((c_ptr) ? \
         sizeof(tsp81_UCS2Char) * \
         sp81UCS2strlen ((tsp81_UCS2Char*) c_ptr) \
    /*else*/: \
         0 /*(SDWORD)SQL_NULL_DATA*/)))

const tsp77encoding *pa04gGetEncodingType(SWORD format);
static boolean pa04gcIsVarChar(SWORD format) ;
static void *  pa04SearchTerminator (void *ptr, int len);
static int pa04DetermineLength (UDWORD *c_len_ptr, UCHAR *c_ptr, 
                                SQLULEN real_c_len, SWORD real_c_type);


/* move/convert a field from C to ODBC-SQL */
API_RETCODE pa04g_apgctos( SWORD      sql_type,
                           UCHAR     *sql_ptr,
                           UDWORD     sql_len,
                           UWORD      sql_scale,
                           UDWORD    *moved_len_ptr,
                           SWORD      fCtype,
                           UCHAR     *c_ptr,
                           UWORD      c_scale,
                           UDWORD    *c_len_ptr);

/* move/convert a field from ESQ to C */
API_RETCODE apgetoc(  SWORD   esq_type,
                      UCHAR  *esq_ptr,
                      UDWORD  esq_len,
                      UWORD   esq_scale,
                      UDWORD *moved_len_ptr,
                      SWORD   fCtype,
                      UWORD   numericScale,
                      UCHAR  *c_ptr,
                      SDWORD  c_len,
                      SDWORD *c_used_ptr )
{
    API_RETCODE api_retcode;
    UWORD sql_type;
    UDWORD sql_len;                 /* length of ODBC field       */
    UWORD sql_scale;

    API_TRACE(API_TR_ENTRY,"apgetoc",0);
    API_TRACE(API_TR_UWORD,"esq_type",&esq_type);
    API_TRACE(API_TR_PTR,"esq_ptr",&esq_ptr);
    API_TRACE(API_TR_UDWORD,"esq_len",&esq_len);
    API_TRACE(API_TR_UWORD,"esq_scale",&esq_scale);
    API_TRACE(API_TR_UDWORD,"*moved_len_ptr",moved_len_ptr);
    API_TRACE(API_TR_SWORD,"fCtype",&fCtype);
    API_TRACE(API_TR_PTR,"c_ptr",&c_ptr);
    API_TRACE(API_TR_UDWORD,"c_len",&c_len);
    API_TRACE(API_TR_PTR,"c_used_ptr",&c_used_ptr);


    api_retcode = API_OK;
    /* convert ESQ type  code to  */ 
    /* ODBC SQL type code         */
    api_retcode = apgstys( esq_type,
                           esq_len,
                           esq_scale,
                           (SWORD FAR *) &sql_type,
                           (UDWORD FAR *) &sql_len,
                           &sql_scale);

    if (api_retcode == API_OK) {
        api_retcode = apgstoc( sql_type,
                               esq_ptr,
                               sql_len,
                               sql_scale,
                               moved_len_ptr,
                               fCtype,
                               numericScale,
                               c_ptr,
                               c_len,
                               c_used_ptr);
    } /* of api_retcode == API_OK */

    API_TRACE(API_TR_EXIT,"apgetoc",0);
    API_TRACE(API_TR_API_RETCODE,"retcode",&api_retcode);
    API_TRACE(API_TR_UDWORD,"*c_used_ptr",c_used_ptr);

    return(api_retcode);
} /* apgetoc */


/* move/convert a field from ODBC/SQL to C */
API_RETCODE apgstoc( SWORD   sql_type,
                     UCHAR  *sql_ptr,
                     UDWORD  sql_len,
                     UWORD   sql_scale,
                     UDWORD *moved_len_ptr,
                     SWORD   fCtype,
                     UWORD   numericScale,
                     UCHAR  *c_ptr,
                     SDWORD  c_len,
                     SDWORD *c_used_ptr )
{
    API_RETCODE api_retcode;
    /* local variable-string      */
    UCHAR  *char_ptr;
    SWORD   real_c_type;
    SQLULEN real_c_len;
    UDWORD  used = 0;

    API_TRACE(API_TR_ENTRY,"apgstoc",0);
    API_TRACE(API_TR_SWORD,"sql_type",&sql_type);
    API_TRACE(API_TR_PTR,"sql_ptr",&sql_ptr);
    API_TRACE(API_TR_UDWORD,"sql_len",&sql_len);
    API_TRACE(API_TR_UWORD,"sql_scale",&sql_scale);
    API_TRACE(API_TR_UDWORD,"*moved_len_ptr",moved_len_ptr);
    API_TRACE(API_TR_SWORD,"fCtype",&fCtype);
    API_TRACE(API_TR_PTR,"c_ptr",&c_ptr);
    API_TRACE(API_TR_UDWORD,"c_len",&c_len);
    API_TRACE(API_TR_PTR,"c_used_ptr",&c_used_ptr);

    api_retcode = API_OK;


    if (apgisvstr(sql_type)) {
        char_ptr = apgvstraddr(sql_ptr);           
        sql_len = apggvstrl (sql_ptr);
        sql_ptr[sql_len+API_VSTRING_OFFSET] = '\0';
    }
    else {
        char_ptr = sql_ptr;
        if (apgischar(sql_type)) {
            if (sql_type == SQL_CHAR)
                sql_type = SQL_VARCHAR;
            else
                if (sql_type == SQL_UNICODE)
                    sql_type = SQL_UNICODE_VARCHAR;
            /* if target variable is UCS2 one need two result bytes for
               one input byte */
/*             if (sizeof (SQLWCHAR) * sql_len < c_len) */
/*                 c_len = sizeof (SQLWCHAR) * sql_len; */
            if ((SDWORD) sql_len < c_len) {
              if (sql_type == SQL_VARCHAR && fCtype == SQL_C_WCHAR)
                c_len = sizeof (SQLWCHAR) * sql_len;
              else
                c_len = sql_len;
            }
        }
    }
    /* set the C type, may have   */
    /* been defaulted by client   */
    apgstyc( fCtype,
             c_len,
             sql_type,
             sql_len,
             sql_scale,
             (SWORD*) &real_c_type,
             &real_c_len);

    /* both fields have a real    */
    /* type, so let the mayhem    */
    /* begin                      */

    /* OUTER SWITCH (from field) */
    if (sql_len > 0) {
        switch (sql_type) {
        case (SQL_CHAR): {}              
        case (SQL_UNICODE): {}
        case (SQL_VARCHAR): {}             
        case (SQL_UNICODE_VARCHAR): {}
        case (SQL_LONGVARCHAR): {}
        case (SQL_UNICODE_LONGVARCHAR): {
            api_retcode = apfchar( char_ptr,
                                   sql_len,
                                   moved_len_ptr,
                                   sql_type, 
                                   c_ptr,
                                   c_len,
                                   real_c_type,
                                   numericScale,
                                   &used );
            break;
        }
        case (SQL_BINARY): {}
        case (SQL_VARBINARY): {}
        case (SQL_LONGVARBINARY): {
            api_retcode = apfbinary( char_ptr,
                                     sql_len,
                                     moved_len_ptr,
                                     sql_type, 
                                     c_ptr,
                                     c_len,
                                     real_c_type,
                                     &used);
            break;
        }
        case (SQL_BIT): {}
        case (SQL_SMALLINT): {}
        case (SQL_INTEGER): {}
        case (SQL_REAL): {}
        case (SQL_FLOAT): {}
        case (SQL_DOUBLE): {}
        case (SQL_DECIMAL): {}           
        case (SQL_NUMERIC): {    
            switch (real_c_type) {               /* INNER SWITCH      */
            case (SQL_C_CHAR): {}
            case (SQL_C_WCHAR): {}
            case (SQL_C_SSHORT): {}
            case (SQL_C_USHORT): {}
            case (SQL_C_SHORT): {}
            case (SQL_C_SLONG): {}
            case (SQL_C_ULONG): {}
            case (SQL_C_LONG): {}
            case (SQL_C_FLOAT): {}
            case (SQL_C_DOUBLE): {}
            case (SQL_C_BINARY): {}
            case (SQL_C_BIT): {}
            case (SQL_C_STINYINT): {}
            case (SQL_C_UTINYINT): {}
            case (SQL_C_TINYINT): {}
                /* these three are new in 3.0 */
            case (SQL_C_NUMERIC): {}
            case (SQL_C_SBIGINT): {}
            case (SQL_C_UBIGINT): {
                 api_retcode = apfnumeric( char_ptr,
                                           sql_len,
                                           sql_scale,
                                           moved_len_ptr,
                                           sql_type, 
                                           c_ptr,
                                           c_len,
                                           real_c_type,
                                           numericScale,
                                           &used);
                break;
            }
            default: {
                API_TRACE(API_TR_SWORD, "format not supported", &real_c_type);
                api_retcode = API_NOT_OK;
                break;
            }
            } /* INNER SWITCH */
            break;
        }
        case (SQL_TYPE_DATE): {}
        case (SQL_TYPE_TIME): {}
        case (SQL_TYPE_TIMESTAMP): {}
        case (SQL_DATE): {}
        case (SQL_TIME): {}
        case (SQL_TIMESTAMP): {
            switch (real_c_type) {               /* INNER SWITCH      */
            case (SQL_C_WCHAR): {}
            case (SQL_C_CHAR): {}
            case (SQL_C_BINARY): {}
            case (SQL_C_TYPE_DATE): {}
            case (SQL_C_TYPE_TIME): {}
            case (SQL_C_TYPE_TIMESTAMP): {}
            case (SQL_C_DATE): {}
            case (SQL_C_TIME): {}
            case (SQL_C_TIMESTAMP): {
                api_retcode = apfdate( char_ptr,
                                       sql_len,
                                       moved_len_ptr,
                                       sql_type, 
                                       c_ptr,
                                       c_len,
                                       real_c_type,
                                       &used);
                break;
            }
            default: {
                API_TRACE(API_TR_SWORD,"can't convert to", &real_c_type);
                api_retcode = API_NOT_OK;
                break;
            }
            } /* inner switch */
            break;
        }
        default: {
            API_TRACE(API_TR_SWORD,"** unknown ** sql_type", &sql_type);
            api_retcode = API_NOT_OK;
            break;
        }
        } /* switch SQL_XXX */
    }
    else {
        used = 0;
        if (*moved_len_ptr == -1)
            api_retcode = API_NO_DATA_FOUND;
        else {
            if (real_c_type == SQL_C_CHAR && c_ptr)
                *c_ptr = '\0';      
            /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1132203 */
            if (real_c_type == SQL_C_WCHAR && c_ptr)
                *(SQLWCHAR*) c_ptr = 0;      
            *moved_len_ptr = (UDWORD)-1;
        }
    }
    if (c_used_ptr != NULL && 
        (api_retcode == API_OK || api_retcode == API_TRUNCATE)) {
        if (api_retcode == API_TRUNCATE && apgislong(sql_type)) {
            *c_used_ptr = SQL_NO_TOTAL;
        }
        else {
            *c_used_ptr = used;
        }
    }

    API_TRACE(API_TR_UDWORD, "c_used_ptr", c_used_ptr);
    API_TRACE(API_TR_EXIT,"apgstoc",0);
    API_TRACE(API_TR_API_RETCODE,"retcode",&api_retcode);
    return(api_retcode);
} /* apgstoc */


UCHAR* apgvstraddr( UCHAR *ptr )
{
    UCHAR FAR * p;
    p = ptr + API_VSTRING_OFFSET;
    API_TRACE(API_TR_PTR, "apgvstraddr", &p);
    return (p);
} /* apgvstraddr */


VOID apgsvstrl( UCHAR *ptr, tsp00_Int4 len )
{
    if (ptr != NULL ) {
        /* UWORD l = (UWORD)len; */
        API_MEMCPY(ptr, &len, API_VSTRING_OFFSET);
        API_TRACE(API_TR_UDWORD, "apgsvstrl", &len);
    }
} /* apgsvstrl */


UDWORD apggvstrl( UCHAR *ptr )
{
    UDWORD l = 0;
    tsp00_Int4 x;
    API_MEMCPY(&x, ptr, API_VSTRING_OFFSET);
    l = (UDWORD) x;
    API_TRACE(API_TR_UDWORD,"apggvstrl", &l);
    return (l);
} /* apggvstrl */

/* apgstst() - convert string to a string    */
API_RETCODE apgstst( UCHAR  *in_ptr,
                     SDWORD  in_length,
                     SWORD   in_format,
                     UCHAR  *out_ptr,
                     SDWORD  out_length,
                     SWORD   out_format,
                     UDWORD *used )
{
    UCHAR FAR * ptr;
    UCHAR FAR * in_string_ptr;
    UCHAR FAR * out_string_ptr;
    const tsp77encoding *in_encoding;
    const tsp77encoding *out_encoding;
    int in_isTerminated;
    unsigned int sizeOfBlank;
    SDWORD len;
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY, "apgstst", 0);
    in_string_ptr = in_ptr;
    API_TRACE(API_TR_PTR, "in_string_ptr", &in_string_ptr);
    API_TRACE(API_TR_UDWORD, "in_length", &in_length);
    API_TRACE(API_TR_UWORD, "in_format", &in_format);
    out_string_ptr = out_ptr;
    API_TRACE(API_TR_PTR, "out_string_ptr", &out_string_ptr);
    API_TRACE(API_TR_UDWORD, "out_length", &out_length);
    API_TRACE(API_TR_SWORD, "out_format", &out_format);  

    api_retcode = API_OK;

    in_encoding = pa04gGetEncodingType(in_format);
    out_encoding = pa04gGetEncodingType(out_format);

    if ( in_length == SQL_NTS
         || in_format == SQL_VARCHAR
         || in_format == SQL_UNICODE_VARCHAR) {
      tsp00_Uint4 cLen, inLength = (tsp00_Uint4) in_length;
      int isCorrupted, isExhausted;
      /* maybe crashed if the string is unterminated (User Error) */
      in_encoding->stringInfo(in_string_ptr, 1UL << 31, TRUE,
                              &cLen, &inLength, &in_isTerminated,
                              &isCorrupted, &isExhausted);
      in_length = inLength;
    }
    else {
      in_isTerminated = FALSE;
    }
    API_TRACE(API_TR_UDWORD, "in_length", &in_length);
    API_TRACE_LEN(API_TR_ODBC_STRING, "in_string", in_string_ptr, in_length);
    if (out_length < 1) {
        *used = in_length;
        if (out_format == SQL_VARCHAR || out_format == SQL_CHAR) {
          if (in_encoding != sp77encodingAscii) {
            *used /= 2;
          }
        }
        else 
          if (out_format == SQL_UNICODE || out_format == SQL_UNICODE_VARCHAR) {
            if (in_encoding == sp77encodingAscii) {
              *used *= 2;              
            }
          }
        api_retcode = API_TRUNCATE;
    }
    else {
      tsp00_Uint4   cbWrite;        /* number of bytes written */
      tsp00_Uint4   cbParsed;       /* number of bytes parsed */
      tsp78ConversionResult rc;

      /* out_length is in character count */
/*       out_length *= out_encoding->fixedCharacterSize; */

      if (pa04gcIsVarChar(out_format)) {
        /* decrement the output size to append an zeroterminator later in this function */
        out_length -= out_encoding->terminatorSize;
      }
      
      rc = sp78convertBuffer(out_encoding, out_string_ptr, out_length,
                             &cbWrite,
                             in_encoding, in_string_ptr, in_length,
                             &cbParsed);      
      if (rc != sp78_Ok) {
        if (rc == sp78_TargetExhausted) {
          /* ignore truncation if there are only blanks left in the input buffer */
          tsp00_Int4 cbPadBlanks;
          ptr = in_string_ptr+cbParsed;
          len = in_length-cbParsed;

          /* gives the number of padding Blanks in Bytes */
          if (in_encoding == sp77encodingUTF8)     /* fixedCharSize is 0! */
            sizeOfBlank = 1;
          else
            sizeOfBlank = in_encoding->fixedCharacterSize;
          cbPadBlanks = in_encoding->countPadChars(ptr, len, ' ') * sizeOfBlank;
          if (len == cbPadBlanks) {
            *used = cbWrite;
            api_retcode = API_OK;
          }
          else {
            /* byte length for output depends on ratio of character sizes 
               of input and output encoding (does not work for UTF8!) */
            *used = in_length / in_encoding->fixedCharacterSize
                              * out_encoding->fixedCharacterSize;
            api_retcode = API_TRUNCATE;
          }
          if (pa04gcIsVarChar(out_format)) {
            tsp00_Uint4 targetLength = out_encoding->terminatorSize;
            ptr = out_string_ptr+cbWrite;
            out_encoding->fillString((void**)&ptr, &targetLength, 1, '\0');
          }
        }
        else
          if (rc == sp78_SourceCorrupted)   /* conversion was not possible */
            api_retcode = API_INVALID;
          else
            api_retcode = API_NOT_OK;
      }
      else {
        if (pa04gcIsVarChar(out_format)) {
          tsp00_Uint4 targetLength = out_encoding->terminatorSize;
          ptr = out_string_ptr+cbWrite;
          out_encoding->fillString((void**)&ptr, &targetLength, 1, '\0');
        }
        *used = cbWrite;
      }
    }
    API_TRACE(API_TR_STRING,"*out_string_ptr",out_string_ptr);
    API_TRACE(API_TR_UDWORD,"*used",used);
    API_TRACE(API_TR_EXIT,"apgstst",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    
    return(api_retcode);
} /* apgstst */

API_RETCODE apgstdt( UCHAR  *in_ptr,
                     SWORD   in_format,
                     VOID   *out_ptr,
                     SWORD   out_format,
                     UDWORD *used)
{
    TIMESTAMP_STRUCT local_stamp;
    TIME_STRUCT *local_time;
    DATE_STRUCT *local_date;
    void *local_ptr = NULL;
    UCHAR FAR *char_ptr;
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY,"apgstdt",0);
    API_TRACE(API_TR_PTR, "&in_ptr", &in_ptr);  
    API_TRACE(API_TR_STRING,"in_ptr",in_ptr);  
    API_TRACE(API_TR_UWORD,"in_format",&in_format);  
    API_TRACE(API_TR_PTR, "&out_ptr", &out_ptr);  
    API_TRACE(API_TR_UWORD,"out_format",&out_format);  

    api_retcode = API_OK;
    local_date = (DATE_STRUCT *) &local_stamp.year;
    local_time = (TIME_STRUCT *) &local_stamp.hour;
    char_ptr = in_ptr;
    if (out_format == SQL_TYPE_DATE
        || out_format == SQL_DATE) {
        if (in_format != SQL_TYPE_DATE && in_format != SQL_TYPE_TIMESTAMP
            && in_format != SQL_DATE && in_format != SQL_TIMESTAMP) {
            api_retcode = API_NOT_OK;
        }
        else {
            /* build the year */
            local_date->year = (SWORD) atoi( (char*) char_ptr);
            char_ptr += 5;
            /* build the month */
            local_date->month = (UWORD) atoi( (char*) char_ptr);
            char_ptr += 3;
            /* build the day */
            local_date->day = (UWORD) atoi( (char*) char_ptr);
            char_ptr += 3;  
            API_TRACE(API_TR_UWORD, "year", &local_date->year);
            API_TRACE(API_TR_UWORD, "month", &local_date->month);
            API_TRACE(API_TR_UWORD, "day", &local_date->day);
            *used = sizeof(DATE_STRUCT);
            local_ptr = local_date;
            if ( in_format == SQL_TYPE_TIMESTAMP
                 || in_format == SQL_TIMESTAMP) {
                apgstdt( char_ptr,
                         SQL_TYPE_TIME,
                         (VOID*) local_time,
                         SQL_TYPE_TIME,
                         used );
                if (local_time->hour != 0 || local_time->minute != 0 ||
                    local_time->second != 0) {
                    api_retcode = API_TRUNCATE;
                }
            }   
        }
    }
    if ( out_format == SQL_TYPE_TIME
         || out_format == SQL_TIME) {
        if (in_format != SQL_TYPE_TIME && in_format != SQL_TYPE_TIMESTAMP
            && in_format != SQL_TIME && in_format != SQL_TIMESTAMP ) {
            api_retcode = API_NOT_OK;
        }
        else {
            if (in_format == SQL_TYPE_TIMESTAMP
                || in_format == SQL_TIMESTAMP) {
                apgstdt( char_ptr,
                         SQL_TYPE_DATE,
                         (VOID*) local_date,
                         SQL_TYPE_DATE,
                         used );
                if (local_date->year != 0 || local_date->month != 0 ||
                    local_date->day != 0) {
                    api_retcode = API_TRUNCATE;
                    char_ptr += 11;
                }
            }
            /* build the year */
            local_time->hour = (SWORD) atoi( (char*) char_ptr);
            char_ptr += 3;
            /* build the month */
            local_time->minute = (UWORD) atoi( (char*) char_ptr);
            char_ptr += 3;
            /* build the day */
            local_time->second = (UWORD) atoi( (char*) char_ptr);
            char_ptr += 3;
            API_TRACE(API_TR_UWORD, "hour", &local_time->hour);
            API_TRACE(API_TR_UWORD, "minute", &local_time->minute);
            API_TRACE(API_TR_UWORD, "second", &local_time->second);
            *used = sizeof(TIME_STRUCT);
            local_ptr = local_time;
        }
    }
    if (out_format == SQL_TYPE_TIMESTAMP
        || out_format == SQL_TIMESTAMP ) {
        if (in_format == SQL_TYPE_DATE || in_format == SQL_TYPE_TIMESTAMP
            || in_format == SQL_DATE || in_format == SQL_TIMESTAMP ) {
            apgstdt( char_ptr,
                     SQL_TYPE_DATE,
                     (VOID*) local_date,
                     SQL_TYPE_DATE,
                     used);
            if (in_format == SQL_TYPE_DATE || in_format == SQL_DATE) {
                local_stamp.hour = (UWORD) 0;
                local_stamp.minute = (UWORD) 0;
                local_stamp.second = (UWORD) 0;
                local_stamp.fraction = 0;
                API_TRACE(API_TR_UWORD, "hour", &local_time->hour);
                API_TRACE(API_TR_UWORD, "minute", &local_time->minute);
                API_TRACE(API_TR_UWORD, "second", &local_time->second);
            }
            else
                char_ptr += 11; 
        }
        if (in_format == SQL_TYPE_TIME || in_format == SQL_TYPE_TIMESTAMP
            || in_format == SQL_TIME || in_format == SQL_TIMESTAMP) {
            apgstdt( char_ptr,
                     SQL_TYPE_TIME,
                     (VOID*) local_time,
                     SQL_TYPE_TIME,
                     used );
            if (in_format == SQL_TYPE_TIME || in_format == SQL_TIME ) {
                time_t ltime;
                struct tm *ltm;
                time(&ltime);
                ltm = localtime(&ltime);
                API_TRACE(API_TR_MSG, "localdate", 0);
                local_stamp.year = (UWORD) (ltm->tm_year+1900);
                local_stamp.month = (UWORD) (ltm->tm_mon+1);
                local_stamp.day = (UWORD) ltm->tm_mday;
                local_stamp.fraction = 0;
            }
            else 
                char_ptr += 9;
        }
        if (in_format == SQL_TYPE_TIMESTAMP || in_format == SQL_TIMESTAMP) {
          local_stamp.fraction = 1000 * atol( (char*) char_ptr);  /* PTS 1121604 */
        }
        API_TRACE(API_TR_UDWORD, "fraction", &local_stamp.fraction);
        *used = sizeof(TIMESTAMP_STRUCT);
        local_ptr = &local_stamp;
    }  
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        if (out_ptr != NULL && (int)*used > 0) {
            API_TRACE(API_TR_UDWORD, "*used", used);
            if ( out_format == SQL_TYPE_TIMESTAMP
                 || out_format == SQL_TYPE_DATE
                 || out_format == SQL_TIMESTAMP || out_format == SQL_DATE) {
                API_TRACE(API_TR_UWORD, "year", &local_date->year);
                API_TRACE(API_TR_UWORD, "month", &local_date->month);
                API_TRACE(API_TR_UWORD, "day", &local_date->day);
                if (out_format == SQL_TYPE_TIMESTAMP
                    || out_format == SQL_TIMESTAMP) {
                    API_TRACE(API_TR_UWORD, "hour", &local_stamp.hour);
                    API_TRACE(API_TR_UWORD, "minute", &local_stamp.minute);
                    API_TRACE(API_TR_UWORD, "second", &local_stamp.second);
                    API_TRACE(API_TR_UDWORD, "fraction",
                              &local_stamp.fraction);
                }
            }
            if (out_format == SQL_TYPE_TIME || out_format == SQL_TIME) {
                API_TRACE(API_TR_UWORD, "hour", &local_time->hour);
                API_TRACE(API_TR_UWORD, "minute", &local_time->minute);
                API_TRACE(API_TR_UWORD, "second", &local_time->second);
            }
            API_MEMCPY((TIMESTAMP_STRUCT *)out_ptr, local_ptr, (int)*used);
        }
        else 
            api_retcode = API_NOT_OK;
    }
    API_TRACE(API_TR_EXIT,"apgstdt",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);

    return(api_retcode);
} /* apgstdt */


/* apgpkst() - convert packed decimal to ODBC style     */
/*             DECIMAL/NUMERIC                          */
VOID apgpkst( UCHAR  *packed_ptr,
              UWORD   scale,
              UDWORD *length_ptr,
              UCHAR  *decimal_ptr)     
{
    char res;
  
    API_TRACE(API_TR_ENTRY,"apgpkst",0);
    API_TRACE(API_TR_PTR,"packed_ptr",&packed_ptr);
    API_TRACE(API_TR_UWORD,"scale",&scale);
    API_TRACE(API_TR_PTR,"length_ptr",&length_ptr);
    API_TRACE(API_TR_PTR,"decimal_string_ptr",&decimal_ptr);

    s46dctos( (char*) packed_ptr,
              (int) *length_ptr,
              (int) scale,
              (char*) decimal_ptr,
              1,
              API_CHAR_LENGTH_DECIMAL, 
              (int *) length_ptr,
              (char *)&res );  
    API_TRACE(API_TR_SWORD, "s46dctos", &res);
    decimal_ptr [*length_ptr]  = '\0';
    API_TRACE(API_TR_EXIT,"apgpkst",0);
    API_TRACE(API_TR_STRING,"*decimal_ptr",decimal_ptr);
} /* apgpkst */


/* move/convert a field from C to ESQ */
API_RETCODE apgctoe( SWORD   esq_type,
                     UCHAR  *esq_ptr,
                     UDWORD  esq_len,
                     UWORD   esq_scale,
                     UDWORD *moved_len_ptr,
                     SWORD   fCtype,
                     UCHAR  *c_ptr,
                     UDWORD  cbColDef,
                     UWORD   ibScale,
                     SQLLEN *c_used_ptr_in,
                     SWORD   fSqlType)
{

    API_RETCODE api_retcode;
    SWORD sql_type;
    UDWORD sql_len;                 /* length of ODBC field       */
    UWORD sql_scale;
    SQLULEN real_c_len;
    UDWORD dummy, *c_used_ptr;

    API_TRACE(API_TR_ENTRY,"apgctoe",0);
    API_TRACE(API_TR_SWORD,"esq_type",&esq_type);
    API_TRACE(API_TR_PTR,"esq_ptr",&esq_ptr);
    API_TRACE(API_TR_UDWORD,"esq_len",&esq_len);
    API_TRACE(API_TR_UWORD,"esq_scale",&esq_scale);
    API_TRACE(API_TR_UDWORD,"*moved_len_ptr",moved_len_ptr);
    API_TRACE(API_TR_SWORD,"fCtype",&fCtype);
    API_TRACE(API_TR_PTR,"c_ptr",&c_ptr);
    API_TRACE(API_TR_UWORD,"cbColDef",&cbColDef);
    API_TRACE(API_TR_UWORD,"ibScale",&ibScale);
    API_TRACE(API_TR_PTR,"c_used_ptr",&c_used_ptr);
    API_TRACE(API_TR_SWORD,"fSqlType",&fSqlType);

    if (c_used_ptr_in == NULL)
      c_used_ptr = NULL;
    else {
      c_used_ptr = &dummy;
      dummy = (UDWORD) *c_used_ptr_in;
    }

    api_retcode = API_OK;
    /* convert ESQ type code to   */
    /* ODBC type code             */
    api_retcode = apgstys( esq_type,
                           esq_len,
                           esq_scale,
                           (SWORD*) &sql_type,
                           (UDWORD*) &sql_len,
                           &sql_scale);

    if (api_retcode == API_OK) {
        apgstyc( fCtype,
                 0,
                 fSqlType,
                 sql_len,
                 sql_scale,
                 (SWORD*) &fCtype,
                 &real_c_len);
        api_retcode = pa04g_apgctos( sql_type,
                                     esq_ptr,
                                     sql_len,
                                     sql_scale,
                                     moved_len_ptr,
                                     fCtype,
                                     c_ptr,
                                     ibScale,
                                     c_used_ptr );
    }

    if (c_used_ptr_in != NULL)
      /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1130257 */
      if (*c_used_ptr_in != SQL_NTS)
        *c_used_ptr_in = (SQLLEN) *c_used_ptr;

    API_TRACE(API_TR_EXIT, "apgctoe", 0);
    API_TRACE(API_TR_UDWORD, "*c_used_ptr", c_used_ptr);
    API_TRACE(API_TR_API_RETCODE, "retcode", &api_retcode);

    return(api_retcode);
} /* apgctoe */


/* move/convert a field from C to ODBC-SQL */
API_RETCODE pa04g_apgctos( SWORD      sql_type,
                           UCHAR     *sql_ptr,
                           UDWORD     sql_len,
                           UWORD      sql_scale,
                           UDWORD    *moved_len_ptr,
                           SWORD      fCtype,
                           UCHAR     *c_ptr,
                           UWORD      c_scale,
                           UDWORD    *c_len_ptr)
{
    API_RETCODE api_retcode;
    /* must be set for max double */
    UCHAR char_number [2*API_CHAR_LENGTH_CHAR]; 
    UCHAR  *char_ptr;
    SWORD   real_c_type = 0;
    SQLULEN real_c_len;
    SDWORD  c_len = 0;
    UDWORD  used = 0;

    API_TRACE(API_TR_ENTRY,"pa04g_apgctos", 0);
    API_TRACE(API_TR_SWORD,"sql_type", &sql_type);
    API_TRACE(API_TR_PTR,"sql_ptr", &sql_ptr);
    API_TRACE(API_TR_UDWORD,"sql_len", &sql_len);
    API_TRACE(API_TR_UWORD,"sql_scale", &sql_scale);
    API_TRACE(API_TR_UDWORD,"*moved_len_ptr", moved_len_ptr);
    API_TRACE(API_TR_SWORD,"fCtype", &fCtype);
    API_TRACE(API_TR_PTR,"c_ptr", &c_ptr);
    API_TRACE(API_TR_PTR,"c_len_ptr", &c_len_ptr);

    api_retcode = API_OK;
    if (apgisvstr(sql_type)) {
        char_ptr = apgvstraddr(sql_ptr);
        /* sql_len nicht setzten bei longspalten (SQLPutData) */
        /*      sql_len =  apggvstrl(sql_ptr); */
      
    }
    else 
        char_ptr = sql_ptr;
   
    if (*moved_len_ptr) {
        char_ptr += *moved_len_ptr;
        sql_len -= *moved_len_ptr;
    }
    if (sql_len > 0) {
        /* set the C type, may have   */
        /* been defaulted by client   */
        apgstyc(fCtype, ((c_len_ptr) ? *c_len_ptr : 0), sql_type, sql_len,
                sql_scale, (SWORD FAR *) &real_c_type, &real_c_len);

        /* OUTER SWITCH (from field)  */
        switch (real_c_type) {
        /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=1&ErrorID=1128557 */
        case (SQL_C_ABAPHANDLE): {
          if (sql_type == SQL_ABAPHANDLE) {
            API_MEMCPY (sql_ptr, c_ptr, sizeof(SQLStreamDesc));
          }
          else {
            api_retcode = API_NOT_OK;
          }
          break;
        }
        case (SQL_C_WCHAR): {}               
        case (SQL_C_CHAR): {             
            switch (sql_type) {         /* INNER SWITCH               */
            case (SQL_CHAR): {}       
            case (SQL_UNICODE): {}        
            case (SQL_VARCHAR): {}
            case (SQL_UNICODE_VARCHAR): {}
            case (SQL_LONGVARCHAR): {}
            case (SQL_UNICODE_LONGVARCHAR): {}
            case (SQL_BINARY): {}
            case (SQL_VARBINARY): {}
            case (SQL_LONGVARBINARY): {
                c_len = pa04DetermineLength (c_len_ptr, c_ptr, real_c_len, 
                                             real_c_type);
                if (c_len >= 0) {
                    /* in vpr01l, p01l_putdata, data is copied to the
                       packet without converting. However, a unicode
                       db expects even long ascii character in unicode
                       (confirmed by HB), if the packet encoding is
                       unicode. Avoiding any changes in vpr01l leads
                       us to following quick&dirty solution */
                  if (sql_type == SQL_LONGVARCHAR && pa01GetUnicodeCatalog() != 0)
                      sql_type = SQL_WLONGVARCHAR; 

                  api_retcode = aptchar(c_ptr, c_len, real_c_type, 
                                        char_ptr, sql_len, sql_scale,
                                        sql_type, &used);
                }
                else {
                    api_retcode = API_INVALID_LENGTH;
                }
                break;
            }
            case (SQL_DECIMAL): {}
            case (SQL_NUMERIC): {}
            case (SQL_BIT): {}
            case (SQL_SMALLINT): {} 
            case (SQL_INTEGER): {} 
            case (SQL_REAL): {} 
            case (SQL_FLOAT): {}
            case (SQL_DOUBLE):{
                c_len = pa04DetermineLength (c_len_ptr, c_ptr, real_c_len, 
                                             real_c_type);
                if (c_len > 0) {
                    c_len = (c_len < (sizeof(char_number)-sizeof(tsp81_UCS2Char))) ?
                        c_len : (sizeof(char_number) - sizeof(tsp81_UCS2Char));

                    if (real_c_type == SQL_CHAR)
                      API_MEMCPY(char_number, c_ptr, (int) c_len);
                    else {
                      tsp00_Uint4   cbWrite;        /* number of bytes written */
                      tsp00_Uint4   cbParsed;       /* number of bytes parsed */

                      sp78convertBuffer (sp77encodingAscii, char_number, c_len,
                                         &cbWrite,
                                         sp77encodingUCS2Native, c_ptr, c_len,
                                         &cbParsed);
                      c_len = cbWrite;
                    }
                    char_number[c_len] = '\0';

                    pa04gpatchnumber(char_number);
                    api_retcode = aptnumeric( char_number,
                                              c_len, c_scale, SQL_CHAR, 
                                              char_ptr,
                                              sql_len, sql_scale, sql_type,
                                              &used);
                }
                else {
                    if (c_len == 0) {
                        api_retcode = API_NOT_NUMBER;
                    }
                    else {
                        api_retcode = API_INVALID_LENGTH;
                    }           
                }
                break;
            }
            case (SQL_TYPE_DATE): {}          
            case (SQL_TYPE_TIME): {}
            case (SQL_TYPE_TIMESTAMP): {}
            case (SQL_DATE): {}
            case (SQL_TIME): {}
            case (SQL_TIMESTAMP): {
                c_len = pa04DetermineLength (c_len_ptr, c_ptr, real_c_len, 
                                             real_c_type);
                if (c_len > 0) {
                    c_len = (c_len < (sizeof(char_number)-sizeof(tsp81_UCS2Char))) ?
                        c_len : (sizeof(char_number) - sizeof(tsp81_UCS2Char));

                    if (real_c_type == SQL_CHAR)
                      API_MEMCPY(char_number, c_ptr, (int) c_len);
                    else {
                      tsp00_Uint4   cbWrite;        /* number of bytes written */
                      tsp00_Uint4   cbParsed;       /* number of bytes parsed */

                      sp78convertBuffer (sp77encodingAscii, char_number, c_len,
                                         &cbWrite,
                                         sp77encodingUCS2Native, c_ptr, c_len,
                                         &cbParsed);
                      c_len = cbWrite;
                    }
                    char_number[c_len] = '\0';

                    pa04gpatchdate(char_number);
                    api_retcode = aptdate (char_number, c_len, SQL_CHAR, 
                                           char_ptr, sql_len, sql_scale,
                                           sql_type, &used);
                }
                else {
                    if (c_len == 0) {
                        api_retcode = API_NOT_DATE;
                    }
                    else {
                        api_retcode = API_INVALID_LENGTH;
                    }           
                }            
                break;
            }
            default: {
                API_TRACE(API_TR_SWORD, "** unknown ** sql_type", &sql_type);
                api_retcode = API_NOT_OK;
                break;
            }
            } /* inner switch */
            break;
        }
        case (SQL_C_BIT): {}
        case (SQL_C_BINARY): {          
            switch (sql_type) {         
            case (SQL_CHAR): {}       
            case (SQL_UNICODE): {}        
            case (SQL_VARCHAR): {}
            case (SQL_UNICODE_VARCHAR): {}
            case (SQL_LONGVARCHAR): {}         
            case (SQL_UNICODE_LONGVARCHAR): {}         
            case (SQL_BIT): {}        
            case (SQL_BINARY): {}         
            case (SQL_VARBINARY): {}
            case (SQL_TYPE_DATE): {}
            case (SQL_TYPE_TIME): {}
            case (SQL_TYPE_TIMESTAMP): {}
            case (SQL_DATE): {}
            case (SQL_TIME): {}
            case (SQL_TIMESTAMP): {}
            case (SQL_LONGVARBINARY): {}
            case (SQL_DECIMAL): {} /* HBI */
            case (SQL_NUMERIC): {} /* HBI */
            case (SQL_SMALLINT): {} 
            case (SQL_INTEGER): {} 
            case (SQL_REAL): {} 
            case (SQL_FLOAT): {}
            case (SQL_DOUBLE): {

                if (real_c_type == SQL_C_WCHAR) {
                    c_len = PA04CLENW (c_len_ptr, c_ptr, real_c_len);
                }
                else if (real_c_type == SQL_C_BIT) {
                      c_len = 1;
                }
                else
                    c_len = PA04CLEN (c_len_ptr, c_ptr, real_c_len);

                if (c_len >= 0) {
                    if (real_c_type == SQL_C_BIT)
                        api_retcode = aptbit (c_ptr, c_len, real_c_type, 
                                              char_ptr, sql_len, sql_scale,
                                              sql_type, &used);
                    else
                        api_retcode = aptbinary(c_ptr, c_len, real_c_type, 
                                                char_ptr, sql_len, sql_scale,
                                                sql_type, &used);
                }
                else {
                    api_retcode = API_INVALID_LENGTH;
                }            
                break;
            }
            default: {
                API_TRACE(API_TR_SWORD,"** unknown ** sql_type", &sql_type);
                api_retcode = API_NOT_OK;
                break;
            }
            } 
            break;
        }
        case (SQL_C_SSHORT): {}
        case (SQL_C_USHORT): {}
        case (SQL_C_SHORT): {}
        case (SQL_C_SLONG): {}
        case (SQL_C_ULONG): {}
        case (SQL_C_LONG): {}     
        case (SQL_C_FLOAT): {}     
        case (SQL_C_DOUBLE): {}
        case (SQL_C_STINYINT): {}
        case (SQL_C_UTINYINT): {}
        case (SQL_C_TINYINT): {}
        /* these three are new in 3.0 */
        case (SQL_C_NUMERIC): {}
        case (SQL_C_SBIGINT): {}
        case (SQL_C_UBIGINT): {
             api_retcode = aptnumeric(c_ptr,
                                      c_len, c_scale, real_c_type, 
                                      char_ptr,
                                      sql_len, sql_scale, sql_type,
                                      &used);
            break;
        }
        case (SQL_C_TYPE_DATE): {}
        case (SQL_C_TYPE_TIME): {}              
        case (SQL_C_TYPE_TIMESTAMP): {}
        case (SQL_C_DATE): {}
        case (SQL_C_TIME): {}              
        case (SQL_C_TIMESTAMP): {               
            switch (sql_type) {              /* INNER SWITCH      */
            case (SQL_CHAR): {}
            case (SQL_UNICODE): {}
            case (SQL_VARCHAR): {}
            case (SQL_UNICODE_VARCHAR): {}
            case (SQL_LONGVARCHAR): {}         
            case (SQL_UNICODE_LONGVARCHAR): {}         
            case (SQL_TYPE_DATE): {}
            case (SQL_TYPE_TIME): {}
            case (SQL_TYPE_TIMESTAMP): {}
            case (SQL_DATE): {}
            case (SQL_TIME): {}
            case (SQL_TIMESTAMP): {}
            case (SQL_LONGVARBINARY): {}
            case (SQL_VARBINARY): {}
            case (SQL_BINARY): {
                api_retcode = aptdate(c_ptr, c_len, real_c_type, 
                                      char_ptr, sql_len, sql_scale,
                                      sql_type, &used);
                break;
            }
            default: {
                API_TRACE(API_TR_SWORD,"** unknown ** sql_type", &sql_type);
                api_retcode = API_NOT_OK;
                break;
            }
            }   /* inner switch */
            break;
        }      

        default: {
            API_TRACE(API_TR_SWORD,"** unknown ** real_c_type", &real_c_type);
            api_retcode = API_NOT_OK;
            break;
        }
        }
    } 
    else {
        used = 0;
        api_retcode = API_TRUNCATE;
    }

    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        UDWORD len = *moved_len_ptr;

        if (real_c_type == SQL_C_CHAR && sql_type == SQL_WLONGVARCHAR) {
          *moved_len_ptr += used / sizeof (SQLWCHAR);
          len += used;
        }
        else if (real_c_type == SQL_C_WCHAR && sql_type == SQL_LONGVARCHAR) {
          *moved_len_ptr += used;
          len += used * sizeof (SQLWCHAR);
        }
        else {
          *moved_len_ptr += used;
          len += used;
        }

        if (apgisvstr(sql_type)) {
            apgsvstrl (sql_ptr, (tsp00_Int4) len);
        }   
    }
    API_TRACE(API_TR_EXIT,"pa04g_apgctos",0);
    API_TRACE(API_TR_UDWORD, "*c_len_ptr", c_len_ptr);
    API_TRACE(API_TR_API_RETCODE,"retcode",&api_retcode);

    return(api_retcode);
} /* apgctos */


/* apgstpk() - convert an ODBC/SQL style DECIMAL/NUMERIC      */
/*             to an ESQ packed format                        */
API_RETCODE apgstpk( UCHAR  *decimal_ptr,
                     UWORD   scale,
                     UDWORD  length,
                     UCHAR  *packed_ptr)
{
    UDWORD decimal_len;
    SWORD res=0;
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY, "apgstpk",0);
    API_TRACE(API_TR_STRING, "decimal_ptr", decimal_ptr);
    API_TRACE(API_TR_UWORD,"scale",&scale);
    API_TRACE(API_TR_UDWORD,"length",&length);
    API_TRACE(API_TR_PTR,"packed_ptr",&packed_ptr);
    api_retcode = API_OK;
  
    decimal_len = (SQLUINTEGER) API_STRLEN(decimal_ptr);

    s46stodc( (char*) packed_ptr, (int) length, (int) scale,
              (char*) decimal_ptr, 1, (int) decimal_len, (char*)&res );
    switch (res) {
    case (0) : {
        break;
    }
    case (1) : {
        api_retcode = API_TRUNCATE;
        break;
    }
    case (2) : {
        api_retcode = API_NOT_NUMBER;
        break;
    }
    case (3) : {}
    default : {
        api_retcode = API_DATA_LOSS;
        break;
    }
    }
    API_TRACE(API_TR_SWORD, "s46stodc", &res);
    API_TRACE(API_TR_EXIT,"apgstpk",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    API_TRACE_BUF(packed_ptr, 1, 10);

    return(api_retcode);
} /* apgstpk */


/* apgstys() - set ODBC sql type code using ESQ type code     */
API_RETCODE apgstys( SWORD   esq_type,
                     UDWORD  esq_len,
                     UWORD   esq_scale,
                     SWORD  *sql_type,
                     UDWORD *sql_len,
                     UWORD  *sql_scale)
{
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY,"apgstys", 0);
    API_TRACE(API_TR_SWORD,"esq_type", &esq_type);
    API_TRACE(API_TR_UDWORD,"esq_len", &esq_len);
    API_TRACE(API_TR_UWORD, "esq_scale", &esq_scale);

    api_retcode = API_OK; 

    /* convert ESQ type code to   */
    /* ODBC type code             */
    *sql_scale = esq_scale;
    *sql_len = esq_len;
    switch (esq_type) {
    case (dcha): {}
    case (dche): {
        *sql_type = SQL_CHAR;
        /*  if (*sql_len > 0) */
        /*     *sql_len--;    */
        break;
    }   
    case (dunicode): {
        *sql_type = SQL_UNICODE;
        /*  if (*sql_len > 0) */
        /*     *sql_len--;    */
        break;
    }   
    case (dvarcharuni): {
        *sql_type = SQL_UNICODE_VARCHAR;
        break;
    }   
    case (dvarchara): {}
    case (dvarchare): {
        *sql_type = SQL_VARCHAR;
        break;
    }
    case (dstra): {}
    case (dstre): {}
    case (dlonga): {}
    case (dlonge): {
        *sql_type = (UWORD) SQL_LONGVARCHAR;
        break;
    }
    case (dstruni): {}
    case (dlonguni): {
        *sql_type = (UWORD) SQL_UNICODE_LONGVARCHAR;
        break;
    }
    case (dstrb): {}
    case (dstrdb): {}
    case (dlongb): {}
    case (dlongdb): {
        *sql_type = (UWORD) SQL_LONGVARBINARY;
        break;
    }
    case (ddbyteebcdic): {}
    case (dchb): {}
    case (dvarcharb): {
        *sql_type = (UWORD) SQL_VARBINARY;
        break;
    }
    case (dinteger): {     /* integer */
        *sql_type = SQL_INTEGER;
        break;
    }
    case (dsmallint): {        /* short integer */
        *sql_type = SQL_SMALLINT;
        break;
    }
    case (dfloat): {        /* float & double */
        if (esq_len > sizeof(SFLOAT)) {
            *sql_type = SQL_FLOAT;
        }
        else {
            *sql_type = SQL_REAL;
        }
        break;
    }
    case (dfixed): {      /* no C type, packed dec. */
        *sql_type = SQL_DECIMAL;
        break;                     
    }    
    case (ddate): {
        *sql_type = SQL_TYPE_DATE;
        break;
    }
    case (dtime): {
        *sql_type = SQL_TYPE_TIME;
        break;
    }
    case (dtimestamp): {
        *sql_type = SQL_TYPE_TIMESTAMP;
        break;
    }
    case (dboolean): {
        *sql_type = SQL_BIT;
        break;
    }
    case (dabaptabhandle): {
        *sql_type = SQL_ABAPHANDLE;
        break;
    }
    default:
        api_retcode = API_NOT_OK;
    }
    API_TRACE(API_TR_EXIT,"apgstys",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    API_TRACE(API_TR_SWORD,"*sql_type", sql_type);
    API_TRACE(API_TR_UDWORD,"*sql_len", sql_len);
    API_TRACE(API_TR_UWORD,"*sql_scale", sql_scale);

    return(api_retcode);
} /* apgstys */


/* apgstyc() - set ODBC C type code and len if type is defaulted    */
VOID apgstyc( SWORD    fCtype,
              SQLULEN  c_len,
              SWORD    sql_type,
              UDWORD   sql_len,
              UWORD    sql_scale,
              SWORD   *real_c_type,
              SQLULEN *real_c_len)
{

    API_TRACE(API_TR_ENTRY,"apgstyc", 0);
    API_TRACE(API_TR_SWORD,"fCtype", &fCtype);
    API_TRACE(API_TR_UDWORD,"c_len", &c_len);
    API_TRACE(API_TR_SWORD,"sql_type", &sql_type);
    API_TRACE(API_TR_UWORD,"sql_scale", &sql_scale);
    API_TRACE(API_TR_UDWORD,"sql_len", &sql_len);
    API_TRACE(API_TR_PTR, "&real_c_type",&real_c_type);

  /* set the C type, may have   */
  /* been defaulted by client   */
    if (fCtype != SQL_C_DEFAULT && c_len != SQL_DEFAULT_PARAM) {
        *real_c_type = fCtype;
        *real_c_len = c_len;
    }
    else {
        switch (sql_type) { /* ODBC book, pg 472 */
        case (SQL_CHAR): {}
        case (SQL_VARCHAR): {}
        case (SQL_LONGVARCHAR): {}
        case (SQL_BIGINT): {}
        case (SQL_DECIMAL): {}
        case (SQL_NUMERIC): {
            *real_c_type = SQL_C_CHAR;
            if (c_len == SQL_DEFAULT_PARAM)
                *real_c_len = sql_len;
            else {
                *real_c_len = c_len;
            }
            break;
        }
        /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1126177 */
        case (SQL_UNICODE): {}
        case (SQL_UNICODE_VARCHAR): {}
        case (SQL_UNICODE_LONGVARCHAR): {
            *real_c_type = SQL_C_WCHAR;
            if (c_len == SQL_DEFAULT_PARAM)
                *real_c_len = sql_len;
            else {
                *real_c_len = c_len;
            }
            break;
        }
        case (SQL_BINARY): {}
        case (SQL_VARBINARY): {}
        case (SQL_LONGVARBINARY): {
            *real_c_type = SQL_C_BINARY;
            if (c_len == SQL_DEFAULT_PARAM)
                *real_c_len = sql_len;
            else {
                *real_c_len = c_len;
            }
            break;
        }
        case (SQL_BIT): {
            *real_c_type = SQL_C_BIT;
            *real_c_len = sizeof(UCHAR);
            break;
        }
        case (SQL_TINYINT): {}
        case (SQL_C_STINYINT): {}
        case (SQL_C_UTINYINT): {
            *real_c_type = SQL_C_TINYINT;
            *real_c_len = sizeof(SCHAR);
            break;
        }
        case (SQL_SMALLINT): {}
        case (SQL_C_SSHORT): {}
        case (SQL_C_USHORT): {
            *real_c_type = SQL_C_SHORT;
            *real_c_len = sizeof(SWORD);
            break;
        }
        case (SQL_INTEGER): {}
        case (SQL_C_SLONG): {}
        case (SQL_C_ULONG): {
            *real_c_type = SQL_C_LONG;
            *real_c_len = sizeof(SDWORD);
            break;
        }
        case (SQL_REAL): {
            *real_c_type = SQL_C_FLOAT;
            *real_c_len = sizeof(SFLOAT);
            break;
        }
        case (SQL_FLOAT): {}
        case (SQL_DOUBLE): {
            *real_c_type = SQL_C_DOUBLE;
            *real_c_len = sizeof(SDOUBLE);
            break;
        }
        case (SQL_DATE): {}    /* PTS 1121248 */
        case (SQL_TYPE_DATE): {
            *real_c_type = SQL_C_TYPE_DATE;
            *real_c_len = sizeof(DATE_STRUCT);
            break;
        }
        case (SQL_TIME): {}
        case (SQL_TYPE_TIME): {
            *real_c_type = SQL_C_TYPE_TIME;
            *real_c_len = sizeof(TIME_STRUCT);
            break;
        }
        case (SQL_TIMESTAMP): {}
        case (SQL_TYPE_TIMESTAMP): {
            *real_c_type = SQL_C_TYPE_TIMESTAMP;
            *real_c_len = sizeof(TIMESTAMP_STRUCT);
            break;
        }
        case (SQL_ABAPHANDLE): {
            *real_c_type = SQL_C_ABAPHANDLE;
            *real_c_len = sizeof(SQLStreamDesc);
            break;
        }
        default:
            *real_c_type = fCtype;
            *real_c_len = c_len;
        } /* of switch */
    } /* of fCtype != SQL_C_DEFAULT */

    API_TRACE(API_TR_EXIT,"apgstyc",0);
    API_TRACE(API_TR_SWORD,"*real_c_type", real_c_type);

    return;
} /* apgstys */


/* function to check whether the input string is a date */
API_RETCODE apgchdt( UCHAR FAR *string_ptr )
{
    UWORD local_yyyy = 0;
    UWORD local_mm = 0, local_dd = 0;
    UCHAR * last_ptr;
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY,"apgchdt", 0);
    API_TRACE(API_TR_PTR,"string_ptr", &string_ptr);
    API_TRACE(API_TR_STRING,"string_ptr", string_ptr);

    api_retcode = API_OK;

    /* check for string not eq."" */
    if (string_ptr [0] == '\0' || string_ptr == NULL) {
        api_retcode = API_NOT_DATE;
    }
    if (api_retcode == API_OK) {
        local_yyyy = (SWORD) strtod( (char*) string_ptr, (char**) &last_ptr);
        API_TRACE(API_TR_SWORD,"local_yyyy", &local_yyyy);
        if ((errno == ERANGE) || (*last_ptr != PA_DATE_SEP)) {
            errno = 0;
            api_retcode = API_NOT_DATE;
        }
        if (api_retcode == API_OK) {
            local_mm = (UWORD) strtod( (char*) (last_ptr+1),
                                       (char**) &last_ptr);
            API_TRACE(API_TR_UWORD,"local_mm", &local_mm);
            if ((errno == ERANGE) || (*last_ptr != PA_DATE_SEP)) {
                errno = 0;
                api_retcode = API_NOT_DATE;
            }
            if (api_retcode == API_OK) {
                local_dd = (UWORD) strtod( (char*)(last_ptr+1),
                                           (char**)&last_ptr);
                API_TRACE(API_TR_UWORD,"local_dd", &local_dd);
                if ( (errno == ERANGE)
                     || ((*last_ptr != '\0')
                         && (*last_ptr != PA_TIMESTAMP_SEP))) {
                    errno = 0;
                    api_retcode = API_NOT_DATE;
                }      
            }
        }
    }
    if (api_retcode == API_OK) {
        /* check the date  */
        api_retcode = API_NOT_DATE;
        if ( local_mm >= 1 && local_mm <= 12 ) 
            if (local_dd >= 1 && local_dd <= 31 ) 
                api_retcode = API_OK;     
    }
    API_TRACE(API_TR_EXIT,"apgchdt", 0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode", &api_retcode);
    return(api_retcode);
} /* apgchdt */


/* function to check whether the input string is a time */
API_RETCODE apgchtm(UCHAR FAR *string_ptr)
{
    UWORD local_hh = 0, local_mm = 0, local_ss = 0;
    UCHAR * last_ptr;
  
    API_RETCODE api_retcode;

    API_TRACE(API_TR_ENTRY,"apgchtm", 0);
    API_TRACE(API_TR_PTR,"string_ptr", &string_ptr);
    API_TRACE(API_TR_STRING,"string_ptr", string_ptr);

    api_retcode = API_OK;

    /* check for string not eq."" */
    if (string_ptr [0] == '\0' || string_ptr == NULL) {
        api_retcode = API_NOT_DATE;
    }
    if (api_retcode == API_OK) {
        local_hh = (UWORD) strtod( (char*)string_ptr, (char**) &last_ptr);
        if ((errno == ERANGE) || (*last_ptr != PA_TIME_SEP)) {
            errno = 0;
            api_retcode = API_NOT_DATE;
        }
        if (api_retcode == API_OK) {
            local_mm = (UWORD) strtod( (char*)(last_ptr+1), (char**)&last_ptr);
            if ((errno == ERANGE) || (*last_ptr != PA_TIME_SEP)) {
                errno = 0;
                api_retcode = API_NOT_DATE;
            }
            if (api_retcode == API_OK) {
                local_ss = (UWORD) strtod((char*)(last_ptr+1),
                                          (char**)&last_ptr);
                if ( (errno == ERANGE)
                     || ((*last_ptr != '\0')
                         && (*last_ptr != ' ') && (*last_ptr != PA_FRAC_SEP))){
                    errno = 0;
                    api_retcode = API_NOT_DATE;
                }
            }
        }
    }
    if (api_retcode == API_OK) {
        /* check the date  */
        api_retcode = API_NOT_DATE;
        if ( local_hh <= 23 && local_mm <= 59 && local_ss <= 59 ) 
            api_retcode = API_OK;     
    }
    API_TRACE(API_TR_EXIT,"apgchtm", 0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode", &api_retcode);
    return(api_retcode);
} /* apgchtm */


/* function to check whether the input string is a timestamp */
API_RETCODE apgchts(UCHAR FAR *string_ptr)
{
    API_RETCODE api_retcode;
    UCHAR FAR *ptr;
    UDWORD local_sf;
    API_TRACE(API_TR_ENTRY,"apgchts", 0);
    API_TRACE(API_TR_STRING,"string_ptr", string_ptr);
    api_retcode = apgchdt(string_ptr);
    if (api_retcode == API_OK) {
        ptr = (string_ptr + API_DATE_PREC);
        if ( *ptr == PA_TIMESTAMP_SEP) {
            api_retcode = apgchtm(ptr+1);
            if (api_retcode == API_OK) {
                ptr += API_TIME_PREC + 1;
                if (*ptr != '\0') {
                    local_sf = (UDWORD) strtod( (char*)(ptr+1), (char**) &ptr);
                    if ( (errno == ERANGE)
                         || ((*ptr != '\0') && (*ptr != ' '))) {
                        errno = 0;
                        api_retcode = API_NOT_DATE;
                    }
                }
            }
        }
        else {
            if (*ptr == ' ' || *ptr == '\0')
                api_retcode = API_OK;
            else
                api_retcode = API_NOT_OK;
        }
    }
    API_TRACE(API_TR_EXIT,"apgchts", 0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode", &api_retcode);
    return(api_retcode);
} /* apgchts */

BOOL apgisvstr(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_BINARY): {}
    case (SQL_VARBINARY):
    case (SQL_LONGVARCHAR): {}
    case (SQL_UNICODE_LONGVARCHAR): {}
    case (SQL_LONGVARBINARY):
        {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgisvstr", &ret);
    return(ret);
} /* apgisvstr */

BOOL apgisnum(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_NUMERIC): {}
    case (SQL_DECIMAL): {}
    case (SQL_INTEGER): {}
    case (SQL_SMALLINT): {}
    case (SQL_FLOAT): {}
    case (SQL_DOUBLE): {}
    case (SQL_REAL): {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgisnum", &ret);
    return(ret);
} /* apgisnum */


BOOL apgislong(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_LONGVARCHAR): {}
    case (SQL_UNICODE_LONGVARCHAR): {}
    case (SQL_LONGVARBINARY): {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgislong", &ret);
    return(ret);
} /* apgislong */


#define SQL_SPECIAL_NULL_DATA (-2)

BOOL apgisindi( tsp00_Int4 *ind_ptr)
{
    tsp00_Int4 ind; /* not SDWORD because it has 8 bytes on 64 bit platforms */
    BOOL ret=FALSE;
    if (ind_ptr) {
        API_MEMCPY(&ind, ind_ptr, sizeof(ind));  
        if (ind == SQL_NULL_DATA)
            ret = TRUE;
        else
            if (ind == SQL_SPECIAL_NULL_DATA)
                ret = TRUE;
            else
                ret = FALSE;
    }      
    API_TRACE(API_TR_SWORD, "apgisindi", &ret);
    return(ret);
} /* apgisindi */


BOOL apgischar(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_CHAR): {}
    case (SQL_UNICODE): {}
    case (SQL_VARCHAR): {}
    case (SQL_UNICODE_VARCHAR): {}
    case (SQL_LONGVARCHAR): {}
    case (SQL_UNICODE_LONGVARCHAR): {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgischar", &ret);
    return(ret);
} /* apgischar */


BOOL apgisbin(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_BINARY): {}
    case (SQL_VARBINARY): {}
    case (SQL_LONGVARBINARY): {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgisbin", &ret);
    return(ret);
} /* apgisbin */


BOOL apgistime(SWORD sql_type)
{
    BOOL ret;
    switch(sql_type) {
    case (SQL_TYPE_TIME): {}
    case (SQL_TYPE_DATE): {}
    case (SQL_TYPE_TIMESTAMP): {}
    case (SQL_TIME): {}
    case (SQL_DATE): {}
    case (SQL_TIMESTAMP): {
        ret = TRUE;
        break;
    }
    default: {
        ret = FALSE;
        break;
    }
    }   
    API_TRACE(API_TR_SWORD, "apgistime", &ret);
    return(ret);
} /* apgistime */


API_RETCODE apgsti1( UCHAR  *in_string, 
                     UDWORD  in_length,
                     UCHAR  *out_ptr,
                     SWORD   out_format)
{
    API_RETCODE api_retcode;
    SCHAR local_tiny;
    UWORD len;
    UCHAR char_number [API_CHAR_LENGTH_CHAR];   
    API_TRACE(API_TR_ENTRY, "apgsti1", 0);
    len = sizeof(char_number)-2;
    len = (in_length < len) ? (UWORD) in_length : len;
    API_STRNCPY(char_number, in_string, len);
    char_number[len] = '\0';
    api_retcode = aptchsl(char_number, out_format);
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        local_tiny = (SCHAR) atoi( (char*) char_number);
        API_MEMCPY(out_ptr, (UCHAR FAR *) &local_tiny, sizeof(SCHAR));
    }
    API_TRACE(API_TR_SCHAR,"out_ptr", out_ptr);
    API_TRACE(API_TR_EXIT,"apgsti1",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    return (api_retcode);
} /* apgsti1 */


API_RETCODE apgsti2( UCHAR  *in_string, 
                     UDWORD  in_length,
                     UCHAR  *out_ptr,
                     SWORD   out_format)
{
    API_RETCODE api_retcode;
    SWORD local_short;
    UWORD len;
    UCHAR char_number [API_CHAR_LENGTH_CHAR];   
    API_TRACE(API_TR_ENTRY, "apgsti2", 0);
    len = sizeof(char_number)-2;
    len = (in_length < len) ? (UWORD) in_length : len;
    API_STRNCPY(char_number, in_string, len);
    char_number[len] = '\0';
    api_retcode = aptchsl(char_number, out_format);
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        local_short = (SWORD) atoi( (char*) char_number);
        API_MEMCPY(out_ptr, (UCHAR FAR *) &local_short, sizeof(SWORD));
    }
    API_TRACE(API_TR_SWORD,"out_ptr", out_ptr);
    API_TRACE(API_TR_EXIT,"apgsti2",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    return (api_retcode);
} /* apgsti2 */


API_RETCODE apgsti4( UCHAR  *in_string, 
                     UDWORD  in_length,
                     UCHAR  *out_ptr,
                     SWORD   out_format)
{
    API_RETCODE api_retcode;
    SDWORD local_long;
    UWORD len;
    UCHAR char_number [API_CHAR_LENGTH_CHAR];   
    API_TRACE(API_TR_ENTRY, "apgsti4", 0);
    len = sizeof(char_number)-2;
    len = (in_length < len) ? (UWORD) in_length : len;
    API_STRNCPY(char_number, in_string, len);
    char_number[len] = '\0';
    api_retcode = aptchsl(char_number, out_format);
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        local_long = atol( (char*) char_number);
        API_MEMCPY(out_ptr, (UCHAR FAR *) &local_long, sizeof(SDWORD));
    }
    API_TRACE(API_TR_SDWORD,"out_ptr", out_ptr);
    API_TRACE(API_TR_EXIT,"apgsti4",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    return (api_retcode);
} /* apgsti4 */

#ifdef BIGINT_SUPPORTED
/* string to bigint; new in 3.0  */
API_RETCODE apgsti8( UCHAR  *in_string, 
                     UDWORD  in_length,
                     UCHAR  *out_ptr,
                     SWORD   out_format)
{
    API_RETCODE  api_retcode;
    
    UWORD len;
    UCHAR char_number [API_CHAR_LENGTH_CHAR];   
    API_TRACE(API_TR_ENTRY, "apgsti8", 0);
    len = sizeof(char_number)-2;
    len = (in_length < len) ? (UWORD) in_length : len;
    API_STRNCPY(char_number, in_string, len);
    char_number[len] = '\0';
    api_retcode = aptchsl(char_number, out_format);
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        switch (out_format) {
        case SQL_C_UBIGINT: {
            API_UBIGINT   local_ubigint;
            
            local_ubigint = API_ATOI64( (char*) char_number );
            API_MEMCPY(out_ptr, (UCHAR*) &local_ubigint, sizeof(local_ubigint));
            break;
        };
        case SQL_C_SBIGINT:{
            API_BIGINT   local_bigint;
            
            local_bigint = API_ATOI64( (char*) char_number );
            API_MEMCPY(out_ptr, (UCHAR*) &local_bigint, sizeof(local_bigint));
            break;
        };
        default: /* illegal type */
            api_retcode = API_NOT_OK;
            break;
        }; /* switch */        
    }
    API_TRACE(API_TR_SDWORD,"out_ptr", out_ptr);
    API_TRACE(API_TR_EXIT,"apgsti8",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    return (api_retcode);
} /* apgsti8 */
#endif /* BIGINT_SUPPORTED */

API_RETCODE apgstfd( UCHAR  *in_string, 
                     UDWORD  in_length,
                     UCHAR  *out_ptr,
                     SWORD   out_format)
{
    API_RETCODE api_retcode;
    SFLOAT local_float;
    SDOUBLE local_double;
    UWORD len;
    UCHAR char_number [API_CHAR_LENGTH_CHAR];   
    API_TRACE(API_TR_ENTRY, "apgstfd", 0);
    len = sizeof(char_number)-2;
    len = (in_length < len) ? (UWORD)in_length : len;
    API_STRNCPY(char_number, in_string, len);
    char_number[len] = '\0';
    api_retcode = aptchfd(char_number, out_format);
    if (api_retcode == API_OK || api_retcode == API_TRUNCATE) {
        if (out_format == SQL_C_FLOAT) {
            local_float = (SFLOAT) atof( (char*) char_number);
            API_MEMCPY(out_ptr, (UCHAR FAR *) &local_float, sizeof(SFLOAT));
        }
        else {
            local_double = atof( (char*) char_number);
            API_MEMCPY(out_ptr, (UCHAR FAR *) &local_double, sizeof(SDOUBLE));
        }
    }
    if (out_format == SQL_C_FLOAT) {
        API_TRACE(API_TR_SFLOAT,"out_ptr", out_ptr);
    }
    else {
        API_TRACE(API_TR_SDOUBLE,"out_ptr", out_ptr);
    }
    API_TRACE(API_TR_EXIT,"apgstfd",0);
    API_TRACE(API_TR_API_RETCODE,"api_retcode",&api_retcode);
    return (api_retcode);
} /* apgstfd */


VOID pa04gpatchdate(UCHAR FAR *str_ptr)
{
    /* patch the ODBC extension of date, time, timestamp to SQL Syntax */
    /* needs a copy of the string incase of modification */
    UCHAR FAR *s, *p;
    UCHAR local_str[30];
    UWORD symb;
    unsigned int length = (unsigned int) API_STRLEN (str_ptr);

    API_TRACE(API_TR_ENTRY, "pa04gpatchdate",0);
    API_TRACE(API_TR_STRING, "str_ptr", str_ptr);
    p=str_ptr;
    API_TRACE(API_TR_STRING, "p", p);
    for ( s=str_ptr;
          (s=pa01NextSymbol(s, &length, &symb, 
                            local_str, sizeof(local_str))) != NULL;
          p=s ) {
        API_TRACE(API_TR_STRING, "local_str", &local_str);
        if (symb == PA01_SYMB_QUOTED) {
            API_STRCPY(str_ptr, local_str);
            break;
        }
        if (local_str[0] == '{') {
            s = pa01NextSymbol(s, &length, &symb, 
                               local_str, sizeof(local_str));
            API_TRACE(API_TR_STRING, "s", s);
            aputoup ((UCHAR FAR *)local_str);    
            if (API_STRCMP(local_str, "D") || API_STRCMP(local_str, "T") ||
                API_STRCMP(local_str, "TS") ) {
                s = pa01NextSymbol(s, &length, &symb, 
                                   local_str, sizeof(local_str));
                if (symb == PA01_SYMB_QUOTED) {
                    API_STRCPY(str_ptr, local_str);
                    break;
                }
            }
        }
    }
    API_TRACE(API_TR_STRING, "str_ptr", str_ptr);
    API_TRACE(API_TR_EXIT, "pa04gpatchdate",0);
} /* pa04patchdate */


VOID pa04gpatchnumber(UCHAR FAR *str_ptr)
{
    /* patch the language specific numeric format */
    /* ACCESS uses a comma (comma instead of a decimal point) */
    /* needs a copy of the string incase of modification */
    UCHAR FAR *p;
    API_TRACE(API_TR_ENTRY, "pa04gpatchnumber",0);
    p = str_ptr;
    for (;p = (UCHAR*) API_STRCHR(p, ',');p++) {
        *p = '.';
        API_TRACE(API_TR_STRING, "str_ptr", str_ptr);
    }
    API_TRACE(API_TR_EXIT, "pa04gpatchnumber",0);
} /* pa04gpatchnumber */


RETCODE pa04gCheckConversion( SWORD   fCType,
                              SWORD   fSqlType,
                              UWORD  *sqlStatePtr )
{
    return SQL_SUCCESS;
} /* pa04gCheckConversion */

const tsp77encoding *pa04gGetEncodingType(SWORD format)
{
  switch(format) {
  case SQL_UNICODE: {}
  case (SQL_UNICODE_VARCHAR): {}
  case (SQL_UNICODE_LONGVARCHAR): {
    return sp77nativeUnicodeEncoding ();
    break;
  };
  default: {
    return sp77encodingAscii;
    break;
  }
  }; /* switch */        
}

static boolean pa04gcIsVarChar(SWORD format) 
{
  switch(format) {
  case (SQL_VARCHAR): {}             
  case (SQL_UNICODE_VARCHAR): {}
  case (SQL_LONGVARCHAR): {}
  case (SQL_UNICODE_LONGVARCHAR): {
    return TRUE;
  }
  default: {
    return FALSE;
  }    
  }
}

static void *  pa04SearchTerminator (void *ptr, int len)
{
  unsigned int i, length;
  tsp81_UCS2Char *p = (tsp81_UCS2Char*) ptr;

  if (len <= 0)
    return (NULL);
  else
    length = (unsigned int) len / sizeof(tsp81_UCS2Char);

  for (i=0; i<length; i++, p++)
    if (p->s == 0)
      return (p);

  return (NULL);
}

static int pa04DetermineLength (UDWORD *c_len_ptr,  UCHAR *c_ptr, 
                                SQLULEN real_c_len, SWORD real_c_type)
{
  UCHAR *p;
  int c_len;

  if (real_c_type == SQL_C_CHAR) {
    c_len = PA04CLEN (c_len_ptr, c_ptr, real_c_len);
    if (c_len >= 0) {
      if (p = (UCHAR*) API_MEMCHR(c_ptr, '\0', (int) c_len))
        c_len = (SQLINTEGER) (p - c_ptr);
    }
  }
  else {
    c_len = PA04CLENW (c_len_ptr, c_ptr, real_c_len);
    if (c_len >= 0) {
      if (p = (UCHAR*) pa04SearchTerminator (c_ptr, (int) c_len))
        c_len = (SQLINTEGER) (p - c_ptr);
    }
  }
  return (c_len);
}



#ifdef TESTMAIN
#define NUMELEM(a) (sizeof(a)/sizeof(a[0]))
typedef struct apgstst_t {
  UCHAR  *in_ptr;
  SDWORD  in_length;
  SWORD   in_format;
  UCHAR  *out_ptr;
  SDWORD  out_length;
  SWORD   out_format;
} apgstst_t;

static apgstst_t t[] = {
  {"ABC", SQL_NTS, SQL_VARCHAR, NULL, 100, SQL_CHAR},
  {"1234    ", SQL_NTS, SQL_VARCHAR, NULL, 100, SQL_VARCHAR},
  {"abcdefghij", SQL_NTS, SQL_VARCHAR, NULL, 10, SQL_CHAR},
  {"987654321    ", SQL_NTS, SQL_VARCHAR, NULL, 10, SQL_VARCHAR}
};
main()
{
  API_RETCODE api_retcode;
  UDWORD used;
  int i;
  for (i=0; i < NUMELEM(t);i++) {
    t[i].out_ptr = malloc(t[i].out_length);
    api_retcode = apgstst( t[i].in_ptr, t[i].in_length, t[i].in_format, t[i].out_ptr, t[i].out_length, t[i].out_format, &used );
    api_retcode = apgststOld( t[i].in_ptr, t[i].in_length, t[i].in_format, t[i].out_ptr, t[i].out_length, t[i].out_format, &used );
    free(t[i].out_ptr);
  }
}
#endif /* TESTMAIN */
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
