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