Esempio n. 1
0
void include_file( int bprepro )
{
    static char buffer[1024];
    char * buffer_ptr = buffer;
    int actual_line = line_count;

    SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
    if ( *source_ptr == '"' )
    {
        source_ptr++;
        buffer_ptr = buffer;
        while ( *source_ptr && *source_ptr != '"' )
        {
            if ( buffer_ptr == buffer + 1023 ) compile_error( MSG_IDENTIFIER_TOO_LONG );
            *buffer_ptr++ = *source_ptr++;
        }
        if ( *source_ptr == '"' ) source_ptr++;
        *buffer_ptr = 0;
        if ( bprepro )
        {
            SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
            if ( *source_ptr == '\n' ) line_count--;
        }
        else
        {
            SKIP_SPACES;
        }
        if ( *source_ptr == ';' )
        {
            if ( bprepro )
            {
                compile_warning( "extra tokens at end of #include directive" );
                SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
                if ( *source_ptr == '\n' ) line_count--;
            }
            else
                token_next();
        }

        load_file( buffer );
        token_next();
        return;
    }
    line_count = actual_line;
    compile_error( MSG_FILENAME_EXP );
}
Esempio n. 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 ;
}
Esempio n. 3
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 ;
}
Esempio n. 4
0
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 ;
}
Esempio n. 5
0
void token_next()
{
    static int  i, len;
    static char buffer[1024];
    char * buffer_ptr = buffer;

    if ( !source_ptr )
    {
        token.type = NOTOKEN;
        return;
    }

    if ( use_saved )
    {
        token        = token_saved;
        line_count   = token.line;
        current_file = token.file;
        use_saved    = 0;
        return;
    }
    token.line = line_count;
    token.file = current_file;
    token_prev = token;

    while ( 1 )
    {
        SKIP_SPACES;

        if ( !disable_prepro && *source_ptr == '#' )
        {
            int line;
            const char * old_source_ptr;

            identifiers_as_strings = 0;

            /* Comandos de preprocesador */
            source_ptr++;

            line = line_count;

            SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;

            if ( *source_ptr == '\n' )
            {
                token.code = identifier_search_or_add( "#" );
                token.type = IDENTIFIER;
                line_count = line;
                compile_error( MSG_IDENTIFIER_EXP );
            }

            old_source_ptr = source_ptr;

            if ( ISWORDFIRST( *source_ptr ) )
            {
                GET_NEXT_TOKEN_IN_TMPBUFFER;

                /* #include "file.h" */

                if ( token.code == identifier_include && !use_saved )
                {
                    include_file( 1 );
                    return;
                }

                source_ptr = old_source_ptr;
            }

            preprocessor();

            buffer_ptr = buffer;
            *buffer_ptr = '\0';
            continue;
        }

        if ( !*source_ptr )
        {
            /* Casos de bloques manuales */
            if ( current_file == -1 )
            {
                token_endfile();
                token.type = NOTOKEN;
                return;
            }

            while ( !*source_ptr )
            {
                if ( sources == 0 )
                {
                    token.type = NOTOKEN;
                    return;
                }

                token_endfile();

                if ( !source_ptr )
                {
                    token.type = NOTOKEN;
                    return;
                }
            }
            continue;
        }

        /* Ignora comentarios */

        SKIP_COMMENTS;
        if ( !*source_ptr )
        {
            token.type = NOTOKEN;
            return;
        }

        /* Cadenas */

        if ( *source_ptr == '"' || *source_ptr == '\'' )
        {
            token.type = STRING;
            token.code = string_compile( &source_ptr );
            token.line = line_count;
            token.file = current_file;
            return;
        }

        /* Operadores de más de un caracter */

        len = 0;

        if ( *source_ptr == '<' )
        {
            if ( source_ptr[1] == '<' )
            {
                if ( source_ptr[2] == '=' ) len = 3;
                else                      len = 2;
            }
            else if ( source_ptr[1] == '>' )    len = 2;
            else if ( source_ptr[1] == '=' )    len = 2;
            else                              len = 1;
        }
        else if ( *source_ptr == '>' )
        {
            if ( source_ptr[1] == '>' )
            {
                if ( source_ptr[2] == '=' ) len = 3;
                else                      len = 2;
            }
            else if ( source_ptr[1] == '=' )    len = 2;
            else if ( source_ptr[1] == '>' )    len = 2;
            else                              len = 1;
        }
        else if ( *source_ptr == '|' )
        {
            if ( source_ptr[1] == '|' )
            {
                if ( source_ptr[2] == '=' ) len = 3;
                else                      len = 2;
            }
            else if ( source_ptr[1] == '=' )    len = 2;
            else                              len = 1;
        }
        else if ( *source_ptr == '=' )
        {
            if ( source_ptr[1] == '=' )     len = 2;
            else if ( source_ptr[1] == '>' )    len = 2;
            else if ( source_ptr[1] == '<' )    len = 2;
            else                              len = 1;
        }
        else if ( *source_ptr == '.' )
        {
            if ( source_ptr[1] == '.' )     len = 2;
            else                          len = 1;
        }
        else if ( strchr( "!&^%*+-/", *source_ptr ) )
        {
            if ( source_ptr[1] == '=' )     len = 2;
            else if ( strchr( "+-&^", *source_ptr ) && source_ptr[1] == *source_ptr ) len = 2;
            else                          len = 1;
        }

        if ( len )
        {
            strncpy( buffer, source_ptr, len );
            buffer[len] = 0;
            source_ptr += len;
            token.code = identifier_search_or_add( buffer );
            token.type = IDENTIFIER;
            token.line = line_count;
            token.file = current_file;
            return;
        }

        /* Numbers */

        if ( ISNUM( *source_ptr ) )
        {
            const char * ptr;
            double num = 0, dec;
            int base = 10;

            /* Hex/Bin/Octal numbers with the h/b/o sufix */
            ptr = source_ptr;
            while ( ISNUM( *ptr ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) ptr++;

            if ( *ptr != 'h' && *ptr != 'H' && *ptr != 'o' && *ptr != 'O' && ( ptr[-1] == 'b' || ptr[-1] == 'B' ) ) ptr--;

            if ( *ptr == 'b' || *ptr == 'B' )
                base = 2;
            if ( *ptr == 'h' || *ptr == 'H' )
                base = 16;
            if ( *ptr == 'o' || *ptr == 'O' )
                base = 8;

            token.code = 0 ; /* for ints values */

            /* Calculate the number value */

            while ( ISNUM( *source_ptr ) || ( base > 10 && ISALNUM( *source_ptr ) ) )
            {
                if ( base == 2 && *source_ptr != '0' && *source_ptr != '1' ) break;
                if ( base == 8 && ( *source_ptr < '0' || *source_ptr > '7' ) ) break;
                if ( base == 10 && !ISNUM( *source_ptr ) ) break;
                if ( base == 16 && !ISNUM( *source_ptr ) && ( TOUPPER( *source_ptr ) < 'A' || TOUPPER( *source_ptr ) > 'F' ) ) break;

                if ( ISNUM( *source_ptr ) )
                {
                    num = num * base + ( *source_ptr - '0' );
                    token.code = token.code * base + ( *source_ptr - '0' );
                    source_ptr++;
                    continue;
                }
                if ( *source_ptr >= 'a' && *source_ptr <= 'f' && base > 10 )
                {
                    num = num * base + ( *source_ptr - 'a' + 10 );
                    token.code = token.code * base + ( *source_ptr - 'a' + 10 );
                    source_ptr++;
                    continue;
                }
                if ( *source_ptr >= 'A' && *source_ptr <= 'F' && base > 10 )
                {
                    num = num * base + ( *source_ptr - 'A' + 10 );
                    token.code = token.code * base + ( *source_ptr - 'A' + 10 );
                    source_ptr++;
                    continue;
                }
            }
            token.type = NUMBER;
            token.value = ( float )num;

            /* We have the integer part now - convert to int/float */

            if ( *source_ptr == '.' && base == 10 )
            {
                source_ptr++;
                if ( !ISNUM( *source_ptr ) )
                    source_ptr--;
                else
                {
                    dec = 1.0 / ( double )base;
                    while ( ISNUM( *source_ptr ) || ( base > 100 && ISALNUM( *source_ptr ) ) )
                    {
                        if ( ISNUM( *source_ptr ) ) num = num + dec * ( *source_ptr++ - '0' );
                        if ( *source_ptr >= 'a' && *source_ptr <= 'f' && base > 10 ) num = num + dec * ( *source_ptr++ - 'a' + 10 );
                        if ( *source_ptr >= 'A' && *source_ptr <= 'F' && base > 10 ) num = num + dec * ( *source_ptr++ - 'A' + 10 );
                        dec /= ( double )base;
                    }
                    token.type  = FLOAT;
                    token.value = ( float )num;
                }
            }

            /* Skip the base sufix */

            if ( base == 16 && ( *source_ptr == 'h' || *source_ptr == 'H' ) ) source_ptr++;
            if ( base == 8  && ( *source_ptr == 'o' || *source_ptr == 'O' ) ) source_ptr++;
            if ( base == 2  && ( *source_ptr == 'b' || *source_ptr == 'B' ) ) source_ptr++;

            token.line = line_count;
            token.file = current_file;
            return;
        }

        /* Identificadores */
        if ( ISWORDFIRST( *source_ptr ) )
        {
            int maybe_label = source_ptr[-1] == '\n';
            GET_NEXT_TOKEN_IN_TMPBUFFER;

            token.line = line_count;
            token.file = current_file;

            if ( maybe_label && *source_ptr == ':' )
            {
                source_ptr++;
                token.code = identifier_search_or_add( buffer );
                token.type = LABEL;
                return;
            }

            /* Search for #define constant inclusion at this point */

            if ( !disable_expand_defines )
            {
                if ( !strcmp( buffer, "__FILE__" ) )
                {
                    token.type = STRING;
                    token.code = string_new(( current_file != -1 && files[current_file] && *files[current_file] ) ? files[current_file] : "N/A" );
                    token.line = line_count;
                    token.file = current_file;
                    return;
                }

                if ( !strcmp( buffer, "__LINE__" ) )
                {
                    token.type = NUMBER;
                    token.code = ( int )line_count;
                    token.value = ( float )line_count;
                    token.line = line_count;
                    token.file = current_file;
                    return;
                }

                for ( i = 0; i < defines_count; i++ )
                {
                    if ( defines[i].code == token.code )
                    {
                        preprocessor_expand( &defines[i] );
                        token_next();
                        token.line = line_count;
                        token.file = current_file;
                        return;
                    }
                }
            }

            /* In a #if, all identifiers are strings */

            if ( identifiers_as_strings )
            {
                token.type = STRING;
                token.code = string_new( buffer );
                token.line = line_count;
                token.file = current_file;
                return;
            }

            /* Include */

            if ( !disable_prepro && token.code == identifier_include && !use_saved )
            {
                include_file( 0 );
                return;
            }
            return;
        }

        /* 1-char operator or invalid symbol */

        if ( !*source_ptr ) break;

        if ( *source_ptr > 0 && *source_ptr < 32 ) compile_error( MSG_INVALID_CHAR );

        *buffer_ptr++ = *source_ptr++;
        *buffer_ptr = 0;

        token.code = identifier_search_or_add( buffer );
        token.type = IDENTIFIER;
        token.line = line_count;
        token.file = current_file;

        return;
    }

    token.type = NOTOKEN;
    return;        /* End-of-file */
}
Esempio n. 6
0
void preprocessor()
{
    int i, ifdef;
    char * ptr;
    int actual_line_count;

    static int initialized = 0;

    if ( !initialized )
    {
        id_define  = identifier_search_or_add( "DEFINE" );
        id_undef   = identifier_search_or_add( "UNDEF" );
        id_ifdef   = identifier_search_or_add( "IFDEF" );
        id_ifndef  = identifier_search_or_add( "IFNDEF" );
        id_else    = identifier_search_or_add( "ELSE" );
        id_endif   = identifier_search_or_add( "ENDIF" );
        id_if      = identifier_search_or_add( "IF" );
        initialized = 1;
    }

    token_next();

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

    /* #define TEXT value */

    if ( token.code == id_define )
    {
        disable_expand_defines++;

        token_next();
        if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER );

        if ( find_define( token.code ) != -1 ) compile_error( MSG_MACRO_ERROR, identifier_name( token.code ) );

        /* Allocate the macro */

        if ( defines_allocated == defines_count )
        {
            defines_allocated += 8;
            defines = ( DEFINE * ) realloc( defines, sizeof( DEFINE ) * defines_allocated );
        }

        defines[defines_count].code = token.code;

        /* Check for parameters: no space allowed between name and ( */

        if ( *source_ptr == '(' )
        {
            source_ptr++;
            for ( defines[defines_count].param_count = i = 0; *source_ptr != ')'; )
            {
                if ( !*source_ptr ) compile_error( MSG_EXPECTED, ")" );
                if ( i == MAX_MACRO_PARAMS ) compile_error( MSG_TOO_MANY_PARAMS );
                token_next();

                if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_INVALID_IDENTIFIER );

                defines[defines_count].param_id[i++] = token.code;
                defines[defines_count].param_count++;

                SKIP_SPACES;
                if ( *source_ptr == ',' ) source_ptr++;
            }
            source_ptr++;
        }
        else
        {
            /* No parameters and no parenthesis */
            defines[defines_count].param_count = -1;
        }

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;

        ptr = ( char * ) source_ptr;

        while ( *ptr && *ptr != '\n' )
            if ( *ptr == '\\' && *( ptr + 1 ) == '\n' )
            {
                *ptr = ' ';
                ptr++;
                *ptr = ' ';
                ptr++;
                line_count++;
            }
            else
                ptr++;

        while ( ptr > source_ptr && ( !*ptr || ISSPACE( *ptr ) ) ) ptr--;

        defines[defines_count].text = ( char * )calloc( ptr - source_ptr + 2, sizeof( char ) );
        strncpy( defines[defines_count].text, source_ptr, ptr - source_ptr + 1 );
        defines[defines_count].text[ptr - source_ptr + 1] = 0;

        defines_count++;

        source_ptr = ptr + 1;

        disable_expand_defines--;

        return;
    }

    /* #undef TEXT */

    if ( token.code == id_undef )
    {
        disable_expand_defines++;

        token_next();
        if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER );

        if (( i = find_define( token.code ) ) != -1 )
        {
            defines_count--;
            if ( defines[i].text ) free( defines[i].text );
            memmove( &defines[i], &defines[i+1], ( defines_count - i ) * sizeof( DEFINE ) );
        }

        disable_expand_defines--;

        return;
    }

    /* #ifdef CONST / #ifndef CONST*/

    if ( token.code == id_ifdef || token.code == id_ifndef )
    {
        ifdef = token.code == id_ifdef;

        prepro_stack[prepro_sp++] = token.code;

        disable_expand_defines++;
        token_next();
        disable_expand_defines--;

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

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr && *source_ptr != '\n' )
        {
            if ( ifdef ) compile_warning( "extra tokens at end of #ifdef directive" );
            else compile_warning( "extra tokens at end of #ifndef directive" );
            SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
        }

        if ( *source_ptr == '\n' ) line_count--;

        for ( i = 0; i < defines_count; i++ )
        {
            if ( defines[i].code == token.code )
            {
                if ( ifdef ) return;
                break;
            }
        }
        if ( !ifdef && i == defines_count ) return;


        preprocessor_jumpto( id_else, id_endif );

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr && *source_ptr != '\n' )
        {
            if ( token.code == id_else ) compile_warning( "extra tokens at end of #else directive" );
            else if ( token.code == id_endif ) compile_warning( "extra tokens at end of #endif directive" );
            SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
        }
        if ( *source_ptr == '\n' ) line_count--;
        return;
    }

    /* #if */

    if ( token.code == id_if )
    {
        int actual_sources;
        expresion_result res;
        char c;

        prepro_stack[prepro_sp++] = token.code;

        ptr = ( char * ) source_ptr;

        while ( *ptr && *ptr != '\n' && *ptr != ';' )
            if ( *ptr == '\\' && *( ptr + 1 ) == '\n' )
            {
                *ptr = ' ';
                ptr++;
                *ptr = ' ';
                ptr++;
                line_count++;
            }
            else
                ptr++;

        c = *ptr;
        *ptr = '\0';

        actual_line_count = line_count;
        actual_sources = sources;

        token_init( source_ptr, current_file );

        identifiers_as_strings = 1;
        res = compile_expresion( 0, 0, 1, TYPE_DWORD );
        identifiers_as_strings = 0;
        /*
        printf ("exp: asignation: [%d] call: [%d] lvalue: [%d] constant: [%d] value: [%d] lvalue: [%f] type: [%d]\n",
                      res.asignation,
                      res.call,
                      res.lvalue,
                      res.constant,
                      res.value,
                      res.fvalue,
                      typedef_base(res.type));
        */
        if ( sources != actual_sources ) token_endfile();
        *ptr = c;
        source_ptr = ptr;
        line_count = actual_line_count;

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr && *source_ptr != '\n' )
        {
            compile_warning( "extra tokens at end of #if directive" );
            SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
        }
        if ( *source_ptr == '\n' ) line_count--;

        use_saved = 0;
        if ( !res.constant ) compile_error( MSG_CONSTANT_EXP );
        if ( !res.value )
        {
            preprocessor_jumpto( id_else, id_endif );

            SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
            if ( *source_ptr && *source_ptr != '\n' )
            {
                if ( token.code == id_else ) compile_warning( "extra tokens at end of #else directive" );
                else if ( token.code == id_endif ) compile_warning( "extra tokens at end of #endif directive" );
                SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
            }
            if ( *source_ptr == '\n' ) line_count--;
        }

        return;
    }

    /* #else */

    if ( token.code == id_else )
    {
        if ( !prepro_sp ) compile_error( "#else without #if" );

        int stck_code = prepro_stack[--prepro_sp];

        if ( prepro_sp < 0 ||
                (
                    stck_code != id_if &&
                    stck_code != id_ifdef &&
                    stck_code != id_ifndef
                )
           )
        {
            if ( stck_code == id_else )
            {
                compile_error( "#else after #else" );
            }
            else
            {
                compile_error( "#else without #if" );
            }
        }
        prepro_stack[prepro_sp++] = token.code;

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr && *source_ptr != '\n' )
        {
            compile_warning( "extra tokens at end of #else directive" );
            SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
        }
        if ( *source_ptr == '\n' ) line_count--;

        preprocessor_jumpto( id_endif, 0 );

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr && *source_ptr != '\n' )
        {
            compile_warning( "extra tokens at end of #endif directive" );
            SKIP_ALL_UNTIL_LF_AND_COUNT_LINES;
        }
        if ( *source_ptr == '\n' ) line_count--;
        return;
    }

    /* #endif */

    if ( token.code == id_endif )
    {
        int stck_code = prepro_stack[--prepro_sp];

        if ( prepro_sp < 0 || (
                    stck_code != id_else &&
                    stck_code != id_if &&
                    stck_code != id_ifdef &&
                    stck_code != id_ifndef ) ) compile_error( "#endif without #if" );

        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr == '\n' ) line_count--;
        return;
    }

    /* Unknown preprocessor directive */
    compile_error( MSG_UNKNOWN_PREP );
}
Esempio n. 7
0
void preprocessor_expand( DEFINE * def )
{
    const char * param_left[MAX_MACRO_PARAMS];
    const char * param_right[MAX_MACRO_PARAMS];
    const char * begin = NULL;
    const char * old_source = NULL;
    char * text;
    int i, count, depth, allocated, size, part, actual_line_count;

    /* No params - easy case */

    if ( def->param_count == -1 )
    {
        int line = line_count - 1;
        token_init( def->text, current_file );
        line_count = line;
        return;
    }

    /* Find left parenthesis */

    disable_expand_defines++;
    token_next();
    disable_expand_defines--;
    if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" );

    /* Mark parameters' starting and ending positions */

    if ( def->param_count > 0 )
    {
        for ( count = 0; count < def->param_count; count++ )
        {
            depth = 0;
            param_left[count] = source_ptr;

            while ( *source_ptr && ( depth > 0 || ( *source_ptr != ')' && *source_ptr != ',' ) ) )
            {
                if ( *source_ptr == '"' || *source_ptr == '\'' )
                {
                    begin = source_ptr++;
                    while ( *source_ptr && *source_ptr != *begin ) source_ptr++;
                    if ( !*source_ptr ) compile_error( MSG_EXPECTED, "\"" );
                    source_ptr++;
                    continue;
                }
                if ( *source_ptr == '(' ) depth++;
                if ( *source_ptr == ')' ) depth--;
                source_ptr++;
            }
            param_right[count] = source_ptr;
            if ( !*source_ptr ) compile_error( MSG_EXPECTED, ")" );
            if ( *source_ptr == ')' ) break;
            source_ptr++;
        }

        if ( count != def->param_count - 1 || *source_ptr != ')' )
            compile_error( MSG_INCORRECT_PARAMC, identifier_name( def->code ), def->param_count - 1 );
    }
    else
    {
        if ( *source_ptr != ')' )
            compile_error( MSG_INCORRECT_PARAMC, identifier_name( def->code ), def->param_count );
    }

    source_ptr++;

    /* Expand the macro */

    allocated = 128;
    size = 0;
    text = ( char * )calloc( allocated, sizeof( char ) );
    old_source = source_ptr;
    source_ptr = def->text;
    actual_line_count = line_count;

    while ( *source_ptr )
    {
        SKIP_SPACES_UNTIL_LF;
        if ( *source_ptr == '\n' ) break;

        begin = source_ptr;
        SKIP_SPACES_UNTIL_LF;
        if ( *source_ptr )
        {
            SKIP_SPACES_UNTIL_LF;
            if ( !*source_ptr ) break;
            if ( *source_ptr != '\n' )
            {
                disable_expand_defines++;
                token_next();
                disable_expand_defines--;
                if ( token.type == NOTOKEN ) break;
                if ( token.type == IDENTIFIER )
                {
                    /* Next token is an identifier. Search for parameter */

                    for ( i = 0; i < def->param_count; i++ )
                        if ( def->param_id[i] == token.code ) break;

                    if ( i != def->param_count )   /* Parameter found - expand it */
                    {

                        part = param_right[i] - param_left[i];
                        if ( size + part + 1 >= allocated )
                        {
                            allocated += (( part + 256 ) & ~ 127 );
                            text = ( char * )realloc( text, allocated );
                        }
                        text[size++] = ' ';
                        memcpy( text + size, param_left[i], part );
                        size += part;
                        continue;
                    }
                }

                /* No parameter found - copy the token */

                part = source_ptr - begin;
                if ( size + part + 1 >= allocated )
                {
                    allocated += (( part + 256 ) & ~127 );
                    text = ( char * )realloc( text, allocated );
                }
                memcpy( text + size, begin, part );
                size += part;
            }
            else
            {
                line_count++;
                source_ptr++;
            }
        }
    }

    text[size] = 0;
    source_ptr = old_source;
    line_count = actual_line_count;

    /* Now "include" the expanded text "file" */

    token_init( text, current_file );
    line_count = actual_line_count - 1;

    free( text );
}
Esempio n. 8
0
void preprocessor_jumpto( int id, int id2 )
{
    int depth = 1;
    use_saved = 0;

    disable_prepro = 1;

    while ( depth > 0 && *source_ptr )
    {
        SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
        if ( *source_ptr == '\n' )
        {
            source_ptr++;

            SKIP_SPACES;

            if ( *source_ptr == '#' )
            {
                source_ptr++;
                SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES;
                if ( *source_ptr == '\n' ) line_count--;

                token_next();
                if ( token.type == IDENTIFIER )
                {
                    if ( token.code == id_endif )
                    {
                        int stck_code = prepro_stack[--prepro_sp];

                        if ( prepro_sp < 0 || (
                                    stck_code != id_else &&
                                    stck_code != id_if &&
                                    stck_code != id_ifdef &&
                                    stck_code != id_ifndef ) )
                            compile_error( "#endif without #if" );
                    }
                    if ( token.code == id_else )
                    {
                        int stck_code = prepro_stack[--prepro_sp];

                        if ( prepro_sp < 0 ||
                                (
                                    stck_code != id_if &&
                                    stck_code != id_ifdef &&
                                    stck_code != id_ifndef
                                )
                           )
                        {
                            if ( stck_code == id_else )
                            {
                                compile_error( "#else after #else" );
                            }
                            else
                            {
                                compile_error( "#else without #if" );
                            }
                        }
                        prepro_stack[prepro_sp++] = token.code;
                    }
                    else if ( token.code == id_ifdef || token.code == id_ifndef || token.code == id_if )
                    {
                        prepro_stack[prepro_sp++] = token.code;
                    }

                    if ( token.code == id_endif /*id || (id2 && token.code == id2)*/ )
                    {
                        depth--;
                    }
                    else if ( token.code == id_else )
                    {
                        depth--;
                        if ( !depth ) break;
                        depth++;
                    }
                    else if ( token.code == id_ifdef || token.code == id_ifndef || token.code == id_if )
                    {
                        depth++;
                    }
                }
                continue;
            }
        }
        source_ptr++;
    }

    if ( token.code != id && ( id2 && token.code != id2 ) ) compile_error( "unbalanced #if/#else/#endif" );

    if ( depth > 0 ) compile_error( "unterminate #if" );

    disable_prepro = 0;

}