From 302e24671942051d70707586cf8c605a5815edac Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 15 Dec 2025 22:39:52 +0100 Subject: create distinct interned string type Interned strings are used pervasively, so it's a good idea to add a layer of type safety to differentiate them from general cstrs and avoid potential bugs from comparing non-interned and interned strings. Not that that's happened so far that I can remember, but it could. I'm 90% sure it's legal to alias `struct {char c;}` pointers with `char` pointers. This specific typedef gives type safety but with a simple one-way `internstr -> const char *` typecast (with `&istr->c`). Converting the other way around is more intentional: a straight up cast `(internstr)cstr` which sticks out as unchecked and probably wrong, or calling the intern(cstr) function, which is the right way. --- common.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'common.h') diff --git a/common.h b/common.h index 061c379..3d2166b 100644 --- a/common.h +++ b/common.h @@ -179,7 +179,8 @@ void free(void *); #define xrealloc(p,n) xrealloc(p, n, __func__) /* string interning */ -const char *intern(const char *); +typedef const struct internstr {char c;} *internstr; +internstr intern(const char *); /* growable buffer that stores its capacity in the allocated memory */ #define xbnew_(n) (void *)(1 + (size_t *)xcalloc(sizeof(size_t) + (n))) @@ -404,8 +405,8 @@ struct memfile *getfile(int id); void addfileline(int id, uint off); void setfileline(int id, uint off, int line, const char *file); const char *getfilepos(int *line, int *col, int id, uint off); -bool isoncefile(int id, const char **guard); -void markfileonce(int id, const char *guard); +bool isoncefile(int id, internstr *guard); +void markfileonce(int id, internstr guard); void markfileseen(int id); bool isfileseen(int id); void closefile(int id); -- cgit v1.2.3