| /* do not edit automatically generated by mc from StringConvert. */ |
| /* StringConvert.mod provides functions to convert numbers to and from strings. |
| |
| Copyright (C) 2001-2025 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| 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 |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include <stdbool.h> |
| # if !defined (PROC_D) |
| # define PROC_D |
| typedef void (*PROC_t) (void); |
| typedef struct { PROC_t proc; } PROC; |
| # endif |
| |
| # if !defined (TRUE) |
| # define TRUE (1==1) |
| # endif |
| |
| # if !defined (FALSE) |
| # define FALSE (1==0) |
| # endif |
| |
| #if defined(__cplusplus) |
| # undef NULL |
| # define NULL 0 |
| #endif |
| #define _StringConvert_C |
| |
| #include "GStringConvert.h" |
| # include "GSYSTEM.h" |
| # include "Glibc.h" |
| # include "Glibm.h" |
| # include "GM2RTS.h" |
| # include "GDynamicStrings.h" |
| # include "Gldtoa.h" |
| # include "Gdtoa.h" |
| |
| |
| /* |
| IntegerToString - converts INTEGER, i, into a String. The field with can be specified |
| if non zero. Leading characters are defined by padding and this |
| function will prepend a + if sign is set to TRUE. |
| The base allows the caller to generate binary, octal, decimal, hexidecimal |
| numbers. The value of lower is only used when hexidecimal numbers are |
| generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF |
| are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_IntegerToString (int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower); |
| |
| /* |
| CardinalToString - converts CARDINAL, c, into a String. The field with can be specified |
| if non zero. Leading characters are defined by padding. |
| The base allows the caller to generate binary, octal, decimal, hexidecimal |
| numbers. The value of lower is only used when hexidecimal numbers are |
| generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF |
| are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_CardinalToString (unsigned int c, unsigned int width, char padding, unsigned int base, bool lower); |
| |
| /* |
| StringToInteger - converts a string, s, of, base, into an INTEGER. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" int StringConvert_StringToInteger (DynamicStrings_String s, unsigned int base, bool *found); |
| |
| /* |
| StringToCardinal - converts a string, s, of, base, into a CARDINAL. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" unsigned int StringConvert_StringToCardinal (DynamicStrings_String s, unsigned int base, bool *found); |
| |
| /* |
| LongIntegerToString - converts LONGINT, i, into a String. The field with |
| can be specified if non zero. Leading characters |
| are defined by padding and this function will |
| prepend a + if sign is set to TRUE. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongIntegerToString (long int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower); |
| |
| /* |
| StringToLongInteger - converts a string, s, of, base, into an LONGINT. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" long int StringConvert_StringToLongInteger (DynamicStrings_String s, unsigned int base, bool *found); |
| |
| /* |
| LongCardinalToString - converts LONGCARD, c, into a String. The field |
| width can be specified if non zero. Leading |
| characters are defined by padding. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongCardinalToString (long unsigned int c, unsigned int width, char padding, unsigned int base, bool lower); |
| |
| /* |
| StringToLongCardinal - converts a string, s, of, base, into a LONGCARD. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" long unsigned int StringConvert_StringToLongCardinal (DynamicStrings_String s, unsigned int base, bool *found); |
| |
| /* |
| ShortCardinalToString - converts SHORTCARD, c, into a String. The field |
| width can be specified if non zero. Leading |
| characters are defined by padding. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ShortCardinalToString (short unsigned int c, unsigned int width, char padding, unsigned int base, bool lower); |
| |
| /* |
| StringToShortCardinal - converts a string, s, of, base, into a SHORTCARD. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" short unsigned int StringConvert_StringToShortCardinal (DynamicStrings_String s, unsigned int base, bool *found); |
| |
| /* |
| stoi - decimal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_stoi (DynamicStrings_String s); |
| |
| /* |
| itos - integer to decimal string. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_itos (int i, unsigned int width, char padding, bool sign); |
| |
| /* |
| ctos - cardinal to decimal string. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ctos (unsigned int c, unsigned int width, char padding); |
| |
| /* |
| stoc - decimal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_stoc (DynamicStrings_String s); |
| |
| /* |
| hstoi - hexidecimal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_hstoi (DynamicStrings_String s); |
| |
| /* |
| ostoi - octal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_ostoi (DynamicStrings_String s); |
| |
| /* |
| bstoi - binary string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_bstoi (DynamicStrings_String s); |
| |
| /* |
| hstoc - hexidecimal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_hstoc (DynamicStrings_String s); |
| |
| /* |
| ostoc - octal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_ostoc (DynamicStrings_String s); |
| |
| /* |
| bstoc - binary string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_bstoc (DynamicStrings_String s); |
| |
| /* |
| StringToLongreal - returns a LONGREAL and sets found to TRUE if a legal number is seen. |
| */ |
| |
| extern "C" long double StringConvert_StringToLongreal (DynamicStrings_String s, bool *found); |
| |
| /* |
| LongrealToString - converts a LONGREAL number, Real, which has, |
| TotalWidth, and FractionWidth into a string. |
| It uses decimal notation. |
| |
| So for example: |
| |
| LongrealToString(1.0, 4, 2) -> '1.00' |
| LongrealToString(12.3, 5, 2) -> '12.30' |
| LongrealToString(12.3, 6, 2) -> ' 12.30' |
| LongrealToString(12.3, 6, 3) -> '12.300' |
| |
| if total width is too small then the fraction |
| becomes truncated. |
| |
| LongrealToString(12.3, 5, 3) -> '12.30' |
| |
| Positive numbers do not have a '+' prepended. |
| Negative numbers will have a '-' prepended and |
| the TotalWidth will need to be large enough |
| to contain the sign, whole number, '.' and |
| fractional components. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongrealToString (long double x, unsigned int TotalWidth, unsigned int FractionWidth); |
| |
| /* |
| stor - returns a REAL given a string. |
| */ |
| |
| extern "C" double StringConvert_stor (DynamicStrings_String s); |
| |
| /* |
| stolr - returns a LONGREAL given a string. |
| */ |
| |
| extern "C" long double StringConvert_stolr (DynamicStrings_String s); |
| |
| /* |
| ToSigFig - returns a floating point or base 10 integer |
| string which is accurate to, n, significant |
| figures. It will return a new String |
| and, s, will be destroyed. |
| |
| |
| So: 12.345 |
| |
| rounded to the following significant figures yields |
| |
| 5 12.345 |
| 4 12.34 |
| 3 12.3 |
| 2 12 |
| 1 10 |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ToSigFig (DynamicStrings_String s, unsigned int n); |
| |
| /* |
| ToDecimalPlaces - returns a floating point or base 10 integer |
| string which is accurate to, n, decimal |
| places. It will return a new String |
| and, s, will be destroyed. |
| Decimal places yields, n, digits after |
| the . |
| |
| So: 12.345 |
| |
| rounded to the following decimal places yields |
| |
| 5 12.34500 |
| 4 12.3450 |
| 3 12.345 |
| 2 12.34 |
| 1 12.3 |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ToDecimalPlaces (DynamicStrings_String s, unsigned int n); |
| |
| /* |
| Assert - implement a simple assert. |
| */ |
| |
| static void Assert (bool b, const char *file_, unsigned int _file_high, unsigned int line, const char *func_, unsigned int _func_high); |
| |
| /* |
| Max - |
| */ |
| |
| static unsigned int Max (unsigned int a, unsigned int b); |
| |
| /* |
| Min - |
| */ |
| |
| static unsigned int Min (unsigned int a, unsigned int b); |
| |
| /* |
| LongMin - returns the smallest LONGCARD |
| */ |
| |
| static long unsigned int LongMin (long unsigned int a, long unsigned int b); |
| |
| /* |
| IsDigit - returns TRUE if, ch, lies between '0'..'9'. |
| */ |
| |
| static bool IsDigit (char ch); |
| |
| /* |
| IsDecimalDigitValid - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValid (char ch, unsigned int base, unsigned int *c); |
| |
| /* |
| IsHexidecimalDigitValid - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValid (char ch, unsigned int base, unsigned int *c); |
| |
| /* |
| IsDecimalDigitValidLong - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c); |
| |
| /* |
| IsHexidecimalDigitValidLong - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c); |
| |
| /* |
| IsDecimalDigitValidShort - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c); |
| |
| /* |
| IsHexidecimalDigitValidShort - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c); |
| |
| /* |
| ToThePower10 - returns a LONGREAL containing the value of v * 10^power. |
| */ |
| |
| static long double ToThePower10 (long double v, int power); |
| |
| /* |
| DetermineSafeTruncation - we wish to use TRUNC when converting REAL/LONGREAL |
| into a string for the non fractional component. |
| However we need a simple method to |
| determine the maximum safe truncation value. |
| */ |
| |
| static unsigned int DetermineSafeTruncation (void); |
| |
| /* |
| rtos - |
| */ |
| |
| static DynamicStrings_String rtos (double r, unsigned int TotalWidth, unsigned int FractionWidth); |
| |
| /* |
| lrtos - |
| */ |
| |
| static DynamicStrings_String lrtos (long double r, unsigned int TotalWidth, unsigned int FractionWidth); |
| |
| /* |
| doDecimalPlaces - returns a string which is accurate to |
| n decimal places. It returns a new String |
| and, s, will be destroyed. |
| */ |
| |
| static DynamicStrings_String doDecimalPlaces (DynamicStrings_String s, unsigned int n); |
| |
| /* |
| doSigFig - returns a string which is accurate to |
| n decimal places. It returns a new String |
| and, s, will be destroyed. |
| */ |
| |
| static DynamicStrings_String doSigFig (DynamicStrings_String s, unsigned int n); |
| |
| /* |
| carryOne - add a carry at position, i. |
| */ |
| |
| static DynamicStrings_String carryOne (DynamicStrings_String s, unsigned int i); |
| |
| |
| /* |
| Assert - implement a simple assert. |
| */ |
| |
| static void Assert (bool b, const char *file_, unsigned int _file_high, unsigned int line, const char *func_, unsigned int _func_high) |
| { |
| char file[_file_high+1]; |
| char func[_func_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (file, file_, _file_high+1); |
| memcpy (func, func_, _func_high+1); |
| |
| if (! b) |
| { |
| M2RTS_ErrorMessage ((const char *) "assert failed", 13, (const char *) file, _file_high, line, (const char *) func, _func_high); |
| } |
| } |
| |
| |
| /* |
| Max - |
| */ |
| |
| static unsigned int Max (unsigned int a, unsigned int b) |
| { |
| if (a > b) |
| { |
| return a; |
| } |
| else |
| { |
| return b; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| Min - |
| */ |
| |
| static unsigned int Min (unsigned int a, unsigned int b) |
| { |
| if (a < b) |
| { |
| return a; |
| } |
| else |
| { |
| return b; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| LongMin - returns the smallest LONGCARD |
| */ |
| |
| static long unsigned int LongMin (long unsigned int a, long unsigned int b) |
| { |
| if (a < b) |
| { |
| return a; |
| } |
| else |
| { |
| return b; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsDigit - returns TRUE if, ch, lies between '0'..'9'. |
| */ |
| |
| static bool IsDigit (char ch) |
| { |
| return (ch >= '0') && (ch <= '9'); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsDecimalDigitValid - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValid (char ch, unsigned int base, unsigned int *c) |
| { |
| if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base)) |
| { |
| (*c) = ((*c)*base)+( ((unsigned int) (ch))- ((unsigned int) ('0'))); |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsHexidecimalDigitValid - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValid (char ch, unsigned int base, unsigned int *c) |
| { |
| if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base)) |
| { |
| (*c) = ((*c)*base)+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10); |
| return true; |
| } |
| else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base)) |
| { |
| /* avoid dangling else. */ |
| (*c) = ((*c)*base)+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10); |
| return true; |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsDecimalDigitValidLong - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c) |
| { |
| if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base)) |
| { |
| (*c) = (*c)*((long unsigned int ) (base+( ((unsigned int) (ch))- ((unsigned int) ('0'))))); |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsHexidecimalDigitValidLong - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValidLong (char ch, unsigned int base, long unsigned int *c) |
| { |
| if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base)) |
| { |
| (*c) = (*c)*((long unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10))); |
| return true; |
| } |
| else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base)) |
| { |
| /* avoid dangling else. */ |
| (*c) = (*c)*((long unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10))); |
| return true; |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsDecimalDigitValidShort - returns the TRUE if, ch, is a base legal decimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsDecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c) |
| { |
| if ((IsDigit (ch)) && (( ((unsigned int) (ch))- ((unsigned int) ('0'))) < base)) |
| { |
| (*c) = (*c)*((short unsigned int ) (base+( ((unsigned int) (ch))- ((unsigned int) ('0'))))); |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IsHexidecimalDigitValidShort - returns the TRUE if, ch, is a base legal hexidecimal digit. |
| If legal then the value is appended numerically onto, c. |
| */ |
| |
| static bool IsHexidecimalDigitValidShort (char ch, unsigned int base, short unsigned int *c) |
| { |
| if (((ch >= 'a') && (ch <= 'f')) && ((( ((unsigned int) (ch))- ((unsigned int) ('a')))+10) < base)) |
| { |
| (*c) = (*c)*((short unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('a')))+10))); |
| return true; |
| } |
| else if (((ch >= 'A') && (ch <= 'F')) && ((( ((unsigned int) (ch))- ((unsigned int) ('F')))+10) < base)) |
| { |
| /* avoid dangling else. */ |
| (*c) = (*c)*((short unsigned int ) (base+(( ((unsigned int) (ch))- ((unsigned int) ('A')))+10))); |
| return true; |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| return false; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ToThePower10 - returns a LONGREAL containing the value of v * 10^power. |
| */ |
| |
| static long double ToThePower10 (long double v, int power) |
| { |
| int i; |
| |
| i = 0; |
| if (power > 0) |
| { |
| while (i < power) |
| { |
| v = v*10.0; |
| i += 1; |
| } |
| } |
| else |
| { |
| while (i > power) |
| { |
| v = v/10.0; |
| i -= 1; |
| } |
| } |
| return v; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| DetermineSafeTruncation - we wish to use TRUNC when converting REAL/LONGREAL |
| into a string for the non fractional component. |
| However we need a simple method to |
| determine the maximum safe truncation value. |
| */ |
| |
| static unsigned int DetermineSafeTruncation (void) |
| { |
| double MaxPowerOfTen; |
| unsigned int LogPower; |
| |
| MaxPowerOfTen = static_cast<double> (1.0); |
| LogPower = 0; |
| while ((MaxPowerOfTen*10.0) < ((double) ((INT_MAX) / 10))) |
| { |
| MaxPowerOfTen = MaxPowerOfTen*10.0; |
| LogPower += 1; |
| } |
| return LogPower; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| rtos - |
| */ |
| |
| static DynamicStrings_String rtos (double r, unsigned int TotalWidth, unsigned int FractionWidth) |
| { |
| M2RTS_HALT (-1); |
| __builtin_unreachable (); |
| return static_cast<DynamicStrings_String> (NULL); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| lrtos - |
| */ |
| |
| static DynamicStrings_String lrtos (long double r, unsigned int TotalWidth, unsigned int FractionWidth) |
| { |
| M2RTS_HALT (-1); |
| __builtin_unreachable (); |
| return static_cast<DynamicStrings_String> (NULL); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| doDecimalPlaces - returns a string which is accurate to |
| n decimal places. It returns a new String |
| and, s, will be destroyed. |
| */ |
| |
| static DynamicStrings_String doDecimalPlaces (DynamicStrings_String s, unsigned int n) |
| { |
| int i; |
| int l; |
| int point; |
| DynamicStrings_String t; |
| DynamicStrings_String tenths; |
| DynamicStrings_String hundreths; |
| |
| l = DynamicStrings_Length (s); |
| i = 0; |
| /* remove '.' */ |
| point = DynamicStrings_Index (s, '.', 0); |
| if (point == 0) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0); |
| } |
| else if (point < l) |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point+1, 0))); |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point); |
| } |
| l = DynamicStrings_Length (s); |
| i = 0; |
| if (l > 0) |
| { |
| /* skip over leading zeros */ |
| while ((i < l) && ((DynamicStrings_char (s, i)) == '0')) |
| { |
| i += 1; |
| } |
| /* was the string full of zeros? */ |
| if ((i == l) && ((DynamicStrings_char (s, i-1)) == '0')) |
| { |
| s = DynamicStrings_KillString (s); |
| s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), n))); |
| return s; |
| } |
| } |
| /* insert leading zero */ |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('0'), DynamicStrings_Mark (s)); |
| point += 1; /* and move point position to correct place */ |
| l = DynamicStrings_Length (s); /* update new length */ |
| i = point; /* update new length */ |
| while ((n > 1) && (i < l)) |
| { |
| n -= 1; |
| i += 1; |
| } |
| if ((i+3) <= l) |
| { |
| t = DynamicStrings_Dup (s); |
| hundreths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+3); |
| s = t; |
| if ((StringConvert_stoc (hundreths)) >= 50) |
| { |
| s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i)); |
| } |
| hundreths = DynamicStrings_KillString (hundreths); |
| } |
| else if ((i+2) <= l) |
| { |
| /* avoid dangling else. */ |
| t = DynamicStrings_Dup (s); |
| tenths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+2); |
| s = t; |
| if ((StringConvert_stoc (tenths)) >= 5) |
| { |
| s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i)); |
| } |
| tenths = DynamicStrings_KillString (tenths); |
| } |
| /* check whether we need to remove the leading zero */ |
| if ((DynamicStrings_char (s, 0)) == '0') |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0); |
| l -= 1; |
| point -= 1; |
| } |
| if (i < l) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i); |
| l = DynamicStrings_Length (s); |
| if (l < point) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l))); |
| } |
| } |
| /* re-insert the point */ |
| if (point >= 0) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (point == 0) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('.'), DynamicStrings_Mark (s)); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0))); |
| } |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| doSigFig - returns a string which is accurate to |
| n decimal places. It returns a new String |
| and, s, will be destroyed. |
| */ |
| |
| static DynamicStrings_String doSigFig (DynamicStrings_String s, unsigned int n) |
| { |
| int i; |
| int l; |
| int z; |
| int point; |
| DynamicStrings_String t; |
| DynamicStrings_String tenths; |
| DynamicStrings_String hundreths; |
| |
| l = DynamicStrings_Length (s); |
| i = 0; |
| /* remove '.' */ |
| point = DynamicStrings_Index (s, '.', 0); |
| if (point >= 0) |
| { |
| if (point == 0) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 1, 0); |
| } |
| else if (point < l) |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point+1, 0))); |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point); |
| } |
| } |
| else |
| { |
| s = DynamicStrings_Dup (DynamicStrings_Mark (s)); |
| } |
| l = DynamicStrings_Length (s); |
| i = 0; |
| if (l > 0) |
| { |
| /* skip over leading zeros */ |
| while ((i < l) && ((DynamicStrings_char (s, i)) == '0')) |
| { |
| i += 1; |
| } |
| /* was the string full of zeros? */ |
| if ((i == l) && ((DynamicStrings_char (s, i-1)) == '0')) |
| { |
| /* truncate string */ |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (n)); |
| i = n; |
| } |
| } |
| /* add a leading zero in case we need to overflow the carry */ |
| z = i; /* remember where we inserted zero */ |
| if (z == 0) /* remember where we inserted zero */ |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('0'), DynamicStrings_Mark (s)); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i), '0'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), i, 0))); |
| } |
| n += 1; /* and increase the number of sig figs needed */ |
| l = DynamicStrings_Length (s); /* and increase the number of sig figs needed */ |
| while ((n > 1) && (i < l)) |
| { |
| n -= 1; |
| i += 1; |
| } |
| if ((i+3) <= l) |
| { |
| t = DynamicStrings_Dup (s); |
| hundreths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+3); |
| s = t; |
| if ((StringConvert_stoc (hundreths)) >= 50) |
| { |
| s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i)); |
| } |
| hundreths = DynamicStrings_KillString (hundreths); |
| } |
| else if ((i+2) <= l) |
| { |
| /* avoid dangling else. */ |
| t = DynamicStrings_Dup (s); |
| tenths = DynamicStrings_Slice (DynamicStrings_Mark (s), i+1, i+2); |
| s = t; |
| if ((StringConvert_stoc (tenths)) >= 5) |
| { |
| s = carryOne (DynamicStrings_Mark (s), static_cast<unsigned int> (i)); |
| } |
| tenths = DynamicStrings_KillString (tenths); |
| } |
| /* check whether we need to remove the leading zero */ |
| if ((DynamicStrings_char (s, z)) == '0') |
| { |
| if (z == 0) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), z+1, 0); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, z), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), z+1, 0))); |
| } |
| l = DynamicStrings_Length (s); |
| } |
| else |
| { |
| point += 1; |
| } |
| if (i < l) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i); |
| l = DynamicStrings_Length (s); |
| if (l < point) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l))); |
| } |
| } |
| /* re-insert the point */ |
| if (point >= 0) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (point == 0) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('.'), DynamicStrings_Mark (s)); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0))); |
| } |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| carryOne - add a carry at position, i. |
| */ |
| |
| static DynamicStrings_String carryOne (DynamicStrings_String s, unsigned int i) |
| { |
| if (i >= 0) |
| { |
| if (IsDigit (DynamicStrings_char (s, static_cast<int> (i)))) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if ((DynamicStrings_char (s, static_cast<int> (i))) == '9') |
| { |
| if (i == 0) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('1'), DynamicStrings_Mark (s)); |
| return s; |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (i)), '0'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0))); |
| return carryOne (s, i-1); |
| } |
| } |
| else |
| { |
| if (i == 0) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ( ((char) ( ((unsigned int) (DynamicStrings_char (s, static_cast<int> (i))))+1))), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, static_cast<int> (i)), ((char) ( ((unsigned int) (DynamicStrings_char (s, static_cast<int> (i))))+1))), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), static_cast<int> (i+1), 0))); |
| } |
| } |
| } |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| IntegerToString - converts INTEGER, i, into a String. The field with can be specified |
| if non zero. Leading characters are defined by padding and this |
| function will prepend a + if sign is set to TRUE. |
| The base allows the caller to generate binary, octal, decimal, hexidecimal |
| numbers. The value of lower is only used when hexidecimal numbers are |
| generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF |
| are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_IntegerToString (int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower) |
| { |
| DynamicStrings_String s; |
| unsigned int c; |
| |
| if (i < 0) |
| { |
| if (i == (INT_MIN)) |
| { |
| /* remember that -15 MOD 4 = 1 in Modula-2 */ |
| c = ((unsigned int ) (abs (i+1)))+1; |
| if (width > 0) |
| { |
| return DynamicStrings_ConCat (StringConvert_IntegerToString (-((int ) (c / base)), width-1, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (c % base), 0, ' ', false, base, lower))); |
| } |
| else |
| { |
| return DynamicStrings_ConCat (StringConvert_IntegerToString (-((int ) (c / base)), 0, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (c % base), 0, ' ', false, base, lower))); |
| } |
| } |
| else |
| { |
| s = DynamicStrings_InitString ((const char *) "-", 1); |
| } |
| i = -i; |
| } |
| else |
| { |
| if (sign) |
| { |
| s = DynamicStrings_InitString ((const char *) "+", 1); |
| } |
| else |
| { |
| s = DynamicStrings_InitString ((const char *) "", 0); |
| } |
| } |
| if (i > (((int ) (base))-1)) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (((unsigned int ) (i)) / base), 0, ' ', false, base, lower))), DynamicStrings_Mark (StringConvert_IntegerToString (static_cast<int> (((unsigned int ) (i)) % base), 0, ' ', false, base, lower))); |
| } |
| else |
| { |
| if (i <= 9) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (i))+ ((unsigned int) ('0'))))))); |
| } |
| else |
| { |
| if (lower) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('a')))-10))))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('A')))-10))))); |
| } |
| } |
| } |
| if (width > (DynamicStrings_Length (s))) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), DynamicStrings_Mark (s)); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| CardinalToString - converts CARDINAL, c, into a String. The field with can be specified |
| if non zero. Leading characters are defined by padding. |
| The base allows the caller to generate binary, octal, decimal, hexidecimal |
| numbers. The value of lower is only used when hexidecimal numbers are |
| generated and if TRUE then digits abcdef are used, and if FALSE then ABCDEF |
| are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_CardinalToString (unsigned int c, unsigned int width, char padding, unsigned int base, bool lower) |
| { |
| DynamicStrings_String s; |
| |
| s = DynamicStrings_InitString ((const char *) "", 0); |
| if (c > (base-1)) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_CardinalToString (c / base, 0, ' ', base, lower))), DynamicStrings_Mark (StringConvert_CardinalToString (c % base, 0, ' ', base, lower))); |
| } |
| else |
| { |
| if (c <= 9) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (c+ ((unsigned int) ('0'))))))); |
| } |
| else |
| { |
| if (lower) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((c+ ((unsigned int) ('a')))-10))))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((c+ ((unsigned int) ('A')))-10))))); |
| } |
| } |
| } |
| if (width > (DynamicStrings_Length (s))) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToInteger - converts a string, s, of, base, into an INTEGER. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" int StringConvert_StringToInteger (DynamicStrings_String s, unsigned int base, bool *found) |
| { |
| unsigned int n; |
| unsigned int l; |
| unsigned int c; |
| bool negative; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* returns a new string, s */ |
| l = DynamicStrings_Length (s); /* returns a new string, s */ |
| c = 0; |
| n = 0; |
| negative = false; |
| if (n < l) |
| { |
| /* parse leading + and - */ |
| while (((DynamicStrings_char (s, static_cast<int> (n))) == '-') || ((DynamicStrings_char (s, static_cast<int> (n))) == '+')) |
| { |
| if ((DynamicStrings_char (s, static_cast<int> (n))) == '-') |
| { |
| negative = ! negative; |
| } |
| n += 1; |
| } |
| while ((n < l) && ((IsDecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)))) |
| { |
| (*found) = true; |
| n += 1; |
| } |
| } |
| s = DynamicStrings_KillString (s); |
| if (negative) |
| { |
| return -((int ) (Min (((unsigned int ) (INT_MAX))+1, c))); |
| } |
| else |
| { |
| return (int ) (Min (static_cast<unsigned int> (INT_MAX), c)); |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToCardinal - converts a string, s, of, base, into a CARDINAL. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" unsigned int StringConvert_StringToCardinal (DynamicStrings_String s, unsigned int base, bool *found) |
| { |
| unsigned int n; |
| unsigned int l; |
| unsigned int c; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* returns a new string, s */ |
| l = DynamicStrings_Length (s); /* returns a new string, s */ |
| c = 0; |
| n = 0; |
| if (n < l) |
| { |
| /* parse leading + */ |
| while ((DynamicStrings_char (s, static_cast<int> (n))) == '+') |
| { |
| n += 1; |
| } |
| while ((n < l) && ((IsDecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValid (DynamicStrings_char (s, static_cast<int> (n)), base, &c)))) |
| { |
| (*found) = true; |
| n += 1; |
| } |
| } |
| s = DynamicStrings_KillString (s); |
| return c; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| LongIntegerToString - converts LONGINT, i, into a String. The field with |
| can be specified if non zero. Leading characters |
| are defined by padding and this function will |
| prepend a + if sign is set to TRUE. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongIntegerToString (long int i, unsigned int width, char padding, bool sign, unsigned int base, bool lower) |
| { |
| DynamicStrings_String s; |
| long unsigned int c; |
| |
| if (i < 0) |
| { |
| if (i == (LONG_MIN)) |
| { |
| /* remember that -15 MOD 4 is 1 in Modula-2, and although ABS(MIN(LONGINT)+1) |
| is very likely MAX(LONGINT), it is safer not to assume this is the case */ |
| c = ((long unsigned int ) (labs (i+1)))+1; |
| if (width > 0) |
| { |
| return DynamicStrings_ConCat (StringConvert_LongIntegerToString (-((long int ) (c / ((long unsigned int ) (base)))), width-1, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_LongIntegerToString (static_cast<long int> (c % ((long unsigned int ) (base))), 0, ' ', false, base, lower))); |
| } |
| else |
| { |
| return DynamicStrings_ConCat (StringConvert_LongIntegerToString (-((long int ) (c / ((long unsigned int ) (base)))), 0, padding, sign, base, lower), DynamicStrings_Mark (StringConvert_LongIntegerToString (static_cast<long int> (c % ((long unsigned int ) (base))), 0, ' ', false, base, lower))); |
| } |
| } |
| else |
| { |
| s = DynamicStrings_InitString ((const char *) "-", 1); |
| } |
| i = -i; |
| } |
| else |
| { |
| if (sign) |
| { |
| s = DynamicStrings_InitString ((const char *) "+", 1); |
| } |
| else |
| { |
| s = DynamicStrings_InitString ((const char *) "", 0); |
| } |
| } |
| if (i > ((long int ) (base-1))) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (StringConvert_LongIntegerToString (i / ((long int ) (base)), 0, ' ', false, base, lower))), DynamicStrings_Mark (StringConvert_LongIntegerToString (i % ((long int ) (base)), 0, ' ', false, base, lower))); |
| } |
| else |
| { |
| if (i <= 9) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (i))+ ((unsigned int) ('0'))))))); |
| } |
| else |
| { |
| if (lower) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('a')))-10))))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (i))+ ((unsigned int) ('A')))-10))))); |
| } |
| } |
| } |
| if (width > (DynamicStrings_Length (s))) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToLongInteger - converts a string, s, of, base, into an LONGINT. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" long int StringConvert_StringToLongInteger (DynamicStrings_String s, unsigned int base, bool *found) |
| { |
| unsigned int n; |
| unsigned int l; |
| long unsigned int c; |
| bool negative; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* returns a new string, s */ |
| l = DynamicStrings_Length (s); /* returns a new string, s */ |
| c = 0; |
| n = 0; |
| negative = false; |
| if (n < l) |
| { |
| /* parse leading + and - */ |
| while (((DynamicStrings_char (s, static_cast<int> (n))) == '-') || ((DynamicStrings_char (s, static_cast<int> (n))) == '+')) |
| { |
| if ((DynamicStrings_char (s, static_cast<int> (n))) == '-') |
| { |
| negative = ! negative; |
| } |
| n += 1; |
| } |
| while ((n < l) && ((IsDecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)))) |
| { |
| (*found) = true; |
| n += 1; |
| } |
| } |
| s = DynamicStrings_KillString (s); |
| if (negative) |
| { |
| return -((long int ) (LongMin (((long unsigned int ) (LONG_MAX))+1, c))); |
| } |
| else |
| { |
| return (long int ) (LongMin (static_cast<long unsigned int> (LONG_MAX), c)); |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| LongCardinalToString - converts LONGCARD, c, into a String. The field |
| width can be specified if non zero. Leading |
| characters are defined by padding. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongCardinalToString (long unsigned int c, unsigned int width, char padding, unsigned int base, bool lower) |
| { |
| DynamicStrings_String s; |
| |
| s = DynamicStrings_InitString ((const char *) "", 0); |
| if (c > ((long unsigned int ) (base-1))) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, StringConvert_LongCardinalToString (c / ((long unsigned int ) (base)), 0, ' ', base, lower)), StringConvert_LongCardinalToString (c % ((long unsigned int ) (base)), 0, ' ', base, lower)); |
| } |
| else |
| { |
| if (c <= 9) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (c))+ ((unsigned int) ('0')))))); |
| } |
| else |
| { |
| if (lower) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('a')))-10)))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('A')))-10)))); |
| } |
| } |
| } |
| if (width > (DynamicStrings_Length (s))) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToLongCardinal - converts a string, s, of, base, into a LONGCARD. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" long unsigned int StringConvert_StringToLongCardinal (DynamicStrings_String s, unsigned int base, bool *found) |
| { |
| unsigned int n; |
| unsigned int l; |
| long unsigned int c; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* returns a new string, s */ |
| l = DynamicStrings_Length (s); /* returns a new string, s */ |
| c = 0; |
| n = 0; |
| if (n < l) |
| { |
| /* parse leading + */ |
| while ((DynamicStrings_char (s, static_cast<int> (n))) == '+') |
| { |
| n += 1; |
| } |
| while ((n < l) && ((IsDecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidLong (DynamicStrings_char (s, static_cast<int> (n)), base, &c)))) |
| { |
| (*found) = true; |
| n += 1; |
| } |
| } |
| s = DynamicStrings_KillString (s); |
| return c; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ShortCardinalToString - converts SHORTCARD, c, into a String. The field |
| width can be specified if non zero. Leading |
| characters are defined by padding. |
| The base allows the caller to generate binary, |
| octal, decimal, hexidecimal numbers. |
| The value of lower is only used when hexidecimal |
| numbers are generated and if TRUE then digits |
| abcdef are used, and if FALSE then ABCDEF are used. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ShortCardinalToString (short unsigned int c, unsigned int width, char padding, unsigned int base, bool lower) |
| { |
| DynamicStrings_String s; |
| |
| s = DynamicStrings_InitString ((const char *) "", 0); |
| if (((unsigned int ) (c)) > (base-1)) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, StringConvert_ShortCardinalToString (c / ((short unsigned int ) (base)), 0, ' ', base, lower)), StringConvert_ShortCardinalToString (c % ((short unsigned int ) (base)), 0, ' ', base, lower)); |
| } |
| else |
| { |
| if (c <= 9) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) (((unsigned int ) (c))+ ((unsigned int) ('0')))))); |
| } |
| else |
| { |
| if (lower) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('a')))-10)))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_InitStringChar ( ((char) ((((unsigned int ) (c))+ ((unsigned int) ('A')))-10)))); |
| } |
| } |
| } |
| if (width > (DynamicStrings_Length (s))) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (padding)), width-(DynamicStrings_Length (s))), s); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToShortCardinal - converts a string, s, of, base, into a SHORTCARD. |
| Leading white space is ignored. It stops converting |
| when either the string is exhausted or if an illegal |
| numeral is found. |
| The parameter found is set TRUE if a number was found. |
| */ |
| |
| extern "C" short unsigned int StringConvert_StringToShortCardinal (DynamicStrings_String s, unsigned int base, bool *found) |
| { |
| unsigned int n; |
| unsigned int l; |
| short unsigned int c; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* returns a new string, s */ |
| l = DynamicStrings_Length (s); /* returns a new string, s */ |
| c = 0; |
| n = 0; |
| if (n < l) |
| { |
| /* parse leading + */ |
| while ((DynamicStrings_char (s, static_cast<int> (n))) == '+') |
| { |
| n += 1; |
| } |
| while ((n < l) && ((IsDecimalDigitValidShort (DynamicStrings_char (s, static_cast<int> (n)), base, &c)) || (IsHexidecimalDigitValidShort (DynamicStrings_char (s, static_cast<int> (n)), base, &c)))) |
| { |
| (*found) = true; |
| n += 1; |
| } |
| } |
| s = DynamicStrings_KillString (s); |
| return c; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| stoi - decimal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_stoi (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToInteger (s, 10, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| itos - integer to decimal string. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_itos (int i, unsigned int width, char padding, bool sign) |
| { |
| return StringConvert_IntegerToString (i, width, padding, sign, 10, false); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ctos - cardinal to decimal string. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ctos (unsigned int c, unsigned int width, char padding) |
| { |
| return StringConvert_CardinalToString (c, width, padding, 10, false); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| stoc - decimal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_stoc (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToCardinal (s, 10, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| hstoi - hexidecimal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_hstoi (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToInteger (s, 16, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ostoi - octal string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_ostoi (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToInteger (s, 8, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| bstoi - binary string to INTEGER |
| */ |
| |
| extern "C" int StringConvert_bstoi (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToInteger (s, 2, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| hstoc - hexidecimal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_hstoc (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToCardinal (s, 16, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ostoc - octal string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_ostoc (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToCardinal (s, 8, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| bstoc - binary string to CARDINAL |
| */ |
| |
| extern "C" unsigned int StringConvert_bstoc (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToCardinal (s, 2, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StringToLongreal - returns a LONGREAL and sets found to TRUE if a legal number is seen. |
| */ |
| |
| extern "C" long double StringConvert_StringToLongreal (DynamicStrings_String s, bool *found) |
| { |
| bool error; |
| long double value; |
| |
| s = DynamicStrings_RemoveWhitePrefix (s); /* new string is created */ |
| value = ldtoa_strtold (DynamicStrings_string (s), &error); /* new string is created */ |
| s = DynamicStrings_KillString (s); |
| (*found) = ! error; |
| return value; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| LongrealToString - converts a LONGREAL number, Real, which has, |
| TotalWidth, and FractionWidth into a string. |
| It uses decimal notation. |
| |
| So for example: |
| |
| LongrealToString(1.0, 4, 2) -> '1.00' |
| LongrealToString(12.3, 5, 2) -> '12.30' |
| LongrealToString(12.3, 6, 2) -> ' 12.30' |
| LongrealToString(12.3, 6, 3) -> '12.300' |
| |
| if total width is too small then the fraction |
| becomes truncated. |
| |
| LongrealToString(12.3, 5, 3) -> '12.30' |
| |
| Positive numbers do not have a '+' prepended. |
| Negative numbers will have a '-' prepended and |
| the TotalWidth will need to be large enough |
| to contain the sign, whole number, '.' and |
| fractional components. |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_LongrealToString (long double x, unsigned int TotalWidth, unsigned int FractionWidth) |
| { |
| bool maxprecision; |
| DynamicStrings_String s; |
| void * r; |
| int point; |
| bool sign; |
| int l; |
| |
| if (TotalWidth == 0) |
| { |
| maxprecision = true; |
| r = ldtoa_ldtoa (x, static_cast<int> (ldtoa_decimaldigits), 100, &point, &sign); |
| } |
| else |
| { |
| r = ldtoa_ldtoa (x, static_cast<int> (ldtoa_decimaldigits), 100, &point, &sign); |
| } |
| s = DynamicStrings_InitStringCharStar (r); |
| libc_free (r); |
| l = DynamicStrings_Length (s); |
| if (point > l) |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (point-l)))); |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".0", 2))); |
| if (! maxprecision && (FractionWidth > 0)) |
| { |
| FractionWidth -= 1; |
| if (((int ) (FractionWidth)) > (point-l)) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), FractionWidth))); |
| } |
| } |
| } |
| else if (point < 0) |
| { |
| /* avoid dangling else. */ |
| s = DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), static_cast<unsigned int> (-point)), DynamicStrings_Mark (s)); |
| l = DynamicStrings_Length (s); |
| s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (s)); |
| if (! maxprecision && (l < ((int ) (FractionWidth)))) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), static_cast<unsigned int> (((int ) (FractionWidth))-l)))); |
| } |
| } |
| else |
| { |
| /* avoid dangling else. */ |
| if (point == 0) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0.", 2), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0))); |
| } |
| else |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, point), '.'), DynamicStrings_Mark (DynamicStrings_Slice (DynamicStrings_Mark (s), point, 0))); |
| } |
| if (! maxprecision && ((l-point) < ((int ) (FractionWidth)))) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "0", 1)), static_cast<unsigned int> (((int ) (FractionWidth))-(l-point))))); |
| } |
| } |
| if ((DynamicStrings_Length (s)) > TotalWidth) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (TotalWidth > 0) |
| { |
| if (sign) |
| { |
| s = DynamicStrings_Slice (DynamicStrings_Mark (StringConvert_ToDecimalPlaces (s, FractionWidth)), 0, static_cast<int> (TotalWidth-1)); |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('-'), DynamicStrings_Mark (s)); |
| sign = false; |
| } |
| else |
| { |
| /* minus 1 because all results will include a '.' */ |
| s = DynamicStrings_Slice (DynamicStrings_Mark (StringConvert_ToDecimalPlaces (s, FractionWidth)), 0, static_cast<int> (TotalWidth)); |
| } |
| } |
| else |
| { |
| if (sign) |
| { |
| s = StringConvert_ToDecimalPlaces (s, FractionWidth); |
| s = DynamicStrings_ConCat (DynamicStrings_InitStringChar ('-'), DynamicStrings_Mark (s)); |
| sign = false; |
| } |
| else |
| { |
| /* minus 1 because all results will include a '.' */ |
| s = StringConvert_ToDecimalPlaces (s, FractionWidth); |
| } |
| } |
| } |
| if ((DynamicStrings_Length (s)) < TotalWidth) |
| { |
| s = DynamicStrings_ConCat (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar (' ')), TotalWidth-(DynamicStrings_Length (s))), DynamicStrings_Mark (s)); |
| } |
| return s; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| stor - returns a REAL given a string. |
| */ |
| |
| extern "C" double StringConvert_stor (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return (double ) (StringConvert_StringToLongreal (s, &found)); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| stolr - returns a LONGREAL given a string. |
| */ |
| |
| extern "C" long double StringConvert_stolr (DynamicStrings_String s) |
| { |
| bool found; |
| |
| return StringConvert_StringToLongreal (s, &found); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ToSigFig - returns a floating point or base 10 integer |
| string which is accurate to, n, significant |
| figures. It will return a new String |
| and, s, will be destroyed. |
| |
| |
| So: 12.345 |
| |
| rounded to the following significant figures yields |
| |
| 5 12.345 |
| 4 12.34 |
| 3 12.3 |
| 2 12 |
| 1 10 |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ToSigFig (DynamicStrings_String s, unsigned int n) |
| { |
| int point; |
| unsigned int poTen; |
| |
| Assert ((IsDigit (DynamicStrings_char (s, 0))) || ((DynamicStrings_char (s, 0)) == '.'), (const char *) "../../gcc/m2/gm2-libs/StringConvert.mod", 39, 1220, (const char *) "ToSigFig", 8); |
| point = DynamicStrings_Index (s, '.', 0); |
| if (point < 0) |
| { |
| poTen = DynamicStrings_Length (s); |
| } |
| else |
| { |
| poTen = point; |
| } |
| s = doSigFig (s, n); |
| /* if the last character is '.' remove it */ |
| if (((DynamicStrings_Length (s)) > 0) && ((DynamicStrings_char (s, -1)) == '.')) |
| { |
| return DynamicStrings_Slice (DynamicStrings_Mark (s), 0, -1); |
| } |
| else |
| { |
| if (poTen > (DynamicStrings_Length (s))) |
| { |
| s = DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), poTen-(DynamicStrings_Length (s))))); |
| } |
| return s; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ToDecimalPlaces - returns a floating point or base 10 integer |
| string which is accurate to, n, decimal |
| places. It will return a new String |
| and, s, will be destroyed. |
| Decimal places yields, n, digits after |
| the . |
| |
| So: 12.345 |
| |
| rounded to the following decimal places yields |
| |
| 5 12.34500 |
| 4 12.3450 |
| 3 12.345 |
| 2 12.34 |
| 1 12.3 |
| */ |
| |
| extern "C" DynamicStrings_String StringConvert_ToDecimalPlaces (DynamicStrings_String s, unsigned int n) |
| { |
| int point; |
| |
| Assert ((IsDigit (DynamicStrings_char (s, 0))) || ((DynamicStrings_char (s, 0)) == '.'), (const char *) "../../gcc/m2/gm2-libs/StringConvert.mod", 39, 1069, (const char *) "ToDecimalPlaces", 15); |
| point = DynamicStrings_Index (s, '.', 0); |
| if (point < 0) |
| { |
| /* avoid gcc warning by using compound statement even if not strictly necessary. */ |
| if (n > 0) |
| { |
| return DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitStringChar ('.'))), DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitStringChar ('0')), n)); |
| } |
| else |
| { |
| return s; |
| } |
| } |
| s = doDecimalPlaces (s, n); |
| /* if the last character is '.' remove it */ |
| if (((DynamicStrings_Length (s)) > 0) && ((DynamicStrings_char (s, -1)) == '.')) |
| { |
| return DynamicStrings_Slice (DynamicStrings_Mark (s), 0, -1); |
| } |
| else |
| { |
| return s; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| extern "C" void _M2_StringConvert_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |
| |
| extern "C" void _M2_StringConvert_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |