Syntax10.Scn.Fnt Syntax10i.Scn.Fnt StampElems Alloc 24 Feb 94 Courier10.Scn.Fnt Syntax10b.Scn.Fnt MODULE Make; (** SHML 8 Sep 92, IMPORT Texts, TF := TextFrames, Viewers, MV := MenuViewers, Oberon, Log; CONST Debug = FALSE; defaultCompiler = "Compiler.Compile"; optionChar = "/"; defaultOptions = "s"; null = 0; ident = 1; semicolon = 2; becomes = 3; TYPE Table = ARRAY 128, 32 OF CHAR; VAR W: Texts.Writer; ch: CHAR; PROCEDURE Scan(VAR r: Texts.Reader; VAR name: ARRAY OF CHAR; VAR sym: INTEGER); PROCEDURE Identifier; VAR i: INTEGER; BEGIN i := 0; REPEAT name[i] := ch; INC(i); Texts.Read(r, ch) UNTIL (ch < "0") OR ("9" < ch) & (CAP(ch) < "A") OR ("Z" < CAP(ch)) OR (i = LEN(name)); IF i = LEN(name) THEN DEC(i); sym := null ELSE sym := ident END; name[i] := 0X END Identifier; PROCEDURE Comment; (* do not read after end of file *) BEGIN Texts.Read(r, ch); LOOP LOOP WHILE ch = "(" DO Texts.Read(r, ch); IF ch = "*" THEN Comment END END; IF ch = "*" THEN Texts.Read(r, ch); EXIT END; IF r.eot THEN EXIT END; Texts.Read(r, ch) END; IF ch = ")" THEN Texts.Read(r, ch); EXIT END; IF r.eot THEN EXIT END END END Comment; BEGIN WHILE ch <= " " DO (* ignore control characters *) IF r.eot THEN RETURN ELSE Texts.Read(r, ch) END END; CASE ch OF (* ch > " " *) | "(": Texts.Read(r, ch); IF ch = "*" THEN Comment; Scan(r, name, sym) END | ":": Texts.Read(r, ch); IF ch = "=" THEN Texts.Read(r, ch); sym := becomes ELSE sym := null END | ";": sym := semicolon; Texts.Read(r, ch) | "A".."Z", "a".."z": Identifier ELSE Texts.Read(r, ch); sym := null END; END Scan; PROCEDURE Imports(VAR list: Table; VAR max: INTEGER; name: ARRAY OF CHAR; short: BOOLEAN); VAR T: Texts.Text; r: Texts.Reader; source, import, s: ARRAY 32 OF CHAR; this, i, j, sym: INTEGER; BEGIN IF (name = "SYSTEM") OR short & ((name = "Display") OR (name = "FileDir") OR (name = "Files") OR (name = "Fonts") OR (name = "Input") OR (name = "Kernel") OR (name = "MenuViewers") OR (name = "Modules") OR (name = "Oberon") OR (name = "Printer") OR (name = "Reals") OR (name = "TextFrames") OR (name = "Texts") OR (name = "Viewers") OR (name = "WriteFrames") OR (name = "WritePrinter")) THEN RETURN END; i := -1; REPEAT INC(i); source[i] := name[i] UNTIL name[i] = 0X; source[i] := "."; source[i+1] := "M"; source[i+2] := "o"; source[i+3] := "d"; source[i+4] := 0X; T := TF.Text(source); IF T.len = 0 THEN name[i] := "-"; name[i+1] := 0X END; (* append name to list, if not already there *) i := 0; WHILE (i < max) & (name # list[i]) DO INC(i) END; IF i < max THEN RETURN (* was processed already *) ELSE COPY(name, list[max]); this := max; INC(max) END; IF Debug THEN Log.Str("inserting "); Log.Str(name); Log.Ln END; Texts.OpenReader(r, T, 0); ch := " "; REPEAT Scan(r, s, sym) UNTIL r.eot OR (sym = ident) & (s = "IMPORT"); IF r.eot THEN RETURN END; LOOP Scan(r, s, sym); IF r.eot THEN EXIT END; COPY(s, import); Scan(r, s, sym); IF r.eot THEN EXIT END; IF sym = becomes THEN Scan(r, s, sym); COPY(s, import); Scan(r, s, sym) END; IF r.eot THEN EXIT END; (* search import in list *) i := 0; WHILE (i < this) & (import # list[i]) DO INC(i) END; IF i < this THEN (* was imported already by another module -> move name (@ this) before import (@ i) *) IF Debug THEN Log.Str("moving "); Log.Str(name); Log.Int(this); Log.Str(" before "); Log.Str(import); Log.Int(i); Log.Ln END; j := this; WHILE j > i DO list[j] := list[j-1]; DEC(j) END; COPY(name, list[i]); this := i END; Imports(list, max, import, short); IF r.eot OR (sym = semicolon) THEN EXIT END END END Imports; PROCEDURE MakeList(short: BOOLEAN); CONST Menu = "System.Close System.Copy System.Grow Edit.Search Edit.Replace All Edit.Store "; VAR V: Viewers.Viewer; T: Texts.Text; S: Texts.Scanner; beg, end, time: LONGINT; imports: Table; max, x, y, i: INTEGER; opt: ARRAY 32 OF CHAR; BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF (S.class = Texts.String) & (S.line = 0) THEN COPY(S.s, opt); Texts.Scan(S) ELSE opt := defaultOptions END; IF (S.class = Texts.Char) & (S.line = 0) & (S.c = "^") THEN Oberon.GetSelection(T, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(S, T, beg); Texts.Scan(S) END END; IF S.class = Texts.Name THEN i := S.len; IF (i >= 6) & (S.s[i-4] = ".") & (S.s[i-3] = "M") & (S.s[i-2] = "o") & (S.s[i-1] = "d") THEN S.s[i-4] := 0X END; max := 0; Imports(imports, max, S.s, short); IF max > 0 THEN Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); T := TF.Text(""); V := MV.New(TF.NewMenu(S.s, Menu), TF.NewText(T, 0), TF.menuH, x, y); Texts.WriteString(W, defaultCompiler); Texts.WriteLn(W); REPEAT DEC(max); Texts.WriteString(W, imports[max]); Texts.WriteString(W, ".Mod"); IF opt[0] # 0X THEN Texts.Write(W, optionChar); Texts.WriteString(W, opt) END; Texts.WriteLn(W) UNTIL max = 0; Texts.Write(W, "~"); Texts.WriteLn(W); Texts.Append(T, W.buf) END END END MakeList; PROCEDURE Make*; (** (name options) | "^" generate compile list of module name with /options appended to it **) BEGIN MakeList(TRUE) END Make; PROCEDURE MakeLong*; (** (name options) | "^" generate compile list including core modules of module name with /options appended to it **) BEGIN MakeList(FALSE) END MakeLong; BEGIN Texts.OpenWriter(W) END Make.