/* */
/* */
/* */
-/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2003-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "addrsize.h"
/* ca65 */
+#include "condasm.h"
#include "error.h"
#include "expr.h"
#include "nexttok.h"
#include "scanner.h"
+#include "sizeof.h"
#include "symbol.h"
#include "symtab.h"
#include "struct.h"
{
long Multiplicator;
- /* A comma and a multiplicator may follow */
- if (Tok == TOK_COMMA) {
- NextTok ();
+ /* A multiplicator may follow */
+ if (CurTok.Tok != TOK_SEP) {
Multiplicator = ConstExpression ();
if (Multiplicator <= 0) {
- Error ("Range error");
+ ErrorSkip ("Range error");
Multiplicator = 1;
}
AllocSize *= Multiplicator;
}
+ /* Check the size for a reasonable value */
+ if (AllocSize >= 0x10000) {
+ ErrorSkip ("Range error");
+ }
+
/* Return the size */
return AllocSize;
}
* union, the struct may be anonymous, in which case no new lexical level
* is started.
*/
- int Anon = (Tok != TOK_IDENT);
- if (Anon) {
- unsigned char T = GetCurrentSymTabType ();
- if (T != ST_STRUCT) {
- ErrorSkip ("Struct/union needs a name");
- return 0;
- }
- } else {
+ int Anon = (CurTok.Tok != TOK_IDENT);
+ if (!Anon) {
/* Enter a new scope, then skip the name */
- SymEnterLevel (SVal, ST_STRUCT, ADDR_SIZE_ABS);
+ SymEnterLevel (&CurTok.SVal, ST_STRUCT, ADDR_SIZE_ABS);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
ConsumeSep ();
/* Read until end of struct */
- while (Tok != TOK_ENDSTRUCT && Tok != TOK_ENDUNION && Tok != TOK_EOF) {
+ while (CurTok.Tok != TOK_ENDSTRUCT &&
+ CurTok.Tok != TOK_ENDUNION &&
+ CurTok.Tok != TOK_EOF) {
long MemberSize;
- SymEntry* Sym;
SymTable* Struct;
+ SymEntry* Sym;
+
+ /* Allow empty and comment lines */
+ if (CurTok.Tok == TOK_SEP) {
+ NextTok ();
+ continue;
+ }
/* The format is "[identifier] storage-allocator [, multiplicator]" */
- if (Tok == TOK_IDENT) {
+ Sym = 0;
+ if (CurTok.Tok == TOK_IDENT) {
/* We have an identifier, generate a symbol */
- Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
+ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW);
/* Assign the symbol the offset of the current member */
SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE);
/* Read storage allocators */
MemberSize = 0; /* In case of errors, use zero */
- switch (Tok) {
+ switch (CurTok.Tok) {
case TOK_BYTE:
NextTok ();
break;
case TOK_RES:
- Error ("Not implemented");
+ NextTok ();
+ if (CurTok.Tok == TOK_SEP) {
+ ErrorSkip ("Size is missing");
+ } else {
+ MemberSize = Member (1);
+ }
break;
case TOK_TAG:
NextTok ();
- Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
+ Struct = ParseScopedSymTable ();
if (Struct == 0) {
- Error ("Unknown struct/union");
+ ErrorSkip ("Unknown struct/union");
} else if (GetSymTabType (Struct) != ST_STRUCT) {
- Error ("Not a struct/union");
+ ErrorSkip ("Not a struct/union");
} else {
- MemberSize = Member (GetStructSize (Struct));
+ SymEntry* SizeSym = GetSizeOfScope (Struct);
+ if (!SymIsDef (SizeSym) || !SymIsConst (SizeSym, &MemberSize)) {
+ ErrorSkip ("Size of struct/union is unknown");
+ }
}
+ MemberSize = Member (MemberSize);
break;
case TOK_STRUCT:
break;
default:
- Error ("Invalid storage allocator in struct/union");
- SkipUntilSep ();
+ if (!CheckConditionals ()) {
+ /* Not a conditional directive */
+ ErrorSkip ("Invalid storage allocator in struct/union");
+ }
+ }
+
+ /* Assign the size to the member if it has a name */
+ if (Sym) {
+ DefSizeOfSymbol (Sym, MemberSize);
}
/* Next member */
*/
if (!Anon) {
/* Add a symbol */
- SymEntry* SizeSym = SymFind (CurrentScope, ".size", SYM_ALLOC_NEW);
+ SymEntry* SizeSym = GetSizeOfScope (CurrentScope);
SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE);
/* Close the struct scope */
long GetStructSize (SymTable* Struct)
/* Get the size of a struct or union */
{
- SymEntry* Sym = SymFind (Struct, ".size", SYM_FIND_EXISTING);
+ SymEntry* Sym = SymFind (Struct, &SizeEntryName, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Size of struct/union is unknown");
return 0;