/*------------------------------------------------------------------------- * * list.c-- * various list handling routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $ * * NOTES * XXX a few of the following functions are duplicated to handle * List of pointers and List of integers separately. Some day, * someone should unify them. - ay 11/2/94 * This file needs cleanup. * * HISTORY * AUTHOR DATE MAJOR EVENT * Andrew Yu Oct, 1994 file creation * *------------------------------------------------------------------------- */ #include #include "postgres.h" #include "nodes/pg_list.h" #include "nodes/parsenodes.h" #include "utils/builtins.h" /* for namecpy */ #include "utils/elog.h" #include "utils/palloc.h" List * makeList(void *elem, ...) { va_list args; List *retval = NIL; List *temp = NIL; List *tempcons = NIL; va_start(args, elem); temp = elem; while (temp != (void *) -1) { temp = lcons(temp, NIL); if (tempcons == NIL) retval = temp; else lnext(tempcons) = temp; tempcons = temp; temp = va_arg(args, void *); } va_end(args); return (retval); } List * lcons(void *datum, List *list) { List *l = makeNode(List); lfirst(l) = datum; lnext(l) = list; return l; } List * lappend(List *list, void *obj) { return nconc(list, lcons(obj, NIL)); } Value * makeInteger(long i) { Value *v = makeNode(Value); v->type = T_Integer; v->val.ival = i; return v; } Value * makeFloat(double d) { Value *v = makeNode(Value); v->type = T_Float; v->val.dval = d; return v; } Value * makeString(char *str) { Value *v = makeNode(Value); v->type = T_String; v->val.str = str; return v; } /* n starts with 0 */ void * nth(int n, List *l) { /* XXX assume list is long enough */ while(n > 0) { l = lnext(l); n--; } return lfirst(l); } /* this is here solely for rt_store. Get rid of me some day! */ void set_nth(List *l, int n, void *elem) { /* XXX assume list is long enough */ while(n > 0) { l = lnext(l); n--; } lfirst(l) = elem; return; } int length(List *l) { int i=0; while(l!=NIL) { l = lnext(l); i++; } return i; } void freeList(List *list) { while(list!=NIL) { List *l = list; list = lnext(list); pfree(l); } } /* * below are for backwards compatibility */ List * append(List *l1, List *l2) { List *newlist, *newlist2, *p; if (l1==NIL) return copyObject(l2); newlist = copyObject(l1); newlist2 = copyObject(l2); for (p=newlist; lnext(p)!=NIL; p=lnext(p)) ; lnext(p) = newlist2; return newlist; } /* * below are for backwards compatibility */ List * intAppend(List *l1, List *l2) { List *newlist, *newlist2, *p; if (l1==NIL) return listCopy(l2); newlist = listCopy(l1); newlist2 = listCopy(l2); for (p=newlist; lnext(p)!=NIL; p=lnext(p)) ; lnext(p) = newlist2; return newlist; } List * nconc(List *l1, List *l2) { List *temp; if (l1 == NIL) return l2; if (l2 == NIL) return l1; if (l1 == l2) elog(WARN, "tryout to nconc a list to itself"); for (temp = l1; lnext(temp)!=NULL; temp = lnext(temp)) ; lnext(temp) = l2; return(l1); /* list1 is now list1[]list2 */ } List * nreverse(List *list) { List *rlist = NIL; List *p = NIL; if(list==NULL) return(NIL); if (length(list) == 1) return(list); for (p = list; p!=NULL; p = lnext(p)) { rlist = lcons(lfirst(p),rlist); } lfirst(list) = lfirst(rlist); lnext(list) = lnext(rlist); return(list); } /* * same * * Returns t if two lists contain the same elements. * now defined in lispdep.c * * XXX only good for IntList -ay */ bool same(List *foo, List *bar) { List *temp = NIL; if (foo == NULL) return (bar==NULL); if (bar == NULL) return (foo==NULL); if (length(foo) == length(bar)) { foreach (temp,foo) { if (!intMember((int)lfirst(temp),bar)) return(false); } return(true); } return(false); } List * LispUnion(List *foo, List *bar) { List *retval = NIL; List *i = NIL; List *j = NIL; if (foo==NIL) return(bar); /* XXX - should be copy of bar */ if (bar==NIL) return(foo); /* XXX - should be copy of foo */ foreach (i,foo) { foreach (j,bar) { if (! equal(lfirst(i), lfirst(j))) { retval = lappend(retval,lfirst(i)); break; } } } foreach(i,bar) { retval = lappend(retval,lfirst(i)); } return(retval); } List * LispUnioni(List *foo, List *bar) { List *retval = NIL; List *i = NIL; List *j = NIL; if (foo==NIL) return(bar); /* XXX - should be copy of bar */ if (bar==NIL) return(foo); /* XXX - should be copy of foo */ foreach (i,foo) { foreach (j,bar) { if (lfirsti(i) != lfirsti(j)) { retval = lappendi(retval,lfirst(i)); break; } } } foreach(i,bar) { retval = lappendi(retval, lfirsti(i)); } return(retval); } /* * member() * - nondestructive, returns t iff foo is a member of the list * bar */ bool member(void *foo, List *bar) { List *i; foreach (i,bar) if (equal((Node*)(lfirst(i)),(Node*)foo)) return(true); return(false); } bool intMember(int foo, List *bar) { List *i; foreach (i,bar) if (foo == (int)lfirst(i)) return(true); return(false); } /* * lremove - * only does pointer comparisons. Removes 'elem' from the the linked list. */ List * lremove(void *elem, List *list) { List *l; List *prev = NIL; List *result = list; foreach(l, list) { if (elem == lfirst(l)) break; prev = l; } if (l!=NULL) { if (prev == NIL) { result = lnext(list); } else { lnext(prev) = lnext(l); } } return result; } List * LispRemove(void *elem, List *list) { List *temp = NIL; List *prev = NIL; if (equal(elem, lfirst(list))) return lnext(list); temp = lnext(list); prev = list; while(temp!=NIL) { if (equal(elem, lfirst(temp))) { lnext(prev) = lnext(temp); break; } temp = lnext(temp); prev = lnext(prev); } return(list); } List * intLispRemove(int elem, List *list) { List *temp = NIL; List *prev = NIL; if (elem == (int)lfirst(list)) return lnext(list); temp = lnext(list); prev = list; while(temp!=NIL) { if (elem == (int)lfirst(temp)) { lnext(prev) = lnext(temp); break; } temp = lnext(temp); prev = lnext(prev); } return(list); } List * set_difference(List *list1, List *list2) { List *temp1 = NIL; List *result = NIL; if (list2==NIL) return(list1); foreach (temp1, list1) { if (!member(lfirst(temp1), list2)) result = lappend(result, lfirst(temp1)); } return(result); } List * set_differencei(List *list1, List *list2) { List *temp1 = NIL; List *result = NIL; if (list2==NIL) return(list1); foreach (temp1, list1) { if (!intMember(lfirsti(temp1), list2)) result = lappendi(result, lfirst(temp1)); } return(result); }