libsrc/credel.cxx

Go to the documentation of this file.
00001 /**********************************************************************
00002  * Copyright 2002 Jeff Rush <jrush@taupro.com>
00003  * Original Copyright 1979-2002 Udanax.com
00004  *
00005  * This file is part of the Udanax xanalogical storage system.
00006  *
00007  * Udanax is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * Udanax is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with Udanax; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  **********************************************************************/
00021 
00030 /* Modification History:
00031  * $Log: credel.cxx,v $
00032  * Revision 1.12  2004/09/11 13:59:21  jrush
00033  * Changed all fprintf's to stderr to use the Nana library L() macro.  Also
00034  * removed a 2-3 minor compiler warnings.
00035  *
00036  * Revision 1.11  2004/09/04 16:02:17  jrush
00037  * Added Doxygen headers before each and every function definition.
00038  *
00039  * Revision 1.10  2004/08/28 13:57:00  jrush
00040  * Further syncing of local copies to CVS; builds but I haven't run it yet.
00041  *
00042  * Revision 1.9  2002/07/14 08:35:23  jrush
00043  * Replace gerror(), qerror() with assert()
00044  *
00045  * Revision 1.8  2002/05/28 04:22:29  jrush
00046  * Adjusted source files to comply with GPL licensing.
00047  *
00048  * Revision 1.7  2002/05/28 02:49:42  jrush
00049  * Made static any functions and global variables private to this source file
00050  * and commented out any unused functions.
00051  *
00052  * Revision 1.6  2002/04/12 22:53:20  jrush
00053  * Changed from using my setmem() to the clib's memset() and removed no
00054  * longer-needed usefull.cxx
00055  *
00056  * Revision 1.5  2002/04/12 11:56:42  jrush
00057  * Reorganized include file layout, renamed xanadu.h to udanax.h and
00058  * typecontext/typecrumcontext to C++ class Context/CrumContext.
00059  *
00060  * Revision 1.4  2002/04/06 19:51:30  jrush
00061  * Renamed TRUE/FALSE constant use to the C++ standard of true/false.
00062  *
00063  * Revision 1.3  2002/04/06 15:01:17  jrush
00064  * Changed INT to just 'int'.
00065  *
00066  * Revision 1.2  2002/02/14 09:27:43  jrush
00067  * Cleaned up source:
00068  *
00069  * 1. ran thru the indent tool to achieve a standard look,
00070  * 2. added structured comments at top for use with DOxygen reporting
00071  *    as well as CVS keywords,
00072  * 3. fixed compiler warnings re ambiguous assign/compares,
00073  *    needed casts and unused/uninitialized variables,
00074  * 4. fixed funcs that didn't specify a return type,
00075  * 5. centralized prototypes in protos.h, removing incomplete ones,
00076  * 6. cleaned up use of bool/BOOLEAN type to suit C++ type,
00077  * 7. fixed initializer nesting in tumbler constants,
00078  * 8. renamed vars that conflict with C++ keywords (new, this),
00079  * 9. fixed global/extern confusion re some global vars.
00080  *
00081  */
00082 
00083 #include <memory.h>
00084 #include <malloc.h>
00085 #include <unistd.h>
00086 
00087 #define NEWALLOC
00088 #include "udanax.h"
00089 
00090 typecorecrum *grimreaper;
00091 int ingrimreaper      = false;
00092 int reaplevel         = 0;
00093 int timesaroundreaper = 0;
00094 int crumnumber        = 0;
00095 int reapnumber        = 0;
00096 int nreapings         = 0;
00097 int reservnumber      = 0;
00098 
00099 #define MAXALLOCQUEUEARRAY 500
00100 struct queue allocqueuearray[MAXALLOCQUEUEARRAY];
00101 
00102 static bool isreapable(int *fuckinap, typecorecrum *localreaper);
00103 static void reap(typecorecrum *localreaper);
00104 
00112     void
00113 initqueues()
00114 {
00115     for (int i = 0; i < MAXALLOCQUEUEARRAY; i++)
00116         qinit(&allocqueuearray[i]);
00117 
00118 #ifdef NEWALLOC
00119     int num = allocsize / 3;
00120 #else
00121     int num = 0;
00122 #endif
00123 
00124     for (int j = 0; j < num; j += sizeof(typecuc) + sizeof(typecbc) + sizeof(type2dcbc) + 3 * sizeof(tagtype)) {
00125         qpush(&allocqueuearray[(sizeof(typecuc) + sizeof(tagtype) + sizeof(HEADER) - 1) / sizeof(HEADER)],
00126               (queue *) falloc(sizeof(typecuc) + sizeof(tagtype)));
00127         qpush(&allocqueuearray[(sizeof(typecbc) + sizeof(tagtype) + sizeof(HEADER) - 1) / sizeof(HEADER)],
00128               (queue *) falloc(sizeof(typecbc) + sizeof(tagtype)));
00129         qpush(&allocqueuearray[(sizeof(type2dcbc) + sizeof(tagtype) + sizeof(HEADER) - 1) / sizeof(HEADER)],
00130               (queue *) falloc(sizeof(type2dcbc) + sizeof(tagtype)));
00131     }
00132 }
00133 
00134 //UNUSED static void
00135 //UNUSED dumptable()
00136 //UNUSED {
00137 //UNUSED     L("dumptable\n");
00138 //UNUSED     for (int i = 0; i < MAXALLOCQUEUEARRAY; i++) {
00139 //UNUSED         int tmp = qlength(&allocqueuearray[i]);
00140 //UNUSED         if (tmp != 0)
00141 //UNUSED             L("len of %d = %d\n", i, tmp);
00142 //UNUSED     }
00143 //UNUSED }
00144 
00152     static char *
00153 allocfromqueue(
00154     int n)
00155 {
00156     return (char *) qremove(&allocqueuearray[((n + sizeof(HEADER) - 1) / sizeof(HEADER))]);
00157 }
00158 
00166     static void
00167 freetoqueue(
00168     char *ptr)
00169 {
00170     // Located in memory before the tag is the sizeof the block in align uints
00171     // including the header
00172 
00173     // dumptable();
00174 
00175     int n = ((HEADER *) (ptr - sizeof(HEADER)))->s.size - 1;
00176     qpush(&allocqueuearray[n], (queue *) ptr);
00177 
00178     // dumptable();
00179 }
00180 
00181     static typecorecrum *
00182 createcruminternal(
00183     int           crumheight,
00184     int           enftype,
00185     typecorecrum *allocated)
00186 {
00187     unsigned crumsize = 0;
00188 
00189     if (crumheight == 0) {
00190         switch (enftype) {
00191         case GRAN:
00192             crumsize = sizeof(typecbc);
00193             break;
00194         case SPAN:
00195         case POOM:
00196             crumsize = sizeof( /* typecbc */ type2dcbc);
00197             break;
00198         default:
00199             L(" enftype = %d\n", enftype);
00200             assert(0); // createcrum illegal enftype
00201         }
00202     } else
00203         crumsize = sizeof(typecuc);
00204 
00205     typecorecrum *ptr;
00206     if (!allocated)
00207         ptr = (typecorecrum *) eallocwithtag(crumsize, (tagtype) (crumheight > 0 ? CUCTAG : CBCTAG));
00208     else
00209         ptr = allocated;
00210 
00211     ptr->height          = crumheight;
00212     ptr->isapex          = false;
00213     ptr->cenftype        = enftype;
00214     ptr->modified        = true /*false*/;
00215     ptr->isleftmost      = false;
00216     ptr->age             = NEW;
00217     ptr->leftbroorfather = NULL;
00218     ptr->rightbro        = NULL;
00219 
00220     clear(&ptr->cdsp, sizeof(ptr->cdsp));
00221     clear(&ptr->cwid, sizeof(ptr->cwid));
00222 
00223     if (crumheight > 0) {
00224         ((typecuc *) ptr)->numberofsons              = 0;
00225         ((typecuc *) ptr)->leftson                   = NULL;
00226         ((typecuc *) ptr)->sonorigin.diskblocknumber = DISKPTRNULL;
00227 
00228     } else {
00229         if (enftype == GRAN) {
00230             clear(&((typecbc *) ptr)->cinfo, sizeof(((typecbc *) ptr)->cinfo));
00231             ((typecbc *) ptr)->cinfo.infotype = GRANCLEARLYILLEGALINFO;
00232         } else
00233             clear(&((type2dcbc *) ptr)->c2dinfo, sizeof(((type2dcbc *) ptr)->c2dinfo));
00234     }
00235     ++crumnumber;
00236 
00237     return ptr;
00238 }
00239 
00247     void
00248 initcrum(
00249     int           crumheight,
00250     int           enftype,
00251     typecorecrum *ptr)
00252 {
00253     createcruminternal(crumheight, enftype, ptr);
00254 }
00255 
00263     static void
00264 xgrabmorecore()
00265 {
00266     char *tmp = (char *) sbrk(incrementalallocsize);
00267     if (!tmp)
00268         assert(0); // no more memory in xgrabmorecore
00269 
00270     ((HEADER *) tmp)->s.size = (incrementalallocsize + sizeof(HEADER) - 1) / sizeof(HEADER);
00271     ffree(tmp + sizeof(HEADER));
00272 
00273     L("xgrabmorecore got another %d\n", incrementalallocsize);
00274 }
00275 
00283     static void
00284 grimlyreap()
00285 {
00286     typecorecrum *ptr;
00287     int eh;
00288 
00289     ingrimreaper = true;
00290     if (reaplevel++)
00291 #ifndef DISTRIBUTION
00292         if (reaplevel == 1)
00293             L("Recursive grimreaper call.\n");
00294 #endif
00295 
00296     if (!grimreaper)
00297         assert(0); // nothing to reap!
00298 
00299     reapnumber = 0;
00300     timesaroundreaper = 0;
00301     for (ptr = grimreaper; grimreaper; grimreaper = (typecorecrum *) grimreaper->nextcrum) {
00302         if (grimreaper == ptr) {
00303             ++timesaroundreaper;
00304         }
00305         if (timesaroundreaper > 10) {
00306             L("urk in grimlyreap\n");
00307 /* lookatalloc(); */
00308             xgrabmorecore();
00309             break;
00311 // * #ifndef DISTRIBUTION assert(0); /* I'm getting bored in grimlyreap */); #else
00312 // * assert(0); /* memory fouled */); #endif */
00313         }
00314 
00315         if (grimreaper->age == RESERVED)
00316             continue;
00317 
00318         if (isreapable(&eh, grimreaper)) {
00319             reap(grimreaper);
00320             reapnumber = 0;
00321             timesaroundreaper = 0;
00322             --reaplevel;
00323             break;
00324         } else {
00325             if (eh) {
00326 /* dump(grimreaper); */
00327             }
00328         }
00329 
00330         ++reapnumber;
00331         grimreaper->age++;
00332     }
00333 
00334     ingrimreaper = false;
00335 }
00336 
00344     static int *
00345 ealloc(
00346     unsigned nbytes)
00347 {                                      /* with tag */
00348     /* L("ealloc called with %d\n", nbytes); */
00349 
00350     for (;;) {
00351         char *ret;
00352 
00353         if ((ret = allocfromqueue(nbytes + sizeof(tagtype))) != 0) {
00354             ret += sizeof(tagtype);
00355             return (int *) ret;
00356         }
00357         ret = (char *)falloc(nbytes + sizeof(tagtype));
00358 
00359         if (ret) {
00360             // memset(ret + sizeof(tagtype), 0xF9, nbytes);
00361             *(tagtype *) ret = false;
00362             return (int *) (ret + sizeof(tagtype));
00363         }
00364         if (grimreaper == NULL) {
00365             xgrabmorecore();
00366             /*
00367              * assert(0); // Why am I out of room?
00368              */
00369         }
00370         grimlyreap();
00371     }
00372 }
00373 
00381     void
00382 efree(
00383     char *ptr)
00384 {                                      /* with tag */
00385 /* ffree(ptr); */
00386     if (*(ptr - sizeof(tagtype)) == CBCTAG || *(ptr - sizeof(tagtype)) == CUCTAG) {
00387 #ifdef NEWALLOC
00388         freetoqueue(ptr - sizeof(tagtype));
00389 #else
00390         ffree(ptr - sizeof(tagtype));
00391 #endif
00392     } else {
00393         free(ptr - sizeof(tagtype));
00394     }
00395 }
00396 
00397 /* 
00398  * void etag(ptr, tag) char * ptr; tagtype tag; { *(ptr -sizeof(tagtype)) =
00399  * tag; } */
00400 
00408     int *
00409 eallocwithtag(
00410     unsigned nbytes,
00411     tagtype  tag)
00412 {
00413     char *ret = NULL;
00414 
00415     if (tag == CBCTAG || tag == CUCTAG) {
00416         ret = (char *) ealloc(nbytes);
00417 
00418     } else {
00419         ret = (char *) malloc(nbytes + sizeof(tagtype));
00420         ret += sizeof(tagtype);
00421     }
00422 
00423 /* etag((char*)ret,tag); */
00424 
00425     *(ret - sizeof(tagtype)) = tag;
00426     return (int *) ret;
00427 }
00428 
00436     static bool
00437 isreapable(
00438     int          *fuckinap,
00439     typecorecrum *localreaper)
00440 {
00441     register typecorecrum *p;
00442     typecuc *father;
00443 
00444     *fuckinap = 0;
00445     if (!localreaper)
00446         assert(0); // localreaper NULL
00447 
00448     if (localreaper->age < OLD || localreaper->age == RESERVED) {
00449         *fuckinap = 1;
00450         return false;
00451     }
00452 
00453     if (localreaper->isapex) {
00454         if (localreaper->cenftype != POOM)
00455             return false;
00456 
00457         if (localreaper->modified) {
00458             if (!((typecuc *) localreaper)->leftson) {
00459 #ifndef DISTRIBUTION
00460                 dump(localreaper);
00461                 L("in isreapable modified and no son in apex");
00462 #endif
00463                 return false;
00464             }
00465 
00466             for (p = ((typecuc *) localreaper)->leftson; p; p = p->rightbro) {
00467                 if (p->modified)
00468                     return false;
00469 
00470                 if (p->age < OLD || p->age == RESERVED)
00471                     return false;
00472 
00473                 if (p->height > 0 && ((typecuc *) p)->leftson)
00474                     return false;
00475 
00476                 if (p->height == 0 && p->cenftype == GRAN && ((typecbc *) p)->cinfo.infotype == GRANORGL && ((typecbc *) p)->cinfo.granstuff.orglstuff.orglincore)
00477                     return false;
00478             }
00479             return true;
00480 
00481         } else {
00482             for (p = ((typecuc *) localreaper)->leftson; p; p = p->rightbro) {
00483                 if (p->modified)
00484                     return false;
00485 
00486                 if (p->age < OLD || p->age == RESERVED)
00487                     return false;
00488 
00489                 if (p->height > 0 && ((typecuc *) p)->leftson)
00490                     return false;
00491 
00492                 if (p->height == 0 && p->cenftype == GRAN && ((typecbc *) p)->cinfo.infotype == GRANORGL && ((typecbc *) p)->cinfo.granstuff.orglstuff.orglincore)
00493                     return false;
00494             }
00495             return true;
00496         }
00497     }
00498 
00499 /* if height == 0 and not cinfo.orglincore return true */
00500     if (!localreaper)
00501         assert(0); // in isreapable localreaper is NULL
00502 
00503     father = weakfindfather((typecorecrum *) localreaper);
00504     if (!father) {
00505         L("in isreapable no father !! \n");
00506         return false;
00507     }
00508 
00509     if (localreaper->height == 0) {
00510         if (localreaper->cenftype == GRAN) {
00511             if (((typecbc *) localreaper)->cinfo.infotype == GRANORGL) {
00512                 if (((typecbc *) localreaper)->cinfo.granstuff.orglstuff.orglincore)
00513                     return false;
00514             }
00515         }
00516 
00517         for (p = weakfindleftmostbro(localreaper); p; p = p->rightbro) {
00518             if (p->age < OLD || p->age == RESERVED)
00519                 return false;
00520 
00521             if (p->height == 0 && p->cenftype == GRAN && ((typecbc *) p)->cinfo.infotype == GRANORGL && ((typecbc *) p)->cinfo.granstuff.orglstuff.orglincore)
00522                 return false;
00523         }
00524         return true;
00525 
00526     } else {                           /* != 0 */
00527         if (father->modified) {
00528             for (p = weakfindleftmostbro(localreaper); p; p = p->rightbro) {
00529                 if (p->modified)
00530                     return false;
00531 
00532                 if (p->age < OLD || p->age == RESERVED)
00533                     return false;
00534 
00535                 if (p->height > 0 && ((typecuc *) p)->leftson)
00536                     return false;
00537             }
00538             return true;
00539 
00540         } else {                       /* if (!father->modified) */
00541             for (p = weakfindleftmostbro(localreaper); p; p = p->rightbro) {
00542                 if (p->modified)
00543                     return false;
00544 
00545                 if (p->age < OLD || p->age == RESERVED)
00546                     return false;
00547 
00548                 if (p->height > 0 && ((typecuc *) p)->leftson)
00549                     return false;
00550             }
00551             return true;
00552         }
00553     }
00554 }
00555 
00563     static void
00564 reap(
00565     typecorecrum *localreaper)
00566 {
00567     typecuc *temp;
00568 
00569     if (!localreaper)
00570         assert(0); // localreaper NULL0
00571 
00572     ++nreapings;
00573     if (localreaper->isapex) {
00574         temp = (typecuc *) localreaper->leftbroorfather;
00575         grimreaper = grimreaper->nextcrum;
00576         if (!temp)
00577             return;
00578 
00579         orglwrite((typecbc *) temp);
00580         if (!localreaper)
00581             assert(0); // localreaper NULL2
00582 
00583         return;
00584     }
00585 
00586     temp = weakfindfather((typecorecrum *) localreaper);
00587     if (!temp)
00588         assert(0); // localreaper doesn't have a father
00589 
00590     if (!temp->leftson) {
00591         grimreaper = grimreaper->nextcrum;
00592         return;
00593     }
00594 
00595     subtreewrite(temp);
00596 }
00597 
00605 /* 
00606  * void efreewithtag(ptr) char * ptr; { ffree(ptr - sizeof(tagtype)); } */
00607     void
00608 initgrimreaper()
00609 {
00610     grimreaper = NULL;
00611 }
00612 
00620     int
00621 testforrejuvinate(
00622     typecorecrum *ptr)
00623 {
00624     if (ptr->age == RESERVED) {
00625         if (!reservnumber)
00626             assert(0); // There shouldn't be any more reserved
00627 
00628         --reservnumber;
00629     }
00630     return 0;
00631 }
00632 
00640     void
00641 funcrejuvinate(
00642     typecorecrum *ptr)
00643 {                                      /* inner if is testing very useful * test */
00644     if (ptr->age == RESERVED) {
00645         if (!reservnumber) {
00646 #ifndef DISTRIBUTION
00647             dump(ptr);
00648             assert(0); // There shouldn't be any more reserved
00649 #else
00650             assert(0); // memory mess
00651 #endif
00652         }
00653         --reservnumber;
00654     }
00655     ptr->age = NEW;
00656 }
00657 
00665 /* protect a crum and its ancestors from being grimly reaped */
00666     void
00667 reserve(
00668     typecorecrum *ptr)
00669 {
00670 #ifndef DISTRIBUTION
00671     foohex("reserve\n", (int) ptr);
00672 #endif
00673     if (ptr->age != RESERVED) {
00674         ++reservnumber;
00675     } else {
00676 #ifndef DISTRIBUTION
00677         assert(0); // reserve already reserved
00678 #else
00679         assert(0); // arg!
00680 #endif
00681     }
00682     ptr->age = RESERVED;
00683 }
00684 
00692     void
00693 testforreservedness(
00694     char *msg)
00695 {                                      /* test to see if any reserved flags linger * in the memory.  if they do is a
00696                                         * gross * error in crum stuff */
00697     int numreserved = 0;
00698     bool first;
00699 
00700     typecorecrum *ptr;
00701     for (ptr = grimreaper, first = true; ptr && (first ? true : ptr != grimreaper); ptr = ptr->nextcrum, first = false)
00702         if (ptr->age == RESERVED) {
00703             ++numreserved;
00704             if (true || debug)
00705                 dump(ptr);
00706         }
00707 
00708     if (numreserved) {
00709         L("numreserved = %s:  There are %d reserved crums. (reservnumber = %d)\n", msg, numreserved, reservnumber);
00710         assert(0); // This isn't supposed to be the case
00711     }
00712 
00713     if (reservnumber) {
00714         L("reservnumber = %d\n", reservnumber);
00715         assert(0); // reservnumber is incorrect
00716     }
00717 }
00718 
00726 /* assumes crum is disowned */
00727     void
00728 subtreefree(
00729     typecorecrum *ptr)
00730 {
00731     if (!ptr)
00732         assert(0); // boom in subtreefree called with ptr == NULL
00733 
00734     if (ptr->height > 0) {
00735         typecorecrum *p, *right;
00736 
00737         for (p = ((typecuc *) ptr)->leftson; p; p = right) {
00738             right = p->rightbro;
00739             disown(p);
00740             subtreefree(p);
00741         }
00742 
00743     } else if (ptr->cenftype == GRAN
00744            && ((typecbc *) ptr)->cinfo.infotype == GRANORGL
00745            && ((typecbc *) ptr)->cinfo.granstuff.orglstuff.orglincore)
00746         orglfree(((typecbc *) ptr)->cinfo.granstuff.orglstuff.orglptr);
00747 
00748     freecrum(ptr);
00749 }
00750 
00758     void
00759 freecrum(
00760     typecorecrum *ptr)
00761 {
00762     if (ptr->age == RESERVED)
00763         assert(0); // freecrum called with RESERVED crum
00764 
00765     if (grimreaper == ptr)
00766         grimreaper = grimreaper->nextcrum;
00767 
00768     if (grimreaper == ptr)
00769         grimreaper = NULL;
00770 
00771     ptr->nextcrum->prevcrum = ptr->prevcrum;
00772     ptr->prevcrum->nextcrum = ptr->nextcrum;
00773 
00774 /* zzz should it decrement usecount here sometimes? */
00775 
00776     --crumnumber;
00777     efree((char *)ptr);
00778 }
00779 
00787     void
00788 loaffree(
00789     typecuc *father)
00790 {
00791     if (father->height <= 0 /* || !father->leftson */ )
00792         assert(0); // bad call
00793 
00794     typecorecrum *ptr, *next;
00795     for (ptr = father->leftson; ptr; ptr = next) {
00796         next = ptr->rightbro;
00797         disownnomodify(ptr);
00798         subtreefree(ptr);
00799     }
00800 
00801     father->modified = false;
00802 }
00803 
00811     void
00812 orglfree(
00813     typecuc *ptr)
00814 {
00815     assert(ptr);         // ERROR: orglfree called with no orglptr
00816     assert(ptr->isapex); // ERROR: Orglfree called with non-fullcrum
00817     assert(((typecbc *) ptr->leftbroorfather)->cinfo.granstuff.orglstuff.diskorglptr.diskblocknumber != DISKPTRNULL); // ERROR: orglfree called with unwritten-out orgl
00818 
00819     ((typecbc *) ptr->leftbroorfather)->cinfo.granstuff.orglstuff.orglincore = false;
00820     ((typecbc *) ptr->leftbroorfather)->cinfo.granstuff.orglstuff.orglptr    = NULL;
00821 
00822     subtreefree((typecorecrum *) ptr);
00823 }
00824 
00832     typecuc *
00833 createenf(
00834     int enftype)
00835 {
00836     typecuc *fullcrumptr = (typecuc *) createcrum(1, enftype);
00837 
00838     fullcrumptr->cenftype   = enftype;
00839     fullcrumptr->isapex     = true;
00840     fullcrumptr->isleftmost = true;
00841 
00842     typecorecrum *ptr = createcrum(0, enftype);
00843 
00844     adopt(ptr, SON, (typecorecrum *) fullcrumptr);
00845     if (enftype == GRAN)
00846         ((typecbc *) ptr)->cinfo.infotype = GRANNULL;   /* KLUGE will this work?? */
00847 
00848     ivemodified(ptr);
00849 
00850 /* if(enftype == GRAN){ levelpush(fullcrumptr); adopt (createcrum(0,enftype), RIGHTBRO, fullcrumptr->leftson);
00851  * adopt(createcrum(0,enftype),SON,fullcrumptr->leftson->rightbro); ptr = fullcrumptr->leftson->leftson;
00852  * tumblerincrement(&(ptr->cwid.dsas[WIDTH]),2,1,&(ptr->cwid.dsas[WIDTH])); setwispupwards(ptr,1); } */
00853 
00854     return fullcrumptr;
00855 }
00856 
00864     typecorecrum *
00865 createcrum(
00866     int crumheight,
00867     int enftype)
00868 {
00869     typecorecrum *ptr = createcruminternal(crumheight, enftype, (typecorecrum *) NULL);
00870 
00871     if (grimreaper) {
00872         ptr->nextcrum                  = grimreaper;
00873         ptr->prevcrum                  = grimreaper->prevcrum;
00874         grimreaper->prevcrum->nextcrum = ptr;
00875         grimreaper->prevcrum           = ptr;
00876     } else
00877         grimreaper = ptr->nextcrum = ptr->prevcrum = ptr;
00878 
00879     return ptr;
00880 }

Generated on Sun Aug 21 04:18:14 2005 for Udanax-Green by doxygen1.3.4