home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097s.zip / NASMLIB.C < prev    next >
C/C++ Source or Header  |  1997-11-20  |  25KB  |  967 lines

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