Subversion Repositories Kolibri OS

Rev

Rev 6618 | Rev 7545 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6446 GerdtR 1
#define _MAIN_
2
 
3
#ifdef _UNIX_
6447 GerdtR 4
#define DIV_PATH ':'			//делитель путей в переменной окружения PATH
5
#define DIV_FOLD '/'			//этим символом разделяются папки в пути к файлу
6
#endif
7
 
8
#ifdef _WIN32_
6446 GerdtR 9
#define DIV_PATH ';'
6447 GerdtR 10
#define DIV_FOLD '\\'
6446 GerdtR 11
#endif
12
 
6447 GerdtR 13
#ifdef _KOS_
14
#define DIV_PATH ';'
15
#define DIV_FOLD '/'
16
#endif
17
 
6446 GerdtR 18
#include 
6618 siemargl 19
#include 
20
#include 
6446 GerdtR 21
#include 
22
#include "tok.h"
23
 
24
static char **_Argv; //!!! simplest way to make your own variable
25
 
26
unsigned char compilerstr[]="SPHINX C-- 0.239";
27
char *rawfilename;					/* file name */
28
char *rawext;
29
LISTCOM *listcom;
30
EWAR wartype={NULL,NULL},errfile={NULL,NULL};
31
int numfindpath=0;
32
char *findpath[16];
33
char modelmem=TINY;
34
char *stubfile=NULL;
35
char *winstub=NULL;
36
FILE *hout=NULL;
37
char *namestartupfile="startup.h--";
38
 
39
char outext[4]="com";
40
short extflag=TRUE;//расширение можно присвоить
41
//int scrsize;
42
unsigned char gwarning=FALSE;
43
unsigned char sobj=FALSE;
44
unsigned char usestub=TRUE;
45
unsigned char dpmistub=FALSE;
46
short dllflag=FALSE;
47
static int numstr;
48
 
49
char meinfo[]=
50
	"\nEdition of this version by\n"
51
	"    Mishel Sheker\n"
52
	"    Fido 2:5021/3.40\n"
53
	"    E-Mail sheker@mail.ru\n"
54
	"    Russia";
55
 
56
time_t systime;
57
struct tm timeptr;
58
char comsymbios=FALSE;
59
char fobj=FALSE;	//признак генерации obj
60
unsigned int	startptr = 0x100; 			// start address
61
unsigned char wconsole=FALSE;	//признак генерации консольного приложения windows
62
unsigned char optstr=FALSE;	//оптимизация строковых констант
63
unsigned char crif=TRUE;	//check reply include file
64
unsigned char idasm=FALSE;	//ассемблерные инструкции считать идентификаторами
65
unsigned char wbss=2;	//пост переменные в отдельную секцию
66
unsigned char use_env=FALSE;	//переменная окружения
67
int numrel=0;	//число элементов в таблице перемещений
68
unsigned char useordinal=FALSE;
69
unsigned char useDOS4GW=FALSE;
70
unsigned char clearpost=FALSE;
71
unsigned char uselea=TRUE;
72
unsigned char regoverstack=TRUE;
73
unsigned char shortimport=FALSE;
74
unsigned char useinline=2;
75
unsigned char ocoff=FALSE;
76
unsigned char ESPloc=FALSE;
77
 
78
int startupfile=-1;
79
int alignproc=8,aligncycle=8;
80
 
81
char *usage[]={
82
"USAGE: C-- [options] [FILE_NAME.INI] [SOURCE_FILE_NAME]",
83
"",
84
"                       C-- COMPILER OPTIONS",
85
"",
86
"                           OPTIMIZATION",
87
"/OC  optimize for code size           /DE  enable temporary expansion variable",
88
"/OS  optimize for speed               /OST enable optimization string",
89
"/ON  enable optimization number       /AP[=n] align start function",
90
"/UST use startup code for variables   /AC[=n] align start cycles",
91
#ifdef OPTVARCONST
92
"/ORV replace variable on constant     /OIR skip repeated initializing register",
93
#else
94
"                                      /OIR skip repeated initializing register",
95
#endif
96
"",
97
"                          CODE GENERATION",
98
"/2   80286 code optimizations         /SA=#### start code address",
99
"/3   80386 code optimizations         /AL=## set value insert byte",
100
"/4   80486 code optimizations         /WFA fast call API functions",
101
"/5   pentium code optimizations       /IV  initial all variables",
102
"/A   enable address alignment         /SUV=#### start address variables",
103
"/AS[=n] def. alignment in structures  /LRS load in registers over stack",
104
"/UL  use 'lea' for adding registers   /JS  join stack calling functions",
105
"/BA  byte access to array",//             /ASP addressing local variable via ESP",
106
"",
107
"                           PREPROCESSOR",
108
"/IP=  include file path         /IA   assembly instructions as identifier",
109
"/D= defined identifier        /CRI- not check include file on repeated",
110
"/MIF= main input file           /IND= import name from dll",
111
"/SF=  other startup file",
112
"",
113
"                              LINKING",
114
"/AT    insert ATEXIT support block    /NS    disable stub",
115
"/ARGC  insert parse command line      /S=#####  set stack size",
116
"/P     insert parse command line      /WIB=##### set image base address",
117
"/C     insert CTRL ignoring code   /WFU   add Fix Up table, for Windows",
118
"/R     insert resize memory block     /WMB   create Windows mono block",
119
"/ENV   insert variable with environ   /WS= set name stub file for win32",
120
"/J0    disable initial jump to main() /WBSS  set post data in bss section",
121
"/J1    initial jump to main() short   /WO    call API functions on ordinals",
122
"/J2    initial jump to main() near    /CPA   clear post area",
123
"/STUB=  set name stub file      /WSI   short import table, for Windows",
124
"/DOS4GW file running with DOS4GW      /WAF=#### align Windows file (def 512)",
125
"/STM   startup code in main function",
126
"",
127
"                           OUTPUT FILES",
128
"/TEXE DOS EXE file (model TINY)       /D32  EXE file (32bit code for DOS)",
129
"/EXE  DOS EXE file (model SMALL)      /W32  EXE for Windows32 GUI",
130
"/OBJ  OBJ output file                 /W32C EXE for Windows32 console",
131
"/SOBJ slave OBJ output file           /DLL  DLL for Windows32",
132
"/COFF OBJ COFF output file            /DBG  create debug information",
133
"/SYM  COM file symbiosis              /LST  create assembly listing",
134
"/SYS  device (SYS) file               /B32  32bit binary files",
135
"/MEOS executable file for MeOS        /MAP  create function map file",
136
"/EXT=  set file extension",
137
"",
138
"                           MISCELLANEOUS",
139
"/HELP /H /? help, this info           /WORDS list of C-- reserved words",
140
"/W         enable warning             /LAI   list of assembler instructions",
141
"/WF= direct warnings to a file  /ME    display my name and my address",
142
"/MER=##    set maximum number errors  /X     disable SPHINX C-- header in output",
143
"/NW=##     disable selected warnings  /WE=## selected warning will be error",
144
//" /SCD        split code and date",
145
NULL};
146
 
147
char *dir[]={
148
	"ME",    "WORDS",   "SYM",   "LAI",
149
 
150
	"OBJ",   "SOBJ",    "J0",		 "J1",     "J2",    "C",     "R",
151
	"P",     "X",       "EXE",   "S",      "SYS",   "ARGC",  "TEXE",
152
	"ROM",   "W32",     "D32",   "W32C",   "AT",    "WFA",   "SA",
153
	"STM",   "SUV",     "UST",   "MIF",    "DLL", 	"DOS4GW","ENV",
154
	"CPA",   "WBSS",    "MEOS",  "SF",     "B32",   "WIB",   "DBG",
155
 
156
	"OS",    "OC",      "A",     "0",      "1",     "2",     "3",
157
	"4",     "5",       "6",     "7",      "8",     "9",     "W",
158
	"WF",    "DE",
159
	"ON",    "IP",      "STUB",  "NS",     "AP",    "D",     "OST",
160
	"CRI",   "IA",      "SCD",   "AL",     "WFU",   "IV",
161
	"MER",   "WMB",     "HELP",  "H",      "?",     "AC",    "WS",
162
	"IND",   "WO",      "NW",    "LST",    "AS",    "UL",    "LRS",
163
	"WSI",   "WAF",     "OIR",   "COFF",   "JS",    "BA",    "ASP",
164
#ifdef OPTVARCONST
165
	"ORV",
166
#endif
167
   "MAP",  "WE",   "EXT",   NULL};
168
 
169
enum {
170
	c_me,    c_key,     c_sym,   c_lasm,   c_endinfo=c_lasm,
171
 
172
	c_obj,   c_sobj,    c_j0,    c_j1,     c_j2,    c_ctrlc, c_r,
173
	c_p,     c_x,		    c_exe,   c_s,      c_sys,   c_arg,   c_texe,
174
	c_rom,   c_w32,     c_d32,   c_w32c,   c_at,    c_wfa,   c_sa,
175
	c_stm,   c_suv,     c_ust,   c_mif,    c_dll,   c_d4g,   c_env,
176
	c_cpa,   c_wbss,    c_meos,  c_sf,     c_b32,   c_wib,   c_dbg,
177
	c_endstart=c_dbg,
178
 
179
	c_os,    c_oc,      c_a,     c_0,      c_1,     c_2,     c_3,
180
	c_4,     c_5,       c_6,     c_7,      c_8,     c_9,     c_w,
181
	c_wf,    c_de,
182
	c_opnum, c_ip,      c_stub,  c_ns,     c_ap,    c_define,c_ost,
183
	c_cri,   c_ia,      c_scd,   c_al,     c_wfu,   c_iv,
184
	c_mer,   c_wmb,     c_help,  c_h,      c_hh,    c_ac,    c_ws,
185
	c_ind,   c_wo,      c_nw,    c_lst,    c_as,    c_ul,    c_lrs,
186
	c_wsi,   c_waf,     c_oir,   c_coff,   c_js,    c_ba,    c_asp,
187
#ifdef OPTVARCONST
188
	c_orv,
189
#endif
190
	c_map,   c_we,      c_ext,   c_end};
191
 
192
#define NUMEXT 6	//число разрешенных расширений компилируемого файла
193
char extcompile[NUMEXT][4]={"c--","cmm","c","h--","hmm","h"};
194
 
195
#ifdef _KOS_
196
char __pgmname[256];
197
char __cmdline[256];
198
#endif
199
 
200
char *bufstr=NULL;	//буфер для строк из процедур
201
int sbufstr=SIZEBUF;	//начальный размер этого буфера
202
 
203
void compile();
204
void PrintInfo(char **str);
205
void LoadIni(char *name);
206
//void CheckNumStr();
207
void ListId(int num,unsigned char *list,short *ofs);
208
void printmemsizes();
209
void print8item(char *str);
210
void doposts(void);
211
void GetMemExeDat();
212
void AddJmpApi();
213
void startsymbiosys(char *symfile);
214
int writeoutput();
215
void BadCommandLine(char *str);
216
void  CheckExtenshions();
217
void ImportName(char *name);
218
void WarnUnusedVar();//предупреждения о неиспользованных процедурах и переменных
219
void MakeExeHeader(EXE_DOS_HEADER *exeheader);
220
void CheckPageCode(unsigned int ofs);
221
int MakePE();
222
int MakeObj();
223
void CheckUndefClassProc();
7543 leency 224
 
6446 GerdtR 225
/*
7543 leency 226
 
227
PAVEL YAKOV
228
 
229
char* strupr(char* s)
230
{
231
  char* p = s;
232
  while (*p = toupper(*p)) p++;
233
  return s;
234
}
235
char* strlwr(char* s)
236
{
237
  char* p = s;
238
  while (*p = tolower(*p)) p++;
239
  return s;
240
}
241
int strnicmp(const char* s1, const char* s2, int len)
242
{
243
  unsigned char c1,c2;
244
 
245
  if(!len)
246
	return 0;
247
 
248
  do{
249
    c1 = *s1++;
250
    c2 = *s2++;
251
    if (!c1||!c2)
252
      break;
253
    if (c1 == c2)
254
      continue;
255
    c1 = tolower(c1);
256
    c2 = tolower(c2);
257
    if (c1!=c2)
258
      break;
259
  } while (--len);
260
  return (int)c1 - (int)c2;
261
}
262
*/
263
 
264
/*
6446 GerdtR 265
void PrintTegList(structteg *tteg)
266
{
267
	if(tteg){
268
		PrintTegList(tteg->left);
269
		PrintTegList(tteg->right);
270
		puts(tteg->name);
271
	}
272
} */
273
 
274
//unsigned long maxusedmem=0;
275
 
276
void ErrOpenFile(char *str)
277
{
278
	printf("Unable to open file %s.\n",str);
279
}
280
 
281
int main(int argc,char *argv[])
282
{
283
int count;
284
unsigned char pari=FALSE;
6447 GerdtR 285
	char *buffer;
6446 GerdtR 286
 
287
	printf("\nSPHINX C-- Compiler   Version %d.%d%s   %s\r\n",ver1,ver2,betta,__DATE__);
288
 
289
//	scrsize=24;
290
	if(argc>1){
291
		_Argv=argv;// This make portable code
292
		bufstr=(char *)MALLOC(SIZEBUF);
293
		output=(unsigned char *)MALLOC((size_t)MAXDATA);
294
		outputdata=output;
295
		postbuf=(postinfo *)MALLOC(MAXPOSTS*sizeof(postinfo));
296
		strcpy((char *)string,argv[0]);
6447 GerdtR 297
		rawext=strrchr((char *)string,DIV_FOLD);
6446 GerdtR 298
 
299
		if(rawext!=NULL){
300
			rawext[0]=0;
301
			IncludePath((char *)string);
302
		}
303
		rawfilename=getenv("C--");
304
		if(rawfilename!=NULL)IncludePath(rawfilename);
305
 
306
		rawfilename=rawext=NULL;
307
		LoadIni("c--.ini");
308
 
309
		for(count=1;count
6447 GerdtR 310
			//if(argv[count][0]=='/'||argv[count][0]=='-'){
311
			if(argv[count][0]=='-'){
6446 GerdtR 312
				if(SelectComand(argv[count]+1,&count)==c_end) BadCommandLine(argv[count]);
313
			}
314
			else{
315
				if(pari==FALSE){
316
					rawfilename=argv[count];
317
					pari=TRUE;
318
					if((rawext=strrchr(rawfilename,'.'))!=NULL){
319
						if(stricmp(rawext,".ini")==0){	//указан ini файл
320
							rawfilename=NULL;
321
							rawext=NULL;
6447 GerdtR 322
							LoadIni(argv[count]);
6446 GerdtR 323
							if(rawfilename==NULL)pari=FALSE;
324
						}
325
						else{
326
							*rawext++=0;
327
							CheckExtenshions();
328
						}
329
					}
330
				}
331
			}
332
		}
333
	}
334
	if(rawfilename==NULL){
335
		PrintInfo(usage);
336
		exit( e_noinputspecified );
337
	}
338
	time(&systime); //текущее время
339
	memcpy(&timeptr,localtime(&systime),sizeof(tm));
340
	InitDefineConst();
341
	compile();
342
	if(error==0)exit(e_ok);
343
	exit(e_someerrors);
344
	return 0;
345
}
346
 
347
void CheckExtenshions()
348
{
349
int i;
350
	for(i=0;i
351
		if(stricmp(rawext,extcompile[i])==0)break;
352
	}
353
	if(i==NUMEXT){
354
	 	printf("Bad input file extension '%s'.",rawext);
355
	  exit(e_badinputfilename);
356
	}
357
}
358
 
359
void compile()
360
{
361
long segments_required;
362
union{
363
	long longhold;
364
	void *nextstr;
365
};
366
//создать имя файла с предупреждениями и если он есть удалить
367
	errfile.name=(char *)MALLOC(strlen(rawfilename)+5);
368
	sprintf(errfile.name,"%s.err",rawfilename);
369
	if(stat(errfile.name,(struct stat *)string2)==0)remove(errfile.name);
370
//если есть имя файла для предупреждений проверить его существование и удалить.
371
	if(wartype.name!=NULL){
372
		if(stat(wartype.name,(struct stat *)string2)==0)remove(wartype.name);
373
	}
374
	puts("Compiling Commenced . . .");
375
	if(rawext!=NULL)sprintf((char *)string,"%s.%s",rawfilename,rawext);
376
	else{
377
		for(unsigned int i=0;i
378
			sprintf((char *)string,"%s.%s",rawfilename,extcompile[i]);
379
			if(stat((char *)string,(struct stat *)string2)==0)break;
380
		}
381
	}
382
	linenumber=0;
383
	initregstat();
384
#ifdef OPTVARCONST
385
	CreateMainLVIC();
386
#endif
387
#ifdef __NEWLEX__
388
	inittokn();
389
#endif
390
	compilefile((char *)string,2); //собственно разборка и компиляция
391
	puts("Link . . .");
392
	if(comfile==file_w32&&wbss==2){
393
		wbss=FALSE;
394
		if(wconsole==FALSE)wbss=TRUE;
395
	}
396
	if(notdoneprestuff==TRUE)doprestuff();	//startup code
397
	if(endifcount>=0)preerror("?endif expected before end of file");
398
	AddObj();
399
	docalls();	//добавить внешние процедуры
400
	addinitvar();
401
	CheckUndefClassProc();
402
	if(undefoffstart!=NULL){	//выдать список неизвестных ссылок
403
		UNDEFOFF *curptr=undefoffstart;
404
		for(;;){
405
			char holdstr[80];
406
			UNDEFOFF *ocurptr;
407
			linenumber=curptr->pos->line;
408
			sprintf(holdstr,"\'%s\' offset undefined",curptr->name);
409
			currentfileinfo=curptr->pos->file;
410
			preerror(holdstr);
411
			free(curptr->pos);
412
			if(curptr->next==NULL)break;
413
			ocurptr=curptr->next;
414
			free(curptr);
415
			curptr=ocurptr;
416
		}
417
		free(curptr);
418
	}
419
	while(liststring!=NULL){
420
		STRING_LIST *ins;
421
		ins=(STRING_LIST *)liststring;
422
		nextstr=ins->next;
423
		free(liststring);
424
		liststring=nextstr;
425
	}
426
	free(bufstr);
427
	if(warning==TRUE&&wact[7].usewarn)WarnUnusedVar();//предупреждения о неиспользованных процедурах и переменных
428
	if(numstrtbl)CreatStrTabRes();	//завершить создание ресурсов
429
	if(fobj==FALSE){
430
		if(comfile==file_w32&&error==0){
431
			AddJmpApi();	//косвенные вызовы API
432
			CreatWinStub();
433
		}
434
		longhold=outptr;
435
		if(comfile==file_rom){
436
			ooutptr=outptr;
437
			if(modelmem==SMALL){
438
				*(short *)&output[stackstartaddress]=(short)(((outptrdata+postsize+stacksize)/4+1)*4);
439
				*(short *)&output[dataromstart]=(short)(outptr+4);
440
				*(short *)&output[dataromsize]=(short)(outptrdata/2);
441
//				printf("outptr=%d outptrdate=%d outptrsize=%d\n",outptr,outptrdata,outptrsize);
442
				for(unsigned int i=0;i
443
			}
444
			if(romsize==0){
445
				unsigned int i=outptr/1024;
446
				if((outptr%1024)!=0)i++;
447
				if(i>32)i=64;
448
				else if(i>16)i=32;
449
				else if(i>8)i=16;
450
				else if(i>4)i=8;
451
				else if(i>2)i=4;
452
		 		romsize=i*1024;
453
				output[2]=(unsigned char)(romsize/512);
454
			}
455
			if(outptr>=romsize)preerror("The size of a code is more than the size of the ROM");
456
			for(;outptr
457
			unsigned char summa=0;
458
			for(unsigned int i=0;i
459
			output[romsize-1]-=summa;
460
			outptr=ooutptr;
461
		}
462
		else if(modelmem==SMALL&&comfile==file_exe){ // if an EXE file
463
			longhold+=AlignCD(CS,16);
464
//			if((outptr%16)!=0)outptr+=16-outptr%16;// paragraph align the end of the code seg
465
			if(((long)outptrdata+(long)postsize+(long)stacksize)>65535L)
466
					preerror("Data and stack total exceeds 64k");
467
		}
468
		else if(comfile==file_sys){
469
			for(int i=0;i
470
				searchvar((listcom+i)->name);
471
				*(short *)&output[syscom+i*2]=(unsigned short)itok.number;
472
			}
473
			free(listcom);
474
		}
475
		else longhold+=(long)postsize+(long)(stacksize);
476
		if(am32==0&&longhold>65535L&&!(modelmem==TINY&&(!resizemem)))preerror("Code, data and stack total exceeds 64k");
477
		if(posts>0)doposts();  //Установить адреса вызовов процедур и переходов
478
		if(resizemem&&comfile==file_com){
479
			segments_required=(outptr+postsize+stacksize+15)/16;
480
			*(short *)&output[resizesizeaddress]=(short)segments_required;
481
			*(short *)&output[stackstartaddress]=(short)(segments_required*16);
482
		}
483
	}
484
	deinitregstat();
485
#ifdef OPTVARCONST
486
	KillMainLVIC();
487
#endif
488
//	puts("List Teg name:");
489
//	PrintTegList(tegtree);
490
	printf("COMPILING FINISHED.  Errors: %d\n",error);
491
	if(error==0){
492
		if(cpu>=1){
493
			char m1[12];
494
			switch(cpu){
495
				case 5:
496
					strcpy(m1,"Pentium");
497
					break;
498
				case 6:
499
					strcpy(m1,"MMX");
500
					break;
501
				case 7:
502
					strcpy(m1,"Pentium II");
503
					break;
504
				case 8:
505
					strcpy(m1,"Pentium III");
506
					break;
507
				case 9:
508
					strcpy(m1,"Pentium IV");
509
					break;
510
				default: sprintf(m1,"80%d86",cpu);
511
			}
512
			printf("CPU required: %s or greater.\n",m1);
513
		}
514
		runfilesize=outptr-startptr;
515
		if(comfile==file_rom)runfilesize=romsize;
516
		else if(modelmem==SMALL&&comfile==file_exe){
517
			runfilesize+=outptrdata-startptrdata+0x20;
518
			postsize+=postsize%2;
519
			stacksize=(stacksize+15)/16*16;
520
		}
521
		else if((comfile==file_exe||comfile==file_d32)&&modelmem==TINY)
522
				runfilesize+=0x20;
523
		printmemsizes();
524
		endinptr=outptr;
525
		if(writeoutput()==0)printf("Run File Saved (%ld bytes).\n",runfilesize);
526
		if(comfile==file_w32&&fobj==FALSE)printf("Created file of a format PE for Windows.\nFor alignment section code, added %u zero bytes.\n",filingzerope);
527
//		else if(FILEALIGN&&fobj==FALSE)printf("For alignment file, added %u zero bytes.\n",filingzerope);
528
	}
529
		if(pdbg)DoTDS();
530
}
531
 
532
void printmemsizes()
533
{
534
long stacklong;
535
unsigned int stackword;
536
unsigned int postword,codeword;
537
	postword=postsize;
538
	codeword=outptr-startptr;
539
	stackword=stacksize;
540
	if(comfile==file_com||(comfile==file_exe&&modelmem==TINY)){
541
		if(resizemem==0){
542
			stacklong=0xFFFE - outptr - postsize;
543
			stackword=stacklong;
544
		}
545
		codeword=codeword-datasize-alignersize;
546
	}
547
	else if(comfile==file_sys)stackword=sysstack;
548
	else if(comfile==file_exe||comfile==file_rom)datasize=outptrdata;
549
	else if(comfile==file_d32)codeword-=datasize;
550
	printf("Code: %u bytes, Data: %u bytes, Post: %u bytes, Stack: %u bytes\n"
551
			,codeword,datasize,postword,stackword);
552
	for(int i=0;i
553
		switch((postbuf+i)->type){
554
			case CODE_SIZE:
555
				*(short *)&output[(postbuf+i)->loc]+=codeword;
556
				break;
557
			case CODE_SIZE32:
558
				*(long *)&output[(postbuf+i)->loc]+=codeword;
559
				break;
560
			case DATA_SIZE:
561
				*(short *)&output[(postbuf+i)->loc]+=datasize;
562
				break;
563
			case DATA_SIZE32:
564
				*(long *)&output[(postbuf+i)->loc]+=datasize;
565
				break;
566
			case POST_SIZE:
567
				*(short *)&output[(postbuf+i)->loc]+=postword;
568
				break;
569
			case POST_SIZE32:
570
				*(long *)&output[(postbuf+i)->loc]+=postword;
571
				break;
572
			case STACK_SIZE:
573
				*(short *)&output[(postbuf+i)->loc]+=stackword;
574
				break;
575
			case STACK_SIZE32:
576
				*(long *)&output[(postbuf+i)->loc]+=stackword;
577
				break;
578
		}
579
	}
580
}
581
 
582
void PrintInfo(char **str)
583
{
584
	numstr=1;
585
	for(int i=0;str[i]!=NULL;i++){
586
		puts(str[i]);
587
//		CheckNumStr();
588
	}
589
}
590
 
591
/*void CheckNumStr()
592
{
593
#ifndef _UNIX_
594
	if(((numstr+1)%(scrsize-1))==0&&outfile!=0){
595
		puts("Press any key...");
596
		getch();
597
	}
598
	numstr++;
599
#endif
600
} */
601
 
602
void strbtrim(char *st)
603
{
604
int i;
605
char *p,*q;
606
	p=q=st;
607
	while(isspace(*p))p++;	//пока незначащие символы
608
	while(*p)*q++=*p++;     //переместить строку
609
	*q='\0';
610
	for(i=strlen(st)-1;isspace(st[i])&&i>=0;i--);
611
	st[i+1]='\0';
612
}
613
 
614
unsigned long getnumber(unsigned char *buf)
615
{
616
int temp2;
617
unsigned long retnum;
618
unsigned char *oinput;
619
unsigned int oinptr,oendinptr;
620
	if(!isdigit(buf[0]))return 0;
621
	oinptr=inptr;
622
	oinput=input;
623
	oendinptr=endinptr;
624
	input=buf;
625
	inptr=0;
626
	endinptr=256;
627
	retnum=scannumber(&temp2);
628
	inptr=oinptr;
629
	input=oinput;
630
	endinptr=oendinptr;
631
	return retnum;
632
}
633
 
634
int SelectComand(char *pptr,int *count)
635
{
636
int i;
637
unsigned char neg=FALSE;
638
char *ptr;
639
int len;
640
	if((ptr=strchr(pptr,';'))!=NULL)*ptr=0;// ищем комментарий отсекаем все после него
641
        if((ptr=strchr(pptr,'='))!=NULL){ // ищем знак равенства
642
		*ptr=0; // делим
643
		ptr++;
644
	  strbtrim(ptr);	//убрать лишние пробелы
645
	}
646
  strbtrim(pptr);	//убрать лишние пробелы
647
	if(*pptr==0)return c_end+1;	//пустая строка
648
	if((i=strlen(pptr))>1&&pptr[i-1]=='-'){
649
		neg=TRUE;
650
		pptr[i-1]=0;
651
	}
652
	strupr(pptr);
653
	for(i=0;dir[i]!=NULL;i++){
654
		if(strcmp(dir[i],pptr)==0){
655
			if((i<=c_endinfo)&&count==0){
656
				char buf[80];
657
				sprintf(buf,"Option '%s' is used only in command line",dir[i]);
658
				preerror(buf);
659
				return i;
660
			}
661
			if(i<=c_endstart&¬doneprestuff!=TRUE){
662
errlate:
663
				char buf[80];
664
				sprintf(buf,"Too late used '#pragma option %s'",dir[i]);
665
				preerror(buf);
666
				return i;
667
			}
668
			switch(i){
669
				case c_j0: jumptomain=(unsigned char)(neg!=FALSE?CALL_NEAR:CALL_NONE); header=(unsigned char)0^neg; break;
670
				case c_j1: jumptomain=(unsigned char)CALL_SHORT; header=(unsigned char)1; break;
671
				case c_j2: jumptomain=(unsigned char)(neg==FALSE?CALL_NEAR:CALL_NONE); header=(unsigned char)1^neg; break;
672
				case c_ctrlc: killctrlc=(unsigned char)1^neg; break;
673
				case c_os: optimizespeed=(unsigned char)1^neg; break;
674
				case c_oc: optimizespeed=(unsigned char)0^neg; break;
675
				case c_r: resizemem=(unsigned char)1^neg; break;
676
				case c_p: parsecommandline=(unsigned char)1^neg; break;
677
				case c_a: alignword=(unsigned char)1^neg; break;
678
				case c_sym:
679
					startptr=0x100;
680
					comsymbios=TRUE;
681
					*count=*count+1;
682
          startsymbiosys(_Argv[*count]);
683
					break;
684
				case c_0: chip=0; break;
685
				case c_1: chip=1; break;
686
				case c_2: chip=2; break;
687
				case c_3: chip=3; break;
688
				case c_4: chip=4; break;
689
				case c_5: chip=5; break;
690
				case c_6: chip=6; break;	//MMX
691
				case c_7: chip=7; break;  //Pro
692
				case c_8: chip=8; break;  //PII
693
				case c_9: chip=9; break;  //PIII
694
				case c_x: header=(unsigned char)0^neg; break;
695
				case c_exe:
696
					comfile=file_exe;
697
					modelmem=SMALL;
698
					splitdata=TRUE;
699
					GetMemExeDat();
700
					if(extflag) strcpy(outext,"exe");
701
					startptr=0; 			// start address
702
					startptrdata=0; 	// data start address
703
					dos1=2;
704
					dos2=0;
705
					break;
706
				case c_sys:
707
					comfile=file_sys;
708
					if(extflag) strcpy(outext,"sys");
709
					startptr=0; 		// start address
710
					startptrdata=0; 	// data start address
711
					jumptomain=CALL_NONE;
712
					header=0;
713
					break;
714
				case c_sobj:
715
					sobj=TRUE;
716
					FixUp=TRUE;
717
					jumptomain=CALL_NONE;
718
				case c_obj:
719
					fobj=TRUE;
720
//					if(comfile==file_d32)FixUp=TRUE;
721
					FastCallApi=FALSE;
722
					break;
723
				case c_me:
724
					puts(meinfo);
725
					exit( e_ok );
726
				case c_key:
727
					int j,jj;
728
					puts("LIST OF RESERVED IDENTIFIERS:");
729
					numstr=1;
730
					ListId(53,id,idofs);
731
					for(j=0;j
732
						puts(id2[j]);
733
//						CheckNumStr();
734
					}
735
					for(jj=0;jj<2;jj++){
736
						for(j=0;j<8;j++)printf("%s ",regs[jj][j]);
737
						puts("");
738
//						CheckNumStr();
739
					}
740
					for(j=0;j<8;j++)printf("%s ",begs[j]);
741
					puts("");
742
//					CheckNumStr();
743
					for(j=0;j<6;j++)printf("%s ",segs[j]);
744
					print8item("ST(%d) ");
745
					puts("ST");
746
					print8item("st(%d) ");
747
					puts("st");
748
					exit(e_ok);
749
				case c_lasm:
750
					puts("LIST OF SUPPORTED ASSEMBLER INSTRUCTIONS:");
751
					numstr=1;
752
					ListId(26,asmMnem,ofsmnem);
753
					exit(e_ok);
754
				case c_s:
755
					if(ptr==NULL)return c_end;
756
					if((stacksize=getnumber((unsigned char *)ptr))==0){
757
						puts("Bad stack size.");
758
						exit(e_unknowncommandline);
759
					}
760
					stacksize=Align(stacksize,4);
761
					break;
762
				case c_w:
763
					gwarning=(unsigned char)TRUE^neg;
764
					break;
765
				case c_wf:
766
					if(wartype.name)free(wartype.name);
767
					wartype.name=BackString(ptr);
768
					break;
769
				case c_de:
770
					divexpand=(unsigned char)TRUE^neg;
771
					break;
772
				case c_opnum:
773
					optnumber=(unsigned char)TRUE^neg;
774
					break;
775
				case c_ip:
776
					IncludePath(ptr);
777
					break;
778
				case c_arg:
779
					parsecommandline=(unsigned char)TRUE^neg;
780
					fargc=(unsigned char)TRUE^neg;
781
					break;
782
				case c_texe:
783
					if(extflag) strcpy(outext,"exe");
784
					comfile=file_exe;
785
					break;
786
				case c_rom:
787
					if(extflag) strcpy(outext,"rom");
788
					comfile=file_rom;
789
					startptr=0;
790
					startptrdata=0; 	// data start address
791
					GetMemExeDat();
792
					break;
793
				case c_dll:
794
					wconsole=TRUE;
795
					dllflag=TRUE;
796
					if(extflag) strcpy(outext,"dll");
797
					comfile=file_w32;
798
					FixUpTable=TRUE;
799
					goto nexpardll;
800
 
801
/*					FixUp=TRUE;
802
					startptrdata=startptr=0;
803
					am32=TRUE;
804
					if(chip<3)chip=3;
805
					if(FILEALIGN==0)FILEALIGN=512;
806
					break;*/
807
				case c_w32c:
808
					wconsole=TRUE;
809
					goto init_w32;
810
				case c_w32:
811
					wconsole=FALSE;
812
					dllflag=FALSE;
813
init_w32:
814
					comfile=file_w32;
815
					goto nexpar;
816
				case c_d32:
817
					comfile=file_d32;
818
nexpar:
819
					if(extflag) strcpy(outext,"exe");
820
nexpardll:
821
					FixUp=TRUE;
822
					startptrdata=startptr=0;
823
					am32=TRUE;
824
					if(chip<3)chip=3;
825
					if(FILEALIGN==0)FILEALIGN=512;
826
					break;
827
				case c_meos:
828
					comfile=file_meos;
829
					am32=TRUE;
830
					startptrdata=startptr=0;
831
					if(extflag) strcpy(outext,"");
832
					if(chip<3)chip=3;
833
					break;
834
				case c_b32:
835
					comfile=file_bin;
836
					am32=TRUE;
837
					startptrdata=startptr=0;
838
					if(extflag) strcpy(outext,"bin");
839
					FixUp=TRUE;
840
					ImageBase=0;
841
					if(chip<3)chip=3;
842
					break;
843
				case c_stub:
844
					if(stubfile)free(stubfile);
845
					stubfile=BackString(ptr);
846
					dpmistub=FALSE;
847
					if(stricmp(stubfile,"dpmi")==0){
848
						if(notdoneprestuff!=TRUE)goto errlate;
849
						dpmistub=TRUE;
850
						usestub=FALSE;
851
					}
852
					break;
853
				case c_ns:
854
					usestub=(unsigned char)0^neg;
855
					break;
856
				case c_ap:
857
					AlignProc=(unsigned char)1^neg;
858
					if(ptr!=NULL){
859
						alignproc=getnumber((unsigned char *)ptr);
860
						if(alignproc<1||alignproc>4096)alignproc=8;
861
					}
862
					break;
863
				case c_define:
864
					addconsttotree(ptr,TRUE);
865
					break;
866
				case c_ost:
867
					optstr=(unsigned char)TRUE^neg;
868
					break;
869
				case c_cri:
870
					crif=(unsigned char)1^neg;
871
					break;
872
				case c_ia:
873
					idasm=(unsigned char)1^neg;
874
					break;
875
				case c_dbg:
876
					dbg&=0xFE;
877
					char c;
878
					c=(unsigned char)1^neg;
879
					dbg|=c;
880
					if(!neg)InitDbg();
881
					break;
882
				case c_scd:
883
/*-----------------13.08.00 23:01-------------------
884
 будет введена после доработки динамических процедур
885
	--------------------------------------------------*/
886
					splitdata=(unsigned char)1^neg;
887
					if(modelmem==SMALL)splitdata=TRUE;
888
					break;
889
				case c_al:
890
					if(ptr==NULL)return c_end;
891
					aligner=(unsigned char)getnumber((unsigned char *)ptr);
892
					break;
893
				case c_at:
894
					atex=(unsigned char)1^neg;
895
					break;
896
				case c_wfa:
897
					FastCallApi=(unsigned char)1^neg;
898
					break;
899
				case c_wfu:
900
					FixUpTable=(unsigned char)1^neg;
901
					break;
902
				case c_wib:
903
					if(ptr==NULL)return c_end;
904
					ImageBase=getnumber((unsigned char *)ptr);
905
					break;
906
				case c_iv:
907
					notpost=(unsigned char)1^neg;
908
					break;
909
				case c_mer:
910
					if(ptr==NULL)return c_end;
911
					if((maxerrors=getnumber((unsigned char *)ptr))==0)maxerrors=16;
912
					break;
913
				case c_sa:
914
					if(ptr==NULL)return c_end;
915
					startptrdata=startptr=getnumber((unsigned char *)ptr);
916
					break;
917
				case c_stm:
918
					startuptomain=(unsigned char)1^neg;
919
					break;
920
				case c_suv:
921
					if(ptr==NULL)return c_end;
922
					startStartup=getnumber((unsigned char *)ptr);
923
					break;
924
				case c_wmb:
925
					WinMonoBlock=(unsigned char)1^neg;
926
					break;
927
				case c_ust:
928
					useStartup=(unsigned char)1^neg;
929
					break;
930
				case c_help:
931
				case c_h:
932
				case c_hh:
933
					PrintInfo(usage);
934
					exit(e_ok);
935
				case c_mif:
936
					if(ptr==NULL)return c_end;
937
					if(rawfilename!=NULL){
938
						free(rawfilename);
939
						rawfilename=NULL;
940
					}
941
					if(rawext!=NULL){
942
						free(rawext);
943
						rawext=NULL;
944
					}
945
					char *temp;
946
        	if((temp=strrchr(ptr,'.'))!=NULL){
947
						*temp++=0;
948
						rawext=BackString(temp);
949
						CheckExtenshions();
950
 	  	    }
951
					rawfilename=BackString(ptr);
952
					break;
953
				case c_ac:
954
					AlignCycle=(unsigned char)1^neg;
955
					if(ptr!=NULL){
956
						aligncycle=getnumber((unsigned char *)ptr);
957
						if(aligncycle<1&&aligncycle>4096)aligncycle=8;
958
					}
959
					break;
960
				case c_ws:	//dos-stub for windows programs
961
					if(winstub)free(winstub);
962
					winstub=BackString(ptr);
963
					break;
964
				case c_ind:
965
					ImportName(ptr);
966
					break;
967
				case c_wbss:
968
					wbss=(unsigned char)1^neg;
969
					break;
970
				case c_wo:
971
					useordinal=(unsigned char)1^neg;
972
					break;
973
				case c_nw:
974
					if(ptr==NULL)return c_end;
975
					len=getnumber((unsigned char *)ptr);
976
					if(len>0&&len<=WARNCOUNT)wact[len-1].usewarn=(unsigned char)0^neg;
977
					break;
978
				case c_we:
979
					if(ptr==NULL)return c_end;
980
					len=getnumber((unsigned char *)ptr);
981
					if(len>0&&len<=WARNCOUNT){
982
						if(neg)wact[len-1].fwarn=warningprint;
983
						else wact[len-1].fwarn=preerror3;
984
					}
985
					break;
986
				case c_lst:
987
					SetLST(neg);
988
					break;
989
				case c_d4g:
990
					useDOS4GW=(unsigned char)1^neg;
991
					break;
992
				case c_env:
993
					use_env=(unsigned char)1^neg;
994
					break;
995
				case c_cpa:
996
					clearpost=(unsigned char)1^neg;
997
					break;
998
				case c_ul:
999
					uselea=(unsigned char)1^neg;
1000
					break;
1001
				case c_as:
1002
					if(ptr){
1003
						len=getnumber((unsigned char *)ptr);
1004
						if(caselong(len)!=NUMNUM)strpackdef=len;
1005
					}
1006
					else strpackdef=(neg==FALSE?8:1);
1007
					strpackcur=strpackdef;
1008
					break;
1009
				case c_lrs:
1010
					regoverstack=(unsigned char)1^neg;
1011
					break;
1012
				case c_wsi:
1013
					shortimport=(unsigned char)1^neg;
1014
					break;
1015
				case c_waf:
1016
					if(ptr!=NULL){
1017
						FILEALIGN=Align(getnumber((unsigned char *)ptr),16);
1018
					}
1019
					break;
1020
				case c_sf:
1021
					if(ptr==NULL)return c_end;
1022
					namestartupfile=BackString(ptr);
1023
					break;
1024
				case c_oir:
1025
					optinitreg=(unsigned char)1^neg;
1026
					break;
1027
				case c_coff:
1028
					ocoff=(unsigned char)1^neg;
1029
					break;
1030
				case c_js:
1031
					addstack=(unsigned char)1^neg;
1032
					if(addstack==0)RestoreStack();
1033
					break;
1034
				case c_ba:
1035
					bytesize=(unsigned char)1^neg;
1036
					break;
1037
				case c_asp:
1038
					if(blockproc)goto errlate;
1039
					else ESPloc=(unsigned char)1^neg;
1040
					break;
1041
#ifdef OPTVARCONST
1042
				case c_orv:
1043
					replasevar=(unsigned char)1^neg;
1044
					if(replasevar&&listvic)ClearLVIC();
1045
					break;
1046
				case c_map:
1047
					mapfile=(unsigned char)1^neg;
1048
					break;
1049
#endif
1050
				case c_ext:     //***lev***
1051
					strcpy(outext,BackString(ptr)); //***lev***
1052
					extflag=FALSE; //чтобы расширение не перезабивалось другими ключами, если они идут позже
1053
					break;  //***lev***
1054
			}
1055
			break;
1056
		}
1057
	}
1058
	return i;
1059
}
1060
 
1061
void SetLST(unsigned char neg)
1062
{
1063
	if(((dbg&2)>>1)==neg){
1064
		dbg&=0xFD;
1065
		unsigned char c=(unsigned char)((1^neg)<<1);
1066
		dbg|=c;
1067
		if(neg){
1068
			if((dbg&0xFE)==0)dbgact=TRUE;
1069
			AddEndLine();
1070
		}
1071
		else{
1072
			InitDbg();
1073
			if(notdoneprestuff!=TRUE)dbgact=FALSE;	//startup cod
1074
		}
1075
	}
1076
}
1077
 
1078
void print8item(char *str)
1079
{
1080
//	CheckNumStr();
1081
	for(int j=0;j<8;j++)printf(str,j);
1082
	puts("");
1083
}
1084
 
1085
 
1086
 
1087
 
1088
void _loadIni(FILE *inih)
1089
{
1090
	char m1[256];
1091
	for(;;){
1092
		if(fgets(m1,255,inih)==NULL)break;
1093
		if(SelectComand(m1,0)==c_end)BadCommandLine(m1);
1094
	}
1095
	fclose(inih);
1096
}
1097
 
1098
void LoadIni(char *name)
1099
{
1100
FILE *inih;
1101
char m1[256];
1102
 
1103
							// load name
6447 GerdtR 1104
	if (inih = fopen(name,"rb"))
1105
	{_loadIni(inih);return;}
6446 GerdtR 1106
 
6447 GerdtR 1107
	if(strcmp(name,"c--.ini")!=0)
1108
			return;
6446 GerdtR 1109
 
1110
							//load findpath[0]\c--.ini
6447 GerdtR 1111
	if (findpath[0]!=0)
6446 GerdtR 1112
	{
6447 GerdtR 1113
		sprintf(m1,"%s%s",findpath[0],name);
6446 GerdtR 1114
		if (inih = fopen(m1,"rb"))
1115
		{_loadIni(inih);return;}
6447 GerdtR 1116
	}
6446 GerdtR 1117
							//load PATH[i=0..end]/c--.ini
6447 GerdtR 1118
	char* pth = getenv("PATH");
6446 GerdtR 1119
	if (pth != 0)
1120
	{
1121
		char* start;
1122
		int size;
1123
		start = pth;
1124
		while(*start)
1125
		{
1126
			size = 0;
1127
			char* endp = strchr(start, DIV_PATH);
1128
			size = (endp == 0)? strlen(start): endp-start;
1129
			strncpy(m1, start, size);
1130
			start += size + 1;
6447 GerdtR 1131
			if (m1[size - 1] != DIV_FOLD)
6446 GerdtR 1132
				m1[size++] = '/';
1133
 
1134
			strcpy(m1 + size,"c--.ini");
1135
			if (inih = fopen(m1,"rb"))
1136
			{_loadIni(inih);return;}
1137
		}
1138
	}
1139
#ifdef _KOS_
1140
								//for KolibriOS: load program_dir/c--.ini
1141
	int p;
1142
	strcpy(m1,__pgmname);
1143
	p = strlen(m1);
1144
	while ((*(m1+p)!='/') && (p != 0))
1145
		p--;
1146
	if (p){
1147
		p++;
1148
		strcpy(m1+p,"c--.ini");
6447 GerdtR 1149
		if (inih = fopen(m1,"rb"))
1150
		{_loadIni(inih);return;}
6446 GerdtR 1151
	}
6447 GerdtR 1152
								//for KolibriOS: load /rd/0/settings/c--.ini
6446 GerdtR 1153
	inih = fopen("/rd/1/settings/c--.ini","rb");
6447 GerdtR 1154
	for(;;){
1155
		if(fgets(m1,255,inih)==NULL)break;
1156
		if(SelectComand(m1,0)==c_end)BadCommandLine(m1);
1157
	}
6446 GerdtR 1158
	fclose(inih);
6447 GerdtR 1159
	return;
1160
#endif //_KOS_
6446 GerdtR 1161
}
1162
 
1163
/*****************************************************************************
1164
* .NAME   : MALLOC
1165
* .TITLE  : Выделяет память с обработкой ошибок.
1166
*****************************************************************************/
1167
void OutMemory()
1168
{
1169
	preerror("Compiler out of memory");
1170
	exit(e_outofmemory);
1171
}
1172
 
1173
void * MALLOC (unsigned long size)
1174
{
1175
void *mem;
1176
	mem=malloc(size);
1177
	if(mem==NULL)OutMemory();
1178
 
1179
//	if(((unsigned long)mem+size)>maxusedmem)maxusedmem=(unsigned long)mem+size;
1180
 
1181
	return mem;
1182
}
1183
 
1184
void *REALLOC(void *block,unsigned long size)
1185
{
1186
void *mem;
1187
	mem=realloc(block,size);
1188
	if(mem==NULL)OutMemory();
1189
 
1190
//	if(((unsigned long)mem+size)>maxusedmem)maxusedmem=(unsigned long)mem+size;
1191
 
1192
	return mem;
1193
}
1194
 
1195
void IncludePath(char *buf)
1196
{
6447 GerdtR 1197
	char divfold[3];
1198
	sprintf(divfold,"%c",DIV_FOLD);
6446 GerdtR 1199
	if(numfindpath
1200
		int len=strlen(buf);
6447 GerdtR 1201
		if(buf[len-1]==DIV_FOLD)buf[len-1]=0;
6446 GerdtR 1202
		else len++;
1203
		char *a=(char *)MALLOC(len+1);
1204
		strcpy(a,buf);
6447 GerdtR 1205
		strcat(a,divfold);
6446 GerdtR 1206
		findpath[numfindpath]=a;
1207
		numfindpath++;
1208
		findpath[numfindpath]="";
1209
	}
1210
	else puts("Too many include paths");
1211
}
1212
 
1213
void doposts()
1214
{
1215
unsigned long addvalue,i,addval,addvalw32=0,addvalbss=0;
1216
	if(splitdata&&modelmem==TINY&&outptrdata){
1217
		memcpy((char *)&output[outptr],(char *)&outputdata[0],outptrdata);
1218
		addval=outptr;
1219
		outptr+=outptrdata;
1220
		outptrdata=outptr;
1221
	}
1222
	addvalue=outptrdata;
1223
	if(comfile==file_bin)addvalbss=addvalw32=ImageBase;
1224
	else if(comfile==file_w32){
1225
		addvalbss=addvalw32=ImageBase+vsizeheader;
1226
		if(postsize&&wbss){
1227
			addvalw32+=Align(postsize,OBJECTALIGN);
1228
			addvalue=0;
1229
		}
1230
	}
1231
	else{
1232
		if((outptrdata%2)==1){	/* alignment of entire post data block manditory */
1233
			addvalue++;	//начало неиниц.данных
1234
			postsize++;
1235
		}
1236
/*		if(am32&&(outptrdata%4)==2){
1237
			addvalue+=2;	//начало неиниц.данных
1238
			postsize+=2;
1239
		}*/
1240
	}
1241
	if(am32==0&&(MAXDATA-outptrdata)
1242
	for(i=0;i
1243
		switch((postbuf+i)->type){
1244
			case POST_VAR:
1245
				*(short *)&output[(postbuf+i)->loc]+=(short)addvalue;
1246
				break;
1247
			case POST_VAR32:
1248
				*(long *)&output[(postbuf+i)->loc]+=addvalue+addvalbss;
1249
				numrel++;
1250
				break;
1251
			case FIX_VAR32:
1252
			case FIX_CODE32:
1253
				*(long *)&output[(postbuf+i)->loc]+=addvalw32;
1254
				numrel++;
1255
				break;
1256
			case FIX_CODE_ADD:
1257
				if(am32){
1258
					*(long *)&output[(postbuf+i)->loc]+=addvalw32+(postbuf+i)->num;
1259
					(postbuf+i)->type=(unsigned short)FIX_VAR32;
1260
				}
1261
				else{
1262
					*(short *)&output[(postbuf+i)->loc]+=(short)(addval+(postbuf+i)->num);
1263
					(postbuf+i)->type=(unsigned short)FIX_VAR;
1264
				}
1265
				numrel++;
1266
				break;
1267
			case DATABLOCK_VAR:
1268
				*(short *)&output[(postbuf+i)->loc]+=(short)addval;
1269
				if(FixUp)(postbuf+i)->type=(unsigned short)FIX_VAR;
1270
				break;
1271
			case DATABLOCK_VAR32:
1272
				*(long *)&output[(postbuf+i)->loc]+=addval+addvalw32;
1273
				if(FixUp)(postbuf+i)->type=(unsigned short)FIX_VAR32;
1274
				numrel++;
1275
				break;
1276
		}
1277
	}
1278
	ooutptr=addvalue;	//сохранить начало post для debug;
1279
}
1280
 
1281
void GetMemExeDat()
1282
{
1283
	if(outputdata==output&&outputdata!=0)outputdata=(unsigned char *)MALLOC((size_t)MAXDATA);
1284
}
1285
 
1286
void ListId(int numfirstchar,unsigned char *list,short *ofs)
1287
{
1288
char buf[40];
1289
	for(int i=0;i
1290
		if((short)ofs[i]!=-1){
1291
			if(i<26)buf[0]=(char)('A'+i);
1292
			else if(i==26)buf[0]='_';
1293
			else buf[0]=(char)(i-27+'a');
1294
			unsigned char *ii=(unsigned char *)(list+ofs[i]);
1295
			while(*(short *)&*ii!=-1){
1296
				ii+=2;
1297
				strcpy(buf+1,(char *)ii);
1298
				ii+=strlen((char *)ii)+1;
1299
				puts(buf);
1300
//				CheckNumStr();
1301
			}
1302
		}
1303
	}
1304
}
1305
 
1306
int writeoutput()
1307
{
1308
EXE_DOS_HEADER exeheader;  // header for EXE format
1309
	if(fobj){
1310
		if(comfile==file_w32&&ocoff)return MakeCoff();
1311
		return MakeObj();
1312
	}
1313
	if(comfile==file_w32)return MakePE();
1314
	if(comfile==file_meos)return MakeMEOS();
1315
	if(comfile==file_bin)return MakeBin32();
1316
	memset(&exeheader,0,sizeof(EXE_DOS_HEADER));
1317
	if(comfile==file_d32){
1318
		if(usestub){
1319
			MakeLE();
1320
			runfilesize+=ftell(hout)-32;
1321
			goto savecode;
1322
		}
1323
		else goto exefile;
1324
	}
1325
	if(comfile==file_com||comfile==file_sys||comfile==file_rom){
1326
		hout=CreateOutPut(outext,"wb");
1327
		if(fwrite(output+startptr,comfile==file_rom?romsize:outptr-startptr,1,hout)!=1){
1328
			ErrWrite();
1329
			return(-1);
1330
		}
1331
	}
1332
	else if(comfile==file_exe){
1333
exefile:
1334
		hout=CreateOutPut(outext,"wb");
1335
		MakeExeHeader(&exeheader);
1336
		if(fwrite(&exeheader,sizeof(EXE_DOS_HEADER),1,hout)!=1){
1337
errwr:
1338
			fclose(hout);
1339
			hout=NULL;
1340
			ErrWrite();
1341
			return(-1);
1342
		}
1343
		outputcodestart=ftell(hout);
1344
savecode:
1345
		if(fwrite(output+startptr,outptr-startptr,1,hout)!=1)goto errwr;
1346
		if(modelmem==SMALL&&outptrdata!=0){
1347
			if(fwrite(outputdata,outptrdata,1,hout)!=1)goto errwr;
1348
		}
1349
	}
1350
	fclose(hout);
1351
	hout=NULL;
1352
	return(0);
1353
}
1354
 
1355
long CopyFile(FILE *in,FILE *out)
1356
{
1357
char tbuf[1024];
1358
long loads=0;
1359
unsigned int len;
1360
	do{
1361
		len=fread(tbuf,1,1024,in);
1362
		if(fwrite(tbuf,1,len,out)!=len){
1363
			ErrWrite();
1364
			return -1;
1365
		}
1366
		loads+=len;
1367
	}while(len==1024);
1368
	return loads;
1369
}
1370
 
1371
unsigned int EntryPoint()
1372
{
1373
ITOK btok;
1374
int bb=tk_id;
1375
unsigned char bufmain[]="main";
1376
unsigned char buf2[]="__startupproc";
1377
unsigned char *buf;
1378
	if(comfile==file_com)return startptr;
1379
	btok.number=0;
1380
//	if(jumptomain!=CALL_NONE||(comfile==file_w32&&dllflag))buf=buf2;
1381
//	else buf=bufmain;
1382
 
1383
	if(jumptomain==CALL_NONE){
1384
		if(useDOS4GW)buf=buf2;
1385
		else buf=bufmain;
1386
	}
1387
	else buf=buf2;
1388
 
1389
	searchtree(&btok,&bb,buf);
1390
	if(bb==tk_id){
1391
		if(comfile==file_w32&&dllflag)return 0xffffffff;
1392
		printf("Error! Entry point '%s' is not found.\n",buf);
1393
		exit(e_entrynotfound);
1394
	}
1395
	return btok.number;
1396
}
1397
 
1398
void MakeExeHeader(EXE_DOS_HEADER *exeheader)
1399
{
1400
long paragraphsrequired;
1401
unsigned short count,i;
1402
int pointstart;
1403
	exeheader->sign=0x5a4D;				 // MZ
1404
//	if(modelmem==TINY&&comfile==file_exe)pointstart=0x100;
1405
/*	else*/ pointstart=EntryPoint();
1406
	count=(unsigned short)(runfilesize%512);
1407
	i=(unsigned short)(runfilesize/512);
1408
	exeheader->numlastbyte=count;
1409
	exeheader->numpage=(unsigned short)(count==0?i:i+1);
1410
	exeheader->headsize=2; 		// size of header in paragraphs (2 paragraphs)
1411
	exeheader->initIP=(unsigned short)pointstart;	 // IP at entry (0x0000)
1412
	paragraphsrequired=(outptr+outptrdata+postsize+stacksize+15)/16;
1413
	if(modelmem==TINY&&comfile==file_exe){
1414
		exeheader->initSS=0xFFF0; 		 // displacement of SS
1415
		exeheader->initSP=0xFFFE; // intial value of SP
1416
		exeheader->initCS=0xfff0;						 // displacement of CS (0x0000)
1417
		if(!resizemem){
1418
			exeheader->minmem=0xfff;	// min-paragraphs
1419
			exeheader->maxmem=0xffff;	// max-paragraphs
1420
		}
1421
		else{
1422
			paragraphsrequired-=0x10;
1423
			exeheader->initSP=(unsigned short)(paragraphsrequired*16); // intial value of SP
1424
			exeheader->minmem=(unsigned short)paragraphsrequired;	// min-paragraphs
1425
			exeheader->maxmem=(unsigned short)paragraphsrequired;	// max-paragraphs
1426
		}
1427
	}
1428
	else if(comfile==file_d32){
1429
		exeheader->initSP=(unsigned short)stacksize; // intial value of SP
1430
		exeheader->initSS=(unsigned short)((outptr+postsize+15)/16); // displacement of SS
1431
		exeheader->initCS=(unsigned short)((pointstart/65536)*4096);
1432
		if(resizemem){
1433
			exeheader->minmem=(unsigned short)paragraphsrequired;	// min-paragraphs
1434
			exeheader->maxmem=(unsigned short)paragraphsrequired;	// max-paragraphs
1435
		}
1436
		else exeheader->maxmem=(unsigned short)0xFFFF;	// max-paragraphs
1437
	}
1438
	else{
1439
		exeheader->initSS=(unsigned short)(outptr/16); 		 // displacement of SS
1440
		exeheader->initSP=(unsigned short)(outptrdata+postsize+stacksize); // intial value of SP
1441
		exeheader->minmem=(unsigned short)paragraphsrequired;	// min-paragraphs
1442
		exeheader->maxmem=(unsigned short)paragraphsrequired;	// max-paragraphs
1443
	}
1444
	exeheader->ofsreloc=0x1c;						 // offset of first relocation item (0x0000)
1445
}
1446
 
1447
void startsymbiosys(char *symfile)
1448
{
1449
unsigned int size;
1450
int filehandle;
1451
long filesize;
1452
	outptr=startptr;
1453
	if((filehandle=open(symfile,O_BINARY|O_RDONLY))==-1){;
1454
		ErrOpenFile(symfile);
1455
		exit(e_symbioerror);
1456
	}
1457
	if((filesize=getfilelen(filehandle))!=-1L){
1458
		if(filesize+outptr
1459
			size=filesize;
1460
			if((unsigned int)read(filehandle,output+outptr,size)!=size){
1461
				close(filehandle);
1462
				puts("Error reading symbio COM file.");
1463
				exit(e_symbioerror);
1464
			}
1465
			outptr+=size;
1466
		}
1467
		else{
1468
			puts("Symbio COM file is too large.");
1469
			exit(e_symbioerror);
1470
		}
1471
	}
1472
	else{
1473
		puts("Unable to determine symbio COM file size.");
1474
		exit(e_symbioerror);
1475
	}
1476
	close(filehandle);
1477
	outptrdata=outptr;
1478
	outputcodestart=outptr-startptr;
1479
	addconsttotree("__comsymbios",TRUE);
1480
}
1481
 
1482
void BadCommandLine(char *str)
1483
{
1484
	printf("Unknown or bad command line option '%s'.\n",str);
1485
//					PrintInfo(usage);
1486
	exit(e_unknowncommandline);
1487
}
1488
 
1489
void warnunused(struct idrec *ptr)
1490
{
1491
//static count=0;
1492
	if(ptr!=NULL){
1493
		if(ptr->count==0&&startupfile!=ptr->file){
1494
			linenumber=ptr->line;
1495
			currentfileinfo=ptr->file;
1496
			int i=0;
1497
			switch(ptr->rectok){
1498
				case tk_proc:
1499
					if(ptr->recsegm!=NOT_DYNAMIC||strcmp(ptr->recid,mesmain)==0)break;
1500
					i++;
1501
				case tk_structvar:
1502
					i++;
1503
				case tk_charvar:
1504
				case tk_bytevar:
1505
				case tk_intvar:
1506
				case tk_wordvar:
1507
				case tk_longvar:
1508
				case tk_dwordvar:
1509
				case tk_floatvar:
1510
				case tk_pointer:
1511
				case tk_qword:
1512
				case tk_double:
1513
					if(i<=1&&(ptr->recpost==DYNAMIC_VAR||ptr->recpost==DYNAMIC_POST))break;
1514
					warningnotused(ptr->recid,i);
1515
					break;
1516
			}
1517
		}
1518
		warnunused(ptr ->left);
1519
		warnunused(ptr ->right);
1520
	}
1521
}
1522
 
1523
void WarnUnusedVar()//предупреждения о неиспользованных процедурах и переменных
1524
{
1525
	warnunused(treestart);
1526
	for(unsigned int i=0;istlist);
1527
}
1528
 
1529
void addinitvar()
1530
{
1531
unsigned int i;
1532
	if(numfloatconst){	//вставить константы float и привязать их
1533
		if(alignword||optimizespeed)AlignCD(DS,chip>5?16:4);
1534
		for(i=0;i
1535
			if((postbuf+i)->type==POST_FLOATNUM){
1536
				if(am32)*(unsigned long *)&output[(postbuf+i)->loc]=outptrdata+(postbuf+i)->num;
1537
				else *(unsigned short *)&output[(postbuf+i)->loc]=(unsigned short)(outptrdata+(postbuf+i)->num);
1538
				if(FixUp)(postbuf+i)->type=FIX_VAR32;
1539
				else killpost(i--);
1540
			}
1541
		}
1542
		for(i=0;i
1543
			if(dbg&2){
1544
				if((floatnum+i)->type==tk_float)sprintf((char *)string,"const float %f",(floatnum+i)->fnum);
1545
				else sprintf((char *)string,"const double %f",(floatnum+i)->dnum);
1546
				AddDataNullLine(4,(char *)string);
1547
			}
1548
			outdwordd((floatnum+i)->num[0]);
1549
			if((floatnum+i)->type!=tk_float){
1550
				outdwordd((floatnum+i)->num[1]);
1551
				datasize+=4;
1552
			}
1553
			datasize+=4;
1554
		}
1555
		free(floatnum);
1556
		numfloatconst=0;
1557
		floatnum=NULL;
1558
	}
1559
	for(i=0;i<(unsigned int)numswtable;i++){	//создать и вставить таблицы switch
1560
		int j;
1561
		FSWI *swt=swtables+i;
1562
		if(alignword)AlignCD(DS,swt->type);
1563
		if(dbg&2)AddDataNullLine((char)swt->type,"switch table address");
1564
		if(am32==FALSE){	//вставить в код адрес таблицы
1565
			*(unsigned short *)&output[swt->ptb]=(unsigned short)outptrdata;
1566
		}
1567
		else *(unsigned long *)&output[swt->ptb]=outptrdata;
1568
		unsigned char oam32=am32;
1569
		am32=(unsigned char)(swt->type/2-1);
1570
 
1571
		unsigned long val=swt->defal;
1572
		int oline=outptrdata;
1573
		for(j=0;jsizetab;j++){	//заполнить таблицу значениями по умолчанию
1574
//			if((swt->info+jj)->type==singlcase)
1575
			AddReloc(DS);
1576
			if(am32)outdwordd(val);
1577
			else outwordd(val);
1578
		}
1579
		if(swt->mode==2){
1580
			if(dbg&2)AddDataNullLine((char)swt->razr,"switch table value");
1581
			if(oam32==FALSE){	//вставить в код адрес таблицы
1582
				*(unsigned short *)&output[swt->ptv]=(unsigned short)outptrdata;
1583
			}
1584
			else *(unsigned long *)&output[swt->ptv]=outptrdata;
1585
		}
1586
		int ii=0;	//счетчик case
1587
		for(int jj=0;jjnumcase;jj++){
1588
			j=(swt->info+jj)->value;	//значение
1589
			val=(swt->info+jj)->postcase;
1590
			if((swt->info+jj)->type==singlcase){
1591
				if(swt->mode==1){
1592
					if(am32==FALSE)*(unsigned short *)&outputdata[oline+j*2]=(unsigned short)val;
1593
					else *(unsigned long *)&outputdata[oline+j*4]=val;
1594
				}
1595
				else{
1596
					if(am32==FALSE)*(unsigned short *)&outputdata[oline+ii*2]=(unsigned short)val;
1597
					else *(unsigned long *)&outputdata[oline+ii*4]=val;
1598
					switch(swt->razr){
1599
						case r8: opd(j); break;
1600
						case r16: outwordd(j); break;
1601
						case r32: outdwordd(j); break;
1602
					}
1603
					ii++;
1604
				}
1605
			}
1606
			else{
1607
				jj++;
1608
				for(;(unsigned int)j<=(swt->info+jj)->value;j++){
1609
					if(swt->mode==1){
1610
						if(am32==FALSE)*(unsigned short *)&outputdata[oline+j*2]=(unsigned short)val;
1611
						else *(unsigned long *)&outputdata[oline+j*4]=val;
1612
					}
1613
					else{
1614
						if(am32==FALSE)*(unsigned short *)&outputdata[oline+ii*2]=(unsigned short)val;
1615
						else *(unsigned long *)&outputdata[oline+ii*4]=val;
1616
						switch(swt->razr){
1617
							case r8: opd(j); break;
1618
							case r16: outwordd(j); break;
1619
							case r32: outdwordd(j); break;
1620
						}
1621
						ii++;
1622
					}
1623
				}
1624
			}
1625
		}
1626
		am32=oam32;
1627
		free(swt->info);
1628
	}
1629
	if(numswtable){
1630
		free(swtables);
1631
		numswtable=0;
1632
	}
1633
 
1634
	for(i=0;i
1635
		if((postbuf+i)->type==DIN_VAR||(postbuf+i)->type==DIN_VAR32){
1636
			idrec *ptr=(idrec *)(postbuf+i)->num;
1637
//			printf("post=%u num=%08X %s\n",ptr->recpost,ptr->recnumber,ptr->recid);
1638
			if(ptr->recpost==USED_DIN_VAR)setdindata(ptr,i);
1639
			else{
1640
				if((postbuf+i)->type==DIN_VAR){
1641
					*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)(ptr->recnumber);
1642
				}
1643
				else{
1644
//					printf("loc=%08X num=%08X\n",*(unsigned long *)&output[(postbuf+i)->loc],ptr->recnumber);
1645
					*(unsigned long *)&output[(postbuf+i)->loc]+=ptr->recnumber;
1646
				}
1647
			}
1648
			if(FixUp)(postbuf+i)->type=(unsigned short)((postbuf+i)->type==DIN_VAR?FIX_VAR:FIX_VAR32);
1649
			else killpost(i--);
1650
		}
1651
	}
1652
	dopoststrings();
1653
}
1654
 
1655
void setdindata(idrec *ptr,int i)
1656
{
1657
unsigned char *oldinput;
1658
unsigned int oldinptr,oldendinptr;
1659
unsigned char bcha;
1660
unsigned int oline,ofile;
1661
char *ostartline;
1662
	if(alignword){
1663
		if(ptr->rectok==tk_structvar)alignersize+=AlignCD(DS,2);	//выровнять
1664
		else alignersize+=AlignCD(DS,GetVarSize(ptr->rectok));
1665
	}
1666
//	printf("loc=%08X out=%08X num=%08X\n",*(unsigned long *)&output[(postbuf+i)->loc],outptrdata,ptr->recnumber);
1667
	if((postbuf+i)->type==DIN_VAR)*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)(outptrdata);
1668
	else *(unsigned long *)&output[(postbuf+i)->loc]+=outptrdata;
1669
	ptr->recpost=0;
1670
	ptr->recnumber+=outptrdata;
1671
	oline=linenum2;
1672
	ofile=currentfileinfo;
1673
	oldinput=input;
1674
	oldinptr=inptr2;
1675
	bcha=cha2;
1676
	oldendinptr=endinptr;
1677
	input=(unsigned char *)ptr->sbuf;
1678
	inptr2=1;
1679
	ostartline=startline;
1680
	startline=(char*)input;
1681
	cha2=input[0];
1682
	linenum2=ptr->line;
1683
	currentfileinfo=ptr->file;
1684
	endinptr=strlen((char *)input);
1685
	endinput=startline+endinptr;
1686
	endoffile=0;
1687
	tok=ptr->rectok;
1688
	if(tok==tk_structvar)datasize+=initstructvar((structteg *)ptr->newid,ptr->recrm);
1689
	else{
1690
long type,ssize;
1691
unsigned char typev;
1692
		if(tok>=tk_charvar&&tok<=tk_doublevar){
1693
			type=tok-(tk_charvar-tk_char);
1694
			typev=variable;
1695
			ssize=typesize(type);
1696
		}
1697
		else if(tok==tk_pointer){
1698
			typev=pointer;
1699
			type=itok.type;
1700
			if(am32==FALSE&&((itok.flag&f_far)==0))ssize=2;
1701
			else ssize=4;
1702
		}
1703
		datasize+=initglobalvar(type,ptr->recsize/ssize,ssize,typev);
1704
	}
1705
	free(input);
1706
	linenum2=oline;
1707
	currentfileinfo=ofile;
1708
	input=oldinput;
1709
	inptr2=oldinptr;
1710
	cha2=bcha;
1711
	endinptr=oldendinptr;
1712
	endoffile=0;
1713
	startline=ostartline;
1714
}
1715
 
1716
FILE *CreateOutPut(char *ext,char *mode)
1717
{
1718
char buf[256];
1719
FILE *diskout;
1720
	sprintf(buf,"%s.%s",rawfilename,ext);
1721
	if((diskout=fopen(buf,mode))==NULL){
1722
		ErrOpenFile(buf);
1723
		exit(e_notcreateoutput);
1724
	}
1725
	return diskout;
1726
}
1727
 
1728
int numundefclassproc=0;
1729
idrec **undefclassproc;
1730
 
1731
void AddUndefClassProc()
1732
{
1733
	if(numundefclassproc==0)undefclassproc=(idrec **)MALLOC(sizeof(idrec **));
1734
	else undefclassproc=(idrec **)REALLOC(undefclassproc,sizeof(idrec **)*(numundefclassproc+1));
1735
	undefclassproc[numundefclassproc]=itok.rec;
1736
	numundefclassproc++;
1737
}
1738
 
1739
void CheckUndefClassProc()
1740
{
1741
	for(int i=0;i
1742
		idrec *ptr=undefclassproc[i];
1743
		if(ptr->rectok==tk_undefproc){
1744
			currentfileinfo=ptr->file;
1745
			linenumber=ptr->line;
1746
			thisundefined(ptr->recid);
1747
		}
1748
	}
1749
}