X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fexpr.c;h=497a6143abbece80766303dd70af328eb520dd0f;hb=46209118b1a77d2e57f28026b1e5916c2c074778;hp=509dc6ebacea6f4d060cc7de37e8889ffeded0ef;hpb=522c7e8c46d0aae3b13885a769ca4a9e87e36733;p=cc65 diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 509dc6eba..497a6143a 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -33,12 +33,19 @@ -#include "../common/exprdefs.h" +#include +/* 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" -#include "mem.h" #include "nexttok.h" #include "objcode.h" #include "objfile.h" @@ -85,7 +92,7 @@ static ExprNode* NewExprNode (void) FreeExprNodes = N->Left; } else { /* Allocate fresh memory */ - N = Xmalloc (sizeof (ExprNode)); + N = xmalloc (sizeof (ExprNode)); } N->Op = EXPR_NULL; N->Left = N->Right = 0; @@ -106,152 +113,13 @@ static void FreeExprNode (ExprNode* E) FreeExprNodes = E; } else { /* Free the memory */ - Xfree (E); + xfree (E); } } } -/*****************************************************************************/ -/* 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 */ /*****************************************************************************/ @@ -467,6 +335,111 @@ static int FuncReferenced (void) +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 */ +{ + /* We have a list of tokens that ends with the closing paren. Skip + * the tokens, handling nested braces and count them. + */ + int Count = 0; + unsigned Parens = 0; + while (Parens != 0 || Tok != TOK_RPAREN) { + + /* Check for end of line or end of input. Since the calling function + * will check for the closing paren, we don't need to print an error + * here, just bail out. + */ + if (Tok == TOK_SEP || Tok == TOK_EOF) { + break; + } + + /* One more token */ + ++Count; + + /* Keep track of the nesting level */ + switch (Tok) { + case TOK_LPAREN: ++Parens; break; + case TOK_RPAREN: --Parens; break; + default: break; + } + + /* Skip the token */ + NextTok (); + } + + /* Return the number of tokens */ + return Count; +} + + + static int FuncXMatch (void) /* Handle the .XMATCH function */ { @@ -492,7 +465,7 @@ static ExprNode* Function (int (*F) (void)) NextTok (); /* Call the function itself */ - Result = (F () != 0); + Result = F (); /* Closing brace must follow */ ConsumeRParen (); @@ -511,8 +484,12 @@ static ExprNode* Factor (void) switch (Tok) { case TOK_INTCON: + N = LiteralExpr (IVal); + NextTok (); + break; + case TOK_CHARCON: - N = LiteralExpr (IVal); + N = LiteralExpr (TgtTranslateChar (IVal)); NextTok (); break; @@ -530,7 +507,7 @@ static ExprNode* Factor (void) /* Create symbol node */ N = NewExprNode (); N->Op = EXPR_SYMBOL; - N->V.Sym = S; + N->V.Sym = S; } NextTok (); } @@ -579,14 +556,14 @@ static ExprNode* Factor (void) 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: @@ -620,13 +597,30 @@ static ExprNode* Factor (void) 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; + case TOK_XMATCH: N = Function (FuncXMatch); 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; } @@ -1043,7 +1037,7 @@ int IsConstExpr (ExprNode* Root) case EXPR_SYMBOL: Sym = Root->V.Sym; if (SymHasUserMark (Sym)) { - if (Verbose) { + if (Verbosity > 0) { DumpExpr (Root); } PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE); @@ -1116,10 +1110,13 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte) 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: @@ -1158,7 +1155,8 @@ int IsByteExpr (ExprNode* Root) 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 { @@ -1255,12 +1253,18 @@ long GetExprVal (ExprNode* Expr) 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); @@ -1308,7 +1312,7 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone) SymEntry* Sym = Expr->V.Sym; if (SymHasUserMark (Sym)) { /* Circular definition */ - if (Verbose) { + if (Verbosity) { DumpExpr (Expr); } PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);