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