X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=parmode.h;h=27863d08c69f65f0886ec64c2ad6cd736cf03ecc;hp=c03be6e144625ac7bce95e89de06b6aa5bec4c25;hb=HEAD;hpb=7d748dc6e2259984c9093c48d84ae1ed280632ad diff --git a/parmode.h b/parmode.h index c03be6e..27863d0 100644 --- a/parmode.h +++ b/parmode.h @@ -37,10 +37,6 @@ AMn = IMMED; } - // Small problem with this is that the opening parentheses might be an - // expression that's part of a displacement; this code will falsely flag - // that as an error. - // (An) // (An)+ // (An,Xn[.siz][*scale]) @@ -919,14 +915,72 @@ IS_SUPPRESSEDn: else { // (expr... + // We have an aliasing problem here, because a couple of differenct cases end up here: + // (a0), 0(a0,d0), (-288,a0,d0.l) can be easily detected and parsed. + // But what about (160*150)+4(A1)? With the old scheme, i.e. skip past the left parenthesis and try to parse the inside + // tokens will only parse (160*150) and everything else is assumed that it's part of the ea, i.e. +4(a1). This would produce + // an error since the parser would expect (a1). The way to work around this used to be to wrap all the displacement in + // parenthesis, ((160*150)+4)(a1). But that's something the user really doesn't want to think about. + // What we can do is to peek ahead in the token stream and see if we have something that reminds of an expression + // (i.e. no register tokens or commas) until we hit an open parenthesis plus a register (parenthesis balance during the scan + // has to be maintained of course, otherwise we might be led into false conclusions). + TOKEN *look_ahead = tok; + int parenthesis_level = 1; // We count the opening parenthesis so we're not at level 0 + int this_is_an_expression = 0; + while (1) + { + if (*look_ahead == EOL) + { + // Something really bad happened, abort + return error("reached end of line while parsing expression"); + } + if (*look_ahead == '(') + { + if (parenthesis_level == 0) + { + if (look_ahead[1] == EOL) + { + return error("reached end of line while parsing expression"); + } + if ((look_ahead[1] >= REG68_A0 && look_ahead[1] <= REG68_A7) || look_ahead[1] == REG68_PC) + { + tok--; // Rewind token pointer to start of parenthesis + this_is_an_expression = 1; + break; + } + } + parenthesis_level++; + look_ahead++; + continue; + } + if (*look_ahead == ',' || (*look_ahead >= REG68_A0 && *look_ahead <= REG68_A7)) + { + // Nope, this is a different case, abort + break; + } + if (*look_ahead == ')') + { + parenthesis_level--; + if (parenthesis_level < 0) return error("unbalanced parenthesis in expression"); + look_ahead++; + continue; + } + if (*look_ahead == ACONST||*look_ahead==FCONST) + { + look_ahead += 3; // Skip all the data associated with ACONST + continue; + } + + look_ahead++; + } + if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK) return ERROR; // It could be that this is really just an expression prefixing a // register as a displacement... - if (*tok == ')') + if (*tok == '(') { - tok++; goto CHK_FOR_DISPn; } @@ -1167,7 +1221,7 @@ CHK_FOR_DISPn: { // When PC relative is enforced, check for any symbols that aren't // EQU'd, in this case it's an illegal mode - if ((CHECK_OPTS(OPT_PC_RELATIVE)) && (AnEXATTR & (DEFINED | REFERENCED | EQUATED) == (DEFINED | REFERENCED))) + if ((CHECK_OPTS(OPT_PC_RELATIVE)) && ((AnEXATTR & (DEFINED | REFERENCED | EQUATED)) == (DEFINED | REFERENCED))) return error("relocation not allowed when o30 is enabled"); tok++;