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

Generated by: LCOV version 1.13