コード例 #1
0
ファイル: os.c プロジェクト: xupingmao/minipy
Object os_listdir() {
    Object list = list_new(10);
    Object path = arg_take_str_obj("listdir");
#ifdef _WIN32
    WIN32_FIND_DATA Find_file_data;
    Object _path = obj_add(path, string_new("\\*.*"));
    HANDLE h_find = FindFirstFile(GET_STR(_path), &Find_file_data);
    if (h_find == INVALID_HANDLE_VALUE) {
        tm_raise("%s is not a directory", path);
    }
    do {
        if (strcmp(Find_file_data.cFileName, "..")==0 || strcmp(Find_file_data.cFileName, ".") == 0) {
            continue;
        }
        if (Find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            // do nothing.
        }
        Object file = string_new(Find_file_data.cFileName);
        obj_append(list, file);
    } while (FindNextFile(h_find, &Find_file_data));
    FindClose(h_find);
#else
    tm_raise("listdir not implemented in posix.");
#endif
    return list;
}
コード例 #2
0
ファイル: X86_emu.c プロジェクト: zuloloxi/bolt
Da_emulate_result Da_emulate(Da* d, CONTEXT * ctx, MemoryCache *mem, bool emulate_FS_accesses, address FS)
{
#ifdef _WIN64
    return DA_NOT_EMULATED;
#endif        
    //bool SF=IS_SET(ctx->EFlags, FLAG_SF);
    //bool OF=IS_SET(ctx->EFlags, FLAG_OF);
    //bool ZF=IS_SET(ctx->EFlags, FLAG_ZF);
    bool CF=IS_SET(ctx->EFlags, FLAG_CF);
    bool b;

    if (x86_emu_debug)
    {
        // FIXME: write to log also?
        L ("%s() begin: [", __func__);
        Da_DumpString(&cur_fds, d);
        L ("]\n");
    };

    if ((emulate_FS_accesses==false && IS_SET(d->prefix_codes, PREFIX_FS)) ||
            (IS_SET(d->prefix_codes, PREFIX_SS) || IS_SET(d->prefix_codes, PREFIX_GS)))
    {
        if (x86_emu_debug)
            L ("%s() skipping (data selector prefix present) at 0x" PRI_ADR_HEX "\n", __func__, CONTEXT_get_PC(ctx));
        return DA_EMULATED_CANNOT_READ_MEMORY;
    };

    switch (d->ins_code)
    {
        case I_CDQ:
            {
                uint32_t a=CONTEXT_get_Accum (ctx)&0xFFFFFFFF;
                CONTEXT_set_xDX (ctx, (a&0x80000000) ? 0xFFFFFFFF : 0);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_PUSH:
            {
                address rt_adr;
                obj v;
                b=Da_op_get_value_of_op (&d->op[0], &rt_adr, ctx, mem, __FILE__, __LINE__, &v, d->prefix_codes, FS);
                if (b==false)
                {
                    if (x86_emu_debug)
                        L ("%s() I_PUSH: can't read memory\n", __func__);
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                };
                b=DO_PUSH (ctx, mem, obj_get_as_REG(&v));
                if (b==false)
                {
                    if (x86_emu_debug)
                        L ("%s() I_PUSH: can't write memory\n", __func__);
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_PUSHFD:
            if (DO_PUSH (ctx, mem, ctx->EFlags | FLAG_TF)==false)
            {
                if (x86_emu_debug)
                    L ("%s() I_PUSHFD: can't write memory\n", __func__);
                return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            goto add_to_PC_and_return_OK;
            break;

        case I_POP:
            {
                REG val;
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                obj v;
                obj_tetrabyte2 (val, &v);
                Da_op_set_value_of_op (&d->op[0], &v, ctx, mem, d->prefix_codes, FS);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_POPFD:
            {
                REG val;
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                ctx->EFlags=val;
                goto add_to_PC_and_return_OK;
            };
            break;
        
        case I_LEAVE:
            {
                //ESP <- EBP
                //POP EBP

                REG val;
                CONTEXT_set_SP(ctx, CONTEXT_get_BP(ctx));
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY; // FIXME: а надо еще SP назад возвращать!
                CONTEXT_set_BP(ctx, val);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_REP_STOSB:
        case I_REP_STOSW:
        case I_REP_STOSD:
            {
                BYTE *buf;
                bool DF=IS_SET(ctx->EFlags, FLAG_DF);
                if (DF)
                    return DA_NOT_EMULATED; // not supported... bug here

                SIZE_T BUF_SIZE;

                if (d->ins_code==I_REP_STOSB)
                    BUF_SIZE=CONTEXT_get_xCX (ctx);
                else if (d->ins_code==I_REP_STOSW)
                    BUF_SIZE=CONTEXT_get_xCX (ctx)*2;
                else if (d->ins_code==I_REP_STOSD)
                    BUF_SIZE=CONTEXT_get_xCX (ctx)*4;

                buf=DMALLOC(BYTE, BUF_SIZE, "buf");

                if (d->ins_code==I_REP_STOSB)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        buf[i]=CONTEXT_get_Accum(ctx)&0xFF;
                } 
                else if (d->ins_code==I_REP_STOSW)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        ((WORD*)buf)[i]=CONTEXT_get_Accum(ctx)&0xFFFF;
                } 
                else if (d->ins_code==I_REP_STOSD)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        ((DWORD*)buf)[i]=(DWORD)(CONTEXT_get_Accum(ctx)&0xFFFFFFFF);
                } 
                else
                {
                    oassert(0);
                };

                if (MC_WriteBuffer (mem, CONTEXT_get_xDI (ctx), BUF_SIZE, buf)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                DFREE(buf);
                CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) + BUF_SIZE);
                CONTEXT_set_xCX (ctx, 0);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_REP_MOVSB:
        case I_REP_MOVSW:
        case I_REP_MOVSD:
            {
                BYTE *buf;
                bool DF=IS_SET(ctx->EFlags, FLAG_DF);
                if (DF)
                    return DA_NOT_EMULATED; // not supported... bug here

                SIZE_T BUF_SIZE;
                SIZE_T sizeof_element;

                if (d->ins_code==I_REP_MOVSB)
                    sizeof_element=1;
                else if (d->ins_code==I_REP_MOVSW)
                    sizeof_element=2;
                else if (d->ins_code==I_REP_MOVSD)
                    sizeof_element=4;
                else
                {
                    oassert(0);
                };

                BUF_SIZE=CONTEXT_get_xCX(ctx)*sizeof_element;

                //printf ("%s() BUF_SIZE=0x%x\n", __func__, BUF_SIZE);
                //printf ("%s() (before) SI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xSI(ctx));
                //printf ("%s() (before) DI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xDI(ctx));

                buf=DMALLOC(BYTE, BUF_SIZE, "buf");

                address blk_src=CONTEXT_get_xSI(ctx);
                address blk_dst=CONTEXT_get_xDI(ctx);

                if (DF)
                {
                    blk_src-=BUF_SIZE; // +sizeof_element;
                    blk_dst-=BUF_SIZE; // +sizeof_element;
                };

                if (MC_ReadBuffer (mem, blk_src, BUF_SIZE, buf)==false)
                {
                    DFREE(buf);
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                };

                if (MC_WriteBuffer (mem, blk_dst, BUF_SIZE, buf)==false)
                {
                    DFREE(buf);
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };

                DFREE(buf);
                if (DF==false)
                {
                    CONTEXT_set_xSI (ctx, CONTEXT_get_xSI (ctx) + BUF_SIZE);
                    CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) + BUF_SIZE);
                }
                else
                {
                    CONTEXT_set_xSI (ctx, CONTEXT_get_xSI (ctx) - BUF_SIZE);
                    CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) - BUF_SIZE);
                };
                CONTEXT_set_xCX (ctx, 0);

                //printf ("%s() (after) SI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xSI(ctx));
                //printf ("%s() (after) DI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xDI(ctx));

                goto add_to_PC_and_return_OK;
            };

        case I_STD:
            SET_BIT (ctx->EFlags, FLAG_DF);
            goto add_to_PC_and_return_OK;

        case I_CLD:
            REMOVE_BIT (ctx->EFlags, FLAG_DF);
            goto add_to_PC_and_return_OK;

        case I_RETN:
            {
                WORD ret_arg=0;
                if (d->ops_total==1)
                {
                    oassert (d->op[0].type==DA_OP_TYPE_VALUE);
                    ret_arg=obj_get_as_wyde(&d->op[0].val._v); // RETN arg is 16-bit
                };

                address newPC;
                if (DO_POP(ctx, mem, &newPC)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                CONTEXT_set_SP(ctx, CONTEXT_get_SP(ctx)+ret_arg);
                CONTEXT_set_PC(ctx, newPC);
                return DA_EMULATED_OK;
            };
            break;

        case I_ADD:
        case I_ADC:
        case I_INC:
            {
                //L (__FUNCTION__ "() I_ADD/I_INC begin: [%s]\n", ToString().c_str());

                obj rt1, rt2;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                if (d->ins_code==I_ADD || d->ins_code==I_ADC)
                {
                    oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                    b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                    if (b==false)
                        return DA_EMULATED_CANNOT_READ_MEMORY;
                }
                else
                {   // INC case
                    // make second op 1
                    obj_REG2_and_set_type (rt1.t, 1, 0, &rt2);
                };

                obj res_sum;
                obj_add (&rt1, &rt2, &res_sum);
                if (d->ins_code==I_ADC && CF)
                    obj_increment(&res_sum); 

                set_PF (ctx, &res_sum);
                set_SF (ctx, &res_sum);
                set_ZF (ctx, &res_sum);
                set_AF (ctx, &rt1, &rt2, &res_sum);
                if (d->ins_code==I_ADD || d->ins_code==I_ADC)
                    set_or_clear_flag (ctx, FLAG_CF, obj_compare (&res_sum, &rt1)==-1); // res_sum < rt1

                octabyte tmp=((zero_extend_to_REG(&rt1) ^ zero_extend_to_REG(&rt2) ^ 
                            get_sign_bit (d->op[0].value_width_in_bits)) & 
                        (zero_extend_to_REG(&res_sum) ^ zero_extend_to_REG(&rt1))) 
                    & 
                    get_sign_bit (d->op[0].value_width_in_bits);
                set_or_clear_flag (ctx, FLAG_OF, tmp);

                b=Da_op_set_value_of_op (&d->op[0], &res_sum, ctx, mem, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_NOT:
            {
                obj rt1, res;
                REG rt1_adr;
                if (Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj_NOT(&rt1, &res);

                if (Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS))
                    goto add_to_PC_and_return_OK;
            };
            break;

        case I_NEG:
            {
                obj rt1, res;
                REG rt1_adr;
                if (Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj_NEG(&rt1, &res);
                set_or_clear_flag (ctx, FLAG_CF, obj_is_zero(&rt1)==false);

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                set_or_clear_flag (ctx, FLAG_AF, (0 ^ obj_get_4th_bit(&rt1)) ^ obj_get_4th_bit(&res));
                REMOVE_BIT (ctx->EFlags, FLAG_OF);
                //SET_BIT (ctx->EFlags, FLAG_AF);

                if (Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS))
                    goto add_to_PC_and_return_OK;
            };
            break;


        case I_OR:
        case I_XOR:
        case I_AND:
        case I_TEST:
            {
                oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                obj rt1, rt2, res;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                switch (d->ins_code)
                {
                    case I_OR:  
                        obj_OR(&rt1, &rt2, &res); 
                        break;
                    case I_XOR: 
                        obj_XOR(&rt1, &rt2, &res); 
                        break;
                    case I_TEST: 
                    case I_AND: 
                        obj_AND(&rt1, &rt2, &res); 
                        break;
                    default: 
                        oassert(0);
                        break;
                };

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                REMOVE_BIT (ctx->EFlags, FLAG_AF);
                REMOVE_BIT (ctx->EFlags, FLAG_CF);
                REMOVE_BIT (ctx->EFlags, FLAG_OF);

                if (d->ins_code==I_TEST)
                    b=true;
                else
                    b=Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS);

                if (b)
                    goto add_to_PC_and_return_OK;
                else
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            break;

        case I_DEC:
        case I_SUB:
        case I_SBB:
        case I_CMP:
            {
                if (d->ins_code==I_SUB || d->ins_code==I_SBB || d->ins_code==I_CMP)
                {
                    oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                };
                obj rt1, rt2;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false) 
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                if (d->ins_code==I_DEC)
                {
                    // make second op 1
                    obj_REG2_and_set_type (rt1.t, 1, 0, &rt2);
                }
                else
                {
                    b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                    if (b==false)
                        return DA_EMULATED_CANNOT_READ_MEMORY;
                };

                obj res;
                obj_subtract (&rt1, &rt2, &res);
                if (d->ins_code==I_SBB && CF)
                    obj_decrement (&res);

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                set_AF (ctx, &rt1, &rt2, &res);

                if (d->ins_code==I_SBB)
                {
                    int tmp=(obj_compare (&rt1, &res)==-1 /* rt1<res */) || (CF && obj_get_as_tetrabyte(&rt2)==0xffffffff);
                    set_or_clear_flag (ctx, FLAG_CF, tmp);
                }
                else
                {
                    if (d->ins_code!=I_DEC) // DEC leave CF flag unaffected
                        set_or_clear_flag (ctx, FLAG_CF, obj_compare (&rt1, &rt2)==-1); /* rt1<rt2 */
                };

                octabyte tmp=((zero_extend_to_octabyte(&rt1) ^ zero_extend_to_octabyte(&rt2)) & 
                        (zero_extend_to_octabyte(&res) ^ zero_extend_to_octabyte(&rt1))) &
                    get_sign_bit (d->op[0].value_width_in_bits);
                set_or_clear_flag (ctx, FLAG_OF, tmp);

                if (d->ins_code==I_CMP)
                    b=true;
                else
                    b=Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS);

                if (b)
                    goto add_to_PC_and_return_OK;
                else
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            break;

        case I_XCHG:
            {
                REG op1_adr, op2_adr;

                obj op1;
                b=Da_op_get_value_of_op(&d->op[0], &op1_adr, ctx, mem, __FILE__, __LINE__, &op1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj op2;
                b=Da_op_get_value_of_op(&d->op[1], &op2_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                if (Da_op_set_value_of_op (&d->op[0], &op2, ctx, mem, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;

                if (Da_op_set_value_of_op (&d->op[1], &op1, ctx, mem, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;

                goto add_to_PC_and_return_OK;
            };
            break;

        case I_MOV:
        case I_MOVDQA:
        case I_MOVDQU:
            return Da_emulate_MOV_op1_op2(d, ctx, mem, d->prefix_codes, FS);

        case I_MOVZX:
        case I_MOVSX:
            {
                address rt_adr;
                obj op2;
                bool b=Da_op_get_value_of_op(&d->op[1], &rt_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                {
                    /*
                       if (L_verbose_level>=2)
                       {
                       printf (__FUNCTION__ "(): [");
                       Da_DumpString(d);
                       printf ("]: can't read src (2nd) operand\n");
                       };
                       */
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };

                obj to_be_stored_v;

                if (d->ins_code==I_MOVZX)
                {
                    enum obj_type op1_type_will_be=bit_width_to_obj_type (d->op[0].value_width_in_bits);
                    obj_zero_extend (&op2, op1_type_will_be, &to_be_stored_v);
                }
                else if (d->ins_code==I_MOVSX)
                {
                    enum obj_type op1_type_will_be=bit_width_to_obj_type (d->op[0].value_width_in_bits);
                    obj_sign_extend (&op2, op1_type_will_be, &to_be_stored_v);
                }
                else
                {
                    oassert (0);
                };

                b=Da_op_set_value_of_op (&d->op[0], &to_be_stored_v, ctx, mem, d->prefix_codes, FS);

                if (b==false)
                {
                    /*
                       if (L_verbose_level>=2)
                       {
                       printf(__FUNCTION__ "(): [");
                       Da_DumpString(d);
                       printf ("]: can't write dst (1st) operand\n");
                       };
                       */
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };
                goto add_to_PC_and_return_OK;
            };

        case I_NOP:
            goto add_to_PC_and_return_OK;

        case I_LEA:
            {
                address a=(address)Da_op_calc_adr_of_op(&d->op[1], ctx, mem, d->prefix_codes, FS);
                obj val;
                obj_tetrabyte2(a, &val);
                b=Da_op_set_value_of_op (&d->op[0], &val, ctx, mem, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                goto add_to_PC_and_return_OK;
            };

        case I_SAR:
        case I_SHR:
        case I_SHL:
            {
                // http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH06/CH06-3.html

                REG op1_adr, op2_adr;

                obj op1;
                bool b=Da_op_get_value_of_op(&d->op[0], &op1_adr, ctx, mem, __FILE__, __LINE__, &op1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                // should be read anyway!
                obj op2;
                b=Da_op_get_value_of_op(&d->op[1], &op2_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
#ifdef _WIN64 
                obj_AND_with (&op2, 0x3F);
#else
                obj_AND_with (&op2, 0x1F);
#endif
                if (obj_is_zero(&op2)==false)
                {
                    unsigned new_CF;

                    if (d->ins_code==I_SHR || d->ins_code==I_SAR)
                        new_CF=(zero_extend_to_octabyte(&op1) >> (obj_get_as_byte (&op2) - 1)) & 1;
                    else // SHL
                        new_CF=(zero_extend_to_octabyte(&op1) >> (obj_width_in_bits(&op1) - obj_get_as_byte (&op2))) & 1;

                    obj new_op1;

                    if (d->ins_code==I_SHR)
                    {
                        REG new_v=zero_extend_to_REG(&op1) >> obj_get_as_byte (&op2);
                        obj_REG2_and_set_type(op1.t, new_v, 0, &new_op1);
                    }
                    else if (d->ins_code==I_SAR)
コード例 #3
0
ファイル: obj.c プロジェクト: BlackBoxe/minuit
void _op_obj_import(void)
{
	t_context *C=ctx_get();
	char *filename=C->event->standby_string;

	if(filename)
	{
		// init list
		OBJECTS=lst_new("lst");

		// parse file
		t_file *file = file_new(filename);

		free(C->event->standby_string);
		//C->event->standby_function=NULL;
		C->event->callback=NULL;

		file_read(file);
		file_read_lines(file);

		//parse words
		t_link *link;
		t_link *l;
		t_word *word;

		for(link=file->lines->first;link;link=link->next)
		{
			t_line *line = link->data;
			line_read_words(line);
		}

		// parse tokens
		int object_start;
		int line_object;
		int is_face;
		//int tot_object;
		int tot_vert;
		int tot_face;
		int tot_tri;
		int tot_quad;
		int tot_indice;

		char *object_name;

		//tot_object=0;
		tot_face=0;
		tot_quad=0;
		tot_tri=0;
		object_start=0;
		
		for(link=file->lines->first;link;link=link->next)
		{
			// LINE
			t_line *line = link->data;

			// RESET
			is_face=0;

			for(l=line->words->first;l;l=l->next)
			{
				// WORD

				word=l->data;

				if(word_equal(word,"o"))
				{
					if(object_start)
					{
						obj_add(object_name,tot_vert,tot_face,tot_quad,tot_tri);

						tot_vert=0;
						tot_face=0;
						tot_quad=0;
						tot_tri=0;
					
						free(object_name);
					}
					else
					{
						object_start=1;
					}

					tot_vert=0;
					line_object=1;
				}
				else if(line_object)
				{
					object_name=(char *)malloc(sizeof(char)*(strlen(word->data)+1));
					strcpy(object_name,word->data);
					line_object=0;
				}
				else if(word_equal(word,"v"))
				{
					tot_vert++;
				}
				else if(word_equal(word,"f"))
				{
					tot_face++;
					is_face=1;
					tot_indice=0;
				}
				else if(is_face)
				{
					tot_indice++;
				}
				else if(word_equal(word,"usemtl"))
				{
				}
				else if(word_equal(word,"s"))
				{
				}
			}

			if(is_face)
			{
				if(tot_indice==4)
				{
					tot_quad++;
				}
				else
				{
					tot_tri++;
				}
			}
		}

		// add last object
		obj_add(object_name,tot_vert,tot_face,tot_quad,tot_tri);

		// vars
		int is_data=0;
		int indice_vertex=0;
		int indice_face=0;
		int cursor_tri=0;
		int cursor_quad=0;
		int global_cursor=0;
		int tmp_global_cursor=0;
		int face[4];

		object_start=0;

		t_token_type token;
		t_link *link_object;
		t_obj *obj;

		for(link=file->lines->first;link;link=link->next)
		{
			// LINE

			t_line *line = link->data;
			
			// reset
			is_data=0;
			indice_face=0;

			for(l=line->words->first;l;l=l->next)
			{
				// WORD

				word=l->data;

				if(word_equal(word,"o"))
				{
					token=token_object;

					if(object_start)
					{
						if(link_object->next) link_object=link_object->next;
						obj=link_object->data;
						// global cursor
						global_cursor+=tmp_global_cursor;
						tmp_global_cursor=obj->tot_vert;
					}
					//first
					else
					{
						link_object=OBJECTS->first;
						obj=link_object->data;
						object_start=1;
						tmp_global_cursor=obj->tot_vert;
					}

					indice_vertex=0;
					indice_face=0;
					cursor_tri=0;
					cursor_quad=0;
				}
				else if(word_equal(word,"v"))
				{
					token=token_vertex;
				}
				else if(word_equal(word,"f"))
				{
					token=token_face;
				}
				else if(word_equal(word,"usemtl"))
				{
					token=token_material;
				}
				else if(word_equal(word,"s"))
				{
					token=token_unknown;
				}
				else
				{
					is_data=1;
				}

				if(is_data)
				{
					if(token==token_vertex)
					{
						obj->verts[indice_vertex]=atof(word->data);
						indice_vertex++;
					}
					else if(token==token_face)
					{
						face[indice_face]=atoi(word->data);
						indice_face++;
					}
				}
			}

			// store face indice
			if(token==token_face)
			{
				int i;
				if(indice_face==3)
				{
					for(i=0;i<3;i++)
					{
						obj->tris[cursor_tri]=face[i]-global_cursor-1;
						cursor_tri++;
					}
				}
				else
				{
					for(i=0;i<4;i++)
					{
						obj->quads[cursor_quad]=face[i]-global_cursor-1;
						cursor_quad++;
					}
				}
			}
		}

		
		// add objects to scene

		C->scene->store=1;

		for(link=OBJECTS->first;link;link=link->next)
		{
			t_obj *obj = link->data;

			// new mesh
			t_node *node_mesh=mesh_make(
						obj->name,
						//"me_obj",
						obj->tot_vert,
						obj->tot_face,
						obj->tot_quad,
						obj->tot_tri,
						obj->verts,
						obj->quads,
						obj->tris);


			// new object
			t_node *node_object=object_add("mesh",obj->name);

			// link
			t_object *object=node_object->data;
			object->cls->link(object,node_mesh);
		}

		C->scene->store=0;

		// free obj

		for(link=OBJECTS->first;link;link=link->next)
		{
			t_obj *obj = link->data;
			obj_free(obj);
		}
	}
}