UNSAFE MODULE CharsTo_us EXPORTS CharsTo, CharsTo_us; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT CharType; IMPORT Ctypes, Cstdlib; IMPORT Uerror, UnixMutex; (* These are needed for 'errno' *) PROCEDURE AToF( READONLY chars: ARRAY OF CHAR; VAR long: LONGREAL) : BOOLEAN RAISES {}= VAR ptr: UNTRACED REF Ctypes.char; localErrno: Ctypes.int; result: LONGREAL; BEGIN IF NOT chars[0] IN CharType.Digit THEN RETURN FALSE END; LOCK UnixMutex.errno DO Uerror.errno := 0; result := Cstdlib.strtod(ADR(chars[0]), ADR(ptr)); localErrno := Uerror.errno; END; IF localErrno = 0 AND ptr >= ADR(chars[LAST(chars)]) THEN long := result; RETURN TRUE; ELSE RETURN FALSE; END; END AToF; (* Sadly we end up doing a copy here to ensure 'chars' is null terminated. Yuck. However it is still probably just as fast as coding the whole thing in Modula 3 - 'strtod', which is what we eventually call, is often lovingly hand coded in assembler.... *) <*INLINE*> PROCEDURE CopyAndNullTerminate( READONLY chars: ARRAY OF CHAR) : REF ARRAY OF CHAR RAISES {}= VAR n := NUMBER(chars); cn := n; copy: REF ARRAY OF CHAR; BEGIN IF chars[n-1] # '\000' THEN INC(cn) END; copy := NEW(REF ARRAY OF CHAR, cn); SUBARRAY(copy^, 0, n) := chars; copy[cn-1] := '\000'; (* now deal with the fact that M3 uses 'd' for LONGREALs and C doesnt *) FOR i := 0 TO cn - 1 DO WITH c = copy[i] DO IF (c = 'D' OR c = 'd') OR (c = 'X' OR c = 'x') THEN c := 'e'; EXIT; END; END; END; RETURN copy; END CopyAndNullTerminate; PROCEDURE Real(READONLY chars: Chars; VAR real: REAL): BOOLEAN RAISES {}= VAR longreal: LONGREAL; BEGIN IF AToF(CopyAndNullTerminate(chars)^, longreal) THEN (* some check needed! *) real := FLOAT(longreal); RETURN TRUE; ELSE RETURN FALSE; END; END Real; PROCEDURE LongReal( READONLY chars: Chars; VAR long: LONGREAL) : BOOLEAN RAISES {}= BEGIN RETURN AToF(CopyAndNullTerminate(chars)^, long); END LongReal; BEGIN END CharsTo_us.