Header And Logo

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

Data Structures | Defines | Typedefs | Functions

preproc-outofscope.c File Reference

#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
Include dependency graph for preproc-outofscope.c:

Go to the source code of this file.

Data Structures

struct  numeric
struct  decimal
struct  mytype
struct  mynulltype

Defines

#define ECPGdebug(X, Y)   ECPGdebug((X)+100,(Y))
#define NUMERIC_POS   0x0000
#define NUMERIC_NEG   0x4000
#define NUMERIC_NAN   0xC000
#define NUMERIC_NULL   0xF000
#define NUMERIC_MAX_PRECISION   1000
#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION
#define NUMERIC_MIN_DISPLAY_SCALE   0
#define NUMERIC_MIN_SIG_DIGITS   16
#define DECSIZE   30

Typedefs

typedef unsigned char NumericDigit
typedef struct mytype MYTYPE
typedef struct mynulltype MYNULLTYPE

Functions

numericPGTYPESnumeric_new (void)
decimalPGTYPESdecimal_new (void)
void PGTYPESnumeric_free (numeric *)
void PGTYPESdecimal_free (decimal *)
numericPGTYPESnumeric_from_asc (char *, char **)
char * PGTYPESnumeric_to_asc (numeric *, int)
int PGTYPESnumeric_add (numeric *, numeric *, numeric *)
int PGTYPESnumeric_sub (numeric *, numeric *, numeric *)
int PGTYPESnumeric_mul (numeric *, numeric *, numeric *)
int PGTYPESnumeric_div (numeric *, numeric *, numeric *)
int PGTYPESnumeric_cmp (numeric *, numeric *)
int PGTYPESnumeric_from_int (signed int, numeric *)
int PGTYPESnumeric_from_long (signed long int, numeric *)
int PGTYPESnumeric_copy (numeric *, numeric *)
int PGTYPESnumeric_from_double (double, numeric *)
int PGTYPESnumeric_to_double (numeric *, double *)
int PGTYPESnumeric_to_int (numeric *, int *)
int PGTYPESnumeric_to_long (numeric *, long *)
int PGTYPESnumeric_to_decimal (numeric *, decimal *)
int PGTYPESnumeric_from_decimal (decimal *, numeric *)
static void get_var1 (MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
static void open_cur1 (void)
static void get_record1 (void)
static void close_cur1 (void)
int main (void)

Define Documentation

#define DECSIZE   30

Definition at line 40 of file preproc-outofscope.c.

#define ECPGdebug (   X,
  Y 
)    ECPGdebug((X)+100,(Y))

Definition at line 7 of file preproc-outofscope.c.

#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION

Definition at line 36 of file preproc-outofscope.c.

#define NUMERIC_MAX_PRECISION   1000

Definition at line 35 of file preproc-outofscope.c.

#define NUMERIC_MIN_DISPLAY_SCALE   0

Definition at line 37 of file preproc-outofscope.c.

#define NUMERIC_MIN_SIG_DIGITS   16

Definition at line 38 of file preproc-outofscope.c.

#define NUMERIC_NAN   0xC000

Definition at line 33 of file preproc-outofscope.c.

#define NUMERIC_NEG   0x4000

Definition at line 32 of file preproc-outofscope.c.

#define NUMERIC_NULL   0xF000

Definition at line 34 of file preproc-outofscope.c.

#define NUMERIC_POS   0x0000

Definition at line 31 of file preproc-outofscope.c.


Typedef Documentation

typedef struct mynulltype MYNULLTYPE

Definition at line 123 of file preproc-outofscope.c.

typedef struct mytype MYTYPE

Definition at line 110 of file preproc-outofscope.c.

typedef unsigned char NumericDigit

Definition at line 42 of file preproc-outofscope.c.


Function Documentation

static void close_cur1 ( void   )  [static]

Definition at line 250 of file preproc-outofscope.c.

References ECPGdo(), ECPGst_normal, ECPGt_EOIT, ECPGt_EORT, NULL, and sqlca.

Referenced by main().

{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur", ECPGt_EOIT, ECPGt_EORT);
#line 58 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 58 "outofscope.pgc"


    if (sqlca.sqlcode != 0)
        exit(1);
}

static void get_record1 ( void   )  [static]

Definition at line 226 of file preproc-outofscope.c.

References ECPG_NOT_FOUND, ECPGdo(), ECPGget_var(), ECPGst_normal, ECPGt_char, ECPGt_double, ECPGt_EOIT, ECPGt_EORT, ECPGt_int, NULL, and sqlca.

Referenced by main().

{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch mycur", ECPGt_EOIT, 
    ECPGt_int,&((*( MYTYPE  *)(ECPGget_var( 0)) ).id),(long)1,(long)1,sizeof(int), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).id),(long)1,(long)1,sizeof(int), 
    ECPGt_char,&((*( MYTYPE  *)(ECPGget_var( 0)) ).t),(long)64,(long)1,(64)*sizeof(char), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).t),(long)1,(long)1,sizeof(int), 
    ECPGt_double,&((*( MYTYPE  *)(ECPGget_var( 0)) ).d1),(long)1,(long)1,sizeof(double), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).d1),(long)1,(long)1,sizeof(int), 
    ECPGt_double,&((*( MYTYPE  *)(ECPGget_var( 0)) ).d2),(long)1,(long)1,sizeof(double), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).d2),(long)1,(long)1,sizeof(int), 
    ECPGt_char,&((*( MYTYPE  *)(ECPGget_var( 0)) ).c),(long)30,(long)1,(30)*sizeof(char), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).c),(long)1,(long)1,sizeof(int), ECPGt_EORT);
#line 49 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 49 "outofscope.pgc"


    if (sqlca.sqlcode != 0 && sqlca.sqlcode != ECPG_NOT_FOUND)
        exit(1);
}

static void get_var1 ( MYTYPE **  myvar0,
MYNULLTYPE **  mynullvar0 
) [static]

Definition at line 171 of file preproc-outofscope.c.

References ECPGset_var(), malloc, and sqlca.

Referenced by main().

{
    /* exec sql begin declare section */
              
          
    
#line 22 "outofscope.pgc"
 MYTYPE * myvar = malloc ( sizeof ( MYTYPE ) ) ;
 
#line 23 "outofscope.pgc"
 MYNULLTYPE * mynullvar = malloc ( sizeof ( MYNULLTYPE ) ) ;
/* exec sql end declare section */
#line 24 "outofscope.pgc"


    /* Test DECLARE ... SELECT ... INTO with pointers */

    ECPGset_var( 0, ( myvar ), __LINE__);\
 ECPGset_var( 1, ( mynullvar ), __LINE__);\
 /* declare mycur cursor for select * from a1 */
#line 28 "outofscope.pgc"


    if (sqlca.sqlcode != 0)
        exit(1);

    *myvar0 = myvar;
    *mynullvar0 = mynullvar;
}

int main ( void   ) 

Definition at line 264 of file preproc-outofscope.c.

References mynulltype::c, mytype::c, close_cur1(), mynulltype::d1, mytype::d1, mynulltype::d2, mytype::d2, ECPG_NOT_FOUND, ECPGconnect(), ECPGdebug, ECPGdisconnect(), ECPGdo(), ECPGst_normal, ECPGt_EOIT, ECPGt_EORT, ECPGtrans(), get_record1(), get_var1(), mynulltype::id, mytype::id, NULL, open_cur1(), sqlca, mynulltype::t, and mytype::t.

{
    MYTYPE      *myvar;
    MYNULLTYPE  *mynullvar;

    char msg[128];

    ECPGdebug(1, stderr);

    strcpy(msg, "connect");
    { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); 
#line 75 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 75 "outofscope.pgc"


    strcpy(msg, "set");
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
#line 78 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 78 "outofscope.pgc"


    strcpy(msg, "create");
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table a1 ( id serial primary key , t text , d1 numeric , d2 float8 , c character ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);
#line 81 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 81 "outofscope.pgc"


    strcpy(msg, "insert");
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'a' , 1.0 , 2 , 'a' )", ECPGt_EOIT, ECPGt_EORT);
#line 84 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 84 "outofscope.pgc"

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , null , null , null , null )", ECPGt_EOIT, ECPGt_EORT);
#line 85 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 85 "outofscope.pgc"

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
#line 86 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 86 "outofscope.pgc"


    strcpy(msg, "commit");
    { ECPGtrans(__LINE__, NULL, "commit");
#line 89 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 89 "outofscope.pgc"


    /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */

    get_var1(&myvar, &mynullvar);
    open_cur1();

    /* exec sql whenever not found  break ; */
#line 96 "outofscope.pgc"


    while (1)
    {
        memset(myvar, 0, sizeof(MYTYPE));
        get_record1();
        if (sqlca.sqlcode == ECPG_NOT_FOUND)
            break;
        printf("id=%d%s t='%s'%s d1=%lf%s d2=%lf%s c = '%s'%s\n",
            myvar->id, mynullvar->id ? " (NULL)" : "",
            myvar->t, mynullvar->t ? " (NULL)" : "",
            myvar->d1, mynullvar->d1 ? " (NULL)" : "",
            myvar->d2, mynullvar->d2 ? " (NULL)" : "",
            myvar->c, mynullvar->c ? " (NULL)" : "");
    }

    close_cur1();

    strcpy(msg, "drop");
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
#line 115 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 115 "outofscope.pgc"


    strcpy(msg, "commit");
    { ECPGtrans(__LINE__, NULL, "commit");
#line 118 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 118 "outofscope.pgc"


    strcpy(msg, "disconnect");
    { ECPGdisconnect(__LINE__, "CURRENT");
#line 121 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 121 "outofscope.pgc"


    return (0);
}

static void open_cur1 ( void   )  [static]

Definition at line 202 of file preproc-outofscope.c.

References ECPGdo(), ECPGget_var(), ECPGst_normal, ECPGt_char, ECPGt_double, ECPGt_EOIT, ECPGt_EORT, ECPGt_int, NULL, and sqlca.

Referenced by main().

{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT, 
    ECPGt_int,&((*( MYTYPE  *)(ECPGget_var( 0)) ).id),(long)1,(long)1,sizeof(int), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).id),(long)1,(long)1,sizeof(int), 
    ECPGt_char,&((*( MYTYPE  *)(ECPGget_var( 0)) ).t),(long)64,(long)1,(64)*sizeof(char), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).t),(long)1,(long)1,sizeof(int), 
    ECPGt_double,&((*( MYTYPE  *)(ECPGget_var( 0)) ).d1),(long)1,(long)1,sizeof(double), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).d1),(long)1,(long)1,sizeof(int), 
    ECPGt_double,&((*( MYTYPE  *)(ECPGget_var( 0)) ).d2),(long)1,(long)1,sizeof(double), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).d2),(long)1,(long)1,sizeof(int), 
    ECPGt_char,&((*( MYTYPE  *)(ECPGget_var( 0)) ).c),(long)30,(long)1,(30)*sizeof(char), 
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPGget_var( 1)) ).c),(long)1,(long)1,sizeof(int), ECPGt_EORT);
#line 40 "outofscope.pgc"

if (sqlca.sqlcode < 0) exit (1);}
#line 40 "outofscope.pgc"


    if (sqlca.sqlcode != 0)
        exit(1);
}

void PGTYPESdecimal_free ( decimal  ) 

Definition at line 473 of file numeric.c.

{
    free(var);
}

decimal* PGTYPESdecimal_new ( void   ) 

Definition at line 143 of file numeric.c.

{
    decimal    *var;

    if ((var = (decimal *) pgtypes_alloc(sizeof(decimal))) == NULL)
        return NULL;

    memset(var, 0, sizeof(decimal));

    return var;
}

int PGTYPESnumeric_add ( numeric ,
numeric ,
numeric  
)

Definition at line 718 of file numeric.c.

{
    /*
     * Decide on the signs of the two variables what to do
     */
    if (var1->sign == NUMERIC_POS)
    {
        if (var2->sign == NUMERIC_POS)
        {
            /*
             * Both are positive result = +(ABS(var1) + ABS(var2))
             */
            if (add_abs(var1, var2, result) != 0)
                return -1;
            result->sign = NUMERIC_POS;
        }
        else
        {
            /*
             * var1 is positive, var2 is negative Must compare absolute values
             */
            switch (cmp_abs(var1, var2))
            {
                case 0:
                    /* ----------
                     * ABS(var1) == ABS(var2)
                     * result = ZERO
                     * ----------
                     */
                    zero_var(result);
                    result->rscale = Max(var1->rscale, var2->rscale);
                    result->dscale = Max(var1->dscale, var2->dscale);
                    break;

                case 1:
                    /* ----------
                     * ABS(var1) > ABS(var2)
                     * result = +(ABS(var1) - ABS(var2))
                     * ----------
                     */
                    if (sub_abs(var1, var2, result) != 0)
                        return -1;
                    result->sign = NUMERIC_POS;
                    break;

                case -1:
                    /* ----------
                     * ABS(var1) < ABS(var2)
                     * result = -(ABS(var2) - ABS(var1))
                     * ----------
                     */
                    if (sub_abs(var2, var1, result) != 0)
                        return -1;
                    result->sign = NUMERIC_NEG;
                    break;
            }
        }
    }
    else
    {
        if (var2->sign == NUMERIC_POS)
        {
            /* ----------
             * var1 is negative, var2 is positive
             * Must compare absolute values
             * ----------
             */
            switch (cmp_abs(var1, var2))
            {
                case 0:
                    /* ----------
                     * ABS(var1) == ABS(var2)
                     * result = ZERO
                     * ----------
                     */
                    zero_var(result);
                    result->rscale = Max(var1->rscale, var2->rscale);
                    result->dscale = Max(var1->dscale, var2->dscale);
                    break;

                case 1:
                    /* ----------
                     * ABS(var1) > ABS(var2)
                     * result = -(ABS(var1) - ABS(var2))
                     * ----------
                     */
                    if (sub_abs(var1, var2, result) != 0)
                        return -1;
                    result->sign = NUMERIC_NEG;
                    break;

                case -1:
                    /* ----------
                     * ABS(var1) < ABS(var2)
                     * result = +(ABS(var2) - ABS(var1))
                     * ----------
                     */
                    if (sub_abs(var2, var1, result) != 0)
                        return -1;
                    result->sign = NUMERIC_POS;
                    break;
            }
        }
        else
        {
            /* ----------
             * Both are negative
             * result = -(ABS(var1) + ABS(var2))
             * ----------
             */
            if (add_abs(var1, var2, result) != 0)
                return -1;
            result->sign = NUMERIC_NEG;
        }
    }

    return 0;
}

int PGTYPESnumeric_cmp ( numeric ,
numeric  
)

Definition at line 1363 of file numeric.c.

{

    /* use cmp_abs function to calculate the result */

    /* both are positive: normal comparation with cmp_abs */
    if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
        return cmp_abs(var1, var2);

    /* both are negative: return the inverse of the normal comparation */
    if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
    {
        /*
         * instead of inverting the result, we invert the paramter ordering
         */
        return cmp_abs(var2, var1);
    }

    /* one is positive, one is negative: trivial */
    if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
        return 1;
    if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
        return -1;

    errno = PGTYPES_NUM_BAD_NUMERIC;
    return INT_MAX;

}

int PGTYPESnumeric_copy ( numeric ,
numeric  
)

Definition at line 1472 of file numeric.c.

{
    int         i;

    if (dst == NULL)
        return -1;
    zero_var(dst);

    dst->weight = src->weight;
    dst->rscale = src->rscale;
    dst->dscale = src->dscale;
    dst->sign = src->sign;

    if (alloc_var(dst, src->ndigits) != 0)
        return -1;

    for (i = 0; i < src->ndigits; i++)
        dst->digits[i] = src->digits[i];

    return 0;
}

int PGTYPESnumeric_div ( numeric ,
numeric ,
numeric  
)

Definition at line 1134 of file numeric.c.

{
    NumericDigit *res_digits;
    int         res_ndigits;
    int         res_sign;
    int         res_weight;
    numeric     dividend;
    numeric     divisor[10];
    int         ndigits_tmp;
    int         weight_tmp;
    int         rscale_tmp;
    int         ri;
    int         i;
    long        guess;
    long        first_have;
    long        first_div;
    int         first_nextdigit;
    int         stat = 0;
    int         rscale;
    int         res_dscale = select_div_scale(var1, var2, &rscale);
    int         err = -1;
    NumericDigit *tmp_buf;

    /*
     * First of all division by zero check
     */
    ndigits_tmp = var2->ndigits + 1;
    if (ndigits_tmp == 1)
    {
        errno = PGTYPES_NUM_DIVIDE_ZERO;
        return -1;
    }

    /*
     * Determine the result sign, weight and number of digits to calculate
     */
    if (var1->sign == var2->sign)
        res_sign = NUMERIC_POS;
    else
        res_sign = NUMERIC_NEG;
    res_weight = var1->weight - var2->weight + 1;
    res_ndigits = rscale + res_weight;
    if (res_ndigits <= 0)
        res_ndigits = 1;

    /*
     * Now result zero check
     */
    if (var1->ndigits == 0)
    {
        zero_var(result);
        result->rscale = rscale;
        return 0;
    }

    /*
     * Initialize local variables
     */
    init_var(&dividend);
    for (i = 1; i < 10; i++)
        init_var(&divisor[i]);

    /*
     * Make a copy of the divisor which has one leading zero digit
     */
    divisor[1].ndigits = ndigits_tmp;
    divisor[1].rscale = var2->ndigits;
    divisor[1].sign = NUMERIC_POS;
    divisor[1].buf = digitbuf_alloc(ndigits_tmp);
    if (divisor[1].buf == NULL)
        goto done;
    divisor[1].digits = divisor[1].buf;
    divisor[1].digits[0] = 0;
    memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);

    /*
     * Make a copy of the dividend
     */
    dividend.ndigits = var1->ndigits;
    dividend.weight = 0;
    dividend.rscale = var1->ndigits;
    dividend.sign = NUMERIC_POS;
    dividend.buf = digitbuf_alloc(var1->ndigits);
    if (dividend.buf == NULL)
        goto done;
    dividend.digits = dividend.buf;
    memcpy(dividend.digits, var1->digits, var1->ndigits);

    /*
     * Setup the result. Do the allocation in a temporary buffer first, so we
     * don't free result->buf unless we have successfully allocated a buffer
     * to replace it with.
     */
    tmp_buf = digitbuf_alloc(res_ndigits + 2);
    if (tmp_buf == NULL)
        goto done;
    digitbuf_free(result->buf);
    result->buf = tmp_buf;
    res_digits = result->buf;
    result->digits = res_digits;
    result->ndigits = res_ndigits;
    result->weight = res_weight;
    result->rscale = rscale;
    result->sign = res_sign;
    res_digits[0] = 0;

    first_div = divisor[1].digits[1] * 10;
    if (ndigits_tmp > 2)
        first_div += divisor[1].digits[2];

    first_have = 0;
    first_nextdigit = 0;

    weight_tmp = 1;
    rscale_tmp = divisor[1].rscale;

    for (ri = 0; ri <= res_ndigits; ri++)
    {
        first_have = first_have * 10;
        if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
            first_have += dividend.digits[first_nextdigit];
        first_nextdigit++;

        guess = (first_have * 10) / first_div + 1;
        if (guess > 9)
            guess = 9;

        while (guess > 0)
        {
            if (divisor[guess].buf == NULL)
            {
                int         i;
                long        sum = 0;

                memcpy(&divisor[guess], &divisor[1], sizeof(numeric));
                divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
                if (divisor[guess].buf == NULL)
                    goto done;
                divisor[guess].digits = divisor[guess].buf;
                for (i = divisor[1].ndigits - 1; i >= 0; i--)
                {
                    sum += divisor[1].digits[i] * guess;
                    divisor[guess].digits[i] = sum % 10;
                    sum /= 10;
                }
            }

            divisor[guess].weight = weight_tmp;
            divisor[guess].rscale = rscale_tmp;

            stat = cmp_abs(&dividend, &divisor[guess]);
            if (stat >= 0)
                break;

            guess--;
        }

        res_digits[ri + 1] = guess;
        if (stat == 0)
        {
            ri++;
            break;
        }

        weight_tmp--;
        rscale_tmp++;

        if (guess == 0)
            continue;

        if (sub_abs(&dividend, &divisor[guess], &dividend) != 0)
            goto done;

        first_nextdigit = dividend.weight - weight_tmp;
        first_have = 0;
        if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
            first_have = dividend.digits[first_nextdigit];
        first_nextdigit++;
    }

    result->ndigits = ri + 1;
    if (ri == res_ndigits + 1)
    {
        int         carry = (res_digits[ri] > 4) ? 1 : 0;

        result->ndigits = ri;
        res_digits[ri] = 0;

        while (carry && ri > 0)
        {
            carry += res_digits[--ri];
            res_digits[ri] = carry % 10;
            carry /= 10;
        }
    }

    while (result->ndigits > 0 && *(result->digits) == 0)
    {
        (result->digits)++;
        (result->weight)--;
        (result->ndigits)--;
    }
    while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
        (result->ndigits)--;
    if (result->ndigits == 0)
        result->sign = NUMERIC_POS;

    result->dscale = res_dscale;
    err = 0;                    /* if we've made it this far, return success */

done:

    /*
     * Tidy up
     */
    if (dividend.buf != NULL)
        digitbuf_free(dividend.buf);

    for (i = 1; i < 10; i++)
    {
        if (divisor[i].buf != NULL)
            digitbuf_free(divisor[i].buf);
    }

    return err;
}

void PGTYPESnumeric_free ( numeric  ) 

Definition at line 466 of file numeric.c.

{
    digitbuf_free(var->buf);
    free(var);
}

numeric* PGTYPESnumeric_from_asc ( char *  ,
char **   
)

Definition at line 406 of file numeric.c.

{
    numeric    *value = (numeric *) pgtypes_alloc(sizeof(numeric));
    int         ret;

    char       *realptr;
    char      **ptr = (endptr != NULL) ? endptr : &realptr;

    if (!value)
        return (NULL);

    ret = set_var_from_str(str, ptr, value);
    if (ret)
    {
        PGTYPESnumeric_free(value);
        return (NULL);
    }

    return (value);
}

int PGTYPESnumeric_from_decimal ( decimal ,
numeric  
)

Definition at line 1646 of file numeric.c.

{
    int         i;

    zero_var(dst);

    dst->weight = src->weight;
    dst->rscale = src->rscale;
    dst->dscale = src->dscale;
    dst->sign = src->sign;

    if (alloc_var(dst, src->ndigits) != 0)
        return -1;

    for (i = 0; i < src->ndigits; i++)
        dst->digits[i] = src->digits[i];

    return 0;
}

int PGTYPESnumeric_from_double ( double  ,
numeric  
)

Definition at line 1495 of file numeric.c.

{
    char        buffer[100];
    numeric    *tmp;
    int         i;

    if (sprintf(buffer, "%f", d) == 0)
        return -1;

    if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
        return -1;
    i = PGTYPESnumeric_copy(tmp, dst);
    PGTYPESnumeric_free(tmp);
    if (i != 0)
        return -1;

    errno = 0;
    return 0;
}

int PGTYPESnumeric_from_int ( signed  int,
numeric  
)

Definition at line 1393 of file numeric.c.

{
    /* implicit conversion */
    signed long int long_int = int_val;

    return PGTYPESnumeric_from_long(long_int, var);
}

int PGTYPESnumeric_from_long ( signed long  int,
numeric  
)

Definition at line 1402 of file numeric.c.

{
    /* calculate the size of the long int number */
    /* a number n needs log_10 n digits */

    /*
     * however we multiply by 10 each time and compare instead of calculating
     * the logarithm
     */

    int         size = 0;
    int         i;
    signed long int abs_long_val = long_val;
    signed long int extract;
    signed long int reach_limit;

    if (abs_long_val < 0)
    {
        abs_long_val *= -1;
        var->sign = NUMERIC_NEG;
    }
    else
        var->sign = NUMERIC_POS;

    reach_limit = 1;
    do
    {
        size++;
        reach_limit *= 10;
    } while (reach_limit - 1 < abs_long_val && reach_limit <= LONG_MAX / 10);

    if (reach_limit > LONG_MAX / 10)
    {
        /* add the first digit and a .0 */
        size += 2;
    }
    else
    {
        /* always add a .0 */
        size++;
        reach_limit /= 10;
    }

    if (alloc_var(var, size) < 0)
        return -1;

    var->rscale = 1;
    var->dscale = 1;
    var->weight = size - 2;

    i = 0;
    do
    {
        extract = abs_long_val - (abs_long_val % reach_limit);
        var->digits[i] = extract / reach_limit;
        abs_long_val -= extract;
        i++;
        reach_limit /= 10;

        /*
         * we can abandon if abs_long_val reaches 0, because the memory is
         * initialized properly and filled with '0', so converting 10000 in
         * only one step is no problem
         */
    } while (abs_long_val > 0);

    return 0;
}

int PGTYPESnumeric_mul ( numeric ,
numeric ,
numeric  
)

Definition at line 977 of file numeric.c.

{
    NumericDigit *res_buf;
    NumericDigit *res_digits;
    int         res_ndigits;
    int         res_weight;
    int         res_sign;
    int         i,
                ri,
                i1,
                i2;
    long        sum = 0;
    int         global_rscale = var1->rscale + var2->rscale;

    res_weight = var1->weight + var2->weight + 2;
    res_ndigits = var1->ndigits + var2->ndigits + 1;
    if (var1->sign == var2->sign)
        res_sign = NUMERIC_POS;
    else
        res_sign = NUMERIC_NEG;

    if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
        return -1;
    res_digits = res_buf;
    memset(res_digits, 0, res_ndigits);

    ri = res_ndigits;
    for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
    {
        sum = 0;
        i = --ri;

        for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
        {
            sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
            res_digits[i--] = sum % 10;
            sum /= 10;
        }
        res_digits[i] = sum;
    }

    i = res_weight + global_rscale + 2;
    if (i >= 0 && i < res_ndigits)
    {
        sum = (res_digits[i] > 4) ? 1 : 0;
        res_ndigits = i;
        i--;
        while (sum)
        {
            sum += res_digits[i];
            res_digits[i--] = sum % 10;
            sum /= 10;
        }
    }

    while (res_ndigits > 0 && *res_digits == 0)
    {
        res_digits++;
        res_weight--;
        res_ndigits--;
    }
    while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
        res_ndigits--;

    if (res_ndigits == 0)
    {
        res_sign = NUMERIC_POS;
        res_weight = 0;
    }

    digitbuf_free(result->buf);
    result->buf = res_buf;
    result->digits = res_digits;
    result->ndigits = res_ndigits;
    result->weight = res_weight;
    result->rscale = global_rscale;
    result->sign = res_sign;
    result->dscale = var1->dscale + var2->dscale;

    return 0;
}

numeric* PGTYPESnumeric_new ( void   ) 

Definition at line 126 of file numeric.c.

{
    numeric    *var;

    if ((var = (numeric *) pgtypes_alloc(sizeof(numeric))) == NULL)
        return NULL;

    if (alloc_var(var, 0) < 0)
    {
        free(var);
        return NULL;
    }

    return var;
}

int PGTYPESnumeric_sub ( numeric ,
numeric ,
numeric  
)

Definition at line 846 of file numeric.c.

{
    /*
     * Decide on the signs of the two variables what to do
     */
    if (var1->sign == NUMERIC_POS)
    {
        if (var2->sign == NUMERIC_NEG)
        {
            /* ----------
             * var1 is positive, var2 is negative
             * result = +(ABS(var1) + ABS(var2))
             * ----------
             */
            if (add_abs(var1, var2, result) != 0)
                return -1;
            result->sign = NUMERIC_POS;
        }
        else
        {
            /* ----------
             * Both are positive
             * Must compare absolute values
             * ----------
             */
            switch (cmp_abs(var1, var2))
            {
                case 0:
                    /* ----------
                     * ABS(var1) == ABS(var2)
                     * result = ZERO
                     * ----------
                     */
                    zero_var(result);
                    result->rscale = Max(var1->rscale, var2->rscale);
                    result->dscale = Max(var1->dscale, var2->dscale);
                    break;

                case 1:
                    /* ----------
                     * ABS(var1) > ABS(var2)
                     * result = +(ABS(var1) - ABS(var2))
                     * ----------
                     */
                    if (sub_abs(var1, var2, result) != 0)
                        return -1;
                    result->sign = NUMERIC_POS;
                    break;

                case -1:
                    /* ----------
                     * ABS(var1) < ABS(var2)
                     * result = -(ABS(var2) - ABS(var1))
                     * ----------
                     */
                    if (sub_abs(var2, var1, result) != 0)
                        return -1;
                    result->sign = NUMERIC_NEG;
                    break;
            }
        }
    }
    else
    {
        if (var2->sign == NUMERIC_NEG)
        {
            /* ----------
             * Both are negative
             * Must compare absolute values
             * ----------
             */
            switch (cmp_abs(var1, var2))
            {
                case 0:
                    /* ----------
                     * ABS(var1) == ABS(var2)
                     * result = ZERO
                     * ----------
                     */
                    zero_var(result);
                    result->rscale = Max(var1->rscale, var2->rscale);
                    result->dscale = Max(var1->dscale, var2->dscale);
                    break;

                case 1:
                    /* ----------
                     * ABS(var1) > ABS(var2)
                     * result = -(ABS(var1) - ABS(var2))
                     * ----------
                     */
                    if (sub_abs(var1, var2, result) != 0)
                        return -1;
                    result->sign = NUMERIC_NEG;
                    break;

                case -1:
                    /* ----------
                     * ABS(var1) < ABS(var2)
                     * result = +(ABS(var2) - ABS(var1))
                     * ----------
                     */
                    if (sub_abs(var2, var1, result) != 0)
                        return -1;
                    result->sign = NUMERIC_POS;
                    break;
            }
        }
        else
        {
            /* ----------
             * var1 is negative, var2 is positive
             * result = -(ABS(var1) + ABS(var2))
             * ----------
             */
            if (add_abs(var1, var2, result) != 0)
                return -1;
            result->sign = NUMERIC_NEG;
        }
    }

    return 0;
}

char* PGTYPESnumeric_to_asc ( numeric ,
int   
)

Definition at line 428 of file numeric.c.

{
    numeric    *numcopy = PGTYPESnumeric_new();
    char       *s;

    if (dscale < 0)
        dscale = num->dscale;

    if (PGTYPESnumeric_copy(num, numcopy) < 0)
    {
        PGTYPESnumeric_free(numcopy);
        return NULL;
    }
    /* get_str_from_var may change its argument */
    s = get_str_from_var(numcopy, dscale);
    PGTYPESnumeric_free(numcopy);
    return (s);
}

int PGTYPESnumeric_to_decimal ( numeric ,
decimal  
)

Definition at line 1623 of file numeric.c.

{
    int         i;

    if (src->ndigits > DECSIZE)
    {
        errno = PGTYPES_NUM_OVERFLOW;
        return -1;
    }

    dst->weight = src->weight;
    dst->rscale = src->rscale;
    dst->dscale = src->dscale;
    dst->sign = src->sign;
    dst->ndigits = src->ndigits;

    for (i = 0; i < src->ndigits; i++)
        dst->digits[i] = src->digits[i];

    return 0;
}

int PGTYPESnumeric_to_double ( numeric ,
double *   
)

Definition at line 1564 of file numeric.c.

{
    double      tmp;

    if (numericvar_to_double(nv, &tmp) != 0)
        return -1;
    *dp = tmp;
    return 0;
}

int PGTYPESnumeric_to_int ( numeric ,
int *   
)

Definition at line 1575 of file numeric.c.

{
    long        l;
    int         i;

    if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
        return i;

    if (l < -INT_MAX || l > INT_MAX)
    {
        errno = PGTYPES_NUM_OVERFLOW;
        return -1;
    }

    *ip = (int) l;
    return 0;
}

int PGTYPESnumeric_to_long ( numeric ,
long *   
)

Definition at line 1594 of file numeric.c.

{
    char       *s = PGTYPESnumeric_to_asc(nv, 0);
    char       *endptr;

    if (s == NULL)
        return -1;

    errno = 0;
    *lp = strtol(s, &endptr, 10);
    if (endptr == s)
    {
        /* this should not happen actually */
        free(s);
        return -1;
    }
    free(s);
    if (errno == ERANGE)
    {
        if (*lp == LONG_MIN)
            errno = PGTYPES_NUM_UNDERFLOW;
        else
            errno = PGTYPES_NUM_OVERFLOW;
        return -1;
    }
    return 0;
}