1 | unit Producer;
|
---|
2 |
|
---|
3 | interface
|
---|
4 |
|
---|
5 | uses
|
---|
6 | SourceCodePascal, Classes, SysUtils, StrUtils, Generics.Collections, Process,
|
---|
7 | FileUtil, Forms;
|
---|
8 |
|
---|
9 | type
|
---|
10 |
|
---|
11 | TWriteTargetEvent = function (Name: string; const Code: string): Boolean of object;
|
---|
12 | TStringEvent = procedure (Value: string) of object;
|
---|
13 |
|
---|
14 | { TProducer }
|
---|
15 |
|
---|
16 | TProducer = class
|
---|
17 | private
|
---|
18 | FOnProcessOutput: TStringEvent;
|
---|
19 | FOnWriteTarget: TWriteTargetEvent;
|
---|
20 | public
|
---|
21 | Process: TProcess;
|
---|
22 | TextSource: TStringList;
|
---|
23 | IndentationLength: Integer;
|
---|
24 | Indentation: Integer;
|
---|
25 | CompilerPath: string;
|
---|
26 | CompilerParameters: string;
|
---|
27 | procedure Emit(AText: string);
|
---|
28 | procedure EmitLn(AText: string = '');
|
---|
29 | procedure AssignToStringList(Target: TStringList); virtual; abstract;
|
---|
30 | procedure Produce(Module: TSourceModule); virtual; abstract;
|
---|
31 | procedure ExternalExecute(CommandLine: string);
|
---|
32 | constructor Create;
|
---|
33 | destructor Destroy; override;
|
---|
34 | property OnWriteTarget: TWriteTargetEvent read FOnWriteTarget write FOnWriteTarget;
|
---|
35 | property OnProcessOutput: TStringEvent read FOnProcessOutput write FOnProcessOutput;
|
---|
36 | end;
|
---|
37 |
|
---|
38 | implementation
|
---|
39 |
|
---|
40 | { TProducer }
|
---|
41 |
|
---|
42 | procedure TProducer.EmitLn(AText: string = '');
|
---|
43 | begin
|
---|
44 | Emit(AText);
|
---|
45 | TextSource.Add('');
|
---|
46 | end;
|
---|
47 |
|
---|
48 | procedure TProducer.ExternalExecute(CommandLine: string);
|
---|
49 | var
|
---|
50 | Buffer: string;
|
---|
51 | Count: Integer;
|
---|
52 | Text: string;
|
---|
53 | Line: string;
|
---|
54 | begin
|
---|
55 | if not FileExists(CompilerPath) then Exit;
|
---|
56 | Text := '';
|
---|
57 | try
|
---|
58 | Process := TProcess.Create(nil);
|
---|
59 | //if Path <> '' then
|
---|
60 | // Process.CurrentDirectory := Path;
|
---|
61 | //Path := '';
|
---|
62 | //if Environment <> '' then
|
---|
63 | // Process.Environment.Text := Environment;
|
---|
64 | //Environment := '';
|
---|
65 | Process.CommandLine := CommandLine;
|
---|
66 | Process.Options := [poUsePipes, poNoConsole];
|
---|
67 | Process.Execute;
|
---|
68 | Application.ProcessMessages;
|
---|
69 | while Process.Running or (Process.Output.NumBytesAvailable > 0) or
|
---|
70 | (Process.Stderr.NumBytesAvailable > 0) do
|
---|
71 | begin
|
---|
72 | if Process.Output.NumBytesAvailable > 0 then begin
|
---|
73 | SetLength(Buffer, 1000);
|
---|
74 | Count := Process.Output.Read(Buffer[1], Length(Buffer));
|
---|
75 | SetLength(Buffer, Count);
|
---|
76 | Text := Text + Buffer;
|
---|
77 | while Pos(LineEnding, Text) > 0 do begin
|
---|
78 | Line := Copy(Text, 1, Pos(LineEnding, Text) - 1);
|
---|
79 | Delete(Text, 1, Length(Line) + Length(LineEnding));
|
---|
80 | if Assigned(FOnProcessOutput) then
|
---|
81 | FOnProcessOutput(Line);
|
---|
82 | end;
|
---|
83 | end;
|
---|
84 |
|
---|
85 | if Process.Stderr.NumBytesAvailable > 0 then begin
|
---|
86 | SetLength(Buffer, 1000);
|
---|
87 | Count := Process.Stderr.Read(Buffer[1], Length(Buffer));
|
---|
88 | SetLength(Buffer, Count);
|
---|
89 | Text := Text + Buffer;
|
---|
90 | while Pos(LineEnding, Text) > 0 do begin
|
---|
91 | Line := Copy(Text, 1, Pos(LineEnding, Text) - 1);
|
---|
92 | Delete(Text, 1, Length(Line) + Length(LineEnding));
|
---|
93 | if Assigned(FOnProcessOutput) then
|
---|
94 | FOnProcessOutput(Line);
|
---|
95 | end;
|
---|
96 | end;
|
---|
97 | Sleep(10);
|
---|
98 | Application.ProcessMessages;
|
---|
99 | end;
|
---|
100 | finally
|
---|
101 | if Assigned(FOnProcessOutput) then
|
---|
102 | FOnProcessOutput(Text);
|
---|
103 | FreeAndNil(Process);
|
---|
104 | end;
|
---|
105 | end;
|
---|
106 |
|
---|
107 | constructor TProducer.Create;
|
---|
108 | begin
|
---|
109 | TextSource := TStringList.Create;
|
---|
110 | IndentationLength := 2;
|
---|
111 | CompilerParameters := '%0:s';
|
---|
112 | end;
|
---|
113 |
|
---|
114 | destructor TProducer.Destroy;
|
---|
115 | begin
|
---|
116 | TextSource.Free;
|
---|
117 | inherited Destroy;
|
---|
118 | end;
|
---|
119 |
|
---|
120 | procedure TProducer.Emit(AText: string);
|
---|
121 | begin
|
---|
122 | with TextSource do begin
|
---|
123 | if Count = 0 then Add('');
|
---|
124 | if Strings[Count - 1] = '' then
|
---|
125 | Strings[Count - 1] := Strings[Count - 1] + DupeString(' ', IndentationLength * Indentation);
|
---|
126 | Strings[Count - 1] := Strings[Count - 1] + AText;
|
---|
127 | end;
|
---|
128 | end;
|
---|
129 |
|
---|
130 | end.
|
---|