Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

Oberon/ETH Oberon/2.3.7/Compiler.Mod

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE Compiler; (** portable, except where noted *) IMPORT OPP, OPB, OPV, OPT, OPS, OPC, OPL, OPO, OPM, Modules, Display, Oberon, Texts; CONST NoBreakPC = -1; module = OPS.module; ident = OPS.ident; period = OPS.period; (* symbols *) VAR W: Texts.Writer; PROCEDURE SignOn; BEGIN Texts.WriteString(W, "Oberon Portable Compiler / nw, rc, nm, tk, prk"); Texts.WriteLn(W); Texts.WriteString(W, OPP.SignOnMessage); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) END SignOn; PROCEDURE GetOptions(VAR S: Texts.Scanner; VAR opts: ARRAY OF CHAR); VAR i: LONGINT; ch: CHAR; BEGIN WHILE (S.class = Texts.Char) & (S.c = Oberon.OptionChar) DO i := 0; WHILE opts[i] # 0X DO INC(i) END; ch := S.nextCh; WHILE ch > " " DO opts[i] := ch; INC(i); Texts.Read(S, ch) END; opts[i] := " "; INC(i); opts[i] := 0X; S.nextCh := ch; Texts.Scan(S) END; END GetOptions; PROCEDURE InOptions(VAR opt: ARRAY OF CHAR; ch: CHAR): BOOLEAN; VAR i: LONGINT; BEGIN i := 0; WHILE (opt[i] # 0X) & (opt[i] # ch) DO IF (opt[i] = ".") OR (opt[i] = "P") THEN REPEAT INC(i) UNTIL (opt[i] = 0X) OR (opt[i] = " ") ELSE INC(i) END END; RETURN opt[i] = ch END InOptions; PROCEDURE Locate(F: Display.Frame; T: Texts.Text; pos: LONGINT); VAR M: Oberon.CaretMsg; N: Oberon.ControlMsg; BEGIN IF pos < 0 THEN pos := 0 ELSIF pos > T.len THEN pos := T.len END; N.F := NIL; N.id := Oberon.neutralize; Display.Broadcast(N); Oberon.FadeCursor(Oberon.Pointer); M.id := Oberon.set; M.F := F; M.car := F; M.text := T; M.pos := pos; Display.Broadcast(M) END Locate; PROCEDURE GetBreakPC(): LONGINT; VAR S: Texts.Scanner; t: Texts.Text; beg, end, time: LONGINT; BEGIN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(S, t, beg); Texts.Scan(S); end := S.line; WHILE (S.class # Texts.Int) & (S.line = end) DO Texts.Scan(S) END; END; IF (time < 0) OR (S.class # Texts.Int) THEN Texts.WriteString(W, " pc not selected"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); RETURN NoBreakPC ELSE RETURN S.i END END GetBreakPC; PROCEDURE ParseOptions(VAR name, options, path, pref, extension: ARRAY OF CHAR; VAR codeOpt, parserOpt: SET); VAR i, j, k: LONGINT; ch: CHAR; BEGIN codeOpt := OPM.DefaultCodeOpt; parserOpt := OPM.DefaultParserOpt; i := 0; path[0] := 0X; pref[0] := 0X; COPY(Modules.extension, extension); LOOP ch := options[i]; INC(i); IF ch = 0X THEN EXIT ELSIF ch = "x" THEN codeOpt := codeOpt / {OPM.inxchk} ELSIF ch = "v" THEN codeOpt := codeOpt / {OPM.ovflchk} ELSIF ch = "t" THEN codeOpt := codeOpt / {OPM.typchk} ELSIF ch = "p" THEN codeOpt := codeOpt / {OPM.ptrinit} ELSIF ch = "a" THEN codeOpt := codeOpt / {OPM.assert} ELSIF ch = "z" THEN codeOpt := codeOpt / {OPM.fullstackinit} ELSIF ch = "q" THEN codeOpt := codeOpt / {OPM.trace} ELSIF ch = "s" THEN parserOpt := parserOpt / {OPM.newsf} ELSIF ch = "S" THEN parserOpt := parserOpt / {OPM.systemchk} ELSIF ch = "n" THEN parserOpt := parserOpt / {OPM.nofiles} ELSIF ch = "e" THEN parserOpt := parserOpt / {OPM.extsf} ELSIF ch = "f" THEN parserOpt := parserOpt / {OPM.findpc} ELSIF ch = "w" THEN parserOpt := parserOpt / {OPM.warning} ELSIF ch = "X" THEN parserOpt := parserOpt + {OPM.prefix} ELSIF ch = "2" THEN parserOpt := parserOpt / {OPM.oberon2} ELSIF ch = "1" THEN parserOpt := parserOpt / {OPM.oberon1} ELSIF ch = "T" THEN parserOpt := parserOpt / {OPM.traceprocs} (* temp *) ELSIF ch = "." THEN j := 0; WHILE (ch # 0X) & (ch # " ") DO extension[j] := ch; ch := options[i]; INC(j); INC(i) END; extension[j] := 0X ELSIF ch = "P" THEN ch := options[i]; INC(i); k := 0; WHILE (ch # 0X) & (ch # " ") DO path[k] := ch; INC(k); ch := options[i]; INC(i) END; path[k] := 0X ELSIF ch = "O" THEN (* mutually exclusive with "X" *) ch := options[i]; INC(i); k := 0; WHILE (ch # 0X) & (ch # " ") DO pref[k] := ch; INC(k); ch := options[i]; INC(i) END; pref[k] := 0X END END; IF OPM.prefix IN parserOpt THEN i := -1; REPEAT INC(i); pref[i] := name[i] UNTIL (name[i] = 0X) OR (name[i] = "."); IF name[i] # "." THEN i := 0 ELSE INC(i) END; pref[i] := 0X END END ParseOptions; PROCEDURE WriteMsg(source: Texts.Reader; log: Texts.Text); VAR sym: SHORTINT; BEGIN Texts.WriteString(W, " compiling "); OPM.Init({}, {}, source, log); OPS.Get(sym); IF sym = module THEN OPS.Get(sym); IF sym = ident THEN Texts.WriteString(W, OPM.outputPath); Texts.WriteString(W, OPM.outputPrefix); OPS.Get(sym); Texts.WriteString(W, OPS.name); WHILE sym = period DO Texts.Write(W, "."); OPS.Get(sym); IF sym = ident THEN Texts.WriteString(W, OPS.name); OPS.Get(sym) END; END; IF OPM.extension # Modules.extension THEN Texts.WriteString(W, OPM.extension) ELSIF (OPM.outputPath = "") & (OPM.outputPrefix = "") THEN (* not cross-compiling *) IF Modules.FindMod(OPS.name) # NIL THEN Texts.WriteString(W, " (in use) ") END ELSE (* skip *) END END END; Texts.Append(log, W.buf) END WriteMsg; PROCEDURE Module*(source: Texts.Reader; name, options: ARRAY OF CHAR; breakpc: LONGINT; log: Texts.Text; VAR error: BOOLEAN); VAR codeOpt, parserOpt: SET; extSF, newSF: BOOLEAN; p: OPT.Node; modName: OPS.Name; BEGIN ParseOptions(name, options, OPM.outputPath, OPM.outputPrefix, OPM.extension, codeOpt, parserOpt); WriteMsg(source, log); OPM.Init(codeOpt, parserOpt, source, log); OPS.ch := " "; OPB.typSize := OPV.TypSize; OPV.Init(breakpc); newSF := OPM.newsf IN parserOpt; extSF := OPM.extsf IN parserOpt; OPP.Module(p, modName); IF OPM.noerr THEN OPL.Init; OPM.errpos := 0; OPM.Begin(modName); IF OPM.noerr THEN OPT.Export(modName, newSF, extSF); OPV.AdrAndSize(OPT.topScope); IF newSF THEN OPM.LogWStr(" new symbol file") ELSIF extSF THEN OPM.LogWStr(" extended symbol file") END; IF OPM.noerr THEN OPM.errpos := 0; OPC.Init; OPV.Module(p); IF OPM.noerr THEN OPL.OutCode(modName); IF OPM.noerr THEN OPM.LogWStr (" "); OPM.LogWNum(OPO.pc, 1) END END END; OPL.Close END END; OPT.CloseScope; OPT.Close; OPM.LogWLn; error := ~OPM.noerr; OPM.outputPath := "!"; OPM.outputPrefix := "!" (* invalid filename *) END Module; PROCEDURE CompileText(t: Texts.Text; pos: LONGINT; frame: Display.Frame; opt: ARRAY OF CHAR; VAR error: BOOLEAN); VAR f: BOOLEAN; pc: LONGINT; r: Texts.Reader; BEGIN IF t # NIL THEN Texts.OpenReader(r, t, pos); f := InOptions(opt, "f"); IF f THEN pc := GetBreakPC(); IF pc = NoBreakPC THEN RETURN END END; OPS.Init; Module(r, "", opt, pc, Oberon.Log, error); IF f & (frame # NIL) THEN Locate(frame, t, OPM.breakpos) END ELSE Texts.WriteString(W, "No text marked"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); error := TRUE END END CompileText; PROCEDURE CompileFile*(name, opt: ARRAY OF CHAR; VAR error: BOOLEAN); VAR t: Texts.Text; r: Texts.Reader; pc: LONGINT; BEGIN NEW(t); Texts.Open(t, name); IF t.len # 0 THEN Texts.OpenReader(r, t, 0); IF InOptions(opt, "f") THEN pc := GetBreakPC(); IF pc = NoBreakPC THEN RETURN END END; Texts.WriteString(W, name); OPS.Init; Module(r, name, opt, pc, Oberon.Log, error) ELSE Texts.WriteString(W, name); Texts.WriteString(W, " not found"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); error := TRUE END END CompileFile; PROCEDURE Compile*; VAR S: Texts.Scanner; globalOpt, localOpt: ARRAY 32 OF CHAR; t: Texts.Text; pos, end, time: LONGINT; frame: Display.Frame; name: ARRAY 64 OF CHAR; error: BOOLEAN; BEGIN error := FALSE; Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); globalOpt := ""; GetOptions(S, globalOpt); IF (S.class = Texts.Char) & ((S.c = "*") OR (S.c = "@")) THEN IF S.c = "*" THEN t := Oberon.MarkedText(); pos := 0; frame := Oberon.MarkedFrame(); ELSE (* S.c = "@" *) Oberon.GetSelection(t, pos, end, time); frame := NIL; IF time < 0 THEN RETURN END END; Texts.Scan(S); GetOptions(S, globalOpt); CompileText(t, pos, frame, globalOpt, error); ELSIF ((S.class = Texts.Char) & (S.c = "^")) OR (S.class = Texts.Name) THEN IF (S.c = "^") THEN Oberon.GetSelection(t, pos, end, time); Texts.OpenScanner(S, t, pos); Texts.Scan(S) ELSE end := MAX(LONGINT) END; WHILE (S.class = Texts.Name) & (Texts.Pos(S) - S.len <= end) & ~error DO COPY(S.s, name); COPY(globalOpt, localOpt); Texts.Scan(S); GetOptions(S, localOpt); CompileFile(name, localOpt, error) END END END Compile; BEGIN Texts.OpenWriter(W); SignOn END Compiler. Compiler.Compile Test.Mod ~ Compiler.Compile Test.Mod\s ~ Compiler.Compile Test.Mod\sX.Obx ~ Compiler.Compile * Compiler.Compile *\s Compiler.Compile \.Obx Test.Mod Test.Mod\.Obf Test.Mod ~ Compiler.Compile @