1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2019 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 #include "nasmlib.h"
40 #include "error.h"
41 #include "alloc.h"
42 
43 size_t _nasm_last_string_size;
44 
nasm_alloc_failed(void)45 fatal_func nasm_alloc_failed(void)
46 {
47     nasm_critical("out of memory!");
48 }
49 
nasm_malloc(size_t size)50 void *nasm_malloc(size_t size)
51 {
52     void *p;
53 
54 again:
55     p = malloc(size);
56 
57     if (unlikely(!p)) {
58         if (!size) {
59             size = 1;
60             goto again;
61         }
62         nasm_alloc_failed();
63     }
64     return p;
65 }
66 
nasm_calloc(size_t nelem,size_t size)67 void *nasm_calloc(size_t nelem, size_t size)
68 {
69     void *p;
70 
71 again:
72     p = calloc(nelem, size);
73 
74     if (unlikely(!p)) {
75         if (!nelem || !size) {
76             nelem = size = 1;
77             goto again;
78         }
79         nasm_alloc_failed();
80     }
81 
82     return p;
83 }
84 
nasm_zalloc(size_t size)85 void *nasm_zalloc(size_t size)
86 {
87     return nasm_calloc(size, 1);
88 }
89 
90 /*
91  * Unlike the system realloc, we do *not* allow size == 0 to be
92  * the equivalent to free(); we guarantee returning a non-NULL pointer.
93  *
94  * The check for calling malloc() is theoretically redundant, but be
95  * paranoid about the system library...
96  */
nasm_realloc(void * q,size_t size)97 void *nasm_realloc(void *q, size_t size)
98 {
99     if (unlikely(!size))
100         size = 1;
101     q = q ? realloc(q, size) : malloc(size);
102     return validate_ptr(q);
103 }
104 
nasm_free(void * q)105 void nasm_free(void *q)
106 {
107     if (q)
108         free(q);
109 }
110 
nasm_strdup(const char * s)111 char *nasm_strdup(const char *s)
112 {
113     char *p;
114     const size_t size = strlen(s) + 1;
115 
116     _nasm_last_string_size = size;
117     p = nasm_malloc(size);
118     return memcpy(p, s, size);
119 }
120 
nasm_strndup(const char * s,size_t len)121 char *nasm_strndup(const char *s, size_t len)
122 {
123     char *p;
124 
125     len = strnlen(s, len);
126     _nasm_last_string_size = len + 1;
127     p = nasm_malloc(len+1);
128     p[len] = '\0';
129     return memcpy(p, s, len);
130 }
131 
nasm_strcat(const char * one,const char * two)132 char *nasm_strcat(const char *one, const char *two)
133 {
134     char *rslt;
135     const size_t l1 = strlen(one);
136     const size_t s2 = strlen(two) + 1;
137 
138     _nasm_last_string_size = l1 + s2;
139     rslt = nasm_malloc(l1 + s2);
140     memcpy(rslt, one, l1);
141     memcpy(rslt + l1, two, s2);
142     return rslt;
143 }
144 
nasm_strcatn(const char * str1,...)145 char *nasm_strcatn(const char *str1, ...)
146 {
147     va_list ap;
148     char *rslt;                 /* Output buffer */
149     size_t s;                   /* Total buffer size */
150     size_t n;                   /* Number of arguments */
151     size_t *ltbl;               /* Table of lengths */
152     size_t l, *lp;              /* Length for current argument */
153     const char *p;              /* Currently examined argument */
154     char *q;                    /* Output pointer */
155 
156     n = 0;                      /* No strings encountered yet */
157     p = str1;
158     va_start(ap, str1);
159     while (p) {
160         n++;
161         p = va_arg(ap, const char *);
162     }
163     va_end(ap);
164 
165     ltbl = nasm_malloc(n * sizeof(size_t));
166 
167     s = 1;                      /* Space for final NULL */
168     p = str1;
169     lp = ltbl;
170     va_start(ap, str1);
171     while (p) {
172         *lp++ = l = strlen(p);
173         s += l;
174         p = va_arg(ap, const char *);
175     }
176     va_end(ap);
177 
178     _nasm_last_string_size = s;
179 
180     q = rslt = nasm_malloc(s);
181 
182     p = str1;
183     lp = ltbl;
184     va_start(ap, str1);
185     while (p) {
186         l = *lp++;
187         memcpy(q, p, l);
188         q += l;
189         p = va_arg(ap, const char *);
190     }
191     va_end(ap);
192     *q = '\0';
193 
194     nasm_free(ltbl);
195 
196     return rslt;
197 }
198