home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
pygmyforth
/
pfkerm.src
< prev
next >
Wrap
Text File
|
1997-11-12
|
10KB
|
437 lines
file pfkerm.src
This is a conversion of the Forth block file KERMIT.SCR
so as to be readable as a plain text file. Do not try
load it (compile it) without editing it to suit your
version of Forth. Don't load it under Pygmy Forth;
instead, get the actual block files from
http://www.eskimo.com/~pygmy/pfkerm.zip
KERMIT.SCR
Contains a simple implementation of the Kermit
file transfer protocol.
copyright 1997 Frank Sergeant pygmy@pobox.com
809 W. San Antonio St.
San Marcos, TX 78666
This source code is not Public Domain or Shareware.
You may use it freely for any private or commercial purpose
provided you do so at your own risk.
( load screen Kermit file transfer protocol)
" *** Simple Kermit file transfer protocol Copyright (c) 1997
Frank Sergeant (pygmy@pobox.com) *** " DROP
12002 12024 THRU
EXIT ( KERMIT - user interface)
: GET-Y/N ( - f)
BEGIN KEY DUP 'Y = OVER 'y = OR IF DROP -1 EXIT THEN
DUP 'N = SWAP 'n = OR IF 0 EXIT THEN BEEP
AGAIN ;
: TRY-AGAIN? ( a - f)
CR COUNT TYPE CR ." Try again? (Y/N) "
GET-Y/N ( f) ;
: .MSG ( a -) 0 0 AT 160 SPACES 0 0 AT COUNT TYPE ;
( KERMIT)
1 CONSTANT SOH
VARIABLE SEQ SEQ OFF
: BUMPSEQ ( -) SEQ @ 1+ 63 AND SEQ ! ;
94 ( 35) CONSTANT MYMAXL ( fields SEQ TYPE DATA & CKSUM)
CREATE OUT-BUF MYMAXL ( 1+) 2 + ALLOT VARIABLE OUTLEN
CREATE IN-BUF MYMAXL ( 1+) 2 + ALLOT VARIABLE INLEN
: ?NUM-OK ( n -) $5E > ABORT" too big" ;
: CHAR ( n - c) DUP ?NUM-OK ( n) $20 + ;
: UNCHAR ( c - n) $20 - ( n) DUP ?NUM-OK ;
( KERMIT - protocol parameters)
VARIABLE MAXL
VARIABLE QCTL
VARIABLE NPAD
VARIABLE PADC
VARIABLE EOLC
VARIABLE TIMEOUT
: INIT-LIMITS ( -)
MYMAXL MAXL ! ( maximum "len" value)
'# QCTL ! ( control code escape character)
0 NPAD ! ( number of pad characters)
0 PADC ! ( pad character)
$0D EOLC ! ( end of line character)
4 TIMEOUT ! ( timeout in seconds) ; INIT-LIMITS
( KERMIT - address of fields in buffers)
: FIELD: ( offset -) ( buff - a) CREATE C, DOES> C@ + ;
0 FIELD: >LEN
1 FIELD: >SEQ
2 FIELD: >TYPE
3 FIELD: >DATA
: >CKSUM ( buff - a) >LEN DUP C@ UNCHAR + ;
3 FIELD: >MAXL
4 FIELD: >TIME
5 FIELD: >NPAD
6 FIELD: >PADC
7 FIELD: >EOLC
8 FIELD: >QCTL
( KERMIT - compromise on the parameters)
: COMPROMISE ( -)
OUT-BUF IN-BUF ( a a)
OVER >MAXL C@ UNCHAR OVER >MAXL C@ UNCHAR
MIN MAXL ! ( a a)
OVER >TIME C@ UNCHAR OVER >TIME C@ UNCHAR
MAX TIMEOUT ! ( a a) 2DROP ;
DEFER M ( the menu to return to)
: KSER-IN ( - c f)
TIMEOUT @ 1000 * ( ms)
BEGIN KEY? IF KEY DROP CR
." Abort file transfer (Y/N)? " GET-Y/N CR
IF ." Transfer aborted -- press "
." any key to return to menu"
KEY DROP M
ELSE ." Transfer continuing "
THEN THEN
SER-IN? IF ( ms) DROP SER-IN DUP SOH = ( c f) EXIT THEN
( ms) 1- DUP 0= IF POP 2DROP 'V -1 EXIT THEN 1 MS
AGAIN ;
: TEST-IN ( - c f) KSER-IN ;
( KERMIT )
: CTRL ( c - c')
DUP QCTL @ = OVER '~ = OR IF EXIT THEN $40 XOR ;
: CTRL? ( c - f)
DUP $20 < OVER QCTL @ = OR OVER $7E = OR SWAP $7F = OR ;
: (KEMIT ( c -) OUT-BUF OUTLEN @ + C! ( ) 1 OUTLEN +! ;
: KEMIT ( c -) PAUSE ( just in case)
( c) DUP CTRL? IF QCTL @ (KEMIT CTRL ( c) THEN (KEMIT ;
: ROOM? ( - u) MAXL @ 1- OUTLEN @ > ;
( KERMIT )
: CK%% ( u - c)
DUP $C0 AND 2/ 2/ 2/ 2/ 2/ 2/ + $3F AND CHAR ;
: CKSUM ( buffer - c) >LEN DUP C@ UNCHAR ( a #) 0 ROT ROT
FOR ( sum a) C@+ +UNDER NEXT DROP CK%% ( c) ;
: CKSUM? ( - f)
IN-BUF CKSUM ( c) IN-BUF >CKSUM C@ ( c c) = ;
DEFER MODEM!
( ' EMIT) ' SER-OUT IS MODEM!
: DATA! ( a # - a' #') SWAP ( # a)
BEGIN ( # a) OVER 0= ROOM? 0= OR ( ie out of source or room)
NOT WHILE ( # a) C@+ KEMIT -1 +UNDER REPEAT SWAP ( a #) ;
: BUILD-FRAME ( a # type - a' #') OUTLEN OFF
0 ( ie dummy len) CHAR (KEMIT SEQ @ CHAR (KEMIT
(KEMIT ( a #) DATA! ( a' #')
OUTLEN @ CHAR OUT-BUF >LEN C! ( a #)
OUT-BUF CKSUM OUT-BUF >CKSUM C! ( a #) ;
( KERMIT - debugging aids)
: .FRAME ( buf -) ." len = " C@+ UNCHAR DUP PUSH 2 U.R
." seq = " C@+ UNCHAR 2 U.R SPACE SPACE
." myseq = " SEQ @ 2 U.R SPACE SPACE
POP 1- TYPE CR ;
: .INB ( type -) .S 3 SPACES
'V = IF ." V-frame " CR ELSE ." IN: " IN-BUF .FRAME THEN ;
: .OUTB ( -) .S 3 SPACES ." OUT: " OUT-BUF .FRAME ;
" WHAT DOES THE SYMBOL # STAND FOR?" CONSTANT TEST1
" as much labor for the study of its" CONSTANT TEST2
( KERMIT)
: SENDFRAME ( -) SOH MODEM! OUT-BUF >LEN DUP C@ UNCHAR 1+
FOR ( a) C@+ MODEM! NEXT DROP ( ) $0D MODEM! ;
( KERMIT)
: LIMITS ( type -)
SEQ OFF PUSH
'~ ( the repeat char)
'1 ( 1-byte chksum, either '1 or 1 CHAR seems to work)
'N ( no hi-bit prefix)
QCTL @ EOLC @ CHAR PADC @ CTRL
NPAD @ CHAR TIMEOUT @ CHAR MAXL @ CHAR POP
SEQ @ CHAR 12 ( len) CHAR
OUT-BUF 12 FOR DUP PUSH C! POP 1+ NEXT DROP ( )
OUT-BUF CKSUM OUT-BUF >CKSUM C! ;
( KERMIT)
: BUILD/SEND ( a # type -) BUILD-FRAME SENDFRAME 2DROP ;
: KINIT ( -) 'S LIMITS SENDFRAME ;
: KINITACK ( -) 'Y LIMITS COMPROMISE 'Y LIMITS SENDFRAME ;
: FILEHEADER ( a # -) " sending file " .MSG 2DUP TYPE
( a #) 'F BUILD/SEND ;
: EMPTY-FRAME ( type -) ( ) CREATE C,
DOES> C@ 0 0 ROT BUILD/SEND ;
'Y EMPTY-FRAME (ACK 'N EMPTY-FRAME (NAK
'Z EMPTY-FRAME EOF 'B EMPTY-FRAME EOT
'A EMPTY-FRAME ATTRIB 'E EMPTY-FRAME ERROR
: ACK ( seq# -) SEQ @ SWAP SEQ ! (ACK SEQ ! ;
: NAK ( seq# -) SEQ @ SWAP SEQ ! (NAK SEQ ! ;
( KERMIT)
VARIABLE EXPECTED
: INBUF! ( c -) IN-BUF INLEN @ + C! 1 INLEN +! ;
: SETLENGTH ( clength -)
INLEN OFF DUP INBUF! ( c) UNCHAR EXPECTED ! ;
: PUT-IN-BUFFER ( c - f) INBUF! INLEN @ EXPECTED @ > ;
( KERMIT)
: GETFRAME ( - type f)
BEGIN KSER-IN NIP UNTIL ( ) ( ie await SOH)
BEGIN
BEGIN KSER-IN WHILE DROP REPEAT ( c) SETLENGTH ( )
BEGIN KSER-IN NOT WHILE ( c) PUT-IN-BUFFER ( f)
IF IN-BUF >TYPE C@ CKSUM?
OVER 'E = OVER AND ABORT" Fatal Error in Kermit"
EXIT THEN ( )
REPEAT ( c) DROP
AGAIN ( type f) ;
( KERMIT)
: GET-GOOD-FRAME ( - type)
BEGIN GETFRAME ( type cksumflag) NOT WHILE
." bad cksum " DROP REPEAT ;
: IN-SEQ ( - u) IN-BUF >SEQ C@ UNCHAR ;
: GOOD-SEQ? ( - f) IN-SEQ SEQ @ = ;
( KERMIT)
: (GETACK ( - type)
BEGIN GETFRAME ( type f) NOT WHILE DROP REPEAT ( type) ;
: GETACK ( -)
BEGIN (GETACK ( type)
'Y OF GOOD-SEQ? ( f) DUP IF BUMPSEQ THEN ( f) ELSE
'N OF GOOD-SEQ? IF SENDFRAME THEN 0 ELSE
'V OF SENDFRAME 0 ELSE
( default) DROP 0 [ 3 ] THENS ( f)
UNTIL ;
: READ ( h - a #) PUSH 32767 BUFFER ( ie dummy buffer)
DUP 1024 POP FILE-READ #BYTES-READ @ ;
( KERMIT)
: GET-FIRST-NAK ( -) BEGIN (GETACK 'N = UNTIL ;
: SEND ( name -) CLS " Waiting to send " .MSG INIT-LIMITS
DUP FOPEN IF CR ." cannot open input file" CR EXIT THEN
( name h) 1000 MS ( name h) GET-FIRST-NAK
( n h) KINIT RESET-SER-IN GETACK
COMPROMISE SWAP COUNT ( h a #) FILEHEADER ( h) GETACK
BEGIN ( h) DUP READ DUP WHILE ( h a #)
BEGIN 'D BUILD-FRAME SENDFRAME GETACK '. EMIT
DUP 0= UNTIL 2DROP
REPEAT 2DROP ( h) FCLOSE ( ) EMPTY-BUFFERS ( just in case)
EOF GETACK EOT GETACK ;
( KERMIT)
CREATE IN-DATA MYMAXL 3 / 94 * 2 + ALLOT
: C!+ ( c a - a+) DUP PUSH C! POP 1+ ;
: C@+- ( fr # - fr # c) 1- PUSH C@+ POP SWAP ;
: UNCTRL'd ( from # c - from # c)
DUP QCTL @ - IF EXIT THEN DROP C@+- CTRL ;
( KERMIT)
: REPEAT'd ( to from # - to from #) ROT PUSH ( fr #)
C@+- UNCHAR PUSH C@+- ( fr # c) UNCTRL'd ( fr # c)
POP POP ( ie rpt# to) 2DUP + PUSH ( fr # c rpt# to)
SWAP ROT FILL ( fr #) POP ROT ROT ( to fr #) ;
: UNCTRL ( from to # - a #)
ROT PUSH PUSH DUP POP POP SWAP ( to to from #)
BEGIN DUP WHILE ( to to fr #)
C@+- DUP '~ = IF ( to to fr # c) DROP REPEAT'd
ELSE UNCTRL'd PUSH ROT POP SWAP C!+ ROT ROT THEN
REPEAT ( to to fr 0) 2DROP OVER - ( a #) ;
: >IN-DATA ( - a #) IN-BUF >DATA IN-DATA ( from to)
IN-BUF C@ UNCHAR 3 - ( from to #) UNCTRL ;
( KERMIT)
VARIABLE KHANDLE
CREATE KFNAME 50 ALLOT
: BUILDFNAME ( -)
>IN-DATA ( a #) DUP PUSH KFNAME 1+ SWAP CMOVE ( )
0 KFNAME R@ + 1+ C! ( make name into an asciiz string)
POP KFNAME C! ;
: RCVNAME ( -)
BUILDFNAME KFNAME FMAKE ( h f)
ABORT" cannot open output file" ( h) KHANDLE !
" receiving file " .MSG KFNAME COUNT TYPE SPACE ;
( KERMIT)
: GETNEXT ( - type)
BEGIN GETFRAME ( type f)
IF ( type) DUP 'V =
IF ( type) SEQ @ NAK -1 ( type f)
ELSE ( type) IN-SEQ DUP ACK ( type seq) SEQ @ -
THEN
ELSE
( ie bad cksum)
SEQ @ NAK -1 ( type f) ( -1 ABORT" BAD CKSUM" )
THEN
WHILE DROP
REPEAT BUMPSEQ ;
: WRITE ( -) >IN-DATA KHANDLE @ ( a # h) FILE-WRITE ;
( KERMIT)
: RECEIVE ( -) CLS " Waiting to receive " .MSG
RESET-SER-IN INIT-LIMITS
BEGIN 0 NAK 1000 MS GET-GOOD-FRAME 'S = UNTIL
( ) KINITACK BUMPSEQ
BEGIN GETNEXT ( type) ( DUP EMIT )
'D OF WRITE '. EMIT 0 ELSE
'F OF RCVNAME 0 ELSE
'Z OF KHANDLE @ FCLOSE 0 ELSE
'B OF -1 ELSE
( otherwise) DROP 0 [ 4 ] THENS
UNTIL ( ) ;
(end file pfkerm.src)