]> Shamusworld >> Repos - rmac/blobdiff - token.c
Roll back TOKENPTR changes and most of the .u32 changes weren't needed.
[rmac] / token.c
diff --git a/token.c b/token.c
index 77fec1efbeac0071594df0dbd22de787d8b02dd8..e1be9b5b8871ea3cde208b29b8e9a072f43ec64d 100644 (file)
--- a/token.c
+++ b/token.c
@@ -1,29 +1,33 @@
 //
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// RMAC - Reboot's Macro Assembler for all Atari computers
 // 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 <errno.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 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
@@ -33,7 +37,8 @@ WORD cfileno;                         // Current file number
 TOKEN * tok;                           // Ptr to current token
 TOKEN * etok;                          // Ptr past last token in tokbuf[]
 TOKEN tokeol[1] = {EOL};       // Bailout end-of-line token
-char * string[TOKBUFSIZE*2];   // Token buffer string pointer storage
+char * string[TOKBUFSIZE*2];// Token buffer string pointer storage
+int optimizeOff;                       // Optimization override flag
 
 // File record, used to maintain a list of every include file ever visited
 #define FILEREC struct _filerec
@@ -46,71 +51,111 @@ FILEREC
 FILEREC * filerec;
 FILEREC * last_fr;
 
-INOBJ * cur_inobj;                                             // Ptr current input obj (IFILE/IMACRO)
-static INOBJ * f_inobj;                                        // Ptr list of free INOBJs
-static IFILE * f_ifile;                                        // Ptr list of free IFILEs
-static IMACRO * f_imacro;                              // Ptr list of free IMACROs
+INOBJ * cur_inobj;                     // Ptr current input obj (IFILE/IMACRO)
+static INOBJ * f_inobj;                // Ptr list of free INOBJs
+static IFILE * f_ifile;                // Ptr list of free IFILEs
+static IMACRO * f_imacro;      // Ptr list of free IMACROs
 
-static TOKEN tokbuf[TOKBUFSIZE];               // Token buffer (stack-like, all files)
+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 
+uint8_t chrtab[0x100] = {
+       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,                       // < = > ? 
-
-       MULTX, STSYM+CTSYM+HDIGIT,                                                                      // @ A
-       (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,       // B C
-       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
-       (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
-       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
-       STSYM+CTSYM+HDIGIT, STSYM+CTSYM,                                                        // f g
-       STSYM+CTSYM, 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 
-       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 
+       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
+       DOT+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,     // B C
+       DOT+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,     // D E
+       STSYM+CTSYM+HDIGIT, STSYM+CTSYM,                        // F G
+       STSYM+CTSYM, DOT+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // H I J K
+       DOT+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // L M N O
+
+       DOT+STSYM+CTSYM, DOT+STSYM+CTSYM, STSYM+CTSYM, DOT+STSYM+CTSYM, // P Q R S
+       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, 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
+       DOT+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,     // b c
+       DOT+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT,     // d e
+       STSYM+CTSYM+HDIGIT, STSYM+CTSYM,                        // f g
+       STSYM+CTSYM, DOT+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // h i j k
+       DOT+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // l m n o
+
+       DOT+STSYM+CTSYM, DOT+STSYM+CTSYM, STSYM+CTSYM, DOT+STSYM+CTSYM, // p q r s
+       STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, DOT+STSYM+CTSYM, // t u v w
+       DOT+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF,                // x y z {
+       SELF, SELF, SELF, ILLEG,                                        // | } ~ DEL
+
+       // Anything above $7F is illegal (and yes, we need to check for this,
+       // otherwise you get strange and spurious errors that will lead you astray)
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG,
+       ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG, ILLEG
 };
 
 // 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", // 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 +200,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['w'] = DOTW;                                    // .w .W 
+       //dotxtab['s'] = DOTB;
+       //dotxtab['S'] = DOTB;
+       dotxtab['w'] = DOTW;                                    // .w .W
        dotxtab['W'] = DOTW;
-       dotxtab['l'] = DOTL;                                    // .l .L 
+       dotxtab['l'] = DOTL;                                    // .l .L
        dotxtab['L'] = DOTL;
-       dotxtab['i'] = DOTI;                                    // .i .I (???) 
+       dotxtab['i'] = DOTI;                                    // .i .I (WTF is this???)
        dotxtab['I'] = DOTI;
+       dotxtab['D'] = DOTD;                                    // .d .D (double)
+       dotxtab['d'] = DOTD;
+       dotxtab['S'] = DOTS;                                    // .s .S
+       dotxtab['s'] = DOTS;
+       dotxtab['Q'] = DOTQ;                                    // .q .Q (quad word)
+       dotxtab['q'] = DOTQ;
+       dotxtab['X'] = DOTX;                                    // .x .x
+       dotxtab['x'] = DOTX;
+       dotxtab['P'] = DOTP;                                    // .p .P
+       dotxtab['p'] = DOTP;
 }
 
 
@@ -230,7 +285,8 @@ 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
@@ -241,9 +297,10 @@ INOBJ * a_inobj(int typ)
 
                inobj->inobj.imacro = imacro;
                break;
+
        case SRC_IREPT:                                                 // Alloc and init an IREPT
                inobj->inobj.irept = malloc(sizeof(IREPT));
-               DEBUG printf("alloc IREPT\n");
+               DEBUG { printf("alloc IREPT\n"); }
                break;
        }
 
@@ -288,7 +345,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 +370,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 +391,11 @@ int ExpandMacro(char * src, char * dest, int destsiz)
 
                                *dst++ = *s++;
                                continue;
-                       case '?':                                               // \? <macro>  set `questmark' flag 
-                               ++s;
+                       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 +408,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;
@@ -397,7 +458,7 @@ copy_d:
                                        *d++ = *s++;
 
                                if (*s != '}')
-                                       return error("missing '}'");
+                                       return error("missing closing brace ('}')");
                                else
                                        s++;
                        }
@@ -406,10 +467,10 @@ copy_d:
 
                        // Lookup the argument and copy its (string) value into the
                        // destination string
-                       DEBUG printf("argument='%s'\n", mname);
+                       DEBUG { printf("argument='%s'\n", mname); }
 
                        if ((arg = lookup(mname, MACARG, macnum)) == NULL)
-                               return errors("undefined argument: '%s'", mname);
+                               return error("undefined argument: '%s'", mname);
                        else
                        {
                                // Convert a string of tokens (terminated with EOL) back into
@@ -417,24 +478,18 @@ copy_d:
                                // macro invocation) then it is ignored.
                                i = (int)arg->svalue;
 arg_num:
-                               DEBUG printf("~argnumber=%d (argBase=%u)\n", i, imacro->argBase);
+                               DEBUG { printf("~argnumber=%d\n", i); }
                                tk = NULL;
 
                                if (i < imacro->im_nargs)
                                {
-#if 0
-//                                     tk = argp[i];
-//                                     tk = argPtrs[i];
-                                       tk = argPtrs[imacro->argBase + i];
-#else
                                        tk = imacro->argument[i].token;
                                        symbolString = imacro->argument[i].string;
 //DEBUG
 //{
 //     printf("ExM: Preparing to parse argument #%u...\n", i);
-//     dumptok(tk);
+//     DumpTokens(tk);
 //}
-#endif
                                }
 
                                // \?arg yields:
@@ -482,7 +537,7 @@ arg_num:
 #else
                                                                // This fix should be done for strings too
                                                                d = symbolString[*tk++];
-DEBUG printf("ExM: SYMBOL=\"%s\"", d);
+DEBUG { printf("ExM: SYMBOL=\"%s\"", d); }
 #endif
                                                                break;
                                                        case STRING:
@@ -511,11 +566,12 @@ 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", (uint64_t)*tk++);
+                                                               tk++;
                                                                d = numbuf;
                                                                break;
                                                        case DEQUALS:
@@ -604,13 +660,15 @@ strcopy:
                }
        }
 
+skipcomments:
+
        *dst = EOS;
        DEBUG { printf("ExM: dst=\"%s\"\n", dest); }
        return OK;
 
 overflow:
        *dst = EOS;
-       DEBUG printf("*** OVERFLOW LINE ***\n%s\n", dest);
+       DEBUG { printf("*** OVERFLOW LINE ***\n%s\n", dest); }
        return fatal("line too long as a result of macro expansion");
 }
 
@@ -620,16 +678,13 @@ overflow:
 //
 char * GetNextMacroLine(void)
 {
-//     unsigned source_addr;
-
        IMACRO * imacro = cur_inobj->inobj.imacro;
 //     LONG * strp = imacro->im_nextln;
-       struct LineList * strp = imacro->im_nextln;
+       LLIST * strp = imacro->im_nextln;
 
        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);
@@ -643,28 +698,30 @@ char * GetNextMacroLine(void)
 //
 char * GetNextRepeatLine(void)
 {
-
        IREPT * irept = cur_inobj->inobj.irept;
-       LONG * strp = irept->ir_nextln;                 // initial null
+//     LONG * strp = irept->ir_nextln;                 // initial null
 
        // Do repeat at end of .rept block's string list
-       if (strp == NULL)
+//     if (strp == NULL)
+       if (irept->ir_nextln == NULL)
        {
-               DEBUG printf("back-to-top-of-repeat-block count=%d\n", (int)irept->ir_count);
+               DEBUG { printf("back-to-top-of-repeat-block count=%d\n", (int)irept->ir_count); }
                irept->ir_nextln = irept->ir_firstln;   // copy first line
 
                if (irept->ir_count-- == 0)
                {
-                       DEBUG printf("end-repeat-block\n");
+                       DEBUG { printf("end-repeat-block\n"); }
                        return NULL;
                }
 
-               strp = irept->ir_nextln;
+//             strp = irept->ir_nextln;
        }
 
-       strcpy(irbuf, (char *)(irept->ir_nextln + 1));
-       DEBUG printf("repeat line='%s'\n", irbuf);
-       irept->ir_nextln = (LONG *)*strp;
+//     strcpy(irbuf, (char *)(irept->ir_nextln + 1));
+       strcpy(irbuf, irept->ir_nextln->line);
+       DEBUG { printf("repeat line='%s'\n", irbuf); }
+//     irept->ir_nextln = (LONG *)*strp;
+       irept->ir_nextln = irept->ir_nextln->next;
 
        return irbuf;
 }
@@ -675,42 +732,36 @@ char * GetNextRepeatLine(void)
 //
 int include(int handle, char * fname)
 {
-       IFILE * ifile;
-       INOBJ * inobj;
-       FILEREC * fr;
-
        // Debug mode
-       if (debug)
-               printf("[include: %s, cfileno=%u]\n", fname, cfileno);
+       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
-       ifile->ifoldlineno = curlineno;                 // Save old line number
-       ifile->ifoldfname = curfname;                   // Save old filename
-       ifile->ifno = cfileno;                                  // Save old file number
+       ifile->ifhandle = handle;                       // Setup file handle
+       ifile->ifind = ifile->ifcnt = 0;        // Setup buffer indices
+       ifile->ifoldlineno = curlineno;         // Save old line number
+       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
+       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);
+       DEBUG { printf("[include: curfname: %s, cfileno=%u]\n", curfname, cfileno); }
 
        return OK;
 }
@@ -721,73 +772,78 @@ int include(int handle, char * fname)
 //
 int fpop(void)
 {
-       IFILE * ifile;
-       IMACRO * imacro;
-       LONG * p, * p1;
        INOBJ * inobj = cur_inobj;
 
-       if (inobj != NULL)
+       if (inobj == NULL)
+               return 0;
+
+       // 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)
        {
-               // Pop IFENT levels until we reach the conditional assembly context we
-               // were at when the input object was entered.
-               int numUnmatched = 0;
+               if (d_endif() != 0)     // Something bad happened during endif parsing?
+                       return -1;              // If yes, bail instead of getting stuck in a loop
 
-               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
+               numUnmatched++;
+       }
 
-                       numUnmatched++;
-               }
+       // Give a warning to the user that we had to wipe their bum for them
+       if (numUnmatched > 0)
+               warn("missing %d .endif(s)", numUnmatched);
 
-               // 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;
 
-               tok = inobj->in_otok;           // Restore tok and otok
-               etok = inobj->in_etok;
+       switch (inobj->in_type)
+       {
+       case SRC_IFILE:                 // Pop and release an IFILE
+       {
+               DEBUG { printf("[Leaving: %s]\n", curfname); }
+
+               IFILE * ifile = inobj->inobj.ifile;
+               ifile->if_link = f_ifile;
+               f_ifile = ifile;
+               close(ifile->ifhandle);                 // Close source file
+DEBUG { printf("[fpop (pre):  curfname=%s]\n", curfname); }
+               curfname = ifile->ifoldfname;   // Set current filename
+DEBUG { printf("[fpop (post): curfname=%s]\n", curfname); }
+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
+DEBUG { printf("[fpop: (post) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno); }
+               break;
+       }
 
-               switch (inobj->in_type)
-               {
-               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 (debug)     printf("[fpop (pre):  curfname=%s]\n", curfname);
-                       curfname = ifile->ifoldfname;   // Set current filename
-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 (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;
-                       imacro->im_link = f_imacro;
-                       f_imacro = imacro;
-                       break;
-               case SRC_IREPT:                                         // Pop and release an IREPT
-                       DEBUG printf("dealloc IREPT\n");
-                       p = inobj->inobj.irept->ir_firstln;
+       case SRC_IMACRO:                                        // Pop and release an IMACRO
+       {
+               IMACRO * imacro = inobj->inobj.imacro;
+               imacro->im_link = f_imacro;
+               f_imacro = imacro;
+               break;
+       }
 
-                       while (p != NULL)
-                       {
-                               p1 = (LONG *)*p;
-                               p = p1;
-                       }
+       case SRC_IREPT:                                         // Pop and release an IREPT
+       {
+               DEBUG { printf("dealloc IREPT\n"); }
+               LLIST * p = inobj->inobj.irept->ir_firstln;
 
-                       break;
+               // Deallocate repeat lines
+               while (p != NULL)
+               {
+                       free(p->line);
+                       p = p->next;
                }
 
-               cur_inobj = inobj->in_link;
-               inobj->in_link = f_inobj;
-               f_inobj = inobj;
+               break;
        }
+       }
+
+       cur_inobj = inobj->in_link;
+       inobj->in_link = f_inobj;
+       f_inobj = inobj;
 
        return 0;
 }
@@ -820,7 +876,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++;
                                }
@@ -890,21 +946,23 @@ char * GetNextLine(void)
 //
 int TokenizeLine(void)
 {
-       char * ln = NULL;                       // Ptr to current position in line
-       char * p;                                       // Random character ptr
-       TOKEN * tk;                                     // Token-deposit ptr
+       uint8_t * ln = NULL;            // Ptr to current position in line
+       uint8_t * p;                            // Random character ptr
+       PTR tk;                                         // Token-deposit ptr
        int state = 0;                          // State for keyword detector
        int j = 0;                                      // Var for keyword detector
-       char c;                                         // Random char
-       VALUE v;                                        // Random value
-       char * nullspot = NULL;         // Spot to clobber for SYMBOL termination
+       uint8_t c;                                      // Random char
+       uint64_t v;                                     // Random value
+       uint32_t cursize = 0;           // Current line's size (.b, .w, .l, .s, .q, .d)
+       double f;                                       // Random float
+       uint8_t * nullspot = NULL;      // Spot to clobber for SYMBOL termination
        int stuffnull;                          // 1:terminate SYMBOL '\0' at *nullspot
-       char c1;
+       uint8_t c1;
        int stringNum = 0;                      // Pointer to string locations in tokenized line
 
 retry:
 
-       if (cur_inobj == NULL)                                  // Return EOF if input stack is empty
+       if (cur_inobj == NULL)                  // Return EOF if input stack is empty
                return TKEOF;
 
        // Get another line of input from the current input source: a file, a
@@ -919,12 +977,12 @@ retry:
        case SRC_IFILE:
                if ((ln = GetNextLine()) == NULL)
                {
-if (debug) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n");
+DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); }
                        if (fpop() == 0)                                // Pop input level
-                               goto retry;                                     // Try for more lines 
+                               goto retry;                                     // Try for more lines
                        else
                        {
-                               ifent->if_prev = (IFENT *) - 1; //Signal Assemble() that we have reached EOF with unbalanced if/endifs
+                               ifent->if_prev = (IFENT *)-1;   //Signal Assemble() that we have reached EOF with unbalanced if/endifs
                                return TKEOF;
                        }
                }
@@ -953,27 +1011,29 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n");
                }
 
                break;
+
        // Macro-block:
        // o  Handle end-of-macro;
        // o  tag the listing-line with an at (@) sign.
        case SRC_IMACRO:
                if ((ln = GetNextMacroLine()) == NULL)
                {
-                       if (ExitMacro() == 0)                   // Exit macro (pop args, do fpop(), etc)
-                               goto retry;                                     // Try for more lines...
+                       if (ExitMacro() == 0)   // Exit macro (pop args, do fpop(), etc)
+                               goto retry;                     // Try for more lines...
                        else
-                               return TKEOF;                           // Oops, we got a non zero return code, signal EOF
+                               return TKEOF;           // Oops, we got a non zero return code, signal EOF
                }
 
                lntag = '@';
                break;
+
        // Repeat-block:
        // o  Handle end-of-repeat-block;
        // o  tag the listing-line with a pound (#) sign.
        case SRC_IREPT:
                if ((ln = GetNextRepeatLine()) == NULL)
                {
-if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
+                       DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); }
                        fpop();
                        goto retry;
                }
@@ -982,15 +1042,15 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                break;
        }
 
-       // Save text of the line.  We only do this during listings and within
+       // Save text of the line. We only do this during listings and within
        // macro-type blocks, since it is expensive to unconditionally copy every
        // line.
        if (lnsave)
                strcpy(lnbuf, ln);
 
-       // General house-keeping
-       tok = tokeol;                   // Set "tok" to EOL in case of error
-       tk = etok;                              // Reset token ptr
+       // General housekeeping
+       tok = tokeol;           // Set "tok" to EOL in case of error
+       tk.u32 = etok;                  // Reset token ptr
        stuffnull = 0;                  // Don't stuff nulls
        totlines++;                             // Bump total #lines assembled
 
@@ -999,20 +1059,30 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
        if (*ln == '*' || *ln == ';' || ((*ln == '/') && (*(ln + 1) == '/')))
                goto goteol;
 
+       // And here we have a very ugly hack for signalling a single line 'turn off
+       // optimization'. There's really no nice way to do this, so hack it is!
+       optimizeOff = 0;                // Default is to take optimizations as they come
+
+       if (*ln == '!')
+       {
+               optimizeOff = 1;        // Signal that we don't want to optimize this line
+               ln++;                           // & skip over the darned thing
+       }
+
        // Main tokenization loop;
-       // o  skip whitespace;
-       // o  handle end-of-line;
-       // o  handle symbols;
-       // o  handle single-character tokens (operators, etc.);
-       // o  handle multiple-character tokens (constants, strings, etc.).
+       //  o  skip whitespace;
+       //  o  handle end-of-line;
+       //  o  handle symbols;
+       //  o  handle single-character tokens (operators, etc.);
+       //  o  handle multiple-character tokens (constants, strings, etc.).
        for(; *ln!=EOS;)
        {
                // Skip whitespace, handle EOL
-               while ((int)chrtab[*ln] & WHITE)
+               while (chrtab[*ln] & WHITE)
                        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
@@ -1027,6 +1097,27 @@ if (debug) 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.u32++ = (TOKEN)dotxtab[*ln++];
+                                       continue;
+                               }
+                       }
+
                        p = nullspot = ln++;    // Nullspot -> start of this symbol
 
                        // Find end of symbol (and compute its length)
@@ -1038,19 +1129,20 @@ if (debug) 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
+                               // 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++];
+                               v = (uint32_t)dotxtab[*ln++];
+                               cursize = (uint32_t)v;
 
-                               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
@@ -1102,9 +1194,9 @@ if (debug) 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;
+                               *tk.u32++ = SYMBOL;
 //#warning
 //problem here: nullspot is a char * but TOKEN is a uint32_t. On a 64-bit
 //system, this will cause all kinds of mischief.
@@ -1112,18 +1204,18 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                *tk++ = (TOKEN)nullspot;
 #else
                                string[stringNum] = nullspot;
-                               *tk++ = stringNum;
+                               *tk.u32++ = stringNum;
                                stringNum++;
 #endif
                        }
                        else
                        {
-                               *tk++ = (TOKEN)j;
+                               *tk.u32++ = (TOKEN)j;
                                stuffnull = 0;
                        }
 
                        if (v)                                                  // Record attribute token (if any)
-                               *tk++ = (TOKEN)v;
+                               *tk.u32++ = (TOKEN)v;
 
                        if (stuffnull)                                  // Arrange for string termination on next pass
                                nullspot = ln;
@@ -1134,7 +1226,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                // Handle identity tokens
                if (c & SELF)
                {
-                       *tk++ = *ln++;
+                       *tk.u32++ = *ln++;
                        continue;
                }
 
@@ -1143,30 +1235,31 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                {
                        switch (*ln++)
                        {
-                       case '!':               // ! or != 
+                       case '!':               // ! or !=
                                if (*ln == '=')
                                {
-                                       *tk++ = NE;
-                                       ++ln;
+                                       *tk.u32++ = NE;
+                                       ln++;
                                }
                                else
-                                       *tk++ = '!';
+                                       *tk.u32++ = '!';
 
                                continue;
-                       case '\'':              // 'string' 
-                       case '\"':              // "string" 
+                       case '\'':              // 'string'
+                               if (m6502)
+                               {
+                                       // Hardcoded for now, maybe this will change in the future
+                                       *tk.u32++ = STRINGA8;
+                                       goto dostring;
+                               }
+                               // Fall through
+                       case '\"':              // "string"
+                               *tk.u32++ = STRING;
+dostring:
                                c1 = ln[-1];
-                               *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
                                string[stringNum] = ln;
-                               *tk++ = stringNum;
+                               *tk.u32++ = stringNum;
                                stringNum++;
-#endif
 
                                for(p=ln; *ln!=EOS && *ln!=c1;)
                                {
@@ -1205,6 +1298,11 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                                case '\\':
                                                        c = '\\';
                                                        break;
+                                               case '!':
+                                                       // If we're evaluating a macro
+                                                       // this is valid and expands to
+                                                       // "dot-size"
+                                                       break;
                                                default:
                                                        warn("bad backslash code in string");
                                                        ln--;
@@ -1229,42 +1327,9 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        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')
                                                        {
@@ -1278,76 +1343,94 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                                        }
                                                        else if ((*(ln + 1) & 0xDF) == 'L')
                                                        {
+                                                               v &= 0xFFFFFFFF;
                                                                ln += 2;
                                                        }
                                                }
                                        }
 
-                                       *tk++ = CONST;
-                                       *tk++ = v;
+                                       *tk.u32++ = CONST;
+                                       *tk.u64++ = v;
+
+                                       if (obj_format == ALCYON)
+                                       {
+                                               if (*ln == '.')
+                                               {
+                                                       if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W'))
+                                                       {
+                                                               *tk.u32++ = DOTW;
+                                                               ln += 2;
+                                                       }
+                                                       else if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
+                                                       {
+                                                               *tk.u32++ = DOTL;
+                                                               ln += 2;
+                                                       }
+                                               }
+                                       }
                                }
                                else
-                                       *tk++ = '$';
+                                       *tk.u32++ = '$';
 
                                continue;
-                       case '<':               // < or << or <> or <= 
+                       case '<':               // < or << or <> or <=
                                switch (*ln)
                                {
                                case '<':
-                                       *tk++ = SHL;
-                                       ++ln;
+                                       *tk.u32++ = SHL;
+                                       ln++;
                                        continue;
                                case '>':
-                                       *tk++ = NE;
-                                       ++ln;
+                                       *tk.u32++ = NE;
+                                       ln++;
                                        continue;
                                case '=':
-                                       *tk++ = LE;
-                                       ++ln;
+                                       *tk.u32++ = LE;
+                                       ln++;
                                        continue;
                                default:
-                                       *tk++ = '<';
+                                       *tk.u32++ = '<';
                                        continue;
                                }
                        case ':':               // : or ::
                                if (*ln == ':')
                                {
-                                       *tk++ = DCOLON;
-                                       ++ln;
+                                       *tk.u32++ = DCOLON;
+                                       ln++;
                                }
                                else
-                                       *tk++ = ':';
+                                       *tk.u32++ = ':';
 
                                continue;
-                       case '=':               // = or == 
+                       case '=':               // = or ==
                                if (*ln == '=')
                                {
-                                       *tk++ = DEQUALS;
-                                       ++ln;
+                                       *tk.u32++ = DEQUALS;
+                                       ln++;
                                }
                                else
-                                       *tk++ = '=';
+                                       *tk.u32++ = '=';
 
                                continue;
-                       case '>':               // > or >> or >= 
+                       case '>':               // > or >> or >=
                                switch (*ln)
                                {
                                case '>':
-                                       *tk++ = SHR;
+                                       *tk.u32++ = SHR;
                                        ln++;
                                        continue;
                                case '=':
-                                       *tk++ = GE;
+                                       *tk.u32++ = GE;
                                        ln++;
                                        continue;
                                default:
-                                       *tk++ = '>';
+                                       *tk.u32++ = '>';
                                        continue;
                                }
-                       case '%':               // % or binary constant 
+                       case '%':               // % or binary constant
                                if (*ln < '0' || *ln > '1')
                                {
-                                       *tk++ = '%';
+                                       *tk.u32++ = '%';
                                        continue;
                                }
 
@@ -1372,17 +1455,18 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
 
                                        if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
                                        {
+                                               v &= 0xFFFFFFFF;
                                                ln += 2;
                                        }
                                }
 
-                               *tk++ = CONST;
-                               *tk++ = v;
+                               *tk.u32++ = CONST;
+                               *tk.u64++ = v;
                                continue;
-                       case '@':               // @ or octal constant 
+                       case '@':               // @ or octal constant
                                if (*ln < '0' || *ln > '7')
                                {
-                                       *tk++ = '@';
+                                       *tk.u32++ = '@';
                                        continue;
                                }
 
@@ -1393,31 +1477,32 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
 
                                if (*ln == '.')
                                {
-                                       if ((*(ln+1) == 'b') || (*(ln+1) == 'B'))
+                                       if ((*(ln + 1) == 'b') || (*(ln + 1) == 'B'))
                                        {
                                                v &= 0x000000FF;
                                                ln += 2;
                                        }
 
-                                       if ((*(ln+1) == 'w') || (*(ln+1) == 'W'))
+                                       if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W'))
                                        {
                                                v &= 0x0000FFFF;
                                                ln += 2;
                                        }
 
-                                       if ((*(ln+1) == 'l') || (*(ln+1) == 'L'))
+                                       if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
                                        {
+                                               v &= 0xFFFFFFFF;
                                                ln += 2;
                                        }
                                }
 
-                               *tk++ = CONST;
-                               *tk++ = v;
+                               *tk.u32++ = CONST;
+                               *tk.u64++ = v;
                                continue;
                        case '^':               // ^ or ^^ <operator-name>
                                if (*ln != '^')
                                {
-                                       *tk++ = '^';
+                                       *tk.u32++ = '^';
                                        continue;
                                }
 
@@ -1434,7 +1519,7 @@ if (debug) 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')
@@ -1463,7 +1548,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                        continue;
                                }
 
-                               *tk++ = (TOKEN)j;
+                               *tk.u32++ = (TOKEN)j;
                                continue;
                        default:
                                interror(2);    // Bad MULTX entry in chrtab
@@ -1474,6 +1559,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                // Handle decimal constant
                if (c & DIGIT)
                {
+                       uint8_t * numStart = ln;
                        v = 0;
 
                        while ((int)chrtab[*ln] & DIGIT)
@@ -1486,37 +1572,80 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n");
                                {
                                        v &= 0x000000FF;
                                        ln += 2;
+                                       *tk.u32++ = CONST;
+                                       *tk.u64++ = v;
+                                       *tk.u32++ = DOTB;
                                }
                                else if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W'))
                                {
                                        v &= 0x0000FFFF;
                                        ln += 2;
+                                       *tk.u32++ = CONST;
+                                       *tk.u64++ = v;
+                                       *tk.u32++ = DOTW;
                                }
                                else if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
                                {
+                                       v &= 0xFFFFFFFF;
                                        ln += 2;
+                                       *tk.u32++ = CONST;
+                                       *tk.u64++ = v;
+                                       *tk.u32++ = DOTL;
                                }
+                               else if ((int)chrtab[*(ln + 1)] & DIGIT)
+                               {
+                                       // Hey, more digits after the dot, so we assume it's a
+                                       // floating point number of some kind
+#if 0
+                                       double fract = 10;
+                                       ln++;
+                                       f = (double)v;
+
+                                       while ((int)chrtab[*ln] & DIGIT)
+                                       {
+                                               f = f + (double)(*ln++ - '0') / fract;
+                                               fract *= 10;
+                                       }
+#else
+                                       // Here we parse the whole floating point number
+                                       char * numEnd;
+                                       errno = 0;
+                                       double f = strtod(numStart, &numEnd);
+                                       ln = (uint8_t *)numEnd;
+
+                                       if (errno != 0)
+                                               return error("floating point parse error");
+#endif
+
+                                       *tk.u32++ = FCONST;
+// Shamus: Well, this is all kinds of icky--not the least of which is that unlike uintNN_t types, we have no guarantees of any kind when it comes to the size of floating point numbers in C (as far as I know of). If there is, we need to use those kinds here, or else figure out at runtime what sizes we're dealing with and act accordingly. To be fair, this is OK as long as the double type is less than 64 bits wide, but again, there's no guarantee that it isn't. :-/
+                                       *tk.u64++ = f;
+                                       continue;
+                               }
+                       }
+                       else
+                       {
+                               *tk.u32++ = CONST;
+                               *tk.u64++ = v;
                        }
 
-                       *tk++ = CONST;
-                       *tk++ = v;
 //printf("CONST: %i\n", v);
                        continue;
                }
 
                // Handle illegal character
-               return error("illegal character");
+               return error("illegal character $%02X found", *ln);
        }
 
        // Terminate line of tokens and return "success."
 
 goteol:
-       tok = etok;                                                             // Set tok to beginning of line
+       tok = etok;                                                     // Set tok to beginning of line
 
        if (stuffnull)                                                  // Terminate last SYMBOL
                *nullspot = EOS;
 
-       *tk++ = EOL;
+       *tk.u32++ = EOL;
 
        return OK;
 }
@@ -1524,30 +1653,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;
 
@@ -1555,40 +1679,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;
+       LLIST * 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++;
                        }
                }
        }
@@ -1597,22 +1716,105 @@ WARNING(!!!! Bad string comparison !!!)
 }
 
 
+void DumpToken(TOKEN t)
+{
+       if (t == COLON)
+               printf("[COLON]");
+       else if (t == CONST)
+               printf("[CONST]");
+       else if (t == ACONST)
+               printf("[ACONST]");
+       else if (t == STRING)
+               printf("[STRING]");
+       else if (t == SYMBOL)
+               printf("[SYMBOL]");
+       else if (t == EOS)
+               printf("[EOS]");
+       else if (t == TKEOF)
+               printf("[TKEOF]");
+       else if (t == DEQUALS)
+               printf("[DEQUALS]");
+       else if (t == SET)
+               printf("[SET]");
+       else if (t == REG)
+               printf("[REG]");
+       else if (t == DCOLON)
+               printf("[DCOLON]");
+       else if (t == GE)
+               printf("[GE]");
+       else if (t == LE)
+               printf("[LE]");
+       else if (t == NE)
+               printf("[NE]");
+       else if (t == SHR)
+               printf("[SHR]");
+       else if (t == SHL)
+               printf("[SHL]");
+       else if (t == UNMINUS)
+               printf("[UNMINUS]");
+       else if (t == DOTB)
+               printf("[DOTB]");
+       else if (t == DOTW)
+               printf("[DOTW]");
+       else if (t == DOTL)
+               printf("[DOTL]");
+       else if (t == DOTQ)
+               printf("[DOTQ]");
+       else if (t == DOTS)
+               printf("[DOTS]");
+       else if (t == DOTD)
+               printf("[DOTD]");
+       else if (t == DOTI)
+               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)
+               printf("[CR_REFERENCED]");
+       else if (t == CR_STREQ)
+               printf("[CR_STREQ]");
+       else if (t == CR_MACDEF)
+               printf("[CR_MACDEF]");
+       else if (t == CR_TIME)
+               printf("[CR_TIME]");
+       else if (t == CR_DATE)
+               printf("[CR_DATE]");
+       else if (t >= 0x20 && t <= 0x2F)
+               printf("[%c]", (char)t);
+       else if (t >= 0x3A && t <= 0x3F)
+               printf("[%c]", (char)t);
+       else if (t >= 0x80 && t <= 0x87)
+               printf("[D%u]", ((uint32_t)t) - 0x80);
+       else if (t >= 0x88 && t <= 0x8F)
+               printf("[A%u]", ((uint32_t)t) - 0x88);
+       else
+               printf("[%X:%c]", (uint32_t)t, (char)t);
+}
+
+
 void DumpTokenBuffer(void)
 {
-       TOKEN * t;
        printf("Tokens [%X]: ", sloc);
 
-       for(t=tokbuf; *t!=EOL; t++)
+       for(TOKEN * t=tokbuf; *t!=EOL; t++)
        {
                if (*t == COLON)
                        printf("[COLON]");
                else if (*t == CONST)
                {
-                       t++;
-                       printf("[CONST: $%X]", (uint32_t)*t);
+                       PTR tp;
+                       tp.u32 = t + 1;
+                       printf("[CONST: $%lX]", *tp.u64);
+                       t += 2;
                }
                else if (*t == ACONST)
-                       printf("[ACONST]");
+               {
+                       printf("[ACONST: $%X, $%X]", (uint32_t)t[1], (uint32_t)t[2]);
+                       t += 2;
+               }
                else if (*t == STRING)
                {
                        t++;
@@ -1653,6 +1855,12 @@ void DumpTokenBuffer(void)
                        printf("[DOTW]");
                else if (*t == DOTL)
                        printf("[DOTL]");
+               else if (*t == DOTQ)
+                       printf("[DOTQ]");
+               else if (*t == DOTS)
+                       printf("[DOTS]");
+               else if (*t == DOTD)
+                       printf("[DOTD]");
                else if (*t == DOTI)
                        printf("[DOTI]");
                else if (*t == ENDEXPR)