andyr@inmos.com (Andy Rabagliati) (04/19/91)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: fifo.occ fifoc.c inout.occ makefile test1c.c test1o.occ
# test2c.c test2o.occ
# Wrapped by andyr@inmos-c on Fri Apr 19 08:56:35 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'fifo.occ' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fifo.occ'\"
else
echo shar: Extracting \"'fifo.occ'\" \(1689 characters\)
sed "s/^X//" >'fifo.occ' <<'END_OF_FILE'
X--{{{ description of function
X-- fifo implements a true fifo - ready to input any time there is room, and
X-- ready to output any time there are characters in the buffer. Note that
X-- because we have no output ALT, this must be done with two processes.
X--
X-- input handles the resource of the buffer itself and the pointers into it,
X-- and services requests from two places. First, characters being input from
X-- in. Second, requests from the output process for new characters to
X-- output. These come in on channel signal. Responses to requests from
X-- signal go out on channel more.
X--
X-- There is no other way to handle this, given the CSP process model that the
X-- Transputer implements.
X--
X--}}}
XPROC fifo(CHAN OF BYTE in, out)
X VAL max IS 256 : -- max buffer size
X CHAN OF BOOL signal :
X CHAN OF BYTE more :
X PAR
X --{{{ input process and buffer
X [max] BYTE buffer :
X INT the.front, back :
X BOOL running :
X SEQ
X the.front, back, running := 0, 0, TRUE
X WHILE running OR (the.front <> back)
X INT front :
X BOOL any :
X SEQ
X front := (the.front+1) \ max
X ALT
X (the.front <> back) & signal ? any -- signal for more
X SEQ
X more ! buffer [back] -- send next
X running := buffer[back] <> '~' -- end condition test
X back := (back+1) \ max
X (front <> back) & in ? buffer[the.front]
X the.front := front
X --}}}
X --{{{ output process
X BYTE datum :
X SEQ
X datum := ' '
X WHILE datum <> '~'
X SEQ
X signal ! TRUE
X more ? datum
X out ! datum
X --}}}
X:
END_OF_FILE
if test 1689 -ne `wc -c <'fifo.occ'`; then
echo shar: \"'fifo.occ'\" unpacked with wrong size!
fi
# end of 'fifo.occ'
fi
if test -f 'fifoc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fifoc.c'\"
else
echo shar: Extracting \"'fifoc.c'\" \(2888 characters\)
sed "s/^X//" >'fifoc.c' <<'END_OF_FILE'
X#include <process.h>
X#define MAX 256
X#define NULL ((void *) 0)
X
X /*
X * fifo implements a true fifo - ready to input any time there is room, and
X * ready to output any time there are characters in the buffer. Note that
X * because we have no output ALT, this must be done with two processes.
X *
X * input_p handles the resource of the buffer itself and the pointers into it,
X * and services requests from two places. First, characters being input from
X * *in. Second, requests from the process output_p for new characters to
X * output. These come in on channel *signal. Responses to requests from
X * signal go out on channel *more.
X *
X * There is no other way to handle this, given the CSP process model that the
X * Transputer implements.
X *
X * output_p simply requests characters, then outputs them on channel *out.
X *
X * Please note the way guards on ALTs are implemented. There are slightly more
X * simple methods, but this is a very general mechanism. If the guard is
X * false, we put the channel always_empty in the alt list. Having an empty
X * channel means that the index returned by the ProcAltList function always
X * corresponds to the same input being ready. Very handy.
X *
X * Though in this case we will only be using always_empty in one place in the
X * alt list, it can be put in many places. Thus if we have a 100-way guarded
X * ALT, we only need one always_empty channel.
X *
X */
X
Xvoid input_p(Process * parent,
X Channel * in, Channel * signal, Channel * more)
X{
X Channel always_empty; /* remember to use & in refs */
X Channel *altlist[3];
X char buffer[MAX], lastchar = ' ';
X int the_front = 0, back = 0;
X ChanInit(&always_empty);
X altlist[2] = NULL; /* terminator for ProcAltList */
X
X while (lastchar != '~')
X {
X /* useful incremented version of the_front */
X int front = (the_front + 1) % MAX;
X altlist[0] = (the_front != back) ? signal : &always_empty;
X altlist[1] = (front != back) ? in : &always_empty;
X switch (ProcAltList(altlist))
X {
X case 0:
X ChanInChar(signal); /* must input signal !! */
X ChanOutChar(more, lastchar = buffer[back++]);
X back = back % MAX;
X break;
X case 1:
X buffer[the_front] = ChanInChar(in);
X the_front = front;
X break;
X }
X }
X}
X
Xvoid output_p(Process * parent,
X Channel * out, Channel * signal, Channel * more)
X{
X char c = ' ';
X while (c != '~')
X {
X ChanOutChar(signal, '*'); /* anything */
X ChanOutChar(out, c = ChanInChar(more));
X }
X}
X
Xvoid fifo(Process * parent, Channel * in, Channel * out)
X{
X Channel signal, more;
X ChanInit(&signal);
X ChanInit(&more);
X ProcPar(
X ProcAlloc(input_p, 100, 3, in, &signal, &more),
X ProcAlloc(output_p, 100, 3, out, &signal, &more),
X NULL );
X}
END_OF_FILE
if test 2888 -ne `wc -c <'fifoc.c'`; then
echo shar: \"'fifoc.c'\" unpacked with wrong size!
fi
# end of 'fifoc.c'
fi
if test -f 'inout.occ' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'inout.occ'\"
else
echo shar: Extracting \"'inout.occ'\" \(2002 characters\)
sed "s/^X//" >'inout.occ' <<'END_OF_FILE'
X-- The iserver routines can easily be replaced by similar ones in the hostio
X-- library. I just like to know exactly what is going on - this way nothing
X-- goes on the Transputer that I dont know about.
X-- This applies to write.char, pollkey, and so.exit.
X
XPROTOCOL SP IS INT16::[]BYTE :
X--{{{ PROC inout(CHAN OF SP fs, ts, CHAN OF BYTE out, in)
XPROC inout(CHAN OF SP fs, ts, CHAN OF BYTE out, in)
X -- routines similar to these are in hostio.lib
X --{{{ PROC write.char (VAL BYTE char)
X PROC write.char (VAL BYTE char)
X SEQ
X ts ! 8(INT16)::[24(BYTE), -- length, FPutBlock
X 1(BYTE), 0(BYTE), 0(BYTE), 0(BYTE), -- StreamId = 1
X 1(BYTE), 0(BYTE), -- INT16 len = 1
X char ]
X INT16 len :
X [8]BYTE packet :
X fs ? len::packet
X :
X --}}}
X --{{{ PROC pollkey(BYTE char, BYTE result)
X PROC pollkey(BYTE char, BYTE result)
X INT16 len :
X [8]BYTE packet :
X SEQ
X ts ! 8(INT16)::[31(BYTE), -- length, Pollkey
X 'x','x','x','x','x','x','x'] -- padding to 8 bytes
X fs ? len::packet -- read result
X char, result := packet[1], packet[0]
X :
X --}}}
X BYTE char :
X SEQ
X char := ' '
X WHILE char <> '~'
X TIMER TIME :
X INT now :
X SEQ
X TIME ? now
X ALT
X in ? char
X write.char(char)
X TIME ? AFTER now PLUS 156 -- 1/100 sec
X BYTE key, result :
X SEQ
X pollkey(key, result)
X IF
X result = 0(BYTE)
X out ! (BYTE key)
X TRUE
X SKIP
X:
X--}}}
X--{{{ PROC so.exit(CHAN OF SP fs, ts)
XPROC so.exit(CHAN OF SP fs, ts)
X SEQ
X ts ! 8(INT16)::[35(BYTE), -- length, Exit
X #FF(BYTE), #C9(BYTE), #9A(BYTE), #3B(BYTE), -- Success 999999999
X 'x','x','x'] -- padding
X INT16 len :
X [8]BYTE packet :
X fs ? len::packet
X:
X--}}}
END_OF_FILE
if test 2002 -ne `wc -c <'inout.occ'`; then
echo shar: \"'inout.occ'\" unpacked with wrong size!
fi
# end of 'inout.occ'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(1423 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
XOCCOPT= /y /t8
XLINKOPT= /y /t8
XCONFOPT=
XOCONFOPT=
XCOLLECTOPT= /t
XCOPT= /t8
X
Xtest2c: test2c.btl
X iserver /se /sb test2c.btl
X
Xtest2c.btl: test2c.lku
X icollect $(COLLECTOPT) test2c.lku
X
Xtest2c.lku: test2c.tco fifoc.tco
X ilink $(LINKOPT) test2c.tco fifoc.tco libc.lib centry.lib /me C.ENTRY
X
Xtest2c.tco: test2c.c
X icc $(COPT) test2c.c
X
Xfifoc.tco: fifoc.c
X icc $(COPT) fifoc.c
X
Xtest1c: test1c.btl
X iserver /se /sb test1c.btl
X
Xtest1c.btl: test1c.lku
X icollect $(COLLECTOPT) test1c.lku
X
Xtest1c.lku: test1c.tco
X ilink $(LINKOPT) test1c.tco libc.lib centry.lib /me C.ENTRY
X
Xtest1c.tco: test1c.c
X icc $(COPT) test1c.c
X
Xtest2o: test2o.btl
X iserver /se /sb test2o.btl
X
Xtest2o.btl: test2o.lku
X icollect $(COLLECTOPT) test2o.lku
X
Xtest2o.lku: test2o.tco inout.tco fifo.tco
X ilink $(LINKOPT) test2o.tco inout.tco fifo.tco
X
Xtest2o.tco: test2o.occ inout.tco fifo.tco
X oc $(OCCOPT) test2o.occ
X
Xtest1o: test1o.btl
X iserver /se /sb test1o.btl
X
Xtest1o.btl: test1o.lku
X icollect $(COLLECTOPT) test1o.lku
X
Xtest1o.lku: test1o.tco
X ilink $(LINKOPT) test1o.tco inout.tco
X
Xtest1o.tco: test1o.occ inout.tco
X oc $(OCCOPT) test1o.occ
X
Xinout.tco: inout.occ
X oc $(OCCOPT) inout.occ
X
Xfifo.tco: fifo.occ
X oc $(OCCOPT) fifo.occ
X
END_OF_FILE
if test 1423 -ne `wc -c <'makefile'`; then
echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'test1c.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test1c.c'\"
else
echo shar: Extracting \"'test1c.c'\" \(1905 characters\)
sed "s/^X//" >'test1c.c' <<'END_OF_FILE'
X#include <process.h>
X#include <stdio.h>
X#include <iocntrl.h>
X
X#define MAX 100
X
Xvoid buf (Process *parent, Channel *in, Channel *out) {
X char c = ' ';
X while (c!='~')
X ChanOutChar(out, c=ChanInChar(in));
X}
X
Xvoid buffer (Process *parent, Channel *in, Channel *out) {
X Channel pipe[MAX]; /* we are declaring the channels themselves,
X * so remember to use & address-of */
X Process *list[MAX+2]; /* will be MAX+1 processes */
X int i;
X
X for (i=0; i < (MAX-1); i++) {
X ChanInit(&pipe[i]); /* clear channel */
X list[i] = ProcAlloc(buf, 80, 2, &pipe[i], &pipe[i+1]);
X /* 80 bytes seems to be enough */
X }
X ChanInit(&pipe[MAX-1]); /* last pipe - not hit by loop above */
X
X list[MAX-1] = ProcAlloc(buf, 80, 2, in, &pipe[0]);
X list[MAX] = ProcAlloc(buf, 80, 2, &pipe[MAX-1], out);
X list[MAX+1] = NULL; /* end of list for ProcParList */
X
X ProcParList(list);
X}
X
Xvoid inout(Process *parent, Channel *out, Channel *in) {
X int key;
X char c = ' ';
X while (c!='~') {
X switch (ProcTimerAlt(ProcTimePlus(ProcTime(), 156), in, NULL)) {
X case -1:
X key = pollkey();
X if (key != -1)
X ChanOutChar(out, (char) key);
X break;
X case 0:
X putchar(c = ChanInChar(in));
X fflush(stdout);
X break;
X }
X }
X}
X
Xint main(void) {
X Channel to_buf, from_buf; /* we are declaring the channels themselves,
X * so remember to use & address-of */
X ChanInit(&to_buf);
X ChanInit(&from_buf);
X ProcPar(
X ProcAlloc(inout, 4096, 2, &to_buf, &from_buf),
X ProcAlloc(buffer, 4096, 2, &to_buf, &from_buf), NULL );
X
X return (999999999); /* success */
X}
X
END_OF_FILE
if test 1905 -ne `wc -c <'test1c.c'`; then
echo shar: \"'test1c.c'\" unpacked with wrong size!
fi
# end of 'test1c.c'
fi
if test -f 'test1o.occ' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test1o.occ'\"
else
echo shar: Extracting \"'test1o.occ'\" \(458 characters\)
sed "s/^X//" >'test1o.occ' <<'END_OF_FILE'
XPROTOCOL SP IS INT16::[]BYTE :
X#USE "inout.tco"
XPROC exercise1(CHAN OF SP fs, ts, []INT memory)
X SEQ
X VAL MAX IS 10 :
X [MAX+1]CHAN OF BYTE pipe :
X PAR
X inout(fs, ts, pipe[0], pipe[MAX])
X PAR i = 0 FOR MAX
X --{{{ little buffer processes
X BYTE char :
X SEQ
X char := ' '
X WHILE char <> '~'
X SEQ
X pipe[i] ? char
X pipe[i+1] ! char
X --}}}
X so.exit(fs, ts)
X:
END_OF_FILE
if test 458 -ne `wc -c <'test1o.occ'`; then
echo shar: \"'test1o.occ'\" unpacked with wrong size!
fi
# end of 'test1o.occ'
fi
if test -f 'test2c.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test2c.c'\"
else
echo shar: Extracting \"'test2c.c'\" \(1301 characters\)
sed "s/^X//" >'test2c.c' <<'END_OF_FILE'
X#include <process.h>
X#include <stdio.h>
X#include <iocntrl.h>
X
Xvoid fifo(Process *, Channel *, Channel *, Channel *);
X
X /*
X * inout is functionally equivalent to two parallel processes, one taking
X * keys from the keyboard and outputting them to *out, the other reading
X * characters from *in and writing them to the screen. It is in fact
X * implemented as an ALT, because both pseudo-processes need both iserver
X * channels.
X */
X
Xvoid inout(Process * parent, Channel * out, Channel * in)
X{
X int key;
X char c = ' ';
X while (c != '~')
X {
X switch (ProcTimerAlt(ProcTimePlus(ProcTime(), 156), in, NULL))
X {
X case -1: /* timeout - poll keyboard */
X key = pollkey();
X if (key != -1)
X ChanOutChar(out, (char) key);
X break;
X case 0: /* in is ready - read it */
X putchar(c = ChanInChar(in));
X fflush(stdout);
X break;
X }
X }
X}
X
Xint main(void)
X{
X Channel to_buf, from_buf; /* we are declaring the channels
X * themselves, so remember to use &
X * address-of */
X ChanInit(&to_buf);
X ChanInit(&from_buf);
X ProcPar(
X ProcAlloc(inout, 4096, 2, &to_buf, &from_buf),
X ProcAlloc(fifo, 4096, 2, &to_buf, &from_buf),
X NULL );
X
X return (999999999); /* success */
X}
END_OF_FILE
if test 1301 -ne `wc -c <'test2c.c'`; then
echo shar: \"'test2c.c'\" unpacked with wrong size!
fi
# end of 'test2c.c'
fi
if test -f 'test2o.occ' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test2o.occ'\"
else
echo shar: Extracting \"'test2o.occ'\" \(251 characters\)
sed "s/^X//" >'test2o.occ' <<'END_OF_FILE'
XPROTOCOL SP IS INT16::[]BYTE :
X#USE "inout.tco"
X#USE "fifo.tco"
XPROC exercise2(CHAN OF SP fs, ts, []INT memory)
X SEQ
X CHAN OF BYTE to.buf, from.buf :
X PAR
X inout(fs, ts, to.buf, from.buf)
X fifo(to.buf, from.buf)
X so.exit(fs, ts)
X:
END_OF_FILE
if test 251 -ne `wc -c <'test2o.occ'`; then
echo shar: \"'test2o.occ'\" unpacked with wrong size!
fi
# end of 'test2o.occ'
fi
echo shar: End of shell archive.
exit 0