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 }