home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a081 / 2.ddi / PREDB.EXE / PRE_DB.TXT < prev   
Encoding:
Text File  |  1991-04-16  |  17.7 KB  |  559 lines

  1. Introduction
  2.  
  3. PRE/DB is a database language preprocessor.  It processes your
  4. program source file and produces an output file acceptable to the
  5. compiler/interpreter being used.  The source file may be
  6. embellished with preprocessor directives.  The preprocessor
  7. processes these directives and then removes them from the file it
  8. produces.
  9.  
  10. C programmers have long enjoyed the convenience of a
  11. preprocessor.  That language's compiler automatically invokes its
  12. preprocessor as a first pass in the compilation process.  PRE/DB,
  13. however, must be explicitly run on the source program - the
  14. database language processors now available do not automatically
  15. invoke it.
  16.  
  17. By using a preprocessor, then, the programmer can use programming
  18. commands not supported by the compiler/interpreter being used.
  19. The preprocessor processes these commands and produces a
  20. translated output file acceptable to the language processor being
  21. used.
  22.  
  23. PRE/DB is language independent - it does not care what language
  24. the program is written in.  It simply processes the preprocessor
  25. directives and leaves the other statements untouched.
  26.  
  27.  
  28. Here are the directive PRE/DB recognizes
  29.  
  30. A preprocessor directive consists of the character #. followed by
  31. a command.  The preprocessor supports the same commands in the
  32. same manner as the C preprocessor.  These commands are:
  33.  
  34.      1)   #define
  35.      2)   #undef
  36.      3)   #ifdef
  37.      4)   #else
  38.      5)   #endif
  39.      6)   #ifndef
  40.      7)   #include
  41.  
  42. These commands will now be examined one at a time.
  43.  
  44. #define
  45.  
  46. The #define directive is used in one of two ways, either to
  47. symbolically define a constant, or to define a compiler macro.
  48. Let us look at the definition of a constant first.
  49.  
  50. #define and Constants
  51.  
  52. While the dBASE language allows a constant to be used, as in:
  53.  
  54.      IF key = 27
  55.  
  56. there is no way to associate the constant 27 with a name.  The
  57. constant could be defined as a memory variable with:
  58.  
  59.      ESC = 27
  60.  
  61.      IF key = ESC
  62.  
  63. but it is no longer a constant.  There is nothing to stop the
  64. variable being modified.  Still, this method of using memory
  65. variables to hold constant data is popular because it makes
  66. programs more readable.
  67.  
  68. A common practice is to group all such definitions in a common
  69. procedure which is called once by the program's startup code.
  70. These memory variables are defined as PUBLIC, which allows them
  71. to be seen outside of this routine.  The following procedure is
  72. an example.  It defines a number of key values and a few color
  73. definitions:
  74.  
  75.      PROCEDURE init_consts
  76.  
  77.      PUBLIC, ESC,UP_ARROW,PG_UP,DOWN_ARROW,PG_DOWN
  78.  
  79.      PUBLIC END_KEY, HOME, ENTER
  80.  
  81.      PUBLIC F1, F2, F3, F4, F5, F6, F7
  82.  
  83.      PUBLIC F8, F9, F10, LT_ARROW, RT_ARROW
  84.  
  85.      PUBLIC BRIGHT, NORM, ENH, HIDDEN
  86.  
  87.           ESC = 27
  88.           UP_ARROW = 5
  89.           PG_UP = 18
  90.           DOWN_ARROW = 24
  91.           PG_DOWN = 3
  92.           END_KEY = 6
  93.           HOME = 1
  94.           ENTER = 13
  95.           F1 = 28
  96.           F2 = -1
  97.           F3 = -2
  98.           F4 = -3
  99.           F5 = -4
  100.           F6 = -5
  101.           F7 = -6
  102.           F8 = -7
  103.           F9 = -8
  104.           F10 = -9
  105.           LT_ARROW = 19
  106.           ARROW = 4
  107.           BRIGHT = "W+/ "
  108.           NORM = "W/ "
  109.           ENH = " /W"
  110.           HIDDEN = " / "
  111.  
  112.      RETURN
  113.  
  114. Although use of this technique results in a better-structured,
  115. more readable program, it does come at some expense both in terms
  116. of program speed and size.  dBASE imposes a limit on the number
  117. of memory variables that may be active at one time.  Clipper has
  118. a 22 byte overhead for each memory variable used.  Both products
  119. can execute a constant access such as:
  120.  
  121.      IF key = 27
  122.  
  123. faster than they can process a memory variable such as:
  124.  
  125.      IF key = ESC
  126.  
  127. These memory variables occupy valuable memory space whether they
  128. are used or not.  Some applications you write will use some of
  129. the variables, others different ones.  It is tempting to write
  130. "custom" versions of this "init_consts" routine to save space,
  131. but this probably produces more problems than it solves.
  132.  
  133. Using the preprocessor's #define directive overcomes all of the
  134. problems outlined above.  It allows a constant to be defined with
  135. a name, but without using a memory variable.
  136.  
  137. It does this as follows.  When the preprocessor comes across a
  138. #define directive such as
  139.  
  140.      #define ESC 27
  141.  
  142. it "remembers" that the constant ESC has the value 27 and deletes
  143. this line from the output file it is producing.  (If the line
  144. remained in the output file, the language processor would
  145. complain when it encountered that line, as it is an invalid
  146. statement.)  Then, when the preprocessor encounters a line such
  147. as
  148.  
  149.      IF key = ESC
  150.  
  151. it substitutes the value 27 for the ESC constant in the output
  152. file, producing the line
  153.  
  154.      IF key = 27
  155.  
  156. Since the language processor only sees the output file, it
  157. successfully processes the line.  It has no idea that the #define
  158. line or the ESC constant ever existed.
  159.  
  160. Using constants in this manner has three advantages.  First, it
  161. makes the program more readable.  Second, it leads to a greatly
  162. reduced program size in compiled applications.  Third, these
  163. constants cannot be changed, protecting the programmer from
  164. inadvertently changing one of the "pseudo" constants.
  165.  
  166. The "init_consts" procedure, therefore, could be replaced with
  167. the following set of #define statements:
  168.  
  169.      #define ESC 27
  170.      #define UP_ARROW 5
  171.      #define PG_UP 18
  172.      #define DOWN_ARROW 24
  173.      #define PG_DOWN  3
  174.      #define END_KEY  6
  175.      #define HOME  1
  176.      #define ENTER  13
  177.      #define F1  28
  178.      #define F2  -1
  179.      #define F3  -2
  180.      #define F4  -3
  181.      #define F5  -4
  182.      #define F6  -5
  183.      #define F7  -6
  184.      #define F8  -7
  185.      #define F9  -8
  186.      #define F10  -9
  187.      #define LT_ARROW  19
  188.      #define RT_ARROW  4
  189.      #define BRIGHT "W+/ "
  190.      #define NORM "W/ "
  191.      #define ENH " /W"
  192.      #define HIDDEN " / "
  193.  
  194. Note that the "=" signs are not included in the #define
  195. statement.  The preprocessor performs a strict textual
  196. replacement of the constant being defined with the defined value.
  197. If ESC had been defined as:
  198.  
  199.      #define ESC = 27
  200.  
  201. when the preprocessor came upon the line:
  202.  
  203.      IF key = ESC
  204.  
  205. it would substitute ESC with "ESC = 27," producing the line:
  206.  
  207.      IF key = = ESC
  208.  
  209. A large number of #defines such as this would typically be
  210. contained within a separate file included with the preprocessor
  211. #include directive (see page 9).
  212.  
  213. Be careful not to define words that the database dialect uses as
  214. keywords.  The most common example of this is defining RETURN as
  215. 13 when using a dBASE-like language.  This would be done with
  216.  
  217.      #define RETURN 13
  218.  
  219. Now, whenever the preprocessor encounters the word RETURN, it
  220. replaces it with the value 13.  It does this both in constructs
  221. such as:
  222.  
  223.      IF key = RETURN
  224.  
  225. replacing it in the output file with:
  226.  
  227.      IF key = 13
  228.  
  229. AND in such statements as:
  230.  
  231.      PROCEDURE xyz
  232.            .
  233.            .
  234.            .
  235.      RETURN
  236.  
  237. replacing it with:
  238.  
  239.      PROCEDURE xyz
  240.            .
  241.            .
  242.            .
  243.      13
  244.  
  245. which is definitely not what is required.  In this case, use the
  246. word ENTER instead.
  247.  
  248. Compiler Macros
  249.  
  250. The #define directive can be used with parameters to produce what
  251. is known as a compiler macro.  This must be distinguished from
  252. the dBASE language runtime macro.  The compiler macro is
  253. processed by the preprocessor, whereas the runtime macro is
  254. processed by the runtime system of the language processor.
  255.  
  256. Compiler macros are basically text substitutions which can be
  257. parameterized.  They are defined by enclosing a formal parameter
  258. list within parentheses following the name of the defined macro.
  259. Here is an example:
  260.  
  261.      #define inc(x)  x = x + 1
  262.  
  263. This defines a macro "inc" with a formal parameter "x."  The
  264. macro is defined as adding one to the parameter.  To use this
  265. macro, the macro name is called, followed by the actual parameter
  266. in parentheses.  For example:
  267.  
  268.      inc(y)
  269.  
  270. would be expanded to:
  271.  
  272.      y = y + 1
  273.  
  274. in the output file.  This method of substituting actual
  275. parameters with formal parameters is exactly what Clipper does
  276. when a user-defined function is defined and invoked, and what
  277. Clipper, dBASE, and other database language processors do when a
  278. PROCEDURE is defined and called.
  279.  
  280. Macros can be defined with several parameters separated by
  281. commas.  The following macro, for example, produces code that
  282. adds parameter 2 to parameter 1:
  283.  
  284.      #define  addto(x, y)  x = x + y
  285.  
  286. A macro to increment a field in a database can be written as:
  287.  
  288.      #define replinc(x, y)  REPLACE x WITH x + y
  289.  
  290. Macros are mainly used to make programs more readable.  They are
  291. especially useful as substitutes for simple Clipper user-defined
  292. functions.  When used in this manner, they result in smaller,
  293. more efficient programs.  Here are some examples:
  294.  
  295.      #define isescape inkey() = ESC
  296.  
  297.      #define center(x)  SPACE(80 - (len(x) / 2)) + x
  298.  
  299. These could be used in the following manner:
  300.  
  301.      USE sales
  302.  
  303.      * list entire database or until escape key is hit
  304.      LIST name, address1, address2 ..WHILE !isescape
  305.  
  306.      @ 24, 0 SAY center("A centered message on line 24")
  307.  
  308. The following macro would be used to assign a default value to a
  309. parameter if it was not defined:
  310.  
  311. #define p_default(x,not_def) x =IIF(type([x]) = 'U',not_def,x)
  312.  
  313. This would be used in the following manner:
  314.  
  315.      FUNCTION test
  316.  
  317.      PARAM p1, p2, p3
  318.  
  319.           p_default(p1, 1)
  320.           p_default(p2, 2)
  321.           p_default(p3, 3)
  322.  
  323.           .
  324.           .
  325.           .
  326.  
  327.      RETURN  .T.
  328.  
  329. When used with a language such as dBASE, which does not support
  330. user-defined functions, this sort of macro gives that language
  331. the "look and feel" of a language that does support them.
  332.  
  333. Macros are also used to save typing.  Assume that a dBASE-like
  334. program wishes to validate that the memory variable "state_name"
  335. contained either the value "Ca," "Az," "Nv," or "Wa."  This would
  336. be written as
  337.  
  338.      IF state_name = 'Ca' .OR. state_name = 'Az' .OR.;
  339.           state_name = 'Nv' .OR. state_name = 'Wa'
  340.      .
  341.      .
  342.      ENDIF
  343.  
  344. If this validation had to be performed at many places in the
  345. program, this code would either be written as a user-defined
  346. function in Clipper (incurring the overhead of a function call),
  347. or would require a typing marathon!  A better method would to
  348. write the condition as a macro, as in
  349.  
  350.    #define good_state(s) s='Ca' .OR. s='Az' .OR. s='Nv';
  351.          .OR. s='Wa'
  352.  
  353. and then reference it as
  354.  
  355.      IF good_state(state_name)
  356.  
  357.  
  358. #undef
  359.  
  360. The #undef directive is basically the inverse of the #define
  361. directive.  It "undefines" the specified variable or macro.  This
  362. is useful when you wish to restrict the scope of a define to a
  363. well-defined area of the program.
  364.  
  365.  
  366. #ifdef / #else / #endif / #ifndef
  367.  
  368. These four directives are used together to provide conditional
  369. compilation/interpretation.  A section of code is enclosed within
  370. an #ifdef/#endif pair, and if the name following the #ifdef
  371. directive is defined, the code within the block is passed through
  372. to the output file.  If it is not defined, the code is not passed
  373. through.
  374.  
  375. The #else directive can be used within the #ifdef/#endif pair to
  376. delimit another section of code.  If the name following the
  377. #ifdef directive is declared, the code delimited by the
  378. #ifdef/#else code is passed through; if not, the code delimited
  379. by the #else/#endif code is declared.  Here is an example:
  380.  
  381.      #define CLIPPER
  382.  
  383.      #ifdef CLIPPER
  384.        DO edit_code
  385.      #else
  386.        edit
  387.      #endif
  388.  
  389. In this case, the code "DO edit_code" is passed through to the
  390. output file, since "Clipper" is defined.  If it were not, the
  391. code "edit" would be passed through.  Once again, the directives
  392. are stripped from the output file so the language processor does
  393. not know that a pre-pass even took place.
  394.  
  395. Do not confuse the above method of selective processing with that
  396. currently used by Clipper programmers.  They use a runtime IF
  397. statement on a PUBLIC variable CLIPPER which the Clipper runtime
  398. system has set to .T.  This takes place at runtime, and any code
  399. contained in the ELSE part of that statement is still compiled
  400. (often producing annoying compilation errors for non-supported
  401. commands).
  402.  
  403. The #ifndef directive is the inverse of the #ifdef directive.  It
  404. means "allow the following code if the following symbol is NOT
  405. defined."  The #else directive used with a #ifndef thus means
  406. "allow the following code if the symbol following the preceding
  407. #ifndef was defined."
  408.  
  409. #include
  410.  
  411. The #include directive causes the specified file to be read and
  412. replaced into the current file.  The file would usually contain a
  413. number of #define statements.  It may contain regular code, but
  414. this is not recommended, since it will destroy the integrity of
  415. line numbering (see Line Numbers.)
  416.  
  417. The preceding example we gave of the series of #defines for key
  418. values, etc., would be contained in a file that is #included into
  419. the main file.  It then appears to the preprocessor as if the
  420. statements had been included directly in the main program file.
  421.  
  422. It is recommended that the include file be given a .H ("header")
  423. extension.
  424.  
  425. The preprocessor looks for the include file in the current
  426. directory.  If it doesn't find it there, it will search all
  427. directories specified by the PPINCLUDE environment variable.  For
  428. example, let's say you have issued the DOS command
  429.  
  430.      SET PPINCLUDE=\clipper;\mc\include
  431.  
  432. and in your preprocessor file you have
  433.  
  434.      #include "KEYS.H"
  435.  
  436. The preprocessor first looks in the current directory for the
  437. file "KEYS.H".  If it doesn't find it there, it searches first
  438. the \clipper directory and then the \mc\include directory before
  439. returning a "file not found" error.
  440.  
  441.  
  442. Syntax
  443.  
  444. Here is the syntax of the directives described above.
  445.  
  446.      #include "pathspec"      "pathspec" is a regular DOS file
  447.                               specification.  If no extension is
  448.                               specified, .PRG is assumed.
  449.      
  450.      #define a b              "a" is a name, containing any
  451.                               sequence of letters or digits.  "b"
  452.                               is any text.
  453.      
  454.      #define m(args) m_txt    Define macro "m" with formal
  455.                               arguments "args" as "m_txt."
  456.      
  457.      #undef a                 Remove latest definition of "a."
  458.      
  459.      #ifdef a                 Include following block up to next
  460.                               #else or #endif if "a" is defined.
  461.      
  462.      #ifndef a                Include following block up to next
  463.                               #else or #endif if "a" is not
  464.                               defined.
  465.      
  466.      #else                    Include following block up to next
  467.                               #endif if preceding #ifx is false.
  468.      
  469.      #endif                   End of a conditional block.
  470.      
  471.  
  472. PRE/DB and the dBASE Language
  473.  
  474. PRE/DB takes into account certain idiosyncrasies of the dBASE
  475. language.  It will not perform the above substitutions inside a
  476. TEXT/ENDTEXT block, inside a comment (started with either && or
  477. *), inside a NOTE, or inside a character string delimited with
  478. either ' or " (single or double quotation mark).  However, it
  479. will perform a substitution inside strings delimited with [].
  480. This is because, for speed, PRE/DB takes a simplistic approach to
  481. parsing, and distinguishing between the use of [] for strings and
  482. Clipper's use of [] for array subscripts would be time-consuming.
  483.  
  484. When using Clipper, ensure that any files automatically compiled
  485. by Clipper as a result of a DO <proc_name> or SET PROCEDURE TO
  486. command have been processed with the preprocessor; PRE/DB does
  487. not automatically read and process any procedures referenced in
  488. this manner, as Clipper does.  When using dBASE, be sure that the
  489. preprocessor has been run on files specified by a SET PROCEDURE
  490. TO command.
  491.  
  492.  
  493. Running PRE/DB
  494.  
  495. PRE/DB is a filter.  It takes one file as input and produces
  496. another as output.  If no extension is specified, an extension of
  497. .PRE is assumed for the input file and an extension of .PRG for
  498. the output.  Running PRE/DB and specifying only an input file
  499. causes an output file with the same root name and an extension of
  500. .PRG.  The following are thus equivalent:
  501.  
  502.      pp test.pre test.prg
  503.  
  504.      pp test test
  505.  
  506.      pp test
  507.  
  508. The third method is preferred.
  509.  
  510. When using the preprocessor with Clipper, you may wish to modify
  511. Nantucket's CL.BAT file to
  512.  
  513.      pp %1
  514.      clipper %1
  515.      link %1,,,\clipper\clipper \clipper\extend
  516.  
  517. This automatically invokes PRE/DB as the first stage of the
  518. compilation.
  519.  
  520. Two command line options are supported:  -i and -d.  These must
  521. appear after the file name.  These must appear after the file
  522. name.  The -i turns off case sensitivity.  By default, PRE/DB is
  523. case-sensitive.  This means that symbols such as
  524.  
  525.      test
  526.  
  527. and
  528.  
  529.      TEST
  530.  
  531. are different.  Using the -i option makes them equivalent.
  532.  
  533. The -d option is used to define a symbol on the command line.
  534. For example,
  535.  
  536.      pp test -dRick
  537.  
  538. would define the symbol "Rick."  A subsequent test such as
  539.  
  540.      #ifdef Rick
  541.  
  542. would then evaluate to true.
  543.  
  544.  
  545. Line Numbers
  546.  
  547. PRE/DB maintains line numbers between the input and the output
  548. file.  A given program statement in the source file resides at
  549. the same line number in the output file as it does in the input
  550. file.  This is important because compile and runtime errors, and
  551. debugger line numbers, refer to line numbers in the output file,
  552. but the programmer is working with the input file.
  553.  
  554. There is one exception to this rule.  When a #include file
  555. contains program code, rather than preprocessor directives, the
  556. lines of code are include as-is in the output file.  For this
  557. reason, use of program code in #include files is not recommended.
  558.  
  559.