home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / vrac / chkarg.zip / CHECKARG.DOC < prev    next >
Text File  |  1994-09-10  |  16KB  |  411 lines

  1.  
  2.                             CheckArg v1.0
  3.                    Function-Argument Type Checking
  4.                                9/10/94
  5.  
  6.          Copyright (C) 1994 All rights reserved. Paul Long
  7.                        CompuServe: 72607,1506
  8.                  Internet: Paul_Long@ortel.org
  9.                            pci!plong@ormail.intel.com
  10.  
  11.                             At A Glance
  12.                             -----------
  13.              // test.prg
  14.              #include "checkarg.ch"
  15.              // Generates the following run-time error
  16.              //    because function expects numeric.
  17.              DoIt("Now")
  18.              function DoIt(nHowMuch)
  19.              return nil
  20.  
  21.          ┌──────────────────────────────────────────────┐
  22.          │  C is an invalid type for parameter nHowMuch │
  23.          │   of module DOIT, called from TEST/5.        │
  24.          │                                              │
  25.          │   Quit    Skip    Skip Module    Skip All    │
  26.          └──────────────────────────────────────────────┘
  27.  
  28.  
  29. Introduction
  30. ------------
  31. CheckArg performs type checking on function and procedure arguments
  32. based on Hungarian notation without source-code changes.  To use
  33. CheckArg, your parameter names must use the notation that has become
  34. somewhat of a standard in the Clipper programming community.  For
  35. example, an array parameter must start with a lower-case "a", as in
  36. aCons, and a numeric must start with a lower-case "n", as in nRequested.
  37.  
  38. CheckArg is capable of performing the following checks:
  39.  
  40. 1. Argument types.
  41. 2. Parameter names to assure that they conform to Hungarian notation.
  42.    This is especially useful in larger shops in order to enforce naming
  43.    conventions.
  44. 3. Missing required arguments.  This relies on a non-standard naming
  45.    convention, e.g., nuEnd for an optional numeric and nEnd for a
  46.    required numeric, and is therefore initially turned off.
  47. 4. Extra arguments that the called function could not possibly be
  48.    expecting because no parameters are defined for them.  This may not
  49.    be considered a transgression by some programmers so it is initially
  50.    turned off.
  51.  
  52.  
  53. LIMITED WARRANTY AND REMEDIES
  54. -----------------------------
  55. CHECKARG IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  56. EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO WARRANTIES OF
  57. PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  58. FUNCTIONALITY, OR COMPLETENESS.  IN NO EVENT WILL PAUL LONG BE LIABLE TO
  59. YOU FOR ANY DAMAGES, INCLUDING INCIDENTAL OR CONSEQUENTIAL DAMAGES,
  60. ARISING OUT OF THE USE OF THE PROGRAM, EVEN IF ADVISED OF THE
  61. POSSIBILITY OF SUCH DAMAGES.
  62.  
  63.  
  64. Integration
  65. -----------
  66. The following steps are required to integrate CheckArg into your code:
  67.  
  68. 1. Compile the source files in which you want to perform type checking with
  69.    checkarg.ch included at the top of the file.
  70. 2. Compile (with the options, /a/w/n) and link checkarg.obj into the
  71.    executable.
  72.  
  73.  
  74. Compile-time Control
  75. --------------------
  76. Normally checking is not enabled.  Identifiers defined on the
  77. compilation command line control this.  Checking is enabled by defining
  78. the DEBUG identifier.  To always enable type checking regardless of
  79. whether DEBUG is defined, define CHECKARG on the command line. Likewise,
  80. to disable type checking, define NOCHECKARG.  If both are specified,
  81. CHECKARG takes precedence over NOCHECKARG.  Run-time control is affected
  82. by the functions that are described in the section, Modifying Default
  83. Behavior.
  84.  
  85.  
  86. Requirements
  87. ------------
  88. 1. Hungarian notation used for function and procedure parameter names.
  89. 2. Short or long names used for the FUNCTION and PROCEDURE keywords, not
  90.    anything in between, such as FUNCTI or PROCED.
  91. 3. Clipper 5.2.
  92.  
  93.  
  94. Type checking in OOP
  95. --------------------
  96. In a typeless, pure object-oriented programming language such as
  97. Smalltalk, arguments have no type.  Therefore, argument type checking
  98. such as that performed by CheckArg would be useless.  With OOP
  99. extensions such as Class(y), Clipper becomes a hybrid OOPL like C++.
  100. As a result, Clipper OO programs tend to use objects for some
  101. medium-to-large-grained entities, such as windows, and conventional
  102. types for low-level entitites, such as record count and list of field
  103. names.  Therefore, it still makes sense to use CheckArg in an
  104. object-oriented program.
  105.  
  106.  
  107. Possible Enhancements
  108. ----------------------
  109. Support other versions of Clipper.
  110. Allow to be used with other products that have a function UDC, such as
  111.    Class(y).
  112. Ignore "self" parameter for use with Class(y)?  General solution would
  113.    be to let user provide an array of parameter names to ignore.
  114. Allow user to define type indicators to ignore.  For example, "h" if
  115.    they use that for file handles, as in hSource.  Eventually, let the user
  116.    define how these types are to be type checked by CheckArg.
  117. Optionally check all elements of an array argument instead of just the
  118.    first one?
  119. Allow user to provide a code block for error logging.
  120. Allow user to provide a code block to replace CheckArg's error reporting
  121.    mechanism.
  122. For bad-type error, try to display actual value, not just type.
  123. Allow user to define their own non-standard naming convention.
  124. Detect and optionally ignore non-Hungarian parameter names.  For
  125.    example, if "custno" is encountered, assume that no type checking is
  126.    to be performed.
  127. Allow typing prefix to be used without a base, as in just "n" for a
  128.    numeric.  Presently an uppercase character must be present after the
  129.    typing prefix.
  130. Allow user to indicate that no type checking is to be performed on a
  131.    particular function, such as NOCHECK FUNCTION DoIt(nThisMuch).  For
  132.    the time being, using an otherwise illegal keyword variation, such as
  133.    FUNCT fakes out CheckArg.  Yucko.
  134. Other type checking, such as on return values and initializers.
  135.  
  136.  
  137. Parameter-name Syntax
  138. ---------------------
  139. In general, a parameter name consists of a type prefix and a base.  The
  140. base must begin with an uppercase letter to distinguish it from the
  141. all-lower-case prefix.  The prefix is either one or two characters long.
  142. The first character is the type indicator; the second, the modifier.
  143.  
  144. The type indicator is either a scalar (b, c, d, l, m, n, o, or x) or an
  145. array (a).  "Any type" is indicated by x and may be redefined to another
  146. character with the CAAnyChars() function.  The other type indicators are
  147. standard Clipper types, such as those returned by VALTYPE().
  148.  
  149. The array type can be used with a type indicator as its modifier.  This
  150. indicates that the parameter is an array of the specified type.  For
  151. example, anSelected is an array of numerics.  Noteable array parameter
  152. names include, for example, axList, aList, and aaList.  The first two
  153. are arrays of any type; the third is an array of arrays.  An array of
  154. arrays of a particular type cannot be expressed using this naming
  155. convention.  For example, it is illegal to express an array of arrays of
  156. character strings as aacGrid.
  157.  
  158. When CheckArg checks whether a passed value is of the proper type for an
  159. array parameter with a type-indicator modifier, it only checks the first
  160. element in the array.  This is to save time.  All elements are assumed
  161. to be of the same type.
  162.  
  163. The u modifier indicates that the parameter may be undefined, or, in
  164. other words, is optional.  Examples include luSoftSeek and auText.  This
  165. is the only modifier that may be used with scalars.  When used to modify
  166. the array type, it indicates an optional array argument, not an array of
  167. undefined's.  The CAOptChars() function redefines the character that
  168. CheckArg recognizes for this modifier.  The CACheckReq() function
  169. determines whether CheckArg assures that required parameters--those
  170. without the u modifier--are actually passed a value.
  171.  
  172.  
  173. Backus-Naur Form:
  174.  
  175. The following is the Backus-Naur Form, or BNF, of parameter names that
  176. CheckArg expects.  This means of syntax specification is very exacting
  177. but a bit hard to read, especially if you are not used to reading BNF.
  178. ::= means "is the same as," | means "or," <> identifies an intermediate
  179. grammar by name, [] means "is optional."
  180.  
  181. scalar ::= b | c | d | l | m | n | o | <any>
  182. any ::= x
  183. array ::= a
  184. undefined ::= u
  185. scalar prefix ::= <scalar> [ <undefined> ]
  186. array prefix ::= <array> [ <array modifier> ]
  187. array modifier ::= <scalar> | <undefined>
  188. prefix ::= <scalar prefix> | <array prefix>
  189. upper ::= A | B | ... | Y | Z
  190. digit ::= 0 | 1 | ... | 8 | 9
  191. lower ::= a | b | ... | y | z
  192. id char ::= <upper> | <lower> | <digit>
  193. id chars ::= <id chars> | <id char>
  194. base ::= <upper> <id chars>
  195. name ::= <prefix> <base>
  196.  
  197.  
  198. Syntax Diagram:
  199.  
  200. If you found BNF hard to understand, rest your eyes and take a look at
  201. the following syntax diagram.  It is kind of loose, but it gets the
  202. point across a little easier.  | mean "is optional."
  203.  
  204.       b| |
  205.       c| |
  206.       d| |
  207.       l|u|
  208.       m| |
  209.       n| |
  210.       o| |
  211.       x| |
  212.  
  213.       t m N a m e
  214.  
  215.        |a|
  216.        |b|
  217.        |c|
  218.        |d|
  219.       a|l|
  220.        |m|
  221.        |n|
  222.        |o|
  223.        |x|
  224.        |u|
  225.  
  226.  
  227. Examples:
  228.  
  229. ndStart              Clipper meta-syntax, such as this, is not
  230.                         supported--you cannot specify a list of possible
  231.                         types, only one.
  232. xStart               Any type (no type checking)
  233. luFull               Optional logical
  234. nLedgers
  235. oWExam
  236. aRecords
  237. axRecords            Equivalent to aRecords.
  238. auRecords            An optional array, not an array of optional values.
  239.  
  240.  
  241. Error Messages
  242. --------------
  243. When CheckArg detects an error, it displays an error box containing a
  244. description of the error and gives the user the following options:
  245.  
  246.    Quit - Terminate the program, close all open files, and return to the
  247.       operating system.
  248.  
  249.    Skip - Skip only this transgression.
  250.  
  251.    Skip Function - Discontinue type checking for this function for this
  252.       and all subsequent calls.
  253.  
  254.    Skip All - Discontinue all type checking.  Can be turned back on from
  255.       within the program by executing CASkipAll(.t.).
  256.  
  257. The possible error messages are:
  258.  
  259.    <cType> is an invalid type for parameter <cArg> of module <cModule>,
  260.    called from <cModule>/<nLine>
  261.  
  262.    <cArg> is an invalid parameter name in module <cModule>,
  263.    called from <cModule>/<nLine>
  264.  
  265.    <nExtra> extra argument(s) passed to module <cModule>,
  266.    called from <cModule>/<nLine>
  267.  
  268.  
  269. Modifying Default Behavior
  270. --------------------------
  271. The following functions can be called to modify the default behavior of
  272. CheckArg.  They are all accessor functions in that if the argument is
  273. present, CheckArg uses the value.  The value of the previous setting is
  274. returned regardless of whether the argument is present.  Their effect is
  275. program-wide, not just in the function or source file from which they
  276. are called.  They can be called any number of times and at any time.
  277.  
  278.  
  279. CASkipAll(luSkipAll)
  280.  
  281. Example: CASkipAll(.t.)
  282.  
  283. Whether to skip type checking.  This overrides whatever was specified
  284. when a source file was compiled.
  285.  
  286.  
  287. CACheckReq(luStrict)
  288.  
  289. Example: CACheckReq(.t.)
  290.  
  291. Whether to distinguish between optional and required arguments.
  292. Initially false--all arguments are assumed to be optional.  This has to
  293. do with the character that indicates whether an argument is optional.
  294. This character is initially "u" but can be set to any other character
  295. with the CAOptChars() function.
  296.  
  297. Consider the following code segment:
  298.  
  299.    CACheckReq(.f.)      // Do not check whether arguments are required.
  300.    DoIt1()              // No error detected because checking turned off.
  301.    DoIt2()              // Ditto.
  302.  
  303.    CACheckReq(.t.)      // Check whether args are required.
  304.    DoIt1()              // No prob--argument is defined to be optional
  305.                         //    as indicated by the "u" in the name.
  306.    DoIt2()              // Prob--CheckArg would detect that a required
  307.                         //    argument is missing.  Required is
  308.                         //    indicated by the absence of a "u" in the
  309.                         //    name.
  310.  
  311.    function DoIt1(nuHowFar)
  312.    ...
  313.    return nil
  314.  
  315.    function DoIt2(nHowFar)
  316.    ...
  317.    return nil
  318.  
  319.  
  320. CACheckExtra(luExtra)
  321.  
  322. Example: CACheckExtra(.t.)
  323.  
  324. Whether to check for extra arguments in a call to this function.
  325. Initially false.  This could uncover a situation where the caller passes
  326. more arguments than are expected.
  327.  
  328. Consider the following code segment:
  329.  
  330.    CACheckExtra(.f.)    // Do not check for extra arguments.
  331.    DoIt(1, "Hello")     // None detected, although present.
  332.  
  333.    CACheckExtra(.t.)    // Check for extra arguments.
  334.    DoIt(1, "Hello")     // CheckArg would detect that an extra argument,
  335.                         //    "Hello", is present.
  336.  
  337.    function DoIt(nHowFar)
  338.    ...
  339.    return nil
  340.  
  341.  
  342. CAOptChars(cuOpt)
  343.  
  344. Example: CAOptChars("e")
  345.  
  346. Determines what character or characters to use to indicate that an
  347. argument is optional.  Initially "u".  The actual check is turned on and
  348. off with the CACheckReq() function.  If more than one character is
  349. specified, each character can be used individually to indicate an
  350. optional argument--they are synonyms.  For example, "ue" means that
  351. either "u" or "e" indicates an optional argument, not "ue" together.
  352.  
  353.  
  354. CAAnyChars(cuAny)
  355.  
  356. Example: CAAnyChars("v")
  357.  
  358. Determines what character or characters to use to indicate "any
  359. type"--no type checking.  Initially "x".  Like the CAOptChars()
  360. function, if more than one character is specified, each character can be
  361. used individually to indicate "any type."
  362.  
  363.  
  364. CAModName(buModName)
  365.  
  366. Example: CAModName({|nAct| methodname(nAct)})
  367.  
  368. Specifies a block that accepts an activation level and returns the
  369. corresponding module name.  Initially {|nAct| procname(nAct)}.  This is
  370. provided so that the Class(y) methodname() function can be used in place
  371. of procname(), as in {|nAct| methodname(nAct)}.
  372.  
  373.  
  374. Trademarks
  375. ----------
  376. Trademarks are the property of their respective owners.
  377.  
  378.  
  379. Licensing agreement
  380. -------------------
  381. The CheckArg source, header, and included accessory files ("the
  382. software") are the copyrighted work of their author, Paul Long. All
  383. descendant manifestations of the software are also the copyright of Paul
  384. Long. All rights under US and international copyright law are reserved.
  385. You are hereby granted a limited license at no charge to use the
  386. software and to make copies of and distribute said copies of the
  387. software, as long as:
  388.  
  389. 1. Such use is not primarily for profit. "For profit" use is defined as
  390. primary use of the program whereby the user accrues financial benefit or
  391. gain directly from use of the software; for example, integrating the
  392. software with a commercial quality-assurance product would be a use
  393. primarily for profit. "Primary use" is defined as the major use of the
  394. program, or the primary reason for acquiring and using the program.
  395.  
  396. 2. Such copies maintain the complete set of files as provided in the
  397. original distribution set, with no changes, deletions or additions. The
  398. archive storage format may be changed as long as the rest of this
  399. condition is met.
  400.  
  401. 3. Copies are not distributed by any person, group or business that has
  402. as its primary purpose the distribution of free and "shareware" software
  403. by any means magnetic, electronic or in print, for profit. BBS
  404. distribution is allowed as long as no fee is charged specifically for
  405. this software. Bona fide non-profit user's groups, clubs and other
  406. organizations may copy and distribute the software as long as no charge
  407. is made for such service beyond a nominal disk/duplication fee not to
  408. exceed $5.00. For-profit organizations or businesses wishing to
  409. distribute the software must contact the author for licensing
  410. agreements.
  411.