/*
 * pydasm -- Python module wrapping libdasm
 * (c) 2005 ero / dkbza.org
 *
*/


#include <Python.h>
#include "../libdasm.h"


#define INSTRUCTION_STR_BUFFER_LENGTH   256

/*
    Instruction types borrowed from
    "libdasm.h"
*/
char *instruction_types[] = {
    "INSTRUCTION_TYPE_ASC",
    "INSTRUCTION_TYPE_DCL",
    "INSTRUCTION_TYPE_MOV",
    "INSTRUCTION_TYPE_MOVSR",
    "INSTRUCTION_TYPE_ADD",
    "INSTRUCTION_TYPE_XADD",
    "INSTRUCTION_TYPE_ADC",
    "INSTRUCTION_TYPE_SUB",
    "INSTRUCTION_TYPE_SBB",
    "INSTRUCTION_TYPE_INC",
    "INSTRUCTION_TYPE_DEC",
    "INSTRUCTION_TYPE_DIV",
    "INSTRUCTION_TYPE_IDIV",
    "INSTRUCTION_TYPE_NOT",
    "INSTRUCTION_TYPE_NEG",
    "INSTRUCTION_TYPE_STOS",
    "INSTRUCTION_TYPE_LODS",
    "INSTRUCTION_TYPE_SCAS",
    "INSTRUCTION_TYPE_MOVS",
    "INSTRUCTION_TYPE_MOVSX",
    "INSTRUCTION_TYPE_MOVZX",
    "INSTRUCTION_TYPE_CMPS",
    "INSTRUCTION_TYPE_SHX",
    "INSTRUCTION_TYPE_ROX",
    "INSTRUCTION_TYPE_MUL",
    "INSTRUCTION_TYPE_IMUL",
    "INSTRUCTION_TYPE_EIMUL",
    "INSTRUCTION_TYPE_XOR",
    "INSTRUCTION_TYPE_LEA",
    "INSTRUCTION_TYPE_XCHG",
    "INSTRUCTION_TYPE_CMP",
    "INSTRUCTION_TYPE_TEST",
    "INSTRUCTION_TYPE_PUSH",
    "INSTRUCTION_TYPE_AND",
    "INSTRUCTION_TYPE_OR",
    "INSTRUCTION_TYPE_POP",
    "INSTRUCTION_TYPE_JMP",
    "INSTRUCTION_TYPE_JMPC",
    "INSTRUCTION_TYPE_SETC",
    "INSTRUCTION_TYPE_MOVC",
    "INSTRUCTION_TYPE_LOOP",
    "INSTRUCTION_TYPE_CALL",
    "INSTRUCTION_TYPE_RET",
    "INSTRUCTION_TYPE_INT",
    "INSTRUCTION_TYPE_BT",
    "INSTRUCTION_TYPE_BTS",
    "INSTRUCTION_TYPE_BTR",
    "INSTRUCTION_TYPE_BTC",
    "INSTRUCTION_TYPE_BSF",
    "INSTRUCTION_TYPE_BSR",
    "INSTRUCTION_TYPE_BSWAP",
    "INSTRUCTION_TYPE_SGDT",
    "INSTRUCTION_TYPE_SIDT",
    "INSTRUCTION_TYPE_SLDT",
    "INSTRUCTION_TYPE_LFP",
    "INSTRUCTION_TYPE_FCMOVC",
    "INSTRUCTION_TYPE_FADD",
    "INSTRUCTION_TYPE_FADDP",
    "INSTRUCTION_TYPE_FIADD",
    "INSTRUCTION_TYPE_FSUB",
    "INSTRUCTION_TYPE_FSUBP",
    "INSTRUCTION_TYPE_FISUB",
    "INSTRUCTION_TYPE_FSUBR",
    "INSTRUCTION_TYPE_FSUBRP",
    "INSTRUCTION_TYPE_FISUBR",
    "INSTRUCTION_TYPE_FMUL",
    "INSTRUCTION_TYPE_FMULP",
    "INSTRUCTION_TYPE_FIMUL",
    "INSTRUCTION_TYPE_FDIV",
    "INSTRUCTION_TYPE_FDIVP",
    "INSTRUCTION_TYPE_FDIVR",
    "INSTRUCTION_TYPE_FDIVRP",
    "INSTRUCTION_TYPE_FIDIV",
    "INSTRUCTION_TYPE_FIDIVR",
    "INSTRUCTION_TYPE_FCOM",
    "INSTRUCTION_TYPE_FCOMP",
    "INSTRUCTION_TYPE_FCOMPP",
    "INSTRUCTION_TYPE_FCOMI",
    "INSTRUCTION_TYPE_FCOMIP",
    "INSTRUCTION_TYPE_FUCOM",
    "INSTRUCTION_TYPE_FUCOMP",
    "INSTRUCTION_TYPE_FUCOMPP",
    "INSTRUCTION_TYPE_FUCOMI",
    "INSTRUCTION_TYPE_FUCOMIP",
    "INSTRUCTION_TYPE_FST",
    "INSTRUCTION_TYPE_FSTP",
    "INSTRUCTION_TYPE_FIST",
    "INSTRUCTION_TYPE_FISTP",
    "INSTRUCTION_TYPE_FISTTP",
    "INSTRUCTION_TYPE_FLD",
    "INSTRUCTION_TYPE_FILD",
    "INSTRUCTION_TYPE_FICOM",
    "INSTRUCTION_TYPE_FICOMP",
    "INSTRUCTION_TYPE_FFREE",
    "INSTRUCTION_TYPE_FFREEP",
    "INSTRUCTION_TYPE_FXCH",
    "INSTRUCTION_TYPE_FPU",
    "INSTRUCTION_TYPE_MMX",
    "INSTRUCTION_TYPE_SSE",
    "INSTRUCTION_TYPE_OTHER",
    "INSTRUCTION_TYPE_PRIV",
    NULL };

/*
    Operand types borrowed from
    "libdasm.h"
*/
char *operand_types[] = {
	"OPERAND_TYPE_NONE",
	"OPERAND_TYPE_MEMORY",
	"OPERAND_TYPE_REGISTER",
	"OPERAND_TYPE_IMMEDIATE",
    NULL };

/*
    Registers borrowed from
    "libdasm.h"
*/
char *registers[] = {
    "REGISTER_EAX",
    "REGISTER_ECX",
    "REGISTER_EDX",
    "REGISTER_EBX",
    "REGISTER_ESP",
    "REGISTER_EBP",
    "REGISTER_ESI",
    "REGISTER_EDI",
    "REGISTER_NOP",
    NULL };


/*
    Register types borrowed from
    "libdasm.h"
*/
char *register_types[] = {
    "REGISTER_TYPE_GEN",
    "REGISTER_TYPE_SEGMENT",
    "REGISTER_TYPE_DEBUG",
    "REGISTER_TYPE_CONTROL",
    "REGISTER_TYPE_TEST",
    "REGISTER_TYPE_XMM",
    "REGISTER_TYPE_MMX",
    "REGISTER_TYPE_FPU",
    NULL };


PyObject *module;   // Main module Python object


/*
    Check whether we got a Python Object
*/
PyObject *check_object(PyObject *pObject)
{
	PyObject *pException;
	
	if(!pObject) {
		pException = PyErr_Occurred();
		if(pException)
            PyErr_Print();
        return NULL;
	}
    
    return pObject;
}


/*
    Assign an attribute "attr" named "name" to an object "obj"
*/
void assign_attribute(PyObject *obj, char *name, PyObject *attr)
{
    PyObject_SetAttrString(obj, name, attr);
    Py_DECREF(attr);
}


/*
    Get an attribute named "attr_name" from object "obj"
    The function steals the reference! note the decrement of
    the reference count.
*/
PyObject *get_attribute(PyObject *obj, char *attr_name)
{
    PyObject *pObj;
    
    pObj = PyObject_GetAttrString(obj, attr_name);
	if(!check_object(pObj)) {
        PyErr_SetString(PyExc_ValueError, "Can't get attribute from object");
        return NULL;
    }
    
    Py_DECREF(pObj);
    return pObj;
}


/*
    Get an Long attribute named "attr_name" from object "obj" and
    return it as a "long int"
*/
long int get_long_attribute(PyObject *o, char *attr_name)
{
    PyObject *pObj;
    
    pObj = get_attribute(o, attr_name);
	if(!pObj)
        return 0;
        
    return PyLong_AsLong(pObj);;
}


/*
    Create a new class and take care of decrementing references.
*/
PyObject *create_class(char *class_name)
{
    PyObject *pClass;
    PyObject *pClassDict = PyDict_New();
    PyObject *pClassName = PyString_FromString(class_name);
    
    pClass = PyClass_New(NULL, pClassDict, pClassName);
    if(!check_object(pClass))
        return NULL;
        
    Py_DECREF(pClassDict);
    Py_DECREF(pClassName);
    
    return pClass;
}


/*
    Create an "Inst" Python object from an INST structure.
*/
PyObject *create_inst_object(INST *pinst)
{
    PyObject *pPInst = create_class("Inst");
    
    if(!pPInst)
        return NULL;

    assign_attribute(pPInst, "type", PyLong_FromLong(pinst->type));
    assign_attribute(pPInst, "mnemonic", PyString_FromString(pinst->mnemonic));
    assign_attribute(pPInst, "flags1", PyLong_FromLong(pinst->flags1));
    assign_attribute(pPInst, "flags2", PyLong_FromLong(pinst->flags2));
    assign_attribute(pPInst, "flags3", PyLong_FromLong(pinst->flags3));
    assign_attribute(pPInst, "modrm", PyLong_FromLong(pinst->modrm));
    
    return pPInst;
}

/*
    Fill an INST structure from the data in an "Inst" Python object.
*/
void fill_inst_structure(PyObject *pPInst, PINST *_pinst)
{
    int mnemonic_length;
    PINST pinst;
    
    if(!pPInst || !_pinst)
        return;
        
    *_pinst = (PINST)calloc(1, sizeof(INST));
    pinst = *_pinst;
    if(!pinst) {
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory");
		return;
	}
    
    pinst->type = get_long_attribute(pPInst, "type");
    
    PyString_AsStringAndSize(
        get_attribute(pPInst, "mnemonic"),
        (void *)&pinst->mnemonic, &mnemonic_length);


    pinst->flags1 = get_long_attribute(pPInst, "flags1");
    pinst->flags2 = get_long_attribute(pPInst, "flags2");
    pinst->flags3 = get_long_attribute(pPInst, "flags3");
    pinst->modrm = get_long_attribute(pPInst, "modrm");
}


/*
    Create an "Operand" Python object from an OPERAND structure.
*/
PyObject *create_operand_object(OPERAND *op)
{
    PyObject *pOperand = create_class("Operand");
    
    if(!pOperand)
        return NULL;

    assign_attribute(pOperand, "type", PyLong_FromLong(op->type));
    assign_attribute(pOperand, "reg", PyLong_FromLong(op->reg));
    assign_attribute(pOperand, "basereg", PyLong_FromLong(op->basereg));
    assign_attribute(pOperand, "indexreg", PyLong_FromLong(op->indexreg));
    assign_attribute(pOperand, "scale", PyLong_FromLong(op->scale));
    assign_attribute(pOperand, "dispbytes", PyLong_FromLong(op->dispbytes));
    assign_attribute(pOperand, "dispoffset", PyLong_FromLong(op->dispoffset));
    assign_attribute(pOperand, "immbytes", PyLong_FromLong(op->immbytes));
    assign_attribute(pOperand, "immoffset", PyLong_FromLong(op->immoffset));
    assign_attribute(pOperand, "sectionbytes", PyLong_FromLong(op->sectionbytes));
    assign_attribute(pOperand, "section", PyLong_FromLong(op->section));
    assign_attribute(pOperand, "displacement", PyLong_FromLong(op->displacement));
    assign_attribute(pOperand, "immediate", PyLong_FromLong(op->immediate));
    assign_attribute(pOperand, "flags", PyLong_FromLong(op->flags));
    
    return pOperand;
}


/*
    Fill an OPERAND structure from the data in an "Operand" Python object.
*/
void fill_operand_structure(PyObject *pOperand, OPERAND *op)
{
    if(!pOperand || !op)
        return;
        
    op->type = get_long_attribute(pOperand, "type");
    op->reg = get_long_attribute(pOperand, "reg");
    op->basereg = get_long_attribute(pOperand, "basereg");
    op->indexreg = get_long_attribute(pOperand, "indexreg");
    op->scale = get_long_attribute(pOperand, "scale");
    op->dispbytes = get_long_attribute(pOperand, "dispbytes");
    op->dispoffset = get_long_attribute(pOperand, "dispoffset");
    op->immbytes = get_long_attribute(pOperand, "immbytes");
    op->immoffset = get_long_attribute(pOperand, "immoffset");
    op->sectionbytes = get_long_attribute(pOperand, "sectionbytes");
    op->section = get_long_attribute(pOperand, "section");
    op->displacement = get_long_attribute(pOperand, "displacement");
    op->immediate = get_long_attribute(pOperand, "immediate");
    op->flags = get_long_attribute(pOperand, "flags");
}


/*
    Create an "Instruction" Python object from an INSTRUCTION structure.
*/
PyObject *create_instruction_object(INSTRUCTION *insn)
{
    PyObject *pInstruction = create_class("Instruction");

    if(!pInstruction)
        return NULL;
    
    assign_attribute(pInstruction, "length", PyLong_FromLong(insn->length));
    assign_attribute(pInstruction, "type", PyLong_FromLong(insn->type));
    assign_attribute(pInstruction, "mode", PyLong_FromLong(insn->mode));
    assign_attribute(pInstruction, "opcode", PyLong_FromLong(insn->opcode));
    assign_attribute(pInstruction, "modrm", PyLong_FromLong(insn->modrm));
    assign_attribute(pInstruction, "sib", PyLong_FromLong(insn->sib));
    assign_attribute(pInstruction, "extindex", PyLong_FromLong(insn->extindex));
    assign_attribute(pInstruction, "fpuindex", PyLong_FromLong(insn->fpuindex));
    assign_attribute(pInstruction, "dispbytes", PyLong_FromLong(insn->dispbytes));
    assign_attribute(pInstruction, "immbytes", PyLong_FromLong(insn->immbytes));
    assign_attribute(pInstruction, "sectionbytes", PyLong_FromLong(insn->sectionbytes));
    assign_attribute(pInstruction, "op1", create_operand_object(&insn->op1));
    assign_attribute(pInstruction, "op2", create_operand_object(&insn->op2));
    assign_attribute(pInstruction, "op3", create_operand_object(&insn->op3));
    assign_attribute(pInstruction, "ptr", create_inst_object(insn->ptr));
    assign_attribute(pInstruction, "flags", PyLong_FromLong(insn->flags));
        
    return pInstruction;
}


/*
    Fill an INSTRUCTION structure from the data in an "Instruction" Python object.
*/
void fill_instruction_structure(PyObject *pInstruction, INSTRUCTION *insn)
{
    insn->length = get_long_attribute(pInstruction, "length");
    insn->type = get_long_attribute(pInstruction, "type");
    insn->mode = get_long_attribute(pInstruction, "mode");
    insn->opcode = get_long_attribute(pInstruction, "opcode");
    insn->modrm = get_long_attribute(pInstruction, "modrm");
    insn->sib = get_long_attribute(pInstruction, "sib");
    insn->extindex = get_long_attribute(pInstruction, "extindex");
    insn->fpuindex = get_long_attribute(pInstruction, "fpuindex");
    insn->dispbytes = get_long_attribute(pInstruction, "dispbytes");
    insn->immbytes = get_long_attribute(pInstruction, "immbytes");
    insn->sectionbytes = get_long_attribute(pInstruction, "sectionbytes");
    insn->flags = get_long_attribute(pInstruction, "flags");
    fill_operand_structure(get_attribute(pInstruction, "op1"), &insn->op1);
    fill_operand_structure(get_attribute(pInstruction, "op2"), &insn->op2);
    fill_operand_structure(get_attribute(pInstruction, "op3"), &insn->op3);
    fill_inst_structure(get_attribute(pInstruction, "ptr"), &insn->ptr);
}

/*
    Python counterpart of libdasm's "get_instruction"
*/
#define GET_INSTRUCTION_DOCSTRING                                               \
    "Decode an instruction from the given buffer.\n\n"                          \
    "Takes in a string containing the data to disassemble and the\nmode, "      \
    "either MODE_16 or MODE_32. Returns an Instruction object or \nNone if "    \
    "the instruction can't be disassembled."
    
PyObject *pydasm_get_instruction(PyObject *self, PyObject *args)
{
	PyObject *pBuffer, *pMode;
	INSTRUCTION insn;
	int size, data_length, mode;
    char *data;

    
	if(!args || PyObject_Length(args)!=2) {
		PyErr_SetString(PyExc_TypeError,
			"Invalid number of arguments, 2 expected: (data, mode)");
		return NULL;
	}
	
	pBuffer = PyTuple_GetItem(args, 0);
	if(!check_object(pBuffer)) {
        PyErr_SetString(PyExc_ValueError, "Can't get buffer from arguments");
    }
    
	pMode = PyTuple_GetItem(args, 1);
	if(!check_object(pMode)) {
        PyErr_SetString(PyExc_ValueError, "Can't get mode from arguments");
    }
    mode = PyLong_AsLong(pMode);

    PyString_AsStringAndSize(pBuffer, &data, &data_length);
	
	size = get_instruction(&insn, data, mode);
    
    if(!size) {    
        Py_INCREF(Py_None);
        return Py_None;
    }

    return create_instruction_object(&insn);
}


/*
    Python counterpart of libdasm's "get_instruction_string"
*/
#define GET_INSTRUCTION_STRING_DOCSTRING                                    \
    "Transform an instruction object into its string representation.\n\n"   \
    "The function takes an Instruction object; its format, either \n"       \
    "FORMAT_INTEL or FORMAT_ATT and finally an offset (refer to \n"         \
    "libdasm for meaning). Returns a string representation of the \n"       \
    "disassembled instruction."
    
PyObject *pydasm_get_instruction_string(PyObject *self, PyObject *args)
{
	PyObject *pInstruction, *pFormat, *pOffset, *pStr;
	INSTRUCTION insn;
	unsigned long int offset, format;
    char *data;

    
	if(!args || PyObject_Length(args)!=3) {
		PyErr_SetString(PyExc_TypeError,
			"Invalid number of arguments, 3 expected: (instruction, format, offset)");
		return NULL;
	}
	
	pInstruction = PyTuple_GetItem(args, 0);
	if(!check_object(pInstruction)) {
        PyErr_SetString(PyExc_ValueError, "Can't get instruction from arguments");
    }
    if(pInstruction == Py_None) {
        Py_INCREF(Py_None);
        return Py_None;
    }
    memset(&insn, 0, sizeof(INSTRUCTION));
    fill_instruction_structure(pInstruction, &insn);
    
	pFormat = PyTuple_GetItem(args, 1);
	if(!check_object(pFormat)) {
        PyErr_SetString(PyExc_ValueError, "Can't get format from arguments");
    }
    format = PyLong_AsLong(pFormat);
	
	pOffset = PyTuple_GetItem(args, 2);
	if(!check_object(pOffset)) {
        PyErr_SetString(PyExc_ValueError, "Can't get offset from arguments");
    }
    offset = PyLong_AsLong(pOffset);

    data = (char *)calloc(1, INSTRUCTION_STR_BUFFER_LENGTH);
    if(!data) {
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory");
		return NULL;
	}
    
    if(!get_instruction_string(&insn, format, offset,
        data, INSTRUCTION_STR_BUFFER_LENGTH))
    {    
        Py_INCREF(Py_None);
        return Py_None;
    }
    
    pStr = PyString_FromStringAndSize(data, strlen(data));    
    free(insn.ptr);
    free(data);
    
    return pStr;
}


/*
    Python counterpart of libdasm's "get_mnemonic_string"
*/
#define GET_MNEMONIC_STRING_DOCSTRING                                       \
    "Transform an instruction object's mnemonic into its string representation.\n\n"    \
    "The function takes an Instruction object and its format, either \n"    \
    "FORMAT_INTEL or FORMAT_ATT. Returns a string representation of the \n" \
    "mnemonic."
    
PyObject *pydasm_get_mnemonic_string(PyObject *self, PyObject *args)
{
	PyObject *pInstruction, *pFormat, *pStr;
	INSTRUCTION insn;
	unsigned long int format;
    char *data;

	if(!args || PyObject_Length(args)!=2) {
		PyErr_SetString(PyExc_TypeError,
			"Invalid number of arguments, 3 expected: (instruction, format)");
		return NULL;
	}
	
	pInstruction = PyTuple_GetItem(args, 0);
	if(!check_object(pInstruction)) {
        PyErr_SetString(PyExc_ValueError, "Can't get instruction from arguments");
    }
    fill_instruction_structure(pInstruction, &insn);
    
	pFormat = PyTuple_GetItem(args, 1);
	if(!check_object(pFormat)) {
        PyErr_SetString(PyExc_ValueError, "Can't get format from arguments");
    }
    format = PyLong_AsLong(pFormat);
	
    data = (char *)calloc(1, INSTRUCTION_STR_BUFFER_LENGTH);
    if(!data) {
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory");
		return NULL;
	}
    
    get_mnemonic_string(&insn, format, data, INSTRUCTION_STR_BUFFER_LENGTH);
      
    pStr = PyString_FromStringAndSize(data, strlen(data));
    free(data);
    
    return pStr;
}


/*
    Python counterpart of libdasm's "get_operand_string"
*/
#define GET_OPERAND_STRING_DOCSTRING                                        \
    "Transform an instruction object's operand into its string representation.\n\n"    \
    "The function takes an Instruction object; the operand index (0,1,2);\n"\
    " its format, either FORMAT_INTEL or FORMAT_ATT and finally an offset\n"\
    "(refer to libdasm for meaning). Returns a string representation of \n" \
    "the disassembled operand."
    
PyObject *pydasm_get_operand_string(PyObject *self, PyObject *args)
{
	PyObject *pInstruction, *pFormat, *pOffset, *pOpIndex, *pStr;
	INSTRUCTION insn;
	unsigned long int offset, format, op_idx;
    char *data;

    
	if(!args || PyObject_Length(args)!=4) {
		PyErr_SetString(PyExc_TypeError,
			"Invalid number of arguments, 4 expected: (instruction, operand index, format, offset)");
		return NULL;
	}
	
	pInstruction = PyTuple_GetItem(args, 0);
	if(!check_object(pInstruction)) {
        PyErr_SetString(PyExc_ValueError, "Can't get instruction from arguments");
    }
    memset(&insn, 0, sizeof(INSTRUCTION));
    fill_instruction_structure(pInstruction, &insn);
    
	pOpIndex = PyTuple_GetItem(args, 1);
	if(!check_object(pOpIndex)) {
        PyErr_SetString(PyExc_ValueError, "Can't get operand index from arguments");
    }
    op_idx = PyLong_AsLong(pOpIndex);
	
    pFormat = PyTuple_GetItem(args, 2);
	if(!check_object(pFormat)) {
        PyErr_SetString(PyExc_ValueError, "Can't get format from arguments");
    }
    format = PyLong_AsLong(pFormat);
	
	pOffset = PyTuple_GetItem(args, 3);
	if(!check_object(pOffset)) {
        PyErr_SetString(PyExc_ValueError, "Can't get offset from arguments");
    }
    offset = PyLong_AsLong(pOffset);

    data = (char *)calloc(1, INSTRUCTION_STR_BUFFER_LENGTH);
    if(!data) {
		PyErr_SetString(PyExc_MemoryError, "Can't allocate memory");
		return NULL;
	}
    
    if(!get_operand_string(&insn, &(insn.op1)+op_idx,
        format, offset, data, INSTRUCTION_STR_BUFFER_LENGTH))
    {    
        Py_INCREF(Py_None);
        return Py_None;
    }
    
    pStr = PyString_FromStringAndSize(data, strlen(data));
    free(data);
    
    return pStr;
}


/*
    Python counterpart of libdasm's "get_register_type"
*/
#define GET_REGISTER_TYPE_DOCSTRING                                         \
    "Get the type of the register used by the operand.\n\n"                 \
    "The function takes an Operand object and returns a Long representing\n"\
    "the type of the register."
    
PyObject *pydasm_get_register_type(PyObject *self, PyObject *args)
{
	PyObject *pOperand;
    OPERAND op;

	if(!args || PyObject_Length(args)!=1) {
		PyErr_SetString(PyExc_TypeError,
			"Invalid number of arguments, 1 expected: (operand)");
		return NULL;
	}
	
	pOperand = PyTuple_GetItem(args, 0);
	if(!check_object(pOperand)) {
        PyErr_SetString(PyExc_ValueError, "Can't get instruction from arguments");
    }
    memset(&op, 0, sizeof(OPERAND));
    fill_operand_structure(pOperand, &op);
        
    return PyLong_FromLong(get_register_type(&op));
}


/*
    Map all the exported methods.
*/
static PyMethodDef pydasmMethods[] = {
	{"get_instruction", pydasm_get_instruction, METH_VARARGS,
	GET_INSTRUCTION_DOCSTRING},
	{"get_instruction_string", pydasm_get_instruction_string, METH_VARARGS,
	GET_INSTRUCTION_STRING_DOCSTRING},
	{"get_mnemonic_string", pydasm_get_mnemonic_string, METH_VARARGS,
	GET_MNEMONIC_STRING_DOCSTRING},
	{"get_operand_string", pydasm_get_operand_string, METH_VARARGS,
	GET_OPERAND_STRING_DOCSTRING},
	{"get_register_type", pydasm_get_register_type, METH_VARARGS,
	GET_REGISTER_TYPE_DOCSTRING},
	{NULL, NULL, 0, NULL}
};


/*
    Init the module, set constants.
*/
PyMODINIT_FUNC initpydasm(void)
{
    int i;
    PyObject *pModule;
    
	pModule = Py_InitModule("pydasm", pydasmMethods);

    assign_attribute(pModule, "FORMAT_ATT", PyLong_FromLong(0));
    assign_attribute(pModule, "FORMAT_INTEL", PyLong_FromLong(1));

    assign_attribute(pModule, "MODE_16", PyLong_FromLong(1));
    assign_attribute(pModule, "MODE_32", PyLong_FromLong(0));
    
    for(i=0; instruction_types[i]; i++)
        assign_attribute(pModule, instruction_types[i], PyLong_FromLong(i));
    
    for(i=0; operand_types[i]; i++)
        assign_attribute(pModule, operand_types[i], PyLong_FromLong(i));

    for(i=0; registers[i]; i++)
        assign_attribute(pModule, registers[i], PyLong_FromLong(i));
        
    for(i=0; register_types[i]; i++)
        assign_attribute(pModule, register_types[i], PyLong_FromLong(i+1));

}


int main(int agrc, char *argv[])
{
	Py_SetProgramName(argv[0]);
	
	Py_Initialize();
	
	initpydasm();

	return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1