1 #include "all.h" 2 3 void* 4 erealloc(void *a, int n) 5 { 6 a = realloc(a, n); 7 if(a==nil) 8 sysfatal("realloc: %r"); 9 return a; 10 } 11 12 char* 13 estrdup(char *s) 14 { 15 s = strdup(s); 16 if(s == nil) 17 sysfatal("strdup: %r"); 18 return s; 19 } 20 21 void* 22 emalloc(int n) 23 { 24 void *a; 25 26 a = mallocz(n, 1); 27 if(a == nil) 28 sysfatal("malloc: %r"); 29 return a; 30 } 31 32 /* 33 * Custom allocators to avoid malloc overheads on small objects. 34 * We never free these. (See below.) 35 */ 36 typedef struct Stringtab Stringtab; 37 struct Stringtab { 38 Stringtab *link; 39 char *str; 40 }; 41 static Stringtab* 42 taballoc(void) 43 { 44 static Stringtab *t; 45 static uint nt; 46 47 if(nt == 0){ 48 t = malloc(64*sizeof(Stringtab)); 49 if(t == 0) 50 sysfatal("out of memory"); 51 nt = 64; 52 } 53 nt--; 54 return t++; 55 } 56 57 static char* 58 xstrdup(char *s) 59 { 60 char *r; 61 int len; 62 static char *t; 63 static int nt; 64 65 len = strlen(s)+1; 66 if(len >= 8192) 67 sysfatal("strdup big string"); 68 69 if(nt < len){ 70 t = malloc(8192); 71 if(t == 0) 72 sysfatal("out of memory"); 73 nt = 8192; 74 } 75 r = t; 76 t += len; 77 nt -= len; 78 strcpy(r, s); 79 return r; 80 } 81 82 /* 83 * Return a uniquely allocated copy of a string. 84 * Don't free these -- they stay in the table for the 85 * next caller who wants that particular string. 86 * String comparison can be done with pointer comparison 87 * if you know both strings are atoms. 88 */ 89 static Stringtab *stab[1024]; 90 91 static uint 92 hash(char *s) 93 { 94 uint h; 95 uchar *p; 96 97 h = 0; 98 for(p=(uchar*)s; *p; p++) 99 h = h*37 + *p; 100 return h; 101 } 102 103 char* 104 atom(char *str) 105 { 106 uint h; 107 Stringtab *tab; 108 109 h = hash(str) % nelem(stab); 110 for(tab=stab[h]; tab; tab=tab->link) 111 if(strcmp(str, tab->str) == 0) 112 return tab->str; 113 114 tab = taballoc(); 115 tab->str = xstrdup(str); 116 tab->link = stab[h]; 117 stab[h] = tab; 118 return tab->str; 119 } 120 121 char* 122 unroot(char *path, char *root) 123 { 124 int len; 125 char *s; 126 127 len = strlen(root); 128 while(len >= 1 && root[len-1]=='/') 129 len--; 130 if(strncmp(path, root, len)==0 && (path[len]=='/' || path[len]=='\0')){ 131 s = path+len; 132 while(*s == '/') 133 s++; 134 return s; 135 } 136 return path; 137 } 138