This file documents the utility functions available to hardcoded macros in the mp processor. First, some definitions: str(mp) = a structure used to store strings internal to mp. There are two varietys. One is a single string, the other is a multiple string structure. The format of both are similar, they were originally only one type, but for cases where only one string was being manipulated, the overhead was great. So, a special case occurs where there is just one string. The structure is a block of 6 words of header data followed by n bytes of string storage. Strings are stored as a single byte count followed by count bytes. No allignment on word boundarys. Where there are null strings, a zero is stored in the count, and the next byte is the next strings count. Otherwise, we have: count/text, count/text etc. The format of the 6 header words is only important if multiple strings are stored. These strings usually represent a macro line which has been broken into its name and parameters. The first string is the name unless the line had contained a label. This was a poor design choice as it means at times a test has to be made to determine where the parameters are. To circumvent this, all lines processed only inside macros assume no labels present on a line. str1(mp) = a string like above, but must be of the single string variety. strn(mp) = like above but a 20 string structure. Note that where a strn(mp) is accepted, then a str1(mp) will work provided the first string is being accessed only. However, the reverse is not true. This is because when only 1 string is present no shifting of strings is necessary thus pointers and other header stuff is not updated. "str" = an asciz string (either literal or the address of) "ex" = an asciz string to be expanded. There are two routines which are called by the dispatcher: hards[function-code,s,t,n,l] let[s,t,n,l] There is a convention which permits the 4 parameters to be passed around as a single parameter. The address of the location where s is stored is used to represent an array of 4 words. Thus where the notation is &s this means the address of parameter s. These 4 parameters are the context in which a macro can be evaluated. S = the original line intact. T = the same line but broken into arguments (or tokens). N = the number of tokens in T. l = 0 or -1 (0 = no label present, -1 = there is a label) The following functions exist for hard coded macro statements. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - expand["str",str1(mp),&s] Expands "str" into str1(mp) according to the context of &s. "str" would usually contain argument references (like found in macro lines). Example: . expand["let #@5 = #@1",m,&s] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - state[str(mp)] outst[str(mp)] Each of these take an str(mp) and either recursively expand as a statement (state) or just directly output it (outst). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exjsr[#routine,"ex",&s] Executes routine as routine[s,t,n,l] using "ex". Thus it evaluates "ex", replacing any argument references (via the &s reference) and then breaks it into tokens and calls routine. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exstate["str",&s,str(mp) or #0] Expands "str" using &s into str(mp) and outputs it recursively. IF str(mp) is #0 then it allocates a str(mp) internally. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exout[- - -] Not yet. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - n=toks[str1(mp),strn(mp)] breaks up str(mp) into n tokens into strn(mp) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - stack[str1(mp),loc] places the contents of the string stack at location loc into the string str1(mp). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - labl[n,&s] Replaces parameter n in context s with a generated label. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - strng[str1(mp),"str"] copies "str" into str(mp) creating a str1(mp) string (even if str(mp) had been allocated as a 20 string str(mp).) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - instr[str(mp),size] initializes a str(mp) into a strn(mp) of n = size (but 20 is the convention). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - copy[s1,i1,s2,i2] s1 and s2 are strn(mp), and i1 and i2 are integers. This is like saying: s1(i1):=s2(i2); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - addr=fndstr[str(mp),i] returns the address of the count field in string i in str(mp). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mvstr[str1(mp),strn(mp),i] this is copies the i'th string in strn(mp) into str1(mp). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - result=cmpstr[str(mp),i,str(mp),j] compares 2 strings, 0 is equal, -1 is not equal. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - n=ifnstr[n,strn(mp),str1(mp)] returns position of str1(mp) in strn(mp) as 1,2,3... or else 0 if not there. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - n=ifrec1[fndstr[str(mp)]] returns n=1 if a recursive string, else n=0 if not - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - summary - - - - - - - - - - - - - - - - - - - - - - - - - - - addr=fndstr[str(mp),i] find addr of string copy[s1,i1,s2,i2] copy s1(i1)=s2(i2) exjsr[#routine,"ex",&s] expand & execute routine expand["str",str1(mp),&s] expand "str" into str1 exstate["str",&s,str(mp) or #0] expand "str" an& execute hards[function-code,s,t,n,l] hards processor instr[str(mp),size] init str(mp) labl[n,&s] generate labels let[s,t,n,l] let processor mvstr[str1(mp),strn(mp),i] move strn into str1 n=ifnstr[n,strn(mp),str1(mp)] if in string n=ifrec1[fndstr[str(mp)]] if recursive n=toks[str1(mp),strn(mp)] tokenize str1 into strn outst[str(mp)] output non-recursive result=cmpstr[str(mp),i,str(mp),j] compare strings stack[str1(mp),loc] stuff stack state[str(mp)] execute statement strng[str1(mp),"str"] copy "str" into str1(mp)