Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!jarthur!sburke From: sburke@jarthur.Claremont.EDU (Scott Burke) Newsgroups: comp.sys.handhelds Subject: CLEARing stack Keywords: CLEAR Message-ID: <10535@jarthur.Claremont.EDU> Date: 29 Jan 91 03:47:27 GMT Organization: Harvey Mudd College, Claremont, CA Lines: 85 Here are some more thoughts on stack clearing. As a commerical software developer for the HP-48SX, I can attest that of all the issues involved in a major piece of software, by far the trickiest is the error handling. Tortuous programming algorithms pale in comparison to being "polite" and not changing the state of the calculator, _whatever_ the user happens to do. In general, storing the stack in a list and a global or local variable is bad for several reasons: 1. There may be a large object on the stack, and if you want your code to run in low memory conditions, it is a _really_ bad idea to stick those 1K GROBs (to pick an example) in a list and try to store it. 2. Using a global variable during programming should only be done when parameters must be stored _between_ executions of the code--just like HP does with 'PTpar' to store Periodic Table parameters. Otherwise, using global variables is never necessary, unless using a built-in RPL command that requires them (like ROOT), or unless providing stack access during a program, where you would like to give the user access to their data. Obviously, globals must be used for data files. However, (here is the long-winded point of this paragraph), creating and deleting global variables is _slow_ _slow_ _slow_!! Much better to use locals. One other advantage is that even if the user manages to escape your code at an unpredicted place, there aren't a whole bunch of temporary globals sitting in their directory. Name conflicts are also irrelevant if locals are used. 3. The _real_ reason it's a bad idea to store the stack away is that during input of data (say, with the INPUT statement), the user has _no_ access to their current stack. What if the user wants to do a bunch of cal- culations on the stack and then insert those calculated values into a data field in a program? This functionality is supported in the EDIT menu with the ^STK key, which provides crippled access to the inter- active stack of the 48SX. But if you've dumped all the stack into a local variable, the user can't do that. _Bad_! Also, if your code supports copying values to the stack, the list-based scheme would have to append new values to the stored list. Finally, if the user breaks out of the code unexpectedly, their stack is gone. So how do you get around these problems? In an earlier message, Eric (edp) hit on the solution I have found to work acceptably: to use a stack depth counter and then upon exiting the program, restore the correct depth of the stack. This simply changes the headache, however, because now the code has to be absolutely sure what the user has done to the stack in the program (by this, I mean how many values have they _added_ to the stack, since there is no way to delete objects on the stack without stack access). Tracking a stack depth is a simple matter in theory--just do an initial DEPTH and then increment the local variable each time the stack size is increased with a ->STK press (or whatever). Whoever complained about not being able to comprehend how it would be possible to not know the stack depth merely needs to imagine this scenario: The code has exploded two lists onto the stack and is doing a meta-object filter pass (i.e., simply looping from 1 to the size of one of the lists), performing some sort of concatenation operation (or whatever) each time through the list. If the user breaks out of the code, who knows how many iterations have been per- formed, and therefore how much of the original lists remain, or how many new entries have been created? I have written code with hundreds of items on the stack, because stack operations take noticeably less time than dealing with lists or variables. If the user hits the ATTN key in the middle of a loop or a sort operation, then it is not possible to know how much has happened so far. All this is well and good, but tracking a stack depth pointer or storing the stack in a list will both fail if the user is allowed to break out of the code unpredictably. Only a few of the routines posted to the net make very much attempt to trap ATTN presses, but this is crucial for commercial software (such as HP's card). In user language, the only way to do this is to layer the code with IFERR loops, placing the restoration code after all the error traps. In internal RPL code, there are ways to turn off the ATTN vector, but I stick to user language because of the limited document- ation available. I toss SYSEVALs in to speed up crucial loops and GROB operations, but by and large there are too many dangers associated with some of the internal routines, unless you have access to _all_ of them. This means that while HP can write code that is truly impervious to user abuse, we on the outside are doomed to crashed code after sufficiently many ATTN presses. The solution is just to trap a certain number (say 5 or 10) and let the user beware if they are determined to be malicious. Scott. sburke@jarthur.claremont.edu