]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/compatlib/informix.c
- Added Dave patch for Informix handling of numeric/int conversion.
[postgresql] / src / interfaces / ecpg / compatlib / informix.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <math.h>
5 #include <ctype.h>
6
7 #include <ecpgtype.h>
8 #include <ecpg_informix.h>
9 #include <pgtypes_error.h>
10 #include <pgtypes_date.h>
11 #include <sqltypes.h>
12
13 char       *ECPGalloc(long, int);
14
15 static int
16 deccall2(decimal * arg1, decimal * arg2, int (*ptr) (numeric *, numeric *))
17 {
18         numeric    *a1,
19                            *a2;
20         int                     i;
21
22         if ((a1 = PGTYPESnumeric_new()) == NULL)
23                 return -1211;
24
25         if ((a2 = PGTYPESnumeric_new()) == NULL)
26         {
27                 PGTYPESnumeric_free(a1);
28                 return -1211;
29         }
30
31         if (PGTYPESnumeric_from_decimal(arg1, a1) != 0)
32         {
33                 PGTYPESnumeric_free(a1);
34                 PGTYPESnumeric_free(a2);
35                 return -1211;
36         }
37
38         if (PGTYPESnumeric_from_decimal(arg2, a2) != 0)
39         {
40                 PGTYPESnumeric_free(a1);
41                 PGTYPESnumeric_free(a2);
42                 return -1211;
43         }
44
45         i = (*ptr) (a1, a2);
46
47         PGTYPESnumeric_free(a1);
48         PGTYPESnumeric_free(a2);
49
50         return (i);
51 }
52
53 static int
54 deccall3(decimal * arg1, decimal * arg2, decimal * result, int (*ptr) (numeric *, numeric *, numeric *))
55 {
56         numeric    *a1,
57                            *a2,
58                            *nres;
59         int                     i;
60
61         if (risnull(CDECIMALTYPE, (char *) arg1) || risnull(CDECIMALTYPE, (char *) arg2))
62         {
63                 rsetnull(CDECIMALTYPE, (char *) result);
64                 return 0;
65         }
66
67         if ((a1 = PGTYPESnumeric_new()) == NULL)
68                 return -1211;
69
70         if ((a2 = PGTYPESnumeric_new()) == NULL)
71         {
72                 PGTYPESnumeric_free(a1);
73                 return -1211;
74         }
75
76         if ((nres = PGTYPESnumeric_new()) == NULL)
77         {
78                 PGTYPESnumeric_free(a1);
79                 PGTYPESnumeric_free(a2);
80                 return -1211;
81         }
82
83         if (PGTYPESnumeric_from_decimal(arg1, a1) != 0)
84         {
85                 PGTYPESnumeric_free(a1);
86                 PGTYPESnumeric_free(a2);
87                 PGTYPESnumeric_free(nres);
88                 return -1211;
89         }
90
91         if (PGTYPESnumeric_from_decimal(arg2, a2) != 0)
92         {
93                 PGTYPESnumeric_free(a1);
94                 PGTYPESnumeric_free(a2);
95                 PGTYPESnumeric_free(nres);
96                 return -1211;
97         }
98
99         i = (*ptr) (a1, a2, nres);
100
101         if (i == 0)                                     /* No error */
102                 PGTYPESnumeric_to_decimal(nres, result);
103
104         PGTYPESnumeric_free(nres);
105         PGTYPESnumeric_free(a1);
106         PGTYPESnumeric_free(a2);
107
108         return (i);
109 }
110
111 /* we start with the numeric functions */
112 int
113 decadd(decimal * arg1, decimal * arg2, decimal * sum)
114 {
115         deccall3(arg1, arg2, sum, PGTYPESnumeric_add);
116
117         if (errno == PGTYPES_NUM_OVERFLOW)
118                 return -1200;
119         else if (errno != 0)
120                 return -1201;
121         else
122                 return 0;
123 }
124
125 int
126 deccmp(decimal * arg1, decimal * arg2)
127 {
128         return (deccall2(arg1, arg2, PGTYPESnumeric_cmp));
129 }
130
131 void
132 deccopy(decimal * src, decimal * target)
133 {
134         memcpy(target, src, sizeof(decimal));
135 }
136
137 static char *
138 strndup(const char *str, size_t len)
139 {
140         int                     real_len = strlen(str);
141         int                     use_len = (real_len > len) ? len : real_len;
142
143         char       *new = malloc(use_len + 1);
144
145         if (new)
146         {
147                 memcpy(new, str, use_len);
148                 new[use_len] = '\0';
149         }
150         else
151                 errno = ENOMEM;
152
153         return new;
154 }
155
156 int
157 deccvasc(char *cp, int len, decimal * np)
158 {
159         char       *str = strndup(cp, len); /* decimal_in always converts the
160                                                                                  * complete string */
161         int                     ret = 0;
162         numeric    *result;
163
164         if (risnull(CSTRINGTYPE, cp))
165         {
166                 rsetnull(CDECIMALTYPE, (char *) np);
167                 return 0;
168         }
169
170         if (!str)
171                 ret = -1201;
172         else
173         {
174                 result = PGTYPESnumeric_from_asc(str, NULL);
175                 if (!result)
176                 {
177                         switch (errno)
178                         {
179                                 case PGTYPES_NUM_OVERFLOW:
180                                         ret = -1200;
181                                         break;
182                                 case PGTYPES_NUM_BAD_NUMERIC:
183                                         ret = -1213;
184                                         break;
185                                 default:
186                                         ret = -1216;
187                                         break;
188                         }
189                 }
190                 else
191                 {
192                         if (PGTYPESnumeric_to_decimal(result, np) != 0)
193                                 ret = -1200;
194
195                         free(result);
196                 }
197         }
198
199         free(str);
200         return ret;
201 }
202
203 int
204 deccvdbl(double dbl, decimal * np)
205 {
206         numeric    *nres = PGTYPESnumeric_new();
207         int                     result = 1;
208
209         if (risnull(CDOUBLETYPE, (char *) &dbl))
210         {
211                 rsetnull(CDECIMALTYPE, (char *) np);
212                 return 0;
213         }
214
215         if (nres == NULL)
216                 return -1211;
217
218         result = PGTYPESnumeric_from_double(dbl, nres);
219         if (result == 0)
220                 result = PGTYPESnumeric_to_decimal(nres, np);
221
222         PGTYPESnumeric_free(nres);
223         return (result);
224 }
225
226 int
227 deccvint(int in, decimal * np)
228 {
229         numeric    *nres = PGTYPESnumeric_new();
230         int                     result = 1;
231
232         if (risnull(CINTTYPE, (char *) &in))
233         {
234                 rsetnull(CDECIMALTYPE, (char *) np);
235                 return 0;
236         }
237
238         if (nres == NULL)
239                 return -1211;
240
241         result = PGTYPESnumeric_from_int(in, nres);
242         if (result == 0)
243                 result = PGTYPESnumeric_to_decimal(nres, np);
244
245         PGTYPESnumeric_free(nres);
246         return (result);
247 }
248
249 int
250 deccvlong(long lng, decimal * np)
251 {
252         numeric    *nres = PGTYPESnumeric_new();
253         int                     result = 1;
254
255         if (risnull(CLONGTYPE, (char *) &lng))
256         {
257                 rsetnull(CDECIMALTYPE, (char *) np);
258                 return 0;
259         }
260
261         if (nres == NULL)
262                 return -1211;
263
264         result = PGTYPESnumeric_from_long(lng, nres);
265         if (result == 0)
266                 result = PGTYPESnumeric_to_decimal(nres, np);
267
268         PGTYPESnumeric_free(nres);
269         return (result);
270 }
271
272 int
273 decdiv(decimal * n1, decimal * n2, decimal * n3)
274 {
275         int                     i = deccall3(n1, n2, n3, PGTYPESnumeric_div);
276
277         if (i != 0)
278                 switch (errno)
279                 {
280                         case PGTYPES_NUM_DIVIDE_ZERO:
281                                 return -1202;
282                                 break;
283                         case PGTYPES_NUM_OVERFLOW:
284                                 return -1200;
285                                 break;
286                         default:
287                                 return -1201;
288                                 break;
289                 }
290
291         return 0;
292 }
293
294 int
295 decmul(decimal * n1, decimal * n2, decimal * n3)
296 {
297         int                     i = deccall3(n1, n2, n3, PGTYPESnumeric_mul);
298
299         if (i != 0)
300                 switch (errno)
301                 {
302                         case PGTYPES_NUM_OVERFLOW:
303                                 return -1200;
304                                 break;
305                         default:
306                                 return -1201;
307                                 break;
308                 }
309
310         return 0;
311 }
312
313 int
314 decsub(decimal * n1, decimal * n2, decimal * n3)
315 {
316         int                     i = deccall3(n1, n2, n3, PGTYPESnumeric_sub);
317
318         if (i != 0)
319                 switch (errno)
320                 {
321                         case PGTYPES_NUM_OVERFLOW:
322                                 return -1200;
323                                 break;
324                         default:
325                                 return -1201;
326                                 break;
327                 }
328
329         return 0;
330 }
331
332 int
333 dectoasc(decimal * np, char *cp, int len, int right)
334 {
335         char       *str;
336         numeric    *nres = PGTYPESnumeric_new();
337
338         if (nres == NULL)
339                 return -1211;
340
341         if (risnull(CDECIMALTYPE, (char *) np))
342         {
343                 rsetnull(CSTRINGTYPE, (char *) cp);
344                 return 0;
345         }
346
347         if (PGTYPESnumeric_from_decimal(np, nres) != 0)
348                 return -1211;
349
350         if (right >= 0)
351                 str = PGTYPESnumeric_to_asc(nres, right);
352         else
353                 str = PGTYPESnumeric_to_asc(nres, 0);
354
355         PGTYPESnumeric_free(nres);
356         if (!str)
357                 return -1;
358
359         /*
360          * TODO: have to take care of len here and create exponatial notion if
361          * necessary
362          */
363         strncpy(cp, str, len);
364         free(str);
365
366         return 0;
367 }
368
369 int
370 dectodbl(decimal * np, double *dblp)
371 {
372         numeric    *nres = PGTYPESnumeric_new();
373         int                     i;
374
375         if (nres == NULL)
376                 return -1211;
377
378         if (PGTYPESnumeric_from_decimal(np, nres) != 0)
379                 return -1211;
380
381         i = PGTYPESnumeric_to_double(nres, dblp);
382         PGTYPESnumeric_free(nres);
383
384         return i;
385 }
386
387 int
388 dectoint(decimal * np, int *ip)
389 {
390         int                     ret;
391         numeric    *nres = PGTYPESnumeric_new();
392
393         if (nres == NULL)
394                 return -1211;
395
396         if (PGTYPESnumeric_from_decimal(np, nres) != 0)
397                 return -1211;
398
399         ret = PGTYPESnumeric_to_int(nres, ip);
400
401         if (ret == PGTYPES_NUM_OVERFLOW)
402                 ret = -1200;
403
404         return ret;
405 }
406
407 int
408 dectolong(decimal * np, long *lngp)
409 {
410         int                     ret;
411         numeric    *nres = PGTYPESnumeric_new();;
412
413         if (nres == NULL)
414                 return -1211;
415
416         if (PGTYPESnumeric_from_decimal(np, nres) != 0)
417                 return -1211;
418
419         ret = PGTYPESnumeric_to_long(nres, lngp);
420
421         if (ret == PGTYPES_NUM_OVERFLOW)
422                 ret = -1200;
423
424         return ret;
425 }
426
427 /* Now the date functions */
428 int
429 rdatestr(Date d, char *str)
430 {
431         char       *tmp = PGTYPESdate_to_asc(d);
432
433         if (!tmp)
434                 return -1210;
435
436         /* move to user allocated buffer */
437         strcpy(str, tmp);
438         free(tmp);
439
440         return 0;
441 }
442
443 int
444 rstrdate(char *str, Date * d)
445 {
446         Date            dat = PGTYPESdate_from_asc(str, NULL);
447
448         if (errno != PGTYPES_DATE_BAD_DATE && dat == 0)
449                 return -1218;
450
451         *d = dat;
452         return 0;
453 }
454
455 void
456 rtoday(Date * d)
457 {
458         PGTYPESdate_today(d);
459         return;
460 }
461
462 int
463 rjulmdy(Date d, short mdy[3])
464 {
465         int                     mdy_int[3];
466
467         PGTYPESdate_julmdy(d, mdy_int);
468         mdy[0] = (short) mdy_int[0];
469         mdy[1] = (short) mdy_int[1];
470         mdy[2] = (short) mdy_int[2];
471         return 0;
472 }
473
474 int
475 rdefmtdate(Date * d, char *fmt, char *str)
476 {
477         /* TODO: take care of DBCENTURY environment variable */
478         /* PGSQL functions allow all centuries */
479
480         if (PGTYPESdate_defmt_asc(d, fmt, str) == 0)
481                 return 0;
482
483         switch (errno)
484         {
485                 case PGTYPES_DATE_ERR_ENOSHORTDATE:
486                         return -1209;
487                 case PGTYPES_DATE_ERR_EARGS:
488                 case PGTYPES_DATE_ERR_ENOTDMY:
489                         return -1212;
490                 case PGTYPES_DATE_BAD_DAY:
491                         return -1204;
492                 case PGTYPES_DATE_BAD_MONTH:
493                         return -1205;
494                 default:
495                         return -1206;
496         }
497 }
498
499 int
500 rfmtdate(Date d, char *fmt, char *str)
501 {
502         if (PGTYPESdate_fmt_asc(d, fmt, str) == 0)
503                 return 0;
504
505         if (errno == ENOMEM)
506                 return -1211;
507
508         return -1210;
509 }
510
511 int
512 rmdyjul(short mdy[3], Date * d)
513 {
514         int                     mdy_int[3];
515
516         mdy_int[0] = mdy[0];
517         mdy_int[1] = mdy[1];
518         mdy_int[2] = mdy[2];
519         PGTYPESdate_mdyjul(mdy_int, d);
520         return 0;
521 }
522
523 int
524 rdayofweek(Date d)
525 {
526         return (PGTYPESdate_dayofweek(d));
527 }
528
529 /* And the datetime stuff */
530
531 void
532 dtcurrent(timestamp *ts)
533 {
534         PGTYPEStimestamp_current(ts);
535 }
536
537 int
538 dtcvasc(char *str, timestamp *ts)
539 {
540         timestamp       ts_tmp;
541         int                     i;
542         char      **endptr = &str;
543
544         ts_tmp = PGTYPEStimestamp_from_asc(str, endptr);
545         i = errno;
546         if (i)
547                 return i;
548         if (**endptr)
549         {
550                 /* extra characters exist at the end */
551                 return -1264;
552         }
553
554         /* everything went fine */
555         *ts = ts_tmp;
556
557         return 0;
558 }
559
560 int
561 dtsub(timestamp *ts1, timestamp *ts2, interval *iv)
562 {
563         return PGTYPEStimestamp_sub(ts1, ts2, iv);
564 }
565
566 int
567 dttoasc(timestamp *ts, char *output)
568 {
569         char       *asctime = PGTYPEStimestamp_to_asc(*ts);
570
571         strcpy(output, asctime);
572         free(asctime);
573         return 0;
574 }
575
576 int
577 dttofmtasc(timestamp *ts, char *output, int str_len, char *fmtstr)
578 {
579         return PGTYPEStimestamp_fmt_asc(ts, output, str_len, fmtstr);
580 }
581
582 int
583 intoasc(interval *i, char *str)
584 {
585         str = PGTYPESinterval_to_asc(i);
586
587         if (!str)
588                 return -errno;
589
590         return 0;
591 }
592
593 /***************************************************************************
594                                                   rfmt.c  -  description
595                                                          -------------------
596         begin                            : Wed Apr 2 2003
597         copyright                        : (C) 2003 by Carsten Wolff
598         email                            : carsten.wolff@credativ.de
599  ***************************************************************************/
600
601 static struct
602 {
603         long            val;
604         int                     maxdigits;
605         int                     digits;
606         int                     remaining;
607         char            sign;
608         char       *val_string;
609 }       value;
610
611 /**
612  * initialize the struct, wich holds the different forms
613  * of the long value
614  */
615 static void
616 initValue(long lng_val)
617 {
618         int                     i,
619                                 div,
620                                 dig;
621         char            tmp[2] = " ";
622
623         /* set some obvious things */
624         value.val = lng_val >= 0 ? lng_val : lng_val * (-1);
625         value.sign = lng_val >= 0 ? '+' : '-';
626         value.maxdigits = log10(2) * (8 * sizeof(long) - 1);
627
628         /* determine the number of digits */
629         for (i = 1; i <= value.maxdigits; i++)
630         {
631                 if ((int) (value.val / pow(10, i)) != 0)
632                         value.digits = i + 1;
633         }
634         value.remaining = value.digits;
635
636         /* convert the long to string */
637         value.val_string = (char *) malloc(value.digits + 1);
638         for (i = value.digits; i > 0; i--)
639         {
640                 div = pow(10, i);
641                 dig = (value.val % div) / (div / 10);
642                 tmp[0] = (char) (dig + 48);
643                 strcat(value.val_string, tmp);
644         }
645         /* safety-net */
646         value.val_string[value.digits] = '\0';
647         /* clean up */
648         free(tmp);
649 }
650
651 /* return the position oft the right-most dot in some string */
652 static int
653 getRightMostDot(char *str)
654 {
655         size_t          len = strlen(str);
656         int                     i,
657                                 j;
658
659         j = 0;
660         for (i = len - 1; i >= 0; i--)
661         {
662                 if (str[i] == '.')
663                         return len - j - 1;
664                 j++;
665         }
666         return -1;
667 }
668
669 /* And finally some misc functions */
670 int
671 rfmtlong(long lng_val, char *fmt, char *outbuf)
672 {
673         size_t          fmt_len = strlen(fmt);
674         size_t          temp_len;
675         int                     i,
676                                 j,
677                                 k,
678                                 dotpos;
679         int                     leftalign = 0,
680                                 blank = 0,
681                                 sign = 0,
682                                 entity = 0,
683                                 entitydone = 0,
684                                 signdone = 0,
685                                 brackets_ok = 0;
686         char       *temp;
687         char            tmp[2] = " ";
688         char            lastfmt = ' ',
689                                 fmtchar = ' ';
690
691         temp = (char *) malloc(fmt_len + 1);
692
693         /* put all info about the long in a struct */
694         initValue(lng_val);
695
696         /* '<' is the only format, where we have to align left */
697         if (strchr(fmt, (int) '<'))
698                 leftalign = 1;
699
700         /* '(' requires ')' */
701         if (strchr(fmt, (int) '(') && strchr(fmt, (int) ')'))
702                 brackets_ok = 1;
703
704         /* get position of the right-most dot in the format-string */
705         /* and fill the temp-string wit '0's up to there. */
706         dotpos = getRightMostDot(fmt);
707
708         /* start to parse the formatstring */
709         temp[0] = '\0';
710         j = 0;                                          /* position in temp */
711         k = value.digits - 1;           /* position in the value_string */
712         for (i = fmt_len - 1, j = 0; i >= 0; i--, j++)
713         {
714                 /* qualify, where we are in the value_string */
715                 if (k < 0)
716                 {
717                         if (leftalign)
718                         {
719                                 /* can't use strncat(,,0) here, Solaris would freek out */
720                                 temp[j] = '\0';
721                                 break;
722                         }
723                         blank = 1;
724                         if (k == -2)
725                                 entity = 1;
726                         else if (k == -1)
727                                 sign = 1;
728                 }
729                 /* if we're right side of the right-most dot, print '0' */
730                 if (dotpos >= 0 && dotpos <= i)
731                 {
732                         if (dotpos < i)
733                         {
734                                 if (fmt[i] == ')')
735                                         tmp[0] = value.sign == '-' ? ')' : ' ';
736                                 else
737                                         tmp[0] = '0';
738                         }
739                         else
740                                 tmp[0] = '.';
741                         strcat(temp, tmp);
742                         continue;
743                 }
744                 /* the ',' needs special attention, if it is in the blank area */
745                 if (blank && fmt[i] == ',')
746                         fmtchar = lastfmt;
747                 else
748                         fmtchar = fmt[i];
749                 /* analyse this format-char */
750                 switch (fmtchar)
751                 {
752                         case ',':
753                                 tmp[0] = ',';
754                                 k++;
755                                 break;
756                         case '*':
757                                 if (blank)
758                                         tmp[0] = '*';
759                                 else
760                                         tmp[0] = value.val_string[k];
761                                 break;
762                         case '&':
763                                 if (blank)
764                                         tmp[0] = '0';
765                                 else
766                                         tmp[0] = value.val_string[k];
767                                 break;
768                         case '#':
769                                 if (blank)
770                                         tmp[0] = ' ';
771                                 else
772                                         tmp[0] = value.val_string[k];
773                                 break;
774                         case '<':
775                                 tmp[0] = value.val_string[k];
776                                 break;
777                         case '-':
778                                 if (sign && value.sign == '-' && !signdone)
779                                 {
780                                         tmp[0] = '-';
781                                         signdone = 1;
782                                 }
783                                 else if (blank)
784                                         tmp[0] = ' ';
785                                 else
786                                         tmp[0] = value.val_string[k];
787                                 break;
788                         case '+':
789                                 if (sign && !signdone)
790                                 {
791                                         tmp[0] = value.sign;
792                                         signdone = 1;
793                                 }
794                                 else if (blank)
795                                         tmp[0] = ' ';
796                                 else
797                                         tmp[0] = value.val_string[k];
798                                 break;
799                         case '(':
800                                 if (sign && brackets_ok && value.sign == '-')
801                                         tmp[0] = '(';
802                                 else if (blank)
803                                         tmp[0] = ' ';
804                                 else
805                                         tmp[0] = value.val_string[k];
806                                 break;
807                         case ')':
808                                 if (brackets_ok && value.sign == '-')
809                                         tmp[0] = ')';
810                                 else
811                                         tmp[0] = ' ';
812                                 break;
813                         case '$':
814                                 if (blank && !entitydone)
815                                 {
816                                         tmp[0] = '$';
817                                         entitydone = 1;
818                                 }
819                                 else if (blank)
820                                         tmp[0] = ' ';
821                                 else
822                                         tmp[0] = value.val_string[k];
823                                 break;
824                         default:
825                                 tmp[0] = fmt[i];
826                 }
827                 strcat(temp, tmp);
828                 lastfmt = fmt[i];
829                 k--;
830         }
831         /* safety-net */
832         temp[fmt_len] = '\0';
833
834         /* reverse the temp-string and put it into the outbuf */
835         temp_len = strlen(temp);
836         outbuf[0] = '\0';
837         for (i = temp_len - 1; i >= 0; i--)
838         {
839                 tmp[0] = temp[i];
840                 strcat(outbuf, tmp);
841         }
842         outbuf[temp_len] = '\0';
843
844         /* cleaning up */
845         free(temp);
846         free(value.val_string);
847
848         return 0;
849 }
850
851 void
852 rupshift(char *str)
853 {
854         for (; *str != '\0'; str++)
855                 if (islower(*str))
856                         *str = toupper(*str);
857         return;
858 }
859
860 int
861 byleng(char *str, int len)
862 {
863         for (len--; str[len] && str[len] == ' '; len--);
864         return (len + 1);
865 }
866
867 void
868 ldchar(char *src, int len, char *dest)
869 {
870         memmove(dest, src, len);
871         dest[len] = 0;
872 }
873
874 int
875 rgetmsg(int msgnum, char *s, int maxsize)
876 {
877         return 0;
878 }
879
880 int
881 rtypalign(int offset, int type)
882 {
883         return 0;
884 }
885
886 int
887 rtypmsize(int type, int len)
888 {
889         return 0;
890 }
891
892 int
893 rtypwidth(int sqltype, int sqllen)
894 {
895         return 0;
896 }
897
898 int
899 dtcvfmtasc(char *inbuf, char *fmtstr, dtime_t * dtvalue)
900 {
901         return PGTYPEStimestamp_defmt_asc(inbuf, fmtstr, dtvalue);
902 }
903
904 static struct var_list
905 {
906         int                     number;
907         void       *pointer;
908         struct var_list *next;
909 }       *ivlist = NULL;
910
911 void
912 ECPG_informix_set_var(int number, void *pointer, int lineno)
913 {
914         struct var_list *ptr;
915
916         for (ptr = ivlist; ptr != NULL; ptr = ptr->next)
917         {
918                 if (ptr->number == number)
919                 {
920                         /* already known => just change pointer value */
921                         ptr->pointer = pointer;
922                         return;
923                 }
924         }
925
926         /* a new one has to be added */
927         ptr = (struct var_list *) ECPGalloc(sizeof(struct var_list), lineno);
928         ptr->number = number;
929         ptr->pointer = pointer;
930         ptr->next = ivlist;
931         ivlist = ptr;
932 }
933
934 void *
935 ECPG_informix_get_var(int number)
936 {
937         struct var_list *ptr;
938
939         for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next);
940         return (ptr) ? ptr->pointer : NULL;
941 }
942
943 int
944 rsetnull(int t, char *ptr)
945 {
946         ECPGset_informix_null(t, ptr);
947         return 0;
948 }
949
950 int
951 risnull(int t, char *ptr)
952 {
953         return (ECPGis_informix_null(t, ptr));
954 }