Mercurial > hg > index.cgi
comparison lwasm/lwasm.c @ 370:8764142b3192
Convert internal error/warning handling framework to a new unified system
Replace the ad hoc error and warning handling with a new system that
codifies the errors with specific codes. This makes it possible in the
future for error numbers to be used for testing and other purposes. It also
makes sure the error strings themselves are consistent.
Thanks to Erik G <erik@6809.org> for the patch.
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 22 Jun 2015 18:49:38 -0600 |
parents | 433dbc18fb41 |
children | 8e25147c2aa8 |
comparison
equal
deleted
inserted
replaced
369:682524a1f32f | 370:8764142b3192 |
---|---|
31 #include <lw_string.h> | 31 #include <lw_string.h> |
32 | 32 |
33 #include "lwasm.h" | 33 #include "lwasm.h" |
34 #include "instab.h" | 34 #include "instab.h" |
35 | 35 |
36 void lwasm_register_error(asmstate_t *as, line_t *l, const char *msg, ...); | |
37 | |
38 int lwasm_expr_exportable(asmstate_t *as, lw_expr_t expr) | 36 int lwasm_expr_exportable(asmstate_t *as, lw_expr_t expr) |
39 { | 37 { |
40 return 0; | 38 return 0; |
41 } | 39 } |
42 | 40 |
46 } | 44 } |
47 | 45 |
48 void lwasm_dividezero(void *priv) | 46 void lwasm_dividezero(void *priv) |
49 { | 47 { |
50 asmstate_t *as = (asmstate_t *)priv; | 48 asmstate_t *as = (asmstate_t *)priv; |
51 lwasm_register_error(as, as -> cl, "Division by zero"); | 49 lwasm_register_error(as, as -> cl, E_DIV0); |
52 } | 50 } |
53 | 51 |
54 lw_expr_t lwasm_evaluate_var(char *var, void *priv) | 52 lw_expr_t lwasm_evaluate_var(char *var, void *priv) |
55 { | 53 { |
56 asmstate_t *as = (asmstate_t *)priv; | 54 asmstate_t *as = (asmstate_t *)priv; |
98 return e; | 96 return e; |
99 | 97 |
100 nomatch: | 98 nomatch: |
101 if (as -> badsymerr) | 99 if (as -> badsymerr) |
102 { | 100 { |
103 lwasm_register_error(as, as -> cl, "Undefined symbol %s", var); | 101 lwasm_register_error2(as, as -> cl, E_SYMBOL_UNDEFINED, "%s", var); |
104 } | 102 } |
105 return NULL; | 103 return NULL; |
106 } | 104 } |
107 | 105 |
108 lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv) | 106 lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv) |
204 } | 202 } |
205 } | 203 } |
206 return NULL; | 204 return NULL; |
207 } | 205 } |
208 | 206 |
209 void lwasm_register_error_real(asmstate_t *as, line_t *l, char *iptr, const char *msg, va_list args) | 207 const char* lwasm_lookup_error(lwasm_errorcode_t error_code) |
208 { | |
209 switch (error_code) | |
210 { | |
211 case E_6309_INVALID: return "Illegal use of 6309 instruction in 6809 mode"; | |
212 case E_6809_INVALID: return "Illegal use of 6809 instruction in 6309 mode"; | |
213 case E_ALIGNMENT_INVALID: return "Invalid alignment"; | |
214 case E_BITNUMBER_INVALID: return "Invalid bit number"; | |
215 case E_BITNUMBER_UNRESOLVED: return "Bit number must be fully resolved"; | |
216 case E_BYTE_OVERFLOW: return "Byte overflow"; | |
217 case E_CONDITION_P1: return "Conditions must be constant on pass 1"; | |
218 case E_DIRECTIVE_OS9_ONLY: return "Directive only valid for OS9 target"; | |
219 case E_DIV0: return "Division by zero"; | |
220 case E_EXEC_ADDRESS: return "Exec address not constant!"; | |
221 case E_EXPRESSION_BAD: return "Bad expression"; | |
222 case E_EXPRESSION_NOT_CONST: return "Expression must be constant"; | |
223 case E_EXPRESSION_NOT_RESOLVED: return "Expression not fully resolved"; | |
224 case E_FILE_OPEN: return "Cannot open file"; | |
225 case E_FILENAME_MISSING: return "Missing filename"; | |
226 case E_FILL_INVALID: return "Invalid fill length"; | |
227 case E_IMMEDIATE_INVALID: return "Immediate mode not allowed"; | |
228 case E_IMMEDIATE_UNRESOLVED: return "Immediate byte must be fully resolved"; | |
229 case E_INSTRUCTION_FAILED: return "Instruction failed to resolve."; | |
230 case E_INSTRUCTION_SECTION: return "Instruction generating output outside of a section"; | |
231 case E_LINE_ADDRESS: return "Cannot resolve line address"; | |
232 case E_LINED_ADDRESS: return "Cannot resolve line data address"; | |
233 case E_OBJTARGET_ONLY: return "Only supported for object target"; | |
234 case E_OPCODE_BAD: return "Bad opcode"; | |
235 case E_OPERAND_BAD: return "Bad operand"; | |
236 case E_PADDING_BAD: return "Bad padding"; | |
237 case E_PRAGMA_UNRECOGNIZED: return "Unrecognized pragma string"; | |
238 case E_REGISTER_BAD: return "Bad register"; | |
239 case E_SETDP_INVALID: return "SETDP not permitted for object target"; | |
240 case E_SETDP_NOT_CONST: return "SETDP must be constant on pass 1"; | |
241 case E_STRING_BAD: return "Bad string condition"; | |
242 case E_SYMBOL_BAD: return "Bad symbol"; | |
243 case E_SYMBOL_MISSING: return "Missing symbol"; | |
244 case E_SYMBOL_UNDEFINED_EXPORT: return "Undefined exported symbol"; | |
245 case E_MACRO_DUPE: return "Duplicate macro definition"; | |
246 case E_MACRO_ENDM: return "ENDM without MACRO"; | |
247 case E_MACRO_NONAME: return "Missing macro name"; | |
248 case E_MACRO_RECURSE: return "Attempt to define a macro inside a macro"; | |
249 case E_MODULE_IN: return "Already in a module!"; | |
250 case E_MODULE_NOTIN: return "Not in a module!"; | |
251 case E_NEGATIVE_BLOCKSIZE: return "Negative block sizes make no sense!"; | |
252 case E_NEGATIVE_RESERVATION: return "Negative reservation sizes make no sense!"; | |
253 case E_NW_8: return "n,W cannot be 8 bit"; | |
254 case E_SECTION_END: return "ENDSECTION without SECTION"; | |
255 case E_SECTION_EXTDEP: return "EXTDEP must be within a section"; | |
256 case E_SECTION_FLAG: return "Unrecognized section flag"; | |
257 case E_SECTION_NAME: return "Need section name"; | |
258 case E_SECTION_TARGET: return "Cannot use sections unless using the object target"; | |
259 case E_STRUCT_DUPE: return "Duplicate structure definition"; | |
260 case E_STRUCT_NONAME: return "Cannot declare a structure without a symbol name."; | |
261 case E_STRUCT_NOSYMBOL: return "Structure definition with no effect - no symbol"; | |
262 case E_STRUCT_RECURSE: return "Attempt to define a structure inside a structure"; | |
263 case E_SYMBOL_DUPE: return "Multiply defined symbol"; | |
264 case E_UNKNOWN_OPERATION: return "Unknown operation"; | |
265 | |
266 case W_ENDSTRUCT_WITHOUT: return "ENDSTRUCT without STRUCT"; | |
267 case W_DUPLICATE_SECTION: return "Section flags can only be specified the first time; ignoring duplicate definition"; | |
268 case W_NOT_SUPPORTED: return "Not supported"; | |
269 | |
270 default: return "Error"; | |
271 } | |
272 } | |
273 | |
274 void lwasm_register_error_real(asmstate_t *as, line_t *l, lwasm_errorcode_t err, const char *msg) | |
210 { | 275 { |
211 lwasm_error_t *e; | 276 lwasm_error_t *e; |
212 char errbuff[1024]; | |
213 | 277 |
214 if (!l) | 278 if (!l) |
215 return; | 279 return; |
216 | 280 |
217 e = lw_alloc(sizeof(lwasm_error_t)); | 281 e = lw_alloc(sizeof(lwasm_error_t)); |
218 | 282 |
219 e -> next = l -> err; | 283 if (err >= 1000) |
220 l -> err = e; | 284 { |
285 e->next = l->warn; | |
286 l->warn = e; | |
287 as->warningcount++; | |
288 } | |
289 else | |
290 { | |
291 e->next = l->err; | |
292 l->err = e; | |
293 as->errorcount++; | |
294 } | |
295 | |
221 e -> charpos = -1; | 296 e -> charpos = -1; |
222 | 297 |
223 if (iptr) | 298 e -> mess = lw_strdup(msg); |
224 e -> charpos = iptr - l -> ltext + 1; | 299 } |
225 | 300 |
226 as -> errorcount++; | 301 void lwasm_register_error(asmstate_t *as, line_t *l, lwasm_errorcode_t err) |
227 | 302 { |
228 (void)vsnprintf(errbuff, 1024, msg, args); | 303 lwasm_register_error_real(as, l, err, lwasm_lookup_error(err)); |
229 e -> mess = lw_strdup(errbuff); | 304 } |
230 } | 305 |
231 | 306 void lwasm_register_error2(asmstate_t *as, line_t *l, lwasm_errorcode_t err, const char* fmt, ...) |
232 void lwasm_register_error(asmstate_t *as, line_t *l, const char *msg, ...) | 307 { |
233 { | 308 char errbuff[1024]; |
309 char f[128]; | |
310 | |
311 sprintf(f, "%s %s", lwasm_lookup_error(err), fmt); | |
312 | |
234 va_list args; | 313 va_list args; |
235 | 314 |
236 va_start(args, msg); | 315 va_start(args, fmt); |
237 | 316 |
238 lwasm_register_error_real(as, l, NULL, msg, args); | 317 (void) vsnprintf(errbuff, 1024, f, args); |
239 | 318 |
240 va_end(args); | 319 lwasm_register_error_real(as, l, err, errbuff); |
241 } | 320 |
242 | |
243 void lwasm_register_error_n(asmstate_t *as, line_t *l, char *iptr, const char *msg, ...) | |
244 { | |
245 va_list args; | |
246 | |
247 va_start(args, msg); | |
248 | |
249 lwasm_register_error_real(as, l, iptr, msg, args); | |
250 | |
251 va_end(args); | |
252 } | |
253 | |
254 void lwasm_register_warning_real(asmstate_t *as, line_t *l, char *iptr, const char *msg, va_list args) | |
255 { | |
256 lwasm_error_t *e; | |
257 char errbuff[1024]; | |
258 | |
259 if (!l) | |
260 return; | |
261 | |
262 e = lw_alloc(sizeof(lwasm_error_t)); | |
263 | |
264 e -> next = l -> warn; | |
265 l -> warn = e; | |
266 | |
267 e -> charpos = -1; | |
268 if (iptr) | |
269 e -> charpos = iptr - l -> ltext + 1; | |
270 | |
271 as -> warningcount++; | |
272 | |
273 (void)vsnprintf(errbuff, 1024, msg, args); | |
274 e -> mess = lw_strdup(errbuff); | |
275 } | |
276 | |
277 void lwasm_register_warning(asmstate_t *as, line_t *l, const char *msg, ...) | |
278 { | |
279 va_list args; | |
280 | |
281 va_start(args, msg); | |
282 | |
283 lwasm_register_warning_real(as, l, NULL, msg, args); | |
284 | |
285 va_end(args); | |
286 } | |
287 | |
288 void lwasm_register_warning_n(asmstate_t *as, line_t *l, char *iptr, const char *msg, ...) | |
289 { | |
290 va_list args; | |
291 | |
292 va_start(args, msg); | |
293 | |
294 lwasm_register_warning_real(as, l, iptr, msg, args); | |
295 | |
296 va_end(args); | 321 va_end(args); |
297 } | 322 } |
298 | 323 |
299 int lwasm_next_context(asmstate_t *as) | 324 int lwasm_next_context(asmstate_t *as) |
300 { | 325 { |
306 | 331 |
307 void lwasm_emit(line_t *cl, int byte) | 332 void lwasm_emit(line_t *cl, int byte) |
308 { | 333 { |
309 if (cl -> as -> output_format == OUTPUT_OBJ && cl -> csect == NULL) | 334 if (cl -> as -> output_format == OUTPUT_OBJ && cl -> csect == NULL) |
310 { | 335 { |
311 lwasm_register_error(cl -> as, cl, "Instruction generating output outside of a section"); | 336 lwasm_register_error(cl -> as, cl, E_INSTRUCTION_SECTION); |
312 return; | 337 return; |
313 } | 338 } |
314 if (cl -> outputl < 0) | 339 if (cl -> outputl < 0) |
315 cl -> outputl = 0; | 340 cl -> outputl = 0; |
316 | 341 |
815 reloctab_t *re; | 840 reloctab_t *re; |
816 lw_expr_t te; | 841 lw_expr_t te; |
817 | 842 |
818 if (l -> csect == NULL) | 843 if (l -> csect == NULL) |
819 { | 844 { |
820 lwasm_register_error(l -> as, l, "Instruction generating output outside of a section"); | 845 lwasm_register_error(l -> as, l, E_INSTRUCTION_SECTION); |
821 return -1; | 846 return -1; |
822 } | 847 } |
823 | 848 |
824 if (size == 4) | 849 if (size == 4) |
825 { | 850 { |
869 } | 894 } |
870 for (v = 0; v < size; v++) | 895 for (v = 0; v < size; v++) |
871 lwasm_emit(l, 0); | 896 lwasm_emit(l, 0); |
872 return 0; | 897 return 0; |
873 } | 898 } |
874 lwasm_register_error(l -> as, l, "Expression not fully resolved"); | 899 lwasm_register_error(l->as, l, E_EXPRESSION_NOT_RESOLVED); |
875 return -1; | 900 return -1; |
876 } | 901 } |
877 | 902 |
878 switch (size) | 903 switch (size) |
879 { | 904 { |
992 e = lwasm_parse_expr(as, p); | 1017 e = lwasm_parse_expr(as, p); |
993 debug_message(as, 250, "COND EXPR: %s", lw_expr_print(e)); | 1018 debug_message(as, 250, "COND EXPR: %s", lw_expr_print(e)); |
994 | 1019 |
995 if (!e) | 1020 if (!e) |
996 { | 1021 { |
997 lwasm_register_error(as, as -> cl, "Bad expression"); | 1022 lwasm_register_error(as, as -> cl, E_EXPRESSION_BAD); |
998 return NULL; | 1023 return NULL; |
999 } | 1024 } |
1000 | 1025 |
1001 /* handle condundefzero */ | 1026 /* handle condundefzero */ |
1002 if (CURPRAGMA(as -> cl, PRAGMA_CONDUNDEFZERO)) | 1027 if (CURPRAGMA(as -> cl, PRAGMA_CONDUNDEFZERO)) |
1024 lwasm_save_expr(as -> cl, 4242, e); | 1049 lwasm_save_expr(as -> cl, 4242, e); |
1025 | 1050 |
1026 if (!lw_expr_istype(e, lw_expr_type_int)) | 1051 if (!lw_expr_istype(e, lw_expr_type_int)) |
1027 { | 1052 { |
1028 debug_message(as, 250, "Non-constant expression"); | 1053 debug_message(as, 250, "Non-constant expression"); |
1029 lwasm_register_error(as, as -> cl, "Conditions must be constant on pass 1"); | 1054 lwasm_register_error(as, as -> cl, E_CONDITION_P1); |
1030 return NULL; | 1055 return NULL; |
1031 } | 1056 } |
1032 debug_message(as, 250, "Returning expression"); | 1057 debug_message(as, 250, "Returning expression"); |
1033 return e; | 1058 return e; |
1034 } | 1059 } |