1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include "jam.h"
#include "subst.h"
#include "builtins.h"
#include "frames.h"
#include "hash.h"
#include "lists.h"
#include <stddef.h>
typedef struct regex_entry
{
OBJECT * pattern;
regexp * regex;
} regex_entry;
static struct hash * regex_hash;
regexp * regex_compile( OBJECT * pattern )
{
int found;
regex_entry * e ;
if ( !regex_hash )
regex_hash = hashinit( sizeof( regex_entry ), "regex" );
e = (regex_entry *)hash_insert( regex_hash, pattern, &found );
if ( !found )
{
e->pattern = object_copy( pattern );
e->regex = regcomp( (char *)pattern );
}
return e->regex;
}
LIST * builtin_subst( FRAME * frame, int flags )
{
LIST * result = L0;
LIST * const arg1 = lol_get( frame->args, 0 );
LISTITER iter = list_begin( arg1 );
LISTITER const end = list_end( arg1 );
if ( iter != end && list_next( iter ) != end && list_next( list_next( iter )
) != end )
{
char const * const source = object_str( list_item( iter ) );
OBJECT * const pattern = list_item( list_next( iter ) );
regexp * const repat = regex_compile( pattern );
if ( regexec( repat, (char *)source) )
{
LISTITER subst = list_next( iter );
while ( ( subst = list_next( subst ) ) != end )
{
#define BUFLEN 4096
char buf[ BUFLEN + 1 ];
char const * in = object_str( list_item( subst ) );
char * out = buf;
for ( ; *in && out < buf + BUFLEN; ++in )
{
if ( *in == '\\' || *in == '$' )
{
++in;
if ( *in == 0 )
break;
if ( *in >= '0' && *in <= '9' )
{
unsigned int const n = *in - '0';
size_t const srclen = repat->endp[ n ] -
repat->startp[ n ];
size_t const remaining = buf + BUFLEN - out;
size_t const len = srclen < remaining
? srclen
: remaining;
memcpy( out, repat->startp[ n ], len );
out += len;
continue;
}
/* fall through and copy the next character */
}
*out++ = *in;
}
*out = 0;
result = list_push_back( result, object_new( buf ) );
#undef BUFLEN
}
}
}
return result;
}
static void free_regex( void * xregex, void * data )
{
regex_entry * const regex = (regex_entry *)xregex;
object_free( regex->pattern );
BJAM_FREE( regex->regex );
}
void regex_done()
{
if ( regex_hash )
{
hashenumerate( regex_hash, free_regex, (void *)0 );
hashdone( regex_hash );
}
}
|