]> git.xonotic.org Git - xonotic/gmqcc.git/blob - util.c
assembler can parse internal functions. Wrote all internal functions (that are not...
[xonotic/gmqcc.git] / util.c
1 /*
2  * Copyright (C) 2012
3  *     Dale Weiler
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #include <stdarg.h>
24 #include <errno.h>
25 #include "gmqcc.h"
26
27 unsigned long long mem_ab = 0;
28 unsigned long long mem_db = 0;
29 unsigned long long mem_at = 0;
30 unsigned long long mem_dt = 0;
31
32 struct memblock_t {
33     const char  *file;
34     unsigned int line;
35     unsigned int byte;
36 }; 
37
38 void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
39     struct memblock_t *info = malloc(sizeof(struct memblock_t) + byte);
40     void              *data =(void*)((uintptr_t)info+sizeof(struct memblock_t));
41     if (!data) return NULL;
42     info->line = line;
43     info->byte = byte;
44     info->file = file;
45
46     util_debug("MEM", "allocation: % 8u (bytes) address 0x%08X @ %s:%u\n", byte, data, file, line);
47     mem_at++;
48     mem_ab += info->byte;
49
50     return data;
51 }
52
53 void util_memory_d(void *ptrn, unsigned int line, const char *file) {
54     if (!ptrn) return;
55     void              *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
56     struct memblock_t *info = (struct memblock_t*)data;
57
58     util_debug("MEM", "released:   % 8u (bytes) address 0x%08X @ %s:%u\n", info->byte, data, file, line);
59     mem_db += info->byte;
60     mem_dt++;
61
62     free(data);
63 }
64
65 void util_meminfo() {
66     if (!opts_memchk)
67         return;
68
69     util_debug("MEM", "Memory information:\n\
70         Total allocations:   %llu\n\
71         Total deallocations: %llu\n\
72         Total allocated:     %llu (bytes)\n\
73         Total deallocated:   %llu (bytes)\n\
74         Leaks found:         lost %llu (bytes) in %d allocations\n",
75             mem_at,   mem_dt,
76             mem_ab,   mem_db,
77            (mem_ab -  mem_db),
78            (mem_at -  mem_dt)
79     );
80 }
81
82 /*
83  * Some string utility functions, because strdup uses malloc, and we want
84  * to track all memory (without replacing malloc).
85  */
86 char *util_strdup(const char *s) {
87     size_t  len = 0;
88     char   *ptr = NULL;
89
90     if (!s)
91         return NULL;
92
93     if ((len = strlen(s)) && (ptr = mem_a(len+1))) {
94         memcpy(ptr, s, len);
95         ptr[len] = '\0';
96     }
97     return ptr;
98 }
99
100 /*
101  * Remove quotes from a string, escapes from \ in string
102  * as well.  This function shouldn't be used to create a
103  * char array that is later freed (it uses pointer arith)
104  */
105 char *util_strrq(char *s) {
106     char *dst = s;
107     char *src = s;
108     char  chr;
109     while ((chr = *src++) != '\0') {
110         if (chr == '\\') {
111             *dst++ = chr;
112             if ((chr = *src++) == '\0')
113                 break;
114             *dst++ = chr;
115         } else if (chr != '"')
116             *dst++ = chr;
117     }
118     *dst = '\0';
119     return dst;
120 }
121
122 /*
123  * Chops a substring from an existing string by creating a
124  * copy of it and null terminating it at the required position.
125  */
126 char *util_strchp(const char *s, const char *e) {
127     if (!s || !e)
128         return NULL;
129         
130     size_t m  = 0;
131     char  *c  = util_strdup(s);
132     while (s != e)
133         s++,c++,m++;
134          
135     *c = '\0';
136     return c-m;
137 }
138
139 /*
140  * Remove newline from a string (if it exists).  This is
141  * done pointer wise instead of strlen(), and an array
142  * access.
143  */
144 char *util_strrnl(char *src) {
145     if (!src) return NULL;
146     char   *cpy = src;
147     while (*cpy && *cpy != '\n')
148         cpy++;
149
150     *cpy = '\0';
151     return src;
152 }
153
154 /*
155  * Removes any whitespace prefixed on a string by moving
156  * skipping past it, and stroing the skip distance, so
157  * the string can later be freed (if it was allocated)
158  */
159 char *util_strsws(const char *skip) {
160     size_t size = 0;
161     if (!skip)
162         return NULL;
163     
164     while (*skip == ' ' || *skip == '\t')
165         skip++,size++;
166     return util_strdup(skip-size);
167 }
168
169 /*
170  * Returns true if string is all uppercase, otherwise
171  * it returns false.
172  */
173 bool util_strupper(const char *str) {
174     while (*str) {
175         if(!isupper(*str))
176             return false;
177         str++;
178     }
179     return true;
180 }
181
182 void util_debug(const char *area, const char *ms, ...) {
183     if (!opts_debug)
184         return;
185
186     va_list  va;
187     va_start(va, ms);
188     fprintf (stdout, "DEBUG: ");
189     fputc   ('[',  stdout);
190     fprintf(stdout, "%s", area);
191     fputs   ("] ", stdout);
192     vfprintf(stdout, ms, va);
193     va_end  (va);
194 }
195
196 /*
197  * Endianess swapping, all data must be stored little-endian.  This
198  * reorders by stride and length, much nicer than other functions for
199  * certian-sized types like short or int.
200  */
201 void util_endianswap(void *m, int s, int l) {
202     size_t w = 0;
203     size_t i = 0;
204
205     /* ignore if we're already LE */
206     if(*((char *)&s))
207         return;
208
209     for(; w < l; w++) {
210         for(;  i < s << 1; i++) {
211             unsigned char *p = (unsigned char *)m+w*s;
212             unsigned char  t = p[i];
213             p[i]             = p[s-i-1];
214             p[s-i-1]         = t;
215         }
216     }
217 }
218
219 /*
220  * This is an implementation of CRC32 & CRC16. The polynomials have been
221  * offline computed for faster generation at the cost of larger code size.
222  *
223  * CRC32 Polynomial: 0xEDB88320
224  * CRC16 Polynomial: 0x00001021
225  */
226 static const uint32_t util_crc32_table[] = {
227     0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
228     0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
229     0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
230     0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
231     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
232     0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
233     0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
234     0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
235     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
236     0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
237     0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
238     0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
239     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
240     0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
241     0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
242     0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
243     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
244     0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
245     0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
246     0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
247     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
248     0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
249     0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
250     0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
251     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
252     0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
253     0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
254     0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
255     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
256     0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
257     0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
258     0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
259     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
260     0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
261     0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
262     0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
263     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
264     0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
265     0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
266     0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
267     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
268     0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
269     0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
270 };
271 static const uint16_t util_crc16_table[] = {
272     0x0000,     0x1021,     0x2042,     0x3063,     0x4084,     0x50A5,
273     0x60C6,     0x70E7,     0x8108,     0x9129,     0xA14A,     0xB16B,
274     0xC18C,     0xD1AD,     0xE1CE,     0xF1EF,     0x1231,     0x0210,
275     0x3273,     0x2252,     0x52B5,     0x4294,     0x72F7,     0x62D6,
276     0x9339,     0x8318,     0xB37B,     0xA35A,     0xD3BD,     0xC39C,
277     0xF3FF,     0xE3DE,     0x2462,     0x3443,     0x0420,     0x1401,
278     0x64E6,     0x74C7,     0x44A4,     0x5485,     0xA56A,     0xB54B,
279     0x8528,     0x9509,     0xE5EE,     0xF5CF,     0xC5AC,     0xD58D,
280     0x3653,     0x2672,     0x1611,     0x0630,     0x76D7,     0x66F6,
281     0x5695,     0x46B4,     0xB75B,     0xA77A,     0x9719,     0x8738,
282     0xF7DF,     0xE7FE,     0xD79D,     0xC7BC,     0x48C4,     0x58E5,
283     0x6886,     0x78A7,     0x0840,     0x1861,     0x2802,     0x3823,
284     0xC9CC,     0xD9ED,     0xE98E,     0xF9AF,     0x8948,     0x9969,
285     0xA90A,     0xB92B,     0x5AF5,     0x4AD4,     0x7AB7,     0x6A96,
286     0x1A71,     0x0A50,     0x3A33,     0x2A12,     0xDBFD,     0xCBDC,
287     0xFBBF,     0xEB9E,     0x9B79,     0x8B58,     0xBB3B,     0xAB1A,
288     0x6CA6,     0x7C87,     0x4CE4,     0x5CC5,     0x2C22,     0x3C03,
289     0x0C60,     0x1C41,     0xEDAE,     0xFD8F,     0xCDEC,     0xDDCD,
290     0xAD2A,     0xBD0B,     0x8D68,     0x9D49,     0x7E97,     0x6EB6,
291     0x5ED5,     0x4EF4,     0x3E13,     0x2E32,     0x1E51,     0x0E70,
292     0xFF9F,     0xEFBE,     0xDFDD,     0xCFFC,     0xBF1B,     0xAF3A,
293     0x9F59,     0x8F78,     0x9188,     0x81A9,     0xB1CA,     0xA1EB,
294     0xD10C,     0xC12D,     0xF14E,     0xE16F,     0x1080,     0x00A1,
295     0x30C2,     0x20E3,     0x5004,     0x4025,     0x7046,     0x6067,
296     0x83B9,     0x9398,     0xA3FB,     0xB3DA,     0xC33D,     0xD31C,
297     0xE37F,     0xF35E,     0x02B1,     0x1290,     0x22F3,     0x32D2,
298     0x4235,     0x5214,     0x6277,     0x7256,     0xB5EA,     0xA5CB,
299     0x95A8,     0x8589,     0xF56E,     0xE54F,     0xD52C,     0xC50D,
300     0x34E2,     0x24C3,     0x14A0,     0x0481,     0x7466,     0x6447,
301     0x5424,     0x4405,     0xA7DB,     0xB7FA,     0x8799,     0x97B8,
302     0xE75F,     0xF77E,     0xC71D,     0xD73C,     0x26D3,     0x36F2,
303     0x0691,     0x16B0,     0x6657,     0x7676,     0x4615,     0x5634,
304     0xD94C,     0xC96D,     0xF90E,     0xE92F,     0x99C8,     0x89E9,
305     0xB98A,     0xA9AB,     0x5844,     0x4865,     0x7806,     0x6827,
306     0x18C0,     0x08E1,     0x3882,     0x28A3,     0xCB7D,     0xDB5C,
307     0xEB3F,     0xFB1E,     0x8BF9,     0x9BD8,     0xABBB,     0xBB9A,
308     0x4A75,     0x5A54,     0x6A37,     0x7A16,     0x0AF1,     0x1AD0,
309     0x2AB3,     0x3A92,     0xFD2E,     0xED0F,     0xDD6C,     0xCD4D,
310     0xBDAA,     0xAD8B,     0x9DE8,     0x8DC9,     0x7C26,     0x6C07,
311     0x5C64,     0x4C45,     0x3CA2,     0x2C83,     0x1CE0,     0x0CC1,
312     0xEF1F,     0xFF3E,     0xCF5D,     0xDF7C,     0xAF9B,     0xBFBA,
313     0x8FD9,     0x9FF8,     0x6E17,     0x7E36,     0x4E55,     0x5E74,
314     0x2E93,     0x3EB2,     0x0ED1,     0x1EF0
315 };
316     
317 /*
318  * Implements a CRC function for X worth bits using (uint[X]_t)
319  * as type. and util_crc[X]_table.
320  */
321 #define CRC(X) \
322 uint##X##_t util_crc##X(const char *k, int len, const short clamp) {  \
323     register uint##X##_t h= (uint##X##_t)0xFFFFFFFF;                  \
324     for (; len; --len, ++k)                                           \
325         h = util_crc##X##_table[(h^((unsigned char)*k))&0xFF]^(h>>8); \
326     return (~h)%clamp;                                                \
327 }
328 CRC(32)
329 CRC(16)
330 #undef CRC
331
332 /*
333  * Implements libc getline for systems that don't have it, which is
334  * assmed all.  This works the same as getline().
335  */
336 int util_getline(char **lineptr, size_t *n, FILE *stream) {
337     int   chr;
338     int   ret;
339     char *pos;
340
341     if (!lineptr || !n || !stream)
342         return -1;
343     if (!*lineptr) {
344         if (!(*lineptr = mem_a((*n=64))))
345             return -1;
346     }
347
348     chr = *n;
349     pos = *lineptr;
350
351     for (;;) {
352         int c = getc(stream);
353
354         if (chr < 2) {
355             char *tmp = mem_a((*n+=(*n>16)?*n:64));
356             if  (!tmp)
357                 return -1;
358
359             chr = *n + *lineptr - pos;
360             strcpy(tmp,*lineptr);
361             if (!(*lineptr = tmp)) {
362                 mem_d (tmp);
363                 return -1;
364             }
365             pos = *n - chr + *lineptr;
366         }
367
368         if (ferror(stream))
369             return -1;
370         if (c == EOF) {
371             if (pos == *lineptr)
372                 return -1;
373             else
374                 break;
375         }
376
377         *pos++ = c;
378         chr--;
379         if (c == '\n')
380             break;
381     }
382     *pos = '\0';
383     return (ret = pos - *lineptr);
384 }