diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-02-04 15:23:59 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-02-04 15:23:59 -0500 |
| commit | 98f0c51119f9d42d733f44cb516b1c2bcd9061af (patch) | |
| tree | 39ab4fa635f858b76b9a8bbf84701c2788d5f498 /util.c | |
Initial commit
Diffstat (limited to 'util.c')
| -rw-r--r-- | util.c | 84 |
1 files changed, 84 insertions, 0 deletions
@@ -0,0 +1,84 @@ +#include <ctype.h> +#include <gc.h> +#include <gc/cord.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + +public char *heap_strn(const char *str, size_t len) +{ + if (!str) return NULL; + if (len == 0) return ""; + char *heaped = GC_MALLOC_ATOMIC(len + 1); + memcpy(heaped, str, len); + heaped[len] = '\0'; + return heaped; +} + +public char *heap_str(const char *str) +{ + if (!str) return NULL; + return heap_strn(str, strlen(str)); +} + +public char *heap_strf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + char *tmp = NULL; + int len = vasprintf(&tmp, fmt, args); + if (len < 0) return NULL; + va_end(args); + char *ret = heap_strn(tmp, (size_t)len); + free(tmp); + return ret; +} + +// Name mangling algorithm to produce valid identifiers: +// Escape individual chars as "_x%02X" +// Things being escaped: +// - Leading digit +// - Non alphanumeric/non-underscore characters +// - "_" when followed by "x" and two uppercase hex digits +public char *mangle(const char *name) +{ + size_t len = 0; + for (const char *p = name; *p; p++) { + if ((!isalnum(*p) && *p != '_') // Non-identifier character + || (p == name && isdigit(*p)) // Leading digit + || (p[0] == '_' && p[1] == 'x' && strspn(p+2, "ABCDEF0123456789") >= 2)) { // Looks like hex escape + len += strlen("_x00"); // Hex escape + } else { + len += 1; + } + } + char *mangled = GC_MALLOC_ATOMIC(len + 1); + char *dest = mangled; + for (const char *src = name; *src; src++) { + if ((!isalnum(*src) && *src != '_') // Non-identifier character + || (src == name && isdigit(*src)) // Leading digit + || (src[0] == '_' && src[1] == 'x' && strspn(src+2, "ABCDEF0123456789") >= 2)) { // Looks like hex escape + dest += sprintf(dest, "_x%02X", *src); // Hex escape + } else { + *(dest++) = *src; + } + } + mangled[len] = '\0'; + return mangled; +} + +CORD CORD_asprintf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + CORD c = NULL; + CORD_vsprintf(&c, fmt, args); + va_end(args); + return c; +} + + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
