diff --git a/src/compiler/OPM.Mod b/src/compiler/OPM.Mod index fe43393b..7c88f8fc 100644 --- a/src/compiler/OPM.Mod +++ b/src/compiler/OPM.Mod @@ -500,8 +500,6 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) WHILE i > 0 DO LogW(" "); DEC(i) END; LogVT100(VT100.Green); LogW("^"); LogVT100(VT100.ResetAll); - - Files.Close(f); END ShowLine; @@ -597,7 +595,8 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *) oldSFile := Files.Old(fileName); done := oldSFile # NIL; IF done THEN Files.Set(oldSF, oldSFile, 0); Files.Read(oldSF, tag); Files.Read(oldSF, ver); - IF (tag # SFtag) OR (ver # SFver) THEN err(-306); (*possibly a symbol file from another Oberon implementation, e.g. HP-Oberon*) + IF (tag # SFtag) OR (ver # SFver) THEN + err(-306); (*possibly a symbol file from another Oberon implementation, e.g. HP-Oberon*) CloseOldSym; done := FALSE END END diff --git a/src/runtime/Files.Mod b/src/runtime/Files.Mod index 543a5c9c..983b4f64 100644 --- a/src/runtime/Files.Mod +++ b/src/runtime/Files.Mod @@ -18,14 +18,15 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files BufSize = 4096; NoDesc = -1; - (* file states *) + (* No file states, used when FileDesc.fd = NoDesc *) open = 0; (* OS File has been opened *) create = 1; (* OS file needs to be created *) - close = 2; (* Register telling Create to use registerName directly: - i.e. since we're closing and all data is still in - buffers bypass writing to temp file and then renaming - and just write directly to fianl register name *) - + close = 2; (* Flag used by Files.Register to tell Create to create the + file using it's registerName directly, rather than to + create a temporary file: i.e. since we're closing and all + data is still in buffers bypass writing to temp file and + then renaming and just write directly to final register + name *) TYPE FileName = ARRAY 101 OF CHAR; @@ -37,7 +38,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files registerName: FileName; tempFile: BOOLEAN; identity: Platform.FileIdentity; - fd-: Platform.FileHandle; + fd: Platform.FileHandle; len, pos: LONGINT; bufs: ARRAY NumBufs OF Buffer; swapper: INTEGER; @@ -63,7 +64,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files VAR - files: File; (* List of files that have an OS file handle/descriptor assigned *) + files: File; (* List of files backed by an OS file, whether open, registered or temporary. *) tempno: INTEGER; HOME: ARRAY 1024 OF CHAR; SearchPath: POINTER TO ARRAY OF CHAR; @@ -122,6 +123,10 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files END GetTempName; PROCEDURE Create(f: File); + (* Makes sure there is an OS file backing this Oberon file. + Used when more data has been written to an unregistered new file than + buffers can hold, or when registering a new file whose data is all in + buffers. *) VAR identity: Platform.FileIdentity; done: BOOLEAN; @@ -137,16 +142,20 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files *) IF f.fd = NoDesc THEN IF f.state = create THEN + (* New file with enough data written to exceed buffers, so we need to + create a temporary file to back it. *) GetTempName(f.registerName, f.workName); f.tempFile := TRUE - ELSIF f.state = close THEN + ELSE + ASSERT(f.state = close); + (* New file with all data in buffers being registered. No need for a + temp file, will just write the buffers to the registerName. *) f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE END; error := Platform.Unlink(f.workName); (*unlink first to avoid stale NFS handles and to avoid reuse of inodes*) - error := Platform.New(f.workName, f.fd); done := error = 0; IF done THEN - f.next := files; files := f; + f.next := files; files := f; (* Link this file into the list of OS bakced files. *) INC(Heap.FileCount); Heap.RegisterFinalizer(f, Finalize); f.state := open; @@ -186,31 +195,12 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files IF error # 0 THEN Err("error writing file", f, error) END; f.pos := buf.org + buf.size; buf.chg := FALSE; - error := Platform.Identify(f.fd, f.identity); + error := Platform.Identify(f.fd, f.identity); (* Update identity with new modification time. *) IF error # 0 THEN Err("error identifying file", f, error) END; - (* - error := Platform.Identify(f.fd, identity); - f.identity.mtime := identity.mtime; - *) END END Flush; - PROCEDURE CloseOSFile(f: File); - (* Close the OS file handle and remove f from 'files' *) - VAR prev: File; error: Platform.ErrorCode; - BEGIN - IF files = f THEN files := f.next - ELSE - prev := files; - WHILE (prev # NIL) & (prev.next # f) DO prev := prev.next END; - IF prev.next # NIL THEN prev.next := f.next END - END; - error := Platform.Close(f.fd); - f.fd := NoDesc; f.state := create; DEC(Heap.FileCount); - END CloseOSFile; - - PROCEDURE Close* (f: File); VAR i: LONGINT; @@ -219,12 +209,6 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files IF (f.state # create) OR (f.registerName # "") THEN Create(f); i := 0; WHILE (i < NumBufs) & (f.bufs[i] # NIL) DO Flush(f.bufs[i]); INC(i) END; - (* There's no reason to sync this file - we're about to close it. The OS - will sync if necessary. Further, sync will fail for a R/O file on Windows. - error := Platform.Sync(f.fd); - IF error # 0 THEN Err("error syncing file", f, error) END; - *) - CloseOSFile(f); END END Close; @@ -323,7 +307,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files error := Platform.Identify(fd, identity); f := CacheEntry(identity); IF f # NIL THEN - (* error := Platform.Close(fd); DCWB: Either this should be removed or should call CloseOSFile. *) + error := Platform.Close(fd); (* fd not needed - we'll be using f.fd. *) RETURN f ELSE NEW(f); Heap.RegisterFinalizer(f, Finalize); f.fd := fd; f.state := open; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*) @@ -579,7 +563,7 @@ Especially Length would become fairly complex. END Rename; PROCEDURE Register* (f: File); - VAR idx, errcode: INTEGER; f1: File; file: ARRAY 104 OF CHAR; + VAR idx, errcode: INTEGER; f1: File; BEGIN (* Out.String("Files.Register f.registerName = "); Out.String(f.registerName); @@ -595,7 +579,7 @@ Especially Length would become fairly complex. Out.String(" to registerName "); Out.String(f.registerName); Out.String(" errorcode = "); Out.Int(errcode,1); Out.Ln; *) - IF errcode # 0 THEN COPY(f.registerName, file); HALT(99) END; + 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 END Register; @@ -725,6 +709,20 @@ Especially Length would become fairly complex. COPY (f.workName, name); END GetName; + PROCEDURE CloseOSFile(f: File); + (* Close the OS file handle and remove f from 'files' *) + VAR prev: File; error: Platform.ErrorCode; + BEGIN + IF files = f THEN files := f.next + ELSE + prev := files; + WHILE (prev # NIL) & (prev.next # f) DO prev := prev.next END; + IF prev.next # NIL THEN prev.next := f.next END + END; + error := Platform.Close(f.fd); + f.fd := NoDesc; f.state := create; DEC(Heap.FileCount); + END CloseOSFile; + PROCEDURE Finalize(o: SYSTEM.PTR); VAR f: File; res: LONGINT; BEGIN diff --git a/src/runtime/Heap.Mod b/src/runtime/Heap.Mod index 71a0d161..e368ae88 100644 --- a/src/runtime/Heap.Mod +++ b/src/runtime/Heap.Mod @@ -530,7 +530,8 @@ MODULE Heap; PROCEDURE GC*(markStack: BOOLEAN); VAR m: Module; - i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23: S.ADDRESS; + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, + i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23: S.ADDRESS; cand: ARRAY 10000 OF S.ADDRESS; BEGIN IF (lockdepth = 0) OR (lockdepth = 1) & ~markStack THEN diff --git a/src/runtime/Modules.Mod b/src/runtime/Modules.Mod index 28050126..970bc547 100644 --- a/src/runtime/Modules.Mod +++ b/src/runtime/Modules.Mod @@ -136,7 +136,7 @@ MODULE Modules; (* jt 6.1.96 *) PROCEDURE Halt*(code: SYSTEM.INT32); BEGIN - (*IF HaltHandler # NIL THEN HaltHandler(code) END;*) + Heap.FINALL; errstring("Terminated by Halt("); errint(code); errstring("). "); IF code < 0 THEN DisplayHaltCode(code) END; errstring(Platform.NL); @@ -145,6 +145,7 @@ MODULE Modules; (* jt 6.1.96 *) PROCEDURE AssertFail*(code: SYSTEM.INT32); BEGIN + Heap.FINALL; errstring("Assertion failure."); IF code # 0 THEN errstring(" ASSERT code "); errint(code); errstring("."); END; errstring(Platform.NL);