forked from KolibriOS/kolibrios
9067bf0a18
git-svn-id: svn://kolibrios.org@9355 a494cfbc-eb01-0410-851d-a64ba20cac60
1724 lines
47 KiB
C++
1724 lines
47 KiB
C++
#define _MAIN_
|
|
|
|
#ifdef _UNIX_
|
|
#define DIV_PATH ':' //äåëèòåëü ïóòåé â ïåðåìåííîé îêðóæåíèÿ PATH
|
|
#define DIV_FOLD '/' //ýòèì ñèìâîëîì ðàçäåëÿþòñÿ ïàïêè â ïóòè ê ôàéëó
|
|
#endif
|
|
|
|
#ifdef _WIN32_
|
|
#define DIV_PATH ';'
|
|
#define DIV_FOLD '\\'
|
|
#endif
|
|
|
|
#ifdef _KOS_
|
|
#define DIV_PATH ';'
|
|
#define DIV_FOLD '/'
|
|
#endif
|
|
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include "tok.h"
|
|
|
|
static char **_Argv; //!!! simplest way to make your own variable
|
|
|
|
unsigned char compilerstr[]="SPHINX C-- 0.239";
|
|
char *rawfilename; /* file name */
|
|
char *rawext;
|
|
LISTCOM *listcom;
|
|
EWAR wartype={NULL,NULL},errfile={NULL,NULL};
|
|
int numfindpath=0;
|
|
char *findpath[16];
|
|
char modelmem=TINY;
|
|
char *stubfile=NULL;
|
|
char *winstub=NULL;
|
|
FILE *hout=NULL;
|
|
const char *namestartupfile="startup.h--";
|
|
|
|
char outext[4]="kex";
|
|
short extflag=TRUE;//ðàñøèðåíèå ìîæíî ïðèñâîèòü
|
|
//int scrsize;
|
|
unsigned char gwarning=FALSE;
|
|
unsigned char sobj=FALSE;
|
|
unsigned char usestub=TRUE;
|
|
unsigned char dpmistub=FALSE;
|
|
short dllflag=FALSE;
|
|
static int numstr;
|
|
|
|
char meinfo[]=
|
|
"\nEdition of this version by\n"
|
|
" Mishel Sheker\n"
|
|
" Fido 2:5021/3.40\n"
|
|
" E-Mail sheker@mail.ru\n"
|
|
" Russia";
|
|
|
|
time_t systime;
|
|
struct tm timeptr;
|
|
char comsymbios=FALSE;
|
|
char fobj=FALSE; //ïðèçíàê ãåíåðàöèè obj
|
|
unsigned int startptr = 0x100; // start address
|
|
unsigned char wconsole=FALSE; //ïðèçíàê ãåíåðàöèè êîíñîëüíîãî ïðèëîæåíèÿ windows
|
|
unsigned char optstr=FALSE; //îïòèìèçàöèÿ ñòðîêîâûõ êîíñòàíò
|
|
unsigned char crif=TRUE; //check reply include file
|
|
unsigned char idasm=FALSE; //àññåìáëåðíûå èíñòðóêöèè ñ÷èòàòü èäåíòèôèêàòîðàìè
|
|
unsigned char wbss=2; //ïîñò ïåðåìåííûå â îòäåëüíóþ ñåêöèþ
|
|
unsigned char use_env=FALSE; //ïåðåìåííàÿ îêðóæåíèÿ
|
|
int numrel=0; //÷èñëî ýëåìåíòîâ â òàáëèöå ïåðåìåùåíèé
|
|
unsigned char useordinal=FALSE;
|
|
unsigned char useDOS4GW=FALSE;
|
|
unsigned char clearpost=FALSE;
|
|
unsigned char uselea=TRUE;
|
|
unsigned char regoverstack=TRUE;
|
|
unsigned char shortimport=FALSE;
|
|
unsigned char useinline=2;
|
|
unsigned char ocoff=FALSE;
|
|
unsigned char ESPloc=FALSE;
|
|
|
|
int startupfile=-1;
|
|
int alignproc=8,aligncycle=8;
|
|
|
|
const char *usage[]={
|
|
"USAGE: C-- [options] [FILE_NAME.INI] [SOURCE_FILE_NAME]",
|
|
"",
|
|
" C-- COMPILER OPTIONS",
|
|
"",
|
|
" OPTIMIZATION",
|
|
"-OC optimize for code size -DE enable temporary expansion variable",
|
|
"-OS optimize for speed -OST enable optimization string",
|
|
"-ON enable optimization number -AP[=n] align start function",
|
|
"-UST use startup code for variables -AC[=n] align start cycles",
|
|
#ifdef OPTVARCONST
|
|
"-ORV replace variable on constant -OIR skip repeated initializing register",
|
|
#else
|
|
" -OIR skip repeated initializing register",
|
|
#endif
|
|
"",
|
|
" CODE GENERATION",
|
|
"-2 80286 code optimizations -SA=#### start code address",
|
|
"-3 80386 code optimizations -AL=## set value insert byte",
|
|
"-4 80486 code optimizations -WFA fast call API functions",
|
|
"-5 pentium code optimizations -IV initial all variables",
|
|
"-A enable address alignment -SUV=#### start address variables",
|
|
"-AS[=n] def. alignment in structures -LRS load in registers over stack",
|
|
"-UL use 'lea' for adding registers -JS join stack calling functions",
|
|
"-BA byte access to array",// -ASP addressing local variable via ESP",
|
|
"",
|
|
" PREPROCESSOR",
|
|
"-IP=<path> include file path -IA assembly instructions as identifier",
|
|
"-D=<idname> defined identifier -CRI- not check include file on repeated",
|
|
"-MIF=<file> main input file -IND=<name> import name from dll",
|
|
"-SF=<file> other startup file",
|
|
"",
|
|
" LINKING",
|
|
"-AT insert ATEXIT support block -NS disable stub",
|
|
"-ARGC insert parse command line -S=##### set stack size",
|
|
"-P insert parse command line -WIB=##### set image base address",
|
|
"-C insert CTRL<C> ignoring code -WFU add Fix Up table, for Windows",
|
|
"-R insert resize memory block -WMB create Windows mono block",
|
|
"-ENV insert variable with environ -WS=<name> set name stub file for win32",
|
|
"-J0 disable initial jump to main() -WBSS set post data in bss section",
|
|
"-J1 initial jump to main() short -WO call API functions on ordinals",
|
|
"-J2 initial jump to main() near -CPA clear post area",
|
|
"-STUB= <name> set name stub file -WSI short import table, for Windows",
|
|
"-DOS4GW file running with DOS4GW -WAF=#### align Windows file (def 512)",
|
|
"-STM startup code in main function",
|
|
"",
|
|
" OUTPUT FILES",
|
|
"-TEXE DOS EXE file (model TINY) -D32 EXE file (32bit code for DOS)",
|
|
"-EXE DOS EXE file (model SMALL) -W32 EXE for Windows32 GUI",
|
|
"-OBJ OBJ output file -W32C EXE for Windows32 console",
|
|
"-SOBJ slave OBJ output file -DLL DLL for Windows32",
|
|
"-COFF OBJ COFF output file -DBG create debug information",
|
|
"-SYM COM file symbiosis -LST create assembly listing",
|
|
"-SYS device (SYS) file -B32 32bit binary files",
|
|
"-MEOS executable file for MeOS -MAP create function map file",
|
|
"-EXT= <ext> set file extension",
|
|
"",
|
|
" MISCELLANEOUS",
|
|
"-HELP -H -? help, this info -WORDS list of C-- reserved words",
|
|
"-W enable warning -LAI list of assembler instructions",
|
|
"-WF=<file> direct warnings to a file -ME display my name and my address",
|
|
"-MER=## set maximum number errors -X disable SPHINX C-- header in output",
|
|
"-NW=## disable selected warnings -WE=## selected warning will be error",
|
|
//" -SCD split code and date",
|
|
NULL};
|
|
|
|
const char *dir[]={
|
|
"ME", "WORDS", "SYM", "LAI",
|
|
|
|
"OBJ", "SOBJ", "J0", "J1", "J2", "C", "R",
|
|
"P", "X", "EXE", "S", "SYS", "ARGC", "TEXE",
|
|
"ROM", "W32", "D32", "W32C", "AT", "WFA", "SA",
|
|
"STM", "SUV", "UST", "MIF", "DLL", "DOS4GW","ENV",
|
|
"CPA", "WBSS", "MEOS", "SF", "B32", "WIB", "DBG",
|
|
|
|
"OS", "OC", "A", "0", "1", "2", "3",
|
|
"4", "5", "6", "7", "8", "9", "W",
|
|
"WF", "DE",
|
|
"ON", "IP", "STUB", "NS", "AP", "D", "OST",
|
|
"CRI", "IA", "SCD", "AL", "WFU", "IV",
|
|
"MER", "WMB", "HELP", "H", "?", "AC", "WS",
|
|
"IND", "WO", "NW", "LST", "AS", "UL", "LRS",
|
|
"WSI", "WAF", "OIR", "COFF", "JS", "BA", "ASP",
|
|
#ifdef OPTVARCONST
|
|
"ORV",
|
|
#endif
|
|
"MAP", "WE", "EXT", NULL};
|
|
|
|
enum {
|
|
c_me, c_key, c_sym, c_lasm, c_endinfo=c_lasm,
|
|
|
|
c_obj, c_sobj, c_j0, c_j1, c_j2, c_ctrlc, c_r,
|
|
c_p, c_x, c_exe, c_s, c_sys, c_arg, c_texe,
|
|
c_rom, c_w32, c_d32, c_w32c, c_at, c_wfa, c_sa,
|
|
c_stm, c_suv, c_ust, c_mif, c_dll, c_d4g, c_env,
|
|
c_cpa, c_wbss, c_meos, c_sf, c_b32, c_wib, c_dbg,
|
|
c_endstart=c_dbg,
|
|
|
|
c_os, c_oc, c_a, c_0, c_1, c_2, c_3,
|
|
c_4, c_5, c_6, c_7, c_8, c_9, c_w,
|
|
c_wf, c_de,
|
|
c_opnum, c_ip, c_stub, c_ns, c_ap, c_define,c_ost,
|
|
c_cri, c_ia, c_scd, c_al, c_wfu, c_iv,
|
|
c_mer, c_wmb, c_help, c_h, c_hh, c_ac, c_ws,
|
|
c_ind, c_wo, c_nw, c_lst, c_as, c_ul, c_lrs,
|
|
c_wsi, c_waf, c_oir, c_coff, c_js, c_ba, c_asp,
|
|
#ifdef OPTVARCONST
|
|
c_orv,
|
|
#endif
|
|
c_map, c_we, c_ext, c_end};
|
|
|
|
#define NUMEXT 6 //÷èñëî ðàçðåøåííûõ ðàñøèðåíèé êîìïèëèðóåìîãî ôàéëà
|
|
char extcompile[NUMEXT][4]={"c--","cmm","c","h--","hmm","h"};
|
|
|
|
#ifdef _KOS_
|
|
char __pgmname[256];
|
|
char __cmdline[256];
|
|
#endif
|
|
|
|
char *bufstr=NULL; //áóôåð äëÿ ñòðîê èç ïðîöåäóð
|
|
int sbufstr=SIZEBUF; //íà÷àëüíûé ðàçìåð ýòîãî áóôåðà
|
|
|
|
void compile();
|
|
void PrintInfo(char **str);
|
|
void LoadIni(char *name);
|
|
//void CheckNumStr();
|
|
void ListId(int num,unsigned char *list,unsigned short *ofs);
|
|
void printmemsizes();
|
|
void print8item(char *str);
|
|
void doposts(void);
|
|
void GetMemExeDat();
|
|
void AddJmpApi();
|
|
void startsymbiosys(char *symfile);
|
|
int writeoutput();
|
|
void BadCommandLine(char *str);
|
|
void CheckExtenshions();
|
|
void ImportName(char *name);
|
|
void WarnUnusedVar();//ïðåäóïðåæäåíèÿ î íåèñïîëüçîâàííûõ ïðîöåäóðàõ è ïåðåìåííûõ
|
|
void MakeExeHeader(EXE_DOS_HEADER *exeheader);
|
|
void CheckPageCode(unsigned int ofs);
|
|
int MakePE();
|
|
int MakeObj();
|
|
void CheckUndefClassProc();
|
|
|
|
#ifdef _KOS_
|
|
extern "C"{
|
|
void con_set_title(char* title);
|
|
}
|
|
#endif
|
|
|
|
void ListId(int numfirstchar,unsigned char *list,unsigned short *ofs)
|
|
{
|
|
char buf[40];
|
|
for(int i=0;i<numfirstchar;i++){
|
|
if((short)ofs[i]!=-1){
|
|
if(i<26)buf[0]=(char)('A'+i);
|
|
else if(i==26)buf[0]='_';
|
|
else buf[0]=(char)(i-27+'a');
|
|
unsigned char *ii=(unsigned char *)(list+ofs[i]);
|
|
while(*(short *)&*ii!=-1){
|
|
ii+=2;
|
|
strcpy(buf+1,(char *)ii);
|
|
ii+=strlen((char *)ii)+1;
|
|
puts(buf);
|
|
// CheckNumStr();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
void PrintTegList(structteg *tteg)
|
|
{
|
|
if(tteg){
|
|
PrintTegList(tteg->left);
|
|
PrintTegList(tteg->right);
|
|
puts(tteg->name);
|
|
}
|
|
} */
|
|
|
|
//unsigned long maxusedmem=0;
|
|
|
|
void ErrOpenFile(char *str)
|
|
{
|
|
printf("Unable to open file %s.\n",str);
|
|
}
|
|
|
|
int main(int argc,char *argv[])
|
|
{
|
|
int count;
|
|
unsigned char pari=FALSE;
|
|
char *buffer;
|
|
|
|
printf("\nSPHINX C-- Compiler Version %d.%d%s %s\r\n",ver1,ver2,betta,__DATE__);
|
|
#ifdef _KOS_
|
|
con_set_title((char*)compilerstr);
|
|
#endif
|
|
// scrsize=24;
|
|
if(argc>1){
|
|
_Argv=argv;// This make portable code
|
|
bufstr=(char *)MALLOC(SIZEBUF);
|
|
output=(unsigned char *)MALLOC((size_t)MAXDATA);
|
|
outputdata=output;
|
|
postbuf=(postinfo *)MALLOC(MAXPOSTS*sizeof(postinfo));
|
|
strcpy((char *)string,argv[0]);
|
|
rawext=strrchr((char *)string,DIV_FOLD);
|
|
|
|
if(rawext!=NULL){
|
|
rawext[0]=0;
|
|
IncludePath((char *)string);
|
|
}
|
|
rawfilename=getenv("C--");
|
|
if(rawfilename!=NULL)IncludePath(rawfilename);
|
|
|
|
rawfilename=rawext=NULL;
|
|
LoadIni((char *)"c--.ini");
|
|
|
|
for(count=1;count<argc;count++){ //îáðàáîòêà êîìàíäíîé ñòðîêè
|
|
//if(argv[count][0]=='/'||argv[count][0]=='-'){
|
|
if(argv[count][0]=='-'){
|
|
if(SelectComand(argv[count]+1,&count)==c_end) BadCommandLine(argv[count]);
|
|
}
|
|
else{
|
|
if(pari==FALSE){
|
|
rawfilename=argv[count];
|
|
pari=TRUE;
|
|
if((rawext=strrchr(rawfilename,'.'))!=NULL){
|
|
if(stricmp(rawext,".ini")==0){ //óêàçàí ini ôàéë
|
|
rawfilename=NULL;
|
|
rawext=NULL;
|
|
LoadIni(argv[count]);
|
|
if(rawfilename==NULL)pari=FALSE;
|
|
}
|
|
else{
|
|
*rawext++=0;
|
|
CheckExtenshions();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(rawfilename==NULL){
|
|
PrintInfo((char **)usage);
|
|
exit( e_noinputspecified );
|
|
}
|
|
time(&systime); //òåêóùåå âðåìÿ
|
|
memcpy(&timeptr,localtime(&systime),sizeof(tm));
|
|
InitDefineConst();
|
|
compile();
|
|
if(error==0)exit(e_ok);
|
|
exit(e_someerrors);
|
|
return 0;
|
|
}
|
|
|
|
void CheckExtenshions()
|
|
{
|
|
int i;
|
|
for(i=0;i<NUMEXT;i++){
|
|
if(stricmp(rawext,extcompile[i])==0)break;
|
|
}
|
|
if(i==NUMEXT){
|
|
printf("Bad input file extension '%s'.",rawext);
|
|
exit(e_badinputfilename);
|
|
}
|
|
}
|
|
|
|
void compile()
|
|
{
|
|
long segments_required;
|
|
union{
|
|
long longhold;
|
|
void *nextstr;
|
|
};
|
|
//ñîçäàòü èìÿ ôàéëà ñ ïðåäóïðåæäåíèÿìè è åñëè îí åñòü óäàëèòü
|
|
errfile.name=(char *)MALLOC(strlen(rawfilename)+5);
|
|
sprintf(errfile.name,"%s.err",rawfilename);
|
|
if(stat(errfile.name,(struct stat *)string2)==0)remove(errfile.name);
|
|
//åñëè åñòü èìÿ ôàéëà äëÿ ïðåäóïðåæäåíèé ïðîâåðèòü åãî ñóùåñòâîâàíèå è óäàëèòü.
|
|
if(wartype.name!=NULL){
|
|
if(stat(wartype.name,(struct stat *)string2)==0)remove(wartype.name);
|
|
}
|
|
puts("Compiling Commenced . . .");
|
|
if(rawext!=NULL)sprintf((char *)string,"%s.%s",rawfilename,rawext);
|
|
else{
|
|
for(unsigned int i=0;i<NUMEXT;i++){
|
|
sprintf((char *)string,"%s.%s",rawfilename,extcompile[i]);
|
|
if(stat((char *)string,(struct stat *)string2)==0)break;
|
|
}
|
|
}
|
|
linenumber=0;
|
|
initregstat();
|
|
#ifdef OPTVARCONST
|
|
CreateMainLVIC();
|
|
#endif
|
|
#ifdef __NEWLEX__
|
|
inittokn();
|
|
#endif
|
|
compilefile((char *)string,2); //ñîáñòâåííî ðàçáîðêà è êîìïèëÿöèÿ
|
|
puts("Link . . .");
|
|
if(comfile==file_w32&&wbss==2){
|
|
wbss=FALSE;
|
|
if(wconsole==FALSE)wbss=TRUE;
|
|
}
|
|
if(notdoneprestuff==TRUE)doprestuff(); //startup code
|
|
if(endifcount>=0)preerror("?endif expected before end of file");
|
|
AddObj();
|
|
docalls(); //äîáàâèòü âíåøíèå ïðîöåäóðû
|
|
addinitvar();
|
|
CheckUndefClassProc();
|
|
if(undefoffstart!=NULL){ //âûäàòü ñïèñîê íåèçâåñòíûõ ññûëîê
|
|
UNDEFOFF *curptr=undefoffstart;
|
|
for(;;){
|
|
char holdstr[80];
|
|
UNDEFOFF *ocurptr;
|
|
linenumber=curptr->pos->line;
|
|
sprintf(holdstr,"\'%s\' offset undefined",curptr->name);
|
|
currentfileinfo=curptr->pos->file;
|
|
preerror(holdstr);
|
|
free(curptr->pos);
|
|
if(curptr->next==NULL)break;
|
|
ocurptr=curptr->next;
|
|
free(curptr);
|
|
curptr=ocurptr;
|
|
}
|
|
free(curptr);
|
|
}
|
|
while(liststring!=NULL){
|
|
STRING_LIST *ins;
|
|
ins=(STRING_LIST *)liststring;
|
|
nextstr=ins->next;
|
|
free(liststring);
|
|
liststring=nextstr;
|
|
}
|
|
free(bufstr);
|
|
if(warning==TRUE&&wact[7].usewarn)WarnUnusedVar();//ïðåäóïðåæäåíèÿ î íåèñïîëüçîâàííûõ ïðîöåäóðàõ è ïåðåìåííûõ
|
|
if(numstrtbl)CreatStrTabRes(); //çàâåðøèòü ñîçäàíèå ðåñóðñîâ
|
|
if(fobj==FALSE){
|
|
if(comfile==file_w32&&error==0){
|
|
AddJmpApi(); //êîñâåííûå âûçîâû API
|
|
CreatWinStub();
|
|
}
|
|
longhold=outptr;
|
|
if(comfile==file_rom){
|
|
ooutptr=outptr;
|
|
if(modelmem==SMALL){
|
|
*(short *)&output[stackstartaddress]=(short)(((outptrdata+postsize+stacksize)/4+1)*4);
|
|
*(short *)&output[dataromstart]=(short)(outptr+4);
|
|
*(short *)&output[dataromsize]=(short)(outptrdata/2);
|
|
// printf("outptr=%d outptrdate=%d outptrsize=%d\n",outptr,outptrdata,outptrsize);
|
|
for(unsigned int i=0;i<outptrdata;i++)op(outputdata[i]);
|
|
}
|
|
if(romsize==0){
|
|
unsigned int i=outptr/1024;
|
|
if((outptr%1024)!=0)i++;
|
|
if(i>32)i=64;
|
|
else if(i>16)i=32;
|
|
else if(i>8)i=16;
|
|
else if(i>4)i=8;
|
|
else if(i>2)i=4;
|
|
romsize=i*1024;
|
|
output[2]=(unsigned char)(romsize/512);
|
|
}
|
|
if(outptr>=romsize)preerror("The size of a code is more than the size of the ROM");
|
|
for(;outptr<romsize;)op(aligner);
|
|
unsigned char summa=0;
|
|
for(unsigned int i=0;i<romsize;i++)summa+=output[i];
|
|
output[romsize-1]-=summa;
|
|
outptr=ooutptr;
|
|
}
|
|
else if(modelmem==SMALL&&comfile==file_exe){ // if an EXE file
|
|
longhold+=AlignCD(CS,16);
|
|
// if((outptr%16)!=0)outptr+=16-outptr%16;// paragraph align the end of the code seg
|
|
if(((long)outptrdata+(long)postsize+(long)stacksize)>65535L)
|
|
preerror("Data and stack total exceeds 64k");
|
|
}
|
|
else if(comfile==file_sys){
|
|
for(int i=0;i<sysnumcom;i++){
|
|
searchvar((listcom+i)->name);
|
|
*(short *)&output[syscom+i*2]=(unsigned short)itok.number;
|
|
}
|
|
free(listcom);
|
|
}
|
|
else longhold+=(long)postsize+(long)(stacksize);
|
|
if(am32==0&&longhold>65535L&&!(modelmem==TINY&&(!resizemem)))preerror("Code, data and stack total exceeds 64k");
|
|
if(posts>0)doposts(); //Óñòàíîâèòü àäðåñà âûçîâîâ ïðîöåäóð è ïåðåõîäîâ
|
|
if(resizemem&&comfile==file_com){
|
|
segments_required=(outptr+postsize+stacksize+15)/16;
|
|
*(short *)&output[resizesizeaddress]=(short)segments_required;
|
|
*(short *)&output[stackstartaddress]=(short)(segments_required*16);
|
|
}
|
|
}
|
|
deinitregstat();
|
|
#ifdef OPTVARCONST
|
|
KillMainLVIC();
|
|
#endif
|
|
// puts("List Teg name:");
|
|
// PrintTegList(tegtree);
|
|
printf("COMPILING FINISHED. Errors: %d\n",error);
|
|
if(error==0){
|
|
if(cpu>=1){
|
|
char m1[12];
|
|
switch(cpu){
|
|
case 5:
|
|
strcpy(m1,"Pentium");
|
|
break;
|
|
case 6:
|
|
strcpy(m1,"MMX");
|
|
break;
|
|
case 7:
|
|
strcpy(m1,"Pentium II");
|
|
break;
|
|
case 8:
|
|
strcpy(m1,"Pentium III");
|
|
break;
|
|
case 9:
|
|
strcpy(m1,"Pentium IV");
|
|
break;
|
|
default: sprintf(m1,"80%d86",cpu);
|
|
}
|
|
printf("CPU required: %s or greater.\n",m1);
|
|
}
|
|
runfilesize=outptr-startptr;
|
|
if(comfile==file_rom)runfilesize=romsize;
|
|
else if(modelmem==SMALL&&comfile==file_exe){
|
|
runfilesize+=outptrdata-startptrdata+0x20;
|
|
postsize+=postsize%2;
|
|
stacksize=(stacksize+15)/16*16;
|
|
}
|
|
else if((comfile==file_exe||comfile==file_d32)&&modelmem==TINY)
|
|
runfilesize+=0x20;
|
|
printmemsizes();
|
|
endinptr=outptr;
|
|
if(writeoutput()==0)printf("Run File Saved (%ld bytes).\n",runfilesize);
|
|
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);
|
|
// else if(FILEALIGN&&fobj==FALSE)printf("For alignment file, added %u zero bytes.\n",filingzerope);
|
|
}
|
|
if(pdbg)DoTDS();
|
|
}
|
|
|
|
void printmemsizes()
|
|
{
|
|
long stacklong;
|
|
unsigned int stackword;
|
|
unsigned int postword,codeword;
|
|
postword=postsize;
|
|
codeword=outptr-startptr;
|
|
stackword=stacksize;
|
|
if(comfile==file_com||(comfile==file_exe&&modelmem==TINY)){
|
|
if(resizemem==0){
|
|
stacklong=0xFFFE - outptr - postsize;
|
|
stackword=stacklong;
|
|
}
|
|
codeword=codeword-datasize-alignersize;
|
|
}
|
|
else if(comfile==file_sys)stackword=sysstack;
|
|
else if(comfile==file_exe||comfile==file_rom)datasize=outptrdata;
|
|
else if(comfile==file_d32)codeword-=datasize;
|
|
printf("Code: %u bytes, Data: %u bytes, Post: %u bytes, Stack: %u bytes\n"
|
|
,codeword,datasize,postword,stackword);
|
|
for(int i=0;i<posts;i++){
|
|
switch((postbuf+i)->type){
|
|
case CODE_SIZE:
|
|
*(short *)&output[(postbuf+i)->loc]+=codeword;
|
|
break;
|
|
case CODE_SIZE32:
|
|
*(long *)&output[(postbuf+i)->loc]+=codeword;
|
|
break;
|
|
case DATA_SIZE:
|
|
*(short *)&output[(postbuf+i)->loc]+=datasize;
|
|
break;
|
|
case DATA_SIZE32:
|
|
*(long *)&output[(postbuf+i)->loc]+=datasize;
|
|
break;
|
|
case POST_SIZE:
|
|
*(short *)&output[(postbuf+i)->loc]+=postword;
|
|
break;
|
|
case POST_SIZE32:
|
|
*(long *)&output[(postbuf+i)->loc]+=postword;
|
|
break;
|
|
case STACK_SIZE:
|
|
*(short *)&output[(postbuf+i)->loc]+=stackword;
|
|
break;
|
|
case STACK_SIZE32:
|
|
*(long *)&output[(postbuf+i)->loc]+=stackword;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintInfo(char **str)
|
|
{
|
|
numstr=1;
|
|
for(int i=0;str[i]!=NULL;i++){
|
|
puts(str[i]);
|
|
// CheckNumStr();
|
|
}
|
|
}
|
|
|
|
/*void CheckNumStr()
|
|
{
|
|
#ifndef _UNIX_
|
|
if(((numstr+1)%(scrsize-1))==0&&outfile!=0){
|
|
puts("Press any key...");
|
|
getch();
|
|
}
|
|
numstr++;
|
|
#endif
|
|
} */
|
|
|
|
void strbtrim(char *st)
|
|
{
|
|
int i;
|
|
char *p,*q;
|
|
p=q=st;
|
|
while(isspace(*p))p++; //ïîêà íåçíà÷àùèå ñèìâîëû
|
|
while(*p)*q++=*p++; //ïåðåìåñòèòü ñòðîêó
|
|
*q='\0';
|
|
for(i=strlen(st)-1;isspace(st[i])&&i>=0;i--);
|
|
st[i+1]='\0';
|
|
}
|
|
|
|
unsigned long getnumber(unsigned char *buf)
|
|
{
|
|
int temp2;
|
|
unsigned long retnum;
|
|
unsigned char *oinput;
|
|
unsigned int oinptr,oendinptr;
|
|
if(!isdigit(buf[0]))return 0;
|
|
oinptr=inptr;
|
|
oinput=input;
|
|
oendinptr=endinptr;
|
|
input=buf;
|
|
inptr=0;
|
|
endinptr=256;
|
|
retnum=scannumber(&temp2);
|
|
inptr=oinptr;
|
|
input=oinput;
|
|
endinptr=oendinptr;
|
|
return retnum;
|
|
}
|
|
|
|
int SelectComand(char *pptr,int *count)
|
|
{
|
|
int i;
|
|
unsigned char neg=FALSE;
|
|
char *ptr;
|
|
int len;
|
|
if((ptr=strchr(pptr,';'))!=NULL)*ptr=0;// èùåì êîììåíòàðèé îòñåêàåì âñå ïîñëå íåãî
|
|
if((ptr=strchr(pptr,'='))!=NULL){ // èùåì çíàê ðàâåíñòâà
|
|
*ptr=0; // äåëèì
|
|
ptr++;
|
|
strbtrim(ptr); //óáðàòü ëèøíèå ïðîáåëû
|
|
}
|
|
strbtrim(pptr); //óáðàòü ëèøíèå ïðîáåëû
|
|
if(*pptr==0)return c_end+1; //ïóñòàÿ ñòðîêà
|
|
if((i=strlen(pptr))>1&&pptr[i-1]=='-'){
|
|
neg=TRUE;
|
|
pptr[i-1]=0;
|
|
}
|
|
strupr(pptr);
|
|
for(i=0;dir[i]!=NULL;i++){
|
|
if(strcmp(dir[i],pptr)==0){
|
|
if((i<=c_endinfo)&&count==0){
|
|
char buf[80];
|
|
sprintf(buf,"Option '%s' is used only in command line",dir[i]);
|
|
preerror(buf);
|
|
return i;
|
|
}
|
|
if(i<=c_endstart&¬doneprestuff!=TRUE){
|
|
errlate:
|
|
char buf[80];
|
|
sprintf(buf,"Too late used '#pragma option %s'",dir[i]);
|
|
preerror(buf);
|
|
return i;
|
|
}
|
|
switch(i){
|
|
case c_j0: jumptomain=(unsigned char)(neg!=FALSE?CALL_NEAR:CALL_NONE); header=(unsigned char)0^neg; break;
|
|
case c_j1: jumptomain=(unsigned char)CALL_SHORT; header=(unsigned char)1; break;
|
|
case c_j2: jumptomain=(unsigned char)(neg==FALSE?CALL_NEAR:CALL_NONE); header=(unsigned char)1^neg; break;
|
|
case c_ctrlc: killctrlc=(unsigned char)1^neg; break;
|
|
case c_os: optimizespeed=(unsigned char)1^neg; break;
|
|
case c_oc: optimizespeed=(unsigned char)0^neg; break;
|
|
case c_r: resizemem=(unsigned char)1^neg; break;
|
|
case c_p: parsecommandline=(unsigned char)1^neg; break;
|
|
case c_a: alignword=(unsigned char)1^neg; break;
|
|
case c_sym:
|
|
startptr=0x100;
|
|
comsymbios=TRUE;
|
|
*count=*count+1;
|
|
startsymbiosys(_Argv[*count]);
|
|
break;
|
|
case c_0: chip=0; break;
|
|
case c_1: chip=1; break;
|
|
case c_2: chip=2; break;
|
|
case c_3: chip=3; break;
|
|
case c_4: chip=4; break;
|
|
case c_5: chip=5; break;
|
|
case c_6: chip=6; break; //MMX
|
|
case c_7: chip=7; break; //Pro
|
|
case c_8: chip=8; break; //PII
|
|
case c_9: chip=9; break; //PIII
|
|
case c_x: header=(unsigned char)0^neg; break;
|
|
case c_exe:
|
|
comfile=file_exe;
|
|
modelmem=SMALL;
|
|
splitdata=TRUE;
|
|
GetMemExeDat();
|
|
if(extflag) strcpy(outext,"exe");
|
|
startptr=0; // start address
|
|
startptrdata=0; // data start address
|
|
dos1=2;
|
|
dos2=0;
|
|
break;
|
|
case c_sys:
|
|
comfile=file_sys;
|
|
if(extflag) strcpy(outext,"sys");
|
|
startptr=0; // start address
|
|
startptrdata=0; // data start address
|
|
jumptomain=CALL_NONE;
|
|
header=0;
|
|
break;
|
|
case c_sobj:
|
|
sobj=TRUE;
|
|
FixUp=TRUE;
|
|
jumptomain=CALL_NONE;
|
|
case c_obj:
|
|
fobj=TRUE;
|
|
// if(comfile==file_d32)FixUp=TRUE;
|
|
FastCallApi=FALSE;
|
|
break;
|
|
case c_me:
|
|
puts(meinfo);
|
|
exit( e_ok );
|
|
case c_key:
|
|
int j,jj;
|
|
puts("LIST OF RESERVED IDENTIFIERS:");
|
|
numstr=1;
|
|
ListId(53,(unsigned char *)id,idofs);
|
|
for(j=0;j<ID2S;j++){
|
|
puts(id2[j]);
|
|
// CheckNumStr();
|
|
}
|
|
for(jj=0;jj<2;jj++){
|
|
for(j=0;j<8;j++)printf("%s ",regs[jj][j]);
|
|
puts("");
|
|
// CheckNumStr();
|
|
}
|
|
for(j=0;j<8;j++)printf("%s ",begs[j]);
|
|
puts("");
|
|
// CheckNumStr();
|
|
for(j=0;j<6;j++)printf("%s ",segs[j]);
|
|
print8item("ST(%d) ");
|
|
puts("ST");
|
|
print8item("st(%d) ");
|
|
puts("st");
|
|
exit(e_ok);
|
|
case c_lasm:
|
|
puts("LIST OF SUPPORTED ASSEMBLER INSTRUCTIONS:");
|
|
numstr=1;
|
|
ListId(26,asmMnem,ofsmnem);
|
|
exit(e_ok);
|
|
case c_s:
|
|
if(ptr==NULL)return c_end;
|
|
if((stacksize=getnumber((unsigned char *)ptr))==0){
|
|
puts("Bad stack size.");
|
|
exit(e_unknowncommandline);
|
|
}
|
|
stacksize=Align(stacksize,4);
|
|
break;
|
|
case c_w:
|
|
gwarning=(unsigned char)TRUE^neg;
|
|
break;
|
|
case c_wf:
|
|
if(wartype.name)free(wartype.name);
|
|
wartype.name=BackString(ptr);
|
|
break;
|
|
case c_de:
|
|
divexpand=(unsigned char)TRUE^neg;
|
|
break;
|
|
case c_opnum:
|
|
optnumber=(unsigned char)TRUE^neg;
|
|
break;
|
|
case c_ip:
|
|
IncludePath(ptr);
|
|
break;
|
|
case c_arg:
|
|
parsecommandline=(unsigned char)TRUE^neg;
|
|
fargc=(unsigned char)TRUE^neg;
|
|
break;
|
|
case c_texe:
|
|
if(extflag) strcpy(outext,"exe");
|
|
comfile=file_exe;
|
|
break;
|
|
case c_rom:
|
|
if(extflag) strcpy(outext,"rom");
|
|
comfile=file_rom;
|
|
startptr=0;
|
|
startptrdata=0; // data start address
|
|
GetMemExeDat();
|
|
break;
|
|
case c_dll:
|
|
wconsole=TRUE;
|
|
dllflag=TRUE;
|
|
if(extflag) strcpy(outext,"dll");
|
|
comfile=file_w32;
|
|
FixUpTable=TRUE;
|
|
goto nexpardll;
|
|
|
|
/* FixUp=TRUE;
|
|
startptrdata=startptr=0;
|
|
am32=TRUE;
|
|
if(chip<3)chip=3;
|
|
if(FILEALIGN==0)FILEALIGN=512;
|
|
break;*/
|
|
case c_w32c:
|
|
wconsole=TRUE;
|
|
goto init_w32;
|
|
case c_w32:
|
|
wconsole=FALSE;
|
|
dllflag=FALSE;
|
|
init_w32:
|
|
comfile=file_w32;
|
|
goto nexpar;
|
|
case c_d32:
|
|
comfile=file_d32;
|
|
nexpar:
|
|
if(extflag) strcpy(outext,"exe");
|
|
nexpardll:
|
|
FixUp=TRUE;
|
|
startptrdata=startptr=0;
|
|
am32=TRUE;
|
|
if(chip<3)chip=3;
|
|
if(FILEALIGN==0)FILEALIGN=512;
|
|
break;
|
|
case c_meos:
|
|
comfile=file_meos;
|
|
am32=TRUE;
|
|
startptrdata=startptr=0;
|
|
if(extflag) strcpy(outext,"");
|
|
if(chip<3)chip=3;
|
|
break;
|
|
case c_b32:
|
|
comfile=file_bin;
|
|
am32=TRUE;
|
|
startptrdata=startptr=0;
|
|
if(extflag) strcpy(outext,"bin");
|
|
FixUp=TRUE;
|
|
ImageBase=0;
|
|
if(chip<3)chip=3;
|
|
break;
|
|
case c_stub:
|
|
if(stubfile)free(stubfile);
|
|
stubfile=BackString(ptr);
|
|
dpmistub=FALSE;
|
|
if(stricmp(stubfile,"dpmi")==0){
|
|
if(notdoneprestuff!=TRUE)goto errlate;
|
|
dpmistub=TRUE;
|
|
usestub=FALSE;
|
|
}
|
|
break;
|
|
case c_ns:
|
|
usestub=(unsigned char)0^neg;
|
|
break;
|
|
case c_ap:
|
|
AlignProc=(unsigned char)1^neg;
|
|
if(ptr!=NULL){
|
|
alignproc=getnumber((unsigned char *)ptr);
|
|
if(alignproc<1||alignproc>4096)alignproc=8;
|
|
}
|
|
break;
|
|
case c_define:
|
|
addconsttotree(ptr,TRUE);
|
|
break;
|
|
case c_ost:
|
|
optstr=(unsigned char)TRUE^neg;
|
|
break;
|
|
case c_cri:
|
|
crif=(unsigned char)1^neg;
|
|
break;
|
|
case c_ia:
|
|
idasm=(unsigned char)1^neg;
|
|
break;
|
|
case c_dbg:
|
|
dbg&=0xFE;
|
|
char c;
|
|
c=(unsigned char)1^neg;
|
|
dbg|=c;
|
|
if(!neg)InitDbg();
|
|
break;
|
|
case c_scd:
|
|
/*-----------------13.08.00 23:01-------------------
|
|
áóäåò ââåäåíà ïîñëå äîðàáîòêè äèíàìè÷åñêèõ ïðîöåäóð
|
|
--------------------------------------------------*/
|
|
splitdata=(unsigned char)1^neg;
|
|
if(modelmem==SMALL)splitdata=TRUE;
|
|
break;
|
|
case c_al:
|
|
if(ptr==NULL)return c_end;
|
|
aligner=(unsigned char)getnumber((unsigned char *)ptr);
|
|
break;
|
|
case c_at:
|
|
atex=(unsigned char)1^neg;
|
|
break;
|
|
case c_wfa:
|
|
FastCallApi=(unsigned char)1^neg;
|
|
break;
|
|
case c_wfu:
|
|
FixUpTable=(unsigned char)1^neg;
|
|
break;
|
|
case c_wib:
|
|
if(ptr==NULL)return c_end;
|
|
ImageBase=getnumber((unsigned char *)ptr);
|
|
break;
|
|
case c_iv:
|
|
notpost=(unsigned char)1^neg;
|
|
break;
|
|
case c_mer:
|
|
if(ptr==NULL)return c_end;
|
|
if((maxerrors=getnumber((unsigned char *)ptr))==0)maxerrors=16;
|
|
break;
|
|
case c_sa:
|
|
if(ptr==NULL)return c_end;
|
|
startptrdata=startptr=getnumber((unsigned char *)ptr);
|
|
break;
|
|
case c_stm:
|
|
startuptomain=(unsigned char)1^neg;
|
|
break;
|
|
case c_suv:
|
|
if(ptr==NULL)return c_end;
|
|
startStartup=getnumber((unsigned char *)ptr);
|
|
break;
|
|
case c_wmb:
|
|
WinMonoBlock=(unsigned char)1^neg;
|
|
break;
|
|
case c_ust:
|
|
useStartup=(unsigned char)1^neg;
|
|
break;
|
|
case c_help:
|
|
case c_h:
|
|
case c_hh:
|
|
PrintInfo((char **)usage);
|
|
exit(e_ok);
|
|
case c_mif:
|
|
if(ptr==NULL)return c_end;
|
|
if(rawfilename!=NULL){
|
|
free(rawfilename);
|
|
rawfilename=NULL;
|
|
}
|
|
if(rawext!=NULL){
|
|
free(rawext);
|
|
rawext=NULL;
|
|
}
|
|
char *temp;
|
|
if((temp=strrchr(ptr,'.'))!=NULL){
|
|
*temp++=0;
|
|
rawext=BackString(temp);
|
|
CheckExtenshions();
|
|
}
|
|
rawfilename=BackString(ptr);
|
|
break;
|
|
case c_ac:
|
|
AlignCycle=(unsigned char)1^neg;
|
|
if(ptr!=NULL){
|
|
aligncycle=getnumber((unsigned char *)ptr);
|
|
if(aligncycle<1&&aligncycle>4096)aligncycle=8;
|
|
}
|
|
break;
|
|
case c_ws: //dos-stub for windows programs
|
|
if(winstub)free(winstub);
|
|
winstub=BackString(ptr);
|
|
break;
|
|
case c_ind:
|
|
ImportName(ptr);
|
|
break;
|
|
case c_wbss:
|
|
wbss=(unsigned char)1^neg;
|
|
break;
|
|
case c_wo:
|
|
useordinal=(unsigned char)1^neg;
|
|
break;
|
|
case c_nw:
|
|
if(ptr==NULL)return c_end;
|
|
len=getnumber((unsigned char *)ptr);
|
|
if(len>0&&len<=WARNCOUNT)wact[len-1].usewarn=(unsigned char)0^neg;
|
|
break;
|
|
case c_we:
|
|
if(ptr==NULL)return c_end;
|
|
len=getnumber((unsigned char *)ptr);
|
|
if(len>0&&len<=WARNCOUNT){
|
|
if(neg)wact[len-1].fwarn=warningprint;
|
|
else wact[len-1].fwarn=preerror3;
|
|
}
|
|
break;
|
|
case c_lst:
|
|
SetLST(neg);
|
|
break;
|
|
case c_d4g:
|
|
useDOS4GW=(unsigned char)1^neg;
|
|
break;
|
|
case c_env:
|
|
use_env=(unsigned char)1^neg;
|
|
break;
|
|
case c_cpa:
|
|
clearpost=(unsigned char)1^neg;
|
|
break;
|
|
case c_ul:
|
|
uselea=(unsigned char)1^neg;
|
|
break;
|
|
case c_as:
|
|
if(ptr){
|
|
len=getnumber((unsigned char *)ptr);
|
|
if(caselong(len)!=NUMNUM)strpackdef=len;
|
|
}
|
|
else strpackdef=(neg==FALSE?8:1);
|
|
strpackcur=strpackdef;
|
|
break;
|
|
case c_lrs:
|
|
regoverstack=(unsigned char)1^neg;
|
|
break;
|
|
case c_wsi:
|
|
shortimport=(unsigned char)1^neg;
|
|
break;
|
|
case c_waf:
|
|
if(ptr!=NULL){
|
|
FILEALIGN=Align(getnumber((unsigned char *)ptr),16);
|
|
}
|
|
break;
|
|
case c_sf:
|
|
if(ptr==NULL)return c_end;
|
|
namestartupfile=BackString(ptr);
|
|
break;
|
|
case c_oir:
|
|
optinitreg=(unsigned char)1^neg;
|
|
break;
|
|
case c_coff:
|
|
ocoff=(unsigned char)1^neg;
|
|
break;
|
|
case c_js:
|
|
addstack=(unsigned char)1^neg;
|
|
if(addstack==0)RestoreStack();
|
|
break;
|
|
case c_ba:
|
|
bytesize=(unsigned char)1^neg;
|
|
break;
|
|
case c_asp:
|
|
if(blockproc)goto errlate;
|
|
else ESPloc=(unsigned char)1^neg;
|
|
break;
|
|
#ifdef OPTVARCONST
|
|
case c_orv:
|
|
replasevar=(unsigned char)1^neg;
|
|
if(replasevar&&listvic)ClearLVIC();
|
|
break;
|
|
case c_map:
|
|
mapfile=(unsigned char)1^neg;
|
|
break;
|
|
#endif
|
|
case c_ext: //***lev***
|
|
strcpy(outext,BackString(ptr)); //***lev***
|
|
extflag=FALSE; //÷òîáû ðàñøèðåíèå íå ïåðåçàáèâàëîñü äðóãèìè êëþ÷àìè, åñëè îíè èäóò ïîçæå
|
|
break; //***lev***
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void SetLST(unsigned char neg)
|
|
{
|
|
if(((dbg&2)>>1)==neg){
|
|
dbg&=0xFD;
|
|
unsigned char c=(unsigned char)((1^neg)<<1);
|
|
dbg|=c;
|
|
if(neg){
|
|
if((dbg&0xFE)==0)dbgact=TRUE;
|
|
AddEndLine();
|
|
}
|
|
else{
|
|
InitDbg();
|
|
if(notdoneprestuff!=TRUE)dbgact=FALSE; //startup cod
|
|
}
|
|
}
|
|
}
|
|
|
|
void print8item(char *str)
|
|
{
|
|
// CheckNumStr();
|
|
for(int j=0;j<8;j++)printf(str,j);
|
|
puts("");
|
|
}
|
|
|
|
|
|
|
|
|
|
void _loadIni(FILE *inih)
|
|
{
|
|
char m1[256];
|
|
for(;;){
|
|
if(fgets(m1,255,inih)==NULL)break;
|
|
if(SelectComand(m1,0)==c_end)BadCommandLine(m1);
|
|
}
|
|
fclose(inih);
|
|
}
|
|
|
|
void LoadIni(char *name)
|
|
{
|
|
FILE *inih;
|
|
char m1[256];
|
|
|
|
// load name
|
|
if (inih = fopen(name,"rb"))
|
|
{_loadIni(inih);return;}
|
|
|
|
if(strcmp(name,"c--.ini")!=0)
|
|
return;
|
|
|
|
//load findpath[0]\c--.ini
|
|
if (findpath[0]!=0)
|
|
{
|
|
sprintf(m1,"%s%s",findpath[0],name);
|
|
if (inih = fopen(m1,"rb"))
|
|
{_loadIni(inih);return;}
|
|
}
|
|
//load PATH[i=0..end]/c--.ini
|
|
char* pth = getenv("PATH");
|
|
if (pth != 0)
|
|
{
|
|
char* start;
|
|
int size;
|
|
start = pth;
|
|
while(*start)
|
|
{
|
|
size = 0;
|
|
char* endp = strchr(start, DIV_PATH);
|
|
size = (endp == 0)? strlen(start): endp-start;
|
|
strncpy(m1, start, size);
|
|
start += size + 1;
|
|
if (m1[size - 1] != DIV_FOLD)
|
|
m1[size++] = '/';
|
|
|
|
strcpy(m1 + size,"c--.ini");
|
|
if (inih = fopen(m1,"rb"))
|
|
{_loadIni(inih);return;}
|
|
}
|
|
}
|
|
#ifdef _KOS_
|
|
//for KolibriOS: load program_dir/c--.ini
|
|
int p;
|
|
strcpy(m1,__pgmname);
|
|
p = strlen(m1);
|
|
while ((*(m1+p)!='/') && (p != 0))
|
|
p--;
|
|
if (p){
|
|
p++;
|
|
strcpy(m1+p,"c--.ini");
|
|
if (inih = fopen(m1,"rb"))
|
|
{_loadIni(inih);return;}
|
|
}
|
|
//for KolibriOS: load /rd/0/settings/c--.ini
|
|
inih = fopen("/rd/1/settings/c--.ini","rb");
|
|
for(;;){
|
|
if(fgets(m1,255,inih)==NULL)break;
|
|
if(SelectComand(m1,0)==c_end)BadCommandLine(m1);
|
|
}
|
|
fclose(inih);
|
|
return;
|
|
#endif //_KOS_
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* .NAME : MALLOC
|
|
* .TITLE : Âûäåëÿåò ïàìÿòü ñ îáðàáîòêîé îøèáîê.
|
|
*****************************************************************************/
|
|
void OutMemory()
|
|
{
|
|
preerror("Compiler out of memory");
|
|
exit(e_outofmemory);
|
|
}
|
|
|
|
void * MALLOC (unsigned long size)
|
|
{
|
|
void *mem;
|
|
mem=malloc(size);
|
|
if(mem==NULL)OutMemory();
|
|
#ifdef _UNIX_
|
|
else memset(mem,0,size);
|
|
#endif
|
|
|
|
// if(((unsigned long)mem+size)>maxusedmem)maxusedmem=(unsigned long)mem+size;
|
|
|
|
return mem;
|
|
}
|
|
|
|
void *REALLOC(void *block,unsigned long size)
|
|
{
|
|
void *mem;
|
|
mem=realloc(block,size);
|
|
if(mem==NULL)OutMemory();
|
|
|
|
// if(((unsigned long)mem+size)>maxusedmem)maxusedmem=(unsigned long)mem+size;
|
|
|
|
return mem;
|
|
}
|
|
|
|
void IncludePath(char *buf)
|
|
{
|
|
char divfold[3];
|
|
sprintf(divfold,"%c",DIV_FOLD);
|
|
if(numfindpath<MAXNUMPATH-1){
|
|
int len=strlen(buf);
|
|
if(buf[len-1]==DIV_FOLD)buf[len-1]=0;
|
|
else len++;
|
|
char *a=(char *)MALLOC(len+1);
|
|
strcpy(a,buf);
|
|
strcat(a,divfold);
|
|
findpath[numfindpath]=a;
|
|
numfindpath++;
|
|
findpath[numfindpath]="";
|
|
}
|
|
else puts("Too many include paths");
|
|
}
|
|
|
|
void doposts()
|
|
{
|
|
unsigned long addvalue,i,addval,addvalw32=0,addvalbss=0;
|
|
if(splitdata&&modelmem==TINY&&outptrdata){
|
|
memcpy((char *)&output[outptr],(char *)&outputdata[0],outptrdata);
|
|
addval=outptr;
|
|
outptr+=outptrdata;
|
|
outptrdata=outptr;
|
|
}
|
|
addvalue=outptrdata;
|
|
if(comfile==file_bin)addvalbss=addvalw32=ImageBase;
|
|
else if(comfile==file_w32){
|
|
addvalbss=addvalw32=ImageBase+vsizeheader;
|
|
if(postsize&&wbss){
|
|
addvalw32+=Align(postsize,OBJECTALIGN);
|
|
addvalue=0;
|
|
}
|
|
}
|
|
else{
|
|
if((outptrdata%2)==1){ /* alignment of entire post data block manditory */
|
|
addvalue++; //íà÷àëî íåèíèö.äàííûõ
|
|
postsize++;
|
|
}
|
|
/* if(am32&&(outptrdata%4)==2){
|
|
addvalue+=2; //íà÷àëî íåèíèö.äàííûõ
|
|
postsize+=2;
|
|
}*/
|
|
}
|
|
if(am32==0&&(MAXDATA-outptrdata)<postsize)preerror("post variable size exceeds size left in data segment");
|
|
for(i=0;i<posts;i++){
|
|
switch((postbuf+i)->type){
|
|
case POST_VAR:
|
|
*(short *)&output[(postbuf+i)->loc]+=(short)addvalue;
|
|
break;
|
|
case POST_VAR32:
|
|
*(long *)&output[(postbuf+i)->loc]+=addvalue+addvalbss;
|
|
numrel++;
|
|
break;
|
|
case FIX_VAR32:
|
|
case FIX_CODE32:
|
|
*(long *)&output[(postbuf+i)->loc]+=addvalw32;
|
|
numrel++;
|
|
break;
|
|
case FIX_CODE_ADD:
|
|
if(am32){
|
|
*(long *)&output[(postbuf+i)->loc]+=addvalw32+(postbuf+i)->num;
|
|
(postbuf+i)->type=(unsigned short)FIX_VAR32;
|
|
}
|
|
else{
|
|
*(short *)&output[(postbuf+i)->loc]+=(short)(addval+(postbuf+i)->num);
|
|
(postbuf+i)->type=(unsigned short)FIX_VAR;
|
|
}
|
|
numrel++;
|
|
break;
|
|
case DATABLOCK_VAR:
|
|
*(short *)&output[(postbuf+i)->loc]+=(short)addval;
|
|
if(FixUp)(postbuf+i)->type=(unsigned short)FIX_VAR;
|
|
break;
|
|
case DATABLOCK_VAR32:
|
|
*(long *)&output[(postbuf+i)->loc]+=addval+addvalw32;
|
|
if(FixUp)(postbuf+i)->type=(unsigned short)FIX_VAR32;
|
|
numrel++;
|
|
break;
|
|
}
|
|
}
|
|
ooutptr=addvalue; //ñîõðàíèòü íà÷àëî post äëÿ debug;
|
|
}
|
|
|
|
void GetMemExeDat()
|
|
{
|
|
if(outputdata==output&&outputdata!=0)outputdata=(unsigned char *)MALLOC((size_t)MAXDATA);
|
|
}
|
|
|
|
|
|
|
|
int writeoutput()
|
|
{
|
|
EXE_DOS_HEADER exeheader; // header for EXE format
|
|
if(fobj){
|
|
if(comfile==file_w32&&ocoff)return MakeCoff();
|
|
return MakeObj();
|
|
}
|
|
if(comfile==file_w32)return MakePE();
|
|
if(comfile==file_meos)return MakeMEOS();
|
|
if(comfile==file_bin)return MakeBin32();
|
|
memset(&exeheader,0,sizeof(EXE_DOS_HEADER));
|
|
if(comfile==file_d32){
|
|
if(usestub){
|
|
MakeLE();
|
|
runfilesize+=ftell(hout)-32;
|
|
goto savecode;
|
|
}
|
|
else goto exefile;
|
|
}
|
|
if(comfile==file_com||comfile==file_sys||comfile==file_rom){
|
|
hout=CreateOutPut(outext,"wb");
|
|
if(fwrite(output+startptr,comfile==file_rom?romsize:outptr-startptr,1,hout)!=1){
|
|
ErrWrite();
|
|
return(-1);
|
|
}
|
|
}
|
|
else if(comfile==file_exe){
|
|
exefile:
|
|
hout=CreateOutPut(outext,"wb");
|
|
MakeExeHeader(&exeheader);
|
|
if(fwrite(&exeheader,sizeof(EXE_DOS_HEADER),1,hout)!=1){
|
|
errwr:
|
|
fclose(hout);
|
|
hout=NULL;
|
|
ErrWrite();
|
|
return(-1);
|
|
}
|
|
outputcodestart=ftell(hout);
|
|
savecode:
|
|
if(fwrite(output+startptr,outptr-startptr,1,hout)!=1)goto errwr;
|
|
if(modelmem==SMALL&&outptrdata!=0){
|
|
if(fwrite(outputdata,outptrdata,1,hout)!=1)goto errwr;
|
|
}
|
|
}
|
|
fclose(hout);
|
|
hout=NULL;
|
|
return(0);
|
|
}
|
|
|
|
long CopyFile(FILE *in,FILE *out)
|
|
{
|
|
char tbuf[1024];
|
|
long loads=0;
|
|
unsigned int len;
|
|
do{
|
|
len=fread(tbuf,1,1024,in);
|
|
if(fwrite(tbuf,1,len,out)!=len){
|
|
ErrWrite();
|
|
return -1;
|
|
}
|
|
loads+=len;
|
|
}while(len==1024);
|
|
return loads;
|
|
}
|
|
|
|
unsigned int EntryPoint()
|
|
{
|
|
ITOK btok;
|
|
int bb=tk_id;
|
|
unsigned char bufmain[]="main";
|
|
unsigned char buf2[]="__startupproc";
|
|
unsigned char *buf;
|
|
if(comfile==file_com)return startptr;
|
|
btok.number=0;
|
|
// if(jumptomain!=CALL_NONE||(comfile==file_w32&&dllflag))buf=buf2;
|
|
// else buf=bufmain;
|
|
|
|
if(jumptomain==CALL_NONE){
|
|
if(useDOS4GW)buf=buf2;
|
|
else buf=bufmain;
|
|
}
|
|
else buf=buf2;
|
|
|
|
searchtree(&btok,&bb,buf);
|
|
if(bb==tk_id){
|
|
if(comfile==file_w32&&dllflag)return 0xffffffff;
|
|
printf("Error! Entry point '%s' is not found.\n",buf);
|
|
exit(e_entrynotfound);
|
|
}
|
|
return btok.number;
|
|
}
|
|
|
|
void MakeExeHeader(EXE_DOS_HEADER *exeheader)
|
|
{
|
|
long paragraphsrequired;
|
|
unsigned short count,i;
|
|
int pointstart;
|
|
exeheader->sign=0x5a4D; // MZ
|
|
// if(modelmem==TINY&&comfile==file_exe)pointstart=0x100;
|
|
/* else*/ pointstart=EntryPoint();
|
|
count=(unsigned short)(runfilesize%512);
|
|
i=(unsigned short)(runfilesize/512);
|
|
exeheader->numlastbyte=count;
|
|
exeheader->numpage=(unsigned short)(count==0?i:i+1);
|
|
exeheader->headsize=2; // size of header in paragraphs (2 paragraphs)
|
|
exeheader->initIP=(unsigned short)pointstart; // IP at entry (0x0000)
|
|
paragraphsrequired=(outptr+outptrdata+postsize+stacksize+15)/16;
|
|
if(modelmem==TINY&&comfile==file_exe){
|
|
exeheader->initSS=0xFFF0; // displacement of SS
|
|
exeheader->initSP=0xFFFE; // intial value of SP
|
|
exeheader->initCS=0xfff0; // displacement of CS (0x0000)
|
|
if(!resizemem){
|
|
exeheader->minmem=0xfff; // min-paragraphs
|
|
exeheader->maxmem=0xffff; // max-paragraphs
|
|
}
|
|
else{
|
|
paragraphsrequired-=0x10;
|
|
exeheader->initSP=(unsigned short)(paragraphsrequired*16); // intial value of SP
|
|
exeheader->minmem=(unsigned short)paragraphsrequired; // min-paragraphs
|
|
exeheader->maxmem=(unsigned short)paragraphsrequired; // max-paragraphs
|
|
}
|
|
}
|
|
else if(comfile==file_d32){
|
|
exeheader->initSP=(unsigned short)stacksize; // intial value of SP
|
|
exeheader->initSS=(unsigned short)((outptr+postsize+15)/16); // displacement of SS
|
|
exeheader->initCS=(unsigned short)((pointstart/65536)*4096);
|
|
if(resizemem){
|
|
exeheader->minmem=(unsigned short)paragraphsrequired; // min-paragraphs
|
|
exeheader->maxmem=(unsigned short)paragraphsrequired; // max-paragraphs
|
|
}
|
|
else exeheader->maxmem=(unsigned short)0xFFFF; // max-paragraphs
|
|
}
|
|
else{
|
|
exeheader->initSS=(unsigned short)(outptr/16); // displacement of SS
|
|
exeheader->initSP=(unsigned short)(outptrdata+postsize+stacksize); // intial value of SP
|
|
exeheader->minmem=(unsigned short)paragraphsrequired; // min-paragraphs
|
|
exeheader->maxmem=(unsigned short)paragraphsrequired; // max-paragraphs
|
|
}
|
|
exeheader->ofsreloc=0x1c; // offset of first relocation item (0x0000)
|
|
}
|
|
|
|
void startsymbiosys(char *symfile)
|
|
{
|
|
unsigned int size;
|
|
int filehandle;
|
|
long filesize;
|
|
outptr=startptr;
|
|
if((filehandle=open(symfile,O_BINARY|O_RDONLY))==-1){;
|
|
ErrOpenFile(symfile);
|
|
exit(e_symbioerror);
|
|
}
|
|
if((filesize=getfilelen(filehandle))!=-1L){
|
|
if(filesize+outptr<MAXDATA){
|
|
size=filesize;
|
|
if((unsigned int)read(filehandle,output+outptr,size)!=size){
|
|
close(filehandle);
|
|
puts("Error reading symbio COM file.");
|
|
exit(e_symbioerror);
|
|
}
|
|
outptr+=size;
|
|
}
|
|
else{
|
|
puts("Symbio COM file is too large.");
|
|
exit(e_symbioerror);
|
|
}
|
|
}
|
|
else{
|
|
puts("Unable to determine symbio COM file size.");
|
|
exit(e_symbioerror);
|
|
}
|
|
close(filehandle);
|
|
outptrdata=outptr;
|
|
outputcodestart=outptr-startptr;
|
|
addconsttotree("__comsymbios",TRUE);
|
|
}
|
|
|
|
void BadCommandLine(char *str)
|
|
{
|
|
printf("Unknown or bad command line option '%s'.\n",str);
|
|
// PrintInfo(usage);
|
|
exit(e_unknowncommandline);
|
|
}
|
|
|
|
void warnunused(struct idrec *ptr)
|
|
{
|
|
//static count=0;
|
|
if(ptr!=NULL){
|
|
if(ptr->count==0&&startupfile!=ptr->file){
|
|
linenumber=ptr->line;
|
|
currentfileinfo=ptr->file;
|
|
int i=0;
|
|
switch(ptr->rectok){
|
|
case tk_proc:
|
|
if(ptr->recsegm!=NOT_DYNAMIC||strcmp(ptr->recid,mesmain)==0)break;
|
|
i++;
|
|
case tk_structvar:
|
|
i++;
|
|
case tk_charvar:
|
|
case tk_bytevar:
|
|
case tk_intvar:
|
|
case tk_wordvar:
|
|
case tk_longvar:
|
|
case tk_dwordvar:
|
|
case tk_floatvar:
|
|
case tk_pointer:
|
|
case tk_qword:
|
|
case tk_double:
|
|
if(i<=1&&(ptr->recpost==DYNAMIC_VAR||ptr->recpost==DYNAMIC_POST))break;
|
|
warningnotused(ptr->recid,i);
|
|
break;
|
|
}
|
|
}
|
|
warnunused(ptr ->left);
|
|
warnunused(ptr ->right);
|
|
}
|
|
}
|
|
|
|
void WarnUnusedVar()//ïðåäóïðåæäåíèÿ î íåèñïîëüçîâàííûõ ïðîöåäóðàõ è ïåðåìåííûõ
|
|
{
|
|
warnunused(treestart);
|
|
for(unsigned int i=0;i<totalmodule;i++)warnunused((startfileinfo+i)->stlist);
|
|
}
|
|
|
|
void addinitvar()
|
|
{
|
|
unsigned int i;
|
|
if(numfloatconst){ //âñòàâèòü êîíñòàíòû float è ïðèâÿçàòü èõ
|
|
if(alignword||optimizespeed)AlignCD(DS,chip>5?16:4);
|
|
for(i=0;i<posts;i++){
|
|
if((postbuf+i)->type==POST_FLOATNUM){
|
|
if(am32)*(unsigned long *)&output[(postbuf+i)->loc]=outptrdata+(postbuf+i)->num;
|
|
else *(unsigned short *)&output[(postbuf+i)->loc]=(unsigned short)(outptrdata+(postbuf+i)->num);
|
|
if(FixUp)(postbuf+i)->type=FIX_VAR32;
|
|
else killpost(i--);
|
|
}
|
|
}
|
|
for(i=0;i<numfloatconst;i++){
|
|
if(dbg&2){
|
|
if((floatnum+i)->type==tk_float)sprintf((char *)string,"const float %f",(floatnum+i)->fnum);
|
|
else sprintf((char *)string,"const double %f",(floatnum+i)->dnum);
|
|
AddDataNullLine(4,(char *)string);
|
|
}
|
|
outdwordd((floatnum+i)->num[0]);
|
|
if((floatnum+i)->type!=tk_float){
|
|
outdwordd((floatnum+i)->num[1]);
|
|
datasize+=4;
|
|
}
|
|
datasize+=4;
|
|
}
|
|
free(floatnum);
|
|
numfloatconst=0;
|
|
floatnum=NULL;
|
|
}
|
|
for(i=0;i<(unsigned int)numswtable;i++){ //ñîçäàòü è âñòàâèòü òàáëèöû switch
|
|
int j;
|
|
FSWI *swt=swtables+i;
|
|
if(alignword)AlignCD(DS,swt->type);
|
|
if(dbg&2)AddDataNullLine((char)swt->type,"switch table address");
|
|
if(am32==FALSE){ //âñòàâèòü â êîä àäðåñ òàáëèöû
|
|
*(unsigned short *)&output[swt->ptb]=(unsigned short)outptrdata;
|
|
}
|
|
else *(unsigned long *)&output[swt->ptb]=outptrdata;
|
|
unsigned char oam32=am32;
|
|
am32=(unsigned char)(swt->type/2-1);
|
|
|
|
unsigned long val=swt->defal;
|
|
int oline=outptrdata;
|
|
for(j=0;j<swt->sizetab;j++){ //çàïîëíèòü òàáëèöó çíà÷åíèÿìè ïî óìîë÷àíèþ
|
|
// if((swt->info+jj)->type==singlcase)
|
|
AddReloc(DS);
|
|
if(am32)outdwordd(val);
|
|
else outwordd(val);
|
|
}
|
|
if(swt->mode==2){
|
|
if(dbg&2)AddDataNullLine((char)swt->razr,"switch table value");
|
|
if(oam32==FALSE){ //âñòàâèòü â êîä àäðåñ òàáëèöû
|
|
*(unsigned short *)&output[swt->ptv]=(unsigned short)outptrdata;
|
|
}
|
|
else *(unsigned long *)&output[swt->ptv]=outptrdata;
|
|
}
|
|
int ii=0; //ñ÷åò÷èê case
|
|
for(int jj=0;jj<swt->numcase;jj++){
|
|
j=(swt->info+jj)->value; //çíà÷åíèå
|
|
val=(swt->info+jj)->postcase;
|
|
if((swt->info+jj)->type==singlcase){
|
|
if(swt->mode==1){
|
|
if(am32==FALSE)*(unsigned short *)&outputdata[oline+j*2]=(unsigned short)val;
|
|
else *(unsigned long *)&outputdata[oline+j*4]=val;
|
|
}
|
|
else{
|
|
if(am32==FALSE)*(unsigned short *)&outputdata[oline+ii*2]=(unsigned short)val;
|
|
else *(unsigned long *)&outputdata[oline+ii*4]=val;
|
|
switch(swt->razr){
|
|
case r8: opd(j); break;
|
|
case r16: outwordd(j); break;
|
|
case r32: outdwordd(j); break;
|
|
}
|
|
ii++;
|
|
}
|
|
}
|
|
else{
|
|
jj++;
|
|
for(;(unsigned int)j<=(swt->info+jj)->value;j++){
|
|
if(swt->mode==1){
|
|
if(am32==FALSE)*(unsigned short *)&outputdata[oline+j*2]=(unsigned short)val;
|
|
else *(unsigned long *)&outputdata[oline+j*4]=val;
|
|
}
|
|
else{
|
|
if(am32==FALSE)*(unsigned short *)&outputdata[oline+ii*2]=(unsigned short)val;
|
|
else *(unsigned long *)&outputdata[oline+ii*4]=val;
|
|
switch(swt->razr){
|
|
case r8: opd(j); break;
|
|
case r16: outwordd(j); break;
|
|
case r32: outdwordd(j); break;
|
|
}
|
|
ii++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
am32=oam32;
|
|
free(swt->info);
|
|
}
|
|
if(numswtable){
|
|
free(swtables);
|
|
numswtable=0;
|
|
}
|
|
|
|
for(i=0;i<posts;i++){
|
|
if((postbuf+i)->type==DIN_VAR||(postbuf+i)->type==DIN_VAR32){
|
|
idrec *ptr=(idrec *)(postbuf+i)->num;
|
|
// printf("post=%u num=%08X %s\n",ptr->recpost,ptr->recnumber,ptr->recid);
|
|
if(ptr->recpost==USED_DIN_VAR)setdindata(ptr,i);
|
|
else{
|
|
if((postbuf+i)->type==DIN_VAR){
|
|
*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)(ptr->recnumber);
|
|
}
|
|
else{
|
|
// printf("loc=%08X num=%08X\n",*(unsigned long *)&output[(postbuf+i)->loc],ptr->recnumber);
|
|
*(unsigned long *)&output[(postbuf+i)->loc]+=ptr->recnumber;
|
|
}
|
|
}
|
|
if(FixUp)(postbuf+i)->type=(unsigned short)((postbuf+i)->type==DIN_VAR?FIX_VAR:FIX_VAR32);
|
|
else killpost(i--);
|
|
}
|
|
}
|
|
dopoststrings();
|
|
}
|
|
|
|
void setdindata(idrec *ptr,int i)
|
|
{
|
|
unsigned char *oldinput;
|
|
unsigned int oldinptr,oldendinptr;
|
|
unsigned char bcha;
|
|
unsigned int oline,ofile;
|
|
char *ostartline;
|
|
if(alignword){
|
|
if(ptr->rectok==tk_structvar)alignersize+=AlignCD(DS,2); //âûðîâíÿòü
|
|
else alignersize+=AlignCD(DS,GetVarSize(ptr->rectok));
|
|
}
|
|
// printf("loc=%08X out=%08X num=%08X\n",*(unsigned long *)&output[(postbuf+i)->loc],outptrdata,ptr->recnumber);
|
|
if((postbuf+i)->type==DIN_VAR)*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)(outptrdata);
|
|
else *(unsigned long *)&output[(postbuf+i)->loc]+=outptrdata;
|
|
ptr->recpost=0;
|
|
ptr->recnumber+=outptrdata;
|
|
oline=linenum2;
|
|
ofile=currentfileinfo;
|
|
oldinput=input;
|
|
oldinptr=inptr2;
|
|
bcha=cha2;
|
|
oldendinptr=endinptr;
|
|
input=(unsigned char *)ptr->sbuf;
|
|
inptr2=1;
|
|
ostartline=startline;
|
|
startline=(char*)input;
|
|
cha2=input[0];
|
|
linenum2=ptr->line;
|
|
currentfileinfo=ptr->file;
|
|
endinptr=strlen((char *)input);
|
|
endinput=startline+endinptr;
|
|
endoffile=0;
|
|
tok=ptr->rectok;
|
|
if(tok==tk_structvar)datasize+=initstructvar((structteg *)ptr->newid,ptr->recrm);
|
|
else{
|
|
long type = 0,ssize = 0;
|
|
unsigned char typev = 0;
|
|
if(tok>=tk_charvar&&tok<=tk_doublevar){
|
|
type=tok-(tk_charvar-tk_char);
|
|
typev=variable;
|
|
ssize=typesize(type);
|
|
}
|
|
else if(tok==tk_pointer){
|
|
typev=pointer;
|
|
type=itok.type;
|
|
if(am32==FALSE&&((itok.flag&f_far)==0))ssize=2;
|
|
else ssize=4;
|
|
}
|
|
datasize+=initglobalvar(type,ptr->recsize/ssize,ssize,typev);
|
|
}
|
|
free(input);
|
|
linenum2=oline;
|
|
currentfileinfo=ofile;
|
|
input=oldinput;
|
|
inptr2=oldinptr;
|
|
cha2=bcha;
|
|
endinptr=oldendinptr;
|
|
endoffile=0;
|
|
startline=ostartline;
|
|
}
|
|
|
|
FILE *CreateOutPut(char *ext,char *mode)
|
|
{
|
|
char buf[256];
|
|
FILE *diskout;
|
|
sprintf(buf,"%s.%s",rawfilename,ext);
|
|
if((diskout=fopen(buf,mode))==NULL){
|
|
ErrOpenFile(buf);
|
|
exit(e_notcreateoutput);
|
|
}
|
|
return diskout;
|
|
}
|
|
|
|
int numundefclassproc=0;
|
|
idrec **undefclassproc;
|
|
|
|
void AddUndefClassProc()
|
|
{
|
|
if(numundefclassproc==0)undefclassproc=(idrec **)MALLOC(sizeof(idrec **));
|
|
else undefclassproc=(idrec **)REALLOC(undefclassproc,sizeof(idrec **)*(numundefclassproc+1));
|
|
undefclassproc[numundefclassproc]=itok.rec;
|
|
numundefclassproc++;
|
|
}
|
|
|
|
void CheckUndefClassProc()
|
|
{
|
|
for(int i=0;i<numundefclassproc;i++){
|
|
idrec *ptr=undefclassproc[i];
|
|
if(ptr->rectok==tk_undefproc){
|
|
currentfileinfo=ptr->file;
|
|
linenumber=ptr->line;
|
|
thisundefined(ptr->recid);
|
|
}
|
|
}
|
|
}
|