diff --git a/ReadMe.md b/ReadMe.md index a3f55f77..95732f0d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -125,7 +125,7 @@ Alternatively the Oakwood module Out can be used to write directly to stdout: MODULE hello; IMPORT Out; BEGIN - Out.String("Hello."); Out.Ln; + Out.String("Hello."); Out.Ln END hello. ``` @@ -144,7 +144,7 @@ Execute as usual on Linux (`./hello`) or Windows (`hello`). In order to see the definition of a module's interface, use the "showdef" program. ``` -$ showdef Out.sym +$ showdef Out DEFINITION Out; VAR diff --git a/src/compiler/Compiler.Mod b/src/compiler/Compiler.Mod index 4e9c5c10..c9f454cf 100644 --- a/src/compiler/Compiler.Mod +++ b/src/compiler/Compiler.Mod @@ -6,9 +6,6 @@ MODULE Compiler; (* J. Templ 3.2.95 *) OPV, OPC, OPM, extTools, Strings, VT100; - VAR mname: ARRAY 256 OF CHAR; (* noch *) - - PROCEDURE Module*(VAR done: BOOLEAN); VAR ext, new: BOOLEAN; p: OPT.Node; BEGIN @@ -20,11 +17,12 @@ MODULE Compiler; (* J. Templ 3.2.95 *) OPT.Export(ext, new); IF OPM.noerr THEN OPM.OpenFiles(OPT.SelfName); + OPM.DeleteObj(OPT.SelfName); (* Make sure old object file isn't left hanging around. *) OPC.Init; OPV.Module(p); IF OPM.noerr THEN IF (OPM.mainprog IN OPM.Options) & (OPM.modName # "SYSTEM") THEN - OPM.DeleteNewSym; + OPM.DeleteNewSym(OPT.SelfName); OPM.LogVT100(VT100.Green); OPM.LogWStr(" Main program."); OPM.LogVT100(VT100.ResetAll); ELSE IF new THEN @@ -36,7 +34,7 @@ MODULE Compiler; (* J. Templ 3.2.95 *) END END; ELSE - OPM.DeleteNewSym + OPM.DeleteNewSym(OPT.SelfName) END END END; @@ -83,17 +81,48 @@ MODULE Compiler; (* J. Templ 3.2.95 *) END PropagateElementaryTypeSizes; + PROCEDURE FindLocalObjectFiles(VAR objectnames: ARRAY OF CHAR); + VAR + l: OPT.Link; + fn: ARRAY 64 OF CHAR; + id: Platform.FileIdentity; + BEGIN + objectnames[0] := 0X; + l := OPT.Links; WHILE l # NIL DO + (* Tell linker to link this module as an object file if both a symbol + and an object file exist in the current directory. *) + COPY(l.name, fn); Strings.Append('.sym', fn); + IF Platform.IdentifyByName(fn, id) = 0 THEN + COPY(l.name, fn); Strings.Append(Configuration.objext, fn); + IF Platform.IdentifyByName(fn, id) = 0 THEN + Strings.Append(' ', objectnames); + Strings.Append(fn, objectnames) + ELSE + (* Found symbol file but no object file. *) + OPM.LogVT100(VT100.Yellow); + OPM.LogWStr("Link warning: a local symbol file is present for module "); OPM.LogWStr(l.name); + OPM.LogWStr(", but local object file '"); OPM.LogWStr(fn); OPM.LogWStr("' is missing."); + OPM.LogVT100(VT100.ResetAll); OPM.LogWLn + END + ELSE + (* No symbol file present in current directory. + Assume this referenced module is in a library. *) + END; + l := l.next + END + END FindLocalObjectFiles; + + PROCEDURE Translate*; VAR - done: BOOLEAN; - modulesobj: ARRAY 2048 OF CHAR; (* here we hold all modules name given on the command line, to add corresponding .o files to the external compiler options *) + done: BOOLEAN; + linkfiles: ARRAY 2048 OF CHAR; (* Object files to be linked into main program. *) BEGIN - modulesobj := ""; IF OPM.OpenPar() THEN (* gclock(); slightly faster translation but may lead to opening "too many files" *) LOOP - OPM.Init(done, mname); (* Get next module name from command line *) + OPM.Init(done); (* Get next module name from command line *) IF ~done THEN RETURN END ; OPM.InitOptions; (* Get options for this module *) @@ -116,12 +145,10 @@ MODULE Compiler; (* J. Templ 3.2.95 *) IF ~(OPM.mainprog IN OPM.Options) THEN (* Assemble non main program and add object name to link list *) extTools.Assemble(OPM.modName); - Strings.Append(" ", modulesobj); - Strings.Append(OPM.modName, modulesobj); - Strings.Append(Configuration.objext, modulesobj) ELSE (* Assemble and link main program *) - extTools.LinkMain(OPM.modName, OPM.mainlinkstat IN OPM.Options, modulesobj) + FindLocalObjectFiles(linkfiles); + extTools.LinkMain(OPM.modName, OPM.mainlinkstat IN OPM.Options, linkfiles) END END END diff --git a/src/compiler/OPM.Mod b/src/compiler/OPM.Mod index 583c4318..a5a3df1a 100644 --- a/src/compiler/OPM.Mod +++ b/src/compiler/OPM.Mod @@ -76,7 +76,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) BFext = ".c"; (* body file extension *) HFext = ".h"; (* header file extension *) SFtag = 0F7X; (* symbol file tag *) - SFver = 082X; (* symbol file version. Increment if symbol file format is changed. *) + SFver = 083X; (* symbol file version. Increment if symbol file format is changed. *) @@ -353,7 +353,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) END InitOptions; - PROCEDURE Init*(VAR done: BOOLEAN; VAR mname : ARRAY OF CHAR); (* get the source for one translation *) + PROCEDURE Init*(VAR done: BOOLEAN); (* get the source for one translation *) VAR T: Texts.Text; beg, end, time: LONGINT; @@ -367,7 +367,6 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) NEW(T); Texts.Open(T, s); LogWStr(s); LogWStr(" "); - COPY(s, mname); COPY(s, SourceFileName); (* to keep it also in this module -- noch *) IF T.len = 0 THEN @@ -636,9 +635,16 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) IF (modName # "SYSTEM") OR (mainprog IN Options) THEN Files.Register(newSFile) END END RegisterNewSym; - PROCEDURE DeleteNewSym*; + PROCEDURE DeleteNewSym*(VAR modulename: ARRAY OF CHAR); + VAR fn: FileName; res: INTEGER; + BEGIN MakeFileName(modulename, fn, SFext); Files.Delete(fn, res) END DeleteNewSym; + PROCEDURE DeleteObj*(VAR modulename: ARRAY OF CHAR); + VAR fn: FileName; res: INTEGER; + BEGIN MakeFileName(modulename, fn, Configuration.objext); Files.Delete(fn, res) + END DeleteObj; + PROCEDURE NewSym*(VAR modName: ARRAY OF CHAR); VAR fileName: FileName; BEGIN MakeFileName(modName, fileName, SFext); @@ -742,7 +748,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) END Append; PROCEDURE OpenFiles*(VAR moduleName: ARRAY OF CHAR); - VAR FName: ARRAY 32 OF CHAR; + VAR FName: FileName; BEGIN COPY(moduleName, modName); HFile := Files.New(""); @@ -756,7 +762,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) END OpenFiles; PROCEDURE CloseFiles*; - VAR FName: ARRAY 32 OF CHAR; res: INTEGER; + VAR FName: FileName; res: INTEGER; BEGIN IF noerr THEN LogWStr(" "); LogWNum(Files.Pos(R[BodyFile]), 0); LogWStr(" chars.") END; IF noerr THEN @@ -779,7 +785,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) (* === Installation directory discovery === *) PROCEDURE IsProbablyInstallDir(s: ARRAY OF CHAR): BOOLEAN; - VAR testpath: ARRAY 1024 OF CHAR; identity: Platform.FileIdentity; + VAR testpath: ARRAY 4096 OF CHAR; identity: Platform.FileIdentity; BEGIN COPY(InstallDir, testpath); Strings.Append("/lib/lib", testpath); diff --git a/src/compiler/OPP.Mod b/src/compiler/OPP.Mod index 0ff9b7fb..8cfc5a55 100644 --- a/src/compiler/OPP.Mod +++ b/src/compiler/OPP.Mod @@ -922,7 +922,7 @@ MODULE OPP; (* NW, RC 6.3.89 / 10.2.94 *) (* object model 4.12.93 *) OPT.Insert(OPS.name, obj); obj^.mode := OPT.Typ; obj^.typ := OPT.undftyp; CheckMark(obj^.vis); IF sym = OPS.eql THEN - IF (obj^.name = "SHORTINT") OR + IF (obj^.name = "SHORTINT") OR (obj^.name = "INTEGER") OR (obj^.name = "LONGINT") OR (obj^.name = "HUGEINT") OR @@ -931,7 +931,7 @@ MODULE OPP; (* NW, RC 6.3.89 / 10.2.94 *) (* object model 4.12.93 *) (obj^.name = "SET") OR (obj^.name = "CHAR") OR (obj^.name = "TRUE") OR (obj^.name = "FALSE") THEN - OPM.Mark(-310, OPM.curpos); (* notice about aliasing of predefined type *) + OPM.Mark(-310, OPM.curpos); (* notice about aliasing of predefined type *) END; OPS.Get(sym); TypeDecl(obj^.typ, obj^.typ) ELSIF (sym = OPS.becomes) OR (sym = OPS.colon) THEN @@ -1005,17 +1005,7 @@ MODULE OPP; (* NW, RC 6.3.89 / 10.2.94 *) (* object model 4.12.93 *) c: LONGINT; done: BOOLEAN; BEGIN OPS.Init; LoopLevel := 0; level := 0; OPS.Get(sym); - IF sym = OPS.module THEN OPS.Get(sym) ELSE - (* Debug intermittent failure only found on OpenBSD *) - OPM.LogWLn; - OPM.LogWStr("Unexpected symbol found when MODULE expected:"); OPM.LogWLn; - OPM.LogWStr(" sym: "); OPM.LogWNum(sym,1); OPM.LogWLn; - OPM.LogWStr(" OPS.name: "); OPM.LogWStr(OPS.name); OPM.LogWLn; - OPM.LogWStr(" OPS.str: "); OPM.LogWStr(OPS.str); OPM.LogWLn; - OPM.LogWStr(" OPS.numtyp: "); OPM.LogWNum(OPS.numtyp,1); OPM.LogWLn; - OPM.LogWStr(" OPS.intval: "); OPM.LogWNum(OPS.intval,1); OPM.LogWLn; - err(16) - END; + IF sym = OPS.module THEN OPS.Get(sym) ELSE err(16) END; IF sym = OPS.ident THEN OPM.LogWStr("compiling "); OPM.LogWStr(OPS.name); OPM.LogW("."); OPT.Init(OPS.name, opt); OPS.Get(sym); CheckSym(OPS.semicolon); diff --git a/src/compiler/OPT.Mod b/src/compiler/OPT.Mod index 54975745..2c54d11f 100644 --- a/src/compiler/OPT.Mod +++ b/src/compiler/OPT.Mod @@ -176,7 +176,7 @@ CONST Srvar* = 22; Svalpar* = 23; Svarpar* = 24; Sfld* = 25; Srfld* = 26; Shdptr* = 27; Shdpro* = 28; Stpro* = 29; Shdtpro* = 30; Sxpro* = 31; Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36; - Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; + Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37; TYPE ImpCtxt = RECORD @@ -207,6 +207,18 @@ VAR recno: LONGINT; (* number of anonymous record types *) +(* Linking control - modules whose object files will be required to link a module. *) + +TYPE + Link* = POINTER TO LinkDesc; + LinkDesc* = RECORD + name-: OPS.Name; + next-: Link + END; + +VAR + Links-: Link; + PROCEDURE InitRecno*; BEGIN recno := 0 END InitRecno; PROCEDURE err(n: INTEGER); BEGIN OPM.err(n) END err; @@ -392,7 +404,8 @@ BEGIN topScope := universe; OpenScope(0, NIL); SYSimported := FALSE; SelfName := name; topScope^.name := name; GlbMod[0] := topScope; nofGmod := 1; - newsf := nsf IN opt; findpc := fpc IN opt; extsf := newsf OR (esf IN opt); sfpresent := TRUE + newsf := nsf IN opt; findpc := fpc IN opt; extsf := newsf OR (esf IN opt); sfpresent := TRUE; + NEW(Links); Links.name := name END Init; PROCEDURE Close*; @@ -733,6 +746,20 @@ BEGIN END END InMod; +PROCEDURE InLinks; (* Load a list of all modules whose object files we will need to link with *) + VAR linkname: OPS.Name; l: Link; +BEGIN + InName(linkname); + WHILE linkname[0] # 0X DO + l := Links; WHILE (l # NIL) & (l.name # linkname) DO l := l.next END; + IF l = NIL THEN + l := Links; NEW(Links); + Links.next := l; Links.name := linkname + END; + InName(linkname) + END +END InLinks; + PROCEDURE InConstant(f: LONGINT; conval: Const); VAR ch: CHAR; i: INTEGER; ext: ConstExt; rval: REAL; BEGIN @@ -1022,7 +1049,7 @@ BEGIN impCtxt.self := aliasName = "@self"; impCtxt.reffp := 0; OPM.OldSym(name, done); IF done THEN - InMod(mno); + InMod(mno); InLinks; impCtxt.nextTag := OPM.SymRInt(); WHILE ~OPM.eofSF() DO obj := InObj(mno); impCtxt.nextTag := OPM.SymRInt() @@ -1057,6 +1084,13 @@ END Import; END END OutMod; + PROCEDURE OutLinks; + VAR l: Link; + BEGIN + l := Links; WHILE l # NIL DO OutName(l.name); l := l.next END; + OPM.SymWCh(0X) + END OutLinks; + PROCEDURE ^OutStr(typ: Struct); PROCEDURE ^OutFlds(fld: Object; adr: LONGINT; visible: BOOLEAN); @@ -1235,7 +1269,7 @@ END Import; IF OPM.noerr THEN (* ~OPM.noerr => ~done *) OPM.NewSym(SelfName); IF OPM.noerr THEN - OPM.SymWInt(Smname); OutName(SelfName); + OPM.SymWInt(Smname); OutName(SelfName); OutLinks; expCtxt.reffp := 0; expCtxt.ref := FirstRef(*Comp+1*); expCtxt.nofm := 1; expCtxt.locmno[0] := 0; i := 1; WHILE i < maxImps DO expCtxt.locmno[i] := -1; INC(i) END; @@ -1248,7 +1282,7 @@ END Import; END; newsf := FALSE; symNew := FALSE; (* because of call to FPrintErr from OPL *) IF ~OPM.noerr OR findpc THEN - OPM.DeleteNewSym + OPM.DeleteNewSym(SelfName) END (* OPM.RegisterNewSym is called in OP2 after writing the object file *) END @@ -1256,6 +1290,8 @@ END Import; END Export; (* no new symbol file if ~OPM.noerr or findpc *) +(*------------------------- Initialise types --------------------------*) + PROCEDURE InitStruct(VAR typ: Struct; form: SHORTINT); BEGIN typ := NewStr(form, Basic); typ^.ref := form; typ^.size := 1; typ^.allocated := TRUE; diff --git a/src/compiler/OPV.Mod b/src/compiler/OPV.Mod index 31e07fd9..d0cbde89 100644 --- a/src/compiler/OPV.Mod +++ b/src/compiler/OPV.Mod @@ -790,7 +790,7 @@ MODULE OPV; (* J. Templ 16.2.95 / 3.7.96 OPM.WriteString("__X("); OPC.Len(r.obj, r.typ, 0); OPM.WriteString(" * "); OPM.WriteInt(r.typ.BaseTyp.size); OPM.WriteString(", "); - OPM.WriteInt(l.typ.size+1); (* _X vaidates 0 .. n-1 so we need to +1. *) + OPM.WriteInt(l.typ.size+1); (* _X validates 0 .. n-1 so we need top+1. *) OPM.Write(")") ELSE (* Array to array copy. *) ASSERT(r.typ.comp = OPT.Array); ASSERT(r.typ.size <= l.typ.size); diff --git a/src/runtime/Files.Mod b/src/runtime/Files.Mod index 76fbdf77..f60e67bb 100644 --- a/src/runtime/Files.Mod +++ b/src/runtime/Files.Mod @@ -645,21 +645,11 @@ Especially Length would become fairly complex. PROCEDURE Register* (f: File); VAR idx, errcode: INTEGER; f1: File; BEGIN - (* - Out.String("Files.Register f.registerName = "); Out.String(f.registerName); - Out.String(", fd = "); Out.Int(f.fd,1); Out.Ln; - *) IF (f.state = create) & (f.registerName # "") THEN f.state := close (* shortcut renaming *) END; Close(f); IF f.registerName # "" THEN Deregister(f.registerName); Rename(f.workName, f.registerName, errcode); - (* - Out.String("Renamed (for register) f.fd = "); Out.Int(f.fd,1); - Out.String(" from workname "); Out.String(f.workName); - Out.String(" to registerName "); Out.String(f.registerName); - Out.String(" errorcode = "); Out.Int(errcode,1); Out.Ln; - *) IF errcode # 0 THEN Err("Couldn't rename temp name as register name", f, errcode) END; f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE END