From mauricio@mozart.aero.ufl.edu Tue Jan 11 20:42:50 MET 1994 Article: 722 of comp.sys.sinclair Newsgroups: comp.sys.sinclair Path: flode.nvg.unit.no!trane.uninett.no!sunic!EU.net!uunet!olivea!charnel!psgrain!m2xenix!m2n From: mauricio@mozart.aero.ufl.edu ("Mauricio Tavares") Subject: Q L H A C K E R ' S J O U R N A L X-M2n: psg.com Organization: PSGnet mail to news gate Date: Tue, 11 Jan 1994 13:37:02 GMT Message-ID: <9401111337.AA12369@mozart.aero.ufl.edu> Sender: @psg.com Lines: 908 Forwarded message: >From swensotc@ss1.sews.wpafb.af.mil Mon Jan 10 15:56:17 1994 Date: Mon, 10 Jan 94 15:55:25 EST From: swensotc@ss1.sews.wpafb.af.mil (TIMOTHY C. SWENSON) Message-Id: <9401102055.AA18167@ss1> To: mauricio@gauss.aero.ufl.edu Q L H A C K E R ' S J O U R N A L =========================================== Supporting All QL Programmers =========================================== #16 January 1994 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@ss1.sews.wpafb.af.mil swensotc@p2.ams.wpafb.af.mil tswenson@dgis.dtic.dla.mil EDITOR'S FORUM Again another issue has taken longer than I wanted to come out. Since the last issue one important thing has happened to further complicate my life. Her name is Ashlyn Nicole; 7 Lbs 2 oz, born 23 November at 5:17 PM. Recently I attended a local book sale, that had a good selection of computer books. I was able to pick up a few books that I wanted to add to my library. Namely, "Mythical Man-Month" and "Software Tools in Pascal". I picked up a few that looked interesting and worth the small price. I did pick up a copy of "The Elements of Programming Style" real cheap and am willing to send it to the first person to respond. I've already got a copy, but I could not pass on picking it up for 80 cents, especially when it still retails for over $25. I do have some news items. Recently on USENET a new newsgroup has been created, called comp.sys.sinclair. This newsgroup is aimed at the discussion of all Sinclair computers, although the majority of traffic has been on the Spectrum. I have seen some relatively new QLer's looking for sources of software and hardware. I will be posting future issues of the QHJ to the newsgroup, hoping to expand the readership. As some of you may know, another part of my computer hobby is collecting older computers. I have recently found a new group that shares the same interest. The Historical Computer Society puts out a bi-monthly newsletter called "Historically Brewed". It has articles talking about older computers. Issue number 3 was Dec 93/Jan 94, so they are fairly new. If you are interested, the address is: Historical Computer Society 10928 Ted Williams Place El Paso, TX 79934 USA Before I finish, I would like to thank Emiliano Barbaini for contributing an article for this issue. He also worked on the natural language C program that I asked for help on. I will be providing this in a future issue. QUILL READER By Emiliano Barbaini One of the major defects of QUILL is the lack of an "EXPORT" function. Only after release 2.35, PSION added the export command. But also in this case, if we want ascii text from a doc, we have to : 1) load QUILL 2) load the document 3) select the export option 4) export the document 5) quit QUILL 6) load an ascii editor If we don't have the 2.35 version, we can print the document to a filename, with an appropriate printer driver. In both case, there is not a simple way. My solution is a QUILL filter. A filter, in UNIX, is a little program that applies some rules to an input file to obtain output : for example a program that translates all lowercase characters to uppercase. For the QUILL filter, is not a simple matter, for many reasons : 1) Quill does not append a newline after each line, but only a '\0' (character code zero) after each paragraph. 2) There are many control codes, i.e. character code 9 for tab, code 14 for signaling the end of document and so on. 3) The line width, indent and so on, is a mystery (for me least). So, I arbitrarily decided on a line length of 70 chars and a page length of 60 lines , and to discard any control code except : 9 tabulation 14 end of document 12 new page 32 to 127 : ASCII code The flow of the program is as follows: In the first section, there is the declaration of some useful variables : #define WIDTH 70 /** width of a line **/ #define MAXLINE 60 /** Nr of lines for page **/ #define HTAB 5 /** tab length **/ #define PAR_SIZE 32768 /** max size for paragraph **/ char *Paragraph; int Page = 1; /** Start printing at page =1 **/ int Nlines = 1; /** number of lines, max 60 **/ int count; FILE *output; These two variables are 'file pointers' : FILE *input; with them it is possible to access a file. Next, came the "main" function : each C program must to have a main function. The main function takes 2 parameters: argc : an integer. The numbers of parameters passed to the program via command line plus one, the program name argv : a pointer to character array that holds the parameters. argv[0] is the program name argv[1] is the first parameter .. and so on ... main(register int rage, register char *argv[]) { The following declare an integer to be 'register' : this value is assigned by the compiler to a 68000 register. This allows for short code and better performance, but only 8 variables may be declared as register. register int ch; /** character analyzed **/ Next we allow a max paragraph of 32K chars : Paragraph = (char *)malloc(32768); /** request for a 32K buffer **/ Paragraph is an array, that can be 32768 characters long. Now we try to open a filename, that is the first parameter : if this fails, a message is written to standard error, and then the program exits. Otherwise, the variable 'input' points to the filename. The first parameter must be present and it is the QUILL file to be translated. if ( (input=fopen(argv[1],"r")) == NULL ) { fprintf(stderr,"I cannot open the input file !!\n"); exit(1); } Then, we test if the number of parameters is greater than 2 : if yes, we try to open 'write only' a second filename. That becomes the output of the filter. Otherwise the output is standard output. NOTE : if you have the C68 v 4.01 compiler, the same job can be performed in the following way : "qreader QUILL.doc >filename" (this is the Unix syntax ). output = stdout ; if (argc>2) { if ( (output=fopen(argv[2],"w")) == NULL ) { fprintf(stderr,"I cannot open the output file !!\n"); exit(1); } } The getc function reads a character from input; it stops at the end of the file. If the character is an ASCII code (characters from 32 to 127), it is stored in the Paragraph array, else it was decoded as follows : if ch is equal to 14, execute the 'End_of_Document' function, if ch is equal to 12, execute a 'Newpage' function ... and so on : it is a SELect ON ch statement ! while( (ch=getc(input)) != EOF ) { if (ch==14) End_of_Document(); if (ch==12) Newpage(); if (ch==0) Newparagraph(); if (ch==9) Htab(); if (ch>=32 && ch<=127) Paragraph[count++]=ch; } The statement count++ increments the variable count : it is a concise form for "count=count+1". } The Htab function is called when a character code 9 is recognised in the input file. It evaluates the number of blanks to be added to the current line . void Htab() { register int blank,j; count % 5 => count=count MOD 5 , this is the number of blank to be added for the next tab. blank=count % 5; for (j=0;j MAXLINE ) { Nlines=1; fprintf(output,"\n ----- End of Page %2d -----\n",Page++); } return; } /**/ This is the most important function : it takes a parameter (the Paragraph array) and outputs it in lines no longer than WIDTH char, without splitting the words. If a Paragraph contains more than MAXLINE lines, the function Newpage is called : this action is performed by Check_Lines function. void right_justify(register char *stringa) { register int j,k; /** 'for' variables **/ int pos = 0; int start_pos = 0; int len; If Paragraph is shorter than a line, it will be printed, then the function returns to main. len=strlen(stringa); if (len<=WIDTH) { fprintf (output,"%s\n",stringa); Check_Nlines(); return; } Otherwise the Paragraph array will be splitted in lines ... pos=WIDTH; while(start_pos len ) { for (j=start_pos;j<=len;j++) putc(stringa[j], output); putc('\n', output); Check_Nlines(); return; } if ( stringa[pos] != ' ' ) pos--; else { for (j=start_pos,k=0;j<=pos;j++,k++) putc(stringa[j], output); putc('\n', output); Check_Nlines(); start_pos+=k ; pos=start_pos + k; } } return; } For the future : I hope to discover the internal structure of QUILL documents (indents, margins and so on). If this happens, I can write a postscript driver for QUILL documents. I hope that the explanation was clear. For further details, contact me at E-mail : E.Barbaini.cons@it12.bull.it. Full text of the program: /******************************************************/ /********** quill reader : a simple filter ************/ /********** vs 1.08 08 Oct. 1993 ************/ /********** Emiliano Barbaini ************/ /********** E-mail E.Barbaini.cons@it12.bull.it *****/ /******************************************************/ #include #include void right_justify(); void End_of_Document(); void Newpage(); void Newparagraph(); void Htab(); void Check_Nlines(); #define WIDTH 70 /** width of a line **/ #define MAXLINE 60 /** Nr of lines for page **/ #define HTAB 5 /** tab length **/ #define PAR_SIZE 32768 /** max size for a paragraph **/ char *Paragraph; int Page = 1; /** Start printing at page =1 **/ int Nlines = 1; /** number of lines, max 60 **/ int count; FILE *output; /** output channel **/ FILE *input; /** input channel **/ main(register int argc, register char *argv[]) { register int ch; /** character analized **/ Paragraph = (char *)malloc(32768); /** request for a 32K buffer **/ if ( (input=fopen(argv[1],"r")) == NULL ) { fprintf(stderr,"I cannot open the input file !!\n"); exit(1); } output = stdout ; if (argc>2) { if ( (output=fopen(argv[2],"w")) == NULL ) { fprintf(stderr,"I cannot open the output file !!\n"); exit(1); } } while( (ch=getc(input)) != EOF ) { if (ch==14) End_of_Document(); if (ch==12) Newpage(); if (ch==0) Newparagraph(); if (ch==9) Htab(); if (ch>=32 && ch<=127) Paragraph[count++]=ch; } } void Htab() { register int blank,j; blank=count % 5; for (j=0;j MAXLINE ) { Nlines=1; fprintf(output,"\n ----- End of Page %2d -----\n", Page++); } return; } /**/ void right_justify(register char *stringa) { register int j,k; /** 'for' variables **/ int pos = 0; int start_pos = 0; int len; len=strlen(stringa); if (len<=WIDTH) { fprintf (output,"%s\n",stringa); Check_Nlines(); return; } pos=WIDTH; while(start_pos len ) { for (j=start_pos;j<=len;j++) putc(stringa[j], output); putc('\n', output); Check_Nlines(); return; } if ( stringa[pos] != ' ' ) pos--; else { for (j=start_pos,k=0;j<=pos;j++,k++) putc(stringa[j], output); putc('\n', output); Check_Nlines(); start_pos+=k ; pos=start_pos + k; } } return; } /******************************************************/ DICE PERCENTAGES By Tim Swenson I'm still distracted by my other hobby, wargaming. In tying the two together, I thought about dice, percentages, and To-Hit rolls. In gaming a To-Hit roll is a die roll, where your try to roll a certain value or less. For example, for a To-Hit roll of 10 with 2 six-sided die (2d6), you would have to roll a die total of 10 or less. In designing a game or gaming system, it's easy to determine the chances that something will happen by purely guessing the general percent chance that you feel that it will happen. The difficult part is translating that into terms of die. Some designers use a 10- or 20-sided die to work out the nice percentages, but others prefer to stick to 6-sided dice because of how common they are. I wrote a short program that will take a given number of 6-sided dice and print out the possible die rolls with the percent change that that number will come up, and the percent change that that number or less will come up (the To-Hit roll). ** dice_ssb ** This program will simulate a number of 6 ** sided dice. It will determine what ** percentage chance a certain number ** has of rolling, and what percentage ** a number or lower has of rolling. dice = 2 DIM array(dice+1) DIM total_array(6^dice) ** Calculation Section ** Set all dice to 1 FOR x = 1 to dice array(x) = 1 NEXT x ** Set first dice to 0 so that it will ** INC to 1 in first run through the ** program. array(1) = 0 FOR y = 1 TO 6^dice array(1) = array(1)+1 total = 0 FOR x = 1 TO dice IF array(x) = 7 THEN array(x) = 1 array(x+1) = array(x+1)+1 END IF total = total+array(x) NEXT x total_array(total) = total_array(total)+1 NEXT y ** Report Section total = 0 FOR x = dice TO 6*dice temp1 = INT((total_array(x)/6^dice)*100) total = total + total_array(x) temp2 = int(((total)/6^dice)*100) print "Die roll of ";x;" ";total_array(x);" "; temp1;" ";temp2 NEXT x QL ANON-FTP SERVER I have recently found a QL FTP site that allows the storage of binary files. The site name is: maya.dei.unipd.it I am guessing that it is being run by one of the Zannetti brothers in Italy. The key advantage of this FTP site is the fast distribution of QL software. As an example, version 4 of C68 is on the site. Below is a listing of the files avaiable. C68 -rwxr--r-- 303356 Dec 5 1992 c68disk1.zoo -rwxr--r-- 243545 Dec 5 1992 c68disk2.zoo -rwxr--r-- 210370 Dec 13 1992 c68disk3.zoo C68.version4 -r--r--r-- 2482 Oct 23 09:38 C68.bugs -r--r--r-- 172 Oct 19 16:59 C68.readme -r--r--r-- 295480 Oct 19 16:59 runtime1.zoo -r--r--r-- 296381 Oct 19 16:59 runtime2.zoo -r--r--r-- 223647 Oct 19 17:00 runtime3.zoo CLUBS -rw-r--r-- 3970 Oct 13 1992 qlpdita.txt -rw-r--r-- 10930 Oct 13 1992 sinqldbf.zip -rw-r--r-- 42158 Oct 13 1992 sinqltxt.zip COMPRESS -rw-r--r-- 41506 Oct 13 1992 arc.exe -rw-r--r-- 59078 Oct 13 1992 qlarc.uue -rw-r--r-- 10099 Oct 13 1992 qlunarc.uue -rw-r--r-- 7075 Oct 13 1992 qlunarc.zip -rw-r--r-- 53431 Oct 13 1992 qlunzip.uue -rw-r--r-- 37428 Oct 13 1992 qlunzip.zip -rw-r--r-- 5749 Oct 13 1992 qz.uue -rw-r--r-- 6994 Oct 13 1992 unzip96.exe DME3 -r--r--r-- 38 Jan 11 1993 000_README drwxr-xr-x 512 Jan 11 1993 DME2 -rw-r--r-- 129329 Jan 11 1993 hdk1_dme3.zoo DME2 -r--r--r-- 38 Nov 26 1992 000_README -r--r--r-- 97862 Nov 26 1992 dme2.zoo DOCS -rw-r--r-- 446 Oct 13 1992 000IBM_TO_QL -rw-r--r-- 371 Oct 13 1992 000README -rwxr--r-- 1172 Oct 13 1992 000_MAILING_LI -rw-r--r-- 2327 Oct 13 1992 000index -r--r--r-- 36741 Oct 13 1992 QLAW.doc -rw-r--r-- 10196 Oct 13 1992 minix.txt -rw-r--r-- 2847 Oct 13 1992 myqlpd -rw-r--r-- 11099 Oct 13 1992 op_sys.txt -rw-r--r-- 3178 Oct 13 1992 project -rw-r--r-- 7454 Oct 13 1992 qlnet.txt FSH_v2 drwxr-xr-x 512 Apr 20 1993 OLD -r--r--r-- 181690 Apr 20 1993 fshv2.zip -r--r--r-- 36857 Apr 20 1993 fshv2Src.zip HARD_DISK -rw-r--r-- 650 Nov 25 1992 000_README -rw-r--r-- 279405 Nov 25 1992 qlhd.zoo KERMIT -rw-r--r-- 122 Dec 28 1992 000_README -r--r--r-- 106314 Dec 28 1992 bcplkerm.td0 -r--r--r-- 129948 Dec 28 1992 c_kermit.td0 -r--r--r-- 93607 Dec 28 1992 teledisk.zip NEWZOO -rw-r--r-- 20372 Oct 13 1992 bilf -rw-r--r-- 25844 Oct 13 1992 fiz -rw-r--r-- 4227 Oct 13 1992 fiz.man -rw-r--r-- 77382 Oct 13 1992 ooz -rw-r--r-- 187517 Oct 13 1992 source.zoo -rw-r--r-- 85354 Oct 13 1992 zoo -rw-r--r-- 50140 Oct 13 1992 zoo.man -rw-r--r-- 8160 Oct 13 1992 zoo.readme QLDB3 -rw-r--r-- 5448 Oct 13 1992 qldb.txt -rw-r--r-- 8192 Oct 13 1992 qldbase.doc -rw-r--r-- 12686 Oct 13 1992 qldbase.exe -rw-r--r-- 6967 Oct 13 1992 qldbase.pas -rw-r--r-- 12686 Oct 13 1992 qldbita.exe QLSCR41 -rw-r--r-- 72 Oct 13 1992 000README -rw-r--r-- 115957 Oct 13 1992 qlscr41.tar.Z QLTOOLS16 -rw-r--r-- 54 Nov 8 11:20 000-README -rw-r--r-- 17384 Nov 8 11:18 qltools.1.6.tar.Z QLUTIL -rw-r--r-- 5983 Oct 13 1992 qimi223.asm -rw-r--r-- 434 Oct 13 1992 qimi223.cde -rw-r--r-- 6047 Oct 13 1992 qimi229.asm -rw-r--r-- 442 Oct 13 1992 qimi229.cde -rw-r--r-- 3985 Oct 13 1992 qlutil.txt -rw-r--r-- 4228 Oct 13 1992 quits.txt -rw-r--r-- 1033 Oct 13 1992 sysbase.asm -rw-r--r-- 104 Oct 13 1992 sysbase.cde -rw-r--r-- 5335 Oct 13 1992 trumpwar.asm -rw-r--r-- 184 Oct 13 1992 trumpwar.cde -rw-r--r-- 4385 Oct 13 1992 wreset.asm -rw-r--r-- 154 Oct 13 1992 wreset.cde QUILL2ASCII -r--r--r-- 4236 Oct 19 17:07 quill_reader ROGUE -rwxr--r-- 958 Mar 4 1993 000-README -r--r--r-- 4678 Mar 1 1993 FACT_asm -r--r--r-- 98677 Feb 26 1993 rogue.zoo SCHEME -r--r--r-- 276 Oct 19 17:01 00readme -r--r--r-- 44126 Oct 19 17:01 hobb.zoo -r--r--r-- 64105 Oct 19 17:01 jacal.zoo -r--r--r-- 30761 Oct 19 17:01 jacman.zoo -r--r--r-- 4364 Oct 19 17:01 readme.scm -r--r--r-- 200462 Oct 19 17:01 scmexe.zoo -r--r--r-- 179164 Oct 19 17:01 scmsourc.zoo TIFF -rwx------ 171 Oct 13 1992 00INDEX -r--r--r-- 10273 Oct 13 1992 beppe.uue -r--r--r-- 18592 Oct 13 1992 qltiff.uue -r--r--r-- 18275 Oct 13 1992 unipd.uue XLISP -r--r--r-- 464 Nov 16 15:30 00readme -r--r--r-- 5247 Nov 16 15:31 readme -r--r--r-- 80330 Nov 16 15:31 xldoc1.zoo -r--r--r-- 130741 Nov 16 15:31 xldoc2.zoo -r--r--r-- 139256 Nov 16 15:31 xlexe.zoo -r--r--r-- 140422 Nov 16 15:33 xlsrc.zoo incoming -rw-rw-rw- 384694 Dec 11 13:39 C68unix.tar.gz old drwxr-xr-x 512 Nov 8 11:19 QLTOOLS14 drwxr-xr-x 512 Nov 17 10:07 XLISP PROLOG INTERPRETER: A SECOND LOOK A Review by Tim Swenson Back in QHJ #13 I have a cursory review of the Prolog interpreter written by Hans Lub. I said that when I found the book that the interpreter was based upon, I could look into it further. Well, I found the book; The Art of Prolog by Sterling and Shapiro. Even though Hans described the book as excellent, I found it a bit heavy. "The Art of Prolog" is your typical college textbook. It is not designed to be an easy introduction to Prolog, but delves a little more in to the theory of logic programming and Prolog. Don't expect to pick it up and read it lightly. The documentation for the interpreter is 10 pages long. A seperate document detailing all of the keywords or predicates is an additional 5 pages. The documentation is designed only to cover the interpreter and not the language. It does a fine job of covering how to use the interpreter and delves into the nitty-gritty. It covers error messages, limitations, sone do's and don'ts, using tracing, and any peculiarities of the program. It comes with a few example programs, which I did not really look at in the first review. These example programs demonstrate the robustness of the interpreter. When the interpreter is described as a learning tool and not a platform for porting Prolog programs to the QL, I figured the interpreter would be only able to handle some simple, short programs. One example program is an interpreter of a language called Monica. There is even an example Monica program. An interpreter can can write another interpreter is more than just a learning tool. A couple of example programs are directly from the book, with a few minor changes to fit the interpreter and add a few nice touches. I compared the list of system predicates for the interpreter and those in the book. The interpreter is missing a few predicates, but seems to have most of the important ones. As mentioned above, any programs taken from the book would have to be slightly adjusted. The interpreter itself is easy to use. It is designed to handle the QJUMP pointer interface, but can be run with out it. The interpreter does prefer extra memory, but there is a version to run in 128K. Start up is easy and it quickly gives you the "?" prompt. When I ran the Eliza example program, I thought it was a bit slow, but after I ran it with the Trace function on, I saw how much processing the interpreter was doing. I take back any comments that I might have made about it's speed. It's not blazingly fast, but it's no dog either. The interpreter does have some QDOS screen predicates so you can "pretty" up your programs. CLS, INK, UNDER, PAPER, CSIZE, WINDOW, and AT are supported. Beware of changing the ink in a program and then running trace. Your trace output will be shown in the new ink color. Red text on black was a bit hard to read. The interpreter is configurable. You can change the names of the help and start up files. You can add to the start up file and add any of your own "subroutines", sort of like the way MicroEmacs boots up. You can even change the size of the interpreter screen (something that I previously said could not be done). The interpreter is sort of shareware and freeware. There is no implied limit on how long you can use the program with out paying the 10 pound fee, but registering will give you the source code and an advanced user manual. The program is dated March 1990 so I don't know if the auther is still supporting it. Some of the books that I've seen on Prolog describe the language as a language of rules and facts. This leads you to believe that Prolog is more for AI work and not general computing. The examples that come with the interpreter and described in the book dispell this belief. One example program is Quick Sort done in Prolog. If Prolog can do Quick Sort, then it can probably be adapted to most computing needs. I did find Prolog a bit difficult to read. The facts and rules can be easy to read, especially with the simple examples: male (X) <- father (X, Y). father (john, mary). But the code for Quick Sort and some other examples were beyond me. I guess if you can read Lisp, then you will have no problem reading Prolog. If not, find a good book and spend a few hours with it. QHJ READER SURVEY In the time that I've been doing the QHJ I have received responses like "good job", "nice work", but very little actual comments (good or bad) on the overall content of the QHJ. In thinking of what to put into this issue, the idea of a reader survey popped in to my head. I am hoping that a number of you will respond to the survey and help me is figuring out what direction the QHJ should take. I would like to know what sort of articles you prefer and want. I want to know what languages you prefer. I want to know the level of programming knowledge you know. All of this will help me figure out what sort of people read the QHJ. In the past I've just guessed at what to cover. I've put in articles that I found interesting. I've included stuff that I thought others would find interesting. But, it's always been a guess. Programming Questions: What languages do you program in? [ List language in order of preference and rank your knowledge of each on a scale of 1-5 ] What compiler/interpreter do you use? What languages would you like to see covered? State your areas of interest in programming? How much time do you program? In a day? In a week? In a month? Do you program professionally? What level of training have you had in programming? Self-taught? A few classes? College? What is your favorite text editor? QHJ Related Questions: What languages would you like to see covered? What areas of programming would you like to see covered? Do you prefer code intensive articles? Do you prefer more verbose articles? Do you prefer the hard-copy or the electronic version? How many other persons read your copy of the QHJ? Would you be interested in a QHJ T-shirt? QL Environment Questions: Do you use the Pointer Environment? Do you use ToolKit II? Do you use other computers?