Comp-3 conversion possible with Shell Scripting or PERL?

I guess the subject asks it all, but I am wondering (before I go and code a COBOL module) if conversion of regular ASCII data to COMP-3 is possible on a UNIX environment (AIX 5.1)? Any help would be appreciated! Thanks, Dave

If you are talking about "Packing" the data which is what COMP-3 does in COBOL then yes you will have to write a COBOL program to do that. I don't know of anything in UNIX that will do that without using COBOL. Of course I am not a UNIX expert so I could be wrong. Good Luck!

jyoung, meet ksh. This script will convert an integer argument to packed decimal.

#! /usr/bin/ksh
typeset -R1 dig
typeset -i8 octal
typeset -Z4 result

#
#  handle sign

number=$1
sign="C"
if ((number<0)) ; then
        ((number=-number))
        sign="D"
fi


#
#  prepend a zero if needed

((ilength=${#number}))
if ((ilength/2*2 == ilength)) ; then
        number=0${number}
        ((ilength=${#number}))
fi

#
#  conversion loop

((olength=ilength/2))
packswitch=1
char2=$sign
while ((ilength)) ; do
        dig=$number
        ((ilength=ilength-1))
        typeset -L$ilength newnumber=$number
        number=$newnumber
        if ((packswitch)) ; then
                char1=$dig
                octal=16#${char1}${char2}
                result=${octal#??}
                echo packing $olength $char1 $char2 $octal $result
                output[olength]=$(print -n \\${result})
                ((olength=olength-1))

        else
                char2=$dig
        fi
        ((packswitch=!packswitch))
done

#
#  output the packed decimal to prove it worked

olength=${#output[*]}
o=0
while ((o <= olength)) ; do
        print -n ${output[o]} | od -t x1
        ((o=o+1))
done

exit 0

Thanks Per. I'm assuming this doesn't work for decimal data? Only true integers?

/home/rse0/xxgvlqr> /home/rse0/xxgvlqr/ascii_to_packed.ksh 123.45
packing 3 5 C 8#134 0134
/home/rse0/xxgvlqr/ascii_to_packed.ksh[39]: 16#.4: bad number

With packed decimal, any decimal point is assumed. It is not stored in the data.

Per, thanks very very much for your help. I think this will save me from having to write a COBOL routine. One more question: do you know of a way to put out "low-values" or "high-values" through a script. Basically we want our summary record to look like this:

high values positions 1-5
# of records in the file positions 6-10

Totaling the records, I can handle. LOL. Just need to know if there is a way to "write" low values or hgih values within a shell script. Thanks.

So the total field is numeric rather than packed decimal? I think this should do it:
high5=$(print -n \\0377\\0377\\0377\\0377\\0377)

Define your total field like this:
typeset -Z5 total
to get the leading zeroes you will need.

Remember that ksh will add new line characters unless you supress them:
print -n ${high5}${total}

To test this:

$ cat x
#! /usr/bin/ksh
high5=$(print -n \\0377\\0377\\0377\\0377\\0377)
typeset -Z5 total
total=123
print -n ${high5}${total} | od -t x1
$  ./x
0000000   ff  ff  ff  ff  ff  30  30  31  32  33
0000012
$

Per, need some more help. Noting your quote above, we have a field that is signed (see below) that I need to put into comp-3 format. Any ideas? I know you said the decimal is implied, but what about handling a positive or negative number?

+000000000050408

or

-000086214050408

Take another look. The script handles negative numbers.

Oops, sorry about that. Was so concerned about the packing piece of the puzzle that I overlooked the negative handling. One thing in your script has me confused. I did a man on "od" and there is no "-t" option. What is this line doing:

print -n ${output[o]} | od -t x1

Also, in your script, is it the "$result" variable that is ultimately holding the packed output? With all of the outputting in different formats and display messages (and my "light" UNIX coding experience), I got a little disoriented.

Here is the AIX man page for od. I see the -t option which is required for posix compatability.

Look at the end of my script:

#
#  output the packed decimal to prove it worked

olength=${#output[*]}
o=0
while ((o <= olength)) ; do
        print -n ${output[o]} | od -t x1
        ((o=o+1))
done

The output is in "output".

I have tried using the sample script, but have a problem when trying to pack a number that has concurrent zeroes. The result of packing to two zeroes results in a null hex value, that cannot be printed. Is there any way to deal with this?

Thanks for the info.

I found this thread showing how to make a Comp-3 field. However, I have to accomplish the opposite:
Read a count variable stored as Comp-3 telling me how many records to expect. Then, report back if I received all of the records in an ftp.

So, any ideas or past scripts, on how to convert a signed Comp-3 field?

Thanks.

The main problem is that comp-3 is just binary data. Thoughout the thread I am doing stuff like "print -n ${output[o]} | od -t x1" because the data is binary. This is why coutulea's question made no sense. So where is your data? How do you propose to make it available to a shell script? If you can isolate the comp-3 field and pump it through od and read the out of od into a script, it probably can be done.