Unix.StdIO.Mod 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. MODULE StdIO; (** AUTHOR gf; PURPOSE "Unix standard IO and argument channels *)
  2. (* Commands.Context for programs running outside Aos *)
  3. IMPORT SYSTEM, Modules, Commands, Streams,Pipes , Unix;
  4. #IF COOP THEN
  5. IMPORT Activities, Counters, Environment;
  6. #END
  7. CONST
  8. Echo* = FALSE;
  9. TYPE
  10. String=POINTER TO ARRAY OF CHAR;
  11. VAR
  12. env-: Commands.Context;
  13. stdInDecoupler: Pipes.ReadDecoupler;
  14. PROCEDURE Args(): String;
  15. VAR size, pos: SIZE; i,j: LONGINT; str: String;
  16. argc: LONGINT;
  17. argv {UNTRACED}: POINTER {UNSAFE} TO ARRAY OF POINTER {UNSAFE,UNTRACED} TO ARRAY OF CHAR;
  18. BEGIN
  19. argc := Unix.argc;
  20. argv := Unix.argv;
  21. pos := 0;
  22. FOR i := 0 TO argc-1 DO
  23. j := 0;
  24. WHILE argv[i,j] # 0X DO
  25. INC(pos); INC(j);
  26. END;
  27. INC(pos);
  28. END;
  29. size := pos + 1;
  30. NEW(str, size);
  31. pos := 0;
  32. FOR i := 0 TO argc-1 DO
  33. j := 0;
  34. WHILE argv[i,j] # 0X DO
  35. str[pos] := argv[i,j];
  36. INC(pos); INC(j);
  37. END;
  38. str[pos] := " ";
  39. INC(pos);
  40. END;
  41. str[pos] := 0X;
  42. RETURN str;
  43. END Args;
  44. #IF COOP THEN
  45. VAR processor: Activities.Activity;
  46. VAR reader: Unix.Thread_t;
  47. VAR read : RECORD buffer: ADDRESS; size, result: SIZE; ready: BOOLEAN END;
  48. PROCEDURE {C} ReaderThread (): ADDRESS;
  49. BEGIN {UNCOOPERATIVE, UNCHECKED}
  50. Activities.CallVirtual (ReadActivity, NIL, processor);
  51. RETURN NIL;
  52. END ReaderThread;
  53. PROCEDURE ReadActivity (p: ADDRESS);
  54. BEGIN
  55. WHILE Environment.status = Environment.Running DO
  56. BEGIN {EXCLUSIVE}
  57. Counters.Inc (Activities.awaiting);
  58. AWAIT (~read.ready);
  59. read.result := Unix.read( Unix.stdin, read.buffer, read.size );
  60. read.ready := TRUE;
  61. Counters.Dec (Activities.awaiting);
  62. END;
  63. END;
  64. END ReadActivity;
  65. PROCEDURE Read (buffer: ADDRESS; size: SIZE): SIZE;
  66. BEGIN {EXCLUSIVE}
  67. read.buffer := buffer;
  68. read.size := size;
  69. read.ready := FALSE;
  70. IF processor = NIL THEN
  71. processor := Activities.CreateVirtualProcessor ();
  72. ASSERT (Unix.pthread_create(ADDRESS OF reader, NIL, ReaderThread, NIL) = 0);
  73. END;
  74. AWAIT (read.ready);
  75. RETURN read.result;
  76. END Read;
  77. #ELSE
  78. PROCEDURE Read (buffer: ADDRESS; size: SIZE): SIZE;
  79. BEGIN RETURN Unix.read( Unix.stdin, buffer, size );
  80. END Read;
  81. #END
  82. PROCEDURE ReceiveStdin( VAR data: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD );
  83. VAR ures: SIZE; i, err: LONGINT;
  84. BEGIN
  85. len := 0;
  86. REPEAT
  87. ures := Read( ADDRESSOF (data[ofs]), size );
  88. IF ures > 0 THEN
  89. INC( ofs, LONGINT(ures) ); DEC( size, LONGINT(ures) ); INC( len, LONGINT(ures) )
  90. END;
  91. IF ures < 0 THEN err := Unix.errno() END;
  92. UNTIL (len >= min) OR ((ures <= 0) & (err # Unix.EINTR) & (err # 0));
  93. IF len >= min THEN res := Streams.Ok ELSE res := Streams.EOF END;
  94. END ReceiveStdin;
  95. PROCEDURE SendStdout( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; prop: BOOLEAN; VAR res: WORD );
  96. VAR ignore: SIZE;
  97. BEGIN
  98. ignore := Unix.write( 1, ADDRESSOF( data[ofs] ), len ); res := Streams.Ok
  99. END SendStdout;
  100. PROCEDURE SendErrout( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; prop: BOOLEAN; VAR res: WORD );
  101. VAR ignore: SIZE;
  102. BEGIN
  103. ignore := Unix.write( 2, ADDRESSOF( data[ofs] ), len ); res := Streams.Ok
  104. END SendErrout;
  105. PROCEDURE Cleanup;
  106. BEGIN
  107. env.error.Update;
  108. env.out.Update
  109. END Cleanup;
  110. PROCEDURE Setup;
  111. VAR
  112. arg: Streams.StringReader;
  113. stdin: Streams.Reader;
  114. stdout: Streams.Writer;
  115. errout: Streams.Writer;
  116. str: String;
  117. BEGIN
  118. str := Args();
  119. NEW( arg, LEN(str) ); arg.Set(str^);
  120. NEW(stdInDecoupler, ReceiveStdin);
  121. NEW( stdin, stdInDecoupler.Receive, 1024 );
  122. NEW( stdout, SendStdout, 1024 );
  123. NEW( errout, SendErrout, 512 );
  124. NEW( env, stdin, arg, stdout, errout, NIL );
  125. Modules.InstallTermHandler( Cleanup );
  126. END Setup
  127. BEGIN
  128. Setup;
  129. END StdIO.