Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.
PROGRAM()
, Sys(16), ASTACKINFO()
These functions tell you about the program currently executing and the execution chain. They’re especially handy when you’re debugging.
nProgDepth = PROGRAM( -1 )
cProgInChain = PROGRAM( [ nLevel ] )
cProgInChain = SYS( 16 [ , nLevel ] )
PROGRAM()
returns just the name of the program without any path information. SYS(16) provides the complete path. Neither pays any attention to the setting of FULLPATH. If the program is contained in another file (like a procedure file or a class library), SYS(16) specifies the name of that file as well.
nLevel traces the execution chain. Specifying either 0 or 1 returns the main program that started the whole thing. As nLevel increases, you get closer to the currently executing program. If nLevel is greater than the number of programs in the chain, both functions return the empty string. Omitting the nLevel parameter from either function returns the currently executing program.
SYS(16, 1) is the key to finding out how you got started. It returns the name of the APP or EXE file that was run (assuming that's how you ran the application). This is especially important when working with apps that have a form marked as main—in that case, the file portion of SYS(16) indicates the SCT, not the APP or EXE. |
PROGRAM(–1), added in VFP 6, tells you how deep you are in the program chain. Before that, you had to test for EMPTY(PROGRAM()
) to know when you’d reached the end. Watch out for one thing here—PROGRAM(–1) returns a numeric value, while passing any other value gives a character return.
SYS(16) is incredibly useful for locating files in an interactive development environment. Doug often builds tools that need to open a table or access some other file that belongs to the tool. Although all these files are in the same directory, it isn’t usually the current directory when the tool is running, so code like USE Table or LOADPICTURE(SomePicture) bombs out. To avoid hard-coding paths, he uses code like:
lcDir = JustPath(SYS(16))
&& Or in VFP 5 and before, lcDir = LEFT(SYS(16), AT('\', SYS(16)))
USE (lcDir + 'MYTABLE')
The example below is a function that traces the entire execution chain and fills an array with the results. In VFP 6 and earlier versions, you might call this function from an error handler to determine what was going on when the program failed. In VFP 7, you don’t need this function; use ASTACKINFO()
, instead.
* AProgram.PRG
* Fill an array with the programs in use, except this one.
* Column 1 contains the program name returned by PROGRAM().
* Column 2 contains the detailed information returned by
* SYS(16).
* Return the size of the array.
* If parameter isn't an array, return -1.
LPARAMETERS aProgs
* Check parameter
IF TYPE("aProgs[1]")="U"
RETURN -1
ENDIF
* Trace the calling chain.
LOCAL nLevel
FOR nLevel = 1 TO PROGRAM(-1)
DIMENSION aProgs[nLevel,2]
aProgs[nLevel,1] = PROGRAM(nLevel)
aProgs[nLevel,2] = SYS(16,nLevel)
ENDFOR
* Now remove last row which represents this program.
DIMENSION aProgs[nLevel-2,2]
RETURN nLevel-2
nLevels = ASTACKINFO( aProgChain )
We’d like to think that we’re partially responsible for having this function, added in VFP 7, in the language. Just maybe the Fox team saw the example above in earlier versions of this book and decided it would make a good addition. Then again, maybe not.
In any case, ASTACKINFO()
fills an array with information about the calling stack. Each row corresponds to one call, in the same order that PROGRAM()
and SYS(16) return them. The array contains more information than other functions, and in fact, contains some items you can’t find any other way, like the line number and the source code of the specified line. The array has six columns, as follows:
Column |
Contents |
1 |
The stack level. |
2 |
The name of the file executing at this level. |
3 |
The name of the module or object executing at this level. |
4 |
The name of the source code file for the code executing at this level. |
5 |
The line number executing at this level. |
6 |
The line of code executing at this level. |
When you're running an APP or EXE, the second column of the array should contain the name of the APP or EXE in every row. When you call AStackInfo() from a form or class, the second column contains the name of the SCT or VCT, instead. |