C:/Users/Dennis/src/lang/russell.orig/src/stree/listops.c

Go to the documentation of this file.
00001 /* 
00002  *   Primitive list operations.
00003  *   These and the roiutines in mknode.c should be the only routines
00004  *   that know about the implementation of lists.
00005  */
00006 
00007 # include "parm.h"
00008 
00009 # include <stdio.h>
00010 
00011 # include <varargs.h>
00012 
00013 # include "ststructs.mh"
00014 
00015 # include "Array.h"
00016 
00017 # ifdef BAD
00018     extern boolean BADflag;
00019 # endif
00020 
00021 extern int stsize[];
00022 extern int stptrs[];
00023 extern int stmkfields[];
00024 
00025 
00026 /*
00027  * add node e at beginning of list l.
00028  * if e is NIL do nothing
00029  * return l
00030  */
00031 NODE * addleft(l,e)
00032 NODE *l,*e;
00033 {
00034     register ConsNode * p;
00035     if (e == NIL) return(l);
00036 
00037 #   ifdef DEBUG
00038         if( !is_list(l) ) {
00039             dbgmsg("addleft: bad arg: kind = %s\n", kindname(l->kind));
00040             abort();
00041         }
00042 #   endif
00043 
00044     if( is_empty(l) ) {
00045         p = cn_cons(lock(e),NIL);
00046         l->lh_first = p;
00047         l->lh_last = p;
00048     } else {
00049         l -> lh_first = cn_cons(lock(e), l -> lh_first);
00050     }
00051 #   ifdef BAD
00052         if (BADflag)
00053             flcheck(0,0);
00054         else
00055             flcheck(0,1);
00056 #   endif
00057     return ( l );
00058 }
00059 
00060 /*
00061  * Add node e at end of list l.
00062  * If e is NIL do nothing.
00063  */
00064 LIST addright(l,e)
00065 LIST l;
00066 NODE *e;
00067 {
00068     register ConsNode * p;
00069 
00070     if ( e == NIL ) return(l);
00071 
00072 #   ifdef DEBUG
00073         if( !is_list(l) ) {
00074             dbgmsg("\naddright: bad arg: kind = %s\n", kindname(l -> kind));
00075             abort();
00076         }
00077 #   endif
00078 
00079     p = cn_cons(lock(e), NIL);
00080     if( is_empty(l) ) {
00081         l -> lh_first = p;
00082         l -> lh_last = p;
00083     } else {
00084         cn_settail( l -> lh_last, p );
00085         l -> lh_last = p;
00086     }
00087 #   ifdef BAD
00088         if (BADflag)
00089             flcheck(0,0);
00090         else
00091             flcheck(0,1);
00092 #   endif
00093     return ( l );
00094 }
00095 
00096 /*
00097  * mklist( e1, ..., ek, -1 )
00098  *
00099  * Paste e1 ... ek together into a list and return it.
00100  * If ei is NIL, it is ignored.
00101  */
00102 
00103 LIST mklist( va_alist )
00104 va_dcl
00105 {
00106 va_list lp;
00107 register unsigned p;
00108 register NODE *l;
00109 
00110     va_start(lp);
00111     p = va_arg(lp, unsigned);
00112     l = emptylist();
00113     while( p != -1 ) {
00114         addright( l, p );
00115         p = va_arg(lp, unsigned);
00116     }
00117     va_end(lp);
00118     return ( l );
00119 }
00120 
00121 /*
00122  * length(l)
00123  *
00124  * assuming l is a list
00125  *   return the number of elements in it
00126  */
00127 int length(l)
00128 NODE *l;
00129 {
00130 register int count = 0;
00131 
00132 #   ifdef DEBUG
00133         if ( !is_list(l) ) {
00134             dbgmsg("length: nonlist arg\n");
00135             abort();
00136         }
00137 #   endif
00138     maplist(p, l, count++);
00139     return ( count );
00140 }
00141 
00142 
00143 
00144 /*
00145  * list_to_array(l)
00146  *
00147  * input: A list l.
00148  *
00149  * output: An array containing pointers to the elements of l.
00150  *         The elements of l are locked.
00151  *         l is vfreed (but unaffected if it has nonzero reference count).
00152  */
00153 Array * list_to_array(l)
00154 NODE * l;
00155 {
00156     Array * a;      /* the array */
00157     int len;        /* size of the list */
00158 
00159 #   ifdef DEBUG
00160         if(!is_list(l)) {
00161             dbgmsg("list_to_array: bad arg: %x\n",l);
00162         }
00163 #   endif
00164     len = length(l);
00165     a = (Array *)salloc( sizeof(Array) + len * sizeof(NODE *) );
00166 #   ifdef BAD
00167         if(BADflag) {
00168             diagmsg("list_to_array: addr= 0x%x, size(bytes) = %d\n", a, sizeof(Array) + len * sizeof(NODE *) );
00169         }
00170 #   endif
00171     a->a_size = len;
00172 
00173     /* Fill the array with pointers to elements, adjusting ref counts.     */
00174     { register NODE **q;
00175 
00176         q = a->a_body;
00177         maplist(p, l, *q++ = lock(p) );
00178     }
00179 
00180     vfree(l);
00181     return ( a );
00182 }
00183 
00184 
00185 /*
00186  * free_array(a)
00187  *
00188  * The array a is reclaimed. Its elements are assumed
00189  * to point to nodes, so their ref counts are decremented
00190  * and an attempt is made to reclaim them.
00191  */
00192 
00193 free_array(a)
00194 Array *a;
00195 {
00196     NODE ** p;
00197 
00198     for (p = a->a_body; p < &a->a_body[a->a_size]; p++)
00199         vfree( unlock(*p) );
00200 
00201 #   ifdef BAD
00202         if(BADflag) {
00203             diagmsg("free_array: arg = 0x%x, size = %d\n", a, a -> a_size);
00204             diagmsg("  calling sfree with size = %d\n", sizeof(Array) + a->a_size * sizeof(NODE *) );
00205             flcheck(0,0);
00206         } else {
00207             flcheck(0,1);
00208         }
00209 #   endif
00210 
00211     free( a );
00212 
00213 #   ifdef BAD
00214         if(BADflag)
00215             flcheck(0,0);
00216         else
00217             flcheck(0,1);
00218 #   endif
00219 
00220 }
00221 
00222 
00223 /*
00224  *  split(kind, id_list, other args ...)
00225  *
00226  *  input: Similar to vertex, where id_list is a list of ids.
00227  *
00228  *  output: A list of "kind" nodes, with one of the ids on the id_list
00229  *          in the id field of each node, and the other args replicated
00230  *          for each node. 
00231  */
00232 LIST split(kindno, id_list, arg1, arg2, arg3, arg4, arg5)
00233 int kindno;
00234 NODE * id_list;
00235 NODE * arg1, *arg2, *arg3, *arg4, *arg5;
00236 {
00237     NODE * vrtx;
00238     NODE * result;
00239 
00240     result = emptylist();
00241     maplist (p, id_list, {
00242         /* Build a node with the id pointed to by p in the id field */
00243         /* and add it to the result.                                 */
00244             switch( bitcnt(stmkfields[kindno]) ) {
00245                 case 2: vrtx = mknode(kindno, p, arg1); break;
00246                 case 3: vrtx = mknode(kindno, p, arg1, arg2); break;
00247                 case 4: vrtx = mknode(kindno, p, arg1, arg2, arg3); break;
00248                 case 5: vrtx = mknode(kindno, p, arg1, arg2, arg3, arg4); break;
00249                 case 6: vrtx = mknode(kindno, p, arg1, arg2, arg3, arg4, arg5); break;
00250                 default: dbgmsg("split: bad node size: %d\n", stsize[kindno]);
00251             }
00252             addright(result, vrtx);
00253     } );
00254 
00255     return ( result );
00256 }
00257 
00258 /* 
00259  *     conc(l1,l2)
00260  *
00261  *  Destructively appends l1 to l2 and returns the result.
00262  *  l1 becomes the result. l2 is destroyed.
00263  *
00264  */
00265 NODE * conc(l1,l2)
00266 NODE * l1, *l2;
00267 {
00268 #   ifdef DEBUG
00269         if ( !is_list(l1) || !is_list(l2)) {
00270             dbgmsg("\nconc: args are not lists: l1=%x, l2=%x\n",l1,l2);
00271             abort();
00272         }
00273         if ( is_refd(l1) || is_refd(l2) ) {
00274             dbgmsg("\nconc: args have non-zero ref counts: l1=%x,l2=%x\n",l1,l2);
00275             abort();
00276         }
00277 #   endif
00278 
00279     if ( is_empty(l1) ) { vfree(l1); return(l2); }
00280     if ( !is_empty(l2) ) {
00281         cn_settail( l1 -> lh_last, l2 -> lh_first );
00282         (l1 -> lh_last) = (l2 -> lh_last);
00283     }
00284     /* free l2. Note that vfree cannot be used without clearing the first */
00285     /* last fields since the cons nodes are being reused. */ 
00286         (l2 -> lh_last) = (l2 -> lh_first) = NIL;
00287         vfree(l2);
00288     return ( l1 );
00289 }
00290 
00291 /*
00292  *  replace_last(l,p)
00293  * Destructively change the last element of the list l to be p
00294  */
00295 NODE * replace_last(l,p)
00296 NODE *l, *p;
00297 {
00298     NODE * q = last(l);
00299 
00300     cn_sethead(l -> lh_last, lock(p));
00301     vfree(unlock(q));
00302     return(l);
00303 }

Generated on Fri Jan 25 10:39:48 2008 for russell by  doxygen 1.5.4