⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oxccl.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 5 页
字号:
static int
setup_nodelinks(Piv iv, char *infile_name, void *inbuf, int insize)
{
unsigned char *p = inbuf;
unsigned char *endbuf = inbuf+insize;
Pafile pf=0;
long lastline = 0;
unsigned char *funcp;
unsigned char *nfuncp;

	while(p < endbuf && *p != endallop)
	{
	unsigned char *q = p;
		if(iv->debug)
		{
			PRINTF("OP(%d '%s' p=%p line=%ld)\n", *p, oxgenops[*p], p, lastline);
		}
		switch(*p)
		{
			case headerop:
				if(iv->numfiles >= 1024) {
					PERROR(pName ": Sorry, too many files\n");
					return 1;
				}
				pf = iv->files[iv->numfiles] = 
					Ccalloc(iv->category, 1, sizeof(struct _afile));
				pf->filenum = iv->numfiles++;
				pf->file_p = p;
				pf->header_p = POPI;
				if(iv->strip)
				{/* Gonna strip declarations and line numbers */
					pf->header_p->hdr.target_debugger = 0;
				}
				break;

			case dataop:
				pf->size_p = POPI;
				pf->thunk_offset = GL(POPI->dat.thunk_offset);
				pf->bss_offset = GL(POPI->dat.bss_offset);
				break;
			case gfuncdefop:
			case sfuncdefop:
				if(pf->prog_p == 0)
					pf->prog_p = p;
				funcp = p;
				break;
			case funcexitop:
				PS(((PopI)(funcp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
				break;
			case nestedfuncdefop:
				nfuncp = p;
				break;
			case nestedfuncexitop:
				PS(((PopI)(nfuncp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
				break;
			case segdefop:
				if(pf->seg_p == 0)
					pf->seg_p = p;
				pf->numsegs += 1;
				iv->numsegs += 1;
				break;
			case lineop:
				lastline = GL( POPI->line.line );
				if(iv->strip)
					*p = 0;		/* strip line numbers */
				break;
			case declop:
				if(iv->strip)
				{/* strip declarations */
					do {
						*p = 0;
						q += (long)GL(POP->next);
						POP->next = q;
						p = q;
					} while(*p != endop);					
					*p = 0;
				}
				else
				{
					if(pf->decl_p == 0)
						pf->decl_p = p;
					pf->numdecls += 1;
					iv->numdecls += 1;
				}
				break;
			case switchidop:
				if(pf->switch_p == 0)
					pf->switch_p = p;
			/* FALL THROUGH */
			case labelop:
				PL( POP->data ) = 
						label_insert(iv, GL( POP->data ), pf->filenum);
				break;			
			case symbop:
				pf->numsyms = GL(POP->data);
				iv->numsyms += pf->numsyms;
				break;
			case symblockop:
				pf->symtext_p = p + 12;
				goto blka;
			case stringblockop:
			case datablockop:
			case mallocblockop:
			case thunkblockop:
			{
			long size;
				if(pf->data_p == 0)
					pf->data_p = p;
blka:
				size = GL(POP->data);
				q += size+((4-(size&3))&3);
				break;
			}
			case glofuncop:
			case extfuncop:
			case glodatop:
			case globssop:
			case extvarop:
			case bssblockop:
				if(pf->data_p == 0)
					pf->data_p = p;
				break;
			case maxtempop:
				pf->maxtemp = GL(POP->data);
				pf->maxtempclass = GL(POP->data1);
				pf->maxtemp_p = p;
				break;
		}
		q += (long)GL(POP->next);
		POP->next = q;
		p = q;
	}
	if(*p != endallop)
	{
		PERROR(pName ":ERROR: Malformed input file: %s\n", infile_name);
		return 1;
	}
	return 0;
}
static void
setup_syms_decls(Piv iv)
{
int i;

	for(i = 0; i < iv->numfiles; ++i)
	{
	int symnum = 0;
	Pafile pf = iv->files[i];
	unsigned char *p = pf->file_p;

		pf->symaddr = Ccalloc(iv->category, sizeof(void*), pf->numsyms);
		pf->decladdr = Ccalloc(iv->category, sizeof(void*), pf->numdecls);

		while(*p != endfileop)
		{
			switch(*p)
			{
				case	symoffsetop:
				  pf->symaddr[symnum] = pf->symtext_p + GL(POP->data);
				  ++symnum;
				  break;

				case	declop:
				  pf->decladdr[GS(POPI->dcl.declnum)] = p;
				  break;

				case	relocop:
				case	extlocop:
				  ++pf->numrelocs;
				  reloc_insert(iv, i, p);
				  break;

				case	glodatop:
				case	globssop:
				case	glofuncop:
				case	extfuncop:
				  global_insert(iv, pf, p);
				  break;

				case	extvarop:
				  extern_insert(iv, p, i);
				  global_insert(iv, pf, p);
				  break;

				case	stringblockop:
				case	datablockop:
				case	mallocblockop:
				case	thunkblockop:
				case	bssblockop:
				  if(!pf->datatbl)
					pf->datatbl = NewSymTable(iv->category, 0);  /* sorted */

				  data_insert(pf->datatbl,GL(DATI.offset),GL(DATI.size),p);

				  if(*p == thunkblockop) {
					PL(POP->data4) = label_find(iv, GL(POP->data4),i);
				  }
				  break;

				case	jmploopop:
				case	jmpcontinueop:
				case	jmpbreakop:
				case	jmpgotoop:
				case	jmptrueop:
				case	jmpfalseop:
				  PL(POP->data) = label_find(iv, GL(POP->data), i);
				  break;
				case	switchidop:
				  if(GL(POP->data1))
					PL(POP->data1) = label_find(iv, GL(POP->data1), i);
				  break;
				case	switchop:
				  PL(POP->data) = label_find(iv, GL(POP->data), i);
				  PL(POP->data1) = label_find(iv, GL(POP->data1), i);
				  break;
				case casevalop:
				  PL(POP->data1) = label_find(iv, GL(POP->data1), i);
				  break;
			}
			p = POP->next;
		}
	}
}
static int
sym_insert(Piv iv, char *symname, int symnum)
{/* Used only for combining symbols in link phase */
struct {
	char *symname;
	int symnum;
} *valp;

	if(StringInsert(iv->symtbl, symname, &valp))
		return -valp->symnum;	/* MATCH */
	valp->symnum = symnum;
	return symnum;
}
static void
combine_syms_decls(Piv iv)
{
int i,j;
Pafile pf;
int numsyms;
int numdecls;


	/* COMBINE SYMBOLS */
	pf = iv->files[0];
	numsyms = pf->numsyms;
	pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms);
	memcpy(iv->symaddr, pf->symaddr, sizeof(void*) * numsyms);


	for(i = 0; i < numsyms; ++i)
	{/* file 0 */
		sym_insert(iv, pf->symaddr[i], i);
		pf->symtran[i] = i;
	}
	for(i = 1; i < iv->numfiles; ++i)
	{
	int start;
		pf = iv->files[i];
		pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms);
		if(pf->header_p->hdr.target_debugger)
			start = 1;
		else
			start = 3;
		for(j = start; j < pf->numsyms; ++j)
		{
		int k;
		  if((k = sym_insert(iv, pf->symaddr[j], numsyms)) > 0)
		  { /* new entry */
			iv->symaddr[numsyms++] = pf->symaddr[j];
			pf->symtran[j] = k;
		  }
		  else pf->symtran[j] = -k;
		}
	}
	iv->numsyms = numsyms;

	/* COMBINE DECLARATIONS */
	pf = iv->files[0];
	numdecls = pf->numdecls;
	pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls);
	memcpy(iv->decladdr, pf->decladdr, sizeof(void*) * numdecls);

	for(i = 0; i < numdecls; ++i)
	{/* file 0 */
		pf->decltran[i] = i;
	}
	for(i = 1; i < iv->numfiles; ++i)
	{
		pf = iv->files[i];
		pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls);
		if(pf->numdecls < 21)
			continue;
		for(j = 1; j <= 21; ++j)
			pf->decltran[j] = j;
		for(j = 22; j < pf->numdecls; ++j) {
			iv->decladdr[numdecls] = pf->decladdr[j];
			pf->decltran[j] = numdecls++;
		}
	}
	iv->numdecls = numdecls;
}

static void
link_dups(Piv iv, int dupcnt, struct _gloval *valp[])
{
int i;
int vars[5] = {0,0,0,0,0};
unsigned long cdsize = 0;
unsigned long cdoffset = 0;
short cdfile = 0;
int cdnum = 0;
short segid = 0;

#define GDAT vars[0]
#define GBSS vars[1]
#define GFUNC vars[2]
#define EVAR vars[3]
#define EFUNC vars[4]

	/* Count the types of matches */
	for(i = 0; i <= dupcnt; ++i)
		vars[*(valp[i]->p) - glodatop] += 1;

	/* Check for errors */
	if(		GDAT > 1 
		||	GFUNC > 1
		||	(GFUNC && (GDAT || GBSS || EVAR))
		||	(EFUNC && (GDAT || GBSS || EVAR)))
	{
		++iv->errors;
		for(i = 0; i < dupcnt; ++i)
		{
			PWARN(pName ": Symbol `%s' multiply defined or mistyped.\n",
			  	valp[i]->symname);
			PWARN(pName ":  In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
		}
		return;
	}
	if(EFUNC && GFUNC)
	{/* match up functions */
	Pop dp;
		for(i = 0; i <= dupcnt; ++i)
		  if(*(valp[i]->p) == glofuncop)
			break;
		dp = (Pop)((Pop)valp[i]->p)->next;	/* points to thunkblockop */
		cdoffset = GL(dp->data1);			/* save this offset */
		cdfile = valp[i]->pf->filenum;		/* save this file */

		for(i = 0; i <= dupcnt; ++i)
		{
		  if(*(valp[i]->p) == extfuncop)
		  {
			*(valp[i]->p) = 0;					/* convert to nilop */
			dp = (Pop)((Pop)valp[i]->p)->next;	/* points to thunkblockop */

			/* Kill the functhunk */
			*((char*)dp) = 0;
			PL(dp->data4) = cdoffset;			/* use this offset for access */
			PS(((short*)dp)[1]) = cdfile;		/* fileno to unused slots */
		  }
		}
	}
	else if(EFUNC)
	{/* multiple references to external function */
	Pop	dp = (Pop)((Pop)valp[0]->p)->next;	/* points to first thunkblockop */

		cdoffset = GL(dp->data1);			/* save first offset */
		cdfile = valp[0]->pf->filenum;		/* save first file */
		for(i = 1; i <= dupcnt; ++i)
		{/* Kill all thunkblocks except the first */
			*(valp[i]->p) = 0;					/* convert to nilop */
			dp = (Pop)((Pop)valp[i]->p)->next;	/* points to thunkblockop */
			*((char*)dp) = 0;
			PL(dp->data4) = cdoffset;			/* use this offset for access */
			PS(((short*)dp)[1]) = cdfile;		/* fileno to unused slots */
		}
	}
	else if(GBSS)
	{/* comdefs */
	int multsize = 0;

		/* PICK THE BIGGEST GLOBAL BSS (comdef) */
		for(i = 0; i <= dupcnt; ++i)
		{
		Pop dp = (Pop)((Pop)valp[i]->p)->next;	/* points to bssblockop */
		  if((short)dp->data4 && segid == 0)
		  {
			segid = (short)dp->data4;
		  }
		  else if((short)dp->data4 && (short)dp->data4 != segid)
		  {
			++iv->errors;
			PWARN(pName, ": Variable `%s' defined in multiple segments.\n",
				valp[i]->symname);
			PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
		  }
		  if(*(valp[i]->p) == globssop)
		  {
		  long size = GL(dp->data);
			if(cdsize && size != cdsize)
				multsize = 1;
			if(size > cdsize) {
				cdsize = size;
				cdoffset = GL(dp->data1);
				cdfile = valp[i]->pf->filenum;
				cdnum = i;
			}
		  }
		}
		if(GDAT)
		{
		  /* INITIALIZED DATA WILL ALWAYS OVERRIDE BSS */
		  for(i = 0; i <= dupcnt; ++i)
		  {
			if(*(valp[i]->p) == glodatop)
			{
			Pop dp = (Pop)((Pop)valp[i]->p)->next;	/* points to datablockop */
			long size = GL(dp->data);
			  if(cdsize && size != cdsize)
			  	multsize = 1;
			  if(size < cdsize)
			  {
			++iv->errors;
			PWARN(pName ": Initialized variable `%s' of size (%d)\n",
			  valp[i]->symname, size);
			PWARN(pName ":  In file: `%s'\n",
			  valp[i]->pf->symaddr[INFILE_SYMNUM]);
			PWARN(pName ":  Is incommensurate with common size (%d).\n",
			  cdsize);
			  }
			  else
			  {
				  cdsize = size;
				  cdoffset = GL(dp->data1);
				  cdfile = valp[i]->pf->filenum;
				  cdnum = i;
			  }
			}
		  }
		}
		if(multsize)
		{
		  PWARN(pName ":warning: Common Variable `%s' has multiple sizes.\n",
			  valp[0]->symname);
		  for(i = 0; i <= dupcnt; ++i)
		  {
		  unsigned char opcode = *(valp[i]->p);
		    if(opcode == globssop || opcode == glodatop)
		    {
				PWARN(pName ":  Size=%d in file: `%s'\n",
				  GL(((Pop)((Pop)valp[i]->p)->next)->data),
				  valp[i]->pf->symaddr[INFILE_SYMNUM]);
			}
		  }
		}
		/* FINALLY, LINK COMMONS TO THE CHOSEN ONE */
		for(i = 0; i <= dupcnt; ++i)
		{
		  if(i != cdnum && *(valp[i]->p) == globssop)
		  {
		  Pop dp = (Pop)((Pop)valp[i]->p)->next;	/* points to bssblockop */

			*(valp[i]->p) = 0;			/* globssop becomes nilop */
			*((char*)dp) = 0;			/* bssblockop becomes nilop */
			PL(dp->data1) = cdoffset;	/* use this new offset for access */
			PS(((short*)dp)[1]) = cdfile;	/* put fileno in unused slots */
		  }
		}
	}
	else if(GDAT)
	{
		for(i = 0; i <= dupcnt; ++i)
		{
		Pop dp = (Pop)((Pop)valp[i]->p)->next;	/* points to datablockop */
		  if((short)dp->data4 && segid == 0)
		  {
			segid = (short)dp->data4;
		  }
		  else if((short)dp->data4 && (short)dp->data4 != segid)
		  {
			++iv->errors;
			PWARN(pName, ": Variable `%s' defined in multiple segments.\n",
				valp[i]->symname);
			PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
		  }
		  if(*(valp[i]->p) == glodatop)
		  {
			cdsize = GL(dp->data);
			cdoffset = GL(dp->data1);
			cdfile = valp[i]->pf->filenum;
			cdnum = i;
			break;
		  }
		}
	}
	if(EVAR && (GDAT || GBSS))
	{/* match up variables */
		/* LINK EXTERNS TO THE CHOSEN ONE */
		for(i = 0; i <= dupcnt; ++i)
		{
		  if(*(valp[i]->p) == extvarop)
		  {
		  Pop dp = (Pop)valp[i]->p;

			*((char*)dp) = 0;			/* extvarop becomes nilop */
			PL(dp->data1) = cdoffset;	/* use this new offset for access */
			PS(((short*)dp)[1]) = cdfile;	/* put fileno in unused slots */
			PS(dp->data4) = segid;
			break;
		  }
		}
	}
#undef GDAT
#undef GBSS
#undef GFUNC
#undef EVAR
#undef EFUNC

}
static void
link_globals(Piv iv)
{
	if(SymHead(iv->gbltbl))
	{
	struct _gloval *valp[1024];	/* pointers to symtable value structs */

	  /* Pass over the sorted symbol table and process duplicate entries */
	  while(SymNext(iv->gbltbl))
	  {
	  unsigned long *key;
	  long mark[2];							/* Table position saver */
	  int dupcnt = 0;
		SymKey(iv->gbltbl, &key);			/* Pointer to first key */
		SymValue(iv->gbltbl, &valp[0]);		/* Pointer to first value */

		while(SymMarkNext(iv->gbltbl, mark))
		{/* Look forward for duplicates */
		unsigned long *key1;
		  SymKey(iv->gbltbl, &key1);				/* Pointer to next key */
		  if(KEYEQ(key, key1))
		  {/* Hashed keys match, check the strings */
			SymValue(iv->gbltbl, &valp[dupcnt+1]);	/* Pointer to next value */
			if(!strcmp(valp[dupcnt]->symname, valp[dupcnt+1]->symname))
			{/* Duplicate entry found */
				++dupcnt;
				continue;
			}
		  }
		  break;
		}
		if(dupcnt > 0)
		{/* Process a collection of duplicate symbol names */
		  link_dups(iv, dupcnt, valp);
		}
		SymSetMark(iv->gbltbl, mark);

	  }/* END: while(SymNext) */
	}/* END: if(SymHead) */
}
static void
realloc_data(Piv iv)
{
int i;
Pafile pf;
unsigned char *p;
unsigned long offset = 0;

	for(i = 0; i < iv->numfiles; ++i)
	{
		pf = iv->files[i];
		p = pf->data_p;

		while(*p != endfileop)
		{
			if(		*p == datablockop 
				||	*p == mallocblockop
				||	*p == stringblockop)
			{
				PL(POP->data1) = offset;				
				offset += GL(POP->data);
				ROUNDUP(offset, 4);
			}
			p =  POP->next;
		}
	}
	iv->thunk_offset = offset;

	for(i = 0; i < iv->numfiles; ++i)
	{
		pf = iv->files[i];
		p = pf->data_p;

		while(*p != endfileop)
		{
			if(*p == thunkblockop) {
				PL(POP->data1) = offset;
				offset += GL(POP->data);
				ROUNDUP(offset,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -