identifier.c (2702B)
1 #include <assert.h> 2 #include <errno.h> 3 #include <limits.h> 4 #include <stdarg.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include "identifier.h" 9 #include "util.h" 10 11 uint32_t 12 identifier_hash(uint32_t init, const struct identifier *ident) 13 { 14 init = fnv1a_s(init, ident->name); 15 init = fnv1a(init, 0); 16 if (ident->ns) { 17 init = identifier_hash(init, ident->ns); 18 } 19 return init; 20 } 21 22 static int 23 _asprintf(char **strp, const char *fmt, ...) 24 { 25 va_list ap; 26 va_start(ap, fmt); 27 int n = vsnprintf(NULL, 0, fmt, ap); 28 va_end(ap); 29 30 *strp = xcalloc(n + 1, 1); 31 32 va_start(ap, fmt); 33 n = vsnprintf(*strp, n + 1, fmt, ap); 34 va_end(ap); 35 return n; 36 } 37 38 char * 39 identifier_unparse(const struct identifier *ident) 40 { 41 if (ident->ns) { 42 char *ns = identifier_unparse(ident->ns); 43 if (!ns) { 44 return NULL; 45 } 46 char *str = NULL; 47 _asprintf(&str, "%s::%s", ns, ident->name); 48 free(ns); 49 return str; 50 } 51 return xstrdup(ident->name); 52 } 53 54 int 55 identifier_unparse_static(const struct identifier *ident, char *buf, size_t len) 56 { 57 assert(len < INT_MAX); 58 if (ident->ns) { 59 int prefix = identifier_unparse_static(ident->ns, buf, len); 60 int n = snprintf(&buf[prefix], len - prefix, 61 "::%s", ident->name); 62 if (n >= (int)len) { 63 buf[len - 1] = '\0'; 64 } 65 return prefix + n; 66 } 67 int n = snprintf(buf, len, "%s", ident->name); 68 if (n >= (int)len) { 69 buf[len - 1] = '\0'; 70 } 71 return n; 72 } 73 74 const char * 75 ident_to_path(const struct identifier *ident) 76 { 77 static char path[PATH_MAX+1]; 78 memset(path, 0, sizeof(path)); 79 while (ident) { 80 size_t len = strlen(ident->name); 81 size_t oldlen = strlen(path); 82 if (oldlen != 0) { 83 len++; 84 } 85 memmove(path + len, path, oldlen); 86 memcpy(path, ident->name, strlen(ident->name)); 87 if (oldlen != 0) { 88 path[strlen(ident->name)] = '/'; 89 } 90 ident = ident->ns; 91 } 92 return path; 93 } 94 95 char * 96 ident_to_sym(const struct identifier *ident) 97 { 98 if (ident->ns) { 99 char *ns = ident_to_sym(ident->ns); 100 if (!ns) { 101 return NULL; 102 } 103 int n = snprintf(NULL, 0, "%s.%s", ns, ident->name); 104 char *str = xcalloc(1, n + 1); 105 snprintf(str, n + 1, "%s.%s", ns, ident->name); 106 free(ns); 107 return str; 108 } 109 return xstrdup(ident->name); 110 } 111 112 void 113 identifier_dup(struct identifier *new, const struct identifier *ident) 114 { 115 assert(ident && new); 116 new->name = xstrdup(ident->name); 117 if (ident->ns) { 118 new->ns = xcalloc(1, sizeof(struct identifier)); 119 identifier_dup(new->ns, ident->ns); 120 } else { 121 new->ns = NULL; 122 } 123 } 124 125 bool 126 identifier_eq(const struct identifier *a, const struct identifier *b) 127 { 128 if (!a && !b) { 129 return true; 130 } else if ((!a && b) || (a && !b)) { 131 return false; 132 } 133 if (strcmp(a->name, b->name) != 0) { 134 return false; 135 } 136 return identifier_eq(a->ns, b->ns); 137 }