Tag Archives: BREAK
Harbour hvm Functions
Harbour Virtual Machine Functions
AEval | Evaluates the subscript element of an array |
CLIPINIT | Initialize various Harbour sub-systems |
dbEval | Performs a code block operation on the current Database |
Do | Calls a procedure or a function |
Eval | Evaluate a code block |
HB_PValue | Retrieves the value of an argument |
HB_ForNext | Inline FOR…NEXT loop |
PCount | Retrieves the number of arguments passed to a function |
ProcFile | This function allways returns an empty string |
ProcLine | Gets the line number of the current function on the stack |
ProcName | Gets the name of the current function on the stack |
Break()
BREAK()
Exits from a BEGIN SEQUENCE block
Syntax
BREAK( <xExp> )
Arguments
<xExp> is any valid expression. It is always required. If do not want to pass any argument, just use NIL.
Description
This function passes control to the RECOVER statement in a BEGIN SEQUENCE block.
Examples
Break( NIL )
Compliance
Clipper
Files
Library is vm
Seealso
BEGIN SEQUENCE
C5DG-6 DBFNDX Driver
Clipper 5.x – Drivers Guide
Chapter 6
DBFNDX Driver Installation and Usage
DBFNDX is the dBASE III PLUS compatible RDD for Clipper. The DBFNDX driver uses the Clipper driver architecture to access dBASE III PLUS compatible index files within a Clipper program.
In This Chapter
This chapter explains how to install DBFNDX and how to use it in your applications. The following major topics are discussed:
. Overview of the DBFNDX RDD
. Installing DBFNDX Driver Files
. Linking the DBFNDX Driver
. Using the DBFNDX Driver
. Compatibility with dBASE III PLUS
Overview of the DBFNDX RDD
The DBFNDX database driver allows creation, access, and updating of dBASE III and dBASE III PLUS compatible index (.ndx) files. Index files (.ndx) created with Clipper are exactly the same as those created by dBASE III PLUS. All operations that can be performed on standard Clipper index (.ntx) files can be performed on (.ndx) files using the DBFNDX database driver.
In a network environment, the DBFNDX driver supports the Clipper file and record locking scheme. The multiuser behavior is the same as the default DBFNTX driver. This means that the DBFNDX database driver supports concurrent access to (.ndx) files between Clipper applications only. Concurrent access to (.ndx) files between dBASE III PLUS and Clipper programs is not supported.
Important! Updating database (.dbf) and index (.ndx) files shared between dBASE III PLUS and Clipper programs may corrupt the (.dbf) and any of its associated (.ndx) files.
Installing DBFNDX Driver Files
The DBFNDX database driver is supplied as the file, DBFNDX.LIB.
The Clipper installation program installs this driver in the \CLIPPER5\LIB subdirectory on the drive that you specify, so you need not install the driver manually.
Linking the DBFNDX Database Driver
To link the DBFNDX database driver into an application program, you must specify DBFNDX.LIB to the linker in addition to your application object files (.OBJ).
1. To link with .RTLink using positional syntax:
C>RTLINK <appObjectList> ,,, DBFNDX
2. To link with .RTLink using freeformat syntax:
C>RTLINK FI <appObjectList> LIB DBFNDX
Note: These link commands all assume the LIB, OBJ, and PLL environment variables are set to the standard locations. They also assume that the Clipper programs were compiled without the /R option.
Using the DBFNDX Database Driver
To use (.ndx) files in a Clipper program:
1. Place a REQUEST DBFNDX at the beginning of your application or at the top of the first program file (.prg) that opens a database file using the DBFNDX driver.
2. Specify the VIA “DBFNDX” clause if you open the database file with the USE command.
-OR-
3. Specify “DBFNDX” for the <cDriver> argument if you open the database file with the DBUSEAREA() function.
-OR-
4. Use RDDSETDEFAULT(“DBFNDX”) to set the default driver to DBFNDX.
Except in the case of REQUEST, the RDD name must be a literal character string or a variable. In all cases it is important that the driver name be spelled correctly.
The following program fragments illustrate:
REQUEST DBFNDX . . . USE Customers INDEX Name, Address NEW VIA "DBFNDX"
-OR-
REQUEST DBFNDX RDDSETDEFAULT( "DBFNDX" ) . . . USE Customers INDEX Name, Address NEW
Using (.ntx) and (.ndx) Files Concurrently
You can use (.ndx) and (.ntx) files concurrently in a Clipper program like this:
REQUEST DBFNDX
// (.ntx) file using default DBFNTX driver USE File1 INDEX File1 NEW
// (.ndx) files using DBFNDX driver USE File2 VIA “DBFNDX” INDEX File2 NEW
Note, however, that you cannot use (.ndx) and (.ntx) files in the same work area. For example, the following does not work:
USE File1 VIA "DBFNDX" INDEX File1.ntx, File2.ndx
Compatibility with dBASE III PLUS
When accessing dBASE III PLUS (.ndx) files, there are several compatibility issues of which you must be aware. These issues are discussed below.
Supported Data Types
The DBFNDX database driver supports the following data types for key expressions:
. Character
. Numeric
. Date
This is consistent with dBASE III PLUS.
The DBFNDX database driver does not support indexing with logical key expressions as does the default DBFNTX database driver. This is actually a dBASE III PLUS limitation and is not supported by the DBFNDX driver in order to enforce compatibility with dBASE III PLUS.
To work around this limitation, index logical values by converting them to character values like this:
INDEX ON IIF(<lExp>, "T", "F") TO <logicalIndex>
Supported Key Expressions
When you create (.ndx) files using the DBFNDX driver, you must use only Clipper or user-defined functions compatible with dBASE III PLUS. Use of the other functions will render the (.ndx) file unreadable in dBASE III PLUS.
FIND vs SEEK
In Clipper, you can use the FIND command only to locate keys in indexes where the index key expression is character type. This differs from dBASE III PLUS where FIND supports character and numeric key values.
Note: In Clipper programs, always use the SEEK command or the DBSEEK() function to search an index for a key value.
The DBFNDX driver lets you recover from a data type error raised during a FIND or SEEK. However, since Error:canDefault, Error:canRetry, or Error:canSubstitute are set to false (.F.), you should use BEGIN SEQUENCE…END to handle a SEEK or FIND data type error. Within the error block for the current operation, issue a BREAK() using the error object the DBFNDX database driver generates, like this:
bOld := ERRORBLOCK({|oError| BREAK(oError)})
.
.
.
BEGIN SEQUENCE
SEEK xVar
RECOVER USING oError
// Recovery code
END
.
.
.
ERRORBLOCK(bOld)
There is an extensive discussion of the effective use of the Clipper error system in the Error Handling Strategies chapter of the Programming and Utilities guide.
Sharing Data on a Network
As mentioned above, the DBFNDX driver does not support dBASE III PLUS file and record locking schemes. Instead, the DBFNDX driver supports the DBFNTX file and record locking scheme. This means that if the same database and index files are open in Clipper and dBASE III PLUS, Clipper program locks are not visible to dBASE III PLUS and vice versa.
Warning! Database integrity is not guaranteed and index corruption will occur if Clipper and dBASE III PLUS programs attempt to write to a database or index file at the same time. For this reason, concurrent use of the same database (.dbf) and index (.ndx) files by dBASE III PLUS and Clipper programs is strongly discouraged and not supported.
Compatibility with dBASE IV
Specific compatibility with dBASE IV is provided through the DBFMDX driver. It includes (.dbf), (.mdx), and (.dbt) file format compatibility and is described in detail in the previous chapter.
Summary
In this chapter, you were given an overview of the features and benefits of the DBFNDX RDD. You learned how to link this driver and how to use it in your applications, and were given an overview of the compatibility issues.
C5_BREAK
BREAK() Branch out of a BEGIN SEQUENCE...END construct ------------------------------------------------------------------------------ Syntax BREAK(<exp>) --> NIL Arguments <exp> is the value passed to the RECOVER clause, if any. Note that <exp> is not optional. NIL may be specified if there is no break value. Returns BREAK() always returns NIL. Description The BREAK() function is identical in functionality to the BREAK statement. The function must be executed during a SEQUENCE. BREAK() has the advantage that, as an expression, it can be executed from a code block. Examples . This example illustrates exiting a SEQUENCE from a code block: bSave := ERRORBLOCK( {|x| BREAK(x)} ) BEGIN SEQUENCE . . . RECOVER USING objError . . . END ERRORBLOCK(bSave) Files Library is CLIPPER.LIB.
See Also: BEGIN SEQUENCE
CT System Information – Introduction
Introduction The functions in this chapter provide system information about the operating system (MS-DOS), the BIOS, and hardware. It determines a large number of system facts and settings -- from the DOS-COUNTRY setting to the mathematical coprocessor. It is even possible to warm or cold boot a computer from within a program. In addition, you can query and set DOS VERIFY and BREAK.
C5 Error Management
Clipper Error Management
You may encounter several categories of error messages when you develop applications in Clipper. Run-time errors occur when your application hits a snag, and Clipper gives you other messages when you compile and link the application.
You will discover that the greatest number of messages are returned to you by the Clipper Compiler. You don’t risk missing error messages by using a third-party linker.
Clipper’s Run-Time Errors
One product enhancement in the Summer ’87 release of Clipper is a total revamping of error handling. In the past, most error messages would prompt the operator to ‘Quit, Abort or Ignore’. The Summer ’87 release no longer routinely prompts the operator but simply
– present an error message, wich cities the
– procedure name,
– line number, and a simple explanation of the error;
– closes all files; and
– return to DOS.
There are two types of errors in Clipper applications;
– recoverable and
– non-recoverable.
‘Recoverable Errors’ are ones that you can trap and deal with in your applications. You may not always be able to fix the problem, but you can avoid aborting to DOS. This category represents the bulk of errors you will encounter.
‘Non-recoverable’ errors can be introduced by C or assembly routines, corrupted data files, hardware errors and so on. There is no way to handle nonrecoverable errors inside the application.
There are six basic error groups. Nearky all of them have to do with ‘source code errors’ and they occur because you may have tried to add a character string to a number, or you tried to print a variable that doesn’t exist, and so on. You will find 96 percent of potential errors that happen when operators type things that make the program “hiccup”. These errors are also programmer’s responsibility. In some way, the programmer didn’t validate the user input well enough to keep a request for nonexistent files from being processed, or the error occurs for some other similarly pedestrian reason.
Whenever you realize that some errant variable might cause a problem, you have half of the problem solved. Fully half of the battle is seeing what can go wrong – and why.
The other half of the battle is developing an error trap that will catch the bugs before they trigger a nonrecoverable error. What do you do when a user tries to duplicate account number ? What do you do when a record
locks fails ?
Trapping Errors with the
BEGIN SEQUENCE Command
Clipper gives you some interesting tools to trap error conditions before they can damage your application. For example, the Summer ’87 release include a new command construct, the BEGIN SEQUENCE command. BEGIN SEQUENCE has the following syntax:
BEGIN SEQUENCE program code ... BREAK program code ... END program code ... && Usually error recovery procedures.
The BEGIN SEQUENCE command is similar to a DO WHILE loop in the contruction of its code. Unlike the DO WHILE loop, however, BEGIN SEQUENCE is meant to make an umbrella over a group of procedures. Any time the BREAK command is encountered, control of the program immediately passes to the first line after the END statement. Some Clipper programmers use BEGIN SEQUENCE as a sneaky way of emulating the unsupported RETURM TO MASTER command, but its actual intent is to enable you to program your own disaster recovery routines.
The BEGIN SEQUENCE command is most useful in keeping an error condition from exiting the program and displaying the DOS prompt. See the BEGIN SEQUENCE command listing in Part III for more information.
Recoverable Error Functions
The nonfatal or recoverable errors are divided into six basic groups. CLIPPER.LIB include six error-handling function – one for each of the six basic error groups. The error handling functions are written in Clipper code that you can alter to customize your application’s error handling. These are exracted for you on the Clipper disks in a file called ERRORSYS.PRG. The six group are:
Database errors
Expression errors
Miscellaneous errors
Open errors
Print errors
Undefined errors
Note: The file ALTERROR.PRG on your Clipper disks contains a set of error functions specifically designed for use with the Clipper debugger.
Producing Your Own Recovery Functions
You can modify the default error functions by replacing them with user-defined functions that have the same name. Group these replacement functions into a file and compile them. When it comes time to link your program together, add that .obj file to the FILES directive to the linker. Do not specify the error object file as the first name in the list. Always put your application’s main module first in the list. As long as your functions have the same name as the ones in CLIPPER.LIB, they will be linked into the program rather than the functions in the library.
Each of the error-handling functions that are supplied with the Clipper library share the same basic syntax:
XXX_ERROR(name, line, info [,model][,_1][,_2][,_3][,_4][,_5]
The XXX in the FUNCTION name is filled with the name of actual function itself.
The ‘name‘ parameter returns a character string equal to the name of the procedure or function that was active when the error was triggered.
The ‘line‘ argument refers to the program line number assigned by the Clipper compiler. If you compiled the application with the -l switch for no line number, this parameter will be zero.
The ‘info‘ (information) parameter contains a character string that describes the error-for example, DATA TYPE MISMATCH or DIVISION BY ZERO.
The ‘model‘ parameter is optional and is not supplied by some of functions When it is supplied, the model argument to the function is the portion of source code that triggered the error.
The _1 ,_2 ,_3 ,_4 ,_5 parameters – if they are supplied by the function – can be of any type; character, numeris, logical, or date. You can look at these as being the parameters that were passed to the command when the error was triggered, and they will contain values that were in effect at the time the error was triggered. The unusual names reflect a desire on the part of the Clipper development team not to conflict with any variable names to be reserved words. Also because Clipper is written in Microsoft C 5.0, you should aviod using using underscore (_) as the first character in a field, file or variable name. This could bugs that seem to make no sense by invoking internal Clipper functions.
By identifying and manupulating the errors and the information associated with an error, you can develop a strategy to recover from that error. To develop recovery procedure, look at each of the error functions individually. In general, the value that is returned by the error function determines what action the Clipper program takes.
The code included in the next six examples is reprinted by permission of Nantucket Corporation and is the actual code found in CLIPPER.LIB. It is also included on your factory disks in a file called ERROR.DOC.
Handling Database Errors
Database errors are classified as those errors that occur during the time
a file is open. This does not include the opening and closing operations.
REPLACE, DELETE, AVERAGE, and similar commands are the types of commands
that can trigger this error message.
The following syntax is for the error-hanfling function DB_ERROR():
*** * * db_error( name, line, info) * FUNCTION db_error PARAM name, line, info
SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Pro- c ' + M->name +; ' line ' + LTRIM(STR(M->line)) +; ', ' + M->info
NOTE BREAK
QUIT
RETURN .F.
After declaring the function name, ‘DB_ERROR()’ recognizes three parameters: ‘name’, ‘line’, and ‘info’.
The function then SETs the DEVICE to the SCREEN so that the error message is displayed even if the application is printing at the time.
The command NOTE BREAK suggests that you might prefer to issue a BREAK to your BEGIN SEQUENCE construct rather that the QUIT.
The ‘info‘ parameter may return one of these messages:
DATABASE REQUIRED
This message occurs when you attempt to access a data file in a work area where none is open.
LOCK REQUIRED
This error message is triggered when your application attempts to perform a command that requires file or record locking. When you have used a data file in a nonexclusive mode, you must continue to follow networking rules throughout the entire application.
EXCLUSIVE REQUIRED
This error message is given whenever your application execute a command that requires exclusive use of a file.
FIELD NUMERIC OVERFLOW
This message indicates an application attempted to write into a field a number that is larger than the length of the field.
INDEX FILE CORRUPTED
This message occurs when an application attempts to manipulate an index file that is damaged.
You can modify DB_ERROR() to perform actions that will try to rectify the situation. Use the value of the variable, ‘info’ to key a DO CASE structure to specify corrective action. For example:
IF info = 'INDEX FILE CORRUPTED'
you could have the function rebuild the index.
You have three choices of action when the DB_ERROR() function is triggered:
– You can perform actions to correct the situation and RETURN the value of the function as true (.T.) RETURNing a true (.T.) retries the command that triggered the error.
– You can return false (.F.) and abort the program to DOS.
– You can issue a BREAK statement as part of a BEGIN SEQUENCE contruct. The control of the program would revert to the next line following the END command. Your program then can back out of the situation as gracefully as possible, repaint the main menu, and start fresh.
Handling Expression Errors
Expression errors generally are associated with conditions such as division by zero or data type mismatches. A good example of this would be a command in your ptogram that tries to add a number to a character string. This causes a data type mismatch error to occur.
This error occurs whenever a Clipper application contains an invalid expression. For example, in VAL(‘AU-H20’) the value of function has no mathematical meaning.
The following syntax is for the error-handling function EXPR_ERROR();
*** * * expr_error(name, line, info, model, _1, _2, _3 ) * FUNCTION expr_error PARAM name, line, info, model, _1, _2, _3
SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Proc ' + M->name + ' line ' +; LTRIM(STR(M->line)) + ', ' + M->info
QUIT
RETURN .F.
The ‘model‘ portion of the function argument contains the expression that triggered the error. In all cases, that expression is delivered as a character string. The operand parameters have values equal to the variables in effect when the error was triggered. In other words, the model is returned as a piece of code with the operands substitued as variable elements of the code. For example:
TONE( c#,277 )
would return the following values in EXPR_ERROR():
info = 'Expression Error' model = 'TONE(_1,_2)' _1 = 'c#' _2 = 277
If you devise a lookup function so that your EXPR_ERROR function can “know” what the TONE() function should look like, it is fairly simple matter to compare data types of the operands to find out that _1 should be numeric. The function then could substitute a numeric value into _1 and RETURN &model. This would reevaluate the expression, and control would be passed to the next line in the program if the error condition was corrected.
The ‘information’ parameter of the EXPR_ERROR() function returns one of the following messages:
TYPE MISMATCH
This error occurs when two different types of variable are in some way joined or operated upon jointly.
SUBSCRIPT RANGE
This error occurs if your Clipper application attempts to use an array element that does not exist.
ZERO DIVIDE
This error occurs whenever your Clipper application attempts to divide any number by 0, which is mathematically meaningless and therefore illegal.
Handling Miscellaneous Errors
Miscellaneous errors consist of lower-level errors that usually would not be considered fatal. This function also acts as a “dust bin,” handling those errors that the other error functions are not equipped to handle.
The following syntax is for the error-handling function MISC_ERROR():
*** * * misc_error(name, line, info, model) * FUNCTION misc_error PARAM name, line, info, model SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Proc ' + M->name + ' line ' + ; LTRIM(STR(M->line)) + ', ' + M->info
NOTE BREAK
QUIT
RETURN .F.
You cannot use the MISC_ERROR() function to return the model argument as executable code, as you can with the EXPR_ERROR() function.
To recover from a MISC_ERROR(), you can try retry the operation by returning true (.T.) after making some changes to variables. You can issue the BREAK command to jettison out of a BEGIN SEQUENCE construct, or you can abort to DOS.
The ‘info’ parameter may return one of the following messages:
TYPE MISMATCH
The TYPE MISMATCH error message occurs when a REPLACE command attempts to place the wrong data type into a field. For example, trying to place “123” into a numeric field would cause a type-mismatch, miscellaneous error.
Note: This is different from the TYPE MISMATCH in the expression error-handling function. The context of the error determines which function is called. If there is not a write to the file, the expression error will be triggered. If it involves writing to a file, the miscellaneous error will be called.
RUN ERROR
The RUN ERROR error message occurs when a Clipper application attempts to run another executable file by loading a new COMMAND.COM into memory. The underlying cause of this error can be determined by reading the value of DOSERROR() function. The ‘model’ parameter contains the portion of your Clipper code that triggered the error.
Handling Open Errors
Open errors occur when file-opening operations fail. Special consideration is given to opening data files. When the request to open a data file is not honored by DOS (usually by passing along a network operating system message), an evaluation is made. If NETERR() is true and the ‘model’ paramater is USE, the error function simply returns a value of false. In such a case, the application ignores the error.
This is why you have to structure the USE command the way you do in a Clipper application. If your application tries to open a data file and fails, the error is ignored, and the next portion of code is executed. If the next portion of code tries to open index files for a data file that could not be opened, a second, more serious, error occurs. The open error on the index files is not ignored, and the application aborts to DOS.
The following syntax is for the error-handling function OPEN_ERROR() :
*** * * open_error(name, line, info, model, _1) * FUNCTION open_error PARAM name, line, info, model, _1
IF NETERR() .AND. model == 'USE' RETURN .F. END
SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Proc ' + M->name + ' line ' + ; LTRIM(STR(M->line)) + ', ' + M->info + ' ' +; M->_1 +' (' + LTRIM(STR(DOSERROR())) + ')' @ 0,65 SAY 'Retry ? (Y/N)'
INKEY(0)
DO WHILE .NOT. CHR(LASTKEY()) $ 'YyNn' INKEY(0) END
IF .NOT. CHR( LASTKEY() ) $ 'Yy' QUIT END
@ 0,0
RETURN .T.
OPEN_ERROR() is the most active of the six types of error-handling functions. First, it terminates itself in the case of USE errors where NETERR() is true. Thise helps you determine what you need to do about unavailable files. (Refer to Chapter 7, “Clipper and Networking” for more information.) Then, OPEN_ERROR() prompts you to retry the operation.
The ‘info’ parameter of the OPEN_ERROR() returns only the message OPEN ERROR. The ‘model’ argument to the function is the command that triggered the error. The operand parameter, _1, is the file name that triggered the error.
To recover from an OPEN_ERROR(), you can return true (.T.) and retry the operation. Returning false ignores the command that created the error. Further error messages are certain if the application tries to perform operations on a file that is not open. You could also issue a BREAK, which would provide you with your own error-recovery facility if you have a BEGIN SEQUENCE construct in your application.
Handling Print Errors
A print error occurs whenever your Clipper application is running DOS 3.1 or higher and is accessible a parallel port that is sensed to be not ready. Users running earlier versions of DOS get the straight DOS ‘Abort, Retry, Ignore?’ error message without being able to trap the error first. Usually, the operator has forgotten to place the printer on-line. This error occurs also when a network spooler is unable to continue receiving output or when you redirect @ … SAY commands to a file with the SET PRINTER TO command, and a disk error occurs.
If the printer has been redirected with MODE to a serial port, an OPEN ERROR error is triggered instead.
The following syntax is for the error-handling function PRINT_ERROR():
*** * * print_error(name, line) * FUNCTION print_error PARAM name, line
SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Proc ' + M->name + ' line ' + ; LTRIM(STR(M->line)) + ', printer not ready'
@ 0,65 SAY 'Retry ? (Y/N)'
INKEY(0)
DO WHILE .NOT. CHR( LASTKEY() ) $ 'YyNn' INKEY(0) END
IF .NOT. CHR( LASTKEY() ) $ 'Yy' QUIT END
@ 0,0
RETURN .T.
The ‘info’ parameter always returns the string PRINTER ERROR.
You can recover from the PRINT_ERROR function by prompting the operator to correct the situation, then returning true (.T.) which will retry the command.
BREAK can be used to terminate the error function and pass control to a custom error-handling portion of your Clipper application.
Returning false (.F.) continues the application without retrying the command that triggered the error message. This can lead to problems because the next command may also access the printer; your program’s operator will see an endless srtring of error messages.
Because the error message automatically SETs DEVICE TO SCREEN, a retry would cause any @ … SAY commands to be displayed on the screen, causing another error. If you are doing to develop your own PRINT_ERROR() function, use a semaphore variable that will store the condition of the SET DEVICE command. In that way, your error-recovery code will “know” if it must SET DEVICE TO PRINT in order to resume without further errors.
Handling Undefined Errors
The UNDEF_ERROR() function is triggered whenever you refer to a variable that has not been defined. You can consider this to be any situation in which the TYPE() function would return a value of ‘U’.
The following syntax is for the error-handling function UNDEF_ERROR():
*** * * undef_error(name, line, info, model, _1) * FUNCTION undef_error PARAM name, line, info, model, _1
SET DEVICE TO SCREEN @ 0,0 @ 0,0 SAY 'Proc ' + M->name + ' line ' + ; LTRIM(STR(M->line)) + ', ' + M->info + ' ' + M->_1
QUIT
RETURN .T.
The ‘info’ parameter returns one of the following character strings:
UNDEFINED IDENTIFIER
This message is given whenever you attempt to access a memory variable name that does not exits.
NOT AN ARRAY
This error message indicates your Clipper application accessed an array element that does not exist, or the array itself does not exists.
MISSING INTERNAL
This error message occurs whenever your application refers to a user-defined function or procedure that has not been declared within the application itself. This would apply also to any function contained in the the Extend library that has not been referenced within the body of the application. This error message usually indicates that a function has been used in either a label or report form but has not been invoked in the application itself. Whenever you use a function in a report form that is not used is the application itself, use the EXTERNAL command so that the compiler includes the function in the .EXE file.
The ‘model’ parameter contains the portion of the source code that triggered the error. The _1 operand contains the name of the unidentified identifier.
In recovering from this error, returning true (.T.) retries the operation. The BREAK command could be used to exit out of a BEGIN SEQUENCE construct to a custom error-handling routine. Returning false (.F.) causes Clipper to close all files and return to DOS.
Nonrecoverable Errors
Yor Clipper application may trigger other errors that are not handled by the previously described error-handling functions. These errors include the following:
INTERNAL ERROR
An INTERNAL ERROR message generally is caused by a corrupted index file. Clipper presentsthe error message and pauses for a key to be pressed. Pressing any key causes Clipper to quit and return to DOS.
DISK FULL
This error occurs when the application is writing a database file back to disk, and the write attempts to go beyond the amount of available disk space. This error message displays a prompt, allowing the user to retry the operation, just in case the cause of the error is a floppy disk that is not ready. Answering ‘No’ to the prompt causes the application to quit and return you to DOS. In essence, there is little real choice here because the pause does not include the opportunity to delete any files.
MULTIPLE ERROR
This is triggered when the error that begins the process is so bad that it cause an error within one of the error functions. Clipper indicates this by posting this error message and prompting you to press any key. When you press any key, the application quits and return to DOS.
OUT OF MEMORY
This error displays when the upper limits of RAM have been reached. Clipper display the error message and pauses; pressing any key causes Clipper to abort and return you to the DOS prompt.
NOT ENOUGH MEMORY
This error happens whenever Clipper senses that the application does not have enough memory to perform an operation. Clipper displays the message and pauses. Pressing any key causes Clipper to quit, close all files, and return you to the DOS prompt.
Error Messages Returned at
Compile and Link Time
During the development cycle, you will get error messages telling you that there are errors in your program. Ninety percent of these errors come from the Clipper compiler. The other 10 percent are presented by the linker.
Compiler Error Messages
The compiler itself is your front-line debugging tools. Most syntactical bugs and errors in your program are caught by the compiler and noted for you.
You can redirect or echo the Clipper error messages to a printer or a file. To redirect Clipper error messages to the printer, simply enter your commands as you normally would, adding a standard argument for DOS output redirection. For example :
CLIPPER prognam > PRN
This sends any output from Clipper to the printer. There are a great number of errors that you might see as you use the compiler. Most are self-explanatory. They tell you the procedure name, the line number of the program, and show you the piece of code that is causing the problem. Clipper also points to problem with caret (^). Figure 8.1 shows a typical Clipper error message.
------------------------------------------------------------------------- Fig. 8.1 Clipper error message. -------------------------------------------------------------------------
C:\iii\clip\book>clipper dbedit The Clipper Compiler, Summer '87 Copyright (c) Nantucket Corp 1985-1987, All Rights Reserved, Microsoft C Runtime Library Routines, Copyright (c) Microsoft Corp 1985-1987, All Rights Reserved,
Compiling DBEDIT.PRG line 9: rest of line ignored CLEAR ALL the extra stuff off the screen
1 error Code Pass 1 Code Pass 2 Code size 443, Symbols 160, Constants 181
C:\iii\clip\book>
-------------------------------------------------------------------------
Documenting all of the errors that the compiler can return to you would be nearly impossible. Almost any command with an incorrect syntax will produce the same type of error message that dBASE III Plus delivers in its interpretive mode except that Clipper does not ask if you want to cancel, suspend, or ignore. Other error messages, however are fairly common and require only small amounts of clarification. The following is an alphabetical list of errors returned by the compiler.
CASE WITHOUT DO CASE
This error message suggest that you have placed a CASE comparison in your program but forgot to begin with a DO CASE statement.
ELSE WITHOUT IF
You have probably placed an ELSE statement in the wrong place, The compiler does not find a matching IF for ELSE.
ENDCASE WITHOUT DO CASE
This error normally occurs when you remove a DO CASE statement from a program but forget to erase the ENDCASE at the bottom. Clipper is telling you that it has found an ENDCASE statement but no DO CASE statement to open the construct.
ENDDO WITHOUT WHILE
The compiler has found an ENDDO that is unbalanced. There is no corresponding DO WHILE to open the construct.
ENDIF WITHOUT IF
This error is most likely to occur when you are nesting IF … ELSE … ENDIF statements or have erased an IF construct but have forgotten to remove the ENDIF.
EXIT WITHOUT DO WHILE
Clipper has found an EXIT command, requesting Clipper to drop out of a DO WHILE loop, but Clipper does not find a DO WHILE construct.
FATAL AT <n> - INVALID PROCEDURE MODE
This error is triggered if two programs contain the same procedure name or if you have created two user-defined functions with the same name. This message is displayed only to the screen and is not affected by DOS redirection.
ILLEGAL DEVICE
You have a syntax error in a SET DEVICE TO command.
ILLEGAL VALUE
This is triggered whenever the left side of an expression using the equal sign (=) is an illegal expression, or the STORE command tries to perform an illegal variable initialization.
– for example, STORE 8 TO 5+5.
LOOP WITHOUT DO WHILE
Clipper has located a LOOP command that is not inside a DO WHILE construct.
MISSING SECOND QUOTE
This error is triggered by omitting the closing quotation marks on string expressions.
NEXT WITHOUT FOR
This error message means that a NEXT command has no balancing FOR command.
OTHERWISE WITHOUT DO CASE
Clipper has found an OTHERWISE command that is not inside a DO CASE construct.
REST OF LINE IGNORED
This error message is displayed usually when you have given an illegal argument or option to a command. The illegal portion is to the right of the command verb, so it is looked at as unnecessary baggage. Clipper simply ignores the existence of anything else on that line.
SYMBOL REDEFINITION ERROR
This error message is triggered usually when a procedure name has been duplicated in an application.
TOO MANY CONSTANTS
The compiler is limited to a 64K constant table to keep track of elements of the program while it is being compiled. If you get this message, break the program into two seperate object files. Include both object file names in the linking command.
TOO MANY SYMBOLS
The compiler is limited to 64K of memory for symbols table. If you receive this error message from Clipper, divide your program in half and compile it into two object files. Specify both object file names to the linker when you prepare the .EXE file.
UNBALANCED DO CASE
The compiler has found a DO CASE statement without an ENDCASE.
UNBALANCED DO WHILE
The compiler has found a DO WHILE that is not terminated by an ENDDO.
UNBALANCED FOR/NEXT
Clipper has found a FOR command without the NEXT statement that terminates it.
UNBALANCED IF/ELSE
Clipper has found an IF without a terminating ENDIF.
VERB NOT RECOGNIZED
Clipper does not recognize a command verb or keyword that has been included in your command. Usually, this error is caused by a spelling error.
PLink86 Plus Messages
PLink86 Plus, supplied with Clipper, is a product published by Phoenix Technologies, the same company that produces compatible ROMs for computer manufacturers. Most people simply refer to it as PLink or PLink86. PLink86 Plus is used widely by software delevopper.
PLink86 Plus is included with Clipper because of its capability to produce overlay files efficiently. The copy of PLink86 Plus included with your Clipper package has been modified by Nantucket to be Clipper-specific. Some of the error messages that PLink86 Plus is capable of returning actually should never be seen by a Clipper programmer unless he or she is plugging in assembly language routines and having problems. Each of these error messages is coded by number. If you experience problems with PLink86 Plus, refer to Nantucket technical support for help in resolving your problem. The following discussion centers on the messages most often occuring in the Clipper environment. For a complete listing of the PLink86 Plus error messages, see the Clipper manual.
The messages that are delivered by Plink86 Plus are broken into two categories: warnings and errors.
PLink86-Plus Warning Messages
Warning 3: This error message is triggered when a ‘group’, a set of memory segments that must be able to fit within a 64K frame in memory, exceeds the limit. This warning message happens usually when you are mixing C and assembly language routines within modules for the Clipper application. Assembly language class and segment names must match those used in the high-level language. If not, assembler segments may be assigned to areas of memory that are not within the 64K frame of the ‘group’. This error message may appear also if you name one of your procedures DATA or SYSTEM. These are reserved words; don’t use them.
Warning 4: A file has been specified in the MODULE command but does not appear in the directory.
Warning 7: Usually, this means you have included the .PRG extension with the file name when you access the CL.BAT batch file. PLink86-Plus is trying to link .PRG files instead of .OBJ files because the batch file specified .PRG as the file extensions.
Warning 8: This warning is usually the first indication of a corrupted object file.
Warning 9: This warning also is an early indication of a corrupted object file.
Warning 11: You have declared the same variable to be public more than once. The compiler ignores the second declaration of the public variable and continues to link the file.
Warning 12 or Warning 13: These warnings are triggered usually when an assembly language module you are linking as part of your program makes an errouneous memory assignment.
Warning 14: This message also deals with assembly language routines assigning memory for stack storage. Using PLink86 Plus and .LIB files from different Clipper versions generates this message also.
Warning 19: This usually indicates that you are nearing the limits of memory in linking your application. PLink86 Plus determines that there is not enough memory to store path names for a file that it cannot locate and will prompt you to enter the path name.
PLink86 Plus Error Messages
PLink86 Plus error messages are grouped into categories that have common roots.
Plink86 Plus File Error Messages
The first group deals wiht errors in the input to the Plink86 Plus command, usually dealing with macro-substituted file names.
Error 1 : This error message indicates that @ files are nested more than three deep or that the @ files contain a circular reference.
Error 2 : A DOS error occurred while trying to read the @ file.
Error 3 : The @ file specified cannot be found.
Error 5 : The Plink86-Plus input line exceeds the maximum lengh of 64 characters.
Error 10: This error message indicates an invalid file name. Plink86 Plus has been given a character string that is an illegal DOS file name.
Error 11: A keyword is missing from the .LNK file.
Error 14: This message indicates that PLink86 Plus is expecting an identifier. A section module segment or symbol name is missing from the .LNK file or was mistyped at interactive input time.
Error 15: An equal sign (=) is missing in the .LNK file.
Error 17: No files have been specified to be linked. Check the .LNK file to make sure the file command is present.
PLink86 Plus Work File Error Messages
Plink86 Plus requires at least 256K of memory to work properly. As PLink86 Plus runs out of memory, it opens a scratch file on disk to hold contents of the link temporarily. The following error messages indicate a problem with the work file.
Error 30: A work file cannot be created, probably because of a lack of disk space.
Error 31: A DOS I/O error happened while Plink86 Plus was writing the .EXE file.
Error 32: PLink86 Plus encountered a DOS I/O error as it was reading the work file.
Error 33: A DOS I/O error occured while Plink86 Plus was positioning the pointer within the file.
Error 34: This error message indicates that you have created an application that is too large for PLink86 Plus to handle. Please check the source code for possible inefficiencies. See the section outlining the SWITCH utility in Chapter 9, “Clipper Tools”.
PLink86 Plus Input Object File Error Messages
These errors involve the object files that have been presented to PLink86 Plus. They genereally indicate a corrupted object file that should be recompiled.
Error 41: Premature end of object file. PLink86 Plus is finding an object file that is a different size from that stated by the header at the beginning of the file. This error message can be triggered also by specifying the .PRG extension to the CL.BAT batch file. This error canbe the result also of high-order bits being turned on when you use WordStar in the document mode as an editor. While rare, this cause is possibility.
Error 42: Fatal read error in object file. This error message indicates that the object file is completely unusable.
Error 43: PLink86 Plus cannot find a specified object file. If PLink86 Plus was not invoked with a batch file, it will prompt you for a path name.
PLink86 Plus Output File Error Messages
This group of errors deals with problems in creating the .EXE file itself.
Error 45: A DOS error has occured as PLink86 Plus tried to creat the .EXE file. The disk is either full or possibly write-protected.
Error 46: Invalid output file type. You probably have included in your .LNK file an output command that specifies an invalid extension to the .EXE file.
Error 47: Fatal disk write error. PLink86 Plus was able to creat the file; but as it was writing the file, the disk drive probably was filled.
Error 48: Fatal read error in output file. PLink86 Plus is unable to read the file it has constructed. This is probably due to a hardware error.
Error 49: Cannot close output file. This error is probably caused by a hardware error or a write-protect error.
Error 50: Cannot construct memory map. The memory map cannot be constructed, probably because the disk is full.
PLink86 Plus Miscellaneous Error Messages
Error 51: Undefined symbol exist. This error occurs when you specify a procedure or function in your program, and the linker cannot find object code to construct it. Usually, you have forgotten to include the EXTEND.LIB in your PLink86 Plus command after including a function from EXTEND.LIB in your application.
Error 54: This error indicates there is not enough random access memory on the computer to run PLink86 Plus.
Error 57: This error indicates a problem with OVERLAY.LIB. Recopy the file from your factory disks.
Error 58: You have created a stack segment in an assembly language program that is too large.
PLink86 Plus Program Structure Error Messages
These error are triggered when there are problems within overlay for your application.
Error 80: Overlays are nested too deeply.
Error 81: There are more ENDAREA statements than BEGINAREA statements in your .LNK file.
Error 82: There are more BEGINAREA statements than ENDAREA statements in your .LNK file.
Error 83: Your application is too large, but it can be compiled if you break the application into a load module with overlays.
PLink86 Plus Diagnostic Error Messages
If you receive error messages greater than 200 from PLink86 Plus PLink86 Plus rest assured that your program could not have caused these error messages. Usually, these error messages indicate that the PLink86 Plus file itself has been corrupted. Recopy PLink86 Plus from the factory disk. If the problem repeats, record the error code and whatever information is necassary to produce repeatable results and contact Nantucket Technical Support.
Summary
In this chapter, you have seen the source code that produces Clipper’s run-time error messages. You should have some idea of how you might resolve them.
You should also be prepared to decipher error messages and warnings from both Clipper and PLink86 Plus. Don’t forget that most link errors occur simply because you have forgotten to declare a file to the linking process.
If you encounter a stubborn linkage problem with a third-party linker, come back to PLink86 Plus and decipher the error message it delivers. Correct the problem, and relink using the linker of your choice.
16:31:41 18/11/1991
C5 Error Handling
C5 Error Handling Commands, Statements and Funtions
Statement :
BEGIN SEQUENCE :
Define a sequence of statements for a BREAK
BEGIN SEQUENCE <statements>... [BREAK [<exp>]] <statements>... [RECOVER [USING <idVar>]] <statements>... END [SEQUENCE]
Functions :
ALTD() :
Invoke the Clipper Debugger
ALTD( [ <nAction> ] ) --> NIL
BREAK() :
Branch out of a BEGIN SEQUENCE…END construct
BREAK( <exp> ) --> NIL
DOSERROR() :
Return the DOS error number
DOSERROR( [ <nNewOsCode> ] ) --> nOsCode
ERRORBLOCK() :
Post a code block to execute when a runtime error occurs
ERRORBLOCK( [ <bErrorHandler> ] ) --> bCurrentErrorHandler
ERRORLEVEL() :
Set the Clipper return code
ERRORLEVEL( [ <nNewReturnCode> ] ) --> nCurrentReturnCode
NETERR() :
Determine if a network command has failed
NETERR( [ <lNewError> ] ) --> lError
OUTERR() :
Write a list of values to the standard error device
OUTERR( <exp list> ) --> NIL
PROCLINE() :
Return the source line number of the current or previous activation
PROCLINE( [ <nActivation> ] ) --> nSourceLine
PROCNAME() :
Return the name of the current or previous procedure or user-defined function
PROCNAME( [ <nActivation> ] ) --> cProcedureName
Error Class :
Provides objects containing information about runtime errors.
Description :
An Error object is a simple object that contains information pertaining to a runtime error. Error objects have no methods, only exported instance variables. When a runtime error occurs, CA-Clipper creates a new Error object and passes it as an argument to the error handler block specified with the ERRORBLOCK() function. Within the error handler, the Error object can then be queried to determine the nature of the error condition.
Error objects can also be returned to the RECOVER statement of a BEGIN SEQUENCE construct with a BREAK statement. Here, the error object can be queried for local error handling. For more detailed information and examples refer to the Error Handling Strategies chapter in the Programming and Utilities guide.
Class Function :
ErrorNew() :
Returns a new Error object.
ErrorNew() --> objError
Exported Instance Variables :
args (Assignable) :
An array of function or operator arguments.
Contains an array of the arguments supplied to an operator or function when an argument error occurs. For other types of errors, Error:args contains a NIL value.
canDefault (Assignable) :
Indicates whether or not default recovery is available.
Contains a logical value indicating whether the subsystem can perform default error recovery for the error condition. A value of true (.T.) indicates that default recovery is available. Availability of default handling and the actual default recovery strategy depends on the subsystem and the error condition. The minimum action is simply to ignore the error condition.
Default recovery is requested by returning false (.F.) from the error block invoked to handle the error. Note that Error:canDefault is never true (.T.) if Error:canSubstitute is true (.T.).
canRetry (Assignable) :
Indicates whether or not a retry is possible after an error.
Contains a logical value indicating whether the subsystem can retry the operation that caused the error condition. A value of true (.T.) indicates that a retry is possible. Retry may or may not be available, depending on the subsystem and the error condition.
Retry is requested by returning true (.T.) from the error block invoked to handle the error. Note that Error:canRetry never contains true (.T.) if Error:canSubstitute contains true (.T.).
canSubstitute (Assignable) :
Indicates if a new result can be substituted after an error
Contains a logical value indicating whether a new result can be substituted for the operation that produced the error condition. Argument errors and certain other simple errors allow the error handler to substitute a new result value for the failed operation. A value of true (.T.) means that substitution is possible.
The substitution is performed by returning the new result value from the code block invoked to handle the error. Note that Error:canSubstitute is never true (.T.) if either Error:canDefault or Error:canRetry is true (.T.).
cargo (Assignable) :
User-definable variable.
Contains a value of any data type unused by the Error system. It is provided as a user-definable slot, allowing arbitrary information to be attached to an Error object and retrieved later.
description (Assignable) :
Character description of the error condition.
Contains a character string that describes the error condition. A zero-length string indicates that the subsystem does not provide a printable description for the error. If Error:genCode is not zero, a printable description is always available.
filename (Assignable) :
Name of the file associated with the error
Contains a character value representing the name originally used to open the file associated with the error condition. A zero-length string indicates either that the error condition is not associated with a particular file or that the subsystem does not retain filename information.
genCode (Assignable) :
Error code number.
Contains an integer numeric value representing a CA-Clipper generic error code. Generic error codes allow default handling of similar errors from different subsystems. A value of zero indicates that the error condition is specific to the subsystem and does not correspond to any of the generic error codes. The header file, Error.ch, provides a set of manifest constants for generic error codes.
operation (Assignable) :
Character description of the failed operation.
Contains a character string that describes the operation being attempted when the error occurred. For operators and functions, Error:operation contains the name of the operator or function. For undefined variables or functions, it contains the name of the variable or function. A zero-length string indicates that the subsystem does not provide a printable description of the operation.
osCode (Assignable) :
Operating system error code number
Contains an integer numeric value representing the operating system error code associated with the error condition. A value of zero indicates that the error condition was not caused by an error from the operating system. When Error:osCode is set to a value other than zero DOSERROR() is updated with the same value.
Error:osCode properly reflects the DOS extended error code for file errors. This allows proper distinction between errors which result from sharing violations (e.g., opening EXCLUSIVE when another process has already opened the file) and access violations (e.g., opening read/write when the file is marked read-only).
For a list of DOS error codes please look at here
severity (Assignable) :
Indicates error severity
Contains a numeric value indicating the severity of the error condition. Four standard values are defined in Error.ch:
Error:severity Values ------------------------------------------------------------ Error.ch Meaning ------------------------------------------------------------ ES_WHOCARES The condition does not represent a failure; the error is informational. ES_WARNING The condition does not prevent further operations, but may result in a more serious error later. ES_ERROR The condition prevents further operations without corrective action of some kind. ES_CATASTROPHIC The condition requires immediate termination of the application.
------------------------------------------------------------
Note that the Clipper runtime support code only generates errors with severities of ES_WARNING or ES_ERROR
subCode (Assignable) :
Subsystem-specific error code number.
Contains an integer numeric value representing a subsystem-specific error code. A value of zero indicates that the subsystem does not assign any particular number to the error condition.
subSystem (Assignable) :
Character description of the subsystem generating the error.
Contains a character string representing the name of the subsystem generating the error. For errors with basic CA-Clipper operators and functions, the subsystem name “BASE” is given. For errors generated by a database driver, Error:subSystem contains the name of the database driver
tries (Assignable) :
Number of times the failed operation has been attempted.
Contains an integer numeric value representing the number of times the failed operation has been attempted. When Error:canRetry is true (.T.), Error:tries can be used to limit the number of retry attempts. A value of zero indicates that the subsystem does not track the number of times the operation has been tried.
Examples :
. This example demonstrates how a file open operation might be handled in an error handler replicating the default CA-Clipper behavior. When, for example, an attempt to open a database file with a USE command fails, control returns to the statement following the offending command:
#include "Error.ch"
#command RETRY => RETURN (.T.) // Retry operation #command RESUME => RETURN (.F.) // Default recovery
//
FUNCTION MyError( objError ) // // Handle file open error IF objError:genCode == EG_OPEN .AND.; objError:canDefault .AND.; NETERR() // RESUME ENDIF . . <other error statements> . RETURN NIL
. This example retries an operation within an error handler a specified number of times:
#include "Error.ch" #command RETRY => RETURN (.T.) // Retry operation #command RESUME => RETURN (.F.) // Default recovery //
FUNCTION MyError( objError ) // Handle printer not ready error IF objError:genCode == EG_PRINT .AND.; objError:canRetry .AND.; objError:tries < 25 RETRY ENDIF . . <other error statements> . RETURN NIL
. This code fragment returns an error object from an error handler to the RECOVER statement for further processing:
LOCAL objLocal, bLastHandler
// Save current and set new error handler
bLastHandler := ERRORBLOCK({ |objErr| ; MyHandler(objErr, .T.)})
BEGIN SEQUENCE . . <operation that might fail> . RECOVER USING objLocal . . <send messages to objLocal and handle the error> . END
// Restore previous error handler
ERRORBLOCK( bLastHandler )
FUNCTION MyHandler( objError, lLocalHandler ) // Handle locally returning the error object IF lLocalHandler BREAK objError ENDIF . . <other statements to handle the error> . RETURN NIL
Files: Header file is Error.ch, default error handler is in Errorsys.prg.
C5 Flow Control Commands, Statements and Funtions
Commands :
CALL* :
Execute a C or Assembler procedure
CALL <idProcedure> [WITH <exp list>]
CANCEL* :
Terminate program processing
CANCEL* | QUIT
DO* :
Call a procedure
DO <idProcedure> [WITH <argument list>]
QUIT :
Terminate program processing
QUIT | CANCEL*
RUN :
Execute a DOS command or program
RUN | !* <xcCommandLine>
SET KEY :
Assign a procedure invocation to a key
SET KEY <nInkeyCode> TO [<idProcedure>]
SET PROCEDURE *:
Compile procedures/functions into the current .OBJ file
SET PROCEDURE TO [<idProgramFile>[.<ext>]]
WAIT* :
Suspend program processing until a key is pressed
WAIT [<expPrompt>] [TO <idVar>]
Statements :
ANNOUNCE :
Declare a module identifier
ANNOUNCE <idModule>
BEGIN SEQUENCE :
Define a sequence of statements for a BREAK
BEGIN SEQUENCE <statements>... [BREAK [<exp>]] <statements>... [RECOVER [USING <idVar>]] <statements>... END [SEQUENCE]
DO CASE :
Execute one of several alternative blocks of statements
DO CASE CASE <lCondition1> <statements>... [CASE <lCondition2>] <statements>... [OTHERWISE] <statements>... END[CASE]
DO WHILE :
Execute a loop while a condition is true (.T.)
[DO] WHILE <lCondition> <statements>... [EXIT] <statements>... [LOOP] <statements>... END[DO]
EXIT PROCEDURE :
Declare an exit procedure
EXIT PROCEDURE <idProcedure> [FIELD <idField list> [IN <idAlias>]] [LOCAL <identifier> [[:= <initializer>]]] [MEMVAR <identifer list>] . . <executable statements> . [RETURN]
EXTERNAL* :
Declare a list of procedure or user-defined function names
EXTERNAL <idProcedure list>
FOR :
Execute a block of statements a specified number of times
FOR <idCounter> := <nStart> TO <nEnd> [STEP <nIncrement>] <statements>... [EXIT] <statements>... [LOOP] NEXT
FUNCTION :
Declare a user-defined function name and formal parameters
[STATIC] FUNCTION <idFunction>[(<idParam list>)] [LOCAL <identifier> [[:= <initializer>], ... ]] [STATIC <identifier> [[:= <initializer>], ... ]] [FIELD <identifier list> [IN <idAlias>]] [MEMVAR <identifier list>] . . <executable statements> . RETURN <exp>
IF :
Execute one of several alternative blocks of statements
IF <lCondition1> <statements>... [ELSEIF <lCondition2>] <statements>... [ELSE] <statements>... END[IF]
INIT PROCEDURE :
Declare an initialization procedure
INIT PROCEDURE <idProcedure> [(<idParam list>)] [FIELD <idField list> [IN <idAlias>]] [LOCAL <identifier> [[:= <initializer>]]] [MEMVAR <identifer list>] . . <executable statements> . [RETURN]
NOTE :
Place a single-line comment in a program file
NOTE This is a comment line
PARAMETERS :
Create private parameter variables
PARAMETERS <idPrivate list>
PROCEDURE :
Declare a procedure name and formal parameters
[STATIC] PROCEDURE <idProcedure> [(<idParam list>)] [FIELD <idField list> [IN <idAlias>] [LOCAL <identifier> [[:= <initializer>], ... ]] [MEMVAR <identifier list>] [STATIC <identifier> [[:= <initializer>], ... ]] . . <executable statements> . [RETURN]
REQUEST :
Declare a module request list
REQUEST <idModule list>
RETURN :
Terminate a procedure, user-defined function or program
RETURN [<exp>]
Functions :
BREAK() :
Branch out of a BEGIN SEQUENCE…END construct
BREAK(<exp>) --> NIL
EVAL() :
Evaluate a code block
EVAL(<bBlock>, [<BlockArg list>]) --> LastBlockValue
IF() :
Return the result of an expression based on a condition
[I]IF(<lCondition>, <expTrue>, <expFalse>) --> Value
PCOUNT() :
Determine the position of the last actual parameter passed
PCOUNT() --> nLastArgumentPos
SETKEY() :
Assign an action block to a key
SETKEY(<nInkeyCode>, [<bAction>]) --> bCurrentAction
SETCANCEL() :
Toggle Alt-C and Ctrl-Break as program termination keys
SETCANCEL([<lToggle>]) --> lCurrentSetting
WORD()* :
Convert CALL command numeric parameters from double to int
WORD(<nNumber>) --> NIL