diff --git a/src/ca65/expr.c b/src/ca65/expr.c index e4d6f7363..ad1a0b155 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -629,6 +629,92 @@ static ExprNode* FuncReferenced (void) +static ExprNode* FuncAddrSize(void) +/* Handle the .ADDRSIZE function */ +{ + StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; + StrBuf Name = STATIC_STRBUF_INITIALIZER; + SymEntry* Sym; + int AddrSize; + int NoScope; + + + /* Assume we don't know the size */ + AddrSize = 0; + + /* Check for a cheap local which needs special handling */ + if (CurTok.Tok == TOK_LOCAL_IDENT) { + + /* Cheap local symbol */ + Sym = SymFindLocal(SymLast, &CurTok.SVal, SYM_FIND_EXISTING); + if (Sym == 0) { + Error("Unknown symbol or scope: `%m%p'", &CurTok.SVal); + } + else { + AddrSize = Sym->AddrSize; + } + + /* Remember and skip SVal, terminate ScopeName so it is empty */ + SB_Copy(&Name, &CurTok.SVal); + NextTok(); + SB_Terminate(&ScopeName); + + } + else { + + /* Parse the scope and the name */ + SymTable* ParentScope = ParseScopedIdent(&Name, &ScopeName); + + /* Check if the parent scope is valid */ + if (ParentScope == 0) { + /* No such scope */ + SB_Done(&ScopeName); + SB_Done(&Name); + return GenLiteral0(); + } + + /* If ScopeName is empty, no explicit scope was specified. We have to + * search upper scope levels in this case. + */ + NoScope = SB_IsEmpty(&ScopeName); + + /* If we did find a scope with the name, read the symbol defining the + * size, otherwise search for a symbol entry with the name and scope. + */ + if (NoScope) { + Sym = SymFindAny(ParentScope, &Name); + } + else { + Sym = SymFind(ParentScope, &Name, SYM_FIND_EXISTING); + } + /* If we found the symbol retrieve the size, otherwise complain */ + if (Sym) { + AddrSize = Sym->AddrSize; + } + else { + Error("Unknown symbol or scope: `%m%p%m%p'", + &ScopeName, &Name); + } + + } + + /* Check if we have a size */ + /* if we don't know, return it anyway, zero can mean unknown, or uncomment this code for an error + if (AddrSize == 0 ) { + Error ("Address size of `%m%p%m%p' is unknown", &ScopeName, &Name); + } + */ + + /* Free the string buffers */ + SB_Done(&ScopeName); + SB_Done(&Name); + + /* Return the size */ + return GenLiteralExpr(AddrSize); +} + + + static ExprNode* FuncSizeOf (void) /* Handle the .SIZEOF function */ { @@ -965,6 +1051,10 @@ static ExprNode* Factor (void) N = Function (FuncBankByte); break; + case TOK_ADDRSIZE: + N = Function(FuncAddrSize); + break; + case TOK_BLANK: N = Function (FuncBlank); break; diff --git a/src/ca65/feature.c b/src/ca65/feature.c index c398d2b37..3462d5501 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -63,6 +63,7 @@ static const char* FeatureKeys[FEAT_COUNT] = { "c_comments", "force_range", "underline_in_numbers", + "addrsize", }; @@ -119,6 +120,7 @@ feature_t SetFeature (const StrBuf* Key) case FEAT_C_COMMENTS: CComments = 1; break; case FEAT_FORCE_RANGE: ForceRange = 1; break; case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break; + case FEAT_ADDRSIZE: AddrSize = 1; break; default: /* Keep gcc silent */ break; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 9682ad9b9..3a520a54a 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -65,6 +65,7 @@ typedef enum { FEAT_C_COMMENTS, FEAT_FORCE_RANGE, FEAT_UNDERLINE_IN_NUMBERS, + FEAT_ADDRSIZE, /* Special value: Number of features available */ FEAT_COUNT diff --git a/src/ca65/global.c b/src/ca65/global.c index b3d6d6c6e..77ed66e7f 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -82,3 +82,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */ unsigned char CComments = 0; /* Allow C like comments */ unsigned char ForceRange = 0; /* Force values into expected range */ unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */ +unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */ diff --git a/src/ca65/global.h b/src/ca65/global.h index 378a776e6..fb254f835 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -84,6 +84,8 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */ extern unsigned char CComments; /* Allow C like comments */ extern unsigned char ForceRange; /* Force values into expected range */ extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */ +extern unsigned char AddrSize; /* Allow .ADDRSIZE function */ + diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 0b066c7bd..2e8a473a5 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1964,6 +1964,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoA16 }, { ccNone, DoA8 }, { ccNone, DoAddr }, /* .ADDR */ + { ccNone, DoUnexpected }, /* .ADDRSIZE */ { ccNone, DoAlign }, { ccNone, DoASCIIZ }, { ccNone, DoAssert }, diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 890e1c7a3..9543c9872 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -135,6 +135,7 @@ struct DotKeyword { { ".A16", TOK_A16 }, { ".A8", TOK_A8 }, { ".ADDR", TOK_ADDR }, + { ".ADDRSIZE", TOK_ADDRSIZE }, { ".ALIGN", TOK_ALIGN }, { ".AND", TOK_BOOLAND }, { ".ASCIIZ", TOK_ASCIIZ }, @@ -723,8 +724,24 @@ static token_t FindDotKeyword (void) R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]), sizeof (DotKeywords [0]), CmpDotKeyword); if (R != 0) { + + /* By default, disable any somewhat experiemental DotKeyword. */ + + switch (R->Tok) { + + case TOK_ADDRSIZE: + /* Disallow .ADDRSIZE function by default */ + if (AddrSize == 0) { + return TOK_NONE; + } + break; + + default: + break; + } return R->Tok; - } else { + } + else { return TOK_NONE; } } diff --git a/src/ca65/token.h b/src/ca65/token.h index 803b12785..7aaba34c3 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -123,6 +123,7 @@ typedef enum token_t { TOK_A16 = TOK_FIRSTPSEUDO, TOK_A8, TOK_ADDR, + TOK_ADDRSIZE, TOK_ALIGN, TOK_ASCIIZ, TOK_ASSERT,