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