]> Shamusworld >> Repos - rmac/blobdiff - expr.c
Treat ':' as a path separator on non-Windows platforms
[rmac] / expr.c
diff --git a/expr.c b/expr.c
index d1ee1f55a1ffc824ecfaa540a91aa8b422baa17d..65b4a1149ec37058e3354a810ca0421ff982294d 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -1,7 +1,7 @@
 //
-// RMAC - Reboot's Macro Assembler for all Atari computers
+// RMAC - Renamed Macro Assembler for all Atari computers
 // EXPR.C - Expression Analyzer
-// Copyright (C) 199x Landon Dyer, 2011-2019 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
 // Source utilised with the kind permission of Landon Dyer
 //
@@ -35,7 +35,7 @@ char itokcl[] = {
        CR_DEFINED, CR_REFERENCED,              // SUNARY (special unary)
        CR_STREQ, CR_MACDEF,
        CR_DATE, CR_TIME,
-       CR_ABSCOUNT, 0,
+       CR_ABSCOUNT, CR_FILESIZE, 0,
        '!', '~', UNMINUS, UNLT, UNGT, 0,       // UNARY
        '*', '/', '%', 0,                               // MULT
        '+', '-', 0,                                    // ADD
@@ -155,8 +155,53 @@ int expr1(void)
                switch (*tok++)
                {
                case CR_ABSCOUNT:
+                       if (cursect != ABS)
+                       {
+                               *evalTokenBuffer.u32++ = CONST;
+                               *evalTokenBuffer.u64++ = sect[ABS].sloc;
+                       }
+                       else
+                       {
+                               *evalTokenBuffer.u32++ = CONST;
+                               *evalTokenBuffer.u64++ = sloc;
+                       }
+                       break;
+               case CR_FILESIZE:
+                       if (*tok++ != STRING)
+                               return error("^^FILESIZE expects filename inside string");
                        *evalTokenBuffer.u32++ = CONST;
-                       *evalTokenBuffer.u64++ = (uint64_t)sect[ABS].sloc;
+                       // @@copypasted from d_incbin, maybe factor this out somehow?
+                       // Attempt to open the include file in the current directory, then (if that
+                       // failed) try list of include files passed in the enviroment string or by
+                       // the "-d" option.
+                       int fd, i;
+                       char buf1[256];
+
+                       if ((fd = open(string[*tok], _OPEN_INC)) < 0)
+                       {
+                               for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
+                               {
+                                       fd = strlen(buf1);
+
+                                       // Append path char if necessary
+                                       if ((fd > 0) && (buf1[fd - 1] != SLASHCHAR))
+                                               strcat(buf1, SLASHSTRING);
+
+                                       strcat(buf1, string[*tok]);
+
+                                       if ((fd = open(buf1, _OPEN_INC)) >= 0)
+                                               goto allright;
+                               }
+
+                               return error("cannot open: \"%s\"", string[tok[1]]);
+                       }
+
+allright:
+                       *evalTokenBuffer.u64++ = (uint64_t)lseek(fd, 0L, SEEK_END);
+                       close(fd);
+
+                       // Advance tok because of consumed string token
+                       tok++;
                        break;
                case CR_TIME:
                        *evalTokenBuffer.u32++ = CONST;
@@ -336,49 +381,20 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
        PTR ptk;
 
        evalTokenBuffer.u32 = otk;      // Set token pointer to 'exprbuf' (direct.c)
-                                                       // Also set in various other places too (riscasm.c,
-                                                       // e.g.)
+                                                               // Also set in various other places too (riscasm.c,
+                                                               // e.g.)
 
-//printf("expr(): tokens 0-2: %i %i %i (%c %c %c); tc[2] = %i\n", tok[0], tok[1], tok[2], tok[0], tok[1], tok[2], tokenClass[tok[2]]);
        // Optimize for single constant or single symbol.
-       // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
-       //         followed by the value 101, it will trigger a bad evaluation here.
-       //         This is probably a really bad assumption to be making here...!
-       //         (assuming tok[1] == EOL is a single token that is)
-       //         Seems that even other tokens (SUNARY type) can fuck this up too.
-#if 0
-//     if ((tok[1] == EOL)
-       if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
-//             || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
-//             && (tokenClass[tok[2]] < UNARY)))
-               || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
-                       && (tokenClass[tok[2]] < UNARY))
-               || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
-               )
-#else
 // Shamus: Seems to me that this could be greatly simplified by 1st checking if the first token is a multibyte token, *then* checking if there's an EOL after it depending on the actual length of the token (multiple vs. single). Otherwise, we have the horror show that is the following:
        if ((tok[1] == EOL
                        && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY))
-               || (((tok[0] == SYMBOL)
-                               || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
+               || ((tok[0] == SYMBOL)
                        && (tokenClass[tok[2]] < UNARY))
                || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY))
                )
-// Shamus: Yes, you can parse that out and make some kind of sense of it, but damn, it takes a while to get it and understand the subtle bugs that result from not being careful about what you're checking; especially vis-a-vis niavely checking tok[1] for an EOL. O_o
-#endif
+// Shamus: Yes, you can parse that out and make some kind of sense of it, but damn, it takes a while to get it and understand the subtle bugs that result from not being careful about what you're checking; especially vis-a-vis naively checking tok[1] for an EOL. O_o
        {
-               if (*tok >= KW_R0 && *tok <= KW_R31)
-               {
-                       *evalTokenBuffer.u32++ = CONST;
-                       *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0);
-                       *a_attr = ABS | DEFINED;
-
-                       if (a_esym != NULL)
-                               *a_esym = NULL;
-
-                       tok++;
-               }
-               else if (*tok == CONST)
+               if (*tok == CONST)
                {
                        ptk.u32 = tok;
                        *evalTokenBuffer.u32++ = *ptk.u32++;
@@ -476,19 +492,19 @@ be converted from a linked list into an array).
                        symbolNum++;
 #endif
 
-                       if (symbol->sattr & DEFINED)
-                               *a_value = symbol->svalue;
-                       else
-                               *a_value = 0;
+                       *a_value = (symbol->sattr & DEFINED ? symbol->svalue : 0);
+                       *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
 
 /*
 All that extra crap that was put into the svalue when doing the equr stuff is
 thrown away right here. What the hell is it for?
 */
                        if (symbol->sattre & EQUATEDREG)
+                       {
                                *a_value &= 0x1F;
-
-                       *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
+                               *a_attr |= RISCREG; // Mark it as a register, 'cause it is
+                               *a_esym = symbol;
+                       }
 
                        if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
                                && a_esym != NULL)