/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* (C) 1998-2007 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
} else {
/* Mark the symbol as referenced */
SymRef (S);
- /* Create symbol node */
- return GenSymExpr (S);
+ /* If the symbol is a variable, return just its value, otherwise
+ * return a reference to the symbol.
+ */
+ if (SymIsVar (S)) {
+ return CloneExpr (GetSymExpr (S));
+ } else {
+ /* Create symbol node */
+ return GenSymExpr (S);
+ }
}
}
static ExprNode* FuncBlank (void)
/* Handle the .BLANK builtin function */
{
- int Result = 1;
-
- /* Assume no tokens if the closing brace follows (this is not correct in
- * all cases, since the token may be the closing brace, but this will
- * give a syntax error anyway and may not be handled by .BLANK.
+ /* We have a list of tokens that ends with the closing paren. Skip
+ * the tokens, and count them. Allow optionally curly braces.
*/
- if (Tok != TOK_RPAREN) {
- /* Skip any tokens */
- int Braces = 0;
- while (!TokIsSep (Tok)) {
- if (Tok == TOK_LPAREN) {
- ++Braces;
- } else if (Tok == TOK_RPAREN) {
- if (Braces == 0) {
- /* Done */
- break;
- } else {
- --Braces;
- }
- }
- NextTok ();
+ enum Token Term = GetTokListTerm (TOK_RPAREN);
+ unsigned Count = 0;
+ while (Tok != Term) {
+
+ /* 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 (TokIsSep (Tok)) {
+ break;
}
- return 0;
+
+ /* One more token */
+ ++Count;
+
+ /* Skip the token */
+ NextTok ();
}
- return GenLiteralExpr (Result);
+
+ /* If the list was enclosed in curly braces, skip the closing brace */
+ if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+ NextTok ();
+ }
+
+ /* Return true if the list was empty */
+ return GenLiteralExpr (Count == 0);
}
int Result;
TokNode* Root = 0;
TokNode* Last = 0;
- TokNode* Node = 0;
+ TokNode* Node;
/* A list of tokens follows. Read this list and remember it building a
* single linked list of tokens including attributes. The list is
- * terminated by a comma.
+ * either enclosed in curly braces, or terminated by a comma.
*/
- while (Tok != TOK_COMMA) {
+ enum Token Term = GetTokListTerm (TOK_COMMA);
+ while (Tok != Term) {
/* We may not end-of-line of end-of-file here */
if (TokIsSep (Tok)) {
Error ("Unexpected end of line");
- return 0;
+ return GenLiteral0 ();
}
/* Get a node with this token */
NextTok ();
}
- /* Skip the comma */
+ /* Skip the terminator token*/
NextTok ();
- /* Read the second list which is terminated by the right parenthesis and
- * compare each token against the one in the first list.
+ /* If the token list was enclosed in curly braces, we expect a comma */
+ if (Term == TOK_RCURLY) {
+ ConsumeComma ();
+ }
+
+ /* Read the second list which is optionally enclosed in curly braces and
+ * terminated by the right parenthesis. Compare each token against the
+ * one in the first list.
*/
+ Term = GetTokListTerm (TOK_RPAREN);
Result = 1;
Node = Root;
- while (Tok != TOK_RPAREN) {
+ while (Tok != Term) {
/* We may not end-of-line of end-of-file here */
if (TokIsSep (Tok)) {
Error ("Unexpected end of line");
- return 0;
+ return GenLiteral0 ();
}
/* Compare the tokens if the result is not already known */
NextTok ();
}
+ /* If the token list was enclosed in curly braces, eat the closing brace */
+ if (Term == TOK_RCURLY) {
+ NextTok ();
+ }
+
/* Check if there are remaining tokens in the first list */
if (Node != 0) {
Result = 0;
if (ParentScope == 0) {
/* No such scope */
DoneStrBuf (&ScopeName);
- return GenLiteralExpr (0);
+ return GenLiteral0 ();
}
/* If ScopeName is empty, no explicit scope was specified. We have to
if (Tok != TOK_STRCON) {
Error ("String constant expected");
NextTok ();
- return 0;
-
+ return GenLiteral0 ();
}
/* Remember the string and skip it */
/* Must be a valid index */
if (Index >= (long) strlen (Str)) {
Error ("Range error");
- return 0;
+ return GenLiteral0 ();
}
/* Get the char, handle as unsigned. Be sure to translate it into
/* 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.
+ * the tokens, and count them. Allow optionally curly braces.
*/
- int Count = 0;
- unsigned Parens = 0;
- while (Parens != 0 || Tok != TOK_RPAREN) {
+ enum Token Term = GetTokListTerm (TOK_RPAREN);
+ int Count = 0;
+ while (Tok != Term) {
/* 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
/* 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 ();
}
+ /* If the list was enclosed in curly braces, skip the closing brace */
+ if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+ NextTok ();
+ }
+
/* Return the number of tokens */
return GenLiteralExpr (Count);
}
if (Tok != TOK_LPAREN) {
Error ("'(' expected");
SkipUntilSep ();
- return GenLiteralExpr (0);
+ return GenLiteral0 ();
}
NextTok ();
NextTok ();
break;
+ case TOK_PLUS:
+ NextTok ();
+ N = Factor ();
+ break;
+
case TOK_MINUS:
NextTok ();
L = Factor ();
/* A character constant */
N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
} else {
- N = GenLiteralExpr (0); /* Dummy */
+ N = GenLiteral0 (); /* Dummy */
Error ("Syntax error");
}
NextTok ();
+ExprNode* GenLiteral0 (void)
+/* Return an expression tree that encodes the the number zero */
+{
+ return GenLiteralExpr (0);
+}
+
+
+
ExprNode* GenSymExpr (SymEntry* Sym)
/* Return an expression node that encodes the given symbol */
{
{
ExprNode* Root;
- if (RelocMode) {
+ if (GetRelocMode ()) {
/* Create SegmentBase + Offset */
Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
GenLiteralExpr (GetPC ()));
* (Val - PC - Offs) - Seg
*/
Root = GenLiteralExpr (Val - GetPC () - Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root->Right = GenLiteralExpr (GetPC () + Offs);
- if (RelocMode) {
+ if (GetRelocMode ()) {
N = Root;
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
case EXPR_LITERAL:
ObjWrite8 (EXPR_LITERAL);
- ObjWrite32 (Expr->V.Val);
- break;
+ ObjWrite32 (Expr->V.Val);
+ break;
case EXPR_SYMBOL:
- if (SymIsImport (Expr->V.Sym)) {
+ if (SymIsImport (Expr->V.Sym)) {
ObjWrite8 (EXPR_SYMBOL);
ObjWriteVar (GetSymIndex (Expr->V.Sym));
} else {
+void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
+/* Mark the address size of the given expression tree as guessed. The address
+ * size passed as argument is the one NOT used, because the actual address
+ * size wasn't known. Example: Zero page addressing was not used because symbol
+ * is undefined, and absolute addressing was available.
+ * This function will actually parse the expression tree for undefined symbols,
+ * and mark these symbols accordingly.
+ */
+{
+ /* Accept NULL expressions */
+ if (Expr == 0) {
+ return;
+ }
+
+ /* Check the type code */
+ switch (Expr->Op & EXPR_TYPEMASK) {
+
+ case EXPR_LEAFNODE:
+ if (Expr->Op == EXPR_SYMBOL) {
+ if (!SymIsDef (Expr->V.Sym)) {
+ /* Symbol is undefined, mark it */
+ SymGuessedAddrSize (Expr->V.Sym, AddrSize);
+ }
+ }
+ return;
+
+ case EXPR_BINARYNODE:
+ ExprGuessedAddrSize (Expr->Right, AddrSize);
+ /* FALLTHROUGH */
+
+ case EXPR_UNARYNODE:
+ ExprGuessedAddrSize (Expr->Left, AddrSize);
+ break;
+ }
+}
+
+