perl.h: Add macros and comments
authorKarl Williamson <public@khwilliamson.com>
Tue, 17 Dec 2013 04:47:27 +0000 (21:47 -0700)
committerKarl Williamson <public@khwilliamson.com>
Sat, 4 Jan 2014 20:33:05 +0000 (13:33 -0700)
These macros are used in making sure the current locale is the correct
one for the circumstances.  I'm not a fan of this type of code
generation macro, but this just extends what is already there, and
aren't all that complicated.

perl.h

diff --git a/perl.h b/perl.h
index bf6c129..c777b1b 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -5230,12 +5230,54 @@ typedef struct am_table_short AMTS;
        (IN_PERL_COMPILETIME ? IN_SOME_LOCALE_FORM_COMPILETIME \
                             : IN_SOME_LOCALE_FORM_RUNTIME)
 
+/* These macros are for toggling between the underlying locale (LOCAL) and the
+ * C locale. */
+
+/* The first set makes sure that the locale is set to C unless within a 'use
+ * locale's scope; otherwise to the default locale.  A function pointer is
+ * used, which can be declared separately by
+ * DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED, followed by the actual
+ * setting (using STORE_LC_NUMERIC_SET_TO_NEEDED()), or the two can be combined
+ * into one call DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED().
+ * RESTORE_LC_NUMERIC() in all cases restores the locale to what it was before
+ * these were called */
+
+#define DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED                       \
+    void (*_restore_LC_NUMERIC_function)(pTHX) = NULL;
+
+#define STORE_LC_NUMERIC_SET_TO_NEEDED()                                     \
+    if (IN_SOME_LOCALE_FORM) {                                               \
+        if (! PL_numeric_local) {                                            \
+            SET_NUMERIC_LOCAL();                                             \
+            _restore_LC_NUMERIC_function = &Perl_set_numeric_standard;       \
+        }                                                                    \
+    }                                                                        \
+    else {                                                                   \
+        if (! PL_numeric_standard) {                                         \
+            SET_NUMERIC_STANDARD();                                          \
+            _restore_LC_NUMERIC_function = &Perl_set_numeric_local;          \
+        }                                                                    \
+    }
+
+#define DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED()                             \
+    DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED;                          \
+    STORE_LC_NUMERIC_SET_TO_NEEDED();
+
+#define RESTORE_LC_NUMERIC()                                                 \
+    if (_restore_LC_NUMERIC_function) {                                      \
+        _restore_LC_NUMERIC_function(aTHX);                                  \
+    }
+
+/* The next two macros set unconditionally.  These should be rarely used, and
+ * only after being sure that this is what is needed */
 #define SET_NUMERIC_STANDARD() \
        set_numeric_standard();
 
 #define SET_NUMERIC_LOCAL() \
        set_numeric_local();
 
+/* The rest of these LC_NUMERIC macros toggle to one or the other state, with
+ * the RESTORE_foo ones called to switch back, but only if need be */
 #define STORE_NUMERIC_LOCAL_SET_STANDARD() \
        bool was_local = PL_numeric_local; \
        if (was_local) SET_NUMERIC_STANDARD();
@@ -5261,8 +5303,14 @@ typedef struct am_table_short AMTS;
 #define IS_NUMERIC_RADIX(a, b)         (0)
 #define STORE_NUMERIC_LOCAL_SET_STANDARD()     /**/
 #define STORE_NUMERIC_STANDARD_SET_LOCAL()     /**/
+#define STORE_NUMERIC_STANDARD_FORCE_LOCAL()
 #define RESTORE_NUMERIC_LOCAL()                /**/
 #define RESTORE_NUMERIC_STANDARD()     /**/
+#define DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED
+#define STORE_LC_NUMERIC_SET_TO_NEEDED()
+#define DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED()
+#define RESTORE_LC_NUMERIC()
+
 #define Atof                           my_atof
 #define IN_LOCALE_RUNTIME              0
 #define IN_LOCALE_COMPILETIME          0