home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff247.lzh / XprLib / library / xprascii.c < prev    next >
C/C++ Source or Header  |  1989-09-15  |  11KB  |  377 lines

  1. /** xprascii.c
  2. *
  3. *   These are the protocol transfer routines for a simple ASCII upload.
  4. *
  5. **/
  6. #include <exec/exec.h>
  7. #include <functions.h>
  8. #include <stdio.h>
  9. /*
  10. *   xproto.h is the include file given in Appendix B.
  11. */
  12. #include "xproto.h"
  13. /*
  14. *   The following two strings must exist.
  15. */
  16. char  XPRname[]   = "xprascii.library";
  17. char  XPRid[]     = "xprascii 0.9 (May 89)\r\n";
  18. UWORD XPRrevision = 9;
  19.  
  20. long atol();
  21. /*
  22. *   The callxx...() routines are described later. They provide the 
  23. *   assembler interface from the XPR library to the call-back routines.
  24. */
  25. long calla(), callaa(), callad(), calladd(), calladda();
  26.  
  27. char *malloc();
  28.  
  29.  
  30. /**
  31. *
  32. *   Send a file
  33. *
  34. **/
  35. long XProtocolSend(IO)
  36. struct XPR_IO *IO;
  37. {
  38.    long fp, r, i;
  39.    long brkflag = 0, fl = 0L, sd = 0L;
  40.    long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(),
  41.         (*xsread)(),  (*xchkabort)();
  42.    unsigned char *buff = NULL, *serbuff = NULL;
  43.    struct XPR_UPDATE xpru;
  44.  
  45. /*
  46. *   These are the call-backs we need. If any of them isn't provided, quit.
  47. *   Could do some error reporting if at least xupdate is there.
  48. */
  49.    if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  50.    if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  51.    if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  52.    if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  53.    if ((xfread     = IO->xpr_fread)    == NULL) return(0L);
  54.    if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  55.    if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  56. /*
  57. *   Allocate a few buffers.
  58. */
  59.    buff    = (unsigned char *) malloc(80);
  60.    serbuff = (unsigned char *) malloc(80);
  61. /*
  62. *   If we ran out of memory, print a message.
  63. *   The argument needs to go in A0: calla does this for us. 
  64. */
  65.    if (buff == NULL || serbuff == NULL) {
  66.       xpru.xpru_updatemask = XPRU_ERRORMSG;
  67.       xpru.xpru_errormsg   = "Ran out of memory!";
  68.       calla(xupdate, &xpru);
  69.       return(0L);
  70.    }
  71. /*
  72. *   Read the send delay, if a XProtocolSetup() was done before.
  73. *   If send delay is too large, cut it off at 10 seconds.
  74. *   In this example, the xpr_data field contains a null terminated string
  75. *   containing the number of ticks to delay each 80 characters.
  76. */
  77.    if (IO->xpr_data) {
  78.       sd = atol(IO->xpr_data);
  79.       if (sd > 500L) sd = 500L;
  80.    }
  81. /*
  82. *   Open the file. One could do wild card detection here.
  83. *   xfopen requires two arguments, in a0 and a1 respectively.
  84. *   Again, this must be done in assembler, and callaa does it.
  85. */
  86.    fp = callaa(xfopen, IO->xpr_filename, "r");
  87.    if (fp == NULL) {
  88.       free(buff);
  89.       free(serbuff);
  90.       xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  91.       xpru.xpru_errormsg   = "Failed to open input file";
  92.       xpru.xpru_filename   = IO->xpr_filename;
  93.       calla(xupdate, &xpru);
  94.       return(0L);
  95.    }
  96. /*
  97. *   Start the transfer. See 3.8 for a discussion on how to implement
  98. *   xupdate. 
  99. */
  100.    xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  101.    xpru.xpru_msg        = "Starting ASCII Send";
  102.    xpru.xpru_filename   = IO->xpr_filename;
  103.    calla(xupdate, &xpru);
  104. /*
  105. *   Now read 80 byte chunks from the file using xfread.
  106. *   xfread requires four arguments, a0, d0, d1 and a1.
  107. */
  108.    xpru.xpru_blocks = 0L;
  109.    while (r = calladda(xfread, buff, 1L, 80L, fp)) {
  110. /*
  111. *   Convert line feeds to carriage returns before sending to host.
  112. *   fl counts the characters. Display how many characters are sent.
  113. */
  114.       for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r';
  115.       fl += r;
  116.       xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  117.       xpru.xpru_bytes      = fl;
  118.       xpru.xpru_blocks++;
  119.       xpru.xpru_blocksize  = r;
  120.       calla(xupdate, &xpru);
  121.       callad(xswrite, buff, r);
  122. /*
  123. *   Every 80 bytes, put out a message and delay if requested.
  124. */
  125.       xpru.xpru_updatemask  = XPRU_PACKETDELAY;
  126.       xpru.xpru_packetdelay = sd * 20L;  /* msec! */
  127.       calla(xupdate, &xpru);
  128. /*
  129. *   Can't use Delay() here, because Delay() is in dos.library!
  130. *   However writing an equivalent function using the timer.device is
  131. *   trivial.
  132. */
  133.       TimeOut(sd);
  134. /*
  135. *   Eat any characters that might arrive from the serial port.
  136. *   calladd stores arg1 in a0, arg2 in d0, arg3 in d1.
  137. *   We're not really waiting for any characters: use a timeout of 0L.
  138. */
  139.       while (calladd(xsread, serbuff, 80L, 0L) > 0L) ;
  140. /*
  141. *   Check for "abort" here. Perhaps should call chkmisc() as well.
  142. */
  143.       if (brkflag = xchkabort()) break;
  144.    }
  145. /*
  146. *   Close the file
  147. */
  148.    calla(xfclose, fp);
  149.    free(buff);
  150.    free(serbuff);
  151. /*
  152. *   If we got here through chkabort() say Aborted.
  153. */
  154.    xpru.xpru_updatemask       = XPRU_MSG;
  155.    if (brkflag) xpru.xpru_msg = "Aborted";
  156.    else         xpru.xpru_msg = "Done"; 
  157.    calla(xupdate, &xpru);
  158.    if (brkflag) return(0L);
  159.    else        return(1L);
  160. }
  161.  
  162.  
  163. /**
  164. *
  165. *   Receive a file.
  166. *
  167. **/
  168. long XProtocolReceive(IO)
  169. struct XPR_IO *IO;
  170. {
  171.    long fp, r, i;
  172.    long brkflag = 0, fl = 0L, sd = 0L;
  173.    long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(),
  174.         (*xsread)(),  (*xchkabort)();
  175.    unsigned char *serbuff = NULL;
  176.    struct XPR_UPDATE xpru;
  177.  
  178. /*
  179. *   These are the call-backs we need. If any of them isn't provided, quit.
  180. *   Could do some error reporting if at least xupdate is there.
  181. */
  182.    if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  183.    if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  184.    if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  185.    if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  186.    if ((xfwrite    = IO->xpr_fwrite)   == NULL) return(0L);
  187.    if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  188.    if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  189. /*
  190. *   Allocate a buffer.
  191. */
  192.    serbuff = (unsigned char *) malloc(80);
  193. /*
  194. *   If we ran out of memory, print a message.
  195. *   The argument needs to go in A0: calla does this for us. 
  196. */
  197.    if (serbuff == NULL) {
  198.       xpru.xpru_updatemask = XPRU_ERRORMSG;
  199.       xpru.xpru_errormsg   = "Ran out of memory!";
  200.       calla(xupdate, &xpru);
  201.       return(0L);
  202.    }
  203. /*
  204. *   Open the file. One could do wild card detection here.
  205. *   xfopen requires two arguments, in a0 and a1 respectively.
  206. *   Again, this must be done in assembler, and callaa does it.
  207. */
  208.    fp = callaa(xfopen, IO->xpr_filename, "w");
  209.    if (fp == NULL) {
  210.       free(serbuff);
  211.       xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  212.       xpru.xpru_errormsg   = "Failed to open output file";
  213.       xpru.xpru_filename   = IO->xpr_filename;
  214.       calla(xupdate, &xpru);
  215.       return(0L);
  216.    }
  217. /*
  218. *   Start the transfer. See 3.8 for a discussion on how to implement
  219. *   xupdate. 
  220. */
  221.    xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  222.    xpru.xpru_msg        = "Starting ASCII Receive";
  223.    xpru.xpru_filename   = IO->xpr_filename;
  224.    calla(xupdate, &xpru);
  225. /*
  226. *   Now read 80 byte chunks from the serial port using xsread. Stop
  227. *   when no characters arrive for 5 sec.
  228. */
  229.    xpru.xpru_blocks = 0L;
  230.    while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L)  {
  231. /*
  232. *   Strip high-bit before storing in file.
  233. *   fl counts the characters. Display how many characters are received.
  234. */
  235.       for (i = 0L; i < r; i++) serbuff[i] &= 0177;
  236.       fl += r;
  237.       xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  238.       xpru.xpru_bytes      = fl;
  239.       xpru.xpru_blocks++;
  240.       xpru.xpru_blocksize  = r;
  241.       calla(xupdate, &xpru);
  242. /* 
  243. *   Write 80 byte chunks to the file using xwrite
  244. */
  245.       calladda(xfwrite, serbuff, 1L, r, fp);
  246.  
  247. /*
  248. *   Check for "abort" here. Perhaps should call chkmisc() as well.
  249. */
  250.       if (brkflag = xchkabort()) break;
  251.    }
  252. /*
  253. *   Close the file
  254. */
  255.    calla(xfclose, fp);
  256.    free(serbuff);
  257. /*
  258. *   If we got here through chkabort() say Aborted.
  259. */
  260.    xpru.xpru_updatemask       = XPRU_MSG;
  261.    if (brkflag) xpru.xpru_msg = "Aborted";
  262.    else         xpru.xpru_msg = "Done"; 
  263.    calla(xupdate, &xpru);
  264.    if (brkflag) return(0L);
  265.    else        return(1L);
  266. }
  267.  
  268.  
  269. /**
  270. *
  271. *   Setup
  272. *
  273. **/
  274. long XProtocolSetup(IO)
  275. struct XPR_IO *IO;
  276. {
  277.    long (*xupdate)(), (*xgets)();
  278.    struct XPR_UPDATE xpru;
  279.  
  280.    if ((xupdate = IO->xpr_update) == NULL) return(0L);
  281.    if ((xgets   = IO->xpr_gets)   == NULL) return(0L);
  282. /*
  283. *   Allocate a bit of memory for a data buffer
  284. */
  285.    if (IO->xpr_data == NULL) {
  286.       if ((IO->xpr_data = (long *) malloc(256)) == NULL) {
  287.          xpru.xpru_updatemask = XPRU_ERRORMSG;
  288.          xpru.xpru_errormsg   = "ASCII - Out of memory!";
  289.          calla(xupdate, &xpru);
  290.          return(0L);
  291.       }
  292.    }
  293. /*
  294. *   If setup string isn't handed to us, ask questions
  295. */
  296.    if (IO->xpr_filename == NULL) {
  297. /*
  298. *   Get the value for the send dealy
  299. */
  300.       callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)",
  301.                   IO->xpr_data);
  302.    }
  303.    else {
  304.       strcpy(IO->xpr_data, IO->xpr_filename);
  305.    }
  306.    
  307.    return(1L);
  308. }
  309.  
  310. /**
  311. *
  312. *   Cleanup
  313. *
  314. **/
  315. long XProtocolCleanup(IO)
  316. struct XPR_IO *IO;
  317. {
  318.    if (IO->xpr_data) free(IO->xpr_data);
  319.    IO->xpr_data = NULL;
  320.  
  321.    return(1L);
  322. }
  323.  
  324. /**
  325. *
  326. *   The following functions setup the proper registers for the call-back 
  327. *   functions.
  328. *
  329. **/
  330. #asm
  331.         public _callad
  332. _callad:
  333.         movea.l 8(sp),a0                ; Second argument goes in a0
  334.         move.l  12(sp),d0               ; Third  argument goes in d0
  335. /*
  336. *   Now this is a trick to avoid using another register.
  337. *   Charlie taught me this...
  338. */
  339.         move.l  4(sp),-(sp)             ; First  argument is function
  340.         rts
  341.  
  342.         public  _calladda
  343. _calladda:
  344.         movea.l 8(sp),a0                ; Second argument goes in a0
  345.         move.l  12(sp),d0               ; Third  argument goes in d0
  346.         move.l  16(sp),d1               ; Fourth argument goes in d1
  347.         movea.l 20(sp),a1               ; Fifth  argument goes in a1
  348.         move.l  4(sp),-(sp)             ; First  argument is function
  349.         rts
  350.  
  351.         public  _calla
  352. _calla:
  353.         movea.l 8(sp),a0                ; Second argument goes in a0
  354.         move.l  4(sp),-(sp)             ; First  argument is function
  355.         rts
  356.  
  357.         public  _callaa
  358. _callaa:
  359.         movea.l 8(sp),a0                ; Second argument goes in a0
  360.         movea.l 12(sp),a1               ; Third  argument goes in a1
  361.         move.l  4(sp),-(sp)             ; First  argument is function
  362.         rts
  363.  
  364.         public  _calladd
  365. _calladd:
  366.         move.l  8(sp),a0                ; Second argument goes in a0
  367.         move.l  12(sp),d0               ; Third  argument goes in d0
  368.         move.l  16(sp),d1               ; Fourth argument goes in d1
  369.         move.l  4(sp),-(sp)             ; First  argument is function
  370.         rts
  371.  
  372. #endasm
  373. /*
  374. *   Could have added any other functions needed for other call-backs.
  375. *   Could have written a fancier single one... Could've...
  376. */
  377.