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

📄 directcall.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* directcall.cpp
 * Direct access to native code, exported 'builtin' functions
 * UnderC C++ interpreter
 * Steve Donovan, 2001
 * This is GPL'd software, and the usual disclaimers apply.
 * See LICENCE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "common.h"
#include "opcodes.h"
#include "directcall.h"
#include "mangle.h"
#include "hard_except.h"
#include "os.h"
#include "ex_vfscanf.h"
#include "main.h"
#include <map>

#ifdef _WCON
#include "uc_graphics.h"
int exec(char *, int, bool);  // in twl.cpp
#define fprintf wcon_fprintf
#define fgets wcon_fgets
#else
#define fprintf con_fprintf
#define fgets con_fgets
#define wcon_fscanf con_fscanf
#endif

void* _copy_body(char* buff); // debug

// from lexer.cpp!
void uc_hash_cmd(char *s); 
void uc_macro_subst(const char *str, char *buff, int sz);

// *add 1.2.4 uc_exec(), uc_result() from main.cpp
int _uc_exec(char* s, void* cntxt, char* filename, int line);
void _uc_result(int ret, char *output, int sz, char* filename, int* line);

int _uc_exec_1(char* s) { return _uc_exec(s,0,0,0); }

void __mangle(); //*DEBUG*

// from tokens.cpp; exported as uc_include_path()
int _uc_include_path(const char *fname, char* buff, int sz);

extern void* gObjectReturnPtr;

typedef int (* CALL_FUN)(int, int);
#define STDCALL __stdcall
typedef int (*CALLFN) (void);

#ifndef __GNUC__

void callfn(CALLFN fn, int args[], int argc, void *optr, int flags, void *buff)
{
   int sz = sizeof(int)*argc;
  __asm {
    mov ecx, argc
    mov ebx, args
    // push the arguments onto the stack, backwards
a_loop:
    cmp ecx,0
    jz a_out
    mov eax, [ebx + 4*ecx]
    push eax
    dec ecx
    jmp a_loop

a_out:
    mov ecx,optr // thiscall calling convention (MS only)
    call fn
    // Cleanup stack ptr if this was a cdecl call
    mov ecx, flags
    test ecx,DC_CDECL
    jz  a_over
    add  esp,sz
a_over:
    test ecx,DC_RET_OBJ
    jz a_again
// these cases are peculiar to GCC
    cmp ecx,DC_RET_VAL
    jl  a_skip
    mov ebx, gObjectReturnPtr
    mov [ebx],eax
    mov [ebx+4],edx
    jmp a_finish
a_skip:
	sub  esp,4
a_again:
    mov ebx,buff
    test ecx,DC_QWORD
    jnz  a_dbl
    mov  dword ptr[ebx],eax
    jmp a_finish
a_dbl:
    fstp qword ptr[ebx]
a_finish:
  } 
}


// 'bare' inline functions w/ no usual prolog/epilog!
#define PROC(name) __declspec(naked) void name() { __asm {
#define ENDP }}

static ArgBlock *pArgs;  // only used for type info below!

// *fix 1.2.6 don't use edi! ecx is always safe.
PROC(copy_array)
// edi contains ptr to ArgBlock, eax contains no of args  
  pop [ecx]pArgs.ret_addr   // return addr!
  mov [ecx]pArgs.esi_ptr, esi
  mov [ecx]pArgs.no, eax
  lea esi,[ecx]pArgs.values
 l1:
  pop edx
  dec eax
  mov [esi + 4*eax],edx
  cmp eax,0
  jnz l1
  mov esi,[ecx]pArgs.esi_ptr
  push [ecx]pArgs.ret_addr
  ret
ENDP

#else 

//  *fix 0.9.9c  Two issues here: GCC does not emit locals,
// and 'const int' vars are optimized away.
// *fix 1.0.0L ELF does not use underscores in front of symbols 
// used in inline asm.
#ifndef _WIN32
#define DC_CDECL_ _DC_CDECL_
#define DC_QWORD_ _DC_QWORD_
#define DC_RET_OBJ_ _DC_RET_OBJ_
#define DC_RET_VAL_ _DC_RET_VAL_
#endif
static int DC_CDECL_ = DC_CDECL, DC_QWORD_ = DC_QWORD, DC_RET_OBJ_ = DC_RET_OBJ, DC_RET_VAL_ = DC_RET_VAL;

void callfn(CALLFN fn, int args[], int argc, void *optr, int flags, void *buff)
{
  // *fix 1.2.0  The RET_OBJ correction was wrong; it shd be subl $4,esp!
  // *fix 1.2.4  Using static variables leads to disasters. Here's the offsets
  // of the parameters:
  //  fn 8
  //  args 12
  //  argc 16
  //  optr 20
  // flags 24
  // buff 28
asm(
      "movl 12(%ebp),%ebx\t\n"
      "movl 16(%ebp),%eax\t\n"
      "imul $4,%eax\t\n"
      "movl %eax,16(%ebp)\t\n"
      "movl %eax,%ecx\t\n"
      "a_loop: cmpl $0,%ecx\t\n"
      "jz a_out\t\n"
      "movl (%ebx,%ecx),%eax\t\n" 
      "pushl %eax\t\n"
      "addl $-4,%ecx\t\n"
      "jmp a_loop\t\n"
      "a_out:  movl 20(%ebp),%ecx\t\n"
      "movl 8(%ebp),%eax\t\n"
      "call *%eax\t\n"
      "movl 24(%ebp),%ecx\t\n"
      "testl _DC_CDECL_,%ecx\t\n"
      "jz a_over\t\n"
      "addl 16(%ebp),%esp\t\n"
      "a_over:  testl _DC_RET_OBJ_,%ecx\t\n"
      "jz a_again\t\n"
      "cmpl _DC_RET_VAL_,%ecx\t\n"
      "jl a_skip\t\n"
      "movl _gObjectReturnPtr,%ebx\t\n"
      "movl (%ebx),%eax\t\n"
      "movl 4(%ebx),%edx\t\n"
      "jmp a_finish\t\n"
      "a_skip: subl $4,%esp\t\n"
      "a_again:   movl 28(%ebp),%ebx\t\n"
      "testl _DC_QWORD_,%ecx\t\n"
      "jnz a_dbl\t\n"
      "movl %eax,(%ebx)\t\n" 
      "jmp a_finish\t\n"
      "a_dbl:    fstpl (%ebx)\t\n"
      "a_finish:");
}
// *fix 1.2.9 sorted out a nasty in the above code! We were
// testing against EDX  and trying to move stuff from [ECX]

// I know this looks like portable code, but it isn't!
void copy_array(int sz, ArgBlock *xargs)
{
  int k,i;
  int *args = xargs->values;
  int *p = (int *)&xargs + 1;
  xargs->no = sz;
  // *fix 1.2.0L Copy these args backwards!
  for(k = sz-1,i=0; k >= 0; k--,i++)
    args[i] = p[k];
}

#endif

using namespace Parser;

//namespace { // private stuff
typedef std::list<Handle> HandleList;
HandleList lib_list;
Handle s_lib = NULL;

void *_get_std_stream(int i)
 {
  switch(i) {
   case 1: return stdin;
   case 2: return stdout;
   case 3: return stderr;
   case 4: return _str_in;   //See ex_vfscanf.cpp for this hack!
   case 5: return _str_out;
  }
  return stdout;
 }

void __break(int icode)
// use this builtin when debugging the system;
// *add 1.2.1 (Eric) Now takes an integer argument
{
 int i = 10; // set your breakpoint here!
}

// Sig is a hack that directly manipulates the Parser state so that when
// start_function() is called, it believes that a prototype has been found.

Sig& Sig::operator << (Type t)
{
 char *name;
 if(m_arg_name) { name = m_arg_name; m_arg_name = NULL; }
 else name = "*";
 Parser::state.add_to_arg_list(t,name,NULL);
 return *this;
}

Sig& Sig::operator << (char *arg_name)
{
 m_arg_name = arg_name;
 return *this;
}

void Sig::set_const(bool t)
{
  Parser::state.member_is_const = t;
}


void dissemble(PFBlock fb); // from dissem.cpp

int _dissem(FBlock *pfb) {
  try {
    dissemble(pfb);
   } catch(...) {
     return 0;
   }
   return 1;
}

typedef std::map<void *,int> PointerMap;
PointerMap mPtrMap;
bool gPtrCheckStart = false;

void *_new(int sz)
{
#ifdef _WIN32  
  void *ptr = (void *)new char[sz];
#else
  void *ptr = malloc(sz);
#endif  
  
if (Parser::debug.ptr_check) mPtrMap[ptr] = 1;
// cerr << "new " << sz << ' ' << ptr << endl;
return ptr;
}
// do note that "builtin" wrappers reverse their arg lists,
// so these guys are done backwards. (They will _never_ be called
// directly)
void *_new_vect(int n,int sz)
{
#ifdef _WIN32  
  void *p = (void *)new char[sz*n];
#else  
 void *p = malloc(sz*n);
#endif  
 if (Parser::debug.ptr_check) mPtrMap[p] = n;
 return p;
}

void _delete(char *ptr,int sz)
{  
  if (Parser::debug.ptr_check && Builtin::alloc_size(ptr) == 0) {
      if (! Parser::debug.suppress_link_errors && gPtrCheckStart)
	     cerr << (void *)ptr << " is not allocated by us!\n";
  } else
// *ch 1.2.9 patch
#ifdef _WIN32    
  delete ptr;
#else  
 free(ptr);
#endif 
}

// *change 1.1.0 Overallocation to make room for the VMT now done by builtins...
void* _new_ex(int sz)
{
 int *p = (int *)_new(sz+sizeof(int)); 
 *p = 0;   // to flag the VMT as NOT being created...
 return p+1;
}

void* _new_vect_ex(int n, int sz)
{
 int *p = (int *)_new_vect(n,sz+sizeof(int));
 *p = 0;
 return p+1;
}

void _delete_ex(char *ptr, int sz)
{
  if (ptr != NULL) { _delete(ptr-sizeof(int),sz); }
}

// *ch 1.2.9 patch
#ifndef _WIN32
void* operator new(size_t sz)
{
  return _new_ex(sz);
}

void operator delete(void *p)
{
 _delete_ex((char *)p,0);  
}

void* operator new[](size_t sz)
{
  return _new_ex(sz);
}

void operator delete[](void *p)
{
  _delete_ex((char *)p,0);

⌨️ 快捷键说明

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