harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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 }