summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-06-03 14:12:36 -0400
committerJakob Kaivo <jkk@ung.org>2024-06-03 14:12:36 -0400
commitb604cd380c1a974a736525b6993e9c8a5a6cf95f (patch)
tree77fed5a6d81012ec4f5d2a190707b1f1dbd19417
parenta686d047d79bdfc37c096a4fa350c37e4ccf3cf5 (diff)
mark return value as read-only, put all strings in a single page with the struct lconv itself
-rw-r--r--src/locale/localeconv.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/locale/localeconv.c b/src/locale/localeconv.c
index 9dc79302..146bd484 100644
--- a/src/locale/localeconv.c
+++ b/src/locale/localeconv.c
@@ -1,18 +1,48 @@
#include <locale.h>
+#include <string.h>
#include "_locale.h"
#include "_safety.h"
+#include "_readonly.h"
/** return locale-specific information **/
+#define ROCOPY(__dst, __src, __field, __offset) do { \
+ (__dst)->__field = (char*)(__dst) + __offset; \
+ strcpy((__dst)->__field, (__src)->__field); \
+ __offset += strlen((__dst)->__field) + 1; \
+ } while (0)
+
struct lconv * localeconv(void)
{
SIGNAL_SAFE(0);
+ static struct lconv *lc = NULL;
+ struct lconv *current = &(__get_locale()->lconv);
+
+ if (lc == NULL) {
+ lc = __readonly(RO_ALLOC, "localeconv");
+ }
/*
RETURN_SUCCESS(a pointer to a filled-in STRUCTDEF(lconv) for the current locale);
*/
- /* TODO: mark return value read-only */
- return &(__get_locale()->lconv);
+
+ __readonly(RO_UNLOCK, lc);
+ /* TODO: This assumes all strings fit in a single page */
+ (*lc) = (*current);
+ size_t offset = sizeof(*lc);
+ ROCOPY(lc, current, decimal_point, offset);
+ ROCOPY(lc, current, thousands_sep, offset);
+ ROCOPY(lc, current, grouping, offset);
+ ROCOPY(lc, current, int_curr_symbol, offset);
+ ROCOPY(lc, current, currency_symbol, offset);
+ ROCOPY(lc, current, mon_decimal_point, offset);
+ ROCOPY(lc, current, mon_thousands_sep, offset);
+ ROCOPY(lc, current, mon_grouping, offset);
+ ROCOPY(lc, current, positive_sign, offset);
+ ROCOPY(lc, current, negative_sign, offset);
+ __readonly(RO_LOCK, lc);
+
+ return lc;
}
CHECK_0(struct lconv *, NULL, localeconv)