(* LongConv.mod implement the ISO LongConv specification. Copyright (C) 2009-2023 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 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 3, or (at your option) any later version. GNU Modula-2 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. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . *) IMPLEMENTATION MODULE LongConv ; FROM SYSTEM IMPORT ADDRESS ; FROM ConvTypes IMPORT ScanClass ; FROM CharClass IMPORT IsNumeric, IsWhiteSpace ; FROM DynamicStrings IMPORT String, InitString, InitStringCharStar, KillString, Length, Slice, Mark, Index, string ; FROM ldtoa IMPORT strtold ; FROM ConvStringLong IMPORT RealToFloatString, RealToEngString, RealToFixedString ; FROM M2RTS IMPORT Halt ; FROM libc IMPORT free ; IMPORT EXCEPTIONS ; TYPE RealConvException = (noException, invalid, outofrange) ; VAR realConv: EXCEPTIONS.ExceptionSource ; (* Low-level LONGREAL/string conversions *) (* Represents the start state of a finite state scanner for real numbers - assigns class of inputCh to chClass and a procedure representing the next state to nextState. *) PROCEDURE ScanReal (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanSecondDigit ; chClass := valid ELSIF (inputCh='+') OR (inputCh='-') THEN nextState := scanFirstDigit ; chClass := valid ELSIF IsWhiteSpace(inputCh) THEN nextState := ScanReal ; chClass := padding ELSE nextState := ScanReal ; chClass := invalid END END ScanReal ; (* scanFirstDigit - *) PROCEDURE scanFirstDigit (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanSecondDigit ; chClass := valid ELSE nextState := scanFirstDigit ; chClass := invalid END END scanFirstDigit ; (* scanSecondDigit - *) PROCEDURE scanSecondDigit (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanSecondDigit ; chClass := valid ELSIF inputCh='.' THEN nextState := scanFixed ; chClass := valid ELSIF inputCh='E' THEN nextState := scanScientific ; chClass := valid ELSE nextState := noOpFinished ; chClass := terminator END END scanSecondDigit ; (* scanFixed - *) PROCEDURE scanFixed (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanFixed ; chClass := valid ELSIF inputCh='E' THEN nextState := scanScientific ; chClass := valid ELSE nextState := noOpFinished ; chClass := terminator END END scanFixed ; (* scanScientific - *) PROCEDURE scanScientific (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanScientificSecond ; chClass := valid ELSIF (inputCh='-') OR (inputCh='+') THEN nextState := scanScientificSign ; chClass := valid ELSE nextState := scanScientific ; chClass := invalid END END scanScientific ; (* scanScientificSign - *) PROCEDURE scanScientificSign (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanScientificSecond ; chClass := valid ELSE nextState := scanScientificSign ; chClass := invalid END END scanScientificSign ; (* scanScientificSecond - *) PROCEDURE scanScientificSecond (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN IF IsNumeric(inputCh) THEN nextState := scanScientificSecond ; chClass := valid ELSE nextState := noOpFinished ; chClass := terminator END END scanScientificSecond ; (* noOpFinished - *) PROCEDURE noOpFinished (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass; VAR nextState: ConvTypes.ScanState) ; BEGIN nextState := noOpFinished ; chClass := terminator ; (* should we raise an exception here? *) END noOpFinished ; (* Returns the format of the string value for conversion to LONGREAL. *) PROCEDURE FormatReal (str: ARRAY OF CHAR) : ConvResults ; VAR proc : ConvTypes.ScanState ; chClass: ConvTypes.ScanClass ; i, h : CARDINAL ; BEGIN i := 1 ; h := LENGTH(str) ; ScanReal(str[0], chClass, proc) ; WHILE (i