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); }
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 ; }
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); }
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 ; }