source: util.c @ 5639bf2

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