~ubuntu-branches/ubuntu/natty/pd-zexy/natty

« back to all changes in this revision

Viewing changes to src/regex.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard, IOhannes m zmölnig, Jonas Smedegaard
  • Date: 2010-08-20 12:17:41 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100820121741-4kxozn8b9rhee9fr
Tags: 2.2.3-1
* New upstream version

[ IOhannes m zmölnig ]
* Adopt package, on behalf of Multimedia Team.
  Closes: #546964
* Simply debian/rules with CDBS, and don't unconditionally strip
  binaries.
  Closes: #437763
* Install into /usr/lib/pd/extra/zexy/. Document usage in REAME.Debian
  and warn about change in NEWS.
* git'ify package. Add Vcs-* stanzas to control file.
* Use dpkg source format 3.0 (quilt). Drop build-dependency on quilt.

[ Jonas Smedegaard ]
* Enable CDBS copyright-check routine.
* Add copyright and licensing header to debian/rules.
* Add myself as uploader.
* Rewrite debian/copyright using rev. 135 of draft DEP5 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
 *
 
3
 * zexy - implementation file
 
4
 *
 
5
 * copyleft (c) IOhannes m zm�lnig
 
6
 *
 
7
 *   1999:forum::f�r::uml�ute:2004
 
8
 *
 
9
 *   institute of electronic music and acoustics (iem)
 
10
 *
 
11
 ******************************************************
 
12
 *
 
13
 * license: GNU General Public License v.2
 
14
 *
 
15
 ******************************************************/
 
16
 
 
17
#include "zexy.h"
 
18
 
 
19
#ifdef HAVE_REGEX_H
 
20
# include <sys/types.h>
 
21
# include <regex.h>
 
22
# include <string.h>
 
23
#endif
 
24
 
 
25
# define NUM_REGMATCHES 10
 
26
 
 
27
/*
 
28
 * regex    : see whether a regular expression matches the given symbol
 
29
 */
 
30
 
 
31
/* ------------------------- regex ------------------------------- */
 
32
 
 
33
/* match a regular expression against a string */
 
34
 
 
35
static t_class *regex_class;
 
36
 
 
37
typedef struct _regex
 
38
{
 
39
  t_object x_obj;
 
40
#ifdef HAVE_REGEX_H
 
41
  char    *x_regexstring; /* the uncompiled regular expression */
 
42
  int      x_regexstringlength; 
 
43
 
 
44
  regex_t *x_regexp;
 
45
  int x_matchnum;
 
46
 
 
47
  int x_flags; /* flags for the regex-compiler; REG_EXTENDED is always enabled */
 
48
#endif
 
49
 
 
50
  t_outlet*x_outResult;
 
51
  t_outlet*x_outDetails;
 
52
  t_outlet*x_outNumDetails;
 
53
 
 
54
} t_regex;
 
55
 
 
56
#ifdef HAVE_REGEX_H
 
57
static char*regex_l2s(int *reslen, t_symbol*s, int argc, t_atom*argv)
 
58
{
 
59
  char *result = 0;
 
60
  int pos=0, i=0;
 
61
  t_atom*ap;
 
62
  int length=0;
 
63
  if(reslen)*reslen=length;
 
64
 
 
65
  /* 1st get the length of the symbol */
 
66
  if(s)length+=strlen(s->s_name);
 
67
  else length-=1;
 
68
  length+=argc;
 
69
 
 
70
  i=argc;
 
71
  ap=argv;
 
72
  while(i--){
 
73
    char buffer[MAXPDSTRING];
 
74
    int len=0;
 
75
    if(A_SYMBOL==ap->a_type){
 
76
      len=strlen(ap->a_w.w_symbol->s_name);
 
77
    } else {
 
78
      atom_string(ap, buffer, MAXPDSTRING);
 
79
      len=strlen(buffer);
 
80
    }
 
81
    length+=len;
 
82
    ap++;
 
83
  }
 
84
 
 
85
  if(length<=0)return(0);
 
86
 
 
87
  result = (char*)getbytes((length+1)*sizeof(char));
 
88
 
 
89
  if (s) {
 
90
    char *buf = s->s_name;
 
91
    strcpy(result+pos, buf);
 
92
    pos+=strlen(buf);
 
93
    if(i){
 
94
      strcpy(result+pos, " ");
 
95
      pos += 1;
 
96
    }
 
97
  }
 
98
 
 
99
  ap=argv;
 
100
  i=argc;
 
101
  while(i--){
 
102
    if(A_SYMBOL==ap->a_type){
 
103
      strcpy(result+pos, ap->a_w.w_symbol->s_name);
 
104
      pos+= strlen(ap->a_w.w_symbol->s_name);
 
105
    } else {
 
106
      char buffer[MAXPDSTRING];
 
107
      atom_string(ap, buffer, MAXPDSTRING);
 
108
      strcpy(result+pos, buffer);
 
109
      pos += strlen(buffer);
 
110
    }
 
111
    ap++;
 
112
    if(i){
 
113
      strcpy(result+pos, " ");
 
114
      pos++;
 
115
    }
 
116
  }
 
117
 
 
118
  result[length]=0;
 
119
  if(reslen)*reslen=length;
 
120
  return result;
 
121
}
 
122
 
 
123
static void regex_compile(t_regex *x)
 
124
{
 
125
  int flags =  x->x_flags;
 
126
  flags |= REG_EXTENDED;
 
127
 
 
128
  if(0==x->x_regexstring || 0==x->x_regexstringlength){
 
129
    pd_error(x, "[regex]: no regular expression given");
 
130
    return;
 
131
  }
 
132
 
 
133
 
 
134
  if(x->x_regexp){
 
135
   regfree(x->x_regexp);
 
136
   freebytes(x->x_regexp, sizeof(t_regex));
 
137
   x->x_regexp=0;
 
138
  }
 
139
  x->x_regexp=(regex_t*)getbytes(sizeof(t_regex));
 
140
 
 
141
  if(regcomp(x->x_regexp, x->x_regexstring, flags)) {
 
142
    pd_error(x, "[regex]: invalid regular expression: %s", x->x_regexstring);
 
143
    if(x->x_regexp)freebytes(x->x_regexp, sizeof(t_regex));
 
144
    x->x_regexp=0;
 
145
  }
 
146
}
 
147
#endif
 
148
 
 
149
 
 
150
static void regex_case(t_regex *x, t_float f){
 
151
#if HAVE_REGEX_H
 
152
  if(f>0.f)
 
153
    x->x_flags |= REG_ICASE;
 
154
  else
 
155
    x->x_flags ^= REG_ICASE;
 
156
 
 
157
  regex_compile(x);
 
158
#endif
 
159
}
 
160
 
 
161
 
 
162
static void regex_regex(t_regex *x, t_symbol*s, int argc, t_atom*argv)
 
163
{
 
164
#ifdef HAVE_REGEX_H
 
165
  char*result=0;
 
166
  int length=0;
 
167
 
 
168
  result=regex_l2s(&length, 0, argc, argv);
 
169
 
 
170
  if(0==result || 0==length){
 
171
    pd_error(x, "[regex]: no regular expression given");
 
172
    return;
 
173
  }
 
174
 
 
175
  if(x->x_regexstring) {
 
176
    freebytes(x->x_regexstring, x->x_regexstringlength);
 
177
    x->x_regexstring=0;
 
178
    x->x_regexstringlength=0;
 
179
  }
 
180
  
 
181
  x->x_regexstring=result;
 
182
  x->x_regexstringlength=length;
 
183
 
 
184
  regex_compile(x);
 
185
#endif
 
186
}
 
187
 
 
188
/* compare the given list as string with the precompiled regex */
 
189
static void regex_symbol(t_regex *x, t_symbol *s, int argc, t_atom*argv)
 
190
{
 
191
#ifdef HAVE_REGEX_H
 
192
  char*teststring=0;
 
193
  int length=0;
 
194
 
 
195
  int num_matches=x->x_matchnum;
 
196
  regmatch_t*match=(regmatch_t*)getbytes(sizeof(regmatch_t)*num_matches);
 
197
  t_atom*ap=(t_atom*)getbytes(sizeof(t_atom)*(3*num_matches));
 
198
 
 
199
  int err=0;
 
200
 
 
201
  if(!x->x_regexp){
 
202
    pd_error(x, "[regex]: no regular expression!");
 
203
    goto cleanup;
 
204
  }
 
205
  teststring=regex_l2s(&length, 0, argc, argv);
 
206
  if(!teststring||!length){
 
207
    pd_error(x, "[regex]: cannot evaluate string");
 
208
    goto cleanup;
 
209
  }
 
210
 
 
211
  /* do the actual comparing against the regex */
 
212
  err=regexec(x->x_regexp, teststring, num_matches, match, 0);
 
213
  if(teststring){
 
214
    freebytes(teststring, length);
 
215
    teststring=0;
 
216
  }
 
217
 
 
218
  if(err) { /* NO match */
 
219
    if(match){
 
220
      freebytes(match, sizeof(regmatch_t)*num_matches);
 
221
      match=0;
 
222
    }
 
223
 
 
224
    outlet_float(x->x_outResult, 0.f);
 
225
  } else { /* match! */
 
226
    int num_results=0;
 
227
    int i=0;
 
228
    t_atom*ap2=ap;
 
229
 
 
230
    for(i=0; i<num_matches; i++){
 
231
      if(match[i].rm_so!=-1){
 
232
        /* output the matches */
 
233
        if(i>0 && (match[i].rm_so==match[i-1].rm_so) && (match[i].rm_eo==match[i-1].rm_eo)){
 
234
          /* duplicate matches */
 
235
        } else {
 
236
          SETFLOAT(ap2+0, (t_float)i);
 
237
          SETFLOAT(ap2+1, (t_float)match[i].rm_so);
 
238
          SETFLOAT(ap2+2, (t_float)match[i].rm_eo);
 
239
          ap2+=3;
 
240
          num_results++;
 
241
        }
 
242
      }
 
243
    }
 
244
    if(match){
 
245
      freebytes(match, sizeof(regmatch_t)*num_matches);
 
246
      match=0;
 
247
    }
 
248
    outlet_float(x->x_outNumDetails, (t_float)num_results);
 
249
    for(i=0; i<num_results; i++){
 
250
      outlet_list(x->x_outDetails, gensym("list"), 3, ap+(i*3));
 
251
    }
 
252
    outlet_float(x->x_outResult, 1.f);
 
253
  }
 
254
 cleanup:
 
255
  if(teststring)freebytes(teststring, length);
 
256
  if(match)freebytes(match, sizeof(regmatch_t)*num_matches);
 
257
 
 
258
  if(ap){
 
259
    freebytes(ap, sizeof(t_atom)*(1+2*num_matches));
 
260
  }
 
261
#endif
 
262
}
 
263
 
 
264
static void *regex_new(t_symbol *s, int argc, t_atom*argv)
 
265
{
 
266
  t_regex *x = (t_regex *)pd_new(regex_class);
 
267
 
 
268
  inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym("regex"));
 
269
 
 
270
  x->x_outResult=outlet_new(&x->x_obj, 0);
 
271
  x->x_outDetails=outlet_new(&x->x_obj, gensym("list"));
 
272
  x->x_outNumDetails=outlet_new(&x->x_obj, &s_float);
 
273
 
 
274
 
 
275
#ifdef HAVE_REGEX_H
 
276
  x->x_flags=0;
 
277
 
 
278
  x->x_regexstring=0;
 
279
  x->x_regexstringlength=0;
 
280
 
 
281
  x->x_regexp=0;
 
282
  x->x_matchnum=NUM_REGMATCHES;
 
283
  if(argc)regex_regex(x, gensym(""), argc, argv);
 
284
  else{
 
285
    t_atom a;
 
286
    SETSYMBOL(&a, gensym(".*"));
 
287
    regex_regex(x, 0, 1, &a);
 
288
  }
 
289
#else
 
290
  error("[regex] non-functional: compiled without regex-support!");
 
291
#endif
 
292
 
 
293
  return (x);
 
294
}
 
295
 
 
296
static void regex_free(t_regex *x)
 
297
{
 
298
#ifdef HAVE_REGEX_H
 
299
  if(x->x_regexstring){
 
300
    freebytes(x->x_regexstring, x->x_regexstringlength);
 
301
    x->x_regexstring=0;
 
302
    x->x_regexstringlength=0;
 
303
  }
 
304
 
 
305
  if(x->x_regexp) {
 
306
    regfree(x->x_regexp);
 
307
    freebytes(x->x_regexp, sizeof(t_regex));
 
308
    x->x_regexp=0;
 
309
  }
 
310
#endif
 
311
}
 
312
 
 
313
static void regex_help(t_regex*x)
 
314
{
 
315
  post("\n%c regex\t\t:: test the input whether it matches a regular expression", HEARTSYMBOL);
 
316
}
 
317
 
 
318
void regex_setup(void)
 
319
{
 
320
  regex_class = class_new(gensym("regex"), (t_newmethod)regex_new, 
 
321
                         (t_method)regex_free, sizeof(t_regex), 0, A_GIMME, 0);
 
322
 
 
323
  class_addlist  (regex_class, regex_symbol);
 
324
  class_addmethod(regex_class, (t_method)regex_regex, gensym("regex"), A_GIMME, 0);
 
325
 
 
326
  class_addmethod(regex_class, (t_method)regex_case, gensym("case"), A_FLOAT, 0);
 
327
 
 
328
  class_addmethod(regex_class, (t_method)regex_help, gensym("help"), A_NULL);
 
329
  zexy_register("regex");
 
330
}