LCOV - code coverage report
Current view: top level - src/tds - convert.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 1539 1641 93.8 %
Date: 2026-11-07 23:58:45 Functions: 53 55 96.4 %

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

Generated by: LCOV version 1.13