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