2 * This file is part of DisOrder
3 * Copyright (C) 2004, 2005 Richard Kettlewell
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #define PREMATCH (-1) /* fictitious pre-match substring */
33 #define POSTMATCH (-2) /* fictitious post-match substring */
35 static inline int substring_start(const char attribute((unused
)) *subject
,
39 case PREMATCH
: return 0;
40 case POSTMATCH
: return ovector
[1];
41 default: return ovector
[2 * n
];
45 static inline int substring_end(const char *subject
,
49 case PREMATCH
: return ovector
[0];
50 case POSTMATCH
: return strlen(subject
);
51 default: return ovector
[2 * n
+ 1];
55 static void transform_append(struct dynstr
*d
,
59 int start
= substring_start(subject
, ovector
, n
);
60 int end
= substring_end(subject
, ovector
, n
);
63 dynstr_append_bytes(d
, subject
+ start
, end
- start
);
66 static void replace_core(struct dynstr
*d
,
77 transform_append(d
, subject
, ovector
, 0);
80 case '1': case '2': case '3':
81 case '4': case '5': case '6':
82 case '7': case '8': case '9':
83 substr
= replace
[1] - '0';
85 transform_append(d
, subject
, ovector
, substr
);
89 dynstr_append(d
, '$');
93 dynstr_append(d
, *replace
++);
97 dynstr_append(d
, *replace
++);
101 unsigned regsub_flags(const char *flags
) {
106 case 'g': f
|= REGSUB_GLOBAL
; break;
107 case 'i': f
|= REGSUB_CASE_INDEPENDENT
; break;
114 int regsub_compile_options(unsigned flags
) {
117 if(flags
& REGSUB_CASE_INDEPENDENT
)
118 options
|= PCRE_CASELESS
;
122 const char *regsub(const pcre
*re
, const char *subject
, const char *replace
,
124 int rc
, ovector
[99], matches
;
129 /* find the next match */
130 while((rc
= pcre_exec(re
, 0, subject
, strlen(subject
), 0,
131 0, ovector
, sizeof ovector
/ sizeof (int))) > 0) {
132 /* text just before the match */
133 if(!(flags
& REGSUB_REPLACE
))
134 transform_append(&d
, subject
, ovector
, PREMATCH
);
135 /* the replacement text */
136 replace_core(&d
, subject
, replace
, rc
, ovector
);
138 if(!*subject
) /* end of subject */
140 if(flags
& REGSUB_REPLACE
) /* replace subject entirely */
142 /* step over the matched substring */
143 subject
+= substring_start(subject
, ovector
, POSTMATCH
);
144 if(!(flags
& REGSUB_GLOBAL
))
147 if(rc
<= 0 && rc
!= PCRE_ERROR_NOMATCH
) {
148 error(0, "pcre_exec returned %d, subject '%s'", rc
, subject
);
151 if((flags
& REGSUB_MUST_MATCH
) && matches
== 0)
153 /* append the remainder of the subject */
154 if(!(flags
& REGSUB_REPLACE
))
155 dynstr_append_string(&d
, subject
);
156 dynstr_terminate(&d
);