Recognize 'd', 't' and 'y' as radix suffixes
[platform/upstream/nasm.git] / nasmlib.c
1 /* nasmlib.c    library routines for the Netwide Assembler
2  *
3  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4  * Julian Hall. All rights reserved. The software is
5  * redistributable under the licence given in the file "Licence"
6  * distributed in the NASM archive.
7  */
8
9 #include "compiler.h"
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <inttypes.h>
16
17 #include "nasm.h"
18 #include "nasmlib.h"
19 #include "insns.h"
20
21 int globalbits = 0;    /* defined in nasm.h, works better here for ASM+DISASM */
22 efunc nasm_malloc_error;        /* Exported for the benefit of vsnprintf.c */
23
24 #ifdef LOGALLOC
25 static FILE *logfp;
26 #endif
27
28 void nasm_set_malloc_error(efunc error)
29 {
30     nasm_malloc_error = error;
31 #ifdef LOGALLOC
32     logfp = fopen("malloc.log", "w");
33     setvbuf(logfp, NULL, _IOLBF, BUFSIZ);
34     fprintf(logfp, "null pointer is %p\n", NULL);
35 #endif
36 }
37
38 #ifdef LOGALLOC
39 void *nasm_malloc_log(char *file, int line, size_t size)
40 #else
41 void *nasm_malloc(size_t size)
42 #endif
43 {
44     void *p = malloc(size);
45     if (!p)
46         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
47 #ifdef LOGALLOC
48     else
49         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
50                 file, line, (long)size, p);
51 #endif
52     return p;
53 }
54
55 #ifdef LOGALLOC
56 void *nasm_zalloc_log(char *file, int line, size_t size)
57 #else
58 void *nasm_zalloc(size_t size)
59 #endif
60 {
61     void *p = calloc(size, 1);
62     if (!p)
63         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
64 #ifdef LOGALLOC
65     else
66         fprintf(logfp, "%s %d calloc(%ld, 1) returns %p\n",
67                 file, line, (long)size, p);
68 #endif
69     return p;
70 }
71
72 #ifdef LOGALLOC
73 void *nasm_realloc_log(char *file, int line, void *q, size_t size)
74 #else
75 void *nasm_realloc(void *q, size_t size)
76 #endif
77 {
78     void *p = q ? realloc(q, size) : malloc(size);
79     if (!p)
80         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
81 #ifdef LOGALLOC
82     else if (q)
83         fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
84                 file, line, q, (long)size, p);
85     else
86         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
87                 file, line, (long)size, p);
88 #endif
89     return p;
90 }
91
92 #ifdef LOGALLOC
93 void nasm_free_log(char *file, int line, void *q)
94 #else
95 void nasm_free(void *q)
96 #endif
97 {
98     if (q) {
99         free(q);
100 #ifdef LOGALLOC
101         fprintf(logfp, "%s %d free(%p)\n", file, line, q);
102 #endif
103     }
104 }
105
106 #ifdef LOGALLOC
107 char *nasm_strdup_log(char *file, int line, const char *s)
108 #else
109 char *nasm_strdup(const char *s)
110 #endif
111 {
112     char *p;
113     int size = strlen(s) + 1;
114
115     p = malloc(size);
116     if (!p)
117         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
118 #ifdef LOGALLOC
119     else
120         fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
121                 file, line, (long)size, p);
122 #endif
123     strcpy(p, s);
124     return p;
125 }
126
127 #ifdef LOGALLOC
128 char *nasm_strndup_log(char *file, int line, char *s, size_t len)
129 #else
130 char *nasm_strndup(char *s, size_t len)
131 #endif
132 {
133     char *p;
134     int size = len + 1;
135
136     p = malloc(size);
137     if (!p)
138         nasm_malloc_error(ERR_FATAL | ERR_NOFILE, "out of memory");
139 #ifdef LOGALLOC
140     else
141         fprintf(logfp, "%s %d strndup(%ld) returns %p\n",
142                 file, line, (long)size, p);
143 #endif
144     strncpy(p, s, len);
145     p[len] = '\0';
146     return p;
147 }
148
149 #ifndef nasm_stricmp
150 int nasm_stricmp(const char *s1, const char *s2)
151 {
152     while (*s1 && tolower(*s1) == tolower(*s2))
153         s1++, s2++;
154     if (!*s1 && !*s2)
155         return 0;
156     else if (tolower(*s1) < tolower(*s2))
157         return -1;
158     else
159         return 1;
160 }
161 #endif
162
163 #ifndef nasm_strnicmp
164 int nasm_strnicmp(const char *s1, const char *s2, int n)
165 {
166     while (n > 0 && *s1 && tolower(*s1) == tolower(*s2))
167         s1++, s2++, n--;
168     if ((!*s1 && !*s2) || n == 0)
169         return 0;
170     else if (tolower(*s1) < tolower(*s2))
171         return -1;
172     else
173         return 1;
174 }
175 #endif
176
177 #ifndef nasm_strsep
178 char *nasm_strsep(char **stringp, const char *delim)
179 {
180         char *s = *stringp;
181         char *e;
182
183         if (!s)
184                 return NULL;
185
186         e = strpbrk(s, delim);
187         if (e)
188                 *e++ = '\0';
189
190         *stringp = e;
191         return s;
192 }
193 #endif
194
195
196 #define lib_isnumchar(c)   ( isalnum(c) || (c) == '$')
197 #define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
198
199 int64_t readnum(char *str, bool *error)
200 {
201     char *r = str, *q;
202     int32_t radix;
203     uint64_t result, checklimit;
204     int digit, last;
205     bool warn = false;
206     int sign = 1;
207
208     *error = false;
209
210     while (isspace(*r))
211         r++;                    /* find start of number */
212
213     /*
214      * If the number came from make_tok_num (as a result of an %assign), it
215      * might have a '-' built into it (rather than in a preceeding token).
216      */
217     if (*r == '-') {
218         r++;
219         sign = -1;
220     }
221
222     q = r;
223
224     while (lib_isnumchar(*q))
225         q++;                    /* find end of number */
226
227     /*
228      * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
229      * ends in Q, it's octal. if it ends in B, it's binary.
230      * Otherwise, it's ordinary decimal.
231      */
232     if (*r == '0' && (r[1] == 'x' || r[1] == 'X'))
233         radix = 16, r += 2;
234     else if (*r == '$')
235         radix = 16, r++;
236     else if (q[-1] == 'H' || q[-1] == 'h')
237         radix = 16, q--;
238     else if (q[-1] == 'Q' || q[-1] == 'q' || q[-1] == 'O' || q[-1] == 'o')
239         radix = 8, q--;
240     else if (q[-1] == 'B' || q[-1] == 'b' || q[-1] == 'Y' || q[-1] == 'y')
241         radix = 2, q--;
242     else if (q[-1] == 'D' || q[-1] == 'd' || q[-1] == 'T' || q[-1] == 't')
243         radix = 10, q--;
244     else
245         radix = 10;
246
247     /*
248      * If this number has been found for us by something other than
249      * the ordinary scanners, then it might be malformed by having
250      * nothing between the prefix and the suffix. Check this case
251      * now.
252      */
253     if (r >= q) {
254         *error = true;
255         return 0;
256     }
257     
258     /*
259      * `checklimit' must be 2**(32|64) / radix. We can't do that in
260      * 32/64-bit arithmetic, which we're (probably) using, so we
261      * cheat: since we know that all radices we use are even, we
262      * can divide 2**(31|63) by radix/2 instead.
263      */
264     if (globalbits == 64)
265         checklimit = 0x8000000000000000ULL / (radix >> 1);
266     else
267         checklimit = 0x80000000UL / (radix >> 1);
268
269     /*
270      * Calculate the highest allowable value for the last digit of a
271      * 32-bit constant... in radix 10, it is 6, otherwise it is 0
272      */
273     last = (radix == 10 ? 6 : 0);
274
275     result = 0;
276     while (*r && r < q) {
277         if (*r < '0' || (*r > '9' && *r < 'A')
278             || (digit = numvalue(*r)) >= radix) {
279             *error = true;
280             return 0;
281         }
282         if (result > checklimit || (result == checklimit && digit >= last)) {
283             warn = true;
284         }
285
286         result = radix * result + digit;
287         r++;
288     }
289
290     if (warn)
291         nasm_malloc_error(ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
292                           "numeric constant %s does not fit in 32 bits",
293                           str);
294
295     return result * sign;
296 }
297
298 int64_t readstrnum(char *str, int length, bool *warn)
299 {
300     int64_t charconst = 0;
301     int i;
302
303     *warn = false;
304
305     str += length;
306     if (globalbits == 64) {
307         for (i = 0; i < length; i++) {
308             if (charconst & 0xFF00000000000000ULL)
309                 *warn = true;
310             charconst = (charconst << 8) + (uint8_t)*--str;
311         }
312     } else {
313         for (i = 0; i < length; i++) {
314             if (charconst & 0xFF000000UL)
315                 *warn = true;
316             charconst = (charconst << 8) + (uint8_t)*--str;
317         }
318     }
319     return charconst;
320 }
321
322 static int32_t next_seg;
323
324 void seg_init(void)
325 {
326     next_seg = 0;
327 }
328
329 int32_t seg_alloc(void)
330 {
331     return (next_seg += 2) - 2;
332 }
333
334 void fwriteint16_t(int data, FILE * fp)
335 {
336     fputc((int)(data & 255), fp);
337     fputc((int)((data >> 8) & 255), fp);
338 }
339
340 void fwriteint32_t(int32_t data, FILE * fp)
341 {
342     fputc((int)(data & 255), fp);
343     fputc((int)((data >> 8) & 255), fp);
344     fputc((int)((data >> 16) & 255), fp);
345     fputc((int)((data >> 24) & 255), fp);
346 }
347
348 void fwriteint64_t(int64_t data, FILE * fp)
349 {
350     fputc((int)(data & 255), fp);
351     fputc((int)((data >> 8) & 255), fp);
352     fputc((int)((data >> 16) & 255), fp);
353     fputc((int)((data >> 24) & 255), fp);
354     fputc((int)((data >> 32) & 255), fp);
355     fputc((int)((data >> 40) & 255), fp);
356     fputc((int)((data >> 48) & 255), fp);
357     fputc((int)((data >> 56) & 255), fp);
358 }
359
360 void standard_extension(char *inname, char *outname, char *extension,
361                         efunc error)
362 {
363     char *p, *q;
364
365     if (*outname)               /* file name already exists, */
366         return;                 /* so do nothing */
367     q = inname;
368     p = outname;
369     while (*q)
370         *p++ = *q++;            /* copy, and find end of string */
371     *p = '\0';                  /* terminate it */
372     while (p > outname && *--p != '.') ;        /* find final period (or whatever) */
373     if (*p != '.')
374         while (*p)
375             p++;                /* go back to end if none found */
376     if (!strcmp(p, extension)) {        /* is the extension already there? */
377         if (*extension)
378             error(ERR_WARNING | ERR_NOFILE,
379                   "file name already ends in `%s': "
380                   "output will be in `nasm.out'", extension);
381         else
382             error(ERR_WARNING | ERR_NOFILE,
383                   "file name already has no extension: "
384                   "output will be in `nasm.out'");
385         strcpy(outname, "nasm.out");
386     } else
387         strcpy(p, extension);
388 }
389
390 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
391 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
392
393 #define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
394
395 static struct RAA *real_raa_init(int layers)
396 {
397     struct RAA *r;
398     int i;
399
400     if (layers == 0) {
401         r = nasm_zalloc(LEAFSIZ);
402         r->stepsize = 1L;
403     } else {
404         r = nasm_malloc(BRANCHSIZ);
405         r->layers = layers;
406         for (i = 0; i < RAA_LAYERSIZE; i++)
407             r->u.b.data[i] = NULL;
408         r->stepsize = RAA_BLKSIZE;
409         while (--layers)
410             r->stepsize *= RAA_LAYERSIZE;
411     }
412     return r;
413 }
414
415 struct RAA *raa_init(void)
416 {
417     return real_raa_init(0);
418 }
419
420 void raa_free(struct RAA *r)
421 {
422     if (r->layers == 0)
423         nasm_free(r);
424     else {
425         struct RAA **p;
426         for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++)
427             if (*p)
428                 raa_free(*p);
429     }
430 }
431
432 int32_t raa_read(struct RAA *r, int32_t posn)
433 {
434     if (posn >= r->stepsize * LAYERSIZ(r))
435         return 0;               /* Return 0 for undefined entries */
436     while (r->layers > 0) {
437         ldiv_t l;
438         l = ldiv(posn, r->stepsize);
439         r = r->u.b.data[l.quot];
440         posn = l.rem;
441         if (!r)
442             return 0;           /* Return 0 for undefined entries */
443     }
444     return r->u.l.data[posn];
445 }
446
447 struct RAA *raa_write(struct RAA *r, int32_t posn, int32_t value)
448 {
449     struct RAA *result;
450
451     if (posn < 0)
452         nasm_malloc_error(ERR_PANIC, "negative position in raa_write");
453
454     while (r->stepsize * LAYERSIZ(r) <= posn) {
455         /*
456          * Must add a layer.
457          */
458         struct RAA *s;
459         int i;
460
461         s = nasm_malloc(BRANCHSIZ);
462         for (i = 0; i < RAA_LAYERSIZE; i++)
463             s->u.b.data[i] = NULL;
464         s->layers = r->layers + 1;
465         s->stepsize = LAYERSIZ(r) * r->stepsize;
466         s->u.b.data[0] = r;
467         r = s;
468     }
469
470     result = r;
471
472     while (r->layers > 0) {
473         ldiv_t l;
474         struct RAA **s;
475         l = ldiv(posn, r->stepsize);
476         s = &r->u.b.data[l.quot];
477         if (!*s)
478             *s = real_raa_init(r->layers - 1);
479         r = *s;
480         posn = l.rem;
481     }
482
483     r->u.l.data[posn] = value;
484
485     return result;
486 }
487
488 /* Aggregate SAA components smaller than this */
489 #define SAA_BLKLEN 65536
490
491 struct SAA *saa_init(size_t elem_len)
492 {
493     struct SAA *s;
494     char *data;
495
496     s = nasm_zalloc(sizeof(struct SAA));
497
498     if (elem_len >= SAA_BLKLEN)
499         s->blk_len = elem_len;
500     else
501         s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len);
502
503     s->elem_len = elem_len;
504     s->length = s->blk_len;
505     data = nasm_malloc(s->blk_len);
506     s->nblkptrs = s->nblks = 1;
507     s->blk_ptrs = nasm_malloc(sizeof(char *));
508     s->blk_ptrs[0] = data;
509     s->wblk = s->rblk = &s->blk_ptrs[0];
510
511     return s;
512 }
513
514 void saa_free(struct SAA *s)
515 {
516     char **p;
517     size_t n;
518
519     for (p = s->blk_ptrs, n = s->nblks; n; p++, n--)
520         nasm_free(*p);
521
522     nasm_free(s->blk_ptrs);
523     nasm_free(s);
524 }
525
526 /* Add one allocation block to an SAA */
527 static void saa_extend(struct SAA *s)
528 {
529     size_t blkn = s->nblks++;
530     
531     if (blkn >= s->nblkptrs) {
532         size_t rindex = s->rblk - s->blk_ptrs;
533         size_t windex = s->wblk - s->blk_ptrs;
534
535         s->nblkptrs <<= 1;
536         s->blk_ptrs = nasm_realloc(s->blk_ptrs, s->nblkptrs*sizeof(char *));
537
538         s->rblk = s->blk_ptrs + rindex;
539         s->wblk = s->blk_ptrs + windex;
540     }
541
542     s->blk_ptrs[blkn] = nasm_malloc(s->blk_len);
543     s->length += s->blk_len;
544 }
545
546 void *saa_wstruct(struct SAA *s)
547 {
548     void *p;
549
550     if (s->wpos % s->elem_len)
551             nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
552                               "misaligned wpos in saa_wstruct");
553
554     if (s->wpos + s->elem_len > s->blk_len) {
555         if (s->wpos != s->blk_len)
556             nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
557                               "unfilled block in saa_wstruct");
558
559         if (s->wptr + s->elem_len > s->length)
560             saa_extend(s);
561         s->wblk++;
562         s->wpos = 0;
563     }
564
565     p = *s->wblk + s->wpos;
566     s->wpos += s->elem_len;
567     s->wptr += s->elem_len;
568
569     if (s->wptr > s->datalen)
570         s->datalen = s->wptr;
571
572     return p;
573 }
574
575 void saa_wbytes(struct SAA *s, const void *data, size_t len)
576 {
577     const char *d = data;
578
579     while (len) {
580         size_t l = s->blk_len - s->wpos;
581         if (l > len)
582             l = len;
583         if (l) {
584             if (d) {
585                 memcpy(*s->wblk + s->wpos, d, l);
586                 d += l;
587             } else
588                 memset(*s->wblk + s->wpos, 0, l);
589             s->wpos += l;
590             s->wptr += l;
591             len -= l;
592
593             if (s->datalen < s->wptr)
594                 s->datalen = s->wptr;
595         }
596         if (len) {
597             if (s->wptr >= s->length)
598                 saa_extend(s);
599             s->wblk++;
600             s->wpos = 0;
601         }
602     }
603 }
604
605 void saa_rewind(struct SAA *s)
606 {
607     s->rblk = s->blk_ptrs;
608     s->rpos = s->rptr = 0;
609 }
610
611 void *saa_rstruct(struct SAA *s)
612 {
613     void *p;
614
615     if (s->rptr + s->elem_len > s->datalen)
616         return NULL;
617
618     if (s->rpos % s->elem_len)
619             nasm_malloc_error(ERR_PANIC|ERR_NOFILE,
620                               "misaligned rpos in saa_rstruct");
621
622     if (s->rpos + s->elem_len > s->blk_len) {
623         s->rblk++;
624         s->rpos = 0;
625     }
626
627     p = *s->rblk + s->rpos;
628     s->rpos += s->elem_len;
629     s->rptr += s->elem_len;
630
631     return p;
632 }
633
634 const void *saa_rbytes(struct SAA *s, size_t *lenp)
635 {
636     const void *p;
637     size_t len;
638
639     if (s->rptr >= s->datalen) {
640         *lenp = 0;
641         return NULL;
642     }
643
644     if (s->rpos >= s->blk_len) {
645         s->rblk++;
646         s->rpos = 0;
647     }
648
649     len = *lenp;
650     if (len > s->datalen - s->rptr)
651         len = s->datalen - s->rptr;
652     if (len > s->blk_len - s->rpos)
653         len = s->blk_len - s->rpos;
654
655     *lenp = len;
656     p = *s->rblk + s->rpos;
657
658     s->rpos += len;
659     s->rptr += len;
660
661     return p;
662 }
663
664 void saa_rnbytes(struct SAA *s, void *data, size_t len)
665 {
666     char *d = data;
667
668     if (s->rptr + len > s->datalen) {
669         nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_rnbytes");
670         return;
671     }
672
673     while (len) {
674         size_t l;
675         const void *p;
676
677         l = len;
678         p = saa_rbytes(s, &l);
679
680         memcpy(d, p, l);
681         d   += l;
682         len -= l;
683     }
684 }
685
686 /* Same as saa_rnbytes, except position the counter first */
687 void saa_fread(struct SAA *s, size_t posn, void *data, size_t len)
688 {
689     size_t ix;
690     
691     if (posn+len > s->datalen) {
692         nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fread");
693         return;
694     }
695
696     ix = posn / s->blk_len;
697     s->rptr = posn;
698     s->rpos = posn % s->blk_len;
699     s->rblk = &s->blk_ptrs[ix];
700
701     saa_rnbytes(s, data, len);
702 }
703
704 /* Same as saa_wbytes, except position the counter first */
705 void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len)
706 {
707     size_t ix;
708     
709     if (posn > s->datalen) {
710         /* Seek beyond the end of the existing array not supported */
711         nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fwrite");
712         return;
713     }
714
715     ix = posn / s->blk_len;
716     s->wptr = posn;
717     s->wpos = posn % s->blk_len;
718     s->wblk = &s->blk_ptrs[ix];
719
720     if (!s->wpos) {
721         s->wpos = s->blk_len;
722         s->wblk--;
723     }
724
725     saa_wbytes(s, data, len);
726 }
727
728 void saa_fpwrite(struct SAA *s, FILE * fp)
729 {
730     const char *data;
731     size_t len;
732
733     saa_rewind(s);
734     while (len = s->datalen, (data = saa_rbytes(s, &len)) != NULL)
735         fwrite(data, 1, len, fp);
736 }
737
738 /*
739  * Common list of prefix names
740  */
741 static const char *prefix_names[] = {
742     "a16", "a32", "lock", "o16", "o32", "rep", "repe", "repne",
743     "repnz", "repz", "times"
744 };
745
746 const char *prefix_name(int token)
747 {
748     unsigned int prefix = token-PREFIX_ENUM_START;
749     if (prefix > sizeof prefix_names / sizeof(const char *))
750         return NULL;
751
752     return prefix_names[prefix];
753 }
754
755 /*
756  * Binary search.
757  */
758 int bsi(char *string, const char **array, int size)
759 {
760     int i = -1, j = size;       /* always, i < index < j */
761     while (j - i >= 2) {
762         int k = (i + j) / 2;
763         int l = strcmp(string, array[k]);
764         if (l < 0)              /* it's in the first half */
765             j = k;
766         else if (l > 0)         /* it's in the second half */
767             i = k;
768         else                    /* we've got it :) */
769             return k;
770     }
771     return -1;                  /* we haven't got it :( */
772 }
773
774 int bsii(char *string, const char **array, int size)
775 {
776     int i = -1, j = size;       /* always, i < index < j */
777     while (j - i >= 2) {
778         int k = (i + j) / 2;
779         int l = nasm_stricmp(string, array[k]);
780         if (l < 0)              /* it's in the first half */
781             j = k;
782         else if (l > 0)         /* it's in the second half */
783             i = k;
784         else                    /* we've got it :) */
785             return k;
786     }
787     return -1;                  /* we haven't got it :( */
788 }
789
790 static char *file_name = NULL;
791 static int32_t line_number = 0;
792
793 char *src_set_fname(char *newname)
794 {
795     char *oldname = file_name;
796     file_name = newname;
797     return oldname;
798 }
799
800 int32_t src_set_linnum(int32_t newline)
801 {
802     int32_t oldline = line_number;
803     line_number = newline;
804     return oldline;
805 }
806
807 int32_t src_get_linnum(void)
808 {
809     return line_number;
810 }
811
812 int src_get(int32_t *xline, char **xname)
813 {
814     if (!file_name || !*xname || strcmp(*xname, file_name)) {
815         nasm_free(*xname);
816         *xname = file_name ? nasm_strdup(file_name) : NULL;
817         *xline = line_number;
818         return -2;
819     }
820     if (*xline != line_number) {
821         int32_t tmp = line_number - *xline;
822         *xline = line_number;
823         return tmp;
824     }
825     return 0;
826 }
827
828 void nasm_quote(char **str)
829 {
830     int ln = strlen(*str);
831     char q = (*str)[0];
832     char *p;
833     if (ln > 1 && (*str)[ln - 1] == q && (q == '"' || q == '\''))
834         return;
835     q = '"';
836     if (strchr(*str, q))
837         q = '\'';
838     p = nasm_malloc(ln + 3);
839     strcpy(p + 1, *str);
840     nasm_free(*str);
841     p[ln + 1] = p[0] = q;
842     p[ln + 2] = 0;
843     *str = p;
844 }
845
846 char *nasm_strcat(char *one, char *two)
847 {
848     char *rslt;
849     int l1 = strlen(one);
850     rslt = nasm_malloc(l1 + strlen(two) + 1);
851     strcpy(rslt, one);
852     strcpy(rslt + l1, two);
853     return rslt;
854 }
855
856 void null_debug_init(struct ofmt *of, void *id, FILE * fp, efunc error)
857 {
858         (void)of;
859         (void)id;
860         (void)fp;
861         (void)error;
862 }
863 void null_debug_linenum(const char *filename, int32_t linenumber, int32_t segto)
864 {
865         (void)filename;
866         (void)linenumber;
867         (void)segto;    
868 }
869 void null_debug_deflabel(char *name, int32_t segment, int32_t offset,
870                          int is_global, char *special)
871 {
872         (void)name;
873         (void)segment;
874         (void)offset;
875         (void)is_global;
876         (void)special;
877 }
878 void null_debug_routine(const char *directive, const char *params)
879 {
880         (void)directive;
881         (void)params;
882 }
883 void null_debug_typevalue(int32_t type)
884 {
885         (void)type;
886 }
887 void null_debug_output(int type, void *param)
888 {
889         (void)type;
890         (void)param;
891 }
892 void null_debug_cleanup(void)
893 {
894 }
895
896 struct dfmt null_debug_form = {
897     "Null debug format",
898     "null",
899     null_debug_init,
900     null_debug_linenum,
901     null_debug_deflabel,
902     null_debug_routine,
903     null_debug_typevalue,
904     null_debug_output,
905     null_debug_cleanup
906 };
907
908 struct dfmt *null_debug_arr[2] = { &null_debug_form, NULL };