|
|
DataMuseum.dkPresents historical artifacts from the history of: RC3500 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC3500 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 20736 (0x5100)
Types: TextFileVerbose
Names: »ww«
└─⟦a41ae585a⟧ Bits:30001842 SW-save af projekt 1000, Alarm-system
└─⟦72244f0ef⟧
└─⟦this⟧ »ww«
job jg 8 200 time 6 0 area 10 size 100000
(source= copy 25.1
festrlst=set 1 disc1
festrlst= indent source mark lc
listc= cross festrlst
o errors
head 1
message festr program
pascal80 spacing.3000 codesize.3000 evaenv alarmenv feaosenv source
o c
lookup pass6code
if ok.yes
(festrbin= set 1 disc1
festrbin= move pass6code
scope user festrbin
)
festrlst= copy listc errors
scope user festrlst
convert errors
finis
)
process streamer(
var input_sem, xmitter, receiver : ! ts_pointer;
retrans_max : integer;
op : sempointer);
const
output_buffers = 2;
input_buffers = 2;
own_data_size = 8; (* bytes *)
sense_com = 0;
write_data = 2;
write_read_data= 3;
regret_input = 4;
input = 5;
output = 6; <* output = input + 1 is demanded *>
tell_next_notice=8;
read_stream = 9;
write_stream =10;
regret_output =12;
const
chain_in = 8;
chain_out = 8;
restart_notices= 1;
noticed_output = 2;
received_input = 3;
ready_request = 4;
free_in = 5;
free_out = 6;
chain_max = 6 + chain_in + chain_out;
type
chain_rec = record
next, prev, c_stream, c_func : byte;
ref : reference;
end;
chain_mem = array(1..chain_max) of chain_rec;
var
chain : chain_mem;
const
request = 0;
notice = 0;
master_out = 1;
no_stream = 0;
max_stream =63;
stream_size =max_stream + 1;
master_block = 256 div stream_size - 1;
master_size = 2;
buffer_size = stream_size div master_size;
ok_result = 0;
rejected = 1;
soft_error = 2;
(* *) blocklength_error = 64;
hard_error = 3;
un_intelligible= 4;
master = 5;
overload = 6;
max_integer = 32767;
type
data_buffer = record
first, last, next : integer;
end;
own_data = record
first, last, next : integer;
d : array(1..own_data_size div 2) of integer;
end;
var
header, sense_device, desc_header, message : reference;
waiting_output,
out_desc_sem,
pending_input, in_desc_sem : semaphore;
output_stopped, input_stopped: boolean;
notices_received: packed array(0..max_stream) of byte ;
xmit_pool : pool output_buffers + output_buffers;
sense_pool : pool input_buffers + output_buffers;
receive_pool : pool input_buffers + buffer_size;
message_pool : pool input_buffers of own_data;
operation, result, status, stream , result_modif,
output_block_no, input_block_no : integer;
procedure move_element(from, into : integer);
var fn, fp, tn : integer;
begin
with chain(into) do
begin
tn := next; next := from;
end;
with chain(from) do
begin
fn := next; fp := prev;
next := tn ; prev := into;
end;
chain(fp).next := fn ;
chain(fn).prev := fp ;
chain(tn).prev := from;
end (* procedure move chain-element *) ;
function search_sem(var s: semaphore): integer;
var stream, stop : byte;
begin
with message^ do
begin
stop := u1; stream := u3;
end;
search_sem := 0;
repeat
signal(message, s);
wait(message, s);
with message^ do
if u1 <> stop then
if u3 div stream_size <> master_block then
if u3 mod stream_size = stream then search_sem := 1;
until stop = message^.u1;
end (* procedure to find a specific stream request on a semaphore *) ;
function search_chain(start, stream, func_code : integer; no_regret:boolean) : integer;
var last, s, f : byte;
begin
search_chain := 0;
last := start;
start := chain(start).next;
while start <> last do
with chain(start) do
begin
if nil(ref) then
begin
s := c_stream; f := c_func;
if no_regret then f := sense_com;
end else
with ref^ do
begin
s := u3; f := u1;
end;
if (s = stream) and (f = func_code) then
begin
search_chain := start;
start := last ;
end else
begin
start := next ;
end;
end;
end (* procedure search chain for stream-number *) ;
procedure decode_message(var operation, result : integer);
var user_result, block_no : integer;
label comp_result;
begin
pop(header, message);
with header^ do
begin
result := u2 mod 8;
result_modif := u2 - result;
if u1 = write_read_data then
begin
user_result := ok_result;
operation := u4 mod master_size + input;
comp_result:
case result of
ok_result, soft_error:
begin
block_no := u3 div stream_size;
if block_no = master_block then
begin
result := master;
end else
if block_no <> u4 div stream_size then
begin
result := master;
end;
end;
▶18◀ hard_error: ;
rejected : ;
otherwise begin
user_result := un_intelligible;
result := result - un_intelligible;
goto comp_result;
end;
end;
end else
begin
operation := u1;
user_result:= u2;
push(header, message);
end;
end;
if not nil(message) then
begin
message^.u2 := user_result;
end;
end (* decode the received message *) ;
procedure next_notice(var stream : integer);
var r : reference;
ptr : integer;
begin
with chain(restart_notices) do
if prev <> restart_notices then
begin
stream := chain(next).ref^.u3;
move_element(next, chain(noticed_output).prev);
end else
with chain(free_out) do
if prev = free_out then
begin
stream := no_stream;
end else
begin
sensesem(r, waiting_output);
if nil(r) then
begin
stream := no_stream;
end else
begin
stream := r^.u3;
ptr := search_chain(noticed_output, stream, write_stream, false);
if ptr = 0 then ptr := next else
if not nil(chain(ptr).ref) then ptr := next;
chain(ptr).ref :=: r;
if ptr = next then
move_element(next, chain(noticed_output).prev) else
stream := no_stream;
end;
end;
end (* procedure to find the next notice *) ;
procedure return_output(result : integer);
begin
if not nil(message) then
begin
with message^ do u2 := u2 + result;
return(message);
end;
end (* procedure to return output-data to the user *) ;
procedure xqt_request;
var stream, ptr : integer;
begin
stream := header^.u3 mod stream_size;
if stream <> no_stream then
begin
ptr := search_chain(noticed_output, stream, write_stream, false);
message :=: chain(ptr).ref ;
move_element(ptr, free_out);
end;
end (* procedure to find the requested data *) ;
procedure xmit(operation, status : integer);
var block_no, stream, buffers : integer;
begin
if operation = notice then
begin
block_no := output_block_no mod 3;
buffers := 0;
next_notice(stream);
end else
begin
stream := output_buffers*master_size + status;
block_no:= master_block;
buffers := output_buffers;
alloc(sense_device, sense_pool, input_sem.w^);
sense_device^.u1 := sense_com;
signal(sense_device, xmitter.s^);
end;
desc_header^.u3 := block_no*stream_size + stream;
with header^ do
begin
u1 := write_read_data;
u3 := desc_header^.u3;
u4 := block_no*stream_size + buffers*master_size + 1;
end;
signal(desc_header, out_desc_sem);
push(header, message);
signal(message, xmitter.s^);
if output_block_no = max_integer then output_block_no := -1;
output_block_no := output_block_no + 1;
end (* procedure to send a new data-buffer to the transmitter *) ;
procedure restart_xmitter(receiver_buffers : integer);
var ptr : integer;
begin
ptr := restart_notices;
with chain(noticed_output) do
while noticed_output <> prev do
begin
move_element(next, ptr);
ptr := chain(ptr).next ;
end;
output_stopped := false;
output_block_no := 0;
for ptr := 1 to output_buffers do
begin
alloc(desc_header, xmit_pool, out_desc_sem);
alloc(header, xmit_pool , input_sem.w^);
xmit(notice, 0);
end;
end (* restart of the transmitter *) ;
function master_match(var received, xmitted : integer): boolean;
begin
master_match := false;
with desc_header^ do
if u3 div stream_size = master_block then
begin
master_match := true;
xmitted := u3 mod master_size;
if received = master then
received := header^.u3 mod master_size else
received := -1;
end;
end (* procedure to test if a master-out is answered with master-in *) ;
procedure return_input(result : integer);
begin
if not nil(message) then
begin
lock message as d:data_buffer do with d do
if next - first <= 1 then
begin
next := first;
if result = ok_result then result := rejected;
end;
with message^ do u2 := u2 + result;
return(message);
end;
end (* procedure to return input buffers to the user *) ;
procedure xqt_notice;
var stream, ptr, notice_no : integer;
begin
stream := header^.u3 mod stream_size;
if stream <> no_stream then
begin
notice_no := notices_received(stream);
if notice_no = 0 then
begin
ptr := search_chain(received_input, stream, read_stream, false);
if ptr = 0 then
begin
notice_no := 1;
ptr := search_chain(received_input, stream, tell_next_notice, false);
if ptr <> 0 then
begin
message :=: chain(ptr).ref;
message^.u2 := ok_result;
return(message);
move_element(ptr, free_in);
end;
end else
begin
move_element(ptr, chain(ready_request).prev);
end;
end else
begin
notice_no := notice_no + 1;
end;
notices_received(stream) := notice_no;
end;
end (* procedure to execute a notice *) ;
procedure place_input(el:integer; var in_ref: reference);
var stream, n : integer;
begin
stream := in_ref^.u3;
n := notices_received(stream);
if n > 0 then
begin
if in_ref^.u1 = tell_next_notice then
begin
n := 0;
end else
begin
notices_received(stream) := n -1;
n := ready_request;
end;
end else
begin
n := received_input;
end;
if n > 0 then
begin
chain(el).ref :=: in_ref;
move_element(el, chain(n).prev);
end else
begin
in_ref^.u2 := ok_result;
return(in_ref);
end;
end (* procedure to place incoming input-request *) ;
procedure next_request(var stream : integer);
begin
with chain(ready_request) do
if prev = ready_request then
begin
stream := no_stream;
end else
begin
message :=: chain(next).ref;
stream := message^.u3;
move_element(next, free_in);
end;
end (* procedure to find the next request *) ;
procedure send_input;
begin
wait(message, pending_input);
pop(desc_header, message);
signal(desc_header, in_desc_sem);
lock header as buf:own_data do
with buf do
begin
first := 6;
if nil(message) then last := own_data_size else last := 0;
last := first + last - 1;
next := first;
end;
push(header, message);
signal(message, receiver.s^);
input_block_no := (input_block_no + 1) mod 3;
end (* procedure to send the next input message *) ;
procedure receive(operation, status : integer);
var block_no, stream, buffers, expected_block : integer;
begin
if operation = request then
begin
buffers := 0;
block_no := input_block_no;
expected_block := (block_no+1)mod 3;
next_request(stream);
end else
begin
alloc(sense_device, sense_pool, input_sem.w^);
sense_device^.u1 := sense_com;
signal(sense_device, receiver.s^);
buffers := input_buffers;
stream := input_buffers*master_size + status;
block_no:= master_block;
expected_block := master_block;
end;
desc_header^.u3 := block_no*stream_size + stream;
with header^ do
begin
u1 := write_read_data;
u3 := desc_header^.u3;
u4 := expected_block*stream_size + buffers*master_size;
end;
push(desc_header, message);
signal(message, pending_input);
send_input;
end (* procedure to send the next receive-operation *) ;
procedure restart_receiver(buffering : integer);
var ptr : integer;
begin
ptr := received_input;
with chain(ready_request) do
while ready_request <> prev do
begin
move_element(next, ptr);
ptr := chain(ptr).next;
end;
for ptr := 0 to max_stream do
notices_received(ptr) := 0;
for ptr := 1 to buffering-1 do
begin
alloc(message, receive_pool, pending_input);
with message^ do
begin
u1 := 0; u2 := 0;
u3 := no_stream ;
end;
return(message);
end;
ptr := 1;
if not nil(desc_header) then
begin
with desc_header^ do
begin
u1 := 0; u2 := 0; u3 := no_stream;
end;
signal(desc_header, pending_input);
with header^ do
begin
u3 := (master_block*stream_size + input_buffers*master_size);
u4 := 0;
end;
send_input;
ptr := 2;
end;
input_block_no := 0; input_stopped := false;
for ptr := ptr to input_buffers do
begin
alloc(desc_header, receive_pool, in_desc_sem);
alloc(header, message_pool, input_sem.w^);
receive(request, 0);
end;
end (* procedure to restart the receiver *) ;
procedure test_master(trans_mitter : boolean; answer : integer);
var sent, count : integer;
begin
if master_match(answer, sent) then
begin
if answer = 0 then
begin
sent := (header^.u3 mod stream_size) div master_size;
if trans_mitter then
begin
release(header); release(desc_header);
restart_xmitter(sent);
end else
begin
restart_receiver(sent);
end;
end else
begin
if trans_mitter then count := -1 else count := 0;
if answer <> sent then
begin
sent := master_size;
count:= -1;
end;
sent := sent + count;
if trans_mitter then xmit(master_out, sent) else receive(master_out, sent);
end;
end else
begin
release(desc_header);
sent := (header^.u4 mod stream_size) div master_size;
if sent = 0 then
begin
release(header);
end else
begin
sent := sent*master_size + master_size - 1;
header^.u3 := master_block*stream_size + sent;
if trans_mitter then signal(header, xmitter.s^) else
if open(pending_input) then send_input else
signal(header, receiver.s^);
end;
end;
end (* procedure to master-clear the transmitter *) ;
procedure link_chain(head, start, stop : integer);
var i : integer;
begin
with chain(head) do
begin
next := start; prev := stop;
end;
for i := start to stop do
with chain(i) do
begin
next := i + 1;
prev := i - 1;
if i = start then prev := head;
if i = stop then next := head;
end;
end (* procedure to initialize a chain *);
begin
for input_block_no := 1 to chain_max do
with chain(input_block_no) do
begin
next := input_block_no; prev := next;
end;
link_chain(free_in, 7, 6 + chain_in);
link_chain(free_out, 7 + chain_in, chain_max);
restart_xmitter(1);
restart_receiver(1);
while true do
begin
wait(message, input_sem.w^);
decode_message(operation, result);
case operation of
sense_com,
write_data:
release(message);
regret_output:
begin
status := search_sem(out_desc_sem);
if status = 0 then
begin
status := search_chain(restart_notices, message^.u3, write_stream, true);
if status <> 0 then move_element(status, free_in) else
begin
status := search_chain(noticed_output, message^.u3, write_stream, true);
if status <> 0 then
with chain(status), ref^ do
begin
c_func := u1; c_stream := u3;
end;
end;
if status <> 0 then sense_device :=: chain(status).ref else
begin
status := search_sem(waiting_output);
if status <> 0 then
begin
stream := message^.u3;
repeat
if not nil(message) then signal(message, waiting_output);
wait(message, waiting_output);
operation := message^.u1;
if (message^.u3=stream) and (nil(sense_device)) then
sense_device :=: message;
until operation = regret_output;
end;
end;
if status <> 0 then status := ok_result else status := un_intelligible;
end else status := rejected;
message^.u2 := status;
push(message, sense_device);
return(sense_device);
end;
regret_input:
begin
status := search_sem(in_desc_sem);
if status = 0 then status := search_sem(pending_input);
if status = 0 then
begin
status := search_chain(ready_request, message^.u3, read_stream, false);
if status = 0 then
status := search_chain(received_input, message^.u3, read_stream, false);
if status = 0 then
begin
status := un_intelligible;
end else
begin
sense_device :=: chain(status).ref;
move_element(status, free_in);
status := ok_result;
end;
end else
begin
status := rejected;
end;
message^.u2 := status;
push(message, sense_device);
return(sense_device);
end;
write_stream:
signal(message, waiting_output);
read_stream, tell_next_notice:
with chain(free_in) do
if free_in = prev then
begin
with chain(received_input) do
if prev <> received_input then place_input(next, message);
message^.u2 := ok_result;
return_input(overload);
end else
begin
place_input(next, message);
end;
output:
begin
wait(desc_header, out_desc_sem);
if output_stopped then
begin
return_output(master);
test_master(true, result);
end else
begin
return_output(result + result_modif);
case result of
ok_result, soft_error:
begin
xqt_request;
operation := notice;
end;
otherwise
begin
output_stopped := true;
operation := master_out;
status := master_size - 1;
end;
end;
xmit(operation, status);
end;
end;
input:
begin
wait(desc_header, in_desc_sem);
if input_stopped then
begin
return_input(master);
test_master(false, result);
end else
begin
return_input(result+result_modif);
case result of
ok_result, soft_error:
begin
xqt_notice;
operation := request;
end;
otherwise
begin
input_stopped := true;
operation := master_out;
status := master_size - 1;
end;
end;
receive(operation, status);
end;
end;
otherwise
begin
message^.u2 := un_intelligible;
return(message);
end;
end;
end;
end.
«eof»