Free Pascal Square One Vol 1
Free Pascal Square One Vol 1
by Jeff Duntemann
Revision of 2/1/2010
Repeat...
Until...
This work is licensed under the Creative Commons Attribution-Share alike 3.0
United States License. To view a copy of this license, visit this Web link:
http://creativecommons.org/licenses/by-sa/3.0/us/
or send a letter to:
Creative Commons
171 Second Street, Suite 300
San Francisco CA 94105 USA
Y essir, the book you’re reading has been around the block a few times since
I began writing it in November of 1983—which I boggle to think was over
twenty-five years ago. It’s been through four print editions and on paper sold over
125,000 copies. It’s been translated into five languages.
Now it’s time set it free.
Pascal was not my first programming language. That honor belongs to FORTH,
though I don’t admit it very often. FORTH struck a spark in my imagination, but
it burned like a pile of shredded rubber tires, leaving a stink and a greasy residue
behind that I’m still trying to get rid of. BASIC came next, and burned like dry pine;
with fury and small explosions of insight, but there was more light than heat, and
it burned out quickly. BASIC taught me a lot, but it didn’t take me far enough, and
left me cold halfway into the night.
Pascal, when I found it, caught and burned like well-seasoned ash: Slow, deep,
hot; I learned it with a measured cadence by which one fact built on all those before
it. 1981 is a long time gone, and the fire’s still burning. I’ve learned a lot of other
languages in the meantime, including C, which burns like sticks of dynamite: It
either digs your ditch or blows you to Kingdom Come. Or both. But when something
needs doing, I always come back to Pascal.
When I began writing Pascal From Square One in the fall of 1983, I had no particular
compiler in mind. There were several, and they were all (by today’s standards)
agonizingly bad. The best of the bunch was the long-extinct Pascal/MT+, and I used
that as the host compiler for all of my example code. The book, however, was about
Pascal the language: How to get started using it; how to think in Pascal; how to see
the language from a height and then learn its component parts one by one.
When I turned the book in at the end of summer 1984, my editor at Scott,
Foresman had a radical suggestion: Rewrite the book to focus not on Pascal the
language but on Turbo Pascal the product. The maverick compiler from Scotts
Valley was rapidly plowing all the other Pascals into the soil, and he smelled a new
and ravenous audience. I took the manuscript back, and by January of 1985 I had
5
6 FreePascal from Square One, Volume 1
rewritten it heavily to take into account the numerous extensions and peccadilloes
of Borland’s Turbo Pascal compiler, version 2.0.
The book was delayed getting into print for several months, and as it happened,
Complete Turbo Pascal was not quite the first book on the shelves focusing on Turbo
Pascal. It was certainly the second, however, and it sold over 125,000 copies in the
four print editions that were published between 1985 and 1993. The Second Edition
of Complete Turbo Pascal (“2E”, as we publishing insiders called it) came out in 1986,
and addressed Turbo Pascal V3.0.
By March 1987 I had moved to Scotts Valley, California and was working for
Borland itself, creating a programmer’s magazine that eventually appeared in the
fall of 1987 as Turbo Technix. Doing the magazine was a handful, and I gladly let
others write the books for Turbo Pascal 4.0. I had the insider’s knowledge that V5.0
would come soon enough, and change plenty, so I worked a little bit ahead, and
Complete Turbo Pascal, Third Edition was published in early 1989.
It’s tough to stay ahead in this business. Turbo Pascal 5.5 appeared in May of 1989,
largely as a response to Microsoft’s totally unexpected (but now long-forgotten)
QuickPascal. V5.5 brought with it the new dazzle of object-oriented programming,
and while I did write the V5.5 OOP Guide manual that Borland published with the V5.5
product I chose to pass on updating Complete Turbo Pascal for either V5.5 or V6.0.
The magazine Turbo Technix folded after only a year, and I left Borland at the
end of 1988, wrote documentation for them until the end of 1989, and moved to
Arizona in February of 1990 to start my own publishing company. This included
my own programmers’ magazine, PC Techniques, which became Visual Developer in
1996 and ran until early 2000.
The early 1990s saw some turbulence in the Pascal business. Borland retired
the “Turbo Pascal” brand and renamed their flagship product Borland Pascal.
The computer books division of my publisher, Scott Foresman, was engulfed and
devoured by some other publisher. Complete Turbo Pascal was put out of print, and I
got the rights back. An inquiry from Bantam Books in 1992 led to my expanding
Complete Turbo Pascal into a new book focused on Borland Pascal 7. I was able to re-
title the book Borland Pascal 7 From Square One (the title Complete Turbo Pascal had been
imposed by Scott, Foresman) and bring it up to date. That edition didn’t sell well
because by 1994, Borland had created Delphi, and most of us considered the DOS
era closed. I began writing books about Delphi and never looked back.
And so it was for almost 15 years. I considered just posting the word-processor
files from Borland Pascal from Square One a few years ago, but figured that no one was
using Pascal all by itself anymore. Not so. I first saw FreePascal in 1998 and tried it
from time to time, but it wasn’t until January 2008 that Anthony Henry emailed me
How This Book Came to Be 7
to suggest that FreePascal could use a good tutorial, and it shouldn’t be too hard to
update Borland Pascal 7 from Square One to that role. He was right—and the project
has been a lot of fun.
I mention all this history because I want people to understand where FreePascal
from Square One came from, emphasizing that it’s been a work in progress for 25 years.
Why stop now? I don’t have to cater to publishers, paper costs, print runs, or release
schedules anymore. The book can evolve with the compiler, and every so often you
can download the latest update. My publishing company Copperwood Press offers a
print-on-demand paper edition if you’d like one, but you can print it yourself if you
prefer. That’s how technical publishing ought to be, and someday will be.
If...Then...Else...
9
10 FreePascal from Square One, Volume 1
Chapter 1.
The Box
that Follows a Plan
T here is a rare class of human being with a gift for aphorism, which is the ability
to capture the essence of a thing in only a few words. My old man was one; he
could speak volumes in saying things like, “Kick ass. Just don’t miss.” Lacking the
gene for aphorism, I write books—but I envy the ability all the same.
The patron aphorist of computing is Ted Nelson, the eccentric wizard who
created the perpetually almost-there Xanadu database system, and who wrote the
seminal book Computer Lib/Dream Machines. It’s a scary, wonderful work, in and out
of print for thirty years but worth hunting down if you can find it. In six words, Ted
Nelson defined “computer” better than anyone else probably ever will:
A computer is a box that follows a plan.
We’ll come back to the box. For now, let’s think about plans, where they come
from, and what we do with them.
11
12 FreePascal from Square One, Volume 1
Read email.
Pay bills.
Put money into checking account if necessary.
Get cash at ATM.
Go to Home Depot.
Get Thompson’s Water Seal.
Get 2 4’ flourescent bulbs.
Get more steel wool if we’re out.
Get more #120 sandpaper if we’re out.
Get birthday present for Brian. Bookman Books? He likes ghost towns.
Put together grocery list. Go to Safeway for groceries.
Sand rough spots on the deck.
Water seal the deck.
See if my back-ordered water filter cartridge is in at Shouse; call first.
Replace refrigerator water filter cartridge if they have it.
Take the empty grill propane tank in and get a full one.
Do what laundry needs doing.
Go to the gym and swim fifty laps.
That’s a lot to ask of one day. If it’s going to be done, it’s going to have to be done
smart, which is to say, in an efficient order so that as little time and energy gets lost
in the process as possible. In other words, to get the most out of a day, you’d better
have a plan.
Pay bills.
Call and add money to checking account if required based on balance.
Check in the garage for steel wool and #120 sandpaper.
Put together grocery list.
Call Shouse Appliance to see if the filters are in.
Check oil in the 4Runner. Add if necessary.
Run errands:
Go up Nevada to hit Home Depot first.
Get Thompson’s Water Seal.
Get 2 4’ flourescent bulbs.
Get more steel wool if we’re out.
Get more #120 sandpaper if we’re out.
Swap out empty propane tank.
14 FreePascal from Square One, Volume 1
Pay bills.
Replenish checking account from savings.
Put together grocery list.
Put together a Home Depot list.
Call Shouse Appliance to see if the filters are in.
Check in the garage for steel wool and #120 sandpaper.
Check oil in the Magic Van. Add if necessary.
Run errands:
Home Depot.
Bookman Books.
Shouse Appliance
Safeway.
Sand and water seal the deck.
If I get it, replace water filter cartridge behind refrigerator.
Do what laundry needs doing.
Read EMAIL.
Swim fifty laps at gym.
Collapse!
Look carefully at the differences between this list and the previous list. Mostly
I’ve condensed obvious, common-sense things that I was unlikely to forget. I’ve
been to the various stores so often that I could do it asleep, so there’s really little
point in giving myself driving directions. I have an intuitive grasp of where all the
stores are located, and I can plot a minimal course among them all without really
thinking about it. At best, the order in which the stores are written down jogs my
memory in the direction of that optimal course.
I combined items that always go together. Paying bills and adding money back
into my checking account are things I always do together; to do otherwise risks
disorder and insufficient funds.
I pulled details out of the “Home depot” item and instead added an item further
up the plan, reminding me to “Make a Home Depot list.” If I was already going to put
together a grocery list, I figured I might as well flip it over and put a hardware-store
list on the other side. There’s a lesson here: Plan-making is something that gets
better with practice. Every time you draft a plan, you’ll probably see some way of
improving it.
16 FreePascal from Square One, Volume 1
On the other hand, sooner or later you have to stop fooling around and execute
the plan.
I’m saying all this to get you in the habit of looking at a plan as something that
works at different levels. A good plan can be reduced to an “at-a-glance” form that
tells you the general shape of the things you want to do today, without confusing
the issue with reams of details. On the other hand, to be complete, the plan must
at some level contain all necessary details. Suppose I had sprained an ankle out in
the garage and had to have someone else run errands in my place? In that case, the
detailed plan would have been required, down to and perhaps including detailed
driving directions to the various stores.
Had Carol been the one to take over errand-running for me, I might not have
had to add a lot of detail to my list. When you live with a woman for thirty years,
you share a lot of context and assumptions with her. But had my long-lost cousin
Tony from Wisconsin been charged with dashing around Colorado Springs doing
my day’s errands, I would have had to write pages and pages to make sure he had
enough information to do it right.
Or if my very distant relative Heinz Duntemann from Dusseldorf were visiting, I
would have had to do all that, and write the plan in German as well.
Or...if my friend Hkrepats from Tau Ceti V (who neither knows nor cares what a
wood deck is, and might consider Thompson’s Water Seal a species of sports drink)
volunteered to run errands for me, I would have had to explain even the minutest
detail (over and above the English language and alphabet), including what stop
lights mean, how to drive, our decimal currency (Hkrepats has sixteen fingers and
counts in hex) and that cats are pets, not hors d’oerves.
To summarize: The shape of the plan—and the level of detail in the plan—
depends on who’s reading the plan, and who has to follow it. Remember this. We’ll
come back to it a little later.
I’m not going to go into a tremendous amount of detail here as to the electrical
internals of computers. If you’re curious about such things, you might pick up my
earlier book Assembly Language From Square One (John Wiley & Sons, 2000; available
on Amazon) and read its first several chapters, which take some pains to explain the
CPU chip and computer memory in plain language.
Left to her own devices, Emily does nothing but sit in one place. However, if you
take a card full of instructions and insert the card into the slot on Emily’s lid and
press the “GO” button, Emily zips off on her own, stopping and going and turning
and reversing. She’s following the instructions on the card. Eventually she reaches
and obeys the last instruction on the card, and simply stops where she is, waiting
for another card and another press of the “GO” button.
Figure 1.2 shows one of Emily’s instruction cards. The card contains thirteen
rows of eight holes. In the figure, the black rectangles represent holes punched
through the card, and the white rectangles are places where holes could be punched,
but are not. Underneath the slot in Emily’s lid is a mechanism for detecting holes
by shining eight small beams of light at the card. Where the light goes through
and strikes a photocell on the other side, there is a hole. Where the light is blocked,
there is no hole.
The holes can be punched in numerous patterns. Some of the patterns “mean
something” to Emily, in that they cause her machinery to react in a predictable way.
When Emily’s internal photocells detect the pattern that stands for “Go forward 1
foot” her motors come on and move her forward a distance of one foot, then stop.
Similarly, when Emily detects the pattern that means “Turn right,” she pivots on
one motor, turning to the right. Patterns that don’t correspond to some sort of
action are ignored.
The Box That Follows a Plan 19
The card shown in Figure 1.2 describes a plan for Emily. It is literally a list of things
that she must do, arranged in order from top to bottom. The arrow shows which end
of the card must be inserted into Emily’s card slot, with the cut corner on the left.
Once the card is inserted into the slot in her lid, a press on her “GO” button sets her in
motion, following the plan as surely as I followed mine by jumping into the 4Runner
and heading off down Nevada Street to do my Saturday morning errands.
When Emily follows the plan outlined on the card, she moves in the pattern
shown in Figure 1.3. It’s not an especially sophisticated or useful plan—but then
again, there’s only room for thirteen instructions on the card. With a bigger
card—or more slots to put cards into—Emily could execute much longer and more
complex programs.
20 FreePascal from Square One, Volume 1
Go forward 1 foot
Go forward 10 feet
Turn left
Turn right
The Box That Follows a Plan 21
There’s no instruction to stop; when Emily runs out of instructions, she stops
automatically.
Now, Emily is a little more sophisticated than this one simple card might
indicate. Over and above the four instructions shown above, Emily “understands”
four more:
Go backward 1 foot
Go backward 10 feet
Rotate 180°
Sound buzzer
When you want to punch up a new card for Emily to follow, you must choose
from among the eight instructions in Emily’s instruction set. That’s all she knows,
and there’s no way to make her do something that isn’t part of the instruction set.
However, it isn’t always completely plain when something is or isn’t part of the
instruction set. Suppose you want Emily to move forward seven feet. There’s
no single instruction in Emily’s instruction set called “Go forward seven feet.”
However, you could put seven of the “Go forward 1 foot” instructions in a row, and
Emily would go forward seven feet.
22 FreePascal from Square One, Volume 1
But that would take seven positions on the card, which only has thirteen
positions altogether. Is there a way to make Emily move forward seven feet without
taking so many instructions?
Consider the full instruction set, and then consider this sequence of
instructions:
Go forward 10 feet
Go backward 1 foot
Go backward 1 foot
Go backward 1 foot
It’s the long way around, in a sense, but the end result is indeed getting Emily to a
position seven feet ahead of her starting point. It takes a little longer, timewise, but
it only uses up four positions on the card.
This is a lot of what the skill of programming involves: Looking at the computer’s
instruction set and choosing sequences of instructions that get the job done. There
is usually more than one way to do any job you could name—and sometimes an
infinite number of ways, each with its own set of pluses and minuses. You will find,
as you develop your skills as a programmer, that it’s relatively easy to get a program
to work—and a whole lot harder to get it to work well.
created the 80286, but the remarkable thing was that it only added capabilities—
Intel took nothing away. The 80286’s instruction set is larger than the 8088’s, but it
also contains the 8088’s. That being the case, anything that runs on an 8088 also
runs on an 80286. This has been the case as Intel’s product line has evolved down
the years through the 80386, 80486, and the many varieties of Pentium. All the
instructions available in Intel’s original 8086/8088 instruction set are still there
in the latest Pentium 4. (Whether programs written for the 8088 will run on a
Pentium 4 really depends more on the operating system than the CPU chip.)
Emily Mark II
We can return to Emily for a more concrete example. Once we’ve played with Emily
for a few months, let’s say we dismantle her and rebuild her with more complex
circuitry to do different things. We add more sophisticated motor controls that
allow Emily to make half-turns (45°) instead of just full 90° left and right turns. This
alone allows tremendously more complex paths to be taken.
But the most intriguing addition to Emily is an electrically operated “tail” that
can be raised or lowered under program control. Attached to this tail is a felt-tip
reservoir brush, much like the ones sign painters use for large paper signs. One new
instruction in Emily’s enlarged instruction set lowers the brush so that it contacts
the ground. Another instruction raises it off the ground so that it remains an inch
or so in the air.
If we then put down large sheets of paper in the room where we test Emily, she
can draw things on the paper by lowering the brush, moving around, and then
raising the brush. Emily can draw a 1-foot square by executing the following set of
instructions:
Lower brush
Go forward 1 foot
Turn right
Go forward 1 foot
Turn right
Go forward 1 foot
Turn right
Go forward 1 foot
Raise brush
The whole point I’m making here is that a computer program is a plan for action,
and the individual actions must be chosen from a limited set that the computer
understands. If the computer doesn’t understand a particular instruction, that
instruction can’t be used. Sometimes you can emulate a missing instruction by
combining existing instructions to accomplish the same results. We did this earlier
by using several instructions to make Emily act as though she had a “Move forward
seven feet” instruction. Often, however, that is difficult or impossible. How, for
example, might you make Emily perform a half-left turn by combining sequences
of her original eight instructions? Easy. You can’t.
This is one way to understand the limitations of computers. A computer has a
fundamental instruction set. This instruction set is fairly limited, and the individual
instructions are very tiny in their impact. An instruction, for example, might simply
add 1 to a location in memory. Through a great deal of cleverness, this elemental
instruction set can be expanded enormously by combining a multitude of tiny,
limited instructions into larger, more complex instructions. One such mechanism
is the subject of this book: FreePascal, as I’ll come to show in the next chapter.
The Box That Follows a Plan 25
D:
CD \PARADOX3\PERSONAL
VHR MDS /N
PARADOX3
It’s not much, but it saved me having to type these four lines every time I wanted
to update someone’s phone number in my address book database. (We forget
sometimes what tremendous time savers Windows and Mac OS have been by
handling things like that for us, and retaining applications in memory for quick use
at any time.) The first command shown above moves me to the D: hard disk drive.
The second command moves me into the subdirectory containing my address
book database. The third command invokes a special utility program that resets
and clears the unusual monitor and video board that I used for years in the DOS era.
The fourth and last line invokes the Paradox 3.0 database program.
Yes, DOS batch files are ancient and little-used these days, but they perfectly
illustrate my point: Like most people’s “do-it” lists, DOS batch files run straight
through from top to bottom, in one path only.
on your grocery list. Now when you get to Safeway, suppose it’s late in the day and
the poppy-seed rolls are long gone. You’re faced with a decision: What to buy? If
you’re having hamburgers for supper, you need something to put them on. So you
buy Mother Ersatz’ Genuine Bread-Flavored Imitation Hamburger Buns. You didn’t
write it down this way and may not even think of it this way, but your “do-it” list
contains this assumed entry:
Then again, if Mother Ersatz’ products make your tummy breakdance all night
after supper, you might change your whole supper strategy, leave the frozen
hamburg in the freezer, and gather materials for stir-fry chicken instead:
Most of the time we perform such last-minute decision-making “on the fly,”
hence we rarely write such detailed decisions down in our original and carefully
crafted “do-it” lists. Most of the time, Safeway will have the poppy-seed rolls and we
operate under the assumption that they will always be there. We think of “Plan B”
decisions as things that happens only when the world goes ballistic on us and acts
in an unexpected fashion.
In computer programming, such decisions happen all the time, and programming
would be impossible without them. In a computer program, little or nothing can
be assumed. There’s no “usual situation” to rely on. Everything has to be explained
in full. It’s rather like the situation that would occur if I sent Hkrepats the alien out
shopping for me. I’d have to spell the full decision out in great detail:
four, I start making tick marks on a piece of scratch paper for each however much
of whatever I throw into the bowl. This makes for much better cakes. (Or at least
more predictable ones.)
You might write out (for cousin Heinz or perhaps Hkrepats the alien) this part of
the plan like so:
This is another element that you’ll see very frequently in Pascal programming.
It’s called a FOR..DO loop, and we’ll return to it later in this book.
Dig the scoop into the jelly beans and fill it.
Take the full scoop over to the digital scale.
Repeat the following:
Shake a few jelly beans from the scoop into the scale’s bowl;
Until the scale’s digital readout reads 0.25 pounds.
Exactly how many times Mary Jo has to shake the scoop over the scale depends
on what kind of a shaker she is. If she’s new on the job and cautious because she
doesn’t want to go too far, she’ll just shake one or two jelly beans at a time onto the
scale. Once she wises up, she’ll realize that going over the requested weight doesn’t
matter so much, and she’ll shake a little harder so that more jelly beans drop out of
The Box That Follows a Plan 29
the scoop with each shake. This way, she’ll shake a lot fewer times, and when she
ends up handing you half a pound of jelly beans, that’s OK—since one can’t ever
have enough broccoli-flavored jelly beans, now, can one?
Computers, of course, do mind when they go over the established weight limit,
and they don’t mind making small shakes if that’s what it takes to get the final
weight bang-on. A computer, in fact, is a tireless creature, and would probably
shake out only one bean at a time, testing the total weight after each bean falls
into the bowl.
This sort of loop is called a REPEAT..UNTIL loop, and it’s also common in
Pascal programming, as I’ll demonstrate later on in this book.
But there’s another reason: Thinking of code and data as “doing” and “knowing”
leaves out an essential component: The gizmo that does the doing and the knowing;
that is, the computer itself. I recommend that you always keep the computer in the
picture, and think of the computer, code, and data as an unbreakable love triangle.
No single corner is worth a damn without both of the other two. Between any two
corners you’ll read what those two corners, working together, create. See Figure
1.6.
In summary: The program code is a series of steps. The computer takes these
steps, and in doing so manipulates the program’s data.
Let’s talk a little about the nature of data.
Let X be...
A lot of people shy away from computer programming due to math anxiety. Drop
an “X” in front of them and they panic. In truth, there’s very little math involved
in most programming, and what math there is very rarely goes beyond the high-
school level. In virtually all programs you’re likely to write for data processing
purposes (as opposed to scientific or engineering work) you’ll be doing nothing
more complex than adding, subtracting, multiplying, or (maybe) dividing—and very
rarely taking square roots.
What programming does involve is symbolic thinking. A program is a series
of steps that acts upon a group of symbols. These symbols represent some reality
existing apart from the computer program itself. It’s a little like explaining a point
in astronomy by saying, “Let this tennis ball represent the Earth, and this marble
represent the Moon...” Using the tennis ball and the marble as symbols, you can
show someone how the moon moves around the earth. Add a third symbol (a
soccer ball, perhaps) to represent the Sun, and you can explain solar eclipses and
the phases of the Moon. The tennis ball, marble, and soccer ball are placeholders
for their real-life rock-and-hot-gas counterparts. They allow us to think about
the Earth, Sun, and Moon without getting boggled by the massiveness of scale on
which the solar system operates. They’re symbols.
In both instances, the variable itself is simply a place somewhere inside the
computer where you can store a number. What’s important is the mask of meaning
that you place in front of that variable. The variable contains a number—and that
number represents something.
This is the fundamental idea that underlies all computer data items. They’re all
buckets with names—for which you provide a meaning.
CPU and is much slower to read from and write to. Balancing that disadvantage is
the fact that disk storage is cheap and (better still) once something is written onto a
disk, it stays there until you erase it or write something over it.
Input and output are similar, and differ mainly in the direction that information
moves. Your keyboard is an input device, in that it sends data to the CPU when you
press a key. Your screen is an output device, in that it puts up on display information
sent to it by the CPU. The parallel port to which you connect your printer is another
output device, and your Ethernet network port swings both ways: It both sends and
receives data, and thus is both and input and an output device at once.
If you press the “Y” key, one road at the fork will be taken, and that fork leads to
the end of the program. If you press the “N” key, the other road at the fork will be
taken, back into the program to do some more work.
Programs like this are said to be interactive, since there’s a constant conversation
going on between the program and you, the user. Inside the computer, the program
The Box That Follows a Plan 35
is threading its way among a great many possible paths, choosing a path at each
fork in the road depending on questions it asks you, or else depending on the results
of the work it is doing.
Sooner or later, the program either finishes its work or is told by you to pack
up for the day, and it “exits,” which means that it returns control to the operating
system, whatever the operating system might be.
It would be like buying a birdhouse kit, opening the package, leaving the opened
package on the shelves, and then traipsing over the to shelves to pull each piece out
of the birdhouse kit as you need it while assembling the birdhouse.
That’s dumb. The CPU would instead take the entire kit to the workbench and
assemble it there, only going back to the shelves for something too big to fit on the
workbench, or to find something it hadn’t anticipated needing.
One final note on our metaphor: The CPU has a number of storage locations that
are actually inside itself, closer even than RAM. These are called registers, and they
are like the pockets in a crasftman’s apron. Rather than placing something back on
the workbench, the craftsman can tuck a small tool or part conveniently in a pocket
for very quick retrieval a moment later. The CPU has a few such pockets, and can
use them to tuck away a number or a character for a moment.
So there are actually three different types of storage in a computer: Disk storage,
RAM, and registers. Disk storage is very large (these days, hundreds of billions of
bytes is not uncommon in hard drives) and quite cheap—but the CPU has to spend
considerable time and effort getting at it. RAM is much closer to the CPU, but it is
a lot more expensive and rarely anything near as large. Few computers have more
than 2 or 4 gigabytes of RAM these days. Finally, registers are the closest storage
to the CPU, and are in fact inside the CPU—but there are only a half dozen or so of
them, and you can’t just buy more and plug them in.
There was, in fact, an intriguing software product available years ago called “Karel
the Robot” which was in fact a simulation of a robot on the computer screen. Karel
could be given commands and would follow them obediently, and the net effect was
a very good education on the nature of computers.
This chapter has been groundwork, basically, for people who have had absolutely
no experience in programming. All I’ve wanted to do is present some of the
fundamental ideas of both computing and programming, so that we can now dive
in and get on with the process of creating our program metaphors in earnest.
38 FreePascal from Square One, Volume 1
Chapter 2.
The Nature of
Software development
A s I hinted in the last chapter, a computer program is a plan, written by you, that
the computer follows in order to get something done. The plan consists of a
series of steps that must be taken, and some number of decisions to be made along
the way when a fork in the road turns up.
That’s programming in the abstract, as simply put as possible. There are a lot of
ways of actually writing a program, each way focusing on a different programming
language. In this book, I’ll be talking about only one programming language, the
one called Pascal. Furthermore, I’ll be focusing on only one single “dialect” of that
language, FreePascal. FreePascal is itself very similar to the venerable Turbo Pascal
from Borland, which has been with us since 1983. Nearly all program code written
for Turbo Pascal (including Turbo Pascal’s big brother Borland Pascal) will compile
and run correctly under FreePascal.
This is not a limitation. Borland’s Pascal implementations pretty much plowed
all other Pascal dialects under the soil. If you’re going to learn Pascal programming
at all, you might as well learn the dialect comprising probably 95% of all Pascal
compilers ever sold.
Look no further. You won’t find anything better.
39
40 FreePascal from Square One, Volume 1
Assembly language
The fast answer is that computers understand something called “assembly language,”
in which each step in the plan is one of those fundamental machine instructions I
described conceptually in Chapter 1. Machine instructions are incredibly minute in
what they do; for example, a single instruction may do nothing more than fetch a
byte of data from a location in RAM and store it in a location inside the CPU called
register AX. It takes an enormous number of such instructions to do anything useful;
hundreds or thousands for small programs, and many hundreds of thousands or
even millions for major application programs like Microsoft Excel or AutoCAD.
The instructions themselves are terse, cryptic, and look more like something
copied out of a mad scientist’s notebook than anything you or I would call a
language:
MOV EAX,[EBX]
SUB EAX,EDX
AND EAX,0FF0DH
DEC ECX
LOOPNZ MSK13
Actually, the frightening truth is that even these cryptic statements are
themselves “masks” for the true machine instructions, which are nothing more than
sequences of 0’s and 1’s:
0110101000110010
0000000101110011
1110111110011011
0110110110001010
It’s possible to program computers by writing down sequences of 0’s and 1’s
and somehow cramming them into a computer through toggle switches, with an
“up” switch for a “1” and a “down” switch for a “0”. I used to do this in 1976 (for my
home-made computer called the COSMAC ELF) and thought it was great good fun,
because back then it was the best that my machine and I could do.
Is it really fun?
Mmmmm...no. In truth, it gets old in a big hurry. Doing something as simple as
making the PC’s speaker beep requires fifteen or twenty machine instructions, all
laid out precisely the right way. Even writing assembly language in almost-words like
MOV EAX,[EBX] is tiresome and done today only by the most curious and the most
dedicated among us. But the computer only understands machine instructions.
What to do?
The Nature of Software Development 41
Remainder := Remainder - 1;
IF Remainder = 0 THEN
BEGIN
BEEP;
Write(‘Warning! Your time has run out!’);
END;
Once you have a feeling for the high-level language, you can look at sequences
like this and know exactly what they’ll do without stretching your brain too much.
The reality is that it may take hundreds of machine instructions for the CPU to do
the work involved in what we have written, but for our eyes, it’s only a few short
lines.
like words and phrases, and writes out an equivalent file of machine instructions.
This file of machine instructions can be loaded and executed by the CPU. But even
though this program file consists of thousands or tens of thousands of machine
instructions, we never had to know even a single machine instruction to write it. All we had
to do was understand how the English-like commands of the high-level language
affect the machine. The compiler takes care of the “ugly” stuff like remembering
which sequence of twenty machine instructions beeps the speaker. All we have to
remember is what BEEP does.
Much better!
A compiler program is thus a program that writes other programs, with some
direction from us. It does its job so well that we can actually forget all about what
happens with the machine instructions (most of the time, anyway) and concentrate
on the logic of how the English-like words and phrases go together.
Different languages
A whole host of high-level languages exists for the PC. Pascal, C, C++, C#, and BASIC
are the most common, but there are hundreds of others with obscure or puckish
names like COBOL, Perl, Python, Java, Forth, APL, Smalltalk, Eiffel, PHP, PL/1, Rexx,
FORTRAN, Lisp, Scheme, and on and on and on. As different as they may seem on
the surface, they all do the same thing underneath: Arrange machine instructions to
accomplish the work that we encode in English-like words and phrases.
Pascal, for example, uses the word Write to display information on the screen.
BASIC, by contrast, uses the word PRINT. The C and C++ languages use the word
printf. Forth uses the word TYPE. Others use words like SAY, OUTPUT, or
Show. Those words were chosen by the people who designed each language for
reasons they considered good ones. However, what those different words do is all
pretty much the same.
A high-level language is defined as a set of commands, plus a set of rules as to
how these commands are used alone and combined. These rules are called the syntax
of the language, and they correspond roughly to the syntax and grammar of spoken
human languages like English and German. Computer languages are not as rich in
expression as human languages, but they are much more precise—and needless to
say, they “speak” only of things that a computer can actually accomplish.
A fifth grader once wrote on an exam: “Now that dinosaurs are safely dead, we
can call them clumsy and stupid.” It’s easy to dismiss the DOS-style command-
line interface as clumsy, awkward, and time consuming, but it has the virtue of
simplicity. (We also forget that dinosaurs ruled the Earth for 100 million years. They
must have done something right.) It’s also far from extinct.
The existence of console windows make certain things easier for people creating
computer language compilers like FreePascal. If a compiler only communicates
with its users through simple text screens, it can work pretty much the same way
no matter what operating system is in control of the computer. So it was done with
FreePascal: By default, it works in a console window. This means that you can open
a console window and type textual commands to FreePascal, which responds by
displaying textual information in the same window on the next line or lines. Figure
2.2 is a console window “conversation” with FreePascal, as it would occur during
the compilation of a very simple pascal program.
All the major FreePascal implementations look pretty much the same when run
in console windows, whether you’re using Windows, Linux, OS/X, or anything else.
Of course, once you begin writing programs that work specifically with a graphical
user interface belonging to a particular operating system, the explanations begin to
diverge. I won’t, however, be going that far in this introductory volume.
be displayed in different colors. Boxes and frames may be created using special
characters. (IBM pioneered text-mode “graphics” this way with their original 1981
IBM PC.) Furthermore, the console window text cursor may be directed around the
window by the computer’s mouse.
Abilities like these allow us to create simple editing and compiling environment
sentirely in text mode, to run in a console window. Many of the concepts we’re
used to in graphical operating environments like Gnome, KDE, and Windows
can be emulated, albeit on a character basis and with far less resolution. Such an
environment (whether implemented in text-mode or graphics mode) is called an
Interactive Development Environment (IDE), and one is included with and installed
with FreePascal on most operating systems for which the compiler is available.
The FreePascal console window IDE is shown in Figure 2.3, with a simple Pascal
program loaded and displayed, ready to be compiled and run.
Lazarus is itself a multi-window application, and the good news is that we can
make Lazarus a lot simpler to understand by closing the windows that you don’t
need for the time being. Figure 2.5 shows Lazarus as it appears while you’re writing
a simple Pascal program. The program code is edited from a GUI window (here,
under Windows XP) but the program’s output is displayed in a console window.
Figure 2.5. Lazarus Used to Edit and Run a Simple Pascal Program
There are three Lazarus windows shown: The control window is the narrow
one at the top. It’s the “boss” window that controls all the rest of the Lazarus
system. The larger window in the center is the editor window, where you write your
Pascal code and fix your inevitable errors. The slim window at the bottom is the
messages window, which tells you what the system is doing and points out your
errors. The black window is a console window, and is not itself a part of Lazarus.
Lazarus launches a console window when your program runs, to provide a separate
“blackboard” (literally!) on which your program can write its output, and display
the input that you enter through the keyboard.
50 FreePascal from Square One, Volume 1
images that must be “baked into” an executable program file. Finally, there are files
associated with a programming project that summarize the details of the project
for the benefit of the programming environment itself. In our case, that would be
Lazarus, but all of the ambitious RAD environments used today generate project files
to manage the mountain of details inherent in advanced programming projects.
You may not have to pay details attention to resource and project files while writing
simple programs in FreePascal, but at least understand that they’re necessary. For
the most part they are generated and maintained by the RAD environment, and
while they must be understood, you don’t often have to explicitly edit them.
In your early explorations of FreePascal, you’ll be creating simple, standalone
.PAS files and compiling them to executable files. (I’ll explain about creating unit
files for maintaining reusable code libraries later on.) You’ll then run the executable
files in a console window to see how well they work. The executable files may be run
from a console window prompt without any help from the FreePascal compiler or
the Lazarus IDE. However, for the example programs in this book you’ll generally
be able to test your executable files from inside console windows created by the
Lazarus IDE itself.
Cross-platform programming
This is a slightly advanced topic, but it’s worth noting as part of the big picture:
FreePascal can handle cross-platform programming. What this means is that you
create a program on one operating system running on one type of computer
hardware, but generate programs that can run on other, different operating systems
or hardware. For example, if your main machine is Microsoft Windows running on
Intel x86 hardware (a very common combo that we often call the “Wintel” platform)
you can still write programs that will run under Linux, Unix, Mac OS/X, and a long
list of other operating systems that you may not have even heard of.
There are often limitations on what such programs can do. For example, there
are whole classes of operating systems that don’t have a graphical user interface.
Everything that they do is done in a purely textual environment much like a console
window. If you load a graphical windowed program intended for the Linux GNOME
windowing environment on such a system, the machine will throw up its hands
in despair because it won’t know how to deal with requests to create windows or
accept mouse clicks to buttons.
The issues that come into play suring cross-platform programming are many
and they are subtle. You need to become fluent in FreePascal long before you should
attempt to create code on one platform to run on another.
52 FreePascal from Square One, Volume 1
FreePascal and Lazarus contain a number of built-in tools to help you flush out
the inevitable bugs you’ll find in your programs. Using these tools and your own
good sense, you gradually find and fix the causes of whatever bugs come to light.
This process can take awhile. Getting rid of disastrous and obvious bugs happens
early in the cycle, because you’re pretty motivated to find them and fix them. Getting
rid of minor or subtler bugs that don’t necessarily make your program worthless
could be a long process—and for programs of a useful size may be an endless one.
People say that there’s always one more bug, and you can devote as much time and
energy as you care to rooting that last bug out.
But even when you root the “last” bug out, there’s always one more bug. Trust me.
{$mode objfpc}{$H+}
Don’t worry about exactly what this means; I’ll explain it later on. Lazarus knows
how the FreePascal compiler needs to do its job in most circumstances, and the red
text (which is not program code!) contains instructions to the compiler telling it
how to compile your project and prepare the executable file. All the text in red can
be safely ignored for the time being. Don’t change it, however, or bad things could
happen!
The test program is shown below in its entirety. Some of it was already “typed
in” by Lazarus when it created the new skeleton program. The words PROGRAM,
USES, BEGIN, and END are all there in black (albeit in lower case), along with
some necessary commas and semicolons. Your job right now is to enter all of the
text in the test program that is not already present in the editor window.
1 PROGRAM EatAtJoes;
2 USES Crt;
3 BEGIN
4 ClrScr;
5 GotoXY(10,5);
6 Writeln(‘Eat at Joe’’s!’);
7 GotoXY(10,7);
8 Writeln(‘Ten Million Flies Can’’t ALL Be Wrong!’);
9 Readln;
10 END.
Important: The numbers in the left margin are not to be entered! Those are line
numbers, and I added them to the printed program so that I can refer unambiguously
to a specific line in a program while talking about the program in the book. For a
program this short that may seem unnecessary, but for the larger and more complex
programs I’ll present later on it will be essential. Lazarus always shows line numbers
in the left margin of its editor windows without any orders from you.
The Nature of Software Development 57
In Lazarus, this is almost trivial. Just click the Save icon (which looks like a
diskette) in the main menu bar (third icon from the left) or press Ctrl-S. Lazarus
will save your project into your working directory. If you haven’t already given your
project a name, Lazarus will pop up the Save Project As... dialog, and allow you to
specify a directory and a name for the project. Thereafter, saving the project will be
done without a dialog, and it will be saved to the directory and name specifed via
Save Project As...
There’s more to a project than just one file. If you look at your working directory
after naming and saving your project, you’ll see a fair number of files with your
project name and different extensions; for example, EatAtJoes.exe, EatAtJoes.ico,
EatAtJoes.manifest, EatAtJoes.lpr, and so on. For simple programs not all of these
files might be strictly necessary, but Lazarus treats a little 10-line example program
the same way it treats a million-line windowed application. I’ll have more to say
about the various files that make up a project in Chapter 5.
delay at all. And you’ll have to forgive me, but I slipped a minor error into the Pascal
file as I printed it on page 56. If you typed the code in exactly as shown, FreePascal will
post an error message in the Lazarus Messages window. (This is the slender window
below the Source Editor window.) Your screen will then look like Figure 2.9.
It’s a little like the situation you find yourself in when you go out after supper to
fill your gas tank and forget your wallet. You made a mistake when you failed to put
your wallet back in your pocket when you changed pants after work. But you only
notice the mistake when you’ve pumped a tank full of gas and reach for your credit
cards. Whoops...
I make the point here because a lot of people assume that FreePascal not only
discovers errors but points out where those errors are. Not true—it can only tell
you where it frst noticed that something was wrong. Keep that in mind as you
struggle through your first few error-rich sessions with FreePascal!
Repairing this particular error is easy. Place the text cursor atthe end of the
GotoXY(10,5) line, and type a semicolon there. Click the Save icon (the diskette)
to save the change. Then select Run | Build again.
Or, if you think there may be still more compile-time errors lurking in your
Pascal code, select Run | Quick Compile. This option is different from Build in that
it only compiles the source code file currently loaded in the Source Editor window.
When you’re working on a large, multi-file project, Build will take more time. If
you’re simply checking the current source code file for errors, Quick Compile will
do the job faster. (For small files like this you won’t see much difference.)
Lazarus doesn’t blow a trumpet or pop up a special window when a build
completes successfully. All you’ll see is the following message in the Messages
window, in very small type:
The arrowhead icon in the main menu bar isn’t the only way to execute your
program. You can also select Run | Run, or simply press the F9 shortcut key. Note
also that to run, your program does not require Lazarus or FreePascal at all. In your
working directory (or wherever you saved the EatAtJoes project) you’ll find a file
called EatAtJoes.exe. This is a complete and independent executable file, and you
can run it by naming it on a console window command line, or by double-clicking
on it in Windows Explorer. (Other graphical environments may have their own
ways of executing standalone .exe files.)
An interesting point to be made here is that FreePascal, Lazarus, and the
EatAtJoes program you’ve just successfully run are all native code programs,
conceptually identical and pretty much equal in the eyes of the computer itself. The
programs you’re writing are not “toy” programs by nature nor are they crippled in
any way. (They’re just small—for now.) You could theoretically write something as
complex as—or even more complex than—FreePascal itself. This is definitely big-
time programming. Don’t let anyone tell you otherwise.
When the program that you ran finishes its execution, it immediately hands the
baton back to the Lazarus environment. You can then continue the development
cycle of write code, save, build, and run.
4. Test your new program by clicking on the green arrowhead Run icon, or
by selecting the Run | Run menu option. You can also run your program
using shortcut key F9.
Here are a few other points worth remembering:
• As much as you might be tempted to do otherwise, spend some time
designing your program before you begin to write actual program code in
the FreePascal IDE editor. We’ll talk more about program design later on.
• Character case does not matter. BEGIN and begin are exactly the same!
• Text shown in bright red in the Source Editor window are instructions
to the compiler, not Pascal code! Lazarus generates some of these
instructions automatically, and as you become more of an expert and
write more complicated programs, you may find it necessary to add some
to the project yourself.
• When a problem comes up during compilation, it’s called an error. When
a problem comes up during your actual testing of a program that has
compiled correctly, it’s called a bug. The compiler will give you some
hints when it discovers an error. But you’re pretty much on your own to
identify and correct bugs.
Finally, this would be a good time to go back and take one more look at
EatAtJoes.pas. It’s a series of steps bracketed between the two words BEGIN and
END. In this simple program, these steps should be close to self-explanatory, even
thought you may never have looked at a single line of Pascal code before.
The line USES Crt simply tells FreePascal to use a library named Crt. We’ll
talk about using code libraries later on in this book.The only other line that might
have you (as a beginner) squinting hard is the last program step: Readln. That’s the
step that waits for you to press the Enter key so that the program can terminate its
execution and give control of the console window back to FreePascal. As with all of
the fundamental elements of FreePascal code, we’ll return to Readln in more detail
later in this book.
65
66 FreePascal from Square One, Volume 1
happen, I’ve heard) so to keep the blood pumping and the gas tank full I got a job as
a Xerox machine repairman.
And I’ll never forget the horrible sinking feeling in my guts the first time I saw
a Xerox copier with its panels off, merrily making copies. There were gears and
drums turning, cams flipping, relays clicking, little claws grabbing a document and
dragging it through a maze of harsh green fluorescent lights, past crackling high-
voltage corotron wires, under a grimy, grinding developer housing, and ultimtely
dropping it into a stainless-steel paper chute.
The instructor must have seen the expression on my face. He snorted through
his bushy mustache and said, “Hey, Jeff, don’t panic! It’s only a copier. Just take it
subsystem by subsystem.”
He was right, of course.
It’s easy to fall into despair the first time you try to make sense of a programming
language. There’s five times the complexity of that gross little Model 660
electromechanical copier, and each and every detail must be exactly right, or nothing
is accomplished but the wholesale tearing of hair.
So do what I did, and take it subsystem by subsystem.
BEGIN
ClrScr;
GotoXY(15,11);
Writeln(‘Eat at Joe’’s!’);
GotoXY(15,12);
Writeln(‘Ten Million Flies Can’’t ALL Be Wrong!’);
Readln;
END.
BEGIN and END are what we call reserved words. They have special meanings to
the FreePascal compiler and you can’t use them for anything else. I’ll have more
to say about reserved words a little later, when we get into the detailed view of the
Pascal language. They are the “framing members” of a Pascal program—the logical
2 X 4s that give a program its structure. They define its shape, and control the way
execution flows within a program.
In this book, reserved words will always be printed entirely in upper-case
characters, as BEGIN, END, WHILE, RECORD, and so on. (Additionally, all
program identifiers of any kind will be printed in bold in the body text of the book.)
In Pascal, character case is not significant for reserved words and other identifiers
like the names of variables, so some people write them in lower case. That’s fine;
68 FreePascal from Square One, Volume 1
FreePascal considers BEGIN and begin to be precisely the same. I like to place
reserved words in capital letters so that they stand out—it helps you take in the
overall structure of a program quickly and easily. Reserved words and variables
are not the same thing—not even close, in fact—so making them look different is
actually a very good thing.
Statements
Between BEGIN and END are six lines, each of which is a step in the program’s
execution. When a program begins running, the first step in the main block
executes, (here, ClrScr) and then the second, and then the third, and so on, until the
last step in the main block is executed. Program execution is then finished, and the
program stops running.
Each one of those steps is called a statement. The single word ClrScr is a statement,
as is the more complicated line Writeln('Eat at Joe''s!').
Note carefully here that statements and lines are very different things. (Beginners often
confuse them, with predictably bad results.) A statement may exist all by itself on a
single line. A statement may occupy more than one line. More than one statement
may exist on a single line. The key is that statements are separated by semicolons.
Semicolons don’t end lines. They separate statements. This means that you can
have a perfectly legal line like the following:
ClrScr; GotoXY(15,11);
Here there are two statements on one line, with a semicolon after the first to act
as a separator. There is a semicolon after the second as well, but that semicolon
separates the statement GotoXY(15,11) from whatever statement begins the next
line. More on this a little later.
The statements in EatAtJoes.PAS are simple and easy to dope out by reading
them and by watching what the program does. ClrScr clears the screen. GotoXY
moves the cursor to an X,Y position on the screen. Think of your CRT screen as a
Cartesian grid like the ones you worked with in high school math. The X (across)
value comes first, followed by the Y (down) value. The upper left corner of the
screen is the origin, 1,1. Saying GotoXY(15,11) moves the cursor 15 positions
across, and 11 positions down. Writeln writes a line of text to the screen, starting
at the cursor position.
There is always a period after the END of the main block of a Pascal program.
The period indicates that the fat lady has indeed sung, and that the program is over.
Control leaves the Pascal program and returns to the operating system.
The Secret Word Is "Structure" 69
Compound statements
I’ll have a great deal more to say about statements later on in this book. It’s
important to note that, in a Pascal sense, the whole main block of the program is
itself a compound statement. In most cases, a compound statement is some number of
statements delimited by a BEGIN and END reserved word. There are a couple of
instances where a compound statement may be framed by other reserved words,
like REPEAT and UNTIL rather than BEGIN and END. We’ll deal with these
special cases later on.
It might help to characterize the main block by considering it to be a collective
statement that indicates the larger, single purpose that the program as a whole was
designed to accomplish. Just as a sentence in the English language is a statement
made of words followed by a period, so the main block in Pascal is a compound
statement made of statements followed by a period. This compound statement
summarizes the program’s larger purpose, and by reading the main block of a Pascal
program first, you should be able to garner the big picture of what the program is
supposed to do.
Compound statements appear in many other parts of the Pascal language.
You’ll be tripping over them wherever you go. When you see one in a program,
ask yourself what the unifying purpose of the compound statement is. It’ll help
you refine your “structure vision” and help you focus on just that one part of the
program as a whole.
1 {--------------------------------------------------------------}
2 { Aliens }
3 { }
4 { by Jeff Duntemann }
5 { FreePascal V2.2.0 }
6 { Last update 2/8/2008 }
7 { }
8 { From: FREEPASCAL FROM SQUARE ONE by Jeff Duntemann }
9 {--------------------------------------------------------------}
10
11 PROGRAM Aliens;
12
13 USES Crt; { For ClrScr, Random, and Randomize }
14
15 CONST
16 MaxLength = 9; { The longest name we’ll try to generate }
17 MinLength = 2; { The shortest name we’ll try to generate }
18 LastLetter = 122; { Lower-case ‘z’ in the ASCII symbol set }
19
20 TYPE
21 NameString = STRING[MaxLength]; { Waste no space in our strings! }
22
23 VAR
24 Printables : SET OF Char; { Holds the set of printable letters }
25 I,J : Integer; { General-purpose counter variables }
26 NameLength : Integer; { Holds the length of each name }
27 NameChar : Char; { Holds a randomly-selected character }
28 NamesWanted : Integer; { Holds the number of names we want }
29 CurrentName : NameString; { Holds the name we’re working on }
30
31 BEGIN
32 Randomize; { Seed the random number generator }
33 Printables := [‘A’..’Z’,’a’..’z’]; { Only printable letters! }
34 ClrScr;
35 Write(‘How many alien names do you want? (1-10): ‘);
36 Readln(NamesWanted); { Answer the question }
37
38 FOR I := 1 TO NamesWanted DO
39 BEGIN
40 CurrentName := ‘’; { Start with an empty name }
41
42 REPEAT
43 NameLength := Random(MaxLength); { Pick length for this name }
44 UNTIL NameLength > MinLength;
45
46 FOR J := 1 TO NameLength DO { Pick a letter: }
47 BEGIN
48 REPEAT { Keep picking letters until one is printable: }
49 NameChar := Chr(Random(LastLetter));
50 UNTIL NameChar IN Printables;
The Secret Word Is "Structure" 71
Don’t panic!
I mean that. You’re not going to be tested on the full details of how the Aliens
program works at this point, so don’t worry about digesting it whole and in every
last little detail. It’s a complete Pascal program that even does something interesting,
and I’ll be talking about it for a while in this chapter, explaining most of its workings
as I do. So follow along as we go, and don’t fret not knowing the details of character
sets or the REPEAT..UNTIL statement right now. All in good time. Remember,
we’re going for the big picture here. The details will crystallize out in the chapters
to come.
CONST
MaxLength = 9; { The longest name we’ll try to generate }
MinLength = 2; { The shortest name we’ll try to generate }
LastLetter = 122; { Lower-case ‘z’ in the ASCII symbol set }
TYPE
NameString = STRING[MaxLength]; { Waste no space in our strings! }
CharSet = SET OF Char; { To weed out odd symbols }
VAR
Printables : SET OF Char; { Holds the set of printable letters }
I,J : Integer; { General-purpose counter variables }
NameLength : Integer; { Holds the length of each name }
NameChar : Char; { Holds a randomly-selected character }
NamesWanted : Integer; { Holds the number of names we want }
CurrentName : NameString; { Holds the name we’re working on }
The data definition part of a Pascal program is almost literally a set of blueprints
for the data that the program will be using during its execution. The Pascal compiler
reads the definitions and sets up a little reference table for itself that it uses while it
converts your source code file to a unit file or an executable program file. This
reference table allows the Turbo Pascal compiler to tell you when something you’re
trying to write as part of a program is bad practice or nonsensical.
Variables as buckets
Variables are defined after the VAR reserved word. Think of variables as buckets
into which data values may be placed. In variable definitions, you declare the name
of a variable followed by its type. The name and the type are separated by a colon.
Variables—like buckets—come in a great many shapes and sizes. The type of a
variable indicates how large the bucket is and what sorts of stuff you can safely put in
it. A plastic water bucket will carry water handily—but don’t try to lug molten lead
in it. A colander can be thought of as a bucket suitable for carrying meatballs—but
don’t expect to use it to hold flour or tomato juice without making a mess.
The notion of types in Pascal exists precisely to keep you from making certain
kinds of messes.
In Aliens, there’s a variable called NameLength. Its type is Integer, which is
a signed whole number from -32,678 to 32,767. NameLength is thus a bucket
for carrying numeric values falling in that range that don’t have a decimal part.
Similarly, NameChar is a Char variable, meaning it is intended to hold character
values like ‘A’ or ‘*’.
The Secret Word Is "Structure" 73
This is a type definition. It defines a type called NameString. This type is a string
type—meaning that it’s designed to contain data in alphanumeric strings of
characters like ‘I am an American, Chicago-born’ or ‘THX1138’. FreePascal strings
come in all sizes from 1 character to 255 characters and you can create a string type
in any size within that range. That’s what the type definition statement in Aliens
does: It creates a string type with a length given by a constant named MaxLength.
(We’ll get back to MaxLength and what it is shortly. For now, just assume it’s a
number—or look a few lines back to see how it’s defined!)
NameString is a very simple type. You can create much, much more complex
types in FreePascal, as I’ll explain later in this book. It’s easy to see how a type is in
fact a blueprint for making buckets, in that it defines what sort of data some new
kind of bucket is meant to contain.
Then, when you actually need a bucket of this new type, you can make one in the
VAR section:
This statement gives you a variable in memory that contains string data. The name
of the variable is CurrentName. The length of the string is given by the MaxLength
constant.
Remember: A type is not a variable and holds no data. It’s simply a spec or
template that allows you to create variables with a specified size and set of attributes
and uses. Use the TYPE reserved word to create blueprints for buckets—and then
use VAR to create the buckets themselves.
74 FreePascal from Square One, Volume 1
values are not predictable, and can cause many kinds of trouble. Better by far to give
every variable a value early on, before it finds one on its own!
You can give a variable a value in several ways, but the most straightforward way
is through an assignment statement. An assignment statement takes a value and assigns
that value to a variable. In effect, it takes the value and “loads it into” that variable, as
though dropping something into a bucket. Here’s a simple assignment statement:
Repetitions := 141;
What we’ve done here is taken the numeric value 141 and dropped it into
the variable Repetitions. The two character sequence := is called the assignment
operator. When FreePascal sees the assignment operator, it takes whatever is on the
right side of the operator and drops it into whatever is on the left side.
Here’s an assignment statement from Aliens.PAS:
CurrentName := '';
What it does is drop an empty string (that is, a string containing no characters) into
the variable CurrentName. (A string with something in it would look like this:
‘Jeff’) It may seem odd to think of dropping an empty value into a bucket, so you
might consider this a way of emptying the bucket of anything else that might have
already been there.
Taken as the sum of its individual steps, brushing your teeth is a real mouthful.
When you actually get down and do it, you run faithfully through each of those
steps, and if you ever had to tell somebody how to do it, you could. But when you’re
trying to impose some order on your morning, the whole shebang shows up in
your mind under the single descriptive term, “brushing your teeth.”
behind a single identifier of your own choosing. You can execute the new identifier
as though it were a single statement, masking the complexity represented by the
original sequence of Pascal statements.
Suppose you have these three statements in a Pascal program:
DoThis;
DoThat;
DoTOther;
Taken together, these three statements accomplish something. Let’s call that
something “grobbling.” (It’s a made-up word. Don’t read anything into it.) We could
say that the following compound statement represents what must be done in order
to grobble:
BEGIN
DoThis;
DoThat;
DoTOther;
END;
We can hide this compound statement behind a single statement, which we’ll
call Grobble—so that any time we need to execute those three statements together,
we only have to execute this single statement:
Grobble;
PROCEDURE Grobble;
BEGIN
DoThis;
DoThat;
DoTOther;
END;
An adventure in structuring
To make it all click, let’s do it, right now, to Aliens.pas. This is a slightly advanced
exercise, and if you’ve never written a line of program code before some of it may
78 FreePascal from Square One, Volume 1
puzzle you. Bear with me—and have faith that all will be explained in good time.
One of the things that Aliens has to do is choose a length for any given alien
name. It does this by “pulling” random numbers repeatedly until it pulls a random
number within a specified range. This range is the range from MinLength to
MaxLength, both of which are defined as constants, and in this case are equivalent
to the range 2 through 9.
The code that pulls a random length within those two boundaries is this:
REPEAT
NameLength := Random(MaxLength); { Pick a length for this name }
UNTIL NameLength > MinLength;
Creating a function
Random numbers are useful things, and it’s even more useful to be able to specify
a range of values within which a random number is to be pulled. It would be nice
to have a procedure of some sort that would pull a random number for us without
our having to remember all the precise details of how it was done. We could call the
procedure Pull, and it would be a sort of number-generating machine. We would
pass it a minimum value and a maximum value, and Pull would somehow return a
value for us that fell within those two bounds.
As I said a little earlier, in Pascal, a function is a procedure that returns a value.
I’ll have much more to say about functions and how they’re used later in this book,
but it cooks down to that. To illustrate, suppose we had a numeric variable called
NumberBucket. We could define a function called Pull, and it would be Pull’s job
to generate a random number. To fill NumberBucket with a brand-new random
number, we would use this statement:
The Secret Word Is "Structure" 79
NumberBucket := Pull;
Although it may look like one, Pull is neither a constant nor a variable. It’s actually a
compound statement masquerading as a single value. The value is computed within
the compound statement, and then returned “through” the name of the function.
With that in mind, let’s create the Pull function from the three lines in Aliens
that pull a random length for alien names:
VAR I : Integer;
BEGIN
REPEAT
I := Random(MaxValue); { Pick a length for this name }
UNTIL I >= MinValue;
Pull := I;
END;
Things have changed a little—but for a reason, as I’ll explain. The central portion of
Pull does the same thing that the three lines we lifted from the Aliens program did.
What we’ve mostly added is framework; a body for the lines to exist in.
But we’ve also added a strong measure of generality. The lines that pull a random
name length within Aliens can be used only to pull a random name length. The new
Pull function can be used to pull random numbers within a specified range for any
reason. We could use it just as easily in a dice game as in an alien name generator—
and that’s a big, big advantage.
We can use Pull in Aliens.pas. Just insert the definition for Pull in the program
file just before the beginning of the main block, and then replace the three lines that
pull a random name length with the following single line:
NameLength := Pull(MinLength,MaxLength);
The two items named MinLength and MaxLength are called parameters. They’re
special-purpose variables belonging to the function that work as pipelines,
allowing you to drop values into the function. Drop a “7” value into MaxLength,
and the Pull function’s internal machinery will receive the value 7 as the maximum
allowable value for the random number it’s been told to generate.
The altered copy of Aliens.pas(let’s call it Aliens2.pas) is shown on the next page,
with the Pull function replacing the three lines used to pull random numbers in the
original Aliens.pas.
80 FreePascal from Square One, Volume 1
1 {--------------------------------------------------------------}
2 { Aliens2 }
3 { }
4 { by Jeff Duntemann }
5 { FreePascal V2.2.0 }
6 { Last update 2/8/2008 }
7 { }
8 { From: FREEPASCAL FROM SQUARE ONE by Jeff Duntemann }
9 {--------------------------------------------------------------}
10
11
12 PROGRAM Aliens2;
13
14 USES Crt; { For ClrScr, Random, and Randomize }
15
16 CONST
17 MaxLength = 9; { The longest name we’ll try to generate }
18 MinLength = 2; { The shortest name we’ll try to generate }
19 LastLetter = 122; { Lower-case ‘z’ in the ASCII symbol set }
20
21 TYPE
22 NameString = STRING[MaxLength]; { Waste no space in our strings! }
23
24 VAR
25 Printables : SET OF Char; { Holds the set of printable letters }
26 I,J : Integer; { General-purpose counter variables }
27 NameLength : Integer; { Holds the length of each name }
28 NameChar : Char; { Holds a randomly-selected character }
29 NamesWanted : Integer; { Holds the number of names we want }
30 CurrentName : NameString; { Holds the name we’re working on }
31
32 FUNCTION Pull(MinValue,MaxValue : Integer) : Integer;
33
34 VAR I : Integer;
35
36 BEGIN
37 REPEAT
38 I := Random(MaxValue); { Pick a length for this name }
39 UNTIL I >= MinValue;
40 Pull := I;
41 END;
42
43
44 BEGIN
45 Printables := [‘A’..’Z’,’a’..’z’];
46 Randomize; { Seed the random number generator }
47 ClrScr;
48
49 Write(‘How many alien names do you want? (1-10): ‘);
The Secret Word Is "Structure" 81
Hiding complexity
The details of having to pull a number again and again until one appears that falls
within a specified range are masked now. We only see the “front door” of the
random number factory. The machinery that actually builds the random numbers
is hidden away behind the door somewhere. And that’s good—because most of the
time we really don’t care how random numbers are made; we only care that they do
get made according to our specifications.
It’s true that creating the Pull function added a few lines to the program. Later
on, we’ll see how we can remove Pull from Aliens2.pas and place it in a library
of functions and procedures called a unit. This library is available to any of your
programs that need it. If ten of your programs need a random-number puller,
you can give a random number puller to all ten of them—and yet have only one
copy of Pull’s ten little lines. If you yank enough general-purpose procedures and
functions out of your programs into libraries, you can actually cut the source code
bulk of your programs considerably.
But consider a simple accounting program. A good one (even a simple one,
as accounting programs go) might have 10,000 lines of code. You could write all
10,000 lines of code in one enormous main block. But how would you read and
understand those 10,000 lines of code? You’d probably have to do what was done
in the ancient days of programming, and literally cut a long program listing up into
chunks with a scissors, and only look at the chunk you needed to concentrate on at
the moment.
Even War and Peace is divided into chapters—and procedures are often used as
“chapters” in a larger program. In our accounting program example, you would have
several accounting tasks like Payroll, Accounts Payable, Accounts Receivable, General
Ledger, and so on. It’s possible to make each of these accounting tasks a procedure:
PROCEDURE AccountsPayable;
BEGIN
<about 2000 lines>
END;
PROCEDURE AccountsReceivable;
BEGIN
<about 3000 lines>
END;
PROCEDURE Payroll;
BEGIN
<about 2000 lines>
END;
PROCEDURE GeneralLedger;
BEGIN
<about 2200 lines>
END;
Now at least you have a fighting chance. When you need to work on the payroll
portion of your accounting program, you can print out the Payroll procedure and
ignore the rest. All the “payroll-ness” of the accounting program is concentrated
right there in one procedure, so you don’t have to go searching for payroll details
across the entire program. Better still, details that you don’t have to pay attention to
right now remain hidden, inside their respective procedures.
The Secret Word Is "Structure" 83
With your payroll blinders on, you’ll have a much easier time focusing on the
payroll part of the program. The main block becomes quite small then, and is
mostly a little menu manager that lets you choose which of the four big procedures
you want to run.
If...Then...Else...
87
88 FreePascal from Square One, Volume 1
d
e
h
is
n
fi
n
U
Is
Chapter 4.
r
te
Installing FreePascal
p
a
and Lazarus
h
C
is
h
O ne of the (few) downsides to free and open-source software is that you can’t
T
cover installation by saying, “Order the product, open the box, and follow the
manufacturer’s instructions.” It’s a little more complex than that, especially when
the product (like FreePascal) can be run on a number of different operating systems
and CPU types. So in this chapter, I’ll explain how to find the downloadable install
suites for FreePascal, how to be sure you have the right one, and then how to install
it for Windows and Linux.
89
90 FreePascal from Square One, Volume 1
Binaries only!
One important point to note is that the installable files listed in Table 5.1 include
only the binary files for the FreePascal compiler, its libraries, and its text-mode IDE.
The source code for FreePascal is available as a separate archive. Using the source
code files, you can recompile FreePascal in itself (which sounds impossible to
newcomers, but it’s true!) and tweak it to run on other operating systems and CPUs.
That, however, is a very advanced topic that I won’t be going into in this book.
Installing FreePascal and Lazarus 91
FreePascal’s Documentation
When you install FreePascal (all versions, for all platforms) you get a substantial
set of manuals in PDF file format. The files reside in the DOC directory under FPC,
if you installed using the default directory locations. Interestingly the PDF files are
available online, but at this writing, the files installed with the compiler itself are
newer than the ones you can download from the Web.
The available manuals are these:
• The FreePascal User Guide (user.pdf) explains how to install and configure
the compiler and how to invoke it. This includes compiler modes,
compiler error messages, debugging using gdb, and a list of the standard
units installed with the compiler. (The units are not described in detail; for
that see the Runtime Library Reference Guide.) A large part of the file explains
how to use the text-mode IDE, which I won’t be discussing in detail in this
book.
• The FreePascal Programmer’s Guide (prog.pdf) explains programming issues
that go beyond the fundamentals of Standard Pascal. This includes
language extensions, compiler directives, low-level issues like assembly
language interface and external calling conventions.
• The FreePascal Reference Guide (ref.pdf) is a concise description of the Pascal
language as implemented by the FreePascal compiler, including “railroad”
syntax diagrams. The descriptions are terse and should not be considered
tutorial in any sense.
• The Runtime Library Reference Guide (rtl.pdf) describes all of FreePascal’s
standard units in detail, procedure by procedure. If you want to know how
to call the GotoXY procedure, this is where to look, keeping mind that
the descriptions of individual procedures and functions are necessarily
brief and technical. The file is 1,450 pages long.
• The Compiler Switch Summary Chart (chart.pdf) is a two-page document with
a summary of global compiler switches on one page, and local compiler
switches on the other. This can be handy, and the best way to use it is to
print it on both sides of a single sheet of paper and keep it close by while
you program.
• The Free Component Library Reference Guide (fcl.pdf) is a reference for the
FCL object-oriented library that is used for writing component-based
programs, particularly for GUI platforms like Windows and Linux under
one of the graphical shells. The FCL is an advanced topic that I won’t be
covering in this book, so this file won’t be of much use to you in your first
steps as a Pascal programmer.
94 FreePascal from Square One, Volume 1
All the documentation files are PDF files, and if you’ve got a printer capable of
duplexing, it can be useful to print the files and place them in 3-ring or duo-tang
binders. The page size is A4, but the pages will print well if scaled to fit American
Letter-size sheets. The Runtime Library Reference Guide is an immense file, but you
don’t need to print all of it. (Some of the libraries are relatively arcane.) For your
initial learning exercises, print the sections covering the following units: crt and
sysutils.
I did something interesting but very useful: I uploaded the PDF files to the
Lulu.com self-publishing site and ordered printed books for my own use. As a
courtesy to Michaël Van Canneyt and the other authors, I uploaded the files as
provate projects and they are not available to the public. You’ll have to upload
them yourself! It was, however, worthwhile: I ordered the books made with a spiral
binding that lies flat on the desktop or propped on a copy frame.
http://www.freepascal.org/
Once you’re there, definitely poke around! The page will show you news on the
latest releases. If you’re reading this book a long time after I published it (mid-2010)
the latest stable version of FreePascal may not be the one I call out here. To find
the current version, click on the Downloads link, and look for the list of available
binary installers. For 32-bit Windows, click on the Win32 link.
Once the FreePascal Web site hands you off to SourceForge, look frst for a big
green button saying Download Now! Click the button, and the installer fle for 32-bit
Windows will begin coming down. If for some reason the download doesn’t begin
Installing FreePascal and Lazarus 95
immediately, click on the direct link just under the title reading, “Your FreePascal
Compiler download will start shortly...”
And just in case you’re a better typist than a hotlink navigator, here’s a shortcut
that goes directly to the installer fle for version 2.4.0:
http://sourceforge.net/projects/freepascal/fles/Win32/2.4.0/fpc-2.4.0.i386-
win32.exe/download
The installer is an ordinary Windows executable file. Close all open Windows
applications and run it, either from the Run window or by navigating to the installer
fle and double-clicking on it. The installer will open a conventional Windows
install wizard. All of the wizard’s felds provide useful default values, so you can
accept all the default values in each one of the wizard’s dialogs. When the wizard
has completed its series of dialogs and terminated, you’ll see a new icon on your
desktop, for the FreePascal IDE.
http://www.lazarus.freepascal.org/
This is the Lazarus “home page” and a good starting point when looking for the
latest on Lazarus. There’s a link to the Downloads section in the left column, which
will take you to the Lazarus download page on SourceForge. Click Downloads,
and (as with FreePascal) locate the big green button once the page loads. (See
Figure 4.1.) If you hover the mouse over the green button, Windows will show
you the full filename that you’re about to download. The string “win32” should be
there somewhere for the 32-bit Windows version. If you’re looking for the 32-bit
Windows installer, just click the green button and the download will begin.
If you want the 64-bit Windows version instead, click the link labeled “View
All Files” to the right of the big green button. This expands the folders list below
the button, and if you scan down the list you will eventually find a folder labeled
“Lazarus Windows 64 bits”. Click the link to expand it. Inside the folder will be
two additional folders. The first contains the current release of Lazarus, and the
second contains all the older releases gathered into a single (very large) archive.
People who have old code originally written for an older version of Lazarus may
need to download past versions of Lazarus, but if you’re just learning FreePascal
and Lazarus, click the folder for the current version. The folder will open to reveal a
link in blue. Click the blue link to begin the download.
While you’re there, it might be a good idea to download the Lazarus documentation.
The documentation folder is right beneath the folder for the 32-bit Windows version,
labeled “Lazarus Documentation.” The documentation fle is available in HTML or as
a Windows .chm help fle. The two files are otherwise identical.
To run Lazarus, just double-click the desktop icon, as with any Windows app.
Note that when you install FreePascal as part of the Lazarus installation, the text-
mode IDE fp.exe will not be installed. If you want to experiment with fp.exe after
installing Lazarus, I suggest installing FreePascal separately. There’s nothing wrong
or hazardous about having two copies of FreePascal installed on a single hard drive,
though the second copy will cost you about 150 MB in disk space.
Installing FreePascal separately under Windows will create a desktop icon for
the text-mode IDE, and you run the IDE by double-clicking on the icon. Keep in
mind that the operation of the IDE can be erratic under Windows, so if it crashes or
looks peculiar, there may not be much you can do about it.
Again, there is much more to Lazarus than you need in order to learn the
fundamentals of the Pascal language, and much more than I’ll be covering in this
first book. I recommend confguring Lazarus to hide the IDE windows that you
won’t need, to keep the clutter down and make the product easier to grasp. I’ll
explain how to do this in Chapter 5.
http://www.lazarus.freepascal.org/index.php?action=forum
Installing FreePascal and Lazarus 99
http://software.opensuse.org/search
The OBS is a platform for distribution and installation of open source software.
It uses the YaST installation/configuration manager, and provides “1-click install”
buttons on the search page. Calling it “1-click” is a bit of an exaggeration, but the
big win is that you don’t have to type in the names of any packages or repositories,
enter any scripts, or do any manual unpacking or building. One click kicks off the
process, which launches an installation wizard. Run through the wizard, answer its
questions (which does require a few additional clicks) and YaST will begin installing
the selected package.
Here’s a step-by-step:
100 FreePascal from Square One, Volume 1
of Lazarus and FPC installed are not the latest, and (peculiarly) the FreePascal source
is not included in the package, even though Lazarus requires it. So if you install
Lazarus from one of the Debian packages downloadable at this writing (mid-2010),
Lazarus will complain when you launch it that the FreePascal source code is not
available, and that some of its features (not stated) will not work completely.
This is not the fault of the people who wrote and maintain FreePascal and
Lazarus, because they do not have complete control over how the Debian package
for the product is maintained, which is a separate issue from maintaining the
product itself.
The RPM package, by contrast, is far better maintained and works very well, but
does not install under Debian-based distributions. One solution that I have not yet
tried is to convert the RPM package to a Debian package with a utility called Alien.
This tutorial may be useful:
http://www.howtoforge.com/converting_rpm_to_deb_with_alien
If you expect to be using Lazarus and FreePascal over the long term, you might
be better off using OpenSuSE, because updating Lazarus on Ubuntu as new releases
have been issued has been a bumpy business for me, and far more work than it
needs to be.
102 FreePascal from Square One, Volume 1
out of the sandbox. If it damages the sandbox, you can revert and have a brand-new
sandbox in almost no time at all, ready to try again.
VMWare Workstation 7
I learned virtual machine techology on VMWare’s Workstation product, and
although at about $200 is moderately expensive (especially compared to free
alternatives) it works extremely well and I’ve continued to pay for upgrades and use
it daily. Shortcomings: Older versions do not support 4-core CPUs, and no version
supports FireWire peripherals. It really does pay to keep the product current.
There is an add-on package for installation in supported “guest” operating
systems (those installed in VMs) called VMWare Tools, allowing better graphics and
better mouse integration. Not all operating systems and versions are compatible
with VMWare Tools, but if you’re installing a compatible OS in a VM, definitely
install VMWare Tools for it.
Here’s the vendor’s product page:
http://www.vmware.com/products/workstation/
Microsoft Virtual PC
Microsoft’s Virtual PC product has been around since 1997, and was a paid product
for years, until it was made a free (but not open-source) product in 2006. The 2007
version is the last version of the product to support Linux in its VMs. More recent
versions are called Windows Virtual PC, and do not allow the creation of VMs for
use with Linux or other non-Microsoft operating systems. Note well that each copy
of Windows installed in a VM must be separately licensed, and Microsoft’s VMMs
enforce this to the best of their abilities. Linux support is better in both VMWare
Workstation and VirtualBox.
104 FreePascal from Square One, Volume 1
For these reasons, I don’t recommend Virtual PC, even though it is technically
robust and reasonably easy to use. If you do want to try it, you can download the
most recent Linux-compatible version here:
http://www.microsoft.com/downloads/details.aspx?FamilyId=28C97D22-
6EB8-4A09-A7F7-F6C7A1F000B5&displaylang=en
Oracle VM VirtualBox
This was called Sun VirtualBox until Oracle acquired Sun in early 2010 and
rebranded the product. VirtualBox is available in both closed-source and open-
source versions. The open-source version lacks some of the server-associated
features of the “full” version and is intended for desktop use only.
Licensing is complex. Oracle offers the closed-source “full” version without
charge for personal (non-commercial) use. If you’re part of a corporation that may
be an issue; if you’re just learning Pascal at home it will not be. You can download
the closed-source version here:
http://www.sun.com/software/products/virtualbox/get.jsp
There is a weirdness in VirtualBox involving USB support. In the open-source
version USB peripherals cannot be accessed from within a VirtualBox VM. I don’t
completely understand the technical issues, but a detailed tutorial explaining how
to enable USB support is here:
http://news.softpedia.com/news/How-to-Fix-VirtualBox-USB-Support-
111715.shtml
The free and open source version of VirtualBox may be downloaded here:
http://www.virtualbox.org/wiki/Downloads
I’ve used both, and prefer the closed-source version, since I have no interest in
modifying and re-compiling the product in any way.
Parallels
I am not a Mac user and don’t have any Apple expertise, but the Parallels VMM
product is highly regarded by my Mac-user friends. There are two versions of the
Parallels product:
• Parallels Desktop for Mac is for Intel-based Mac machines running OS X
Tiger or later. The host OS must be Mac OS X. Guest OSes include Mac OS
X, Linux, BSD Unix, OS/2, Solaris, and Windows. eSATA, Firewire, and
Installing FreePascal and Lazarus 105
What I do
My main development machine runs Windows XP. I have VMWare Workstation
installed, and keep “clean” snapshots of VMs containing major Linux distros on
disk. These snapshots include FreePascal and Lazarus, installed and configured as I
like them. My project directory tree is shared with the several VMWare VMs.
I do most of my programming on Windows, but when I need to test a build
on Linux I open one of the Linux VMs and load the project into Lazarus from the
shared project directory. Because all project source code is kept in a single location,
there’s no danger of the Windows and Linux source code getting “out of sync.”
That said, once I move beyond simple Pascal console apps to GUI apps (which
I won’t be covering in this book) I tend to keep the source code suites separated by
platform. Portability is an ideal to shoot for, but depending on what your app needs
to do, it may not be possible to target both Windows and Linux from the same
source code suite. Fortunately, you won’t have to worry about this until such time
as you learn enough FreePascal to move ahead to Lazarus and GUI apps.
Is
Using the Lazarus
r
te
Environment
p
a
h
C
is
h
T
“G ive me a lever long enough, and a place to stand, and I will move the Earth.”
In perhaps his best-known statement, Archimedes was speaking literally
about the power of mechanical levers, but behind his words there is a larger truth
about work in general: To get something done, you need a place to work, with
access to tools. My radio bench down in my workshop is set up that way: A large,
flat space to lay ailing transmitters down, and a shelf above where my oscilloscope,
VTVM, frequency counter, signal generator, and dip meter are within easy reach.
Much of the initial success of Turbo Pascal 25-odd years ago was grounded in that
simple but compelling truth. For the first time, a compiler vendor had assembled
the most important tools of software development and put them together in an
intuitive fashion so that the various tasks involved in creating software flowed
easily and quickly from one step to the next.
107
108 FreePascal from Square One, Volume 1
Pascal language, and it will have to wait until later in this book. Think of
object-orientation as a new, higher level of program structure that defines
relationships between code and data in a hierarchical way.
• Delphi actually wrote parts of the code for new applications, especially
applications crafted with the help of the GUI builder. Delphi basically
generated a sort of generic program skeleton that programmers would
“flesh out” to make it perform specific tasks. Object-orientation was
essential to this code-generation mechanism.
Delphi was a roaring success for many reasons, primarily that it made the process
of writing programs to run under Windows easier to understand and hugely faster.
The improvement in programmer productivity was such that Delphi became
known as a rapid application development (RAD) environment.
Delphi is still being actively developed and is widely used by corporate developers,
especially outside the US. It is, however, very expensive compared to the original $50
Turbo Pascal. Even the entry-level version of Delphi 2010 costs over $1000. This
puts it beyond the means of newcomers and hobby programmers who don’t have a
corporation with an IT budget behind them.
Back when Delphi was released, a company called SpeedSoft offered a product
called SpeedPascal, written to run under IBM’s ill-fated OS/2 operating system.
Speedsoft created a RAD environment for OS/2, using SpeedPascal as the “back
end” compiler. The RAD environment was called Sibyl. Sibyl was very compatible
with Delphi, and allowed programmers to port Delphi apps to OS/2 without
rewriting all their code from scratch. OS/2’s success began to wane in the shadow of
Windows 95’s success, and Sibyl’s fate was tied to OS/2. In 1998, SpeedSoft released
the source code for Sibyl and made it an open-source product before the company
finally closed its doors.
With the Sibyl source code as a model, a group of Israeli programmers began a
project in 1998 that they called Megido. The idea behind Megido was to create an
open-source Windows-based RAD environment like Borland’s Delphi. The project
vanished after about a year for reasons that never became fully known. Later in
1999 several programmers resurrected the idea of Megido as the Lazarus Project.
(Lazarus, some of you may recall from Sunday School, was the man whom Jesus
brought back from the dead.)
The Sibyl source code was less useful than originally thought, largely because
so much of it was in 32-bit x86 assembly and thus not easily portable to platforms
based on other CPUs. So over the past ten years, Lazarus has been written entirely
in FreePascal, thus making it at least potentially portable to any platform where
FreePascal exists.
Using the Lazarus Environment 109
Ten years on, Lazarus is still very actively in development, and is definitely
mature enough to develop commercial applications with.
One thing to be aware of is that a lot of the way Lazarus is designed caters to
the needs of object-oriented programming, and it will take most of a book before
we can discuss objects at any length at all. The object inspector and the restriction
browser, in particular, make little sense until you “get” the object-oriented idea. The
Lazarus Component Library is completely object-oriented and is not something
that may be called from within very simple Pascal programs.
A project-oriented IDE
Through most of the history of Pascal programming, a “project” in Pascal was
simply a Pascal program, or perhaps a program and a number of Pascal library files
named within the program and linked with the program to create the executable
program file. As Pascal programming has gotten more complex, and especially
with the advent of object orientation and GUI apps for Windows and the Linux
110 FreePascal from Square One, Volume 1
graphical shells, Pascal projects include more than simple Pascal code. You need
icon files, form files, and many other things in the general category called resources.
For this reason, when you want to write a program in FreePascal using Lazarus, you
don’t simply create a new Pascal source code file. You create a project.
A Lazarus project includes the main program’s source code file, obviously. It also
includes code libraries and other resources. Giving a project a single name (which
does not have to be the name of any source code file) gives you a sort of umbrella
beneath which you can tinker the various elements of an ambitious Pascal project
without losing track of what parts belong to what project.
Once you’ve created a project, you can add new files to the project whenever you
need to, and being able to treat the collection of files as a named entity helps a great
deal in managing the complexity of a sophisticated project.
This will become a lot clearer once we create an example project later in this
chapter.
If...Then...Else...
113
114 FreePascal from Square One, Volume 1
H aving gotten a feeling for both programming and the “big picture” of Pascal
itself, it’s now time to after the details of both the Pascal language and the
programming process. And therein lies a snag for me.
I’d like to be able to say, “Read this book from cover to cover and you’ll learn
Pascal.” That’s how I think books of this kind work best. The problem with teaching
Pascal in a strictly linear fashion is that it’s a continuous, linear narrative that weaves
all of Pascal’s ideas together in a single stream. There would be no “chapter” on
simple data types, because you have to introduce simple data types right alongside
reserved words, identifiers, operators, and so on. This reads well in the fashion of a
novel, but it doesn’t re-read very well. By that I mean that once you’ve read it, you may
feel that your understanding of derived types is fuzzy, and you may want to go back
and reread a discussion of derived types. But in a strictly linear exposition of Pascal,
derived types are discussed in no one place, but here, there, and in several other
places. Like all the other topics, they weave in now and again in the one big story.
Once I’ve laid the groundwork it’ll be a lot easier. But in laying the groundwork
I’ve had to make a number of seemingly arbitrary decisions: Do I explain first what
reserved words and identifiers are, and then explain what data is? Or do I explain data
types first, so that I can explain how reserved words and identifiers come together
to make statements? Maybe it’s a silly thing to worry about. But I’m trying hard to
make this book accessible to the total newcomer to the idea of programming, and
putting across the foundations of any idea is absolutely critical.
So you’ll have to cut me a little slack here. I’ve chosen to begin with Pascal’s
fundamental atoms like letters and symbols. In keeping with Pascal’s idea of
structure, I’ll go from there to reserved words and identifiers, and from there to
data types. After data types I’ll cover operators, expressions, and statements. That’s
mostly a linear, bottom-up approach, and it will help things come back to mind
when you return to these early chapters for review. Some might prefer that I cover
operators before the apparently more complex topic of data types, but trust me:
Data types without operators make more sense than operators without data types.
It will help a great deal if you’ve already read Chapter 3, which presents an
overview of most of the fundamental ideas of Pascal. If you haven’t, you ought to go
back and read Chapter 3 now. The overview material will definitely help bridge the
occasional chicken-and-egg dependencies you’ll find in the next several chapters.
And once you’ve got the core of the language under your belt, the problem goes
away.
Really!
d
e
h
is
n
fi
n
U
Is
Chapter 6.
r
te
Pascal Atoms
p
a
h
C
is
h
P
T
115
116 FreePascal from Square One, Volume 1
FOR I := 1 TO 17 DO
BEGIN
SHR(J);
INC(J)
END;
However, after it removes excess whitespace, the compiler “sees” a continuous and
unformattted stream like this:
FOR I := 1 TO 17 DO BEGIN SHR(J); INC(J) END;
The point here is that how you arrange the lines of code in your program is
not important to the FreePascal compiler. You can indent lines by two spaces per
level (as is my custom) or six or eight spaces. You can place two lines in between
procedures and functions, or three, or whatever you prefer. You can, if you like,
place short compound statements (that is, code falling between BEGIN and END
reserved words) on a single line. Pascal reserved words and identifiers must be
separated from one another by spaces. Beyond that, well, it’s up to you.
Some of the invisible 33 ASCII characters are “control characters” that were originally
designed to control the operation of mechanical teletype printers and later on, CRT
terminals. These are almost all obsolete nowadays and rarely used. Interestingly, one
such control character, the BEL character, was originally used to ring a small mechanical
bell in teletype machines, and later on caused CRT terminals to beep.
Pascal Atoms 117
Numeric Digits
Individually and together, the digits 0-9 are used by Pascal as you would expect: to
express literal numeric values:
8
71
29784
Pascal does not separate large values into groups of thousands with commas, as we
often do when writing ordinary text; for example, 29,784. Placing a comma within
a number will trigger a compiler error.
In addition to expressing literal numeric values, the digits 0-9 can also be part of
the identifiers you create as variable and procedure names; for example, Area51.
More on this a little later.
Alphabetic characters
The alphabetic characters A-Z and a-z are used individually and in combination
to create the names of compiler commands, reserved words, constants, variables,
procedures, and functions. Note well that unlike in some other programming
languages (the C familiar, particularly) character case is not significant. For example,
the FreePascal compiler considers A and a to be the same character except when
present in quoted string literals. As I’ll explain later, within a string literal, case is
significant; ‘Jeff’ and ‘JEFF’ are considered different by the compiler.
Symbols
The ASCII character set includes a number of visible symbols that are neither
numeric digits nor letters of the English alphabet. These include punctuation marks
like ! and ?, arithmetic symbols like + and -, straight and curly brackets { } [ ], slashes,
and a few others. Most such symbols have very specific meanings to the FreePascal
compiler. Some symbols can mean more than one thing; for example, the period
character, which expresses decimal parts of numeric literals, and also references to
fields within records. Sometimes two symbols are combined into a single symbol.
For example, the two symbols <> together mean “not equal to” and the symbols (*
begin a comment.
For the most part, symbols are not allowed within identifiers. That is, you cannot
create a variable named Ham&Cheese. The exception is the underscore character;
Ham_and_Cheese is perfectly legal. More on this later.
118 FreePascal from Square One, Volume 1
Table 6.2 lists the additional reserved words recognized by FreePascal when
operating in Delphi mode, using the $MODE DELPHI switch. Note well that these
are additional to the reserved words in Table 6.1. When operating in Delphi mode,
FreePascal recognizes all of the reserved words in Table 6.1 as well as all the reserved
words in Table 6.2.
Pascal Atoms 119
When FreePascal is operating in its default FreePascal mode (or has been set to
FreePascal mode using the $MODE FPC switch) it enforces a few more reserved
words in addition to all of those enforced in Turbo Pascal 7 mode and Delphi mode.
These are listed in Table 7.3. Again, keep in mind that when operating in FreePascal
mode, the compiler enforces all reserved words listed in Tables 7.1 through 7.3.
In addition to the reserved words shown in Tables 6.1-6.3, there is another list of
predefined words that you should be aware of. These are called modifiers, and they
work in conjunction with certain reserved words to modify what those reserved
words mean to the compiler, hence their name. For the most part, you will have no
call to use them while you’re just learning FreePascal. However, it is important that
you not use them for anything else in your own programs.
The compiler has its own somewhat arcane uses for them, but it will also allow
you to use them if you choose to, as the names of variables, constants, procedures,
or functions. That, however, is a bad idea. I recommend treating the list of modifiers
in Table 6.4 as though they were reserved words. To avoid confusion, especially as
you advance in your skills, use them only where and how they were designed to be
120 FreePascal from Square One, Volume 1
used by FreePascal’s authors. All of them are considered advanced to very advanced
topics, and I will be discussing few if any of them in this first book. For now, treat
them as a list of words to be avoided as you define named elements in your own
programs.
6.3. Identifiers
Your computer creates programs for your use. Programs are collections of things
(data) and steps to be taken in storing, changing, and displaying those things
(statements). The computer knows such things by their addresses in its memory.
The readable, English-language names of data, of programs, of functions and
procedures, are for your benefit. We call such names, taken as a group, identifiers.
They exist in the source code only. Identifiers do not exist in the final executable code file.
Any name that you invent and apply to an entity in a program is an identifier. The
names of variables, of data types, of named constants, of procedures and functions,
and of the program itself are identifiers. An identifier you create can mean whatever
you want it to mean (within Pascal’s own rules and limits) as long as it is unique
within its scope.
The notion of scope is a subtle and important concept that I will explain at length
later on, but broadly put, it indicates what portion of your program the compiler
Pascal Atoms 121
can “see” at any given point in your code. The compiler will complain if it can “see”
more than one item with the same identifier. That is, if you have a variable named
Counter you cannot have a procedure named Counter within the same scope. Nor
can you have another variable (or anything else) named Counter within that scope.
Understanding scope requires that you understand more about program structure
than I’ve explained so far; hold on until we get there.
FreePascal identifiers are sequences of characters of any length up to 255
characters that obey these few rules:
• Legal characters include letters, digits, and underscores. Spaces and
symbols like &,!,*, or % (or any symbol not a letter or digit) are not
allowed.
• Digits (0-9) may not be used as the first character in an identifier. All
identifiers must begin with a letter from A-Z (or lowercase a-z) or an
underscore.
• Identifiers may not identical to any reserved word.
• Case differences are ignored. The letter A is the same as a to the compiler.
• Underscores are legal and significant. Note that this differs from most
older, non-Borland derived Pascal compilers, in which underscores
are legal but ignored. You may use underscores to “spread out” a long
identifier and make it more readable: SORT_ON_ZIP_CODE rather
than SORTONZIPCODE. (A better method that has become the custom
in the Pascal community is to use mixed case to accomplish the same
thing: SortOnZIPCode.)
• All characters are significant in a FreePascal identifier, up to 255
characters. Some ancient Pascal compilers allowed longer identifiers but
ignored any character after the eighth character.
The following are all invalid identifiers that will generate errors:
binary program. They are used by FreePascal to build a “symbol table” of memory
addresses that allow it to generate the executable code file, but they are left behind
when the work is done.
With that in mind, create identifiers that help you read your source code. That’s what
they’re for. An identifier can be too long, of course, but that’s rarely the problem.
A value on the right side of the assignment operator is assigned to the variable on
the left side of the assignment operator. In an assignment statement, there is always
a variable on the left side of the assignment operator. On the right side may be a
constant, a variable, or an expression.
Expressions
An expression in Pascal is a combination of data items and operators that eventually
“cook down” to a single value. Data items are constants and variables. The best way
to understand expressions is to think back to your grade-school arithmetic, and
how you used arithmetic operations to combine two or more values into a single
result. This is an expression, both in basic arithmetic and in Pascal:
17 + 3
The addition operator + performs an add operation on its two operands, 17 and 3.
The value of the expression is 20.
An expression like “17 + 3”, while valid in Pascal, would not be used in a real
program, where the literal value “20” would suffice. It’s a lot more useful to create
expressions that involve variables. For example:
3.14159 * Radius * Radius
This expression’s value is recognizable as the area of the circle defined by whatever
value is contained in the variable Radius. Note here that a Pascal expression is not
the same thing as a Pascal statement, and expressions do not stand alone. To pass
the compiler’s picky standards, expression must always be part of a statement.
Standard Pascal includes a good many different operators for building
expressions, and FreePascal enhances ISO Pascal with a few additional operators.
They fall into a number of related groups depending on what sort of result they
return: Relational, arithmetic, set, and logical (also called “bitwise”) operators.
124 FreePascal from Square One, Volume 1
The column labeled “Precedence” has to do with order of evaluation, which I’ll
return to later on in this book.
The set operators fall into two separate worlds; they’re set operators, obviously,
but they also express certain relationships between sets and set members that return
Boolean values. (I’ll come back to sets later on.) The convention is that any operator
that returns a Boolean value is relational, since Boolean values express the “truth
or falsehood” of some stated relation. The three relational operators that involve
sets, set membership and the two set inclusion operators, will be discussed along
Pascal Atoms 125
with the operators that return set values, in Section X.X. Note that the set inclusion
operators share symbols with the greater than or equal to/less than or equal to
operators, but the sense of these two types of operations are radically different.
Some of the types mentioned briefly in this section are types I haven’t yet
explained in detail. Most of these will be covered in the next chapter except for
pointers, which will have to wait until considerably later on. The mentions are here
not so much for you to read on your first linear pass through this book, but on those
occasions when you return to this section for a brushup.
Equality
If two values compared for equality are the same, the expression will evaluate as
True. In general, for two values to be considered equal by Turbo Pascal’s runtime
code, they must be identical on a bit-by-bit basis. This is true for comparisons
between like types. Most comparisons must be done between values of the same
type.
The exceptions are comparisons done between numeric values expressed as
different types. Turbo Pascal allows comparisons rather freely among integer types
and real number types, but this sort of type-crossing must be done with great care.
In particular, do not compare calculated reals (real number results of a real number
arithmetic operation) for equality, either to other reals or to numeric values of other
types. Rounding effects may cause real numbers to appear unequal to compiled
code even though the mathematical sense of the calculation would seem to make
them equal.
Integer types Byte, ShortInt, Word, Integer, and LongInt may be freely
compared among themselves.
Two sets are considered equal if they both contain exactly the same members.
(The two sets must, of course, be of the same base type to be compared at all.) Two
pointers are considered equal if they both point to the same dynamic variable. Two
pointers are also considered equal if they both point to NIL.
Two records are considered equal if they are of the same type (you cannot
compare ecords of different types) and each field in one record is bit-by-bit identical
to its corresponding field in the other record. Remember that you cannot compare
records, even of the same type, using the greater than/less than operators >, <, >=,
or <=.
Two strings are considered equal if they both have the same logical length (See
Section X.X) and contain the same characters. This makes them bit-by-bit identical
out as far as the logical length, which is the touchstone for all like-type equality
comparisons under Turbo Pascal. Remember that this makes leading and trailing
126 FreePascal from Square One, Volume 1
blanks significant:
Inequality
The rules for testing for inequality are exactly the same as the rules for equality. The
only difference is that the Boolean state of the result is reversed:
17 = 17 { True }
17 <> 17 { False }
42 = 17 { False }
42 <> 16 { True }
In general, you can use the inequality operator anywhere you can use the
equality operator.
Pointers are considered unequal when they point to different dynamic variables,
or when one points to NIL and the other does not. The bit-by-bit rule is again
applied: Even one bit’s difference found during a like-type comparison means the
two compared operands are unequal. The warning/ applied to rounding errors
produced in calculated reals applies to inequality comparisons as well.
The higher 128 values assignable to Char variables have no truly standard characters
outside of the PC world, but they still exist in fixed order and are numbered from
128 to 255.
Enumerated types are limited to no more than 255 different values, and usually
have fewer than ten or twelve. Their fixed order is the order the values were given in
the definition of the enumerated type:
TYPE
Colors = (Red,Orange,Yellow,Green,Blue,Indigo,Violet);
The ordering of string values involves two components: The length of the string
and the ASCII values of the characters present in the string. Essentially, Turbo
Pascal begins by comparing the first characters in the two strings being compared.
If those two characters are different, the test stops there, and the ordering of the two
strings is based upon the relation of those two first characters. If the two characters
are the same, the second characters in each string are compared. If they turn out to
be the same, then the third characters in both strings are compared.
This process continues until the code finds two characters that differ, or until
one string runs out of characters. In that case, the longer of the two is considered to
be greater than the shorter. All of the following expressions evaluate to True:
128 FreePascal from Square One, Volume 1
The parentheses indicate that the expression within the parentheses is evaluated
first, and only then is the resultant value acted upon by NOT. This expression is an
instance where “order of evaluation” becomes important. I’ll discuss this in detail
in Section X.X.
AND (also known as “conjunction”) requires two operands, and follows this
rule: If both operands are True, the expression returns True; else the expression returns False.
If either operand or both operands have the value False, the value of the expression
as a whole will be False. Some examples:
All of these example expressions use constants, and thus are not realistic uses of
Pascal Atoms 129
AND within a program. We present them this way so the logic of the statement is
obvious without having to remember what value is currently in a variable present
in an expression. We’ll be presenting some real-life coding examples of the use of
NOT, AND, and OR in connection with the discussion of order of evaluation in
Section X.X.
OR (also known as “disjunction”) requires two operands, and follows this rule:
If either (or both) operands is True, the expression returns True; only if both operands are False
will the expression return False.
Some examples, again using constants:
Finally, there is XOR, which also requires two operands, and follows this rule: If
both operands are the same Boolean value, XOR returns False; only if the operands have unlike
Boolean values will XOR return True. Some examples:
X >= Y
(X > Y) OR (X = Y)
X <= Y
(X < Y) OR (X = Y)
The rules for applying >= and <= are exactly the same as those for < and >. They
may take only scalars or strings as operands.
Note that for the purposes of the table, “Integer” types include Integer, LongInt,
ShortInt, and SmallInt. “Cardinal” types include Word, Byte, LongWord,
Cardinal. “Real” types include Real, Single, Double, Extended, and Currency.
The old Comp type inherited from Borland Pascal is also considered a real type, but
it is not implemented on all platforms and I recommend that you not use it.
There are a lot of numeric types, and there are “gotchas” connected with some of
them, like Comp. I’ll explain numeric types in a great deal more detail in the next
chapter.
The Table 6.6 “operands” column lists those data types that a given operator
may take as operands. The compiler is fairly free about allowing you to mix types
Pascal Atoms 131
of numeric variables within an expression. In other words, you may multiply bytes
by integers, add reals to bytes, multiply integers by bytes, and so on. For example,
these are all legal expressions in FreePascal:
VAR
I,J,K : Integer;
R,S,T : Real;
A,B,C : Byte;
U,V : Single;
W,X : Double;
Q : ShortInt;
L : LongInt;
The “result type” column in the table indicates the data type that the value
of an expression incorporating that operator may take on. Pascal is ordinarily
very picky about the assignment of different types to one another in assigment
statements. This “strict type checking” is relaxed to some extent in simple arithmetic
expressions. Numeric types may, in fact, be mixed fairly freely within expressions
as long as a few rules are obeyed:
1. Any expression including a floating point value may only be assigned
to a floating point variable.
2. Expressions containing floating point division (/) may only be assigned
to a floating point variable even if the operands are integer types.
Failure to follow these rules will generate the following error message:
Error 26: Type mismatch.
Division
There are three distinct division operators in Pascal. One supports floating point
division, and the other two support division for integer and cardinal types. Floating
point division (/) may take operands of any numeric type, but it always produces a
floating point value, complete with decimal part. Attempting to assign a floating
point division expression to an integer type will generate error #26, even if all numeric
variables involved are integers:
VAR
I,J,K : Integer;
I := J / K; { Won’t compile!!! }
Division for numbers that cannot hold decimal parts is handled much the same
way division is first taught to grade schoolers: When one number is divided by
another, two numbers result. One is a whole number quotient; the other a whole
number remainder.
In Pascal, integer division is actually two separate operations that do not depend
upon one another. One operator, DIV, produces the quotient of its operands:
J := 17;
K := 3;
I := J DIV K; { I is assigned the value 5 }
No remainder is generated at all by DIV, and the operation should not be considered
incomplete. If you wish to compute the remainder, the modulus operator (MOD)
is used:
I := J MOD K; { I is assigned the value 2 }
Assuming the same values given above for J and K, the remainder of dividing J by K
is computed as 2. The quotient is not calculated at all (or calculated internally and
thrown away); only the remainder is returned.
Sign inversion
Sign inversion is a “unary” operator; that is, it takes only a single operand. What it
does is reverse the sign of its operand. It will make a positive quantity negative, or a
negative quantity positive. It does not affect the absolute value (distance from zero)
of the operand. Note that sign inversion cannot be used with cardinal types like
Cardinal, Byte, Word, or LongWord. Cardinal types are “unsigned”; that is, they
are never considered negative, and so changing the sign of the value is impossible.
Pascal Atoms 133
The variable’s identifier comes first, followed by a colon and then the name of the
type that you choose to define that variable by. The definition shown above allows
you to manipulate integer values in a variable called CreditHours, subject to
Pascal’s explicit limitations on what can be done with Integer data types.
I didn’t show it explicitly in the above definition, but variable definitions must
reside in the variable definition section of a Pascal program. The reserved word
VAR begins the variable definition section, and it runs until another program
section (say, a procedure or a function, or the main program) begins. The variable
definition section of a program (and there may be more than one in Turbo Pascal) is
where you give names to variables and assign them types. We’ll speak more of the
several sections of a Pascal program when we get into program structure later on.
In the meantime, you can refer back to a complete Pascal program with a variable
definition section on Page 80.
137
138 FreePascal from Square One, Volume 1
• Word is like Byte in that it is unsigned and cannot hold negative values.
Like Integer it occupies two bytes of memory. Word types are sometimes
referred to, in fact, as “unsigned integers.” They may contain values from
0 to 65,535. Word variables are handy at times because they can hold
positive numbers twice as large as type Integer can.
• LongInt is what its name implies: A “long integer.” It occupies four bytes
in memory rather than two, as Integer types do. Their range is hugely
greater than Integer, however, and can express values from -2147483648
to 2147483647. Note again that you cannot use commas to break up the
expression of large numbers in Pascal, as we often do in ordinary day-
to-day correspondence. So while spitting out a number like 214748647
seems awkward without the commas, do get used to it: it’s simply the way
we do things in programming.
• ShortInt is another numeric type related to Integer, in that it holds
signed numeric values. Its range, however, is limited to -128 to 127, and it
occupies only one byte in memory. It is, in fact, a “signed byte.”
There are a number of additional numeric values defined in FreePascal. These are
the real number types modeled on the CPU’s “in silicon” real-number support, and
I’ll address them in detail later, in Section X.X.
In this line of code, “4” and “3” are literal constants, representing the numeric values
of 4 and 3.
There is another constant in that statement: The identifier PI was previously
declared a constant in the constant declaration part of the program. The constant
Pascal Atoms 141
declaration part begins with the reserved word CONST and runs until some other
part of the program begins. The constant declaration part is typically very early in a
program, and is often the very first part of a program after the program name:
PROGRAM AreaCalc;
CONST
PI = 3.14159;
Here, PI is a named constant. We could as well have used the literal constant
3.14159 in the statement, but “PI” is shorter and makes the expression less cluttered
and more readable. Especially where numbers are concerned, named constants
almost always make a program more readable.
Another use for constants is in the setting of program parameters that need
changing only very rarely. They still might be changed someday, and if you use a
named constant, changing the constant anywhere in the program is only a matter of
changing the constant’s declaration once in the constant declaration part of the
program and then recompiling.
The alternative is to hunt through hundreds or thousands of lines of source code
to find every instance of a literal constant to change it. You will almost certainly
miss at least one, and the resultant bug explosion may cost you dearly in time and
torn hair.
In short, don’t use literal constants anywhere you will ever anticipate needing
changes. In mathematical formulae literal constants are usually OK; but keep in
mind that using a named constant in place of a literal constant allows you to control
the precision of the constant everywhere in the program, from one constant
definition. You may want to use pi to eight decimal places initially, but later on, to
improve program performance, you may decide that five decimal places is plenty.
If you define the mathematical constant pi in a named constant at the front of your
program, you can change the precision instantly just by changing the definition—
and not have to worry about forgetting one or two places where you had hard-
coded a specific value of pi into an expression.
Structured types like records, pointers and arrays may not be constants in Standard
Pascal. FreePascal supports data structure constants, (see Section X.X) but I must
explain data structures first before going into those.
Here are some example named constants of various types:
CONST
PI = 3.14159; { Floating point real }
Threshold = -71.47; { Negative FP real }
PenIOAddress = $06; { Hexadecimal value }
Using8087 = True; { Boolean }
DriveUnit = ‘A’; { Character }
Revision = ‘V2.61B’; { String }
Answer = 42; { Integer }
NotAnswer = -42; { Negative integer }
YesSet = [‘Y’,’y’]; { Set }
NullString = ‘’; { Null (empty) string }
BigNumber = 6117834 { Long integer or real }
I haven’t said much about strings yet (and will cover them in detail in Chapter
X) but string literals are easy to understand: You enclose some sequence of ASCII
characters between single-quote marks:
‘Call me Ishmael. In fact, call me anything but late for dinner.’
Literal string constants like this may be assigned to string variables later on in
the program.
because Answer has been defined as a constant that already has a value of 42.
There is an important difference between constants and variables. In FreePascal,
simple constants are written into the code by the compiler as what we call immediate
data. This is difficult to explain if you don’t have some grasp of how computers
work down at the silicon level, but think of it this way: The value represented by a
simple constant is written into your program every place you use it. If you were to
define the Answer constant as shown above and reference it twelve times in your
program, the compiler would store Answer’s equivalent binary value (here, 42)
twelve times in your program code.
Pascal Atoms 143
Variables, by contrast, are kept separate from the code portion of a program, and
each variable is stored in only one place. Your program has a data segment in memory
where it stores its variables, and a named variable is present in the data segment
only once. To access the value stored in a variable, your program must use a memory
reference into the data segment to the place where the variable’s value is stored.
This isn’t something you need to know a lot about, and (especially while you’re a
beginner) where a variable is stored in memory and how the variable is represented
in memory aren’t terribly important. The important thing to remember is this:
• A constant is defined at compile time and cannot be changed whiel your
program is running.
• A variable is not given a value until your program gives it one at runtime,
and that value may be changed by your program at any point while the
program runs.
The type of a constant depends, to some extent, on its context. Consider:
PROGRAM AllTheAnswers;
CONST
Answer = 42;
VAR
Tiny : Byte; { One byte }
Little : ShortInt { A short integer (1 byte) }
Small : Integer; { An integer (2 bytes) }
Big : LongInt { A long integer (4 bytes) }
Huge : Real; { A real number (8 bytes) }
BEGIN
Tiny := Answer;
Little := Answer;
Small := Answer;
Big := Answer;
Huge := Answer;
END.
In the code snippet given above, Answer’s value is defined as 42. But it is perfectly
legal to assign the value of Answer to type Byte, type Integer, type ShortInt, type
LongInt, or type Real. The code the compiler generates to do the assignment in
each case is a little different, and that code is smart enough to translate the numeric
value “42” into a binary number that will be properly expressed as type Byte,
Integer, ShortInt, LongInt, or Real, or any other numeric type supported by the
compiler. (There are a few others that I’ll explain later on. FreePascal really does
have a numeric type for every occasion.) But the end result is that all five variables
of five different types will each express a numeric value of 42 in its own fashion.
144 FreePascal from Square One, Volume 1
I cover the hexadecimal system and hex numbers in great detail in my print book,
Assembly Language Step By Step, Third Edition (John Wiley & Sons, 2009).
Inside string literals, lower case and upper case characters are distinct. If you
wish to include a single quote mark as a character inside a string literal, you must
use two single quotes together:
Writeln(‘>>You haven’’t gotten it right yet...’);
• Pascal operators. These are the basic arithmetic operators like addition
and subtraction, the logical operators like AND and OR, and the
bitwise operators like AND, OR, SHR, SHL, and so on. For a complete
discussion of FreePascal’s operators, see Chapter X.
• Certain built-in functions. A very few of FreePascal’s built-in functions may
take part in constant expressions. These include Ord, Chr, Odd, Hi,
Lo, Length, Abs, Pred, Succ, and Swap. All other functions, including
those you write yourself and those built into the compiler (including Sqr
and Cos) are illegal. For those of you who can appreciate the differences
at this point in your understanding of Pascal, FreePascal generates code
for “functions” like Abs in-line (in the fashion of an assembly language
macro) while other functions like Sqrt and Cos are true Pascal functions
that must be called like any other functions from the FreePascal runtime
library. Abs and its kin are more properly macros than functions, and can
be evaluated in-line by the compiler during compilation.
Although it might be obvious to veteran Pascal programmers, it’s worth stating
clearly that variables cannot be part of constant expressions. FreePascal allows constants
to be defined after variables are declared (as Standard Pascal does not) but not after
variables are assigned values. This means that a variable would introduce an undefined
quantity into a constant expression, which can cause a lot of trouble at runtime.
LongSide = 17;
ShortSide = 6;
TankDepth = 8;
Volume = LongSide * ShortSide * TankDepth; { Constant expression }
Pascal Atoms 147
{ Base I/O port is $3F8 for COM1: and $2F8 for COM2: }
PORTBASE = COMBASE OR (COMPORT SHL 8);
Don’t panic if most of this doesn’t make immediate sense to you! What matters
here is knowing how each of the identifiers in the example above is given a value.
Every one of the constants defined in the example code fragment has a different
value depending on whether the COM1: or COM2: serial ports is to be used. By
changing the value of the constant COMPORT from 1 to 2, all the other constants
change accordingly to the values that apply to serial port COM2:. The program
does not need to be peppered with magic numbers like $2FC and $3FA. Also,
your program does not need to spend time initializing all these port numbers as
variables, because the compiler does all the calculation at compile time, and the
resulting values are inserted as immediate data into the code generated from your
source file.
The other use for constant expressions helps your programs document
themselves. You may need some sort of mathematical “fudge factor” in a complicated
program. You can define it as a simple named real-number constant:
FudgeFactor = 8.8059;
No one, looking at the literal numeric value, would have any idea of its derivation.
If the value is in fact the result of an established formula, it can help readability to
make the formula part of a constant expression:
ZincOxideDensity = 5.606;
FudgeFactor = ZincOxideDensity * (PI / 2);
This will help others (or maybe even you) keep in mind that you had to fudge things
by multiplying the density of zinc oxide by Pi over 2. (That is, assuming you want
the world to know...)
The idea should never be far from your mind that Pascal programs are meant
to be read. If you can’t read them, you can’t change them (or fix them) and then you
might as well throw them away and start from scratch. Do whatever you can to
make your programs readable. You (or whoever will someday inherit and have to
work with your code) will be glad you did.
them in the next section, as there are complications unique to numeric types that
will take some time to explain. Enumerated types are also considered ordinal, but
I’ll treat them separately in Chapter X.
Characters
The best way to explain Pascal’s ordinal types is through a close look at the most
common such type: Char.Type Char (character) is an ISO Standard Pascal type,
present in all implementations of Pascal. Type Char includes the familiar ASCII
character set: Letters, numbers, common symbols, and the control characters
like carriage return, backspace, tab, etc. There are 128 characters in the ASCII
character set. But type Char actually includes 256 different values, since a character
is expressed as an eight-bit byte. (Eight bits may encode 256 different values.)
The “other” 128 characters have no standard names or meanings in the ASCII
character set. When displayed on a device that supports their glyphs, the “high” 128
characters show up as foreign language characters, fractions, segments of boxes, or
mathematical and other miscellaneous symbols.
How, then, to represent such characters in your program? The key lies in the
concept of ordinality. There are 256 different characters included in type Char.
These characters exist in a specific ordered sequence numbered 0,1,2,3 and onward
up to 255. The 65th character (counting from 0, remember) is always capital A. The
32rd character is always a space, and so on.
An ordinal number is a number indicating a position in an ordered series. A
character’s position in the sequence of type Char is its ordinality. The ordinality
of capital A is 65. The ordinality of capital B is 66, and so on. Any character in
type Char can be unambiguously expressed by its ordinality, using the standard
“transfer function” Chr. A capital A may be expressed as the character literal ‘A’. It
may also be expressed as Chr(65). The expression Chr(65) may be used anywhere
you would use the character literal ‘A’.
Beyond the limits of the displayable ASCII character set, the Chr function is the
only reasonable way to express a character. The character expressed as Chr(234)
will display on the PC-compatible screena as the Greek capital letter omega (Ω) but
may be displayed as something else on another computer that is not PC-compatible.
It is best to express such characters using the function Chr.
What will Pascal allow you to do with variables of type Char?
1. You can write them to the screen or printer using Write and Writeln:
Writeln(‘A’);
Write(Chr(234));
Write(UnitChar); { UnitChar is a variable of type Char }
150 FreePascal from Square One, Volume 1
2. You can concatenate them with string variables using the string
concatenation operator (+) or the Concat built-in function: (See Section
X.X)
ErrorString := Concat(‘Disk error on drive ‘,UnitChar);
DriveSpec := UnitChar + ‘:’ + FileName;
3. You can derive the ordinality of characters with the Ord transfer
function:
BounceValue := 31+Ord(UnitChar);
8.5. Booleans
Type Boolean is part of ISO Standard Pascal. A Boolean variable has only two
possible values, TRUE and FALSE. Like type Char, type Boolean is an ordinal
type, which means it has a fixed number of possible values that exist in a definite
order. In this order, FALSE comes before TRUE. By using the transfer function
Ord you would find that:
Ord(FALSE) returns the value 0.
Ord(TRUE) returns the value 1.
Pascal Atoms 151
The status of the words TRUEand FALSEis a little tricky. In older versions
of Pascal, including both the Borland Pascals and Delphi, TRUEand FALSE are
predefined identifiers with no special status beyond that. The compiler predefines
them as constants of type Boolean. This means that if you really want to, you
can give TRUE and FALSE some other definition in your programs, as constants
or variables. (This is a very bad idea and I don’t recommend it.) When FreePascal
is operating in Turbo mode ($MODE TP) or Delphi mode ($MODE DELPHI) this
remains the case. However, in FreePascal’s native mode ($MODE FPC) TRUE and
FALSE are reserved words and may not be redefined. Unless you explicitly specify
one of the other modes, FreePascal operates in FreePascal mode, so by default
TRUE and FALSE are reserved words. I think this is a good idea, and the upper-
case expression of TRUE and FALSE in the rest of this book reflects it.
A Boolean variable occupies only a single byte in memory. The actual words
True and False are not physically present in a Boolean variable. When a Boolean
variable contains the value TRUE, it actually contains the binary number 01.
When a Boolean variable contains the value FALSE, it actually contains the binary
number 00. If you write a Boolean variable to a disk file, the binary values 00 or 01
will be physically written to the disk. However, when you print or display a Boolean
variable using Write or Writeln, the binary values are recognized by program
code and the words “TRUE” or “FALSE” (in uppercase ASCII characters) will be
substituted for the binary values 00 and 01.
Boolean variables are used to store the results of expressions using the relational
operators =, >, <, <>, >=, and <=, and the set operators +, *, -. Operators and
expressions will be discussed more fully in Section X.) An expression such as “2
< 3” is easy enough to evaluate; logically you would say that the statement “two is
less than three” is “true.” If this were put as an expression in Pascal, the expression
would return a Boolean value of True, which could be assigned to a Boolean
variable and saved for later processing:
OK := 2 < 3;
This assignment statement stores a Boolean value of TRUE into the Boolean variable
OK. The value of OK can later be tested with an IF..THEN..ELSE statement, with
different actions taken by the code depending on the value assigned to OK:
OK := 2 < 3;
IF OK THEN
Writeln(‘>>Two comes before three, not after!’)
ELSE
Writeln(‘>>We are all in very serious trouble...’);
152 FreePascal from Square One, Volume 1
Boolean variables are also used to alter the flow of program control in the
WHILE..DO statement and the REPEAT..UNTIL statement. (See Sections X.X
and X.X.)
Pascal Atoms 153