#include #include "jam.h" #include "regexp.h" #include "hash.h" #include "newstr.h" #include "lists.h" #include "parse.h" #include "compile.h" #include "frames.h" struct regex_entry { const char* pattern; regexp* regex; }; typedef struct regex_entry regex_entry; static struct hash* regex_hash; regexp* regex_compile( const char* pattern ) { regex_entry entry, *e = &entry; entry.pattern = pattern; if ( !regex_hash ) regex_hash = hashinit(sizeof(regex_entry), "regex"); if ( hashenter( regex_hash, (HASHDATA **)&e ) ) e->regex = regcomp( (char*)pattern ); return e->regex; } LIST* builtin_subst( PARSE *parse, FRAME *frame ) { LIST* result = L0; LIST* arg1 = lol_get( frame->args, 0 ); if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) ) { const char* source = arg1->string; const char* pattern = list_next(arg1)->string; regexp* repat = regex_compile( pattern ); if ( regexec( repat, (char*)source) ) { LIST* subst = list_next(arg1); while ((subst = list_next(subst)) != L0) { # define BUFLEN 4096 char buf[BUFLEN + 1]; const char* in = subst->string; char* out = buf; for ( in = subst->string; *in && out < buf + BUFLEN; ++in ) { if ( *in == '\\' || *in == '$' ) { ++in; if ( *in == 0 ) { break; } else if ( *in >= '0' && *in <= '9' ) { unsigned n = *in - '0'; const size_t srclen = repat->endp[n] - repat->startp[n]; const size_t remaining = buf + BUFLEN - out; const size_t 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_new( result, newstr( buf ) ); #undef BUFLEN } } } return result; }