Mercurial > hg > index.cgi
comparison lwasm/lwasm.c @ 375:71f507f404f1
Add "testmode" pragma
Add a pragma to allow testing more easily.
Thanks to Erik G <erik@6809.org> for the patch.
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 13 Jul 2015 20:35:16 -0600 |
parents | 8e25147c2aa8 |
children | 35d4213e6657 |
comparison
equal
deleted
inserted
replaced
374:8e25147c2aa8 | 375:71f507f404f1 |
---|---|
25 #include <ctype.h> | 25 #include <ctype.h> |
26 | 26 |
27 #include <lw_expr.h> | 27 #include <lw_expr.h> |
28 #include <lw_alloc.h> | 28 #include <lw_alloc.h> |
29 #include <lw_string.h> | 29 #include <lw_string.h> |
30 #include <lw_error.h> | |
30 | 31 |
31 #include "lwasm.h" | 32 #include "lwasm.h" |
32 #include "instab.h" | 33 #include "instab.h" |
33 | 34 |
34 int lwasm_expr_exportable(asmstate_t *as, lw_expr_t expr) | 35 int lwasm_expr_exportable(asmstate_t *as, lw_expr_t expr) |
267 | 268 |
268 default: return "Error"; | 269 default: return "Error"; |
269 } | 270 } |
270 } | 271 } |
271 | 272 |
272 void lwasm_register_error_real(asmstate_t *as, line_t *l, lwasm_errorcode_t err, const char *msg) | 273 /* keeping this as a separate error output for stability in unit test scripts */ |
273 { | 274 void lwasm_error_testmode(line_t *cl, const char* msg, int fatal) |
274 lwasm_error_t *e; | 275 { |
276 cl -> as -> testmode_errorcount++; | |
277 fprintf(stderr, "line %d: %s : %s\n", cl->lineno, msg, cl->ltext); | |
278 if (fatal == 1) lw_error("aborting\n"); | |
279 } | |
280 | |
281 /* parse unit test input data from comment field */ | |
282 void lwasm_parse_testmode_comment(line_t *l, lwasm_testflags_t *flags, lwasm_errorcode_t *err, int *len, char **buf) | |
283 { | |
284 *flags = 0; | |
275 | 285 |
276 if (!l) | 286 if (!l) |
277 return; | 287 return; |
278 | 288 |
289 char* s = strstr(l -> ltext, ";."); | |
290 if (s == NULL) return; | |
291 | |
292 char* t = strstr(s, ":"); | |
293 if (t == NULL) | |
294 { | |
295 /* parse: ;.8E0FCE (emitted code) */ | |
296 | |
297 if (buf == NULL) return; | |
298 | |
299 int i; | |
300 *flags = TF_EMIT; | |
301 | |
302 s = s + 2; /* skip ;. prefix */ | |
303 t = s; | |
304 while (*t > 32) t++; | |
305 | |
306 if ((t - s) & 1) | |
307 { | |
308 lwasm_error_testmode(l, "bad test data (wrong length of hex chars)", 1); | |
309 return; | |
310 } | |
311 | |
312 *len = (t - s) / 2; | |
313 | |
314 t = lw_alloc(*len); | |
315 *buf = t; | |
316 | |
317 for (i = 0; i < *len; i++) | |
318 { | |
319 int val; | |
320 sscanf(s, "%2x", &val); | |
321 *t++ = (char) val; | |
322 s += 2; | |
323 } | |
324 } | |
325 else | |
326 { | |
327 /* parse: ;.E:1000 or ;.E:7 (warnings or errors) */ | |
328 *flags = TF_ERROR; | |
329 | |
330 char ch = toupper(*(t - 1)); | |
331 if (ch != 'E') lwasm_error_testmode(l, "bad test data (expected E: flag)", 1); | |
332 sscanf(t + 1, "%d", (int*) err); | |
333 } | |
334 } | |
335 | |
336 void lwasm_register_error_real(asmstate_t *as, line_t *l, lwasm_errorcode_t error_code, const char *msg) | |
337 { | |
338 lwasm_error_t *e; | |
339 | |
340 if (!l) | |
341 return; | |
342 | |
343 if (CURPRAGMA(l, PRAGMA_TESTMODE)) | |
344 { | |
345 lwasm_testflags_t flags; | |
346 lwasm_errorcode_t testmode_error_code; | |
347 lwasm_parse_testmode_comment(l, &flags, &testmode_error_code, NULL, NULL); | |
348 if (flags == TF_ERROR) | |
349 { | |
350 l -> len = 0; /* null out bogus line */ | |
351 l -> insn = -1; | |
352 l -> err_testmode = error_code; | |
353 if (testmode_error_code == error_code) return; /* expected error: ignore and keep assembling */ | |
354 | |
355 char buf[128]; | |
356 sprintf(buf, "wrong error code (%d)", error_code); | |
357 lwasm_error_testmode(l, buf, 0); | |
358 return; | |
359 } | |
360 } | |
361 | |
279 e = lw_alloc(sizeof(lwasm_error_t)); | 362 e = lw_alloc(sizeof(lwasm_error_t)); |
280 | 363 |
281 if (err >= 1000) | 364 if (error_code >= 1000) |
282 { | 365 { |
283 e->next = l->warn; | 366 e->next = l->warn; |
284 l->warn = e; | 367 l->warn = e; |
285 as->warningcount++; | 368 as->warningcount++; |
286 } | 369 } |
289 e->next = l->err; | 372 e->next = l->err; |
290 l->err = e; | 373 l->err = e; |
291 as->errorcount++; | 374 as->errorcount++; |
292 } | 375 } |
293 | 376 |
377 e -> code = error_code; | |
294 e -> charpos = -1; | 378 e -> charpos = -1; |
295 | 379 |
296 e -> mess = lw_strdup(msg); | 380 e -> mess = lw_strdup(msg); |
297 } | 381 } |
298 | 382 |
982 { | 1066 { |
983 if (!(cl -> err) && !(cl -> warn)) | 1067 if (!(cl -> err) && !(cl -> warn)) |
984 continue; | 1068 continue; |
985 for (e = cl -> err; e; e = e -> next) | 1069 for (e = cl -> err; e; e = e -> next) |
986 { | 1070 { |
987 fprintf(stderr, "ERROR: %s\n", e -> mess); | 1071 fprintf(stderr, "ERROR: %s (%d)\n", e -> mess, e -> code); |
988 } | 1072 } |
989 for (e = cl -> warn; e; e = e -> next) | 1073 for (e = cl -> warn; e; e = e -> next) |
990 { | 1074 { |
991 fprintf(stderr, "WARNING: %s\n", e -> mess); | 1075 fprintf(stderr, "WARNING: %s (%d)\n", e -> mess, e -> code); |
992 } | 1076 } |
993 fprintf(stderr, "%s:%05d %s\n\n", cl -> linespec, cl -> lineno, cl -> ltext); | 1077 fprintf(stderr, "%s:%05d %s\n\n", cl -> linespec, cl -> lineno, cl -> ltext); |
994 } | 1078 } |
995 } | 1079 } |
996 | 1080 |