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

📄 bterp.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 
	bterp.c -- v1.430 interpreter prototype for oxcc byte codes

	Copyright (c) 1995
	Norman D. Culver dba
	Oxbow Software
	1323 S.E. 17th Street #662
	Ft. Lauderdale, FL 33316
	(954) 463-4754
	ndc@icanect.net
	All rights reserved.

 * Redistribution and use in source and binary forms are permitted
 * provided that: (1) source distributions retain this entire copyright
 * notice and comment, and (2) distributions including binaries display
 * the following acknowledgement:  ``This product includes software
 * developed by Norman D. Culver dba Oxbow Software''
 * in the documentation or other materials provided with the distribution
 * and in all advertising materials mentioning features or use of this
 * software.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*/

#define SUPPORT_LONG_LONG 1
#define SUPPORT_LONG_DOUBLE 1

#define NEED_BYTECODES 1
#define NEED_AOUT_FORMAT 1
#include "oxbytes.h"

#define NEED_FUNCTHUNK 1
#include "oxanf.h"
#include <stdlib.h>
#include <setjmp.h>
#include <stdio.h>

#define PROG bterp
#define USING_FRAMEWORK 1

#define SWITCHMOD 1009
typedef struct _key
{
	unsigned long k[2];
	unsigned long hv;
} KEY, *KEYP;

typedef struct _nodeS
{
	unsigned long value;
	unsigned long key[2];
	struct _nodeS *fptr;
} NodeS, *NodePS;

typedef struct _callblk {
	void *loc;
	char *es;
	unsigned short argofs;
	unsigned short flags;
	long argsiz;
	char *base_stack;			/* must be last element */
} *PCB;

typedef struct _stakblk {
	void *backlink;
	long first_loc;
	long last_loc;
	char *cbes;
	void *thunkaddr;
	int stksize;
} SB, *PSB;

typedef struct _fe {
	char *filename;
	long string_size;
	char *strings;
	char *text_start_address;
	char *data_start_address;
	char *bss_start_address;
} *FE;

typedef struct _iv {
	struct _iv *piv;
	char *text_base;
	char *dd;
	void **struclist;
	long slcnt;
	long strretcnt;
	void *allocalist;
	NodePS *swtable;
	char *chunkbase;
	void *chunklist;
	long chunksize;
	FE entry;
	char *filename;
	char *funcptr;
	Pft ft;
	long funcaddr;
	long stksiz;
	long argsiz;
	long maxes;
	char *base_stack;
	char *e_stack;
	jmp_buf jb;
#define MAX_RUNARGS 15
	long run_argcnt;
	char *run_args[MAX_RUNARGS];
	int debug;
} *Piv;

typedef struct _retval {
	void *ptr;
	long p1;
	long p2;
} RV;

int cfeprintf(const char *fmt, ...);

void _ExternCall();
void _ExternCallS();
void *oxlink_load_bare_symb(const char *symb, int dynlink);
void *oxlink_find_bare_func(const char *);
void *oxlink_find_func(const char *);
int oxlink_load_file(const char *);
int oxlink_load_object(const char *);
int oxlink_unload_file(const char *, int);
void oxlink_demand_load(void);
void oxlink_demand_noload(void);
void *oxlink_get_entry_struct(const char *filename);
char *oxlink_errstr(void);

static void* bterp_eval();

#define SZ (20)	/* size of evaluation stack frame */

#define MIN(a,b) ((a<b)?a:b)

#define SRC(a) (a<<4)
#define G1(a) ((unsigned long)*((unsigned char*)(a)))
#define G2(a) ((unsigned long)*((unsigned short*)(a)))
#define G3(a) (*((unsigned long*)(a))&0x00ffffff)
#define G4(a) (*((unsigned long*)(a)))
#define G8(a) (*((double*)(a)))
#define GX(a) (*((long double*)(a)))
#define GP1(a) ((long)*((char*)(a)))
#define GP2(a) ((long)*((short*)(a)))
#define GP3(a) ((*((long*)(a))<<8)>>8)
#define GP4(a) (*((long*)(a)))

#define NEG_ES(t) {*((t*)es)=-(*((t*)es));break;}
#define NOT_ES(t) {*((t*)es)=!(*((t*)es));break;}
#define NOT_ES1 {*es=(((long*)es)[0]==0&&((long*)es)[1]==0)?1:0;}
#define COMP_ES(t) {*((t*)es)=~(*((t*)es));break;}
#define TRUTH_ES(t) {*((long*)es)=(*((t*)es))?1:0;break;}
#define TRUTH_ES1 {*((long*)es)=(((long*)es)[0]==0&&((long*)es)[1]==0)?0:1;}
#define GT_ES(t) {*((long*)oes)=(*((t*)oes)>*((t*)es))?1:0;es=oes;break;}
#define LT_ES(t) {*((long*)oes)=(*((t*)oes)<*((t*)es))?1:0;es=oes;break;}
#define GE_ES(t) {*((long*)oes)=(*((t*)oes)>=*((t*)es))?1:0;es=oes;break;}
#define LE_ES(t) {*((long*)oes)=(*((t*)oes)<=*((t*)es))?1:0;es=oes;break;}
#define NE_ES(t) {*((long*)oes)=(*((t*)oes)!=*((t*)es))?1:0;es=oes;break;}
#define EQ_ES(t) {*((long*)oes)=(*((t*)oes)==*((t*)es))?1:0;es=oes;break;}
#define ADD_ES(t) {*((t*)oes)+=*((t*)es);es=oes;break;}
#define SUB_ES(t) {*((t*)oes)-=*((t*)es);es=oes;break;}
#define MUL_ES(t) {*((t*)oes)*=*((t*)es);es=oes;break;}
#define DIV_ES(t) {*((t*)oes)/=*((t*)es);es=oes;break;}
#define OR_ES(t)  {*((t*)oes)|=*((t*)es);es=oes;break;}
#define AND_ES(t) {*((t*)oes)&=*((t*)es);es=oes;break;}
#define XOR_ES(t) {*((t*)oes)^=*((t*)es);es=oes;break;}
#define MOD_ES(t) {*((t*)oes)%=*((unsigned long*)es);es=oes;break;}
#define MODL_ES(t) {*((t*)oes)%=*((unsigned long long*)es);es=oes;break;}
#define MODI_ES(t) {*((t*)es)%=*((unsigned short*)np);pc+=2;break;}
#define RSH_ES(t) {*((t*)oes)>>=*((unsigned char*)es);es=oes;break;}
#define LSH_ES(t) {*((t*)oes)<<=*((unsigned char*)es);es=oes;break;}
#define RSHI_ES(t) {*((t*)es)>>=*np;pc+=1;break;}
#define LSHI_ES(t) {*((t*)es)<<=*np;pc+=1;break;}
#define DEREF_ES(t) {*((long*)es)=**((t**)es);break;}
#define UDEREF_ES(t) {*((unsigned long*)es)=**((t**)es);break;}
#define FDEREF_ES(t) {*((t*)es)=**((t**)es);break;}
#define DEREF1_ES(t) {*((long*)nes)=**((t**)es);es=nes;break;}
#define UDEREF1_ES(t) {*((unsigned long*)nes)=**((t**)es);es=nes;break;}
#define FDEREF1_ES(t) {*((t*)nes)=**((t**)es);es=nes;break;}
#define SIGNE if(*(es+3)&0x80)*((long*)(es+4))=-1;else *((long*)(es+4))=0
#define USIGNE *((long*)(es+4))=0
#define LOADI1() {*((long*)nes)=GP1(np);es=nes;SIGNE;pc+=1;break;}
#define LOADI2() {*((long*)nes)=GP2(np);es=nes;SIGNE;pc+=2;break;}
#define LOADI4() {*((long*)nes)=GP4(np);es=nes;SIGNE;pc+=4;break;}
#define LOADUI1() {*((unsigned long*)nes)=G1(np);es=nes;USIGNE;pc+=1;break;}
#define LOADUI2() {*((unsigned long*)nes)=G2(np);es=nes;USIGNE;pc+=2;break;}
#define LOADUI4() {*((unsigned long*)nes)=G4(np);es=nes;USIGNE;pc+=4;break;}
#define LOADI8() {*((double*)nes)=G8(np);es=nes;pc+=8;break;}
#define LOADIX() {*((long double*)nes)=GX(np);es=nes;pc+=XSZ;break;}

#define LOADADDRI1() {*((unsigned long*)nes)=(G1(np)<<2);es=nes;pc+=1;break;}
#define LOADADDRI2() {*((unsigned long*)nes)=(G2(np)<<2);es=nes;pc+=2;break;}
#define LOADADDRI3() {*((unsigned long*)nes)=(G3(np));es=nes;pc+=3;break;}
#define LOADADDRI4() {*((unsigned long*)nes)=G4(np);es=nes;pc+=4;break;}

#define LOADSTK1(t) {*((t*)nes)=*((t*)(fs+(G1(np)<<2)));es=nes;pc+=1;break;}
#define LOADSTK2(t) {*((t*)nes)=*((t*)(fs+(G2(np)<<2)));es=nes;pc+=2;break;}
#define LOADSTK3(t) {*((t*)nes)=*((t*)(fs+(G3(np))));es=nes;pc+=3;break;}

#define STORSTK1(t) {*((t*)(fs+(G1(np)<<2)))=*((t*)es);es=oes;pc+=1;break;}
#define STORSTK2(t) {*((t*)(fs+(G2(np)<<2)))=*((t*)es);es=oes;pc+=2;break;}
#define STORSTK3(t) {*((t*)(fs+(G3(np)<<0)))=*((t*)es);es=oes;pc+=3;break;}

#define STORSTKI1(t) {*((t*)(fs+(G1(np)<<2)))=*((t*)(np+1));pc+=sizeof(t)+1;break;}
#define STORSTKI2(t) {*((t*)(fs+(G2(np)<<2)))=*((t*)(np+2));pc+=sizeof(t)+2;break;}
#define STORSTKI3(t) {*((t*)(fs+(G3(np)<<0)))=*((t*)(np+3));pc+=sizeof(t)+3;break;}

#define LOADMEM1(t) {*((t*)nes)=*((t*)(dd+(G1(np)<<2)));es=nes;pc+=1;break;}
#define LOADMEM2(t) {*((t*)nes)=*((t*)(dd+(G2(np)<<2)));es=nes;pc+=2;break;}
#define LOADMEM3(t) {*((t*)nes)=*((t*)(dd+(G3(np))));es=nes;pc+=3;break;}
#define LOADMEM4(t) {*((t*)nes)=*((t*)((void*)G4(np)));es=nes;pc+=4;break;}

#define STORMEM1(t) {*((t*)(dd+(G1(np)<<2)))=*((t*)es);es=oes;pc+=1;break;}
#define STORMEM2(t) {*((t*)(dd+(G2(np)<<2)))=*((t*)es);es=oes;pc+=2;break;}
#define STORMEM3(t) {*((t*)(dd+(G3(np)<<2)))=*((t*)es);es=oes;pc+=3;break;}
#define STORMEM4(t) {*((t*)((void*)G4(np)))=*((t*)es);es=oes;pc+=4;break;}

#define STORMEMI1(t) {*((t*)(dd+(G1(np)<<2)))=*((t*)(np+1));pc+=sizeof(t)+1;break;}
#define STORMEMI2(t) {*((t*)(dd+(G2(np)<<2)))=*((t*)(np+2));pc+=sizeof(t)+2;break;}
#define STORMEMI3(t) {*((t*)(dd+(G3(np)<<0)))=*((t*)(np+3));pc+=sizeof(t)+3;break;}
#define STORMEMI4(t) {*((t*)((void*)G4(np)))=*((t*)(np+4));pc+=sizeof(t)+4;break;}

static unsigned long bfields[33] = {
	0x00000000,0x00000001,0x00000003,0x00000007,
	0x0000000f,0x0000001f,0x0000003f,0x0000007f,
	0x000000ff,0x000001ff,0x000003ff,0x000007ff,
	0x00000fff,0x00001fff,0x00003fff,0x00007fff,
	0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
	0x000fffff,0x001fffff,0x003fffff,0x007fffff,
	0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff,
	0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,
	0xfffffff
	};
static unsigned long tsfields[33] = {
	0x00000000,0x00000001,0x00000002,0x00000004,
	0x00000008,0x00000010,0x00000020,0x00000040,
	0x00000080,0x00000100,0x00000200,0x00000400,
	0x00000800,0x00001000,0x00002000,0x00004000,
	0x00008000,0x00010000,0x00020000,0x00040000,
	0x00080000,0x00100000,0x00200000,0x00400000,
	0x00800000,0x01000000,0x02000000,0x04000000,
	0x08000000,0x10000000,0x20000000,0x40000000,
	0x80000000
	};
static unsigned long sfields[33] = {
	0x00000000,0xfffffffe,0xfffffffc,0xfffffff8,
	0xfffffff0,0xffffffe0,0xffffffc0,0xffffff80,
	0xffffff00,0xfffffe00,0xfffffc00,0xfffff800,
	0xfffff000,0xffffe000,0xffffc000,0xffff8000,
	0xffff0000,0xfffe0000,0xfffc0000,0xfff80000,
	0xfff00000,0xffe00000,0xffc00000,0xff800000,
	0xff000000,0xfe000000,0xfc000000,0xf8000000,
	0xf0000000,0xe0000000,0xc0000000,0x80000000,
	0x80000000
	};
#if SUPPORT_LONG_LONG
static unsigned long long lbfields[65] = {
	0x0000000000000000LL,0x0000000000000001LL,0x0000000000000003LL,0x0000000000000007LL,
	0x000000000000000fLL,0x000000000000001fLL,0x000000000000003fLL,0x000000000000007fLL,
	0x00000000000000ffLL,0x00000000000001ffLL,0x00000000000003ffLL,0x00000000000007ffLL,
	0x0000000000000fffLL,0x0000000000001fffLL,0x0000000000003fffLL,0x0000000000007fffLL,
	0x000000000000ffffLL,0x000000000001ffffLL,0x000000000003ffffLL,0x000000000007ffffLL,
	0x00000000000fffffLL,0x00000000001fffffLL,0x00000000003fffffLL,0x00000000007fffffLL,
	0x0000000000ffffffLL,0x0000000001ffffffLL,0x0000000003ffffffLL,0x0000000007ffffffLL,
	0x000000000fffffffLL,0x000000001fffffffLL,0x000000003fffffffLL,0x000000007fffffffLL,
	0x00000000ffffffffLL,0x00000001ffffffffLL,0x00000003ffffffffLL,0x00000007ffffffffLL,
	0x0000000fffffffffLL,0x0000001fffffffffLL,0x0000003fffffffffLL,0x0000007fffffffffLL,
	0x000000ffffffffffLL,0x000001ffffffffffLL,0x000003ffffffffffLL,0x000007ffffffffffLL,
	0x00000fffffffffffLL,0x00001fffffffffffLL,0x00003fffffffffffLL,0x00007fffffffffffLL,
	0x0000ffffffffffffLL,0x0001ffffffffffffLL,0x0003ffffffffffffLL,0x0007ffffffffffffLL,
	0x000fffffffffffffLL,0x001fffffffffffffLL,0x003fffffffffffffLL,0x007fffffffffffffLL,
	0x00ffffffffffffffLL,0x01ffffffffffffffLL,0x03ffffffffffffffLL,0x07ffffffffffffffLL,
	0x0fffffffffffffffLL,0x1fffffffffffffffLL,0x3fffffffffffffffLL,0x7fffffffffffffffLL,
	0xfffffffffffffffLL
	};
static unsigned long long ltsfields[65] = {
	0x0000000000000000LL,0x0000000000000001LL,0x0000000000000002LL,0x0000000000000004LL,
	0x0000000000000008LL,0x0000000000000010LL,0x0000000000000020LL,0x0000000000000040LL,
	0x0000000000000080LL,0x0000000000000100LL,0x0000000000000200LL,0x0000000000000400LL,
	0x0000000000000800LL,0x0000000000001000LL,0x0000000000002000LL,0x0000000000004000LL,
	0x0000000000008000LL,0x0000000000010000LL,0x0000000000020000LL,0x0000000000040000LL,
	0x0000000000080000LL,0x0000000000100000LL,0x0000000000200000LL,0x0000000000400000LL,
	0x0000000000800000LL,0x0000000001000000LL,0x0000000002000000LL,0x0000000004000000LL,
	0x0000000008000000LL,0x0000000010000000LL,0x0000000020000000LL,0x0000000040000000LL,
	0x0000000080000000LL,0x0000000100000000LL,0x0000000200000000LL,0x0000000400000000LL,
	0x0000000800000000LL,0x0000001000000000LL,0x0000002000000000LL,0x0000004000000000LL,
	0x0000008000000000LL,0x0000010000000000LL,0x0000020000000000LL,0x0000040000000000LL,
	0x0000080000000000LL,0x0000100000000000LL,0x0000200000000000LL,0x0000400000000000LL,
	0x0000800000000000LL,0x0001000000000000LL,0x0002000000000000LL,0x0004000000000000LL,
	0x0008000000000000LL,0x0010000000000000LL,0x0020000000000000LL,0x0040000000000000LL,
	0x0080000000000000LL,0x0100000000000000LL,0x0200000000000000LL,0x0400000000000000LL,
	0x0800000000000000LL,0x1000000000000000LL,0x2000000000000000LL,0x4000000000000000LL,
	0x8000000000000000LL
	};
static unsigned long long lsfields[65] = {
	0x0000000000000000LL,0xfffffffffffffffeLL,0xfffffffffffffffcLL,0xfffffffffffffff8LL,
	0xfffffffffffffff0LL,0xffffffffffffffe0LL,0xffffffffffffffc0LL,0xffffffffffffff80LL,
	0xffffffffffffff00LL,0xfffffffffffffe00LL,0xfffffffffffffc00LL,0xfffffffffffff800LL,
	0xfffffffffffff000LL,0xffffffffffffe000LL,0xffffffffffffc000LL,0xffffffffffff8000LL,
	0xffffffffffff0000LL,0xfffffffffffe0000LL,0xfffffffffffc0000LL,0xfffffffffff80000LL,
	0xfffffffffff00000LL,0xffffffffffe00000LL,0xffffffffffc00000LL,0xffffffffff800000LL,
	0xffffffffff000000LL,0xfffffffffe000000LL,0xfffffffffc000000LL,0xfffffffff8000000LL,
	0xfffffffff0000000LL,0xffffffffe0000000LL,0xffffffffc0000000LL,0xffffffff80000000LL,
	0xffffffff00000000LL,0xfffffffe00000000LL,0xfffffffc00000000LL,0xfffffff800000000LL,
	0xfffffff000000000LL,0xffffffe000000000LL,0xffffffc000000000LL,0xffffff8000000000LL,  
	0xffffff0000000000LL,0xfffffe0000000000LL,0xfffffc0000000000LL,0xfffff80000000000LL,
	0xfffff00000000000LL,0xffffe00000000000LL,0xffffc00000000000LL,0xffff800000000000LL,
	0xffff000000000000LL,0xfffe000000000000LL,0xfffc000000000000LL,0xfff8000000000000LL,
	0xfff0000000000000LL,0xffe0000000000000LL,0xffc0000000000000LL,0xff80000000000000LL,
	0xff00000000000000LL,0xfe00000000000000LL,0xfc00000000000000LL,0xf800000000000000LL,
	0xf000000000000000LL,0xe000000000000000LL,0xc000000000000000LL,0x8000000000000000LL,
	0x8000000000000000LL
	};
#endif /* SUPPORT_LONG_LONG */

static char thunk386[41] =
{/* THE EXTERNAL CALLBACK THUNK (Intel 386) */
	0x55,				/* pushl %ebp */
	0x89,0xE5,			/* movl %esp,%ebp */
	0x68,0,0,0,0,		/* pushl ft */
	0x68,0,0,0,0,		/* pushl iv */
	0x68,0,0,0,0,		/* pushl base_stack */
	0x83,0xEC,0x0C,		/* subl $12,%esp (RETVAL) */
	0xB8,0,0,0,0,		/* movl _bterp_handle_callbacks,%eax */
	0xFF,0xD0,			/* call *%eax */
	0x8B,0x04,0x24,		/* movl (%esp),%eax	 */
	0x8B,0x54,0x24,0x04,/* movl 4(%esp),%edx */
	0x8B,0x4C,0x24,0x08,/* movl 8(%esp),%ecx */
	0xC9,				/* leave */
	0xC3				/* ret */
};
static char thunk386S[42] =
{/* THE EXTERNAL CALLBACK THUNK (Intel 386) */
	0x55,				/* pushl %ebp */
	0x89,0xE5,			/* movl %esp,%ebp */
	0x68,0,0,0,0,		/* pushl ft */
	0x68,0,0,0,0,		/* pushl iv */
	0x68,0,0,0,0,		/* pushl base_stack */
	0x83,0xEC,0x0C,		/* subl $12,%esp (RETVAL) */
	0xB8,0,0,0,0,		/* movl _bterp_handle_callbacks,%eax */
	0xFF,0xD0,			/* call *%eax */
	0x8B,0x04,0x24,		/* movl (%esp),%eax	 */
	0x8B,0x54,0x24,0x04,/* movl 4(%esp),%edx */
	0x8B,0x4C,0x24,0x08,/* movl 8(%esp),%ecx */
	0xC9,				/* leave */
	0xC2,0x04			/* ret $4 (prune structret arg, GCC convention) */
};



/* ========================== INTERPRETER CODE =========================== */

static int
findswitch(Piv iv, unsigned long *key, void *result)
{
int bin;
NodePS node;
	bin = (((~key[0] ^ key[1]) * 1103515245UL) + 12345) % SWITCHMOD;
	if((node = iv->swtable[bin]))
	{
		do {
			if(node->key[0] == key[0] && node->key[1] == key[1])
			{
				*((NodePS*)result) = node;
				return 1;
			}
		} while((node = node->fptr));
	}
	return 0;
}
static void *
new_Snode(Piv iv)
{
void *p;

	if(iv->chunksize < sizeof(NodeS))
	{
		iv->chunkbase = calloc(1, 4088);
		*((void**)iv->chunkbase) = iv->chunklist;
		iv->chunklist = iv->chunkbase;
		iv->chunkbase += sizeof(void*);
		iv->chunksize = 4088 - sizeof(void*);
	}
	p = iv->chunkbase;
	iv->chunkbase += sizeof(NodeS);
	iv->chunksize -= sizeof(NodeS);
	return p;
}
static void
saveswitch(Piv iv, unsigned long *key, long value)
{
int bin;
NodePS node;

	bin = (((~key[0] ^ key[1]) * 1103515245UL) + 12345) % SWITCHMOD;
	node = new_Snode(iv);
	node->key[0] = key[0];
	node->key[1] = key[1];
	node->value = value;
	node->fptr = iv->swtable[bin];
	iv->swtable[bin] = node;
}
static void
purge_allocas(Piv iv, void *last)
{
	while(iv->allocalist && (iv->allocalist != last))
	{
	void *this = iv->allocalist;
		iv->allocalist = *((void**)this);
		free(this);
	}
}

static void
_bterp_handle_callbacks(RV retval, char *base_stack, Piv iv, Pft ft, 
							int ebp, int pret, ...)
{/* Call to interpreted function from external function */
unsigned short fmods;
long stksiz, maxes, strucsiz, fs_size, argofs, es_beg, argsiz;
int hidden;
void *strret = 0;
void *argaddr, *e_stack, *lastalloca;
void *pes;
DATUM lastval;

	fmods = ft->fmods;
	argaddr = ((long*)&pret)+1;
	if((hidden = (fmods & Fretstr)))
	{/* return a struct or union */
		strucsiz = ft->retsiz<<2;
		strret = (void*) *(((long*)&pret)+1);
	}
	stksiz = ft->stksiz<<2;
	maxes = ft->maxes;
	argsiz = ft->argsiz<<2;

	if(fmods & Fnested)
	{/* callback to nested function */
		argofs = ft->stkbeg+(stksiz-argsiz-hidden);
		e_stack = ((PSB)base_stack)->cbes;
	}
	else
	{/* callback to non-nested function */
		if(fmods & Fellipsis)
			argsiz += 128;
		es_beg = stksiz+hidden+argsiz;
		argofs = stksiz;
		fs_size = es_beg + ((maxes+6)*SZ);

		/* Create a stack for the called function */
		base_stack = calloc(1, fs_size + sizeof(SB));
		e_stack = base_stack + sizeof(SB) + es_beg;
		((PSB)base_stack)->stksize = fs_size + sizeof(SB);
	}

	/* Copy the callers arguments */
	memcpy(base_stack+argofs+sizeof(SB),argaddr,argsiz+hidden);

	/* EVALUATE THE FUNCTION */
	lastalloca = iv->allocalist;
	pes = bterp_eval(iv, ft->funcaddr, base_stack, e_stack,
		base_stack+((PSB)base_stack)->stksize);

	/* Transfer the return value */
#if SUPPORT_LONG_DOUBLE
	lastval.Ulongdouble = *((long double*)pes);
#else
	lastval.Udouble = *((double*)pes);
#endif

	/* Return to callers' stack */
	if(fmods & Fretdbl)
	{
		asm ("fldl %0" :: "g"(lastval.Udouble));
	}
	else if(fmods & Fretflt)
	{
		asm ("flds %0" :: "g"(lastval.Ufloat));
	}
	else if(fmods & Fretldbl)
	{
#if SUPPORT_LONG_DOUBLE
		asm ("fstpt %0" :: "g"(lastval.Udouble));
#else
		asm ("fldl %0" :: "g"(lastval.Udouble));
#endif
	}
	else if(strret)
	{/* return pointer to struct */
		retval.ptr = strret;
		/* GCC needs this */
		memcpy(&retval.p1, strret, MIN(8,strucsiz));	/* 8 bytes of struct */
	}
	else
	{
		retval.ptr = lastval.Upointer;
		retval.p1 = lastval.lng.d[1];
		retval.p2 = lastval.lng.d[2];
	}
	purge_allocas(iv, lastalloca);
	if(fmods & Fnested)
	{
#if 0
		*((char**)pes) -= SZ;
#endif
		ft->fmods &= ~Fthunked;
		free(((PSB)base_stack)->thunkaddr);
	}
	else
	{
		free(base_stack);
	}
}

static void *
make_callback_thunk(Piv iv, void *base_stack, Pft ft)
{
char *pth;

	if(ft->fmods & Fretstr)
	{
		pth = malloc(sizeof(thunk386S));
		memcpy(pth, thunk386S, sizeof(thunk386S));
	}
	else
	{
		pth = malloc(sizeof(thunk386));
		memcpy(pth, thunk386, sizeof(thunk386));
	}

⌨️ 快捷键说明

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