RDROYA01@ULKYVX.BITNET (Robert Royar) (01/02/87)
The other day I wrote about trouble with wild card expansion on the command line using the Alcyon runtime library. Yesterday I spent the entire day tracking down the problem and discovered a few loose ends in the operating system and in the startup code. The problem turned out to be three problems all related to the spurious trap #2 vector. The Alcyon library was originally designed to work with CP/M-68K (note that's 68 not 86 as a number of Atari users seem to believe). That OS used trap #2 for all BDOS service and trap #3 for the BIOS. Apparently, GEM still uses the trap #2 vector for some calls to the GSX, but none of these were supported in the original CP/M system and none are used by gemlib. The ones that are used by gemlib are function 2 (conout), function 9 (print string), and 26 (set DMA, really a set DTA call). But when these functions go through trap #2, after about 6 branches all over the place, the trap routine simply RTEs. What this means is that calls to conout in ttyout.o, calls to print string in ttyout.o and in xmain.o, and calls to set DMA in xmain.o are all big no ops. Therefore, the runtime lib cannot print its own startup error messages. It cannot find the names of files it has searched for with the Fsfirst() call (because the DMA address it set with the set DMA command contains only garbage). And, chances are, any attempt to use stdout or any other standard TTY:/CON: file will fail simply because the routine to output the characters are no ops. Fixing these problems was relatively simple, rewrite the ___BDOS function in gemstart.s. Since the function numbers and parameters are the same (just the trap vectors differ), all that was needed were some simple comparisons. Below is the new __BDOS call in my revised gemstart.s: * * Surprise, the trap #2 vector is largely a do nothing routine. * Redirecting the basic calls may help solve a few problems. * .globl ___BDOS ___BDOS: link A6,#-4 cmpi.w #9,$8(A6) * print string beq togem cmpi.w #2,$8(A6) * conout beq togem cmpi.w #1,$8(A6) * conin (not called in gemlib) beq togem cmpi.w #26,$8(A6) * set dma bne bdos * GSX uses some functions above # $C0 togem: move.l $a(A6),(sp) * value move.w $8(A6),-(sp) * function bsr _gemdos addq.l #2,sp bra out bdos: move.l $a(A6),d1 * value move.w $8(A6),d0 * function trap #2 * Enter BDOS cmpa.l __break,sp * Check for stack ovf bcs __sovf * overflow! print msg and abort out: unlk A6 * no error; return rts * Back to caller _gemdos: move.l (sp)+,biosret trap #1 move.l biosret,-(sp) rts Compiling with this startup file let me get "*.C No match" from the runtime library as it tried to open all the C files on the drive. Before the error would not print. The next problem is in the gemlib module xopen.o, the function ___open. This is a low level IO function which is apparently only called to parse and expand command line file names. It uses gemdos for all service. But the problem in this part of the library is one I have discovered twice before with the Alcyon library in other functions, an error that is either a simple typo or one which signals a problem with the code parser. Since this error does not occur, or has not yet occurred, in files I've compiled, I assume it was a typo in the original source, something that could easily be corrected. The problem is a `beq' instruction which should have been a `bne.' The test occurs twice in ___open, once after Fsfirst() at offset $ae from the first address of the file and again after Fsnext() at offset $c8. In both cases these calls return -1 on error and 0 for success. But the code tests for the value in register D0 and if it is equal to 0, branches to the error exit routine. Changing the value of that instruction fixed most of the wild card problems. Here's how to do that: 1. using ar68, extract xopen.o from gemlib 2. start up sid 3. type r xopen.o at the sid `-' prompt 4. sid responds by reading the file and reporting the start and end addresses 5. type l<the start address sid reports> 6. the very first instruction is a "bra <absolute address>" 7. type l<that absolute address> (now we're alligned on the proper boundary) 8. use the l command to look for a "move.w #$4e,(sp)-" followed by a "jsr $0" (this is the search first command) 9. about three instructions down from the jsr is the beq. Change this to a bne using the s command (beq=$67; bne=$66) 10. at offset $1a from the beq is another beq (right after the search next). again using the s command, change this to a bne. 11. after both changes are made, write the file by typing "w xopen.o" 12. replace the old xopen.o in gemlib with the new one (ar68 r gemlib xopen.o) Sid preserves the relocation bits and symbols, so the file will still work properly. Now for the last problem. With this patched gemlib, programs can finally get at the expanded file lists created by wildcards, except for one problem. The search commands read the drive and path name for the files and return only the name to the dta. None of the startup routines bother with paths or drive names (although they do extensive checking to assure they are correct). So the program's main() gets a list of file names without the path or drive appended (again, only if wildcards are used). It assumes that these names are for files on the current disk and path, which they may not be. So, even though the startup routine has diligently expanded the wildcards and assured that the files exist, if the logged in drive and current directory do not match the default drive/directory, main() cannot open the files. If the logged in drive/directory does match that used to expand the wildcards, then everything works OK. Somewhere in ___main there needs to be code to strcat the drivecode and directory (supplied on the command line) to the individula filenames before passing the argv vector to main. This is not the kind of thing which can be patched. So if Alcyon is listening or Atari, perhaps someone with source could do this for those of us who grew up with command lines, wildcards and all that hoopla.