//
// RMAC - Reboot's Macro Assembler for all Atari computers
// EXPR.C - Expression Analyzer
-// Copyright (C) 199x Landon Dyer, 2011-2018 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
CR_DEFINED, CR_REFERENCED, // SUNARY (special unary)
CR_STREQ, CR_MACDEF,
CR_DATE, CR_TIME,
- CR_ABSCOUNT, 0,
- '!', '~', UNMINUS, 0, // UNARY
+ CR_ABSCOUNT, CR_FILESIZE, 0,
+ '!', '~', UNMINUS, UNLT, UNGT, 0, // UNARY
'*', '/', '%', 0, // MULT
'+', '-', 0, // ADD
SHL, SHR, 0, // SHIFT
const char missym_error[] = "missing symbol";
const char str_error[] = "missing symbol or string";
+const char noflt_error[] = "operator not usable with float";
// Convert expression to postfix
static PTR evalTokenBuffer; // Deposit tokens here (this is really a
//
int expr1(void)
{
- TOKEN t;
- SYM * sy;
- char * p, * p2;
+ char * p;
WORD w;
- int j;
int class = tokenClass[*tok];
- if (*tok == '-' || *tok == '+' || class == UNARY)
+ if (*tok == '-' || *tok == '+' || *tok == '<' || *tok == '>' || class == UNARY)
{
- t = *tok++;
+ TOKEN t = *tok++;
if (expr2() != OK)
return ERROR;
if (t == '-')
t = UNMINUS;
+ else if (t == '<')
+ t = UNLT;
+ else if (t == '>')
+ t = UNGT;
// With leading + we don't have to deposit anything to the buffer
// because there's no unary '+' nor we have to do anything about it
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;
return error(missym_error);
p = string[*tok++];
- j = (*p == '.' ? curenv : 0);
- w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
+ int j = (*p == '.' ? curenv : 0);
+ SYM * sy = lookup(p, LABEL, j);
+ w = ((sy != NULL) && (sy->sattr & w ? 1 : 0));
*evalTokenBuffer.u32++ = CONST;
*evalTokenBuffer.u64++ = (uint64_t)w;
break;
if (*tok != SYMBOL && *tok != STRING)
return error(str_error);
- p2 = string[tok[1]];
+ char * p2 = string[tok[1]];
tok += 2;
w = (WORD)(!strcmp(p, p2));
//
int expr2(void)
{
- char * p;
- SYM * sy;
- int j;
PTR ptk;
switch (*tok++)
tok = ptk.u32;
break;
case SYMBOL:
- p = string[*tok++];
- j = (*p == '.' ? curenv : 0);
- sy = lookup(p, LABEL, j);
+ {
+ char * p = string[*tok++];
+ int j = (*p == '.' ? curenv : 0);
+ SYM * sy = lookup(p, LABEL, j);
if (sy == NULL)
sy = NewSymbol(p, LABEL, j);
symbolPtr[symbolNum] = sy;
symbolNum++;
break;
+ }
case STRING:
*evalTokenBuffer.u32++ = CONST;
*evalTokenBuffer.u64++ = str_value(string[*tok++]);
tok += 2;
}
+ // Holy hell... This is likely due to the fact that LSR is mistakenly set as a SUNARY type... Need to fix this... !!! FIX !!!
+ else if (m6502)
+ {
+ *evalTokenBuffer.u32++ = *tok++;
+ }
else
{
// Unknown type here... Alert the user!,
- error("undefined RISC register in expression");
+ error("undefined RISC register in expression [token=$%X]", *tok);
// Prevent spurious error reporting...
tok++;
return ERROR;
//
int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
{
- WORD attr, attr2;
+ WORD attr;
SYM * sy;
uint64_t * sval = evstk; // (Empty) initial stack
WORD * sattr = evattr;
break;
+ case UNLT: // Unary < (get the low byte of a word)
+//printf("evexpr(): UNLT\n");
+ if (*sattr & TDB)
+ return error(seg_error);
+
+ if (*sattr & FLOAT)
+ return error(noflt_error);
+
+ *sval = (int64_t)((*sval) & 0x00FF);
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+
+ case UNGT: // Unary > (get the high byte of a word)
+//printf("evexpr(): UNGT\n");
+ if (*sattr & TDB)
+ return error(seg_error);
+
+ if (*sattr & FLOAT)
+ return error(noflt_error);
+
+ *sval = (int64_t)(((*sval) >> 8) & 0x00FF);
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+
case '!':
//printf("evexpr(): !\n");
if (*sattr & TDB)
// All other binary operators must have two ABS items to work with.
// They all produce an ABS value.
+ // Shamus: Is this true? There's at least one counterexample of legit
+ // code where this assumption fails to produce correct code.
default:
//printf("evexpr(): default\n");
- // GH - Removed for v1.0.15 as part of the fix for indexed loads.
- //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
- //error(seg_error);
switch ((int)tk.u32[-1])
{
}
//printf("%i\n", *sval);
- *sattr = ABS | DEFINED | attr; // Expr becomes absolute
+//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute
break;
case '/':
}
//printf("%i\n", *sval);
- *sattr = ABS | DEFINED | attr; // Expr becomes absolute
+//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute
break;
case '%':
return error("mod (%) by zero");
*sval %= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
case SHL:
return error("floating point numbers not allowed with operator '<<'.");
*sval <<= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
case SHR:
return error("floating point numbers not allowed with operator '>>'.");
*sval >>= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '&':
return error("floating point numbers not allowed with operator '&'.");
*sval &= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '^':
return error("floating point numbers not allowed with operator '^'.");
*sval ^= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '|':
return error("floating point numbers not allowed with operator '|'.");
*sval |= sval[1];
- *sattr = ABS | DEFINED; // Expr becomes absolute
+//no *sattr = ABS | DEFINED; // Expr becomes absolute
break;
default: