From 06a3719304c066d287d6ef27e8df73bb69f2e76b Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 20 Jan 2020 19:49:22 -0600 Subject: [PATCH] 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. --- Scanner.pas | 72 ++++++++++++++++++++++++++++++----------------------- cc.notes | 2 ++ 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/Scanner.pas b/Scanner.pas index be30a93..5d558c8 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -1363,37 +1363,35 @@ if macro^.parameters >= 0 then begin {find the values of the parameters} parmEnd := nil; repeat done := true; - if token.kind <> rparench then begin - parenCount := 0; - paramCount := paramCount+1; - new(newParm); - newParm^.next := nil; - if parmEnd = nil then - parms := newParm - else - parmEnd^.next := newParm; - parmEnd := newParm; - newParm^.tokens := nil; - while (token.kind <> eofsy) - and ((parenCount <> 0) - or (not (token.kind in [rparench,commach]))) do begin - new(tPtr); - tPtr^.next := newParm^.tokens; - newParm^.tokens := tPtr; - tPtr^.token := token; - tPtr^.tokenStart := tokenStart; - tPtr^.tokenEnd := tokenEnd; - tPtr^.expandEnabled := tokenExpandEnabled; - if token.kind = lparench then - parenCount := parenCount+1 - else if token.kind = rparench then - parenCount := parenCount-1; - NextToken; - end; {while} - if token.kind = commach then begin - NextToken; - done := false; - end; {if} + parenCount := 0; + paramCount := paramCount+1; + new(newParm); + newParm^.next := nil; + if parmEnd = nil then + parms := newParm + else + parmEnd^.next := newParm; + parmEnd := newParm; + newParm^.tokens := nil; + while (token.kind <> eofsy) + and ((parenCount <> 0) + or (not (token.kind in [rparench,commach]))) do begin + new(tPtr); + tPtr^.next := newParm^.tokens; + newParm^.tokens := tPtr; + tPtr^.token := token; + tPtr^.tokenStart := tokenStart; + tPtr^.tokenEnd := tokenEnd; + tPtr^.expandEnabled := tokenExpandEnabled; + if token.kind = lparench then + parenCount := parenCount+1 + else if token.kind = rparench then + parenCount := parenCount-1; + NextToken; + end; {while} + if token.kind = commach then begin + NextToken; + done := false; end; {if} until done; if paramCount <> macro^.parameters then @@ -1501,6 +1499,8 @@ else begin {handle macro stringization} if stringization then begin tcPtr := pptr^.tokens; + if tcPtr = nil then + BuildStringToken(nil, 0); while tcPtr <> nil do begin if tcPtr^.token.kind = stringconst then BuildStringToken(@tcPtr^.token.sval^.str, @@ -1516,6 +1516,16 @@ else begin {expand a macro parameter} else begin 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 tokenStart := tcPtr^.tokenStart; tokenEnd := tcPtr^.tokenEnd; diff --git a/cc.notes b/cc.notes index c7e37b6..6031a2b 100644 --- a/cc.notes +++ b/cc.notes @@ -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. (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 ----------------------------------- 1. In some situations, fread() reread the first 1K or so of the file.