|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 207360 (0x32a00) Types: TextFile Names: »D99«
└─⟦5dbd6b396⟧ Bits:30005867/disk12.imd Dokumenter (RCSL m.m.) └─⟦this⟧ »D99«
zone convert(10,1,stderror); integer array ia(1:20); getzone6 open(convert,0,<:dummy:',0); repeat write(convert,<<ddd.dd>dd', the number to be converted,false,2); comment the partial word has been forced into the buffer by the 2 null characters; getzone6(convert,ia); ia(12):= 1; ia(14):= ia(19); ia(16):= 40; setzone6(convert,ia); comment Now the record contains the number in character form. record base and partial word are ready for converting the next number; x1:= long convert(1); x2:= long convert(2); ... until ...; comment the zone convert must n_o_t_ be closed; E_x_a_m_p_l_e_ _3_: improved setposition: The procedures getposition, setposition do only enable a device to be positioned at the beginning of a block. You may resume reading from the middle of a block on magnetic tape or backing storage in this way: begin zone z(...), z1(...); integer array ia(1:20); integer pos1, pos2, pos3, pos4, c; integer field paritial _word, record _base, used _share, no _of _shares, base _buf _area, buf _length; partial _word := 12*2; record _base := 14*2; used _share := 17*2; no _of _shares := 18*2; base _buf _area := 19*2; buf _length := 20*2; \f comment generalised getposition;getzone6 read (z, ...); getposition (z, pos1, pos2); getzone6 (z, ia); pos3:= ia.record _base - ia.base _buf _area - ia.buf _length*4//ia.no _of _shares * (ia.used share-1); <*pos3 is the relative position within the used share*' pos4:= ia.partial _word; comment generalised setposition, perhaps with the device connected to another zone; setposition (z1, pos1, pos2); readchar (z1, c); <* now the device is positioned and the first block is read into the first share *' getzone6 (z1, ia); ia.record _base:= pos3 + ia.base _buf _area; ia.partial _word:= pos4; setzone6 (z1, ia); read (z1, ...); \f F_ 2_._5_9_ _ _ _ _ _ _g_o_t_o_ 2.59 goto This delimiter, which is a sequential operator, can be used to change the program flow. S_y_n_t_a_x_: goto <designational expression' S_e_m_a_n_t_i_c_: A goto statement interrupts the normal sequence of operations. The next statement to be executed will be the one having this value as its label. A jump (by a goto statement) out of an activity or a disable statement is not allowed. This will give the run time alarm "goto" (alarmcause = -14). A jump (by a goto statement) into a for-, repeat-, or while- statement is also forbidden. This will give the error message "for label" during the compilation. E_x_a_m_p_l_e_ _1_: a:= q; if a ' p then goto lab; .... lab: b:= a + 17; \f F_2_._6_0_ _ _ _ _ _ _g_r_e_a_t_e_r_ _t_h_a_n_ _(_'_)_ 2.60 greater than This delimiter, which is a relational operator, yields the value true or false. S_y_n_t_a_x_: <operand1' ' <operand2' P_r_i_o_r_i_t_y_: 5 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_s_: always boolean. S_e_m_a_n_t_i_c_: The relation takes on the value true whenever the corresponding relation is satisfied for the expressions involved, otherwise false. In case one of the operands is different from type integer the relation is executed as a subtraction. Thus you must be prepared for overflow, underflow, or spill (see example 3 of monitor). E_x_a_m_p_l_e_ _1_: a:= b ' c; if d ' q then ... else ...; while k ' l do ...; \f F_2_._6_1_ _ _ _ _ _ _g_r_e_a_t_e_r_ _t_h_a_n_ _o_r_ _e_q_u_a_l_ _(_'_=_)_ 2.61 greater than or equal This delimiter, which is a relational operator, yields the value true or false. S_y_n_t_a_x_: <operand1' '= <operand2' P_r_i_o_r_i_t_y_: 5 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: always boolean. S_e_m_a_n_t_i_c_: The relation takes on the value true whenever the corresponding relation is satisfied for the expressions involved, otherwise false. The relation is always executed as a subtrac- tion. Thus, you must be prepared for overflow, underflow, or spill. E_x_a_m_p_l_e_ _1_: q:= a '= c; if d '= k then ... else ...; while x '= y do ...; \f F_ 2_._6_2_ _ _ _ _ _ _i_m_p_l_i_c_a_t_i_o_n_ _(_=_'_)_ 2.62 implication This delimiter, which is a logical operator, yields the logical implication of the two operands. S_y_n_t_a_x_: <operand1' =' <operand2' P_r_i_o_r_i_t_y_: 9 O_p_e_r_a_n_d_ _t_y_p_e_s_: boolean R_e_s_u_l_t_ _t_y_p_e_: boolean. S_e_m_a_n_t_i_c_: The truth value is determined according to the following rule: right left true false true true false false true true \f F_ 2_._6_3_ _ _ _ _ _ _i_n_ 2.63 in This standard identifier is a preopened z_o_n_e_ available for input on character level. The actual file connected to the zone is determined by the file processor command which started the pro- gram (see ref. 15). The call <program' will let >in> be connected to the current input file of the file processor. The call <program' <text file' will let >in> be connected to the file <text file', if the program is not translated with the pa- rameter connect.no. The call <program' <integer' makes >in> and the file processor unavailable (but frees some space in the job area), if the program is translated with the parameter fp.no. When the program terminates, the latest operation on >in> must have been a call of a character reading procedure. E_x_a_m_p_l_e_ _1_: read (in,a,b,c); readchar (in,char); E_x_a_m_p_l_e_ _2_: prog= algol connect.no ... prog param ; the program will n_o_t_ use param ; as input text file. E_x_a_m_p_l_e_ _3_: prog= algol fp.no ... prog 7; in/out fp are removed from the process \f F_ 2_._6_4_ _ _ _ _ _ _i_n_c_r_e_a_s_e_ 2.64 increase This integer standard procedure is used in connection with a variable text as parameter to write, open etc. C_a_l_l_: increase (i) increase (return value, integer). The procedure performs: increase:= i; i:= i + 1; but i is only evaluated once. i (call and return value, integer). E_x_a_m_p_l_e_ _1_: This procedure could be used in a procedure call, where the formal parameter is a string, but the actual parameter is a real array, when the par- ameter is referenced only once. The zonerecord in zone z contains a text from element 4. This text can be written out by: i:= 4; write (out, string z (increase(i)); \f F_ 2_._6_5_ _ _ _ _ _ _i_n_i_t_k_e_y_ 2.65 initkey This standard procedure generates a piece of code for comparison of two records in a zone. Succeeding calls of the procedure newsort, outsort, and lifesort with the zone as parameter will cause this code to be used, provided the second parameter in the calls is omitted (see procedure newsort). This procedure is the A_L_G_O_L_5_ version of changekey6, and must not be used if the sorting was initiated by startsort6. C_a_l_l_: initkey (z, keydescr, n) z (call and return value, zone). The name of the zone used for sorting. keydescr (call value, array). A real array holding information about types and relative locations of the key field in a record (see below). n (call value, integer). Number of key fields (number of rows in keydescr). K_e_y_ _d_e_s_c_r_i_p_t_i_o_n_: The array keydescr must be declared as: array keydescr(1:n, 1:2); with the restriction: 1 <= n <= 4 * max. record length Each row in the array holds a description of a key field in the records to be sorted. The priority of the key decreases with increasing row number of their description, so the highest priority key is described in the first row, and so on. \f Column one holds information about key field initkey type and rule of sequencing. For the key field type the following conventions hold: v_a_l_u_e_ k_e_y_ _f_i_e_l_d_ _t_y_p_e_ +_1 12-bit integer +_2 24-bit integer +_4 48-bit real A long field or a 12-bit unsigned integer cannot be specified as a key field. The sign of the type descriptor indicates the rule of sequencing: plus for ascending, minus for descending. Column two is the relative location of the described field within a record. The meaning of this location is related to the key field type as follows (r stands for record length): k_e_y_ _f_i_e_l_d_ _t_y_p_e_ p_o_s_s_i_b_l_e_ _r_e_l_a_t_i_v_e_ _l_o_c_a_t_i_o_n_s_ 48-bit real 1,2,3,...,r-1,r 24-bit integer 1,1.5,2,2.5,...,r,r+0.5 12-bit integer 1,1.25,1.5,1.75,2,...,r,r+0.25, r+0.5,r+0.75 This means that the relative location of a key field is counted in fractions of reals. Z_o_n_e_ _s_t_a_t_e_: The zone state must be 9, in sort, i.e. initsort must have been called. The state is not changed by the procedure. \f E_x_a_m_p_l_e_ _1_: A certain sort key consists of an integer, two initkey halfwords and a real stored in this order in double words 2 and 3 of a record. The following sequence is wanted: 1. ascending on the real. 2. descending on the first halfword. 3. descending on the integer. 4. ascending on the second halfword. The following program will generate a proper code for comparison of two records. begin zone z(size, 1, error); real array crit(1:4, 1:2); crit(1,1):= 4; crit(1,2):= 3; crit(2,1):= -1; crit(2,2):= 2.5; crit(3,1):= -2; crit(3,2):= 2; crit(4,1):= 1; crit(4,2):= 2.75 initsort(z, length); initkey(z, crit, 4); ..... end; \f F_2_._6_6_ _ _ _ _ _ _i_n_i_t_s_o_r_t_ 2.66 initsort This standard procedure initiates a sorting process in a zone, so that the procedures newsort, outsort, deadsort, and lifesort can be used with that zone as a parameter. This procedure is the A_L_G_O_L_5_ version of startsort6, and must not be used together with changekey6. A call of initsort followed by a call of initkey is analoguos to a call of startsort6. C_a_l_l_: initsort (z, length) z (call and return value, zone). The name of the zone used for sorting. length (call value, integer). Max. length in double words of the records to enter the sorting process. Z_o_n_e_ A sort zone capable of holding N records at the d_e_c_l_a_r_a_t_i_o_n_: same time must be declared as follows: zone z((N+9)*(length+1), 1, error) where length is max. record length. The declaration has the same form as a zone declaration for input/output use with buffer length = (N+9)*(length+1) and no. of shares = 1. The error procedure must be supplied by the user, as described in startsort6. Z_o_n_e_ _s_t_a_t_e_: The zone must be in state 4, after declaration. The state becomes 9, in sort. \f F_ 2_._6_7_ _ _ _ _ _ _i_n_i_t_z_o_n_e_s_ 2.67 initzones This procedure changes the buffersize and number of shares of each zone in a zone array. C_a_l_l_: initzones (za, bufsize, shares) za (call and return value, zone array). The buffersize and number of shares are changed for all zones: za(1), za(2), ... za(no. of zones). The zone states must be 4 (after declara- tion) for all za(i). bufsize (call value, integer array). Bufsize(i) specifies the number of elements of 4 halfwords each in the bufferarea to be allocated to the zone za(i). shares (call value, integer array). Shares(i) specifies the number of shares to be assigned to za(i). N_o_t_e_: The sum of all bufsize(i), 1 <= i <= no _of _zones, must not exceed the original total buffer size for the zone array za, as determinated by the declara- tion. Obviously bufsize(i) and shares(i) must be positive integers. Z_o_n_e_ _s_t_a_t_e_: All zones of the zone array must be in state 4, after declaration. The zone state is not changed by the procedure. \f E_x_a_m_p_l_e_ _1_: The procedure can be used in a program where a num- initzones ber of files are handled by means of a logical file number, but the files use different block lengths: begin zone array za(n, total _bufsize//n, shares, stderror); integer array buf, sh(1:n); <* blocklength, no _of _shares*' buf(1):= 128; sh(1):= 1; <*file1: 1 1 *' buf(2):= 128*2; sh(2):= 2; <*file2: 1 2 *' buf(3):= 128*4; sh(3):= 1; <*file3: 4 1 *' ... initzones (za, buf, sh); ... open(z(i), ...); invar(z(i)); <* read from file no. i *' \f F_ 2_._6_8_ _ _ _ _ _ _i_n_r_e_c_ 2.68 inrec This integer standard procedure is the A_L_G_O_L_5_ version of inrec6. Inrec gets a sequence of elements of 4 halfwords each from a document and makes them available as a zone record. C_a_l_l_: inrec (z, length) inrec (return value, integer). The number of elements each of 4 halfwords in the present block for further calls of inrec. z (call and return value, zone). The name of the record. Determines further the document, the buffering, and the position of the document. length (call value, integer, long, or real). The number of elements of 4 halfwords each in the new record. Length must be '= 0. For further description see inrec6. Inrec may be used with advantage, if the do- cument is considered to contain reals. E_x_a_m_p_l_e_ _1_: Records of variable length may be handled in the Algol 5-way by means of inrec and outrec, but you should be careful: For magnetic tapes the record length should be checked in the block procedure to make sure that they match the block length. For backing storage areas the unused elements at the block end must be skipped (outrec clears them). Suppose the record length is stored as the first element of the record. The record may then be fetched in this way for all devices: \f for remaining:= inrec(z,1) while z(1)<= 0 do inrec inrec(z,remaining); comment unused elements are skipped; inrec(z, z(1) - 1); Another solution is to call the block procedure after all normal answers and let it adjust or check the z(1). N_o_t_e_ that the relation z(1) = 0 instead of z(1) <= 0 would not work because a backing storage area is filled up with binary zeroes. \f F_ 2_._6_9_ _ _ _ _ _ _i_n_r_e_c_6_ 2.69 inrec6 This integer standard procedure gets a sequence of halfwords from a document and makes them available as a zone record. The document may be scanned sequentially by means of inrec6, because the next call of inrec6 gets the elements just after those got now. C_a_l_l_: inrec6 (z, length) inrec6 (return value, integer). The number of halfwords left in the present block for further calls of inrec6. z (call and return value, zone). The name of the record. Determines further the document, the buffering, and the position of the document (see ref. 15). length (call value, integer, long, or real). The number of halfwords in the new record. Length must be '= 0. If length is odd, 1 is added to the call value. Z_o_n_e_ _s_t_a_t_e_: The zone z must be open and ready for record input (state 0 or 5, i.e. the zone must only have been used by inrec6, invar or the like since the latest call of open or setposition). To make sense, the document should be an internal process, a backing storage area, a typewriter, a paper tape reader, a card reader, or a magnetic tape. In the latter case setposition(z,...) must have been called after the call of open(z,...). B_l_o_c_k_i_n_g_: Inrec6 must be thought of as transferring the half- words just after the current logical position of the document and changing the logical position to after the last halfword of the record. \f However, all halfwords of the record are taken inrec6 from the same block, so if the record cannot be taken from the current block, the block is changed as described in ref. 15. Then the record becomes the first halfwords of that block, but if it still cannot hold the record the run is terminated (empty blocks are completely disregarded). Records of length 0 need a special explanation: if not even a single word is left in the block, the block is changed and the logical position points to just before the first word of the new block. At end of document the standard error action will simulate an "end block" containing one word of three end medium characters. So the call b:= inrec6(z,0) will in this case give the result b=2, and the "end block" may be read by inrec6(z,2). (This is not valid for inrec, as inrec cannot read less than 4 halfwords). Note that inrec6 changes the blocks in such a way that a portion at the end of a block may be skip- ped. So be careful to read a backing storage area with the same share length as that with which is was written, otherwise, wrong portions might be skipped at reading. E_x_a_m_p_l_e_ _1_: A simple scan of a file on a magnetic tape in dou- ble buffer mode may be programmed in this way (all records are assumed to be of 20 halfwords): \f begin inrec6 zone file(2*128,2,endfile); boolean in _file; integer i; procedure endfile(z,s,b); zone z; integer s,b; if s extract 1 = 1 then stderror(z,s,b) else if b ' 0 or s shift (-18) extract 1 = 1 then in _file:= false; open(file,18,<:mt600304:', 1 shift 18 + 1 shift 16); setposition (file,1,0); comment skip the label in file 0, in _file:= true; for i:= inrec6 (file, 20) while in _file do begin ... end; close(file,true); The scan is terminated by the procedure end- file which is called at tape mark (1 shift 16), end of tape (1 shift 18), and all hard errors. After the positioning (but before the first input operation) endfile may be called with tape mark indication. In this case howe- ver, b = 0, while b ' 0 after input of a tape mark. The same piece of code would work for an area on the backing store if the file was genera- ted with a share length of 128 elements of 4 halfwords and if the second and third parame- ter to open were changed. E_x_a_m_p_l_e_ _2_: Two files of 100 halfwords records on magne- tic tape are arranged in ascending order (sorted with respect to the key indicated by the integer field keyf). They may be merged into one file in this way: \f begin zone result(2*256,2,stderror); inrec6 zone array inp(2,2*256,2,endfile); procedure endfile(z,s,b); zone z; integer s,b; if s extract 1 ' 0 then stderror(z,s,b) else begin b:= 100; z.keyf:= large; comment the procedure simulates the presence of a record with a very large key; end; open(inp(1),...,1 shift 16); open (inp(2),... setposition ... setposition ... large:= (-1) shift (-1); inrec6(inp(1),100); inrec6(inp(2),100); for k:= if inp(1).keyf < inp(2).keyf then 1 else 2 while inp(k).keyf < large do begin outrec6(result,100); tofrom(result,inp(k),100); inrec6(inp(k),100); end; close(result, ...); E_x_a_m_p_l_e_ _3_: You may read a magnetic tape file or backing storage area block by block in this way: for b:= inrec6(z,0) while b ' 2 do begin comment b is now the block length in halfwords, the standard actions simulate one word containing <:<25'<25'<25':' at end of document; inrec6(z,b); comment the block is now available as one record; ... ; end; comment check that the last record is the simulated end block; inrec6(z,2); if z.firstword <' long <:<25'<25'<25':' shift (-24) extract 24 then error; \f F_ 2_._7_0_ _ _ _ _ _ _i_n_t_a_b_l_e_ 2.70 intable This standard procedure exchanges the current input alphabet used by all the read procedures on character level. C_a_l_l_: intable (alpha) or intable (0) alpha (call value, integer array of one dimension). Contains the character class and the value of each character in the new input alphabet as described below. 0 (call value, integer). A zero signals that the standard alphabet is to be used. i_n_t_a_b_l_e_ _(_a_l_p_h_a_)_: The actual contents of alpha are used in all calls of read proce- dures, until another array or the standard alphabet is selected. This means that any change in the contents of alpha may have ef- fects on the character reading. If a read procedure is called at a place where alpha is undeclared, an undefined alphabet is used. To each character >c> delivered by the peripheral device is associated a C_l_a_s_s_ and a V_a_l_u_e_, determined by the read procedures in this way: alpha(c+tableindex) = Class shift 12 + Value extract 12 Class is an integer 0 <= Class <= 4095. Value is an integer, -2048 <= Value <= 2047. The character >c> is an integer, 0 <= c <= 255. The ISO characters utilize only half of this interval. The standard integer >tableindex> is normally 0, but you may use it to modify the alphabet. The class determines how the value corresponding to a character is handled: \f Class = 0, blind: The character is skipped by all read proce- intable dures. Class = 1, shift character: The value is assigned to tableindex and the character is looked up again in the alphabet to determine Class and Value. Class = 2, digits: The character is a decimal digit the value of which is Value - 48. To make sense, 48 <= Value <= 57 should be fulfilled. Class = 3, signs: The character is the sign of a decimal number. Value = 43 means +, Value = 45 means -. Class = 4, decimal point: The character may be used as a decimal point. Class = 5, exponent mark: The character may be used as the > of Algol. Class = 6, letters: The character may be used as part of a text but not as part of a number. Class = 7, delimiter: The character cannot be part of a text or a number. Class = 8, terminator: The character is a delimiter as class 7, but it will terminate a call of readall. If value is 25, it will immediately terminate a call of read or readstring. Class ' 8, other delimiters: The character is handled as class 7. The elements 0:127 of alpha may be initialized with the ISO al- phabet by a call of the standard procedure isotable. i_n_t_a_b_l_e_ _(_0_)_: The standard alphabet given in ref. 14 is used until a new alphabet is selected. The value of tableindex has no influence on the alphabet. When the run starts, the standard alphabet is selected automatically. You should not hesitate to use a special alphabet table: The character reading will be speeded up compared to what you could do in algol with the standard alphabet, and the input algorithm becomes clearer. The table takes space, but remember that 2*128 integers correspond to one segment of a program (10 to 20 lines), and that much is easily saved in the central loop of the input program. \f E_x_a_m_p_l_e_ _1_: N_u_m_b_e_r_ _v_a_r_i_a_n_t_s_ intable Assume you want to read numbers coded in ISO but with space regarded as blind information and without exponent part. You may then proceed like this: isotable(table); table(32):= 0; table(39):= 7 shift 12 + 39; ... comment define space, apostrophe, and other special characters; intable(table); tableindex:= 0; read(z,...); E_x_a_m_p_l_e_ _2_: F_l_e_x_o_w_r_i_t_e_r_ _c_o_n_v_e_r_s_i_o_n_ It is possible to use the read procedure for input represented in flexowriter code if the underlining may be disregarded. The shift characters, class 1, may take care of the case shift characters. An alphabet table of 2*128 elements is required. One way of initialising the table goes like this: for i:= 0 step 1 until 255 do table(i):= (case i+1 of (0,2,2,2,2, 2,2,2,2,2, 0,8,8,6,0, 0,2,7,6,6, ...) shift 12 + (case i+1 of (32,49,50,51,52, 53,54,55,56,57, 0,12,25,125,0, 0,48,60,115,116, ... )); Upper case and Lower case require table(60):= 1 shift 12 + 128; table(60 + 128):= 0; table(58 + 128):= 1 shift 12 + 0; table(58):= 0; \f Note, that if the input was flexowriter paper intable tapes which were read in ISO-mode, the parity hole would not be the flexowriter parity hole, and as a consequence a different alphabet table would be needed. E_x_a_m_p_l_e_ _3_: begin .... begin integer array table (0:127); <* an alphabet is initialised in table *' table (32):= ... intable (table); tableindex:= 0; .... intable (0); <* if you forget returning to the standard alphabet before leaving the block where table is declared, an undefined alphabet will be used *' end block; ... end program E_x_a_m_p_l_e_ _4_: See example 3 of readall. \f F_ 2_._7_1_ _ _ _ _ _ _i_n_t_e_g_e_r_ 2.71 integer This delimiter, which is a declarator, is used in declaration and specifications of variables of type integer. S_y_n_t_a_x_: integer <namelist' S_e_m_a_n_t_i_c_: The variables in namelist will all be of type integer, and occupy 24 bits in the storage area. The value of an integer is in the interval: -8388608 <= value <= 8388607 E_x_a_m_p_l_e_ _1_: integer i1; integer i2, yes, no, price; procedure pip (a); integer a; \f F_ 2_._7_2_ _ _ _ _ _ _i_n_t_e_g_e_r_ _d_i_v_i_d_e_ _(_/_/_)_ 2.72 integer divide This delimiter, which is an arithmetic operator, performs an integer division. S_y_n_t_a_x_: <operand1' // <operand2' P_r_i_o_r_i_t_y_: 3 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer or long R_e_s_u_l_t_ _t_y_p_e_: When both operands are of type integer the result is of type integer, otherwise the result is of type long. S_e_m_a_n_t_i_c_: The result of the operator is defined as follows: a//b = sign (a/b)* entier(abs (a/b)) E_x_a_m_p_l_e_ _1_: a:= 35//12; <* a has the value 2 *' b:= -13//3; <* b has the value -4 *' \f F_2_._7_3_ _ _ _ _ _ _i_n_v_a_r_ 2.73 invar This standard integer procedure together with outvar, changevar, and checkvar are intended for easy handling of records of vari- able length. Every record must contain its own length in half- words in its first word, the l_e_n_g_t_h_ _w_o_r_d_. Invar makes the next record written by means of outvar available as a zone record. A record checksum in the second word may be checked, and the number of records are counted in the so called free parameter in the zone descriptor (see getzone6). This procedure may call the block procedure with the status 1 shift 11, checksum error, if the record length wanted is < 4 or ' remaining halfwords in the block or odd or if the checksum is calculated and not equal to the value of the second word in the record. C_a_l_l_: invar (z) invar (return value, integer). The number of halfwords left in the present block. z (call and return value, zone). The name of the record. Determines the document, the buffering, and the position of the document. Z_o_n_e_ _s_t_a_t_e_: The zone z must be open and ready for record input (state 0 or 5), i.e. the zone must only have been used by invar or the like since the latest call of open or setposition. F_r_e_e_ _p_a_r_a_m_e_t_e_r_:The free parameter in the zone descriptor is used to count the number of records accepted by invar. The value of this parameter is interpreted as check _wanted shift 23 + record _count where check _wanted = 1 means that a checksum is calcula- ted by invar and checked against the second word in the record. The free parameter could be set in the program by: getzone6(z,ia); ia(11):= 1 shift 23; setzone6(z,ia); See below for further details. \f B_l_o_c_k_i_n_g_: You may think of invar in the way that the procedure invar tests the value of the first word just after the cur- rent logical position of the document. Now invar ex- poses as many halfwords as the length word indicates, including the two halfwords of this word. However all halfwords must be taken from the same block. If this is not possible, the block procedure of the zone is called. See further on length errors below. If the length word is null, it is skipped and the next word from the document is tried as length word. When there are no more in a block, the block is changed. This covers skipping of blank block tails that may be generated by outvar when the kind of the document is backing storage (see outvar). L_e_n_g_t_h_ _e_r_r_o_r_s_._ _C_h_e_c_k_s_u_m_: If the length word is <' 0, it is expected to be even, '= 4 and <= the number of halfwords remaining in the present block. If not all three conditions are fulfilled, invar will give up and call the block pro- cedure (see below). When the length word has passed the tests above, the contents of the second word may be tested as a check sum of the record (see example 2 below). If check is wanted (see free parameter above), invar tests if the sum of all words in the record taken modulo 2**24 is equal to -3. If not, invar calls the block procedure. B_l_o_c_k_ _p_r_o_c_e_d_u_r_e_,_ _c_a_l_l_ _c_o_n_d_i_t_i_o_n_s_: Invar may call the block procedure in two diffe- rent situations: \f a) The length word is not sensible (see above). invar b) Record sumcheck is wanted, and the sum is not ok (see above). The call conditions for the parameters to the block procedure are: z: The zone state is after record input. The defect record is not counted in the free parameter. The record starts just before the length word and depends on the length word like this: record _length:= if length _word < 4 or length _word ' remaining then remaining else if record _length is odd then length _word + 1 else length _word. Remaining means the number of halfwords remaining in the present block including the length word. The terms zonestate, free parameter, and record length are explained in getzone6. s: The status word parameter has the value 1 shift 11. b: The halfwords transferred parameter is equal to the record length, described above. After return from the block procedure, invar re- starts its algorithm by fetching the next logical record. A defect record will thus be skipped if the block procedure simply ignores the call, (see example 2). \f E_x_a_m_p_l_e_ _1_: Your block procedure may test whether situation invar a) or situation b) above has caused the block procedure to be called. This may be done as follows: procedure blpr(z,s,b); zone z; integer s,b; begin ..... if s = 1 shift 11 then begin integer field lengthword; lengthword:= 2; if b < 4 then begin comment end of documment; ... end else if b <' z.lengthword then begin comment length error; ... end else begin comment checksum error; ... end; end ..... end; E_x_a_m_p_l_e_ _2_: A_t_t_e_m_p_t_ _t_o_ _r_e_p_a_i_r_ _a_ _d_e_f_e_c_t_ _r_e_c_o_r_d_. When you read a file from magnetic tape written by means of outvar, you may try to make sense of blocks with parity error and where the standard actions have given up. This will only be waste of machine power if all records are needed in a run. In such case it is better to give up once status errors occur. It must be recognized, however, that problems exist where it is essential to make as much sense out of a file as possible in one run and then try to pick up the defect records in a later run. \f A block procedure which counts the number of wrong invar >records> and only gives up when this number is too large may look something like this: procedure after _parity (z,s,b); zone z; integer s, b; begin own integer faults; integer field length; integer array ia (1:20); procedure drop; write (out, <:record dropped, expected::', z.length, <: dropped::', b, <: halfwords<10':'); length:= 2; if s shift (-18) extract 1 = 1 or s shift (-16) extract 1 = 1 then begin comment end of document or tapemark, simulate a dummy record and switch off the sum check, in order to prevent invar from calling the block procedure again; z.length:= b:= min _length; end _medium:= true; getzone6(z, ia); ia(11):= ia(11) extract 23; setzone6(z, ia); end else if s = 1 shift 11 then begin faults:= faults + 1; if faults ' max then stderror (z,s,b); if b <' z.length then drop else begin comment maybe only checksum error; if b<min _length or b'max _length then drop else \f begin invar comment now check the contents of the possible record. If it does not seem sensible then drop it, else set a mark that it may be erroneous; .... checkvar (z); changerec6 (z,0); comment force a new checksum into the record and regret the record so that invar may take it once more; end; end; end s = 1 shift 11 else if logand (s, -1 - (1 shift 22 <*parity error*' + 1 shift 15 <*writing enabled*' + 1 shift 1 <*normal answer*' + 1 shift 0 <*hard error*' )) <' 0 then stderror (z,s,b); comment give up if hard error, except in connection with parity error, ring indication, and/or normal answer; end after _parity; When the zone with this block procedure is opened, the give up mask should contain the tapemark bit (or end document bit if reading from backing storage), as standard action would simulate a dummy block of 2 halfwords, which invar would consider a length error. On the other hand the give up mask should not contain the parity error bit, as the standard action, 5 readings, is wanted for parity error. The bit for checksum wanted should be set in the free zone parameter (see getzone6): \f open(z,18,<:...:', 1 shift 18 + 1 shift 16); invar setposition(z,1,0); getzone6(z,ia); ia(11):= 1 shift 23; setzone6(z,ia); repeat invar(z); ..... handle the record, note the error-mark; until end _medium; E_x_a_m_p_l_e_ _3_: See example of changevar. \f F_ 2_._7_4_ _ _ _ _ _ _i_s_o_t_a_b_l_e_ 2.74 isotable This standard procedure initializes an array with the ISO character table for use in intable or outtable. C_a_l_l_: isotable (alpha) alpha (return value, integer array of one dimension). The elements alpha (0:127) of the array are initialized with class shift 12 + value of the ISO characters, as defined in ref. 14. E_x_a_m_p_l_e_ _1_: See example 1 of intable. \f F_2_._7_5_ _ _ _ _ _ _l_e_s_s_ _t_h_a_n_ _(_<_)_ 2.75 less than This delimiter, which is a relational operator, yields the value true or false. S_y_n_t_a_x_: <operand1' < <operand2' P_r_i_o_r_i_t_y_: 5 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: always boolean S_e_m_a_n_t_i_c_: The relation takes on the value true whenever the corresponding relation is satisfied for the ex- pressions involved, otherwise false. In case one of the operands is different from type integer the relation is executed as a subtraction. Thus, you may be prepared for overflow, underflow, or spill. E_x_a_m_p_l_e_ _1_: a:= b < c; if d < q then .... else ...; while k < l do ...; \f F_ 2_._7_6_ _ _ _ _ _ _l_e_s_s_ _t_h_a_n_ _o_r_ _e_q_u_a_l_ _(_<_=_)_ 2.76 less than or equal This delimiter, which is a relational operator, yields the value true or false. S_y_n_t_a_x_: <operand1' <= <operand2' P_r_i_o_r_i_t_y_: 5 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: always boolean. S_e_m_a_n_t_i_c_: The relation takes on the value true whenever the corresponding relation is satisfied for the expressions involved, otherwise false. The relation is always executed as a subtraction. Thus, you may be prepared for overflow, underflow, or spill (see example 3 of monitor). E_x_a_m_p_l_e_ _1_: q:= a <= c; if d <= k then ... else ...; while x <= y do ...; \f F_ 2_._7_7_ _ _ _ _ _ _l_i_f_e_s_o_r_t_ 2.77 lifesort This standard procedure makes available that zone record which is to be the next record in a sorted string of records from a zone. The winning record is selected among the active and inactive records in the zone, and at the same time all inactive records are activated. The user is supposed to move the record away from the zone before next call of any sorting procedure. C_a_l_l_: lifesort (z, key) or liftsort (z) z (call and return value, zone). The name of the selected record. key (call value, integer procedure or empty). The name of a procedure for comparison of two records (see procedure newsort). The key parameter is omitted if standard sequencing is used (see procedure startsort6). Z_o_n_e_ _s_t_a_t_e_: The zone state must be 9, in sort, i.e. startsort6 (or initsort) must have been called. The state is not changed by the procedure. E_x_a_m_p_l_e_ _1_: See example 1 of newsort for a user specified key procedure. E_x_a_m_p_l_e_ _2_: See example 2 of deadsort. \f F_2_._7_8_ _ _ _ _ _ _l_n_ 2.78 ln This real standard procedure performs the mathematical function ln. C_a_l_l_: ln (r) ln (return value, real). The Napierian logarithm of r. r ' 0. r (call value, real, long, or integer). A_c_c_u_r_a_c_y_: r = 1 gives ln = 0 0.5 <= r < 2 gives absolute error below 2.2>-10 0.25 <= r < 0.5 or 2 <= r < 4 gives relative error below 1.8>-10 r < 0.25 or 4 <= r gives relative error below 1.2>-10 A_l_a_r_m_: The run is terminated if r <= 0. E_x_a_m_p_l_e_ _1_: A procedure which gives the decimal logarithm may look like this: real procedure log(x); value x; real x; log:= ln(x) / ln(10); \f F_2_._7_9_ _ _ _ _ _ _l_o_c_k_ 2.79 lock This standard procedure transfers immediately a number of program segments to core and locks them: i.e. they are not released later on caused by some request for space for other segments. M_ * C_a_l_l_: lock ( <pair of parameters' ) P_ 1 <pair of <label expression',<label expression' parameters' ::= <integer expression',<integer expression' <procedure identifier',<integer expression' Each pair of parameters is evaluated, and a locking process is performed depending on the parameter pair: <_l_a_b_e_l_ _e_x_p_r_e_s_s_i_o_n_'_,_<_l_a_b_e_l_ _e_x_p_r_e_s_s_i_o_n_'_ The values of the two label expressions define two points in the program. All program segments between (and inclusive) the two points are locked. <_i_n_t_e_g_e_r_ _e_x_p_r_e_s_s_i_o_n_'_,_<_i_n_t_e_g_e_r_ _e_x_p_r_e_s_s_i_o_n_'_ The values of the two integer expressions define two segment numbers in the program. All segments in the program between (and inclusive) those segments are locked. Segment numbers of first segment of the main program and all external procedures included in the program may be obtained from a compilation with survey.yes specified (see ref. 15 and ref. 10). This parameter pair is intended for locking segments of the run time system. The run time system consists of 11 segments: \f segment 0 : alarm segment 0, c_a_n_n_o_t_ be locked lock segment 1-5 : resident part of RS, c_a_n_n_o_t_ be locked segment 6 : long division and multiplication, stderror segment 7 : alarm segment 1, used by run time alarms segment 8 : declaration of zones, exponentiation: ** segment 9 : RS block segment (i.e. inblock, outblock etc.) segment 10 : RS error segment (i.e. special handl. of status) <_p_r_o_c_e_d_u_r_e_ _i_d_e_n_t_i_f_i_e_r_'_,_<_i_n_t_e_g_e_r_ _e_x_p_r_e_s_s_i_o_n_'_ The value of integer expression defines a number of consecutive segments - starting with the entry segment of the procedure - to be locked. E_x_a_m_p_l_e_ _1_: If we want to lock in primary store segment 6 (long division and multiplication), two segments containing procedure readin, and one or more segments surround- ing label seglock1 to label seglock2, this could be done by the call: lock(6,6, readin, 2, seglock1, seglock2); \f F_2_._8_0_ _ _ _ _ _ _l_o_c_k_e_d_ 2.80 locked This integer standard procedure transfers the segment numbers (0,1,...) of the segments, which are locked for the moment, to an integer array parameter. C_a_l_l_: locked (ia) locked (return value, integer). Number of segments locked at the moment. ia (return value, integer array). ia(1), ia(2),... ia(locked) is the list of segment numbers for the segments locked at the moment. E_x_a_m_p_l_e_ _1_: If the call locked (ia); is used after the call shown in example 1 under lock, the results could be: ia(1) = 6 ia(2) = 24 ia(3) = 25 ia(4) = 32 ia(5) = 33 ia(6) = 34 \f F_2_._8_1_ _ _ _ _ _ _l_o_g_a_n_d_ 2.81 logand This long standard procedure performs the function logical and (logical multiplication) on two 48 bit entities a and b. If the type length of a and/or b is smaller than 48 bits, they are ex- tended by repetition of the sign bit. C_a_l_l_: logand (a, b) logand (return value, long). Bitpattern equal to (a and b) performed bit by bit after a possible extension of the parameters a and b. a,b (call values, short string (text portion), real, long, integer, or boolean). The two parameters do not have to be of the same kind. They are - if necessary - extended and they are handled as described below. H_a_n_d_l_i_n_g_ _o_f_ _a_ _a_n_d_ _b_ _a_c_c_o_r_d_i_n_g_ _t_o_ _k_i_n_d_: String: It is tested that a string parameter describes a text portion or a short string (see ref. 15). This is a 48 bit entity. Real: A real is represented by 48 bits. No conversion. Long: A long is represented by 48 bits. No conversion. Integer: An integer is extended to a long as if the operator extend had been applied. Boolean: A boolean is considered as a short integer. The 12 bit boolean is extended to a 48 bit long according to the algorithm: int:= boo extract 12; if int ' 2047 then int:= int - 4096; param:= extend int; \f The rules for extension imply that actual parameters with the logand values true, -1, and extend (-1) are equivalent. Note that the rules also imply that the effect of an integer with the value 2048 differs from the effect of a boolean with the value false add 2048. E_x_a_m_p_l_e_ _1_: See example 2 of invar. E_x_a_m_p_l_e_ _2_: I_n_f_o_r_m_a_t_i_o_n_ _r_e_t_r_i_e_v_a_l_ Each record is a certain file has an element inf that contains binary information in each binary position (sex, salary on hour basis or not, ...). A statement that writes out the identification for each record that fulfil all the criteria in a read search element, could look like this: for i:= inrec6 (z, length) while z.ident <' endident do if logand (searchcrit, z.inf) = searchcrit then write (out, "nl", 1, z.ident); \f 2_._8_2_ _ _ _ _ _ _l_o_g_o_r_ 2.82 logor This long standard procedure performs logical or (logical addi- tion) on two 48 bit entities a and b. If the type length of a and/or b is smaller than 48 bits, they are extended by repetition of the sign bit. C_a_l_l_: logor (a, b) logor (return value, long). Bit pattern equal to (a or b) performed bit by bit after a possible extension of the parameters. a,b (call values, short string (text position), real, long, integer, or boolean). The two parameters do not have to be of the same kind. They are - if necessary - extended and they are handled as described for logand. E_x_a_m_p_l_e_ _1_: About the same as example 2 for logand, but you are now searching for records that are not in con- flict with the search criteria i.e. each found record should only contain all, some or none of the information found in the search criteria. This could be done by replacing logand (searchrit, z.inf) = searchrit by: logor (searchrit, z.inf) = z.inf \f F_ 2_._8_3_ _ _ _ _ _ _l_o_n_g_ 2.83 long This delimiter, which is a declarator, is used in declarations and specifications of variables of type long. S_y_n_t_a_x_: long <namelist' S_e_m_a_n_t_i_c_: The variables in namelist will all be of type long, and occupy 48 bits in the storage area. The value of a long is in the interval: -140 737 488 355 328 <= value <= 140 737 488 355 327. All values can be assigned to the variable by use of shift and the like, but if you assign by constants or character reading procedures you are confined to th range: -140 737 488 355 327 <= value <= 140 737 488 355 327 E_x_a_m_p_l_e_ _1_: long l1; long l2, yes, no, price; procedure pip(a); long a; E_x_a_m_p_l_e_ _2_: The greatest possible positive and negative long values can be assigned by the statements: max _pos:= extend (-1) shift (-1); max _neg:= extend 1 shift 47; \f 2_._8_4_ _ _ _ _ _ _l_o_n_g_ 2.84 long This delimiter, which is a transfer operator, changes the type string and real to type long. S_y_n_t_a_x_: long <operand' P_r_i_o_r_i_t_y_: 1 O_p_e_r_a_n_d_ _t_y_p_e_: real or string. R_e_s_u_l_t_ _t_y_p_e_: long. S_e_m_a_t_i_c_: Changes the type of a string or a real to type long. The binary pattern of the operand is unchanged. The binary pattern of a string and a real is described in ref. 14. N_o_t_e_: This use of the delimiter long is totally different from its use in a declaration or specification. E_x_a_m_p_l_e_ _1_: l:= long <:abcde:' add >f>; E_x_a_m_p_l_e_ _2_: See the examples in real and replace real with long where real is used as a transfer operator. E_x_a_m_p_l_e_ _3_: See example 1 of swoprec6. \f F_ 2_._8_5_ _ _ _ _ _ _m_e_s_s_a_g_e_ 2.85 message This delimiter, which is a compiler directive, may print a mes- sage during the translation of a program. Messages follow the same rules as comment. S_y_n_s_t_a_x_: ; message <text no containing ";"' ; may replace any ; (semicolon) begin message <text not containing ";"' ; may replace any begin S_e_m_a_n_t_i_c_: The text between message and semicolon is printed on current output if the program is translated with the parameter message.yes. E_x_a_m_p_l_e_ _1_: You can spare the listing of a long algol program and still keep track of the line numbers. Put 1 or 2 messages on each page of the program (for instance as page head) and translate it with: algol message.yes (the default value). The messages are then printed with their line numbers attached and you can easily find any other line given its line number. \f F_ 2_._8_6_ _ _ _ _ _ _m_i_n_u_s_ _(_-_)_ 2.86 minus This delimiter, which is an arithmetic operator, can be used both as a dyadic and as a monadic operator. 1_._ _D_y_a_d_i_c_: S_y_n_t_a_x_: <operand1' - <operand2' P_r_i_o_r_i_t_y_: 4 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long or real. R_e_s_u_l_t_ _t_y_p_e_: <integer' - <integer' is of type integer <integer' - <long' - - - long <integer' - <real' - - - real <long' - <integer' - - - long <long' - <long' - - - long <long' - <real' - - - real <real' - <integer' - - - real <real' - <long' - - - real <real' - <real' - - - real S_e_m_a_n_t_i_c_: This operator yields the normal arithmetic difference of the expressions involved. 2_._ _M_o_n_a_d_i_c_: S_y_n_t_a_x_: - <operand' P_r_i_o_r_i_t_y_: 4 O_p_e_r_a_n_d_ _t_y_p_e_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: - <integer' is of type integer - <long' - - - long - <real' - - - real \f S_e_m_a_n_t_i_c_: This monadic operator yields the "opposite" minus value of the operand. E_x_a_m_p_l_e_ _1_: 5-7 a-q -5-a s shift (-11) (-1) shift (-1) \f F_ 2_._8_7_ _ _ _ _ _ _m_o_d_ 2.87 mod This delimiter, which is an arithmetic operator, yields the remainder corresponding to an integer division. S_y_n_t_a_x_: <operand1' mod <operand2' P_r_i_o_r_i_t_y_: 3 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer or long. R_e_s_u_l_t_ _t_y_p_e_: When both operands are of type integer, the result is of type integer, otherwise the result is of type long. S_e_m_a_n_t_i_c_: The value of i mod j is defined as i - i//j*j The sign of i mod j is the same as the sign of i. E_x_a_m_p_l_e_ _1_: C_y_c_l_i_c_a_l_ _c_o_u_n_t_i_n_g_ Counting i = 1,2,3,1,2,3,1,... may be done in this way: i:= i mod 3 + 1; A longer but slightly faster version is: i:= if i = 3 then 1 else i + 1; \f F_2_._8_8_ _ _ _ _ _ _m_o_n_i_t_o_r_ 2.88 monitor This integer standard procedure is the algol equivalent of the monitor procedures. You may use it to handle peripheral devices in a non-standard way and to program operating systems and exe- cutive functions in algol. In most cases the algol procedure will only transform the para- meters to the form required by the monitor, and the description below describes mainly this transformation. You will have to consult the Monitor manuals (ref. 1 and 2) for the details and the ideas behind each entry. Be aware that the monitor tables have halfword addresses. C_a_l_l_: monitor (fnc, z, i, ia) monitor (return value, integer). In most cases the result of the corresponding call of a monitor procedure, the meaning of which is found in the Monitor manual, part 2 (ref. 2). fnc (call value, integer). A function code speci- fying the monitor procedure to be called. z (call and return value, zone). The zone des- criptor contains in most cases the name of the process or catalog entry concerned. i (call and return value, integer). Used for various purposes, e.g. device number, message buffer address. ia (call and return value, integer array). Used for various purposes, e.g. tail of catalog entry, contents of answer. Various lengths of ia are required in the various cases. N_o_t_e_: Fielding has no influence on the addressing of ia as the procedure always uses the array from the first element and on. In most cases only some of the last 3 parameters are actually used by the procedure. The value of fnc determines the function\f as follows: monitor f_n_c_ _=_ _4_,_ _p_r_o_c_e_s_s_ _d_e_s_c_r_i_p_t_i_o_n_: monitor result, i.e. process description address, 0 if the process does not exist. z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _6_,_ _i_n_i_t_i_a_l_i_s_e_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process initialised, 1,2,3 means not initialised. z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _8_,_ _r_e_s_e_r_v_e_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process reserved, 1,2,3 means not reserved. z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _1_0_,_ _r_e_l_e_a_s_e_ _p_r_o_c_e_s_s_: monitor result dummy z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _1_2_,_ _i_n_c_l_u_d_e_ _u_s_e_r_: monitor result, i.e. 0 means included, 2,3,4 means not included. z (call value). Contains the process name. i (call value). Device number. ia dummy \f f_n_c_ _=_ _1_4_,_ _e_x_c_l_u_d_e_ _u_s_e_r_: monitor monitor result, i.e. 0 means excluded, 2,3,4 means not excluded. z (call value). Contains the process name. i (call value). Device number. ia dummy The format of messages and answers used in the following 5 functions can be found in the Monitor manual, part 2 and 3, (ref. 2-3) and in the description of getshare6. f_n_c_ _=_ _1_6_,_ _s_e_n_d_ _m_e_s_s_a_g_e_: monitor buffer address, 0 if the buffer claim is exceeded. z (call value). Contains the process name of the receiving process. i (call value). The number of a share within z. The share state must at call time be 0 or 1, at return time it is the buffer address. The message sent is given in the share descriptor. (See getshare6). Note that you may change the message in the share by means of the procedure setshare6. ia dummy. The value of "current activity no" is used as mes- sage identification. This is stored in the message buffer (buffer address - 2), which later (f.ex. in wait event) may supply the number of the sending activity (see ref. 19, concurrent i/o transfers). \f f_n_c_ _=_ _1_8_,_ _w_a_i_t_ _a_n_s_w_e_r_:monitor monitor result, i.e. 1 means a normal answer, 2,3,4,5 means dummy answers. z (call value). Determines together with >i> the buffer address. i (call value). The number of a share within z. The share state must be the buffer address at call time, at return time it is 0. ia (return value, length '= 8). The answer is stored here. If the program is in activity mode, and the give up mask in the zone includes 1 shift 9, this function will execute an implicit passivate statement just before call of the monitor procedure. f_n_c_ _=_ _2_0_,_ _w_a_i_t_ _m_e_s_s_a_g_e_: monitor result, i.e. process description address of the sender, positive for a normal message, negative for a message from a removed process, or 0 if the buffer claim is exceeded. z (return value). The process name is stored here. i (return value). Buffer address. ia (return value, length '= 8). The message is stored here. f_n_c_ _=_ _2_2_,_ _s_e_n_d_ _a_n_s_w_e_r_: monitor result dummy z dummy i (call value). Buffer address. ia (call value, length '= 9). The first 8 elements contain the answer, the 9th element contains the result, which is 1 for a normal answer, 2,3,4,5, for a dummy answer. \f f_n_c_ _=_ _2_4_,_ _w_a_i_t_ _e_v_e_n_t_: monitor monitor result, i.e. 0 for a message, 1 for an answer. z (return value). The name of the sending process is stored here if a message was received. i (call and return value). Last and next buffer address. ia (return value, length '= 8). If a message is received, it is stored here. The value of ia(1) which is loaded from the message buffer (buffer address - 2), indicates: ia(1)'0: the activity number of the activity, which sent the message ia(1)=0: the message was sent in monitor or neutral mode ia(1)<0: the message was sent in disable mode. If an answer is received, ia is dummy. In this case the buffer address returned in i corresponds to a message buffer address in the share state of some zone (see getshare6). f_n_c_ _=_ _2_6_,_ _g_e_t_ _e_v_e_n_t_: monitor result dummy z dummy i (call value). Buffer address pointing to a message. An answer must not be released in this way - use wait answer (or procedure check) instead. ia dummy The format of the catalog entry tails used in the following 3 functions is described in the File Processor manual, part 1 (ref. 6). \f f_n_c_ _=_ _4_0_,_ _c_r_e_a_t_e_ _e_n_t_r_y_: monitor monitor result, i.e. 0 means entry created, 2,3,4,5,6,7 means entry not created. z (call value). Contains the entry name. i dummy ia (call value, length '= 10). Contains the tail of the entry. f_n_c_ _=_ _4_2_,_ _l_o_o_k_u_p_ _e_n_t_r_y_: monitor result, i.e. 0 means entry looked up, 2,3,6,7 means not looked up. z (call value). Contains the entry name. i dummy ia (return value, length '= 10). The tail of the entry is stored here. f_n_c_ _=_ _4_4_,_ _c_h_a_n_g_e_ _e_n_t_r_y_: monitor result, i.e. 0 means changed, 2,3,4,5,6,7 means entry not changed. z (call value). Contains the entry name. i dummy ia (call value, length '= 10). Contains the new tail of the entry. f_n_c_ _=_ _4_6_,_ _r_e_n_a_m_e_ _e_n_t_r_y_: monitor result, i.e. 0 means entry renamed, 2,3,4,5,6,7 means entry not renamed. z (call value). Contains the present entry name. i dummy ia (call value, length '= 4). Contains the new entry name. \f f_n_c_ _=_ _4_8_,_ _r_e_m_o_v_e_ _e_n_t_r_y_: monitor monitor result, i.e. 0 means entry removed, 2,3,4,5,6,7 means entry did not exist or entry is not removed. z (call value). Contains the entry name. i dummy ia dummy f_n_c_ _=_ _5_0_,_ _p_e_r_m_a_n_e_n_t_ _e_n_t_r_y_: monitor result, i.e. 0 means entry made permanent, 2,3,4, 5,6,7 means entry not permanent. z (call value). Contains the entry name. i (call value). Catalog key. ia dummy f_n_c_ _=_ _5_2_,_ _c_r_e_a_t_e_ _a_r_e_a_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means area process created, 1,2,3,4,5,6 means process not created. z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _5_4_,_ _c_r_e_a_t_e_ _p_e_r_i_p_h_e_r_a_l_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process created, 1,2,3,4,5,6 means process not created. z (call value). Contains the process name. i (call value). Device number. ia dummy \f f_n_c_ _=_ _5_6_,_ _c_r_e_a_t_e_ _i_n_t_e_r_n_a_l_ _p_r_o_c_e_s_s_: monitor monitor result, i.e. 0 means process created, 1,2,3,6 means process not created. z (call value). Contains the process name. The process will be created in the buffer area of z. i dummy ia (call value, length '= 9). Contains the parameters in this way: ia(1) buffer index for start of process ia(2) buffer index for last of process ia(3) buffer claim shift 12 + area claim ia(4) internal claim shift 12 + function mask ia(5) priority of the process ia(6) lower limit of max base ia(7) upper limit of max base ia(8) lower limit of std base ia(9) upper limit of std base f_n_c_ _=_ _5_8_,_ _s_t_a_r_t_ _i_n_t_e_r_n_a_l_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process started, 2,3,6 means process not started. z (call value). Contains the process name. The process must have been created inside the zone buffer. i (call value). The number of a share within z. The share state must at call time be 0 or 1, at return time it is - process description address. ia dummy \f f_n_c_ _=_ _6_0_,_ _s_t_o_p_ _i_n_t_e_r_n_a_l_ _p_r_o_c_e_s_s_: monitor monitor result, i.e. 0 means stop initiated, 3,6 means stop not allowed. z (call value). Determines together with i the process. i (call value). The number of a share within z. The share state must at call time be - process des- cription address. At return time it is the buffer address. Notice that the process name in z is ir- relevant. ia dummy f_n_c_ _=_ _6_2_,_ _m_o_d_i_f_y_ _i_n_t_e_r_n_a_l_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process modified, 2,3,6 means modification not allowed. z (call value). Contains the process name. i dummy ia (call value, length '= 6). Contains the modified registers. f_n_c_ _=_ _6_4_,_ _r_e_m_o_v_e_ _p_r_o_c_e_s_s_: monitor result, i.e. 0 means process removed, 1,2,3,5,6 means removal not allowed. z (call value). Contains the process name. i dummy ia dummy f_n_c_ _=_ _6_6_,_ _t_e_s_t_ _e_v_e_n_t_: monitor result, i.e. 0 when the first event is a message, 1 when the first event is an answer, and -1 when the event queue in the call moment is empty. z as for fnc= 24, wait event i - - - - - ia - - - - - \f Works as monitor (24, ...), wait event, except monitor that no waiting takes place. f_n_c_ _=_ _6_8_,_ _g_e_n_e_r_a_t_e_ _n_a_m_e_: monitor result, i.e. 0 means name generated, 2 means name not generated. z (return value). The generated name is stored here. i dummy ia dummy f_n_c_ _=_ _7_0_,_ _c_o_p_y_ _c_o_r_e_ _a_r_e_a_: monitor result of the copying, 0 meaning area copied, 2 or 3 area not copied. z (call value). Contains the area to or from which the copying will take place. The limits of the copying are given by the zone parameters record base and last halfword. i (call value). The buffer address of the input or output message defining sender>s copy area. ia (return value, length '= 9). Contains information about the copying almost ready to be used by send answer (see ref. 3): ia(1) should then be set by the user ia(2) if result <' 0 then 0 else halfwords copied ia(3) if result <' 0 then 0 else chars copied ia(9) if result = 3 then 3 else 1. \f f_n_c_ _=_ _7_2_,_ _s_e_t_ _c_a_t_a_l_o_g_ _b_a_s_e_: monitor monitor result, 0 means catalog base set, 2,3,4,6 means catalog bas not set. z (call value). Contains the name of a child process or a null-name, meaning own process. i dummy ia (call value, length '= 2). Contains the base to be set. ia(1) lower limit of the base ia(2) upper limit of the base f_n_c_ _=_ _7_4_,_ _s_e_t_ _e_n_t_r_y_ _b_a_s_e_: monitor result, 0 means entry base set, 2,3,4,5,6,7 means entry base not set. z (call value). Contains the entry name. i dummy ia (call value, length '= 2). Contains the entry base to be set, as for the fnc = 72, set catalog base. f_n_c_ _=_ _7_6_,_ _l_o_o_k_u_p_ _h_e_a_d_ _a_n_d_ _t_a_i_l_: monitor result, 0 means entry looked up, 2,3,6,7 means entry not look up. z (call value). Contains the entry name. i dummy ia (return value, length '= 17). The head and tail of the entry is stored here. (The format is described in ref. 2). \f f_n_c_ _=_ _7_8_,_ _s_e_t_ _b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ _c_l_a_i_m_s_: monitor monitor result, 0 means claims set, 1,2,3,6 means claims not set. z (call value). Contains the name of a child process. i dummy ia (call value, length '= 4 + 2*no of keys). The first 4 elements contain the name of the bs document ia(5) entry claim, key 0 ia(6) segment claim, key 0 ....... ia(5+2*max key) entry claim, max key ia(6+2*max key) segment claim, max key f_n_c_ _=_ _8_0_,_ _c_r_e_a_t_e_ _p_s_e_u_d_o_ _p_r_o_c_e_s_s_: monitor result, 0 means pseudo process created, 1,2,3,6 means pseudo process not created. z (call value). Contains the name of the pseudo process. i dummy ia dummy f_n_c_ _=_ _8_2_,_ _r_e_g_r_e_t_ _m_e_s_s_a_g_e_: monitor no result from this operation. Misuse will give break 6. z (call value). Determines together with >i> the buffer address of the message to be regretted. i (call value). The number of a share within z. The share state must be the buffer address at call time. At return it is 0. ia dummy \f f_n_c_ _=_ _9_0_,_ _p_e_r_m_a_n_e_n_t_ _e_n_t_r_y_ _i_n_ _a_u_x_i_l_i_a_r_y_ _c_a_t_a_l_o_g_: monitor monitor result, 0 means entry made permanent, 2,3,4,5,6,7 means entry not made permanent. z (call value). Contains the entry name. i (call value). The catalog key. ia (call value, length '= 4). Contains the name of the bs document. f_n_c_ _=_ _1_0_2_,_ _p_r_e_p_a_r_e_ _b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ monitor result, i.e. 0 means chaintable allocated, 1,2,3,4,5,6,7 means chaintable not allocated. z (call value), the zone record holds the chainhead. i dummy ia dummy f_n_c_ _=_ _1_0_4_,_ _i_n_s_e_r_t_ _e_n_t_r_y_ monitor result, i.e. 0 means entry inserted in maincata- log, 1,2,3,4,5,6,7 means entry not inserted in maincatalog. z (call value), the zone record holds the chainhead. i dummy ia (call value, length '= 17), contains head and tail of the entry. f_n_c_ _=_ _1_0_6_,_ _i_n_s_e_r_t_ _b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ monitor result, i.e. 0 means document included, 1,2,4,6 means document not included. z dummy i dummy ia (call value, length '= 21), contains the document name in word 18,19,20, and 21. \f f_n_c_ _=_ _1_0_8_,_ _d_e_l_e_t_e_ _b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ monitor monitor result, i.e. 0 means document removed, 1,2,4,5,6 means document not removed. z dummy i dummy ia (call value, length'=21), contains the document name in word 18,19,20, and 21. f_n_c_ _=_ _1_1_0_,_ _d_e_l_e_t_e_ _e_n_t_r_i_e_s_ monitor result, i.e. 0 means entries deleted, 1,2,3,4,6 means not deleted. z dummy i dummy ia (call value, length '= 21) contains the document name in word 18,19,20, and 21. f_n_c_ _=_ _1_1_2_,_ _c_o_n_n_e_c_t_ _m_a_i_n_ _c_a_t_a_l_o_g_ monitor result, i.e. 0 means catalog connected, 1,2,3,4,5,6,7 means catalog not connected. z (call value), zone record holds the chainhead. i dummy ia (call value, length '= 4), contains the catalog name. f_n_c_ _=_ _1_1_4_,_ _r_e_m_o_v_e_ _m_a_i_n_ _c_a_t_a_l_o_g_ monitor result, i.e. 0 means main catalog removed, 7 means main catalog not removed. z dummy i dummy ia dummy \f f_n_c_ _=_ _1_2_0_,_ _c_r_e_a_t_e_ _a_u_x_ _e_n_t_r_y_ _a_n_d_ _a_r_e_a_ _p_r_o_c_e_s_s_ monitor monitor result, i.e. 0 means entry and area process created, 1,2,3,4,5,6 means entry and area process not created. z (call value), contains the area process name. i dummy ia (call value), length '= 21), contains head and tail in word 1 to 17, and the document name in word 18 to 21. f_n_c_ _=_ _1_2_2_,_ _r_e_m_o_v_e_ _a_u_x_ _e_n_t_r_y_ monitor result, i.e. 0 means entry removed, 1,2,3,6 means entry not removed. z dummy i dummy ia (call value, length '= 21), contains head and tail in word 1 to 17 and the document name in word 18 to 21. If the requirements stated above are not fulfilled, or if the situation termed >parameter error> in ref. 2 occurs, the run will be terminated with an alarm. Values of fnc not mentioned above will also terminate the run. E_x_a_m_p_l_e_ _1_: C_r_e_a_t_e_ _a_ _b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ _a_r_e_a_ A backing storage area sldata3 of s segments may be created and then used like this: \f begin zone z(512,1,stderror); monitor integer array tail(1:10); integer i; open(z,4,<:sldata3:',0); <* The zone contains now the document name. The document is not initialized in case of kind=4*' tail(1):= s; tail(2):= 1; <*preferably a disc area*' for i:= 3 step 1 until 10 do tail(i) := 0; tail(6):= systime (7,0, 0.0); <*shortclock*' if monitor(40<*create _entry*',z,0,tail) ' 0 then error(1); outrec(z,...); E_x_a_m_p_l_e_ _2_: S_c_o_p_e_ _u_s_e_r_ _o_f_ _a_n_ _a_r_e_a_: The scope user function consists of 2 steps. First the area is made permanent with catalog key 3. Now, as key is '= min global key (see ref. 2), the entry base may be set to the user base of the process. Let the zone z be opened to the area to be scoped. system(11)bases:(i,ia); ia(1):= ia(5); ia(2):= ia(6); <* fetch the user base;*' if monitor(50)permanent entry:(z,3,ia) <' 0 then error(1) else if monitor(74)set _base:(z,0,ia) <' 0 then error(2) else ... E_x_a_m_p_l_e_ _3_: F_i_n_d_ _s_c_o_p_e_ _o_f_ _a_n_ _e_n_t_r_y_: As the catalog base of an internal process and of a catalog entry may use almost the full integer range they must be handled as longs when relations of type <= or '= between them are calculated, in order to prevent overflow. \f system(11)bases:(i,bases); monitor monitor(76 <*head _and _tail*', z,0,entry) <' 0 then goto error; case entry(1) extract 3 + 1 of begin <*key 0, maybe temp *' if entry(2) = bases(3) and entry(3) = bases(4) then scope:= 1 <*temp*' else scope:= 6; <*undef*' <*key 1 *' scope:= 6; <*undef*' <*key 2, maybe login *' if entry(2) = bases(3) and entry(3) = bases(4) then scope:= 2 <*login*' else scope:= 6; <*undef*' <*key 3, user, project, or system *' begin l1:= entry(2); l2:= entry(3); if l1 = bases(5) and l2 = bases(6) then scope:= 3 <*user*' else if l1 = bases(7) and 12 = bases(8) then scope:= 4 <*project*' else if l1 <= extend bases(7) and l2 '= extend bases(8) then scope:= 5 <*system*' else scope:= 6; <*undef*' end end case; write(out,<:the scope is: :',case scope of( <:temp:',<:login:',<:user:', <:project:',<:system:',<:***, i.e. undef:')); \f E_x_a_m_p_l_e_ _4_: monitor G_e_t_ _t_h_e_ _c_l_a_i_m_s_ _o_f_ _a_ _p_r_o_c_e_s_s_ _o_n_ _a_ _g_i_v_e_n_ _b_s_-_d_e_v_i_c_e_ boolean procedure claimproc (keyno,bsno,bsname,entries,segm,slicelength); value keyno; integer keyno,bsno,entries,segm,slicelength; long array bsname; <* claimproc (return, boolean) true if bsno'=-1 and bsno <= max _bsno and keyno is legal else false. If claimproc is false then all return parameters are zero. keyno (call, integer) 0=temp 2=login 3=user/project bsno (call/return, integer) if call value is -1 then return value is main bsdevice number, else bsno is unchanged bsname (return, long array 1:2) name of called device entries (return, integer) no. of entries of key=keyno on called device segm (return, integer) no. of segm. of key=keyno on called device slicelength (return, integer) slicelength on called device *' begin integer bsdevices,firstbs,ownadr,mainbs,i; long array field name; integer array core(1:18); system(5,92,core); bsdevices:=(core(3)-core(1))//2; firstbs:=core(1); mainbs:= core(4); ownadr:=system(6,i,bsname); if bsno<-1 or bsno'=bsdevices or keyno<'0 and keyno<'2 and keyno<'3 then begin \f claimproc:=false; goto exitclaim monitor end; claimproc:=true; begin integer array nametable(1:bsdevices); name:=18; system(5,firstbs,nametable); if bsno= -1 then <*find main device number*' for bsno:= bsno + 1 while nametable(bsno+1) <' mainbs do; system(5,nametable(bsno+1)-36,core); <*get chaintable*' if core(10)=0 then goto exitclaim; bsname(1):=core.name(1); bsname(2):=core.name(2); slicelength:=core(15); system(5,ownadr+core(1),core); <*get process description*' entries:=core(keyno+1) shift (-12); segm:=core(keyno+1) extract 12 * slicelength; end; if false then begin exitclaim: entries:=segm:=slicelength:=0; bsname(1):=bsname(2):=0; end; end claimproc; Claims on a specific device are found as follows: bsno:=-1; for bsno:=bsno+1 while claimproc(keyno,bsno,bsname,entries,segm,slicelength) and -,(searchname(1)=bsname(1) and searchname(2)=bsname(2)) do; Max claims are found as follows: \f maxentr:=max:=maxslice:=0; monitor maxbs(1):=maxbs(2):=0; bsno:=-1; for bsno:=bsno+1 while claimproc(keyno,bsno,bsname,entries,segm,slicelength) do if entries'0 and segm'max then begin maxentr:=entries; max:=segm; maxslice:=slicelength; maxbs(1):=bsname(1); maxbs(2):=bsname(2); end; E_x_a_m_p_l_e_ _5_: R_e_n_a_m_i_n_g_ _a_n_ _e_n_t_r_y_ The procedure renames a catalog entry. The procedure works iden- tical to the utility program rename, with the extension that a work-name may be returned. integer procedure renameproc (oldname, newname); long array oldname, newname; <* renameproc (return integer) 0 ok 1 new name exists already 2 cat i/o error document not mounted or document not ready 3 oldname not found 4 name protected 5 name in use 6 name format illegal 7 catalog inconsistent oldname (call long array) contains old name newname (call long array) contains new name or <::'. if newname(1)=long<::' then newname is a return parameter, containing a wrk-name. '* \f begin monitor integer i; boolean wrk; long array field laf; zone zhelp(1, 1, stderror); integer array ia(1:20); wrk:=newname(1)=long<::'; if wrk then begin generate _next: monitor(68<*generate*', zhelp, 0, ia); getzone6(zhelp, ia); laf:=2; newname(1):=ia.laf(1); newname(2):=ia.laf(2); end; laf:=0; ia.laf(1):=newname(1); ia.laf(2):=if newname(1) extract 8 = 0 then long<::' else newname(2); open(zhelp, 0, oldname, 0); renameproc:= i:= monitor(46<*rename*', zhelp, 0, ia); if i=3 then begin <*oldname not found, or newname already exists*' i:=monitor(42<*lookup*', zhelp, 0, ia); if i=0 then begin if wrk then goto generate _next else renameproc:=1 end; end end renameproc; \f E_x_a_m_p_l_e_ _6_: L_i_s_t_i_n_g_ _o_f_ _a_n_ _e_n_t_r_y_ _t_a_i_l_ monitor Monitor 42, lookup entry, will place the catalog tail in an array, which can be listed by the following procedure: procedure list _tail (zout, tail); zone zout; integer array tail; <* the procedure lists the contents of array tail as a catalog entry zout (return, zone) zone for output tail (call, integer array) contains entry tail *' begin integer n,i; long array field docname; real r; docname:=2; n:=tail(1); if n'=0 then write(zout,<<z',n) else write(zout,<<z',n shift (-12) extract 12,<:.:',n extract 12); n:=tail(2); if n=0 or n=1 then write(zout,n) else write(zout,<: :',tail.docname); n:=tail(9) shift (-12); i:=6; if -,(n=4 or n'=32) and tail(6)<'0 then begin write(out),<:d.:',<<zddddd.dddd', systime(6, tail(6), r)+r/1000000); i:= 7; end; while i<11 do \f begin monitor n:=tail(i); if n'= 0 and n<4096 then write(zout,<<z',n) else write(zout,<<z',n shift (-12) extract 12,<:.:',<<z',n extract 12); i:= i + 1; end; end list _tail; E_x_a_m_p_l_e_ _7_: C_r_e_a_t_i_n_g_ _a_ _n_e_w_ _e_n_t_r_y_ The procedure creates a new catalog entry with scope temp or changes an already existing entry (with scope temp) according to the parameters. The procedure works identical to the utility program set, with the extension that a work-name may be returned. integer procedure setproc (name, tail); long array name; integer array tail; <* setproc (return, integer) 0 ok 1 change kind impossible 2 bs device unknown 3 change bs device impossible 4 no resources 5 in use 6 name format illegal 7 catalog inconsistent name (call, long array) contains the entry name. If name(1)=long<::' a wrkname is created and name is returnparameter. tail (call, integer array) contains the entry tail 1 size or modekind 2:5 docname 6 shortclock, in case shortclock is wanted in the entry 7:10 remaining tail *' \f begin monitor integer i; long array field laf; zone zhelp(1,1,stderror); integer array ia(1:20); open(zhelp, 0, name ,0); for i:= 1 step 1 until 10 do ia(i):= tail(i); <*tail could possible be a fielded array. As fielding does not work in monitor the contents of tail is moved to the non-fielded array ia*' setproc:= i:= monitor(40<*create*',zhelp,0,ia); if name(1)=long<::' then begin <*get wrkname*' getzone6(zhelp,ia); laf:=2; name(1):=ia.laf(1); name(2):=ia.laf(2); end; if i=3 then begin <*entry exist*' i:=monitor(42<*lookup*',zhelp,0,ia); if i<'0 then begin setproc:=7; goto exit _setproc end; if tail(1)<0 or ia(1)<0 then begin if tail(1)'=0 or ia(1)'=0 then begin setproc:=1; goto exit _setproc end; goto change end; if tail(2)=0 or tail(2)=1 then goto change; if tail(3) extract 8=0 then tail(4):=tail(5):=0; if tail(2)<'ia(2) or tail(3)<'ia(3) or tail(4)<'ia(4) or tail(5)<'ia(5) then \f begin monitor setproc:=3; goto exit _setproc end; change: for i:= 1 step 1 until 10 do ia(i):= tail(i); i:=monitor(44<*change*',zhelp,0,ia); if i=6 then i:=4; setproc:=i; end entry exists; exit _setproc: end setproc; In case an array containing head _and _tail exists, it may be used as follows: iaf:= 14; setproc(name,head _and _tail.iaf); \f E_x_a_m_p_l_e_ _8_: C_h_a_n_g_i_n_g_ _a_n_ _e_n_t_r_y_ monitor The procedure changes the specified entry. The procedure works identical to the utility program changeentry. integer procedure changeentryproc (name, tail); long array name; integer array tail; <* changeentryproc (return, integer) 0 ok 1 change kind impossible 2 cat i/o error, doc. not mounted or not ready 3 name not found 4 name protected 5 name in use 6 name format illegal 7 catalog inconsistent 8 change bs device impossible 9 claims exceeded name (call, long array) contains the entry name tail (call, integer array) contains new entry tail *' begin integer i; integer array ia(1:10); zone zhelp(1,1,stderror); open(zhelp,0,name,0); i:= monitor(42<*lookup*',zhelp,0,ia); if i<'0 then begin changeentryproc:=i; goto exit _changeentryproc end; if tail(1)<0 or ia(1)<0 then begin if tail(1)'=0 or ia(1)'=0 then begin changeentryproc:= 1; goto exit _changentryproc end; goto change; end; \f if tail(2)=0 or tail(2)=1 then goto change; monitor if tail(3) extract 8=0 then tail(4):=tail(5):=0; if tail(2)<'ia(2) or tail(3)<'ia(3) or tail(4)<'ia(4) or tail(5)<'ia(5) then begin changeentryproc:=8; goto exit _changeentryproc end; change: <*tail could be a fielded array, cf.example 7*' i:=monitor(44<*change*',zhelp,0,ia); if i=6 then i:=9; changeentryproc:=i; exit _changeentryproc: end changeentryproc; In case the programmer only wants to change shortclock and maybe size, it may be done as follows: begin integer i; zone z(128,1,stderror); integer array ia(1:10); open(z,4,<:pip:',0); ... ... i:=monitor(42<*lookup*',z,0,ia); if i<'0 then begin <* alarm, see lookupproc (ex. 9)*' end; ia(1):=36; <*new size*' ia(6):= systime (7, 0, 0.0); <*shortclock*' i:=monitor(44<*change*',z,0,ia); if i<'0 then begin <* alarm, as changeentryproc, except 6=claims exceeded *' end; ... \f E_x_a_m_p_l_e_ _9_: L_o_o_k_u_p_ _o_f_ _a_n_ _e_n_t_r_y_ monitor The procedure performs a lookup of the specified name. integer procedure lookupproc (scope, name, tail); long array scope, name; integer array tail; <* lookupproc (return, integer) 0 found 1 the call param scope does not contain a legal scope name 2 cat i/o error 3 not found 6 name format illegal scope (call, long array) contains the name of a scope or <::'. If scope(1)=long <::' then scope will be a return parameter which may be <:***:' name (call, long array) contains the name of the entry tail (return, integer array) contains tail of the entry: 1 size or modekind 2:5 docname 6 shortclock, in case shortclock is found in the entry 7:10 remaining tail *' \f integer procedure lookupproc (scope, name, tail); monitor long array scope, name; integer array tail; begin integer scopeno, permkey, i; long l1, l2; zone zhelp(1, 1, stderror); integer array bases(1:8), ba(1:2), head _and _tail(1:17); real array field raf; procedure return (val); value val; integer val; begin lookupproc:= val; for i:= 1 step 1 until 10 do tail(i):= 0; if scopeno <' 6 then reset _base; goto exit _lookupproc; end; procedure reset _base; begin close(zhelp,false); open(zhelp,0,<::',0); monitor (72<*set bases*', zhelp, 0, bases); end; lookupproc:= 0; l1:= scope(1) shift (-8) shift 8; <*first 5 chars*' scopeno:= 6; for i:= 0 step 1 until 5 do if l1 = long (case i+1 of ( <::', <:temp:', <:login:', <:user:', <:proje:' <:syste:')) then scopeno:= i; if scope = 6 then return(1); <*illegal scope specified*' \f system (11<*catalog bases*', 0, bases); monitor if scopeno < 3 then 3 else if scopeno = 3 then 5 else 7; ba(1):= bases(i); ba(2):= bases(i+1); open(zhelp,0,<::',0); monitor (72<*set cat base*', zhelp,0,ba); close (zhelp, true); open (zhelp,0,name,0); i:= monitor (76<*head _and _tail*', zhelp,0,head _and _tail); if i<'0 then return(i); if scopeno'0 and scopeno<5 and (head _and _tail(2) <' ba(1) or head _and _tail(3) <' ba(2)) then return(3); <*entry not found*' permkey:= head _and _tail(1) extract 3; if scopeno=1 and permkey<'0 or scopeno=2 and permkey<'2 or scopeno'2 and permkey<'3 then return(3); <*entry not found*' if scopeno=5 then begin if -, (head _and _tail(2) < ba(1) or head _and _tail(3) ' ba(2)) then return(3); <*entry not found*' end; \f <*now the entry has been found, find the scopemonitor if this was not specified*' if scopeno = 0 then begin l1:= head _and _tail(2); l2:= head _and _tail(3); case permkey+1 of begin <*0*' if l1 = bases(3) and l2 = bases(4) then scopeno:= 1 <*temp*' else scopeno:= 6;<*undef*' <*1*' scopeno:= 6;<*undef*' <*2*' if l1 = bases(3) and l2 = bases(4) then scopeno:= 2 <*login*' else scopeno:= 6;<*undef*' <*3*' if l1 = bases(5) and l2 = bases(6) then scopeno:= 3 <*user*' else if l1 = bases(7) and l2 = bases(8) then scopeno:= 4 <*project*' else if l1 <= extend bases(7) and l2 '= extend bases(8) then scopeno:= 5 <*system*' else scopeno:= 6;<*undef*' end case; raf:= 0 scope(2):= 0; movestring (scope.raf, 1, case scopeno of ( <:temp:', <:login:', <:user:', <:project:',<:system:',<:***:')); end scopeno = 0; \f <*assign the catalog tail to the return parameter*' monitor for i:= 1 step 1 until 10 do tail(i):= head _and _tail(i+7); reset _base; exit _lookupproc: end lookupproc; If the entry of smallest scope should be looked up, this procedure is not necessary, as this can be done by the following procedure or similar statements: integer procedure xlookup (name, tail); long array name; integer array tail; begin zone zhelp(1,1,stderror); integer i; open(zhelp,0, name ,0); xlookup:= i:= monitor(42<*lookup*',zhelp,0,tail); if i<'0 then for i:=1 step 1 until 10 do tail(i):=0; end xlookup where xlookup will contain the value corresponding to lookupproc with the exception of the value 1. E_x_a_m_p_l_e_ _1_0_: W_a_i_t_ The procedure waits as many seconds as specified by the parameter. procedure pause (time); integer time ; begin integer array ia(1:20); zone clock(1,1, stderror); \f open (clock, 2, <:clock:', 1 shift 9); monitor getshare6(clock, ia, 1); ia(4):= 0; ia(5):= time; setshare6(clock, ia, 1); if monitor (16<*send message*), clock, 1, ia) = 0 then system(9,6,<:<10'break:'); <*buffer claim exceeded*' monitor (18<* wait answer*', clock, 1, ia); end pause; E_x_a_m_p_l_e_ _1_1_: See example 4 of system. \f F_ 2_._8_9_ _ _ _ _ _ _m_o_v_e_s_t_r_i_n_g_ 2.89 movestring This integer standard procedure is used for moving textstrings of various kind. C_a_l_l_: movestring (ra, i, st); movestring (return value, integer); the number of elements in ra to which a string port- ion has been assigned. It is negative if the string was too big for the array. ra (return value, real array or zone). The string is stored in ra(i), ra(i+1), and so on. For arrays of more dimensions the lexicographical ordering is used. i (call value, integer); see ra above. st (call value, string); layout or text- string terminated by a NULL character. Moves either a layout or a whole textstring until a null character is encountered or the array is filled. The various string expressions are defined in ref. 15. E_x_a_m_p_l_e_ _1_: A textstring can be inserted in a long array when using a real array field: begin long array la(1:10); real array field raf; ... raf:= 0; movestring (la.raf, 1, <:some text:'); \f 2_._9_0_ _ _ _ _ _ _m_u_l_t_i_p_l_y_ _(_*_)_ 2.90 multiply This delimiter, which is an arithmetic operator, yields the product of the two operands. S_y_n_t_a_x_: <operand1' * <operand2' P_r_i_o_r_i_t_y_: 3 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: <integer' * <integer' is of type integer <integer' * <long' - - - long <integer' * <real' - - - real <long' * <integer' - - - long <long' * <long' - - - long <long' * <real' - - - real <real' * <integer' - - - real <real' * <long' - - - real <real' * <real' - - - real S_e_m_a_n_t_i_c_: The operation may include a type conversion. Real values are represented with a relative pre- cision of about 3>-11 (cf. ref. 15). This means that real variables holding an integral value is represented exact in the interval -2**35 <= real <= 2**35-1. As multiplication of long values includes call of subroutines (cf. ref. 15), and cannot be performed by built-in operations, a representation of certain long variables in real variables may be advantageous (cf. ref. 15). E_x_a_m_p_l_e_ _1_: i:= 5*a; j:= i*(b+4); r:= k * z.laf(4) * arr(7*c) \f F_ 2_._9_1_ _ _ _ _ _ _n_e_w_a_c_t_i_v_i_t_y_ 2.91 newactivity This long standard procedure initializes an e_m_p_t_y_ _a_c_t_i_v_i_t_y_ with a procedure (a coroutine), and starts the activity. C_a_l_l_: new _activity (actno, virt, proc, params); new _activity (return value, long). The value is composed by two integers: activityno shift 24 add cause describing the way in which newactivity returns (see below). actno (call value, integer). The identifica- tion of the activity to be initialized. The activity must be e_m_p_t_y_. virt (call value, integer). Determines whether or not the designated activity will share stack area with another activity: virt = 0: The designated activity will n_o_t_ be virtual, i.e. it will have its own stack area. virt ' 0: must be a legal activity number. The activity: actno, will be virtual, i.e. share stack area with the activity numbered: virt. If virt <' actno virt must define a non-empty virtual activity. proc (call value, procedure). The activity actno is initialized with this procedure, wich is called with the actual parameters stated in the parameter list params. params (call values). A (possibly empty) list of parameters in the call of proc. Storage resources for variables etc. are allocated in the stack, the top of which is defined by a running system variable: last _used. \f The stack administration is for activity purposes supplied withnewactivity another running system variable: max _last _used, defining the upper limit for last used. Stack overflow is detected by compari- son of these two variables. To each activity is allocated a maximal contiguous stack area, defined by the pair: (initial _last _used, max _last _used) for the activity. The very first call of new _activity for each activity, determines the values of the corresponding: (initial _last _used, max _last _used). When an activity is entered (by activate), the running system uses the stack allocated to the activity. When an activity returns to the monitor block (by passivate), the running system uses the stack allocated to the monitor block. F_u_n_c_t_i_o_n_: new _activity must be called at the m_o_n_i_t_o_r_ _b_l_o_c_k_ level (cf. procedure activity). The execution of: result := new _activity (actno, virt, proc, params); now proceeds as follows: 1) If the block level of the call is not the monitor block level, new _activity terminates with an alarm. 2) If the program is not in monitor mode, the run is terminated with an alarm. 3) If actno < 1 or actno ' max _no _of _activities or virt < 0 or virt ' max _no _of _activities, the run is terminated with an alarm. 4) If the activity actno, is not empty, new _activity returns with the result = actno shift 24 add (-1). 5) If the stack area is not allocated, the actual value of last _used (monitor last used) defines the stack and initial _last _used for the activity. \f 6) If the activity is to be virtual, and shared vir- newactivity tual occupies the stack area, the used part of the stack area is transferred to the virtual storage. If, however, the shared virtual waits for an i/o operation to complete, newactivity returns with the result: shared _virtual shift 24 add (-2). 7) The procedure: proc, is called with params as ac- tual parameters, and the program is now in activity mode. It is n_o_t_ _c_h_e_c_k_e_d_, that this parameter list corresponds to the formal specifications in the procedure declaration. The procedure returns: - executing a passivate statement or - leaving through its final end or - because of a runtime alarm. defining the value of: result. At return, the program is back in monitor mode. 8) If a stack area was not allocated, when newactivity was called, the following is done at return from newactivity: The maximal last _used appearing during the execution in activity mode is selected to re- present max _last _used of the activity, and at the same time last _used of the monitor block. 9) If the activity is to be virtual, a record in the virtual storage is reserved to hold the stack area of the activity. The transfers between stack and virtual storage (swops) are initiated by newactivity or activate, when an activity, not at present occupying the stack area, is to be activated (restarted). The virtual storage is the same as used for context blocks. \f If the designated activity is empty, but has been in-newactivity itialized before in a previous call of new _activity, the stack area is a priori fixed by limits defined in the very first call of new _activity for the designated activity. A non-empty activity becomes empty, if it: - leaves throuth its final end or - terminates with a runtime alarm. R_e_s_u_l_t_ _v_a_l_u_e_s_: The return values activityno shift 24 add cause have the following meaning: activity _no: The identification of the activity causing the return. In case of cause = -2, the activity waiting for an i/o operation to complete. cause indicate the return cause: cause = -3: new _activity returned because of an alarm in a started activity, which is now empty. cause = -2: new _activity returns, because the designated activity is virtual and shares storage with another activi- ty waiting for an i/o operation to complete (see the parameter: virt). cause = -1: new _activity returns because the designated activity is n_o_t_ empty. cause = 0: new _activity returns because a started activity terminated via its final end. The activity is now empty. cause = 1: new _activity returns because a started activity is passivated by a p_r_o_g_r_a_m_m_e_d_ passivate statement. \f cause = 2: new _activity returns because anewactivity started activity is passivated by an implicit passivate statement in the zone i/o system. E_x_a_m_p_l_e_ _1_: If a minimum space is needed in the stack for an activity (for later procedure calls, arrays in inner blocks etc.) this may be assured by calling the following procedure from an activity, during its very first execution (cf. 8 in the description above); procedure claim (n); value n; integer n; begin array a (1:n); end; Example 1 of activity shows the use of the procedure. E_x_a_m_p_l_e_ _2_: begin integer i, j; <*monitor block*' procedure p (n, m); integer n, m; begin integer s, t; ...<*activity mode*' s:=2; t:=3; passivate; ... end; procedure q (x, y, z); value x, y, z; real x, y, z; begin integer k, l; ...<*activity mode*' k:=4; 1:=5; passivate; ... end; <*neutral mode*' activity (5); <*monitor mode*' for i:=1, 2 do new _activity (i, 0, p, i, j); for i:= 3, 4, 5 do new _activity (i, 3, q, 0, 0, 0); ... \f newactivity In this example, 5 activities are created and initialized. Activity no. 1 and 2 are both started with the procedure p. The virtual activities no. 3, 4, and 5 are all started with the procedure q. In the figure above is shown the contents of stack and virtual storage after initialization of activity no. 5. Note that activity no. 1 and 2 via name parameter work on common variables. Note also, that the virtual record of activity no. 5 is empty, because the stack is still in core. \f 2_._9_2_ _ _ _ _ _ _n_e_w_s_o_r_t_ 2.92 newsort This standard procedure creates a zone record in core store which is to take part in a sorting process. The contents of the record is initially undefined, but the user is supposed to assign values to the record variables before next call of any sorting procedure. The so defined record becomes an active record in the sorting process (see procedure outsort). C_a_l_l_: newsort (z, key) or newsort (z) z (call and return value, zone). The name of the record created. key (call value, integer procedure or empty). The name of a procedure for comparison of two re- cords (see below). The key parameter is omitted if standard sequen- cing is used (see procedure startsort6). Z_o_n_e_ _s_t_a_t_e_: The zone state must be 9, in sort, i.e. startsort6 (or initsort) must have been called. The state is not changed by the procedure. S_e_q_u_e_n_c_i_n_g_: The integer procedure key is supplied by the user, when a non-standard sequencing is wanted. It det- ermines which of two records is to appear first in a sorted string of records: C_a_l_l_: key (record1, record2) record1, record2, (call values, arrays). The name of two records to be compared. key (return value, integer). The result of comparison of record1 and record2. This return value must adhere to the following rules. record1 before record2: key < 0 record1 after record2 : key ' 0 sequence unimportant : key = 0 \f E_x_a_m_p_l_e_ _1_: This is an example of a key procedure which can be newsort used to sort a number of records of length 10 real on ascending number of equal words within a single record. integer procedure mostequals(v, w); real array v, w ; begin integer procedure equals(x); real array x ; begin integer count, i, j, k; real z; count:= 0; for i:= 1, i+1 while i<= 10 and count < i do begin z:= x(i); k:= 1; for j:= i + 1 step 1 until 10 do if z = x(j) then k:= k + 1; if k ' count then count := k; end; equals:= count end equals; mostequals:= equals(v) - equals(w) end mostequals; Note that the structure of a record (for instance the record length) is supposed to be known to the procedure as global information (for instance by certain values of certain fields in the record). E_x_a_m_p_l_e_ _2_: 100 records of length 10 double words per record are stored in array B(1:100,1:10). These records are to be sorted on ascending number of equal words within a single record. Therefore, the key procedure of example 1 is used. \f begin newsort zone z(1199,1,sorterror); <*buffer length as required by initsort*' integer i, j; initsort(z, 10); for i:= 1 step 1 until 100 do begin newsort(z, mostequals); for j:= 1 step 1 until 10 do z(j):= B(i, j) end; for i:= 1 step 1 until 100 do begin outsort(z, mostequals); for j:= 1 step 1 until 10 do B(i, j):= z(j) end end; E_x_a_m_p_l_e_ _3_: Same as example 2, but now the sorting is on ascending double word one followed by descending double word five (standard sequencing). begin zone z(1022,1,sorterror); <*buffer length as required by startsort6*' integer i, j; integer array keys(1:2, 1:2); keys(1,1):= 4; keys(1,2):= 4; keys(2,1):=-4; keys(2,2):=20; <* definition of sequencing, see startsort6*' startsort6(z, keys, 2, 40); for i:= 1 step 1 until 100 do begin newsort(z); for j:= 1 step 1 until 10 do z(j):= B(i, j) end; for i:= 1 step 1 until 100 do \f begin newsort outsort(z); for j:= 1 step 1 until 10 do B(i,j):= z(j) end end; \f F_ 2_._9_3_ _ _ _ _ _ _n_o_t_ _(_-_,_)_ 2.93 not This delimiter, which is a monadic logical operator, yields the logical negation of the operand. S_y_n_t_a_x_: -, <operand' P_r_i_o_r_i_t_y_: 6 O_p_e_r_a_n_d_ _t_y_p_e_: boolean R_e_s_u_l_t_ _t_y_p_e_: boolean S_e_m_a_n_t_i_c_: The negation of a boolean gives the result false if the boolean is true and the result true if the boolean is false. E_x_a_m_p_l_e_ _1_: -, b -, (a=2) -, (-,p) is equivalent to p -, (p and q) is equivalent to -,p or -,q -, (p or q) is equivalent to -,p and -,q -, p or q is equivalent to p =' q \f F_ 2_._9_4_ _ _ _ _ _ _n_o_t_ _e_q_u_a_l_ _(_<_'_)_ 2.94 not equal This delimiter, which is a relational operator, gives the value true or false. S_y_n_t_a_x_: <operand1' <' <operand2' P_r_i_o_r_i_t_y_: 5 O_p_e_r_a_n_d_ _t_y_p_e_s_: integer, long, or real. R_e_s_u_l_t_ _t_y_p_e_: always boolean. S_e_m_a_n_t_i_c_: The relation takes on the value true whenever the bitpattern of the two operands are equal, otherwise false. The relation is performed as a bit by bit compari- son of the two operands (after a possible type conversion whenever the operands are of different types). E_x_a_m_p_l_e_ _1_: c:= d <' q; if m <' idle then ... else ... while empty <' full do ... \f F_ 2_._9_5_ _ _ _ _ _ _o_p_e_n_ 2.95 open This standard procedure connects a document to a given zone in such a way that the zone may be used for input/output with the high level zone procedures. C_a_l_l_: open (z, modekind, doc, giveup) z (call and return value, zone). After re- turn, z describes the document. modekind (call value, integer). Mode shift 12 + kind. See below. doc (call value, string or any type array). A text string or an array containing a text, specifying the name of the document as re- quired by the monitor, i.e. a small letter followed by a maximum of 10 small letters or digits. giveup (call value, integer). Used in connection with the checking of a transfer. See below. M_o_d_e_k_i_n_d_: Specifies the kind of the document (typewriter, backing storage, magnetic tape, etc.) and the mode in which it should be operated (even parity, odd parity, etc.). The kind of the document tells the input/output proce- dures how error conditions are to be handled, how the device should be positioned, etc. This kind has nothing to do with the kind mentioned in ref. 1. As a rule, the procedures do not care for the actual physical kind of the document, but disagreements may give rise to bad answers from the document. If you, for example, open a backing storage area with a kind specifying printer, and later attempt to output via the zone, the backing storage area will reject the message because the docu- ment was initialised as required by printer. \f Mode and kind must be coded as shown in the table be-open low. If you attempt a mode which does not fit into the table, an alarm occurs. Kind: 0 i_n_t_e_r_n_a_l_ _p_r_o_c_e_s_s_ 4 b_a_c_k_i_n_g_ _s_t_o_r_a_g_e_ _a_r_e_a_ mode = 0, specifies full error recovery. mode = 2, specifies suppression of automatic error recovery. mode = 4, specifies limited error recovery on parity errors occuring at an input operation. 8 t_e_r_m_i_n_a_l_s_ input modes: mode = 0, intended for conversational operation by means of keyboard. mode = 2, paper tape input from teleterminal, ISO characters in even parity. mode = 4, paper tape input from teleterminal, no parity. output modes: mode = 0, normal text mode. mode = 2, transparent text mode, even parity. mode = 4, transparent output mode, no parity. 10 p_a_p_e_r_ _t_a_p_e_ _r_e_a_d_e_r_ mode = 0, odd parity. mode = 2, even parity. mode = 4, no parity. mode = 6, flexowriter to ISO conversion. 12 p_a_p_e_r_ _t_a_p_e_ _p_u_n_c_h_ mode = 0, odd parity. mode = 2, even parity. mode = 4, no parity. mode = 6, ISO to flexowriter conversion. mode = 8, even parity (<10' implies <13' <10' <127'). \f 14 l_i_n_e_ _p_r_i_n_t_e_r_ open mode = 0, the answer is returned when the transmitted block has been w_r_i_t_t_e_n_. mode = 2, the answer is returned when the transmitted block has been r_e_c_e_i_v_e_d_. 16 c_a_r_d_ _r_e_a_d_e_r_ mode = 0, punched binary. mode = 10, punched decimal with conversion. mode = 64, mark sense binary. mode = 74, mark sense decimal with conversion. mode = 256, basic cards. See ref. 3 for further information. 18 m_a_g_n_e_t_i_c_ _t_a_p_e_: modekind is defined to be: T shift 16 + mode shift 12 + 18 9 track tape: mode = 0, means 1600 bpi MTO mode = 4, means 800 bpi NRZ For output 0 <= T < 6 specifies that the last T physical characters in a block should not be output to the tape. For input T should be 0. 7 track tape: mode = 4, means 556 bpi NRZ mode = 6, means 556 bpi NRZE For the description of T see ref. 3. For further information see ref. 3. If you use T <' 0 during output you should set the word defect bit (1 shift 7) and the stopped bit (1 shift 8) in your give up mask and after a check of halfwords transferred simply ignore the bit in your block proce- dure. \f 18 c_a_s_e_t_t_e_ _t_a_p_e_ open modekind is defined to be: SLEW shift 20 + ECMA shift 19 + T shift 16 + mode shift 12 + kind. ECMA = 1 for ECMA version 1 (read only), = 0 otherwise. SLEW = 0, normal = 1, slew mode T see description of 9-track tape. mode = 4, 800 bpi NRZ For further information about kind and mode, see relevant manual describing the external processes. I_n_i_t_i_a_l_i_s_a_t_i_o_n_ _o_f_ _a_ _d_o_c_u_m_e_n_t_ Open prepares the later use of the document according to kind: Internal process, backing storage area, typewriter: Nothing is done. When a transfer is checked later, the necessary initialisation is performed. Paper tape, card reader: First, open checks to see whether the reader is reser- ved by another process. If it is, the parent receives the message wait for <name of document' and open waits until the reader is free. Second, open initialises the reader and empties it. Third, open initialises the reader again (in order to start reading in lower case), sends a parent message asking for the reader to be loaded, and waits until the first char- acter is available. \f Paper tape punch, line printer: open Open attempts to reserve the document for the job, but the result of the reservation is neglected. Magnetic tape: If the tape is not mounted, a parent message is sent asking for mounting of the tape. The message is sent without wait indication (see ref. 7). Some of these rules have been introduced to remedy a possible lack of an advanced operating system. G_i_v_e_u_p_: The parameter giveup is a mask of 24 bits which will be compared to the logical status word (ref. 15) each time a transfer is checked. If the logical status word contains a one in a bit where giveup has a one, the standard action for that error is skipped and the block procedure is called instead (the block procedure is also called if a hard error is detected during the checking). The bit 1 shift 9 in giveup has a special meaning: If the zone is opened with this bit set to one, and the program is in activity mode, then an implicit passivate statement is executed in the running systems check routine and in monitor (18 ...) making concurrent i/o transfers possible in a program containing coroutines. For further information see ref. 19. Z_o_n_e_ The zone must be in state 4, after declaration. The s_t_a_t_e_: state becomes positioned after open (ready for input- /output) except for magnetic tapes, where setposition must be called prior to a call of an input/output procedure. The entire buffer area of z is divided evenly among the shares and if the document is a backing storage area, the share length is made a multiple of 512 halfwords. If this cannot be done without using a share length of 0, the run is terminated. The logical position becomes just before the first element of block 0, file 0. \f E_x_a_m_p_l_e_ _1_: The normal usage of a tape reader named >reader> goes open like this: begin zone z(25*2,2,stderror); open(z,2 shift 12+10,<:reader:',0); read(z,...);... close(z,true); end; If you replaced stderror with the procedure >list>: procedure list(z,s,b); zone z; integer s,b; write(out,<:<10':',s,b); and called open with 1 shift 1 instead of 0, the block procedure would be activated after each tape transfer and you would get a complete log of the actions of the reader. (The procedure >list> should print in a better way to be really useful). E_x_a_m_p_l_e_ _2_: Assume you need two magnetic tapes in a job. Then the best communication with the operating system is obtaine in this way: open(z1,18,<:mt1706:',0); open(z2,18,<:mt1712:',0); setposition(z1,1,0); setposition(z2,1,0); If none of the tapes are mounted, the operating system may get the messages: mount mt1706 without wait indication (caused by open(z1,...)) mount mt1712 without wait indication (caused by open(z2,...)) mount mt1706 with wait indication (caused by setposition(z1...)) and the job is stopped by the operating system until the tape waited for has been mounted. \f E_x_a_m_p_l_e_ _3_: Nearly all document names will be supplied as data to open the algol program and in many cases the kind and mode are given as data too. A convenient way of doing this is to use the following syntax of the data: <kind and mode' <document name' <possibly a fileno' Kind and mode are represented as the mnemonic code of the fp-utility program >set>. The algol program may then look like this: begin boolean procedure openvar(z,giveup); zone z; integer giveup; begin array text(1:3); integer i,j; openvar:= true; j:= 0; readstring(in,text,1); for i:= 1 step 1 until 17 do if text(1) = real(case i of (<:ip:',<:bs:',<:tw:',<:tro:',<:tre:',...)) then j:= i; if readstring(in,text,1) ' 2 or j = 0 then openvar:= false else open(z,case j of(0,4,8,10,2 shift 12 + 10,...), text, giveup); if j ' 15 then <*magnetic tape*' begin read(in,i); setposition(z,i,0) end; end openvar; ... begin zone master,trans,new(256*2,2,stderror); if -, (openvar(master,0) and openvar(trans,0) and openvar(new,0)) then dataerror else begin inrec6(master,m1); inrec6(trans,t1);... \f F_ 2_._9_6_ _ _ _ _ _ _o_p_e_n_t_r_a_n_s_ 2.96 opentrans This standard procedure outputs a transaction head of a format 8000 transaction, and initiates a zone for character writing. Opentrans may be regarded as the reverse operation of waittrans. Note, that no waiting takes place. C_a_l_l_: opentrans (z, format, destination, aux1, aux2) z (call and return value, zone). Specifies the document to which transactions are transferred. format (call value, integer). Defines the format of the transaction to be sent: 1: read modified format 2: short read format 3: write format 4: read buffer format destination (call value, integer). Designates the receiver of the transaction, i.e. display terminal, computer, or RC8000 application. aux1 (call value, integer). Depending on the format of the transaction, aux1 speci- fies the attention type, write command code, or is not used. aux2 (call value, integer). Depending on the format of the transaction, aux2 speci- fies the cursorposition, write control character, or is not used. Note that in communication with display terminals, only format 3 (write format) can be used. Format 1, 2, and 4 can only be sent to computers or other RC8000 applica- tions. For further details about format, aux1, and aux2 see waittrans. \f Z_o_n_e_ _s_t_a_t_e_: The zone must be open and ready for opentrans opentrans (state 0 or 13), i.e. since the latest call of open, setposition, or closetrans. The state becomes 3, i.e. the zone is ready for character output by means of the procedures writefield, write, outtext, etc. E_x_a_m_p_l_e_ _1_: The following procedure sends the number of sound alarms specified by the parameter no: procedure beep (z, dest, no); zone z ; integer dest, no ; begin integer i, state; getstate (z, state); if state = 3 then closetrans (z); for i:= 1 step until no do begin opentrans (z, 3<*write format*', dest, 49<*write*', 1 shift 2 <*sound*'); closetrans(z); end; if state =3 then opentrans (z, 3<*write format*', dest, 49<*write*', 1<*reset MDT bits*'); end beep; E_x_a_m_p_l_e_ _2_: See example 3 of writefield. \f \f i T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_ 1. INTRODUCTION ........................................... 1 2. THE FRONT PROCESS ADAPTOR .............................. 2 3. FDLC PROTOCOL CHARACTERISTICS .......................... 4 3.1 Transmission Elements ............................. 4 3.2 Error Detection and Correction .................... 4 3.3 Transmission Unit Identification .................. 4 4. PROTOCOL FORMAT SPECIFICATIONS ......................... 5 4.1 Startbyte ......................................... 5 4.2 Statusbyte ........................................ 5 4.3 Textblocks ........................................ 6 4.4 Master Clear ...................................... 6 5. PROTOCOL PROCEDURES SPECIFICATIONS ..................... 7 5.1 Flow Control ...................................... 7 5.2 Initialization .................................... 8 5.3 Error Detection and Correction .................... 8 5.4 Transmission Unit Numbering ....................... 9 5.5 Standard Operation of the Transmitter ............. 9 5.6 Error Actions of the Transmitter .................. 10 5.7 Standard Operation of the Receiver ................ 10 5.8 Error Reactions of the Receiver ................... 11 A_P_P_E_N_D_I_X_: A. REFERENCES ............................................. 13 \f ii \f 1_._ _ _ _ _ _ _ _ _I_N_T_R_O_D_U_C_T_I_O_N_ 1. This manual describes a communication line protocol, the FDLC- protocol (F_PA D_ata L_ink C_ontrol), which is used in CENTERNET to connect the RC8000 host with the RC3502 TC. The protocol is a subset of the FDLC-protocol described in ref. 5. The FPA is a high-speed, 8-bit parallel data communication line. When initated, a transfer may proceed with a speed of up to 600.000 bytes per second. Interfaces exist to FPA-lines on RC8000, RC3600 and RC3500 series of computers. In the network hierarchy of protocol levels generally used in international standards, the FDLC is a level 2 protocol. Thus it functionally corresponds to the HDLC or the X25.2 protocol. Being a reference manual, this description only defines the for- mats and procedures to be followed on the line. Thus this de- scription is independent of the computers actually involved. However, the presence of an FDLC-handler module in the computers is assumed. This module implements the FDLC-protocol on the FPA- line and offers a computer-type-dependent interface to user-mo- dules. \f F_ 2_._ _ _ _ _ _ _ _ _T_H_E_ _F_R_O_N_T_ _P_R_O_C_E_S_S_ _A_D_A_P_T_O_R_ 2. The communication between the computers is carried out using an FPA-connection (Front Process Adaptor). Fig. 1 shows an FPA-con- nection seen from a logical point of view. Figure 1: The logical structure of the FPA-connection. The FPA consists of two subdevices - a transmitter and a receiver. These two devices are totally independent of each other. The FPA transmitter can execute the following tasks: - it can transmit a data block of any size to the receiver - it can receive one single byte - normally holding status information - it can transfer a reset signal which, in case the receiver is waiting for data, will stop the receiver immediately \f - it can transfer an autoload signal, which will activate the autoload function of the computer on which the receiving FPA is situated. The FPA receiver is able to execute the following tasks: - it can be set up for reception of any data block - it can transmit one single byte to the transmitting end of line. An FPA-connection between two computers can be regarded as a pair of independent simplex-lines with a low-volume return channel. Both computers have two channels, a transmitter channel and a receiver channel. A detailed description of the FPA hardware used on RC8000, RC3600 and RC3500 can be found in ref. 1, 2, 3, 4. \f F_ 3_._ _ _ _ _ _ _ _ _F_D_L_C_ _P_R_O_T_O_C_O_L_ _C_H_A_R_A_C_T_E_R_I_S_T_I_C_S_ 3. This chapter gives an overview of the FDLC-protocol and defines the elements of the protocol. Details of formats and procedures are found in the following chapter. 3_._1_ _ _ _ _ _ _ _T_r_a_n_s_m_i_s_s_i_o_n_ _E_l_e_m_e_n_t_s_ 3.1 The protocol is based on the exchange of T_r_a_n_s_m_i_s_s_i_o_n_ _U_n_i_t_s_ _(_T_U_)_. A TU consists of a s_t_a_r_t_b_y_t_e_ followed by a number (at least one) of d_a_t_a_ _b_y_t_e_s_. The receiver of a TU will return a s_t_a_t_u_s_b_y_t_e_ which specifies the result of the transfer and indicates that the receiver is ready for the next transfer. The FPA-connection may be regarded as two independent communica- tion channels (one for each direction). Each channel is unidirec- tional but with a l_o_w_-_v_o_l_u_m_e_ return channel, which is used to re- turn the statusbytes. The startbyte, databytes and the statusbyte each occupy 8 bits. 3_._2_ _ _ _ _ _ _ _E_r_r_o_r_ _D_e_t_e_c_t_i_o_n_ _a_n_d_ _C_o_r_r_e_c_t_i_o_n_ 3.2 Error detection is based on a parity checking mechanism. The FPAs will add a parity-bit to each transmitted byte. The parity is checked by the receiving FPA and an error will be reported. Error correction is based on retransmission of the erroneous TU. 3_._3_ _ _ _ _ _ _ _T_r_a_n_s_m_i_s_s_t_i_o_n_ _U_n_i_t_ _I_d_e_n_t_i_f_i_c_a_t_i_o_n_ 3.3 Retransmission of a TU is detected by a TU-number which is added to each TU. This number counts modulo 2, which means that only one TU may be outstanding waiting for acknowledge. \f F_ 4_._ _ _ _ _ _ _ _ _P_R_O_T_O_C_O_L_ _F_O_R_M_A_T_ _S_P_E_C_I_F_I_C_A_T_I_O_N_S_ 4. This presents the formats used for the various transmission elements. 4_._1_ _ _ _ _ _ _ _S_t_a_r_t_b_y_t_e_ 4.1 All Transmission Units are preceded by a startbyte. It contains the following information: 0 1 2 3 4 5 6 7 0 0 0 0 0 TU _NUMBER TYPE TU _NUMBER: is a modulo 2 sequence number as described in section 3.3. TYPE : 0 Text block 1 Not used 2 Master clear 3 Not used 4_._2_ _ _ _ _ _ _ _S_t_a_t_u_s_b_y_t_e_ 4.2 A statusbyte is returned, when a TU has been received. It indicates whether the TU was received correctly or whether an error occured. A statusbyte has the following format: 0 1 2 3 4 5 6 7 0 0 0 0 0 0 PARITY ERROR BLOCK SIZE ERROR \f P_a_r_i_t_y_ _e_r_r_o_r_ indicates that the parity checking mechanism indicated an error for at least one of the characters received. B_l_o_c_k_ _s_i_z_e_ _e_r_r_o_r_ indicates an overflow in the user buffer, in which the textblock should be stored. The statusbyte should have initial value = 255, see section 5.4. 4_._3_ _ _ _ _ _ _ _T_e_x_t_b_l_o_c_k_s_ 4.3 Textblocks are used to exchange information between the users of the FDLC-protocol. The datapart of a textblock is solely defined by the user and the bytes in the datapart may take any value from 0 to 255. 4_._4_ _ _ _ _ _ _ _M_a_s_t_e_r_ _C_l_e_a_r_ 4.4 A master clear block is used to synchronize the two ends of the transmission line. It is used after initial load or after an irrecoverable error. The master clear block carries no data and consists solely of a startbyte. The master clear startbyte will have: TU _NUMBER = 0 TYPE = 2 \f F_ 5_._ _ _ _ _ _ _ _ _P_R_O_T_O_C_O_L_ _P_R_O_C_E_D_U_R_E_S_ _S_P_E_C_I_F_I_C_A_T_I_O_N_S_ 5. This chapter presents the procedures that are to be followed by the FDLC-handlers. 5_._1_ _ _ _ _ _ _ _F_l_o_w_ _C_o_n_t_r_o_l_ 5.1 Due to the characteristics of the line and the intended use of the protocol, only a rather simple method of flowcontrol is implemented. The flowcontrol is based on the assumption that the users of the protocol should in general always assure that a buffer is ready in which to receive data. If a buffer is not always present, the time in which the F_D_L_C_-_h_a_n_d_l_e_r_ is without a buffer should be short compared to the time-out period after which retransmission will take place. The flowcontrol is implemented by means of the statusbytes in the following manner: A statusbyte is not returned until a buffer is ready for reception of a new (or retransmitted) TU. This means that if the FDLC-handler receives a textblock into the last buffer from the user, it will not return the statusbyte until a new buffer is present. In case this exceeds the timeout value of the transmitter, a re- transmission, will take place. This will, until a buffer is ready, terminate immediately because no input operation is pre- sent at the receiving end. \f 5_._2_ _ _ _ _ _ _ _I_n_i_t_i_a_l_i_z_a_t_i_o_n_ 5.2 During initialization, the FPA-connection is regarded as a pair of totally independant lines, one for each direction. The lines are initialized during initial start up or after an irrecoverable error. The initiative for initialization always rests with the transmitting end of the line. If the receive part of an FDLC-handler receives a master clear startbyte, it should perform the clean up actions necessary and return a statusbyte = 0 (ok), indicating that the receive part is ready to operate. When the transmit part of an FDLC-handler wants to initialize the line, it should transmit a master clear startbyte. If a status- byte = 0 has not been received within a certain time interval, the master clear startbyte should be retransmitted. Having re- ceived the statusbyte (and assuming no error indications) the transmit part is ready to operate. During initial start up of the two FDLC-handlers, the initial- ization described above is performed for both directions. If an irrecoverable error has been detected by only one of the FLDC- handlers or if one of the FDLC-handlers has been restarted, the initialization need only be performed for the direction in- volved. 5_._3_ _ _ _ _ _ _ _E_r_r_o_r_ _D_e_t_e_c_t_i_o_n_ _a_n_d_ _C_o_r_r_e_c_t_i_o_n_ 5.3 Error detection is based on a parity checking mechanism. For each transmitted byte, the FPA will generate a parity bit, which is transmitted along with the byte. If the receiving FPA detects a parity error, it will indicate this in a hardware status. In this case a statusbyte which contains the PARITY ERROR-bit should be returned and the TU will be retransmitted. \f 5_._4_ _ _ _ _ _ _ _T_r_a_n_s_m_i_s_s_i_o_n_ _U_n_i_t_ _N_u_m_b_e_r_i_n_g_ 5.4 All TU's are numbered. The TU-number counts modulo 2. The first TU transmitted after initalization has a TU-number of 1. The transmitter and receiver will each maintain its version of a TU-counter. The TU-counter in the transmitter holds the number of the next TU that is going to be transmitted or is during transmission. The TU-counter is increased by 1 (modulo 2) each time a statusbyte without errorindication has been received. When a TU is trans- mitted or retransmitted, the current value of the TU-counter is inserted as TU-number in the startbyte. The TU-counter in the receiver holds the TU-number that is ex- pected in the next TU. It is increased by 1 (modulo 2), when a TU with this expected TU-number has been received without error. If a TU is received with a TU-number different from what is expected (and it is not a master clear block), the block is ignored and the last statusbyte is transmitted again. The statusbyte does not itself include any TU-number because it will always refer to the TU just received. However, the initial value of statusbyte is used to signal to the transmitting end of the line if a TU-number mismatch has occurred at the receiving end, due to restart of the local FDLC-handler. Therefore, the initial value of statusbyte should be 255. If a statusbyte hold- ing this value is received, this indicates that the TU-counter should be increased by 1 (modulo 2) before retransmission. 5_._5_ _ _ _ _ _ _ _S_t_a_n_d_a_r_d_ _O_p_e_r_a_t_i_o_n_ _o_f_ _t_h_e_ _T_r_a_n_s_m_i_t_t_e_r_ 5.5 The transmitter is the active part in the communication. Its normal working cycle consists of a transmission of a TU, headed by the startbyte after which the transmitter waits to receive the statusbyte. \f Now the transfer is checked by inspecting partly the hardware status from the transmission, partly the received statusbyte. If no errors are indicated, the TU-counter is increased. The operation must terminate within a certain time, if necessary by means of a software timer. The FPA-connection will very seldom cause errors to be imposed on the transmitted data except in case of permanent hardware errors. Therefore the timeout value may be rather big and it should be set to 5 seconds. 5_._6_ _ _ _ _ _ _ _E_r_r_o_r_ _A_c_t_i_o_n_s_ _o_f_ _t_h_e_ _T_r_a_n_s_m_i_t_t_e_r_ 5.6 The standard error action is to retransmit the TU. In order to force the receiver into a well defined state, the retransmission must be initated by transmission of a reset signal. This will terminate a possible input operation at the receiver. After transmission of the reset signal, the transmitter must wait at least 50 msec. to allow the receiver to prepare a new input operation. Then the transmit-operation is repeated. The FPA-line must be initialized if the same block has been transmitted 5 times without success. 5_._7_ _ _ _ _ _ _ _S_t_a_n_d_a_r_d_ _O_p_e_r_a_t_i_o_n_ _o_f_ _t_h_e_ _R_e_c_e_i_v_e_r_ 5.7 The receiver is the passive part in the transmission. Having received a TU, the receiver checks the hardware status for parity errors or blocklength errors, and generates the appropriate statusbyte. Then the statusbyte is returned and a new receive operation issued. \f 5_._8_ _ _ _ _ _ _ _E_r_r_o_r_ _R_e_a_c_t_i_o_n_s_ _o_f_ _t_h_e_ _R_e_c_e_i_v_e_r_ 5.8 Parity error in block received: set PARITY ERROR in statusbyte transmit statusbyte - receive new TU Wrong TU-number in TU: ignore block arrived transmit old statusbyte - receive new TU Blocklength error: Set BLOCK SIZE ERROR in statusbyte transmit statusbyte - receive new TU Master clear received Initialize the FPA-line Any other error situation Receive new TU The receiver should keep on repeating the operation, because the decision of whether to give up is placed at the transmitter. \f F_ \f F_ A_._ _ _ _ _ _ _ _ _R_E_F_E_R_E_N_C_E_S_ A. 1 FPA 801, RC8000 2 FPA 705, RC3600 3 FPA 707, RC3600 4 FPA 100, RC3500 5 RCSL No 43-GL7810: RCNET, FDLC-FPA Data Line Control Erik Lilholt \f F_ \f «eof»