comparison lwasm/pass1.c @ 345:7416c3f9c321

Basic macro processor ported forward; added context break handling for local symbols
author lost@starbug
date Thu, 25 Mar 2010 23:17:54 -0600
parents 0215a0fbf61b
children a82c55070624
comparison
equal deleted inserted replaced
344:0215a0fbf61b 345:7416c3f9c321
57 { 57 {
58 sym = NULL; 58 sym = NULL;
59 line = input_readline(as); 59 line = input_readline(as);
60 if (!line) 60 if (!line)
61 break; 61 break;
62 if (line[0] == 1 && line[1] == 1)
63 {
64 // special internal directive
65 // these DO NOT appear in the output anywhere
66 // they are generated by the parser to pass information
67 // forward
68 for (p1 = line + 2; *p1 && !isspace(*p1); p1++)
69 /* do nothing */ ;
70 *p1++ = '\0';
71 if (!strcmp(line + 2, "SETCONTEXT"))
72 {
73 as -> context = strtol(p1, NULL, 10);
74 }
75 lw_free(line);
76 continue;
77 }
62 printf("%s\n", line); 78 printf("%s\n", line);
63 79
64 cl = lw_alloc(sizeof(line_t)); 80 cl = lw_alloc(sizeof(line_t));
65 cl -> next = NULL; 81 cl -> next = NULL;
66 cl -> prev = as -> line_tail; 82 cl -> prev = as -> line_tail;
82 lw_expr_simplify(cl -> addr); 98 lw_expr_simplify(cl -> addr);
83 } 99 }
84 as -> line_tail = cl; 100 as -> line_tail = cl;
85 101
86 // blank lines don't count for anything 102 // blank lines don't count for anything
103 // except a local symbol context break
87 if (!*line) 104 if (!*line)
88 { 105 {
106 as -> context = lwasm_next_context(as);
89 goto nextline; 107 goto nextline;
90 } 108 }
91 109
92 // skip comments 110 // skip comments
111 // commends do not create a context break
93 if (*line == '*' || *line == ';' || *line == '#') 112 if (*line == '*' || *line == ';' || *line == '#')
94 goto nextline; 113 goto nextline;
95 114
96 p1 = line; 115 p1 = line;
97 if (isdigit(*p1)) 116 if (isdigit(*p1))
103 p1 = line; 122 p1 = line;
104 else if (*p1 && isspace(*p1)) 123 else if (*p1 && isspace(*p1))
105 p1++; 124 p1++;
106 } 125 }
107 126
127 // blank line - context break
108 if (!*p1) 128 if (!*p1)
109 goto nextline; 129 {
110 130 as -> context = lwasm_next_context(as);
131 goto nextline;
132 }
133
134 // comment - no context break
111 if (*p1 == '*' || *p1 == ';' || *p1 == '#') 135 if (*p1 == '*' || *p1 == ';' || *p1 == '#')
112 goto nextline; 136 goto nextline;
113 137
114 if (isspace(*p1)) 138 if (isspace(*p1))
115 { 139 {
118 stspace = 1; 142 stspace = 1;
119 } 143 }
120 else 144 else
121 stspace = 0; 145 stspace = 0;
122 146
123 if (*p1 == '*' || *p1 == ';' || *p1 == '#' || !*p1) 147 if (*p1 == '*' || *p1 == ';' || *p1 == '#')
124 goto nextline; 148 goto nextline;
149 if (!*p1)
150 {
151 // nothing but whitespace - context break
152 as -> context = lwasm_next_context(as);
153 goto nextline;
154 }
125 155
126 // find the end of the first token 156 // find the end of the first token
127 for (tok = p1; *p1 && !isspace(*p1) && *p1 != ':'; p1++) 157 for (tok = p1; *p1 && !isspace(*p1) && *p1 != ':'; p1++)
128 /* do nothing */ ; 158 /* do nothing */ ;
129 159
154 for (opnum = 0; instab[opnum].opcode; opnum++) 184 for (opnum = 0; instab[opnum].opcode; opnum++)
155 { 185 {
156 if (!strcasecmp(instab[opnum].opcode, sym)) 186 if (!strcasecmp(instab[opnum].opcode, sym))
157 break; 187 break;
158 } 188 }
159 lw_free(sym);
160 189
161 // p1 points to the start of the operand 190 // p1 points to the start of the operand
162 191
192 // if we're inside a macro definition and not at ENDM,
193 // add the line to the macro definition and continue
194 if (as -> inmacro && !(instab[opnum].flags & lwasm_insn_endm))
195 {
196 add_macro_line(as, line);
197 goto linedone;
198 }
199
200 // if skipping a condition and the operation code doesn't
201 // operate within a condition (not a conditional)
202 // do nothing
203 if (as -> skipcond && !(instab[opnum].flags & lwasm_insn_cond))
204 goto linedone;
205
163 if (instab[opnum].opcode == NULL) 206 if (instab[opnum].opcode == NULL)
164 { 207 {
165 cl -> insn = -1; 208 cl -> insn = -1;
166 if (*tok != ';' && *tok != '*') 209 if (*tok != ';' && *tok != '*')
167 { 210 {
168 // bad opcode; check for macro here 211 // bad opcode; check for macro here
169 lwasm_register_error(as, cl, "Bad opcode"); 212 if (expand_macro(as, cl, &p1, sym) != 0)
213 {
214 // macro expansion failed
215 lwasm_register_error(as, cl, "Bad opcode");
216 }
170 } 217 }
171 } 218 }
172 else 219 else
173 { 220 {
174 cl -> insn = opnum; 221 cl -> insn = opnum;
175 // call parse function 222 // no parse func means operand doesn't matter
176 223 if (instab[opnum].parse)
177 if (*p1 && !isspace(*p1))
178 { 224 {
179 // flag bad operand error 225 // call parse function
180 lwasm_register_error(as, cl, "Bad operand (%s)", p1); 226 (instab[opnum].parse)(as, cl, &p1);
227
228 if (*p1 && !isspace(*p1))
229 {
230 // flag bad operand error
231 lwasm_register_error(as, cl, "Bad operand (%s)", p1);
232 }
181 } 233 }
182 } 234 }
183 } 235 }
184 236
185 if (cl -> sym && cl -> symset == 0) 237 linedone:
186 { 238 lw_free(sym);
187 printf("Register symbol %s:", sym); 239
240 if (!as -> skipcond && !as -> inmacro)
241 {
242 if (cl -> sym && cl -> symset == 0)
243 {
244 printf("Register symbol %s:", sym);
245 lw_expr_print(cl -> addr);
246 printf("\n");
247
248 // register symbol at line address
249 if (!register_symbol(as, cl, cl -> sym, cl -> addr, symbol_flag_none))
250 {
251 // symbol error
252 lwasm_register_error(as, cl, "Bad symbol '%s'", cl -> sym);
253 }
254 }
255
188 lw_expr_print(cl -> addr); 256 lw_expr_print(cl -> addr);
189 printf("\n"); 257 printf("\n");
190 258 }
191 // register symbol at line address
192 if (!register_symbol(as, cl, cl -> sym, cl -> addr, symbol_flag_none))
193 {
194 // symbol error
195 lwasm_register_error(as, cl, "Bad symbol '%s'", cl -> sym);
196 }
197 }
198
199 lw_expr_print(cl -> addr);
200 printf("\n");
201 // now parse the line
202 259
203 nextline: 260 nextline:
204 lw_free(line); 261 lw_free(line);
205 } 262 }
206 } 263 }