diff options
Diffstat (limited to 'core/bgdc/src/c_data.c')
-rw-r--r-- | core/bgdc/src/c_data.c | 960 |
1 files changed, 960 insertions, 0 deletions
diff --git a/core/bgdc/src/c_data.c b/core/bgdc/src/c_data.c new file mode 100644 index 0000000..83ef97d --- /dev/null +++ b/core/bgdc/src/c_data.c @@ -0,0 +1,960 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include <stdio.h> +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif +#include <string.h> +#include <stdlib.h> + +#include "bgdc.h" +#include "xctype.h" + +/* ---------------------------------------------------------------------- */ +/* Este módulo contiene las funciones que compilan definiciones de datos: */ +/* declaraciones de variables e inicialización de las mismas */ +/* ---------------------------------------------------------------------- */ + +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 ; +} + +static BASETYPE get_basetype( VARSPACE * v ) +{ + TYPEDEF t ; + BASETYPE type = TYPE_UNDEFINED, newtype ; + int n ; + + for ( n = 0 ; n < v->count ; n++ ) + { + t = v->vars[n].type ; + while ( typedef_is_array( t ) ) + { + t = typedef_reduce( t ) ; + } + + if ( typedef_is_struct( t ) ) + { + newtype = get_basetype( typedef_members( t ) ) ; + } + else + { + newtype = typedef_base( t ) ; + } + + if ( type != TYPE_UNDEFINED && type != newtype ) + { + return TYPE_UNDEFINED ; + } + + type = newtype ; + } + return type ; +} + +/* + * FUNCTION : compile_struct_data + * + * Compile the values of an struct initialization + * Does not suppor parenthized sections or the DUP operator + * + * PARAMS: + * n Current variable space + * data Current data segment + * size Size (total number of variables) of the array + * including all dimensions (1 for single struct) + * sub 1 if the struct we'are initializing is part of + * another one + * (the function will then ignore a trailing comma) + * + * RETURN VALUE: + * Number of structs initialized + */ + +int compile_struct_data( VARSPACE * n, segment * data, int size, int sub ) +{ + int elements = 0 ; + int position = 0 ; + expresion_result res ; + + for ( ;; ) + { + token_next() ; + + /* Allow parenthized struct initialization */ + if ( token.type == IDENTIFIER && token.code == identifier_leftp ) + { + if (( elements % n->count ) != 0 ) compile_error( MSG_NOT_ENOUGH_INIT ); + + /* Note - don't ignore a trailing comma! */ + elements = compile_struct_data( n, data, size, 0 ) ; + + if ( elements >= n->count ) size -= ( elements / n->count ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; + + token_next() ; + if (( elements % n->count ) == 0 && size > 0 && token.type == IDENTIFIER && token.code == identifier_comma ) + continue; + + token_back() ; + return elements ; + } + + /* Allow empty initialization */ + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) return 0 ; + + token_back() ; + + for ( ;; ) + { + TYPEDEF next_type = n->vars[position].type ; + + /* Next variable is a pointer */ + + if ( typedef_is_pointer( next_type ) ) + { + res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ; + if ( !res.constant ) compile_error( MSG_INCORRECT_PTR_INIT ); + segment_add_as( data, 0, TYPE_POINTER ) ; + } + else if ( typedef_is_array( next_type ) ) /* Next variable is an array */ + { + int elements = typedef_tcount( next_type ) ; + BASETYPE base; + + /* Get the array base type */ + + while ( typedef_is_array( next_type ) ) next_type = typedef_reduce( next_type ); + + base = typedef_base( next_type ); + + /* Special case: array of structs */ + + if ( base == TYPE_STRUCT ) + { + compile_struct_data( next_type.varspace, data, elements, 1 ); + + } + else + { + token_next(); + + /* Special case: intializing char[] strings */ + + if ( token.type == STRING && next_type.chunk[1].type == TYPE_CHAR ) + { + const char * str = string_get( token.code ) ; + int subcount = 0 ; + + if (( int )strlen( str ) > typedef_count( next_type ) - 1 ) compile_error( MSG_TOO_MANY_INIT ) ; + + while ( *str ) + { + segment_add_as( data, *str++, TYPE_CHAR ) ; + subcount++ ; + } + + while ( subcount++ < typedef_count( next_type ) ) segment_add_as( data, 0, TYPE_CHAR ) ; + + } + else /* Initializing normal arrays */ + { + int has_parents = 1; + + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) + { + has_parents = 0; + token_back(); + } + + compile_array_data( n, data, elements, elements, &base ) ; + + if ( has_parents ) + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; + } + } + } + } + else if ( typedef_is_struct( next_type ) ) /* Next variable is another struct */ + { + compile_struct_data( next_type.varspace, data, 1, 1 ) ; + } + else /* Next variable is a single type */ + { + res = compile_expresion( 1, 0, 0, typedef_base( next_type ) ) ; + if ( !res.constant ) compile_error( MSG_CONSTANT_EXP ); + segment_add_as( data, typedef_base( next_type ) == TYPE_FLOAT ? *( int* )&res.fvalue : res.value, typedef_base( next_type ) ) ; + } + + position++ ; + elements++ ; + + if ( position == n->count && size < 2 && sub ) break ; + + /* A comma should be here */ + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) + { + token_back(); + break ; + } + + if ( token.type == IDENTIFIER && token.code == identifier_rightp ) + { + token_back() ; + break ; + } + + if ( token.type != IDENTIFIER || token.code != identifier_comma ) compile_error( MSG_EXPECTED, "," ) ; + + /* Wrap around for the next struct */ + + if ( position == n->count ) + { + if ( size == 1 && !sub ) compile_error( MSG_TOO_MANY_INIT ) ; + size--; + position = 0; + } + } + break; + } + + return elements ; +} + +static void set_type( TYPEDEF * t, BASETYPE type ) +{ +/* + int n ; + + for ( n = 0 ; n < t->depth ; n++ ) + if ( t->chunk[n].type == TYPE_UNDEFINED ) + { + t->chunk[n].type = type ; + break ; + } + return ; +*/ + t->chunk[t->depth-1].type = type ; +} + +/* + * FUNCTION : compile_varspace + * + * Compile a variable space (a LOCAL, PRIVATE or GLOBAL section, or part of a STRUCT data) + * + * PARAMS : + * n Pointer to the VARSPACE object (already initialized) + * data Pointer to the data segment. All variables are added at end. + * additive 1 if the compiling is additive (the struct members have non-local offset; GLOBAL case) + * or not (STRUCT case) + * copies Number of data copies (if the STRUCT is part of an array) + * collision Check this varspace array for name collisions (NULL = end of array), + * if nonzero (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) + * alignment Byte size for member alignment. Empty data will be added + * to the varspace if its size is not multiple of this value. + * + * In any case, nested varspaces (structs) will have an alignment of 0. + * + * RETURN VALUE : + * None + * + */ + +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 - jj_arg@yahoo.com) */ + 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 - jj_arg@yahoo.com) */ + + 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 ; +} |