123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 |
- unit prefixer;
- {$mode ObjFPC}{$H+}
- interface
- uses
- Classes, SysUtils, PScanner, PParser, PasTree, strutils, regexpr;
- Type
- { We have to override abstract TPasTreeContainer methods.
- See utils/fpdoc/dglobals.pp for an implementation of TFPDocEngine,
- a "real" engine. }
- TSimpleEngine = class(TPasTreeContainer)
- public
- function CreateElement(AClass: TPTreeElement; const AName: String;
- AParent: TPasElement; AVisibility: TPasMemberVisibility;
- const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
- override;
- function FindElement(const AName: String): TPasElement; override;
- end;
- { TPrefixer }
- TFileMode = (
- fmReplace, // new file replaces old completely.
- fmReplaceNamespace, // new file replaces old completely. Namespaces are used for uses clause.
- fmInclude, // new file includes old, units in uses clause replaced with new names
- fmIncludeNamespace // new file includes old. Namespaces are used for uses clause.
- );
- TIncludeNameMode = (
- inmIfdefElse, // Unit name in include file is set using {$IFDEF DEFINE} NEWNAME {$ELSE} OLDNAME {$ENDIF}
- inmIfndef // Unit clause is included in main file, it is skipped in include file using {$IFNDEF DEFINE} unit OLDNAME; {$ENDIF}
- );
- TPrefixLog = Procedure (Sender : TObject; aType : TEventType; const aMsg : String) of object;
- TPrefixer = class(TComponent)
- private
- FCasedFileNames: Boolean;
- FCreateBackups: Boolean;
- FDefine: String;
- FDestFileName: String;
- FDestUnitName: String;
- FFileName: String;
- FKnownNameSpaces: TStrings;
- FNameMode: TIncludeNameMode;
- FNameSpace: String;
- FOnLog: TPrefixLog;
- FParams: TStrings;
- FSkipDestFileName: Boolean;
- FSources : TStrings;
- FDottedSources : TStrings;
- FNewUses : TStrings;
- FUnitFileMode: TFileMode;
- FFullFileName : String;
- Protected
- Procedure DoLog(aType : TEventType; Const aMsg : String);
- Procedure DoLog(aType : TEventType; Const aFmt : String; aArgs : array of const);
- procedure AddNameSpaces(Src: TStrings; aUses: TPasUsesClause);
- procedure CorrectUnitName(aName: String; aLineNr: Integer);
- procedure DoParseLog(Sender: TObject; const Msg: String);
- procedure GetAdditionalUnits(aUnitNames: TStrings; aSource: String);
- function GetDefine: String;
- function GetDestFileName: String;
- function GetDestUnitName: String;
- function MaybeBackup(const aFileName: string): Boolean;
- function ParseSource(AEngine: TPasTreeContainer;
- const FPCCommandLine: array of String; OSTarget, CPUTarget: String;
- Options: TParseSourceOptions): TPasModule;
- function ReplaceUnits(const aLine: string; aUnitNames : TStrings): String;
- function ReplaceWord(aLine, aName, aFull: String): String;
- function FindWord(aName,aLine : String): Boolean;
- procedure ReworkUses(aSection: TPasSection);
- Public
- Constructor Create(aOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure PrintUses(aSection : TPasSection; aShowFileName : Boolean = false);
- procedure Execute;
- procedure ReworkUses(aUses,aNewUses : TStrings);
- class function ExtractPrefix(const aRule: String): String;
- class function ApplyRule(const aFile,aCasedName,aRule : String; PrettyPrint : Boolean) : String;
- class function ApplyAliasRule(const aName, aRule: String): String;
- // Create backups of created/changed files ?
- Property CreateBackups : Boolean Read FCreateBackups Write FCreateBackups;
- // How to create the new file.
- Property UnitFileMode : TFileMode Read FUnitFileMode Write FUnitFileMode;
- // How to set the unit name in the case of an include file.
- Property IncludeUnitNameMode : TIncludeNameMode Read FNameMode Write FNameMode;
- // Define to use to protect dotted names. Default FPC_DOTTEDUNITS
- Property Define : String Read GetDefine Write FDefine;
- // Filename to process. For include modes, this file will be overwritten !
- Property FileName : String Read FFileName Write FFileName;
- // Do not write dotted Filename
- Property SkipDestFileName : Boolean Read FSkipDestFileName Write FSkipDestFileName;
- // Dotted Filename to produce (including path & extension). If not set, NameSpace.FileName is used.
- Property DestFileName : String Read GetDestFileName Write FDestFileName;
- // Filename to produce. If not set, DestFileName without extension is used.
- Property DestUnitName : String Read GetDestUnitName Write FDestUnitName;
- // Namespace to be used for this unit.
- Property NameSpace : String Read FNameSpace Write FNameSpace;
- // Namespaces for used units, in format UnitName=NameSpace
- Property KnownNameSpaces : TStrings Read FKnownNameSpaces;
- // Params needed to parse FileName
- Property Params : TStrings Read FParams;
- // if True, then the output files have the same case as the unit names.
- // If False, all filenames are lowercased.
- Property CasedFileNames : Boolean Read FCasedFileNames Write FCasedFileNames;
- // For messages
- Property OnLog : TPrefixLog Read FOnLog Write FOnLog;
- end;
- implementation
- function TSimpleEngine.CreateElement(AClass: TPTreeElement;
- const AName: String;
- AParent: TPasElement;
- AVisibility: TPasMemberVisibility;
- const ASourceFilename: String;
- ASourceLinenumber: Integer): TPasElement;
- begin
- // Writeln(AName,' : ',AClass.ClassName,' at ',ASourceFilename,':',ASourceLinenumber);
- Result := AClass.Create(AName, AParent);
- Result.Visibility := AVisibility;
- Result.SourceFilename := ASourceFilename;
- Result.SourceLinenumber := ASourceLinenumber;
- end;
- function TSimpleEngine.FindElement(const AName: String): TPasElement;
- begin
- { dummy implementation, see TFPDocEngine.FindElement for a real example }
- Result := nil;
- end;
- constructor TPrefixer.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FKnownNameSpaces:=TStringList.Create;
- FParams:=TStringList.Create;
- FSources:=TStringList.Create;
- FDottedSources:=TStringList.Create;
- FNewuses:=TStringList.Create;
- FUnitFileMode:=fmInclude;
- FNameMode:=inmIfndef;
- end;
- destructor TPrefixer.Destroy;
- begin
- FreeAndNil(FKnownNameSpaces);
- FreeAndNil(FParams);
- FreeAndNil(FSources);
- FreeAndNil(FDottedSources);
- FreeAndNil(FNewuses);
- inherited Destroy;
- end;
- procedure TPrefixer.PrintUses(aSection: TPasSection; aShowFileName: Boolean);
- Var
- aUses : TPasUsesUnit;
- aName : string;
- begin
- if aSection=Nil then
- exit;
- for aUses in aSection.UsesClause do
- begin
- aName:='';
- if aShowFileName and assigned(aUses.InFileName) then
- aName:=AnsiDequotedStr(aUses.InFileName.Value,'''');
- if (aName='') and assigned(aUses.Expr) then
- aName:=aUses.Expr.GetDeclaration(False);
- if aName='' then
- aName:=aUses.Name;
- DoLog(etInfo,'%s, { location: %s:%d }',[aName,aUses.SourceFilename,aUses.SourceLinenumber]);
- end;
- end;
- function TPrefixer.ReplaceWord(aLine, aName, aFull: String): String;
- var
- RE : TRegExpr;
- begin
- RE:=TRegExpr.Create('\b'+aName+'\b');
- try
- Result:=RE.Replace(aLine,aFull);
- DoLog(etDebug, '%s: %s -> %s = %s',[aLine,aName,aFull,Result]);
- finally
- RE.Free;
- end;
- end;
- function TPrefixer.FindWord(aName, aLine: String): Boolean;
- var
- RE : TRegExpr;
- begin
- RE:=TRegExpr.Create('\b'+aName+'\b');
- try
- RE.ModifierI:=True;
- Result:=RE.Exec(aLine);
- DoLog(etDebug, '%s: %s = %s',[aLine,aName,BoolToStr(Result,'true','false')]);
- finally
- RE.Free;
- end;
- end;
- function TPrefixer.ReplaceUnits(const aLine: string; aUnitNames: TStrings): String;
- Var
- res,aName,aFull,aNameSpace,aUnit : String;
- idx : Integer;
- begin
- Res:=aLine;
- for aName in aUnitNames do
- begin
- Idx:=FKnownNameSpaces.IndexOfName(aName);
- if Idx<>-1 then
- begin
- FKnownNameSpaces.GetNameValue(Idx,aUnit,aNameSpace);
- if Copy(aNameSpace,1,1)='*' then
- aFull:=Copy(aNameSpace,2)
- else
- aFull:=aNameSpace+'.'+aUnit;
- Res:=ReplaceWord(Res,aName,aFull);
- end;
- end;
- Result:=Res;
- end;
- procedure TPrefixer.GetAdditionalUnits(aUnitNames : TStrings; aSource : String);
- Var
- aRE : TRegExpr;
- aWords : TStringList;
- aWord : string;
- begin
- awords:=nil;
- aRE:=TRegExpr.Create('(\w+)');
- Try
- aWords:=TstringList.Create;
- if aRe.Exec(aSource) then
- repeat
- aWord:=System.Copy(aSource, ARE.MatchPos[0], ARE.MatchLen[0]);
- if IndexText(aWord,['uses','define','undef','if','ifdef', 'endif','else'])=-1 then
- if (FKnownNameSpaces.IndexOfName(aWord)<>-1) then
- aUnitNames.Add(aWord); // Duplicates set to ignore
- until not Are.ExecNext;
- Finally
- aWords.Free;
- aRE.Free;
- end;
- end;
- procedure TPrefixer.ReworkUses(aSection: TPasSection);
- Var
- aUses : TPasUsesUnit;
- S,aName,aLine,FNUses,FNMain : String;
- aUnitNames : TStringList;
- // all 0-based
- I,Idx, FUses,FUsesEnd, FFirst,FLast : Integer;
- begin
- if (aSection=Nil)
- or (Length(aSection.UsesClause)=0)
- or ((Length(aSection.UsesClause)=1)
- and (SameText(aSection.UsesClause[0].Name,'System'))) then
- exit;
- FNMain:=ExtractFileName(FFileName);
- FFirst:=FSources.Count+1;
- FLast:=0;
- aUnitNames:=TStringList.Create;
- try
- aUnitNames.Sorted:=True;
- aUnitNames.Duplicates:=dupIgnore;
- for aUses in aSection.UsesClause do
- begin
- if aUses.SourceLinenumber-1>FLast then
- FLast:=aUses.SourceLinenumber-1;
- if aUses.SourceLinenumber-1<FFirst then
- FFirst:=aUses.SourceLinenumber-1;
- FNUses:=ExtractFileName(aUses.SourceFilename);
- aName:='';
- if (aName='') and assigned(aUses.Expr) then
- aName:=aUses.Expr.GetDeclaration(False);
- if aName='' then
- aName:=aUses.Name;
- if (FNUses<>FNMain) or (expandfilename(aUses.SourceFileName)<>FFullFileName) then
- Raise Exception.CreateFmt('Uses clause unit %s not in main unit: (uses: %s) <> %s',[aName,FNUses,FNMain]);
- aUnitNames.Add(aName);
- end;
- Fuses:=FFirst;
- if Fuses>=FSources.Count then
- FUses:=FSources.Count-1;
- While (FUses>=0) and (Pos('uses',lowerCase(FSources[FUses]))=0) do
- Dec(Fuses);
- FUsesEnd:=FLast; // Fuses is 0 bases
- While (FUsesEnd<FSources.Count) and (Pos(';',FSources[FUsesEnd])=0) do
- Inc(FusesEnd);
- DoLog(etDebug, 'Uses clause extends from %d: %s',[FUses,FSources[FUses]]);
- DoLog(etDebug, 'Uses clause extends to %d: %s',[FUsesEnd,FSources[FUsesEnd]]);
- S:='';
- For I:=Fuses to FUsesEnd do
- S:=S+#10+FSources[I];
- GetAdditionalUnits(aUnitNames,S);
- FNewuses.Clear;
- if UnitFileMode<>fmReplace then
- FNewuses.Add('{$IFDEF '+Define+'}');
- For Idx:=FUses to FUsesEnd do
- begin
- aLine:=FSources[Idx];
- If (Idx>=FFirst) and (Idx<=FLast) then
- begin
- aLine:=ReplaceUnits(aLine,aUnitNames);
- end;
- FNewUses.Add(aLine);
- end;
- // Check what we need to do with original sources
- if UnitFileMode<>fmReplace then
- begin
- FNewuses.Add('{$ELSE '+Define+'}');
- // Insert before uses
- FSources.Insert(FUsesEnd+1,'{$ENDIF '+Define+'}');
- end
- else
- begin
- // If we need to replace, we just remove all old lines before adding the new ones
- if UnitFileMode=fmReplace then
- For I:=FUsesEnd downto FUses do
- FSources.Delete(I);
- end;
- For I:=FNewUses.Count-1 downto 0 do
- FSources.Insert(FUses,FNewUses[i]);
- finally
- aUnitNames.Free;
- end;
- end;
- function TPrefixer.GetDefine: String;
- begin
- Result:=FDefine;
- if Result='' then
- Result:='FPC_DOTTEDUNITS';
- end;
- function TPrefixer.MaybeBackup(const aFileName: string): Boolean;
- Var
- BFN : String;
- FIn,Fout : TFileStream;
- begin
- Result:=FileExists(aFileName);
- if Result then
- begin
- BFN:=aFileName+'.bak';
- Fout:=Nil;
- Fin:=TFileStream.Create(aFilename,fmOpenRead or fmShareDenyWrite);
- try
- Fout:=TFileStream.Create(BFN,fmCreate);
- Fout.CopyFrom(FIn,0);
- finally
- Fin.Free;
- Fout.Free;
- end;
- end;
- end;
- function TPrefixer.GetDestFileName: String;
- Var
- DN, FN, NS : String;
- begin
- Result:=FDestFileName;
- if Result='' then
- begin
- DN:=ExtractFilePath(FileName);
- FN:=ExtractFileName(FileName);
- NS:=NameSpace;
- if NS<>'' then
- NS:=NS+'.';
- if CasedFileNames then
- Result:=DN+NS+FN
- else
- Result:=DN+LowerCase(NS+FN);
- end;
- end;
- function TPrefixer.GetDestUnitName: String;
- begin
- Result:=FDestUnitName;
- if Result='' then
- Result:=ChangeFileExt(ExtractFileName(DestFileName),'');
- end;
- procedure TPrefixer.CorrectUnitName(aName : String; aLineNr : Integer);
- Var
- aLine,aReplace,aNewName : string;
- Idx : Integer;
- begin
- aNewName:=DestUnitName;
- if (aNewName=aName) then
- exit; // nothing to do.
- case IncludeUnitNameMode of
- inmIfdefElse:
- begin
- aLine:=FSources[aLineNr];
- aReplace:='{$IFDEF '+Define+'} '+aNewName+' {$ELSE} '+aName+' {$ENDIF}';
- aLine:=ReplaceWord(aLine,aName,aReplace);
- end;
- inmIfndef:
- begin
- // Look for ;
- idx:=aLineNr-1;
- While (Idx<FSources.Count) and (Pos(';',FSources[Idx])=0) do
- Inc(Idx);
- if (Idx<FSources.Count-1) then
- FSources.Insert(Idx+1,'{$ENDIF '+DEFINE+'}');
- // Look for unit
- idx:=aLineNr;
- if Idx>=FSources.Count then
- Idx:=FSources.Count-1;
- While (Idx>=0) and Not FindWord('unit',FSources[Idx]) do
- Dec(Idx);
- if Idx>=0 then
- FSources.Insert(Idx,'{$IFNDEF '+DEFINE+'}');
- end;
- end;
- end;
- procedure TPrefixer.DoParseLog(Sender: TObject; const Msg: String);
- begin
- DoLog(etDebug,Msg);
- end;
- procedure TPrefixer.DoLog(aType: TEventType; const aMsg: String);
- begin
- if assigned(FOnLog) then
- FOnLog(Self,aType,aMsg);
- end;
- procedure TPrefixer.DoLog(aType: TEventType; const aFmt: String;
- aArgs: array of const);
- begin
- DoLog(aType,Format(aFmt,aArgs));
- end;
- procedure TPrefixer.AddNameSpaces(Src : TStrings; aUses : TPasUsesClause);
- Var
- aUsed : TPasUsesUnit;
- aDirective,aName,aNameSpace,aUnit : String;
- idx : Integer;
- begin
- for aUsed in aUses do
- begin
- aName:='';
- if assigned(aUsed.Expr) then
- aName:=aUsed.Expr.GetDeclaration(False);
- if aName='' then
- aName:=aUsed.Name;
- Idx:=FKnownNameSpaces.IndexOfName(aName);
- if Idx<>-1 then
- begin
- FKnownNameSpaces.GetNameValue(Idx,aUnit,aNameSpace);
- aDirective:='{$NAMESPACE '+aNameSpace+'}';
- if Src.IndexOf(aDirective)=-1 then
- Src.Insert(0,aDirective);
- end;
- end;
- end;
- function TPrefixer.ParseSource(AEngine: TPasTreeContainer;
- const FPCCommandLine: array of String; OSTarget, CPUTarget: String;
- Options: TParseSourceOptions): TPasModule;
- var
- FileResolver: TBaseFileResolver;
- Parser: TPasParser;
- lFilename: String;
- Scanner: TPascalScanner;
- allowmem : Boolean;
- procedure ProcessCmdLinePart(S : String);
- var
- l,Len: Integer;
- begin
- if (S='') then
- exit;
- Len:=Length(S);
- if (s[1] = '-') and (len>1) then
- begin
- case s[2] of
- 'd': // -d define
- begin
- s:=Copy(s, 3, Len);
- Scanner.AddDefine(UpperCase(S));
- if s='allowmem' then
- AllowMem:=True;
- end;
- 'u': // -u undefine
- Scanner.RemoveDefine(UpperCase(Copy(s, 3, Len)));
- 'F': // -F
- if (len>2) and (s[3] = 'i') then // -Fi include path
- FileResolver.AddIncludePath(Copy(s, 4, Len));
- 'I': // -I include path
- FileResolver.AddIncludePath(Copy(s, 3, Len));
- 'S': // -S mode
- if (len>2) then
- begin
- l:=3;
- While L<=Len do
- begin
- case S[l] of
- 'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
- 'd' : Scanner.SetCompilerMode('DELPHI');
- '2' : Scanner.SetCompilerMode('OBJFPC');
- 'h' : ; // do nothing
- end;
- inc(l);
- end;
- end;
- 'M' :
- begin
- delete(S,1,2);
- l:=pos(':',S);
- if (L<>0) and (UpperCase(Copy(S,1,l-1))='MODESWITCH') then
- begin
- Delete(S,1,l);
- if SameText(S,'externalclass') then
- Scanner.ReadOnlyModeSwitches:=Scanner.ReadOnlyModeSwitches+[msExternalClass];
- Scanner.SetModeSwitch(S);
- end
- else
- Scanner.SetCompilerMode(S);
- end;
- end;
- end else
- if lFilename <> '' then
- raise ENotSupportedException.Create(SErrMultipleSourceFiles)
- else
- lFilename := s;
- end;
- var
- S: String;
- opts : TPOptions;
- begin
- AllowMem:=False;
- if DefaultFileResolverClass=Nil then
- raise ENotImplemented.Create(SErrFileSystemNotSupported);
- Result := nil;
- FileResolver := nil;
- Scanner := nil;
- Parser := nil;
- try
- FileResolver := DefaultFileResolverClass.Create;
- if FileResolver is TFileResolver then
- TFileResolver(FileResolver).UseStreams:=poUseStreams in Options;
- Scanner := TPascalScanner.Create(FileResolver);
- Scanner.LogEvents:=AEngine.ScannerLogEvents;
- Scanner.OnLog:=AEngine.Onlog;
- if not (poSkipDefaultDefs in Options) then
- begin
- Scanner.AddDefine('FPK');
- Scanner.AddDefine('FPC');
- Scanner.AddDefine('FPC_LITTLE_ENDIAN');
- // TargetOS
- s := UpperCase(OSTarget);
- Scanner.AddDefine(s);
- Case s of
- 'LINUX' : Scanner.AddDefine('UNIX');
- 'FREEBSD' :
- begin
- Scanner.AddDefine('BSD');
- Scanner.AddDefine('UNIX');
- end;
- 'NETBSD' :
- begin
- Scanner.AddDefine('BSD');
- Scanner.AddDefine('UNIX');
- end;
- 'SUNOS' :
- begin
- Scanner.AddDefine('SOLARIS');
- Scanner.AddDefine('UNIX');
- end;
- 'GO32V2' : Scanner.AddDefine('DPMI');
- 'BEOS' : Scanner.AddDefine('UNIX');
- 'QNX' : Scanner.AddDefine('UNIX');
- 'AROS' : Scanner.AddDefine('HASAMIGA');
- 'MORPHOS' : Scanner.AddDefine('HASAMIGA');
- 'AMIGA' : Scanner.AddDefine('HASAMIGA');
- end;
- // TargetCPU
- s := UpperCase(CPUTarget);
- Scanner.AddDefine('CPU'+s);
- if (s='X86_64') then
- Scanner.AddDefine('CPU64')
- else
- Scanner.AddDefine('CPU32');
- end;
- Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
- if (poSkipDefaultDefs in Options) then
- Parser.ImplicitUses.Clear;
- lFilename := '';
- Parser.LogEvents:=AEngine.ParserLogEvents;
- Parser.OnLog:=AEngine.Onlog;
- For S in FPCCommandLine do
- ProcessCmdLinePart(S);
- if lFilename = '' then
- raise Exception.Create(SErrNoSourceGiven);
- FileResolver.AddIncludePath(ExtractFilePath(lFileName));
- opts:=[po_AsmWhole,po_AsmPascalComments];
- if AllowMem then
- Include(opts,po_allowmem);
- opts:=opts+Scanner.options;
- Parser.Options:=Parser.Options+opts;
- Parser.OnLog:=@DoParseLog;
- Scanner.OpenFile(lFilename);
- Parser.ParseMain(Result);
- finally
- Parser.Free;
- Scanner.Free;
- FileResolver.Free;
- end;
- end;
- procedure TPrefixer.Execute;
- var
- M: TPasModule;
- P : TPasProgram absolute M;
- L : TPasLibrary absolute M;
- E: TPasTreeContainer;
- cmdline : Array of String;
- begin
- FFullFileName:=ExpandFileName(FFileName);
- cmdline:=Params.ToStringArray;
- CmdLine:=Concat(CmdLine,[FileName]);
- E := TSimpleEngine.Create;
- M := nil;
- try
- E.OnLog:=@DoParseLog;
- E.ParserLogEvents:=[pleImplementation,pleInterface];
- FSources.LoadFromFile(FFileName);
- FDottedSources.Clear;
- M := Self.ParseSource(E, cmdline, 'linux', 'i386',[]);
- if UnitFileMode in [fmInclude,fmIncludeNamespace] then
- begin
- if IncludeUnitNameMode=inmIfndef then
- FDottedSources.Add('unit '+DestUnitName+';');
- FDottedSources.Add('{$DEFINE '+Define+'}');
- end;
- if M is TPasProgram then
- begin
- if UnitFileMode in [fmReplace,fmInclude] then
- ReworkUses(P.ProgramSection)
- else
- AddNameSpaces(FSources,P.ProgramSection.UsesClause);
- end
- else if M is TPasLibrary then
- begin
- if UnitFileMode in [fmReplace,fmInclude] then
- ReworkUses(L.LibrarySection)
- else
- AddNameSpaces(FSources,L.LibrarySection.UsesClause);
- end
- else
- begin
- if UnitFileMode in [fmReplace,fmInclude] then
- begin
- ReworkUses(M.ImplementationSection);
- ReworkUses(M.InterfaceSection);
- CorrectUnitName(M.Name,M.SourceLinenumber);
- end
- else
- begin
- AddNamespaces(FDottedSources,M.ImplementationSection.UsesClause);
- AddNameSpaces(FDottedSources,M.InterfaceSection.UsesClause);
- end;
- end;
- if UnitFileMode in [fmReplace,fmReplaceNamespace] then
- begin
- MaybeBackup(DestFileName);
- FSources.SaveToFile(DestFileName);
- end
- else
- begin
- MaybeBackup(FileName);
- FSources.SaveToFile(FileName);
- if not SkipDestFileName then
- begin
- FDottedSources.Add('{$i '+ExtractFileName(FileName)+'}');
- MaybeBackup(DestFileName);
- FDottedSources.SaveToFile(DestFileName);
- end;
- end;
- finally
- FreeAndNil(M);
- FreeAndNil(E)
- end;
- end;
- procedure TPrefixer.ReworkUses(aUses, aNewUses: TStrings);
- Var
- S,aLine : String;
- aUnitNames : TStringList;
- I,Idx : Integer;
- begin
- aUnitNames:=TStringList.Create;
- try
- aUnitNames.Sorted:=True;
- aUnitNames.Duplicates:=dupIgnore;
- S:='';
- For I:=0 to aUses.Count-1 do
- S:=S+#10+aUses[I];
- GetAdditionalUnits(aUnitNames,S);
- aNewuses.Clear;
- aNewuses.Add('{$IFDEF '+Define+'}');
- For Idx:=0 to aUses.Count-1 do
- begin
- aLine:=aUses[Idx];
- aLine:=ReplaceUnits(aLine,aUnitNames);
- aNewUses.Add(aLine);
- end;
- // Add original
- aNewuses.Add('{$ELSE '+Define+'}');
- aNewuses.AddStrings(aUses);
- aNewuses.Add('{$ENDIF '+Define+'}');
- finally
- aUnitNames.Free;
- end;
- end;
- class function TPrefixer.ExtractPrefix(const aRule: String) : String;
- Var
- P : Integer;
- begin
- // *Prefix.UnitName
- if Copy(aRule,1,1)='*' then
- begin
- P:=Pos('.',aRule);
- Result:=Copy(aRule,2,P-2);
- end
- else
- begin
- // Prefix,UnitNamerule
- P:=Pos(',',aRule);
- if P=0 then
- P:=Length(aRule)+1;
- Result:=Copy(aRule,1,P-1);
- end;
- end;
- class function TPrefixer.ApplyAliasRule(const aName, aRule: String) : String;
- begin
- If Copy(aRule,1,1)='*' then
- Result:=Copy(aRule,2)
- else if aRule<>'' then
- Result:=aRule+'.'+aName
- else
- Result:=aName;
- end;
- class function TPrefixer.ApplyRule(const aFile, aCasedName,aRule: String;
- PrettyPrint: Boolean): String;
- Var
- p,len : Integer;
- aExt,aDir,aName,aPrefix : String;
- begin
- aPrefix:='';
- aDir:=ExtractFilePath(aFile);
- aExt:=ExtractFileExt(aFile);
- Result:=ExtractFileName(aFile);
- // *DottedUnitName
- // Prefix
- // Prefix,*UnitSuffix
- // Prefix,-DeleteFromOriginalAtStart
- // Prefix,DeleteFromOriginalAtEnd-
- P:=Pos(',',aRule);
- if P=0 then
- begin
- if aRule<>'' then
- if aRule[1]='*' then
- Result:=Copy(aRule,2)+aExt
- else if PrettyPrint and (aCasedName<>'') then
- Result:=aRule+'.'+aCasedName+aExt
- else
- aPrefix:=aRule+'.'
- end
- else
- begin
- aPrefix:=Copy(aRule,1,P-1)+'.';
- aName:=Copy(aRule,P+1);
- Len:=Length(AName);
- if Len>0 then
- begin
- Case aName[1] of
- '*' : Result:=Copy(aName,2)+ExtractFileExt(Result);
- '-' : if Pos(Copy(aName,2),Result)=1 then
- Delete(Result,1,Len-1);
- else
- if (aName[Len]='-') and (RPos(aName,Result)=Length(Result)-Len+1) then
- Result:=Copy(Result,1,Length(Result)-Len);
- end;
- end;
- end;
- if PrettyPrint then
- Result[1]:=Upcase(Result[1]);
- Result:=aDir+aPrefix+Result;
- end;
- end.
|