memory.track.c

Go to the documentation of this file.
00001 
00002 /*  $Id: memory.track.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #ifdef MACVERSION
00029 #include <standard.h>
00030 #endif
00031 
00032 #ifdef WIN95VERSION
00033 #include "standard.h"
00034 #endif
00035 
00036 #include "error.h"
00037 #include "memory.h"
00038 #include "shellhooks.h"
00039 
00040 
00041 
00042 #define safetycushionsize 0x2800 /*10K*/
00043 
00044 #ifdef fldebug
00045 
00046 long cttemphandles = 0;
00047 
00048 THz tempzone;
00049 
00050 #endif
00051 
00052 
00053 static Handle hsafetycushion = nil; /*a buffer to allow memory error reporting*/
00054 
00055 static boolean flholdsafetycushion = false;
00056 
00057 
00058 static boolean getsafetycushion (void) {
00059     
00060     if (hsafetycushion == nil)
00061         hsafetycushion = NewHandle (safetycushionsize);
00062     
00063     return (hsafetycushion != nil);
00064     } /*getsafetycushion*/
00065 
00066 
00067 static boolean safetycushionhook (long *ctbytesneeded) {
00068     
00069     if (!flholdsafetycushion && (hsafetycushion != nil)) {
00070         
00071         *ctbytesneeded -= safetycushionsize;
00072         
00073         DisposeHandle (hsafetycushion);
00074         
00075         hsafetycushion = nil;
00076         }
00077     
00078     return (true); /*call remaining hooks*/
00079     } /*safetycushionhook*/
00080 
00081 #if (MEMTRACKER == 1)
00082     static Handle debuggetnewhandle (char * filename, unsigned long linenumber, unsigned long threadid, long ctbytes, boolean fltemp) {
00083         
00084         /*
00085         2.1b3 dmb: new fltemp parameter. if true, try temp memory first, then 
00086         our heap.
00087         */
00088         
00089         register Handle h;
00090         OSErr err;
00091         long extrasize;
00092 
00093         extrasize = strlen(filename) + 1 + sizeof(long) + sizeof(long) + sizeof(long) + (2 * (sizeof(Handle))) + 4;
00094 
00095         #ifdef MACVERSION
00096             if (fltemp) { /*try grabbing temp memory first*/
00097                 
00098                 h = TempNewHandle (ctbytes + extrasize, &err);
00099                 
00100                 if (h != nil) {
00101                     
00102                     debugaddmemhandle (h, ctbytes, filename, linenumber, threadid);
00103 
00104                     #ifdef fldebug
00105                     
00106                     ++cttemphandles;
00107                     
00108                     tempzone = HandleZone (h);
00109                     
00110                     #endif
00111                     
00112                     return (h);
00113                     }
00114                 }
00115         #endif
00116         
00117         if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00118             
00119             if (!getsafetycushion ())
00120                 return (nil);
00121             }
00122         
00123         flholdsafetycushion = true;
00124         
00125         #ifdef MACVERSION
00126             h = NewHandle (ctbytes);
00127 
00128             if (h != nil)
00129                 debugaddmemhandle (h, ctbytes, filename, linenumber, threadid);
00130         #endif
00131         #ifdef WIN95VERSION
00132             h = debugfrontierAlloc (filename, linenumber, threadid, ctbytes);
00133         #endif
00134         
00135         flholdsafetycushion = false;
00136         
00137         return (h);
00138         } /*getnewhandle*/
00139 
00140 #else
00141     static Handle getnewhandle (long ctbytes, boolean fltemp) {
00142         
00143         /*
00144         2.1b3 dmb: new fltemp parameter. if true, try temp memory first, then 
00145         our heap.
00146         */
00147         
00148         register Handle h;
00149         OSErr err;
00150 
00151         #ifdef MACVERSION
00152             if (fltemp) { /*try grabbing temp memory first*/
00153                 
00154                 h = TempNewHandle (ctbytes, &err);
00155                 
00156                 if (h != nil) {
00157                     
00158                     #ifdef fldebug
00159                     
00160                     ++cttemphandles;
00161                     
00162                     tempzone = HandleZone (h);
00163                     
00164                     #endif
00165                     
00166                     return (h);
00167                     }
00168                 }
00169         #endif
00170         
00171         if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00172             
00173             if (!getsafetycushion ())
00174                 return (nil);
00175             }
00176         
00177         flholdsafetycushion = true;
00178         
00179         h = NewHandle (ctbytes);
00180         
00181         flholdsafetycushion = false;
00182         
00183         return (h);
00184         } /*getnewhandle*/
00185 #endif
00186 
00187 static boolean resizehandle (Handle hresize, long size) {
00188     
00189     register Handle h = hresize;
00190     
00191     if (size > gethandlesize (h)) {
00192         
00193         if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00194             
00195             if (!getsafetycushion ())
00196                 return (false);
00197             }
00198         }
00199     
00200     flholdsafetycushion = true;
00201     
00202     SetHandleSize (h, size);
00203     
00204     flholdsafetycushion = false;
00205     
00206     return (MemError () == noErr);
00207     } /*resizehandle*/
00208 
00209 
00210 /*
00211 heapmess (void) {
00212     
00213     Handle ray [1000];
00214     short ixray = 0;
00215     Handle h;
00216     short i;
00217     
00218     while (true) {
00219         
00220         h = NewHandle (1024L);
00221         
00222         if (h == nil)
00223             break;
00224         
00225         ray [ixray++] = h;
00226         } /*while%/
00227     
00228     for (i = 0; i < ixray; i++)
00229         disposehandle (ray [i]);
00230     } /*heapmess*/
00231 
00232 /*
00233 boolean analyzeheap (void) {
00234     
00235     /*
00236     get some statistics about the heap.  doesn't work in 32-bit mode.
00237     %/
00238     
00239     register byte *pblock;
00240     register long size;
00241     register byte *plimit;
00242     static long cthandles;
00243     static long ctbytes;
00244     static long avghandlesize;
00245     
00246     pblock = (byte *) &(*TheZone).heapData; /*point for first block in heap zone%/
00247     
00248     plimit = (byte *) (*TheZone).bkLim;
00249     
00250     cthandles = 0;
00251     
00252     ctbytes = 0; /*logical size of each handle%/
00253     
00254     while (pblock < plimit) {
00255         
00256         size = *(long *)pblock & 0x00ffffff;
00257         
00258         if (*pblock & 0x80) { /*a relocateable block%/
00259             
00260             ctbytes += size; /*add physical size%/
00261             
00262             /*ctbytes -= 8 + (*pblock & 0x0f); /*subtract header & size correction%/
00263             
00264             ++cthandles;
00265             }
00266         
00267         pblock += size;
00268         }
00269     
00270     avghandlesize = ctbytes / cthandles;
00271     } /*analyzeheap*/
00272 
00273 
00274 boolean haveheapspace (long size) {
00275     
00276     /*
00277     see if there's enough space in the heap to allocate a handle of the given size.
00278     
00279     if not, return false, but don't generate an error.
00280     */
00281     
00282     Handle h;
00283 
00284     #if (MEMTRACKER == 1)
00285         h = debuggetnewhandle (__FILE__, __LINE__, GetCurrentThreadId(), size, false);
00286     #else
00287         h = getnewhandle (size, false);
00288     #endif
00289 
00290     if (h == nil)
00291         return (false);
00292     
00293     DisposeHandle (h);
00294     
00295     return (true);
00296     } /*haveheapspace*/
00297 
00298 
00299 boolean testheapspace (long size) {
00300     
00301     /*
00302     see if there's enough space in the heap to allocate a handle of the given size.
00303     
00304     if not, generate an error, and return false.
00305     */
00306     
00307     if (haveheapspace (size))
00308         return (true);
00309     
00310     memoryerror ();
00311     
00312     return (false);
00313     } /*testheapspace*/
00314 
00315 
00316 void lockhandle (Handle h) {
00317     
00318     HLock (h);
00319     } /*lockhandle*/
00320 
00321 
00322 void unlockhandle (Handle h) {
00323     
00324     HUnlock (h);
00325     } /*unlockhandle*/
00326 
00327 
00328 boolean validhandle (Handle h) {
00329     
00330     if (h == nil)
00331         return (true);
00332     
00333 #ifdef MACVERSION
00334 
00335     if (GetHandleSize (h) < 0) /*negative length never valid*/
00336         return (false);
00337     
00338     return (MemError () == noErr);
00339 #endif
00340 
00341 #ifdef WIN95VERSION
00342     if (GlobalSize (h) <= 0)
00343         return (false);
00344 
00345     return (true);
00346 #endif
00347     } /*validhandle*/
00348 
00349 
00350 #if (MEMTRACKER == 1)
00351     boolean debugnewhandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *h) {
00352         
00353         *h = debuggetnewhandle (filename, linenumber, threadid, size, false);
00354         
00355         if (*h == nil) {
00356             
00357             memoryerror ();
00358             
00359             return (false);
00360             }
00361         
00362         return (true);
00363         } /*newhandle*/
00364 
00365 
00366     boolean debugnewemptyhandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle *h) {
00367         
00368         return (debugnewhandle (filename, linenumber, threadid, (long) 0, h));
00369         } /*newemptyhandle*/
00370 #else
00371     boolean newhandle (long size, Handle *h) {
00372         
00373         *h = getnewhandle (size, false);
00374         
00375         if (*h == nil) {
00376             
00377             memoryerror ();
00378             
00379             return (false);
00380             }
00381         
00382         return (true);
00383         } /*newhandle*/
00384 
00385 
00386     boolean newemptyhandle (Handle *h) {
00387         
00388         return (newhandle ((long) 0, h));
00389         } /*newemptyhandle*/
00390 #endif
00391 
00392 void disposehandle (Handle h) {
00393     
00394     if (h != nil) {
00395         
00396     #ifdef WIN95VERSION
00397         DisposeHandle (h);
00398     #endif
00399 
00400     #ifdef MACVERSION       
00401         #if (MEMTRACKER == 1)
00402             debugremovememhandle(h);
00403         #endif
00404 
00405         #ifdef fldebug
00406 
00407         if (HandleZone (h) == tempzone)
00408             --cttemphandles;
00409 
00410         #endif
00411         
00412         DisposeHandle (h);
00413         
00414         #ifdef fldebug
00415         
00416         if (MemError ())
00417              memoryerror ();
00418         
00419         #endif
00420     #endif      
00421         }
00422     } /*disposehandle*/
00423 
00424 
00425 long gethandlesize (Handle h) {
00426     
00427     if (h == nil)
00428         return (0L);
00429     
00430     return (GetHandleSize (h));
00431     } /*gethandlesize*/
00432 
00433 
00434 boolean sethandlesize (Handle h, long size) {
00435     
00436     if (h == nil) /*defensive driving*/
00437         return (false);
00438     
00439     if (!resizehandle (h, size)) {
00440         
00441         memoryerror ();
00442         
00443         return (false);
00444         }
00445     
00446     return (true);
00447     } /*sethandlesize*/
00448     
00449     
00450 boolean minhandlesize (Handle h, long size) {
00451     
00452     if (gethandlesize (h) >= size) /*already big enough*/
00453         return (true);
00454         
00455     return (sethandlesize (h, size)); /*try to make it larger*/
00456     } /*minhandlesize*/
00457 
00458 
00459 void moveleft (ptrvoid psource, ptrvoid pdest, long length) {
00460     
00461     /*
00462     do a mass memory move with the left edge leading.  good for closing
00463     up a gap in a buffer, among other thingsÉ
00464     */
00465 #if defined (MACVERSION)
00466     BlockMoveData (psource, pdest, length);
00467     
00468 #elif defined (WIN95VERSION)
00469     CopyMemory (pdest, psource, length);
00470     
00471 #else
00472     register ptrbyte ps = psource, pd = pdest;
00473     register long ctloops = length;
00474     
00475     while (--ctloops >= 0)
00476         *pd++ = *ps++;
00477 #endif
00478     } /*moveleft*/
00479 
00480 
00481 void moveright (ptrvoid psource, ptrvoid pdest, long length) {
00482     
00483     /*
00484     do a mass memory move with the right edge leading.  good for opening
00485     up a gap in a buffer, among other thingsÉ
00486     */
00487     
00488 #if defined (MACVERSION)
00489     BlockMoveData (psource, pdest, length);
00490     
00491 #else
00492     register ptrbyte ps, pd;
00493     register long ctloops;
00494     
00495     ctloops = length;
00496     
00497     if (ctloops > 0) {
00498     
00499         ps = (ptrbyte) psource + length - 1; /*right edge of source*/
00500     
00501         pd = (ptrbyte) pdest + length - 1; /*right edge of destination*/
00502     
00503         while (ctloops--) 
00504             *pd-- = *ps--;
00505         }
00506 #endif
00507     } /*moveright*/
00508     
00509     
00510 void fillchar (ptrvoid pfill, long ctfill, char chfill) {
00511     
00512     /*
00513     do a mass memory fill -- copy ctfill chfills at pfill.
00514     */
00515     
00516 #ifdef MACVERSION
00517     register ptrbyte p = pfill;
00518     register long ct = ctfill;
00519     register char ch = chfill;
00520     
00521     while (--ct >= 0)
00522         *p++ = (char) ch; /*tight loop*/
00523 #endif
00524 
00525 #ifdef WIN95VERSION
00526     FillMemory (pfill, ctfill, chfill);
00527 #endif
00528     } /*fillchar*/
00529     
00530 
00531 void clearbytes (ptrvoid pclear, long ctclear) {
00532     
00533     /*
00534     fill memory with 0's.
00535     */
00536     
00537     fillchar (pclear, ctclear, (char) 0);
00538     } /*clearbytes*/
00539     
00540 
00541 void clearhandle (Handle hclear) {
00542     
00543     /*
00544     fill a handle's data with 0's.
00545     */
00546     
00547     register Handle h = hclear;
00548     register long size;
00549     
00550     size = gethandlesize (h);
00551     
00552     /*
00553     lockhandle (h);
00554     */
00555     
00556     fillchar (*h, size, (char) 0);
00557     
00558     /*
00559     unlockhandle (h);
00560     */
00561     } /*clearhandle*/
00562     
00563 
00564 void movefromhandle (Handle h, ptrvoid pdest, long length) {
00565     
00566     if (h != nil) {
00567     
00568         /*
00569         HLock (h);
00570         */
00571     
00572         moveleft (*h, pdest, length);
00573     
00574         /*
00575         HUnlock (h);
00576         */
00577         }
00578     } /*movefromhandle*/
00579     
00580 #if (MEMTRACKER == 1)
00581     boolean debugnewclearhandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *hreturned) {
00582         
00583         register Handle h;
00584         register long ctbytes;
00585         
00586         ctbytes = size; /*copy into a register*/
00587         
00588         h = debuggetnewhandle (filename, linenumber, threadid, ctbytes, false);
00589         
00590         if (h == nil) {
00591             
00592             *hreturned = nil;
00593             
00594             memoryerror ();
00595             
00596             return (false);
00597             }
00598             
00599         clearhandle (h);
00600         
00601         *hreturned = h;
00602         
00603         return (true);
00604         } /*newclearhandle*/
00605         
00606 
00607     boolean debugnewfilledhandle (char * filename, unsigned long linenumber, unsigned long threadid, ptrvoid pdata, long size, Handle *hreturned) {
00608         
00609         register Handle h;
00610         register long ctbytes;
00611         
00612         ctbytes = size; 
00613         
00614         h = debuggetnewhandle (filename, linenumber, threadid, ctbytes, false);
00615         
00616         if (h == nil) {
00617             
00618             *hreturned = nil;
00619             
00620             memoryerror ();
00621             
00622             return (false);
00623             }
00624         
00625         moveleft (pdata, *h, ctbytes);
00626             
00627         *hreturned = h;
00628         
00629         return (true);
00630         } /*newfilledhandle*/
00631 #else   
00632     boolean newclearhandle (long size, Handle *hreturned) {
00633         
00634         register Handle h;
00635         register long ctbytes;
00636         
00637         ctbytes = size; /*copy into a register*/
00638         
00639         h = getnewhandle (ctbytes, false);
00640         
00641         if (h == nil) {
00642             
00643             *hreturned = nil;
00644             
00645             memoryerror ();
00646             
00647             return (false);
00648             }
00649             
00650         clearhandle (h);
00651         
00652         *hreturned = h;
00653         
00654         return (true);
00655         } /*newclearhandle*/
00656         
00657 
00658     boolean newfilledhandle (ptrvoid pdata, long size, Handle *hreturned) {
00659         
00660         register Handle h;
00661         register long ctbytes;
00662         
00663         ctbytes = size; 
00664         
00665         h = getnewhandle (ctbytes, false);
00666         
00667         if (h == nil) {
00668             
00669             *hreturned = nil;
00670             
00671             memoryerror ();
00672             
00673             return (false);
00674             }
00675         
00676         moveleft (pdata, *h, ctbytes);
00677             
00678         *hreturned = h;
00679         
00680         return (true);
00681         } /*newfilledhandle*/
00682 #endif
00683 
00684 #if (flruntime==0)
00685 #if (odbengine==0)
00686 static long getidealchunksize (void) {
00687     
00688     /*
00689     our caller wants to pre-allocate something large. as large as possible 
00690     without necessarily forcing a heap compaction.
00691     
00692     our algorith: find out what the largest possible size would be if the 
00693     heap was compated, then back off a bit, depending on what the number is. 
00694     often, there's one big free block and many small ones, so hopefully this 
00695     will yield a good result on average.
00696     
00697     4/20/93 dmb: tweaked algorith; if more than 64K is available, grab half
00698     */
00699 #ifdef MACVERSION       
00700     register long ctgrab = MaxBlock ();
00701     
00702     if (ctgrab < 0x4000)
00703         ctgrab -= 0x0400;
00704     else
00705         if (ctgrab < 0x10000)
00706             ctgrab -= 0x2000;
00707         else
00708             ctgrab >>= 1;
00709     
00710     return (ctgrab);
00711 #endif
00712 
00713 #ifdef WIN95VERSION
00714     return (32768L);
00715 #endif
00716 
00717     } /*getidealchunksize*/
00718 
00719 #if (MEMTRACKER == 1)
00720     boolean debugnewgrowinghandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *h) {
00721         
00722         /*
00723         allocate a handle of the specified size, but with room to grow.
00724         
00725         note that the first getnewhandle should never fail, since the memory 
00726         manager just told us that an even large block could be produced. but 
00727         it's easy enough to handle that case too, so we do.
00728         */
00729         
00730         register long ctgrab = getidealchunksize ();
00731         
00732         if (ctgrab > size) {
00733             
00734             *h = debuggetnewhandle (filename, linenumber, threadid, ctgrab, false);
00735             
00736             if (*h != nil) {
00737                 
00738                 SetHandleSize (*h, size); /*can't fail, getting smaller*/
00739                 
00740                 return (true);
00741                 }
00742             }
00743         
00744         return (debugnewhandle (filename, linenumber, threadid, size, h));
00745         } /*newhandlewithroomtogrow*/
00746 #else
00747     boolean newgrowinghandle (long size, Handle *h) {
00748         
00749         /*
00750         allocate a handle of the specified size, but with room to grow.
00751         
00752         note that the first getnewhandle should never fail, since the memory 
00753         manager just told us that an even large block could be produced. but 
00754         it's easy enough to handle that case too, so we do.
00755         */
00756         
00757         register long ctgrab = getidealchunksize ();
00758         
00759         if (ctgrab > size) {
00760             
00761             *h = getnewhandle (ctgrab, false);
00762             
00763             if (*h != nil) {
00764                 
00765                 SetHandleSize (*h, size); /*can't fail, getting smaller*/
00766                 
00767                 return (true);
00768                 }
00769             }
00770         
00771         return (newhandle (size, h));
00772         } /*newhandlewithroomtogrow*/
00773 #endif
00774 
00775 #endif
00776 #endif
00777 
00778 
00779 boolean prepareforgrowing (Handle h) {
00780     
00781     /*
00782     like newgrowinghandle, but for an already-existing handle. the 
00783     caller is about to push a bunch of stuff onto it, and wants to 
00784     avoid having it continually compacting the heap along the way.
00785     */
00786     
00787     return (true); /*it turns out to be incredibly slow to resize an existing handle like this*/
00788     
00789     /*
00790     register long ctgrab = getidealchunksize ();
00791     register long ctorig = gethandlesize (h);
00792     
00793     if (h == nil) /*defensive driving%/
00794         return (false);
00795     
00796     ctgrab >>= 1; /*cut in half%/
00797     
00798     if (ctgrab > ctorig) {
00799         
00800         if (resizehandle (h, ctgrab)) {
00801             
00802             SetHandleSize (h, ctorig);
00803             
00804             return (true);
00805             }
00806         }
00807     
00808     return (false);
00809     */
00810     } /*prepareforgrowing*/
00811         
00812 
00813 #if (MEMTRACKER == 1)
00814 boolean debugcopyhandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle horig, Handle *hcopy) {
00815     
00816     register Handle h;
00817     register long ct;
00818     
00819     if (horig == nil) /*easy to copy a nil handle*/
00820         h = nil;
00821     
00822     else {
00823         
00824         ct = gethandlesize (horig);
00825         
00826         h = debuggetnewhandle (filename, linenumber, threadid, ct, false);
00827         
00828         if (h == nil) {
00829             
00830             memoryerror ();
00831             
00832             return (false);
00833             }
00834         
00835         moveleft (*horig, *h, ct);
00836         }
00837     
00838     *hcopy = h;
00839     
00840     return (true);
00841     } /*copyhandle*/
00842 #else
00843 boolean copyhandle (Handle horig, Handle *hcopy) {
00844     
00845     register Handle h;
00846     register long ct;
00847     
00848     if (horig == nil) /*easy to copy a nil handle*/
00849         h = nil;
00850     
00851     else {
00852         
00853         ct = gethandlesize (horig);
00854         
00855         h = getnewhandle (ct, false);
00856         
00857         if (h == nil) {
00858             
00859             memoryerror ();
00860             
00861             return (false);
00862             }
00863         
00864         moveleft (*horig, *h, ct);
00865         }
00866     
00867     *hcopy = h;
00868     
00869     return (true);
00870     } /*copyhandle*/
00871 #endif
00872 
00873 short comparehandles (Handle h1, Handle h2) {
00874     
00875     /*
00876     return -1 if h1 is less than h2, or +1 if h1 is greater than h2.
00877     
00878     return zero if the two byte streams are equal.
00879     
00880     9/21/92 dmb: make sure we don't dereference nil handles.
00881     */
00882     
00883     long len1, len2;
00884     register long ct;
00885     
00886     len1 = gethandlesize (h1);
00887     
00888     len2 = gethandlesize (h2);
00889     
00890     ct = min (len1, len2);
00891     
00892     if (ct > 0) { /*both handles are non-nil; safe to dereference*/
00893         
00894         register ptrbyte p1 = (ptrbyte) *h1;
00895         register ptrbyte p2 = (ptrbyte) *h2;
00896         
00897         for (; --ct >= 0; ++p1, ++p2)
00898         
00899             if (*p1 != *p2) { /*unequal chars*/
00900                 
00901                 register char n = (char) (*p1 - *p2); /*change into signed value*/
00902                 
00903                 return (sgn (n));
00904                 }
00905         }
00906     
00907     return (sgn (len1 - len2));
00908     } /*comparehandles*/
00909 
00910 
00911 boolean equalhandles (Handle h1, Handle h2) {
00912     
00913     /*
00914     we could check for equal handle sizes first, we don't expect this 
00915     to be a time-critical routine
00916     */
00917     
00918     return (comparehandles (h1, h2) == 0);
00919     } /*equalhandles*/
00920 
00921 
00922 long searchhandle (Handle hsearch, Handle hpattern, long ixstart, long ixlimit) {
00923     
00924     /*
00925     the beginning of something bigger.  first version -- search for the 
00926     pattern in the byte stream, return the offset of the first occurrence of
00927     the pattern.  -1 if not found.
00928     
00929     8/12/92 dmb: make sure ixstart is in range
00930     
00931     8/14/92 dmb: added ixlimit parameter
00932     */
00933     
00934     register ptrbyte psearch = (ptrbyte) *hsearch;
00935     register ptrbyte ppattern = (ptrbyte) *hpattern;
00936     register long ixstring = ixstart;
00937     register long i;
00938     register long lensearch = gethandlesize (hsearch);
00939     register long lenpattern = gethandlesize (hpattern);
00940     register byte chfirst;
00941     
00942     lensearch = min (ixlimit, lensearch) - lenpattern + 1;
00943     
00944     if ((lensearch <= 0) || (lenpattern == 0) || (ixstring >= lensearch))
00945         return (-1L);
00946     
00947     chfirst = ppattern [0];
00948     
00949     while (true) {
00950         
00951         if (psearch [ixstring] == chfirst) { /*matched at least first character in string*/
00952             
00953             for (i = 1; i < lenpattern; ++i) {
00954                 
00955                 if (psearch [ixstring + i] != ppattern [i]) 
00956                     goto L1;
00957                 } /*for*/
00958             
00959             return (ixstring); /*loop terminated, full match*/
00960             }
00961         
00962         L1: /*advance to next character in string*/
00963         
00964         if (++ixstring == lensearch) /*reached end of string, not found*/
00965             return (-1L);
00966         } /*while*/
00967     } /*searchhandle*/
00968 
00969 
00970 boolean sethandlecontents (ptrvoid pdata, long ctset, Handle hset) {
00971     
00972     if (!sethandlesize (hset, ctset))
00973         return (false);
00974     
00975     moveleft (pdata, *hset, ctset);
00976     
00977     return (true);
00978     } /*sethandlecontents*/
00979 
00980 
00981 void texttostring (ptrvoid ptext, long ctchars, bigstring bs) {
00982     
00983     register long len = ctchars;
00984     
00985     if (len > lenbigstring)
00986         len = lenbigstring;
00987     
00988     setstringlength (bs, len);
00989     
00990     moveleft (ptext, &bs [1], len);
00991     } /*texttostring*/
00992 
00993 
00994 void texthandletostring (Handle htext, bigstring bs) {
00995     
00996     texttostring (*htext, gethandlesize (htext), bs);
00997     } /*texthandletostring*/
00998 
00999 #if (MEMTRACKER == 1)
01000 boolean debugnewtexthandle (char * filename, unsigned long linenumber, unsigned long threadid, const bigstring bs, Handle *htext) {
01001     
01002     /*
01003     create a new handle to hold the text of the string.
01004     
01005     if the string is "\pABC" -- you get a handle of size 3.
01006     */
01007     
01008     register long len = stringlength (bs);
01009     register Handle h;
01010     
01011     h = debuggetnewhandle (filename, linenumber, threadid, len, false);
01012     
01013     if (h == nil) {
01014         
01015         memoryerror ();
01016         
01017         return (false);
01018         }
01019     
01020     if (len > 0)
01021         moveleft ((ptrstring) stringbaseaddress (bs), *h, len);
01022     
01023     *htext = h; /*pass handle back to caller*/
01024     
01025     return (true);
01026     } /*newtexthandle*/
01027 #else
01028 boolean newtexthandle (const bigstring bs, Handle *htext) {
01029     
01030     /*
01031     create a new handle to hold the text of the string.
01032     
01033     if the string is "\pABC" -- you get a handle of size 3.
01034     */
01035     
01036     register long len = stringlength (bs);
01037     register Handle h;
01038     
01039     h = getnewhandle (len, false);
01040     
01041     if (h == nil) {
01042         
01043         memoryerror ();
01044         
01045         return (false);
01046         }
01047     
01048     if (len > 0)
01049         moveleft ((ptrstring) stringbaseaddress (bs), *h, len);
01050     
01051     *htext = h; /*pass handle back to caller*/
01052     
01053     return (true);
01054     } /*newtexthandle*/
01055 #endif
01056 
01057 boolean insertinhandle (Handle hgrow, long ix, ptrvoid pdata, long ctgrow) {
01058     
01059     /*
01060     make the handle big enough to hold the new data, and insert the new 
01061     data into the newly enlarged handle.
01062     
01063     8.1.97 dmb: if pdata is nil, initialize new data to zeros
01064     */
01065     
01066     Handle h = hgrow;
01067     unsigned long origsize;
01068     
01069     if (ctgrow == 0)
01070         return (true);
01071     
01072     origsize = gethandlesize (hgrow);
01073     
01074     if (!sethandlesize (hgrow, origsize + ctgrow))
01075         return (false);
01076     
01077     if (ix < origsize)
01078         moveright (*hgrow + ix, *hgrow + ix + ctgrow, origsize - ix);
01079     
01080     if (pdata == nil)
01081         clearbytes (*hgrow + ix, ctgrow);
01082     else
01083         moveleft (pdata, *hgrow + ix, ctgrow);
01084     
01085     return (true);
01086     } /*insertinhandle*/
01087 
01088 
01089 boolean inserthandleinhandle (Handle hinsert, Handle h, unsigned long ix) {
01090     
01091     unsigned long insertlen = gethandlesize (hinsert);
01092     unsigned long ct = gethandlesize (h);
01093     unsigned long newlen = ct + insertlen;
01094     
01095     if (hinsert == nil) /*nothing to do*/
01096         return (true);
01097         
01098     if (!sethandlesize (h, newlen))
01099         return (false);
01100     
01101     moveright (&(*h) [ix], &(*h) [ix + insertlen], ct - ix);
01102     
01103     moveleft (*hinsert, &(*h) [ix], insertlen);
01104     
01105     return (true);
01106     } /*inserthandleinhandle*/
01107     
01108     
01109 boolean pullfromhandle (Handle hpull, long ixpull, long ctpull, ptrvoid pdata) {
01110     
01111     /*
01112     8/14/91 dmb: accept nil for pdata to remove bytes without retaining them
01113     */
01114     
01115     register Handle h = hpull;
01116     register long ix = ixpull;
01117     register long ct = ctpull;
01118     register long newsize = gethandlesize (h) - ct;
01119     
01120     if ((ix < 0) || (ix > newsize))
01121         return (false);
01122     
01123     if (pdata != nil)
01124         moveleft (*h + ix, pdata, ct); /*copy out of the handle*/
01125     
01126     moveleft (*h + ix + ct, *h + ix, newsize - ix);
01127     
01128     return (sethandlesize (h, newsize)); /*should never fail -- getting smaller*/
01129     } /*pullfromhandle*/
01130 
01131 
01132 boolean enlargehandle (Handle hgrow, long ctgrow, ptrvoid newdata) {
01133     
01134     /*
01135     make the handle big enough to hold the new data, and move the new data in
01136     at the end of the newly enlarged handle.
01137     
01138     8.1.97 dmb: if newdata is nil, initialize new data to zeros
01139     */
01140     
01141     return (insertinhandle (hgrow, gethandlesize (hgrow), newdata, ctgrow));
01142     
01143     /*
01144     register Handle h = hgrow;
01145     register long ct = ctgrow;
01146     register ptrbyte p = newdata;
01147     register long origsize;
01148     
01149     if (hgrow == nil)
01150         Debugger ();
01151     
01152     if (ct == 0)
01153         return (true);
01154     
01155     origsize = gethandlesize (h);
01156     
01157     if (!sethandlesize (h, origsize + ct))
01158         return (false);
01159     
01160     moveleft (p, *h + origsize, ct);
01161     
01162     return (true);
01163     */
01164     
01165     } /*enlargehandle*/
01166 
01167 
01168 boolean mungehandle (Handle hmunge, long ixmunge, long ctmunge, ptrvoid pinsert, long ctinsert) {
01169     
01170     /*
01171     modeled after the Mac Toolbox utility "Munger", minus the search 
01172     capability, plus some error handling...
01173     
01174     overwrite ctmunge bytes in the handle hmunge, starting at offset ixmunge, 
01175     with the bytes indicated by pinsert, ctinsert.  resize the handle as 
01176     required, shifting any bytes to the right
01177     */
01178     
01179     register long sizediff = ctinsert - ctmunge;
01180     register byte *pdata = pinsert;
01181     
01182     switch (sgn (sizediff)) { /*insert or delete unmatched bytes*/
01183         
01184         case +1: /*growing*/
01185             if (!insertinhandle (hmunge, ixmunge + ctmunge, pdata + ctmunge, sizediff))
01186                 return (false);
01187             
01188             break;
01189         
01190         case -1: /*shrinking*/
01191             pullfromhandle (hmunge, ixmunge + ctinsert, -sizediff, nil);
01192             
01193             break;
01194         
01195         default: /*no change*/
01196             break;
01197         }
01198     
01199     moveleft (pdata, *hmunge + ixmunge, min (ctinsert, ctmunge));
01200     
01201     return (true);
01202     } /*mungehandle*/
01203 
01204 
01205 boolean pushstringhandle (const bigstring bs, Handle htext) {
01206     
01207     /*
01208     htext is a handle created with newtexthandle.
01209     
01210     increase the size of the handle so we can push the pascal string bs 
01211     at the end of the handle (including length byte).
01212     */
01213     
01214     return (enlargehandle (htext, (long) stringsize (bs), (ptrvoid) bs));
01215     } /*pushstringhandle*/
01216 
01217 
01218 boolean pushtexthandle (const bigstring bs, Handle htext) {
01219     
01220     /*
01221     htext is a handle created with newtexthandle.
01222     
01223     increase the size of the handle so we can push the text of bs at 
01224     the end of the handle (not including length byte).
01225     */
01226     
01227     return (enlargehandle (htext, (long) stringlength (bs), (ptrvoid) stringbaseaddress (bs)));
01228     } /*pushtexthandle*/
01229 
01230 
01231 /*
01232 boolean pushindentedline (short level, bigstring bs, Handle htext) {
01233     
01234     /*
01235     add a line to the indicated text buffer, indented with tab characters and
01236     terminated with a carriage return.
01237     
01238     return false if it failed, we dispose of htext if it failed.
01239     %/
01240     
01241     bigstring bsoutput;
01242     
01243     filledstring (chtab, level, bsoutput); /*put out leading tabs%/
01244     
01245     pushstring (bs, bsoutput); /*put out the string itself%/
01246     
01247     pushchar (chreturn, bsoutput); /*put out a terminating carriage return character%/
01248     
01249     if (!pushtexthandle (bsoutput, htext)) { /*out of memory%/
01250     
01251         disposehandle (htext);
01252         
01253         return (false);
01254         }
01255     
01256     return (true);
01257     } /*pushindentedline*/
01258        
01259 
01260 #if (MEMTRACKER == 1)
01261 boolean debugnewheapstring (char * filename, unsigned long linenumber, unsigned long threadid, const bigstring bs, hdlstring *hstring) {
01262     
01263     /*
01264     3/28/97 dmb: rewrote x-plat; don't use NewString toolbox
01265     */
01266 
01267     return (debugnewfilledhandle (filename, linenumber, threadid, (void *) bs, stringsize (bs), (Handle *)hstring));
01268     } /*newheapstring*/
01269 #else
01270 boolean newheapstring (const bigstring bs, hdlstring *hstring) {
01271     
01272     /*
01273     3/28/97 dmb: rewrote x-plat; don't use NewString toolbox
01274     */
01275 
01276     return (newfilledhandle ((void *) bs, stringsize (bs), (Handle *)hstring));
01277     } /*newheapstring*/
01278 #endif
01279 
01280 boolean setheapstring (const bigstring bs, hdlstring hstring) {
01281     
01282     return (sethandlecontents ((ptrvoid) bs, stringlength (bs) + 1, (Handle) hstring));
01283     } /*setheapstring*/
01284 
01285 
01286 /*
01287 boolean concatheapstrings (h1, h2, hreturned) hdlstring *h1, *h2, *hreturned; {
01288 
01289     /*
01290     given two heap strings, return a heap string that's the result of 
01291     concatenating the two strings.
01292     
01293     return false if the resulting string would be too long, or if there
01294     was a memory allocation error.
01295     %/
01296     
01297     bigstring bs1, bs2;
01298     bigstring bs;
01299     register long len1, len2;
01300     register long len;
01301     register hdlstring hstring;
01302     
01303     copyheapstring (*h1, bs1);
01304     
01305     copyheapstring (*h2, bs2);
01306     
01307     len1 = stringlength(bs1);
01308     
01309     len2 = stringlength(bs2);
01310     
01311     len = len1 + len2;
01312     
01313     if (len > lenbigstring)
01314         return (false);
01315         
01316     setstringlength(bs, len);
01317     
01318     moveleft (&bs1 [1], &bs [1], len1);
01319     
01320     moveleft (&bs2 [1], &bs [1 + len1], len2);
01321         
01322     return (newheapstring (bs, hreturned));
01323     } /*concatheapstrings%/
01324 */
01325 
01326 
01327 boolean pushhandle (Handle hsource, Handle hdest) {
01328     
01329     /*
01330     add the content of the source handle at the end of the destination handle.
01331     */
01332     
01333     register boolean fl;
01334     
01335     if (hsource == nil)
01336         return (true);
01337     
01338     HLock (hsource);
01339     
01340     fl = enlargehandle (hdest, gethandlesize (hsource), *hsource);
01341     
01342     HUnlock (hsource);
01343     
01344     return (fl);
01345     } /*pushhandle*/
01346     
01347 
01348 boolean loadfromhandle (Handle hload, long *ixload, long ctload, ptrvoid pdata) {
01349     
01350     /*
01351     copy the next ctload bytes from hload into pdata and increment the index.
01352     
01353     return false if there aren't enough bytes.
01354     
01355     start ixload at 0.
01356     */
01357     
01358     register Handle h = hload;
01359     register ptrbyte p = pdata;
01360     register long ct = ctload;
01361     register long ix = *ixload;
01362     register long size;
01363     
01364     size = gethandlesize (h);
01365     
01366     if (ix < 0) /*bad index*/
01367         return (false);
01368     
01369     if ((ix + ct) > size) /*asked for more bytes than there are*/
01370         return (false); 
01371         
01372     moveleft (*h + ix, p, ct); /*copy out of the handle*/
01373     
01374     *ixload = ix + ct; /*increment the index into the handle*/
01375     
01376     return (true);
01377     } /*loadfromhandle*/
01378 
01379 #if (MEMTRACKER == 1)
01380 boolean debugloadfromhandletohandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle hload, long *ixload, long ctload, boolean fltemp, Handle *hnew) {
01381     
01382     /*
01383     load from the source handle, creating a new handle to hold the loaded stuff.
01384     
01385     6/8/91 dmb: fixed memory leak if loadfromhandle fails
01386     
01387     11/27/91 dmb: reject ctload < 0
01388     
01389     2.1b3 dmb: added fltemp parameter to determine whether caller is going 
01390     to dispose the result soon.
01391     */
01392     
01393     Handle h;
01394     
01395     if (ctload < 0)
01396         return (false);
01397     
01398     h = debuggetnewhandle (filename, linenumber, threadid, ctload, fltemp);
01399     
01400     if (h == nil) {
01401         
01402         memoryerror ();
01403         
01404         return (false);
01405         }
01406     
01407     if (!loadfromhandle (hload, ixload, ctload, *h)) {
01408         
01409         disposehandle (h);
01410         
01411         return (false);
01412         }
01413     
01414     *hnew = h;
01415     
01416     return (true);
01417     } /*loadfromhandletohandle*/
01418 
01419 
01420 boolean debugloadhandleremains (char * filename, unsigned long linenumber, unsigned long threadid, long ix, Handle hsource, Handle *hdest) {
01421 
01422     /*
01423     load all the bytes following ix from the source handle into the dest handle.
01424     
01425     2.1b3 dmb: callers of this routine are (almost) always fine with 
01426     temporary memory, so let's use it.
01427     */
01428     
01429     return (debugloadfromhandletohandle (filename, linenumber, threadid, hsource, &ix, gethandlesize (hsource) - ix, true, hdest));
01430     } /*loadhandleremains*/
01431 #else
01432 boolean loadfromhandletohandle (Handle hload, long *ixload, long ctload, boolean fltemp, Handle *hnew) {
01433     
01434     /*
01435     load from the source handle, creating a new handle to hold the loaded stuff.
01436     
01437     6/8/91 dmb: fixed memory leak if loadfromhandle fails
01438     
01439     11/27/91 dmb: reject ctload < 0
01440     
01441     2.1b3 dmb: added fltemp parameter to determine whether caller is going 
01442     to dispose the result soon.
01443     */
01444     
01445     Handle h;
01446     
01447     if (ctload < 0)
01448         return (false);
01449     
01450     h = getnewhandle (ctload, fltemp);
01451     
01452     if (h == nil) {
01453         
01454         memoryerror ();
01455         
01456         return (false);
01457         }
01458     
01459     if (!loadfromhandle (hload, ixload, ctload, *h)) {
01460         
01461         disposehandle (h);
01462         
01463         return (false);
01464         }
01465     
01466     *hnew = h;
01467     
01468     return (true);
01469     } /*loadfromhandletohandle*/
01470 
01471 
01472 boolean loadhandleremains (long ix, Handle hsource, Handle *hdest) {
01473 
01474     /*
01475     load all the bytes following ix from the source handle into the dest handle.
01476     
01477     2.1b3 dmb: callers of this routine are (almost) always fine with 
01478     temporary memory, so let's use it.
01479     */
01480     
01481     return (loadfromhandletohandle (hsource, &ix, gethandlesize (hsource) - ix, true, hdest));
01482     } /*loadhandleremains*/
01483 #endif
01484     
01485     
01486 boolean pushlongondiskhandle (long x, Handle hpush) {
01487     
01488     memtodisklong (x);
01489     
01490     return (enlargehandle (hpush, sizeof (long), &x));
01491     } /*pushlongtodiskhandle*/
01492 
01493 
01494 boolean loadlongfromdiskhandle (Handle hload, long *ixload, long *x) {
01495     
01496     if (!loadfromhandle (hload, ixload, sizeof (long), x))
01497         return (false);
01498     
01499     disktomemlong (*x);
01500     
01501     return (true);
01502     } /*loadlongfromdiskhandle*/
01503 
01504 
01505 boolean popfromhandle (Handle hpop, long ctpop, ptrvoid pdata) {
01506     
01507     register Handle h = hpop;
01508     register long ixpop = gethandlesize (h) - ctpop;
01509     
01510     if (ixpop < 0)
01511         return (false);
01512     
01513     if (pdata != nil)
01514         moveleft (*h + ixpop, pdata, ctpop); /*copy out of the handle*/
01515     
01516     return (sethandlesize (h, ixpop)); /*should never fail -- getting smaller*/
01517     } /*popfromhandle*/
01518 
01519 
01520 boolean copyhandlecontents (Handle hsource, Handle hdest) {
01521     
01522     /*
01523     copy the contents of hsource into hdest's space.  if hdest isn't large
01524     enough to receive hsource's content, we enlarge hdest.  if this fails 
01525     we return false.
01526     
01527     7/5/91 dmb: we now implement a more strict copy; the destination handle 
01528     is always sized to match the original.
01529     */
01530     
01531     register long ctsource;
01532     
01533     ctsource = gethandlesize (hsource);
01534     
01535     if (!sethandlesize (hdest, ctsource)) /*heap allocation failed*/
01536         return (false);
01537     
01538     moveleft (*hsource, *hdest, ctsource);
01539     
01540     return (true);
01541     } /*copyhandlecontents*/
01542     
01543 
01544 #if (MEMTRACKER == 1)
01545 boolean debugconcathandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle h1, Handle h2, Handle *hmerged) {
01546     
01547     /*
01548     create a new handle which is the concatenation of two handles.
01549     */
01550     
01551     register Handle h;
01552     long sizefirsthandle;
01553     long sizesecondhandle;
01554     register ptrbyte p;
01555     
01556     *hmerged = nil; /*default return value*/
01557     
01558     sizefirsthandle = gethandlesize (h1);
01559     
01560     sizesecondhandle = gethandlesize (h2);
01561     
01562     h = debuggetnewhandle (filename, linenumber, threadid, sizefirsthandle + sizesecondhandle, false);
01563     
01564     if (h == nil) {
01565         
01566         memoryerror ();
01567         
01568         return (false);
01569         }
01570     
01571     p = (ptrbyte) *h;
01572         
01573     moveleft (*h1, p, sizefirsthandle);
01574     
01575     p += sizefirsthandle;
01576     
01577     moveleft (*h2, p, sizesecondhandle);
01578     
01579     *hmerged = h;
01580     
01581     return (true);
01582     } /*concathandles*/
01583     
01584     
01585 boolean debugmergehandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle h1, Handle h2, Handle *hmerged) {
01586     
01587     /*
01588     create a new handle which is the concatenation of two handles.  the first
01589     four bytes of the new handle store the size of the first handle so the merged
01590     handle can be easily unpacked.
01591     
01592     6/8/90 DW: modified so it could deal with nil handles.
01593     
01594     10/7/91 dmb: try to merge result into the larger of the original handles, so 
01595     that our memory overhead can be almost cut in half.
01596     
01597     2.1b3 dmb: in the unusual case the we allocated a new handle, go ahead 
01598     and use temporary memory if available. this might not always be ideal, but 
01599     more often than not it will be best -- we're likely Saving, and tossing 
01600     the merged handle soon.
01601     */
01602     
01603     register Handle h;
01604     long sizefirsthandle;
01605     long sizesecondhandle;
01606     long sizemergedhandle;
01607     long storesizefirsthandle;
01608     register ptrbyte p;
01609     
01610     *hmerged = nil; /*default return value*/
01611     
01612     sizefirsthandle = gethandlesize (h1);
01613     storesizefirsthandle = conditionallongswap (sizefirsthandle);
01614     
01615     sizesecondhandle = gethandlesize (h2);
01616     
01617     sizemergedhandle = sizeof (long) + sizefirsthandle + sizesecondhandle;
01618     
01619     if (sizefirsthandle > sizesecondhandle) { /*try using h1 for result*/
01620         
01621         if (resizehandle (h1, sizemergedhandle)) {
01622             
01623             p = (ptrbyte) *h1;
01624             
01625             moveright (p, p + sizeof (long), sizefirsthandle);
01626             
01627             moveleft (&storesizefirsthandle, p, sizeof (long));
01628             
01629             if (h2 != nil)
01630                 moveleft (*h2, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01631             
01632             *hmerged = h1;
01633             
01634             disposehandle (h2);
01635             
01636             return (true);
01637             }
01638         }
01639     
01640     else if (h2 != nil) { /*try using h2 for result*/
01641         
01642         if (resizehandle (h2, sizemergedhandle)) {
01643             
01644             p = (ptrbyte) *h2;
01645             
01646             moveright (p, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01647             
01648             moveleft (&storesizefirsthandle, p, sizeof (long));
01649             
01650             if (h1 != nil)
01651                 moveleft (*h1, p + sizeof (long), sizefirsthandle);
01652             
01653             *hmerged = h2;
01654             
01655             disposehandle (h1);
01656             
01657             return (true);
01658             }
01659         }
01660     
01661     /*resizing didn't work; try it the old way, using a newly-allocated handle*/
01662     
01663     h = debuggetnewhandle (filename, linenumber, threadid, sizemergedhandle, true);
01664     
01665     if (h == nil) {
01666         
01667         memoryerror ();
01668         
01669         disposehandle (h1);
01670         
01671         disposehandle (h2);
01672         
01673         return (false);
01674         }
01675     
01676     p = (ptrbyte) *h;
01677     
01678     moveleft (&storesizefirsthandle, p, sizeof (long));
01679     
01680     p += sizeof (long);
01681     
01682     if (h1 != nil)
01683         moveleft (*h1, p, sizefirsthandle);
01684     
01685     if (h2 != nil)
01686         moveleft (*h2, p + sizefirsthandle, sizesecondhandle);
01687     
01688     *hmerged = h;
01689     
01690     disposehandle (h1);
01691     
01692     disposehandle (h2);
01693     
01694     return (true);
01695     } /*mergehandles*/
01696 
01697 
01698 boolean debugunmergehandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle hmerged, Handle *hfirst, Handle *hsecond) {
01699     
01700     /*
01701     split up a handle created by mergehandle.
01702     
01703     3/12/91 dmb: rewrote so that we own hmerged; caller no longer diposes it.  
01704     this allows us to reuse the handle to greatly reduce memory requirements.  
01705     we could further optimize by reusing hmerged for the larger handle instead 
01706     of always hsecond.
01707     
01708     also, avoid locking handles when we're trying to allocate potentially 
01709     large chunks of memory.
01710     
01711     2.1b3 dmb: newly-created handle is always ok as temporary memory
01712     */
01713     
01714     register Handle h1 = nil, h2 = nil;
01715     register Handle h = hmerged;
01716     long ix;
01717     long sizefirsthandle, sizesecondhandle;
01718     
01719     *hfirst = *hsecond = nil; /*default return values*/
01720     
01721     moveleft (*h, &sizefirsthandle, sizeof (long));
01722 
01723 #ifdef PACKFLIPPED
01724     longswap (sizefirsthandle);
01725 #endif
01726     
01727     ix = sizeof (long);
01728     
01729     if (sizefirsthandle == 0)
01730         h1 = nil;
01731         
01732     else {
01733         h1 = debuggetnewhandle (filename, linenumber, threadid, sizefirsthandle, true);
01734         
01735         if (h1 == nil) 
01736             goto error;
01737         
01738         moveleft (*h + ix, *h1, sizefirsthandle);
01739         }
01740     
01741     ix += sizefirsthandle;
01742     
01743     sizesecondhandle = gethandlesize (h) - sizefirsthandle - sizeof (long);
01744     
01745     if (sizesecondhandle == 0) {
01746         
01747         h2 = nil;
01748         
01749         disposehandle (h);
01750         }
01751     else {
01752         
01753         h2 = h; /*second handle can safely re-use merged handle*/
01754         
01755         moveleft (*h2 + ix, *h2, sizesecondhandle);
01756         
01757         sethandlesize (h2, sizesecondhandle);
01758         }
01759     
01760     *hfirst = h1; /*return handles to caller*/
01761     
01762     *hsecond = h2;
01763     
01764     return (true);
01765         
01766     error:
01767     
01768     disposehandle (h);
01769     
01770     disposehandle (h1);
01771         
01772     disposehandle (h2);
01773     
01774     memoryerror ();
01775     
01776     return (false);
01777     } /*unmergehandles*/
01778     
01779     
01780 boolean debugnewintarray (char * filename, unsigned long linenumber, unsigned long threadid, short ct, hdlintarray *harray) {
01781     
01782     Handle h;
01783     
01784     if (!debugnewclearhandle (filename, linenumber, threadid, sizeof (short) * ct, &h))
01785         return (false);
01786         
01787     *harray = (hdlintarray) h;
01788     
01789     return (true);
01790     } /*newintarray*/
01791 #else   
01792 boolean concathandles (Handle h1, Handle h2, Handle *hmerged) {
01793     
01794     /*
01795     create a new handle which is the concatenation of two handles.
01796     */
01797     
01798     register Handle h;
01799     long sizefirsthandle;
01800     long sizesecondhandle;
01801     register ptrbyte p;
01802     
01803     *hmerged = nil; /*default return value*/
01804     
01805     sizefirsthandle = gethandlesize (h1);
01806     
01807     sizesecondhandle = gethandlesize (h2);
01808     
01809     h = getnewhandle (sizefirsthandle + sizesecondhandle, false);
01810     
01811     if (h == nil) {
01812         
01813         memoryerror ();
01814         
01815         return (false);
01816         }
01817     
01818     p = (ptrbyte) *h;
01819         
01820     moveleft (*h1, p, sizefirsthandle);
01821     
01822     p += sizefirsthandle;
01823     
01824     moveleft (*h2, p, sizesecondhandle);
01825     
01826     *hmerged = h;
01827     
01828     return (true);
01829     } /*concathandles*/
01830     
01831     
01832 boolean mergehandles (Handle h1, Handle h2, Handle *hmerged) {
01833     
01834     /*
01835     create a new handle which is the concatenation of two handles.  the first
01836     four bytes of the new handle store the size of the first handle so the merged
01837     handle can be easily unpacked.
01838     
01839     6/8/90 DW: modified so it could deal with nil handles.
01840     
01841     10/7/91 dmb: try to merge result into the larger of the original handles, so 
01842     that our memory overhead can be almost cut in half.
01843     
01844     2.1b3 dmb: in the unusual case the we allocated a new handle, go ahead 
01845     and use temporary memory if available. this might not always be ideal, but 
01846     more often than not it will be best -- we're likely Saving, and tossing 
01847     the merged handle soon.
01848     */
01849     
01850     register Handle h;
01851     long sizefirsthandle;
01852     long sizesecondhandle;
01853     long sizemergedhandle;
01854     long storesizefirsthandle;
01855     register ptrbyte p;
01856     
01857     *hmerged = nil; /*default return value*/
01858     
01859     sizefirsthandle = gethandlesize (h1);
01860     storesizefirsthandle = conditionallongswap (sizefirsthandle);
01861     
01862     sizesecondhandle = gethandlesize (h2);
01863     
01864     sizemergedhandle = sizeof (long) + sizefirsthandle + sizesecondhandle;
01865     
01866     if (sizefirsthandle > sizesecondhandle) { /*try using h1 for result*/
01867         
01868         if (resizehandle (h1, sizemergedhandle)) {
01869             
01870             p = (ptrbyte) *h1;
01871             
01872             moveright (p, p + sizeof (long), sizefirsthandle);
01873             
01874             moveleft (&storesizefirsthandle, p, sizeof (long));
01875             
01876             if (h2 != nil)
01877                 moveleft (*h2, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01878             
01879             *hmerged = h1;
01880             
01881             disposehandle (h2);
01882             
01883             return (true);
01884             }
01885         }
01886     
01887     else if (h2 != nil) { /*try using h2 for result*/
01888         
01889         if (resizehandle (h2, sizemergedhandle)) {
01890             
01891             p = (ptrbyte) *h2;
01892             
01893             moveright (p, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01894             
01895             moveleft (&storesizefirsthandle, p, sizeof (long));
01896             
01897             if (h1 != nil)
01898                 moveleft (*h1, p + sizeof (long), sizefirsthandle);
01899             
01900             *hmerged = h2;
01901             
01902             disposehandle (h1);
01903             
01904             return (true);
01905             }
01906         }
01907     
01908     /*resizing didn't work; try it the old way, using a newly-allocated handle*/
01909     
01910     h = getnewhandle (sizemergedhandle, true);
01911     
01912     if (h == nil) {
01913         
01914         memoryerror ();
01915         
01916         disposehandle (h1);
01917         
01918         disposehandle (h2);
01919         
01920         return (false);
01921         }
01922     
01923     p = (ptrbyte) *h;
01924     
01925     moveleft (&storesizefirsthandle, p, sizeof (long));
01926     
01927     p += sizeof (long);
01928     
01929     if (h1 != nil)
01930         moveleft (*h1, p, sizefirsthandle);
01931     
01932     if (h2 != nil)
01933         moveleft (*h2, p + sizefirsthandle, sizesecondhandle);
01934     
01935     *hmerged = h;
01936     
01937     disposehandle (h1);
01938     
01939     disposehandle (h2);
01940     
01941     return (true);
01942     } /*mergehandles*/
01943 
01944 
01945 boolean unmergehandles (Handle hmerged, Handle *hfirst, Handle *hsecond) {
01946     
01947     /*
01948     split up a handle created by mergehandle.
01949     
01950     3/12/91 dmb: rewrote so that we own hmerged; caller no longer diposes it.  
01951     this allows us to reuse the handle to greatly reduce memory requirements.  
01952     we could further optimize by reusing hmerged for the larger handle instead 
01953     of always hsecond.
01954     
01955     also, avoid locking handles when we're trying to allocate potentially 
01956     large chunks of memory.
01957     
01958     2.1b3 dmb: newly-created handle is always ok as temporary memory
01959     */
01960     
01961     register Handle h1 = nil, h2 = nil;
01962     register Handle h = hmerged;
01963     long ix;
01964     long sizefirsthandle, sizesecondhandle;
01965     
01966     *hfirst = *hsecond = nil; /*default return values*/
01967     
01968     moveleft (*h, &sizefirsthandle, sizeof (long));
01969 
01970 #ifdef PACKFLIPPED
01971     longswap (sizefirsthandle);
01972 #endif
01973     
01974     ix = sizeof (long);
01975     
01976     if (sizefirsthandle == 0)
01977         h1 = nil;
01978         
01979     else {
01980         h1 = getnewhandle (sizefirsthandle, true);
01981         
01982         if (h1 == nil) 
01983             goto error;
01984         
01985         moveleft (*h + ix, *h1, sizefirsthandle);
01986         }
01987     
01988     ix += sizefirsthandle;
01989     
01990     sizesecondhandle = gethandlesize (h) - sizefirsthandle - sizeof (long);
01991     
01992     if (sizesecondhandle == 0) {
01993         
01994         h2 = nil;
01995         
01996         disposehandle (h);
01997         }
01998     else {
01999         
02000         h2 = h; /*second handle can safely re-use merged handle*/
02001         
02002         moveleft (*h2 + ix, *h2, sizesecondhandle);
02003         
02004         sethandlesize (h2, sizesecondhandle);
02005         }
02006     
02007     *hfirst = h1; /*return handles to caller*/
02008     
02009     *hsecond = h2;
02010     
02011     return (true);
02012         
02013     error:
02014     
02015     disposehandle (h);
02016     
02017     disposehandle (h1);
02018         
02019     disposehandle (h2);
02020     
02021     memoryerror ();
02022     
02023     return (false);
02024     } /*unmergehandles*/
02025     
02026     
02027 boolean newintarray (short ct, hdlintarray *harray) {
02028     
02029     Handle h;
02030     
02031     if (!newclearhandle (sizeof (short) * ct, &h))
02032         return (false);
02033         
02034     *harray = (hdlintarray) h;
02035     
02036     return (true);
02037     } /*newintarray*/
02038 #endif
02039 
02040 boolean setintarray (hdlintarray harray, short ix, short val) {
02041     
02042     /*
02043     assign into a cell in a variable-size array of integers, 0-based index.
02044     
02045     return false if the array needed to be extended but there isn't enough
02046     memory to do it.
02047     */
02048     
02049     register hdlintarray h = harray;
02050 
02051     if (!minhandlesize ((Handle) h, (ix + 1) * sizeof (short)))
02052         return (false);
02053     
02054     (*harray) [ix] = val;
02055     
02056     return (true);
02057     } /*setintarray*/
02058     
02059     
02060 boolean getintarray (hdlintarray harray, short ix, short *val) {
02061     
02062     *val = (*harray) [ix];
02063     
02064     return (true);
02065     } /*getintarray*/
02066     
02067     
02068 void fillintarray (hdlintarray harray, short val) {
02069     
02070     register hdlintarray h = harray;
02071     register short ct;
02072     /*
02073     register short i;
02074     */
02075     
02076     ct = (short) gethandlesize ((Handle) h) / sizeof (short);
02077 
02078     while (--ct >= 0)
02079         (*h) [ct] = val;
02080 
02081     /*
02082     lockhandle ((Handle) h);
02083     
02084     for (i = 0; i < ct; i++)
02085         (*h) [i] = x;
02086 
02087     unlockhandle ((Handle) h);
02088     */
02089 
02090     } /*fillintarray*/
02091 
02092 #if (flruntime==0)
02093 #if (odbengine==0)
02094 boolean initmemory (void) {
02095     
02096     shellpushmemoryhook (&safetycushionhook);
02097     
02098     return (getsafetycushion ());
02099     } /*initmemory*/
02100 #endif
02101 #endif
02102 
02103 
02104 
02105 
02106 
02107 
02108 

Generated on Wed May 31 18:19:55 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6