summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-06-03 13:56:25 -0400
committerJakob Kaivo <jkk@ung.org>2024-06-03 13:56:25 -0400
commita686d047d79bdfc37c096a4fa350c37e4ccf3cf5 (patch)
treeca631b9095454a239211b6f676bdd3e0cb102156
parentc575f269ed4a04f89d610b423cc43ce7bd6f008b (diff)
add LC_CTYPE epoch and use separate CT_ categories and CTM_ masks to support detecting change of LC_CTYPE between calls to wctype()/iswctype() and wctrans()/towctrans()
-rw-r--r--src/__main.c16
-rw-r--r--src/ctype/_ctype.h39
-rw-r--r--src/ctype/isblank.c2
-rw-r--r--src/ctype/iscntrl.c2
-rw-r--r--src/ctype/isgraph.c2
-rw-r--r--src/ctype/islower.c2
-rw-r--r--src/ctype/isprint.c2
-rw-r--r--src/ctype/ispunct.c2
-rw-r--r--src/ctype/isspace.c2
-rw-r--r--src/ctype/isupper.c2
-rw-r--r--src/ctype/isxdigit.c2
-rw-r--r--src/locale/__load_locale.c1
-rw-r--r--src/locale/_locale.h1
-rw-r--r--src/locale/setlocale.c11
-rw-r--r--src/string/strcpy.c5
-rw-r--r--src/wctype/_wctype.h2
-rw-r--r--src/wctype/iswctype.c4
-rw-r--r--src/wctype/towctrans.c4
-rw-r--r--src/wctype/wctrans.c5
-rw-r--r--src/wctype/wctrans_t.h2
-rw-r--r--src/wctype/wctype.c25
-rw-r--r--src/wctype/wctype_t.h2
22 files changed, 91 insertions, 44 deletions
diff --git a/src/__main.c b/src/__main.c
index aac8317c..16fe3808 100644
--- a/src/__main.c
+++ b/src/__main.c
@@ -22,23 +22,31 @@ void __init_libc(void)
}
init = 1;
- __stdin = stdin ? stdin : __stdio.FILES + 0;
+ __stdin = /* stdin ? stdin : */ __stdio.FILES + 0;
__stdin->fd = 0;
freopen(NULL, "r", __stdin);
- __stdout = stdout ? stdout : __stdio.FILES + 1;
+ __stdout = /* stdout ? stdout : */ __stdio.FILES + 1;
__stdout->fd = 1;
freopen(NULL, "w", __stdout);
- __stderr = stderr ? stderr : __stdio.FILES + 2;
+ __stderr = /* stderr ? stderr : */ __stdio.FILES + 2;
__stderr->fd = 2;
freopen(NULL, "w", __stderr);
setvbuf(__stderr, NULL, _IONBF, 0);
+
+ #if 0 && _POSIX_SOURCE
+ extern char **environ;
+ __stdlib.environ = environ;
+ #endif
}
void __main(int (*main)(int, char*[]), int argc, char **argv)
{
- environ = argv + argc + 1;
+ __stdlib.environ = argv + argc + 1;
+ #ifdef _POSIX_SOURCE
+ environ = __stdlib.environ;
+ #endif
__init_libc();
exit(main(argc, argv));
diff --git a/src/ctype/_ctype.h b/src/ctype/_ctype.h
index d167ef8b..cc823848 100644
--- a/src/ctype/_ctype.h
+++ b/src/ctype/_ctype.h
@@ -18,18 +18,33 @@
#endif
typedef enum {
- CT_ALPHA = (1 << 0),
- CT_CNTRL = (1 << 1),
- CT_DIGIT = (1 << 2),
- CT_GRAPH = (1 << 3),
- CT_LOWER = (1 << 4),
- CT_PRINT = (1 << 5),
- CT_PUNCT = (1 << 6),
- CT_SPACE = (1 << 7),
- CT_UPPER = (1 << 8),
- CT_XDIGIT = (1 << 9),
- CT_BLANK = (1 << 10),
-} ctype_t;
+ CT_ALPHA = 0,
+ CT_CNTRL = 1,
+ CT_DIGIT = 2,
+ CT_GRAPH = 3,
+ CT_LOWER = 4,
+ CT_PRINT = 5,
+ CT_PUNCT = 6,
+ CT_SPACE = 7,
+ CT_UPPER = 8,
+ CT_XDIGIT = 9,
+ CT_BLANK = 10,
+ CT_ALNUM = 11,
+} c_type;
+
+typedef enum {
+ CTM_ALPHA = (1 << CT_ALPHA),
+ CTM_CNTRL = (1 << CT_CNTRL),
+ CTM_DIGIT = (1 << CT_DIGIT),
+ CTM_GRAPH = (1 << CT_GRAPH),
+ CTM_LOWER = (1 << CT_LOWER),
+ CTM_PRINT = (1 << CT_PRINT),
+ CTM_PUNCT = (1 << CT_PUNCT),
+ CTM_SPACE = (1 << CT_SPACE),
+ CTM_UPPER = (1 << CT_UPPER),
+ CTM_XDIGIT = (1 << CT_XDIGIT),
+ CTM_BLANK = (1 << CT_BLANK),
+} c_type_mask;
/*
STDC(-1)
diff --git a/src/ctype/isblank.c b/src/ctype/isblank.c
index 3568241c..8649ea6e 100644
--- a/src/ctype/isblank.c
+++ b/src/ctype/isblank.c
@@ -9,7 +9,7 @@ int isblank(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, "unsigned char", EOF);
- return c == EOF ? 0 : map[c] & CT_BLANK;
+ return c == EOF ? 0 : map[c] & CTM_BLANK;
}
CHECK_1(int, 0, isblank, int)
diff --git a/src/ctype/iscntrl.c b/src/ctype/iscntrl.c
index a8107d05..d39a79ee 100644
--- a/src/ctype/iscntrl.c
+++ b/src/ctype/iscntrl.c
@@ -9,7 +9,7 @@ int iscntrl(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_CNTRL;
+ return c == EOF ? 0 : map[c] & CTM_CNTRL;
}
CHECK_1(int, 0, iscntrl, int)
diff --git a/src/ctype/isgraph.c b/src/ctype/isgraph.c
index be28a436..a45a2740 100644
--- a/src/ctype/isgraph.c
+++ b/src/ctype/isgraph.c
@@ -9,7 +9,7 @@ int isgraph(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_GRAPH;
+ return c == EOF ? 0 : map[c] & CTM_GRAPH;
}
CHECK_1(int, 0, isgraph, int)
diff --git a/src/ctype/islower.c b/src/ctype/islower.c
index 30aa16d1..6715e64a 100644
--- a/src/ctype/islower.c
+++ b/src/ctype/islower.c
@@ -9,7 +9,7 @@ int islower(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_LOWER;
+ return c == EOF ? 0 : map[c] & CTM_LOWER;
}
CHECK_1(int, 0, islower, int)
diff --git a/src/ctype/isprint.c b/src/ctype/isprint.c
index 5cbc726c..fcb88b8e 100644
--- a/src/ctype/isprint.c
+++ b/src/ctype/isprint.c
@@ -9,7 +9,7 @@ int isprint(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_PRINT;
+ return c == EOF ? 0 : map[c] & CTM_PRINT;
}
CHECK_1(int, 0, isprint, int)
diff --git a/src/ctype/ispunct.c b/src/ctype/ispunct.c
index 17bd3e76..90bd5683 100644
--- a/src/ctype/ispunct.c
+++ b/src/ctype/ispunct.c
@@ -9,7 +9,7 @@ int ispunct(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_PUNCT;
+ return c == EOF ? 0 : map[c] & CTM_PUNCT;
}
CHECK_1(int, 0, ispunct, int)
diff --git a/src/ctype/isspace.c b/src/ctype/isspace.c
index 654d50fb..20dcf6cc 100644
--- a/src/ctype/isspace.c
+++ b/src/ctype/isspace.c
@@ -9,7 +9,7 @@ int isspace(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_SPACE;
+ return c == EOF ? 0 : map[c] & CTM_SPACE;
}
CHECK_1(int, 0, isspace, int)
diff --git a/src/ctype/isupper.c b/src/ctype/isupper.c
index c21be203..95c2a787 100644
--- a/src/ctype/isupper.c
+++ b/src/ctype/isupper.c
@@ -9,7 +9,7 @@ int isupper(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_UPPER;
+ return c == EOF ? 0 : map[c] & CTM_UPPER;
}
CHECK_1(int, 0, isupper, int)
diff --git a/src/ctype/isxdigit.c b/src/ctype/isxdigit.c
index 8a227e2a..dfaa13ea 100644
--- a/src/ctype/isxdigit.c
+++ b/src/ctype/isxdigit.c
@@ -9,7 +9,7 @@ int isxdigit(int c)
SIGNAL_SAFE(0);
ASSERT_REPRESENTABLE(c, 0, UCHAR_MAX, unsigned char, EOF);
- return c == EOF ? 0 : map[c] & CT_XDIGIT;
+ return c == EOF ? 0 : map[c] & CTM_XDIGIT;
}
CHECK_1(int, 0, isxdigit, int)
diff --git a/src/locale/__load_locale.c b/src/locale/__load_locale.c
index 89fbd8a9..1831f798 100644
--- a/src/locale/__load_locale.c
+++ b/src/locale/__load_locale.c
@@ -43,6 +43,7 @@ char * __load_locale(struct __locale_t *loc, int mask, const char *name)
if (mask & LC_CTYPE_MASK) {
strcpy(loc->ctype, name);
+ loc->ctype_epoch++;
if (localefile == NULL) {
char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
diff --git a/src/locale/_locale.h b/src/locale/_locale.h
index 41441456..b7867731 100644
--- a/src/locale/_locale.h
+++ b/src/locale/_locale.h
@@ -36,6 +36,7 @@ struct __locale_t {
char all[UCHAR_MAX];
char ctype[UCHAR_MAX];
+ unsigned int ctype_epoch;
struct {
unsigned int ctattr[UCHAR_MAX + 1];
unsigned char ctoupper[UCHAR_MAX + 1];
diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c
index 86c44a5f..22779792 100644
--- a/src/locale/setlocale.c
+++ b/src/locale/setlocale.c
@@ -72,9 +72,14 @@ char * setlocale(int category, const char *locale)
name_to_return = __load_locale(l, mask, locale);
}
- __readonly(RO_UNLOCK, retname);
- strcpy(retname, name_to_return);
- __readonly(RO_LOCK, retname);
+ if (name_to_return != NULL) {
+ __readonly(RO_UNLOCK, retname);
+ strcpy(retname, name_to_return);
+ __readonly(RO_LOCK, retname);
+ } else {
+ retname = NULL;
+ }
+
return retname;
}
diff --git a/src/string/strcpy.c b/src/string/strcpy.c
index 3f5339bf..620fdd1e 100644
--- a/src/string/strcpy.c
+++ b/src/string/strcpy.c
@@ -10,12 +10,17 @@ char * strcpy(char * restrict s1, const char * restrict s2)
SIGNAL_SAFE(0);
ASSERT_NONNULL(s1);
ASSERT_NONNULL(s2);
+
+ DANGER(s2);
+
ASSERT_NOOVERLAP(s1, strlen(s2), s2, strlen(s2));
while ((*s1++ = *s2++) != '\0') {
continue;
}
+ DANGER(0);
+
/*
RETURN_ALWAYS(ARGUMENT(s1));
*/
diff --git a/src/wctype/_wctype.h b/src/wctype/_wctype.h
index 8dfbf3cd..24b4649e 100644
--- a/src/wctype/_wctype.h
+++ b/src/wctype/_wctype.h
@@ -1,5 +1,7 @@
#include "ctype/_ctype.h"
+#define CT_EPOCH_SHIFT (8)
+
/*
STDC(0)
*/
diff --git a/src/wctype/iswctype.c b/src/wctype/iswctype.c
index b1d1a3a1..ae952279 100644
--- a/src/wctype/iswctype.c
+++ b/src/wctype/iswctype.c
@@ -9,6 +9,10 @@ int iswctype(wint_t wc, wctype_t desc)
ASSERT_REPRESENTABLE(wc, WCHAR_MIN, WCHAR_MAX, "wchar_t", WEOF);
//ASSERT_REPRESENTABLE(desc, 1, __libc.wctype.nwctype, "wctype_t", 0);
+ if (__get_locale()->ctype_epoch != (desc >> CT_EPOCH_SHIFT)) {
+ UNDEFINED("LC_CTYPE has been changed since the call to wctype()");
+ }
+
/* TODO: actual work */
(void)wc; (void)desc;
diff --git a/src/wctype/towctrans.c b/src/wctype/towctrans.c
index 8e6d266c..4dccfa64 100644
--- a/src/wctype/towctrans.c
+++ b/src/wctype/towctrans.c
@@ -8,6 +8,10 @@ wint_t towctrans(wint_t wc, wctrans_t desc)
ASSERT_REPRESENTABLE(wc, WCHAR_MIN, WCHAR_MAX, "wchar_t", WEOF);
//ASSERT_REPRESENTABLE(desc, 1, __libc.wctype.nwctrans, "wctrans_t", 0);
+ if (__get_locale()->ctype_epoch != (desc >> CT_EPOCH_SHIFT)) {
+ UNDEFINED("LC_CTYPE has changed since the call to wctrans()");
+ }
+
/* TODO: actual work */
(void)wc; (void)desc;
diff --git a/src/wctype/wctrans.c b/src/wctype/wctrans.c
index aa47d945..7f724d27 100644
--- a/src/wctype/wctrans.c
+++ b/src/wctype/wctrans.c
@@ -7,11 +7,12 @@ wctrans_t wctrans(const char * property)
{
SIGNAL_SAFE(0);
ASSERT_NONNULL(property);
+ wctrans_t epoch = __get_locale()->ctype_epoch << CT_EPOCH_SHIFT;
if (!strcmp(property, "tolower")) {
- return CT_LOWER;
+ return epoch | CT_LOWER;
} else if (!strcmp(property, "toupper")) {
- return CT_UPPER;
+ return epoch | CT_UPPER;
}
return 0;
diff --git a/src/wctype/wctrans_t.h b/src/wctype/wctrans_t.h
index f11d5863..0ebf8d24 100644
--- a/src/wctype/wctrans_t.h
+++ b/src/wctype/wctrans_t.h
@@ -1,5 +1,5 @@
#include <wctype.h>
-typedef int wctrans_t;
+typedef unsigned int wctrans_t;
/*
STDC(199409)
diff --git a/src/wctype/wctype.c b/src/wctype/wctype.c
index 2dd4599f..cf82c4ed 100644
--- a/src/wctype/wctype.c
+++ b/src/wctype/wctype.c
@@ -7,31 +7,32 @@ wctype_t wctype(const char * property)
{
SIGNAL_SAFE(0);
ASSERT_NONNULL(property);
+ wctype_t epoch = ((__get_locale()->ctype_epoch) << CT_EPOCH_SHIFT);
if (!strcmp(property, "alnum")) {
- return CT_ALPHA | CT_DIGIT;
+ return epoch | CT_ALNUM;
} else if (!strcmp(property, "alpha")) {
- return CT_ALPHA;
+ return epoch | CT_ALPHA;
} else if (!strcmp(property, "blank")) {
- return CT_BLANK;
+ return epoch | CT_BLANK;
} else if (!strcmp(property, "cntrl")) {
- return CT_CNTRL;
+ return epoch | CT_CNTRL;
} else if (!strcmp(property, "digit")) {
- return CT_DIGIT;
+ return epoch | CT_DIGIT;
} else if (!strcmp(property, "graph")) {
- return CT_GRAPH;
+ return epoch | CT_GRAPH;
} else if (!strcmp(property, "lower")) {
- return CT_LOWER;
+ return epoch | CT_LOWER;
} else if (!strcmp(property, "print")) {
- return CT_PRINT;
+ return epoch | CT_PRINT;
} else if (!strcmp(property, "punct")) {
- return CT_PUNCT;
+ return epoch | CT_PUNCT;
} else if (!strcmp(property, "space")) {
- return CT_SPACE;
+ return epoch | CT_SPACE;
} else if (!strcmp(property, "upper")) {
- return CT_UPPER;
+ return epoch | CT_UPPER;
} else if (!strcmp(property, "xdigit")) {
- return CT_XDIGIT;
+ return epoch | CT_XDIGIT;
}
return 0;
diff --git a/src/wctype/wctype_t.h b/src/wctype/wctype_t.h
index f2dbd801..b1dcd910 100644
--- a/src/wctype/wctype_t.h
+++ b/src/wctype/wctype_t.h
@@ -1,5 +1,5 @@
#include <wctype.h>
-typedef int wctype_t;
+typedef unsigned int wctype_t;
/*
STDC(199409)