Przeglądaj źródła

UnixOberon and WinOberon now decouple the StdIO with the help of a thread that continuously reads the stdIO and provides a normal oberon stream to the rest of the system.
This allows the use of getAvailable and peek for the rest of the system.
WinOberon version not tested yet

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7100 8c9fc860-2736-0410-a75d-ab315db34111

skoster 8 lat temu
rodzic
commit
29555a257d
5 zmienionych plików z 64 dodań i 17 usunięć
  1. 40 0
      source/Pipes.Mod
  2. 2 7
      source/Shell.Mod
  3. 12 5
      source/StdIOShell.Mod
  4. 5 3
      source/Unix.StdIO.Mod
  5. 5 2
      source/Win32.StdIO.Mod

+ 40 - 0
source/Pipes.Mod

@@ -71,6 +71,44 @@ TYPE
 
 	END Pipe;
 
+
+(** Any stream input procedure or method. Identical to the definition in Streams.Mod, but I don't want to import that here*)
+TYPE	Receiver* = PROCEDURE {DELEGATE} ( VAR buf: ARRAY OF CHAR;  ofs, size, min: LONGINT;  VAR len, res: LONGINT );
+(*makes a decoupled copy of a receiver*)
+(*internally it's a pipe that automatically reads the input in a continuous loop*)
+TYPE ReadDecoupler*= OBJECT
+	VAR
+		pipe: Pipe;
+		inputReceiver: Receiver;
+		numR: LONGINT;
+		smallbuf: ARRAY[128] OF CHAR;
+		len,res: LONGINT;
+
+	PROCEDURE &InitReadDecoupler*(inputReceiver: Receiver);
+	BEGIN
+		NEW(pipe,128);
+		SELF.inputReceiver:=inputReceiver;
+	END InitReadDecoupler;
+	
+	PROCEDURE Receive*(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
+	BEGIN
+		pipe.Receive(buf,ofs,size,min,len,res);
+	END Receive;
+	
+BEGIN{ACTIVE}
+		
+		LOOP
+			(*todo: check res, if inputReceiver throws anything but 'OK' exit the loop*)
+			inputReceiver(smallbuf, 0, 128, 1, len,res); (*read at least 1 byte into the small buffer*)
+			pipe.Send(smallbuf, 0, len, FALSE,  res);   (*feed the amount read (usually 1 entire line) into the pipe to cross threads*)
+		END;
+END ReadDecoupler;
+
+
+
+
+
+
 END Pipes.
 
 (*
@@ -145,3 +183,5 @@ END Pipes.
 
 
 *)
+
+

+ 2 - 7
source/Shell.Mod

@@ -219,16 +219,12 @@ TYPE
 					IF IsControlCharacter(ch) OR (ch = Delete) THEN
 
 						IF (ch = CR) OR (ch = LF) OR (ch = Streams.EOT) OR (context.in.res # Streams.Ok) THEN
-							
-							(* skip redundant CR and LF to avoid generation of empty commands *)
+							(* skip redundant CR and LF to avoid generation of empty commands. This requires peek functionality which doesn't work on the Input stream from an underlying OS, so a decoupler is needed that transforms that into an oberon stream*)
 							WHILE (context.in.res = Streams.Ok) & (context.in.Available() # 0) & ((context.in.Peek() = CR) OR (context.in.Peek() = LF)) DO
 								context.in.SkipBytes(1);
 							END;
-							
 							ch := LF;
-
 							EXIT
-
 						ELSIF (ch = Backspace) OR (ch = Delete)THEN
 							IF currentIndex >= 0 THEN (* There is a character at the left of the cursor *)
 								command[currentIndex] := 0X;
@@ -262,7 +258,6 @@ TYPE
 					(* ignore non-ascii characters *)
 				END;
 			END;
-
 			command[currentIndex+1] := 0X;
 
 			IF (ch = LF) (*OR (ch =CR)*)  THEN
@@ -669,4 +664,4 @@ END Shell.
 
 SystemTools.Free Shell ~
 
-WMShell.Open ~
+WMShell.Open ~

+ 12 - 5
source/StdIOShell.Mod

@@ -1,6 +1,6 @@
 MODULE StdIOShell; (** AUTHOR ""; PURPOSE ""; *)
 
-IMPORT StdIO, Commands, Streams, Modules, Objects, Shell;
+IMPORT StdIO, Commands, Modules, Streams, Pipes, Strings;
 
 PROCEDURE Activate(context: Commands.Context; CONST cmd: ARRAY OF CHAR): BOOLEAN;
 VAR msg: ARRAY 256 OF CHAR;  res: LONGINT; 
@@ -11,7 +11,7 @@ BEGIN
 END Activate;
 
 PROCEDURE Execute(context: Commands.Context);
-VAR str, msg: ARRAY 256 OF CHAR;  res: LONGINT; shell: Shell.Shell; b: BOOLEAN;
+VAR str: ARRAY 256 OF CHAR;  b: BOOLEAN;
 BEGIN
 	IF ~context.arg.GetString(str) THEN  
 		context.out.String("Critical error: no arg"); 
@@ -33,8 +33,15 @@ END Execute;
 
 (* do not add commands here -- the module loader does not finish here and they will not become available *)
 
-BEGIN
+VAR
+	env: Commands.Context;
+	str: Strings.String;
+	decoupler: Pipes.ReadDecoupler;
+	inDecoupled: Streams.Receiver;
+	inStreamDecoupled: Streams.Reader;
+BEGIN	
 	Execute(StdIO.env);
+	TRACE('shell died');
 	Modules.Shutdown(Modules.PowerDown);
 	LOOP END;
 END StdIOShell.
@@ -146,13 +153,13 @@ SystemTools.DoCommands
 		Options Locks Debugging
 		StaticLinker 
 		FoxBasic  FoxProgTools  FoxScanner FoxSyntaxTree FoxGlobal
-		FoxActiveCells FoxHardware FoxFormats FoxPrintout
+		FoxActiveCells FoxHardware FoxFormats FoxFingerPrinter  FoxPrintout
 		FoxParser  FoxSemanticChecker
 		FoxBackend FoxSections 
 		
 		FoxFrontend
 		Compiler  FoxOberonFrontend 
-		FoxFingerPrinter FoxInterfaceComparison FoxTextualSymbolFile FoxBinarySymbolFile
+		FoxInterfaceComparison FoxTextualSymbolFile FoxBinarySymbolFile
 		
 		FoxBinaryCode FoxIntermediateCode FoxIntermediateBackend FoxCodeGenerators
 		FoxBinaryObjectFile FoxGenericObjectFile

+ 5 - 3
source/Unix.StdIO.Mod

@@ -2,7 +2,7 @@ MODULE StdIO;	(** AUTHOR gf;  PURPOSE "Unix standard IO and argument channels *)
 
 (* Commands.Context for programs running outside Aos *)
 
-IMPORT S := SYSTEM, Modules, Commands, Streams, Unix;
+IMPORT S := SYSTEM, Modules, Commands, Streams,Pipes , Unix;
 
 CONST 
 	AddrSize = SIZEOF( ADDRESS );
@@ -10,7 +10,8 @@ TYPE
 	String=POINTER TO ARRAY OF CHAR;
 VAR 
 	env-: Commands.Context;
-
+	stdInDecoupler: Pipes.ReadDecoupler;
+	
 PROCEDURE Args(): String;
 VAR size, pos: SIZE; i,j: LONGINT; str: String;
 	argc: LONGINT;
@@ -94,7 +95,8 @@ VAR
 BEGIN
 	str := Args();
 	NEW( arg, LEN(str) ); arg.Set(str^);
-	NEW( stdin, ReceiveStdin, 1024 );
+	NEW(stdInDecoupler, ReceiveStdin);
+	NEW( stdin, stdInDecoupler.Receive, 1024 );
 	NEW( stdout, SendStdout, 1024 );
 	NEW( errout, SendErrout, 512 );
 	NEW( env, stdin, arg, stdout, errout, NIL );

+ 5 - 2
source/Win32.StdIO.Mod

@@ -2,7 +2,7 @@ MODULE StdIO;	(** AUTHOR gf;  PURPOSE "Unix standard IO and argument channels *)
 
 (* Commands.Context for programs running outside Aos *)
 
-IMPORT S := SYSTEM, Modules, Commands, Streams, WinTrace, Kernel32;
+IMPORT S := SYSTEM, Modules, Commands, Streams, Pipes, WinTrace, Kernel32;
 
 CONST 
 	AddrSize = SIZEOF( ADDRESS );
@@ -12,6 +12,8 @@ VAR
 	env-: Commands.Context;
 
 	hin-, hout-, herr-: Kernel32.HANDLE;
+	stdInDecoupler: Pipes.ReadDecoupler;
+	
 
 PROCEDURE Args(): String;
 VAR size, pos: SIZE; i,j: LONGINT; str: String;
@@ -50,7 +52,8 @@ BEGIN
 	WinTrace.OpenConsole;
 	str := Args();
 	NEW( arg, LEN(str) ); arg.Set(str^);
-	NEW( stdin, WinTrace.Receive, 1024 );
+	NEW(stdInDecoupler, WinTrace.Receive);
+	NEW( stdin, stdInDecoupler.Receive, 1024 );
 	NEW( stdout, WinTrace.Send, 1024 );
 	NEW( errout, WinTrace.SendError, 512 );
 	NEW( env, stdin, arg, stdout, errout, NIL );