LCOV - code coverage report
Current view: top level - src/tds - convert.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 1432 1536 93.2 %
Date: 2024-03-23 09:12:27 Functions: 47 48 97.9 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 2010-2015  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdarg.h>
      24             : #include <stdio.h>
      25             : 
      26             : #include <freetds/time.h>
      27             : 
      28             : #include <assert.h>
      29             : #include <ctype.h>
      30             : 
      31             : #if HAVE_ERRNO_H
      32             : #include <errno.h>
      33             : #endif /* HAVE_ERRNO_H */
      34             : 
      35             : #if HAVE_STDLIB_H
      36             : #include <stdlib.h>
      37             : #endif /* HAVE_STDLIB_H */
      38             : 
      39             : #if HAVE_STRING_H
      40             : #include <string.h>
      41             : #endif /* HAVE_STRING_H */
      42             : 
      43             : #if HAVE_STRINGS_H
      44             : #include <strings.h>
      45             : #endif /* HAVE_STRINGS_H */
      46             : 
      47             : #include <freetds/tds.h>
      48             : #include <freetds/convert.h>
      49             : #include <freetds/bytes.h>
      50             : #include <freetds/replacements.h>
      51             : 
      52             : typedef unsigned short utf16_t;
      53             : 
      54             : struct tds_time
      55             : {
      56             :         int tm_year; /**< year (0=1900) */
      57             :         int tm_mon;  /**< month (0-11) */
      58             :         int tm_mday; /**< month day (1-31) */
      59             :         int tm_hour; /**< hours (0-23) */
      60             :         int tm_min;  /**< minutes (0-59) */
      61             :         int tm_sec;  /**< seconds (0-59) */
      62             :         int tm_ns;   /**< nanoseconds (0-999999999) */
      63             : };
      64             : 
      65             : static TDS_INT tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr);
      66             : static TDS_INT tds_convert_int1(const TDS_TINYINT * src, int desttype, CONV_RESULT * cr);
      67             : static TDS_INT tds_convert_int2(const TDS_SMALLINT * src, int desttype, CONV_RESULT * cr);
      68             : static TDS_INT tds_convert_uint2(const TDS_USMALLINT * src, int desttype, CONV_RESULT * cr);
      69             : static TDS_INT tds_convert_int4(const TDS_INT* src, int desttype, CONV_RESULT * cr);
      70             : static TDS_INT tds_convert_uint4(const TDS_UINT * src, int desttype, CONV_RESULT * cr);
      71             : static TDS_INT tds_convert_int8(const TDS_INT8 * src, int desttype, CONV_RESULT * cr);
      72             : static TDS_INT tds_convert_uint8(const TDS_UINT8 * src, int desttype, CONV_RESULT * cr);
      73             : static int string_to_datetime(const char *datestr, TDS_UINT len, int desttype, CONV_RESULT * cr);
      74             : static bool is_dd_mon_yyyy(char *t);
      75             : static int store_dd_mon_yyy_date(char *datestr, struct tds_time *t);
      76             : static const char *parse_numeric(const char *buf, const char *pend,
      77             :         bool * p_negative, size_t *p_digits, size_t *p_decimals);
      78             : 
      79             : #define test_alloc(x) {if ((x)==NULL) return TDS_CONVERT_NOMEM;}
      80             : 
      81             : /*
      82             :  * Macros for number checks.
      83             :  * They work for signed/unsigned integers and floating point values
      84             :  * (accounting for truncation of any fractional portions of the latter).
      85             :  */
      86             : #define IS_TINYINT(x) ( -1 < (x) && (x) < 0x100 )
      87             : #define IS_SMALLINT(x) ( -32769 < (x) && (x) < 32768 )
      88             : #define IS_USMALLINT(x) ( -1 < (x) && (x) < 65536 )
      89             : 
      90             : /*
      91             :  * Macros for integer number checks.
      92             :  * IS_UINT works for both integers and floating point values.
      93             :  *
      94             :  * f77: I don't write -2147483648, some compiler seem to have some problem 
      95             :  * with this constant although is a valid 32bit value
      96             :  */
      97             : #define TDS_INT_MIN (-2147483647-1)
      98             : #define TDS_INT_MAX 2147483647
      99             : #define INT_IS_INT(x) (TDS_INT_MIN <= (x) && (x) <= TDS_INT_MAX)
     100             : #define TDS_UINT_MAX 4294967295u
     101             : #define IS_UINT(x) (-1 < (TDS_INT8)(x) && (x) < (TDS_INT8) TDS_UINT_MAX + 1)
     102             : #define TDS_INT8_MIN (-(((TDS_INT8)1)<<62) -(((TDS_INT8)1)<<62))
     103             : #define TDS_INT8_MAX ((((TDS_INT8) 0x7fffffff) << 32) + (TDS_INT8) 0xffffffffu)
     104             : 
     105             : /*
     106             :  * Macros for floating point number checks.
     107             :  * To avoid possible loss of precision, use upper bounds for floating point
     108             :  * values and test MIN - (x) < 1 rather than MIN - 1 < (x) for signed
     109             :  * destination types.
     110             :  */
     111             : #define TDS_INT_UPPER_FLOAT 2147483648.0f
     112             : #define FLOAT_IS_INT(x) (TDS_INT_MIN - (x) < 1.0f && (x) < TDS_INT_UPPER_FLOAT)
     113             : #define TDS_INT8_MIN_FLOAT (-9223372036854775808.0f)
     114             : #define TDS_INT8_UPPER_FLOAT 9223372036854775808.0f
     115             : #define FLOAT_IS_INT8(x) (TDS_INT8_MIN_FLOAT - (x) < 1.0f && (x) < TDS_INT8_UPPER_FLOAT)
     116             : #define TDS_UINT8_UPPER 18446744073709551616.0f
     117             : #define FLOAT_IS_UINT8(x) (-1.0f < (x) && (x) < TDS_UINT8_UPPER)
     118             : 
     119             : #define TDS_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
     120             : 
     121             : #define BIGDATETIME_BIAS 693961
     122             : 
     123             : /**
     124             :  * \ingroup libtds
     125             :  * \defgroup convert Conversion
     126             :  * Conversions between datatypes.  Supports, for example, dbconvert().  
     127             :  */
     128             : 
     129             : /**
     130             :  * \addtogroup convert
     131             :  * @{ 
     132             :  */
     133             : 
     134             : /**
     135             :  * convert a number in string to a TDSNUMERIC
     136             :  * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure 
     137             :  */
     138             : static int string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr);
     139             : 
     140             : /**
     141             :  * convert a zero terminated string to NUMERIC
     142             :  * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure 
     143             :  */
     144             : static int stringz_to_numeric(const char *instr, CONV_RESULT * cr);
     145             : 
     146             : static TDS_INT string_to_int(const char *buf, const char *pend, TDS_INT * res);
     147             : static TDS_INT string_to_int8(const char *buf, const char *pend, TDS_INT8 * res);
     148             : static TDS_INT string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res);
     149             : static TDS_INT string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr);
     150             : 
     151             : static int store_hour(const char *, const char *, struct tds_time *);
     152             : static int store_time(const char *, struct tds_time *);
     153             : static int store_yymmdd_date(const char *, struct tds_time *);
     154             : static int store_monthname(const char *, struct tds_time *);
     155             : static int store_numeric_date(const char *, struct tds_time *);
     156             : static int store_mday(const char *, struct tds_time *);
     157             : static int store_year(int, struct tds_time *);
     158             : 
     159             : /* static int days_this_year (int years); */
     160             : static bool is_timeformat(const char *);
     161             : static bool is_numeric(const char *);
     162             : static bool is_alphabetic(const char *);
     163             : static bool is_ampm(const char *);
     164             : #define is_monthname(s) (store_monthname(s, NULL) >= 0)
     165             : static bool is_numeric_dateformat(const char *);
     166             : 
     167             : #if 0
     168             : static TDS_UINT utf16len(const utf16_t * s);
     169             : static const char *tds_prtype(int token);
     170             : #endif
     171             : 
     172             : const char tds_hex_digits[] = "0123456789abcdef";
     173             : 
     174             : /**
     175             :  * Copy a terminated string to result and return len or TDS_CONVERT_NOMEM
     176             :  */
     177             : static TDS_INT
     178       16480 : string_to_result(int desttype, const char *s, CONV_RESULT * cr)
     179             : {
     180       16480 :         size_t len = strlen(s);
     181             : 
     182       16480 :         if (desttype != TDS_CONVERT_CHAR) {
     183        4598 :                 cr->c = tds_new(TDS_CHAR, len + 1);
     184        4598 :                 test_alloc(cr->c);
     185        4598 :                 memcpy(cr->c, s, len + 1);
     186             :         } else {
     187       11882 :                 memcpy(cr->cc.c, s, len < cr->cc.len ? len : cr->cc.len);
     188             :         }
     189       16480 :         return (TDS_INT)len;
     190             : }
     191             : 
     192             : /**
     193             :  * Copy binary data to to result and return len or TDS_CONVERT_NOMEM
     194             :  */
     195             : static TDS_INT
     196        1682 : binary_to_result(int desttype, const void *data, size_t len, CONV_RESULT * cr)
     197             : {
     198        1682 :         if (desttype != TDS_CONVERT_BINARY) {
     199        1664 :                 cr->ib = tds_new(TDS_CHAR, len);
     200        1664 :                 test_alloc(cr->ib);
     201        1664 :                 memcpy(cr->ib, data, len);
     202             :         } else {
     203          18 :                 memcpy(cr->cb.ib, data, len < cr->cb.len ? len : cr->cb.len);
     204             :         }
     205        1682 :         return (TDS_INT)len;
     206             : }
     207             : 
     208             : #define CASE_ALL_CHAR \
     209             :         SYBCHAR: case SYBVARCHAR: case SYBTEXT: case XSYBCHAR: case XSYBVARCHAR
     210             : #define CASE_ALL_BINARY \
     211             :         SYBBINARY: case SYBVARBINARY: case SYBIMAGE: case XSYBBINARY: case XSYBVARBINARY: \
     212             :         case SYBLONGBINARY: case TDS_CONVERT_BINARY
     213             : 
     214             : /* TODO implement me */
     215             : /*
     216             : static TDS_INT 
     217             : tds_convert_ntext(int srctype,TDS_CHAR *src,TDS_UINT srclen,
     218             :       int desttype, CONV_RESULT *cr)
     219             : {
     220             :       return TDS_CONVERT_NOAVAIL;
     221             : }
     222             : */
     223             : 
     224             : static TDS_INT
     225       14676 : tds_convert_binary(const TDS_UCHAR * src, TDS_INT srclen, int desttype, CONV_RESULT * cr)
     226             : {
     227             :         int cplen;
     228             :         int s;
     229             :         char *c;
     230             : 
     231       14676 :         switch (desttype) {
     232         614 :         case TDS_CONVERT_CHAR:
     233         614 :                 cplen = srclen * 2;
     234         614 :                 if ((TDS_UINT)cplen > cr->cc.len)
     235         384 :                         cplen = cr->cc.len;
     236             : 
     237         614 :                 c = cr->cc.c;
     238      640754 :                 for (s = 0; cplen >= 2; ++s, cplen -= 2) {
     239      640140 :                         *c++ = tds_hex_digits[src[s]>>4];
     240      640140 :                         *c++ = tds_hex_digits[src[s]&0xF];
     241             :                 }
     242         614 :                 if (cplen)
     243         192 :                         *c = tds_hex_digits[src[s]>>4];
     244             :                 return srclen * 2;
     245             : 
     246         542 :         case CASE_ALL_CHAR:
     247             : 
     248             :                 /*
     249             :                  * NOTE: Do not prepend 0x to string.  
     250             :                  * The libraries all expect a bare string, without a 0x prefix. 
     251             :                  * Applications such as isql and query analyzer provide the "0x" prefix.
     252             :                  */
     253             : 
     254             :                 /* 2 * source length + 1 for terminator */
     255             : 
     256         542 :                 cr->c = tds_new(TDS_CHAR, (srclen * 2) + 1);
     257         542 :                 test_alloc(cr->c);
     258             : 
     259             :                 c = cr->c;
     260             : 
     261       92148 :                 for (s = 0; s < srclen; s++) {
     262       92148 :                         *c++ = tds_hex_digits[src[s]>>4];
     263       92148 :                         *c++ = tds_hex_digits[src[s]&0xF];
     264             :                 }
     265             : 
     266         542 :                 *c = '\0';
     267         542 :                 return (srclen * 2);
     268             :                 break;
     269        1616 :         case SYBINT1:
     270             :         case SYBUINT1:
     271             :         case SYBINT2:
     272             :         case SYBUINT2:
     273             :         case SYBINT4:
     274             :         case SYBUINT4:
     275             :         case SYBINT8:
     276             :         case SYBUINT8:
     277             :         case SYBMONEY4:
     278             :         case SYBMONEY:
     279             :         case SYBREAL:
     280             :         case SYBFLT8:
     281        1616 :                 cplen = tds_get_size_by_type(desttype);
     282        1616 :                 if (srclen >= cplen)
     283         496 :                         srclen = cplen;
     284        1616 :                 memcpy(cr, src, srclen);
     285        1616 :                 memset(((char*) cr) + srclen, 0, cplen - srclen);
     286        1616 :                 return cplen;
     287             :                 break;
     288             : 
     289             :                 /* conversions not allowed */
     290             :         case SYBDATETIME4:
     291             :         case SYBDATETIME:
     292             :         case SYBDATETIMN:
     293             : 
     294             :                 /* TODO should we do some test for these types or work as ints ?? */
     295             :         case SYBDECIMAL:
     296             :         case SYBNUMERIC:
     297             :         case SYBBIT:
     298             :         case SYBBITN:
     299             : 
     300             :         default:
     301             :                 break;
     302             :         }
     303             :         return TDS_CONVERT_NOAVAIL;
     304             : }
     305             : 
     306             : TDS_INT
     307         760 : tds_char2hex(TDS_CHAR *dest, TDS_UINT destlen, const TDS_CHAR * src, TDS_UINT srclen)
     308             : {
     309             :         unsigned int i;
     310         760 :         unsigned char hex1, c = 0;
     311             : 
     312             :         /* if srclen if odd we must add a "0" before ... */
     313         760 :         i = 0;          /* number where to start converting */
     314         760 :         if (srclen & 1) {
     315         288 :                 ++srclen;
     316         288 :                 i = 1;
     317         288 :                 --src;
     318             :         }
     319      497052 :         for (; i < srclen; ++i) {
     320      497052 :                 hex1 = src[i];
     321             : 
     322      497052 :                 if ('0' <= hex1 && hex1 <= '9')
     323      414854 :                         hex1 &= 0x0f;
     324             :                 else {
     325       82198 :                         hex1 &= 0x20 ^ 0xff;        /* mask off 0x20 to ensure upper case */
     326       82198 :                         if ('A' <= hex1 && hex1 <= 'F') {
     327       82198 :                                 hex1 -= ('A' - 10);
     328             :                         } else {
     329           0 :                                 tdsdump_log(TDS_DBG_INFO1,
     330             :                                             "error_handler:  attempt to convert data stopped by syntax error in source field \n");
     331             :                                 return TDS_CONVERT_SYNTAX;
     332             :                         }
     333             :                 }
     334      497052 :                 assert(hex1 < 0x10);
     335             : 
     336      497052 :                 if ((i/2u) >= destlen)
     337           0 :                         continue;
     338             : 
     339      497052 :                 if (i & 1)
     340      248670 :                         dest[i / 2u] = c | hex1;
     341             :                 else
     342      248382 :                         c = hex1 << 4;
     343             :         }
     344         760 :         return srclen / 2u;
     345             : }
     346             : 
     347             : static TDS_INT
     348     1013408 : tds_convert_char(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
     349             : {
     350             :         unsigned int i;
     351             : 
     352             :         TDS_INT8 mymoney;
     353             :         char mynumber[28];
     354             : 
     355             :         TDS_INT tds_i;
     356             :         TDS_INT8 tds_i8;
     357             :         TDS_UINT8 tds_ui8;
     358             :         TDS_INT rc;
     359             : 
     360             :         bool negative;
     361             :         size_t digits, decimals;
     362             : 
     363     1013408 :         switch (desttype) {
     364           0 :         case TDS_CONVERT_CHAR:
     365           0 :                 memcpy(cr->cc.c, src, srclen < cr->cc.len ? srclen : cr->cc.len);
     366           0 :                 return srclen;
     367             : 
     368        1692 :         case CASE_ALL_CHAR:
     369        1692 :                 cr->c = tds_new(TDS_CHAR, srclen + 1);
     370        1692 :                 test_alloc(cr->c);
     371        1692 :                 memcpy(cr->c, src, srclen);
     372        1692 :                 cr->c[srclen] = 0;
     373        1692 :                 return srclen;
     374             :                 break;
     375             : 
     376      154640 :         case SYBINT1:
     377             :         case SYBUINT1:
     378      154640 :                 if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
     379             :                         return rc;
     380       96144 :                 if (!IS_TINYINT(tds_i))
     381             :                         return TDS_CONVERT_OVERFLOW;
     382       19408 :                 cr->ti = tds_i;
     383       19408 :                 return sizeof(TDS_TINYINT);
     384             :                 break;
     385       77368 :         case SYBINT2:
     386       77368 :                 if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
     387             :                         return rc;
     388       48112 :                 if (!IS_SMALLINT(tds_i))
     389             :                         return TDS_CONVERT_OVERFLOW;
     390       25320 :                 cr->si = tds_i;
     391       25320 :                 return sizeof(TDS_SMALLINT);
     392             :                 break;
     393       77264 :         case SYBUINT2:
     394       77264 :                 if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
     395             :                         return rc;
     396       48016 :                 if (!IS_USMALLINT(tds_i))
     397             :                         return TDS_CONVERT_OVERFLOW;
     398       18256 :                 cr->usi = (TDS_USMALLINT) tds_i;
     399       18256 :                 return sizeof(TDS_USMALLINT);
     400             :                 break;
     401       77784 :         case SYBINT4:
     402       77784 :                 if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
     403             :                         return rc;
     404       48408 :                 cr->i = tds_i;
     405       48408 :                 return sizeof(TDS_INT);
     406             :                 break;
     407       77296 :         case SYBUINT4:
     408       77296 :                 if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
     409             :                         return rc;
     410       68304 :                 if (!IS_UINT(tds_i8))
     411             :                         return TDS_CONVERT_OVERFLOW;
     412       29928 :                 cr->ui = (TDS_UINT) tds_i8;
     413       29928 :                 return sizeof(TDS_UINT);
     414             :                 break;
     415       77512 :         case SYBINT8:
     416       77512 :                 if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
     417             :                         return rc;
     418       68392 :                 cr->bi = tds_i8;
     419       68392 :                 return sizeof(TDS_INT8);
     420             :                 break;
     421       77400 :         case SYBUINT8:
     422       77400 :                 if ((rc = string_to_uint8(src, src + srclen, &tds_ui8)) < 0)
     423             :                         return rc;
     424       40120 :                 cr->ubi = tds_ui8;
     425       40120 :                 return sizeof(TDS_UINT8);
     426             :                 break;
     427      143672 :         case SYBFLT8:
     428             :         case SYBREAL:
     429      143672 :                 return string_to_float(src, srclen, desttype, cr);
     430             :                 break;
     431         472 :         case SYBBIT:
     432             :         case SYBBITN:
     433         472 :                 if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
     434             :                         return rc;
     435         472 :                 cr->ti = tds_i ? 1 : 0;
     436         472 :                 return sizeof(TDS_TINYINT);
     437             :                 break;
     438      155272 :         case SYBMONEY:
     439             :         case SYBMONEY4:
     440             : 
     441      155272 :                 src = parse_numeric(src, src + srclen, &negative, &digits, &decimals);
     442      155272 :                 if (!src)
     443             :                         return TDS_CONVERT_SYNTAX;
     444      155248 :                 if (digits > 18)
     445             :                         return TDS_CONVERT_OVERFLOW;
     446             : 
     447      130800 :                 i = 0;
     448      130800 :                 if (negative)
     449       59504 :                         mynumber[i++] = '-';
     450      839344 :                 for (; digits; --digits)
     451      839344 :                         mynumber[i++] = *src++;
     452      130800 :                 src++;
     453      133200 :                 for (digits = 0; digits < 4 && digits < decimals; ++digits)
     454        2400 :                         mynumber[i++] = *src++;
     455      520800 :                 for (; digits < 4; ++digits)
     456      520800 :                         mynumber[i++] = '0';
     457             : 
     458             :                 /* convert number and check for overflow */
     459      130800 :                 if (string_to_int8(mynumber, mynumber + i, &mymoney) < 0)
     460             :                         return TDS_CONVERT_OVERFLOW;
     461             : 
     462      124496 :                 if (desttype == SYBMONEY) {
     463       62240 :                         cr->m.mny = mymoney;
     464       62240 :                         return sizeof(TDS_MONEY);
     465             :                 } else {
     466       62256 :                         if (!INT_IS_INT(mymoney))
     467             :                                 return TDS_CONVERT_OVERFLOW;
     468       41192 :                         cr->m4.mny4 = (TDS_INT) mymoney;
     469       41192 :                         return sizeof(TDS_MONEY4);
     470             :                 }
     471             :                 break;
     472        2292 :         case SYBDATETIME:
     473             :         case SYBDATETIME4:
     474             :         case SYBMSTIME:
     475             :         case SYBMSDATE:
     476             :         case SYBMSDATETIME2:
     477             :         case SYBMSDATETIMEOFFSET:
     478             :         case SYBTIME:
     479             :         case SYBDATE:
     480             :         case SYB5BIGTIME:
     481             :         case SYB5BIGDATETIME:
     482        2292 :                 return string_to_datetime(src, srclen, desttype, cr);
     483             :                 break;
     484       81800 :         case SYBNUMERIC:
     485             :         case SYBDECIMAL:
     486       81800 :                 return string_to_numeric(src, src + srclen, cr);
     487             :                 break;
     488         224 :         case SYBUNIQUE:{
     489         224 :                         unsigned n = 0;
     490             :                         char c;
     491             : 
     492             :                         /* 
     493             :                          * format:       XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 
     494             :                          * or           {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} 
     495             :                          * or            XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX  
     496             :                          * or           {XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX} 
     497             :                          * SQL seem to ignore the additional braces.
     498             :                          */
     499         224 :                         if (srclen < (32 + 3))
     500             :                                 return TDS_CONVERT_SYNTAX;
     501             : 
     502         152 :                         if (src[0] == '{') {
     503           8 :                                 TDS_UINT last = (src[8+1 + 4+1 + 4+1 + 4 + 1] == '-') ? 32+4+1 : 32+3+1;
     504           8 :                                 if (srclen <= last || src[last] != '}')
     505             :                                         return TDS_CONVERT_SYNTAX;
     506           8 :                                 ++src;
     507             :                         }
     508             : 
     509             :                         /* 
     510             :                          * Test each character and get value.  
     511             :                          * sscanf works if the number terminates with less digits. 
     512             :                          */
     513        4248 :                         for (i = 0; i < 32 + 3; ++i) {
     514        4288 :                                 c = src[i];
     515        4288 :                                 switch (i) {
     516         128 :                                 case 8:
     517         128 :                                         if (c != '-')
     518             :                                                 return TDS_CONVERT_SYNTAX;
     519         128 :                                         cr->u.Data1 = n;
     520         128 :                                         n = 0;
     521         128 :                                         break;
     522         128 :                                 case 8+1 + 4:
     523         128 :                                         if (c != '-')
     524             :                                                 return TDS_CONVERT_SYNTAX;
     525         128 :                                         cr->u.Data2 = n;
     526         128 :                                         n = 0;
     527         128 :                                         break;
     528         120 :                                 case 8+1 + 4+1 + 4:
     529         120 :                                         if (c != '-')
     530             :                                                 return TDS_CONVERT_SYNTAX;
     531         120 :                                         cr->u.Data3 = n;
     532         120 :                                         n = 0;
     533         120 :                                         break;
     534         120 :                                 case 8+1 + 4+1 + 4+1 + 4:
     535             :                                         /* skip last (optional) dash */
     536         120 :                                         if (c == '-') {
     537          88 :                                                 if (--srclen < 32 + 3)
     538             :                                                         return TDS_CONVERT_SYNTAX;
     539          88 :                                                 c = (++src)[i];
     540             :                                         }
     541             :                                         /* fall through */
     542             :                                 default:
     543        3912 :                                         n = n << 4;
     544        3912 :                                         if (c >= '0' && c <= '9')
     545        2678 :                                                 n += c - '0';
     546             :                                         else {
     547        1234 :                                                 c &= 0x20 ^ 0xff;
     548        1234 :                                                 if (c >= 'A' && c <= 'F')
     549        1194 :                                                         n += c - ('A' - 10);
     550             :                                                 else
     551             :                                                         return TDS_CONVERT_SYNTAX;
     552             :                                         }
     553        3872 :                                         if (i > (16 + 2) && !(i & 1)) {
     554         912 :                                                 cr->u.Data4[(i >> 1) - 10] = n;
     555         912 :                                                 n = 0;
     556             :                                         }
     557             :                                 }
     558             :                         }
     559             :                 }
     560             :                 return sizeof(TDS_UNIQUE);
     561             :         default:
     562             :                 return TDS_CONVERT_NOAVAIL;
     563             :                 break;
     564             :         }                       /* end switch */
     565             : }                               /* tds_convert_char */
     566             : 
     567             : static TDS_INT
     568             : tds_convert_bit(const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
     569             : {
     570        5260 :         return tds_convert_int(src[0] ? 1 : 0, desttype, cr);
     571             : }
     572             : 
     573             : static TDS_INT
     574             : tds_convert_int1(const TDS_TINYINT * src, int desttype, CONV_RESULT * cr)
     575             : {
     576       16932 :         return tds_convert_int(*src, desttype, cr);
     577             : }
     578             : 
     579             : static TDS_INT
     580             : tds_convert_int2(const TDS_SMALLINT * src, int desttype, CONV_RESULT * cr)
     581             : {
     582       20990 :         return tds_convert_int(*src, desttype, cr);
     583             : }
     584             : 
     585             : static TDS_INT
     586             : tds_convert_uint2(const TDS_USMALLINT * src, int desttype, CONV_RESULT * cr)
     587             : {
     588       12578 :         return tds_convert_int(*src, desttype, cr);
     589             : }
     590             : 
     591             : static TDS_INT
     592             : tds_convert_int4(const TDS_INT * src, int desttype, CONV_RESULT * cr)
     593             : {
     594       38552 :         return tds_convert_int(*src, desttype, cr);
     595             : }
     596             : 
     597             : static TDS_INT
     598             : tds_convert_uint4(const TDS_UINT * src, int desttype, CONV_RESULT * cr)
     599             : {
     600             :         TDS_UINT8 num;
     601             : 
     602       20422 :         num = *src;
     603       20422 :         return tds_convert_uint8(&num, desttype, cr);
     604             : }
     605             : 
     606             : static TDS_INT
     607             : tds_convert_int_numeric(unsigned char scale,
     608             :         unsigned char sign, TDS_UINT num, CONV_RESULT * cr)
     609             : {
     610       11408 :         unsigned char orig_prec = cr->n.precision, orig_scale = cr->n.scale;
     611       11408 :         cr->n.precision = 10;
     612       11408 :         cr->n.scale = scale;
     613       11408 :         cr->n.array[0] = sign;
     614       11408 :         cr->n.array[1] = 0;
     615       11408 :         TDS_PUT_UA4BE(&(cr->n.array[2]), num);
     616       11408 :         return tds_numeric_change_prec_scale(&(cr->n), orig_prec, orig_scale);
     617             : }
     618             : 
     619             : static TDS_INT
     620             : tds_convert_int8_numeric(unsigned char scale,
     621             :         unsigned char sign, TDS_UINT8 num, CONV_RESULT * cr)
     622             : {
     623        5056 :         unsigned char orig_prec = cr->n.precision, orig_scale = cr->n.scale;
     624        5056 :         cr->n.precision = 20;
     625        5056 :         cr->n.scale = scale;
     626        5056 :         cr->n.array[0] = sign;
     627        5056 :         cr->n.array[1] = 0;
     628        5056 :         TDS_PUT_UA4BE(&(cr->n.array[2]), (TDS_UINT) (num >> 32));
     629        5056 :         TDS_PUT_UA4BE(&(cr->n.array[6]), (TDS_UINT) num);
     630        5056 :         return tds_numeric_change_prec_scale(&(cr->n), orig_prec, orig_scale);
     631             : }
     632             : 
     633             : static TDS_INT
     634      159604 : tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr)
     635             : {
     636             :         TDS_CHAR tmp_str[16];
     637             : 
     638      159604 :         switch (desttype) {
     639        9520 :         case TDS_CONVERT_CHAR:
     640             :         case CASE_ALL_CHAR:
     641        9520 :                 sprintf(tmp_str, "%d", num);
     642        9520 :                 return string_to_result(desttype, tmp_str, cr);
     643             :                 break;
     644       18644 :         case SYBINT1:
     645             :         case SYBUINT1:
     646       18644 :                 if (!IS_TINYINT(num))
     647             :                         return TDS_CONVERT_OVERFLOW;
     648        7204 :                 cr->ti = (TDS_TINYINT) num;
     649        7204 :                 return sizeof(TDS_TINYINT);
     650             :                 break;
     651       11040 :         case SYBINT2:
     652       11040 :                 if (!IS_SMALLINT(num))
     653             :                         return TDS_CONVERT_OVERFLOW;
     654        7824 :                 cr->si = num;
     655        7824 :                 return sizeof(TDS_SMALLINT);
     656             :                 break;
     657        9128 :         case SYBUINT2:
     658        9128 :                 if (!IS_USMALLINT(num))
     659             :                         return TDS_CONVERT_OVERFLOW;
     660        5264 :                 cr->usi = (TDS_USMALLINT) num;
     661        5264 :                 return sizeof(TDS_USMALLINT);
     662             :                 break;
     663       16434 :         case SYBINT4:
     664       16434 :                 cr->i = num;
     665       16434 :                 return sizeof(TDS_INT);
     666             :                 break;
     667       10078 :         case SYBUINT4:
     668       10078 :                 if (num < 0)
     669             :                         return TDS_CONVERT_OVERFLOW;
     670        7558 :                 cr->ui = (TDS_UINT) num;
     671        7558 :                 return sizeof(TDS_UINT);
     672             :                 break;
     673        9392 :         case SYBINT8:
     674        9392 :                 cr->bi = num;
     675        9392 :                 return sizeof(TDS_INT8);
     676             :                 break;
     677        9256 :         case SYBUINT8:
     678        9256 :                 if (num < 0)
     679             :                         return TDS_CONVERT_OVERFLOW;
     680        6736 :                 cr->ubi = (TDS_UINT8) num;
     681        6736 :                 return sizeof(TDS_UINT8);
     682             :                 break;
     683         928 :         case SYBBIT:
     684             :         case SYBBITN:
     685         928 :                 cr->ti = num ? 1 : 0;
     686         928 :                 return sizeof(TDS_TINYINT);
     687             :                 break;
     688        8720 :         case SYBFLT8:
     689        8720 :                 cr->f = num;
     690        8720 :                 return sizeof(TDS_FLOAT);
     691             :                 break;
     692        8720 :         case SYBREAL:
     693        8720 :                 cr->r = (TDS_REAL) num;
     694        8720 :                 return sizeof(TDS_REAL);
     695             :                 break;
     696        9096 :         case SYBMONEY4:
     697        9096 :                 if (num > 214748 || num < -214748)
     698             :                         return TDS_CONVERT_OVERFLOW;
     699        8112 :                 cr->m4.mny4 = num * 10000;
     700        8112 :                 return sizeof(TDS_MONEY4);
     701             :                 break;
     702        9192 :         case SYBMONEY:
     703        9192 :                 cr->m.mny = (TDS_INT8) num *10000;
     704             : 
     705        9192 :                 return sizeof(TDS_MONEY);
     706             :                 break;
     707        9544 :         case SYBNUMERIC:
     708             :         case SYBDECIMAL:
     709        9544 :                 if (num < 0)
     710        5312 :                         return tds_convert_int_numeric(0, 1, (TDS_UINT) -num, cr);
     711       13776 :                 return tds_convert_int_numeric(0, 0, (TDS_UINT) num, cr);
     712             :                 break;
     713             :                 /* handled by upper layer */
     714             :         case CASE_ALL_BINARY:
     715             :                 /* conversions not allowed */
     716             :         case SYBUNIQUE:
     717             :         case SYBDATETIME4:
     718             :         case SYBDATETIME:
     719             :         case SYBDATETIMN:
     720             :         default:
     721             :                 break;
     722             :         }
     723             :         return TDS_CONVERT_NOAVAIL;
     724             : }
     725             : 
     726             : static TDS_INT
     727       45998 : tds_convert_int8(const TDS_INT8 *src, int desttype, CONV_RESULT * cr)
     728             : {
     729             :         TDS_INT8 buf;
     730             :         TDS_CHAR tmp_str[24];
     731             : 
     732       45998 :         memcpy(&buf, src, sizeof(buf));
     733       45998 :         if (INT_IS_INT(buf))
     734       30456 :                 return tds_convert_int((TDS_INT) buf, desttype, cr);
     735             : 
     736       15542 :         switch (desttype) {
     737         498 :         case TDS_CONVERT_CHAR:
     738             :         case CASE_ALL_CHAR:
     739         498 :                 sprintf(tmp_str, "%" PRId64, buf);
     740         498 :                 return string_to_result(desttype, tmp_str, cr);
     741             :                 break;
     742             :         case SYBINT1:
     743             :         case SYBUINT1:
     744             :         case SYBINT2:
     745             :         case SYBUINT2:
     746             :         case SYBINT4:
     747             :         case SYBMONEY4:
     748             :                 return TDS_CONVERT_OVERFLOW;
     749             :                 break;
     750        1096 :         case SYBUINT4:
     751        1096 :                 if (!IS_UINT(buf))
     752             :                         return TDS_CONVERT_OVERFLOW;
     753         184 :                 cr->ui = (TDS_UINT) buf;
     754         184 :                 return sizeof(TDS_UINT);
     755             :                 break;
     756        1244 :         case SYBINT8:
     757        1244 :                 cr->bi = buf;
     758        1244 :                 return sizeof(TDS_INT8);
     759             :                 break;
     760        1128 :         case SYBUINT8:
     761        1128 :                 if (buf < 0)
     762             :                         return TDS_CONVERT_OVERFLOW;
     763         624 :                 cr->ubi = (TDS_UINT8) buf;
     764         624 :                 return sizeof(TDS_UINT8);
     765             :                 break;
     766          72 :         case SYBBIT:
     767             :         case SYBBITN:
     768             :                 /* this cannot be 0 as already tested above */
     769          72 :                 cr->ti = 1;
     770          72 :                 return sizeof(TDS_TINYINT);
     771             :                 break;
     772        1080 :         case SYBFLT8:
     773        1080 :                 cr->f = (TDS_FLOAT) buf;
     774        1080 :                 return sizeof(TDS_FLOAT);
     775             :                 break;
     776        1080 :         case SYBREAL:
     777        1080 :                 cr->r = (TDS_REAL) buf;
     778        1080 :                 return sizeof(TDS_REAL);
     779             :                 break;
     780        1056 :         case SYBMONEY:
     781        1056 :                 if (buf > (TDS_INT8_MAX / 10000) || buf < (TDS_INT8_MIN / 10000))
     782             :                         return TDS_CONVERT_OVERFLOW;
     783         728 :                 cr->m.mny = buf * 10000;
     784         728 :                 return sizeof(TDS_MONEY);
     785             :                 break;
     786        1160 :         case SYBNUMERIC:
     787             :         case SYBDECIMAL:
     788        1160 :                 if (buf < 0)
     789        1072 :                         return tds_convert_int8_numeric(0, 1, -buf, cr);
     790        1248 :                 return tds_convert_int8_numeric(0, 0, buf, cr);
     791             :                 break;
     792             :                 /* conversions not allowed */
     793             :         case SYBUNIQUE:
     794             :         case SYBDATETIME4:
     795             :         case SYBDATETIME:
     796             :         case SYBDATETIMN:
     797             :         default:
     798             :                 break;
     799             :         }
     800         504 :         return TDS_CONVERT_NOAVAIL;
     801             : }
     802             : 
     803             : static TDS_INT
     804       46968 : tds_convert_uint8(const TDS_UINT8 *src, int desttype, CONV_RESULT * cr)
     805             : {
     806             :         TDS_UINT8 buf;
     807             :         TDS_CHAR tmp_str[24];
     808             : 
     809       46968 :         memcpy(&buf, src, sizeof(buf));
     810             :         /* INT_IS_INT does not work here due to unsigned/signed conversions */
     811       46968 :         if (buf <= TDS_INT_MAX)
     812       34836 :                 return tds_convert_int((TDS_INT) buf, desttype, cr);
     813             : 
     814       12132 :         switch (desttype) {
     815         380 :         case TDS_CONVERT_CHAR:
     816             :         case CASE_ALL_CHAR:
     817         380 :                 sprintf(tmp_str, "%" PRIu64, buf);
     818         380 :                 return string_to_result(desttype, tmp_str, cr);
     819             :                 break;
     820             :         case SYBINT1:
     821             :         case SYBUINT1:
     822             :         case SYBINT2:
     823             :         case SYBUINT2:
     824             :         case SYBINT4:
     825             :         case SYBMONEY4:
     826             :                 return TDS_CONVERT_OVERFLOW;
     827             :                 break;
     828         896 :         case SYBUINT4:
     829         896 :                 if (!IS_UINT(buf))
     830             :                         return TDS_CONVERT_OVERFLOW;
     831         368 :                 cr->ui = (TDS_UINT) buf;
     832             :                 return sizeof(TDS_UINT);
     833             :                 break;
     834         928 :         case SYBINT8:
     835         928 :                 if (buf > TDS_INT8_MAX)
     836             :                         return TDS_CONVERT_OVERFLOW;
     837         760 :                 cr->bi = (TDS_INT8) buf;
     838             :                 return sizeof(TDS_INT8);
     839             :                 break;
     840         944 :         case SYBUINT8:
     841         944 :                 cr->ubi = buf;
     842             :                 return sizeof(TDS_UINT8);
     843             :                 break;
     844          24 :         case SYBBIT:
     845             :         case SYBBITN:
     846             :                 /* this cannot be 0 as already tested above */
     847          24 :                 cr->ti = 1;
     848             :                 return sizeof(TDS_TINYINT);
     849             :                 break;
     850         864 :         case SYBFLT8:
     851         864 :                 cr->f = (TDS_FLOAT) buf;
     852             :                 return sizeof(TDS_FLOAT);
     853             :                 break;
     854         864 :         case SYBREAL:
     855         864 :                 cr->r = (TDS_REAL) buf;
     856             :                 return sizeof(TDS_REAL);
     857             :                 break;
     858         888 :         case SYBMONEY:
     859         888 :                 if (buf > (TDS_INT8_MAX / 10000))
     860             :                         return TDS_CONVERT_OVERFLOW;
     861         560 :                 cr->m.mny = buf * 10000;
     862             :                 return sizeof(TDS_MONEY);
     863             :                 break;
     864         944 :         case SYBNUMERIC:
     865             :         case SYBDECIMAL:
     866        1888 :                 return tds_convert_int8_numeric(0, 0, buf, cr);
     867             :                 break;
     868             :                 /* conversions not allowed */
     869             :         case SYBUNIQUE:
     870             :         case SYBDATETIME4:
     871             :         case SYBDATETIME:
     872             :         case SYBDATETIMN:
     873             :         default:
     874             :                 break;
     875             :         }
     876             :         return TDS_CONVERT_NOAVAIL;
     877             : }
     878             : 
     879             : static TDS_INT
     880       56398 : tds_convert_numeric(const TDS_NUMERIC * src, int desttype, CONV_RESULT * cr)
     881             : {
     882             :         char tmpstr[MAXPRECISION];
     883             :         TDS_INT i, ret;
     884             :         TDS_INT8 bi;
     885             : 
     886       56398 :         switch (desttype) {
     887        1812 :         case TDS_CONVERT_CHAR:
     888             :         case CASE_ALL_CHAR:
     889        1812 :                 if (tds_numeric_to_string(src, tmpstr) < 0)
     890             :                         return TDS_CONVERT_FAIL;
     891        1812 :                 return string_to_result(desttype, tmpstr, cr);
     892             :                 break;
     893        7584 :         case SYBINT1:
     894             :         case SYBUINT1:
     895        7584 :                 cr->n = *src;
     896        7584 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 3, 0);
     897        7584 :                 if (ret < 0)
     898             :                         return ret;
     899        2112 :                 if (cr->n.array[1] || (cr->n.array[0] && cr->n.array[2]))
     900             :                         return TDS_CONVERT_OVERFLOW;
     901         944 :                 cr->ti = cr->n.array[2];
     902         944 :                 return sizeof(TDS_TINYINT);
     903             :                 break;
     904        3848 :         case SYBINT2:
     905        3848 :                 cr->n = *src;
     906        3848 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 5, 0);
     907        3848 :                 if (ret < 0)
     908             :                         return ret;
     909        1768 :                 if (cr->n.array[1])
     910             :                         return TDS_CONVERT_OVERFLOW;
     911        1592 :                 i = TDS_GET_UA2BE(&(cr->n.array[2]));
     912        1592 :                 if (cr->n.array[0])
     913         776 :                         i = -i;
     914        1592 :                 if (i != 0 && ((i >> 15) ^ cr->n.array[0]) & 1)
     915             :                         return TDS_CONVERT_OVERFLOW;
     916        1264 :                 cr->si = (TDS_SMALLINT) i;
     917        1264 :                 return sizeof(TDS_SMALLINT);
     918             :                 break;
     919        3808 :         case SYBUINT2:
     920        3808 :                 cr->n = *src;
     921        3808 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 5, 0);
     922        3808 :                 if (ret < 0)
     923             :                         return ret;
     924        1760 :                 i = TDS_GET_UA2BE(&(cr->n.array[2]));
     925        1760 :                 if ((i != 0 && cr->n.array[0]) || cr->n.array[1])
     926             :                         return TDS_CONVERT_OVERFLOW;
     927         840 :                 cr->usi = (TDS_USMALLINT) i;
     928         840 :                 return sizeof(TDS_USMALLINT);
     929             :                 break;
     930        3928 :         case SYBINT4:
     931        3928 :                 cr->n = *src;
     932        3928 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 10, 0);
     933        3928 :                 if (ret < 0)
     934             :                         return ret;
     935        2920 :                 if (cr->n.array[1])
     936             :                         return TDS_CONVERT_OVERFLOW;
     937        2744 :                 i = TDS_GET_UA4BE(&(cr->n.array[2]));
     938        2744 :                 if (cr->n.array[0])
     939        1312 :                         i = -i;
     940        2744 :                 if (i != 0 && ((i >> 31) ^ cr->n.array[0]) & 1)
     941             :                         return TDS_CONVERT_OVERFLOW;
     942        2416 :                 cr->i = i;
     943        2416 :                 return sizeof(TDS_INT);
     944             :                 break;
     945        3856 :         case SYBUINT4:
     946        3856 :                 cr->n = *src;
     947        3856 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 10, 0);
     948        3856 :                 if (ret < 0)
     949             :                         return ret;
     950        2848 :                 i = TDS_GET_UA4BE(&(cr->n.array[2]));
     951        2848 :                 if ((i != 0 && cr->n.array[0]) || cr->n.array[1])
     952             :                         return TDS_CONVERT_OVERFLOW;
     953        1424 :                 cr->ui = i;
     954        1424 :                 return sizeof(TDS_UINT);
     955             :                 break;
     956        3976 :         case SYBINT8:
     957        3976 :                 cr->n = *src;
     958        3976 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 20, 0);
     959        3976 :                 if (ret < 0)
     960             :                         return ret;
     961        3976 :                 if (cr->n.array[1])
     962             :                         return TDS_CONVERT_OVERFLOW;
     963        3800 :                 bi = TDS_GET_UA4BE(&(cr->n.array[2]));
     964        3800 :                 bi = (bi << 32) + TDS_GET_UA4BE(&(cr->n.array[6]));
     965        3800 :                 if (cr->n.array[0])
     966        1848 :                         bi = -bi;
     967        3800 :                 if (bi != 0 && ((bi >> 63) ^ cr->n.array[0]) & 1)
     968             :                         return TDS_CONVERT_OVERFLOW;
     969        3472 :                 cr->bi = bi;
     970        3472 :                 return sizeof(TDS_INT8);
     971             :                 break;
     972        3904 :         case SYBUINT8:
     973        3904 :                 cr->n = *src;
     974        3904 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 20, 0);
     975        3904 :                 if (ret < 0)
     976             :                         return ret;
     977        3904 :                 bi = TDS_GET_UA4BE(&(cr->n.array[2]));
     978        3904 :                 bi = (bi << 32) + TDS_GET_UA4BE(&(cr->n.array[6]));
     979        3904 :                 if ((bi != 0 && cr->n.array[0]) || cr->n.array[1])
     980             :                         return TDS_CONVERT_OVERFLOW;
     981        1976 :                 cr->ubi = bi;
     982        1976 :                 return sizeof(TDS_UINT8);
     983             :                 break;
     984          64 :         case SYBBIT:
     985             :         case SYBBITN:
     986          64 :                 cr->ti = 0;
     987         128 :                 for (i = tds_numeric_bytes_per_prec[src->precision]; --i > 0;)
     988          64 :                         if (src->array[i] != 0) {
     989          64 :                                 cr->ti = 1;
     990          64 :                                 break;
     991             :                         }
     992             :                 return sizeof(TDS_TINYINT);
     993             :                 break;
     994        3832 :         case SYBMONEY4:
     995        3832 :                 cr->n = *src;
     996        3832 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 10, 4);
     997        3832 :                 if (ret < 0)
     998             :                         return ret;
     999        2152 :                 if (cr->n.array[1])
    1000             :                         return TDS_CONVERT_OVERFLOW;
    1001        2152 :                 i = TDS_GET_UA4BE(&(cr->n.array[2]));
    1002        2152 :                 if (cr->n.array[0])
    1003        1048 :                         i = -i;
    1004        2152 :                 if (i != 0 && ((i >> 31) ^ cr->n.array[0]) & 1)
    1005             :                         return TDS_CONVERT_OVERFLOW;
    1006        1992 :                 cr->m4.mny4 = i;
    1007        1992 :                 return sizeof(TDS_MONEY4);
    1008             :                 break;
    1009        3912 :         case SYBMONEY:
    1010        3912 :                 cr->n = *src;
    1011        3912 :                 ret = tds_numeric_change_prec_scale(&(cr->n), 20, 4);
    1012        3912 :                 if (ret < 0)
    1013             :                         return ret;
    1014        3240 :                 if (cr->n.array[1])
    1015             :                         return TDS_CONVERT_OVERFLOW;
    1016        3240 :                 bi = TDS_GET_UA4BE(&(cr->n.array[2]));
    1017        3240 :                 bi = (bi << 32) + TDS_GET_UA4BE(&(cr->n.array[6]));
    1018        3240 :                 if (cr->n.array[0])
    1019        1584 :                         bi = -bi;
    1020        3240 :                 if (bi != 0 && ((bi >> 63) ^ cr->n.array[0]) & 1)
    1021             :                         return TDS_CONVERT_OVERFLOW;
    1022        3080 :                 cr->m.mny = bi;
    1023        3080 :                 return sizeof(TDS_MONEY);
    1024             :                 break;
    1025        4498 :         case SYBNUMERIC:
    1026             :         case SYBDECIMAL:
    1027             :                 {
    1028        4498 :                         unsigned char prec = cr->n.precision, scale = cr->n.scale;
    1029        4498 :                         cr->n = *src;
    1030        4498 :                         return tds_numeric_change_prec_scale(&(cr->n), prec, scale);
    1031             :                 }
    1032             :                 break;
    1033        3744 :         case SYBFLT8:
    1034        3744 :                 if (tds_numeric_to_string(src, tmpstr) < 0)
    1035             :                         return TDS_CONVERT_FAIL;
    1036        3744 :                 cr->f = atof(tmpstr);
    1037        3744 :                 return 8;
    1038             :                 break;
    1039        3744 :         case SYBREAL:
    1040        3744 :                 if (tds_numeric_to_string(src, tmpstr) < 0)
    1041             :                         return TDS_CONVERT_FAIL;
    1042        3744 :                 cr->r = (TDS_REAL) atof(tmpstr);
    1043        3744 :                 return 4;
    1044             :                 break;
    1045             :                 /* TODO conversions to money */
    1046             :                 /* conversions not allowed */
    1047             :         case SYBUNIQUE:
    1048             :         case SYBDATETIME4:
    1049             :         case SYBDATETIME:
    1050             :         case SYBDATETIMN:
    1051             :         default:
    1052             :                 break;
    1053             :         }
    1054             :         return TDS_CONVERT_NOAVAIL;
    1055             : }
    1056             : 
    1057             : static TDS_INT
    1058       26920 : tds_convert_money4(const TDSCONTEXT * tds_ctx, const TDS_MONEY4 * src, int desttype, CONV_RESULT * cr)
    1059             : {
    1060             :         TDS_MONEY4 mny;
    1061             :         long dollars;
    1062             :         char tmp_str[33];
    1063             :         char *p;
    1064             : 
    1065       26920 :         mny = *src;
    1066       26920 :         switch (desttype) {
    1067        1184 :         case TDS_CONVERT_CHAR:
    1068             :         case CASE_ALL_CHAR: {
    1069             :                 unsigned dollars;
    1070             :                 /*
    1071             :                  * round to 2 decimal digits
    1072             :                  * rounding with dollars = (mny.mny4 + 5000) /10000
    1073             :                  * can give arithmetic overflow so I use
    1074             :                  * dollars = (mny.mny4/50 + 1)/2 
    1075             :                  */
    1076             :                 /* TODO round also all conversions to int and from money ?? */
    1077        1184 :                 p = tmp_str;
    1078        1184 :                 if (mny.mny4 < 0) {
    1079         248 :                         *p++ = '-';
    1080             :                         /* we use unsigned cause this cause arithmetic problem for -2^31*/
    1081         248 :                         dollars = -mny.mny4;
    1082             :                 } else {
    1083         936 :                         dollars = mny.mny4;
    1084             :                 }
    1085        1184 :                 if (tds_ctx->money_use_2_digits) {
    1086             :                         /* print only 2 decimal digits as server does */
    1087           0 :                         dollars = (dollars + 50) / 100;
    1088           0 :                         sprintf(p, "%u.%02u", dollars / 100u, dollars % 100u);
    1089             :                 } else {
    1090        1184 :                         sprintf(p, "%u.%04u", dollars / 10000u, dollars % 10000u);
    1091             :                 }
    1092        1184 :                 return string_to_result(desttype, tmp_str, cr);
    1093             :                 } break;
    1094        3576 :         case SYBINT1:
    1095             :         case SYBUINT1:
    1096        3576 :                 dollars = mny.mny4 / 10000;
    1097        3576 :                 if (!IS_TINYINT(dollars))
    1098             :                         return TDS_CONVERT_OVERFLOW;
    1099         752 :                 cr->ti = (TDS_TINYINT) dollars;
    1100             :                 return sizeof(TDS_TINYINT);
    1101             :                 break;
    1102        1848 :         case SYBINT2:
    1103        1848 :                 dollars = mny.mny4 / 10000;
    1104        1848 :                 if (!IS_SMALLINT(dollars))
    1105             :                         return TDS_CONVERT_OVERFLOW;
    1106        1168 :                 cr->si = (TDS_SMALLINT) dollars;
    1107             :                 return sizeof(TDS_SMALLINT);
    1108             :                 break;
    1109        1800 :         case SYBUINT2:
    1110        1800 :                 dollars = mny.mny4 / 10000;
    1111        1800 :                 if (!IS_USMALLINT(dollars))
    1112             :                         return TDS_CONVERT_OVERFLOW;
    1113         784 :                 cr->usi = (TDS_USMALLINT) dollars;
    1114             :                 return sizeof(TDS_USMALLINT);
    1115             :                 break;
    1116        1896 :         case SYBINT4:
    1117        1896 :                 cr->i = mny.mny4 / 10000;
    1118             :                 return sizeof(TDS_INT);
    1119             :                 break;
    1120        1816 :         case SYBUINT4:
    1121        1816 :                 dollars = mny.mny4 / 10000;
    1122        1816 :                 if (!IS_UINT(dollars))
    1123             :                         return TDS_CONVERT_OVERFLOW;
    1124         976 :                 cr->ui = dollars;
    1125             :                 return sizeof(TDS_UINT);
    1126             :                 break;
    1127        1856 :         case SYBINT8:
    1128        1856 :                 cr->bi = mny.mny4 / 10000;
    1129             :                 return sizeof(TDS_INT8);
    1130             :                 break;
    1131        1816 :         case SYBUINT8:
    1132        1816 :                 dollars = mny.mny4 / 10000;
    1133        1816 :                 if (dollars < 0)
    1134             :                         return TDS_CONVERT_OVERFLOW;
    1135         976 :                 cr->ubi = dollars;
    1136             :                 return sizeof(TDS_UINT8);
    1137             :                 break;
    1138          56 :         case SYBBIT:
    1139             :         case SYBBITN:
    1140          56 :                 cr->ti = mny.mny4 ? 1 : 0;
    1141             :                 return sizeof(TDS_TINYINT);
    1142             :                 break;
    1143        1736 :         case SYBFLT8:
    1144        1736 :                 cr->f = ((TDS_FLOAT) mny.mny4) / 10000.0;
    1145             :                 return sizeof(TDS_FLOAT);
    1146             :                 break;
    1147        1736 :         case SYBREAL:
    1148        1736 :                 cr->r = (TDS_REAL) (mny.mny4 / 10000.0);
    1149             :                 return sizeof(TDS_REAL);
    1150             :                 break;
    1151        1816 :         case SYBMONEY:
    1152        1816 :                 cr->m.mny = (TDS_INT8) mny.mny4;
    1153             :                 return sizeof(TDS_MONEY);
    1154             :                 break;
    1155        1808 :         case SYBMONEY4:
    1156        1808 :                 cr->m4 = mny;
    1157             :                 return sizeof(TDS_MONEY4);
    1158             :                 break;
    1159        1864 :         case SYBDECIMAL:
    1160             :         case SYBNUMERIC:
    1161        1864 :                 if (mny.mny4 < 0)
    1162        1760 :                         return tds_convert_int_numeric(4, 1, (TDS_UINT) -mny.mny4, cr);
    1163        1968 :                 return tds_convert_int_numeric(4, 0, (TDS_UINT) mny.mny4, cr);
    1164             :                 /* conversions not allowed */
    1165             :         case SYBUNIQUE:
    1166             :         case SYBDATETIME4:
    1167             :         case SYBDATETIME:
    1168             :         case SYBDATETIMN:
    1169             :         default:
    1170             :                 return TDS_CONVERT_NOAVAIL;
    1171             :                 break;
    1172             :         }
    1173             :         return TDS_CONVERT_FAIL;
    1174             : }
    1175             : 
    1176             : static TDS_INT
    1177       40826 : tds_convert_money(const TDSCONTEXT * tds_ctx, const TDS_MONEY * src, int desttype, CONV_RESULT * cr)
    1178             : {
    1179             :         char *s;
    1180             : 
    1181             :         TDS_INT8 mymoney, dollars;
    1182             :         char tmpstr[64];
    1183             : 
    1184       40826 :         tdsdump_log(TDS_DBG_FUNC, "tds_convert_money()\n");
    1185       40826 :         mymoney = ((TDS_INT8) src->tdsoldmoney.mnyhigh << 32) | src->tdsoldmoney.mnylow;
    1186             : 
    1187       40826 :         switch (desttype) {
    1188        1592 :         case TDS_CONVERT_CHAR:
    1189             :         case CASE_ALL_CHAR:
    1190        1592 :                 s = tds_money_to_string((const TDS_MONEY *) src, tmpstr, tds_ctx->money_use_2_digits);
    1191        1592 :                 return string_to_result(desttype, s, cr);
    1192             :                 break;
    1193        5592 :         case SYBINT1:
    1194             :         case SYBUINT1:
    1195        5592 :                 if (mymoney <= -10000 || mymoney >= 256 * 10000)
    1196             :                         return TDS_CONVERT_OVERFLOW;
    1197             :                 /* TODO: round ?? */
    1198         752 :                 cr->ti = (TDS_TINYINT) (((TDS_INT) mymoney) / 10000);
    1199             :                 return sizeof(TDS_TINYINT);
    1200             :                 break;
    1201        2856 :         case SYBINT2:
    1202        2856 :                 if (mymoney <= -32769 * 10000 || mymoney >= 32768 * 10000)
    1203             :                         return TDS_CONVERT_OVERFLOW;
    1204        1168 :                 cr->si = (TDS_SMALLINT) (((TDS_INT) mymoney) / 10000);
    1205             :                 return sizeof(TDS_SMALLINT);
    1206             :                 break;
    1207        2808 :         case SYBUINT2:
    1208        2808 :                 if (mymoney <= -1 * 10000 || mymoney >= 65536 * 10000)
    1209             :                         return TDS_CONVERT_OVERFLOW;
    1210         784 :                 cr->usi = (TDS_USMALLINT) (((TDS_INT) mymoney) / 10000);
    1211             :                 return sizeof(TDS_USMALLINT);
    1212             :                 break;
    1213        2936 :         case SYBINT4:
    1214        2936 :                 dollars = mymoney / 10000;
    1215        2936 :                 if (!INT_IS_INT(dollars))
    1216             :                         return TDS_CONVERT_OVERFLOW;
    1217        2256 :                 cr->i = (TDS_INT) dollars;
    1218             :                 return sizeof(TDS_INT);
    1219             :                 break;
    1220        2856 :         case SYBUINT4:
    1221        2856 :                 dollars = mymoney / 10000;
    1222        2856 :                 if (!IS_UINT(dollars))
    1223             :                         return TDS_CONVERT_OVERFLOW;
    1224        1336 :                 cr->ui = (TDS_UINT) dollars;
    1225             :                 return sizeof(TDS_UINT);
    1226             :                 break;
    1227        2944 :         case SYBINT8:
    1228        2944 :                 cr->bi = mymoney / 10000;
    1229             :                 return sizeof(TDS_INT8);
    1230             :                 break;
    1231        2872 :         case SYBUINT8:
    1232        2872 :                 dollars = mymoney / 10000;
    1233        2872 :                 if (dollars < 0)
    1234             :                         return TDS_CONVERT_OVERFLOW;
    1235        1528 :                 cr->ubi = (TDS_UINT8) dollars;
    1236             :                 return sizeof(TDS_UINT8);
    1237             :                 break;
    1238          56 :         case SYBBIT:
    1239             :         case SYBBITN:
    1240          56 :                 cr->ti = mymoney ? 1 : 0;
    1241             :                 return sizeof(TDS_TINYINT);
    1242             :                 break;
    1243        2786 :         case SYBFLT8:
    1244        2786 :                 cr->f = ((TDS_FLOAT) mymoney) / 10000.0;
    1245             :                 return sizeof(TDS_FLOAT);
    1246             :                 break;
    1247        2744 :         case SYBREAL:
    1248        2744 :                 cr->r = (TDS_REAL) (mymoney / 10000.0);
    1249             :                 return sizeof(TDS_REAL);
    1250             :                 break;
    1251        2824 :         case SYBMONEY4:
    1252        2824 :                 if (!INT_IS_INT(mymoney))
    1253             :                         return TDS_CONVERT_OVERFLOW;
    1254        1816 :                 cr->m4.mny4 = (TDS_INT) mymoney;
    1255             :                 return sizeof(TDS_MONEY4);
    1256             :                 break;
    1257        2896 :         case SYBMONEY:
    1258        2896 :                 cr->m.mny = mymoney;
    1259             :                 return sizeof(TDS_MONEY);
    1260             :                 break;
    1261        2952 :         case SYBDECIMAL:
    1262             :         case SYBNUMERIC:
    1263        2952 :                 if (mymoney < 0)
    1264        2832 :                         return tds_convert_int8_numeric(4, 1, -mymoney, cr);
    1265        3072 :                 return tds_convert_int8_numeric(4, 0, mymoney, cr);
    1266             :                 break;
    1267             :                 /* conversions not allowed */
    1268             :         case SYBUNIQUE:
    1269             :         case SYBDATETIME4:
    1270             :         case SYBDATETIME:
    1271             :         case SYBDATETIMN:
    1272             :         default:
    1273             :                 break;
    1274             :         }
    1275             :         return TDS_CONVERT_NOAVAIL;
    1276             : }
    1277             : 
    1278             : static TDS_INT
    1279       19420 : tds_convert_datetimeall(const TDSCONTEXT * tds_ctx, int srctype, const TDS_DATETIMEALL * dta, int desttype, CONV_RESULT * cr)
    1280             : {
    1281             :         char whole_date_string[64];
    1282             :         const char *datetime_fmt;
    1283             :         TDSDATEREC when;
    1284             : 
    1285       19420 :         switch (desttype) {
    1286         482 :         case TDS_CONVERT_CHAR:
    1287             :         case CASE_ALL_CHAR:
    1288         482 :                 tds_datecrack(srctype, dta, &when);
    1289         482 :                 datetime_fmt = tds_ctx->locale->datetime_fmt;
    1290         482 :                 if (srctype == SYBMSDATE && tds_ctx->locale->date_fmt)
    1291          88 :                         datetime_fmt = tds_ctx->locale->date_fmt;
    1292         482 :                 if (srctype == SYBMSTIME && tds_ctx->locale->time_fmt)
    1293         176 :                         datetime_fmt = tds_ctx->locale->time_fmt;
    1294         482 :                 tds_strftime(whole_date_string, sizeof(whole_date_string), datetime_fmt, &when,
    1295         482 :                              dta->time_prec);
    1296             : 
    1297         482 :                 return string_to_result(desttype, whole_date_string, cr);
    1298         334 :         case SYBDATETIME:
    1299         334 :                 cr->dt.dtdays = dta->date;
    1300         334 :                 cr->dt.dttime = (TDS_INT) ((dta->time * 3u + 50000u) / 100000u);
    1301             :                 return sizeof(TDS_DATETIME);
    1302          64 :         case SYBDATETIME4:
    1303          64 :                 if (!IS_USMALLINT(dta->date))
    1304             :                         return TDS_CONVERT_OVERFLOW;
    1305          64 :                 cr->dt4.days = (TDS_USMALLINT) dta->date;
    1306          64 :                 cr->dt4.minutes = (TDS_USMALLINT) ((dta->time + 30u * 10000000u) / (60u * 10000000u));
    1307             :                 return sizeof(TDS_DATETIME4);
    1308        1148 :         case SYBMSDATETIMEOFFSET:
    1309             :         case SYBMSDATE:
    1310             :         case SYBMSTIME:
    1311             :         case SYBMSDATETIME2:
    1312        1148 :                 cr->dta = *dta;
    1313             :                 return sizeof(TDS_DATETIMEALL);
    1314          80 :         case SYBDATE:
    1315          80 :                 cr->date = dta->date;
    1316             :                 return sizeof(TDS_DATE);
    1317          64 :         case SYBTIME:
    1318          64 :                 cr->time = (TDS_INT) ((dta->time * 3u + 50000u) / 100000u);
    1319             :                 return sizeof(TDS_TIME);
    1320          72 :         case SYB5BIGTIME:
    1321          72 :                 cr->bigtime = dta->time / 10u;
    1322             :                 return sizeof(TDS_UINT8);
    1323          88 :         case SYB5BIGDATETIME:
    1324         176 :                 cr->bigtime = dta->time / 10u
    1325          88 :                               + (dta->date + BIGDATETIME_BIAS) * ((TDS_UINT8) 86400u * 1000000u);
    1326             :                 return sizeof(TDS_UINT8);
    1327             :                 /* conversions not allowed */
    1328             :         case SYBUNIQUE:
    1329             :         case SYBBIT:
    1330             :         case SYBBITN:
    1331             :         case SYBINT1:
    1332             :         case SYBUINT1:
    1333             :         case SYBINT2:
    1334             :         case SYBUINT2:
    1335             :         case SYBINT4:
    1336             :         case SYBUINT4:
    1337             :         case SYBINT8:
    1338             :         case SYBUINT8:
    1339             :         case SYBMONEY4:
    1340             :         case SYBMONEY:
    1341             :         case SYBNUMERIC:
    1342             :         case SYBDECIMAL:
    1343             :         default:
    1344             :                 break;
    1345             :         }
    1346             :         return TDS_CONVERT_NOAVAIL;
    1347             : }
    1348             : 
    1349             : static TDS_INT
    1350        6504 : tds_convert_datetime(const TDSCONTEXT * tds_ctx, const TDS_DATETIME * dt, int desttype, unsigned precision, CONV_RESULT * cr)
    1351             : {
    1352             :         char whole_date_string[64];
    1353             :         TDSDATEREC when;
    1354             : 
    1355        6504 :         switch (desttype) {
    1356         414 :         case TDS_CONVERT_CHAR:
    1357             :         case CASE_ALL_CHAR:
    1358         414 :                 tds_datecrack(SYBDATETIME, dt, &when);
    1359         414 :                 tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->datetime_fmt, &when, 3);
    1360             : 
    1361         414 :                 return string_to_result(desttype, whole_date_string, cr);
    1362           8 :         case SYBDATETIME:
    1363           8 :                 cr->dt = *dt;
    1364             :                 return sizeof(TDS_DATETIME);
    1365           8 :         case SYBDATETIME4:
    1366           8 :                 if (!IS_USMALLINT(dt->dtdays))
    1367             :                         return TDS_CONVERT_OVERFLOW;
    1368           8 :                 cr->dt4.days = dt->dtdays;
    1369           8 :                 cr->dt4.minutes = (dt->dttime / 300) / 60;
    1370             :                 return sizeof(TDS_DATETIME4);
    1371          24 :         case SYBDATE:
    1372          24 :                 cr->date = dt->dtdays;
    1373             :                 return sizeof(TDS_DATE);
    1374          24 :         case SYBTIME:
    1375          24 :                 cr->time = dt->dttime;
    1376             :                 return sizeof(TDS_TIME);
    1377         954 :         case SYBMSDATETIMEOFFSET:
    1378             :         case SYBMSDATE:
    1379             :         case SYBMSTIME:
    1380             :         case SYBMSDATETIME2:
    1381         954 :                 memset(&cr->dta, 0, sizeof(cr->dta));
    1382         954 :                 cr->dta.time_prec = precision;
    1383         954 :                 if (desttype == SYBMSDATETIMEOFFSET)
    1384          16 :                         cr->dta.has_offset = 1;
    1385         954 :                 if (desttype != SYBMSDATE) {
    1386         938 :                         cr->dta.has_time = 1;
    1387         938 :                         cr->dta.time_prec = 3;
    1388         938 :                         cr->dta.time = (((TDS_UINT8) dt->dttime) * 20 + 3) / 6 * 10000u;
    1389             :                 }
    1390         954 :                 if (desttype != SYBMSTIME) {
    1391         938 :                         cr->dta.has_date = 1;
    1392         938 :                         cr->dta.date = dt->dtdays;
    1393             :                 }
    1394             :                 return sizeof(TDS_DATETIMEALL);
    1395          16 :         case SYB5BIGTIME:
    1396          16 :                 cr->bigtime = (((TDS_UINT8) dt->dttime) * 20u + 3u) / 6u * 1000u;
    1397             :                 return sizeof(TDS_BIGTIME);
    1398          16 :         case SYB5BIGDATETIME:
    1399          32 :                 cr->bigdatetime = (((TDS_UINT8) dt->dttime) * 20u + 3u) / 6u * 1000u
    1400          16 :                                   + (dt->dtdays + BIGDATETIME_BIAS) * ((TDS_UINT8) 86400u * 1000000u);
    1401             :                 return sizeof(TDS_BIGDATETIME);
    1402             :                 /* conversions not allowed */
    1403             :         case SYBUNIQUE:
    1404             :         case SYBBIT:
    1405             :         case SYBBITN:
    1406             :         case SYBINT1:
    1407             :         case SYBUINT1:
    1408             :         case SYBINT2:
    1409             :         case SYBUINT2:
    1410             :         case SYBINT4:
    1411             :         case SYBUINT4:
    1412             :         case SYBINT8:
    1413             :         case SYBUINT8:
    1414             :         case SYBMONEY4:
    1415             :         case SYBMONEY:
    1416             :         case SYBNUMERIC:
    1417             :         case SYBDECIMAL:
    1418             :         default:
    1419             :                 break;
    1420             :         }
    1421             :         return TDS_CONVERT_NOAVAIL;
    1422             : }
    1423             : 
    1424             : static TDS_INT
    1425        2948 : tds_convert_datetime4(const TDSCONTEXT * tds_ctx, const TDS_DATETIME4 * dt4, int desttype, CONV_RESULT * cr)
    1426             : {
    1427             :         TDS_DATETIME dt;
    1428             : 
    1429        2948 :         if (desttype == SYBDATETIME4) {
    1430           0 :                 cr->dt4 = *dt4;
    1431           0 :                 return sizeof(TDS_DATETIME4);
    1432             :         }
    1433             : 
    1434             :         /* convert to DATETIME and use tds_convert_datetime */
    1435        2948 :         dt.dtdays = dt4->days;
    1436        2948 :         dt.dttime = dt4->minutes * (60u * 300u);
    1437        2948 :         return tds_convert_datetime(tds_ctx, &dt, desttype, 0, cr);
    1438             : }
    1439             : 
    1440             : static TDS_INT
    1441        2560 : tds_convert_time(const TDSCONTEXT * tds_ctx, const TDS_TIME * time, int desttype, CONV_RESULT * cr)
    1442             : {
    1443             :         TDS_DATETIMEALL dta;
    1444             : 
    1445        2560 :         if (desttype == SYBTIME) {
    1446           8 :                 cr->time = *time;
    1447           8 :                 return sizeof(TDS_TIME);
    1448             :         }
    1449             : 
    1450             :         /* convert to DATETIMEALL and use tds_convert_datetimeall */
    1451        2552 :         memset(&dta, 0, sizeof(dta));
    1452        2552 :         dta.has_time = 1;
    1453        2552 :         dta.time_prec = 3;
    1454        2552 :         dta.time = ((TDS_UINT8) *time * 100000 + 2) / 3;
    1455        2552 :         dta.time = (((TDS_UINT8) *time) * 20 + 3) / 6 * 10000;
    1456        2552 :         return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
    1457             : }
    1458             : 
    1459             : static TDS_INT
    1460        2576 : tds_convert_date(const TDSCONTEXT * tds_ctx, const TDS_DATE * date, int desttype, CONV_RESULT * cr)
    1461             : {
    1462             :         TDS_DATETIMEALL dta;
    1463             : 
    1464        2576 :         if (desttype == SYBDATE) {
    1465           8 :                 cr->date = *date;
    1466           8 :                 return sizeof(TDS_DATE);
    1467             :         }
    1468             : 
    1469             :         /* convert to DATETIMEALL and use tds_convert_datetimeall */
    1470        2568 :         memset(&dta, 0, sizeof(dta));
    1471        2568 :         dta.has_date = 1;
    1472        2568 :         dta.date = *date;
    1473        2568 :         return tds_convert_datetimeall(tds_ctx, SYBMSDATE, &dta, desttype, cr);
    1474             : }
    1475             : 
    1476             : static TDS_INT
    1477        2192 : tds_convert_bigtime(const TDSCONTEXT * tds_ctx, const TDS_BIGTIME * bigtime, int desttype, CONV_RESULT * cr)
    1478             : {
    1479             :         TDS_DATETIMEALL dta;
    1480             : 
    1481        2192 :         if (desttype == SYB5BIGTIME) {
    1482           0 :                 cr->bigtime = *bigtime;
    1483           0 :                 return sizeof(TDS_BIGTIME);
    1484             :         }
    1485             : 
    1486             :         /* convert to DATETIMEALL and use tds_convert_datetimeall */
    1487        2192 :         memset(&dta, 0, sizeof(dta));
    1488        2192 :         dta.time_prec = 6;
    1489        2192 :         dta.has_time = 1;
    1490        2192 :         dta.time = *bigtime % ((TDS_UINT8) 86400u * 1000000u) * 10u;
    1491        2192 :         return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
    1492             : }
    1493             : 
    1494             : static TDS_INT
    1495        2216 : tds_convert_bigdatetime(const TDSCONTEXT * tds_ctx, const TDS_BIGDATETIME * bigdatetime, int desttype, CONV_RESULT * cr)
    1496             : {
    1497             :         TDS_DATETIMEALL dta;
    1498             :         TDS_UINT8 bdt;
    1499             : 
    1500        2216 :         if (desttype == SYB5BIGDATETIME) {
    1501           0 :                 cr->bigdatetime = *bigdatetime;
    1502             :                 return sizeof(TDS_BIGDATETIME);
    1503             :         }
    1504             : 
    1505             :         /* convert to DATETIMEALL and use tds_convert_datetimeall */
    1506        2216 :         bdt = *bigdatetime;
    1507        2216 :         memset(&dta, 0, sizeof(dta));
    1508        2216 :         dta.time_prec = 6;
    1509        2216 :         dta.has_time = 1;
    1510        2216 :         dta.time = bdt % ((TDS_UINT8) 86400u * 1000000u) * 10u;
    1511        2216 :         bdt /= (TDS_UINT8) 86400u * 1000000u;
    1512        2216 :         dta.has_date = 1;
    1513        2216 :         dta.date = bdt - BIGDATETIME_BIAS;
    1514        2216 :         return tds_convert_datetimeall(tds_ctx, SYBMSDATETIME2, &dta, desttype, cr);
    1515             : }
    1516             : 
    1517             : 
    1518             : static TDS_INT
    1519       49232 : tds_convert_real(const TDS_REAL* src, int desttype, CONV_RESULT * cr)
    1520             : {
    1521             :         TDS_REAL the_value;
    1522             : 
    1523             :         /* FIXME how big should be this buffer ?? */
    1524             :         char tmp_str[128];
    1525             :         TDS_INT mymoney4;
    1526             :         TDS_INT8 mymoney;
    1527             : 
    1528       49232 :         the_value = *src;
    1529             : 
    1530       49232 :         switch (desttype) {
    1531         200 :         case TDS_CONVERT_CHAR:
    1532             :         case CASE_ALL_CHAR:
    1533         200 :                 sprintf(tmp_str, "%.9g", the_value);
    1534         200 :                 return string_to_result(desttype, tmp_str, cr);
    1535             :                 break;
    1536        7192 :         case SYBINT1:
    1537             :         case SYBUINT1:
    1538        7192 :                 if (!IS_TINYINT(the_value))
    1539             :                         return TDS_CONVERT_OVERFLOW;
    1540         688 :                 cr->ti = (TDS_TINYINT) the_value;
    1541             :                 return sizeof(TDS_TINYINT);
    1542             :                 break;
    1543        3616 :         case SYBINT2:
    1544        3616 :                 if (!IS_SMALLINT(the_value))
    1545             :                         return TDS_CONVERT_OVERFLOW;
    1546        1096 :                 cr->si = (TDS_SMALLINT) the_value;
    1547             :                 return sizeof(TDS_SMALLINT);
    1548             :                 break;
    1549        3576 :         case SYBUINT2:
    1550        3576 :                 if (!IS_USMALLINT(the_value))
    1551             :                         return TDS_CONVERT_OVERFLOW;
    1552         720 :                 cr->usi = (TDS_USMALLINT) the_value;
    1553             :                 return sizeof(TDS_USMALLINT);
    1554             :                 break;
    1555        3616 :         case SYBINT4:
    1556        3616 :                 if (!FLOAT_IS_INT(the_value))
    1557             :                         return TDS_CONVERT_OVERFLOW;
    1558        2112 :                 cr->i = (TDS_INT) the_value;
    1559             :                 return sizeof(TDS_INT);
    1560             :                 break;
    1561        3576 :         case SYBUINT4:
    1562        3576 :                 if (!IS_UINT(the_value))
    1563             :                         return TDS_CONVERT_OVERFLOW;
    1564        1224 :                 cr->ui = (TDS_UINT) the_value;
    1565             :                 return sizeof(TDS_UINT);
    1566             :                 break;
    1567        3576 :         case SYBINT8:
    1568        3576 :                 if (!FLOAT_IS_INT8(the_value))
    1569             :                         return TDS_CONVERT_OVERFLOW;
    1570        3080 :                 cr->bi = (TDS_INT8) the_value;
    1571             :                 return sizeof(TDS_INT8);
    1572             :                 break;
    1573        3576 :         case SYBUINT8:
    1574        3576 :                 if (!FLOAT_IS_UINT8(the_value))
    1575             :                         return TDS_CONVERT_OVERFLOW;
    1576        1728 :                 cr->ubi = (TDS_UINT8) the_value;
    1577             :                 return sizeof(TDS_UINT8);
    1578             :                 break;
    1579          56 :         case SYBBIT:
    1580             :         case SYBBITN:
    1581          56 :                 cr->ti = the_value ? 1 : 0;
    1582             :                 return sizeof(TDS_TINYINT);
    1583             :                 break;
    1584             : 
    1585        3786 :         case SYBFLT8:
    1586        3786 :                 cr->f = the_value;
    1587             :                 return sizeof(TDS_FLOAT);
    1588             :                 break;
    1589             : 
    1590        3694 :         case SYBREAL:
    1591        3694 :                 cr->r = the_value;
    1592             :                 return sizeof(TDS_REAL);
    1593             :                 break;
    1594             : 
    1595        3536 :         case SYBMONEY:
    1596        3536 :                 if (the_value > (TDS_REAL) (TDS_INT8_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT8_MIN / 10000))
    1597             :                         return TDS_CONVERT_OVERFLOW;
    1598        2704 :                 mymoney = (TDS_INT8) (the_value * 10000);
    1599        2704 :                 cr->m.mny = mymoney;
    1600             :                 return sizeof(TDS_MONEY);
    1601             :                 break;
    1602             : 
    1603        3536 :         case SYBMONEY4:
    1604        3536 :                 if (the_value > (TDS_REAL) (TDS_INT_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT_MIN / 10000))
    1605             :                         return TDS_CONVERT_OVERFLOW;
    1606        1696 :                 mymoney4 = (TDS_INT) (the_value * 10000);
    1607        1696 :                 cr->m4.mny4 = mymoney4;
    1608             :                 return sizeof(TDS_MONEY4);
    1609             :                 break;
    1610        3584 :         case SYBNUMERIC:
    1611             :         case SYBDECIMAL:
    1612        3584 :                 sprintf(tmp_str, "%.*f", cr->n.scale, the_value);
    1613        3584 :                 return stringz_to_numeric(tmp_str, cr);
    1614             :                 break;
    1615             :                 /* not allowed */
    1616             :         case SYBUNIQUE:
    1617             :         case SYBDATETIME4:
    1618             :         case SYBDATETIME:
    1619             :         case SYBDATETIMN:
    1620             :         default:
    1621             :                 break;
    1622             :         }
    1623             :         return TDS_CONVERT_NOAVAIL;
    1624             : }
    1625             : 
    1626             : /*
    1627             :  * TODO: emit SYBECLPR errors: "Data conversion resulted in loss of precision".  
    1628             :  * There are many places where this would be correct to do, but the test is tedious 
    1629             :  * (convert e.g. 1.5 -> SYBINT and test if output == input) and we don't have a good, 
    1630             :  * API-independent alternative to tds_client_msg().  Postponed until then.  
    1631             :  */
    1632             : static TDS_INT
    1633       49322 : tds_convert_flt8(const TDS_FLOAT* src, int desttype, CONV_RESULT * cr)
    1634             : {
    1635             :         TDS_FLOAT the_value;
    1636             :         char tmp_str[25];
    1637             : 
    1638       49322 :         memcpy(&the_value, src, 8);
    1639       49322 :         switch (desttype) {
    1640         240 :         case TDS_CONVERT_CHAR:
    1641             :         case CASE_ALL_CHAR:
    1642         240 :                 sprintf(tmp_str, "%.17g", the_value);
    1643         240 :                 return string_to_result(desttype, tmp_str, cr);
    1644             :                 break;
    1645        7192 :         case SYBINT1:
    1646             :         case SYBUINT1:
    1647        7192 :                 if (!IS_TINYINT(the_value))
    1648             :                         return TDS_CONVERT_OVERFLOW;
    1649         688 :                 cr->ti = (TDS_TINYINT) the_value;
    1650         688 :                 return sizeof(TDS_TINYINT);
    1651             :                 break;
    1652        3616 :         case SYBINT2:
    1653        3616 :                 if (!IS_SMALLINT(the_value))
    1654             :                         return TDS_CONVERT_OVERFLOW;
    1655        1096 :                 cr->si = (TDS_SMALLINT) the_value;
    1656        1096 :                 return sizeof(TDS_SMALLINT);
    1657             :                 break;
    1658        3576 :         case SYBUINT2:
    1659        3576 :                 if (!IS_USMALLINT(the_value))
    1660             :                         return TDS_CONVERT_OVERFLOW;
    1661         720 :                 cr->usi = (TDS_USMALLINT) the_value;
    1662         720 :                 return sizeof(TDS_USMALLINT);
    1663             :                 break;
    1664        3616 :         case SYBINT4:
    1665        3616 :                 if (!FLOAT_IS_INT(the_value))
    1666             :                         return TDS_CONVERT_OVERFLOW;
    1667        2104 :                 cr->i = (TDS_INT) the_value;
    1668        2104 :                 return sizeof(TDS_INT);
    1669             :                 break;
    1670        3576 :         case SYBUINT4:
    1671        3576 :                 if (!IS_UINT(the_value))
    1672             :                         return TDS_CONVERT_OVERFLOW;
    1673        1224 :                 cr->ui = (TDS_UINT) the_value;
    1674        1224 :                 return sizeof(TDS_UINT);
    1675             :                 break;
    1676        3576 :         case SYBINT8:
    1677        3576 :                 if (!FLOAT_IS_INT8(the_value))
    1678             :                         return TDS_CONVERT_OVERFLOW;
    1679        3080 :                 cr->bi = (TDS_INT8) the_value;
    1680        3080 :                 return sizeof(TDS_INT8);
    1681             :                 break;
    1682        3576 :         case SYBUINT8:
    1683        3576 :                 if (!FLOAT_IS_UINT8(the_value))
    1684             :                         return TDS_CONVERT_OVERFLOW;
    1685        1728 :                 cr->ubi = (TDS_UINT8) the_value;
    1686        1728 :                 return sizeof(TDS_UINT8);
    1687             :                 break;
    1688          56 :         case SYBBIT:
    1689             :         case SYBBITN:
    1690          56 :                 cr->ti = the_value ? 1 : 0;
    1691          56 :                 return sizeof(TDS_TINYINT);
    1692             :                 break;
    1693             : 
    1694        3536 :         case SYBMONEY:
    1695        3536 :                 if (the_value > (TDS_FLOAT) (TDS_INT8_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT8_MIN / 10000))
    1696             :                         return TDS_CONVERT_OVERFLOW;
    1697        2704 :                 cr->m.mny = (TDS_INT8) (the_value * 10000);
    1698             : 
    1699        2704 :                 return sizeof(TDS_MONEY);
    1700             :                 break;
    1701        3536 :         case SYBMONEY4:
    1702        3536 :                 if (the_value > (TDS_FLOAT) (TDS_INT_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT_MIN / 10000))
    1703             :                         return TDS_CONVERT_OVERFLOW;
    1704        1696 :                 cr->m4.mny4 = (TDS_INT) (the_value * 10000);
    1705        1696 :                 return sizeof(TDS_MONEY4);
    1706             :                 break;
    1707        3786 :         case SYBREAL:
    1708             :                 /* TODO check overflow */
    1709        3786 :                 cr->r = (TDS_REAL)the_value;
    1710        3786 :                 return sizeof(TDS_REAL);
    1711             :                 break;
    1712        3736 :         case SYBFLT8:
    1713        3736 :                 cr->f = the_value;
    1714        3736 :                 return sizeof(TDS_FLOAT);
    1715             :                 break;
    1716        3592 :         case SYBNUMERIC:
    1717             :         case SYBDECIMAL:
    1718        3592 :                 sprintf(tmp_str, "%.*f", cr->n.scale, the_value);
    1719        3592 :                 return stringz_to_numeric(tmp_str, cr);
    1720             :                 break;
    1721             :                 /* not allowed */
    1722             :         case SYBUNIQUE:
    1723             :         case SYBDATETIME4:
    1724             :         case SYBDATETIME:
    1725             :         case SYBDATETIMN:
    1726             :         default:
    1727             :                 break;
    1728             :         }
    1729             :         return TDS_CONVERT_NOAVAIL;
    1730             : }
    1731             : 
    1732             : static TDS_INT
    1733        2498 : tds_convert_unique(const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
    1734             : {
    1735             :         /*
    1736             :          * raw data is equivalent to structure and always aligned, 
    1737             :          * so this cast is portable
    1738             :          */
    1739        2498 :         const TDS_UNIQUE *u = (const TDS_UNIQUE *) src;
    1740             :         char buf[37];
    1741             : 
    1742        2498 :         switch (desttype) {
    1743         158 :         case TDS_CONVERT_CHAR:
    1744             :         case CASE_ALL_CHAR:
    1745        1738 :                 sprintf(buf, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
    1746         474 :                         (int) u->Data1, (int) u->Data2, (int) u->Data3,
    1747        1264 :                         u->Data4[0], u->Data4[1], u->Data4[2], u->Data4[3], u->Data4[4], u->Data4[5], u->Data4[6], u->Data4[7]);
    1748         158 :                 return string_to_result(desttype, buf, cr);
    1749             :                 break;
    1750          52 :         case SYBUNIQUE:
    1751             :                 /*
    1752             :                  * Here we can copy raw to structure because we adjust
    1753             :                  * byte order in tds_swap_datatype
    1754             :                  */
    1755          52 :                 memcpy(&(cr->u), src, sizeof(TDS_UNIQUE));
    1756          52 :                 return sizeof(TDS_UNIQUE);
    1757             :                 break;
    1758             :                 /* do not warn for not convertible types */
    1759             :         case SYBBIT:
    1760             :         case SYBBITN:
    1761             :         case SYBINT1:
    1762             :         case SYBUINT1:
    1763             :         case SYBINT2:
    1764             :         case SYBUINT2:
    1765             :         case SYBINT4:
    1766             :         case SYBUINT4:
    1767             :         case SYBINT8:
    1768             :         case SYBUINT8:
    1769             :         case SYBMONEY4:
    1770             :         case SYBMONEY:
    1771             :         case SYBDATETIME4:
    1772             :         case SYBDATETIME:
    1773             :         case SYBDATETIMN:
    1774             :         case SYBREAL:
    1775             :         case SYBFLT8:
    1776             :         default:
    1777             :                 break;
    1778             :         }
    1779             :         return TDS_CONVERT_NOAVAIL;
    1780             : }
    1781             : 
    1782             : static TDS_INT
    1783       12874 : tds_convert_to_binary(int srctype, const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
    1784             : {
    1785             :         size_t len;
    1786             :         TDS_CHAR *ib;
    1787             : 
    1788       12874 :         switch (srctype) {
    1789         306 :         case CASE_ALL_BINARY:
    1790         306 :                 len = srclen;
    1791         306 :                 break;
    1792             :         case SYBBIT:
    1793             :         case SYBBITN:
    1794             :         case SYBINT1:
    1795             :         case SYBUINT1:
    1796             :                 len = 1;
    1797             :                 break;
    1798         104 :         case SYBINT2:
    1799             :         case SYBUINT2:
    1800         104 :                 len = 2;
    1801         104 :                 break;
    1802         136 :         case SYBINT4:
    1803             :         case SYBUINT4:
    1804         136 :                 len = 4;
    1805         136 :                 break;
    1806         120 :         case SYBINT8:
    1807             :         case SYBUINT8:
    1808         120 :                 len = sizeof(TDS_INT8);
    1809         120 :                 break;
    1810          48 :         case SYBMONEY4:
    1811          48 :                 len = sizeof(TDS_MONEY4);
    1812          48 :                 break;
    1813          48 :         case SYBMONEY:
    1814          48 :                 len = sizeof(TDS_MONEY);
    1815          48 :                 break;
    1816          96 :         case SYBNUMERIC:
    1817             :         case SYBDECIMAL:
    1818          96 :                 len = sizeof(TDS_NUMERIC);
    1819          96 :                 break;
    1820          48 :         case SYBREAL:
    1821          48 :                 len = sizeof(TDS_REAL);
    1822          48 :                 break;
    1823          48 :         case SYBFLT8:
    1824          48 :                 len = sizeof(TDS_FLOAT);
    1825          48 :                 break;
    1826          48 :         case SYBDATETIME:
    1827          48 :                 len = sizeof(TDS_DATETIME);
    1828          48 :                 break;
    1829          48 :         case SYBDATETIME4:
    1830          48 :                 len = sizeof(TDS_DATETIME4);
    1831          48 :                 break;
    1832          48 :         case SYBTIME:
    1833          48 :                 len = sizeof(TDS_TIME);
    1834          48 :                 break;
    1835          48 :         case SYBDATE:
    1836          48 :                 len = sizeof(TDS_DATE);
    1837          48 :                 break;
    1838         192 :         case SYBMSTIME:
    1839             :         case SYBMSDATE:
    1840             :         case SYBMSDATETIME2:
    1841             :         case SYBMSDATETIMEOFFSET:
    1842         192 :                 len = sizeof(TDS_DATETIMEALL);
    1843         192 :                 break;
    1844          48 :         case SYB5BIGTIME:
    1845          48 :                 len = sizeof(TDS_BIGTIME);
    1846          48 :                 break;
    1847          48 :         case SYB5BIGDATETIME:
    1848          48 :                 len = sizeof(TDS_BIGDATETIME);
    1849          48 :                 break;
    1850          48 :         case SYBUNIQUE:
    1851          48 :                 len = sizeof(TDS_UNIQUE);
    1852          48 :                 break;
    1853         728 :         case CASE_ALL_CHAR:
    1854             : 
    1855             :                 /* skip leading "0x" or "0X" */
    1856         728 :                 if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
    1857         184 :                         src += 2;
    1858         184 :                         srclen -= 2;
    1859             :                 }
    1860             : 
    1861             :                 /* ignore trailing blanks and nulls */
    1862             :                 /* FIXME is good to ignore null ?? */
    1863         772 :                 while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\0'))
    1864             :                         --srclen;
    1865             : 
    1866             :                 /* a binary string output will be half the length of */
    1867             :                 /* the string which represents it in hexadecimal     */
    1868             : 
    1869         728 :                 ib = cr->cb.ib;
    1870         728 :                 if (desttype != TDS_CONVERT_BINARY) {
    1871         564 :                         cr->ib = tds_new(TDS_CHAR, (srclen + 2u) / 2u);
    1872         564 :                         test_alloc(cr->ib);
    1873             :                         ib = cr->ib;
    1874             :                 }
    1875         728 :                 return tds_char2hex(ib, desttype == TDS_CONVERT_BINARY ? cr->cb.len : 0xffffffffu, src, srclen);
    1876             : 
    1877             :         default:
    1878             :                 return TDS_CONVERT_NOAVAIL;
    1879             :         }
    1880        1682 :         return binary_to_result(desttype, src, len, cr);
    1881             : }
    1882             : 
    1883             : /**
    1884             :  * tds_convert
    1885             :  * convert a type to another.
    1886             :  * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision 
    1887             :  * and scale of cr.
    1888             :  * Do not expect strings to be zero terminated. Databases support zero inside
    1889             :  * string. Using strlen may result on data loss or even a segmentation fault.
    1890             :  * Instead, use memcpy to copy destination using length returned.
    1891             :  * This function does not handle NULL, srclen should be >0.  Client libraries handle NULLs each in their own way. 
    1892             :  * @param tds_ctx  context (used in conversion to data and to return messages)
    1893             :  * @param srctype  type of source
    1894             :  * @param src      pointer to source data to convert
    1895             :  * @param srclen   length in bytes of source (not counting terminator or strings)
    1896             :  * @param desttype type of destination
    1897             :  * @param cr       structure to hold result
    1898             :  * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* constants are <0.
    1899             :  */
    1900             : TDS_INT
    1901     1917284 : tds_convert(const TDSCONTEXT *tds_ctx, int srctype, const void *src, TDS_UINT srclen, int desttype, CONV_RESULT *cr)
    1902             : {
    1903     1917284 :         TDS_INT length = 0;
    1904             : 
    1905     1917284 :         assert(srclen >= 0 && srclen <= 2147483647u);
    1906             : 
    1907     1917284 :         if (srctype == SYBVARIANT) {
    1908        2054 :                 const TDSVARIANT *v = (const TDSVARIANT*) src;
    1909        2054 :                 srctype = v->type;
    1910        2054 :                 src = v->data;
    1911        2054 :                 srclen = v->data_len;
    1912             :         }
    1913             : 
    1914     1917284 :         switch (desttype) {
    1915       12874 :         case CASE_ALL_BINARY:
    1916       12874 :                 return tds_convert_to_binary(srctype, src, srclen, desttype, cr);
    1917             :         }
    1918             : 
    1919     1904410 :         switch (srctype) {
    1920     1013408 :         case CASE_ALL_CHAR:
    1921     1013408 :                 length = tds_convert_char(src, srclen, desttype, cr);
    1922     1013408 :                 break;
    1923       26920 :         case SYBMONEY4:
    1924       26920 :                 length = tds_convert_money4(tds_ctx, (const TDS_MONEY4 *) src, desttype, cr);
    1925       26920 :                 break;
    1926       40826 :         case SYBMONEY:
    1927       40826 :                 length = tds_convert_money(tds_ctx, (const TDS_MONEY *) src, desttype, cr);
    1928       40826 :                 break;
    1929       56398 :         case SYBNUMERIC:
    1930             :         case SYBDECIMAL:
    1931       56398 :                 length = tds_convert_numeric((const TDS_NUMERIC *) src, desttype, cr);
    1932       56398 :                 break;
    1933        5260 :         case SYBBIT:
    1934             :         case SYBBITN:
    1935       10520 :                 length = tds_convert_bit(src, desttype, cr);
    1936        5260 :                 break;
    1937       16932 :         case SYBINT1:
    1938             :         case SYBUINT1:
    1939       33864 :                 length = tds_convert_int1((const TDS_TINYINT *) src, desttype, cr);
    1940       16932 :                 break;
    1941       20990 :         case SYBINT2:
    1942       41980 :                 length = tds_convert_int2((const TDS_SMALLINT *) src, desttype, cr);
    1943       20990 :                 break;
    1944       12578 :         case SYBUINT2:
    1945       25156 :                 length = tds_convert_uint2((const TDS_USMALLINT *) src, desttype, cr);
    1946       12578 :                 break;
    1947       38552 :         case SYBINT4:
    1948       77104 :                 length = tds_convert_int4((const TDS_INT *) src, desttype, cr);
    1949       38552 :                 break;
    1950       20422 :         case SYBUINT4:
    1951       40844 :                 length = tds_convert_uint4((const TDS_UINT *) src, desttype, cr);
    1952       20422 :                 break;
    1953       45998 :         case SYBINT8:
    1954       45998 :                 length = tds_convert_int8((const TDS_INT8 *) src, desttype, cr);
    1955       45998 :                 break;
    1956       26546 :         case SYBUINT8:
    1957       26546 :                 length = tds_convert_uint8((const TDS_UINT8 *) src, desttype, cr);
    1958       26546 :                 break;
    1959       49232 :         case SYBREAL:
    1960       49232 :                 length = tds_convert_real((const TDS_REAL *) src, desttype, cr);
    1961       49232 :                 break;
    1962       49322 :         case SYBFLT8:
    1963       49322 :                 length = tds_convert_flt8((const TDS_FLOAT *) src, desttype, cr);
    1964       49322 :                 break;
    1965        9892 :         case SYBMSTIME:
    1966             :         case SYBMSDATE:
    1967             :         case SYBMSDATETIME2:
    1968             :         case SYBMSDATETIMEOFFSET:
    1969        9892 :                 length = tds_convert_datetimeall(tds_ctx, srctype, (const TDS_DATETIMEALL *) src, desttype, cr);
    1970        9892 :                 break;
    1971        3556 :         case SYBDATETIME:
    1972        3556 :                 length = tds_convert_datetime(tds_ctx, (const TDS_DATETIME* ) src, desttype, 3, cr);
    1973        3556 :                 break;
    1974        2948 :         case SYBDATETIME4:
    1975        2948 :                 length = tds_convert_datetime4(tds_ctx, (const TDS_DATETIME4* ) src, desttype, cr);
    1976        2948 :                 break;
    1977        2560 :         case SYBTIME:
    1978        2560 :                 length = tds_convert_time(tds_ctx, (const TDS_TIME *) src, desttype, cr);
    1979        2560 :                 break;
    1980        2576 :         case SYBDATE:
    1981        2576 :                 length = tds_convert_date(tds_ctx, (const TDS_DATE *) src, desttype, cr);
    1982        2576 :                 break;
    1983        2192 :         case SYB5BIGTIME:
    1984        2192 :                 length = tds_convert_bigtime(tds_ctx, (const TDS_BIGTIME *) src, desttype, cr);
    1985        2192 :                 break;
    1986        2216 :         case SYB5BIGDATETIME:
    1987        2216 :                 length = tds_convert_bigdatetime(tds_ctx, (const TDS_BIGDATETIME *) src, desttype, cr);
    1988        2216 :                 break;
    1989       14676 :         case CASE_ALL_BINARY:
    1990       14676 :                 length = tds_convert_binary((const TDS_UCHAR *) src, srclen, desttype, cr);
    1991       14676 :                 break;
    1992        2498 :         case SYBUNIQUE:
    1993        2498 :                 length = tds_convert_unique(src, desttype, cr);
    1994        2498 :                 break;
    1995             :         case SYBNVARCHAR:
    1996             :         case SYBNTEXT:
    1997             :         case SYBMSTABLE:
    1998             :         default:
    1999             :                 return TDS_CONVERT_NOAVAIL;
    2000             :                 break;
    2001             :         }
    2002             : 
    2003             : /* fix MONEY case */
    2004             : #if !defined(WORDS_BIGENDIAN)
    2005     1466498 :         if (length > 0 && desttype == SYBMONEY) {
    2006       85968 :                 cr->m.mny = ((TDS_UINT8) cr->m.mny) >> 32 | (cr->m.mny << 32);
    2007             :         }
    2008             : #endif
    2009             :         return length;
    2010             : }
    2011             : 
    2012             : static int
    2013        2292 : string_to_datetime(const char *instr, TDS_UINT len, int desttype, CONV_RESULT * cr)
    2014             : {
    2015             :         enum states {
    2016             :                 GOING_IN_BLIND,
    2017             :                 PUT_NUMERIC_IN_CONTEXT,
    2018             :                 DOING_ALPHABETIC_DATE
    2019             :         };
    2020             : 
    2021             :         char *in;
    2022             :         char *tok;
    2023             :         char *lasts;
    2024             :         char last_token[32];
    2025        2292 :         int monthdone = 0;
    2026        2292 :         int yeardone = 0;
    2027        2292 :         int mdaydone = 0;
    2028             : 
    2029             :         struct tds_time t;
    2030             : 
    2031             :         unsigned int dt_time;
    2032             :         TDS_INT dt_days;
    2033             :         int i;
    2034             : 
    2035             :         enum states current_state;
    2036             : 
    2037        2292 :         memset(&t, '\0', sizeof(t));
    2038        2292 :         t.tm_mday = 1;
    2039             : 
    2040        2292 :         in = tds_strndup(instr, len);
    2041        2292 :         test_alloc(in);
    2042             : 
    2043        2292 :         tok = strtok_r(in, " ,", &lasts);
    2044             : 
    2045        2292 :         current_state = GOING_IN_BLIND;
    2046             : 
    2047        9176 :         while (tok != NULL) {
    2048             : 
    2049        4600 :                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: current_state = %d\n", current_state);
    2050        4600 :                 switch (current_state) {
    2051        3096 :                 case GOING_IN_BLIND:
    2052             :                         /* If we have no idea of current context, then if we have */
    2053             :                         /* encountered a purely alphabetic string, it MUST be an  */
    2054             :                         /* alphabetic month name or prefix...                     */
    2055             : 
    2056        3096 :                         if (is_alphabetic(tok)) {
    2057         744 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_alphabetic\n");
    2058         744 :                                 if (store_monthname(tok, &t) >= 0) {
    2059         736 :                                         monthdone++;
    2060         736 :                                         current_state = DOING_ALPHABETIC_DATE;
    2061             :                                 } else {
    2062             :                                         goto string_garbled;
    2063             :                                 }
    2064             :                         }
    2065             : 
    2066             :                         /* ...whereas if it is numeric, it could be a number of   */
    2067             :                         /* things...                                              */
    2068             : 
    2069        2352 :                         else if (is_numeric(tok)) {
    2070          32 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric\n");
    2071          32 :                                 switch (strlen(tok)) {
    2072             :                                         /* in this context a 4 character numeric can   */
    2073             :                                         /* ONLY be the year part of an alphabetic date */
    2074             : 
    2075           0 :                                 case 4:
    2076           0 :                                         store_year(atoi(tok), &t);
    2077           0 :                                         yeardone++;
    2078           0 :                                         current_state = DOING_ALPHABETIC_DATE;
    2079           0 :                                         break;
    2080             : 
    2081             :                                         /* whereas these could be the hour part of a   */
    2082             :                                         /* time specification ( 4 PM ) or the leading  */
    2083             :                                         /* day part of an alphabetic date ( 15 Jan )   */
    2084             : 
    2085          16 :                                 case 2:
    2086             :                                 case 1:
    2087          16 :                                         strcpy(last_token, tok);
    2088          16 :                                         current_state = PUT_NUMERIC_IN_CONTEXT;
    2089          16 :                                         break;
    2090             : 
    2091             :                                         /* this must be a [YY]YYMMDD date             */
    2092             : 
    2093          16 :                                 case 6:
    2094             :                                 case 8:
    2095          16 :                                         if (store_yymmdd_date(tok, &t))
    2096             :                                                 current_state = GOING_IN_BLIND;
    2097             :                                         else
    2098             :                                                 goto string_garbled;
    2099             :                                         break;
    2100             : 
    2101             :                                         /* anything else is nonsense...               */
    2102             : 
    2103             :                                 default:
    2104             :                                         goto string_garbled;
    2105             :                                         break;
    2106             :                                 }
    2107             :                         }
    2108             : 
    2109             :                         /* it could be [M]M/[D]D/[YY]YY format              */
    2110             : 
    2111        2320 :                         else if (is_numeric_dateformat(tok)) {
    2112         812 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric_dateformat\n");
    2113         812 :                                 store_numeric_date(tok, &t);
    2114         812 :                                 current_state = GOING_IN_BLIND;
    2115        1508 :                         } else if (is_dd_mon_yyyy(tok)) {
    2116           8 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_dd_mon_yyyy\n");
    2117           8 :                                 store_dd_mon_yyy_date(tok, &t);
    2118           8 :                                 current_state = GOING_IN_BLIND;
    2119        1500 :                         } else if (is_timeformat(tok)) {
    2120        1500 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_timeformat\n");
    2121        1500 :                                 store_time(tok, &t);
    2122        1500 :                                 current_state = GOING_IN_BLIND;
    2123             :                         } else {
    2124           0 :                                 tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: string_garbled\n");
    2125             :                                 goto string_garbled;
    2126             :                         }
    2127             : 
    2128             :                         break;  /* end of GOING_IN_BLIND */
    2129             : 
    2130        1488 :                 case DOING_ALPHABETIC_DATE:
    2131             : 
    2132        1488 :                         if (is_alphabetic(tok)) {
    2133           0 :                                 if (!monthdone && store_monthname(tok, &t) >= 0) {
    2134           0 :                                         monthdone++;
    2135           0 :                                         if (monthdone && yeardone && mdaydone)
    2136             :                                                 current_state = GOING_IN_BLIND;
    2137             :                                         else
    2138           0 :                                                 current_state = DOING_ALPHABETIC_DATE;
    2139             :                                 } else {
    2140             :                                         goto string_garbled;
    2141             :                                 }
    2142        1488 :                         } else if (is_numeric(tok)) {
    2143        1488 :                                 if (mdaydone && yeardone)
    2144             :                                         goto string_garbled;
    2145             :                                 else
    2146        1488 :                                         switch (strlen(tok)) {
    2147         752 :                                         case 4:
    2148        1504 :                                                 store_year(atoi(tok), &t);
    2149         752 :                                                 yeardone++;
    2150         752 :                                                 if (monthdone && yeardone && mdaydone)
    2151             :                                                         current_state = GOING_IN_BLIND;
    2152             :                                                 else
    2153           0 :                                                         current_state = DOING_ALPHABETIC_DATE;
    2154             :                                                 break;
    2155             : 
    2156         736 :                                         case 2:
    2157             :                                         case 1:
    2158         736 :                                                 if (!mdaydone) {
    2159        1472 :                                                         store_mday(tok, &t);
    2160             : 
    2161         736 :                                                         mdaydone++;
    2162         736 :                                                         if (monthdone && yeardone && mdaydone)
    2163             :                                                                 current_state = GOING_IN_BLIND;
    2164             :                                                         else
    2165         736 :                                                                 current_state = DOING_ALPHABETIC_DATE;
    2166             :                                                 } else {
    2167           0 :                                                         store_year(atoi(tok), &t);
    2168           0 :                                                         yeardone++;
    2169           0 :                                                         if (monthdone && yeardone && mdaydone)
    2170             :                                                                 current_state = GOING_IN_BLIND;
    2171             :                                                         else
    2172           0 :                                                                 current_state = DOING_ALPHABETIC_DATE;
    2173             :                                                 }
    2174             :                                                 break;
    2175             : 
    2176             :                                         default:
    2177             :                                                 goto string_garbled;
    2178             :                                         }
    2179             :                         } else {
    2180             :                                 goto string_garbled;
    2181             :                         }
    2182             : 
    2183             :                         break;  /* end of DOING_ALPHABETIC_DATE */
    2184             : 
    2185          16 :                 case PUT_NUMERIC_IN_CONTEXT:
    2186             : 
    2187          16 :                         if (is_alphabetic(tok)) {
    2188          16 :                                 if (store_monthname(tok, &t) >= 0) {
    2189          32 :                                         store_mday(last_token, &t);
    2190          16 :                                         mdaydone++;
    2191          16 :                                         monthdone++;
    2192          16 :                                         if (monthdone && yeardone && mdaydone)
    2193             :                                                 current_state = GOING_IN_BLIND;
    2194             :                                         else
    2195          16 :                                                 current_state = DOING_ALPHABETIC_DATE;
    2196           0 :                                 } else if (is_ampm(tok)) {
    2197           0 :                                         store_hour(last_token, tok, &t);
    2198           0 :                                         current_state = GOING_IN_BLIND;
    2199             :                                 } else {
    2200             :                                         goto string_garbled;
    2201             :                                 }
    2202           0 :                         } else if (is_numeric(tok)) {
    2203           0 :                                 switch (strlen(tok)) {
    2204             :                                 case 4:
    2205             :                                 case 2:
    2206           0 :                                         store_mday(last_token, &t);
    2207           0 :                                         mdaydone++;
    2208           0 :                                         store_year(atoi(tok), &t);
    2209           0 :                                         yeardone++;
    2210             : 
    2211           0 :                                         if (monthdone && yeardone && mdaydone)
    2212             :                                                 current_state = GOING_IN_BLIND;
    2213             :                                         else
    2214           0 :                                                 current_state = DOING_ALPHABETIC_DATE;
    2215             :                                         break;
    2216             : 
    2217             :                                 default:
    2218             :                                         goto string_garbled;
    2219             :                                 }
    2220             :                         } else {
    2221             :                                 goto string_garbled;
    2222             :                         }
    2223             : 
    2224             :                         break;  /* end of PUT_NUMERIC_IN_CONTEXT */
    2225             :                 }
    2226             : 
    2227        4592 :                 tok = strtok_r(NULL, " ,", &lasts);
    2228             :         }
    2229             : 
    2230        2284 :         i = (t.tm_mon - 13) / 12;
    2231        6852 :         dt_days = 1461 * (t.tm_year + 1900 + i) / 4 +
    2232        4568 :                 (367 * (t.tm_mon - 1 - 12 * i)) / 12 - (3 * ((t.tm_year + 2000 + i) / 100)) / 4 + t.tm_mday - 693932;
    2233             : 
    2234        2284 :         free(in);
    2235             : 
    2236        2284 :         if (desttype == SYBDATE) {
    2237         136 :                 cr->date = dt_days;
    2238         136 :                 return sizeof(TDS_DATE);
    2239             :         }
    2240        2148 :         dt_time = t.tm_hour * 60 + t.tm_min;
    2241             :         /* TODO check for overflow */
    2242        2148 :         if (desttype == SYBDATETIME4) {
    2243         512 :                 cr->dt4.days = dt_days;
    2244         512 :                 cr->dt4.minutes = dt_time;
    2245         512 :                 return sizeof(TDS_DATETIME4);
    2246             :         }
    2247        1636 :         dt_time = dt_time * 60 + t.tm_sec;
    2248        1636 :         if (desttype == SYBDATETIME) {
    2249         616 :                 cr->dt.dtdays = dt_days;
    2250         616 :                 cr->dt.dttime = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
    2251         616 :                 return sizeof(TDS_DATETIME);
    2252             :         }
    2253        1020 :         if (desttype == SYBTIME) {
    2254         136 :                 cr->time = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
    2255         136 :                 return sizeof(TDS_TIME);
    2256             :         }
    2257         884 :         if (desttype == SYB5BIGTIME) {
    2258          72 :                 cr->bigtime = dt_time * (TDS_UINT8) 1000000u + t.tm_ns / 1000u;
    2259          72 :                 return sizeof(TDS_BIGTIME);
    2260             :         }
    2261         812 :         if (desttype == SYB5BIGDATETIME) {
    2262         192 :                 cr->bigdatetime = (dt_days + BIGDATETIME_BIAS) * ((TDS_UINT8) 86400u * 1000000u)
    2263          96 :                                   + dt_time * (TDS_UINT8) 1000000u + t.tm_ns / 1000u;
    2264          96 :                 return sizeof(TDS_BIGDATETIME);
    2265             :         }
    2266             : 
    2267         716 :         cr->dta.has_offset = 0;
    2268         716 :         cr->dta.offset = 0;
    2269         716 :         cr->dta.has_date = 1;
    2270         716 :         cr->dta.date = dt_days;
    2271         716 :         cr->dta.has_time = 1;
    2272         716 :         cr->dta.time_prec = 7; /* TODO correct value */
    2273         716 :         cr->dta.time = ((TDS_UINT8) dt_time) * 10000000u + t.tm_ns / 100u;
    2274         716 :         return sizeof(TDS_DATETIMEALL);
    2275             : 
    2276           8 : string_garbled:
    2277           8 :         tdsdump_log(TDS_DBG_INFO1,
    2278             :                     "error_handler:  Attempt to convert data stopped by syntax error in source field \n");
    2279           8 :         free(in);
    2280           8 :         return TDS_CONVERT_SYNTAX;
    2281             : }
    2282             : 
    2283             : static int
    2284        7176 : stringz_to_numeric(const char *instr, CONV_RESULT * cr)
    2285             : {
    2286        7176 :         return string_to_numeric(instr, instr + strlen(instr), cr);
    2287             : }
    2288             : 
    2289             : static int
    2290       88976 : string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr)
    2291             : {
    2292             :         char mynumber[(MAXPRECISION + 7) / 8 * 8 + 8];
    2293             : 
    2294             :         /* num packaged 8 digit, see below for detail */
    2295             :         TDS_UINT packed_num[(MAXPRECISION + 7) / 8];
    2296             : 
    2297             :         char *ptr;
    2298             : 
    2299       88976 :         int i = 0;
    2300       88976 :         int j = 0;
    2301             :         int bytes;
    2302             : 
    2303             :         bool negative;
    2304             :         size_t digits, decimals;
    2305             : 
    2306             :         /* FIXME: application can pass invalid value for precision and scale ?? */
    2307       88976 :         if (cr->n.precision > MAXPRECISION)
    2308             :                 return TDS_CONVERT_FAIL;
    2309             : 
    2310       88976 :         if (cr->n.precision == 0)
    2311           0 :                 cr->n.precision = MAXPRECISION;      /* assume max precision */
    2312             : 
    2313       88976 :         if (cr->n.scale > cr->n.precision)
    2314             :                 return TDS_CONVERT_FAIL;
    2315             : 
    2316       88976 :         instr = parse_numeric(instr, pend, &negative, &digits, &decimals);
    2317       88976 :         if (!instr)
    2318             :                 return TDS_CONVERT_SYNTAX;
    2319             : 
    2320       88968 :         cr->n.array[0] = negative ? 1 : 0;
    2321             : 
    2322             :         /* translate a number like 000ddddd.ffff to 00000000dddddffff00 */
    2323             : 
    2324             :         /* 
    2325             :          * Having disposed of any sign and leading blanks, 
    2326             :          * vet the digit string, counting places before and after 
    2327             :          * the decimal point.  Dispense with trailing blanks, if any.  
    2328             :          */
    2329             : 
    2330       88968 :         ptr = mynumber;
    2331      800712 :         for (i = 0; i < 8; ++i)
    2332      711744 :                 *ptr++ = '0';
    2333             : 
    2334             :         /* too many digits, error */
    2335       88968 :         if (cr->n.precision - cr->n.scale < digits)
    2336             :                 return TDS_CONVERT_OVERFLOW;
    2337             : 
    2338             :         /* copy digits before the dot */
    2339       88736 :         memcpy(ptr, instr, digits);
    2340       88736 :         ptr += digits;
    2341       88736 :         instr += digits + 1;
    2342             : 
    2343             :         /* copy digits after the dot */
    2344       88736 :         if (decimals > cr->n.scale)
    2345         104 :                 decimals = cr->n.scale;
    2346       88736 :         memcpy(ptr, instr, decimals);
    2347             : 
    2348             :         /* fill up decimal digits */
    2349       88736 :         memset(ptr + decimals, '0', cr->n.scale - decimals);
    2350       88736 :         ptr += cr->n.scale;
    2351             : 
    2352             :         /*
    2353             :          * Packaged number explanation: 
    2354             :          * We package 8 decimal digits in one number.  
    2355             :          * Because 10^8 = 5^8 * 2^8 = 5^8 * 256, dividing 10^8 by 256 leaves no remainder.
    2356             :          * We can thus split it into bytes in an optimized way.
    2357             :          */
    2358             : 
    2359             :         /* transform to packaged one */
    2360       88736 :         j = -1;
    2361       88736 :         ptr -= 8;
    2362             :         do {
    2363      139336 :                 TDS_UINT n = *ptr++;
    2364             : 
    2365     1114688 :                 for (i = 1; i < 8; ++i)
    2366      975352 :                         n = n * 10u + *ptr++;
    2367             :                 /* fix packet number and store */
    2368      139336 :                 packed_num[++j] = n - ((TDS_UINT) '0' * 11111111lu);
    2369      139336 :                 ptr -= 16;
    2370      139336 :         } while (ptr > mynumber);
    2371             : 
    2372       88736 :         memset(cr->n.array + 1, 0, sizeof(cr->n.array) - 1);
    2373       88736 :         bytes = tds_numeric_bytes_per_prec[cr->n.precision];
    2374      177472 :         while (j > 0 && !packed_num[j])
    2375           0 :                 --j;
    2376             : 
    2377      328032 :         for (;;) {
    2378      416768 :                 bool is_zero = true;
    2379      416768 :                 TDS_UINT carry = 0;
    2380      416768 :                 i = j;
    2381      416768 :                 if (!packed_num[j])
    2382      139336 :                         --j;
    2383             :                 do {
    2384      602216 :                         TDS_UINT tmp = packed_num[i];
    2385      602216 :                         if (tmp)
    2386      462368 :                                 is_zero = false;
    2387             : 
    2388             :                         /* divide for 256 for find another byte */
    2389             :                         /*
    2390             :                          * carry * (25u*25u*25u*25u) = carry * 10^8 / 256u
    2391             :                          * using unsigned number is just an optimization
    2392             :                          * compiler can translate division to a shift and remainder 
    2393             :                          * to a binary AND
    2394             :                          */
    2395      602216 :                         packed_num[i] = carry * (25u * 25u * 25u * 25u) + tmp / 256u;
    2396      602216 :                         carry = tmp % 256u;
    2397      602216 :                 } while(--i >= 0);
    2398      416768 :                 if (is_zero)
    2399             :                         break;
    2400             :                 /*
    2401             :                  * source number is limited to 38 decimal digit
    2402             :                  * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
    2403             :                  */
    2404      328032 :                 cr->n.array[--bytes] = carry;
    2405             :         }
    2406             :         return sizeof(TDS_NUMERIC);
    2407             : }
    2408             : 
    2409             : static bool
    2410        2320 : is_numeric_dateformat(const char *t)
    2411             : {
    2412             :         const char *instr;
    2413        2320 :         int slashes = 0;
    2414        2320 :         int hyphens = 0;
    2415        2320 :         int periods = 0;
    2416        2320 :         int digits = 0;
    2417             : 
    2418       12976 :         for (instr = t; *instr; instr++) {
    2419       12164 :                 if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.')
    2420             :                         return false;
    2421             : 
    2422       10656 :                 if (*instr == '/')
    2423           0 :                         slashes++;
    2424       10656 :                 else if (*instr == '-')
    2425        1624 :                         hyphens++;
    2426        9032 :                 else if (*instr == '.')
    2427           0 :                         periods++;
    2428             :                 else
    2429        9032 :                         digits++;
    2430             : 
    2431             :         }
    2432         812 :         if (hyphens + slashes + periods != 2)
    2433             :                 return false;
    2434         812 :         if (hyphens == 1 || slashes == 1 || periods == 1)
    2435             :                 return false;
    2436             : 
    2437         812 :         if (digits < 4 || digits > 8)
    2438             :                 return false;
    2439             : 
    2440         812 :         return true;
    2441             : 
    2442             : }
    2443             : 
    2444             : /* This function will check if an alphanumeric string */
    2445             : /* holds a date in any of the following formats :     */
    2446             : /*    DD-MON-YYYY */
    2447             : /*    DD-MON-YY   */
    2448             : /*    DDMONYY     */
    2449             : /*    DDMONYYYY   */
    2450             : static bool
    2451        1508 : is_dd_mon_yyyy(char *t)
    2452             : {
    2453             :         char *instr;
    2454             :         char month[4];
    2455             : 
    2456        1508 :         instr = t;
    2457             : 
    2458        1508 :         if (!isdigit((unsigned char) *instr))
    2459             :                 return false;
    2460             : 
    2461        1508 :         instr++;
    2462             : 
    2463        1508 :         if (!isdigit((unsigned char) *instr))
    2464             :                 return false;
    2465             : 
    2466        1028 :         instr++;
    2467             : 
    2468        1028 :         if (*instr == '-') {
    2469           0 :                 instr++;
    2470             : 
    2471           0 :                 strlcpy(month, instr, 4);
    2472             : 
    2473           0 :                 if (!is_monthname(month))
    2474             :                         return false;
    2475             : 
    2476           0 :                 instr += 3;
    2477             : 
    2478           0 :                 if (*instr != '-')
    2479             :                         return false;
    2480             : 
    2481           0 :                 instr++;
    2482           0 :                 if (!isdigit((unsigned char) *instr))
    2483             :                         return false;
    2484             : 
    2485           0 :                 instr++;
    2486           0 :                 if (!isdigit((unsigned char) *instr))
    2487             :                         return false;
    2488             : 
    2489           0 :                 instr++;
    2490             : 
    2491           0 :                 if (*instr) {
    2492           0 :                         if (!isdigit((unsigned char) *instr))
    2493             :                                 return false;
    2494             : 
    2495           0 :                         instr++;
    2496           0 :                         if (!isdigit((unsigned char) *instr))
    2497             :                                 return false;
    2498             :                 }
    2499             : 
    2500             :         } else {
    2501             : 
    2502        1028 :                 strlcpy(month, instr, 4);
    2503             : 
    2504        1028 :                 if (!is_monthname(month))
    2505             :                         return false;
    2506             : 
    2507           8 :                 instr += 3;
    2508             : 
    2509           8 :                 if (!isdigit((unsigned char) *instr))
    2510             :                         return false;
    2511             : 
    2512           8 :                 instr++;
    2513           8 :                 if (!isdigit((unsigned char) *instr))
    2514             :                         return false;
    2515             : 
    2516           8 :                 instr++;
    2517           8 :                 if (*instr) {
    2518           8 :                         if (!isdigit((unsigned char) *instr))
    2519             :                                 return false;
    2520             : 
    2521           8 :                         instr++;
    2522           8 :                         if (!isdigit((unsigned char) *instr))
    2523             :                                 return false;
    2524             :                 }
    2525             :         }
    2526             : 
    2527             :         return true;
    2528             : 
    2529             : }
    2530             : 
    2531             : static bool
    2532         480 : is_ampm(const char *datestr)
    2533             : {
    2534         480 :         if (strcasecmp(datestr, "am") == 0)
    2535             :                 return true;
    2536             : 
    2537         480 :         if (strcasecmp(datestr, "pm") == 0)
    2538             :                 return true;
    2539             : 
    2540           0 :         return false;
    2541             : }
    2542             : 
    2543             : static bool
    2544        4600 : is_alphabetic(const char *datestr)
    2545             : {
    2546             :         const char *s;
    2547             : 
    2548        6944 :         for (s = datestr; *s; s++) {
    2549        6184 :                 if (!isalpha((unsigned char) *s))
    2550             :                         return false;
    2551             :         }
    2552             :         return true;
    2553             : }
    2554             : 
    2555             : static bool
    2556        3840 : is_numeric(const char *datestr)
    2557             : {
    2558             :         const char *s;
    2559             : 
    2560       14160 :         for (s = datestr; *s; s++) {
    2561       12640 :                 if (!isdigit((unsigned char) *s))
    2562             :                         return false;
    2563             :         }
    2564             :         return true;
    2565             : }
    2566             : 
    2567             : static bool
    2568        1500 : is_timeformat(const char *datestr)
    2569             : {
    2570             :         const char *s;
    2571             : 
    2572       15076 :         for (s = datestr; *s; s++) {
    2573       14056 :                 if (!isdigit((unsigned char) *s) && *s != ':' && *s != '.')
    2574             :                         break;
    2575             :         }
    2576        1500 :         if (*s)
    2577         480 :                 return is_ampm(s);
    2578             : 
    2579             :         return true;
    2580             : }
    2581             : 
    2582             : static int
    2583             : store_year(int year, struct tds_time *t)
    2584             : {
    2585             : 
    2586        1588 :         if (year < 0)
    2587             :                 return 0;
    2588             : 
    2589        1588 :         if (year < 100) {
    2590           8 :                 if (year > 49)
    2591           0 :                         t->tm_year = year;
    2592             :                 else
    2593           8 :                         t->tm_year = 100 + year;
    2594             :                 return (1);
    2595             :         }
    2596             : 
    2597        1580 :         if (year < 1753)
    2598             :                 return (0);
    2599             : 
    2600        1580 :         if (year <= 9999) {
    2601        1580 :                 t->tm_year = year - 1900;
    2602             :                 return (1);
    2603             :         }
    2604             : 
    2605             :         return (0);
    2606             : 
    2607             : }
    2608             : 
    2609             : static int
    2610             : store_mday(const char *datestr, struct tds_time *t)
    2611             : {
    2612         752 :         int mday = atoi(datestr);
    2613             : 
    2614         752 :         if (mday > 0 && mday < 32) {
    2615         752 :                 t->tm_mday = mday;
    2616             :                 return 1;
    2617             :         }
    2618             :         return 0;
    2619             : }
    2620             : 
    2621             : static int
    2622         812 : store_numeric_date(const char *datestr, struct tds_time *t)
    2623             : {
    2624         812 :         int TDS_MONTH = 0;
    2625         812 :         int TDS_DAY = 0;
    2626         812 :         int TDS_YEAR = 0;
    2627             : 
    2628             :         int state;
    2629         812 :         char last_char = 0;
    2630             :         const char *s;
    2631         812 :         int month = 0, year = 0, mday = 0;
    2632             : 
    2633             :         /* Its YYYY-MM-DD format */
    2634             : 
    2635         812 :         if (strlen(datestr) == 10 && *(datestr + 4) == '-' && *(datestr + 7) == '-') {
    2636             : 
    2637             :                 TDS_YEAR = 0;
    2638             :                 TDS_MONTH = 1;
    2639             :                 TDS_DAY = 2;
    2640             :                 state = TDS_YEAR;
    2641             : 
    2642             :         }
    2643             :         /* else we assume MDY */
    2644             :         else {
    2645           0 :                 TDS_MONTH = 0;
    2646           0 :                 TDS_DAY = 1;
    2647           0 :                 TDS_YEAR = 2;
    2648           0 :                 state = TDS_MONTH;
    2649             :         }
    2650        8932 :         for (s = datestr; *s; s++) {
    2651        8120 :                 if (!isdigit((unsigned char) *s) && isdigit((unsigned char) last_char)) {
    2652        1624 :                         state++;
    2653             :                 } else {
    2654        6496 :                         if (state == TDS_MONTH)
    2655        1624 :                                 month = (month * 10) + (*s - '0');
    2656        6496 :                         if (state == TDS_DAY)
    2657        1624 :                                 mday = (mday * 10) + (*s - '0');
    2658        6496 :                         if (state == TDS_YEAR)
    2659        3248 :                                 year = (year * 10) + (*s - '0');
    2660             :                 }
    2661        8120 :                 last_char = *s;
    2662             :         }
    2663             : 
    2664         812 :         if (month > 0 && month < 13)
    2665         812 :                 t->tm_mon = month - 1;
    2666             :         else
    2667             :                 return 0;
    2668         812 :         if (mday > 0 && mday < 32)
    2669         812 :                 t->tm_mday = mday;
    2670             :         else
    2671             :                 return 0;
    2672             : 
    2673         812 :         return store_year(year, t);
    2674             : 
    2675             : }
    2676             : 
    2677             : static int
    2678           8 : store_dd_mon_yyy_date(char *datestr, struct tds_time *t)
    2679             : {
    2680             : 
    2681             :         char dd[3];
    2682             :         int mday;
    2683             :         char mon[4];
    2684             :         int year;
    2685             : 
    2686           8 :         tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: %s\n", datestr);
    2687           8 :         strlcpy(dd, datestr, 3);
    2688           8 :         mday = atoi(dd);
    2689             : 
    2690           8 :         if (mday > 0 && mday < 32)
    2691           8 :                 t->tm_mday = mday;
    2692             :         else
    2693             :                 return 0;
    2694             : 
    2695           8 :         if (datestr[2] == '-') {
    2696           0 :                 strlcpy(mon, &datestr[3], 4);
    2697             : 
    2698           0 :                 if (store_monthname(mon, t) < 0) {
    2699           0 :                         tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
    2700             :                         return 0;
    2701             :                 }
    2702             : 
    2703           0 :                 year = atoi(&datestr[7]);
    2704           0 :                 tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
    2705             : 
    2706           0 :                 return store_year(year, t);
    2707             :         } else {
    2708           8 :                 strlcpy(mon, &datestr[2], 4);
    2709             : 
    2710           8 :                 if (store_monthname(mon, t) < 0) {
    2711           0 :                         tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
    2712             :                         return 0;
    2713             :                 }
    2714             : 
    2715          16 :                 year = atoi(&datestr[5]);
    2716           8 :                 tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
    2717             : 
    2718           8 :                 return store_year(year, t);
    2719             :         }
    2720             : 
    2721             : }
    2722             : 
    2723             : /**
    2724             :  * Test if a string is a month name and store correct month number
    2725             :  * @return month number (0-11) or -1 if not match
    2726             :  * @param datestr string to check
    2727             :  * @param t       where to store month (if NULL no store is done)
    2728             :  */
    2729             : static int
    2730        1796 : store_monthname(const char *datestr, struct tds_time *t)
    2731             : {
    2732             :         int ret;
    2733             : 
    2734        1796 :         tdsdump_log(TDS_DBG_INFO1, "store_monthname: %ld %s\n", (long) strlen(datestr), datestr);
    2735        1796 :         if (strlen(datestr) == 3) {
    2736        1772 :                 if (strcasecmp(datestr, "jan") == 0)
    2737             :                         ret = 0;
    2738        1652 :                 else if (strcasecmp(datestr, "feb") == 0)
    2739             :                         ret = 1;
    2740        1652 :                 else if (strcasecmp(datestr, "mar") == 0)
    2741             :                         ret = 2;
    2742        1652 :                 else if (strcasecmp(datestr, "apr") == 0)
    2743             :                         ret = 3;
    2744        1508 :                 else if (strcasecmp(datestr, "may") == 0)
    2745             :                         ret = 4;
    2746        1500 :                 else if (strcasecmp(datestr, "jun") == 0)
    2747             :                         ret = 5;
    2748        1500 :                 else if (strcasecmp(datestr, "jul") == 0)
    2749             :                         ret = 6;
    2750        1500 :                 else if (strcasecmp(datestr, "aug") == 0)
    2751             :                         ret = 7;
    2752        1500 :                 else if (strcasecmp(datestr, "sep") == 0)
    2753             :                         ret = 8;
    2754        1500 :                 else if (strcasecmp(datestr, "oct") == 0)
    2755             :                         ret = 9;
    2756        1500 :                 else if (strcasecmp(datestr, "nov") == 0)
    2757             :                         ret = 10;
    2758        1500 :                 else if (strcasecmp(datestr, "dec") == 0)
    2759             :                         ret = 11;
    2760             :                 else
    2761             :                         return -1;
    2762             :         } else {
    2763          24 :                 if (strcasecmp(datestr, "january") == 0)
    2764             :                         ret = 0;
    2765          16 :                 else if (strcasecmp(datestr, "february") == 0)
    2766             :                         ret = 1;
    2767          16 :                 else if (strcasecmp(datestr, "march") == 0)
    2768             :                         ret = 2;
    2769           8 :                 else if (strcasecmp(datestr, "april") == 0)
    2770             :                         ret = 3;
    2771           8 :                 else if (strcasecmp(datestr, "june") == 0)
    2772             :                         ret = 5;
    2773           8 :                 else if (strcasecmp(datestr, "july") == 0)
    2774             :                         ret = 6;
    2775           8 :                 else if (strcasecmp(datestr, "august") == 0)
    2776             :                         ret = 7;
    2777           8 :                 else if (strcasecmp(datestr, "september") == 0)
    2778             :                         ret = 8;
    2779           8 :                 else if (strcasecmp(datestr, "october") == 0)
    2780             :                         ret = 9;
    2781           8 :                 else if (strcasecmp(datestr, "november") == 0)
    2782             :                         ret = 10;
    2783           8 :                 else if (strcasecmp(datestr, "december") == 0)
    2784             :                         ret = 11;
    2785             :                 else
    2786             :                         return -1;
    2787             :         }
    2788         768 :         if (t)
    2789         760 :                 t->tm_mon = ret;
    2790             :         return ret;
    2791             : }
    2792             : 
    2793             : static int
    2794          16 : store_yymmdd_date(const char *datestr, struct tds_time *t)
    2795             : {
    2796          16 :         int month = 0, year = 0, mday = 0;
    2797             : 
    2798             :         int wholedate;
    2799             : 
    2800          16 :         wholedate = atoi(datestr);
    2801             : 
    2802          16 :         year = wholedate / 10000;
    2803          16 :         month = (wholedate - (year * 10000)) / 100;
    2804          16 :         mday = (wholedate - (year * 10000) - (month * 100));
    2805             : 
    2806          16 :         if (month > 0 && month < 13)
    2807          16 :                 t->tm_mon = month - 1;
    2808             :         else
    2809             :                 return 0;
    2810          16 :         if (mday > 0 && mday < 32)
    2811          16 :                 t->tm_mday = mday;
    2812             :         else
    2813             :                 return 0;
    2814             : 
    2815          16 :         return (store_year(year, t));
    2816             : 
    2817             : }
    2818             : 
    2819             : static int
    2820        1500 : store_time(const char *datestr, struct tds_time *t)
    2821             : {
    2822             :         enum
    2823             :         { TDS_HOURS,
    2824             :                 TDS_MINUTES,
    2825             :                 TDS_SECONDS,
    2826             :                 TDS_FRACTIONS
    2827             :         };
    2828             : 
    2829        1500 :         int state = TDS_HOURS;
    2830        1500 :         char last_sep = '\0';
    2831             :         const char *s;
    2832        1500 :         unsigned int hours = 0, minutes = 0, seconds = 0, nanosecs = 0;
    2833        1500 :         int ret = 1;
    2834        1500 :         unsigned ns_div = 1;
    2835             : 
    2836       15076 :         for (s = datestr; *s && strchr("apmAPM", (int) *s) == NULL; s++) {
    2837       13576 :                 if (*s == ':' || *s == '.') {
    2838        3124 :                         last_sep = *s;
    2839        3124 :                         state++;
    2840             :                 } else {
    2841       10452 :                         if (*s < '0' || *s > '9')
    2842           0 :                                 ret = 0;
    2843       10452 :                         switch (state) {
    2844        2520 :                         case TDS_HOURS:
    2845        2520 :                                 hours = (hours * 10u) + (*s - '0');
    2846        2520 :                                 break;
    2847        3000 :                         case TDS_MINUTES:
    2848        3000 :                                 minutes = (minutes * 10u) + (*s - '0');
    2849        3000 :                                 break;
    2850        2040 :                         case TDS_SECONDS:
    2851        2040 :                                 seconds = (seconds * 10u) + (*s - '0');
    2852        2040 :                                 break;
    2853        2892 :                         case TDS_FRACTIONS:
    2854        2892 :                                 if (ns_div < 1000000000u) {
    2855        2892 :                                         nanosecs = (nanosecs * 10u) + (*s - '0');
    2856        2892 :                                         ns_div *= 10;
    2857             :                                 }
    2858             :                                 break;
    2859             :                         }
    2860             :                 }
    2861             :         }
    2862        1500 :         if (*s) {
    2863         480 :                 if (strcasecmp(s, "am") == 0) {
    2864           0 :                         if (hours == 12)
    2865           0 :                                 hours = 0;
    2866             : 
    2867           0 :                         t->tm_hour = hours;
    2868             :                 }
    2869         480 :                 if (strcasecmp(s, "pm") == 0) {
    2870         480 :                         if (hours == 0)
    2871           0 :                                 ret = 0;
    2872         480 :                         if (hours > 0u && hours < 12u)
    2873         480 :                                 t->tm_hour = hours + 12;
    2874             :                         else
    2875           0 :                                 t->tm_hour = hours;
    2876             :                 }
    2877             :         } else {
    2878        1020 :                 if (hours < 24u)
    2879        1020 :                         t->tm_hour = hours;
    2880             :                 else
    2881             :                         ret = 0;
    2882             :         }
    2883        1500 :         if (minutes < 60u)
    2884        1500 :                 t->tm_min = minutes;
    2885             :         else
    2886             :                 ret = 0;
    2887        1500 :         if (seconds < 60u)
    2888        1500 :                 t->tm_sec = seconds;
    2889             :         else
    2890             :                 ret = 0;
    2891        1500 :         tdsdump_log(TDS_DBG_FUNC, "store_time() nanosecs = %d\n", nanosecs);
    2892        1500 :         if (nanosecs) {
    2893         436 :                 if (nanosecs < ns_div && last_sep == '.')
    2894         436 :                         t->tm_ns = nanosecs * (1000000000u / ns_div);
    2895           0 :                 else if (nanosecs < 1000u)
    2896           0 :                         t->tm_ns = nanosecs * 1000000u;
    2897             :                 else
    2898             :                         ret = 0;
    2899             :         }
    2900             : 
    2901        1500 :         return (ret);
    2902             : }
    2903             : 
    2904             : static int
    2905           0 : store_hour(const char *hour, const char *ampm, struct tds_time *t)
    2906             : {
    2907           0 :         int ret = 1;
    2908             :         int hours;
    2909             : 
    2910           0 :         hours = atoi(hour);
    2911             : 
    2912           0 :         if (hours >= 0 && hours < 24) {
    2913           0 :                 if (strcasecmp(ampm, "am") == 0) {
    2914           0 :                         if (hours == 12)
    2915           0 :                                 hours = 0;
    2916             : 
    2917           0 :                         t->tm_hour = hours;
    2918             :                 }
    2919           0 :                 if (strcasecmp(ampm, "pm") == 0) {
    2920           0 :                         if (hours == 0)
    2921           0 :                                 ret = 0;
    2922           0 :                         if (hours > 0 && hours < 12)
    2923           0 :                                 t->tm_hour = hours + 12;
    2924             :                         else
    2925           0 :                                 t->tm_hour = hours;
    2926             :                 }
    2927             :         }
    2928           0 :         return ret;
    2929             : }
    2930             : 
    2931             : /**
    2932             :  * Get same type but nullable
    2933             :  * @param srctype type requires
    2934             :  * @return nullable type
    2935             :  */
    2936             : TDS_SERVER_TYPE
    2937          68 : tds_get_null_type(TDS_SERVER_TYPE srctype)
    2938             : {
    2939             : 
    2940          68 :         switch (srctype) {
    2941             :         case SYBCHAR:
    2942             :                 return SYBVARCHAR;
    2943             :                 break;
    2944          28 :         case SYBINT1:
    2945             :         case SYBUINT1:
    2946             :         case SYBINT2:
    2947             :         case SYBINT4:
    2948             :         case SYBINT8:
    2949             :         /* TODO sure ?? */
    2950             :         case SYBUINT2:
    2951             :         case SYBUINT4:
    2952             :         case SYBUINT8:
    2953          28 :                 return SYBINTN;
    2954             :                 break;
    2955           0 :         case SYBREAL:
    2956             :         case SYBFLT8:
    2957           0 :                 return SYBFLTN;
    2958             :                 break;
    2959           0 :         case SYBDATETIME:
    2960             :         case SYBDATETIME4:
    2961           0 :                 return SYBDATETIMN;
    2962             :                 break;
    2963           2 :         case SYBBIT:
    2964           2 :                 return SYBBITN;
    2965             :                 break;
    2966           0 :         case SYBMONEY:
    2967             :         case SYBMONEY4:
    2968           0 :                 return SYBMONEYN;
    2969             :                 break;
    2970           0 :         case SYBTIME:
    2971           0 :                 return SYBTIMEN;
    2972             :                 break;
    2973           0 :         case SYBDATE:
    2974           0 :                 return SYBDATEN;
    2975             :                 break;
    2976             :         default:
    2977             :                 break;
    2978             :         }
    2979          22 :         return srctype;
    2980             : }
    2981             : 
    2982             : static void
    2983             : two_digit(char *out, int num)
    2984             : {
    2985         458 :         if (num < 1)
    2986             :                 num = 1;
    2987         458 :         if (num > 31)
    2988             :                 num = 31;
    2989         482 :         out[0] = num < 10 ? ' ' : num/10 + '0';
    2990         482 :         out[1] = num%10 + '0';
    2991             : }
    2992             : 
    2993             : /**
    2994             :  * format a date string according to an "extended" strftime(3) formatting definition.
    2995             :  * @param buf     output buffer
    2996             :  * @param maxsize size of buffer in bytes (space include terminator)
    2997             :  * @param format  format string passed to strftime(3), except that %z represents fraction of seconds.
    2998             :  * @param dr      date to convert
    2999             :  * @param prec    second fraction precision (0-7).
    3000             :  * @return length of string returned, 0 for error
    3001             :  */
    3002             : size_t
    3003        1628 : tds_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC * dr, int prec)
    3004             : {
    3005             :         struct tm tm;
    3006             : 
    3007             :         size_t length;
    3008             :         char *our_format;
    3009             :         char *pz;
    3010        1628 :         bool z_found = false;
    3011             :         
    3012        1628 :         assert(buf);
    3013        1628 :         assert(format);
    3014        1628 :         assert(dr);
    3015        1628 :         assert(0 <= dr->decimicrosecond && dr->decimicrosecond < 10000000);
    3016        1628 :         if (prec < 0 || prec > 7)
    3017           0 :                 prec = 3;
    3018             : 
    3019        1628 :         tm.tm_sec = dr->second;
    3020        1628 :         tm.tm_min = dr->minute;
    3021        1628 :         tm.tm_hour = dr->hour;
    3022        1628 :         tm.tm_mday = dr->day;
    3023        1628 :         tm.tm_mon = dr->month;
    3024        1628 :         tm.tm_year = dr->year - 1900;
    3025        1628 :         tm.tm_wday = dr->weekday;
    3026        1628 :         tm.tm_yday = dr->dayofyear;
    3027        1628 :         tm.tm_isdst = 0;
    3028             : #ifdef HAVE_STRUCT_TM_TM_ZONE
    3029        1628 :         tm.tm_zone = NULL;
    3030             : #elif defined(HAVE_STRUCT_TM___TM_ZONE)
    3031             :         tm.__tm_zone = NULL;
    3032             : #endif
    3033             : 
    3034             :         /* more characters are required because we replace %z with up to 7 digits */
    3035        1628 :         our_format = tds_new(char, strlen(format) + 1 + 5 + 1);
    3036        1628 :         if (!our_format)
    3037             :                 return 0;
    3038             : 
    3039        1628 :         strcpy(our_format, format);
    3040             : 
    3041       19870 :         for (pz = our_format; *pz; ) {
    3042       16614 :                 if (*pz++ != '%')
    3043        7206 :                         continue;
    3044             : 
    3045        9408 :                 switch (*pz) {
    3046           8 :                 case 0:
    3047           8 :                         *pz++ = '%';
    3048           8 :                         *pz = 0;
    3049           8 :                         continue;
    3050             :                 case '%':
    3051             :                         /* escaped, do not treat as format on next iteration */
    3052             :                         break;
    3053         458 :                 case 'e':
    3054             :                         /* not portable: day of month, single digit preceded by a blank */
    3055             :                         /* not supported on old Windows versions */
    3056         458 :                         two_digit(pz-1, dr->day);
    3057             :                         break;
    3058          24 :                 case 'l':
    3059             :                         /* not portable: 12-hour, single digit preceded by a blank */
    3060             :                         /* not supported on: SCO Unix, AIX, HP-UX, Windows
    3061             :                          * supported on: *BSD, MacOS, Linux, Solaris */
    3062          24 :                         two_digit(pz-1, (dr->hour + 11u) % 12u + 1);
    3063             :                         break;
    3064        1130 :                 case 'z':
    3065             :                         /*
    3066             :                          * Look for "%z" in the format string.  If found, replace it with dr->milliseconds.
    3067             :                          * For example, if milliseconds is 124, the format string
    3068             :                          * "%b %d %Y %H:%M:%S.%z" would become
    3069             :                          * "%b %d %Y %H:%M:%S.124".
    3070             :                          */
    3071        1130 :                         if (z_found)
    3072             :                                 break;
    3073        1130 :                         z_found = true;
    3074             : 
    3075        1130 :                         --pz;
    3076        2144 :                         if (prec || pz <= our_format || pz[-1] != '.') {
    3077             :                                 char buf[12];
    3078        1014 :                                 sprintf(buf, "%07d", dr->decimicrosecond);
    3079        1014 :                                 memcpy(pz, buf, prec);
    3080        1014 :                                 strcpy(pz + prec, format + (pz - our_format) + 2);
    3081        1014 :                                 pz += prec;
    3082             :                         } else {
    3083         116 :                                 strcpy(pz - 1, format + (pz - our_format) + 2);
    3084         116 :                                 pz--;
    3085             :                         }
    3086        1130 :                         continue;
    3087             :                 }
    3088        8270 :                 ++pz;
    3089             :         }
    3090             : 
    3091        1628 :         length = strftime(buf, maxsize, our_format, &tm);
    3092             : 
    3093        1628 :         free(our_format);
    3094             : 
    3095        1628 :         return length;
    3096             : }
    3097             : 
    3098             : #if 0
    3099             : static TDS_UINT
    3100             : utf16len(const utf16_t * s)
    3101             : {
    3102             :         const utf16_t *p = s;
    3103             : 
    3104             :         while (*p++)
    3105             :                 continue;
    3106             :         return p - s;
    3107             : }
    3108             : #endif
    3109             : 
    3110             : #include "tds_willconvert.h"
    3111             : 
    3112             : /**
    3113             :  * Test if a conversion is possible
    3114             :  * @param srctype  source type
    3115             :  * @param desttype destination type
    3116             :  * @return 0 if not convertible
    3117             :  */
    3118             : unsigned char
    3119     1290584 : tds_willconvert(int srctype, int desttype)
    3120             : {
    3121             :         TDS_TINYINT cat_from, cat_to;
    3122             :         TDS_UINT yn;
    3123             : 
    3124     1290584 :         tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d)\n", srctype, desttype);
    3125             : 
    3126             :         /* they must be from 0 to 255 */
    3127     1290584 :         if (((srctype|desttype) & ~0xff) != 0)
    3128             :                 return 0;
    3129             : 
    3130     1290584 :         cat_from = type2category[srctype];
    3131     1290584 :         cat_to   = type2category[desttype];
    3132     1290584 :         yn = category_conversion[cat_from];
    3133             : 
    3134     1290584 :         yn = (yn >> cat_to) & 1;
    3135             : 
    3136     1290584 :         tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d) returns %s\n",
    3137             :                     srctype, desttype, yn? "yes":"no");
    3138     1290584 :         return yn;
    3139             : }
    3140             : 
    3141             : #if 0
    3142             : select day(d) as day, datepart(dw, d) as weekday, datepart(week, d) as week, d as 'date' from #t order by d
    3143             : day         weekday     week        date                                                   
    3144             : ----------- ----------- ----------- ----------
    3145             :           1           5           1 2009-01-01 Thursday
    3146             :           2           6           1 2009-01-02 Friday
    3147             :           3           7           1 2009-01-03 Saturday
    3148             :           4           1           2 2009-01-04 Sunday
    3149             :           5           2           2 2009-01-05
    3150             :           6           3           2 2009-01-06
    3151             :           7           4           2 2009-01-07
    3152             :           8           5           2 2009-01-08
    3153             :           9           6           2 2009-01-09
    3154             :          10           7           2 2009-01-10
    3155             :          11           1           3 2009-01-11
    3156             :          12           2           3 2009-01-12
    3157             :          13           3           3 2009-01-13
    3158             :          14           4           3 2009-01-14
    3159             :          15           5           3 2009-01-15
    3160             :          16           6           3 2009-01-16
    3161             :          17           7           3 2009-01-17
    3162             :          18           1           4 2009-01-18
    3163             :          19           2           4 2009-01-19
    3164             :          20           3           4 2009-01-20
    3165             :          21           4           4 2009-01-21
    3166             :          22           5           4 2009-01-22
    3167             :          23           6           4 2009-01-23
    3168             :          24           7           4 2009-01-24
    3169             :          25           1           5 2009-01-25
    3170             :          26           2           5 2009-01-26
    3171             :          27           3           5 2009-01-27
    3172             :          28           4           5 2009-01-28
    3173             :          29           5           5 2009-01-29
    3174             :          30           6           5 2009-01-30
    3175             :          31           7           5 2009-01-31
    3176             : #endif
    3177             : /**
    3178             :  * Convert from db date format to a structured date format
    3179             :  * @param datetype source date type. SYBDATETIME or SYBDATETIME4
    3180             :  * @param di       source date
    3181             :  * @param dr       destination date
    3182             :  * @return TDS_FAIL or TDS_SUCCESS
    3183             :  */
    3184             : TDSRET
    3185        3810 : tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
    3186             : {
    3187             :         int dt_days;
    3188             :         unsigned int dt_time;
    3189             : 
    3190        3810 :         int years, months, days, ydays, wday, hours, mins, secs, dms, tzone = 0;
    3191             :         int l, n, i, j;
    3192             : 
    3193        3810 :         memset(dr, 0, sizeof(*dr));
    3194             : 
    3195        3810 :         if (datetype == SYBMSDATE || datetype == SYBMSTIME 
    3196        3810 :             || datetype == SYBMSDATETIME2 || datetype == SYBMSDATETIMEOFFSET) {
    3197        2850 :                 const TDS_DATETIMEALL *dta = (const TDS_DATETIMEALL *) di;
    3198        2850 :                 dt_days = (datetype == SYBMSTIME) ? 0 : dta->date;
    3199        2850 :                 if (datetype == SYBMSDATE) {
    3200             :                         dms = 0;
    3201             :                         secs = 0;
    3202             :                         dt_time = 0;
    3203             :                 } else {
    3204        2668 :                         dms = dta->time % 10000000u;
    3205        2668 :                         dt_time = (unsigned int) (dta->time / 10000000u);
    3206        2668 :                         secs = dt_time % 60;
    3207        2668 :                         dt_time = dt_time / 60;
    3208             :                 }
    3209        2850 :                 if (datetype == SYBMSDATETIMEOFFSET) {
    3210          96 :                         --dt_days;
    3211          96 :                         dt_time = dt_time + 1440 + dta->offset;
    3212          96 :                         dt_days += dt_time / 1440;
    3213          96 :                         dt_time %= 1440;
    3214          96 :                         tzone = dta->offset;
    3215             :                 }
    3216         960 :         } else if (datetype == SYBDATETIME) {
    3217         650 :                 const TDS_DATETIME *dt = (const TDS_DATETIME *) di;
    3218         650 :                 dt_time = dt->dttime;
    3219         650 :                 dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
    3220         650 :                 dt_time = dt_time / 300;
    3221         650 :                 secs = dt_time % 60;
    3222         650 :                 dt_time = dt_time / 60;
    3223         650 :                 dt_days = dt->dtdays;
    3224         310 :         } else if (datetype == SYBDATETIME4) {
    3225         112 :                 const TDS_DATETIME4 *dt4 = (const TDS_DATETIME4 *) di;
    3226         112 :                 secs = 0;
    3227         112 :                 dms = 0;
    3228         112 :                 dt_days = dt4->days;
    3229         112 :                 dt_time = dt4->minutes;
    3230         198 :         } else if (datetype == SYBDATE) {
    3231          74 :                 dt_days = *((const TDS_DATE *) di);
    3232          74 :                 dms = 0;
    3233          74 :                 secs = 0;
    3234          74 :                 dt_time = 0;
    3235         124 :         } else if (datetype == SYBTIME) {
    3236          76 :                 dt_time = *((const TDS_TIME *) di);
    3237          76 :                 dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
    3238          76 :                 dt_time = dt_time / 300;
    3239          76 :                 secs = dt_time % 60;
    3240          76 :                 dt_time = dt_time / 60;
    3241          76 :                 dt_days = 0;
    3242          48 :         } else if (datetype == SYB5BIGTIME) {
    3243          24 :                 TDS_UINT8 bigtime = *((const TDS_BIGTIME *) di);
    3244          24 :                 dt_days = 0;
    3245          24 :                 dms = bigtime % 1000000u * 10u;
    3246          24 :                 dt_time = (bigtime / 1000000u) % 86400u;
    3247          24 :                 secs = dt_time % 60;
    3248          24 :                 dt_time = dt_time / 60u;
    3249          24 :         } else if (datetype == SYB5BIGDATETIME) {
    3250          24 :                 TDS_UINT8 bigdatetime = *((const TDS_BIGDATETIME*) di);
    3251          24 :                 dms = bigdatetime % 1000000u * 10u;
    3252          24 :                 bigdatetime /= 1000000u;
    3253          24 :                 secs = bigdatetime % 60u;
    3254          24 :                 bigdatetime /= 60u;
    3255          24 :                 dt_time = bigdatetime % (24u*60u);
    3256          24 :                 dt_days = bigdatetime / (24u*60u) - BIGDATETIME_BIAS;
    3257             :         } else {
    3258             :                 return TDS_FAIL;
    3259             :         }
    3260             : 
    3261             :         /*
    3262             :          * -53690 is minimun  (1753-1-1) (Gregorian calendar start in 1732) 
    3263             :          * 2958463 is maximun (9999-12-31)
    3264             :          */
    3265        3810 :         l = dt_days + (146038 + 146097*4);
    3266        3810 :         wday = (l + 4) % 7;
    3267        3810 :         n = (4 * l) / 146097;   /* n century */
    3268        3810 :         l = l - (146097 * n + 3) / 4;   /* days from xx00-02-28 (y-m-d) */
    3269        3810 :         i = (4000 * (l + 1)) / 1461001; /* years from xx00-02-28 */
    3270        3810 :         l = l - (1461 * i) / 4; /* year days from xx00-02-28 */
    3271        3810 :         ydays = l >= 306 ? l - 305 : l + 60;
    3272        3810 :         l += 31;
    3273        3810 :         j = (80 * l) / 2447;
    3274        3810 :         days = l - (2447 * j) / 80;
    3275        3810 :         l = j / 11;
    3276        3810 :         months = j + 1 - 12 * l;
    3277        3810 :         years = 100 * (n - 1) + i + l;
    3278        3810 :         if (l == 0 && (years & 3) == 0 && (years % 100 != 0 || years % 400 == 0))
    3279         496 :                 ++ydays;
    3280             : 
    3281        3810 :         hours = dt_time / 60;
    3282        3810 :         mins = dt_time % 60;
    3283             : 
    3284        3810 :         dr->year = years;
    3285        3810 :         dr->month = months;
    3286        3810 :         dr->quarter = months / 3;
    3287        3810 :         dr->day = days;
    3288        3810 :         dr->dayofyear = ydays;
    3289        3810 :         dr->weekday = wday;
    3290        3810 :         dr->hour = hours;
    3291        3810 :         dr->minute = mins;
    3292        3810 :         dr->second = secs;
    3293        3810 :         dr->decimicrosecond = dms;
    3294        3810 :         dr->timezone = tzone;
    3295        3810 :         return TDS_SUCCESS;
    3296             : }
    3297             : 
    3298             : /**
    3299             :  * \brief convert a number in string to TDS_INT
    3300             :  *
    3301             :  * \return TDS_CONVERT_* or failure code on error
    3302             :  * \remarks Sybase's char->int conversion tolerates embedded blanks, 
    3303             :  * such that "convert( int, ' - 13 ' )" works.  
    3304             :  * If we find blanks, we copy the string to a temporary buffer, 
    3305             :  * skipping the blanks.  
    3306             :  * We return the results of atoi() with a clean string.  
    3307             :  * 
    3308             :  * n.b. it is possible to embed all sorts of non-printable characters, but we
    3309             :  * only check for spaces.  at this time, no one on the project has tested anything else.  
    3310             :  */
    3311             : static TDS_INT
    3312      387528 : string_to_int(const char *buf, const char *pend, TDS_INT * res)
    3313             : {
    3314             :         bool negative;
    3315             :         unsigned int num;       /* we use unsigned here for best overflow check */
    3316             :         size_t digits, decimals;
    3317             : 
    3318      387528 :         buf = parse_numeric(buf, pend, &negative, &digits, &decimals);
    3319      387528 :         if (!buf)
    3320             :                 return TDS_CONVERT_SYNTAX;
    3321             : 
    3322             :         num = 0;
    3323     2424896 :         for (; digits; --digits, ++buf) {
    3324             :                 /* add a digit to number and check for overflow */
    3325             :                 /* NOTE I didn't forget a digit, I check overflow before multiply to prevent overflow */
    3326     2566776 :                 if (num > 214748364u)
    3327             :                         return TDS_CONVERT_OVERFLOW;
    3328     2424896 :                 num = num * 10u + (*buf - '0');
    3329             :         }
    3330             : 
    3331             :         /* check for overflow and convert unsigned to signed */
    3332      245208 :         if (negative) {
    3333      110754 :                 if (num > 2147483648u)
    3334             :                         return TDS_CONVERT_OVERFLOW;
    3335      109186 :                 *res = 0 - num;
    3336             :         } else {
    3337      134454 :                 if (num >= 2147483648u)
    3338             :                         return TDS_CONVERT_OVERFLOW;
    3339      131966 :                 *res = num;
    3340             :         }
    3341             : 
    3342             :         return sizeof(TDS_INT);
    3343             : }
    3344             : 
    3345             : /**
    3346             :  * \brief convert a number in string to TDS_INT8
    3347             :  *
    3348             :  * \return TDS_CONVERT_* or failure code on error
    3349             :  */
    3350             : static TDS_INT  /* copied from string_ti_int and modified */
    3351      363008 : parse_int8(const char *buf, const char *pend, TDS_UINT8 * res, bool * p_negative)
    3352             : {
    3353             :         TDS_UINT8 num;
    3354             :         size_t digits, decimals;
    3355             : 
    3356      363008 :         buf = parse_numeric(buf, pend, p_negative, &digits, &decimals);
    3357      363008 :         if (!buf)
    3358             :                 return TDS_CONVERT_SYNTAX;
    3359             : 
    3360             :         num = 0;
    3361     3326664 :         for (; digits; --digits, ++buf) {
    3362             :                 /* add a digit to number and check for overflow */
    3363     3335720 :                 TDS_UINT8 prev = num;
    3364     3335720 :                 if (num > (((TDS_UINT8) 1u) << 63) / 5u)
    3365             :                         return TDS_CONVERT_OVERFLOW;
    3366     3330104 :                 num = num * 10u + (*buf - '0');
    3367     3330104 :                 if (num < prev)
    3368             :                         return TDS_CONVERT_OVERFLOW;
    3369             :         }
    3370             : 
    3371      353656 :         *res = num;
    3372      353656 :         return sizeof(TDS_INT8);
    3373             : }
    3374             : 
    3375             : /**
    3376             :  * \brief convert a number in string to TDS_INT8
    3377             :  *
    3378             :  * \return TDS_CONVERT_* or failure code on error
    3379             :  */
    3380             : static TDS_INT  /* copied from string_ti_int and modified */
    3381      285608 : string_to_int8(const char *buf, const char *pend, TDS_INT8 * res)
    3382             : {
    3383             :         TDS_UINT8 num;
    3384             :         TDS_INT parse_res;
    3385             :         bool negative;
    3386             : 
    3387      285608 :         parse_res = parse_int8(buf, pend, &num, &negative);
    3388      285608 :         if (parse_res < 0)
    3389             :                 return parse_res;
    3390             : 
    3391             :         /* check for overflow and convert unsigned to signed */
    3392      279376 :         if (negative) {
    3393      127856 :                 if (num > (((TDS_UINT8) 1) << 63))
    3394             :                         return TDS_CONVERT_OVERFLOW;
    3395      119336 :                 *res = 0 - num;
    3396             :         } else {
    3397      151520 :                 if (num >= (((TDS_UINT8) 1) << 63))
    3398             :                         return TDS_CONVERT_OVERFLOW;
    3399      141856 :                 *res = num;
    3400             :         }
    3401             :         return sizeof(TDS_INT8);
    3402             : }
    3403             : 
    3404             : /**
    3405             :  * \brief convert a number in string to TDS_UINT8
    3406             :  *
    3407             :  * \return TDS_CONVERT_* or failure code on error
    3408             :  */
    3409             : static TDS_INT  /* copied from string_to_int8 and modified */
    3410       77400 : string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res)
    3411             : {
    3412             :         TDS_UINT8 num;
    3413             :         TDS_INT parse_res;
    3414             :         bool negative;
    3415             : 
    3416       77400 :         parse_res = parse_int8(buf, pend, &num, &negative);
    3417       77400 :         if (parse_res < 0)
    3418             :                 return parse_res;
    3419             : 
    3420             :         /* check for overflow */
    3421       74280 :         if (negative && num)
    3422             :                 return TDS_CONVERT_OVERFLOW;
    3423             : 
    3424       40120 :         *res = num;
    3425       40120 :         return sizeof(TDS_UINT8);
    3426             : }
    3427             : 
    3428             : /**
    3429             :  * Parse a string for numbers.
    3430             :  *
    3431             :  * Syntax can be something like " *[+-] *[0-9]*\.[0-9]* *".
    3432             :  *
    3433             :  * The function ignore all spaces. It strips leading zeroes which could
    3434             :  * possibly lead to overflow.
    3435             :  * The function returns a pointer to the integer part followed by *p_digits
    3436             :  * digits followed by a dot followed by *p_decimals digits (dot and
    3437             :  * fractional digits are optional, in this case *p_decimals is 0).
    3438             :  *
    3439             :  * @param buf         start of string
    3440             :  * @param pend        pointer to string end
    3441             :  * @param p_negative  store if number is negative
    3442             :  * @param p_digits    store number of integer digits
    3443             :  * @param p_decimals  store number of fractional digits
    3444             :  * @return pointer to first not zero digit. If NULL this indicate a syntax
    3445             :  *         error.
    3446             :  */
    3447             : static const char *
    3448      994784 : parse_numeric(const char *buf, const char *pend, bool *p_negative, size_t *p_digits, size_t *p_decimals)
    3449             : {
    3450             :         enum { blank = ' ' };
    3451             : #define SKIP_IF(cond) while (p != pend && (cond)) ++p;
    3452             :         const char *p, *start;
    3453      994784 :         bool negative = false;
    3454             : 
    3455      994784 :         *p_decimals = 0;
    3456      994784 :         p = buf;
    3457             : 
    3458             :         /* ignore leading spaces */
    3459      994784 :         SKIP_IF(*p == blank);
    3460      994784 :         if (p == pend) {
    3461         400 :                 *p_negative = false;
    3462         400 :                 *p_digits = 0;
    3463         400 :                 return p;
    3464             :         }
    3465             : 
    3466             :         /* check for sign */
    3467      994384 :         switch (*p) {
    3468      455490 :         case '-':
    3469      455490 :                 negative = true;
    3470             :                 /* fall thru */
    3471      455626 :         case '+':
    3472             :                 /* skip spaces between sign and number */
    3473      455626 :                 ++p;
    3474      455626 :                 SKIP_IF(*p == blank);
    3475             :                 break;
    3476             :         }
    3477      994384 :         *p_negative = negative;
    3478             : 
    3479             :         /* a digit must be present */
    3480      994384 :         if (p == pend)
    3481             :                 return NULL;
    3482             : 
    3483             :         /*
    3484             :          * skip leading zeroes
    3485             :          * Not skipping them cause numbers like "000000000000" to
    3486             :          * appear like overflow
    3487             :          */
    3488        7840 :         SKIP_IF(*p == '0');
    3489             : 
    3490             :         start = p;
    3491     8673376 :         SKIP_IF(TDS_ISDIGIT(*p));
    3492      994256 :         *p_digits = p - start;
    3493             : 
    3494             :         /* parse decimal part */
    3495      994256 :         if (p != pend && *p == '.') {
    3496        2976 :                 const char *decimals_start = ++p;
    3497        2976 :                 SKIP_IF(TDS_ISDIGIT(*p));
    3498        2976 :                 *p_decimals = p - decimals_start;
    3499             :         }
    3500             : 
    3501             :         /* check for trailing spaces */
    3502         466 :         SKIP_IF(*p == blank);
    3503      994256 :         if (p != pend)
    3504             :                 return NULL;
    3505             : 
    3506      993616 :         return start;
    3507             : }
    3508             : 
    3509             : static TDS_INT
    3510      143672 : string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
    3511             : {
    3512             :         char tmpstr[128];
    3513             :         char *end;
    3514             :         double res;
    3515             : 
    3516             :         /* ignore leading spaces */
    3517      287344 :         while (srclen > 0 && src[0] == ' ')
    3518           0 :                 ++src, --srclen;
    3519             : 
    3520             :         /* ignore trailing blanks and nulls */
    3521      143672 :         while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\0'))
    3522             :                 --srclen;
    3523             : 
    3524      143672 :         if (srclen >= sizeof(tmpstr))
    3525             :                 return TDS_CONVERT_OVERFLOW;
    3526             : 
    3527      143672 :         memcpy(tmpstr, src, srclen);
    3528      143672 :         tmpstr[srclen] = 0;
    3529             : 
    3530      143672 :         errno = 0;
    3531      143672 :         res = strtod(tmpstr, &end);
    3532      143672 :         if (errno == ERANGE)
    3533             :                 return TDS_CONVERT_OVERFLOW;
    3534      143672 :         if (end != tmpstr + srclen)
    3535             :                 return TDS_CONVERT_SYNTAX;
    3536             : 
    3537      143672 :         if (desttype == SYBREAL) {
    3538             :                 /* FIXME check overflows */
    3539       71832 :                 cr->r = (TDS_REAL)res;
    3540       71832 :                 return sizeof(TDS_REAL);
    3541             :         }
    3542       71840 :         cr->f = res;
    3543       71840 :         return sizeof(TDS_FLOAT);
    3544             : }
    3545             : 
    3546             : /** @} */

Generated by: LCOV version 1.13