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

Generated by: LCOV version 1.13