]> Shamusworld >> Repos - rmac/blobdiff - token.c
Initial commit for 68020/30/40/60/68881/68882/68851 support.
[rmac] / token.c
diff --git a/token.c b/token.c
index c78d97ac6f0054d8ca02bf68b0a3a1c0c10406e4..75b4cc166546e978932c1655faf1e3f70e2e2379 100644 (file)
--- a/token.c
+++ b/token.c
@@ -1,30 +1,32 @@
 //
 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
 // TOKEN.C - Token Handling
-// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
 // Source utilised with the kind permission of Landon Dyer
 //
 
 #include "token.h"
+#include "direct.h"
 #include "error.h"
 #include "macro.h"
 #include "procln.h"
+#include "sect.h"
 #include "symbol.h"
 
 #define DECL_KW                                // Declare keyword arrays
-#define DEF_KW                         // Declare keyword values 
+#define DEF_KW                         // Declare keyword values
 #include "kwtab.h"                     // Incl generated keyword tables & defs
 
 
 int lnsave;                                    // 1; strcpy() text of current line
-int curlineno;                         // Current line number
+uint16_t curlineno;                    // Current line number (64K max currently)
 int totlines;                          // Total # of lines
 int mjump_align = 0;           // mjump alignment flag
 char lntag;                                    // Line tag
 char * curfname;                       // Current filename
-char tolowertab[128];          // Uppercase ==> lowercase 
-char hextab[128];                      // Table of hex values
+char tolowertab[128];          // Uppercase ==> lowercase
+int8_t hextab[128];                    // Table of hex values
 char dotxtab[128];                     // Table for ".b", ".s", etc.
 char irbuf[LNSIZ];                     // Text for .rept block line
 char lnbuf[LNSIZ];                     // Text of current line
@@ -54,63 +56,87 @@ static IMACRO * f_imacro;                           // Ptr list of free IMACROs
 static TOKEN tokbuf[TOKBUFSIZE];               // Token buffer (stack-like, all files)
 
 char chrtab[] = {
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // NUL SOH STX ETX 
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // EOT ENQ ACK BEL 
-       ILLEG, WHITE, ILLEG, ILLEG,                     // BS HT LF VT 
-       WHITE, ILLEG, ILLEG, ILLEG,                     // FF CR SO SI 
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // NUL SOH STX ETX
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // EOT ENQ ACK BEL
+       ILLEG, WHITE, ILLEG, ILLEG,                     // BS HT LF VT
+       WHITE, ILLEG, ILLEG, ILLEG,                     // FF CR SO SI
 
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // DLE DC1 DC2 DC3 
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // DC4 NAK SYN ETB 
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // CAN EM SUB ESC 
-       ILLEG, ILLEG, ILLEG, ILLEG,                     // FS GS RS US 
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // DLE DC1 DC2 DC3
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // DC4 NAK SYN ETB
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // CAN EM SUB ESC
+       ILLEG, ILLEG, ILLEG, ILLEG,                     // FS GS RS US
 
        WHITE, MULTX, MULTX, SELF,                      // SP ! " #
        MULTX+CTSYM, MULTX, SELF, MULTX,        // $ % & '
        SELF, SELF, SELF, SELF,                         // ( ) * +
        SELF, SELF, STSYM, SELF,                        // , - . /
 
-       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 0 1 
-       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 2 3 
-       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 4 5 
-       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 6 7 
-       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 8 9 
-       MULTX, MULTX,                                                           // : ; 
-       MULTX, MULTX, MULTX, STSYM+CTSYM,                       // < = > ? 
+       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 0 1
+       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 2 3
+       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 4 5
+       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 6 7
+       DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM,         // 8 9
+       MULTX, MULTX,                                                           // : ;
+       MULTX, MULTX, MULTX, STSYM+CTSYM,                       // < = > ?
 
        MULTX, STSYM+CTSYM+HDIGIT,                                                                      // @ A
        (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,       // B C
-       STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,                                         // D E
+       (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,                                               // D E
        STSYM+CTSYM+HDIGIT, STSYM+CTSYM,                                                        // F G
-       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,                     // H I J K
+       STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,                   // H I J K
        (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,   // L M N O
 
-       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,   // P Q R S
+       (char)((BYTE)DOT)+STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,       // P Q R S
        STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,   // T U V W
        STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF,                            // X Y Z [
        SELF, SELF, MULTX, STSYM+CTSYM,                                                         // \ ] ^ _
 
        ILLEG, STSYM+CTSYM+HDIGIT,                                                                      // ` a
        (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,       // b c
-       STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,                                         // d e
+       (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,                                               // d e
        STSYM+CTSYM+HDIGIT, STSYM+CTSYM,                                                        // f g
-       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,                     // h i j k
+       STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,                   // h i j k
        (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM,   // l m n o
 
-       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,   // p q r s 
+       (char)((BYTE)DOT)+STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,       // p q r s 
        STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM,   // t u v w 
-       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF,                            // x y z { 
-       SELF, SELF, SELF, ILLEG                                                                         // | } ~ DEL 
+       (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF,                          // x y z { 
+       SELF, SELF, SELF, ILLEG                                                                         // | } ~ DEL
 };
 
 // Names of registers
 static char * regname[] = {
-       "d0", "d1",  "d2",  "d3", "d4", "d5", "d6", "d7",
-       "a0", "a1",  "a2",  "a3", "a4", "a5", "a6", "a7",
-       "pc", "ssp", "usp", "sr", "ccr"
+//     "d0", "d1",  "d2",  "d3", "d4", "d5", "d6", "d7",
+//     "a0", "a1",  "a2",  "a3", "a4", "a5", "a6", "a7",
+//     "pc", "ssp", "usp", "sr", "ccr"
+    "d0","d1","d2","d3","d4","d5","d6","d7", // 128,135
+    "a0","a1","a2","a3","a4","a5","a6","sp", // 136,143
+    "ssp","pc","sr","ccr","regequ","set","reg","r0", // 144,151
+    "r1","r2","r3","r4","r5","r6","r7","r8", // 152,159
+    "r9","r10","r11","r12","r13","r14","r15","r16", // 160,167
+    "r17","r18","r19","r20","r21","r22","r23","r24", // 168,175
+    "r25","r26","r27","r28","r29","r30","r31","ccdef", // 176,183
+    "usp","ic40","dc40","bc40","sfc","dfc","","vbr", // 184,191
+    "cacr","caar","msp","isp","tc","itt0","itt1","dtt0", // 192,199
+    "dtt1","mmusr","urp","srp","iacr0","iacr1","dacr0","dacr1", // 200,207
+    "tt0","tt1","crp","","","","","", // 208,215
+    "","","","","fpiar","fpsr","fpcr","", // 216,223
+    "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7", // 224,231
+    "","","","","","","","", // 232,239
+    "","","","","","","","", // 240,247
+    "","","","","","","","", // 248,255
+    "","","","","x0","x1","y0","y1", // 256,263
+    "","b0","","b2","","b1","a","b", // 264,271
+    "mr","omr","la","lc","ssh","ssl","ss","", // 272,279
+    "n0","n1","n2","n3","n4","n5","n6","n7", // 280,287
+    "m0","m1","m2","m3","m4","m5","m6","m7", // 288,295
+    "","","","","","","l","p", // 296,303
+    "mr","omr","la","lc","ssh","ssl","ss","", // 304,311
+    "a10","b10","x","y","","","ab","ba"  // 312,319
 };
 
 static char * riscregname[] = {
-        "r0",  "r1",  "r2",  "r3",  "r4", "r5",   "r6",  "r7", 
+        "r0",  "r1",  "r2",  "r3",  "r4", "r5",   "r6",  "r7",
         "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15",
        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
@@ -155,16 +181,26 @@ void InitTokenizer(void)
                tolowertab[i] |= 0x20;
 
        // These characters are legal immediately after a period
-       dotxtab['b'] = DOTB;                                    // .b .B .s .S 
+       dotxtab['b'] = DOTB;                                    // .b .B .s .S
        dotxtab['B'] = DOTB;
-       dotxtab['s'] = DOTB;
-       dotxtab['S'] = DOTB;
+       //dotxtab['s'] = DOTB;
+       //dotxtab['S'] = DOTB;
        dotxtab['w'] = DOTW;                                    // .w .W 
        dotxtab['W'] = DOTW;
        dotxtab['l'] = DOTL;                                    // .l .L 
        dotxtab['L'] = DOTL;
        dotxtab['i'] = DOTI;                                    // .i .I (???) 
        dotxtab['I'] = DOTI;
+       dotxtab['D'] = DOTD;                                    // .d .D (quad word)
+       dotxtab['d'] = DOTD;
+       dotxtab['S'] = DOTS;                                    // .s .S
+       dotxtab['s'] = DOTS;                                    
+       dotxtab['Q'] = DOTQ;                                    // .q .Q
+       dotxtab['q'] = DOTQ;                                    
+       dotxtab['X'] = DOTX;                                    // .x .x
+       dotxtab['x'] = DOTX;                                    
+       dotxtab['P'] = DOTP;                                    // .p .P
+       dotxtab['p'] = DOTP;                                    
 }
 
 
@@ -230,7 +266,7 @@ INOBJ * a_inobj(int typ)
 
                inobj->inobj.ifile = ifile;
                break;
-       case SRC_IMACRO:                                                // Alloc and init an IMACRO 
+       case SRC_IMACRO:                                                // Alloc and init an IMACRO
                if (f_imacro == NULL)
                        imacro = malloc(sizeof(IMACRO));
                else
@@ -288,7 +324,6 @@ int ExpandMacro(char * src, char * dest, int destsiz)
        IMACRO * imacro = cur_inobj->inobj.imacro;
        int macnum = (int)(imacro->im_macro->sattr);
 
-//     destsiz--;
        char * dst = dest;                                              // Next dest slot
        char * edst = dest + destsiz - 1;               // End + 1(?) of dest buffer
 
@@ -314,6 +349,11 @@ int ExpandMacro(char * src, char * dest, int destsiz)
                        if (dst >= edst)
                                goto overflow;
 
+                       // Skip comments in case a loose @ or \ is in there
+                       // In that case the tokeniser was trying to expand it.
+                       if ((*s == ';') || ((*s == '/') && (*(s + 1) == '/')))
+                               goto skipcomments;
+
                        *dst++ = *s++;
                }
                // Do macro expansion
@@ -330,11 +370,11 @@ int ExpandMacro(char * src, char * dest, int destsiz)
 
                                *dst++ = *s++;
                                continue;
-                       case '?':                                               // \? <macro>  set `questmark' flag 
+                       case '?':                                               // \? <macro>  set `questmark' flag
                                ++s;
                                questmark = 1;
                                break;
-                       case '#':                                               // \#, number of arguments 
+                       case '#':                                               // \#, number of arguments
                                sprintf(numbuf, "%d", (int)imacro->im_nargs);
                                goto copystr;
                        case '!':                                               // \! size suffix supplied on invocation
@@ -347,7 +387,7 @@ int ExpandMacro(char * src, char * dest, int destsiz)
                                }
 
                                goto copy_d;
-                       case '~':                                               // ==> unique label string Mnnnn... 
+                       case '~':                                               // ==> unique label string Mnnnn...
                                sprintf(numbuf, "M%u", curuniq);
 copystr:
                                d = numbuf;
@@ -511,11 +551,11 @@ DEBUG printf("ExM: SYMBOL=\"%s\"", d);
                                                                *dst++ = '"';
                                                                continue;
                                                                break;
-// Shamus: Changing the format specifier from %lx to %ux caused
-//         the assembler to choke on legitimate code... Need to investigate
-//         this further before changing anything else here!
+// Shamus: Changing the format specifier from %lx to %ux caused the assembler
+//         to choke on legitimate code... Need to investigate this further
+//         before changing anything else here!
                                                        case CONST:
-                                                               sprintf(numbuf, "$%lx", (LONG)*tk++);
+                                                               sprintf(numbuf, "$%lx", (long unsigned int)*tk++);
                                                                d = numbuf;
                                                                break;
                                                        case DEQUALS:
@@ -554,6 +594,9 @@ DEBUG printf("ExM: SYMBOL=\"%s\"", d);
                                                        case DOTL:
                                                                d = ".l";
                                                                break;
+                                                       case CR_ABSCOUNT:
+                                                               d = "^^abscount";
+                                                               break;
                                                        case CR_DATE:
                                                                d = "^^date";
                                                                break;
@@ -601,6 +644,8 @@ strcopy:
                }
        }
 
+skipcomments:
+
        *dst = EOS;
        DEBUG { printf("ExM: dst=\"%s\"\n", dest); }
        return OK;
@@ -617,8 +662,6 @@ overflow:
 //
 char * GetNextMacroLine(void)
 {
-//     unsigned source_addr;
-
        IMACRO * imacro = cur_inobj->inobj.imacro;
 //     LONG * strp = imacro->im_nextln;
        struct LineList * strp = imacro->im_nextln;
@@ -626,7 +669,6 @@ char * GetNextMacroLine(void)
        if (strp == NULL)                                               // End-of-macro
                return NULL;
 
-//     imacro->im_nextln = (LONG *)*strp;
        imacro->im_nextln = strp->next;
 //     ExpandMacro((char *)(strp + 1), imacro->im_lnbuf, LNSIZ);
        ExpandMacro(strp->line, imacro->im_lnbuf, LNSIZ);
@@ -640,7 +682,6 @@ char * GetNextMacroLine(void)
 //
 char * GetNextRepeatLine(void)
 {
-
        IREPT * irept = cur_inobj->inobj.irept;
        LONG * strp = irept->ir_nextln;                 // initial null
 
@@ -672,17 +713,13 @@ char * GetNextRepeatLine(void)
 //
 int include(int handle, char * fname)
 {
-       IFILE * ifile;
-       INOBJ * inobj;
-       FILEREC * fr;
-
-       // Verbose mode
-       if (verb_flag)
+       // Debug mode
+       if (debug)
                printf("[include: %s, cfileno=%u]\n", fname, cfileno);
 
        // Alloc and initialize include-descriptors
-       inobj = a_inobj(SRC_IFILE);
-       ifile = inobj->inobj.ifile;
+       INOBJ * inobj = a_inobj(SRC_IFILE);
+       IFILE * ifile = inobj->inobj.ifile;
 
        ifile->ifhandle = handle;                               // Setup file handle
        ifile->ifind = ifile->ifcnt = 0;                // Setup buffer indices
@@ -690,21 +727,20 @@ int include(int handle, char * fname)
        ifile->ifoldfname = curfname;                   // Save old filename
        ifile->ifno = cfileno;                                  // Save old file number
 
-//     cfileno = filecount++;                                  // Compute new file number
        // NB: This *must* be preincrement, we're adding one to the filecount here!
        cfileno = ++filecount;                                  // Compute NEW file number
        curfname = strdup(fname);                               // Set current filename (alloc storage)
        curlineno = 0;                                                  // Start on line zero
 
        // Add another file to the file-record
-       fr = (FILEREC *)malloc(sizeof(FILEREC));
+       FILEREC * fr = (FILEREC *)malloc(sizeof(FILEREC));
        fr->frec_next = NULL;
        fr->frec_name = curfname;
 
        if (last_fr == NULL)
-               filerec = fr;                                           // Add first filerec 
+               filerec = fr;                                           // Add first filerec
        else
-               last_fr->frec_next = fr;                        // Append to list of filerecs 
+               last_fr->frec_next = fr;                        // Append to list of filerecs
 
        last_fr = fr;
        DEBUG printf("[include: curfname: %s, cfileno=%u]\n", curfname, cfileno);
@@ -727,33 +763,41 @@ int fpop(void)
        {
                // Pop IFENT levels until we reach the conditional assembly context we
                // were at when the input object was entered.
+               int numUnmatched = 0;
+
                while (ifent != inobj->in_ifent)
                {
-                       if (d_endif() != 0)                             // Something bad happened during endif parsing?
-                               return -1;                                      // If yes, bail instead of getting stuck in a loop
+                       if (d_endif() != 0)             // Something bad happened during endif parsing?
+                               return -1;                      // If yes, bail instead of getting stuck in a loop
+
+                       numUnmatched++;
                }
 
-               tok = inobj->in_otok;                           // Restore tok and otok
+               // Give a warning to the user that we had to wipe their bum for them
+               if (numUnmatched > 0)
+                       warni("missing %d .endif(s)", numUnmatched);
+
+               tok = inobj->in_otok;           // Restore tok and otok
                etok = inobj->in_etok;
 
                switch (inobj->in_type)
                {
-               case SRC_IFILE:                                         // Pop and release an IFILE
-                       if (verb_flag)
+               case SRC_IFILE:                         // Pop and release an IFILE
+                       if (debug)
                                printf("[Leaving: %s]\n", curfname);
 
                        ifile = inobj->inobj.ifile;
                        ifile->if_link = f_ifile;
                        f_ifile = ifile;
                        close(ifile->ifhandle);                 // Close source file
-if (verb_flag) printf("[fpop (pre):  curfname=%s]\n", curfname);
+if (debug)     printf("[fpop (pre):  curfname=%s]\n", curfname);
                        curfname = ifile->ifoldfname;   // Set current filename
-if (verb_flag) printf("[fpop (post): curfname=%s]\n", curfname);
-if (verb_flag) printf("[fpop: (pre)  cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno);
-                       curlineno = ifile->ifoldlineno; // Set current line# 
+if (debug)     printf("[fpop (post): curfname=%s]\n", curfname);
+if (debug)     printf("[fpop: (pre)  cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno);
+                       curlineno = ifile->ifoldlineno; // Set current line#
                        DEBUG printf("cfileno=%d ifile->ifno=%d\n", (int)cfileno, (int)ifile->ifno);
                        cfileno = ifile->ifno;                  // Restore current file number
-if (verb_flag) printf("[fpop: (post) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno);
+if (debug)     printf("[fpop: (post) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno);
                        break;
                case SRC_IMACRO:                                        // Pop and release an IMACRO
                        imacro = inobj->inobj.imacro;
@@ -809,7 +853,7 @@ char * GetNextLine(void)
                                if (*p == '\r')
                                {
                                        if (i >= j)
-                                               break;  // Need to read more, then look for '\n' to eat 
+                                               break;  // Need to read more, then look for '\n' to eat
                                        else if (p[1] == '\n')
                                                i++;
                                }
@@ -908,9 +952,14 @@ retry:
        case SRC_IFILE:
                if ((ln = GetNextLine()) == NULL)
                {
-if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n");
-                       fpop();                                                 // Pop input level
-                       goto retry;                                             // Try for more lines 
+if (debug) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n");
+                       if (fpop() == 0)                                // Pop input level
+                               goto retry;                                     // Try for more lines
+                       else
+                       {
+                               ifent->if_prev = (IFENT *) - 1; //Signal Assemble() that we have reached EOF with unbalanced if/endifs
+                               return TKEOF;
+                       }
                }
 
                curlineno++;                                            // Bump line number
@@ -957,7 +1006,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n");
        case SRC_IREPT:
                if ((ln = GetNextRepeatLine()) == NULL)
                {
-if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
+if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                        fpop();
                        goto retry;
                }
@@ -996,7 +1045,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                        ln++;
 
                // Handle EOL, comment with ';'
-               if (*ln == EOS || *ln == ';'|| ((*ln == '/') && (*(ln + 1) == '/'))) 
+               if (*ln == EOS || *ln == ';'|| ((*ln == '/') && (*(ln + 1) == '/')))
                        break;
 
                // Handle start of symbol. Symbols are null-terminated in place. The
@@ -1011,6 +1060,27 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
 
                        v = 0;                                  // Assume no DOT attrib follows symbol
                        stuffnull = 1;
+
+                       // In some cases, we need to check for a DOTx at the *beginning*
+                       // of a symbol, as the "start" of the line we're currently looking
+                       // at could be somewhere in the middle of that line!
+                       if (*ln == '.')
+                       {
+                               // Make sure that it's *only* a .[bwsl] following, and not the
+                               // start of a local symbol:
+                               if ((chrtab[*(ln + 1)] & DOT)
+                                       && (dotxtab[*(ln + 1)] != 0)
+                                       && !(chrtab[*(ln + 2)] & CTSYM))
+                               {
+                                       // We found a legitimate DOTx construct, so add it to the
+                                       // token stream:
+                                       ln++;
+                                       stuffnull = 0;
+                                       *tk++ = (TOKEN)dotxtab[*ln++];
+                                       continue;
+                               }
+                       }
+
                        p = nullspot = ln++;    // Nullspot -> start of this symbol
 
                        // Find end of symbol (and compute its length)
@@ -1022,19 +1092,19 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                        if (*ln == '.')
                        {
                                *ln++ = EOS;            // Terminate symbol
-                               stuffnull = 0;          // And never try it again 
+                               stuffnull = 0;          // And never try it again
 
                                // Character following the `.' must have a DOT attribute, and
                                // the chararacter after THAT one must not have a start-symbol
                                // attribute (to prevent symbols that look like, for example,
                                // "zingo.barf", which might be a good idea anyway....)
-                               if ((((int)chrtab[*ln] & DOT) == 0) || ((int)dotxtab[*ln] <= 0))
-                                       return error("[bwsl] must follow `.' in symbol");
+                               if (((chrtab[*ln] & DOT) == 0) || (dotxtab[*ln] == 0))
+                                       return error("[bwsl] must follow '.' in symbol");
 
                                v = (VALUE)dotxtab[*ln++];
 
-                               if ((int)chrtab[*ln] & CTSYM)
-                                       return error("misuse of `.', not allowed in symbols");
+                               if (chrtab[*ln] & CTSYM)
+                                       return error("misuse of '.', not allowed in symbols");
                        }
 
                        // If the symbol is small, check to see if it's really the name of
@@ -1086,7 +1156,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                        }
 
                        // If not tokenized keyword OR token was not found
-                       if (j < 0 || state < 0)
+                       if ((j < 0) || (state < 0))
                        {
                                *tk++ = SYMBOL;
 //#warning
@@ -1125,9 +1195,10 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                // Handle multiple-character tokens
                if (c & MULTX)
                {
+
                        switch (*ln++)
                        {
-                       case '!':               // ! or != 
+                       case '!':               // ! or !=
                                if (*ln == '=')
                                {
                                        *tk++ = NE;
@@ -1137,20 +1208,21 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        *tk++ = '!';
 
                                continue;
-                       case '\'':              // 'string' 
-                       case '\"':              // "string" 
-                               c1 = ln[-1];
+                       case '\'':              // 'string'
+                               if (m6502)
+                               {
+                                       // Hardcoded for now, maybe this will change in the future
+                                       *tk++ = STRINGA8;
+                                       goto dostring;
+                               }
+                               // Fall through
+                       case '\"':              // "string"
                                *tk++ = STRING;
-//#warning
-// More char * stuffing (8 bytes) into the space of 4 (TOKEN).
-// Need to figure out how to fix this crap.
-#if 0
-                               *tk++ = (TOKEN)ln;
-#else
+dostring:
+                               c1 = ln[-1];
                                string[stringNum] = ln;
                                *tk++ = stringNum;
                                stringNum++;
-#endif
 
                                for(p=ln; *ln!=EOS && *ln!=c1;)
                                {
@@ -1205,50 +1277,17 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                *p++ = EOS;
                                continue;
                        case '$':               // $, hex constant
-                               if ((int)chrtab[*ln] & HDIGIT)
+                               if (chrtab[*ln] & HDIGIT)
                                {
                                        v = 0;
 
                                        // Parse the hex value
-                                       while ((int)hextab[*ln] >= 0)
+                                       while (hextab[*ln] >= 0)
                                                v = (v << 4) + (int)hextab[*ln++];
 
-                                       // ggn: Okay, some comments here are in order I think....
-                                       // The original madmac sources didn't parse the size at
-                                       // this point (i.e. .b/.w/.l). It was probably done at
-                                       // another point, although it's unclear to me exactly
-                                       // where. So why change this? My understanding (at least
-                                       // from what SCPCD said on IRC) is that .w addressing
-                                       // formats produce wrong code on jaguar (or doesn't execute
-                                       // properly? something like that). So the code was changed
-                                       // to mask off the upper bits depending on length (note: I
-                                       // don't think .b is valid at all! I only know of .w/.l, so
-                                       // this should probably be wiped). Then the code that
-                                       // parses the constant and checks to see if it's between
-                                       // $ffff0000 and $8000 never got triggered, so yay job
-                                       // done! ...now say we want to assemble a st .prg. One of
-                                       // the most widely spread optimisations is move.X expr.w,Y
-                                       // (or vice versa, or both, anyway...) to access hardware
-                                       // registers (which are mapped to $fxxxxx). This botchy
-                                       // thing would create "hilarious" code while trying to
-                                       // access hardware registers. So I made a condition to see
-                                       // if st mode or jaguar is active and apply the both or
-                                       // not. One last note: this is hardcoded to get optimised
-                                       // for now on ST mode, i.e. it can't generate code like
-                                       // move.w $00001234,d0 - it'll always get optimised to
-                                       // move.w $1234.w,d0. It's probably ok, but maybe a warning
-                                       // should be emitted? Or maybe finding a way to make it not
-                                       // auto-optimise? I think it's ok for now...
                                        if (*ln == '.')
                                        {
-                                               if (obj_format == ALCYON)
-                                               {
-                                                       if ((*(ln + 1) == 'b') || (*(ln + 1) == 'B') || (*(ln + 1) == 'w') || (*(ln + 1) == 'W') || (*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
-                                                       {
-                                                               ln += 2;
-                                                       }
-                                               }
-                                               else
+                                               if (obj_format == BSD)
                                                {
                                                        if ((*(ln + 1) & 0xDF) == 'B')
                                                        {
@@ -1269,12 +1308,29 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
 
                                        *tk++ = CONST;
                                        *tk++ = v;
+
+                                       if (obj_format == ALCYON)
+                                       {
+                                               if (*ln == '.')
+                                               {
+                                                       if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W'))
+                                                       {
+                                                               *tk++ = DOTW;
+                                                               ln += 2;
+                                                       }
+                                                       else if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
+                                                       {
+                                                               *tk++ = DOTL;
+                                                               ln += 2;
+                                                       }
+                                               }
+                                       }
                                }
                                else
                                        *tk++ = '$';
 
                                continue;
-                       case '<':               // < or << or <> or <= 
+                       case '<':               // < or << or <> or <=
                                switch (*ln)
                                {
                                case '<':
@@ -1303,7 +1359,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        *tk++ = ':';
 
                                continue;
-                       case '=':               // = or == 
+                       case '=':               // = or ==
                                if (*ln == '=')
                                {
                                        *tk++ = DEQUALS;
@@ -1313,7 +1369,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        *tk++ = '=';
 
                                continue;
-                       case '>':               // > or >> or >= 
+                       case '>':               // > or >> or >=
                                switch (*ln)
                                {
                                case '>':
@@ -1328,7 +1384,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        *tk++ = '>';
                                        continue;
                                }
-                       case '%':               // % or binary constant 
+                       case '%':               // % or binary constant
                                if (*ln < '0' || *ln > '1')
                                {
                                        *tk++ = '%';
@@ -1363,7 +1419,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                *tk++ = CONST;
                                *tk++ = v;
                                continue;
-                       case '@':               // @ or octal constant 
+                       case '@':               // @ or octal constant
                                if (*ln < '0' || *ln > '7')
                                {
                                        *tk++ = '@';
@@ -1418,7 +1474,7 @@ if (verb_flag) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
 
                                for(state=0; state>=0;)
                                {
-                                       // Get char, convert to lowercase 
+                                       // Get char, convert to lowercase
                                        j = *p++;
 
                                        if (j >= 'A' && j <= 'Z')
@@ -1508,30 +1564,25 @@ goteol:
 
 //
 // .GOTO <label>       goto directive
-// 
+//
 // The label is searched for starting from the first line of the current,
 // enclosing macro definition. If no enclosing macro exists, an error is
 // generated.
-// 
+//
 // A label is of the form:
-// 
+//
 // :<name><whitespace>
-// 
+//
 // The colon must appear in column 1.  The label is stripped prior to macro
 // expansion, and is NOT subject to macro expansion.  The whitespace may also
 // be EOL.
 //
-//int d_goto(WORD siz) {
-//int d_goto(void)
 int d_goto(WORD unused)
 {
-       char * s1, * s2;
-
        // Setup for the search
        if (*tok != SYMBOL)
                return error("missing label");
 
-//     sym = (char *)tok[1];
        char * sym = string[tok[1]];
        tok += 2;
 
@@ -1539,40 +1590,35 @@ int d_goto(WORD unused)
                return error("goto not in macro");
 
        IMACRO * imacro = cur_inobj->inobj.imacro;
-//     defln = (LONG *)imacro->im_macro->svalue;
        struct LineList * defln = imacro->im_macro->lineList;
 
-       // Find the label, starting with the first line.
-//     for(; defln!=NULL; defln=(LONG *)*defln)
+       // Attempt to find the label, starting with the first line.
        for(; defln!=NULL; defln=defln->next)
        {
-//             if (*(char *)(defln + 1) == ':')
+               // Must start with a colon
                if (defln->line[0] == ':')
                {
                        // Compare names (sleazo string compare)
-                       // This string compare is not right. Doesn't check for lengths.
-                       // (actually it does, but in a crappy, unclear way.)
-WARNING(!!!! Bad string comparison !!!)
-                       s1 = sym;
-//                     s2 = (char *)(defln + 1) + 1;
-                       s2 = defln->line;
-
-                       while (*s1 == *s2)
+                       char * s1 = sym;
+                       char * s2 = defln->line;
+
+                       // Either we will match the strings to EOS on both, or we will
+                       // match EOS on string 1 to whitespace on string 2. Otherwise, we
+                       // have no match.
+                       while ((*s1 == *s2) || ((*s1 == EOS) && (chrtab[*s2] & WHITE)))
                        {
+                               // If we reached the end of string 1 (sym), we're done.
+                               // Note that we're also checking for the end of string 2 as
+                               // well, since we've established they're equal above.
                                if (*s1 == EOS)
-                                       break;
-                               else
                                {
-                                       s1++;
-                                       s2++;
+                                       // Found the label, set new macro next-line and return.
+                                       imacro->im_nextln = defln;
+                                       return 0;
                                }
-                       }
 
-                       // Found the label, set new macro next-line and return.
-                       if ((*s2 == EOS) || ((int)chrtab[*s2] & WHITE))
-                       {
-                               imacro->im_nextln = defln;
-                               return 0;
+                               s1++;
+                               s2++;
                        }
                }
        }
@@ -1641,6 +1687,8 @@ void DumpTokenBuffer(void)
                        printf("[DOTI]");
                else if (*t == ENDEXPR)
                        printf("[ENDEXPR]");
+               else if (*t == CR_ABSCOUNT)
+                       printf("[CR_ABSCOUNT]");
                else if (*t == CR_DEFINED)
                        printf("[CR_DEFINED]");
                else if (*t == CR_REFERENCED)