1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 1996-2018 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | /* |
35 | * nasmlib.c library routines for the Netwide Assembler |
36 | */ |
37 | |
38 | #include "compiler.h" |
39 | |
40 | #include <stdlib.h> |
41 | |
42 | #include "nasmlib.h" |
43 | #include "error.h" |
44 | |
45 | static no_return nasm_alloc_failed(void) |
46 | { |
47 | /* If nasm_fatal() gets us back here, then croak hard */ |
48 | static bool already_here = false; |
49 | FILE *errfile; |
50 | |
51 | if (likely(!already_here)) { |
52 | already_here = true; |
53 | nasm_fatal(0, "out of memory!" ); |
54 | } |
55 | |
56 | errfile = error_file; |
57 | if (!errfile) |
58 | error_file = stderr; |
59 | |
60 | fprintf(error_file, "nasm: out of memory!\n" ); |
61 | fflush(error_file); |
62 | fflush(NULL); |
63 | abort(); |
64 | } |
65 | |
66 | static inline void *validate_ptr(void *p) |
67 | { |
68 | if (unlikely(!p)) |
69 | nasm_alloc_failed(); |
70 | return p; |
71 | } |
72 | |
73 | void *nasm_malloc(size_t size) |
74 | { |
75 | return validate_ptr(malloc(size)); |
76 | } |
77 | |
78 | void *nasm_calloc(size_t size, size_t nelem) |
79 | { |
80 | return validate_ptr(calloc(size, nelem)); |
81 | } |
82 | |
83 | void *nasm_zalloc(size_t size) |
84 | { |
85 | return validate_ptr(calloc(1, size)); |
86 | } |
87 | |
88 | void *nasm_realloc(void *q, size_t size) |
89 | { |
90 | return validate_ptr(q ? realloc(q, size) : malloc(size)); |
91 | } |
92 | |
93 | void nasm_free(void *q) |
94 | { |
95 | if (q) |
96 | free(q); |
97 | } |
98 | |
99 | char *nasm_strdup(const char *s) |
100 | { |
101 | char *p; |
102 | size_t size = strlen(s) + 1; |
103 | |
104 | p = nasm_malloc(size); |
105 | return memcpy(p, s, size); |
106 | } |
107 | |
108 | char *nasm_strndup(const char *s, size_t len) |
109 | { |
110 | char *p; |
111 | |
112 | len = strnlen(s, len); |
113 | p = nasm_malloc(len+1); |
114 | p[len] = '\0'; |
115 | return memcpy(p, s, len); |
116 | } |
117 | |
118 | char *nasm_strcat(const char *one, const char *two) |
119 | { |
120 | char *rslt; |
121 | size_t l1 = strlen(one); |
122 | size_t l2 = strlen(two); |
123 | rslt = nasm_malloc(l1 + l2 + 1); |
124 | memcpy(rslt, one, l1); |
125 | memcpy(rslt + l1, two, l2+1); |
126 | return rslt; |
127 | } |
128 | |
129 | char *nasm_strcatn(const char *str1, ...) |
130 | { |
131 | va_list ap; |
132 | char *rslt; /* Output buffer */ |
133 | size_t s; /* Total buffer size */ |
134 | size_t n; /* Number of arguments */ |
135 | size_t *ltbl; /* Table of lengths */ |
136 | size_t l, *lp; /* Length for current argument */ |
137 | const char *p; /* Currently examined argument */ |
138 | char *q; /* Output pointer */ |
139 | |
140 | n = 0; /* No strings encountered yet */ |
141 | p = str1; |
142 | va_start(ap, str1); |
143 | while (p) { |
144 | n++; |
145 | p = va_arg(ap, const char *); |
146 | } |
147 | va_end(ap); |
148 | |
149 | ltbl = nasm_malloc(n * sizeof(size_t)); |
150 | |
151 | s = 1; /* Space for final NULL */ |
152 | p = str1; |
153 | lp = ltbl; |
154 | va_start(ap, str1); |
155 | while (p) { |
156 | *lp++ = l = strlen(p); |
157 | s += l; |
158 | p = va_arg(ap, const char *); |
159 | } |
160 | va_end(ap); |
161 | |
162 | q = rslt = nasm_malloc(s); |
163 | |
164 | p = str1; |
165 | lp = ltbl; |
166 | va_start(ap, str1); |
167 | while (p) { |
168 | l = *lp++; |
169 | memcpy(q, p, l); |
170 | q += l; |
171 | p = va_arg(ap, const char *); |
172 | } |
173 | va_end(ap); |
174 | *q = '\0'; |
175 | |
176 | nasm_free(ltbl); |
177 | |
178 | return rslt; |
179 | } |
180 | |