DIRECTORY Ascii: TYPE USING [CR, NUL], Heap: TYPE USING [systemZone], LongString: TYPE USING [ AppendChar, AppendString, EquivalentSubStrings, SubString, SubStringDescriptor], MBCommandUtil: TYPE USING [CommandObject, CommandPtr], Streams: TYPE USING [Handle, PutChar]; MBCommandPack: PROGRAM IMPORTS Heap, Streams, String: LongString EXPORTS MBCommandUtil SHARES MBCommandUtil = BEGIN OPEN MBCommandUtil, String; CR: Char = Ascii.CR; Char: TYPE = CHARACTER; String: TYPE = LONG STRING; Pair: TYPE = RECORD [key, val: String, next: PairList]; PairList: PUBLIC TYPE = LONG POINTER TO Pair; TokenClass: TYPE = Char; id: TokenClass = 'I; eom: TokenClass = Ascii.NUL; State: TYPE = [0..17]; Failed: PUBLIC ERROR = CODE; Echo: PUBLIC PROC [ d: Streams.Handle, operator: String, argList, resultList: PairList, switches: String] = { PutString: PROC [d: Streams.Handle, s: LONG STRING] = { FOR i: CARDINAL IN [0..s.length) DO Streams.PutChar[d, s[i]] ENDLOOP}; EchoList: PROC [list: PairList] = { Streams.PutChar[d, '[]; FOR p: PairList _ list, p.next UNTIL p = NIL DO IF p.key # NIL THEN {PutString[d, p.key]; PutString[d, ": "L]}; PutString[d, p.val]; IF p.next # NIL THEN PutString[d, ", "L]; ENDLOOP; Streams.PutChar[d, ']]; }; IF resultList # NIL THEN { IF resultList.next = NIL AND resultList.key = NIL THEN PutString[d, resultList.val] ELSE EchoList[resultList]; PutString[d, " _ "L]; }; PutString[d, operator]; IF argList # NIL THEN EchoList[argList]; IF switches # NIL AND switches.length > 0 THEN { PutString[d, "/"L]; PutString[d, switches]; }; }; Create: PUBLIC PROC [get: PROC RETURNS [CHARACTER]] RETURNS [cmd: CommandPtr] = { cmd _ (Heap.systemZone).NEW[MBCommandUtil.CommandObject _ [getChar: get]]; cmd.idString _ (Heap.systemZone).NEW[StringBody[100]]; }; Destroy: PUBLIC PROC [cmd: CommandPtr] = { IF cmd = NIL THEN RETURN; (Heap.systemZone).FREE[@cmd.idString]; (Heap.systemZone).FREE[@cmd]; }; Parse: PUBLIC PROC [ cmd: MBCommandUtil.CommandPtr, opX, argX, resultX: CARDINAL, allowNoTagParm: BOOL _ FALSE] RETURNS [operator: String, argList, resultList: PairList, switches: String] = { state: State; RestoreToken: PROC = INLINE {cmd.reset _ TRUE}; NextToken: PROC = { IF cmd.reset THEN {cmd.reset _ FALSE; RETURN}; WHILE cmd.c = ' OR cmd.c = CR DO cmd.c _ cmd.getChar[] ENDLOOP; SELECT cmd.c FROM IN ['a..'z], IN ['A..'Z], IN ['0..'9], '<, '., '+, '-, '~, '!, '$ => { cmd.idString.length _ 0; WHILE TRUE DO SELECT cmd.c FROM IN ['a..'z], IN ['A..'Z], IN ['0..'9], '<, '>, '., '+, '-, '~, '!, '$ => { AppendChar[cmd.idString, cmd.c]; cmd.c _ cmd.getChar[]}; ENDCASE => EXIT; ENDLOOP; cmd.token _ id; }; '_, '[, ',, '], ':, '/ => {cmd.token _ cmd.c; cmd.c _ cmd.getChar[]}; '" => { cmd.idString.length _ 0; DO cmd.c _ cmd.getChar[]; IF cmd.c = '" THEN {cmd.c _ cmd.getChar[]; IF cmd.c # '" THEN EXIT}; AppendChar[cmd.idString, cmd.c]; ENDLOOP; cmd.token _ id; }; ';, eom => cmd.token _ cmd.c; ENDCASE => BadCommand[]}; CopyId: PROC [extra: CARDINAL] RETURNS [String] = INLINE { RETURN[CopyString[cmd.idString, extra]]}; pair: ARRAY [0..1] OF String; PushArg: PROC = INLINE {argList _ AddPair[argList, pair[0], pair[1]]}; PushResult: PROC = INLINE {resultList _ AddPair[resultList, pair[0], pair[1]]}; BadCommand: PROC = { operator _ FreeString[operator]; resultList _ FreePairList[resultList]; argList _ FreePairList[argList]; switches _ FreeString[switches]; ERROR Failed }; IF ~cmd.reset THEN cmd.c _ ' ; state _ 0; operator _ switches _ NIL; argList _ resultList _ NIL; UNTIL state = LAST[State] DO NextToken[]; SELECT cmd.token FROM id => SELECT state FROM 0 => {operator _ CopyId[MAX[resultX, opX]]; state _ 1}; 2, 8 => {operator _ CopyId[opX]; state _ 9}; 3 => {pair[0] _ CopyId[0]; state _ 4}; 5 => {pair[1] _ CopyId[resultX]; PushResult[]; state _ 6}; 10 => {pair[0] _ CopyId[0]; state _ 11}; 12 => {pair[1] _ CopyId[argX]; PushArg[]; state _ 13}; 15 => {switches _ CopyId[0]; state _ 16}; 1, 9, 14, 16 => {RestoreToken[]; state _ 17}; ENDCASE => BadCommand[]; '_ => SELECT state FROM 1 => { pair[0] _ NIL; pair[1] _ operator; operator _ NIL; PushResult[]; state _ 2}; 7 => state _ 8; ENDCASE => BadCommand[]; '[ => SELECT state FROM 0 => state _ 3; 1, 9 => state _ 10; 14 => {RestoreToken[]; state _ 17}; ENDCASE => BadCommand[]; '] => SELECT state FROM 3, 6 => state _ 7; 4 => IF allowNoTagParm THEN { pair[1] _ pair[0]; pair[0] _ NIL; PushArg[]; state _ 7} ELSE BadCommand[]; 10, 13 => state _ 14; 11 => IF allowNoTagParm THEN { pair[1] _ pair[0]; pair[0] _ NIL; PushArg[]; state _ 14} ELSE BadCommand[]; ENDCASE => BadCommand[]; ': => SELECT state FROM 4 => state _ 5; 11 => state _ 12; ENDCASE => BadCommand[]; ', => SELECT state FROM 4 => IF allowNoTagParm THEN { pair[1] _ pair[0]; pair[0] _ NIL; PushArg[]; state _ 3} ELSE BadCommand[]; 6 => state _ 3; 11 => IF allowNoTagParm THEN { pair[1] _ pair[0]; pair[0] _ NIL; PushArg[]; state _ 10} ELSE BadCommand[]; 13 => state _ 10; ENDCASE => BadCommand[]; '/ => SELECT state FROM 0, 1, 9, 14 => state _ 15; ENDCASE => BadCommand[]; '; => SELECT state FROM 1, 9, 14, 15, 16 => state _ 17; ENDCASE => BadCommand[]; eom => SELECT state FROM 0, 1, 9, 14, 15, 16 => state _ 17; ENDCASE => BadCommand[]; ENDCASE; ENDLOOP; }; CopyString: PUBLIC PROC [s: String, extra: CARDINAL _ 0] RETURNS [String] = { copy: String = (Heap.systemZone).NEW[StringBody[IF s=NIL THEN 0 ELSE s.length + extra]]; IF s # NIL THEN AppendString[copy, s]; RETURN [copy] }; FreeString: PUBLIC PROC [s: String] RETURNS [String _ NIL] = { IF s # NIL THEN (Heap.systemZone).FREE[@s]; }; GetNthPair: PUBLIC PROC [list: PairList, n: CARDINAL, delete: BOOLEAN _ FALSE] RETURNS [key,value: String _ NIL] = { i: CARDINAL _ 0; FOR p: PairList _ list, p.next UNTIL p = NIL DO IF i = n THEN {key _ p.key; value _ p.val; IF delete THEN p.key _ p.val _ NIL; EXIT}; i _ i+1; ENDLOOP; }; ListLength: PUBLIC PROC [list: PairList] RETURNS [n: CARDINAL _ 0] = { FOR p: PairList _ list, p.next UNTIL p = NIL DO n _ n+1 ENDLOOP; }; KeyValue: PUBLIC PROC [key: SubString, list: PairList, delete: BOOLEAN _ FALSE] RETURNS [s: String _ NIL] = { FOR p: PairList _ list, p.next UNTIL p = NIL DO ss: SubStringDescriptor _ [base: p.key, offset: 0, length: p.key.length]; IF EquivalentSubStrings[@ss, key] THEN {s _ p.val; IF delete THEN p.val _ NIL; EXIT}; ENDLOOP; }; FreePairList: PUBLIC PROC [list: PairList] RETURNS [PairList _ NIL] = { next: PairList; p: PairList _ list; UNTIL p = NIL DO next _ p.next; [] _ FreeString[p.key]; [] _ FreeString[p.val]; (Heap.systemZone).FREE[@p]; p _ next; ENDLOOP; }; AddPair: PUBLIC PROC [list: PairList, key,val: String] RETURNS [PairList] = { new: PairList _ (Heap.systemZone).NEW[Pair _ [key: key, val: val, next: NIL]]; p: PairList; IF list = NIL THEN list _ new ELSE { FOR p _ list, p.next UNTIL p.next = NIL DO ENDLOOP; p.next _ new}; RETURN [list] }; SetExtension: PUBLIC PROC [root, defaultExt: String] RETURNS [name: String] = { SELECT TRUE FROM ~Dotted[root] => { name _ AdjustString[root, defaultExt.length + 2]; AppendChar[name, '.]; AppendString[name, defaultExt]; }; ENDCASE => name _ root; }; Dotted: PROC [s: String] RETURNS [BOOLEAN] = INLINE { FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN [TRUE] ENDLOOP; RETURN [FALSE] }; AdjustString: PROC [old: String, extra: CARDINAL] RETURNS [new: String] = { IF old.length + extra <= old.maxlength THEN new _ old ELSE { new _ (Heap.systemZone).NEW[StringBody[old.length + extra]]; AppendString[new, old]; (Heap.systemZone).FREE[@old]; }; }; END. øfile MBCommandPack.Mesa last modified by Satterthwaite, September 22, 1980 12:26 PM last modified by Russ Atkinson, 24-Nov-80 14:40:48 last modified by Lewis on 24-Aug-81 14:42:07 last modified by Sweet on March 10, 1981 9:58 AM last modified by Loretta on 24-Aug-81 19:44:10 last modified by JGS on 17-Aug-81 21:45:14 last modified by Levin on April 5, 1983 2:32 pm 0: 1: id 2: id _ 3: [ ?{ARG}, 4: [ ?{ARG}, id 5: [ ?{ARG}, id : 6: [ ?{ARG}, id : id 7: [ ?{ARG}, ] 8: [ ?{ARG}, ] _ 9: LHS _ id 10: ?(LHS _) id [ ?{ARG}, 11: ?(LHS _) id [ ?{ARG}, id 12: ?(LHS _) id [ ?{ARG}, id : 13: ?(LHS _) id [ ?{ARG}, id : id 14: ?(LHS _) id RHS 15: ?(LHS _) id ?RHS / 16: ?(?(LHS _) id ?RHS) / id 17: ?(?(LHS _) id ?RHS) ?(/ ?id) (;|eom) | eom where LHS = id | [ ?{ARG}, ] RHS = [ ?{ARG}, ] ARG = id : id | id (if allowNoTagParm) stream-like utilities object management external parsing routine PairList utilities file naming utilities storage allocation Ê Ù˜Jšœ™Jšœ<™Jšœœœœ˜+šœ˜J˜——Jšœ™J˜š ž œœœœ œœ˜NJšœœ˜%Jšœœ˜šœœ˜,Jš˜Jš œœ œœœœ˜XJ˜Jšœ˜—Jšœ˜J˜—š ž œœœœœ ˜FJš œœœœ œ˜@Jšœ˜J˜—š žœœœ*œœ˜OJšœœ˜šœœ˜,Jš˜J˜Išœ˜!Jš œ œœ œœ˜3—Jšœ˜—Jšœ˜J˜—š ž œœœœ œ˜GJ˜J˜šœ˜ Jšœ˜J˜J˜/Jšœœ˜&Jšœ˜—Jšœ˜J˜J˜—šžœœœ#œ˜MJšœ"œ#œ˜NJ˜ Jšœœœ ˜šœ˜Jš œœ œœœ˜3J˜—Jšœ˜ Jšœ˜˜J˜——Jšœ™J˜šž œœœœ˜Ošœœ˜˜J˜1J˜J˜J˜—Jšœ˜—Jšœ˜J˜—š žœœ œœœ˜5Jšœœœœœ œœœœ˜LJšœœ˜šœ˜J˜——Jšœ™J˜šž œœœœ˜KJšœ%œ ˜5šœ˜Jšœœ!˜