The QL Hacker’s Journal (QHJ) is published by Tim Swenson as a service to the QL Community. The QHJ is freely distributable. Past issues are available on disk, via e-mail, or via the Anon-FTP server, garbo.uwasa.fi. The QHJ is always on the look out for article submissions.
Editor’s Forum
I don’t have much to say for an introduction to this issue. I do want to thank Peter Tillier for contributing two articles. He really filled a few pages for me. The more articles I get the easier it is on me and the more often I can publish. I hate it when I have programming dry spells.
In QHJ #22, was a Day of the Week program. Mel Laverne found out one small bug in the program that did not make it work. Then translating from C to superBASIC, I forgot that the original program was done with Integer arithmetic. SuperBASIC defaults to floating point, so the program was off fairly often. So change all variables to integers and the whole thing should work out.
While browsing the Internet recently, I came across an article that I had heard about but had not read; The Tao of Programming. The Tao of Programming is written in a very Eastern way of writing, with formal sounding wisdom, but sprinkled lightly with modern humor. Here is an example:
“The Tao gave birth to machine language. Machine language gave birth to the Assembler.
The Assembler gave birth to the compiler. Now their are ten thousand languages.
Each language has its purpose, however humble. Each language expresses the Yin and Yany of software. Each language has its place within the Tao.
But do not program in COBOL if you can avoid it. If you find the Tao of Programming, give it a read. I hope you like this issue, and I’ll see you on the ‘Net.
Boot Up Reminder
Productivity tools for the QL are far and few between. On the PC, there is a dirth of these tools; Meeting Maker, Lotus Organizer, Maximizer, etc. One feature of most productivity tools is the ability to remind you of special days, such as birthdays, anniversaries, appointments, and so on.
Without doing much development work, a simple day reminder can be written for the QL. A good way to setup a reminder program is to have it check for special days when the QL boots up. During boot up, the program reads in the reminder data file and outputs any special days that are set for today. These special days can be set up to appear yearly (a birthday), weekly (trash day), or monthly (bills, bills, and more bills). Of course, this program will only work well if you boot up your QL at least once a day. If you boot it up less than that, you will need to set your reminders to appear days before the special day.
The format of the reminder file ( reminder_dat ) is as follows: T:XXXXXX:………………..
Where T is the type of reminder, W for weekly, M for monthly, and Y for yearly. XXXXXX is the date of the reminder. …… is the text of the reminder. Colons separate each field.
The program is case insensitive. There are three types of reminders, weekly, monthly, and yearly. A weekly reminder is based on the day of the week. If you must take out the trash every Wednesday night, then you could set a reminder for Wed to say “Take out Trash.” The first field has a W and the second field has a three letter abbreviation for the day of the week. Mon for Monday, Tue, etc. This is all based on the format returned from DAY$.
A Monthly reminder is based only on the day of the month. If you have to pay a bill on the 1st of each month, you could set a monthly reminder to “Pay Bill” for the 1st. The first field has an M and the second field is the day of the month in a two number format. The 6th of the month would be listed as 06.
A yearly reminder is based on the month and day. This is for reminding you of things like birthdays. The first field has a Y and the second field has a three letter abbreviation for the month (Jun), a space, and the day of the month listed as two digits (06 for the 6th). The 4th of Jul. would be listed as “Jul 04”.
The text of the reminder is the last field. It goes from the second colon to the end of the line. You can put anything in this text, as it is copied from the reminder file and printed to the screen.
This program can easily be included into a Boot program or it can be called from the Boot program. It simply prints out the reminders, but you can liven it up with flashing letters or beeping noises, what ever will get your attention.
100 OPEN #3,scr_350x75a75x50
110 PAPER #3,0: INK #3,2: BORDER #3,3,4
120 CLS #3
130 month$ = DATE$
140 month$=upper$(month$(6 TO 11))
150 daym$ = DATE$
160 daym$=upper$(daym$(10 TO 11))
170 dayw$=upper$(DAY$)
180 OPEN_IN #4,flp1_reminder_dat
190 REPeat loop
200 IF EOF(#4) THEN EXIT loop
210 INPUT #4,in$
220 IF LEN(in$) < 3 THEN END REPeat loop
230 colon = ":" INSTR in$
240 type$ = upper$(in$(1 TO colon-1))
250 in$ = in$(colon+1 TO )
260 colon = ":" INSTR in$
270 remind$ = upper$(in$(1 TO colon-1))
280 reminder$ = in$(colon+1 TO )
290 IF type$ = "W" THEN
300 IF remind$ = dayw$ THEN
310 BEEP 1000,10
320 PRINT #3,dayw$;" ";reminder$
330 END IF
340 END IF
350 IF type$ = "M" THEN
360 IF remind$ = daym$ THEN
370 BEEP 1000,10
380 PRINT #3,daym$;" ";reminder$
390 END IF
400 END IF
410 IF type$ = "Y" THEN
420 IF remind$ = month$ THEN
430 BEEP 1000,10
440 PRINT #3,month$;" ";reminder$
450 END IF
460 END IF
470 END REPeat loop
480 CLOSE #4
490 CLOSE #3
500 DEFine FuNction upper$(up$)
510 LOCal x, temp
520 FOR x = 1 TO LEN(up$)
530 temp = CODE(up$(x))
540 IF temp > 96 AND temp < 123 THEN
up$(x)=CHR$(temp-32)
550 NEXT x
560 RETurn up$
570 END DEFine upper$
Example Reminder File:
w:tue:This is a Tuesday Reminder
w:wed:This is a Wednesday Reminder
m:04:This is a 4th day of the month Reminder
m:13:This is a 13th day of the month reminder
y:jun 04:This is a June 4th reminder
y:jul 19:This is a July 19th reminder
Some Thoughts On Programming Style
By Peter Tillier
In QHJ #24 Tim talks about a colleague’s style of writing Perl and contrasts it with his own. I have spent several years as a programming and system development lecturer within my company’s internal training department and nothing seems to cause more grief/criticism/etc., etc., as differences of programming style.
I tend to use procedure calls in preference to the use of deep nesting of ‘if..then..else..endif’ structures as does Tim’s colleague. I do this for a number of reasons and even if the procedure may only be called once in the entire program (incidentally this approach is taken by Kernighan and Ritchie in ‘The C Programming Language’ and by Kernighan and Plauger in ‘Software Tools in Pascal’).
My reasons are these: It is sometimes inconvenient to read deeply nested ‘if..else..endif’ or ‘while..endwhile’ constructions; this approach works very well with the program design method that I prefer to use (Jackson Structured Programming, aka. JSP); if suitable procedure names are chosen the clarity of the code is often improved; the style is closer to the object-oriented programming approach that I would prefer to use; the arguments about inefficiency (“It’s wasteful to set up a stack frame and call code that could have been inline.”) take little account of the maintenance benefits that can accrue from well-designed and named procedures.
I find something like this much easier to follow (and debug!),
procedure DoLotsOfThingsTo(var A : AType); var
i : integer;
procedure DoOneThingTo(var A : AType );
begin
A.A := ...;
A.B := ...;
end {DoOneThingTo};
begin
for i := 1 to SizeOfAType do
DoOneThingTo(A);
...
end {DoLotsOfThingsTo};
(the above also shows one reason that I like Pascal – the ability to nest procedure declarations – I miss it a lot when I use C, C++ or things like Visual Basic).
Incidentally, Question: can you nest procedure definitions in SuperBASIC?
Answer: Yes you can:
1000 define procedure testa
1010 :
1020 define procedure testb
1030 print "In testb"
1040 end define testb
1050 :
1060 print "In testa (1)"
1070 testb
1080 print "In testa (2)"
1090 :
1100 end define testa
works perfectly, printing out,
In testa (1)
In testb
In testa (2)
as expected.
As I said in my article on parameters and parameter passing mechanisms I think that most languages would be better if they were designed so that procedures and functions (in the SB or Pascal sense) could only access local variables or parameters – even for read access only.
Software Reuse
For years I’ve reading articles on Software Reuse and how it can increase the productivity of programming shops. Since I program alone, as most QLers programmers do, I have never given it much thought for my programming. For some reason, a recent article on software reuse sparked a new thought about software reuse and the QL.
Before I go into my sparked thought, I want repeat here one sideline from the article. The Eight Commandments of Reuse:
1. Golden rule of reuse: encourage individuals and teams to behave in ways that support reuse.
2. Keep an inventory of reusable artifacts.
3. Provide a catalog with descriptors and search support.
4. Designate a reuse administrator/facilitator who keeps the catalog and helps users.
5. Develop a methodology outlining how and when to re-use software components.
6. Have a measurement program to track reuse and adherence to the methodology.
7. Design standards that specify how artifacts are constructed.
8. Adhere to a quality-assurance program to guarantee the integrity of artifacts.
Now that you have read the above, set it aside for the moment (for you Assembly programmers, PUSH it. You will need to POP it later).
I think one of the most difficult areas of writing programs for the QL is dealing with the Pointer Environment. You either buy a PE Toolkit (such as EasyPointer) and a SuperBasic Compiler (QLiberator) for a fair amount of dollars, or, you can program in C with C68 and the Pointer libraries. Being cheap, I would opt out for C68, but I am very weak with full C (OK, I write a few hacks in C, but I am no where near calling myself a C programmer). Using C68 and the Pointer Environment is not trivial. It’s not something for the fledgling C programmer.
For those that do program in C and the Pointer Environment, each programmer is writing a lot of the same display routines to get output to the screen. For some this is not easy and takes up some significant time and effort.
OK, now POP what you had PUSHed earlier; software reuse. What if a number of C68 programmers were to get together (just like they do in the development of C68) and started collecting a library of C68 PE routines that could be used by other programmers? Kind of sounds like software reuse.
If QLers where to use the 8 Commandments of Reuse, we would only need to use commandments 2, 3, 4, 5, and 7. We would not need to track who uses reuse or who does not. If someone was to volunteer to be the administrator (they would need to be a C68 programmer), other C68 programmers could send in their functions and procedures to be added to a library. This could be documented and then distributed back out to C68 programmers.
Submitting functions and procedures may require some code changes on the part of the submitting programmers. The functions and procedures would have to be written in a more portable “black box”. No use of global variables.
I don’t know if the time and effort put into this would save any programmer time in the long run. The time saver for the programmer would be the time saving in having to re-write code that has been written before. Would this time savings be enough to warrant the cost of organizing the library? Again, I don’t know. I just thought it might be worth considering. Any takers?
DBAS
For most database programming, the QL programmer has been pretty much stuck with Archive. Archive is a fine language and is fairly similar to dBase III in programming feel. It has many advantages: editing of records built in, easy screen creation, a well structured language. But it also has a few weak points: limited functions, little control over end user accessing code, relatively slow.
If you are looking for a database development system that allows you to create stand-alone code, full access to features of QDOS, relatively fast, and free, then DBAS is something that you should look into.
DBAS, also called Database Handler, is a library of database handling routines for SuperBasic, C68, or Machine Code. DBAS is not a database language system like Archive, so it is not a true replacement for Archive.
The core part of DBAS resides in DATA_BIN. It is loaded by LRESPR. DATA_BIN contains the main routines for database handling, but only for Machine Code programs. If you use SuperBasic, DBAS_BIN contains the SuperBasic interface to DATA_BIN, and it too is LRESPRed. For C68 programmers, there is a library of database routines that access DATA_BIN.
Programming with DBAS is not as easy as programming with Archive. You are using DBAS for database function calls, but you still have your programming control constructs (looping, branching, etc.) in SuperBasic or C68. What you loose in ease of programming from Archive, you gain in power of programming. Since you are using SuperBasic or C68 to program in, you still have the full power of either language and all that they can do.
DBAS has both procedures and functions. A sampling of procedures is:
ADD_FIELD Add a field APPEND Add a new record CREATE Create a database EXCLUDE Deselect records FIND Find by INSTR INCLUDE Select records LOCATE Find by ORDER parameters OPEN_DATA Open a database ORDER Order a database REMOVE Delete a record SEARCH Find by INCLUDE parameters UPDATE Update a record
A sample list of functions is:
COUNT Get record count FETCH Get record contents FLLEN Get field length FLNAME Get field name
Databases are treaded like files and are opened with the OPEN_DATA procedure. After that they are referred to by their channel number. Fields do not specifically have names – they are referenced by field number – but field names can be implemented with some work arounds. DBAS does not seem to prohibit opening more than one database at one time, but I do not see in any of the commands where you can specify a JOIN ( selecting records from two databases/tables with a common equality). By doing a couple of searches on each database, you should be able to rig up the equivalency of a JOIN.
Since DBAS does not have a front-end for doing database creating, editing databases, etc., two utilities come with DBAS to make maintaining individual records easier. DBPTR_BIN is a Pointer Environment program for editing, adding, and deleting records. For non-PE users, there is ALTER_BIN. Both of these programs are executables.
DBAS has a lot of potential. Since it is LRESPRed, it is compatible with SuperBasic compilers, like QLiberator. You can compile your code and create a stand alone application. The _BIN files are freeware and can be distributed with your program.
DBAS comes with full documentation for all of its features, including the SuperBasic, C68, and Machine Code interfaces. It comes with example programs that help in learning how to use DBAS.
If you are new to databases and you want to learn how to program them, stay with Archive. If already know how databases work and want to develop your own stand-alone applications, then DBAS is worth the look.
DBAS should be available on most QL BBS’s worldwide. For North American QL users, you can get it from QHJ Freeware (me) (just send a disk with return postage).
See the Unclassified Ads for address.