1/*****************************************************************************/
2/* */
3/* enum.c */
4/* */
5/* .ENUM command */
6/* */
7/* */
8/* */
9/* (C) 2003-2011, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36/* common */
37#include "addrsize.h"
38#include "scopedefs.h"
39
40/* ca65 */
41#include "condasm.h"
42#include "enum.h"
43#include "error.h"
44#include "expr.h"
45#include "macro.h"
46#include "nexttok.h"
47#include "scanner.h"
48#include "symbol.h"
49#include "symtab.h"
50
51
52
53/*****************************************************************************/
54/* Code */
55/*****************************************************************************/
56
57
58
59void DoEnum (void)
60/* Handle the .ENUM command */
61{
62 /* Start at zero */
63 long Offs = 0;
64 ExprNode* BaseExpr = GenLiteral0 ();
65
66 /* Check for a name */
67 int Anon = (CurTok.Tok != TOK_IDENT);
68 if (!Anon) {
69 /* Enter a new scope, then skip the name */
70 SymEnterLevel (&CurTok.SVal, SCOPE_ENUM, ADDR_SIZE_ABS, 0);
71 NextTok ();
72 }
73
74 /* Test for end of line */
75 ConsumeSep ();
76
77 /* Read until end of struct */
78 while (CurTok.Tok != TOK_ENDENUM && CurTok.Tok != TOK_EOF) {
79
80 Macro* M;
81 SymEntry* Sym;
82 ExprNode* EnumExpr;
83
84 /* Skip empty lines */
85 if (CurTok.Tok == TOK_SEP) {
86 NextTok ();
87 continue;
88 }
89
90 /* The format is "identifier [ = value ]" */
91 if (CurTok.Tok != TOK_IDENT) {
92 /* Maybe it's a conditional? */
93 if (!CheckConditionals ()) {
94 ErrorSkip ("Identifier expected");
95 }
96 continue;
97 }
98
99 /* We have an identifier. Is it a macro? */
100 if ((M = FindMacro (&CurTok.SVal)) != 0) {
101 MacExpandStart (M);
102 continue;
103 }
104
105 /* We have an identifier, generate a symbol */
106 Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW);
107
108 /* Skip the member name */
109 NextTok ();
110
111 /* Check for an assignment */
112 if (CurTok.Tok == TOK_EQ) {
113
114 /* Skip the equal sign */
115 NextTok ();
116
117 /* Read the new expression */
118 EnumExpr = Expression ();
119
120 /* Reset the base expression and the offset */
121 FreeExpr (BaseExpr);
122 BaseExpr = CloneExpr (EnumExpr);
123 Offs = 0;
124
125 } else {
126
127 /* No assignment, use last value + 1 */
128 EnumExpr = GenAddExpr (CloneExpr (BaseExpr), GenLiteralExpr (Offs));
129
130 }
131
132 /* Assign the value to the enum member */
133 SymDef (Sym, EnumExpr, ADDR_SIZE_DEFAULT, SF_NONE);
134
135 /* Increment the offset for the next member */
136 ++Offs;
137
138 /* Expect end of line */
139 ConsumeSep ();
140 }
141
142 /* If this is not an anon enum, leave its scope */
143 if (!Anon) {
144 /* Close the enum scope */
145 SymLeaveLevel ();
146 }
147
148 /* End of enum definition */
149 Consume (TOK_ENDENUM, "'.ENDENUM' expected");
150
151 /* Free the base expression */
152 FreeExpr (BaseExpr);
153}
154