|
1 /* |
|
2 * pcre.c - interface to the PCRE library |
|
3 * |
|
4 * This file is part of zsh, the Z shell. |
|
5 * |
|
6 * Copyright (c) 2001, 2002, 2003, 2004 Clint Adams |
|
7 * All rights reserved. |
|
8 * |
|
9 * Permission is hereby granted, without written agreement and without |
|
10 * license or royalty fees, to use, copy, modify, and distribute this |
|
11 * software and to distribute modified versions of this software for any |
|
12 * purpose, provided that the above copyright notice and the following |
|
13 * two paragraphs appear in all copies of this software. |
|
14 * |
|
15 * In no event shall Clint Adams or the Zsh Development Group be liable |
|
16 * to any party for direct, indirect, special, incidental, or consequential |
|
17 * damages arising out of the use of this software and its documentation, |
|
18 * even if Andrew Main and the Zsh Development Group have been advised of |
|
19 * the possibility of such damage. |
|
20 * |
|
21 * Clint Adams and the Zsh Development Group specifically disclaim any |
|
22 * warranties, including, but not limited to, the implied warranties of |
|
23 * merchantability and fitness for a particular purpose. The software |
|
24 * provided hereunder is on an "as is" basis, and Andrew Main and the |
|
25 * Zsh Development Group have no obligation to provide maintenance, |
|
26 * support, updates, enhancements, or modifications. |
|
27 * |
|
28 */ |
|
29 |
|
30 |
|
31 #include "pcre.mdh" |
|
32 #include "pcre.pro" |
|
33 |
|
34 #define CPCRE_PLAIN 0 |
|
35 |
|
36 /**/ |
|
37 #if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC) |
|
38 #include <pcre.h> |
|
39 |
|
40 static pcre *pcre_pattern; |
|
41 static pcre_extra *pcre_hints; |
|
42 |
|
43 /**/ |
|
44 static int |
|
45 bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func)) |
|
46 { |
|
47 int pcre_opts = 0, pcre_errptr; |
|
48 const char *pcre_error; |
|
49 |
|
50 if(OPT_ISSET(ops,'a')) pcre_opts |= PCRE_ANCHORED; |
|
51 if(OPT_ISSET(ops,'i')) pcre_opts |= PCRE_CASELESS; |
|
52 if(OPT_ISSET(ops,'m')) pcre_opts |= PCRE_MULTILINE; |
|
53 if(OPT_ISSET(ops,'x')) pcre_opts |= PCRE_EXTENDED; |
|
54 |
|
55 pcre_hints = NULL; /* Is this necessary? */ |
|
56 |
|
57 pcre_pattern = pcre_compile(*args, pcre_opts, &pcre_error, &pcre_errptr, NULL); |
|
58 |
|
59 if (pcre_pattern == NULL) |
|
60 { |
|
61 zwarnnam(nam, "error in regex: %s", pcre_error, 0); |
|
62 return 1; |
|
63 } |
|
64 |
|
65 return 0; |
|
66 } |
|
67 |
|
68 /**/ |
|
69 #ifdef HAVE_PCRE_STUDY |
|
70 |
|
71 /**/ |
|
72 static int |
|
73 bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int func)) |
|
74 { |
|
75 const char *pcre_error; |
|
76 |
|
77 if (pcre_pattern == NULL) |
|
78 { |
|
79 zwarnnam(nam, "no pattern has been compiled for study", |
|
80 NULL, 0); |
|
81 return 1; |
|
82 } |
|
83 |
|
84 pcre_hints = pcre_study(pcre_pattern, 0, &pcre_error); |
|
85 if (pcre_error != NULL) |
|
86 { |
|
87 zwarnnam(nam, "error while studying regex: %s", pcre_error, 0); |
|
88 return 1; |
|
89 } |
|
90 |
|
91 return 0; |
|
92 } |
|
93 |
|
94 /**/ |
|
95 #else /* !HAVE_PCRE_STUDY */ |
|
96 |
|
97 # define bin_pcre_study bin_notavail |
|
98 |
|
99 /**/ |
|
100 #endif /* !HAVE_PCRE_STUDY */ |
|
101 |
|
102 /**/ |
|
103 static int |
|
104 zpcre_get_substrings(char *arg, int *ovec, int ret, char *receptacle) |
|
105 { |
|
106 char **captures, **matches; |
|
107 |
|
108 if(!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) { |
|
109 |
|
110 matches = zarrdup(&captures[1]); /* first one would be entire string */ |
|
111 if (receptacle == NULL) |
|
112 setaparam("match", matches); |
|
113 else |
|
114 setaparam(receptacle, matches); |
|
115 |
|
116 pcre_free_substring_list((const char **)captures); |
|
117 } |
|
118 |
|
119 return 0; |
|
120 } |
|
121 |
|
122 /**/ |
|
123 static int |
|
124 bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) |
|
125 { |
|
126 int ret, capcount, *ovec, ovecsize; |
|
127 char *receptacle = NULL; |
|
128 |
|
129 if(OPT_ISSET(ops,'a')) { |
|
130 receptacle = *args++; |
|
131 if(!*args) { |
|
132 zwarnnam(nam, "not enough arguments", NULL, 0); |
|
133 return 1; |
|
134 } |
|
135 } |
|
136 |
|
137 if ((ret = pcre_fullinfo(pcre_pattern, pcre_hints, PCRE_INFO_CAPTURECOUNT, &capcount))) |
|
138 { |
|
139 zwarnnam(nam, "error %d in fullinfo", NULL, ret); |
|
140 return 1; |
|
141 } |
|
142 |
|
143 ovecsize = (capcount+1)*3; |
|
144 ovec = zalloc(ovecsize*sizeof(int)); |
|
145 |
|
146 ret = pcre_exec(pcre_pattern, pcre_hints, *args, strlen(*args), 0, 0, ovec, ovecsize); |
|
147 |
|
148 if (ret==0) return 0; |
|
149 else if (ret==PCRE_ERROR_NOMATCH) return 1; /* no match */ |
|
150 else if (ret>0) { |
|
151 zpcre_get_substrings(*args, ovec, ret, receptacle); |
|
152 return 0; |
|
153 } |
|
154 else { |
|
155 zwarnnam(nam, "error in pcre_exec", NULL, 0); |
|
156 return 1; |
|
157 } |
|
158 |
|
159 return 1; |
|
160 } |
|
161 |
|
162 /**/ |
|
163 static int |
|
164 cond_pcre_match(char **a, int id) |
|
165 { |
|
166 pcre *pcre_pat; |
|
167 const char *pcre_err; |
|
168 char *lhstr, *rhre; |
|
169 int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; |
|
170 |
|
171 lhstr = cond_str(a,0,0); |
|
172 rhre = cond_str(a,1,0); |
|
173 |
|
174 switch(id) { |
|
175 case CPCRE_PLAIN: |
|
176 pcre_pat = pcre_compile(rhre, pcre_opts, &pcre_err, &pcre_errptr, NULL); |
|
177 pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt); |
|
178 ovsize = (capcnt+1)*3; |
|
179 ov = zalloc(ovsize*sizeof(int)); |
|
180 r = pcre_exec(pcre_pat, NULL, lhstr, strlen(lhstr), 0, 0, ov, ovsize); |
|
181 if (r==0) return 1; |
|
182 else if (r==PCRE_ERROR_NOMATCH) return 0; /* no match */ |
|
183 else if (r>0) { |
|
184 zpcre_get_substrings(lhstr, ov, r, NULL); |
|
185 return 1; |
|
186 } |
|
187 break; |
|
188 } |
|
189 |
|
190 return 0; |
|
191 } |
|
192 |
|
193 /**/ |
|
194 #else /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */ |
|
195 |
|
196 # define bin_pcre_compile bin_notavail |
|
197 # define bin_pcre_study bin_notavail |
|
198 # define bin_pcre_match bin_notavail |
|
199 # define cond_pcre_match cond_match |
|
200 |
|
201 /**/ |
|
202 #endif /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */ |
|
203 |
|
204 static struct builtin bintab[] = { |
|
205 BUILTIN("pcre_compile", 0, bin_pcre_compile, 1, 1, 0, "aimx", NULL), |
|
206 BUILTIN("pcre_study", 0, bin_pcre_study, 0, 0, 0, NULL, NULL), |
|
207 BUILTIN("pcre_match", 0, bin_pcre_match, 1, 2, 0, "a", NULL) |
|
208 }; |
|
209 |
|
210 static struct conddef cotab[] = { |
|
211 CONDDEF("pcre-match", CONDF_INFIX, cond_pcre_match, 0, 0, CPCRE_PLAIN) |
|
212 }; |
|
213 |
|
214 |
|
215 /**/ |
|
216 int |
|
217 setup_(UNUSED(Module m)) |
|
218 { |
|
219 return 0; |
|
220 } |
|
221 |
|
222 /**/ |
|
223 int |
|
224 boot_(Module m) |
|
225 { |
|
226 return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) || |
|
227 !addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)); |
|
228 } |
|
229 |
|
230 /**/ |
|
231 int |
|
232 cleanup_(Module m) |
|
233 { |
|
234 deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); |
|
235 deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)); |
|
236 return 0; |
|
237 } |
|
238 |
|
239 /**/ |
|
240 int |
|
241 finish_(UNUSED(Module m)) |
|
242 { |
|
243 return 0; |
|
244 } |