memory.c

Go to the documentation of this file.
00001 
00002 /*  $Id: memory.c 1259 2006-04-13 04:56:46Z sethdill $    */
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 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "error.h"
00032 #include "memory.h"
00033 #include "ops.h"
00034 #include "shellhooks.h"
00035 #include "strings.h"
00036 #include "byteorder.h"  /* 2006-04-08 aradke: endianness conversion macros */
00037 
00038 
00039 #define safetycushionsize 0x2800 /*10K*/
00040 
00041 // TRT - 20 Mar 2005 - 10.1a2 - only used for debugging on Mac OS
00042 #ifdef MACVERSION
00043 
00044     #ifdef fldebug
00045 
00046         long cttemphandles = 0;
00047 
00048         THz tempzone;
00049 
00050     #endif
00051 
00052     #if (MEMTRACKER==1)
00053 
00054         // for real tracking need to implement these functions
00055         #define debugaddmemhandle(h, ctbytes, filename, linenumber, threadid)
00056         #define debugremovememhandle(h)
00057 
00058     #endif
00059 
00060 #endif
00061 
00062 static Handle hsafetycushion = nil; /*a buffer to allow memory error reporting*/
00063 
00064 static boolean flholdsafetycushion = false;
00065 
00066 
00067 static boolean getsafetycushion (void) {
00068     
00069     if (hsafetycushion == nil)
00070         hsafetycushion = NewHandle (safetycushionsize);
00071     
00072     return (hsafetycushion != nil);
00073     } /*getsafetycushion*/
00074 
00075 
00076 static boolean safetycushionhook (long *ctbytesneeded) {
00077     
00078     if (!flholdsafetycushion && (hsafetycushion != nil)) {
00079         
00080         *ctbytesneeded -= safetycushionsize;
00081         
00082         DisposeHandle (hsafetycushion);
00083         
00084         hsafetycushion = nil;
00085         }
00086     
00087     return (true); /*call remaining hooks*/
00088     } /*safetycushionhook*/
00089 
00090 
00091 #if (MEMTRACKER == 1)
00092     static Handle debuggetnewhandle (char * filename, unsigned long linenumber, unsigned long threadid, long ctbytes, boolean fltemp) {
00093         
00094         /*
00095         2.1b3 dmb: new fltemp parameter. if true, try temp memory first, then 
00096         our heap.
00097         */
00098         
00099         register Handle h;
00100         OSErr err;
00101         long extrasize;
00102 
00103         extrasize = strlen(filename) + 1 + sizeof(long) + sizeof(long) + sizeof(long) + (2 * (sizeof(Handle))) + 4;
00104 
00105         #ifdef MACVERSION
00106             #if TARGET_API_MAC_CARBON == 1
00107             // TRT - 13 Mar 2005 - 10.1a2
00108             // There is no temp memory in Carbon or OS X so make sure 
00109             // we never ask for it.
00110             fltemp = false;
00111             #endif
00112 
00113             if (fltemp) { /*try grabbing temp memory first*/
00114                 
00115                 h = TempNewHandle (ctbytes + extrasize, &err);
00116                 
00117                 if (h != nil) {
00118                     
00119                     debugaddmemhandle(h, ctbytes, filename, linenumber, threadid);
00120 
00121                     #ifdef fldebug
00122                     
00123                     // again we can't have any temp handles so this
00124                     // code isn't useful
00125                     #if TARGET_API_MAC_CARBON == 0
00126                     
00127                     ++cttemphandles;
00128                     
00129                     tempzone = HandleZone (h);
00130                     
00131                     #endif
00132                     
00133                     #endif
00134                     
00135                     return (h);
00136                     }
00137                 }
00138         #endif
00139         
00140         if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00141             
00142             if (!getsafetycushion ())
00143                 return (nil);
00144             }
00145         
00146         flholdsafetycushion = true;
00147         
00148         #ifdef MACVERSION
00149             h = NewHandle (ctbytes);
00150 
00151             if (h != nil)
00152                 debugaddmemhandle(h, ctbytes, filename, linenumber, threadid);
00153         #endif
00154         #ifdef WIN95VERSION
00155             h = debugfrontierAlloc (filename, linenumber, threadid, ctbytes);
00156         #endif
00157         
00158         flholdsafetycushion = false;
00159         
00160         return (h);
00161         } /*getnewhandle*/
00162 
00163 #else
00164 static Handle getnewhandle (long ctbytes, boolean fltemp) {
00165     
00166     /*
00167     2.1b3 dmb: new fltemp parameter. if true, try temp memory first, then 
00168     our heap.
00169     */
00170     
00171     register Handle h;
00172 
00173 #ifdef MACVERSION
00174 
00175     OSErr err;
00176     
00177     #if TARGET_API_MAC_CARBON == 1
00178     //Code change by Timothy Paustian Friday, June 9, 2000 9:39:50 PM
00179     //There is no temp memory in Carbon or OS X so make sure 
00180     //we never ask for it.
00181     fltemp = false;
00182     #endif
00183 
00184     if (fltemp) { /*try grabbing temp memory first*/
00185         h = TempNewHandle (ctbytes, &err);
00186 
00187         if (h != nil) {
00188             
00189             #ifdef fldebug
00190             
00191             //again we can't have any temp handles so this
00192             //code isn't useful
00193             #if TARGET_API_MAC_CARBON == 0
00194     
00195             ++cttemphandles;
00196             
00197             tempzone = HandleZone (h);
00198             #endif
00199             
00200             #endif
00201             
00202             return (h);
00203             }
00204         }
00205 #endif
00206     
00207     if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00208         
00209         if (!getsafetycushion ())
00210             return (nil);
00211         }
00212     
00213     flholdsafetycushion = true;
00214     
00215     h = NewHandle (ctbytes);
00216     
00217     flholdsafetycushion = false;
00218     
00219     return (h);
00220     } /*getnewhandle*/
00221 #endif
00222 
00223 
00224 static boolean resizehandle (Handle hresize, long size) {
00225     
00226     register Handle h = hresize;
00227     #ifdef WIN95VERSION
00228         Handle foo;
00229     #endif
00230 
00231     if (size > gethandlesize (h)) {
00232         
00233         if (hsafetycushion == nil) { /*don't allocate new stuff w/out safety cushion*/
00234             
00235             if (!getsafetycushion ())
00236                 return (false);
00237             }
00238         }
00239     
00240     flholdsafetycushion = true;
00241     
00242     #ifdef WIN95VERSION
00243         foo = SetHandleSize (h, size);
00244     #else
00245         SetHandleSize (h, size);
00246     #endif
00247 
00248     flholdsafetycushion = false;
00249     
00250     #ifdef WIN95VERSION
00251         return (foo != NULL);
00252     #else
00253         return (MemError () == noErr);
00254     #endif
00255     } /*resizehandle*/
00256 
00257 
00258 #if 0
00259 
00260 heapmess (void) {
00261     
00262     Handle ray [1000];
00263     short ixray = 0;
00264     Handle h;
00265     short i;
00266     
00267     while (true) {
00268         
00269         h = NewHandle (1024L);
00270         
00271         if (h == nil)
00272             break;
00273         
00274         ray [ixray++] = h;
00275         } /*while*/
00276     
00277     for (i = 0; i < ixray; i++)
00278         disposehandle (ray [i]);
00279     } /*heapmess*/
00280 
00281 
00282 boolean analyzeheap (void) {
00283     
00284     /*
00285     get some statistics about the heap.  doesn't work in 32-bit mode.
00286     */
00287     
00288     register byte *pblock;
00289     register long size;
00290     register byte *plimit;
00291     static long cthandles;
00292     static long ctbytes;
00293     static long avghandlesize;
00294     
00295     pblock = (byte *) &(*TheZone).heapData; /*point for first block in heap zone*/
00296     
00297     plimit = (byte *) (*TheZone).bkLim;
00298     
00299     cthandles = 0;
00300     
00301     ctbytes = 0; /*logical size of each handle*/
00302     
00303     while (pblock < plimit) {
00304         
00305         size = *(long *)pblock & 0x00ffffff;
00306         
00307         if (*pblock & 0x80) { /*a relocateable block*/
00308             
00309             ctbytes += size; /*add physical size*/
00310             
00311             //ctbytes -= 8 + (*pblock & 0x0f); /*subtract header & size correction*/
00312             
00313             ++cthandles;
00314             }
00315         
00316         pblock += size;
00317         }
00318     
00319     avghandlesize = ctbytes / cthandles;
00320     } /*analyzeheap*/
00321 
00322 #endif
00323 
00324 
00325 boolean haveheapspace (long size) {
00326     
00327     /*
00328     see if there's enough space in the heap to allocate a handle of the given size.
00329     
00330     if not, return false, but don't generate an error.
00331     */
00332     
00333     Handle h;
00334     
00335     #if (MEMTRACKER == 1)
00336         h = debuggetnewhandle (__FILE__, __LINE__, GetCurrentThreadId(), size, false);
00337     #else
00338         h = getnewhandle (size, false);
00339     #endif
00340     
00341     if (h == nil)
00342         return (false);
00343     
00344     DisposeHandle (h);
00345     
00346     return (true);
00347     } /*haveheapspace*/
00348 
00349 
00350 boolean testheapspace (long size) {
00351     
00352     /*
00353     see if there's enough space in the heap to allocate a handle of the given size.
00354     
00355     if not, generate an error, and return false.
00356     */
00357     
00358     if (haveheapspace (size))
00359         return (true);
00360     
00361     memoryerror ();
00362     
00363     return (false);
00364     } /*testheapspace*/
00365 
00366 
00367 void lockhandle (Handle h) {
00368     
00369     HLock (h);
00370     } /*lockhandle*/
00371 
00372 
00373 void unlockhandle (Handle h) {
00374     
00375     HUnlock (h);
00376     } /*unlockhandle*/
00377 
00378 
00379 boolean validhandle (Handle h) {
00380     
00381     if (h == nil)
00382         return (true);
00383     
00384 #ifdef MACVERSION
00385 
00386     if (GetHandleSize (h) < 0) /*negative length never valid*/
00387         return (false);
00388     
00389     return (MemError () == noErr);
00390 #endif
00391 
00392 #ifdef WIN95VERSION
00393     if (frontierSize (h) < 0)
00394         return (false);
00395 
00396     return (true);
00397 #endif
00398     } /*validhandle*/
00399 
00400 
00401 #if (MEMTRACKER == 1)
00402     boolean debugnewhandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *h) {
00403         
00404         *h = debuggetnewhandle (filename, linenumber, threadid, size, false);
00405         
00406         if (*h == nil) {
00407             
00408             memoryerror ();
00409             
00410             return (false);
00411             }
00412         
00413         return (true);
00414         } /*newhandle*/
00415 
00416 
00417     boolean debugnewemptyhandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle *h) {
00418         
00419         return (debugnewhandle (filename, linenumber, threadid, (long) 0, h));
00420         } /*newemptyhandle*/
00421 #else
00422 boolean newhandle (long size, Handle *h) {
00423     
00424     *h = getnewhandle (size, false);
00425     
00426     if (*h == nil) {
00427         
00428         memoryerror ();
00429         
00430         return (false);
00431         }
00432     
00433     return (true);
00434     } /*newhandle*/
00435 
00436 
00437 boolean newemptyhandle (Handle *h) {
00438     
00439     return (newhandle ((long) 0, h));
00440     } /*newemptyhandle*/
00441 #endif
00442 
00443 
00444 void disposehandle (Handle h) {
00445     
00446     if (h != nil) {
00447         
00448     #ifdef WIN95VERSION
00449         DisposeHandle (h);
00450     #endif
00451 
00452     #ifdef MACVERSION
00453         #if (MEMTRACKER == 1)
00454             debugremovememhandle(h);
00455         #endif
00456 
00457         #ifdef fldebug
00458         //Code change by Timothy Paustian Friday, June 9, 2000 9:43:15 PM
00459         //No temp memory in Carbon
00460         #if TARGET_API_MAC_CARBON == 0
00461         if (HandleZone (h) == tempzone)
00462             --cttemphandles;
00463         #endif
00464         #endif
00465         
00466         DisposeHandle (h);
00467         //Code change by Timothy Paustian Friday, May 19, 2000 1:18:56 PM
00468         //disposed of handles should always be set to nil
00469         h = nil;
00470         #ifdef fldebug
00471         
00472         if (MemError ())
00473              memoryerror ();
00474         
00475         #endif
00476     #endif      
00477         }
00478     } /*disposehandle*/
00479 
00480 
00481 long gethandlesize (Handle h) {
00482     
00483     if (h == nil)
00484         return (0L);
00485     
00486     return (GetHandleSize (h));
00487     } /*gethandlesize*/
00488 
00489 
00490 boolean sethandlesize (Handle h, long size) {
00491     
00492     if (h == nil) /*defensive driving*/
00493         return (false);
00494     
00495     if (!resizehandle (h, size)) {
00496         
00497         memoryerror ();
00498         
00499         return (false);
00500         }
00501     
00502     return (true);
00503     } /*sethandlesize*/
00504     
00505     
00506 boolean minhandlesize (Handle h, long size) {
00507     
00508     if (gethandlesize (h) >= size) /*already big enough*/
00509         return (true);
00510         
00511     return (sethandlesize (h, size)); /*try to make it larger*/
00512     } /*minhandlesize*/
00513 
00514 
00515 void moveleft (ptrvoid psource, ptrvoid pdest, long length) {
00516     
00517     /*
00518     do a mass memory move with the left edge leading.  good for closing
00519     up a gap in a buffer, among other things...
00520     
00521     2002-11-12 AR: It is dangerous to use CopyMemory on Windows here. The
00522     current Win32 SDK headers map this to RtlCopyMemory which in turn is
00523     mapped to memcpy. According to the ANSI-C standard, the memcpy function
00524     does not have to deal properly with situations where the source and
00525     destination regions overlap, as may very well be the case here.
00526     
00527     Apparently, this still worked all right with the implementation of
00528     memcpy from the Micrsoft C runtime library, but it did not with
00529     the Metrowerks Standard Library (MSL).
00530     
00531     Just calling memmove on all platforms looks to be the best solution
00532     both in terms of performance and future maintainability.
00533     */
00534     
00535     memmove (pdest, psource, length);
00536 
00537 /*
00538     assert (length >= 0);
00539 
00540 #if defined (MACVERSION)
00541     if (length > 0)
00542         BlockMoveData (psource, pdest, length);
00543     
00544 #elif defined (WIN95VERSION)
00545     if (length > 0)
00546         CopyMemory (pdest, psource, length);
00547     
00548 #else
00549     #pragma error "moveleft direction in mergehandlestreamdata matters!"
00550 
00551     register ptrbyte ps = psource, pd = pdest;
00552     register long ctloops = length;
00553     
00554     while (--ctloops >= 0)
00555         *pd++ = *ps++;
00556 #endif
00557 */
00558     } /*moveleft*/
00559 
00560 
00561 void moveright (ptrvoid psource, ptrvoid pdest, long length) {
00562     
00563     /*
00564     do a mass memory move with the right edge leading.  good for opening
00565     up a gap in a buffer, among other things...
00566     
00567     2002-11-12 AR: see note with same date in moveleft above
00568     */
00569     
00570     memmove (pdest, psource, length);
00571     
00572 /*
00573 #if defined (MACVERSION)
00574     if (length > 0)
00575         BlockMoveData (psource, pdest, length);
00576     
00577 #elif defined (WIN95VERSION)
00578     if (length > 0)
00579         CopyMemory (pdest, psource, length);
00580     
00581 #else
00582     #pragma error "moveright direction in mergehandlestreamdata matters!"
00583     register ptrbyte ps, pd;
00584     register long ctloops;
00585     
00586     ctloops = length;
00587     
00588     if (ctloops > 0) {
00589     
00590         ps = (ptrbyte) psource + length - 1; /%right edge of source%/
00591     
00592         pd = (ptrbyte) pdest + length - 1; /%right edge of destination%/
00593     
00594         while (ctloops--) 
00595             *pd-- = *ps--;
00596         }
00597 #endif
00598 */
00599     } /*moveright*/
00600     
00601 
00602 void clearbytes (ptrvoid pclear, long ctclear) {
00603     
00604     /*
00605     fill memory with 0's.
00606     */
00607     
00608     memset (pclear, 0, ctclear);
00609     } /*clearbytes*/
00610     
00611 
00612 void clearhandle (Handle hclear) {
00613     
00614     /*
00615     fill a handle's data with 0's.
00616     */
00617     
00618     register Handle h = hclear;
00619     register long size;
00620     
00621     size = gethandlesize (h);
00622     
00623     /*
00624     lockhandle (h);
00625     */
00626     
00627     memset (*h, 0, size);
00628     
00629     /*
00630     unlockhandle (h);
00631     */
00632     } /*clearhandle*/
00633     
00634 
00635 void movefromhandle (Handle h, ptrvoid pdest, long length) {
00636     
00637     if (h != nil) {
00638     
00639         /*
00640         HLock (h);
00641         */
00642     
00643         moveleft (*h, pdest, length);
00644     
00645         /*
00646         HUnlock (h);
00647         */
00648         }
00649     } /*movefromhandle*/
00650     
00651 
00652 #if (MEMTRACKER == 1)
00653     boolean debugnewclearhandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *hreturned) {
00654         
00655         register Handle h;
00656         register long ctbytes;
00657         
00658         ctbytes = size; /*copy into a register*/
00659         
00660         h = debuggetnewhandle (filename, linenumber, threadid, ctbytes, false);
00661         
00662         if (h == nil) {
00663             
00664             *hreturned = nil;
00665             
00666             memoryerror ();
00667             
00668             return (false);
00669             }
00670             
00671         clearhandle (h);
00672         
00673         *hreturned = h;
00674         
00675         return (true);
00676         } /*newclearhandle*/
00677         
00678 
00679     boolean debugnewfilledhandle (char * filename, unsigned long linenumber, unsigned long threadid, ptrvoid pdata, long size, Handle *hreturned) {
00680         
00681         register Handle h;
00682         register long ctbytes;
00683         
00684         ctbytes = size; 
00685         
00686         h = debuggetnewhandle (filename, linenumber, threadid, ctbytes, false);
00687         
00688         if (h == nil) {
00689             
00690             *hreturned = nil;
00691             
00692             memoryerror ();
00693             
00694             return (false);
00695             }
00696         
00697         moveleft (pdata, *h, ctbytes);
00698             
00699         *hreturned = h;
00700         
00701         return (true);
00702         } /*newfilledhandle*/
00703 #else   
00704 boolean newclearhandle (long size, Handle *hreturned) {
00705     
00706     register Handle h;
00707     register long ctbytes;
00708     
00709     ctbytes = size; /*copy into a register*/
00710     
00711     h = getnewhandle (ctbytes, false);
00712     
00713     if (h == nil) {
00714         
00715         *hreturned = nil;
00716         
00717         memoryerror ();
00718         
00719         return (false);
00720         }
00721         
00722     clearhandle (h);
00723     
00724     *hreturned = h;
00725     
00726     return (true);
00727     } /*newclearhandle*/
00728     
00729 
00730 boolean newfilledhandle (ptrvoid pdata, long size, Handle *hreturned) {
00731     
00732     register Handle h;
00733     register long ctbytes;
00734     
00735     ctbytes = size; 
00736     
00737     h = getnewhandle (ctbytes, false);
00738     
00739     if (h == nil) {
00740         
00741         *hreturned = nil;
00742         
00743         memoryerror ();
00744         
00745         return (false);
00746         }
00747     
00748     moveleft (pdata, *h, ctbytes);
00749         
00750     *hreturned = h;
00751     
00752     return (true);
00753     } /*newfilledhandle*/
00754 #endif
00755 
00756 #if (flruntime==0)
00757 #if (odbengine==0)
00758 static long getidealchunksize (void) {
00759     
00760     /*
00761     our caller wants to pre-allocate something large. as large as possible 
00762     without necessarily forcing a heap compaction.
00763     
00764     our algorith: find out what the largest possible size would be if the 
00765     heap was compated, then back off a bit, depending on what the number is. 
00766     often, there's one big free block and many small ones, so hopefully this 
00767     will yield a good result on average.
00768     
00769     4/20/93 dmb: tweaked algorith; if more than 64K is available, grab half
00770     */
00771 #ifdef MACVERSION       
00772     register long ctgrab = MaxBlock ();
00773     
00774     if (ctgrab < 0x4000)
00775         ctgrab -= 0x0400;
00776     else
00777         if (ctgrab < 0x10000)
00778             ctgrab -= 0x2000;
00779         else
00780             ctgrab >>= 1;
00781     
00782     return (ctgrab);
00783 #endif
00784 
00785 #ifdef WIN95VERSION
00786     return (32768L);
00787 #endif
00788 
00789     } /*getidealchunksize*/
00790 
00791 
00792 #if (MEMTRACKER == 1)
00793     boolean debugnewgrowinghandle (char * filename, unsigned long linenumber, unsigned long threadid, long size, Handle *h) {
00794         
00795         /*
00796         allocate a handle of the specified size, but with room to grow.
00797         
00798         note that the first getnewhandle should never fail, since the memory 
00799         manager just told us that an even large block could be produced. but 
00800         it's easy enough to handle that case too, so we do.
00801         */
00802         
00803         register long ctgrab = getidealchunksize ();
00804         
00805         if (ctgrab > size) {
00806             
00807             *h = debuggetnewhandle (filename, linenumber, threadid, ctgrab, false);
00808             
00809             if (*h != nil) {
00810                 
00811                 SetHandleSize (*h, size); /*can't fail, getting smaller*/
00812                 
00813                 return (true);
00814                 }
00815             }
00816         
00817         return (debugnewhandle (filename, linenumber, threadid, size, h));
00818         } /*newhandlewithroomtogrow*/
00819 #else
00820 boolean newgrowinghandle (long size, Handle *h) {
00821     
00822     /*
00823     allocate a handle of the specified size, but with room to grow.
00824     
00825     note that the first getnewhandle should never fail, since the memory 
00826     manager just told us that an even large block could be produced. but 
00827     it's easy enough to handle that case too, so we do.
00828     */
00829     
00830     register long ctgrab = getidealchunksize ();
00831     
00832     if (ctgrab > size) {
00833         
00834         *h = getnewhandle (ctgrab, false);
00835         
00836         if (*h != nil) {
00837             
00838             SetHandleSize (*h, size); /*can't fail, getting smaller*/
00839             
00840             return (true);
00841             }
00842         }
00843     
00844     return (newhandle (size, h));
00845     } /*newgrowinghandle*/
00846 #endif
00847 
00848 #endif
00849 #endif
00850 
00851 
00852 boolean prepareforgrowing (Handle h) {
00853 #pragma unused (h)
00854     
00855     /*
00856     like newgrowinghandle, but for an already-existing handle. the 
00857     caller is about to push a bunch of stuff onto it, and wants to 
00858     avoid having it continually compacting the heap along the way.
00859     */
00860     
00861     return (true); /*it turns out to be incredibly slow to resize an existing handle like this*/
00862     
00863     /*
00864     register long ctgrab = getidealchunksize ();
00865     register long ctorig = gethandlesize (h);
00866     
00867     if (h == nil) /%defensive driving%/
00868         return (false);
00869     
00870     ctgrab >>= 1; /%cut in half%/
00871     
00872     if (ctgrab > ctorig) {
00873         
00874         if (resizehandle (h, ctgrab)) {
00875             
00876             SetHandleSize (h, ctorig);
00877             
00878             return (true);
00879             }
00880         }
00881     
00882     return (false);
00883     */
00884     } /*prepareforgrowing*/
00885         
00886 
00887 #if (MEMTRACKER == 1)
00888 boolean debugcopyhandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle horig, Handle *hcopy) {
00889     
00890     register Handle h;
00891     register long ct;
00892     
00893     if (horig == nil) /*easy to copy a nil handle*/
00894         h = nil;
00895     
00896     else {
00897         
00898         ct = gethandlesize (horig);
00899         
00900         h = debuggetnewhandle (filename, linenumber, threadid, ct, false);
00901         
00902         if (h == nil) {
00903             
00904             memoryerror ();
00905             
00906             return (false);
00907             }
00908         
00909         moveleft (*horig, *h, ct);
00910         }
00911     
00912     *hcopy = h;
00913     
00914     return (true);
00915     } /*copyhandle*/
00916 #else
00917 boolean copyhandle (Handle horig, Handle *hcopy) {
00918     
00919     register Handle h;
00920     register long ct;
00921     
00922     if (horig == nil) /*easy to copy a nil handle*/
00923         h = nil;
00924     
00925     else {
00926         
00927         ct = gethandlesize (horig);
00928         
00929         h = getnewhandle (ct, false);
00930         
00931         if (h == nil) {
00932             
00933             memoryerror ();
00934             
00935             return (false);
00936             }
00937         
00938         moveleft (*horig, *h, ct);
00939         }
00940     
00941     *hcopy = h;
00942     
00943     return (true);
00944     } /*copyhandle*/
00945 #endif
00946 
00947 
00948 short comparehandles (Handle h1, Handle h2) { //, boolean flunicase) {
00949     
00950     /*
00951     return -1 if h1 is less than h2, or +1 if h1 is greater than h2.
00952     
00953     return zero if the two byte streams are equal.
00954     
00955     9/21/92 dmb: make sure we don't dereference nil handles.
00956     */
00957     
00958     long len1, len2;
00959     register long ct;
00960     
00961     len1 = gethandlesize (h1);
00962     
00963     len2 = gethandlesize (h2);
00964     
00965     ct = min (len1, len2);
00966     
00967     if (ct > 0) { /*both handles are non-nil; safe to dereference*/
00968         
00969         register ptrbyte p1 = (ptrbyte) *h1;
00970         register ptrbyte p2 = (ptrbyte) *h2;
00971         
00972         for (; --ct >= 0; ++p1, ++p2)
00973         
00974         //  if (flunicase? toupper (*p1) != toupper (*p2) : *p1 != *p2) { /*unequal chars*/
00975         
00976             if (*p1 != *p2) { /*unequal chars*/
00977                 
00978                 register char n = (char) (*p1 - *p2); /*change into signed value*/
00979                 
00980                 return (sgn (n));
00981                 }
00982         }
00983     
00984     return (sgn (len1 - len2));
00985     } /*comparehandles*/
00986 
00987 
00988 boolean equalhandles (Handle h1, Handle h2) {
00989     
00990     /*
00991     we could check for equal handle sizes first, we don't expect this 
00992     to be a time-critical routine
00993     */
00994     
00995     return (comparehandles (h1, h2) == 0);
00996     } /*equalhandles*/
00997 
00998 
00999 long searchhandle (Handle hsearch, Handle hpattern, long ixstart, long ixlimit) {
01000     
01001     /*
01002     the beginning of something bigger.  first version -- search for the 
01003     pattern in the byte stream, return the offset of the first occurrence of
01004     the pattern.  -1 if not found.
01005     
01006     8/12/92 dmb: make sure ixstart is in range
01007     
01008     8/14/92 dmb: added ixlimit parameter
01009     
01010     2004-11-13 aradke: accept nil handles for hsearch and hpattern as valid input.
01011     this fixes a crashing bug when accessing an empty result received from filemaker
01012     via apple events. [thanks to Karsten Wolf for the bug report and investigation]
01013     */
01014     
01015     register ptrbyte psearch;
01016     register ptrbyte ppattern;
01017     register long ixstring;
01018     register long i;
01019     register long lensearch;
01020     register long lenpattern;
01021     register byte chfirst;
01022     
01023     if ((hsearch == nil) || (hpattern == nil))
01024         return (-1L);
01025 
01026     lensearch = gethandlesize (hsearch);
01027     
01028     lenpattern = gethandlesize (hpattern);
01029     
01030     lensearch = min (ixlimit, lensearch) - lenpattern + 1;
01031     
01032     ixstring = ixstart;
01033     
01034     if ((lensearch <= 0) || (lenpattern == 0) || (ixstring >= lensearch))
01035         return (-1L);
01036 
01037     psearch = (ptrbyte) *hsearch;
01038     
01039     ppattern = (ptrbyte) *hpattern;
01040 
01041     chfirst = ppattern [0];
01042     
01043     while (true) {
01044         
01045         if (psearch [ixstring] == chfirst) { /*matched at least first character in string*/
01046             
01047             for (i = 1; i < lenpattern; ++i) {
01048                 
01049                 if (psearch [ixstring + i] != ppattern [i]) 
01050                     goto L1;
01051                 } /*for*/
01052             
01053             return (ixstring); /*loop terminated, full match*/
01054             }
01055         
01056         L1: /*advance to next character in string*/
01057         
01058         if (++ixstring == lensearch) /*reached end of string, not found*/
01059             return (-1L);
01060         } /*while*/
01061     } /*searchhandle*/
01062 
01063 
01064 long searchhandleunicase (Handle hsearch, Handle hpattern, long ixstart, long ixlimit) {
01065     
01066     /*
01067     the beginning of something bigger.  first version -- search for the 
01068     pattern in the byte stream, return the offset of the first occurrence of
01069     the pattern.  -1 if not found.
01070     
01071     8/12/92 dmb: make sure ixstart is in range
01072     
01073     8/14/92 dmb: added ixlimit parameter
01074     
01075     2004-11-13 aradke: accept nil handles for hsearch and hpattern as valid input.
01076     this fixes a crashing bug when accessing an empty result received from filemaker
01077     via apple events. [thanks to Karsten Wolf for the bug report and investigation]
01078     */
01079     
01080     register ptrbyte psearch;
01081     register ptrbyte ppattern;
01082     register long ixstring;
01083     register long i;
01084     register long lensearch;
01085     register long lenpattern;
01086     register byte chfirst;
01087     
01088     if ((hsearch == nil) || (hpattern == nil))
01089         return (-1L);
01090 
01091     lensearch = gethandlesize (hsearch);
01092     
01093     lenpattern = gethandlesize (hpattern);
01094 
01095     lensearch = min (ixlimit, lensearch) - lenpattern + 1;
01096     
01097     ixstring = ixstart;
01098     
01099     if ((lensearch <= 0) || (lenpattern == 0) || (ixstring >= lensearch))
01100         return (-1L);
01101     
01102     psearch = (ptrbyte) *hsearch;
01103     
01104     ppattern = (ptrbyte) *hpattern;
01105 
01106     chfirst = getlower (ppattern [0]);
01107 
01108     while (true) {
01109         
01110         if (getlower (psearch [ixstring]) == chfirst) { /*matched at least first character in string*/
01111             
01112             for (i = 1; i < lenpattern; ++i) {
01113                 
01114                 if (getlower (psearch [ixstring + i]) != tolower(ppattern [i])) 
01115                     goto L1;
01116                 } /*for*/
01117             
01118             return (ixstring); /*loop terminated, full match*/
01119             }
01120         
01121         L1: /*advance to next character in string*/
01122         
01123         if (++ixstring == lensearch) /*reached end of string, not found*/
01124             return (-1L);
01125         } /*while*/
01126     } /*searchhandleunicase*/
01127 
01128 
01129 boolean sethandlecontents (ptrvoid pdata, long ctset, Handle hset) {
01130     
01131     if (!sethandlesize (hset, ctset))
01132         return (false);
01133     
01134     moveleft (pdata, *hset, ctset);
01135     
01136     return (true);
01137     } /*sethandlecontents*/
01138 
01139 
01140 void texttostring (ptrvoid ptext, long ctchars, bigstring bs) {
01141     
01142     register long len = ctchars;
01143     
01144     if (len > lenbigstring)
01145         len = lenbigstring;
01146     
01147     setstringlength (bs, len);
01148     
01149     moveleft (ptext, &bs [1], len);
01150     } /*texttostring*/
01151 
01152 
01153 void texthandletostring (Handle htext, bigstring bs) {
01154     
01155     /*
01156     5.1.2 dmb: handle nil htext
01157     */
01158 
01159     if (htext == nil)
01160         setemptystring (bs);
01161     else
01162         texttostring (*htext, gethandlesize (htext), bs);
01163     } /*texthandletostring*/
01164 
01165 
01166 #if (MEMTRACKER == 1)
01167 boolean debugnewtexthandle (char * filename, unsigned long linenumber, unsigned long threadid, const bigstring bs, Handle *htext) {
01168     
01169     /*
01170     create a new handle to hold the text of the string.
01171     
01172     if the string is "\pABC" -- you get a handle of size 3.
01173     */
01174     
01175     register long len = stringlength (bs);
01176     register Handle h;
01177     
01178     h = debuggetnewhandle (filename, linenumber, threadid, len, false);
01179     
01180     if (h == nil) {
01181         
01182         memoryerror ();
01183         
01184         return (false);
01185         }
01186     
01187     if (len > 0)
01188         moveleft ((ptrstring) stringbaseaddress (bs), *h, len);
01189     
01190     *htext = h; /*pass handle back to caller*/
01191     
01192     return (true);
01193     } /*newtexthandle*/
01194 #else
01195 boolean newtexthandle (const bigstring bs, Handle *htext) {
01196     
01197     /*
01198     create a new handle to hold the text of the string.
01199     
01200     if the string is "\pABC" -- you get a handle of size 3.
01201     */
01202     
01203     register long len = stringlength (bs);
01204     register Handle h;
01205     
01206     h = getnewhandle (len, false);
01207     
01208     if (h == nil) {
01209         
01210         memoryerror ();
01211         
01212         return (false);
01213         }
01214     
01215     if (len > 0)
01216         moveleft ((ptrstring) stringbaseaddress (bs), *h, len);
01217     
01218     *htext = h; /*pass handle back to caller*/
01219     
01220     return (true);
01221     } /*newtexthandle*/
01222 #endif
01223 
01224 
01225 boolean insertinhandle (Handle hgrow, long ix, ptrvoid pdata, long ctgrow) {
01226     
01227     /*
01228     make the handle big enough to hold the new data, and insert the new 
01229     data into the newly enlarged handle.
01230     
01231     8.1.97 dmb: if pdata is nil, initialize new data to zeros
01232     */
01233     
01234     unsigned long origsize;
01235     
01236     if (ctgrow == 0)
01237         return (true);
01238     
01239     origsize = gethandlesize (hgrow);
01240     
01241     if (!sethandlesize (hgrow, origsize + ctgrow))
01242         return (false);
01243     
01244     if (ix < (long) origsize)
01245         moveright (*hgrow + ix, *hgrow + ix + ctgrow, origsize - ix);
01246     
01247     if (pdata == nil)
01248         clearbytes (*hgrow + ix, ctgrow);
01249     else
01250         moveleft (pdata, *hgrow + ix, ctgrow);
01251     
01252     return (true);
01253     } /*insertinhandle*/
01254 
01255 
01256 boolean inserttextinhandle (Handle hgrow, long ix, bigstring bs) {
01257     
01258     return (insertinhandle (hgrow, ix, stringbaseaddress (bs), stringlength (bs)));
01259     } /*inserttextinhandle*/
01260 
01261 
01262 boolean inserthandleinhandle (Handle hinsert, Handle h, unsigned long ix) {
01263     
01264     unsigned long insertlen = gethandlesize (hinsert);
01265     unsigned long ct = gethandlesize (h);
01266     unsigned long newlen = ct + insertlen;
01267     
01268     if (hinsert == nil) /*nothing to do*/
01269         return (true);
01270         
01271     if (!sethandlesize (h, newlen))
01272         return (false);
01273     
01274     moveright (&(*h) [ix], &(*h) [ix + insertlen], ct - ix);
01275     
01276     moveleft (*hinsert, &(*h) [ix], insertlen);
01277     
01278     return (true);
01279     } /*inserthandleinhandle*/
01280     
01281     
01282 boolean pullfromhandle (Handle h, long ix, long ct, ptrvoid pdata) {
01283     
01284     /*
01285     8/14/91 dmb: accept nil for pdata to remove bytes without retaining them
01286     */
01287     
01288     register long newsize;
01289     
01290     if (ct <= 0)
01291         return (true);
01292     
01293     newsize = gethandlesize (h) - ct;
01294     
01295     if ((ix < 0) || (ix > newsize))
01296         return (false);
01297     
01298     if (pdata != nil)
01299         moveleft (*h + ix, pdata, ct); /*copy out of the handle*/
01300     
01301     moveleft (*h + ix + ct, *h + ix, newsize - ix);
01302     
01303     return (sethandlesize (h, newsize)); /*should never fail -- getting smaller*/
01304     } /*pullfromhandle*/
01305 
01306 
01307 boolean enlargehandle (Handle hgrow, long ctgrow, ptrvoid newdata) {
01308     
01309     /*
01310     make the handle big enough to hold the new data, and move the new data in
01311     at the end of the newly enlarged handle.
01312     
01313     8.1.97 dmb: if newdata is nil, initialize new data to zeros
01314     */
01315     
01316     return (insertinhandle (hgrow, gethandlesize (hgrow), newdata, ctgrow));
01317     
01318     /*
01319     register Handle h = hgrow;
01320     register long ct = ctgrow;
01321     register ptrbyte p = newdata;
01322     register long origsize;
01323     
01324     if (hgrow == nil)
01325         Debugger ();
01326     
01327     if (ct == 0)
01328         return (true);
01329     
01330     origsize = gethandlesize (h);
01331     
01332     if (!sethandlesize (h, origsize + ct))
01333         return (false);
01334     
01335     moveleft (p, *h + origsize, ct);
01336     
01337     return (true);
01338     */
01339     
01340     } /*enlargehandle*/
01341 
01342 
01343 boolean mungehandle (Handle hmunge, long ixmunge, long ctmunge, ptrvoid pinsert, long ctinsert) {
01344     
01345     /*
01346     modeled after the Mac Toolbox utility "Munger", minus the search 
01347     capability, plus some error handling...
01348     
01349     overwrite ctmunge bytes in the handle hmunge, starting at offset ixmunge, 
01350     with the bytes indicated by pinsert, ctinsert.  resize the handle as 
01351     required, shifting any bytes to the right
01352     */
01353     
01354     register long sizediff = ctinsert - ctmunge;
01355     register byte *pdata = pinsert;
01356     
01357     switch (sgn (sizediff)) { /*insert or delete unmatched bytes*/
01358         
01359         case +1: /*growing*/
01360             if (!insertinhandle (hmunge, ixmunge + ctmunge, pdata + ctmunge, sizediff))
01361                 return (false);
01362             
01363             break;
01364         
01365         case -1: /*shrinking*/
01366             pullfromhandle (hmunge, ixmunge + ctinsert, -sizediff, nil);
01367             
01368             break;
01369         
01370         default: /*no change*/
01371             break;
01372         }
01373     
01374     moveleft (pdata, *hmunge + ixmunge, min (ctinsert, ctmunge));
01375     
01376     return (true);
01377     } /*mungehandle*/
01378 
01379 
01380 boolean pushcharhandle (char ch, Handle htext) {
01381 
01382     /*
01383     2006-03-10 aradke: grow handle by one and push char onto end
01384     */
01385 
01386     unsigned long size;
01387     
01388     size = gethandlesize (htext);
01389     
01390     if (!sethandlesize (htext, size + 1))
01391         return (false);
01392     
01393     (*htext)[size] = ch;
01394 
01395     return (true);
01396     } /*pushcharhandle*/
01397 
01398 
01399 boolean pushstringhandle (const bigstring bs, Handle htext) {
01400     
01401     /*
01402     htext is a handle created with newtexthandle.
01403     
01404     increase the size of the handle so we can push the pascal string bs 
01405     at the end of the handle (including length byte).
01406     */
01407     
01408     return (enlargehandle (htext, (long) stringsize (bs), (ptrvoid) bs));
01409     } /*pushstringhandle*/
01410 
01411 
01412 boolean pushtexthandle (const bigstring bs, Handle htext) {
01413     
01414     /*
01415     htext is a handle created with newtexthandle.
01416     
01417     increase the size of the handle so we can push the text of bs at 
01418     the end of the handle (not including length byte).
01419     */
01420     
01421     return (enlargehandle (htext, (long) stringlength (bs), (ptrvoid) stringbaseaddress (bs)));
01422     } /*pushtexthandle*/
01423 
01424 
01425 #if 0
01426 
01427 boolean pushindentedline (short level, bigstring bs, Handle htext) {
01428     
01429     /*
01430     add a line to the indicated text buffer, indented with tab characters and
01431     terminated with a carriage return.
01432     
01433     return false if it failed, we dispose of htext if it failed.
01434     */
01435     
01436     bigstring bsoutput;
01437     
01438     filledstring (chtab, level, bsoutput); /*put out leading tabs*/
01439     
01440     pushstring (bs, bsoutput); /*put out the string itself*/
01441     
01442     pushchar (chreturn, bsoutput); /*put out a terminating carriage return character*/
01443     
01444     if (!pushtexthandle (bsoutput, htext)) { /*out of memory*/
01445     
01446         disposehandle (htext);
01447         
01448         return (false);
01449         }
01450     
01451     return (true);
01452     } /*pushindentedline*/
01453 
01454 #endif
01455        
01456 
01457 #if (MEMTRACKER == 1)
01458 boolean debugnewheapstring (char * filename, unsigned long linenumber, unsigned long threadid, const bigstring bs, hdlstring *hstring) {
01459     
01460     /*
01461     3/28/97 dmb: rewrote x-plat; don't use NewString toolbox
01462     */
01463 
01464     return (debugnewfilledhandle (filename, linenumber, threadid, (void *) bs, stringsize (bs), (Handle *)hstring));
01465     } /*newheapstring*/
01466 #else
01467 boolean newheapstring (const bigstring bs, hdlstring *hstring) {
01468     
01469     /*
01470     3/28/97 dmb: rewrote x-plat; don't use NewString toolbox
01471     */
01472 
01473     return (newfilledhandle ((void *) bs, stringsize (bs), (Handle *)hstring));
01474     } /*newheapstring*/
01475 #endif
01476 
01477 
01478 boolean setheapstring (const bigstring bs, hdlstring hstring) {
01479     
01480     return (sethandlecontents ((ptrvoid) bs, stringlength (bs) + 1, (Handle) hstring));
01481     } /*setheapstring*/
01482 
01483 
01484 /*
01485 boolean concatheapstrings (hdlstring *h1, hdlstring *h2, hdlstring *hreturned) {
01486 
01487     /%
01488     given two heap strings, return a heap string that's the result of 
01489     concatenating the two strings.
01490     
01491     return false if the resulting string would be too long, or if there
01492     was a memory allocation error.
01493     %/
01494     
01495     bigstring bs1, bs2;
01496     bigstring bs;
01497     register long len1, len2;
01498     register long len;
01499     register hdlstring hstring;
01500     
01501     copyheapstring (*h1, bs1);
01502     
01503     copyheapstring (*h2, bs2);
01504     
01505     len1 = stringlength(bs1);
01506     
01507     len2 = stringlength(bs2);
01508     
01509     len = len1 + len2;
01510     
01511     if (len > lenbigstring)
01512         return (false);
01513         
01514     setstringlength(bs, len);
01515     
01516     moveleft (&bs1 [1], &bs [1], len1);
01517     
01518     moveleft (&bs2 [1], &bs [1 + len1], len2);
01519         
01520     return (newheapstring (bs, hreturned));
01521     } /%concatheapstrings%/
01522 */
01523 
01524 
01525 boolean pushhandle (Handle hsource, Handle hdest) {
01526     
01527     /*
01528     add the content of the source handle at the end of the destination handle.
01529     
01530     5.0.2b10 dmb: don't lock source handle during dest resize; don't
01531     use enlargehandle
01532     */
01533     
01534     unsigned long ctsource, ctdest;
01535     
01536     if (hsource == nil)
01537         return (true);
01538     
01539     ctsource = gethandlesize (hsource);
01540     
01541     ctdest = gethandlesize (hdest);
01542     
01543     if (!sethandlesize (hdest, ctsource + ctdest))
01544         return (false);
01545     
01546     moveleft (*hsource, *hdest + ctdest, ctsource);
01547     
01548     return (true);
01549     } /*pushhandle*/
01550     
01551 
01552 boolean loadfromhandle (Handle hload, long *ixload, long ctload, ptrvoid pdata) {
01553     
01554     /*
01555     copy the next ctload bytes from hload into pdata and increment the index.
01556     
01557     return false if there aren't enough bytes.
01558     
01559     start ixload at 0.
01560     */
01561     
01562     register Handle h = hload;
01563     register ptrbyte p = pdata;
01564     register long ct = ctload;
01565     register long ix = *ixload;
01566     register long size;
01567     
01568     size = gethandlesize (h);
01569     
01570     if (ix < 0) /*bad index*/
01571         return (false);
01572     
01573     if ((ix + ct) > size) /*asked for more bytes than there are*/
01574         return (false); 
01575         
01576     moveleft (*h + ix, p, ct); /*copy out of the handle*/
01577     
01578     *ixload = ix + ct; /*increment the index into the handle*/
01579     
01580     return (true);
01581     } /*loadfromhandle*/
01582 
01583 
01584 #if (MEMTRACKER == 1)
01585 boolean debugloadfromhandletohandle (char * filename, unsigned long linenumber, unsigned long threadid, Handle hload, long *ixload, long ctload, boolean fltemp, Handle *hnew) {
01586     
01587     /*
01588     load from the source handle, creating a new handle to hold the loaded stuff.
01589     
01590     6/8/91 dmb: fixed memory leak if loadfromhandle fails
01591     
01592     11/27/91 dmb: reject ctload < 0
01593     
01594     2.1b3 dmb: added fltemp parameter to determine whether caller is going 
01595     to dispose the result soon.
01596     */
01597     
01598     Handle h;
01599     
01600     if (ctload < 0)
01601         return (false);
01602     
01603     h = debuggetnewhandle (filename, linenumber, threadid, ctload, fltemp);
01604     
01605     if (h == nil) {
01606         
01607         memoryerror ();
01608         
01609         return (false);
01610         }
01611     
01612     if (!loadfromhandle (hload, ixload, ctload, *h)) {
01613         
01614         disposehandle (h);
01615         
01616         return (false);
01617         }
01618     
01619     *hnew = h;
01620     
01621     return (true);
01622     } /*loadfromhandletohandle*/
01623 
01624 
01625 boolean debugloadhandleremains (char * filename, unsigned long linenumber, unsigned long threadid, long ix, Handle hsource, Handle *hdest) {
01626 
01627     /*
01628     load all the bytes following ix from the source handle into the dest handle.
01629     
01630     2.1b3 dmb: callers of this routine are (almost) always fine with 
01631     temporary memory, so let's use it.
01632     */
01633     
01634     return (debugloadfromhandletohandle (filename, linenumber, threadid, hsource, &ix, gethandlesize (hsource) - ix, true, hdest));
01635     } /*loadhandleremains*/
01636 #else
01637 boolean loadfromhandletohandle (Handle hload, long *ixload, long ctload, boolean fltemp, Handle *hnew) {
01638     
01639     /*
01640     load from the source handle, creating a new handle to hold the loaded stuff.
01641     
01642     6/8/91 dmb: fixed memory leak if loadfromhandle fails
01643     
01644     11/27/91 dmb: reject ctload < 0
01645     
01646     2.1b3 dmb: added fltemp parameter to determine whether caller is going 
01647     to dispose the result soon.
01648     */
01649     
01650     Handle h;
01651     
01652     if (ctload < 0)
01653         return (false);
01654     
01655     h = getnewhandle (ctload, fltemp);
01656     
01657     if (h == nil) {
01658         
01659         memoryerror ();
01660         
01661         return (false);
01662         }
01663     
01664     if (!loadfromhandle (hload, ixload, ctload, *h)) {
01665         
01666         disposehandle (h);
01667         
01668         return (false);
01669         }
01670     
01671     *hnew = h;
01672     
01673     return (true);
01674     } /*loadfromhandletohandle*/
01675 
01676 
01677 boolean loadhandleremains (long ix, Handle hsource, Handle *hdest) {
01678 
01679     /*
01680     load all the bytes following ix from the source handle into the dest handle.
01681     
01682     2.1b3 dmb: callers of this routine are (almost) always fine with 
01683     temporary memory, so let's use it.
01684     */
01685     
01686     return (loadfromhandletohandle (hsource, &ix, gethandlesize (hsource) - ix, true, hdest));
01687     } /*loadhandleremains*/
01688 #endif
01689 
01690     
01691 boolean pushlongondiskhandle (long x, Handle hpush) {
01692     
01693     memtodisklong (x);
01694     
01695     return (enlargehandle (hpush, sizeof (long), &x));
01696     } /*pushlongtodiskhandle*/
01697 
01698 
01699 boolean loadlongfromdiskhandle (Handle hload, long *ixload, long *x) {
01700     
01701     if (!loadfromhandle (hload, ixload, sizeof (long), x))
01702         return (false);
01703     
01704     disktomemlong (*x);
01705     
01706     return (true);
01707     } /*loadlongfromdiskhandle*/
01708 
01709 
01710 boolean popfromhandle (Handle hpop, long ctpop, ptrvoid pdata) {
01711     
01712     register Handle h = hpop;
01713     register long ixpop = gethandlesize (h) - ctpop;
01714     
01715     if (ixpop < 0)
01716         return (false);
01717     
01718     if (pdata != nil)
01719         moveleft (*h + ixpop, pdata, ctpop); /*copy out of the handle*/
01720     
01721     return (sethandlesize (h, ixpop)); /*should never fail -- getting smaller*/
01722     } /*popfromhandle*/
01723 
01724 
01725 boolean copyhandlecontents (Handle hsource, Handle hdest) {
01726     
01727     /*
01728     copy the contents of hsource into hdest's space.  if hdest isn't large
01729     enough to receive hsource's content, we enlarge hdest.  if this fails 
01730     we return false.
01731     
01732     7/5/91 dmb: we now implement a more strict copy; the destination handle 
01733     is always sized to match the original.
01734     */
01735     
01736     register long ctsource;
01737     
01738     ctsource = gethandlesize (hsource);
01739     
01740     if (!sethandlesize (hdest, ctsource)) /*heap allocation failed*/
01741         return (false);
01742     
01743     moveleft (*hsource, *hdest, ctsource);
01744     
01745     return (true);
01746     } /*copyhandlecontents*/
01747     
01748 
01749 #if (MEMTRACKER == 1)
01750 boolean debugconcathandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle h1, Handle h2, Handle *hmerged) {
01751     
01752     /*
01753     create a new handle which is the concatenation of two handles.
01754     */
01755     
01756     register Handle h;
01757     long sizefirsthandle;
01758     long sizesecondhandle;
01759     register ptrbyte p;
01760     
01761     *hmerged = nil; /*default return value*/
01762     
01763     sizefirsthandle = gethandlesize (h1);
01764     
01765     sizesecondhandle = gethandlesize (h2);
01766     
01767     h = debuggetnewhandle (filename, linenumber, threadid, sizefirsthandle + sizesecondhandle, false);
01768     
01769     if (h == nil) {
01770         
01771         memoryerror ();
01772         
01773         return (false);
01774         }
01775     
01776     p = (ptrbyte) *h;
01777         
01778     moveleft (*h1, p, sizefirsthandle);
01779     
01780     p += sizefirsthandle;
01781     
01782     moveleft (*h2, p, sizesecondhandle);
01783     
01784     *hmerged = h;
01785     
01786     return (true);
01787     } /*concathandles*/
01788     
01789     
01790 boolean debugmergehandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle h1, Handle h2, Handle *hmerged) {
01791     
01792     /*
01793     create a new handle which is the concatenation of two handles.  the first
01794     four bytes of the new handle store the size of the first handle so the merged
01795     handle can be easily unpacked.
01796     
01797     6/8/90 DW: modified so it could deal with nil handles.
01798     
01799     10/7/91 dmb: try to merge result into the larger of the original handles, so 
01800     that our memory overhead can be almost cut in half.
01801     
01802     2.1b3 dmb: in the unusual case the we allocated a new handle, go ahead 
01803     and use temporary memory if available. this might not always be ideal, but 
01804     more often than not it will be best -- we're likely Saving, and tossing 
01805     the merged handle soon.
01806     */
01807     
01808     register Handle h;
01809     long sizefirsthandle;
01810     long sizesecondhandle;
01811     long sizemergedhandle;
01812     long storesizefirsthandle;
01813     register ptrbyte p;
01814     
01815     *hmerged = nil; /*default return value*/
01816     
01817     sizefirsthandle = gethandlesize (h1);
01818     storesizefirsthandle = disklong (sizefirsthandle);
01819     
01820     sizesecondhandle = gethandlesize (h2);
01821     
01822     sizemergedhandle = sizeof (long) + sizefirsthandle + sizesecondhandle;
01823     
01824     if (sizefirsthandle > sizesecondhandle) { /*try using h1 for result*/
01825         
01826         if (resizehandle (h1, sizemergedhandle)) {
01827             
01828             p = (ptrbyte) *h1;
01829             
01830             moveright (p, p + sizeof (long), sizefirsthandle);
01831             
01832             moveleft (&storesizefirsthandle, p, sizeof (long));
01833             
01834             if (h2 != nil)
01835                 moveleft (*h2, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01836             
01837             *hmerged = h1;
01838             
01839             disposehandle (h2);
01840             
01841             return (true);
01842             }
01843         }
01844     
01845     else if (h2 != nil) { /*try using h2 for result*/
01846         
01847         if (resizehandle (h2, sizemergedhandle)) {
01848             
01849             p = (ptrbyte) *h2;
01850             
01851             moveright (p, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
01852             
01853             moveleft (&storesizefirsthandle, p, sizeof (long));
01854             
01855             if (h1 != nil)
01856                 moveleft (*h1, p + sizeof (long), sizefirsthandle);
01857             
01858             *hmerged = h2;
01859             
01860             disposehandle (h1);
01861             
01862             return (true);
01863             }
01864         }
01865     
01866     /*resizing didn't work; try it the old way, using a newly-allocated handle*/
01867     
01868     h = debuggetnewhandle (filename, linenumber, threadid, sizemergedhandle, true);
01869     
01870     if (h == nil) {
01871         
01872         memoryerror ();
01873         
01874         disposehandle (h1);
01875         
01876         disposehandle (h2);
01877         
01878         return (false);
01879         }
01880     
01881     p = (ptrbyte) *h;
01882     
01883     moveleft (&storesizefirsthandle, p, sizeof (long));
01884     
01885     p += sizeof (long);
01886     
01887     if (h1 != nil)
01888         moveleft (*h1, p, sizefirsthandle);
01889     
01890     if (h2 != nil)
01891         moveleft (*h2, p + sizefirsthandle, sizesecondhandle);
01892     
01893     *hmerged = h;
01894     
01895     disposehandle (h1);
01896     
01897     disposehandle (h2);
01898     
01899     return (true);
01900     } /*mergehandles*/
01901 
01902 
01903 boolean debugunmergehandles (char * filename, unsigned long linenumber, unsigned long threadid, Handle hmerged, Handle *hfirst, Handle *hsecond) {
01904     
01905     /*
01906     split up a handle created by mergehandle.
01907     
01908     3/12/91 dmb: rewrote so that we own hmerged; caller no longer diposes it.  
01909     this allows us to reuse the handle to greatly reduce memory requirements.  
01910     we could further optimize by reusing hmerged for the larger handle instead 
01911     of always hsecond.
01912     
01913     also, avoid locking handles when we're trying to allocate potentially 
01914     large chunks of memory.
01915     
01916     2.1b3 dmb: newly-created handle is always ok as temporary memory
01917     */
01918     
01919     register Handle h1 = nil, h2 = nil;
01920     register Handle h = hmerged;
01921     long ix;
01922     long sizefirsthandle, sizesecondhandle;
01923     
01924     *hfirst = *hsecond = nil; /*default return values*/
01925     
01926     moveleft (*h, &sizefirsthandle, sizeof (long));
01927 
01928     disktomemlong (sizefirsthandle);
01929     
01930     ix = sizeof (long);
01931     
01932     if (sizefirsthandle == 0)
01933         h1 = nil;
01934         
01935     else {
01936         h1 = debuggetnewhandle (filename, linenumber, threadid, sizefirsthandle, true);
01937         
01938         if (h1 == nil) 
01939             goto error;
01940         
01941         moveleft (*h + ix, *h1, sizefirsthandle);
01942         }
01943     
01944     ix += sizefirsthandle;
01945     
01946     sizesecondhandle = gethandlesize (h) - sizefirsthandle - sizeof (long);
01947     
01948     if (sizesecondhandle == 0) {
01949         
01950         h2 = nil;
01951         
01952         disposehandle (h);
01953         }
01954     else {
01955         
01956         h2 = h; /*second handle can safely re-use merged handle*/
01957         
01958         moveleft (*h2 + ix, *h2, sizesecondhandle);
01959         
01960         sethandlesize (h2, sizesecondhandle);
01961         }
01962     
01963     *hfirst = h1; /*return handles to caller*/
01964     
01965     *hsecond = h2;
01966     
01967     return (true);
01968         
01969     error:
01970     
01971     disposehandle (h);
01972     
01973     disposehandle (h1);
01974         
01975     disposehandle (h2);
01976     
01977     memoryerror ();
01978     
01979     return (false);
01980     } /*debugunmergehandles*/
01981     
01982     
01983 boolean debugnewintarray (char * filename, unsigned long linenumber, unsigned long threadid, short ct, hdlintarray *harray) {
01984     
01985     Handle h;
01986     
01987     if (!debugnewclearhandle (filename, linenumber, threadid, sizeof (short) * ct, &h))
01988         return (false);
01989         
01990     *harray = (hdlintarray) h;
01991     
01992     return (true);
01993     } /*newintarray*/
01994 #else   
01995 boolean concathandles (Handle h1, Handle h2, Handle *hmerged) {
01996     
01997     /*
01998     create a new handle which is the concatenation of two handles.
01999     */
02000     
02001     register Handle h;
02002     long sizefirsthandle;
02003     long sizesecondhandle;
02004     register ptrbyte p;
02005     
02006     *hmerged = nil; /*default return value*/
02007     
02008     sizefirsthandle = gethandlesize (h1);
02009     
02010     sizesecondhandle = gethandlesize (h2);
02011     
02012     h = getnewhandle (sizefirsthandle + sizesecondhandle, false);
02013     
02014     if (h == nil) {
02015         
02016         memoryerror ();
02017         
02018         return (false);
02019         }
02020     
02021     p = (ptrbyte) *h;
02022         
02023     moveleft (*h1, p, sizefirsthandle);
02024     
02025     p += sizefirsthandle;
02026     
02027     moveleft (*h2, p, sizesecondhandle);
02028     
02029     *hmerged = h;
02030     
02031     return (true);
02032     } /*concathandles*/
02033     
02034     
02035 boolean mergehandles (Handle h1, Handle h2, Handle *hmerged) {
02036     
02037     /*
02038     create a new handle which is the concatenation of two handles.  the first
02039     four bytes of the new handle store the size of the first handle so the merged
02040     handle can be easily unpacked.
02041     
02042     6/8/90 DW: modified so it could deal with nil handles.
02043     
02044     10/7/91 dmb: try to merge result into the larger of the original handles, so 
02045     that our memory overhead can be almost cut in half.
02046     
02047     2.1b3 dmb: in the unusual case the we allocated a new handle, go ahead 
02048     and use temporary memory if available. this might not always be ideal, but 
02049     more often than not it will be best -- we're likely Saving, and tossing 
02050     the merged handle soon.
02051     */
02052     
02053     register Handle h;
02054     long sizefirsthandle;
02055     long sizesecondhandle;
02056     long sizemergedhandle;
02057     long storesizefirsthandle;
02058     register ptrbyte p;
02059     
02060     *hmerged = nil; /*default return value*/
02061     
02062     sizefirsthandle = gethandlesize (h1);
02063     storesizefirsthandle = disklong (sizefirsthandle);
02064     
02065     sizesecondhandle = gethandlesize (h2);
02066     
02067     sizemergedhandle = sizeof (long) + sizefirsthandle + sizesecondhandle;
02068     
02069     if (sizefirsthandle > sizesecondhandle) { /*try using h1 for result*/
02070         
02071         if (resizehandle (h1, sizemergedhandle)) {
02072             
02073             p = (ptrbyte) *h1;
02074             
02075             moveright (p, p + sizeof (long), sizefirsthandle);
02076             
02077             moveleft (&storesizefirsthandle, p, sizeof (long));
02078             
02079             if (h2 != nil)
02080                 moveleft (*h2, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
02081             
02082             *hmerged = h1;
02083             
02084             disposehandle (h2);
02085             
02086             return (true);
02087             }
02088         }
02089     
02090     else if (h2 != nil) { /*try using h2 for result*/
02091         
02092         if (resizehandle (h2, sizemergedhandle)) {
02093             
02094             p = (ptrbyte) *h2;
02095             
02096             moveright (p, p + sizeof (long) + sizefirsthandle, sizesecondhandle);
02097             
02098             moveleft (&storesizefirsthandle, p, sizeof (long));
02099             
02100             if (h1 != nil)
02101                 moveleft (*h1, p + sizeof (long), sizefirsthandle);
02102             
02103             *hmerged = h2;
02104             
02105             disposehandle (h1);
02106             
02107             return (true);
02108             }
02109         }
02110     
02111     /*resizing didn't work; try it the old way, using a newly-allocated handle*/
02112     
02113     h = getnewhandle (sizemergedhandle, true);
02114     
02115     if (h == nil) {
02116         
02117         memoryerror ();
02118         
02119         disposehandle (h1);
02120         
02121         disposehandle (h2);
02122         
02123         return (false);
02124         }
02125     
02126     p = (ptrbyte) *h;
02127     
02128     moveleft (&storesizefirsthandle, p, sizeof (long));
02129     
02130     p += sizeof (long);
02131     
02132     if (h1 != nil)
02133         moveleft (*h1, p, sizefirsthandle);
02134     
02135     if (h2 != nil)
02136         moveleft (*h2, p + sizefirsthandle, sizesecondhandle);
02137     
02138     *hmerged = h;
02139     
02140     disposehandle (h1);
02141     
02142     disposehandle (h2);
02143     
02144     return (true);
02145     } /*mergehandles*/
02146 
02147 
02148 boolean unmergehandles (Handle hmerged, Handle *hfirst, Handle *hsecond) {
02149     
02150     /*
02151     split up a handle created by mergehandle.
02152     
02153     3/12/91 dmb: rewrote so that we own hmerged; caller no longer diposes it.  
02154     this allows us to reuse the handle to greatly reduce memory requirements.  
02155     we could further optimize by reusing hmerged for the larger handle instead 
02156     of always hsecond.
02157     
02158     also, avoid locking handles when we're trying to allocate potentially 
02159     large chunks of memory.
02160     
02161     2.1b3 dmb: newly-created handle is always ok as temporary memory
02162     */
02163     
02164     register Handle h1 = nil, h2 = nil;
02165     register Handle h = hmerged;
02166     long ix;
02167     long sizefirsthandle, sizesecondhandle;
02168     
02169     *hfirst = *hsecond = nil; /*default return values*/
02170     
02171     moveleft (*h, &sizefirsthandle, sizeof (long));
02172 
02173     disktomemlong (sizefirsthandle);
02174     
02175     ix = sizeof (long);
02176     
02177     if (sizefirsthandle == 0)
02178         h1 = nil;
02179         
02180     else {
02181         h1 = getnewhandle (sizefirsthandle, true);
02182         
02183         if (h1 == nil) 
02184             goto error;
02185         
02186         moveleft (*h + ix, *h1, sizefirsthandle);
02187         }
02188     
02189     ix += sizefirsthandle;
02190     
02191     sizesecondhandle = gethandlesize (h) - sizefirsthandle - sizeof (long);
02192     
02193     if (sizesecondhandle == 0) {
02194         
02195         h2 = nil;
02196         
02197         disposehandle (h);
02198         }
02199     else {
02200         
02201         h2 = h; /*second handle can safely re-use merged handle*/
02202         
02203         moveleft (*h2 + ix, *h2, sizesecondhandle);
02204         
02205         sethandlesize (h2, sizesecondhandle);
02206         }
02207     
02208     *hfirst = h1; /*return handles to caller*/
02209     
02210     *hsecond = h2;
02211     
02212     return (true);
02213         
02214     error:
02215     
02216     disposehandle (h);
02217     
02218     disposehandle (h1);
02219         
02220     disposehandle (h2);
02221     
02222     memoryerror ();
02223     
02224     return (false);
02225     } /*unmergehandles*/
02226     
02227     
02228 boolean newintarray (short ct, hdlintarray *harray) {
02229     
02230     Handle h;
02231     
02232     if (!newclearhandle (sizeof (short) * ct, &h))
02233         return (false);
02234         
02235     *harray = (hdlintarray) h;
02236     
02237     return (true);
02238     } /*newintarray*/
02239 #endif
02240 
02241     
02242 
02243 boolean setintarray (hdlintarray harray, short ix, short val) {
02244     
02245     /*
02246     assign into a cell in a variable-size array of integers, 0-based index.
02247     
02248     return false if the array needed to be extended but there isn't enough
02249     memory to do it.
02250     */
02251     
02252     register hdlintarray h = harray;
02253 
02254     if (!minhandlesize ((Handle) h, (ix + 1) * sizeof (short)))
02255         return (false);
02256     
02257     (*harray) [ix] = val;
02258     
02259     return (true);
02260     } /*setintarray*/
02261     
02262     
02263 boolean getintarray (hdlintarray harray, short ix, short *val) {
02264     
02265     *val = (*harray) [ix];
02266     
02267     return (true);
02268     } /*getintarray*/
02269     
02270     
02271 void fillintarray (hdlintarray harray, short val) {
02272     
02273     register hdlintarray h = harray;
02274     register short ct;
02275     /*
02276     register short i;
02277     */
02278     
02279     ct = (short) gethandlesize ((Handle) h) / sizeof (short);
02280 
02281     while (--ct >= 0)
02282         (*h) [ct] = val;
02283 
02284     /*
02285     lockhandle ((Handle) h);
02286     
02287     for (i = 0; i < ct; i++)
02288         (*h) [i] = x;
02289 
02290     unlockhandle ((Handle) h);
02291     */
02292 
02293     } /*fillintarray*/
02294 
02295 
02296 void openhandlestream (Handle h, handlestream *s) {
02297     
02298     (*s).data = h;
02299     (*s).pos = 0;
02300     (*s).eof = (*s).size = gethandlesize (h);
02301     } /*openhandlestream*/
02302 
02303 
02304 boolean growhandlestream (handlestream *s, long ct) {
02305     
02306     /*
02307     make the stream large enough to accomodate ct bytes of data
02308 
02309     6.1d1 AR: Fixed a bug: (*s).sizeneeded was not set correctly
02310     for newly created handles.
02311     */
02312     
02313     #define blocksize 1024
02314     long sizeneeded = quantumize (ct, blocksize);
02315     
02316     if ((*s).data == nil) {
02317         
02318         if (!newhandle (sizeneeded, &(*s).data))
02319             return (false);
02320         
02321         (*s).size = sizeneeded;
02322         }
02323     else {
02324         if ((*s).size < sizeneeded) {
02325             
02326             if (!sethandlesize ((*s).data, sizeneeded))
02327                 return (false);
02328             
02329             (*s).size = sizeneeded;
02330             }
02331         }
02332     
02333     return (true);
02334     } /*growhandlestream*/
02335 
02336 
02337 boolean writehandlestream (handlestream *s, void *p, long ct) {
02338     
02339     if (!growhandlestream (s, (*s).pos + ct))
02340         return (false);
02341     
02342     moveleft (p, *(*s).data + (*s).pos, ct);
02343     
02344     (*s).pos += ct;
02345     
02346     (*s).eof = max ((*s).eof, (*s).pos);
02347     
02348     return (true);
02349     } /*writehandlestream*/
02350 
02351 
02352 boolean writehandlestreamlong (handlestream *s, long x) {
02353 
02354     bigstring bs;
02355 
02356     numbertostring (x, bs);
02357     
02358     return (writehandlestream (s, stringbaseaddress (bs), stringlength (bs)));
02359     } /*writehandlestreamstring*/
02360 
02361 boolean writehandlestreamchar (handlestream *s, byte ch) {
02362     
02363     return (writehandlestream (s, &ch, sizeof (ch)));
02364     } /*writehandlestreamchar*/
02365 
02366 
02367 boolean writehandlestreamstring (handlestream *s, bigstring bs) {
02368     
02369     return (writehandlestream (s, stringbaseaddress (bs), stringlength (bs)));
02370     } /*writehandlestreamstring*/
02371 
02372 
02373 boolean writehandlestreamhandle (handlestream *s, Handle h) {
02374     
02375     long ct = gethandlesize (h);
02376     
02377     if (ct == 0)
02378         return (true);
02379     
02380     if (!growhandlestream (s, (*s).pos + ct)) // grow first, so we don't have to lock handle
02381         return (false);
02382     
02383     return (writehandlestream (s, *h, ct));
02384     } /*writehandlestreamhandle*/
02385 
02386 
02387 boolean writehandlestreamhandlepart (handlestream *s, Handle h, long ix, long len) {
02388     
02389     long ct = gethandlesize (h);
02390     
02391     if (len <= 0 || ix < 0 || ix >= ct)
02392         return (true);
02393     
02394     if (ix + len > ct)
02395         len = ct - ix;
02396     
02397     if (!growhandlestream (s, (*s).pos + len)) // grow first, so we don't have to lock handle
02398         return (false);
02399     
02400     return (writehandlestream (s, &((*h)[ix]), len));
02401     } /*writehandlestreamhandlepart*/
02402 
02403 
02404 boolean writehandlestreamhandleindent (handlestream *s, Handle h, long i) {
02405 
02406     while (i > 0) { /*indent*/
02407 
02408         if (!writehandlestreamchar (s, '\t'))
02409             return (false);
02410         
02411         i--;
02412         } /*while*/
02413 
02414     if (!writehandlestreamhandle (s, h))
02415         return (false);
02416 
02417     return (writehandlestreamchar (s, '\r'));
02418     } /*writehandlestreamhandleindent*/
02419 
02420 
02421 boolean writehandlestreamstringindent (handlestream *s, bigstring bs, long i) {
02422 
02423     while (i > 0) { /*indent*/
02424 
02425         if (!writehandlestreamchar (s, '\t'))
02426             return (false);
02427         
02428         i--;
02429         } /*while*/
02430 
02431     if (!writehandlestreamstring (s, bs))
02432         return (false);
02433 
02434     return (writehandlestreamchar (s, '\r'));
02435     }/*writehandlestreamstringindent*/
02436 
02437 
02438 boolean mergehandlestreamdata (handlestream *s, long ctreplace, ptrvoid pdata, long ctmerge) {
02439     
02440     /*
02441     "munge" the stream data.
02442     
02443     unlike the write calls, we preserve data following the current position.
02444     we push out the eof accordingly.
02445     */
02446     
02447     long ctgrow = ctmerge - ctreplace;
02448     char *p;
02449     
02450     if (!growhandlestream (s, (*s).eof + ctgrow))
02451         return (false);
02452     
02453     p = *(*s).data + (*s).pos;
02454     
02455     // these directions will be wrong is ctmerge < ctreplace, but they're the same
02456     moveright (p + ctreplace, p + ctmerge, (*s).eof - (*s).pos - ctreplace);
02457     
02458     moveleft (pdata, p, ctmerge);
02459     
02460     (*s).pos += ctmerge;
02461     
02462     (*s).eof += ctgrow;
02463     
02464     return (true);
02465     } /*mergehandlestreamdata*/
02466 
02467 
02468 boolean mergehandlestreamhandle (handlestream *s, long ctreplace, Handle hmerge) {
02469     
02470     /*
02471     "munge" the stream data, cosuming h.
02472     
02473     unlike the write calls, we preserve data following the current position.
02474     we push out the eof accordingly.
02475     */
02476     
02477     long ctmerge = gethandlesize (hmerge);
02478     long ctgrow = ctmerge - ctreplace;
02479     
02480     if (!growhandlestream (s, (*s).eof + ctgrow)) { // grow first, so we don't have to lock handle
02481         
02482         disposehandle (hmerge);
02483         
02484         return (false);
02485         }
02486     
02487     mergehandlestreamdata (s, ctreplace, *hmerge, ctmerge);
02488 
02489     disposehandle (hmerge);
02490     
02491     return (true);
02492     } /*mergehandlestreamhandle*/
02493 
02494 
02495 boolean mergehandlestreamstring (handlestream *s, long ctreplace, bigstring bsmerge) {
02496     
02497     return (mergehandlestreamdata (s, ctreplace, stringbaseaddress (bsmerge), stringlength (bsmerge)));
02498     } /*mergehandlestreamstring*/
02499 
02500 
02501 boolean readhandlestream (handlestream *s, void *p, long ct) {
02502     
02503     if (ct > (*s).eof - (*s).pos)
02504         return (false);
02505     
02506     moveleft (*(*s).data + (*s).pos, p, ct);
02507     
02508     (*s).pos += ct;
02509     
02510     return (true);
02511     } /*readhandlestream*/
02512 
02513 
02514 boolean pullfromhandlestream (handlestream *s, long ctpull, void *pdata) {
02515 
02516     /*
02517     pull bytes out of the stream, shrinking the data. if a pointer is 
02518     provided, copy the data to it.
02519     */
02520     
02521     char *p;
02522     
02523     p = *(*s).data + (*s).pos;
02524     
02525     if (pdata != nil)
02526         moveleft (p, pdata, ctpull);
02527     
02528     moveleft (p + ctpull, p, (*s).eof - (*s).pos - ctpull);
02529     
02530     (*s).eof -= ctpull;
02531     
02532     return (true);
02533     } /*pullfromhandlestream*/
02534 
02535 
02536 long skiphandlestreamchars (handlestream *s, byte chskip) {
02537     
02538     /*
02539     return the number of characters skipped
02540     */
02541     
02542     char *p = *(*s).data;
02543     long ctskipped = 0;
02544     
02545     while ((*s).pos < (*s).eof) {
02546         
02547         if (p [(*s).pos] != chskip)
02548             break;
02549         
02550         ++ctskipped;
02551         
02552         ++(*s).pos;
02553         }
02554     
02555     return (ctskipped);
02556     } /*skiphandlestreamchars*/
02557 
02558 
02559 boolean skiphandlestreamwhitespace (handlestream *s) {
02560     
02561     char *p = *(*s).data;
02562     
02563     while (isspace (p [(*s).pos])) {
02564         
02565         if (++(*s).pos >= (*s).eof)
02566             return (false);
02567         }
02568     
02569     return (true);
02570     } /*skiphandlestreamwhitespace*/
02571 
02572 
02573 long seekhandlestreamchar (handlestream *s, byte chseek)  {
02574     
02575     /*
02576     return the number of characters skipped
02577     */
02578     
02579     char *p = *(*s).data;
02580     long ctskipped = 0;
02581     
02582     while ((*s).pos < (*s).eof) {
02583         
02584         if (p [(*s).pos] == chseek)
02585             break;
02586         
02587         ++ctskipped;
02588         
02589         ++(*s).pos;
02590         }
02591     
02592     return (ctskipped);
02593     } /*skiphandlestreamchars*/
02594 
02595 
02596 boolean readhandlestreamfieldtohandle (handlestream *s, byte chdelimiter, Handle *hreturned) {
02597     
02598     long startpos = (*s).pos;
02599     char *p = *(*s).data;
02600     boolean fl;
02601     
02602     while (p [(*s).pos] != chdelimiter) {
02603         
02604         if (++(*s).pos >= (*s).eof)
02605             break;
02606         }
02607     
02608     fl = loadfromhandletohandle ((*s).data, &startpos, (*s).pos - startpos, false, hreturned);
02609     
02610     ++(*s).pos; //skip delimiter
02611     
02612     return (fl);
02613     } /*readhandlestreamfieldtohandle*/
02614 
02615 
02616 boolean readhandlestreamfield (handlestream *s, byte chdelimiter, bigstring bsfield) {
02617     
02618     long startpos = (*s).pos;
02619     char *p = *(*s).data;
02620     
02621     while (p [(*s).pos] != chdelimiter) {
02622         
02623         if (++(*s).pos >= (*s).eof)
02624             break;
02625         }
02626     
02627     texttostring (p + startpos, (*s).pos - startpos, bsfield);
02628     
02629     ++(*s).pos; //skip delimiter
02630     
02631     return (!isemptystring (bsfield));
02632     } /*readhandlestreamfield*/
02633 
02634 
02635 byte gethandlestreamcharacter (handlestream *s, long pos) {
02636     
02637     return ((*(*s).data) [pos]);
02638     } /*gethandlestreamcharacter*/
02639 
02640 
02641 byte nexthandlestreamcharacter (handlestream *s) {
02642     
02643     return (gethandlestreamcharacter (s, (*s).pos));
02644     } /*nexthandlestreamcharacter*/
02645 
02646 
02647 byte lasthandlestreamcharacter (handlestream *s) {
02648     
02649     return (gethandlestreamcharacter (s, (*s).eof - 1));
02650     } /*lasthandlestreamcharacter*/
02651 
02652 
02653 boolean athandlestreameof (handlestream *s) {
02654     
02655     return ((*s).pos >= (*s).eof);
02656     } /*athandlestreameof*/
02657 
02658 
02659 Handle closehandlestream (handlestream *s) {
02660     
02661     sethandlesize ((*s).data, (*s).eof);
02662     
02663     (*s).size = (*s).eof;
02664     
02665     return ((*s).data);
02666     } /*closehandlestream*/
02667 
02668 
02669 void disposehandlestream (handlestream *s) {
02670     
02671     disposehandle ((*s).data);
02672     
02673     clearbytes (s, sizeof (*s));
02674     } /*disposehandlestream*/
02675 
02676 
02677 
02678 #if (flruntime==0)
02679 #if (odbengine==0)
02680 boolean initmemory (void) {
02681     
02682 #if (MEMTRACKER == 1)
02683     // TRT - 13 Mar 2005 - 10.1a2
02684     // Initialize memory debugging structures
02685 #endif
02686 
02687     shellpushmemoryhook (&safetycushionhook);
02688     
02689     return (getsafetycushion ());
02690     } /*initmemory*/
02691 #endif
02692 #endif
02693 
02694 
02695 
02696 
02697 
02698 
02699 

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