home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / packdec.zip / PD.C < prev    next >
C/C++ Source or Header  |  1994-09-01  |  5KB  |  155 lines

  1. /*
  2.  
  3.     Packed Decimal, Binary Conversion
  4.     Copyright (c) 1994, Iambic Software, Inc.
  5.     All rights reserved
  6.  
  7. */
  8.  
  9.  
  10. #include <mem.h>
  11. #include "pd.h"
  12.  
  13.  
  14. short int sPackedToBin( unsigned char *pPack, long *lBin, short nLen )
  15. {
  16. /************************************************************
  17.  
  18.    Name:  sPackedToBin
  19.  
  20.    Function:
  21.  
  22.       This routine will convert IBM 370 packed dicimal numbers to fixed
  23.       point binary numbers four bytes long.
  24.  
  25.    arguments:
  26.  
  27.       1.  unsigned char pointer to the packed decimal number, max length
  28.       is six bytes.
  29.  
  30.       2.  pointer to a long int to receive the result.
  31.  
  32.       3.  short int length of argument 1, the packed decimal number.
  33.  
  34.    return codes:
  35.  
  36.       0   success
  37.       1   invalid decimal digit
  38.       2   overflow, numbers greater than 2,147,483,647 (0x7fffff)
  39.       3   invalid length specified
  40.  
  41.  
  42. *************************************************************/
  43.  
  44.  
  45.    short int             iI;           /* loop index */
  46.    unsigned short int    iFirstNib;    /* first nibble */
  47.    unsigned short int    iLastNib;     /* last nibble */
  48.    long int              lTBin;        /* binary work */
  49.    unsigned char         *pWork;       /* work pointer for packed number */
  50.  
  51.    if ( nLen > 6 || nLen < 1 )         /* validate length */
  52.       return( 3 );
  53.    lTBin = 0;                          /* initialize work number */
  54.    pWork = pPack;                      /* copy pointer to work */
  55.    for( iI = 1; iI <= nLen; iI++ )
  56.    {
  57.       iFirstNib = ( *pWork & 0xf0 ) >> 4; /* obtain high order 4 bits */
  58.         iLastNib = *pWork & 0x0f;           /* obtain low order 4 bits */
  59.       if ( iFirstNib > 0x90 )      /* check first nibble */
  60.      return( 1 );
  61.       if ( iI != nLen )            /* is this the last byte ? */
  62.       {
  63.      if ( iLastNib > 9 )       /* last nibble digit ok ? */
  64.         return( 1 );
  65.       }
  66.       else
  67.       {
  68.      if ( iLastNib < 10 )      /* last nibble of number, for sign */
  69.         return( 1 );
  70.       }
  71.       lTBin *= 10;                /* shift one digit to left */
  72.       lTBin += iFirstNib;         /* add in the next number */
  73.       if ( lTBin < 0 )            /* number has overflowed */
  74.      return(2);
  75.       if ( iI != nLen )           /* last byte, dont add sign */
  76.       {
  77.      lTBin *= 10;             /* shift one byte to the left */
  78.      lTBin += iLastNib;       /* add in the next number */
  79.      if ( lTBin < 0 )         /* number has overflowed */
  80.      return(2);
  81.         }
  82.       pWork++;                    /* point to the next output byte */
  83.    }
  84.    switch ( iLastNib )            /* make negative if needed */
  85.    {
  86.       case 0x0b:                  /* negative  decimal signs ? */
  87.       case 0x0d:
  88.      lTBin *= -1;             /* make the number negative */
  89.      break;
  90.    }
  91.    *lBin = lTBin;               /*  return the result to the source field */
  92.    return( 0 );
  93. }
  94. /************************************************************
  95.  
  96.    Name:  sBinToPacked
  97.  
  98.    Function:
  99.  
  100.       This routine will convert long binary number to IBM 370 packed
  101.       decimal format eight bytes long.
  102.  
  103.    arguments:
  104.  
  105.       1.  unsigned char pointer to the packed decimal number result
  106.       8 bytes long
  107.  
  108.       2.  pointer to a long int to convert.
  109.  
  110.    return codes:
  111.  
  112.       0   success
  113.  
  114. *************************************************************/
  115. short int sBinToPacked( unsigned char *pPack, long *lBin )
  116. {
  117.    unsigned char *pPkd;             /* working pointer for packed numb */
  118.    long          lWBin;             /* working binary number */
  119.    unsigned char Pkd[8];            /* work packed number */
  120.    short         iRem;              /* remainder (may cause warnings
  121.                        abound significant digits during
  122.                        compile )                      */
  123.    short          iI;               /* loop counter */
  124.    lWBin = *lBin;                   /* copy input */
  125.    memset( Pkd, 0, 8);              /* clear number */
  126.    pPkd = Pkd + 7;                  /* point to last byte of packed num */
  127.     if ( lWBin < 0 )                 /* is number negative */
  128.    {
  129.       *pPkd |= 0x0d;                /* move in negative sign */
  130.       lWBin *= -1;                  /* make it positive */
  131.    }
  132.    else
  133.       *pPkd |= 0x0c;                /* move in positive sign */
  134.    iRem = lWBin % 10;               /* get ones digit */
  135.    *pPkd |= iRem << 4;              /* add digit to number */
  136.    lWBin /= 10;                     /* divide by 10 */
  137.    for ( iI=1 ; iI < 8 ; iI++ )     /* setup loop for remainder of digits */
  138.    {
  139.      pPkd--;                        /* move pointer one left */
  140.       if ( ! lWBin )                /* no more digits, exit */
  141.      break;
  142.       iRem = lWBin % 10;            /* get next digit */
  143.       *pPkd |= iRem;                /* add digit to packed number */
  144.       lWBin /= 10;                  /* divide number by 10 */
  145.       if ( ! lWBin )                /* no more digits, exit */
  146.      break;
  147.       iRem = lWBin % 10;            /* get next digit */
  148.       *pPkd |= iRem << 4;           /* add digit to paced number */
  149.       lWBin /= 10;                  /* divide number by 10 */
  150.     }
  151.    memmove( pPack, Pkd, 8);         /* return number to target field */
  152.    return( 0 );
  153. }
  154.  
  155.