Subversion Repositories Kolibri OS

Rev

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  [/map] [/debug]
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
} */