File: orca.cpp
Size: 12605
Date: Tue, 08 May 2012 23:13:40 +0200
Type: cpp
#include "pbvm.h"
#include <eh.h>

/*
These are the implementations of the n_pb_orca class methods
*/

typedef struct pborca_comperr
{
    INT     iLevel;                         /* Error level */
    wchar_t *   lpszMessageNumber;              /* Pointer to message number */
    wchar_t *   lpszMessageText;                /* Pointer to message text */
    UINT    iColumnNumber;                  /* Column number */
    UINT    iLineNumber;                    /* Line number */
} PBORCA_COMPERR, FAR *PPBORCA_COMPERR;

#define PBCALLBACK(r,n) r ( CALLBACK n )
typedef PBCALLBACK(void, *PBORCA_ERRPROC) ( PPBORCA_COMPERR, LPVOID );

typedef struct{
    vm_state *vm;
    pb_class *obj;
    int refs;
    HMODULE library;
    LPVOID (WINAPI *PBORCA_SessionOpen)         ( void );
    VOID  (WINAPI *PBORCA_SessionClose)         ( LPVOID hORCASession );
    INT (WINAPI *PBORCA_SessionSetLibraryList)  ( LPVOID hORCASession, wchar_t **pLibNames, INT iNumberOfLibs );
    INT (WINAPI *PBORCA_SessionSetCurrentAppl)  ( LPVOID hORCASession, wchar_t *lpszApplLibName, wchar_t *lpszApplName );
    VOID (WINAPI *PBORCA_SessionGetError)       ( LPVOID hORCASession, wchar_t *buff, int buff_size );
    INT (WINAPI *PBORCA_ApplicationRebuild)     ( LPVOID hORCASession, int eRebldType, PBORCA_ERRPROC pCompErrProc, LPVOID pUserData );
    INT (WINAPI *PBORCA_CompileEntryImport)     ( LPVOID hORCASession, wchar_t *lpszLibraryName, wchar_t *lpszEntryName, int otEntryType, wchar_t *lpszComments, wchar_t *lpszEntrySyntax, LONG lEntrySyntaxBuffSize, PBORCA_ERRPROC pCompErrProc, LPVOID pUserData );
    INT (WINAPI *PBORCA_CompileEntryRegenerate) ( LPVOID hORCASession, wchar_t *lpszLibraryName, wchar_t *lpszEntryName, int otEntryType, PBORCA_ERRPROC pCompErrProc, LPVOID pUserData );
bool unicode;
}orca_state;

typedef void (*_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );

void SeTrans(unsigned int x, struct _EXCEPTION_POINTERS *p){
    throw p->ExceptionRecord->ExceptionCode;
}

wchar_t* convert_w2a(wchar_t*p){
    size_t bytes=wcstombs(NULL,p,0);
    char *ret=new char[bytes+1];
    wcstombs(ret,p,bytes+1);
    return (wchar_t*)ret;
}

void __stdcall ErrorProc(PPBORCA_COMPERR error, LPVOID *parm){
    orca_state *state=(orca_state *)parm;
    value val;

    if (!state->unicode){
        size_t chars=mbstowcs(NULL,(char*)error->lpszMessageText,0) +1;
        wchar_t*dest = (wchar_t*)pbstg_alc(state->vm, chars *2, GET_HEAP(state->vm));
        mbstowcs(dest,(char*)error->lpszMessageText,chars);
        val.value=(DWORD)dest;
    }else{
        int buff_size=wcslen(error->lpszMessageText)+1;
        wchar_t*dest = (wchar_t*)pbstg_alc(state->vm, buff_size *2, GET_HEAP(state->vm));
        wcscpy(dest,error->lpszMessageText);
        val.value=(DWORD)dest;
    }
    val.type=pbvalue_string;
    val.flags=0x0d00;

    rtRoutineExec(state->vm, 0, state->obj, 0, 0, &val, 1, 21, 1, 0);
    /*TODO
    invoke method? (error->lpszMessageText)
    */
}

void check_orca_error(vm_state *vm, orca_state *state, LPVOID session, int ret){
    wchar_t buff[256];
    state->PBORCA_SessionGetError(session, buff, 256);
    if (!state->unicode){
        wchar_t buff2[256];
        mbstowcs(buff2,(char*)buff,256);
        Throw_Exception(vm,buff2);
    }else{
        Throw_Exception(vm,buff);
    }
}


DWORD __declspec(dllexport) __stdcall Orca_Destroy (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *obj;

    ot_get_curr_obinst_expr(vm, &obj, &isvalid);
    ob_get_field(vm, obj, 1, &field);
    if (field.value){
        orca_state *state=(orca_state*)field.value;
        state->refs --;
        if (state->refs==0){
            if (state->library)
                FreeLibrary(state->library);
            delete state;
        }
    }
    ot_no_return_val(vm);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Init (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid, isnull;
    orca_state *state;
    pb_class *obj;

    last_vm = vm;

    ot_get_curr_obinst_expr(vm, &obj, &isvalid);
    ob_get_field(vm, obj, 1, &field);
    if (field.value){
        Throw_Exception(vm, L"Orca object already initialised");
        return 1;
    }
    state=new orca_state;
    state->refs=1;
    field.value=(DWORD)state;
    ob_set_field(vm,obj,1,&field);

    wchar_t *dll=(wchar_t *)ot_get_valptr_arg(vm, &isnull);
    if (isnull){
        Throw_Exception(vm, L"Dll name expected");
        return 1;
    }
    state->unicode=(bool)ot_get_simple_intarg(vm, &isnull);
    
    state->library=LoadLibrary(dll);
    if (!state->library){
        Throw_Exception(vm, L"Unable to load orca dll \"%s\"",dll);
        return 1;
    }

    state->PBORCA_SessionOpen               =(LPVOID(WINAPI *)(void))GetProcAddress(state->library,"PBORCA_SessionOpen");
    state->PBORCA_SessionClose              =(void (WINAPI *)(LPVOID))GetProcAddress(state->library,"PBORCA_SessionClose");
    state->PBORCA_SessionSetLibraryList     =(INT (WINAPI *) (LPVOID, wchar_t **, INT))GetProcAddress(state->library,"PBORCA_SessionSetLibraryList");
    state->PBORCA_SessionSetCurrentAppl     =(INT (WINAPI *) (LPVOID, wchar_t *, wchar_t *))GetProcAddress(state->library,"PBORCA_SessionSetCurrentAppl");
    state->PBORCA_SessionGetError           =(void (WINAPI *) (LPVOID, wchar_t *, int))GetProcAddress(state->library,"PBORCA_SessionGetError");
    state->PBORCA_ApplicationRebuild        =(INT (WINAPI *) (LPVOID, int, PBORCA_ERRPROC, LPVOID))GetProcAddress(state->library,"PBORCA_ApplicationRebuild");
    state->PBORCA_CompileEntryImport        =(INT (WINAPI *) (LPVOID, wchar_t *, wchar_t *, int, wchar_t *, wchar_t *, LONG, PBORCA_ERRPROC, LPVOID))GetProcAddress(state->library,"PBORCA_CompileEntryImport");
    state->PBORCA_CompileEntryRegenerate    =(INT (WINAPI *) (LPVOID, wchar_t *, wchar_t *, int, PBORCA_ERRPROC, LPVOID))GetProcAddress(state->library,"PBORCA_CompileEntryRegenerate");
    
    ot_no_return_val(vm);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Session_Open (vm_state *vm, DWORD arg_count){
    value field, ret;
    DWORD isvalid;
    orca_state *state;
    pb_class *obj, *session;
    
    _se_translator_function old=_set_se_translator(SeTrans);

    try{

        ot_get_curr_obinst_expr(vm, &obj, &isvalid);
        ob_get_field(vm, obj, 1, &field);
        state=(orca_state*)field.value;
        
        lvalue_ref *session_arg = ot_get_next_lvalue_arg(vm, &isvalid);
        ot_create_obinst_at_lval(vm, session_arg, 0, 0);
        session = (pb_class *)get_lvalue(vm, session_arg)->value;
        
        state->refs++;
        ob_set_field(vm, session, 1, &field);

        ob_get_field(vm, session, 2, &field);
        field.value=(DWORD)state->PBORCA_SessionOpen();
        if (!field.value){
            Throw_Exception(vm,L"Session open failed");
            return 1;
        }
        ob_set_field(vm, session, 2, &field);

        ret.value=(DWORD)session;

        ret.type=0x8000u;
        ret.flags=0xD00u;
        ot_set_return_val(vm, &ret);
    }catch(DWORD code){
        Throw_Exception(vm,L"Error %x during of_create_orca_session",code);
    }catch(...){
        Throw_Exception(vm,L"Unknown error during of_create_orca_session");
    }
    _set_se_translator(old);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Session_Close (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;
    
    ot_get_curr_obinst_expr(vm, &session, &isvalid);
    ob_get_field(vm, session, 1, &field);
    orca_state *state=(orca_state*)field.value;
    state->refs --;
    ob_get_field(vm, session, 2, &field);
    state->PBORCA_SessionClose((LPVOID)field.value);

    if (state->refs==0){
        if (state->library)
            FreeLibrary(state->library);
        delete state;
    }

    ot_no_return_val(vm);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Set_Target (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;

    _se_translator_function old=_set_se_translator(SeTrans);

    try{

        ot_get_curr_obinst_expr(vm, &session, &isvalid);
        ob_get_field(vm, session, 1, &field);
        orca_state *state=(orca_state*)field.value;

        ob_get_field(vm, session, 2, &field);
        
        value *v_value = ot_get_next_evaled_arg_no_convert(vm);
        pb_array *libs=(pb_array *)v_value->value;
        
        int count = ot_array_num_items(vm, libs);
        wchar_t **lib_list = new wchar_t*[count];

        for (long i=0;i<count;i++){
            value *v=ot_array_index(vm, libs, i);
            if (!state->unicode){
                lib_list[i]=convert_w2a((wchar_t*)v->value);
            }else{
                lib_list[i]=(wchar_t*)v->value;
            }
        }

        int ret=state->PBORCA_SessionSetLibraryList((LPVOID)field.value,lib_list,count);
        if (!state->unicode){
            for (long i=0;i<count;i++){
                delete lib_list[i];
            }
        }
        delete lib_list;
        if (ret!=0){
            check_orca_error(vm, state, (LPVOID)field.value, ret);
            return 1;
        }

        wchar_t *appl_lib=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        wchar_t *appl=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        
        if (!state->unicode){
            appl_lib=convert_w2a(appl_lib);
            appl=convert_w2a(appl);
        }

        ret = state->PBORCA_SessionSetCurrentAppl((LPVOID)field.value,appl_lib,appl);
        if (!state->unicode){
            delete appl_lib;
            delete appl;
        }
        if (ret!=0){
            check_orca_error(vm, state, (LPVOID)field.value, ret);
            return 1;
        }

        ot_no_return_val(vm);
    }catch(DWORD code){
        Throw_Exception(vm,L"Error %x during of_set_target",code);
    }catch(...){
        Throw_Exception(vm,L"Unknown error during of_set_target");
    }
    _set_se_translator(old);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Import (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;

    _se_translator_function old=_set_se_translator(SeTrans);

    try{

        ot_get_curr_obinst_expr(vm, &session, &isvalid);
        ob_get_field(vm, session, 1, &field);
        orca_state *state=(orca_state*)field.value;

        ob_get_field(vm, session, 2, &field);
        
        wchar_t *lib=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        wchar_t *entry=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        short ent_type = ot_get_simple_intarg(vm, &isvalid);
        wchar_t *comment=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        wchar_t *syntax=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
        if (!state->unicode){
            lib=convert_w2a(lib);
            entry=convert_w2a(entry);
            comment=convert_w2a(comment);
            syntax=convert_w2a(syntax);
        }
        int syntax_len=wcslen(syntax)*2;
        
        state->vm=vm;
        state->obj=session;
        int ret = state->PBORCA_CompileEntryImport((LPVOID)field.value,lib,entry,ent_type,comment,syntax,syntax_len,(PBORCA_ERRPROC)ErrorProc,(LPVOID)state);
        if (!state->unicode){
            delete lib;
            delete entry;
            delete comment;
            delete syntax;
        }
        if (ret!=0){
            check_orca_error(vm, state, (LPVOID)field.value, ret);
            return 1;
        }

        ot_no_return_val(vm);
    }catch(DWORD code){
        Throw_Exception(vm,L"Error %x during of_import",code);
    }catch(...){
        Throw_Exception(vm,L"Unknown error during of_import");
    }
    _set_se_translator(old);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Regenerate (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;

    ot_get_curr_obinst_expr(vm, &session, &isvalid);
    ob_get_field(vm, session, 1, &field);
    orca_state *state=(orca_state*)field.value;

    ob_get_field(vm, session, 2, &field);
    
    wchar_t *lib=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
    wchar_t *entry=(wchar_t *)ot_get_valptr_arg(vm, &isvalid);
    short ent_type = ot_get_simple_intarg(vm, &isvalid);
    
    if (!state->unicode){
        lib=convert_w2a(lib);
        entry=convert_w2a(entry);
    }

    state->vm=vm;
    state->obj=session;
    int ret = state->PBORCA_CompileEntryRegenerate((LPVOID)field.value,lib,entry,ent_type,(PBORCA_ERRPROC)ErrorProc,(LPVOID)state);
    if (!state->unicode){
        delete lib;
        delete entry;
    }
    if (ret!=0){
        check_orca_error(vm, state, (LPVOID)field.value, ret);
        return 1;
    }

    ot_no_return_val(vm);
    return 1;
}

DWORD __declspec(dllexport) __stdcall Orca_Rebuild (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;

    ot_get_curr_obinst_expr(vm, &session, &isvalid);
    ob_get_field(vm, session, 1, &field);
    orca_state *state=(orca_state*)field.value;

    ob_get_field(vm, session, 2, &field);

    short rebuild_type = ot_get_simple_intarg(vm, &isvalid);

    state->vm=vm;
    state->obj=session;
    int ret = state->PBORCA_ApplicationRebuild((LPVOID)field.value, rebuild_type, (PBORCA_ERRPROC)ErrorProc, (LPVOID)state);
    if (ret!=0){
        check_orca_error(vm, state, (LPVOID)field.value, ret);
        return 1;
    }

    ot_no_return_val(vm);
    return 1;
}
/*
DWORD __declspec(dllexport) __stdcall Orca_Create_Exe (vm_state *vm, DWORD arg_count){
    value field;
    DWORD isvalid;
    pb_class *session;

    ot_get_curr_obinst_expr(vm, &session, &isvalid);
    ob_get_field(vm, session, 1, &field);
    orca_state *state=(orca_state*)field.value;

    ob_get_field(vm, session, 2, &field);
    

    int ret = state->PBORCA_SetExeInfo((LPVOID)field.value,);
    if (ret!=0){
        check_orca_error(vm, state, (LPVOID)field.value, ret);
        return 1;
    }
    int ret = state->PBORCA_ExecutableCreate((LPVOID)field.value,);
    if (ret!=0){
        check_orca_error(vm, state, (LPVOID)field.value, ret);
        return 1;
    }

    ot_no_return_val(vm);
    return 1;
}*/