Header And Logo

PostgreSQL
| The world's most advanced open source database.

informix.c

Go to the documentation of this file.
00001 /* src/interfaces/ecpg/compatlib/informix.c */
00002 
00003 #define POSTGRES_ECPG_INTERNAL
00004 #include "postgres_fe.h"
00005 
00006 #include <math.h>
00007 #include <ctype.h>
00008 #include <limits.h>
00009 
00010 #include <ecpgtype.h>
00011 #include <ecpg_informix.h>
00012 #include <pgtypes_error.h>
00013 #include <pgtypes_date.h>
00014 #include <pgtypes_numeric.h>
00015 #include <sqltypes.h>
00016 #include <sqlca.h>
00017 #include <ecpgerrno.h>
00018 
00019 /* this is also defined in ecpglib/misc.c, by defining it twice we don't have to export the symbol */
00020 
00021 static struct sqlca_t sqlca_init =
00022 {
00023     {
00024         'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
00025     },
00026     sizeof(struct sqlca_t),
00027     0,
00028     {
00029         0,
00030         {
00031             0
00032         }
00033     },
00034     {
00035         'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
00036     },
00037     {
00038         0, 0, 0, 0, 0, 0
00039     },
00040     {
00041         0, 0, 0, 0, 0, 0, 0, 0
00042     },
00043     {
00044         '0', '0', '0', '0', '0'
00045     }
00046 };
00047 static int
00048 deccall2(decimal *arg1, decimal *arg2, int (*ptr) (numeric *, numeric *))
00049 {
00050     numeric    *a1,
00051                *a2;
00052     int         i;
00053 
00054     if ((a1 = PGTYPESnumeric_new()) == NULL)
00055         return ECPG_INFORMIX_OUT_OF_MEMORY;
00056 
00057     if ((a2 = PGTYPESnumeric_new()) == NULL)
00058     {
00059         PGTYPESnumeric_free(a1);
00060         return ECPG_INFORMIX_OUT_OF_MEMORY;
00061     }
00062 
00063     if (PGTYPESnumeric_from_decimal(arg1, a1) != 0)
00064     {
00065         PGTYPESnumeric_free(a1);
00066         PGTYPESnumeric_free(a2);
00067         return ECPG_INFORMIX_OUT_OF_MEMORY;
00068     }
00069 
00070     if (PGTYPESnumeric_from_decimal(arg2, a2) != 0)
00071     {
00072         PGTYPESnumeric_free(a1);
00073         PGTYPESnumeric_free(a2);
00074         return ECPG_INFORMIX_OUT_OF_MEMORY;
00075     }
00076 
00077     i = (*ptr) (a1, a2);
00078 
00079     PGTYPESnumeric_free(a1);
00080     PGTYPESnumeric_free(a2);
00081 
00082     return (i);
00083 }
00084 
00085 static int
00086 deccall3(decimal *arg1, decimal *arg2, decimal *result, int (*ptr) (numeric *, numeric *, numeric *))
00087 {
00088     numeric    *a1,
00089                *a2,
00090                *nres;
00091     int         i;
00092 
00093     /*
00094      * we must NOT set the result to NULL here because it may be the same
00095      * variable as one of the arguments
00096      */
00097     if (risnull(CDECIMALTYPE, (char *) arg1) || risnull(CDECIMALTYPE, (char *) arg2))
00098         return 0;
00099 
00100     if ((a1 = PGTYPESnumeric_new()) == NULL)
00101         return ECPG_INFORMIX_OUT_OF_MEMORY;
00102 
00103     if ((a2 = PGTYPESnumeric_new()) == NULL)
00104     {
00105         PGTYPESnumeric_free(a1);
00106         return ECPG_INFORMIX_OUT_OF_MEMORY;
00107     }
00108 
00109     if ((nres = PGTYPESnumeric_new()) == NULL)
00110     {
00111         PGTYPESnumeric_free(a1);
00112         PGTYPESnumeric_free(a2);
00113         return ECPG_INFORMIX_OUT_OF_MEMORY;
00114     }
00115 
00116     if (PGTYPESnumeric_from_decimal(arg1, a1) != 0)
00117     {
00118         PGTYPESnumeric_free(a1);
00119         PGTYPESnumeric_free(a2);
00120         PGTYPESnumeric_free(nres);
00121         return ECPG_INFORMIX_OUT_OF_MEMORY;
00122     }
00123 
00124     if (PGTYPESnumeric_from_decimal(arg2, a2) != 0)
00125     {
00126         PGTYPESnumeric_free(a1);
00127         PGTYPESnumeric_free(a2);
00128         PGTYPESnumeric_free(nres);
00129         return ECPG_INFORMIX_OUT_OF_MEMORY;
00130     }
00131 
00132     i = (*ptr) (a1, a2, nres);
00133 
00134     if (i == 0)                 /* No error */
00135     {
00136 
00137         /* set the result to null in case it errors out later */
00138         rsetnull(CDECIMALTYPE, (char *) result);
00139         PGTYPESnumeric_to_decimal(nres, result);
00140     }
00141 
00142     PGTYPESnumeric_free(nres);
00143     PGTYPESnumeric_free(a1);
00144     PGTYPESnumeric_free(a2);
00145 
00146     return (i);
00147 }
00148 
00149 /* we start with the numeric functions */
00150 int
00151 decadd(decimal *arg1, decimal *arg2, decimal *sum)
00152 {
00153     errno = 0;
00154     deccall3(arg1, arg2, sum, PGTYPESnumeric_add);
00155 
00156     if (errno == PGTYPES_NUM_OVERFLOW)
00157         return ECPG_INFORMIX_NUM_OVERFLOW;
00158     else if (errno == PGTYPES_NUM_UNDERFLOW)
00159         return ECPG_INFORMIX_NUM_UNDERFLOW;
00160     else if (errno != 0)
00161         return -1;
00162     else
00163         return 0;
00164 }
00165 
00166 int
00167 deccmp(decimal *arg1, decimal *arg2)
00168 {
00169     return (deccall2(arg1, arg2, PGTYPESnumeric_cmp));
00170 }
00171 
00172 void
00173 deccopy(decimal *src, decimal *target)
00174 {
00175     memcpy(target, src, sizeof(decimal));
00176 }
00177 
00178 static char *
00179 ecpg_strndup(const char *str, size_t len)
00180 {
00181     size_t      real_len = strlen(str);
00182     int         use_len = (int) ((real_len > len) ? len : real_len);
00183 
00184     char       *new = malloc(use_len + 1);
00185 
00186     if (new)
00187     {
00188         memcpy(new, str, use_len);
00189         new[use_len] = '\0';
00190     }
00191     else
00192         errno = ENOMEM;
00193 
00194     return new;
00195 }
00196 
00197 int
00198 deccvasc(char *cp, int len, decimal *np)
00199 {
00200     char       *str;
00201     int         ret = 0;
00202     numeric    *result;
00203 
00204     rsetnull(CDECIMALTYPE, (char *) np);
00205     if (risnull(CSTRINGTYPE, cp))
00206         return 0;
00207 
00208     str = ecpg_strndup(cp, len);/* decimal_in always converts the complete
00209                                  * string */
00210     if (!str)
00211         ret = ECPG_INFORMIX_NUM_UNDERFLOW;
00212     else
00213     {
00214         errno = 0;
00215         result = PGTYPESnumeric_from_asc(str, NULL);
00216         if (!result)
00217         {
00218             switch (errno)
00219             {
00220                 case PGTYPES_NUM_OVERFLOW:
00221                     ret = ECPG_INFORMIX_NUM_OVERFLOW;
00222                     break;
00223                 case PGTYPES_NUM_BAD_NUMERIC:
00224                     ret = ECPG_INFORMIX_BAD_NUMERIC;
00225                     break;
00226                 default:
00227                     ret = ECPG_INFORMIX_BAD_EXPONENT;
00228                     break;
00229             }
00230         }
00231         else
00232         {
00233             int         i = PGTYPESnumeric_to_decimal(result, np);
00234 
00235             PGTYPESnumeric_free(result);
00236             if (i != 0)
00237                 ret = ECPG_INFORMIX_NUM_OVERFLOW;
00238         }
00239     }
00240 
00241     free(str);
00242     return ret;
00243 }
00244 
00245 int
00246 deccvdbl(double dbl, decimal *np)
00247 {
00248     numeric    *nres;
00249     int         result = 1;
00250 
00251     rsetnull(CDECIMALTYPE, (char *) np);
00252     if (risnull(CDOUBLETYPE, (char *) &dbl))
00253         return 0;
00254 
00255     nres = PGTYPESnumeric_new();
00256     if (nres == NULL)
00257         return ECPG_INFORMIX_OUT_OF_MEMORY;
00258 
00259     result = PGTYPESnumeric_from_double(dbl, nres);
00260     if (result == 0)
00261         result = PGTYPESnumeric_to_decimal(nres, np);
00262 
00263     PGTYPESnumeric_free(nres);
00264     return (result);
00265 }
00266 
00267 int
00268 deccvint(int in, decimal *np)
00269 {
00270     numeric    *nres;
00271     int         result = 1;
00272 
00273     rsetnull(CDECIMALTYPE, (char *) np);
00274     if (risnull(CINTTYPE, (char *) &in))
00275         return 0;
00276 
00277     nres = PGTYPESnumeric_new();
00278     if (nres == NULL)
00279         return ECPG_INFORMIX_OUT_OF_MEMORY;
00280 
00281     result = PGTYPESnumeric_from_int(in, nres);
00282     if (result == 0)
00283         result = PGTYPESnumeric_to_decimal(nres, np);
00284 
00285     PGTYPESnumeric_free(nres);
00286     return (result);
00287 }
00288 
00289 int
00290 deccvlong(long lng, decimal *np)
00291 {
00292     numeric    *nres;
00293     int         result = 1;
00294 
00295     rsetnull(CDECIMALTYPE, (char *) np);
00296     if (risnull(CLONGTYPE, (char *) &lng))
00297         return 0;
00298 
00299     nres = PGTYPESnumeric_new();
00300     if (nres == NULL)
00301         return ECPG_INFORMIX_OUT_OF_MEMORY;
00302 
00303     result = PGTYPESnumeric_from_long(lng, nres);
00304     if (result == 0)
00305         result = PGTYPESnumeric_to_decimal(nres, np);
00306 
00307     PGTYPESnumeric_free(nres);
00308     return (result);
00309 }
00310 
00311 int
00312 decdiv(decimal *n1, decimal *n2, decimal *result)
00313 {
00314 
00315     int         i;
00316 
00317     errno = 0;
00318     i = deccall3(n1, n2, result, PGTYPESnumeric_div);
00319 
00320     if (i != 0)
00321         switch (errno)
00322         {
00323             case PGTYPES_NUM_DIVIDE_ZERO:
00324                 return ECPG_INFORMIX_DIVIDE_ZERO;
00325                 break;
00326             case PGTYPES_NUM_OVERFLOW:
00327                 return ECPG_INFORMIX_NUM_OVERFLOW;
00328                 break;
00329             default:
00330                 return ECPG_INFORMIX_NUM_UNDERFLOW;
00331                 break;
00332         }
00333 
00334     return 0;
00335 }
00336 
00337 int
00338 decmul(decimal *n1, decimal *n2, decimal *result)
00339 {
00340     int         i;
00341 
00342     errno = 0;
00343     i = deccall3(n1, n2, result, PGTYPESnumeric_mul);
00344 
00345     if (i != 0)
00346         switch (errno)
00347         {
00348             case PGTYPES_NUM_OVERFLOW:
00349                 return ECPG_INFORMIX_NUM_OVERFLOW;
00350                 break;
00351             default:
00352                 return ECPG_INFORMIX_NUM_UNDERFLOW;
00353                 break;
00354         }
00355 
00356     return 0;
00357 }
00358 
00359 int
00360 decsub(decimal *n1, decimal *n2, decimal *result)
00361 {
00362     int         i;
00363 
00364     errno = 0;
00365     i = deccall3(n1, n2, result, PGTYPESnumeric_sub);
00366 
00367     if (i != 0)
00368         switch (errno)
00369         {
00370             case PGTYPES_NUM_OVERFLOW:
00371                 return ECPG_INFORMIX_NUM_OVERFLOW;
00372                 break;
00373             default:
00374                 return ECPG_INFORMIX_NUM_UNDERFLOW;
00375                 break;
00376         }
00377 
00378     return 0;
00379 }
00380 
00381 int
00382 dectoasc(decimal *np, char *cp, int len, int right)
00383 {
00384     char       *str;
00385     numeric    *nres;
00386 
00387     rsetnull(CSTRINGTYPE, (char *) cp);
00388     if (risnull(CDECIMALTYPE, (char *) np))
00389         return 0;
00390 
00391     nres = PGTYPESnumeric_new();
00392     if (nres == NULL)
00393         return ECPG_INFORMIX_OUT_OF_MEMORY;
00394 
00395     if (PGTYPESnumeric_from_decimal(np, nres) != 0)
00396     {
00397         PGTYPESnumeric_free(nres);
00398         return ECPG_INFORMIX_OUT_OF_MEMORY;
00399     }
00400 
00401     if (right >= 0)
00402         str = PGTYPESnumeric_to_asc(nres, right);
00403     else
00404         str = PGTYPESnumeric_to_asc(nres, nres->dscale);
00405 
00406     PGTYPESnumeric_free(nres);
00407     if (!str)
00408         return -1;
00409 
00410     /*
00411      * TODO: have to take care of len here and create exponential notation if
00412      * necessary
00413      */
00414     if ((int) (strlen(str) + 1) > len)
00415     {
00416         if (len > 1)
00417         {
00418             cp[0] = '*';
00419             cp[1] = '\0';
00420         }
00421         free(str);
00422         return -1;
00423     }
00424     else
00425     {
00426         strcpy(cp, str);
00427         free(str);
00428         return 0;
00429     }
00430 }
00431 
00432 int
00433 dectodbl(decimal *np, double *dblp)
00434 {
00435     int         i;
00436     numeric    *nres = PGTYPESnumeric_new();
00437 
00438     if (nres == NULL)
00439         return ECPG_INFORMIX_OUT_OF_MEMORY;
00440 
00441     if (PGTYPESnumeric_from_decimal(np, nres) != 0)
00442     {
00443         PGTYPESnumeric_free(nres);
00444         return ECPG_INFORMIX_OUT_OF_MEMORY;
00445     }
00446 
00447     i = PGTYPESnumeric_to_double(nres, dblp);
00448     PGTYPESnumeric_free(nres);
00449 
00450     return i;
00451 }
00452 
00453 int
00454 dectoint(decimal *np, int *ip)
00455 {
00456     int         ret;
00457     numeric    *nres = PGTYPESnumeric_new();
00458 
00459     if (nres == NULL)
00460         return ECPG_INFORMIX_OUT_OF_MEMORY;
00461 
00462     if (PGTYPESnumeric_from_decimal(np, nres) != 0)
00463     {
00464         PGTYPESnumeric_free(nres);
00465         return ECPG_INFORMIX_OUT_OF_MEMORY;
00466     }
00467 
00468     ret = PGTYPESnumeric_to_int(nres, ip);
00469     PGTYPESnumeric_free(nres);
00470 
00471     if (ret == PGTYPES_NUM_OVERFLOW)
00472         ret = ECPG_INFORMIX_NUM_OVERFLOW;
00473 
00474     return ret;
00475 }
00476 
00477 int
00478 dectolong(decimal *np, long *lngp)
00479 {
00480     int         ret;
00481     numeric    *nres = PGTYPESnumeric_new();
00482 
00483     if (nres == NULL)
00484         return ECPG_INFORMIX_OUT_OF_MEMORY;
00485 
00486     if (PGTYPESnumeric_from_decimal(np, nres) != 0)
00487     {
00488         PGTYPESnumeric_free(nres);
00489         return ECPG_INFORMIX_OUT_OF_MEMORY;
00490     }
00491 
00492     ret = PGTYPESnumeric_to_long(nres, lngp);
00493     PGTYPESnumeric_free(nres);
00494 
00495     if (ret == PGTYPES_NUM_OVERFLOW)
00496         ret = ECPG_INFORMIX_NUM_OVERFLOW;
00497 
00498     return ret;
00499 }
00500 
00501 /* Now the date functions */
00502 int
00503 rdatestr(date d, char *str)
00504 {
00505     char       *tmp = PGTYPESdate_to_asc(d);
00506 
00507     if (!tmp)
00508         return ECPG_INFORMIX_DATE_CONVERT;
00509 
00510     /* move to user allocated buffer */
00511     strcpy(str, tmp);
00512     free(tmp);
00513 
00514     return 0;
00515 }
00516 
00517 /*
00518 *
00519 * the input for this function is mmddyyyy and any non-numeric
00520 * character can be used as a separator
00521 *
00522 */
00523 int
00524 rstrdate(char *str, date * d)
00525 {
00526     return rdefmtdate(d, "mm/dd/yyyy", str);
00527 }
00528 
00529 void
00530 rtoday(date * d)
00531 {
00532     PGTYPESdate_today(d);
00533     return;
00534 }
00535 
00536 int
00537 rjulmdy(date d, short mdy[3])
00538 {
00539     int         mdy_int[3];
00540 
00541     PGTYPESdate_julmdy(d, mdy_int);
00542     mdy[0] = (short) mdy_int[0];
00543     mdy[1] = (short) mdy_int[1];
00544     mdy[2] = (short) mdy_int[2];
00545     return 0;
00546 }
00547 
00548 int
00549 rdefmtdate(date * d, char *fmt, char *str)
00550 {
00551     /* TODO: take care of DBCENTURY environment variable */
00552     /* PGSQL functions allow all centuries */
00553 
00554     errno = 0;
00555     if (PGTYPESdate_defmt_asc(d, fmt, str) == 0)
00556         return 0;
00557 
00558     switch (errno)
00559     {
00560         case PGTYPES_DATE_ERR_ENOSHORTDATE:
00561             return ECPG_INFORMIX_ENOSHORTDATE;
00562         case PGTYPES_DATE_ERR_EARGS:
00563         case PGTYPES_DATE_ERR_ENOTDMY:
00564             return ECPG_INFORMIX_ENOTDMY;
00565         case PGTYPES_DATE_BAD_DAY:
00566             return ECPG_INFORMIX_BAD_DAY;
00567         case PGTYPES_DATE_BAD_MONTH:
00568             return ECPG_INFORMIX_BAD_MONTH;
00569         default:
00570             return ECPG_INFORMIX_BAD_YEAR;
00571     }
00572 }
00573 
00574 int
00575 rfmtdate(date d, char *fmt, char *str)
00576 {
00577     errno = 0;
00578     if (PGTYPESdate_fmt_asc(d, fmt, str) == 0)
00579         return 0;
00580 
00581     if (errno == ENOMEM)
00582         return ECPG_INFORMIX_OUT_OF_MEMORY;
00583 
00584     return ECPG_INFORMIX_DATE_CONVERT;
00585 }
00586 
00587 int
00588 rmdyjul(short mdy[3], date * d)
00589 {
00590     int         mdy_int[3];
00591 
00592     mdy_int[0] = mdy[0];
00593     mdy_int[1] = mdy[1];
00594     mdy_int[2] = mdy[2];
00595     PGTYPESdate_mdyjul(mdy_int, d);
00596     return 0;
00597 }
00598 
00599 int
00600 rdayofweek(date d)
00601 {
00602     return (PGTYPESdate_dayofweek(d));
00603 }
00604 
00605 /* And the datetime stuff */
00606 
00607 void
00608 dtcurrent(timestamp * ts)
00609 {
00610     PGTYPEStimestamp_current(ts);
00611 }
00612 
00613 int
00614 dtcvasc(char *str, timestamp * ts)
00615 {
00616     timestamp   ts_tmp;
00617     int         i;
00618     char      **endptr = &str;
00619 
00620     errno = 0;
00621     ts_tmp = PGTYPEStimestamp_from_asc(str, endptr);
00622     i = errno;
00623     if (i)
00624         /* TODO: rewrite to Informix error codes */
00625         return i;
00626     if (**endptr)
00627     {
00628         /* extra characters exist at the end */
00629         return ECPG_INFORMIX_EXTRA_CHARS;
00630     }
00631     /* TODO: other Informix error codes missing */
00632 
00633     /* everything went fine */
00634     *ts = ts_tmp;
00635 
00636     return 0;
00637 }
00638 
00639 int
00640 dtcvfmtasc(char *inbuf, char *fmtstr, timestamp * dtvalue)
00641 {
00642     return PGTYPEStimestamp_defmt_asc(inbuf, fmtstr, dtvalue);
00643 }
00644 
00645 int
00646 dtsub(timestamp * ts1, timestamp * ts2, interval * iv)
00647 {
00648     return PGTYPEStimestamp_sub(ts1, ts2, iv);
00649 }
00650 
00651 int
00652 dttoasc(timestamp * ts, char *output)
00653 {
00654     char       *asctime = PGTYPEStimestamp_to_asc(*ts);
00655 
00656     strcpy(output, asctime);
00657     free(asctime);
00658     return 0;
00659 }
00660 
00661 int
00662 dttofmtasc(timestamp * ts, char *output, int str_len, char *fmtstr)
00663 {
00664     return PGTYPEStimestamp_fmt_asc(ts, output, str_len, fmtstr);
00665 }
00666 
00667 int
00668 intoasc(interval * i, char *str)
00669 {
00670     errno = 0;
00671     str = PGTYPESinterval_to_asc(i);
00672 
00673     if (!str)
00674         return -errno;
00675 
00676     return 0;
00677 }
00678 
00679 /*
00680  *  rfmt.c  -  description
00681  *  by Carsten Wolff <[email protected]>, Wed Apr 2 2003
00682  */
00683 
00684 static struct
00685 {
00686     long        val;
00687     int         maxdigits;
00688     int         digits;
00689     int         remaining;
00690     char        sign;
00691     char       *val_string;
00692 }   value;
00693 
00698 static int
00699 initValue(long lng_val)
00700 {
00701     int         i,
00702                 j;
00703     long        l,
00704                 dig;
00705 
00706     /* set some obvious things */
00707     value.val = lng_val >= 0 ? lng_val : lng_val * (-1);
00708     value.sign = lng_val >= 0 ? '+' : '-';
00709     value.maxdigits = log10(2) * (8 * sizeof(long) - 1);
00710 
00711     /* determine the number of digits */
00712     i = 0;
00713     l = 1;
00714     do
00715     {
00716         i++;
00717         l *= 10;
00718     }
00719     while ((l - 1) < value.val && l <= LONG_MAX / 10);
00720 
00721     if (l <= LONG_MAX / 10)
00722     {
00723         value.digits = i;
00724         l /= 10;
00725     }
00726     else
00727         value.digits = i + 1;
00728 
00729     value.remaining = value.digits;
00730 
00731     /* convert the long to string */
00732     if ((value.val_string = (char *) malloc(value.digits + 1)) == NULL)
00733         return -1;
00734     dig = value.val;
00735     for (i = value.digits, j = 0; i > 0; i--, j++)
00736     {
00737         value.val_string[j] = dig / l + '0';
00738         dig = dig % l;
00739         l /= 10;
00740     }
00741     value.val_string[value.digits] = '\0';
00742     return 0;
00743 }
00744 
00745 /* return the position oft the right-most dot in some string */
00746 static int
00747 getRightMostDot(char *str)
00748 {
00749     size_t      len = strlen(str);
00750     int         i,
00751                 j;
00752 
00753     j = 0;
00754     for (i = len - 1; i >= 0; i--)
00755     {
00756         if (str[i] == '.')
00757             return len - j - 1;
00758         j++;
00759     }
00760     return -1;
00761 }
00762 
00763 /* And finally some misc functions */
00764 int
00765 rfmtlong(long lng_val, char *fmt, char *outbuf)
00766 {
00767     size_t      fmt_len = strlen(fmt);
00768     size_t      temp_len;
00769     int         i,
00770                 j,              /* position in temp */
00771                 k,
00772                 dotpos;
00773     int         leftalign = 0,
00774                 blank = 0,
00775                 sign = 0,
00776                 entitydone = 0,
00777                 signdone = 0,
00778                 brackets_ok = 0;
00779     char       *temp;
00780     char        tmp[2] = " ";
00781     char        lastfmt = ' ',
00782                 fmtchar = ' ';
00783 
00784     temp = (char *) malloc(fmt_len + 1);
00785     if (!temp)
00786     {
00787         errno = ENOMEM;
00788         return -1;
00789     }
00790 
00791     /* put all info about the long in a struct */
00792     if (initValue(lng_val) == -1)
00793     {
00794         free(temp);
00795         errno = ENOMEM;
00796         return -1;
00797     }
00798 
00799     /* '<' is the only format, where we have to align left */
00800     if (strchr(fmt, (int) '<'))
00801         leftalign = 1;
00802 
00803     /* '(' requires ')' */
00804     if (strchr(fmt, (int) '(') && strchr(fmt, (int) ')'))
00805         brackets_ok = 1;
00806 
00807     /* get position of the right-most dot in the format-string */
00808     /* and fill the temp-string wit '0's up to there. */
00809     dotpos = getRightMostDot(fmt);
00810 
00811     /* start to parse the formatstring */
00812     temp[0] = '\0';
00813     k = value.digits - 1;       /* position in the value_string */
00814     for (i = fmt_len - 1, j = 0; i >= 0; i--, j++)
00815     {
00816         /* qualify, where we are in the value_string */
00817         if (k < 0)
00818         {
00819             blank = 1;
00820             if (k == -1)
00821                 sign = 1;
00822             if (leftalign)
00823             {
00824                 /* can't use strncat(,,0) here, Solaris would freek out */
00825                 if (sign)
00826                     if (signdone)
00827                     {
00828                         temp[j] = '\0';
00829                         break;
00830                     }
00831             }
00832         }
00833         /* if we're right side of the right-most dot, print '0' */
00834         if (dotpos >= 0 && dotpos <= i)
00835         {
00836             if (dotpos < i)
00837             {
00838                 if (fmt[i] == ')')
00839                     tmp[0] = value.sign == '-' ? ')' : ' ';
00840                 else
00841                     tmp[0] = '0';
00842             }
00843             else
00844                 tmp[0] = '.';
00845             strcat(temp, tmp);
00846             continue;
00847         }
00848         /* the ',' needs special attention, if it is in the blank area */
00849         if (blank && fmt[i] == ',')
00850             fmtchar = lastfmt;
00851         else
00852             fmtchar = fmt[i];
00853         /* waiting for the sign */
00854         if (k < 0 && leftalign && sign && !signdone && fmtchar != '+' && fmtchar != '-')
00855             continue;
00856         /* analyse this format-char */
00857         switch (fmtchar)
00858         {
00859             case ',':
00860                 tmp[0] = ',';
00861                 k++;
00862                 break;
00863             case '*':
00864                 if (blank)
00865                     tmp[0] = '*';
00866                 else
00867                     tmp[0] = value.val_string[k];
00868                 break;
00869             case '&':
00870                 if (blank)
00871                     tmp[0] = '0';
00872                 else
00873                     tmp[0] = value.val_string[k];
00874                 break;
00875             case '#':
00876                 if (blank)
00877                     tmp[0] = ' ';
00878                 else
00879                     tmp[0] = value.val_string[k];
00880                 break;
00881             case '-':
00882                 if (sign && value.sign == '-' && !signdone)
00883                 {
00884                     tmp[0] = '-';
00885                     signdone = 1;
00886                 }
00887                 else if (blank)
00888                     tmp[0] = ' ';
00889                 else
00890                     tmp[0] = value.val_string[k];
00891                 break;
00892             case '+':
00893                 if (sign && !signdone)
00894                 {
00895                     tmp[0] = value.sign;
00896                     signdone = 1;
00897                 }
00898                 else if (blank)
00899                     tmp[0] = ' ';
00900                 else
00901                     tmp[0] = value.val_string[k];
00902                 break;
00903             case '(':
00904                 if (sign && brackets_ok && value.sign == '-')
00905                     tmp[0] = '(';
00906                 else if (blank)
00907                     tmp[0] = ' ';
00908                 else
00909                     tmp[0] = value.val_string[k];
00910                 break;
00911             case ')':
00912                 if (brackets_ok && value.sign == '-')
00913                     tmp[0] = ')';
00914                 else
00915                     tmp[0] = ' ';
00916                 break;
00917             case '$':
00918                 if (blank && !entitydone)
00919                 {
00920                     tmp[0] = '$';
00921                     entitydone = 1;
00922                 }
00923                 else if (blank)
00924                     tmp[0] = ' ';
00925                 else
00926                     tmp[0] = value.val_string[k];
00927                 break;
00928             case '<':
00929                 tmp[0] = value.val_string[k];
00930                 break;
00931             default:
00932                 tmp[0] = fmt[i];
00933         }
00934         strcat(temp, tmp);
00935         lastfmt = fmt[i];
00936         k--;
00937     }
00938     /* safety-net */
00939     temp[fmt_len] = '\0';
00940 
00941     /* reverse the temp-string and put it into the outbuf */
00942     temp_len = strlen(temp);
00943     outbuf[0] = '\0';
00944     for (i = temp_len - 1; i >= 0; i--)
00945     {
00946         tmp[0] = temp[i];
00947         strcat(outbuf, tmp);
00948     }
00949     outbuf[temp_len] = '\0';
00950 
00951     /* cleaning up */
00952     free(temp);
00953     free(value.val_string);
00954 
00955     return 0;
00956 }
00957 
00958 void
00959 rupshift(char *str)
00960 {
00961     for (; *str != '\0'; str++)
00962         if (islower((unsigned char) *str))
00963             *str = toupper((unsigned char) *str);
00964     return;
00965 }
00966 
00967 int
00968 byleng(char *str, int len)
00969 {
00970     for (len--; str[len] && str[len] == ' '; len--);
00971     return (len + 1);
00972 }
00973 
00974 void
00975 ldchar(char *src, int len, char *dest)
00976 {
00977     int         dlen = byleng(src, len);
00978 
00979     memmove(dest, src, dlen);
00980     dest[dlen] = '\0';
00981 }
00982 
00983 int
00984 rgetmsg(int msgnum, char *s, int maxsize)
00985 {
00986     (void) msgnum;              /* keep the compiler quiet */
00987     (void) s;                   /* keep the compiler quiet */
00988     (void) maxsize;             /* keep the compiler quiet */
00989     return 0;
00990 }
00991 
00992 int
00993 rtypalign(int offset, int type)
00994 {
00995     (void) offset;              /* keep the compiler quiet */
00996     (void) type;                /* keep the compiler quiet */
00997     return 0;
00998 }
00999 
01000 int
01001 rtypmsize(int type, int len)
01002 {
01003     (void) type;                /* keep the compiler quiet */
01004     (void) len;                 /* keep the compiler quiet */
01005     return 0;
01006 }
01007 
01008 int
01009 rtypwidth(int sqltype, int sqllen)
01010 {
01011     (void) sqltype;             /* keep the compiler quiet */
01012     (void) sqllen;              /* keep the compiler quiet */
01013     return 0;
01014 }
01015 
01016 void
01017 ECPG_informix_set_var(int number, void *pointer, int lineno)
01018 {
01019     ECPGset_var(number, pointer, lineno);
01020 }
01021 
01022 void *
01023 ECPG_informix_get_var(int number)
01024 {
01025     return ECPGget_var(number);
01026 }
01027 
01028 void
01029 ECPG_informix_reset_sqlca(void)
01030 {
01031     struct sqlca_t *sqlca = ECPGget_sqlca();
01032 
01033     memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
01034 }
01035 
01036 int
01037 rsetnull(int t, char *ptr)
01038 {
01039     ECPGset_noind_null(t, ptr);
01040     return 0;
01041 }
01042 
01043 int
01044 risnull(int t, char *ptr)
01045 {
01046     return (ECPGis_noind_null(t, ptr));
01047 }