Rev 1846 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1846 | yogev_ezra | 1 | byte Directives={ |
2 | "IF","ELSE","ENDIF", // Условная компиляция |
||
3 | "INCLUDE","DEFINE", // Включение файла/Определение константы |
||
4 | "IMPORT", // Импорт из DLL по имени API |
||
5 | "IMPORTN", // Импорт из DLL по номеру API |
||
6 | "MAP", // Генерация MAP-файла |
||
7 | "DEBUG", // Генерация отладочной информации |
||
8 | "LIST", // Выдача ASM-листинга |
||
9 | "DLL", // Генерация DLL-файла |
||
10 | "DB","DW","DD", // Типы переменных |
||
11 | "BYTE","CHAR","WORD","SHORT","DWORD","INT", |
||
12 | "ENUM", // Нумерованные константы |
||
13 | "STRUC", // Определение структуры |
||
14 | "CYCLE","RETURN", |
||
15 | "WHILE","DO","INLINE", |
||
16 | "CONTINUE","BREAK", |
||
17 | "DOCASE","CASE","DEFAULT", |
||
18 | "CARRYFLAG","EXTRACT","FROM", |
||
19 | "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW", |
||
20 | "ZEROFLAG","NOTZEROFLAG",_END}; |
||
21 | // ----- Для tokens, НЕ обрабатываемых через таблицу переключателей |
||
22 | EMPTY() |
||
23 | { |
||
24 | WRITESTR(#string); |
||
25 | WRITESTR("-ToDo\n"); |
||
26 | NextTok(); |
||
27 | } |
||
28 | |||
29 | // ---- Возвращает адрес из Jmp_.... |
||
30 | dword GetDirAddr(dword table,num) |
||
31 | { |
||
32 | EAX=num<<2+table; |
||
33 | EAX=DSDWORD[EAX]; |
||
34 | } |
||
35 | |||
36 | // ----- Директива #define |
||
37 | DirDefine() |
||
38 | byte holdid[IDLENGTH]; |
||
39 | dword next; |
||
40 | { |
||
41 | next=1; |
||
42 | NextTok(); |
||
43 | if(tok==tk_id){ |
||
44 | lstrcpyA(#holdid,#string); // Имя константы |
||
45 | NextTok(); |
||
46 | IF(tok==tk_eof) unexpectedeof(); |
||
47 | ELSE IF(tok==tk_number){ |
||
48 | AddConstToTree(#holdid,DoConstLongMath()); next = 0; |
||
49 | } |
||
50 | ELSE IF(tok==tk_minus){ |
||
51 | IF(tok2==tk_number) { |
||
52 | AddConstToTree(#holdid,DoConstLongMath()); |
||
53 | next = 0; |
||
54 | } |
||
55 | } |
||
56 | ELSE IF(tok==tk_undefproc){ |
||
57 | tok = tk_id; AddToTree(#holdid); |
||
58 | } |
||
59 | ELSE AddToTree(#holdid); |
||
60 | } |
||
61 | ELSE idexpected(); |
||
62 | IF(next)NextTok(); |
||
63 | } |
||
64 | |||
65 | // -- #enum |
||
66 | DirEnum() |
||
67 | dword counter; |
||
68 | byte holdid[IDLENGTH]; |
||
69 | { |
||
70 | counter=0; |
||
71 | NextTok(); |
||
72 | IF(tok!=tk_openbrace)expected('{'); |
||
73 | for(;;){ |
||
74 | NextTok(); |
||
75 | IF(tok==tk_id){ |
||
76 | lstrcpyA(#holdid,#string); |
||
77 | IF( tok2 == tk_assign ){ |
||
78 | NextTok(); NextTok(); |
||
79 | IF(tok==tk_number)counter=DoConstLongMath(); |
||
80 | ELSE numexpected(); |
||
81 | } |
||
82 | AddConstToTree(#holdid,counter); |
||
83 | counter++; |
||
84 | CONTINUE; |
||
85 | } |
||
86 | IF(tok==tk_comma)CONTINUE; |
||
87 | IF(tok==tk_semicolon)BREAK; |
||
88 | } |
||
89 | NextTok(); |
||
90 | } |
||
91 | |||
92 | // Директива #import |
||
93 | DirImport() |
||
94 | { |
||
95 | NextTok(); |
||
96 | IF(tok==tk_string)GetImport(1); // import по имени API-функций |
||
97 | ELSE stringexpected(); |
||
98 | NextTok(); |
||
99 | } |
||
100 | |||
101 | // Директива #importN |
||
102 | DirImportN() |
||
103 | { |
||
104 | NextTok(); |
||
105 | IF(tok==tk_string)GetImport(0); // import по имени API-функций |
||
106 | ELSE stringexpected(); |
||
107 | NextTok(); |
||
108 | } |
||
109 | |||
110 | // ---- Импорт из DLL |
||
111 | GetImport(dword byName) |
||
112 | dword dll; |
||
113 | dword dllpos,base,export,fptr,i,nexports,nsect,delta; |
||
114 | byte path[80],name[120]; |
||
115 | dword tok0,type0,src0,post0; |
||
116 | dword number0; |
||
117 | dword ord; |
||
118 | dword pname1,pname2,j; |
||
119 | { |
||
120 | pname1 = 0; ord=0; importFlag=1; |
||
121 | IF(DLLcount>=MAXDLLS)outofmemory2(); |
||
122 | IF(SearchTree(#tok0,#type0,#src0,#post0,#string,#number0))return; // DLL уже импортирован |
||
123 | wsprintfA(#name,"%s",#string); |
||
124 | dll=_lopen(#name,0); |
||
125 | IF(dll== -1){ |
||
126 | GetSystemDirectoryA(#path,80); |
||
127 | wsprintfA(#name,"%s\\%s",#path,#string); |
||
128 | dll=_lopen(#name,0); |
||
129 | IF(dll==-1) { |
||
130 | unabletoopen(#string); |
||
131 | return; |
||
132 | } |
||
133 | } |
||
134 | nsect=0; |
||
135 | _llseek(dll,0x3c,0); _lread(dll,#fptr,4); |
||
136 | _llseek(dll,fptr+120,0); _lread(dll,#export,4); // Get export address |
||
137 | IF(export==0) { |
||
138 | wsprintfA(#mapstr,"ERROR: No export directory in file %s.\n",#string); |
||
139 | preerror(#mapstr); return; |
||
140 | } |
||
141 | _llseek(dll,fptr+6,0); _lread(dll,#nsect,2); // Number of sections |
||
142 | delta=export; |
||
143 | i=1; |
||
144 | while(i<=nsect){ |
||
145 | EAX=i; EAX--; EAX=EAX*40; EAX+=260; EAX+=fptr; // fptr+260+40*(i-1) |
||
146 | _llseek(dll,EAX,0); _lread(dll,#base,4); // RVA of section |
||
147 | IF(base<=export){ |
||
148 | EAX=export-base; |
||
149 | IF(EAX |
||
150 | delta=export-base; |
||
151 | EAX=i; EAX--; EAX=EAX*40; EAX+=268; EAX+=fptr; // fptr+268+40*(i-1) |
||
152 | _llseek(dll,EAX,0); _lread(dll,#dllpos,4); |
||
153 | } |
||
154 | } |
||
155 | i++; |
||
156 | } |
||
157 | dllpos = dllpos + delta; // filepos for export directory table |
||
158 | delta = dllpos - export; |
||
159 | _llseek(dll,dllpos+24,0); _lread(dll,#nexports,4); // number of entries for export |
||
160 | _llseek(dll,dllpos+32,0); _lread(dll,#base,4); // address of export name pointer table |
||
161 | _llseek(dll,dllpos+36,0); _lread(dll,#fptr,4);// address of Ordinal Table |
||
162 | base=base+delta; fptr=fptr+delta; |
||
163 | tok0=tok; number0=number;src0=src;type0=type;post0=post; |
||
164 | tok=tk_DLL; number=nexports;src=NULL; type=byName; post=0; modline=0; |
||
165 | AddToTree(#string); |
||
166 | EBX=DLLcount; EBX<<=2; |
||
167 | DLLlist[EBX] = treeptr; // save ptr in tree |
||
168 | tok=tk_API; type=treeptr; |
||
169 | i=0; |
||
170 | while(nexports-1>i){ |
||
171 | EAX=i; EAX<<=1; EAX+=fptr; // fptr+2*i |
||
172 | _llseek(dll,EAX,0); _lread(dll,#ord,2);// Ordinal number |
||
173 | EAX=i; EAX<<=2; EAX+=base; // base+4*i |
||
174 | _llseek(dll,EAX,0); _lread(dll,#pname1,8); // address of name |
||
175 | _llseek(dll,pname1+delta,0); _lread(dll,#string,pname2-pname1);// address of Ordinal Table |
||
176 | number=ord+1; // при загрузке используется номер на 1 больше экспортируемого из DLL |
||
177 | AddToTree(#string); |
||
178 | // SHOW(#string);SHOW("\n"); |
||
179 | i++; |
||
180 | } |
||
181 | EAX=i; EAX<<=1; EAX+=fptr; // fptr+2*i |
||
182 | _llseek(dll,EAX,0); _lread(dll,#ord,2); // Ordinal number |
||
183 | j=0; |
||
184 | for(;;){ |
||
185 | _llseek(dll,pname2+delta+j,0); EAX=j; |
||
186 | _lread(dll,#string[EAX],1); EAX=j; |
||
187 | IF(string[EAX]==0)BREAK; |
||
188 | j++; |
||
189 | } |
||
190 | number=ord+1; |
||
191 | AddToTree(#string); |
||
192 | tok=tok0; number=number0;src=src0;type=type0;post=post0; |
||
193 | _lclose(dll); |
||
194 | DLLcount++; importFlag=0; |
||
195 | } |
||
196 | |||
197 | // ----- Директива #include |
||
198 | DirInclude() |
||
199 | byte s[STRLEN],s2[STRLEN]; |
||
200 | { |
||
201 | NextTok(); |
||
202 | if(tok==tk_string) { |
||
203 | AL=cha2; |
||
204 | $PUSH EAX,linenum2,inptr2,number,tok2,tok,input,inptr,endoffile, |
||
205 | displaytokerrors,currmod; |
||
206 | lstrcpyA(#s,#string); lstrcpyA(#s2,#string2); |
||
207 | Preview(#s); |
||
208 | lstrcpyA(#string,#s); lstrcpyA(#string2,#s2); |
||
209 | $POP currmod,displaytokerrors,endoffile,inptr,input,tok,tok2,number,inptr2, |
||
210 | linenum2,EAX; |
||
211 | cha2=AL; |
||
212 | NextTok(); |
||
213 | } |
||
214 | ELSE stringexpected(); |
||
215 | } |
||
216 | |||
217 | // ----- Директива list |
||
218 | DirList() |
||
219 | { |
||
220 | IF(mapfile==0){ |
||
221 | makemapfile=1; |
||
222 | StartMapfile(); |
||
223 | } |
||
224 | list^=1; // Переключение вывода листинга |
||
225 | NextTok(); |
||
226 | } |
||
227 | |||
228 | // ----- Директива map |
||
229 | DirMap() |
||
230 | { |
||
231 | makemapfile = 1; StartMapfile(); |
||
232 | NextTok(); |
||
233 | } |
||
234 | |||
235 | // ---- Обработка глобальной переменной или процедуры с типом |
||
236 | GetProc(dword vartype) |
||
237 | dword src0,beg,count; |
||
238 | byte var_name[IDLENGTH]; |
||
239 | { |
||
240 | lstrcpyA(#var_name,#string); // Имя процедуры |
||
241 | beg=inptr2; // отметим начало описания |
||
242 | count=0; EAX=0; // ищем начало блока процедуры |
||
243 | modline=currmod<<16+linenum2; |
||
244 | for(;;){ |
||
245 | ESI> |
||
246 | $LODSB; |
||
247 | ESI> |
||
248 | cha2=AL; |
||
249 | IF(AL==0){ |
||
250 | unexpectedeof(); |
||
251 | return; |
||
252 | } |
||
253 | IF(AL==13){ // CR |
||
254 | linenum2++; // Обнаружен конец строки |
||
255 | totallines++; |
||
256 | CONTINUE; |
||
257 | } |
||
258 | IF(AL=='{'){ // список инициализации |
||
259 | count++; |
||
260 | BREAK; |
||
261 | } |
||
262 | } |
||
263 | for(;;){ |
||
264 | ESI> |
||
265 | $LODSB; |
||
266 | ESI> |
||
267 | cha2=AL; |
||
268 | IF(AL==0){ |
||
269 | unexpectedeof(); |
||
270 | break; |
||
271 | } |
||
272 | IF(AL==13){ // CR |
||
273 | linenum2++; // Обнаружен конец строки |
||
274 | totallines++; |
||
275 | } |
||
276 | else if(AL=='}'){ // блок закрыт |
||
277 | count--; |
||
278 | IF(count==0){ // конец процедуры |
||
279 | ESI> |
||
280 | $LODSB; |
||
281 | ESI> |
||
282 | cha2=AL; // замыкающая } |
||
283 | src0=LocalAlloc(0x40,inptr2-beg+2); // копируем исх.текст |
||
284 | EAX=src0; |
||
285 | DSBYTE[EAX]='('; |
||
286 | lstrcpynA(src0+1,beg,inptr2-beg); |
||
287 | tok=tk_proc; |
||
288 | type=vartype; |
||
289 | src=src0; |
||
290 | number=0; |
||
291 | post=1; |
||
292 | AddToTree(#var_name); |
||
293 | BREAK; |
||
294 | } |
||
295 | } |
||
296 | ELSE IF(AL=='{'){ // список инициализации |
||
297 | count++; |
||
298 | } |
||
299 | } |
||
300 | NextTok(); |
||
301 | } |
||
302 | |||
303 | // ---- Обработка глобальной переменной или процедуры с типом |
||
304 | GetVar(dword vartype) |
||
305 | dword src0,beg,end,count,size; |
||
306 | byte var_name[IDLENGTH]; |
||
307 | { |
||
308 | beg=inptr; |
||
309 | modline=0; // отметим начало описания |
||
310 | NextTok(); |
||
311 | IF(tok2==tk_openbracket){ // Объявление функции: type FunctionName(...) |
||
312 | GetProc(vartype); |
||
313 | return; |
||
314 | } |
||
315 | for(;;){ // Объявление переменной |
||
316 | IF(tok==tk_semicolon){ // Конец определения переменной |
||
317 | tok=tk_var; |
||
318 | type=vartype; |
||
319 | src=src0; |
||
320 | number=0; |
||
321 | post=1; |
||
322 | AddToTree(#var_name); |
||
323 | break; |
||
324 | } |
||
325 | IF(tok==tk_comma){ // список переменных |
||
326 | tok=tk_var; |
||
327 | type=vartype; |
||
328 | src=src0; |
||
329 | number=0; |
||
330 | post=1; |
||
331 | AddToTree(#var_name); |
||
332 | NextTok(); |
||
333 | } |
||
334 | else IF(tok==tk_id){ // tk_id |
||
335 | src0=NULL; |
||
336 | beg=inptr2; |
||
337 | size=0; |
||
338 | lstrcpyA(#var_name,#string); // Имя переменной |
||
339 | number=0; |
||
340 | tok=tk_var; |
||
341 | type=vartype; |
||
342 | post=1; |
||
343 | NextTok(); |
||
344 | } |
||
345 | else if(tok==tk_assign)||(tok==tk_openblock){ |
||
346 | inptr2--; |
||
347 | count=0; |
||
348 | EAX=0; |
||
349 | for(;;){ |
||
350 | ESI> |
||
351 | $LODSB; |
||
352 | ESI> |
||
353 | cha2=AL; |
||
354 | IF(AL==0){ |
||
355 | unexpectedeof(); |
||
356 | break; |
||
357 | } |
||
358 | IF(AL=='"'){ |
||
359 | ESI> |
||
360 | do{ |
||
361 | $LODSB; |
||
362 | }while(AL!='"'); |
||
363 | ESI> |
||
364 | cha2=AL; |
||
365 | } |
||
366 | else IF(AL==',')||(AL==';'){ |
||
367 | IF(count==0){ |
||
368 | end=inptr2; |
||
369 | src0 = LocalAlloc(0x40,end-beg+2); |
||
370 | IF(size){ |
||
371 | EAX=src0; |
||
372 | DSBYTE[EAX]='['; |
||
373 | lstrcpynA(src0+1,beg,end-beg); |
||
374 | } |
||
375 | ELSE lstrcpynA(src0,beg,end-beg); |
||
376 | modline=currmod<<16+linenumber; |
||
377 | BREAK; |
||
378 | } |
||
379 | } |
||
380 | ELSE IF(AL=='}'){ // список закончен |
||
381 | count--; |
||
382 | } |
||
383 | ELSE IF(AL=='{'){ // список инициализации |
||
384 | count++; |
||
385 | } |
||
386 | IF(AL==']'){ // размерность |
||
387 | size++; |
||
388 | } |
||
389 | } |
||
390 | NextTok(); |
||
391 | } |
||
392 | } |
||
393 | NextTok(); |
||
394 | } |
||
395 | |||
396 | // ---- Объявление типа данных |
||
397 | CmdByte() |
||
398 | { |
||
399 | GetVar(tk_byte); |
||
400 | } |
||
401 | |||
402 | CmdChar() |
||
403 | { |
||
404 | GetVar(tk_char); |
||
405 | } |
||
406 | |||
407 | CmdWord() |
||
408 | { |
||
409 | GetVar(tk_word); |
||
410 | } |
||
411 | |||
412 | CmdShort() |
||
413 | { |
||
414 | GetVar(tk_short); |
||
415 | } |
||
416 | |||
417 | CmdDword() |
||
418 | { |
||
419 | GetVar(tk_dword); |
||
420 | } |
||
421 | |||
422 | CmdInt() |
||
423 | { |
||
424 | GetVar(tk_int); |
||
425 | } |
||
426 | |||
427 | // ---- break; |
||
428 | CmdBreak() |
||
429 | { |
||
430 | wsprintfA(#mapstr,"jmp @L%d",endlabel); |
||
431 | Asm(#mapstr); |
||
432 | NextSemiNext(); |
||
433 | } |
||
434 | |||
435 | // ---- case(Cond) ... |
||
436 | CmdCase() |
||
437 | dword loclabel; |
||
438 | { |
||
439 | NextTok(); |
||
440 | expecting(tk_openbracket); |
||
441 | loclabel=label; |
||
442 | label++; |
||
443 | relation=0; |
||
444 | if(tok==tk_command){ |
||
445 | GetDirAddr(#Jmp_Commands,number); |
||
446 | IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",loclabel); |
||
447 | else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",loclabel); |
||
448 | ELSE IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",loclabel); |
||
449 | ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",loclabel); |
||
450 | ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",loclabel); |
||
451 | ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",loclabel); |
||
452 | NextTok(); |
||
453 | } |
||
454 | ELSE{ |
||
455 | IF(Expression("eax",tk_reg,tk_dword))wsprintfA(loclabel,"test eax,eax;jnz @L%d",#mapstr); |
||
456 | ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",loclabel); |
||
457 | } |
||
458 | Asm(#mapstr); |
||
459 | expecting(tk_closebracket); |
||
460 | DoCommand(); |
||
461 | wsprintfA(#mapstr,"jmp @L%d",endlabel); |
||
462 | Asm(#mapstr); |
||
463 | wsprintfA(#mapstr,"@L%d:",loclabel); |
||
464 | Asm(#mapstr); |
||
465 | } |
||
466 | |||
467 | // ---- continue; |
||
468 | CmdContinue() |
||
469 | { |
||
470 | wsprintfA(#mapstr,"jmp @L%d",startlabel); |
||
471 | Asm(#mapstr); NextSemiNext(); |
||
472 | } |
||
473 | |||
474 | // ---- cycle(Var) ... |
||
475 | CmdCycle() |
||
476 | byte varName[2*IDLENGTH]; |
||
477 | { |
||
478 | NextTok(); |
||
479 | expecting(tk_openbracket); |
||
480 | $PUSH startlabel,endlabel; |
||
481 | startlabel=label; |
||
482 | label++; |
||
483 | endlabel=label; |
||
484 | label++; |
||
485 | relation=0; |
||
486 | wsprintfA(#mapstr,"@L%d:",startlabel); |
||
487 | Asm(#mapstr); |
||
488 | GetVarname(#varName); |
||
489 | NextTok(); |
||
490 | expecting(tk_closebracket); |
||
491 | DoCommand(); |
||
492 | IF(varName[0]==0){ // Счетчик цикла отсутствует - бесконечный цикл |
||
493 | wsprintfA(#mapstr,"jmp @L%d",startlabel); |
||
494 | } |
||
495 | ELSE{ |
||
496 | wsprintfA(#mapstr,"dec %s;jnz @L%d",#varName,startlabel); |
||
497 | } |
||
498 | Asm(#mapstr); |
||
499 | wsprintfA(#mapstr,"@L%d:",endlabel); |
||
500 | Asm(#mapstr); |
||
501 | $POP endlabel,startlabel; |
||
502 | } |
||
503 | |||
504 | // ---- Флаги условий в if |
||
505 | CmdCarryFlag() |
||
506 | { |
||
507 | CmdNotCarryFlag: |
||
508 | CmdZeroFlag: |
||
509 | CmdNotZeroFlag: |
||
510 | CmdOverflow: |
||
511 | CmdNotOverflow: |
||
512 | } |
||
513 | // ---- ... else ... |
||
514 | CmdElse() |
||
515 | { |
||
516 | } |
||
517 | |||
518 | // ---- Объявление нумерованных констант |
||
519 | CmdEnum() |
||
520 | dword counter; |
||
521 | byte holdid[IDLENGTH]; |
||
522 | { |
||
523 | counter=0; |
||
524 | NextTok(); |
||
525 | expecting(tk_openbrace); |
||
526 | for(;;){ |
||
527 | IF(tok==tk_eof)unexpectedeof(); |
||
528 | ELSE IF(tok==tk_comma)NextTok(); |
||
529 | ELSE IF(tok==tk_closebrace)BREAK; |
||
530 | ELSE IF(tok==tk_id){ |
||
531 | lstrcpyA(#holdid,#string); |
||
532 | IF(tok2==tk_assign ){ |
||
533 | NextTok(); |
||
534 | NextTok(); |
||
535 | IF(tok==tk_number)counter=DoConstLongMath(); |
||
536 | ELSE numexpected(); |
||
537 | } |
||
538 | AddConstToTree(#holdid,counter); |
||
539 | counter++; |
||
540 | NextTok(); |
||
541 | } |
||
542 | ELSE{ |
||
543 | idexpected(); |
||
544 | NextTok(); |
||
545 | } |
||
546 | } |
||
547 | expecting(tk_closebrace); |
||
548 | SemiNext(); |
||
549 | } |
||
550 | |||
551 | // ---- while(Cond) ... |
||
552 | CmdWhile() |
||
553 | { |
||
554 | NextTok(); |
||
555 | expecting(tk_openbracket); |
||
556 | $PUSH startlabel,endlabel; |
||
557 | startlabel=label; |
||
558 | label++; |
||
559 | endlabel=label; |
||
560 | label++; |
||
561 | relation=0; |
||
562 | wsprintfA(#mapstr,"@L%d:",startlabel); |
||
563 | Asm(#mapstr); |
||
564 | if(tok==tk_command){ |
||
565 | GetDirAddr(#Jmp_Commands,number); |
||
566 | IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",endlabel); |
||
567 | else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",endlabel); |
||
568 | else IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",endlabel); |
||
569 | ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",endlabel); |
||
570 | ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",endlabel); |
||
571 | ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",endlabel); |
||
572 | NextTok(); |
||
573 | } |
||
574 | ELSE{ |
||
575 | IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jnz @L%d",endlabel); |
||
576 | ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",endlabel); |
||
577 | } |
||
578 | Asm(#mapstr); |
||
579 | expecting(tk_closebracket); |
||
580 | DoCommand(); |
||
581 | wsprintfA(#mapstr,"jmp @L%d",startlabel); |
||
582 | Asm(#mapstr); |
||
583 | wsprintfA(#mapstr,"@L%d:",endlabel); |
||
584 | Asm(#mapstr); |
||
585 | $POP endlabel,startlabel; |
||
586 | } |
||
587 | |||
588 | // ---- default |
||
589 | CmdDefault() |
||
590 | { |
||
591 | NextTok(); |
||
592 | DoCommand(); |
||
593 | } |
||
594 | |||
595 | CmdDb() |
||
596 | { |
||
597 | NextTok(); |
||
598 | for(;;){ |
||
599 | IF(tok==tk_number)OP(byte DoConstLongMath()); |
||
600 | ELSE IF(tok==tk_string ){ |
||
601 | ECX=number; |
||
602 | EDX=#string; |
||
603 | loop(ECX){ |
||
604 | OP(byte DSBYTE[EDX]); |
||
605 | EDX++; |
||
606 | } |
||
607 | NextTok(); |
||
608 | } |
||
609 | ELSE IF(tok==tk_comma)NextTok(); |
||
610 | ELSE IF(tok==tk_semicolon)BREAK; |
||
611 | ELSE{ |
||
612 | numexpected(); |
||
613 | NextTok(); |
||
614 | } |
||
615 | } |
||
616 | } |
||
617 | |||
618 | CmdDd() |
||
619 | { |
||
620 | NextTok(); |
||
621 | for(;;){ |
||
622 | IF(tok==tk_number)OUTDWORD(DoConstDwordMath()); |
||
623 | ELSE IF(tok==tk_comma)NextTok(); |
||
624 | ELSE IF(tok==tk_semicolon)BREAK; |
||
625 | ELSE{ |
||
626 | numexpected(); |
||
627 | NextTok(); |
||
628 | } |
||
629 | } |
||
630 | } |
||
631 | |||
632 | CmdDw() |
||
633 | { |
||
634 | NextTok(); |
||
635 | for(;;){ |
||
636 | IF(tok==tk_number)OUTWORD(DoConstDwordMath()); |
||
637 | ELSE IF(tok==tk_comma)NextTok(); |
||
638 | ELSE IF(tok==tk_semicolon)BREAK; |
||
639 | ELSE{ |
||
640 | numexpected(); |
||
641 | NextTok(); |
||
642 | } |
||
643 | } |
||
644 | } |
||
645 | |||
646 | // ---- do ... while(Cond) |
||
647 | CmdDo() |
||
648 | { |
||
649 | NextTok(); |
||
650 | $PUSH startlabel,endlabel; |
||
651 | startlabel=label; |
||
652 | label++; |
||
653 | endlabel=label; |
||
654 | label++; |
||
655 | relation=0; |
||
656 | wsprintfA(#mapstr,"@L%d:",startlabel); |
||
657 | Asm(#mapstr); |
||
658 | DoCommand(); |
||
659 | if(tok==tk_command){ |
||
660 | if(GetDirAddr(#Jmp_Commands,number)==#CmdWhile){ |
||
661 | NextTok(); |
||
662 | expecting(tk_openbracket); |
||
663 | if(tok==tk_command){ |
||
664 | GetDirAddr(#Jmp_Commands,number); |
||
665 | IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jc @L%d",startlabel); |
||
666 | else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jnc @L%d",startlabel); |
||
667 | else IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jz @L%d",startlabel); |
||
668 | ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jnz @L%d",startlabel); |
||
669 | ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jo @L%d",startlabel); |
||
670 | ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jno @L%d",startlabel); |
||
671 | NextTok(); |
||
672 | } |
||
673 | ELSE{ |
||
674 | IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jz @L%d",startlabel); |
||
675 | ELSE wsprintfA(#mapstr,"test eax,eax;jnz @L%d",startlabel); |
||
676 | } |
||
677 | Asm(#mapstr); |
||
678 | expecting(tk_closebracket); |
||
679 | } |
||
680 | ELSE{ |
||
681 | ER: |
||
682 | preerror("'while' expected following 'do'"); |
||
683 | } |
||
684 | } |
||
685 | ELSE GOTO ER; |
||
686 | wsprintfA(#mapstr,"@L%d:",endlabel); |
||
687 | Asm(#mapstr); |
||
688 | $POP endlabel,startlabel; |
||
689 | } |
||
690 | |||
691 | // ---- docase ... |
||
692 | CmdDoCase() |
||
693 | { |
||
694 | NextTok(); |
||
695 | $PUSH startlabel,endlabel; |
||
696 | startlabel=label; |
||
697 | label++; |
||
698 | endlabel=label; |
||
699 | label++; |
||
700 | wsprintfA(#mapstr,"@L%d:",startlabel); |
||
701 | Asm(#mapstr); |
||
702 | DoCommand(); |
||
703 | wsprintfA(#mapstr,"@L%d:",endlabel); |
||
704 | Asm(#mapstr); |
||
705 | $POP endlabel,startlabel; |
||
706 | } |
||
707 | |||
708 | // ---- if(Cond) ... |
||
709 | CmdIf() |
||
710 | dword loclabel; |
||
711 | { |
||
712 | NextTok(); |
||
713 | expecting(tk_openbracket); |
||
714 | loclabel=label; |
||
715 | label++; |
||
716 | relation=0; |
||
717 | if(tok==tk_command){ |
||
718 | GetDirAddr(#Jmp_Commands,number); |
||
719 | IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",loclabel); |
||
720 | else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",loclabel); |
||
721 | ELSE IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",loclabel); |
||
722 | ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",loclabel); |
||
723 | ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",loclabel); |
||
724 | ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",loclabel); |
||
725 | NextTok(); |
||
726 | } |
||
727 | ELSE{ |
||
728 | IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jnz @L%d",loclabel); |
||
729 | ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",loclabel); |
||
730 | } |
||
731 | Asm(#mapstr); |
||
732 | expecting(tk_closebracket); |
||
733 | DoCommand(); |
||
734 | IF(tok==tk_command){ |
||
735 | IF(GetDirAddr(#Jmp_Commands,number)==#CmdElse){ |
||
736 | wsprintfA(#mapstr,"jmp @L%d;\n@L%d:",label,loclabel); |
||
737 | Asm(#mapstr); |
||
738 | loclabel=label; |
||
739 | label++; |
||
740 | NextTok(); |
||
741 | DoCommand(); |
||
742 | } |
||
743 | } |
||
744 | wsprintfA(#mapstr,"@L%d:",loclabel); |
||
745 | Asm(#mapstr); |
||
746 | } |
||
747 | |||
748 | // ---- return(Expr) |
||
749 | CmdReturn() |
||
750 | { |
||
751 | NextTok(); |
||
752 | IF(tok==tk_openbracket){ |
||
753 | NextTok(); |
||
754 | IF(tok!=tk_closebracket){ |
||
755 | IF(returntype!=tk_void)Expression("eax",tk_reg,returntype); |
||
756 | } |
||
757 | expecting(tk_closebracket); |
||
758 | } |
||
759 | LeaveProc(); |
||
760 | SemiNext(); |
||
761 | } |
||
762 | |||
763 | // ---- Объявление глобальной переменной |
||
764 | GlobalVar(dword vartype) // both initialized and unitialized combined |
||
765 | dword size,elements,ptr; |
||
766 | long i,count; |
||
767 | { |
||
768 | ptr=treeptr; |
||
769 | elements=1; |
||
770 | size = TypeSize(vartype); |
||
771 | NextTok(); |
||
772 | for(;;){ |
||
773 | IF(tok==tk_eof)goto G04; //break; |
||
774 | ELSE IF(tok==tk_semicolon)NextTok(); |
||
775 | else IF(tok==tk_assign)NextTok(); |
||
776 | else IF(tok==tk_plus)NextTok(); |
||
777 | else IF(tok==tk_openblock){ // type VarName[...] |
||
778 | NextTok(); |
||
779 | elements = DoConstLongMath(); |
||
780 | expecting(tk_closeblock); |
||
781 | } |
||
782 | else if(tok==tk_number){ // type VarName=initvalue |
||
783 | ESI=ptr; // Откорректируем ранее сделанную запись |
||
784 | DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode; |
||
785 | DSDWORD[ESI+recpost] = 0; |
||
786 | G01: |
||
787 | IF(vartype==tk_byte)i=DoConstDwordMath(); |
||
788 | ELSE IF(vartype==tk_word)i=DoConstDwordMath(); |
||
789 | ELSE IF(vartype==tk_dword)i=DoConstDwordMath(); |
||
790 | ELSE i=DoConstLongMath(); |
||
791 | count=elements; |
||
792 | loop(count){ |
||
793 | IF(size==1)OP(byte i); |
||
794 | ELSE IF(size==2)OUTWORD(i); |
||
795 | ELSE IF(size==4)OUTDWORD(i); |
||
796 | } |
||
797 | } |
||
798 | else IF(tok==tk_minus){ |
||
799 | NextTok(); |
||
800 | number=-number; |
||
801 | goto G01; |
||
802 | } |
||
803 | else IF(tok==tk_string){ |
||
804 | ESI=ptr; // Откорректируем ранее сделанную запись |
||
805 | DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode; |
||
806 | DSDWORD[ESI+recpost] = 0; |
||
807 | count = 1; |
||
808 | do{ |
||
809 | i=number; |
||
810 | EDX=#string; |
||
811 | loop(i){ |
||
812 | OP(byte DSBYTE[EDX]); |
||
813 | EDX++; |
||
814 | count++; |
||
815 | } |
||
816 | NextTok(); |
||
817 | }while(tok==tk_string); |
||
818 | OP(byte 0);// count++; |
||
819 | i=elements; |
||
820 | i-=count; |
||
821 | IF(i>0)loop(i)OP(byte 0); |
||
822 | } |
||
823 | else IF(tok==tk_from){ |
||
824 | NextTok(); |
||
1848 | yogev_ezra | 825 | WRITESTR("count = DoFrom(1);\n"); |
1846 | yogev_ezra | 826 | i=size*elements; |
827 | i-=count; |
||
828 | loop(i)OP(byte 0); |
||
829 | NextTok(); |
||
830 | } |
||
831 | else IF(tok==tk_extract){ |
||
832 | NextTok(); |
||
1848 | yogev_ezra | 833 | WRITESTR("count = DoExtract(1);\n"); |
1846 | yogev_ezra | 834 | i=size*elements; |
835 | i-=count; |
||
836 | loop(i)OP(byte 0); |
||
837 | } |
||
838 | else if(tok==tk_openbrace){ // varname={...}; |
||
839 | ESI=ptr; // Откорректируем ранее сделанную запись |
||
840 | DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode; |
||
841 | DSDWORD[ESI+recpost] = 0; |
||
842 | count = 0; |
||
843 | NextTok(); |
||
844 | for(;;){ |
||
845 | IF(tok==tk_closebrace)break; |
||
846 | ELSE IF(tok==tk_comma)NextTok(); |
||
847 | else IF(tok==tk_plus)NextTok(); |
||
848 | else IF(tok==tk_string){ |
||
849 | i=number; |
||
850 | EDX=#string; |
||
851 | loop(i){ |
||
852 | OP(DSBYTE[EDX]); |
||
853 | EDX++; |
||
854 | count++; |
||
855 | } |
||
856 | IF(tok2!=tk_plus){ |
||
857 | OP(byte 0); |
||
858 | count++; |
||
859 | } |
||
860 | NextTok(); |
||
861 | } |
||
862 | else IF(tok==tk_postnumber){ |
||
863 | SetPost(treeptr,POST_DATA); |
||
864 | OUTDWORD(number); |
||
865 | NextTok(); |
||
866 | } |
||
867 | else IF(tok==tk_number){ |
||
868 | G02: |
||
869 | IF(vartype==tk_byte)OP(byte DoConstDwordMath()); |
||
870 | ELSE IF(vartype==tk_word)OUTWORD(DoConstDwordMath()); |
||
871 | ELSE IF(vartype==tk_char)OP(byte DoConstLongMath()); |
||
872 | ELSE IF(vartype==tk_short) OUTWORD(DoConstLongMath()); |
||
873 | ELSE IF(vartype==tk_dword) OUTDWORD(DoConstDwordMath()); |
||
874 | ELSE IF(vartype==tk_int) OUTDWORD(DoConstLongMath()); |
||
875 | count++; |
||
876 | } |
||
877 | ELSE IF(tok==tk_minus){ |
||
878 | NextTok(); |
||
879 | number=-number; |
||
880 | goto G02; |
||
881 | } |
||
882 | ELSE{ |
||
883 | numexpected(); |
||
884 | NextTok(); |
||
885 | } |
||
886 | } |
||
887 | count=elements-count; |
||
888 | IF(count>0){ |
||
889 | loop(count){ |
||
890 | IF(size==1)OP(byte 0); |
||
891 | ELSE IF(size==2)OUTWORD(0); |
||
892 | ELSE IF(size==4)OUTDWORD(0); |
||
893 | } |
||
894 | } |
||
895 | } |
||
896 | ELSE{ |
||
897 | G04: |
||
898 | ESI=ptr; |
||
899 | DSDWORD[ESI+recnumber] = postsize; |
||
900 | DSDWORD[ESI+recpost] = 1; |
||
901 | postsize = elements * size + postsize; |
||
902 | BREAK; |
||
903 | } |
||
904 | } |
||
905 | } |
||
906 | |||
907 | //===== Таблица переключателей директив |
||
908 | dword Jmp_Directives={ |
||
909 | // "if","else","endif", // Условная компиляция |
||
910 | #EMPTY,#EMPTY,#EMPTY, |
||
911 | // "include","define", // Включение фа ла |
||
912 | #DirInclude,#DirDefine, |
||
913 | // "import", // Импорт из DLL |
||
914 | #DirImport, |
||
915 | // "importN", // Импорт из DLL |
||
916 | #DirImportN, |
||
917 | // "map", // Генерация MAP-файла |
||
918 | #DirMap, |
||
919 | // "debug", // Генерация отладочной информации |
||
920 | #EMPTY, |
||
921 | // "list", // Выдача ASM-листинга |
||
922 | #DirList, |
||
923 | // "dll", // Генерация DLL-файла |
||
924 | #EMPTY, |
||
925 | // "db","dw","dd", // Типы переменных |
||
926 | #EMPTY,#EMPTY,#EMPTY, |
||
927 | // "byte","char","word","short","dword","int", |
||
928 | #EMPTY,#EMPTY,#EMPTY,#EMPTY,#EMPTY,#EMPTY, |
||
929 | // "enum", // Нумерованные константы |
||
930 | #DirEnum, |
||
931 | // "struc", // Определение структуры |
||
932 | #EMPTY, |
||
933 | // "cycle","return", |
||
934 | #EMPTY,#EMPTY, |
||
935 | // "while","do","inline", |
||
936 | #EMPTY,#EMPTY,#EMPTY, |
||
937 | // "continue","break", |
||
938 | #EMPTY,#EMPTY, |
||
939 | // "docase","case","default", |
||
940 | #EMPTY,#EMPTY,#EMPTY, |
||
941 | // "CARRYFLAG","extract","from", |
||
942 | #EMPTY,#EMPTY,#EMPTY, |
||
943 | // "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW", |
||
944 | #EMPTY,#EMPTY,#EMPTY, |
||
945 | // "ZEROFLAG","NOTZEROFLAG" |
||
946 | #EMPTY,#EMPTY |
||
947 | }; |
||
948 | //===== Таблица переключателей команд |
||
949 | dword Jmp_Commands={ |
||
950 | // "if","else","endif", // Условная компиляция |
||
951 | #CmdIf,#CmdElse,#EMPTY, |
||
952 | // "include","define", // Включение фа ла |
||
953 | #EMPTY,#EMPTY, |
||
954 | // "import","importN", // Импорт из DLL |
||
955 | #EMPTY,#EMPTY, |
||
956 | // "map", // Генерация MAP-файла |
||
957 | #EMPTY, |
||
958 | // "debug", // Генерация отладочно информации |
||
959 | #EMPTY, |
||
960 | // "list", // Выдача ASM-л стинга |
||
961 | #EMPTY, |
||
962 | // "dll", // Генерация DLL-файла |
||
963 | #EMPTY, |
||
964 | // "db","dw","dd", // Типы переменных |
||
965 | #CmdDb,#CmdDw,#CmdDd, |
||
966 | // "byte","char","word","short","dword","int", |
||
967 | #CmdByte,#CmdChar,#CmdWord,#CmdShort,#CmdDword,#CmdInt, |
||
968 | // "enum", // Нумерованные константы |
||
969 | #CmdEnum, |
||
970 | // "struc", // Определение структуры |
||
971 | #EMPTY, |
||
972 | // "cycle","return", |
||
973 | #CmdCycle,#CmdReturn, |
||
974 | // "while","do","inline", |
||
975 | #CmdWhile,#CmdDo,#EMPTY, |
||
976 | // "continue","break", |
||
977 | #CmdContinue,#CmdBreak, |
||
978 | // "docase","case","default", |
||
979 | #CmdDoCase,#CmdCase,#CmdDefault, |
||
980 | // "CARRYFLAG","extract","from", |
||
981 | #CmdCarryFlag,#EMPTY,#EMPTY, |
||
982 | // "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW", |
||
983 | #CmdNotCarryFlag,#CmdNotOverflow,#CmdOverflow, |
||
984 | // "ZEROFLAG","NOTZEROFLAG" |
||
985 | #CmdZeroFlag,#CmdNotZeroFlag |
||
986 | };16+linenumber; |