************************************************************************** * DBG043R3: Character to Number conversion * Copyright (C) 2000 Martin Rowe <martin@dbg400.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ************************************************************************** * DESCRIPTION: Character to number conversion * Convert a numeric string (held somewhere in a 16 alpha field) to a 15,5 * number. Leading/trailing blanks are handled, as is the decimal point if * found. Conversion stops at the first embedded blank found (in which * case the string parm is set to '*WARNING'. If non numeric data is found * in the first portion of the string, the result will be zero, and the * string parm is set to '*ERROR'. If a negative sign is found anywhere * in the string, the number is assumed to be negative. * Note. THE LR INDICATOR IS NOT SET ON IN THIS PGM. ************************************************************************** H 1 Y ************************************************************************** I 'ABCDEFGHIJKLMNOPQR' C LTRS I '##################' C DROP ************************************************************************** C *ENTRY PLIST C PARM P#CHAR 16 C PARM P#DEC 155 ************************************************************************** * Field initialisation C MOVE *BLANKS @STRNG 16 Working string C MOVE *BLANKS @FLD16 16 Right adjusted string C MOVE *BLANKS @LFT16 16 Left adjusted string C MOVE *BLANKS @STORE 16 Store after -ve check C MOVE *OFF @NEGVL 1 Negative indicator C Z-ADD0 @S 20 String start position C Z-ADD0 @R 20 Required leading ' 's C Z-ADD0 @LEN 20 String length C Z-ADD0 @E 20 String end position C Z-ADD0 @DEC 20 Decimal point C MOVE *BLANKS @DECFL 15 Alpha decimal portion C MOVE *ZEROS @ZEROS 15 Decimal trailing 0's C Z-ADD0 @NBR10 100 Whole number portion C Z-ADD0 @DEC05 55 Decimal portion ************************************************************************** * Swap letters for # symbol as a single letter (from A to R) can be a * valid number - according to TESTN. Bizarre, isn't it. C LTRS:DROP XLATEP#CHAR @STRNG * Determine if negative sign used C '-':' ' XLATE@STRNG @STORE B001 C @STORE IFNE @STRNG C MOVE @STORE @STRNG C MOVE *ON @NEGVL E001 C ENDIF * Determine start of number in string (first non-blank element) C ' ' CHECK@STRNG @S 70 * Non-blanks found, so start adjustment B001 C *IN70 IFEQ *ON * Left adjust field to start off (substring from start of non-blank data) C 17 SUB @S @LEN C @LEN SUBST@STRNG:@S @LFT16 C MOVE @LFT16 @STRNG * Look for end of 'numeric' string (first embedded blank - same thing) C ' ' SCAN @STRNG @E 70 * If trailing blanks found B002 C *IN70 IFEQ *ON * Is trailing blank an embedded blank?? (look for data after the blank) C ' ' CHECK@STRNG:@E 72 * Yes, it is, so set warning flag B003 C *IN72 IFEQ *ON C MOVEL'*WARNING'P#CHAR P * Just extract first part of field before embedded blank and use that C @E SUB 1 @LEN C @LEN SUBST@STRNG:1 @LFT16 P C MOVE @LFT16 @STRNG E003 C ENDIF * Process resultant string * Check if decimal point in string C '.' SCAN @STRNG @DEC 71 * Yes, it has B003 C *IN71 IFEQ *ON * Assume number has a decimal fraction & treat accordingly * (Field of 123.45 or .876 format) B004 C @DEC IFLE @E C @E OREQ 0 * By subtracting position of decimal point from the result * result field length (plus 1) the number of leading blanks * required to create a whole number string is obtained C 17 SUB @DEC @R * Now add those leading blanks to 'numeric' string (holding field) C MOVE *BLANKS @STORE C CAT @STRNG:@R @STORE * Now deal with decimal portion C @DEC ADD 1 @R C 17 SUB @R @LEN B005 C @DEC IFLT 16 C @LEN SUBST@STRNG:@R @DECFL C CAT @ZEROS:0 @DECFL E005 C ENDIF * Move 'holding field' back C MOVE @STORE @FLD16 E004 C ENDIF * Otherwise process as a whole number only * (Field of 12345 format) X003 C ELSE * By subtracting position of first trailing blank from the * result field length (plus 1) the number of leading blanks * required is obtained. C 17 SUB @E @R * Now add those leading blanks to 'numeric' string C CAT @STRNG:@R @FLD16 E003 C ENDIF * Otherwise no adjustment required - just a straightforward move * (Field of 1234567890123456 format - all positions used - unlikely) X002 C ELSE C MOVE @STRNG @FLD16 E002 C ENDIF * Otherwise indicate error - non numeric data (blanks) X001 C ELSE C MOVEL'*ERROR' P#CHAR P E001 C ENDIF ************************************************************************** * Final check of Whole & Decimal portions * Check that string is valid to put in numeric field C TESTN @FLD16 707070 B001 C *IN70 IFEQ *ON C MOVE @FLD16 @NBR10 * Check that string is valid to put in numeric field C TESTN @DECFL 717171 B002 C *IN71 IFEQ *ON C MOVEL@DECFL @DEC05 * Add whole number and decimal portions to exit parameter C @NBR10 ADD @DEC05 P#DEC * If negative sign at start or end of field, then make field negative B003 C @NEGVL IFEQ *ON C Z-SUBP#DEC P#DEC E003 C ENDIF * Otherwise indicate error - non numeric data X002 C ELSE C MOVEL'*ERROR' P#CHAR P E002 C ENDIF * Otherwise indicate error - non numeric data X001 C ELSE C MOVEL'*ERROR' P#CHAR P E001 C ENDIF * EXIT C RETRN *****************************************************************