-- ComStringA.Mesa Curry - September 26, 1980 DIRECTORY AltoFileDefs, Ascii, ComString, IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs; ComStringA: PROGRAM IMPORTS IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs EXPORTS ComString = BEGIN OPEN ComString, IODefs, StreamDefs, StringDefs; OpenCommandLine:PUBLIC PROCEDURE RETURNS [ in:DiskHandle ]= BEGIN OPEN AltoFileDefs, MiscDefs, SegmentDefs; cfa: POINTER TO CFA; cfa _ CommandLineCFA[]; in _ CreateByteStream[InsertFile[@cfa.fp, Read], Read]; JumpToFA[in, @cfa.fa]; END; CloseCommandLine:PUBLIC PROCEDURE[in:StreamHandle]= BEGIN OPEN AltoFileDefs, MiscDefs, SegmentDefs; cfa: POINTER TO CFA; streamIndex:StreamIndex; cfa _ CommandLineCFA[]; streamIndex _ GetIndex[in]; streamIndex.page _ streamIndex.page + cfa.fa.page; streamIndex.byte _ streamIndex.byte + cfa.fa.byte; streamIndex _ NormalizeIndex[streamIndex]; cfa.fa.page _ streamIndex.page; cfa.fa.byte _ streamIndex.byte; in.destroy[in]; END; StrToIndex : PUBLIC PROCEDURE [ str:STRING, sad:StrArrayDesc ] RETURNS [ index:CARDINAL ] = -- 0 => Not found BEGIN refstr:STRING; i:CARDINAL; FOR i_1, i+1 DO refstr _ sad[i] ; IF refstr = NIL THEN EXIT; IF CompareStrings[refstr,str] = 0 THEN RETURN [i]; ENDLOOP; RETURN [0]; END; -- Tries to find str using sad:StrArrayDesc -- If not found then found _ No -- If str is part of or equal to only one string then -- found _ Yes -- unkstr is filled out -- if addstr present -- then addstr gets remainder of string -- else the remainder is output using IODefs.WriteStr -- If str is part of more than one string then -- found _ Multiple -- unkstr is filled out to point of disaggreement -- if addstr # NILL -- then addstr gets additions to string -- else the additions are output using WriteStr StrFill: PUBLIC PROCEDURE [ unkstr:STRING, sad:StrArrayDesc, addstr:STRING _ NIL ] RETURNS [ found:Found ] = BEGIN refstr:STRING _ [1]; tempstr:STRING _ [100]; comp:INTEGER _ 0; i,j:CARDINAL _ 0; refSstr, unkSstr:SubStringDescriptor _ [unkstr,0,unkstr.length]; found _ No; FOR i_1, i+1 DO refstr _ sad[i]; IF refstr = NIL THEN EXIT; comp _ CompareStrings[unkstr,refstr]; IF comp = 1 THEN LOOP; IF comp = 0 THEN GOTO Equal; IF refstr.length <= unkstr.length THEN LOOP; refSstr _ [refstr,0,unkstr.length]; IF NOT EquivalentSubString[@unkSstr,@refSstr] THEN LOOP; IF found = No THEN BEGIN refSstr.offset _ unkstr.length; refSstr.length _ refstr.length - unkstr.length; AppendSubString[tempstr, @refSstr]; END ELSE FOR j IN [0..tempstr.length-1] DO IF refstr.length > j+unkstr.length AND tempstr[j] = refstr[j+unkstr.length] THEN LOOP; tempstr.length _ j; IF j=0 THEN GOTO Nohelp; EXIT; ENDLOOP; IF found # No THEN found _ Multiple ELSE found _ Yes; REPEAT Equal => BEGIN found _ Yes; tempstr.length _ 0; END; Nohelp => found _ Multiple; ENDLOOP; IF tempstr.length > 0 THEN IF addstr # NIL THEN BEGIN addstr.length _ 0; AppendString[addstr,tempstr]; END ELSE WriteString[tempstr]; AppendString[unkstr,tempstr]; END; GetKeyboardCommand:PUBLIC PROCEDURE [queststr:STRING, sad:StrArrayDesc] RETURNS[index:CARDINAL] = BEGIN OPEN IODefs; i,j:CARDINAL; char:CHARACTER; found:Found _ No; resultstr:STRING _ [100]; WHILE found # Yes DO resultstr.length _ 0; WriteString[queststr]; DO char _ ReadChar[]; SELECT char FROM TAB, ESC => GOTO possibles; '?, DEL, CR => GOTO restart; ENDCASE => BEGIN WriteChar[char]; AppendChar[resultstr, char]; found _ StrFill[ resultstr, sad]; IF found = Yes THEN GOTO foundIt; IF found = No THEN GOTO restart; END; REPEAT foundIt => EXIT; possibles => FOR i_1, i+1 WHILE sad[i] # NIL DO IF sad[i].length > resultstr.length THEN FOR j IN [0..resultstr.length) DO IF sad[i][j] # resultstr[j] THEN EXIT; REPEAT FINISHED => BEGIN WriteChar[SP]; WriteString[sad[i]]; END; ENDLOOP; ENDLOOP; restart => BEGIN WriteChar[CR];WriteString["Commands are: "]; FOR i IN [1..100) WHILE sad[i] # NIL DO WriteString[sad[i]]; WriteChar[SP]; ENDLOOP; END; ENDLOOP; WriteChar[CR]; ENDLOOP; index _ StrToIndex[resultstr,sad]; END; GetStreamCommand:PUBLIC PROCEDURE[ stream:StreamHandle, sad:StrArrayDesc, substr:STRING] RETURNS[index:CARDINAL] = -- 0 if command not found BEGIN comstring:STRING _ [100]; [] _ GetStreamArg[stream, comstring, substr]; index _ StrToIndex[comstring,sad] END; GetStreamArg:PUBLIC PROCEDURE[ stream:StreamHandle, argstr:STRING, substr:STRING ] RETURNS[argfound:BOOLEAN] = BEGIN get:PROCEDURE RETURNS[CHARACTER] = BEGIN RETURN[ stream.get[stream]] END; end:PROCEDURE RETURNS[BOOLEAN] = BEGIN RETURN[ stream.endof[stream]] END; RETURN[GetArg[get, end, argstr, substr]]; END; -- Parses sourcestr starting at index to get next arg -- Returns 0 if arg not found -- Otherwise returns index of next char -- Strings rep: SingArgStr/SubStr or SingArgStr[SubStr] GetStringArg:PUBLIC PROCEDURE[ sourcestr:STRING, index:CARDINAL, argstr:STRING, substr:STRING] RETURNS[CARDINAL] = BEGIN get:PROCEDURE RETURNS[CHARACTER] = BEGIN index _ index + 1; RETURN[sourcestr[index-1]] END; end:PROCEDURE RETURNS[BOOLEAN] = BEGIN RETURN[ index >= sourcestr.length] END; IF GetArg[get, end, argstr, substr] THEN RETURN[index] ELSE RETURN[ 0 ]; END; -- argstr/substr or argstr[substr] GetArg:PROCEDURE[ get:PROCEDURE RETURNS[CHARACTER], end:PROCEDURE RETURNS[BOOLEAN], argstr, substr:STRING ] RETURNS[ BOOLEAN ] = BEGIN OPEN IODefs; char:CHARACTER; argstr.length _ substr.length _ 0; char _ GetNextGoodChar[get, end]; IF char # NUL THEN DO SELECT char FROM '/ => GOTO getSingleArg; '[ => GOTO getMultipleArgs; SP, TAB, CR, ', => EXIT; ENDCASE => AppendChar[argstr, char]; IF end[] THEN EXIT; char _ get[]; REPEAT getSingleArg => BEGIN WHILE NOT end[] DO char _ get[]; IF char = SP OR char = TAB OR char = ', OR char = CR THEN EXIT; AppendChar[substr,char]; ENDLOOP; END; getMultipleArgs => BEGIN WHILE NOT end[] DO char _ get[]; IF char = '] THEN EXIT; AppendChar[substr,char]; ENDLOOP; END; ENDLOOP; IF argstr.length # 0 OR substr.length # 0 THEN RETURN[ TRUE ] ELSE RETURN[ FALSE ]; END; GetNextGoodChar:PROCEDURE[ get:PROCEDURE RETURNS[CHARACTER], end:PROCEDURE RETURNS[BOOLEAN] ] RETURNS[CHARACTER] = BEGIN char:CHARACTER; WHILE NOT end[] DO char _ get[]; SELECT char FROM IN['0..'9], IN['a..'z], IN['A..'Z], '. => EXIT; ENDCASE => LOOP; REPEAT FINISHED => RETURN[NUL]; ENDLOOP; RETURN[char]; END; END. (635)\12b1B142b10B152b15B230b17B427b10B823b7B1305b18B1133b16B249b12B488b12B404b6B869b16B