User Tools

Site Tools


forcing_20a_20variable_20to_20exist

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

forcing_20a_20variable_20to_20exist [2018/03/31 13:19]
127.0.0.1 external edit
forcing_20a_20variable_20to_20exist [2018/04/17 16:18] (current)
tbest3112 Added syntax highlighting
Line 2: Line 2:
  
 //by Richard Russell, May 2006//\\ \\  Programs frequently need to contain a //cleanup// routine which gets called before the program quits. Such a routine may close files, remove open dialogue boxes, free Windows resources that have been allocated (e.g. memory or graphics objects) etc. So the routine will typically include code similar to the following:​\\ \\  //by Richard Russell, May 2006//\\ \\  Programs frequently need to contain a //cleanup// routine which gets called before the program quits. Such a routine may close files, remove open dialogue boxes, free Windows resources that have been allocated (e.g. memory or graphics objects) etc. So the routine will typically include code similar to the following:​\\ \\ 
 +<code bb4w>
         DEF PROCcleanup         DEF PROCcleanup
         CLOSE #Outfile%         CLOSE #Outfile%
Line 7: Line 8:
         SYS "​GlobalFree",​ Memory%         SYS "​GlobalFree",​ Memory%
         ENDPROC         ENDPROC
 +</​code>​
 The cleanup code will need to be executed not only on the normal exit from the program but also if a premature exit takes place because of an error (including Escape) or the user clicking on the **Close** button. Therefore it is likely that the routine will be called from both **ON ERROR ** and **ON CLOSE** statements:​\\ \\  The cleanup code will need to be executed not only on the normal exit from the program but also if a premature exit takes place because of an error (including Escape) or the user clicking on the **Close** button. Therefore it is likely that the routine will be called from both **ON ERROR ** and **ON CLOSE** statements:​\\ \\ 
 +<code bb4w>
         ON CLOSE PROCcleanup : QUIT         ON CLOSE PROCcleanup : QUIT
         ON ERROR SYS "​MessageBox",​ @hwnd%, REPORT$, 0, 48 : PROCcleanup : QUIT         ON ERROR SYS "​MessageBox",​ @hwnd%, REPORT$, 0, 48 : PROCcleanup : QUIT
 +</​code>​
 But this immediately causes a problem. What happens if the premature exit occurs //before// one or more of the variables used in **PROCcleanup** have been created? The result would be a **No such variable** error, which would activate the ON ERROR routine, which would call PROCcleanup,​ which would result in another error and so on //ad infinitum//​. This is not good!\\ \\  What is needed is a way of forcing a variable to exist if it doesn'​t already, but leaving its value unchanged if it does. Fortunately **BBC BASIC** provides two ways of doing this:\\ \\  But this immediately causes a problem. What happens if the premature exit occurs //before// one or more of the variables used in **PROCcleanup** have been created? The result would be a **No such variable** error, which would activate the ON ERROR routine, which would call PROCcleanup,​ which would result in another error and so on //ad infinitum//​. This is not good!\\ \\  What is needed is a way of forcing a variable to exist if it doesn'​t already, but leaving its value unchanged if it does. Fortunately **BBC BASIC** provides two ways of doing this:\\ \\ 
 +<code bb4w>
         variable = variable         variable = variable
         variable += 0         variable += 0
 +</​code>​
 Both these have the same effect: if **variable** already exists it is left unaltered, if **variable** doesn'​t exist it is created and its value is set to zero. Obviously there are a number of other equivalent operations such as "​variable *= 1" but the two listed are the ones most commonly used.\\ \\  So armed with this knowledge we can now modify **PROCcleanup** so that it never fails with a **No such variable** error:\\ \\  Both these have the same effect: if **variable** already exists it is left unaltered, if **variable** doesn'​t exist it is created and its value is set to zero. Obviously there are a number of other equivalent operations such as "​variable *= 1" but the two listed are the ones most commonly used.\\ \\  So armed with this knowledge we can now modify **PROCcleanup** so that it never fails with a **No such variable** error:\\ \\ 
 +<code bb4w>
         DEF PROCcleanup         DEF PROCcleanup
         Outfile% += 0  : IF Outfile%<>​0 ​ CLOSE #Outfile%         Outfile% += 0  : IF Outfile%<>​0 ​ CLOSE #Outfile%
Line 19: Line 26:
         Memory% += 0   : IF Memory%<>​0 ​  SYS "​GlobalFree",​ Memory%         Memory% += 0   : IF Memory%<>​0 ​  SYS "​GlobalFree",​ Memory%
         ENDPROC         ENDPROC
 +</​code>​
 Of course this relies on the normal values of the variables never being zero, but in general that is the case.\\ \\  You can use this technique whenever you can't be sure whether a variable has been created or not.\\ \\ //Added by JGH, May 2006//\\ \\  This can be improved a little. What would happen if **PROCcleanup** was called again? If **Outfile%** was still nonzero, it would attempt to close a channel that has already been closed. After the cleanup operation the variable should be set to zero, eg **CLOSE#​Outfile%:​Outfile%=0**.\\ \\  If **PROCcleanup** is called by ON ERROR, what happens if the cleanup causes an error? It is called again. If, for example, **CLOSE#​Outfile%** causes an error, **PROCcleanup** will be called again, which will then try to do **CLOSE#​Outfile%** again, which will cause an error...\\ \\  What I prefer to do is zero the variable before doing the cleanup, which means if the cleanup is called again an invalid cleanup isn't attempted.\\ \\  Of course this relies on the normal values of the variables never being zero, but in general that is the case.\\ \\  You can use this technique whenever you can't be sure whether a variable has been created or not.\\ \\ //Added by JGH, May 2006//\\ \\  This can be improved a little. What would happen if **PROCcleanup** was called again? If **Outfile%** was still nonzero, it would attempt to close a channel that has already been closed. After the cleanup operation the variable should be set to zero, eg **CLOSE#​Outfile%:​Outfile%=0**.\\ \\  If **PROCcleanup** is called by ON ERROR, what happens if the cleanup causes an error? It is called again. If, for example, **CLOSE#​Outfile%** causes an error, **PROCcleanup** will be called again, which will then try to do **CLOSE#​Outfile%** again, which will cause an error...\\ \\  What I prefer to do is zero the variable before doing the cleanup, which means if the cleanup is called again an invalid cleanup isn't attempted.\\ \\ 
 +<code bb4w>
         DEF PROCcleanup         DEF PROCcleanup
         LOCAL temp%         LOCAL temp%
Line 26: Line 35:
         Memory% += 0   :IF Memory% ​ :​temp%=Memory% ​ :​Memory%=0 ​ :SYS "​GlobalFree",​ temp%         Memory% += 0   :IF Memory% ​ :​temp%=Memory% ​ :​Memory%=0 ​ :SYS "​GlobalFree",​ temp%
         ENDPROC         ENDPROC
 +</​code>​
 This is the technique I use in my BASIC program libraries, such as the Close library. This is the technique I use in my BASIC program libraries, such as the Close library.
forcing_20a_20variable_20to_20exist.txt ยท Last modified: 2018/04/17 16:18 by tbest3112