pastojs: adaptions for pas2js

git-svn-id: trunk@40049 -
This commit is contained in:
Mattias Gaertner 2018-10-27 11:17:58 +00:00
parent 43c2dce24f
commit a2c16728cc
6 changed files with 174 additions and 86 deletions

View File

@ -76,7 +76,7 @@ begin
raise Exception.Create('TPas2JSSrcMap.Release');
dec(fRefCount);
if fRefCount<0 then
Free;
{$IFDEF pas2js}Destroy{$ELSE}Free{$ENDIF};
end;
{ TPas2JSMapper }
@ -128,8 +128,7 @@ end;
procedure TPas2JSMapper.Writing;
var
S: TJSString;
p: PWideChar;
Line: Integer;
p, l, Line: Integer;
begin
inherited Writing;
if SrcMap=nil then exit;
@ -153,15 +152,14 @@ begin
begin
// possible multi line value, e.g. asm-block
S:=TJSLiteral(CurElement).Value.CustomValue;
p:=PWideChar(S);
l:=length(S);
p:=1;
Line:=0;
repeat
case p^ of
#0:
break;
while p<=l do
case S[p] of
#10,#13:
begin
if (p[1] in [#10,#13]) and (p^<>p[1]) then
if (p<l) and (S[p+1] in [#10,#13]) and (S[p]<>S[p+1]) then
inc(p,2)
else
inc(p);
@ -175,7 +173,6 @@ begin
else
inc(p);
end;
until false;
end;
end;
@ -187,33 +184,33 @@ end;
procedure TPas2JSMapper.WriteFile(Src, Filename: string);
var
p, EndP, LineStart: PChar;
l, p, LineStart: integer;
begin
if Src='' then exit;
FSrcFilename:=Filename;
FSrcLine:=1;
FSrcColumn:=1;
p:=PChar(Src);
EndP:=p+length(Src);
l:=length(Src);
p:=1;
repeat
LineStart:=p;
repeat
case p^ of
#0: if p=EndP then break;
while (p<=l) do
case Src[p] of
#10,#13:
begin
if (p[1] in [#10,#13]) and (p^<>p[1]) then
if (p<l) and (Src[p+1] in [#10,#13]) and (Src[p]<>Src[p+1]) then
inc(p,2)
else
inc(p);
inc(p);
break;
end;
else
inc(p);
end;
inc(p);
until false;
FNeedMapping:=true;
Write(copy(Src,LineStart-PChar(Src)+1,p-LineStart));
Write(copy(Src,LineStart,p-LineStart));
inc(FSrcLine);
until p>=EndP;
until p>l;
end;
end.

View File

@ -15,8 +15,10 @@
{$IFDEF FPC}
{$DEFINE UsePChar}
{$DEFINE HasInt64}
{$DEFINE HasStreams}
{$DEFINE UTF8_RTL}
{$DEFINE HasStdErr}
{$DEFINE HasPas2jsFiler}
{$ENDIF}

View File

@ -25,9 +25,17 @@ unit Pas2jsFileCache;
interface
uses
Classes, SysUtils, AVL_Tree,
PScanner, PasResolver, FPPJsSrcMap,
Pas2jsLogger, Pas2jsFileUtils, Pas2JsFiler;
{$IFDEF Pas2js}
{$IFDEF NodeJS}
NodeJSFS,
{$ENDIF}
{$ENDIF}
Classes, SysUtils,
PScanner, PasUseAnalyzer, PasResolver, FPPJsSrcMap,
{$IFDEF HasPas2jsFiler}
Pas2JsFiler,
{$ENDIF}
Pas2jsLogger, Pas2jsFileUtils;
const // Messages
nIncludeSearch = 201; sIncludeSearch = 'Include file search: %s';
@ -43,7 +51,7 @@ type
type
TPas2jsFileAgeTime = longint;
TPas2jsFileAttr = longint;
TPas2jsFileSize = int64;
TPas2jsFileSize = TMaxPrecInt;
TPas2jsSearchFileCase = (
sfcDefault,
sfcCaseSensitive,
@ -115,7 +123,7 @@ type
TPas2jsCachedDirectories = class
private
FChangeStamp: TChangeStamp;
FDirectories: TAVLTree;// tree of TPas2jsCachedDirectory sorted by Directory
FDirectories: TPasAnalyzerKeySet;// set of TPas2jsCachedDirectory, key is Directory
FWorkingDirectory: string;
private
FOnReadDirectory: TReadDirectoryEvent;
@ -202,7 +210,7 @@ type
FIsEOF: boolean;
FLineNumber: integer;
FSource: string;
FSrcPos: PChar;
FSrcPos: integer;
public
constructor Create(const AFilename: string); override;
constructor Create(aFile: TPas2jsCachedFile); reintroduce;
@ -211,7 +219,7 @@ type
property LineNumber: integer read FLineNumber;
property CachedFile: TPas2jsCachedFile read FCachedFile;
property Source: string read FSource;
property SrcPos: PChar read FSrcPos;
property SrcPos: integer read FSrcPos;
end;
{ TPas2jsCachedFile }
@ -263,7 +271,7 @@ type
FBaseDirectory: string;
FDefaultOutputPath: string;
FDirectoryCache: TPas2jsCachedDirectories;
FFiles: TAVLTree; // tree of TPas2jsCachedFile sorted for Filename
FFiles: TPasAnalyzerKeySet; // set of TPas2jsCachedFile, key is Filename
FForeignUnitPaths: TStringList;
FForeignUnitPathsFromCmdLine: integer;
FIncludePaths: TStringList;
@ -279,7 +287,9 @@ type
FOnReadFile: TPas2jsReadFileEvent;
FOnWriteFile: TPas2jsWriteFileEvent;
FOptions: TP2jsFileCacheOptions;
{$IFDEF HasPas2jsFiler}
FPrecompileFormat: TPas2JSPrecompileFormat;
{$ENDIF}
FReadLineCounter: SizeInt;
FResetStamp: TChangeStamp;
FSrcMapBaseDir: string;
@ -329,7 +339,9 @@ type
procedure GetListing(const aDirectory: string; var Files: TStrings;
FullPaths: boolean = true);
procedure RaiseDuplicateFile(aFilename: string);
{$IFDEF HasStreams}
procedure SaveToFile(ms: TMemoryStream; Filename: string);
{$ENDIF}
function ExpandDirectory(const Filename, BaseDir: string): string;
public
property AllJSIntoMainJS: Boolean read GetAllJSIntoMainJS write SetAllJSIntoMainJS;
@ -348,7 +360,9 @@ type
property Namespaces: TStringList read FNamespaces;
property NamespacesFromCmdLine: integer read FNamespacesFromCmdLine;
property Options: TP2jsFileCacheOptions read FOptions write SetOptions default DefaultPas2jsFileCacheOptions;
{$IFDEF HasPas2jsFiler}
property PrecompileFormat: TPas2JSPrecompileFormat read FPrecompileFormat write FPrecompileFormat;
{$ENDIF}
property ReadLineCounter: SizeInt read FReadLineCounter write FReadLineCounter;
property ResetStamp: TChangeStamp read FResetStamp;
property SearchLikeFPC: boolean read GetSearchLikeFPC write SetSearchLikeFPC;
@ -362,21 +376,59 @@ type
property OnWriteFile: TPas2jsWriteFileEvent read FOnWriteFile write FOnWriteFile;
end;
{$IFDEF Pas2js}
function PtrStrToStr(StrAsPtr: Pointer): string;
function PtrFilenameToKeyName(FilenameAsPtr: Pointer): string;
function Pas2jsCachedFileToKeyName(Item: Pointer): string;
function Pas2jsCacheDirToKeyName(Item: Pointer): string;
{$ELSE}
function CompareFilenameWithCachedFile(Filename, CachedFile: Pointer): integer;
function CompareCachedFiles(File1, File2: Pointer): integer;
function ComparePas2jsCacheDirectories(Dir1, Dir2: Pointer): integer;
function CompareAnsiStringWithDirectoryCache(Path, DirCache: Pointer): integer;
function ComparePas2jsDirectoryEntries(Entry1, Entry2: Pointer): integer;
{$ENDIF}
function ComparePas2jsDirectoryEntries(Entry1, Entry2: {$IFDEF Pas2js}jsvalue{$ELSE}Pointer{$ENDIF}): integer;
function CompareFirstCaseInsThenSensitive(const s, h: string): integer;
{$IFDEF FPC_HAS_CPSTRING}
// UTF-8 helper functions
function ConvertTextToUTF8(const Src: string; var SrcEncoding: string): string;
function GuessEncoding(const Src: string): string;
function HasUTF8BOM(const s: string): boolean;
function RemoveUTFBOM(const s: string): string;
{$ENDIF}
implementation
{$IFDEF pas2js}
function PtrStrToStr(StrAsPtr: Pointer): string;
var
S: String absolute StrAsPtr;
begin
Result:=S;
end;
function PtrFilenameToKeyName(FilenameAsPtr: Pointer): string;
var
Filename: String absolute FilenameAsPtr;
begin
Result:=FilenameToKey(Filename);
end;
function Pas2jsCachedFileToKeyName(Item: Pointer): string;
var
aFile: TPas2jsCachedFile absolute Item;
begin
Result:=FilenameToKey(aFile.Filename);
end;
function Pas2jsCacheDirToKeyName(Item: Pointer): string;
var
Dir: TPas2jsCachedDirectory absolute Item;
begin
Result:=FilenameToKey(Dir.Path);
end;
{$ELSE}
function CompareFilenameWithCachedFile(Filename, CachedFile: Pointer): integer;
var
Cache: TPas2jsCachedFile absolute CachedFile;
@ -406,8 +458,9 @@ var
begin
Result:=CompareFilenames(AnsiString(Path),Directory.Path);
end;
{$ENDIF}
function ComparePas2jsDirectoryEntries(Entry1, Entry2: Pointer): integer;
function ComparePas2jsDirectoryEntries(Entry1, Entry2: {$IFDEF Pas2js}jsvalue{$ELSE}Pointer{$ENDIF}): integer;
var
E1: TPas2jsCachedDirectoryEntry absolute Entry1;
E2: TPas2jsCachedDirectoryEntry absolute Entry2;
@ -422,6 +475,7 @@ begin
Result:=CompareStr(s,h);
end;
{$IFDEF FPC_HAS_CPSTRING}
function ConvertTextToUTF8(const Src: string; var SrcEncoding: string): string;
var
p: PChar;
@ -512,6 +566,7 @@ begin
if not HasUTF8BOM(Result) then exit;
Delete(Result,1,3);
end;
{$ENDIF}
{ TPas2jsCachedDirectory }
@ -548,12 +603,18 @@ begin
end;
procedure TPas2jsCachedDirectory.DoReadDir;
{$IFDEF Pas2js}
{$ELSE}
var
Info: TUnicodeSearchRec;
{$ENDIF}
begin
if Assigned(Pool.OnReadDirectory) then
if Pool.OnReadDirectory(Self) then exit;
{$IFDEF Pas2js}
raise Exception.Create('TPas2jsCachedDirectory.DoReadDir TODO');
{$ELSE}
// Note: do not add a 'if not DirectoryExists then exit'.
// This will not work on automounted directories. You must use FindFirst.
if FindFirst(UnicodeString(Path+AllFilesMask),faAnyFile,Info)=0 then
@ -568,6 +629,7 @@ begin
until FindNext(Info)<>0;
end;
FindClose(Info);
{$ENDIF}
end;
constructor TPas2jsCachedDirectory.Create(aPath: string;
@ -596,7 +658,7 @@ var
i: Integer;
begin
for i:=0 to FEntries.Count-1 do
TObject(FEntries[i]).Free;
TObject(FEntries[i]).{$IFDEF Pas2js}Destroy{$ELSE}Free{$ENDIF};
FEntries.Clear;
FSorted:=true;
end;
@ -881,7 +943,12 @@ end;
constructor TPas2jsCachedDirectories.Create;
begin
IncreaseChangeStamp(FChangeStamp);
FDirectories:=TAVLTree.Create(@ComparePas2jsCacheDirectories);
FDirectories:=TPasAnalyzerKeySet.Create(
{$IFDEF pas2js}
@Pas2jsCacheDirToKeyName,@PtrFilenameToKeyName
{$ELSE}
@ComparePas2jsCacheDirectories,@CompareAnsiStringWithDirectoryCache
{$ENDIF});
end;
destructor TPas2jsCachedDirectories.Destroy;
@ -898,17 +965,21 @@ end;
procedure TPas2jsCachedDirectories.Clear;
var
Node: TAVLTreeNode;
Dir: TPas2jsCachedDirectory;
List: TFPList;
i: Integer;
begin
Node:=FDirectories.FindLowest;
while Node<>nil do begin
Dir:=TPas2jsCachedDirectory(Node.Data);
if Dir.FRefCount<>1 then
raise Exception.Create('TPas2jsCachedDirectories.Clear [20180126090807] "'+Dir.Path+'" '+IntToStr(Dir.FRefCount));
Dir.Release;
Node.Data:=nil;
Node:=FDirectories.FindSuccessor(Node);
List:=FDirectories.GetList;
try
for i:=0 to List.Count-1 do
begin
Dir:=TPas2jsCachedDirectory(List[i]);
if Dir.FRefCount<>1 then
raise Exception.Create('TPas2jsCachedDirectories.Clear [20180126090807] "'+Dir.Path+'" '+IntToStr(Dir.FRefCount));
Dir.Release;
end;
finally
List.Free;
end;
FDirectories.Clear;
end;
@ -1032,16 +1103,14 @@ function TPas2jsCachedDirectories.GetDirectory(const Directory: string;
CreateIfNotExists: boolean; DoReference: boolean): TPas2jsCachedDirectory;
var
Dir: String;
Node: TAVLTreeNode;
begin
Dir:=ResolveDots(Directory);
if not FilenameIsAbsolute(Dir) then
Dir:=WorkingDirectory+Dir;
Dir:=IncludeTrailingPathDelimiter(Dir);
Node:=FDirectories.FindKey(Pointer(Dir),@CompareAnsiStringWithDirectoryCache);
if Node<>nil then
Result:=TPas2jsCachedDirectory(FDirectories.FindKey(Pointer(Dir)));
if Result<>nil then
begin
Result:=TPas2jsCachedDirectory(Node.Data);
if DoReference then
Result.Reference;
Result.Update;
@ -1071,7 +1140,7 @@ begin
inherited Create(aFile.Filename);
FCachedFile:=aFile;
FSource:=aFile.Source;
FSrcPos:=PChar(FSource);
FSrcPos:=1;
FIsEOF:=FSource='';
end;
@ -1082,16 +1151,15 @@ end;
function TPas2jsFileLineReader.ReadLine: string;
var
p: PChar;
S: string;
p, SrcLen: integer;
procedure GetLine;
var
l: SizeInt;
begin
l:=p-FSrcPos;
SetLength(Result,l);
if l>0 then
Move(FSrcPos^,Result[1],l);
Result:=copy(S,FSrcPos,l);
FSrcPos:=p;
inc(FLineNumber);
if (CachedFile<>nil) and (CachedFile.Cache<>nil) then
@ -1099,35 +1167,29 @@ var
//writeln('GetLine "',Result,'"');
end;
var
c: Char;
begin
if FIsEOF then exit('');
S:=Source;
SrcLen:=length(S);
p:=FSrcPos;
repeat
c:=p^;
case c of
#0:
if p-PChar(FSource)=length(FSource) then
begin
FIsEOF:=true;
GetLine;
exit;
end;
while p<=SrcLen do
case S[p] of
#10,#13:
begin
GetLine;
inc(p);
if (p^ in [#10,#13]) and (p^<>c) then inc(p);
if (p^=#0) and (p-PChar(FSource)=length(FSource)) then
if (p<=SrcLen) and (S[p] in [#10,#13]) and (S[p]<>S[p-1]) then
inc(p);
if p>SrcLen then
FIsEOF:=true;
FSrcPos:=p;
exit;
end;
else
inc(p);
end;
inc(p);
until false;
Result:='';
FIsEOF:=true;
GetLine;
end;
{ TPas2jsCachedFile }
@ -1817,7 +1879,12 @@ begin
FForeignUnitPaths:=TStringList.Create;
FNamespaces:=TStringList.Create;
FUnitPaths:=TStringList.Create;
FFiles:=TAVLTree.Create(@CompareCachedFiles);
FFiles:=TPasAnalyzerKeySet.Create(
{$IFDEF Pas2js}
@Pas2jsCachedFileToKeyName,@PtrFilenameToKeyName
{$ELSE}
@CompareCachedFiles,@CompareFilenameWithCachedFile
{$ENDIF});
FDirectoryCache:=TPas2jsCachedDirectories.Create;
RegisterMessages;
end;
@ -1825,7 +1892,7 @@ end;
destructor TPas2jsFilesCache.Destroy;
begin
FLog:=nil;
FFiles.FreeAndClear;
FFiles.FreeItems;
FreeAndNil(FDirectoryCache);
FreeAndNil(FFiles);
FreeAndNil(FInsertFilenames);
@ -1840,7 +1907,7 @@ procedure TPas2jsFilesCache.Reset;
begin
IncreaseChangeStamp(FResetStamp);
FDirectoryCache.Invalidate;
// FFiles: TAVLTree; keep data, files are checked against LoadedFileAge
// FFiles: keep data, files are checked against LoadedFileAge
FOptions:=DefaultPas2jsFileCacheOptions;
FMainJSFile:='';
FMainJSFileResolved:='';
@ -1859,7 +1926,9 @@ begin
FStates:=FStates-[cfsMainJSFileResolved];
FNamespaces.Clear;
FNamespacesFromCmdLine:=0;
{$IFDEF HasPas2jsFiler}
FPrecompileFormat:=nil;
{$ENDIF}
FSrcMapBaseDir:='';
// FOnReadFile: TPas2jsReadFileEvent; keep
// FOnWriteFile: TPas2jsWriteFileEvent; keep
@ -1958,30 +2027,21 @@ begin
end;
function TPas2jsFilesCache.FindFile(Filename: string): TPas2jsCachedFile;
var
Node: TAVLTreeNode;
begin
Filename:=NormalizeFilename(Filename,true);
Node:=FFiles.FindKey(Pointer(Filename),@CompareFilenameWithCachedFile);
if Node=nil then
exit(nil);
Result:=TPas2jsCachedFile(Node.Data);
Result:=TPas2jsCachedFile(FFiles.FindKey(Pointer(Filename)));
end;
function TPas2jsFilesCache.LoadFile(Filename: string; Binary: boolean
): TPas2jsCachedFile;
var
Node: TAVLTreeNode;
begin
Filename:=NormalizeFilename(Filename,true);
Node:=FFiles.FindKey(Pointer(Filename),@CompareFilenameWithCachedFile);
if Node=nil then
Result:=TPas2jsCachedFile(FFiles.FindKey(Pointer(Filename)));
if Result=nil then
begin
// new file
Result:=TPas2jsCachedFile.Create(Self,Filename);
FFiles.Add(Result);
end else begin
Result:=TPas2jsCachedFile(Node.Data);
end;
Result.Load(true,Binary);
end;
@ -2086,6 +2146,7 @@ begin
end;
end;
{$IFDEF HasStreams}
procedure TPas2jsFilesCache.SaveToFile(ms: TMemoryStream; Filename: string);
var
s: string;
@ -2122,6 +2183,7 @@ begin
end;
end;
end;
{$ENDIF}
function TPas2jsFilesCache.ExpandDirectory(const Filename, BaseDir: string
): string;

View File

@ -60,7 +60,11 @@ unit Pas2JsFiler;
interface
uses
Classes, Types, SysUtils, contnrs, zstream, AVL_Tree,
Classes, Types, SysUtils, contnrs,
{$ifdef pas2js}
{$else}
zstream, AVL_Tree,
{$endif}
fpjson, jsonparser, jsonscanner,
PasTree, PScanner, PParser, PasResolveEval, PasResolver,
Pas2jsFileUtils, FPPas2Js;

View File

@ -48,6 +48,9 @@ function GetForcedPathDelims(Const FileName: string): String;
function ExtractFilenameOnly(const aFilename: string): string;
function GetCurrentDirPJ: String;
function CompareFilenames(const File1, File2: string): integer;
{$IFDEF Pas2js}
function FilenameToKey(const Filename: string): string;
{$ENDIF}
function GetPhysicalFilename(const Filename: string;
ExceptionOnError: boolean): string;
@ -594,6 +597,26 @@ begin
{$ENDIF}
end;
{$IFDEF Pas2js}
function FilenameToKey(const Filename: string): string;
begin
{$IFDEF Pas2js}
Result:=Filename;
// ToDo lowercase on windows, normalize on darwin
{$ELSE}
{$IFDEF Windows}
Result:=AnsiLowerCase(Filename);
{$ELSE}
{$IFDEF Darwin}
todo
{$ELSE}
Result:=Filename;
{$ENDIF}
{$ENDIF}
{$ENDIF}
end;
{$ENDIF}
function MatchGlobbing(Mask, Name: string): boolean;
// match * and ?
{$IFDEF Pas2js}

View File

@ -9,7 +9,7 @@ uses
fpjson,
PasTree, PScanner, PParser, PasResolveEval, PasResolver, PasUseAnalyzer,
FPPas2Js,
Pas2jsFileUtils, Pas2jsLogger, Pas2jsPParser;
Pas2jsFileUtils, Pas2jsLogger, Pas2jsPParser, Pas2jsFileCache;
begin
// Your code here