From 509283957c894d958d75cccfcae6776614c60a09 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Thu, 11 May 2023 18:56:10 -0600 Subject: [PATCH] perl.h: Add DISABLE_LC_NUMERIC_CHANGES macro This is for code that needs to keep other code from changing LC_NUMERIC out from under it, but avoids the knowledge of PL_numeric_standard, which is used when perl controls the locale handling. This is designed for 'version' (vutil.c) to use, because it has to operate seamlessly in the mode where perl controls the handling, and when it doesn't, even if it doesn't know it doesn't. --- perl.h | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/perl.h b/perl.h index 53fb5189565d..1f08525e4e18 100644 --- a/perl.h +++ b/perl.h @@ -7795,18 +7795,22 @@ cannot have changed since the precalculation. } \ } STMT_END -/* Lock/unlock to the C locale until unlock is called. This needs to be - * recursively callable. [perl #128207] */ -# define LOCK_LC_NUMERIC_STANDARD() \ +/* Lock/unlock changes to LC_NUMERIC. This needs to be recursively callable. + * The highest level caller is responsible for making sure that LC_NUMERIC is + * set to a locale with a dot radix character. These deliberately don't check + * for the internal state being so, as they can be called from code that is not + * party to the internal conventions, namely 'version' (vutil.c). + * PL_numeric_standard changing doesn't affect anything about what locale is in + * effect, etc. [perl #128207] */ +# define DISABLE_LC_NUMERIC_CHANGES() \ STMT_START { \ DEBUG_Lv(PerlIO_printf(Perl_debug_log, \ "%s: %d: lc_numeric_standard now locked to depth %d\n", \ __FILE__, __LINE__, PL_numeric_standard)); \ - __ASSERT_(PL_numeric_standard) \ PL_numeric_standard++; \ } STMT_END -# define UNLOCK_LC_NUMERIC_STANDARD() \ +# define REENABLE_LC_NUMERIC_CHANGES() \ STMT_START { \ if (PL_numeric_standard > 1) { \ PL_numeric_standard--; \ @@ -7824,6 +7828,17 @@ cannot have changed since the precalculation. PL_numeric_standard););\ } STMT_END +/* Essentially synonyms for the above. The LOCK asserts at the top level that + * we are in a locale equivalent to C. By including the top level, this can be + * recursively called from chains which include DISABLE_LC_NUMERIC_CHANGES(). + * */ +# define LOCK_LC_NUMERIC_STANDARD() \ + STMT_START { \ + assert(PL_numeric_standard > 0 || PL_numeric_standard); \ + DISABLE_LC_NUMERIC_CHANGES(); \ + } STMT_END +# define UNLOCK_LC_NUMERIC_STANDARD() REENABLE_LC_NUMERIC_CHANGES() + # define WITH_LC_NUMERIC_SET_TO_NEEDED_IN(in_lc_numeric, block) \ STMT_START { \ DECLARATION_FOR_LC_NUMERIC_MANIPULATION; \ @@ -7848,6 +7863,8 @@ cannot have changed since the precalculation. # define RESTORE_LC_NUMERIC() # define LOCK_LC_NUMERIC_STANDARD() # define UNLOCK_LC_NUMERIC_STANDARD() +# define DISABLE_LC_NUMERIC_CHANGES() +# define REENABLE_LC_NUMERIC_CHANGES() # define WITH_LC_NUMERIC_SET_TO_NEEDED_IN(in_lc_numeric, block) \ STMT_START { block; } STMT_END # define WITH_LC_NUMERIC_SET_TO_NEEDED(block) \