source: util.c @ ae4cd12

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since ae4cd12 was 65ad073, checked in by James M. Kretchmar <kretch@mit.edu>, 22 years ago
'addbuddy zephyr <user>' and 'delbuddy zephyr <user>' now work.
  • Property mode set to 100644
File size: 18.4 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <malloc.h>
6#include <unistd.h>
7#include <ctype.h>
8
9static const char fileIdent[] = "$Id$";
10
11void sepbar(char *in) {
12  char buff[1024];
13  WINDOW *sepwin;
14  owl_messagelist *ml;
15  owl_view *v;
16  int x, y, i;
17  char *foo, *appendtosepbar;
18
19  sepwin=owl_global_get_curs_sepwin(&g);
20  ml=owl_global_get_msglist(&g);
21  v=owl_global_get_current_view(&g);
22
23  werase(sepwin);
24  wattron(sepwin, A_REVERSE);
25  whline(sepwin, ACS_HLINE, owl_global_get_cols(&g));
26
27  wmove(sepwin, 0, 2); 
28
29  if (owl_messagelist_get_size(ml)==0) {
30    strcpy(buff, " (-/-) ");
31  } else {
32    snprintf(buff, 1024, " (%i/%i/%i) ", owl_global_get_curmsg(&g)+1,
33            owl_view_get_size(v),
34            owl_messagelist_get_size(ml));
35  }
36  waddstr(sepwin, buff);
37
38  foo=owl_view_get_filtname(v);
39  if (strcmp(foo, "all")) wattroff(sepwin, A_REVERSE);
40  waddstr(sepwin, " ");
41  waddstr(sepwin, owl_view_get_filtname(v));
42  waddstr(sepwin, " ");
43  if (strcmp(foo, "all")) wattron(sepwin, A_REVERSE);
44
45  if (owl_mainwin_is_curmsg_truncated(owl_global_get_mainwin(&g))) {
46    getyx(sepwin, y, x);
47    wmove(sepwin, y, x+2);
48    wattron(sepwin, A_BOLD);
49    waddstr(sepwin, " <truncated> ");
50    wattroff(sepwin, A_BOLD);
51  }
52
53  i=owl_mainwin_get_last_msg(owl_global_get_mainwin(&g));
54  if ((i != -1) &&
55      (i < owl_view_get_size(v)-1)) {
56    getyx(sepwin, y, x);
57    wmove(sepwin, y, x+2);
58    wattron(sepwin, A_BOLD);
59    waddstr(sepwin, " <more> ");
60    wattroff(sepwin, A_BOLD);
61  }
62
63  if (owl_global_get_rightshift(&g)>0) {
64    getyx(sepwin, y, x);
65    wmove(sepwin, y, x+2);
66    snprintf(buff, 1024, " right: %i ", owl_global_get_rightshift(&g));
67    waddstr(sepwin, buff);
68  }
69
70  if (owl_global_is_zaway(&g)) {
71    getyx(sepwin, y, x);
72    wmove(sepwin, y, x+2);
73    wattron(sepwin, A_BOLD);
74    wattroff(sepwin, A_REVERSE);
75    waddstr(sepwin, " ZAWAY ");
76    wattron(sepwin, A_REVERSE);
77    wattroff(sepwin, A_BOLD);
78  }
79
80  if (owl_global_get_curmsg_vert_offset(&g)) {
81    getyx(sepwin, y, x);
82    wmove(sepwin, y, x+2);
83    wattron(sepwin, A_BOLD);
84    wattroff(sepwin, A_REVERSE);
85    waddstr(sepwin, " SCROLL ");
86    wattron(sepwin, A_REVERSE);
87    wattroff(sepwin, A_BOLD);
88  }
89 
90  if (in) {
91    getyx(sepwin, y, x);
92    wmove(sepwin, y, x+2);
93    waddstr(sepwin, in);
94  }
95
96  appendtosepbar = owl_global_get_appendtosepbar(&g);
97  if (appendtosepbar && *appendtosepbar) {
98    getyx(sepwin, y, x);
99    wmove(sepwin, y, x+2);
100    waddstr(sepwin, " ");
101    waddstr(sepwin, owl_global_get_appendtosepbar(&g));
102    waddstr(sepwin, " ");
103  }
104
105  getyx(sepwin, y, x);
106  wmove(sepwin, y, owl_global_get_cols(&g)-1);
107   
108  wattroff(sepwin, A_BOLD);
109  wattroff(sepwin, A_REVERSE);
110  wnoutrefresh(sepwin);
111}
112
113
114void pophandler_quit(int ch) {
115  if (ch=='q') {
116    owl_popwin_close(owl_global_get_popwin(&g));
117  }
118}
119
120char **atokenize(char *buffer, char *sep, int *i) {
121  /* each element of return must be freed by user */
122  char **args;
123  char *workbuff, *foo;
124  int done=0, first=1, count=0;
125
126  workbuff=owl_malloc(strlen(buffer)+1);
127  memcpy(workbuff, buffer, strlen(buffer)+1);
128
129  args=NULL;
130  while (!done) {
131    if (first) {
132      first=0;
133      foo=(char *)strtok(workbuff, sep);
134    } else {
135      foo=(char *)strtok(NULL, sep);
136    }
137    if (foo==NULL) {
138      done=1;
139    } else {
140      args=(char **)owl_realloc(args, sizeof(char *) * (count+1));
141      args[count]=owl_malloc(strlen(foo)+1);
142      strcpy(args[count], foo);
143      count++;
144    }
145  }
146  *i=count;
147  owl_free(workbuff);
148  return(args);
149}
150
151char *skiptokens(char *buff, int n) {
152  /* skips n tokens and returns where that would be.
153   * TODO: handle quotes more sanely. */
154 
155  int inquotes=0;
156  while (*buff && n>0) {
157      while (*buff == ' ') buff++;
158      while (*buff && (inquotes || *buff != ' ')) { 
159        if (*buff == '"' || *buff == '\'') inquotes=!inquotes;
160        buff++;
161      }
162      while (*buff == ' ') buff++;
163      n--;
164  }
165  return buff;
166}
167
168void atokenize_free(char **tok, int nels) {
169  int i;
170  for (i=0; i<nels; i++) {
171    owl_free(tok[i]);
172  }
173  owl_free(tok);
174}
175
176
177void owl_parsefree(char **argv, int argc) {
178  int i;
179
180  if (!argv) return;
181 
182  for (i=0; i<argc; i++) {
183    if (argv[i]) owl_free(argv[i]);
184  }
185  owl_free(argv);
186}
187
188char **owl_parseline(char *line, int *argc) {
189  /* break a command line up into argv, argc.  The caller must free
190     the returned values.  If there is an error argc will be set to
191     -1, argv will be NULL and the caller does not need to free
192     anything */
193
194  char **argv;
195  int i, len, between=1;
196  char *curarg;
197  char quote;
198
199  argv=owl_malloc(sizeof(char *));
200  len=strlen(line);
201  curarg=owl_malloc(len+10);
202  strcpy(curarg, "");
203  quote='\0';
204  *argc=0;
205  for (i=0; i<len+1; i++) {
206    /* find the first real character */
207    if (between) {
208      if (line[i]==' ' || line[i]=='\t' || line[i]=='\0') {
209        continue;
210      } else {
211        between=0;
212        i--;
213        continue;
214      }
215    }
216
217    /* deal with a quote character */
218    if (line[i]=='"' || line[i]=="'"[0]) {
219      /* if this type of quote is open, close it */
220      if (quote==line[i]) {
221        quote='\0';
222        continue;
223      }
224
225      /* if no quoting is open then open with this */
226      if (quote=='\0') {
227        quote=line[i];
228        continue;
229      }
230
231      /* if another type of quote is open then treat this as a literal */
232      curarg[strlen(curarg)+1]='\0';
233      curarg[strlen(curarg)]=line[i];
234      continue;
235    }
236
237    /* if it's not a space or end of command, then use it */
238    if (line[i]!=' ' && line[i]!='\t' && line[i]!='\n' && line[i]!='\0') {
239      curarg[strlen(curarg)+1]='\0';
240      curarg[strlen(curarg)]=line[i];
241      continue;
242    }
243
244    /* otherwise, if we're not in quotes, add the whole argument */
245    if (quote=='\0') {
246      /* add the argument */
247      argv=owl_realloc(argv, sizeof(char *)*((*argc)+1));
248      argv[*argc]=owl_malloc(strlen(curarg)+2);
249      strcpy(argv[*argc], curarg);
250      *argc=*argc+1;
251      strcpy(curarg, "");
252      between=1;
253      continue;
254    }
255
256    /* if it is a space and we're in quotes, then use it */
257    curarg[strlen(curarg)+1]='\0';
258    curarg[strlen(curarg)]=line[i];
259  }
260
261  /* check for unbalanced quotes */
262  if (quote!='\0') {
263    owl_parsefree(argv, *argc);
264    *argc=-1;
265    return(NULL);
266  }
267
268  return(argv);
269}
270
271
272
273int owl_util_find_trans(char *in, int len) {
274  /* return the index of the last char before a change from the first
275     one */
276  int i;
277  for (i=1; i<len; i++) {
278    if (in[i] != in[0]) return(i-1);
279  }
280  return(i);
281}
282
283
284void downstr(char *foo) {
285  int i;
286  for (i=0; foo[i]!='\0'; i++) {
287    foo[i]=tolower(foo[i]);
288  }
289}
290
291char *stristr(char *a, char *b) {
292  /* exactly like strstr but it's case insensitive */
293  char *x, *y, *ret;
294
295  if ((x=owl_strdup(a))==NULL) return(NULL);
296  if ((y=owl_strdup(b))==NULL) return(NULL);
297  downstr(x);
298  downstr(y);
299  ret=strstr(x, y);
300  if (ret==NULL) {
301    owl_free(x);
302    owl_free(y);
303    return(NULL);
304  }
305  ret=ret-x+a;
306  owl_free(x);
307  owl_free(y);
308  return(ret);
309}
310
311char *owl_util_uniq(char *A, char *B, char *prohibit) {
312  /* Caller must free response.
313     Takes in strings which are space-separated lists of tokens
314     and returns a single string containing no token more than once.
315     If prohibit is non-null, no token may start with a character
316     in prohibit.
317  */
318 
319  char *cat, **tok;
320  int toklen, i, j, first=1;
321  cat = owl_malloc(strlen(A)+strlen(B)+3);
322  strcpy(cat, A);
323  strcat(cat, " ");
324  strcat(cat, B);
325  tok = atokenize(cat, " ", &toklen);
326  strcpy(cat, "");
327  for (i=0; i<toklen; i++) {
328    int dup=0;
329    for (j=0; j<i; j++) {
330      if (!strcmp(tok[i], tok[j])) dup=1;
331    }
332    if (!dup && (!prohibit || !strchr(prohibit, tok[i][0]))) {
333      if (!first) {
334        strcat(cat, " ");
335      }
336      first=0;
337      strcat(cat, tok[i]);
338    }
339  }
340  atokenize_free(tok, toklen);
341  return(cat);
342}
343
344int only_whitespace(char *s) {
345  /* returns if a string is only whitespace */
346
347  int i;
348  for (i=0; s[i]; i++) {
349    if (!isspace((int) s[i])) return(0);
350  }
351  return(1);
352}
353
354/* hooks for doing memory allocation et. al. in owl */
355
356void *owl_malloc(size_t size) {
357  return(malloc(size));
358}
359
360void owl_free(void *ptr) {
361  free(ptr);
362}
363
364char *owl_strdup(const char *s1) {
365  return(strdup(s1));
366}
367
368void *owl_realloc(void *ptr, size_t size) {
369  return(realloc(ptr, size));
370}
371
372char *owl_sprintf(const char *fmt, ...) {
373  /* allocates memory and returns the string or null.
374   * caller must free the string.
375   * from Linux sprintf man page.
376   */
377 
378  int n, size = 100;
379  char *p;
380  va_list ap;
381  if ((p = owl_malloc (size)) == NULL) return (NULL);
382  while (1) {
383    /* Try to print in the allocated space. */
384    va_start(ap, fmt);
385    n = vsnprintf (p, size, fmt, ap);
386    va_end(ap);
387    /* If that worked, return the string. */
388    if (n > -1 && n < size)
389      return p;
390    /* Else try again with more space. */
391    if (n > -1)    /* glibc 2.1 */
392      size = n+1; /* precisely what is needed */
393    else           /* glibc 2.0 */
394      size *= 2;  /* twice the old size */
395    if ((p = owl_realloc (p, size)) == NULL)
396      return NULL;
397  }
398}
399
400char *short_zuser(char *in) {
401  /* the caller must free the return */
402  char *out, *ptr;
403
404  out=owl_strdup(in);
405  ptr=strchr(out, '@');
406  if (ptr) {
407    if (!strcasecmp(ptr+1, ZGetRealm())) {
408      *ptr='\0';
409    }
410  }
411  return(out);
412}
413
414
415char *long_zuser(char *in) {
416  /* the caller must free the return */
417  char *ptr;
418
419  if (NULL != (ptr=strchr(in, '@'))) {
420    return owl_strdup(in);
421  } else {
422    return owl_sprintf("%s@%s", in, ZGetRealm());
423  }
424}
425
426
427char *owl_util_smartstripped_user(char *in) {
428  /* strip out the instance from a zsender's principal.  Preserves the
429   * realm if present.  daemon.webzephyr is a special case.  The
430   * caller must free the return */
431
432  char *ptr, *realm, *out;
433
434  out=owl_strdup(in);
435
436  /* bail immeaditly if we don't have to do any work */
437  ptr=strchr(in, '.');
438  if (!strchr(in, '/') && !ptr) {
439    /* no '/' and no '.' */
440    return(out);
441  }
442  if (ptr && strchr(in, '@') && (ptr > strchr(in, '@'))) {
443    /* There's a '.' but it's in the realm */
444    return(out);
445  }
446  if (!strncasecmp(in, "daemon.webzephyr", strlen("daemon.webzephyr"))) {
447    return(out);
448  }
449
450
451  /* remove the realm from ptr, but hold on to it */
452  realm=strchr(out, '@');
453  if (realm) realm[0]='\0';
454
455  /* strip */
456  ptr=strchr(out, '.');
457  if (!ptr) ptr=strchr(out, '/');
458  ptr[0]='\0';
459
460  /* reattach the realm if we had one */
461  if (realm) {
462    strcat(out, "@");
463    strcat(out, realm+1);
464  }
465
466  return(out);
467}
468
469char *owl_getquoting(char *line) {
470  if (line[0]=='\0') return("'");
471  if (strchr(line, '\'')) return("\"");
472  if (strchr(line, '"')) return("'");
473  if (strchr(line, ' ')) return("'");
474  return("");
475}
476
477char *owl_util_substitute(char *in, char *from, char *to) {
478  /* Caller must free returned string.
479   * Returns a string with any occurances of 'from' replaced with 'to'.
480   * Does not currently handle backslash quoting, but may in the future.
481   */
482 
483  char *out;
484  int   outlen, tolen, fromlen, inpos=0, outpos=0;
485
486  if (!*from) return owl_strdup(in);
487
488  outlen = strlen(in)+1;
489  tolen  = strlen(to);
490  fromlen  = strlen(from);
491  out = malloc(outlen);
492
493  while (in[inpos]) {
494    if (!strncmp(in+inpos, from, fromlen)) {
495      outlen += tolen;
496      out = owl_realloc(out, outlen);
497      strcpy(out+outpos, to);
498      inpos += fromlen;
499      outpos += tolen;
500    } else {
501      out[outpos] = in[inpos];
502      inpos++; outpos++;
503    }
504  }
505  out[outpos] = '\0';
506  return(out);
507}
508
509void owl_util_tr(char *buff, char a, char b) {
510  /* replace all instances of character a in buff with the character
511     b.  buff must be null terminated */
512  int i;
513
514  owl_function_debugmsg("In: %s", buff);
515  for (i=0; buff[i]!='\0'; i++) {
516    if (buff[i]==a) buff[i]=b;
517  }
518  owl_function_debugmsg("Out: %s", buff);
519}
520
521int owl_util_string_to_color(char *color) {
522  if (!strcasecmp(color, "black")) {
523    return(OWL_COLOR_BLACK);
524  } else if (!strcasecmp(color, "red")) {
525    return(OWL_COLOR_RED);
526  } else if (!strcasecmp(color, "green")) {
527    return(OWL_COLOR_GREEN);
528  } else if (!strcasecmp(color, "yellow")) {
529    return(OWL_COLOR_YELLOW);
530  } else if (!strcasecmp(color, "blue")) {
531    return(OWL_COLOR_BLUE);
532  } else if (!strcasecmp(color, "magenta")) {
533    return(OWL_COLOR_MAGENTA);
534  } else if (!strcasecmp(color, "cyan")) {
535    return(OWL_COLOR_CYAN);
536  } else if (!strcasecmp(color, "white")) {
537    return(OWL_COLOR_WHITE);
538  } else if (!strcasecmp(color, "default")) {
539    return(OWL_COLOR_DEFAULT);
540  }
541  return(OWL_COLOR_DEFAULT);
542}
543
544char *owl_util_color_to_string(int color) {
545  if (color==OWL_COLOR_BLACK)   return("black");
546  if (color==OWL_COLOR_RED)     return("red");
547  if (color==OWL_COLOR_GREEN)   return("green");
548  if (color==OWL_COLOR_YELLOW)  return("yellow");
549  if (color==OWL_COLOR_BLUE)    return("blue");
550  if (color==OWL_COLOR_MAGENTA) return("magenta");
551  if (color==OWL_COLOR_CYAN)    return("cyan");
552  if (color==OWL_COLOR_WHITE)   return("white");
553  if (color==OWL_COLOR_DEFAULT) return("default");
554  return("Unknown color");
555}
556
557char *owl_util_get_default_tty() {
558  /* call must free the return */
559  char *out, *tmp;
560
561  if (getenv("DISPLAY")) {
562    out=owl_strdup(getenv("DISPLAY"));
563  } else if ((tmp=ttyname(fileno(stdout)))!=NULL) {
564    out=owl_strdup(tmp);
565    if (!strncmp(out, "/dev/", 5)) {
566      owl_free(out);
567      out=owl_strdup(tmp+5);
568    }
569  } else {
570    out=owl_strdup("unknown");
571  }
572  return(out);
573}
574
575
576void owl_hack_animate() {
577  owl_messagelist *ml;
578  owl_message *m;
579  owl_fmtext *fm;
580  char *text, *ptr;
581  int place;
582
583  /* grab the first message and make sure its id is 0 */
584  ml=owl_global_get_msglist(&g);
585  m=owl_messagelist_get_element(ml, 0);
586  if (!m) return;
587  if (owl_message_get_id(m)!=0) return;
588
589  fm=owl_message_get_fmtext(m);
590  text=owl_fmtext_get_text(fm);
591
592  ptr=strstr(text, "OvO");
593  if (ptr) {
594    place=ptr-text;
595    owl_fmtext_set_char(fm, place, '-');
596    owl_fmtext_set_char(fm, place+2, '-');
597
598    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
599    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
600      owl_popwin_refresh(owl_global_get_popwin(&g));
601      /* TODO: this is a broken kludge */
602      if (owl_global_get_viewwin(&g)) {
603        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
604      }
605    }
606    owl_global_set_needrefresh(&g);
607    return;
608  }
609
610  ptr=strstr(text, "-v-");
611  if (ptr) {
612    place=ptr-text;
613    owl_fmtext_set_char(fm, place, 'O');
614    owl_fmtext_set_char(fm, place+2, 'O');
615
616    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
617    if (owl_popwin_is_active(owl_global_get_popwin(&g))) {
618      owl_popwin_refresh(owl_global_get_popwin(&g));
619      /* TODO: this is a broken kludge */
620      if (owl_global_get_viewwin(&g)) {
621        owl_viewwin_redisplay(owl_global_get_viewwin(&g), 0);
622      }
623    }
624    owl_global_set_needrefresh(&g);
625    return;
626  }
627}
628
629char *owl_util_stripnewlines(char *in) {
630  /* strip leading and trailing new lines.
631     caller must free the return */
632 
633  char  *tmp, *ptr1, *ptr2, *out;
634
635  ptr1=tmp=owl_strdup(in);
636  while (ptr1[0]=='\n') {
637    ptr1++;
638  }
639  ptr2=ptr1+strlen(ptr1)-1;
640  while (ptr2[0]=='\n' && ptr2>ptr1) {
641    ptr2[0]='\0';
642    ptr2--;
643  }
644
645  out=owl_strdup(ptr1);
646  owl_free(tmp);
647  return(out);
648}
649
650/* Delete the line matching "line" from the named file.  If no such
651 * line is found the file is left intact.  If backup==1 then create a
652 * backupfile containing the original contents.  This is an
653 * inefficient impelementation which reads the entire file into
654 * memory.
655 */
656void owl_util_file_deleteline(char *filename, char *line, int backup)
657{
658  char buff[LINE], *text;
659  char *backupfilename;
660  FILE *file, *backupfile;
661  int size, newline;
662
663  /* open the file for reading */
664  file=fopen(filename, "r");
665  if (!file) {
666    owl_function_makemsg("Error opening file %s", filename);
667    return;
668  }
669 
670  /* open the backup file for writing */
671  if (backup) {
672    backupfilename=owl_sprintf("%s.backup", filename);
673    backupfile=fopen(backupfilename, "w");
674    owl_free(backupfilename);
675    if (!backupfile) {
676      owl_function_makemsg("Error opening file %s for writing", backupfilename);
677      return;
678    }
679  }
680
681  /* we'll read the entire file into memory, minus the line we don't want and
682   * and at the same time create the backup file if necessary
683   */
684  text=owl_malloc(LINE);
685  strcpy(text, "");
686  size=LINE;
687  while (fgets(buff, LINE, file)!=NULL) {
688    /* strip the newline */
689    newline=0;
690    if (buff[strlen(buff)-1]=='\n') {
691      buff[strlen(buff)-1]='\0';
692      newline=1;
693    }
694   
695    /* if we don't match the line, add to saved text in memory */
696    if (strcasecmp(buff, line)) {
697      size+=LINE;
698      text=owl_realloc(text, size);
699      strcat(text, buff);
700      if (newline) strcat(text, "\n");
701    }
702
703    /* write to backupfile if necessary */
704    if (backup) fputs(buff, backupfile);
705  }
706  if (backup) fclose(backupfile);
707  fclose(file);
708
709  /* now rewrite the original file from memory */
710  file=fopen(filename, "w");
711  if (!file) {
712    owl_function_makemsg("WARNING: Error opening %s for writing.  Use %s to restore.", filename, backupfilename);
713    owl_function_beep();
714    owl_free(line);
715    return;
716  }
717
718  fputs(text, file);
719  fclose(file);
720}
721
722/**************************************************************************/
723/************************* REGRESSION TESTS *******************************/
724/**************************************************************************/
725
726#ifdef OWL_INCLUDE_REG_TESTS
727
728#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
729
730int owl_util_regtest(void) {
731  int numfailed=0;
732
733  printf("BEGIN testing owl_util\n");
734
735  FAIL_UNLESS("owl_util_substitute 1",
736              !strcmp("foo", owl_util_substitute("foo", "", "Y")));
737  FAIL_UNLESS("owl_util_substitute 2",
738              !strcmp("fYZYZ", owl_util_substitute("foo", "o", "YZ")));
739  FAIL_UNLESS("owl_util_substitute 3",
740              !strcmp("foo", owl_util_substitute("fYZYZ", "YZ", "o")));
741  FAIL_UNLESS("owl_util_substitute 4",
742              !strcmp("/u/foo/meep", owl_util_substitute("~/meep", "~", "/u/foo")));
743
744  FAIL_UNLESS("skiptokens 1", 
745              !strcmp("bar quux", skiptokens("foo bar quux", 1)));
746  FAIL_UNLESS("skiptokens 2", 
747              !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
748
749  FAIL_UNLESS("owl_util_uniq 1", 
750              !strcmp("foo bar x", owl_util_uniq("foo", "bar x", "-")));
751  FAIL_UNLESS("owl_util_uniq 2", 
752              !strcmp("foo bar x", owl_util_uniq("foo", "bar -y x", "-")));
753  FAIL_UNLESS("owl_util_uniq 3", 
754              !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
755
756  if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
757  printf("END testing owl_util (%d failures)\n", numfailed);
758  return(numfailed);
759}
760
761#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.