DIRECTORY Atom USING [GetPName], BasicTime USING [Now, Unpack, Update], Char, Commander, CommanderOps, EditSpan, IO, NodeProps, NodeStyleOps, PFS, PFSNames, Rope, TextEdit, TextEditBogus, TextNode, TiogaIO USING [FromFile, ToStream], UserProfile USING [Line]; TranslateCedarFilesImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, Char, Commander, CommanderOps, EditSpan, IO, NodeProps, NodeStyleOps, PFS, PFSNames, Rope, TextEdit, TextEditBogus, TextNode, TiogaIO, UserProfile ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Node: TYPE ~ TextNode.Ref; CommentPrefix: PROC [rope: ROPE, start: INT] RETURNS [prefixLength: INT] ~ { IF (rope.Run[start, "--"] = 2) OR (rope.Run[start, "//"] = 2) THEN RETURN [2] ELSE IF rope.Run[start, ";"] = 1 THEN RETURN [rope.SkipOver[start, ";"] - start] ELSE RETURN [0]; }; SkipOverBackward: PROC [s: ROPE, pos: INT ¬ Rope.MaxLen, skip: ROPE] RETURNS [INT] ~ { skipText: Rope.Text = skip.Flatten[]; skiplen: NAT ~ skipText.Size[]; slen: INT ~ s.Size[]; start: INT ~ MIN[slen-1, pos]; IF start < 0 OR s.IsEmpty[] THEN RETURN [-1]; IF skiplen=0 THEN RETURN[start]; FOR n: INT ¬ start, n - 1 WHILE n>=0 DO c: CHAR ~ s.Fetch[n]; FOR i: NAT IN [0..skiplen) DO IF c = skipText[i] THEN EXIT; REPEAT FINISHED => RETURN [n]; ENDLOOP; ENDLOOP; RETURN [-1]; }; EnumerateInitialCommentLines: PROC [root: Node, proc: PROC [text: ROPE, node: Node, start, length: INT] RETURNS [continue, redo: BOOL]] RETURNS [finalNode: Node ¬ NIL, finalIndex: INT ¬ 0] ~ { contents: ROPE; index: INT ¬ 0; node: Node ¬ TextNode.StepForward[root]; continue, redo: BOOL; contents ¬ TextEditBogus.GetRope[node]; DO GetTrimmedLine: PROC [begin: INT] RETURNS [start, length: INT] ~ { end: INT; index ¬ contents.SkipTo[begin, "\l\r"] + 1; -- set up for next line start ¬ contents.SkipOver[begin, " \t"]; end ¬ SkipOverBackward[contents, index - 2, " \t"]; RETURN [start, MAX[0, end - start + 1]]; }; prefixLength, start, length: INT; IF (prefixLength ¬ CommentPrefix[contents, index]) > 0 OR TextEdit.GetComment[node] THEN { savedIndex: INT ~ index; [start, length] ¬ GetTrimmedLine[index + prefixLength]; IF length > 0 OR prefixLength > 0 THEN { -- don't count truly empty comments finalNode ¬ node; -- remember this one in case it's the last one finalIndex ¬ savedIndex; }; } ELSE EXIT; [continue, redo] ¬ proc[contents.Substr[start, length], node, start, length]; IF NOT continue THEN EXIT; IF redo THEN { -- node has been changed, start again node ¬ TextNode.StepForward[root]; contents ¬ TextEditBogus.GetRope[node]; LOOP; }; IF index >= contents.Length[] THEN { -- on to the next node node ¬ TextNode.StepForward[node]; index ¬ 0; IF node = NIL THEN EXIT; contents ¬ TextEditBogus.GetRope[node]; }; ENDLOOP; }; UpdateCopyrightNotice: PROC[root: Node, short, hasNodes, alreadyChanged: BOOL] RETURNS[changed: BOOL ¬ FALSE, funnyCopyRight: BOOL ¬ FALSE] ~ { secondCopyright, shortFound: BOOL ¬ FALSE; shortCopyrightNode: Node; EachComment: PROC [text: ROPE, node: Node, start, length: INT] RETURNS [continue, redo: BOOL] ~ { index, foundYear, lastDigitPos: INT ¬ 0; thisLooks: TextEdit.Looks ~ IF hasNodes THEN eLooks ELSE TextEdit.noLooks; doneWithLine: BOOL ¬ FALSE; IF NOT Rope.IsPrefix["Copyright ", text] THEN RETURN [TRUE, FALSE]; IF shortFound THEN { secondCopyright ¬ TRUE; funnyCopyRight ¬ NOT Rope.Equal[text, fullCopyright]; RETURN[FALSE, FALSE]; }; shortCopyrightNode ¬ node; IF text.Run[9, " c "] = 3 THEN { -- replace obsolete math font symbol [] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: " Σ ", start: start + 9, len: 3, looks: thisLooks]; changed ¬ TRUE; } ELSE IF text.Run[pos1: 9, s2: " (C) ", case: FALSE] = 5 THEN { -- replace legally useless "(C)" symbol [] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: " Σ ", start: start + 9, len: 5, looks: thisLooks]; changed ¬ TRUE; RETURN[TRUE, TRUE]; -- need new copy of text to work with } ELSE IF hasNodes THEN { looks: TextEdit.Looks ~ TextEdit.FetchLooks[node, start + 10]; IF NOT looks['e] THEN { TextEdit.ChangeLooks[root: root, text: node, add: eLooks, start: start + 10, len: 1]; changed ¬ TRUE; }; }; index ¬ text.SkipTo[0, " \t"]; -- skip "Copyright" and the index ¬ text.SkipOver[index, " \t"]; index ¬ text.SkipTo[index, " \t"]; index ¬ text.SkipOver[index, " \t"]; lastDigitPos ¬ index-2; -- for malformed Copyright's, put year after symbol WHILE index < length DO ch: CHAR ~ text.Fetch[index]; SELECT TRUE FROM ch IN ['0..'9] => { lastDigitPos ¬ index; index ¬ index + 1; IF foundYear < 1000 THEN foundYear ¬ foundYear * 10 + (ch - '0) ELSE foundYear ¬ -1; }; foundYear = thisYear => { doneWithLine ¬ TRUE; EXIT }; ( ch = ', ) OR ( ch = ' ) OR ( ch = '\t ) => { foundYear ¬ 0; index ¬ text.SkipOver[index + 1, ", \t"]; }; ENDCASE => { IF changed OR alreadyChanged THEN { [] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: yearRope, start: start + lastDigitPos + 1, len: 0]; changed ¬ TRUE; }; doneWithLine ¬ TRUE; EXIT; }; IF doneWithLine THEN EXIT; ENDLOOP; shortFound ¬ TRUE; RETURN[TRUE, FALSE]; }; CopyrightLines: PROC[node: Node] ~ { -- We must add at least one new copyright line. rope: ROPE ~ TextEditBogus.GetRope[node]; prefixLength: INT ~ CommentPrefix[rope, 0]; prefix: ROPE ~ rope.Substr[len: prefixLength]; index: INT ~ rope.SkipTo[skip: "\l\r"]; Add: PROC[node: Node, fullLine: ROPE, where: EditSpan.Place, isComment, short: BOOL] ~ { child: Node ~ EditSpan.InsertTextNode[root: root, old: node, where: where]; [] ¬ TextEdit.ReplaceByRope[root: root, dest: child, rope: fullLine]; IF isComment THEN TextEdit.PutComment[child, TRUE]; IF short AND hasNodes THEN TextEdit.ChangeLooks[root: root, text: child, add: eLooks, start: 10, len: 1]; IF node # root AND where # $before THEN TextEdit.PutFormat[node: child, format: IF short THEN TextEdit.GetFormat[node] ELSE $finepoint]; }; IF NOT TextEdit.GetComment[node] AND prefixLength = 0 THEN { -- no initial comment IF NOT shortFound THEN Add[node, shortCopyright, $before, TRUE, TRUE]; node ¬ TextNode.StepForward[node]; IF NOT short THEN Add[node, fullCopyright, $after, TRUE, FALSE]; } ELSE IF index < rope.Length[] THEN { -- first comment ends with a newline newline: CHAR ~ rope.Fetch[index]; resultLen: INT ¬ 0; fullLine: ROPE; IF NOT shortFound THEN { fullLine ¬ IF prefixLength = 0 THEN shortCopyright.Concat[Rope.FromChar[newline]] ELSE IO.PutFR["%g %g%g", [rope[prefix]], [rope[shortCopyright]], [character[newline]]]; resultLen ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: fullLine, start: index+1, len: 0].resultLen; }; IF NOT short THEN { -- add rest of fullCopyright fullLine ¬ IF prefixLength = 0 THEN fullCopyright.Concat[Rope.FromChar[newline]] ELSE IO.PutFR["%g %g%g", [rope[prefix]], [rope[fullCopyright]], [character[newline]]]; [] ¬ TextEdit.ReplaceByRope[root: root, dest: node, rope: fullLine, start: index+resultLen+1, len: 0]; }; } ELSE IF prefixLength = 0 THEN { IF NOT shortFound THEN { Add[node, shortCopyright, $child, TRUE, TRUE]; IF NOT short THEN Add[TextNode.StepForward[node], fullCopyright, $after, TRUE, FALSE]; } ELSE Add[node, fullCopyright, $after, TRUE, FALSE]; } ELSE { IF NOT shortFound THEN Add[node, IO.PutFR["%g %g", [rope[prefix]], [rope[shortCopyright]]], $after, TextEdit.GetComment[node], TRUE]; IF NOT short THEN Add[TextNode.StepForward[node], IO.PutFR["%g %g", [rope[prefix]], [rope[fullCopyright]]], $after, TextEdit.GetComment[node], FALSE]; }; }; [] ¬ EnumerateInitialCommentLines[root, EachComment]; IF shortFound AND ( short OR secondCopyright ) THEN RETURN; IF NOT shortFound THEN CopyrightLines[TextNode.StepForward[root]] ELSE CopyrightLines[shortCopyrightNode]; changed ¬ TRUE; }; CheckProperties: PROC[root: TextNode.Ref, isTioga: BOOL, isDoc: BOOL ¬ FALSE] RETURNS[changed: BOOL ¬ FALSE, oldStyleDef: BOOL ¬ FALSE] = { IF root.hasStyleDef THEN oldStyleDef ¬ TRUE -- has $StyleDef property, don't clobber it ELSE { currentStyle: ROPE ~ Atom.GetPName[NodeStyleOps.StyleNameForNode[root]]; wantedStyle: ROPE ~ IF isTioga THEN "cedardoc" ELSE "cedarcode"; IF NOT Rope.Equal[currentStyle, wantedStyle, FALSE] THEN { TextEdit.ChangeStyle[root, wantedStyle]; changed ¬ TRUE; }; }; IF isDoc THEN { lastEdited: ROPE ~ "LastEdited"; FOR node: Node ¬ TextNode.StepForward[root], TextNode.StepForward[node] WHILE (node#NIL AND TextEdit.GetComment[node]) DO WITH NodeProps.GetProp[node, $Mark] SELECT FROM rope: ROPE => IF Rope.Equal[rope, lastEdited] THEN LOOP; ENDCASE; NodeProps.PutProp[node, $Mark, lastEdited]; changed ¬ TRUE; ENDLOOP; }; IF isTioga THEN { }; }; CheckForEmptyNodes: PROC[root: TextNode.Ref, out: IO.STREAM, file: ROPE] RETURNS[changed: BOOL ¬ FALSE] = { nonEmptySeen, nonEmptyComment: BOOL ¬ FALSE; atBeginning: BOOL ¬ TRUE; this: TextNode.Ref ¬ TextNode.StepForward[root]; AddNameAsNode: PROC = { child: Node ¬ EditSpan.InsertTextNode[root: root, old: TextNode.StepForward[root], where: $before]; [] ¬ TextEdit.ReplaceByRope[root: root, dest: child, rope: file]; TextEdit.PutComment[child, TRUE]; child ¬ EditSpan.InsertTextNode[root: root, old: TextNode.StepForward[root], where: $after]; TextEdit.PutComment[child, TRUE]; out.PutF1["\t$$ %g has no non-empty comment nodes at the beginning\n", [rope[file]] ]; out.PutRope["\t\t$$\tadding file name as inital node\n" ]; changed ¬ TRUE; }; UNTIL this = NIL DO thisLevel: INT; commentPrefixLen: INT ¬ CommentPrefix[this.rope, 0]; IF ( Rope.Size[this.rope] = 0 ) AND atBeginning THEN { span: TextNode.Span ~ TextNode.MakeNodeSpan[this, this]; this ¬ TextNode.StepForward[this]; EditSpan.Delete[root, span, NIL, FALSE]; changed ¬ TRUE; LOOP; }; IF ( commentPrefixLen = 0 ) AND ( NOT TextEdit.GetComment[this] ) THEN { IF atBeginning OR ( nonEmptySeen AND NOT nonEmptyComment ) THEN AddNameAsNode[]; RETURN; }; nonEmptySeen ¬ nonEmptySeen OR ( Rope.Size[this.rope] # 0 ); IF nonEmptySeen AND TextEdit.GetComment[this] THEN nonEmptyComment ¬ TRUE; thisLevel ¬ TextNode.Level[this]; IF atBeginning THEN { IF thisLevel # 1 THEN { [] ¬ EditSpan.ChangeNesting[root, TextNode.MakeNodeSpan[this, this], -thisLevel+1]; changed ¬ TRUE; }; atBeginning ¬ FALSE; this ¬ TextNode.StepForward[this]; LOOP; }; IF thisLevel = 1 THEN { [] ¬ EditSpan.ChangeNesting[root, TextNode.MakeNodeSpan[this, this], +1]; changed ¬ TRUE; LOOP; }; this ¬ TextNode.StepForward[this]; ENDLOOP; }; ChangeCharCodes: PROC[root: TextNode.Ref, hasNodes: BOOL] RETURNS[changed: BOOL ¬ FALSE] = { inQuotes: BOOL ¬ FALSE; FOR each: TextNode.Ref ¬ TextNode.StepForward[root], TextNode.StepForward[each] UNTIL each = NIL DO size: INT; index: INT ¬ 0; IF TextEdit.GetComment[each] THEN LOOP; IF hasNodes AND ( TextEdit.GetFormat[each] = NIL ) THEN { TextEdit.PutFormat[each, $code]; changed ¬ TRUE; }; size ¬ Rope.Size[each.rope]; WHILE index < size DO xchar: Char.XCHAR ¬ TextEdit.FetchChar[each, index]; IF ( Char.Set[xchar] = 0 ) THEN { char: CHAR ~ Char.Narrow[xchar]; SELECT TRUE FROM inQuotes => SELECT char FROM '\\ => index ¬ index + 1; --skip one char; '" => inQuotes ¬ FALSE; ENDCASE => NULL; ( char = '" ) => inQuotes ¬ NOT inQuotes; ( char = '' ) => { index ¬ index + 1; --skip one char (and maybe two) IF index >= size THEN EXIT; -- ' was last char in rope (comment) xchar ¬ TextEdit.FetchChar[each, index]; IF ( Char.Set[xchar] = 0 ) AND ( Char.Narrow[xchar] = '\\ ) THEN index ¬ index + 1; }; ( char = '_ ) => { [] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "¬", start: index, len: 1]; TextEdit.ChangeLooks[root: root, text: each, remove: kLooks, start: index, len: 1]; changed ¬ TRUE; }; ( char = '^ ) => { [] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "­", start: index, len: 1]; TextEdit.ChangeLooks[root: root, text: each, remove: kLooks, start: index, len: 1]; changed ¬ TRUE; }; ( char = '\030 ) => { [] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "\045", charSet: 357B, start: index, len: 1]; changed ¬ TRUE; }; ENDCASE => NULL; }; index ¬ index + 1; ENDLOOP; ENDLOOP; }; ChangeNewLinesToLF: PROC[root: TextNode.Ref] = { NodeProps.PutProp[n: root, name: $NewlineDelimiter, value: Rope.Flatten["\l"]]; root.comment ¬ TRUE; FOR each: TextNode.Ref ¬ TextNode.StepForward[root], TextNode.StepForward[each] UNTIL each = NIL DO size: INT ~ Rope.Size[each.rope]; FOR index: INT ¬ Rope.SkipTo[s: each.rope, pos: 0, skip: "\l\r"], Rope.SkipTo[s: each.rope, pos: index+1, skip: "\l\r"] UNTIL index = size DO IF Char.Set[TextEdit.FetchChar[each, index]] = 0 THEN [] ¬ TextEdit.ReplaceByRope[root: root, dest: each, rope: "\l", start: index, len: 1]; ENDLOOP; ENDLOOP; }; scriptPrefix: ROPE ~ "#!"; scriptPrefixLen: INT ~ scriptPrefix.Length[]; IsScript: PROC[root: TextNode.Ref] RETURNS[isScript: BOOL ¬ FALSE] = { this: ROPE ¬ TextNode.StepForward[root].rope; IF this.Length[] < scriptPrefixLen THEN RETURN; RETURN[ ( this.Fetch[0] = '# ) AND ( this.Fetch[1] = '! ) ]; }; DoOneFile: PROC[out: IO.STREAM, file: ROPE, short, isTioga, isMesa: BOOL] = { root: TextNode.Ref; changed, funnySecondCopyright: BOOL ¬ FALSE; ref: REF; hasNodes, oldStyleDef: BOOL ¬ FALSE; root ¬ TiogaIO.FromFile[PFS.PathFromRope[file] ! PFS.Error => { out.PutF1["** Couldn't open %g\n", [rope[file]] ]; CONTINUE; } ].root; IF root = NIL THEN RETURN; IF NOT short AND IsScript[root] THEN { out.PutF1["\t\t~ %g is a shell script\n", [rope[file]] ]; RETURN }; hasNodes ¬ ( TextNode.StepForward[TextNode.StepForward[root]] # NIL ); SELECT TRUE FROM Rope.Match["*.df", file, FALSE] => NULL; isTioga => { this: BOOL; [this, oldStyleDef] ¬ CheckProperties[root: root, isTioga: TRUE, isDoc: Rope.Match["*Doc.tioga", file, FALSE]]; changed ¬ changed OR this; }; ENDCASE => { this: BOOL ¬ CheckProperties[root: root, isTioga: FALSE].changed; changed ¬ changed OR this; this ¬ CheckForEmptyNodes[root, out, file]; changed ¬ changed OR this; IF isMesa THEN { this ¬ ChangeCharCodes[root, hasNodes]; changed ¬ changed OR this; }; }; IF oldStyleDef THEN out.PutF1["\t\t*==> %g has StyleDef property\n", [rope[file]] ]; ref ¬ NodeProps.GetProp[root, $NewlineDelimiter]; -- does it have $NewlineDelimiter? IF ref = NIL THEN { ChangeNewLinesToLF[root]; changed ¬ TRUE } ELSE { rp: ROPE ¬ NARROW[ref]; IF rp.Equal["\r"] THEN { ChangeNewLinesToLF[root]; changed ¬ TRUE }; }; IF NOT isTioga THEN { this: BOOL; [this, funnySecondCopyright] ¬ UpdateCopyrightNotice[root, TRUE, hasNodes, changed]; changed ¬ changed OR this; }; IF funnySecondCopyright THEN out.PutF1["\t\t*** %g has a funny secondCopyright notice\n", [rope[file]] ]; IF changed THEN { of: PFS.OpenFile; filePath: PFS.PATH ~ PFS.PathFromRope[file]; fileType: PFS.FileType; uid: PFS.UniqueID; stream: IO.STREAM; [ , , uid, , , fileType] ¬ PFS.FileInfo[filePath]; uid.egmt.gmt ¬ BasicTime.Update[uid.egmt.gmt, 60]; of ¬ PFS.Open[name: filePath, access: $create, wantedUniqueID: uid, fileType: fileType]; stream ¬ PFS.StreamFromOpenFile[of, $create]; [] ¬ TiogaIO.ToStream[stream, root]; IO.Close[stream]; IF isTioga THEN out.PutF1["\t=> %g has been updated\n", [rope[file]] ] ELSE out.PutF1["\t%g has been updated\n", [rope[file]] ]; } ELSE { IF isTioga THEN out.PutF1["\t\t=> %g did not change\n", [rope[file]] ] ELSE out.PutF1["\t\t& %g did not change\n", [rope[file]] ]; }; }; FixupCedarFileCmd: Commander.CommandProc = { arg: ROPE ¬ CommanderOps.NextArgument[cmd]; ignoreExtn: BOOL ¬ Rope.Equal[arg, "-d", FALSE]; fileBase: ROPE ¬ IF ignoreExtn THEN CommanderOps.NextArgument[cmd] ELSE arg; fileExtn: ROPE ~ CommanderOps.NextArgument[cmd]; file: ROPE ¬ Rope.Concat[fileBase, fileExtn]; IF file = NIL THEN RETURN; DoFixup[cmd.out, fileExtn, file, ignoreExtn]; }; FixupCedarFile: Commander.CommandProc = { ignoreExtn: BOOL ¬ FALSE; FOR arg: ROPE ¬ CommanderOps.NextArgument[cmd], CommanderOps.NextArgument[cmd] UNTIL arg = NIL DO short, fileExtn: ROPE; pos: INT; IF Rope.Equal[arg, "-d", FALSE] THEN { ignoreExtn ¬ TRUE; LOOP }; IF Rope.Equal[arg, "-~d", FALSE] THEN { ignoreExtn ¬ FALSE; LOOP }; short ¬ PFSNames.ComponentRope[PFSNames.ShortName[PFS.PathFromRope[arg]]]; pos ¬ short.Find["."]; IF pos # -1 THEN { fileExtn ¬ short.Substr[pos] }; -- include . in extn DoFixup[cmd.out, fileExtn, arg, ignoreExtn]; ENDLOOP; }; DoFixup: PROC[out: IO.STREAM, fileExtn, file: ROPE, ignoreExtn: BOOL] = { short, isTioga, isMesa: BOOL ¬ FALSE; doIt: BOOL ¬ TRUE; IF NOT ignoreExtn THEN SELECT TRUE FROM Rope.Equal[".mesa", fileExtn] => isMesa ¬ TRUE; Rope.Equal[".meta", fileExtn] => isMesa ¬ TRUE; Rope.Equal[".tioga", fileExtn] => isTioga ¬ TRUE; Rope.Equal[".config", fileExtn] => NULL; Rope.Equal[".abbreviations", fileExtn] => NULL; Rope.Equal[".command", fileExtn] => NULL; Rope.Equal[".cm", fileExtn] => NULL; Rope.Equal[".df", fileExtn] => NULL; Rope.Equal[".require", fileExtn] => NULL; ENDCASE => { doIt ¬ FALSE; short ¬ TRUE }; IF doIt THEN DoOneFile[out, file, short, isTioga, isMesa] ELSE out.PutF1["\t\t\t# skipping %g\n", [rope[file]] ]; }; eLooks: TextEdit.Looks ¬ TextEdit.noLooks; kLooks: TextEdit.Looks ¬ TextEdit.noLooks; thisYear: INT ~ BasicTime.Unpack[BasicTime.Now[]].year; yearRope: ROPE ~ IO.PutFR1[", %g", [integer[thisYear]]]; shortCopyright: ROPE; fullCopyright: ROPE ~ "Copyright protection claimed includes all forms and matters of copyrightable material and information now allowed by statutory or judicial law or hereinafter granted, including without limitation, material generated from the software programs which are displayed on the screen such as icons, screen display looks, character bitmaps, etc."; InitVals: PROC = { holder: ROPE ~ UserProfile.Line["Tioga.CopyrightHolder", "Xerox Corporation"]; shortCopyright ¬ IO.PutFR["Copyright Σ %g by %g. All rights reserved.", [integer[thisYear]], [rope[holder]]]; eLooks['e] ¬ TRUE; kLooks['k] ¬ TRUE; }; Commander.Register["FixupCedarFileCmd", FixupCedarFileCmd, "Usage: FixupCedarFileCmd {-d} base .extension"]; Commander.Register["FixupCedarFile", FixupCedarFile, "Usage: FixupCedarFile {-d} base.extension"]; InitVals[]; END.  TranslateCedarFilesImpl.mesa Copyright Σ 1991, 1992 by Xerox Corporation. All rights reserved. Willie-s, June 30, 1992 6:27 pm PDT Michael Plass, March 9, 1992 4:23 pm PST Doug Wyatt, June 29, 1992 12:08 pm PDT Like Rope.SkipOver, but backwards. Returns the highest position N in s such that s[N] is NOT in the skip string and N <= pos. If no such character occurs in s, then return -1. Calls proc on the text and location of each line of comments at the beginning of the given document until proc returns FALSE. Returns the location of the last comment line found. In all cases, the ``line'' is not considered to include any initial comment characters (e.g., "--" or ";"), leading or trailing whitespace, or the terminating newline character if any. The copyright line is assumed to have the format Copyright , , ..., We fix up the to be a true copyright symbol and add the current year to the end of the list if it's not already present. Add the line as the second line of the document, copying the comment characters and EOL character of the first line. put LastEdited $Mark property on initial comment nodes of doc files check for obsolete $Postfix property DKW: What was the intent of this??? prop: REF ¬ NodeProps.GetProp[root, $Postfix]; IF prop # NIL THEN { NodeProps.RemProp[root, $Postfix]; changed ¬ TRUE; }; make special check for mesa files, looking for empty nodes at beginning add file name as first node of file add a blank node after name check for nesting level; only the first node should be at level 1 called only for .mesa files make all the non-comment nodes have format $code if they don't already have a format we play fast and loose with single quotes here - we only skip the very next char and ignore the fact of quoted chars like '\030, knowing it won't be one of the special chars we are looking for; we assume legal cedar syntax don't do the copyright stuff for tioga files - that will be dealt with by hand for now, just use short copyright notice set date of new file one minute later than its "source"; one minute allows one to see the time difference with Unix's ls IF pos = -1 THEN { fileBase ¬ file } ELSE { fileExtn ¬ short.Substr[pos]; -- include . in extn fileBase ¬ file.Substr[0, file.Length[]-(short.Length[] - pos)]; }; Κ•NewlineDelimiter –"cedarcode" style™code™Kšœ Οeœ7™BK™#K™(K™&K˜—šΟk ˜ Kšœžœ ˜Kšœ žœ˜&K˜K˜ K˜ K˜ Kšžœ˜K˜ K˜ Kšžœ˜K˜ K˜K˜ K˜K˜ Kšœžœ˜#Kšœ žœ˜K™—KšΟnœžœž˜&Kšžœ;žœžœJ˜¬šœž˜K˜Kšžœžœžœ˜Kšœžœ˜K˜š Ÿ œžœžœ žœžœžœ˜Lšžœžœžœ˜CKšžœ˜ —šžœžœž˜%Kšžœ$˜*—šž˜Kšžœ˜ —K˜—K˜šŸœžœžœžœžœžœžœ˜VK™±K˜%Kšœ žœ˜Kšœžœ ˜Kšœžœžœ˜Kšžœ žœ žœžœ˜-Kšžœ žœžœ˜ šžœžœžœž˜'Kšœžœ˜šžœžœžœž˜Kšžœžœžœ˜K˜šž˜Kšžœžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ˜ K˜—K˜šŸœžœžœžœžœžœžœ˜‡Kšžœžœžœ ˜8KšœΟrœ` œ Πrsœρ™νKšœ žœ˜Kšœžœ˜K˜(Kšœžœ˜K˜'šž˜š Ÿœžœ žœžœžœ˜BKšœžœ˜ Kšœ,Οc˜CK˜(K˜3Kšžœ žœ˜(K˜—Kšœžœ˜!K˜šžœ5žœžœ˜ZKšœ žœ ˜K˜7šžœ žœžœ’#˜LKšœ’.˜@K˜K˜—K˜šž˜Kšžœ˜——K˜K˜MKšžœžœ žœžœ˜šžœžœ’%˜4K˜"K˜'Kšžœ˜K˜—šžœžœ’˜;K˜"K˜ Kšžœžœžœžœ˜K˜'K˜—Kšžœ˜—K˜—K˜K˜šŸœžœ.žœžœ žœžœžœžœ˜Kšœžœžœ˜*K˜K˜š Ÿ œžœžœžœœžœžœ˜a™0K™@—K™Kšœ žœ˜(Kšœžœ žœžœ˜JKšœžœžœ˜K˜Kš žœžœ#žœžœžœžœ˜Cšžœ žœ˜Kšœžœ˜Kšœžœ!˜5Kšžœžœžœ˜K˜—K˜K˜šžœžœ’$˜FK˜mKšœ žœ˜K˜š žœžœ&žœžœ’'˜hK˜mKšœ žœ˜Kšžœžœžœ’%˜9K˜šžœžœ žœ˜K˜>šžœžœ žœ˜K˜UKšœ žœ˜K˜—K˜———Kšœ’$˜CK˜$K˜"K˜$Kšœ’3˜Kšžœž˜KšœžœΟt˜šžœžœž˜š£œžœ˜K˜K˜šžœž˜K˜'—šž˜K˜—K˜—Kšœ)žœžœ˜6šœ žœ žœ˜/K˜K˜)K˜—šžœ˜ šžœ žœžœ˜#K˜mKšœ žœ˜K˜—Kšœžœ˜Kšžœ˜K˜——Kšžœžœžœ˜Kšžœ˜—Kšœ žœ˜Kšžœžœžœ˜K˜K˜—šŸœžœ’/˜TKšœžœ˜)Kšœžœ˜+Kšœžœ"˜.šœžœ˜'KšŸœžœžœ+žœ˜XK˜KK˜K˜EKšžœ žœžœ˜3Kšžœžœ žœO˜išžœ žœž˜'Kšœ(žœžœžœ ˜`—K˜—K˜š žœžœžœžœ’˜RKš žœžœ žœ$žœžœ˜FK˜"Kš žœžœžœ"žœžœ˜@K˜šžœžœžœ’$˜IK™tKšœ žœ˜"Kšœ žœ˜Kšœ žœ˜šžœžœ žœ˜Kš œ žœžœ/žœžœP˜©K˜mK˜—šžœžœžœ’˜1Kš œ žœžœ.žœžœO˜§K˜fK˜—˜šžœžœžœ˜šžœžœ žœ˜Kšœ"žœžœ˜.Kš žœžœžœ8žœžœ˜VK˜Kšžœ"žœžœ˜3—K˜—K˜šžœ˜Kš žœžœ žœ žœ\žœ˜…Kš žœžœžœ!žœ[žœ˜–K˜————K˜—K˜K˜K˜5Kš žœ žœ žœžœžœ˜;K˜šžœžœ žœ+˜AKšžœ$˜(—Kšœ žœ˜K˜K˜—šŸœžœžœ žœžœžœ žœžœžœžœ˜‹šžœ˜Kšžœžœ’+˜Cšžœ˜Kšœžœ6˜HKš œ žœžœ žœ žœ ˜@šžœžœ'žœžœ˜:K˜(Kšœ žœ˜K˜—K˜——šžœžœ˜K™CKšœ žœ˜ š žœFžœžœžœž˜zšžœ žœž˜/Kš œžœžœžœžœ˜8Kšžœ˜—K˜+Kšœ žœ˜Kšžœ˜—K˜—šžœ žœ˜K™$K™#KšΟyΠky€%™.š₯€₯€₯€™Kš€"™"Kš€ ₯€™Kš€™—K˜—K˜K˜—šŸœžœžœžœžœžœ žœžœ˜kK™GKšœžœžœ˜,Kšœ žœžœ˜K˜0šŸ œžœ˜K™#K˜cK˜AKšœžœ˜!K˜K™K˜\Kšœžœ˜!K˜VK˜:Kšœ žœ˜K˜—šžœžœž˜Kšœ žœ˜Kšœžœ˜4šžœžœ žœ˜6K˜8K˜"Kšœžœžœ˜(Kšœ žœ˜Kšžœ˜K˜—šžœžœžœžœ˜IKš žœ žœžœžœžœ˜PKšžœ˜K˜—K™AKšœžœ˜šžœ˜Kšœžœžœ˜Kšžœžœ'žœ˜DK˜——K˜K™Nšžœžœ žœ˜Kšœžœ˜ K™(Kšœ;žœ˜TKšœžœ˜K˜—šžœž˜K˜LK˜—šžœ žœ˜K™xKšœžœ ˜Kšœ žœžœžœ˜,Kšœ žœ ˜Kšœžœ ˜Kšœžœžœ˜Kšœžœ˜2K˜2KšœžœP˜XKšœ žœ!˜-K˜$Kšžœ˜šžœ žœ7˜FKšžœ5˜9—K˜šžœ˜Kšžœ žœ8žœ7˜‚K˜——K˜K˜—šŸœ˜-Kšœžœ"˜+Kšœ žœžœ˜0Kš œ žœžœ žœ žœ˜LKšœ žœ"˜0Kšœžœ#˜-Kšžœžœžœžœ˜K˜-K˜K˜—šŸœ˜*Kšœ žœžœ˜š žœžœBžœžœž˜aKšœžœ˜Kšœžœ˜ Kš žœžœžœžœžœ˜AKš žœžœžœžœžœ˜CKšœ2žœ˜JK˜Kšžœ žœ#’˜Gšžœ žœ™$šžœ™Kšœ’™2K™@K™——K˜,Kšžœ˜—K˜—K˜š Ÿœžœžœžœžœžœ˜IKšœžœžœ˜%Kšœžœžœ˜šžœžœ ž˜šžœžœž˜Kšœ*žœ˜/Kšœ*žœ˜/Kšœ,žœ˜1Kšœ#žœ˜(Kšœ*žœ˜/Kšœ$žœ˜)Kšœžœ˜$Kšœžœ˜$Kšœ$žœ˜)Kšžœ žœ žœ˜*—K˜—Kšžœžœ-žœ3˜qK˜K˜—K˜*K˜*Kšœ žœ*˜7Kšœ ž œ%˜8Kšœžœ˜šœžœΧ˜κK˜—šŸœžœ˜KšœžœB˜NKšœžœžœ[˜nKšœ žœ˜Kšœ žœ˜K˜K˜—K˜lK˜bK˜ K˜—Kšžœ˜—…—EΜe