-- SMCommentTableImpl.mesa -- last edit by Satterthwaite, April 29, 1983 10:19 am -- last edit by Schmidt, May 3, 1982 3:35 pm DIRECTORY SMCommentTable: TYPE USING [ BreakSequence, BreakTab, Index, Node, Ref, Table, TableNode, Text], SMCommentTableOps: TYPE USING []; SMCommentTableImpl: CEDAR PROGRAM EXPORTS SMCommentTableOps ~ { OPEN SMCommentTable; CommentManager: PUBLIC TYPE ~ RECORD[ z: ZONE_, commentTable: SMCommentTable.Table_NIL, breakTable: SMCommentTable.BreakTab_NIL, ending: INT_0]; CommentM: TYPE ~ REF CommentManager; TableOverflow: PUBLIC ERROR ~ CODE; TableOrder: PUBLIC ERROR ~ CODE; Create: PUBLIC PROC[zone: ZONE] RETURNS [CommentM] ~ { RETURN [zone.NEW[CommentManager _ [z~zone]]]}; Reset: PUBLIC PROC[cm: CommentM] ~ { IF cm.commentTable # NIL THEN { cm.commentTable.size _ 0; cm.commentTable.last _ NIL; cm.commentTable.lastx _ 0}; IF cm.breakTable # NIL THEN cm.breakTable.size _ 0; cm.ending _ 0}; Add: PUBLIC PROC[cm: CommentM, start: Index, text: Text, lastToken,prefix: Index] ~ { ref: Ref ~ (cm.z).NEW[Node _ [start, text, lastToken, prefix]]; size: NAT ~ (IF cm.commentTable = NIL THEN 0 ELSE cm.commentTable.size); max: NAT ~ (IF cm.commentTable = NIL THEN 0 ELSE cm.commentTable.max); last: Ref ~ (IF size > 0 THEN cm.commentTable[size-1] ELSE NIL); IF lastToken > start THEN RETURN; IF last # NIL THEN { IF last.start > start OR lastToken < last.lastToken THEN RETURN; IF last.start = start THEN { -- merge the blank line comment with the actual comment IF last.text # NIL THEN RETURN; ref.prefix _ prefix + last.prefix; cm.commentTable[size-1] _ ref; RETURN} }; IF size >= max THEN { newMax: NAT ~ (IF max > (NAT.LAST/2 - 2) THEN NAT.LAST ELSE max*2 + 4); IF newMax <= size THEN ERROR TableOverflow; {newTable: Table ~ (cm.z).NEW[TableNode[newMax]]; newTable.last _ NIL; FOR i: NAT IN [0..size) DO newTable[i] _ cm.commentTable[i]; cm.commentTable[i] _ NIL; ENDLOOP; cm.commentTable _ newTable; }}; cm.commentTable[size] _ ref; cm.commentTable.size _ size + 1}; AddBreakHint: PUBLIC PROC[cm: CommentM, index: Index] ~ { size: NAT ~ (IF cm.breakTable = NIL THEN 0 ELSE cm.breakTable.size); max: NAT ~ (IF cm.breakTable = NIL THEN 0 ELSE cm.breakTable.max); last: Index ~ (IF size = 0 THEN 0 ELSE cm.breakTable[size-1]); IF index <= last THEN RETURN; IF size >= max THEN { -- must extend the table new: BreakTab _ NIL; nmax: NAT _ MAX[200, IF max < NAT.LAST/2 THEN max+max ELSE NAT.LAST]; IF nmax <= max THEN ERROR TableOverflow; new _ (cm.z).NEW[BreakSequence[nmax]]; FOR i: NAT IN [0..size) DO new[i] _ cm.breakTable[i]; ENDLOOP; cm.breakTable _ new}; cm.breakTable[size] _ index; cm.breakTable.size _ size + 1}; FindNext: PUBLIC PROC[cm: CommentM, notBefore: Index] RETURNS[Ref] ~ { IF cm.commentTable # NIL AND cm.commentTable.size > 0 THEN { low: NAT _ 0; high: NAT _ cm.commentTable.size-1; last: Ref _ cm.commentTable.last; lastx: NAT _ cm.commentTable.lastx; lval: Index _ 0; IF last # NIL THEN { lval _ last.start; IF notBefore = lval THEN RETURN [last]; IF notBefore < lval THEN high _ lastx ELSE low _ lastx+1}; WHILE low < high DO lval _ (last _ cm.commentTable[lastx _ (low+high)/2]).start; IF notBefore < lval THEN {high _ lastx; LOOP}; IF notBefore > lval THEN {low _ lastx+1; LOOP}; cm.commentTable.lastx _ lastx; RETURN [cm.commentTable.last _ last]; ENDLOOP; IF high # lastx OR last = NIL THEN lval _ (last _ cm.commentTable[lastx _ high]).start; IF notBefore <= lval THEN { cm.commentTable.lastx _ lastx; RETURN [cm.commentTable.last _ last]}}; RETURN [NIL]}; TestBreakHint: PUBLIC PROC[cm: CommentM, start: Index, next: Index] RETURNS[BOOL] ~ { IF start = 0 OR next <= start THEN RETURN [TRUE]; IF cm.breakTable = NIL OR cm.breakTable.size <= 1 THEN RETURN [FALSE]; {low: NAT _ 0; high: NAT _ cm.breakTable.size - 1; DO last: NAT _ (low+high)/2; lval: Index _ cm.breakTable[last]; IF low = high THEN RETURN [start < lval AND next > lval]; IF start < lval THEN { IF next > lval THEN RETURN [TRUE]; high _ last; LOOP}; IF start >= lval THEN {low _ last+1; LOOP}; ENDLOOP; }}; Explode: PUBLIC PROC[ref: Ref] RETURNS[start: Index, text: Text, lastToken, prefix: Index] ~ { IF ref = NIL THEN RETURN [Index.LAST, NIL, Index.LAST, 0]; RETURN [ref.start, ref.text, ref.lastToken, ref.prefix]}; SetEnding: PUBLIC PROC[cm: CommentM, end: Index] ~ {cm.ending _ end}; GetEnding: PUBLIC PROC[cm: CommentM] RETURNS[Index] ~ {RETURN [cm.ending]}; }.