/*****************************************************************************/ /* */ /* enum.c */ /* */ /* .ENUM command */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "scopedefs.h" /* ca65 */ #include "condasm.h" #include "enum.h" #include "error.h" #include "expr.h" #include "macro.h" #include "nexttok.h" #include "scanner.h" #include "symbol.h" #include "symtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoEnum (void) /* Handle the .ENUM command */ { /* Start at zero */ long Offs = 0; ExprNode* BaseExpr = GenLiteral0 (); /* Check for a name */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ SymEnterLevel (&CurTok.SVal, SCOPE_ENUM, ADDR_SIZE_ABS, 0); NextTok (); } /* Test for end of line */ ConsumeSep (); /* Read until end of struct */ while (CurTok.Tok != TOK_ENDENUM && CurTok.Tok != TOK_EOF) { Macro* M; SymEntry* Sym; ExprNode* EnumExpr; /* Skip empty lines */ if (CurTok.Tok == TOK_SEP) { NextTok (); continue; } /* The format is "identifier [ = value ]" */ if (CurTok.Tok != TOK_IDENT) { /* Maybe it's a conditional? */ if (!CheckConditionals ()) { ErrorSkip ("Identifier expected"); } continue; } /* We have an identifier. Is it a macro? */ if ((M = FindMacro (&CurTok.SVal)) != 0) { MacExpandStart (M); continue; } /* We have an identifier, generate a symbol */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Skip the member name */ NextTok (); /* Check for an assignment */ if (CurTok.Tok == TOK_EQ) { /* Skip the equal sign */ NextTok (); /* Read the new expression */ EnumExpr = Expression (); /* Reset the base expression and the offset */ FreeExpr (BaseExpr); BaseExpr = CloneExpr (EnumExpr); Offs = 0; } else { /* No assignment, use last value + 1 */ EnumExpr = GenAddExpr (CloneExpr (BaseExpr), GenLiteralExpr (Offs)); } /* Assign the value to the enum member */ SymDef (Sym, EnumExpr, ADDR_SIZE_DEFAULT, SF_NONE); /* Increment the offset for the next member */ ++Offs; /* Expect end of line */ ConsumeSep (); } /* If this is not an anon enum, leave its scope */ if (!Anon) { /* Close the enum scope */ SymLeaveLevel (); } /* End of enum definition */ Consume (TOK_ENDENUM, "'.ENDENUM' expected"); /* Free the base expression */ FreeExpr (BaseExpr); }