The length of the space in the variables area for the string is specified by the left-hand side of the LET statement, the specification of the variable in assignment; the length of the variable being assigned, the right-hand side, may not match.The work space is first filled with spaces, then if the string being assigned is shorter, use its own length, if the space is shorter use its length - so the string gets Procrusteanly curtailed. See pages 52 and 80 of the old Spectrum handbook, p. 62 of the Spectrum +2 book: when a string value is assigned to afixed length variable, the string assigned "is cut off on the right if it is too long, or filled out with spaces if it is too short - this is called Procrustean assignment after the [legendary Greek] inn-keeper Procrustes who used to make sure that his guests fitted the bed by either stretching them out on a rack or cutting their feet off." In L ADD$, when an old complete simple string is replaced, the new string is added to the variables area_before the old one is deleted; momentarily there are two variables withthe same name. There could be an "Out of memory" error here, even though there is really room for the new variable once the old one is deleted - tiresome, especially if the new string is shorter than the old. Input parameters: none - the value to be assigned, numeric or string parameters,is last value on the calculator stack - 5C4D DEST holds an address, which for a new variable is the first letter of the variable name in the program area; for a declared numeric variable is the byte before the five bytes of the FP value of the variable in the variables area; for a declared string variable is the first byte of the value of the variable in the variables area - FLAGX bit 1, misprinted FLAGS in the heading notes, is set for a new variable, and bit 0 is set for a "complete simple string", ie a string of which the version in the variables area doesn't have arecord of its length - FLAGS bit 6 is set for a numeric variable, zero for a string variable. Action: get a pointer to the variable from 5C4D DEST - if FLAGX shows an old variable jump on to L EXISTS - (new variable; the pointer is on the start of the variable name in the BASIC command) make a byte counter 05; fivebytes in a numeric value or pair of string parameters. _2B0B_L_EACH_CH: increment the byte counter to allow for another byte; initially for the variable letter. _2B0C_L_NO_SP: move on the variable pointer and read the next character - if it is 20h space jump back to L NO SP; spaces are ignored in variable names - if it is more than 20h jump on to L TEST CH - if it is less than 10h or more than 15h jump on to L SPACES; control codes 00 -> 0F and 16 -> 1F are all taken as terminating a variable name. The only code in these categories which one could attempt to include in a variable name from BASICis a PRINT comma inserted in the variable name by E mode 6 followed by DELETE; this passes syntax, but all of the variable name following the PRINT comma is ignored. A variable name "hello PRINT comma Johnny" is read as "hello" - (this leaves 10 INK -> 15 OVER, most of which can be included in variable names; they are ignored at this stage but cause trouble elsewhere, see under 28B2 LOOK VARS) step over theparameter which follows the control code - jump back to L NO SP; ignoring both and stepping the variable pointer on to the next letter of the variable name. _2B1F_L_TEST_CH (a code 21h or more): call 2C88 ALPHANUM - if the character is alphanumeric jump back to L EACH CH; reading it as the next character of a long variable name - if it is "$" jump on to L NEW$; this is a new simple string variable. _2B29_L_SPACES (we now have the full name of a new numeric variable, not an array, and its length): get a pointer on the end of the variables area from 5C59 E LINE - call 1655 MAKE ROOM to make space there of the length of the variable with its letter or letters - set pointers on 5C4D DEST and the first byte of the space in the variables area - stack a pointer to the second byte in the space; recovered in L SINGLE - reduce the length by 6 - if this leaves zero jump on to L SINGLE; a short name. _2B3E_L_CHAR (long name): skip the first variable letter - read the next code - if it is less than 21h jump back to L CHAR; skip spaces and control codes - set bit 5 of the code, converting upper to lower case - increment the variables area pointer and copy the codeto it - loop back to L CHAR for the next character till the length counter reaches zero - (counter is zero, but since the first letter was skipped, there is still one code left) set its hi bit; marking the end of a long name - copy it to the variables pointer - make a mask 11000000b/C0h for the flag bits which go in the three hi bits of the first character of a long name. _2B4F_L_SINGLE: get the variable pointer from 5C4D DEST again - XOR it with the mask; if the variable name is a singleletter, the routine jumped here from L SPACES with a zero mask, and since letters have codes from 01000001b/41h "A" to 01111010b/7Ah "z", short names will now start with 01 and long names with 10 - set bit 5 for lower case; now the letter flags are 011for short names and 101 for long, see under variables - recover the pointer to byte 2 of the new place in the variables area; it was stacked in L SPACES - call 2BEA L FIRST, which puts the flagged variable letter in byte 1 and sets a pointer on the end of the variables area. _2B59_L_NUMERIC (this exit is common to both old and new numeric variables): use 0028 FP CALC and 02 delete; the value assigned to the variable, the last value on the calculator stack, is deleted, ie no longer counts as part of the stack, butits five bytes are still in the same location, and DE is now on the stack end, which is the first of these five bytes - make a counter of five for the bytes - point HL at the location for the value in the variables area - exit into 2BA6 L ENTER, which copies the five bytes from DE to HL. _2B66_L_EXISTS (an old variable; in this case the variable pointer from 5C4D DEST is on the old value in the variables area, or one byte before it in the case of a numeric variable): if FLAGS indicates a string variable jump on to LD DELETE$ - (numeric variable) move the pointer on six places pastthe old value in the variables area - jump back to L NUMERIC; all numeric variables have thesame length for their value, so the old value can be simply overwritten, without deleting it. _2B72_L_DELETE$ (an old string variable or array): get the start from 5C4D DEST; actually this is in HL already, as thenotes point out - get the length from 5C72 STRLEN - if FLAGX signals a simple string jump on to L ADD$ - (array or slice) check the length of the variable in assignment - if it is zero return at once; there is no assignment to be made. This could only happen with a slice, you can't have arrays with zero-length elements - call 0030 BC SPACES to make the required number of spaces in the work space - save the pointers to the variables area and work space, and the length - fill the space in the work space with spaces - call 2BF1 STK FETCH to get the string parameters of the string to be assigned - check its length with the length made in the work space - if there is enough room in the work space jump on to LLENGTH - (the string being assigned is longer than the space made for it) use the length available; this is Procrustean shortening. _2B9B_L_LENGTH: check the length of the string being assigned - if it is a slice of zero length jump on to L IN W/S - copy it to the work space. _2BA3_L_IN_W/S: get back the pointers to the variables area and work space, and the length - exit into 2BA6 L ENTER to copy the string into the variables area. [2BA6 L ENTER has a separate entry in this index, since it is useful as a free-standing subroutine even though in the ROM it is just an exit routine.] _2BAF_L_ADD$ (an old complete single string; HL and 5C4D DEST are pointing to the first letter of the string in the variables area): move the pointer back three spaces; over the 2 length bytes to the variable letter - read the letter; it already has the proper flag bits - save its start and length; which came from 5C72 STRLENin L DELETE$ - call 2BC6 L STRING, which puts the new variable at theend of the variables area - recover the start and length of the old variable - add three to the length for the letter and length bytes - exit into 19E8 RECLAIM 2 to delete it. _2BC0_L_NEW$ (a new complete single string; 5C4D DEST points to the variable letter in the BASIC command): AND the variable letter with 11011111b/DFh to make the correct flags - exit into 2BC6 L STRING, which puts the new value of the variable at the end of the variables area. Exit: RET from L DELETE$ for a null string in assignment - into 2BA6 L ENTER from L NUMERIC and from L EXISTS through L NUMERIC to copy a FP number into the variables area - and from L IN W/S to copy a string to the variables area - into 19E8 RECLAIM 2 from L ADD$ to delete an old variable after entering the new version. Output parameters: none, except where input parameters are made for the various exit routines. Called from: 1D16 F REORDER 219B IN VAR 6 Exit from: 1C59 VAL FET 2 (1C56 VAL FET 1) Rems: 1DEC READ 3 similar to a series of LETs 2AB1 STK ST 0 flag byte of string parameters used by letter and digit keys see character codes letter of variable see variables L EXISTS 2B66 (2AFF LET) Jumps from: 2AFF LET L FIRST subroutine 2BEA An "ad hoc" subroutine: somebody noticed that the same sequence of instructions was used twice, so why not make it a subroutine? But it makes little sense out of context. Input parameters: A holds a byte, HL an address; in the ROM, A is a variable letter and HL the bottom of a new block just added to the variables area. Action: move HL down one - put A in it; overwriting what was the end marker of the variables area - reload HL from 5C59 E LINE and move it down one. Exit: RET. Output parameters: HL holds the address of the 80-byte marking the end of the variables area; others unchanged. Called from: 2B4F L SINGLE Exit from: 2BC6 L STRING LIMIT of FOR ... NEXT loops see FOR ... NEXT loops limit value see 2ACC INT EXP1 LINE key (CA) see also KEYBOARD SCANNING, 0284 key table (f) The 3 key in E mode with symbol shift produces the tokenLINE, which is neither command, function nor operator; a sort of"adverb", like DATA in SAVE/LOAD statements or STEP in FOR statements. It has two quite unrelated uses, in INPUT commands and in SAVE/LOAD commands; see INPUT key, 20C1 IN ITEM 1 under 2089 INPUT, and 0605 SAVE ETC. 0716 SA LINE jump forward with SAVE ... LINE 0723 SA LINE 1 find line number for SAVE ... LINE 073A SA TYPE 0 type 0 for SAVE ... LINE 0873 LD PROG checks whether line number was saved 0F38 ED LOOP gets AT/TAB values for INPUT LINE ... 1076 ED SYMBOL jump if dealing with INPUT LINE ... 20D8 IN ITEM 2 handles INPUT LINE ... 20ED IN ITEM 3 excludes INPUT LINE ... 20FA IN PROMPT jump if dealing with INPUT LINE ... 2129 IN PR 3 jump if dealing with INPUT LINE ... 215E IN VAR 3 collects LINE (a string) 2174 IN VAR 5 jump if dealing with INPUT LINE ... 219B IN VAR 6 stacks parameters of LINE line see line of ... LINE ADDR subroutine 196E Given a BASIC line number, finds the start addresses in the program area of the first line with that or a higher number,and of the line before. If the given line number is higher than any line in the program, the "next line number" reached in the end will either be the 80-byte, giving a line number at least 8000h/32768d, or avariable letter, which will indicate a line number at least 4000h/16384d. If the subroutine were called with a line number value larger than these, it wouldn't work. Input parameters: HL holds the number of the line in normal lo-hi form. Action: make two pointers to the start of the program area from 5C53 PROG; both are on the first line number. _1974_LINE_AD_1: call 1980 CP LINES - if it makes NC return; the line number found at the pointer is equal to or more than the given one - call 19B8 NEXT ONE, which advances one pointer to the next line number and returns with the other on the old number - jump back to LINE AD 1 with the advance pointer on thenew line number. Exit: RET, in 1974 LINE AD 1. Output parameters: HL holds the start address of the BASIC line - DE the address of the line before - BC holds the input line number - the Z flag indicates "exact line number found". Called from: 0FA9 ED EDIT 1059 ED UP 155D MAIN ADD 1795 AUTO LIST (twice) 17E4 AUTO L 3 1822 LIST 5 190F LN FETCH 1B9E LINE NEW 1E45 REST RUN LINE AD 1 1974 (196E LINE ADDR) Exit from: 196E LINE ADDR Jumps from: auto line counter see DISPLAY AREA LINE DRAW 2477 (2420 DRW STEPS) Jumps from: 2382 DRAW 238D DR 3 PRMS 23A3 DR SIN NZ 23C1 DR PRMS LINE DRAWING SUBROUTINE see 24B7 DRAW LINE