This repository has been archived by the owner on Oct 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
uexternalvariables.pas
185 lines (149 loc) · 4.39 KB
/
uexternalvariables.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
unit uExternalVariables;
{$mode objfpc}{$H+}
{$modeswitch advancedrecords}
interface
uses
Classes, SysUtils, uObjects, uContainers;
type
TExtVarInfo = class
public
BelongsToProgram: string;
VariableName: string;
constructor Create(const InProgram, Name: string);
end;
type
{ TUsedProgram }
TUsedProgram = record
Timestamp: longint;
Name: string;
FullPath: string;
Variables: TVariablesTable;
class operator = (a, b: TUsedProgram): Boolean;
procedure Free;
end;
type
TUsedProgramsList = specialize TGenericHashTable<string, TUsedProgram>;
function UsedProgram(const ProgramName, ProgramFullPath: string): TUsedProgram;
procedure FetchUsedPrograms(Code: TStrings; const CurrentDir: string; var Programs: TUsedProgramsList);
procedure ProcessUsedProgram(var TheProgram: TUsedProgram);
implementation
uses uSettings, regexpr, Forms, FileUtil, uVariableFetcher;
var
UsedProgramRegex: TRegexpr;
function UsedProgram(const ProgramName, ProgramFullPath: string): TUsedProgram;
var
TheFile: longint;
begin
TheFile := -1;
try
with Result do
begin
Name := ProgramName;
FullPath := ProgramFullPath;
TheFile := FileOpen(ProgramFullPath, fmOpenRead + fmShareDenyNone);
Variables := TVariablesTable.Create;
Variables.Sorted := True;
Variables.OnCompare := @KeyCompare;
end;
finally
if TheFile > 0 then
FileClose(TheFile);
end;
end;
function UsedProgramDummy(const ProgramName: string): TUsedProgram;
begin
Result.Name := ProgramName;
end;
function CheckExists(const ProgramName, CurrentDir: string; out ActualPath: string): boolean;
var
Aux: string;
begin
Result := False;
Aux := ChangeFileExt(Settings.GetValue('kspfolder', '') + PathDelim + 'Plugins' + PathDelim + 'PluginData' +
PathDelim + 'Archive' + PathDelim + ProgramName, '.txt');
if FileExists(Aux) then
begin
ActualPath := Aux;
Result := True;
end
else if FileExists(ChangeFileExt(CurrentDir + PathDelim + ProgramName, '.txt')) then
begin
ActualPath := ChangeFileExt(CurrentDir + PathDelim + ProgramName, '.txt');
Result := True;
end;
end;
procedure FetchUsedPrograms(Code: TStrings; const CurrentDir: string; var Programs: TUsedProgramsList);
var
Line, ActualPath: string;
AuxList: TUsedProgramsList;
Key: string;
Aux: TUsedProgram;
begin
AuxList := TUsedProgramsList.Create;
for Line in Code do
if UsedProgramRegex.Exec(Line) then
if CheckExists(UsedProgramRegex.Match[2], CurrentDir, ActualPath) then
AuxList[UsedProgramRegex.Match[2]] := UsedProgram(UsedProgramRegex.Match[2], ActualPath);
AuxList.PrepareIterator;
while AuxList.GetNextKey(Key) do
begin
if Programs.Contains(Key) then
begin
Aux := Programs[Key];
Aux.Variables := TVariablesTable.Create;
Aux.Variables.Assign(Programs[Key].Variables);
AuxList[Key] := Aux;
end;
end;
Programs.Clear;
Programs.AddFrom(AuxList);
Application.ProcessMessages;
end;
procedure ProcessUsedProgram(var TheProgram: TUsedProgram);
var TheFile: longint;
Code: TStrings;
Stream: TFileStream;
begin
TheFile := -1;
Code := TStringList.Create;
Stream := nil;
try
try
TheFile := FileOpen(TheProgram.FullPath, fmOpenRead or fmShareDenyNone);
if TheProgram.Timestamp <> FileGetDate(TheFile) then
begin
Stream := TFileStream.Create(Utf8ToSys(TheProgram.FullPath), fmOpenRead or fmShareDenyNone);
Code.LoadFromStream(Stream);
FetchVariables(Code, TheProgram.Variables, True);
TheProgram.Timestamp := FileGetDate(TheFile);
end;
except
end;
finally
if Assigned(Stream) then
Stream.Free;
Code.Free;
if TheFile > 0 then
FileClose(TheFile);
end;
end;
class operator TUsedProgram.=(a, b: TUsedProgram): Boolean;
begin
Result := UpperCase(a.Name) = UpperCase(b.Name);
end;
procedure TUsedProgram.Free;
begin
Variables.Free;
end;
{ ExtVarInfo }
constructor TExtVarInfo.Create(const InProgram, Name: string);
begin
BelongsToProgram := InProgram;
VariableName := Name;
end;
initialization
UsedProgramRegex := TRegExpr.Create;
UsedProgramRegex.Expression := '(?i)(run\s)([a-z,0-9_]+)';
finalization
UsedProgramRegex.Free;
end.