Turbo Pascal Version 4.0 Owners Manual 1987 PDF
Turbo Pascal Version 4.0 Owners Manual 1987 PDF
Turbo Pascal Version 4.0 Owners Manual 1987 PDF
Owner's Handbook
Version 4.0
Borland International
4585 Scotts Valley Drive
Scotts Valley. CA 95066
Table of Contents
Introduction
1
Understanding 4.0 ................................................ 2
Integrated Environment and Command-Line Compilers ............. 2
Separate Compilation ........................................... 2
Programs and Units ............................................. 2
Compile, Make, and Build ....................................... 3
Pick File List ................................................... 3
File Extensions ................................................. 3
About This Manual .............................................. .4
The User's Guide ............................................... 5
The Reference Manual ........................................... 6
Appendices .................................................... 6
Typography ...................................................... 7
How to Contact Borland ........................................... 7
Part 1
Chapter 1. Getting Started
11
What's On Your Disks ............................................ 12
Installing Turbo Pascal On Your System ............................. 14
Setting Up On a Floppy Disk System ............................. 14
Setting Up On a Hard Disk ...................................... 15
Choosing From Two Compilers .................................... 15
Using This Manual ............................................... 16
Chapter 2. Beginning Turbo Pascal
19
Using the Integrated Environment ................................. 19
Using Hotkeys ................................................ 21
Loading Turbo Pascal ............................................ 25
Creating Your First Program ...................................... 25
Analyzing Your First Program ................................... 26
Saving Your First Program ...................................... 26
Compiling Your First Program ................................... 26
Running Your First Program .................................... 27
Checking the Files You've Created ............................... 28
Stepping Up: Your Second Program ................................ 28
Programming Pizazz: Your Third Program .......................... 29
The Turbo Pascal Compiler ..................................... 31
iii
iv
vi
viii
ix
xiv
xv
xvi
xvii
xviii
xix
609
xx
a high degree of compatibility with version 3.0, and utilities and units to
aid in converting 3.0 programs to 4.0 .
command-line and integrated environment versions of the compiler.
Understanding 4.0
As you're reading through this manual, several major concepts will be
introduced. To help clarify these ideas, here's a summary of some of 4.0's
highlights.
Separate Compilation
Separate compilation lets you break programs into parts and compile them.
That way you can test each part to make sure it works. You can then link all
the parts together to build a program. This is useful, since you don't have
to recompile everything that makes up a program each time you use it. In
addition, this feature lets you build up a toolbox of precompiled, tested
code that you can use in all your programs.
piece of source code that can be compiled as a stand-alone entity. You can
think of units as a library of data and program code. They provide a
description of the interface between the unit's code and data and other
programs that will use that unit. Programs and other units can use units;
units don't use programs.
File Extensions
There are all kinds of file name extensions used in the DOS world; most are
usually application- or program-specific. (Remember that a file name
consists of up to eight characters with an optional three-character
extension.) Turbo Pascal uses several different file name extensions:
Introduction
.EXE: an executable file. The two compilers themselves are .EXE files. The
compiled programs you'll build with the compilers will be .EXE files.
(Turbo Pascal 3.0 created .COM files that were also executable files.)
.TPU: a precompiled unit file. When you compile a Pascal unit, the
compiler generates a .TPU file with the same first eight characters of the
source file. A .TPU file contains the symbol information and compiled
code for the unit.
.TPL: a Turbo Pascal library file. You can use only one of these at a time.
The standard library file on the disk is called TURBO.TPL. You can
modify TURBO.TPL to suit your needs .
.TP and .CFG: configuration files for the two compilers. These files allow
you to override default settings in the compilers and customize compiler
default values to your own needs.
A .TP file is a binary file containing the options you set for the integrated
environment. You can have multiple .TP files for different settings.
TPC.CFG is the configuration file for the command-line version of the
compiler. There can be only one TPC.CFG file. It is a text file that contains
directories to the compiler, command-line switches, etc.
.TPM: a Turbo MAP file. This file is generated if you use the {$T +}
compiler option. It contains information about your program that can be
useful for finding runtime errors and doing source-level debugging. The
TPMAP.EXE utility on the disk will convert the .TPM file to a MAP file
that can be used with most standard symbolic debuggers.
~P AS: Use this for your Pascal source code files. You can use other file
name extensions, but traditionally .PAS is used.
.BAK: backup source file extension. The editor in the integrated
environment renames the existing file on disk to a .BAK file when you
save a modified version of the file. You can enable or disable .BAK file
generation.
.PCK: the Turbo Pascal pick file extension. The pick file contains the state
of the integrated environment so that when you leave TURBO.EXE and
return later on, you are placed at the spot in the file where you were last
working. You can enable or disable pick file generation.
Sample programs are provided on your distribution disks for you to study.
You can also tailor these sample exercises to your particular needs.
Before you get started, you should be somewhat familiar with the basics of
operating an IBM PC (or compatible) under MS-DOS (or PC-DOS). You'll
need to know how to run programs, copy and delete files, and how to use
other basic DOS commands. If you're not sure about how to do these
things, spend some time playing with your PC and reviewing the MS-DOS
user's manual that came with it; you can also look at Appendix G, "A DOS
Primer," to learn some basics. Appendix H lists many of the terms
introduced in this manual.
This manual is divided into three main sections: "The User's Guide" (Part
I), "The Reference Section" (Part 2), and "The Appendices" (Part 3).
Introduction
Appendices
Finally, Part 3 of this manual contains nine appendices that deal with the
following topics:
Typography
This manual was produced entirely by Borland's Sprint: The Professional
Word Processor, on an Apple LaserWriter Plus. The different typefaces
displayed are used for the following purposes:
Italics
Boldface
Monospace
Keycaps
Introduction
10
1
Getting Started
In this chapter, we'll get you started using Turbo Pascal by providing
instructions for loading it on systems with floppy disk or hard disk drives.
We'll also offer some guidance on how to go about reading this manual,
based on your programming experience.
The three distribution disks that accompany this manual are formatted for
standard 5 1/ 4-inch disks, 360K disk drives, and can be read by IBM pes
and compatibles (those with 3 1/2-inch disk, 720K disk drives will receive
two distribution disks). Now, before you do anything else, we want you to
make backup copies of these three disks and then put the originals away.
Since there's a replacement charge if you erase or damage the original
disks, take heed and use your originals only to make work or backup
copies. Here's how:
Get three new (or unused) floppy disks.
Boot up your computer.
At the system prompt, type di skcopy A: B: and press Enter. The message
Insert source diskette in drive A: will be displayed on your screen.
Remove your system disk from drive A and put distribution disk 1 into
driveA.
If your system has two floppy disk drives, your screen will also say
Insert destination diskette into drive B. In that case you'll need to
remove any disk in drive B, replacing it with a blank disk. If your system
only has one floppy drive, then you'll be swapping disks in drive A. Just
remember that the distribution disk is the source disk, the blank disk is
the destination disk.
If you haven't done it already, press Enter. The computer will start
reading from the source disk in drive A.
Chapter 7, Getting Started
11
If you have a two-drive system, it will then write out to the destination
disk in drive B and continue reading from A and writing to B until
copying is complete. If you have a one-drive system, you'll be asked to
put the destination disk in A, then the source disk, then the destination
disk, and so on and so forth until it's finished.
When copying is completed, remove the distribution (source) disk from
drive A, and put it away. Remove the copy (destination) disk from drive
B and label it "Disk #1."
Repeat the preceding process with the second and third distribution
disks and the other blank floppies.
Now that you've made your backup copies, we can get on to the meat of
this chapter.
TURBO.TPL
TINST.EXE
GRAPH.TPU
12
TPC.EXE
TPMAP.EXE
TPUMOVER.EXE This utility allows you to move units between .TPL files;
more specifically, you can use it to add units (that you
write) to TURBO.TPL or to remove units from that file.
Copy it if you plan to modify TURBO.TPL.
README.COM
README
UPGRADE.EXE
TPCONFIG.EXE
MAKE.EXE
TOUCH.COM
GREP.COM
13
*.PAS files
BlNOB].EXE
*.DOC files
*.BGl files
*.CHRfiles
Your system will ask you to insert a DOS disk into drive A; just insert your
regular system boot disk. If you have a two-drive system, place a blank
disk into drive B and press Enter when prompted. If you have a one-drive
system, place your blank disk into the drive whenever you are asked to
insert a blank disk into drive B, and place your original boot disk into the
drive whenever you are asked to insert a DOS disk into drive A.
When you're finished, your blank disk will be formatted and will contain a
copy of MS-DOS (the operating system). Label it as your Turbo Pascal
system disk and continue to the next step.
Put your Turbo Pascal system disk into drive A. If you have a second drive,
put your Turbo Pascal distribution disk 1 into drive B and type
A>dir b:
14
That will list all the files on the first distribution disk. You can copy them
one at a time from your Turbo Pascal distribution disk onto your system
disk by typing
A>copy b:filename a:
where filename is the name of the file you wish to copy. As mentioned, the
two files you absolutely must copy are TURBO.TPL, and either
TURBO.EXE or TPC.EXE (or both).
Now place each Turbo Pascal distribution disk into drive A and type the
following command:
copy a:*.* c:\tp
Now put your distribution disks in a safe place. If you'd like, you can
delete from your hard disk any of the files you don't need. (Refer to the
preceding section for which files you might not need.)
15
and then press Enter. TPC.EXE compiles and links your program, producing
an .EXE file (just like TURBO.EXE). Command-line options allow you to
specify a number of things, such as where the system library (TURBO.TPL)
resides and whether to recompile any files upon which MYFIRST.PAS
depends.
Which version should you use? Chances are you'll find the integrated
environment best suits your needs. It provides a complete development
system in which you can quickly build and debug programs. On the other
hand, if you are currently using a command-line Pascal compiler, if you
have another editor that you prefer, or if you are making heavy use of an
assembler (for external subroutines), you may want to use the commandline compiler in conjunction with a batch file or Make utility.
16
17
18
2
Beginning Turbo Pascal
Turbo Pascal is more than just a fast Pascal compiler; it is an efficient Pascal
compiler with an easy-to-Iearn and easy-to-use integrated development
environment. With Turbo Pascal, you don't need to use a separate editor,
compiler, and linker in order to create and run your Pascal programs
(although, you can use the command-line version). All these features are
built into Turbo Pascal, and they are all accessible from the Turbo Pascal
integrated environment~
Now that you're set up, you can begin writing your first Turbo Pascal
program using the integrated environment compiler. By the end of this
chapter, you'll have learned the basics of this development environment,
written three small programs, saved them, and learned a few basic
programming skills.
19
get more detailed help on the selected item. You can use the Home and End
keys to go to the first and last keywords on the screen, respectively.
To get to the Help index, press F1 again once you're in the Help system. The
Help index lets you access both language and environment help. While
you're in the editor, you can also get help on a particular procedure,
function, variable, constant, type, or unit by positioning the cursor on the
item and pressing etrl-F1. (Note: etrl-F1 is an editor command that can be
redefined using TINST described in Appendix F.)
If you want to return to a previous Help screen while either in or out of the
Help system, press Alt-F1. (You can back up through 20 previous Help
screens.) Within a help group (a series of related help screens), AIt-F1
remembers the group as one screen .viewed rather than remembering each
screen individually. In a help group, wherever PgUp and pgOn occur, PgUp
takes you back a screen, and PgOn takes you forward. To exit from Help and
return to your menu selection, press Esc (or any of the hotkeys described in
the next section).
When youload Turbo Pascal (type turbo and press Enter at the DOS
prompt), the program's first screen includes the main screen and product
version information (pressing AIt-F10 any time will bring up this
information). When you press any key, the version information disappears,
but the main screen remains.
:~\\\'Illfi\\\
Edit
Line I
Run
ColI
Compile Edit
Insert Indent
Options
C:NONAME.PAS
Output
Fl-Help
F2-Save
F3-Load
F5-Zoom
FS-Edit
F9-Make
FlO-Main menu
Look closely at the main screen; it consists of four parts: the main menu, the
Edit window, the Output window, and the bottom line (which indicates
which keys do what at that particular instance).
To get familiar with the Turbo Pascal system, here are some navigating
basics.
20
Using Hotkeys
There are a number of hotkeys (shortcuts) you can use. Hotkeys are keys set
up to perform a certain function. For example, as discussed previously,
pressing Aft and the first letter of a main menu command will take you to
the specified option's menu or perform an action (see Figure 2.1 for a
graphic example); these are all considered hotkeys. The only other Alt! firstletter command is Alt-X, which is really just a shortcut for File/Quit.
In general, hotkeys work from anywhere; but there are two exceptions.
21
One is that hotkeys are disabled in error boxes and verify boxes. In these
cases, you are required to press the key specified.
The second exception is in the editor. If you use TIN5T to install editor key
commands, you can define hotkeys as edit commands. This means that
while you are in the editor, the hotkey will behave as an edit command,
and when you are not in the editor, the hotkey will work as originally
defined. For example, if you define Alt-R to be PgUp in the editor, it will not
run your programs from the editor. 50 you must somehow exit the editor
(F10 or F6) before Alt-R will run your program. This gives you the flexibility
to define the keys you prefer to use when editing. (Refer to Appendix F for
a complete discussion of redefining the editor keys.)
22
Edit Window
Output Window
~""-F6
Alt-E to go
from any
menu level to
Edit window
F10from
either
window
~
Main Menu Bar (F10 takes you here
from anywhere)
F6 to go from any
menu level to
active
WIndow
previo~sly
Pull-down Menus
and Submenus
The initial
(highlighted) letter
always selects
the menu item.
Press Esc
to exit a
menu
From anywhere in Turbo Pascal, Alt plus the first letter of any main menu command (F, E, R, C, or 0)
invokes that command, and F1 calls up context-sensitive help information. Press Alt and hold for
a list of Alt-key shortcuts.
23
Table 2.1 lists all the hotkeys you can use while in Turbo Pascal. Remember
that when these keys are pressed, their specific function is carried out no
matter where you are in the Turbo Pascal environment.
Table 2.1: Turbo Pascal's Hotkeys
Key(s)
Function
F1
F2
F3
FS
F6
F9
F10
Alt-F1
Alt-F3
Alt-FS
Alt-F9
Alt-F10
AIt-C
AIt-E
AIt-F
Alt-O
Alt-R
Alt-X
Ctrl-F6
In this book, we will refer to all menu items by an abbreviated name. The
abbreviated name for a given menu item is represented by the sequence of
letters you type to get to that item from the main menu. For example:
At the main menu, the menu offering compile-time options related to
memory sizes is the Options/Compiler/Memory sizes; we'll tell you to
select O/C/Memory (press 0 C M) .
At the main menu, the menu for specifying the name of the Include directories is the Options/Directories/Include directories; we'll tell you to
select OlD/Include (press 00 /).
If you feel like you need more help using the integrated environment, look
at Chapter 10. If you're comfortable with what you've learned to date, let's
get on to actually writing some programs in Turbo Pascal.
24
and press Enter. This runs the program TURBO.EXE, which brings up the
integrated environment, placing you in the main menu.
If you're using a hard disk, get into the Turbo Pascal subdirectory you
created in the previous chapter and run TURBO.EXE by typing the
following:
C>cd tp
C:\TP>turbo
To move around in the Edit window, you can use the arrow keys. (If you're
unfamiliar with editing commands, Chapter 11 discusses all the editing
commands you have at your disposal.) Note the semicolon at the end of
most lines, as well as the period at the end of the last line-these are
necessary. If you make any errors, you can use the arrows keys on the
keyboard to move around; you can use the Backspace key to make deletions;
and you can simply type new text to make insertions.
25
26
Turbo Pascal compiles your program, changing it from Pascal (which you
can read) to 8086 machine code for the microprocessor (which your PC can
execute). You don't see the 8086 machine code; it's stored in memory
somewhere (or on disk).
When you start compiling, a box appears in the middle of the screen, giving
information about the compilation taking place. A message flashes across
the box to press etr/-Break to quit compilation. If compilation is successful,
the message Success: Press any key flashes across the box. The box
remains visible until you press a key. See how fast that went?
If an error occurs during compilation, Turbo Pascal stops, positions the
cursor at the point of error in the editor, and displays an error message at
the top of the editor. Press any key to clear the error message. (Note: The
keystroke you select is used by the editor.) Then make the correction, save
the updated file, compile it again.
appears on the screen. Type in any two integers (whole numbers), with a
space between them, and press Enter. The following message will appear:
The ratio is
appears at the bottom of the screen. Notice that your program output is
displayed in the Output window so you can refer to it while looking at
your program.
If an error occurs while your program is executing, you'll get a message on
the screen that looks like this:
Runtime error <errnum> at <segment>:<offset>
where <errnum> is the appropriate error number (see Appendix I), and
<segment>:<offset> is the memory address where the error occurred.(If you
need this number later, look for it in the Ouptput window.} The rest of the
program is skipped over, and you'll be asked to press any key to return to
Chapter 2, Beginning Turbo Pascal
27
Turbo Pascal. Once you're there, Turbo Pascal automatically finds the
location of the error and displays it to you. If you need to find the error
location again, select the Find error command from the Compile menu.
When your program has finished executing, you press any key and the PC
returns control to Turbo Pascal, and you're back where you started. You
can now modify your program if so desired. If you select the Run command before you make any changes to your program, Turbo Pascal
immediately executes it, without recompiling.
listing of the source (Pascal) file you've created. Press 0 for as shell in the
File menu or, alternatively, press Q and type the following command at the
DOS prompt:
dir myfirst. *
PAS
171
7-10-87
11:07a
The file MYFIRST.PAS contains the Pascal program you just wrote.
(Note: You'll only see the executable file if you've changed your default
Destination setting in the Compile menu to Disk. You would then get a file
called MYFIRST.EXE, which would contain the machine code that Turbo
Pascal generated from your program. You could then execute that program
by typing MYFIRST followed by Enter at the DOS system prompt.)
This will place you directly into the editor. Now, modify your
MYFIRST.PAS program to look like this:
program MySecond;
var
A,B
integer;
real;
Ratio
Ans
char;
begin
28
repeat
Write('Enter two numbers: ');
Readln (A, B) ;
if B = 0 then
Writeln('Division by zero is not allowed.')
else
begin
Ratio := A / B;
Writeln('The ratio is ' ,Ratio:8:2)
end;
You want to save this as a separate program, so go to the main menu (press
F10), select the File menu (press F), and then Write to (press W). When
prompted for a new name, type MYSECOND.PAS and press Enter. Exit
from the File menu by pressing Esc.
Now here's a shortcut: To compile and run your second program, just press
R for Run (at the main menu). This tells Turbo Pascal to run your updated
program. And since you've made changes to the program, Turbo Pascal
knows to compile the program before running it.
Two major changes have been made to the program. First, most of the
program has been enclosed in the repeat..untilloop. This causes all the
statements between repeat and until to be executed until the expression
following until is True. Also, a test is made to see if B has a value of zero or
not. If B has a value of zero, then the message
Division by zero is not allowed
appears; otherwise, the ratio is calculated and displayed. Note that the ratio
has a more readable format now; it looks like this:
The ratio is 2.43
If you enter Y to the Are you done? message, you'll get the Press any key
to return to Turbo Pascal message at the bottom of the screen.
Press any key and you'll be returned to Turbo's main menu.
29
your system, and that you are currently set up to use that card or adapter. If
in doubt, try the program and see what happens. If an error message
appears, then you probably don't have a graphics adapter (or you have one
that's not supported by our Graph unit). In any case, pressing Enter twice
should get you back to the integrated environment.
At the main menu, press File/Load. Enter the program MYTHIRD.PAS at
the prompt, and you'll be placed in the editor. Here's the program to enter:
program MyThird;
uses
Graph;
const
Start
25;
Finish
175;
Step
2;
var
end;
Yl := Start;
Y2 := Finish;
Xl := Start;
while Xl <= Finish do
begin
X2 := (StarttFinish) - Xl;
Line (Xl, Yl, X2, Y2);
Xl := Xl t Step;
end;
Xl := Start;
X2 := Finish;
Yl := Start;
while Yl <= Finish do
begin
Y2 := (StarttFinish) - Yl;
Line(Xl, Yl, X2, Y2);
Yl := Yl t Step;
end;
OutText('Press <RETURN> to quit:');
Readln;
CloseGraph;
end. { MyThird )
30
After you finish entering this program, press F2 to save it and then G to
compile. If you have no errors during compilation, press R to run it. This
program produces a square with some wavy patterns along the edges.
When execution is over, you'll get the message Press any key to
return to Turbo Pascal at the bottom of your screen. Let's look at
how it works.
The uses statement says that the program uses a unit named Graph. A unit
is a library, or collection, of subroutines (procedures and functions) and
other declarations. In this case, the unit Graph contains the routines you
want to use: InitGraph, Line, CloseGraph.
The section labeled const defines three numeric constants-Start, Finish,
and Step-that affect the size, location, and appearance of the square. By
changing their values, you can change how the square looks.
Warning: Don't set Step to anything less than 1; if you do, the program will
get stuck in what is known as an infinite loop (a loop that circles endlessly).
You won't be able to exit except by pressing Gtrl-Alt-Oel or by turning your
PC off.
The variables Xl, Yl, X2, and Y2 hold the values of locations along
opposite sides of the square. The square itself is drawn by drawing a
straight line from Xl,Yl to X2,Y2. The coordinates are then changed, and
the next line drawn. The coordinates always start out in opposite corners:
The first line drawn goes from (25,25) to (175,175).
The program itself consists primarily of two loops. The first loop draws a
line from (25,25,) to (175,175). It then moves the X (horizontal) coordinates
by two, so that the next line goes from (27,25) to (173,175). This continues
until the loop draws a line from (175,25) to (25,175).
The program then goes into its second loop, which pursues a similar
course, changing the Y (vertical) coordinates by two each time. The routine
Line is from the Graph unit and draws a line between the endpoints given.
The final Readln statement causes the program to wait for you to press a
key before it goes back into text mode and exits to the integrated
environment.
31
32
Second, you can ask Turbo Pascal to recompile any units that the program
you're compiling might use. You actually have two options here:
1. You can tell Turbo Pascal to recompile any units that have been changed
since the last time you compiled your program. This is called a "make."
2. You can tell Turbo Pascal to recompile all units that your program uses.
This is called a "build."
every time? Two reasons. First, because the resulting machine code is never
saved on disk, you could only run your programs from Turbo Pascal. There
would be no way to execute your program from MS-DOS, nor would you
be able to copy your program.
The second problem is memory-you might not have enough. This could
happen if your system doesn't have much memory, if your program is very
large, or if your program uses a lot of memory for dynamic data allocation.
It's easy to produce an .EXE file (application) you can run from outside
Turbo Pascal: Select the Destination option from the Compile menu. This
option allows you to toggle between Disk and Memory for your destination. If you select Disk and then recompile, Turbo Pascal produces a code
file that you can run from MS-DOS by typing its name at the prompt.
The file produced has the same name as your source file but with the
extension .EXE; for example, the resulting code file of a program named
MYFIRST.PAS would be MYFIRST.EXE.
Regardless of whether you are compiling to disk or to memory, the Run
command still executes the resulting program once the compilation is done.
33
Note that the $U directive comes right before the corresponding unit
name.
34
Compile-Time Errors
Like English, Pascal has rules of grammar you must follow. However,
unlike English, Pascal's structure isn't lenient enough to allow for slang or
poor syntax-the compiler won't understand what you want. In Pascal,
when you don't use the appropriate words or symbols in a statement or
when you organize them incorrectly, it results in a compile-time (syntax)
error.
What compile-time errors are you likely to get? Probably the most common
error novice Pascal programmers will get is Unknown identifier or
, ; , expected. Pascal requires that you declare all variables, data types,
constants, and subroutines-in short, all identifiers-before using them. If
you refer to an undeclared identifier or if you misspell it, you'll get this
error. Other common errors are unmatched begin.. end pairs, assignment of
incompatible data types (such as assigning reals to integers), parameter
count and type mismatches in procedure and function calls, and so on.
Runtime Errors
In programming, sometimes just following the rules governing correct
syntax isn't enough. For example, suppose you write a simple program that
prompts you for two integer values, adds them together, then prints out the
result. The entire program might look something like this:
program AddSum;
var
A,B,Sum : integer;
begin
Write('Enter two integer values: ');
Readln(A,B) ;
Sum := A + B;
Writeln('The sum is ',Sum,' .')
end.
In response to the prompt, Enter two integer values:, say you type in real
numbers (numbers with decimal points), integer values that are too large,
or even character strings instead of numbers. What happens? You'll get a
message that looks something like this:
Runtime error 106 at IF9C:0062
35
If you are running from within Turbo Pascal, you'll get the Press any key to
return to Turbo Pascal prompt; after pressing any key, you'll be returned to
Turbo Pascal's integrated environment, which will then automatically
locate the error for you in the Edit window.
What if the runtime error occurred in a unit used by your program? Turbo
Pascal can still locate the error if the unit was compiled with the $D+
compiler option. (This is the Debug info toggle in the Options/Compile
menu; it is on by default.)
In either case, Turbo Pascal loads that source code file into the editor and
positions the cursor at the appropriate spot. (You may be prompted to save
the current .edit file.) You can then make the appropriate changes,
recompile, and run it again.
If you need to relocate the error after having moved to another section of
your file, use the Ctrl-Q W command. If you change files, you can find the
error again by loading the main program and using the Find error
command in the Compile menu. It will ask you for the segment and offset
values displayed when the error occurred, but will default to the last error
address that was found.
36
3
Programming in Turbo Pascal
The Pascal language was designed by Niklaus Wirth in the early 1970s to
teach programming. Because of that, it's particularly well-suited as a first
programming language. And if you've already programmed in other
languages, you'll find it easy to pick up Pascal.
To get you started on the road to Pascal programming, in this chapter we'll
teach you the basic elements of the Pascal language, and show you how to
use them in your programs. Of course, we won't cover everything about
programming in Pascal in this chapter. So if you're a Pascal novice, your
best bet would be to pick up a copy of the Turbo Pascal Tutor, a complete
book-pIus-disk tutorial about programming in Pascal and using version 4.0
of Turbo Pascal.
Before you work through this chapter, you might want to read Chapters 10
and 11 to learn how to use the menus and text editor in Turbo Pascal. You
should have installed Turbo Pascal (made a working copy of your Turbo
Pascal disk or copied the files onto your hard disk) as described in Chapter
1. Make sure that you've created the file TURBO.TP or installed the .EXE
file using TINST.EXE (see Appendix F); otherwise, Turbo Pascal won't
know the location of the standard units in TURBO.TPL and the
configuration file. (Unless you happen to own MS-DOS 3.x and you have
those files in the same directory as TURBO.EXE.)
Once you've done all that, get ready to learn about programming in Turbo
Pascal.
37
38
Conditional Execution
This refers to executing a set of instructions if a specified condition is True
(and skipping them or executing a different set if it is False) or if a data item
has a specified value or range of values.
Loops
These execute a set of instructions some fixed number of times, while some
condition is True or until some condition is True.
Subroutines
These are separately named sets of instructions that can be executed anywhere in the program just by referencing the name.
Now we'll take a look at how to use these elements in Turbo Pascal.
Data Types
When you write a program, you're working with information that
generally falls into one of five basic types: integers, real numbers, characters
and strings, boolean, and pointers.
Integers are the whole numbers you learned to count with (1, 5, -21, and
752, for example).
39
Turbo Pascal also supports four other integer data types, each of which has
a different range of values. Table 3.1 shows all five integer types.
Table 3.1: Integer Data Types
Range
Type
byte
shortint
integer
wora
longint
Size in Bytes
0.. 255
-128 .. 127
-32768 .. 32767
0.. 65535
-2147483648 .. 2147483647
1
1
2
2
4
A final note: Turbo Pascal allows you to use hexadecimal (base-16) integer
values. To specify a constant value as hexadecimal, place a dollar sign ($) in
front of it; for example, $27 = 39 decimal.
Type
Range
real
single
double
extended
comp*
Significant Digits
11-12
7- 8
15-16
19-20
19-20
Size in Bytes
6
8
10
8
40
Get into the Turbo Pascal editor and enter the following program:
program DoRatio;
var
A,B
: integer;
Ratio : real;
begin
Write ('Enter two numbers: ');
Readln(A,B) ;
Ratio := A div B;
Writeln('The ratio is ' ,Ratio)
end.
Save the code (press F2), then compile and run. The result is now
3.3333333333, as you expected. Using the division operator U) gives you
the most precise result-a real number.
41
') ;
end.
After calculating the ratio once, the program writes the message
Do it again? (YIN)
and waits for you to type in a single character, followed by pressing Enter. If
you type in a lowercase n or an uppercase N, the until condition is met and
the loop ends; otherwise, the program goes back to the repeat statement
and starts over again.
Note that n is not the same as N. This is because they have different ASCII
code values. Characters are represented by the ASCII code: Each character
has its own 8-bit number (characters take up 1 byte, remember). Appendix
E lists the ASCII codes for all characters.
Turbo Pascal gives you two additional ways of representing character
constants: with a caret (1\) or a number symbol (#). First, the characters
with codes 0 through 31 are known as control characters (because historically
they were used to control teletype operations). They are referred to by their
abbreviations (CR for carriage return, LF for linefeed, ESC for escape, and
so on) or by the word Ctrl followed by a corresponding letter (meaning the
letter produced by adding 64 to the control code). For example, the control
character with ASCII code 7 is known as BEL or Ctr/-G. Turbo Pascal lets you
represent these characters using the caret (1\), followed by the corresponding letter (or character). Thus, I\C is a legal representation in your
program of Ctrl-G, and you could write statements such as Writeln (1\ C),
causing your computer to beep at you. This method, however, only works
for the control characters.
You can also represent any character using the number symbol (#), followed
by the character's ASCII code. Thus, #7 would be the same as I\C, #65
would be the same as A', and #233 would represent one of the special IBM
PC graphics characters.
I
Defining a String
Individual characters are nice, but what about strings of characters? After
all, that's how you will most often use them. Standard Pascal does not
support a separate string data type, but Turbo Pascal does. Take a look at
this program:
42
program Hello;
var
Name : string[30];
begin
Write('What is your name?
Readln(Name);
Writeln('Hello, ',Name)
end.
');
This declares the variable Name to be of type string, with space set aside to
hold 30 characters. One more byte is set aside internally by Turbo Pascal to
hold the current length of the string. That way, no matter how long or short
the name is you enter at the prompt, that is exactly how much is printed
out in the Writeln statement. Unless, of course, you enter a name more than
30 characters long, in which case only the first 30 characters are used, and
the rest are ignored.
When you declare a string variable, you can specify how many characters
(up to 255) it can hold. Or you can declare a variable (or parameter) to be of
type string with no length mentioned, in which case the default size of 255
characters is assumed.
Turbo Pascal offers a number of predefined procedures and functions to
use with strings; they can be found in Chapter 27.
43
The data type Buffer is now just another name for string[255], while the
type BufPtr defines a pointer to a Buffer. The variable Bufl is of type Buffer;
it takes up 256 bytes of memory. The variable Buf2 is of type BufPtr; it
contains a 32-bit address and only takes up 4 bytes of memory.
Where does Buf2 point to? Nowhere, currently. Before you can use BufPtr,
you need to set aside (allocate) some memory and store its address in Buf2.
You do that using theNew procedure:
New(Buf2);
Since Buf2 points to the type Buffer, this statement creates a 256-byte buffer
somewhere in memory, then puts its address into Buf2.
How do you use the data pointed to by Buf2? Via the indirection operator
For example, suppose you want to store a string in both Bufl and the
buffer pointed to by Buf2. Here's what the statements would look like:
A.
Note the difference between Buf2 and BUf2/\. Buf2 refers to a 4-byte pointer
variable; Buf2/\ refers to a 256-byte string variable whose address is stored
in Buf2.
How do you free up the memory pointed to by Buf2? Using the Dispose
procedure. Dispose makes the memory available for other uses. After you
use Dispose on a pointer, it's good practice to assign the (predefined) value
nil to that pointer. That lets you know that the pointer no longer points to
anything:
44
Dispose(Buf2);
Buf2 := nil;
Identifiers
Up until now, we've given names to variables without worrying about
what restrictions there might be. Let's talk about those restrictions now.
The names you give to constants, data types, variables, and functions are
known as identifiers. Some of the identifiers used so far include
Turbo Pascal has a few rules about identifiers; here's a quick summary:
All identifiers must start with a letter (a ... z or A .. .2). The rest of an
identifier can consist of letters, underscores, and/or digits (0 ... 9); no
other characters are allowed.
Identifiers are case-insensitive, which means that lowercase letters (a ... z)
are considered the same as uppercase letters (A ... 2). For example, the
identifiers indx, Indx, and INDX are identical.
Identifiers can be of any length, but only the first 63 characters are
significant.
Operators
Once you get that data into the program (and into your variables), you'll
probably want to manipulate it somehow, using the operators available to
you. There are eight types: assignment, unary/binary, bitwise, relational,
logical, address, set, and string.
Most Pascal operators are binary, taking two operands; the rest are unary,
taking only one operand. Binary operators use the usual algebraic form, for
example, a + b. A unary operator always precedes its operand, for example,
-b.
45
Operators
Precedence
Categories
@,not
*, /, div, mod, and, shl, shr
+,-, or, xor
=,<>,<, >, <=,>=,in
First (high)
Second
Third
Fourth (low)
Unary operators
MultIplying operators
Adding operators
Relational operators
Assignment Operators
The most basic operation is assignment, as in Ratio := A / B. In Pascal, the
assignment symbol is a colon followed by an equal sign (:=). In the example
given, the value of A / B on the right of the assignment symbol is assigned
to the variable Ratio on the left.
Multiplication (*)
Integer division (div)
Real division (/)
Modulus (mod)
Addition (+)
Subtraction (-)
Also, Turbo Pascal supports both unary minus (a + (-b, which performs a
two's complement evaluation, and unary plus (a + (+b, which does nothing
at all but is there for completeness.
46
Bitwise Operators
For bit-level operations, Pascal has the following operators:
shl (shift left)
shr (shift right)
and
or
xor
not
Relational Operators
Relational operators allow you to compare two values, yielding a Boolean
result of True or False. Here are the relational operators in Pascal:
>
>=
<
<=
<>
in
greater than
greater than or equal to
less than
less than or equal to
equal to
not equal to
is a member of
So why would you want to know if something were True or False? Enter
the following program:
program TestGreater;
var
A,B
: integer;
Test : boolean;
47
begin
Write('Enter two numbers: ');
Readln(A,B);
Test := A > B;
Writeln('A is greater than B', Test);
end.
This will print True if A is greater than B or False if A is less than or equal
to B.
Logical Operators
There are four logical operators-and, xor, or, and not-which are similar
to but not identical with the bitwise operators. These logical operators work
with logical values (True and False), allowing you to combine relational
expressions, Boolean variables, and Boolean expressions.
They differ from the corresponding bitwise operators in this manner:
Logical operators always produce a result of either True or False (a
Boolean value), while the bitwise operators do bit-by-bit operations on
type integer values.
You cannot combine boolean and integer-type expressions with these
operators; in other words, the expression Flag and Indx is illegal if Flag is
of type boolean, and Indx is of type integer (or vice versa).
The logical operators and and or will short-circuit by default; xor and not
will not. Suppose you have the expression expl and exp2. If expl is False,
then the entire expression is False, so exp2 will never be evaluated.
Likewise, given the expression expl or exp2, exp2 will never be evaluated
if expl is True. You can force full Boolean expression using the {$B+}
compiler directive or environment option.
Address Operators
Pascal supports two special address operators: the address-of operator (@)
and the indirection operator (").
The @ operator returns the address of a given variable; if Sum is a variable
of type integer, then @Sum is the address (memory location) of that
variable. Likewise, if ChrPtr is a pointer to type char, then ChrPtr" is the
character to which ChrPtr points.
48
Set Operators
Set operators perform according to the rules of set logic. The set operators
and operations include:
+
*
union
difference
multiplication
String Operators
The only string operation is the + operator, which is used to concatenate
two strings.
Output
It may seem funny to talk about output before input, but a program that
doesn't output information isn't of much use. That output usua~ly takes the
form of information written to the screen (words and pictures), to a storage
device (floppy or hard disk), or to an I/O port (serial or printer ports).
where each item is something you want to print to the screen. item can be a
literal value, such as an integer or a real number (3, 42, -1732.3), a character
('a', 'Z'), a string ('Hello, world'), or a Boolean value (True). It can also be a
named constant, a variable, a dereferenced pointer, or a function call, as
long as it yields a value that is of type integer, real, char, string, or boolean.
All the items are printed on one line, in the order given. The cursor is then
moved to the start of the next line. If you wish to leave the cursor after the
last item on the same line, then use the statement
Write (item, item, ... );
49
So, for example, the following statements produce the indicated output:
A := 1; B := 2; C := 3;
Name := 'Frank';
WriteIn(A,B,C) ;
WriteIn(A,' ',B,' ',C);
WriteIn('Hi' ,Name);
Writeln (' Hi, , ,Name,' .');
123
123
HiFrank
Hi, Frank.
You can also use field-width specifiers to define a field width for a given item.
The format for this is
WriteIn(item:width, ... );
102100
10 2100
10 2100
10 2 100
Note that the item is padded with leading blanks on the left to make it
equal to the field width. The actual value is right-justified.
What if the field width is less than what is needed? In the second Writeln
statement given earlier, C has a field width of 2 but has a value of 100 and
needs a width of 3. As you can see by the output, Pascal simply expands
the width to the minimum size needed.
This method works for all allowable items: integers, reals, characters,
strings, and booleans. However, real numbers printed with the field-width
specifier (or with none at all) come out in exponential form:
x := 421.53;
Write In (X);
WriteIn(X:8);
4.2153000000E+02
4.2E+02
50
X := 421. 53;
Writeln(X:6:2);
Writeln(X:8:2);
Writeln(X:8:4);
421. 53
421.53
421.5300
Input
Standard Pascal has two basic input functions, Read and Readln, which are
used to read data from the keyboard. The general syntax is
Read (item, item, ... );
or
Readln (item, item, ... );
where each item is a variable of any integer, real, char, or string type.
Numbers must be separated from other values by spaces or by pressing
Enter.
Conditional Statements
There are times when you want to execute some portion of your program
when a given condition is True or not, or when a particular value of a given
expression is reached. Let's look at how to do this in Pascal.
The If Statement
Look again at the if statement in the previous examples; note that it can
take the following generic format:
if expr
then statement!
else statement2
then statement!
51
In this case, statementl is executed if and only if expr is True. If expr is False,
then statementl is skipped, and the program continues.
Second, what if you want to execute more than one statement if a particular
expression is True or False? You would use a compound statement. A
compound statement consists of the keyword begin, some number of
statements separated by semicolons (;), and the keyword end.
The ratio example uses a single statement for the if clause
if B = 0.0 then
Writeln('Division by zero is not allowed.')
You might also notice that the body of each program you've written is
simply a compound statement followed by a period.
:= Curlews + 1;
:= Herons + 1;
:= Egrets + 1;
:= Terns + 1;
52
follows the case label is executed if the selector's value equals one of the
constants or if it lies within one of the subranges.
Loops
Just as there are statements (or groups of statements) that you want to
execute conditionally, there are other statements that you may want to
execute repeatedly. This kind of construct is known as a loop.
There are three basic kinds of loops: the while loop, the repeat loop, and
the for loop. We'll cover them in that order.
The first thing that happens when you run this program is that Count is set
equal to 1, then you enter the while loop. This tests to see if Count is less
then or equal to 10. Count is, so the loop's body (begin .. end) is executed.
This prints the message Hello and goodbye! to the screen, then increments
Count by 1. Count is again tested, and the loop's body is executed once
more. This continues as long as Count is less than or equal to 10 when it is
tested. Once Count reaches 11, the loop exits, and the string This is the
end! is printed on the screen.
The format of the while statement is
while expr do statement
53
The while loop evaluates expr. If it's True, then statement is executed, and
expr is evaluated again. If expr is False, the while loop is finished and the
program continues.
There are three major differences between the while loop and the repeat
loop. First, the statements in the repeat loop always execute at least once,
because the test on expr is not made until after the repeat occurs. By
contrast, the while loop will skip over its body if the expression is initially
False.
Next, the repeat loop executes until the expression is True, where the while
loop executes while the expression is True. This means that care must be
taken in translating from one type of loop to the other. For example, here's
the HELLO program rewritten using a repeat loop:
54
program Hello;
var
Count : integer;
begin
Count := 1;
repeat
Writeln{'Hello and goodbye!');
Inc (Count)
until Count > 10;
Writeln{'This is the end!')
end.
Note that the test is now Count> 10, where for the while loop it was Count
<= 10.
Finally, the repeat loop can hold multiple statements without using a
compound statement. Notice that you didn't have to use begin.. end in the
preceding program, but you did for the earlier version using a while loop.
Again, be careful to note that the repeat loop will always execute at least
once. A while loop may never execute depending on the expression.
When you run this program, you can see that the loop works the same as
the while and repeat loops already shown and, in fact, is precisely
equivalent to the while loop. Here's the generic format of the for loop
statement:
for index := exprl to expr2 do statement
55
where index is a variable of some scalar type (any integer type, char,
boolean, any enumerated type), exprl and expr2 are expressions of some
type compatible with index, and statement is a single or compound
statement. Index is incremented by one after each time through the loop.
You can also decrement the index variable instead of incrementing it by
replacing the keyword to with the keyword downto.
The for loop is equivalent to the following code:
index := exprl;
while index <= expr2 do
begin
statement;
Inc (index)
end;
The main drawback of the for loop is that it only allows you to increment
or decrement by one. Its main advantages are conciseness and the ability to
use char and enumerated types in the range of values.
x : = Sin (A) ;
while a procedure is called to perform one or more tasks:
Writeln('This is a test');
However, before you learn any more about procedures and functions, you
need to understand Pascal program structure.
Program Structure
In Standard Pascal, programs adhere to a rigid format:
56
program ProgName;
label
labels;
const
constant declarations;
type
data type definitions;
var
variable declarations;
procedures and functions;
begin
main body of program
end.
The five declaration sections-label, const, type, var, and procedures and
functions-do not all have to be in every program. But in standard Pascal,
if they do appear, they must be in that order, and each section can appear
only once. The declaration section is followed by any procedures and
functions you might have, then finally the main body of the program,
consisting of some number of statements.
Turbo Pascal gives you tremendous flexibility in your program structure.
All it requires is that your program statement (if you have one) be first and
that your main program body be last. Between those two, you can have as
many declaration sections as you want, in any order you want, with
procedures and functions freely mixed in. But things must be defined
before they are used, or else a compile-time error will occur.
57
Functions look just like procedures except that they start with a function
header and end with a data type for the return value of the function:
function FuncName(parameters) : data type;
As you can see, there are only two differences between this and regular
program structure: Procedures or functions start with a procedure or
function header instead of a program header, and they end with a semicolon instead of a period. A procedure or function can have its own
constants, data types, and variables, and even its own procedures and
functions. What's more, all these items can only be used with the procedure
or function in which they are declared.
Sample Program
Here's a version of the DORATIO program that uses a procedure to get the
two values, then uses a function to calculate the ratio:
program DoRatio;
var
A,B
: integer;
Ratio : real;
procedure GetData(var X,Y integer);
begin
Write('Enter two numbers: ');
Readln(X,Y)
end;
function GetRatio(I,J : integer)
begin
GetRatio := I/J
end;
real;
begin
GetData (A, B) ;
Ratio := GetRatio(A,B);
Writeln('The ratio is ' ,Ratio)
end.
58
parameters must be variables and that the variable values can be changed
and passed back to the caller. So you can't pass literals, constants,
expressions, and so on to GetData. Once GetData is finished, execution
returns to the main body of the program and continues with the statement
following the call to GetData.
That next statement is a function call to GetRatio. Note that there are some
key differences here. First, GetRatio returns a value; which must then be
used somehow; in this case, it's assigned to Ratio. Second, a value is
assigned to GetRatio in its main body; this is how a function determines
what value to return. Third, there is no var keyword in front of the formal
parameters I and J. This means that the actual parameters could be any two
integer expressions, such as Ratio := GetRatio(A + B,300); and that even if
you change the values of the formal parameters in the function body, the
new values will not be passed back to the caller. This, by the way, is not a
distinction between procedures and functions; you can use both types of
parameters with either type of subprogram.
Program Comments
Sometimes you want to insert notes into your program to remind you (or
inform someone else) of what certain variables mean, what certain
functions or statements do, and so on. These notes are known as comments.
Pascal, like most, other programming languages, lets you put as many
comments as you want into your program.
You can start a comment with the left curly brace (0, which signals to the
compiler to ignore everything until after it sees,the right curly brace 0).
Comments can even extend across multiple lines, like this:
{ This is a long
comment, extending
over several lines.
59
60
4
Units and Related Mysteries
In Chapter 3, you learned how to write standard Pascal programs. What
about non-standard programming-more specifically, PC-style programming, with screen control, DOS calls, and graphics? To write such
programs, you have to understand units or understand the PC hardware
enough to do the work yourself. This chapter explains what a unit is, how
you use it, what predefined units are available, how to go about writing
your own units, and how to compile them.
61
Turbo Pascal provides seven standard units for your use. Five of
them-System, Graph, Dos, Crt, and Printer-provide support for your
regular Turbo Pascal programs. The other two- Turbo3 and Graph3 are
designed to help maintain compatibility with programs and data files
created under version 3.0 of Turbo Pascal. All but Graph are stored in the
file TURBO.TPL. Some of these are explained more fully in Chapter 5, but
we'll look at each one here and explain its general function.
A Unit's Structure
A unit provides a set of capabilities through procedures and functionswith supporting constants, data types, and variables-but it hides how
those capabilities are actually implemented by separating the unit into two
sections: the interface and the implementation. When a program uses a unit,
all the unit's declarations become available, as if they had been defined
within the program itself.
A unit's structure is not unlike that of a program, but with some significant
differences. Here's a unit, for example:
unit <identifier>;
interface
uses <list of units>;
{Optional
{ public declarations }
implementation
{ private declarations }
{ procedures and functions
begin
{ initialization code
end.
The unit header starts with the reserved word unit, followed by the unit's
name (an identifier), exactly like a program has a name. The next item in a
unit is the keyword interface. This signals the start of the interface section
of the unit-the section visible to any other units or programs that use this
unit.
A unit can use other units by specifying them in a uses clause. If present,
the uses clause appears immediately after the keyword interface.
Interface Section
The interface portion-the "public" part-of a unit starts at the reserved
word interface, which appears after the unit header and ends when the
reserved word implementation is encountered. The interface determines
62
what is "visible" to any program (or other unit) using that unit; any
program using the unit has access to these "visible" items.
In the unit interface, you can declare constants, data types, variables,
procedures, and functions. As with a program, these can be arranged in
any order, and sections can repeat themselves (for example, type ... var ...
<procs> ... const ... type ... const ... var).
The procedures and functions visible to any program using the unit are
declared here, but their actual bodies-implementations-are found in the
implementation section. forward declarations are neither necessary nor
allowed. The bodies of all the regular procedures and functions are held in
the implementation section after all the procedure and function headers
have been listed in the interface section.
Implementation Section
The implementation section-the "private" part-starts at the reserved
word implementation. Everything declared in the interface portion is
visible in the implementation: constants, types, variables, procedures, and
functions. Furthermore, the implementation can have additional
declarations of its own, although these are not visible to any programs
using the unit. The program doesn't know they exist and can't reference or
call them. However, these hidden items can be (and usually are) used by
the "visible" procedures and functions-those routines whose headers
appear in the interface section.
If any procedures have been declared external, one or more {$L filename}
directive(s) should appear anywhere in the source file before the final end
of the unit.
The normal procedures and functions declared in the interface-those that
are not inline-m ust rea ppear in the im plemen ta tion. The
procedure/ function header that appears in the implementation should
either be identical to that which appears in the interface or should be in the
short form. For the short form, type in the keyword (procedure or
function), followed by the routine's name (identifier). The routine will then
contain all its local declarations (labels, constants, types, variables, and
nested procedures and functions), followed by the main body of the routine
itself. Say the following declarations appear in the interface of your unit:
procedure ISwap(var Vl,V2 : integer);
function IMax(Vl,V2 : integer) : integer;
63
procedure ISwap;
var
Temp : integer;
begin
Temp := VI; VI := V2; V2 := Temp
end; {of proc ISwap }
function IMax(VI,V2 : integer) : integer;
begin
if VI > V2 then
IMax := VI
else IMax := V2
end; {of func IMax }
Routines local to the implementation (that is, not declared in the interface
section) must have their complete procedure/function header intact.
Initialization Section
The entire implementation portion of the unit is normally bracketed within
the reserved words implementation and end. However, if you put the
reserved word begin before end, with statements between the two, the
resulting compound statement-looking very much like the main body of a
program-becomes the initialization section of the unit.
The initialization section is where you initialize any data structures
(variables) that the unit uses or makes available (through the interface) to
the program using it. You can use it to open files for the program to use
later. For example, the standard unit Printer uses its initialization section to
make all the calls to open (for output) the text file Lst, which you can then
use in your program's Write and Writeln statements.
When a program using that unit is executed, the unit's initialization section
is called before the program's main body is run. If the program uses more
than one unit, each unit's initialization section is called (in the order
specified in the program's uses statement) before the program's main body
is executed.
64
As a result, using a unit or several units adds very little time (typically less
than a second) to the length of your program's compilation. If the units are
being loaded in from a separate disk file, a few additional seconds may be
required because of the time it takes to read from the disk.
As stated earlier, to use a specific unit or collection of units, you must place
a .uses clause at the start of your program, followed by a list of the unit
names you want to use, separated by commas:
program MyProgi
uses thisUnit,thatUnit,theOtherUniti
When the compiler sees this uses clause, it adds the interface information in
each unit to the symbol table and links the machine code that is the
implementation to the program itself.
The ordering of units in the uses clause is not important. If thisUnit uses
thatUnit or vice versa, you can declare them in either order, and the
compiler will determine which unit must be linked into MyProg first. In
fact, if thisUnit uses thatUnit but MyProg doesn't need to directly call any of
the routines in thatUnit, you can "hide" the routines in thatUnit by omitting
it from the uses clause:
unit thisUniti
uses thatUniti
program MyProgi
uses thisUnit, theOtherUniti
In this example, this Unit can call any of the routines in that Unit, and
MyProg can call any of the routines in thisUnit or theOtherUnit. MyProg
cannot, however, call any of the routines in that Unit because that Unit does
not appear in MyProg's uses clause.
If you don't put a uses clause in your program, Turbo Pascal links in the
System standard unit anyway. This unit provides some of the standard
65
unit MyStuff;
interface
const
MyValue = 915;
type
MyStars = (Deneb,Antares,Betelgeuse);
var
MyWord : string[20];
procedure SetMyWord(Star : MyStars);
function TheAnswer: integer;
What you see here is the unit's interface, the portion that is visible to (and
used by) your program. Given this, you might write the following
program:
program TestStuff;
uses MyStuff;
var
I
: integer;
AStar : MyStars;
begin
Writeln(MyValue);
AStar := Deneb;
SetMyWord(AStar);
Writeln(MyWord);
I := TheAnswer;
Writeln (I)
end.
Now that you have included the statement uses MyStuff in your program,
you can refer. to all the identifiers declared in the interface section in the
interface of MyStuff (MyWord, MyValue, and so on). However, consider the
following situation:
program TestStuff;
uses MyStuff;
const
MyValue = 22;
var
I
integer;
AStar : MyStars;
function TheAnswer
begin
TheAnswer := -1
end;
integer;
begin
Writeln(MyValue);
AStar := Deneb;
SetMyWord(AStar);
Writeln(MyWord);
I := TheAnswer;
Writeln (I)
end.
66
integer;
end;
begin
Writeln(MyStuff.MyValue);
AStar := Deneb;
SetMyWord(AStar);
Writeln(MyWord);
I := MyStuff.TheAnswer
Writeln(I)
end.
This program will give you the same answers as the first one, even though
you've redefined MyValue and TheAnswer. Indeed, it would have been.
perfectly legal (although rather wordy) to write the first program as
follows:
program TestStuff;
uses MyStuff;
var
I
: integer;
AStar : MyStuff.MyStars;
begin
Writeln(MyStuff.MyValue);
AStar := MyStuff.Deneb;
MyStuff.SetMyWord(AStar);
Writeln(MyStuff.MyWord);
I := MyStuff.TheAnswer;
Writeln(I)
end.
Note that you can preface any identifier-constant, data type, variable, or
subprogram-with the unit name.
67
TURBO.TPL
The file TURBO.TPL contains all the standard units except Graph: System,
Crt, Dos, Printer, Turbo3, and Graph3. These are the units loaded into
memory with Turbo Pascal; they're always readily available to you. You
will normally keep the file TURBO.TPL in the same directory as
TURBO.EXE (or TPC.EXE). However, you can keep it somewhere else, as
long as that "somewhere else" is defined as the Turbo directory. That's
done using TINST.EXE to install the Turbo directory directly in the
TURBO.EXE file.
System
Units used: none
System contains all the standard and built-in procedures and functions of
Turbo Pascal. Every Turbo Pascal routine that is not part of standard Pascal
and that is not in one of the other units is in System. This unit is always
linked into every program.
Dos
Dos defines numerous Pascal procedures and functions that are equivalent
to the most commonly used DOS calls, such as GetTime, SetTime, DiskSize,
and so on. It also defines two low-level routines, MsDos and Intr, which
allow you to directly invoke any MS-DOS call or system interrupt. Registers
is the data type for the parameter to MsDos and Intr. Some other constants
and data types are also defined.
Crt
68
Printer
Printer declares the text-file variable Lst and connects it to a device driver
that (you guessed it) allows you to send standard Pascal output to the
printer using Write and Writeln. For example, once you include Printer in
your program, you could do the following:
Write(Lst,'The sum of ' ,A:4,' and' ,B:4,' is ')i
:= A + Bi
Writeln(Lst,C:8)i
C
Graph3
Turbo3
This unit contains two variables and several procedures that are no longer
supported by Turbo Pascal. These include the predefined file variable Kbd,
the Boolean variable CBreak, and the original integer versions of MemAmil
and MaxAvail (which return paragraphs free instead of bytes free, as do the
current versions).
Graph
The Graph unit is not built into TURBO.TPL, but instead resides on the
same disk with the .BGI and .CHR support files. Place GRAPH.TPU in the
current directory or use the unit directory to specify the full path to
GRAPH.TPU.
Graph supplies a set of fast, powerful graphics routines that allow you to
make full use of the graphics capabilities of your PC. It implements the
device-independent Borland graphics handler, allowing support of CGA,
EGA, Hercules, AT &T 400, MCGA, 3270 PC, and VGA graphics.
Now that you've been introduced to units, let's see about writing your
own.
69
Note that Turbo Pascal expects the unit code file to have the same name (up
to eight characters) of the unit itself. If your unit name is MyUtilities, then
Turbo is going to look for a file called MYUTILIT.PAS. You can override
that assumption with the $U compiler directive. This directive is passed the
name of the .PAS file and must appear just before the unit's name in the
uses statement. For example, if your program uses Dos, Crt, and
MyUtilities, and the last one is stored in a file called UTIL.PAS, then you
would write
uses Dos, Crt, ($U UTIL.PAS) MyUtilities;
Compiling a Unit
You compile a unit exactly like you'd compile a program: Write it using the
editor and select the Compile/Compile command (or press Alt-C). However,
instead of creating an .EXE file, Turbo Pascal will create a .TPU (Turbo
Pascal Unit) file. You can then leave this file as is or merge it into
TURBO.TPL using TPUMOVER.EXE (see Chapter 7).
In any case, you probably want to move your .TPU files (along with their
source) to the unit directory you specified with the 0 /D /Unit directories
command. That way, you can reference those files without having to give a
{$U} directive (The Unit directories command lets you give multiple
directories for the compiler to search for in unit files.)
You can only have one unit in a given source file; compilation stops when
the final end statement is encountered.
An Example
Okay, now let's write a small unit. We'll call it IntLib and put in two simple
integer routines-a procedure and a function:
70
unit IntLib;
interface
procedure ISwap(var I,J : integer);
function IMax(I,J: integer) : integer;
implementation
procedure ISwap;
var
Temp : integer;
begin
Temp := I; I := J; J := Temp
end; {of proc ISwap
function IMax;
begin
if I > J then
IMax := I
else IMax := J
end; {of func IMax }
end. {of unit IntLib
Type this in, save it as the file INTLIB.PAS, then compile it to disk. The
resulting unit code file is INTLIB.TPU. Move it to your unit directory
(whatever that might happen to be).
This next program uses the unit IntLib:
program IntTest;
uses IntLib;
var
A,B : integer;
begin
Write('Enter two integer values: ');
Readln(A,B);
ISwap(A,B);
Writeln('A = ' ,A,' B = ' ,B)i
Writeln('The max is ' ,IMax(A,B))i
end. {of program IntTest }
71
TPUMOVER
You don't have to use a {$U <filename>} directive when using the standard
runtime units (System, Dos, and so on). That's because all those units have
been moved into the Turbo Pascal unit file (TURBO.TPL). When you
compile, those units are always ready to be used when you want them.
Suppose you want to add a well-designed and thoroughly debugged unit
to the standard units so that it's automatically loaded into memory when
72
you run the compiler. Is there any way to move it into the Turbo Pascal
standard unit library file? Yes, by using the TPUMOVER.EXE utility.
You can also use TPUMOVER to remove units from the Turbo Pascal
standard unit library file, reducing its size and the amount of memory it
takes up when loaded. (More details on using TPUMOVER can be found in
Chapter 7.)
As you've seen, it's really quite simple to write your own units. A welldesigned, well-implemented unit simplifies program development; you
solve the problems only once, not for each new program. Best of all, a unit
provides a clean, simple mechanism for writing very large programs.
73
74
5
Getting the Most from Your PC
Now that you've learned about Pascal and units, it's time to see how to put
it all together.
In this chapter, you'll start off learning about writing "textbook" programs
in Turbo Pascal, then move on to some of the extensions that Turbo Pascal
offers over standard Pascal. After that, we'll look at the standard units,
giving some sample programs of how to use the routines in them. Finally,
we'll touch on how to access machine and assembly language in your
Pascal program.
75
performing this task. In Turbo Pascal, you use the Assign procedure, which
has the format
Assign(filevar,filestr);
where fiZevar is a file variable of any type, and fiZestr any string expression
containing the name of a disk file (including its path name if desired or
necessary) .
Data-Type Extensions
Turbo Pascal 4.0 has some significant data-type extensions to standard
Pascal. These consist of new integer and floating-point data types that give
you greater control over variable precision and size.
In addition to the standard type integer (-32768 .. 32767), Turbo Pascal
supports shortint (-128 .. 127), byte (0 .. 255), word (0 .. 65535), and longint
(-2147483648 .. 2147483647). This variety of integer types allows you to
precisely define the variables and data structures you need, rather than
having to fit everything into the type integer.
Turbo Pascal 4.0 now has an option to support the 8087/80287/80387 math
coprocessor. When you enable the {$N+} compiler directive or environment
option, you then have access to four new data types: single (4-byte real),
double (8-byte real), extended (lO-byte real), and comp (8-byte integer). All
floating-point operations are compiled as calls to the 8087 coprocessor, so
that a program compiled using the {$N+} option can run only on a
computer equipped with that processor.
76
at the start of your program, after your program statement but before any
of your declarations. If you are using more than this one unit, you can list
all the units in this uses statement, separated by commas.
Let's start by writing a directory program. Here's the initial main body:
program GetOirectory;
uses Dos;
var
Path : string;
SRec : SearchRec;
{ Rest of program }
begin
repeat
Write('Enter path name: '); Readln(Path);
if Path <> " then
begin
FindFirst(Path,AnyFile,SRec);
while OosError = 0 do
begin
PutSRec(SRec);
FindNext(SRec)
end;
Writeln
end
until Path = "
end. { of proc GetOirectory
Note that the uses Dos statement is after the program statement, and also
that the global variables Path and SRec are declared. In this program
fragment, you are using five items from Dos: SearchRec, AnyFile, FindFirst,
Dos Error, and FindNext.
The procedure PutSRec is user-defined; it'll go right where the Rest of
program comment is. Let's look at that procedure:
procedure PutSRec(SRec : SearchRec);
var
OT : OateTime;
begin
with SRec do
begin
PutName(Name);
77
Again, you borrow from Dos: the data types SearchRec and DateTime, the
constant Directory, and the procedure UnpackTime. Name, Attr, Size, and
Time are all fields of SRec.
78
PutLead writes out an integer with a leading zero if it's less than 10.
PutDateTime prints out the date and time in the same format used by the
Dir command. Likewise, PutName writes out the file (or directory) name
using a Dir-like format.
This is just a small sample of what Turbo Pascal allows you to do with the
Dos unit. In addition to the file and clock manipulation routines, Dos offers
two general routines that let you make any DOS call or system software
interrupt: MsDos and Intr. Full details on this unit are found in Chapter 24.
Screen Routines
Another unit, Crt, gives you full control over your text display. It contains
many of the routines offered in version 3.0, but adds a number of new,
powerful routines. As with other features of Turbo Pascal, the emphasis is
on flexibility and user control. For example, you can now enable (or disable) program abort on Ctr/-Break, end-of-file recognition of Ctrl-Z, direct
output to video RAM (as opposed to using BIOS calls), and limiting direct
video RAM output to the period during horizontal retrace to avoid "snow"
onscreen.
To show you what you can do with the Crt unit, here's a simple "editing"
program that brings up a window on the screen and lets you type in text,
including some very simple editing commands. The main body of the program looks like this:
program Edit;
uses Crt;
const
Xl = 50;
Y1
5;
X2 = 75;
Y2 = 22;
var
Ch : char;
{ More code goes
begin
CheckBreak :=
CheckEOF
:=
DirectVideo :=
here
False;
False;
True;
79
SetWindow(X1,Y1,X2,Y2);
GoToXY(l,l);
repeat
Ch := ReadKey;
if Ch <> #0 then
HandleKey(Ch)
else HandleFuncKey(ReadKey)
until Ch = "Z;
Window (1, 1, 80,25);
ClrScr
end.
First, you turn off CheckBreak and CheckEOF and turn on DirectVideo. You
then set up your own window (Set Window is a user-defined routine) and
enter an input/output loop. This consists of reading in a character straight
from the keyboard (using ReadKey), checking to see if it's a function key or
not, then handling it appropriately. Note that if ReadKey returns a #0 (NUL
character), it means the user has pressed a function key, and the next call to
ReadKey gives the scan code. This loop continues until the user types a CtrlZ, at which point the program resets the screen.
The Set Window procedure (which follows) uses the special line-drawing
characters of the IBM PC to draw a border around the requested window
area. It clears that window and then sets the cursor in the upper left-hand
corner of the actual text area.
Note that once you've called Window,
upper left screen. Here's the code:
GotoXY (1,1)
80
GoToXY(Xl-l,Y2+l);
Write(LowLeftCorner);
for I := Xl to X2 do
Write(HorzBar);
Write(LowRightCorner);
Window(Xl,Yl,X2,Y2)
end; ( of proc SetWindow
The last two procedures called in the main program are HandleKey and
HandleFuncKey. These execute an action based on the character value or
scan code. Note that only the arrow keys are used for HandleFuncKey, and
the user-defined routines SetXY and Condition limit the movement of the
cursor. These routines appear before the main body of the program.
procedure HandleKey(Ch : char);
const
BEL = #7;
BS = #8;
CR = #13;
SP = #32;
begin
if Ch = BS
then Write(BS,SP,BS)
else if Ch = CR
then Writeln
else if Ch >= SP
then Write (Ch)
else if Ch <> AZ
then Write (BEL)
end; { of proc HandleKey
procedure Condition(Low : integer; var X
begin
if X < Low then
X := Low
else if X > High then
X := High
end; ( of proc Condition
{ Bell
Backspace
{ Enter
Space bar
{ Enter }
integer; High
integer);
char);
81
begin
case Ch of
UpArrow
SetXY(WhereX,WhereY-l)
LeftArrow
SetXY(WhereX-l,WhereY)
RightArrow SetXY(WhereXtl,WhereY)
DownArrow
SetXY(WhereX,WhereYtl)
end
end; { of proe HandleFuneKey }
Again, this is only a sample of what you can achieve using the Crt unit. For
full documentation, see Chapter 24.
Graphics Routines
Turbo Pascal 4.0 contains the Graph unit, which supports the new Borland
device-independent standard for graphics devices; Graph implements more
than 50 graphics procedures and functions.
For an example of the use of graphics, take a look at the sample program
with Graph in Chapter 2. Also, several example programs are given on your
distribution disks; full documentation can be found in Chapter 24.
82
ftype;
You can then use these procedures and functions as you would any others.
However, you are not actually calling subroutines. Instead, the Turbo
Pascal compiler replaces each call with the given inline code. Because of
that, inline directives are typically not very large. See Chapter 26 for more
details and examples.
83
Note that there is no body to the procedure or function, only the header
statement.
The procedure/function headers go wherever a regular procedure or
function can go. If they're in a program, you can place them anywhere (as
long as you define them before you use them). If they're in a unit, they can
go either in the interface (if you want the user to be able to call them) or in
the implementation (if you don't) section.
Next, write the appropriate routines using an assembler that generates
standard .OBJ files. Two assemblers that Turbo Pascal works. with are A86
.and MASM. (A86 is a shareware assembler available from Eric Isaacson of
Bloomington, Indiana. A86 is downloadable from CompuServe and many
bulletin board systems. MASM is Microsoft's macro-assembler.) Refer to
Chapter 26 for details on how Turbo Pascal passes parameters to external
routines, and how external functions should pass values back.
Finally, you must tell the compiler what file to link to it, using the {$L}
compiler directive. If you had assembled your assembly language routines
into a file called MYSTUFF.OBJ, then you'd put the following directive
somewhere in your program:
{$L MyStuff}
This directive can appear anywhere before the begin of the main body of
your program or the begin of the initialization section in your unit (if
you're writing your own unit).
When you compile your program, Turbo Pascal goes to MYSTUFF.OBJ,
copies the machine code into your application file, and creates the
necessary links.
This chapter gave you an idea of the kinds of programs you can write for
the IBM PC; what you actually decide to write is limited only by your
system memory and your imagination. There are more examples on the
distribution disks and in Chapter 27.
84
6
Project Management
So far, you've learned how to write Turbo Pascal programs, how to use the
predefined units, and how to write your own units. At this point, your
program has the capability of becoming large and separated into multiple
source files. How do you manage such a program? This chapter suggests
how to organize your program into units, how to take advantage of the
built-in Make and Build options, how to use the stand-alone Make utility,
how to use conditional compilation within a source code file, and how to
optimize your code for speed.
Program Organization
Turbo Pascal 4.0 allows you to divide your program into code segments.
Your main program is a single code segment, which means that after
compilation, it can have no more than 64K of machine code. However, you
can exceed this limit by breaking your program up into units. Each unit can
also contain up to 64K of machine code when compiled. The question is
how should you organize your program into units?
The first step is to collect all your global definitions-constants, data types,
and variables-into a single unit; let's call it MyGlobals. This is necessary if
your other units reference those definitions. Unlike include files, units can't
"see" any definitions made in your main program; they can only see what's
in the interface section of their own unit and other units they use. Your
units can use MyGlobals and thus reference all your global declarations.
A second possible unit is MyUtils. In this unit you could collect all the
utility routines used by the rest of your program. These would have to be
85
routines that don't depend on any others (except possibly other routines in
MyUtils).
Beyond that, you should collect procedures and functions into logical
groups. In each group, you'll often find a few procedures and functions
that are called by the rest of the program, and then several (or many)
procedures/functions that are called by those few. A group like that makes
a wonderful unit. Here's how to convert it over:
Copy all those procedures and functions into a separate file and delete
them from your main program.
Open that file for editing.
Type the following lines in front of those procedures and functions:
unit unitname;
interface
uses MyGlobals;
implementation
where unitname is the name of your unit (and also the name of the file
you're editing).
Type end. at the very end of the file.
Into the space between interface and implementation, copy the procedure and function headers of those routines called by the rest of the
program. Those headers are simply the first line of each routine, the one
that starts with procedure (or function).
If this unit needs to use any others, type their names (separated by
commas) between MyGlobals and the semicolon in the uses statement.
Compile the unit you've created.
Go back to your main program and add the unit's name to the uses
statement at the start of the program.
Ideally, you want your program organized so that when you are working
on a particular aspect of it, you are modifying and recompiling a single
segment (unit or main program). This minimizes compile time; more
importantly, it lets you work with smaller, more manageable chunks of
code.
Initialization
Remember in all this that each unit can (optionally) have its own
initialization code. This code is automatically executed when the program
is first loaded. If your program uses several units, then the initialization
code for each unit is executed. The order of execution follows in which the
86
units are listed in your program's uses statement; thus, if your program
had the statement
uses MyGlobals,MyUtils,EditLib,GraphLib;
then the initialization section (if any) of MyGlobals would be called first,
followed by that of MyUtils, then EditLib, then GraphLib.
To create an initialization section for a unit, put the keyword begin above
the end that ends the implementation section. This defines the initialization
section of your unit, much as the begin.. end pair defines the main body of
a program, a procedure, or a function. You can then put any Pascal code
you want in here. It can reference everything declared in that unit, in both
the public (interface) and private (implementation) sections; it can also
reference anything from the interface portions of any units that this unit
uses.
87
88
A Quick Example
Suppose you're writing some programs to help you display information
about nearby star systems. You have one program-GETSTARS.PAS-that
reads in a text file listing star systems, does some processing on it, then
produces a binary data file with the resulting information in it.
GETSTARS.P AS uses three units: STARDEFS.TPU, which contains the
global definitions; STARLIB.TPU, which has certain utility routines; and
STARPROC.TPU, which does the bulk of the processing. The source code
for these units are found in STARDEFS.PAS, STARLIB.PAS, and
STARPROC.PAS, respectively.
Chapter 6, Project Management
89
Creating a Makefile
Your makefile for this project might look like this:
getstars.exe: getstars.pas stardefs.pas starlib.pas slibl.asm \
slib2.asm slibl.obj slib2.obj
tpc getstars 1m
slibl.obj: slibl.asm
A86 slibl.asm slibl.obj
slib2.obj: slib2.asm
A86 slib2.asm slib2.obj
90
The third line tells MAKE how to build a new GETSTARS.EXE. Notice
that it simply invokes the command-line compiler on GETSTARS.PAS
and uses the built-in Turbo Pascal Make facility (/ M option).
The next two lines (ignoring the blank line) tell MAKE that SLIB1.0BJ
depends on SLIB1.ASM and show MAKE how to build a new SLIB1.0BJ.
Similarly, the last two lines define the dependencies (only one file,
actually) and MAKE procedures for the file SLIB2.0BJ.
Using MAKE
Let's suppose you've created this file using the Turbo Pascal integrated
environment editor (or any other ASCII editor) and saved it as the file
STARS.MAK. You would then use it by issuing the command
make -fstars.mak
where - f is an option telling MAKE which file to use. MAKE works from
the bottom of the file to the top. First, it checks to see if SLIB2.0BJ is older
than SLIB2.ASM. If it is, then MAKE issues the command
A86 SLIB2.asm SLIB2.obj
1m
The / M option tells Turbo Pascal to use its own internal MAKE routines,
which will then resolve all unit dependencies, including recompiling
STARLIB.PAS if either SLIB1.0BJ or SLIB2.0BJ is newer than
STARLIB.TPU.
This is only a simple example using MAKE; more complete documentation
can be found in Appendix D.
Conditional Compilation
To make your job easier, Turbo Pascal version 4.0 offers conditional
compilation. This means that you can now decide what portions of your
program to compile based on options or defined symbols.
The conditional directives are similar in format to the compiler directives
that you're accustomed to; in other words, they take the format
91
{$directive arg}
where directive is the directive (such as DEFINE, IFDEF, and so on), and arg
is the argument, if any. Note that there must be a separator (blank, tab)
between directive and argo Table 6.1 lists all the conditional directives, with
their meanings.
Table 6.1: Summary of Compiler Directives
{$DEFINE symbol}
{$UNDEF symbol}
{$IFDEF symbol}
{$IFNDEF symbol}
{$IFOPTx+}
{$IFOPTx-}
{$ELSE}
{$ENDIF}
into your program. symbol follows the usual rules for identifiers as far as
length, characters allowed, and other specifications. For example, you
might write
{$DEFINE debug}
This defines the symbol debug for the remainder of the program, or until the
statement
{$UNDEF debug}
This would define the symbols debug, test, and dump for the program
MYPROG.PAS. Note that the / D option is cumulative, so that the following
command line is equivalent to the previous one:
tpc myprog /Odebug /Otest /Odump
Predefined Symbols
In addition to any symbols you define, you also can test certain symbols
that Turbo Pascal has defined. Table 6.2 lists these symbols; let's look at
each in a little more detail.
Table 6.2: Predefined Conditional Symbols
VER40
MSDOS
CPU86
CPU87
93
You can use a similar construct to define variables, or you could use the
{$IFOPT N+} directive to handle those.
94
If the expression in IFxxx is True, then source code A is compiled, else source
code B is compiled.
Note that all IFxxx directives must be completed within the same source
file, which means they cannot start in one source file and end in another.
However, an IFxxx directive can encompass an include file:
{$IFxxx}
{$I filel.pas}
{$ELSE}
{$I file2.pas}
{$ENDIF}
That way, you can select alternate include files based on some condition.
You can nest IFxxx .. ENDIF constructs so that you can have something like
this:
{$IFxxx}
{ First IF directive
{$IFxxx}
{ Second IF directive
{$ENDIF}
{$ENDIF}
95
{$N+}
{$ELSE}
{$N-}
{$ENDIF}
By putting this in your program, you can automatically select the $N option
if an 8087 math coprocessor is present when your program is compiled.
That's an important point: This is a compile-time option. If there is an 8087
coprocessor in your machine when you compile, then your program will be
compiled with the $N+ compiler directive or environment option, selecting
direct calls to the 8087 and allowing you to use only the IEEE floating-point
types. Otherwise, it will be compiled with the $N- directive or option, using
the software floating-point package and allowing you to use only the usual
Turbo Pascal 6-byte real data type. If you compile this program on a
machine with an 8087, you can't run the resulting .EXE file on a machine
without an 8087.
Another typical use of the IFDEF and IFNDEF directives is debugging. For
example, you could put the following code at the start of each procedure:
{$IFDEF debug}
Writeln('Now entering proc name');
Readln;
{$ENDIF}
where proc name is the name of that procedure. If you put the following
directive at the start of your program:
{$DEFINE debug}
and compile your program, then those statements will be included at the
start of each procedure. If you remove the DEFINE directive or follow it
with an UNDEF directive, then those statements at the start of each
procedure won't be compiled. In a similar fashion, you may have sections
of code that you want compiled only if you are not debugging; in that case,
you would write
{$IFNDEF debug}
source code
{$ENDIF}
where source code will be compiled only if debug is not defined at that point.
96
have been selected. Turbo Pascal lets you do that with the IFOPT directive,
which takes two forms:
($IFOPT
Xi}
and
($IFOPT x-}
: double;
: real;
This selects the data type for the listed variables based on whether or not
8087 support is desired. If you combine this with the {$IFDEF CPU87}
example given earlier, then your source code will automatically select the
proper compiler option and data type(s) based on whether there's an 8087
coprocessor in the machine on which you're compiling.
An alternate example might be
Assign(F,Filename);
Reset(F);
($IFOPT I-}
IOCheek;
($ENDIF}
Optimizing Code
A number of compiler options influence both the size and the speed of the
code. This is because they insert error-checking and error-handling code
into your program. They are best left enabled while you are developing
your program, but you may want to disable them for your final version.
Here are those options, with their settings for optimization:
97
{$B-} uses short-circuit Boolean evaluation. This produces code that can
run faster, depending upon how you set up your Boolean expressions.
The default equals B-.
{$I-} turns off I/O error-checking. By calling the predefined function
IOResuit, you can handle I/O errors yourself. The default equals 1+.
{$R-} turns off range-checking. This prevents code generation to check for
array subscripting errors and assignment of out-of-range values. The
default equals R-.
{$S-} turns off stack-checking. This prevents code generation to ensure
that there is enough space on the stack for each procedure or function
call. The default equals 5+.
{$V-} turns off checking of var parameters that are strings. This lets you
pass actual parameters strings that are of a different length than the type
defined for the formal var parameter. The default equals V+.
Disabling each of these options has two advantages. First, it usually makes
your code smaller and faster. Second, it allows you to get away with
something that you couldn't normally. However, they all have corresponding risks as well, so use them carefully, and reenable them if your
program starts behaving strangely.
Note that besides embedding the compiler options in your source code
directly, you can also set them using the Options/Compiler menu in the
integrated environment or the /$x option in the command-line compiler
(where x represents a letter for a compiler directive).
98
7
Using the Unit Mover
When you write units, you want to make them easily available to any
programs that you develop. Chapter 4 explains what a unit is and tells how
to create your own units. This chapter shows you how to use TPUMOVER
to remove seldom-used units from TURBO.TPL, and how to insert oftenused units into TURBO.TPL.
99
Normally, when you write your own unit, it gets saved to a .TPU file; to use
that unit, you must tell Turbo Pascal where to find it. If you're using the
integrated environment, you must set the Unit directories option in the
Options/Directories menu. (TURBO.TPL is loaded from the Turbo
directory in the same menu.) If you're using the command-line environment, you must use the /U option. (Use the /T option to load the Turbo
library from another subdirectory in the command-line compiler.)
You may have noticed, though, that you can use the standard Turbo Pascal
units without giving a file name. That's because these units are stored in
the Turbo Pascal standard unit file-TURBO.TPL on your distribution disk.
Because the units are in that file, any program can use them without
"knowing" their location.
Suppose you have a unit called TOOLS.TPU, and you use it in many
different programs. Though adding Tools to TURBO.TPL takes up memory
(TURBO.TPL is automatically loaded into memory by the compiler),
adding it to the resident library makes "using" Tools faster because the unit
is in memory instead of on disk.
There are six standard units already in TURBO.TPL: System, Printer, Crt,
Dos, Turbo3, and Graph3.
You probably won't ever use Turbo3 or Graph3 unless you have a lot of
programs written with version 3.0 and haven't yet converted them. So, you
might as well use TPUMOVER to remove them from TURBO.TPL and
recover about 10K of memory.
Using TPUMOVER
TPUMOVER is a display-oriented program, much like the integrated
environment. It shows you the units contained in two different files and
allows you to copy units back and forth between them or to delete units
from a given file. It's primarily used for moving files in and out of
TURBO.TPL, but it has other useful functions.
Note that the TPUMOVER display consists of two side-by-side windows.
The name of the file appears at the top of the window, followed by a list of
the units in that file. Each line in a window gives information for a single
unit: unit name, code size, data size, symbol table size, and the name(s) of
any unit(s) that this unit uses. The sizes are all in bytes, and the unit names
are all truncated to seven characters. If the list of units being used is too
long to fit, it ends with three dots; press F4 to see a pop-up window to see
the names of the other unit dependencies. Finally, two lines of information
100
appear in that window, giving (in bytes) the current size of that file and the
amount of free space on the disk drive containing that file.
At any time, one of the two windows is the "active" window. This is
indicated by a double line around the active window. Also, only the active
window contains a highlighted bar that appears within the list of units in
that file; the bar can be moved up or down using the arrow keys All
commands apply to the active window; pressing F6 switches back and forth
between the two windows.
To use TPUMOVER, simply type
TPUMOVER filel file2
where filel and file2 are .TPL or .TPU files. The extension .TPU is assumed,
so you must explicitly add .TPL for .TPL files.
TPUMOVER loads and displays two windows-with filel in the left
window of the display and file2 in the right window. Note that both filel
and file2 are optional. If you only specify filel, then the right window has
the default name NONAME.TPU. If you don't specify either file,
TPUMOVER will attempt to load TURBO.TPL (in the left window with
nothing in the right window). If that file cannot be found, TPUMOVER will
display a directory of all files on the current disk that end in .TPL.
TPUMOVER Commands
The basic commands are listed at the bottom of the screen. Here's a brief
description of each:
101
Ins copies all marked units from the active window to the inactive
window .
Del deletes all marked units from the active window.
Esc lets you exit from TPUMOVER. Note that this does not automatically
save any changes that were made; you must explicitly use F2 to save
modifications before leaving TPUMOVER.
This will bring up the TPUMOVER display with TURBO.TPL in the left
window (the active one) and TOOLS.TPU in the right window. Note that
this example assumes that TURBO.TPL and TOOLS.TPU are both in the
current directory; if they are not, then you need to supply the appropriate
path name for each.
N ow perform the following steps:
1.
2.
3.
4.
5.
6.
The unit Tools is now part of TURBO.TPL and will be automatically loaded
whenever you use Turbo Pascal.
If you want to add other units to TURBO.TPL, you can do so without
exiting TPUMOVER. After pressing F2 to save TURBO.TPL to disk,
perform the following steps:
102
You can repeat this as many times as desired in order to build up your
library.
Use the Down arrow key to move the highlighted bar over Turbo3.
Press + to select Turbo3.
Press Del to delete Turbo3.
Press F2to save the changes to TURBO.TPL.
Press Esc to exit TPUMOVER.
103
Command-Line Shortcuts
You can use several command-line parameters that let you manipulate
units quickly. The format for these parameters is
TPUMOVER TURBO /parameter unitname
1+
1-
1*
I?
104
8
Converting from Turbo Pascal 3.0
Turbo Pascal 4.0 contains some exciting new features. This chapter
discusses the tools we've provided to help you convert your 3.0 programs
to 4.0. Note that in some cases, changes in your source code may be
necessary.
We've provided a few upgrading tools: UPGRADE.EXE and two
compatibility units, Turbo3 and Graph3.
UPGRADE reads in a version 3.0 source code file and makes a series of
changes to convert it for compilation under version 4.0. Some of these
changes include commenting out obsolete buffer sizes, inserting appropriate uses statements, and optionally splitting large applications into
separate units.
Turbo3 offers several predefined identifiers from version 3.0 that version 4.0
no longer supports. Graph3 supports the full set of graphics calls (basic,
Using UPGRADE
The UPGRADE program will aid in converting Turbo Pascal programs
written for earlier versions of the compiler. UPGRADE scans the source
code of an existing program, and performs the following actions:
Chapter 8, Converting from Turbo Posco/3.G
105
. Places warnings in the source where Turbo Pascal 4.0 differs in syntax or
runtime behavior from earlier versions of the compiler.
Automatically fixes some constructions that have new syntactic
requirements.
Optionally writes a journal file that contains detailed warnings and
advice for upgrading a program to 4.0.
Automatically inserts a uses statement to pull in needed routines from
the standard units.
Optionally divides large programs into multiple units, to remove
overlays or take advantage of separate compilation.
In order to use UPGRADE, you must access two files from your Turbo
Pascal distribution disk. Copy the files UPGRADE.EXE and UPGRADE.DTA into your working drive and directory, or copy them into a
subdirectory that is listed in the MS-DOS path.
UPGRADE is command-line driven; its format from the DOS prompt is
UPGRADE {options] filename
filename specifies the name of an existing Pascal source file, which should be
present in the current drive and directory. If no extension is specified,
UPGRADE assumes '.PAS' as the file's extension.
106
This comment refers to the fact that Turbo Pascal 4.0 uses a new syntax to
specify buffering of text files. Instead of the optional bracketed buffer size
in the data declaration, Turbo Pascal 4.0 provides a new standard
procedure SetTextBuf, which should be called to specify a buffer area and
buffer size. Note that in this case UPGRADE automatically comments out
the obsolete buffer size, and inserts a comment notifying you to call the
SetTextBuf procedure at the appropriate location in your program.
UPGRADE accepts the following options on the command line:
13
II
IN
10 [d:][path]
IU
107
.Kbd
CBreak
MemAvail
MaxAvail
LongFileSize
LongFilePos
LongSeek
If your program uses any of these identifiers and you specify the /3 option,
UPGRADE will insert the Turbo3 unit name into the uses statement
genera ted for the program.
Although the Turbo3 unit and the /3 option can minimize the time required
to convert an existing application, in the long run it may be better to make
the (small) additional effort to use Turbo Pascal 4.0' s new facilities. If you
don't specify the /3 option, you will cause UPGRADE to generate warnings
for each instance of the identifiers. With these warnings and the journal file
(described next), you can achieve a complete upgrade in a short time.
IN No Source Markup
Use this option is you don't want UPGRADE's comments inserted into
your source code. UPGRADE will still perform any automatic fixes: the
uses statement, Turbo Pascal 3.0 default compiler directives, mapping of
compiler directives to Turbo Pascal 4.0 standards, and deactivation of
Overlay, Ovrpath, and text buffer sizes.
Generally, you should use the /N option in combination with the If (journal
file) or /U (unitize) option.
IU Unitize
The /U option activates a second major function of UPGRADE. In
combination with directives you place into your existing source code,
UPGRADE will automatically split a large application into separate units.
You should use the /U option only if your program is large enough to
require overlays in Turbo Pascal 3.0, or if compilation times are long
enough to be bothersome.
Before using the /U option, you must make minor additions to your
existing source program. These additions take the form of special
comments that serve as directives to the UPGRADE utility. Each directive
must have the following form:
{. U unitname}
109
It does not match the name of any existing global identifier in the
(*.U ScrnUnit *)
{ . u heapstuf}
110
111
a The Form function (and BCD arithmetic) are not supported in Turbo
Pascal 4.0.
BufLen (for restricting Readln) is not supported in Turbo Pascal 4.0.
The TextMode procedure requires a parameter (Mode:integer) in Turbo
Pascal 4.0.
a interrupt, unit, interface, implementation, and uses are now reserved
words.
System, Dos, and Crt are standard unit names in Turbo Pascal 4.0.
a Special file names INP:, OUT:, ERR: are not supported in Turbo Pascal
4.0.
Assign unsigned values of $8000 or larger only to word or longint types.
aUse Turbo3 unit in order for MemAvail and MaxAvail to return
paragraphs.
a Use Turbo3 unit to perform LongFile operations.
a Cbreak has been renamed to CheckBreak in Turbo Pascal 4.0.
a 10Result now returns different values corresponding to DOS error codes.
a Use Turbo3 unit for access to Kbd, or instead use Crt and ReadKey.
a The $1 include file directive must now be followed by a space.
a Directives A, B, C, D, F, G, P, U, W, and X are obsolete or changed in
meaning.
a Stack-checking directive K has been changed to S in Turbo Pascal 4.0.
The effects of HighVideo, LowVideo, and NormVideo are different in Turbo
Pascal 4.0.
a Special file name LST: is not supported now. Use Printer Lst file.
a Special file name KBD: is not supported now. Use Turbo3 Kbd file.
a Special file names CON:, TRM:, AUX:, USR: are not supported in Turbo
Pascal 4.0.
a Special devices Can, Trm, Aux, Usr are not supported in Turbo Pascal
4.0.
a An identifier duplicating a program/unit name is not allowed in Turbo
Pascal 4.0; instead use the Registers type from the Turbo Pascal 4.0 Dos
unit.
a forwards will require manual modification after unitizing.
a Include directives cannot be located within an executable block.
a The CrtInit and Crt Exit procedures are not supported in Turbo Pascal 4.0.
for loop counter variables must be pure locals or globals in Turbo Pascal
4.0.
a All defined labels within the current routine must be used.
112
Type mismatches due to Turbo Pascal 4.0' s more stringent checking; for
example:
var
a : Ainteger;
b : Ainteger;
begin
a := b;
end.
{ Invalid assignment }
Turbo Pascal 3.0 would have always called the built-in IOResult function,
and thus cleared it to zero when the Boolean expression was evaluated.
With short-circuiting activated in Turbo Pascal 4.0, the IOResult function
would not be called if HaltOnError were False, and thus IOResult would
potentially be left holding an error code from the previous I/O
operation.
Note that UPGRADE automatically inserts compiler directives that
deactivate Boolean short-circuiting, thus avoiding problems such as that
just described. Use caution before changing the Boolean evaluation
directive.
An UPGRADE Checklist
Here is a summary of the basic steps for using UPGRADE:
1. Copy the files UPGRADE.EXE and UPGRADE.DTA from the compiler
distribution disk to your current directory or to a directory in the DOS
path.
2. If necessary, go to the directory where the Pascal source files for the
program you wish to upgrade are located.
3. Decide which UPGRADE options, if any, you wish to use.
Chapter 8, Converting from Turbo Pascal 3.0
113
4. If you decide to unitize the program, you must first edit the main source
file to insert r.u unitname} directives, subject to the restrictions outlined
previously.
5. From the DOS command line, enter the appropriate UPGRADE
command, using the following syntax:
UPGRADE [options] filename
6. UPGRADE will make two passes through the source code: one pass to
detect areas of the program that may require modification, and a second
pass to insert the appropriate uses statement, and optionally complete
the process of unitization. At the end of the second pass, it will report
the number of warnings that it generated.
7. When UPGRADE is finished, change to the directory where output was
sent (if other than the current directory). If you specified the /1 option,
you may wish to browse through the journal file first to see the detailed
explanations of UPGRADE's warnings. After doing so, use the Turbo
Pascal editor to edit each source file that UPGRADE produced. Search
for the string {!. Each match will display a warning produced by
UPGRADE. In many cases, you will be able to change the source code
immediately-when you do so, you may wish to delete UPGRADE's
warning.
8. Once you have looked at all of UPGRADE's warnings and made
changes to your source code as appropriate, you are ready to compile
with Turbo Pascal 4.0.
Both units are already in TURBO.TPL; if you plan on using one or both,
place the statement
uses unitname;
114
at the start of your program, following your program header (if you have
one). If you use more than one unit, then the unit names should be
separated by commas,like this:
uses Crt,Turbo3,Graph3;
Kbd: Version 4.0 doesn't have the predefined file variable Kbd; instead, it
provides the function ReadKey. However, for those of you who don't
want to change your program, you can use Kbd instead .
.. CBreak: This was an undocumented Boolean variable in version 3.0. It is
named CheckBreak in version 4.0 and is documented in Chapter 24.
Turbo3 declares CBreak to be at the same address so that you can use it
instead.
MemAvail: Version 4.0 has MemAvail, but it is a function of type longint
and returns the memory available in bytes. The Turbo3 version returns
the amount available in paragraphs (groups of 16 bytes), as version 3.0
did. Note that if you use Turbo3, this will now be the default version of
MemAvail; to access the version 4.0 MemAvail, you must refer to
System.MemAvail.
MaxAvail: returns the size of the largest chunk of available memory in
paragraphs, while version 4.0 returns it in bytes. Again, if you use
Turbo3, you'll need to refer to System.MaxAvail to get the one in version
4.0.
LongFileSize: The FileSize function in version 4.0 is of type longint and can
handle any file. Turbo3 supports this function (of type real) for version 3.0
compatibility.
LongFilePos: The LongFilePos function in version 4.0 is of type longint and
can handle any file. Turbo3 supports this function (of type real) for
version 3.0 compatibility.
LongSeek: The LongSeek function in version 4.0 is of type longint and can
handle any file. Turbo3 supports this function (of type real) for version 3.0
compatibility.
IOResult: The 4.0 IOResult returns different error codes. Turbo3's IOResult
simply calls System.IOResult, and re-maps the 4.0 error codes in the same
way Turbo Pascal 3.0 did (wherever possible).
115
NormVideo, LowVideo, and HighVideo: By using the Turbo3 unit, these three
routines will set the foreground and background colors to the same as
3.0:
Mono/B&W
Color
LowVideo
light gray
Norm Video
High Video
white
white
light
gray
yellow
yellow
116
Predefined Identifiers
Version 4.0 doesn't support all the predefined identifiers (constants, types,
variables, procedures, functions) that version 3.0 did. Some have been
dropped; others have been superseded by new identifiers; still others have
been moved into the units found in TURBO.TPL.
Use Crt as needed.
D Use Turbo3 and/or Graph3 as needed. This is a great stop-gap measure,
but ultimately you may want to completely convert to version 4.0
identifiers. (HELPFUL)
II Take advantage of the new routines found in the standard units, such as
ReadKey (returns a scan code). (HELPFUL)
Use the appropriate units for certain data types, variables, procedures,
and functions that were "built-in" in version 3.0. For example, the
procedures Intr and MsDos are no longer predeclared; instead, they are
found in the Dos unit. Similarly, the Lst device (text file associated with
the printer) is defined in the Printer unit. (ESSENTIAL)
Data Types
Version 4.0 introduces a number of new data types and language functions
involving data types. Many of these will help you to drop some of the
"kludges" you've had to use in the past.
Use typecasting in place of the MoveO routine to copy the contents of one
variable into the space of another variable of an incompatible type. For
example, use
RealVar := real(BuffPtr A);
instead of
Move(BufferPtrA,RealVar,SizeOf(RealVar));
With extended typecasting, you can handle most such transfers as long
as the destination is the exact same size as the source. (HELPFUL)
Convert to new data types where appropriate and practical. These
include longint and word (to replace integer); pointer as a generic pointer
type; and string, with an assumed maximum length of 255 characters.
(RECOMMENDED)
Be aware that hexadecimal (base 16) constants are considered to be of
type word rather than type integer, so that the hex constant $FFFF
represents 65535 instead of -1. You should consider converting any
117
is not. (ESSENTIAL)
Version 4.0 enforces stricter type-checking on derived types, which
means that variables must have identically named types or be declared
together in order to be assignment compatible. For example, given
var
A : "integer;
B : "integer;
: "integer;
118
Either of these solutions will work just fine; the second one is more
general and is preferred (allowing other variables, parameters, and
functions to be of the same data type). (ESSENTIAL)
II The BCD data type (and the Form routine) are not supported in this
version. Consider using the longint data type; if you have a math
coprocessor, then use the {$N+} directive and use the IEEE type comp (8byte integer). (See the sample program on disk, BCD.PAS.) (ESSENTIAL)
Language Features
Version 4.0 introduces some restrictions and some enhancements. The
restrictions are geared to help it conform to the ANSI standard definition of
Pascal, while the enhancements are there to make your life as a
programmer easier.
.. Version 4.0 assumes short-circuit Boolean evaluation. This means that
evaluation of Boolean expressions is halted as soon as possible. For
example, consider the expression
if exprl and expr2 ...
If exprl is False, then the entire expression will be False, regardless of the
value of expr2. If Boolean expression evaluation is short-circuit, then if
exprl is False, expr2 won't be evaluated. This means, for example, if expr2
contains a function call, then that function won't be called if exprl is
False. You can enable complete (nonshort-circuit) Boolean evaluation
with the {$B+} compiler directive or the environment option in the
Options/Compiler menu. Be aware of the implications of enabling
short-circuit evaluation. (HELPFUL)
Keeping in line with the ANSI standard, Turbo Pascal version 4.0 allows
you to use only global and local variables as for loop control variables.
For example, if the statement
for Indx := Start to Finish ...
119
Version 4.0 has a new compiler directive, {$M}, that allows you to set the
stack and heap sizes within your program. The format is as follows:
{$M stacksize,heapmin,heapmax}
where all three values are in bytes. The default values are {$M
16384,O,655360}. You can also set the default values in the integrated
environment (O/e/Memory sizes) and use the command-line compiler
(/$M). (HELPFUL)
Convert large programs from overlays to units. You must do this,
because version 4.0 does not support overlays. If you have been using
overlays to get around the 64K code limit, then you won't have to worry
anymore: The main program and each unit can be up to 64K in size. If
you've been using overlays because all your code wouldn't fit into
memory at once anyway, then you'll have to do some rewriting-the
main program and all units must fit into memory at the same time.
(ESSENTIAL)
Be aware that MemAvail and MaxAvail are now of type longint and return
their values in bytes instead of paragraphs. You should make the
appropriate changes to your program (or use Turbo3, which supplies the
original versions of MemAvail and MaxAvail). (ESSENTIAL)
121
your Turbo Pascal verion 4.0 distribution disk for any additional
conversion notes.
123
124
9
Debugging Your Turbo Pascal
Programs
The term debugging comes from the early days of computers, when actual
bugs (moths and the like) sometimes clogged up the machinery. Nowadays,
it means correcting errors in a program.
You'll undoubtedly have bugs to contend with-errors of syntax,
semantics, and logic within your program-and you'll have to fix them by
trial and error. However, there are tools and methods to make it less of a
trial and to cut down on the errors. In this chapter, we'll look at common
errors and the different ways to debug them.
Compile-Time Errors
A compile-time, or syntax, error occurs when you forget to declare a
variable, you pass the wrong number of parameters to a procedure, or you
assign a real value to an integer variable. What it really means is that you're
writing Pascal statements that don't follow the rules of Pascal.
Pascal has strict rules, especially compared to other languages, so once
you've cleaned up your syntax errors, much of your debugging will be
done.
Turbo Pascal won't compile your program (generate machine code) until all
your syntax errors are gone. If Turbo Pascal finds a syntax error while
compiling your program, it stops compiling, goes into your program,
locates the error, positions the cursor there, and prints what the error
message was in the Edit window. Once you've corrected it, you can start
compiling again.
Chapter 9, Debugging Your Turbo Pascal Programs
125
Runtime Errors
Another type of error that can occur is a runtime (or semantic) error. This
happens when you compile a legal program but then try to do something
illegal while executing it, such as open a nonexistent file for input or divide
an integer by o. In that case, Turbo Pascal prints an error message to the
screen that looks like this:
Runtime error ## at seg:ofs
and halts your program. If you ran your program from the MS-DOS
prompt, you'll be returned to MS-DOS. If you ran it under Turbo Pascal,
you'll get the usual Press any key ... message.
If you're running under the integrated environment, then Turbo Pascal
find the error using the / F option. (See Chapter 12 for a complete
explanation and tour of finding runtime errors by using TPC.EXE when
running an .EXE program.)
begin
Write('Enter two numbers: ');
Readln(A,B);
Sum := A + B;
Writeln('The sum is ' ,Sum)
end.
Suppose you ran this program and entered the following values:
Enter two numbers: 45
8x
then pressed Enter. What would happen? You'd get a runtime error (106, in
fact) like we described in the previous section. And if you used the Find
error command, you'd discover that it occurred at the statement
Readln (A, B) ;
126
First, you disable automatic I/O error-checking with the {$I-} compiler
directive. Then you put the input code into a repeat.. untilloop, because
you're going to repeat the input until the user gets it right. The Write and
Readln statements are the same, but after them comes the statement
IOCode := IOResult;
127
A similar structure can be used for error-checking while opening files for
input. Look at the following code sample:
var
FileName
F
string [ 40]:
text:
begin
Write('Enter file name: ');
Readln(FileName);
Assign(F,Filename):
Reset(F);
This code fragment asks you to enter a file name, then tries to open that file
for input. If the file you name doesn't exist, the program will halt with a
runtime error (02). However, you can rewrite the code like this:
var
FileName
F
IOCode
string [ 40] ;
text;
integer;
begin
{$I-}
repeat
Write('Enter file name: ');
Readln(FileName);
Assign(F,Filename);
Reset (F) ;
IOCode := IOResult;
if IOCode <> 0 then
Write In ('File' , FileName, 'does not exist, try again'}
until IOCode = 0;
{$It}
Using these and similar techniques, you can create a crash-proof program
that lets you make mistakes without halting your program.
Range-Checking
Another common class of semantic errors involves out-of-range or out-ofbounds values. Some examples of how these can occcur include assigning
too large a value to an integer variable or trying to index an array beyond
its bounds. If you want it to, Turbo Pascal will generate code to check for
range errors. It makes your program larger and slower, but it can be
invaluable in tracking down any range errors in your program.
Suppose you had the following program:
128
program RangeTest;
var
List: array[1 .. 10] of integer;
Indx : integer;
begin
for Indx := 1 to 10 do
List [Indx] := Indx;
Indx := 0;
while (Indx < 11) do
begin
Indx := Indx + 1;
if List[Indx] > 0 then
List [Indx] := -List[Indx]
end;
for Indx := 1 to 10 do
Writeln(List[Indx])
end.
If you type in this program, it will compile and run. And run. And run. It
will, in fact, get stuck in an infinite loop. Look carefully at this code: The
while loop executes 11 times, not 10, and the variable Indx has a value of 11
the last time through the loop. Since the array List only has 10 elements in
it, List[1ll points to some memory location outside of List. Because of the
way variables are allocated, List[1ll happens to occupy the same space in
memory as the variable Indx. This means that when Indx = 11, the statement
List [Indx] := -List [Indx]
is equivalent to
Indx := -Indx
Since Indx equals 11, this statement sets Indx to -11, which starts the
program through the loop again. That loop now changes additional bytes
elsewhere, at the locations corresponding to List[-11 ..0].
In other words, this program can really mess itself up. And because Indx
never ends the loop at a value greater than or equal to 11, the loop never
ends. Period.
How do you check for things like this? You can insert {$R+} at the start of
the program to turn range-checking on. Now when you run it, the program
will halt with runtime error 201 (out of range error, because the array index
is out of bounds) as soon as you hit the statement if List[Indx] > 0 with Indx
= 11. If you were running under the integrated environment, it will
automatically take you to that statement and display the error. (Rangechecking is off by default; turning range-checking on makes your program
larger and slower.)
129
{ Enable range-checking
{ Disable range-checking
Tracing Errors
A tried-and-true debugging practice is to insert trace statements within
your program. A trace statement is usually a statement that writes variable
values to the screen, telling you where you are and listing some current
values. Often a trace is set up to execute only if a global Boolean variable
has been set to True (so that you can turn tracing on or off).
Suppose you have a large program in which some variables are set to
incorrect (but not necessarily illegal) values. The program consists of
several procedures, but you haven't figured out which one is causing the
problem. You might do something like this for each procedure:
procedure ThisOne({any parameters});
{ any declarations }
begin
if Trace then
Writeln('entering ThisOne: A = ' ,A,' B = ' ,B);
{ rest of procedure ThisOne }
if Trace then
Writeln('exiting ThisOne:
A = ' ,A,' B = ' ,B)
end; {of proc ThisOne }
130
This code assumes that Trace is a global variable of type boolean, and that
you set it to True or False at the start of the program. It also assumes that A
and B are parameters to ThisOne or global variables of some sort.
If Trace is True, then each time ThisOne is called, it writes out the values of
A and B after it is called and again just before it returns to where it was
called from. By putting similar statements in other procedures, you can
trace the values of A and Band find out where and when they change to
undesired values.
Once the wrong values of A and B come out in a trace statement, you know
that the changes occurred somewhere before that statement but after the
previously executed one. You can then start moving those two trace
statements closer together, or you can insert additional trace statements
between the two. By doing this, you can eventually pinpoint where the
error is and take appropriate steps.
As another example of tracing, you could have modified the program listed
in the previous section to look like this:
program RangeTest;
var
List array[1 .. 10] of integer;
Indx : integer;
begin
for Indx := 1 to 10 do
List [Indx] := Indx;
Indx := 0;
while (Indx < 11) do
begin
Indx := Indx + 1;
Writeln('Indx = ' ,Indx:2);
if List[Indx] > 0 then
List [Indx] : = -List [Indx]
end;
for Indx := 1 to 10 do
Writeln(List[Indx])
end.
The addition of the Writeln (' Indx = ',Indx: 2) statement in the loop does
two things. First, it shows you that Indx is acting crazy: It gets up to 11 and
then suddenly jumps back down to -10 (yes, Indx was -11, but it had 1
added to it before the Writeln statement). Second, Turbo Pascal will (by
default) allow you to interrupt an infinite loop with a Ctr/-C or etr/-Break if
you are doing input or output.
131
program MapTest;
var
A, B, C : integer;
procedure Test;
begin
Writeln('Enter two values: ');
Readln(A, B);
C := A div B;
Writeln('The answer is " C);
end;
begin
Test;
end.
When you compile this program to disk, it produces the file TEST.TPM.
You can then generate a .MAP file with the following command:
tprnap Maptest
Note that you need not put test.tpm after tpmap. This is because TPMAP
always assumes the .TPM extension.
132
Length Name
Class
OOOOOH
OOOCOH
009AOH
OOBFOH
04BFOH
000B3H
008D6H
0024FH
04000H
OOOOOH
CODE
CODE
DATA
STACK
HEAP
000B2H
00995H
OOBEEH
04BEFH
04BFOH
MAPTEST
SYSTEM
DATA
STACK
HEAP
Address
Publics by Value
0000:0022
OOOO:OOAO
oooc:OOOO
009A:0000
009A:0002
009A:0004
009A:0006
009A:OI06
009A:0206
009A:0208
009A:020C
009A:0210
009A:0214
009A:0216
009A: 021A
009A:021E
009A:0220
009A:0224
009A:0228
009A:022C
009A:0230
009A:0234
009A:0238
009A:023C
TEST
@
@
A
B
C
INPUT
OUTPUT
PREFIXSEG
HEAPORG
HEAPPTR
FREEPTR
FREEMIN
HEAP ERROR
EXITPROC
EXITCODE
ERRORADDR
RAND SEED
SAVEINTOO
SAVEINT02
SAVEINT23
SAVEINT24
SAVEINT75
FILEMODE
10 0000:002C
14 0000:009C
11 0000:0048
16 OOOO:OOAO
12 0000:0067
17 0000:00A7
The first section of the .MAP file shows the memory map for the entire .EXE
file, with all addresses and values shown in hexadecimal (base 16). First
comes the code for the program MapTest itself, 179 bytes long. This is
followed by whatever routines have been linked in from the unit System
(2262 bytes). Next comes the data segment, which takes up 591 bytes. That
is followed by the stack, which is 16K in size. After that comes the heap,
which occupies (in theory) all the rest of memory.
133
The second part of the .MAP file lists all the public (global) symbols:
procedures, functions, and variables. All values are given in hexadecimal.
The first three records refer to code entry points, the remaining references
are addresses for variables.
The first code record describes procedure Test, which resides at offset 34 in
MapTest's code segment. Next, the two @ symbols represent the beginning
of the initialization code for each program module in this program (in this
case, program MapTest and the System unit). The first @ record points to
the main program of MapTest, the second points to the beginning of the
System unit's code segment.
There are three publics variables in MapTest: A, B, and C. The rest of the
publics are variables in the System unit. All the variables reside in the
DATA segment, which begins 2464 bytes from the start of the code.
The third section correlates line numbers in the source code with the
machine code in the .EXE file. There is one line number record for each line
of code in each program file. (In this simple example, MAPTEST.PAS is the
only source code module.) Each record consists of the line number of a
source code statement, and the segment and offset of the corresponding
machine code.
The last line in the .MAP file tells you that program execution starts at
address OOOO:OOAO, or 160 bytes from the start of the code segment.
In addition to converting a .TPM file to a .MAP file, the TPMAP program
now also produces a text file that contains a complete list of all
dependencies (units, Include and .OBJ files) in the Turbo Pascal program.
For example, given a file named TEST.PAS:
program Test;
uses Crt;
begin
ClrScr;
Write('Turbo Pascal');
end.
will (1) compile TEST.EXE and produce a TEST.TPM file and (2) convert
TEST.TPM to TEST.MAP and produce TEST.DEP.
Here's a dump of TEST.DEP:
program TEST in TEST.PAS;
134
uses
Crt;
unit Crt in CRT.PAS;
Links
CRT.OBJ;
As you can see, the listing contains the module names (TEST, Crt), the
corresponding file names (TEST.PAS and CRT.PAS), and a list of .OBJ files
linked in using the {$L} compiler directive (CRT.OBJ). TPMAP will produce
a .MAP file only if you use the / M command-line option. Similarly, the / D
option will only produce a .DEP file.
Using a Debugger
Sometimes none of the traditional Pascal language-based approaches work.
The nature of the problem is such that either you can't track down where
the errors are or, having located them, you can't figure out why they're
occurring or what's causing them. Then it's time to call in the heavy
artillery: a debugger.
A debugger is a program designed to allow you to trace the execution of
your program step by step, one instruction at a time. There are many
varieties of debuggers, but most require some familiarity with assembly
language (machine code) instructions and with the architecture (registers,
memory map, and so on) of your computer's microprocessor.
One such debugger, Periscope, is described in the next section. (Periscope is
published by The Periscope Company, Inc., of Atlanta, Georgia.)
135
Turn on both the {$D+} and {$T +} compiler directives via the Options
menu, a command-line switch, or by inserting the directives at the start
of your program.
Compile your program to disk, which will create .EXE and .TPM files.
Run the TPMAP utility (as described previously) to create a .MAP file.
For example, if your program were named TEST.PAS, you would now have
three other files: TEST.EXE, TEST.TPM, and TEST.MAP.
You are now ready to debug your program with Periscope.
Starting Periscope
Periscope is a memory-resident program, much like SideKick and
SuperKey. If you have these or other memory-resident programs installed
in your system, you will need to exercise some caution when loading the
debugger. Consult the Periscope manual for more details on how to
configure the debugger for your computer, as well as how to load it safely
when other memory-resident programs are present. In the simplest case,
however, you can load Periscope simply by entering
ps
46BA:0031 9AOOOOC846
>
CALL
The first two rows show you the contents of the CPU registers. The third
row shows you the contents of the region of memory that will be altered
(WRitten to) when the CALL instruction is executed. The fourth and fifth
rows show you (1) that you have reached an address that corresponds to an
136
unnamed entry in the symbol table, and (2) that the call is being made to
another such address. The last line shows Periscope's command prompt, a
greater than ( sign.
Although this display will make long-time users of DOS DEBUG feel right
at home, you will probably prefer using Periscope's "windowed" display
instead. To switch to a windowed display, press Ctrl-F10 (if you have a color
monitor) or Ctrl-F9 (if you have a monochrome monitor). Now you can see
much more information at a glance:
46AA:OIOO 11 45 6E 74 65 72 20 74-77 6F 20 76 61 6C 75 65 .Enter two val>IOOOO
46AA:OIIO 73 3A 00 80 FF FF FF 7F-00 00 OE 74 68 65 20 61 s: ......... theIOOOO
46AA:0120 6E 73 77 65 72 20 69 73-20 00 00 00 80 FF FF FF answer is .... 10000
46AA:0130 7F 9A 00 00 C8 46 89 E5-BF 06 01 IE 57 BF 00 00
.... HF.e? .. W?IOOOO
DO" - - - - - - - - - - - - - - - - - - - - - - - - - - 10000
AX=OOOO BX=052E CX=0552 OX=8003 SP=2000 BP=2000 S1=OOBA 01=0106
10000
OS=4746 ES=4746 SS=476A CS=46BA 1P=0038 FL=0246 NV UP E1 PL ZR NA PE NIOOOO
R" WR SS:IFFC = 46BA CFFO
10000
@:
10000
46BA:0031 9AOOOOC846
CALL
10000
46BA:0036 89E5
MOV
BP,SP
10000
A6:
Write('Enter two values:');
10000
46BA:0038 BF0601
MOV
01,0106
; OUTPUT
10000
46BA:003B IE
PUSH OS
10000
46BA:003C 57
PUSH 01
10000
46BA: 0030 BFOOOO
MOV
01,0000
; A
10000
U"_1n C:\PER1\RUN.Cm1
10000
>
The screen is now divided into five distinct sections, or windows. At the
top of the screen is the Display window, used for examining memory;
below it is the Registers window. To the right is the Stack window, which
shows you the contents of the stack and, using the arrow now seen at the
top, the location pointed to by theBP (Base Page) register. At the bottom of
the screen is the Command window, where commands are entered and in
many cases command output is displayed. In the middle of the screen is the
Unassemble window. Here you can see a mixture of source code and
machine code, and the instruction that is about to be executed is always
highlighted by a reverse video bar.
Like most things in Periscope, the size and color of these windows can be
changed at your discretion (consult the manual for details). Once you have
the display configured to your liking, you can begin to experiment with
some of the basic debugging commands. In the sections that follow, it is
assumed that you will be using a windowed display while debugging and
that you are using version 3.0 or greater of Periscope.
137
Useful tip: There's no need to repeatedly press T and Enter while singlestepping. Once you have entered a command, you can repeat it simply by
pressing the F4 key.
[ J
The address parameter(s) are optional, and you can specify as many as four
of them at a time. If you do specify a parameter, Periscope will set a
temporary breakpoint at the specified address, causing the execution of the
program to stop if the instruction pointer (IP) ever points to that address.
You can specify an address either as an offset within the current code
segment or as a 32-bit pointer in segment:offset format. You can also specify
an address by using a symbolic identifier. For example, the following
command would set three temporary breakpoints:
>g 003D 46C8:0000 MyProc
139
When you give the View command, the specified file is displayed in the
command window, and you can scroll through it using the cursor keys.
This command is particularly useful when you want to glance at type or
variable declarations, or at the interface section of a unit without disturbing
the contents of the Unassemble window.
140
Using Enter, you could change the contents of the variable to test your
theory.
The format of the Enter command looks like this:
>e
<address> [<list>]
to set the AX register to 1. You can also use the Registers command
(carefully) to prevent certain instructions from being executed. For
example, a near CALL that is about to be executed can be avoided by
entering
>r ip ip+3
Finally, and less dangerously, you can use the Registers command without
a parameter to reset the display in the Unassemble window to point to the
instruction about to be executed.
would set a breakpoint at the start of the procedure named MyProc. Any
time MyProc was called, the debugger would stop the execution of the
program so that you could examine memory or single-step through the
procedure. This command, like most of the earlier ones, takes an address as
a parameter.
There are several conditional breakpoint commands, but the more common
ones are Breakpoint on Register (BR) and Breakpoint on Memory (BM).
141
would tell the debugger to stop the program if CS does Not Equal C5-that
is, if the value in the code segment (CS) register changes. Similarly,
>bm 0: 0 0: 3FC w
would tell the debugger to stop the execution of the program as soon as
any change is made to the interrupt vector table at the bottom of memory
(the W stands for Write, as opposed to R for Read).
The conditional breakpoint commands are powerful indeed, and so require
a more complete explanation than can be given here. One final and
important point should be made, however.
Conditional breakpoints generally require the debugger to monitor the
execution of the program very carefully. Although the rewards can be
great, the process is time-consuming. For that reason, Periscope requires
you request this special treatment specifically by issuing a special
command to watch for conditional breakpoints: either the Go Trace (GT) or
the Go Munitor (GM) command (see the Periscope manual for details).
You have numerous options and tools to use in debugging your
programming: syntax error handling, runtime error handling, rangechecking, I/O error-checking, tracing, map files, and debuggers. The
combination of these and the speed of Turbo Pascal create a powerful
development environment for even the most serious programmer.
142
10
The Turbo Pascal Menu Reference
This chapter is designed to help you quickly review all the menu commands available in the Turbo Pascal integrated environment. You'll learn
how to select menu commands, then we'll discuss each menu item in detail.
Menu Structure
Figure 10.1 shows the complete structure of Turbo Pascal's main menu and
its successive pull-down menus.
143
Edit
File
Options
Compile
Run
~
v
Load
Pick
New
Save
Write to
Directory
ChanQe dir
OS shell
Quit
..---
Corrpile
Make
Build
Destination
Find error
Primary file:
I- Get info
Memory
,......- Corrpiler
E nvi ronment
Directories
P ararreters
Load options
S ave options
Recent f l l e . s l
C:\TURB04\NONAME.PAS
-- load file --
I.-
Code size
Data size
Stack size
Minimum heap size
Maximum heap size
Proqram exit code
Error MessaQe
Error module
Error address
,I.-
Information
Primary file:
Current file : C: \ TURB04 \NONAME. PAS
Available Memory
File size
0
Line corrpiled: 0
Run code
302K
o bytes
o bytes
16384 bytes
o bytes
655360 bytes
RanQe checkinQ
Stack checkinQ
I/O checkinQ
DebuQ information
Turbo pascal map file
Force far calls
Var-strinQ checkinQ
Boolean evaluation
Numeric processinQ
Link buffer
Conditional defines
Memory sizes - - - ,
0
unexpected end of text
C:\TURB04
[
Stack size
Low heap limit
H iQh heap limit
Turbo
directory:
Executable directory:
Include directories:
Unit
directories:
Object
directories:
Pick file name:
Current pick file:
On
On
On
Off
Off
Off
Strict
Short-Circuit
Software
Memory
16384
0
655360
I ....
I
~
On
On
Off
On
8
Off
144
Menu commands can be selected several ways. First, you can get to the
main menu by pressing F10. If you're in the Edit window, you can get to the
main menu by pressing Ctrl-K D or Ctrl-K Q. You can also press an Aft key and
the first letter of the main menu item you'd like to get to; for example, Alt-O
to get to the Options menu.
Once you're at the main menu, you can select an item by pressing the key
corresponding to the first letter of the menu name: File, Edit, Run, Compile,
and Options. File, Compile, and Options have several other items in their
pull-down menus; Edit and Run have no other options. You can also use
the Up arrow and Down arrow keys on your keyboard to move the highlight bar
up and down the list of commands, pressing Enter when the bar is on the
command you want. To close a menu, just press Esc.
Here's the five main menu selections:
File
Handles files (loading, saving, picking, creating, writing to disk), manipulates directories (listing, changing), quits the program, and invokes DOS.
Edit
Lets you create and edit source files in the built-in text editor.
Run
Automatically compiles, links, and runs your program.
Compile
Compiles and makes your programs into object and executable files, and
more.
Options
Allows you to select compiler options (such as range-checking, debugging
information, and memory sizes) and define an input string of parameters.
Also records the Turbo, Executable, Include, Unit file and Object
directories, saves compiler options, and loads options from the configuration file.
There are three general types of items on the Turbo Pascal menus:
Commands perform a task (running, compiling, storing options, and so
on).
Toggles let you switch a Turbo Pascal feature on or off (Range-checking,
Edit auto save, and so on) or cycle through and select one of several
options by repeatedly pressing the Enter key till you reach the item
desired (such as Destination or Boolean evaluation).
Settings allow you to specify certain compile-time and runtime
information to the compiler, such as directory locations, primary files,
and so forth.
145
When you hold down the Alt key, a summary of Aft-key combinations is
displayed, like this:
Alt-F1-Last-Help Alt-F3-Pick Alt-F5-Saved Screen Alt-F9-Compile Alt-X-Exit
These are all the options found on the Options/Compiler and Memory
sizes menus. In addition, any conditional defines from the
Options/Compiler/Conditional defines menu item would have been
inserted as {$DEFINE xxxx } directives.
146
Besides the body of the Edit window, where you can see and edit several
lines of your source file, the Turbo Pascal Edit screen has two information
lines you should note: an Edit status line and the bottom line.
The status line. at the top of the Edit window gives information about the
file you are editing, where in the file the cursor is located, and which
editing modes are activated:
Line n Col n Insert
Indent
Tab C:FILENAME.EXT
Linen
CoIn
Insert
Indent
Tab
F2-Save
F3-Load
F5-Zoom
F6-0utput
F9-Make
FlO-Main menu
147
If you're entering code in the editor, you can press Enter to end a line (the
editor has no wordwrap). The maximum line width is 249 characters; you'll
get a beep if you try to type past that. (Note that the compiler only
recognizes characters out to column 128.) The Edit window is 77 columns
wide. If you type past column 77, the text you've already entered moves to
the left as you type. The Edit window's status line gives the cursor's
location in the file by line and column.
After you've entered your code into the Edit window, press FlO to invoke
the main menu. Your file will remain onscreen; you need only press E (for
Edit) at the main menu to return to it, or AIt-E from anywhere.
While you are creating or editing a source file but before you have
compiled and run it, you don't need the Output window. So you can press
F5 to zoom the Edit window to full screen. Press F5 again to unzoom the
Edit window (return to split-screen mode).
148
Type in the name of the file you want to edit; paths are accepted-for
example,
C:\TP\TESTFILE.PAS
Enter a mask in the Load File Name prompt box (using the DOS
wildcards * and ?), and press Enter. Entering * . * will display all of the
files in the current directory as well as any other directories. Directory
names are followed by a backslash (\). Selecting a directory displays the
files in that directory. Entering c: \ * . PAS, for example, will bring up
only the files with that extension in the root directory. You can change the
wildcard mask by pressing F4. (For more on directories, look at
Appendix G.)
Press the Up, Down, Left, and Right arrow keys to highlight the file name
you want to select. Then press Enter to load the selected file; you are
placed in the Edit window. If you press Enter when you're positioned on
a directory name, you'll get a new directory box.
Pick lets you quickly pick the name of a previously loaded file. So, if you
select File/Pick or Alt-F3 (see the discussion of the Pick option later in this
chapter), you can
Press AIt-F then P to bring up your pick list (or press the shortcut Alt-F3).
Use the Up and Down arrow keys to move the selection bar to the file of
your choice.
149
FlO-Main menu
F2-Save
F3-Load
F5-Zoom
F6-Edit
F9-Make
FlO-Main menu
150
Fc------=~IFi~ll!!1;;:::.I:::::::;;;:::;;;;;;;E;;;:::d::::;_it~;=;==R=un==;=C=;o~m=p=;=ile=;:Edit=O=P=t=io=ns======l
I'LOatf::;;;;::" :::';::::::1 Col 1
Pick
New
Save
Write to
Directory
Change dir
OS shell
Quit
Insert Indent
C:NONAME.PAS
/ - - - - - - - - - - - - Output - - - - - - - - - - . J
Fl-Help
F2-Save
F3-Load
FS-Zoom
F6-Edil
F9-Make
FlO-Mam menu
Load
Loads a file. You can use DOS-style masks to get a listing of file choices, or
you can load a specific file. Simply type in the name of the file you want to
load.
You can move through the directory box by using first letter selection.
Pressing the B key, for example, takes you to the first file name starting with
B. Pressing B again takes you to the next file name, and so on. If there are
no other file names beginning with the letter B, you will be taken back to
the first one. If no file names start with the letter B, then the cursor will not
move. Holding down the Shift key and pressing B will take you to the first
subdirectory that begins with the letter B.
Note: If you enter an incorrect drive or directory, you'll get an error box
onscreen. You'll get a verify box if you have an unsaved, modified file in
the editor while you're trying to load another file. In either case, the hot
keys are disabled until you press the key specified in the error or verify
box.
Pick
Lets you pick a file from a list of the previous eight files loaded into the
Edit window. At the top of list, you'll find the file that is currently in the
editor. This provides an easy way to reload the current file if you wish to
abandon changes. The file selected is loaded into the Editor and the cursor
Chapter 70, The Turbo Pascal Menu Reference
151
is positioned at the location where you last edited that file. Note that the
block marks and state is saved for each file, as are each of the four markers.
If you select the "-load file-If item from the pick list, you'll get a Load
File Name prompt box exactly as if you had selected File/Load or F3. Alt-F3
is a short cut to get this list.
You can define the pick file name from the a /D /Pick file name menu item
from within Turbo Pascal's installation program (TINST). This will have
Turbo Pascal automatically save the current pick list when you exit Turbo
Pascal and then reload that file upon reentering the program. For more
information, see the OlD/Pick file name option.
New
Specifies that the file is to be a new one. You are placed in the editor; by
default, this file is called NONAME.PAS. (You can change this name later
on when you save the file.)
Save
Saves the file in the Editor to disk. If your file is named NONAME.PAS and
you go to save it, the editor will ask if you want to rename it. From
anywhere in the system, pressing F2 will accomplish the same thing.
Write to
Writes the file to a new name or overwrites an existing file. If a file by that
name already exists, you'll be asked to verify the overwrite.
Directory
Displays the directory and file set you want (to get the current directory,
just press Enter).
You can move through the directory box by using first letter selection.
Pressing the B key, for example, takes you to the first file name starting with
B. Pressing B again takes you to the next file name, and so on. If there are
no other file names beginning with the letter B, you will be taken back to
the first one. If no file names start with the letter B, then the cursor will not
move. Holding down the Shift key and pressing B will take you to the first
subdirectory that begins with the letter B.
Change dir
Displays the current directory and allows you to change to a specified drive
and/ or directory.
152
OS shell
Leaves Turbo Pascal temporarily and takes you to the DOS prompt. To
return to Turbo Pascal, type exi t. This is useful when you want to run a
DOS command without quitting Turbo Pascal.
Quit
Quits Turbo Pascal and returns you to the DOS prompt to the currently
active directory.
153
File
Edit
. Run
i_Bil&}
Options
F=======~========
Line 1
Col 1
Inse r~iMl~,ril
Make
Build
Destination Memory
Find error
Primary file:
Get info
1 - - - - - - - - - - - Output - - - - - - - - - - - i
FI-Help
F2-Save
F3-Load
FS-Zoom
F6-Edit
F9-Make
FlO-Main menu
Compile
This menu item is a command. The last file you loaded into the editor is
compiled.
Make
Invokes Turbo' Pascal's Make sequence. If a primary file has been named,
then that file is compiled; otherwise the last file loaded into the editor is
compiled. Turbo Pascal checks all files upon which the file being compile
depends. If the source file for a given unit has been modified since the .TPU
(object code) file was created, then that unit is recompiled. If the interface
for a given unit has been changed, then all other units that depend upon it
.are recompiled. If a unit links in an .OB} file (external routines), and the
.OBJ.file is newer than the unit's .TPU file, then the unit is recompiled. If a
unit includes an Include file and the Include file is newer than that unit's
.TPU file, then the unit is recompiled.
Build
Recompiles all your files regardless of whether they are out of date or not.
This option is similar to Make except that it is unconditional; Make
rebuilds only the files that aren't current.
154
Destination
Use this option to specify whether the executable code will be saved to disk
(as an .EXE file) or whether it will just be saved in memory (and thus lost
when you exit from Turbo Pascal). Note that even if Destination is set to
Memory, any units that are recompiled during a Make or a Build have their
.TPU files updated on disk. If the code is being saved to disk, then the .EXE
file name listed is derived from one of two names, in the following order:
the Primary file name, or if none is specified
the name of the last file you loaded into the Edit window.
Find error
Finds the location of a runtime error. When a runtime error occurs, the
address in memory of where it occurred is given in the format seg:ofs. When
you return to Turbo Pascal, Turbo locates the error automatically for you.
This command allows you to find the error again, given the seg and ofs
values.
For this to work, you must turn on the Debug information menu item.
When entering the error address, you must give it in hexadecimal, segment
and offset notation. The format is "xxxX:yyyy"; for example, "2BEO:FFD4."
If runtime errors occur when running within the integrated environment,
the default values for error address is set automatically. This allows you to
re-find the error location after changing files. (Note that if you just move
around in the same file, you can get back to the error location with the Ctrl-Q
Wcommand.)
When runtime errors occur under DOS, you should note the segment offset
displayed on the screen. Then load the main program into the editor or
specify it as the Primary file. Be sure to set the Destination to Disk. Then
type in the segment offset value.
Primary file
Use this option to specify which .PAS file will be compiled when you use
Make (F9) or Build (Alt-C B).
Get info
Brings up a window of information about the current .PAS file you're
working with, including the size (in bytes and lines) of the source code, the
size (in bytes of code and data) of the resulting .EXE (or .TPU) file, available
memory, state of code, and error information.
155
When Turbo Pascal is compiling, a window pops up to display the compilation results. When compiling/making is complete, press any key to
remove this compiling window. If an error occurs, you are automatically
placed in the Edit window at the error.
Edit
Line 1
Run
Col 1
IPm~~iH"""~:
Environment
Directories
Parameters
Load Options
Save Option
I------------Output - - - - - - - - - - - - 1
FI-Help
F2-Save
F3-Load
FS-Zoom
F6-Edit
F9-Make
FlO-Main menu
Compiler
These options allow you to specify different compiler options, including
range-checking, stack-checking, I/O checking, and so on. These same
options can also be specified directly in your source code using compiler
directives (see Appendix C). Note that the first letter of each menu item
corresponds to its equivalent compiler directive; for example, Rangechecking corresponds to {$R}. (The only exception is compiler defines,
which is / Dxxx.)
156
File
Edit
Line I
Run
Coli
Compile Edit
Insert Indent
.,
.:~ti9~S9~P.&~9::: : QU:
I;
StackcheckingO~n
1/0 checking
On
Debug information
On
Turbo pascal map file Off
Force far calls
Off
Var-string checking
Strict
Boolean evaluation
Short Circuit
Numeric processing
Software
Link buffer
Memory
Conditional defines
Memory sizes
1 - - - - - - - - - - - - Output - - - - - - - - - - - - - 1
FI-Help
F2-Save
F3-Load
FS-Zoom
F6-Edit
F9-Make
flO-Main menu
157
Turbo pascal map file: Causes the compiler to generate a MAP file
during the linking phase. the MAP file generated has a .TPM extension.
This file is used by Find error when information is not in memory. You
can also use this file with symbolic debuggers. TPMAP.EXE will convert
the .TPM file to a MAP file.
Force far calls: Allows you to force all procedure/function calls to be far
calls. If not enabled, then the compiler will generate near calls for any
procedures and functions within the file being compiled. This is
equivalent to the $F compiler directive.
Var-string checking: Allows you to choose between strict or relaxed
string parameter error checking. With strict checking, the compiler
compares the declared size of a var-type string parameter with the actual
parameter being passed. If the declared size of the actual parameter is
smaller than that of the formal parameter, then a compiler error occurs.
With the relaxed option, no such checking is done. This is equivalent to
the $V compiler directive.
Boolean evaluation: Allows you to select between short-circuit and
complete Boolean evaluation. With short-circuit evaluation, the compiler
generates code to terminate evaluation of a Boolean expression as soon as
possible; for example, in the expression if False and MyFunc ... , the
function MyFunc would never be called. With complete evaluation, all
terms in a Boolean expression are evaluated. This is equivalent to the $B
compiler directive.
Numeric processing: Allows for two options-Hardware, which
generates direct 8087 inline code and allows the use of IEEE floatingpoint types (single, double, extended, comp); and Software, which allows
only the standard Turbo Pascal 6-byte real data type. This is equivalent to
the $N compiler directive.
Link buffer: Allows you to tell Turbo to use memory or disk for the link
buffer. Using memory speeds things up, but you may run out of memory
for large programs; using disk frees up memory but slows things down.
This is equivalent to the $L compiler directive.
Conditional defines: Defines symbols referenced in conditional compilation directives in your source code. Symbols are defined by typing in
their name. Multiple symbols are separated by semicolons; for example,
you may define the two symbols Test and Debug by entering
Test; Debug.
158
then the code for the Writeln will be generated. This is equivalent to
defining symbols on the command line with the / Dxxx directive under
TPC.EXE.
Memory sizes: Lets you configure the memory map for the resulting
code file. All three settings here can be specified in your source code
using the $M compiler directive.
Stack size: Allows you to specify the size (in bytes) of the stack segment.
The default size is 16K, the maximum size is 64K.
Low heap limit: Allows you to specify the minimum acceptable heap
size (in bytes). The default minimum size is OK. If you attempt to run
your program and there is not enough heap space to satisfy the
minimum requirement, then the program aborts with a runtime error.
High heap limit: Allows you to specify the maximum amount of
memory (in bytes) to allocate to the heap. The default is 655360, which
(on most systems) will allocate all available memory to the heap. This
value must be greater than or equal to the smallest heap size.
Environment
This menu's entries tell Turbo Pascal where to find the files it needs to
compile, link, and provide Help. Some miscellaneous options permit you to
tailor the Turbo Pascal working environment to suit your programming
needs.
F==F=il=e==E=dl=t==R=un===C=om=,p=i=le Edit0ptiSniilt:
Line 1
ColI
Insert
Indent!i#~~;m..id.1
~~.gp.~IfiJ~g~ni!:.
~
Off
Off
On
8
Off
1 - - - - - - - - - - - Output - - - - - - - - - - - 1
FI-Help
F2-Save
F3-Load
FS-Zoom
FS-Edit
F9-Make
FlO-Main menu
159
Directories
This menu lets you direct Turbo Pascal to the location of any directories
listed, as well as to the pick file.
160
File
Run
Edit
Compile
F=============Edit
Line I
ColI
Insert Indent
,--------,=======
Compiler
Environment
Parameters
Un~p'ij~::
iJ$rt:l9"':'I:m;;!p.rr..i\.
Executable directory:
Include directories:
Unit
directories:
Object directories:
Pick file name:
Current pick file:
I-----------Output ------------1
FI-Help
F2-Save
F3-Load
F5-Zoom
FS-Edlt
F9-Make
FIO-Mam menu
Turbo directory: This is used by the Turbo Pascal system to find the
configuration file (.TP) and the help file (TURBO.HLP). For Turbo Pascal
to find your default configuration file (TURBO.TP) at startup you must
install this path using this command.
Executable directory: .EXE files are stored here. If the entry is blank, the
files are stored in the current directory.
Include directories: Specifies the directories that contain your standard
include files. Standard include files are those specified with the {$I
filename} compiler directive. Multiple directories are separated by
semicolons (;), like in the DOS path command.
Unit directories: Specifies the directories that contain your Turbo Pascal
unit files. Multiple directories are separated by semicolons (;), like in the
DOS path command.
Object directories: Specifies the directories that contain .OBJ files
(assembly language routines). When Turbo Pascal encounters a {$L
filename} directive, it looks first in the current directory, then in the
directories specified here. Multiple directories are separated by
semicolons (;), like in the DOS path command.
Pick file name: Defines the name and location of a pick file. When this
field is defined, a pick file will always be written. If it is not defined, then
a pick file is written only if the Current pick file entry is non-blank. Since
any name can be used, you must save the pick file name in your
configuration file if it is not the default name of TURBO.PCK. For more
161
information about this option, see the later section entitled "About the
Pick File and the Pick List."
Current pick file: Shows the file name and location of the current pick
file, if any. This is where the current pick list information will be stored if
the pick file name changes or if you exit the integrated environment. This
item is always disabled and is for informational purposes. For more
information, see the later section entitled "About the Pick File and the
Pick List."
Parameters
This setting allows you to give your running programs command-line
parameters (or arguments) exactly as if you had typed them on the DOS
command line (redirection is not supported). It is only necessary to give the
arguments here; the program name is omitted.
Load Options
Loads a configuration file (the default file is TURBO.TP) previously saved
with the Save options command.
Save Options
Saves all your selected Compiler, Environment, and Directories options in a
configuration file (the default file is TURBO.TP). On start-up, Turbo Pascal
looks in the current directory for TURBO.TP; if the file's not found, then
Turbo Pascal looks in the Turbo directory for the same file. If the file's not
found there and you're running DOS 3.x, it will search the exec directory
(or the directory where TURBO.EXE was started from).
162
The pick file name can be defined in several ways. TINST-the Turbo
Pascal integrated environment program-can be used to permanently
install a pick file name into the TURBO.EXE file. A configuration file can be
loaded that contains a pick file name. Or you can type in a pick file name. If
a pick file name is defined but the integrated environment cannot find it,
then an error message is issued.
163
If no pick file name is defined, then the integrated environment searches for
the default pick file name, TURBO.PCK, first in the current directory, then
in the Turbo directory, and if you are running under DOS 3.x, it will then
search the executable directory.
Once a pick file is loaded, the integrated environment remembers the name
and location of that file so that it can update that file when you exit after
changing directories.
Usually, pick files are only saved on exit from the integrated environment.
However, there are certain times when the current pick file is updated and
a new pick file is started (or restarted).
Whenever you change the pick file name, the integrated environment will
cause the current pick list to be written to the last pick file and then the
newly named pick file will be in effect.
164
11
Using the Editor
Turbo Pascal's built-in editor is specifically designed for creating program
source text in the integrated environment. If you use the command-line
version of the compiler, however, you'll be using another editor and can
therefore skip this chapter.
The Turbo Pascal editor lets you enter up to 64K of text, 248 character lines,
and any characters in the ASCII character set, extended character set, and
control characters.
If you are familiar with WordStar, the version 3.0 Turbo Pascal editor, or the
SideKick editor, you already know how to use the Turbo Pascal editor. At
the end of this chapter, there's a summary of the few differences between
Turbo Pascal's editor commands and the ever-familiar WordStar
commands.
165
To invoke the main menu from within the editor, press F10, Ctrl-K 0, or Ctrl-K
Q. The data in the Edit window remains on screen, but the menu bar now
becomes active. To get back to editing, press E again.
Indent
Tab
C:FILENAME.TYP
Line n
Col n
Insert
Indent
Tab
C: FILENAME. EXT
Editor Commands
The editor uses approximately 50 commands to move the cursor around,
page through text, find and replace strings, and so on. These commands
can be grouped into four main categories:
166
Table 11.1 summarizes the commands. Each entry in the table consists of a
command definition, followed by the default keystrokes used to activate
the command. The remainder of the chapter details each editor command.
Table 11.1: Summary of Editor Commands
Ctrl-Q S or Home
Ctrl-Q D or End
Ctrl-Q E or Ctrl-Home
Ctrl-Q X or Ctrl-End
Ctrl-Q R or Ctrl-PgUp
Ctrl-Q C or Ctrl-PgDn
Ctrl-Q B
Ctrl-Q K
Ctrl-Q P
Ctrl-Q W
Ctrl-Vor Ins
Ctrl-N
Ctrl-Y
Ctrl-Q Y
Ctrl-H or Backspace
Ctrl-G or Del
Ctrl-T
167
Block Commands
Mark block-begin
Mark block-ena
Mark single word
Print block
Copy block
Delete block
Hide/ display block
Move block
Read block from disk
Write block to disk
Ctrl-K B or F7
Ctrl-K K or FB
Ctrl-K T
Ctrl-K P
Ctrl-K C
Ctrl-K Y
Ctrl-K H
Ctrl-K V
Ctrl-K R
Ctrl-K W
Miscellaneous Commands
Abort operation
Autoindent on/ off
Control character prefix
Pair braces forward
Pair braces backward
Find
Find and replace
Find place marker
Invoke main menu
Load file
Exit editor, no save
Repeat last find
Restore line
Save and edit
Set place marker
Tab
Tab mode
Language help
Insert compiler directives
Ctrl-U
Ctrl-O I or Ctrl-Q I
Ctrl-P
Ctrl-Q [
Ctrl-Q J
Ctrl-Q F
Ctrl-Q A
Ctrl-Q n
F10
F3
Ctrl-K 0 or Ctrl-K Q
Ctrl-L
Ctrl-Q L
Ctrl-K S or F2
Ctrl-K n
Ctrl-I or Tab
Ctrl-O T or Ctrl-Q T
Ctrl-F1
Ctrl-F7
168
Ctr/-Q S or Home
Ctrl-Q D or End
Ctr/-Q E or Ctrl-Home
Ctrl-Q X or Ctrl-End
Ctr/-Q R
Ctr/-Q C
169
Insert mode is the Turbo Pascal editor's default; this lets you insert new
characters into old text. Text to the right of the cursor moves further right
as you enter new text.
Use Overwrite mode to replace old text with new; any characters entered
replace existing characters under the cursor.
Delete character left of cursor
Ctrl-H or Backspace
Moves one character to the left and deletes the character positioned there.
Any characters to the right of the cursor move one position to the left. You
can use this command to remove line breaks.
Ctrl-G or Del
Delete character under cursor
Deletes the character under the cursor and moves any characters to the
right of the cursor one position to the left. You can use this command to
remove line breaks.
Delete word right of cursor
Ctrl-T
Deletes the word to the right of the cursor. A word is defined as a sequence
of characters delimited by one of the following characters:
1\
*+ _ / $
This command works across line breaks, and can be used to remove them.
170
Insert line
Inserts a line break at the cursor position.
etrl-N
Delete line
etrl-Y
Deletes the line containing the cursor and moves any lines below it one line
up. There's no way to restore a deleted line, so use this command with care.
Delete to end of line
Deletes all text from the cursor position to the end of the line.
etrl-Q Y
Block Commands
The block commands also require a control-character command sequence.
A block of text is any amount of text, from a single character to hundreds of
lines, that has been surrounded with special block-marker characters. There
can be only one block in a document at a time.
You mark a block by placing a block-begin marker before the first character
and a block-end marker after the last character of the desired portion of
text. Once marked, you can copy, move, or delete the block, or write it to a
file.
Mark block begin
etrl-K B or F7
Marks the beginning of a block. The marker itself is not visible, and the
block only becomes visible when the block-end marker is set. Marked text
(a block) is displayed in a different intensity.
Mark block end
etrl-K K or FB
Marks the end of a block. The marker itself is invisible, and the block
becomes visible only when the block-begin marker is also set.
Mark single word
etrl-K T
Marks a single word as a block, replacing the block-begin/block-end
sequence. If the cursor is placed within a word, then the word will be
marked. If it is not within a word, then the word to the left of the cursor
will be marked.
Print block
Prints the marked block.
etrl-K P
Copy block
etrl-K e
Copies a previously marked block to the current cursor position. The
original block is unchanged, and the markers are placed around the new
copy of the block. If no block is marked or the cursor is within the marked
block, nothing happens.
171
Delete block
etr/-K Y
Deletes a previously marked block. There is no provision to restore a
deleted block, so be careful with this command.
Hide/display block
etr/-K H
Causes the visual marking of a block to be alternately switched off and on.
The block manipulation commands (copy, move, delete, and write to a file)
work only when the block is displayed. Block-related cursor movements
(jump to beginning/ end of block) work whether the block is hidden or
displayed.
Move block
etr/-K V
Moves a previously marked block from its original position to the cursor
position. The block disappears from its original position, and the markers
remain around the block at its new position. If no block is marked, nothing
happens.
etr/-K R
Read block from disk
Reads a previously marked disk file into the current text at the cursor
position, exactly as if it were a block. The text read is then marked as a
block of different intensity.
When you issue this command, Turbo Pascal's editor prompts you for the
name of the file to read. You can use DOS wildcards to select a file to read; a
directory appears in a small window onscreen. The file specified can be any
legal file name. If you don't specify a file type (.PAS, .TXT), the editor
appends .PAS. To read a file without an extension, append a period to the
file name.
Abort operation
Ctrl-U
Lets you abort any command in progress whenever it pauses for input,
such as when Find/replace asks Replace YIN? or when you are entering a
search string or a file name (block read and write).
Autoindent on/off
Ctrl-O I or Ctrl-Q I
Provides automatic indenting of successive lines. When autoindent is
active, the cursor does not return to column one when you press Enter;
instead, it returns to the starting column of the line you just terminated.
When you want to change the indentation, use the space bar and Left arrow
key to select the new column. When autoindent is on, the message Indent
shows up in the status line; when off, the message disappears. Autoindent
is on by default. (When Tab is on, it works the same way, but it will use tabs
if possible when indenting.)
Control character prefix
Ctrl-P
Allows you to enter control characters into the file by prefixing the desired
control character with a Ctrl-P; that is, first press Ctrl-P, then press the desired
control character. Control characters will appear as low-intensity capital
letters on the screen (or inverse, depending on your screen setup).
Go to error position
Ctrl-Q W
Displays the last error generated in the Edit window and places you in the
editor at the point of error.
Find
Ctrl-Q F
Lets you search for a string of up to 30 characters. When you enter this
command, the status line is cleared, and the editor prompts you for a
search string. Enter the string you are looking for and then press Enter.
The search string can contain any characters, including control characters.
You enter control characters into the search string with the Ctrl-P prefix. For
example, enter a Ctrl- Tby holding down the Ctrl key as you press P, and then
press T. You can include a line break in a search string by specifying Ctrl-M J
carriage return/line feed). Note that Ctrl-A has a special meaning: It matches
any character and can be used as a wildcard in search strings.
You can edit search strings with the Character left, Character right, Word
left, and Word right commands. Word right recalls the previous search
string, which you can then edit. To abort (quit) the search operation, use the
Abort command (Ctrl-U).
When you specify the search string, Turbo Pascal's editor asks which
search options you'd like to use. The following options are available:
B
173
Locally searches the marked block for the next occurrence of the
string.
Examples:
W
Searches for whole words only. The search string term will match
term, for example, but not terminal.
BU
125
You can end the list of find options (if any) by pressing Enter; the search
starts. If the text contains a target matching the search string, the editor
positions the cursor on the target. The search operation can be repeated
with the Repeat last find command (Ctrl-L).
Find and replace
Ctrl-Q A
This operation works identically to the Find command except that you can
replace the "found" string with any other string of up to 30 characters.
Note that Ctrl-A has a special meaning: It matches any character and can be
used as a wildcard in search strings.
After you specify the search string, the editor asks you to enter a
replacement string. Enter up to 30 characters; control-character entry and
editing is performed as stated in the Find command. If you press Enter, the
editor replaces the target with nothing, effectively deleting it.
Your options are the same as those in the Find command, with the addition
of the following:
N
Replaces the next n cases of the search string. When you're also
using the G option, the search starts at the top of the file and
ignores the n; otherwise it starts at the current cursor position.
174
Examples:
NIO
Finds the next ten occurrences of the search string and replaces
each without asking.
GW
F3
175
Restore line
Ctrl-Q L
Lets you undo changes made to a line, as long as you have not left the line.
The line is restored to its original state regardless of any changes you have
made.
Save file
Saves the file and remains in the editor.
Ctrl-K S or F2
176
Cursor movement
Turbo Pascal's cursor movement controls-Ctr/-S, Ctr/-O, Ctr/-E, and Ctr/X-move freely around on the screen without jumping to column one on
empty lines. This does not mean that the screen is full of blanks, on the
contrary, all trailing blanks are automatically removed. This way of moving
the cursor is especially useful for program editing, for example, when
matching indented statements.
Delete to left
The WordStar sequence Ctr/-Q De/ (delete from cursor position to beginning
of line) is not supported.
Mark word as block
Turbo Pascal allows you to mark a single word as a block using Ctr/-K T. This
is more convenient than WordStar's two-step process of separately marking
the beginning and the end of the word.
Movement across line breaks
Ctr/-S and Ctr/-O do not work across line breaks. To move from one line to
another you must use Ctr/-E, Ctr/-X, Ctr/-A, or CtrJ-F.
Quit edit
Turbo Pascal's Ctr/-K Q does not resemble WordStar's Ctr/-K Q (quit edit)
command. In Turbo Pascal, the changed text is not abandoned-it is left in
memory, ready to be compiled and saved.
Undo
Turbo Pascal's Ctr/-Q L command restores a line to its pre-edit contents as
long as the cursor has not left the line.
Updating disk file
Since editing in Turbo Pascal is done entirely in memory, the Ctr/-K 0
command does not change the file on disk as it does in WordStar. You must
explicitly update the disk file with the Save option within the File menu or
by using Ctr/-K S or F2 within the editor.
177
178
12
Command-Line Reference
For you die-hard hackers using .custom editors and extended batch
files-good news: Turbo Pascal 4.0 comes with a command-line version of
the compiler so you can use the Turbo Pascal compiler without entering the
integrated environment (TURBO.EXE). This version of the compileridentical to the one in TURBO.EXE-is called TPC.EXE and is found on
your distribution disk.
If filename does not have an extension, then TPC will assume .PAS. If you
don't want the file you're compiling to have an extension, then append a
period (.) to the end of filename. If you omit both options and filename, then
TPC outputs a summary of its syntax and command-line options.
You can specify a number of options for TPC. An opt~on consists of a slash
(/) followed by one or two characters, either a letter or a dollar sign,
followed by a letter. In some cases, the option is then followed by
additional information, such as a path or a file name. Options can be given
in any order and can come before and/or after the file name.
When you type the command, TPC compiles the file, links in the necessary
runtime routines, and produces a file named filename.EXE. TPC has the
same "smart" linker as TURBO, removing "dead" code and only linking in
those routines actually needed. (If you compile a unit, it doesn't link, it
produces a .TPU file.)
Chapter 72, Command-Line Reference
179
Compiler Options
The integrated environment (TURBO) allows you to set various options
using the menus. The command-line compiler (TPC) gives you access to
most of those same options using the slash/command method described
earlier. Alternately, you can precede options with a dash (-) instead of a
slash U). However, options that start with a dash must be separated from
each other by blanks; those starting with a slash don't need to be separated
but it's legal to do so. So, for example, the following two command lines
are equivalent and legal:
tpc -ic:\tp\include -xnames.dta sortname -$r- -$f+
tpc /ic:\tp\include/xnames.dta sortname /$r-/$f+
The first uses dashes, and so at least one blank separates options from each
other; the second uses slashes, so no separation is needed.
Table 12.1 lists all the command-line options and gives their integrated
environment equivalents. In some cases, a single command-line option
corresponds to two or three menu commands.
Table 12.1: Command-Line Options
Command line
Menu selection
/$B+
/$B/$D+
/$D/$F+
/$F/$1+
/$1/$L+
/$L/$Msss,min,max
/$N+
/$N/$R+
/$R/$S+
/$S/$T+
/$T/$V+
/$V-
180
Command line
Menu selection
/B
/Epath
Compile/Build
Options /Directories /Executable directory
Compile/Find error
Options /Directories /Include directories
Compile/Make
Options /Directories / Object directories
Compile/Destination ... Memory
Run
Options /Parameters
Run
Options/Directories/Turbo directory
Options /Directories /Unit directories
Compile /Destination ... Disk
Options /Parameters
Run
Options / Compiler / Conditional defines
(none)
/Fseg:ofs
/Ipath
/M
/Opath
/Rparms
/Tpath
/Upath
/Xparms
/Ddefines
/Q
where directive is a single letter. These directives can also be specified on the
command line, using the /$ or -$ option. Hence,
tpc mystuff /$r-
would compile it with range-checking turned on. You can, of course, repeat
this option in order to specify multiple compiler directives:
tpc mystuff /$r-/$i-/$v-/$f+
Remember, though, that if you use the dash instead of the slash, you must
separate directives with at least one blank:
181
Alternately, TPC will allow you to put a list of directives (except for $M),
separated by commas:
tpc mystuff /$r-,i-,v-,f+
Note that no dollar signs ($) are needed after the first one.
The one exception to this format is the memory allocation options ($M). It
takes the format
/$mstack,heapmin,heapmax
where stack is the stack size, heapmin is the minimum heap size, and
heapmax is the maximum heap size. All three values are in bytes, and each
is a decimal number unless it is preceded by a dollar sign ($), in which case
it is assumed to be hexadecimal. So, for example, the following command
lines are equivalent:
tpc mystuff /$m16384,O,655360
tpc mystuff /$m$4000,$O,$AOOOO
Note that because of this format, you cannot use the $M option in a list of
directives separated by commas.
182
If you were applying this option to the previous example, the command
would be
tpc mystuff
1m
IQ
will suppress the printing of file names and line numbers during the
compilation. Normally, TPC reports elapsed compilation time based on the
IBM PC's internal timer. On generic MS-DOS machines using the /Q
option, the current file name and line number is only updated when files
are opened and closed, and the compiler does not calculate the elapsed
time.
183
Suppose you have a file called TEST.PAS that contains the following
program:
program Oops;
var
i : integer;
begin
i := 0;
i := i div i;
end.
Go ahead and compile this program using the command-line compiler, and
at the same time have the compiler generate a Turbo Pascal Map file
(.TPM):
tpc test /$t+
Notice that you're given an error code (200) and the segment and offset
(0000:0010 in hex) of the instruction pointer OP) where the error occurred.
How do you figure out which line in your source code caused the error?
Since you already have a .TPM file, simply invoke the compiler, use the
find runtime error option, and specify the segment and offset as reported in
the error message:
C:\ >tpc test /fOOOO:0010
Turbo Pascal Version 4.0 Copyright (c) 1987 Borland International
TEST.PAS(6): Target address found.
i := i DIV i;
Note that test refers to the .TPM file name. The compiler gives you the file
name and line number, and points to the offending line in your source
code.
If a .TPM file had not been present, here's what the screen would look like:
C:\ >tpc test /fOOOO:0010
Turbo Pascal Version 4.0 Copyright (c) 1987 Borland International
Error 133: Old or missing map file (TEST.TPM).
When a program is executed from disk and a runtime error occurs, a .TPM
file must be present in order to find the location of the error in the source
184
code. In that case, you would have to first re-compile TEST.PAS with the
I$T+ option. Then you'd invoke TPC again and specify
If<segment>:<offset>, as done earlier.
The I$T directive determines whether a .TPM file is created. The I$D
directive controls whether line number information is put into that .TPM
file. It is possible to generate a .TPM file that contains only symbols and no
line numbers by typing
C:\ >tpc test /$tt /$d-
Then, when the now-familiar runtime error occurs, you'll have problems
when trying to find its location using the If option:
C:\ >tpc test /fOOOO:0010
Turbo Pascal Version 4.0 Copyright (c) 1987 Borland International
Error 125: Module has no debug information (OOPS).
Since no line numbers were placed in the file (you specified I$D-), the
compiler can only provide the module name where the runtime error
occurred (inside program OOPS).
By the way, you can also compile this program using the command- line
compiler, and run it at the same time. Then, just like when we're running a
program from inside the integrated environment, you don't need a .TPM
file to find the runtime error:
1
2
4
5
6
7
Directory Options
TPC supports several options that are equivalent to commands in the
Options I Directories menu in the integrated environment. These options
185
allow you to specify the five directories used by TPC: executable, include,
object, Turbo, and unit.
The first option tells TPC where to put the executable (.EXE) file it creates;
the other four tell it where to search for certain types of files.
If no such option is given, then TPC creates the .EXE and .TPM files in the
current directory. This option is the same as the 0/0 /Executable
directories command within TURBO.
TPC will search for those include files in C: \ TPC\INCLUDE after searching
the current directory. You can specify more than one path name by
separating them with semicolons (;). The directories will then be searched
in the order given. This option is identical to the 0 /D /Include directories
command in TURBO. If multiple /1 directives are given, the directories are
concatenated together. Thus
tpc mystuff /ic:\tp\include;d:\move
is the same as
tpc mystuff /ic:\tp\include/id:\move
186
For example, if your program used some assembly language routines that
had already been assembled and whose .OBI files were stored in
C: \ TPC\ASM, then you could say
tpc rnystuff /oc:\tp\asrn
is the same as
tpc rnystuff /oc:\tp\include/id:\rnove
Note: If you want the IT option to affect the search for TPC.CFG, it must be
the very first command-line argument. This is identical to the OlD ITurbo
directory command within TURBO.
187
This tells TPC to look in C: \ TP\ UNITSl and C: \ TP\ UNITS2 for any units
it doesn't find in TURBO.TPL and the current directory. This is identical to
the 0 /D /Unit directories command within TURBO.
If multiple / IU directives are given, the directories are concatenated
together. Thus
tpc rnystuff /uc:\tp\include;d:\rnove
is the same as
tpc rnystuff /uc:\tp\include/ud:\rnove
then TPC will compile and execute MYSTUFF, but won't write any code
out to disk. If a runtime error occurs, TPC automatically finds the runtime
error, tells you the error number, address, and message, offending file name
and line number, and then prints the source line on the screen.
Should your program require a parameter line, you can give one after the
/ R option, making sure to enclose it in double quotes:
tpc rnystuff /r"filel file2"
Everything after the / R and up to (but not including) the. next option is
passed to the program as the parameter line.
If you need to pass multiple parameters to a program, enclose all
parameters in double quotes. You can embed slashes and dashes in your
parameter line:
188
Execution, of course, does not take place if an error has occurred during
compilation and linking. As with the I R option, you can also specify a
parameter line:
tpc mystuff Ix"filel file2"
that line defines a default file name to compile. In that case, starting TPC
with an empty command line (or with a command line consisting of
command-line options only) will compile the default file name, instead of
displaying a syntax summary.
Here's an example TPC.CFG file, defining some of the directories:
189
/tc:\tpc\bin\turbo
/uc:\tpc\units
/oc:\tpc\asm
at the system prompt, TPC acts as if you had typed in the following:
tpc /tc:\tpc\bin/turbo /uc:\tpc\units /uc:\tpc\asm mystuff
190
191
192
13
Tokens and Constants
Tokens are the smallest meaningful units of text in a Pascal program, and
they are categorized as special symbols, identifiers, labels, numbers, and
string constants.
A Pascal program is made up of tokens and separators, where a separator is
either a blank or a comment. Two adjacent tokens must be separated by one
or more separators if each token is a reserved word, an identifer, a label, or
a number.
Separators cannot be part of tokens except in string constants.
letter
193
digit
hex digit
Special symbols and reserved words are characters that have one or more
fixed meanings. These single characters are special symbols:
+_*/=<>[].,():;A@{}$#
absolute
and
array
begIn
case
const
div
do
downto
else
194
end
external
file
for
forward
function
goto
if
implementation
in
inline
interface
interrupt
label
mod
nil
not
of
or
packed
procedure
program
record
repeat
set
shl
shr
string
then
to
type
unit
until
uses
var
while,
with
xor
Identifiers
Identifiers denote constants, types, variables, procedures, functions, units,
programs, and fields in records. An identifier can be of any length, but only
the first 63 characters are significant.
You'll notice that Turbo Pascal syntax is illustrated by diagrams. To read a
syntax diagram, follow the arrows. Alternative paths are often possible;
paths that begin at the left and end with an arrow on the right are valid. A
path traverses boxes that hold the names of elements used to construct that
portion of the syntax.
The names in rectangular boxes stand for actual constructions. Those in
circular boxes-reserved words, operators, and punctuation-are the actual
terms to be used in the program.
An identifier must begin with a letter and cannot contain spaces. Letters,
digits, and underscore characters (ASCII $5F) are allowed after the first
character. Like reserved words, identifiers are not case sensitive.
When several instances of the same identifier exist, you may need to'
qualify the identifier by a unit identifier in order to select a specific instance
(units are described in Chapter 24). For example, to qualify the identifier
Ident by the unit identifier UnitName, you would write UnitName.Ident. The
combined identifier is called a qualified identifier.
195
identifier
underscore
program identifier,
unit identifier,
field identifier
--.j
identifier
~
.
qualified identifier
196
Labels
A label is a digit sequence in the range 0 to 9999. Leading zeros are not
significant. Labels are used with goto statements.
label
Numbers
Ordinary decimal notation is used for numbers that are constants of type
integer and real. A hexadecimal integer constant uses a dollar sign ($) as a
prefix. Engineering notation (E or e, followed by an exponent) is read as
"times ten to the power of" in real types. For example, 7E-2 means 7 x 10-2;
12.25e+6 or 12.25e6 both mean 12.25 x 10+6 Syntax diagrams for writing
numbers follow.
t "I
hex digil
digit sequence
unsigned integer
digit sequence
sign
197
unsigned real
digit sequence
scale factor
digit sequence
ifl----.r---r----.,-.~I. .
L.cv--J ~
unsigned number
-..,.......,~
digit sequence
unsigned integer
unsigned real
signed number
I --=t ~I
unsigned number
I---
~
Numbers with decimals or exponents denote real-type constants. Other
decimal numbers denote integer-type constants; they must be within the
range -2147483648 to 2147483647.
Hexadecimal numbers denote integer-type constants; they must be within
the range $00000000 to $FFFFFFFF. The resulting value's sign is implied by
the hexademical notation.
Character Strings
A character string is a sequence of zero or more characters from the
extended ASCII character set (Appendix E), written on one line in the
program and enclosed by apostrophes. A character string with nothing
between the apostrophes is a null string. Two sequential apostrophes in a
character string denote a single character, an apostrophe. The length
attribute of a character string is the actual number of characters within the
apostrophes.
As an extension to standard Pascal, Turbo Pascal allows control characters
to be embedded in character strings. The # character followed by an
unsigned integer constant in the range 0 to 255 denotes a character of the
corresponding ASCII value. There must be no separators between the #
198
character string
---.0
string character
string character
~a---.
or CR t - - r - - - .
A character string of length zero (the null string) is compatible only with
string types. A character string of length one is compatible with any char
and string type. A character string of length n, where n is greater than or
equal to 2, is compatible with any string type and with packed arrays of n
characters.
Here are some examples of character strings:
, ,.'
'TURBO'
'You'll see'
#13#10
'Line l'#13'Line2'
#7#7'Wake up!'#7#7
Constant Declarations
A constant declaration declares an identifier that marks a constant within
the block containing the declaration. A constant identifier cannot be
included in its own declaration.
199
constant declaration
i-------aoi
L...-_ _ _ _ _~
signed number
character string
Comments
The following constructs are comments and are ignored by the compiler:
{ Any text not containing right brace }
(* Any text not containing star/right parenthesis *)
A comment that contains a dollar sign ($) immediately after the opening
{ or (* is a compiler directive. A mnemonic of the compiler command
follows the $ character. The compiler directives are summarized in
AppendixC.
Program Lines
Turbo Pascal program lines have a maximum length of 126 characters.
200
14
Blocks, Locality, and Scope
A block is made up of declarations, which are written and combined in any
order, and statements. Each block is part of a procedure declaration, a
function declaration, or a program or unit. All identifiers and labels
declared in the declaration part are local to the block.
Syntax
The overall syntax of any block follows this format:
block
declaration part
--'"
.~
I
I
201
The label declaration part is where labels that mark statements in the
corresponding statement part are declared. Each label must mark only one
statement.
label declaration part
The digit sequence used for a label must be in the range 0 to 9999.
The constant declaration part consists of constant declarations local to the
block.
constant declaration part
l--y---,-.t
constant declaration
typed constant declaration
The type declaration part includes all type declarations to the block.
type declaration part
The procedure and function declaration part comprises procedure and function
declarations local to the block.
procedure and function declaration part
-........---r---I~
procedure declaration
I--_-r-I.
function declaration
202
statement part
--"~I
compound statement
r-----.
Rules of 'Scope
The presence of an identifier or label in a .declaration defines the identifier
or label. Each time the identifier or label occurs again, it must be within the
scope of this declaration. The scope of an identifier or label encompasses its
declaration to the end of the current block, including all blocks enclosed-by
the current block; some exceptions follow.
Redeclaration in an enclosed -block: Suppose that Exterior is a block that
encloses another block, Interior. If -Exterior and Interior both have an
identifier with the same name, for example, j, then Interior can only
access the j it declared, and similarly Exterior can only access the j it
declared.
Position of declaration within its block: Identifiers and labels cannot be
used until after they are declared. An identifier or label's declaration
must come before any occurrence of that identifier or label in the
program text, with one exception.
The base type of a pointer type can be an identifier that has not yet been
declared. However, the identifier must eventually be declared in the
same type declaration part that the pointer type occurs in.
Redeclaration within a block: An identifier or label can only be declared
once in the outer level of a given block. The only exception to this is when
it is declared within a contained block or is in a record's field list.
A record field identifier is declared within a record type and is significant
only in combination with a reference to a variable of that record type. So,
you can redeclare a field identifier (with the same spelling) within the
same block but not at the same level within the same record type.
However, an identifier that has been declared can be redeclared as a field
identifier in the same block.
203
the outermost scope, and the last unit represents the innermost scope. This
implies that if two or more units declare the same identifier, an unqualified
reference to the identifier will select the instance declared by the last unit in
the uses clause. However, by writing a qualified identifier, every instance of
the identifier can be selected.
The identifiers of Turbo Pascal's predefined constants, types, variables,
procedures, and functions act as if they were declared in a block enclosing
all used units and the entire program. In fact, these standard objects are
defined in a unit called System, which is used by any program or unit
before the units named in the uses clause. This suggests that any unit or
program can redeclare the standard identifiers, but a specific reference can
still be made through a qualified identifier, for example, System.Integer or
System. Writeln.
204
15
Types
When you declare a variable, you must state its type. A variable's type
circumscribes the set of values it can have and the operations that can be
performed on it. A type declaration specifies the identifier that denotes a
type.
type declaration
type
205
ordinal type
integer type
real type
string type
Simple Types
Simple types define ordered sets of values.
simple type
real type
r---+-
A type real identifier is one of the standard identifiers: real, single, double,
extended, or compo Refer to the sections entitled "Numbers" and "String
Constants" in Chapter 13 to find out how to denote constant type integer
and real values.
Ordinal Types
Ordinal types are a subset of simple types. All simple types other than real
types are ordinal types, which are set off by four characteristics:
All possible values of a given ordinal type are an ordered set, and each
possible value is associated with an ordinality, which is an integral value.
Except for type intege values, the first value of every ordinal type has
ordinality 0, the next has ordinality 1, and so on for each value in that
ordinal type. An type integer value's ordinality is the value itself. In any
ordinal type, each value other than the first has a predecessor, and each
value other than the last has a successor based on the ordering of the
type.
The standard function Ord can be applied to any ordinal type value to
return the ordinality of the value.
The standard function Pred can be applied to any ordinal-type value to
return the predecessor of the value. If applied to the first value in the
ordinal type, Pred produces an error.
206
ordinal type
enumerated type
ordinal type identifier
Turbo Pascal has seven predefined ordinal types: integer, shortint, longint,
byte, word, boolean, and char. In addition, there are two other classes of userdefined ordinal types: enumerated types and subrange types.
Type
shortint
integer
longint
byte
word
Range
-128 .. 127
-32768 .. 32767
-2147483648 .. 2147483647
0 .. 255
0 .. 65535
Format
Signed 8-bit
Signed 16-bit
Signed 32-bit
Unsigned 8-bit
Unsigned 16-bit
207
Arithmetic operations with type integer operands use 8-bit, 16-bit, or 32-bit
precision, according to the following rules:
The type of an integer constant is the predefined integer type with the
mallest range that includes the value of the integer constant.
For a binary operator (an operator that takes two operands), both
perands are converted to their common type before the operation. The
common type is the predefined integer type with the smallest range that
includes all possible values of both types. For instance, the common type
of integer and byte is integer, and the common type of integer and word
is longint. The operation is performed using the precision of the common
type, and the result type is the common type.
The expression on the right of an assignment statement is evaluated
independently from the size or type of the variable on the left.
Any byte-signed operand is converted to an intermediate word-signed
operand that is compatible with both integer and word before any
arithmetic operation is performed.
=1
Succ(False) = True
Ord(True)
Pred(True)
=False
208
~ identifier list ~
identifier list
-.J
constant
j--.()-.I constant
Both constants must be of the same ordinal type. Subrange types of the
form a.. b require that a is less than or equal to b.
Examples of subrange types:
Chapter 75, Types
209
o.. 99
-128 .. 127
club .. heart
A variable of a subrange type has all the properties of variables of the host
type, but its runtime value must be in the specified interval.
Type
Range
real
2.9 X 10E-39 .. 1.7 X 10E38
single
1.5 X 10E-45 .. 3.4 X 10E38
double
5.0 X 10E-324 .. 1.7 X 10E308
extended 1.9 X 10E-4951 .. 1.1 X 10E4932
comp*
-2E+63+ 1 ..2E+63-1
*
4
8
10
8
The comp type holds only integral values within the range _2 63+1 to 2 63_1,
which is approximately -9.2 x 10 18 to 9.2 X 1018
Turbo Pascal supports two models of code generation for performing realtype operations: software floating point and hardware floating point. The
appropriate model is selected through the $N compiler directive.
210
allowed in this state. Any attempt to compile statements that operate on the
single, double, extended, and comp types generate an error.
String Types
A type string value is a sequence of characters with a dynamic length
attribute (depending on the actual character count during program
execution) and a constant size attribute from 1 to 255. A string type
declared without a size attribute is given the default size attribute 255. The
length attribute's current value is returned by the standard function Length.
L:CD=+i . .
[
unsigned Integer
~~
.]
The ordering between any two string values is set by the ordering
relationship of the character values in corresponding positions. In two
strings of unequal length, each, character in the longer string without a
corresponding character in the shorter string takes on a higher or greaterthan value; for example, 'Xs' is greater than 'X'. Null strings can only be
equal to other null strings, and they hold the least string values.
Characters in a string can be accessed as components of an array, as
described in "Arrays, Strings, and Indexes" in Chapter 16. Type string
operators are described in "String Operators" and "Relational Operators"
in Chapter 20. Type string standard procedures and functions are described
in "String Procedures and Functions" in Chapter 25.
211
Structured Types
A structured type, characterized by its structuring method and by its
component type(s), holds more than one value. If a component type is
structured, the resulting structured type has more than one level of
structuring. A structured type can have unlimited levels of structuring.
structured type
--r----~~---t~
'-------'
Array Types
Arrays have a fixed number of components of one type-the component
type. In the following syntax diagram, the component type follows the
word of.
array type
---.c:
array
~,--in_d_e_x_ty_p_e--,~
'-------;O}<ll41---J
index type
ordinal type
The index types, one for each dimension of the array, specify the number of
elements. Valid index types are all ordinal types except longint and
subranges of longint. The array can be indexed in each dimension by all
values of the corresponding index type; the number of elements is therefore
the number of values in each index type. The number of dimensions is
unlimited.
212
If an array type's component type is also an array, you can treat the result
as
packed array[1 .. lO,1 .. 8] of boolean
where m is less than n is called a packed string type (the word packed may
be omitted, because it has no effect in Turbo Pascal). A packed string type
has certain properties not shared by other array types (see "Identical and
Compatible Types" later in this chapter).
Record Types
A record type comprises a set number of components, or fields, that can be
of different types. The record type declaration specifies the type of each
field and the identifier that names the field.
213
field list
fixed part
I~,
_ _ll~,f ~
~
~ VJ
variant part
fixed part
The fixed part of a record type sets out the list of fixed fields, giving an
identifier and a type for each. Each field contains information that is always
retrieved in the same way.
The following is an example of a record type:
record
year: integer;
month: 1. .12;
day:
1. .31;
end
The variant part shown in the syntax diagram of a record type declaration
distributes memory space for more than one list of fields, so the
information can be accessed in more ways than one. Each list of fields is a
variant. The variants overlay the same space in memory, and all fields of all
variants can be accessed at all times.
---+I
variant
c=~~
,
field list
IJ~CD--
You can see from the diagram that each variant is identified by at least one
constant. All constants must be distinct and of an ordinal type compatible
with the tag-field type. Variant and fixed fields are accessed the same way.
214
Set Types
A set type's range of values is the power set of a particular ordinal type (the
base type). Each possible value of a set type is a subset of the possible
values of the base type.
A variable of a set type can hold from none to all values of the set.
set type
- -..
~~ ordinal type
The base type must not have more than 256 possible values, and the ordinal
values of the upper and lower bounds of the base type must be within the
range 0 to 255. For these reasons, the base type of a set cannot be shortint,
integer, longint, or word.
Set-type operators are described in the section entitled "Set Operators" in
Chapter 18. "Set Constructors" in the same chapter shows how to construct
set values.
Every set type can hold the value [ ], which is called the empty set.
215
File Types
A file type consists of a linear sequence of components of the component
type, which can be of any type except a file type or any structured type
with a file-type component. The number of components is not set by the
file-type declaration.
~~
file type
typeT
If the word of and the component type are omitted, the type denotes an
untyped file. Untyped files are low-level I/O channels primarily used for
direct access to any disk file regardless of its internal format.
The standard file type Text signifies a file containing characters organized
into lines. Text files use special input/output procedures, which are
discussed in Chapter 24.
Pointer Types
A pointer type defines a set of values that point to dynamic variables of a
specified type called the base type. A type pointer variable contains the
memory address of a dynamic variable.
pointer type
-----~~----+I
base type
base type
216
The predefined type pointer denotes an untyped pointer, that is, a pointer
that does not point to any specific type. Variables of type Pointer cannot be
dereferenced; writing the pointer symbol 1\ after such a variable is an error.
Like the value denoted by the word nil, values of type pointer are
compatible with all other pointer types.
See Chapter 16's section entitled "Pointers and Dynamic Variables" for the
syntax of referencing the dynamic variable pointed to by a pointer variable.
Type Jdentity
Type identity is required only between actual and formal variable
parameters in procedure and function calls.
Two types-say, Tl and T2-are identical if one of the following is True: Tl
and T2 are the same type identifier; Tl is declared to be equivalent to a type
identical to T2.
The second condition connotes that Tl does not have to be declared directly
to be equivalent to T2. The type declarations
Tl
T2
T3
T4
=
=
=
=
integer;
T1;
integer;
T2;
result in Tl, T2, T3, T4, and integer as identical types. The type declarations
T5
T6
=
=
set of integer;
set of integer;
don't make T5 and T6 identical, since set of integer is not a type identifier.
Two variables declared in the same declaration, for example:
VI, V2: set of integer;
217
VI:
V2:
V3:
V4:
set of integer;
set.of integer;
integer;
integer;
Type Compatibility
Compatibility between two types is sometimes required, such as in
expressions or in relational operations. Type compatibility is important,
however, as a precondition of assignment compatibility.
Type compatibility exists when at least. one of the following conditions is
True:
Assignment Compatibility
Assignment compatibility is necessary when a value is assigned to something, such as in an assignment statement or in passing value parameters.
A value of type T2 is assignment-compatible with a type Tl (that is, Tl := T2
is allowed) if any of the following..are True:
T1 and T2 are identical types and neither is a file type or a structured type
. that contains a file-type component at any level of structuring.
T1 and T2 are compatible ordinal types, and the values of type T2 falls
within the range of possible values of T1.
T1 and T2 are real types, and the value of type T2 falls within the range of
possible values of T1.
218
integer;
integer;
= (red/green/blue);
= 1 .. 100;
= -99 .. 99;
= array[Testlndex] of TestValue;
= ATestList;
= record
year: integer;
month: 1. .12;
day: 1. .31;
end;
MeasureData = record
when: Date;
count: Testlndex;
data: TestListPtr;
end;
MeasureList = array[I .. 50] of MeasureData;
Name
= string[80];
Sex
= (male/female);
Person
= APersonData;
PersonData = record
name/firstName: Name;
age:
integer;
married:
boolean;
father/child/sibling: Person;
case s: Sex of
male:
(bearded: boolean);
female: (pregnant: boolean);
end;
People = file of PersonData;
IntFile = file of integer
=
=
219
In the example, Range, Number, and integer are identical types. TestIndex is
compatible and assignment-compatible with, but not identical to, the types
Number, Range, and integer.
220
16
Variables
Variable Declarations
A variable declaration embodies a list of identifiers that designate new
variables and their type.
variable declaration --.jL-_id_e_n_tif_ie_r_lis_t--,I~~
l.j
absolute clause
0--+
The type given for the variable(s) can be a type identifier previously
declared in a type declaration part in the same block, in an enclosing block,
or in a unit, or it can be a new type definition.
When an identifier is specified within the identifier list of a variable
declaration, that identifier is a variable identifier for the block in which the
declaration occurs. The variable can then be referred to throughout the
block, unless the identifier is redeclared in an enclosed block. Redeclaration
causes a new variable using the same identifier, without affecting the value
of the original variable.
An example of a variable declaration part follows:
var
X, Y, Z: real;
I, J, K: integer;
Digit: 0 .. 9;
C: Color;
Done,Error: boolean;
Operator: (plus, minus, times);
Huel,Hue2: set of Color;
221
Today: Date;
Results: MeasureList;
P1,P2: Person;
Matrix: array[l .. 10,1 .. 10] of real;
222
Absolute Variables
Variables can be declared to reside at specific memory addresses, and are
then called absolute variables. The declaration of such variables must include
an absolute clause following the type:
absolute clause
unsigned integer
Note that the variable declaration's identifier list can only specify one
identifier when an absolute clause is present.
The first form of the absolute clause specifies the segment and offset at
which the variable is to reside:
CrtMode : byte absolute $0040:$0049;
The first constant specifies the segment base, and the second specifies the
offset within that segment. Both constants must be within the range $0000
to $FFFF (0 to 65535).
The second form of the absolute clause is used to declare a variable "on
top" of another variable, meaning it declares a variable that resides at the
same memory address as another variable.
var
Str: string[32];
StrLen: byte absolute Str;
This declaration specifies that the variable StrLen should start at the same
address as the variable Str, and because the first byte of a string variable
contains the dynamic length of the string, StrLen will contain the length of
Str.
Variable References
A variable reference signifies one of the following:
a variable
a component of a structured- or string-type variable
a dynamic variable pointed to by a pointer-type variable
223
Note that the syntax for a variable reference allows a function call to a
pointer function. The resulting pointer is then dereferenced to denote a
dynamic variable.
Qualifiers
A variable reference is a variable identifier with zero or more qualifiers that
modify the meaning of the variable reference.
qualifier
224
is the same as
Matrix[I,J]
You can index a string variable with a single index expression, whose value
must be in the range O.. n, where n is the declared size of the string. This
accesses one character of the string value, with the type char given to that
character value.
The first character of a string variable (at index 0) contains the dynamic
length of the string; that is, Length(S) is the same as Ord(S[OJ). If a value is
assigned to the length attribute, the compiler does not check whether this
value is less than the declared size of the string. It is possible to index a
string beyond its current dynamic length. The characters thus read are
random, and assignments beyond the current length will not affect the
actual value of the string variable.
225
field identifier
~ither
Variable Typecasts
A variable reference of one type can be changed into a variable reference of
another type through a variable typecast.
226
variable typecast
type identifier
variable reference
The built-in functions Hi and Lo return the high- and low-order bytes of a
word or integer variable. To determine the high- and low-order words of a
long integer variable, you should use a value typecast:
type
WordRec = record
LOW, High : word;
end;
var
L : longint;
begin
L := $10000;
Writeln(WordRec(L) .Low);
Writeln (WordRec (L) .High);
end.
65536 decimal
{ 0 }
{ 1 }
227
end;
var
P : pointer;
begin
P := Ptr($1234, $4567)
Writeln(PtrRec(P) .Gfs)
Writeln (PtrRec (P) .Seg)
end.
{ $4567
{ $1234
This generates less code and is faster than using the standard functions Seg
and Ofs. Value typecasting is described in more detail in Chapter 18.
228
17
Typed Constants
Typed constants can be compared to initialized variables-variables whose
values are defined on entry to their block. Unlike an untyped constant (see
the section entitled "Constant Declarations" in Chapter 13), the declaration
of a typed constant specifies both the type and the value of the constant.
typed
c~nstant declaration
-1
identifier
typed constant
typed constant
Typed constants can be used exactly like variables of the same type, and
can appear on the left-hand side in an assignment statement. Note that
typed constants are initialized only once-at the beginning of a program.
Thus, for each entry to a procedure or function, the locally declared typed
constants are not reinitialized.
229
Simple-Type Constants
Declaring a typed constant as a simple type simply specifies the value of
the constant:
const
Maximum
Factor
Breakchar
integer = 9999;
real = -0.1;
char = #3;
The Vector declaration is invalid, because Min and Max are typed constants.
String-Type Constants
The declaration of a typed constant of a string type specifies the maximum
length of the string and its initial value:
const
Heading
NewLine
TrueStr
FalseStr
string[7]
string[2]
string[5]
string[5]
= 'Section';
= #13#10;
= 'Yes';
= 'No';
Structured-Type Constants
The declaration of a structured-type constant specifies the value of each of
the structure's components. Turbo Pascal supports the declaration of type
array, record, set, and pointer constants; type file constants, and constants
of array and record types that contain type file components are not
allowed.
230
Array-Type Constants
The declaration of an array-type constant specifies, enclosed in parentheses
and separated by commas, the values of the components.
array constant
typed constant
'-----iO}oollIlllt----'
This example defines the array constant StatStr, which can be used to convert values of type Status into their corresponding string representations.
The components of StatStr are
StatStr[Active] = 'Active'
StatStr[Passive] = 'Passive'
StatStr[Waiting] = 'Waiting'
The component type of an array constant can be any type except a file type.
Packed string-type constants (character arrays) can be specified both as
single characters and as strings. The definition
const
Digits: array[O .. 9] of char = ('0','1','2','3','4','5','6','7','8','9');
231
Maze[0,0,1]
Maze[0,1,0]
Maze[0,1,1]
Maze[1,0,0]
Maze[1,0,1]
Maze[1,1,0]
Maze[1,1,1]
=1
=2
=3
=4
=5
=6
=7
Record-Type Constants
The declaration of a record-type constant specifies the identifier and value
of each field, enclosed in parentheses and separated by semicolons.
record constant
field identifier
typed constant
record
x,y: real;
end;
Vector = array[0 .. 1] of Point;
Month = (Jan,Feb,Mar,Apr,May,Jun,Jly,Aug,Sep,Oct,Nov,Dec);
Date = record
d: 1 .. 31; m: Month; y: 1900 .. 1999;
end;
const
Origin : Point = (x: 0.0; y: 0.0);
Line
: Vector = ((x: -3.1; y: 1.5), (x: 5.8; y: 3.0));
SomeDay: Date = (d: 2; m: Dec; y: 1960);
=
The fields must be specified in the same order as they appear in the
definition of the record type. If a record contains fields of file types, the
constants of that record type cannot be declared. If a record contains a
variant, only fields of the selected variant can be specified. If the variant
contains a tag field, then its value must be specified.
Set-Type Constants
The declaration of a set-type constant specifies zero or more member
constants, enclosed in square brackets and separated by commas. A
member constant is a constant, or a range consisting of two constants,
separated by two periods.
232
set constant
Pointer-Type Constants
The declaration of a pointer-type constant can only specify the value nil.
Some examples include
type
NamePtr = ANameReCi
NameRec = record
Next: NamePtri
Name: string[31]i
endi
const
NameList: NamePtr = nili
NoName: NameRec = (Next: nili Name: ")i
233
234
18
Expressions
Expressions are made up of operators and operands. Most Pascal operators
are binary, that is, they take two operands; the rest are unary and take only
one operand. Binary operators use the usual algebraic form, for example, a
+ b. A unary operator always precedes its operand, for example,-b.
In more complex expressions, rules of precedence clarify the order in which
operations are performed (see Table 18.1).
Table 18.1: Precedence of Operators
Operators
Precedence
Categories
@,not
*, /, div, mod, and, shl, shr
+,-, or, xor
=,<>,<,>,<=,>=,in
first (high)
second
third
fourth (low)
unary operators
multiplying operators
adding operators
relationaIoperators
235
Expression Syntax
The precedence rules follow from the syntax of expressions, which are built
from factors, terms, and simple expressions.
A factor's syntax follows:
factor
procedure identifier
function identifier
t--------------'
A function call activates a function and denotes the value returned by the
function (see "Function Calls" later in this chapter). A set constructor
denotes a value of a set type (see the section entitled "Set Constructors"). A
value typecast changes the type of a value (see "Value Typecasts"). An
unsigned constant has the following syntax:
236
unsigned constant
-~--+I
unsigned number I - - - - - - r - - .
character string
1-------1
{ Variable reference
Pointer to a variable
{ Unsigned constant
{ SUbexpression
{ Function call
Set constructor
Negation of a boolean
{ Value typecast
@X
15
(X+Y+Z)
Sin(X/2)
[' 0 .. ' 9' ,'A' .. ' z' 1
not Done
char (Digit+48)
237
simple expression
o
Here's some examples of simple expressions:
x+Y
-x
Huel + Hue2
I*J + 1
simple expression
simple expression
238
Operators
The operators are classified as arithmetic operators, logical operators, string
operators, set operators, relational operators, and the @ operator.
Arithmetic Operators
The following tables show the types of operands and results for binary and
unary arithmetic operations.
Table 18.2: Binary Arithmetic Operations
Operator
Operation
Operand Types
Result Type
addition
integer type
real type
integer type
real type
integer type
real type
integer type
real type
integer type
integer type
integer type
real type
integer type
real type
integer type
real type
real type
real type
integer type
integer type
subtraction
*
multiplication
division
div
mod
integer division
remainder
Note: The + operator is also used as a string or set operator, and the +, -,
and * operators are also used as set operators.
Table 18.3: Unary Arithmetic Operations
Operator
Operation
Operand Types
Result Type
sign identity
integer type
real type
integer type
real type
integer type
real type
integer type
real type
sign negation
239
the result is real in the $N- state or extended in the $N+ state.
If the operand of the sign identity or sign negation operator is of an integer
type, the result is of the same integer type. If the operator is of a real type,
i - (i div j)
* j
The sign of the result of mod is the same as the sign of i. An error occurs if j
is zero.
Logical Operators
The types of operands and results for logical operations are shown in Table
18.4.
Table 18.4: Logical Operations
Operator
Operation
Operand Types
Result Type
not
and
or
xor
shl
shr
Bitwise negation
Bitwise and
Bitwise or
Bitwise xor
Shift left
Shift right
integer type
integer type
integer type
integer type
integer type
integer type
integer type
integer type
integer type
integer type
integer type
integer type
240
Boolean Operators
The types of operands and results for boolean operations are shown in
Table 18.5.
Table 18.5: Boolean Operations
Operator
Operation
Operand Types
Result Type
not
and
or
xor
negation
logical and
logical or
logical xor
boolean
boolean
boolean
boolean
boolean
boolean
boolean
boolean
In both cases, the second test is not evaluated if the first test is False.
The evaluation model is controlled through the $B compiler directive. The
default state is {$B-} (unless changed using the Options/Compiler menu),
and in this state, short-circuit evaluation code is generated. In the {$B+}
state, complete evaluation code is generated.
Since standard Pascal does not specify which model should be used for
Boolean expression evaluation, programs depending on either model being
241
String Operator
The types of operands and results for string operation are shown in Table
18.6.
Table 18.6: String Operation
Operator
Operation
Operand Types
Result Type
concatenation
string type,
char type, or
packecf.string type
string type
Set Operators.
The types of operands for set operations are shown in Table 18.7.
Table 18.7: Set Operations
Operator
Operation
Operand Types
union
difference
intersection
242
If the smallest ordinal value that is a member of the result of a set operation
is a and the largest is b, then the type of the result is set of a.. b.
Relational Operators
The types of operands and results for relational operations are shown in
Table 18.8.
Table 18.8: Relational Operations
Operator
Type
Result Type
Operation
Operand Types
equal
compatible simple,
pointer, set, string,
or packed string types
boolean
<>
not equal
compatible simple,
pointer, set, string,
or packed string types
boolean
<
less than
compatible simple,
string, or packed
string types
boolean
>
greater than
compatible simple,
string, or packed
string types
boolean
<=
less or equal
compatible simple,
string, or packed
string types
boolean
>=
greater or
equal
compatible simple,
string, or packed
string types
boolean
<=
subset of
boolean
>=
superset of
boolean
in
member of
boolean
243
Comparing Strings
The relational operators =, <>, <, >, >=, and <= compare strings according
to the ordering of the extended ASCII character set. Any two string values
can be compared, because all string values are compatible.
A char-type value is compatible with a string-type value, and when the two
are compared, the char-type value is treated as a string-type value with
length 1. When a packed string-type value with n components is compared
with a string-type value, it is treated as a string-type value with length n.
Comparing Pointers
The operators = and <> can be used on compatible pointer-type operands.
Two pointers are equal only if they point to the same object.
Note: When comparing pointers, Turbo Pascal simply compares the
segment and offset parts. Because of the segment mapping scheme of the
80x86 processors, two logically different pointers can in fact point to the
same physical memory location. For instance, $0040:$0049 and $0000:$0449
are two pointers to the same physical address. Pointers returned by the
standard procedures New and GetMem are always normalized (offset part
in the range $0000 to $OOOF), and will therefore always compare correctly.
When creating pointers with the Ptr standard function, special care must be
taken if such pointers are to be compared.
244
Comparing Sets
If a and b are set operands, their comparisons produce these results:
The
Operator
A pointer to a variable can be created with the @ operator. Table 18.9 shows
the operand and result types.
Table 18.9: Pointer Operation
Operator
@
Operation
Operand Types
Result Type
Pointer formation
Variable reference
or procedure or
function identifier
Pointer (same
as nil)
with a Variable
245
then FooPtr" references Foo's value. However, FooPtr" does not reference
Foo itself, rather it references the value that was taken from Foo and stored
on the stack.
Function Calls
A function call activates the function specified by the function identifier.
Any identifier declared to denote a function is a function identifier.
246
The function call must have a list of actual parameters if the corresponding
function declaration contains a list of formal parameters. Each parameter
takes the place of the corresponding formal parameter according to
parameter rules set forth in Chapter 22.
function call
function identifier
actual parameter list
--cv-rL--__
0"
actual parameter
Set Constructors
A set constructor denotes a set-type value, and is formed by writing
expressions within brackets ([D. Each expression denotes a value of the set.
set constructor
--cD LJ
~CD--
member group ~
'-------10. .
4t----'
member group
-----I
expression
l:c;=:j . rJ
..
expression
247
Value Typecasts
The type of an expression can be changed to another type through a value
typecast.
value typecast
type identifier
expression
The expression type and the specified type must both be either ordinal
types or pointer types. For ordinal types, the resulting value is obtained by
converting the expression. The conversion may involve truncation or
extension of the original value if the size of the specified type is different
from that of the expression. In cases where the value is extended, the sign
. of the value is always preserved; that is, the value is sign-extended.
The syntax of a value typecast is almost identical to that of a variable typecast (see Chapter 16, "Variable Typecasts"). However, value typecasts
operate on values not on variables, and can therefore not participate in
variable references; that is, a value typecast may not be followed by
qualifiers. In particular, value typecasts cannot appear on the left-hand side
of an assignment statement.
Some examples of value typecasts include
integer (' A' )
char (48)
boo1ean(O)
Color(2)
Longint(@Buffer)
BytePtr(Ptr($40,$49))
248
19
Statements
Statements describe algorithmic actions that can be executed. Labels can
prefix statements, and these labels can be referenced by goto statements.
statement
simple statement
structured statement
As you saw in Chapter 13, a label is either a digit sequence in the range 0 to
9999 or an identifier.
Ther~
Simple Statements
A simple statement is a statement that doesn't contain any other statements.
simple statement
----r--l~
assignment statement
I----.,-----I~
gata statement
249
Assignment Statements
Assignment statements either replace the current value of a variable with a
new value specified by an expression or specify an expression whose value
is to be returned by a function.
assignment statement
variable reference
function identifier
The expression must be assignment-compatible with the type of the variable or the result type of the function (see Chapter 15, "Type
Compatibility").
Some examples of assignment statements follow:
X
:= YtZ;
Procedure Statements
A procedure statement specifies the activation of the procedure denoted by
the .procedure identifier. If the corresponding procedure declaration contains a list of formal parameters, then the procedure statement must have a
matching list of actual parameters (parameters listed in definitions are
formal parameters; in the calling statement, they are actual parameters). The
actual parameters are passed to the formal parameters as part of the call.
procedure statement
250
Goto Statements
A goto statement transfers program execution to the statement prefixed by
the label referenced in the goto statement. The syntax diagram of a go to
statement follows:
goto statement
Structured Statements
Structured statements are constructs composed of other statements that are
to be executed in sequence (compound and with statements), conditionally
(conditional statements), or repeatedly (repetitive statements).
repetitive statement
with statement
Compound Statements
The compound statement specifies that its component statements are to be
executed in the same sequence as they are written. The component
statements are treated as one statement, crucial in contexts where the Pascal
syntax only allows one statement. begin and end bracket the statements,
which are separated by semicolons.
251
end;
Conditional Statements
A conditional statement selects for execution a single one (or none) of its
component statements.
If Statements
The syntax for an if statement reads like this:
if statement
~ expression
The expression must yield a result of the standard type boolean. If the
expression produces the value True, then the statement following then is
executed.
If the expression produces False and the else part is present, the statement
252
Case Statements
The case statement consists of an expression (the selector) and a list of
statements, each prefixed with one or more constants (called case constants)
or with the word else. The selector must be of an ordinal type, and the
ordinal values of the upper and lower bounds of that type must be within
the range -32768 to 32767. Thus, string types and the integer types longInt
and word are invalid selector types. All case constants must be unique and
of an ordinal type compatible with the selector type.
case statement
expression
I-;::::::==~~rl-::::~T-"'~~
else part
L.Q--t
253
case
else part
The case statement executes the statement prefixed by a case constant equal
to the value of the selector or a case range containing the value of the
selector. If no such case constant of the case range exists and an else part is
present, the statement following else is executed. If there is no else part,
nothing is executed.
Examples of case statements follow:
case Operator of
plus:
X:= X+Y;
minus: X:= X-Y;
times: X:= X*Y;
end;
case I of
0,2,4,6,8: Writeln('Even digit');
1,3,5,7,9: Writeln('Odd digit');
10 .. 100:
Writeln('Between 10 and 100');
else
Writeln('Negative or greater than 100');
end;
Repetitive Statements
Repetitive statements specify certain statements to be executed repeatedly.
repetitive statement
---,r----.t
repeat statement
while statement
for statement
254
Repeat Statements
A repeat statement contains an expression that controls the repeated
execution of a statement sequence within that repeat statement.
repeat statement
re pea'
~I
expression
I-
repeat
Write ('Enter value (0 .. 91: 'I;
Readln(II;
until (I >= 01 and (I <= 91;
While Statements
A while statement contains an expression that controls the repeated
execution of a statement (which can be a compound statement).
while statement
expression
statement
255
For Statements
The for statement causes a statement (which can be a compound statement)
to be repeatedly executed while a progression of values is assigned to a
control variable.
control variable
for statement
+I
control variable
initial value
final value
---+/
---+/
---+/
variable identifier
statement
expression
expression
256
starts off at initial value. When a for statement uses to, the value of the
control variable is incremented by one for each repetition. If initial value is
greater than final value, the contained statement is not executed. When a for
statement uses downto, the value of the control variable is decremented by
one for each repetition. If initial value value is less than final value, the
contained statement is not executed.
It's an error if the contained statement alters the value of the control
variable. After a for statement is executed, the value of the control variable
value is undefined, unless execution of the for statement was interrupted
by a goto from the for statement.
With these restrictions in mind, the for statement
for V := Exprl to Expr2 do Body;
is equivalent to
begin
TempI := Exprl;
Temp2 := Expr2;
if TempI <= Temp2 then
begin
V := TempI;
Body;
while V <> Temp2 do
begin
V := Succ (V) ;
Body;
end;
end;
end;
is equivalent to
begin
TempI : = Exprl;
Temp2 := Expr2;
if TempI >= Temp2 then
begin
V := TempI;
Body;
while V <> Temp2 do
begin
V := Pred(V);
Body;
end;
end;
end;
257
where Templ and Temp2 are auxiliary variables of the host type of the
variable V and don't occur elsewhere in the program.
Examples of for statements follow:
for I := 2 to 63 do
if Data[I] > Max then Max := Data[I]
for I := 1 to 10 do
for J := 1 to 10 do
begin
X := 0;
for K := 1 to 10 do
X := X + Mat1[I,K]
Mat [I, J] := X;
end;
* Mat2[K,J];
VVith
State~ents
This is equivalent to
258
if Date.month = 12 then
begin
Date.month := 1;
Date.year := Date.year + 1
end
else
Date.month := Date.month + 1;
In this case, both x and y can refer to a variable or to a field of the record. In
the statement
with x do
begin
x := 10;
y := 25;
end;
the x between with and do refers to the variable of type Point, but in the
compound statement, x and y refer to x.x and x.y.
The statement
with Vl,V2, '"
Vn do s;
is equivalent to
with VI do
with V2 do
with Vn do
S;
259
260
20
Procedures and Functions
Procedures and functions allow you to nest additional blocks in the main
program block. Each procedure or function declaration has a heading
followed by a block. A procedure is activated by a procedure statement; a
function is activated by the evaluation of an expression that contains its call
and returns a value to that expression.
This chapter discusses the different types of procedure and function
declarations and their parameters.
Procedure Declarations
A procedure declaration associates an identifier with a block as a
procedure; that procedure can then be activated by a procedure statement.
procedure declaration
-----I
procedure heading
procedure body
The procedure heading names the procedure's identifier and specifies the
formal parameters (if any).
parameter type
261
procedure body
---r---------~,.__~
The syntax for a formal parameter list is shown in the section "Parameters"
later in this chapter.
A procedure is activated by a procedure statement, which states the
procedure's identifier and any actual parameters required. The statements
to be executed on activation are noted in the statement part of the
procedure'S block. If the procedure'S identifier is used in a procedure
statement within the procedure's block, the procedure is executed
recursively (it calls itself while executing).
Here's an example of a procedure declaration:
procedure NumString(N: integer; var S: string);
var
V: integer;
begin
V
:= Abs (N);
S := ";
repeat
S := Chr(N mod 10 + Ord('O')) + S;
N :=Ndivl0;
until N = 0;
if N < 0 then S := '-' + S;
end;
262
Forward Declarations
A procedure declaration that specifies the directive forward instead of a
block is a forward declaration. Somewhere after this declaration, the
procedure must be defined by a defining declaration-a procedure
declaration that uses the same procedure identifier but omits the formal
parameter list and includes a block. The forward declaration and the
defining declaration must appear in the same procedure and function
declaration part. Other procedures and functions can be declared between
them, and they can call the forward-declared procedure. Mutual recursion
is thus possible.
The forward declaration and the defining declaration constitute a complete
procedure declaration. The procedure is considered declared at the forward
declaration.
An example of a forward declaration follows:
procedure Walter(m,n : integer); forward;
procedure Clara(x,y : real);
begin
Walter(4,5);
end;
procedure Walter;
begin
Clara(8.3,2.4);
end;
External Declarations
External declarations allow you to interface with separately compiled
procedures and functions written in assembly language. The external code
must be linked with the Pascal program or unit through {$L filename}
directives. For further details on linking with assembly language, refer to
Chapter 26.
263
Inline Declarations
The inline directive permits you to write machine code instructions instead
of the block. When a normal procedure is called, the compiler generates
code that pushes the procedure'S parameters onto the stack, and then
generates a CALL instruction to call the procedure. When you "call" an
inline procedure, the compiler generates code from the inline directive
instead of the CALL. Thus, an inline procedure is "expanded" every time
you refer to it, just like a macro in assembly language. Here's a short
example of two inline procedures:
procedure Disablelnterrupts; inline($FA);
procedure Enablelnterrupts; inline($FB);
CLI
STI
Inline procedures are described in full in Chapter 26, "Inside Turbo Pascal."
Function Declarations
A function declaration defines a part of the program that computes and
returns a value.
function declaration
The function heading specifies the identifier for the function, the formal
parameters (if any), and the function result type.
264
function heading
formal parameter list
result type
for i := 2 to n do
if x < a[i] then x := a[i];
Max := x;
end;
function Power(x: extended; y: integer): extended;
var
z: extended;
i: integer;
begin
z := 1.0; i := y;
while i > 0 do
265
begin
if Odd (i) then z := z
i := i div 2;
X;
x := Sqr (x);
end;
Power := Z;
end;
function body
Parameters
The declaration of a procedure or function specifies a formal parameter list.
Each parameter declared in a formal parameter list is local to the procedure
or function being declared, and can be referred to by its identifier in the
block associated with the procedure or function.
formal parameter list
parameter declaration
.+ "
There are three kinds of parameters: value, variable, and untyped variable.
They are characterized as follows:
A parameter group without a preceding var and followed by a type is a
list of value parameters.
A parameter group preceded by var and followed by a type is a list of
variable parameters.
A parameter group preceded by var and not followed by a type is a list of
untyped variable parameters.
266
Value Parameters
A formal value parameter acts like a variable local to the procedure or
function, except that it gets its initial value from the corresponding actual
parameter upon activation of the procedure or function. Changes made to a
formal value parameter do not affect the value of the actual parameter.
A value parameter's corresponding actual parameter in a procedure
statement or function call must be an expression, and its value must not be
of file type or of any structured type that contains a file type.
The actual parameter must be assignment-compatible with the type of the
formal value parameter. If the parameter type is string, then the formal
parameter is given a size attribute of 255.
Variable Parameters
A variable parameter is employed when a value must be passed from a
finding the object of a pointer, these actions are executed before the
activation of the procedure or function.
267
This function can be used to compare any two variables of any size. For
instance, given the declarations
type
Vector
Point
=
=
var
Vecl,Vec2: Vector;
N: integer;
P: Point;
compare Vec1 to Vee2, compare the first N components of Vec1 to the first N
components of Vee2, compare the first five components of Veel to the last
five components of Vec1, and compare Vec1[1] to P.x and Vec1[2] to P.y.
268
21
Programs and Units
Program Syntax
A Turbo Pascal program takes the form of a procedure declaration except
for its heading and an optional uses clause.
program
program heading
~f
'p~~
. uses clause
program parameters
-.1
identifier list
269
uses clause
The System unit is always used automatically. System implements all lowlevel, runtime support routines to support such features as file I/O, string
handling, floating point, dynamic memory allocation, and others.
Apart from System, Turbo Pascal implements many standard units, such as
Printer, Dos, and Crt. These are not used automatically; you must include
them in your uses clause, for instance,
uses Dos,Crti
where Memory is not a resident unit, causes the compiler to look for the file
MEMORY.TPU in the current directory, and then in each of the unit
directories.
The {$U filename} directive allows you to override the compiler'S file name
selection. If a {$U filename} directive appears just before a unit name in a
uses clause, the compiler uses that file name instead of the unit name. For
instance, the construct
uses {$U MEM} MemorYi
will cause the compiler to look for Memory in the file MEM.TPU. If the {$U
filename} directive specifies a drive letter and/ or a directory path, the unit is
only searched for in that directory.
270
will cause the compiler to look for Memory's source text in the file
MEMORY.LIB.
Unit Syntax
Units are the basis of modular programming in Turbo Pascal. They are
used to create libraries that you can include in various programs without
making the source code available, and to divide large programs into
logically related modules.
unit
implementation part
initialization part
unit identifier
The unit name is used when referring to the unit in a uses clause. The name
must be unique-two units with the same name cannot be used at the same
time.
271
interface part
procedure heading
function heading
inline directive
Unless a procedure or function is inline, the interface part only lists the
procedure or function heading. The block of the procedure or function
follows in the implementation part. Note: the procedure and function
heading can be duplicated from the interface part. You don't have to
specify the formal parameter list, but if you do, the compiler will issue a
compile-time error if the interface and implementation declarations don't
match.
272
implementation part
implementation)
~~
I
I
procedure declaration
function declaration
In effect, the procedure and function declarations in the interface part are
like forward declarations, although the forward directive is not specified.
Therefore, these procedures and functions can be defined and referenced in
any sequence in the implementation part.
~~
statement part
The initialization parts of units used by a program are executed in the same
order that the units appear in the uses clause.
273
unit Unitl;
interface
constc = 1;
implementation
const d = 2;
end.
unit Unit2;
interface
uses Unit!;
const b = c;
implementation
end.
Unit2 uses Unitl, so for Host to use Unit2, it first names Unitl in its uses
clause. Because Host does not directly reference any identifiers in Unitl, it
doesn't have to name Unitl.
uses Un i t 1 ,
uses Unit2;
Un i t 2 ;
274
22
Input and Output
This chapter briefly describes the standard (or built-in) input and output
(I/O) procedures and functions of Turbo Pascal; for more detailed
information, refer to Chapter 27.
An Introduction to lID
A Pascal file variable is any variable whose type is a file type. There are
three classes of Pascal files: typed, text, and untyped. The syntax for writing
file types is given in the section "Structured Types" in Chapter 15.
Before a file variable can be used, it must be associated with an external file
through a call to the Assign procedure. An external file is typically a named
disk file, but it can also be a device, such as the keyboard or the display.
The external file stores the information written to the file or supplies the
information read from the file.
Once the association with an external file is established, the file variable
must be "opened" to prepare it for input and/or output. An existing file
can be opened via the Reset procedure, and a new file can be created and
opened via the Rewrite procedure. Text files opened with Reset are readonly, and text files opened with Rewrite and Append are write-only. Typed
files and untyped files always allow both reading and writing regardless of
whether they were opened with Reset or Rewrite.
The standard text-file variables Input and Output are opened automatically
when program execution begins. Input is a read-only file associated with
the keyboard and Output is a write-only file associated with the display.
275
Procedures
Assign
ChDir
Close
Erase
GetDir
MkDir
Creates a subdirectory.
276
Rename
Reset
Rewrite
RmDir
Functions
Eof
IOResult
277
Note: If a program uses the Crt standard unit, Input and Output will no
longer by default refer to the standard input and standard output files. For
further details, refer to the description of the Crt unit in Chapter 24,
"Standard Units").
Some of the standard procedures and functions listed in this section need
not have a file variable explicitly given as a parameter. If the file parameter
is omitted, Input or Output will be assumed by default, depending on
whether the procedure or function is input- or output-oriented. For
instance, Read(x) corresponds to Read(Input,x) and Write(x) corresponds to
Write(Output,x).
If you do specify a file when calling one of the procedures or functions in
this section, the file must have been associated with an external file using
Assign, and opened using Reset, Rewrite, or Append. An error message is
generated if you pass a file that was opened with Reset to an outputoriented procedure or function. Likewise, it's an error to pass a file that was
opened with Rewrite or Append to an input-oriented procedure or function.
Procedures
Append
Flush
Read
Reads one or more values from a text file into one or more
variables.
Readln
SetTextBuf
Write
Writeln
Functions
Eoln
SeekEof
SeekEoln
278
For untyped files, the Reset and Rewrite procedures allow an extra
parameter to specify the record size used in data transfers.
For historical reasons, the default record size is 128 bytes. The preferred
record size is 1, because that is the only value that correctly reflects the
exact size of any file (no partial records are possible when the record size is
1).
Except for Read and Write, all typed file standard procedures and functions
are also allowed on untyped files. Instead of Read and Write, two
procedures called BlockRead and BlockWrite are used for high-speed data
transfers.
BlockRead
BlockWrite
FileSize
Seek
Truncate
FileMode Variable
The FileMode variable defined by the System unit determines the access code
to pass to DOS when typed and untyped files (not text files) are opened
using the Reset procedure.
The default FileMode is 2, which allows both reading and writing.
Assigning another value to FileMode causes all subsequent Resets to use that
mode.
Chapter 22, Input and Output
279
The range of valid FileMode values depends on the version of DOS in use.
However, for all versions, the following modes are defined:
0:
1:
2:
Read only
Write only
Read/Write
DOS version 3.x defines additional modes, which are primarily concerned
with file-sharing on networks. (For further details on these, please refer to
your DOS Programmer's Reference manual.)
Note: New files created using Rewrite are always opened in Read/Write
mode, corresponding to FileMode = 2.
DOS Devices
DOS devices are implemented through reserved file names that have a
special meaning attached to them. DOS devices are completely
transparent-in fact, Turbo Pascal is not even aware when a file variable
refers to a device instead of a disk file. For example, the program
var
Lst: Text;
begin
Assign(Lst,'LPT1'); Rewrite(Lst);
Writeln(Lst,'Hello World ... ');
Close(Lst);
end.
will write the string Hello World ... on the printer, even though the syntax
for doing so is exactly the same as for a disk file.
The devices implemented by DOS are used for obtaining or presenting
legible input or output. Therefore, DOS devices are normally used only in
connection with text files. On rare occasions, untyped files can also be
useful for interfacing with DOS devices.
280
Each of the DOS devices is described in the next section. Other DOS
implementations can provide additional devices, and still others cannot
provide all the ones described here.
281
create a particular file, but the program requires an input or output file
name.
Text-File Devices
Text-file devices are used to implement devices unsupported by DOS or to
make available another set of features other than those provided by a
similar DOS device. A good example of a text file device is the CRT device
implemented by the Crt standard unit. Its main function is to provide an
interface to the display and the keyboard, just like the CON device in DOS.
However, the CRT device is much faster and supports such invaluable
features as color and windows (for further details on the CRT device, see
Chapter 24, "Standard Units").
Contrary to DOS devices, text-file devices have no reserved file names; in
fact, they have no file names at all. Instead, a file is associated with a textfile device through a customized Assign procedure. For instance, the Crt
standard unit implements an AssignCrt procedure that associates text files
with the CRT device.
In addition to the CRT device, Turbo Pascal allows you to write your own
text file device drivers. A full description of this is given in the section
"Writing Text File Device Drivers" in Chapter 26, "Inside Turbo Pascal."
282
23
Standard Procedures and Functions
This chapter briefly describes all the standard (built-in) procedures and
functions in Turbo Pascal, except for the I/O procedures and functions
discussed in Chapter 22, "Input and Output." Additional procedures and
functions are provided by the standard units described in Chapter 24,
"Standard Units." For more detailed information, refer to Chapter 27,
"Turbo Pascal Reference Lookup."
Standard procedures and functions are predeclared. Since all predeclared
entities act as if they were declared in a block surrounding the program, no
conflict arises from a declaration that redefines the same identifier within
the program.
Halt
283
Procedures
Dispose
FreeMem
GetMem
Mark
New
Release
Functions
MaxAvail
MemAvail
Transfer Functions
The procedures Pack and Unpack, as defined in standard Pascal, are not
implemented by Turbo Pascal.
Chr
Ord
Round
Trune
Arithmetic Functions
Note: When compiling in numeric processing mode, {$N+}, the return
values of the floating-point routines in the System unit (Sqrt, Pi, Sin, and so
on) are of type extended instead of real:
($N+)
begin
Writeln(Pi);
284
( 3.14159265358979E+OOOO )
end.
{$N-}
begin
Writeln(Pi)
end.
{ 3.1415926536E+OO}
Abs
ArcTan
Cos
Exp
Frac
Int
Ln
Pi
Sin
Sqr
Sqrt
Decrements a variable.
Inc
Increments a variable.
Functions
Odd
Pred
Succ
285
Insert
Str
Val
Functions
Concat
Copy
Length
Pos
CSeg
DSeg
Dfs
Ptr
Seg
SPtr
SSeg
286
Move
Randomize
Functions
Hi
Lo
ParamCount
ParamStr
Random
SizeO
Swap
UpCase
287
288
24
Standard Units
Chapters 20 and 23 described all the built-in procedures and functions of
Turbo.Pascal, which can be referred to without explicitly requesting them
(as standard Pascal specifies). It's through Turbo Pascal's standard units,
though,that you'll get the most programming power (see Chapter 27 for
more information).
Standard units are no different from the units you can write yourself. The
following standard units are available to you:
Crt
Dos
Graph3
Printer
System
Turbo3
Graph
289
To use one of the standard units, simply include its name in your uses
clause, for instance:
uses Dos,Crt,Graph;
The standard units usually all reside in the TURBO.TPL library, which is
automatically loaded when you start up Turbo Pascal. To save memory,
you can move seldom-used units, such as Turbo3 and Graph3, out of the
TURBO.TPL file by using the TPUMOVER utility.
Unit
Uses
System
Printer
Dos
Crt
Graph
Turb03
Graph3
None
None
None
None
None
Crt
Crt
We purposefully didn't indicate in the table that all units use the System
unit; that's because System is always used implicitly, and need never be
specified in a uses clause.
290
var
Input
Output
PrefixSeg
HeapOrg
HeapPtr
FreePtr
FreeMin
HeapError
ExitProc
RandSeed
FileMode
:
:
:
:
text;
text;
word;
pointer
pointer
pointer
word;
pointer;
pointer;
longint;
byte;
Input and Output are the standard I/O files required by every Pascal
implementation. By default, they refer to the standard input and output
files in DOS. For further details, refer to Chapter 23.
PrefixSeg is a word variable containing the segment address of the Program
Segment Prefix (PSP) created by DOS when the program was executed. For
a complete description of the PSP, refer to your DOS manual.
HeapOrg, HeapPtr, FreePtr, FreeMin, and HeapError are used by the heap
manager to implement Turbo Pascal's dynamic memory allocation
routines. The heap manager is described in full in Chapter 26, "Inside
Turbo Pascal."
The ExitProc pointer variable is used to implement exit procedures. This is
also described in Chapter 26.
{
{
{
{
$00
$02
$23
$24
$75
}
}
}
}
Note that the System unit contains an INT 24 handler for trapping critical
errors. When running an .EXE program created by Turbo Pascal, a DOS
critical error will be treated like any other I/O error: The program counter
Chapter 24, Standard Units
291
and an error number will display, and the program will terminate. Disk
errors are detected by using {$I-} and checking IOResult. Here's a simple
program that re-installs the original vector:
program Restore;
uses Dos;
begin
SetlntVec($24, Savelnt24);
end.
Note that the original INT 24 vector is saved in a pointer variable in the
System unit (SaveInt24).
292
Flags Constants
The following constants are used to test individual flag bits in the Flags
register after a call to Intr or MsDos:
const
FCarry
FParity
FAuxiliary
FZero
FSign
FOverflow
= $0001;
= $0004;
= $0010;
= $0040;
= $0080;
$0800;
are True respectively if the Carry flag is set and if the Zero flag is clear.
= $D7BO;
= $D7B1;
= $D7B2;
= $D7B3;
293
( Textfile record )
TextBuf = array[0 .. 127]
TextRec = record
Handle
Mode
BufSize
Private
BufPos
BufEnd
BufPtr
OpenFunc
InOutFunc
FlushFunc
CloseFunc
UserData
Name
Buffer
end;
of char;
word;
word;
word;
word;
word;
word;
ATextBuf;
pointer;
pointer;
pointer;
pointer;
array [1. .16] of Byte;
array[0 .. 79] of Char;
TextBuf;
=
=
=
=
=
=
=
$01;
$02;
$04;
$08;
$10;
$20;
$3F;
will locate all normal files as well as read-only files and subdirectories in
the current directory. The AnyFile constant is simply the sum of all
attributes.
294
type
Registers = record
case integer of
0: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: word);
1: (AL,AH,BL,BH,CL,CH,DL,DH: byte);
end;
Notice the use of a variant record to map the 8-bit registers on top of their
16-bit equivalents.
Valid ranges are Year 1980 ..2099, Month 1..12, Day 1..31, Hour 0 .. 23, Min
0..59, and Sec 0..59.
record
Fill:
Attr:
Time:
Size:
Name:
end;
The information for each file found by one of these procedures is reported
back in a SearchRec. The Attr field contains the file's attributes (constructed
from file attribute constants), Time contains its packed date and time (use
UnpackTime to unpack), Size contains its size in bytes, and Name contains its
name. The Fill field is reserved by DOS and should never be modified.
295
The values stored in Dos Error are DOS error codes. A value of 0 indicates
no error; other possible error codes include:
2 = File not found
3 = Path not found
5 = Access denied
6 = Invalid handle
8 = Not enough memory
10 = Invalid environment
11 = Invalid format
18 = No more files
Intr
MsDos
SetIntVec
GetFTime
GetTime
PackTime
Converts a DateTime record into a 4-byte, packed dateand-time character longint used by SetFTime. The fields
of the DateTime record are not range-checked.
SetDate
SetFTime
SetTime
296
UnpackTime
DiskSize
File-Handling Procedures
FindFirst
FindNext
GetFAttr
SetFAttr
Keep
Functions
DosExitCode
297
This means that I/O redirection of the Input and Output files is no longer
possible unless these files are explicitly assigned back to standard input
and output by executing
Assign(Input,"); Reset(Input);
Assign(Output,"); Rewrite(Output);
Windows
Crt supports a simple yet powerful form of windows. The Window
proced ure lets you define a window anywhere on the screen. When you
write in such a window, the window behaves exactly as if you were using
the entire screen, leaving the rest of the screen untouched. In other words,
the screen outside the window is not accessible. Inside the window, lines
can be inserted and deleted, the cursor wraps around at the right edge, and
the text scrolls when the cursor reaches the bottom line.
All screen coordinates, except the ones used to define a window, are
relative to the current window, and screen coordinates (1,1) correspond to
the upper left corner of the screen.
298
Special Characters
When writing to Output or to a file that has been assigned to the CRT, the
following control characters have special meanings:
#7 Bell-emits a beep from the internal speaker.
#8 Backspace-moves the cursor left one character. If the cursor is
already at the left edge of the current window, nothing happens.
#10 Line feed-moves the cursor one line down. If the cursor is
already at the bottom of the current window, the window scrolls
up one line.
#13 Carriage return-returns the cursor to the left edge of the current
window.
All other characters will appear on the screen when written.
Line Input
When readingfrom Input or from a text file that has been assigned to Crt,
text is input one line at a time. The line is stored in the text file's internal
buffer, and when-variables are read, this buffer is used as the input source.
Whenever the buffer has been emptied, a new line. is input.
When entering lines, the following editing keys are available:
BackSpace
Esc
Enter
Ctrl-S
Same as BackSpace
Ctrl-D
Ctrl-A
Same as Esc.
Ctrl-F
Ctrl-Z
299
Ctrl-Z will only generate an end-of-file marker if the CheckEOF variable has
been set to True; it is False by default.
To test keyboard status and input single characters under program control,
use the Key Pressed and ReadKey functions.
BW40, C040, BWBO, and COBO represent the four color text modes supported
by the IBM PC Color/Graphics Adapter (CGA). The Mono constant represents the single black-and-white text mode supported by the. IBM PC
Monochrome Adapter. FontBxB represents EGA/VGA 43- and 50-line
modes. The C40 and CBO constants are for 3.0 compatibility.
300
= 0;
= 1;
= 2;
= 3;
= 4;
= 5;
= 6;
= 7;
DarkGray
LightBlue
LightGreen
LightCyan
LightRed
LightMagenta
Yellow
White
Blink
8;
= 9;
= 10;
= 11;
12;
= 13;
= 14;
= 15;
= 128;
=
Colors are represented by the numbers between 0 and 15; to easily identify
each color, these constants can be used instead of numbers. In the color text
modes, the foreground of each character is selectable from 16 colors, and
the background from 8 colors. The foreground of each character can also be
made to blink.
Crt Variables
Here are the variables in Crt:
var
CheckBreak
CheckEof
CheckSnow
DirectVideo
LastMode
TextAttr
WindMin
WindMax
:
SavelntlB
boolean;
boolean;
boolean;
boolean;
word;
byte;
word;
word;
pointer;
CheckBreak
Enables and disables checks for etr/-Break.
var CheckBreak: boolean;
When CheckBreak is True, pressing etr/-Break will abort the program when it
next writes to the display. When CheckBreak is False, pressing etr/-Break has
no effect. CheckBreak is True by default. (At runtime, Crt stores the old
Control-Break interrupt vector, $IB, in a global pointer variable called
SavelntlB.)
CheckEOF
Enables and disables the end-of-file character:
301
CheckSnow
Enables and disables "snow-checking" when storing characters directly in
video memory.
var CheckSnow: boolean;
DirectVideo
Enables and disables direct memory access for Write and Writeln statements
that output to the screen.
var DirectVideo: boolean;
When DirectVideo is True, Writes and Writelns to files associated with the
CRT will store characters directly in video memory instead of calling the
BIOS to display them. When DirectVideo is False, all characters are written
through BIOS calls, which is a significantly slower process.
DirectVideo always defaults to True. If, for some reason, you want characters displayed through BIOS calls, set DirectVideo to False at the
beginning of your program and after each call to TextMode.
LastMode
Each time TextMode is called, the current video mode is stored in LastMode.
In addition, LastMode is initialized at program startup to the then-active
video mode.
302
TextAttr
Stores the currently selected text attributes.
var TextAttr: byte;
The text attributes are normally set through calls to TextColor and
TextBackground. However, you can also set them by directly storing a value
in TextAttr. The color information is encoded in TextAttr as follows:
where iff! is the 4-bit foreground color, bbb is the 3-bit background color,
and B is the blink-enable bit. If you use the color constants for creating
TextAttr values, note that the background color can only be selected from
the first 8 colors, and that it must be multiplied by 16 to get it into the
correct bit positions. The following assignment selects blinking yellow
characters on a blue background:
TextAttr := Yellow + Blue
16 + Blink;
These variables are set by calls to the Window procedure. WindMin defines
the upper left corner, and WindMax defines the lower right corner. The X
coordinate is stored in the low byte, and the Y coordinate is stored in the
high byte. For example, Lo(WindMin) produces the X coordinate of the left
edge, and Hi(WindMax) produces the Y coordinate of the bottom edge. The
upper left corner of the screen corresponds to (X,Y) = (0,0). Note, however,
that for coordinates passed to Window and GotoXY, the upper left corner is
at (1,1).
Procedures
Assignert
303
ClrEol
ClrScr
Delay
DelLine
GotoXY
HighVideo
InsLine
LowVideo
NoSound
Sound
TextBackground
TextColor
TextMode
Window
Functions
KeyPressed
NormVideo
ReadKey
WhereX
WhereY
304
Drivers
Graphics drivers are provided for the following graphics adapters (and true
compatibles):
.CGA
MCGA
EGA
.VGA
Hercules
AT&T 400 line
.3270 PC
Each driver contains code and data and is stored in a separate file on disk.
At runtime, the InitGraph procedure identifies the graphics hardware, loads
and initializes the appropriate graphics driver, puts the system into
graphics mode, and then returns control to the calling routine. The
CloseGraph procedure unloads the driver from memory and restores the
previous video mode. You can switch back and forth between text and
graphics modes using the RestoreCrtMode and setGraphMode routines. To
load the driver files yourself or link them into your .EXE, refer to
RegisterBGldriver in Chapter 27.
305
requested on a dual monitor system, InitGraph will select the monitor and
graphics card that will produce the highest quality graphics output.
CGA.BGI
EGAVGA.BGI
HERC.BGI
ATT.BGI
PC3270.BGI
Coordinate System
By convention, the upper left corner of the graphics screen is (0,0). The x
values, or columns, increment to the right. The y values, or rows, increment
downward. Thus, in 320x200 mode on a CGA, the screen coordinates for
each of the four corners with a specified point in the middle of the screen
would look like this:
(0,0)
(319,0)
(159,99)
(0,199)
(319,199)
Current Pointer
Many graphics systems support the notion of a current pointer (CP). The
CP is similar in concept to a text mode cursor except that the CP is not
visible.
Write (' ABC') ;
In text mode, the preceding Write statement will leave the cursor in the
column immediately following the letter C. If the C is written in column 80,
then the cursor will wrap around to column 1 of the next line. If the C is
written in column 80 on the 25th line, the entire screen will scroll up one
line, and the cursor will be in column 1 of line 25.
306
MoveTo(O,O)
LineTo(20,20)
In graphics mode, the preceding LineTo statement will leave the CP at the
last point referenced (20,20). The actual line output would be clipped to the
current viewport if clipping is active. Note that the CP is never clipped.
The MoveTo command is the equivalent of GoToXY. It's only purpose is to
move the CPo Only the commands that use the CP move the CP: InitGraph,
MoveTo, MoveRel, LineTo, LineRel, OutText, SetGraphMode,* GraphDefaults,*
ClearDevice,* SetViewPort,* and ClearViewPort*. (The * indicates procedures
that move the CP to (0,0).)
Text
An 8x8 bit-mapped font and several "stroked" fonts are included for text
output while in graphics mode. A bit-mapped. character is defined by an
8x8 matrix of pixels. A stroked font is defined by a series of vectors that tell
the graphics system how to draw the font.
The advantage to using a stroked font is apparent when you start to draw
large characters. Since a stroked font is defined by vectors, it will still retain
good resolution and quality when the font is enlarged.
When a bit-mapped font is enlarged, the matrix is multiplied by a scaling
factor and as the scaling factors becomes larger, the characters' resolution
becomes coarser. For small characters, the bit-mapped font should be
sufficient, but for larger text you will want to select a "stroked" font.
The justification of graphics text is controlled by the SetTextJustify
procedure. Scaling and font selection is done with the SetTextStyle
procedure. Graphics text is output by calling either the OutText or
OutTextXY procedures. Inquiries about the current text settings are made
by calling the GetTextSettings procedure. The size of stroked fonts can be
customized by the SetUserCharSize procedure.
Stroked fonts are each kept in a separate file on disk with a .CHR file
extension. Font files can be loaded from disk automatically by the Graph
unit at runtime (as described), or they can also be linked in or loaded by the
user program and "registered" with the Graph unit.
A special utility, BINOBJ.EXE, is provided that converts a font file (or any
binary data file, for that matter) to an .OBJ file that can be linked into a unit
or program using the {$L} compiler directive. This makes it possible for a
program to have all its font files built into the .EXE file. (Read the
comments at the beginning of the GRLINK.PAS sample program Disk 3.)
307
GetPixel and PutPixel are provided for reading and plotting pixels. GetImage
and PutImage can be used to save and restore rectangular regions on the
screen. They support the full complement of BitBlt operations (normal, XOf,
Of, and, not).
Error Handling
Internal errors in the Graph unit are returned by the function GraphResult.
GraphResult returns an error code that reports the status of the last graphics
operation. The following error return codes are defined:
.0: No error
-1: (BGI) graphics not installed (use InitGraph)
-2: Graphics hardware not detected
-3: Device driver file not found
-4: Invalid device driver file
308
Bar
Bar3D
ClearViewPort
DetectGraph
DrawPoly
FillPoly
FloodFill
ImageSize
InitGraph
PieSlice
RegisterBGldriver
RegisterBGlfont
SetAliPalette
SetFillPattern
SetFillStyle
SetGraphBufSize
SetGraphMode
SetLineStyle
SetPalette
SetTextJustify
SetTextStyle
Set ViewPort
ValidMode
Note that GraphResult is reset to zero after it has been called. Therefore, the
user should store the value of GraphResult into a temporary variable and
then test it. The following return code constants are defined:
const
{ GraphResult error return codes
grOk
0;
grNolnitGraph
-1;
grNotDetected
-2;
grFileNotFound
-3;
grlnvalidDriver
-4;
grNoLoadMem
-5;
grNoScanMem
-6;
grNoFloodMem
-7;
-8;
grFontNotFound
grNoFontMem
-9;
grlnvalidMode
= -10;
= -11;
grError
grIOError
= -12;
= -13;
grlnvalidFont
grlnvalidFontNum = -14;
grlnvalidDeviceNum = -15;
309
Getting Started
Here's a simple graphics program:
1 program GraphTest;
2 uses
3
Graph;
4 var
5
GraphDriver integer;
6
GraphMode
integer;
7
ErrorCode
integer;
8 begin
9
GraphDriver := Detect;
{ Set flag: do detection
10 InitGraph(GraphDriver, GraphMode, 'C:\DRIVERS');
ErrorCode := GraphResult;
11
12 if ErrorCode <> grOk then
{ Error?
begin
13
14
Writeln('Graphics error: " GraphErrorMsg(ErrorCode));
15
Writeln('Program aborted ... ');
16
Halt(1);
17
end;
18 Rectangle (0, 0, GetMaxX, GetMaxY);
Draw full screen box
19 SetTextJustify(CenterText, CenterText);
{ Center text
20 SetTextStyle(DefaultFont, HorizDir, 3);
21 OutTextXY(GetMaxX div 2, GetMaxY div 2,
Center of screen
22
'Borland Graphics Interface (BGI)');
23 Readln;
24 CloseGraph;
25 end. { GraphTest
The program begins with a call to InitGraph, which autodetects the hardware and loads the appropriate graphics driver (located in C:\DRIVERS). If
no graphics hardware is recognized or an error occurs during initialization,
an error message is displayed and the program terminates. Otherwise, a
box is drawn along the edge of the screen and text is displayed in the center
of the screen.
Note: The AT&T 400 line card is not autodetected. You can still use the
AT&T graphics driver by overriding autodection and passing InitGraph the
AT&T driver code and a valid graphics mode. Replace lines 9 and 10 in the
preceding example with the following three lines of code:
GraphDriver := ATT400;
GraphMode := ATT400Hi;
InitGraph(GraphDriver, GraphMode, 'C:\DRIVERS');
This instructs the graphics system to load the AT&T 400 line driver located
in C: \ DRIVERS and set the graphics mode to 640 by 400.
Here's another example that demonstrates how to switch back and forth
between graphics and text modes:
310
1 program GraphTest;
2 uses
3
Graph;
4 var
5
GraphDriver integer
6
GraphMode
integer
7
ErrorCode
integer
8 begin
9
GraphDriver:= Detect;
{ Set flag: do detection
10
InitGraph(GraphDriver, GraphMode, 'C:\DRIVERS');
11
ErrorCode:= GraphResult;
12
if ErrorCode <> grOk then
{ Error?
13 begin
14
Writeln('Graphics error: " GraphErrorMsg(ErrorCode));
15
Writeln('Program aborted ... ');
16
Halt(I);
17
end;
18 OutText('In Graphics mode. Press <RETURN>');
19 Readln;
20
RestoreCRTMode;
21
Write('Now in text mode. Press <RETURN>');
22
Readln;
23
SetGraphMode(GraphMode);
24
OutText('Back in Graphics mode. Press <RETURN>');
25
Readln;
26 CloseGraph;
27 end. { GraphTest
Note that the SetGraphMode call on line 23 resets all the graphics parameters
(palette, current pointer, foreground, and background colors, and so on) to
the default values.
The call to Close Graph restores the video mode that was detected initially by
InitGraph and frees the heap memory that was used to hold the graphics
driver.
311
Two pointers are defined by Graph that by default point to the two
standard routines described here. The pointers are defined as follows:
var
GraphGetMemPtr
GraphFreeMemPtr
pointer;
pointer
312
pointer; Size
word);
{ Deallocate memory for graphics device drivers, fonts, and scan buffer}
begin
if P <> Nil then
{ Don't free Nil pointers!
begin
FreeMem(P, Size);
P := Nil;
end;
end; { MyFreeMem
procedure MyExitProc;
{ Always gets called when program terminates
begin
ExitProc := PreGraphExitProc;
CloseGraph;
end; { MyExitProc
{$F-}
begin
{ Install clean-up routine }
PreGraphExitProc := ExitProc;
ExitProc := @MyExitProc;
GraphGetMemPtr := @MyGetMem;
GraphFreeMemPtr := @MyFreeMem;
GraphDriver := Detect;
InitGraph(GraphDriver, GraphMode, ");
ErrorCode := GraphResult;
if ErrorCode <> grOk then
begin
Writeln('Graphics error: " GraphErrorMsg(ErrorCode));
Readln;
Ralt(l);
end;
Line(O, 0, GetMaxX, GetMaxY);
OutTextXY(I, I, 'Press <Return>:');
Readln;
end. {UserReapManagment}
313
grNoFloodMem
grFontNotFound
grNoFontMem
grlnvalidMode
grError
grIOerror
grlnvalidFont
grlnvalidFontNum
grlnvalidDeviceNum
{ Define
Detect
CGA
MCGA
EGA
EGA64
EGAMono
RESERVED
HercMono
ATT400
VGA
PC3270
=
=
=
=
=
=
-7;
-8;
-9;
-10;
-11;
-12;
-13;
-14;
-15;
graphics drivers
0;
1;
2;
= 3;
= 4;
= 5;
= 6;
= 7;
= 8;
= 9;
= 10;
=
=
=
( Graphics
CGACO
CGAC1
CGAC2
CGAC3
CGAHi
MCGACO
MCGAC1
MCGAC2
MCGAC3
MCGAMed
MCGAHi
EGALo
EGAHi
EGA64Lo
EGA64Hi
EGAMonoHi
HercMonoHi
ATT400CO
ATT400C1
ATT400C2
ATT400C3
ATT400Med
ATT400Hi
VGALo
VGAMed
VGAHi
PC3270Hi
( Generic error }
{ Requests autodetection }
1 page
1 page
1 page
1 page
1 page
1 page
1 page
1 page
1 page
1 page }
1 page }
4 page }
2 page }
1 page }
1 page }
2 page }
2 page }
1 page}
1 page}
1 page}
1 page }
1 page }
1 page }
4 page }
2 page }
1 page }
1 page }
314
Magenta
Brown
LightGray
DarkGray
LightBlue
LightGreen
LightCyan
LightRed
LightMagenta
Yellow
White
= 5;
= 6;
= 7;
= 8;
= 9;
= 10;
= 11;
= 12;
= 13;
= 14;
=
15;
NormWidth = 1;
ThickWidth = 3;
{ Set/GetTextStyle constants
DefaultFont = 0;
TriplexFont = 1;
= 2;
SmallFont
SansSerifFont = 3;
GothicFont
= 4;
HorizDir
VertDir
{ Left to right
{ Bottom to top
0;
= 1;
UserCharSize
0;
{ Clipping constants
ClipOn = True;
ClipOff = False;
{ Bar3D constants
TopOn = True;
TopOff = False;
{ Fill patterns
EmptyFill
SolidFill
LineFill
LtSlashFill
SlashFill
BkSlashFill
LtBkSlashFill
HatchFill
XHatchFill
InterleaveFill
WideDotFill
CloseDotFill
UserFill
for Get/SetFillStyle
0;
1;
= 2;
= 3;
= 4;
= 5;
6;
= 7;
= 8;
= 9;
= 10;
= 11;
= 12;
=
=
315
MOV
XOR
OR
AND
NOT
1;
2;
0;
2;
const
MaxColors 15;
type
PaletteType record
Size
Colors
end;
byte;
LineSettingsType = record
LineStyle
Pattern
Thickness
end;
word;
word;
word;
TextSettingsType = record
Font
Direction
CharSize
Horiz
Vert
end;
word;
word;
word;
word;
word;
FillSettingsType
record
Pattern
Color
end;
316
record
X, Y
Xstart, Ystart
Xend, Yend
end;
integer;
boolean;
integer;
integer;
integer;
var
GraphGetMemPtr
GraphFreeMemPtr
pointer;
pointer;
integer);
boolean);
317
word);
Procedures
Arc
Bar
Bar3D
Circle
ClearDevice
318
ClearViewPort
Close Graph
DetectGraph
DrawPoly
Ellipse
FillPoly
FloodFill
GetArcCoords
GetAspectRatio
GetFillPattem
GetFillSettings
Getlmage
GetLineSettings
GetModeRange
GetPalette
GetTextSettings
GetViewSettings
GraphDefaults
319
InitGraph
Line
LineRel
LineTo
MoveRel
MoveTo
OutText
OutTextXY
PieSlice
PutImage
PutPixel
Rectangle
RestoreCrtMode
SetActivePage
SetAllPalette
SetBkColor
SetColor
SetFillPattern
SetFillStyle
SetGraphBufSize
SetGraphMode
SetLineStyle
SetPalette
320
SetTextJustify
SetTextStyle
SetUserCharSize
SetViewPort
SetVisualPage
Functions
GetBkColor
GetColor
GetGraphMode
GetMaxColor
GetMaxX
GetMaxY
GetPixel
GetX
GetY
GraphErrorMsg
GraphResult
ImageSize
RegisterBGIdriver
RegisterBGIfont
321
TextHeight
TextWidth
Interface Section
Here's a look at the interface section of the Turbo3 unit:
unit Turbo3;
interface
uses Crt;
var
Kbd
Text;
CBreak : boolean absolute CheckBreak;
function MemAvail: integer;
function MaxAvail: integer;
function LongFileSize(var F): real;
function LongFilePos(var F): real;
procedure LongSeek(var F; Pos: real);
procedure HighVideo;
procedure NormVideo;
procedure LowVideo;
function IOResult : integer;
As you can see, there are two global variables, five functions, and four
procedures declared in the Turbo3 unit.
322
Kbd
This is provided for 3.0 programs that read from.the keyboard device; for
example, Read(Kbd, CharVar). Note that there is now a function in the Crt
unit called ReadKey that should be used in place of Read(Kbd, CharVar). Here
are two programs that read a character and report whether an extended
key was typed (F1, F2, Left arrow, and so on):
In version 3.0:
program TestKbd;
uses Crt, Turbo3;
var
c : char;
begin
Read (Kbd, c);
if (c = #27) and KeyPressed then
begin
Read (Kbd, c);
Writeln('Extended key: " c);
end
else
Writeln(c);
end.
Notice that the Kbd device handler converts extended keys from (null +
character) to (ESC + second character). Since Esc (#27) is a perfectly valid
key to enter from the keyboard, a call to KeyPressed must be made to
determine whether the #27 is the first key from an extended key or an
actual Esc typed on the keyboard. If an Esc is typed, followed quickly by
another character before the program detected the Esc, the two keys would
be mistaken as an extended keystroke.
In version 4.0:
program TestReadKey;
uses Crt;
var
c : char;
begin
c := ReadKey;
if (c = #0) then
Writeln('Extended key: " ReadKey);
else
Writeln(c);
end.
The code in 4.0 is smaller (and faster), and contains none of the ambiguity
about the leading character of an extended keystroke. (It is impossible to
generate a null character from the keyboard except when using the
extended keys.)
323
Cbreak
Cbreak has been renamed to CheckBreak in version 4.0. Backward
compatibility is achieved by giving Cbreak the same address as CheckBreak,
which is declared in the Crt unit. The statement Cbreak := False turns off
Control-Break checking; Cbreak := True turns it back on.
Procedures
LongSeek
HighVideo
NormVideo
LowVideo
Functions
MemAvail
MaxAvail
LongFileSize
.LongFilePos
IOResult
was made up of two files, GRAPH.P and GRAPH. BIN that supported the
IBM CGA and compatibles. GRAPH.P actually defines the external
machine code routines contained in GRAPH.BIN.
Graph3 combines GRAPH.P and GRAPH.BIN into a single unit, still
retaining the same functionality. The only modification you need to make
to a Turbo Pascal 3.0 program that uses the turtlegraphics driver is to
remove the {$I GRAPH.P} compiler directive, replacing it with a reference
to Crt and Graph3 in your program's uses clause.
Note: The routines that follow are not described in Chapter 27, the lookup
section. For more detailed information about Graph3J routines, refer to your
Turbo Pascal 3.0 reference manual.
Here are Graph3' s constants:
const
North = 0;
East = 90;
South = 180;
West = 270;
Procedures
Arc
Back
Circle
Draws a circle.
ClearScreen
ColorTable
Draw
FillPattem
FillScreen
FillShape
Forwd
325
GetDotColor
GetPic
GraphBackground
GraphColorMode
GraphMode
GraphWindow
Heading
HideTurtle
HiRes
HiRes Color
Home
NoWrap
Palette
Pattern
PenDown
PenUp
Plot
PutPic
SetHeading
326
,
Turns the turtle to the specified angle.
(Turtlegraphics)
I
SetPenColor
SetPosition
ShowTurtle
TumLeft
TumRight
TurtleWindow
TurtleThere
TurtleDelay
Wrap
XCor
YCor
327
328
25
Using the 8087
There are two kinds of numbers you can work with in Turbo Pascal:
integers (shortint, integer, longint, byte, word) and reals (real, single,
double, extended, comp). Reals are also known as floating-point numbers.
The 8086 processor is designed to easily handle integer values, but it takes
considerably more time and effort to handle reals; The 8086 family of
processors has a corresponding family of math coprocessors, the 8087s.
The 8087 is a special hardware numeric processor that can be installed in
your PC. It executes floating-point instructions very quickly, so if you use
floating point a lot, you'll probably want a coprocessor.
Turbo Pascal is designed to provide optimal floating-point performance
whether or not you have an 8087.
For programs running on any PC, with or without an 8087, Turbo Pascal
provides the real type and an associated library of-software routines that
handle floating-point operations. The real type occufies 6 bytes of
memory, providing a range of 2.9 x 10-39 to 1.7 X 103 with 11 to 12
significant digits. The software floating.;.point library is optimized for
speed and size, trading in some of the fancier features provided by the
8087 processor.
If you're only writing programs for systems that have a math
coprocessor, you can instruct Turbo Pascal to produce code that uses the
8087 chip. This gives you access to four additional real types (single,
double, extended, and comp), and an extended floating-point range of 1.9
x 10E-4951 .. 1.1 x 10E4932 with 19 to 20 significant digits.
You can switch between the two different models of floating-point code
generation with the $N compiler directives or with the Ole/Numeric
329
processing menu item. {$N-} indicates software floating point (the default),
and {$N+} indicates hardware floating point.
The remainder of this chapter discusses special issues concerning Turbo
Pascal programs that use the 8087 coprocessor.
330
* B - A * Cll / A;
With no special effort by the programmer, Turbo Pascal performs computations using the precision and range of the extended type. The added
precision means smaller round-off errors, and the additional range means
overflow and underflow are less common, so that programs work more
often.
You can go beyond Turbo Pascal's automatic extended capabilities. For
example, you can declare- variables used for intermediate results to be of
type extended. The following example computes a sum of products:
var
Sum : single;
X,Y array[1 .. 100] of single;
I
integer;
T
extended;
begin
T := 0.0;
for I := 1 to 100 do T := T + XlI]
Sum := T;
end;
* Y[I];
331
Comparing Reals
Because real-type values are approximations, the results of comparing
values of different real types are not always as expected. For example, if X
is a variable of type single and Y is a variable of type double, then the
following statements will output False:
x
:= 1/3;
Y := 1/3;
Writeln(X
Y);
x :=
1/3;
Writeln(X
1/3);
will output False, since the result of 1/3 in the Writeln statement is
calculated with 20 significant digits.
332
The parameters only occupy 8087 stack space during the call, not during
execution of the procedure or function.
In theory, very complicated real-type expressions can cause an 8087 stack
overflow. However, this is not likely to occur, since it would require the
expression to generate more than eight temporary results.
A more tangible danger lies in nested function calls. If such constructs are
not coded correctly, they can very well cause an 8087 stack overflow.
Assuming function Test is an extended function that takes three extended
value parameters, then the construct
X := Test(A,B,Test(C,D,Test(E,F,Test(X,Y,Z))));
will cause an 8087 stack overflow. This is because at the innermost call to
Test, six floating-point values have already been pushed on the 8087 stack,
leaving room for only two more. The correct construct in this case is
X :=
X :=
X :=
X :=
Test(X,Y,Z);
Test(E,F,X);
Test(C,D,X);
Test(A,B,X);
A call to this version of Fib will cause an 8087 stack overflow for values of N
larger than 8. The reason is that the calculation of the last assignment
requires a temporary on the 8087 stack to store the result of Fib(N-l). Each
recursive invocation allocates one such temporary, causing an overflow the
ninth time. The correct construct is this case is
function Fib(N: integer): extended;
var
F1,F2: extended;
begin
if N = a then
Fib := 0.0
else
if N = 1 then
Fib := 1. a
333
else
begin
Fl := Fib(N-l); F2 := Fib(N-2);
Fib := Fl + F2;
end;
end;
The temporary results are now stored in variables allocated on the 8086
stack. (The 8086 stack can of course also overflow, but this would typically
require significantly more recursive calls.)
334
26
Inside Turbo Pascal
In this chapter, we provide technical information for advanced Turbo
Pascal programmers. We'll cover such topics as memory maps, the heap
manager, internal data formats, calling conventions, and more.
Figure 26.1 (on page 336) depicts the memory map of a Turbo Pascal
program.
The Program Segment Prefix (PSP) is a 256-byte area built by MS-DOS
when the .EXE file is loaded. The segment address of PSP is stored in the
predeclared word variable PrefixSeg.
Each module (which includes the main program and each unit) has its own
code segment. The main program occupies the first code segment; the code
segments that follow it are occupied by the units (in reverse order from
how they are listed in the uses clause), and the last code segment is
occupied by the runtime library (the System unit). The size of a single code
segment cannot exceed 64K, but the total size of the code is limited only by
the available memory.
335
Top of D OS M emory
~
FreePfr
-+
Free memory
HeapPfr
HeapOrg
-+
-+
The Heap
grows
toward high
memory ...
+-
Sptr
+-
SSeg
Global Variables
The Data Segment
Typed Constants
DSeg
-+
c. D. E;
<:
"'7'
"'7
Contents
of .EXE
File
Image
PrefixSeg
The data segment (addressed through D5) contains all typed constants
followed by all global variables. The D5 register is never changed during
program execution. The size of the data segment cannot exceed 64K.
On entry to the program, the stack segment register (55) and the stack
pointer (5P) are loaded so that 55:5P points to the first byte past the stack
segment. The 55 register is never changed during program execution, but
5P can move downward until it reaches the bottom of the segment. The size
of the stack segment cannot exceed 64K; the default size is 16K, but this can
be changed with a $M compiler directive.
The heap stores dynamic variables, that is, variables allocated through calls
to the New and GetMem standard procedures. It occupies all or some of the
free memory left when a program is executed. The actual size of the heap
depends on the minimum and maximum heap values, which can be set
336
HeapPtr is always normalized after each operation, thus forcing the offset
part into the range $0000 to $OOOF. The maximum size of a single variable
that can be allocated on the heap is 65521 bytes (corresponding to $10000
minus $OOOF), since every variable must be completely contained in a single
segment.
Disposal Methods
The dynamic variables stored on the heap are disposed of in one of two
ways: (1). through Dispose or FreeMem or (2) through Mark and Release. The
simplest scheme is that of Mark and Release; for example, if the following
statements are executed:
New (Ptrl) ;
New(Ptr2) ;
Mark(P);
New(Ptr3);
New(Ptr4);
New(PtrS);
the layout of the heap will then look like Figure 26.2.
337
Pfr1
low
Memory
-+
Contents of Pfr1"
Pfr2
-+
Pfr3
-+
Pfr4
-+
PfrS
-+
HeapPfr
-+
Contents of
Pfr2~
Contents of Pfr3"
Contents of Pfr4"
Contents of PfrS"
High
Memory
Figure 26.2: Disposal Method Using Mark and Release
The Mark(P) statement marks the state of the heap just before Ptr3 is
allocated (by storing the current ReapPtr in P). If the statement Release(P) is
executed, the heap layout becomes like that of Figure 26.3, effectively
disposing of all pointers allocated since the call to Mark.
Pfr1
low
Memory
-+
Contents of Pfr1"
Pfr2
-+
HeapPfr
-+
Contents of Pfr2"
High
Memory
Figure 26.3: Heap Layout with Release(P) Executed
338
--+
Contents of ptr1"
ptr2
Low
Memory
--+
Contents of ptr2"
ptr4
--+
ptrS
--+
Heapptr
--+
Contents of ptr4"
Contents of ptrS"
L - -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _----1
High
Memory
If at this time New(Ptr3) has been executed, it would again occupy the same
memory area. On the other hand, executing Dispose(Ptr4) enlarges the free
block, since Ptr3 and Ptr4 were neighboring blocks (see Figure 26.5).
339
ptr1
Low
-+
Memory
Contents of ptr1"
ptr2
-+
Contents of ptr2"
ptr5
-+
Heapptr
-+
Contents of ptr5"
------I
L - -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
High
Memory
Finally, executing Dispose(Ptr5) first creates an even bigger free block, and
then lowers HeapPtr. This, in effect, releases the free block, since the last
valid pointer is now Ptr2 (see Figure 26.6).
ptr1
Low
-+
Memory
Contents of ptr1"
ptr2
-+
Heapptr
-+
Contents of ptr2"
~-----------------------I
High
Memory
The heap is now in the same state as it would be after executing Release(P),
as shown in Figure 26.2. However, the free blocks created and destroyed in
the process were tracked for possible reuse.
340
FreeList
FreeListP
=
=
record
OrgPtr,EndPtr: pointer;
end;
array[O .. 8190] of FreeRec;
AFreeList;
The OrgPtr and EndPtr fields of each record define the origin and end of
each free block. (EndPtr is in fact a pointer to the first byte after the block.)
Both are normalized pointers. The number of entries in the FreeList array is
calculated from
FreeCount = (8192 - Ofs(FreePtr A) div 8) mod 8192
This means that there can be up to 8191 entries in the free list. When the
offset part of FreePtr is 0, the free list is empty. FreePtr can be compared to
the stack pointer in the sense that it grows downward, and that all bytes
from FreePtr to the end of the heap segment are part of the "free stack."
Note: Trying to dispose of a pointer when the free list is full causes a
runtime error. However, a full free list is a highly unlikely situation-it
would reqire 8191 completely noncontiguous blocks to be disposed of and
not reused.
FreePtr also serves to mark the top of free memory in the heap (the bottom
of which is pointed to by HeapPtr). Note, though, that when the offset part
of FreePtr is 0, $1000 must be added to the segment part to produce the true
top-of-heap pointer. (In fact, the segment part of FreePtr always contains the
segment address of top-of-memory minus $1000.)
341
342
{ 16 byte blocks }
{ 16 byte blocks }
Note that the {$F+} compiler directive forces the heap error function to use
the far call model.
The heap error function is installed by assigning its address to the
HeapError variable:
HeapError:=@HeapFunc;
The heap error function gets called whenever a call to New or GetMem
cannot complete the request. The Size parameter contains the size of the
block that could not be allocated, and the heap error function should
attempt to free a block of at least that size.
Depending on its success, the heap error function should return 0, 1, or 2. A
return of indicates failure, causing a runtime error to occur immediately.
A return of 1 also indicates failure, but instead of a runtime error, it causes
New or GetMem to return a nil pointer. Finally, a return of 2 indicates
success and causes a retry (which could also cause another call to the heap
error function).
The standard heap error function always returns 0, thus causing a runtime
error whenever a call to New or GetMem cannot be completed. However, for
many applications, the simple heap error function that follows is more
appropriate:
{$F+} function HeapFunc(Size: word) integer; {$F-}
begin
HeapFunc:=l;
end;
343
When installed, this function causes New or GetMem to return nil when
they cannot complete the request, instead of aborting the program.
Char Types
A char, or a subrange of a char type, is stored as an unsigned byte.
Boolean Types
A boolean type is stored as a byte that can assume the value of 0 (False) or
1 (True).
Enumerated Types
An enumerated type is stored as an unsigned byte if the enumeration has
256 or fewer values; otherwise, it is stored as an unsigned word.
344
Floating-Point Types
The floating-point types (real, single, double, extended, and camp) store the
binary representations of a sign (+ or -), an exponent, and a significand. A
represented number has the value
+/- significand x
2exponent
where the significand has a single bit to the left of the binary decimal point
(that is, 0 <= significand < 2).
Note: In the figures that follow, msb means most significant bit, and lsb
means least significant bit. The left-most items are stored at the highest
addresses. For example, for a real-type value, e is stored in the first byte, fin
the following five bytes, and s in the most significant bit of the last byte.
The-Real.Type
A 6-byte (48-bit) Real number is divided into three fields:
39
width
e
Isb msb
msb
Isb
order
2(e-129)
(1.f).
Note: The real type cannot store denormals, _NaNs, and infinities.
Denormals become zero when stored in a real, and NaNs and infinities
produce an overflow error if an attempt is made to store them in a real.
e
msb
width
I.
Isb msb
Isb
order
(1.f).
345
if
if
if
if
e
e
e
e
=
=
= 255
= 255
and
and
and
and
<> 0,
= 0,
= 0,
<> 0,
f
f
f
f
then
then
then
then
v
v
v
v
is a NaN.
11
width
e
msb
Isb msb
Isb
order
if
if
if
if
=< e <
=
=
e
e
e
e
2047,
and
and
2047 and
= 2047 and
f
f
f
f
<> 0,
= 0,
= 0,
<> 0,
then
then
then
then
then
v
v
v
v
v
15
width
e
msb
Isb
msb
Isb
order
63
d
msb
346
Isb
order
Pointer Types
A pointer type is stored as a double word, with the offset part in the low
word and the segment part in the high word. The pointer value nil is
stored as a double-word zero.
String Types
A string occupies as many bytes as its maximum length plus one. The first
byte contains the' current dynamic length of the string, and the following
bytes contain the characters of the string. The length byte and the
. characters are considered unsigned values. Maximum string length is 255
characters plus a length byte (string[255]).
Set Types
A setis a bit array, where each bit indicates whether an element is in the set
or not. The maximum. number of elements in a set is 256, so a set never
occupies more than 32 bytes. The number of bytes occupied by a particular
set is calculated as
ByteSize = (Max div 8) - (Min div 8) + 1
where Min and Max are the lower and upper bounds of the base type of
that set. The byte number of a specific element E is
ByteNumber
E mod 8
347
Array Types
An array is stored as a contiguous sequence of variables of the component
type of the array. The components with the lowest indexes are stored at the
lowest memory addresses. A multidimensional array is stored with the
right-most dimension increasing first.
Record Types
The fields of a record are stored as a contiguous sequence of variables. The
first field is stored at the lowest memory address. If the record contains
variant parts, then each variant starts at the same memory address.
File Types
File types are represented as records. Typed files and untyped files occupy
128 bytes, which are laid out as follows:
type
FileRec
record
Handle
Mode
RecSize
Private
UserData
Name
end;
word;
word;
word;
array[1 .. 26] of byte;
array[1 .. 16] of byte;
array[O .. 79] of char;
Text files occupy 256 bytes, which are laid out as follows:
type
CharBuf = array[O .. 127] of char;
TextRec = record
Handle
word;
Mode
word;
BufSize
word;
Private
word;
BufPos
word;
BufEnd
word;
BufPtr
ACharBuf;
OpenFunc pointer;
InOutFunc: pointer;
FlushFunc: pointer;
CloseFunc: pointer;
UserData array[1 .. 16] of byte;
Name
array[O .. 79] of char;
Buffer
CharBuf;
end;
348
fmClosed indicates that the file is closed. fmlnput and fmOutput indicate that
the file is a text file that has been reset (fmlnput) or rewritten (fmOutput).
fmlnOut indicates that the file variable is a typed or an untyped file that has
been reset or rewritten. Any other value indicates that the file variable has
not been assigned (and thereby not initialized).
The UserData field is never accessed by Turbo Pascal, and is free for userwritten routines to store data in.
Calling Conventions
Parameters are transferred to procedures and functions via the stack.
Before calling a procedure or function, the parameters are pushed onto the
stack in their order of declaration. Before returning, the procedure or
function removes all parameters from the stack.
The skeleton code for a procedure or function call looks like this:
PUSH
PUSH
Paraml
Param2
PUSH
CALL
PararnX
ProcOrFunc
349
Variable Parameters
Variable parameters (var parameters) are always passed by reference-a
pointer points to the actual storage location.
Value Parameters
Value parameters are passed by value or by reference depending on the
type and size of the parameter. In general, if the value parameter occupies
1, 2, or 4 bytes, the value is pushed directly onto the stack. Otherwise a
pointer to the value is pushed, and the procedure or function then copies
the value into a local storage location.
Note: The 8086 does not support byte-sized PUSH and POP instructions, so
byte-sized parameters are always transferred onto the stack as words. The
low-order byte of the word contains the value, and the high-order byte is
unused (and undefined).
An integer type or parameter is passed as a byte, a word, or a double word,
using the same format as an integer-type variable. (For double words, the
high-order word is pushed before the low-order word so that the low-order
word ends up at the lowest address.)
A char-type parameter is passed as an unsigned byte.
A boolean-type parameter is passed as a byte with the value 0 or 1.
An enumerated-type parameter is passed as an unsigned byte if the
enumeration has 256 or fewer values; otherwise it is passed as an unsigned
word.
A real-type parameter (type real) is passed as 6 bytes on the stack, thus
being an exception to the rule that only 1,2, and 4 byte values are passed
directly on the stack.
An 8087-type parameter (type single, double, extended, or comp) is not
passed on the 8086 stack. Instead, 8087-type parameters are pushed in
order of appearance onto the internal stack of the 8087 numeric coprocessor. This limits to eight the allowable number of 8087-type value
350
Function Results
Ordinal-type function results (integer, char, boolean, and enumeration
types) are returned in the CPU registers: Bytes are returned in AL, words
are returned in AX, and double words are returned in DX:AX (high-order
word in DX, low-order word in AX).
Real-type function results (type real) are returned in the DX:BX:AX
registers (high-order word in DX, middle word in BX, low-order word in
AX).
8087-type function results (type single, double, extended, and comp) are
returned in the 8087 coprocessor's top-of-stack register (ST(O.
Pointer-type function results are returned in DX:AX (segment part in DX,
offset part in AX).
For a string-type function result, the caller pushes a pointer to a temporary
storage location before pushing any parameters, and the function returns a
string value in that temporary location. The function must not remove the
pointer.
351
segment and offset). The corresponding RET instructions pop only an offset
or both an offset and a segment.
Turbo Pascal will automatically select the correct call model based on the
procedure's declaration. Procedures declared in the interface section of a
unit are far-they can be called from other units. Procedures declared in a
program or in the implementation section of a unit are near-they can only
be called from within that program or unit.
For some specific purposes, a procedure may be required to be far; for
instance, exit procedures, text file device drivers, and other features that
involve procedure pointers. The $F compiler directive forces the far model
into effect. Procedures and functions compiled in the {$F+} state are always
far; Turbo Pascal automatically selects the correct model in the {$F-} state.
The default state is {$F-}.
A procedure or function is said to be nested when it is declared within
another procedure or function. Nested procedures and functions always
use the near call model regardless of the setting of the {$F} compiler switch,
since they are only IIvisible" within a specific procedure or function in the
same code segment.
When calling a nested procedure or function, the compiler generates a
PUSH BP instruction just before the CALL, in effect passing the caller's BP
as an additional parameter. Once the called procedure has set up its own
BP, the caller's BP is accessible as a word stored at [BP+4]. Using this "link"
at [BP+4], the called procedure can access the local variables in the caller's
stack frame. If the caller itself is also a nested procedure, it also has a link at
[BP+4], and so on. The following demonstrates how to access local
variables from an inline statement in a nested procedure:
procedure A;
var IntA: Integer;
procedure B;
var IntB: Integer;
procedure C;
var IntC: Integer;
begin inline (
$8B/$46/<IntC/
$8B/$5E/$04/
$36/$8B/$47/<IntB/
$8B/$5E/$04/
$36/$8B/$5F/$04/
$36/$8B/$47/<IntA);
end;
{C}
begin {B}
end;
{B}
begin {A}
end;
352
{A}
;Save BP
;Set up stack frame
;Allocate local variables
where LocalSize is the size of the local variables. The SUB instruction is only
present if LocalSize is not O. If the procedure's call model is near, the
parameter5 start at BP + 4; if it is far, they start at BP + 6.
The standard exit code is
MOV
POP
RET
SP,BP
BP
ParamSize
where ParamSize is the size of the parameters. The RET instruction is either
a near or a far return, depending on the procedure's call model.
. Register-Saving Conventions
Procedures and functions should preserve the BP, SP, 55, and DS registers.
All other registers may be modified.
353
354
MyProc: NEAR
MyProc + 8
Examples
The assembly language file that implements the UpperCase and StringOf
routines is shown next. It must be assembled into a file called STRS.OBJ
before the Strings unit can be compiled. Note that the routines use the far
call model because they are declared in the interface section of the unit.
CODE
EQU
EQU
UpperCase
PROC FAR
PUSH
MOV
PUSH
LOS
LES
CLD
LODSB
STOSB
MOV
XOR
JCXZ
BP
BP,SP
OS
SI,UpperStr
DI,UpperRes
CL,AL
CH,CH
U3
iSave BP
iSet up stack frame
iSave OS
iLoad string address
iLoad result address
iForward string-ops
iLoad string length
i Copy to result
iString length to CX
355
U1 :
LODSB
CMP
U2:
U3:
;Load character
;Skip if not 'a' .. 'z'
AL,' a'
JB
U2
CMP
AL,' z'
JA
U2
SUB
STOSB
LOOP
POP
POP
RET
AL,'a'-'A'
UpperCase
;Convert to uppercase
iStore in result
iLoop for all characters
iRestore OS
;Restore BP
;Remove parameter and return
U1
OS
BP
4
ENDP
EQU
EQU
EQU
StringOf
PROC FAR
PUSH
MOV
LES
MOV
CLD
STOSB
MOV
XOR
MOV
REP
POP
RET
StringOf
CODE
BP
BP,SP
DI,StrOfRes
AL,StrOfCount
CL,AL
CH,CH
AL,StrOfChar
STOSB
iSave BP
iSet up stack frame
;Load result address
iLoad count
;Forward string-ops
iStore length
iCount to CX
;Load character
;Store string of characters
iRestore BP
;Remove parameters and return
ENDP
ENDS
END
The next example shows how an assembly language routine can refer to
Pascal routines and variables. The Numbers program reads up to 100
integer values, and then calls an assembly language procedure to check the
range of each of these values. If a value is out of range, the assembly
language procedure calls a Pascal procedure to print it.
program Numbers;
{$L CHECK}
var
Data: array[1 .. 100] of integer;
Count,I: integer;
procedure RangeError(N: integer);
begin
Writeln('Range error: ' ,N);
356
end;
procedure CheckRange(Min,Max: integer); external;
begin
Count := 0;
while not Eof and (Count<100) do
begin
Count := Count+1; Readln(Data[Count]);
end;
CheckRange(-10,10);
end.
Data:WORD,Count:WORD
OATA
ENOS
CODE
;Pascal variables
ASSUME CS:CODE,OS:DATA
EXTRN
RangeError:NEAR
PUBLIC CheckRange
CheckRange
SOl:
MOV
MOV
MOV
XOR
MOV
JCXZ
CMP
JL
CMF
S02:
SD3:
JLE
PUSH
PUSH
PUSH
PUSH
PUSH
CALL
POP
POP
POP
POP
INC
INC
LOOP
PROC
;Implemented in Pascal
; Implemented here
NEAR
BX,SP
AX,SS: [BX+4]
OX,SS: [BX+2]
BX,BX
CX,Count
S04
Data[BX],AX
SD2
Oata[BX] ,OX
S03
AX
BX
CX
DX
Oata[BX]
RangeError
DX
CX
BX
AX
BX
BX
SD1
357
SD4:
CheckRange
CODE
RET
ENDP
ENDS
END
Inline Statements
An inline statement consists of the reserved word inline followed by one
or more inline elements, separated by slashes and enclosed in parentheses:
inline(lO/$2345/Count+l/Data-Offset);
intin. element
LI-----t0
M41----'-
Each inline element consists of an optional size specifier, < or >, and a
constant or a variable identifier, followed by zero or more offset specifiers
(see the syntax that follows). An offset specifier consists of a + or a followed by a constant.
inline element
358
Each inline element generates 1 byte or one word of code. The value is
computed from the value of the first constant or the offset of the variable
identifier, to which is added or subtracted the value of each of the constants
that follow it.
An inline element generates 1 byte of code if it consists of constants only
and if its value is within the 8-bit range (0 ..255). If the value is outside the
8-bit range or if the inline element refers to a variable, one word of code is
generated (least-significant byte first).
The < and> operators can be used to override the automatic size selection
we described earlier. If an inline element starts with a < operator, only the
least-significant byte of the value is coded, even if it is a 16-bit value. If an
inline element starts with a > operator, a word is always coded, even
though the most-significant byte is O. For example, the statement
inline$1234/>$44);
{ LES DI,Dest[BP]
{ MOV CX,Count[BP]
{ MOV AX,Data[BP]
{ CLD
{ REP STOSW
}
}
}
}
}
Inline statements can be freely mixed with other statements throughout the
statement part of a block.
359
Inline Directives
Inline directives let you write procedures and functions that expand into a
given sequence of machine code instructions whenever they are called.
These are comparable to macros in assembly language. The syntax for an
inline directive is the same as that of an inline statement:
inline directive
----'1
inline statement
{ eLI }
{ STI }
{ POP AX ;Pop Y }
{ POP ox ;Pop X }
IMUL OX ;OX : AX = X*Y }
Note the lack of entry and exit code and the missing return instruction.
These are not required, because the 4 bytes are inserted into the instruction
stream when LongMul is called.
Inline directives are intended for very short (less than 10 bytes) procedures
and functions only.
Because of the macro-like nature of inline procedures and functions, they
cannot be used as arguments to the @ operator and the Addr, Ofs, and Seg
functions.
360
The first statement stores the value 7 in the byte at $0040:$0049. The second
statement moves the word value stored in the first 2 bytes of the variable V
into the variable Data. The third statement moves the longint value stored
at $0040:$000C into the variable MemLong.
{ Wait };
Use of the Port and PortW arrays is restricted to assignment and reference
in expressions only, that is, components of Port and Port W cannot be used
as variable parameters. Furthermore, references to the entire Port or Port W
array (reference without index) are not allowed.
361
Interrupt Handling
The Turbo Pascal runtime library and the code generated by the compiler
are fully interruptible. Also, most of the runtime library is reentrant, which
allows you to write interrupt service routines in Turbo Pascal.
end;
As you can see, all the registers are passed as pseudo!..parameters so you
. can use and modify them in your code. You can omit some or all of the
parameters, starting with Flags and moving towards BP. It is an error to
declare more parameters than are listed in the preceding example or to
omit a specific parameter without also omitting the ones before it (although
no error is reported). For example:
procedure IntHandler(DI,ES,BP : word);
procedure IntHandler(SI,DI,DS,ES,BP : word);
362
AX
BX
CX
DX
SI
DI
DS
ES
BP
BP,SP
SP,LocalSize
AX,SEG DATA
DS,AX
Notice the lack of a STI instruction to enable further interrupts. You should
code this yourself (if required) using an inline statement. The exit code
restores the registers and executes an interrupt-return instruction:
MOV
POP
pOP
pOP
pOP
POP
POP
POP
POP
POP
SP,BP
BP
ES
os
01
SI
ox
ex
BX
AX
IRET
where TextRec is the text file record type defined in the earlier section, "File
Types." Each function must be compiled in the {$F+} state to force it to use
the far call model. The return value of a device interface function becomes
the value returned by IOResult. The return value of 0 indicates a successful
operation.
To associate the device interface functions with a specific file, you must
write a customized Assign procedure (like the AssignCrt procedure in the
Crt unit). The Assign procedure must assign the addresses of the four
device interface functions to the four function pointers in the text file
Chapter 26, Inside Turbo Pascal
363
The device interface functions can use the UserData field in the file record to
store private information. This field is not modified by the Turbo Pascal file
system at any time.
Open is always called before any of the other device interface functions. For
that reason, Assign only initializes the OpenFunc field, leaving initialization
of the remaining vectors up to Open. Based on Mode, Open can then install
pointers to either input- or output-oriented functions. This saves the InOut,
Flush, and Close functions from determining the current mode.
364
If Mode is fmlnput, the Flush function can store 0 in BufPos and BufEnd to
flush the remaining (un-read) characters in the buffer. This feature is
seldom used.
If Mode is fmOutput, the Flush function can write the contents of the buffer,
exactly like the InOut function, which ensures that text written to the device
appears on the device immediately. If Flush does nothing, the text will not
appear on the device until the buffer becomes full or the file is closed.
365
POP DX
;Pop port number
MOV AH,3
;Code for status
{ INT 14H
;Call BIOS
{ MOV AL,AH ;Get line status in AH
{ AND AL,1
iIsolate Data Ready bit
{$F+)
function AuxInput(var F: TextRec): integer;
var
P: word;
begin
with F,AuxRec(UserData) do
begin
P := 0;
while AuxInReady(Port) and (P<BufSize) do
begin
BufPtr" [P) := AuxInChar (Port); Inc (P);
end;
BufPos := 0; Bufend := P;
end;
AuxInput := 0;
end;
function AuxOutput(var F: TextRec): integer;
var
P: word;
366
begin
with F,AuxRec(UserData) do
begin
P := 0;
while P<BufPos do
begin
AuxOutChar(Port,BufPtrA[P]); Inc(P);
end;
BufPos := 0;
end;
AuxOutput := 0;
end;
function AuxIgnore(var F: TextRec): integer;
begin
AuxIgnore := 0;
end;
function AuxOpen(var F: TextRec): integer;
begin
with F,AuxRec(UserData) do
begin
Auxlnit(Port,Pararns);
if Mode=frnlnput then
begin
InOutFunc
@Auxlnput;
FlushFunc
@AuxIgnore;
end else
begin
Mode := frnOutput;
InOutFunc := @AuxOutput;
FlushFunc := @AuxOutput;
end;
CloseFunc := @AuxIgnore;
end;
AuxOpen .- 0;
end;
($F-j
procedure AssignAux;
begin
with TextRec(F) do
begin
Handle := $FFFF;
Mode := frnClosed;
BufSize := Sizeof(Buffer);
BufPtr := @Buffer;
OpenFunc := @AuxOpen;
AuxRec(UserData) .Port := Port;
AuxRec(UserData) .Pararns := Pararns;
Narne [0] . - #0;
end;
end;
end.
367
The TextRec record is defined in the Dos unit. The first two words of the 16byte UserData array are used for storing the communications port number
and parameter byte. The remaining 12 bytes are not used. Note that the
AuxRec record is used only for typecasting.
The AuxInit procedure initializes a specified communications port
according to a specified parameter byte. The AuxInChar function reads a
character from the specified port. The AuxOutChar procedure outputs a
character to the specified port. The AuxInReady function returns True if a
character is ready to be read from the specified port. Notice the use of inline
directives to implement these procedures and functions. For further details
on the communication ports, refer to the IBM PC Technical Reference Manual.
AssignAux initializes a specified text file variable to refer to a specified
communication port with a specified parameter byte. Port numbers 0 and 1
correspond to COM1 and COM2. The parameter byte is described in the
IBM PC Technical Reference Manual.
AuxOpen initializes the selected communication port and sets up the
function pointers according to the Mode field. Note that for output,
FlushFunc is set to the same address as InOutFunc, causing the text file
buffer to be flushed after each Write or Writeln.
AuxInput inputs up to BufSize characters from the selected port, and
AuxOutput outputs the contents of the buffer to the selected port.
AuxIgnore is used in those cases where no special action is required, such as
for Close and for Flush (when in input mode).
The following short program uses the AuxIn Out unit to write a string to
one of the communication ports. Through the AssignAux procedure, the
Coml file is associated with the COM1 port using 1200 baud, no parity, 1
stop bit, and 8 data bits:
program TestAux;
uses AuxlnOut;
var
Coml: Text;
begin
AssignAux(Coml,O,$83);
Rewrite (Coml) ;
Writeln(Coml,'Device Drivers are fun!');
Close(Coml);
end.
Exit Procedures
By installing an exit procedure, you can gain control over a program's
termination process. This is useful when you want to make sure specific
368
end.
On entry, the program saves the contents of ExitProc in ExitSave, and then
installs the MyExit exit procedure. After having been called as part of the
termination process and just before returning, MyExit re-installs the
previous exit procedure.
The termination routine in the runtime library keeps calling exit procedures
until ExitProc becomes nil. To. avoid infinite loops, ExitProc is set to nil
Chapter 26, Inside Turbo Pascal
369
before every call, so the next exit procedure is called only if the current exit
procedure assigns an address to ExitProc. If an error occurs in an exit
procedure, the exit procedure will not yet have assigned a new value to
ExitProc, since this is done just before it returns.
An exit procedure may learn the cause of termination by examining the
ExitCode integer variable and the ErrorAddrpointer variable.
In case of normal termination, ExitCode is zero and ErrorAddr is nil. In case
of termination through a call to Halt, ExitCode contains the value passed to
Halt and ErrorAddr is nil. Finally, in case of termination due to a runtime
error, ExitCode contains the error code and ErrorAddr contains the address
of the statement in error.
The last exit procedure (the one installed by the runtime library) closes the
Input and Output files, and restores the interrupt vectors that were captured
by Turbo Pascal. In addition, if ErrorAddr is not nil, it outputs a runtime
error message.
If you wish to present runtime error messages yourself, install an exit
procedure that examines ErrorAddr and outputs a message if it is not nil. In
addition, before returning, make sure to set ErrorAddrto nil, so that the
error is not reported again by other exit procedures.
Once the runtime library has called all exit procedures, it returns to DOS,
passing as a return code the value stored in ExitCode.
Automatic Optimizations
Turbo Pascal performs several different types of code optimizations,
ranging from constant folding and short-circuit Boolean expression
evaluation all the way up to smart linking. Here are some of the typesof
optimizations performed.
Constant Folding
If the operand(s) of an operator are constants of an ordinal type, Turbo
Pascal evaluates the expression at compile time. For example, X := 3 + 4 * 2
produces the exact same code as X:= 11.
Likewise, if the operand of an Abs, Sqr, Succ, Pred, Odd, Lo, Hi, or Swap
function call is a constant of an ordinal type, the function is evaluated at
compile time.
370
Constant Merging
Using the same string constant two or more times in a statement part
generates only one copy of the constant. For example, two or more
Write('Done') statements in the same statement part will reference the same
copy of the string constant 'Done'.
Short-Circuit Evaluation
Turbo Pascal implements short-circuit Boolean evaluation, which means
that evaluation of a Boolean expression stops as soon as the result of the
entire expression becomes evident. This guarantees minimum execution
time, and usually minimum code size. Short-circuit evaluation also makes
possible the evaluation of constructs that would not otherwise be legal; for
instance:
while (I<=Length (S)) and. (8 [I] <>' ') do Inc (I) i
while (P<>nil) and (pA.Value<>S) do P:=PA.Nexti
In both cases, the second test is not evaluated if the first test is False.
The opposite of short-circuit evaluation is complete evaluation, which is
selected through a {$B+} compiler directive. In this state, every operand of a
Boolean expression is guaranteed to be evaluated.
Order of Evaluation
As permitted by the Pascal standards, operands of an expression are
frequently evaluated differently from the left to right order in which they
are written. For example, the statement
I:=F(J) div G(J);
371
Range-Checking
Assignment of a constant to a variable and use of a constant as a value
parameter is range-checked at compile time; no runtime range-check code
is generated. For example, X: =999, where X is of type Byte, causes a
compile-time error.
Smart Linking
The linker automatically removes unused code on a per-procedure basis;
that is, procedures and functions that are part of a compilation but never
get called are removed in the .EXE file.
372
27
Turbo Pascal Reference Lookup
This chapter describes all the procedures and functions of Turbo Pascal 4.0.
For your convenience, they're arranged alphabetically. Here's a sample
layout so you can easily understand the format of the lookup; note that
only the relevant items are listed in each entry.
Sample procedure
Function
What it does
Declaration
Result type
Remarks
Restrictions
Things to be aware of
Differences
From 3.0
See also
Example
373
Abs function
Function
Declaration
Abs (x)
Result type
Remarks
Example
var
r: real;
i: integer;
begin
r := Abs(-2.3);
i := Abs (-157);
end.
{ 2.3 }
{ 157 }
Addr function
Function
Declaration
Addr (x)
Result type
pointer
Remarks
See also
Ptr
Example
var p: pointer;
begin
p
:= Addr (p) ;
end.
Append procedure
Function
374
Declaration
Append(var f: text)
Remarks
f is
Reset, Rewrite
Example
var f: text;
begin
Assign(f, 'TEST.TXT');
Rewrite (f) ;
Writeln(f, 'original text');
Close (f);
Append (f) ;
Writeln(f, 'appended text');
Close(f);
end.
Arc procedure
Graph
Function
Declaration
375
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
Radius: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
for Radius := 1 to 5 do
Arc(100, 100, 0, 90, Radius*10);
Readln;
CloseGraph;
end.
ArcTan function
Function
Declaration
ArcTan(x: real)
Result type
real
Remarks
Example
var r: real;
begin
r := ArcTan(Pi);
end.
376
Assign procedure
Function
Declaration
Remarks
f is a file variable of any file type, and name is a stringtype expression. All further operations on f will operate
on the external file with the file name name.
After a call to Assign, the association between f and the
external file continues to exist until another Assign is
done onf.
A file name consists of a path of zero or more directory
names separated by backslashes, followed by the actual
file name:
Drive:\DirName\ ... \DirName\FileName
Example
377
Assign(f, ");
Rewrite (f) ;
Writeln(f, 'standard output ... ');
Close(f);
{ Standard output }
end.
AssignCrt procedure
Crt
Function
Declaration
AssignCrt(var f: Text)
Remarks
AssignCrt works exactly like the Assign standard pro. cedure except that no file name is specified. Instead, the
text file is associated with the CRT.
This allows faster output (and input) than would
normally be possible using standard output (or input).
Example
uses Crt;
var f: text;
begin
Write('Output to screen or printer [S, P)? ');
if UpCase(ReadKey) = 'P' then
Assign(f, 'PRN')
{ Output to printer}
else
AssignCrt(f);
{ Output to screen, use
fast CRT write routines
Rewrite (f) ;
Writeln(f, 'Fast output via CRT routines ... ');
Close(f);
end.
Bar procedure
Graph
Function
Declaration
Remarks
.Restrictions
378
See also
Example
var
Gd, Gm : integer;
I, Width: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
Width := 10;
for I := 1 to 5 do
Bar(I*Width, 1*10, Succ(I)*Width, 200);
Readln;
CloseGraph;
end.
Bar3D procedure
Graph
Function
Draws a 3-D bar using the current fill style and color.
Declaration
Remarks
=
=
True;
False;
Restrictions
See also
379
Example
uses Graph;
var
Gd, Gm: integer;
yO, yl, y2, xl, x2: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm,
if GraphResult <>
Halt(l);
yO := 10;
yl := 60;
y2 := 110;
xl := 10;
x2 := 50;
Bar3D(xl, yO, x2,
Bar3D(xl, yl, x2,
Readln;
CloseGraph;
end.
");
grOk then
BlockRead procedure
Function
Declaration
Remarks
380
Differences
See also
BlockWrite
Example
program CopyFile;
{ Simple, fast file copy program with NO error-checking
var
FromF, ToF: file;
NumRead, NumWritten: word;
buf: array[1 .. 2048] of char;
begin
{ Open input file
Assign (FromF, ParamStr(1));
Reset (FromF, 1);
{ Record size = 1
Assign (ToF, ParamStr(2));
{ Open output file
Rewrite (ToF, 1);
{ Record size = 1
Writeln('Copying " FileSize(FromF), , bytes ... ');
repeat
BlockRead(FromF,buf,SizeOf(buf),NumRead);
BlockWrite(ToF,buf,NumRead,NumWritten);
until (NumRead = 0) or (NumWritten <> NumRead) ;
Close(FromF);
Close (ToF) ;
end.
}
}
}
}
BlockWrite procedure
Function
Declaration
Remarks
381
Differences
See also
BlockRead
Example
ChDir procedure
Function
Declaration
Remarks
382
See also
Example
begin
{$I-}
{ Get directory name from command line
ChDir(ParamStr(l));
if IOResult <> 0 then
Writeln('Cannot find directory');
end.
Chr function
Function
Declaration
Chr(x: byte)
Result type
char
Remarks
See also
Ord
Example
uses Printer;
begin
Writeln(Lst, Chr(12));
end.
Circle procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
Radius: integer;
begin
Gd := Detect;
383
for Radius := 1 to 5 do
Circle(100, 100, Radius*10);
Readln;
CloseGraph;
end.
ClearDevice procedure
Graph
Function
Declaration
ClearDevice
Remarks
Restrictions
See also
Example
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
Randomize;
repeat
LineTo(Random(200), Random(200));
until KeyPressed;
ClearDevice;
Readln;
CloseGraph;
end.
ClearViewPort procedure
Graph
Function
Declaration
ClearViewPort
384
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
Rectangle (19, 19, GetMaxX-19, GetMaxY-19);
SetViewPort(20, 20, GetMaxX-20, GetMaxY-20, ClipOn);
OutTextXY(O, 0, '<RETURN> clears viewport:');
Readln;
ClearViewPort;
OutTextXY(O, 0, '<RETURN> to quit:');
Readln;
CloseGraph;
end.
Close procedure
Function
Declaration
Close (f)
Remarks
f is
Example
var f: file;
begin
Assign(f, '\AUTOEXEC.BAT');
Reset(f, 1);
Writeln('File size = " FileSize(f));
Close(f);
end.
{ Open file }
{ Close file }
385
CloseGraph procedure
Graph
Function
Declaration
CloseGraph
Remarks
Restrictions
See also
InitGraph, RestoreCrtMode
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
ClrEol procedure
Crt
Function
Declaration
ClrEol
Remarks
386
ClrSer, Window
Example
uses Crt;
begin
TextBackground(LightGray);
ClrEol; {Changes cleared columns to LightGray background }
end.
ClrScr procedure.
Crt
Function
Declaration
ClrScr
Remarks
All character positions are set to blanks with the currently defined text attributes. Thus, if TextBackground is
not black, the entire screen becomes the background
color. This also applies to characters cleared by ClrEol,
InsLine, and DeiLine, as well as empty lines created by
scrolling.
This-procedure is window-relative:
Window(l,l,60,20);
ClrScr;
ClrEol, Window
Example
uses Crt;
begin
TextBackground(LightGray);
ClrScr;
{ Changes entire screen to LightGray background }
end.
Concat function
Function
Declaration
Result type
string
387
Remarks
Example
var s: string;
begin
s := Concat('ABC', 'DEF');
{ , ABCDEF' }
end.
Copy function
Function
Declaration
Copy(s:
Result type
string
Remarks
s is a string-type expression. index and count are integertype expressions. Copy returns a string containing count
characters starting with the indexth character in s. If
index is larger than the length of s, an empty string is
returned. If count specifies more characters than remain
starting at the indexth position, only the remainder of the
string is returned.
Example
var s: string;
begin
s := ' ABCDEF';
s := Copy(s, 2, 3)
{ 'BCD' }
end.
Cos function
Function
Declaration
Result type
real
Remarks
Example
var r: real;
begin
r :=Cos(Pi);
388
end.
CSeg function
Function
Declaration
CSeg
Result type
word
Remarks
See also
DSeg,Sseg
Dec procedure
Function
Decrements a variable.
Declaration
Remarks
See also
Example
var
IntVar: integer;
LongintVar: longint;
begin
Dec (IntVar);
Dec (LongintVar, 5);
end.
{ IntVar := IntVar - 1
LongintVar := LongintVar - 5
Delay procedure
Function
Declaration
Delay(ms: word)
Crt
389
Remarks
Delete procedure
Function
Declaration
Delete(var s: string;
index: integer; count: integer)
Remarks
s is a string-type variable. index and count are integertype expressions. Delete deletes count characters from s
starting at the indexth position. If index is larger than the
length of s, no characters are deleted. If count specifies
more characters than remain starting at the indexth
position, the remainder of the string is deleted.
See also
DelLine procedure
Crt
Function
Declaration
DelLine
Remarks
390
Insline, Window
DetectGraph procedure
Graph
Function
Declaration
Remarks
( Request autodetection
InitGraph, GraphResult
Example
uses Graph;
var
GraphDriver, GraphMode: integer;
begin
DetectGraph(GraphDriver, GraphMode);
if (GraphDriver = EGA) or
(GraphDriver = EGA64) then
begin
GraphDriver := CGA;
391
GraphMode := CGAHi;
end;
InitGraph(GraphDriver,GraphMode,");
if GraphResult <> grOk then
Halt(l);
Line(O, 0, GetMaxX, GetMaxY);
Readln;
CloseGraph;
end.
DiskFree function
Dos
Function
Declaration
DiskFree(Drive: word)
Result type
longint
Remarks
See also
DiskSize, GetDir
Example
uses Dos;
begin
Writeln(DiskFree(O) div 1024, , k-bytes ');
end.
DiskSize function
Dos
Function
Declaration
DiskSize(Drive: word)
Result type
longint
Remarks
See also
DiskFree, GetDir
392
Example
uses Dos;
begin
Writeln(DiskSize(O) div 1024, ' k-bytes ');
end.
Dispose procedure
Function
Declaration
Remarks
P is a pointer variable of any pointer type that was previously assigned by the New procedure or was assigned
a meaningful value by an assignment statement. Dispose
destroys the variable referenced by p and returns its
memory region to the heap. After a call to Dispose, the
value of p becomes undefined, and it is an error to
subsequently reference p".
Restrictions
See also
Release, FreeMem
Example
type
Str18 = string[18];
var
p: "Strl8;
begin
New(p);
p" := 'Now you see it ... ';
Dispose(p);
end.
DosExitCode function
Dos
Function
Declaration
DosExitCode
Result type
word
Remarks
393
DrawPolY'procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
Example
uses Graph;
const
Triangle: array[l .. 4] of PointType = ( (x:
(x:
(x:
(x:
50;
100;
150;
50;
y:
y:
y:
y:
100) ,
100) ,
150) ,
100)) ;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
394
{4}
DSeg function
Function
Declaration
DSeg
Result type
word
Remarks
See also
CSeg, Sseg
Ellipse procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Grn: integer;
begin
Gd := Detect;
InitGraph(Gd, Grn, ");
if GraphResult <> grOk then
Halt(l);
Ellipse(lOO,lOO,O,360,30,50);
Ellipse(lOO,lOO,O,180,50,30);
395
Readln;
CloseGraph;
end.
Declaration
Result type
boolean
Remarks
I,
Eoln
Example
var
f : text;
ch: char;
begin
{ Get file to read from command line }
Assign(f, ParamStr(l));
Reset(f);
while not Eof(f) do
begin
Read(f,ch);
Write (ch);
end;
end.
Declaration
Eof (f)
Result type
boolean
Remarks
I is a
396
Eoln function
Function
Declaration
Result type
boolean
Remarks
f,
end.
Eof
Erase procedure
Function
Declaration
Erase(f)
Remarks
397
Restrictions
See also
Rename
Example
var
f : file;
ch: char;
begin
{ Get file to delete from command line
Assign{f, ParamStr{l));
{$I-}
Reset{f);
{$I+}
Dos
Exec procedure
Function
Declaration
Remarks
398
(DosError = 8).
See also
Example
{$M $4000,0,0 }
{ 16K stack, no heap required or reserved }
uses Dos;
var
ProgramName, CmdLine: string;
begin
Write ('Program to Exec (include full path): ');
Readln(ProgramName);
Write('Command line to pass to " ProgramName, '. ');
Readln(CmdLine);
Writeln('About to Exec ... ');
Exec (ProgramName, CmdLine);
Writeln(' ... back from Exec');
{ Error? }
if DosError <> then
Writeln('Dos error #', DosError)
else
Writeln('Exec successful.',
'Child process exit code = "
'DosExitCode);
end.
Exit procedure
Function
Declaration
Exit
Remarks
See also
Halt
Example
uses Crt;
procedure WasteTime;
begin
repeat
if KeyPressed then Exit;
Write (' Xx') ;
399
until False;
end;
begin
WasteTirne;
end.
Exp function
Function
Declaration
Exp(x:
Result type
real
Remarks
See also
Ln
real)
FilePos function
Function
Declaration
FilePos (f)
Result type
longint
Remarks
Restrictions
Differences
See also
FileSize, Seek
FileSize function
Function
400
Declaration
FileSize (f)
Result type
longint
Remarks
Restrictions
Differences
See also
FilePos
Example
var
f: file of byte;
begin
{ Get file name from command line
Assign(f, ParamStr(l));
Reset (f) ;
Writeln('File size in bytes:' FileSize(f));
Close(f);
end.
FillChar procedure
Function
Declaration
Remarks
x is a variable reference of any type. count is an expression of type word. ch is an ordinal-type expression.
FillChar writes the value of ch into count contiguous
bytes of memory, starting at the first byte occupied by x.
No range-checking is performed, so be careful.
Whenever possible, use the SizeD! function to specify the
count parameter when using FiliChar on strings.
Remember to set the length byte after the fill.
See also
Move
401
Example
var s: string[80];
begin
( Set a string to all spaces
FillChar(s, SizeOf(s), ' 'I;
s[O] := #80;
end.
Graph
FillPoly procedure
Function
Declaration
Remarks
See also
Example
uses Graph;
const
Triangle: array[1 .. 3] of Point Type
((x:
50; y: 100),
var
Gd, Gm : integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, "~I;
if GraphResult <> grOk then
Halt (1);
402
Readln;
CloseGraph;
end.
FindFirst procedure
Dos
Function
Declaration
Remarks
FindNext
403
Example
uses Dos;
var
DirInfo: SearchRec;
begin
FindFirst('*.PAS', Archive, DirInfo);
while DosError = 0 do
begin
Writeln(DirInfo.Name);
FindNext(DirInfo);
end;
end.
Dos
FindNext procedure
Function
Declaration
FindNext(var
Remarks
See also
FindFirst
Example
s:
SearchRec)
FloodFil1 procedure
Graph
Function
Declaration
Remarks
404
Note that FloodFill stops after two blank lines have been
output. This can occur with a sparse fill pattern and a
small polygon. In the following program, the rectangle
is not completely filled:
program StopFill;
uses Graph;
var
Driver, Mode: integer;
begin
Driver := Detect;
InitGraph(Driver, Mode, 'c:\bgi');
if GraphResult <> grOk then
Halt (1) ;
SetFillStyle(LtSlashFill, GetMaxColor);
Rectangle (0, 0, 8, 20);
FloodFill(I, I, GetMaxColor);
Readln;
CloseGraph;
end.
See also
SetFillStyle, SetFillPattern
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(I);
SetColor(GetMaxColor);
Circle (50, 50, 20) i
FloodFill(50,50,GetMaxColor);
Readlni
CloseGraph;
end.
405
Flush procedure
Function
Declaration
Flush(var f: text)
Remarks
f is a text-file variable.
When a text file has been opened for output using
Rewrite or Append, a call to Flush will empty the file's
buffer. This guarantees that all characters written to the
file at that time have actually been written to the
external file. Flush has no effect on files opened for
input.
With {$I-}, IOResult will return a 0 if the operation was
successful; otherwise, it will return a nonzero error code.
Frac function
Function
Declaration
Result type
real
Remarks
See also
Int
Example
var r: real;
begin
r := Frac(123.456);
end.
{0.456}
FreeMem procedure
Function
Declaration
Remarks
406
See also
GetArcCoords procedure
Graph
Function
Declaration
Remarks
record
X, Y
Xstart, Ystart, Xend, Yend: integer;
end;
See also
Example
uses Graph;
var
Gd, Gm : integer;
ArcCoords : ArcCoordsType;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
407
Halt (1);
Arc(100,100,0,270,30);
GetArcCoords(ArcCoords);
with ArcCoords do
Line (Xstart, Ystart, Xend, Yend);
Readln;
CloseGraph;
end.
GetAspectRatio procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm : integer;
Xasp, Yasp : word;
XSideLength, YSideLength
integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
GetAspectRatio(Xasp, Yasp);
XSideLength := 20;
( Adjust Y length for aspect ratio
YSideLength := Round((Xasp/Yasp) * XSideLength);
408
GetBkColor function
Graph
Function
Declaration
GetBkColor
Result type
word
Remarks
See also
Example
Randomize;
Getpalette (Pal) ;
if Pal.Size <> 1 then
begin
{ Cycle through colors }
repeat
Color := Succ(GetBkColor);
if Color> Pal.Size-l then
Color := 0;
SetBkColor(Color);
LineTo(Random(GetMaxX), Random(GetMaxY));
until KeyPressed;
409
end
else
Line(O, 0, GetMaxX, GetMaxY);
Readln;
CloseGraph;
end.
Graph
GetColor function
Function
Declaration
GetColor
Result type
word
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd , Gm: integer;
Color: word;
Pal: PaletteType;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
Randomize;
GetPalette(Pal);
repeat
Color := Succ(GetColor);
if Color> Pal.Size-l then
Color := 0;
SetColor(Color);
LineTo(Random(GetMaxX), Random(GetMaxY));
until KeyPressed;
CloseGraph;
end.
410
GetDate procedure
Dos
Function
Declaration
Remarks
See also
GetDir procedure
Function
Declaration
Remarks
See also
GetFAttr procedure
Dos
Function
Declaration
Remarks
411
Directory = $10;
Archive = $20;
AnyFile = $3F;
f cannot be open.
See also
Example
uses Dos;
var
f: file;
attr: word;
begin
( Get file name from command line
Assign(f, ParamStr(1));
GetFAttr(f, attr);
Writeln(ParamStr(1));
if DosError <> 0 then
Writeln('Dos error code = " DosError)
else
begin
Write('Attribute =' attr, 'to:'to);
{ Determine file attribute type
using flags in Dos unit )
if attr and ReadOnly <> 0 then
Writeln('read only file');
if attr and Hidden <> 0 then
Writeln('hidden file');
if attr and SysFile <> 0 then
Writeln('system file');
if attr and VolumeID <> 0 then
Writeln('volume ID');
if attr and Directory <> 0 then
Writeln('directory name');
if attr and Archive <> 0 then
Writeln('archive (normal file)');
end; ( else )
end.
GetFillPattern procedure
Graph
Function
Declaration
412
Remarks
Restrictions
See also
SetFillPattern, GetFillSettings
GetFillSettings procedure
Graph
Function
Declaration
Remarks
record
Pattern: word;
Color: word;
end;
See also
Example
uses Graph;
var
Gd, Gm : integer;
Filllnfo: FillSettingsType;
begin
Gd := Detect;
InitGraph(Gd, Gm, "~I;
if GraphResult <> grOk then
Halt (1);
GetFillSettings(Filllnfo);
413
GetFTime procedure
Dos
Function
Declaration
Remarks
Restrictions
f must be open.
See also
Graph
GetGraphMode function
Function
Declaration
GetGraphMode
Result type
integer
Remarks
414
Graphics Graphics
Driver Modes
Column
Value x Row Palette
Pages
2
3
4
320x200
320x200
320x200
320x200
640x200
CO
Cl
C2
C3
2 color
1
1
1
1
1
MCGACO
MCGAC1
MCGAC2
MCGAC3
MCGAMed
MCGAHi
0
1
2
3
4
5
320x200
320x200
320x200
320x200
640x200
640x480
CO
C1
C2
C3
2 color
2 color
1
1
1
1
1
EGA
EGALo
EGAHi
0
1
640x200
640x350
16 color
16 color
4
2
EGA64
EGA64Lo
EGA64Hi
0
1
640x200
640x350
16 color
4 color
1
1
EGAMONO
EGAMonoHi
EGAMonoHi
3
3
640x350
640x350
2 color
2 color
1*
2**
HERC
HercMonoHi
720x348
2 color
ATT400
ATI400CO
ATT400C1
ATT400C2
ATT400C3
ATT400Med
ATT400Hi
0
2
3
4
5
320x200
320x200
320x200
320x200
640x200
640x400
CO
C1
C2
C3
2 color
2 color
1
1
1
1
1
1
VGA
VGALo
VGAMed
VGAHi
0
1
2
640x200
640x350
640x480
16 color
16 color
16 color
2
2
1
PC3270
PC3270Hi
720x350
2 color
CGA
MCGA
*
**
CGACO
CGACI
CGAC2
CGAC3
CGAHi
0
1
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
415
Mode
: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
OutText('<RETURN> to leave graphics:');
Readln;
RestoreCRTMode;
Writeln('Now in text mode');
Write('<RETURN> to enter graphics mode:');
Readln;
SetGraphMode(GetGraphMode);
OutTextXY(O, 0, 'Back in graphics mode');
OutTextXY(O, Text Height('H'), '<RETURN> to quit:');
Readln;
CloseGraph;
end.
GetImage procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
ImageSize, PutImage
Example
uses Graph;
var
Gd, Gm integer;
p
pointer;
word;
Size
begin
Gd := Detect;
416
GetIntVec procedure
Dos
Function
Declaration
Remarks
See also
SetIntVec
GetLineSettings procedure
Graph
Function
Declaration
Remarks
417
DashedLn = 3;
UserBitLn = 4;
{ Line widths }
NormWidth = 1;
ThickWidth = 3;
Restrictions
See also
SetLineStyle
Example
uses Graph;
var
Gd, Gm : integer;
OldStyle: LineSettingsType;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
GetMaxColor function
Graph
Function
Declaration
GetMaxColor : word;
Remarks
Restrictions
See also
SetColor
418
GetMaxX function
Graph
Function
Declaration
GetMaxX
Result type
integer
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
Rectangle(O,O,GetMaxX,GetMaxY);
Readln;
CloseGraph;
end.
GetMaxY function
Graph
Function
Declaration
GetMaxY
Result type
integer
Remarks
419
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
Rectangle(O,O,GetMaxX,GetMaxY);
Readln;
CloseGraph;
end.
GetMem procedure
Function
Declaration
Remarks
Restrictions
Differences
See also
New, FreeMem
420
GetModeRange procedure
Graph
Function
Declaration
GetModeRange(GraphDriver
: integer;
var LoMode, HiMode: integer);
Remarks
= 1.
If the value of GraphDriver is invalid, the return parameters are set to -1.
See also
GetPalette procedure
Graph
Function
Declaration
Remarks
421
Restrictions
See also
SetPalette, SetAllPalette
Example
uses Graph;
var
Gd, Gm : integer;
Color : word;
Palette: PaletteType;
begin
Gd := Detect;
InitGraph(Gd, Gm, "~I;
if GraphResult <> grOk then
Halt (1) ;
GetPalette(Palette);
if Palette. Size <> 1 then
for Color := to Pred(Palette.Size) do
begin
SetColor(Color);
Line(O, Color*5, 100, Color*5);
end
else
Line (0, 0, 100, 0);
Readln;
CloseGraph;
end.
GetPixel function
Graph
Function
Declaration
GetPixel(X,Y: integer)
Result type
word
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm
integer;
PixelColor: word;
begin
Gd := Detect;
InitGraph(Gd, Gm,
422
"~I;
GetTextSettings procedure
Graph
Function
Declaration
Remarks
0;
1;
2;
3;
4;
0;
1;
=
=
=
=
=
Left to right
Bottom to top
Restrictions
See also
Example
uses Graph;
var
Gd, Gm : integer;
OldStyle: TextSettingsType;
begin
Gd := Detect;
423
GetTime procedure
Dos
Function
Declaration
Remarks
See also
GetViewSettings procedure
Graph
Function
Declaration
Remarks
record
xl, yl, x2, y2: integer;
Clip: boolean;
end;
424
The points (xl, yl) and (x2, y2) are the dimensions of the
active viewport and are given in absolute screen
coordinates. Clip is a Boolean variable that controls
whether clipping is active.
Restrictions
See also
Set ViewPort
Example
uses Graph;
var
Gd, Gm : integer;
ViewPort: ViewPortType;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
GetViewSettings(ViewPort);
with ViewPort do
begin
Rectangle (0, 0, x2-xl, y2-yl);
if Clip then
Out Text ('Clipping is active.')
else
OutText('No clipping today.');
end;
Readln;
CloseGraph;
end.
GetX function
Graph
Function
Declaration
GetX
Result type
integer
Remarks
SetViewPort(O,O,GetMaxX,GetMaxY,True);
MoveTo(5,5);
SetViewPort(lO,lO,lOO,lOO,True);
MoveTo(5,5);
425
See also
Example
uses Graph;
var
Gd, Gm: integer;
X, Y: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
GetY function
Graph
Function
Declaration
GetY
Result type
integer
Remarks
SetViewPort(O,O,GetMaxX,GetMaxY,True);
MoveTo(5,5);
SetViewPort(lO,lO,lOO,lOO,True);
MoveTo(5,5);
426
See also
Example
uses Graph;
var
Gd, Gm: integer;
X, Y: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
OutText('Starting here. ');
X := GetX;
Y := GetY;
OutTextXY(20, 10, 'Now over here ... ');
OutTextXY(X, Y, 'Now back over here.');
Readln;
CloseGraph;
end.
GotoXYprocedure
Crt
Function
Declaration
GotoXY(X, Y: byte)
Remarks
and will move the cursor to the upper left corner of the
active window (absolute coordinates (1,10.
427
Restrictions
See also
GraphDefaults procedure
Graph
Function
Declaration
GraphDefaults;
Remarks
viewport
palette
draw and background colors
line style and line pattern
fill style, fill color, and fill pattern
active font, text style, text justification, and user char
size
Restrictions
See also
InitGraph
GraphErrorMsg function
Graph
Function
Declaration
GraphErrorMsg(ErrorCode: integer)
Result type
string
Remarks
See also
GraphResult
Example
uses Graph;
var
GraphDriver, GraphMode: integer;
ErrorCode: integer;
428
begin
GraphDriver := Detect;
InitGraph(GraphDriver, GraphMode, ");
ErrorCode := GraphResult;
if ErrorCode <> grOk then
begin
Writeln('Graphics error: " GraphErrorMsg(ErrorCode));
Readln;
Halt(l);
end;
Line(O, 0, GetMaxX, GetMaxY);
Readln;
CloseGraph;
end.
GraphResult function
Graph
Function
Declaration
GraphResult
Result type
integer
Remarks
429
Corresponding
Error Message String
0
-1
grOk
grNoInitGraph
-2
grNotDetected
-3
-4
-5
grFileNotFound
grInvalidDriver
grNoLoadMem
-6
grNoScanMem
grNoFloodMem
grFontNotFound
grNoFontMem
-7
-8
-9
-10
grInvalidMode
-11
-12
-13
-14
-15
grError
grIOerror
grIn valid Font
grInvalidFontNum
grInvalidDeviceNum
No error
(BGI) graphics not installed
(use InitGraph)
Graphics hardware not
detected
Device driver file not found
Invalid device driver file
Not enough memory to load
driver
Out of memory in scan fill
Out of memory in flood fill
Font file not found
Not enough memory to load
font
Invalid graphics mode for
selected driver
Graphics error
Graphics I/O error
Invalid font file
Invalid font number
Invalid device number
DetectGraph
ImageSize
InitGraph
Regis terB Gldriver
Regis terBGlfon t
SetAllPattern
SetFillStyle
SetGraphBufSize
SetGraphMode
SetLineStyle
SetPalette
SetTextJustify
SetTextStyle
SetViewPort
See also
GraphErrorMsg
Example
uses Graph;
var
ErrorCode: integer;
GrDriver, GrMode: integer;
430
begin
GrDriver := Detect;
InitGraph(GrDriver, GrMode, "~I;
ErrorCode := GraphResult;
if ErrorCode <> grOk then
begin
Writeln('Graphics error:');
Writeln(GraphErrorMsg(ErrorCode));
Writeln('Program aborted ... ');
Halt(l);
end;
Halt procedure
Function
Declaration
Remarks
Exit
See also
Hi function
Function
Declaration
Hi(x)
Result type
byte
431
Remarks
See also
Lo, Swap
Example
var w: word;
begin
w := Hi ($1234) ;
end;
{$12}
Crt
HighVideo procedure
Function
Declaration
HighVideo
Remarks
Differences
See also
Example
uses Crt;
begin
TextAttr := LightGray;
HighVideo;
end.
ImageSize function
Graph
Function
Declaration
Result type
word
Remarks
432
Restrictions
See also
GetImage, PutImage
Example
uses Graph;
var
Gd, Gm: integer;
P: pointer;
Size: word;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <>,grOk then
Halt (1) ;
Bar(O, 0, GetMaxX, GetMaxY);
Size := ImageSize(10,20,30,40);
GetMem(P, Size);
{ Allocate memory on heap}
GetImage(10,20,30,40,PA);
Readln;
ClearDevice;
PutImage(100, 100, pA , NormalPut);
Readln;
CloseGraph;
end.
Inc procedure
Function
Increments a variable.
Declaration
Remarks
See also
Dec, Pred
Example
var
IntVar: integer;
LongintVar: longint;
433
begin
Inc(IntVar);
Inc (LongintVar, 5);
end.
InitGraph procedure
{ IntVar := IntVar + 1
{ LongintVar := LongintVar + 5
Graph
Function
Declaration
Remarks
434
0
-1
grOk
grNolnitGraph
-2
grNotDetected
-3
-4
-5
grFileNotFound
grlnvalidDriver
grNoLoadMem
-6
grNoScanMem
grNoFloodMem
grFontNotFound
grNoFontMem
-7
-8
-9
-10
grlnvalidMode
-11
-12
-13
-14
-15
grError
grlOerror
grlnvalidFont
grlnvalidFontNum
grlnvalidDeviceNum
Corresponding
Error Message String
No error
(BGI) graphics not installed
(use InitGraph)
Graphics hardware not
detected
Device driver file not found
Invalid device driver file
Not enough memory to load
driver
Out of memory in scan fill
Out of memory in flood fill
Font file not found
Not enough memory to load
font
Invalid graphics mode for
selected driver
Graphics error
Graphics I/O error
Invalid font file
Invalid font number
Invalid device number
435
Restrictions
See also
Example
uses Graph;
var
grDriver: integer;
grMode
integer;
ErrCode : integer;
begin
grDriver := Detect;
InitGraph(grDriver,grMode,");
ErrCode := GraphResult;
if ErrCode = grOk then
begin {Do graphics }
Line(O, 0, GetMaxX, GetMaxY);
Readln;
CloseGraph;
end
else
Writeln('Graphics error:', GraphErrorMsg(ErrCode));
end.
Insert procedure
Function
Declaration
Remarks
See also
Example
var
s: string;
begin
s := 'Honest Lincoln';
Insert (' Abe " s, 8);
end.
436
Crt
InsLine procedure
Function
Declaration
InsLine
Remarks
All lines below the inserted line are moved down one
line, and the bottom line scrolls off the screen (using the
BIOS scroll routine).
All character positions are set to blanks with the currently defined text attributes. Thus, if TextBackground is
not black, the new line becomes the background color.
This procedure is window-relative:
Window(1,10,60,20);
InsLine;
DelLine, Window
Int function
Function
Declaration
Int(x: real)
Result type
real
Remarks
See also
Frac
Example
var r: real;
begin
r:= Int(123.456);
end.
{123.0}
Intr procedure
Function
Dos
437
Declaration
Remarks
record
case integer of
0: (AX,BX,CX,DX,BP,SI,DI,DS,ES,
Flags: word);
1: (AL, AH, BL, BH, CL, CH, DL, DH: byte);
end;
Differences
In 3.0, the Registers variable passed to Intr was a userdefined type. In 4.0, the Registers variable must be of
type Registers defined in the Dos unit.
See also
MsDos
IOResult function
Function
Declaration
IOResult
Result type
word
Remarks
438
Example
Keep procedure
FileSize(f))
Dos
Function
Declaration
Remarks
Restrictions
See also
DosExitCode
KeyPressed function
Crt
Function
Declaration
KeyPressed
439
Result type
boolean
Remarks
Differences
See also
ReadKey
Example
uses Crt;
begin
repeat
Write ('Xx');
until KeyPressed;
end.
Length function
Function
Declaration
Length(s: string)
Result type
integer
Remarks
Example
Line procedure
Graph
Function
Declaration
Remarks
440
MoveTo(lOO,lOO);
LineTo(200,200);
is equivalent to
Line(lOO,lOO,200,200);
MoveTo(200,200);
See also
Example
LineRel procedure
Graph
Function
Declaration
Remarks
441
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
MoveTo(I,2);
LineRel (100, 100);
Readln;
CloseGraph;
end.
LineTo procedure
Graph
Function
Declaration
LineTo(x, y: integer)
Remarks
is equivalent to
Line(IOO,IOO,200,200);
442
Restrictions
See also
Example
Randomize;
repeat
LineTo(Random(200),Random(200));
until KeyPressed;
Readln;
CloseGraph;
end.
Ln function
Function
Declaration
Ln(x: real)
Result type
real
Remarks
See Also
Exp
Lo function
Function
Declaration
Lo(x)
Result type
byte
Remarks
See also
Hi, Swap
443
Example
var w: word;
begin
w := Lo($1234);
end.
{$34}
LowVideo procedure
Crt
Function
Declaration
LowVideo
Remarks
Differences
See also
Example
uses Crt;
begin
TextAttr := White;
LowVideo;
end.
Mark procedure .
Function
Declaration
Mark(var p: pointer)
Remarks
Restrictions
See also
444
MaxAvail function
Function
Declaration
MaxAvail
Result type
longint
Remarks
Differences
In 3.0, the returned value was an integer that represented the size of the largest free block in paragraphs.
See also
MemAvail
Example
type
FriendRec = record
Name: string(30);
Age : byte;
end;
var
p: pointer;
begin
if MaxAvail < SizeOf(FriendRec) then
Writeln('Not enough memory')
else
begin
{ Allocate memory on heap
GetMem(p, SizeOf(FriendRec));
end;
end.
MemAvail function
Function
445
Declaration
MemAvail
Result type
longint
Remarks
Differences
See also
MaxAvail
Example
begin
Writeln(MemAvail, , bytes available');
Writeln('Largest block contains', MaxAvail, , bytes');
end.
MkDir procedure
Function
Creates a subdirectory.
Declaration
MkDir(s: string)
Remarks
See also
Example
begin
{$I-}
{ Get directory name from command line
MkDir(ParamStr(l));
if IOResult <> 0 then
Writeln('Cannot create directory')
else
Writeln('New directory created');
end.
446
Move procedure
Function
Declaration
Remarks
See also
FillChar
Example
var
a: array[1 .. 4] of chari
b: longinti
begin
Move (a, b, SizeOf(a))i
end.
MoveRel procedure
{ SizeOf = safety! }
Graph
Function
Declaration
Remarks
447
Restrictions
See also
Example
uses Graphi
var
Gd, Gm: integeri
begin
Gd := Detecti
InitGraph (Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) i
MoveTo(1,2)i
MoveRel(10,10);
{ Move to the point (11, 12) }
PutPixel(GetX, GetY, GetMaxColor)i
Readln;
CloseGraphi
end.
MoveTo procedure
Graph
Function
Declaration
MoveTo(x, y: integer)
Remarks
ClearDevice
ClearViewPort
Graph Defa ults
InitGraph
LineRel
LineTo
MoveRel
MoveTo
OutText
setGraphMode
Set ViewPort
See also
Example
uses Graphi
var
Gd, Gm: integeri
begin
Gd := Detect;
448
MsDos procedure
Dos
Function
Declaration
Remarks
Restrictions
Differences
See also
Intr
New procedure
Function
Declaration
Remarks
449
GetMem, Dispose
NormVideo procedure
Crt
Function
Declaration
NormVideo
Remarks
Differences
See also
N oSound procedure
Crt
Function
Declaration
NoSound
Remarks
See also
Sound
Odd function
Function
Declaration
Result type
boolean
450
Remarks
Ofs function
Function
Declaration
Ofs (x)
Result type
word
Remarks
See also
Seg, Addr
Ord function
Function
Declaration
Ord(x)
Result type
longint
Remarks
See also
Chr
OutText procedure
Graph
Function
Declaration
OutText(TextString: string)
Remarks
451
{ #l }
MoveTo (0, 0);
SetTextStyle(DefaultFont, HorizDir, 1);
SetTextJustify(LeftText, TopText);
Out Text (' ABC');
{ CharSize = 1 }
{ CP is updated
}
OutText('DEF');
CP is updated
)
{ #2 )
MoveTo(lOO, 50);
SetTextStyle(DefaultFont, HorizDir, 1);
SetTextJustify(RightText, TopText);
OutText('ABC');
( CharSize = 1 )
{ CP is updated
}
CP is updated
)
452
{ #3 }
MoveTo(100, 100);
SetTextStyle(DefaultFont, VertDir, 1);
SetTextJustify(LeftText, TopText);
OutText (' ABC');
OutText('DEF');
Readln;
CloseGraph;
end.
{ CharSize = 1 }
CP is NOT updated }
CP is NOT updated }
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
OutTextXY procedure
Function
Graph
453
Declaration
Remarks
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
MoveTo(O, 0);
OutText('Inefficient');
Readln;
OutTextXY(GetX, GetY, 'Also inefficient');
Readln;
ClearDevice;
{ Replaces above }
OutTextXY(O, 0, 'Perfect!');
Readln;
CloseGraph;
end.
454
PackTime procedure
Dos
Function
Converts a DateTime record into a 4-byte, packed dateand-time longint used by SetFTime.
Declaration
Remarks
ParamCount function
Function
Returns the number of parameters passed to the program on the command line.
Declaration
ParamCount
Result type
word
Remarks
See also
ParamStr
Example
begin
if ParamCount < 1 then
Writeln('No parameters on command line'}
else
Writeln(ParamCount, , parameter(s}'};
end.
ParamStr function
Function
Declaration
ParamStr(index}
Result type
string
455
Remarks
See also
ParamCount
Example
var i: word;
begin
for i := 1 to PararnCount do
Writeln(PararnStr(i));
end.
Pi function
Function
Declaration
Pi
Result type
real
Remarks
Differences
PieSlice procedure
Graph
Function
Declaration
Remarks
Restrictions
456
See also
Example
uses Graph;
const
Radius = 30;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
PieSlice(100, 100, 0, 270, Radius);
Readln;
CloseGraph;
end.
Pos function.
Function
Declaration
Pos(substr, s: string)
Result type
byte
Remarks
Example
var s: string;
begin
s:='
123.5';
{ Convert spaces to zeroes
while Post' " s) > 0 do
s[Pos(' " s)] := '0';
end.
Pred function
Function
Declaration
Pred(x)
Result type
457
Remarks
See also
Ptr function
Function
Declaration
Result type
pointer
Remarks
.See also
Example
Addr
var p: Abyte;
begin
p := Ptr($40, $49);
Writeln('Current video mode is " pAl;
end.
Graph
Putlmage procedure
Function
Declaration
Remarks
458
= 0;
= 1;
= 2;
= 3;
= 4;
{
{
{
{
{
MOV
XOR
OR
AND
NOT
}
}
}
}
}
begin
Driver := Detect;
InitGraph(Driver, Mode, ");
if GraphResult < a then
Halt(l);
SetViewPort(O, 0, GetMaxX, GetMaxY, clipon);
GetMern(p, IrnageSize (0, 0, 99, 49));
PieSlice (50, 25, 0, 360, 45);
GetImage (0, 0, 99, 49, pA);
{ Width = 100, height = 50 }
459
ClearDevice;
PutImage(GetMaxX - 99, 0,
pA, NormalPut);
PutImage(GetMaxX - 98, 0,
pA, NormalPut);
PutImage(-l, 0,
pA, NormalPut);
PutImage (0, -1,
pA, NormalPut);
Put Image (0, GetMaxY - 30,
pA, NormalPut);
Readln;
CloseGraph;
end.
See also
GetImage, ImageSize
Example
uses Graph;
var
Gd, Gm: integer;
P: pointer;
Size: word;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(1);
460
PutPixel procedure
Graph
Function
Declaration
Remarks
Restrictions
See also
Example
{Plot "stars" }
Random function
Function
Declaration
Result type
Remarks
461
Randomize
Example
uses Crt;
begin
Randomize;
repeat
( Write text in random colors
TextAttr := Random(256);
Write (' !') ;
until KeyPressed;
end.
Randomize procedure
Function
Declaration
Randomize
Remarks
See also
Random
Declaration
Remarks
462
463
Read with a type string variable does not skip to the next
line after reading. For this reason, you cannot use
successive Read calls to read a sequence of strings, since
you will never get past the first line; after the first Read,
each subsequent Read will see the end-of-line marker
and return a zero-length string. Instead, use multiple
Readln calls to read successive string values.
Differences
See Appendix A.
See also
Readln, ReadKey
Declaration
Remarks
Restrictions
See also
Write
ReadKey function
Crt
Function
Declaration
ReadKey
Result type
char
Remarks
464
KeyPressed
Readln procedure
Function
Declaration
Remarks
465
See also
Read
Graph
Rectangle procedure
Function
Declaration
Remarks
(xl, yl) define the upper left corner of the rectangle, and
(x2, y2) define the lower right corner (0 <= xl < x2
See also
Example
466
RegisterBGIdriver function
Graph
Function
Declaration
Remarks
InitGraph:
program LoadDriv;
uses Graph;
var
Driver, Mode: integer;
DriverF: file;
DriverP: pointer;
begin
{ Open driver file, read into memory, register it }
Assign (DriverF, 'CGA.BGI');
Reset (DriverF, 1);
GetMem(DriverP, FileSize(DriverF));
BlockRead(DriverF, DriverP A , FileSlze(DriverF));
if RegisterBGldriver(DriverP) < 0 then
begin
Writeln('Error registering driver: "
GraphErrorMsg(GraphResult));
Halt (1) ;
end;
{ Init graphics
Driver := CGA;
Mode := CGAHi;
467
Restrictions
See also
InitGraph
RegisterBGlfont function
Graph
Function
Declaration
RegisterBGlfont(font: pointer)
468
integer;
Remarks
Comments
-11
grError
-13
grInvalidFont
-14
grInvalidFontNum
begin
{ Open font file, read into memory, register it )
Assign (FontF, 'TRIP.CHR');
Reset (FontF, 1);
GetMem(FontP, FileSize(FontF));
BlockRead(FontF, Fontp A , FileSize(FontF));
if RegisterBGlfont(FontP) < 0 then
469
begin
Writeln('Error registering font: "
GraphErrorMsg(GraphResult));
Halt(l);
end;
{ Init graphics
Driver := Detect;
InitGraph(Driver, Mode, , .. \');
if GraphResult < 0 then
Halt (1) ;
Readln;
{ Select registered font
Set Text Style (TriplexFont, HorizDir, 4);
OutText('Triplex loaded by user program');
MoveTo(O, TextHeight('a'));
Readln;
( Select font that must be loaded from disk
Set Text Style (SansSerifFont, HorizDir, 4);
OutText('Your disk should be spinning ... ');
MoveTo(O, GetY + TextHeight('a'));
Readln;
{ Re-select registered font (already in memory)
SetTextStyle(TriplexFont, HorizDir, 4);
OutText('Back to Triplex');
Readln;
CloseGraph;
end.
program. Then Graph will not load and unload the fonts
each time a call to SetTextStyle is made.
Second, you may wish to incorporate the font files
directly into your .EXE file. This way, the font files that
your program needs will be built-in, and only the .EXE
and driver files will be needed in order to run. The
process for incorporating a font file into your .EXE is
straightforward:
1. Run BINOBJ on the font file(s).
2. Link the resulting .OBJ file(s) into your program.
3. Register the linked-in font file(s) before calling
InitGraph.
For a detailed explanation and example of the
preceding, refer to the comments at the top of the
GRLINK.PAS example program on Disk 3. Documentation on the BINOBJ utility is contained in a file named
BINOBJ.DOC on Disk 2.
Note that the default (8x8 bit-mapped) font is built into
GRAPH.TPU, and thus is always in memory. Once a
stroked font has been loaded, your program can
alternate between the default font and the stroked font
without having to reload either one of them.
It is also possible to register driver files; refer to the
description of RegisterBGldriver.
See also
SetTextStyle
Release procedure
Function
Declaration
Release(var p: pointer)
Remarks
Restrictions
471
Rename procedure
Function
Declaration
Remarks
f is a file variable of any file type. newname is a stringtype expression. The external file associated with f is
renamed to newname. Further operations on f will
operate on the external file with the new name.
With {$I-}, IOResult will return 0 if the operation was
successful; otherwise, it will return a nonzero error code.
Restrictions
See also
Erase
Reset procedure
Function
Declaration
Remarks
472
See also
Example
begin
if FileExists(PararnStr(l)) then { Get file name from command
line }
Writeln('File exists')
else
Writeln('File not found');
end.
RestoreCrtMode procedure
Graph
Function
Declaration
RestoreCrtMode
Remarks
Restrictions
See also
473
Example
uses Graph;
var
Gd, Gm: integer;
Mode : integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
OutText('<RETURN> to leave graphics:');
Readln;
RestoreCRTMode;
Writeln('Now in text mode');
Write('<RETURN> to enter graphics mode:');
Readln;
SetGraphMode(GetGraphMode);
OutTextXY(O, 0, 'Back in graphics mode');
OutTextXY(O, TextHeight('H'), '<RETURN> to quit:');
Readln;
CloseGraph;
end.
Rewrite procedure
Function
Declaration
Remarks
1is a file variable of any file type, which must have been
associated with an external file using Assign. recsize is an
. optional expression of type word, which can only be
specified if 1is an untyped file.
If 1 is a text file,
1 becomes
See. also
Example
var f: text;
begin
Assign(f, 'NEWFILE.$$$');
Rewrite (f) ;
Writeln(f,'Just created file with this text in it ... ');
Close(f);
end.
RmDir procedure
Function
Declaration
Remarks
See also
Example
begin
{$I-}
{ Get directory name from command line
RmDir(ParamStr(l));
if IOResult <> 0 then
Writeln('Cannot remove directory')
else
Writeln('directory removed');
end.
475
Round function
Function
Declaration
Result type
longint
Remarks
Differences
See also
Trunc,Int
Seek procedure
Function
Declaration
Seek(f; n: longint)
Remarks
Restrictions
Differences
See also
FilePos
476
SeekEof function
Function
Declaration
Result type
boolean
Remarks
See also
Eof, SeekEoln
SeekEoln function
Function
Declaration
Result type
boolean
Remarks
See also
Eoln, SeekEof
Seg function
Function
Declaration
Seg(x)
Result type
word
477
Remarks
See also
Dis, Addr
SetActivePage procedure
Graph
Function
Declaration
SetActivePage(Page: word)
Remarks
Restrictions
See also
SetVisualPage
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
if (Gd=HercMono) or (Gd=EGA) or
(Gd=EGA64) or (Gd=VGA) then
begin
SetVisualPage(O)i
SetActivePage(l)i
Rectangle (10, 20, 30, 40);
SetVisualPage(l)i
end
else
OutText('No paging supported.')i
Readln;
CloseGraph;
478
end.
SetAIIPalette procedure
Graph
Function
Declaration
SetAllPalette(var Palette)
Remarks
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
= 10;
= 11;
= 12;
= 13;
= 14;
= 15;
= 15;
479
type
PaletteType = record
Size: byte;
Colors: array[O ... MaxColors] of shortint;
end;
Restrictions
See also
Example
uses Graph;
var
Gd, Gm : integer;
Palette: PaletteType;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Balt(1);
Line(O, 0, GetMaxX, GetMaxY);
with Palette do
begin
Size
:= 4;
Colors [0] := 5;
Colors [1] := 3;
Colors [2] := 1;
Colors [3] := 2;
SetAllPalette(Palette);
end;
Readln;
CloseGraph;
end.
SetBkColor procedure
Graph
Function
Declaration
SetBkColor(Color: word)
Remarks
480
See also
Example
GetPalette(Palette);
repeat
if Palette.Size <> 1 then
SetBkColor(Random(Palette.Size));
LineTo(Random(GetMaxX),Random(GetMaxY));
until KeyPressed;
CloseGraph;
end.
SetColor procedure
Graph
Function
Declaration
SetColor(Color: word)
Remarks
Restrictions
See also
481
Example
SetDate procedure
Dos
Function
Declaration
Remarks
Valid parameter ranges are Year 1980 .. 2099, Month 1.. 12,
and Day 1..31. If the date is invalid, the request is
ignored.
See also
SetFAttr procedure
Dos
Function
Declaration
Remarks
482
Archive
AnyFile
= $20;
=
$3F;
f cannot be open.
See also
Example
uses Dos;
var
f: file;
begin
Assign(f, 'C:\AUTOEXEC.BAT');
SetFAttr(f, Hidden);
Readln;
SetFAttr(f, Archive);
end.
SetFillPattern procedure
{Uh-oh}
{ Whew!}
Graph
Function
Declaration
Remarks
Sets the pattern and color for all filling done by FillPoly,
FloodFill, Bar, Bar3D, and PieSlice to the bit pattern
specified in Pattern and the color specified by Color. If
invalid input is passed to SetFillPattern, GraphResult will
return a value of -11 (grError), and the current fill
settings will be unchanged. FillPatternType is predefined
as follows:
type
FillPatternType
array[1 .. 8] of byte;
483
Binary
Hex
10101010
01010101
10101010
01010101
10101010
01010101
10101010
01010101
$AA
$55
$AA
$55
$AA
$55
$AA
$55
=
=
=
(1st byte)
(2nd byte)
(3rd byte)
(4th byte)
(5th byte)
(6th byte)
(7th byte)
(8th byte)
See also
GraphResult
Example
uses Graph;
const
Gray50: FillPatternType
($AA,$55,$AA,$55,
$AA,$55,$AA,$55) ;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
SetFillPattern(Gray50, White);
Bar(O, 0, 100, 100);
{ Draw a bar in a 50% gray scale}
Readln;
CloseGraph;
end.
SetFillStyle procedure
Graph
Function
Declaration
484
Remarks
Sets the pattern and color for all filling done by FillPoly,
Bar, Bar3D, and Pieslice. A variety of fill patterns are
available. The default pattern is solid, and the default
color is the maximum color in the palette. If invalid
input is passed to setFillstyle, GraphResult will return a
value of -11 (grError), and the current fill settings will be
unchanged. The following constants are defined:
const
{ Fill patterns
EmptyFil1
SolidFill
LineFill
LtSlashFill
SlashFill
BkSlashFill
LtBkSlashFill
HatchFill
XHatchFill
InterleaveFill
WideDotFill
CloseDotFill
for Get/SetFillStyle: }
{Fills area in background color
= 1;
{Fills area in solid fill color }
{ --- fill }
= 2;
= 3;
{ 11/ fill }
= 4;
III fill with thick lines}
= 5;
\\\ fill with thick lines}
= 6;
{ \ \ \ fill }
{ Light hatch fill }
= 7;
= 8;
Heavy cross hatch fill }
= 9;
Interleaving line fill }
{ Widely spaced dot fill }
= 10;
{ Closely spaced dot fill }
= 11;
= 0;
Restrictions
See also
Example
SetFiIIStyle(SolidFill,O);
Bar(x1, y1, x2, y2);
SetFiIIStyle(XHatchFill,l);
Bar(x1, y1, x2, y2);
SetFTime procedure
Dos
Function
Declaration
Remarks
Restrictions
f must be open.
485
See also
SetGraphBufSize procedure
Graph
Function
Allows you to change the size of the buffer used for scan
and flood fills.
Declaration
SetGraphBufSize(BufSize: word);
Remarks
Restrictions
See also
FloodFill, FillPoly
SetGraphMode procedure
Graph
Function
Declaration
SetGraphMode(Mode: integer)
Remarks
-10 (grlnvalidMode).
486
Column
Value x Row
Palette
Pages
CGA
CGACO
CGAC1
CGAC2
CGAC3
CGAHi
0
1
2
3
4
320x200
320x200
320x200
320x200
640x200
CO
C1
C2
C3
2 color
1
1
1
1
1
MCGA
MCGACO
MCGAC1
MCGAC2
MCGAC3
MCGAMed
MCGAHi
0
1
2
3
4
5
320x200
320x200
320x200
320x200
640x200
640x480
CO
C1
C2
C3
2 color
2 color
1
1
1
1
1
1
EGA
EGALo
EGAHi
0
1
640x200
640x3S0
16 color
16 color
4
2
EGA64
EGA64Lo
EGA64Hi
0
1
640x200
640x3S0
16 color
4 color
1
1
EGAMONO
EGAMonoHi
EGAMonoHi
3
3
640x3S0
640x3S0
2 color
2 color
1*
2**
HERC
HercMonoHi
720x348
2 color
ATI400
ATI400CO
ATT400C1
ATI400C2
ATT400C3
ATI400Med
ATI400Hi
0
1
2
3
4
5
320x200
320x200
320x200
320x200
640x200
640x400
CO
C1
C2
C3
2 color
2 color
1
1
1
1
1
1
VGA
VGALo
VGAMed
VGAHi
0
1
2
640x200
640x3S0
640x480
16 color
16 color
16 color
2
2
1
PC3270
PC3270Hi
720x3S0
2 color
*
**
Restrictions
See also
487
Example
uses Graph;
var
GraphDriver:
GraphMode
LowMode
HighMode
integer;
integer;
integer;
integer;
begin
GraphDriver := Detect;
InitGraph(GraphDriver, GraphMode, ");
if GraphResult <> grOk then
Halt (1);
GetModeRange(GraphDriver, LowMode, HighMode);
SetGraphMode(LowMode);
( Select low-resolution mode
Line(O, 0, GetMaxX, GetMaxY);
Readln;
CloseGraph;
end.
SetlntVec procedure
Dos
Function
Declaration
Remarks
SetIntVec($1B,Int1BSave);
See also
GetIntVec
SetLineStyle procedure
Function
488
Graph
Declaration
Remarks
0;
1;
= 2;
= 3;
= 4;
= 1;
= 3;
=
{ NormWidth }
1010101010101010
1010101010101010
1010101010101010
{ ThickWidth )
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
xl, y1, x2, y2: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
xl .- 10;
y1 .- 10;
x2 .- 200;
y2 .- 150;
SetLineStyle(DottedLn, 0, NormWidth);
Rectangle (xl, y1, x2, y2);
489
SetPalette procedure
Graph
Function
Declaration
Remarks
490
=
=
=
=
=
=
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
11;
12;
13;
14;
15;
Restrictions
See also
Example
end;
Randomize;
repeat
SetPalette(Random(Palette.Size),Random(Palette.Size));
until KeyPressed;
end
else
Line (0, 0, 100, 0);
Readln;
CloseGraph;
end.
SetTextBuf .procedure
Function
Declaration
Remarks
491
Differences
Example
var
f : text;
ch : char;
buf: array[1 .. 10240] of char;
{ 10K buffer }
begin
{ Get file to read from command line
Assign(f, ParamStr(1));
{ Bigger buffer for faster reads
SetTextBuf(f, buf);
Reset(f);
{ Dump text file onto screen }
while not Eof(f) do
begin
Read(f, ch);
Write (ch);
end;
end.
492
Graph
SetTextJustify procedure
Function
Declaration
Remarks
justification
= 0;
= 1;
= 2;
Restrictions
See also
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(l);
{ Center text onscreen }
493
SetTextJustify(CenterText, CenterText);
OutTextXY (Succ (GetMaxX)
div 2, Succ(GetMaxY)
div 2, 'Easily Centered');
Readln;
CloseGraph;
end.
SetTextStyle procedure
Graph
Function
Sets the current text font, style, and character magnification factor.
Declaration
Remarks
494
-8
-9
-11
-12
-13
-14
= 0;
= 1;
Left to right
Bottom to top
Restrictions
See also
Example
uses Graph;
var
Gd, Gm : integer;
Y, Size: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
Y := 0;
for Size := 1 to 4 do
begin
SetTextStyle(DefaultFont, HorizDir, Size);
OutTextXY(O, Y, 'Size = , + Chr(Size+48));
Inc(Y, TextHeight('H') + 1);
end;
Readln;
CloseGraph;
end.
495
SetTime procedure
Dos
Function
Declaration
Remarks
See also
SetUserCharSize procedure
Graph
Function
Declaration
Remarks
496
OutText('Short ');
SetUserCharSize(3, 1, 1, 1);
SetTextStyle(TriplexFont, Horizdir, UserCharSize);
OutText ('Wide');
Readln;
CloseGraph;
end.
See also
SetViewPort procedure
Graph
Function
Declaration
Remarks
(xl, y1) define the upper left corner of the viewport, and
(x2, y2) define the lower right corner (0 <= xl < x2 and
497
(GetMaxX,O)
(0,0)
D
(O,GetMaxY)
(GetMaxX,GetMaxY)
See also
Example
uses Graph;
var
Gd, Gm: integer;
498
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
if (Gd = HercMono)
or (Gd = EGA) or (Gd = EGA64) or (Gd
begin
SetVisualPage(O);
SetActivePage(I);
Rectangle (10, 20, 30, 40);
SetVisualPage(I);
end
else
OutText('No paging supported.');
Readln;
CloseGraph;
end.
SetVisualPage procedure
Function
Declaration
SetVisualPage(Page: word)
Remarks
VGA) then
Graph
See also
SetActivePage
Example
uses Graph;
var
Gd, Gm: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1) ;
if (Gd = HercMono)
499
VGA) then
Sin function
Function
Declaration
Sin(x: real)
Result type
real
Remarks
Example
var
r: real;
begin
r := Sin(Pi);
end.
SizeOf function
Function
Declaration
SizeOf (x)
Result type
word
Remarks
500
Example
type
CustRec = record
Name
Phone
end;
var
p: "CustRec;
string[30];
string[14];
begin
GetMem(p, SizeOf(CustRec));
end.
Sound procedure
Crt
Function
Declaration
Sound(Hz: word)
Remarks
See also
NoSound
Example
uses Crt;
begin
Sound(220) ;
Delay(200);
NoSound;
end.
{ Beep }
{ Pause }
{ Relief! }
SPtr function
Function
Declaration
SPtr
Result type
word
Remarks
See also
Sseg
501
Sqr function
Function
Declaration
Sqr(x)
Result type
Remarks
Sqrt function
Function
Declaration
Sqrt(x: real)
Result type
real
Remarks
SSeg function
Function
Declaration
SSeg
Result type
word
Remarks
See also
Str procedure
Function
Declaration
Remarks
502
Val, Write
Example
begin
Writeln(IntToStr(-5322));
end.
Succ function
Function
Declaration
Succ (x)
Result type
Remarks
See also
Pred, Inc
Swap function
Function
Declaration
Swap (x)
Result type
Remarks
See also
Hi, Lo
Example
var
x: word;
503
begin
x := Swap($1234);
end.
($3412}
TextBackground procedure
Crt
Function
Declaration
TextBackground(Co1or: byte);
Remarks
Color is an integer expression in the range 0.. 7, corresponding to one of the first eight color constants:
const
( Foreground and background color constants
= 0;
Black
Blue
= 1;
Green
= 2;
Cyan
= 3;
Red
= 4;
Magenta
= 5;
Brown
= 6;
LightGray = 7;
TextColor procedure
Crt
Function
Declaration
TextColor(Color:
Remarks
Color is an integer expression in the range 0.. 15, corresponding to one of the color constants defined in Crt:
byte)
const
{ Foreground and background color constants
= 0;
Black
= 1;
Blue
504
Green
Cyan
Red
Magenta
Brown
LightGray
DarkGray
LightBlue
LightGreen
LightCyan
LightRed
LightMagenta
Yellow
White
= 2;
= 3;
= 4;
= 5;
= 6;
= 7;
=
8;
= 9;
= 10;
= 11;
= 12;
= 13;
= 14;
= 15;
See also
Example
TextColor(Green);
TextColor(LightRedtBlink) ;
TextColor(14);
TextHeight function
Graph
Function
Declaration
TextHeight(TextString: string)
Result type
word
Remarks
505
See also
Example
uses Graph;
var
Gd, Gm : integer;
Y, Size: integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt (1);
Y := 0;
for Size := 1 to 5 do
begin
SetTextStyle(DefaultFont, HorizDir, Size);
OutTextXY(O, Y, 'Turbo Graphics');
Inc(Y, TextHeight('Turbo Graphics'));
end;
Readln;
CloseGraph;
end.
TextMode procedure
Function
. Declaration
Remarks
506
Crt
BW80
2;
Mono
7;
1;
C040
3;
C080
Font8x8 = 256;
C40 = C040;
C80 = C080;
}
}
}
}
}
}
}
TextMode(Lo(LastMode) + Font8x8)
will keep the video mode the same, but reset the display
into 43 or 50 lines.
If your system is in 43- or 50-line mode when you load a
Turbo Pascal program, the mode will be preserved by
the Crt startup code, and. the window variable that
keeps track of the maximum number of lines on the
screen (WindMax) will be initialized correctly.
507
var
OrigMode: integer;
begin
OrigMode := LastMode;
TextMode(OrigMode);
end.
See also
RestoreCrt
TextWidth function
Graph
Function
Declaration
TextWidth(TextString: string)
Result type
word
Remarks
See also
Example
uses Graph;
var
Gd, Grn: integer;
508
Row
Title
Size
integer;
string;
integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, ");
if GraphResult <> grOk then
Halt(I);
Row := 0;
Title := 'Turbo Graphics';
Size := 1;
while TextWidth(Title) < GetMaxX do
begin
OutTextXY(O, Row, Title);
Inc (Row, TextHeight('M'));
Inc (Size) ;
SetTextStyle(DefaultFont, HorizDir, Size);
end;
Readln;
CloseGraph;
end.
Trunc function
Function
Declaration
Trunc(x: real)
Result type
longint
Remarks
Restrictions
Differences
See also
Round,Int
Truncate procedure
Function
Declaration
Truncate (f)
509
Remarks
Restrictions
See also
Seek, Reset
Dos
UnpackTime procedure
Function
Declaration
Remarks
record
Year, Month, Day, Hour,
Min, Sec: word
end;
UpCase function
Function
Declaration
UpCase(ch: char)
Result type
char
Remarks
Val procedure
Function
510
Declaration
Remarks
s is a string-type expression. v is an integer-type or realtype variable. NumType is any numeric type. code is a
variable of type integer. s must be a sequence of
characters that form a signed whole number according
to the syntax shown in the section "Numbers" in
Chapter 13. Val converts s to its numeric representation
and stores the result in v. If the string is somehow
invalid, the index of the offending character is stored in
code; otherwise, code is set to zero.
The standard procedure Val, which converts a string's
contents to a numeric variable, performs range-checking
differently depending on the state of {$R} and the type
of the parameter V:
Val(s: string; var V; var Code: integer);
511
See also
Str
Example
WhereX function
Crt
Function
Declaration
WhereX
Result type
byte
See also
WhereY function
Crt
Function
Declaration
WhereY
Result type
byte
See also
Window procedure
Crt
Function
Declaration
Remarks
512
Example
uses Crt;
var
x, y: byte;
begin
{ Clear screen }
TextBackground(Black);
ClrScr;
repeat
{ Draw random windows
x := Succ(Random(80));
y := Succ(Random(25));
Window (x, y, x + Random(IO), y + Random(8));
TextBackground(Random(16));
{ In random colors
ClrScr;
until KeyPressed;
end.
Declaration
Remarks
I,
513
[ I -]
<digit>
<decimals>
[+ I -]
<exponent>
[<blanks> ]
[- ]
<digits>
[ . <decimals> ]
515
Differences
See Appendix A
See also
Writeln
Declaration
Remarks
Writeln
Writeln procedure
Function
Executes the Write procedure, then outputs an end-ofline marker to the file.
Declaration
l~riteln(
Remarks
Differences
See Appendix A.
See also
Write
517
518
519
520
A
Differences Between Version 3.0
and 4.0
This appendix lists the differences between version 3.0 of Turbo Pascal and
version 4.0. Despite the many changes to the compiler and the introduction
of many powerful features, version 4.0 is highly compatible with previous
releases. As you will see by reading through this section, most of the
differences are small, resulting from the introduction of some of the new
features.
Where appropriate, we've made suggestions how to make any conversion
necessary. Also consult Chapter 8 for more information on converting from
version 3.0 to version 4.0.
Program Declarations
In version 3.0, the program name (the identifier given in the program
statement) could be the same as another identifier in the program. In
version 4.0, the program name must be unique-there cannot be a label,
constant, data type, variable, procedure, or function, unit with the same
name. That's because you can now refer to any identifier declared in your
program as progname.identifier. This lets you resolve ambiguities in case you
use a unit that also declares something named identifier. In that situation,
you can refer to the unit's item as unitname.identifier (see Chapter 4).
In version 3.0, all Pascal items (constants, data types, variables, procedures,
functions) had to be compiled at the same time and were located either in
your source file or in an include file. In version 4.0, you can collect a group
of constants, data types, variables, procedures and functions, compile them.
Appendix A, Differences Between Version 3.0 and 4.0
521
separately into a unit, and then use them in a series of programs. (See
Chapter 4 for more details on units.)
In version 3.0, you could not have a program with more than 64K of code,
and the compiler produced a .COM file. To get around this, you had to use
chaining and/or overlays. In version 4.0, your code size is limited only by
the operating system (and your computer), since each unit itself can have
up to 64K of code. Because of this, neither chaining nor overlays are
supported in version 4.0. If you have been using chaining, you can either
use the Exec procedure (found in the Dos unit), or you can convert your
.CHN files to units. If you've been using overlays, you should break your
program into several sections and make each section a unit.
Compiler Directives
In version 3.0, you could embed a set of compiler directives in your code to
set (or clear) certain options. In version 4.0, that set has been modified. Here
is a list of the current compiler directives; see Appendix C for more details:
Default
'Directive
Description
$B+/-
$D+/$F+/-
$1+/$1 file
$L+/-
$L file
$M s,l,h
$N+/$R+/-
$5+/$T+/-
$U file
$V+/-
$B-
$D+
$F-
$1+
$L+
$N$R+
$5+
$T$V+
In version 3.0, the include option ({$1 filename}) could be placed anywhere,
and could simply contain executable statements. In version 4.0, the include
option cannot be placed within a begin/end pair; if filename contains
executable statements, they must be within a complete procedure or
522
function or the file must contain the entire main body of the program,
including begin/end.
In version 3.0, the include option ({$1 filename}) did not require a space
between $1 and filename. In version 4.0, you must have a space after the $1.
In version 3.0, you could not nest include files; that is, if your program had
the directive {$1 mystuff.pas}, then MYSTUFF.PAS could not have any $1
(include) directives. In version 4.0, you can nest include files and units up
to eight levels deep.
Predeclared Identifiers
In version 3.0, all predefined constants, data types, variables, procedures,
and functions were always available. In version 4.0, many of those
predefined items are now located in one of the standard units (Dos, Crt,
Printer, Graph, Turb03, Graph3). In order to use those items, your program
must have a uses statement listing the units to be used. For example,
uses Crt, Dos;
Here's a list of the 4.0 units with their items that were predeclared in
version 3.0:
4.0
3.0
Dos
Crt
Printer
Lst
Turb03
Graph3
523
In version 3.0, CBreak was an undocumented Boolean variable that let you
enable or disable checking for program interruption via etr/-Break. In version
4.0, it is documented and has been renamed CheckBreak; CBreak is still
available in the Turbo3 unit.
In version 3.0, the Execute procedure was passed a file variable. In version
4.0, it has been renamed Exec (found in the Dos unit), and you pass it a
program name and a command line (parameters).
In version 3.0, the predefined file variables Aux, Con, Kbd, Lst, Trm, and Usr
were all available. In version 4.0, none of them are predefined; however, Lst
is available by using the unit Printer, and Kbd is available in the unit Turbo3.
By using the Dos unit, you can write your own device drivers; see Chapter
26 for more details.
.
In version 3.0, the functions MemAvail and MaxAvail were of type integer
and returned the number of paragraphs (16-byte chunks) free. In version
4.0, those functions are of type longint and return the number of bytes free.
Note that the original versions are available in the unit Turbo3.
In version 3.0, the FileSize, FilePos, and FileSeek functions returned a value of
type integer. In version 4.0, they return a value of type longint and can
return values up to 2,147,483,647.
In version 3.0, Mem W returned an integer value. In version 4.0, it returns a
value of type word.
In version 3.0, the LongFile functions (LongFileSize, LongFilePos, LongSeek)
returned a value of type real. In version 4.0, these functions are available
only through the Turbo3 unit, and they return a value of type real.
In version 3.0, the procedures MsDos and Intr both had an untyped
parameter; you had to declare the appropriate register data structure and
pass it in. In version 4.0, MsDos and Intr both require a parameter of type
Registers, which is also defined in the Dos unit.
In version 3.0, the procedure Intr took a constant of type integer as its first
parameter. In version 4.0, it accepts any expression (constant, variable, and
so on), but the value must be of type byte.
In version 3.0, the function IOResult returned error codes specific to Turbo
Pascal. In version 4.0, IOResult returns standard MS-DOS error codes.
(Turbo3 contains an IOResult function that maps 4.0 error codes to 3.0
values wherever possible.)
In version 3.0, if you had several successive I/O errors and then called
IOResuit, it would return the error code corresponding to the first I/O error.
In version 4.0, it returns the code corresponding to the last (most recent)
I/O error.
524
In version 3.0, the procedure Seek took a parameter of type integer for the
record number. In version 4.0, that parameter is now of type longint.
In version 3.0, you could call TextMode without any parameters; this would
restore the text mode to the last active mode before graphics. In version 4.0,
TextMode must always have a parameter; however, there is now the
predefined text mode constant Last, which sets the text mode to the last
active mode before graphics:
TextMode(LastMode);
Programming Changes
In version 3.0, the Addr function returned the address of any variable. Even
though Addr is supported in 4.0, you should now use the @ operator
instead, so that Ptr := Addr(Item) becomes Ptr := @Item.
In version 3.0, assignment was allowed between types that were identical
but defined separately:
var
Ainteger;
B: Ainteger;
A:
begin
A := B;
In version 3.0, you could use a string variable of length 1 as a case selector
in a case statement. In version 4.0, you no longer can, though you can use
the individual characters.
In version 3.0, the type char was compatible with a string of length 1:
525
var
Ch: char;
S: string[10];
begin
S :=' a';
Ch := S;
In version 4.0, neither is allowed. You can, however, still assign Ch to S, and
you can always assign S[lJ to Ch.
In version 3.0, you could call the procedure Close on a file that was already
closed with no results. In version 4.0, it produces an I/O error, which you
can handle by disabling I/O error checking (via the {$I-} option) and testing
the value returned by IOResult.
In version 3.0, you could use CSeg and DSeg in absolute statements:
var
Parameters: string[127] absolute CSeg: $80;
{ I is declared in Outer }
In version 3.0, you could not assign -32768 directly to an integer variable;
instead, you had to use the hex constant $8000. In version 4.0, you can now
assign -32768 directly; the hex constant $8000 (which now equals +32768) is
of type word and cannot be assigned to variables of type integer. You can
also assign $FFFF8000 to an integer variable.
526
In version 3.0, you could declare labels in the label section without using
the labels in your program. In version 4.0, if you declare a label and then
don't use it, you'll get a compiler error. In that case, you need to either use
the label in your code or remove it from the label declarations.
In version 3.0, you could (optionally) set the buffer size on a text file when
you declared it:
var
F: text[4096]i
In version 4.0, you now declare the text buffer as a data structure and
assign it to the text file using the SetTextBuf procedure:
var
F : texti
Buf: array[0 .. 4095] of chari
begin
Assign(F,'MyFile.TXT')i
SetTextBuf(F,Buf)i
Reset (F) i
end
else ... i
{ Special key }
{ Read again }
Handle special key }
Handle regular key }
527
begin
I := 30;
Write('Enter I:
'); Readln(I);
and pressed Enter when asked to enter I, the program would continue and
would leave I with a value of 30. In version 4.0, your program won't
continue until you enter an integer value.
In version 3.0, typed constants resided in the code segment (CS). In version
4.0, they reside in the data segment.
begin
New(BufPtr);
Move(BufPtr",X,SizeOf(X));
The exception was for ordinal data types (char, byte, integer, boolean,
enumerated types), in which case you use retyping (typecasting):
IntVar
:= byte('a');
MonthVar := Month(3);
In version 4.0, typecasting has been extended to all types, with the
requirement that the source and destination be exactly the same size:
type
Buffer = array[0 .. 5] of byte;
var
BufPtr: "Buffer;
X: real;
begin
New(BufPtr);
X := real(BufPtr");
In version 3.0, you were limited to the integer types byte (0 .. 255, 1 byte) and
integer (-32768 .. 32767, 2 bytes). In version 4.0, you also have the types
shortint (-128 .. 127, 1 byte), word (0 .. 65535, 2 bytes), and longint
(-2147483648 .. 2147483647,4 bytes).
528
In version 3.0, you were limited to the floating-point type real. In version
4.0, if you have an 8087 math coprocessor in your machine, you can set the
{$N+} option and use three additional floating-point data types: single (4
bytes), double (8 bytes), and extended (10 bytes). You can also use the 8byte integer type, compo
In version 3.0, you had to give an explicit length to any string variable you
declared; you also had to define your own type if you wanted to pass
strings as parameters:
type
BigStr = string[255];
var
Name: string[20];
S : BigStr;
procedure Whatever(T : BigStr);
In version 4.0, you can now declare a variable to be of type string, which is
equivalent to string[255]; you can declare formal parameters to be of type
string:
var
S: string;
procedure Whatever(T: string);
In version 3.0, all terms in a Boolean expression were evaluated, even if one
term already ensured that the expression was True or False. Because of
that, you couldn't write
if (B = 0) or (AlB = X) then ...
529
In version 3.0, you had the predefined identifiers Mem and Mem W for direct
memory access. In version 4.0, you also have MemL, which maps an array
of type longint onto memory.
In version 3.0, you could embed machine code within procedures and
functions (or the main body of your program) using the inline statement.
In version 4.0, you can also declare entire short procedures and functions to
be of type inHne; the machine code is then directly inserted (much like
macro expansion) everywhere the procedure or function is called.
In version 3.0, external assembly language routines had to be in .BIN
format and were declared in your program as offsets to the first routine in
the file. In version 4.0, those routines can be in .OB] format (produced by an
assembler) and are simply declared external, with a {$L files} directive
listing the .OB] files to be linked in.
In version 3.0, all procedure and function calls were near calls, which
meant all code had to be in the same segment. In version 4.0, the compiler
automatically generates near or far calls as needed, and you can. force all
calls to be far using the {$F+} option.
In version 3.0, there were no provisions to aid debugging of executable
files. In version 4.0, you can set {$D+} and {$T +} directives to support
symbolic debugging (Periscope, and so forth). See Chapter 9 for more
information.
530
B
Comparing Turbo Pascal 4.0 with
ANSI Pascal
This appendix compares Turbo Pascal to ANSI Pascal as defined by
ANSI/IEEE770X3.97-1983 in the book American National Standard Pascal
Computer Programming Language (ISBN 0-471-88944-X, published by The
Institute of Electrical and Electronics Engineers in New York).
531
532
interface
interrupt
shl
shr
string
unit
uses
xor
533
The type compatibility rules are extended to make char types and packed
string types compatible with string types.
Variables can be declared at absolute memory addresses using an
absolute clause.
A variable reference can contain a call to a pointer-type function, the
result of which is then dereferenced to denote a dynamic variable.
String-type variables can be indexed as arrays to access individual
characters in a string.
The type of a variable reference can be changed to another type through
a variable typecast.
Turbo Pascal implements typed constants, which can be used to declare
initialized variables of all types except file types.
Turbo Pascal implements three new logical operators: xor, shl, and shr.
The not, and, or, and xor operators can be used with integer-type
operands to perform bitwise logical operations.
The + operator can be used to concatenate strings.
The relational operators can be used to compare strings.
Turbo Pascal implements the @ operator, which is used to obtain the
address of a variable or a procedure or function.
The type of an expression can be changed to another type through a
value typecast.
The case statement allows constant ranges in case label lists, and
provides an optional else part.
Procedures and functions can be declared with external, inline, and
interrupt directives to support assembly language subroutines, inline
machine code, and interrupt procedures.
A variable parameter can be untyped (typeless), in which case any
variable reference can serve as the actual parameter.
Turbo Pascal implements units to facilitate modular programming and
separate compilation.
Turbo Pascal implements the following file-handling procedures and
functions, which are not available in ANSI Pascal:
Append
BlockRead
BlockWrite
ChDir
Close
Erase
FilePos
FileSize
Flush
GetDir
MkDir
Rename
RmDir
Seek
SeekEof
SeekEoln
String-type values can be input and output with the Read, Readln, Write,
and Writeln standard procedures.
534
Addr
CSeg
Concat
Copy
DSeg
Dec
Delete
Exit
FillChar
Frac
FreeMem
GetMem
Halt
Hi
Inc
Insert
Int
Length
Lo
Mark
MaxAvail
MemAvail
Move
Ofs
ParamCount
ParamStr
Pi
Pos
Ptr
Random
Randomize
Release
SPtr
SSeg
Seg
SizeOf
Str
Swap
UpCase
Val
Implementation-Dependent Features
The effect of using an implementation-dependent feature of Pascal, as
defined by ANSI/IEEE770X3.97-1983, is unspecified. Programs should not
depend on any specific path being taken in cases where an
implementation-dependent feature is being used. Implementationdependent features include
535
Treatment of Errors
This section lists those errors from Appendix D of the ANSI Pascal
Standard that are not automatically detected by Turbo Pascal. The numbers
referred to here are the numbers used in the ANSI Pascal Standard. Errors
6, 19-22, and 25-31 are not detected because they are not applicable to
Turbo Pascal.
2.
3.
5.
43.
48.
536
c
Compiler Directives
Some of the Turbo Pascal compiler's features are controlled through
compiler directives. A compiler directive is introduced as a comment with a
special syntax. Turbo Pascal allows compiler directives wherever
comments are allowed.
You can put compiler directives in your source code, in the command line
for the command-line compiler (use the format /$<directive> instead of
{directive}), in the command-line configuration file, or in the integrated
environment (through the Options/Compiler menu items).
A compiler directive starts with a $ as the first character after the opening
comment delimiter. The $ is immediately followed by a name (one or more
letters) that designates the particular directive. There are three types of
directives:
Switch directives. These directives turn particular compiler features on
or off by specifying + or - immediately after the directive name.
Parameter directives. These directives specify parameters that affect the
compilation, such as file names and memory sizes.
Conditional directives. These directives control conditional compilation
of parts of the source text, based on user-definable conditional symbols.
All directives, except switch directives, must have at least one blank
between the directive name and the parameters. Here are some examples of
compiler directives:
{$B+}
{$R- Turn off range-checking}
{$I TYPES. INC}
{$U C:\UNITS\MEM}
537
{$M 65520,8192,655360}
{$DEFINE Debug}
{$IFDEF Debug}
{$ENDIF}
Switch Directives
Switch directives are either global or local. Global directives affect the entire
compilation, whereas local directives affect only the part of the compilation
that extends from the directive until the next occurrence of the same
directive.
Global directives must appear before the declaration part of the program or
the unit being compiled, that is, before the first uses, label, const, type,
procedure, function, or begin keyword. Local directives, on the other
hand, can appear anywhere in the program or unit.
Multiple switch directives can be grouped in a single compiler directive
comment by separating them with commas; for example:
{$Bt,R-,S-}
Boolean Evaluation
Syntax:
Default:
{$B+}
or
{$B-}
{$ B - }
Type: Local
.Menu equivalent: Options/Compiler/Boolean evaluation
This directive switches between the two different models of code
generation for the and and or Boolean operators.
In the {$B+} state, the compiler generates code for complete Boolean
expression evaluation. This means that every operand of a Boolean
expression, built from the and and or operators, is guaranteed to be
evaluated, even when the result of the entire expression is already known.
In the {$B-} state, the compiler generates code for short-curcuit Boolean
expression evaluation, which means that evaluation stops as soon as the
result of the entire expression becomes evident. For further details, refer to
the section "Boolean Operators" in Chapter 18.
538
Debug Information
Syntax:
Default:
{$D+}
or
{$D-}
{$D+}
Type: Global
Menu equivalent: Options / Compiler /Debug information
This switch enables or disables the generation of debug information. Debug
information consists of a line number table for each procedure, which maps
object code addresses into source text line numbers.
When a runtime error occurs in a program or unit that was compiled with
the option Debug information on, Turbo Pascal uses that information to
locate the statement in the source text that caused the error.
For units, the debug information is recorded in the .TPU file, along with the
unit's object code and symbols. For programs, when compiling to memory,
it is kept in memory for later use. When compiling to disk, it is recorded in
the .TPM file, provided .TPM file generation is enabled through a {$T+}
directive. Debug information increases the size of .TPU and .TPM files, and
takes up additional room.when compiling to memory, but it does not affect
the size or speed of the executable program.
The TPMAP.EXE utility converts debug information in a .TPM file to a
line-number table in the resulting .MAP file. A number of symbolic
debuggers can use the line-number information to display source code
lines.
{$F+}
or
{$F-}
{$ F - }
Type: Local
Menu equivalent: Options/Compiler/Force far calls
This switch controls which call model to use for subsequently compiled
procedures and functions. Procedures and functions compiled in the {$F+}
state always use the far call model. In the {$F-} state, Turbo Pascal
automatically selects the appropriate model: far if the procedure or
function is declared in the interface section of a unit; near otherwise.
The {$F} (force far calls) compiler directive has no effect on a nested
procedure. The nested procedure is always of near model.
Appendix C, Compiler Directives
539
The near and far call models are described in full in Chapter 26, "Inside
Turbo Pascal."
Input/Output Checking
Syntax:
Default:
{$1+}
{$ I
or
{$1-}
+}
Type: Local
Menu equivalent: Options/Compiler/I/O checking
This switch enables or disables the automatic code generation that checks
the result of a call to an I/O procedure. I/O procedures are described in
Chapter 22, "Input and Output." If an I/O procedure returns a nonzero
I/O result when this switch is on, the program terminates, displaying a
runtime error message. When this switch is off, you must check for I/O
errors by using the IOResult function.
Link Buffer
Syntax:
Default:
{$L+}
or
{$L-}
{$L+}
Type: Global
Menu equivalent: Options/ Compiler /Link buffer
This directive enables or disables buffering in memory when linking .TPU
files at the end of compiling a program to disk.
Turbo Pascal's built-in linker is a two-pass linker. In the first pass through
the .TPU files, the linker marks every procedure that gets called by other
procedures. In the second pass, it generates the .EXE file by extracting the
marked procedures from the .TPU files. In the {$L+} state, the .TPU files are
kept in memory between two passes; in the {$L-} state, they are reread
during the second pass. {$L+} is faster than {$L-} but requires more
memory, so for very large programs you'll have to turn link buffering off.
Numeric Processing
Syntax:
Default:
540
{$N+}
or
{$N-}
{$N-}
Type: Global
Menu equivalent: Options/Compiler/Numeric processing
This directive switches between the two different models of floating-point
code generation supported by Turbo Pascal. In the {$N-} state, code is
generated to perform all real-type calculations in software by calling
runtime library routines. In the {$N+} state, code is generated to perform all
real-type calculations using the 8087 numeric coprocessor.
For further details on floating-point code generation, refer to Chapter 25,
"Using the 8087."
Range-Checking
Syntax:
Default:
{$R+}
or
{$R-}
{$R-}
Type: Local
Menu equivalent: Options/Compiler/Range checking
This switch enables or disables the generation of range-checking code. In
the {$R+} state, all array and string-indexing expressions are checked to be
within the defined bounds, and all assignments to scalar and subrange
variables are checked to be within range. If a range-check fails, the program
terminates, displaying a runtime error message. Enabling range-checking
slows down your program and makes it larger. Use this option when
debugging, then tum it off once the program is bug-free.
{$3+}
or
{$3-}
{$ 3 + }
Type: Local
Menu equivalent: Options/Compiler/Stack checking
This switch enables or disables the generation of stack-overflow-checking
code. In the {$S+} state, the compiler generates code at the beginning of
each procedure or function, which checks whether there is sufficient stack
space for the local variables. When there is not enough stack space, a call to
a procedure or function compiled with {$S+} causes the program to
terminate, displaying a runtime error message. In the {$S-} state, such a call
is most likely to cause a system crash.
Appendix C, Compiler Directives
541
{$T+}
or
{$T-}
Default: {$ T - }
Type: Global
Menu equivalent: Options/Compiler/Turbo pascal map file
This switch enables or disables the generation of a .TPM file when
compiling a program to disk.
A program's .TPM file is used by the Compile/Find error menu command
to locate the statement in the source text that caused a runtime error in the
program's .EXE file. This requires, however, that the program (and the
units it uses) be compiled in the {$D+} state, otherwise the .TPM file will
not contain all the necessary debug information. If some units weren't
compiled with {$D+}, the compiler will report the unit name, but not
position the source text.
The TPMAP.EXE utility converts .TPM files to .MAP files, which can be
processed by most symbolic debuggers.
Note: The $T directive has no effect when compiling a unit or when
compiling a program to memory.
Var-String Checking
Syntax:
Default:
{$V+}
or
{$V-}
{$v+}
Type: Local
Menu equivalent: Options / Compiler /Var-string checking
This directive controls type-checking on strings passed as variable
parameters. In the {$V+} state, strict type-checking is performed, requiring
the formal and actual parameters to be of identical string types. In the {$V-}
state, any string type variable is allowed as an actual parameter, even if the
declared maximum length is not the same as that of the formal parameter.
542
Parameter Directives
Include File
Syntax:
{$ I
filename}
Type: Local
Menu equivalent: Options/Directories/Include directories This directive
instructs the compiler to include the named file in the compilation. In effect,
the file is inserted in the compiled text right after the {$I filename} directive.
The default extension for filename is .PAS. If filename does not specify a
directory, then, in addition to searching for the file in the current directory,
Turbo Pascal searches in the directories specified in the
Options/Directories/Include directories menu, or in the directories
specified ia the / I option on the TPC command line.
Turbo Pascal allows, at most, five input files to be open at any given time.
This means that include files can be nested up to eight levels deep.
There is one restriction to the use of include files: An include file cannot be
specified in the middle of a statement part. In fact, all statements between
the begin and end of a statement part must reside in the same source file.
543
The stack segment and the heap are further discussed in Chapter 16,
''Variables,'' and Chapter 26, "Inside Turbo Pascal."
Note: The $M directive has no effect when used in a unit.
Conditional Compilation
Turbo-Pascal's conditional compilation directives allow you to produce
different code from the same source text, based on conditional symbols.
There are two basic conditional compilation constructs, which closely
resemble Pascal's if statement. The first construct
{$IFxxx} ... {$ENDIF}
544
causes the source text between {$IFxxx} and {$ENDIF} to be compiled only
if the condition specified in {$IFxxx} is True; if the condition is False, the
source text between the two directives is ignored.
The second conditional compilation construct
{$IFxxx} ... {$ELSE} ... {$ENDIF}
causes either the source text between {$IFxxx} and {$ELSE} or the source
text between {$ELSE} and {$ENDIF} to be compiled, based on the condition
specified by the {$IFxxx}.
Here are some examples of conditional compilation constructs:
{$IFDEF Debug}
Writeln{'X = ',X);
{$ENDIF}
{$IFDEF CPU87}
{$N+}
type
real = double;
{$ELSE}
{$N-}
type
single = real;
double = real;
extended = real;
camp = real;
{$ENDIF}
Conditional Symbols
Conditional compilation is based on the evaluation of conditional symbols.
Conditional symbols are defined and undefined (forgotten) using the
directives
{$DEFINE name}
{$UNDEF name}
You can also use the /D switch in the command-line compiler or the menu
selection 0/ C/ Conditional defines from within the integrated
environment.
545
MSDOS
Always defined, indicating that the operating system is MSDOS or PC-DOS. Versions of Turbo Pascal for other operating
systems will instead define a symbolic name for that particular
operating system.
CPU86
CPU87
546
{$DEFINE name}
Defines a conditional symbol of the given name. The symbol is known for
the remainder of the compilation or until it appears in an {$UNDEF name}
directive. The {$DEFINE name} directive has no effect if name is already
defined.
{$UNDEF name}
{$ IFDEF name}
{$ IFNDEF symbol}
547
548
D
The Turbo Pascal Utilities
This appendix describes in detail the three stand-alone utility programs
that come with Turbo Pascal: MAKE, TOUCH, and GREP.
Creating Makefiles
A makefile contains the definitions and relationships needed to help MAKE
keep your program(s) up-to-date. You can create as many makefiles as you
want and name them whatever you want. If you don't specify a makefile
when you run MAKE (using the -[ option), then MAKE looks for a file with
the default name MAKEFILE.
You create a makefile with any ASCII text editor, such as Turbo Pascal's
built-in interactive editor. All rules, definitions, and directives end with a
carriage return; if a line is too long, you can continue it to the next line by
placing a backslash (\) as the last character on the line.
Whitespace-spaces and tabs-is used to separate adjacent identifiers (such
as dependencies) and to indent commands within a rule.
Creating a makefile is almost like writing a program-with definitions,
commands, and directives. Here's a list of the constructs allowed in a
makefile:
549
comments
explicit rules
implicit rules
macro definitions
directives: file inclusion, conditional execution, error detection, macro
undefinition
Comments
Comments begin with a number sign (#); the rest of the line following the #
is ignored by MAKE. Comments can be placed anywhere and never have to
start in a particular column.
A backslash (\) will not continue a comment onto the next line; instead, you
must use a # on each line. In fact, you cannot use a backslash as a
continuation character in a line that has a comment. That's because if the
backs lash precedes the #, it is no longer the last character on the line; if it
follows the #, it is part of the comment itself.
Here are some examples of comments in a makefile:
# makefile for GETSTARS.EXE
# does complete project maintenance
# implicit rule
.asm.obj
masm $*.asm,$*.obj;
# unconditional rule
getstars.exe:
tpc getstars 1m
# dependencies
slib2.obj: slib2.asm
slibl.obj: slibl.asm
masm slibl.asm,slibl.obj;
# end of makefile
# command to create it
Explicit Rules
Explicit rules take the form
target [target ... ]: [source source ... ]
[command]
[command]
550
where target is the file to be updated, source is a file upon which target
depends, and command is any valid MS-DOS command (including
invocation of .BAT files and execution of .COM and .EXE files).
Explicit rules define one or more target names, zero or more source files,
and an optional list of commands to be performed. Target and source file
names listed in explicit rules can contain normal MS-DOS drive and
directory specifications, but they cannot contain wildcards.
Syntax here is important. target must be at the start of a line (in column 1),
and each command must be indented (preceded by at least one space
character or tab). As mentioned before, the backslash (\) can be used as a
continuation character if the list of source files or a given command is too
long for one line. Finally, both the source files and the commands are
optional; it is possible to have an explicit rule consisting only of target
[target .. .] followed by a colon.
The idea behind an explicit rule is that the command or commands listed
will create or update target, usually using the source files. When MAKE
encounters an explicit rule, it first checks to see if any of the source files are
target files elsewhere in the makefile. If so, those rules are evaluated first.
Once all the source files have been created or updated based on other
explicit (or implicit) rules, MAKE checks to see if target exists. If not, each
command is invoked in the order given. If target does exist, its time and date
of last modification are compared against the time and date for each source.
If any source has been modified more recently than target, the list of
commands is executed.
A given file name can occur on the left side of an explicit rule only once in a
given execution of MAKE.
Each command line in an explicit rule begins with whitespace. MAKE
considers all lines following an explicit rule to be part of the command list
for that rule, up to the next line that begins in column 1 (without any
preceding whitespace) or up to the end of the file. Blank lines are ignored.
An explicit rule, with no command lines following it, is treated a little
differently than an explicit rule with command lines .
If an explicit rule exists for a target with commands, the only files that the
551
Implicit Rules
MAKE also allows you to define implicit rules, which are generalizations of
explicit rules. What does that mean? Here's an example to illustrate the
relationship between the two types. Consider this explicit rule from the
previous sample program:
myutil.obj: myutil.asm
masm myutil.asm,myutil.obj;
552
This rule means, "any file ending with .OB} depends on the file with the
same name that ends in .ASM, and the .OB} file is created using the command rnasm $* .asm, $* .obj, where $* represents the file's name with no
extension./I (The symbol $* is a special macro and is discussed in the next
section.)
The syntax for an implicit rule follows:
. source_extension. target_extension:
{command}
{command}
where fname is the same for both files. In other words, this implicit rule
replaces all explicit rules having the format
fnarne.target_extension:fnarne.source_extension
[command]
[command]
553
asm. obj:
masm $*.asm,$*.obj;
You could then rewrite the last two explicit rules as follows:
myglobal.tpu: myglobal.pas
myutils.tpu: myutils.pas myglobal.tpu myutil.obj
Since you don't have explicit information on how to create these .TPU files,
MAKE applies the implicit rule defined earlier.
Several implicit rules can be written with the same target extension, but
only one such rule can apply at a time. If more than one implicit rule exists
for a given target extension, each rule is checked in the order the rules
appear in the makefile, until all applicable rules are checked.
MAKE uses the first implicit rule that it discovers for a file with the source
extension. Even if the commands of that rule fail, no more implicit rules are
checked.
All lines following an implicit rule are considered to be part of the
command list for the rule, up to the next line that begins without
whitespace or to the end of the file. Blank lines are ignored. The syntax for
a command line is provided later in this appendix.
Unlike explicit rules, MAKE does not know -the full file name with an
implicit rule. For that reason, special macros are provided with MAKE that
allow you to include the name of the file being built by the rule. (For
details, see the discussion of macro definitions later in this appendix.)
Here are some examples of implicit rules:
554
.pas.exe:
tpc $<
.pas.tpu:
tpc $<
.asm.obj:
masm $* /mx;
In the first example, the target files are .EXE files and their source files are
.PAS files. This example has one command line in the command list
(command-line syntax is covered later). Likewise, the second implicit rule
creates.TPU files from .PAS files.
The last example directs MAKE to assemble a given file from its .ASM
source file, using MASM with the /mx option.
Command Lists
We've talked about both explicit and implicit rules, and how they can have
lists of commands. Let's talk about those commands and your options in
setting them up.
Commands in a command list must be indented-that is,preceded by at
least one space character or tab-and take the form
[ prefix ... 1 command_body
-num
If no -num prefix is given, MAKE checks the exit status for the
command. If the status is nonzero, MAKE will stop and delete
the current target file.
555
With a hyphen but no number, MAKE will not check the exit
status at all. Regardless of what the exit status was, MAKE will
continue.
The command body is treated exactly as if it were entered as a line to
COMMAND. COM, with the exception that redirection and pipes are not
supported. MAKE executes the following built-in commands by invoking a
copy of COMMAND. COM to perform them:
break
md
rename
verify
cd
mkdir
set
vol
chdir
path
time
cIs
prompt
type
copy
ren
ver
MAKE searches for any other command name using the MS-DOS search
algorithm:
The current directory is searched first, followed by each directory in the
path.
In each directory, first a file with the extension .COM is checked, then an
.EXE file, and finally a .BAT.
If a .BAT file is found, a copy of COMMAND. COM is invoked to execute
the batch file.
Obviously, if an extension is supplied in the command line, MAKE searches
only for that extension.
This command will cause COMMAND. COM to execute the changedirectory command:
cd c:\include
This command will be searched for using the full search algorithm:
tpc myprog.pas /$Bt,Rt,It
This command will be searched for using only the .COM extension:
myprog.com geo.xyz
This command will be executed using the explicit file name provided:
c:\myprogs\fil.exe -r
Macros
Often certain commands, file names, or options are used again and again in
your makefile. In an example earlier in this appendix, all the TPC
commands used the switch jTc:\tp4\bin, which means that the files
TPC.CFG and TURBO.TPL are in the subdirectory C: \ TP4 \BIN. Suppose
556
you wanted to switch to another subdirectory for those files; what would
you do? You could go through and modify all the IT options, inserting the
appropriate path name. Or, you could define a macro.
A macro is a name that represents some string of characters (letters and
digits). A macro definition gives a macro name and the expansion text;
thereafter, when MAKE encounters the macro name, it replaces the name
with the expansion text.
Suppose you defined the following macro at the start of your makefile:
TURBO=c:\tp4\bin
Everywhere the Turbo directory is specified, you use the macro invocation
$(TURBO). When you run MAKE, $(TURBO) is replaced with its expansion
text, m. The result is the same set of commands you had before.
So what have you gained? Flexibility. By changing the first line to
TURBO=c:\tp4\project
you've changed all the commands to use the configuration and library files
in a different subdirectory. In fact, if you leave out the first line altogether,
you can specify which subdirectory you want each time you run MAKE,
using the -D (Define) option:
make -DTURBO=c:\tp4\project
This tells MAKE to treat TURBO as a macro with the expansion text
c:\tp4\project.
Macro definitions take the form
macro_name=expansion text
where macro_name is the name of a macro made up of a string of letters and
digits with no whites pace in it, though you can have whitespace between
macro_name and the equal sign (=). expansion text is any arbitrary string
Appendix 0, The Turbo Pascal Utilities
557
Case is significant in macros; that is, the macros names turbo, Turbo, and
TURBO are all considered to be different.
Macros are invoked in your makefile with the format
$ (macro_name)
The parentheses are required for all invocation, even if the macro name is
just one character, with the exception of three special predefined macros
that we'll talk about in just a minute. This construct-$(macro_name)-is
known as a macro invocation.
When MAKE encounters a macro invocation, it replaces the invocation
with the macro's expansion text. If the macro is not defined, MAKE
replaces it with the null string.
Macros in macros: Macro cannot be invoked on the left (macro_name) side
of a macro definition. They can be used on the right (expansion text) side,
but they are not expanded until the macro being defined is invoked. In
other words, when a macro invocation is expanded, any macros embedded
in its expansion text are also expanded.
Macros in rules: Macro invocations are expanded immediately in rule
lines.
Macros in directives: Macro invocations are expanded immediately in lif
and lelif directives. If the macro being invoked in an lif or lelif directive is
not currently defined, it is expanded to the value 0 (False).
Macros in commands: Macro invocations in commands are expanded
when the command is executed.
MAKE comes with several special predefined macros built-in: $d, $*, $<, $:,
$., and $&. The first is a defined test macro, used in the conditional
directives lif and lelif; the others are file name macros, used in explicit and
implicit rules. The various file name macros work in similar ways,
expanding to some variation of the full path name of the file being built. In
addition, the current SET environment strings are automatically loaded as
macros, and the macro _MAKE_ is defined to be 1 (one).
558
For example, you could modify the explicit MYAPP.EXE rule already given
to look like this:
myapp.exe: myapp.pas myglobal.tpu myutils.tpu
tpc $* /T$(TURBO)
When the command in this rule is executed, the macro $* is replaced by the
target file name (without an extension), myapp. This macro is very useful for
implicit rules. For example, an implicit rule for TPC might look like this
(assuming that the macro TURBO has been or will be defined):
.pas.exe:
tpc $* /T$(TURBO)
559
can be rewritten as
.asm.obj:
masm $<, $* . obj;
560
Directives
The version of MAKE bundled with Turbo Pascal allows something that
other versions of MAKE don't: conditional directives similiar to those
allowed for Turbo Pascal. You can use these directives to include other
makefiles, to make the rules and commands conditional, to print out error
messages, and to "undefine" macros.
Directives in a makefile begin with an exclamation point (!). Here is the
complete list of MAKE directives:
!include
!if
!else
!elif
!endif
!error
!undef
or
!include <filename>
You could then make use of this conditional macro definition in any
makefile by including the directive
!include "PATH.MAC"
561
When MAKE encounters the !include directive, it opens the specified file
and reads the contents as if they were in the makefile itself.
Conditional directives (lif, lelif, lelse, and lendif) give a programmer a measure
of flexibility in constructing makefiles. Rules and macros can be
"conditionalized" so that a command-line macro .definition (using the -D
option) can enable or disable sections of the makefile.
The format of these directives parallels, but is more extensive than, the
conditional directives allowed by Turbo Pascal:
!if expression
[ lines 1
!endif
!if expression
[ lines 1
!else
[ lines
!endif
!if expression
[ lines 1
!elif expression
[ lines 1
!endif
562
Any lif directives must have matching !endif directives within the same
source file. Thus the following include file is illegal regardless of what is
contained in any file that might include it, because it does not have a
matching lendif directive:
!if $(FILE_COUNT) > 5
some rules
!else
other rules
<end-of-file>
# decimal constant
# octal constant (note the leading zero)
# hexadecimal constant
/
%
&
I
A
&&
II
>
<
>=
<=
!=
addition
subtraction
multiplication
division
remainder
right shift
left shift
bitwise and
bitwise or
bitwise exclusive or
logical and
logical or
greater than
less than
greater than or equal to
less than or equal to
equality
inequality
563
If the value of that operand is nonzero, then the second operand (the part
between the? and the colon) is the result. If the value of the first operand is
zero, the value of the result is the value of the third operand (the part after
the :).
If you reach this spot without having defined TURBO, then MAKE will
stop with this error message:
Fatal rnakefile 5: Error directive: TURBO not defined
The undefine directive (fundef) causes any definition for the named macro to
be forgotten. If the macro is currently undefined, this directive has no
effect. The syntax is
!undef macro name
564
Using MAKE
You now know a lot about how to write makefiles; now's the time to learn
how to use them with MAKE. The simplest way to use MAKE is to type the
command
make
at the MS-DOS prompt. MAKE then looks for MAKEFILE; if it can't find it,
it looks for MAKEFILE.MAK; if it can't find that, it halts with an error
message.
What if you want to use a file with a name other than MAKE FILE or
MAKEFILE.MAK? You give MAKE the file (-f> option, like this:
make -fstars.mak
where option is a MAKE option (discussed later) and target is the name of a
target file to be handled by explicit rules.
Here are the syntax rules:
The word make is followed by a space, then a list of make options.
Each make option must be separated from its adjacent options by a space.
Options can be placed in any order, and any number of these options can
be entered (as long as there is room in the command line).
After the list of make options comes a space, then an optional list of
targets.
Each target must also be separated from its adjacent targets by a space.
MAKE evaluates the target files in the order listed, recompiling their
constituents as necessary.
If the command line does not include any target names, MAKE uses the
first target file mentioned in an explicit rule. If one or more targets are
mentioned on the command line, they will be built as necessary.
MAKE will stop if any command it has executed is aborted via a etr/-Break.
Thus, a Ctr/-C will stop the currently executing command and MAKE as
well.
565
-Diden=string Defines the named identifier iden to the string after the
equal sign. The string cannot contain any spaces or tabs.
566
-Idirectory
-Uidentifier
-s
-n
-ffi1ename
-? or-h
Fatals
Don't know how to make XXXXXXXX
This message is issued when MAKE encounters a nonexistent file name
in the build sequence, and no rule exists that would allow the file name
to be built.
Error directive: XXXX
This message is issued when MAKE processes an #error directive in the
source file. The text of the directive is displayed in the message.
Incorrect command line argument: XXX
This error occurs if MAKE is executed with incorrect command-line
arguments.
Not enough memory
This error occurs when the total working storage has been exhausted.
You should try this on a machine with more memory. If you already
have 640K in your machine, you may have to simplify the source file.
567
Errors
Bad file name format in include statement
Include file names must be surrounded by quotes or angle brackets. The
file name was missing the opening quote or angle bracket.
Bad undef statement syntax
An lundef statement must contain a single identifier and nothing else as
the body of the statement.
Character constant too long
Character constants can be only one or two characters long.
Command arguments too long
The arguments to a command executed by MAKE were more than 127
characters-a limit imposed by MS-DOS.
Command syntax error
This message occurs if
the first rule line of the makefile contained any leading whitespace.
an implicit rule did not consist of .ext.ext:.
an explicit rule did not contain a name before the: character.
a macro definition did not contain a name before the = character.
Division by zero
A divide or remainder in an lif statement has a zero divisor.
Expression syntax error in lit statement
The expression in an lif statement is badly formed-it contains a
mismatched parenthesis, an extra or missing operator, or a missing or
extra constant.
File name too long
The file name given in an linclude directive was too long for MAKE to
process. File path names in MS-DOS must be no more than 78 characters
long.
568
569
Turbo Pascal. TOUCH changes the date and time of one or more files to the
current date and time, making it "newer" than the files that depend on it.
To force a target file to be rebuilt, "touch" one of the files that target
depends on. To touch a file (or files), enter
touch filename [ filename ... ]
at the DOS prompt. TOUCH will then update the file's creation date(s).
Once you do this, you can invoke MAKE to rebuild the touched target
file(s). (You can use the DOS.wildcards * and? with TOUCH.)
SetUpMyModem.
The command-line syntax for GREP follows:
GREP [options] searchstring filers]
-1
-c
Only a count of matching lines is printed. For each file that contains
at least one matching line, the file name and a count of the number
of matching lines is printed. Matching lines are not printed.
570
-n
-v
Only non-matching lines are printed. Only lines that do not contain
the search string are considered to be matching lines.
-i
-z
-w
Several of these options are in direct conflict with each other. In these cases,
the following order applies (the first one is the one that takes precedence):
-z -1 -c -n
Each occurrence of an option overrides the previous definition. The default
setting for each option can be installed.
A dollar sign at the end of the expression matches the end of a line.
A period matches any character.
571
[]
The backslash "escape character" tells GREP to seach for the literal
character that follows it. For example, \. matches a period instead
of any character.
Any ordinary character not mentioned in this list matches that character. A
concatenation of regular expressions is a regular expression.
main ()
mymain(
Searches:
Note:
main(i:integer)
main(i,j:integer)
if (main ()) halt;
MAIN(i:integer);
Searches:
Note:
A:\data.fil
c:\Data.Fil
B: \DATA.FIL
d:\data.fil
a:data.fil
Writeln("c:\\data.fil");
Searches:
Note:
If you wish to search for the characters 1/\" and 1/.", you
must quote them by placing the backslash (\) escape
character immediately in front of them.
Searches:
Note:
573
Searches:
Note:
He said hi to me.
Where are you going?
Happening in anticipation of a unique situation,
Examples include the following:
"Many men smoke, but fu man chu."
He said "Hi" to me
Where are you going? I'm headed to the beach this
Searches:
Note:
Searches:
Note:
574
source is the binary file to convert; destination is the name of the .OBJ to be
produced; and public name is the name of the procedure as it will be
declared in your Turbo Pascal program.
The following example, the procedure ShowScreen, takes a pointer as a
parameter and moves 4000 bytes of data to screen memory. The file called
MENU.DTA contains the image of the main menu screen (80 * 25 * 2 = 4000
bytes).
Here's a simple (no error-checking) version of MYPROG.PAS:
program MyProg;
procedure ShowScreen(var ScreenData : pointer);
{ Display a screenful of data--no error-checking!
var
ScreenSegrnent: word;
begin
if (Lo(LastMode) = 7) then
ScreenSegrnent := $BOOO
else
ScreenSegrnent := $B800;
Move (ScreenData A,
Ptr(ScreenSegment, O)A,
4000);
end;
var
MenuP
MenuF
{ Mono? }
{ From pointer
To video memory
{ 80 * 25 * 2
pointer;
file;
begin
Assign (MenuF, 'MENU.DTA');
Reset (MenuF, 1);
GetMem(MenuP, 4000);
BlockRead(MenuF, Menup A , 4000);
Close(MenuF);
ShowScreen(MenuP);
end.
575
The screen data file (MENU.DTA) is opened and then read into a buffer on
the heap. Both MYPROG.EXE and MENU.DTA must be present at runtime
for this program to work. You can use BINOBJ to convert MENU.DTA to an
.OBJ file (MENUDTA.OBJ) and tell it to associate the data with a procedure
called MenuData. Then you can declare the fake external procedure
MenuData, which actually contains the screen data. Once you link in the
.OBJ file with the {$L} compiler directive, MenuData will be 4000 bytes long
and contain your screen data. First, run BINOBJ on MENU.DTA:
binobj MENU.DTA MENUDTA MenuData
The first parameter, MENV.DTA, shows a familiar file of screen data; the
second, MENUDTA, is the name of the .OBJ file to be created (since you
didn't specify an extension, .OBJ will be added). The last parameter,
MenuData, is the name of the external procedure as it will be declared in
your progam. Now that you've converted MENU.DTA to an .OBJ file,
here's what the new MYPROG.PAS looks like:
program MyProg;
procedure ShowScreen(ScreenData : pointer);
{ Display a screenful of data--no error checking!
var
ScreenSegment: word;
begin
if (Lo(LastMode) = 7) then
ScreenSegment := $BOOO
else
ScreenSegment := $B800;
Move(ScreenData~,
Ptr(ScreenSegment,
4000);
O)~,
end;
procedure MenuData; external;
{$L MENUDTA.OBJ }
begin
ShowScreen(@MenuData);
end.
{ Mono? }
{ From pointer }
{ To video memory }
{ 80 * 25 * 2 }
{ Display screen }
Notice that ShowScreen didn't change at all, and that the ADDRESS of your
procedure is passed using the @ operator.
The advantage of linking the screen data into the .EXE is apparent: You
don't need any support files in order to run the program. In addition, you
have the luxury of referring to your screen by name (MenuData). The
disadvantages are that (1) every time you modify the screen data file, you
must reconvert it to an .OBJ file and recompile MYPROG and (2) you have
to have a separate .OBJ file (and external procedure) for each screen you
want to display.
576
BINOB] is especially useful when the binary file you wish to link in is fairly
stable. One of the sample graphics programs uses BINOB] to build two
units that contain the driver and font files; refer to the extensive comment
at the beginning of GRLINK.PAS on Disk 2.
577
578
E
Reference M'aterials
This chapter is devoted to certain reference materials, including an ASCII
table, keyboard scan codes, and extended codes.
ASCII Codes
The American Standard Code for Information Interchange (ASCII) is a
code that translates alphabetic and numeric characters and symbols and
control instructions into 7-bit binary code. Table E.1 shows both printable
characters and control characters.
579
8
8
9
9
0
10
A
I
11
B
cJ
12
C
9
13
D
l'
14
E
J'
15
F
a
16
10
~
11
17
...
12
18
1
19
13
II
14
20
~
21
15
22
16
23
17
1
18
24
T
19
25
!
26
1A . -+
427
1B
1C
28
L
29
1D
++
30
1E
A
31
1F
...
580
156 9C
157 90
Y
158 9E
Pt
159 9F
f
174 AE
175 AF
176 BO
[~
177 B1
II
178 B2
I
179 B3
I
180 B4
~
181 B5
~
182 B6
~I
183 B7
11
184 B8
9
185 B9
~I
186 BA
II
187 BB
il
188 BC :!J
189 BO .1J
::I
190 BE
191 BF
1
242 F2
~
::;
243 F3
244 F4
245 F5
J
246 F6
:::
247 F7
248 F8
249 F9
250 FA
251 FB
n
252 FC
2
253 FO
254 FE
255 FF
.,
581
Second Code
3
15
16-25
30-38
44-50
59-68
71
72
73
75
77
79
80
81
82
83
84-93
94-103
104-113
114
115
116
117
118
119
120-131
132
133
134
135
136
137
138
139
140
582
Meaning
583
Key
Esc
11
@2
#3
$4
%5
"6
&7
"'8
(9
)0
+=
Backspace
Gtrl
A
S
D
F
G
H
J
K
L
...,
.11
",'
LeftShift
SpaceBar
Gaps Lock
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
Scroll Lock
584
Scan Code
in Hex
01
02
03
04
05
06
07
08
09
OA
OB
OC
00
OE
10
IE
IF
20
21
22
23
24
25
26
27
28
29
2A
39
3A
3B
3C
3D
3E
3F
40
41
42
43
44
09
OA
46
Scan Code
in Hex
Key
Left/ Right arrow
Q
W
E
R
T
Y
U
I
P
{[
}]
Return
/1
X
G
V
B
N
M
<,
>.
?/
RightShift
PrtSc'"
Alt
7Home
8Uparrow
9PgUp
Minus sign
4Left arrow
5
6Right arrow
+
1End
2Downarrow
3PgDn
Olns
Del
NumLock
OF
10
11
12
13
14
15
16
17
18
19
lA
IB
lC
2B
2C
20
2E
2F
30
31
32
33
34
35
36
37
38
47
48
49
4A
4B
4C
40
4E
4F
50
51
52
53
45
F
Customizing Turbo Pascal
This appendix explains how to customize Turbo Pascal and install your
customizations in the TURBO.EXE file.
What Is TINST?
TINST is the Turbo Pascal installation program that you can use to
customize TURBO.EXE (the integrated environment version of Turbo
Pascal). Through TINST, you can change various default settings in the
Turbo Pascal operating environment, such as the screen size, editing
commands, menu colors, and default directories. It directly modifies certain
default values within your copy of TURBO.EXE.
With TINST, you can do any of the following:
set up paths to the directories where your include files, unit files,
configuration files, Help files, Pick file, and executable files are located
customize the Editor command keys
set up Turbo Pascal's editor defaults and onscreen appearance
set up the default video display mode
change screen colors
resize Turbo Pascal's Edit and Output windows
change the defaults of any of the settings accessible through the
Options/Compiler menu or the Options/Compiler/Memory sizes menu
change the defaults of any of the settings accessible through the
Options/Environment menu or the Options/Environment/Screen size
menu
Appendix F, Customizing Turbo Pascal
585
You can use the Editor commands option to reconfigure (customize) the
interactive editor's keystrokes to your liking.
The Environment option is for setting various defaults for the default
editing modes and the appearance of the Turbo Pascal integrated
environment.
With Display mode, you can specify the video display mode that Turbo
Pascal will operate in, and whether your display is a "snowy" video
adapter.
You can customize the colors of almost every part of Turbo Pascal's
integrated environment through the Set colors option.
The Resize windows option allows you to change the sizes of the Edit and
Output windows.
Running TINST
1. To get started, type tinst Enter at the DOS prompt. TURBO.EXE must be
in the same directory as TINST; if it isn't, you must add the path name
of TURBO.EXE to the command invoking TINST.
Note: TINST comes up in black and white by default. If you have a color
monitor and want to run TINST in color rather than black and white,
type tinst Ie Enter at the DOS prompt.
586
Note that you can use one version of TINST to customize several
different copies of Turbo Pascal on your system. These various copies of
TURBO.EXE can have different executable program names. Simply
invoke TINST and give a (relative or absolute) path name to the copy of
TURBO.EXE you're customizing; for example,
tinst e:\turboOO\tpOO.exe
tinst .. \ .. \bwtp.exe
tinst Ie c:\borland\eolortp.exe
In this way, you can customize the different copies of Turbo Pascal on
your system to use different editor command keys, different menu
colors, and so on, if you're so inclined.
2. From the main TINST installation menu, you can select Compile,
Options, Editor commands, Display mode, Set colors, Resize windows,
or Quit/save. You can either press the highlighted capital letter of a
given option, or use the Up and Down arrow keys to move to your
selection and then press Enter. For instance, press S to Set the colors of
the Turbo Pascal integrated environment.
3. In general, pressing Esc (more than once if necessary) will return you
from a submenu to the main installation menu.
Turbo directory
Executable directory
Include directories
Unit directories
Object directories
Pick file name
587
If, in addition, you have divided your unit files among four different
directories, and want Turbo Pascal to search each of those directories when
looking for units, you could enter the following in the Unit directories
pop-up input window:
c:\turbo\startups;c:\turbo\stdunits;c: .. \myunits2;a:newunits3
Then, if Turbo Pascal can't find the configuration and Help files in the
current directory, it will look for them in the directory called TURBO\
CFGSNHLP (off the root directory of the C drive).
588
you want to save the changes. Once you save the Turbo directory paths, the
locations are written to disk and become part of TURBO.EXE's default
settings.
cursor movement
text insertion and deletion
block and file manipulation
string search (plus search-and-replace)
These editing commands are assigned to certain keys (or key combinations), which are explained in detail in Chapter II.
When you select Editor commands from TINST's main installation menu,
the Install Editor screen comes up, displaying three columns of text:
The left-hand column describes all the functions available in Turbo
Pascal's interactive editor.
The middle column lists the Primary keystrokes; what keys or special key
combinations you press to invoke a particular editor command.
The right-hand column lists the Secondary keystrokes; these are optional
alternate keystrokes you can also press to invoke the same editor
command.
Note: Secondary keystrokes always take precedence over primary keystrokes.
The bottom lines of text in the Install Editor screen summarize the keys you
use to select entries in the Primary and Secondary columns.
589
Key
Legend
What It Does
Left, Right,
Up, and Down
Arrow keys
Select
PgUpand
PgDn
Page
Enter
Modify
Restore factory
defaults
Esc
Exit
F4
Key Modes
After you press Enter to enter the modify mode, a pop-up window appears
on screen, listing the currently defined keystrokes for the selected
command. The bottom lines of text in the Install Editor screen summarize
the keys you use to change those keystrokes.
590
Key
Legend
What It Does
Backspace
Enter
Backspace
Accept
Esc
Abandon
changes
F2
Restore
F3
Clear
F4
Key Modes
Note: To enter the keys F2, F3, F4, or the backquote (') character, as part of
an editor command key sequence, first press the backquote key, then the
appropriate function key.
Keystroke combinations come in three flavors: WordStar-like, Ignore case,
and Verbatim. These are listed on the bottom line of the screen; the
highlighted one is the current selection.
591
If you type a letter (or one of these five characters: [,], \, '\ -) in this mode,
it will automatically be entered as a control-character combination. For
example:
In WordStar-like keystrokes, any letter you type is converted to a controluppercase-letter combination. Five other characters are also converted to
control-character combinations:
592
entered as a control-character combination; if a keystroke is to be a controlletter combination, you must hold down the Ctr! key while typing the letter.
For example:
Typing a or A will yield A (if this is the first keystroke, you'll get an error
message)
Typing Ctr! y or Ctr! Y will yield < Ctr! Y>
Typing Ctr! [ will yield < Ctr! [ >
In Ignore case keystrokes, the only character conversions are from
lowercase to uppercase (letters only).
Verbatim Selection
These keystrokes must always explicitly begin with a character that is a
special key or control key. If you type a letter in this mode, it will be
entered exactly as you type it.
Typing a will yield a (if this is the first keystroke, you'll get an error
message)
Typing A will yield A (if this is the first keystroke, you'll get an error
message)
Typing Ctr! Y will yield < Ctr! Y>
Typing Ctr! y will yield < Ctr! y >
Typing Ctr! [ will yield < Ctr! [ >
In Verbatim keystrokes, what you enter in the Install Editor screen for a
command's keystroke sequence is exactly what you must type in the Turbo
Pascal editor when you want to invoke that command. If, for example, you
enter < Ctr! A > band < Crt! H > B as the Verbatim primary and secondary
keystroke sequences for some editor command, you will only be able to
type those keys to invoke the command. Using the same letters but in
different cases-< Ctr! A> Band < Ctr! H > b-won't work.
Allowed Keystrokes
Although TINST provides you with lots of flexibility for customizing the
Turbo Pascal editor commands to your own taste, there are a few rules
governing the keystroke sequences you can define. Some of the rules apply
to any keystroke definition, while others only come into effect in certain
keystroke modes.
593
Global Rules
1. You can enter a maximum of six keystrokes for any given editor
2.
3.
4.
5.
6.
Primary
New Line
Cursor Left
Cursor Right
Word Left
Word Right
Cursor Up
Cursor Down
Scroll Up
Scroll Down
594
*
*
*
*
*
*
*
*
*
<CtrlM>
<CtrlS>
<CtrlD>
<CtrlA>
<CtrlF>
<CtrlE>
<CtrlX>
<CtrlW>
<CtrlZ>
Secondary
<CtrlM>
<Lft>
<Rgt>
<CtrlLft>
<CtrlRgt>
<Up>
<Dn>
Cormnand name
-
....
----------
Page Up
Page Down
Left of Line
Right of Line
Top of Screen
Bottom of Screen
Top of File
Bottom of File
Move to error
Move to Block Begin
Move to Block End
Move to Block End
Move to Previous Pos
Move to Marker 0
Move to Marker 1
Move to Marker 2
Move to Marker 3
Toggle Insert
Insert Line
Delete Line
Delete to End of Line
Delete Word
Delete Char
Delete Char Left
Set Block Begin
Set Block End
Mark Word
Hide Block
Set Marker 0
Set Marker 1
Set Marker 2
Set Marker 3
Copy Block
Move Block
Delete Block
Read Block
Write Block
Print Block
Exit Editor
Tab
Toggle Autoindent
Toggle Tabs
Restore Line
Find String
Find and Replace
Secondary
Primary
* <CtrlR>
* <CtrIC>
* <CtrIQ><CtrIS>
* <CtrIQ><CtrID>
* <CtrIQ><CtrIE>
* <CtrIQ><CtrIX>
* <CtrIQ><CtrIR>
* <CtrIQ><CtrIC>
* <CtrIQ><CtrIW>
* <CtrIQ><CtrIB>
* <CtrIQ><CtrIK>
* <CtrlQ><CtrIK>
* <CtrIQ><CtrIP>
* <CtrlQ>O
* <CtrlQ>l
* <CtrlQ>2
* <CtrlQ>3
* <CtrlV>
* <CtrlN>
* <CtrlY>
* <CtrIQ><CtrIY>
* <CtrIT>
* <CtrIG>
* <CtrlBkSp>
* <CtrIK><CtrIB>
* <CtrIK><CtrIK>
* <CtrIK><CtrIT>
* <CtrlK><CtrlH>
* <CtrIK>O
* <CtrlK>l
* <CtrlK>2
* <CtrIK>3
* <CtrIK><CtrIC>
* <CtrIK><CtrIV>
* <CtrlK><CtrlY>
* <CtrIK><CtrIR>
* <CtrIK><CtrIW>
* <CtrIK><CtrIP>
* <CtrIK><CtrID>
* <CtrlI>
* <CtrIO><CtrII>
* <CtrIO><CtrIT>
* <CtrIQ><CtrIL>
* <CtrIQ><CtrIF>
* <CtrIQ><CtrIA>
---------
<PgUp>
<PgDn>
<Home>
<End>
<CtrlHome>
<CtrIEnd>
<CtrlPgUp>
<CtrlPgDn>
<Ins>
<Del>
<CtrlH>
<CtrIK><CtrIQ>
<CtrlQ><CtrlI>
<CtrIQ><CtrlT>
595
Command name
Search Again
Insert Control Char
Save file
Match pair
Match pair backward
Primary
Secondary
* <CtrlL>
* <CtrlP>
* <CtrlK><CtrlS>
* <CtrlQ><Ctrl[>
* <CtrlQ><Ctrl]>
596
you want to select a mode other than the current video mode
you have a Color/Graphics Adapter that doesn't "snow"
you think Turbo Pascal is incorrectly detecting your hardware
your system has a composite screen, which acts like a CGA with only one
color-for this situation, select Black and white
597
Press D to select Display mode from the installation menu. A pop-up menu
will appear; from this menu you can select the screen mode Turbo Pascal
will use during operation. Your options include Default, Color, Black and
white, or Monochrome.
Default
By default, Turbo Pascal always operates in the mode that is active when
you load it.
Color
Turbo Pascal uses SO-column color mode no matter what mode is active
when you load TURBO.EXE, and switches back to the previously active
mode when you exit.
Monochrome
Turbo Pascal uses monochrome mode if you're currently in monochrome
mode, and switches back to the previously active mode when you exit.
When you select one of the first three options, the program conducts a
video test on your screen; look at the bottom status line for instructions
about what to do.
When you press any key, a window comes up with the query
Was there Snow on the screen?
599
simply copy TURBO.EXE from your master disk onto your work disk. You
can also restore the Editor commands by selecting the E option at the main
menu, then press R (for restore factory defaults) and Esc.
600
G
A DOS Primer
If you are new to computers or to DOS, you may have trouble
understanding certain terms used in this manual. This appendix provides
you with a brief overview of the following DOS concepts and functions:
What"ls DOS?
DOS is shorthand for Disk Operating System. MS-DOS is Microsoft's
version of DOS, while PC-DOS is IBM's rendition. DOS is the traffic
coordinator, manager, and operator for the transactions that occur between
the parts of the computer system and the computer system and you. DOS
operates in the background, taking care of may of the menial computer
tasks you wouldn't want to have to think about-for instance, the flow of
characters between your keyboard and the computer, between the
computer and your printer, and between your disk(s) and internal memory
(RAM).
601
The capital letter refers to the active disk drive (the one DOS and you are
using right now). For instance, if the prompt is A>, it means you are
working with the files on drive A, and that commands you give DOS will
refer to that drive. When you want to switch to another disk, making it the
active disk, all you do is type the letter of the disk, followed by a colon and
press Enter. For instance, to switch to drive B, just type
B:
Enter
There are a few commands you will use often with DOS, if you haven't
alread y, such as
DEL or ERASE
To erase a file
DIR
COpy
TURBO
602
the program is located in order to load it; unless you have set up a DOS path
(described shortly), DOS won't know where to find the program.
For instance, if your distribution disk with the TURBO.EXE program is in
drive A but the prompt you see on your screen is B>, DOS won't know
what you're talking about if you type TURBO and press Enter. Instead of
starting Turbo Pascal, it will give you the message Bad command or file
name.
It's as if you were shuffling through the "Pet Records" file in your file
cabinet looking for information about your home finances. You're in the
wrong place. So if you happen to get that DOS message, simply switch to
drive A by typing A: and then press Enter. Then type TURBO and press Enter
to load Turbo Pascal.
You can set up a "path" to the Turbo Pascal files so that DOS can find them,
using the DOS path command. See the section titled "The AUTOEXEC.BAT
File" for more information.
Directories
A directory is a convenient way to organize your floppy or hard disk files.
Directories allow you to subdivide your disk into sections, much the way
you might put groups of manila file folders into separate file boxes. For
instance, you might want to put all your file folders having to do with
finance-a bank statement file, an income tax file, or the like-into a box
labeled "Finances."
On your computer, it would be convenient to make a directory to hold all
your Turbo Pascal files, another for your SideKick files, another for your
letters, and so on. That way, when you type DIR on the DOS command line,
you don't have to wade through hundreds of file names looking for the file
you want. You'll get a listing of only the files on the directory you're
currently logged onto.
Although you can make directories on either floppy or hard disks, they are
used most often on hard disks. Because hard disks can hold a greater
volume of data, there is a greater need for organization and
compartmentalization.
When you're at the DOS level, rather than in Turbo Pascal or another
program, you can tell DOS to create directories, move files around between
directories, and display which files are in a particular directory.
In the examples that follow, we assume you are using a hard disk system,
and that you are logged onto the hard disk so that the prompt you see on
603
your screen is C>. If you want to create directories on your floppy disks,
substitute A or B for C in the example.
To make a directory for your Turbo Pascal files, do the following:
1. At the C> prompt, type MKDIR Turbo and press Enter. The MKDIR
command tells DOS to make a directory called TURBO.
2. Type CHDIR TURBO and press Enter. The CHDIR command tells DOS to
move you into the TURBO directory.
3. Now, put the Turbo Pascal disk you want to copy from into one of your
floppy drives-let's say A for this example-and type COPY A: * . * Enter.
(The asterisks are wildcards that stand for all files.) The COPY command
tells DOS to copy all files on the A drive to the TURBO directory on the
C drive. As each file on the disk is copied, you will see it listed on the
screen.
That's all there is to it. Treat a directory the same way you would a disk
drive: To load Turbo Pascal, you must be in the TURBO directory before
typing TURBO and pressing Enter or DOS won't be able to find the
program.
Subdirectories
If you are someone who really likes organization, you can subdivide your
directories into subdirectories. You can create as many directories and
subdirectories as you like-just don't forget where you put your files!
A subdirectory is created the same way as a directory. To create a
subdirectory from the TURBO directory (for instance, for storing your unit
files), do the following:
1.
2.
3.
4.
604
and from now on (until you turn your computer off or reboot), the prompt
will show you exactly where you are. Try it. If you are still in the UNITS
subdirectory, your DOS prompt will look like
C:\TURBO\UNITS >
605
Changing Directories
How do you get from one directory to another? It depends on where you
want to go. The basic DOS command for changing directories is CHOIR.
Use it like this:
To move from one directory to another: For example, to change from the
TURBO directory to one called SPRINT, type the following from the
TURBO directory:
C:\TURBO>
Notice the backslash (\) before the directory name. Whenever you are
moving from one directory to another unrelated directory, type the name
of the directory, preceded by a backslash.
To move from a directory to its subdirectory: For example, to move
from the TURBO directory to the UNITS subdirectory, type the following
from the TP directory:
C:\TP> CHOIR UNITS Enter
In this case, you did not need the backslash, because the UNITS directory
is a direct offshoot of the TP directory. In fact, DOS would have
misunderstood what you meant if you had used the backslash-OOS
would have thought that UNITS was a directory off the main (root)
directory.
To move from a subdirectory to its parent directory: For example, to
move from the UNITS subdirectory to the TP directory, type the
following from the UNITS subdirectory:
C:\TP\UNITS> CHDIR Enter
DOS will move you back to the TP directory. Any time you want to move
back to the parent directory, use a space followed by two periods after
the CHOIR command.
To move to the root directory: The root directory is the original directory.
It is the parent (or grandparent) of all directories (and subdirectories).
When you are in the root directory, you'll see this prompt: C:\ >.
To move to the root directory from any other directory, simply type
CHOIR \ Enter
The backslash without a directory name signals DOS that you want to
return to the root directory.
606
This appendix has presented only a quick look at DOS and some of its
functions. Once you're familiar with the information given here, you may
want to study your DOS manual and discover all the other things you can
do with your computer's operating system. There are many DOS functions
not mentioned here that can simplify and enhance your computer use.
607
608
H
Glossary
Here are some quick glossary ideas. Enjoy.
absolute variable A variable declared to exist at a fixed location in
memory rather than letting the compiler determine its location.
ANSI The acronym for the the American National Standards Institute, the
organization that, among other things, describes the elements of so-called
standard Pascal.
ASCII character set The American Standard Code for Information
Interchange's standard set of numbers to represent the characters and
control signals used by computers.
actual parameter A variable, expression, or constant that is substituted for
a formal parameter in a procedure or function call.
address A specific location in memory.
algorithm A set of rules that defines the solution to a problem.
allocate To reserve memory space for a particular purpose, usually from
the heap.
array A sequential group of identical data elements that are arranged in a
single data structure and are accessible by an index.
argument An alternative name for a parameter (see actual parameter).
assignment operator The symbol :=, which gives a value to a variable or
function of the same type.
assignment statement A statement that assigns a specific value to an
identifier.
Appendix H, Glossary
609
610
611
612
Appendix H, Glossary
613
614
nil pointer A pointer having the special value nil; a nil pointer doesn't
point to anything.
node An individual element of a tree or list.
object code The output of a compiler.
offset An index within a segment.
operand An argument that is combined with one or more operands and
opera tors to form an expression.
operating system A program that manages all operations and resources of
the computer.
operator A symbol, such as +, that is used to form expressions.
operator hierarchy The rules that determine the order in which operators
in an expression are evaluated.
ordinal type An ordered range of values; same as scalar type.
output The result of running a program. Output can be sent to a printer,
displayed on screen, or written to disk.
overflow The condition that results when an operation produces a value
that is more positive or negative than the computer can represent, given the
allocated space for the value or expression.
parameter A variable or value that is passed to a procedure or function.
parameter list The list of value and variable parameters declared in the
heading of a procedure or function declaration.
Pascal, Blaise A French mathematician and philosopher (1623-66) who
built a mechanical adding machine, considered to be an early predecessor
to calculators and computers.
pass To use as a parameter.
pointer A variable that points to a specific memory location.
pop The removal of the topmost element from a stack.
port An I/O device that can be accessed through the CPU's data bus.
precedence The order in which operators are executed.
predefined identifier A constant, type, file, logical device, procedure, or
function that is available to the programmer without having to be defined
or declared.
procedure A subprogram that can be called from various parts of a larger
program.
Appendix H, Glossary
615
616
Appendix H, Glossary
617
618
I
Error Messages and Codes
Compiler Error Messages
The following lists the possible error messages you can get from the
compiler during program development. Whenever possible, the compiler
will display additional diagnostic information in the form of an identifier or
a file name, for example:
Error 15: File not found (WINDOW.TPU).
environment.
If Options/Compiler/Link buffer in the integrated environment is set to
Memory, set it to Disk. Alternatively, place a {$L-} directive at the
beginning of your program. Use / $L- option to link to disk in the
command-line compiler.
619
2 Identifier expected.
An identifier was expected at this point. You may be trying to redeclare a
reserved word.
3 Unknown identifier.
This identifier has not been declared.
4 Duplicate identifier.
The identifier has already been used within the current block.
5 Syntax error.
An illegal character was found in the source text. You may have forgotten
the quotes around a string constant.
6 Error in real constant.
The syntax of real-type constants is defined in Chapter 13, "Tokens and
Constants."
7 Error in integer constant.
The syntax of integer-type constants is defined in Chapter 13, "Tokens and
Constants." Note that whole real numbers outside the maximum integer
range must be followed by a decimal point and a zero; for example,
12345678912.0.
8 String constant exceeds line.
You have most likely forgotten the ending quote in a string constant.
620
621
622
26 Type mismatch.
This is due to
incompatible types of the variable and the expression in an assignment
statement
incompatible types of the actual and formal parameter in a call to a
procedure or function
g an expression type that is incompatible with index type in array indexing
incompatible types of operands in an expression
27 Invalid sub range base type.
All ordinal types are valid base types.
28 Lower bound greater than upper bound.
The declaration of a subrange type specifies a lower bound greater than the
upper bound.
29 Ordinal type expected.
Real types, string types, structured types, and pointer types are not allowed
here.
30 Integer constant expected.
31 Constant expected.
32 Integer or real constant expected.
33 Type identifier expected.
The identifier does not denote a type as it should.
34 Invalid function result type.
Valid function result types are all simple types, string types, and pointer
types.
35 Label identifier expected.
The identifier does not denote a label as it should.
623
36 BEGIN expected.
37 END expected.
38 Integer expression expected.
624
46 Undefined external.
The external procedure or function did not have a matching PUBLIC
definition in an object file. Make sure you have specified all object files in
{$L filename} directives, and check the spelling of the procedure or function
identifier in the .ASM file.
47 Invalid object file record.
The .OBJ file contains an invalid object record; make sure the file is in fact
an .OBJ file.
48 Code segment too large.
The maximum size of the code of a program or unit is 65520 bytes. If you
are compiling a program, move some procedures or functions into a unit. If
you are compiling a unit, break it into two or more units.
49 Data segment too large.
The maximum size of a program's data segment is 65520 bytes, including
data declared by the used units. If you need more global data than this,
declare the larger structures as pointers, and allocate them dynamically
using the New procedure.
50 DO expected.
51 Invalid PUBLIC definition.
The identifier was made public through a PUBLIC directive in assembly
language, but is has no matching external declaration in the Pascal
program or unit.
Two or more PUBLIC directives in assembly language define the same
identifier.
The .OBJ file defines PUBLIC symbols that do not reside in the CODE
segment.
52 Invalid EXTRN definition.
The identifier was referred to through an EXTRN directive in assembly
language, but it is not declared in the Pascal program or unit, nor in the
interface part of any of the used units.
The identifier denotes an absolute variable.
The identifier denotes an inline procedure or function.
Appendix /, Error Messages and Codes
625
626
61 Invalid typecast.
The sizes of the variable reference and the destination type differ in a
variable typecast.
You are attempting to typecast an expression where only a variable
reference is allowed.
62 Division by zero.
The preceding operand attempts to divide by zero.
63 Invalid file type.
The file type is not supported by the file-handling procedure; for example,
readln with a typed file or Seek with a text file.
64 Cannot Read or Write variables of this type.
Read and Readln can input variables of char, integer, real, and string
types.
Write and Writeln can output variables of char, integer, real, string, and
boolean types.
65 Pointer variable expected.
The preceding variable must be of a pointer type.
66 String variable expected.
The preceding variable must be of a string type.
67 String expression expected.
The preceding expression must be of a string type.
68 Circular unit reference.
Two units are not allowed to use each other:
unit U1;
uses U2;
unit U2;
uses U1;
In this example, doing a Make on either unit will generate error 68.
627
86 ":" expected.
87 "," expected.
88 "(" expected.
89 ")" expected.
90 "=" expected.
91 ":=" expected.
629
94 "." expected.
95 " ." expected.
630
631
632
633
The procedure or function header specified in the interface part does not
match this header.
The' procedure or function header specified in the forward declaration
does not match this header.
132 Critical disk error
A critical error occurred during compilation (for example, drive not ready
error).
133 Old map file
The .TPM file is older than the corresponding .EXE file. This indicates that
the 'last time you compiled your program, a .TPM file was not produced.
For example, if TEST.TPM is older than TEST.EXE, you must recompile
TEST.PAS with the {$T} compiler directive in order to find a runtime error.
Runtime Errors
Certain errors at runtime cause the program to display an error message
and terminate:
Runtime error nnn at xxxx:yyyy
where nnn is the runtime error number, and xxxx:yyyy is the runtime error
address (segment and offset).
The runtime errors are divided into four categories: DOS errors 1-99; 1/0
errors, 100-149; critical errors, 150-199; and fatal errors, 200-255.
DOS Errors
2 File not found.
Reported by Reset, Append, Rename, or Erase if the name assigned to the file
variable does not specify an existing file.
634
635
I/O Errors
These errors cause termination if the particular statement was compiled in
the {$I+} state. In the {$I-} state, the program continues to execute, and the.
error is reported by the JOResult function;
100 Disk read error.
Reported by Read on a typed file if you attempt to read past the end of the
file.
101 Disk write error.
Reported by Close, Write, Writeln, Flush, or Page if the disk becomes full.
102 File not assigned.
Reported by Reset, Rewrite, Append, Rename, and Erase if the file variable has
not been assigned a name through a call to Assign.
103 File not open.
Reported by Close, Read, Write, Seek, Eot, FilePos, FileSize, Flush, BlockRead, or
Block Write if the file is not open.
104 File not open for input.
Reported by Read, Readln, Eot, Eoln, SeekEot, or SeekEoln on a text file if the
file is not open for input.
636
Critical Errors
150 Disk is write-protected.
151 Unknown unit.
152 Drive not ready.
153 Unknown command.
154 CRC error in data.
155 Bad drive request structure length.
156 Disk seek error.
157 Unknown media type.
158 Sector not found.
159 Printer out of paper.
160 Device write fault.
161 Device read fault.
162 Hardware failure.
Refer to your DOS programmer's reference manual for more information
about critical errors.
637
Fatal Errors
These errors always immediately terminate the program.
200 Division by zero.
201 Range check error.
This error is reported by statements compiled in the {$R+} state when one
of the following situations arise:
The index expression of an array qualifier was out of range.
An attempt was made to assign an out of range value to a variable.
An attempt was made to pass an out of range value as a parameter to a
procedure or function.
202 Stack overflow error.
This error is reported on entry to a procedure or function compiled in the
{$S+} state when there is not enough stack space to allocate the
subprogram's local variables. Increase the size of the stack by using the $M
compiler directive.
203 Heap overflow error.
This error is reported by New or GetMem when there is not enough free
space in the heap to allocate a block of the requested size. For a complete
discussion of the heap manager, refer to Chapter 26, "Inside Turbo Pascal."
204 Invalid pointer operation.
This error is reported by Dispose or FreeMem if the pointer is nil or points to
a location outside the heap, or if the free list cannot be expanded.
205 Floating point overflow.
A floating-point operation produced an overflow.
638
639
640
Borland
.Software
INTERNATIONAL
OUATTRO~
THE PROFESSIONAL SPREADSHEET
Borland's super graphic new generation spreadsheet: Twice the power at
half the price! 'Jen types of presentation-quality graphs. Compatible with
1-2-3, dBASE, Paradox and other
spreadsheets and databases.
Quattro, Borland's new generation professional
spreadsheet, proves there are better and faster
ways to get your work done-whether it's graphics, recalculations, macros, or search and sort.
Presentation-quality graphics
Quattro has excellent built-in graphics capabilities that help you create a wide variety of graphs.
Bar graphs, line graphs, pie charts, XY graphs,
area charts-you can create up to 10 types of
graphs, and print them directly from the spreadsheet or store them for future use.
Smarter recalculation
When a formula needs to be recalculated,
Quattro uses "intelligent recalc" to recalculate
only those formulas whose elements have changed.
This makes Quattro smarter and faster than other
spreadsheets.
Direct compatibility
Quattro can directly load and use data files
created with other spreadsheet and database programs like 1-2-3, dBASE, and Paradox. Quattro can
read and even write WKS, WKl, and WKE files. You
can also import ASCII and other text files into the
spreadsheet.
Easy installation
Quattro can detect most computers and screen
types, so it's always ready to load and run!
Plus, like all other Borland products, Quattro is
not copy protected!
'Jechnical Features
o
o
o
o
o
o
o
o
o
o
o
o
o
o
Minimum system requirements: For the IBM PS/2~ and the IBM and
Compaq- families of personal computers and all 100% compatibles. PCDOS (MS-DOS) 2.0 or later. Two floppies or a hard disk. 384K.
Quattro and Paradox are trademarks of Borland International. Inc. Lotus and 1-2-3 are registered trademarks of Lotus Development Corp Other brand and product names are trademarks or registered trademarks of their respective holders. Copynght C1987 Berland InternaIiOnal, Inc
BOR 0414
lJ,j
In'lIn: IIIIA.,IEI
All the SideKick windows stacked up over Lotus 1-2-3.From bottom to top: SideKick's "Menu Window," ASCII
Table, Notepad, Calculator, Appointment Calendar, Monthly
Calendar, and Phone Dialer.
BIIPEIIEY: :~:::IIt:'''"'r
RAM-resident
Increased productivity lor IBMPCs or compatibles
SuperKey's simple macros are electronic shortcuts to success.
By letting you reduce a lengthy paragraph into a single .keystroke
01 your choice, SuperKey eliminates repetition.
SuperKey turns 1,000 keystrokes into 11
SuperKey can record lengthy keystroke sequences and play them back at the touch of a single key.
Instantly. Like magic.
In fact, with SuperKey's simple macros, you can turn "Dear Customer: Thank you for your inquiry.
We are pleased to let you know that shipment will be made within 24 hours. Sincerely," into the
one keystroke of your choice!
SuperKey keeps your confidential files-confidential!
Without encryption, your files are open secrets. Anyone can walk up to your PC and read your
confidential files (tax returns, business plans, customer lists, personal letters, etc.).
With SuperKey you can encrypt any file, even while running another program. As long as you keep
the password secret, only you can decode your file correctly. Super Key aTso implements the U.S.
government Data Encryption Standard (DES).
~
~
~
~
~
~
~
~
~
~
~
~
Lightning
Turbo Lightning teams up
with the Random House
Concise Word List to
check your spelling as
you type!
Turbo Lightning, using the
BO,OOO-word Random House
Dictionary, checks your spelling
as you type. If you misspell a
word, it alerts you with a
"beep." At the touch of a key,
Turbo Lightning opens a
window on top of your
application program and
suggests the correct spelling.
Just press one key and the
misspelled word is instantly
replaced with the correct word.
Turbo Lightning works
hand-in-hand with the
Random House Thesaurus
to give you instant access
to synonyms
Turbo Lightning lets you
choose just the right word from
a list of alternates, so you
don't say the same thing the
same way every time. Once
Turbo Lightning opens the
Thesaurus window, you see a
list of alternate words; select
the word you want, press
ENTER and your new word will
instantly replace the original
word. Pure magic!
~~~~ ~~Ht:'.
it
hl~lItd iI' "ht-ih
k~')
~j.'~.af
tlt.l:t
d~'~:"$
~~
':i>1'
ad:l.. !h
~~
>l ,II
BORLAND
INTERNATIONAL
Turbo lightning and Turbo Lightning library are registered trademarks of Borland International. Inc
IBM. Xl. AT. and PCjr are registered trademarks of International Business Machines Corp Random
House is a registered trademark of Random House. Inc
Copyright 1987 Borland International
BOR 0070B
Your Development Toolbox and Technical Reference Manual for Thrbo Lightning
Minimum system configuration: IBM PC, Xl, AT, PCjr, Portable, and true compatibles. 256K RAM minimum. PCDOS (MSDOS) 2.0
or greater. Turbo Lightning software required. Optional-Turbo Pascal 3.0 or greater to edit and compile Turbo Pascal source code.
'1 11
THE IATABASE
~r'~II: .AIASE'
Lets you organize, analyze and report information faster than ever before! If you manage mailing lists,
customer files, or even your company's budgets-Reflex is the database manager for you!
Reflex is the acclaimed, high-performance database manager you've been waiting for. Reflex extends
database management with business graphics. Because a picture is often worth a 1000 words, Reflex
lets you extract critical information buried in mountains of data. With Reflex, when you look, you see.
The REPORT VIEW allows you to generate everything from mailing labels to sophisticated reports.
You can use database files created with Reflex or transferred from Lotus 1-2-3,e dBASE,e PFS: File,e
and other applications.
BEILE1'HE WIIISHIP"
Scheduling Appointments
Planning Conference Facilities
Managing a Project
Creating a Mailing System
Managing Employment Applications
Whether you're a newcomer learning Reflex basics or an experienced "power user" looking for tips, Reflex:
The Workshop will help you quickly become an expert database analyst.
Minimum system configuration: IBM PC, AI, and Xl, and true compatibles. PC-DOS (MS-DOS) 2.0 or greater. 384K RAM minimum. Requires Reflex:
The Database Manager, and IBM Color Graphics Adapter, Hercules Monochrome Graphics Card or equivalent.
TURBO
o
o
o
--..=..
--:::"'
BORLAND
INTERNATIONAL
Minimum system configuration: IBM PC, Xl, AT, Portable, 3270, PCjr
and true compatibles. PC-DOS (MS-DOS) 2.0 or later. 384K RAM
minimum.
"IIII',IIIIIST.
"'11"
@
@
@
@
@
@
@
@
@
Minimum system configuration: IBM PC, XT, AT or true compatibles. PC-DOS (MS-DOS) 2.0 or later. Requires Turbo Prolog 1.10
or higher. Dual-floppy disk drive or hard disk. 512K.
Turbo Prolog Toolbox and Turbo Prolog are trademarks 01 Borland International, Inc. Rellex
is a registered trademark of Borland/Analytica, Inc. dBASE III is a registered trademark of
Ashlon-Tate. Lotus 1-2-3 and SYfTllhony are registered trademarks of Lotus Development
Corp. IBM, XT. and AT are registered trademarks of International Business Machines Corp.
MS-DOS is a registered trademark of Microsoft Corp.
BOR 0240
TUBIII IABIC
The high-speed BASIC you've been waiting lor!
You probably know us for our Turbo Pascal and Turbo Prolog. Well, we've done
it again! We've created Turbo Basic, because BASIC doesn't have to be slow.
If BASIC taught you how to walk, Turbo Basic will teach you how to run!
With Turbo Basic, your only speed is "Full Speed Ahead"! Turbo Basic is a complete development envir0nment with an amazingly fast compiler, an interactive editor and a trace debugging system. And because
Turbo Basic is also compatible with BASICA, chances are that you already know how to use Turbo Basic.
IBM PC. AT, XT, PS/2 or true compatibles. 320K. One floppy drive. PC-DOS (MS-DOS) 2.0 or later.
liJrbo BaSic. Turbo Prolog and Turbo Pascal are registered trademarks and MicroCalc is a trademark of Borland International. Inc. Other brand and product names are trademarks or registered
trademarks of their respective holders.
Copyright 1987 Borland International
BOA 0265B
"RBII BABIC
DATABASE TOOLBOX'
With the Turbo Basic Database Toolbox you can build your own
powerful, professional-quality database programs. And like aI/ other
Borland Toolboxes, it's advanced enough for professional
programmers yet easy enough for beginners.
Three ready-to-use modules
The Toolbox enhances your programming with three problem-solving
modules:
Turbo Access quickly locates, inserts,
or deletes records in a database using
B+ trees-the ,fastest method for finding
and retrieving database information.
(Source code is included.)
Turbo Sort uses the Quicksort
method to sort data on single items
or on multiple keys. Features virtual
memory management for sorting large
data files. (Commented source code
is on disk.)
TRAINER is a demonstration program
that graphically displays how B+ trees
work. You can key in sample records and
see a visual index of B+ trees being
built.
Technical Features
@ Maximum number of files open: 15 files,
or 7 data sets
@ Maximum file size: 32 Mb
@ Maximum record size: 32K
@
@
@
@
',IBI BABIC
EI1111B 11111lllll"
With Turbo Basic we gave you the fastest BASIC around. Now the
Turbo Basic Editor Toolbox will help you build your own superfast
editor to incorporate into your Turbo Basic programs. We provide all
the editing routines. You plug in the features you want!
Two sample editors with source code
To demonstrate the tremendous power of the Toolbox, we've included two sample editors
with complete source code:
FirstEd. Acompl~te editor with windows, block commands, and memory-mapped screen
routines, all ready to include in your programs.
MicroSta"-: Afull-blown text editor with a pull-down menu user interface and all the standard
features you'd expect in any word processor. Plus features other word processors can't begin
to match:
g
g
g
g
g
=, EJ~- =- BORLAND
INTERNATIONAL
',1111 C
Includes tree
MicroCalc spreadsheet
with source code
5r'
5r'
Technical Specifications
Compiler: One-pass compiler generating native in- 5r' Development Environment: A powerful "Make" is
line code, linkable object morules and assembler.
included so that managing Turbo C program
The object module format is compatible with the
development is easy. Borland's fast "Turbo
PC-DOS linker. Supports small, medium, compact,
Linker" is also included. Also includes pull-down
large, and huge memory model libraries. Can mix
menus and windows. Can run from the environmodels with near and far pOinters. Includes
ment or generate an executable file.
floating point emulator (utilizes 8087/80287 if
5r' Links with relocatable object modules created
installed).
using Borland's Turbo Prolog into a
Interactive Editor: The system includes a powerful,
single program.
interactive full-screen text editor. If the compiler
5r' ANSI C compatible.
.
detects an error, the editor automatically positions 5r' Start-up routine ~ource ~ode Included ..
the cursor appropriately in the source code.
5r' Both. co~mand lIne and Integrated enVIronment
versIOns Included.
"Sieve" benchmark (25 iterations)
Compile time
Turbo C
Microsoftf'J C
3.89
16.37
13.90
29.06
27.79
Lattice C
9.94
Execution time
s.n
9.51
13.79
214
297
301
Price
$99.95
$450.00
$500.00
Benchmark run on a 6 Mhz IBM AT USing Turbo eversion 1.0 and the Turbo Linker version 1.0; Microsoft eversion 4.0 and the
MS overlay linker version 3.51; Lattice eversion 3.1 and the MS object linker version 3.05.
Minimum system configuration: IBM PC, XT, AT and true compatibles. PC-DOS (MS-DOS) 2.0 or later. One floppy drive. 320K.
Turbo C and Turbo Pascal are registered trademarks and Turbo Prolog is a trademark of Borland
International. Inc. Microson C and MS-DOS ife registered trademarks of Microson Corp. Lattice C
is a registered trademark of Lattice. Inc. IBM. Xl. and AT are registered trademarks of International
Business Machines Corp.
BOR 0243
If you're a scientist, engineer, financial analyst, student, teacher, or any other professional working with
equations, Eureka: The Solver can do your Algebra, Trigonometry and Calculus problems in a snap.
Eureka also handles maximization and minimization problems, plots functions, generates reports, and
saves an incredible amount of time. Even if you're not a computer specialist, Eureka can help you
solve your real-world mathematical problems fast, without having to learn numerical approximation
techniques. Using Borland's famous pull-down menu design and context-sensitive help screens, Eureka
is easy to learn and easy to use-as simple as a hand-held calculator.
Imagine you have to "solve for X," where X + exp(X) = 10, and you don't have Eureka: The Solver.
What you do have is a problem, because it's going to take a lot of time guessing at "X." With Eureka,
there's no guessing, no dancing in the dark-you get the right answer, right now. (Ps: X = 2.0705799,
and Eureka solved that one in .4 of a second!)
Eureka: The Solver is a trademark of Borland International, Inc. IBM, AT, and XT are registered
trademarks of International BUSiness Machines Corp. MS-DOS is a registered trademark of
Microsoft Corp. Copyright 1987 Borland International
BOR 0221 B
.,nrll'PI
.. :
THE DESKTOP
1J'"~n' Macintosh'M
~
ORBAN/IER Release 2.0
The most complete and comprehensive collection of
desk accessories available for your Macintosh!
Thousands of users already know that SideKick is the best collection of desk accessories available
for the Macintosh. With our new Release 2.0, the best just got better.
We've just added two powerful high-performance tools to SideKick-Outlook'": The Outliner
and MacPlan'": The Spreadsheet. They work in perfect harmony with each other and while you
run other programs!
~
~
~
~
~
~
~
~
~
~
1361~ Sall's ~
01594' Sooll'sB
II
[]
o
[D
~
o
IJ
0:1 X,fflm
Q3114 Labor
4(.e.1i Natff'\ill;
621-;11 Ovtl'h.~1f
111&'E TOl<1lllxl'fflSIS
".
1843'6 Hf.tF'ro(lt
Turbo Pascal lor the Mac does both Windows and "Units"
The separate compilation of routines offered by Turbo Pascal for the Mac creates modules called "Units,"
which can be linked to any Turbo Pascal program. This "modular pathway" gives you "pieces" which can
then be integrated into larger programs. You get a more efficient use of memory and a reduction in the
time it takes to develop large programs.
Turbo Pascal lor the Mac is so compatible with Lisa e that they should be living together
Routines from Macintosh Programmer's Workshop Pascal and Inside Macintosh can be compiled and run
with only the subtlest changes. Turbo Pascal for the Mac is also compatible with the Hierarchical File
System of the Macintosh.
The 27-second Guide to Turbo Pascal for the Mac
Compilation speed of more than 12,000 lines
per minute
"Unit" structure lets you create programs in
modular form
Multiple editing windows-up to 8 at once
Compilation options include compiling to disk or
memory, or compile and run
No need to switch between programs to compile
or run a program
Streamlined development and debugging
Compatibility with Macintosh Programmer's
Minimum system configuration: Macintosh 512K or Macintosh Plus with one disk drive.
Turbo Pascal and SideKick are registered trademarks of Borland International. Inc. and Reflex is a
registered trademark of Borland/Analytica. Inc. Macintosh is a trademark of Mcintosh Laboratories, Inc. licensed
to Apple Computer with its express permission. Lisa is a registered trademark of Apple Computer, Inc. Inside
MaCintosh is a copyright of Apple Computer. Inc.
Copyright 1987 Borland International BOA 0167A
1URBB PABCAl
TIITI'
QuickDraw
controls
g menus
g desk accessory support
g events
g windows
dialogs
g File Manager
g debugging
~:;o
BORLAND
~_.
INTERNATIONAL
Turbo Pascal and Turbo Tulor are reglslered Irademarks 01 Borland Inlernatlonal.lnc Other brand and product names
are trtidemarks or registered trademarks 01 the" respect"e holders Copyrlqht 1987 Borland Inlernallonal BaR 0381
of eventually!
Imagine you have to solve for X, where X +
exp(X) = 10, and you don't have Eureka: The Solver.
What you do have is a problem, because it's going
to take a lot of time guessing at X. With Eureka,
there's no guessing, no dancing in the darkyou get the right answer, right now. (PS: X =
2.0705799, and Eureka solved that one in less than
5 seconds!)
Some of Eureka's key features
You can key in:
51 A formula or formulas
51 A series of equations-and solve for
all variables
51 Constraints (like X must be < or = 2)
51 Functions to plot
51 Unit conversions
51 Maximization and minimization problems
51 Interest Rate/Present Value calculations
51 Variables we call "What happens?," like
"What happens if I change this variable to
21 and that variable to 27?"
51
51
51
51
51
51
51
51
51
1'.ERICAl.ETIII's
Turbo Pascal Numerical Methods Toolbox for the Macintosh
implements the latest high-level mathematical methods to solve
common scientific and engineering problems. Fast.
So every time you need to calculate an integral, work with Fourier transforms, or incorporate any of
the classical numerical analysis tools into your programs, you don't have to reinvent the wheel, because
the Numerical Methods Toolbox is a complete collection of Turbo Pascal routines and programs that
gives you applied state-of-the-art math tools. It also includes two graphics demo programs that use
least-square and Fast Fourier Transform routines to give you the picture along with the numbers.
The Turbo Pascal Numerical Methods Toolbox is a must if you're involved with any type of scientific or
engineering computing on the Macintosh. Because it comes with complete source code, you have total
control of your application at all times.
Differential equations
Least-squares approximations
Fourier transforms
Graphics
As well as a free demo of Fast Fourier Transforms, you also get the Least-Squares Fit in
five different forms-which gives you five different methods of fitting curves to a collection
of data pOints. You instantly get the picture! The five different forms are
1. Power
4. 5-term Fourier
2. Exponential
5. 5-term
3. Logarithm
Poynomial
They're all ready to compile and run as is.
Borland
Software
OBDEll rODAY
-----I
4585
95066
I
In
I ByTo Credit
Orde~ ,"'-", California
call .
I Card, ' ... , ' (800)
I (~:g)
742-1133
I 255-8008
In Canada call
(800) 237-1136
------BOA023~
Index
Index
A
A86 assembler, 84
Abs, 285, 374
Absolute clause, 223
Active window, 165
Actual parameters, 247
defined, 59
Addr, 286, 374
in version 3.0, 525
Address operators, 49
And operator, 241,308
AndPut constant, 316,459
ANSI Pascal, 75, 531-536
compatibility with 4.0, 119
errors in, 536
Append procedure, 275, 278, 374
Arc procedure, 318, 325, 375
ArcTan function, 285, 376
Arithmetic functions, 285
Arithmetic operators, 239
Arrays, 212, 231
types, 348
variables, 225
ASCII codes, 579-581
.ASM files, Make utility and, 89
Aspect ratio, 408
Assembler, 353
Assembly language, 82, 122, 353-361,
530,543
A86 and, 84
examples, 355-358
external procedures and functions,
83
inline directive, 83, 360-361
B
Back procedure, 325
Backup disks, 12-14
Backup source files option, 4, 160
default, 592
.BAK files, 4
Bar procedure, 318, 378
Bar3D procedure, 305, 318,379
Basic editor commands, 166
BCD arithmetic, 112, 119,527
BCD.PAS,119
$B compiler directive, 48, 98, 119,
121,158,522,529
.BCI files, 305
Binary floating-point arithmetic, 40
.BIN files, 111,530
BINOBJ, 14,467-471
BIOS, 298
BitBlt operations, 308, 316, 458
Bit images, 308, 416
Bit-mapped fonts, 307
Bit-oriented routines, 305
Bitwise operators, 47, 240
Block commands, 171
BlockRead procedure, 279, 380
Blocks, program, 201
BlockWrite procedure, 279, 381
Boolean, 39
c
Calling conventions, 349
Case statement, 52, 253
CBreak variable, 108, 112, 115,324,
523
.CFG files, 4
CGA, 300, 305, 314, 434-435
CheckSnow and, 302
Chain programs, 111,522
Change dir option, 152
Characters
reading, See ReadKey
special, 299, See also
Char data types
strings, 198
Char data types, 41, 208, 344
defined,39
ChDir procedure, 276, 382
CheckBreak variable, 112, 115, 301
CheckEOF variable, 301
CheckSnow variable, 302
.CHR files, 305
Chr function, 284, 383
Circle procedure, 305, 318, 325, 383
ClearDevice procedure, 318, 384
ClearScreen procedure, 325
ClearViewPort procedure, 318, 384
Index
TextMode, 506
variables, 301-303
WhereX, 512
WhereY, 512
Window,512
CSEG354
CSeg function, 111,286,354,389,526
CS register, 362, 389
Current pick option, 162
Current pointer, 306
Cursor position
reading, 512
setting, 427
Customizing Turbo Pascal, 12, 22,
585-600
CX register, 362
D
DATA, 354, See also DSEG
Data
defined, 38
ports, 361
segment, 222
Data types, 39-45,117
BCD,119
boolean, 39, 43,344
byte, 76
char, 39, 344
defined,39
8087,330
enumerated,344
integer, 39,76,344
longint,76
pointers, 39, 44
real numbers, 39
shortint, 76
string, 43
typecasting, 528
word, 76
Date and time procedures, 296-297
GetDate, 411
GetFfime, 414
GetTime, 424
SetDate, 482
SetFfime, 485
SetTime, 496
Index
GetTime, 424
interrupt support procedures, 296
Intr, 79,437
Keep, 439
MsDos, 79, 449
PackTime, 455
process-handling procedures and
functions, 297
SetFTime, 485
SetIntVec,488
SetTime, 496
types, 293
UnpackTime,510
DosError, 296, 398-399, 403, 412, 414,
483,485
DosExitCode, 297, 393
Double type, 76, 330, 345
Draw procedure, 325
DrawPoly procedure, 305, 319, 394
Drivers, 305
DSeg function, 111, 286, 354, 395, 526
DS register, 354, 359, 362, 395
DX register, 351, 362
Dynamic memory allocation, 290-291
functions, 283-284
Dynamic variables, See Heap
E
East constant, 325
Edit auto save option, 160
Edit window, 20, 25,146,165
creating source files in, 148
status line, 166
working in, 148
Editor commands, 145, 153, 166-176
option in TINST, 589-596
specifications, 165
summary of, 166-168
EGA, 29-31, 598-600
CheckSnow and, 302
8087, See Math coprocessor
Ellipse, 319, 395
ELSE
directive, 548
symbol, 94
$ELSE directive, 92, 94, 548
Index
F
Factor (syntax), 236
Far calls, 351, 530
menu option, 158
model, 539
Fatal runtime errors, 638
See also Errors
$F compiler directive, 121, 158,352,
522,530
Field designators, 226
Field list (of records), 214
Field-width specifiers, 50
File access denied error, 635
File attribute constants, 294
File menu, 26
Files
Assign procedure, 76, 377
attributes, 411
backup source, 4
buffer, 348-349
closing, 385
commands, 150-153
configuration, 4
debugging, 4
default settings, 4
erasing, 397
extension names, 3
handles, 348-349
1/0,290
library, 4
.MAP, 4
mode, 348-349
constants, 293
name macros, 559-561
pick,4
primary, 32
Read,75
record types, 293
saving, 152
source code, 4
text, 277
TPC.CFG,4
TPMAP.EXE,4
Turbo Pascal 3.0, 4
TURBO.TPL,4
typed,291
types, 348
unit, 3
untyped, 279, 291
Write, 75
File-handling procedures, 297, 534
Rename, 472
Reset, 472
Rewrite, 474
routines, 291
Seek,476
SetFAttr, 297, 482
Truncate, 509
FileMode variable, 279, 291
FilePos function, 279, 400, 524
FileRec, 293, 348
FileSeek function, 524
G
GetArcCoords procedure, 319, 407
GetAspectRatio procedure, 319,408
GetBkColor function, 321, 409
GetColor function, 321, 410
GetDate procedure, 296, 411
GetDir procedure, 276, 411
GetDotColor procedure, 326
GetFAttr procedure, 294,297,411
GetFillPattern procedure, 319, 412
GetFillSettings procedure, 319, 413
GetFfime procedure, 296, 414
GetGraphMode function, 321, 414
GetImage procedure, 305, 319,416
Get info option, 155
GetIntVec procedure, 296, 417
GetLineSettings procedure, 319, 417
GetMaxColor function, 321,418
GetMaxX function, 321,419
GetMaxY function, 321, 419
GetMem procedure, 284,342-343,420
GetModeRange procedure, 319, 421
GetPalette procedure, 319, 421
GetPic procedure, 326
GetPixel function, 308, 321, 422
Index
Get procedure, 75
GetTextSettings procedure, 307, 319,
423
GetTime procedure, 296, 424
GetViewSettings procedure, 319,424
GetX function, 321, 425
GetY function, 321, 426
Global declarations, 111
Glossary, 609-618
GotoXY procedure, 304, 427,523
Graph3 unit, 62, 69, 105, 116,289,
290, 324-327
GraphBackground procedure, 326
GRAPH.BIN, 325
GraphColorMode procedure, 326
GraphDefaults procedure, 319,428
GraphErrorMsg function, 321, 428
GraphFreeMem, 311
Graphics, 29
bit-image operations, 458
cards, 391,434-436
CloseGraph, 305
current pointer in, 306
drawing operations, 440-443, 458,
466,488
drivers, 305, 434-436
figures and styles in, 308
fill operations, 483-485
InitGraph in, 305
mode, 414, 434-436,441-442
page operations, 478, 499
palette operations, 479-481, 490
plotting operations, 461
pointer operations, 448
polygon,drawing, 394
routines, 82
sample program, 310-311
system operations, 486
text operations, 451-454, 493, 505
turtlegraphics, 116, 324-327
video mode operations, 473
viewport operations, 497
GraphMode procedure, 326
GraphMode variable, 433
GRAPH.P,325
GraphResult function, 308-309, 321,
429
GetImage, 416
GetLineSettings,417
GetMaxColor, 418
GetMaxX, 419
GetMaxY,419
GetModeRange, 421
GetPalette, 421
GetPixel, 422
GetTextSettings, 423
GetViewSettings, 424
GetX,425
GetY,426
GraphDefaults, 428
GraphErrorMsg, 428
GraphResult, 429
heap management routines, 311
ImageSize, 432
InitGraph, 434
interface section, 313-318
Line, 440
LineRel, 441
LineTo,442
MoveRel, 447
MoveTo,448
OutText, 451
OutTextXY, 453
paging in, 308
PieSlice, 456
procedures, 318-321
PutImage, 458
PutPixel, 461
Rectangle, 466
RegisterBGIdriver, 467
RegisterBGIfont, 468
RestoreCrtMode, 473
sample program, 310-311
SetActivePage, 478
SetAllPalette, 479
SetBkColor, 480
SetColor, 481
SetFillPattern, 483
SetFillStyle, 484
SetGraphBufSize, 486
SetGraphMode,486
SetLineStyle, 488
SetPalette, 490
SetTextJustify, 493
SetTextStyle, 494
SetUserCharSize, 496
SetViewPort, 497
SetVisualPage, 499
TextHeight, 505
text in, 307
TextWidth, 508
viewports in, 308
GraphWindow procedure, 326
GREP.COM,13,570-574
grError, 314, 430
grInvalidDeviceNum, 314, 430
grInvalidFont, 314, 430
grInvalidFontNum, 314, 430
grIOError, 314, 430
GROUP directives, 354
H
HaltOnError, 113
Halt procedure, 283, 369,431
Handles
DOS, 377-378
file, 348, See also
FileRec, TextRec
Hardware interrupts,362
Hardware numeric processing
option, 158,210,211
Heading procedure, 326
HeapError, 291, 343
Heap management, 335,337-344
allocating, 337, 338, 341-343
deallocating, 337-343
error trapping, See HeapError
fragmenting, 337-343
free list, 341-343
granularity,342
map,336
pointers, 336
procedures, 469
routines, 311
sizes, 121, 159, 182,544
trapping errors, 343
Heapmax, 544
Heapmin, 544
HeapOrg variable, 291, 338
HeapPtr variable, 291, 337-340, 341
Help, Turbo Pascal, 19
Hexadecimal constants, 40, 117, 197
HideTurtle procedure, 326
Hi function, 287, 431
High heap limit setting, 159
High-intensity characters, 432
High-order bytes, 431
HighVideo procedure, 112, 116, 304,
324,432
HiResColor procedure, 326
HiRes procedure, 326
Home procedure, 326
Hotkeys, 21-24
I
$1 compiler directive, 98, 112, 157,
161,276,438,522-523,526
Identifiers, 195-197
defined,45
Turbo3,107
Index
Integers
defined, 39-40
types, 344
Integrated environment
Build command, 32, 34
Compile menu, 26
compiling in, 27
context-sensitive help, 19
Debug command, 36
Destination setting command, 28
Edit window, 20, 25, 146
editor in, 165
File menu, 26
Find error command, 28, 36
Graph and, 31
graphics in, 29
hotkeys in, 21-24, 147
loading Turbo Pascal, 25
machine code in, 32
main menu commands, 145
main screen, 20
Make command, 32, 34
menu reference, 143-164
.OBJ files in, 34
Output window, 20, 27, 150
Primary file command, 32
quitting 21
Run command, 27, 29, 33
runtime errors, See Errors, runtime
saving files in, 26
selecting menu items, 24
syntax errors, See Errors, syntax
TINST and, 22
.TPU files in, 34
Tutorial, 25-36
using, 2, 12, 15, 19-36
variables, 26
Write to command, 29
Interface section (program), 271, 313,
322,352,354
Internal data formats, 335, 344
Interrupt
directives, 262
handlers, 362, 529
handling routines, 292, 362
procedures, 488
routines (lSR's), 362
support procedures, 296
J
Journal file, UPGRADE's, 108
Justification, font, 423
K
Kbd, 108, 112, 115,323,523,527
See also ReadKey
KBD:, 112
Keep procedure, 297, 439
Keyboard
operations, 439,464
scan codes, 583
status, 300
See also ReadKey
Key codes, 582
KeyPressed function, 300, 304, 439,
523
Keystrokes
changing commands, 589
changing control keys, 591-592
changing function keys, 591
L
Labels, 197,527
declaration part, 202
Language help
online, 176
Large programs, 631
managing, 85-98
Last text mode constant, 525
$L compiler directive, 63, 84, 158,
161,353,522,530,540
Length function, 118,286,440
Libraries
files, 4
program, 12
routines, 120
Line input, Crt, 299
Line numbers, in .MAP files, 539
Line procedure, 320, 440
LineRelprocedure,320,441
Line settings, 417
LineTo procedure, 320, 442
Link
assembly language, 353
buffer, 158,540
$L directive, 63
object file, 543
Ln function, 285, 443
Loading
options, 151, 162
pick files, 163
programs in 005, 602
Turbo Pascal, 25
Load options, 151, 162
Lo function, 287, 443
Logical operators, 48, 240
LongFile functions (3.0), 112, 524
LongFilePos function, 108, 115,324,
523
LongFileSize function, 108, 115,324,
523-524
Longint data type, 40, 76, 207
LongSeek function, 108, 115, 324, 524
Loops
defined, 39
for, 55
repeat..until,54
Index
while, 53
Low heap limit setting, 159
LowVideo procedure, 112, 116, 304,
324,444,523
LPT devices, 281, 292
LST:,l12
Lstfunction,l17,292,523
LstOutPtr, 523
M
Machine code, 32,358-361
Macros
inline,360-361
makefile,556-561
Main screen, integrated environment,
20
Make command, 3, 32, 34, 88, 154,
182
MAKE utility, 13,89-91
command-line options, 89-91, 549,
566
error messages, 567-569
syntax, 565
using, 565
Makefiles, creating, 549
.MAP files, 4,132-142,539,542
menu option, 158
Mark procedure, 284, 337-338, 444
MASM assembler, 84
Math coprocessor, 40, 76, 94,96, 119,
329-334,350,526-527,540
data types, 76
error messages, 632
evaluation stack, 332
menu option, 158
mode, 632
$N+ directive, 76, 119
MaxAvail function, 108, 112, 115, 121,
284,324,342,445,523
Maxlnt,39
$M compiler directive, 121, 159, 182,
336,438,445-446,522
Mem array, 361,530
MemAvail function, 108, 112, 115,
121,284,322,324,342,445,523
MemL array, 361, 530
N
$N compiler directive, 40, 76, 96,
119-120,158,373,522,527,529,632
Near calls, 351, 530
Nesting files, 522, 543
New option, 152
New procedure, 216, 284, 337, 343,
449
Nil,216,226,347
NormalPut constant, 316, 459
NormVideo procedure, 112, 116,304,
324,450,523
North constant, 325
NoSound procedure, 304, 450, 523
Not operator, 241, 308
o
Object directories option, 161, 186,
543
Object files, 353
linking with, 543
.OBJ files, 34, 353, 530
linking with, 543
MAKE utility and, 89
.PAS files, 4, 14
Odd function, 285, 450
Ofs function, 286, 451
Online help, 176
/0 option, 186
Op code, 358-360
Open function, 364
Operands, 235
Operations, defined, 38
Operators, 194,239-246
@,49
address, 49
arithmetic, 239
assignment, 46
binary, 46
bitwise, 47, 240
boolean, 241
defined,46
logical, 48, 240
makefile directives, 561
precedence of, 239
relational,47
set, 49
string, 49
unary, 46
Optimization of code, 97, 370-372
Options command, 143, 156-164
Options/Environment, in TINST, 596
Order of evaluation, 371
Ord function, 206, 209, 284, 451
Ordinal functions, 285
p
Packed (reserved ~ord), 212
Pack procedure, 284
PackTime procedure, 296, 455
DateTime and, 295
Palette procedure, 326
ParamCount function, 287, 455
Parameters, 266
actual,250
formal, 250
passing, 250, 349
untyped variables, 267
value, 267
variable, 267
Parameters option, 162
Parameter transfers, 332
ParamStr, 287, 455
.PAS files, 4,14
Pattern procedure, 326
PC-DOS, 601
.PCK file, 4
PenDo~n procedure, 326
PenUp procedure, 326
Periscope, 135-141
Pick files, 4, 162-164
list, 3
Pick list, 163-165
Index
editing, 25
execution options, 188
halting, 431
heading of, 269
lines, 200
parameters, 269
running, 27-32
saving, 26
structure of, 57, 85-97, 120, 521
syntax, 269
termination, 368
updating, 28
Program Segment Prefix (PSP), 291,
335
Project management, 85-97
Ptr, 286, 458
PUBUC,354
definition errors, 625
PutImage procedure, 305, 308, 320,
458
PutPic procedure, 326
PutPixel procedure, 308,320,461
Put procedure, 75
Q
Qualified identifiers, 196,204
Quiet mode UQ), 183
Quitting, Turbo Pascal, 21, 153
R
Random function, 287, 291, 461
Randomize procedure, 287, 462
Random number generator, 291
RandSeed function, 291
Range-checking, 98, 121, 157, 181,541
compile time, 372
errors, 128
Val and, 510
$R compiler directive, 98, 121,
156-157,522
Reading records, 380
Reading the keyboard, See ReadKey
ReadKey function, 112, 115, 117,300,
304,323,464
scope, 203
Run command, 27, 29, 33, 145, 153
Run in memory option, 188
Runtime errors, 126, 157, 634-638
Debug info option and, 155
Find error option and, 155
finding, 183-185
handling, See ExitProc
Runtime support routines, 290
s
SavelntOO, 291
Savelnt02, 291
Savelnt23,291
Savelnt24, 291-292
Savelnt75, 291
Save option, 152, 162
Saving
files, See Close option
pick files, 164
programs, 26
Scale factor, 198
Scan codes, keyboard, 583
$S compiler directive, 98, 157, 522
Scope (of declaration), 203-204
Screen
editor, 146-148, 153
mode control, 298
output operations, 298
routines, 79
size, 160, 597
Search utility, 13, 570
Searching directories, 403
SearchRec type, 295
Seek procedure, 276,279,476,525
SeekEof function, 278, 477
SeekEoln function, 278, 477
Seg function, 286, 477
Separate compilation, 2, 61-73, 99-104
Serial communications, 365
Serial ports, 365
SetActivePage procedure, 320, 478
SetAllPalette procedure, 320, 479
SetBkColor procedure, 320, 480
SetColor procedure, 320, 481
SetDate procedure, 296, 482
Index
deletion, 390
functions, 286, 436, 502, 510
handling, 290
initializing, 401
length byte, 347, 401
library routines, 118
maxrrnum length, 347
operator, 49, 242
parameters, relaxed checking, 542
procedures, 286
types, 347
variables, 225
Stroked fonts, 305, 307
Str procedure, 286, 502
Subdirectories, OOS, 604
Subroutines, 56
defined, 39
See also procedures and functions
Substrings
copying, 388
deleting, 390
inserting, 436
position of, 457
Succ function, 207,285,502
Swap function, 287, 503
Symbol definition, menu option, 158
Symbolic debugging, 13, 132,530
.MAP files, 539, 542
Symbols, 193
Syntax diagrams, reading, 195
Syntax errors, See Errors, syntax
Syntax, MAKE, 565
System unit, 62, 65,68,112,270,
289-292, 373
T
Tabs default, 597
Tab size option, 160
Tag field (of records), 214
$T compiler directive, 4, 132, 183,
522,530
/$T directive, 185
Terminating a program, 368, 399
Terms (syntax), 237
Text, 307
attributes, 423
Index
u
$U compiler directive, 34, 70, 270,
522,544
$UNDEF directive, 92, 546-547
Unit directories option, 70, 100, 161,
187,544
Units, 2, 3, 12-13, 61-73
Build option, 88
compiling, 34, 70, 88-91
converting from 3.0 and, 106,
109-111,522
Index
dependencies, 290
8087 and, 334
file name, 544
forward declarations and, 63
global, 72, 85
large programs and, 72, 85-97
heading, 271
identifier, 196
implementation section, 63
initialization section, 64
initializing, 86
inserting, 102
interface section, 62
Turbo 3.0 and, 111
large programs and, 71, 85-97
Make option, 88
merging, 70
mover utility, 99-104
overlays and, 109, 111
removing, 103
scope of, 203
specify location of, 544
standard, 289
Crt, 62, 68, 79, 298
Dos, 62, 68, 77
Graph,31,62,69,82,305
Graph3,62;69, 105, 116,324
Printer, 62, 69
System, 62, 65, 68
Turbo3, 62,69, 105, 107,322-324
syntax, 271
.TPL file, 99
.TPU file, 70-71, 99
TPUMOVER,72
TURBO.TPL file, 62, 68, 70, 72
inserting into, 102
removing from, 103
Unit directories option, 70, 100
uses statement, 62, 65, 70
using units, 274
version mismatch errors, 628
version number, 274
writing, 70
Unpack procedure, 284
UnpackTime, 297, 510
DateTime and, 295
Unsigned
constant, 237
integer, 198
number, 198
real, 198
Untyped files, 291, 348
variable, 380-381
Untyped var parameters, 267
IU option, 187
UpCase function, 287, 510
UPGRADE.DTA,106
UPGRADE.EXE, 13
comments, 109, 111
options, 110
using, 105-114
warnings, 108, 111-112
Uses statement, 34, 65, 70,270,290
path to units, 544
Usr,523
USR:,l12
UsrInPtr,523
UsrOutPtr,523
Utilities
BINOB}, 575-577
Build, 3
GREP, 13,570-574
MAKE, 3, 89-98, 549-569
TINST, 12, 585-600
TOUCH, 13,569-570
TPMAP, 13,542
TPUMOVER, 13, 72-73
UPGRADE, 13, 105-113
v
Val procedure, 286, 510
range-checking and, 510
Value parameters, 267,350-351
Value typecasts, 248
Variable-length buffers, 120
Variables, 26, 221-228
absolute, 223
CheckBreak, 301
CheckEOF,301
CheckSnow, 302
declaration part, 201-202
declarations, 221
decrementing, 389
DirectVideo, 302
disposing of, 392, 406
DosError, 296, 398, 403, 412, 414,
483,485
dynamic, 216, 226
global, 222
incrementing, 433
initializing; 64,229
local, 222
Lst,292
parameters, 267, 350
pointer, 226
record, 226
reference, 223
TextAttr, 303
typecast, 226
Wind Max, 303
WindMin, 303
Variant part (syntax), 214
Var parameter checking, 98
Var parameters, 267, 350
Var-string checking option, 158,542
$V compiler directive, 98, 158,542
VER40, 93, 546
Version 3.0, See Turbo Pascal 3.0
VGAHi, 421, 435, 480
VGALo, 421, 435, 480
VGAMed, 421, 435, 480
VGA modes, 421, 435, 480
Video memory, 298
Video modes, changing, 597
Video operations
AssignCrt, 378
CirEoI,386
CisScr,387
DelLine, 390
GoToXY,427
HighVideo, 432
InsLine,437
LowVideo,444
NormVideo, 450
RestoreCrtMode, 473
TextBackground, 504
TextColor, 504
WhereX,512
WhereY,512
Window, 512
Write (text), 513
Write (typed), 516
Writeln, 516
Viewport parameter, 424
Viewports, 308, 384
w
West constant, 325
WhereX function, 304, 512
WhereY function, 304,512
While (syntax), 255
loop, 53
WindMax variable, 303
WindMin variable, 303
Window procedure, 298, 303, 512,
523
current coordinates, 303
Windows, 298, 600
active, 165
compilation, 156
Edit, 146, 156, 165
graphics, See SetViewPort
Output, 150
zoom, 160
With statements, 258
Word alignment, 354
Word data type, 40, 76
WordStar, Turbo Pascal editor vs. 176
Index
x
XCor procedure, 327
IX option, 189
Xor operator, 241, 308
XorPut, 316, 459
y
YCor procedure, 327
z
Zoom windows option, 160, 597
~..
I
(g~;;tm,~.
' " . {f&fJj]m
(J]lJ[jjjfii!J1:f ;11f!i!1[jj