From d8d1c29e6f646431d9a6fa78621586ba56c8cfd2 Mon Sep 17 00:00:00 2001 From: Norayr Chilingarian Date: Mon, 21 Oct 2013 19:53:26 +0400 Subject: [PATCH] added OakFiles.Mod which does not search for files in OBERON path, implemented ReadLine procedure. added oocRts wrapper around Unix.Mod and Args.Mod,added Filenames.Mod. Unix.Mod and Args.Mod modified, interface extended. Former-commit-id: 8f34e77d9d77f165231b1ef8c32b5f99cb71d30b --- makefile | 4 +- makefile.gnuc.armv6j | 4 +- makefile.gnuc.armv6j_hardfp | 6 +- makefile.gnuc.armv7a_hardfp | 6 +- makefile.gnuc.x86 | 4 +- makefile.gnuc.x86_64 | 4 +- ocat | Bin 208830 -> 209462 bytes showdef.REMOVED.git-id | 2 +- src/lib/ooc/oocFilenames.Mod | 187 ++++++ src/lib/ooc/oocRts.Mod | 78 +++ src/lib/system/gnuc/armv6j/Args.Mod | 12 + src/lib/system/gnuc/armv6j/Unix.Mod | 7 +- src/lib/system/gnuc/armv6j_hardfp/Args.Mod | 12 + src/lib/system/gnuc/armv6j_hardfp/Unix.Mod | 7 +- src/lib/system/gnuc/armv7a_hardfp/Args.Mod | 12 + src/lib/system/gnuc/armv7a_hardfp/Unix.Mod | 7 +- src/lib/system/gnuc/x86/Args.Mod | 12 + src/lib/system/gnuc/x86/Unix.Mod | 7 +- src/lib/system/gnuc/x86_64/Args.Mod | 12 + src/lib/system/gnuc/x86_64/Unix.Mod | 9 + src/lib/v4/OakFiles.Mod | 643 +++++++++++++++++++++ voc.REMOVED.git-id | 2 +- vocstatic.REMOVED.git-id | 2 +- vocstatic.linux.gnuc.x86_64.REMOVED.git-id | 2 +- 24 files changed, 1025 insertions(+), 16 deletions(-) create mode 100644 src/lib/ooc/oocFilenames.Mod create mode 100644 src/lib/ooc/oocRts.Mod create mode 100644 src/lib/v4/OakFiles.Mod 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 85a685c8355116947bc3f1c3b46909ec868304ca..07389ef150433aafb465788a129ecff581332014 100755 GIT binary patch delta 43937 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 z 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 L24|)_6Wsp*TR`sK delta 43267 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%0ABmbCDPYu-oXe%(WR)Vz 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 b!K82hzJZ!<))(yqvwB+= 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.REMOVED.git-id b/voc.REMOVED.git-id index a494cc2b..f50622c1 100644 --- a/voc.REMOVED.git-id +++ b/voc.REMOVED.git-id @@ -1 +1 @@ -eb7855c3da28b25bac66fa2b1632c6523dc6b801 \ No newline at end of file +23db325f4c239f0f35dbb541886b717260d6be01 \ No newline at end of file diff --git a/vocstatic.REMOVED.git-id b/vocstatic.REMOVED.git-id index a494cc2b..f50622c1 100644 --- a/vocstatic.REMOVED.git-id +++ b/vocstatic.REMOVED.git-id @@ -1 +1 @@ -eb7855c3da28b25bac66fa2b1632c6523dc6b801 \ No newline at end of file +23db325f4c239f0f35dbb541886b717260d6be01 \ No newline at end of file diff --git a/vocstatic.linux.gnuc.x86_64.REMOVED.git-id b/vocstatic.linux.gnuc.x86_64.REMOVED.git-id index a494cc2b..f50622c1 100644 --- a/vocstatic.linux.gnuc.x86_64.REMOVED.git-id +++ b/vocstatic.linux.gnuc.x86_64.REMOVED.git-id @@ -1 +1 @@ -eb7855c3da28b25bac66fa2b1632c6523dc6b801 \ No newline at end of file +23db325f4c239f0f35dbb541886b717260d6be01 \ No newline at end of file