]> git.saurik.com Git - apple/boot.git/blob - i386/nasm/nasmlib.c
boot-111.tar.gz
[apple/boot.git] / i386 / nasm / nasmlib.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* nasmlib.c library routines for the Netwide Assembler
26 *
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "nasm.h"
39 #include "nasmlib.h"
40
41 static efunc nasm_malloc_error;
42
43 #ifdef LOGALLOC
44 static FILE *logfp;
45 #endif
46
47 void nasm_set_malloc_error (efunc error) {
48 nasm_malloc_error = error;
49 #ifdef LOGALLOC
50 logfp = fopen ("malloc.log", "w");
51 setvbuf (logfp, NULL, _IOLBF, BUFSIZ);
52 fprintf (logfp, "null pointer is %p\n", NULL);
53 #endif
54 }
55
56 #ifdef LOGALLOC
57 void *nasm_malloc_log (char *file, int line, size_t size)
58 #else
59 void *nasm_malloc (size_t size)
60 #endif
61 {
62 void *p = malloc(size);
63 if (!p)
64 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
65 #ifdef LOGALLOC
66 else
67 fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
68 file, line, (long)size, p);
69 #endif
70 return p;
71 }
72
73 #ifdef LOGALLOC
74 void *nasm_realloc_log (char *file, int line, void *q, size_t size)
75 #else
76 void *nasm_realloc (void *q, size_t size)
77 #endif
78 {
79 void *p = q ? realloc(q, size) : malloc(size);
80 if (!p)
81 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
82 #ifdef LOGALLOC
83 else if (q)
84 fprintf(logfp, "%s %d realloc(%p,%ld) returns %p\n",
85 file, line, q, (long)size, p);
86 else
87 fprintf(logfp, "%s %d malloc(%ld) returns %p\n",
88 file, line, (long)size, p);
89 #endif
90 return p;
91 }
92
93 #ifdef LOGALLOC
94 void nasm_free_log (char *file, int line, void *q)
95 #else
96 void nasm_free (void *q)
97 #endif
98 {
99 if (q) {
100 free (q);
101 #ifdef LOGALLOC
102 fprintf(logfp, "%s %d free(%p)\n",
103 file, line, q);
104 #endif
105 }
106 }
107
108 #ifdef LOGALLOC
109 char *nasm_strdup_log (char *file, int line, char *s)
110 #else
111 char *nasm_strdup (char *s)
112 #endif
113 {
114 char *p;
115 int size = strlen(s)+1;
116
117 p = malloc(size);
118 if (!p)
119 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
120 #ifdef LOGALLOC
121 else
122 fprintf(logfp, "%s %d strdup(%ld) returns %p\n",
123 file, line, (long)size, p);
124 #endif
125 strcpy (p, s);
126 return p;
127 }
128
129 #ifdef LOGALLOC
130 char *nasm_strndup_log (char *file, int line, char *s, size_t len)
131 #else
132 char *nasm_strndup (char *s, size_t len)
133 #endif
134 {
135 char *p;
136 int size = len+1;
137
138 p = malloc(size);
139 if (!p)
140 nasm_malloc_error (ERR_FATAL | ERR_NOFILE, "out of memory");
141 #ifdef LOGALLOC
142 else
143 fprintf(logfp, "%s %d strndup(%ld) returns %p\n",
144 file, line, (long)size, p);
145 #endif
146 strncpy (p, s, len);
147 p[len] = '\0';
148 return p;
149 }
150
151 int nasm_stricmp (char *s1, char *s2) {
152 while (*s1 && toupper(*s1) == toupper(*s2))
153 s1++, s2++;
154 if (!*s1 && !*s2)
155 return 0;
156 else if (toupper(*s1) < toupper(*s2))
157 return -1;
158 else
159 return 1;
160 }
161
162 int nasm_strnicmp (char *s1, char *s2, int n) {
163 while (n > 0 && *s1 && toupper(*s1) == toupper(*s2))
164 s1++, s2++, n--;
165 if ((!*s1 && !*s2) || n==0)
166 return 0;
167 else if (toupper(*s1) < toupper(*s2))
168 return -1;
169 else
170 return 1;
171 }
172
173 #define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
174 #define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
175
176 long readnum (char *str, int *error) {
177 char *r = str, *q;
178 long radix;
179 unsigned long result, checklimit;
180 int warn = FALSE;
181
182 *error = FALSE;
183
184 while (isspace(*r)) r++; /* find start of number */
185 q = r;
186
187 while (lib_isnumchar(*q)) q++; /* find end of number */
188
189 /*
190 * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
191 * ends in Q, it's octal. if it ends in B, it's binary.
192 * Otherwise, it's ordinary decimal.
193 */
194 if (*r=='0' && (r[1]=='x' || r[1]=='X'))
195 radix = 16, r += 2;
196 else if (*r=='$')
197 radix = 16, r++;
198 else if (q[-1]=='H' || q[-1]=='h')
199 radix = 16 , q--;
200 else if (q[-1]=='Q' || q[-1]=='q')
201 radix = 8 , q--;
202 else if (q[-1]=='B' || q[-1]=='b')
203 radix = 2 , q--;
204 else
205 radix = 10;
206
207 /*
208 * If this number has been found for us by something other than
209 * the ordinary scanners, then it might be malformed by having
210 * nothing between the prefix and the suffix. Check this case
211 * now.
212 */
213 if (r >= q) {
214 *error = TRUE;
215 return 0;
216 }
217
218 /*
219 * `checklimit' must be 2**32 / radix. We can't do that in
220 * 32-bit arithmetic, which we're (probably) using, so we
221 * cheat: since we know that all radices we use are even, we
222 * can divide 2**31 by radix/2 instead.
223 */
224 checklimit = 0x80000000UL / (radix>>1);
225
226 result = 0;
227 while (*r && r < q) {
228 if (*r<'0' || (*r>'9' && *r<'A') || numvalue(*r)>=radix) {
229 *error = TRUE;
230 return 0;
231 }
232 if (result >= checklimit)
233 warn = TRUE;
234 result = radix * result + numvalue(*r);
235 r++;
236 }
237
238 if (warn)
239 nasm_malloc_error (ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
240 "numeric constant %s does not fit in 32 bits",
241 str);
242
243 return result;
244 }
245
246 static long next_seg;
247
248 void seg_init(void) {
249 next_seg = 0;
250 }
251
252 long seg_alloc(void) {
253 return (next_seg += 2) - 2;
254 }
255
256 void fwriteshort (int data, FILE *fp) {
257 fputc ((int) (data & 255), fp);
258 fputc ((int) ((data >> 8) & 255), fp);
259 }
260
261 void fwritelong (long data, FILE *fp) {
262 fputc ((int) (data & 255), fp);
263 fputc ((int) ((data >> 8) & 255), fp);
264 fputc ((int) ((data >> 16) & 255), fp);
265 fputc ((int) ((data >> 24) & 255), fp);
266 }
267
268 void standard_extension (char *inname, char *outname, char *extension,
269 efunc error) {
270 char *p, *q;
271
272 if (*outname) /* file name already exists, */
273 return; /* so do nothing */
274 q = inname;
275 p = outname;
276 while (*q) *p++ = *q++; /* copy, and find end of string */
277 *p = '\0'; /* terminate it */
278 while (p > outname && *--p != '.');/* find final period (or whatever) */
279 if (*p != '.') while (*p) p++; /* go back to end if none found */
280 if (!strcmp(p, extension)) { /* is the extension already there? */
281 if (*extension)
282 error(ERR_WARNING | ERR_NOFILE,
283 "file name already ends in `%s': "
284 "output will be in `nasm.out'",
285 extension);
286 else
287 error(ERR_WARNING | ERR_NOFILE,
288 "file name already has no extension: "
289 "output will be in `nasm.out'");
290 strcpy(outname, "nasm.out");
291 } else
292 strcpy(p, extension);
293 }
294
295 #define RAA_BLKSIZE 4096 /* this many longs allocated at once */
296 #define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */
297
298 typedef struct RAA RAA;
299 typedef union RAA_UNION RAA_UNION;
300 typedef struct RAA_LEAF RAA_LEAF;
301 typedef struct RAA_BRANCH RAA_BRANCH;
302
303 struct RAA {
304 /*
305 * Number of layers below this one to get to the real data. 0
306 * means this structure is a leaf, holding RAA_BLKSIZE real
307 * data items; 1 and above mean it's a branch, holding
308 * RAA_LAYERSIZE pointers to the next level branch or leaf
309 * structures.
310 */
311 int layers;
312 /*
313 * Number of real data items spanned by one position in the
314 * `data' array at this level. This number is 1, trivially, for
315 * a leaf (level 0): for a level 1 branch it should be
316 * RAA_BLKSIZE, and for a level 2 branch it's
317 * RAA_LAYERSIZE*RAA_BLKSIZE.
318 */
319 long stepsize;
320 union RAA_UNION {
321 struct RAA_LEAF {
322 long data[RAA_BLKSIZE];
323 } l;
324 struct RAA_BRANCH {
325 struct RAA *data[RAA_LAYERSIZE];
326 } b;
327 } u;
328 };
329
330 #define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF))
331 #define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH))
332
333 #define LAYERSIZ(r) ( (r)->layers==0 ? RAA_BLKSIZE : RAA_LAYERSIZE )
334
335 static struct RAA *real_raa_init (int layers) {
336 struct RAA *r;
337
338 if (layers == 0) {
339 r = nasm_malloc (LEAFSIZ);
340 memset (r->u.l.data, 0, sizeof(r->u.l.data));
341 r->layers = 0;
342 r->stepsize = 1L;
343 } else {
344 r = nasm_malloc (BRANCHSIZ);
345 memset (r->u.b.data, 0, sizeof(r->u.b.data));
346 r->layers = layers;
347 r->stepsize = RAA_BLKSIZE;
348 while (--layers)
349 r->stepsize *= RAA_LAYERSIZE;
350 }
351 return r;
352 }
353
354 struct RAA *raa_init (void) {
355 return real_raa_init (0);
356 }
357
358 void raa_free (struct RAA *r) {
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 if (posn > r->stepsize * LAYERSIZ(r))
371 return 0L;
372 while (r->layers > 0) {
373 ldiv_t l;
374 l = ldiv (posn, r->stepsize);
375 r = r->u.b.data[l.quot];
376 posn = l.rem;
377 if (!r) /* better check this */
378 return 0L;
379 }
380 return r->u.l.data[posn];
381 }
382
383 struct RAA *raa_write (struct RAA *r, long posn, long value) {
384 struct RAA *result;
385
386 if (posn < 0)
387 nasm_malloc_error (ERR_PANIC, "negative position in raa_write");
388
389 while (r->stepsize * LAYERSIZ(r) < posn) {
390 /*
391 * Must go up a layer.
392 */
393 struct RAA *s;
394
395 s = nasm_malloc (BRANCHSIZ);
396 memset (s->u.b.data, 0, sizeof(r->u.b.data));
397 s->layers = r->layers + 1;
398 s->stepsize = RAA_LAYERSIZE * r->stepsize;
399 s->u.b.data[0] = r;
400 r = s;
401 }
402
403 result = r;
404
405 while (r->layers > 0) {
406 ldiv_t l;
407 struct RAA **s;
408 l = ldiv (posn, r->stepsize);
409 s = &r->u.b.data[l.quot];
410 if (!*s)
411 *s = real_raa_init (r->layers - 1);
412 r = *s;
413 posn = l.rem;
414 }
415
416 r->u.l.data[posn] = value;
417
418 return result;
419 }
420
421 #define SAA_MAXLEN 8192
422
423 struct SAA {
424 /*
425 * members `end' and `elem_len' are only valid in first link in
426 * list; `rptr' and `rpos' are used for reading
427 */
428 struct SAA *next, *end, *rptr;
429 long elem_len, length, posn, start, rpos;
430 char *data;
431 };
432
433 struct SAA *saa_init (long elem_len) {
434 struct SAA *s;
435
436 if (elem_len > SAA_MAXLEN)
437 nasm_malloc_error (ERR_PANIC | ERR_NOFILE, "SAA with huge elements");
438
439 s = nasm_malloc (sizeof(struct SAA));
440 s->posn = s->start = 0L;
441 s->elem_len = elem_len;
442 s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len);
443 s->data = nasm_malloc (s->length);
444 s->next = NULL;
445 s->end = s;
446
447 return s;
448 }
449
450 void saa_free (struct SAA *s) {
451 struct SAA *t;
452
453 while (s) {
454 t = s->next;
455 nasm_free (s->data);
456 nasm_free (s);
457 s = t;
458 }
459 }
460
461 void *saa_wstruct (struct SAA *s) {
462 void *p;
463
464 if (s->end->length - s->end->posn < s->elem_len) {
465 s->end->next = nasm_malloc (sizeof(struct SAA));
466 s->end->next->start = s->end->start + s->end->posn;
467 s->end = s->end->next;
468 s->end->length = s->length;
469 s->end->next = NULL;
470 s->end->posn = 0L;
471 s->end->data = nasm_malloc (s->length);
472 }
473
474 p = s->end->data + s->end->posn;
475 s->end->posn += s->elem_len;
476 return p;
477 }
478
479 void saa_wbytes (struct SAA *s, void *data, long len) {
480 char *d = data;
481
482 while (len > 0) {
483 long l = s->end->length - s->end->posn;
484 if (l > len)
485 l = len;
486 if (l > 0) {
487 if (d) {
488 memcpy (s->end->data + s->end->posn, d, l);
489 d += l;
490 } else
491 memset (s->end->data + s->end->posn, 0, l);
492 s->end->posn += l;
493 len -= l;
494 }
495 if (len > 0) {
496 s->end->next = nasm_malloc (sizeof(struct SAA));
497 s->end->next->start = s->end->start + s->end->posn;
498 s->end = s->end->next;
499 s->end->length = s->length;
500 s->end->next = NULL;
501 s->end->posn = 0L;
502 s->end->data = nasm_malloc (s->length);
503 }
504 }
505 }
506
507 void saa_rewind (struct SAA *s) {
508 s->rptr = s;
509 s->rpos = 0L;
510 }
511
512 void *saa_rstruct (struct SAA *s) {
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 void *p;
532
533 if (!s->rptr)
534 return NULL;
535
536 p = s->rptr->data + s->rpos;
537 *len = s->rptr->posn - s->rpos;
538 s->rptr = s->rptr->next;
539 s->rpos = 0L;
540 return p;
541 }
542
543 void saa_rnbytes (struct SAA *s, void *data, long len) {
544 char *d = data;
545
546 while (len > 0) {
547 long l;
548
549 if (!s->rptr)
550 return;
551
552 l = s->rptr->posn - s->rpos;
553 if (l > len)
554 l = len;
555 if (l > 0) {
556 memcpy (d, s->rptr->data + s->rpos, l);
557 d += l;
558 s->rpos += l;
559 len -= l;
560 }
561 if (len > 0) {
562 s->rptr = s->rptr->next;
563 s->rpos = 0L;
564 }
565 }
566 }
567
568 void saa_fread (struct SAA *s, long posn, void *data, long len) {
569 struct SAA *p;
570 long pos;
571 char *cdata = data;
572
573 if (!s->rptr || posn > s->rptr->start + s->rpos)
574 saa_rewind (s);
575 while (posn >= s->rptr->start + s->rptr->posn) {
576 s->rptr = s->rptr->next;
577 if (!s->rptr)
578 return; /* what else can we do?! */
579 }
580
581 p = s->rptr;
582 pos = posn - s->rptr->start;
583 while (len) {
584 long l = s->rptr->posn - pos;
585 if (l > len)
586 l = len;
587 memcpy (cdata, s->rptr->data+pos, l);
588 len -= l;
589 cdata += l;
590 p = p->next;
591 if (!p)
592 return;
593 pos = 0L;
594 }
595 }
596
597 void saa_fwrite (struct SAA *s, long posn, void *data, long len) {
598 struct SAA *p;
599 long pos;
600 char *cdata = data;
601
602 if (!s->rptr || posn > s->rptr->start + s->rpos)
603 saa_rewind (s);
604 while (posn >= s->rptr->start + s->rptr->posn) {
605 s->rptr = s->rptr->next;
606 if (!s->rptr)
607 return; /* what else can we do?! */
608 }
609
610 p = s->rptr;
611 pos = posn - s->rptr->start;
612 while (len) {
613 long l = s->rptr->posn - pos;
614 if (l > len)
615 l = len;
616 memcpy (s->rptr->data+pos, cdata, l);
617 len -= l;
618 cdata += l;
619 p = p->next;
620 if (!p)
621 return;
622 pos = 0L;
623 }
624 }
625
626 void saa_fpwrite (struct SAA *s, FILE *fp) {
627 char *data;
628 long len;
629
630 saa_rewind (s);
631 while ( (data = saa_rbytes (s, &len)) )
632 fwrite (data, 1, len, fp);
633 }
634
635 /*
636 * Register, instruction, condition-code and prefix keywords used
637 * by the scanner.
638 */
639 #include "names.c"
640 static char *special_names[] = {
641 "byte", "dword", "far", "long", "near", "nosplit", "qword",
642 "short", "to", "tword", "word"
643 };
644 static char *prefix_names[] = {
645 "a16", "a32", "lock", "o16", "o32", "rep", "repe", "repne",
646 "repnz", "repz", "times"
647 };
648
649
650 /*
651 * Standard scanner routine used by parser.c and some output
652 * formats. It keeps a succession of temporary-storage strings in
653 * stdscan_tempstorage, which can be cleared using stdscan_reset.
654 */
655 static char **stdscan_tempstorage = NULL;
656 static int stdscan_tempsize = 0, stdscan_templen = 0;
657 #define STDSCAN_TEMP_DELTA 256
658
659 static void stdscan_pop(void) {
660 nasm_free (stdscan_tempstorage[--stdscan_templen]);
661 }
662
663 void stdscan_reset(void) {
664 while (stdscan_templen > 0)
665 stdscan_pop();
666 }
667
668 static char *stdscan_copy(char *p, int len) {
669 char *text;
670
671 text = nasm_malloc(len+1);
672 strncpy (text, p, len);
673 text[len] = '\0';
674
675 if (stdscan_templen >= stdscan_tempsize) {
676 stdscan_tempsize += STDSCAN_TEMP_DELTA;
677 stdscan_tempstorage = nasm_realloc(stdscan_tempstorage,
678 stdscan_tempsize*sizeof(char *));
679 }
680 stdscan_tempstorage[stdscan_templen++] = text;
681
682 return text;
683 }
684
685 char *stdscan_bufptr = NULL;
686 int stdscan (void *private_data, struct tokenval *tv) {
687 char ourcopy[256], *r, *s;
688
689 while (isspace(*stdscan_bufptr)) stdscan_bufptr++;
690 if (!*stdscan_bufptr)
691 return tv->t_type = 0;
692
693 /* we have a token; either an id, a number or a char */
694 if (isidstart(*stdscan_bufptr) ||
695 (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1]))) {
696 /* now we've got an identifier */
697 int i;
698 int is_sym = FALSE;
699
700 if (*stdscan_bufptr == '$') {
701 is_sym = TRUE;
702 stdscan_bufptr++;
703 }
704
705 r = stdscan_bufptr++;
706 while (isidchar(*stdscan_bufptr)) stdscan_bufptr++;
707 tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
708
709 for (s=tv->t_charptr, r=ourcopy; *s; s++)
710 *r++ = tolower (*s);
711 *r = '\0';
712 if (is_sym)
713 return tv->t_type = TOKEN_ID;/* bypass all other checks */
714 /* right, so we have an identifier sitting in temp storage. now,
715 * is it actually a register or instruction name, or what? */
716 if ((tv->t_integer=bsi(ourcopy, reg_names,
717 elements(reg_names)))>=0) {
718 tv->t_integer += EXPR_REG_START;
719 return tv->t_type = TOKEN_REG;
720 } else if ((tv->t_integer=bsi(ourcopy, insn_names,
721 elements(insn_names)))>=0) {
722 return tv->t_type = TOKEN_INSN;
723 }
724 for (i=0; i<(int)elements(icn); i++)
725 if (!strncmp(ourcopy, icn[i], strlen(icn[i]))) {
726 char *p = ourcopy + strlen(icn[i]);
727 tv->t_integer = ico[i];
728 if ((tv->t_inttwo=bsi(p, conditions,
729 elements(conditions)))>=0)
730 return tv->t_type = TOKEN_INSN;
731 }
732 if ((tv->t_integer=bsi(ourcopy, prefix_names,
733 elements(prefix_names)))>=0) {
734 tv->t_integer += PREFIX_ENUM_START;
735 return tv->t_type = TOKEN_PREFIX;
736 }
737 if ((tv->t_integer=bsi(ourcopy, special_names,
738 elements(special_names)))>=0)
739 return tv->t_type = TOKEN_SPECIAL;
740 if (!strcmp(ourcopy, "seg"))
741 return tv->t_type = TOKEN_SEG;
742 if (!strcmp(ourcopy, "wrt"))
743 return tv->t_type = TOKEN_WRT;
744 return tv->t_type = TOKEN_ID;
745 } else if (*stdscan_bufptr == '$' && !isnumchar(stdscan_bufptr[1])) {
746 /*
747 * It's a $ sign with no following hex number; this must
748 * mean it's a Here token ($), evaluating to the current
749 * assembly location, or a Base token ($$), evaluating to
750 * the base of the current segment.
751 */
752 stdscan_bufptr++;
753 if (*stdscan_bufptr == '$') {
754 stdscan_bufptr++;
755 return tv->t_type = TOKEN_BASE;
756 }
757 return tv->t_type = TOKEN_HERE;
758 } else if (isnumstart(*stdscan_bufptr)) { /* now we've got a number */
759 int rn_error;
760
761 r = stdscan_bufptr++;
762 while (isnumchar(*stdscan_bufptr))
763 stdscan_bufptr++;
764
765 if (*stdscan_bufptr == '.') {
766 /*
767 * a floating point constant
768 */
769 stdscan_bufptr++;
770 while (isnumchar(*stdscan_bufptr)) {
771 stdscan_bufptr++;
772 }
773 tv->t_charptr = stdscan_copy(r, stdscan_bufptr - r);
774 return tv->t_type = TOKEN_FLOAT;
775 }
776 r = stdscan_copy(r, stdscan_bufptr - r);
777 tv->t_integer = readnum(r, &rn_error);
778 stdscan_pop();
779 if (rn_error)
780 return tv->t_type = TOKEN_ERRNUM;/* some malformation occurred */
781 tv->t_charptr = NULL;
782 return tv->t_type = TOKEN_NUM;
783 } else if (*stdscan_bufptr == '\'' ||
784 *stdscan_bufptr == '"') {/* a char constant */
785 char quote = *stdscan_bufptr++, *r;
786 r = tv->t_charptr = stdscan_bufptr;
787 while (*stdscan_bufptr && *stdscan_bufptr != quote) stdscan_bufptr++;
788 tv->t_inttwo = stdscan_bufptr - r; /* store full version */
789 if (!*stdscan_bufptr)
790 return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */
791 tv->t_integer = 0;
792 r = stdscan_bufptr++; /* skip over final quote */
793 while (quote != *--r) {
794 tv->t_integer = (tv->t_integer<<8) + (unsigned char) *r;
795 }
796 return tv->t_type = TOKEN_NUM;
797 } else if (*stdscan_bufptr == ';') { /* a comment has happened - stay */
798 return tv->t_type = 0;
799 } else if (stdscan_bufptr[0] == '>' && stdscan_bufptr[1] == '>') {
800 stdscan_bufptr += 2;
801 return tv->t_type = TOKEN_SHR;
802 } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '<') {
803 stdscan_bufptr += 2;
804 return tv->t_type = TOKEN_SHL;
805 } else if (stdscan_bufptr[0] == '/' && stdscan_bufptr[1] == '/') {
806 stdscan_bufptr += 2;
807 return tv->t_type = TOKEN_SDIV;
808 } else if (stdscan_bufptr[0] == '%' && stdscan_bufptr[1] == '%') {
809 stdscan_bufptr += 2;
810 return tv->t_type = TOKEN_SMOD;
811 } else if (stdscan_bufptr[0] == '=' && stdscan_bufptr[1] == '=') {
812 stdscan_bufptr += 2;
813 return tv->t_type = TOKEN_EQ;
814 } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '>') {
815 stdscan_bufptr += 2;
816 return tv->t_type = TOKEN_NE;
817 } else if (stdscan_bufptr[0] == '!' && stdscan_bufptr[1] == '=') {
818 stdscan_bufptr += 2;
819 return tv->t_type = TOKEN_NE;
820 } else if (stdscan_bufptr[0] == '<' && stdscan_bufptr[1] == '=') {
821 stdscan_bufptr += 2;
822 return tv->t_type = TOKEN_LE;
823 } else if (stdscan_bufptr[0] == '>' && stdscan_bufptr[1] == '=') {
824 stdscan_bufptr += 2;
825 return tv->t_type = TOKEN_GE;
826 } else if (stdscan_bufptr[0] == '&' && stdscan_bufptr[1] == '&') {
827 stdscan_bufptr += 2;
828 return tv->t_type = TOKEN_DBL_AND;
829 } else if (stdscan_bufptr[0] == '^' && stdscan_bufptr[1] == '^') {
830 stdscan_bufptr += 2;
831 return tv->t_type = TOKEN_DBL_XOR;
832 } else if (stdscan_bufptr[0] == '|' && stdscan_bufptr[1] == '|') {
833 stdscan_bufptr += 2;
834 return tv->t_type = TOKEN_DBL_OR;
835 } else /* just an ordinary char */
836 return tv->t_type = (unsigned char) (*stdscan_bufptr++);
837 }
838
839 /*
840 * Return TRUE if the argument is a simple scalar. (Or a far-
841 * absolute, which counts.)
842 */
843 int is_simple (expr *vect) {
844 while (vect->type && !vect->value)
845 vect++;
846 if (!vect->type)
847 return 1;
848 if (vect->type != EXPR_SIMPLE)
849 return 0;
850 do {
851 vect++;
852 } while (vect->type && !vect->value);
853 if (vect->type && vect->type < EXPR_SEGBASE+SEG_ABS) return 0;
854 return 1;
855 }
856
857 /*
858 * Return TRUE if the argument is a simple scalar, _NOT_ a far-
859 * absolute.
860 */
861 int is_really_simple (expr *vect) {
862 while (vect->type && !vect->value)
863 vect++;
864 if (!vect->type)
865 return 1;
866 if (vect->type != EXPR_SIMPLE)
867 return 0;
868 do {
869 vect++;
870 } while (vect->type && !vect->value);
871 if (vect->type) return 0;
872 return 1;
873 }
874
875 /*
876 * Return TRUE if the argument is relocatable (i.e. a simple
877 * scalar, plus at most one segment-base, plus possibly a WRT).
878 */
879 int is_reloc (expr *vect) {
880 while (vect->type && !vect->value) /* skip initial value-0 terms */
881 vect++;
882 if (!vect->type) /* trivially return TRUE if nothing */
883 return 1; /* is present apart from value-0s */
884 if (vect->type < EXPR_SIMPLE) /* FALSE if a register is present */
885 return 0;
886 if (vect->type == EXPR_SIMPLE) { /* skip over a pure number term... */
887 do {
888 vect++;
889 } while (vect->type && !vect->value);
890 if (!vect->type) /* ...returning TRUE if that's all */
891 return 1;
892 }
893 if (vect->type == EXPR_WRT) { /* skip over a WRT term... */
894 do {
895 vect++;
896 } while (vect->type && !vect->value);
897 if (!vect->type) /* ...returning TRUE if that's all */
898 return 1;
899 }
900 if (vect->value != 0 && vect->value != 1)
901 return 0; /* segment base multiplier non-unity */
902 do { /* skip over _one_ seg-base term... */
903 vect++;
904 } while (vect->type && !vect->value);
905 if (!vect->type) /* ...returning TRUE if that's all */
906 return 1;
907 return 0; /* And return FALSE if there's more */
908 }
909
910 /*
911 * Return TRUE if the argument contains an `unknown' part.
912 */
913 int is_unknown(expr *vect) {
914 while (vect->type && vect->type < EXPR_UNKNOWN)
915 vect++;
916 return (vect->type == EXPR_UNKNOWN);
917 }
918
919 /*
920 * Return TRUE if the argument contains nothing but an `unknown'
921 * part.
922 */
923 int is_just_unknown(expr *vect) {
924 while (vect->type && !vect->value)
925 vect++;
926 return (vect->type == EXPR_UNKNOWN);
927 }
928
929 /*
930 * Return the scalar part of a relocatable vector. (Including
931 * simple scalar vectors - those qualify as relocatable.)
932 */
933 long reloc_value (expr *vect) {
934 while (vect->type && !vect->value)
935 vect++;
936 if (!vect->type) return 0;
937 if (vect->type == EXPR_SIMPLE)
938 return vect->value;
939 else
940 return 0;
941 }
942
943 /*
944 * Return the segment number of a relocatable vector, or NO_SEG for
945 * simple scalars.
946 */
947 long reloc_seg (expr *vect) {
948 while (vect->type && (vect->type == EXPR_WRT || !vect->value))
949 vect++;
950 if (vect->type == EXPR_SIMPLE) {
951 do {
952 vect++;
953 } while (vect->type && (vect->type == EXPR_WRT || !vect->value));
954 }
955 if (!vect->type)
956 return NO_SEG;
957 else
958 return vect->type - EXPR_SEGBASE;
959 }
960
961 /*
962 * Return the WRT segment number of a relocatable vector, or NO_SEG
963 * if no WRT part is present.
964 */
965 long reloc_wrt (expr *vect) {
966 while (vect->type && vect->type < EXPR_WRT)
967 vect++;
968 if (vect->type == EXPR_WRT) {
969 return vect->value;
970 } else
971 return NO_SEG;
972 }
973
974 /*
975 * Binary search.
976 */
977 int bsi (char *string, char **array, int size) {
978 int i = -1, j = size; /* always, i < index < j */
979 while (j-i >= 2) {
980 int k = (i+j)/2;
981 int l = strcmp(string, array[k]);
982 if (l<0) /* it's in the first half */
983 j = k;
984 else if (l>0) /* it's in the second half */
985 i = k;
986 else /* we've got it :) */
987 return k;
988 }
989 return -1; /* we haven't got it :( */
990 }