예제 #1
0
t_status	interface_segment_copy(o_syscall*	message)
{
  t_status error;

  error = segment_copy(message->u.request.u.segment_copy.arg1,
			message->u.request.u.segment_copy.arg2,
			message->u.request.u.segment_copy.arg3,
			message->u.request.u.segment_copy.arg4,
			message->u.request.u.segment_copy.arg5);

  message->u.reply.error = error;

  return (STATUS_OK);
}
예제 #2
0
int compile_array_data( VARSPACE * n, segment * data, int size, int subsize, BASETYPE *t )
{
    int block, count = 0, base, remaining = size ;
    int base_offset, total_length ;

    expresion_result res ;

    for ( ;; )
    {
        if ( !remaining && size )
        {
            token_back();
            break;
//            compile_error( MSG_TOO_MANY_INIT ) ;
        }

        token_next() ;
        /*
        if (*t == TYPE_UNDEFINED && token.type == STRING)
        {
            *t = typedef_base(typedef_new(TYPE_STRING)) ;
        }
        */
        if ( token.type == STRING && *t == TYPE_CHAR )
        {
            const char * str = string_get( token.code ) ;
            int subcount = 0 ;

            if ( subsize == 0 ) subsize = strlen( str ) + 1;

            if (( int )strlen( str ) > subsize ) compile_error( MSG_TOO_MANY_INIT ) ;
            while ( *str )
            {
                segment_add_as( data, *str++, *t ) ;
                subcount++ ;
            }
            while ( subcount++ < subsize ) segment_add_as( data, 0, *t ) ;
            count += subsize ;
            remaining -= subsize ;
        }
        else if ( token.type == IDENTIFIER && ( token.code == identifier_rightp || token.code == identifier_semicolon ) )
        {
            token_back() ;
            break ;
        }
        else if ( token.type == IDENTIFIER && token.code == identifier_leftp )
        {
            block = compile_array_data( n, data, remaining, remaining, t ) ;
            remaining -= block ;
            count += block ;
            token_next() ;
            if ( token.type != IDENTIFIER || token.code != identifier_rightp )
                compile_error( MSG_EXPECTED, ")" ) ;
        }
        else
        {
            token_back() ;
            res = compile_expresion( 1, 0, 0, *t ) ;
            if ( *t == TYPE_UNDEFINED )
            {
                *t = typedef_base( res.type ) ;
                if ( *t == TYPE_UNDEFINED )
                {
                    compile_error( MSG_INCOMP_TYPE ) ;
                }
            }
            base = res.value ;
            if ( *t == TYPE_FLOAT ) base = *( int * ) & res.fvalue ;

            token_next() ;
            if ( token.type == IDENTIFIER && token.code == identifier_dup )
            {
                token_next() ;
                if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" ) ;
                base_offset = data->current ;
                block = compile_array_data( n, data, remaining, remaining, t ) ;
                total_length = data->current - base_offset ;
                if ( size && block * base > remaining )
                {
                    break; /* MSG_TOO_MANY_INIT */
                }
                count += block * base ;
                if ( size ) remaining -= block * base ;
                while ( base-- > 1 )
                {
                    segment_copy( data, base_offset, total_length ) ;
                    base_offset += total_length ;
                }
                token_next() ;
                if ( token.type != IDENTIFIER || token.code != identifier_rightp )
                    compile_error( MSG_EXPECTED, ")" ) ;
            }
            else
            {
                token_back() ;
                if ( *t == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                segment_add_as( data, base, *t ) ;
                count ++ ;
                if ( size ) remaining -- ;
            }
        }
        token_next() ;
        if ( token.type == IDENTIFIER && token.code == identifier_comma )
        {
            if ( !size && *t == TYPE_CHAR ) compile_error( MSG_TOO_MANY_INIT );
            continue ;
        }
        token_back() ;
        break ;
    }

    return count ;
}
예제 #3
0
int main(int argc, char **argv)
{
    int chunk_size = 10;
    int n_chunks = 10;
    int bufsize= n_chunks * chunk_size;
    char base_data[bufsize+1];
    char buffer[bufsize+1];
    char log1_data[bufsize+1];
    char log2_data[bufsize+1];
    char log3_data[bufsize+1];
    tbuffer_t tbuf;
    ex_iovec_t ex_iov, ex_iov_table[n_chunks];
    int i, err;
    char *fname = NULL;
    exnode_t *ex;
    exnode_exchange_t *exp;
    segment_t *seg, *clone, *clone2, *clone3;
    seglog_priv_t *s;
    opque_t *q;

    if (argc < 2) {
        printf("\n");
        printf("log_test LIO_COMMON_OPTIONS log.ex3\n");
        lio_print_options(stdout);
        printf("    log.ex3 - Log file to use.  IF the file is not empty all it's contents are truncated\n");
        printf("\n");
        return(1);
    }

    lio_init(&argc, &argv);

    //*** Parse the args
    //** This is the remote file to download
    i = 1;
    fname = argv[i];
    i++;
    if (fname == NULL) {
        printf("Missing log file!\n");
        return(2);
    }

    //** Load it
    exp = exnode_exchange_load_file(fname);

    //** and parse the remote exnode
    ex = exnode_create();
    if (exnode_deserialize(ex, exp, lio_gc->ess) != 0) {
        printf("ERROR parsing exnode!  Aborting!\n");
        abort();
    }

    //** Get the default view to use
    seg = exnode_get_default(ex);
    if (seg == NULL) {
        printf("No default segment!  Aborting!\n");
        abort();
    }
    s = (seglog_priv_t *)seg->priv;

    //** Verify the type
    if (strcmp(segment_type(seg), SEGMENT_TYPE_LOG) != 0) {
        printf("Invalid exnode type.  Segment should be a single level log but got a type of %s\n", segment_type(seg));
        abort();
    }

    //** Now get the base type.  It should NOT be a log
    if (strcmp(segment_type(s->base_seg), SEGMENT_TYPE_LOG) == 0) {
        printf("Log segments base should NOT be another log segment!\n");
        abort();
    }


    //** Truncate the log and base
    q = new_opque();
    opque_add(q, segment_truncate(s->table_seg, lio_gc->da, 0, lio_gc->timeout));
    opque_add(q, segment_truncate(s->data_seg, lio_gc->da, 0, lio_gc->timeout));
    opque_add(q, segment_truncate(s->base_seg, lio_gc->da, 0, lio_gc->timeout));
    err = opque_waitall(q);
    if (err != OP_STATE_SUCCESS) {
        printf("Error with truncate of initial log segment!\n");
        abort();
    }
    s->file_size = 0;
    s->data_size = 0;
    s->log_size = 0;

    //*************************************************************************
    //--------------------- Testing starts here -------------------------------
    //*************************************************************************

    //*************************************************************************
    //------- Generate a base with an empty log and read back -----------------
    //*************************************************************************
    //** Make the base buffer and write it
    memset(base_data, 'B', bufsize);
    base_data[bufsize] = '\0';
    tbuffer_single(&tbuf, bufsize, base_data);
    ex_iovec_single(&ex_iov, 0, bufsize);
    { int result = gop_sync_exec(segment_write(s->base_seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    s->file_size = bufsize;  //** Since we're peeking we have to adjust the file size
    tbuffer_single(&tbuf, bufsize, buffer);  //** Read it directly back fro mthe base to make sure that works
    { int result = gop_sync_exec(segment_read(s->base_seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    buffer[bufsize] = '\0';
    { int result = strcmp(buffer, base_data); assert(result == 0); }

    //** Do the same for the log
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, base_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //-- Clone the base structure and the use segment_copy to copy the data and verify --
    //*************************************************************************
    clone = NULL;
    { int result = gop_sync_exec(segment_clone(seg, lio_gc->da, &clone, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = gop_sync_exec(segment_copy(lio_gc->tpc_unlimited, lio_gc->da, NULL, seg, clone, 0, 0, bufsize, chunk_size, buffer, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, base_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //-------------------- Write to the log and read back ---------------------
    //*************************************************************************
    //** We are writing 1's to the even chunks
    memcpy(log1_data, base_data, bufsize);
    memset(buffer, '1', chunk_size);
    for (i=0; i<n_chunks; i+=2) {
        memcpy(&(log1_data[i*chunk_size]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, chunk_size);
        opque_add(q, segment_write(seg, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //------------------- Merge_with base and verify --------------------------
    //*************************************************************************
    { int result = gop_sync_exec(slog_merge_with_base(seg, lio_gc->da, chunk_size, buffer, 1, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //--------------- Write to the new empty log and verify -------------------
    //*************************************************************************
    //** We are writing 2's to *most* of the odd chunks
    memcpy(log1_data, buffer, bufsize);
    memset(buffer, '2', chunk_size);
    for (i=1; i<n_chunks; i+=2) {
        memcpy(&(log1_data[i*chunk_size]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, chunk_size);
        opque_add(q, segment_write(seg, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---------- Replace the clones base with seg(Log1) and verify ------------
    //*************************************************************************
    { int result = gop_sync_exec(segment_remove(clone, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(clone);
    clone = NULL;
    { int result = gop_sync_exec(segment_clone(seg, lio_gc->da, &clone, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    s = (seglog_priv_t *)clone->priv;

    s->base_seg = seg;
    s->file_size = segment_size(seg);

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---------- Write to the clones log and verify (now have 2 logs) ---------
    //*************************************************************************
    memcpy(log2_data, log1_data, bufsize);
    memset(buffer, '3', 1.5*chunk_size);
    for (i=0; i<n_chunks; i+=4) {
        memcpy(&(log2_data[i*chunk_size]), buffer, 1.5*chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, 1.5*chunk_size);
        opque_add(q, segment_write(clone, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---- clone2 = clone (structure and data). Verify the contents -----------
    //*************************************************************************
    clone2 = NULL;
    { int result = gop_sync_exec(segment_clone(clone, lio_gc->da, &clone2, CLONE_STRUCT_AND_DATA, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //** We don't need this anymore so destroy it
    { int result = gop_sync_exec(segment_remove(clone2, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(clone2);

    //*************************************************************************
    //---------------- Clone2 = clone's structure *only* ----------------------
    //*************************************************************************
    clone2 = NULL;
    { int result = gop_sync_exec(segment_clone(clone, lio_gc->da, &clone2, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    //*************************************************************************
    //-------------- Replace clone2's base with clone and verify --------------
    //*************************************************************************
    s = (seglog_priv_t *)clone2->priv;
    { int result = gop_sync_exec(segment_remove(s->base_seg, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(s->base_seg);

    s->base_seg = clone;
    s->file_size = segment_size(clone);

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //----------- Write to Clone2 and verify (now have 3 logs) ----------------
    //*************************************************************************
    memcpy(log3_data, log2_data, bufsize);
    memset(buffer, '4', chunk_size);
    for (i=0; i<n_chunks; i+=2) {
        memcpy(&(log3_data[i*chunk_size + chunk_size/3]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size + chunk_size/3, chunk_size);
        opque_add(q, segment_write(clone2, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log3_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    // -- clone3 = clone2 structure and contents and verify
    //*************************************************************************
    clone3 = NULL;
    { int result = gop_sync_exec(segment_clone(clone2, lio_gc->da, &clone3, CLONE_STRUCT_AND_DATA, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone3, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log3_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //--------------------- Testing Finished -------------------------------
    //*************************************************************************

    //** Clean up
    { int result = gop_sync_exec(segment_remove(clone3, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = gop_sync_exec(segment_remove(clone2, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    segment_destroy(clone3);
    segment_destroy(clone2);
    segment_destroy(seg);


    exnode_exchange_destroy(exp);

    lio_shutdown();

    return(0);
}
예제 #4
0
int compile_varspace( VARSPACE * n, segment * data, int additive, int copies, int padding, VARSPACE ** collision, int alignment, int duplicateignore )
{
    int i, j, total_count, last_count = 0 ;
    int base_offset = data->current ;
    int total_length ;
    int size, count ;
    int code ;
    expresion_result res ;
    VARIABLE * var ;
    int unsigned_prefix = 0;
    int signed_prefix = 0;

    BASETYPE basetype = TYPE_UNDEFINED ;
    TYPEDEF type, typeaux;
    segment * segm = NULL ;
    PROCDEF * proc = NULL;

    /* Backup vars */
    BASETYPE basetypeb = TYPE_UNDEFINED ;
    TYPEDEF typeb;
    segment * segmb = NULL ;

    /* Initialize some stuffs */

    type = typedef_new( TYPE_UNDEFINED ) ;
    typeb = typedef_new( TYPE_UNDEFINED ) ;

    for ( ;; )
    {
        if ( n->reserved == n->count ) varspace_alloc( n, 16 ) ;

        if ( alignment && ( n->size % alignment ) > 0 )
        {
            int extra = alignment - ( n->size % alignment );
            if ( n->reserved <= n->count + extra )
            {
                varspace_alloc( n, extra + 16 );
            }
            if ( data->reserved <= data->current + extra )
            {
                segment_alloc( data, extra + 16 );
            }
            n->size += extra;
            data->current += extra;
        }

        token_next() ;

        /* Se salta comas y puntos y coma */

        if ( token.type == NOTOKEN ) break ;

        if ( token.type != IDENTIFIER ) compile_error( MSG_INCOMP_TYPE ) ;

        if ( token.code == identifier_comma )
        {
            basetype = basetypeb ;
            type = typeb ;

            segm = segmb ;

            continue ;
        }
        else if ( token.code == identifier_semicolon )
        {
            basetype = TYPE_UNDEFINED ;
            set_type( &type, TYPE_UNDEFINED ) ;

            basetypeb = basetype ;
            typeb = type ;

            segm = NULL ;
            proc = NULL ;

            continue ;
        }
        else if ( token.code == identifier_end )
        {
            break ;
        }

        /* "Unsigned" */

        if ( token.code == identifier_unsigned )
        {
            unsigned_prefix = 1;
            token_next();
        }
        else if ( token.code == identifier_signed )
        {
            signed_prefix = 1;
            token_next();
        }

        /* Tipos de datos básicos */

        if ( token.code == identifier_dword )
        {
            basetype = signed_prefix ? TYPE_INT : TYPE_DWORD ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_word )
        {
            basetype = signed_prefix ? TYPE_SHORT : TYPE_WORD ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_byte )
        {
            basetype = signed_prefix ? TYPE_SBYTE : TYPE_BYTE ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_int )
        {
            basetype = unsigned_prefix ? TYPE_DWORD : TYPE_INT;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_short )
        {
            basetype = unsigned_prefix ? TYPE_WORD : TYPE_SHORT;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_char )
        {
            basetype = TYPE_CHAR ;
            token_next() ;
        }
        else if ( token.code == identifier_float )
        {
            basetype = TYPE_FLOAT ;
            token_next() ;
        }
        else if ( token.code == identifier_string )
        {
            basetype = TYPE_STRING ;
            token_next() ;
        }
        else
        {
            if ( !proc && ( proc = procdef_search( token.code ) ) )    /* Variables tipo proceso, Splinter */
            {
                basetype = TYPE_INT ;
                token_next();
            }
            else
            {
                if (
                    token.type == IDENTIFIER &&
                    token.code >= reserved_words &&
                    !segment_by_name( token.code ) )
                {
                    int code = token.code;
                    token_next();
                    if ( token.type == IDENTIFIER && token.code >= reserved_words )
                    {
                        proc = procdef_new( procdef_getid(), code );
                        basetype = TYPE_INT ;
                    }
                    else
                    {
                        token_back();
                    }
                }
            }
        }

        if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE );
        if ( basetype != TYPE_STRUCT ) type = typedef_new( basetype ) ;
        if ( basetype == TYPE_UNDEFINED ) type = typedef_new( TYPE_INT ) ;

        /* Tipos de datos definidos por el usuario */
        if ( basetype != TYPE_STRUCT && ( segm = segment_by_name( token.code ) ) )
        {
            basetype = TYPE_STRUCT ;
            type = * typedef_by_name( token.code ) ;
            token_next() ;
        }

        if ( token.type == IDENTIFIER && token.code == identifier_struct )
        {
            type.chunk[0].type = TYPE_STRUCT ;
            type.chunk[0].count = 1 ;
            type.depth = 1 ;
            token_next() ;
            segm = 0 ;
        }

        basetypeb = basetype ;
        typeb = type ;
        segmb = segm ;

        /* Tipos de datos derivados */
        while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) )
        {
            type = typedef_enlarge( type ) ;
            type.chunk[0].type = TYPE_POINTER ;
            basetype = TYPE_POINTER ;
            segm = NULL ;
            token_next() ;
        }

        /* Nombre del dato */

        if ( token.type != IDENTIFIER ) compile_error( MSG_IDENTIFIER_EXP ) ;

        if ( token.code < reserved_words )
        {
            if ( proc ) compile_error( MSG_VARIABLE_ERROR );
            token_back() ;
            break ;
        }

        if (( var = varspace_search( n, token.code ) ) )
        {
            if ( duplicateignore )
            {
                int skip_all_until_semicolon = 0;
                int skip_equal = 0;

                if ( debug ) compile_warning( 0, MSG_VARIABLE_REDECLARE ) ;

                for ( ;; )
                {
                    token_next() ;

                    /* Se salta todo hasta el puntos y coma o en el end o la coma si no hay asignacion */

                    if ( token.type == NOTOKEN ) break ;

                    if ( token.type == IDENTIFIER )
                    {
                        if ( !skip_equal && token.code == identifier_equal )
                        {
                            skip_all_until_semicolon = 1;
                            continue;
                        }

                        if ( !skip_all_until_semicolon && token.code == identifier_comma ) break;
                        if ( token.code == identifier_semicolon ) break ;
                        if ( token.code == identifier_end ) break ;
                    }
                }
                token_back();
                continue;
            }
            else
                compile_error( MSG_VARIABLE_REDECLARE ) ;
        }

        /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */
        if ( collision )
            for ( i = 0; collision[i];i++ )
                if ( varspace_search( collision[i], token.code ) ) compile_error( MSG_VARIABLE_REDECLARE ) ;
        /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */

        if ( constants_search( token.code ) ) compile_error( MSG_CONSTANT_REDECLARED_AS_VARIABLE ) ;

        code = token.code ;
        n->vars[n->count].code = token.code ;
        n->vars[n->count].offset = data->current;

        /* Non-additive STRUCT; use zero-based member offsets */

        if ( !additive ) n->vars[n->count].offset -= base_offset;

        token_next() ;

        /* Compila una estructura no predefinida */

        if ( !segm && typedef_is_struct( type ) )
        {
            VARSPACE * members ;

            type.chunk[0].count = 1 ;
            count = 1 ;
            while ( token.type == IDENTIFIER && token.code == identifier_leftb )
            {
                res = compile_expresion( 1, 0, 0, TYPE_INT ) ;
                if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ;
                count *= res.value + 1 ;
                type = typedef_enlarge( type ) ;
                type.chunk[0].type  = TYPE_ARRAY ;
                type.chunk[0].count = res.value + 1 ;
                token_next() ;
                if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ;
                token_next() ;
            }
            token_back() ;

            /* Da la vuelta a los índices [10][5] -> [5][10] */

            for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ;
            i--;
            for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ];
            for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ]    = typeaux.chunk[ j ];

            members = ( VARSPACE * )calloc( 1, sizeof( VARSPACE ) ) ;
            if ( !members )
            {
                fprintf( stdout, "compile_varspace: out of memory\n" ) ;
                exit( 1 ) ;
            }
            varspace_init( members ) ;

            size = compile_varspace( members, data, 0, count, 0, NULL, 0, duplicateignore ) ;

            type.varspace = members ;

            token_next() ;
            if ( token.type == IDENTIFIER && token.code == identifier_equal )
            {
                i = data->current ;
                data->current = n->vars[n->count].offset ;
                compile_struct_data( members, data, count, 0 );
                data->current = i ;
            }
            else
            {
                token_back() ;
            }

            for ( i = 0 ; i < members->stringvar_count ; i++ )
                varspace_varstring( n, members->stringvars[i] ) ;

            n->size += typedef_size( type ) ;
            n->vars[n->count].type = type ;
            n->count++ ;

            continue ;  /* No ; */

        }
        else if ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* Compila un array */
        {
            total_count = 1 ;

            while ( token.type == IDENTIFIER && token.code == identifier_leftb )
            {
                if ( type.depth == MAX_TYPECHUNKS ) compile_error( MSG_TOO_MANY_AL ) ;

                type = typedef_enlarge( type ) ;
                type.chunk[0].type = TYPE_ARRAY ;

                token_next() ;
                if ( token.type == IDENTIFIER && token.code == identifier_rightb )
                {
                    type.chunk[0].count = 0 ;
                    if ( total_count != 1 ) compile_error( MSG_VTA ) ;
                    total_count = 0 ;
                    last_count = 0 ;
                }
                else
                {
                    token_back() ;
                    res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ;
                    if ( !total_count ) compile_error( MSG_VTA ) ;
                    total_count *= res.value + 1 ;
                    last_count = res.value + 1 ;
                    type.chunk[0].count = res.value + 1 ;
                    token_next() ;
                    if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ;
                }

                token_next() ;
            }

            /* Da la vuelta a los índices [10][5] -> [5][10] */

            for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ;
            i--;
            for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ];
            for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ]    = typeaux.chunk[ j ];

            if ( segm && token.type == IDENTIFIER && token.code == identifier_equal )
            {
                for ( i = 0 ; i < total_count ; i++ ) segment_add_from( data, segm ) ;
                i = data->current ;
                data->current = n->vars[n->count].offset ;
                compile_struct_data( type.varspace, data, typedef_count( type ), 0 );

                if ( !type.chunk[0].count )
                    type.chunk[0].count = ( data->current - i ) / typedef_size( typeb );
                else
                    data->current = i; /* Solo si ya habia sido alocada */

            }
            else if ( token.type == IDENTIFIER && token.code == identifier_equal )
            {
                /* if (basetype == TYPE_UNDEFINED) basetype = TYPE_INT; */
                i = compile_array_data( n, data, total_count, last_count, &basetype ) ;
                assert( basetype != TYPE_UNDEFINED ) ;
                set_type( &type, basetype ) ;
                if ( total_count == 0 )
                {
                    type.chunk[0].count = i;
                }
                else if ( i < total_count )
                {
                    for ( ; i < total_count; i++ )
                    {
                        if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                        segment_add_as( data, 0, basetype ) ;
                    }
                }
            }
            else if ( segm )
            {
                int string_offset = 0, j;

                if ( total_count == 0 ) compile_error( MSG_EXPECTED, "=" ) ;

                for ( i = 0; i < total_count; i++ )
                {
                    segment_add_from( data, segm ) ;
                    for ( j = 0; j < type.varspace->stringvar_count; j++ )
                        varspace_varstring( n, type.varspace->stringvars[j] + string_offset );
                    string_offset += type.varspace->size;
                }
                token_back() ;
            }
            else
            {
                if ( basetype == TYPE_UNDEFINED )
                {
                    basetype = TYPE_INT;
                    set_type( &type, basetype ) ;
                }

                if ( type.chunk[0].count == 0 ) compile_error( MSG_EXPECTED, "=" ) ;

                for ( i = 0; i < total_count; i++ )
                {
                    if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                    segment_add_as( data, 0, basetype ) ;
                }
                token_back() ;
            }
        }
        else if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) /* Compila una asignación de valores por defecto */
        {
            segment_add_from( data, segm ) ;
            i = data->current ;
            data->current = n->vars[n->count].offset ;
            if ( !additive ) data->current += base_offset;
            compile_struct_data( type.varspace, data, 1, 0 );
            data->current = i ;

        }
        else if ( token.type == IDENTIFIER && token.code == identifier_equal )
        {
            res = compile_expresion( 1, 0, 0, basetype ) ;

            if ( basetype == TYPE_UNDEFINED )
            {
                basetype = typedef_base( res.type ) ;
                if ( basetype == TYPE_UNDEFINED ) compile_error( MSG_INCOMP_TYPE ) ;
                set_type( &type, basetype ) ;
            }

            if ( basetype == TYPE_FLOAT )
            {
                segment_add_as( data, *( int * )&res.fvalue, basetype ) ;
            }
            else
            {
                if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                segment_add_as( data, res.value, basetype ) ;
            }

        }
        else if ( !segm ) /* Asigna valores por defecto (0) */
        {
            if ( basetype == TYPE_UNDEFINED )
            {
                basetype = TYPE_INT;
                set_type( &type, basetype ) ;
            }

            if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
            segment_add_as( data, 0, basetype ) ;
            token_back() ;

        }
        else
        {
            if ( typedef_is_struct( type ) )
                for ( i = 0 ; i < type.varspace->stringvar_count ; i++ )
                    varspace_varstring( n, type.varspace->stringvars[i] + n->size );
            segment_add_from( data, segm ) ;
            token_back() ;
        }

        n->size += typedef_size( type ) ;
        n->vars[n->count].type = type ;

        /* Variables tipo proceso, asigno varspace al tipo. Splinter */
        if ( proc ) n->vars[n->count].type.varspace = proc->pubvars;

        n->count++ ;

        token_next() ;

        if ( token.type == IDENTIFIER && token.code == identifier_comma )
        {
            token_back() ;
            continue ;
        }

        if ( token.type == IDENTIFIER && token.code == identifier_semicolon )
        {
            token_back() ;
            continue ;
        }

        compile_error( MSG_EXPECTED, ";" ) ;
        token_back() ;
        break ;
    }

    if ( padding && ( data->current % padding ) > 0 )
    {
        padding -= data->current % padding;
        data->current += padding;
        n->size += padding;

        if ( data->reserved <= data->current )
            segment_alloc( data, data->reserved - data->current + 32 );
    }

    n->last_offset = data->current ;
    total_length = data->current - base_offset ;

    /* n->size *= copies ; */
    while ( copies-- > 1 )
    {
        int i ;

        for ( i = 0 ; i < n->stringvar_count ; i++ )
        {
            if ( n->stringvars[i] >= base_offset && n->stringvars[i] < base_offset + total_length )
            {
                varspace_varstring( n, n->stringvars[i] - base_offset + data->current ) ;
            }
        }

        segment_copy( data, base_offset, total_length ) ;
        base_offset += total_length ;
    }

    return total_length ;
}