There are two implementations for an MCP String Variable.
In Algol, a String Variable declared as a Local Variable to a Procedure is implemented by allocating a String Variable from the Program's Strings Pool, which is a String Array located in the base of the D[2] Stack. The MCP provides the GetStringArea, GetStringPoolSize and ResetStringPoolSize Intrinsic functions to manage the Strings Pool. This method requires 2 Stack Cells for a String Variable.
In Algol, a String Variable declared as a local variable in a Structure Block is implemented by calling ArrayDec. This method requires 3 Stack Cells for a String Variable.
A String Variable allocated from the Strings Pool is described by a Copy Descriptor to an Ebcdic Array containing the String Data and above it, a Single Precision Operand which contains the current logical length of the String Data.
002C (02,0016) 0 000000 000000 002B (02,0015) C F20000 001DF9 HEXSTRING (Hex variable) Absent-copy, ASD=00EFCF, Hex, Length=264 (Unreferenced olay space) 002A (02,0014) 0 000000 000000 0029 (02,0013) C D40000 001D6D ASCIISTRING (ASCII variable) Absent-copy, ASD=00EB6E, EBCDIC, Length=132 (Unreferenced olay space) 0028 (02,0012) 0 000000 000000 0027 (02,0011) C B40000 001E27 EBCDICSTRING (EBCDIC variable) Absent-copy, ASD=00F13D, EBCDIC, Length=132 (Unreferenced olay space)
String Variables are managed by the GetStringArea, GetStringPoolSize ResetStringPoolSize Intrinsic functions.
A maximum of 500 String variables can be allocated using these String Intrinsics. (Note: This limit applies only to String Variables, and does not include Strings in String Arrays which are created using ArrayDec, nor to String Variables allocated in a Structure Block).
Although the Algol Compiler differentiates between ASCII and EBCDIC Strings, the architecture does not.
The declaration of GetStringArea is in the MCP at 10810000,
WORD PROCEDURE GETSTRINGAREA;
It returns an Untouched Copy Descriptor to an element in the String Pool of the current Stack.
This is an example of a call to GetStringArea to declare a String Variable.
CodeSegment.MKSN; CodeSegment.NMC1(D1_Stack.MCPIntrinsicSDI(GetStringAreaV)); CodeSegment.ENTR; CodeSegment.ZERO;
The Compiler creates a Hex String by setting the Character Size of the Untouched Descriptor to HexV.
CodeSegment.MKSN; CodeSegment.NMC1(D1_Stack.MCPIntrinsicSDI(GetStringAreaV)); CodeSegment.ENTR; CodeSegment.SE4C; CodeSegment.ZERO;
Since a String Variable is represented by a Copy Descriptor, there is no BlockExit action required.
However, if String Variables are not returned to the Strings Pool upon exiting a procedure, then they can no longer be reused and eventually the Strings Pool will be exceeded.
The GetStringPoolSize and ResetStringPoolSize Intrinsics are provided to manage the Strings Pool as a Stack.
In a Block which declares a String Variable, the Compiler allocates a variable called a 'String Pool Size Location', and calls GetStringPoolSize to initialize it to the current Strings Pool Top.
The Compiler then allocates String Variables by calling GetStringArea.
The Compiler generates an Epilog Procedure for the Block, and calls ResetStringPoolSize with the previously saved String Pool Top, thereby releasing any String variables declared in the Block.
The declaration of GetStringPoolSize is in the MCP at 10820000,
REAL PROCEDURE GETSTRINGPOOLSIZE;
The declaration of ResetStringPoolSize is in the MCP at 10830000,
PROCEDURE RESETSTRINGPOOLSIZE(S); VALUE S; REAL S;
This code was produced by the Algol Compiler.
PROCEDURE P; (02,0002) = P Begin String S; (03,0002) = STRING POOL SIZE LOCATION (03,0003) = S (03,0004) = S.LENGTH End; (01,0005) = RESETSTRINGPOOLSIZE 0004:0000:1 MKSN DF 0004:0000:2 NAMC (01,0005) 6005 RESETSTRINGPOOLSIZE 0004:0000:4 VALC (03,0002) 3002 0004:0001:0 ENTR AB 0004:0001:1 EXIT A3 ********************** STACK BUILDING CODE FOR LEVEL 03 ******************************* (03,0002) (01,0006) = GETSTRINGPOOLSIZE 0004:0001:2 MKSN DF 0004:0001:3 NAMC (01,0006) 6006 GETSTRINGPOOLSIZE 0004:0001:5 ENTR AB (03,0003) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = (01,0007) = GETSTRINGAREA 0004:0002:0 MKSN DF 0004:0002:1 NAMC (01,0007) 6007 GETSTRINGAREA 0004:0002:3 ENTR AB 0004:0002:4 ZERO B0 0004:0002:5 BRUN 0004:3 A26004 0004:0003:2 MKSN DF 0004:0003:3 NAMC (01,0005) 6005 RESETSTRINGPOOLSIZE 0004:0003:5 VALC (03,0002) 3002 0004:0004:1 ENTR AB 0004:0004:2 EXIT A3 (03,0005) = STRING POOL EPILOG PCW 0004:0004:3 MPCW BF 0004:0005 0004:0003:2 000400312004 0004:0006:0 PUSH B4 0004:0006:1 LT48 BE 0004:0007 800000200000 0004:0008:0 LT8 6 B206 0004:0008:2 STAG 95B4 0004:0008:4 BRUN 0000:1 A22000
A String Variable allocated using ArrayDec occupies 3 Stack Cells.
At the lowest address is a Tag 4 String Marker, followed by an Untouched_DD MOM Descriptor for the EBCDIC Array which contains the String's Data, and finally a Single Precision Operand which contains the current logical Length of the String Data.
The Stack Cells are created by calling the MCP ArrayDec Intrinsic.
001A (02,0004) C E00000 001F97 T1 (Structure block) Present-mom, ASD=00FCBF, Length=26
0(0000) 3 08CD00 160000 1 80FCBF 000000 0 000000 000000 0 000000 000001 0 000000 000001 2
000000 000001 2 000000 000001
7(0007) 6 000000 000000 4 000FFF EC0000 5 040008 400000 0 000000 000000 C E00000 001E50
0(0000) 0 000000 000000 Thru 10(000A)
The declaration of ArrayDec is in the MCP at 4709950,
PROCEDURE ARRAYDEC (SIRW_TO_MOM,NO_OF_DIMS,TYPE_INFO); VALUE SIRW_TO_MOM, NO_OF_DIMS, TYPE_INFO; REAL NO_OF_DIMS; WORD SIRW_TO_MOM, TYPE_INFO;
ArrayDec is declared as a PROCEDURE and behaves as one for Strings. The Compiler is responsible for allocating the Stack Cells. ArrayDec stores the String Marker at the Stack Cell below the SIRW_TO_MOM, the Ebcdic String Array Untouched_DD at the SIRW_TO_MOM, and it leaves the Integer in the Stack Cell above the SIRW_TO_MOM as it was allocated by the Compiler.
ArrayDec deletes the Top 2 Stack Items passed under it's MSCW, which are the Maximum String Length and the Initial String Length hidden dimension. These items are used by ArrayDec to create the String Marker.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% First store the MOM template. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% WORD VIA MOM_REF := IDD; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Now address the SIW slot below the MOM and store the SIW. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MOM_REF.SIRWDELTAF := * - 1; WORD VIA MOM_REF := 0 & THIS_STACK [HIST_TOP-1] STRINGMAXLENGTHF & FAULTSTRINGMARK FAULTMARKF & SIW TAG;
STRINGMAXLENGTHF = [39:20] @ 10802800
This code was produced by the Algol Compiler.
Type Structure Block T_1; (02,0002) = STRUCTURE BLOCK PCW (02,0003) = T_1 Begin (03,0002) = T_1 SELF DESCRIPTOR String S; (03,0003) = STRING MARKER (03,0004) = S (03,0005) = S.LENGTH 0003:0000:1 LT8 132 B284 0003:0000:3 LT16 65534 B3FFFE (01,0004) = ARRAYDEC 0003:0001:0 MKSN DF 0003:0001:1 NAMC (01,0004) 6004 ARRAYDEC 0003:0001:3 NAMC (03,0004) 7004 0003:0001:5 STFF AF 0003:0002:0 ONE B1 0003:0002:1 LT8 4 B204 0003:0002:3 BSET 41 9629 0003:0002:5 ENTR AB End;
The use of the Strings Pool takes advantage of the Stack to dynamically allocate and delete String Variables without the cost of repeated Initial Presence Bit action.
A Structure Block is a permanent Procedure instance, hence the static allocation of a String Variable.
In addition to ArrayDec and the String Pool functions, the MCP provides support for the automatic resizing of the String as it expands in size.
When modifying a String, the compiler generates the same machine code used in an Algol REPLACE statement.
For a normal array, if the boundary of the destination array is reached before the operator has completed, a STRING PROTECT (SEG ARRAY) error is reported.
However, when the fault occurs with a String, the MCP resizes the String Data Array, and resumes the interrupted operator.
The fault is handled by calling HWIVP_DESTINATION_BOUNDARY at 11110800,
IF GETSPACEARRAY(P2) THEN BEGIN IF STRINGSTRETCHER (POINTER (P2), MIN ((2 * (DESCRIPTORSIZE (P2, TRUE) DIV IF CHARSIZE (P2) = HEXV THEN HEXADESPERWORD ELSE BYTESPERWORD )), 1000) * BITS_PER_WORD, INSET (SPACEUSAGE (P2), SEGSEG_SET)) THEN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % THE STRING WAS STRETCHED. THEREFORE RESUME. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% RESUME (P1); END;
Strings are allocated by ARRAYDEC, and are therefore a GETSPACEARRAY .
The STRINGSTRETCHER function is at 10840000.
BOOLEAN PROCEDURE STRINGSTRETCHER(DESC, RESIDUE, SEGED); VALUE DESC, RESIDUE, SEGED; POINTER DESC; REAL RESIDUE; BOOLEAN SEGED;
DESCRIPTION: STRINGSTRETCHER IS CALLED WHEN THERE IS A POSSIBILITY THAT A STRING SHOULD BE STRETCHED. THE FOLLOWING ACTIONS MAY BE TAKEN: IF THE STRING IS ALREADY SEGMENTED ONE OR MORE SEG_ARRAY_ROW SIZE SEGMENTS ARE ADDED TO THE STRING. OTHERWISE IF THE STRING IS LESS THAN SEG_ARRAY_ROWSIZE WORDS IT IS EXPANDED TO A MULTIPLE OF STRING_EXP_INCREMENT WORDS LARGE ENOUUGH TO HOLD LEN+RESIDUE, OR SEG_ARRAY_ROWSIZE. OTHERWISE THE STRING IS TURNED INTO A SEGMENTED STRING. . PARAMETERS: DESC: THE DESTINATION DESCRIPTOR THAT WAS INVOLVED IN THE ARRAY INTERRUPT. RESIDUE: THE NUMBER OF BITS TO BE TRANSFERED TO COMPLETE THE INTERRUPTED OPERATOR. SEGED: TRUE IFF THE DESTINATION DESCRIPTOR POINTS AT A "SEGSEG". . RESULTS: STRINGSTRETCHER RETURNS FALSE IF THE DESTINATION DESCRIPTOR IS NOT A STRING DESCRIPTOR OR IF COMPLETION OF THE INTERRUPTED OPERATION WOULD EXCEED THE MAX SIZE FOR THE DESTINATION STRING. OTHERWISE: RETURNS TRUE IF THE STRING IS STRETCHED AND NOT SEGMENTED. RETURNS BOOLEAN(3) IF THE STRING IS STRETCHED AND IS NOW SEGMENTED. . ASSUMPTIONS: WE MUST NOT LOSE CONTROL OR BUZZ LOCKS USED BY SYSTEMSTATUS. SEE COMMENT AT START OF HARDWAREINTERRUPT PROCEDURES. . SIDE EFFECTS: NONE. . LOCKS: NONE.
The function checks if the Array is part of a String, by checking the Tag 4 Word located below the Descriptor.
TWORD:= STACKDESC[STKLOC-1]; IF (TWORD.TAG EQL SIW) AND (TWORD.FAULTMARKF EQL FAULTSTRINGMARK) AND (TWORD.STRINGMAXLENGTHF*CS - LEN GEQ RESIDUE) THEN BEGIN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % THIS STRING MAY BE STRETCHED AS IT HAS NOT REACHED ITS % MAXIMUM LENGTH. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
To pass a String By Reference, the Algol Compiler generates an SIRW for both the Length and the Descriptor.
String S; (03,0003) = STRING MARKER (03,0004) = S (03,0005) = S.LENGTH 0003:0005:1 NAMC (03,0004) 7004 0003:0005:3 STFF AF 0003:0005:4 NAMC (03,0005) 7005 0003:0006:0 STFF AF