]> git.xonotic.org Git - xonotic/gmqcc.git/blob - util.c
command line argument parsing.
[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     return data;
50 }
51
52 void util_memory_d(void *ptrn, unsigned int line, const char *file) {
53     if (!ptrn) return;
54     void              *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
55     struct memblock_t *info = (struct memblock_t*)data;
56     
57     util_debug("MEM", "released:   % 8u (bytes) address 0x%08X @ %s:%u\n", info->byte, data, file, line);
58     mem_db += info->byte;
59     mem_dt++;
60     free(data);
61 }
62
63 void util_meminfo() {
64     if (!opts_memchk)
65         return;
66         
67     util_debug("MEM", "Memory information:\n\
68         Total allocations:   %llu\n\
69         Total deallocations: %llu\n\
70         Total allocated:     %llu (bytes)\n\
71         Total deallocated:   %llu (bytes)\n",
72             mem_at, mem_dt,
73             mem_ab, mem_db
74     );
75 }
76
77 //#ifndef mem_d
78 //#define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
79 //#endif
80 //#ifndef mem_a
81 //#define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
82 //#endif
83
84 /*
85  * Some string utility functions, because strdup uses malloc, and we want
86  * to track all memory (without replacing malloc).
87  */
88 char *util_strdup(const char *s) {
89     size_t  len = 0;
90     char   *ptr = NULL;
91     
92     if (!s)
93         return NULL;
94         
95     if ((len = strlen(s)) && (ptr = mem_a(len+1))) {
96         memcpy(ptr, s, len);
97         ptr[len] = '\0';
98     }
99     return ptr;
100 }
101
102 /*
103  * Remove quotes from a string, escapes from \ in string
104  * as well.  This function shouldn't be used to create a
105  * char array that is later freed (it uses pointer arith)
106  */
107 char *util_strrq(char *s) {
108     char *dst = s;
109     char *src = s;
110     char  chr;
111     while ((chr = *src++) != '\0') {
112         if (chr == '\\') {
113             *dst++ = chr;
114             if ((chr = *src++) == '\0')
115                 break;
116             *dst++ = chr;
117         } else if (chr != '"')
118             *dst++ = chr;
119     }
120     *dst = '\0';
121     return dst;
122 }
123
124 /*
125  * Remove newline from a string (if it exists).  This is
126  * done pointer wise instead of strlen(), and an array
127  * access.
128  */
129 char *util_strrnl(char *src) {
130     if (!src) return NULL;
131     char   *cpy = src;
132     while (*cpy && *cpy != '\n')
133         cpy++;
134         
135     *cpy = '\0';
136     return src;
137 }
138
139 void util_debug(const char *area, const char *ms, ...) {
140     if (!opts_debug)
141         return;
142         
143     va_list  va;
144     va_start(va, ms);
145     fprintf (stdout, "DEBUG: ");
146     fputc   ('[',  stdout);
147     fprintf(stdout, "%s", area);
148     fputs   ("] ", stdout);
149     vfprintf(stdout, ms, va);
150     va_end  (va);
151 }
152
153 /*
154  * Endianess swapping, all data must be stored little-endian.  This
155  * reorders by stride and length, much nicer than other functions for
156  * certian-sized types like short or int.
157  */
158 void util_endianswap(void *m, int s, int l) {
159     size_t w = 0;
160     size_t i = 0;
161
162     /* ignore if we're already LE */
163     if(*((char *)&s))
164         return;
165
166     for(; w < l; w++) {
167         for(;  i < s << 1; i++) {
168             unsigned char *p = (unsigned char *)m+w*s;
169             unsigned char  t = p[i];
170             p[i]             = p[s-i-1];
171             p[s-i-1]         = t;
172         }
173     }
174 }
175
176 /*
177  * Implements libc getline for systems that don't have it, which is 
178  * assmed all.  This works the same as getline().
179  */
180 int util_getline(char **lineptr, size_t *n, FILE *stream) {
181     int   chr;
182     int   ret;
183     char *pos;    
184
185     if (!lineptr || !n || !stream)
186         return -1;
187     if (!*lineptr) {
188         if (!(*lineptr = mem_a((*n = 64))))
189             return -1;
190     }
191
192     chr = *n;
193     pos = *lineptr;
194
195     for (;;) {
196         int c = getc(stream);
197         
198         if (chr < 2) {
199             char *tmp = mem_a((*n+=(*n>16)?*n:64));
200             if  (!tmp)
201                 return -1;
202             
203             chr = *n + *lineptr - pos;
204             strcpy(tmp,*lineptr);
205             if (!(*lineptr = tmp)) {
206                 mem_d (tmp);
207                 return -1;
208             } 
209             pos = *n - chr + *lineptr;
210         }
211
212         if (ferror(stream))
213             return -1;
214         if (c == EOF) {
215             if (pos == *lineptr)
216                 return -1;
217             else
218                 break;
219         }
220
221         *pos++ = c;
222          chr--;
223         if (c == '\n')
224             break;
225     }
226     *pos = '\0';
227     return (ret = pos - *lineptr);
228 }