コード例 #1
0
ファイル: mod_dir.c プロジェクト: GarethNelson/BennuGD
static int __moddir_read(__DIR_ST * dh )
{
    __DIR_FILEINFO_ST * dif;
    char buffer[ 20 ];
    int result;

    dif = dir_read( dh );
    if ( !dif )
    {
        result = string_new( "" );
        string_use( result );
        return ( result );
    }

    /* discard previous strings values */
    string_discard( GLODWORD( mod_dir, FILE_NAME ) );
    string_discard( GLODWORD( mod_dir, FILE_PATH ) );
    string_discard( GLODWORD( mod_dir, FILE_CREATED ) );
    string_discard( GLODWORD( mod_dir, FILE_MODIFIED ) );
    string_discard( GLODWORD( mod_dir, FILE_ACCESSED ) );
    string_discard( GLODWORD( mod_dir, FILE_STATECHG ) );

    GLODWORD( mod_dir, FILE_NAME        ) = string_new( dif->filename ); string_use( GLODWORD( mod_dir, FILE_NAME ) );
    GLODWORD( mod_dir, FILE_PATH        ) = string_new( dif->fullpath ); string_use( GLODWORD( mod_dir, FILE_PATH ) );

    GLODWORD( mod_dir, FILE_DIRECTORY   ) = dif->attributes & DIR_FI_ATTR_DIRECTORY ? 1 : 0;
    GLODWORD( mod_dir, FILE_HIDDEN      ) = dif->attributes & DIR_FI_ATTR_HIDDEN    ? 1 : 0;
    GLODWORD( mod_dir, FILE_READONLY    ) = dif->attributes & DIR_FI_ATTR_READONLY  ? 1 : 0;
    GLODWORD( mod_dir, FILE_SIZE        ) = dif->size;

    /* Store file times */
#ifdef _WIN32
    strftime( buffer, 20, "%d/%m/%Y %H:%M:S", &dif->mtime );
    GLODWORD( mod_dir, FILE_CREATED     ) = string_new( buffer ); string_use( GLODWORD( mod_dir, FILE_CREATED  ) );
#else
    GLODWORD( mod_dir, FILE_CREATED     ) = string_new( "" ); string_use( GLODWORD( mod_dir, FILE_CREATED  ) );
#endif

    strftime( buffer, 20, "%d/%m/%Y %H:%M:S", &dif->crtime );
    GLODWORD( mod_dir, FILE_MODIFIED    ) = string_new( buffer ); string_use( GLODWORD( mod_dir, FILE_MODIFIED ) );

    strftime( buffer, 20, "%d/%m/%Y %H:%M:S", &dif->atime );
    GLODWORD( mod_dir, FILE_ACCESSED    ) = string_new( buffer ); string_use( GLODWORD( mod_dir, FILE_ACCESSED ) );

#ifndef _WIN32
    strftime( buffer, 20, "%d/%m/%Y %H:%M:S", &dif->ctime );
    GLODWORD( mod_dir, FILE_STATECHG    ) = string_new( buffer ); string_use( GLODWORD( mod_dir, FILE_STATECHG ) );
#else
    GLODWORD( mod_dir, FILE_STATECHG    ) = string_new( "" ); string_use( GLODWORD( mod_dir, FILE_STATECHG ) );
#endif

    /* Return */
    result = GLODWORD( mod_dir, FILE_NAME );
    string_use( result );
    return result;
}
コード例 #2
0
ファイル: mod_dir.c プロジェクト: GarethNelson/BennuGD
static int moddir_glob( INSTANCE * my, int * params )
{
    const char * path = string_get( params[ 0 ] );
    static __DIR_ST * dh = NULL;
    int result;

    if ( dh && strcmp( dh->path, path ) )
    {
        dir_close( dh );
        dh = NULL;
    }

    if ( !dh ) dh = dir_open( path );

    string_discard( params[ 0 ] );

    if ( !dh )
    {
        result = string_new( "" );
        string_use( result );
        return ( result );
    }

    return ( __moddir_read( dh ) ) ;
}
コード例 #3
0
ファイル: libjoy.c プロジェクト: segafan/bennugd-monolithic
int libjoy_name( int joy )
{
    int result;
    result = string_new( SDL_JoystickName( joy ) );
    string_use( result );
    return result;
}
コード例 #4
0
ファイル: mod_file.c プロジェクト: segafan/bennugd-monolithic
static int modfile_file( INSTANCE * my, int * params )
{
    char buffer[1025] ;
    int str = string_new( "" ) ;
    file * f ;
    int l;

    f = file_open( string_get( params[0] ), "rb" ) ;
    string_discard( params[0] ) ;

    if ( f )
    {
        while ( !file_eof( f ) )
        {
            l = file_read( f, buffer, sizeof( buffer ) - 1 ) ;
            buffer[l] = '\0' ;
            if ( l )
            {
                string_concat( str, buffer ) ;
                buffer[0] = '\0' ;
            }
            else
                break;
        }
        file_close( f ) ;
    }

    string_use( str ) ;

    return str ;
}
コード例 #5
0
ファイル: mod_dir.c プロジェクト: GarethNelson/BennuGD
static int moddir_cd( INSTANCE * my, int * params )
{
    char * d = dir_current() ;
    int r = string_new( d ) ;
    string_use( r ) ;
    if ( d ) free( d ) ;
    return r ;
}
コード例 #6
0
static int modcd_name( INSTANCE * my, int * params )
{
    int result;

    if ( params[0] < 0 || params[0] >= SDL_CDNumDrives() ) return 0;

    result = string_new( SDL_CDName( params[0] ) );
    string_use( result );
    return result;
}
コード例 #7
0
static int modregex_regex (INSTANCE * my, int * params)
{
    const char * reg = string_get(params[0]);
    const char * str = string_get(params[1]);
    int result = -1;
    unsigned n;

    struct re_pattern_buffer pb;
    struct re_registers re;
    int start[16];
    int end[16];
    int * regex_reg;

    /* Alloc the pattern resources */

    memset (&pb, 0, sizeof(pb));
    memset (&re, 0, sizeof(re));
    pb.buffer = malloc(4096);
    pb.allocated = 4096;
    pb.fastmap = malloc(256);
    pb.regs_allocated = 16;
    re.num_regs = 16;
    re.start = start;
    re.end = end;

    re_syntax_options = RE_SYNTAX_POSIX_MINIMAL_EXTENDED | REG_ICASE;

    /* Match the regex */

    if (re_compile_pattern (reg, strlen(reg), &pb) == 0)
    {
        result = re_search (&pb, str, strlen(str), 0, strlen(str), &re);

        if (result != -1)
        {
            /* Fill the regex_reg global variables */
            regex_reg = (int *) &GLODWORD( mod_regex, REGEX_REG);
            for (n = 0 ; n < 16 && n <= pb.re_nsub ; n++)
            {
                string_discard (regex_reg[n]);
                regex_reg[n] = string_newa (str + re.start[n], re.end[n] - re.start[n]);
                string_use (regex_reg[n]);
            }
        }
    }

    /* Free the resources */
    free (pb.buffer);
    free (pb.fastmap);
    string_discard(params[0]);
    string_discard(params[1]);

    return result;
}
コード例 #8
0
ファイル: mod_sys.c プロジェクト: GarethNelson/BennuGD
static int modsys_getenv( INSTANCE * my, int * params )
{
    char *e ;
    int str ;

    if (( e = getenv( string_get( params[0] ) ) ) )
    {
        str = string_new( e ) ;
    }
    else
    {
        str = string_new( "" ) ;
    }

    string_discard( params[0] ) ;
    string_use( str ) ;
    return str ;
}
コード例 #9
0
ファイル: mod_file.c プロジェクト: segafan/bennugd-monolithic
static int modfile_fgets( INSTANCE * my, int * params )
{
    char buffer[1025] ;
    int len, done = 0 ;
    int str = string_new( "" );

    while ( !done )
    {
        len = file_gets(( file * )params[0], buffer, sizeof( buffer ) - 1) ;
        if ( len < 1 ) break;

        if ( buffer[len-1] == '\r' || buffer[len-1] == '\n' )
        {
            len--;
            if ( len && ( buffer[len-1] == '\r' || buffer[len-1] == '\n' )) len--;
            buffer[len] = '\0' ;
            done = 1;
        }
        string_concat( str, buffer );
    }
    string_use( str ) ;
    return str ;
}
コード例 #10
0
static int modregex_join (INSTANCE * my, int * params)
{
    const char * sep = string_get(params[0]);
    int * string_array = (int *)params[1];
    int count = params[2] ;
    int total_length = 0;
    int sep_len = strlen(sep);
    int n;
    char * buffer;
    char * ptr;
    int result;

    for (n = 0 ; n < count ; n++)
    {
        total_length += strlen(string_get(string_array[n]));
        if (n < count-1) total_length += sep_len;
    }

    buffer = malloc(total_length+1);
    ptr = buffer;

    for (n = 0 ; n < count ; n++)
    {
        memcpy (ptr, string_get(string_array[n]), strlen(string_get(string_array[n])));
        ptr += strlen(string_get(string_array[n]));
        if (n < count-1)
        {
            memcpy (ptr, sep, sep_len);
            ptr += sep_len;
        }
    }
    *ptr = 0;
    result = string_new(buffer);
    free(buffer);
    string_use(result);
    return result;
}
コード例 #11
0
ファイル: instance.c プロジェクト: segafan/bennugd-monolithic
INSTANCE * instance_new( PROCDEF * proc, INSTANCE * father )
{
    INSTANCE * r, * brother;
    int n, pid;

    if ( ( pid = instance_getid() ) == -1 ) return NULL;

    r = ( INSTANCE * ) calloc( 1, sizeof( INSTANCE ) ) ;
    assert( r ) ;

    r->pridata          = ( int * ) malloc( proc->private_size + 4 ) ;
    r->pubdata          = ( int * ) malloc( proc->public_size + 4 ) ;
    r->locdata          = ( int * ) malloc( local_size + 4 ) ;
    r->code             = proc->code ;
    r->codeptr          = proc->code ;
    r->exitcode         = proc->exitcode ;
    r->errorcode        = proc->errorcode ;
    r->proc             = proc ;
    r->call_level       = 0 ;

    r->switchval        = 0;
    r->switchval_string = 0;
    r->cased            = 0;

    r->breakpoint       = 0 ;

    r->private_size     = proc->private_size ;
    r->public_size      = proc->public_size ;
    r->first_run        = 1 ;

    if ( proc->private_size > 0 ) memcpy( r->pridata, proc->pridata, proc->private_size ) ;
    if ( proc->public_size > 0 ) memcpy( r->pubdata, proc->pubdata, proc->public_size ) ;
    if ( local_size > 0 ) memcpy( r->locdata, localdata, local_size ) ;

    /* Inicializa datos de jerarquia */

    LOCDWORD( r, PROCESS_TYPE ) = proc->type ;
    LOCDWORD( r, PROCESS_ID )   = pid ;
    LOCDWORD( r, SON )          = 0 ;
    LOCDWORD( r, SMALLBRO )     = 0 ;

    if ( father )
    {
        LOCDWORD( r, FATHER )     = LOCDWORD( father, PROCESS_ID ) ;
        brother = instance_get( LOCDWORD( father, SON ) ) ;
        if ( brother )
        {
            LOCDWORD( r, BIGBRO )         = LOCDWORD( brother, PROCESS_ID ) ;
            LOCDWORD( brother, SMALLBRO ) = pid ;
        }
        else
        {
            LOCDWORD( r, BIGBRO )         = 0 ;
        }
        LOCDWORD( father, SON )    = pid ;
    }
    else
    {
        LOCDWORD( r, FATHER )     = 0 ;
        LOCDWORD( r, BIGBRO )     = 0 ;
    }

    /* Cuenta los usos de las variables tipo cadena */

    for ( n = 0; n < proc->string_count; n++ ) string_use( PRIDWORD( r, proc->strings[n] ) ) ;  /* Strings privadas */
    for ( n = 0; n < proc->pubstring_count; n++ ) string_use( PUBDWORD( r, proc->pubstrings[n] ) ) ; /* Strings publicas */
    for ( n = 0; n < local_strings; n++ ) string_use( LOCDWORD( r, localstr[n] ) ) ; /* Strings locales */

    r->prev = NULL ;
    r->next = first_instance ;
    if ( first_instance ) first_instance->prev = r;
    first_instance = r ;

    instance_add_to_list_by_id( r, pid );
    instance_add_to_list_by_instance( r );
    instance_add_to_list_by_type( r, proc->type );
    instance_add_to_list_by_priority( r, 0 );

    /* The called_by pointer should be set only when the caller
     * is waiting for this process to return */

    r->called_by = NULL;

    r->stack = malloc( STACK_SIZE );
    r->stack_ptr = &r->stack[1];
    r->stack[0] = STACK_SIZE;

    /* Initialize list pointers */

    LOCDWORD( r, STATUS ) = STATUS_RUNNING;

    if ( instance_create_hook_count )
        for ( n = 0; n < instance_create_hook_count; n++ )
            instance_create_hook_list[n]( r );

    return r ;
}
コード例 #12
0
ファイル: instance.c プロジェクト: segafan/bennugd-monolithic
INSTANCE * instance_duplicate( INSTANCE * father )
{
    INSTANCE * r, * brother ;
    int n, pid ;
    uint32_t type ;

    if ( ( pid = instance_getid() ) == -1 ) return NULL;

    r = ( INSTANCE * ) calloc( 1, sizeof( INSTANCE ) ) ;
    assert( r ) ;

    r->pridata          = ( int * ) malloc( father->private_size + 4 ) ;
    r->pubdata          = ( int * ) malloc( father->public_size + 4 ) ;
    r->locdata          = ( int * ) malloc( local_size + 4 ) ;
    r->code             = father->code ;
    r->codeptr          = father->codeptr ;
    r->exitcode         = father->exitcode ;
    r->errorcode        = father->errorcode ;
    r->proc             = father->proc ;
    r->call_level       = father->call_level ;

    r->switchval        = 0;
    r->switchval_string = 0;
    r->cased            = 0;

    r->breakpoint       = 0 ;

    r->private_size     = father->private_size ;
    r->public_size      = father->public_size ;
    r->first_run        = 1 ;

    if ( father->private_size > 0 ) memcpy( r->pridata, father->pridata, r->private_size ) ;
    if ( father->public_size > 0 ) memcpy( r->pubdata, father->pubdata, r->public_size ) ;
    if ( local_size > 0 ) memcpy( r->locdata, father->locdata, local_size ) ;

    /* Inicializa datos de jerarquia */

    /* Crea el proceso clónico como si lo hubiera llamado el padre */

    type = LOCDWORD( father, PROCESS_TYPE ) ;
    LOCDWORD( r, PROCESS_ID )   = pid ;
    LOCDWORD( r, SON )          = 0 ;
    LOCDWORD( r, SMALLBRO )     = 0 ;

    LOCDWORD( r, FATHER )       = LOCDWORD( father, PROCESS_ID ) ;
    brother = instance_get( LOCDWORD( father, SON ) ) ;
    if ( brother )
    {
        LOCDWORD( r, BIGBRO )         = LOCDWORD( brother, PROCESS_ID ) ;
        LOCDWORD( brother, SMALLBRO ) = pid ;
    }
    else
    {
        LOCDWORD( r, BIGBRO )         = 0 ;
    }
    LOCDWORD( father, SON )      = pid ;

    /* Actualiza las cuentas de uso de las cadenas */

    for ( n = 0; n < r->proc->string_count; n++ ) string_use( PRIDWORD( r, r->proc->strings[n] ) ) ;  /* Strings privadas */
    for ( n = 0; n < r->proc->pubstring_count; n++ ) string_use( PUBDWORD( r, r->proc->pubstrings[n] ) ) ; /* Strings publicas */
    for ( n = 0; n < local_strings; n++ ) string_use( LOCDWORD( r, localstr[n] ) ) ; /* Strings locales */

    r->prev = NULL ;
    r->next = first_instance ;
    if ( first_instance ) first_instance->prev = r;
    first_instance = r ;

    instance_add_to_list_by_id( r, pid );
    instance_add_to_list_by_instance( r );
    instance_add_to_list_by_type( r, type );
    instance_add_to_list_by_priority( r, LOCINT32( r, PRIORITY ) );

    /* The called_by pointer should be set only when the caller
     * is waiting for this process to return */

    r->called_by = NULL;

    r->stack = malloc( father->stack[0] );
    memmove(r->stack, father->stack, (int)father->stack_ptr - (int)father->stack);
    r->stack_ptr = &r->stack[1];

    /* Initialize list pointers */

    LOCDWORD( r, STATUS ) = STATUS_RUNNING;

    if ( instance_create_hook_count )
        for ( n = 0; n < instance_create_hook_count; n++ )
            instance_create_hook_list[n]( r );

    return r ;
}
コード例 #13
0
ファイル: mod_time.c プロジェクト: luislasonbra/bennugd-wii
int modtime_ftime( INSTANCE * my, int * params )
{
    char buffer[128] ;
    char * format ;
    struct tm * t ;
    int ret ;
    time_t tim ;
    char * base ;

#ifdef _WIN32
    /* aux buffer to make all changes... */
    char aux[128] ;
    unsigned char pos ;
#endif

    format = base = strdup( string_get( params[0] ) ) ;
    string_discard( params[0] ) ;

#ifdef _WIN32
    /* Addapting win32 strftime formats to linux formats */
    /* HEAVY PATCH... :( */
    pos = 0 ;
    while ( *format && pos < 127 )
    {
        switch ( *format )
        {
            case '%': /* MIGHT NEED CONVERSION... */
                aux[pos] = *format ;
                pos++ ;
                format++ ;
                switch ( *format )
                {
                    case 'e':
                        aux[pos++] = '#' ;
                        aux[pos] = 'd' ;
                        break ;
                    case 'l':
                        aux[pos++] = '#' ;
                        aux[pos] = 'I' ;
                        break ;
                    case 'k':
                        aux[pos++] = '#' ;
                        aux[pos] = 'H' ;
                        break ;
                    case 'P':
                        aux[pos] = 'p' ;
                        break ;

                    case 'C':
                        aux[pos++] = '%' ;
                        aux[pos++] = *format ;
                        aux[pos++] = '%' ;
                        aux[pos] = 'Y' ;
                        break ;

                    case 'u':
                        aux[pos++] = '%' ;
                        aux[pos++] = *format ;
                        aux[pos++] = '%' ;
                        aux[pos] = 'w' ;
                        break ;

                    case '%':   //MUST BE %%%% TO KEEP 2 IN POSTPROCESS
                        aux[pos++] = '%' ;
                        aux[pos++] = '%' ;
                        aux[pos] = '%' ;
                        break ;

                    default:
                        aux[pos] = *format ;
                        break ;
                }
                break ;

            default: aux[pos] = *format ;
                break ;
        }
        format++ ;
        pos++ ;
    }
    aux[pos] = 0 ;
    format = aux ;
#endif

    tim = ( time_t ) params[1] ;
    t = localtime( &tim ) ;
    strftime( buffer, sizeof( buffer ), format, t ) ;

#ifdef _WIN32
    /* win32 postprocess */
    aux[0] = '\0' ;
    format = buffer ;
    pos = 0 ;
    while ( *format )
    {
        switch ( *format )
        {
            case '%':
                format++ ;
                switch ( *format )
                {
                    case 'u':
                        format++ ;
                        if ( *format == '0' ) *format = '7' ;
                        aux[pos] = *format ;
                        break ;

                    case 'C':
                        format++ ;
                        aux[pos++] = *format ;
                        format++ ;
                        aux[pos] = *format ;
                        format++ ;
                        format++ ;
                        break ;

                    default:
                        aux[pos] = *format ;
                        break ;
                }
                break ;

            default:
                aux[pos] = *format ;
                break ;
        }
        format++ ;
        pos++;
    }
    aux[pos] = '\0' ;
    strcpy( buffer, aux ) ;
#endif

    ret = string_new( buffer ) ;
    string_use( ret ) ;

    free( base ) ;

    return ret ;
}
コード例 #14
0
static int modregex_split (INSTANCE * my, int * params)
{
    const char * reg = string_get(params[0]);
    const char * str = string_get(params[1]);
    int * result_array = (int *)params[2];
    int result_array_size = params[3];
    int count = 0;
    int pos, lastpos = 0;

    struct re_pattern_buffer pb;
    struct re_registers re;
    int start[16];
    int end[16];

    /* Alloc the pattern resources */

    memset (&pb, 0, sizeof(pb));
    memset (&re, 0, sizeof(re));
    pb.buffer = malloc(4096);
    pb.allocated = 4096;
    pb.fastmap = malloc(256);
    pb.regs_allocated = 16;
    re.num_regs = 16;
    re.start = start;
    re.end = end;

    re_syntax_options = RE_SYNTAX_POSIX_MINIMAL_EXTENDED;

    /* Match the regex */

    if (re_compile_pattern (reg, strlen(reg), &pb) == 0)
    {
        for (;;)
        {
            pos = re_search (&pb, str, strlen(str), lastpos, strlen(str), &re);
            if (pos == -1) break;
            *result_array = string_newa (str + lastpos, pos-lastpos);
            string_use(*result_array);
            result_array++;
            count++;
            result_array_size--;
            if (result_array_size == 0) break;
            lastpos = pos + re_match (&pb, str, strlen(str), pos, 0);
            if (lastpos < pos) break;
            if (lastpos == pos) lastpos++;
        }
        if (result_array_size > 0)
        {
            *result_array = string_new (str + lastpos);
            string_use (*result_array);
            count++;
        }
    }

    /* Free the resources */
    free (pb.buffer);
    free (pb.fastmap);
    string_discard(params[0]);
    string_discard(params[1]);

    return count;
}
コード例 #15
0
static int modregex_regex_replace (INSTANCE * my, int * params)
{
    const char * reg = string_get(params[0]);
    const char * rep = string_get(params[1]);
    const char * str = string_get(params[2]);

    unsigned reg_len = strlen(reg);
    unsigned str_len = strlen(str);
    unsigned rep_len = strlen(rep);
    char * replacement;
    unsigned replacement_len;
    int fixed_replacement = strchr(rep, '\\') ? 0:1;

    struct re_pattern_buffer pb;
    struct re_registers re;
    int start[16];
    int end[16];

    unsigned startpos = 0;
    unsigned nextpos;
    int regex_filled = 0;

    char * result = 0;
    unsigned result_allocated = 0;
    int result_string = 0;

    unsigned n;
    int * regex_reg;

    /* Alloc a buffer for the resulting string */

    result = malloc(128);
    result_allocated = 128;
    *result = 0;

    /* Alloc the pattern resources */

    memset (&pb, 0, sizeof(pb));
    memset (&re, 0, sizeof(re));
    pb.buffer = malloc(4096);
    pb.allocated = 4096;
    pb.used = 0;
    pb.fastmap = malloc(256);
    pb.translate = NULL;
    pb.fastmap_accurate = 0;
    pb.regs_allocated = 16;
    re.start = start;
    re.end = end;

    re_syntax_options = RE_SYNTAX_POSIX_MINIMAL_EXTENDED;

    /* Run the regex */

    if (re_compile_pattern (reg, reg_len, &pb) == 0)
    {
        startpos = 0;

        while (startpos < str_len)
        {
            nextpos = re_search (&pb, str, str_len, startpos,
                str_len - startpos, &re);
            if ((int)nextpos < 0) break;

            /* Fill the REGEX_REG global variables */

            if (regex_filled == 0)
            {
                regex_filled = 1;
                regex_reg = (int *)&GLODWORD( mod_regex, REGEX_REG);
                for (n = 0 ; n < 16 && n <= pb.re_nsub ; n++)
                {
                    string_discard (regex_reg[n]);
                    regex_reg[n] = string_newa (str + re.start[n], re.end[n] - re.start[n]);
                    string_use (regex_reg[n]);
                }
            }

            /* Prepare the replacement string */

            if (fixed_replacement == 0)
            {
                int total_length = rep_len;
                const char * bptr;
                char *  ptr;

                /* Count the size */

                ptr = strchr(rep, '\\');
                while (ptr)
                {
                    if (ptr[1] >= '0' && ptr[1] <= '9')
                        total_length += re.end[ptr[1]-'0'] - re.start[ptr[1]-'0'] - 2;
                    ptr = strchr(ptr+1, '\\');
                }

                /* Fill the replacement string */

                replacement = calloc (total_length+1, 1);

                bptr = rep;
                ptr = strchr(rep, '\\');
                while (ptr)
                {
                    if (ptr[1] >= '0' && ptr[1] <= '9')
                    {
                        strncpy (replacement+strlen(replacement), bptr, ptr-bptr);
                        strncpy (replacement+strlen(replacement), str + re.start[ptr[1]-'0'], re.end[ptr[1]-'0'] - re.start[ptr[1]-'0']);
                        bptr = ptr+2;
                    }
                    ptr = strchr (ptr+1, '\\');
                }
                strcat (replacement, bptr);
                replacement_len = strlen(replacement);
            }
            else
            {
                replacement = (char *)rep;
                replacement_len = rep_len;
            }

            /* Fill the resulting string */

            if (result_allocated < strlen(result)+(nextpos-startpos)+1+replacement_len)
            {
                result_allocated += ((nextpos-startpos+1+replacement_len) & ~127) + 128;
                result = realloc(result, result_allocated);
            }
            result[strlen(result)+(nextpos-startpos)] = 0;
            memcpy (result + strlen(result), str+startpos, nextpos-startpos);
            strcat (result, replacement);

            if (fixed_replacement == 0) free (replacement);

            /* Continue the search */

            startpos = nextpos+re_match(&pb, str, str_len, nextpos, 0);
            if (startpos <  nextpos) break;
            if (startpos == nextpos) startpos++;
        }
    }

    /* Copy remaining characters */

    nextpos = str_len;
    if (result_allocated < strlen(result)+(nextpos-startpos)+1)
    {
        result_allocated += ((nextpos-startpos+1) & ~127) + 128;
        result = realloc(result, result_allocated);
    }
    result[strlen(result)+(nextpos-startpos)] = 0;
    memcpy (result + strlen(result), str+startpos, nextpos-startpos);

    /* Free resources */

    free (pb.buffer);
    free (pb.fastmap);
    string_discard(params[0]);
    string_discard(params[1]);
    string_discard(params[2]);

    /* Return the new string */

    result_string = string_new(result);
    string_use(result_string);
    free(result);

    return result_string;
}