harec

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

util.c (3303B)


      1 #include <sys/stat.h>
      2 #include <stdbool.h>
      3 #include <stdlib.h>
      4 #include <stdint.h>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <unistd.h>
      8 #include "util.h"
      9 // Remove safety macros:
     10 #undef malloc
     11 #undef calloc
     12 #undef realloc
     13 #undef strdup
     14 
     15 const char **sources;
     16 
     17 uint32_t
     18 fnv1a(uint32_t hash, unsigned char c)
     19 {
     20 	return (hash ^ c) * 16777619;
     21 }
     22 
     23 uint32_t
     24 fnv1a_u32(uint32_t hash, uint32_t u32)
     25 {
     26 	hash = fnv1a(hash, (u32) & 0xFF);
     27 	hash = fnv1a(hash, (u32 >> 8) & 0xFF);
     28 	hash = fnv1a(hash, (u32 >> 16) & 0xFF);
     29 	hash = fnv1a(hash, (u32 >> 24) & 0xFF);
     30 	return hash;
     31 }
     32 
     33 uint32_t
     34 fnv1a_u64(uint32_t hash, uint64_t u64)
     35 {
     36 	hash = fnv1a(hash, (u64) & 0xFF);
     37 	hash = fnv1a(hash, (u64 >> 8) & 0xFF);
     38 	hash = fnv1a(hash, (u64 >> 16) & 0xFF);
     39 	hash = fnv1a(hash, (u64 >> 24) & 0xFF);
     40 	hash = fnv1a(hash, (u64 >> 32) & 0xFF);
     41 	hash = fnv1a(hash, (u64 >> 40) & 0xFF);
     42 	hash = fnv1a(hash, (u64 >> 48) & 0xFF);
     43 	hash = fnv1a(hash, (u64 >> 54) & 0xFF);
     44 	return hash;
     45 }
     46 
     47 uint32_t
     48 fnv1a_size(uint32_t hash, size_t sz)
     49 {
     50 	for (size_t i = 0; i < sizeof(sz); i++) {
     51 		hash = fnv1a(hash, sz & 0xFF);
     52 		sz >>= 8;
     53 	}
     54 	return hash;
     55 }
     56 
     57 uint32_t
     58 fnv1a_s(uint32_t hash, const char *str)
     59 {
     60 	unsigned char c;
     61 	while ((c = *str++)) {
     62 		hash = fnv1a(hash, c);
     63 	}
     64 	return hash;
     65 }
     66 
     67 void *
     68 xcalloc(size_t n, size_t s)
     69 {
     70 	void *p = calloc(n, s);
     71 	if (!p && s) {
     72 		abort();
     73 	}
     74 	return p;
     75 }
     76 
     77 void *
     78 xrealloc(void *p, size_t s)
     79 {
     80 	p = realloc(p, s);
     81 	if (!p && s) {
     82 		abort();
     83 	}
     84 	return p;
     85 }
     86 
     87 char *
     88 xstrdup(const char *s)
     89 {
     90 	char *ret = strdup(s);
     91 	if (!ret) {
     92 		abort();
     93 	}
     94 	return ret;
     95 }
     96 
     97 char *
     98 gen_name(int *id, const char *fmt)
     99 {
    100 	int n = snprintf(NULL, 0, fmt, *id);
    101 	char *str = xcalloc(1, n + 1);
    102 	snprintf(str, n + 1, fmt, *id);
    103 	++*id;
    104 	return str;
    105 }
    106 
    107 char *
    108 getpath(const struct pathspec *paths, size_t npaths) {
    109 	for (size_t i = 0; i < npaths; i++) {
    110 		const char *var = "";
    111 		if (paths[i].var) {
    112 			var = getenv(paths[i].var);
    113 		}
    114 		if (var) {
    115 			char *out = calloc(1,
    116 				strlen(var) + strlen(paths[i].path) + 1);
    117 			strcat(strcat(out, var), paths[i].path);
    118 			return out;
    119 		}
    120 	}
    121 	return NULL;
    122 }
    123 
    124 int
    125 errline(const char* path, int lineno, int colno)
    126 {
    127 	char* real = realpath(path, NULL);
    128 	struct stat filestat;
    129 	if (stat(real, &filestat) != 0 || !S_ISREG(filestat.st_mode)) {
    130 		free(real);
    131 		return -1;
    132 	}
    133 	free(real);
    134 
    135 	FILE* src = fopen(path, "r");
    136 	if (!src) {
    137 		return -1;
    138 	}
    139 	char* line = NULL;
    140 	size_t len = 0;
    141 	int n = 0;
    142 	while (n < lineno) {
    143 		if (getline(&line, &len, src) == -1) {
    144 			fclose(src);
    145 			if (line) {
    146 				free(line);
    147 			}
    148 			return -1;
    149 		}
    150 		n += 1;
    151 	}
    152 	if (line) {
    153 		bool color = true;
    154 		const char* no_color = getenv("NO_COLOR");
    155 		const char* harec_color = getenv("HAREC_COLOR");
    156 		if (!isatty(fileno(stderr))) {
    157 			color = false;
    158 		}
    159 		if (no_color != NULL) {
    160 			if (0 < strlen(no_color)) {
    161 				color = false;
    162 			}
    163 		}
    164 		if (harec_color != NULL) {
    165 			if (strcmp(harec_color, "0") == 0) {
    166 				color = false;
    167 			} else {
    168 				color = true;
    169 			}
    170 		}
    171 		fprintf(stderr, "\n%d |\t%s", lineno, line);
    172 		for (int i = lineno; 1 <= i; i /= 10) {
    173 			fputc(' ', stderr);
    174 		}
    175 		fputs(" |\t", stderr);
    176 		for (int i = 1; i < colno; i++) {
    177 			fputc(' ', stderr);
    178 		}
    179 		if (color) {
    180 			fputs("\x1b[31m^\x1b[0m\n\n", stderr);
    181 		} else {
    182 			fputs("^\n\n", stderr);
    183 		}
    184 		free(line);
    185 	}
    186 	fclose(src);
    187 	return 0;
    188 }