Make BASIC run PDQ. (Column)
by Tom Campbell
This month we'll look at software and a book by the same author, and we'll examine a program that requires a commercial toolkit.
Ethan Winer, a widely published BASIC columnist, has released a superb $29.95 Ziff-Davis Press book-and-disk combination, BASIC Techniques and Utilities, that should find its way onto the shelf of anyone who wants to go beyond the QuickBASIC and PDS 7 manuals.
This is one of the few books available for the serious BASIC programmer who's advanced beyond the fundamentals, and it hits every target in the bull's-eye.
The example code is always useful: random access files with indexing, reading and writing dBASE files, soundex pattern matching, directory searching with DOS services, and quite a bit more. One of my favorites is a section on sorting files--that is, quantities of data that won't fit into memory. Most authors shy away from this subject because it's just too difficult, but Winer makes short shrift of it. That's one of his strongest points; in fact, he's made a lucrative career giving away valuable information by the boatload.
The file-sorting program is a good example of the scope of Winer's code; the book and disk are crammed with eminently usable routines wrapped in effective demo programs.
Winer doesn't blink at discussing ways to make use of undocumented QuickBASIC internals or making explicit the secrets he uses to write his own software, and his lucid writing is a remarkable contribution to BASIC literature.
There are always a few more topics you could cram into a book like this--I would've appreciated help on dealing with pointers to BASIC's compound data types in MASM and debugging such code under CodeView--yet in no way is the technical content of this excellent book incomplete.
Basic PDQ
Winer also happens to be founder of Crescent Software (203-438-5300), a BASIC tools vendor. This month we'll take a look at Crescent's PDQ, a $149 toolkit that lets you create BASIC memory-resident programs almost effortlessly, reduces the size of BASIC EXE files dramatically by replacing the BASIC runtime library, and offers scores of routines from Sort to StuffBuf.
PDQ works this magic at the cost of some compatibility, but the differences are explained in complete and forthright detail at the front of the manual, and they're all solid decisions (limited but quite adequate support for floating-point numbers, background PLAYs eliminated, arrays limited to only 32K elements per dimension, fewer runtime errors, case preserved in COMMAND$, and so on).
The upshot of it is that you can create very useful TSRs in 10 or 12K, and a version due to be out soon will also support swapping TSRs.
PDQ is also the ideal product for those unfortunate souls who are still using very early versions of the IBM BASIC compiler (which can essentially do nothing more than compile GW-BASIC) in order to keep code size down to the barest minimum. The extra routine (such as Sort, which QuickSorts string arrays, and StuffBuf, which writes directly to the keyboard buffer) aren't meant to form a coherent body; I regard them as bonuses to an already tremendous value.
There are lots of great example programs on the disk, and the manual explains everything beautifully, but it lacks an index and needs more example programs.
PDQ in Action
This month's example presents a rather personal project of mine, a TSR that lets you draw, move, and resize a box onscreen, printing the coordinates so that you can experiment with the box before writing a DrawBox statement. I can't count the times I've had to recompile programs solely because of one changed parameter in a box-drawing routine or the times I've wished for such a TSR. Since I didn't have time to write one in assembly, I did without. PDQ let me write one in almost no time.
To understand how PDQ does what it does and to come to terms with the very few limitations it places on your BASIC programming, you may need a short review of compiler theory and BASIC itself. Some BASICs translate to inline assembly. For example, assigning a value of 1 to the integer variable CurrRow, like this:
CurrRow = 1
translates into this modest amount of assembly code.
MOV AX, 1 MOV [underscore]Currow, AX
But more often than not, BASIC's simplicity as a language belies an incredibly complicated group of subroutines to handle even many apparently simple operations. For example, you've probably already guessed that at the heart of such statements as CIRCLE, DRAW, and INPUT# are pages upon pages of assembly code. And you're right. Take this program as an unlikely illustration of the iceberg principle (90 percent of an iceberg lies unseen beneath the surface of the water).
' Use integers by default. DEFINT A-Z ' Allow user to enter two integers ' separated by a comma. INPUT X, Y ' Divide them and print ' the quotient. PRINT X / Y
This program, compiled as a stand-alone EXE file without debugging, requires a huge 29K. That's because QuickBASIC is making a lot of the decisions for you when it links in the runtime code, and a lot of unnecessary routines wind up in the EXE.
The subroutines that make up such statements as DRAW, INPUT#, and so on are called the runtime library. If you linked all these routines in by hand, you could compile smaller programs.
BASIC also assumes your input will be bad in some cases. For example, if you entered a value of 0 for Y in the short program above, BASIC would issue a runtime error and quit the program. Sounds bad, but if you did the same thing in a C program, the operating system would print Divide error, and your system would hang! So if you eliminated some of the error checking or streamlined the existing error checking, you'd save even more space. That's just what Crescent did with PDQ. I easily reduced the EXE size of the program above to 6K using PDQ.
BOX.BAS shows how I used PDQ to write that box-drawing program. (Note that you need PDQ to compile this program.) PDQ is an astounding product, and it makes things possible in BASIC that you couldn't do before.