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