/********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ /* Wordlist manipulation stuff. */ #include #include #include #include /* Determine the length of a word list. */ int wl_length(wordlist *wlist) { int i = 0; wordlist *wl; for (wl = wlist; wl; wl = wl->wl_next) i++; return (i); } /* Free the storage used by a word list. */ void wl_free(wordlist *wlist) { wordlist *wl, *nw; for (wl = wlist; wl; wl = nw) { nw = wl->wl_next; tfree(wl->wl_word); tfree(wl); } return; } /* Copy a wordlist and the words. */ wordlist * wl_copy(wordlist *wlist) { wordlist *wl, *nwl = NULL, *w = NULL; for (wl = wlist; wl; wl = wl->wl_next) { if (nwl == NULL) { nwl = w = alloc(struct wordlist); w->wl_prev = NULL; w->wl_next = NULL; } else { w->wl_next = alloc(struct wordlist); w->wl_next->wl_prev = w; w = w->wl_next; w->wl_next = NULL; } w->wl_word = copy(wl->wl_word); } return (nwl); } /* Substitute a wordlist for one element of a wordlist, and return a * pointer to the last element of the inserted list. */ wordlist * wl_splice(wordlist *elt, wordlist *list) { if (list) list->wl_prev = elt->wl_prev; if (elt->wl_prev) elt->wl_prev->wl_next = list; if (list) { while (list->wl_next) list = list->wl_next; list->wl_next = elt->wl_next; } if (elt->wl_next) elt->wl_next->wl_prev = list; tfree(elt->wl_word); tfree(elt); return (list); } static void printword(char *string, FILE *fp) { char *s; if (string) for (s = string; *s; s++) putc((strip(*s)), fp); return; } /* Print a word list. (No \n at the end...) */ void wl_print(wordlist *wlist, FILE *fp) { wordlist *wl; for (wl = wlist; wl; wl = wl->wl_next) { printword(wl->wl_word, fp); if (wl->wl_next) putc(' ', fp); } return; } /* Turn an array of char *'s into a wordlist. */ wordlist * wl_build(char **v) { wordlist *wlist = NULL; wordlist *wl = NULL; wordlist *cwl; while (*v) { cwl = alloc(struct wordlist); cwl->wl_prev = wl; if (wl) wl->wl_next = cwl; else { wlist = cwl; cwl->wl_next = NULL; } cwl->wl_word = copy(*v); wl = cwl; v++; } return (wlist); } char ** wl_mkvec(wordlist *wl) { int len, i; char **v; len = wl_length(wl); v = (char **) tmalloc((len + 1) * sizeof (char **)); for (i = 0; i < len; i++) { v[i] = copy(wl->wl_word); wl = wl->wl_next; } v[i] = NULL; return (v); } /* Nconc two wordlists together. */ wordlist * wl_append(wordlist *wlist, wordlist *nwl) { wordlist *wl; if (wlist == NULL) return (nwl); if (nwl == NULL) return (wlist); for (wl = wlist; wl->wl_next; wl = wl->wl_next); wl->wl_next = nwl; nwl->wl_prev = wl; return (wlist); } /* Reverse a word list. */ wordlist * wl_reverse(wordlist *wl) { wordlist *w, *t; for (w = wl; ; w = t) { t = w->wl_next; w->wl_next = w->wl_prev; w->wl_prev = t; if (t == NULL) break; } return (w); } /* Convert a wordlist into a string. */ char * wl_flatten(wordlist *wl) { char *buf; wordlist *tw; int i = 0; for (tw = wl; tw; tw = tw->wl_next) i += strlen(tw->wl_word) + 1; buf = tmalloc(i + 1); *buf = 0; while (wl != NULL) { (void) strcat(buf, wl->wl_word); if (wl->wl_next) (void) strcat(buf, " "); wl = wl->wl_next; } return (buf); } /* Return the nth element of a wordlist, or the last one if n is too * big. Numbering starts at 0... */ wordlist * wl_nthelem(int i, wordlist *wl) { wordlist *ww = wl; while ((i-- > 0) && ww->wl_next) ww = ww->wl_next; return (ww); } static int wlcomp(const void *a, const void *b) { char **s = (char **) a; char **t = (char **) b; return (strcmp(*s, *t)); } void wl_sort(wordlist *wl) { int i = 0; wordlist *ww = wl; char **stuff; for (i = 0; ww; i++) ww = ww->wl_next; if (i < 2) return; stuff = (char **) tmalloc(i * sizeof (char *)); for (i = 0, ww = wl; ww; i++, ww = ww->wl_next) stuff[i] = ww->wl_word; qsort((char *) stuff, i, sizeof (char *), wlcomp); for (i = 0, ww = wl; ww; i++, ww = ww->wl_next) ww->wl_word = stuff[i]; tfree(stuff); return; } /* Return a range of wordlist elements... */ wordlist * wl_range(wordlist *wl, int low, int up) { int i; wordlist *tt; bool rev = FALSE; if (low > up) { i = up; up = low; low = i; rev = TRUE; } up -= low; while (wl && (low > 0)) { tt = wl->wl_next; tfree(wl->wl_word); tfree(wl); wl = tt; if (wl) wl->wl_prev = NULL; low--; } tt = wl; while (tt && (up > 0)) { tt = tt->wl_next; up--; } if (tt && tt->wl_next) { wl_free(tt->wl_next); tt->wl_next = NULL; } if (rev) wl = wl_reverse(wl); return (wl); }