X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=expr.c;h=3a23e6e3cf68d4949ef1372ca98da1defecac7f6;hp=82bb5c6a8ccb2928d0a16256b652bb0cb7f1d0dc;hb=c38505ee4b2a0de59926107e52fb8bb84041a0e4;hpb=0951a3e28907fbaf89a10c5201b71d8080ffe5a8 diff --git a/expr.c b/expr.c index 82bb5c6..3a23e6e 100644 --- a/expr.c +++ b/expr.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for all Atari computers // EXPR.C - Expression Analyzer -// Copyright (C) 199x Landon Dyer, 2011-2017 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 // @@ -35,8 +35,8 @@ char itokcl[] = { 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 @@ -49,6 +49,7 @@ char itokcl[] = { 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 @@ -125,23 +126,24 @@ int expr0(void) // 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 @@ -153,8 +155,54 @@ 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; @@ -183,8 +231,9 @@ getsym: 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; @@ -201,7 +250,7 @@ getsym: 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)); @@ -222,9 +271,6 @@ getsym: // int expr2(void) { - char * p; - SYM * sy; - int j; PTR ptk; switch (*tok++) @@ -242,9 +288,10 @@ int expr2(void) 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); @@ -264,6 +311,7 @@ int expr2(void) symbolPtr[symbolNum] = sy; symbolNum++; break; + } case STRING: *evalTokenBuffer.u32++ = CONST; *evalTokenBuffer.u64++ = str_value(string[*tok++]); @@ -494,10 +542,15 @@ thrown away right here. What the hell is it for? 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; @@ -523,7 +576,7 @@ thrown away right here. What the hell is it for? // 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; @@ -691,6 +744,30 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); 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) @@ -900,11 +977,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // 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]) { @@ -936,7 +1012,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It } //printf("%i\n", *sval); - *sattr = ABS | DEFINED | attr; // Expr becomes absolute +//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute break; case '/': @@ -974,7 +1050,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It } //printf("%i\n", *sval); - *sattr = ABS | DEFINED | attr; // Expr becomes absolute +//no *sattr = ABS | DEFINED | attr; // Expr becomes absolute break; case '%': @@ -988,7 +1064,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It return error("mod (%) by zero"); *sval %= sval[1]; - *sattr = ABS | DEFINED; // Expr becomes absolute +//no *sattr = ABS | DEFINED; // Expr becomes absolute break; case SHL: @@ -999,7 +1075,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It 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: @@ -1010,7 +1086,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It 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 '&': @@ -1021,7 +1097,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It 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 '^': @@ -1032,7 +1108,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It 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 '|': @@ -1043,7 +1119,7 @@ An open question here is do we promote ints to floats as signed or unsigned? It 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: @@ -1066,3 +1142,27 @@ An open question here is do we promote ints to floats as signed or unsigned? It return OK; } + +// +// Count the # of tokens in the passed in expression +// N.B.: 64-bit constants count as two tokens each +// +uint16_t ExpressionLength(TOKEN * tk) +{ + uint16_t length; + + for(length=0; tk[length]!=ENDEXPR; length++) + { + // Add one to length for 2X tokens, two for 3X tokens + if (tk[length] == SYMBOL) + length++; + else if ((tk[length] == CONST) || (tk[length] == FCONST)) + length += 2; + } + + // Add 1 for ENDEXPR + length++; + + return length; +} +