Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1846 | yogev_ezra | 1 | //===== Флаги компиляции |
2 | #pragma option w32c |
||
3 | #stack 0x8000 |
||
4 | #argc TRUE |
||
5 | |||
6 | //===== Подключаемые модули |
||
7 | #include "wapi.h--" |
||
8 | #include "enums.h--" |
||
9 | #include "data.h--" |
||
10 | #include "opcodesc.h--" |
||
11 | #include "tree.h--" |
||
12 | #include "directiv.h--" |
||
13 | #include "tokscan.h--" |
||
14 | #include "exe.h--" |
||
15 | #include "generate.h--" |
||
16 | #include "parser.h--" |
||
17 | |||
18 | //===== Главная функция программы |
||
19 | main() |
||
20 | dword count,pari,cmdline; |
||
21 | { |
||
22 | stdout=GetStdHandle(STD_OUTPUT_HANDLE); |
||
23 | WRITESTR("\n32-Compiler Version 0.01\tXAC (C) 1999."); |
||
24 | WRITESTR("\nBased on SPHINX C-- Compiler Peter Cellik (C) 1995.\n"); |
||
25 | // Разбор коммандной строки: 32.exe |
||
26 | pari=@PARAMCOUNT(); |
||
27 | for(count=1;count |
||
28 | cmdline=@PARAMSTR(count); |
||
29 | CharUpperA(EAX); |
||
30 | CharToOemA(cmdline,cmdline); // Преобразуем в ЗАГЛ в OEM кодровке |
||
31 | ESI=cmdline; |
||
32 | IF(DSBYTE[ESI]=='/'){ |
||
33 | ESI++; |
||
34 | IF(lstrcmpA("MAP",ESI)==0)makemapfile = 1; |
||
35 | ELSE IF(lstrcmpA("DEBUG",ESI)==0)dbg=1; |
||
36 | ELSE{ |
||
37 | WRITESTR("ERROR > Unknown command line option: '"); |
||
38 | WRITESTR(cmdline); |
||
39 | WRITESTR("'\n"); |
||
40 | ExitProcess(e_unknowncommandline); |
||
41 | } |
||
42 | } |
||
43 | ELSE{ // Копируем имя исходного файла без расширения |
||
44 | EDI=#rawfilename; |
||
45 | for(;;){ |
||
46 | $LODSB |
||
47 | IF(AL=='.')||(AL==0)BREAK; // Есть расширение? |
||
48 | $STOSB; |
||
49 | } |
||
50 | AL=0; |
||
51 | $STOSB; |
||
52 | lstrcpyA(#inputfile,cmdline); // Копируем имя входного файла с расширением |
||
53 | } |
||
54 | } |
||
55 | IF(rawfilename[0]==0){ |
||
56 | errmsg(); |
||
57 | WRITESTR("No input file specified"); |
||
58 | pari=1; |
||
59 | } |
||
60 | IF(pari < 2){ |
||
61 | WRITESTR("\nUsage: 32.exe [/MAP] [/DEBUG] |
||
62 | WRITESTR("\n\t/MAP\t<< generate map file"); |
||
63 | WRITESTR("\n\t/DEBUG\t<< generate .TDS - debug info file\n"); |
||
64 | ExitProcess(e_noinputspecified); |
||
65 | } |
||
66 | GetMem(); // выделение памяти для компиляции |
||
67 | TokInit(); // инициализация списков |
||
68 | Compile(); |
||
69 | IF( error == 0 )EAX=e_ok; |
||
70 | ELSE EAX=e_someerrors; |
||
71 | ExitProcess(EAX); |
||
72 | } |
||
73 | |||
74 | //===== Компилятор |
||
75 | Compile() |
||
76 | { |
||
77 | IF(makemapfile)StartMapfile(); |
||
78 | WRITESTR("Compiling ...\n"); |
||
79 | Preview(#inputfile); |
||
80 | CompileAll(); |
||
81 | /*if( endifcount > 0 ) |
||
82 | preerror("#endif expected before end of file"); |
||
83 | if( outptr%16 != 0 ) // paragraph align the end of the code seg |
||
84 | outptr += 16 - outptr%16;*/ |
||
85 | DoLink(); // Формирование link |
||
86 | IF(posts > 0)DoPosts(); // Обновление всех post адресов |
||
87 | SeekUndefined(treestart); |
||
88 | if(error==0){ |
||
89 | wsprintfA(#mapstr,"\nCOMPILING FINISHED.\tErrors: %d\tLines: %u\n",error,totallines); |
||
90 | WRITESTR(#mapstr); |
||
91 | runfilesize = outptr-output; |
||
92 | postsize += postsize%2; |
||
93 | PrintMemsizes(GetStdHandle(STD_OUTPUT_HANDLE)); |
||
94 | IF(WriteEXE()==0) { |
||
95 | wsprintfA(#mapstr,"\nRun File Saved (%ld bytes).\n",runfilesize); |
||
96 | WRITESTR(#mapstr); |
||
97 | wsprintfA(#mapstr,"DLL: %d\tAPI: %d \n",DLLcount,APIcount); |
||
98 | WRITESTR(#mapstr); |
||
99 | } |
||
100 | // if(dbg) |
||
101 | // dotds(); // do turbo debugger line info |
||
102 | } |
||
103 | IF(makemapfile)FinishMapfile(); |
||
104 | } |
||
105 | |||
106 | // ---- Предварительная обработка файла |
||
107 | Preview(dword filename) |
||
108 | long hold; |
||
109 | char trialfilename[FILENAMESIZE]; |
||
110 | { |
||
111 | lstrcpyA(#trialfilename,filename); |
||
112 | hold = LoadInputfile(#trialfilename); |
||
113 | IF(EAX==-2)unabletoopen(#trialfilename); |
||
114 | IF(hold!=0)ExitProcess(e_cannotopeninput); |
||
115 | lstrcpyA(#currentfilename,#trialfilename); |
||
116 | module++; |
||
117 | IF(module |
||
118 | lstrcpyA(FILENAMESIZE*module+#modules,#currentfilename); |
||
119 | currmod = module; |
||
120 | } |
||
121 | IF(makemapfile){ |
||
122 | EBX=inptr; |
||
123 | cha=DSBYTE[EBX]; |
||
124 | wsprintfA(#mapstr,"File %s included.\n\n%c",#currentfilename,cha); |
||
125 | fprint(mapfile,#mapstr); |
||
126 | } |
||
127 | ShowSrcLine(); |
||
128 | NextChar(); |
||
129 | cha2 = cha; |
||
130 | inptr2=inptr; |
||
131 | linenum2 = 1; |
||
132 | NextTok(); |
||
133 | WHILE(tok!=tk_eof){ // Пока не кончится входной буфер |
||
134 | IF(tok==tk_directive){ |
||
135 | GetDirAddr(#Jmp_Directives,number); |
||
136 | EAX(); |
||
137 | } |
||
138 | ELSE IF(tok==tk_command){ |
||
139 | GetDirAddr(#Jmp_Commands,number); |
||
140 | EAX(); |
||
141 | } |
||
142 | ELSE IF(tok==tk_id)GetProc(tk_void); |
||
143 | ELSE IF(tok==tk_void){ |
||
144 | NextTok(); |
||
145 | GetProc(tk_void); |
||
146 | } |
||
147 | ELSE{ |
||
148 | preerror("unuseable input"); |
||
149 | NextTok(); |
||
150 | } |
||
151 | } |
||
152 | LocalFree(input); |
||
153 | } |
||
154 | |||
155 | // ---- Компиляция одной процедуры или объявления данных |
||
156 | CompileSrc(dword ptr) |
||
157 | { |
||
158 | EAX=src; |
||
159 | if(EAX){ |
||
160 | inptr = EAX; |
||
161 | inptr2 = EAX; |
||
162 | endoffile = 0; // На начало буфера |
||
163 | linenum2 = modline&0xFFFF; |
||
164 | currmod=modline>>16; |
||
165 | lstrcpyA(#currentfilename,FILENAMESIZE*currmod+#modules); |
||
166 | NextChar(); |
||
167 | cha2 = cha; |
||
168 | inptr2=inptr; |
||
169 | IF(tok==tk_proc){ |
||
170 | Proc(cpt_near); |
||
171 | DoPoststrings(); |
||
172 | } |
||
173 | ELSE IF(tok==tk_var)GlobalVar(type); |
||
174 | ELSE preerror("Bad input format\n"); |
||
175 | } |
||
176 | ELSE{ // post-переменная без размерности |
||
177 | ESI=ptr; |
||
178 | DSDWORD[ESI+recnumber] = postsize; |
||
179 | DSDWORD[ESI+recpost] = 1; |
||
180 | postsize+=TypeSize(type); |
||
181 | } |
||
182 | } |
||
183 | |||
184 | // ---- Компиляция всех процедур и объявлений данных |
||
185 | CompileAll() |
||
186 | { |
||
187 | IF(SearchTree(#tok,#type,#src,#post,"main",#number))AX=3; // Console |
||
188 | ELSE IF(SearchTree(#tok,#type,#src,#post,"WinMain",#number))AX=2; // GUI |
||
189 | ELSE{ |
||
190 | preerror("Main not found"); |
||
191 | return; |
||
192 | } |
||
193 | OptSubSystem=AX; |
||
194 | OptEntryPointRVA=OptBaseOfCode+outptr-output; |
||
195 | CompileSrc(treeptr); // Компиляция main |
||
196 | WHILE(SeekToDo(treestart)){ |
||
197 | ESI=treeptr; |
||
198 | wsprintfA(#mapstr,"==>%3d %8lXh %8lXh %6Xh\t%s\n",DSDWORD[ESI+rectok], |
||
199 | DSDWORD[ESI+rectype],DSDWORD[ESI+recnumber],DSDWORD[ESI+recpost], |
||
200 | DSDWORD[ESI+recid]); |
||
201 | fprint(mapfile,#mapstr); |
||
202 | CompileSrc(treeptr); // Компиляция исходников |
||
203 | } |
||
204 | IF(makemapfile) |
||
205 | fprint(mapfile,"Compile all sources\n"); |
||
206 | } |
||
207 | |||
208 | // ---- Обработка параметров при объявлении процедуры |
||
209 | DeclareParams() |
||
210 | dword paramtok,paramtype; |
||
211 | { |
||
212 | LL: |
||
213 | IF(tok==tk_command)GetDirAddr(#Jmp_Commands,number); |
||
214 | ELSE EAX=-1; |
||
215 | IF(EAX==#CmdShort){ |
||
216 | paramtok = tk_param; |
||
217 | paramtype=tk_short; |
||
218 | } |
||
219 | ELSE IF(EAX==#CmdWord){ |
||
220 | paramtok = tk_param; |
||
221 | paramtype=tk_word; |
||
222 | } |
||
223 | ELSE IF(EAX==#CmdChar){ |
||
224 | paramtok = tk_param; |
||
225 | paramtype=tk_char; |
||
226 | } |
||
227 | ELSE IF(EAX==#CmdByte){ |
||
228 | paramtok = tk_param; |
||
229 | paramtype=tk_byte; |
||
230 | } |
||
231 | ELSE IF(EAX==#CmdInt){ |
||
232 | paramtok = tk_param; |
||
233 | paramtype=tk_int; |
||
234 | } |
||
235 | ELSE IF(EAX==#CmdDword){ |
||
236 | paramtok = tk_param; |
||
237 | paramtype=tk_dword; |
||
238 | } |
||
239 | ELSE{ |
||
240 | datatype_expected(); |
||
241 | NextTok(); |
||
242 | } |
||
243 | for(;;){ |
||
244 | NextTok(); |
||
245 | IF(tok==tk_id ){ |
||
246 | paramsize += 4; |
||
247 | AddLocalvar(#string,paramtok,paramtype,paramsize); |
||
248 | } |
||
249 | ELSE IF(tok==tk_semicolon){ |
||
250 | NextTok(); |
||
251 | $JMP LL |
||
252 | } |
||
253 | ELSE IF(tok==tk_closebracket)BREAK; |
||
254 | ELSE IF(tok!=tk_comma)idexpected(); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | // ---- Обработка локальных переменных при объявлении процедуры |
||
259 | DeclareLocals() |
||
260 | dword size; |
||
261 | dword loctok,loctype; |
||
262 | { |
||
263 | LL: |
||
264 | IF(tok==tk_command)GetDirAddr(#Jmp_Commands,number); |
||
265 | IF(EAX==#CmdShort){ |
||
266 | loctok = tk_local; |
||
267 | loctype=tk_short; |
||
268 | size = 2; |
||
269 | } |
||
270 | else IF(EAX==#CmdWord){ |
||
271 | loctok = tk_local; |
||
272 | loctype=tk_word; |
||
273 | size = 2; |
||
274 | } |
||
275 | else IF(EAX==#CmdChar){ |
||
276 | loctok = tk_local; |
||
277 | loctype=tk_char; |
||
278 | size = 1; |
||
279 | } |
||
280 | ELSE IF(EAX==#CmdByte){ |
||
281 | loctok = tk_local; |
||
282 | loctype=tk_byte; |
||
283 | size = 1; |
||
284 | } |
||
285 | ELSE IF(EAX==#CmdInt){ |
||
286 | loctok = tk_local; |
||
287 | loctype=tk_int; |
||
288 | size = 4; |
||
289 | } |
||
290 | ELSE IF(EAX==#CmdDword){ |
||
291 | loctok = tk_local; |
||
292 | loctype=tk_dword; |
||
293 | size = 4; |
||
294 | } |
||
295 | ELSE IF(tok==tk_eof)||(tok==tk_openbrace)$JMP L1 |
||
296 | ELSE{ |
||
297 | datatype_expected(); |
||
298 | NextTok(); |
||
299 | goto LL; |
||
300 | } |
||
301 | for(;;){ |
||
302 | NextTok(); |
||
303 | IF(tok==tk_id){ |
||
304 | AddLocalvar(#string,loctok,loctype,localsize); |
||
305 | IF(tok2==tk_openblock){ |
||
306 | NextTok(); |
||
307 | NextTok(); |
||
308 | localsize += DoConstLongMath()*size; |
||
309 | EAX=localsize; |
||
310 | $TEST EAX,3; |
||
311 | IF(NOTZEROFLAG){ |
||
312 | EAX=EAX>>2+1<<2; |
||
313 | localsize=EAX; // Выравнивание на dword |
||
314 | } |
||
315 | expecting(tk_closeblock); |
||
316 | } |
||
317 | ELSE localsize+=4; |
||
318 | } |
||
319 | ELSE IF(tok==tk_semicolon){ |
||
320 | NextTok(); |
||
321 | $JMP LL |
||
322 | } |
||
323 | ELSE IF(tok==tk_openbrace)||(tok==tk_eof)BREAK; |
||
324 | ELSE IF(tok!=tk_comma)idexpected(); |
||
325 | } |
||
326 | L1: |
||
327 | IF(paramsize==0)Asm("push ebp; mov ebp,esp;"); |
||
328 | wsprintfA(#mapstr,"sub esp,%d;",localsize); |
||
329 | Asm(#mapstr); |
||
330 | } |
||
331 | |||
332 | // ---- Обработка обращения к уже описанной процедуре |
||
333 | DoAnyProc() |
||
334 | byte s[80]; |
||
335 | { |
||
336 | wsprintfA(#s,"call %s;",#string); |
||
337 | NextTok(); |
||
338 | DoParams(); |
||
339 | Asm(#s); |
||
340 | } |
||
341 | |||
342 | // ---- Обработка ранее объвленной, но пока не известной метки |
||
343 | dword DoAnyUndefproc(dword expectedreturn) |
||
344 | byte s[80]; |
||
345 | { |
||
346 | IF( tok2 == tk_colon ){ // метка |
||
347 | number = outptr-output+OptImageBase+OptBaseOfCode; |
||
348 | tok = tk_proc; |
||
349 | ESI=treeptr; |
||
350 | DSDWORD[ESI+rectok] = tok; |
||
351 | DSDWORD[ESI+recnumber] = number; |
||
352 | DSDWORD[ESI+recpost] = 0; |
||
353 | NextTok(); // move past id |
||
354 | NextTok(); // move past : |
||
355 | RETURN(tokens); |
||
356 | } |
||
357 | IF( tok2 == tk_openbracket ){ |
||
358 | wsprintfA(#s,"call %s;",#string); |
||
359 | NextTok(); |
||
360 | DoParams(); |
||
361 | Asm(#s); |
||
362 | RETURN(tk_dword); |
||
363 | } |
||
364 | undefinederror(); |
||
365 | NextTok(); |
||
366 | return(tk_int); |
||
367 | } |
||
368 | |||
369 | // ---- Обработка обращения к API функции |
||
370 | dword doAPI() |
||
371 | dword hold; |
||
372 | byte s[IDLENGTH]; |
||
373 | { |
||
374 | if( tok2 == tk_openbracket ){ |
||
375 | hold = treeptr; |
||
376 | GetVarname(#s); |
||
377 | NextTok(); |
||
378 | DoParams(); |
||
379 | IF(posts>=MAXPOSTS){ |
||
380 | preerror("maximum number of API procedure calls exceeded"); |
||
381 | return(tokens); |
||
382 | } |
||
383 | EBX=hold; |
||
384 | IF(DSDWORD[EBX+recpost]==0) { // Первый вызов API? |
||
385 | DSDWORD[EBX+recpost]=1; // отметим вызов данной API |
||
386 | APIcount++; |
||
387 | EAX=DSDWORD[EBX+rectype]; // Указатель на DLL, в котором находится API |
||
388 | DSDWORD[EAX+recmodline]++; // Увеличим счетчик API, вызванных из DLL |
||
389 | } |
||
390 | OUTWORD(0x15FF); // call [dword] |
||
391 | SetPost(hold,POST_API); |
||
392 | OUTDWORD(0); |
||
393 | IF(list){ |
||
394 | fprint(mapfile,"\t//\tcall "); |
||
395 | fprint(mapfile,#s); |
||
396 | fprint(mapfile,"\n"); |
||
397 | } |
||
398 | return(tk_int); |
||
399 | } |
||
400 | undefinederror(); |
||
401 | NextTok(); |
||
402 | return(tokens); |
||
403 | } |
||
404 | |||
405 | // ---- Обработка программного блока {...} |
||
406 | void DoBlock() |
||
407 | { |
||
408 | expecting(tk_openbrace); |
||
409 | for(;;){ |
||
410 | IF(tok==tk_eof){ |
||
411 | unexpectedeof(); |
||
412 | BREAK; |
||
413 | } |
||
414 | IF(tok == tk_closebrace){ |
||
415 | NextTok(); |
||
416 | BREAK; |
||
417 | } |
||
418 | DoCommand(); |
||
419 | } |
||
420 | } |
||
421 | |||
422 | // ---- Обработка одной команды внутри блока |
||
423 | DoCommand() |
||
424 | { |
||
425 | LL: |
||
426 | FastSearch(#string,#St_Sizes);// Это размер операнда? |
||
427 | IF(CARRYFLAG){ // Да: byte,word или dword |
||
428 | type=EAX<<1+tk_byte; |
||
429 | string[0]=0; |
||
430 | tok=tk_var; |
||
431 | GOTO LL; |
||
432 | } |
||
433 | IF(tok==tk_mnemonics){ |
||
434 | DoMnemonics(); |
||
435 | NextTok(); |
||
436 | } |
||
437 | else IF(tok==tk_directive){ |
||
438 | GetDirAddr(#Jmp_Directives,number); |
||
439 | EAX(); |
||
440 | } |
||
441 | else IF(tok==tk_command){ |
||
442 | GetDirAddr(#Jmp_Commands,number); |
||
443 | EAX(); |
||
444 | } |
||
445 | else IF(tok==tk_id){ |
||
446 | DoId(tk_void); |
||
447 | IF(EAX!=tokens)NextSemiNext(); |
||
448 | } |
||
449 | else IF(tok==tk_undefproc){ |
||
450 | DoAnyUndefproc(tk_void); |
||
451 | IF(EAX!=tokens)NextSemiNext(); |
||
452 | } |
||
453 | else IF(tok==tk_proc){ |
||
454 | DoAnyProc(); |
||
455 | NextSemiNext(); |
||
456 | } |
||
457 | else IF(tok==tk_API){ |
||
458 | IF(doAPI()!=tokens)NextSemiNext(); |
||
459 | } |
||
460 | else IF(tok==tk_var)||(tok==tk_local)||(tok==tk_param)||(tok==tk_reg)DoVar(type); |
||
461 | ELSE IF(tok==tk_openblock)DoVar(tk_dword); |
||
462 | ELSE IF(tok==tk_string){ |
||
463 | Macros(); |
||
464 | NextSemiNext(); |
||
465 | } |
||
466 | ELSE IF(tok==tk_locallabel)DoLocalPost(); |
||
467 | ELSE IF(tok==tk_openbrace)DoBlock(); |
||
468 | ELSE IF(tok==tk_comma)||(tok==tk_semicolon)NextTok(); |
||
469 | ELSE IF(tok==tk_eof)unexpectedeof(); |
||
470 | /* case tk_from: |
||
471 | NextTok(); DoFrom(0); NextSemiNext(); break; |
||
472 | case tk_extract: |
||
473 | NextTok(); DoExtract(0); SemiNext(); break; |
||
474 | */ |
||
475 | } |
||
476 | |||
477 | // ---- Обработка новых идентификаторов |
||
478 | dword DoId(dword expectedreturn) |
||
479 | byte s[80]; |
||
480 | { |
||
481 | IF(tok2 == tk_colon){ // метка? |
||
482 | number = outptr-output+OptImageBase+OptBaseOfCode; |
||
483 | tok = tk_proc; |
||
484 | post = 0; |
||
485 | AddToTree(#string); |
||
486 | NextTok(); NextTok(); // пропустим идентификатор и : |
||
487 | EAX=tokens; |
||
488 | } |
||
489 | ELSE IF(tok2 == tk_openbracket){ // вызов процедуры |
||
490 | wsprintfA(#s,"call %s;",#string); |
||
491 | tok = tk_undefproc; |
||
492 | number=0; |
||
493 | post=1; |
||
494 | AddToTree(#string); |
||
495 | NextTok(); |
||
496 | DoParams(); |
||
497 | Asm(#s); |
||
498 | EAX=expectedreturn; |
||
499 | } |
||
500 | ELSE{ |
||
501 | undefinederror(); |
||
502 | NextTok(); |
||
503 | EAX=tk_int; |
||
504 | } |
||
505 | } |
||
506 | |||
507 | // ---- Обработка параметров при вызове процедуры |
||
508 | DoParams() |
||
509 | { |
||
510 | IF(tok==tk_openbracket){ |
||
511 | inptr2--; |
||
512 | DoParam(); |
||
513 | NextTok(); |
||
514 | } |
||
515 | ELSE expecting(tk_openbracket); |
||
516 | } |
||
517 | |||
518 | // ---- Обработка ... |
||
519 | DoVar(dword vartype) |
||
520 | dword next,vtok; |
||
521 | byte varName[2*IDLENGTH]; |
||
522 | byte varName2[2*IDLENGTH]; |
||
523 | { |
||
524 | next=1; |
||
525 | vtok=GetVarname(#varName); |
||
526 | NextTok(); |
||
527 | IF(tok==tk_assign){ |
||
528 | NextTok(); |
||
529 | IF(tok2notstopper()){ |
||
530 | DoExpr(#varName,vtok,vartype,"mov"); |
||
531 | next=0; |
||
532 | } |
||
533 | ELSE GetIntoVar(#varName,vtok,vartype); |
||
534 | } |
||
535 | else IF(tok==tk_minusminus){ // Var--; |
||
536 | wsprintfA(#mapstr,"dec %s",#varName); |
||
537 | Asm(#mapstr); |
||
538 | } |
||
539 | else IF(tok==tk_plusplus){ // Var++; |
||
540 | wsprintfA(#mapstr,"inc %s",#varName); |
||
541 | Asm(#mapstr); |
||
542 | } |
||
543 | else IF(tok==tk_plusequals){ // Var+=Expr; |
||
544 | NextTok(); |
||
545 | DoExpr(#varName,tk_var,vartype,"add"); |
||
546 | next=1; |
||
547 | } |
||
548 | else IF(tok==tk_minusequals){ // Var-=Expr; |
||
549 | NextTok(); |
||
550 | DoExpr(#varName,tk_var,vartype,"sub"); |
||
551 | next=1; |
||
552 | } |
||
553 | else IF(tok==tk_andequals){ // Var&=Expr; |
||
554 | NextTok(); |
||
555 | DoExpr(#varName,tk_var,vartype,"and"); |
||
556 | next=1; |
||
557 | } |
||
558 | else IF(tok==tk_xorequals){ // Var^=Expr; |
||
559 | NextTok(); |
||
560 | DoExpr(#varName,tk_var,vartype,"xor"); |
||
561 | next=1; |
||
562 | } |
||
563 | else IF(tok==tk_orequals){ // Var|=Expr; |
||
564 | NextTok(); |
||
565 | DoExpr(#varName,tk_var,vartype,"or"); |
||
566 | next=1; |
||
567 | } |
||
568 | else if(tok==tk_swap){ // Var> |
||
569 | NextTok(); |
||
570 | GetVarname(#varName2); |
||
571 | IF(tok==tk_reg){ |
||
572 | wsprintfA(#mapstr,"xchg %s,%s",#string,#varName); |
||
573 | Asm(#mapstr); |
||
574 | } |
||
575 | else if(tok==tk_var)&&(tok2notstopper()==0){ |
||
576 | IF(vartype==tk_dword)||(vartype==tk_int){ |
||
577 | wsprintfA(#mapstr,"xchg %s,eax",#varName); |
||
578 | Asm(#mapstr); |
||
579 | wsprintfA(#mapstr,"xchg %s,eax",#varName2); |
||
580 | Asm(#mapstr); |
||
581 | wsprintfA(#mapstr,"xchg %s,eax",#varName); |
||
582 | } |
||
583 | else IF(vartype==tk_word)||(vartype==tk_short){ |
||
584 | wsprintfA(#mapstr,"xchg %s,ax",#varName); |
||
585 | Asm(#mapstr); |
||
586 | wsprintfA(#mapstr,"xchg %s,ax",#varName2); |
||
587 | Asm(#mapstr); |
||
588 | wsprintfA(#mapstr,"xchg %s,ax",#varName); |
||
589 | } |
||
590 | ELSE IF(vartype==tk_byte)||(vartype==tk_char){ |
||
591 | wsprintfA(#mapstr,"xchg %s,al",#varName); |
||
592 | Asm(#mapstr); |
||
593 | wsprintfA(#mapstr,"xchg %s,al",#varName2); |
||
594 | Asm(#mapstr); |
||
595 | wsprintfA(#mapstr,"xchg %s,al",#varName); |
||
596 | } |
||
597 | Asm(#mapstr); |
||
598 | } |
||
599 | ELSE swaperror(); |
||
600 | } |
||
601 | else IF(tok==tk_llequals){ // Var<<=Expr; |
||
602 | NextTok(); |
||
603 | IF(tok == tk_number) wsprintfA(#mapstr,"shl %s,%d",#varName,DoConstMath()); |
||
604 | ELSE{ |
||
605 | Expression("cl",tk_reg,tk_byte); |
||
606 | wsprintfA(#mapstr,"shl %s,cl",#varName); |
||
607 | next=0; |
||
608 | } |
||
609 | Asm(#mapstr); |
||
610 | } |
||
611 | ELSE IF(tok==tk_rrequals){ // Var>>=Expr; |
||
612 | NextTok(); |
||
613 | IF(tok == tk_number)wsprintfA(#mapstr,"shr %s,%d",#varName,DoConstMath()); |
||
614 | ELSE{ |
||
615 | Expression("cl",tk_reg,tk_byte); |
||
616 | wsprintfA(#mapstr,"shr %s,cl",#varName); |
||
617 | next=0; |
||
618 | } |
||
619 | Asm(#mapstr); |
||
620 | } |
||
621 | ELSE operatorexpected(); |
||
622 | IF(next)NextSemiNext(); |
||
623 | ELSE SemiNext(); |
||
624 | } |
||
625 | |||
626 | // ---- Обработка ссылок вперед |
||
627 | DoPosts() |
||
628 | dword addhold,i; |
||
629 | { |
||
630 | i=0; |
||
631 | while(i |
||
632 | ECX=i<<2; |
||
633 | ESI=posttype+ECX; |
||
634 | EAX=DSDWORD[ESI]; |
||
635 | ESI=postloc+ECX; |
||
636 | EBX=DSDWORD[ESI]; |
||
637 | ESI=postnum+ECX; |
||
638 | ECX=DSDWORD[ESI]; |
||
639 | IF(EAX==POST_DATA){ |
||
640 | IF(DSDWORD[ECX+recpost]){ |
||
641 | GetDword(EBX); |
||
642 | EAX=EAX+DSDWORD[ECX+recnumber]+OptImageBase+OptBaseOfCode+outptr-output; |
||
643 | } |
||
644 | ELSE{ |
||
645 | GetDword(EBX); |
||
646 | EAX+=DSDWORD[ECX+recnumber]; |
||
647 | } |
||
648 | SetDword(EBX,EAX); |
||
649 | } |
||
650 | ELSE IF(EAX==POST_CALL){ |
||
651 | EAX=DSDWORD[ECX+recnumber]-OptImageBase-OptBaseOfCode-EBX; // Расчет относительного смещения EAX-=addvalue; |
||
652 | EAX+=output; |
||
653 | SetDword(EBX,EAX-4); |
||
654 | } |
||
655 | ELSE IF(EAX==POST_LOC){ |
||
656 | EAX=ECX; EAX-=OptImageBase; |
||
657 | EAX-=OptBaseOfCode; EAX-=EBX; // Расчет относительного смещения EAX-=addvalue; |
||
658 | EAX+=output; SetDword(EBX,EAX-4); |
||
659 | } |
||
660 | ELSE IF(EAX==POST_API){ |
||
661 | addhold = OptImageBase + DSDWORD[ECX+recmodline]; |
||
662 | SetDword(EBX,addhold); |
||
663 | } |
||
664 | ELSE preerror("Bad post type\n"); |
||
665 | i++; |
||
666 | } |
||
667 | } |
||
668 | |||
669 | // ---- Быстрый поиск по таблице |
||
670 | // OUTPUT: EAX=No.& CARRYFLAG - success |
||
671 | dword FastSearch(dword probe,table) |
||
672 | byte ident[IDLENGTH]; |
||
673 | { |
||
674 | $PUSH ECX,ESI,EDI,EDX |
||
675 | lstrcpyA(#ident,probe); |
||
676 | CharUpperA(#ident); |
||
677 | lstrlenA(#ident); |
||
678 | EDX=EAX-1; |
||
679 | $JZ HET // ident из одного символа |
||
680 | EBX=0; |
||
681 | BL=ident;//[0]; // Проверим первый символ в ident |
||
682 | BL-='A'; |
||
683 | $JC HET // Не буква |
||
684 | $CMP BL,'Z'-'A'; |
||
685 | $JA HET // и не 'A'...'Z' |
||
686 | EAX=0; |
||
687 | EBX=EBX<<2+table; |
||
688 | EDI=DSDWORD[EBX]; // Взять адрес записи из table |
||
689 | $OR EDI,EDI; |
||
690 | $JE HET // Нет записи для такого ident... |
||
691 | TRY0: |
||
692 | AH=DSBYTE[EDI]; |
||
693 | EDI++; // Номер записи из table и на строку в table |
||
694 | TRY1: |
||
695 | ESI=#ident+1; |
||
696 | ECX=EDX; // Взять ident длину - 1 |
||
697 | $REPE $CMPSB; |
||
698 | $JNE NXT // Сравним с записью в table |
||
699 | $JCXZ YES1 // Совпали по длине probe |
||
700 | NXT: |
||
701 | EDI--; |
||
702 | LOOK: |
||
703 | AL=DSBYTE[EDI]; |
||
704 | EDI++; |
||
705 | $OR AL,AL; |
||
706 | $JE TRY0 // Проверим следующую запись |
||
707 | $CMP AL,'/'; |
||
708 | $JE NEAR TRY1 // Проверим ALIAS |
||
709 | $CMP AL,_END; |
||
710 | $JE NEAR HET // Конец таблицы - выход |
||
711 | GOTO LOOK; |
||
712 | HET: |
||
713 | $CLC; |
||
714 | GOTO EX; // ident не найден в table |
||
715 | YES1: |
||
716 | $CMP DSBYTE[EDI],0; |
||
717 | $JZ YES; |
||
718 | $CMP DSBYTE[EDI],_END; |
||
719 | $JZ YES; |
||
720 | $CMP DSBYTE[EDI],'/'; |
||
721 | $JZ YES; |
||
722 | GOTO NXT; |
||
723 | YES: |
||
724 | AL=AH; |
||
725 | AH=0; |
||
726 | $STC // ident найден в table |
||
727 | EX: |
||
728 | $POP EDX,EDI,ESI,ECX; |
||
729 | } |
||
730 | |||
731 | // ---- Вывод статистики по компиляции |
||
732 | FinishMapfile() |
||
733 | { |
||
734 | fprint(mapfile,"\n"); |
||
735 | DisplayTree(); |
||
736 | fprint(mapfile,"Component Sizes:\n"); |
||
737 | PrintMemsizes(mapfile); |
||
738 | wsprintfA(#mapstr,"Run file size: %ld bytes\n",runfilesize); |
||
739 | fprint(mapfile,#mapstr); |
||
740 | wsprintfA(#mapstr,"\nEND OF MAP FILE FOR %s.%s\n\n",#rawfilename,"EXE"); |
||
741 | fprint(mapfile,#mapstr); |
||
742 | _lclose(mapfile); |
||
743 | mapfile=0; |
||
744 | list=0; |
||
745 | } |
||
746 | |||
747 | // ---- Вывод в файл |
||
748 | fprint(dword handle,str) |
||
749 | { |
||
750 | _lwrite(handle,str,lstrlenA(str)); |
||
751 | } |
||
752 | |||
753 | // ---- Выделение памяти для компиляции. При неудаче выход из компилятора |
||
754 | GetMem() |
||
755 | { |
||
756 | output=LocalAlloc(0x40,MAXDATA); |
||
757 | IF(EAX==NULL)outofmemory2(); |
||
758 | LocalUnlock(output); |
||
759 | outptr=output; |
||
760 | startptr=output; |
||
761 | postloc=LocalAlloc(0x40,MAXPOSTS*4); |
||
762 | IF(EAX==NULL)outofmemory2(); |
||
763 | postnum=LocalAlloc(0x40,MAXPOSTS*4); |
||
764 | IF(EAX==NULL)outofmemory2(); |
||
765 | posttype=LocalAlloc(0x40,MAXPOSTS); |
||
766 | IF(EAX==NULL)outofmemory2(); |
||
767 | dbginfo=LocalAlloc(0x40,MAXDBGS*dbg_size); |
||
768 | IF(EAX==NULL)outofmemory2(); |
||
769 | dbgs=dbginfo; |
||
770 | } |
||
771 | |||
772 | // ---- Чтение двойного слова |
||
773 | dword GetDword(dword ptr) |
||
774 | { |
||
775 | ESI> |
||
776 | $LODSD; |
||
777 | ESI> |
||
778 | } |
||
779 | |||
780 | // ---- Инициал зация списка |
||
781 | // Для keylist = {"ZAK",0,"AAD",0,"ABC",0,"BAR",0,"AAA",0,"ZZ",0,"BAC",_END}; |
||
782 | // сформируется структура в памяти следующего в да: |
||
783 | // table |
||
784 | // +-----+ |
||
785 | // | 'A' | ---> db 4,'AA',1,'AD',2,'BC',_END |
||
786 | // +-----+ |
||
787 | // | 'B' | ---> db 6,'AC',3,'AR",_END |
||
788 | // +-----+ |
||
789 | // | ... | |
||
790 | // +-----+ |
||
791 | // | 'Z' | ---> db 0,'AK',5,'Z',_END |
||
792 | // +-----+ |
||
793 | InitList(dword keylist,table) |
||
794 | dword ptr; |
||
795 | { |
||
796 | ptr=LocalAlloc(0x40,SORTSIZE*256); |
||
797 | IF(EAX==NULL)outofmemory2(); |
||
798 | EDI> |
||
799 | ESI=keylist; |
||
800 | ECX=0; |
||
801 | BL=0; |
||
802 | // Занесение строк из keylist в ptr |
||
803 | for(;;){ |
||
804 | for(;;){ |
||
805 | $PUSH EDI; |
||
806 | IF(DSBYTE[ESI]!='-')BREAK; |
||
807 | ESI+=2; |
||
808 | BL++; |
||
809 | $POP EDI; |
||
810 | } |
||
811 | AL=BL; |
||
812 | $STOSB // Сохраним порядковый номер строки |
||
813 | for(;;){ |
||
814 | $LODSB // Скопируем строку в ptr |
||
815 | IF(AL<' ')BREAK; |
||
816 | $STOSB; |
||
817 | } |
||
818 | IF(AL==_END)BREAK; |
||
819 | $STOSB; |
||
820 | $POP EDI; |
||
821 | BL++; |
||
822 | EDI+=SORTSIZE; |
||
823 | ECX++; |
||
824 | } |
||
825 | ESI=ptr; |
||
826 | $PUSH ECX // Копирование в ptr закончено. Сохраним кол-во строк |
||
827 | ECX--; |
||
828 | IF(NOTZEROFLAG){// Всего одна строка? - сортировка не нужна |
||
829 | // Сортировка строк в ptr |
||
830 | loop(ECX){ |
||
831 | $PUSH ESI,ECX; |
||
832 | EDI=ESI+SORTSIZE; |
||
833 | loop(ECX){ |
||
834 | $PUSH ECX,ESI,EDI; |
||
835 | ECX=SORTSIZE; |
||
836 | ESI++; |
||
837 | EDI++; |
||
838 | $REPE $CMPSB; |
||
839 | $POP EDI,ESI; |
||
840 | IF(NOTCARRYFLAG){ // проверит условие ????????????Сравнение двух строк |
||
841 | EAX=ESI; |
||
842 | EDX=EDI; |
||
843 | EDI=#Buffer16; |
||
844 | ECX=SORTSIZE/4; // Нашли меньшую строку |
||
845 | $REP $MOVSD; |
||
846 | ESI=EDX; |
||
847 | EDI=EAX; |
||
848 | ECX=SORTSIZE/4; // -поменяем местами |
||
849 | $REP $MOVSD; |
||
850 | ESI=#Buffer16; |
||
851 | EDI=EDX; |
||
852 | ECX=SORTSIZE/4; |
||
853 | $REP $MOVSD; |
||
854 | ESI=EAX; |
||
855 | EDI=EDX; |
||
856 | } |
||
857 | EDI+=SORTSIZE; |
||
858 | $POP ECX; |
||
859 | } |
||
860 | $POP ECX,ESI; |
||
861 | ESI+=SORTSIZE; |
||
862 | } |
||
863 | } |
||
864 | // Сортировка введенных строк в буфере ptr закончена |
||
865 | EDI=table; |
||
866 | ECX=26; |
||
867 | EAX=0; |
||
868 | $REP $STOSD; // Обнулен е table |
||
869 | $POP ECX; |
||
870 | ESI=ptr; |
||
871 | EDI=ESI; |
||
872 | $PUSH ESI; |
||
873 | GOTO L42; // Форм руем таблицу |
||
874 | loop(ECX){ |
||
875 | $PUSH ESI; |
||
876 | IF(AH!=DSBYTE[ESI+1]){ |
||
877 | EDI--; |
||
878 | AL=_END; |
||
879 | $STOSB // Отметим конец таблицы для данного символа в AH |
||
880 | L42: |
||
881 | AH=DSBYTE[ESI+1]; |
||
882 | EBX=0; |
||
883 | BL=AH; |
||
884 | BL-='A'; |
||
885 | EBX=EBX<<2+table; //дальше идет крах |
||
886 | DSDWORD[EBX]=EDI; // Запись указателя в table |
||
887 | } |
||
888 | $MOVSB // Запомним порядковый номер строки |
||
889 | ESI++; // Пропуск первого символа - он уже известен |
||
890 | do{ |
||
891 | $LODSB; |
||
892 | $STOSB; |
||
893 | }while(AL!=0); // Копируем строку в table |
||
894 | $POP ESI; |
||
895 | ESI+=SORTSIZE; |
||
896 | } // Продолжим для следующей строки |
||
897 | EDI--; |
||
898 | AL=_END; |
||
899 | $STOSB // table сформирована. Отметим конец |
||
900 | } |
||
901 | |||
902 | // ---- Проверка на цифру |
||
903 | dword IsNumber(dword ch) |
||
904 | { |
||
905 | IF(ch<'0')||(ch>'9')EAX=0; |
||
906 | ELSE EAX=1; |
||
907 | } |
||
908 | |||
909 | // ---- Чтение входного файла в буфер |
||
910 | long LoadInputfile(dword infile) |
||
911 | dword fhandle, size; |
||
912 | { |
||
913 | fhandle=_lopen(infile,0); |
||
914 | IF(EAX==-1){ |
||
915 | GetLastError(); |
||
916 | return(-2); |
||
917 | } |
||
918 | EAX=GetFileSize(EAX,0); |
||
919 | IF(EAX==-1){ |
||
920 | unabletoopen(infile); |
||
921 | _lclose(fhandle); |
||
922 | return(-1); |
||
923 | } |
||
924 | size=EAX; |
||
925 | input=LocalAlloc(0x40,EAX+2); // Заполненная нулями |
||
926 | IF(EAX==NULL){ |
||
927 | preerror("Not enough memory for input buffer"); |
||
928 | _lclose(fhandle); |
||
929 | RETURN(-1); |
||
930 | } |
||
931 | EAX=_lread(fhandle,input,size); |
||
932 | IF(EAX!=size){ |
||
933 | preerror("File Read error"); |
||
934 | _lclose(fhandle); |
||
935 | RETURN(-1); |
||
936 | } |
||
937 | _lclose(fhandle); |
||
938 | inptr = input; |
||
939 | inptr2 = input; |
||
940 | endoffile = 0; // На начале файла |
||
941 | return(0); |
||
942 | } |
||
943 | |||
944 | // ---- Обработка макроса |
||
945 | Macros() |
||
946 | byte holdcha; |
||
947 | byte s[STRLEN],s2[STRLEN]; |
||
948 | { |
||
949 | IF(makemapfile){ |
||
950 | fprint(mapfile,#string); |
||
951 | fprint(mapfile,"\n"); |
||
952 | } |
||
953 | holdcha=cha2; |
||
954 | $PUSH linenum2,inptr2,number,tok2,tok,input,inptr,currmod, |
||
955 | linenumber,endoffile,displaytokerrors; |
||
956 | lstrcpyA(#s,#string); |
||
957 | lstrcpyA(#s2,#string2); |
||
958 | input=#s; |
||
959 | inptr=input; |
||
960 | inptr2=input; |
||
961 | endoffile=0; // На начале файла |
||
962 | NextChar(); |
||
963 | cha2=cha; |
||
964 | inptr2=inptr; |
||
965 | linenum2 = 1; |
||
966 | NextTok(); |
||
967 | for(;;){ |
||
968 | IF(tok==tk_eof)BREAK; |
||
969 | DoCommand(); |
||
970 | } |
||
971 | lstrcpyA(#string,#s); |
||
972 | lstrcpyA(#string2,#s2); |
||
973 | $POP displaytokerrors,endoffile,linenumber,currmod,inptr,input,tok,tok2, |
||
974 | number,inptr2,linenum2; |
||
975 | cha2=holdcha; |
||
976 | } |
||
977 | |||
978 | // ---- Очистка списка локальных переменных |
||
979 | KillLocals() |
||
980 | dword ptr1,ptr2; |
||
981 | { |
||
982 | ptr2=locallist; |
||
983 | WHILE( ptr2 != NULL ){ |
||
984 | ptr1=ptr2; |
||
985 | IF( DSDWORD[EAX+localtok]==tk_locallabel) // Проверка на незакрытые метки |
||
986 | localunresolved(EAX+localid); |
||
987 | EAX=ptr2; |
||
988 | ptr2=DSDWORD[EAX+localnext]; |
||
989 | GlobalFree(ptr1); |
||
990 | } |
||
991 | locallist = NULL; |
||
992 | paramsize = 0; |
||
993 | localsize = 0; |
||
994 | } |
||
995 | |||
996 | // ---- Завершение тела процедуры |
||
997 | LeaveProc() |
||
998 | { |
||
999 | IF(localsize > 0)Asm("leave"); |
||
1000 | ELSE{ |
||
1001 | IF(paramsize > 0)Asm("pop ebp"); |
||
1002 | } |
||
1003 | IF( current_proc_type == cpt_far ){ |
||
1004 | IF(paramsize == 0)EAX="retf"; |
||
1005 | ELSE{ |
||
1006 | wsprintfA(#mapstr,"retf %d;",paramsize); |
||
1007 | EAX=#mapstr; |
||
1008 | } |
||
1009 | } |
||
1010 | ELSE{ |
||
1011 | IF(paramsize == 0)EAX="ret"; |
||
1012 | ELSE{ |
||
1013 | wsprintfA(#mapstr,"ret %d;",paramsize); |
||
1014 | EAX=#mapstr; |
||
1015 | } |
||
1016 | } |
||
1017 | Asm(EAX); |
||
1018 | } |
||
1019 | |||
1020 | // ---- Чтение очередного символа из входного буфера |
||
1021 | NextChar() |
||
1022 | { |
||
1023 | ESI> |
||
1024 | // EAX=0; |
||
1025 | $LODSB |
||
1026 | cha=AL; |
||
1027 | inptr> |
||
1028 | IF(AL==0)||(AL==26)endoffile = 1; |
||
1029 | IF(AL == 13){ // CR |
||
1030 | linenumber++; // Обнаружен конец строки |
||
1031 | totallines++; |
||
1032 | ShowSrcLine(); |
||
1033 | NextChar(); |
||
1034 | } |
||
1035 | } |
||
1036 | |||
1037 | // ---- Получение очередного token |
||
1038 | void NextTok() |
||
1039 | { |
||
1040 | inptr = inptr2; |
||
1041 | linenumber = linenum2; |
||
1042 | cha = cha2; |
||
1043 | displaytokerrors = 1; |
||
1044 | TokScan(#tok,#type,#src,#post,#string,#number); |
||
1045 | IF(linenumber!=linenum2){ // Новая строка? |
||
1046 | IF(dbg){ // Требуется отладка? |
||
1047 | $PUSH ESI |
||
1048 | ESI=dbgs*dbg_size+dbginfo; |
||
1049 | EAX=currmod; |
||
1050 | $CMP EAX,DSDWORD[ESI+dbg_mod]; |
||
1051 | $JNE DIFF // Требуется запомнить информацию по новой строке |
||
1052 | EAX=linenumber; |
||
1053 | $CMP EAX,DSDWORD[ESI+dbg_line] |
||
1054 | $JNE DIFF // Требуется запомнить информацию по новой строке |
||
1055 | DSDWORD[ESI+dbg_line]=linenumber; // Запомним номер строки |
||
1056 | GOTO ALL; |
||
1057 | DIFF: |
||
1058 | dbgs++; |
||
1059 | ESI+=dbg_size; |
||
1060 | DSDWORD[ESI+dbg_mod]=currmod; |
||
1061 | DSDWORD[ESI+dbg_line]=linenumber; |
||
1062 | DSDWORD[ESI+dbg_loc]=outptr; |
||
1063 | ALL: |
||
1064 | $POP ESI |
||
1065 | } |
||
1066 | } |
||
1067 | inptr2 = inptr; |
||
1068 | linenum2 = linenumber; |
||
1069 | cha2 = cha; |
||
1070 | displaytokerrors = 0; // Без вывода сообщений об ошибках |
||
1071 | TokScan(#tok2,#type2,#src2,#post2,#string2,#number2); |
||
1072 | linenumber = linenum2; |
||
1073 | } |
||
1074 | |||
1075 | // ---- Следующий token закрытый ; |
||
1076 | NextSemiNext () |
||
1077 | { |
||
1078 | NextTok(); |
||
1079 | SemiNext(); |
||
1080 | } |
||
1081 | |||
1082 | // ---- Закрывающий ; и token за ним |
||
1083 | SemiNext () |
||
1084 | { |
||
1085 | IF(tok != tk_semicolon)expected(';'); |
||
1086 | NextTok(); |
||
1087 | } |
||
1088 | |||
1089 | // ---- Запись байта в CODE |
||
1090 | OP() |
||
1091 | { |
||
1092 | EDI> |
||
1093 | $STOSB; |
||
1094 | outptr> |
||
1095 | } |
||
1096 | |||
1097 | // ---- Запись слова в CODE |
||
1098 | OUTWORD() |
||
1099 | { |
||
1100 | EDI> |
||
1101 | $STOSW; |
||
1102 | outptr> |
||
1103 | } |
||
1104 | // ---- Запись двойного слова в CODE |
||
1105 | OUTDWORD() |
||
1106 | { |
||
1107 | EDI> |
||
1108 | $STOSD; |
||
1109 | outptr> |
||
1110 | } |
||
1111 | |||
1112 | // ---- Вывод размеров CODE&DATA |
||
1113 | PrintMemsizes(dword handle) |
||
1114 | { |
||
1115 | wsprintfA(#mapstr,"Code:%u bytes,\tPost: %u bytes\n",outptr-output,postsize); |
||
1116 | fprint(handle,#mapstr); |
||
1117 | } |
||
1118 | |||
1119 | // ---- Обработка процедур |
||
1120 | Proc(dword proc_type) |
||
1121 | { |
||
1122 | current_proc_type = proc_type; |
||
1123 | tok = tk_proc; |
||
1124 | number = outptr-output+OptImageBase+OptBaseOfCode; |
||
1125 | ESI=treeptr; |
||
1126 | DSDWORD[ESI+rectok] = tok; |
||
1127 | DSDWORD[ESI+recnumber] = number; |
||
1128 | DSDWORD[ESI+recpost] = 0; |
||
1129 | NextTok(); |
||
1130 | expecting(tk_openbracket); |
||
1131 | IF(tok!=tk_closebracket)DeclareParams(); |
||
1132 | NextTok(); |
||
1133 | IF(paramsize > 0)Asm("push ebp;mov ebp,esp"); |
||
1134 | IF( tok != tk_openbrace )DeclareLocals(); |
||
1135 | DoBlock(); // Обработка тела процедуры { ... } |
||
1136 | LeaveProc(); |
||
1137 | KillLocals(); |
||
1138 | } |
||
1139 | |||
1140 | // ---- Запись двойного слова по адресу |
||
1141 | SetDword(dword ptr, value) |
||
1142 | { |
||
1143 | EDI> |
||
1144 | EAX> |
||
1145 | $STOSD; |
||
1146 | EDI> |
||
1147 | EAX> |
||
1148 | } |
||
1149 | |||
1150 | // ---- Вывод строки исходного текста |
||
1151 | ShowSrcLine() |
||
1152 | byte str[STRLEN]; |
||
1153 | { |
||
1154 | IF(list){ |
||
1155 | ESI> |
||
1156 | $PUSH EDI,ESI; |
||
1157 | ESI++; |
||
1158 | EDI=#str; |
||
1159 | for(;;){ |
||
1160 | $LODSB; |
||
1161 | IF(AL==13)||(AL==0)BREAK; |
||
1162 | $STOSB; |
||
1163 | } |
||
1164 | AL=0; |
||
1165 | $STOSB |
||
1166 | $POP ESI,EDI; |
||
1167 | ESI> |
||
1168 | IF(displaytokerrors){ |
||
1169 | fprint(mapfile,#str); |
||
1170 | fprint(mapfile,"\n"); |
||
1171 | } |
||
1172 | // AL=cha; |
||
1173 | } |
||
1174 | } |
||
1175 | |||
1176 | // ---- Создание файла статистики |
||
1177 | StartMapfile() |
||
1178 | byte mapfilename[80]; |
||
1179 | { |
||
1180 | wsprintfA(#mapfilename,"%s.MAP",#rawfilename); |
||
1181 | mapfile=_lcreat(#mapfilename,0x1000); |
||
1182 | IF(EAX==0){ |
||
1183 | errmsg(); |
||
1184 | WRITESTR("Unable to create map file"); |
||
1185 | WRITESTR(#mapfilename); |
||
1186 | ExitProcess(e_cannotopenmapfile); |
||
1187 | } |
||
1188 | wsprintfA(#mapstr,"MAP FILE FOR %s.%s\n\n",#rawfilename,"EXE"); |
||
1189 | fprint(mapfile,#mapstr); |
||
1190 | } |
||
1191 | |||
1192 | // ---- Инициализация списков резервных слов |
||
1193 | TokInit() |
||
1194 | { |
||
1195 | InitList(#Mnemonics,#St_Mnemonics); |
||
1196 | InitList(#Registers,#St_Registers); |
||
1197 | InitList(#Directives,#St_Directives); |
||
1198 | InitList(#Sizes,#St_Sizes); |
||
1199 | } |
||
1200 | |||
1201 | // ---- Возвращает размер для заданного типа данных |
||
1202 | dword TypeSize(dword vartype) |
||
1203 | char holdstr[60]; |
||
1204 | { |
||
1205 | IF(vartype==tk_void) RETURN(0); |
||
1206 | IF(vartype==tk_char)||(vartype==tk_byte) RETURN(1); |
||
1207 | IF(vartype==tk_short)||(vartype==tk_word) RETURN(2); |
||
1208 | IF(vartype==tk_dword)||(vartype==tk_int) RETURN(4); |
||
1209 | wsprintfA(#holdstr,"vartype=%d in TypeSize()",vartype); |
||
1210 | internalerror(holdstr); |
||
1211 | return(-1); |
||
1212 | } |
||
1213 | |||
1214 | // ---- Пропуск пробелов и табуляций |
||
1215 | WhiteSpaces() |
||
1216 | { |
||
1217 | for(;;){ |
||
1218 | AL=cha; |
||
1219 | IF(AL!=32)&&(AL!=10)&&(AL!=9)BREAK; |
||
1220 | NXT: |
||
1221 | NextChar(); |
||
1222 | } |
||
1223 | IF(AL == 13){ // CR |
||
1224 | linenumber++; // Обнаружен конец строки |
||
1225 | totallines++; |
||
1226 | ShowSrcLine(); |
||
1227 | GOTO NXT; |
||
1228 | } |
||
1229 | } |
||
1230 | |||
1231 | // ---- Вывод на stdout |
||
1232 | WRITESTR() |
||
1233 | { |
||
1234 | fprint(stdout,EAX); |
||
1235 | } |
||
1236 | |||
1237 | //===== Обработка ошибок |
||
1238 | // ---- |
||
1239 | datatype_expected() |
||
1240 | { |
||
1241 | preerror("byte, word, short, char, dword or int expected"); |
||
1242 | } |
||
1243 | |||
1244 | // ---- |
||
1245 | errmsg() |
||
1246 | { |
||
1247 | WRITESTR("\nERROR> "); |
||
1248 | } |
||
1249 | |||
1250 | // ---- |
||
1251 | expected(dword ch) |
||
1252 | byte hstr[80]; |
||
1253 | { |
||
1254 | wsprintfA(#hstr,"'%c' expected",ch); |
||
1255 | preerror(#hstr); |
||
1256 | } |
||
1257 | |||
1258 | // ---- |
||
1259 | expectederror(dword str) |
||
1260 | byte hstr[80]; |
||
1261 | { |
||
1262 | IF(displaytokerrors){ |
||
1263 | wsprintfA(#hstr,"'%s' expected",str); |
||
1264 | preerror(#hstr); |
||
1265 | } |
||
1266 | } |
||
1267 | |||
1268 | // ---- Проверка текущего token на заданный тип |
||
1269 | expecting(dword want) |
||
1270 | { |
||
1271 | if(want!=tok){ |
||
1272 | IF(want==tk_closebracket) expected(')'); |
||
1273 | else IF(want==tk_openbracket) expected('('); |
||
1274 | ELSE IF(want==tk_semicolon) expected(';'); |
||
1275 | ELSE IF(want==tk_colon) expected(':'); |
||
1276 | ELSE IF(want==tk_openblock) expected('['); |
||
1277 | ELSE IF(want==tk_closeblock) expected(']'); |
||
1278 | ELSE IF(want==tk_openbrace) expected('{'); |
||
1279 | ELSE IF(want==tk_closebrace) expected('}'); |
||
1280 | ELSE IF(want==tk_comma) expected(','); |
||
1281 | ELSE preerror("expecting a different token"); |
||
1282 | } |
||
1283 | NextTok(); |
||
1284 | } |
||
1285 | |||
1286 | // ---- |
||
1287 | /*idalreadydefined() |
||
1288 | byte holdstr[80]; |
||
1289 | { |
||
1290 | wsprintfA(#holdstr,"identifier %s already defined",#string); |
||
1291 | preerror(#holdstr); |
||
1292 | NextTok(); |
||
1293 | } */ |
||
1294 | |||
1295 | // ---- |
||
1296 | idexpected() |
||
1297 | { |
||
1298 | preerror("undefined 'identifier' expected"); |
||
1299 | } |
||
1300 | |||
1301 | // ---- Внутренняя ошибка компилятора |
||
1302 | internalerror(dword str) |
||
1303 | { |
||
1304 | error++; |
||
1305 | wsprintfA(#mapstr,"%s(%d)#%d> *** SERIOUS COMPILER INTERNAL ERROR ***\n>%s.\n", |
||
1306 | #currentfilename,linenumber,error,str); |
||
1307 | WRITESTR(#mapstr); |
||
1308 | wsprintfA(#mapstr,"STRING:%s\n",#string); |
||
1309 | WRITESTR(#mapstr); |
||
1310 | wsprintfA(#mapstr,"TOK:%d\tPOST:%d\tnumber:%ld\n",tok,post,number); |
||
1311 | WRITESTR(#mapstr); |
||
1312 | wsprintfA(#mapstr,"STRING2:%s\n",#string2); |
||
1313 | WRITESTR(#mapstr); |
||
1314 | wsprintfA(#mapstr,"TOK2:%d\tPOST2:%d\tnumber2:%ld\n",tok2,post2,number2); |
||
1315 | WRITESTR(#mapstr); |
||
1316 | WRITESTR("Oh no.\n"); |
||
1317 | IF(makemapfile)CloseHandle(mapfile); |
||
1318 | ExitProcess(e_internalerror); |
||
1319 | } |
||
1320 | |||
1321 | // ---- |
||
1322 | localunresolved(dword str) |
||
1323 | byte holdstr[80]; |
||
1324 | { |
||
1325 | wsprintfA(#holdstr,"local jump label '%s' unresolved",str); |
||
1326 | preerror(#holdstr); |
||
1327 | } |
||
1328 | |||
1329 | // ---- |
||
1330 | maxwordpostserror () |
||
1331 | { |
||
1332 | preerror("maximum number of word post location references exceeded"); |
||
1333 | } |
||
1334 | |||
1335 | // ---- |
||
1336 | /*notyet() |
||
1337 | { |
||
1338 | preerror("specified syntax not handled in this version!!!"); |
||
1339 | } */ |
||
1340 | // ---- |
||
1341 | numexpected() |
||
1342 | { |
||
1343 | preerror("'number' expected"); |
||
1344 | } |
||
1345 | |||
1346 | // ---- |
||
1347 | operatorexpected () |
||
1348 | { |
||
1349 | preerror("operator identifier expected"); |
||
1350 | } |
||
1351 | // ---- |
||
1352 | outofmemory() |
||
1353 | { |
||
1354 | preerror("Compiler out of memory"); |
||
1355 | IF( makemapfile )CloseHandle(mapfile); |
||
1356 | ExitProcess(e_outofmemory); |
||
1357 | } |
||
1358 | |||
1359 | // ---- |
||
1360 | outofmemory2() |
||
1361 | { |
||
1362 | errmsg(); |
||
1363 | WRITESTR("Not enough memory for the compiler's buffers.\n"); |
||
1364 | ExitProcess(e_outofmemory ); |
||
1365 | } |
||
1366 | |||
1367 | // ---- Ошибка в текущей строке: показ номера строки и имени файла |
||
1368 | preerror(dword str) |
||
1369 | { |
||
1370 | IF(error < maxerrors){ |
||
1371 | error++; |
||
1372 | wsprintfA(#mapstr,"%s (%d)#%d> %s.\n",#currentfilename,linenumber,error,str); |
||
1373 | WRITESTR(#mapstr); |
||
1374 | IF(makemapfile)fprint(mapfile,#mapstr); |
||
1375 | } |
||
1376 | ELSE toomanyerrors(); |
||
1377 | } |
||
1378 | |||
1379 | // ---- |
||
1380 | /*regnameerror() |
||
1381 | { |
||
1382 | preerror("register name cannot be used as an identifier"); |
||
1383 | NextTok(); |
||
1384 | } */ |
||
1385 | |||
1386 | // ---- Требуется строка |
||
1387 | stringexpected() |
||
1388 | { |
||
1389 | preerror("'string' expected"); |
||
1390 | } |
||
1391 | |||
1392 | // ---- Недопустимый операнд для swap |
||
1393 | swaperror () |
||
1394 | { |
||
1395 | preerror("invalid or incompatable swap item"); |
||
1396 | } |
||
1397 | |||
1398 | // ---- Предельное число ошибок - выход |
||
1399 | toomanyerrors() |
||
1400 | { |
||
1401 | IF( makemapfile )CloseHandle(mapfile); |
||
1402 | ExitProcess( e_toomanyerrors ); |
||
1403 | } |
||
1404 | |||
1405 | // ---- |
||
1406 | unabletoopen(dword str) |
||
1407 | byte hstr[80]; |
||
1408 | { |
||
1409 | wsprintfA(#hstr,"unable to open file '%s'",str); |
||
1410 | preerror(#hstr); |
||
1411 | } |
||
1412 | |||
1413 | // ---- |
||
1414 | undefinederror() |
||
1415 | byte holdstr[80]; |
||
1416 | { |
||
1417 | wsprintfA(#holdstr,"'%s' undefined",#string); |
||
1418 | preerror(holdstr); |
||
1419 | } |
||
1420 | |||
1421 | // ---- |
||
1422 | unexpectedeof() |
||
1423 | { |
||
1424 | preerror("unexpected END OF FILE"); |
||
1425 | } |
||
1426 | // ---- |
||
1427 | warning(dword str) |
||
1428 | { |
||
1429 | wsprintfA(#mapstr,"%s (%d)Warning> %s.\n",#currentfilename,linenumber,str); |
||
1430 | WRITESTR(#mapstr); |
||
1431 | IF(makemapfile)fprint(mapfile,#mapstr); |
||
1432 | } |
||
1433 | /* |
||
1434 | void TestProc() |
||
1435 | char buf[20]; |
||
1436 | { |
||
1437 | $pushad |
||
1438 | wsprintfA(#buf,"%08X\n",SSDWORD[EBP+4]); |
||
1439 | WRITESTR(#buf); |
||
1440 | $popad |
||
1441 | } */> |