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
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 static char *
ecpg_strndup(const char * str,size_t len)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
deccvasc(const char * cp,int len,decimal * np)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
deccvdbl(double dbl,decimal * np)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
deccvint(int in,decimal * np)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
deccvlong(long lng,decimal * np)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
decdiv(decimal * n1,decimal * n2,decimal * result)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
decmul(decimal * n1,decimal * n2,decimal * result)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
decsub(decimal * n1,decimal * n2,decimal * result)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
dectoasc(decimal * np,char * cp,int len,int right)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
dectodbl(decimal * np,double * dblp)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
dectoint(decimal * np,int * ip)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
dectolong(decimal * np,long * lngp)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
rdatestr(date d,char * str)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
rstrdate(const char * str,date * d)523 rstrdate(const char *str, date * d)
524 {
525 	return rdefmtdate(d, "mm/dd/yyyy", str);
526 }
527 
528 void
rtoday(date * d)529 rtoday(date * d)
530 {
531 	PGTYPESdate_today(d);
532 	return;
533 }
534 
535 int
rjulmdy(date d,short * mdy)536 rjulmdy(date d, short *mdy)
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
rdefmtdate(date * d,const char * fmt,const char * str)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
rfmtdate(date d,const char * fmt,char * str)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
rmdyjul(short * mdy,date * d)587 rmdyjul(short *mdy, 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
rdayofweek(date d)599 rdayofweek(date d)
600 {
601 	return PGTYPESdate_dayofweek(d);
602 }
603 
604 /* And the datetime stuff */
605 
606 void
dtcurrent(timestamp * ts)607 dtcurrent(timestamp * ts)
608 {
609 	PGTYPEStimestamp_current(ts);
610 }
611 
612 int
dtcvasc(char * str,timestamp * ts)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
dtcvfmtasc(char * inbuf,char * fmtstr,timestamp * dtvalue)639 dtcvfmtasc(char *inbuf, char *fmtstr, timestamp * dtvalue)
640 {
641 	return PGTYPEStimestamp_defmt_asc(inbuf, fmtstr, dtvalue);
642 }
643 
644 int
dtsub(timestamp * ts1,timestamp * ts2,interval * iv)645 dtsub(timestamp * ts1, timestamp * ts2, interval * iv)
646 {
647 	return PGTYPEStimestamp_sub(ts1, ts2, iv);
648 }
649 
650 int
dttoasc(timestamp * ts,char * output)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
dttofmtasc(timestamp * ts,char * output,int str_len,char * fmtstr)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
intoasc(interval * i,char * str)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
initValue(long lng_val)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
getRightMostDot(const char * str)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
rfmtlong(long lng_val,const char * fmt,char * outbuf)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
rupshift(char * str)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
byleng(char * str,int len)971 byleng(char *str, int len)
972 {
973 	for (len--; str[len] && str[len] == ' '; len--);
974 	return (len + 1);
975 }
976 
977 void
ldchar(char * src,int len,char * dest)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
rgetmsg(int msgnum,char * s,int maxsize)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
rtypalign(int offset,int type)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
rtypmsize(int type,int len)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
rtypwidth(int sqltype,int sqllen)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
ECPG_informix_set_var(int number,void * pointer,int lineno)1020 ECPG_informix_set_var(int number, void *pointer, int lineno)
1021 {
1022 	ECPGset_var(number, pointer, lineno);
1023 }
1024 
1025 void *
ECPG_informix_get_var(int number)1026 ECPG_informix_get_var(int number)
1027 {
1028 	return ECPGget_var(number);
1029 }
1030 
1031 void
ECPG_informix_reset_sqlca(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
rsetnull(int t,char * ptr)1043 rsetnull(int t, char *ptr)
1044 {
1045 	ECPGset_noind_null(t, ptr);
1046 	return 0;
1047 }
1048 
1049 int
risnull(int t,const char * ptr)1050 risnull(int t, const char *ptr)
1051 {
1052 	return ECPGis_noind_null(t, ptr);
1053 }
1054