Remove code that treats # as an illegal character in most places.

C90 had constraints requiring # and ## tokens to only appear in preprocessing directives, but C99 and later removed those constraints, so this code is no longer necessary when targeting current languages versions. (It would be necessary in a "strict C90" mode, if that was ever implemented.)

The main practical effect of this is that # and ## tokens can be passed as parameters to macros, provided the macro either ignores or stringizes that parameter. # and ## tokens still have no role in the grammar of the C language after preprocessing, so they will be an unexpected token and produce some kind of error if they appear anywhere.

This also contains a change to ensure that a line containing one or more illegal characters (e.g. $) and then a # is not treated as a preprocessing directive.
This commit is contained in:
Stephen Heumann 2022-10-13 18:12:02 -05:00
parent 99a10590b1
commit b8b7dc2c2b
4 changed files with 20 additions and 41 deletions

View File

@ -166,10 +166,8 @@ var
{ An error was found: skip to the end & quit } { An error was found: skip to the end & quit }
begin {Skip} begin {Skip}
charKinds[ord('#')] := ch_pound;
while not (token.kind in [rbracech,eofsy]) do while not (token.kind in [rbracech,eofsy]) do
NextToken; NextToken;
charKinds[ord('#')] := illegal;
goto 99; goto 99;
end; {Skip} end; {Skip}
@ -329,7 +327,6 @@ while not (token.kind in [rbracech,eofsy]) do begin
{find the label and op-code} {find the label and op-code}
CheckForComment; CheckForComment;
charKinds[ord('#')] := ch_pound; {allow # as a token}
if token.kind <> ident then begin {error if not an identifier} if token.kind <> ident then begin {error if not an identifier}
Error(9); Error(9);
Skip; Skip;
@ -345,7 +342,6 @@ while not (token.kind in [rbracech,eofsy]) do begin
opname := token; opname := token;
NextToken; NextToken;
end; {while} end; {while}
charKinds[ord('#')] := illegal; {don't allow # as a token}
{identify the op-code} {identify the op-code}
if length(opname.name^) = 3 then begin if length(opname.name^) = 3 then begin

View File

@ -3625,33 +3625,19 @@ var
var var
braceCount: integer; {# of unmatched { chars} braceCount: integer; {# of unmatched { chars}
doingAsm: boolean; {compiling an asm statement?}
begin {SkipFunction} begin {SkipFunction}
Match(lbracech,27); {skip to the closing rbrackch} Match(lbracech,27); {skip to the closing rbrackch}
braceCount := 1; braceCount := 1;
doingAsm := false;
if isAsm then
charKinds[ord('#')] := ch_pound;
while (not (token.kind = eofsy)) and (braceCount <> 0) do begin while (not (token.kind = eofsy)) and (braceCount <> 0) do begin
if token.kind = asmsy then begin if token.kind = lbracech then
doingAsm := true;
charKinds[ord('#')] := ch_pound;
end {if}
else if token.kind = lbracech then
braceCount := braceCount+1 braceCount := braceCount+1
else if token.kind = rbracech then begin else if token.kind = rbracech then
braceCount := braceCount-1; braceCount := braceCount-1;
if doingAsm then begin
doingAsm := false;
charKinds[ord('#')] := illegal;
end; {if}
end; {else if}
NextToken; NextToken;
end; {while} end; {while}
nameFound := false; {no pc_nam for the next function (yet)} nameFound := false; {no pc_nam for the next function (yet)}
doingFunction := false; {no longer doing a function} doingFunction := false; {no longer doing a function}
charKinds[ord('#')] := illegal; {# is a preprocessor command}
end; {SkipFunction} end; {SkipFunction}

View File

@ -2545,7 +2545,6 @@ var
mPtr^.saved := false; {not saved in symbol file} mPtr^.saved := false; {not saved in symbol file}
mPtr^.tokens := nil; {no tokens yet} mPtr^.tokens := nil; {no tokens yet}
mPtr^.isVarargs := false; {not varargs (yet)} mPtr^.isVarargs := false; {not varargs (yet)}
charKinds[ord('#')] := ch_pound; {allow # as a token}
if ch = '(' then begin {scan the parameter list...} if ch = '(' then begin {scan the parameter list...}
NextToken; {done with the name token...} NextToken; {done with the name token...}
NextToken; {skip the opening '('} NextToken; {skip the opening '('}
@ -2750,7 +2749,6 @@ var
parameterList := np^.next; parameterList := np^.next;
dispose(np); dispose(np);
end; {while} end; {while}
charKinds[ord('#')] := illegal; {don't allow # as a token}
saveNumber := false; {stop saving numeric strings} saveNumber := false; {stop saving numeric strings}
end; {DoDefine} end; {DoDefine}
@ -3480,7 +3478,6 @@ else if charKinds[ord(ch)] = ch_eol {allow null commands}
if not tSkipping then if not tSkipping then
Error(8); {bad preprocessor command} Error(8); {bad preprocessor command}
2: 2:
charKinds[ord('#')] := ch_pound; {allow # as a token}
expandMacros := false; {skip to the end of the line} expandMacros := false; {skip to the end of the line}
flagOverflows := false; flagOverflows := false;
skipping := tSkipping; skipping := tSkipping;
@ -3488,7 +3485,6 @@ while not (token.kind in [eolsy,eofsy]) do
NextToken; NextToken;
flagOverflows := true; flagOverflows := true;
expandMacros := true; expandMacros := true;
charKinds[ord('#')] := illegal; {don't allow # as a token}
reportEOL := lReportEOL; {restore flags} reportEOL := lReportEOL; {restore flags}
suppressMacroExpansions := lSuppressMacroExpansions; suppressMacroExpansions := lSuppressMacroExpansions;
skipping := tskipping; skipping := tskipping;
@ -4243,7 +4239,6 @@ new(macros); {no preprocessor macros so far}
for i := 0 to hashSize do for i := 0 to hashSize do
macros^[i] := nil; macros^[i] := nil;
pathList := nil; {no additional search paths} pathList := nil; {no additional search paths}
charKinds[ord('#')] := illegal; {don't allow # as a token}
tokenList := nil; {nothing in putback buffer} tokenList := nil; {nothing in putback buffer}
saveNumber := false; {don't save numbers} saveNumber := false; {don't save numbers}
expandMacros := true; {enable macro expansion} expandMacros := true; {enable macro expansion}
@ -4619,7 +4614,7 @@ procedure NextToken;
{ Read the next token from the file. } { Read the next token from the file. }
label 1,2,3,4,5,6; label 1,2,3,4,5,6,7;
type type
three = (s100,s1000,sMAX); {these declarations are used for a} three = (s100,s1000,sMAX); {these declarations are used for a}
@ -4974,21 +4969,14 @@ if tokenList <> nil then begin {get a token put back by a macro}
goto 2; goto 2;
end; {if} end; {if}
5: {skip white space} 5: {skip white space}
while charKinds[ord(ch)] in [illegal,ch_white,ch_eol] do begin while charKinds[ord(ch)] in [illegal,ch_white,ch_eol,ch_pound] do begin
if charKinds[ord(ch)] = illegal then begin if charKinds[ord(ch)] = ch_pound then begin
if (ch = '#') and (lastWasReturn or (token.kind = eolsy)) then begin if lastWasReturn or (token.kind = eolsy) then begin
NextCh; {skip the '#' char} NextCh; {skip the '#' char}
PreProcess {call the preprocessor} PreProcess {call the preprocessor}
end {if} end {if}
else begin else
tokenLine := lineNumber; {record a # token} goto 7;
tokenColumn := ord(ord4(chPtr)-ord4(firstPtr));
tokenStart := pointer(ord4(chPtr)-1);
tokenEnd := chPtr;
if (not skipping) or (not (skipIllegalTokens or (ch = '#'))) then
Error(1);
NextCh;
end; {else}
end {if} end {if}
else if (charKinds[ord(ch)] = ch_eol) and reportEOL then begin else if (charKinds[ord(ch)] = ch_eol) and reportEOL then begin
token.class := reservedSymbol; {record an eol token} token.class := reservedSymbol; {record an eol token}
@ -5000,6 +4988,16 @@ while charKinds[ord(ch)] in [illegal,ch_white,ch_eol] do begin
NextCh; NextCh;
goto 2; goto 2;
end {if} end {if}
else if charKinds[ord(ch)] = illegal then begin
tokenLine := lineNumber; {record an illegal token}
tokenColumn := ord(ord4(chPtr)-ord4(firstPtr));
tokenStart := pointer(ord4(chPtr)-1);
tokenEnd := chPtr;
token.kind := questionch; {make sure it is not eolsy}
if (not skipping) or (not skipIllegalTokens) then
Error(1);
NextCh;
end {else if}
else begin {skip white space} else begin {skip white space}
if printMacroExpansions and not suppressMacroExpansions then if printMacroExpansions and not suppressMacroExpansions then
if charKinds[ord(ch)] = ch_eol then begin if charKinds[ord(ch)] = ch_eol then begin
@ -5011,6 +5009,7 @@ while charKinds[ord(ch)] in [illegal,ch_white,ch_eol] do begin
NextCh; NextCh;
end; end;
end; {while} end; {while}
7:
tokenLine := lineNumber; {record the position of the token} tokenLine := lineNumber; {record the position of the token}
tokenColumn := ord(ord4(currentChPtr)-ord4(firstPtr)+1); tokenColumn := ord(ord4(currentChPtr)-ord4(firstPtr)+1);
tokenStart := currentChPtr; tokenStart := currentChPtr;
@ -5183,8 +5182,6 @@ case charKinds[ord(ch)] of
token.isDigraph := true; token.isDigraph := true;
if (ch = '%') and (chPtr <> eofPtr) and (chr(chPtr^) = ':') then begin if (ch = '%') and (chPtr <> eofPtr) and (chr(chPtr^) = ':') then begin
token.kind := poundpoundop; {%:%: digraph} token.kind := poundpoundop; {%:%: digraph}
if charKinds[ord('#')] = illegal then
Error(1);
NextCh; NextCh;
NextCh; NextCh;
end end

View File

@ -57,7 +57,7 @@ charKinds start character set
dc i'ch_white' space dc i'ch_white' space
dc i'ch_exc' ! dc i'ch_exc' !
dc i'ch_string' " dc i'ch_string' "
dc i'illegal' # dc i'ch_pound' #
dc i'illegal' $ dc i'illegal' $
dc i'ch_percent' % dc i'ch_percent' %
dc i'ch_and' & dc i'ch_and' &