|
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»