]> Shamusworld >> Repos - rmac/blobdiff - token.c
Added floating point support to expression evaluator, introduced FLOAT token, fixup...
[rmac] / token.c
diff --git a/token.c b/token.c
index 27eedc3d849b500d57305740b9d8d910cba6f476..f719dc356791e84142046f6e6251afe62e2ad345 100644 (file)
--- a/token.c
+++ b/token.c
@@ -36,6 +36,7 @@ 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
+int optimizeOff;                       // Optimization override flag
 
 // File record, used to maintain a list of every include file ever visited
 #define FILEREC struct _filerec
@@ -48,12 +49,12 @@ 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)
 
 uint8_t chrtab[0x100] = {
        ILLEG, ILLEG, ILLEG, ILLEG,                     // NUL SOH STX ETX
@@ -475,24 +476,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:
@@ -573,7 +568,8 @@ DEBUG { printf("ExM: SYMBOL=\"%s\"", d); }
 //         to choke on legitimate code... Need to investigate this further
 //         before changing anything else here!
                                                        case CONST:
-                                                               sprintf(numbuf, "$%lx", (long unsigned int)*tk++);
+                                                               sprintf(numbuf, "$%lx", (uint64_t)*tk++);
+                                                               tk++;
                                                                d = numbuf;
                                                                break;
                                                        case DEQUALS:
@@ -830,17 +826,11 @@ DEBUG { printf("[fpop: (post) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)
        case SRC_IREPT:                                         // Pop and release an IREPT
        {
                DEBUG { printf("dealloc IREPT\n"); }
-//             LONG * p = inobj->inobj.irept->ir_firstln;
                LLIST * p = inobj->inobj.irept->ir_firstln;
 
                // Deallocate repeat lines
                while (p != NULL)
                {
-// Shamus: ggn confirmed that this will cause a segfault on 64-bit versions of
-//         RMAC. This is just stupid and wrong anyway, so we need to fix crapola
-//         like this...
-//                     LONG * p1 = (LONG *)*p;
-//                     p = p1;
                        free(p->line);
                        p = p->next;
                }
@@ -960,11 +950,14 @@ int TokenizeLine(void)
        int state = 0;                          // State for keyword detector
        int j = 0;                                      // Var for keyword detector
        uint8_t c;                                      // Random char
-       VALUE v;                                        // Random value
+       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
        uint8_t c1;
        int stringNum = 0;                      // Pointer to string locations in tokenized line
+       uint64_t * tk64;
 
 retry:
 
@@ -1039,7 +1032,7 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); }
        case SRC_IREPT:
                if ((ln = GetNextRepeatLine()) == NULL)
                {
-DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); }
+                       DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); }
                        fpop();
                        goto retry;
                }
@@ -1065,6 +1058,16 @@ 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;
@@ -1134,7 +1137,8 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); }
                                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 (chrtab[*ln] & CTSYM)
                                        return error("misuse of '.'; not allowed in symbols");
@@ -1293,6 +1297,11 @@ dostring:
                                                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--;
@@ -1311,6 +1320,19 @@ dostring:
                        case '$':               // $, hex constant
                                if (chrtab[*ln] & HDIGIT)
                                {
+                                       if (cursize == 'q' || cursize == 'Q')
+                                       {
+                                               // Parse 64-bit integer
+                                               uint64_t v64 = 0;
+
+                                               while (hextab[*ln] >= 0)
+                                                       v64 = (v64 << 4) + (int)hextab[*ln++];
+
+                                               *(uint64_t *)tk = v64;
+                                               tk = tk + 2;
+
+                                               continue;
+                                       }
                                        v = 0;
 
                                        // Parse the hex value
@@ -1333,13 +1355,16 @@ dostring:
                                                        }
                                                        else if ((*(ln + 1) & 0xDF) == 'L')
                                                        {
+                                                               v &= 0xFFFFFFFF;
                                                                ln += 2;
                                                        }
                                                }
                                        }
 
                                        *tk++ = CONST;
-                                       *tk++ = v;
+                                       tk64 = (uint64_t *)tk;
+                                       *tk64++ = v;
+                                       tk = (TOKEN *)tk64;
 
                                        if (obj_format == ALCYON)
                                        {
@@ -1444,12 +1469,15 @@ dostring:
 
                                        if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
                                        {
+                                               v &= 0xFFFFFFFF;
                                                ln += 2;
                                        }
                                }
 
                                *tk++ = CONST;
-                               *tk++ = v;
+                               tk64 = (uint64_t *)tk;
+                               *tk64++ = v;
+                               tk = (TOKEN *)tk64;
                                continue;
                        case '@':               // @ or octal constant
                                if (*ln < '0' || *ln > '7')
@@ -1479,12 +1507,15 @@ dostring:
 
                                        if ((*(ln+1) == 'l') || (*(ln+1) == 'L'))
                                        {
+                                               v &= 0xFFFFFFFF;
                                                ln += 2;
                                        }
                                }
 
                                *tk++ = CONST;
-                               *tk++ = v;
+                               tk64 = (uint64_t *)tk;
+                               *tk64++ = v;
+                               tk = (TOKEN *)tk64;
                                continue;
                        case '^':               // ^ or ^^ <operator-name>
                                if (*ln != '^')
@@ -1558,20 +1589,62 @@ dostring:
                                {
                                        v &= 0x000000FF;
                                        ln += 2;
+                                       *tk++ = CONST;
+                                       tk64 = (uint64_t *)tk;
+                                       *tk64++ = v;
+                                       tk = (uint32_t *)tk64;
+                                       *tk++ = DOTB;
                                }
                                else if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W'))
                                {
                                        v &= 0x0000FFFF;
                                        ln += 2;
+                                       *tk++ = CONST;
+                                       tk64 = (uint64_t *)tk;
+                                       *tk64++ = v;
+                                       tk = (uint32_t *)tk64;
+
+                                       *tk++ = DOTW;
                                }
                                else if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L'))
                                {
+                                       v &= 0xFFFFFFFF;
                                        ln += 2;
+                                       *tk++ = CONST;
+                                       tk64 = (uint64_t *)tk;
+                                       *tk64++ = v;
+                                       tk = (uint32_t *)tk64;
+
+                                       *tk++ = DOTL;
+                               }
+                               else if ((int)chrtab[*(ln + 1)] & DIGIT)
+                               {
+                                       // Hey, more digits after the dot, so assume it's a
+                                       // fractional number
+                                       double fract = 10;
+                                       ln++;
+                                       f = (double)v;
+
+                                       while ((int)chrtab[*ln] & DIGIT)
+                                       {
+                                               f = f + (double)(*ln++ - '0') / fract;
+                                               fract *= 10;
+                                       }
+
+                                       *tk++ = FCONST;
+                                       *((double *)tk) = f;
+                                       tk += 2;
+                                       continue;
                                }
                        }
+                       else
+                       {
+                               *tk++ = CONST;
+                               tk64 = (uint64_t *)tk;
+                               *tk64++ = v;
+                               tk = (TOKEN *)tk64;
+                       }
 
-                       *tk++ = CONST;
-                       *tk++ = v;
 //printf("CONST: %i\n", v);
                        continue;
                }
@@ -1661,20 +1734,22 @@ int d_goto(WORD unused)
 
 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);
+                       printf("[CONST: $%lX]", ((uint64_t)t[1] << 32) | (uint64_t)t[2]);
+                       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++;