From ST2975@SIUCVMB.SIU.EDU Thu Feb 25 03:10:04 1993 Received: from calvin.sfasu.edu by umaxc.weeg.uiowa.edu (5.61.jnf/920629) on Thu, 25 Feb 93 03:09:58 -0600 id AA08328 with SMTP Received: from SIUCVMB.SIU.EDU by calvin.sfasu.EDU with SMTP (5.59/25-eef) id AA27361; Thu, 25 Feb 93 03:01:00 CST Return-Path: Message-Id: <9302250901.AA27361@calvin.sfasu.EDU> Received: from SIUCVMB.SIU.EDU by SIUCVMB.SIU.EDU (IBM VM SMTP V2R1) with BSMTP id 6459; Thu, 25 Feb 93 03:01:48 CST Date: Thu, 25 Feb 93 02:59:17 CST From: ST2975@SIUCVMB.SIU.EDU To: hyperc-l@calvin.sfasu.edu Subject: Re:_create() Status: R It's hard to explain/desribe what I'm doing without showing the code. So here is the latest version of _create(). It is actually a low level C function that further calls one assembly module that actually makes the ProDOS mli call. It does contain ProDOS specific aspects, but ProDOS isn't UNIX. Unix like calls can probably be written on top of this. This is probably not the fastest way or approach to create a file. Of course assembly is, no argument there. This particular function is useful in writing quick C functions to test something or even write HyperC utilities that you don't want to hammer out in assembly. This is a note to those I did send library/source to: I have found some bugs in _create(), syscall() and will probably find others. The following is the C function _create() followed by the compiler generated cp-source that was modified/optimized and followed by syscall() /* * _create.c * source file for modified pseudo-code */ #include #define standard_file 1 #define TXT 0x04 #define create 0xc0 #define full_access 0xc3 #define linked_list 0x0d int _create(filename,storage_type,options) char *filename; char storage_type; struct { char access; char file_type; unsigned int aux_type; unsigned int create_date; unsigned int create_time; } *options; { int val; char *str; struct create_parms { char param_count; char *pathname; char access; char file_type; unsigned int aux_type; char storage_type; unsigned int create_date; unsigned int create_time; } cp; /* prepare C string for conversion to pascal string used by ProDOS */ /* pascal string dynamically allocated in the heap */ if((str = _c2pstr(filename)) == NIL) return(NO); /* set up parameter list dynamically allocated on C stack */ /* WARNING: p-code file generated is edited to align */ /* parameter list for ProDOS's use */ cp.param_count = 7; cp.pathname = str; switch(options) { case 0 : cp.access = full_access; break; default : cp.access = options->access; cp.file_type = options->file_type; cp.aux_type = options->aux_type; cp.create_date = options->create_date; cp.create_time = options->create_time; } switch(storage_type) { case linked_list: /* linked list (directory) */ cp.storage_type = storage_type; if(!options) { cp.aux_type = 0; cp.create_date = 0; cp.create_time = 0; } break; case standard_file: /* standard file */ cp.storage_type = storage_type; if(!options) { cp.file_type = TXT; cp.aux_type = 0; cp.create_date = 0; cp.create_time = 0; } break; default : /* default standard file */ cp.storage_type = standard_file; if(!options) { /* just in case... */ cp.file_type = TXT; cp.aux_type = 0; cp.create_date = 0; cp.create_time = 0; } } val = syscall(create, cp); free(str); return(val); } ========================================================================= ; this is the compiler generated cp-code modified, optimized and ; commented for the readers' enjoyment. ; Labels _2 and _6 are used by swt (switch block) .even ; bool _create(pathame,storage_type,options) _2: .lbl ; char *pathame .word _3,0 ; char storage_type .word 0,_5 ; struct options .even _6: .lbl ; parameters are positive local offsets and .word _10,1 ; local variables are negative offsets .word _7,13 .word 0,_12 ; parameter offsets: .even ; pathname : 4 .entry __create ; storage_type : 6 __create: .lbl ; options : 8 ; lnk 18 lnk 16 ; beginning of function. This one is modified/optimized. plw 4 jsr 2,__c2pstr slw -4 ; C string is converted to pascal string and its address jnez _1 ; is stored in local storage (negative offset) ldc 0 ; check for error and continue or return with NO rtn _1: .lbl ldc 7 ; this is the parameter count of the parameter table ; slb -18 ; stored in a local area on the c stack. It's modified slb -16 ; to align the parameter table for ProDOS llw -4 ; this is the address of the Pascal string ; slw -16 ; which is stored in parameter table for ProDOS slw -15 ; modified to align data for ProDOS llw 8 ; this is the options parameter swt _2 ; switch block. cf. addresses at top. _3: .lbl ldc 195 ; here we have full access ; slb -14 slb -13 ; stick it in parm table jmp _4 ; continue... _5: .lbl llw 8 ; get address of options struct lib 0 ; here we just fill in the parameter table from the ; slb -14 ; options list slb -13 llw 8 lib 1 ; slb -13 slb -12 ; modified to align llw 8 liw 2 ; slw -12 slw -11 ; modified to align... llw 8 liw 4 slw -8 ; this may not be the most efficient code for this llw 8 ; check results from compiler for different methods liw 6 ; also refer to manual re: C compiler description slw -6 _4: .lbl llw 6 ; again we check the parameters for storage type swt _6 ; switch block addresses above... _7: .lbl llw 6 ; slb -10 slb -9 llw 8 ; again check options parameter jnez _9 ; continue if options filled in ldc 0 ; else zero aux_type ; slw -12 slw -11 _8: .lbl ldc 0 slw -8 ; zero create_time and date slw -6 jmp _9 _10: .lbl llw 6 ; slb -10 slb -9 ; storage type is standard file llw 8 ; again check for options jnez _9 ; continue if already filled in ldc 4 ; else TEXT file... ; slb -13 slb -12 _11: .lbl ldc 0 ; and zero out everything else ; slw -12 slw -11 slw -8 slw -6 jmp _9 _12: .lbl ldc 1 ; default is standard file just in case ; slb -10 slb -9 llw 8 ; again check for options jnez _9 ldc 4 ; else default TEXT file ; slb -13 slb -12 _13: .lbl ldc 0 ; and zero out everything else ; slw -12 slw -11 slw -8 slw -6 _9: .lbl ; pla -18 pla -16 ; push address of locally stored parm table pdc 192 ; and number for create mli command jsr 4,_syscall slw -2 ; store result temporarily plw -4 jsr 2,_free ; now free storage for pascal string from heap llw -2 ; load temporarily stored result rtn ; and return ; .extern _free _free = 0x82d .extern _syscall .extern __c2pstr ========================================================================= And here's the latest incantation of syscall(). This assembly module further calls the ProDOS mli. It checks to see if ProDOS is busy ; ; syscall.a, formerly callmli.a ; by Andy Werner ; first written, 1991, modified, February 21, 1992 ; ; modified December 25, 1992 to handle irq handlers that need to make ; calls to the mli, like printer spoolers. ; ; modified December 26, 1992 to simply return with carry set indicating ; that mli is busy, call me later. Expansion for later. ; ; cleaned up February 20, 1993 ; cinclude cinclude ; defines mli .entry _syscall ; BOOL syscall(cmdnum, fcmdparms) _syscall: ; boolean result returned in r1 php pha tya pha bit mliactv bpl $1 ; mli not busy, continue. pla ; simple return, restore registers tay ; and stack with carry set. pla plp sec ; let calling routine handle it. rts ; calling routine should examine mliactv $1: ldy #0 ; ProDOS result returned in __ioresult sty r1 sty r1h lda sp:,y sta cmdnum iny iny lda sp:,y sta cmdlist iny lda sp:,y sta cmdlist+1 pla ; restore y register previously pushed tay pla ; restore accumulator plp ; restore status register jsr mli cmdnum: .byte 0 cmdlist: .word 0 sta __ioresult ; return acc in __ioresult, defined in std.h bcs $1 inc r1 ; return YES in r1 $1: rts ; return NO in r1 already set above