home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
292.lha
/
XPRLib_v2.0
/
library
/
xprascii.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-03
|
11KB
|
377 lines
/** xprascii.c
*
* These are the protocol transfer routines for a simple ASCII upload.
*
**/
#include <exec/exec.h>
#include <functions.h>
#include <stdio.h>
/*
* xproto.h is the include file given in Appendix B.
*/
#include "xproto.h"
/*
* The following two strings must exist.
*/
char XPRname[] = "xprascii.library";
char XPRid[] = "xprascii 0.9 (May 89)\r\n";
UWORD XPRrevision = 9;
long atol();
/*
* The callxx...() routines are described later. They provide the
* assembler interface from the XPR library to the call-back routines.
*/
long calla(), callaa(), callad(), calladd(), calladda();
char *malloc();
/**
*
* Send a file
*
**/
long XProtocolSend(IO)
struct XPR_IO *IO;
{
long fp, r, i;
long brkflag = 0, fl = 0L, sd = 0L;
long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(),
(*xsread)(), (*xchkabort)();
unsigned char *buff = NULL, *serbuff = NULL;
struct XPR_UPDATE xpru;
/*
* These are the call-backs we need. If any of them isn't provided, quit.
* Could do some error reporting if at least xupdate is there.
*/
if ((xupdate = IO->xpr_update) == NULL) return(0L);
if ((xswrite = IO->xpr_swrite) == NULL) return(0L);
if ((xfopen = IO->xpr_fopen) == NULL) return(0L);
if ((xfclose = IO->xpr_fclose) == NULL) return(0L);
if ((xfread = IO->xpr_fread) == NULL) return(0L);
if ((xsread = IO->xpr_sread) == NULL) return(0L);
if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L);
/*
* Allocate a few buffers.
*/
buff = (unsigned char *) malloc(80);
serbuff = (unsigned char *) malloc(80);
/*
* If we ran out of memory, print a message.
* The argument needs to go in A0: calla does this for us.
*/
if (buff == NULL || serbuff == NULL) {
xpru.xpru_updatemask = XPRU_ERRORMSG;
xpru.xpru_errormsg = "Ran out of memory!";
calla(xupdate, &xpru);
return(0L);
}
/*
* Read the send delay, if a XProtocolSetup() was done before.
* If send delay is too large, cut it off at 10 seconds.
* In this example, the xpr_data field contains a null terminated string
* containing the number of ticks to delay each 80 characters.
*/
if (IO->xpr_data) {
sd = atol(IO->xpr_data);
if (sd > 500L) sd = 500L;
}
/*
* Open the file. One could do wild card detection here.
* xfopen requires two arguments, in a0 and a1 respectively.
* Again, this must be done in assembler, and callaa does it.
*/
fp = callaa(xfopen, IO->xpr_filename, "r");
if (fp == NULL) {
free(buff);
free(serbuff);
xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
xpru.xpru_errormsg = "Failed to open input file";
xpru.xpru_filename = IO->xpr_filename;
calla(xupdate, &xpru);
return(0L);
}
/*
* Start the transfer. See 3.8 for a discussion on how to implement
* xupdate.
*/
xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
xpru.xpru_msg = "Starting ASCII Send";
xpru.xpru_filename = IO->xpr_filename;
calla(xupdate, &xpru);
/*
* Now read 80 byte chunks from the file using xfread.
* xfread requires four arguments, a0, d0, d1 and a1.
*/
xpru.xpru_blocks = 0L;
while (r = calladda(xfread, buff, 1L, 80L, fp)) {
/*
* Convert line feeds to carriage returns before sending to host.
* fl counts the characters. Display how many characters are sent.
*/
for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r';
fl += r;
xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
xpru.xpru_bytes = fl;
xpru.xpru_blocks++;
xpru.xpru_blocksize = r;
calla(xupdate, &xpru);
callad(xswrite, buff, r);
/*
* Every 80 bytes, put out a message and delay if requested.
*/
xpru.xpru_updatemask = XPRU_PACKETDELAY;
xpru.xpru_packetdelay = sd * 20L; /* msec! */
calla(xupdate, &xpru);
/*
* Can't use Delay() here, because Delay() is in dos.library!
* However writing an equivalent function using the timer.device is
* trivial.
*/
TimeOut(sd);
/*
* Eat any characters that might arrive from the serial port.
* calladd stores arg1 in a0, arg2 in d0, arg3 in d1.
* We're not really waiting for any characters: use a timeout of 0L.
*/
while (calladd(xsread, serbuff, 80L, 0L) > 0L) ;
/*
* Check for "abort" here. Perhaps should call chkmisc() as well.
*/
if (brkflag = xchkabort()) break;
}
/*
* Close the file
*/
calla(xfclose, fp);
free(buff);
free(serbuff);
/*
* If we got here through chkabort() say Aborted.
*/
xpru.xpru_updatemask = XPRU_MSG;
if (brkflag) xpru.xpru_msg = "Aborted";
else xpru.xpru_msg = "Done";
calla(xupdate, &xpru);
if (brkflag) return(0L);
else return(1L);
}
/**
*
* Receive a file.
*
**/
long XProtocolReceive(IO)
struct XPR_IO *IO;
{
long fp, r, i;
long brkflag = 0, fl = 0L, sd = 0L;
long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(),
(*xsread)(), (*xchkabort)();
unsigned char *serbuff = NULL;
struct XPR_UPDATE xpru;
/*
* These are the call-backs we need. If any of them isn't provided, quit.
* Could do some error reporting if at least xupdate is there.
*/
if ((xupdate = IO->xpr_update) == NULL) return(0L);
if ((xswrite = IO->xpr_swrite) == NULL) return(0L);
if ((xfopen = IO->xpr_fopen) == NULL) return(0L);
if ((xfclose = IO->xpr_fclose) == NULL) return(0L);
if ((xfwrite = IO->xpr_fwrite) == NULL) return(0L);
if ((xsread = IO->xpr_sread) == NULL) return(0L);
if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L);
/*
* Allocate a buffer.
*/
serbuff = (unsigned char *) malloc(80);
/*
* If we ran out of memory, print a message.
* The argument needs to go in A0: calla does this for us.
*/
if (serbuff == NULL) {
xpru.xpru_updatemask = XPRU_ERRORMSG;
xpru.xpru_errormsg = "Ran out of memory!";
calla(xupdate, &xpru);
return(0L);
}
/*
* Open the file. One could do wild card detection here.
* xfopen requires two arguments, in a0 and a1 respectively.
* Again, this must be done in assembler, and callaa does it.
*/
fp = callaa(xfopen, IO->xpr_filename, "w");
if (fp == NULL) {
free(serbuff);
xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
xpru.xpru_errormsg = "Failed to open output file";
xpru.xpru_filename = IO->xpr_filename;
calla(xupdate, &xpru);
return(0L);
}
/*
* Start the transfer. See 3.8 for a discussion on how to implement
* xupdate.
*/
xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
xpru.xpru_msg = "Starting ASCII Receive";
xpru.xpru_filename = IO->xpr_filename;
calla(xupdate, &xpru);
/*
* Now read 80 byte chunks from the serial port using xsread. Stop
* when no characters arrive for 5 sec.
*/
xpru.xpru_blocks = 0L;
while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L) {
/*
* Strip high-bit before storing in file.
* fl counts the characters. Display how many characters are received.
*/
for (i = 0L; i < r; i++) serbuff[i] &= 0177;
fl += r;
xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
xpru.xpru_bytes = fl;
xpru.xpru_blocks++;
xpru.xpru_blocksize = r;
calla(xupdate, &xpru);
/*
* Write 80 byte chunks to the file using xwrite
*/
calladda(xfwrite, serbuff, 1L, r, fp);
/*
* Check for "abort" here. Perhaps should call chkmisc() as well.
*/
if (brkflag = xchkabort()) break;
}
/*
* Close the file
*/
calla(xfclose, fp);
free(serbuff);
/*
* If we got here through chkabort() say Aborted.
*/
xpru.xpru_updatemask = XPRU_MSG;
if (brkflag) xpru.xpru_msg = "Aborted";
else xpru.xpru_msg = "Done";
calla(xupdate, &xpru);
if (brkflag) return(0L);
else return(1L);
}
/**
*
* Setup
*
**/
long XProtocolSetup(IO)
struct XPR_IO *IO;
{
long (*xupdate)(), (*xgets)();
struct XPR_UPDATE xpru;
if ((xupdate = IO->xpr_update) == NULL) return(0L);
if ((xgets = IO->xpr_gets) == NULL) return(0L);
/*
* Allocate a bit of memory for a data buffer
*/
if (IO->xpr_data == NULL) {
if ((IO->xpr_data = (long *) malloc(256)) == NULL) {
xpru.xpru_updatemask = XPRU_ERRORMSG;
xpru.xpru_errormsg = "ASCII - Out of memory!";
calla(xupdate, &xpru);
return(0L);
}
}
/*
* If setup string isn't handed to us, ask questions
*/
if (IO->xpr_filename == NULL) {
/*
* Get the value for the send dealy
*/
callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)",
IO->xpr_data);
}
else {
strcpy(IO->xpr_data, IO->xpr_filename);
}
return(1L);
}
/**
*
* Cleanup
*
**/
long XProtocolCleanup(IO)
struct XPR_IO *IO;
{
if (IO->xpr_data) free(IO->xpr_data);
IO->xpr_data = NULL;
return(1L);
}
/**
*
* The following functions setup the proper registers for the call-back
* functions.
*
**/
#asm
public _callad
_callad:
movea.l 8(sp),a0 ; Second argument goes in a0
move.l 12(sp),d0 ; Third argument goes in d0
/*
* Now this is a trick to avoid using another register.
* Charlie taught me this...
*/
move.l 4(sp),-(sp) ; First argument is function
rts
public _calladda
_calladda:
movea.l 8(sp),a0 ; Second argument goes in a0
move.l 12(sp),d0 ; Third argument goes in d0
move.l 16(sp),d1 ; Fourth argument goes in d1
movea.l 20(sp),a1 ; Fifth argument goes in a1
move.l 4(sp),-(sp) ; First argument is function
rts
public _calla
_calla:
movea.l 8(sp),a0 ; Second argument goes in a0
move.l 4(sp),-(sp) ; First argument is function
rts
public _callaa
_callaa:
movea.l 8(sp),a0 ; Second argument goes in a0
movea.l 12(sp),a1 ; Third argument goes in a1
move.l 4(sp),-(sp) ; First argument is function
rts
public _calladd
_calladd:
move.l 8(sp),a0 ; Second argument goes in a0
move.l 12(sp),d0 ; Third argument goes in d0
move.l 16(sp),d1 ; Fourth argument goes in d1
move.l 4(sp),-(sp) ; First argument is function
rts
#endasm
/*
* Could have added any other functions needed for other call-backs.
* Could have written a fancier single one... Could've...
*/