[comp.lang.c] Packed Decimal Conversion fns sought, TFM is silent

jdm1@eds1.UUCP (Jon McCown) (06/21/89)

I am looking for routines to munge IBM/370 style packed decimal data into
a long (or int) and vice versa.  ptol or ltop anyone?  Range checking is
not a major concern (yet).

My work on the problem has produced some medium kludgy and slow routines that
have yet to be proven reliable.  Surely someone has an elegant (or at least
well tested) shot at this. . . . ?

- Jon McCown

(No, I don't have a COBOL compiler on the system :-)


-- 
             J.D. McCown - RCSG Director - Senate of Pennsylvania  
psuvax1!eds1!jdm1     (this space intentionally     "Your life or your lupins!" 
jdm1@eds1.eds.com      filled with this text)                   - Dennis Moore

abbadon@nuchat.UUCP (David Neal) (06/29/89)

#include <stdio.h>


/* Routine to unpack BCD packed decimal into an integer. */

unpack(packed, length, unpacked)
char packed[];                  /* Array of chars containing packed number */
int length;                     /* Length of the array (not '\0' terminated) */
int *unpacked;                  /* Pointer to integer for return value */
{

  register int i, j;
  static char asciibuf[128];   /* Number cannot be > 63 digits in length */

  j = 0;
  length--;                    /* Decrement length; we always use length - 1
                                  because of the special case and because
                                  of 'C' array indices start at 0. */

  /* Run to length-1 bytes; last byte is a special case */

  for ( i = 0; i < length; i++ )
    {
      asciibuf[j++] = ( (packed[i] & 0xf0) >> 4 ) + 0x30;
      asciibuf[j++] =   (packed[i] & 0x0f)        + 0x30; 
 
                                    /* 0x30 is the delta between BCD nybble
				       x and it's ascii counterpart. */
    }

  asciibuf[j++] = ( (packed[length] & 0xf0) >> 4 ) + 0x30;
  asciibuf[j] = '\0';
  
  fprintf(stderr, "unpack: %s \n", asciibuf);

  *unpacked = atoi(asciibuf);

  /* Special case: If the last nybble is 0x0d, the number is negative */
  if ( (packed[length] & 0x0f) == 0x0d ) *unpacked *= -1;

}

Sorry about the wasted bandwith; this guys mail bounces
and he's tough to get on the phone! Please no flamage
about system dependant this or messy that; it's just
a quick hack to help the guy.


David Neal
abbadon@nuchat.UUCP
uunet!nuchat!abbadon killer!texbell!nuchat!abbadon