blob: d048ba1de43c04e51aeecc90002f480b79d452f0 [file] [log] [blame]
/* Copyright Vladimir Prus 2003. 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 "../native.h"
#include "../timestamp.h"
#include "../newstr.h"
#include "../strings.h"
#include "../regexp.h"
#include "../compile.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( PARSE *parse, FRAME *frame )
{
LIST* l = lol_get( frame->args, 0 );
LIST* pattern = lol_get( frame->args, 1 );
LIST* indices_list = lol_get(frame->args, 2);
int* indices = 0;
int size;
int* p;
LIST* result = 0;
string buf[1];
string_new(buf);
if (indices_list)
{
size = list_length(indices_list);
indices = (int*)BJAM_MALLOC(size*sizeof(int));
for(p = indices; indices_list; indices_list = indices_list->next)
{
*p++ = atoi(indices_list->string);
}
}
else
{
size = 1;
indices = (int*)BJAM_MALLOC(sizeof(int));
*indices = 1;
}
{
/* Result is cached and intentionally never freed */
regexp *re = regex_compile( pattern->string );
for(; l; l = l->next)
{
if( regexec( re, l->string ) )
{
int i = 0;
for(; i < size; ++i)
{
int index = indices[i];
/* Skip empty submatches. Not sure it's 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_new( result, newstr( buf->value ) );
string_truncate( buf, 0 );
}
}
}
}
string_free( buf );
}
BJAM_FREE(indices);
return result;
}
void init_regex()
{
{
char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
declare_native_rule("regex", "transform", args, regex_transform, 2);
}
}