DIRECTORY IO, PFS, Convert, RefText, Commander, CommanderOps, Rope, RopeList, MakoDependency, ProcessProps; MakoDependencyImpl: CEDAR SAFE PROGRAM IMPORTS IO, PFS, Convert, RefText, Commander, CommanderOps, Rope, RopeList, ProcessProps EXPORTS MakoDependency ~ BEGIN ROPE: TYPE ~ Rope.ROPE; ConfigDependencies: TYPE ~ MakoDependency.ConfigDependencies; CDependsCommand: Commander.CommandProc ~ { ENABLE PFS.Error => { IF error.group=user THEN CommanderOps.Failed[error.explanation] }; arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg = NIL OR CommanderOps.NextArgument[cmd] # NIL THEN CommanderOps.Failed[cmd.procData.doc]; FOR tail: LIST OF ROPE ¬ ParseCDependency[arg], tail.rest UNTIL tail = NIL DO IO.PutRope[cmd.out, tail.first]; IO.PutRope[cmd.out, " "]; ENDLOOP; IO.PutRope[cmd.out, "\n"]; }; ParseCDependency: PUBLIC PROC [fileName: ROPE] RETURNS [list: LIST OF ROPE ¬ NIL] ~ { path: PFS.PATH ~ PFS.PathFromRope[IF Rope.Match["*.*", fileName] THEN fileName ELSE Rope.Concat[fileName, ".c"]]; uxname: ROPE ~ PFS.PFSNameToUnixName[path]; pos: INT ¬ 0; size: INT ¬ 0; lines: ROPE; result: REF; cmd: Commander.Handle ~ NARROW[ProcessProps.GetProp[$CommanderHandle]]; [out: lines, result: result] ¬ CommanderOps.DoCommandRope[commandLine: Rope.Concat["cc-M ", uxname], parent: cmd]; IF result = $Failure THEN CommanderOps.Failed["failed to derive dependency for c module"]; size ¬ Rope.Size[lines]; WHILE pos < size DO next: INT ¬ Rope.SkipTo[lines, pos, ": \n"]; IF Rope.Fetch[lines, next] # ': AND Rope.Run[uxname, 0, lines, pos] # Rope.Size[uxname] THEN { list ¬ CONS[Rope.Substr[lines, pos, next-pos], list]; }; pos ¬ Rope.SkipOver[lines, next, ": \n"]; ENDLOOP; }; MesaDependsCommand: Commander.CommandProc ~ { ENABLE PFS.Error => { IF error.group=user THEN CommanderOps.Failed[error.explanation] }; arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg = NIL OR CommanderOps.NextArgument[cmd] # NIL THEN CommanderOps.Failed[cmd.procData.doc]; FOR tail: LIST OF ROPE ¬ ParseMesaDirectory[arg], tail.rest UNTIL tail = NIL DO IO.PutRope[cmd.out, tail.first]; IO.PutRope[cmd.out, " "]; ENDLOOP; IO.PutRope[cmd.out, "\n"]; }; ParseMesaDirectory: PUBLIC PROC [fileName: ROPE] RETURNS [LIST OF ROPE] ~ { head: LIST OF ROPE ~ LIST[NIL]; last: LIST OF ROPE ¬ head; stream: IO.STREAM ~ PFS.StreamOpen[fileName: PFS.PathFromRope[IF Rope.Match["*.*", fileName] THEN fileName ELSE Rope.Concat[fileName, ".mesa"]], accessOptions: $read]; Token: TYPE ~ {null, definitions, program, monitor, directory, from, type, using, cedar, unsafe, safe, semicolon, comma, colon, bracketleft, bracketright, id, string}; token: Token ¬ null; text: REF TEXT ¬ RefText.ObtainScratch[100]; pos: INT ¬ 0; Get: PROC ~ { tokenKind: IO.TokenKind; charsSkipped: INT; error: IO.TokenError; pos ¬ pos + text.length; token ¬ null; [tokenKind: tokenKind, token: text, charsSkipped: charsSkipped, error: error] ¬ IO.GetCedarToken[stream: stream, buffer: text, flushComments: TRUE]; pos ¬ pos + charsSkipped; SELECT tokenKind FROM tokenID => { SELECT TRUE FROM RefText.Equal[text, "DEFINITIONS"] => {token ¬ definitions}; RefText.Equal[text, "PROGRAM"] => {token ¬ program}; RefText.Equal[text, "MONITOR"] => {token ¬ monitor}; RefText.Equal[text, "DIRECTORY"] => {token ¬ directory}; RefText.Equal[text, "FROM"] => {token ¬ from}; RefText.Equal[text, "TYPE"] => {token ¬ type}; RefText.Equal[text, "USING"] => {token ¬ using}; RefText.Equal[text, "CEDAR"] => {token ¬ cedar}; RefText.Equal[text, "UNSAFE"] => {token ¬ unsafe}; RefText.Equal[text, "SAFE"] => {token ¬ safe}; ENDCASE => {token ¬ id}; }; tokenSINGLE => { SELECT text[0] FROM '; => token ¬ semicolon; ', => token ¬ comma; ': => token ¬ colon; '[ => token ¬ bracketleft; '] => token ¬ bracketright; ENDCASE; }; tokenROPE => { token ¬ string; }; ENDCASE; }; Module: PROC ~ { Directory[]; IdentList[]; Cedar[]; IF token = definitions THEN Definitions[] ELSE ProgHead[]; }; Directory: PROC ~ { IF token = directory THEN { Get[]; IF token # semicolon THEN IncludeList[]; IF token = semicolon THEN Get[] ELSE Syntax[]; }; }; IncludeList: PROC ~ { IncludeItem[]; WHILE token = comma DO Get[]; IncludeItem[]; ENDLOOP; }; IncludeItem: PROC ~ { IF token # id THEN Syntax[] ELSE { name: ROPE ¬ Rope.FromRefText[text]; Get[]; SELECT token FROM using => Using[]; colon => { Get[]; SELECT token FROM from => { Get[]; IF token#string THEN Syntax[]; Get[]; Using[]; }; type => { Get[]; IF token = id THEN { Get[]; }; Using[]; }; ENDCASE => Syntax[]; }; ENDCASE; last ¬ last.rest ¬ LIST[name]; }; }; Using: PROC ~ { IF token = using THEN { Get[]; IF token#bracketleft THEN Syntax[]; Get[]; IF token#bracketright THEN IdList[]; IF token=bracketright THEN Get[] ELSE Syntax[]; }; }; IdList: PROC ~ { IdItem[]; WHILE token = comma DO Get[]; IdItem[]; ENDLOOP; }; IdItem: PROC ~ { IF token # id THEN Syntax[]; Get[]; }; IdentList: PROC ~ { IdList[]; IF token = colon THEN Get[] ELSE Syntax[]; }; Cedar: PROC ~ { IF token = cedar THEN Get[]; }; Definitions: PROC ~ { IF token = definitions THEN Get[] ELSE Syntax[]; }; ProgHead: PROC ~ { IF token = safe OR token = unsafe THEN Get[]; IF token = program OR token = monitor THEN Get[] ELSE Syntax[]; }; Syntax: PROC ~ { CommanderOps.Failed[IO.PutFR["Mesa syntax error (%g|%g)", [rope[PFS.RopeFromPath[PFS.GetName[PFS.OpenFileFromStream[stream]].fullFName]]], [integer[pos]]]]; }; Get[]; Module[]; RefText.ReleaseScratch[text]; IO.Close[stream]; RETURN [head.rest]; }; CMesaDependsCommand: Commander.CommandProc ~ { ENABLE PFS.Error => { IF error.group=user THEN CommanderOps.Failed[error.explanation] }; arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg = NIL OR CommanderOps.NextArgument[cmd] # NIL THEN CommanderOps.Failed[cmd.procData.doc] ELSE { d: MakoDependency.ConfigDependencies ¬ ParseCMesaDirectory[arg]; FOR tail: LIST OF ROPE ¬ d.interfaces, tail.rest UNTIL tail = NIL DO IO.PutRope[cmd.out, tail.first]; IO.PutRope[cmd.out, " "]; ENDLOOP; FOR tail: LIST OF ROPE ¬ d.implementations, tail.rest UNTIL tail = NIL DO IO.PutRope[cmd.out, tail.first]; IO.PutRope[cmd.out, " "]; ENDLOOP; }; IO.PutRope[cmd.out, "\n"]; }; ParseCMesaDirectory: PUBLIC PROC [fileName: ROPE] RETURNS [ConfigDependencies] ~ { head: LIST OF ROPE ~ LIST[NIL]; last: LIST OF ROPE ¬ head; dhead: LIST OF ROPE ~ LIST[NIL]; dlast: LIST OF ROPE ¬ dhead; stream: IO.STREAM ~ PFS.StreamOpen[fileName: PFS.PathFromRope[IF Rope.Match["*.*", fileName] THEN fileName ELSE Rope.Concat[fileName, ".config"]], accessOptions: $read]; Token: TYPE ~ {null, id, string, comma, semicolon, colon, gets, tilde, bracketleft, bracketright, braceleft, braceright, period, directory, from, pack, configuration, imports, exports, control, begin, requests, static, dynamic, end, plus, then, links, code, frame, all}; token: Token ¬ null; text: REF TEXT ¬ RefText.ObtainScratch[100]; pos: INT ¬ 0; locals: LIST OF ROPE ¬ NIL; NoteName: PROC [name: ROPE] ~ { last ¬ last.rest ¬ LIST[name]; }; Note: PROC ~ { NoteName[SaveName[]]; }; SaveName: PROC RETURNS [ROPE] ~ { RETURN [SELECT token FROM id => Rope.FromRefText[text], string => Convert.RopeFromLiteral[RefText.TrustTextAsRope[text]], ENDCASE => NIL] }; Get: PROC ~ { tokenKind: IO.TokenKind; charsSkipped: INT; error: IO.TokenError; pos ¬ pos + text.length; token ¬ null; [tokenKind: tokenKind, token: text, charsSkipped: charsSkipped, error: error] ¬ IO.GetCedarToken[stream: stream, buffer: text, flushComments: TRUE]; pos ¬ pos + charsSkipped; SELECT tokenKind FROM tokenID => { IF text.length > 1 AND text[1] IN ['a..'z] THEN {token ¬ id} ELSE { SELECT TRUE FROM RefText.Equal[text, "DIRECTORY"] => {token ¬ directory}; RefText.Equal[text, "FROM"] => {token ¬ from}; RefText.Equal[text, "PACK"] => {token ¬ pack}; RefText.Equal[text, "CONFIGURATION"] => {token ¬ configuration}; RefText.Equal[text, "CONFIG"] => {token ¬ configuration}; RefText.Equal[text, "IMPORTS"] => {token ¬ imports}; RefText.Equal[text, "EXPORTS"] => {token ¬ exports}; RefText.Equal[text, "CONTROL"] => {token ¬ control}; RefText.Equal[text, "BEGIN"] => {token ¬ begin}; RefText.Equal[text, "REQUESTS"] => {token ¬ requests}; RefText.Equal[text, "STATIC"] => {token ¬ static}; RefText.Equal[text, "DYNAMIC"] => {token ¬ dynamic}; RefText.Equal[text, "END"] => {token ¬ end}; RefText.Equal[text, "PLUS"] => {token ¬ plus}; RefText.Equal[text, "THEN"] => {token ¬ then}; RefText.Equal[text, "LINKS"] => {token ¬ links}; RefText.Equal[text, "CODE"] => {token ¬ code}; RefText.Equal[text, "FRAME"] => {token ¬ frame}; RefText.Equal[text, "ALL"] => {token ¬ all}; ENDCASE => {token ¬ id}; }; }; tokenSINGLE => { SELECT text[0] FROM '; => token ¬ semicolon; ', => token ¬ comma; ': => token ¬ colon; '[ => token ¬ bracketleft; '] => token ¬ bracketright; '{ => token ¬ braceleft; '} => token ¬ braceright; '= => token ¬ tilde; '~ => token ¬ tilde; ENDCASE; }; tokenROPE => { token ¬ string; }; ENDCASE; }; Source: PROC ~ { Directory[]; Packing[]; Config[]; }; Directory: PROC ~ { IF token = directory THEN { Get[]; IF token # semicolon THEN IncludeList[]; IF token = semicolon THEN Get[] ELSE Syntax[]; }; }; IncludeList: PROC ~ { IncludeItem[]; WHILE token = comma DO Get[]; IncludeItem[]; ENDLOOP; }; IncludeItem: PROC ~ { IF token # id THEN Syntax[] ELSE { name: ROPE ¬ SaveName[]; Get[]; SELECT token FROM colon => { Get[]; SELECT token FROM from => { Get[]; name ¬ SaveName[]; String[]; }; ENDCASE => Syntax[]; }; ENDCASE => Syntax[]; dlast ¬ dlast.rest ¬ LIST[name]; }; }; Packing: PROC ~ { WHILE token = pack DO Get[]; IdentList[]; ENDLOOP; }; IdList: PROC ~ { IdItem[]; WHILE token = comma DO Get[]; IdItem[]; ENDLOOP; }; IdItem: PROC ~ { IF token # id THEN Syntax[]; Get[]; }; IdentList: PROC ~ { IdList[]; IF token = colon THEN Get[] ELSE Syntax[]; }; Config: PROC ~ { IF token = id THEN { locals ¬ CONS[SaveName[], locals]; Get[] } ELSE Syntax[]; IF token = colon THEN Get[] ELSE Syntax[]; ConfigTail[]; }; ConfigTail: PROC ~ { save: LIST OF ROPE ~ locals; start: LIST OF ROPE ~ last; dstart: LIST OF ROPE ~ dlast; IF token = configuration THEN Get[] ELSE Syntax[]; Links[]; Imports[]; Exports[]; Statics[]; Dynamics[]; Control[]; IF token = tilde THEN Get[] ELSE Syntax[]; Body[]; UNTIL locals = save DO hide: ROPE ~ locals.first; FOR tail: LIST OF ROPE ¬ start.rest, tail.rest UNTIL tail = NIL DO IF Rope.Equal[tail.first, hide] THEN { tail.first ¬ NIL }; ENDLOOP; FOR tail: LIST OF ROPE ¬ dstart.rest, tail.rest UNTIL tail = NIL DO IF Rope.Equal[tail.first, hide] THEN { tail.first ¬ NIL }; ENDLOOP; locals ¬ locals.rest; ENDLOOP; }; Links: PROC ~ { IF token = links THEN { Get[]; IF token = colon THEN Get[] ELSE Syntax[]; IF token = code OR token = frame THEN Get[] ELSE Syntax[]; }; }; Imports: PROC ~ { IF token = imports THEN { Get[]; ItemList[]; }; }; Exports: PROC ~ { IF token = exports THEN { Get[]; ExportItemList[]; }; }; ItemList: PROC ~ { Item[]; WHILE token = comma DO Get[]; Item[]; ENDLOOP; }; Item: PROC ~ { name: ROPE ¬ SaveName[]; IF token # id THEN Syntax[]; Get[]; IF token = colon THEN { Get[]; IF token = id THEN {name ¬ SaveName[]; Get[]} ELSE Syntax[]; }; dlast ¬ dlast.rest ¬ LIST[name]; }; ExportItemList: PROC ~ { ExportItem[]; WHILE token = comma DO Get[]; ExportItem[]; ENDLOOP; }; ExportItem: PROC ~ { IF token = all THEN Get[] ELSE Item[]; }; Statics: PROC ~ { IF token = static THEN {Get[]; Requests[note: TRUE]}; }; Dynamics: PROC ~ { IF token = dynamic THEN {Get[]; Requests[note: FALSE]}; }; Requests: PROC [note: BOOL] ~ { IF token = requests THEN Get[] ELSE Syntax[]; IF note THEN Note[]; String[]; WHILE token = comma DO Get[]; IF note THEN Note[]; String[]; ENDLOOP; }; String: PROC ~ { IF token = string THEN Get[] ELSE Syntax[] }; Control: PROC ~ { IF token = control THEN { Get[]; IdList[] }; }; Body: PROC ~ { SELECT token FROM begin => { Get[]; StatementList[]; IF token = end THEN Get[] ELSE Syntax[] }; braceleft => { Get[]; StatementList[]; IF token = braceright THEN Get[] ELSE Syntax[] }; ENDCASE => Syntax[]; }; StatementList: PROC ~ { Statement[]; WHILE token = semicolon DO WHILE token = semicolon DO Get[] ENDLOOP; IF token = bracketleft OR token = id THEN Statement[]; ENDLOOP; }; Statement: PROC ~ { name: ROPE ¬ NIL; IF token = bracketleft THEN { Get[]; ItemList[]; IF token = bracketright THEN Get[] ELSE Syntax[]; IF token = gets THEN Get[] ELSE Syntax[]; name ¬ InterfaceOrModule[]; } ELSE { name ¬ SaveName[]; IF token # id THEN Syntax[]; Get[]; IF token = colon THEN { Get[]; IF token = id THEN {name ¬ SaveName[]; Get[]} ELSE { locals ¬ CONS[name, locals]; ConfigTail[]; RETURN }; }; SELECT token FROM gets => { Get[]; name ¬ InterfaceOrModule[] }; bracketright => { name ¬ NIL; ModuleTail[] }; links => { Links[] }; ENDCASE; }; IF name # NIL THEN NoteName[name]; }; ModuleTail: PROC ~ { IF token # bracketright THEN Syntax[]; Get[]; IF token # bracketleft THEN IdList[]; IF token = bracketleft THEN Get[] ELSE Syntax[]; Links[]; }; InterfaceOrModule: PROC RETURNS [name: ROPE ¬ NIL] ~ { IF token # id THEN Syntax[]; name ¬ SaveName[]; Get[]; SELECT token FROM colon => {Get[]; IF token = id THEN {name ¬ SaveName[]; Get[]} ELSE Syntax[]; ModuleTail[] }; bracketright => { ModuleTail[] }; then, plus => { InterfaceTail[] }; ENDCASE; }; InterfaceTail: PROC ~ { WHILE token = then OR token = plus DO Get[]; IF token # id THEN Syntax[]; Note[]; Get[]; ENDLOOP; }; Syntax: PROC ~ { CommanderOps.Failed[IO.PutFR["Configuration syntax error (%g|%g)", [rope[PFS.RopeFromPath[PFS.GetName[PFS.OpenFileFromStream[stream]].fullFName]]], [integer[pos]]]]; }; Get[]; Source[]; RefText.ReleaseScratch[text]; IO.Close[stream]; RETURN [[RopeList.Remove[dhead.rest, NIL], RopeList.Remove[head.rest, NIL]]]; }; MakeItDependsCommand: Commander.CommandProc ~ { ENABLE PFS.Error => { IF error.group=user THEN CommanderOps.Failed[error.explanation] }; arg: ROPE ~ CommanderOps.NextArgument[cmd]; IF arg = NIL OR CommanderOps.NextArgument[cmd] # NIL THEN CommanderOps.Failed[cmd.procData.doc] ELSE { FOR tail: LIST OF ROPE ¬ ParseMakeItDependency[arg], tail.rest UNTIL tail = NIL DO IO.PutRope[cmd.out, tail.first]; IO.PutRope[cmd.out, " "]; ENDLOOP; }; IO.PutRope[cmd.out, "\n"]; }; GetLine: PROC [stream: IO.STREAM] RETURNS [ROPE ¬ NIL] ~ { ENABLE IO.EndOfStream => CONTINUE; RETURN [IO.GetLineRope[stream]] }; ParseMakeItDependency: PUBLIC PROC [fileName: ROPE] RETURNS [LIST OF ROPE] ~ { head: LIST OF ROPE ~ LIST[NIL]; last: LIST OF ROPE ¬ head; stream: IO.STREAM ~ PFS.StreamOpen[PFS.PathFromRope[fileName]]; FOR line: ROPE ¬ GetLine[stream], GetLine[stream] DO IF line = NIL THEN EXIT; IF Rope.Match[pattern: "--*{*}*", object: line] THEN { start: INT ~ Rope.Index[line, 0, "{"]+1; end: INT ~ Rope.Index[line, start, "}"]; s: IO.STREAM ~ IO.RIS[Rope.Substr[line, start, end-start]]; FOR tok: ROPE ¬ CommanderOps.GetCmdToken[s].value, CommanderOps.GetCmdToken[s].value UNTIL tok = NIL DO last ¬ last.rest ¬ LIST[tok]; ENDLOOP; }; ENDLOOP; IO.Close[stream]; RETURN [head.rest] }; MOrderCommand: Commander.CommandProc ~ { arg0: ROPE = CommanderOps.NextArgument[cmd]; PutPair: PROC [a, b: ROPE] ~ { IO.PutRope[cmd.out, a]; IO.PutRope[cmd.out, " "]; IO.PutRope[cmd.out, b]; IO.PutRope[cmd.out, "\n"]; }; IF arg0 = NIL THEN CommanderOps.Failed[cmd.procData.doc] ELSE { FOR arg: ROPE ¬ arg0, CommanderOps.NextArgument[cmd] UNTIL arg = NIL DO notMesa: BOOL ¬ FALSE; notMesaOrConfig: BOOL ¬ FALSE; x: LIST OF ROPE ¬ NIL; x ¬ ParseMesaDirectory[arg ! PFS.Error => { IF error.group=user THEN {notMesa ¬ TRUE; CONTINUE} }]; IF notMesa THEN { ENABLE PFS.Error => { IF error.group=user THEN {notMesaOrConfig ¬ TRUE; CONTINUE}}; c: ConfigDependencies ~ ParseCMesaDirectory[arg]; x ¬ RopeList.DAppend[c.interfaces, c.implementations]; }; IF notMesaOrConfig THEN { result ¬ $Failure; msg ¬ Rope.Cat[msg, arg, " not found\n"]; }; IF x = NIL THEN { PutPair[arg, arg] } ELSE { FOR tail: LIST OF ROPE ¬ x, tail.rest UNTIL tail = NIL DO PutPair[tail.first, arg]; ENDLOOP; }; ENDLOOP; }; }; Commander.Register["Mesa-Depends", MesaDependsCommand, "List direct dependencies of a Mesa module"]; Commander.Register["Config-Depends", CMesaDependsCommand, "List direct dependencies of a Configuration (CMesa) module"]; Commander.Register["C-Depends", CDependsCommand, "List dependencies of a c-language module"]; Commander.Register["MakeIt-Depends", MakeItDependsCommand, "List dependencies of a MakeIt file"]; Commander.Register["MOrder", MOrderCommand, "Make a list of dependency pairs (suitable for processing by tsort) for a collection of mesa and config files\nargs: basename ..."]; END. : MakoDependencyImpl.mesa Copyright Σ 1991, 1992 by Xerox Corporation. All rights reserved. Michael Plass, February 24, 1992 2:01 pm PST BUG: assumes UX directory. We get to let cpp do most of the work for us... IO.PutBlock[bug, text]; IO.PutBlock[bug, " "]; IO.PutBlock[bug, text]; IO.PutBlock[bug, " "]; Κ0•NewlineDelimiter –(cedarcode) style™code™Kšœ Οeœ7™BK™,—K˜šΟk œžœžœZ˜kK˜—KšΟnœžœžœž˜&KšžœžœžœI˜XKšžœ˜šœž˜K˜Kšžœžœžœ˜šœžœ%˜=K˜—šŸœ˜*Kšžœžœ žœžœ*˜XKšœžœ"˜+Kš žœžœžœ"žœžœ'˜`š žœžœžœžœ$žœžœž˜MKšžœ˜ Kšžœ˜Kšžœ˜—Kšžœ˜K˜K˜—šŸœžœžœ žœžœžœžœžœžœ˜UK™KKš œžœžœžœžœžœ žœ˜qKšœžœ˜+Kšœžœ˜ Kšœžœ˜Kšœžœ˜ Kšœžœ˜ Kšœžœ)˜GK˜rKšžœžœA˜ZK˜šžœ ž˜Kšœžœ#˜,šžœžœ5žœ˜^Kšœžœ*˜5K˜—K˜)Kšžœ˜—K˜K˜—šŸœ˜-Kšžœžœ žœžœ*˜XKšœžœ"˜+Kš žœžœžœ"žœžœ'˜`š žœžœžœžœ&žœžœž˜OKšžœ˜ Kšžœ˜Kšžœ˜—Kšžœ˜K˜K˜—šŸœžœžœ žœžœžœžœžœ˜KK•StartOfExpansionΚ[fileName: ROPE, accessOptions: FS.AccessOptions _ read, streamOptions: FS.StreamOptions _ (3)[TRUE, TRUE, TRUE], keep: CARDINAL _ 1B (1), createByteCount: FS.ByteCount _ 2560, streamBufferParms: FS.StreamBufferParms _ [vmPagesPerBuffer: 8, nBuffers: 2], extendFileProc: FS.ExtendFileProc, wantedCreatedTime: GMT _ nullGMT, remoteCheck: BOOL _ TRUE, wDir: ROPE _ NIL, checkFileType: BOOL _ FALSE, fileType: FS.FileType _ [0B (0)]]š œžœžœžœžœžœ˜Kšœžœžœžœ˜Kšœžœžœžœžœžœžœ žœ8˜§Kšœžœœ˜§K˜Kšœžœžœ˜,Kšœžœ˜ šŸœžœ˜ K–D[stream: STREAM, buffer: REF TEXT, flushComments: BOOL _ TRUE]šœ žœžœ žœ ˜AK˜K˜ KšœPžœ<žœ˜”K˜K™K™šžœ ž˜˜ šžœžœž˜K˜