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

« back to all changes in this revision

Viewing changes to src/matchbox.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
/* LATER: add a creation argument to specify the initial search mode
 
18
 *
 
19
 * LATER: bind a "name" to the [matchbox] so several objects can share the same entries
 
20
 * if no name is given at creation time, the entries are local only
 
21
 *
 
22
 * even LATER: dynamically bind to several searchlists (via "set" message)
 
23
 */
 
24
 
 
25
 
 
26
#include "zexy.h"
 
27
 
 
28
#define MATCHBOX_EXACT 0
 
29
#define MATCHBOX_OSC 1
 
30
 
 
31
#ifdef HAVE_REGEX_H
 
32
# include <sys/types.h>
 
33
# include <regex.h>
 
34
#define MATCHBOX_REGEX 2
 
35
#endif
 
36
 
 
37
#include <string.h>
 
38
 
 
39
#define FALSE 0
 
40
#define TRUE  1
 
41
 
 
42
/*
 
43
 * matchbox    : see whether a regular expression matches the given symbol
 
44
 */
 
45
 
 
46
/* ------------------------- matchbox ------------------------------- */
 
47
 
 
48
/* match the atoms of 2 lists */
 
49
 
 
50
static t_class *matchbox_class;
 
51
 
 
52
 
 
53
typedef struct _listlist {
 
54
  int                 argc;
 
55
  t_atom             *argv;
 
56
  struct _listlist *next;
 
57
} t_listlist;
 
58
 
 
59
 
 
60
typedef struct _matchbox
 
61
{
 
62
  t_object x_obj;
 
63
 
 
64
  t_listlist*x_lists;
 
65
  unsigned int x_numlists;
 
66
 
 
67
  int x_mode;
 
68
 
 
69
  t_outlet*x_outResult;
 
70
  t_outlet*x_outNumResults;
 
71
} t_matchbox;
 
72
 
 
73
 
 
74
/* ----------- here comes some infrastructure stuff -------------- */
 
75
 
 
76
 
 
77
static t_listlist* addlistlist(t_listlist*list, int argc, t_atom*argv) {
 
78
  t_listlist*ll=(t_listlist*)getbytes(sizeof(t_listlist));
 
79
  t_listlist*lp=0;
 
80
  ll->next=0;
 
81
  ll->argc=argc;
 
82
  ll->argv=(t_atom*)getbytes(argc*sizeof(t_atom));
 
83
  memcpy(ll->argv, argv, argc*sizeof(t_atom)); 
 
84
 
 
85
  if(0==list) {
 
86
    return ll;
 
87
  }
 
88
  
 
89
  lp=list;
 
90
  while(0!=lp->next)lp=lp->next;
 
91
  lp->next=ll;
 
92
 
 
93
  return list;
 
94
}
 
95
 
 
96
/* delete the _next_ element from the list */
 
97
static t_listlist* deletelistnext(t_listlist*list) {
 
98
  t_listlist*ll=0;
 
99
 
 
100
  if(!list || !list->next)return list; /* nothing to delete */
 
101
 
 
102
  ll=list->next;
 
103
  list->next=ll->next;
 
104
  if(ll->argv)freebytes(ll->argv, ll->argc*sizeof(t_atom));
 
105
 
 
106
  ll->argv=0;
 
107
  ll->argc=0;
 
108
  ll->next=0;
 
109
  freebytes(ll, sizeof(t_listlist));
 
110
  return list;
 
111
}
 
112
 
 
113
/* delete the entire list of lists */
 
114
static void clearlistlist(t_listlist*list) {
 
115
  if(!list)return; /* nothing to delete */
 
116
  while(list->next){
 
117
    list=deletelistnext(list);
 
118
  }
 
119
}
 
120
 
 
121
/* -------------- here comes the matching algorithms ----------- */
 
122
 
 
123
 
 
124
static int atommatch_exact(t_atom*pattern, t_atom*atom) {
 
125
  if(pattern->a_type==atom->a_type) {
 
126
    switch(pattern->a_type) {
 
127
    case A_FLOAT:
 
128
      return atom_getfloat(pattern)==atom_getfloat(atom);
 
129
    case A_SYMBOL:
 
130
      return atom_getsymbol(pattern)==atom_getsymbol(atom);
 
131
    default:
 
132
      return pattern==atom;
 
133
    }
 
134
  } else {
 
135
    /* post("types don't match!"); */
 
136
    return FALSE;
 
137
  }
 
138
 
 
139
  return TRUE;
 
140
}
 
141
 
 
142
#ifdef MATCHBOX_OSC /* OSC */
 
143
 
 
144
/*
 
145
OSC pattern matching code was written by Matt Wright, 
 
146
The Center for New Music and Audio Technologies,
 
147
University of California, Berkeley.  Copyright (c) 1998,99,2000,01,02,03,04
 
148
The Regents of the University of California (Regents).  
 
149
 
 
150
Permission to use, copy, modify, distribute, and distribute modified versions
 
151
of this software and its documentation without fee and without a signed
 
152
licensing agreement, is hereby granted, provided that the above copyright
 
153
notice, this paragraph and the following two paragraphs appear in all copies,
 
154
modifications, and distributions.
 
155
 
 
156
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 
157
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
 
158
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
 
159
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
160
 
 
161
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
162
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
163
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
 
164
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
 
165
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
166
 
 
167
The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
 
168
*/
 
169
 
 
170
#define OSCWarning post
 
171
static int OSC_MatchBrackets (const char *pattern, const char *test, const char*theWholePattern);
 
172
static int OSC_MatchList (const char *pattern, const char *test, const char*theWholePattern);
 
173
 
 
174
static int OSC_PatternMatch (const char *  pattern, const char * test, const char*theWholePattern) {
 
175
  if (pattern == 0 || pattern[0] == 0) {
 
176
    return test[0] == 0;
 
177
  } 
 
178
  
 
179
  if (test[0] == 0) {
 
180
    if (pattern[0] == '*')
 
181
      return OSC_PatternMatch (pattern+1,test, theWholePattern);
 
182
    else
 
183
      return FALSE;
 
184
  }
 
185
 
 
186
  switch (pattern[0]) {
 
187
  case 0      : return test[0] == 0;
 
188
  case '?'    : return OSC_PatternMatch (pattern + 1, test + 1, theWholePattern);
 
189
  case '*'    : 
 
190
    if (OSC_PatternMatch (pattern+1, test, theWholePattern)) {
 
191
      return TRUE;
 
192
    } else {
 
193
      return OSC_PatternMatch (pattern, test+1, theWholePattern);
 
194
    }
 
195
  case ']'    :
 
196
  case '}'    :
 
197
    z_verbose(1, "[matchbox]: spurious %c in OSC-pattern \".../%s/...\"",pattern[0], theWholePattern);
 
198
    return FALSE;
 
199
  case '['    :
 
200
    return OSC_MatchBrackets (pattern,test, theWholePattern);
 
201
  case '{'    :
 
202
    return OSC_MatchList (pattern,test, theWholePattern);
 
203
  case '\\'   :  
 
204
    if (pattern[1] == 0) {
 
205
      return test[0] == 0;
 
206
    } else if (pattern[1] == test[0]) {
 
207
      return OSC_PatternMatch (pattern+2,test+1, theWholePattern);
 
208
    } else {
 
209
      return FALSE;
 
210
    }
 
211
  default     :
 
212
    if (pattern[0] == test[0]) {
 
213
      return OSC_PatternMatch (pattern+1,test+1, theWholePattern);
 
214
    } else {
 
215
      return FALSE;
 
216
    }
 
217
  }
 
218
}
 
219
 
 
220
/* we know that pattern[0] == '[' and test[0] != 0 */
 
221
 
 
222
static int OSC_MatchBrackets (const char *pattern, const char *test, const char*theWholePattern) {
 
223
  int result;
 
224
  int negated = FALSE;
 
225
  const char *p = pattern;
 
226
 
 
227
  if (pattern[1] == 0) {
 
228
    z_verbose(1, "[matchbox]: unterminated [ in OSC-pattern \".../%s/...\"", theWholePattern);
 
229
    return FALSE;
 
230
  }
 
231
 
 
232
  if (pattern[1] == '!') {
 
233
    negated = TRUE;
 
234
    p++;
 
235
  }
 
236
 
 
237
  while (*p != ']') {
 
238
    if (*p == 0) {
 
239
      z_verbose(1, "[matchbox]: unterminated [ in OSC-pattern \".../%s/...\"", theWholePattern);
 
240
      return FALSE;
 
241
    }
 
242
    if (p[1] == '-' && p[2] != 0) {
 
243
      if (test[0] >= p[0] && test[0] <= p[2]) {
 
244
        result = !negated;
 
245
        goto advance;
 
246
      }
 
247
    }
 
248
    if (p[0] == test[0]) {
 
249
      result = !negated;
 
250
      goto advance;
 
251
    }
 
252
    p++;
 
253
  }
 
254
 
 
255
  result = negated;
 
256
 
 
257
 advance:
 
258
 
 
259
  if (!result)
 
260
    return FALSE;
 
261
 
 
262
  while (*p != ']') {
 
263
    if (*p == 0) {
 
264
      z_verbose(1, "[matchbox]: unterminated [ in OSC-pattern \".../%s/...\"", theWholePattern);
 
265
      return FALSE;
 
266
    }
 
267
    p++;
 
268
  }
 
269
 
 
270
  return OSC_PatternMatch (p+1,test+1, theWholePattern);
 
271
}
 
272
 
 
273
static int OSC_MatchList (const char *pattern, const char *test, const char* theWholePattern) {
 
274
 
 
275
  const char *restOfPattern, *tp = test;
 
276
 
 
277
  for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
 
278
    if (*restOfPattern == 0) {
 
279
      z_verbose(1, "[matchbox]: unterminated { in OSC-pattern \".../%s/...\"", theWholePattern);
 
280
      return FALSE;
 
281
    }
 
282
  }
 
283
 
 
284
  restOfPattern++; /* skip close curly brace */
 
285
 
 
286
 
 
287
  pattern++; /* skip open curly brace */
 
288
 
 
289
  while (1) {
 
290
   
 
291
    if (*pattern == ',') {
 
292
      if (OSC_PatternMatch (restOfPattern, tp, theWholePattern)) {
 
293
        return TRUE;
 
294
      } else {
 
295
        tp = test;
 
296
        ++pattern;
 
297
      }
 
298
    } else if (*pattern == '}') {
 
299
      return OSC_PatternMatch (restOfPattern, tp, theWholePattern);
 
300
    } else if (*pattern == *tp) {
 
301
      ++pattern;
 
302
      ++tp;
 
303
    } else {
 
304
      tp = test;
 
305
      while (*pattern != ',' && *pattern != '}') {
 
306
        pattern++;
 
307
      }
 
308
      if (*pattern == ',') {
 
309
        pattern++;
 
310
      }
 
311
    }
 
312
  }
 
313
}
 
314
 
 
315
static int atommatch_osc(t_atom*pattern, t_atom*test) {
 
316
  char*s_pattern=0;
 
317
  char*s_test=0;
 
318
  int pattern_size=0, test_size=0;
 
319
 
 
320
  int result = FALSE;
 
321
 
 
322
  if(pattern->a_type==A_SYMBOL) {
 
323
    s_pattern=pattern->a_w.w_symbol->s_name;
 
324
  } else {
 
325
    pattern_size=sizeof(char)*MAXPDSTRING;
 
326
    s_pattern=(char*)getbytes(pattern_size);
 
327
    atom_string(pattern, s_pattern, pattern_size);
 
328
  }
 
329
  if(test->a_type==A_SYMBOL) {
 
330
    s_test=test->a_w.w_symbol->s_name;
 
331
  } else {
 
332
    test_size=sizeof(char)*MAXPDSTRING;
 
333
    s_test=(char*)getbytes(test_size);
 
334
    atom_string(test, s_test, test_size);
 
335
  }
 
336
 
 
337
 
 
338
  result = OSC_PatternMatch(s_pattern, s_test, s_pattern);
 
339
 
 
340
  if(pattern_size>0) {
 
341
    freebytes(s_pattern, pattern_size);
 
342
    s_pattern=0; pattern_size=0;
 
343
  }
 
344
  if(test_size>0) {
 
345
    freebytes(s_test, test_size);
 
346
    s_test=0; test_size=0;
 
347
  }
 
348
 
 
349
 
 
350
  return result;
 
351
}
 
352
#endif /* OSC */
 
353
 
 
354
 
 
355
#ifdef MATCHBOX_REGEX
 
356
static int atommatch_regex(regex_t*pattern,  t_atom*test) {
 
357
  int result=FALSE;
 
358
  char*s_test=0;
 
359
  int test_size=0;
 
360
 
 
361
  if(0==pattern)return FALSE;
 
362
  if(0==test)   return FALSE;
 
363
 
 
364
  if(test->a_type==A_SYMBOL) {
 
365
    s_test=test->a_w.w_symbol->s_name;
 
366
  } else {
 
367
    test_size=sizeof(char)*MAXPDSTRING;
 
368
    s_test=(char*)getbytes(test_size);
 
369
    atom_string(test, s_test, test_size);
 
370
  }
 
371
 
 
372
  result=!(regexec(pattern, s_test, 0, 0, 0));
 
373
 
 
374
  if(test_size>0) {
 
375
    freebytes(s_test, test_size);
 
376
    s_test=0; test_size=0;
 
377
  } 
 
378
  
 
379
  return result;
 
380
}
 
381
 
 
382
static int listmatch_regex(int p_argc, regex_t**pattern, int t_argc, t_atom*test) {
 
383
  /* match the patterns to the test */
 
384
  int argc=p_argc;
 
385
  if(p_argc!=t_argc)
 
386
    return FALSE;
 
387
 
 
388
  while(argc--) {
 
389
    if(FALSE==atommatch_regex(*pattern++, test++)) {
 
390
      return FALSE;
 
391
    }
 
392
  }
 
393
 
 
394
  return TRUE;
 
395
}
 
396
 
 
397
static t_listlist*matchlistlist_regex(unsigned int*numresults, t_listlist*searchlist, int p_argc, t_atom*p_argv, int flags, int delete_results) {
 
398
  regex_t**regexpressions=0;
 
399
  t_listlist*matchinglist=0, *sl;
 
400
  int i=0;
 
401
  int num=0;
 
402
 
 
403
  flags|=REG_EXTENDED;
 
404
 
 
405
  /* 1st compile the patterns */
 
406
  regexpressions=(regex_t**)getbytes(sizeof(regex_t*)*p_argc);
 
407
  for(i=0; i<p_argc; i++) {
 
408
    char*s_pattern=0;
 
409
    int pattern_size=0;
 
410
    t_atom*pattern=p_argv+i;
 
411
    if(pattern->a_type==A_SYMBOL) {
 
412
      s_pattern=pattern->a_w.w_symbol->s_name;
 
413
    } else {
 
414
      pattern_size=sizeof(char)*MAXPDSTRING;
 
415
      s_pattern=(char*)getbytes(pattern_size);
 
416
      atom_string(pattern, s_pattern, pattern_size);
 
417
    }
 
418
    regexpressions[i]=(regex_t*)getbytes(sizeof(regex_t));
 
419
    if(regcomp(regexpressions[i], s_pattern, flags)) {
 
420
      z_verbose(1, "[matchbox]: invalid regular expression: %s", s_pattern);
 
421
      if(regexpressions[i])freebytes(regexpressions[i], sizeof(regex_t));
 
422
       regexpressions[i]=0;
 
423
    }
 
424
    if(pattern_size>0) {
 
425
      freebytes(s_pattern, pattern_size);
 
426
      s_pattern=0; pattern_size=0;
 
427
    }
 
428
  }
 
429
 
 
430
  /* match the patterns to the tests */
 
431
  if(FALSE==delete_results) {
 
432
    for(sl=searchlist; 0!=sl; sl=sl->next) {
 
433
      if(TRUE==listmatch_regex(p_argc, regexpressions, sl->argc, sl->argv)) {
 
434
        matchinglist=addlistlist(matchinglist, sl->argc, sl->argv);
 
435
        num++;
 
436
      }
 
437
    }
 
438
  } else if (TRUE==delete_results) {
 
439
    /* yummy: delete matching lists! */
 
440
    t_listlist*lastgood=searchlist;
 
441
    for(sl=searchlist; 0!=sl; sl=sl->next) {
 
442
      if(TRUE==listmatch_regex(p_argc, regexpressions, sl->argc, sl->argv)) {
 
443
        matchinglist=addlistlist(matchinglist, sl->argc, sl->argv);
 
444
        num++;
 
445
 
 
446
        sl=deletelistnext(lastgood); 
 
447
      } else {
 
448
        lastgood=sl;
 
449
      }
 
450
    }
 
451
  }
 
452
 
 
453
  /* clear the patterns */
 
454
  for(i=0; i<p_argc; i++) {
 
455
    if(regexpressions[i]){
 
456
      regfree(regexpressions[i]);
 
457
      freebytes(regexpressions[i], sizeof(regex_t));
 
458
    }
 
459
  }
 
460
  freebytes(regexpressions, sizeof(regex_t*)*p_argc);
 
461
 
 
462
  /* return the result */  
 
463
  if(numresults!=0)
 
464
    *numresults=num;
 
465
  return matchinglist;
 
466
}
 
467
#endif /* MATCHBOX_REGEX */
 
468
 
 
469
 
 
470
 
 
471
 
 
472
 
 
473
static int matchbox_atommatch(t_atom*pattern, t_atom*atom, int mode) {
 
474
  switch(mode) {
 
475
  default:
 
476
  case MATCHBOX_EXACT: return atommatch_exact(pattern, atom);
 
477
#ifdef MATCHBOX_OSC
 
478
  case MATCHBOX_OSC  : return atommatch_osc(pattern, atom);
 
479
#endif /* OSC */
 
480
  }
 
481
  return atommatch_exact(pattern, atom);
 
482
}
 
483
 
 
484
static int matchlist(int argc_pattern, t_atom*argv_pattern,
 
485
                     int argc, t_atom*argv, int mode) {
 
486
  int i=0;
 
487
 
 
488
  if(argc!=argc_pattern)
 
489
    return FALSE;
 
490
 
 
491
  for(i=0; i<argc; i++) {
 
492
    if(0==matchbox_atommatch(argv_pattern+i, argv+i, mode))
 
493
      return FALSE;
 
494
  }
 
495
  
 
496
  return TRUE;
 
497
}
 
498
 
 
499
static t_listlist*matchlistlist(unsigned int*numresults, t_listlist*searchlist, int p_argc, t_atom*p_argv, int mode, int delete_results) {
 
500
  unsigned int num=0;
 
501
  t_listlist*matchinglist=0, *sl;
 
502
 
 
503
  /* extra handling of regex matching (because we want to compile only once */
 
504
#ifdef MATCHBOX_REGEX
 
505
  if(MATCHBOX_REGEX==mode) {
 
506
    matchinglist=matchlistlist_regex(&num, searchlist, p_argc, p_argv, 0, delete_results);
 
507
  } else 
 
508
#endif /* MATCHBOX_REGEX */
 
509
  /* normal matching */
 
510
  if(FALSE==delete_results) {
 
511
    for(sl=searchlist->next; 0!=sl; sl=sl->next) {
 
512
      if(matchlist(p_argc, p_argv, sl->argc, sl->argv, mode)) {
 
513
        matchinglist=addlistlist(matchinglist, sl->argc, sl->argv);
 
514
        num++;
 
515
      }
 
516
    }
 
517
  } else if (TRUE==delete_results) {
 
518
    /* yummy: delete matching lists! */
 
519
    t_listlist*lastgood=searchlist;
 
520
    for(sl=searchlist->next; 0!=sl; sl=sl->next) {
 
521
      if(matchlist(p_argc, p_argv, sl->argc, sl->argv, mode)) {
 
522
        matchinglist=addlistlist(matchinglist, sl->argc, sl->argv);
 
523
        num++;
 
524
 
 
525
        sl=deletelistnext(lastgood);
 
526
      } else {
 
527
        lastgood=sl;
 
528
      }
 
529
    }
 
530
  }
 
531
 
 
532
  if(numresults!=0)
 
533
    *numresults=num;
 
534
  return matchinglist;
 
535
}
 
536
 
 
537
 
 
538
static void matchbox_list(t_matchbox*x, t_symbol*s, int argc, t_atom*argv) {
 
539
  unsigned int results=0;
 
540
  int mode=x->x_mode;
 
541
  t_listlist*resultlist=matchlistlist(&results, x->x_lists, argc, argv, mode, FALSE);
 
542
  t_listlist*dummylist;
 
543
 
 
544
  outlet_float(x->x_outNumResults, (t_float)results);
 
545
  
 
546
  for(dummylist=resultlist; 0!=dummylist; dummylist=dummylist->next)
 
547
    outlet_list(x->x_outResult,  &s_list, dummylist->argc, dummylist->argv);
 
548
}
 
549
 
 
550
static void matchbox_add(t_matchbox*x, t_symbol*s, int argc, t_atom*argv) {
 
551
  /* 1st match, whether we already have this entry */
 
552
  if(matchlistlist(0, x->x_lists, argc, argv, MATCHBOX_EXACT, FALSE)) {
 
553
    /* already there, skip the rest */
 
554
    z_verbose(1, "[matchbox]: refusing to add already existing list to buffer...");
 
555
    return;
 
556
  }
 
557
 
 
558
  /* 2nd if this is a new entry, add it */
 
559
  x->x_lists=addlistlist(x->x_lists, argc, argv);
 
560
  x->x_numlists++;
 
561
}
 
562
 
 
563
static void matchbox_delete(t_matchbox*x, t_symbol*s, int argc, t_atom*argv) {
 
564
  unsigned int results=0;
 
565
  int mode=x->x_mode;
 
566
  t_listlist*resultlist=matchlistlist(&results, x->x_lists, argc, argv, mode, TRUE);
 
567
  t_listlist*dummylist;
 
568
  t_symbol*delsym=gensym("deleted");
 
569
 
 
570
  x->x_numlists-=results;
 
571
 
 
572
  outlet_float(x->x_outNumResults, (t_float)results);
 
573
  
 
574
  for(dummylist=resultlist; 0!=dummylist; dummylist=dummylist->next)
 
575
    outlet_anything(x->x_outResult, delsym, dummylist->argc, dummylist->argv);
 
576
}
 
577
 
 
578
static void matchbox_dump(t_matchbox*x) {
 
579
  t_listlist*lp=0;
 
580
 
 
581
  if(0==x->x_lists || 0==x->x_lists->next){
 
582
    outlet_float(x->x_outNumResults, 0);
 
583
    return;
 
584
  }
 
585
 
 
586
  outlet_float(x->x_outNumResults, x->x_numlists);
 
587
 
 
588
  for(lp=x->x_lists->next; 0!=lp; lp=lp->next)
 
589
  {
 
590
    outlet_list(x->x_outResult,  &s_list, lp->argc, lp->argv);
 
591
  }
 
592
}
 
593
 
 
594
 
 
595
static void matchbox_clear(t_matchbox*x) {
 
596
  clearlistlist(x->x_lists);
 
597
  x->x_numlists=0;
 
598
}
 
599
 
 
600
 
 
601
static void matchbox_mode(t_matchbox*x, t_symbol*s) {
 
602
  if(gensym("==")==s)
 
603
    x->x_mode=MATCHBOX_EXACT;
 
604
  else if (gensym("OSC")==s) {
 
605
#ifdef MATCHBOX_OSC
 
606
    x->x_mode=MATCHBOX_OSC;
 
607
#else
 
608
     pd_error(x, "[matchbox] has been compiled without 'OSC' support; ignoring your request");
 
609
#endif /* MATCHBOX_OSC */
 
610
  } else if(gensym("regex")==s) {
 
611
#ifdef MATCHBOX_REGEX
 
612
    x->x_mode=MATCHBOX_REGEX;
 
613
#else
 
614
    pd_error(x, "[matchbox] has been compiled without 'regex' support; ignoring your request");
 
615
#endif /* MATCHBOX_REGEX */
 
616
  } else {
 
617
    pd_error(x, "mode '%s' is unknown, switching to 'exact' mode", s->s_name);
 
618
    x->x_mode=MATCHBOX_EXACT;
 
619
  }
 
620
}
 
621
 
 
622
static void *matchbox_new(t_symbol *s, int argc, t_atom*argv)
 
623
{
 
624
  t_matchbox *x = (t_matchbox *)pd_new(matchbox_class);
 
625
 
 
626
  inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym("add"));
 
627
 
 
628
  x->x_outResult    =outlet_new(&x->x_obj, gensym("list"));
 
629
  x->x_outNumResults=outlet_new(&x->x_obj, &s_float);
 
630
 
 
631
 
 
632
  x->x_lists=(t_listlist*)getbytes(sizeof(t_listlist));
 
633
  x->x_lists->next=0;
 
634
  x->x_lists->argc=0;
 
635
  x->x_lists->argv=0;
 
636
  x->x_numlists=0;
 
637
 
 
638
  x->x_mode = MATCHBOX_EXACT;
 
639
 
 
640
  if(argc && argv->a_type==A_SYMBOL) {
 
641
    matchbox_mode(x, atom_getsymbol(argv));
 
642
  }
 
643
 
 
644
 
 
645
  return (x);
 
646
}
 
647
 
 
648
static void matchbox_free(t_matchbox *x)
 
649
{
 
650
  matchbox_clear(x);
 
651
  freebytes(x->x_lists, sizeof(t_listlist));  
 
652
  x->x_lists=0;
 
653
}
 
654
 
 
655
static void matchbox_help(t_matchbox*x)
 
656
{
 
657
  post("\n%c matchbox\t\t:: find a list in a pool of lists", HEARTSYMBOL);
 
658
}
 
659
 
 
660
void matchbox_setup(void)
 
661
{
 
662
#ifdef MATCHBOX_OSC
 
663
  post("matchbox: OSC-pattern matching code (c) Matt Wright, CNMAT");
 
664
#endif /* MATCHBOX_OSC */
 
665
 
 
666
 
 
667
  matchbox_class = class_new(gensym("matchbox"), (t_newmethod)matchbox_new, 
 
668
                         (t_method)matchbox_free, sizeof(t_matchbox), 0, A_GIMME, 0);
 
669
 
 
670
  class_addlist  (matchbox_class, matchbox_list);
 
671
 
 
672
  class_addmethod(matchbox_class, (t_method)matchbox_add, gensym("add"), A_GIMME, 0);
 
673
  class_addmethod(matchbox_class, (t_method)matchbox_delete, gensym("delete"), A_GIMME, 0);
 
674
  class_addmethod(matchbox_class, (t_method)matchbox_clear, gensym("clear"), A_NULL, 0);
 
675
  class_addmethod(matchbox_class, (t_method)matchbox_dump, gensym("dump"), A_NULL);
 
676
 
 
677
  class_addmethod(matchbox_class, (t_method)matchbox_mode, gensym("mode"), A_SYMBOL, 0);
 
678
 
 
679
  class_addmethod(matchbox_class, (t_method)matchbox_help, gensym("help"), A_NULL);
 
680
  zexy_register("matchbox");
 
681
}