pastojs: formatting

git-svn-id: trunk@37983 -
This commit is contained in:
Mattias Gaertner 2018-01-17 10:57:49 +00:00
parent 3e82c18a82
commit a2164135f1
7 changed files with 378 additions and 190 deletions

View File

@ -592,7 +592,8 @@ begin
raise EPas2jsMacro.Create('macro cycle detected: "'+s+'"'); raise EPas2jsMacro.Create('macro cycle detected: "'+s+'"');
p:=1; p:=1;
while p<length(s) do begin while p<length(s) do begin
if (s[p]='$') and (s[p+1] in ['_','a'..'z','A'..'Z']) then begin if (s[p]='$') and (s[p+1] in ['_','a'..'z','A'..'Z']) then
begin
StartP:=p; StartP:=p;
inc(p,2); inc(p,2);
while (p<=length(s)) and (s[p] in ['_','a'..'z','A'..'Z','0'..'9']) do while (p<=length(s)) and (s[p] in ['_','a'..'z','A'..'Z','0'..'9']) do
@ -602,7 +603,8 @@ begin
if Macro=nil then if Macro=nil then
raise EPas2jsMacro.Create('macro not found "'+MacroName+'" in "'+s+'"'); raise EPas2jsMacro.Create('macro not found "'+MacroName+'" in "'+s+'"');
NewValue:=''; NewValue:='';
if Macro.CanHaveParams and (p<=length(s)) and (s[p]='(') then begin if Macro.CanHaveParams and (p<=length(s)) and (s[p]='(') then
begin
// read NewValue // read NewValue
inc(p); inc(p);
ParamStartP:=p; ParamStartP:=p;
@ -613,7 +615,8 @@ begin
case s[p] of case s[p] of
'(': inc(BracketLvl); '(': inc(BracketLvl);
')': ')':
if BracketLvl=1 then begin if BracketLvl=1 then
begin
NewValue:=copy(s,ParamStartP,p-ParamStartP); NewValue:=copy(s,ParamStartP,p-ParamStartP);
break; break;
end else begin end else begin
@ -623,7 +626,8 @@ begin
until false; until false;
end else if (p<=length(s)) and (s[p]='$') then end else if (p<=length(s)) and (s[p]='$') then
inc(p); inc(p);
if Assigned(Macro.OnSubstitute) then begin if Assigned(Macro.OnSubstitute) then
begin
if not Macro.OnSubstitute(Sender,NewValue,Lvl+1) then if not Macro.OnSubstitute(Sender,NewValue,Lvl+1) then
raise EPas2jsMacro.Create('macro "'+MacroName+'" failed in "'+s+'"'); raise EPas2jsMacro.Create('macro "'+MacroName+'" failed in "'+s+'"');
end else end else
@ -670,7 +674,8 @@ begin
FreeAndNil(FUsedBy[ub]); FreeAndNil(FUsedBy[ub]);
FreeAndNil(FJSModule); FreeAndNil(FJSModule);
FreeAndNil(FConverter); FreeAndNil(FConverter);
if FPasModule<>nil then begin if FPasModule<>nil then
begin
FPasModule.Release; FPasModule.Release;
FPasModule:=nil; FPasModule:=nil;
end; end;
@ -731,7 +736,8 @@ begin
Parser.Log:=Log; Parser.Log:=Log;
PascalResolver.P2JParser:=Parser; PascalResolver.P2JParser:=Parser;
if not IsMainFile then begin if not IsMainFile then
begin
aUnitName:=ExtractFilenameOnly(PasFilename); aUnitName:=ExtractFilenameOnly(PasFilename);
if CompareText(aUnitName,'system')=0 then if CompareText(aUnitName,'system')=0 then
Parser.ImplicitUses.Clear; Parser.ImplicitUses.Clear;
@ -746,9 +752,11 @@ begin
if (Element.ClassType=TPasUnitModule) or (Element.ClassType=TPasModule) then if (Element.ClassType=TPasUnitModule) or (Element.ClassType=TPasModule) then
begin begin
SrcName:=Element.Name; SrcName:=Element.Name;
if IsMainFile then begin if IsMainFile then
begin
// main source is an unit // main source is an unit
if PasUnitName='' then begin if PasUnitName='' then
begin
{$IFDEF VerboseSetPasUnitName} {$IFDEF VerboseSetPasUnitName}
writeln('TPas2jsCompilerFile.OnPasTreeCheckSrcName ',PasFilename,' Name=',Element.Name,' IsMainFile=',IsMainFile); writeln('TPas2jsCompilerFile.OnPasTreeCheckSrcName ',PasFilename,' Name=',Element.Name,' IsMainFile=',IsMainFile);
{$ENDIF} {$ENDIF}
@ -867,7 +875,8 @@ var
aFilename: String; aFilename: String;
aRow, aColumn: integer; aRow, aColumn: integer;
begin begin
if E.PasElement<>nil then begin if E.PasElement<>nil then
begin
aFilename:=E.PasElement.SourceFilename; aFilename:=E.PasElement.SourceFilename;
PascalResolver.UnmangleSourceLineNumber(E.PasElement.SourceLinenumber,aRow,aColumn); PascalResolver.UnmangleSourceLineNumber(E.PasElement.SourceLinenumber,aRow,aColumn);
end else begin end else begin
@ -884,7 +893,8 @@ var
aFilename: String; aFilename: String;
aRow, aColumn: integer; aRow, aColumn: integer;
begin begin
if E.PasElement<>nil then begin if E.PasElement<>nil then
begin
aFilename:=E.PasElement.SourceFilename; aFilename:=E.PasElement.SourceFilename;
PascalResolver.UnmangleSourceLineNumber(E.PasElement.SourceLinenumber,aRow,aColumn); PascalResolver.UnmangleSourceLineNumber(E.PasElement.SourceLinenumber,aRow,aColumn);
Log.Log(E.MsgType,E.Message,E.MsgNumber,aFilename,aRow,aColumn); Log.Log(E.MsgType,E.Message,E.MsgNumber,aFilename,aRow,aColumn);
@ -903,7 +913,8 @@ end;
procedure TPas2jsCompilerFile.HandleException(E: Exception); procedure TPas2jsCompilerFile.HandleException(E: Exception);
begin begin
if E is EScannerError then begin if E is EScannerError then
begin
Log.Log(Scanner.LastMsgType,Scanner.LastMsg,Scanner.LastMsgNumber, Log.Log(Scanner.LastMsgType,Scanner.LastMsg,Scanner.LastMsgNumber,
Scanner.CurFilename,Scanner.CurRow,Scanner.CurColumn); Scanner.CurFilename,Scanner.CurRow,Scanner.CurColumn);
Compiler.Terminate(ExitCodeSyntaxError); Compiler.Terminate(ExitCodeSyntaxError);
@ -923,7 +934,8 @@ var
Line, Col: integer; Line, Col: integer;
Filename: String; Filename: String;
begin begin
if (El<>nil) then begin if (El<>nil) then
begin
Filename:=El.SourceFilename; Filename:=El.SourceFilename;
TPasResolver.UnmangleSourceLineNumber(El.SourceLinenumber,Line,Col); TPasResolver.UnmangleSourceLineNumber(El.SourceLinenumber,Line,Col);
end else begin end else begin
@ -942,7 +954,8 @@ end;
procedure TPas2jsCompilerFile.ParserFinished; procedure TPas2jsCompilerFile.ParserFinished;
begin begin
try try
if ShowDebug then begin if ShowDebug then
begin
Log.LogRaw('Pas-Module:'); Log.LogRaw('Pas-Module:');
Log.LogRaw(PasModule.GetDeclaration(true)); Log.LogRaw(PasModule.GetDeclaration(true));
end; end;
@ -1053,15 +1066,18 @@ begin
Result:=nil; Result:=nil;
aModule:=GetCurPasModule; aModule:=GetCurPasModule;
if aModule=nil then exit; if aModule=nil then exit;
if aModule.ClassType=TPasModule then begin if aModule.ClassType=TPasModule then
begin
IntfSection:=TPasModule(aModule).InterfaceSection; IntfSection:=TPasModule(aModule).InterfaceSection;
if IntfSection<>nil then if IntfSection<>nil then
Result:=IntfSection.UsesClause; Result:=IntfSection.UsesClause;
end else if aModule.ClassType=TPasProgram then begin end else if aModule.ClassType=TPasProgram then
begin
PrgSection:=TPasProgram(aModule).ProgramSection; PrgSection:=TPasProgram(aModule).ProgramSection;
if PrgSection<>nil then if PrgSection<>nil then
Result:=PrgSection.UsesClause; Result:=PrgSection.UsesClause;
end else if aModule.ClassType=TPasLibrary then begin end else if aModule.ClassType=TPasLibrary then
begin
LibSection:=TPasLibrary(aModule).LibrarySection; LibSection:=TPasLibrary(aModule).LibrarySection;
if LibSection<>nil then if LibSection<>nil then
Result:=LibSection.UsesClause; Result:=LibSection.UsesClause;
@ -1112,7 +1128,8 @@ begin
if (aModule=nil) or (aModule.CustomData=nil) then exit; if (aModule=nil) or (aModule.CustomData=nil) then exit;
if aModule.CustomData is TPas2jsCompilerFile then if aModule.CustomData is TPas2jsCompilerFile then
Result:=TPas2jsCompilerFile(aModule.CustomData) Result:=TPas2jsCompilerFile(aModule.CustomData)
else if aModule.CustomData is TPasModuleScope then begin else if aModule.CustomData is TPasModuleScope then
begin
Scope:=TPasModuleScope(aModule.CustomData); Scope:=TPasModuleScope(aModule.CustomData);
Resolver:=NoNil(Scope.Owner) as TPas2jsCompilerResolver; Resolver:=NoNil(Scope.Owner) as TPas2jsCompilerResolver;
Result:=Resolver.Owner as TPas2jsCompilerFile; Result:=Resolver.Owner as TPas2jsCompilerFile;
@ -1126,7 +1143,8 @@ var
i: Integer; i: Integer;
begin begin
Result:=nil; Result:=nil;
if CompareText(ExtractFilenameOnly(PasFilename),UseUnitname)=0 then begin if CompareText(ExtractFilenameOnly(PasFilename),UseUnitname)=0 then
begin
// duplicate identifier or unit cycle // duplicate identifier or unit cycle
Parser.RaiseParserError(nUnitCycle,[UseUnitname]); Parser.RaiseParserError(nUnitCycle,[UseUnitname]);
end; end;
@ -1139,11 +1157,13 @@ begin
else else
RaiseInternalError(20170504161408,'internal error TPas2jsCompilerFile.FindModule PasTree.LastElement='+GetObjName(LastEl)+' '+GetObjName(LastEl.Parent)); RaiseInternalError(20170504161408,'internal error TPas2jsCompilerFile.FindModule PasTree.LastElement='+GetObjName(LastEl)+' '+GetObjName(LastEl.Parent));
if (Pos('.',UseUnitname)<1) then begin if (Pos('.',UseUnitname)<1) then
begin
// generic unit -> search with namespaces // generic unit -> search with namespaces
// first the default program namespace // first the default program namespace
aNameSpace:=Compiler.GetDefaultNamespace; aNameSpace:=Compiler.GetDefaultNamespace;
if aNameSpace<>'' then begin if aNameSpace<>'' then
begin
Result:=FindUnit(aNameSpace+'.'+UseUnitname); Result:=FindUnit(aNameSpace+'.'+UseUnitname);
if Result<>nil then exit; if Result<>nil then exit;
end; end;
@ -1172,14 +1192,16 @@ function TPas2jsCompilerFile.FindUnit(const UseUnitname: String): TPasModule;
begin begin
for i:=0 to aFile.UsedByCount[ubMainSection]-1 do begin for i:=0 to aFile.UsedByCount[ubMainSection]-1 do begin
aParent:=aFile.UsedBy[ubMainSection,i]; aParent:=aFile.UsedBy[ubMainSection,i];
if aParent=SearchFor then begin if aParent=SearchFor then
begin
// unit cycle found // unit cycle found
Cycle:=TFPList.Create; Cycle:=TFPList.Create;
Cycle.Add(aParent); Cycle.Add(aParent);
Cycle.Add(aFile); Cycle.Add(aFile);
exit(true); exit(true);
end; end;
if FindCycle(aParent,SearchFor,Cycle) then begin if FindCycle(aParent,SearchFor,Cycle) then
begin
Cycle.Add(aFile); Cycle.Add(aFile);
exit(true); exit(true);
end; end;
@ -1196,7 +1218,8 @@ var
Cycle: TFPList; Cycle: TFPList;
CyclePath: String; CyclePath: String;
begin begin
if Parser.CurModule.ImplementationSection=nil then begin if Parser.CurModule.ImplementationSection=nil then
begin
// main uses section (e.g. interface or program, not implementation) // main uses section (e.g. interface or program, not implementation)
// -> check for cycles // -> check for cycles
@ -1204,7 +1227,8 @@ var
Cycle:=nil; Cycle:=nil;
try try
if FindCycle(aFile,aFile,Cycle) then begin if FindCycle(aFile,aFile,Cycle) then
begin
CyclePath:=''; CyclePath:='';
for i:=0 to Cycle.Count-1 do begin for i:=0 to Cycle.Count-1 do begin
if i>0 then CyclePath+=','; if i>0 then CyclePath+=',';
@ -1230,7 +1254,8 @@ begin
// first try registered units // first try registered units
aFile:=Compiler.FindUsedUnit(UseUnitname); aFile:=Compiler.FindUsedUnit(UseUnitname);
if aFile<>nil then begin if aFile<>nil then
begin
// known unit // known unit
if (aFile.PasUnitName<>'') and (CompareText(aFile.PasUnitName,UseUnitname)<>0) then if (aFile.PasUnitName<>'') and (CompareText(aFile.PasUnitName,UseUnitname)<>0) then
begin begin
@ -1246,7 +1271,8 @@ begin
// search Pascal file // search Pascal file
UsePasFilename:=FileResolver.FindUnitFileName(UseUnitname,InFilename,UseIsForeign); UsePasFilename:=FileResolver.FindUnitFileName(UseUnitname,InFilename,UseIsForeign);
if UsePasFilename='' then begin if UsePasFilename='' then
begin
// can't find unit // can't find unit
exit; exit;
end; end;
@ -1260,7 +1286,8 @@ begin
// load Pascal file // load Pascal file
Compiler.LoadPasFile(UsePasFilename,UseUnitname,aFile); Compiler.LoadPasFile(UsePasFilename,UseUnitname,aFile);
if aFile=Self then begin if aFile=Self then
begin
// unit uses itself -> cycle // unit uses itself -> cycle
Parser.RaiseParserError(nUnitCycle,[UseUnitname]); Parser.RaiseParserError(nUnitCycle,[UseUnitname]);
end; end;
@ -1344,7 +1371,8 @@ var
begin begin
// check defines // check defines
i:=FDefines.IndexOf(aName); i:=FDefines.IndexOf(aName);
if i>=0 then begin if i>=0 then
begin
M:=TMacroDef(FDefines.Objects[i]); M:=TMacroDef(FDefines.Objects[i]);
if M=nil then if M=nil then
Value:=CondDirectiveBool[true] Value:=CondDirectiveBool[true]
@ -1355,7 +1383,8 @@ begin
// check modeswitches // check modeswitches
ms:=StrToModeSwitch(aName); ms:=StrToModeSwitch(aName);
if (ms<>msNone) and (ms in p2jsMode_SwitchSets[Mode]) then begin if (ms<>msNone) and (ms in p2jsMode_SwitchSets[Mode]) then
begin
Value:=CondDirectiveBool[true]; Value:=CondDirectiveBool[true];
exit(true); exit(true);
end; end;
@ -1405,7 +1434,8 @@ begin
FreeAndNil(Checked); FreeAndNil(Checked);
// write success message // write success message
if ExitCode=0 then begin if ExitCode=0 then
begin
Seconds:=(Now-StartTime)*86400; Seconds:=(Now-StartTime)*86400;
Log.LogMsgIgnoreFilter(nLinesInFilesCompiled, Log.LogMsgIgnoreFilter(nLinesInFilesCompiled,
[IntToStr(FileCache.ReadLineCounter),IntToStr(SrcFileCount), [IntToStr(FileCache.ReadLineCounter),IntToStr(SrcFileCount),
@ -1443,7 +1473,8 @@ function TPas2jsCompiler.MarkNeedBuilding(aFile: TPas2jsCompilerFile;
UsedFile:=TPas2jsCompilerFile.GetFile(aModule); UsedFile:=TPas2jsCompilerFile.GetFile(aModule);
if UsedFile=nil then if UsedFile=nil then
RaiseInternalError(20171214121631,aModule.Name); RaiseInternalError(20171214121631,aModule.Name);
if MarkNeedBuilding(UsedFile,Checked,SrcFileCount) then begin if MarkNeedBuilding(UsedFile,Checked,SrcFileCount) then
begin
if not aFile.NeedBuild then if not aFile.NeedBuild then
Mark(nUnitNeedsCompileDueToUsedUnit, Mark(nUnitNeedsCompileDueToUsedUnit,
[aFile.GetModuleName,UsedFile.GetModuleName]); [aFile.GetModuleName,UsedFile.GetModuleName]);
@ -1466,7 +1497,8 @@ begin
CheckUsesClause(aFile.GetPasMainUsesClause); CheckUsesClause(aFile.GetPasMainUsesClause);
CheckUsesClause(aFile.GetPasImplUsesClause); CheckUsesClause(aFile.GetPasImplUsesClause);
if (not aFile.NeedBuild) and (not aFile.IsForeign) then begin if (not aFile.NeedBuild) and (not aFile.IsForeign) then
begin
// this unit can be compiled // this unit can be compiled
if aFile.IsMainFile then if aFile.IsMainFile then
Mark(nUnitNeedsCompileDueToOption,[aFile.GetModuleName,'<main source file>']) Mark(nUnitNeedsCompileDueToOption,[aFile.GetModuleName,'<main source file>'])
@ -1484,9 +1516,11 @@ begin
end; end;
end; end;
if aFile.NeedBuild then begin if aFile.NeedBuild then
begin
// unit needs compile // unit needs compile
if aFile.IsForeign then begin if aFile.IsForeign then
begin
// ... but is forbidden to compile // ... but is forbidden to compile
Log.LogMsg(nOptionForbidsCompile,[aFile.GetModuleName]); Log.LogMsg(nOptionForbidsCompile,[aFile.GetModuleName]);
Terminate(ExitCodeWriteError); Terminate(ExitCodeWriteError);
@ -1555,17 +1589,20 @@ begin
for i:=0 to SrcMap.SourceCount-1 do begin for i:=0 to SrcMap.SourceCount-1 do begin
LocalFilename:=SrcMap.SourceFiles[i]; LocalFilename:=SrcMap.SourceFiles[i];
if LocalFilename='' then continue; if LocalFilename='' then continue;
if SrcMapInclude then begin if SrcMapInclude then
begin
// include source in SrcMap // include source in SrcMap
aFile:=FileCache.LoadTextFile(LocalFilename); aFile:=FileCache.LoadTextFile(LocalFilename);
SrcMap.SourceContents[i]:=aFile.Source; SrcMap.SourceContents[i]:=aFile.Source;
end; end;
// translate local file name // translate local file name
if BaseDir<>'' then begin if BaseDir<>'' then
if not TryCreateRelativePath(LocalFilename,BaseDir,true,MapFilename) begin
then begin if not TryCreateRelativePath(LocalFilename,BaseDir,true,MapFilename) then
begin
// e.g. file is on another partition // e.g. file is on another partition
if not SrcMapInclude then begin if not SrcMapInclude then
begin
Log.Log(mtError, Log.Log(mtError,
SafeFormat(sUnableToTranslatePathToDir,[LocalFilename,BaseDir]), SafeFormat(sUnableToTranslatePathToDir,[LocalFilename,BaseDir]),
nUnableToTranslatePathToDir); nUnableToTranslatePathToDir);
@ -1620,7 +1657,8 @@ var
begin begin
aFileWriter:=TPas2JSMapper.Create(4096); aFileWriter:=TPas2JSMapper.Create(4096);
FreeWriter:=true; FreeWriter:=true;
if SrcMapEnable then begin if SrcMapEnable then
begin
SrcMap:=TPas2JSSrcMap.Create(ExtractFilename(aFilename)); SrcMap:=TPas2JSSrcMap.Create(ExtractFilename(aFilename));
aFileWriter.SrcMap:=SrcMap; aFileWriter.SrcMap:=SrcMap;
SrcMap.Release;// release the refcount from the Create SrcMap.Release;// release the refcount from the Create
@ -1642,7 +1680,8 @@ begin
Checked.Add(aFile); Checked.Add(aFile);
FreeWriter:=false; FreeWriter:=false;
if FileCache.AllJSIntoMainJS and (CombinedFileWriter=nil) then begin if FileCache.AllJSIntoMainJS and (CombinedFileWriter=nil) then
begin
// create CombinedFileWriter // create CombinedFileWriter
DestFilename:=FileCache.GetResolvedMainJSFile; DestFilename:=FileCache.GetResolvedMainJSFile;
CreateFileWriter(DestFilename); CreateFileWriter(DestFilename);
@ -1659,7 +1698,8 @@ begin
aJSWriter:=nil; aJSWriter:=nil;
aFileWriter:=CombinedFileWriter; aFileWriter:=CombinedFileWriter;
try try
if aFileWriter=nil then begin if aFileWriter=nil then
begin
// create writer for this file // create writer for this file
CreateFileWriter(DestFilename); CreateFileWriter(DestFilename);
if aFile.IsMainFile and not FileCache.AllJSIntoMainJS then if aFile.IsMainFile and not FileCache.AllJSIntoMainJS then
@ -1679,10 +1719,12 @@ begin
if DoWriteJSFile(aFile.JSFilename,aFileWriter) then if DoWriteJSFile(aFile.JSFilename,aFileWriter) then
exit;// descendant has written -> finished exit;// descendant has written -> finished
if (aFile.JSFilename='') and (FileCache.MainJSFile='.') then begin if (aFile.JSFilename='') and (FileCache.MainJSFile='.') then
begin
// write to stdout // write to stdout
Log.LogRaw(aFileWriter.AsAnsistring); Log.LogRaw(aFileWriter.AsAnsistring);
end else if FreeWriter then begin end else if FreeWriter then
begin
// write to file // write to file
//writeln('TPas2jsCompiler.WriteJSFiles ',aFile.PasFilename,' ',aFile.JSFilename); //writeln('TPas2jsCompiler.WriteJSFiles ',aFile.PasFilename,' ',aFile.JSFilename);
@ -1691,11 +1733,13 @@ begin
// check output directory // check output directory
DestDir:=ChompPathDelim(ExtractFilePath(DestFilename)); DestDir:=ChompPathDelim(ExtractFilePath(DestFilename));
if (DestDir<>'') and not DirectoryExists(DestDir) then begin if (DestDir<>'') and not DirectoryExists(DestDir) then
begin
Log.LogMsg(nOutputDirectoryNotFound,[FileCache.FormatPath(DestDir)]); Log.LogMsg(nOutputDirectoryNotFound,[FileCache.FormatPath(DestDir)]);
Terminate(ExitCodeFileNotFound); Terminate(ExitCodeFileNotFound);
end; end;
if DirectoryExists(DestFilename) then begin if DirectoryExists(DestFilename) then
begin
Log.LogMsg(nFileIsFolder,[FileCache.FormatPath(DestFilename)]); Log.LogMsg(nFileIsFolder,[FileCache.FormatPath(DestFilename)]);
Terminate(ExitCodeWriteError); Terminate(ExitCodeWriteError);
end; end;
@ -1707,14 +1751,16 @@ begin
fs:=TFileStream.Create(DestFilename,fmCreate); fs:=TFileStream.Create(DestFilename,fmCreate);
try try
// UTF8-BOM // UTF8-BOM
if (Log.Encoding='') or (Log.Encoding='utf8') then begin if (Log.Encoding='') or (Log.Encoding='utf8') then
begin
Src:=String(UTF8BOM); Src:=String(UTF8BOM);
fs.Write(Src[1],length(Src)); fs.Write(Src[1],length(Src));
end; end;
// JS source // JS source
fs.Write(aFileWriter.Buffer^,aFileWriter.BufferLength); fs.Write(aFileWriter.Buffer^,aFileWriter.BufferLength);
// source map comment // source map comment
if aFileWriter.SrcMap<>nil then begin if aFileWriter.SrcMap<>nil then
begin
Src:='//# sourceMappingURL='+ExtractFilename(MapFilename)+LineEnding; Src:='//# sourceMappingURL='+ExtractFilename(MapFilename)+LineEnding;
fs.Write(Src[1],length(Src)); fs.Write(Src[1],length(Src));
end; end;
@ -1730,7 +1776,8 @@ begin
end; end;
// write source map // write source map
if aFileWriter.SrcMap<>nil then begin if aFileWriter.SrcMap<>nil then
begin
Log.LogMsg(nWritingFile,[FileCache.FormatPath(MapFilename)],'',0,0, Log.LogMsg(nWritingFile,[FileCache.FormatPath(MapFilename)],'',0,0,
not (coShowLineNumbers in Options)); not (coShowLineNumbers in Options));
FinishSrcMap(aFileWriter.SrcMap); FinishSrcMap(aFileWriter.SrcMap);
@ -1755,7 +1802,8 @@ begin
end; end;
finally finally
if FreeWriter then begin if FreeWriter then
begin
if CombinedFileWriter=aFileWriter then if CombinedFileWriter=aFileWriter then
CombinedFileWriter:=nil; CombinedFileWriter:=nil;
aFileWriter.Free aFileWriter.Free
@ -1915,7 +1963,8 @@ begin
while (p^ in [' ',#9]) do inc(p); while (p^ in [' ',#9]) do inc(p);
if p^=#0 then continue; // empty line if p^=#0 then continue; // empty line
if p^='#' then begin if p^='#' then
begin
// cfg directive // cfg directive
inc(p); inc(p);
if p^ in [#0,#9,' ','-'] then continue; // comment if p^ in [#0,#9,' ','-'] then continue; // comment
@ -1924,9 +1973,11 @@ begin
'ifdef','ifndef': 'ifdef','ifndef':
begin begin
inc(IfLvl); inc(IfLvl);
if Skip=skipNone then begin if Skip=skipNone then
begin
aName:=GetWord; aName:=GetWord;
if IsDefined(aName)=(Directive='ifdef') then begin if IsDefined(aName)=(Directive='ifdef') then
begin
// execute block // execute block
if ShowDebug then if ShowDebug then
DebugCfgDirective('true -> execute'); DebugCfgDirective('true -> execute');
@ -1942,9 +1993,11 @@ begin
'if': 'if':
begin begin
inc(IfLvl); inc(IfLvl);
if Skip=skipNone then begin if Skip=skipNone then
begin
Expr:=copy(Line,p-PChar(Line)+1,length(Line)); Expr:=copy(Line,p-PChar(Line)+1,length(Line));
if ConditionEvaluator.Eval(Expr) then begin if ConditionEvaluator.Eval(Expr) then
begin
// execute block // execute block
if ShowDebug then if ShowDebug then
DebugCfgDirective('true -> execute'); DebugCfgDirective('true -> execute');
@ -1963,13 +2016,15 @@ begin
CfgSyntaxError('"'+Directive+'" without ifdef'); CfgSyntaxError('"'+Directive+'" without ifdef');
if (Skip=skipElse) and (IfLvl=SkipLvl) then if (Skip=skipElse) and (IfLvl=SkipLvl) then
CfgSyntaxError('"there was already an $else');; CfgSyntaxError('"there was already an $else');;
if (Skip=skipIf) and (IfLvl=SkipLvl) then begin if (Skip=skipIf) and (IfLvl=SkipLvl) then
begin
// if-block was skipped -> execute else block // if-block was skipped -> execute else block
if ShowDebug then if ShowDebug then
DebugCfgDirective('execute'); DebugCfgDirective('execute');
SkipLvl:=0; SkipLvl:=0;
Skip:=skipNone; Skip:=skipNone;
end else if Skip=skipNone then begin end else if Skip=skipNone then
begin
// if-block was executed -> skip else block // if-block was executed -> skip else block
if ShowDebug then if ShowDebug then
DebugCfgDirective('skip'); DebugCfgDirective('skip');
@ -1980,10 +2035,12 @@ begin
begin begin
if IfLvl=0 then if IfLvl=0 then
CfgSyntaxError('"'+Directive+'" without ifdef'); CfgSyntaxError('"'+Directive+'" without ifdef');
if (Skip=skipIf) and (IfLvl=SkipLvl) then begin if (Skip=skipIf) and (IfLvl=SkipLvl) then
begin
// if-block was skipped -> try this elseif // if-block was skipped -> try this elseif
Expr:=copy(Line,p-PChar(Line)+1,length(Line)); Expr:=copy(Line,p-PChar(Line)+1,length(Line));
if ConditionEvaluator.Eval(Expr) then begin if ConditionEvaluator.Eval(Expr) then
begin
// execute elseif block // execute elseif block
if ShowDebug then if ShowDebug then
DebugCfgDirective('true -> execute'); DebugCfgDirective('true -> execute');
@ -1994,7 +2051,8 @@ begin
if ShowDebug then if ShowDebug then
DebugCfgDirective('false -> skip'); DebugCfgDirective('false -> skip');
end; end;
end else if Skip=skipNone then begin end else if Skip=skipNone then
begin
// if-block was executed -> skip without test // if-block was executed -> skip without test
if ShowDebug then if ShowDebug then
DebugCfgDirective('no test -> skip'); DebugCfgDirective('no test -> skip');
@ -2006,7 +2064,8 @@ begin
if IfLvl=0 then if IfLvl=0 then
CfgSyntaxError('"'+Directive+'" without ifdef'); CfgSyntaxError('"'+Directive+'" without ifdef');
dec(IfLvl); dec(IfLvl);
if IfLvl<SkipLvl then begin if IfLvl<SkipLvl then
begin
// end block // end block
if ShowDebug then if ShowDebug then
DebugCfgDirective('end block'); DebugCfgDirective('end block');
@ -2022,7 +2081,8 @@ begin
else else
DebugCfgDirective('skipping unknown directive'); DebugCfgDirective('skipping unknown directive');
end; end;
end else if Skip=skipNone then begin end else if Skip=skipNone then
begin
// option line // option line
Line:=String(p); Line:=String(p);
ReadParam(Line,false,false); ReadParam(Line,false,false);
@ -2063,9 +2123,11 @@ begin
end; end;
// then try compiler directory // then try compiler directory
if (CompilerExe<>'') then begin if (CompilerExe<>'') then
begin
aFilename:=ExtractFilePath(CompilerExe); aFilename:=ExtractFilePath(CompilerExe);
if aFilename<>'' then begin if aFilename<>'' then
begin
aFilename:=IncludeTrailingPathDelimiter(aFilename)+DefaultConfigFile; aFilename:=IncludeTrailingPathDelimiter(aFilename)+DefaultConfigFile;
if TryConfig(aFilename) then exit; if TryConfig(aFilename) then exit;
end; end;
@ -2115,7 +2177,8 @@ begin
ParamMacros.Substitute(Param,Self); ParamMacros.Substitute(Param,Self);
if Param='' then exit; if Param='' then exit;
if Quick and ((Param='-h') or (Param='-?') or (Param='--help')) then begin if Quick and ((Param='-h') or (Param='-?') or (Param='--help')) then
begin
WriteHelp; WriteHelp;
Terminate(0); Terminate(0);
end; end;
@ -2201,10 +2264,12 @@ begin
end; end;
end; end;
'd': // define 'd': // define
if not Quick then begin if not Quick then
begin
Identifier:=copy(Param,3,length(Param)); Identifier:=copy(Param,3,length(Param));
i:=Pos(':=',Identifier); i:=Pos(':=',Identifier);
if i>0 then begin if i>0 then
begin
Value:=copy(Identifier,i+2,length(Identifier)); Value:=copy(Identifier,i+2,length(Identifier));
Identifier:=LeftStr(Identifier,i-1); Identifier:=LeftStr(Identifier,i-1);
if not IsValidIdent(Identifier) then if not IsValidIdent(Identifier) then
@ -2232,7 +2297,8 @@ begin
end; end;
end; end;
'I': // include path, same as -Fi 'I': // include path, same as -Fi
if not Quick then begin if not Quick then
begin
inc(p); inc(p);
if not FileCache.AddIncludePaths(String(p),FromCmdLine,ErrorMsg) then if not FileCache.AddIncludePaths(String(p),FromCmdLine,ErrorMsg) then
ParamFatal('invalid include path "'+ErrorMsg+'"'); ParamFatal('invalid include path "'+ErrorMsg+'"');
@ -2247,11 +2313,13 @@ begin
'i': 'i':
if p^=#0 then if p^=#0 then
ParamFatal('missing insertion file: '+Param) ParamFatal('missing insertion file: '+Param)
else if not Quick then begin else if not Quick then
begin
aFilename:=String(p); aFilename:=String(p);
if aFilename='' then if aFilename='' then
UnknownParam; UnknownParam;
if aFilename[length(aFilename)]='-' then begin if aFilename[length(aFilename)]='-' then
begin
Delete(aFilename,length(aFilename),1); Delete(aFilename,length(aFilename),1);
if aFilename='' then if aFilename='' then
UnknownParam; UnknownParam;
@ -2353,7 +2421,8 @@ begin
inc(p,length(Identifier)); inc(p,length(Identifier));
Enable:=true; Enable:=true;
c:=Identifier[length(Identifier)]; c:=Identifier[length(Identifier)];
if c in ['+','-'] then begin if c in ['+','-'] then
begin
Enable:=c='+'; Enable:=c='+';
Delete(Identifier,length(Identifier),1); Delete(Identifier,length(Identifier),1);
end; end;
@ -2406,7 +2475,8 @@ begin
ParamFatal('invalid target platform "'+Identifier+'"'); ParamFatal('invalid target platform "'+Identifier+'"');
end; end;
'u': // undefine 'u': // undefine
if not Quick then begin if not Quick then
begin
Identifier:=copy(Param,3,length(Param)); Identifier:=copy(Param,3,length(Param));
if not IsValidIdent(Identifier) then if not IsValidIdent(Identifier) then
ParamFatal('-u: invalid undefine: "'+Param+'"'); ParamFatal('-u: invalid undefine: "'+Param+'"');
@ -2422,7 +2492,8 @@ begin
end; end;
end; end;
'@': '@':
if not Quick then begin if not Quick then
begin
// load extra config file // load extra config file
aFilename:=copy(Param,2,length(Param)); aFilename:=copy(Param,2,length(Param));
if aFilename='' then if aFilename='' then
@ -2434,7 +2505,8 @@ begin
end; end;
else else
// filename // filename
if (not Quick) then begin if (not Quick) then
begin
if not FromCmdLine then if not FromCmdLine then
CfgSyntaxError('invalid parameter'); CfgSyntaxError('invalid parameter');
if FileCache.MainSrcFile<>'' then if FileCache.MainSrcFile<>'' then
@ -2452,7 +2524,8 @@ var
Enabled, Disabled: string; Enabled, Disabled: string;
i: Integer; i: Integer;
begin begin
if p^='m' then begin if p^='m' then
begin
// read m-flags // read m-flags
repeat repeat
inc(p); inc(p);
@ -2554,7 +2627,8 @@ begin
if Pos(Letter,Allowed)<1 then if Pos(Letter,Allowed)<1 then
ParamFatal('unknown option "'+Param+'". Use -h for help.'); ParamFatal('unknown option "'+Param+'". Use -h for help.');
inc(p); inc(p);
if p^='-' then begin if p^='-' then
begin
// disable // disable
if Pos(Letter,Disabled)<1 then Disabled+=Letter; if Pos(Letter,Disabled)<1 then Disabled+=Letter;
i:=Pos(Letter,Enabled); i:=Pos(Letter,Enabled);
@ -2820,7 +2894,8 @@ var
M: TMacroDef; M: TMacroDef;
begin begin
i:=FDefines.IndexOf(aName); i:=FDefines.IndexOf(aName);
if (i<>-1) then begin if (i<>-1) then
begin
M:=TMacroDef(FDefines.Objects[i]); M:=TMacroDef(FDefines.Objects[i]);
M.Free; M.Free;
FDefines.Delete(i); FDefines.Delete(i);
@ -2919,7 +2994,8 @@ begin
WriteLogo; WriteLogo;
// show debug info // show debug info
if ShowDebug then begin if ShowDebug then
begin
WriteOptions; WriteOptions;
WriteDefines; WriteDefines;
end; end;
@ -2957,7 +3033,8 @@ const
end; end;
begin begin
if length(s)<=MaxLineLen then begin if length(s)<=MaxLineLen then
begin
Log.LogRaw(s); Log.LogRaw(s);
exit; exit;
end; end;
@ -2982,7 +3059,8 @@ const
inc(p); inc(p);
end; end;
inc(CodePointCount); inc(CodePointCount);
if CodePointCount>=MaxLineLen then begin if CodePointCount>=MaxLineLen then
begin
if (WordBreak=nil) or (WordBreak-PChar(s)<MaxLineLen div 3) then if (WordBreak=nil) or (WordBreak-PChar(s)<MaxLineLen div 3) then
WordBreak:=LastCharStart; WordBreak:=LastCharStart;
Len:=WordBreak-PChar(s); Len:=WordBreak-PChar(s);
@ -3001,7 +3079,8 @@ var
begin begin
WriteLogo; WriteLogo;
Log.LogLn; Log.LogLn;
if CompilerExe<>'' then begin if CompilerExe<>'' then
begin
l('Usage: '+CompilerExe+' <your.pas>'); l('Usage: '+CompilerExe+' <your.pas>');
end else begin end else begin
l('Usage: pas2js <your.pas>'); l('Usage: pas2js <your.pas>');
@ -3128,7 +3207,8 @@ begin
// message encoding // message encoding
Log.LogMsgIgnoreFilter(nMessageEncodingIs,[IntToStr(Log.MsgCount)]); Log.LogMsgIgnoreFilter(nMessageEncodingIs,[IntToStr(Log.MsgCount)]);
// source map options // source map options
if SrcMapEnable then begin if SrcMapEnable then
begin
Log.LogMsgIgnoreFilter(nSrcMapSourceRootIs,[SrcMapSourceRoot]); Log.LogMsgIgnoreFilter(nSrcMapSourceRootIs,[SrcMapSourceRoot]);
Log.LogMsgIgnoreFilter(nSrcMapBaseDirIs,[SrcMapBaseDir]); Log.LogMsgIgnoreFilter(nSrcMapBaseDirIs,[SrcMapBaseDir]);
end; end;
@ -3251,13 +3331,15 @@ begin
aFile:=FindPasFile(PasFilename); aFile:=FindPasFile(PasFilename);
if aFile<>nil then exit; if aFile<>nil then exit;
if (PasFilename='') or not DirectoryCache.FileExists(PasFilename) then begin if (PasFilename='') or not DirectoryCache.FileExists(PasFilename) then
begin
Log.LogMsg(nSourceFileNotFound,[PasFilename]); Log.LogMsg(nSourceFileNotFound,[PasFilename]);
Terminate(ExitCodeFileNotFound); Terminate(ExitCodeFileNotFound);
end; end;
PasFilename:=ExpandFileNameUTF8(PasFilename); PasFilename:=ExpandFileNameUTF8(PasFilename);
if DirectoryExists(PasFilename) then begin if DirectoryExists(PasFilename) then
begin
Log.LogMsg(nFileIsFolder,[PasFilename]); Log.LogMsg(nFileIsFolder,[PasFilename]);
Terminate(ExitCodeFileNotFound); Terminate(ExitCodeFileNotFound);
end; end;
@ -3313,7 +3395,8 @@ begin
if aFile.PasUnitName='' then if aFile.PasUnitName='' then
RaiseInternalError(20170504161347,'missing PasUnitName "'+aFile.PasFilename+'"'); RaiseInternalError(20170504161347,'missing PasUnitName "'+aFile.PasFilename+'"');
OldFile:=FindUsedUnit(aFile.PasUnitName); OldFile:=FindUsedUnit(aFile.PasUnitName);
if OldFile<>nil then begin if OldFile<>nil then
begin
if OldFile<>aFile then if OldFile<>aFile then
RaiseInternalError(20170504161354,'duplicate unit "'+OldFile.PasUnitName+'" "'+aFile.PasFilename+'" "'+OldFile.PasFilename+'"'); RaiseInternalError(20170504161354,'duplicate unit "'+OldFile.PasUnitName+'" "'+aFile.PasFilename+'" "'+OldFile.PasFilename+'"');
end else begin end else begin

View File

@ -391,14 +391,17 @@ begin
SrcEncoding:=GuessEncoding(Src); SrcEncoding:=GuessEncoding(Src);
if Result='' then exit; if Result='' then exit;
NormSrcEncoding:=NormalizeEncoding(SrcEncoding); NormSrcEncoding:=NormalizeEncoding(SrcEncoding);
if NormSrcEncoding=NormalizeEncoding(EncodingUTF8) then begin if NormSrcEncoding=NormalizeEncoding(EncodingUTF8) then
begin
p:=PChar(Result); p:=PChar(Result);
if (p^=#$EF) and (p[1]=#$BB) and (p[2]=#$BF) then begin if (p^=#$EF) and (p[1]=#$BB) and (p[2]=#$BF) then
begin
// cut out UTF-8 BOM // cut out UTF-8 BOM
Delete(Result,1,3); Delete(Result,1,3);
end; end;
end else if (NormSrcEncoding=EncodingSystem) end else if (NormSrcEncoding=EncodingSystem)
or (NormSrcEncoding=GetDefaultTextEncoding) then begin or (NormSrcEncoding=GetDefaultTextEncoding) then
begin
Result:=SystemCPToUTF8(Result); Result:=SystemCPToUTF8(Result);
end else end else
EPas2jsFileCache.Create('invalid encoding "'+SrcEncoding+'"'); EPas2jsFileCache.Create('invalid encoding "'+SrcEncoding+'"');
@ -420,7 +423,8 @@ begin
l:=length(Src); l:=length(Src);
p:=PChar(Src); p:=PChar(Src);
repeat repeat
if ord(p^)<128 then begin if ord(p^)<128 then
begin
// ASCII // ASCII
if (p^=#0) and (p-PChar(Src)>=l) then if (p^=#0) and (p-PChar(Src)>=l) then
exit(EncodingUTF8); exit(EncodingUTF8);
@ -478,7 +482,8 @@ begin
// Note: do not add a 'if not DirectoryExists then exit'. // Note: do not add a 'if not DirectoryExists then exit'.
// This will not work on automounted directories. You must use FindFirst. // This will not work on automounted directories. You must use FindFirst.
if FindFirst(UnicodeString(Path+AllFilesMask),faAnyFile,Info)=0 then begin if FindFirst(UnicodeString(Path+AllFilesMask),faAnyFile,Info)=0 then
begin
repeat repeat
// check if special file // check if special file
if (Info.Name='.') or (Info.Name='..') or (Info.Name='') if (Info.Name='.') or (Info.Name='..') or (Info.Name='')
@ -712,8 +717,10 @@ begin
E('invalid entry "'+Entry.Name+'"'); E('invalid entry "'+Entry.Name+'"');
if (Entry.Size<0) then if (Entry.Size<0) then
E('invalid size "'+Entry.Name+'" '+IntToStr(Entry.Size)); E('invalid size "'+Entry.Name+'" '+IntToStr(Entry.Size));
if Sorted then begin if Sorted then
if (LastEntry<>nil) then begin begin
if (LastEntry<>nil) then
begin
if LastEntry.Name=Entry.Name then if LastEntry.Name=Entry.Name then
E('duplicate "'+Entry.Name+'"'); E('duplicate "'+Entry.Name+'"');
cmp:=CompareText(LastEntry.Name,Entry.Name); cmp:=CompareText(LastEntry.Name,Entry.Name);
@ -753,7 +760,8 @@ begin
Info.ShortFilename:=ExtractFilename(Info.Filename); Info.ShortFilename:=ExtractFilename(Info.Filename);
Info.DirPath:=ExtractFilePath(Info.Filename); Info.DirPath:=ExtractFilePath(Info.Filename);
if (Info.ShortFilename<>'') and (Info.ShortFilename<>'.') and (Info.ShortFilename<>'..') if (Info.ShortFilename<>'') and (Info.ShortFilename<>'.') and (Info.ShortFilename<>'..')
then begin then
begin
Info.Dir:=GetDirectory(Info.DirPath,true,false); Info.Dir:=GetDirectory(Info.DirPath,true,false);
end else begin end else begin
Info.Dir:=nil; Info.Dir:=nil;
@ -903,12 +911,14 @@ begin
Dir:=WorkingDirectory+Dir; Dir:=WorkingDirectory+Dir;
Dir:=IncludeTrailingPathDelimiter(Dir); Dir:=IncludeTrailingPathDelimiter(Dir);
Node:=FDirectories.FindKey(Pointer(Dir),@CompareAnsiStringWithDirectoryCache); Node:=FDirectories.FindKey(Pointer(Dir),@CompareAnsiStringWithDirectoryCache);
if Node<>nil then begin if Node<>nil then
begin
Result:=TPas2jsCachedDirectory(Node.Data); Result:=TPas2jsCachedDirectory(Node.Data);
if DoReference then if DoReference then
Result.Reference; Result.Reference;
Result.Update; Result.Update;
end else if DoReference or CreateIfNotExists then begin end else if DoReference or CreateIfNotExists then
begin
{$IFDEF VerbosePas2JSDirCache} {$IFDEF VerbosePas2JSDirCache}
writeln('TPas2jsCachedDirectories.GetDirectory "',Dir,'"'); writeln('TPas2jsCachedDirectories.GetDirectory "',Dir,'"');
{$ENDIF} {$ENDIF}
@ -973,7 +983,8 @@ begin
c:=p^; c:=p^;
case c of case c of
#0: #0:
if p-PChar(FSource)=length(FSource) then begin if p-PChar(FSource)=length(FSource) then
begin
FIsEOF:=true; FIsEOF:=true;
GetLine; GetLine;
exit; exit;
@ -1020,9 +1031,11 @@ begin
{$IFDEF VerboseFileCache} {$IFDEF VerboseFileCache}
writeln('TPas2jsCachedFile.Load START "',Filename,'" Loaded=',Loaded); writeln('TPas2jsCachedFile.Load START "',Filename,'" Loaded=',Loaded);
{$ENDIF} {$ENDIF}
if Loaded then begin if Loaded then
begin
// already loaded, check if it still valid // already loaded, check if it still valid
if (Cache.ResetStamp=FCacheStamp) then begin if (Cache.ResetStamp=FCacheStamp) then
begin
// nothing changed // nothing changed
Result:=FLastErrorMsg=''; Result:=FLastErrorMsg='';
if (not Result) and RaiseOnError then if (not Result) and RaiseOnError then
@ -1040,11 +1053,13 @@ begin
{$ENDIF} {$ENDIF}
// needs (re)load // needs (re)load
Result:=false; Result:=false;
if not Cache.DirectoryCache.FileExists(Filename) then begin if not Cache.DirectoryCache.FileExists(Filename) then
begin
Err('File not found "'+Filename+'"'); Err('File not found "'+Filename+'"');
exit; exit;
end; end;
if Cache.DirectoryCache.DirectoryExists(Filename) then begin if Cache.DirectoryCache.DirectoryExists(Filename) then
begin
Err('File is a directory "'+Filename+'"'); Err('File is a directory "'+Filename+'"');
exit; exit;
end; end;
@ -1123,7 +1138,8 @@ begin
if Cache.ShowTriedUsedFiles then if Cache.ShowTriedUsedFiles then
Cache.Log.LogMsgIgnoreFilter(nIncludeSearch,[Filename]); Cache.Log.LogMsgIgnoreFilter(nIncludeSearch,[Filename]);
if FilenameIsAbsolute(Filename) then begin if FilenameIsAbsolute(Filename) then
begin
Result:=Filename; Result:=Filename;
if not SearchLowUpCase(Result) then if not SearchLowUpCase(Result) then
Result:=''; Result:='';
@ -1134,7 +1150,8 @@ begin
Result:=SearchCasedInIncPath(Filename); Result:=SearchCasedInIncPath(Filename);
if Result<>'' then exit; if Result<>'' then exit;
if ExtractFileExt(Filename)='' then begin if ExtractFileExt(Filename)='' then
begin
// search with the default file extensions // search with the default file extensions
Result:=SearchCasedInIncPath(Filename+'.inc'); Result:=SearchCasedInIncPath(Filename+'.inc');
if Result<>'' then exit; if Result<>'' then exit;
@ -1174,7 +1191,8 @@ var
begin begin
Result:=''; Result:='';
if InFilename<>'' then begin if InFilename<>'' then
begin
Cache.Log.LogMsgIgnoreFilter(nSearchingFileNotFound,['not yet implemented "in" '+Cache.FormatPath(InFilename)]) Cache.Log.LogMsgIgnoreFilter(nSearchingFileNotFound,['not yet implemented "in" '+Cache.FormatPath(InFilename)])
// ToDo // ToDo
end; end;
@ -1182,7 +1200,8 @@ begin
// first search in foreign unit paths // first search in foreign unit paths
IsForeign:=true; IsForeign:=true;
for i:=0 to Cache.ForeignUnitPaths.Count-1 do for i:=0 to Cache.ForeignUnitPaths.Count-1 do
if SearchInDir(Cache.ForeignUnitPaths[i],Result) then begin if SearchInDir(Cache.ForeignUnitPaths[i],Result) then
begin
IsForeign:=true; IsForeign:=true;
exit; exit;
end; end;
@ -1203,7 +1222,8 @@ function TPas2jsFileResolver.FindUnitJSFileName(const aUnitFilename: string
begin begin
Result:=''; Result:='';
if aUnitFilename='' then exit; if aUnitFilename='' then exit;
if Cache.AllJSIntoMainJS then begin if Cache.AllJSIntoMainJS then
begin
Result:=Cache.GetResolvedMainJSFile; Result:=Cache.GetResolvedMainJSFile;
end else begin end else begin
if Cache.UnitOutputPath<>'' then if Cache.UnitOutputPath<>'' then
@ -1284,12 +1304,14 @@ begin
exit(false); exit(false);
{$IFNDEF CaseInsensitiveFilenames} {$IFNDEF CaseInsensitiveFilenames}
CasedFilename:=ExtractFilePath(Filename)+LowerCase(ExtractFileName(Filename)); CasedFilename:=ExtractFilePath(Filename)+LowerCase(ExtractFileName(Filename));
if (Filename<>CasedFilename) and FileExistsLogged(CasedFilename) then begin if (Filename<>CasedFilename) and FileExistsLogged(CasedFilename) then
begin
Filename:=CasedFilename; Filename:=CasedFilename;
exit(true); exit(true);
end; end;
CasedFilename:=ExtractFilePath(Filename)+UpperCase(ExtractFileName(Filename)); CasedFilename:=ExtractFilePath(Filename)+UpperCase(ExtractFileName(Filename));
if (Filename<>CasedFilename) and FileExistsLogged(CasedFilename) then begin if (Filename<>CasedFilename) and FileExistsLogged(CasedFilename) then
begin
Filename:=CasedFilename; Filename:=CasedFilename;
exit(true); exit(true);
end; end;
@ -1360,7 +1382,8 @@ var
end; end;
spkIdentifier: spkIdentifier:
begin begin
if aPath[length(aPath)]='-' then begin if aPath[length(aPath)]='-' then
begin
Delete(aPath,length(aPath),1); Delete(aPath,length(aPath),1);
Remove:=true; Remove:=true;
end; end;
@ -1374,18 +1397,22 @@ var
end; end;
end; end;
if Remove then begin if Remove then
begin
// remove // remove
if i>=0 then begin if i>=0 then
begin
List.Delete(i); List.Delete(i);
if CmdLineCount>i then dec(CmdLineCount); if CmdLineCount>i then dec(CmdLineCount);
end; end;
exit(true); exit(true);
end; end;
if FromCmdLine then begin if FromCmdLine then
begin
// from cmdline: append in order to the cmdline params, in front of cfg params // from cmdline: append in order to the cmdline params, in front of cfg params
if i>=0 then begin if i>=0 then
begin
if i<=CmdLineCount then exit(true); if i<=CmdLineCount then exit(true);
List.Delete(i); List.Delete(i);
end; end;
@ -1393,7 +1420,8 @@ var
inc(CmdLineCount); inc(CmdLineCount);
end else begin end else begin
// from cfg: append in reverse order to the cfg params, behind cmdline params // from cfg: append in reverse order to the cfg params, behind cmdline params
if i>=0 then begin if i>=0 then
begin
if i<=CmdLineCount+Added then exit(true); if i<=CmdLineCount+Added then exit(true);
List.Delete(i); List.Delete(i);
end; end;
@ -1421,7 +1449,8 @@ begin
if (aPath='') then continue; if (aPath='') then continue;
aPaths.Clear; aPaths.Clear;
FindMatchingFiles(aPath,1000,aPaths); FindMatchingFiles(aPath,1000,aPaths);
if aPaths.Count=0 then begin if aPaths.Count=0 then
begin
if not Add(aPath) then exit; if not Add(aPath) then exit;
end else begin end else begin
for i:=0 to aPaths.Count-1 do for i:=0 to aPaths.Count-1 do
@ -1522,7 +1551,8 @@ begin
Mask:=ResolveDots(Mask); Mask:=ResolveDots(Mask);
p:=1; p:=1;
while p<=length(Mask) do begin while p<=length(Mask) do begin
if Mask[p] in ['*','?'] then begin if Mask[p] in ['*','?'] then
begin
while (p>1) and not (Mask[p-1] in AllowDirectorySeparators) do dec(p); while (p>1) and not (Mask[p-1] in AllowDirectorySeparators) do dec(p);
Dir:=DirectoryCache.GetDirectory(LeftStr(Mask,p-1),true,false); Dir:=DirectoryCache.GetDirectory(LeftStr(Mask,p-1),true,false);
StartP:=p; StartP:=p;
@ -1532,7 +1562,8 @@ begin
Entry:=Dir.Entries[i]; Entry:=Dir.Entries[i];
if not MatchGlobbing(CurMask,Entry.Name) then continue; if not MatchGlobbing(CurMask,Entry.Name) then continue;
Filename:=Dir.Path+Entry.Name; Filename:=Dir.Path+Entry.Name;
if p>length(Mask) then begin if p>length(Mask) then
begin
// e.g. /path/unit*.pas // e.g. /path/unit*.pas
if Files.Count>=MaxCount then if Files.Count>=MaxCount then
raise EListError.Create('found too many files "'+Mask+'"'); raise EListError.Create('found too many files "'+Mask+'"');
@ -1546,7 +1577,8 @@ begin
end; end;
inc(p); inc(p);
end; end;
if DirectoryCache.FileExists(Mask) then begin if DirectoryCache.FileExists(Mask) then
begin
if Files.Count>=MaxCount then if Files.Count>=MaxCount then
raise EListError.Create('found too many files "'+Mask+'"'); raise EListError.Create('found too many files "'+Mask+'"');
Files.Add(Mask); Files.Add(Mask);
@ -1639,8 +1671,10 @@ function TPas2jsFilesCache.FormatPath(const aPath: string): string;
begin begin
Result:=aPath; Result:=aPath;
if (Result='') or (BaseDirectory='') then exit; if (Result='') or (BaseDirectory='') then exit;
if FilenameIsAbsolute(aPath) then begin if FilenameIsAbsolute(aPath) then
if not ShowFullPaths then begin begin
if not ShowFullPaths then
begin
if BaseDirectory=LeftStr(Result,length(BaseDirectory)) then if BaseDirectory=LeftStr(Result,length(BaseDirectory)) then
Delete(Result,1,length(BaseDirectory)); Delete(Result,1,length(BaseDirectory));
end; end;
@ -1652,14 +1686,17 @@ end;
function TPas2jsFilesCache.GetResolvedMainJSFile: string; function TPas2jsFilesCache.GetResolvedMainJSFile: string;
begin begin
if not (cfsMainJSFileResolved in FStates) then begin if not (cfsMainJSFileResolved in FStates) then
begin
if MainJSFile='.' then if MainJSFile='.' then
FMainJSFileResolved:='' FMainJSFileResolved:=''
else begin else begin
FMainJSFileResolved:=MainJSFile; FMainJSFileResolved:=MainJSFile;
if FMainJSFileResolved='' then begin if FMainJSFileResolved='' then
begin
// no option -o // no option -o
if UnitOutputPath<>'' then begin if UnitOutputPath<>'' then
begin
// option -FU and no -o => put into UnitOutputPath // option -FU and no -o => put into UnitOutputPath
FMainJSFileResolved:=UnitOutputPath+ChangeFileExt(ExtractFilename(MainSrcFile),'.js') FMainJSFileResolved:=UnitOutputPath+ChangeFileExt(ExtractFilename(MainSrcFile),'.js')
end else begin end else begin
@ -1683,7 +1720,8 @@ var
begin begin
Filename:=NormalizeFilename(Filename,true); Filename:=NormalizeFilename(Filename,true);
Node:=FFiles.FindKey(Pointer(Filename),@CompareFilenameWithCachedFile); Node:=FFiles.FindKey(Pointer(Filename),@CompareFilenameWithCachedFile);
if Node=nil then begin if Node=nil then
begin
// new file // new file
Result:=TPas2jsCachedFile.Create(Self,Filename); Result:=TPas2jsCachedFile.Create(Self,Filename);
FFiles.Add(Result); FFiles.Add(Result);

View File

@ -113,7 +113,8 @@ var
ExpPath: String; ExpPath: String;
l: integer; l: integer;
begin begin
if Path='' then begin if Path='' then
begin
Result:=false; Result:=false;
exit; exit;
end; end;
@ -132,7 +133,8 @@ begin
if Path = '' then if Path = '' then
exit; exit;
Len:=length(Result); Len:=length(Result);
if (Result[1] in AllowDirectorySeparators) then begin if (Result[1] in AllowDirectorySeparators) then
begin
MinLen := 1; MinLen := 1;
{$IFDEF HasUNCPaths} {$IFDEF HasUNCPaths}
if (Len >= 2) and (Result[2] in AllowDirectorySeparators) then if (Len >= 2) and (Result[2] in AllowDirectorySeparators) then
@ -220,7 +222,8 @@ begin
// skip matching directories // skip matching directories
SharedDirs:=0; SharedDirs:=0;
if FileP^ in AllowDirectorySeparators then begin if FileP^ in AllowDirectorySeparators then
begin
if not (BaseP^ in AllowDirectorySeparators) then exit; if not (BaseP^ in AllowDirectorySeparators) then exit;
repeat repeat
while FileP^ in AllowDirectorySeparators do inc(FileP); while FileP^ in AllowDirectorySeparators do inc(FileP);
@ -256,7 +259,8 @@ begin
//writeln('TryCreateRelativePath UpDirCount=',UpDirCount,' File="',FileP,'" Base="',BaseP,'"'); //writeln('TryCreateRelativePath UpDirCount=',UpDirCount,' File="',FileP,'" Base="',BaseP,'"');
// create relative filename // create relative filename
if (FileP^=#0) and (UpDirCount=0) then begin if (FileP^=#0) and (UpDirCount=0) then
begin
// Filename is the BaseDirectory // Filename is the BaseDirectory
if UsePointDirectory then if UsePointDirectory then
RelPath:='.' RelPath:='.'
@ -327,14 +331,16 @@ begin
if (c in AllowDirectorySeparators) then c := PathDelim; if (c in AllowDirectorySeparators) then c := PathDelim;
{$endif} {$endif}
// check for duplicate path delims // check for duplicate path delims
if (c=PathDelim) then begin if (c=PathDelim) then
begin
inc(SrcPos); inc(SrcPos);
{$IFDEF Windows} {$IFDEF Windows}
if (DestPos>2) if (DestPos>2)
{$ELSE} {$ELSE}
if (DestPos>1) if (DestPos>1)
{$ENDIF} {$ENDIF}
and (Result[DestPos-1]=PathDelim) then begin and (Result[DestPos-1]=PathDelim) then
begin
// skip duplicate PathDelim // skip duplicate PathDelim
continue; continue;
end; end;
@ -343,10 +349,13 @@ begin
continue; continue;
end; end;
// check for special dirs . and .. // check for special dirs . and ..
if (c='.') then begin if (c='.') then
if (SrcPos<Len) then begin begin
if (SrcPos<Len) then
begin
if (AFilename[SrcPos+1] in AllowDirectorySeparators) if (AFilename[SrcPos+1] in AllowDirectorySeparators)
and IsPathDelim(Result,DestPos-1) then begin and IsPathDelim(Result,DestPos-1) then
begin
// special dir ./ or */./ // special dir ./ or */./
// -> skip // -> skip
inc(SrcPos,2); inc(SrcPos,2);
@ -365,31 +374,38 @@ begin
// 6. ../.. -> copy because if the first '..' was not resolved, the next can't neither // 6. ../.. -> copy because if the first '..' was not resolved, the next can't neither
// 7. dir/.. -> trim dir and .. // 7. dir/.. -> trim dir and ..
// 8. dir$macro/.. -> copy // 8. dir$macro/.. -> copy
if DestPos=1 then begin if DestPos=1 then
begin
// 1. .. or ../ -> copy // 1. .. or ../ -> copy
end else if (DestPos=2) and (Result[1]=PathDelim) then begin end else if (DestPos=2) and (Result[1]=PathDelim) then
begin
// 2. /.. -> skip .., keep / // 2. /.. -> skip .., keep /
inc(SrcPos,2); inc(SrcPos,2);
continue; continue;
{$IFDEF Windows} {$IFDEF Windows}
end else if (DestPos=3) and IsDriveDelim(Result,2) then begin end else if (DestPos=3) and IsDriveDelim(Result,2) then
begin
// 3. C:.. -> copy // 3. C:.. -> copy
end else if (DestPos=4) and (Result[3]=PathDelim) end else if (DestPos=4) and (Result[3]=PathDelim)
and IsDriveDelim(Result,2) then begin and IsDriveDelim(Result,2) then
begin
// 4. C:\.. -> skip .., keep C:\ // 4. C:\.. -> skip .., keep C:\
inc(SrcPos,2); inc(SrcPos,2);
continue; continue;
end else if (DestPos=3) and (Result[1]=PathDelim) end else if (DestPos=3) and (Result[1]=PathDelim)
and (Result[2]=PathDelim) then begin and (Result[2]=PathDelim) then
begin
// 5. \\.. -> skip .., keep \\ // 5. \\.. -> skip .., keep \\
inc(SrcPos,2); inc(SrcPos,2);
continue; continue;
{$ENDIF} {$ENDIF}
end else if (DestPos>1) and (Result[DestPos-1]=PathDelim) then begin end else if (DestPos>1) and (Result[DestPos-1]=PathDelim) then
begin
// */. // */.
if (DestPos>3) if (DestPos>3)
and (Result[DestPos-2]='.') and (Result[DestPos-3]='.') and (Result[DestPos-2]='.') and (Result[DestPos-3]='.')
and IsPathDelim(Result,DestPos-4) then begin and IsPathDelim(Result,DestPos-4) then
begin
// 6. ../.. -> copy because if the first '..' was not resolved, the next can't neither // 6. ../.. -> copy because if the first '..' was not resolved, the next can't neither
end else begin end else begin
// 7. xxxdir/.. -> trim dir and skip .. // 7. xxxdir/.. -> trim dir and skip ..
@ -403,28 +419,34 @@ begin
MacroPos:=DirStart; MacroPos:=DirStart;
while MacroPos<DestPos do begin while MacroPos<DestPos do begin
if (Result[MacroPos]='$') if (Result[MacroPos]='$')
and (Result[MacroPos+1] in ['(','a'..'z','A'..'Z']) then begin and (Result[MacroPos+1] in ['(','a'..'z','A'..'Z']) then
begin
// 8. directory contains a macro -> keep // 8. directory contains a macro -> keep
break; break;
end; end;
inc(MacroPos); inc(MacroPos);
end; end;
if MacroPos=DestPos then begin if MacroPos=DestPos then
begin
// previous directory does not contain a macro -> remove dir/.. // previous directory does not contain a macro -> remove dir/..
DestPos:=DirStart; DestPos:=DirStart;
inc(SrcPos,2); inc(SrcPos,2);
//writeln('ResolveDots ',DestPos,' SrcPos=',SrcPos,' File="',AFilename,'" Result="',copy(Result,1,DestPos-1),'"'); //writeln('ResolveDots ',DestPos,' SrcPos=',SrcPos,' File="',AFilename,'" Result="',copy(Result,1,DestPos-1),'"');
if SrcPos>Len then begin if SrcPos>Len then
begin
// '..' at end of filename // '..' at end of filename
if (DestPos>1) and (Result[DestPos-1]=PathDelim) then begin if (DestPos>1) and (Result[DestPos-1]=PathDelim) then
begin
// foo/dir/.. -> foo // foo/dir/.. -> foo
dec(DestPos); dec(DestPos);
end else if (DestPos=1) then begin end else if (DestPos=1) then
begin
// foo/.. -> . // foo/.. -> .
Result[1]:='.'; Result[1]:='.';
DestPos:=2; DestPos:=2;
end; end;
end else if DestPos=1 then begin end else if DestPos=1 then
begin
// e.g. 'foo/../' // e.g. 'foo/../'
while (SrcPos<=Len) and (AFilename[SrcPos] in AllowDirectorySeparators) do while (SrcPos<=Len) and (AFilename[SrcPos] in AllowDirectorySeparators) do
inc(SrcPos); inc(SrcPos);
@ -436,7 +458,8 @@ begin
end; end;
end else begin end else begin
// special dir . at end of filename // special dir . at end of filename
if DestPos=1 then begin if DestPos=1 then
begin
Result:='.'; Result:='.';
exit; exit;
end; end;
@ -535,7 +558,8 @@ function MatchGlobbing(Mask, Name: string): boolean;
#0: #0:
exit(IsNameEnd(NameP)); exit(IsNameEnd(NameP));
'?': '?':
if not IsNameEnd(NameP) then begin if not IsNameEnd(NameP) then
begin
inc(MaskP); inc(MaskP);
c:=UTF8CharacterStrictLength(NameP); c:=UTF8CharacterStrictLength(NameP);
if c<1 then c:=1; if c<1 then c:=1;
@ -611,22 +635,26 @@ end;
function UTF8CharacterStrictLength(P: PChar): integer; function UTF8CharacterStrictLength(P: PChar): integer;
begin begin
if p=nil then exit(0); if p=nil then exit(0);
if ord(p^)<%10000000 then begin if ord(p^)<%10000000 then
begin
// regular single byte character // regular single byte character
exit(1); exit(1);
end end
else if ord(p^)<%11000000 then begin else if ord(p^)<%11000000 then
begin
// invalid single byte character // invalid single byte character
exit(0); exit(0);
end end
else if ((ord(p^) and %11100000) = %11000000) then begin else if ((ord(p^) and %11100000) = %11000000) then
begin
// should be 2 byte character // should be 2 byte character
if (ord(p[1]) and %11000000) = %10000000 then if (ord(p[1]) and %11000000) = %10000000 then
exit(2) exit(2)
else else
exit(0); exit(0);
end end
else if ((ord(p^) and %11110000) = %11100000) then begin else if ((ord(p^) and %11110000) = %11100000) then
begin
// should be 3 byte character // should be 3 byte character
if ((ord(p[1]) and %11000000) = %10000000) if ((ord(p[1]) and %11000000) = %10000000)
and ((ord(p[2]) and %11000000) = %10000000) then and ((ord(p[2]) and %11000000) = %10000000) then
@ -634,7 +662,8 @@ begin
else else
exit(0); exit(0);
end end
else if ((ord(p^) and %11111000) = %11110000) then begin else if ((ord(p^) and %11111000) = %11110000) then
begin
// should be 4 byte character // should be 4 byte character
if ((ord(p[1]) and %11000000) = %10000000) if ((ord(p[1]) and %11000000) = %10000000)
and ((ord(p[2]) and %11000000) = %10000000) and ((ord(p[2]) and %11000000) = %10000000)
@ -648,7 +677,8 @@ end;
function GetDefaultTextEncoding: string; function GetDefaultTextEncoding: string;
begin begin
if EncodingValid then begin if EncodingValid then
begin
Result:=DefaultTextEncoding; Result:=DefaultTextEncoding;
exit; exit;
end; end;
@ -660,7 +690,8 @@ begin
Result:=EncodingUTF8; Result:=EncodingUTF8;
{$ELSE} {$ELSE}
Lang := GetEnvironmentVariable('LC_ALL'); Lang := GetEnvironmentVariable('LC_ALL');
if Lang='' then begin if Lang='' then
begin
Lang := GetEnvironmentVariable('LC_MESSAGES'); Lang := GetEnvironmentVariable('LC_MESSAGES');
if Lang='' then if Lang='' then
Lang := GetEnvironmentVariable('LANG'); Lang := GetEnvironmentVariable('LANG');

View File

@ -90,7 +90,8 @@ begin
while Depth<12 do begin while Depth<12 do begin
inc(Depth); inc(Depth);
LinkFilename:=fpReadLink(Result); LinkFilename:=fpReadLink(Result);
if LinkFilename='' then begin if LinkFilename='' then
begin
AText:='"'+Filename+'"'; AText:='"'+Filename+'"';
case fpGetErrno() of case fpGetErrno() of
ESysEAcces: ESysEAcces:
@ -108,7 +109,8 @@ begin
// not a symbolic link, just a regular file // not a symbolic link, just a regular file
exit; exit;
end; end;
if (not ExceptionOnError) then begin if (not ExceptionOnError) then
begin
Result:=''; Result:='';
exit; exit;
end; end;

View File

@ -475,7 +475,8 @@ var
len: LongInt; len: LongInt;
begin begin
Result:=s; Result:=s;
if IsASCII(Result) then begin if IsASCII(Result) then
begin
// prevent codepage conversion magic // prevent codepage conversion magic
SetCodePage(RawByteString(Result), CP_ACP, False); SetCodePage(RawByteString(Result), CP_ACP, False);
exit; exit;
@ -485,7 +486,8 @@ begin
exit; exit;
len:=WideCharToMultiByte(CP_ACP,0,PUnicodeChar(src),length(src),nil,0,nil,nil); len:=WideCharToMultiByte(CP_ACP,0,PUnicodeChar(src),length(src),nil,0,nil,nil);
SetLength(Result,len); SetLength(Result,len);
if len>0 then begin if len>0 then
begin
WideCharToMultiByte(CP_ACP,0,PUnicodeChar(src),length(src),@Result[1],length(Result),nil,nil); WideCharToMultiByte(CP_ACP,0,PUnicodeChar(src),length(src),@Result[1],length(Result),nil,nil);
// prevent codepage conversion magic // prevent codepage conversion magic
SetCodePage(RawByteString(Result), CP_ACP, False); SetCodePage(RawByteString(Result), CP_ACP, False);
@ -507,7 +509,8 @@ var
UTF16Str: UnicodeString; UTF16Str: UnicodeString;
begin begin
Result:=s; Result:=s;
if IsASCII(Result) then begin if IsASCII(Result) then
begin
// prevent codepage conversion magic // prevent codepage conversion magic
SetCodePage(RawByteString(Result), CP_ACP, False); SetCodePage(RawByteString(Result), CP_ACP, False);
exit; exit;

View File

@ -149,54 +149,67 @@ function DbgString(Element: TJSElement; Indent: integer): string;
begin begin
if Element=nil then if Element=nil then
Result:='(*no element*)' Result:='(*no element*)'
else if Element is TJSLiteral then begin else if Element is TJSLiteral then
begin
Result:=DbgAsString(TJSLiteral(Element).Value,Indent+2); Result:=DbgAsString(TJSLiteral(Element).Value,Indent+2);
end else if Element is TJSPrimaryExpressionIdent then begin end else if Element is TJSPrimaryExpressionIdent then
begin
Result:=String(TJSPrimaryExpressionIdent(Element).Name); Result:=String(TJSPrimaryExpressionIdent(Element).Name);
// array literal // array literal
end else if Element is TJSArrayLiteral then begin end else if Element is TJSArrayLiteral then
begin
Result:='['+DbgAsString(TJSArrayLiteral(Element).Elements,Indent+2)+']'; Result:='['+DbgAsString(TJSArrayLiteral(Element).Elements,Indent+2)+']';
// object literal // object literal
end else if Element is TJSObjectLiteral then begin end else if Element is TJSObjectLiteral then
begin
Result:='['+DbgAsString(TJSObjectLiteral(Element).Elements,Indent+2)+']'; Result:='['+DbgAsString(TJSObjectLiteral(Element).Elements,Indent+2)+']';
// arguments // arguments
end else if Element is TJSArguments then begin end else if Element is TJSArguments then
begin
Result:='('+DbgAsString(TJSArguments(Element).Elements,Indent+2)+')'; Result:='('+DbgAsString(TJSArguments(Element).Elements,Indent+2)+')';
// member // member
end else if Element is TJSMemberExpression then begin end else if Element is TJSMemberExpression then
begin
Result:='('+DbgString(TJSMemberExpression(Element).MExpr,Indent+2)+')'; Result:='('+DbgString(TJSMemberExpression(Element).MExpr,Indent+2)+')';
// ToDo: TJSNewMemberExpression // ToDo: TJSNewMemberExpression
// ToDo: TJSDotMemberExpression // ToDo: TJSDotMemberExpression
// ToDo: TJSBracketMemberExpression // ToDo: TJSBracketMemberExpression
// call // call
end else if Element is TJSCallExpression then begin end else if Element is TJSCallExpression then
begin
Result:=DbgString(TJSCallExpression(Element).Expr,Indent+2) Result:=DbgString(TJSCallExpression(Element).Expr,Indent+2)
+DbgString(TJSCallExpression(Element).Args,Indent+2); +DbgString(TJSCallExpression(Element).Args,Indent+2);
// unary // unary
end else if Element is TJSUnary then begin end else if Element is TJSUnary then
begin
Result:=TJSUnary(Element).PrefixOperator Result:=TJSUnary(Element).PrefixOperator
+DbgString(TJSUnary(Element).A,Indent+2) +DbgString(TJSUnary(Element).A,Indent+2)
+TJSUnary(Element).PostFixOperator; +TJSUnary(Element).PostFixOperator;
// binary // binary
end else if Element is TJSBinary then begin end else if Element is TJSBinary then
if Element is TJSStatementList then begin begin
if Element is TJSStatementList then
begin
Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2)+';'+LineEnding Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2)+';'+LineEnding
+Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent); +Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent);
end else if Element is TJSVariableDeclarationList then begin end else if Element is TJSVariableDeclarationList then
begin
Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2)+';'+LineEnding Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2)+';'+LineEnding
+Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent); +Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent);
end else if Element is TJSWithStatement then begin end else if Element is TJSWithStatement then
begin
Result:='with ('+DbgString(TJSBinaryExpression(Element).A,Indent+2)+'){'+LineEnding Result:='with ('+DbgString(TJSBinaryExpression(Element).A,Indent+2)+'){'+LineEnding
+Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent+2)+LineEnding +Space(Indent)+DbgString(TJSBinaryExpression(Element).B,Indent+2)+LineEnding
+Space(Indent)+'}'; +Space(Indent)+'}';
end else if Element is TJSBinaryExpression then begin end else if Element is TJSBinaryExpression then
begin
Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2); Result:=DbgString(TJSBinaryExpression(Element).A,Indent+2);
if TJSBinaryExpression(Element).AllowCompact then if TJSBinaryExpression(Element).AllowCompact then
Result+=TJSBinaryExpression(Element).OperatorString Result+=TJSBinaryExpression(Element).OperatorString
@ -208,25 +221,29 @@ begin
end; end;
// ? : // ? :
end else if Element is TJSConditionalExpression then begin end else if Element is TJSConditionalExpression then
begin
Result:=DbgString(TJSConditionalExpression(Element).A,Indent+2) Result:=DbgString(TJSConditionalExpression(Element).A,Indent+2)
+'?'+DbgString(TJSConditionalExpression(Element).B,Indent+2) +'?'+DbgString(TJSConditionalExpression(Element).B,Indent+2)
+':'+DbgString(TJSConditionalExpression(Element).C,Indent+2); +':'+DbgString(TJSConditionalExpression(Element).C,Indent+2);
// assignment // assignment
end else if Element is TJSAssignStatement then begin end else if Element is TJSAssignStatement then
begin
Result:=DbgString(TJSAssignStatement(Element).LHS,Indent+2) Result:=DbgString(TJSAssignStatement(Element).LHS,Indent+2)
+TJSAssignStatement(Element).OperatorString +TJSAssignStatement(Element).OperatorString
+DbgString(TJSAssignStatement(Element).Expr,Indent+2); +DbgString(TJSAssignStatement(Element).Expr,Indent+2);
// var // var
end else if Element is TJSVarDeclaration then begin end else if Element is TJSVarDeclaration then
begin
Result:=TJSVarDeclaration(Element).Name; Result:=TJSVarDeclaration(Element).Name;
if TJSVarDeclaration(Element).Init<>nil then if TJSVarDeclaration(Element).Init<>nil then
Result+='='+DbgString(TJSVarDeclaration(Element).Init,Indent+2); Result+='='+DbgString(TJSVarDeclaration(Element).Init,Indent+2);
// if(){} else {} // if(){} else {}
end else if Element is TJSIfStatement then begin end else if Element is TJSIfStatement then
begin
Result:='if('+DbgString(TJSIfStatement(Element).Cond,Indent+2)+'){'+LineEnding Result:='if('+DbgString(TJSIfStatement(Element).Cond,Indent+2)+'){'+LineEnding
+Space(Indent+2)+DbgString(TJSIfStatement(Element).BTrue,Indent+2)+LineEnding +Space(Indent+2)+DbgString(TJSIfStatement(Element).BTrue,Indent+2)+LineEnding
+Space(Indent); +Space(Indent);
@ -236,10 +253,12 @@ begin
+Space(Indent)+'}'; +Space(Indent)+'}';
// body // body
end else if Element is TJSBodyStatement then begin end else if Element is TJSBodyStatement then
begin
// while(){} // while(){}
if Element is TJSWhileStatement then begin if Element is TJSWhileStatement then
begin
Result:='while('+DbgString(TJSWhileStatement(Element).Cond,Indent+2)+')'; Result:='while('+DbgString(TJSWhileStatement(Element).Cond,Indent+2)+')';
if TJSWhileStatement(Element).Body<>nil then if TJSWhileStatement(Element).Body<>nil then
Result+=DbgString(TJSWhileStatement(Element).Body,Indent) Result+=DbgString(TJSWhileStatement(Element).Body,Indent)
@ -247,7 +266,8 @@ begin
Result+='{}'; Result+='{}';
// do{}while() // do{}while()
end else if Element is TJSDoWhileStatement then begin end else if Element is TJSDoWhileStatement then
begin
Result:='do'; Result:='do';
if TJSDoWhileStatement(Element).Body<>nil then if TJSDoWhileStatement(Element).Body<>nil then
Result+=DbgString(TJSDoWhileStatement(Element).Body,Indent) Result+=DbgString(TJSDoWhileStatement(Element).Body,Indent)
@ -256,7 +276,8 @@ begin
Result+='('+DbgString(TJSDoWhileStatement(Element).Cond,Indent+2)+')'; Result+='('+DbgString(TJSDoWhileStatement(Element).Cond,Indent+2)+')';
// for(Init;Incr;Cond)Body // for(Init;Incr;Cond)Body
end else if Element is TJSForStatement then begin end else if Element is TJSForStatement then
begin
Result:='for('; Result:='for(';
if TJSForStatement(Element).Init<>nil then if TJSForStatement(Element).Init<>nil then
Result+=DbgString(TJSForStatement(Element).Init,Indent+2); Result+=DbgString(TJSForStatement(Element).Init,Indent+2);
@ -384,7 +405,8 @@ begin
else else
exit(m); exit(m);
end; end;
if FindInsertPos then begin if FindInsertPos then
begin
Result:=m; Result:=m;
if l>m then inc(Result); if l>m then inc(Result);
end else begin end else begin
@ -413,7 +435,8 @@ var
InsertPos, OldCount: Integer; InsertPos, OldCount: Integer;
begin begin
OldCount:=FMsgNumberDisabledCount; OldCount:=FMsgNumberDisabledCount;
if AValue then begin if AValue then
begin
// enable // enable
InsertPos:=FindMsgNumberDisabled(MsgNumber,true); InsertPos:=FindMsgNumberDisabled(MsgNumber,true);
if (InsertPos<OldCount) and (FMsgNumberDisabled[InsertPos]=MsgNumber) then if (InsertPos<OldCount) and (FMsgNumberDisabled[InsertPos]=MsgNumber) then
@ -520,7 +543,8 @@ var
i: Integer; i: Integer;
LastMsg, CurMsg: TPas2jsMessage; LastMsg, CurMsg: TPas2jsMessage;
begin begin
if FMsg.Count>1 then begin; if FMsg.Count>1 then
begin;
FMsg.Sort(@CompareP2JMessage); FMsg.Sort(@CompareP2JMessage);
// check for duplicates // check for duplicates
@ -664,12 +688,14 @@ var
s: String; s: String;
begin begin
s:=''; s:='';
if Filename<>'' then begin if Filename<>'' then
begin
if Assigned(OnFormatPath) then if Assigned(OnFormatPath) then
s+=OnFormatPath(Filename) s+=OnFormatPath(Filename)
else else
s+=Filename; s+=Filename;
if Line>0 then begin if Line>0 then
begin
s+='('+IntToStr(Line); s+='('+IntToStr(Line);
if Col>0 then s+=','+IntToStr(Col); if Col>0 then s+=','+IntToStr(Col);
s+=')'; s+=')';
@ -711,7 +737,8 @@ end;
procedure TPas2jsLogger.Reset; procedure TPas2jsLogger.Reset;
begin begin
OutputFilename:=''; OutputFilename:='';
if FMsgNumberDisabled<>nil then begin if FMsgNumberDisabled<>nil then
begin
ReAllocMem(FMsgNumberDisabled,0); ReAllocMem(FMsgNumberDisabled,0);
FMsgNumberDisabledCount:=0; FMsgNumberDisabledCount:=0;
end; end;

View File

@ -1217,13 +1217,15 @@ var
StartPos:=p; StartPos:=p;
while not (p^ in [#0,#10,#13]) do inc(p); while not (p^ in [#0,#10,#13]) do inc(p);
ExpLine:=copy(Expected,StartPos-PChar(Expected)+1,p-StartPos); ExpLine:=copy(Expected,StartPos-PChar(Expected)+1,p-StartPos);
if p^ in [#10,#13] then begin if p^ in [#10,#13] then
begin
if (p[1] in [#10,#13]) and (p^<>p[1]) then if (p[1] in [#10,#13]) and (p^<>p[1]) then
inc(p,2) inc(p,2)
else else
inc(p); inc(p);
end; end;
if (p<=ExpectedP) and (p^<>#0) then begin if (p<=ExpectedP) and (p^<>#0) then
begin
writeln('= ',ExpLine); writeln('= ',ExpLine);
end else begin end else begin
// diff line // diff line
@ -1458,8 +1460,10 @@ procedure TCustomTestModule.RaiseException(E: Exception);
var var
MsgNumber: Integer; MsgNumber: Integer;
begin begin
if ExpectedErrorClass<>nil then begin if ExpectedErrorClass<>nil then
if FExpectedErrorClass=E.ClassType then begin begin
if FExpectedErrorClass=E.ClassType then
begin
if E is EPas2JS then if E is EPas2JS then
MsgNumber:=EPas2JS(E).MsgNumber MsgNumber:=EPas2JS(E).MsgNumber
else if E is EPasResolve then else if E is EPasResolve then