[net.micro.amiga] MY.LIB V2.00 SHAR 2 of 2

dillon.UUCP@ucbvax.UUCP (09/24/86)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	breakup.uue
#	memory.b
#	misc.b
#	string.b
#	xstdio.b
# This archive created: Tue Sep 23 22:10:20 1986
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'breakup.uue'
then
	echo shar: "will not over-write existing file 'breakup.uue'"
else
cat << \SHAR_EOF > 'breakup.uue'
begin 600 breakup
M```#\P`````````,``````````L```!Q````;@```=T````C`````@```!0`
M```(```````````````I````#`````````/I````<2//````'"/`````)"/(
M````*$*Y````("QY````!"/.````!)/)3J[^VBA`2JP`K&<``*AA``%L(&P`
MK-'(T<@@:``0T<C1R$CG(#!%^0```*Q'^0```"QT`7``$!@FRF`"%-A1R/_\
M0AH@.0```"0@>0```"@2&%.`;QX,`0`@;_12@B;*8`H2&%.`#`$`(&\$%,%@
M\D(:8-Q"&D*;(`),WPP$2'D````L+P!.N0```&@CP````!!.N0```'@CP```
M`!0CP````!A.N0````!P`"YY````'$YU80``QF$``+`CP````"!"IR\`)$`@
M*@`D9Q`L>0````@@0"(H``!.KO^"(BH`(&<H)#P```/M3J[_XB/`````$"/`
M````%"/`````&&<*Y8@@0"EH``@`I$ZY`````'``8`0@+P`$+GD````<+P`L
M>0````0@.0````AG`B)`3J[^8DJY````(&<.3J[_?")Y````($ZN_H8@'TYU
M2.<!!BX\``.`!RQX``1.KO^43-]@@'!D8+!![`!<3J[^@$'L`%Q.KOZ,3G5"
MN0````A#^0```:P@/````!Y.KOW8(\`````(9[9.=0`````#[````!H````!
M```!N@```:H```&D```!:@```5X```%0```!0@```2(```$<```!%@```/8`
M``#D````U````,8```#`````M````*8```!R````;````%0```!.````(```
M`!0````.````"`````(````"`````@```,P```$T`````0````D```"Z````
M`0````D```"N`````````_(```/J````;@`!````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````9&]S+FQI8G)A<GD````#\@```^D```'=3E;_^$CG`P!A``(.#*X````!
M``AF'$AY`````$ZY```'$%B/2'D````83KD```<06(]^`;ZN``AL``">(`<B
M!^6!(&X`#-'!(E`2$0P!`"UF#A*Y````!!/`````!&!8(`<B!^6!(&X`#-'!
M+SP``"``2'D````W+Q!A``',3^\`#"P`2H9G%"\&+RX`#&%04(\O!F$``M)8
MCV`<(`<B!^6!(&X`#-'!+Q!(>0```#E.N0````!0CTJY`````&<,+SD`````
M80`"H%B/0KD`````4H=@`/]>3-\`P$Y>3G5.5O[V+SP```$`2&[_`"\N``QA
M``.`3^\`#$J`9P`!%G`)+P!(>0```$Q(;O\`80`%4D_O``Q*@&8``-Q![O\)
M+4C^_"!N_OP0$`P``"!F!E*N_OQ@[BUN_OS^^"!N_OA*$&<.$!`,```@9P92
MKO[X8.H@;O[X0A`O.0````!A``((6(]"N0````!*.0````1G1AUY````!/[W
M2B[^]V=6<``0+O[WY8`@;@`(T<`B4%2)+R[^_"\)80`$=%"/2H!G%G``$"[^
M]^6`(&X`"-'`(E`=4?[W8,(O/```(`!(>0```%8O+O[\80``?D_O``PCP```
M``!*N0````!G`/\&+R[^_$AY````6$ZY`````%"/8`#^\$JY`````&<`_N9(
M;O\`+SD`````80`"+E"/8`#^TDY>3G5.5O_\<`!3@"U`__Q2@&<<2'D```!B
M3KD```<06(\O/```PU!.N0```3Q8CTY>3G5.5O_T2.<#'"IN``@H;@`,?``,
MK@````$`$&P&<`$M0``0+SP``0``<!XO`$ZY`````%"/)D"W_`````!G``#4
M$!0,``!R9A8N/````^T0+``!#```*V8&+CP```/M$!0,``!W9C@N/````^X0
M+``!#```*V8H+SP```/M+PU.N0````!0CRP`2H9G$G`!+P!"IR\&3KD```"(
M3^\`#$J&9@XO!R\-3KD`````4(\L`$J&9T8FAB`N`!`G0``,0J<O`$ZY````
M`%"/)T``&DJ`9QQP`"\`+P`O!DZY````B$_O``PG0``4)T``$&`D+P9.N0``
M`!Q8CTYQ<!XO`"\+3KD````84(]P`$S?.,!.7DYU(`LB"R`!3-\XP$Y>3G5.
M5@``2.<`!"IN``B[_`````!G,"\-80`!_EB/+Q5.N0```!Q8CR\M``PO+0`:
M3KD````84(]P'B\`+PU.N0```!A0CTS?(`!.7DYU3E;__$CG`PPJ;@`(*&X`
M#"XN`!`@+0`,D*T`!+"';0(@!RP`(&T`&M'M``0O!B\(+PQA``+<3^\`#)Z&
MV<;=K0`4(`8B+0`$T($K0``$(BT`"+*`;`0K0``($"T`&`````$;0``82H=G
M%"\-80`!7%B/<``K0``(*T``!&"63-\PP$Y>3G5.5@``+RX`#&$``:A8CR\`
M+RX`#"\N``AA`/]@3^\`#'`!+P!(>0```(8O+@`(80#_2D_O``Q.7DYU3E;_
M_$CG`PPJ;@`(*&X`#"XN`!!3AWP`O(=L1B`M``2PK0`(9A8O#6%*6(]*@&8,
M0A1P`$S?,,!.7DYU($S1QB`M``12K0`$(FT`&M/`$!$0@%*M`!00$`P```IG
M!%*&8+8@3-'&0A`@!E*`3-\PP$Y>3G5.5O_X2.<#!"IN``@L%2\-80``A%B/
M<``K0``(*T``!"`M`!`B+0`4LH!G$I*`0J<O`2\&3KD```"(3^\`#"\M``PO
M+0`:+P9.N0```#!/[P`,+@!*AVXD("T`%"M``!!R_R\!+P`O!DZY````B$_O
M``QP`$S?(,!.7DYU(`<K0``((BT`%-*`*T$`$'`!3-\@P$Y>3G5.5O_\2.<!
M!"IN``@0+0`8"````&=0("T`%)"M``0N`"`M`!"PAV<6(`>0K0`00J<O`"\5
M3KD```"(3^\`#"\M``0O+0`:+Q5.N0```$Q/[P`,(@?2@"M!`!`0+0`8`@#_
M_AM``!A,WR"`3EY.=4Y6__Q(YP`$*FX`"$H59P12C6#X(`V0K@`(3-\@`$Y>
M3G5.5@``2.<`#"IN``@H;@`,2A5G+DH49RH0%1(4L`%D"G#_3-\P`$Y>3G40
M%1(4L`%C"G`!3-\P`$Y>3G52C5*,8,X0%1(4L`%FSG``3-\P`$Y>3G5.5@``
M2.<!#"IN``@H;@`,+BX`$$J'9S1*%6<P2A1G+%.'$!42%+`!9`IP_TS?,(!.
M7DYU$!42%+`!8PIP`4S?,(!.7DYU4HU2C&#(2H=G"!`5$A2P`6;*<`!,WS"`
M3EY.=4Y6__Q(YP,,*FX`""AN``PN+@`0N\QD%BP'4X8@!DJ`:R`@3-'&(DW3
MQA"18.Q\`+R';`X@3-'&(DW3QA"14H9@[DS?,,!.7DYU``!.5O_X2.<#`$ZY
M````>"X`+RX`"$ZY```%[%B/+``O!B\N``@O!TZY````3$_O``RPAF8D<`$O
M`$AY````B"\'3KD```!,3^\`#$J`9PIP`4S?`,!.7DYU<`!,WP#`3EY.=0``
M```#[`````D````#```$8````BH```'F```!P````08```"L````=````"8`
M```8````#0````0```(&```!^````=@```'2```!=````6P```%F```!6@``
M`,X```#"````N@```%H```!4`````0````,```=*`````P````(````>````
M+````C`````"````!@```+(```'L`````0````````(^`````@````H```)V
M```##`````(````)```"R````O`````%````"0```MX```,D```%'@``!5(`
M``6T`````@````D```,Z```#B`````,````*```#2@```Y@```.F`````0``
M``D```4R`````P````D```7(```'.```!U(````!````"0``!QH````!````
M`@``!R8````````#\@```^H````C=C$N,#`@8GD@36%T=&AE=R!$:6QL;VX`
M8G)E86MU<"!;+6YS96-T:6]N("XN+ET@9FEL92YB`'(`0V]U;&0@;F]T(&]P
M96X@)7,*`"\J0E)%04M54`!W`&9I;&4Z("5S"@!-55-4($)%($-/35!)3$5$
M(%=)5$@@,S(M8FET($E.5"=S(0`*``H```````/R```#ZP````(```/R```#
MZ0```!1(YP`Z*&\`%"!O`!@B;P`<1?H`.D_O_W0F3RQY````!$ZN_?9P_TH;
M5\C__$:`9Q(O`$AO``1(5$ZY````3$_O``Q/[P",3-]<`$YU%L!.=0```^P`
M```!````"0```#H````````#\@```^D````(+P(D+P`(2&\`#"\"+SD````4
M3KD`````3^\`#"0?3G4```/L`````0````4````4`````0````$````.````
M`````_(```/J`````````_(```/I`````````_(```/I````*4CG(`(L>0``
M``A,[P`&``Q.KO_B3-]`!$YU```O#BQY````""(O``A.KO_<+%].=4CG,`(L
M>0````A,[P`.`!!.KO_63-]`#$YU``!(YS`"+'D````(3.\`#@`03J[_T$S?
M0`Q.=0``+PXL>0````A.KO_*+%].=2\.+'D````(3J[_Q"Q?3G5(YS`"+'D`
M```(3.\`#@`03J[_ODS?0`Q.=0`````#[`````<````!````!@```"`````V
M````4@```&P```!\````C@````````/R```#Z0````PO#BQY````!$SO``,`
M"$ZN_SHL7TYU```O#BQY````!")O``@@+P`,3J[_+BQ?3G4```/L`````@``
>``$````$````'`````````/R```#Z@````````/R
`
end
SHAR_EOF
fi
if test -f 'memory.b'
then
	echo shar: "will not over-write existing file 'memory.b'"
else
cat << \SHAR_EOF > 'memory.b'

/*
 * MEMORY.B    V2.00
 *
 *    Memory routines.  malloc() is memory hog since it
 *    simply call AllocMem().
 *
 *    malloc(bytes)        -allocate
 *    free(ptr)            -free a single allocation
 *    free_memory()        -free all allocations (must be done before exit)
 *    bzero(s, n)          -zero a memory area.
 *    bset (s, n, v)       -set a memory area.
 *    bmov (s, d, n)       -move source to dest.
 *
 */

/*BREAKUP src/xalloc.h  */

typedef struct _ALLC {
   struct _ALLC *next;
   struct _ALLC **prev;
   long         bytes;
   char         buf[4];
} ALLC;

#define HSIZE  12

extern ALLC *Allc_base;
extern char *malloc();


/*BREAKUP src/malloc.c        */

#include "xalloc.h"

char *
malloc(bytes)
{
   register ALLC *a;

   a = (ALLC *)AllocMem(bytes + HSIZE, 0);
   if (Allc_base)
      Allc_base->prev = &a->next;
   a->next = Allc_base;
   a->prev = &Allc_base;
   a->bytes = bytes + HSIZE;
   Allc_base = a;
   return (a->buf);
}



/*BREAKUP src/free.c          */

#include "xalloc.h"

free(ptr)
char *ptr;
{
   register ALLC *a;

   if (ptr) {
      a = (ALLC *)(ptr - HSIZE);
      *a->prev = a->next;
      if (a->next)
         a->next->prev = a->prev;
      FreeMem (a, a->bytes);
   }
}


/*BREAKUP src/free_memory.c   */

#include "xalloc.h"

ALLC *Allc_base;

free_memory()
{
   register ALLC *next;

   while(Allc_base) {
      next = Allc_base->next;
      FreeMem (Allc_base, Allc_base->bytes);
      Allc_base = next;
   }
}


/*BREAKUP src/bzero.asm       */

;BZERO.ASM
;     written in assembly for speed.  Could have written one to write a
;     long at a time, but would be lengthy.

            xdef  _bzero

_bzero
            move.l   4(A7),A0    ;pointer
            move.l   8(A7),D0    ;# bytes
            beq      lend        ;zero 0 bytes
loop2       clr.b    (A0)+
            subq.l   #1,D0
            bne      loop2
lend        rts



/*BREAKUP src/bmov.asm        */

;BMOV.ASM
;     written in assembly for speed.  Could have written one to write a
;     long at a time, but would be lengthy.


            xdef  _bmov

_bmov
            move.l   4(A7),A0           ;source
            move.l   8(A7),A1           ;destination
            move.l   12(A7),D0          ;#bytes
            beq      lend               ;no bytes to copy
            cmp.l    A0,A1              ;A1 ? A0
            beq      lend
            ble      destlessrc
                                        ;dest > src, backwards copy required
            add.l    D0,A0
            add.l    D0,A1
loop1       move.b   -(A0),-(A1)
            subq.l   #1,D0
            bne      loop1
            rts

destlessrc                              ;dest < src, forwards copy required
loop2       move.b   (A0)+,(A1)+
            subq.l   #1,D0
            bne      loop2
lend        rts


/*BREAKUP src/bset.asm       */

;BSET.ASM
;     written in assembly for speed.  Could have written one to write a
;     long at a time, but would be lengthy.

            xdef  _bset

_bset
            move.l   4(A7),A0    ;pointer
            move.l   12(A7),D1   ;what to set
            move.l   8(A7),D0    ;# bytes
            beq      lend        ;zero 0 bytes
loop2       move.b   D1,(A0)+
            subq.l   #1,D0
            bne      loop2
lend        rts


SHAR_EOF
fi
if test -f 'misc.b'
then
	echo shar: "will not over-write existing file 'misc.b'"
else
cat << \SHAR_EOF > 'misc.b'

/*
 * MISC.B      V2.00
 *
 * xmisc.h
 *
 *           atoi(str)
 *
 *                simple string to integer routine
 *
 *    bool = openlibs(libs_mask)
 *
 *                #include <dillon/xmisc.h>
 *                open multiple libraries.  See xmisc.h  TRUE is returned
 *                if all libraries could be openned, FALSE if any of them
 *                could not be openned.  If FALSE is returned, all
 *                libraries that had been openned with openlibs() will be
 *                closed as if a closelibs(-1) had been called.
 *
 *           closelibs(libs_mask)
 *
 *                close libraries that had been openned with openlibs.
 *                Usually one passes a -1 to this routine to close all
 *                openned libraries.
 *
 *                NOTE: if you use openlibs and closelibs, all xxBase
 *                variables will be declared for you. You should not use
 *                the standard OpenLibrary() call if you use openlibs()
 *                (unless you are openning a library which doesn't exist in
 *                openlibs)
 *
 *                please inform me if I forgot any libraries.
 *
 *    bool = wildcmp(wild, name)
 *
 *                compare two strings.  The first contains '*' and '?'
 *                wildcards.  This routine will return TRUE (1) or FALSE (0)
 *                if the wildcard name matches the normal name.
 *
 *           check32()
 *
 *                call before anything else.  This routine will print an
 *                error message and exit() if the program was compiled with
 *                16 bit ints.
 *
 *           io_open()
 *           io_close()
 *
 *                IO device support.  See the io_open() and io_close()
 *                routines below.
 *
 */

/*BREAKUP src/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


/*BREAKUP src/atoi.c       */

atoi(str)
register char *str;
{
   register long i = 0;
   register long neg = 0;

   while (*str == ' ')
      ++str;
   if (*str == '-') {
      ++str;
      neg = 1;
   }
   while (*str >= '0' && *str <= '9')
      i = (i << 1) + (i << 3) + *str++ - '0';
   return ((int)((neg)?-i:i));
}

/*BREAKUP src/openlibs.c   */

#include "xmisc.h"

long GfxBase;
long IntuitionBase;
long ExpansionBase;
long DiskfontBase;
long TranslatorBase;
long IconBase;
long MathBase;
long MathTransBase;
long MathIeeeDoubBasBase;
long MathIeeeSingBasBase;
long LayersBase;
long ClistBase;
long PotgoBase;
long TimerBase;
long xfiller15;
long xfiller16;

openlibs(mask)
unsigned short mask;
{
   static char *strarray[] = {
      "graphics",
      "intuition",
      "expansion",
      "diskfont",
      "translator",
      "icon",
      "mathffp",
      "mathtrans",
      "mathieeedoubbas",
      "mathieeesingbas",
      "layers",
      "clist",
      "potgo",
      "timer",
      "x15",
      "x16"
   };
   register long *base = &GfxBase;
   register char **str = strarray;
   char buf[64];

   for (; mask; mask >>= 1, ++base, ++str) {
      if (mask & 1) {
         strcpy(buf, *str);
         strcat(buf, ".library");
         if ((*base = OpenLibrary(buf, 0)) == 0)
            goto fail;
      }
   }
   return (1);
fail:
   closelibs(-1);
   return (0);
}

/*BREAKUP src/closelibs.c  */

#include "xmisc.h"

extern long GfxBase;

closelibs(mask)
unsigned short mask;
{
   register long *base = &GfxBase;

   for (;mask; mask >>= 1, ++base) {
      if ((mask & 1) && *base) {
         CloseLibrary(*base);
         *base = 0;
      }
   }
}

/*BREAKUP src/wildcmp.c    */


/*
 * Compare a wild card name with a normal name
 */

#define MAXB   8

wildcmp(wild, name)
char *wild, *name;
{
   register char *w = wild;
   register char *n = name;
   char *back[MAXB][2];
   int  bi = 0;

   while (*n || *w) {
      switch (*w) {
      case '*':
         if (bi == MAXB) {
            puts ("Too many levels of '*'");
            return (0);
         }
         back[bi][0] = w;
         back[bi][1] = n;
         ++bi;
         ++w;
         continue;
goback:
         --bi;
         while (bi >= 0 && *back[bi][1] == '\0')
            --bi;
         if (bi < 0)
            return (0);
         w = back[bi][0] + 1;
         n = ++back[bi][1];
         ++bi;
         continue;
      case '?':
         if (!*n) {
            if (bi)
               goto goback;
            return (0);
         }
         break;
      default:
         if (*n != *w) {
            if (bi)
               goto goback;
            return (0);
         }
         break;
      }
      if (*n)  ++n;
      if (*w)  ++w;
   }
   return (1);
}


/*BREAKUP src/check32.c */

check32()
{
   unsigned int i;

   i = 0; --i;
   if (i != 0xFFFFFFFF) {
      puts ("MUST BE COMPILED WITH 32-bit INT's!");
      exit (50000);                                     /* no joke */
   }
}


/*BREAKUP src/io.c      */

/*
 * IO.C           (must be compiled 32-bit ints)
 *
 * I/O support for devices.
 *  io_open()        - Generalized OpenDevice() which does everything for
 *                     you.
 *
 *  io_close()       - Generalized CloseDevice().  Should only be used
 *                     with io_open()'d devices.
 *
 *  long
 *  io_open(device_name, unit, flags, &rreq, &wwreq, req_size, spec1, spec2)
 *
 *    char *device_name          -the device name (ex: "serial.device")
 *    int   unit                 -unit #
 *    int   flags                -OpenDevice flags
 *    struct IOxxxxxx *rreq      -address of pointer (will be filled in)
 *    struct IOxxxxxx *wreq      -address of pointer (will be filled in)
 *    int   req_size             -size of above structures
 *    long  spec1,spec2          -special arguments for preinitialization
 *                                 (depends on the device your openning)
 *
 *    EXAMPLE:
 *    ----------------------
 *    typedef struct IOExtSer SIO;
 *
 *    #define SERFLAGS (SERF_XDISABLED | SERF_SHARED)
 *    SIO *srr, *swr;
 *    long mask;
 *
 *    mask = io_open("serial.device",0,0,&srr,&swr,sizeof(SIO),SERFLAGS,0);
 *                   ...
 *    io_close(srr, swr, sizeof(SIO));
 *
 *    ----------------------
 *
 *    The structure for rreq and wreq depend on the device you are openning.
 *    You must be sure to specify the correct size.
 *
 *    Some devices, such as the serial device, require certain fields inside
 *    their IO structures to be initialized before the OpenDevice().  Since
 *    io_open() Allocates these structures for you, these extra parameters
 *    must be passed to io_open() via SPEC1 and SPEC2 in the arguments list
 *    as outlined below:
 *                     SPEC1              SPEC2
 *    console.device   window pointer     window structure size
 *    parallel.device  parallel flags     0
 *    serial.device    serial flags       0
 *    **ALL OTHERS**   0                  0
 *
 *    note on audio device:  You must ADCMD_ALLOCATE and ADCMD_FREE
 *    manually.
 *
 *    You also pass io_open() the address of two pointers (e.g. **x).  These
 *    will be filled in by io_open() to result in a READ and WRITE request
 *    structure, each with it's own reply port, and with it's io_Command
 *    fields initialized to CMD_READ and CMD_WRITE, respectively.  You may
 *    specify a NULL for the **WRITE request structure instead of a
 *    **wreq.  This will result in only a READ request structure being
 *    set up.
 *
 *    You do not have to use the structures for only CMD_READ and CMD_WRITE,
 *    of course, you can use them for any io command.
 *
 *    a signal MASK with one bit set is returned.  This is the signal bit
 *    for the read-request structure (if rreq was NULL, then it is the
 *    signal for the write-request structure).  an example mask:
 *     00000000001000000000000000000000 in binary.
 *
 *    0 is returned if the open fails.
 *
 *
 *  io_close(rreq, wreq, size)
 *
 *       specify 0 for the wreq if it doesn't exist (e.g. you passed a
 *       NULL for it in the io_open() ).
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/serial.h>
#include <devices/parallel.h>

#define FAIL(ifzero) if (!ifzero) goto fail

typedef struct IORequest IOR;
typedef struct IOStdReq  STD;
typedef struct MsgPort   PORT;

extern char *AllocMem();
extern PORT *CreatePort();


long
io_open(name, unit, od_arg, prr, pww, size, special1, special2)
char *name;
IOR **prr, **pww;
long special1, special2;
{
   PORT  *rport, *wport;
   IOR   *rreq, *wreq;
   int ret;

   rreq  = wreq  = NULL;
   rport = wport = NULL;

   rport = CreatePort(NULL,0);                              FAIL(rport);
   rreq = (IOR *)AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR);    FAIL(rreq);
   if (pww) {
      wport = CreatePort(NULL,0);                           FAIL(wport);
      wreq = (IOR *)AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR); FAIL(wreq);
   }

   if (special1) {
      if (scmp(name, SERIALNAME))
         ((struct IOExtSer *)rreq)->io_SerFlags = special1;
      if (scmp(name, PARALLELNAME))
         ((struct IOExtPar *)rreq)->io_ParFlags = special1;
      if (scmp(name, "console.device")) {
         ((STD *)rreq)->io_Data  = (APTR)special1;
         ((STD *)rreq)->io_Length= special2;
      }
   }

   rreq->io_Message.mn_ReplyPort = rport;
   ret = OpenDevice(name, unit, rreq, od_arg);           FAIL(!ret);

   if (pww) {
      *wreq = *rreq;                         /* structure assignment   */
      wreq->io_Message.mn_ReplyPort = wport;
      wreq->io_Command = CMD_WRITE;
      *pww = wreq;
   }
   rreq->io_Command = CMD_READ;
   *prr = rreq;

   return (1 << rport->mp_SigBit);           /* return read sig bit    */
fail:
   if (rport)  DeletePort(rport);
   if (wport)  DeletePort(wport);
   if (rreq)   FreeMem(rreq, size);
   if (wreq)   FreeMem(wreq, size);
   return (0);
}


io_close(rreq, wreq, size)
IOR *rreq, *wreq;
{
   if (rreq) {
      CloseDevice(rreq);
      if (rreq->io_Message.mn_ReplyPort)
         DeletePort(rreq->io_Message.mn_ReplyPort);
      FreeMem (rreq, size);
   }
   if (wreq) {
      if (wreq->io_Message.mn_ReplyPort)
         DeletePort(wreq->io_Message.mn_ReplyPort);
      FreeMem (wreq, size);
   }
}


scmp(s1, s2)
register char *s1, *s2;
{
   while (*s1 == *s2) {
      if ((*s1 | *s2) == 0)
         return (1);
      ++s1; ++s2;
   }
   return (0);
}

SHAR_EOF
fi
if test -f 'string.b'
then
	echo shar: "will not over-write existing file 'string.b'"
else
cat << \SHAR_EOF > 'string.b'

/*
 * STRING.B    V2.00
 *
 * strlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp
 *
 */


/*BREAKUP src/strlen.asm        */

            xdef  _strlen

_strlen
            move.l   4(A7),A0       ;pointer
loop        tst.b    (A0)+          ;loop until 0
            bne      loop

            sub.l    4(A7),A0
            sub.l    #1,A0
            move.l   A0,D0
            rts


/*BREAKUP src/strcpy.asm         */

            xdef  _strcpy

_strcpy
            move.l   4(A7),A0       ; dest
            move.l   8(A7),A1       ; src
loop        move.b   (A1)+,(A0)+    ; src to dest
            bne      loop           ; until zero

            move.l   4(A7),D0
            rts


/*BREAKUP src/strncpy.c       */

char *
strncpy(dest, src, n)
register char *dest, *src;
register int n;
{
   register char *orig = dest;
   while (*src && n--)
      *dest++ = *src++;
   *dest++ = '\0';
   return (orig);
}


/*BREAKUP src/strcat.asm         */

            xdef  _strcat

_strcat
            move.l   4(A7),A0       ; dest
            move.l   8(A7),A1       ; src
            move.l   A0,D0          ; return the destination
loop1       tst.b    (A0)+          ; skip start of string
            bne      loop1
            subq.l   #1,A0          ; dec. so now points at the 0
loop2       move.b   (A1)+,(A0)+    ; src to dest
            bne      loop2          ; until zero
            rts


/*BREAKUP src/strncat.c       */

char *
strncat(dest, src, n)
register char *dest, *src;
register int n;
{
   register char *orig = dest;
   while (*dest)
      ++dest;
   while (*src && n--)
      *dest++ = *src++;
   *dest++ = '\0';
   return (orig);
}

/*BREAKUP src/strcmp.c        */

strcmp(s1, s2)
register unsigned char *s1, *s2;
{
   while (*s1 && *s2) {
x:
      if (*s1 < *s2)
         return (-1);
      if (*s1 > *s2)
         return (1);
      ++s1;
      ++s2;
   }
   if (*s1 == *s2)
      return (0);
   goto x;
}

/*BREAKUP src/strncmp.c       */

strncmp(s1, s2, n)
register unsigned char *s1, *s2;
register int n;
{
   while (n && *s1 && *s2) {
      --n;
x:
      if (*s1 < *s2)
         return (-1);
      if (*s1 > *s2)
         return (1);
      ++s1;
      ++s2;
   }
   if (n == 0 || (*s1 == *s2))
      return (0);
   goto x;
}

SHAR_EOF
fi
if test -f 'xstdio.b'
then
	echo shar: "will not over-write existing file 'xstdio.b'"
else
cat << \SHAR_EOF > 'xstdio.b'

/*
 * XSTDIO.B    V2.00
 *
 * 32 bit library... you should use it only with 32 bit compilers
 *
 * Provides an alternative to normal standard IO functions.  Mainly, you
 * have a little more control over the situation, and most of the functions
 * are independant of each other (makes for smaller executables).  However,
 * YOU MUST XCLOSE ALL OPEN FILES BEFORE YOU EXIT, it will not be done
 * automagically.
 *
 * In all cases (e.g. close, xdetach ...) any unwritten data will be
 * written out as if an xflush() had been called.  All functions are pretty
 * straight forward with a few exceptions (if you don't like it, tough).
 *
 *
 *
 *    fi    = xopen(file, "access", bufsize);
 *
 *                access is "r"  read           (fail if non-existant)
 *                          "r+" read and write (fail if non-existant)
 *                          "w"  write  (truncates or new file if non-existant)
 *                          "w+" append (append or new file if non-existant)
 *
 *                bufsize of 0 is actually 1 (but I don't suggest you use
 *                such a small bufsize).  If you write a 20K block out
 *                and you have a 1 character bufsize, it will be written
 *                out 1 character at a time, so don't do that.
 *
 *                returns NULL if it failed.
 *
 *  ret     = xasync(fi, mode);
 *
 *                Execute Asyncronous command or set Asyncronous mode for a
 *                file.  Currently, the following modes are supported:
 *
 *                -1 :  Returns (0) if asyncronous writes are off, (1)if on.
 *                 0 :  Turn off asyncronous writes
 *                 1 :  Turn on asyncronous writes, returns bool
 *                 2 :  reserved for future use
 *
 *                 3 :  (internal) Wait for asyncronous oper. to complete
 *                 4 :  (internal) execute asyncronous write (You should
 *                      NEVER call this!)
 *
 *                When on, buffer flushes are double-buffered.  That is,
 *                if you write to the file slow enough (e.g. modem capture),
 *                none of the xstdio write functions will ever cause a
 *                delay.  Since it's double buffered, a second buffer is
 *                allocated while xasync is on.
 *
 *                calling w/ mode 4, though it will not crash machine,
 *                will not have any desirable effects.
 *
 *                Future Versions will also have an asyncronous READ
 *                capability.
 *
 *
 *    fi    = xattach(fh, bufsize);
 *
 *                attach a File Handle and a buffer to create an xstdio
 *                file pointer.  Returns NULL if it failed (fh is NOT
 *                closed).
 *
 *    fh    = xdetach(fi);
 *
 *                detach the File Handle from an xstdio file pointer (fi)
 *                and DEALLOCATES the fi.  The File Handle will be Seek'd
 *                to the correct place.  This always works.
 *
 *    bool  = xsetbuf(fi, newbufsize);
 *
 *                change the size of an fi's buffer.  If it failed (0), the
 *                old buffer is STILL IN PLACE!  Remember that if
 *                asyncronous mode is on, the the actual bytes allocated is
 *                double what you specify (two buffers instead of one).
 *
 *    chars = xgets(fi, buf, n);
 *
 *                get a string from an fi.  The string is \0 terminated and
 *                DOES NOT HAVE A '\n'.  'chars' is the size of the string
 *                INCLUDING the \0.   Therefore, if 0 is returned, you
 *                reached the end of the file or an error occured.
 *
 *    bool  = xputs(fi, buf);
 *
 *                writes a string to an fi.  a '\n' will automatically be
 *                appended to the string.  the '\0' that terminates the
 *                string is NOT written (e.g. the logical reverse of xgets())
 *
 *                FALSE (0) is returned on error.
 *
 *    c     = xgetc(fi);
 *
 *                -1 is returned on EOF
 *
 *    bool  = xputc(fi, c);
 *
 *                Note: Since files are buffered, a write error may not be
 *                returned until the buffer is flushed (by xputc() or
 *                manually)
 *
 *    actual= xread(fi, buf, n);
 *
 *                0 is returned on end of file or error.
 *
 *    bool  = xwrite(fi, buf, n);
 *
 *                Note: xwrite() only returns a true or false.  Additionaly,
 *                since files are buffered, a write error may not be
 *                returned until the buffer is flushed (by xwrite() or
 *                manually)
 *
 *    bool  = xflush(fi);
 *
 *                flush the buffers.  FALSE is returned only if the buffer
 *                was modified AND the Write failed.  If the buffer was not
 *                modified, no Write() is done.
 *
 *    newpos= xseek(fi, offset, which);
 *
 *                'which' uses AMIGA convensions:  -1 start
 *                                                  0 current
 *                                                  1 end
 *
 *                NOTE: the NEW position is returned, not the old.
 *
 *
 *    pos   = xtell(fi);
 *
 *                returns the current position of the r/w pointer
 *
 *
 *            xclose(fi);
 *
 *                You may pass xclose() a NULL without harm.
 *
 *    ptr   = gets(buf);
 *
 *                \0 terminated from Input().  Same as normal gets().  Note
 *                that this one returns passed pointer, or NULL on end-of-
 *                input or error.
 *
 *                This is rather a slow function, since it must call Read()
 *                one character at a time.  If possible, you should
 *                xattach() the Input() file handle to an xstdio file
 *                pointer and use xgets().
 *
 *    bool  = puts(str);
 *
 *                Amiga.LIB's puts() does not allow strings over 256 chars,
 *                this one allows strings of any size.
 *
 *                FALSE is returned on error.
 */

/*BREAKUP src/xstdio.h          */

typedef struct {
   long replyport;         /* non-zero = asyncronous I/O active      */
   int (*func)();          /* asyncronous dispatch function          */
   long fh;                /* file handle                            */
   long i1, i2, max;       /* buffer indexes (current, end, bufsize) */
   long pos, vpos;         /* real current, virtual current          */
   char stat;              /* modified?                              */
   unsigned char *buf;     /* za buffer                              */
   unsigned char *bufexg;  /* exchange buffer for async. IO          */
} FILE;

#define FIS_MODIFIED 0x01
#define FIS_APEND    0x02

#define ASYNC_OFF    0
#define ASYNC_WRITE  1
#define ASYNC_WAIT   3

#ifndef MODE_READWRITE
#define MODE_READWRITE  1004
#endif
#ifndef MODE_READONLY
#define MODE_READONLY   1005
#endif
#ifndef MODE_OLDFILE
#define MODE_OLDFILE    1005
#endif
#ifndef MODE_NEWFILE
#define MODE_NEWFILE    1006
#endif
#ifndef MEMF_CLEAR
#define MEMF_CLEAR   (1 << 16)
#endif
#ifndef NULL
#define NULL 0
#endif

extern FILE *xopen(), *xattach();
extern long xread(), xseek(), xtell(), xdetach();


/*BREAKUP src/xopen.c          */

#include "xstdio.h"

FILE *
xopen(name, str, size)
register char *name, *str;
long size;
{
   register FILE *fi;
   register int mode;
   register long fh = 0;

   if (size < 1)
      size = 1;
   fi = (FILE *)AllocMem((long)sizeof(FILE), MEMF_CLEAR);
   if (fi) {
      if (str[0] == 'r') {
         mode = MODE_READONLY;
         if (str[1] == '+')
            mode = MODE_READONLY;                  /* actually rw */
      }
      if (str[0] == 'w') {
         mode = MODE_NEWFILE;
         if (str[1] == '+') {
            if (fh = Open(name, MODE_OLDFILE))
               Seek(fh, 0L, 1);
         }
      }
      if (!fh)
         fh = Open(name, mode);
      if (fh) {
         fi->fh = fh;
         fi->max = size;
         if (fi->buf = (unsigned char *)AllocMem(size, 0)) {
            fi->pos = fi->vpos = Seek(fh, 0L, 0);
         } else {
            Close(fh);
            goto fail;
         }
      } else {
fail:
         FreeMem(fi, (long)sizeof(FILE));
         return(NULL);
      }
   }
   return(fi);
}


/*BREAKUP src/xasync.c           */

/*
 * XASYNC.C
 *
 * These routines control the asyncronous write mode for xstdio files.
 * Vectors are setup such that this object module is only included if you
 * specifically make a call to xasync().  So if you aren't using asyncronous
 * I/O, the extra code is not included.
 *
 */

#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "xstdio.h"

typedef struct StandardPacket STDPKT;
typedef struct FileHandle     FH;

typedef unsigned char u_char;

xasync(fi, mode)
register FILE *fi;
{
   register long rp;

   switch (mode) {
   case -1:
      return (fi->replyport != 0);
   case 0:
      if (fi->replyport) {
         xasync_wait(fi);
         DeletePort(fi->replyport);
         FreeMem (fi->bufexg, fi->max);
         fi->replyport = 0;
         fi->bufexg = 0;
         fi->func = 0;
      }
      return (1);
   case 1:
      if (fi->replyport == 0) {
         if (rp = CreatePort(NULL,NULL)) {
            if (!(fi->bufexg = (u_char *)AllocMem(fi->max, 0))) {
               DeletePort(rp);
               return (0);
            }
         }
         fi->replyport = rp;
         fi->func = xasync;
      }
      return (1);
   case 2:

      /* Reserved for future asyncronous READ mode */

      break;
   case 3:
      xasync_wait(fi);
      return (1);
   case 4:
      xasync_send(fi);
      return (1);
   }
   return (0);
}


static
xasync_wait(fi)
register FILE *fi;
{
   if (fi->replyport && (fi->stat & FIS_APEND)) {
      WaitPort (fi->replyport);
      FreeMem( GetMsg(fi->replyport), sizeof(STDPKT) );
      fi->stat &= ~FIS_APEND;
   }
}


static
xasync_send(fi)
register FILE *fi;
{
   register int *iptr;
   register STDPKT *sp;
   register FH     *file;
   unsigned char *temp;

   file = (FH *)(fi->fh << 2);
   sp = (STDPKT *)AllocMem(sizeof(STDPKT), MEMF_CLEAR);
   sp->sp_Msg.mn_Node.ln_Name = (char *)&(sp->sp_Pkt);
   sp->sp_Pkt.dp_Link = &(sp->sp_Msg);
   sp->sp_Pkt.dp_Port = (struct MsgPort *)fi->replyport;
   sp->sp_Pkt.dp_Type = ACTION_WRITE;
   iptr = &sp->sp_Pkt.dp_Arg1;
   iptr[0] = (long)file->fh_Arg1;
   iptr[1] = (long)fi->buf;
   iptr[2] = fi->i1;
   xasync_wait (fi);                   /* Wait for previous to finish  */
   PutMsg (file->fh_Type, sp);         /* file handler                 */
   fi->stat |= FIS_APEND;              /* new operation pending        */
   temp = fi->buf;                     /* swap write buffers           */
   fi->buf = fi->bufexg;
   fi->bufexg = temp;
}


/*BREAKUP src/xclose.c           */

#include "xstdio.h"

xclose(fi)
register FILE *fi;
{
   if (fi) {
      xflush(fi);
      if (fi->func)                       /* turn off asyncronous i/o */
         (*fi->func)(fi, ASYNC_OFF);
      if (fi->fh)                         /* close file handle        */
         Close(fi->fh);
      FreeMem(fi->buf, fi->max);
      FreeMem(fi, sizeof(FILE));
   }
}

/*BREAKUP src/xgetc.c            */

xgetc(fi)
{
   unsigned char c;

   if (xread(fi, &c, 1))
      return ((int)c);
   return (-1);
}


/*BREAKUP src/xputc.c            */

xputc(fi, c)
{
   char c;

   return (xwrite(fi, &c, 1));
}


/*BREAKUP src/xread.c            */

#include "xstdio.h"

long
xread(fi, buf, n)
register FILE *fi;
register char *buf;
register long n;
{
   register long r, rr = 0;

   for (;;) {
      r = fi->i2 - fi->i1;
      if (r > n)
         r = n;
      if (r) {
         bmov(fi->buf + fi->i1, buf, r);
         buf += r;
         n   -= r;
         rr  += r;
         fi->vpos += r;
         fi->i1   += r;
      }
      if (n) {
         if (xfilbuf(fi))
            continue;
      }
      break;
   }
   return(rr);
}


/*BREAKUP src/xwrite.c            */

#include "xstdio.h"

xwrite(fi, buf, n)
register FILE *fi;
register char *buf;
register long n;
{
   register long w;

   for (;;) {
      w = (fi->max - fi->i1 < n) ? fi->max - fi->i1 : n;
      bmov(buf, fi->buf + fi->i1, w);
      n -= w;
      buf += w;
      fi->vpos += w;
      fi->i1   += w;
      if (fi->i2 < fi->i1)
         fi->i2 = fi->i1;
      fi->stat |= FIS_MODIFIED;
      if (n) {
         w = xflush(fi);
         if (w == 0)
            return (0);
         continue;
      }
      break;
   }
   return (1);
}


/*BREAKUP src/xsetbuf.c          */

#include "xstdio.h"

xsetbuf(fi, size)
register FILE *fi;
register long size;
{
   register char *new1, *new2;
   register int (*func)();

   if (size < 1)                          /* min buffer size     */
      size = 1;
   xflush(fi);                            /* flush output        */
   new1 = (char *)AllocMem(size, 0);      /* allocate new buffer */
   new2 = NULL;
   if (func = fi->func)                   /* async buffer        */
      new2 = (char *)AllocMem(size, 0);
   if (new1 && (!func || new2)) {         /* all ok?             */
      if (func) {                         /* flush async         */
         (*func)(fi, ASYNC_WAIT);
         FreeMem(fi->bufexg, fi->max);
      }
      FreeMem(fi->buf, fi->max);
      fi->buf    = new1;                  /* emplace new bufs    */
      fi->bufexg = new2;
      fi->max = size;
      return (1);
   }
   if (new1)                              /* error, deallocate   */
      FreeMem(new1, size);
   if (new2)
      FreeMem(new2, size);
   return (0);
}


/*BREAKUP src/xattach.c          */

#include "xstdio.h"

FILE *
xattach(fh, size)
long fh, size;
{
   register FILE *fi;

   if (size < 1)
      size = 1;
   fi = (FILE *)AllocMem(sizeof(FILE), MEMF_CLEAR);
   if (fi) {
      if (fi->buf = (unsigned char *)AllocMem(fi->max = size, 0)) {
         fi->pos = fi->vpos = Seek(fi->fh = fh, 0L, 0);
         return (fi);
      }
      FreeMem(fi, sizeof(FILE));
   }
   return (NULL);
}


/*BREAKUP src/xdetach.c          */

#include "xstdio.h"

long
xdetach(fi)
register FILE *fi;
{
   register long fh;

   xflush(fi);
   Seek(fh = fi->fh, fi->vpos - fi->pos, 0);    /* seek to virtual pos */
   fi->fh = NULL;
   xclose(fi);
   return (fh);
}


/*BREAKUP src/xtell.c            */

#include "xstdio.h"

long
xtell(fi)
FILE *fi;
{
   return (fi->vpos);
}


/*BREAKUP src/xseek.c            */

#include "xstdio.h"

long
xseek(fi, offset, how)
register FILE *fi;
register long offset, how;
{
   register long abs, i1;

   if (how < 1) {                      /* seek beg, seek rel  */
      abs = offset;                    /* get absolute offset */
      if (!how)
         abs += fi->vpos;
      i1 = fi->i1 + abs - fi->vpos;    /* figure new index     */
      if (i1 >= 0 && i1 <= fi->i2) {   /* still in buffer?     */
         fi->i1 = i1;
         fi->vpos = abs;
         return (abs);
      }
      xflush_wait(fi);
      Seek(fi->fh, abs, -1);
   } else {
      xflush_wait(fi);                    /* flush buffer and     */
      Seek(fi->fh, offset, 2);            /* seek to new position */
   }
   fi->pos = fi->vpos = Seek(fi->fh, 0L, 0);
   return (fi->vpos);
}

/*BREAKUP src/xputs.c            */

#include "xstdio.h"

xputs(fi, buf)
FILE *fi;
char *buf;
{
   if (xwrite(fi, buf, (long)strlen(buf)) && xwrite(fi, "\n", 1L))
         return(1);
   return(0);
}

/*BREAKUP src/gets.c             */

char *
gets(buf)
register char *buf;
{
   register int i = 0;
   register long infh = Input();

   while (Read(infh, buf+i, 1L)) {
      ++i;
      if (buf[i-1] == 13 || buf[i-1] == 10)
         break;
   }
   return ((i) ? ((buf[i-1] = '\0'), buf) : 0);
}

/*BREAKUP src/puts.c             */

puts(buf)
char *buf;
{
   register long fh = Output();
   register int len = strlen(buf);

   if (Write(fh, buf, len) == len  &&  Write(fh, "\n", 1))
      return (1);
   return (0);
}

/*BREAKUP src/xgets.c            */

#include "xstdio.h"

xgets(fi, buf, max)
register FILE *fi;
register char *buf;
register long max;
{
   register int i;

   --max;
   for (i = 0; i < max; ++i) {
      if (fi->i1 == fi->i2) {
         if (xfilbuf(fi) == 0) {
            buf[0] = '\0';
            return(0);
         }
      }
      buf[i] = fi->buf[fi->i1++];
      ++fi->vpos;
      if (buf[i] == '\n')
         break;
   }
   buf[i] = '\0';
   return(i+1);
}



/*BREAKUP src/xfilbuf.c          */

#include "xstdio.h"

xfilbuf(fi)
register FILE *fi;
{
   register long n;
   register long fh = fi->fh;

   xflush_wait(fi);
   if (fi->vpos != fi->pos)
      Seek(fh, fi->vpos - fi->pos, 0);
   n = Read(fh, fi->buf, fi->max);
   if (n <= 0) {
      fi->pos = fi->vpos;
      Seek(fh, fi->pos, -1);
      return (0);
   }
   fi->pos = fi->vpos + (fi->i2 = n);
   return(1);
}


/*BREAKUP src/xflush.c        */

#include "xstdio.h"

xflush(fi)
register FILE *fi;
{
   register long vstart;
   register int i;
   register int r = 1;

   if (fi->stat & FIS_MODIFIED) {
      vstart = fi->vpos - fi->i1;
      if (fi->pos != vstart) {
         if (fi->func)
            (*fi->func)(fi, ASYNC_WAIT);
         Seek (fi->fh, vstart - fi->pos, 0);
      }
      if (fi->replyport) {
         (*fi->func)(fi, 4);                    /* asyncronous */
         i = fi->i1;
      } else {
         i = Write(fi->fh, fi->buf, fi->i1);    /* syncronous  */
      }
      if (i != fi->i1) {
         r = 0;
         if (i < 0)
            i = 0;
      }
      fi->pos = vstart + i;
      fi->stat &= ~FIS_MODIFIED;
   }
   fi->i1 = fi->i2 = 0;
   return (r);
}

xflush_wait(fi)
FILE *fi;
{
   register int r;
   r = xflush(fi);
   if (fi->func)
      (*fi->func)(fi, ASYNC_WAIT);
   return (r);
}



/*BREAKUP src/xprintf.asm     */

;XPRINTF.ASM
;
;  Handles formatted printing to xstdio file pointers w/ xprintf
;  Handles formatted printing to Amiga file handles   w/ fprintf

      xdef  _xprintf
      xdef  _fprintf
      xref  _xwrite
      xref  _Write
      xref  _LVORawDoFmt
      xref  _SysBase

_xprintf
      jsr      xformat           ;RawDoFmt to buffer and write setup
      jsr      _xwrite
      bra      done
_fprintf
      jsr      xformat           ;same thing
      jsr      _Write
done
      lea.l    268(A7),A7
      rts

      ;XFORMAT takes a Xprintf(xx, cs, arg, arg...)  where xx is any
      ;integer and returns (xx, buf, bytes) on the stack suitable for an
      ;immediate call to xwrite() or Write().  The caller must deallocate
      ;268 bytes from the stack when done.
      ;
      ;                                     (oret)
      ;  A2 A3 A4 A5 A6 RET FI BUF NUM <thebuffer> printfret fi cs args
      ;  ^               ^                     ^
      ;  1               2                     3


xformat
      move.l   A7,A0             ;sp now at pos. #3      A0 = pos #3
      sub.l    #268,A7           ;sp now at pos. #2      SP = pos #2
      move.l   (A0),(A7)         ;copy return address
      move.l   8(A0),4(A7)       ;copy fi or fh  to FI
      lea.l    16(A7),A1         ;address of buffer
      move.l   A1,8(A7)          ;place in          BUF
      movem.l  A2-A6,-(A7)       ;save regs              SP = pos #1
      move.l   A1,A3             ;A3 = buffer pointer
      lea.l    16(A0),A1         ;A1 = lea of printf arg list
      move.l   12(A0),A0         ;A0 = control string
      move.l   #_xc,A2           ;A2 = call vector

      move.l   _SysBase,A6       ;exec library call
      jsr      _LVORawDoFmt(A6)

      move.l   28(A7),A3         ;buffer start
loop  tst.b    (A3)+             ;find end of string
      bne      loop
      sub.l    28(A7),A3         ;get string length
      subq.l   #1,A3
      move.l   A3,32(A7)         ;place in          NUM
      movem.l  (A7)+,A2-A6       ;restore registers used
      rts

_xc
      move.b   D0,(A3)+
      rts


SHAR_EOF
fi
exit 0
#	End of shell archive