Dr.Godfried-Willem RAES
Kursus Experimentele Muziek
: Boekdeel 1: Algoritmische kompositieHogeschool Gent : Departement Muziek & Drama
< Terug naar inhoudstafel kursus> |
1600:
Programmeerhulpjes
Wie reeds enige ervaring opdeed met programmeren zal zich wel reeds vaak hebben geergerd aan de schier eindeloze reeksen telkens weer te herhalen toets- of muis-instrukties die de programmeeromgeving van ons vergt wanneer we willen kompileren.
Ergernis ook, over de moeilijkheden waarmee we onvermijdelijk te maken krijgen bij het uiteenhouden van diverse versies van onze software.
Over de moeilijkheid telkens weer goed leesbare listings uit onze printer tevoorschijn te toveren, en over de noodzaak een goede historiek van een programma bij te houden.
Aan dit soort laag-bij-de grondse problemen willen we hier ook wat aandacht besteden, en enkele nuttige en vooral tijdsparende tips geven.
Een eerste hoofdstukje hebben we ontleend aan Daniel Smith, en heeft betrekking op het werken met libraries binnen QBX. We hebben de tekst geaktualiseerd en bijgewerkt en in deze vorm sluiten we hem bij:
LIBRARIES AND INCLUDE FILES
This document consists of a basic tutorial on BASIC include files and libraries. It is included with my libraries by the kind permission of the author. The text has been edited for consistency with my existing documentation and includes minor alterations where I considered them helpful. While the following might be considered mundane by experienced programmers, its always nice to have a good foundation to begin building on. With that in mind, the examples and discussion of topics will be in relatively layman terminology. To give you an excellent grasp of each idea presented, examples and step-by-step procedures will be given. If you are using QBX Professional Development System, the information presented here is applicable to all, although some older versions may present specific problems regarding arguments and syntax. In fact, it is germaine to all higher level languages but specifically to the many forms of BASIC which is the language we are concerned about.
Many routines have been developed by programmers to accomplish tasks within the BASIC environment. Some are simple, yet others are extremely complex, possibly requiring memory allocation, etc. Since these routines are already available why waste time trying to re-invent the wheel so to speak; include the ones you require into your program with the $INCLUDE Metacommand (hardly layman language, so lets take time right now to find out about this special terminology).
Metacommands are special commands that are used to make your programs perform in a specific fashion. BASIC has three such commands; two ($DYNAMIC and $STATIC) which deal with allocation of dimensioned arrays and the $INCLUDE command which provides a means of incorporating external programs or routines into your programs. It specifically tells the compiler to stop processing the current program in favor of the program directed by the $INCLUDE Metacommand. When the included program ends, execution returns to the next line of the main program following the included routine.
We are only concerned here with $INCLUDE since it is the means by which all external routines are usually made a part of the main program. There is a specific syntax required with all metacommands that needs to be emphasized; most curious is that these commands are always preceded by REM or the apostrophe character. The following is the correct syntax for $INCLUDE:
REM $INCLUDE: MyFile.BI
or
$INCLUDE: MyFile.BI
More than one metacommand can be placed on the same line as long as they are separated by white space. The other two metacommands dont require an argument, so no colon (delimiter) is required when using them. Note that the above argument is enclosed by single quotation marks (apostrophes).
What is a ".BI" file? Nothing can be more frustrating than trying to figure out what constitutes an include file when you have never been near one before. Forget trying to track it down in reference books!! Here it is in a nutshell and will save you a lot of time.
First, it doesnt have to have the ".BI" extension at all, but thats the common extension used for BASIC Include files. Second, no SUB or FUNCTION programming statements are permitted in the file; and Third, include files must be in ASCII format. A ".BI" file then is simply the declaration statements identifying the external subroutine or function that you want to be included into the main program. The following syntax is what you could expect to find in a typical ".BI" file. Lets call it WINDO.BI.
The metacommand is:
REM $INCLUDE: WINDO.BI
The contents of the file might be:
DECLARE SUB Windo (TRow%, LCol%, BRow%, RCol%)
DECLARE SUB Colour (ForeGrd%, BackGrd%, Scrn%)
DECLARE SUB Border (Style%, Title$)
DECLARE SUB WritWin (FC%, BG%, Text$)
(etc)
The list could go on to include other windowing capabilities such as saving the screen the window pops up on, restoring the screen when the window is closed, etc. Whatever the routine or function you wish to include in your program requires a definition statement similar to the above in the ".BI" file. The actual program defined is, of course, located in a library of subroutines; you are only telling the program to expect these particular subroutines to be called elsewhere in the program. If it were not for the ".BI" file and the declarations contained therein, when the program reached the call to the subroutine a "SUBPROGRAM NOT DEFINED" error message would be encountered. Every subroutine and function must be defined either at the beginning of the main module or in the ".BI" file if it is to be called during program execution. I should also point out here that all arguments (ie., those within the parentheses in the examples above) must be established in your program before you make the call to the external subroutine. The % arguments require integers and $ arguments require strings.
Lets assume you have a key trapped that directs your program to a label called WIN. We would expect to find something like the following:
WIN:
TRow% = 8: LCol% = 20: BRow% = 18: RCol% = 60
BackGrd% = 2: ForeGrd% = 15: Scrn% = 0
Style% = 1: Title$ = "TEST WINDOW"
Now that the parameters are established:
Border Style%, Title$
Colour ForeGrd%, BackGrd%, Scrn%
Windo TRow%, LCol%, BRow%, RCol%
The parameters can be set when the function is used, for example:
LOCATE 10, 25
WritWin 14, 4, "This is only a test!"
By the way, why use Colour instead of Color, or Windo instead of Window? Because COLOR and WINDOW are BASIC keywords! We cant use them, since they are already defined to mean something else. Sometimes you have to be careful with names.
Declaration is not required for GOSUB, since you never have to pass any arguments explicitly. The GOSUB statement is kind of a specialized version of GOTO, not a subroutine in the sense that a SUB or FUNCTION is.
Hopefully, this will help you to a proper perspective of ".BI" files.
NOW!! Here comes the big one. We will step through this very slowly because libraries are the backbone of programming. Each time a programmer prepares a method to accomplish a certain job, it becomes candidate for retention, since the same routine might be required again (either by himself or other persons who program in the same language). These routines are normally placed in libraries. It could be a small library, or, if many routines have been created, it could be quite large. The term "library" is very appropriate, because (like books) routines can be removed from programming libraries and used when you need them, but do not need to be kept in your program when you dont. Much work and research go into solving specific tasks or coming up with better and more efficient ways of doing a particular job. Making these great routines available to others makes programming so much easier because you wont have to waste time trying to come up with the same routine again. Just extract it from the provided library and place in a new library you are going to use. Very easily said, but it takes considerable doing. This is exactly what we are going to examine now.
We will step through the entire procedure for creating a new library exactly in the same order as you should every time you decide to use someone elses QBX library routines.
First you must decide which routines you are going to need from the library. Make a list of the names of each routine on paper leaving room on the right for additional information. You will realize the advantage of doing this shortly.
Next, you must have a listing (.LST) file of the library to find out the specific module file the routine is located in. When .OBJ files are placed in libraries they no longer have an extension associated with them; they are merely modules within the library. However, when they are extracted (as we will see later) they are given the .OBJ extension once again by LIB.EXE which is the default. Programmers often place related routines in one module file within the library. If a routine exists in its own module file then extracting that module file will provide you with that particular routine; however if several routines exist in one module file you cant extract a specific routine you must extract the entire module file. Therefore, just because we know the name of a routine does not necessarily give us access to that routine because it could be in a module file with an entirely different name. When you see your first listing file you will more readily discern what I mean. If the routines are contained in one library and the programmer has provided both ".QLB" and ".LIB" files you will not need a list file if you use the programmers libraries. Otherwise, if no listing (.LST) file exists for the library it will be necessary to create one.
That brings us to our next step, creating a .LST file.
LIB.EXE is the library management tool that comes with most of the versions of BASIC that include a compiler. Some programmers huge libraries may be too large for some older versions of LIB.EXE and if so the programmer will make you aware of that in his readme file or other documentation. PDS/QBX 7.x seem quite up to tackling all library tasks.
To create the .LST file enter:
LIB LIBRARY.LIB
where LIBRARY.LIB is the name of the library requiring the listing file. The .LIB extension is not really required, since LIB.EXE knows it will be working with a .LIB file. NOTE:
LIBRARY.LIB is always replaced with the actual name of a library in the following examples; xx in a QBX .LIB file name is replaced with the actual number of your version. LIB.EXE and the library must be in the same directory. To make everything simple I usually create a special subdirectory for the library and copy LIB.EXE to it along with the library files I intend to use. Also copy LINK.EXE to the same subdirectory for future use. There will be quite a bit of activity in this directory; this will keep everything a little organized. If something goes wrong its easy to identify the erroneous files and start over again without having to search for the files we created and maybe erase something inadvertantly.
After pressing enter in example above you will see the following:
Operations: press Enter to continue
Since we did not define any operation on the command line LIB is prompting for direction; none is required at this time. Next you see:
List file:
type LIBRARY.LST and press EnterYou can name the list file anything you wish but it would be advisable to name it the same as the library to avoid confusion. The .LST file will be created in the current subdirectory. You can use any text editor to view the file. Dos EDIT does this just nicely. To redirect the list file, unformatted, to printer, type the following:
TYPE LIBRARY.LST >PRN
List files are in two columns. Each column has two text entries divided by dots. The left entry is the subroutine name; the right is the module file to which it belongs. Some module file names are really quite cryptic; also as mentioned before some have the same name as the subroutine. Related routines will probably be in a single module file.
Using the example .BI file we looked at before, you might see this in the listing file of the library containing those subroutines.
WINDO...............wnd
COLOR...............wnd
BORDER..............wnd
WRITWIN..........writwn
Please note that all of the above could have been in the same module or in all different modules. Notice also that the module file "writwn" is not spelled the same as the subroutine. Programmers may change the name of .OBJ files, sometimes just by abbreviating the name of the routine.
Now that we have the .LST file we can really get down to work. First we must select the routines that will be needed for inclusion into the main program and identify the module(s) to which they belong. We will continue to use the WINDO example throughout this instruction.
The next step is to copy the module files from the Library. The .LST file has shown us the names of the module files we need to make our imaginary window. We need to extract WND and WRITWN. Recall that when they are extracted they will be given the .OBJ extension by default.
LIB.EXE can do this. Just type the following:
LIB LIBRARY.LIB *WND.OBJ *WRITWN.OBJ
The "*" tells LIB to copy the module files only. The original modules will remain in the library.
There are several operators that tell LIB what to do and I will briefly describe some here:
preceding the .OBJ file means add to library
preceding a module name removes it -+ preceding a module removes original and replaces it with the updated version. Be sure the new version is available to LIB because removal action is always first in order.
There are more but the above gives ample ability to manipulate libraries. Consult your manual on others.After doing the above example, you would have all of the required .OBJ files in the current subdirectory. You could verify their existence by typing DIR at the DOS prompt. When there are more than a few .OBJ files, it may help to keep a notepad handy to keep track of them. If we needed .OBJ files from a second library we would again use LIB.EXE to extract those files from that particular library. There would then be .OBJ files from two different libraries; these can be easily combined into a new library specific to the needs of the main program. As mentioned before, QBX-BASIC uses two types of Library files: the normal .LIB files at linking time and .QLB (QuickLibrary) files when programming in the QBX-BASIC environment. Certainly you want to see your program run, if possible, prior to compiling an .EXE file so all bugs can be removed. Notice I said "if possible". There may be occasions when running a program is not possible because of conflict with the environment. If this should happen, you will have to create the .EXE file from the DOS command line or determine the cause of the conflict and correct it. Refer to the QBX-BC7 guide book for the proper syntax for BC and LINK. I will also describe them briefly after we create these new libraries. If you do run into this type situation I suggest you get the rest of your program functioning the way it should; then make the .EXE file to check the end result. Then you can work with the sticky subroutine; any error subsequent to that would definitely suggest the problem is with that subroutine.
So, a .QLB library is the first one we need to see how the program will function. LINK.EXE will provide the means to do this job. LINK.EXE has a special switch (/Q) which tells the program to make the .QLB library. If the switch is omitted QBX-BASIC will not be able to load the library when instructed to do so with the /L switch because of improper format.
The following syntax for LINK will provide a .QLB library:
LINK /Q WND.OBJ WRITWN.OBJ, MYNEW.QLB,,BQLBxx.LIB;
LINK.EXE will combine the .OBJ files into the new .QLB library using BASICs provided library for support routines. Naturally if you were using some other version of BASIC you would use the library provided to support the specific environmental library.
NOTE: When using the /L swith to load QBX-BASIC only one .QLB file can be specified. This means one thing, ALL external routines must be in the same .QLB library.
Also, .QLB libraries are not manageable as .LIB libraries are, therefore it is important to have identified all routines required prior to creating the .QLB library. If you forget one you will have to LINK all .OBJ files again to include the one(s) you forgot. I should mention that it is possible to do these tasks within the BASIC environment in which case .QLB libraries can be manipulated but only by changing the resulting library to a different name which basically means you are redoing everything again anyway. An advantage of this method is that the parallel .LIB file will be created at the same time. Consult your manual if you opt for this method. It is desirable to know how to do it from the command line. You should copy the .BI and .QLB file now to your program directory. The following syntax will make your new library available to the main program when you are ready to try the external routines. It is assumed of course that you have entered the $INCLUDE metacommand into your program (preferably ahead of other DECLARE statements) and that subroutine arguments have been entered or will be entered before the call is made to a particular routine:
QBX /L MYNEW.QLB
or, if you wish to load the program at the same time:
QBX YOURPROG /L MYNEW.QLB
Your program is up and running now and you have presumably ironed out all the bugs and are ready to create the .EXE file. Whether it is a standalone executable or one requiring the run library your external routines must be supported by parallel .LIB files. These parallel files contain the same object code as the .QLB files but in entirely different format. If, when creating the .EXE file, these files are not found they will be omitted from the .EXE program. Hence a certain function may not work at all even though the rest of the program is perfect. For this reason it is always a very good idea to create the .LIB file at the same time you create the .QLB file. For purposes of illustration I will repeat the syntax for creating the .QLB file so that you may see both of these commands together and their relationship to each other:
LINK /Q WND.OBJ WRITWN.OBJ, MYNEW.QLB,,BQLBxx.LIB;
and here is the command to create the parallel .LIB file:
LIB MYNEW.LIB+WND.OBJ+WRITWN.OBJ;
LIB will create MYNEW.LIB in the current directory as the parallel file of MYNEW.QLB. It should be copied also to your program directory when it is created along with the .BI and .QLB files.
The semicolon at the end of these commands tells LIB that no other directions are necessary. Omitting the semicolon will cause LIB to prompt you for additional information. Try it if youre curious. If you type LIB alone on the command line the program will prompt you for each entry. You are allowed 127 characters on the command line, so if you have a considerable number of .OBJ files to list, using LIB alone on the command line is advisable, since you are not limited to the number of .OBJ files you can list. When you run out of space on the first line, just type an ampersand (&) at the end of the line and press Enter. The Operations prompt will be repeated and you can continue entering information.
You can now create the .EXE version of your program. From within the BASIC environment you determine the type of executable program you desire. BC will compile your program using defaults based on its analysis of the program and automatically enter the LINK phase. If you choose an executable requiring the run time library LINK will use BRUNxx.LIB in conjunction with your .LIB file(s) to create the .EXE file. Advantages are smaller code which may be desirable with larger programs; disadvantages are slower execution and BRUNxx.LIB must be in the same directory or available to the program to provide support routines. If you choose the standalone executable version LINK will use BCOMxx.LIB and your .LIB file(s) to create the .EXE file. Standalone executables are larger but run faster and are self- supporting. Additionally, using command line compiling and linking, certain options can be used to decrease program size depending on the requirements of your program. You must consult your manual for this information; they are usually .OBJ files that can be linked with your program to curtail specific unnecessary functions. To use these you MUST link from the command line.
As we mentioned above, sometimes it may be necessary to create the .EXE file from the command line. In earlier versions of QuickBASIC it was advisable to do so since smaller .EXE files could be obtained. Version 4.5 seems to do fine; QBX 7.1 is even better.
First you must invoke the BASIC Compiler (BC) to compile the program. The default syntax follows:
For .EXE requiring run time support:
BC YOURPROG.BAS;
For .EXE as a standalone program:
BC YOURPROG.BAS/O;
You will need to add /E or /V if you use ON ERROR in your programBC will tell you if you forget. Add /C:512 if you use communications, to set the comm buffer size. There are alternative methods which may be used and they are:
BC (and answer the following prompts:
Source Filename: [.BAS]: YOURPROG.BAS
Object Filename: [YOURPROG.OBJ]: press Enter
Source Listing: [NUL.LST]: press Enter
Result: all error messages will be printed on screen and may scroll out of sight. You may have many object files. If you run out of space on a line, just type a plus (+) at the end and the prompt will be repeated on the next line.
BC YOURPROG.BAS;
Result: all errors will be printed on screen and may scroll out of sight.
BC YOURPROG.BAS; >YOURPROG.ERR
Result: all errors will be printed to a file in the current directory with name following ">". Redirection to the printer would be more functional and would not clutter up the directory as follows:`
BC YOURPROG.BAS; >PRN
Result: a printout of the errors which you can refer to while entering the proper operations which really means in the end you will be using one of the first two examples to tell the compiler what to do.
It is possible to use the same switches as the compiler. When you reach your final compilation from within the environment, use the "MAKE EXE AND EXIT" function. The options used by the QB environment will remain on the screen. Write them down and use those options (except the /T) when you must compile from the command line. This method is not recommended, since QBX uses a lot more options than is usually necessary, which results in your programs being larger and slower than need be. Still, its an easy way to get running in a hurry.
LINK YOURPROG.OBJ/EX;
If you have multiple object files and libraries:
LINK YOURPROG.OBJ+ANY.OBJ/EX, YOURPROG.EXE, NUL, MYNEW.LIB;
Again you are limited to 127 characters on the command line. It might be more convenient to just type:
LINK /EX
(the /EX option is desirable for optimization)and answer the following prompts:
Object Modules [.OBJ]: YOURPROG.OBJ+ANY.OBJ+NEXT.OBJ
Run File [YOURPROG.EXE]: press Enter if no change
List File [NUL.MAP]: press Enter for no map
Libraries [.LIB]: MYNEW.LIB+ANY.LIB
If you run out of room on a line just type "+" at the end of the line and the specific prompt will be repeated.This was not intended to be a complete documentation of the special features of LIB.EXE, BC,EXE and LINK.EXE, but rather specific knowledge about common application of the programs with regards to BASIC programming and the use of third party subroutines therein. Knowing how to manipulate libraries is an important investment of time for anyone considering creating programs no matter what particular language is used. The knowledge gained is applicable to all modern computer languages.
Original source:
LIB_BI.DOC, 1992 by Daniel M. Smith, Jr.
Adapted by Thomas G.Hanlin III, 1993
Adapted to QBX by Godfried-Willem Raes, 1994.
Filedate: 940728
Terug naar inhoudstafel kursus: < Index Kursus> |
Naar homepage dr.Godfried-Willem RAES |