Q L H A C K E R ' S J O U R N A L =========================================== Supporting All QL Programmers =========================================== #21 June 1995 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. QL Hacker's Journal c/o Tim Swenson 5615 Botkins Rd Huber Heights, OH 45424 USA (513) 233-2178 swensotc@ss2.sews.wpafb.af.mil tswenson@dgis.dtic.dla.mil EDITOR'S FORUMN This issue of the QHJ is a little smaller that I would like. I've been busy getting ready for the QL show in Oak Ridge, Tennesse. This is the same show that has been held in Newport, Rhode Island, but Bob Dyl wanted to try a different place this year. I've been busy making some distribution disks of some QL programming freeware, verifying the entries in the Sinclair Internet Resources List, printing up this list, printing up a hard copy of the QHJ, MausNet, and Z88 e-mail lists, spending a week on a trip to Pensacola, Florida (It's tougher when you travel with 2 kids), and all the other QL related stuff I do normally. For those QHJ readers on the net (which is most), you might know that the QL Mailing list that was maintained by Beppe Zannetti is no more and has been sort of absorbed into the QHJ e-mail list. I've also been asked to break out the MausNet readers out of the e-mail list. Due to bandwidth restrictions, it turns out that it is better to mail the QHJ to one MausNet reader and have him post it to the MausNet QL newsgroup. So that others can use either of these mailing lists, I plan to put them on the QL Anon-FTP servers (those in Finland, Norway, and Italy). I've noticed that the Sinclair (Spectrum/ T/S 2068) mailing list is now gone. This means that T/S 2068 and Spectrum users have no mailing lists. I've also noticed more ZX81 interest on comp.sys.sinclair, some from people that have recently picked up older machines at a flea market (or boot sale for those on the other side of the pond), and others that have discovered the various emulators available. I would like to start a Master Sinclair E-Mail list. I hope to create an Archive database with users names, e-mail addresses, and what computer they have. From this database, I can generate any e-mail list I want (with names or just the e-mail address). If you know of anyone out there that would like to be on a Master Sinclair list, have them send me an e-mail note. It is the ZX81, Spectrum, T/S 2068, and Z88 users that I need the most. I think I've got most of the QL users out there. I don't plan to make these mailing lists into a LISTSERV type of system (collecting then redistributing Sinclair e-mail message), but more as a phone book to look up Sinclair persons and to use when wanting to do a mass mailing (instead of a USENET posting). As mentioned above, I've prepared a more up-to-date Sinclair Internet Resources List. It contains a list of Sinclair FTP sites, Gopher sites, World Wide Web Sites, Mailing lists, USENET Newsgroups, etc. Like the e-mail lists, I will put a copy on the three Anon-FTP servers. One project that I am thinking about working is an other version of the Structured SuperBasic (SSB) filter. For those that don't know SSB lets you write SuperBasic programs with no line number and indenting, and will add the line numbers for you. I'm thinking about adding support similar to that found in the C preprocessor, such as; #define, #ifdef, #end, #elseif, etc. I also plan to compile the program and make it all available on the three Anon-FTP servers. I'm looking to see if there is any interest out there for this. Let me know. In QHJ #19 was an article on the Soundex algorithm. For some odd reason I could not get the code to compile. I know I had to be missing something. Peter Tillier found what I was missing. In the comment preceding the FOR statement, it is terminated with a * and not a */. This comments out a bunch of code until the next */. Don't you hate it when it's the little things that get you. Per-Erik Forssen of Sweden, where my great grandparents came from, has provided the QHJ with it's first article dealing with assembly language. I'm glad to have it, since a number of you commented in the readers survey that you wanted to see articles on assembly. QHJ FREEWARE AWARDS Last Issue I introduced the QHJ Freeware Awards and asked for votes on programs for each category. My original idea was to decide the awards myself, but I felt it would be a good idea to get your input. Well, after getting only one response, I did have to decide the awards myself. At least I gave it a shot. Below is the list of categories and the winners. After each category I will give a short discussion on why I chose that particular winner. Since this is the first year for these awards, I have expanded the criteria for consideration to include any Freeware program up to this point. Best Pointer Environment Program: MineField by Phillipe Troin Of all of the Freeware PE programs I have seen, MineField stands well above them. MineField looks and feels like a professional PE program. It uses a number of PE features in the same manner that other PE progams do (like QPAC2). A number of different mouse cursors are used. The skull and crossbones cursor when you lose and the thumbs up cursor when you win are nice touches. I've seen some other freeware PE games, but none look as excellent as MineField. It's design and development shows an in-depth knowledge of the PE by Phillipe. If you wanted a program as an example of how to do PE programs, MineField would be that example. Best Non-Pointer Environment Program QED by Jan Bredenbeek I know this program has been around a while, but as far as an impact in the QL community, I think few programs have gone as far as QED. QED is the standard text editor distributed with any program package that needs one (like C68, Intergroup Freeware Exchange, etc). Best Port to QL ZIP/UNZIP by Erik Slagter There were a lot of contenders in this category. A large number of programs have been ported to the QL. Most have been ported directly, with some consideration for the special needs of the QL. ZIP/UNZIP has taken the functionality of the most popular archiving program, brought it to the QL, and added support for the QDOS header information so that executables will archive well. Best Language or Language Utility C68 by Dave Walker No other compiler has done as much for the QL as C68. C68 has provided many users a full K&R C compiler which allows them to either write their own programs or port programs to the QL. C68 is a very comprehensive and complete C compiler. Best Programmer Jonathan Hudson Jonathan Hudson has written programs that have dominated communications on the QL. QeM, QTPI, and QFAX are the standards in QL communications. Jonathan has consistantly written solid programs with few bugs. Well, there they are. The First Annual QL Hacker's Journal Freeware Awards. I have made up some award certificates (I had to learn Page Designer 3 to do it) and I will mail them to all of the award winners. Next year I would like to keep the contenders down to just those programs released in 1995 - mid-96 timeframe. I would also like to get a little more input from you the reader. I don't mind coming up with my own winners, but I do not get a chance use all freeware programs, so I can't make a very informed decision. QDOS FILTERS By Per-Erik Forssen Filter programs are common in the UNIX world, but they are found to a varying extent on other platforms (such as QDOS) as well. In QDOS filters were introduced in 1984 with the QL-Toolkit (which later turned into Toolkit II). A filter program is typically a program that reads a stream of characters and makes some simple operation on it before passing it on. This function is not too different from what a filter attached to a water pipe will accomplish, thus the name filter. Filters may be connected in chains to perform more complex operations. Examples of what filters can do are converting the character stream to uppercase, encrypting it with a supplied key, etc. From QDOS a filter is started like this: EX UPCASE,ram1_infile,ram2_outfile The EX command is an enhanced version of EXEC that can pass arguments to the started programs. In this case the files 'ram1_infile' and 'ram2_outfile' are opened and the channel ID's are passed to the program (placed on the (A7) stack). Our example filter will strip the input stream from ANSI ESC-codes. ESC-codes are produced by software generating output to a terminal. The name ESC-code is due to all codes starting with the ESC char, chr$(27). After that comes a varying number of argument chars. ESC-codes will, when recieved by the terminal, alter some of it's settings. One code will for example switch to underline mode( chr$(27); '[4m'; ), while another will turn this mode off. This program will only remove some of the ESC-codes. * * A filter to strip _log files from ESC sequences * Current version only strips codes generated by the UNIX * 'nn' program Release 6.5.0 #8 (NOV), * Kim F. Storm, 1991 * This program is (C) 1995 Per-Erik Forssen * Should assemble with Qmac, other assemblers will need * other directives. * * QDOS standard equates * myself equ -1 forever equ -1 err.nc equ -1 err.ef equ -10 mt.frjob equ $05 io.fstrg equ $03 io.sbyte equ $05 ut.err0 equ $ca * * equates special for this program * bufsz equ 8000 ch_lf equ $0A ch_cr equ $0D ch_esc equ $1B ch_brace equ $5B * * Macro to step through the read buffer * NEXTCHAR MACRO [.lab] move.b (a2)+,d1 ; get next char subq.w #1,d2 ; decrement count ENDM section program data 8192 ; 8K data space * bra.s ESCstrip dc.b '1.00' ; program version dc.w $4afb ; standard job dc.w 8 ; program name dc.b 'ESCstrip' ds.w 0 ; word align ESCstrip lea.l 0(a6,a4.l),a6 ; set buffer pointer move.w (sp)+,d7 ; pop no of chan id's subq.w #2,d7 ; should be be two bne.s ESC_exit move.l (sp)+,a0 ; input chan move.l (sp)+,a4 ; output chan * ESC_fstrg moveq #io.fstrg,d0 ; fetch a string move.w #bufsz,d2 ; maximum size moveq #10,d3 ; wait up to a fifth of a second move.l a6,a1 ; place it in buffer trap #3 move.l d0,d4 ; keep error code move.w d1,d2 ; and string length beq.s ESC_errtst ; null string? * move.l a6,a2 ; reset buffer pointer ESC_loop NEXTCHAR cmp.b #ch_cr,d1 ; ignore CR beq.s ESC_loop cmp.b #ch_esc,d1 ; at an ESC-code ? bne.s ESC_send NEXTCHAR cmp.b #ch_brace,d1 bne.s ESC_psend NEXTCHAR bsr.s SKIP_NUM cmp.b #'m',d1 beq.s ESC_lfsend cmp.b #'H',d1 beq.s ESC_loop cmp.b #'J',d1 beq.s ESC_loop cmp.b #'K',d1 beq.s ESC_loop cmp.b #';',d1 bne.s ESC_psend bsr.s SKIP1_NUM * ESC_lfsend moveq #ch_lf,d1 ; send a line feed instead bsr.s BPUT bra.s ESC_next ESC_psend move.b d1,d5 ; esc code unresolved; moveq #ch_esc,d1 ;let it pass through filter bsr.s BPUT move.b d5,d1 ESC_send bsr.s BPUT * ESC_next tst.w d2 bgt.s ESC_loop * ESC_errtst move.l d4,d0 ; test the return from read beq.s ESC_fstrg addq.l #-err.nc,d4 ;not enough time to finish? beq.s ESC_fstrg cmp.l #err.ef-err.nc,d4 ; end of file? bne.s ESC_exit moveq #0,d0 ; yes; exit without errors * ESC_exit move.w ut.err0,a2 ; signal error in SuperBASIC #0 jsr (a2) move.l d0,d3 ; return status to owner moveq #mt.frjob,d0 ; force remove moveq #myself,d1 ; myself trap #1 * * Subroutines * SKIP_NUM skips 0 or more digits in string * SKIP1_NUM skips 1 or more * SKIP_NUM SN_loop cmp.b #'0',d1 blt.s SN_end cmp.b #'9',d1 bgt.s SN_end SKIP1_NUM NEXTCHAR bra.s SN_loop SN_end rts ; number is now skipped * * BPUT sends char in d1.b to output * BPUT movem.l a1/d1,-(a7) exg a4,a0 ; use output chan moveq #forever,d3 ; timeout for write moveq #io.sbyte,d0 trap #3 exg a4,a0 ; use input chan movem.l (a7)+,a1/d1 rts end The program includes many of the programming features used in assembler. For example the equ statements: myself equ -1 This corresponds to the C #define statements, i.e. all occurrences of 'myself' will be replaced with '-1' at assembly. Then we have macros: NEXTCHAR MACRO [.lab] move.b (a2)+,d1 ; get next char subq.w #1,d2 ; decrement count ENDM This corresponds to the C++ inline functions (or perhaps some more advanced C #define directives). All occurences of NEXTCHAR in the code will be replaced by the instructions between MACRO and ENDM. A macro can have arguments, but this feature is not used here. Then we have the BPUT, SKIP_NUM and SKIP1_NUM subroutines. They work much like functions, only that the argument passing is implicit. You will have to decide for each subroutine that for example registers D1 to D4 are arguments, and the result is returned in D0. For those who have never seen assembler before, see this as a brief introduction to how assembler programming works. For others, here is a neat way to write filters for QDOS. Vintrosa Sweden Per-Erik Forssen Email: d92perfo@und.ida.liu.se JOYFU OR FIND THE MISSING CONTRUCT JOYFU when sounded out means "Joyful, with no L" or as it is really supposed to be sounded out "Joyfull Noel." The lack of an L turns one word into two. This is sort of an interesting introduction to missing letters or contructs. I happen to read a DoD journal called "CrossTalk, The Journal of Defense Software Engineering." Most of the journal is either on Ada or above my head. The best part of the journal is the "Curmudgeon's Corner." It's a sort of rambling article, written by Robert Bliss, talking about software topics. In this last issue, Robert talks about missing letters. Robert writes: "The intentional omission of words was the motivation behind Georges Perec's 1969 novel 'La Disparition.' The author created a lipogram, a work in which something is prohibited, in this case any word containing the letter E. Perec wrote the work in French, which uses E for almost everything. When he completed 'La Disparition', Georges Perec realized he now had an abundance of unused words containing the the E left over. So he wrote his next work, 'Les Revenentes', with E as the only vowel used. (Do you ever get the feeling that some people have far too much time on their hands?)" Robert then ponders how interesting it would be to write software where a contruct is prohibited. I know that the GOTO command has suffered this prohibition in the past with a number of very well known articles. But, would it be possible to write something with out a FOR loop, or a WHILE statement. I doubt that you could write something without a IF statement, but it might be possible. An interesting demonstration of this would be a few code segments that would demonstrate how one would build a replacement for any particular contruct. How you would write a FOR loop with a WHILE statement, how you would write a WHILE statement with a FOR statement, etc. I remember back in Computer Architectures class we were told that an entire computer could be constructed of only NOR gates. They showed how every other gate (OR, AND, XOR, NOT, etc) could be constructed with a number of NOR gates (I think it was the NOR gate). I'm hoping someone will take this challenge and produce a some code. It's the little puzzles like this that make programming fun. LANGUAGE DESIGN PRINCIPLES Jon Bentley has been around computers for years, spending most of his time with AT&T Bell Labs (the birth place of Unix and C). In an article in "Unix Review", Jon mentions some guidelines on building languages. I thought these guidelines also apply to writing other programs, so I thought I would pass them along. The items below are taken from the article. My comments are in []'s. [ Jon discussed his ideas with a few major points listed below.] A Zoo of Examples. Start with the zoo to define your problem, use it for testing throughout development, and put the best examples into the documentation. * If you are doing a graphing program, start of with a number of example graphs that you want to be able to create using your program. Use them to help you decide what type of features you want your program to support. [You could also think of all of the strange cases in which your program might blow up at. This would provide a good zoo of examples.] A Working Description. Create a one- or two-page outline of your Language to ensure a cohesive design. [ Clearly defining your problem at the start will have headaches in the design and coding process.] The User's Manual. Document your language or GUI's goals and architecture from the user's perspective. * To create a program that is designed for the user, write your documentation first, describing how you want the program to run, and then write your code based on this. It's too easy to take short cuts in programming, because it's easy to implement and not easy to use. [ Writing the manual afterwards may base the functionality on the program and not how it's supposed to interact with the user. Focus on your user interface and functionality, then work on the code.] [ A sidebar to the article had a listing of Language Design Principles that complement the article.] Language Design Principles. - Design Goals. Before you design a carefully study the problem you are trying to solve. An old rule of thumb states that the first 10% of programming effort provides 90% of the functionality; can you make do with a small implementation that cheaply provides the fir 90%, or do you have to use more powerfull tools to get to 99.9%. - Simplicity. Keep you language as simple as possible. A smaller system is easier for its implementers to design, build, document, and maintain and is easier for its users to learn and use. - Yardsticks of Design. Here are some desirable properties of interfaces: -- Orthogonality: keep unrelated features unrelated. -- Generality: use an operation for many purposes. -- Parsimony: delete unneeded operations. -- Completeness: make the system implement all operations of interest. -- Similarity: make the interface as suggestive as possible. -- Extensibility: make sure the system can grow. -- Openness: let the user "escape" to use related tools. - The Design Process. Like other great software, languages are grown, not built. Start with a solid, simple design expressed in a succinct notation. Before implementing the language, test your design by performing a wide variety of operations. After the system is up and running, interate designs to add features as dictated by your customer's needs.