2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-15 13:02:11 +00:00
Files
build/v2/engine/modules/regex.c

104 lines
2.8 KiB
C

/*
* Copyright 2003. Vladimir Prus
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include "../mem.h"
#include "../native.h"
#include "../strings.h"
#include "../subst.h"
/*
rule transform ( list * : pattern : indices * )
{
indices ?= 1 ;
local result ;
for local e in $(list)
{
local m = [ MATCH $(pattern) : $(e) ] ;
if $(m)
{
result += $(m[$(indices)]) ;
}
}
return $(result) ;
}
*/
LIST * regex_transform( FRAME * frame, int flags )
{
LIST * const l = lol_get( frame->args, 0 );
LIST * const pattern = lol_get( frame->args, 1 );
LIST * const indices_list = lol_get( frame->args, 2 );
int * indices = 0;
int size;
LIST * result = L0;
if ( !list_empty( indices_list ) )
{
int * p;
LISTITER iter = list_begin( indices_list );
LISTITER const end = list_end( indices_list );
size = list_length( indices_list );
indices = (int *)BJAM_MALLOC( size * sizeof( int ) );
for ( p = indices; iter != end; iter = list_next( iter ) )
*p++ = atoi( object_str( list_item( iter ) ) );
}
else
{
size = 1;
indices = (int *)BJAM_MALLOC( sizeof( int ) );
*indices = 1;
}
{
/* Result is cached and intentionally never freed */
regexp * const re = regex_compile( list_front( pattern ) );
LISTITER iter = list_begin( l );
LISTITER const end = list_end( l );
string buf[ 1 ];
string_new( buf );
for ( ; iter != end; iter = list_next( iter ) )
{
if ( regexec( re, object_str( list_item( iter ) ) ) )
{
int i = 0;
for ( ; i < size; ++i )
{
int const index = indices[ i ];
/* Skip empty submatches. Not sure it is right in all cases,
* but surely is right for the case for which this routine
* is optimized -- header scanning.
*/
if ( re->startp[ index ] != re->endp[ index ] )
{
string_append_range( buf, re->startp[ index ],
re->endp[ index ] );
result = list_push_back( result, object_new( buf->value
) );
string_truncate( buf, 0 );
}
}
}
}
string_free( buf );
}
BJAM_FREE( indices );
return result;
}
void init_regex()
{
char const * args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0
};
declare_native_rule( "regex", "transform", args, regex_transform, 2 );
}