page@swan.ulowell.edu (Bob Page) (10/22/88)
Submitted-by: dillon@cory.berkeley.edu (Matt Dillon) Posting-number: Volume 2, Issue 5 Archive-name: util/suplib.1 [You need these library support routines and include files to compile most of Matt's source code. ..Bob] # This is a shell archive. Remove anything before this line # then unpack it by saving it in a file and typing "sh file" # (Files unpacked will be owned by you and have default permissions). # This archive contains the following files: # ./suplib/break.c # ./suplib/lunlink.c # ./suplib/setfiledate.c # ./suplib/NEW/compress.c # ./suplib/NEW/checkmsg.a68 # ./suplib/NEW/waitmsg.a68 # ./suplib/NEW/ioctl.doc # ./suplib/NEW/port.c # ./suplib/NEW/putsmsg.c # ./suplib/NEW/gethead.a68 # ./suplib/NEW/gettail.a68 # ./suplib/resource.asm # ./suplib/dio.c # ./suplib/asyncop.c # ./suplib/enviroment.c # ./suplib/typedefs.h # ./suplib/xmisc.h # ./suplib/dio.h # ./suplib/conwin.c # if `test ! -d ./suplib` then mkdir ./suplib echo "mkdir ./suplib" fi if `test ! -s ./suplib/break.c` then echo "writing ./suplib/break.c" cat > ./suplib/break.c << '\Rogue\Monster\' extern int Enable_Abort; disablebreak() { Enable_Abort = 0; } enablebreak() { Enable_Abort = 1; } \Rogue\Monster\ else echo "will not over write ./suplib/break.c" fi if [ `wc -c ./suplib/break.c | awk '{printf $1}'` -ne 111 ] then echo `wc -c ./suplib/break.c | awk '{print "Got " $1 ", Expected " 111}'` fi if `test ! -s ./suplib/lunlink.c` then echo "writing ./suplib/lunlink.c" cat > ./suplib/lunlink.c << '\Rogue\Monster\' #include <local/xmisc.h> XLIST * lunlink(en) register XLIST *en; { if (en) { if (en->next) en->next->prev = en->prev; *en->prev = en->next; en->next = NULL; en->prev = NULL; } return(en); } \Rogue\Monster\ else echo "will not over write ./suplib/lunlink.c" fi if [ `wc -c ./suplib/lunlink.c | awk '{printf $1}'` -ne 216 ] then echo `wc -c ./suplib/lunlink.c | awk '{print "Got " $1 ", Expected " 216}'` fi if `test ! -s ./suplib/setfiledate.c` then echo "writing ./suplib/setfiledate.c" cat > ./suplib/setfiledate.c << '\Rogue\Monster\' /* * SETFILEDATE.C * * BOOL = setfiledate(filename, date) */ #define BTOC(bptr) ((long)(bptr) << 2) #define CTOB(cptr) ((long)(cptr) >> 2) #ifndef ACTION_SET_DATE #define ACTION_SET_DATE 34 #endif typedef struct Task TASK; typedef struct Process PROC; typedef struct StandardPacket STDPKT; typedef struct MsgPort MSGPORT; typedef struct FileLock LOCK; typedef struct DateStamp DATESTAMP; extern TASK *FindTask(); extern void *AllocMem(); setfiledate(file, date) char *file; DATESTAMP *date; { register STDPKT *packet; register char *buf; register PROC *proc; long result; long lock; { register long flock = Lock(file, SHARED_LOCK); register short i; register char *ptr = file; if (flock == NULL) return(NULL); lock = ParentDir(flock); UnLock(flock); if (!lock) return(NULL); for (i = strlen(ptr) - 1; i >= 0; --i) { if (ptr[i] == '/' || ptr[i] == ':') break; } file += i + 1; } proc = (PROC *)FindTask(NULL); packet = (STDPKT *)AllocMem(sizeof(STDPKT), MEMF_CLEAR|MEMF_PUBLIC); buf = AllocMem(strlen(file)+2, MEMF_PUBLIC); strcpy(buf+1,file); buf[0] = strlen(file); packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &packet->sp_Msg; packet->sp_Pkt.dp_Port = &proc->pr_MsgPort; packet->sp_Pkt.dp_Type = ACTION_SET_DATE; packet->sp_Pkt.dp_Arg1 = NULL; packet->sp_Pkt.dp_Arg2 = (long)lock; /* lock on parent dir of file */ packet->sp_Pkt.dp_Arg3 = (long)CTOB(buf); /* BPTR to BSTR of file name */ packet->sp_Pkt.dp_Arg4 = (long)date; /* APTR to datestamp structure */ PutMsg(((LOCK *)BTOC(lock))->fl_Task, packet); WaitPort(&proc->pr_MsgPort); GetMsg(&proc->pr_MsgPort); result = packet->sp_Pkt.dp_Res1; FreeMem(packet, sizeof(STDPKT)); FreeMem(buf, strlen(file)+2); UnLock(lock); return(result); } \Rogue\Monster\ else echo "will not over write ./suplib/setfiledate.c" fi if [ `wc -c ./suplib/setfiledate.c | awk '{printf $1}'` -ne 1951 ] then echo `wc -c ./suplib/setfiledate.c | awk '{print "Got " $1 ", Expected " 1951}'` fi if `test ! -d ./suplib/NEW` then mkdir ./suplib/NEW echo "mkdir ./suplib/NEW" fi if `test ! -s ./suplib/NEW/compress.c` then echo "writing ./suplib/NEW/compress.c" cat > ./suplib/NEW/compress.c << '\Rogue\Monster\' /* * Independant compress/uncompress module. User must supply the * following routines: * * c = cgetchar() (returns EOF on end/error) * (void) cputchar(c) * len = cread(buf, len) (returns EOF on end/error) * (void) cwrite(buf, len) * * Calls: Compress(filesize) (filesize used only to optimize hash table) * UnCompress() */ #include <stdio.h> #ifndef min #define min(a,b) ((a>b) ? b : a) #endif #define BITS 13 #if BITS == 16 #define HSIZE 69001 /* 95% occupancy */ #endif #if BITS == 15 #define HSIZE 35023 /* 94% occupancy */ #endif #if BITS == 14 #define HSIZE 18013 /* 91% occupancy */ #endif #if BITS == 13 #define HSIZE 9001 /* 91% occupancy */ #endif #if BITS <= 12 #define HSIZE 5003 /* 80% occupancy */ #endif typedef long code_int; typedef long count_int; typedef unsigned char char_type; typedef unsigned short uword; #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) #define INIT_BITS 9 /* initial number of bits/code */ static int n_bits; /* number of bits/code */ static int maxbits; /* user settable max # bits/code */ static code_int maxcode; /* maximum code, given n_bits */ static code_int maxmaxcode; /* should NEVER generate this code */ static long CLen; static count_int htab[HSIZE]; static uword codetab[HSIZE]; #define htabof(i) htab[i] #define codetabof(i) codetab[i] static code_int hsize = HSIZE; /* for dynamic table sizing */ #define tab_prefixof(i) codetabof(i) #define tab_suffixof(i) ((char_type *)(htab))[i] #define de_stack ((char_type *)&tab_suffixof(1<<BITS)) static code_int free_ent; /* first unused entry */ code_int getcode(); #define CHECK_GAP 10000 /* ratio check interval */ static int block_compress = 1; static int clear_flg; static long ratio; static count_int checkpoint; #define FIRST 257 /* first free entry */ #define CLEAR 256 /* table clear output code */ static int offset; long int in_count = 1; /* length of input */ void Compress(fsize) { long fcode; code_int i = 0; int c; code_int ent; int disp; code_int hsize_reg; int hshift; bzero(htab, sizeof(htab)); bzero(codetab, sizeof(codetab)); CLen = 0; hsize = HSIZE; if ( fsize < (1 << 12) ) hsize = min ( 5003, HSIZE ); else if ( fsize < (1 << 13) ) hsize = min ( 9001, HSIZE ); else if ( fsize < (1 << 14) ) hsize = min ( 18013, HSIZE ); else if ( fsize < (1 << 15) ) hsize = min ( 35023, HSIZE ); else if ( fsize < 47000 ) hsize = min ( 50021, HSIZE ); offset = clear_flg = ratio = 0; in_count = 1; checkpoint = CHECK_GAP; n_bits = INIT_BITS; /* number of bits/code */ maxbits = BITS; /* user settable max # bits/code */ maxcode = MAXCODE(INIT_BITS); /* maximum code, given n_bits */ maxmaxcode = 1 << BITS; /* should NEVER generate this code */ free_ent = ((block_compress) ? FIRST : 256 ); ent = ngetchar(); hshift = 0; for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L ) hshift++; hshift = 8 - hshift; /* set hash code range bound */ hsize_reg = hsize; cl_hash((count_int)hsize_reg); /* clear hash table */ while ((c = ngetchar()) != EOF) { in_count++; fcode = (long) (((long) c << maxbits) + ent); i = ((c << hshift) ^ ent); /* xor hashing */ if (htabof (i) == fcode) { ent = codetabof(i); continue; } else if ((long)htabof (i) < 0) /* empty slot */ goto nomatch; disp = hsize_reg - i; /* secondary hash (after G. Knott) */ if (i == 0) disp = 1; probe: if ((i -= disp) < 0) i += hsize_reg; if (htabof (i) == fcode) { ent = codetabof(i); continue; } if ((long)htabof (i) > 0) goto probe; nomatch: output ((code_int) ent); ent = c; if (free_ent < maxmaxcode) { codetabof(i) = free_ent++; /* code -> hashtable */ htabof(i) = fcode; } else if ((count_int)in_count >= checkpoint && block_compress) cl_block (); } /* * Put out the final code. */ output((code_int)ent); output((code_int)-1); } static char buf[BITS]; char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; output( code ) code_int code; { register int r_off = offset, bits= n_bits; register char * bp = buf; if ( code >= 0 ) { /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* * Since code is always >= 8 bits, only need to mask the first * hunk on the left. */ *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; bp++; bits -= (8 - r_off); code >>= 8 - r_off; /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if ( bits >= 8 ) { *bp++ = code; code >>= 8; bits -= 8; } /* Last bits. */ if(bits) *bp = code; offset += n_bits; if (offset == (n_bits << 3)) { bp = buf; bits = n_bits; cwrite(bp, bits); CLen += bits; bp += bits; bits = 0; offset = 0; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if (free_ent > maxcode || (clear_flg > 0)) { /* * Write the whole buffer, because the input side won't * discover the size increase until after it has read it. */ if (offset > 0) cwrite(buf, n_bits); offset = 0; if (clear_flg) { n_bits = INIT_BITS; maxcode = MAXCODE(INIT_BITS); clear_flg = 0; } else { n_bits++; if (n_bits == maxbits) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } } else { /* * At EOF, write the rest of the buffer. */ if (offset > 0) cwrite(buf, (offset + 7) / 8); offset = 0; } } cl_block() /* table clear for block compress */ { register long int rat; checkpoint = in_count + CHECK_GAP; if (in_count > 0x007fffff) { /* shift will overflow */ rat = CLen >> 8; if (rat == 0) { /* Don't divide by zero */ rat = 0x7fffffff; } else { rat = in_count / rat; } } else { rat = (in_count << 8) / CLen; /* 8 fractional bits */ } if (rat > ratio) { ratio = rat; } else { ratio = 0; cl_hash ( (count_int) hsize ); free_ent = FIRST; clear_flg = 1; output ( (code_int) CLEAR ); } } cl_hash(hsize) /* reset code table */ register count_int hsize; { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for ( i += 16; i > 0; i-- ) *--htab_p = m1; } void UnCompress() { register char_type *stackp; register int finchar; register code_int code, oldcode, incode; /* * As above, initialize the first 256 entries in the table. */ bzero(htab, sizeof(htab)); bzero(codetab, sizeof(codetab)); offset = clear_flg = ratio = 0; in_count = 1; checkpoint = CHECK_GAP; n_bits = INIT_BITS; /* number of bits/code */ maxbits = BITS; /* user settable max # bits/code */ maxcode = MAXCODE(INIT_BITS); /* maximum code, given n_bits */ maxmaxcode = 1 << BITS; /* should NEVER generate this code */ for ( code = 255; code >= 0; code-- ) { tab_prefixof(code) = 0; tab_suffixof(code) = (char_type)code; } free_ent = ((block_compress) ? FIRST : 256 ); finchar = oldcode = getcode(); if (oldcode == -1) /* EOF already? */ return; /* Get out of here */ cputchar((char)finchar); /* first code must be 8 bits = char */ ++CLen; stackp = de_stack; while ((code = getcode()) > -1) { if ((code == CLEAR) && block_compress) { for (code = 255; code >= 0; code--) tab_prefixof(code) = 0; clear_flg = 1; free_ent = FIRST - 1; if ((code = getcode()) == -1) /* O, untimely death! */ break; } incode = code; /* * Special case for KwKwK string. */ if (code >= free_ent) { *stackp++ = finchar; code = oldcode; } /* * Generate output characters in reverse order */ while ( code >= 256 ) { *stackp++ = tab_suffixof(code); code = tab_prefixof(code); } *stackp++ = finchar = tab_suffixof(code); /* * And put them out in forward order */ do { cputchar (*--stackp); ++CLen; } while (stackp > de_stack); /* * Generate the new entry. */ if ((code=free_ent) < maxmaxcode) { tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = finchar; free_ent = code+1; } /* * Remember previous code. */ oldcode = incode; } } code_int getcode() { /* * On the VAX, it is important to have the register declarations * in exactly the order given, or the asm will break. */ register code_int code; static int offset = 0, size = 0; static char_type buf[BITS]; register int r_off, bits; register char_type *bp = buf; if (clear_flg > 0 || offset >= size || free_ent > maxcode) { /* * If the next entry will be too big for the current code * size, then we must increase the size. This implies reading * a new buffer full, too. */ if ( free_ent > maxcode ) { n_bits++; if ( n_bits == maxbits ) maxcode = maxmaxcode; /* won't get any bigger now */ else maxcode = MAXCODE(n_bits); } if ( clear_flg > 0) { maxcode = MAXCODE (n_bits = INIT_BITS); clear_flg = 0; } size = cread(buf, n_bits); if (size <= 0) return -1; /* end of file */ offset = 0; size = (size << 3) - (n_bits - 1); } r_off = offset; bits = n_bits; /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ code = (*bp++ >> r_off); bits -= (8 - r_off); r_off = 8 - r_off; /* now, offset into code word */ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if ( bits >= 8 ) { code |= *bp++ << r_off; r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off; offset += n_bits; return code; } #asm ; static (to this module only) bzero... simple and ; stupid. Non critical. _bzero: move.l 4(sp),A0 move.l 8(sp),D0 beq .bz2 .bz1 clr.b D1 move.b D1,(A0)+ subq.l #1,D0 bne .bz1 .bz2 rts #endasm \Rogue\Monster\ else echo "will not over write ./suplib/NEW/compress.c" fi if [ `wc -c ./suplib/NEW/compress.c | awk '{printf $1}'` -ne 10805 ] then echo `wc -c ./suplib/NEW/compress.c | awk '{print "Got " $1 ", Expected " 10805}'` fi if `test ! -s ./suplib/NEW/checkmsg.a68` then echo "writing ./suplib/NEW/checkmsg.a68" cat > ./suplib/NEW/checkmsg.a68 << '\Rogue\Monster\' public _CheckMsg NT_MESSAGE equ 5 NT_FREEMSG equ 6 NT_REPLYMSG equ 7 CheckMsg: move.l 4(sp),A0 ; message clr.l D0 cmp.b #NT_MESSAGE,8(A0) ; type beq .1 move.l A0,D0 .1 rts \Rogue\Monster\ else echo "will not over write ./suplib/NEW/checkmsg.a68" fi if [ `wc -c ./suplib/NEW/checkmsg.a68 | awk '{printf $1}'` -ne 202 ] then echo `wc -c ./suplib/NEW/checkmsg.a68 | awk '{print "Got " $1 ", Expected " 202}'` fi if `test ! -s ./suplib/NEW/waitmsg.a68` then echo "writing ./suplib/NEW/waitmsg.a68" cat > ./suplib/NEW/waitmsg.a68 << '\Rogue\Monster\' public _WaitMsg public _LVOWait public _SysBase NT_MESSAGE equ 5 NT_FREEMSG equ 6 NT_REPLYMSG equ 7 _WaitMsg: movem.l A2/A6,-(sp) move.l 12(sp),A2 ; A2 = message move.l _SysBase,A6 .1 cmp.b #NT_REPLYMSG,8(A2) ; has it been replied? beq .10 .2 cmp.b #NT_FREEMSG,8(A2) ; has it been freed? beq .15 move.l 14(A2),A1 ; reply port tst.l A1 beq .1 ; NULL reply port, busy wait. move.b 15(A1),D1 ; signal bit # moveq.l #1,D0 asl.l D1,D0 ; D0 = signal mask jsr _LVOWait(A6) ; wait for signal bra .1 ; loop again .10 jsr _LVODisable(A6) move.l A2,A1 jsr _LVORemove(A6) jsr _LVOEnable(A6) .15 movem.l (sp)+,A2/A6 ; return the message move.l A2,D0 rts \Rogue\Monster\ else echo "will not over write ./suplib/NEW/waitmsg.a68" fi if [ `wc -c ./suplib/NEW/waitmsg.a68 | awk '{printf $1}'` -ne 754 ] then echo `wc -c ./suplib/NEW/waitmsg.a68 | awk '{print "Got " $1 ", Expected " 754}'` fi if `test ! -s ./suplib/NEW/ioctl.doc` then echo "writing ./suplib/NEW/ioctl.doc" cat > ./suplib/NEW/ioctl.doc << '\Rogue\Monster\' IOCTL.DOC IO control interface (main routines) IoOpen("device") result = IoCtl(fd,cmd,arg1,arg2) result = IoAbort(fd) fd2 = IoDup(fd) IoClose(fd) (useful macros) IoRead(fd,buf,len) normal io IoReadA(fd,buf,len) IoWrite(fd,buf,len) IoWriteA(fd,buf,len) IoReadExt(fd,buf,len,offset) extended io IoWriteExt(fd,buf,len,offset) IoReadExtA(fd,buf,len,offset) IoWriteExtA(fd,buf,len,offset) cmd: FEDCBA98 76543210 FEDCBA9876543210 <GENFLGS> <SPECFLGS> <COMMAND NUMBER> General Flags: Device Independant flags Specific Flags: Device Dependant flags (reused by devices) Command Number: Command # (unique) GENERAL CALLS IOF_ASYNC asynchronous flag (result will be negative or 0) IOC_RESET reset device IOC_READ read or start asynch read IOC_WRITE write or start asynch write IOC_UPDATE update device IOC_CLEAR clear device IOC_STOP stop device IOC_START start device IOC_FLUSH flush device IOC_FLAGS IoCtl flags: IOCF_NBIO non-blocking IO IOCF_TIMEOUT if not IOCF_NBIO, block abort timeout IOC_TIMEOUT set automatic timeout period (default 0=disabled) IOC_SIGNAL return associated signal IOC_SETSIG set associated SigNo. IOC_CHECK check pending request (-1=pulled, 0=ready, 1=pending) IOC_WAIT wait for pending request IOCTL DEVICE IOC_IOCADDDEVICE IOC_IOCREMDEVICE AUDIO DEVICE IOC_AUDFLAGS set/clear ADIOF_* flags IOC_AUDFREE (normal device call) IOC_AUDSETPREC IOC_AUDFINISH IOC_AUDPERVOL IOC_AUDLOCK IOC_AUDWAITCYC CLIPBOARD DEVICE IOC_CLPOST IOC_CLCREADID IOC_CLCWRITEID CONSOLE DEVICE IOC_CONASKKEYMAP IOC_CONSETKEYMAP IOC_CONASKDEFKM IOC_CONSETDEFKM GAMEPORT DEVICE IOC_GPFLAGS IOC_GPREADEVENT IOC_GPASKCTYPE IOC_GPSETCTYPE IOC_GPASKTRIGGER IOC_GPSETTRIGGER INPUT DEVICE IOC_IDADDHANDLER IOC_IDREMHANDLER IOC_IDWRITEEVENT IOC_IDSETTHRESH IOC_IDSETPERIOD IOC_IDSETMPORT IOC_IDSETMTYPE IOC_IDSETMTRIG KEYBOARD DEVICE IOC_KBREADEVENT IOC_KBREADMATRIX IOC_KBADDRESHANDLER IOC_KBREMRESHANDLER IOC_KBRESHANDLERDONE NARRATOR DEVICE PARALLEL DEVICE IOC_PARFLAGS IOC_PARQUERY IOC_PARPARAMS PRINTER DEVICE IOC_PRTRAWWRITE IOC_PRTCOMMAND IOC_PRTDUMPRPORT SERIAL DEVICE IOC_SERFLAGS IOC_SERSEXFLAGS IOC_SERQUERY IOC_SERBREAK IOC_SERPARAMS TIMER DEVICE IOC_TRSETUNIT IOC_TRADDREQUEST IOC_TRGETSYSTIME IOC_TRSETSYSTIME TRACKDISK DEVICE IOF_TDEXTCOM IOC_TDSETOFFSET IOC_TDFLAGS IOC_TDMOTOR IOC_TDSEEK IOC_TDFORMAT IOC_TDREMOVE IOC_TDCHANGENUM IOC_TDCHANGESTATE IOC_TDPROTSTATUS IOC_TDRAWREAD IOC_TDRAWWRITE IOC_TDGETDRIVETYPE IOC_TDGETNUMTRACKS IOC_TDADDCHANGEINT IOC_TDREMCHANGEINT \Rogue\Monster\ else echo "will not over write ./suplib/NEW/ioctl.doc" fi if [ `wc -c ./suplib/NEW/ioctl.doc | awk '{printf $1}'` -ne 3089 ] then echo `wc -c ./suplib/NEW/ioctl.doc | awk '{print "Got " $1 ", Expected " 3089}'` fi if `test ! -s ./suplib/NEW/port.c` then echo "writing ./suplib/NEW/port.c" cat > ./suplib/NEW/port.c << '\Rogue\Monster\' /* * CreateUniquePort(name, pri) * DeleteUniquePort(port) */ #include <exec/types.h> #include <typdefs.h> typedef struct MsgPort PORT; PORT * CreateUniquePort(name, priority) char *name; { register int n = 0; register char *ptr; register PORT *port; char buf[64]; Forbid(); if (ptr = name) { strcpy(buf, name); while (FindPort(buf)) sprintf(buf, "%s.%d\n", name, ++n); if (ptr = AllocMem(strlen(buf)+1, MEMF_PUBLIC)) { strcpy(ptr, buf); } else { Permit(); return(NULL); } } if (!(port = CreatePort(ptr, priority)) && ptr) FreeMem(ptr, strlen(ptr)+1); Permit(); return(port); } DeleteUniquePort(port) register PORT *port; { register char *name; RemPort(port); if (name = port->mp_Node.ln_Name) { FreeMem(name, strlen(name)+1); port->mp_Node.ln_Name = NULL; } DeletePort(port); } \Rogue\Monster\ else echo "will not over write ./suplib/NEW/port.c" fi if [ `wc -c ./suplib/NEW/port.c | awk '{printf $1}'` -ne 879 ] then echo `wc -c ./suplib/NEW/port.c | awk '{print "Got " $1 ", Expected " 879}'` fi if `test ! -s ./suplib/NEW/putsmsg.c` then echo "writing ./suplib/NEW/putsmsg.c" cat > ./suplib/NEW/putsmsg.c << '\Rogue\Monster\' #include <exec/types.h> #include <typedefs.h> typedef struct Port PORT; typedef struct Message MSG; PutSyncMsg(port, msg) PORT *port; MSG *msg; { } PutSyncMsgSimple(port, ptr, cmd) PORT *port; MSG *msg; { } \Rogue\Monster\ else echo "will not over write ./suplib/NEW/putsmsg.c" fi if [ `wc -c ./suplib/NEW/putsmsg.c | awk '{printf $1}'` -ne 215 ] then echo `wc -c ./suplib/NEW/putsmsg.c | awk '{print "Got " $1 ", Expected " 215}'` fi if `test ! -s ./suplib/NEW/gethead.a68` then echo "writing ./suplib/NEW/gethead.a68" cat > ./suplib/NEW/gethead.a68 << '\Rogue\Monster\' ; GETHEAD(list) ; NEXTNODE(node) ; 4(sp) public _gethead public _nextnode _nextnode: _gethead: move.l 4(sp),A0 ;A0 = list or node move.l (A0),A1 ;A1 = lh_Head or ln_Succ move.l A1,D0 ;D0 = result tst.l (A1) ;does it point to lh_Tail? bne .1 ;no clr.l D0 ;yes .1 rts \Rogue\Monster\ else echo "will not over write ./suplib/NEW/gethead.a68" fi if [ `wc -c ./suplib/NEW/gethead.a68 | awk '{printf $1}'` -ne 352 ] then echo `wc -c ./suplib/NEW/gethead.a68 | awk '{print "Got " $1 ", Expected " 352}'` fi if `test ! -s ./suplib/NEW/gettail.a68` then echo "writing ./suplib/NEW/gettail.a68" cat > ./suplib/NEW/gettail.a68 << '\Rogue\Monster\' ; GETTAIL(list) ; 4(sp) public _gettail _gettail: move.l 4(sp),A0 ;A0 = list move.l 8(A0),A1 ;A1 = lh_TailPred move.l A1,D0 ;D0 = result cmp.l A1,A0 ;is it pointing to lh_Head? bne .1 ;no clr.l D0 ;yes .1 rts \Rogue\Monster\ else echo "will not over write ./suplib/NEW/gettail.a68" fi if [ `wc -c ./suplib/NEW/gettail.a68 | awk '{printf $1}'` -ne 279 ] then echo `wc -c ./suplib/NEW/gettail.a68 | awk '{print "Got " $1 ", Expected " 279}'` fi if `test ! -s ./suplib/resource.asm` then echo "writing ./suplib/resource.asm" cat > ./suplib/resource.asm << '\Rogue\Monster\' ; ; EXEC resource support ; 4(sp) 8(sp) ; AutoAllocMiscResource(resno, value) ; resno: MR_SERIALPORT, SERIALBITS, PARALLELPORT, PARALLELBITS ; value: -1 to allocate, 0 to check ; ; returns 0 on success ; ; AutoFreeMiscResource(resno) ; 4(sp) ; Free a misc resource you allocated ; ; No need to open the misc.resource public _AutoAllocMiscResource public _AutoFreeMiscResource public _LVOOpenResource FAR DATA _AutoAllocMiscResource: move.l A6,-(sp) bsr OpenMiscResource beq amfail move.l 8(sp),D0 move.l 12(sp),A1 jsr -6(A6) bra amret amfail moveq.l #-1,D0 amret move.l (sp)+,A6 rts _AutoFreeMiscResource: move.l A6,-(sp) bsr OpenMiscResource beq fmret move.l 8(sp),D0 jsr -12(A6) fmret move.l (sp)+,A6 rts OpenMiscResource: move.l 4,A6 lea.l MiscName,A1 jsr _LVOOpenResource(A6) move.l D0,A6 tst.l D0 rts MiscName: dc.b "misc.resource",0 \Rogue\Monster\ else echo "will not over write ./suplib/resource.asm" fi if [ `wc -c ./suplib/resource.asm | awk '{printf $1}'` -ne 1089 ] then echo `wc -c ./suplib/resource.asm | awk '{print "Got " $1 ", Expected " 1089}'` fi if `test ! -s ./suplib/dio.c` then echo "writing ./suplib/dio.c" cat > ./suplib/dio.c << '\Rogue\Monster\' /* * DIO.C * * (C)Copyright 1987 by Matthew Dillon, All rights reserved * Freely distributable. Donations Welcome. This is NOT shareware, * This is NOT public domain. * * Matthew Dillon * 891 Regal Rd. * Berkeley, Ca. 94708 * * EXEC device driver IO support routines... makes everything easy. * * dfd = dio_open(name, unit, flags, req/NULL) * * open an IO device. Note: in some cases you might have to provide * a request structure with some fields initialized (example, the * console device requires certain fields to be initialized). For * instance, if openning the SERIAL.DEVICE, you would want to give * an IOExtSer structure which is completely blank execept for the * io_SerFlags field. * * The request structure's message and reply ports need not be * initialized. The request structure is no longer needed after * the dio_open(). * * NULL = error, else descriptor (a pointer) returned. * * * dio_close(dfd) * * close an IO device. Any pending asyncronous requests are * AbortIO()'d and then Wait'ed on for completion. * * * dio_closegrp(dfd) * * close EVERY DIO DESCRIPTOR ASSOCIATED WITH THE dio_open() call * that was the parent for this descriptor. That is, you can get * a descriptor using dio_open(), dio_dup() it a couple of times, * then use dio_closegrp() on any ONE of the resulting descriptors * to close ALL of them. * * * dio_ddl(dfd,bool) * * Disable BUF and LEN fields in dio_ctl[_to].. dummy parameters * must still be passed, but they are not loaded into the io_Data * and io_Length fields of the io request. This is for devices * like the AUDIO.DEVICE which has io_Data/io_Length in non-standard * places. * * dio_cact(dfd,bool) * * If an error occurs (io_Error field), the io_Actual field is usually * not modified by the device driver, and thus contains garbage. To * provide a cleaner interface, you can have DIO_CTL() and DIO_CTL_TO() * calls automatically pre-clear this field so if an io_Error does * occur, the field is a definate 0 instead of garbage. * * In most cases you will want to do this. An exception is the * TIMER.DEVICE, which uses the io_Actual field for part of the * timeout structure. * * This flags the particular dio descriptor to do the pre-clear, and * any new descriptors obtained by DIO_DUP()ing this one will also * have the pre-clear flag set. * * * dio_dup(dfd) * * Returns a new channel descriptor referencing the same device. * The new descriptor has it's own signal and IO request structure. * For instance, if you openned the serial device, you might want * to dup the descriptor so you can use one channel to pend an * asyncronous read, and the other channel to write out to the device * and do other things without disturbing the asyncronous read. * * * sig = dio_signal(dfd) * * get the signal number (0..31) used for a DIO descriptor. * This allows you to Wait() for asyncronous requests. Note that * if your Wait() returns, you should double check using dio_isdone() * * dio_flags(dfd, or, ~and) * * Modify the io_Flags field in the request, ORing it with the OR * mask, and ANDing it with ~AND mask. E.G., the AUDIO.DEVICE requires * some flags be put in io_Flags. * * req = dio_ctl_to(dfd, command, buf, len, to) * * Same as DIO_CTL() below, but (A) is always syncronous, and * (B) will attempt to AbortIO()+WaitIO() the request if the * timeout occurs before the IO completes. * * the 'to' argument is in microseconds. * * If timeout occurs before request completes, and DIO aborts the * request, some devices do not have the io_Actual field set * properly. * * req = dio_ctl(dfd, command, buf, len) * * DIO_CTL() is the basis for the entire library. It works as follows: * * (1) If the channel isn't clear (there is an asyncronous IO request * still pending), DIO_CTL() waits for it to complete * * (2) If the command is 0, simply return a pointer to the io * request structure. * * (3) If the DIO_CACT() flag is TRUE, the io_Actual field of the * request is cleared. * * (4) Set the io_Data field to 'buf', and io_Length field to 'len' * If the command is positive, use DoIO(). If the command * negative, take it's absolute value and then do a SendIO(). * (The command is placed in the io_Command field, of course). * * (5) return the IO request structure * * * bool= dio_isdone(dfd) * * return 1 if current channel is clear (done processing), else 0. * e.g. if you did, say, an asyncronous read, and dio_isdone() returns * true, you can now use the data buffer returned and look at the * io_Actual field. * * You need not do a dio_wait() after dio_isdone() returns 1. * * * req = dio_wait(dfd) * * Wait on the current channel for the request to complete and * then return the request structure. (nop if channel is clear) * * * req = dio_abort(dfd) * * Abort the request on the current channel (nop if channel is * clear). Sends an AbortIO() if the channel is active and then * WaitIO()'s the request. * * * MACROS: SEE DIO.H * */ #include <exec/types.h> #include <exec/io.h> #include <exec/memory.h> #include <exec/ports.h> #include <devices/timer.h> #include <local/xmisc.h> #define MPC (MEMF_CLEAR|MEMF_PUBLIC) #define CPORT ior.ior.io_Message.mn_ReplyPort #define MAXREQSIZE 128 /* big enough to hold all Amiga iorequests */ typedef struct IORequest IOR; typedef struct IOStdReq STD; typedef struct MsgPort PORT; typedef struct { STD ior; char filler[MAXREQSIZE-sizeof(STD)]; } MAXIOR; typedef struct { struct _CHAN *list; short refs; } DIO; typedef struct _CHAN { MAXIOR ior; DIO *base; XLIST link; /* doubly linked list */ STD timer; char notclear; char cact; /* automatic io_Actual field clear */ char ddl; UBYTE flagmask; } CHAN; extern CHAN *dio_ctl(), *dio_ctl_to(), *dio_wait(), *dio_abort(); extern PORT *CreatePort(); extern char *AllocMem(); CHAN * dio_open(name, unit, flags, req) char *name; MAXIOR *req; /* not really this big */ { register CHAN *chan; register DIO *dio; register PORT *port; int ret; dio = (DIO *)AllocMem(sizeof(DIO), MPC); if (!dio) goto fail3; chan= (CHAN *)AllocMem(sizeof(CHAN), MPC); if (!chan) goto fail2; if (req) chan->ior = *req; chan->CPORT = CreatePort(NULL,0); if (!chan->CPORT) goto fail1; chan->ior.ior.io_Message.mn_Node.ln_Type = NT_MESSAGE; chan->base = dio; chan->flagmask = 0xF0; dio->refs = 1; if (OpenDevice(name, unit, &chan->ior, flags)) { DeletePort(chan->CPORT); fail1: FreeMem(chan, sizeof(CHAN)); fail2: FreeMem(dio, sizeof(DIO)); fail3: return(NULL); } llink(&dio->list, &chan->link); chan->ior.ior.io_Flags = 0; return(chan); } void dio_dfm(chan,mask) CHAN *chan; { chan->flagmask = mask; } void dio_ddl(chan,n) CHAN *chan; { chan->ddl = n; } void dio_cact(chan,n) CHAN *chan; { chan->cact = n; } void dio_close(chan) register CHAN *chan; { dio_abort(chan); lunlink(&chan->link); if (--chan->base->refs == 0) { FreeMem(chan->base, sizeof(DIO)); CloseDevice(&chan->ior); } if (chan->timer.io_Message.mn_ReplyPort) CloseDevice(&chan->timer); DeletePort(chan->CPORT); FreeMem(chan, sizeof(CHAN)); } void dio_closegroup(chan) register CHAN *chan; { register CHAN *nextc; for (chan = chan->base->list; chan; chan = nextc) { chan = (CHAN *)((char *)chan - ((char *)&chan->link - (char *)chan)); nextc = (CHAN *)chan->link.next; dio_close(chan); } } CHAN * dio_dup(chan) register CHAN *chan; { register CHAN *nc; if (chan) { nc = (CHAN *)AllocMem(sizeof(CHAN), MPC); if (!nc) goto fail2; nc->ior = chan->ior; nc->base = chan->base; nc->CPORT = CreatePort(NULL,0); if (!nc->CPORT) goto fail1; nc->ior.ior.io_Flags = NULL; nc->cact = chan->cact; nc->ddl = chan->ddl; nc->flagmask = chan->flagmask; ++nc->base->refs; llink(&nc->base->list, &nc->link); return(nc); fail1: FreeMem(nc, sizeof(CHAN)); } fail2: return(NULL); } dio_signal(chan) CHAN *chan; { return(chan->CPORT->mp_SigBit); } dio_flags(chan,or,and) long chan; { IOR *ior = (void *)chan; ior->io_Flags = (ior->io_Flags | or) & ~and; } CHAN * dio_ctl_to(chan, com, buf, len, to) register CHAN *chan; char *buf; { register long mask; if (chan->timer.io_Message.mn_ReplyPort == NULL) { chan->timer.io_Message.mn_ReplyPort = chan->CPORT; chan->timer.io_Message.mn_Node.ln_Type = NT_MESSAGE; if (OpenDevice("timer.device", UNIT_VBLANK, &chan->timer, 0)) { puts("Panic: DIO_CTL_TO: No timer.device"); } chan->timer.io_Command = TR_ADDREQUEST; } mask = 1 << chan->CPORT->mp_SigBit; dio_ctl(chan, (com>0)?-com:com, buf, len); /* SendIO the request */ chan->timer.io_Actual = to / 1000000; chan->timer.io_Length = to % 1000000; /* setup timer */ chan->timer.io_Flags = 0; BeginIO(&chan->timer); /* start timer running */ while (Wait(mask)) { /* Wait for something */ if (CheckIO(chan)) /* request done */ break; if (CheckIO(&chan->timer)) { /* timeout? */ dio_abort(chan); break; } } AbortIO(&chan->timer); /* kill the timer */ WaitIO(&chan->timer); /* remove from rp */ return(chan); /* return ior */ } CHAN * dio_ctl(chan, com, buf, len) register CHAN *chan; char *buf; { if (chan->notclear) { /* wait previous req to finish */ WaitIO(chan); chan->notclear = 0; } if (com) { if (chan->cact) chan->ior.ior.io_Actual = 0; /* initialize io_Actual to 0*/ chan->ior.ior.io_Error = 0; /* initialize error to 0 */ if (!chan->ddl) { chan->ior.ior.io_Data = (APTR)buf; /* buffer */ chan->ior.ior.io_Length = len; /* length */ } if (com < 0) { /* asyncronous IO */ chan->ior.ior.io_Command = -com; chan->notclear = 1; chan->ior.ior.io_Flags &= chan->flagmask; BeginIO(chan); } else { /* syncronous IO */ chan->ior.ior.io_Command = com; chan->ior.ior.io_Flags = (chan->ior.ior.io_Flags & chan->flagmask) | IOF_QUICK; BeginIO(chan); if (!(chan->ior.ior.io_Flags & IOF_QUICK)) WaitIO(chan); } } return(chan); } CHAN * dio_isdone(chan) register CHAN *chan; { if (chan->notclear) { /* if not clear */ if (CheckIO(chan)) { /* if done */ WaitIO(chan); /* clear */ chan->notclear = 0; return(chan); /* done */ } return(NULL); /* notdone */ } return(chan); /* done */ } CHAN * dio_wait(chan) register CHAN *chan; { if (chan->notclear) { WaitIO(chan); /* wait and remove from rp */ chan->notclear = 0; } return(chan); } CHAN * dio_abort(chan) register CHAN *chan; { if (chan->notclear) { AbortIO(chan); /* Abort it */ WaitIO(chan); /* wait and remove from rp */ chan->notclear = 0; } return(chan); } \Rogue\Monster\ else echo "will not over write ./suplib/dio.c" fi if [ `wc -c ./suplib/dio.c | awk '{printf $1}'` -ne 11170 ] then echo `wc -c ./suplib/dio.c | awk '{print "Got " $1 ", Expected " 11170}'` fi if `test ! -s ./suplib/asyncop.c` then echo "writing ./suplib/asyncop.c" cat > ./suplib/asyncop.c << '\Rogue\Monster\' /* * ASYNCOP.C */ typedef unsigned char ubyte; typedef unsigned short uword; typedef unsigned long ulong; typedef struct Message MSG; typedef struct MsgPort PORT; typedef struct Task TASK; typedef struct Node NODE; #define ASYMSG struct _ASYMSG #define ASYHAN struct _ASYHAN ASYMSG { MSG msg; void (*func)(); long arg1; long arg2; long arg3; }; ASYHAN { PORT *rport; /* Reply Port */ PORT *port; /* Send Port */ long acount; /* Messages Sent */ long ccount; /* Messages Replied*/ long a4,a5; /* A4 and A5 */ }; extern TASK *CreateTask(); extern TASK *FindTask(); extern PORT *CreatePort(); extern void *AllocMem(); extern void *GetMsg(); extern void asyhandler(); extern void nop(); ASYHAN * NewAsyncOp() { register TASK *task; register TASK *mytask = FindTask(NULL); register ASYHAN *as = AllocMem(sizeof(ASYHAN), MEMF_CLEAR|MEMF_PUBLIC); ASYMSG StartupMsg; as->rport = CreatePort(NULL, 0); PutA4A5(&as->a4); task = CreateTask("async.task", mytask->tc_Node.ln_Pri + 1, asyhandler, 4096); task->tc_UserData = (APTR)as; Signal(task, SIGBREAKF_CTRL_F); Wait(1 << as->rport->mp_SigBit); return(as); } StartAsyncOp(as, func, arg1, arg2, arg3) register ASYHAN *as; void (*func)(); { register ASYMSG *am = GetMsg(as->rport); /* Free Msg List */ if (!am) { am = AllocMem(sizeof(ASYMSG), MEMF_PUBLIC|MEMF_CLEAR); am->msg.mn_ReplyPort = as->rport; } am->func = func; am->arg1 = arg1; am->arg2 = arg2; am->arg3 = arg3; ++as->acount; PutMsg(as->port, am); } CheckAsyncOp(as, n) register ASYHAN *as; unsigned long n; { if (n > as->acount) n = as->acount; return(n <= as->ccount); } /* * acount = #messages sent * ccount = #messages replied */ WaitAsyncOp(as, n) register ASYHAN *as; unsigned long n; { if (n > as->acount) n = as->acount; while (n > as->ccount) Wait(1 << as->rport->mp_SigBit); Forbid(); as->ccount -= n; Permit(); as->acount -= n; } CloseAsyncOp(as) register ASYHAN *as; { ASYMSG EndMsg; ASYMSG *am; WaitAsyncOp(as, -1); /* Wait for all operations to complete */ while (am = GetMsg(as->rport)) /* Free any messages */ FreeMem(am, sizeof(ASYMSG)); EndMsg.func = NULL; EndMsg.msg.mn_ReplyPort = as->rport; PutMsg(as->port, &EndMsg); WaitPort(as->rport); GetMsg(as->rport); DeletePort(as->rport); FreeMem(as, sizeof(*as)); } static void asyhandler() { register ASYHAN *as; register ASYMSG *am; Wait(SIGBREAKF_CTRL_F); as = (ASYHAN *)FindTask(NULL)->tc_UserData; as->port = CreatePort(NULL, 0); Signal(as->rport->mp_SigTask, 1 << as->rport->mp_SigBit); for (;;) { WaitPort(as->port); am = GetMsg(as->port); if (!am->func) break; CallAMFunc(&as->a4, &am->func); ++as->ccount; ReplyMsg(am); } DeletePort(as->port); as->port = NULL; Forbid(); ReplyMsg(am); } #asm ; ; load the lw array ptr with a4 & a5 _PutA4A5: move.l 4(sp),A0 move.l A4,(A0)+ move.l A5,(A0)+ rts _CallAMFunc: move.l 4(sp),A0 ; &a4,a5 move.l 8(sp),A1 ; &func,arg1,arg2,arg3 movem.l D2/D3/A4/A5/A6,-(sp) move.l (A0)+,A4 move.l (A0)+,A5 move.l 12(A1),-(sp) move.l 8(A1),-(sp) move.l 4(A1),-(sp) move.l (A1),A1 jsr (A1) add.w #12,sp movem.l (sp)+,D2/D3/A4/A5/A6 rts #endasm \Rogue\Monster\ else echo "will not over write ./suplib/asyncop.c" fi if [ `wc -c ./suplib/asyncop.c | awk '{printf $1}'` -ne 3495 ] then echo `wc -c ./suplib/asyncop.c | awk '{print "Got " $1 ", Expected " 3495}'` fi if `test ! -s ./suplib/enviroment.c` then echo "writing ./suplib/enviroment.c" cat > ./suplib/enviroment.c << '\Rogue\Monster\' /* * ENVIROMENT.C * * str = GetDEnv(name) * bool= SetDEnv(name, str) (0=failure, 1=success) * * If the enviroment variable 'name' exists, malloc and return a copy * of it. The user program must free() it (or allow the standard C * exit routine to free() it). */ extern void *AllocMem(); extern void *malloc(); char * GetDEnv(name) char *name; { short nlen = strlen(name) + 5; char *ptr = AllocMem(nlen, MEMF_PUBLIC); char *res = NULL; long fh; long len; if (ptr) { strcpy(ptr, "ENV:"); strcat(ptr, name); if (fh = Open(ptr, 1005)) { len = (Seek(fh, 0L, 1), Seek(fh, 0L, 0)); if (len >= 0 && (res = malloc(len+1))) { Seek(fh, 0L, -1); if (Read(fh, res, len) != len) len = 0; res[len] = 0; } Close(fh); } FreeMem(ptr, nlen); } return(res); } SetDEnv(name, str) char *name, *str; { short nlen = strlen(name) + 5; short slen = strlen(str); short res = 0; char *ptr = AllocMem(nlen, MEMF_PUBLIC); long fh; if (ptr) { strcpy(ptr, "ENV:"); strcat(ptr, name); if (fh = Open(ptr, 1006)) { if (Write(fh, str, slen) == slen) res = 1; Close(fh); } FreeMem(ptr, nlen); } return(res); } \Rogue\Monster\ else echo "will not over write ./suplib/enviroment.c" fi if [ `wc -c ./suplib/enviroment.c | awk '{printf $1}'` -ne 1213 ] then echo `wc -c ./suplib/enviroment.c | awk '{print "Got " $1 ", Expected " 1213}'` fi if `test ! -s ./suplib/typedefs.h` then echo "writing ./suplib/typedefs.h" cat > ./suplib/typedefs.h << '\Rogue\Monster\' /* * TYPEDEFS.H */ typedef unsigned char ubyte; typedef unsigned short uword; typedef unsigned long ulong; typedef struct MsgPort PORT; typedef struct Message MSG; typedef struct List LIST; typedef struct Node NODE; typedef struct MinList MLIST; typedef struct MinNode MNODE; typedef struct Device DEV; typedef struct Library LIB; typedef struct ExecBase EXECBASE; #define WINSTD (WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE) typedef struct BoolInfo BOOLINFO; typedef struct Border BORDER; typedef struct Gadget GADGET; typedef struct Image IMAGE; typedef struct IntuiMessage IMESS; typedef struct IntuiText ITEXT; typedef struct Menu MENU; typedef struct MenuItem ITEM; typedef struct NewScreen NS; typedef struct NewWindow NW; typedef struct Preferences PREFS; typedef struct PropInfo PROPINFO; typedef struct Remember REMEMBER; typedef struct Requester REQUESTER; typedef struct Screen SCR; typedef struct StringInfo STRINGINFO; typedef struct Window WIN; typedef struct GListEnv GLISTENV; typedef struct GadgetInfo GADGETINFO; typedef struct IBox IBOX; typedef struct IntuitionBase IBASE; typedef struct PenPair PENPAIR; typedef struct Point POINT; typedef struct IOAudio IOAUD; typedef struct BootBlock BOOTBLOCK; typedef struct IOClipReq IOCLIPREQ; typedef struct ClipboardUnitPartial CLIPUNIT; typedef struct SatisfyMsg SATISFYMSG; typedef struct ConUnit CONUNIT; typedef struct IOStdReq IOCON; typedef struct InputEvent IE; typedef struct TextAttr TA; typedef struct TextFont FONT; typedef struct Layer LAYER; typedef struct Layer_Info LAYERINFO; typedef struct Region REGION; typedef struct ClipRect CLIPRECT; typedef struct BitMap BM; typedef struct RastPort RP; typedef struct View VIEW; typedef struct ViewPort VP; typedef struct GfxBase GFXBASE; typedef struct Process PROC; typedef struct Task TASK; typedef struct FileInfoBlock FIB; typedef struct FileLock LOCK; typedef struct timeval TV; typedef struct timerequest IOTIM; typedef struct PrinterData PD; typedef struct PrinterExtendedData PED; /* * Intuition */ extern WIN *OpenWindow(); extern SCR *OpenScreen(); extern void *AllocRemember(); extern void *ItemAddress(); extern PREFS *GetPrefs(); extern PREFS *GetDefPrefs(); extern VIEW *ViewAddress(); extern VP *ViewPortAddress(); /* * Graphics */ extern void *AllocRaster(); /* * Exec / Exec-Support */ extern void *GetMsg(); extern void *GetHead(), *GetTail(), *GetSucc(), *GetPred(); extern void *GetHeadOff(), *GetTailOff(), *GetSuccOff(), *GetPredOff(); extern void *AllocMem(); extern PORT *FindPort(); extern TASK *CreateTask(); extern PROC *CreateProc(); extern void *FindTask(); /* task or proc */ extern void *malloc(); \Rogue\Monster\ else echo "will not over write ./suplib/typedefs.h" fi if [ `wc -c ./suplib/typedefs.h | awk '{printf $1}'` -ne 2748 ] then echo `wc -c ./suplib/typedefs.h | awk '{print "Got " $1 ", Expected " 2748}'` fi if `test ! -s ./suplib/xmisc.h` then echo "writing ./suplib/xmisc.h" cat > ./suplib/xmisc.h << '\Rogue\Monster\' /* * XMISC.H */ #ifndef MYLIB_XMISC_H #define MYLIB_XMISC_H #define GRAPHICS_LIB 0x0001L #define INTUITION_LIB 0x0002L #define EXPANSION_LIB 0x0004L #define DISKFONT_LIB 0x0008L #define TRANSLATOR_LIB 0x0010L #define ICON_LIB 0x0020L #define MATH_LIB 0x0040L #define MATHTRANS_LIB 0x0080L #define MATHIEEEDOUBBAS_LIB 0x0100L #define MATHIEEESINGBAS_LIB 0x0200L #define LAYERS_LIB 0x0400L #define CLIST_LIB 0x0800L #define POTGO_LIB 0x1000L #define TIMER_LIB 0x2000L struct OLI { char *name; long *var; }; typedef struct _XLIST { struct _XLIST *next, **prev; } XLIST; #endif \Rogue\Monster\ else echo "will not over write ./suplib/xmisc.h" fi if [ `wc -c ./suplib/xmisc.h | awk '{printf $1}'` -ne 644 ] then echo `wc -c ./suplib/xmisc.h | awk '{print "Got " $1 ", Expected " 644}'` fi if `test ! -s ./suplib/dio.h` then echo "writing ./suplib/dio.h" cat > ./suplib/dio.h << '\Rogue\Monster\' /* * DIO.H * * (C)Copyright 1987 Matthew Dillon, All Rights Reserved * Freely distributable. Donations welcome, I guess. * * Matthew Dillon * 891 Regal Rd. * Berkeley, Ca. 94708 * */ #ifndef MYLIB_DIO_H #define MYLIB_DIO_H #include <exec/types.h> #include <exec/io.h> #include <exec/memory.h> #include <exec/ports.h> #include <devices/timer.h> typedef struct IORequest IOR; typedef struct IOStdReq STD; typedef struct MsgPort PORT; /* * 'to' is in microsections. The IO request structure * pointer is optional to dio_open(). If NULL, dio_open() * initializes it's own IO request (to mostly zero). You have * to provide an IO request structure, for instance, if openning * a console device since the window pointer must be passed to * OpenDevice(). * * each DFD descriptor has it's own signal. * * dio_isdone() returns 1 if the channel is clear, 0 otherwise. */ extern long dio_open(); /* dfd = dio_open(devname,unit,flags,req)*/ extern long dio_dup(); /* newdfd = dio_dup(dfd) */ extern STD *dio_ctl(); /* req = dio_ctl(dfd,com,buf,len) */ extern STD *dio_ctl_to(); /* req = dio_ctl_to(dfd,com,buf,len,to) */ extern STD *dio_wait(); /* req = dio_wait(dfd) */ extern STD *dio_abort(); /* req = dio_abort(dfd) */ extern STD *dio_isdone(); /* req = dio_isdone(dfd) */ extern int dio_signal(); /* signm= dio_signal(dfd) */ extern void dio_close(); /* dio_close(dfd) */ extern void dio_cloesgroup(); /* dio_closegroup(dfd) */ extern void dio_cact(); /* dio_cact(dfd,bool) */ /* * dio_simple() and related macros return the !io_Error field. That * is, 0=ERROR, 1=OK * * dio_actual() returns the io_Actual field. * * NOTE: the io_Actual field may not be set by the device if an * error condition exists. To make the io_ctl() and io_ctl_to() * call automatically clear the io_Actual field before doing the * io operation, use the DIO_CACT() call. The reason this isn't * done automatically by default is that some devices require * parameters to be passed in the io_Actual field (like the * timer.device). * * Remember, Asyncronous IO is done by sending -com instead of com. * * CALL Syncronous IO Asyncronous IO * * dio_simple(dfd,com) 0=ERROR, 1=OK undefined * dio_actual(dfd,com) io_Actual undefined * dio_reset(dfd) 0=ERROR, 1=OK n/a * dio_update(dfd) 0=ERROR, 1=OK n/a * dio_clear(dfd) 0=ERROR, 1=OK n/a * dio_stop(dfd) 0=ERROR, 1=OK n/a * dio_start(dfd) 0=ERROR, 1=OK n/a * dio_flush(dfd) 0=ERROR, 1=OK n/a * dio_getreq(dfd) returns a ptr to the IO * request structure * NOTE: If you use the following, you probably want to have the * device library automatically clear the io_Actual field before * sending the request so you get 0 if an error occurs. That * is: dio_cact(dfd,1); * * * dio_read(dfd,buf,len) returns actual bytes read * dio_write(dfd,buf,len) returns actual bytes written * * The timeout argument for dio_readto() and dio_writeto() * is in MICROSECONDS, up to 2^31uS. * * dio_readto(dfd,buf,len,to) returns actual bytes read * dio_writeto(dfd,buf,len,to) returns actual bytes written * * The asyncronous dio_reada() and dio_writea() do not * return anything. * * dio_reada(dfd,buf,len) begin asyncronous read * dio_writea(dfd,buf,len) begin asyncronous write */ #define dio_mask(dfd) (1 << dio_signal(dfd)) #define dio_simple(dfd,com) (!dio_ctl(dfd,com,0,0)->io_Error) #define dio_actual(dfd,com) ( dio_ctl(dfd,com,0,0)->io_Actual) #define dio_reset(dfd) dio_simple(dfd,CMD_RESET) #define dio_update(dfd) dio_simple(dfd,CMD_UPDATE) #define dio_clear(dfd) dio_simple(dfd,CMD_CLEAR) #define dio_stop(dfd) dio_simple(dfd,CMD_STOP) #define dio_start(dfd) dio_simple(dfd,CMD_START) #define dio_flush(dfd) dio_simple(dfd,CMD_FLUSH) #define dio_getreq(dfd) dio_ctl(dfd,0,0,0) #define dio_read(dfd,buf,len) (dio_ctl(dfd,CMD_READ,buf,len)->io_Actual) #define dio_write(dfd,buf,len) (dio_ctl(dfd,CMD_WRITE,buf,len)->io_Actual) #define dio_readto(dfd,buf,len,to) (dio_ctl_to(dfd,CMD_READ,buf,len,to)->io_Actual) #define dio_writeto(dfd,buf,len,to) (dio_ctl_to(dfd,CMD_WRITE,buf,len,to)->io_Actual) #define dio_reada(dfd,buf,len) ((void)dio_ctl(dfd,-CMD_READ,buf,len)) #define dio_writea(dfd,buf,len) ((void)dio_ctl(dfd,-CMD_WRITE,buf,len)) #endif \Rogue\Monster\ else echo "will not over write ./suplib/dio.h" fi if [ `wc -c ./suplib/dio.h | awk '{printf $1}'` -ne 4438 ] then echo `wc -c ./suplib/dio.h | awk '{print "Got " $1 ", Expected " 4438}'` fi if `test ! -s ./suplib/conwin.c` then echo "writing ./suplib/conwin.c" cat > ./suplib/conwin.c << '\Rogue\Monster\' /* * CONWIN.C * * Win = GetConWindow() * * Returns console window associated with the current task or NULL if * no console task associated. * * The intuition.library and graphics.library must be openned. */ #include <exec/types.h> #include <exec/memory.h> #include <intuition/intuition.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #define BTOC(bptr) ((long)(bptr) << 2) #define CTOB(cptr) ((long)(cptr) >> 2) typedef struct Task TASK; typedef struct Process PROC; typedef struct StandardPacket STDPKT; typedef struct MsgPort MSGPORT; typedef struct Window WIN; typedef struct InfoData INFODATA; extern TASK *FindTask(); extern void *AllocMem(); /* * GETCONWINDOW() * * Return the window used by the console of the current process. We can * use our process's message port as the reply port since it is a * synchronous packet (we wait for the result to come back). WARNING: * This routine does not check if the 'console' of the current process * is really a console device. * * The DISK_INFO packet is sent to the console device. Although this * packet is normally used to retrieve disk information from disk * devices, the console device recognizes the packet and places a pointer * to the window in id_VolumeNode of the infodata structure. A pointer * to the console unit is also placed in id_InUse of the infodata structure. */ WIN * GetConWindow() { PROC *proc; STDPKT *packet; INFODATA *infodata; long result; WIN *win; proc = (PROC *)FindTask(NULL); if (!proc->pr_ConsoleTask) return(NULL); /* * NOTE: Since DOS requires the packet and infodata structures to * be longword aligned, we cannot declare them globally or on the * stack (word aligned). AllocMem() always returns longword * aligned pointers. */ packet = (STDPKT *)AllocMem(sizeof(STDPKT) , MEMF_CLEAR|MEMF_PUBLIC); infodata = (INFODATA *)AllocMem(sizeof(INFODATA), MEMF_CLEAR|MEMF_PUBLIC); packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &packet->sp_Msg; packet->sp_Pkt.dp_Port = &proc->pr_MsgPort; packet->sp_Pkt.dp_Type = ACTION_DISK_INFO; packet->sp_Pkt.dp_Arg1 = CTOB(infodata); PutMsg(proc->pr_ConsoleTask, packet); WaitPort(&proc->pr_MsgPort); GetMsg(&proc->pr_MsgPort); result = packet->sp_Pkt.dp_Res1; win = (WIN *)infodata->id_VolumeNode; /* note: id_InUse holds a pointer to the console unit also */ FreeMem(packet , sizeof(STDPKT)); FreeMem(infodata, sizeof(INFODATA)); if (!result) return(NULL); return(win); } \Rogue\Monster\ else echo "will not over write ./suplib/conwin.c" fi if [ `wc -c ./suplib/conwin.c | awk '{printf $1}'` -ne 2672 ] then echo `wc -c ./suplib/conwin.c | awk '{print "Got " $1 ", Expected " 2672}'` fi echo "Finished archive 1 of 2" # if you want to concatenate archives, remove anything after this line exit -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.