--
--	Inmos Libraries
--	Copyright (C) 1988, 1989, 1990, 1991, 1993  Inmos Limited
--
--	This library is free software; you can redistribute it and/or
--	modify it under the terms of the GNU Lesser General Public
--	License as published by the Free Software Foundation; either
--	version 2 of the License, or (at your option) any later version.
--
--	This library 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
--	Lesser General Public License for more details.
--
--	You should have received a copy of the GNU Lesser General Public
--	License along with this library; if not, write to the Free Software
--	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
--

--** @module streamio

#OPTION "E"  -- no compliler libs
#COMMENT "Stream i/o library, V1.1 11/06/90"
#COMMENT "(c) Copyright INMOS Limited, 1988, 1990"
#INCLUDE "streamio.inc"
#USE "convert.lib"

--* Read a decimal or hexadecimal integer from the given keystream.
--
-- A distinction must be made here between a character held in a byte
-- and a character held in a word length quantity. Here the former is
-- referred to as a character and the latter as a 'character' ( note
-- the quotes ). Upper and lower case letters are permissible in a
-- hexadecimal integer. All input up to a plus sign, a minus sign, a
-- hash symbol, decimal digit, or a negative valued word is skipped.
-- If it is the hash that is encountered first then it is a hexadecimal
-- integer ( in two's complement form ) that is expected.  If it is a
-- negative valued word that is encountered then an input error has
-- occurred and that value is returned in char. The integer is
-- terminated when anything other than a valid digit ( hex and/or
-- decimal, as the case may be ) is read, and it is this terminating
-- quantity that is returned in char if the integer read is not
-- invalid.
--
-- @param source for input
-- @param number if char is not ft.number.error or negative, the value
--   of the integer read; otherwise undefined
-- @param char on entry: the first 'character' from the input to be
--   read; on exit: ft.number.error if the integer read overflowed the
--   range of INT; a negative value ( other than ft.number.error )
--   indicating an input error; otherwise the 'character' that
--   terminated the integer
PROC ks.read.int (CHAN OF KS source, INT number, char)
  --{{{  history
  -- Introduced check on index of array digits so that it never overflows,
  -- but char is set to ft.number.error instead. Hence reduced the size of
  -- digits from 15 to 11.  Also cleaned up the code to remove redundant
  -- lines. New version is 1.1 ( old version was 0.01, 23-Dec-88 )
  -- 11-June-90 SRH
  --}}}

  VAL max.number.width IS 11: -- 11 characters in MOSTNEG INT32 = -2147483648
  [max.number.width] BYTE digits:
  BOOL error:
  INT ch, j:

  SEQ
    ch := char
    error := FALSE
    --{{{  skip input until +, -, #, digit, or negative valued word
    WHILE (ch <> (INT '+')) AND (ch <> (INT '-')) AND (ch <> (INT '#')) AND
          (NOT (((INT '0') <= ch) AND (ch <= (INT '9')))) AND
          (ch >= 0)
      source ? ch
    --}}}
    IF
      ch < 0
        SKIP -- input error (not number error) so leave error as FALSE
      ch = (INT '#')
        --{{{  deal with hex
        SEQ
          source ? ch
          j := 0
          WHILE ( ((INT '0') <= ch) AND (ch <= (INT '9')) ) OR
                ( ((INT 'A') <= ch) AND (ch <= (INT 'F')) ) OR
                ( ((INT 'a') <= ch) AND (ch <= (INT 'f')) )
            SEQ
              IF
                j < max.number.width
                  SEQ
                    IF
                      ch >= (INT 'a')
                        digits[j] := BYTE (ch /\ #5F)  -- force to upper case
                      TRUE
                        digits[j] := BYTE ch
                    j := j + 1
                TRUE  -- hex is too large
                  error := TRUE
              source ? ch
          IF
            error
              SKIP
            TRUE
              #PRAGMA DEFINED digits
              STRINGTOHEX (error, number, [digits FROM 0 FOR j])
        --}}}
      TRUE
        --{{{  deal with decimal
        SEQ
          digits[0] := BYTE ch
          source ? ch
          j := 1
          WHILE ((INT '0') <= ch ) AND ( ch <= (INT '9'))
            SEQ
              IF
                j < max.number.width
                  SEQ
                    digits[j] := BYTE ch
                    j := j + 1
                TRUE  -- integer is too large
                  error := TRUE
              source ? ch
          IF
            error
              SKIP
            TRUE
              STRINGTOINT (error, number, [digits FROM 0 FOR j])
        --}}}
    IF
      error
        char := ft.number.error
      TRUE
        char := ch
:
