home *** CD-ROM | disk | FTP | other *** search
- 5 FOCUS: Conditional Linking
- by Roger Donnay
-
-
- Introduction
-
- By now you are probably quite familiar with the features of the
- Clipper 5 preprocessor which allow "conditional compiling". Of
- course, this is a very handy method of controlling the configuration
- of your application, but many times it is simpler to use CONDITIONAL
- LINKING methods instead.
-
- Through Conditional Linking, you can control the symbols and or code
- segments which get linked into your application by using special
- RTLINK commands. Many times it is easier to control the configuration
- of a large application at "link-time" rather than "compile-time".
- This can be accomplished by using RTLINK's DEFINE command and/or REFER
- command.
-
-
- The DEFINE Command
-
- DEFINE <symbol> lets you force a "null address" to be assigned to any
- symbol and prevent that symbol or "function" and its associated code
- from being linked into your application. An example of using DEFINE
- for conditional linking could be shown as follows:
-
- * Your Clipper code
- DO menu
- DO CASE
- CASE choice=1
- DO report1
- CASE choice=2
- DO report2
- CASE choice=3
- DO report3
- ENDCASE
-
- * Your link script file
- DEFINE report2,report3
-
- In the above example, the command DEFINE report2,report3 will insure
- that the REPORT2 and REPORT3 programs do not get linked into the
- program. This allows you to build test versions of your application
- and only link in the portions you are currently testing. This
- conditional linking technique provides the following advantages:
-
- 1. Reduces the .EXE physical size.
-
- 2. Improves the memory model of the program by removing unneeded
- code and symbols.
-
- 3. Improves linking speed.
-
- 4. Can be accomplished without the need to re-compile your code.
-
- DEFINE can also be used to resolve "Undefined Symbol" errors produced
- during linking. For example, let's say you inherited a clipper
- program which calls a specified function in a third-party library.
- You don't happen to have the library so RTLINK will generate
- "Undefined Symbol" errors indicating that it could not find the symbol
- you have referenced in your application. Of course, if the function
- is an important integral part of the application and the application
- cannot even start without it, then you must resolve the problem by
- acquiring the proper library.
-
- There are many other cases, however, in which the symbol is not
- important to you at the current time and you may be only interested in
- running portions of the program in which this symbol is not used. In
- cases such as these, simply use the command DEFINE <symbol> in your
- link script file to eliminate the link errors.
-
-
- The REFER Command
-
- The REFER <symbol> command in your RTLINK script file performs the
- same function as the EXTERNAL <symbol> command in your source code.
- So why use REFER instead? Because, again, configuration control can
- be accomplished at link-time rather than compile-time. For this
- example, I'm going to use my product dCLIP as an example of how
- important this command is used to determine the configuration of a
- large Clipper application.
-
- dCLIP is a database management tool and development platform which
- supports a large variety of features which are all callable by
- commands or functions from our main dot-prompt. There are times that
- the dCLIP programmer wishes to create a "stripped-down" version or
- "subset" of the dot-prompt commands when linking the DC_DOT() function
- into their application. For example, it may not be desirable to
- include the report manager, printer manager, import/export utilities,
- assist system, etc.
-
- The hard way to accomplish this task is to modify the source code,
- recompile it and use the modified code rather than the code in the
- dCLIP library. Wouldn't it be much simpler if the list of desired
- programs to link could be handled by a simple table in the link
- script? Look at the advantages:
-
- 1. No need to modify source code.
-
- 2. No need to produce different sets of object files or libraries.
-
- 3. Only one file, the link-script, needs to be modified.
-
- There is one thing that must be done during programming to give you
- this flexibility: Make sure that the programs called by your menus or
- commands are called by "indirect reference". The simplest example of
- an indirect call is a procedure that is called via macro as follows:
-
- program = "REPORT1"
- DO &program
-
- The indirect reference insures that the REPORT1 symbol is not created
- at compile-time so you can instead force this symbol at link-time.
- When the above code is compiled and linked there will be no symbol
- created for the linker so that the procedure REPORT1 will not be
- linked into the program. Now you can make the decision at link-time
- to decide if you want REPORT1 to be linked into your application by
- using the following command:
-
- REFER REPORT1
-
- Of course, if you don't include the above command, the REPORT1 module
- will NOT be linked into the program thereby causing a runtime error in
- the event that the operator chooses the menu item which selects the
- REPORT1 module. In dCLIP, we handle this problem by calling all major
- programs or functions through our DC_DO() function. DC_DO() is a more
- user-friendly way of handling these situations by allowing you to
- selectively decide the features of your end application at link-time.
- If a procedure or function is accessed indirectly via DC_DO() then the
- operator is given a friendly message rather than a runtime error
- message in the event that you choose not to link the selected module.
-
- The DC_DO() function source code:
-
- FUNCTION dc_do
- PRIVATE _d_c_para, _d_c_doscr, _d_c_1obj, _d_c_c, _d_c_func, ;
- _d_c_doprg, _d_c_pcall
- PARAMETERS _d_c_doprg, _d_c_pcall
- _d_c_pcall = IIF(TYPE('_d_c_pcall') = 'C', _d_c_pcall, '')
- _d_c_doprg = IIF(TYPE('_d_c_doprg') = 'C', _d_c_doprg, '')
- _d_c_para = PCOUNT()
- _d_c_func = _d_c_doprg
- IF '(' $ _d_c_doprg
- _d_c_doprg = SUBSTR(_d_c_doprg, 1, AT('(', _d_c_doprg) - 1)
- ENDIF
- * check to see if called function or procedure is in memory
- IF TYPE(_d_c_doprg + '()') # 'UI'
- IF EMPTY(_d_c_pcall)
- _d_c_c = SETCOLOR()
- _d_c_doscr = DC_EXPLODE(10, 5, 17, 75)
- @ 11,21 SAY 'Sorry, this configuration of dCLIP does not include the'
- @ 12,21 SAY 'selected procedure or function. Include the command'
- @ 13,21 SAY 'EXTERNAL '+_d_c_doprg+' in your program source code or'
- @ 15,21 SAY 'REFER '+_d_c_doprg+' in your link file if you wish to'
- @ 16,21 SAY 'include this function.'
- INKEY(0)
- DC_IMPLODE(_d_c_doscr)
- RETURN .f.
- ELSE
- RETURN DC_DO(_d_c_pcall)
- ENDIF
- ENDIF
- IF '(' $ _d_c_func
- RETURN &_d_c_func
- ELSE
- DO &_d_c_doprg
- ENDIF
- RETURN .t.
-
- Using DC_DO() in your application code:
-
- * Your Clipper code
- DO menu
- DO CASE
- CASE choice=1
- DC_DO('report1')
- CASE choice=2
- DC_DO('report2')
- CASE choice=3
- DC_DO('calc()')
- ENDCASE
-
-
- Quicker Linking
-
- During programming sessions you are usually working on a small portion
- of your application at any one time, yet each time you relink the
- application you must relink all of your executable code. In previous
- articles I have discussed using PLL's and "incremental linking" to
- improve this process. However, in many situations conditional linking
- can be even more effective. By adding DEFINE <symbol> commands in
- your link script file, you can effectively prevent the linking of all
- code that is associated with the defined symbol. By adding a large
- group of DEFINE commands you can eliminate the linking of a major
- portion of the application. During testing it is necessary to link
- only the code you are testing, not all menus and submenus, so use the
- DEFINE command to strip out the code you don't need. You will get a
- smaller .EXE, a smaller memory model and the program will even
- start up faster.
-
-
- Conclusion
-
- Conditional linking is an alternative method of application
- configuration control which can make application development much
- easier to manage. Take the time to experiment with this method. If
- you produce a Clipper add-on library, you may find this technique to
- be invaluable.
-
-
- About the Author
-
- Roger Donnay is the developer of the dCLIP development platform/
- runtime system for Clipper, and the application libraries SOFT.CLIP
- and TIME-TRAK. He will be a featured speaker at the Nantucket
- Developers Conference in June. Feel free to contact Roger via the
- Aquarium Message Center, or at:
-
- DONNAY Software Designs
- 1880 Park Newport, #104
- Newport Beach, CA 92660
- Tel: 714-721-6720
- Fax: 714-721-9495
- Compuserve: 73227,1225
-