1 (* ShortConv.mod implement the ISO ShortConv specification.
3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE ShortConv ;
29 FROM SYSTEM IMPORT ADDRESS ;
30 FROM ConvTypes IMPORT ScanClass ;
31 FROM CharClass IMPORT IsNumeric, IsWhiteSpace ;
32 FROM DynamicStrings IMPORT String, InitString, InitStringCharStar, KillString, Length, Slice, Mark, Index, string ;
33 FROM dtoa IMPORT strtod ;
34 FROM ConvStringShort IMPORT RealToFloatString, RealToEngString, RealToFixedString ;
35 FROM M2RTS IMPORT Halt ;
36 FROM libc IMPORT free ;
41 RealConvException = (noException, invalid, outofrange) ;
44 realConv: EXCEPTIONS.ExceptionSource ;
47 (* Low-level LONGREAL/string conversions. *)
49 (* Represents the start state of a finite state scanner for real
50 numbers - assigns class of inputCh to chClass and a procedure
51 representing the next state to nextState.
54 PROCEDURE ScanReal (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
55 VAR nextState: ConvTypes.ScanState) ;
59 nextState := scanSecondDigit ;
61 ELSIF (inputCh='+') OR (inputCh='-')
63 nextState := scanFirstDigit ;
65 ELSIF IsWhiteSpace(inputCh)
67 nextState := ScanReal ;
70 nextState := ScanReal ;
80 PROCEDURE scanFirstDigit (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
81 VAR nextState: ConvTypes.ScanState) ;
85 nextState := scanSecondDigit ;
88 nextState := scanFirstDigit ;
98 PROCEDURE scanSecondDigit (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
99 VAR nextState: ConvTypes.ScanState) ;
101 IF IsNumeric(inputCh)
103 nextState := scanSecondDigit ;
107 nextState := scanFixed ;
111 nextState := scanScientific ;
114 nextState := noOpFinished ;
115 chClass := terminator
117 END scanSecondDigit ;
124 PROCEDURE scanFixed (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
125 VAR nextState: ConvTypes.ScanState) ;
127 IF IsNumeric(inputCh)
129 nextState := scanFixed ;
133 nextState := scanScientific ;
136 nextState := noOpFinished ;
137 chClass := terminator
146 PROCEDURE scanScientific (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
147 VAR nextState: ConvTypes.ScanState) ;
149 IF IsNumeric(inputCh)
151 nextState := scanScientificSecond ;
153 ELSIF (inputCh='-') OR (inputCh='+')
155 nextState := scanScientificSign ;
158 nextState := scanScientific ;
168 PROCEDURE scanScientificSign (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
169 VAR nextState: ConvTypes.ScanState) ;
171 IF IsNumeric(inputCh)
173 nextState := scanScientificSecond ;
176 nextState := scanScientificSign ;
179 END scanScientificSign ;
183 scanScientificSecond -
186 PROCEDURE scanScientificSecond (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
187 VAR nextState: ConvTypes.ScanState) ;
189 IF IsNumeric(inputCh)
191 nextState := scanScientificSecond ;
194 nextState := noOpFinished ;
195 chClass := terminator
197 END scanScientificSecond ;
204 PROCEDURE noOpFinished (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
205 VAR nextState: ConvTypes.ScanState) ;
207 nextState := noOpFinished ;
208 chClass := terminator ;
209 (* should we raise an exception here? *)
213 (* Returns the format of the string value for conversion to LONGREAL. *)
215 PROCEDURE FormatReal (str: ARRAY OF CHAR) : ConvResults ;
217 proc : ConvTypes.ScanState ;
218 chClass: ConvTypes.ScanClass ;
223 ScanReal(str[0], chClass, proc) ;
224 WHILE (i<h) AND (chClass=padding) DO
225 proc(str[i], chClass, proc) ;
229 IF chClass=terminator
233 WHILE (i<h) AND (chClass=valid) DO
234 proc(str[i], chClass, proc) ;
239 padding : RETURN( strWrongFormat ) |
241 valid : RETURN( strAllRight ) |
242 invalid : RETURN( strWrongFormat )
248 (* Returns the value corresponding to the real number string value
249 str if str is well-formed; otherwise raises the RealConv
253 PROCEDURE ValueReal (str: ARRAY OF CHAR) : SHORTREAL ;
255 IF FormatReal(str)=strAllRight
257 RETURN( doValueReal(str) )
259 EXCEPTIONS.RAISE(realConv, ORD(invalid),
260 'ShortConv.' + __FUNCTION__ + ': real number is invalid')
266 doValueReal - str, is a well-formed real number and its
270 PROCEDURE doValueReal (str: ARRAY OF CHAR) : SHORTREAL ;
276 s := InitString(str) ;
277 r := strtod (string(s), error) ;
281 EXCEPTIONS.RAISE (realConv, ORD(outofrange),
282 'ShortConv.' + __FUNCTION__ + ': real number is out of range')
288 (* Returns the number of characters in the floating-point string
289 representation of real with sigFigs significant figures.
292 PROCEDURE LengthFloatReal (real: SHORTREAL; sigFigs: CARDINAL) : CARDINAL ;
297 s := RealToFloatString (real, sigFigs) ;
299 s := KillString (s) ;
301 END LengthFloatReal ;
304 (* Returns the number of characters in the floating-point engineering
305 string representation of real with sigFigs significant figures.
308 PROCEDURE LengthEngReal (real: SHORTREAL; sigFigs: CARDINAL) : CARDINAL ;
313 s := RealToEngString (real, sigFigs) ;
315 s := KillString (s) ;
320 (* Returns the number of characters in the fixed-point string
321 representation of real rounded to the given place relative to the
325 PROCEDURE LengthFixedReal (real: SHORTREAL; place: INTEGER) : CARDINAL ;
330 s := RealToFixedString (real, place) ;
332 s := KillString (s) ;
334 END LengthFixedReal ;
337 (* Returns TRUE if the current coroutine is in the exceptional
338 execution state because of the raising of an exception in a
339 routine from this module; otherwise returns FALSE.
342 PROCEDURE IsRConvException () : BOOLEAN ;
344 RETURN( EXCEPTIONS.IsCurrentSource(realConv) )
345 END IsRConvException ;
349 EXCEPTIONS.AllocateSource (realConv)