langtmpstack.c

Go to the documentation of this file.
00001 
00002 /*  $Id: langtmpstack.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 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "lang.h" 
00033 #include "langinternal.h"
00034 #include "langexternal.h"
00035 
00036 
00037 
00038 
00039 #define ctgrowtmpstack 5 /*amount to grow tmpstack by when full*/
00040 
00041 
00042 
00043 void cleartmpstack (void) {
00044 
00045     /*
00046     the tmpstack hold all the temporary handles that have been allocated 
00047     since the last time the tmpstack was cleared.
00048     
00049     these are values that are produced in evaluating an expression. the 
00050     evaluator has no way of knowing whether they will be needed so they 
00051     can't be released, yet.
00052     
00053     this is the price you pay for a language that allows everything to
00054     return a value, and where values can be heap-allocated objects like
00055     strings.
00056     
00057     call this routine when you are advancing to the next statement and
00058     know that you will not be using any of the temporaries in the stack.
00059     
00060     1/8/91 dmb: check currenthashtable for nil
00061     */
00062     
00063     register short ctloops;
00064     register tyvaluerecord *p;
00065     
00066     if (currenthashtable == nil)
00067         return;
00068     
00069     lockhandle ((Handle) currenthashtable); 
00070     
00071     p = (**currenthashtable).tmpstack;
00072     
00073     for (ctloops = (**currenthashtable).cttmpstack; ctloops--; ++p) { /*step through tmpstack*/
00074         
00075         if ((*p).valuetype != novaluetype) {
00076             
00077             (*p).fltmpstack = false;
00078             
00079             disposevaluerecord (*p, false);
00080             
00081             initvalue (p, novaluetype);
00082             }
00083         } /*for*/
00084         
00085     unlockhandle ((Handle) currenthashtable);
00086     } /*cleartmpstack*/
00087 
00088 
00089 boolean pushtmpstackvalue (tyvaluerecord *vpush) {
00090     
00091     /*
00092     1/14/91 dmb: check currenthashtable for nil.  this might happen when 
00093     setstringvalue or copyvaluerecord is called outside of language 
00094     execution.  in these situations, the caller should be managing the memory.
00095     */
00096     
00097     register short ctloops;
00098     register tyvaluerecord *p;
00099     
00100     if ((*vpush).data.binaryvalue == nil) /*nothing to push*/
00101         return (true);
00102     
00103     if (currenthashtable == nil) /*not an error, but caller must handle disposal*/
00104         return (true);
00105     
00106     assert (validhandle ((*vpush).data.stringvalue));
00107     
00108     p = (**currenthashtable).tmpstack;
00109     
00110     for (ctloops = (**currenthashtable).cttmpstack; ctloops--; ++p) { /*step through tmpstack*/
00111     
00112         if ((*p).valuetype == novaluetype) { /*found an empty slot in tmpstack*/
00113             
00114             (*vpush).fltmpstack = true;
00115             
00116             *p = *vpush;
00117             
00118             return (true);
00119             }
00120         } /*for*/
00121     
00122     // langerror (tmpstackoverflowerror); /*loop terminated, no room in tmpstack*/
00123     
00124     if (!enlargehandle ((Handle) currenthashtable, ctgrowtmpstack * sizeof (tyvaluerecord), nil))
00125         return (false);
00126     
00127     (*vpush).fltmpstack = true;
00128     
00129     (**currenthashtable).tmpstack [(**currenthashtable).cttmpstack] = *vpush;
00130     
00131     (**currenthashtable).cttmpstack += ctgrowtmpstack;
00132     
00133     return (true);
00134     } /*pushtmpstackvalue*/
00135 
00136 
00137 boolean pushtmpstack (Handle h) {
00138     
00139     tyvaluerecord val;
00140     
00141     if (h == nil) /*nothing to push*/
00142         return (true);
00143     
00144     assert (validhandle (h));
00145     
00146     if (currenthashtable == nil) /*not an error, but caller must handle disposal*/
00147         return (true);
00148     
00149     initvalue (&val, stringvaluetype);
00150     
00151     val.data.binaryvalue = h;
00152     
00153     return (pushtmpstackvalue (&val));
00154     } /*pushtmpstack*/
00155 
00156 
00157 static boolean removeheaptmp (Handle h) {
00158     
00159     /*
00160     remove the handle from the tmpstack.  this keeps it from getting
00161     released when we call cleartmpstack.
00162     
00163     1/8/91 dmb: check currenthashtable for nil
00164     
00165     1/16/91 dmb: return boolean
00166     
00167     3/23/93 dmb: exported
00168     */
00169     
00170     register short ctloops;
00171     register tyvaluerecord *p;
00172     
00173     if (currenthashtable == nil)
00174         return (false);
00175     
00176     p = (**currenthashtable).tmpstack;
00177     
00178     for (ctloops = (**currenthashtable).cttmpstack; ctloops--; ++p) { /*step through tmpstack*/
00179         
00180         if ((*p).data.binaryvalue == h) { /*found the temp in the stack*/
00181             
00182             initvalue (p, novaluetype); /*nil the entry so it can be re-used*/
00183             
00184             return (true);
00185             }
00186         } /*while*/
00187     
00188     return (false); /*didn't find it*/
00189     } /*removeheaptmp*/
00190 
00191 
00192 void releaseheaptmp (Handle h) {
00193     
00194     /*
00195     we're releasing a heap-allocated temporary value.  we make sure that its
00196     entry in the tmpstack is nilled so it doesn't get released when the 
00197     tmpstack is cleared.
00198     */
00199     
00200     if (h != nil) {
00201         
00202         removeheaptmp (h);
00203         
00204         disposehandle (h); 
00205         //Code change by Timothy Paustian Friday, May 19, 2000 1:06:24 PM
00206         //This handle is not nilled out, just disposed of. Maybe put a nil ref in here.
00207         //There are some stale handle references as noticed by spotlight.
00208         //see if this will get us a better clue on where the problem is.
00209         }
00210     } /*releaseheaptmp*/
00211 
00212 
00213 boolean pushvalueontmpstack (tyvaluerecord *val) {
00214 
00215     /*
00216     6.1d9 AR: Allow pushing of external types, too.
00217     */
00218     
00219     Handle h;
00220     
00221     if (!langheapallocated (val, &h)) /*nothing to push, not heap allocated*/
00222         return (true); 
00223     
00224     if ((*val).valuetype == codevaluetype)
00225         return (false);
00226 /*
00227     if ((*val).valuetype == externalvaluetype)
00228         return (false);
00229 */  
00230     return (pushtmpstackvalue (val));
00231     } /*pushvalueontmpstack*/
00232 
00233 
00234 boolean exemptfromtmpstack (tyvaluerecord *val) {
00235     
00236     /*
00237     the caller is asserting that the value must be removed from the tmpstack.
00238     
00239     when you're moving a temporary into a symbol table, if we were to automatically 
00240     release it, the value would disappear.
00241     
00242     1/16/91 dmb: return boolean so caller can tell if it was in the temp stack
00243     */
00244     
00245     Handle h;
00246     
00247     if (!langheapallocated (val, &h)) 
00248         return (false);
00249     
00250     if ((*val).fltmpstack) {
00251         
00252         if (removeheaptmp (h)) {
00253             
00254             (*val).fltmpstack = false;
00255             
00256             return (true);
00257             }
00258         }
00259     
00260     return (false);
00261     } /*exemptfromtmpstack*/
00262     
00263 
00264 boolean disposetmpvalue (tyvaluerecord *val) {
00265     
00266     /*
00267     val is a value that normally would have been pushed onto the tempstack, 
00268     but wasn't because it was the returned value at the highest level of 
00269     evaluatelist.
00270     
00271     if it's indeed a value that normally would be a temp, delete it.
00272 
00273     6.1d9 AR: Dispose of external types, too.
00274     */
00275     
00276     Handle h;
00277     
00278     if (!langheapallocated (val, &h)) /*nothing to delete, not heap allocated*/
00279         return (true);
00280     
00281     if ((*val).valuetype == codevaluetype)
00282         return (false);
00283 /*  
00284     if ((*val).valuetype == externalvaluetype)
00285         return (false);
00286 */
00287     assert (!(*val).fltmpstack);
00288     
00289     disposevaluerecord (*val, false);
00290     
00291     return (true);
00292     } /*disposetmpvalue*/
00293 
00294 

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