]> git.xonotic.org Git - xonotic/gmqcc.git/blob - util.c
Fix clang warnings
[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         util_debug("MEM", "Memory information:\n\
65         Total allocations:   %llu\n\
66         Total deallocations: %llu\n\
67         Total allocated:     %llu (bytes)\n\
68         Total deallocated:   %llu (bytes)\n",
69                 mem_at, mem_dt,
70                 mem_ab, mem_db
71         );
72 }
73
74 #ifndef mem_d
75 #define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
76 #endif
77 #ifndef mem_a
78 #define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
79 #endif
80
81 /*
82  * Some string utility functions, because strdup uses malloc, and we want
83  * to track all memory (without replacing malloc).
84  */
85 char *util_strdup(const char *s) {
86     size_t  len;
87     char   *ptr;
88     
89     if (!s)
90         return NULL;
91         
92     len = strlen(s);
93     ptr = mem_a (len+1);
94     
95     if (ptr && len) {
96         memcpy(ptr, s, len);
97         ptr[len] = '\0';
98     }
99     
100     return ptr;
101 }
102
103 /*
104  * Remove quotes from a string, escapes from \ in string
105  * as well.  This function shouldn't be used to create a
106  * char array that is later freed (it uses pointer arith)
107  */
108 char *util_strrq(char *s) {
109     char *dst = s;
110     char *src = s;
111     char  chr;
112     while ((chr = *src++) != '\0') {
113         if (chr == '\\') {
114             *dst++ = chr;
115             if ((chr = *src++) == '\0')
116                 break;
117             *dst++ = chr;
118         } else if (chr != '"')
119             *dst++ = chr;
120     }
121     *dst = '\0';
122     return dst;
123 }
124
125 /*
126  * Remove newline from a string (if it exists).  This is
127  * done pointer wise instead of strlen(), and an array
128  * access.
129  */
130 char *util_strrnl(char *src) {
131     if (!src) return NULL;
132     char   *cpy = src;
133     while (*cpy && *cpy != '\n')
134         cpy++;
135         
136     *cpy = '\0';
137     return src;
138 }
139
140 void util_debug(const char *area, const char *ms, ...) {
141     va_list  va;
142     va_start(va, ms);
143     fprintf (stdout, "DEBUG: ");
144     fputc   ('[',  stdout);
145     fprintf(stdout, "%s",area);
146     fputs   ("] ", stdout);
147     vfprintf(stdout, ms, va);
148     va_end  (va);
149 }
150
151 /*
152  * Implements libc getline for systems that don't have it, which is 
153  * assmed all.  This works the same as getline().
154  */
155 int util_getline(char **lineptr, size_t *n, FILE *stream) {
156     int   chr;
157     int   ret;
158     char *pos;    
159
160     if (!lineptr || !n || !stream)
161         return -1;
162     if (!*lineptr) {
163         if (!(*lineptr = mem_a((*n = 64))))
164             return -1;
165     }
166
167     chr = *n;
168     pos = *lineptr;
169
170     for (;;) {
171         int c = getc(stream);
172         
173         if (chr < 2) {
174             char *tmp = mem_a((*n+=(*n>16)?*n:64));
175             if  (!tmp)
176                 return -1;
177             
178             chr = *n + *lineptr - pos;
179             strcpy(tmp,*lineptr);
180             if (!(*lineptr = tmp)) {
181                                 mem_d (tmp);
182                 return -1;
183             } 
184             pos = *n - chr + *lineptr;
185         }
186
187         if (ferror(stream))
188             return -1;
189         if (c == EOF) {
190             if (pos == *lineptr)
191                 return -1;
192             else
193                 break;
194         }
195
196         *pos++ = c;
197          chr--;
198         if (c == '\n')
199             break;
200     }
201     *pos = '\0';
202     return (ret = pos - *lineptr);
203 }