4

The LA Fox Developer Newsletter
February 1997
The Nasty Secret Behind
#INCLUDE Nesting in VFP3.Ob
by Marc Deric, Laguna Groupware, Inc.
Through my interminable tinkering with Codebook and the HotLink web stuff, I came across a problem with #INCLUDE nesting that cost me a few hours of consternation and didn’t appear to be in the documentation, on the MS Knowledge base, or in the online help. I hope this article helps you avoid the same problem and gives you a look at some of Codebook’s clever tricks (which you might adopt even if you’re not a Codebook developer).
The cut to the chase is that VFP3.Ob only appears to support 4 levels of include file nesting and Codebook uses them all. When you execute Codebook’s QSTART.APP, which creates the framework of a new project in the destination directory of your choice, an include file hierarchy is created for the application. The project home directory is different from the Codebook CDBK3O\COMMON3O directory, the latter contains all the framework’s standard class libraries, graphics, programs, utility APPs, and include files. The project home directory contains the application-specific class libraries, graphics, programs, and an application-specific include file. APPINCL.H, which contains #DEFINE constants for, among other things, the title of the main window Lscreen.Caption) and the name of the application’s top-level class.
Since any specific class in library can only have one include file (which shows in the “Reserved8” memo field if you open the .VCX as a table) it is important for APPINCL.H itself to contain #lNCLUDE references to the framework’s standard include files. This way, the application-specific classes can have access to both the application’s #DEFINEs as well as to the #DEFINEs in the framework’s standard include files. The astute reader might note that this is only two levels no problem’
WelI...the framework’s standard include files are themselves a two level system. There is a file called FRAMEWRK.H which includes some #DEFINEs and #INCLUDE references to STRINGS.H and ERRORS.H, two Codebook files, and to FOXPRO.H, the standard include file that comes with VFP. If you consider the framework’s standard class libraries which use FRAMEWRK.H as their #INCLUDEd file, it is easy to see the motivation of two levels, access to framework level constants and access to FoxPro standard constants. And we’re up to three levels.
But what about standard classes in the framework, under the CDBK3O\COMMON3O directory, which need to access application-specific constants? An example is the CMainMenu class in the CTMENUS.VCX library. This class creates the application’s Main Menu and is programmed to install a “Utilities” menu pad for debugging based on some application-specific debug mode constants in APPINCL.H. Since this is a standard framework class and not an application-specific class, we cannot simply include the APPINCL.H file. Which one would we use? There are as many APPINCL.H files on our disk as we have active Codebook projects. For these classes, the authors of Codebook offer a
FRAMINCL.H header file. Its only statement is as follows:
#INCLUDE 'INCLUDE\APPLINCL.H'
This works because, at compile time when the header files are used, the relative reference ‘INCLUDE\APPINCL.H’ points to thE correct APPINCL.H file. [Aside: There is an interesting phenomenon which derives from this choice of implementation. The compiled class code for “standard” framework classes usinç FRAMINCL.H has been created using the APPINCL.H file frorr one specific project, the last one in which you compiled. Wher you switch projects, the compilation appears up to date to th€ Project Manager, even though it has been based on the wronç APPINCL.H file! “Recompile All Files” addresses this problem.:
Four levels:
1)
FRAMINCL.H
2)
APPINCL.H
3)
FRAMEWRK.H
4)
STRINGS.H, ERRORS.H, FOXPRO.H
I tried to add a website specific include file, WEBINCL.H, between 2) APPINCL.H and 3) FRAMEWRK.H. The theory was that I wouldn’t need to change any standard Codebook header files, only APPINCL.H which is meant to be changed. My WEBINCL.H file could itself #INCLUDE the FRAMEWRK.H file. It didn’t work, the fifth level of nesting put the constants in STRINGS.H, ERRORS.H, and FOXPRO.H out of visibility. Needless to say, the workaround is simple: #INCLUDE the WEBINCL.H header file in APPINCL.H so it appears with FRAMEWRK.H at level 3 and does not create a fifth level.
For those interested in a Microsoft-style “Steps to Reproduce the Problem” proving that four levels is the maximum try, the following as INCLTEST.PRG:
LOCAL IolnclTestForm
SET CLASSLIB TO
IolnclTestForm = CREATEOBJECT(”ClnclTestForm”)
#INCLUDE “incll.h”
DEFINE CLASS cincltesttorm AS form
Caption “Form”
Name = “cincltestform”
PROCEDURE mit
?“Message: “+ SAMPLEMSG
ENDPROC
ENDDEFINE

Create header files INCLI.H through INCL5.H, with each including the next higher level and INCL5.H containing only the following:
#DEFINE SAMPLEMSG “#DEFINE Was Found.”

When you run it you will get the “Variable SAMPLEMSG not Found.” message. Setting the include file from INCLI .H to INCL2.H fixes the problem; the message “Message: #DEFINE Was Found.” prints.


A Little Humor.....
There was a man who entered a local paper’s pun contest. He sent in ten different puns, in the hope that at least one of the
puns would win. Unfortunately, no pun in ten did.
Page 4

4