**************************************************************************
      * 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
      *****************************************************************
Topic revision: r1 - 27 May 2005 - 05:45:40 - MartinRowe
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding DBG/400? Send feedback