mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-05 01:59:30 +01:00
codetools: implemented start of extern c
git-svn-id: trunk@14283 -
This commit is contained in:
parent
1825f74f2a
commit
9519c2624f
@ -49,6 +49,7 @@ const
|
|||||||
|
|
||||||
ccnRoot = 1+ccnBase;
|
ccnRoot = 1+ccnBase;
|
||||||
ccnDirective = 2+ccnBase;// e.g. "#define a" ,can be multiple lines, without line end
|
ccnDirective = 2+ccnBase;// e.g. "#define a" ,can be multiple lines, without line end
|
||||||
|
ccnExtern = 3+ccnBase;// e.g. extern "C" {}
|
||||||
|
|
||||||
type
|
type
|
||||||
TCCodeParserTool = class;
|
TCCodeParserTool = class;
|
||||||
@ -70,6 +71,7 @@ type
|
|||||||
|
|
||||||
function OtherToken: boolean;
|
function OtherToken: boolean;
|
||||||
function DirectiveToken: boolean;
|
function DirectiveToken: boolean;
|
||||||
|
function ExternToken: boolean;
|
||||||
procedure InitKeyWordList;
|
procedure InitKeyWordList;
|
||||||
|
|
||||||
procedure InitParser;
|
procedure InitParser;
|
||||||
@ -78,6 +80,7 @@ type
|
|||||||
procedure CloseNodes;
|
procedure CloseNodes;
|
||||||
|
|
||||||
procedure RaiseException(const AMessage: string);
|
procedure RaiseException(const AMessage: string);
|
||||||
|
procedure RaiseExpectedButAtomFound(const AToken: string);
|
||||||
public
|
public
|
||||||
Code: TCodeBuffer;
|
Code: TCodeBuffer;
|
||||||
Src: string;
|
Src: string;
|
||||||
@ -101,6 +104,7 @@ type
|
|||||||
function AtomIs(const s: shortstring): boolean;
|
function AtomIs(const s: shortstring): boolean;
|
||||||
function UpAtomIs(const s: shortstring): boolean;
|
function UpAtomIs(const s: shortstring): boolean;
|
||||||
function AtomIsIdentifier: boolean;
|
function AtomIsIdentifier: boolean;
|
||||||
|
function AtomIsStringConstant: boolean;
|
||||||
function GetAtom: string;
|
function GetAtom: string;
|
||||||
|
|
||||||
procedure Replace(FromPos, ToPos: integer; const NewSrc: string);
|
procedure Replace(FromPos, ToPos: integer; const NewSrc: string);
|
||||||
@ -152,12 +156,25 @@ begin
|
|||||||
EndChildNode;
|
EndChildNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCCodeParserTool.ExternToken: boolean;
|
||||||
|
begin
|
||||||
|
Result:=true;
|
||||||
|
CreateChildNode(ccnExtern);
|
||||||
|
ReadNextAtom;
|
||||||
|
if not AtomIsStringConstant then
|
||||||
|
RaiseExpectedButAtomFound('string constant');
|
||||||
|
ReadNextAtom;
|
||||||
|
if not AtomIs('{') then
|
||||||
|
RaiseExpectedButAtomFound('{');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCCodeParserTool.InitKeyWordList;
|
procedure TCCodeParserTool.InitKeyWordList;
|
||||||
begin
|
begin
|
||||||
if FDefaultTokenList=nil then begin
|
if FDefaultTokenList=nil then begin
|
||||||
FDefaultTokenList:=TKeyWordFunctionList.Create;
|
FDefaultTokenList:=TKeyWordFunctionList.Create;
|
||||||
with FDefaultTokenList do begin
|
with FDefaultTokenList do begin
|
||||||
Add('#',{$ifdef FPC}@{$endif}DirectiveToken);
|
Add('#',{$ifdef FPC}@{$endif}DirectiveToken);
|
||||||
|
Add('extern',{$ifdef FPC}@{$endif}ExternToken);
|
||||||
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}OtherToken;
|
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}OtherToken;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -216,6 +233,11 @@ begin
|
|||||||
raise ECCodeParserException.Create(Self,AMessage);
|
raise ECCodeParserException.Create(Self,AMessage);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCCodeParserTool.RaiseExpectedButAtomFound(const AToken: string);
|
||||||
|
begin
|
||||||
|
RaiseException(AToken+' expected, but '+GetAtom+' found');
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TCCodeParserTool.Create;
|
constructor TCCodeParserTool.Create;
|
||||||
begin
|
begin
|
||||||
Tree:=TCodeTree.Create;
|
Tree:=TCodeTree.Create;
|
||||||
@ -318,6 +340,11 @@ begin
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCCodeParserTool.AtomIsStringConstant: boolean;
|
||||||
|
begin
|
||||||
|
Result:=(AtomStart<SrcLen) and (Src[AtomStart]='"');
|
||||||
|
end;
|
||||||
|
|
||||||
function TCCodeParserTool.GetAtom: string;
|
function TCCodeParserTool.GetAtom: string;
|
||||||
begin
|
begin
|
||||||
Result:=copy(Src,AtomStart,SrcPos-AtomStart);
|
Result:=copy(Src,AtomStart,SrcPos-AtomStart);
|
||||||
|
|||||||
@ -1900,7 +1900,8 @@ var
|
|||||||
NeededType:=ctnNone;
|
NeededType:=ctnNone;
|
||||||
|
|
||||||
if BracketStartPos>0 then begin
|
if BracketStartPos>0 then begin
|
||||||
if WordIsKeyWord.DoIt(@Src[ReferingPos]) then exit;
|
if WordIsKeyWord.DoItCaseInsensitive(@Src[ReferingPos]) then
|
||||||
|
exit;
|
||||||
// this is a type cast
|
// this is a type cast
|
||||||
NeededType:=ctnConstDefinition;
|
NeededType:=ctnConstDefinition;
|
||||||
//GetReferingNode;
|
//GetReferingNode;
|
||||||
|
|||||||
@ -1930,7 +1930,8 @@ var
|
|||||||
repeat
|
repeat
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if (AtomStart<=SrcLen)
|
if (AtomStart<=SrcLen)
|
||||||
and IsKeyWordProcedureSpecifier.DoIt(@Src[AtomStart]) then begin
|
and IsKeyWordProcedureSpecifier.DoItCaseInsensitive(@Src[AtomStart])
|
||||||
|
then begin
|
||||||
if UpAtomIs('EXTERNAL') then
|
if UpAtomIs('EXTERNAL') then
|
||||||
IsExternal:=true;
|
IsExternal:=true;
|
||||||
if UpAtomIs('FORWARD') then
|
if UpAtomIs('FORWARD') then
|
||||||
|
|||||||
@ -27,6 +27,8 @@ unit KeywordFuncLists;
|
|||||||
|
|
||||||
{$ifdef FPC}{$mode objfpc}{$endif}{$H+}
|
{$ifdef FPC}{$mode objfpc}{$endif}{$H+}
|
||||||
|
|
||||||
|
{$R-} // turn range checking off for speed
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
{ $DEFINE MEM_CHECK}
|
{ $DEFINE MEM_CHECK}
|
||||||
@ -49,6 +51,8 @@ type
|
|||||||
end;
|
end;
|
||||||
PKeyWordFunctionListItem = ^TKeyWordFunctionListItem;
|
PKeyWordFunctionListItem = ^TKeyWordFunctionListItem;
|
||||||
|
|
||||||
|
{ TKeyWordFunctionList }
|
||||||
|
|
||||||
TKeyWordFunctionList = class
|
TKeyWordFunctionList = class
|
||||||
private
|
private
|
||||||
FItems: PKeyWordFunctionListItem;
|
FItems: PKeyWordFunctionListItem;
|
||||||
@ -65,12 +69,14 @@ type
|
|||||||
public
|
public
|
||||||
DefaultKeyWordFunction: TKeyWordFunction;
|
DefaultKeyWordFunction: TKeyWordFunction;
|
||||||
function DoIt(const AKeyWord: shortstring): boolean;
|
function DoIt(const AKeyWord: shortstring): boolean;
|
||||||
function DoIt(const ASource: string;
|
|
||||||
KeyWordStart, KeyWordLen: integer): boolean;
|
|
||||||
function DoIt(Identifier: PChar): boolean;
|
|
||||||
function DoItUppercase(const AnUpperSource: string;
|
|
||||||
KeyWordStart, KeyWordLen: integer): boolean;
|
|
||||||
function DoItCaseInsensitive(const AKeyWord: shortstring): boolean;
|
function DoItCaseInsensitive(const AKeyWord: shortstring): boolean;
|
||||||
|
function DoItCaseInsensitive(const ASource: string;
|
||||||
|
KeyWordStart, KeyWordLen: integer): boolean;
|
||||||
|
function DoIt(const ASource: string;
|
||||||
|
KeyWordStart, KeyWordLen: integer): boolean;
|
||||||
|
function DoItUppercase(const AnUpperSource: string;
|
||||||
|
KeyWordStart, KeyWordLen: integer): boolean;
|
||||||
|
function DoItCaseInsensitive(Identifier: PChar): boolean;
|
||||||
function DoDataFunction(Start: PChar; Len: integer; Data: pointer): boolean;
|
function DoDataFunction(Start: PChar; Len: integer; Data: pointer): boolean;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
procedure Add(const AKeyWord: shortstring;
|
procedure Add(const AKeyWord: shortstring;
|
||||||
@ -145,9 +151,8 @@ function IsUpperCaseStr(const s: string): boolean;
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
CharToHash: array[char] of integer;
|
CharToIHash: array[char] of integer;
|
||||||
UpWords: array[word] of word;
|
UpWords: array[word] of word;
|
||||||
|
|
||||||
function UpperCaseStr(const s: string): string;
|
function UpperCaseStr(const s: string): string;
|
||||||
@ -181,11 +186,7 @@ end;
|
|||||||
constructor TKeyWordFunctionList.Create;
|
constructor TKeyWordFunctionList.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FItems:=nil;
|
|
||||||
FCount:=0;
|
|
||||||
FCapacity:=0;
|
|
||||||
FSorted:=true;
|
FSorted:=true;
|
||||||
FBucketStart:=nil;
|
|
||||||
FMaxHashIndex:=-1;
|
FMaxHashIndex:=-1;
|
||||||
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}AllwaysFalse;
|
DefaultKeyWordFunction:={$ifdef FPC}@{$endif}AllwaysFalse;
|
||||||
end;
|
end;
|
||||||
@ -220,7 +221,7 @@ begin
|
|||||||
if KeyWordLen>20 then KeyWordLen:=20;
|
if KeyWordLen>20 then KeyWordLen:=20;
|
||||||
Result:=0;
|
Result:=0;
|
||||||
for i:=1 to KeyWordLen do
|
for i:=1 to KeyWordLen do
|
||||||
inc(Result,CharToHash[AKeyWord[i]]);
|
inc(Result,CharToIHash[AKeyWord[i]]);
|
||||||
if Result>FMaxHashIndex then Result:=-1;
|
if Result>FMaxHashIndex then Result:=-1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -232,7 +233,7 @@ begin
|
|||||||
AEnd:=AStart+ALen-1;
|
AEnd:=AStart+ALen-1;
|
||||||
Result:=0;
|
Result:=0;
|
||||||
for i:=AStart to AEnd do
|
for i:=AStart to AEnd do
|
||||||
inc(Result,CharToHash[ASource[i]]);
|
inc(Result,CharToIHash[ASource[i]]);
|
||||||
if Result>FMaxHashIndex then Result:=-1;
|
if Result>FMaxHashIndex then Result:=-1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -242,7 +243,7 @@ begin
|
|||||||
Result:=0;
|
Result:=0;
|
||||||
i:=20;
|
i:=20;
|
||||||
while (i>0) and IsIdentChar[Identifier[0]] do begin
|
while (i>0) and IsIdentChar[Identifier[0]] do begin
|
||||||
inc(Result,CharToHash[Identifier[0]]);
|
inc(Result,CharToIHash[Identifier[0]]);
|
||||||
dec(i);
|
dec(i);
|
||||||
inc(Identifier);
|
inc(Identifier);
|
||||||
end;
|
end;
|
||||||
@ -255,7 +256,7 @@ begin
|
|||||||
Result:=0;
|
Result:=0;
|
||||||
if Len>20 then Len:=20;
|
if Len>20 then Len:=20;
|
||||||
while (Len>0) do begin
|
while (Len>0) do begin
|
||||||
inc(Result,CharToHash[Start^]);
|
inc(Result,CharToIHash[Start^]);
|
||||||
dec(Len);
|
dec(Len);
|
||||||
inc(Start);
|
inc(Start);
|
||||||
end;
|
end;
|
||||||
@ -289,7 +290,7 @@ begin
|
|||||||
Result:=DefaultKeyWordFunction();
|
Result:=DefaultKeyWordFunction();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TKeyWordFunctionList.DoIt(const ASource: string;
|
function TKeyWordFunctionList.DoItCaseInsensitive(const ASource: string;
|
||||||
KeyWordStart, KeyWordLen: integer): boolean;
|
KeyWordStart, KeyWordLen: integer): boolean;
|
||||||
// ! does not test if length(ASource) >= KeyWordStart+KeyWordLen -1
|
// ! does not test if length(ASource) >= KeyWordStart+KeyWordLen -1
|
||||||
var i, KeyPos, WordPos: integer;
|
var i, KeyPos, WordPos: integer;
|
||||||
@ -328,7 +329,47 @@ begin
|
|||||||
Result:=DefaultKeyWordFunction();
|
Result:=DefaultKeyWordFunction();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TKeyWordFunctionList.DoIt(Identifier: PChar): boolean;
|
function TKeyWordFunctionList.DoIt(const ASource: string; KeyWordStart,
|
||||||
|
KeyWordLen: integer): boolean;
|
||||||
|
// ! does not test if length(ASource) >= KeyWordStart+KeyWordLen -1
|
||||||
|
var
|
||||||
|
i, KeyPos, WordPos: integer;
|
||||||
|
KeyWordFuncItem: PKeyWordFunctionListItem;
|
||||||
|
begin
|
||||||
|
if not FSorted then Sort;
|
||||||
|
i:=KeyWordToHashIndex(ASource,KeyWordStart,KeyWordLen);
|
||||||
|
if i>=0 then begin
|
||||||
|
i:=FBucketStart[i];
|
||||||
|
if i>=0 then begin
|
||||||
|
dec(KeyWordStart);
|
||||||
|
repeat
|
||||||
|
KeyWordFuncItem:=@FItems[i];
|
||||||
|
if length(KeyWordFuncItem^.KeyWord)=KeyWordLen then begin
|
||||||
|
KeyPos:=KeyWordLen;
|
||||||
|
WordPos:=KeyWordStart+KeyWordLen;
|
||||||
|
while (KeyPos>=1)
|
||||||
|
and (KeyWordFuncItem^.KeyWord[KeyPos]=ASource[WordPos]) do
|
||||||
|
begin
|
||||||
|
dec(KeyPos);
|
||||||
|
dec(WordPos);
|
||||||
|
end;
|
||||||
|
if KeyPos<1 then begin
|
||||||
|
if Assigned(KeyWordFuncItem^.DoIt) then
|
||||||
|
Result:=KeyWordFuncItem^.DoIt()
|
||||||
|
else
|
||||||
|
Result:=DefaultKeyWordFunction();
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if (KeyWordFuncItem^.IsLast) then break;
|
||||||
|
inc(i);
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=DefaultKeyWordFunction();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKeyWordFunctionList.DoItCaseInsensitive(Identifier: PChar): boolean;
|
||||||
// checks
|
// checks
|
||||||
var i, KeyPos, KeyWordLen: integer;
|
var i, KeyPos, KeyWordLen: integer;
|
||||||
KeyWordFuncItem: PKeyWordFunctionListItem;
|
KeyWordFuncItem: PKeyWordFunctionListItem;
|
||||||
@ -638,11 +679,11 @@ var
|
|||||||
c: char;
|
c: char;
|
||||||
w: word;
|
w: word;
|
||||||
begin
|
begin
|
||||||
for c:=Low(UpChars) to High(UpChars) do begin
|
for c:=Low(char) to High(char) do begin
|
||||||
case c of
|
case c of
|
||||||
'a'..'z':CharToHash[c]:=ord(c)-ord('a')+1;
|
'a'..'z':CharToIHash[c]:=ord(c)-ord('a')+1;
|
||||||
'A'..'Z':CharToHash[c]:=ord(c)-ord('A')+1;
|
'A'..'Z':CharToIHash[c]:=ord(c)-ord('A')+1;
|
||||||
else CharToHash[c]:=0;
|
else CharToIHash[c]:=ord(c);
|
||||||
end;
|
end;
|
||||||
UpChars[c]:=upcase(c);
|
UpChars[c]:=upcase(c);
|
||||||
IsLineEndChar[c]:=c in [#10,#13];
|
IsLineEndChar[c]:=c in [#10,#13];
|
||||||
|
|||||||
@ -884,7 +884,7 @@ begin
|
|||||||
DirLen:=SrcPos-DirStart;
|
DirLen:=SrcPos-DirStart;
|
||||||
if DirLen>255 then DirLen:=255;
|
if DirLen>255 then DirLen:=255;
|
||||||
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
|
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
|
||||||
FDirectiveFuncList.DoIt(Src,DirStart,DirLen);
|
FDirectiveFuncList.DoItCaseInsensitive(Src,DirStart,DirLen);
|
||||||
SrcPos:=CommentEndPos;
|
SrcPos:=CommentEndPos;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -958,7 +958,7 @@ begin
|
|||||||
while (SrcPos<=SrcLen)
|
while (SrcPos<=SrcLen)
|
||||||
and (IsIdentChar[Src[SrcPos]]) do
|
and (IsIdentChar[Src[SrcPos]]) do
|
||||||
inc(SrcPos);
|
inc(SrcPos);
|
||||||
KeywordFuncList.DoIt(Src,TokenStart,SrcPos-TokenStart);
|
KeywordFuncList.DoItCaseInsensitive(Src,TokenStart,SrcPos-TokenStart);
|
||||||
end;
|
end;
|
||||||
'''','#':
|
'''','#':
|
||||||
begin
|
begin
|
||||||
@ -2177,7 +2177,7 @@ begin
|
|||||||
DirLen:=SrcPos-DirStart;
|
DirLen:=SrcPos-DirStart;
|
||||||
if DirLen>255 then DirLen:=255;
|
if DirLen>255 then DirLen:=255;
|
||||||
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
|
FDirectiveName:=UpperCaseStr(copy(Src,DirStart,DirLen));
|
||||||
Result:=FDirectiveFuncList.DoIt(Src,DirStart,DirLen);
|
Result:=FDirectiveFuncList.DoItCaseInsensitive(Src,DirStart,DirLen);
|
||||||
end else
|
end else
|
||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -286,18 +286,15 @@ begin
|
|||||||
'"': // string constant
|
'"': // string constant
|
||||||
begin
|
begin
|
||||||
while (Position<=Len) do begin
|
while (Position<=Len) do begin
|
||||||
case (Source[Position]) of
|
if (Source[Position]='"') then
|
||||||
'"':
|
begin
|
||||||
begin
|
inc(Position);
|
||||||
|
while (Position<=Len)
|
||||||
|
and (Source[Position]<>'"') do
|
||||||
inc(Position);
|
inc(Position);
|
||||||
while (Position<=Len)
|
inc(Position);
|
||||||
and (Source[Position]<>'"') do
|
end else
|
||||||
inc(Position);
|
|
||||||
inc(Position);
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
'''': // char constant
|
'''': // char constant
|
||||||
|
|||||||
@ -1699,7 +1699,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
// read specifiers
|
// read specifiers
|
||||||
while not (CurPos.Flag in [cafSemicolon,cafNone]) do begin
|
while not (CurPos.Flag in [cafSemicolon,cafNone]) do begin
|
||||||
if WordIsPropertySpecifier.DoIt(@Src[CurPos.StartPos]) then begin
|
if WordIsPropertySpecifier.DoItCaseInsensitive(@Src[CurPos.StartPos])
|
||||||
|
then begin
|
||||||
if AtomIs(s) then exit(true);
|
if AtomIs(s) then exit(true);
|
||||||
end else if CurPos.Flag=cafEdgedBracketOpen then begin
|
end else if CurPos.Flag=cafEdgedBracketOpen then begin
|
||||||
ReadTilBracketClose(true);
|
ReadTilBracketClose(true);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user