Notes of a Clipper Language Student

Menu

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:

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:

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.

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 ‘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.

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() 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():

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():

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.

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 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 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.

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.