-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmacro.pas
373 lines (301 loc) · 12.8 KB
/
macro.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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
unit macro;
{$mode objfpc}{$H+}
//{$Define DEBUGMODE}
interface
uses
Classes, SysUtils, mik_asm_compiller, asm_comp;// SynHighlighterAny;
const
macr_file_addr='./macro.masm'; //расположение на физ носителе
type
{макросы}
TMacroPtr=^TMikMacros;
TMikMacros=record
name:TVarName;
prm:string;
body:Ansistring;
MemTablePtr:TLVarTablePTR; //указатель на табл
NextMacros:TMacroPtr;
end;
TMacrosList=object
private
First,Last:TMacroPtr;
Fcount:byte; //до 255 макросов....
public
property count:byte read Fcount;
procedure ini_MacroList;
procedure clean_macroList;
function getPtrToMacros(name:TVarName):TMacroPtr;
function AddNewMacros(name:TVarName; prm:string; var code:ansistring):boolean;
procedure reload_macro_list;
procedure CleanMemTables;
end;
var
macros_list:TMacrosList;
//procedure reload_macro_list;
function proc_macro_code(call_prm:string; var table:TLVarTablePTR; var error_code:byte):Ansistring; //EXPEREMENTAL 30.03.16
implementation
{UTILS}
procedure TMacrosList.ini_MacroList;
begin
first:=nil;
last:=nil;
Fcount:=0;
end;
procedure TMacrosList.clean_macroList;
var
wrk_ptr:TMacroPtr;
begin
with macros_list do
while (First<>nil) do
begin
wrk_ptr:=First;
first:=first^.nextMacros;
dispose(wrk_ptr);
end;
ini_MacroList;
end;
function TMacrosList.getPtrToMacros(name:TVarName):TMacroPtr; //NEW 29.03.16
var
wrk_ptr:TMacroPtr;
begin
wrk_ptr:=macros_list.First;
while ((wrk_ptr<>nil) and (wrk_ptr^.name<>name)) do
wrk_ptr:=wrk_ptr^.NextMacros;
//return
getPtrToMacros:=wrk_ptr;
end;
function TMacrosList.AddNewMacros(name:TVarName; prm:string; var code:ansistring):boolean; //код до max_macro_code_len
var
new_el:TMacroPtr;
begin
result:=false;
name:=Uppercase(name);
prm:=Uppercase(prm);
if (macros_list.count<max_macros_count) then
with macros_list do
begin
//поиск
if (getPtrToMacros(name)=nil) then
begin
new(new_el);
new_el^.NextMacros:=nil;
new_el^.name:=name;
new_el^.prm:=prm;
new_el^.body:=code;
new_el^.MemTablePtr:=nil;
//new_el^.id:=count;
{Задать маски переменным....."каждый уникален с рождения" }
// SetMask2Vars(new_el^.code, genMask(new_el^.id, false));
//линковка
if (last<>nil) then last^.NextMacros:=new_el
else first:=new_el;
last:=new_el;
//finalization
inc(Fcount);
result:=true;
//добавим его в список "известных макросов редактору"
asm_code.ASM_style.Constants.Add(name);
end;
end;
end;
function check_call_prm(src:string):boolean; //25.03.16 (процедуры и ф-ии)
var
prm:string;
begin
check_call_prm:=true;
if src[length(src)]=',' then check_call_prm:=false //фикс лишней запятой в конце
else
if length(src)>0 then
//ищем все переменные разделенные запятыми
while (check_call_prm) and (length(src)>0) do
begin
cut_str_value(src,prm, ',');
delete(src,1,1);
check_call_prm:=check_prm(trim(prm))=0; //должен быть = 0
end;
end;
procedure TMacrosList.reload_macro_list;
var
MacrFile:Text;
Read_line,sub_line:string;
ext_code:byte;
state:(head,t_body,b_body);
m_name,prm:string;
code:ansistring;
begin
//ini
clean_macroList;
{GUI!!}
//asm_code.gui_macros_list.Clear;
state:=head;
ext_code:=0;
asm_code.MacroGUITable.RowCount:=1;
asm_code.ASM_style.Constants.Clear;
//скан файла macr_file_addr:string; на макросы
if FileExists(macr_file_addr) then
begin
assignFile(MacrFile, macr_file_addr);
reset(MacrFile);
while (not EOF(MacrFile)) do
BEGIN
//читай строку и обрабатывай
readln(MacrFile, Read_line);
trim(read_line);
while length(Read_line)>0 do
BEGIN
//set state
if pos('macro ',lowercase(read_line))=1 then state:=head //разве в нижнем только?
else
if pos('{',read_line)=1 then begin state:=t_body; code:=''; delete(Read_line,1,1); end
else
if pos('}',read_line)=1 then begin state:=b_body; delete(Read_line,1,1); end;
//do this...
case State of
HEAD:
begin
//удалим "macro" и получим имя и параметры
delete(read_line,1,6);
cut_str_value(read_line,sub_line,'{');
sub_line:=trim(sub_line);
//получено: |<m_name>[(prms)]|
cut_str_value(sub_line,m_name,'('); //имя
m_name:=trim(m_name);
//что осталось есть prm |( smb )|
delete(sub_line,1,1);
delete(sub_line,length(sub_line),1);
prm:=trim(sub_line);
end;
T_BODY:
begin
//найден { - начало тела макроса
cut_str_value(read_line,sub_line,'}');
code:=code+' '+trim(delete_comments(sub_line)); //подравняй и удали комментраии
end;
B_BODY:
begin
if (check_prm(m_name)<>0) then ext_code:=11
else
if (check_call_prm(prm)=false) then ext_code:=12
else
if (trim(code)='') then ext_code:=13;
if (ext_code=0) then //если коррекны имя и параметры, тело макроса не пусто!...
gen_code_line(code, code, ext_code); //собери код -> error 0/1
if (ext_code=0) then
if (AddNewMacros(m_name,prm,code)=false) then ext_code:=14;
{проверку на существование выполнит добавляюшая п/программа}
//-----------пишем лог----------------
with asm_code.MacroGUITable do
begin
RowCount:=RowCount+1;
Cells[1,RowCount-1]:=Uppercase(m_name+' ('+prm+')');
case ext_code of
0:Cells[2,RowCount-1]:='Загружен. Синтаксических ошибок не обнаружено.';
11:Cells[2,RowCount-1]:='Ошибка: Неверно имя макроса (недопустимое имя идентификатора)';
12:Cells[2,RowCount-1]:='Ошибка: Синтаксическая ошибка при описании формальных параметров';
13:Cells[2,RowCount-1]:='Ошибка: Пустое тело макроса';
1:Cells[2,RowCount-1]:='Ошибка: Синтаксическая ошибка в теле макроса';
14:Cells[2,RowCount-1]:='Ошибка: Макрос '+m_name+' уже был ранее зарегестрирован';
end;
end;
// asm_code.gui_macros_list.Items.Add(Uppercase(m_name+' ('+prm+')'));
{else в GUI сообщение!!!!}
end;
end; //case end
END; //line loop
end; //main loop
end;
end; //procedure end
function proc_macro_code(call_prm:string; var table:TLVarTablePTR; var error_code:byte):Ansistring; {21.10.16 NOT TESTED}
var
macr_prm:string;
code_line:string;
//для замены
from_prm,to_prm:string;
GVar_id:word;
macro_ptr:TMacroPtr; //указатель на макрос
begin
{$IFDEF DEBUGMODE}
writeln(' ****ЗАГРУЗКА proc_macro_code');
{$ENDIF}
{err 4 - несоотв параметров
err 5 - макрос не найден
err 0 - all ok }
{ini}
proc_macro_code:='';
table:=nil;
//дай имя макроса #<...>
delete(call_prm,1,pos('#',call_prm)); //drop #
cut_str_value(call_prm,macr_prm, ' '); //в macr_prm имя макроса...
call_prm:=trim(call_prm);
{$IFDEF DEBUGMODE}
writeln('Ищу макрос=',macr_prm+'|');
{$ENDIF}
//дай макрос
macro_ptr:=macros_list.getPtrToMacros(macr_prm);
if (macro_ptr=nil) then error_code:=5 //не найден
else
with macro_ptr^ do
begin
{таблица есть?}
if (MemTablePtr=nil) then
begin
new(MemTablePtr);
MemTablePtr^.ini;
end
else
begin
{иначе это не первое исп-е, чистим temp}
MemTablePtr^.clear(temponary);
end;
{обязательно дай указатель на таблицу!}
table:=MemTablePtr;
code_line:=body; //получим код макроса
macr_prm:=prm; //получим параметрs от макроса
{$IFDEF DEBUGMODE}
writeln('*Найден: ',code_line, '**с параметрами=',macr_prm);
{$ENDIF}
{занести адреса переменных в temp таблицы, инф из стека...}
REPEAT
cut_str_value(macr_prm,to_prm,','); //дай параметры
cut_str_value(call_prm,from_prm,','); //дай из "кода"
delete(macr_prm,1,1);
delete(call_prm,1,1);
{регистр сохранить!}
from_prm:=trim(from_prm);
to_prm:=trim(to_prm);
{найди переменную FALSE оправдан?????????? }
if (Try2RegVar(from_prm, false, GVar_id)=0)
then begin
MemTablePtr^.add(to_prm, GVar_id, temponary); //только temponary
{$IFDEF DEBUGMODE}
writeln(Debugcode,' запись временной пер-й: ',to_prm,' с адресом=',GVar_id);
{$ENDIF}
end;
UNTIL ((length(to_prm)=0) or (length(from_prm)=0));
{Заменили, теперь:
***********************check**************************
все ок = длинны обоих параметров по окончании цикла = 0}
if (length(to_prm)+length(from_prm)=0) then error_code:=0
else error_code:=4; //несоответствие кол-ва переменных
{finalization}
proc_macro_code:=code_line;
{$IFDEF DEBUGMODE}
writeln('RETURNED=',proc_macro_code);
{$ENDIF}
end;
end;
procedure TMacrosList.CleanMemTables;
var
macros:TMacroPtr;
begin
macros:=First;
while macros<>nil do
begin
if (macros^.MemTablePtr<>nil) then
macros^.MemTablePtr^.ClearAll;
macros:=macros^.NextMacros;
end;
end;
begin
macros_list.ini_MacroList;
end.