Bugfixes in macro expansion:

1. If expansion fails, don't crash.
2. Accept duplicate named arguments, the last one wins.
This commit is contained in:
Paul Koning
2022-06-29 09:45:37 -04:00
parent 7354aadbfc
commit 0513f914bc
4 changed files with 64 additions and 14 deletions

View File

@@ -350,6 +350,10 @@ do_mcalled_macro:
list_location(stack->top, DOT); list_location(stack->top, DOT);
macstr = expandmacro(stack->top, (MACRO *) op, ncp); macstr = expandmacro(stack->top, (MACRO *) op, ncp);
if (macstr == NULL) {
/* Error in expanding the macro, stop now. */
return 0;
}
stack_push(stack, macstr); /* Push macro expansion stack_push(stack, macstr); /* Push macro expansion
onto input stream */ onto input stream */

View File

@@ -478,15 +478,19 @@ STREAM *expandmacro(
label = get_symbol(cp, &nextcp, NULL); label = get_symbol(cp, &nextcp, NULL);
if (label && (nextcp = skipwhite(nextcp), *nextcp == '=') && (macarg = find_arg(mac->args, label))) { if (label && (nextcp = skipwhite(nextcp), *nextcp == '=') && (macarg = find_arg(mac->args, label))) {
/* Check if I've already got a value for it */ /* Check if I've already got a value for it */
if (find_arg(args, label) != NULL) { if ((arg = find_arg(args, label)) != NULL) {
report(refstr, "Duplicate submission of keyword " "argument %s\n", label); /* Duplicate is legal; the last one wins. */
free(label); if (arg->value) {
free_args(args); free (arg->value);
return NULL; arg->value = NULL;
}
}
else {
arg = new_arg();
arg->label = label;
arg->next = args;
args = arg;
} }
arg = new_arg();
arg->label = label;
nextcp = skipwhite(nextcp + 1); nextcp = skipwhite(nextcp + 1);
arg->value = getstring_macarg(refstr, nextcp, &nextcp); arg->value = getstring_macarg(refstr, nextcp, &nextcp);
} else { } else {
@@ -506,6 +510,8 @@ STREAM *expandmacro(
nextcp = skipwhite (cp); nextcp = skipwhite (cp);
arg = new_arg(); arg = new_arg();
arg->label = memcheck(strdup(macarg->label)); /* Copy the name */ arg->label = memcheck(strdup(macarg->label)); /* Copy the name */
arg->next = args;
args = arg;
if (*nextcp != ',') { if (*nextcp != ',') {
arg->value = getstring_macarg(refstr, cp, &nextcp); arg->value = getstring_macarg(refstr, cp, &nextcp);
} }
@@ -515,9 +521,6 @@ STREAM *expandmacro(
nargs++; /* Count nonkeyword arguments only. */ nargs++; /* Count nonkeyword arguments only. */
} }
arg->next = args;
args = arg;
/* If there is a trailing comma, there is an empty last argument */ /* If there is a trailing comma, there is an empty last argument */
cp = skipdelim_comma(nextcp, &onemore); cp = skipdelim_comma(nextcp, &onemore);
} }

View File

@@ -77,15 +77,41 @@
1 000003 .narg label ; second arg is "default" 1 000003 .narg label ; second arg is "default"
53 000000 tstarg 1,2,3 ; 3 args 53 000000 tstarg 1,2,3 ; 3 args
1 000003 .narg label ; second arg is "2" 1 000003 .narg label ; second arg is "2"
53 54
55 ;
56 ; Test default args and strange commas
57 ;
58 .macro tstdef a=1,b=2
59 .word a,b
60 .endm
61
62 000000 tstdef
1 000000 000001 000002 .word 1,2
63 000004 tstdef 4,5
1 000004 000004 000005 .word 4,5
64 000010 tstdef 4,5,6 ; Excess argument is ignored
1 000010 000004 000005 .word 4,5
65 000014 tstdef b=42
1 000014 000001 000042 .word 1,42
66 000020 tstdef a=73
1 000020 000073 000002 .word 73,2
67 000024 tstdef ,b=11
1 000024 000001 000011 .word 1,11
68 000030 tstdef a=5,b=4
1 000030 000005 000004 .word 5,4
69 000034 tstdef ,a=5,b=4 ; Strange case seen in some sources
1 000034 000005 000004 .word 5,4
70 000040 tstdef a=5,a=4 ; Duplicate keyword argument -- legal!
1 000040 000004 000002 .word 4,2
70
Symbol table Symbol table
. 000000R 001 LABEL = 000003 START 000000R 001 . 000044R 001 LABEL = 000003 START 000000R 001
Program sections: Program sections:
. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV) . ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV)
000000 001 (RW,I,LCL,REL,CON,NOSAV) 000044 001 (RW,I,LCL,REL,CON,NOSAV)

View File

@@ -51,3 +51,20 @@ start: tstarg ; 0 args
tstarg ,,3 ; 3 args tstarg ,,3 ; 3 args
tstarg 1,,3 ; 3 args tstarg 1,,3 ; 3 args
tstarg 1,2,3 ; 3 args tstarg 1,2,3 ; 3 args
;
; Test default args and strange commas
;
.macro tstdef a=1,b=2
.word a,b
.endm
tstdef
tstdef 4,5
tstdef 4,5,6 ; Excess argument is ignored
tstdef b=42
tstdef a=73
tstdef ,b=11
tstdef a=5,b=4
tstdef ,a=5,b=4 ; Strange case seen in some sources
tstdef a=5,a=4 ; Duplicate keyword argument -- legal!