aboutsummaryrefslogtreecommitdiff
path: root/core/bgdc/src/c_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/bgdc/src/c_data.c')
-rw-r--r--core/bgdc/src/c_data.c960
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 ;
+}