123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- MODULE StdIO; (** AUTHOR gf; PURPOSE "Unix standard IO and argument channels *)
- (* Commands.Context for programs running outside Aos *)
- IMPORT SYSTEM, Modules, Commands, Streams,Pipes , Unix;
- #IF COOP THEN
- IMPORT Activities, Environment;
- #END
- CONST
- AddrSize = SIZEOF( ADDRESS );
- 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;
- argv {UNTRACED}: POINTER {UNSAFE} TO ARRAY OF POINTER {UNSAFE,UNTRACED} TO ARRAY OF CHAR;
- BEGIN
- argc := Unix.argc;
- argv := Unix.argv;
- pos := 0;
- FOR i := 0 TO argc-1 DO
- j := 0;
- WHILE argv[i,j] # 0X DO
- INC(pos); INC(j);
- END;
- INC(pos);
- END;
- size := pos + 1;
- NEW(str, size);
- pos := 0;
- FOR i := 0 TO argc-1 DO
- j := 0;
- WHILE argv[i,j] # 0X DO
- str[pos] := argv[i,j];
- INC(pos); INC(j);
- END;
- str[pos] := " ";
- INC(pos);
- END;
- str[pos] := 0X;
- RETURN str;
- END Args;
- #IF COOP THEN
- VAR processor: Activities.Activity;
- VAR reader: Unix.Thread_t;
- VAR read : RECORD buffer: ADDRESS; size, result: SIZE; ready: BOOLEAN END;
- PROCEDURE ReaderThread;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Activities.CallVirtual (ReadActivity, NIL, processor);
- Unix.pthread_exit (0);
- END ReaderThread;
- PROCEDURE ReadActivity (p: ADDRESS);
- BEGIN
- WHILE Environment.status = 0 DO
- BEGIN {EXCLUSIVE}
- AWAIT (~read.ready);
- read.result := Unix.read( 0, read.buffer, read.size );
- read.ready := TRUE;
- END;
- END;
- END ReadActivity;
- PROCEDURE Read (buffer: ADDRESS; size: SIZE): SIZE;
- BEGIN {EXCLUSIVE}
- read.buffer := buffer;
- read.size := size;
- read.ready := FALSE;
- IF processor = NIL THEN
- processor := Activities.CreateVirtualProcessor ();
- ASSERT (Unix.pthread_create(ADDRESS OF reader, NIL, ReaderThread, NIL) = 0);
- END;
- AWAIT (read.ready);
- RETURN read.result;
- END Read;
- #ELSE
- PROCEDURE Read (buffer: ADDRESS; size: SIZE): SIZE;
- BEGIN RETURN Unix.read( 0, buffer, size );
- END Read;
- #END
- PROCEDURE ReceiveStdin( VAR data: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT );
- VAR ures: SIZE; i, err: LONGINT;
- BEGIN
- len := 0;
- REPEAT
- ures := Read( ADDRESSOF (data[ofs]), size );
- IF ures > 0 THEN
- INC( ofs, LONGINT(ures) ); DEC( size, LONGINT(ures) ); INC( len, LONGINT(ures) )
- END;
- IF ures < 0 THEN err := Unix.errno() END;
- UNTIL (len >= min) OR ((ures <= 0) & (err # Unix.EINTR) & (err # 0));
- IF len >= min THEN res := Streams.Ok ELSE res := Streams.EOF END;
- END ReceiveStdin;
- PROCEDURE SendStdout( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; prop: BOOLEAN; VAR res: WORD );
- VAR ignore: SIZE;
- BEGIN
- ignore := Unix.write( 1, ADDRESSOF( data[ofs] ), len ); res := Streams.Ok
- END SendStdout;
- PROCEDURE SendErrout( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; prop: BOOLEAN; VAR res: WORD );
- VAR ignore: SIZE;
- BEGIN
- ignore := Unix.write( 2, ADDRESSOF( data[ofs] ), len ); res := Streams.Ok
- END SendErrout;
- PROCEDURE Cleanup;
- BEGIN
- env.error.Update;
- env.out.Update
- END Cleanup;
- PROCEDURE Setup;
- VAR
- arg: Streams.StringReader;
- stdin: Streams.Reader;
- stdout: Streams.Writer;
- errout: Streams.Writer;
- str: String;
- BEGIN
- str := Args();
- NEW( arg, LEN(str) ); arg.Set(str^);
- NEW(stdInDecoupler, ReceiveStdin);
- NEW( stdin, stdInDecoupler.Receive, 1024 );
- NEW( stdout, SendStdout, 1024 );
- NEW( errout, SendErrout, 512 );
- NEW( env, stdin, arg, stdout, errout, NIL );
- Modules.InstallTermHandler( Cleanup );
- END Setup
- BEGIN
- Setup;
- END StdIO.
|