*Syntax10.Scn.FntSyntax10i.Scn.FntIStampElemsAlloc14 Aug 97M8FoldElemsNew#Syntax10.Scn.Fnt END NoNotify; 8,8#Syntax10.Scn.Fnt VAR ch: CHAR; i: INTEGER; quote: CHAR; BEGIN ch := name[0]; i := 0; quote := '"'; WHILE (ch # 0X) & (("a" <= ch) & (ch <= "z") OR ("A" <= ch) & (ch <= "Z") OR (ch = ".") OR (ch = "/") OR (ch = "$") OR (i > 0) & (("0" <= ch) & (ch <= "9") OR (ch = ":"))) DO IF ch = '"' THEN quote := "'" ELSIF ch = "'" THEN quote := '"' END ; INC(i); ch := name[i] END ; IF ch # 0X THEN Texts.Write(w, quote) END ; Texts.WriteString(w, name); IF ch # 0X THEN Texts.Write(w, quote) END END WriteName; 828#Syntax10.Scn.FntTT VAR i, len: INTEGER; BEGIN COPY(old, new); len := Strings.Length(new); i := len - 1; WHILE (i > 0) & (new[i] # "/") DO DEC(i) END ; IF i > 0 THEN Strings.Extract(new, i + 1, 256, new) END ; i := 0; WHILE (new[i] # 0X) & (new[i] # ".") DO INC(i) END ; IF new[i] # 0X THEN new[i] := 0X END ; Strings.Append(".Cod", new) END Convert; 858#Syntax10.Scn.Fnt>> VAR x, y, h, res: INTEGER; v: Viewers.Viewer; s: Texts.Scanner; t0: Texts.Text; BEGIN Strings.Insert(delimiter, 0, cod); Strings.Insert(targDir, 0, cod); x := 1; y := 2; h := Viewers.minH; Viewers.minH := 1; Oberon.DrawCursor(Oberon.Pointer, Oberon.Star, x, y); Oberon.Par.text := t; Oberon.Par.pos := 0; Oberon.Call("AsciiCoder.CodeFiles", Oberon.Par, FALSE, res); v := Viewers.This(x, y-1); t0 := v.dsc(TextFrames.Frame).text; t0.notify := NoNotify; Texts.OpenScanner(s, t0, 0); Texts.Scan(s); Texts.Delete(t0, 0, Texts.Pos(s)-1); WriteName(cod); Texts.Insert(t0, 0, w.buf); Oberon.Par.vwr := v; Oberon.Par.frame := v.dsc; Oberon.Call("EditTools.StoreAscii", Oberon.Par, FALSE, res); Viewers.minH := h; Viewers.Close(v); Texts.Delete(t, 0, t.len); Strings.Append(".Bak", cod); Files.Delete(cod, res) END Copy; 8 Syntax10b.Scn.Fnt:8#Syntax10.Scn.Fnt VAR d: Directories.Directory; BEGIN In.Open; In.Name(targDir); IF ~In.Done THEN Out.String("-- failed$") END ; d := Directories.This(targDir); IF d = NIL THEN Out.String("-- directory not found$") END END TargetDirectory; 8 .8#Syntax10.Scn.Fnt VAR cod: ARRAY 256 OF CHAR; s: Texts.Scanner; t: Texts.Text; beg, end, time: LONGINT; v: Viewers.Viewer; BEGIN IF targDir = "" THEN Out.String("-- use Distributor.TargetDirectory first$") ELSE Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END ELSIF (s.class = Texts.Char) & (s.c = "*") THEN v := Oberon.MarkedViewer(); IF (v.dsc # NIL) & (v.dsc.next # NIL) & (v.dsc.next IS TextFrames.Frame) THEN Texts.OpenScanner(s, v.dsc.next(TextFrames.Frame).text, 0); Texts.Scan(s) END END ; t := TextFrames.Text(""); LOOP IF s.eot THEN EXIT ELSIF s.class IN {Texts.Name, Texts.String} THEN Convert(s.s, cod); Texts.WriteString(w, "% "); WriteName(s.s); Texts.Write(w, "~"); Texts.Append(t, w.buf); Copy(t, cod); Texts.Scan(s) ELSIF (s.class = Texts.Char) & (s.c = "(") THEN Texts.Scan(s); Texts.WriteString(w, "% "); WHILE s.class IN {Texts.Name, Texts.String} DO IF w.buf.len = 2 THEN Convert(s.s, cod) END ; WriteName(s.s); Texts.Write(w, " "); Texts.Scan(s) END ; IF (s.class = Texts.Char) & (s.c = ")") THEN Texts.Scan(s) ELSE Out.String("-- invalid input$"); EXIT END ; Texts.Write(w, "~"); Texts.Append(t, w.buf); Copy(t, cod) ELSE EXIT END ; Out.Ln END END END Transfer; 8qA8#Syntax10.Scn.Fnt BEGIN IF ~isDir & ~Strings.Match(name, "*.Bak") & ~Strings.Match(name, "Oberon.Tmp.*") THEN WriteName(name); Texts.Write(w, " ") END END CollectFiles0; 8 88-8#Syntax10.Scn.FntLL VAR beg, end, time: LONGINT; t: Texts.Text; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN; Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) ELSE s.class := Texts.Inval; END END END OpenArgs; 8p8#Syntax10.Scn.Fnt VAR m: Module; BEGIN IF ~isDir & Strings.Match(name, "*.Mod") THEN NEW(m); COPY(name, m.name); m.dir := d; m.imports := NIL; m.ref := 0; m.next := list; list := m END END CollectFiles; 8{8CSyntax10.Scn.FntSyntax10b.Scn.FntC VAR r: Texts.Reader; e: Texts.Elem; i, len, j: LONGINT; v: VersionElems.Beg; BEGIN ver[0] := 0X; Texts.OpenReader(r, t, 0); Texts.ReadElem(r); WHILE (r.elem # NIL) & ~(r.elem IS VersionElems.Beg) DO Texts.ReadElem(r) END ; IF r.elem # NIL THEN v := r.elem(VersionElems.Beg); len := LEN(v.vers); j := 0; WHILE j < nofVersions DO i := 0; WHILE i < len DO IF v.vers[i] = versions[j] THEN COPY(versions[j], ver); RETURN END ; INC(i) END ; INC(j) END END END DetectVersion; 8gD8#Syntax10.Scn.Fnt VAR ver: ARRAY 32 OF CHAR; BEGIN DetectVersion(t, versions, nofVersions, ver); IF ver # "" THEN VersionElems.SwitchAll(t, ver) END END ToggleVersion; 8A8#Syntax10.Scn.FntSS BEGIN m := list; WHILE (m # NIL) & (m.name # name) DO m := m.next END END Find; 8g/8#Syntax10.Scn.Fnt VAR t: Texts.Text; s: Texts.Scanner; p: Module; imp: Import; name: ModuleName; str: ARRAY 260 OF CHAR; BEGIN COPY(m.dir.path, str); Strings.Append(delimiter, str); Strings.Append(m.name, str); t := TextFrames.Text(str); IF t.len > 0 THEN t.notify := NoNotify; ToggleVersion(t, versions, nofVersions); FoldElems.ExpandAll(t, 0, TRUE); Texts.OpenScanner(s, t, 0); REPEAT Texts.Scan(s) UNTIL s.eot OR (s.class = Texts.Name) & (s.s = "IMPORT"); IF ~s.eot THEN REPEAT Texts.Scan(s); IF s.class = Texts.Name THEN COPY(s.s, name); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = ":") THEN Texts.Scan(s); Texts.Scan(s); COPY(s.s, name) END ; Strings.Append(".Mod", name); Find(list, name, p); IF p # NIL THEN INC(p.ref); NEW(imp); imp.mod := p; imp.next := m.imports; m.imports := imp END END UNTIL (s.class = Texts.Char) & (s.c = ";") END END END FindImports; 8s8CSyntax10.Scn.Fnt<Syntax10i.Scn.FnthK VAR m, prev: Module; imp: Import; t: Texts.Text; str: ARRAY 260 OF CHAR; r: Texts.Reader; error: BOOLEAN; BEGIN IF list # NIL THEN m := list; prev := NIL; WHILE (m # NIL) & (m.ref # 0) DO prev := m; m := m.next END ; IF prev = NIL THEN list := list.next ELSIF m # NIL THEN prev.next := m.next ELSE (* should never reach this ELSE (because cyclic imports are not allowed), if we come here, at least prevent a trap and try compiling the modules one after the other *) m := list; list := list.next END ; imp := m.imports; WHILE imp # NIL DO DEC(imp.mod.ref); imp := imp.next END ; CompileModules(list, options, versions, nofVersions); COPY(m.dir.path, str); Strings.Append(delimiter, str); Strings.Append(m.name, str); t := TextFrames.Text(str); t.notify := NoNotify; ToggleVersion(t, versions, nofVersions); FoldElems.ExpandAll(t, 0, TRUE); Texts.OpenReader(r, t, 0); Texts.WriteString(w, "compiling "); Texts.WriteString(w, str); Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf); Compiler.Module(r, options, 0, Oberon.Log, error) END END CompileModules; 8 +H8mSyntax10.Scn.Fnt>Syntax10i.Scn.Fnt8:O)&L VAR s: Texts.Scanner; cur, d: Directories.Directory; m: Module; i, nofVersions, pos, blankPos: INTEGER; str: ARRAY 256 OF CHAR; versions: ARRAY 10 OF ARRAY 32 OF CHAR; destinationRoot, dir: ARRAY 256 OF CHAR; options: ARRAY 10 OF CHAR; error: BOOLEAN; BEGIN OpenArgs(s); cur := Directories.Current(); (* get current directory *) COPY(targDir, destinationRoot); LOOP IF s.eot OR (s.class # Texts.Name) THEN EXIT END ; IF s.s = "versions" THEN Texts.Scan(s); Texts.Scan(s); Texts.Scan(s); i := 0; nofVersions := 0; pos := 0; COPY(s.s, str); blankPos := Strings.Pos(" ", str, pos); WHILE blankPos # -1 DO Strings.Extract(str, 0, blankPos, versions[nofVersions]); INC(nofVersions); Strings.Delete(str, 0, blankPos + 1); blankPos := Strings.Pos(" ", str, pos) END ; COPY(str, versions[nofVersions]); INC(nofVersions) ELSIF s.s = "options" THEN Texts.Scan(s); Texts.Scan(s); Texts.Scan(s); COPY(s.s, options) ELSE EXIT END ; Texts.Scan(s) END ; error := FALSE; WHILE ~s.eot & ~((s.class = Texts.Char) & (s.c = "~")) & ~error DO list := NIL; WHILE ~s.eot & (s.class IN {Texts.Name, Texts.String}) DO (* read source directories and expand them to list of modules *) d := Directories.This(s.s); IF d # NIL THEN Directories.Enumerate(d, CollectFiles) END ; Texts.Scan(s) END ; IF ~s.eot & (s.class = Texts.Char) & (s.c = "=") THEN Texts.Scan(s); IF ~s.eot & (s.class = Texts.Char) & (s.c = ">") THEN Texts.Scan(s); IF ~s.eot & (s.class IN {Texts.Name, Texts.String}) THEN IF list # NIL THEN IF destinationRoot # "" THEN COPY(destinationRoot, dir); IF dir[Strings.Length(dir) - 1] # delimiter THEN Strings.Append(delimiter, dir) END END ; Strings.Append(s.s, dir); Directories.Create(dir); (* create destination directory if necessary *) Directories.Change(dir); (* and change into it *) m := list; WHILE m # NIL DO FindImports(m, list, versions, nofVersions); m := m.next END ; CompileModules(list, options, versions, nofVersions) END ; Texts.Scan(s) ELSE error := TRUE END ELSE error := TRUE END ELSE error := TRUE END END ; IF error THEN Out.String("Erroneous format of parameters") END ; Directories.Change(cur.path) (* change into original current directory *) END CompileDistribution; 8MODULE Distributor; (* CS 8 Aug 97 /  *) IMPORT Strings, Directories, Files, Viewers, Texts, TextFrames, FoldElems, VersionElems, Oberon, Compiler, In, Out; CONST delimiter = Directories.delimiter; TYPE ModuleName = ARRAY 32 OF CHAR; Import = POINTER TO ImportDesc; Module = POINTER TO ModuleDesc; ModuleDesc = RECORD dir: Directories.Directory; name: ModuleName; imports: Import; ref: INTEGER; next: Module END ; ImportDesc = RECORD mod: Module; next: Import END ; VAR targDir: ARRAY 256 OF CHAR; w: Texts.Writer; list: Module; PROCEDURE NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);  PROCEDURE WriteName (name: ARRAY OF CHAR);  PROCEDURE Convert (VAR old, new: ARRAY OF CHAR);  PROCEDURE Copy (t: Texts.Text; cod: ARRAY OF CHAR);  PROCEDURE TargetDirectory*; (** (^ | dir) sets the target directory for the other commands. *) PROCEDURE Transfer*; (** "*" | ( ^ | name | "(" {name} ")" ) transfers the text from the star-marked viewer or the (selected) file (or list of files if they are included in brackets) asciicoded to the targed directory. The command TargetDirectory must be called first. *) PROCEDURE CollectFiles0 (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);  PROCEDURE TransferDirectory*; (** (^ | {directory}) transfers the files contained in the specified directory (excluding backup and temporary files) asciicoded to the target directory. The command TargetDirectory must be called first. *) VAR cod: ARRAY 256 OF CHAR; s: Texts.Scanner; t: Texts.Text; beg, end, time: LONGINT; v: Viewers.Viewer; dir, cur: Directories.Directory; BEGIN IF targDir = "" THEN Out.String("-- use Distributor.TargetDirectory first$") ELSE cur := Directories.Current(); Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END END ; t := TextFrames.Text(""); REPEAT IF s.class IN {Texts.Name, Texts.String} THEN dir := Directories.This(s.s); IF dir # NIL THEN Directories.Change(cur.path); Directories.Change(s.s); Convert(s.s, cod); Texts.WriteString(w, "% "); Directories.Enumerate(dir, CollectFiles0); Texts.Write(w, "~"); Texts.Append(t, w.buf); Copy(t, cod); END END ; Texts.Scan(s); Out.Ln UNTIL s.eot OR ~(s.class IN {Texts.Name, Texts.String}); Directories.Change(cur.path) END END TransferDirectory;  PROCEDURE OpenArgs (VAR s: Texts.Scanner);  PROCEDURE CollectFiles (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);  PROCEDURE DetectVersion (t: Texts.Text; versions: ARRAY OF ARRAY OF CHAR; nofVersions: INTEGER; VAR ver: ARRAY OF CHAR);  PROCEDURE ToggleVersion (t: Texts.Text; VAR versions: ARRAY OF ARRAY OF CHAR; nofVersions: INTEGER);  PROCEDURE Find (list: Module; name: ModuleName; VAR m: Module);  PROCEDURE FindImports (m, list: Module; VAR versions: ARRAY OF ARRAY OF CHAR; nofVersions: INTEGER);  PROCEDURE CompileModules (VAR list: Module; options: ARRAY OF CHAR; VAR versions: ARRAY OF ARRAY OF CHAR; nofVersions: INTEGER);  PROCEDURE CompileDistribution*; (** [versions := "{ver}" | options := "..."] {{source directory} => destination directory} ~ Compiles the files contained in the (list of) source directories into the destination directory. If you call TargetDirectory first, the destination directories are considered relative to the targetdirectory. *) BEGIN targDir := ""; Texts.OpenWriter(w) END Distributor.TargetDirectory /o:/ftp/pub/Oberon/LinzTools Distributor.Transfer (xxx yyy) ~