1 | #include <stddef.h> |
---|
2 | #include "jam.h" |
---|
3 | #include "regexp.h" |
---|
4 | #include "hash.h" |
---|
5 | |
---|
6 | #include "newstr.h" |
---|
7 | #include "lists.h" |
---|
8 | #include "parse.h" |
---|
9 | #include "compile.h" |
---|
10 | #include "frames.h" |
---|
11 | |
---|
12 | struct regex_entry |
---|
13 | { |
---|
14 | const char* pattern; |
---|
15 | regexp* regex; |
---|
16 | }; |
---|
17 | typedef struct regex_entry regex_entry; |
---|
18 | |
---|
19 | static struct hash* regex_hash; |
---|
20 | |
---|
21 | regexp* regex_compile( const char* pattern ) |
---|
22 | { |
---|
23 | regex_entry entry, *e = &entry; |
---|
24 | entry.pattern = pattern; |
---|
25 | |
---|
26 | if ( !regex_hash ) |
---|
27 | regex_hash = hashinit(sizeof(regex_entry), "regex"); |
---|
28 | |
---|
29 | if ( hashenter( regex_hash, (HASHDATA **)&e ) ) |
---|
30 | e->regex = regcomp( (char*)pattern ); |
---|
31 | |
---|
32 | return e->regex; |
---|
33 | } |
---|
34 | |
---|
35 | LIST* |
---|
36 | builtin_subst( |
---|
37 | PARSE *parse, |
---|
38 | FRAME *frame ) |
---|
39 | { |
---|
40 | LIST* result = L0; |
---|
41 | LIST* arg1 = lol_get( frame->args, 0 ); |
---|
42 | |
---|
43 | if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) ) |
---|
44 | { |
---|
45 | |
---|
46 | const char* source = arg1->string; |
---|
47 | const char* pattern = list_next(arg1)->string; |
---|
48 | regexp* repat = regex_compile( pattern ); |
---|
49 | |
---|
50 | if ( regexec( repat, (char*)source) ) |
---|
51 | { |
---|
52 | LIST* subst = list_next(arg1); |
---|
53 | |
---|
54 | while ((subst = list_next(subst)) != L0) |
---|
55 | { |
---|
56 | # define BUFLEN 4096 |
---|
57 | char buf[BUFLEN + 1]; |
---|
58 | const char* in = subst->string; |
---|
59 | char* out = buf; |
---|
60 | |
---|
61 | for ( in = subst->string; *in && out < buf + BUFLEN; ++in ) |
---|
62 | { |
---|
63 | if ( *in == '\\' || *in == '$' ) |
---|
64 | { |
---|
65 | ++in; |
---|
66 | if ( *in == 0 ) |
---|
67 | { |
---|
68 | break; |
---|
69 | } |
---|
70 | else if ( *in >= '0' && *in <= '9' ) |
---|
71 | { |
---|
72 | unsigned n = *in - '0'; |
---|
73 | const size_t srclen = repat->endp[n] - repat->startp[n]; |
---|
74 | const size_t remaining = buf + BUFLEN - out; |
---|
75 | const size_t len = srclen < remaining ? srclen : remaining; |
---|
76 | memcpy( out, repat->startp[n], len ); |
---|
77 | out += len; |
---|
78 | continue; |
---|
79 | } |
---|
80 | /* fall through and copy the next character */ |
---|
81 | } |
---|
82 | *out++ = *in; |
---|
83 | } |
---|
84 | *out = 0; |
---|
85 | |
---|
86 | result = list_new( result, newstr( buf ) ); |
---|
87 | #undef BUFLEN |
---|
88 | } |
---|
89 | } |
---|
90 | } |
---|
91 | |
---|
92 | return result; |
---|
93 | } |
---|
94 | |
---|