-#include "../common/exprdefs.h"
-#include "../common/xmalloc.h"
+#include <string.h>
+/* common */
+#include "check.h"
+#include "exprdefs.h"
+#include "print.h"
+#include "tgttrans.h"
+#include "xmalloc.h"
+
+/* ca65 */
#include "error.h"
#include "global.h"
#include "instr.h"
-/*****************************************************************************/
-/* Dump an expression tree on stdout for debugging */
-/*****************************************************************************/
-
-
-
-static void InternalDumpExpr (ExprNode* Expr)
-/* Dump an expression in UPN */
-{
- if (Expr == 0) {
- return;
- }
- InternalDumpExpr (Expr->Left);
- InternalDumpExpr (Expr->Right);
-
- switch (Expr->Op) {
-
- case EXPR_LITERAL:
- case EXPR_ULABEL:
- printf (" $%04lX", Expr->V.Val & 0xFFFF);
- break;
-
- case EXPR_SYMBOL:
- printf (" %s", GetSymName (Expr->V.Sym));
- break;
-
- case EXPR_SEGMENT:
- printf (" SEG");
- break;
-
- case EXPR_PLUS:
- printf (" +");
- break;
-
- case EXPR_MINUS:
- printf (" -");
- break;
-
- case EXPR_MUL:
- printf (" *");
- break;
-
- case EXPR_DIV:
- printf (" /");
- break;
-
- case EXPR_MOD:
- printf (" %%");
- break;
-
- case EXPR_OR:
- printf (" OR");
- break;
-
- case EXPR_XOR:
- printf (" XOR");
- break;
-
- case EXPR_AND:
- printf (" AND");
- break;
-
- case EXPR_SHL:
- printf (" SHL");
- break;
-
- case EXPR_SHR:
- printf (" SHR");
- break;
-
- case EXPR_EQ:
- printf (" =");
- break;
-
- case EXPR_NE:
- printf ("<>");
- break;
-
- case EXPR_LT:
- printf (" <");
- break;
-
- case EXPR_GT:
- printf (" >");
- break;
-
- case EXPR_UNARY_MINUS:
- printf (" NEG");
- break;
-
- case EXPR_NOT:
- printf (" ~");
- break;
-
- case EXPR_LOBYTE:
- printf (" LO");
- break;
-
- case EXPR_HIBYTE:
- printf (" HI");
- break;
-
- case EXPR_SWAP:
- printf (" SWAP");
- break;
-
- case EXPR_BAND:
- printf (" BOOL_AND");
- break;
-
- case EXPR_BOR:
- printf (" BOOL_OR");
- break;
-
- case EXPR_BXOR:
- printf (" BOOL_XOR");
- break;
-
- case EXPR_BNOT:
- printf (" BOOL_NOT");
- break;
-
- default:
- Internal ("Unknown Op type: %u", Expr->Op);
-
- }
-}
-
-
-
-void DumpExpr (ExprNode* Expr)
-/* Dump an expression tree to stdout */
-{
- InternalDumpExpr (Expr);
- printf ("\n");
-}
-
-
-
/*****************************************************************************/
/* Code */
/*****************************************************************************/
+static int FuncStrAt (void)
+/* Handle the .STRAT function */
+{
+ char Str [sizeof(SVal)];
+ long Index;
+
+ /* String constant expected */
+ if (Tok != TOK_STRCON) {
+ Error (ERR_STRCON_EXPECTED);
+ NextTok ();
+ return 0;
+
+ }
+
+ /* Remember the string and skip it */
+ strcpy (Str, SVal);
+ NextTok ();
+
+ /* Comma must follow */
+ ConsumeComma ();
+
+ /* Expression expected */
+ Index = ConstExpression ();
+
+ /* Must be a valid index */
+ if (Index >= (long) strlen (Str)) {
+ Error (ERR_RANGE);
+ return 0;
+ }
+
+ /* Return the char, handle as unsigned. Be sure to translate it into
+ * the target character set.
+ */
+ return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
+}
+
+
+
+static int FuncStrLen (void)
+/* Handle the .STRLEN function */
+{
+ /* String constant expected */
+ if (Tok != TOK_STRCON) {
+
+ Error (ERR_STRCON_EXPECTED);
+ /* Smart error recovery */
+ if (Tok != TOK_RPAREN) {
+ NextTok ();
+ }
+ return 0;
+
+ } else {
+
+ /* Get the length of the string */
+ int Len = strlen (SVal);
+
+ /* Skip the string */
+ NextTok ();
+
+ /* Return the length */
+ return Len;
+
+ }
+}
+
+
+
static int FuncTCount (void)
/* Handle the .TCOUNT function */
{
switch (Tok) {
case TOK_LPAREN: ++Parens; break;
case TOK_RPAREN: --Parens; break;
- default: break;
+ default: break;
}
/* Skip the token */
SymEntry* S;
switch (Tok) {
-
+
case TOK_INTCON:
+ N = LiteralExpr (IVal);
+ NextTok ();
+ break;
+
case TOK_CHARCON:
- N = LiteralExpr (IVal);
+ N = LiteralExpr (TgtTranslateChar (IVal));
NextTok ();
break;
/* Create symbol node */
N = NewExprNode ();
N->Op = EXPR_SYMBOL;
- N->V.Sym = S;
+ N->V.Sym = S;
}
NextTok ();
}
NextTok ();
N = NewExprNode ();
N->Left = Factor ();
- N->Op = EXPR_LOBYTE;
+ N->Op = EXPR_BYTE0;
break;
case TOK_GT:
NextTok ();
N = NewExprNode ();
N->Left = Factor ();
- N->Op = EXPR_HIBYTE;
+ N->Op = EXPR_BYTE1;
break;
case TOK_LPAREN:
N = Function (FuncReferenced);
break;
+ case TOK_STRAT:
+ N = Function (FuncStrAt);
+ break;
+
+ case TOK_STRLEN:
+ N = Function (FuncStrLen);
+ break;
+
case TOK_TCOUNT:
N = Function (FuncTCount);
break;
break;
default:
- N = LiteralExpr (0); /* Dummy */
- Error (ERR_SYNTAX);
+ if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
+ /* A character constant */
+ N = LiteralExpr (TgtTranslateChar (SVal[0]));
+ } else {
+ N = LiteralExpr (0); /* Dummy */
+ Error (ERR_SYNTAX);
+ }
NextTok ();
break;
}
case EXPR_SYMBOL:
Sym = Root->V.Sym;
if (SymHasUserMark (Sym)) {
- if (Verbose) {
+ if (Verbosity > 0) {
DumpExpr (Root);
}
PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
case EXPR_LEAFNODE:
switch (N->Op) {
- case EXPR_SYMBOL:
- if (SymIsZP (N->V.Sym)) {
- *IsByte = 1;
- }
+ case EXPR_SYMBOL:
+ if (SymIsZP (N->V.Sym)) {
+ *IsByte = 1;
+ } else if (SymHasExpr (N->V.Sym)) {
+ /* Check if this expression is a byte expression */
+ *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
+ }
break;
case EXPR_SEGMENT:
SimplifyExpr (Root);
}
return IsByteRange (GetExprVal (Root));
- } else if (Root->Op == EXPR_LOBYTE || Root->Op == EXPR_HIBYTE) {
+ } else if (Root->Op == EXPR_BYTE0 || Root->Op == EXPR_BYTE1 ||
+ Root->Op == EXPR_BYTE2 || Root->Op == EXPR_BYTE3) {
/* Symbol forced to have byte range */
IsByte = 1;
} else {
case EXPR_NOT:
return ~GetExprVal (Expr->Left);
- case EXPR_LOBYTE:
+ case EXPR_BYTE0:
return GetExprVal (Expr->Left) & 0xFF;
- case EXPR_HIBYTE:
+ case EXPR_BYTE1:
return (GetExprVal (Expr->Left) >> 8) & 0xFF;
+ case EXPR_BYTE2:
+ return (GetExprVal (Expr->Left) >> 16) & 0xFF;
+
+ case EXPR_BYTE3:
+ return (GetExprVal (Expr->Left) >> 24) & 0xFF;
+
case EXPR_SWAP:
Left = GetExprVal (Expr->Left);
return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00);
SymEntry* Sym = Expr->V.Sym;
if (SymHasUserMark (Sym)) {
/* Circular definition */
- if (Verbose) {
+ if (Verbosity) {
DumpExpr (Expr);
}
PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);