[comp.lang.asm370] Floating pt to and from EBCDIC

royf@attctc.Dallas.TX.US (Roy Frederick) (08/15/89)

Here are a couple of routines I cut out of a calculator program I
wrote several years ago.  The calculator itself runs on a TP monitor
used only at Dallas County - but these routines should be usable
anywhere (on an IBM mainframe or compatible, of course).

AFP converts an EBCDIC string into internal long floating point.  Put
the address of the first character of the string into SCAN.  SCAN
should not point to a space.  Put the length of the string into SCAN
+ 4 - trailing spaces are ok.  AFP will leave the result in FPR0 if
RC = 0.  RC = 4 means it found an error.  SCAN and SCAN + 4 will be
updated to point past the portion of the string converted.

CEF converts to external floating format.  Input is in FPR0.  R1
points to flags that control the result format.  Try r1->x'2785' for
a first attempt.  This should be similar to G15.5 in fortran.  Look
at the comments at the start of CEF for the details.  These routines
work only with long floating format - but it is a simple matter to
convert to and from short format if desired - at the input of CEF and
the output of AFP.

It is quite possible that there are easier and/or better ways to do
these conversions.  These routines are not claimed to be the best of
their genre - but they work for me.  Note that I did have to modify
them slightly to remove some macro calls peculiar to our TP system -
Entry and Exit macros dealing with save areas.  Hopefully I did not
introduce any errors in the process.

AFP, CEF, and FAM are free of copyright restrictions.

------------------ Cut Here -----------------------------
.AFP	 SPACE 2
**	 AFP --	ASSEMBLE FLOATING POINT	OPERAND
*
*	 ENTRY SCAN CONTAINS ADDR OF CHARS TO CONVERT
*	       SCAN + 4	CONTAINS LENGTH	OF STRING
*
*	 EXIT  RC = 0, FPR0 CONTAINS LONG FP RESULT
*	       RC = 4, STRING WAS INVALID NUMBER
*
*
AFP	 STM   14,12,12(13)	  SAVE REGS
	 SR    3,3		  SET EXPONENT TO ZERO
	 LD    0,=D'1.0'	  SET MULTIPLIER = 1
	 MVI   AFPF,0		  CLEAR	FLAG
	 LD    6,=D'0'		  PRESET ZERO RESULT
	 LM    4,5,SCAN		  POINT	TO INPUT OPERAND
*
AFP1	 CLI   0(4),C'+'	  SEE IF POSITIVE
	 BE    AFP8
	 CLI   0(4),C'-'	  SEE IF NEGATIVE
	 BE    AFP4
	 CLI   0(4),C'.'	  SEE IF DECIMAL POINT
	 BE    AFP6
	 CLI   0(4),C'E'	  SEE IF EXPONENT
	 BE    AFP7
*
	 CLI   0(4),C'0'	  MUST BE A DECIMAL DIGIT
	 BL    AFP10		  IF NOT
	 CLI   0(4),C'9'
	 BH    AFP10		  IF NOT
	 OI    AFPF,X'08'	  SHOW DIGITS FOUND
	 MVN   AFPW+7(1),0(4)	  SET DIGIT VALUE
	 TM    AFPF,X'80'	  SEE IF DIGIT IN EXPONENT
	 BO    AFP3		  IF SO
	 TM    AFPF,X'40'	  SEE IF FRACTION DIGIT
	 BO    AFP2		  IF SO
	 MD    6,=D'10.0'	  SHIFT	RESULT 1 DIGIT
	 AD    6,AFPW		  ADD IN CURRENT DIGIT
	 B     AFP9
*
AFP2	 LD    2,AFPW		  GET CURRENT DIGIT
	 AD    2,=D'0'		  NORMALIZE IT
	 DD    0,=D'10.0'	  SCALE	MULTIPLIER
	 MDR   2,0		  SHIFT	CURRENT	DIGIT
	 ADR   6,2		  ADD IN CURRENT SHIFTED DIGIT
	 B     AFP9		  NEXT CHARACTER
*
AFP3	 MH    3,=H'10'		  SHIFT	EXPONENT
	 AH    3,AFPW+6		  ADD IN CURRENT DIGIT
	 B     AFP9		  NEXT CHARACTER
*
AFP4	 TM    AFPF,X'68'	  SEE IF SIGN, DIGITS, OR DECIMAL
	 BNZ   AFP10		  END OF NUMBER	IF SO
	 TM    AFPF,X'80'	  SEE IF EXPONENT SIGN
	 BO    AFP5
	 OI    AFPF,X'30'	  SET NEGATIVE
	 B     AFP9		  NEXT CHARACTER
*
AFP5	 OI    AFPF,X'24'	  SET NEGATIVE EXPONENT, SIGN CHAR
	 B     AFP9		  NEXT CHARACTER
*
AFP6	 TM    AFPF,X'C0'	  SEE IF DECIMAL OR E
	 BNZ   ERR2		  *INVALID FP NUMBER*
	 OI    AFPF,X'40'	  SHOW DECIMAL ENCOUNTERED
	 B     AFP9		  NEXT CHARACTER
*
AFP7	 TM    AFPF,X'80'	  SEE IF E ALREADY FOUND
	 BO    ERR2
	 TM    AFPF,X'08'	  MUST BE SOME DIGITS
	 BZ    ERR2
	 NI    AFPF,255-X'68'	  NO SIGN, NO DIGITS
	 OI    AFPF,X'80'	  SHOW EXPONENT	PRESENT
	 B     AFP9		  NEXT CHARACTER
*
AFP8	 TM    AFPF,X'68'	  SEE IF SIGN, DIGITS, OR DECIMAL
	 BNZ   AFP10		  END OF NUMBER	IF SO
	 OI    AFPF,X'20'	  SET SIGN FLAG
*
AFP9	 LA    4,1(,4)		  NEXT INPUT CHARACTER
	 BCT   5,AFP1		  LOOP FOR ALL CHARACTERS
*
AFP10	 STM   4,5,SCAN		  RESET	SCAN PTRS
	 TM    AFPF,X'80'	  SEE IF ANY EXPONENT
	 BZ    AFP11		  IF NOT
	 TM    AFPF,X'08'	  MUST BE SOME DIGITS IF E
	 BZ    ERR2		  *INVALID FP NUMBER*
*
AFP11	 TM    AFPF,X'10'	  SEE IF NEGATIVE MANTISSA
	 BZ    AFP12		  IF NOT
	 LNDR  6,6		  MAKE IT NEGATIVE
*
AFP12	 LTR   3,3		  SEE IF ANY EXPONENT SPECIFIED
	 BNP   AFP14		  IF NOT
	 LD    0,=D'10.0'	  ASSUME POSITIVE EXPONENT
	 TM    AFPF,X'04'	  SEE IF NEGATIVE EXPONENT
	 BZ    AFP13		  IF NOT
	 LD    0,=D'0.10'	  SET NEGATIVE EXPONENT	MULTIPLIER
*
AFP13	 MDR   6,0		  SCALE	RESULT
	 BCT   3,AFP13
*
AFP14	 STD   6,AFPR		  STORE	RESULT
	 CLC   AFPR+1(7),=XL7'00' SEE IF TRUE ZERO REQUIRED
	 BNE   AFPX
	 XC    AFPR,AFPR	  INSURE RESULT	IS A TRUE ZERO
APFX	 LD    0,AFPR		  GET RESULT IN	FPR0
	 LM    14,12,12(13)	  RESTORE REGS
	 SR    15,15		  GIVE GOOD RC
	 BR    14		  RETURN TO CALLER
*
ERR2	 XC    AFPR,AFPR	  CLEAR	RESULT
	 LD    0,AFPR
	 LM    14,12,12(13)
	 LA    15,4		  GIVE BAD RC
	 BR    14
*
AFPR	 DC    D'0'		  RESULT
*
AFPW	 DC    X'4E00000000000000' WORK	AREA
*
AFPF	 DC    X'00'
*	 ...   X'80'		  'E' ENCOUNTERED
*	 ...   X'40'		  '.' ENCOUNTERED
*	 ...   X'20'		  SIGN ENCOUNTERED
*	 ...   X'10'		  NEGATIVE MANTISSA
*	 ...   X'08'		  DIGITS ENCOUNTERED
*	 ...   X'04'		  NEGATIVE EXPONENT
*
SCAN	 DC    A(0)		  SCAN ADDRESS
	 DC    F'0'		  LENGTH
.CEF	 SPACE 2
**	 CEF --	CONVERT	TO EXTERNAL FLOATING
*
*	 FPR0 -	NUMBER TO BE CONVERTED
*
*	 R1 -> FFNM
*	       FF = 80,	F, FIXED FORMAT
*		    40,	S, SCIENTIFIC FORMAT
*		    20,	G, EITHER OF ABOVE
*		    10,	E, ENGINEERING FORMAT
*		    08,	%, FIXED NOTATION, SCALE BY 100
*
*		    B'00000111'	SIGN OPTION
*
*		    00,	NO SIGN	DISPLAYED
*		    01,	TRAILING - SIGN	OPTION
*		    02,	CR SIGN	OPTION
*		    03,	DB SIGN	OPTION
*		    04,	$, CR
*		    05,	$, DB
*		    06,	+ SIGN OPTION
*		    07,	- SIGN OPTION
*
*	       N  = NUMBER OF FRACTION DIGITS
*	       M  = NUMBER OF INTEGER DIGITS
*
*
CEF	 STM   14,12,12(13)	  SAVE REGS
	 ST    13,CEFV+4	  BACKCHAIN
	 LA    13,CEFV		  POINT	TO SAVE	AREA
*
	 MVC   CEFB,0(1)	  SAVE FLAG BYTE
	 MVC   CEFC,CEFB	  SET SIGN CONTROL BITS
	 NI    CEFC,X'07'	  SAVE ONLY SIGN BITS
	 MVN   CEFI+1(1),1(1)	  SAVE NUMBER OF INTEGER DIGITS
	 IC    1,1(,1)		  SAVE NUMBER OF FRACTION DIGITS
	 SRL   1,4
	 STC   1,CEFF+1
	 NI    CEFF+1,X'0F'	  ...
*
	 TM    CEFB,X'08'	  SEE IF PERCENT NOTATION
	 BZ    CEF1		  IF NOT
	 MD    0,=D'100.0'	  SCALE	PERCENTAGE
*
CEF1	 LA    1,3		  CHECK	FOR MIN	INTEGER	LOCATIONS
	 TM    CEFB,X'10'	  SEE IF ENG NOTATION
	 BO    CEF2
	 LA    1,1
	 TM    CEFB,X'60'	  SCI OR SCI/FIX
	 BO    CEF2
	 SR    1,1		  NO INTEGER PORTION REQUIRED
CEF2	 CH    1,CEFI		  CHECK	AGAINST	LIMIT
	 BNH   CEF3
	 STH   1,CEFI		  SET MINIMUM
*
CEF3	 MVI   CEFS,C'+'	  ASSUME POSITIVE VALUE
	 LTDR  0,0		  TEST INPUT VALUE
	 BNM   CEF4		  IF NOT NEGATIVE
	 MVI   CEFS,C'-'	  SET NEGATIVE SIGN
*
CEF4	 MVC   CEFO,CEFO-1	  CLEAR	OUTPUT AREA
	 LA    7,CEFO		  POINT	TO OUTPUT AREA
	 CLI   CEFC,X'04'	  SEE IF LEADING SIGN OR CURRENCY
	 BL    CEF8		  DO NOT ALLOW SPACE FOR IT
	 CLI   CEFC,X'06'	  SEE IF + SIGN	OPTION
	 BE    CEF6
	 CLI   CEFC,X'07'	  SEE IF - SIGN	OPTION
	 BE    CEF5		  IF SO
	 MVI   0(7),C'$'	  SET CURRENCY SIGN
	 B     CEF7
CEF5	 CLI   CEFS,C'+'	  SEE IF POSITIVE
	 BE    CEF7		  IF SO
CEF6	 MVC   0(1,7),CEFS	  STORE	SIGN
CEF7	 LA    7,1(,7)		  ADVANCE POINTER
*
CEF8	 SR    6,6		  SET ZERO EXPONENT
	 LPDR  0,0		  SET POSITIVE SIGN
	 BZ    CEF14		  IF ZERO ARG
*
	 LD    4,=D'1.0'	  COMPUTE ROUNDING FACTOR
	 LH    2,CEFF		  GET NUMBER OF	FRACTION DIGITS
	 SLL   2,3		  INDEX	INTO SCALE TABLE
	 DD    4,CEFT00(2)	  1.0/SCALE FACTOR
	 HDR   4,4		  1.0/(2*SCALE FACTOR)
*
CEF9	 TM    CEFB,X'40'	  SEE IF SCI FORMAT
	 BO    CEF10		  IF SO
	 LH    1,CEFI		  GET INTEGER DIGITS REQUIRED
	 SLL   1,3		  X LENGTH OF FP NUMBER
	 CD    0,CEFT00(1)	  SEE IF TOO LARGE FOR F FORMAT
	 BNL   CEF10		  IF NOT
	 TM    CEFB,X'80'	  SEE IF FIXED POINT
	 BO    CEF13		  NO SCALING IF	SO
	 CD    0,=D'1.0'	  SEE IF ARG LT	1
	 BNL   CEF13		  IF NOT
	 TM    CEFB,X'10'	  SEE IF ENG FORMAT
	 BO    CEF10		  SCALE	ARG IF ENG
	 LH    1,CEFF		  PREPARE FOR SIGNIFICANCE LOSS	TEST
	 SLL   1,3
	 LD    2,=D'1.0'
	 DD    2,CEFT00(1)	  SIGNIFICANCE FACTOR
	 CDR   0,2
	 BH    CEF13		  IF SOME SIGNIFICANCE RETAINED
*
CEF10	 LD    2,CEFT01		  PRESET SCI SCALING FACTOR
	 LA    2,1		  SET SCALE = 1
	 TM    CEFB,X'10'	  SEE IF ENG FORMAT REQUIRED
	 BZ    CEF11		  IF NOT
	 LD    2,CEFT03		  SET ENG SCALING FACTOR
	 LA    2,3		  SET SCALE = 3
CEF11	 CD    0,=D'1.0'
	 BNL   CEF12		  IF NEG SCALING NOT REQUIRED
	 MDR   0,2		  SCALE	IT
	 SR    6,2		  ADJUST EXPONENT
	 B     CEF11		  LOOP FOR ALL NEG SCALING
CEF12	 CDR   0,2		  CHECK	FOR POSITIVE SCALING
	 BL    CEF13		  IF OK
	 DDR   0,2		  SCALE	IT
	 AR    6,2		  ADJUST EXPONENT
	 B     CEF12
*
CEF13	 LTDR  4,4		  SEE IF ANY ROUNDING FACTOR
	 BZ    CEF14
	 ADR   0,4		  ROUND	SCALED RESULT
	 LD    4,=D'0'		  ZERO OUT ROUNDING FACTOR
	 B     CEF9
*
CEF14	 STD   0,CEFA		  SAVE ROUNDED ABS OF INPUT VALUE
*
	 LH    2,CEFI		  GET INTEGER POSITIONS
	 BAL   14,FAM		  FIX AND MOVE INTEGER DIGITS
*
	 LH    2,CEFF		  GET NUMBER OF	FRACTION DIGITS
	 SLA   2,3		  X LENGTH OF FP NUMBER
	 BZ    CEF15		  IF NO	FRACTION DIGITS	REQUIRED
	 MVI   0(7),C'.'	  STORE	DECIMAL	POINT
	 LA    7,1(,7)		  SKIP DECIMAL POINT
	 AD    0,=D'0'		  GET FRACTION
	 SD    0,CEFA
	 LPDR  0,0		  ...
	 MD    0,CEFT00(2)	  SCALE	FRACTION INTO INTEGER
	 LH    2,CEFF		  GET FRACTION POSITIONS
	 BAL   14,FAM		  FIX AND MOVE FRACTION	DIGITS
*
CEF15	 TM    CEFB,X'40'	  SEE IF SCIENTIFIC
	 BO    CEF16		  ALWAYS DISPLAY EXPONENT IF SCI
	 LTR   6,6		  SEE IF ANY EXPONENT
	 BZ    CEF18		  IF NOT
CEF16	 MVC   0(2,7),=C'E+'	  STORE	EXP INDICATOR
	 LTR   6,6		  SEE IF NEGATIVE EXPONENT
	 BNM   CEF17
	 MVI   1(7),C'-'	  SET NEGATIVE EXP
CEF17	 LPR   6,6		  CONVERT EXPONENT
	 CVD   6,DWORK		  ...
	 OI    DWORK+7,X'0F'	  PRINTABLE SIGN
	 UNPK  2(2,7),DWORK	  MOVE TO OUTPUT LINE
	 LA    7,4(,7)		  SKIP EXPONENT
*
CEF18	 CLI   CEFS,C'-'	  SEE IF NEGATIVE
	 BNE   CEF21		  IF NOT
	 CLI   CEFC,X'05'	  CHECK	FOR LEADING SIGN
	 BH    CEF21		  IF LEADING SIGN
	 CLI   CEFC,X'01'
	 BL    CEF21		  IF NO	SIGN DISPLAYED
	 BH    CEF19		  IF CR	OR DB
	 MVI   0(7),C'-'	  STORE	NEG SIGN
	 LA    7,1(,7)		  SKIP NEG SIGN
	 B     CEF21
CEF19	 MVC   0(2,7),=C'DB'	  STORE	A DEBIT	SYMBOL
	 TM    CEFC,X'01'	  SEE IF DEBIT
	 BO    CEF20		  IF SO
	 MVC   0(2,7),=C'CR'	  STORE	A CREDIT SYMBOL
CEF20	 LA    7,2(,7)		  SKIP CR OR DB
*
CEF21	 TM    CEFB,X'08'	  SEE IF PERCENTAGE OUTPUT
	 BZ    CEF22		  IF NOT
	 MVI   0(7),C'%'	  STORE	PERCENT	SIGN
	 LA    7,1(,7)		  SKIP PERCENT SIGN
*
CEF22	 LA    1,CEFO-1		  ZERO SUPPRESS	OUTPUT
CEF23	 LA    1,1(,1)		  NEXT DIGIT
	 CLI   1(1),C'0'	  SEE IF ZERO
	 BNE   CEFX		  IF DONE
	 CLI   2(1),C'0'	  SEE IF NEXT CHAR IS A	DIGIT
	 BL    CEFX		  IF NOT
	 MVC   1(1,1),0(1)	  MOVE SIGN OR CURRENCY
	 MVI   0(1),C' '	  SPACE	OUT ORIGINAL LOC
	 B     CEF23		  LOOP FOR ALL ZEROS TO	BE SUPPRESSED
*
CEFX	 L     13,4(,13)	  RESTORE SAVE AREA ADDR
	 LM    14,12,12(13)	  RESTORE REGS
	 SR    15,15
	 BR    14
*
	 DC    C' '
CEFO	 DC    CL40' '		  OUTPUT AREA
*
CEFT00	 DC    D'1.0E+00'	  POWERS OF 10
CEFT01	 DC    D'1.0E+01'
CEFT02	 DC    D'1.0E+02'
CEFT03	 DC    D'1.0E+03'
CEFT04	 DC    D'1.0E+04'
CEFT05	 DC    D'1.0E+05'
CEFT06	 DC    D'1.0E+06'
CEFT07	 DC    D'1.0E+07'
CEFT08	 DC    D'1.0E+08'
CEFT09	 DC    D'1.0E+09'
CEFT10	 DC    D'1.0E+10'
CEFT11	 DC    D'1.0E+11'
CEFT12	 DC    D'1.0E+12'
CEFT13	 DC    D'1.0E+13'
CEFT14	 DC    D'1.0E+14'
CEFT15	 DC    D'1.0E+15'
CEFT16	 DC    D'1.0E+16'
*
CEFA	 DC    D'0'		  HOLD FOR INPUT ARG
*
CEFB	 DC    X'00'		  FLAG BYTE
CEFC	 DC    X'00'		  SIGN OPTION
*
CEFR	 DC    X'0000000000000001' ROUNDING FACTOR
*
CEFS	 DC    C'+'		  SIGN
*
CEFF	 DC    H'0'		  NUMBER OF FRACTION DIGITS
CEFI	 DC    H'0'		  NUMBER OF INTEGER DIGITS
*
CEFV	 DC    18F'0'		  SAVE AREA
.FAM	 SPACE 2
**	 FAM --	FIX AND	MOVE
*
*
FAM	 STM   14,2,12(13)
	 AW    0,FAMF		  ADD IN FIX CONSTANT
	 STD   0,DWORK		  SAVE FIXED VALUE
	 CLI   DWORK,X'4E'	  SEE IF OVERFLOW
	 BH    ERR1		  IF OVERFLOW
	 XC    FAMW,FAMW	  CLEAR	WORK AREA
	 SR    0,0		  GET UPPER PART OF INTEGER
	 ICM   0,B'0111',DWORK+1  ...
	 L     1,DWORK+4	  GET LOWER PART
	 SLDL  0,1		  MAKE BOTTOM POSITIVE
	 SRL   1,1		  ...
	 CVD   0,FAMW+8		  CONVERT UPPER
	 MP    FAMW,=P'2147483648' SCALE IT
	 CVD   1,DWORK		  CONVERT LOWER	TO DECIMAL
	 AP    FAMW,DWORK	  ADD IN LOWER PART
	 OI    FAMW+15,X'0F'	  PRINTABLE SIGN
	 BCTR  2,0		  LENGTH CODE
	 SLL   2,4		  SHIFT	INTO POSITION
	 EX    2,FAMX1		  MOVE DIGITS TO OUTPUT
	 SRL   2,4		  RESTORE LENGTH CODE
	 LA    7,1(2,7)		  SKIP DIGITS MOVED
	 LM    14,2,12(13)
	 BR    14
*
ERR1	 L     13,4(,13)	  RESTORE SAVE AREA ADDR
	 LM    14,12,12(13)	  RESTORE REGS
	 LA    15,4		  GIVE RC = 4, OVERFLOW
	 BR    14
*
FAMX1	 UNPK  0(0,7),FAMW	  MOVE DIGITS TO OUTPUT	AREA
*
	 DS    0D
FAMF	 DC    X'4E00000000000000' FIX CONSTANT
*
FAMW	 DC    XL16'00'		  WORK AREA
*
DWORK	 DC    D'0'		  WORK
------------------ Cut Here -----------------------------

Roy Frederick - royf@attctc
Dallas County Data Services
504 Records Building
Dallas, TX 75202
(214) 653-6340

royf@TUT.CIS.OHIO-STATE.EDU (Roy Frederick) (08/15/89)

Here are a couple of routines I cut out of a calculator program I
wrote several years ago.  The calculator itself runs on a TP monitor
used only at Dallas County - but these routines should be usable
anywhere (on an IBM mainframe or compatible, of course).

AFP converts an EBCDIC string into internal long floating point.  Put
the address of the first character of the string into SCAN.  SCAN
should not point to a space.  Put the length of the string into SCAN
+ 4 - trailing spaces are ok.  AFP will leave the result in FPR0 if
RC = 0.  RC = 4 means it found an error.  SCAN and SCAN + 4 will be
updated to point past the portion of the string converted.

CEF converts to external floating format.  Input is in FPR0.  R1
points to flags that control the result format.  Try r1->x'2785' for
a first attempt.  This should be similar to G15.5 in fortran.  Look
at the comments at the start of CEF for the details.  These routines
work only with long floating format - but it is a simple matter to
convert to and from short format if desired - at the input of CEF and
the output of AFP.

It is quite possible that there are easier and/or better ways to do
these conversions.  These routines are not claimed to be the best of
their genre - but they work for me.  Note that I did have to modify
them slightly to remove some macro calls peculiar to our TP system -
Entry and Exit macros dealing with save areas.  Hopefully I did not
introduce any errors in the process.

AFP, CEF, and FAM are free of copyright restrictions.

------------------ Cut Here -----------------------------
.AFP     SPACE 2
**       AFP -- ASSEMBLE FLOATING POINT OPERAND
*
*        ENTRY SCAN CONTAINS ADDR OF CHARS TO CONVERT
*              SCAN + 4 CONTAINS LENGTH OF STRING
*
*        EXIT  RC = 0, FPR0 CONTAINS LONG FP RESULT
*              RC = 4, STRING WAS INVALID NUMBER
*
*
AFP      STM   14,12,12(13)       SAVE REGS
         SR    3,3                SET EXPONENT TO ZERO
         LD    0,=D'1.0'          SET MULTIPLIER = 1
         MVI   AFPF,0             CLEAR FLAG
         LD    6,=D'0'            PRESET ZERO RESULT
         LM    4,5,SCAN           POINT TO INPUT OPERAND
*
AFP1     CLI   0(4),C'+'          SEE IF POSITIVE
         BE    AFP8
         CLI   0(4),C'-'          SEE IF NEGATIVE
         BE    AFP4
         CLI   0(4),C'.'          SEE IF DECIMAL POINT
         BE    AFP6
         CLI   0(4),C'E'          SEE IF EXPONENT
         BE    AFP7
*
         CLI   0(4),C'0'          MUST BE A DECIMAL DIGIT
         BL    AFP10              IF NOT
         CLI   0(4),C'9'
         BH    AFP10              IF NOT
         OI    AFPF,X'08'         SHOW DIGITS FOUND
         MVN   AFPW+7(1),0(4)     SET DIGIT VALUE
         TM    AFPF,X'80'         SEE IF DIGIT IN EXPONENT
         BO    AFP3               IF SO
         TM    AFPF,X'40'         SEE IF FRACTION DIGIT
         BO    AFP2               IF SO
         MD    6,=D'10.0'         SHIFT RESULT 1 DIGIT
         AD    6,AFPW             ADD IN CURRENT DIGIT
         B     AFP9
*
AFP2     LD    2,AFPW             GET CURRENT DIGIT
         AD    2,=D'0'            NORMALIZE IT
         DD    0,=D'10.0'         SCALE MULTIPLIER
         MDR   2,0                SHIFT CURRENT DIGIT
         ADR   6,2                ADD IN CURRENT SHIFTED DIGIT
         B     AFP9               NEXT CHARACTER
*
AFP3     MH    3,=H'10'           SHIFT EXPONENT
         AH    3,AFPW+6           ADD IN CURRENT DIGIT
         B     AFP9               NEXT CHARACTER
*
AFP4     TM    AFPF,X'68'         SEE IF SIGN, DIGITS, OR DECIMAL
         BNZ   AFP10              END OF NUMBER IF SO
         TM    AFPF,X'80'         SEE IF EXPONENT SIGN
         BO    AFP5
         OI    AFPF,X'30'         SET NEGATIVE
         B     AFP9               NEXT CHARACTER
*
AFP5     OI    AFPF,X'24'         SET NEGATIVE EXPONENT, SIGN CHAR
         B     AFP9               NEXT CHARACTER
*
AFP6     TM    AFPF,X'C0'         SEE IF DECIMAL OR E
         BNZ   ERR2               *INVALID FP NUMBER*
         OI    AFPF,X'40'         SHOW DECIMAL ENCOUNTERED
         B     AFP9               NEXT CHARACTER
*
AFP7     TM    AFPF,X'80'         SEE IF E ALREADY FOUND
         BO    ERR2
         TM    AFPF,X'08'         MUST BE SOME DIGITS
         BZ    ERR2
         NI    AFPF,255-X'68'     NO SIGN, NO DIGITS
         OI    AFPF,X'80'         SHOW EXPONENT PRESENT
         B     AFP9               NEXT CHARACTER
*
AFP8     TM    AFPF,X'68'         SEE IF SIGN, DIGITS, OR DECIMAL
         BNZ   AFP10              END OF NUMBER IF SO
         OI    AFPF,X'20'         SET SIGN FLAG
*
AFP9     LA    4,1(,4)            NEXT INPUT CHARACTER
         BCT   5,AFP1             LOOP FOR ALL CHARACTERS
*
AFP10    STM   4,5,SCAN           RESET SCAN PTRS
         TM    AFPF,X'80'         SEE IF ANY EXPONENT
         BZ    AFP11              IF NOT
         TM    AFPF,X'08'         MUST BE SOME DIGITS IF E
         BZ    ERR2               *INVALID FP NUMBER*
*
AFP11    TM    AFPF,X'10'         SEE IF NEGATIVE MANTISSA
         BZ    AFP12              IF NOT
         LNDR  6,6                MAKE IT NEGATIVE
*
AFP12    LTR   3,3                SEE IF ANY EXPONENT SPECIFIED
         BNP   AFP14              IF NOT
         LD    0,=D'10.0'         ASSUME POSITIVE EXPONENT
         TM    AFPF,X'04'         SEE IF NEGATIVE EXPONENT
         BZ    AFP13              IF NOT
         LD    0,=D'0.10'         SET NEGATIVE EXPONENT MULTIPLIER
*
AFP13    MDR   6,0                SCALE RESULT
         BCT   3,AFP13
*
AFP14    STD   6,AFPR             STORE RESULT
         CLC   AFPR+1(7),=XL7'00' SEE IF TRUE ZERO REQUIRED
         BNE   AFPX
         XC    AFPR,AFPR          INSURE RESULT IS A TRUE ZERO
APFX     LD    0,AFPR             GET RESULT IN FPR0
         LM    14,12,12(13)       RESTORE REGS
         SR    15,15              GIVE GOOD RC
         BR    14                 RETURN TO CALLER
*
ERR2     XC    AFPR,AFPR          CLEAR RESULT
         LD    0,AFPR
         LM    14,12,12(13)
         LA    15,4               GIVE BAD RC
         BR    14
*
AFPR     DC    D'0'               RESULT
*
AFPW     DC    X'4E00000000000000' WORK AREA
*
AFPF     DC    X'00'
*        ...   X'80'              'E' ENCOUNTERED
*        ...   X'40'              '.' ENCOUNTERED
*        ...   X'20'              SIGN ENCOUNTERED
*        ...   X'10'              NEGATIVE MANTISSA
*        ...   X'08'              DIGITS ENCOUNTERED
*        ...   X'04'              NEGATIVE EXPONENT
*
SCAN     DC    A(0)               SCAN ADDRESS
         DC    F'0'               LENGTH
.CEF     SPACE 2
**       CEF -- CONVERT TO EXTERNAL FLOATING
*
*        FPR0 - NUMBER TO BE CONVERTED
*
*        R1 -> FFNM
*              FF = 80, F, FIXED FORMAT
*                   40, S, SCIENTIFIC FORMAT
*                   20, G, EITHER OF ABOVE
*                   10, E, ENGINEERING FORMAT
*                   08, %, FIXED NOTATION, SCALE BY 100
*
*                   B'00000111' SIGN OPTION
*
*                   00, NO SIGN DISPLAYED
*                   01, TRAILING - SIGN OPTION
*                   02, CR SIGN OPTION
*                   03, DB SIGN OPTION
*                   04, $, CR
*                   05, $, DB
*                   06, + SIGN OPTION
*                   07, - SIGN OPTION
*
*              N  = NUMBER OF FRACTION DIGITS
*              M  = NUMBER OF INTEGER DIGITS
*
*
CEF      STM   14,12,12(13)       SAVE REGS
         ST    13,CEFV+4          BACKCHAIN
         LA    13,CEFV            POINT TO SAVE AREA
*
         MVC   CEFB,0(1)          SAVE FLAG BYTE
         MVC   CEFC,CEFB          SET SIGN CONTROL BITS
         NI    CEFC,X'07'         SAVE ONLY SIGN BITS
         MVN   CEFI+1(1),1(1)     SAVE NUMBER OF INTEGER DIGITS
         IC    1,1(,1)            SAVE NUMBER OF FRACTION DIGITS
         SRL   1,4
         STC   1,CEFF+1
         NI    CEFF+1,X'0F'       ...
*
         TM    CEFB,X'08'         SEE IF PERCENT NOTATION
         BZ    CEF1               IF NOT
         MD    0,=D'100.0'        SCALE PERCENTAGE
*
CEF1     LA    1,3                CHECK FOR MIN INTEGER LOCATIONS
         TM    CEFB,X'10'         SEE IF ENG NOTATION
         BO    CEF2
         LA    1,1
         TM    CEFB,X'60'         SCI OR SCI/FIX
         BO    CEF2
         SR    1,1                NO INTEGER PORTION REQUIRED
CEF2     CH    1,CEFI             CHECK AGAINST LIMIT
         BNH   CEF3
         STH   1,CEFI             SET MINIMUM
*
CEF3     MVI   CEFS,C'+'          ASSUME POSITIVE VALUE
         LTDR  0,0                TEST INPUT VALUE
         BNM   CEF4               IF NOT NEGATIVE
         MVI   CEFS,C'-'          SET NEGATIVE SIGN
*
CEF4     MVC   CEFO,CEFO-1        CLEAR OUTPUT AREA
         LA    7,CEFO             POINT TO OUTPUT AREA
         CLI   CEFC,X'04'         SEE IF LEADING SIGN OR CURRENCY
         BL    CEF8               DO NOT ALLOW SPACE FOR IT
         CLI   CEFC,X'06'         SEE IF + SIGN OPTION
         BE    CEF6
         CLI   CEFC,X'07'         SEE IF - SIGN OPTION
         BE    CEF5               IF SO
         MVI   0(7),C'$'          SET CURRENCY SIGN
         B     CEF7
CEF5     CLI   CEFS,C'+'          SEE IF POSITIVE
         BE    CEF7               IF SO
CEF6     MVC   0(1,7),CEFS        STORE SIGN
CEF7     LA    7,1(,7)            ADVANCE POINTER
*
CEF8     SR    6,6                SET ZERO EXPONENT
         LPDR  0,0                SET POSITIVE SIGN
         BZ    CEF14              IF ZERO ARG
*
         LD    4,=D'1.0'          COMPUTE ROUNDING FACTOR
         LH    2,CEFF             GET NUMBER OF FRACTION DIGITS
         SLL   2,3                INDEX INTO SCALE TABLE
         DD    4,CEFT00(2)        1.0/SCALE FACTOR
         HDR   4,4                1.0/(2*SCALE FACTOR)
*
CEF9     TM    CEFB,X'40'         SEE IF SCI FORMAT
         BO    CEF10              IF SO
         LH    1,CEFI             GET INTEGER DIGITS REQUIRED
         SLL   1,3                X LENGTH OF FP NUMBER
         CD    0,CEFT00(1)        SEE IF TOO LARGE FOR F FORMAT
         BNL   CEF10              IF NOT
         TM    CEFB,X'80'         SEE IF FIXED POINT
         BO    CEF13              NO SCALING IF SO
         CD    0,=D'1.0'          SEE IF ARG LT 1
         BNL   CEF13              IF NOT
         TM    CEFB,X'10'         SEE IF ENG FORMAT
         BO    CEF10              SCALE ARG IF ENG
         LH    1,CEFF             PREPARE FOR SIGNIFICANCE LOSS TEST
         SLL   1,3
         LD    2,=D'1.0'
         DD    2,CEFT00(1)        SIGNIFICANCE FACTOR
         CDR   0,2
         BH    CEF13              IF SOME SIGNIFICANCE RETAINED
*
CEF10    LD    2,CEFT01           PRESET SCI SCALING FACTOR
         LA    2,1                SET SCALE = 1
         TM    CEFB,X'10'         SEE IF ENG FORMAT REQUIRED
         BZ    CEF11              IF NOT
         LD    2,CEFT03           SET ENG SCALING FACTOR
         LA    2,3                SET SCALE = 3
CEF11    CD    0,=D'1.0'
         BNL   CEF12              IF NEG SCALING NOT REQUIRED
         MDR   0,2                SCALE IT
         SR    6,2                ADJUST EXPONENT
         B     CEF11              LOOP FOR ALL NEG SCALING
CEF12    CDR   0,2                CHECK FOR POSITIVE SCALING
         BL    CEF13              IF OK
         DDR   0,2                SCALE IT
         AR    6,2                ADJUST EXPONENT
         B     CEF12
*
CEF13    LTDR  4,4                SEE IF ANY ROUNDING FACTOR
         BZ    CEF14
         ADR   0,4                ROUND SCALED RESULT
         LD    4,=D'0'            ZERO OUT ROUNDING FACTOR
         B     CEF9
*
CEF14    STD   0,CEFA             SAVE ROUNDED ABS OF INPUT VALUE
*
         LH    2,CEFI             GET INTEGER POSITIONS
         BAL   14,FAM             FIX AND MOVE INTEGER DIGITS
*
         LH    2,CEFF             GET NUMBER OF FRACTION DIGITS
         SLA   2,3                X LENGTH OF FP NUMBER
         BZ    CEF15              IF NO FRACTION DIGITS REQUIRED
         MVI   0(7),C'.'          STORE DECIMAL POINT
         LA    7,1(,7)            SKIP DECIMAL POINT
         AD    0,=D'0'            GET FRACTION
         SD    0,CEFA
         LPDR  0,0                ...
         MD    0,CEFT00(2)        SCALE FRACTION INTO INTEGER
         LH    2,CEFF             GET FRACTION POSITIONS
         BAL   14,FAM             FIX AND MOVE FRACTION DIGITS
*
CEF15    TM    CEFB,X'40'         SEE IF SCIENTIFIC
         BO    CEF16              ALWAYS DISPLAY EXPONENT IF SCI
         LTR   6,6                SEE IF ANY EXPONENT
         BZ    CEF18              IF NOT
CEF16    MVC   0(2,7),=C'E+'      STORE EXP INDICATOR
         LTR   6,6                SEE IF NEGATIVE EXPONENT
         BNM   CEF17
         MVI   1(7),C'-'          SET NEGATIVE EXP
CEF17    LPR   6,6                CONVERT EXPONENT
         CVD   6,DWORK            ...
         OI    DWORK+7,X'0F'      PRINTABLE SIGN
         UNPK  2(2,7),DWORK       MOVE TO OUTPUT LINE
         LA    7,4(,7)            SKIP EXPONENT
*
CEF18    CLI   CEFS,C'-'          SEE IF NEGATIVE
         BNE   CEF21              IF NOT
         CLI   CEFC,X'05'         CHECK FOR LEADING SIGN
         BH    CEF21              IF LEADING SIGN
         CLI   CEFC,X'01'
         BL    CEF21              IF NO SIGN DISPLAYED
         BH    CEF19              IF CR OR DB
         MVI   0(7),C'-'          STORE NEG SIGN
         LA    7,1(,7)            SKIP NEG SIGN
         B     CEF21
CEF19    MVC   0(2,7),=C'DB'      STORE A DEBIT SYMBOL
         TM    CEFC,X'01'         SEE IF DEBIT
         BO    CEF20              IF SO
         MVC   0(2,7),=C'CR'      STORE A CREDIT SYMBOL
CEF20    LA    7,2(,7)            SKIP CR OR DB
*
CEF21    TM    CEFB,X'08'         SEE IF PERCENTAGE OUTPUT
         BZ    CEF22              IF NOT
         MVI   0(7),C'%'          STORE PERCENT SIGN
         LA    7,1(,7)            SKIP PERCENT SIGN
*
CEF22    LA    1,CEFO-1           ZERO SUPPRESS OUTPUT
CEF23    LA    1,1(,1)            NEXT DIGIT
         CLI   1(1),C'0'          SEE IF ZERO
         BNE   CEFX               IF DONE
         CLI   2(1),C'0'          SEE IF NEXT CHAR IS A DIGIT
         BL    CEFX               IF NOT
         MVC   1(1,1),0(1)        MOVE SIGN OR CURRENCY
         MVI   0(1),C' '          SPACE OUT ORIGINAL LOC
         B     CEF23              LOOP FOR ALL ZEROS TO BE SUPPRESSED
*
CEFX     L     13,4(,13)          RESTORE SAVE AREA ADDR
         LM    14,12,12(13)       RESTORE REGS
         SR    15,15
         BR    14
*
         DC    C' '
CEFO     DC    CL40' '            OUTPUT AREA
*
CEFT00   DC    D'1.0E+00'         POWERS OF 10
CEFT01   DC    D'1.0E+01'
CEFT02   DC    D'1.0E+02'
CEFT03   DC    D'1.0E+03'
CEFT04   DC    D'1.0E+04'
CEFT05   DC    D'1.0E+05'
CEFT06   DC    D'1.0E+06'
CEFT07   DC    D'1.0E+07'
CEFT08   DC    D'1.0E+08'
CEFT09   DC    D'1.0E+09'
CEFT10   DC    D'1.0E+10'
CEFT11   DC    D'1.0E+11'
CEFT12   DC    D'1.0E+12'
CEFT13   DC    D'1.0E+13'
CEFT14   DC    D'1.0E+14'
CEFT15   DC    D'1.0E+15'
CEFT16   DC    D'1.0E+16'
*
CEFA     DC    D'0'               HOLD FOR INPUT ARG
*
CEFB     DC    X'00'              FLAG BYTE
CEFC     DC    X'00'              SIGN OPTION
*
CEFR     DC    X'0000000000000001' ROUNDING FACTOR
*
CEFS     DC    C'+'               SIGN
*
CEFF     DC    H'0'               NUMBER OF FRACTION DIGITS
CEFI     DC    H'0'               NUMBER OF INTEGER DIGITS
*
CEFV     DC    18F'0'             SAVE AREA
.FAM     SPACE 2
**       FAM -- FIX AND MOVE
*
*
FAM      STM   14,2,12(13)
         AW    0,FAMF             ADD IN FIX CONSTANT
         STD   0,DWORK            SAVE FIXED VALUE
         CLI   DWORK,X'4E'        SEE IF OVERFLOW
         BH    ERR1               IF OVERFLOW
         XC    FAMW,FAMW          CLEAR WORK AREA
         SR    0,0                GET UPPER PART OF INTEGER
         ICM   0,B'0111',DWORK+1  ...
         L     1,DWORK+4          GET LOWER PART
         SLDL  0,1                MAKE BOTTOM POSITIVE
         SRL   1,1                ...
         CVD   0,FAMW+8           CONVERT UPPER
         MP    FAMW,=P'2147483648' SCALE IT
         CVD   1,DWORK            CONVERT LOWER TO DECIMAL
         AP    FAMW,DWORK         ADD IN LOWER PART
         OI    FAMW+15,X'0F'      PRINTABLE SIGN
         BCTR  2,0                LENGTH CODE
         SLL   2,4                SHIFT INTO POSITION
         EX    2,FAMX1            MOVE DIGITS TO OUTPUT
         SRL   2,4                RESTORE LENGTH CODE
         LA    7,1(2,7)           SKIP DIGITS MOVED
         LM    14,2,12(13)
         BR    14
*
ERR1     L     13,4(,13)          RESTORE SAVE AREA ADDR
         LM    14,12,12(13)       RESTORE REGS
         LA    15,4               GIVE RC = 4, OVERFLOW
         BR    14
*
FAMX1    UNPK  0(0,7),FAMW        MOVE DIGITS TO OUTPUT AREA
*
         DS    0D
FAMF     DC    X'4E00000000000000' FIX CONSTANT
*
FAMW     DC    XL16'00'           WORK AREA
*
DWORK    DC    D'0'               WORK
------------------ Cut Here -----------------------------

Roy Frederick - royf@attctc
Dallas County Data Services
504 Records Building
Dallas, TX 75202
(214) 653-6340