PACKET free channel DEFINES (* Autor: J.Liedtke *) (* Stand: 10.06.86 *) FCHANNEL , := , free channel , open , close , out , in , dialogue , save , fetch : LET ack = 0 , nak = 1 , error nak = 2 , empty message code = 256 , long message code = 257 , file send code = 1024 , file receive code = 2048 , open code = 1000 , close code = 1001 , file type = 1003 ; INT CONST task not existing := - 1 ; TYPE FCHANNEL = STRUCT (TASK server, TEXT input buffer, server name) ; INT VAR message code , response code ; TASK VAR partner ; DATASPACE VAR ds ; BOUND TEXT VAR msg ; TEXT VAR response, char, esc char , record ; FILE VAR file ; OP := (FCHANNEL VAR dest, FCHANNEL CONST source) : dest.server := source.server ; dest.input buffer := "" ; dest.server name := source.server name ; open (dest) ENDOP := ; FCHANNEL PROC free channel (TEXT CONST channel name) : FCHANNEL:(niltask,"", channel name) ENDPROC free channel ; PROC open (FCHANNEL VAR channel) : INT VAR receipt ; initialize message dataspace ; send open code ; IF receipt <> ack THEN errorstop ("channel not free") FI . initialize message dataspace : forget (ds) ; ds := nilspace . send open code : ping pong (channel.server, open code, ds, receipt) ; IF receipt = task not existing THEN channel.server := task (channel.server name) ; ping pong (channel.server, open code, ds, receipt) FI . ENDPROC open ; PROC close (FCHANNEL VAR channel) : forget (ds) ; ds := nilspace ; call (channel.server, close code, ds, response code) ENDPROC close ; PROC close (TEXT CONST channel server) : forget (ds) ; ds := nilspace ; call (task (channel server), close code, ds, response code) ENDPROC close ; PROC out (FCHANNEL VAR channel, TEXT CONST message) : send message ; get response . send message : IF message = "" THEN call (channel.server, empty message code, ds, response code) ELSE msg := ds ; CONCR (msg) := message ; call (channel.server, long message code, ds, response code) FI . get response : IF response code < 0 THEN errorstop ("channel not ready") ELIF response code < 256 THEN channel.input buffer CAT code (response code) ELIF response code = long message code THEN msg := ds ; channel.input buffer CAT CONCR (msg) FI . ENDPROC out ; PROC in (FCHANNEL VAR channel, TEXT VAR response) : out (channel, "") ; response := channel.input buffer ; channel.input buffer := "" ENDPROC in ; PROC save (FCHANNEL VAR channel, TEXT CONST file name, control chars) : prepare ds ; call (channel.server, file send code, ds, response code) ; IF response code = error nak THEN BOUND TEXT VAR error msg := ds ; errorstop (error msg) FI . prepare ds : forget (ds) ; ds := old (file name, file type) ; FILE VAR f := sequential file (modify, ds) ; headline (f, control chars) . ENDPROC save ; PROC fetch (FCHANNEL VAR channel, TEXT CONST file name, control chars) : IF NOT exists (file name) COR yes ("""" + file name + """ loeschen") THEN fetch first part ; WHILE more to fetch REP fetch next part PER FI . fetch first part : INT VAR part := 0 ; receive file (channel, file name, control chars) . fetch next part : part INCR 1 ; receive file (channel, file name + "." + text (part), control chars) . more to fetch : response code = file receive code . ENDPROC fetch ; PROC receive file (FCHANNEL VAR channel,TEXT CONST file name, control chars): prepare ds ; call (channel.server, file receive code, ds, response code); IF response code = error nak THEN BOUND TEXT VAR error msg := ds ; errorstop (error msg) ELSE forget (file name, quiet) ; copy (ds, file name) ; forget (ds) ; ds := nilspace ; FI . prepare ds : forget (ds) ; ds := nilspace ; BOUND TEXT VAR ctl := ds ; ctl := control chars . ENDPROC receive file ; PROC dialogue (FCHANNEL CONST channel, TEXT CONST esc) : forget (ds) ; ds := nilspace ; partner := channel.server ; esc char := esc ; enable stop ; response code := empty message code ; REP get and send message charety ; out response option PER . get and send message charety : IF response code = empty message code THEN char := incharety (10) ELSE char := incharety FI ; IF char = "" THEN call (partner, empty message code, ds, response code) ELIF char = esc char THEN LEAVE dialogue ELSE call (partner, code (char), ds, response code) FI . out response option : IF response code < 256 THEN out (code (response code)) ELIF response code = long message code THEN msg := ds ; out (CONCR (msg)) FI . ENDPROC dialogue ; PROC free channel (INT CONST nr) : INT CONST my channel := nr ; break ; disable stop ; REP wait (ds, message code, partner) ; IF message code = open code THEN connect to my channel ; use channel ; break (quiet) ELIF message code >= 0 THEN send (partner, nak, ds) FI PER . use channel : ping pong (partner, ack, ds, message code) ; WHILE message code <> close code AND message code >= 0 REP IF message code <= long message code THEN dialogue ELIF message code = file receive code THEN receive file ELIF message code = file send code THEN send file ELIF message code = open code THEN ignore open ELSE errorstop ("falsche Sendung") FI UNTIL is error PER ; IF is error THEN send error message ELSE send handshake ack FI . dialogue : IF message code < 256 THEN out (code (message code)) ELIF message code = long message code THEN msg := ds ; out (CONCR (msg)) FI ; response := incharety (1) ; IF response = "" THEN ping pong (partner, empty message code, ds, message code) ELSE short or long response FI . short or long response : char := incharety ; IF char = "" THEN short response ELSE long response FI . short response : ping pong (partner, code (response), ds, message code) . long response : msg := ds ; response CAT char ; msg := response ; REP cat input (msg, char) ; msg CAT char UNTIL char = "" OR LENGTH msg > 500 PER ; ping pong (partner, long message code, ds, message code) . connect to my channel : continue (my channel) ; WHILE is error REP clear error ; pause (100) ; continue (my channel) PER . send handshake ack : send (partner, ack, ds) . send error message : forget (ds) ; ds := nilspace ; BOUND TEXT VAR error msg := ds ; error msg := error message ; clear error ; send (partner, error nak, ds) . ignore open : ping pong (partner, ack, ds, message code) . ENDPROC free channel ; PROC send file : enable stop ; file := sequential file (input,ds) ; get control chars ; skip chars ; REP getline (file, record) ; out (record) ; end of line UNTIL eof (file) PER ; end of transmission ; send ack reply . get control chars : TEXT CONST control chars := headline (file) , end of file char := control chars SUB 1 , end of line char := control chars SUB 2 , handshake char := control chars SUB 3 . end of line : out (end of line char) ; IF handshake char <> "" THEN wait for handshake FI . wait for handshake : REP char := incharety (300) ; IF char = "" THEN errorstop ("timeout") FI UNTIL char = handshake char PER . end of transmission : skip chars ; out (end of file char) . skip chars : WHILE incharety (3) <> "" REP PER . send ack reply : forget (ds) ; ds := nilspace ; ping pong (partner, ack, ds, message code) . ENDPROC send file ; PROC receive file : enable stop ; get control chars ; open file ; INT VAR line no := 0 ; REP receive line ; IF eof received THEN ping pong (partner, ack, ds, message code) ; LEAVE receive file FI ; putline (file, record) ; line no INCR 1 UNTIL near file overflow PER ; ping pong (partner, file receive code, ds, message code) . get control chars : BOUND TEXT VAR control chars := ds ; TEXT CONST end of file char := control chars SUB 1 , end of line char := control chars SUB 2 , handshake char := control chars SUB 3 , handshake prompt := control chars SUB 4 . open file : forget (ds) ; ds := nilspace ; file := sequential file (output, ds) . receive line : record := "" ; REP cat input (record, char) ; IF char = "" THEN wait for char FI ; IF char = handshake prompt THEN out (handshake char) ELIF char = ""9"" THEN expand tabs ELIF char = ""12"" THEN page FI UNTIL char = end of line char OR char = end of file char PER . wait for char : char := incharety (300) ; IF char = "" THEN errorstop ("timeout") ELIF char >= ""32"" THEN record CAT char FI . expand tabs: record CAT (8-(LENGTH record MOD 8)) * " " . page: record := "#page# " . eof received : char = end of file char OR (record SUB LENGTH record ) = end of file char . near file overflow : line no > 3999 OR (line no > 3800 AND record = "#page# ") . ENDPROC receive file ; ENDPACKET free channel ;