"const"-ipation fixes from Trevor Woerner
[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 <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13
14 #include "nasm.h"
15 #include "nasmlib.h"
16
17 static efunc nasm_malloc_error;
18
19 #ifdef LOGALLOC
20 static FILE *logfp;
21 #endif
22
23 void nasm_set_malloc_error (efunc error) 
24 {
25     nasm_malloc_error = error;
26 #ifdef LOGALLOC
27     logfp = fopen ("malloc.log", "w");
28     setvbuf (logfp, NULL, _IOLBF, BUFSIZ);
29     fprintf (logfp, "null pointer is %p\n", NULL);
30 #endif
31 }
32
33 #ifdef LOGALLOC
34 void *nasm_malloc_log (char *file, int line, size_t size)
35 #else
36 void *nasm_malloc (size_t size)
37 #endif
38 {
39     void *p = malloc(size);
40     if (!p)
41         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
42 #ifdef LOGALLOC
43     else
44         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
45                 file, line, (long)size, p);
46 #endif
47     return p;
48 }
49
50 #ifdef LOGALLOC
51 void *nasm_realloc_log (char *file, int line, void *q, size_t size)
52 #else
53 void *nasm_realloc (void *q, size_t size)
54 #endif
55 {
56     void *p = q ? realloc(q, size) : malloc(size);
57     if (!p)
58         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
59 #ifdef LOGALLOC
60     else if (q)
61         fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
62                 file, line, q, (long)size, p);
63     else
64         fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
65                 file, line, (long)size, p);
66 #endif
67     return p;
68 }
69
70 #ifdef LOGALLOC
71 void nasm_free_log (char *file, int line, void *q)
72 #else
73 void nasm_free (void *q)
74 #endif
75 {
76     if (q) {
77         free (q);
78 #ifdef LOGALLOC
79         fprintf(logfp, "%s %d free(%p)\n",
80                 file, line, q);
81 #endif
82     }
83 }
84
85 #ifdef LOGALLOC
86 char *nasm_strdup_log (char *file, int line, const char *s)
87 #else
88 char *nasm_strdup (const char *s)
89 #endif
90 {
91     char *p;
92     int size = strlen(s)+1;
93
94     p = malloc(size);
95     if (!p)
96         nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
97 #ifdef LOGALLOC
98     else
99         fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
100                 file, line, (long)size, p);
101 #endif
102     strcpy (p, s);
103     return p;
104 }
105
106 #ifdef LOGALLOC
107 char *nasm_strndup_log (char *file, int line, char *s, size_t len)
108 #else
109 char *nasm_strndup (char *s, size_t len)
110 #endif
111 {
112     char *p;
113     int size = len+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 strndup(%ld) returns %p\n",
121                 file, line, (long)size, p);
122 #endif
123     strncpy (p, s, len);
124     p[len] = '\0';
125     return p;
126 }
127
128 #if !defined(stricmp) && !defined(strcasecmp)
129 int nasm_stricmp (const char *s1, const char *s2) 
130 {
131     while (*s1 && tolower(*s1) == tolower(*s2))
132         s1++, s2++;
133     if (!*s1 && !*s2)
134         return 0;
135     else if (tolower(*s1) < tolower(*s2))
136         return -1;
137     else
138         return 1;
139 }
140 #endif
141
142 #if !defined(strnicmp) && !defined(strncasecmp)
143 int nasm_strnicmp (const char *s1, const char *s2, int n) 
144 {
145     while (n > 0 && *s1 && tolower(*s1) == tolower(*s2))
146         s1++, s2++, n--;
147     if ((!*s1 && !*s2) || n==0)
148         return 0;
149     else if (tolower(*s1) < tolower(*s2))
150         return -1;
151     else
152         return 1;
153 }
154 #endif
155
156 #define lib_isnumchar(c)   ( isalnum(c) || (c) == '$')
157 #define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
158
159 long readnum (char *str, int *error) 
160 {
161     char *r = str, *q;
162     long radix;
163     unsigned long result, checklimit;
164     int digit, last;
165     int warn = FALSE;
166     int sign = 1;
167
168     *error = FALSE;
169
170     while (isspace(*r)) r++;           /* find start of number */
171
172     /*
173      * If the number came from make_tok_num (as a result of an %assign), it
174      * might have a '-' built into it (rather than in a preceeding token).
175      */
176     if (*r == '-')
177     {
178         r++;
179         sign = -1;
180     }
181
182     q = r;
183
184     while (lib_isnumchar(*q)) q++;     /* find end of number */
185
186     /*
187      * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
188      * ends in Q, it's octal. if it ends in B, it's binary.
189      * Otherwise, it's ordinary decimal.
190      */
191     if (*r=='0' && (r[1]=='x' || r[1]=='X'))
192         radix = 16, r += 2;
193     else if (*r=='$')
194         radix = 16, r++;
195     else if (q[-1]=='H' || q[-1]=='h')
196         radix = 16 , q--;
197     else if (q[-1]=='Q' || q[-1]=='q')
198         radix = 8 , q--;
199     else if (q[-1]=='B' || q[-1]=='b')
200         radix = 2 , q--;
201     else
202         radix = 10;
203
204     /*
205      * If this number has been found for us by something other than
206      * the ordinary scanners, then it might be malformed by having
207      * nothing between the prefix and the suffix. Check this case
208      * now.
209      */
210     if (r >= q) {
211         *error = TRUE;
212         return 0;
213     }
214
215     /*
216      * `checklimit' must be 2**32 / radix. We can't do that in
217      * 32-bit arithmetic, which we're (probably) using, so we
218      * cheat: since we know that all radices we use are even, we
219      * can divide 2**31 by radix/2 instead.
220      */
221     checklimit = 0x80000000UL / (radix>>1);
222
223     /*
224      * Calculate the highest allowable value for the last digit
225      * of a 32 bit constant... in radix 10, it is 6, otherwise it is 0
226      */
227     last = (radix == 10 ? 6 : 0);
228
229     result = 0;
230     while (*r && r < q) {
231         if (*r<'0' || (*r>'9' && *r<'A') || (digit = numvalue(*r)) >= radix) 
232         {
233             *error = TRUE;
234             return 0;
235         }
236         if (result > checklimit ||
237             (result == checklimit && digit >= last))
238         {
239             warn = TRUE;
240         }
241
242         result = radix * result + digit;
243         r++;
244     }
245
246     if (warn)
247         nasm_malloc_error (ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
248                            "numeric constant %s does not fit in 32 bits",
249                            str);
250
251     return result*sign;
252 }
253
254 long readstrnum (char *str, int length, int *warn) 
255 {
256     long charconst = 0;
257     int i;
258
259     *warn = FALSE;
260
261     str += length;
262     for (i=0; i<length; i++) {
263         if (charconst & 0xff000000UL) {
264             *warn = TRUE;
265         }
266         charconst = (charconst<<8) + (unsigned char) *--str;
267     }
268     return charconst;
269 }
270
271 static long next_seg;
272
273 void seg_init(void) 
274 {
275     next_seg = 0;
276 }
277
278 long seg_alloc(void) 
279 {
280     return (next_seg += 2) - 2;
281 }
282
283 void fwriteshort (int data, FILE *fp) 
284 {
285     fputc ((int) (data & 255), fp);
286     fputc ((int) ((data >> 8) & 255), fp);
287 }
288
289 void fwritelong (long data, FILE *fp) 
290 {
291     fputc ((int) (data & 255), fp);
292     fputc ((int) ((data >> 8) & 255), fp);
293     fputc ((int) ((data >> 16) & 255), fp);
294     fputc ((int) ((data >> 24) & 255), fp);
295 }
296
297 void standard_extension (char *inname, char *outname, char *extension,
298                          efunc error) 
299 {
300     char *p, *q;
301
302     if (*outname)                      /* file name already exists, */
303         return;                        /* so do nothing */
304     q = inname;
305     p = outname;
306     while (*q) *p++ = *q++;            /* copy, and find end of string */
307     *p = '\0';                         /* terminate it */
308     while (p > outname && *--p != '.');/* find final period (or whatever) */
309     if (*p != '.') while (*p) p++;     /* go back to end if none found */
310     if (!strcmp(p, extension)) {       /* is the extension already there? */
311         if (*extension)
312             error(ERR_WARNING | ERR_NOFILE,
313                   "file name already ends in `%s': "
314                   "output will be in `nasm.out'",
315                   extension);
316         else
317             error(ERR_WARNING | ERR_NOFILE,
318                   "file name already has no extension: "
319                   "output will be in `nasm.out'");
320         strcpy(outname, "nasm.out");
321     } else
322         strcpy(p, extension);
323 }
324
325 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
326 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
327
328 #define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
329
330 static struct RAA *real_raa_init (int layers) 
331 {
332     struct RAA *r;
333     int i;
334
335     if (layers == 0) {
336         r = nasm_malloc (LEAFSIZ);
337         r->layers = 0;
338         memset (r->u.l.data, 0, sizeof(r->u.l.data));
339         r->stepsize = 1L;
340     } else {
341         r = nasm_malloc (BRANCHSIZ);
342         r->layers = layers;
343         for ( i = 0 ; i < RAA_LAYERSIZE ; i++ )
344           r->u.b.data[i] = NULL;
345         r->stepsize = RAA_BLKSIZE;
346         while (--layers)
347             r->stepsize *= RAA_LAYERSIZE;
348     }
349     return r;
350 }
351
352 struct RAA *raa_init (void) 
353 {
354     return real_raa_init (0);
355 }
356
357 void raa_free (struct RAA *r) 
358 {
359     if (r->layers == 0)
360         nasm_free (r);
361     else {
362         struct RAA **p;
363         for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++)
364             if (*p)
365                 raa_free (*p);
366     }
367 }
368
369 long raa_read (struct RAA *r, long posn) 
370 {
371     if (posn > r->stepsize * LAYERSIZ(r))
372         return 0;               /* Return 0 for undefined entries */
373     while (r->layers > 0) {
374         ldiv_t l;
375         l = ldiv (posn, r->stepsize);
376         r = r->u.b.data[l.quot];
377         posn = l.rem;
378         if (!r)
379             return 0;           /* Return 0 for undefined entries */
380     }
381     return r->u.l.data[posn];
382 }
383
384 struct RAA *raa_write (struct RAA *r, long posn, long value) 
385 {
386     struct RAA *result;
387
388     if (posn < 0)
389         nasm_malloc_error (ERR_PANIC, "negative position in raa_write");
390
391     while (r->stepsize * LAYERSIZ(r) < posn) {
392         /*
393          * Must add a layer.
394          */
395         struct RAA *s;
396         int i;
397
398         s = nasm_malloc (BRANCHSIZ);
399         for ( i = 0 ; i < RAA_LAYERSIZE ; i++ )
400             s->u.b.data[i] = NULL;
401         s->layers = r->layers + 1;
402         s->stepsize = LAYERSIZ(r) * r->stepsize;
403         s->u.b.data[0] = r;
404         r = s;
405     }
406
407     result = r;
408
409     while (r->layers > 0) {
410         ldiv_t l;
411         struct RAA **s;
412         l = ldiv (posn, r->stepsize);
413         s = &r->u.b.data[l.quot];
414         if (!*s)
415             *s = real_raa_init (r->layers - 1);
416         r = *s;
417         posn = l.rem;
418     }
419
420     r->u.l.data[posn] = value;
421
422     return result;
423 }
424
425 #define SAA_MAXLEN 8192
426
427 struct SAA *saa_init (long elem_len) 
428 {
429     struct SAA *s;
430
431     if (elem_len > SAA_MAXLEN)
432         nasm_malloc_error (ERR_PANIC | ERR_NOFILE, "SAA with huge elements");
433
434     s = nasm_malloc (sizeof(struct SAA));
435     s->posn = s->start = 0L;
436     s->elem_len = elem_len;
437     s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len);
438     s->data = nasm_malloc (s->length);
439     s->next = NULL;
440     s->end = s;
441
442     return s;
443 }
444
445 void saa_free (struct SAA *s) 
446 {
447     struct SAA *t;
448
449     while (s) {
450         t = s->next;
451         nasm_free (s->data);
452         nasm_free (s);
453         s = t;
454     }
455 }
456
457 void *saa_wstruct (struct SAA *s) 
458 {
459     void *p;
460
461     if (s->end->length - s->end->posn < s->elem_len) {
462         s->end->next = nasm_malloc (sizeof(struct SAA));
463         s->end->next->start = s->end->start + s->end->posn;
464         s->end = s->end->next;
465         s->end->length = s->length;
466         s->end->next = NULL;
467         s->end->posn = 0L;
468         s->end->data = nasm_malloc (s->length);
469     }
470
471     p = s->end->data + s->end->posn;
472     s->end->posn += s->elem_len;
473     return p;
474 }
475
476 void saa_wbytes (struct SAA *s, const void *data, long len) 
477 {
478     const char *d = data;
479
480     while (len > 0) {
481         long l = s->end->length - s->end->posn;
482         if (l > len)
483             l = len;
484         if (l > 0) {
485             if (d) {
486                 memcpy (s->end->data + s->end->posn, d, l);
487                 d += l;
488             } else
489                 memset (s->end->data + s->end->posn, 0, l);
490             s->end->posn += l;
491             len -= l;
492         }
493         if (len > 0) {
494             s->end->next = nasm_malloc (sizeof(struct SAA));
495             s->end->next->start = s->end->start + s->end->posn;
496             s->end = s->end->next;
497             s->end->length = s->length;
498             s->end->next = NULL;
499             s->end->posn = 0L;
500             s->end->data = nasm_malloc (s->length);
501         }
502     }
503 }
504
505 void saa_rewind (struct SAA *s) 
506 {
507     s->rptr = s;
508     s->rpos = 0L;
509 }
510
511 void *saa_rstruct (struct SAA *s) 
512 {
513     void *p;
514
515     if (!s->rptr)
516         return NULL;
517
518     if (s->rptr->posn - s->rpos < s->elem_len) {
519         s->rptr = s->rptr->next;
520         if (!s->rptr)
521             return NULL;               /* end of array */
522         s->rpos = 0L;
523     }
524
525     p = s->rptr->data + s->rpos;
526     s->rpos += s->elem_len;
527     return p;
528 }
529
530 void *saa_rbytes (struct SAA *s, long *len) 
531 {
532     void *p;
533
534     if (!s->rptr)
535         return NULL;
536
537     p = s->rptr->data + s->rpos;
538     *len = s->rptr->posn - s->rpos;
539     s->rptr = s->rptr->next;
540     s->rpos = 0L;
541     return p;
542 }
543
544 void saa_rnbytes (struct SAA *s, void *data, long len) 
545 {
546     char *d = data;
547
548     while (len > 0) {
549         long l;
550
551         if (!s->rptr)
552             return;
553
554         l = s->rptr->posn - s->rpos;
555         if (l > len)
556             l = len;
557         if (l > 0) {
558             memcpy (d, s->rptr->data + s->rpos, l);
559             d += l;
560             s->rpos += l;
561             len -= l;
562         }
563         if (len > 0) {
564             s->rptr = s->rptr->next;
565             s->rpos = 0L;
566         }
567     }
568 }
569
570 void saa_fread (struct SAA *s, long posn, void *data, long len) 
571 {
572     struct SAA *p;
573     long pos;
574     char *cdata = data;
575
576     if (!s->rptr || posn < s->rptr->start)
577         saa_rewind (s);
578     p = s->rptr;
579     while (posn >= p->start + p->posn) {
580         p = p->next;
581         if (!p)
582             return;                    /* what else can we do?! */
583     }
584
585     pos = posn - p->start;
586     while (len) {
587         long l = p->posn - pos;
588         if (l > len)
589             l = len;
590         memcpy (cdata, p->data+pos, l);
591         len -= l;
592         cdata += l;
593         p = p->next;
594         if (!p)
595             return;
596         pos = 0L;
597     }
598     s->rptr = p;
599 }
600
601 void saa_fwrite (struct SAA *s, long posn, void *data, long len) 
602 {
603     struct SAA *p;
604     long pos;
605     char *cdata = data;
606
607     if (!s->rptr || posn < s->rptr->start)
608         saa_rewind (s);
609     p = s->rptr;
610     while (posn >= p->start + p->posn) {
611         p = p->next;
612         if (!p)
613             return;                    /* what else can we do?! */
614     }
615
616     pos = posn - p->start;
617     while (len) {
618         long l = p->posn - pos;
619         if (l > len)
620             l = len;
621         memcpy (p->data+pos, cdata, l);
622         len -= l;
623         cdata += l;
624         p = p->next;
625         if (!p)
626             return;
627         pos = 0L;
628     }
629     s->rptr = p;
630 }
631
632 void saa_fpwrite (struct SAA *s, FILE *fp) 
633 {
634     char *data;
635     long len;
636
637     saa_rewind (s);
638     while ( (data = saa_rbytes (s, &len)) )
639         fwrite (data, 1, len, fp);
640 }
641
642 /*
643  * Register, instruction, condition-code and prefix keywords used
644  * by the scanner.
645  */
646 #include "names.c"
647 static const char *special_names[] = {
648     "byte", "dword", "far", "long", "near", "nosplit", "qword",
649     "short", "strict", "to", "tword", "word"
650 };
651 static const char *prefix_names[] = {
652     "a16", "a32", "lock", "o16", "o32", "rep", "repe", "repne",
653     "repnz", "repz", "times"
654 };
655
656
657 /*
658  * Standard scanner routine used by parser.c and some output
659  * formats. It keeps a succession of temporary-storage strings in
660  * stdscan_tempstorage, which can be cleared using stdscan_reset.
661  */
662 static char **stdscan_tempstorage = NULL;
663 static int stdscan_tempsize = 0, stdscan_templen = 0;
664 #define STDSCAN_TEMP_DELTA 256
665
666 static void stdscan_pop(void) 
667 {
668     nasm_free (stdscan_tempstorage[--stdscan_templen]);
669 }
670
671 void stdscan_reset(void) 
672 {
673     while (stdscan_templen > 0)
674         stdscan_pop();
675 }
676
677 /*
678  * Unimportant cleanup is done to avoid confusing people who are trying
679  * to debug real memory leaks
680  */
681 void nasmlib_cleanup (void) 
682 {
683     stdscan_reset();
684     nasm_free (stdscan_tempstorage);
685 }
686
687 static char *stdscan_copy(char *p, int len) 
688 {
689     char *text;
690
691     text = nasm_malloc(len+1);
692     strncpy (text, p, len);
693     text[len] = '\0';
694
695     if (stdscan_templen >= stdscan_tempsize) {
696         stdscan_tempsize += STDSCAN_TEMP_DELTA;
697         stdscan_tempstorage = nasm_realloc(stdscan_tempstorage,
698                                            stdscan_tempsize*sizeof(char *));
699     }
700     stdscan_tempstorage[stdscan_templen++] = text;
701
702     return text;
703 }
704
705 char *stdscan_bufptr = NULL;
706 int stdscan (void *private_data, struct tokenval *tv) 
707 {
708     char ourcopy[MAX_KEYWORD+1], *r, *s;
709
710     (void) private_data;  /* Don't warn that this parameter is unused */
711
712     while (isspace(*stdscan_bufptr)) stdscan_bufptr++;
713     if (!*stdscan_bufptr)
714         return tv->t_type = 0;
715
716     /* we have a token; either an id, a number or a char */
717     if (isidstart(*stdscan_bufptr) ||
718         (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1]))) {
719         /* now we've got an identifier */
720         int i;
721         int is_sym = FALSE;
722
723         if (*stdscan_bufptr == '$') {
724             is_sym = TRUE;
725             stdscan_bufptr++;
726         }
727
728         r = stdscan_bufptr++;
729         while (isidchar(*stdscan_bufptr)) stdscan_bufptr++;
730         tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
731
732         if (is_sym || stdscan_bufptr-r > MAX_KEYWORD)
733             return tv->t_type = TOKEN_ID;/* bypass all other checks */
734     
735         for (s=tv->t_charptr, r=ourcopy; *s; s++)
736             *r++ = tolower (*s);
737         *r = '\0';
738         /* right, so we have an identifier sitting in temp storage. now,
739          * is it actually a register or instruction name, or what? */
740         if ((tv->t_integer=bsi(ourcopy, reg_names,
741                                elements(reg_names)))>=0) {
742             tv->t_integer += EXPR_REG_START;
743             return tv->t_type = TOKEN_REG;
744         } else if ((tv->t_integer=bsi(ourcopy, insn_names,
745                                       elements(insn_names)))>=0) {
746             return tv->t_type = TOKEN_INSN;
747         }
748         for (i=0; i<elements(icn); i++)
749             if (!strncmp(ourcopy, icn[i], strlen(icn[i]))) {
750                 char *p = ourcopy + strlen(icn[i]);
751                 tv->t_integer = ico[i];
752                 if ((tv->t_inttwo=bsi(p, conditions,
753                                          elements(conditions)))>=0)
754                     return tv->t_type = TOKEN_INSN;
755             }
756         if ((tv->t_integer=bsi(ourcopy, prefix_names,
757                                   elements(prefix_names)))>=0) {
758             tv->t_integer += PREFIX_ENUM_START;
759             return tv->t_type = TOKEN_PREFIX;
760         }
761         if ((tv->t_integer=bsi(ourcopy, special_names,
762                                   elements(special_names)))>=0)
763             return tv->t_type = TOKEN_SPECIAL;
764         if (!nasm_stricmp(ourcopy, "seg"))
765             return tv->t_type = TOKEN_SEG;
766         if (!nasm_stricmp(ourcopy, "wrt"))
767             return tv->t_type = TOKEN_WRT;
768         return tv->t_type = TOKEN_ID;
769     } else if (*stdscan_bufptr == '$' && !isnumchar(stdscan_bufptr[1])) {
770         /*
771          * It's a $ sign with no following hex number; this must
772          * mean it's a Here token ($), evaluating to the current
773          * assembly location, or a Base token ($$), evaluating to
774          * the base of the current segment.
775          */
776         stdscan_bufptr++;
777         if (*stdscan_bufptr == '$') {
778             stdscan_bufptr++;
779             return tv->t_type = TOKEN_BASE;
780         }
781         return tv->t_type = TOKEN_HERE;
782     } else if (isnumstart(*stdscan_bufptr)) {  /* now we've got a number */
783         int rn_error;
784
785         r = stdscan_bufptr++;
786         while (isnumchar(*stdscan_bufptr))
787             stdscan_bufptr++;
788
789         if (*stdscan_bufptr == '.') {
790             /*
791              * a floating point constant
792              */
793             stdscan_bufptr++;
794             while (isnumchar(*stdscan_bufptr) ||
795                    ((stdscan_bufptr[-1] == 'e' || stdscan_bufptr[-1] == 'E')
796                     && (*stdscan_bufptr == '-' || *stdscan_bufptr == '+')) ) 
797             {
798                 stdscan_bufptr++;
799             }
800             tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
801             return tv->t_type = TOKEN_FLOAT;
802         }
803         r = stdscan_copy(r, stdscan_bufptr - r);
804         tv->t_integer = readnum(r, &rn_error);
805         stdscan_pop();
806         if (rn_error)
807             return tv->t_type = TOKEN_ERRNUM;/* some malformation occurred */
808         tv->t_charptr = NULL;
809         return tv->t_type = TOKEN_NUM;
810     } else if (*stdscan_bufptr == '\'' ||
811                *stdscan_bufptr == '"') {/* a char constant */
812         char quote = *stdscan_bufptr++, *r;
813         int rn_warn;
814         r = tv->t_charptr = stdscan_bufptr;
815         while (*stdscan_bufptr && *stdscan_bufptr != quote) stdscan_bufptr++;
816         tv->t_inttwo = stdscan_bufptr - r;      /* store full version */
817         if (!*stdscan_bufptr)
818             return tv->t_type = TOKEN_ERRNUM;       /* unmatched quotes */
819         stdscan_bufptr++;                       /* skip over final quote */
820         tv->t_integer = readstrnum(r, tv->t_inttwo, &rn_warn);
821         /* FIXME: rn_warn is not checked! */
822         return tv->t_type = TOKEN_NUM;
823     } else if (*stdscan_bufptr == ';') {  /* a comment has happened - stay */
824         return tv->t_type = 0;
825     } else if (stdscan_bufptr[0] == '>' && stdscan_bufptr[1] == '>') {
826         stdscan_bufptr += 2;
827         return tv->t_type = TOKEN_SHR;
828     } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '<') {
829         stdscan_bufptr += 2;
830         return tv->t_type = TOKEN_SHL;
831     } else if (stdscan_bufptr[0] == '/' && stdscan_bufptr[1] == '/') {
832         stdscan_bufptr += 2;
833         return tv->t_type = TOKEN_SDIV;
834     } else if (stdscan_bufptr[0] == '%' && stdscan_bufptr[1] == '%') {
835         stdscan_bufptr += 2;
836         return tv->t_type = TOKEN_SMOD;
837     } else if (stdscan_bufptr[0] == '=' && stdscan_bufptr[1] == '=') {
838         stdscan_bufptr += 2;
839         return tv->t_type = TOKEN_EQ;
840     } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '>') {
841         stdscan_bufptr += 2;
842         return tv->t_type = TOKEN_NE;
843     } else if (stdscan_bufptr[0] == '!' && stdscan_bufptr[1] == '=') {
844         stdscan_bufptr += 2;
845         return tv->t_type = TOKEN_NE;
846     } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '=') {
847         stdscan_bufptr += 2;
848         return tv->t_type = TOKEN_LE;
849     } else if (stdscan_bufptr[0] == '>' && stdscan_bufptr[1] == '=') {
850         stdscan_bufptr += 2;
851         return tv->t_type = TOKEN_GE;
852     } else if (stdscan_bufptr[0] == '&' && stdscan_bufptr[1] == '&') {
853         stdscan_bufptr += 2;
854         return tv->t_type = TOKEN_DBL_AND;
855     } else if (stdscan_bufptr[0] == '^' && stdscan_bufptr[1] == '^') {
856         stdscan_bufptr += 2;
857         return tv->t_type = TOKEN_DBL_XOR;
858     } else if (stdscan_bufptr[0] == '|' && stdscan_bufptr[1] == '|') {
859         stdscan_bufptr += 2;
860         return tv->t_type = TOKEN_DBL_OR;
861     } else                             /* just an ordinary char */
862         return tv->t_type = (unsigned char) (*stdscan_bufptr++);
863 }
864
865 /*
866  * Return TRUE if the argument is a simple scalar. (Or a far-
867  * absolute, which counts.)
868  */
869 int is_simple (expr *vect) 
870 {
871     while (vect->type && !vect->value)
872         vect++;
873     if (!vect->type)
874         return 1;
875     if (vect->type != EXPR_SIMPLE)
876         return 0;
877     do {
878         vect++;
879     } while (vect->type && !vect->value);
880     if (vect->type && vect->type < EXPR_SEGBASE+SEG_ABS) return 0;
881     return 1;
882 }
883
884 /*
885  * Return TRUE if the argument is a simple scalar, _NOT_ a far-
886  * absolute.
887  */
888 int is_really_simple (expr *vect) 
889 {
890     while (vect->type && !vect->value)
891         vect++;
892     if (!vect->type)
893         return 1;
894     if (vect->type != EXPR_SIMPLE)
895         return 0;
896     do {
897         vect++;
898     } while (vect->type && !vect->value);
899     if (vect->type) return 0;
900     return 1;
901 }
902
903 /*
904  * Return TRUE if the argument is relocatable (i.e. a simple
905  * scalar, plus at most one segment-base, plus possibly a WRT).
906  */
907 int is_reloc (expr *vect) 
908 {
909     while (vect->type && !vect->value) /* skip initial value-0 terms */
910         vect++;
911     if (!vect->type)                   /* trivially return TRUE if nothing */
912         return 1;                      /* is present apart from value-0s */
913     if (vect->type < EXPR_SIMPLE)      /* FALSE if a register is present */
914         return 0;
915     if (vect->type == EXPR_SIMPLE) {   /* skip over a pure number term... */
916         do {
917             vect++;
918         } while (vect->type && !vect->value);
919         if (!vect->type)               /* ...returning TRUE if that's all */
920             return 1;
921     }
922     if (vect->type == EXPR_WRT) {      /* skip over a WRT term... */
923         do {
924             vect++;
925         } while (vect->type && !vect->value);
926         if (!vect->type)               /* ...returning TRUE if that's all */
927             return 1;
928     }
929     if (vect->value != 0 && vect->value != 1)
930         return 0;                      /* segment base multiplier non-unity */
931     do {                               /* skip over _one_ seg-base term... */
932         vect++;
933     } while (vect->type && !vect->value);
934     if (!vect->type)                   /* ...returning TRUE if that's all */
935         return 1;
936     return 0;                          /* And return FALSE if there's more */
937 }
938
939 /*
940  * Return TRUE if the argument contains an `unknown' part.
941  */
942 int is_unknown(expr *vect) 
943 {
944     while (vect->type && vect->type < EXPR_UNKNOWN)
945         vect++;
946     return (vect->type == EXPR_UNKNOWN);
947 }
948
949 /*
950  * Return TRUE if the argument contains nothing but an `unknown'
951  * part.
952  */
953 int is_just_unknown(expr *vect) 
954 {
955     while (vect->type && !vect->value)
956         vect++;
957     return (vect->type == EXPR_UNKNOWN);
958 }
959
960 /*
961  * Return the scalar part of a relocatable vector. (Including
962  * simple scalar vectors - those qualify as relocatable.)
963  */
964 long reloc_value (expr *vect) 
965 {
966     while (vect->type && !vect->value)
967         vect++;
968     if (!vect->type) return 0;
969     if (vect->type == EXPR_SIMPLE)
970         return vect->value;
971     else
972         return 0;
973 }
974
975 /*
976  * Return the segment number of a relocatable vector, or NO_SEG for
977  * simple scalars.
978  */
979 long reloc_seg (expr *vect) 
980 {
981     while (vect->type && (vect->type == EXPR_WRT || !vect->value))
982         vect++;
983     if (vect->type == EXPR_SIMPLE) {
984         do {
985             vect++;
986         } while (vect->type && (vect->type == EXPR_WRT || !vect->value));
987     }
988     if (!vect->type)
989         return NO_SEG;
990     else
991         return vect->type - EXPR_SEGBASE;
992 }
993
994 /*
995  * Return the WRT segment number of a relocatable vector, or NO_SEG
996  * if no WRT part is present.
997  */
998 long reloc_wrt (expr *vect) 
999 {
1000     while (vect->type && vect->type < EXPR_WRT)
1001         vect++;
1002     if (vect->type == EXPR_WRT) {
1003         return vect->value;
1004     } else
1005         return NO_SEG;
1006 }
1007
1008 /*
1009  * Binary search.
1010  */
1011 int bsi (char *string, const char **array, int size) 
1012 {
1013     int i = -1, j = size;              /* always, i < index < j */
1014     while (j-i >= 2) {
1015         int k = (i+j)/2;
1016         int l = strcmp(string, array[k]);
1017         if (l<0)                       /* it's in the first half */
1018             j = k;
1019         else if (l>0)                  /* it's in the second half */
1020             i = k;
1021         else                           /* we've got it :) */
1022             return k;
1023     }
1024     return -1;                         /* we haven't got it :( */
1025 }
1026
1027 static char *file_name = NULL;
1028 static long line_number = 0;
1029
1030 char *src_set_fname(char *newname) 
1031 {
1032     char *oldname = file_name;
1033     file_name = newname;
1034     return oldname;
1035 }
1036
1037 long src_set_linnum(long newline) 
1038 {
1039     long oldline = line_number;
1040     line_number = newline;
1041     return oldline;
1042 }
1043
1044 long src_get_linnum(void) 
1045 {
1046     return line_number;
1047 }
1048
1049 int src_get(long *xline, char **xname) 
1050 {
1051     if (!file_name || !*xname || strcmp(*xname, file_name)) 
1052     {
1053         nasm_free(*xname);
1054         *xname = file_name ? nasm_strdup(file_name) : NULL;
1055         *xline = line_number;
1056         return -2;
1057     }
1058     if (*xline != line_number) 
1059     {
1060         long tmp = line_number - *xline;
1061         *xline = line_number;
1062         return tmp;
1063     }
1064     return 0;
1065 }
1066
1067 void nasm_quote(char **str) 
1068 {
1069     int ln=strlen(*str);
1070     char q=(*str)[0];
1071     char *p;
1072     if (ln>1 && (*str)[ln-1]==q && (q=='"' || q=='\''))
1073         return;
1074     q = '"';
1075     if (strchr(*str,q))
1076         q = '\'';
1077     p = nasm_malloc(ln+3);
1078     strcpy(p+1, *str);
1079     nasm_free(*str);
1080     p[ln+1] = p[0] = q;
1081     p[ln+2] = 0;
1082     *str = p;
1083 }
1084     
1085 char *nasm_strcat(char *one, char *two) 
1086 {
1087     char *rslt;
1088     int l1=strlen(one);
1089     rslt = nasm_malloc(l1+strlen(two)+1);
1090     strcpy(rslt, one);
1091     strcpy(rslt+l1, two);
1092     return rslt;
1093 }
1094
1095 void null_debug_init(struct ofmt *of, void *id, FILE *fp, efunc error ) {}
1096 void null_debug_linenum(const char *filename, long linenumber, long segto) {}
1097 void null_debug_deflabel(char *name, long segment, long offset, int is_global, char *special) {}
1098 void null_debug_routine(const char *directive, const char *params) {}
1099 void null_debug_typevalue(long type) {}
1100 void null_debug_output(int type, void *param) {}
1101 void null_debug_cleanup(void){}
1102
1103 struct dfmt null_debug_form = {
1104     "Null debug format",
1105     "null",
1106     null_debug_init,
1107     null_debug_linenum,
1108     null_debug_deflabel,
1109     null_debug_routine,
1110     null_debug_typevalue,
1111     null_debug_output,
1112     null_debug_cleanup
1113 };
1114
1115 struct dfmt *null_debug_arr[2] = { &null_debug_form, NULL };