Переглянути джерело

pastojs: adaptions for pas2js

git-svn-id: trunk@40049 -
Mattias Gaertner 6 роки тому
батько
коміт
a2c16728cc

+ 19 - 22
packages/pastojs/src/fppjssrcmap.pp

@@ -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.

+ 2 - 0
packages/pastojs/src/pas2js_defines.inc

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

+ 124 - 62
packages/pastojs/src/pas2jsfilecache.pp

@@ -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;

+ 5 - 1
packages/pastojs/src/pas2jsfiler.pp

@@ -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;

+ 23 - 0
packages/pastojs/src/pas2jsfileutils.pp

@@ -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}

+ 1 - 1
utils/pas2js/nodepas2js.pp

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