|
|
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: 36864 (0x9000)
Types: TextFileVerbose
Names: »stdroutines«
└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system
└─⟦6b41451d2⟧
└─⟦this⟧ »stdroutines«
prefix break;
procedure break(var sh : shadow; excode : integer);
(********************************************************************)
(* *)
(* break *)
(* *)
(********************************************************************)
const
break_exception = rsexcfirst + 1;
stop_command = 0;
start_command = 1;
var
semp : ^ semaphore;
boo : boolean;
begin
if nil(sh.r) then
excptcall(break_exception)
else
begin
checkstack(break_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
lock sh.r as p : ext_incarnation_descriptor do
asgnsempaddr(semp,p.exit_semaphore);
boo := not locked(semp^);
semp := own.secret_pointer^(monitorsem);
sh.r^.u1 := stop_command;
signal(sh.r,semp^);
wait(sh.r,own.exit_semaphore);
lock sh.r as p : ext_incarnation_descriptor do
with p do
if boo then
begin
exic := entry_point;
entry_point := exception_point;
exception_mask := excode;
dumplm := maxstack;
end;
sh.r^.u1 := start_command;
signal(sh.r,semp^);
wait(sh.r,own.exit_semaphore);
release(own.exitref)
end
end;
prefix copychm;
function copychm(var r1,r2 : reference) : integer;
(*************************************************************************)
(* *)
(* copychm *)
(* *)
(*************************************************************************)
const
ok = 0;
notok = 1;
var
boo : boolean;
begin
copychm := notok;
boo := empty(r1) and (not nil(r1)) and (not nil(r2));
if boo then
if (r1^.messagekind = 0) and (r2^.messagekind < 0) then
begin
r1^.messagekind := r2^.messagekind;
r1^.size := r2^.size;
copychm := ok
end
end;
prefix create;
function create(incarnation_name : alfa; proces : processrec; var sh : shadow; storage : integer):integer;
(********************************************************************)
(* *)
(* create *)
(* *)
(********************************************************************)
const
stopstate = -1;
(* allocator results *)
allocator_no_storage = 0;
(* create results *)
create_ok = 0;
shadow_def = 1;
process_not_linked = 2;
no_storage = 3;
(* process_descriptor linkstates *)
unlinked = 0;
internal_linked = 1;
external_linked = 2;
nil_value = addr(base_type(0,1,0,0,0),0);
minsize = 75;
var
stack : reference;
pointer : addr;
mstart : addr;
index : integer;
index1 : integer;
dope : dope_vector;
function udiv(a,b : integer) : integer;
external;
function umod(a,b : integer) : integer;
external;
function usub(a,b : integer) : integer;
external;
begin
if not nil(sh.r) then
create := shadow_def
else
if (storage > 0) and (storage <= minsize) then
create := no_storage (* just simple test... *)
else
(* check that a process is linked to the process descriptor *)
if proces.processref^.link_state = unlinked then
create := process_not_linked
else
begin
checkstack(create_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
(* init allocator request *)
with own.exitref^ do
begin
size := minint;
answer := ref(own.exit_semaphore);
if storage = 0 then
begin
with proces.processref^ do
begin
start := process_inf_ref;
if link_state = internal_linked then
lock own.exitref as p : process_inf do
storage := p.default_appetite
else
lock own.exitref as p : descriptor_segment do
storage := p.default_appetite
end
end;
u1 := 0 * 4;
u2 := 1; (* number of messages *)
if storage <= minsize then
storage := minint;
u3 := udiv(storage,256);
u4 := umod(storage,256);
end;
signal(own.exitref,own.secret_pointer^(allocsem)^);
wait(sh.r,own.exit_semaphore);
(* the request message is pushed on the *)
(* eventually allocated data message by the allocator *)
pop(own.exitref,sh.r);
if own.exitref^.u2 = allocator_no_storage then
(* shadow remains nill *)
create := no_storage
else
begin
sh.r^.answer := ref(own.exit_semaphore);
dope := dope_vector(range_descriptor(0,maxint),2);
with sh.r^ do
begin
index := udiv(start.disp,2);
mstart := start;
mstart.disp := 0;
end;
lock sh.r as inc : ext_incarnation_descriptor do
begin
with inc do
begin
pu := 0;
level := 0;
incstate := stopstate;
activequeue := addr_of(chain);
chainhead := nil_value;
exic := addr(base_type(0,0,0,0,0),0);
(* this assignment to exic must be synced with printexcept *)
dumpsf := sh.r^.start.disp + 1;
asgnaddrpref(processref,proces.processref);
index1 := index + usub(storage,1);
defineptr(pointer,mstart,index1,dope);
maxstack := pointer.disp + 1;
dumplm := maxstack;
dumpps := 0;
timer := 0;
semchain := nil_value;
refchain := nil_value;
shadowchain := nil_value;
msg_chain := nil_value;
exit_semaphore := nil_value;
delaychain := nil_value;
exitref := nil_value;
statistic := nil_value;
asgnaddrsec(secret_pointer,own.secret_pointer);
plinetable := nil_value;
incname := incarnation_name;
end;
with proces.processref ^ do
begin
own.exitref^.size := minint;
own.exitref^.start := process_inf_ref;
incarnationcount := incarnationcount + 1;
if link_state = internal_linked then
begin (* this begin_end is caused by the indent program *)
lock own.exitref as p : process_inf do
with p do
begin
inc.entry_point := entry_point;
inc.exception_point := exception_point;
inc.exit_point := exit_point;
inc.dumplu := last_param_offset;
end
end
else
begin (* external linked *)
lock own.exitref as p : descriptor_segment do
with p do
begin
inc.entry_point := entry_point;
inc.exception_point := exception_point;
inc.exit_point := exit_point;
inc.dumplu := last_param_offset;
end
end;
end; (* with *)
defineptr(pointer,mstart,index+(inc.dumplu-proces.size_of_params)div 2,dope);
copywords(pointer,proces.firstparam,proces.size_of_params div 2);
defineptr(pointer,mstart,index - 1 + inc.dumplu div 2,dope);
inc.dumplu := pointer.disp + 1;
sh.r^.u3 := stdpriority + 128;
create := create_ok;
end
end;
release(own.exitref);
end;
end;
prefix definetimer;
procedure definetimer (onoff: boolean);
var
lf, gf: addr;
begin
checkstack(20);
getlfgf (lf, gf);
wait (own.exitref, own.secret_pointer^(stopsem)^);
with own.exitref^ do
begin
u1 := 1;
u2 := ord(onoff); (* 0==off, 1==on *)
answer := ref(own.exit_semaphore);
start := gf;
end;
signal (own.exitref, own.secret_pointer^(iotimersem)^);
wait (own.exitref, own.exit_semaphore);
release (own.exitref);
end;
prefix empty;
function empty(var r : reference) : boolean;
(*******************************************************************)
(* *)
(* empty *)
(* *)
(*******************************************************************)
begin
empty := true;
if not nil(r) then
empty := nil(r^.stackchain)
end;
prefix exception;
procedure exception(cause : integer);
(*********************************************************************)
(* *)
(* exception *)
(* *)
(*********************************************************************)
const
kind = 0;
var
lf , gf : addr;
function udiv(a,b : integer) : integer;
external;
function umod(a,b : integer) : integer;
external;
begin
getlfgf(lf,gf);
own.dumpsf := lf.disp;
wait(own.exitref,own.secret_pointer^(stopsem)^);
with own.exitref ^ do
begin
size := minint; (* a whole memory module *)
start := gf;
<*
start.disp := start.disp - 1;
*>
answer := ref(own.exit_semaphore);
u1 := kind;
u2 := udiv(cause,256);
u3 := umod(cause,256);
end;
signal(own.exitref,own.secret_pointer^(exceptionsem)^);
wait(own.exitref,own.exit_semaphore);
release(own.exitref);
end;
;prefix ___exit___rc;
procedure ___exit___rc;
(*******************************************************************)
(* *)
(* exit *)
(* *)
(*******************************************************************)
(* this procedure is called when an
incarnation enters the exit_code *)
const
stop_command = 0;
start_command = 1;
external_linked = 2;
unload_command = 2;
var
msg1 : reference;
saved_sem : ^ semaphore;
sem_p : ^ semaphore;
boo : boolean;
lf, gf : addr;
begin
(* wait for remove from father *)
wait(own.exitref,own.exit_semaphore);
getlfgf (lf, gf);
with own.exitref^ do
begin
saved_sem := answer;
answer := ref(own.exit_semaphore);
size := minint;
(* also initialize message for: 'definetimer(false)' *)
u1 := 1; (* = define timer *)
u2 := 0; (* = false *)
start := gf; (* = own inc descr *)
end;
(* send 'definetimer' to iotimer-process *)
signal (own.exitref, own.secret_pointer^(iotimersem)^);
wait (own.exitref, own.exit_semaphore);
(* stop and unload all children *)
while not nil(own.shadowchain) do
begin
with own.shadowchain^ do
if not nil(r) then
begin
lock r as p : ext_incarnation_descriptor do
asgnsempaddr(sem_p,p.exit_semaphore);
boo := not locked(sem_p^);
sem_p := own.secret_pointer^(monitorsem);
r^.u1 := stop_command;
signal(r,sem_p^);
wait(r,own.exit_semaphore);
lock r as p : ext_incarnation_descriptor do
begin
p.level := 0; (* restart is on level 0 *)
if boo then
p.entry_point := p.exit_point;
end;
r^.u1 := start_command;
signal(r,sem_p^);
wait(r,own.exit_semaphore);
lock r as p : ext_incarnation_descriptor do
begin
(* the child is now waiting at *)
(* the beginning of its exitcode *)
asgnsempaddr(sem_p,p.exit_semaphore);
signal(own.exitref,sem_p^);
(* wait until the child has finished its cleanup *)
wait(own.exitref,own.exit_semaphore);
end;
r^.u1 := stop_command;
signal(r,own.secret_pointer^(monitorsem)^);
wait(r,own.exit_semaphore);
lock r as p : ext_incarnation_descriptor do
begin
own.exitref^.size := minint;
own.exitref^.start := p.processref;
lock own.exitref as proc : process_descriptor do
begin
p.incstate := proc.link_state; (* incstate used as work *)
p.timer := proc.incarnationcount; (* timer used as work *)
end;
if (p.incstate = external_linked) and (p.timer = 0) then
begin
own.exitref^.u1 := unload_command;
signal(own.exitref,own.secret_pointer^(linkersem)^);
wait(own.exitref,own.exit_semaphore);
end;
end;
r^.answer := r^.owner;
return (r); (* release stack of child *)
end;
own.shadowchain := own.shadowchain^.next;
end;
(* scan chain of messages allocated in this incarnation *)
while not nil(own.msg_chain) do
begin
with own.msg_chain^ do
begin
owner := own.secret_pointer^(deallocatorsem);
answer := owner;
end;
own.msg_chain := own.msg_chain^.msg_chain
end;
(* scan chain of reference variables *)
while not nil(own.refchain) do
begin
asgnaddrref(own.exit_point,own.refchain^); (* own.exit_point used as work *)
(* remove the eventually locked bit *)
own.exit_point.base.lockbit := 0;
asgnrefaddr(own.refchain^,own.exit_point);
if not nil(own.refchain^) then
begin
return(own.refchain^);
end;
nextrefp(own.refchain);
end;
(* scan chain of semaphores declared in this incarnation *)
(* only messages may be pending at a semaphore *)
(* because all children are removed at this point *)
sem_p := own.semchain;
while not nil(sem_p) do
begin
while open(sem_p^) do
begin
wait(msg1,sem_p^);
return(msg1)
end;
sem_p := sem_p^.semchain
end;
(* decrement incarnation count in process_descriptor *)
with own.processref^ do
incarnationcount := incarnationcount - 1;
(* return exit_message to father *)
own.exitref^.answer := saved_sem;
return(own.exitref);
(* do something until i die ! *)
wait(own.exitref,own.exit_semaphore)
end;
prefix _initpool_rc;
procedure _initpool_rc(var s : semaphore; number,msize : integer);
(**********************************************************************)
(* *)
(* initpool *)
(* *)
(**********************************************************************)
(* msize is number of words ! *)
const
opcode = 0;
initpool_exception = rsexcfirst + 0;
var
r : reference;
stack : reference;
function udiv(a,b : integer) : integer;
external;
function umod(a,b : integer) : integer;
external;
begin
checkstack(initpool_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
with own.exitref^ do
begin
u1 := opcode;
u2 := number;
if msize < 0 then
msize := minint;
u3 := udiv(msize,256);
u4 := umod(msize,256);
answer := ref(own.exit_semaphore);
end;
signal(own.exitref,own.secret_pointer^(allocsem)^);
wait(stack,own.exit_semaphore);
pop(own.exitref,stack);
if own.exitref^.u2 = 0 then
begin
release(own.exitref);
excptcall(initpool_exception);
end
else
begin
while not nil(stack) do
begin
pop(r,stack);
linkmessage(r);
r^.owner := ref(s);
release(r); (* signal(r,owner) *)
end;
release(own.exitref);
end;
end;
prefix link;
function link(external_name : alfa; var pr : process_descriptor) : integer;
(*******************************************************************)
(* *)
(* link *)
(* *)
(*******************************************************************)
const
link_command = 1;
ok = 0;
allready_linked = 6;
unlinked = 0;
internal_linked = 1;
external_linked = 2;
begin
<*
printnl;
printtext('link call ');
printtext(external_name);
*>
if pr.link_state <> unlinked then
link := allready_linked
else
begin
checkstack(link_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
pr.name := external_name;
with own.exitref^ do
begin
size := minint;
start := addr_of_proc(pr);
answer := ref(own.exit_semaphore);
u1 := link_command;
end;
signal(own.exitref,own.secret_pointer^(linkersem)^);
wait(own.exitref,own.exit_semaphore);
<*
printnl;
printtext('result = ');
printnumber(result,2);
printnl;
*>
if own.exitref^.u2 = ok then
with pr do
begin
link_state := external_linked;
incarnationcount := 0;
end;
link := own.exitref^.u2;
release(own.exitref);
end
end;
prefix remove;
procedure remove(var sh : shadow);
(*******************************************************************)
(* *)
(* remove *)
(* *)
(*******************************************************************)
const
remove_exception = rsexcfirst + 2;
stop_command = 0;
start_command = 1;
var
semp : ^ semaphore;
boo : boolean;
begin
with sh do
begin
if nil(r) then
excptcall(remove_exception)
else
begin
checkstack(remove_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
lock r as p : ext_incarnation_descriptor do
asgnsempaddr(semp,p.exit_semaphore);
boo := not locked(semp^);
semp := own.secret_pointer^(monitorsem);
r^.u1 := stop_command;
signal(r,semp^);
wait(r,own.exit_semaphore);
lock r as p : ext_incarnation_descriptor do
begin
p.level := 0;
if boo then
p.entry_point := p.exit_point;
end;
r^.u1 := start_command;
signal(r,semp^);
wait(r,own.exit_semaphore);
lock r as p : ext_incarnation_descriptor do
begin
(* set answer semaphore pointer *)
own.exitref^.answer := ref(own.exit_semaphore);
(* activate child waiting for this message in its exit_code *)
asgnsempaddr(semp,p.exit_semaphore);
signal(own.exitref,semp^);
(* wait for the dead child *)
wait(own.exitref,own.exit_semaphore)
end;
r^.u1 := stop_command; (* remove child from activequeue *)
signal(r,own.secret_pointer^(monitorsem)^);
wait(r,own.exit_semaphore);
r^.answer := r^.owner;
return(r);
release(own.exitref);
end
end
end;
prefix reservech;
function reservech(var ch_msg : reference; level,mask : integer) : integer;
(*********************************************************************)
(* *)
(* reservech *)
(* *)
(*********************************************************************)
const
opcode = 1;
notnil = 2;
function udiv(a,b : integer) : integer;
external;
function umod(a,b : integer) : integer;
external;
begin
if nil(ch_msg) then
begin
checkstack(reservech_appetite);
wait (own.exitref, own.secret_pointer^(stopsem)^);
with own.exitref^ do
begin
u1 := opcode;
u2 := level;
u3 := udiv(mask,256);
u4 := umod(mask,256);
answer := ref(own.exit_semaphore);
end;
signal(own.exitref,own.secret_pointer^(allocsem)^);
wait(ch_msg,own.exit_semaphore);
pop (own.exitref, ch_msg); (* seperate into r=ownmess, ch-msg=channel-mess *)
reservech := 1 - own.exitref^.u2;
release(own.exitref);
end
else
reservech := notnil
end;
prefix sendtimer;
procedure sendtimer(var r : reference);
(********************************************************************)
(* *)
(* sendtimer *)
(* *)
(********************************************************************)
begin
signal(r,own.secret_pointer^(timersem)^)
end;
prefix setpriority;
procedure setpriority(priority : integer);
(*******************************************************************)
(* *)
(* setpriority *)
(* *)
(*******************************************************************)
const
setpriority_command = 2;
var
lf,gf : addr;
begin
checkstack(20);
getlfgf(lf,gf);
wait(own.exitref,own.secret_pointer^(stopsem)^);
with own.exitref^ do
begin
u1 := setpriority_command;
if (priority>=minpriority) and (priority <= maxpriority) then
u3 := priority + 128;
answer := ref(own.exit_semaphore);
size := minint;
start := gf
end;
signal(own.exitref,own.secret_pointer^(monitorsem)^);
wait(own.exitref,own.exit_semaphore);
release(own.exitref);
end; (* setpriority *)
prefix start;
procedure start(var sh : shadow; priority : integer);
(********************************************************************)
(* *)
(* start *)
(* *)
(********************************************************************)
const
start_exception = rsexcfirst + 3;
start_command = 1;
begin
if nil(sh.r) then
excptcall(start_exception)
else
begin
checkstack(start_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
with sh.r^ do
begin
u1 := start_command;
if (priority >= minpriority) and (priority <= maxpriority) then
u3 := priority + 128;
end;
signal(sh.r,own.secret_pointer^(monitorsem)^);
wait(sh.r, own.exit_semaphore);
release(own.exitref);
end;
end;
prefix stop;
procedure stop(var sh : shadow);
(********************************************************************)
(* *)
(* stop *)
(* *)
(********************************************************************)
const
stop_exception = rsexcfirst + 4;
stop_command = 0;
begin
if nil(sh.r) then
excptcall(stop_exception)
else
begin
checkstack(stop_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
sh.r^.u1 := stop_command;
signal(sh.r,own.secret_pointer^(monitorsem)^);
wait(sh.r, own.exit_semaphore);
release(own.exitref);
end
end;
prefix unlink;
function unlink(var pr : process_descriptor) : integer;
(********************************************************************)
(* *)
(* unlink *)
(* *)
(********************************************************************)
const
ok = 0;
notlinked = 1;
process_active = 2;
unlinked = 0;
unload_command = 2;
var
result : integer;
begin
<*
printnl;
printtext('unlink call ');
printtext(pr.name);
*>
if pr.incarnationcount <> 0 then
unlink := process_active
else
begin
checkstack(unlink_appetite);
wait(own.exitref,own.secret_pointer^(stopsem)^);
with own.exitref^ do
begin
size := minint;
start := addr_of_proc(pr);
answer := ref(own.exit_semaphore);
u1 := unload_command;
end;
signal(own.exitref,own.secret_pointer^(linkersem)^);
wait(own.exitref,own.exit_semaphore);
<*
printnl;
printtext('result = ');
printnumber(result,2);
printnl;
*>
if own.exitref^.u2 = ok then
pr.link_state := unlinked;
unlink := own.exitref^.u2;
release(own.exitref)
end
end;
\f
prefix checkstack;
procedure checkstack(appetite : integer);
(************************************************************************)
(* *)
(* checkstack *)
(* *)
(************************************************************************)
begin
if appetite < 9 then
appetite := 0
else
appetite := appetite - 9;
bcheck
end;
\f
prefix openzone;
procedure openzone ( (* opens a zone for driver comm. *)
var z: zone; (* the zone to be opened *)
driv: ^semaphore; (* driver process sem *)
answ: ^semaphore; (* answers arrives here *)
bufs : integer; (* no of buffers *)
var home: pool 1; (* ownerpool for buffers *)
v1, v2, v3, v4: byte ); (* u values in message headers *)
const
output = 2;
firstbuf = 6; (* general driver buffer *)
type
buffer = record (* for driver comm. *)
first, (* pointer to 1st char *)
last, (* pointer to last output char *)
next: integer; (* pointer to last+1 input char *)
end;
begin
with z do
begin
driver:= driv;
answer:= answ;
u2val := v2;
state := 0;
readstate:= -1;
nextp:= firstbuf;
for bufs:= bufs downto 1 do
begin
alloc ( cur, home, answer^);
cur^.u1:= v1;
cur^.u2:= 0;
cur^.u3:= v3;
cur^.u4:= v4;
if ult(16383,cur^.size) then
lastpos := maxint
else
lastpos := cur^.size * 2 - 1;
lock cur as buf: buffer do with buf do
begin
first:= firstbuf;
last:= lastpos;
next:= first
end;
signal ( cur, free )
end
end
end (* of openzone *)
\f
prefix openopzone;
procedure openopzone ( (* opens a zone for operator comm. *)
var z: zone; (* the zone to be opened *)
driv: ^semaphore; (* driver process sem *)
answ: ^semaphore; (* answers arrives here *)
bufs : integer; (* no of buffers *)
var home: pool 1; (* ownerpool for buffers *)
v1, v2, v3, v4: byte ); (* u values in message headers *)
const
output = 2;
firstbuf = 6+alfalength; (* operator buffer *)
type
opbuffer = record (* for operator comm. *)
first, (* pointer to 1st char *)
last, (* pointer to last output char *)
next: integer; (* pointer to last+1 input char *)
name: alfa; (* process inc name *)
end;
begin
with z do
begin
driver:= driv;
answer:= answ;
u2val := v2;
state := 0;
readstate:= -1;
nextp:= firstbuf;
for bufs:= bufs downto 1 do
begin
alloc ( cur, home, answer^);
cur^.u1:= v1;
cur^.u2:= 0;
cur^.u3:= v3;
cur^.u4:= v4;
if ult(16383,cur^.size) then
lastpos := maxint
else
lastpos := cur^.size * 2 - 1;
lock cur as buf: opbuffer do with buf do
begin
name:= own.incname;
first:= firstbuf;
last:= lastpos;
next:= first
end;
signal ( cur, free )
end
end
end (* of openopzone *)
\f
prefix alloc;
procedure alloc(var r : reference; var p : pool 1; var sem : semaphore);
(******************************************************************)
(* *)
(* alloc *)
(* *)
(******************************************************************)
begin
balloc
end;
\f
prefix outaddr;
procedure outaddr( var z : zone; a : addr );
begin
with a.base do
outhex(z,(((-lockbit*2+nill)*256+moduletype)*32+mem_no)*2+nullbit,4);
outchar(z,'.');
outhex(z,a.disp,4)
end; (* outaddr *)
\f
prefix outhex;
procedure outhex ( (* writes an integer as hexadecimal *)
var z: zone; (* specifies the document *)
num: integer; (* number to be written *)
pos: integer ); (* write positions *)
type
table = array (0..15) of char;
const
hextab = table ("0","1","2","3","4","5","6","7",
"8","9","a","b","c","d","e","f" );
var
bit0: byte:= 0;
begin
if num < 0 then
begin
bit0:= 8;
num:= num - minint;
end;
outfill ( z, sp, pos-4);
outchar ( z, hextab(bit0+num div (16*16*16)));
outchar ( z, hextab(num div (16*16) mod 16));
outchar ( z, hextab(num div 16 mod 16));
outchar ( z, hextab(num mod 16));
end (* of outhex *)
\f
prefix outdate;
procedure outdate(var z : zone; date : coded_date );
begin
with date do
begin
outinteger(z, year_after_1900 + 1900, 5);
outchar(z,'.');
if month < 10 then outchar(z,'0');
outinteger(z, month, 1);
outchar(z,'.');
if day < 10 then outchar(z,'0');
outinteger(z, day, 1 );
end;
end;
\f
prefix outtime;
procedure outtime ( var z : zone; time : coded_time );
begin
with time do
begin
if hour < 10 then outinteger(z, 0 , 1 );
outinteger(z, hour , 1 );
outchar(z, '.' );
if minute < 10 then outinteger(z, 0, 1 );
outinteger(z, minute , 1 );
end; (* with *)
end;
\f
prefix outinteger;
procedure outinteger ( (* write an integer as decimal *)
var z: zone; (* specifies the document *)
num: integer; (* the integer *)
pos: integer ); (* no of writepositions *)
(*
pos may give some spaces before the number, but all
digits are written.
*)
var
neg: boolean;
i: byte:= 1;
digits: array (1..5) of char;
begin
if num = minint then
begin
outfill ( z, sp, pos-6);
outtext ( z, "-32768# ")
end
else
begin
neg:= num < 0;
if neg then
begin
pos:= pos-1;
num:= -num
end;
repeat
digits(i):= chr ( num mod 10 + ord("0"));
num:= num div 10;
i:= i+1
until num = 0;
outfill ( z, sp, pos-i+1);
if neg then outchar ( z, "-");
for i:= i-1 downto 1 do outchar ( z, digits(i))
end
end (* of outinteger *)
\f
prefix opin;
procedure opin ( var z: zone); (* request input *)
var
msg: reference;
begin
with z do
if open ( free) then
begin
wait ( msg, free);
msg^.u2:= u2val;
signal ( msg, driver^)
end
end (* of opin *)
\f
prefix opanswer;
procedure opanswer ( (* transfers a message to zone z *)
var msg: reference; (* a message with operator input *)
var z: zone ); (* an input zone *)
begin
signal ( msg, z.dataready)
end (* of opanswer *)
\f
prefix optest;
function optest ( var z: zone ): boolean;
(*
optest is true if the zone has some data ready.
i. e. opwait will not wait.
*)
begin
optest := open ( z.dataready)
end (* of optest *)
\f
prefix opwait;
procedure opwait ( (* waits for input to z *)
var z: zone; (* specifies the document *)
var inputpool: pool 1 ); (* input buffer pool *)
const
read = 1;
type
zonebuffer = record
first, last, next: integer
end;
var
n: integer:= 0; (* msg counter *)
operatorinput: boolean;
begin
with z do
if nil ( cur) then
begin
if not open ( dataready) then (* wait for input answer *)
begin
repeat
wait ( cur, answer^);
operatorinput:= ownertest ( inputpool, cur) and ( cur^.u1 mod 8 = read);
signal ( cur, dataready);
n:= n+1
until operatorinput;
for n:= n downto 2 do (* send other messages back into queue *)
begin
wait ( cur, dataready);
signal ( cur, answer^);
end;
end;
wait ( cur, dataready);
state:= cur^.u2;
lock cur as buf: zonebuffer do nextp:= buf.first
end
end (* of opwait *)
\f
prefix ininteger;
procedure ininteger ( (* reads a decimal number *)
var z: zone; (* specifies the document *)
var num: integer ); (* value read or 0 *)
(*
syntax: (0..n)*(not digit), (0..1)*sign, (1..5)*digit
z.readstate = 0 if value assigned.
*)
const
max = 3276; (* max integer div 10 *)
digits = (. "0".."9" .);
wanted = (. "0".."9", nl .);
var
prev, t: char:= sp;
d: byte:= 0;
sign: integer;
begin
num:= 0;
repeat
prev:= t;
inchar ( z, t)
until t in wanted;
if t <> nl then (* a number is met *)
begin
if prev = "-" then sign:= -1 else sign:= +1;
while ( num < max ) and ( t in digits ) do
begin
num:= num*10 - ord("0") + ord( t);
inchar ( z, t)
end;
if ( num <= max ) and ( t in digits ) then (* include last digit *)
begin
d:= ord ( t) - ord("0");
if 2*d < 16-sign then (* accept *)
begin
num:= num*10;
z.nextp:= z.nextp+1
end
else d:= 0
end;
num:= sign*num + sign*d;
z.readstate:= 0;
z.nextp:= z.nextp-1
end
end (* of ininteger *)
\f
prefix inhex;
procedure inhex ( (* reads a hexadecimal number *)
var z: zone; (* specifies the document *)
var num: integer ); (* value read or 0 *)
(*
syntax: (0..n)*(not hexdigit), (1..4)*hexdigit
z.readstate = 0 if value assigned.
*)
const
hexdigits = (. "0".."9", "a".."f" .);
wanted = (. nl, "0".."9", "a".."f" .);
var
t: char;
a, b, c, d: byte:= 0; (* 4 digits *)
begin
num:= 0;
repeat inchar ( z, t) until t in wanted;
if t <> nl then (* a number is met *)
begin
while ( a = 0 ) and ( t in hexdigits ) do
begin
a:= b; b:= c; c:= d;
if ord ( t) <= ord ("9") then
d:= ord ( t) - ord ("0") else
d:= ord ( t) - ord ("a") + 10;
inchar ( z, t)
end;
num:= ((((a+8) mod 16 -8)*16+b)*16+c)*16+d;
z.readstate:= 0;
z.nextp:= z.nextp-1
end
end (* of inhex *)
\f
prefix inname;
procedure inname ( (* reads a name from z *)
var z: zone; (* specifies the document *)
var name: alfa ); (* inname *)
(*
syntax: (0..n)*sp, 1*letter, (0..11)*alfanum
readstate = 0 if name assigned.
you may initialize name before inname.
*)
const
letters = (. "A".."]", "_" , "a".."}" .);
alfanum = (. "A".."]", "_" , "a".."}", "0".."9" .);
var
t: char;
i: byte:= 0;
begin
repeat inchar ( z, t) until t <> sp;
if t in letters then (* read the name *)
begin
repeat
i:= i+1;
name(i):= t;
inchar ( z, t);
until ( i = alfalength ) or not ( t in alfanum );
z.readstate:= 0;
z.nextp:= z.nextp-1;
end
else
if z.readstate = 0 then
begin
z.nextp := z.nextp - 1;
z.readstate := 1
end
end (* of inname *)
\f
\f
prefix outnl;
procedure outnl( var z : zone );
begin
outchar(z,nl);
outend(z)
end; (* outnl *)
\f
prefix outfill;
procedure outfill ( (* repeated outchar *)
var z: zone; (* specifies the document *)
filler: char; (* character to be written *)
rep: integer ); (* repeat counter *)
begin
for rep:= rep downto 1 do outchar ( z, filler)
end (* of outfill *)
\f
prefix outtext;
procedure outtext ( (* writes text on z *)
var z: zone; (* specifies the document *)
text: alfa ); (* text to be written
# works as textstop *)
var
i: byte:= 1;
begin
while text(i) <> "#" do
begin
outchar ( z, text(i));
if i = alfalength then text(i):= "#" else i:= i+1
end
end (* of outtext *)
\f
prefix outchar;
procedure outchar ( (* writes 1 char in zone z *)
var z: zone; (* specifies the document *)
t: char ); (* character to be written *)
type
zonebuffer = record
first, last, next: integer;
end;
begin
with z do
begin
if nil ( cur) then (* get a buffer *)
begin
wait ( cur, free);
state:= cur^.u2;
lock cur as buf : zonebuffer do
nextp := buf.first
end;
lock cur as buf : array (0..lastpos) of char do
buf(nextp) := t;
nextp := uadd(nextp,1);
if ult(lastpos,nextp) then
outend(z)
end
end (* of outchar *)
\f
prefix inchar;
procedure inchar ( (* reads next character *)
var z: zone; (* specifies the document *)
var t: char ); (* delivered character or nl *)
begin
t:= nl;
with z do
if nil ( cur) then readstate:= -1
else
begin
readstate:= 0;
lock cur as buf : record
first,last,next : integer;
chars : array (6..lastpos) of char
end do
if ult(nextp,buf.next) then
t:= buf.chars(nextp)
else readstate:= -1;
if readstate = -1 then signal ( cur, free)
else
nextp := uadd(nextp,1)
end
end (* of inchar *)
\f
prefix outend;
procedure outend ( (* sends outputbuffer to driver *)
var z: zone ); (* specifies the document *)
type
zonebuffer = record
first, last, next: integer;
(* the rest is silence here *)
end;
begin
with z do
if not nil ( cur) then
begin
lock cur as buf: zonebuffer do buf.last:= nextp-1;
cur^.u2:= u2val;
signal ( cur, driver^)
end
end (* of outend *)
.
«eof»