mirror of https://gitlab.com/basile.b/dexed.git
158 lines
3.2 KiB
Plaintext
158 lines
3.2 KiB
Plaintext
unit ce_ddemangle;
|
|
|
|
{$I ce_defines.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, process, forms,
|
|
ce_processes, ce_common, ce_stringrange;
|
|
|
|
type
|
|
|
|
TCEDDemangler = class
|
|
strict private
|
|
fActive: boolean;
|
|
fProc: TCEProcess;
|
|
fList, fOut: TStringList;
|
|
procedure procTerminate(sender: TObject);
|
|
public
|
|
constructor create;
|
|
destructor destroy; override;
|
|
procedure demangle(const value: string);
|
|
property output: TStringList read fList;
|
|
property active: boolean read fActive;
|
|
end;
|
|
|
|
// demangle a D name
|
|
function demangle(const value: string): string;
|
|
// demangle a list of D names
|
|
procedure demangle(values, output: TStrings);
|
|
|
|
implementation
|
|
|
|
var
|
|
demangler: TCEDDemangler;
|
|
|
|
constructor TCEDDemangler.create;
|
|
var
|
|
s: string = '.0.';
|
|
r: TStringRange;
|
|
v: integer;
|
|
begin
|
|
fList := TStringList.Create;
|
|
fOut := TStringList.Create;
|
|
fProc := TCEProcess.create(nil);
|
|
fProc.Options:= [poUsePipes];
|
|
fProc.OnTerminate:=@procTerminate;
|
|
fProc.ShowWindow:= swoHIDE;
|
|
|
|
// Arch Linux users can have the tool setup w/o DMD
|
|
{$IFDEF POSIX}
|
|
fProc.Executable := exeFullName('dtools-ddemangle');
|
|
if fProc.Executable.fileExists then
|
|
begin
|
|
fProc.execute;
|
|
fActive := true;
|
|
exit;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
// up to version 2.071 ddemangle cannot be daemon-ized
|
|
with TProcess.Create(nil) do
|
|
try
|
|
Executable := exeFullName('dmd' + exeExt);
|
|
if Executable.fileExists then
|
|
begin
|
|
setLength(s, 128);
|
|
Parameters.Text:= '--version';
|
|
Options:= [poUsePipes];
|
|
ShowWindow:= swoHIDE;
|
|
execute;
|
|
output.Read(s[1], 128);
|
|
while Running do
|
|
sleep(1);
|
|
end;
|
|
finally
|
|
free;
|
|
end;
|
|
r := r.create(s);
|
|
v := r.popUntil('.')^.popFront^.takeUntil('.').yield.toInt;
|
|
|
|
fProc.Executable := exeFullName('ddemangle' + exeExt);
|
|
if (v >= 72) and fProc.Executable.fileExists then
|
|
begin
|
|
fProc.execute;
|
|
fActive := true;
|
|
end
|
|
else fActive := false;
|
|
end;
|
|
|
|
destructor TCEDDemangler.destroy;
|
|
begin
|
|
if fProc.Running then
|
|
fProc.Terminate(0);
|
|
fProc.Free;
|
|
fOut.Free;
|
|
fList.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCEDDemangler.procTerminate(sender: TObject);
|
|
begin
|
|
fActive := false;
|
|
end;
|
|
|
|
procedure TCEDDemangler.demangle(const value: string);
|
|
var
|
|
nb: integer;
|
|
begin
|
|
if value.isNotEmpty then
|
|
fProc.Input.Write(value[1], value.length);
|
|
fProc.Input.WriteByte(10);
|
|
while true do
|
|
begin
|
|
nb := fProc.NumBytesAvailable;
|
|
if nb <> 0 then
|
|
break;
|
|
end;
|
|
fProc.fillOutputStack;
|
|
fProc.getFullLines(fOut);
|
|
if fOut.Count <> 0 then
|
|
fList.Add(fOut[0]);
|
|
end;
|
|
|
|
function demangle(const value: string): string;
|
|
begin
|
|
if demangler.active and (pos('_D', value) > 0) then
|
|
begin
|
|
demangler.output.Clear;
|
|
demangler.demangle(value);
|
|
if demangler.output.Count <> 0 then
|
|
result := demangler.output[0]
|
|
else
|
|
result := value;
|
|
end
|
|
else result := value;
|
|
end;
|
|
|
|
procedure demangle(values, output: TStrings);
|
|
var
|
|
value: string;
|
|
begin
|
|
if demangler.active then
|
|
begin
|
|
for value in values do
|
|
demangler.demangle(value);
|
|
output.AddStrings(demangler.output);
|
|
demangler.output.Clear;
|
|
end
|
|
else output.AddStrings(values);
|
|
end;
|
|
|
|
initialization
|
|
demangler := TCEDDemangler.create;
|
|
finalization
|
|
demangler.Free;
|
|
end.
|