Allow for empty macro arguments, as specified by C99 and later.

These were previously allowed in some cases, but not as the last argument to a macro. Also, stringization and concatenation of them did not behave according to the standards.
This commit is contained in:
Stephen Heumann 2020-01-20 19:49:22 -06:00
parent 656868a095
commit 06a3719304
2 changed files with 43 additions and 31 deletions

View File

@ -1363,37 +1363,35 @@ if macro^.parameters >= 0 then begin {find the values of the parameters}
parmEnd := nil; parmEnd := nil;
repeat repeat
done := true; done := true;
if token.kind <> rparench then begin parenCount := 0;
parenCount := 0; paramCount := paramCount+1;
paramCount := paramCount+1; new(newParm);
new(newParm); newParm^.next := nil;
newParm^.next := nil; if parmEnd = nil then
if parmEnd = nil then parms := newParm
parms := newParm else
else parmEnd^.next := newParm;
parmEnd^.next := newParm; parmEnd := newParm;
parmEnd := newParm; newParm^.tokens := nil;
newParm^.tokens := nil; while (token.kind <> eofsy)
while (token.kind <> eofsy) and ((parenCount <> 0)
and ((parenCount <> 0) or (not (token.kind in [rparench,commach]))) do begin
or (not (token.kind in [rparench,commach]))) do begin new(tPtr);
new(tPtr); tPtr^.next := newParm^.tokens;
tPtr^.next := newParm^.tokens; newParm^.tokens := tPtr;
newParm^.tokens := tPtr; tPtr^.token := token;
tPtr^.token := token; tPtr^.tokenStart := tokenStart;
tPtr^.tokenStart := tokenStart; tPtr^.tokenEnd := tokenEnd;
tPtr^.tokenEnd := tokenEnd; tPtr^.expandEnabled := tokenExpandEnabled;
tPtr^.expandEnabled := tokenExpandEnabled; if token.kind = lparench then
if token.kind = lparench then parenCount := parenCount+1
parenCount := parenCount+1 else if token.kind = rparench then
else if token.kind = rparench then parenCount := parenCount-1;
parenCount := parenCount-1; NextToken;
NextToken; end; {while}
end; {while} if token.kind = commach then begin
if token.kind = commach then begin NextToken;
NextToken; done := false;
done := false;
end; {if}
end; {if} end; {if}
until done; until done;
if paramCount <> macro^.parameters then if paramCount <> macro^.parameters then
@ -1501,6 +1499,8 @@ else begin
{handle macro stringization} {handle macro stringization}
if stringization then begin if stringization then begin
tcPtr := pptr^.tokens; tcPtr := pptr^.tokens;
if tcPtr = nil then
BuildStringToken(nil, 0);
while tcPtr <> nil do begin while tcPtr <> nil do begin
if tcPtr^.token.kind = stringconst then if tcPtr^.token.kind = stringconst then
BuildStringToken(@tcPtr^.token.sval^.str, BuildStringToken(@tcPtr^.token.sval^.str,
@ -1516,6 +1516,16 @@ else begin
{expand a macro parameter} {expand a macro parameter}
else begin else begin
tcPtr := pptr^.tokens; tcPtr := pptr^.tokens;
if tcPtr = nil then begin
if tlPtr^.next <> nil then
if tlPtr^.next^.token.kind = poundpoundop then
tlPtr^.next := tlPtr^.next^.next;
if lastPtr <> nil then
if lastPtr^.token.kind = poundpoundop then
if tokenList <> nil then
if tokenList^.token.kind = poundpoundop then
tokenList := tokenList^.next;
end; {if}
while tcPtr <> nil do begin while tcPtr <> nil do begin
tokenStart := tcPtr^.tokenStart; tokenStart := tcPtr^.tokenStart;
tokenEnd := tcPtr^.tokenEnd; tokenEnd := tcPtr^.tokenEnd;

View File

@ -868,6 +868,8 @@ int foo(int[42]);
109. strtoul() should return 0 when given an empty string. It now does, and also sets errno to EINVAL in that case. 109. strtoul() should return 0 when given an empty string. It now does, and also sets errno to EINVAL in that case.
(This was a regression introduced in ORCA/C 2.2.0 B3.) (This was a regression introduced in ORCA/C 2.2.0 B3.)
110. Any or all of the arguments to a function-like macro can be empty, as specified in the C99 and later standards. (Empty macro arguments previously worked in some cases, but gave errors or non-standard behavior in others.)
-- Bugs from C 2.1.0 that have been fixed ----------------------------------- -- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file. 1. In some situations, fread() reread the first 1K or so of the file.