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