File: tds.h

package info (click to toggle)
freetds 0.82-4
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 10,716 kB
  • ctags: 8,697
  • sloc: ansic: 74,312; sh: 8,868; makefile: 815; perl: 556; php: 22
file content (1609 lines) | stat: -rw-r--r-- 52,996 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef _tds_h_
#define _tds_h_

/* $Id: tds.h,v 1.284 2007/12/27 13:45:22 freddy77 Exp $ */

#include <stdarg.h>
#include <stdio.h>
#include <time.h>

/* forward declaration */
typedef struct tdsiconvinfo TDSICONV;
typedef struct tds_socket TDSSOCKET;

#include "tdsver.h"
#include "tds_sysdep_public.h"
#ifdef _FREETDS_LIBRARY_SOURCE
#include "tds_sysdep_private.h"
#endif /* _FREETDS_LIBRARY_SOURCE */

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

/**
 * A structure to hold all the compile-time settings.
 * This structure is returned by tds_get_compiletime_settings
 */

typedef struct _tds_compiletime_settings
{
	const char *freetds_version;	/* release version of FreeTDS */
	const char *sysconfdir;		/* location of freetds.conf */
	const char *last_update;	/* latest software_version date among the modules */
	int msdblib;		/* for MS style dblib */
	int sybase_compat;	/* enable increased Open Client binary compatibility */
	int threadsafe;		/* compile for thread safety default=no */
	int libiconv;		/* search for libiconv in DIR/include and DIR/lib */
	const char *tdsver;	/* TDS protocol version (4.2/4.6/5.0/7.0/8.0) 5.0 */
	int iodbc;		/* build odbc driver against iODBC in DIR */
	int unixodbc;		/* build odbc driver against unixODBC in DIR */

} TDS_COMPILETIME_SETTINGS;

struct DSTR_STRUCT {
	char *dstr_s;
	size_t dstr_size;
};
typedef struct DSTR_STRUCT DSTR;

/**
 * @file tds.h
 * Main include file for libtds
 */

/**
 * \defgroup libtds LibTDS API
 * Callable functions in \c libtds.
 * 
 * The \c libtds library is for use internal to \em FreeTDS.  It is not
 * intended for use by applications.  Although any use is \em permitted, you're
 * encouraged to use one of the established public APIs instead, because their
 * interfaces are stable and documented by the vendors.  
 */

/* 
 * All references to data that touch the wire should use the following typedefs.  
 *
 * If you have problems on 64-bit machines and the code is 
 * using a native datatype, please change it to use
 * these. (In the TDS layer only, the API layers have their
 * own typedefs which equate to these).
 */
typedef char TDS_CHAR;					/*  8-bit char     */
typedef unsigned char TDS_UCHAR;			/*  8-bit uchar    */
typedef unsigned char TDS_TINYINT;			/*  8-bit unsigned */
typedef tds_sysdep_int16_type TDS_SMALLINT;		/* 16-bit int      */
typedef unsigned tds_sysdep_int16_type TDS_USMALLINT;	/* 16-bit unsigned */
typedef tds_sysdep_int32_type TDS_INT;			/* 32-bit int      */
typedef unsigned tds_sysdep_int32_type TDS_UINT;	/* 32-bit unsigned */
typedef tds_sysdep_real32_type TDS_REAL;		/* 32-bit real     */
typedef tds_sysdep_real64_type TDS_FLOAT;		/* 64-bit real     */
typedef tds_sysdep_int64_type TDS_INT8;			/* 64-bit integer  */
typedef unsigned tds_sysdep_int64_type TDS_UINT8;	/* 64-bit unsigned */
typedef tds_sysdep_intptr_type TDS_INTPTR;

typedef struct tdsnumeric
{
	unsigned char precision;
	unsigned char scale;
	unsigned char array[33];
} TDS_NUMERIC;

typedef struct tdsoldmoney
{
	TDS_INT mnyhigh;
	TDS_UINT mnylow;
} TDS_OLD_MONEY;

typedef union tdsmoney
{
	TDS_OLD_MONEY tdsoldmoney;
	TDS_INT8 mny;
} TDS_MONEY;

typedef struct tdsmoney4
{
	TDS_INT mny4;
} TDS_MONEY4;

typedef struct tdsdatetime
{
	TDS_INT dtdays;
	TDS_INT dttime;
} TDS_DATETIME;

typedef struct tdsdatetime4
{
	TDS_USMALLINT days;
	TDS_USMALLINT minutes;
} TDS_DATETIME4;

typedef struct tdsvarbinary
{
	TDS_SMALLINT len;
	TDS_CHAR array[256];
} TDS_VARBINARY;
typedef struct tdsvarchar
{
	TDS_INT len;
	TDS_CHAR array[256];
} TDS_VARCHAR;

typedef struct tdsunique
{
	TDS_UINT Data1;
	TDS_USMALLINT Data2;
	TDS_USMALLINT Data3;
	TDS_UCHAR Data4[8];
} TDS_UNIQUE;

/** information on data, used by tds_datecrack */
typedef struct tdsdaterec
{
	TDS_INT year;	       /**< year */
	TDS_INT month;	       /**< month number (0-11) */
	TDS_INT day;	       /**< day of month (1-31) */
	TDS_INT dayofyear;     /**< day of year  (1-366) */
	TDS_INT weekday;       /**< day of week  (0-6, 0 = sunday) */
	TDS_INT hour;	       /**< 0-23 */
	TDS_INT minute;	       /**< 0-59 */
	TDS_INT second;	       /**< 0-59 */
	TDS_INT millisecond;   /**< 0-999 */
	TDS_INT tzone;
} TDSDATEREC;

/**
 * The following little table is indexed by precision and will
 * tell us the number of bytes required to store the specified
 * precision.
 */
extern const int tds_numeric_bytes_per_prec[];

#define TDS_SUCCEED          1
#define TDS_FAIL             0
#define TDS_NO_MORE_RESULTS  2
#define TDS_CANCELLED        3

#define TDS_INT_CONTINUE 1
#define TDS_INT_CANCEL 2
#define TDS_INT_TIMEOUT 3


#define TDS_NO_COUNT         -1

#define TDS_ROW_RESULT        4040
#define TDS_PARAM_RESULT      4042
#define TDS_STATUS_RESULT     4043
#define TDS_MSG_RESULT        4044
#define TDS_COMPUTE_RESULT    4045
#define TDS_CMD_DONE          4046
#define TDS_CMD_SUCCEED       4047
#define TDS_CMD_FAIL          4048
#define TDS_ROWFMT_RESULT     4049
#define TDS_COMPUTEFMT_RESULT 4050
#define TDS_DESCRIBE_RESULT   4051
#define TDS_DONE_RESULT       4052
#define TDS_DONEPROC_RESULT   4053
#define TDS_DONEINPROC_RESULT 4054
#define TDS_OTHERS_RESULT     4055

enum tds_token_results
{
	TDS_TOKEN_RES_OTHERS,
	TDS_TOKEN_RES_ROWFMT,
	TDS_TOKEN_RES_COMPUTEFMT,
	TDS_TOKEN_RES_PARAMFMT,
	TDS_TOKEN_RES_DONE,
	TDS_TOKEN_RES_ROW,
	TDS_TOKEN_RES_COMPUTE,
	TDS_TOKEN_RES_PROC,
	TDS_TOKEN_RES_MSG
};

#define TDS_TOKEN_FLAG(flag) TDS_RETURN_##flag = (1 << (TDS_TOKEN_RES_##flag*2)), TDS_STOPAT_##flag = (2 << (TDS_TOKEN_RES_##flag*2))

enum tds_token_flags
{
	TDS_HANDLE_ALL = 0,
	TDS_TOKEN_FLAG(OTHERS),
	TDS_TOKEN_FLAG(ROWFMT),
	TDS_TOKEN_FLAG(COMPUTEFMT),
	TDS_TOKEN_FLAG(PARAMFMT),
	TDS_TOKEN_FLAG(DONE),
	TDS_TOKEN_FLAG(ROW),
	TDS_TOKEN_FLAG(COMPUTE),
	TDS_TOKEN_FLAG(PROC),
	TDS_TOKEN_FLAG(MSG),
	TDS_TOKEN_RESULTS = TDS_RETURN_ROWFMT|TDS_RETURN_COMPUTEFMT|TDS_RETURN_DONE|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_RETURN_PROC,
	TDS_TOKEN_TRAILING = TDS_STOPAT_ROWFMT|TDS_STOPAT_COMPUTEFMT|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_STOPAT_MSG|TDS_STOPAT_OTHERS
};

/**
 * Flags returned in TDS_DONE token
 */
enum tds_end
{
	  TDS_DONE_FINAL 	= 0x00	/**< final result set, command completed successfully. */
	, TDS_DONE_MORE_RESULTS = 0x01	/**< more results follow */
	, TDS_DONE_ERROR 	= 0x02	/**< error occurred */
	, TDS_DONE_INXACT 	= 0x04	/**< transaction in progress */
	, TDS_DONE_PROC 	= 0x08	/**< results are from a stored procedure */
	, TDS_DONE_COUNT 	= 0x10	/**< count field in packet is valid */
	, TDS_DONE_CANCELLED 	= 0x20	/**< acknowledging an attention command (usually a cancel) */
	, TDS_DONE_EVENT 	= 0x40	/* part of an event notification. */
	, TDS_DONE_SRVERROR 	= 0x100	/**< SQL server server error */
	
	/* after the above flags, a TDS_DONE packet has a field describing the state of the transaction */
	, TDS_DONE_NO_TRAN 	= 0	/* No transaction in effect */
	, TDS_DONE_TRAN_SUCCEED = 1	/* Transaction completed successfully */
	, TDS_DONE_TRAN_PROGRESS= 2	/* Transaction in progress */
	, TDS_DONE_STMT_ABORT 	= 3	/* A statement aborted */
	, TDS_DONE_TRAN_ABORT 	= 4	/* Transaction aborted */
};


/*
 * TDSERRNO is emitted by libtds to the client library's error handler
 * (which may in turn call the client's error handler).
 * These match the db-lib msgno, because the same values have the same meaning
 * in db-lib and ODBC.  ct-lib maps them to ct-lib numbers (todo). 
 */
typedef enum {	TDSEICONVIU    = 2400, 
		TDSEICONVAVAIL = 2401, 
		TDSEICONVO     = 2402, 
		TDSEICONVI     = 2403, 
		TDSEICONV2BIG  = 2404, 
		TDSESYNC = 20001, 
		TDSEFCON = 20002, 
		TDSETIME = 20003, 
		TDSEREAD = 20004, 
		TDSEWRIT = 20006, 
		TDSESOCK = 20008, 
		TDSECONN = 20009, 
		TDSEPWD  = 20014, 
		TDSESEOF = 20017, 
		TDSERPND = 20019, 
		TDSEBTOK = 20020, 
		TDSEOOB  = 20022, 
		TDSECLOS = 20056,
		TDSEUSCT = 20058, 
		TDSEUTDS = 20146, 
		TDSEEUNR = 20185, 
		TDSECAP  = 20203, 
		TDSENEG  = 20210, 
		TDSEUMSG = 20212, 
		TDSECAPTYP  = 20213, 
		TDSECLOSEIN = 20292 
} TDSERRNO;

/*
 * TDS_ERROR indicates a successful processing, but that a TDS_ERROR_TOKEN or TDS_EED_TOKEN error was encountered.  
 * TDS_FAIL indicates an unrecoverable failure.
 */
#define TDS_ERROR            3
#define TDS_DONT_RETURN      42

#define TDS5_PARAMFMT2_TOKEN       32	/* 0x20 */
#define TDS_LANGUAGE_TOKEN         33	/* 0x21    TDS 5.0 only              */
#define TDS_ORDERBY2_TOKEN         34	/* 0x22 */
#define TDS_ROWFMT2_TOKEN          97	/* 0x61    TDS 5.0 only              */
#define TDS_LOGOUT_TOKEN          113	/* 0x71    TDS 5.0 only? ct_close()  */
#define TDS_RETURNSTATUS_TOKEN    121	/* 0x79                              */
#define TDS_PROCID_TOKEN          124	/* 0x7C    TDS 4.2 only - TDS_PROCID */
#define TDS7_RESULT_TOKEN         129	/* 0x81    TDS 7.0 only              */
#define TDS7_COMPUTE_RESULT_TOKEN 136	/* 0x88    TDS 7.0 only              */
#define TDS_COLNAME_TOKEN         160	/* 0xA0    TDS 4.2 only              */
#define TDS_COLFMT_TOKEN          161	/* 0xA1    TDS 4.2 only - TDS_COLFMT */
#define TDS_DYNAMIC2_TOKEN        163	/* 0xA3 */
#define TDS_TABNAME_TOKEN         164	/* 0xA4 */
#define TDS_COLINFO_TOKEN         165	/* 0xA5 */
#define TDS_OPTIONCMD_TOKEN   	  166	/* 0xA6 */
#define TDS_COMPUTE_NAMES_TOKEN   167	/* 0xA7 */
#define TDS_COMPUTE_RESULT_TOKEN  168	/* 0xA8 */
#define TDS_ORDERBY_TOKEN         169	/* 0xA9    TDS_ORDER                 */
#define TDS_ERROR_TOKEN           170	/* 0xAA                              */
#define TDS_INFO_TOKEN            171	/* 0xAB                              */
#define TDS_PARAM_TOKEN           172	/* 0xAC    RETURNVALUE?              */
#define TDS_LOGINACK_TOKEN        173	/* 0xAD                              */
#define TDS_CONTROL_TOKEN         174	/* 0xAE    TDS_CONTROL               */
#define TDS_ROW_TOKEN             209	/* 0xD1                              */
#define TDS_CMP_ROW_TOKEN         211	/* 0xD3                              */
#define TDS5_PARAMS_TOKEN         215	/* 0xD7    TDS 5.0 only              */
#define TDS_CAPABILITY_TOKEN      226	/* 0xE2                              */
#define TDS_ENVCHANGE_TOKEN       227	/* 0xE3                              */
#define TDS_EED_TOKEN             229	/* 0xE5                              */
#define TDS_DBRPC_TOKEN           230	/* 0xE6                              */
#define TDS5_DYNAMIC_TOKEN        231	/* 0xE7    TDS 5.0 only              */
#define TDS5_PARAMFMT_TOKEN       236	/* 0xEC    TDS 5.0 only              */
#define TDS_AUTH_TOKEN            237	/* 0xED    TDS 7.0 only              */
#define TDS_RESULT_TOKEN          238	/* 0xEE                              */
#define TDS_DONE_TOKEN            253	/* 0xFD    TDS_DONE                  */
#define TDS_DONEPROC_TOKEN        254	/* 0xFE    TDS_DONEPROC              */
#define TDS_DONEINPROC_TOKEN      255	/* 0xFF    TDS_DONEINPROC            */

/* CURSOR support: TDS 5.0 only*/
#define TDS_CURCLOSE_TOKEN        128  /* 0x80    TDS 5.0 only              */
#define TDS_CURDELETE_TOKEN       129  /* 0x81    TDS 5.0 only              */
#define TDS_CURFETCH_TOKEN        130  /* 0x82    TDS 5.0 only              */
#define TDS_CURINFO_TOKEN         131  /* 0x83    TDS 5.0 only              */
#define TDS_CUROPEN_TOKEN         132  /* 0x84    TDS 5.0 only              */
#define TDS_CURDECLARE_TOKEN      134  /* 0x86    TDS 5.0 only              */

enum {
	TDS_CUR_ISTAT_UNUSED    = 0x00,
	TDS_CUR_ISTAT_DECLARED  = 0x01,
	TDS_CUR_ISTAT_OPEN      = 0x02,
	TDS_CUR_ISTAT_CLOSED    = 0x04,
	TDS_CUR_ISTAT_RDONLY    = 0x08,
	TDS_CUR_ISTAT_UPDATABLE = 0x10,
	TDS_CUR_ISTAT_ROWCNT    = 0x20,
	TDS_CUR_ISTAT_DEALLOC   = 0x40
};

/* 
 * Cursor Declare, SetRows, Open and Close all return 0x83 token. 
 * But only SetRows includes the rowcount (4 byte) in the stream. 
 * So for Setrows we read the rowcount from the stream and not for others. 
 * These values are useful to determine when to read the rowcount from the packet
 */
#define IS_DECLARE  100
#define IS_CURROW   200
#define IS_OPEN     300
#define IS_CLOSE    400

/* states for tds_process_messages() */
#define PROCESS_ROWS    0
#define PROCESS_RESULTS 1
#define CANCEL_PROCESS  2
#define GOTO_1ST_ROW    3
#define LOGIN           4

/* environment type field */
#define TDS_ENV_DATABASE  	1
#define TDS_ENV_LANG      	2
#define TDS_ENV_CHARSET   	3
#define TDS_ENV_PACKSIZE  	4
#define TDS_ENV_LCID        	5
#define TDS_ENV_SQLCOLLATION	7
#define TDS_ENV_BEGINTRANS	8
#define TDS_ENV_COMMITTRANS	9
#define TDS_ENV_ROLLBACKTRANS	10

/* string types */
#define TDS_NULLTERM -9

/* Microsoft internal stored procedure id's */

#define TDS_SP_CURSOR           1
#define TDS_SP_CURSOROPEN       2
#define TDS_SP_CURSORPREPARE    3
#define TDS_SP_CURSOREXECUTE    4
#define TDS_SP_CURSORPREPEXEC   5
#define TDS_SP_CURSORUNPREPARE  6
#define TDS_SP_CURSORFETCH      7
#define TDS_SP_CURSOROPTION     8
#define TDS_SP_CURSORCLOSE      9
#define TDS_SP_EXECUTESQL      10
#define TDS_SP_PREPARE         11
#define TDS_SP_EXECUTE         12
#define TDS_SP_PREPEXEC        13
#define TDS_SP_PREPEXECRPC     14
#define TDS_SP_UNPREPARE       15
/* 
 * <rant> Sybase does an awful job of this stuff, non null ints of size 1 2 
 * and 4 have there own codes but nullable ints are lumped into INTN
 * sheesh! </rant>
 */
typedef enum
{
	SYBCHAR = 47,		/* 0x2F */
#define SYBCHAR	SYBCHAR
	SYBVARCHAR = 39,	/* 0x27 */
#define SYBVARCHAR	SYBVARCHAR
	SYBINTN = 38,		/* 0x26 */
#define SYBINTN	SYBINTN
	SYBINT1 = 48,		/* 0x30 */
#define SYBINT1	SYBINT1
	SYBINT2 = 52,		/* 0x34 */
#define SYBINT2	SYBINT2
	SYBINT4 = 56,		/* 0x38 */
#define SYBINT4	SYBINT4
	SYBFLT8 = 62,		/* 0x3E */
#define SYBFLT8	SYBFLT8
	SYBDATETIME = 61,	/* 0x3D */
#define SYBDATETIME	SYBDATETIME
	SYBBIT = 50,		/* 0x32 */
#define SYBBIT	SYBBIT
	SYBTEXT = 35,		/* 0x23 */
#define SYBTEXT	SYBTEXT
	SYBNTEXT = 99,		/* 0x63 */
#define SYBNTEXT	SYBNTEXT
	SYBIMAGE = 34,		/* 0x22 */
#define SYBIMAGE	SYBIMAGE
	SYBMONEY4 = 122,	/* 0x7A */
#define SYBMONEY4	SYBMONEY4
	SYBMONEY = 60,		/* 0x3C */
#define SYBMONEY	SYBMONEY
	SYBDATETIME4 = 58,	/* 0x3A */
#define SYBDATETIME4	SYBDATETIME4
	SYBREAL = 59,		/* 0x3B */
#define SYBREAL	SYBREAL
	SYBBINARY = 45,		/* 0x2D */
#define SYBBINARY	SYBBINARY
	SYBVOID = 31,		/* 0x1F */
#define SYBVOID	SYBVOID
	SYBVARBINARY = 37,	/* 0x25 */
#define SYBVARBINARY	SYBVARBINARY
	SYBBITN = 104,		/* 0x68 */
#define SYBBITN	SYBBITN
	SYBNUMERIC = 108,	/* 0x6C */
#define SYBNUMERIC	SYBNUMERIC
	SYBDECIMAL = 106,	/* 0x6A */
#define SYBDECIMAL	SYBDECIMAL
	SYBFLTN = 109,		/* 0x6D */
#define SYBFLTN	SYBFLTN
	SYBMONEYN = 110,	/* 0x6E */
#define SYBMONEYN	SYBMONEYN
	SYBDATETIMN = 111,	/* 0x6F */
#define SYBDATETIMN	SYBDATETIMN

/*
 * MS only types
 */
	SYBNVARCHAR = 103,	/* 0x67 */
#define SYBNVARCHAR	SYBNVARCHAR
	SYBINT8 = 127,		/* 0x7F */
#define SYBINT8	SYBINT8
	XSYBCHAR = 175,		/* 0xAF */
#define XSYBCHAR	XSYBCHAR
	XSYBVARCHAR = 167,	/* 0xA7 */
#define XSYBVARCHAR	XSYBVARCHAR
	XSYBNVARCHAR = 231,	/* 0xE7 */
#define XSYBNVARCHAR	XSYBNVARCHAR
	XSYBNCHAR = 239,	/* 0xEF */
#define XSYBNCHAR	XSYBNCHAR
	XSYBVARBINARY = 165,	/* 0xA5 */
#define XSYBVARBINARY	XSYBVARBINARY
	XSYBBINARY = 173,	/* 0xAD */
#define XSYBBINARY	XSYBBINARY
	SYBUNIQUE = 36,		/* 0x24 */
#define SYBUNIQUE	SYBUNIQUE
	SYBVARIANT = 98, 	/* 0x62 */
#define SYBVARIANT	SYBVARIANT

/*
 * Sybase only types
 */
	SYBLONGBINARY = 225,	/* 0xE1 */
#define SYBLONGBINARY	SYBLONGBINARY
	SYBUINT1 = 64,		/* 0x40 */
#define SYBUINT1	SYBUINT1
	SYBUINT2 = 65,		/* 0x41 */
#define SYBUINT2	SYBUINT2
	SYBUINT4 = 66,		/* 0x42 */
#define SYBUINT4	SYBUINT4
	SYBUINT8 = 67,		/* 0x43 */
#define SYBUINT8	SYBUINT8
	SYBBLOB = 36,		/* 0x24 */
#define SYBBLOB		SYBBLOB
	SYBBOUNDARY = 104,	/* 0x68 */
#define SYBBOUNDARY	SYBBOUNDARY
	SYBDATE = 49,		/* 0x31 */
#define SYBDATE		SYBDATE
	SYBDATEN = 123,		/* 0x7B */
#define SYBDATEN	SYBDATEN
	SYB5INT8 = 191,		/* 0xBF */
#define SYB5INT8		SYB5INT8
	SYBINTERVAL = 46,	/* 0x2E */
#define SYBINTERVAL	SYBINTERVAL
	SYBLONGCHAR = 175,	/* 0xAF */
#define SYBLONGCHAR	SYBLONGCHAR
	SYBSENSITIVITY = 103,	/* 0x67 */
#define SYBSENSITIVITY	SYBSENSITIVITY
	SYBSINT1 = 176,		/* 0xB0 */
#define SYBSINT1	SYBSINT1
	SYBTIME = 51,		/* 0x33 */
#define SYBTIME		SYBTIME
	SYBTIMEN = 147,		/* 0x93 */
#define SYBTIMEN	SYBTIMEN
	SYBUINTN = 68,		/* 0x44 */
#define SYBUINTN	SYBUINTN
	SYBUNITEXT = 174,	/* 0xAE */
#define SYBUNITEXT	SYBUNITEXT
	SYBXML = 163,		/* 0xA3 */
#define SYBXML		SYBXML

} TDS_SERVER_TYPE;


typedef enum
{
	USER_UNICHAR_TYPE = 34,		/* 0x22 */
	USER_UNIVARCHAR_TYPE = 35	/* 0x23 */
} TDS_USER_TYPE;

#define SYBAOPCNT  0x4b
#define SYBAOPCNTU 0x4c
#define SYBAOPSUM  0x4d
#define SYBAOPSUMU 0x4e
#define SYBAOPAVG  0x4f
#define SYBAOPAVGU 0x50
#define SYBAOPMIN  0x51
#define SYBAOPMAX  0x52

/* mssql2k compute operator */
#define SYBAOPCNT_BIG		0x09
#define SYBAOPSTDEV		0x30
#define SYBAOPSTDEVP		0x31
#define SYBAOPVAR		0x32
#define SYBAOPVARP		0x33
#define SYBAOPCHECKSUM_AGG	0x72


/** 
 * options that can be sent with a TDS_OPTIONCMD token
 */
typedef enum
{
	  TDS_OPT_SET = 1	/* Set an option. */
	, TDS_OPT_DEFAULT = 2	/* Set option to its default value. */
	, TDS_OPT_LIST = 3	/* Request current setting of a specific option. */
	, TDS_OPT_INFO = 4	/* Report current setting of a specific option. */
} TDS_OPTION_CMD;

typedef enum
{
	  TDS_OPT_DATEFIRST = 1		/* 0x01 */
	, TDS_OPT_TEXTSIZE = 2		/* 0x02 */
	, TDS_OPT_STAT_TIME = 3		/* 0x03 */
	, TDS_OPT_STAT_IO = 4		/* 0x04 */
	, TDS_OPT_ROWCOUNT = 5		/* 0x05 */
	, TDS_OPT_NATLANG = 6		/* 0x06 */
	, TDS_OPT_DATEFORMAT = 7	/* 0x07 */
	, TDS_OPT_ISOLATION = 8		/* 0x08 */
	, TDS_OPT_AUTHON = 9		/* 0x09 */
	, TDS_OPT_CHARSET = 10		/* 0x0a */
	, TDS_OPT_SHOWPLAN = 13		/* 0x0d */
	, TDS_OPT_NOEXEC = 14		/* 0x0e */
	, TDS_OPT_ARITHIGNOREON = 15	/* 0x0f */
	, TDS_OPT_ARITHABORTON = 17	/* 0x11 */
	, TDS_OPT_PARSEONLY = 18	/* 0x12 */
	, TDS_OPT_GETDATA = 20		/* 0x14 */
	, TDS_OPT_NOCOUNT = 21		/* 0x15 */
	, TDS_OPT_FORCEPLAN = 23	/* 0x17 */
	, TDS_OPT_FORMATONLY = 24	/* 0x18 */
	, TDS_OPT_CHAINXACTS = 25	/* 0x19 */
	, TDS_OPT_CURCLOSEONXACT = 26	/* 0x1a */
	, TDS_OPT_FIPSFLAG = 27		/* 0x1b */
	, TDS_OPT_RESTREES = 28		/* 0x1c */
	, TDS_OPT_IDENTITYON = 29	/* 0x1d */
	, TDS_OPT_CURREAD = 30		/* 0x1e */
	, TDS_OPT_CURWRITE = 31		/* 0x1f */
	, TDS_OPT_IDENTITYOFF = 32	/* 0x20 */
	, TDS_OPT_AUTHOFF = 33		/* 0x21 */
	, TDS_OPT_ANSINULL = 34		/* 0x22 */
	, TDS_OPT_QUOTED_IDENT = 35	/* 0x23 */
	, TDS_OPT_ARITHIGNOREOFF = 36	/* 0x24 */
	, TDS_OPT_ARITHABORTOFF = 37	/* 0x25 */
	, TDS_OPT_TRUNCABORT = 38	/* 0x26 */
} TDS_OPTION;

typedef union tds_option_arg
{
	TDS_TINYINT ti;
	TDS_INT i;
	TDS_CHAR *c;
} TDS_OPTION_ARG;

enum {
	TDS_OPT_ARITHOVERFLOW = 0x01,
	TDS_OPT_NUMERICTRUNC = 0x02
};

enum TDS_OPT_DATEFIRST_CHOICE
{
	TDS_OPT_MONDAY = 1, TDS_OPT_TUESDAY = 2, TDS_OPT_WEDNESDAY = 3, TDS_OPT_THURSDAY = 4, TDS_OPT_FRIDAY = 5, TDS_OPT_SATURDAY =
		6, TDS_OPT_SUNDAY = 7
};

enum TDS_OPT_DATEFORMAT_CHOICE
{
	TDS_OPT_FMTMDY = 1, TDS_OPT_FMTDMY = 2, TDS_OPT_FMTYMD = 3, TDS_OPT_FMTYDM = 4, TDS_OPT_FMTMYD = 5, TDS_OPT_FMTDYM = 6
};
enum TDS_OPT_ISOLATION_CHOICE
{
	TDS_OPT_LEVEL1 = 1, TDS_OPT_LEVEL3 = 3
};

typedef enum tds_packet_type
{
	TDS_QUERY = 1,
	TDS_LOGIN = 2,
	TDS_RPC = 3,
	TDS_REPLY = 4,
	TDS_CANCEL = 6,
	TDS_BULK = 7,
	TDS_NORMAL = 15,
	TDS7_LOGIN = 16,
	TDS7_AUTH = 17,
	TDS8_PRELOGIN = 18
} TDS_PACKET_TYPE;

typedef enum tds_encryption_level {
	TDS_ENCRYPTION_OFF, TDS_ENCRYPTION_REQUEST, TDS_ENCRYPTION_REQUIRE
} TDS_ENCRYPTION_LEVEL;

#define TDS_ZERO_FREE(x) do {free((x)); (x) = NULL;} while(0)
#define TDS_VECTOR_SIZE(x) (sizeof(x)/sizeof(x[0]))

/*
 * TODO use system macros for optimization
 * See mcrypt for reference and linux kernel source for optimization
 * check if unaligned access and use fast write/read when implemented
 */
#define TDS_BYTE_SWAP16(value)                 \
         (((((unsigned short)value)<<8) & 0xFF00)   | \
          ((((unsigned short)value)>>8) & 0x00FF))

#define TDS_BYTE_SWAP32(value)                     \
         (((((unsigned long)value)<<24) & 0xFF000000)  | \
          ((((unsigned long)value)<< 8) & 0x00FF0000)  | \
          ((((unsigned long)value)>> 8) & 0x0000FF00)  | \
          ((((unsigned long)value)>>24) & 0x000000FF))

#define is_end_token(x) (x==TDS_DONE_TOKEN    || \
			x==TDS_DONEPROC_TOKEN    || \
			x==TDS_DONEINPROC_TOKEN)

#define is_hard_end_token(x) (x==TDS_DONE_TOKEN    || \
			x==TDS_DONEPROC_TOKEN)

#define is_msg_token(x) (x==TDS_INFO_TOKEN    || \
			x==TDS_ERROR_TOKEN    || \
			x==TDS_EED_TOKEN)

#define is_result_token(x) (x==TDS_RESULT_TOKEN || \
			x==TDS_ROWFMT2_TOKEN    || \
			x==TDS7_RESULT_TOKEN    || \
			x==TDS_COLFMT_TOKEN     || \
			x==TDS_COLNAME_TOKEN    || \
			x==TDS_RETURNSTATUS_TOKEN)

/* FIXME -- not a complete list */
#define is_fixed_type(x) (x==SYBINT1    || \
			x==SYBINT2      || \
			x==SYBINT4      || \
			x==SYBINT8      || \
			x==SYBREAL      || \
			x==SYBFLT8      || \
			x==SYBDATETIME  || \
			x==SYBDATETIME4 || \
			x==SYBBIT       || \
			x==SYBMONEY     || \
			x==SYBMONEY4    || \
			x==SYBVOID      || \
			x==SYBUNIQUE)
#define is_nullable_type(x) ( \
			x==SYBBITN      || \
                     x==SYBINTN      || \
                     x==SYBFLTN      || \
                     x==SYBMONEYN    || \
                     x==SYBDATETIMN  || \
                     x==SYBVARCHAR   || \
                     x==SYBBINARY    || \
                     x==SYBVARBINARY || \
                     x==SYBTEXT      || \
                     x==SYBNTEXT     || \
                     x==SYBIMAGE)

#define is_variable_type(x) ( \
	(x)==SYBTEXT	|| \
	(x)==SYBIMAGE	|| \
	(x)==SYBNTEXT	|| \
	(x)==SYBCHAR	|| \
	(x)==SYBVARCHAR	|| \
	(x)==SYBBINARY	|| \
	(x)==SYBVARBINARY	|| \
	(x)==SYBLONGBINARY	|| \
	(x)==XSYBCHAR	|| \
	(x)==XSYBVARCHAR	|| \
	(x)==XSYBNVARCHAR	|| \
	(x)==XSYBNCHAR)

#define is_blob_type(x) (x==SYBTEXT || x==SYBIMAGE || x==SYBNTEXT)
/* large type means it has a two byte size field */
/* define is_large_type(x) (x>128) */
#define is_numeric_type(x) (x==SYBNUMERIC || x==SYBDECIMAL)
#define is_unicode_type(x) (x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT)
#define is_collate_type(x) (x==XSYBVARCHAR || x==XSYBCHAR || x==SYBTEXT || x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT)
#define is_ascii_type(x) ( x==XSYBCHAR || x==XSYBVARCHAR || x==SYBTEXT || x==SYBCHAR || x==SYBVARCHAR)
#define is_binary_type(x) (x==SYBLONGBINARY)
#define is_char_type(x) (is_unicode_type(x) || is_ascii_type(x))
#define is_similar_type(x, y) ((is_char_type(x) && is_char_type(y)) || ((is_unicode_type(x) && is_unicode_type(y))))


#define TDS_MAX_CAPABILITY	22
#define MAXPRECISION 		80
#define TDS_MAX_CONN		4096
#define TDS_MAX_DYNID_LEN	30

/* defaults to use if no others are found */
#define TDS_DEF_SERVER		"SYBASE"
#define TDS_DEF_BLKSZ		512
#define TDS_DEF_CHARSET		"iso_1"
#define TDS_DEF_LANG		"us_english"
#if TDS42
#define TDS_DEF_MAJOR		4
#define TDS_DEF_MINOR		2
#define TDS_DEF_PORT		1433
#elif TDS46
#define TDS_DEF_MAJOR		4
#define TDS_DEF_MINOR		6
#define TDS_DEF_PORT		4000
#elif TDS70
#define TDS_DEF_MAJOR		7
#define TDS_DEF_MINOR		0
#define TDS_DEF_PORT		1433
#elif TDS80
#define TDS_DEF_MAJOR		8
#define TDS_DEF_MINOR		0
#define TDS_DEF_PORT		1433
#else
#define TDS_DEF_MAJOR		5
#define TDS_DEF_MINOR		0
#define TDS_DEF_PORT		4000
#endif

/* normalized strings from freetds.conf file */
#define TDS_STR_VERSION  "tds version"
#define TDS_STR_BLKSZ    "initial block size"
#define TDS_STR_SWAPDT   "swap broken dates"
#define TDS_STR_SWAPMNY  "swap broken money"
#define TDS_STR_DUMPFILE "dump file"
#define TDS_STR_DEBUGLVL "debug level"
#define TDS_STR_DEBUGFLAGS "debug flags"
#define TDS_STR_TIMEOUT  "timeout"
#define TDS_STR_QUERY_TIMEOUT  "query timeout"
#define TDS_STR_CONNTIMEOUT "connect timeout"
#define TDS_STR_HOSTNAME "hostname"
#define TDS_STR_HOST     "host"
#define TDS_STR_PORT     "port"
#define TDS_STR_TEXTSZ   "text size"
/* for big endian hosts */
#define TDS_STR_EMUL_LE	"emulate little endian"
#define TDS_STR_CHARSET	"charset"
#define TDS_STR_CLCHARSET	"client charset"
#define TDS_STR_LANGUAGE	"language"
#define TDS_STR_APPENDMODE	"dump file append"
#define TDS_STR_DATEFMT	"date format"
#define TDS_STR_INSTANCE "instance"
#define TDS_STR_ENCRYPTION	 "encryption"
/* conf values */
#define TDS_STR_ENCRYPTION_OFF	 "off"
#define TDS_STR_ENCRYPTION_REQUEST "request"
#define TDS_STR_ENCRYPTION_REQUIRE "require"


/* TODO do a better check for alignment than this */
typedef union
{
	void *p;
	int i;
} tds_align_struct;

#define TDS_ALIGN_SIZE sizeof(tds_align_struct)

#define TDS_MAX_LOGIN_STR_SZ 30
typedef struct tds_login
{
	DSTR server_name;
	DSTR server_addr;
	int port;
	TDS_TINYINT major_version;	/* TDS version */
	TDS_TINYINT minor_version;	/* TDS version */
	int block_size;
	DSTR language;		/* ie us-english */
	DSTR server_charset;	/*  ie iso_1 */
	TDS_INT connect_timeout;
	DSTR client_host_name;
	DSTR app_name;
	DSTR user_name;
	DSTR password;
	
	DSTR library;	/* Ct-Library, DB-Library,  TDS-Library or ODBC */
	TDS_TINYINT bulk_copy;
	TDS_TINYINT suppress_language;
	TDS_TINYINT encryption_level;

	TDS_INT query_timeout;
	unsigned char capabilities[TDS_MAX_CAPABILITY];
	DSTR client_charset;
} TDSLOGIN;

typedef struct tds_connection
{
	/* first part of structure is the same of login one */
	DSTR server_name; /**< server name (in freetds.conf) */
	int port;	   /**< port of database service */
	TDS_TINYINT major_version;
	TDS_TINYINT minor_version;
	int block_size;
	DSTR language;
	DSTR server_charset;	/**< charset of server */
	TDS_INT connect_timeout;
	DSTR client_host_name;
	DSTR server_host_name;
	DSTR app_name;
	DSTR user_name;	    /**< account for login */
	DSTR password;	    /**< password of account login */
	DSTR library;
	TDS_TINYINT bulk_copy;
	TDS_TINYINT suppress_language;
	TDS_TINYINT encryption_level;

	TDS_INT query_timeout;
	unsigned char capabilities[TDS_MAX_CAPABILITY];
	DSTR client_charset;

	DSTR ip_addr;	  /**< ip of server */
	DSTR instance_name;
	DSTR database;
	DSTR dump_file;
	int debug_flags;
	int text_size;
	int broken_dates;
	int broken_money;
	int emul_little_endian;
} TDSCONNECTION;

typedef struct tds_locale
{
	char *language;
	char *server_charset;
	char *client_charset;
	char *date_fmt;
} TDSLOCALE;

/** 
 * Information about blobs (e.g. text or image).
 * current_row contains this structure.
 */
typedef struct tds_blob
{
	TDS_CHAR *textvalue;
	TDS_CHAR textptr[16];
	TDS_CHAR timestamp[8];
} TDSBLOB;

/** 
 * TDS 8.0 collation informations.
 */
typedef struct
{
	TDS_USMALLINT locale_id;	/* master..syslanguages.lcid */
	TDS_USMALLINT flags;
	TDS_UCHAR charset_id;		/* or zero */
} TDS8_COLLATION;

/* SF stands for "sort flag" */
#define TDS_SF_BIN                   (TDS_USMALLINT) 0x100
#define TDS_SF_WIDTH_INSENSITIVE     (TDS_USMALLINT) 0x080
#define TDS_SF_KATATYPE_INSENSITIVE  (TDS_USMALLINT) 0x040
#define TDS_SF_ACCENT_SENSITIVE      (TDS_USMALLINT) 0x020
#define TDS_SF_CASE_INSENSITIVE      (TDS_USMALLINT) 0x010

/* UT stands for user type */
#define TDS_UT_TIMESTAMP             80


/**
 * Information relevant to libiconv.  The name is an iconv name, not 
 * the same as found in master..syslanguages. 
 */
typedef struct _tds_encoding
{
	const char *name;
	unsigned char min_bytes_per_char;
	unsigned char max_bytes_per_char;
} TDS_ENCODING;

typedef struct _tds_bcpcoldata
{
	TDS_UCHAR *data;
	TDS_INT    datalen;
	TDS_INT    is_null;
} BCPCOLDATA;


enum
{ TDS_SYSNAME_SIZE = 512 };

/** 
 * Metadata about columns in regular and compute rows 
 */
typedef struct tds_column
{
	TDS_SMALLINT column_type;	/**< This type can be different from wire type because 
	 				 * conversion (e.g. UCS-2->Ascii) can be applied.    
					 * I'm beginning to wonder about the wisdom of this, however. 
					 * April 2003 jkl
					 */
	TDS_INT column_usertype;
	TDS_INT column_flags;

	TDS_INT column_size;		/**< maximun size of data. For fixed is the size. */

	TDS_TINYINT column_varint_size;	/**< size of length when reading from wire (0, 1, 2 or 4) */

	TDS_TINYINT column_prec;	/**< precision for decimal/numeric */
	TDS_TINYINT column_scale;	/**< scale for decimal/numeric */

	TDS_SMALLINT column_namelen;	/**< length of column name */
	TDS_SMALLINT table_namelen;
	struct
	{
		TDS_SMALLINT column_type;	/**< type of data, saved from wire */
		TDS_INT column_size;
	} on_server;

	const TDSICONV *char_conv;	/**< refers to previously allocated iconv information */

	TDS_CHAR table_name[TDS_SYSNAME_SIZE];
	TDS_CHAR column_name[TDS_SYSNAME_SIZE];
	char * table_column_name;

	unsigned char *column_data;
	void (*column_data_free)(struct tds_column *column);
	unsigned int column_nullable:1;
	unsigned int column_writeable:1;
	unsigned int column_identity:1;
	unsigned int column_key:1;
	unsigned int column_hidden:1;
	unsigned int column_output:1;
	unsigned int column_timestamp:1;
	TDS_UCHAR column_collation[5];

	/* additional fields flags for compute results */
	TDS_TINYINT column_operator;
	TDS_SMALLINT column_operand;

	/* FIXME this is data related, not column */
	/** size written in variable (ie: char, text, binary). -1 if NULL. */
	TDS_INT column_cur_size;

	/* related to binding or info stored by client libraries */
	/* FIXME find a best place to store these data, some are unused */
	TDS_SMALLINT column_bindtype;
	TDS_SMALLINT column_bindfmt;
	TDS_UINT column_bindlen;
	TDS_SMALLINT *column_nullbind;
	TDS_CHAR *column_varaddr;
	TDS_INT *column_lenbind;
	TDS_INT column_textpos;
	TDS_INT column_text_sqlgetdatapos;

	BCPCOLDATA *bcp_column_data;
	/**
	 * The length, in bytes, of any length prefix this column may have.
	 * For example, strings in some non-C programming languages are
	 * made up of a one-byte length prefix, followed by the string
	 * data itself.
	 * If the data does not have a length prefix, set prefixlen to 0.
	 * Currently not very used in code, however do not remove.
	 */
	TDS_INT bcp_prefix_len;
	TDS_INT bcp_term_len;
	TDS_CHAR *bcp_terminator;
} TDSCOLUMN;


/** Hold information for any results */
typedef struct tds_result_info
{
	/* TODO those fields can became a struct */
	TDS_SMALLINT num_cols;
	TDSCOLUMN **columns;
	TDS_INT row_size;
	TDS_INT ref_count;
	unsigned char *current_row;
	void (*row_free)(struct tds_result_info* result, unsigned char *row);

	TDS_SMALLINT rows_exist;
	/* TODO remove ?? used only in dblib */
	TDS_INT row_count;
	/* TODO remove ?? used only in dblib */
	TDS_TINYINT more_results;
	TDS_SMALLINT computeid;
	TDS_SMALLINT *bycolumns;
	TDS_SMALLINT by_cols;
} TDSRESULTINFO;

/** values for tds->state */
typedef enum _TDS_STATE
{
	TDS_IDLE,	/**< no data expected */
	TDS_QUERYING,	/**< client is sending request */
	TDS_PENDING,	/**< cilent is waiting for data */
	TDS_READING,	/**< client is reading data */
	TDS_DEAD	/**< no connection */
} TDS_STATE;

#define TDS_DBG_FUNC    __FILE__, ((__LINE__ << 4) | 7)
#define TDS_DBG_INFO2   __FILE__, ((__LINE__ << 4) | 6)
#define TDS_DBG_INFO1   __FILE__, ((__LINE__ << 4) | 5)
#define TDS_DBG_NETWORK __FILE__, ((__LINE__ << 4) | 4)
#define TDS_DBG_WARN    __FILE__, ((__LINE__ << 4) | 3)
#define TDS_DBG_ERROR   __FILE__, ((__LINE__ << 4) | 2)
#define TDS_DBG_SEVERE  __FILE__, ((__LINE__ << 4) | 1)

#define TDS_DBGFLAG_FUNC    0x80
#define TDS_DBGFLAG_INFO2   0x40
#define TDS_DBGFLAG_INFO1   0x20
#define TDS_DBGFLAG_NETWORK 0x10
#define TDS_DBGFLAG_WARN    0x08
#define TDS_DBGFLAG_ERROR   0x04
#define TDS_DBGFLAG_SEVERE  0x02
#define TDS_DBGFLAG_ALLLVL  0xfff
#define TDS_DBGFLAG_PID     0x1000
#define TDS_DBGFLAG_TIME    0x2000
#define TDS_DBGFLAG_SOURCE  0x4000
#define TDS_DBGFLAG_THREAD  0x8000

/**
 * An attempt at better logging.
 * Using these bitmapped values, various logging features can be turned on and off.
 * It can be especially helpful to turn packet data on/off for security reasons.
 */
enum TDS_DBG_LOG_STATE
{
	  TDS_DBG_LOGIN =  (1 << 0)	/**< for diagnosing login problems;                                       
				 	   otherwise the username/password information is suppressed. */
	, TDS_DBG_API =    (1 << 1)	/**< Log calls to client libraries */
	, TDS_DBG_ASYNC =  (1 << 2)	/**< Log asynchronous function starts or completes. */
	, TDS_DBG_DIAG =   (1 << 3)	/**< Log client- and server-generated messages */
	, TDS_DBG_error =  (1 << 4)
	/* TODO:  ^^^^^ make upper case when old #defines (above) are removed */
	/* Log FreeTDS runtime/logic error occurs. */
	, TDS_DBG_PACKET = (1 << 5)	/**< Log hex dump of packets to/from the server. */
	, TDS_DBG_LIBTDS = (1 << 6)	/**< Log calls to (and in) libtds */
	, TDS_DBG_CONFIG = (1 << 7)	/**< replaces TDSDUMPCONFIG */
	, TDS_DBG_DEFAULT = 0xFE	/**< all above except login packets */
};

typedef struct tds_result_info TDSCOMPUTEINFO;

typedef TDSRESULTINFO TDSPARAMINFO;

typedef struct tds_message
{
	TDS_CHAR *server;
	TDS_CHAR *message;
	TDS_CHAR *proc_name;
	TDS_CHAR *sql_state;
	TDS_UINT msgno;
	TDS_INT line_number;
	/* -1 .. 255 */
	TDS_SMALLINT state;
	TDS_TINYINT priv_msg_type;
	TDS_TINYINT severity;
	/* for library-generated errors */
	int oserr;
} TDSMESSAGE;

typedef struct tds_upd_col
{
	struct tds_upd_col *next;	
	TDS_INT colnamelength;
	char * columnname;
} TDSUPDCOL;

typedef enum {
	  TDS_CURSOR_STATE_UNACTIONED = 0   /* initial value */
	, TDS_CURSOR_STATE_REQUESTED = 1	/* called by ct_cursor */ 
	, TDS_CURSOR_STATE_SENT = 2		/* sent to server */
	, TDS_CURSOR_STATE_ACTIONED = 3		/* acknowledged by server */
} TDS_CURSOR_STATE;

typedef struct _tds_cursor_status
{
	TDS_CURSOR_STATE declare;
	TDS_CURSOR_STATE cursor_row;
	TDS_CURSOR_STATE open;
	TDS_CURSOR_STATE fetch;
	TDS_CURSOR_STATE close; 
	TDS_CURSOR_STATE dealloc;
} TDS_CURSOR_STATUS;

typedef enum _tds_cursor_operation
{
	TDS_CURSOR_POSITION = 0,
	TDS_CURSOR_UPDATE = 1,
	TDS_CURSOR_DELETE = 2,
	TDS_CURSOR_INSERT = 4
} TDS_CURSOR_OPERATION;

typedef enum _tds_cursor_fetch
{
	TDS_CURSOR_FETCH_NEXT = 1,
	TDS_CURSOR_FETCH_PREV,
	TDS_CURSOR_FETCH_FIRST,
	TDS_CURSOR_FETCH_LAST,
	TDS_CURSOR_FETCH_ABSOLUTE,
	TDS_CURSOR_FETCH_RELATIVE
} TDS_CURSOR_FETCH;

/**
 * Holds informations about a cursor
 */
typedef struct _tds_cursor 
{
	struct _tds_cursor *next;	/**< next in linked list, keep first */
	TDS_INT ref_count;		/**< reference counter so client can retain safely a pointer */
	TDS_TINYINT cursor_name_len;	/**< length of cursor name > 0 and <= 30  */
	char *cursor_name;		/**< name of the cursor */
	TDS_INT cursor_id;		/**< cursor id returned by the server after cursor declare */
	TDS_TINYINT options;		/**< read only|updatable */
	TDS_TINYINT hasargs;		/**< cursor parameters exists ? */
	TDS_USMALLINT query_len;	/**< SQL query length */
	char *query;                 	/**< SQL query */
	/* TODO for updatable columns */
	/* TDS_TINYINT number_upd_cols; */	/**< number of updatable columns */
	/* TDSUPDCOL *cur_col_list; */	/**< updatable column list */
	TDS_INT cursor_rows;		/**< number of cursor rows to fetch */
	/* TDSPARAMINFO *params; */	/** cursor parameter */
	TDS_CURSOR_STATUS status;
	TDS_SMALLINT srv_status;
	TDSRESULTINFO *res_info;	/** row fetched from this cursor */
	TDS_INT type, concurrency;
} TDSCURSOR;

/**
 * Current environment as reported by the server
 */
typedef struct tds_env
{
	int block_size;
	char *language;
	char *charset;
	char *database;
} TDSENV;

/**
 * Holds information for a dynamic (also called prepared) query.
 */
typedef struct tds_dynamic
{
	struct tds_dynamic *next;	/**< next in linked list, keep first */
	/** 
	 * id of dynamic.
	 * Usually this id correspond to server one but if not specified
	 * is generated automatically by libTDS
	 */
	char id[30];
	int dyn_state;
	/** numeric id for mssql7+*/
	TDS_INT num_id;
	TDSPARAMINFO *res_info;	/**< query results */
	/**
	 * query parameters.
	 * Mostly used executing query however is a good idea to prepare query
	 * again if parameter type change in an incompatible way (ie different
	 * types or larger size). Is also better to prepare a query knowing
	 * parameter types earlier.
	 */
	TDSPARAMINFO *params;
	/**
	 * this dynamic query cannot be prepared so libTDS have to construct a simple query.
	 * This can happen for instance is tds protocol doesn't support dynamics or trying
	 * to prepare query under Sybase that have BLOBs as parameters.
	 */
	int emulated;
	/** saved query, we need to know original query if prepare is impossible */
	char *query;
} TDSDYNAMIC;

typedef enum {
	TDS_MULTIPLE_QUERY,
	TDS_MULTIPLE_EXECUTE,
	TDS_MULTIPLE_RPC
} TDS_MULTIPLE_TYPE;

typedef struct tds_multiple
{
	TDS_MULTIPLE_TYPE type;
	unsigned int flags;
} TDSMULTIPLE;

/* forward declaration */
typedef struct tds_context TDSCONTEXT;

struct tds_context
{
	TDSLOCALE *locale;
	void *parent;
	/* handlers */
	int (*msg_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
	int (*err_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
	int (*int_handler) (void *);
};

enum TDS_ICONV_ENTRY
{ 
	  client2ucs2
	, client2server_chardata
	, iso2server_metadata
	, initial_char_conv_count	/* keep last */
};

struct tds_authentication
{
	TDS_UCHAR *packet;
	int packet_len;
	int (*free)(TDSSOCKET * tds, struct tds_authentication * auth);
	int (*handle_next)(TDSSOCKET * tds, struct tds_authentication * auth, size_t len);
};

typedef struct tds_authentication TDSAUTHENTICATION;

/**
 * Hold information for a server connection
 */
struct tds_socket
{
	/* fixed and connect time */
	/** tcp socket, INVALID_SOCKET if not connected */
	TDS_SYS_SOCKET s;
	TDS_SMALLINT major_version;
	TDS_SMALLINT minor_version;
	/** version of product (Sybase/MS and full version) */
	TDS_UINT product_version;
	char *product_name;
	unsigned char capabilities[TDS_MAX_CAPABILITY];
	unsigned char broken_dates;
	unsigned char option_flag2;
	/* in/out buffers */
	/** input buffer */
	unsigned char *in_buf;
	/** output buffer */
	unsigned char *out_buf;
	/** allocated input buffer */
	unsigned int in_buf_max;
	/** current position in in_buf */
	unsigned in_pos;
	/** current position in out_buf */
	unsigned out_pos;
	/** input buffer length */
	unsigned in_len;
	/* TODO remove blocksize from env and use out_len ?? */
/*	unsigned out_len; */
	/** input buffer type */
	unsigned char in_flag;
	/** output buffer type */
	unsigned char out_flag;
	/** true if current input buffer is the last one */
	unsigned char last_packet;
	void *parent;
	/**
	 * info about current query. 
	 * Contains information in process, both normal and compute results.
	 * This pointer shouldn't be freed; it's just an alias to another structure.
	 */
	TDSRESULTINFO *current_results;
	TDSRESULTINFO *res_info;
	TDS_INT num_comp_info;
	TDSCOMPUTEINFO **comp_info;
	TDSPARAMINFO *param_info;
	TDSCURSOR *cur_cursor;	/**< cursor in use */
	TDSCURSOR *cursors;	/**< linked list of cursors allocated for this connection */
	TDS_TINYINT has_status; /**< true is ret_status is valid */
	TDS_INT ret_status;     /**< return status from store procedure */
	TDS_STATE state;
	/** indicate we are waiting a cancel reply so discard tokens till acknowledge */
	volatile unsigned char in_cancel;
	/** rows updated/deleted/inserted/selected, TDS_NO_COUNT if not valid */
	TDS_INT8 rows_affected;
	/* timeout stuff from Jeff */
	TDS_INT query_timeout;
	TDSENV env;

	/* dynamic placeholder stuff */
	/*@dependent@*/ TDSDYNAMIC *cur_dyn;	/**< dynamic structure in use */
	TDSDYNAMIC *dyns;	/**< list of dynamic allocate for this connection */

	int emul_little_endian;
	char *date_fmt;
	const TDSCONTEXT *tds_ctx;
	int char_conv_count;
	TDSICONV **char_convs;

	/** config for login stuff. After login this field is NULL */
	TDSCONNECTION *connection;

	int spid;
	TDS_UCHAR collation[5];
	TDS_UCHAR tds9_transaction[8];
	void (*env_chg_func) (TDSSOCKET * tds, int type, char *oldval, char *newval);
	int internal_sp_called;

	void *tls_session;
	void *tls_credentials;
	TDSAUTHENTICATION *authentication;
	int option_value;
};

int tds_init_write_buf(TDSSOCKET * tds);
void tds_free_result_info(TDSRESULTINFO * info);
void tds_free_socket(TDSSOCKET * tds);
void tds_free_connection(TDSCONNECTION * connection);
void tds_free_all_results(TDSSOCKET * tds);
void tds_free_results(TDSRESULTINFO * res_info);
void tds_free_param_results(TDSPARAMINFO * param_info);
void tds_free_param_result(TDSPARAMINFO * param_info);
void tds_free_msg(TDSMESSAGE * message);
void tds_cursor_deallocated(TDSSOCKET *tds, TDSCURSOR *cursor);
void tds_release_cursor(TDSSOCKET *tds, TDSCURSOR *cursor);
void tds_free_bcp_column_data(BCPCOLDATA * coldata);

int tds_put_n(TDSSOCKET * tds, const void *buf, int n);
int tds_put_string(TDSSOCKET * tds, const char *buf, int len);
int tds_put_int(TDSSOCKET * tds, TDS_INT i);
int tds_put_int8(TDSSOCKET * tds, TDS_INT8 i);
int tds_put_smallint(TDSSOCKET * tds, TDS_SMALLINT si);
/** Output a tinyint value */
#define tds_put_tinyint(tds, ti) tds_put_byte(tds,ti)
int tds_put_byte(TDSSOCKET * tds, unsigned char c);
TDSRESULTINFO *tds_alloc_results(int num_cols);
TDSCOMPUTEINFO **tds_alloc_compute_results(TDSSOCKET * tds, int num_cols, int by_cols);
TDSCONTEXT *tds_alloc_context(void * parent);
void tds_free_context(TDSCONTEXT * locale);
TDSSOCKET *tds_alloc_socket(TDSCONTEXT * context, int bufsize);

/* config.c */
const TDS_COMPILETIME_SETTINGS *tds_get_compiletime_settings(void);
typedef void (*TDSCONFPARSE) (const char *option, const char *value, void *param);
int tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *parse_param);
int tds_read_conf_file(TDSCONNECTION * connection, const char *server);
TDSCONNECTION *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale);
void tds_fix_connection(TDSCONNECTION * connection);
void tds_config_verstr(const char *tdsver, TDSCONNECTION * connection);
void tds_lookup_host(const char *servername, char *ip);
int tds_set_interfaces_file_loc(const char *interfloc);

TDSLOCALE *tds_get_locale(void);
int tds_alloc_row(TDSRESULTINFO * res_info);
int tds_alloc_compute_row(TDSCOMPUTEINFO * res_info);
BCPCOLDATA * tds_alloc_bcp_column_data(int column_size);
unsigned char *tds7_crypt_pass(const unsigned char *clear_pass, int len, unsigned char *crypt_pass);
TDSDYNAMIC *tds_lookup_dynamic(TDSSOCKET * tds, char *id);
/*@observer@*/ const char *tds_prtype(int token);



/* iconv.c */
void tds_iconv_open(TDSSOCKET * tds, const char *charset);
void tds_iconv_close(TDSSOCKET * tds);
void tds_srv_charset_changed(TDSSOCKET * tds, const char *charset);
void tds7_srv_charset_changed(TDSSOCKET * tds, int sql_collate, int lcid);
int tds_iconv_alloc(TDSSOCKET * tds);
void tds_iconv_free(TDSSOCKET * tds);
TDSICONV *tds_iconv_from_collate(TDSSOCKET * tds, int sql_collate, int lcid);

/* threadsafe.c */
char *tds_timestamp_str(char *str, int maxlen);
struct hostent *tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop);
struct hostent *tds_gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result, char *buffer, int buflen,
				    int *h_errnop);
struct servent *tds_getservbyname_r(const char *name, const char *proto, struct servent *result, char *buffer, int buflen);
#ifdef INADDR_NONE
const char *tds_inet_ntoa_r(struct in_addr iaddr, char *ip, size_t len);
#endif
char *tds_get_homedir(void);

/* mem.c */
TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO * old_param);
void tds_free_input_params(TDSDYNAMIC * dyn);
void tds_free_dynamic(TDSSOCKET * tds, TDSDYNAMIC * dyn);
TDSSOCKET *tds_realloc_socket(TDSSOCKET * tds, int bufsize);
char *tds_alloc_client_sqlstate(int msgno);
char *tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno);
TDSLOGIN *tds_alloc_login(void);
TDSDYNAMIC *tds_alloc_dynamic(TDSSOCKET * tds, const char *id);
void tds_free_login(TDSLOGIN * login);
TDSCONNECTION *tds_alloc_connection(TDSLOCALE * locale);
TDSLOCALE *tds_alloc_locale(void);
void *tds_alloc_param_data(TDSCOLUMN * curparam);
void tds_free_locale(TDSLOCALE * locale);
TDSCURSOR * tds_alloc_cursor(TDSSOCKET * tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen);
void tds_free_row(TDSRESULTINFO * res_info, unsigned char *row);

/* login.c */
void tds_set_packet(TDSLOGIN * tds_login, int packet_size);
void tds_set_port(TDSLOGIN * tds_login, int port);
void tds_set_passwd(TDSLOGIN * tds_login, const char *password);
void tds_set_bulk(TDSLOGIN * tds_login, TDS_TINYINT enabled);
void tds_set_user(TDSLOGIN * tds_login, const char *username);
void tds_set_app(TDSLOGIN * tds_login, const char *application);
void tds_set_host(TDSLOGIN * tds_login, const char *hostname);
void tds_set_server_addr(TDSLOGIN * tds_login, const char *server_addr);
void tds_set_library(TDSLOGIN * tds_login, const char *library);
void tds_set_server(TDSLOGIN * tds_login, const char *server);
void tds_set_client_charset(TDSLOGIN * tds_login, const char *charset);
void tds_set_language(TDSLOGIN * tds_login, const char *language);
void tds_set_version(TDSLOGIN * tds_login, TDS_TINYINT major_ver, TDS_TINYINT minor_ver);
void tds_set_capabilities(TDSLOGIN * tds_login, unsigned char *capabilities, int size);
int tds_connect(TDSSOCKET * tds, TDSCONNECTION * connection);

/* query.c */
int tds_submit_query(TDSSOCKET * tds, const char *query);
int tds_submit_query_params(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params);
int tds_submit_queryf(TDSSOCKET * tds, const char *queryf, ...);
int tds_submit_prepare(TDSSOCKET * tds, const char *query, const char *id, TDSDYNAMIC ** dyn_out, TDSPARAMINFO * params);
int tds_submit_execdirect(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params);
int tds_submit_execute(TDSSOCKET * tds, TDSDYNAMIC * dyn);
int tds_send_cancel(TDSSOCKET * tds);
const char *tds_next_placeholder(const char *start);
int tds_count_placeholders(const char *query);
int tds_get_dynid(TDSSOCKET * tds, char **id);
int tds_submit_unprepare(TDSSOCKET * tds, TDSDYNAMIC * dyn);
int tds_submit_rpc(TDSSOCKET * tds, const char *rpc_name, TDSPARAMINFO * params);
int tds_submit_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD command, TDS_OPTION option, TDS_OPTION_ARG *param, TDS_INT param_size);
int tds_quote_id(TDSSOCKET * tds, char *buffer, const char *id, int idlen);
int tds_quote_string(TDSSOCKET * tds, char *buffer, const char *str, int len);
const char *tds_skip_quoted(const char *s);

int tds_cursor_declare(TDSSOCKET * tds, TDSCURSOR * cursor, TDSPARAMINFO *params, int *send);
int tds_cursor_setrows(TDSSOCKET * tds, TDSCURSOR * cursor, int *send);
int tds_cursor_open(TDSSOCKET * tds, TDSCURSOR * cursor, TDSPARAMINFO *params, int *send);
int tds_cursor_fetch(TDSSOCKET * tds, TDSCURSOR * cursor, TDS_CURSOR_FETCH fetch_type, TDS_INT i_row);
int tds_cursor_close(TDSSOCKET * tds, TDSCURSOR * cursor);
int tds_cursor_dealloc(TDSSOCKET * tds, TDSCURSOR * cursor);
int tds_cursor_update(TDSSOCKET * tds, TDSCURSOR * cursor, TDS_CURSOR_OPERATION op, TDS_INT i_row, TDSPARAMINFO * params);
int tds_cursor_setname(TDSSOCKET * tds, TDSCURSOR * cursor);

int tds_multiple_init(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDS_MULTIPLE_TYPE type);
int tds_multiple_done(TDSSOCKET *tds, TDSMULTIPLE *multiple);
int tds_multiple_query(TDSSOCKET *tds, TDSMULTIPLE *multiple, const char *query, TDSPARAMINFO * params);
int tds_multiple_execute(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDSDYNAMIC * dyn);

/* token.c */
int tds_process_cancel(TDSSOCKET * tds);
void tds_swap_datatype(int coltype, unsigned char *buf);
void tds_swap_numeric(TDS_NUMERIC *num);
int tds_get_token_size(int marker);
int tds_process_login_tokens(TDSSOCKET * tds);
int tds_process_simple_query(TDSSOCKET * tds);
int tds5_send_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD tds_command, TDS_OPTION tds_option, TDS_OPTION_ARG * tds_argument,
			TDS_INT * tds_argsize);
int tds_process_tokens(TDSSOCKET * tds, /*@out@*/ TDS_INT * result_type, /*@out@*/ int *done_flags, unsigned flag);

/* data.c */
void tds_set_param_type(TDSSOCKET * tds, TDSCOLUMN * curcol, TDS_SERVER_TYPE type);
void tds_set_column_type(TDSSOCKET * tds, TDSCOLUMN * curcol, int type);


/* tds_convert.c */
TDS_INT tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr);
int tds_get_conversion_type(int srctype, int colsize);
extern const char tds_hex_digits[];

/* write.c */
int tds_flush_packet(TDSSOCKET * tds);
int tds_put_buf(TDSSOCKET * tds, const unsigned char *buf, int dsize, int ssize);

/* read.c */
unsigned char tds_get_byte(TDSSOCKET * tds);
void tds_unget_byte(TDSSOCKET * tds);
unsigned char tds_peek(TDSSOCKET * tds);
TDS_SMALLINT tds_get_smallint(TDSSOCKET * tds);
TDS_INT tds_get_int(TDSSOCKET * tds);
TDS_INT8 tds_get_int8(TDSSOCKET * tds);
int tds_get_string(TDSSOCKET * tds, int string_len, char *dest, size_t dest_size);
int tds_get_char_data(TDSSOCKET * tds, char *dest, size_t wire_size, TDSCOLUMN * curcol);
void *tds_get_n(TDSSOCKET * tds, /*@out@*/ /*@null@*/ void *dest, int n);
int tds_get_size_by_type(int servertype);


/* util.c */
int tdserror (const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, int msgno, int errnum);
TDS_STATE tds_set_state(TDSSOCKET * tds, TDS_STATE state);
void tds_set_parent(TDSSOCKET * tds, void *the_parent);
void *tds_get_parent(TDSSOCKET * tds);
int tds_swap_bytes(unsigned char *buf, int bytes);
int tds_version(TDSSOCKET * tds_socket, char *pversion_string);
void tdsdump_off(void);
void tdsdump_on(void);
int tdsdump_open(const char *filename);
void tdsdump_close(void);
void tdsdump_dump_buf(const char* file, unsigned int level_line, const char *msg, const void *buf, int length);
void tdsdump_log(const char* file, unsigned int level_line, const char *fmt, ...) 
#if defined(__GNUC__) && __GNUC__ >= 2
	__attribute__ ((__format__ (__printf__, 3, 4)))
#endif
;
extern int tds_debug_flags;
unsigned int tds_gettime_ms(void);

/* net.c */
int tds_open_socket(TDSSOCKET * tds, const char *ip_addr, unsigned int port, int timeout);
int tds_close_socket(TDSSOCKET * tds);
int tds_read_packet(TDSSOCKET * tds);
int tds_write_packet(TDSSOCKET * tds, unsigned char final);
int tds7_get_instance_port(const char *ip_addr, const char *instance);
int tds_ssl_init(TDSSOCKET *tds);
void tds_ssl_deinit(TDSSOCKET *tds);



/* vstrbuild.c */
int tds_vstrbuild(char *buffer, int buflen, int *resultlen, char *text, int textlen, const char *formats, int formatlen,
		  va_list ap);

/* numeric.c */
char *tds_money_to_string(const TDS_MONEY * money, char *s);
TDS_INT tds_numeric_to_string(const TDS_NUMERIC * numeric, char *s);
TDS_INT tds_numeric_change_prec_scale(TDS_NUMERIC * numeric, unsigned char new_prec, unsigned char new_scale);

/* getmac.c */
void tds_getmac(int s, unsigned char mac[6]);

TDSAUTHENTICATION * tds_ntlm_get_auth(TDSSOCKET * tds);
TDSAUTHENTICATION * tds_gss_get_auth(TDSSOCKET * tds);

#define IS_TDS42(x) (x->major_version==4 && x->minor_version==2)
#define IS_TDS46(x) (x->major_version==4 && x->minor_version==6)
#define IS_TDS50(x) (x->major_version==5 && x->minor_version==0)
#define IS_TDS70(x) (x->major_version==7 && x->minor_version==0)
#define IS_TDS80(x) (x->major_version==8 && x->minor_version==0)
#define IS_TDS90(x) (x->major_version==9 && x->minor_version==0)

#define IS_TDS7_PLUS(x) ((x)->major_version>=7)
#define IS_TDS8_PLUS(x) ((x)->major_version>=8)

#define IS_TDSDEAD(x) (((x) == NULL) || TDS_IS_SOCKET_INVALID((x)->s))

/** Check if product is Sybase (such as Adaptive Server Enterrprice). x should be a TDS_SOCKET*. */
#define TDS_IS_SYBASE(x) (!(x->product_version & 0x80000000u))
/** Check if product is Microsft SQL Server. x should be a TDS_SOCKET*. */
#define TDS_IS_MSSQL(x) ((x->product_version & 0x80000000u)!=0)

/** Calc a version number for mssql. Use with TDS_MS_VER(7,0,842).
 * For test for a range of version you can use check like
 * if (tds->product_version >= TDS_MS_VER(7,0,0) && tds->product_version < TDS_MS_VER(8,0,0)) */
#define TDS_MS_VER(maj,min,x) (0x80000000u|((maj)<<24)|((min)<<16)|(x))

/* TODO test if not similar to ms one*/
/** Calc a version number for Sybase. */
#define TDS_SYB_VER(maj,min,x) (((maj)<<24)|((min)<<16)|(x)<<8)

#ifdef __cplusplus
#if 0
{
#endif
}
#endif

#endif /* _tds_h_ */