diff --git a/makefile b/makefile index 98b208f8..4d10be06 100644 --- a/makefile +++ b/makefile @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/makefile.gnuc.armv6j b/makefile.gnuc.armv6j index b8f2b434..987a1f67 100644 --- a/makefile.gnuc.armv6j +++ b/makefile.gnuc.armv6j @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/makefile.gnuc.armv6j_hardfp b/makefile.gnuc.armv6j_hardfp index 4abba44c..7a4b730a 100644 --- a/makefile.gnuc.armv6j_hardfp +++ b/makefile.gnuc.armv6j_hardfp @@ -1,7 +1,7 @@ #SHELL := /bin/bash BUILDID=$(shell date +%Y/%m/%d) TOS = linux -TARCH = armv6j_hardfp +TARCH = armv6j_hardfp #TARCH = x86 x86_64 armv6j armv6j_hardfp armv7a_hardfp CCOMP = gnuc RELEASE = 1.0 @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/makefile.gnuc.armv7a_hardfp b/makefile.gnuc.armv7a_hardfp index 7ca56436..6664890e 100644 --- a/makefile.gnuc.armv7a_hardfp +++ b/makefile.gnuc.armv7a_hardfp @@ -1,7 +1,7 @@ #SHELL := /bin/bash BUILDID=$(shell date +%Y/%m/%d) TOS = linux -TARCH = armv7a_hardfp +TARCH = armv7a_hardfp #TARCH = x86 x86_64 armv6j armv6j_hardfp armv7a_hardfp CCOMP = gnuc RELEASE = 1.0 @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/makefile.gnuc.x86 b/makefile.gnuc.x86 index c84f4ccb..9f5ccb38 100644 --- a/makefile.gnuc.x86 +++ b/makefile.gnuc.x86 @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/makefile.gnuc.x86_64 b/makefile.gnuc.x86_64 index 98b208f8..4d10be06 100644 --- a/makefile.gnuc.x86_64 +++ b/makefile.gnuc.x86_64 @@ -74,6 +74,7 @@ stage3: $(VOCSTATIC) -sPS Args.Mod Console.Mod Unix.Mod $(VOCSTATIC) -sPS oocOakStrings.Mod architecture.Mod version.Mod Kernel.Mod Modules.Mod $(VOCSTATIC) -sxPS Files.Mod + $(VOCSTATIC) -sxPS OakFiles.Mod $(VOCSTATIC) -sPS Reals.Mod CmdlnTexts.Mod errors.Mod # build the compiler @@ -90,7 +91,7 @@ stage4: #this is a way to create a bootstrap binary. stage5: $(CC) SYSTEM.c Args.c Console.c Modules.c Unix.c \ - oocOakStrings.c architecture.c version.c Kernel.c Files.c Reals.c CmdlnTexts.c \ + oocOakStrings.c architecture.c version.c Kernel.c Files.c OakFiles.c Reals.c CmdlnTexts.c \ version.c extTools.c \ OPM.c OPS.c OPT.c OPC.c OPV.c OPB.c OPP.c errors.c @@ -140,6 +141,7 @@ stage6: $(VOCSTATIC) -sP oocLRealConv.Mod oocLRealStr.Mod $(VOCSTATIC) -sP oocRealConv.Mod oocRealStr.Mod $(VOCSTATIC) -sP oocMsg.Mod oocChannel.Mod + $(VOCSTATIC) -sP oocStrings2.Mod oocRts.Mod oocFilenames.Mod $(VOCSTATIC) -sP oocwrapperlibc.Mod $(VOCSTATIC) -sP ulmSYSTEM.Mod $(VOCSTATIC) -sP ulmASCII.Mod ulmSets.Mod diff --git a/ocat b/ocat index 85a685c8..07389ef1 100755 Binary files a/ocat and b/ocat differ diff --git a/showdef b/showdef index fbc76975..6963c10a 100755 Binary files a/showdef and b/showdef differ diff --git a/src/lib/ooc/oocFilenames.Mod b/src/lib/ooc/oocFilenames.Mod new file mode 100644 index 00000000..beccc056 --- /dev/null +++ b/src/lib/ooc/oocFilenames.Mod @@ -0,0 +1,187 @@ +(* This module is obsolete. Don't use it. *) +MODULE oocFilenames; +(* Note: It is not checked whether the concatenated strings fit into the + variables given for them or not *) + +IMPORT + Strings := oocStrings, Strings2 := oocStrings2, Rts := oocRts; + + +PROCEDURE LocateCharLast(str: ARRAY OF CHAR; ch: CHAR): INTEGER; +(* Result is the position of the last occurence of 'ch' in the string 'str'. + If 'ch' does not occur in 'str', then -1 is returned *) + VAR + pos: INTEGER; + BEGIN + pos:=Strings.Length(str); + WHILE (pos >= 0) DO + IF (str[pos] = ch) THEN + RETURN(pos); + ELSE + DEC(pos); + END; (* IF *) + END; (* WHILE *) + RETURN -1 + END LocateCharLast; + +PROCEDURE SplitRChar(str: ARRAY OF CHAR; VAR str1, str2: ARRAY OF CHAR; ch: CHAR); +(* pre : 'str' contains the string to be splited after the rightmost 'ch' *) +(* post: 'str1' contains the left part (including 'ch') of 'str', + iff occurs(ch,str), otherwise "", + 'str2' contains the right part of 'str'. +*) +(* + example: + str = "/aksdf/asdf/gasdfg/esscgd.asdfg" + result: str2 = "esscgd.asdfg" + str1 = "/aksdf/asdf/gasdfg/" +*) + + VAR + len,pos: INTEGER; + BEGIN + len:=Strings.Length(str); + + (* search for the rightmost occurence of 'ch' and + store it's position in 'pos' *) + pos:=LocateCharLast(str,ch); + + COPY(str,str2); (* that has to be done all time *) + IF (pos >= 0) THEN + (* 'ch' occurs in 'str', (str[pos]=ch)=TRUE *) + COPY(str,str1); (* copy the whole string 'str' to 'str1' *) + INC(pos); (* we want to split _after_ 'ch' *) + Strings.Delete(str2,0,pos); (* remove left part from 'str2' *) + Strings.Delete(str1,pos,(len-pos)); (* remove right part from 'str1' *) + ELSE (* there is no pathinfo in 'file' *) + COPY("",str1); (* make 'str1' the empty string *) + END; (* IF *) + END SplitRChar; + +(******************************) +(* decomposition of filenames *) +(******************************) + +PROCEDURE GetPath*(full: ARRAY OF CHAR; VAR path, file: ARRAY OF CHAR); +(* + pre : "full" contains the (maybe) absolute path to a file. + post: "file" contains only the filename, "path" the path for it. + + example: + pre : full = "/aksdf/asdf/gasdfg/esscgd.asdfg" + post: file = "esscgd.asdfg" + path = "/aksdf/asdf/gasdfg/" +*) + + BEGIN + SplitRChar(full,path,file,Rts.pathSeperator); + END GetPath; + +PROCEDURE GetExt*(full: ARRAY OF CHAR; VAR file, ext: ARRAY OF CHAR); + BEGIN + IF (LocateCharLast(full,Rts.pathSeperator) < LocateCharLast(full,".")) THEN + (* there is a "real" extension *) + SplitRChar(full,file,ext,"."); + Strings.Delete(file,Strings.Length(file)-1,1); (* delete "." at the end of 'file' *) + ELSE + COPY(full,file); + COPY("",ext); + END; (* IF *) + END GetExt; + +PROCEDURE GetFile*(full: ARRAY OF CHAR; VAR file: ARRAY OF CHAR); +(* removes both path & extension from 'full' and stores the result in 'file' *) +(* example: + GetFile("/tools/public/o2c-1.2/lib/Filenames.Mod",myname) + results in + myname="Filenames" +*) + VAR + dummy: ARRAY 256 OF CHAR; (* that should be enough... *) + BEGIN + GetPath(full,dummy,file); + GetExt(file,file,dummy); + END GetFile; + + +(****************************) +(* composition of filenames *) +(****************************) + +PROCEDURE AddExt*(VAR full: ARRAY OF CHAR; file, ext: ARRAY OF CHAR); +(* pre : 'file' is a filename + 'ext' is some extension +*) +(* post: 'full' contains 'file'"."'ext', iff 'ext'#"", + otherwise 'file' +*) + BEGIN + COPY(file,full); + IF (ext[0] # 0X) THEN + (* we only append 'real', i.e. nonempty extensions *) + Strings2.AppendChar(".", full); + Strings.Append(ext, full); + END; (* IF *) + END AddExt; + +PROCEDURE AddPath*(VAR full: ARRAY OF CHAR; path, file: ARRAY OF CHAR); +(* pre : 'file' is a filename + 'path' is a path (will not be interpreted) or "" +*) +(* post: 'full' will contain the contents of 'file' with + addition of 'path' at the beginning. +*) + BEGIN + COPY(file,full); + IF (path[0] # 0X) THEN + (* we only add something if there is something... *) + IF (path[Strings.Length(path) - 1] # Rts.pathSeperator) THEN + (* add a seperator, if none is at the end of 'path' *) + Strings.Insert(Rts.pathSeperator, 0, full); + END; (* IF *) + Strings.Insert(path, 0, full) + END; (* IF *) + END AddPath; + +PROCEDURE BuildFilename*(VAR full: ARRAY OF CHAR; path, file, ext: ARRAY OF CHAR); +(* pre : 'file' is the name of a file, + 'path' is its path and + 'ext' is the extension to be added +*) +(* post: 'full' contains concatenation of 'path' with ('file' with 'ext') +*) + BEGIN + AddExt(full,file,ext); + AddPath(full,path,full); + END BuildFilename; + +PROCEDURE ExpandPath*(VAR full: ARRAY OF CHAR; path: ARRAY OF CHAR); +(* Expands "~/" and "~user/" at the beginning of 'path' to it's + intended strings. + "~/" will result in the path to the current user's home, + "~user" will result in the path of "user"'s home. *) + VAR + len, posSep, posSuffix: INTEGER; + suffix, userpath: ARRAY 256 OF CHAR; + username: ARRAY 32 OF CHAR; + BEGIN + COPY (path, full); + IF (path[0] = "~") THEN (* we have to expand something *) + posSep := Strings2.PosChar (Rts.pathSeperator, path); + len := Strings.Length (path); + IF (posSep < 0) THEN (* no '/' in file name, just the path *) + posSep := len; + posSuffix := len + ELSE + posSuffix := posSep+1 + END; + Strings.Extract (path, posSuffix, len-posSuffix, suffix); + Strings.Extract (path, 1, posSep-1, username); + Rts.GetUserHome (userpath, username); + IF (userpath[0] # 0X) THEN (* sucessfull search *) + AddPath (full, userpath, suffix) + END + END + END ExpandPath; + +END oocFilenames. diff --git a/src/lib/ooc/oocRts.Mod b/src/lib/ooc/oocRts.Mod new file mode 100644 index 00000000..e3430141 --- /dev/null +++ b/src/lib/ooc/oocRts.Mod @@ -0,0 +1,78 @@ +MODULE oocRts; (* module is written from scratch by noch to wrap around Unix.Mod and Args.Mod and provide compatibility for some ooc libraries *) +IMPORT Args, Unix, Files := OakFiles, Strings := oocStrings(*, Console*); +CONST + pathSeperator* = "/"; + +VAR i : INTEGER; +b : BOOLEAN; +str0 : ARRAY 128 OF CHAR; + +PROCEDURE System* (command : ARRAY OF CHAR) : INTEGER; +(* Executes `command' as a shell command. Result is the value returned by + the libc `system' function. *) +BEGIN +RETURN Unix.System(command) + +END System; + +PROCEDURE GetEnv* (VAR var: ARRAY OF CHAR; name: ARRAY OF CHAR): BOOLEAN; +(* If an environment variable `name' exists, copy its value into `var' and + return TRUE. Otherwise return FALSE. *) +BEGIN +RETURN Args.getEnv(name, var); +END GetEnv; + + +PROCEDURE GetUserHome* (VAR home: ARRAY OF CHAR; user: ARRAY OF CHAR); +(* Get the user's home directory path (stored in /etc/passwd) + or the current user's home directory if user="". *) +VAR +f : Files.File; +r : Files.Rider; +str, str1 : ARRAY 1024 OF CHAR; +found, found1 : BOOLEAN; +p, p1, p2 : INTEGER; +BEGIN +f := Files.Old("/etc/passwd"); +Files.Set(r, f, 0); + +REPEAT + Files.ReadLine(r, str); + +(* Console.String(str); Console.Ln;*) + + Strings.Extract(str, 0, SHORT(LEN(user)-1), str1); +(* Console.String(str1); Console.Ln;*) + + IF Strings.Equal(user, str1) THEN found := TRUE END; + + UNTIL found OR r.eof; + + IF found THEN + found1 := FALSE; + Strings.FindNext(":", str, SHORT(LEN(user)), found1, p); p2 := p + 1; + Strings.FindNext(":", str, p2, found1, p); p2 := p + 1; + Strings.FindNext(":", str, p2, found1, p); p2 := p + 1; + Strings.FindNext(":", str, p2, found1, p); p2 := p + 1; + Strings.FindNext(":", str, p2, found1, p1); + Strings.Extract(str,p+1,p1-p-1, home); + (*Console.String(home); Console.Ln;*) + ELSE + (* current user's home *) + found1 := GetEnv(home, "HOME"); + (*Console.String("not found"); Console.Ln; Console.String (home); Console.Ln;*) + END + + +END GetUserHome; + +BEGIN +(* test *) +(* +i := System("ls"); +b := GetEnv(str0, "HOME"); +IF b THEN Console.String(str0); Console.Ln END; + +GetUserHome(str0, "noch"); +*) +END oocRts. diff --git a/src/lib/system/gnuc/armv6j/Args.Mod b/src/lib/system/gnuc/armv6j/Args.Mod index 52228613..e8cd2a3c 100644 --- a/src/lib/system/gnuc/armv6j/Args.Mod +++ b/src/lib/system/gnuc/armv6j/Args.Mod @@ -48,5 +48,17 @@ MODULE Args; (* jt, 8.12.94 *) IF p # NIL THEN COPY(p^, val) END END GetEnv; + PROCEDURE getEnv*(var: ARRAY OF CHAR; VAR val: ARRAY OF CHAR): BOOLEAN; + VAR p: ArgPtr; + BEGIN + p := getenv(var); + IF p # NIL THEN + COPY(p^, val); + RETURN TRUE + ELSE + RETURN FALSE + END + END getEnv; + BEGIN argc := Argc(); argv := Argv() END Args. diff --git a/src/lib/system/gnuc/armv6j/Unix.Mod b/src/lib/system/gnuc/armv6j/Unix.Mod index 9b2180b9..21bb53d3 100644 --- a/src/lib/system/gnuc/armv6j/Unix.Mod +++ b/src/lib/system/gnuc/armv6j/Unix.Mod @@ -406,6 +406,11 @@ TYPE r := sys(cmd); END system; - + PROCEDURE System*(cmd : ARRAY OF CHAR): INTEGER; + VAR r : INTEGER; + BEGIN + r := sys(cmd); + RETURN r + END System; END Unix. diff --git a/src/lib/system/gnuc/armv6j_hardfp/Args.Mod b/src/lib/system/gnuc/armv6j_hardfp/Args.Mod index 52228613..e8cd2a3c 100644 --- a/src/lib/system/gnuc/armv6j_hardfp/Args.Mod +++ b/src/lib/system/gnuc/armv6j_hardfp/Args.Mod @@ -48,5 +48,17 @@ MODULE Args; (* jt, 8.12.94 *) IF p # NIL THEN COPY(p^, val) END END GetEnv; + PROCEDURE getEnv*(var: ARRAY OF CHAR; VAR val: ARRAY OF CHAR): BOOLEAN; + VAR p: ArgPtr; + BEGIN + p := getenv(var); + IF p # NIL THEN + COPY(p^, val); + RETURN TRUE + ELSE + RETURN FALSE + END + END getEnv; + BEGIN argc := Argc(); argv := Argv() END Args. diff --git a/src/lib/system/gnuc/armv6j_hardfp/Unix.Mod b/src/lib/system/gnuc/armv6j_hardfp/Unix.Mod index 9b2180b9..21bb53d3 100644 --- a/src/lib/system/gnuc/armv6j_hardfp/Unix.Mod +++ b/src/lib/system/gnuc/armv6j_hardfp/Unix.Mod @@ -406,6 +406,11 @@ TYPE r := sys(cmd); END system; - + PROCEDURE System*(cmd : ARRAY OF CHAR): INTEGER; + VAR r : INTEGER; + BEGIN + r := sys(cmd); + RETURN r + END System; END Unix. diff --git a/src/lib/system/gnuc/armv7a_hardfp/Args.Mod b/src/lib/system/gnuc/armv7a_hardfp/Args.Mod index 52228613..e8cd2a3c 100644 --- a/src/lib/system/gnuc/armv7a_hardfp/Args.Mod +++ b/src/lib/system/gnuc/armv7a_hardfp/Args.Mod @@ -48,5 +48,17 @@ MODULE Args; (* jt, 8.12.94 *) IF p # NIL THEN COPY(p^, val) END END GetEnv; + PROCEDURE getEnv*(var: ARRAY OF CHAR; VAR val: ARRAY OF CHAR): BOOLEAN; + VAR p: ArgPtr; + BEGIN + p := getenv(var); + IF p # NIL THEN + COPY(p^, val); + RETURN TRUE + ELSE + RETURN FALSE + END + END getEnv; + BEGIN argc := Argc(); argv := Argv() END Args. diff --git a/src/lib/system/gnuc/armv7a_hardfp/Unix.Mod b/src/lib/system/gnuc/armv7a_hardfp/Unix.Mod index 9b2180b9..21bb53d3 100644 --- a/src/lib/system/gnuc/armv7a_hardfp/Unix.Mod +++ b/src/lib/system/gnuc/armv7a_hardfp/Unix.Mod @@ -406,6 +406,11 @@ TYPE r := sys(cmd); END system; - + PROCEDURE System*(cmd : ARRAY OF CHAR): INTEGER; + VAR r : INTEGER; + BEGIN + r := sys(cmd); + RETURN r + END System; END Unix. diff --git a/src/lib/system/gnuc/x86/Args.Mod b/src/lib/system/gnuc/x86/Args.Mod index 52228613..e8cd2a3c 100644 --- a/src/lib/system/gnuc/x86/Args.Mod +++ b/src/lib/system/gnuc/x86/Args.Mod @@ -48,5 +48,17 @@ MODULE Args; (* jt, 8.12.94 *) IF p # NIL THEN COPY(p^, val) END END GetEnv; + PROCEDURE getEnv*(var: ARRAY OF CHAR; VAR val: ARRAY OF CHAR): BOOLEAN; + VAR p: ArgPtr; + BEGIN + p := getenv(var); + IF p # NIL THEN + COPY(p^, val); + RETURN TRUE + ELSE + RETURN FALSE + END + END getEnv; + BEGIN argc := Argc(); argv := Argv() END Args. diff --git a/src/lib/system/gnuc/x86/Unix.Mod b/src/lib/system/gnuc/x86/Unix.Mod index 9b2180b9..21bb53d3 100644 --- a/src/lib/system/gnuc/x86/Unix.Mod +++ b/src/lib/system/gnuc/x86/Unix.Mod @@ -406,6 +406,11 @@ TYPE r := sys(cmd); END system; - + PROCEDURE System*(cmd : ARRAY OF CHAR): INTEGER; + VAR r : INTEGER; + BEGIN + r := sys(cmd); + RETURN r + END System; END Unix. diff --git a/src/lib/system/gnuc/x86_64/Args.Mod b/src/lib/system/gnuc/x86_64/Args.Mod index f242766b..c6b7b56e 100644 --- a/src/lib/system/gnuc/x86_64/Args.Mod +++ b/src/lib/system/gnuc/x86_64/Args.Mod @@ -49,5 +49,17 @@ MODULE Args; (* jt, 8.12.94 *) IF p # NIL THEN COPY(p^, val) END END GetEnv; + PROCEDURE getEnv*(var: ARRAY OF CHAR; VAR val: ARRAY OF CHAR): BOOLEAN; + VAR p: ArgPtr; + BEGIN + p := getenv(var); + IF p # NIL THEN + COPY(p^, val); + RETURN TRUE + ELSE + RETURN FALSE + END + END getEnv; + BEGIN argc := Argc(); argv := Argv() END Args. diff --git a/src/lib/system/gnuc/x86_64/Unix.Mod b/src/lib/system/gnuc/x86_64/Unix.Mod index 95c3b867..09351c06 100644 --- a/src/lib/system/gnuc/x86_64/Unix.Mod +++ b/src/lib/system/gnuc/x86_64/Unix.Mod @@ -485,4 +485,13 @@ from man gettimeofday r := sys(cmd); END system; + PROCEDURE System*(cmd : ARRAY OF CHAR): INTEGER; + VAR r : INTEGER; + BEGIN + r := sys(cmd); + RETURN r + END System; + + + END Unix. diff --git a/src/lib/v4/OakFiles.Mod b/src/lib/v4/OakFiles.Mod new file mode 100644 index 00000000..e28bd920 --- /dev/null +++ b/src/lib/v4/OakFiles.Mod @@ -0,0 +1,643 @@ +MODULE OakFiles; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files *) +(* modified version of Files, which opens only the file provided and does not scan any path in any environment variable, also ReadLine procedure added; -- noch *) + IMPORT SYSTEM, Unix, Kernel, Args, Console; + + (* standard data type I/O + + little endian, + Sint:1, Int:2, Lint:4 + ORD({0}) = 1, + false = 0, true =1 + IEEE real format, + null terminated strings, + compact numbers according to M.Odersky *) + + + CONST + nofbufs = 4; + bufsize = 4096; + fileTabSize = 64; + noDesc = -1; + notDone = -1; + + (* file states *) + open = 0; create = 1; close = 2; + + + TYPE + FileName = ARRAY 101 OF CHAR; + File* = POINTER TO Handle; + Buffer = POINTER TO BufDesc; + + Handle = RECORD + workName, registerName: FileName; + tempFile: BOOLEAN; + dev, ino, mtime: LONGINT; + fd-, len, pos: LONGINT; + bufs: ARRAY nofbufs OF Buffer; + swapper, state: INTEGER + END ; + + BufDesc = RECORD + f: File; + chg: BOOLEAN; + org, size: LONGINT; + data: ARRAY bufsize OF SYSTEM.BYTE + END ; + + Rider* = RECORD + res*: LONGINT; + eof*: BOOLEAN; + buf: Buffer; + org, offset: LONGINT + END ; + + Time = POINTER TO TimeDesc; + TimeDesc = RECORD + sec*, min*, hour*, mday*, mon*, year*, wday*, isdst*, zone*, gmtoff*: LONGINT; +(* sec*, min*, hour*, mday*, mon*, year*, wday*, isdst*, zone*, gmtoff*: INTEGER;*) + END ; + + VAR + fileTab: ARRAY fileTabSize OF LONGINT (*=File*); + tempno: INTEGER; + +(* for localtime *) + PROCEDURE -includetime() + '#include "time.h"'; + + PROCEDURE -localtime(VAR clock: LONGINT): Time + "(OakFiles_Time) localtime(clock)"; + + PROCEDURE -getcwd(VAR cwd: Unix.Name) + "getcwd(cwd, cwd__len)"; + + PROCEDURE -IdxTrap "__HALT(-1)"; + + PROCEDURE^ Finalize(o: SYSTEM.PTR); + + PROCEDURE Err(s: ARRAY OF CHAR; f: File; errno: LONGINT); + BEGIN + Console.Ln; Console.String("-- "); Console.String(s); Console.String(": "); + IF f # NIL THEN + IF f.registerName # "" THEN Console.String(f.registerName) ELSE Console.String(f.workName) END + END ; + IF errno # 0 THEN Console.String(" errno = "); Console.Int(errno, 1) END ; + Console.Ln; + HALT(99) + END Err; + + PROCEDURE MakeFileName(dir, name: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR); + VAR i, j: INTEGER; + BEGIN i := 0; j := 0; + WHILE dir[i] # 0X DO dest[i] := dir[i]; INC(i) END ; + IF dest[i-1] # "/" THEN dest[i] := "/"; INC(i) END ; + WHILE name[j] # 0X DO dest[i] := name[j]; INC(i); INC(j) END ; + dest[i] := 0X + END MakeFileName; + + PROCEDURE GetTempName(finalName: ARRAY OF CHAR; VAR name: ARRAY OF CHAR); + VAR n, i, j: LONGINT; + BEGIN + INC(tempno); n := tempno; i := 0; + IF finalName[0] # "/" THEN (* relative pathname *) + WHILE Kernel.CWD[i] # 0X DO name[i] := Kernel.CWD[i]; INC(i) END; + IF Kernel.CWD[i-1] # "/" THEN name[i] := "/"; INC(i) END + END; + j := 0; + WHILE finalName[j] # 0X DO name[i] := finalName[j]; INC(i); INC(j) END; + DEC(i); + WHILE name[i] # "/" DO DEC(i) END; + name[i+1] := "."; name[i+2] := "t"; name[i+3] := "m"; name[i+4] := "p"; name[i+5] := "."; INC(i, 6); + WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END; + name[i] := "."; INC(i); n := SHORT(Unix.Getpid()); + WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END; + name[i] := 0X + END GetTempName; + + PROCEDURE Create(f: File); + VAR stat: Unix.Status; done: BOOLEAN; + errno: LONGINT; err: ARRAY 32 OF CHAR; + BEGIN + IF f.fd = noDesc THEN + IF f.state = create THEN GetTempName(f.registerName, f.workName); f.tempFile := TRUE + ELSIF f.state = close THEN + f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE + END ; + errno := Unix.Unlink(f.workName); (*unlink first to avoid stale NFS handles and to avoid reuse of inodes*) + f.fd := Unix.Open(f.workName, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8}); + done := f.fd >= 0; errno := Unix.errno(); + IF (~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE))) OR (done & (f.fd >= fileTabSize)) THEN + IF done & (f.fd >= fileTabSize) THEN errno := Unix.Close(f.fd) END ; + Kernel.GC(TRUE); + f.fd := Unix.Open(f.workName, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8}); + done := f.fd >= 0 + END ; + IF done THEN + IF f.fd >= fileTabSize THEN errno := Unix.Close(f.fd); Err("too many files open", f, 0) + ELSE fileTab[f.fd] := SYSTEM.VAL(LONGINT, f); INC(Kernel.nofiles); Kernel.RegisterObject(f, Finalize); + f.state := open; f.pos := 0; errno := Unix.Fstat(f.fd, stat); + f.dev := stat.dev; f.ino := stat.ino; f.mtime := stat.mtime + END + ELSE errno := Unix.errno(); + IF errno = Unix.ENOENT THEN err := "no such directory" + ELSIF (errno = Unix.ENFILE) OR (errno = Unix.EMFILE) THEN err := "too many files open" + ELSE err := "file not created" + END ; + Err(err, f, errno) + END + END + END Create; + + PROCEDURE Flush(buf: Buffer); + VAR res: LONGINT; f: File; stat: Unix.Status; + BEGIN + IF buf.chg THEN f := buf.f; Create(f); + IF buf.org # f.pos THEN res := Unix.Lseek(f.fd, buf.org, 0) END ; + res := Unix.Write(f.fd, SYSTEM.ADR(buf.data), buf.size); + IF res < 0 THEN Err("error in writing file", f, Unix.errno()) END ; + f.pos := buf.org + buf.size; + buf.chg := FALSE; + res := Unix.Fstat(f.fd, stat); + f.mtime := stat.mtime + END + END Flush; + + PROCEDURE Close* (f: File); + VAR i, res: LONGINT; + BEGIN + IF (f.state # create) OR (f.registerName # "") THEN + Create(f); i := 0; + WHILE (i < nofbufs) & (f.bufs[i] # NIL) DO Flush(f.bufs[i]); INC(i) END ; + res := Unix.Fsync(f.fd); + IF res < 0 THEN Err("error in writing file", f, Unix.errno()) END + END + END Close; + + PROCEDURE Length* (f: File): LONGINT; + BEGIN RETURN f.len + END Length; + + PROCEDURE New* (name: ARRAY OF CHAR): File; + VAR f: File; + BEGIN + NEW(f); f.workName := ""; COPY(name, f.registerName); + f.fd := noDesc; f.state := create; f.len := 0; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*) + RETURN f + END New; +(* + PROCEDURE ScanPath(VAR pos: INTEGER; VAR dir: ARRAY OF CHAR); (* supports ~, ~user and blanks inside path *) + VAR i: INTEGER; ch: CHAR; home: ARRAY 256 OF CHAR; + BEGIN + i := 0; ch := Kernel.OBERON[pos]; + WHILE (ch = " ") OR (ch = ":") DO INC(pos); ch := Kernel.OBERON[pos] END ; + IF ch = "~" THEN + INC(pos); ch := Kernel.OBERON[pos]; + home := ""; Args.GetEnv("HOME", home); + WHILE home[i] # 0X DO dir[i] := home[i]; INC(i) END ; + IF (ch # "/") & (ch # 0X) & (ch # ":") & (ch # " ") THEN + WHILE (i > 0) & (dir[i-1] # "/") DO DEC(i) END + END + END ; + WHILE (ch # 0X) & (ch # ":") DO dir[i] := ch; INC(i); INC(pos); ch := Kernel.OBERON[pos] END ; + WHILE (i > 0) & (dir[i-1] = " ") DO DEC(i) END ; + dir[i] := 0X + END ScanPath; +*) + PROCEDURE HasDir(VAR name: ARRAY OF CHAR): BOOLEAN; + VAR i: INTEGER; ch: CHAR; + BEGIN i := 0; ch := name[0]; + WHILE (ch # 0X) & (ch # "/") DO INC(i); ch := name[i] END ; + RETURN ch = "/" + END HasDir; + + PROCEDURE CacheEntry(dev, ino: LONGINT; mtime: LONGINT): File; + VAR f: File; i: INTEGER; stat: Unix.Status; res: LONGINT; + BEGIN i := 0; + WHILE i < fileTabSize DO + f := SYSTEM.VAL(File, fileTab[i]); + IF (f # NIL) & (ino = f.ino) & (dev = f.dev) THEN + IF mtime # f.mtime THEN i := 0; + WHILE i < nofbufs DO + IF f.bufs[i] # NIL THEN f.bufs[i].org := -1; f.bufs[i] := NIL END ; + INC(i) + END ; + f.swapper := -1; f.mtime := mtime; + res := Unix.Fstat(f.fd, stat); f.len := stat.size + END ; + RETURN f + END ; + INC(i) + END ; + RETURN NIL + END CacheEntry; + + PROCEDURE Old* (name: ARRAY OF CHAR): File; + VAR f: File; fd, res, errno: LONGINT; pos: INTEGER; done: BOOLEAN; + dir, path: ARRAY 256 OF CHAR; + stat: Unix.Status; + BEGIN + IF name # "" THEN + IF HasDir(name) THEN dir := ""; COPY(name, path) + ELSE pos := 0; (*ScanPath(pos, dir);*) MakeFileName(dir, name, path); (*ScanPath(pos, dir)*) + END ; + LOOP + fd := Unix.Open(path, Unix.rdwr, {}); done := fd >= 0; errno := Unix.errno(); + IF (~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE))) OR (done & (fd >= fileTabSize)) THEN + IF done & (fd >= fileTabSize) THEN res := Unix.Close(fd) END ; + Kernel.GC(TRUE); + fd := Unix.Open(path, Unix.rdwr, {}); + done := fd >= 0; errno := Unix.errno(); + IF ~done & ((errno = Unix.ENFILE) OR (errno = Unix.EMFILE)) THEN Err("too many files open", f, errno) END + END ; + IF ~done & ((errno = Unix.EACCES) OR (errno = Unix.EROFS) OR (errno = Unix.EAGAIN)) THEN + (* errno EAGAIN observed on Solaris 2.4 *) + fd := Unix.Open(path, Unix.rdonly, {}); done := fd >= 0; errno := Unix.errno() + END ; +IF (~done) & (errno # Unix.ENOENT) THEN + Console.String("warning Files.Old "); Console.String(name); + Console.String(" errno = "); Console.Int(errno, 0); Console.Ln; +END ; + IF done THEN + res := Unix.Fstat(fd, stat); + f := CacheEntry(stat.dev, stat.ino, stat.mtime); + IF f # NIL THEN res := Unix.Close(fd); RETURN f + ELSIF fd >= fileTabSize THEN res := Unix.Close(fd); Err("too many files open", f, 0) + ELSE NEW(f); fileTab[fd] := SYSTEM.VAL(LONGINT, f); INC(Kernel.nofiles); Kernel.RegisterObject(f, Finalize); + f.fd := fd; f.state := open; f.len := stat.size; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*) + COPY(name, f.workName); f.registerName := ""; f.tempFile := FALSE; + f.dev := stat.dev; f.ino := stat.ino; f.mtime := stat.mtime; + RETURN f + END + ELSIF dir = "" THEN RETURN NIL + ELSE MakeFileName(dir, name, path); (*ScanPath(pos, dir)*) + END + END + ELSE RETURN NIL + END + END Old; + + PROCEDURE Purge* (f: File); + VAR i: INTEGER; stat: Unix.Status; res: LONGINT; + BEGIN i := 0; + WHILE i < nofbufs DO + IF f.bufs[i] # NIL THEN f.bufs[i].org := -1; f.bufs[i] := NIL END ; + INC(i) + END ; + IF f.fd # noDesc THEN res := Unix.Ftruncate(f.fd, 0); res := Unix.Lseek(f.fd, 0, 0) END ; + f.pos := 0; f.len := 0; f.swapper := -1; + res := Unix.Fstat(f.fd, stat); f.mtime := stat.mtime + END Purge; + + PROCEDURE GetDate* (f: File; VAR t, d: LONGINT); + VAR stat: Unix.Status; clock, res: LONGINT; time: Time; + BEGIN + Create(f); res := Unix.Fstat(f.fd, stat); + time := localtime(stat.mtime); + t := time.sec + ASH(time.min, 6) + ASH(time.hour, 12); + d := time.mday + ASH(time.mon+1, 5) + ASH(time.year MOD 100, 9) + END GetDate; + + PROCEDURE Pos* (VAR r: Rider): LONGINT; + BEGIN RETURN r.org + r.offset + END Pos; + + PROCEDURE Set* (VAR r: Rider; f: File; pos: LONGINT); + VAR org, offset, i, n, res: LONGINT; buf: Buffer; + BEGIN + IF f # NIL THEN + IF pos > f.len THEN pos := f.len ELSIF pos < 0 THEN pos := 0 END ; + offset := pos MOD bufsize; org := pos - offset; i := 0; + WHILE (i < nofbufs) & (f.bufs[i] # NIL) & (org # f.bufs[i].org) DO INC(i) END ; + IF i < nofbufs THEN + IF f.bufs[i] = NIL THEN NEW(buf); buf.chg := FALSE; buf.org := -1; buf.f := f; f.bufs[i] := buf + ELSE buf := f.bufs[i] + END + ELSE + f.swapper := (f.swapper + 1) MOD nofbufs; + buf := f.bufs[f.swapper]; + Flush(buf) + END ; + IF buf.org # org THEN + IF org = f.len THEN buf.size := 0 + ELSE Create(f); + IF f.pos # org THEN res := Unix.Lseek(f.fd, org, 0) END ; + n := Unix.ReadBlk(f.fd, buf.data); + IF n < 0 THEN Err("read from file not done", f, Unix.errno()) END ; + f.pos := org + n; + buf.size := n + END ; + buf.org := org; buf.chg := FALSE + END + ELSE buf := NIL; org := 0; offset := 0 + END ; + r.buf := buf; r.org := org; r.offset := offset; r.eof := FALSE; r.res := 0 + END Set; + + PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE); + VAR offset: LONGINT; buf: Buffer; + BEGIN + buf := r.buf; offset := r.offset; + IF r.org # buf.org THEN Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset END ; + IF (offset < buf.size) THEN + x := buf.data[offset]; r.offset := offset + 1 + ELSIF r.org + offset < buf.f.len THEN + Set(r, r.buf.f, r.org + offset); + x := r.buf.data[0]; r.offset := 1 + ELSE + x := 0X; r.eof := TRUE + END + END Read; + + PROCEDURE ReadBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT); + VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer; + BEGIN + IF n > LEN(x) THEN IdxTrap END ; + xpos := 0; buf := r.buf; offset := r.offset; + WHILE n > 0 DO + IF (r.org # buf.org) OR (offset >= bufsize) THEN + Set(r, buf.f, r.org + offset); + buf := r.buf; offset := r.offset + END ; + restInBuf := buf.size - offset; + IF restInBuf = 0 THEN r.res := n; r.eof := TRUE; RETURN + ELSIF n > restInBuf THEN min := restInBuf ELSE min := n END ; + SYSTEM.MOVE(SYSTEM.ADR(buf.data) + offset, SYSTEM.ADR(x) + xpos, min); + INC(offset, min); r.offset := offset; INC(xpos, min); DEC(n, min) + END ; + r.res := 0; r.eof := FALSE + END ReadBytes; + + PROCEDURE Base* (VAR r: Rider): File; + BEGIN RETURN r.buf.f + END Base; + + PROCEDURE Write* (VAR r: Rider; x: SYSTEM.BYTE); + VAR buf: Buffer; offset: LONGINT; + BEGIN + buf := r.buf; offset := r.offset; + IF (r.org # buf.org) OR (offset >= bufsize) THEN + Set(r, buf.f, r.org + offset); + buf := r.buf; offset := r.offset + END ; + buf.data[offset] := x; + buf.chg := TRUE; + IF offset = buf.size THEN + INC(buf.size); INC(buf.f.len) + END ; + r.offset := offset + 1; r.res := 0 + END Write; + + PROCEDURE WriteBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT); + VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer; + BEGIN + IF n > LEN(x) THEN IdxTrap END ; + xpos := 0; buf := r.buf; offset := r.offset; + WHILE n > 0 DO + IF (r.org # buf.org) OR (offset >= bufsize) THEN + Set(r, buf.f, r.org + offset); + buf := r.buf; offset := r.offset + END ; + restInBuf := bufsize - offset; + IF n > restInBuf THEN min := restInBuf ELSE min := n END ; + SYSTEM.MOVE(SYSTEM.ADR(x) + xpos, SYSTEM.ADR(buf.data) + offset, min); + INC(offset, min); r.offset := offset; + IF offset > buf.size THEN INC(buf.f.len, offset - buf.size); buf.size := offset END ; + INC(xpos, min); DEC(n, min); buf.chg := TRUE + END ; + r.res := 0 + END WriteBytes; + +(* another solution would be one that is similar to ReadBytes, WriteBytes. +No code duplication, more symmetric, only two ifs for +Read and Write in buffer, buf.size replaced by bufsize in Write ops, buf.size and len +must be made consistent with offset (if offset > buf.size) in a lazy way. + +PROCEDURE Write* (VAR r: Rider; x: SYSTEM.BYTE); + VAR buf: Buffer; offset: LONGINT; +BEGIN + buf := r.buf; offset := r.offset; + IF (offset >= bufsize) OR (r.org # buf.org) THEN + Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset; + END ; + buf.data[offset] := x; r.offset := offset + 1; buf.chg := TRUE +END Write; + +PROCEDURE WriteBytes ... + +PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE); + VAR offset: LONGINT; buf: Buffer; +BEGIN + buf := r.buf; offset := r.offset; + IF (offset >= buf.size) OR (r.org # buf.org) THEN + IF r.org + offset >= buf.f.len THEN x := 0X; r.eof := TRUE; RETURN + ELSE Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset + END + END ; + x := buf.data[offset]; r.offset := offset + 1 +END Read; + +but this would also affect Set, Length, and Flush. +Especially Length would become fairly complex. +*) + + PROCEDURE Delete* (name: ARRAY OF CHAR; VAR res: INTEGER); + BEGIN + res := SHORT(Unix.Unlink(name)); + res := SHORT(Unix.errno()) + END Delete; + + PROCEDURE Rename* (old, new: ARRAY OF CHAR; VAR res: INTEGER); + VAR fdold, fdnew, n, errno, r: LONGINT; + ostat, nstat: Unix.Status; + buf: ARRAY 4096 OF CHAR; + BEGIN + r := Unix.Stat(old, ostat); + IF r >= 0 THEN + r := Unix.Stat(new, nstat); + IF (r >= 0) & ((ostat.dev # nstat.dev) OR (ostat.ino # nstat.ino)) THEN + Delete(new, res); (* work around stale nfs handles *) + END ; + r := Unix.Rename(old, new); + IF r < 0 THEN res := SHORT(Unix.errno()); + IF res = Unix.EXDEV THEN (* cross device link, move the file *) + fdold := Unix.Open(old, Unix.rdonly, {}); + IF fdold < 0 THEN res := 2; RETURN END ; + fdnew := Unix.Open(new, Unix.rdwr + Unix.creat + Unix.trunc, {2, 4,5, 7,8}); + IF fdnew < 0 THEN r := Unix.Close(fdold); res := 3; RETURN END ; + n := Unix.Read(fdold, SYSTEM.ADR(buf), bufsize); + WHILE n > 0 DO + r := Unix.Write(fdnew, SYSTEM.ADR(buf), n); + IF r < 0 THEN errno := Unix.errno(); r := Unix.Close(fdold); r := Unix.Close(fdnew); + Err("cannot move file", NIL, errno) + END ; + n := Unix.Read(fdold, SYSTEM.ADR(buf), bufsize) + END ; + errno := Unix.errno(); + r := Unix.Close(fdold); r := Unix.Close(fdnew); + IF n = 0 THEN r := Unix.Unlink(old); res := 0 + ELSE Err("cannot move file", NIL, errno) + END ; + ELSE RETURN (* res is Unix.Rename return code *) + END + END ; + res := 0 + ELSE res := 2 (* old file not found *) + END + END Rename; + + PROCEDURE Register* (f: File); + VAR idx, errno: INTEGER; f1: File; file: ARRAY 104 OF CHAR; + BEGIN + IF (f.state = create) & (f.registerName # "") THEN f.state := close (* shortcut renaming *) END ; + Close(f); + IF f.registerName # "" THEN + Rename(f.workName, f.registerName, errno); + IF errno # 0 THEN COPY(f.registerName, file); HALT(99) END ; + f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE + END + END Register; + + PROCEDURE ChangeDirectory*(path: ARRAY OF CHAR; VAR res: INTEGER); + BEGIN + res := SHORT(Unix.Chdir(path)); + getcwd(Kernel.CWD) + END ChangeDirectory; + + PROCEDURE FlipBytes(VAR src, dest: ARRAY OF SYSTEM.BYTE); + VAR i, j: LONGINT; + BEGIN + IF ~Kernel.littleEndian THEN i := LEN(src); j := 0; + WHILE i > 0 DO DEC(i); dest[j] := src[i]; INC(j) END + ELSE SYSTEM.MOVE(SYSTEM.ADR(src), SYSTEM.ADR(dest), LEN(src)) + END + END FlipBytes; + + PROCEDURE ReadBool* (VAR R: Rider; VAR x: BOOLEAN); + BEGIN Read(R, SYSTEM.VAL(CHAR, x)) + END ReadBool; + + PROCEDURE ReadInt* (VAR R: Rider; VAR x: INTEGER); + VAR b: ARRAY 2 OF CHAR; + BEGIN ReadBytes(R, b, 2); + x := ORD(b[0]) + ORD(b[1])*256 + END ReadInt; + + PROCEDURE ReadLInt* (VAR R: Rider; VAR x: LONGINT); + VAR b: ARRAY 4 OF CHAR; + BEGIN ReadBytes(R, b, 4); + x := ORD(b[0]) + ORD(b[1])*100H + ORD(b[2])*10000H + ORD(b[3])*1000000H + END ReadLInt; + + PROCEDURE ReadSet* (VAR R: Rider; VAR x: SET); + VAR b: ARRAY 4 OF CHAR; + BEGIN ReadBytes(R, b, 4); + x := SYSTEM.VAL(SET, ORD(b[0]) + ORD(b[1])*100H + ORD(b[2])*10000H + ORD(b[3])*1000000H) + END ReadSet; + + PROCEDURE ReadReal* (VAR R: Rider; VAR x: REAL); + VAR b: ARRAY 4 OF CHAR; + BEGIN ReadBytes(R, b, 4); FlipBytes(b, x) + END ReadReal; + + PROCEDURE ReadLReal* (VAR R: Rider; VAR x: LONGREAL); + VAR b: ARRAY 8 OF CHAR; + BEGIN ReadBytes(R, b, 8); FlipBytes(b, x) + END ReadLReal; + + PROCEDURE ReadString* (VAR R: Rider; VAR x: ARRAY OF CHAR); + VAR i: INTEGER; ch: CHAR; + BEGIN i := 0; + REPEAT Read(R, ch); x[i] := ch; INC(i) UNTIL ch = 0X + END ReadString; + + (* need to read line; -- noch *) + PROCEDURE ReadLine* (VAR R: Rider; VAR x: ARRAY OF CHAR); + VAR i: INTEGER; ch: CHAR; b : BOOLEAN; + BEGIN i := 0; + b := FALSE; + REPEAT + Read(R, ch); + IF ((ch = 0X) OR (ch = 0AX) OR (ch = 0DX)) THEN + b := TRUE + ELSE + x[i] := ch; + INC(i); + END; + UNTIL b + END ReadLine; + + PROCEDURE ReadNum* (VAR R: Rider; VAR x: LONGINT); + VAR s: SHORTINT; ch: CHAR; n: LONGINT; + BEGIN s := 0; n := 0; Read(R, ch); + WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); Read(R, ch) END; + INC(n, ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s) ); + x := n + END ReadNum; + + PROCEDURE WriteBool* (VAR R: Rider; x: BOOLEAN); + BEGIN Write(R, SYSTEM.VAL(CHAR, x)) + END WriteBool; + + PROCEDURE WriteInt* (VAR R: Rider; x: INTEGER); + VAR b: ARRAY 2 OF CHAR; + BEGIN b[0] := CHR(x); b[1] := CHR(x DIV 256); + WriteBytes(R, b, 2); + END WriteInt; + + PROCEDURE WriteLInt* (VAR R: Rider; x: LONGINT); + VAR b: ARRAY 4 OF CHAR; + BEGIN + b[0] := CHR(x); b[1] := CHR(x DIV 100H); b[2] := CHR(x DIV 10000H); b[3] := CHR(x DIV 1000000H); + WriteBytes(R, b, 4); + END WriteLInt; + + PROCEDURE WriteSet* (VAR R: Rider; x: SET); + VAR b: ARRAY 4 OF CHAR; i: LONGINT; + BEGIN i := SYSTEM.VAL(LONGINT, x); + b[0] := CHR(i); b[1] := CHR(i DIV 100H); b[2] := CHR(i DIV 10000H); b[3] := CHR(i DIV 1000000H); + WriteBytes(R, b, 4); + END WriteSet; + + PROCEDURE WriteReal* (VAR R: Rider; x: REAL); + VAR b: ARRAY 4 OF CHAR; + BEGIN FlipBytes(x, b); WriteBytes(R, b, 4) + END WriteReal; + + PROCEDURE WriteLReal* (VAR R: Rider; x: LONGREAL); + VAR b: ARRAY 8 OF CHAR; + BEGIN FlipBytes(x, b); WriteBytes(R, b, 8) + END WriteLReal; + + PROCEDURE WriteString* (VAR R: Rider; x: ARRAY [1] OF CHAR); + VAR i: INTEGER; + BEGIN i := 0; + WHILE x[i] # 0X DO INC(i) END ; + WriteBytes(R, x, i+1) + END WriteString; + + PROCEDURE WriteNum* (VAR R: Rider; x: LONGINT); + BEGIN + WHILE (x < - 64) OR (x > 63) DO Write(R, CHR(x MOD 128 + 128)); x := x DIV 128 END; + Write(R, CHR(x MOD 128)) + END WriteNum; + + PROCEDURE Finalize(o: SYSTEM.PTR); + VAR f: File; res: LONGINT; + BEGIN + f := SYSTEM.VAL(File, o); + IF f.fd >= 0 THEN + fileTab[f.fd] := 0; res := Unix.Close(f.fd); f.fd := -1; DEC(Kernel.nofiles); + IF f.tempFile THEN res := Unix.Unlink(f.workName) END + END + END Finalize; + + PROCEDURE Init; + VAR i: LONGINT; + BEGIN + i := 0; WHILE i < fileTabSize DO fileTab[i] := 0; INC(i) END ; + tempno := -1; Kernel.nofiles := 0 + END Init; + +BEGIN Init +END OakFiles. diff --git a/voc b/voc index eb7855c3..23db325f 100755 Binary files a/voc and b/voc differ diff --git a/vocstatic b/vocstatic index eb7855c3..23db325f 100755 Binary files a/vocstatic and b/vocstatic differ diff --git a/vocstatic.linux.gnuc.x86_64 b/vocstatic.linux.gnuc.x86_64 index eb7855c3..23db325f 100755 Binary files a/vocstatic.linux.gnuc.x86_64 and b/vocstatic.linux.gnuc.x86_64 differ