dexed/src/ce_ddemangle.pas

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.