]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/m4/misc.c
Allowus to exclude a.out support from ldd and use it with arm64 as it won't
[FreeBSD/FreeBSD.git] / usr.bin / m4 / misc.c
1 /*      $OpenBSD: misc.c,v 1.44 2014/05/12 19:11:19 espie Exp $ */
2 /*      $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $     */
3
4 /*
5  * Copyright (c) 1989, 1993
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Ozan Yigit at York University.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/types.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdint.h>
45 #include <stdlib.h>
46 #include <stddef.h>
47 #include <string.h>
48 #include <err.h>
49 #include "mdef.h"
50 #include "stdd.h"
51 #include "extern.h"
52 #include "pathnames.h"
53
54
55 char *ep;               /* first free char in strspace */
56 static char *strspace;  /* string space for evaluation */
57 char *endest;           /* end of string space         */
58 static size_t strsize = STRSPMAX;
59 static size_t bufsize = BUFSIZE;
60
61 unsigned char *buf;                     /* push-back buffer            */
62 unsigned char *bufbase;                 /* the base for current ilevel */
63 unsigned char *bbase[MAXINP];           /* the base for each ilevel    */
64 unsigned char *bp;                      /* first available character   */
65 unsigned char *endpbb;                  /* end of push-back buffer     */
66
67 static void *reallocarray(void *, size_t, size_t);
68
69 /*
70  * find the index of second str in the first str.
71  */
72 ptrdiff_t
73 indx(const char *s1, const char *s2)
74 {
75         char *t;
76
77         t = strstr(s1, s2);
78         if (t == NULL)
79                 return (-1);
80         else
81                 return (t - s1);
82 }
83 /*
84  *  pushback - push character back onto input
85  */
86 void
87 pushback(int c)
88 {
89         if (c == EOF)
90                 return;
91         if (bp >= endpbb)
92                 enlarge_bufspace();
93         *bp++ = c;
94 }
95
96 /*
97  *  pbstr - push string back onto input
98  *          pushback is replicated to improve
99  *          performance.
100  */
101 void
102 pbstr(const char *s)
103 {
104         size_t n;
105
106         n = strlen(s);
107         while (endpbb - bp <= (long)n)
108                 enlarge_bufspace();
109         while (n > 0)
110                 *bp++ = s[--n];
111 }
112
113 /*
114  *  pbnum - convert number to string, push back on input.
115  */
116 void
117 pbnum(int n)
118 {
119         pbnumbase(n, 10, 0);
120 }
121
122 void
123 pbnumbase(int n, int base, int d)
124 {
125         static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
126         int num;
127         int printed = 0;
128
129         if (base > 36)
130                 m4errx(1, "base %d > 36: not supported.", base);
131
132         if (base < 2)
133                 m4errx(1, "bad base %d for conversion.", base);
134
135         num = (n < 0) ? -n : n;
136         do {
137                 pushback(digits[num % base]);
138                 printed++;
139         }
140         while ((num /= base) > 0);
141
142         if (n < 0)
143                 printed++;
144         while (printed++ < d)
145                 pushback('0');
146
147         if (n < 0)
148                 pushback('-');
149 }
150
151 /*
152  *  pbunsigned - convert unsigned long to string, push back on input.
153  */
154 void
155 pbunsigned(unsigned long n)
156 {
157         do {
158                 pushback(n % 10 + '0');
159         }
160         while ((n /= 10) > 0);
161 }
162
163 void
164 initspaces(void)
165 {
166         int i;
167
168         strspace = xalloc(strsize+1, NULL);
169         ep = strspace;
170         endest = strspace+strsize;
171         buf = xalloc(bufsize, NULL);
172         bufbase = buf;
173         bp = buf;
174         endpbb = buf + bufsize;
175         for (i = 0; i < MAXINP; i++)
176                 bbase[i] = buf;
177 }
178
179 void
180 enlarge_strspace(void)
181 {
182         char *newstrspace;
183         int i;
184
185         strsize *= 2;
186         newstrspace = malloc(strsize + 1);
187         if (!newstrspace)
188                 errx(1, "string space overflow");
189         memcpy(newstrspace, strspace, strsize/2);
190         for (i = 0; i <= sp; i++)
191                 if (sstack[i])
192                         mstack[i].sstr = (mstack[i].sstr - strspace)
193                             + newstrspace;
194         ep = (ep-strspace) + newstrspace;
195         free(strspace);
196         strspace = newstrspace;
197         endest = strspace + strsize;
198 }
199
200 void
201 enlarge_bufspace(void)
202 {
203         unsigned char *newbuf;
204         int i;
205
206         bufsize += bufsize/2;
207         newbuf = xrealloc(buf, bufsize, "too many characters pushed back");
208         for (i = 0; i < MAXINP; i++)
209                 bbase[i] = (bbase[i]-buf)+newbuf;
210         bp = (bp-buf)+newbuf;
211         bufbase = (bufbase-buf)+newbuf;
212         buf = newbuf;
213         endpbb = buf+bufsize;
214 }
215
216 /*
217  *  chrsave - put single char on string space
218  */
219 void
220 chrsave(int c)
221 {
222         if (ep >= endest)
223                 enlarge_strspace();
224         *ep++ = c;
225 }
226
227 /*
228  * read in a diversion file, and dispose it.
229  */
230 void
231 getdiv(int n)
232 {
233         int c;
234
235         if (active == outfile[n])
236                 m4errx(1, "undivert: diversion still active.");
237         rewind(outfile[n]);
238         while ((c = getc(outfile[n])) != EOF)
239                 putc(c, active);
240         (void) fclose(outfile[n]);
241         outfile[n] = NULL;
242 }
243
244 void
245 onintr(int signo __unused)
246 {
247 #define intrmessage     "m4: interrupted.\n"
248         write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
249         _exit(1);
250 }
251
252 /*
253  * killdiv - get rid of the diversion files
254  */
255 void
256 killdiv(void)
257 {
258         int n;
259
260         for (n = 0; n < maxout; n++)
261                 if (outfile[n] != NULL) {
262                         (void) fclose(outfile[n]);
263                 }
264 }
265
266 extern char *__progname;
267
268 void
269 m4errx(int exitstatus, const char *fmt, ...)
270 {
271         fprintf(stderr, "%s: ", __progname);
272         fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE);
273         if (fmt != NULL) {
274                 va_list ap;
275
276                 va_start(ap, fmt);
277                 vfprintf(stderr, fmt, ap);
278                 va_end(ap);
279         }
280         fprintf(stderr, "\n");
281         exit(exitstatus);
282 }
283
284 /*
285  * resizedivs: allocate more diversion files */
286 void
287 resizedivs(int n)
288 {
289         int i;
290
291         outfile = xreallocarray(outfile, n, sizeof(FILE *),
292             "too many diverts %d", n);
293         for (i = maxout; i < n; i++)
294                 outfile[i] = NULL;
295         maxout = n;
296 }
297
298 void *
299 xalloc(size_t n, const char *fmt, ...)
300 {
301         void *p = malloc(n);
302
303         if (p == NULL) {
304                 if (fmt == NULL)
305                         err(1, "malloc");
306                 else {
307                         va_list va;
308
309                         va_start(va, fmt);
310                         verr(1, fmt, va);
311                         va_end(va);
312                 }
313         }
314         return p;
315 }
316
317 void *
318 xcalloc(size_t n, size_t s, const char *fmt, ...)
319 {
320         void *p = calloc(n, s);
321
322         if (p == NULL) {
323                 if (fmt == NULL)
324                         err(1, "calloc");
325                 else {
326                         va_list va;
327
328                         va_start(va, fmt);
329                         verr(1, fmt, va);
330                         va_end(va);
331                 }
332         }
333         return p;
334 }
335
336 void *
337 xrealloc(void *old, size_t n, const char *fmt, ...)
338 {
339         char *p = realloc(old, n);
340
341         if (p == NULL) {
342                 free(old);
343                 if (fmt == NULL)
344                         err(1, "realloc");
345                 else {
346                         va_list va;
347
348                         va_start(va, fmt);
349                         verr(1, fmt, va);
350                         va_end(va);
351                 }
352         }
353         return p;
354 }
355
356 void *
357 xreallocarray(void *old, size_t s1, size_t s2, const char *fmt, ...)
358 {
359         void *p = reallocarray(old, s1, s2);
360
361         if (p == NULL) {
362                 free(old);
363                 if (fmt == NULL)
364                         err(1, "reallocarray");
365                 else {
366                         va_list va;
367
368                         va_start(va, fmt);
369                         verr(1, fmt, va);
370                         va_end(va);
371                 }
372         }
373         return p;
374 }
375
376 char *
377 xstrdup(const char *s)
378 {
379         char *p = strdup(s);
380         if (p == NULL)
381                 err(1, "strdup");
382         return p;
383 }
384
385 void
386 usage(void)
387 {
388         fprintf(stderr, "usage: m4 [-gPs] [-Dname[=value]] [-d flags] "
389                         "[-I dirname] [-o filename]\n"
390                         "\t[-t macro] [-Uname] [file ...]\n");
391         exit(1);
392 }
393
394 int
395 obtain_char(struct input_file *f)
396 {
397         if (f->c == EOF)
398                 return EOF;
399
400         f->c = fgetc(f->file);
401         if (f->c == '\n')
402                 f->lineno++;
403
404         return f->c;
405 }
406
407 void
408 set_input(struct input_file *f, FILE *real, const char *name)
409 {
410         f->file = real;
411         f->lineno = 1;
412         f->c = 0;
413         f->name = xstrdup(name);
414         emit_synchline();
415 }
416
417 void
418 do_emit_synchline(void)
419 {
420         fprintf(active, "#line %lu \"%s\"\n",
421             infile[ilevel].lineno, infile[ilevel].name);
422         infile[ilevel].synch_lineno = infile[ilevel].lineno;
423 }
424
425 void
426 release_input(struct input_file *f)
427 {
428         if (f->file != stdin)
429             fclose(f->file);
430         f->c = EOF;
431         /*
432          * XXX can't free filename, as there might still be
433          * error information pointing to it.
434          */
435 }
436
437 void
438 doprintlineno(struct input_file *f)
439 {
440         pbunsigned(f->lineno);
441 }
442
443 void
444 doprintfilename(struct input_file *f)
445 {
446         pbstr(rquote);
447         pbstr(f->name);
448         pbstr(lquote);
449 }
450
451 /*
452  * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
453  * and later dump everything that was added since then to a file.
454  */
455 size_t
456 buffer_mark(void)
457 {
458         return bp - buf;
459 }
460
461
462 void
463 dump_buffer(FILE *f, size_t m)
464 {
465         unsigned char *s;
466
467         for (s = bp; s-buf > (long)m;)
468                 fputc(*--s, f);
469 }
470
471 /*      $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $  */
472 /*
473  * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
474  *
475  * Permission to use, copy, modify, and distribute this software for any
476  * purpose with or without fee is hereby granted, provided that the above
477  * copyright notice and this permission notice appear in all copies.
478  *
479  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
480  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
481  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
482  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
483  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
484  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
485  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
486  */
487
488 /*
489  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
490  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
491  */
492 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
493
494 void *
495 reallocarray(void *optr, size_t nmemb, size_t size)
496 {
497         if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
498             nmemb > 0 && SIZE_MAX / nmemb < size) {
499                 errno = ENOMEM;
500                 return NULL;
501         }
502         return realloc(optr, size * nmemb);
503 }