[gcalctool] Fixes for thousand separators and radix points in input, radix points in output



commit 936586876819c25321694794819976d9a6caeeb2
Author: Robin Sonefors <ozamosi flukkost nu>
Date:   Thu Sep 30 21:48:38 2010 +0200

    Fixes for thousand separators and radix points in input, radix points in output
    
    Before, '.' and ',' were always treated as radix points in input. Now
    ',' is only treated as a radix point if the user's locale specifies it.
    
    If it doesn't, it means you can paste something like "1,574.78".
    
    Before, all numbers were displayed with '.' as their radix point. Now
    they respect the user's locale.
    
    The lexer was also reformatted to have roughly 1 order of magnitude fewer
    states.

 src/gcalccmd.c          |    2 +-
 src/gcalctool.c         |    2 +-
 src/math-buttons.c      |   12 +++++-----
 src/math-equation.c     |    6 ++--
 src/math-variables.c    |    2 +-
 src/mp-binary.c         |    6 ++--
 src/mp-convert.c        |   57 ++++++++++++++++++++++++++++++++++++++--------
 src/mp-equation-lexer.l |   47 ++++++++++++++++++++++----------------
 src/mp.h                |    4 +-
 src/unittest.c          |    2 +-
 10 files changed, 92 insertions(+), 48 deletions(-)
---
diff --git a/src/gcalccmd.c b/src/gcalccmd.c
index 9af9a58..2812952 100644
--- a/src/gcalccmd.c
+++ b/src/gcalccmd.c
@@ -48,7 +48,7 @@ solve(const char *equation)
     else if (ret)        
         fprintf(stderr, "Error %d\n", ret);
     else {
-        mp_cast_to_string(&z, 10, 10, 9, 1, result_str, MAXLINE);
+        mp_cast_to_string(&z, 10, 10, 9, 1, TRUE, result_str, MAXLINE);
         printf("%s\n", result_str);
     }
 }
diff --git a/src/gcalctool.c b/src/gcalctool.c
index bc2f6ba..e2d8b45 100644
--- a/src/gcalctool.c
+++ b/src/gcalctool.c
@@ -61,7 +61,7 @@ solve(const char *equation)
         exit(1);
     }
     else {
-        mp_cast_to_string(&result, 10, 10, 9, 1, result_str, 1024);
+        mp_cast_to_string(&result, 10, 10, 9, 1, TRUE, result_str, 1024);
         printf("%s\n", result_str);
         exit(0);
     }
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 1978ca2..802c290 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -422,10 +422,10 @@ update_angle_label (MathButtons *buttons)
             mp_set_from_mp(&x, &input);
             mp_set_from_integer(mp_is_negative(&input) ? -1 : 1, &fraction);
         }
-        mp_cast_to_string(&input, 10, 10, 2, false, input_text, 1024);
+        mp_cast_to_string(&input, 10, 10, 2, false, true, input_text, 1024);
 
         mp_multiply_integer(&fraction, 360, &output);
-        mp_cast_to_string(&output, 10, 10, 2, false, output_text, 1024);
+        mp_cast_to_string(&output, 10, 10, 2, false, true, output_text, 1024);
         label = g_strdup_printf(_("%s radians = %s degrees"), input_text, output_text);
         break;
     case MP_GRADIANS:
@@ -442,10 +442,10 @@ update_angle_label (MathButtons *buttons)
             mp_set_from_integer(mp_is_negative(&input) ? -1 : 1, &fraction);
         }
 
-        mp_cast_to_string(&input, 10, 10, 2, false, input_text, 1024);
+        mp_cast_to_string(&input, 10, 10, 2, false, true, input_text, 1024);
 
         mp_multiply_integer(&fraction, 360, &output);
-        mp_cast_to_string(&output, 10, 10, 2, false, output_text, 1024);
+        mp_cast_to_string(&output, 10, 10, 2, false, true, output_text, 1024);
         label = g_strdup_printf(_("%s gradians = %s degrees"), input_text, output_text);
         break;
     }
@@ -543,8 +543,8 @@ update_currency_label(MathButtons *buttons)
         const char *source_symbol, *target_symbol;
         int i;
 
-        mp_cast_to_string(&x, 10, 10, 2, false, input_text, 1024);
-        mp_cast_to_string(&value, 10, 10, 2, false, output_text, 1024);
+        mp_cast_to_string(&x, 10, 10, 2, false, true, input_text, 1024);
+        mp_cast_to_string(&value, 10, 10, 2, false, true, output_text, 1024);
 
         for (i = 0; strcmp(math_equation_get_source_currency(buttons->priv->equation), currency_names[i].short_name) != 0; i++);
         source_symbol = currency_names[i].symbol;
diff --git a/src/math-equation.c b/src/math-equation.c
index 1cc033d..cec1dc7 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -1276,13 +1276,13 @@ display_make_number(MathEquation *equation, char *target, int target_len, const
 {
     switch(equation->priv->format) {
     case FIX:
-        mp_cast_to_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
+        mp_cast_to_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, true, target, target_len);
         break;
     case SCI:
-        mp_cast_to_exponential_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, false, target, target_len);
+        mp_cast_to_exponential_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, false, true, target, target_len);
         break;
     case ENG:
-        mp_cast_to_exponential_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, true, target, target_len);
+        mp_cast_to_exponential_string(x, equation->priv->base, equation->priv->base, equation->priv->accuracy, !equation->priv->show_zeroes, true, true, target, target_len);
         break;
     }
 }
diff --git a/src/math-variables.c b/src/math-variables.c
index b4f7720..53ef1af 100644
--- a/src/math-variables.c
+++ b/src/math-variables.c
@@ -97,7 +97,7 @@ registers_save(MathVariables *variables)
         MPNumber *value = val;
         char number[1024];
 
-        mp_cast_to_string(value, 10, 10, 50, TRUE, number, 1024);
+        mp_cast_to_string(value, 10, 10, 50, TRUE, FALSE, number, 1024);
         fprintf(f, "%s=%s\n", name, number);
     }
     fclose(f);
diff --git a/src/mp-binary.c b/src/mp-binary.c
index e4cedba..c2a6d16 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -45,8 +45,8 @@ mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, in
     char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS], text_out2[MAX_DIGITS];
     int offset1, offset2, offset_out;
 
-    mp_cast_to_string(x, 16, 16, 0, 0, text1, MAX_DIGITS);
-    mp_cast_to_string(y, 16, 16, 0, 0, text2, MAX_DIGITS);
+    mp_cast_to_string(x, 16, 16, 0, 0, FALSE, text1, MAX_DIGITS);
+    mp_cast_to_string(y, 16, 16, 0, 0, FALSE, text2, MAX_DIGITS);
     offset1 = strlen(text1) - 1;
     offset2 = strlen(text2) - 1;
     offset_out = wordlen / 4 - 1;
@@ -156,7 +156,7 @@ mp_mask(const MPNumber *x, int wordlen, MPNumber *z)
     size_t len, offset;
 
     /* Convert to a hexadecimal string and use last characters */
-    mp_cast_to_string(x, 16, 16, 0, 0, text, MAX_DIGITS);
+    mp_cast_to_string(x, 16, 16, 0, 0, FALSE, text, MAX_DIGITS);
     len = strlen(text);
     offset = wordlen / 4;
     offset = len > offset ? len - offset: 0;
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 68be574..e305aef 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <math.h>
+#include <langinfo.h>
 
 #include "mp.h"
 #include "mp-private.h"
@@ -507,8 +508,20 @@ mp_cast_to_double(const MPNumber *x)
 }
 
 
+static const char*
+mp_radix_char()
+{
+    static const char* radix = NULL;
+    if (radix == NULL) {
+        radix = nl_langinfo(RADIXCHAR);
+        radix = radix ? g_locale_to_utf8(radix, -1, NULL, NULL, NULL) : g_strdup(".");
+    }
+    return radix;
+}
+
+
 static void
-mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accuracy, bool trim_zeroes, bool force_sign, GString *string)
+mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accuracy, bool trim_zeroes, bool force_sign, bool localize_radix, GString *string)
 {
     static char digits[] = "0123456789ABCDEF";
     MPNumber number, integer_component, fractional_component, temp;
@@ -549,7 +562,12 @@ mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accura
     } while (!mp_is_zero(&temp));
 
     last_non_zero = string->len;
-    g_string_append_c(string, '.');
+
+    /* Allow user to change locale without breaking saved numbers */
+    if (localize_radix)
+        g_string_append(string, mp_radix_char());
+    else
+        g_string_append_c(string, '.');
 
     /* Write out the fractional component */
     mp_set_from_mp(&fractional_component, &temp);
@@ -600,7 +618,7 @@ mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accura
 
 
 void
-mp_cast_to_string(const MPNumber *x, int default_base, int base, int accuracy, bool trim_zeroes, char *buffer, int buffer_length)
+mp_cast_to_string(const MPNumber *x, int default_base, int base, int accuracy, bool trim_zeroes, bool localize_radix, char *buffer, int buffer_length)
 {
     GString *string;
     MPNumber x_real;
@@ -608,7 +626,7 @@ mp_cast_to_string(const MPNumber *x, int default_base, int base, int accuracy, b
     string = g_string_sized_new(buffer_length);
 
     mp_real_component(x, &x_real);
-    mp_cast_to_string_real(&x_real, default_base, base, accuracy, trim_zeroes, FALSE, string);
+    mp_cast_to_string_real(&x_real, default_base, base, accuracy, trim_zeroes, FALSE, localize_radix, string);
     if (mp_is_complex(x)) {
         GString *s;
         gboolean force_sign = TRUE;
@@ -622,7 +640,7 @@ mp_cast_to_string(const MPNumber *x, int default_base, int base, int accuracy, b
         }
 
         s = g_string_sized_new(buffer_length);
-        mp_cast_to_string_real(&x_im, default_base, 10, accuracy, trim_zeroes, force_sign, s);
+        mp_cast_to_string_real(&x_im, default_base, 10, accuracy, trim_zeroes, force_sign, localize_radix, s);
         if (strcmp(s->str, "0") == 0 || strcmp(s->str, "+0") == 0 || strcmp(s->str, "â??0") == 0) {
             /* Ignore */
         }
@@ -653,7 +671,7 @@ mp_cast_to_string(const MPNumber *x, int default_base, int base, int accuracy, b
 
 
 void
-mp_cast_to_exponential_string(const MPNumber *x, int default_base, int base_, int max_digits, bool trim_zeroes, bool eng_format, char *buffer, int buffer_length)
+mp_cast_to_exponential_string(const MPNumber *x, int default_base, int base_, int max_digits, bool trim_zeroes, bool eng_format, bool localize_radix, char *buffer, int buffer_length)
 {
     char fixed[1024], *c;
     MPNumber t, z, base, base3, base10, base10inv, mantissa;
@@ -698,7 +716,7 @@ mp_cast_to_exponential_string(const MPNumber *x, int default_base, int base_, in
         }
     }
 
-    mp_cast_to_string(&mantissa, default_base, base_, max_digits, trim_zeroes, fixed, 1024);
+    mp_cast_to_string(&mantissa, default_base, base_, max_digits, trim_zeroes, localize_radix, fixed, 1024);
     g_string_append(string, fixed);
     if (exponent != 0) {
         g_string_append_printf(string, "Ã?10"); // FIXME: Use the current base
@@ -837,7 +855,13 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z)
     const char *fractions[]     = {"½", "â??", "â??", "¼", "¾", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
     int numerators[]            = { 1,   1,   2,   1,   3,   1,   2,   3,   4,   1,   5,   1,   3,   5,   7};
     int denominators[]          = { 2,   3,   3,   4,   4,   5,   5,   5,   5,   6,   6,   8,   8,   8,   8};
-  
+    static const char *tsep = NULL;
+
+    if (tsep == NULL) {
+        tsep = nl_langinfo(THOUSEP);
+        tsep = tsep ? g_locale_to_utf8(tsep, -1, NULL, NULL, NULL) : g_strdup(",");
+    }
+
     if (strstr(str, "°"))
         return set_from_sexagesimal(str, strlen(str), z);
 
@@ -875,7 +899,16 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z)
 
     /* Convert integer part */
     mp_set_from_integer(0, z);
-    while ((i = char_val((char **)&c, base)) >= 0) {
+    while (1) {
+        if (strncmp(c, tsep, strlen(tsep)) == 0) {
+            c += strlen(tsep);
+            continue;
+        }
+
+        i = char_val((char **)&c, base);
+        if (i < 0)
+            break;
+
         if (i > base)
             return true;
         mp_multiply_integer(z, base, z);
@@ -895,7 +928,11 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z)
         mp_add(z, &fraction, z);
     }
 
-    if (*c == '.' || *c == ',') {
+    /* Accept both the user's local radix point (usually '.' or ','), and the
+     * english '.', since at least europeans frequently use '.' despite ','
+     * being the correct one for their locale.
+     */
+    if (*c == '.' || strncmp(c, mp_radix_char(), strlen(mp_radix_char())) == 0) {
         has_fraction = TRUE;
         c++;
     }
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index bbc9765..bc13114 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -36,24 +36,29 @@
 %}
 
 
-ZERO          "0"|"Ù "|"Û°"|"ß?"|"०"|"০"|"੦"|"૦"|"à­¦"|"௦"|"౦"|"೦"|"൦"|"à¹?"|"à»?"|"༠"|"á??"|"á??"|"á? "|"á ?"|"á¥?"|"á§?"|"á­?"|"á®°"|"á±?"|"á±?"|"ê? "|"ê£?"|"ê¤?"|"ê©?"|"ð?? "
-ONE           "1"|"Ù¡"|"Û±"|"ß?"|"१"|"১"|"੧"|"૧"|"à­§"|"௧"|"౧"|"೧"|"൧"|"à¹?"|"à»?"|"༡"|"á??"|"á??"|"á?¡"|"á ?"|"á¥?"|"á§?"|"á­?"|"á®±"|"á±?"|"á±?"|"ê?¡"|"ê£?"|"ê¤?"|"ê©?"|"ð??¡"
-TWO           "2"|"Ù¢"|"Û²"|"ß?"|"२"|"২"|"੨"|"૨"|"à­¨"|"௨"|"౨"|"೨"|"൨"|"à¹?"|"à»?"|"༢"|"á??"|"á??"|"á?¢"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮲"|"á±?"|"á±?"|"ê?¢"|"ê£?"|"ê¤?"|"ê©?"|"ð??¢"
-THREE         "3"|"Ù£"|"Û³"|"ß?"|"३"|"৩"|"à©©"|"à«©"|"à­©"|"௩"|"౩"|"೩"|"൩"|"à¹?"|"à»?"|"༣"|"á??"|"á??"|"á?£"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮳"|"á±?"|"á±?"|"ê?£"|"ê£?"|"ê¤?"|"ê©?"|"ð??£"
-FOUR          "4"|"Ù¤"|"Û´"|"ß?"|"४"|"৪"|"੪"|"૪"|"à­ª"|"௪"|"౪"|"೪"|"൪"|"à¹?"|"à»?"|"༤"|"á??"|"á??"|"á?¤"|"á ?"|"á¥?"|"á§?"|"á­?"|"á®´"|"á±?"|"á±?"|"ê?¤"|"ê£?"|"ê¤?"|"ê©?"|"ð??¤"
-FIVE          "5"|"Ù¥"|"Ûµ"|"ß?"|"५"|"৫"|"à©«"|"à««"|"à­«"|"௫"|"౫"|"೫"|"൫"|"à¹?"|"à»?"|"༥"|"á??"|"á??"|"á?¥"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮵"|"á±?"|"á±?"|"ê?¥"|"ê£?"|"ê¤?"|"ê©?"|"ð??¥"
-SIX           "6"|"Ù¦"|"Û¶"|"ß?"|"६"|"৬"|"੬"|"૬"|"à­¬"|"௬"|"౬"|"೬"|"൬"|"à¹?"|"à»?"|"༦"|"á??"|"á??"|"á?¦"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮶"|"á±?"|"á±?"|"ê?¦"|"ê£?"|"ê¤?"|"ê©?"|"ð??¦"
-SEVEN         "7"|"Ù§"|"Û·"|"ß?"|"७"|"৭"|"à©­"|"à«­"|"à­­"|"௭"|"à±­"|"à³­"|"൭"|"à¹?"|"à»?"|"༧"|"á??"|"á??"|"á?§"|"á ?"|"á¥?"|"á§?"|"á­?"|"á®·"|"á±?"|"á±?"|"ê?§"|"ê£?"|"ê¤?"|"ê©?"|"ð??§"
-EIGHT         "8"|"Ù¨"|"Û¸"|"ß?"|"८"|"৮"|"à©®"|"à«®"|"à­®"|"௮"|"à±®"|"à³®"|"൮"|"à¹?"|"à»?"|"༨"|"á??"|"á??"|"á?¨"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮸"|"á±?"|"á±?"|"ê?¨"|"ê£?"|"ê¤?"|"ê©?"|"ð??¨"
-NINE          "9"|"Ù©"|"Û¹"|"ß?"|"९"|"৯"|"੯"|"૯"|"à­¯"|"௯"|"౯"|"೯"|"൯"|"à¹?"|"à»?"|"༩"|"á??"|"á??"|"á?©"|"á ?"|"á¥?"|"á§?"|"á­?"|"᮹"|"á±?"|"á±?"|"ê?©"|"ê£?"|"ê¤?"|"ê©?"|"ð??©"
-DECIMAL	      "."|","
+ZERO          [0Ù Û°ß?०০੦૦୦௦౦೦൦à¹?à»?༠á??á??á? á ?á¥?á§?á­?á®°á±?á±?ê? ê£?ê¤?ê©?ð?? ]
+ONE           [1Ù¡Û±ß?१১੧૧୧௧౧೧൧à¹?à»?༡á??á??á?¡á ?á¥?á§?á­?á®±á±?á±?ê?¡ê£?ê¤?ê©?ð??¡]
+TWO           [2Ù¢Û²ß?२২੨૨୨௨౨೨൨à¹?à»?༢á??á??á?¢á ?á¥?á§?á­?᮲á±?á±?ê?¢ê£?ê¤?ê©?ð??¢]
+THREE         [3Ù£Û³ß?३৩੩૩୩௩౩೩൩à¹?à»?༣á??á??á?£á ?á¥?á§?á­?᮳á±?á±?ê?£ê£?ê¤?ê©?ð??£]
+FOUR          [4Ù¤Û´ß?४৪੪૪୪௪౪೪൪à¹?à»?༤á??á??á?¤á ?á¥?á§?á­?á®´á±?á±?ê?¤ê£?ê¤?ê©?ð??¤]
+FIVE          [5Ù¥Ûµß?५৫੫૫୫௫౫೫൫à¹?à»?༥á??á??á?¥á ?á¥?á§?á­?᮵á±?á±?ê?¥ê£?ê¤?ê©?ð??¥]
+SIX           [6Ù¦Û¶ß?६৬੬૬୬௬౬೬൬à¹?à»?༦á??á??á?¦á ?á¥?á§?á­?᮶á±?á±?ê?¦ê£?ê¤?ê©?ð??¦]
+SEVEN         [7Ù§Û·ß?७৭੭૭୭௭౭೭൭à¹?à»?༧á??á??á?§á ?á¥?á§?á­?á®·á±?á±?ê?§ê£?ê¤?ê©?ð??§]
+EIGHT         [8Ù¨Û¸ß?८৮੮૮୮௮౮೮൮à¹?à»?༨á??á??á?¨á ?á¥?á§?á­?᮸á±?á±?ê?¨ê£?ê¤?ê©?ð??¨]
+NINE          [9Ù©Û¹ß?९৯੯૯୯௯౯೯൯à¹?à»?༩á??á??á?©á ?á¥?á§?á­?᮹á±?á±?ê?©ê£?ê¤?ê©?ð??©]
+/* FIXME: DECIMAL and TSEP needs to figure out, at runtime, the correct
+ * character. I can't figure out how to make flex do this, so I send
+ * everything at mp_set_from_string and let it fail. This is slow.
+ */
+DECIMAL       .
+TSEP          .
 DEC           {ZERO}|{ONE}|{TWO}|{THREE}|{FOUR}|{FIVE}|{SIX}|{SEVEN}|{EIGHT}|{NINE}
 HEX           {DEC}|[A-F]|[a-f]
-SUPER_DIGITS  "�"|"¹"|"²"|"³"|"�"|"�"|"�"|"�"|"�"|"�"
+SUPER_DIGITS  [�¹²³������]
 SUPER_MINUS   "â?»"
-SUB_DIGITS    "â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
-FRACTION      "½"|"â??"|"â??"|"¼"|"¾"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
-GREEKS        "α"|"β"|"γ"|"δ"|"ε"|"ζ"|"η"|"θ"|"ι"|"κ"|"λ"|"μ"|"ν"|"ξ"|"ο"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"
+SUB_DIGITS    [â??â??â??â??â??â??â??â??â??â??]
+FRACTION      [½â??â??¼¾â??â??â??â??â??â??â??â??â??â??]
+GREEKS        [αβγδεζηθικλμνξοÏ?Ï?Ï?Ï?Ï?Ï?Ï?Ï?Ï?Ï?]
 DEGREES       "°"
 MINUTES       "'"
 SECONDS       "\""
@@ -63,9 +68,11 @@ SUP_NUM  {SUPER_DIGITS}+
 NSUP_NUM {SUPER_MINUS}{SUPER_DIGITS}+
 SUB_NUM  {SUB_DIGITS}+
 WORD     {LETTERS}+
-DEC_NUM  {DEC}+|{DEC}*{DECIMAL}{DEC}+
-DEF_NUM  {HEX}+|{HEX}*{DECIMAL}{HEX}+
-BASE_NUM {HEX}+{SUB_NUM}|{HEX}*{DECIMAL}{HEX}+{SUB_NUM}
+DEC_TSEP {DEC}{1,3}({TSEP}?{DEC}{3})*
+HEX_TSEP {HEX}{1,3}({TSEP}?{HEX}{3})*
+DEC_NUM  {DEC_TSEP}|{DEC_TSEP}?{DECIMAL}{DEC}+
+DEF_NUM  {HEX_TSEP}|{HEX_TSEP}?{DECIMAL}{HEX}+
+BASE_NUM {HEX_TSEP}{SUB_NUM}|{HEX_TSEP}?{DECIMAL}{HEX}+{SUB_NUM}
 ANGLE_NUM {DEC_NUM}{DEGREES}|{DEC}+{DEGREES}{DEC_NUM}{MINUTES}|{DEC}+{DEGREES}{DEC}+{MINUTES}{DEC_NUM}{SECONDS}
 
 NUMBER   {DEF_NUM}|{BASE_NUM}|{FRACTION}|{DEC}+{FRACTION}|{ANGLE_NUM}
@@ -74,8 +81,8 @@ VARIABLE {WORD}|{WORD}{SUB_NUM}|{GREEKS}
 MOD  [mM][oO][dD]
 AND  "â?§"|[aA][nN][dD]
 OR   "â?¨"|[oO][rR]
-XOR  "â?»"|"â??"|[xX][oO][rR]
-NOT  "¬"|"~"|[nN][oO][tT]
+XOR  [â?»â??]|[xX][oO][rR]
+NOT  [¬~]|[nN][oO][tT]
 RE   "â?°â??"
 IM   "â??"
 IN   [iI][nN]
diff --git a/src/mp.h b/src/mp.h
index d71111d..bca77c9 100644
--- a/src/mp.h
+++ b/src/mp.h
@@ -277,7 +277,7 @@ uint64_t mp_cast_to_unsigned_int(const MPNumber *x);
  * If 'trim_zeroes' is non-zero then strip off trailing zeroes.
  * Fractional components are truncated at 'max_digits' digits.
  */
-void   mp_cast_to_string(const MPNumber *x, int default_base, int base, int max_digits, bool trim_zeroes, char *buffer, int buffer_length);
+void   mp_cast_to_string(const MPNumber *x, int default_base, int base, int max_digits, bool trim_zeroes, bool localize_radix, char *buffer, int buffer_length);
 
 /* Converts x to a string representation in exponential form.
  * The string is written into 'buffer' which is guaranteed to be at least 'buffer_length' octets in size.
@@ -286,7 +286,7 @@ void   mp_cast_to_string(const MPNumber *x, int default_base, int base, int max_
  * If 'trim_zeroes' is non-zero then strip off trailing zeroes.
  * Fractional components are truncated at 'max_digits' digits.
  */
-void   mp_cast_to_exponential_string(const MPNumber *x, int default_base, int base, int max_digits, bool trim_zeroes, bool eng_format, char *buffer, int buffer_length);
+void   mp_cast_to_exponential_string(const MPNumber *x, int default_base, int base, int max_digits, bool trim_zeroes, bool eng_format, bool localize_radix, char *buffer, int buffer_length);
 
 /* Sets z = sin x */
 void   mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
diff --git a/src/unittest.c b/src/unittest.c
index 791391b..417813f 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -83,7 +83,7 @@ test(char *expression, char *expected, int expected_error)
     error = mp_equation_parse(expression, &options, &result, NULL);
 
     if(error == 0) {
-        mp_cast_to_string(&result, options.base, options.base, 9, 1, result_str, 1024);
+        mp_cast_to_string(&result, options.base, options.base, 9, 1, TRUE, result_str, 1024);
         if(expected_error != 0)
             fail("'%s' -> %s, expected error %s", expression, result_str, error_code_to_string(expected_error));
         else if(strcmp(result_str, expected) != 0)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]