comp.lang.ada
 help / color / mirror / Atom feed
From: sk <sknipe@ktc.com>
To: comp.lang.ada@ada.eu.org
Subject: Re: Unix text handling on stdin
Date: Fri, 24 Aug 2001 18:44:36 -0500
Date: 2001-08-24T18:44:36-05:00	[thread overview]
Message-ID: <mailman.998696873.32161.comp.lang.ada@ada.eu.org> (raw)
In-Reply-To: 9m6hcj$aai1@news.cis.okstate.edu

[-- Attachment #1: Type: text/plain, Size: 1048 bytes --]

Hi, 

I tried the ICFP thing for S&G's (didn't, and didn't intend to, 
really enter) and ran into the same problem ...

So, my solution involved

Ada.Text_Io;
Ada.Text_Io.C_Streams;
Interfaces.C_Streams;

and here is a distilled way to take std in and copy it to 
stdout without TIO adding extra Line feeds when closing 
the file etc.

I fully intended to look up the issue in both the LRM and
Ada Issues to see if the compiler was behaving according to
spec, but once I found a work-around, I never got round
to checking about the legitimacy of this TIO behaviour.

The output of this procedure will be of exactly the same
size as the input ... unlike when exclusively using TIO
which always added an extra byte or two when closing.

sknipe@ktc.com

PS. Please note that this is a QAD[1] and not very careful such
that exceptions can and will be raised by going out of range

[1] Quick and Dirty :-)

PPS. Text attachment, sorry, to preserve formatting ...

PPPS. Linux, GNAT 3.13p

----------------------------------------------------------------

[-- Attachment #2: standard_io_play.adb --]
[-- Type: text/plain, Size: 2945 bytes --]

with Interfaces.C_Streams;

with Ada.Streams;
with Ada.Streams.Stream_Io;

with Ada.Text_Io;
with Ada.Text_Io.C_Streams;

procedure Standard_IO_Play is

	package ICS				renames Interfaces.C_Streams;
	
	package AS				renames Ada.Streams;
	package ASSIO			renames Ada.Streams.Stream_Io;

	package TIO				renames Ada.Text_Io;
	package TIOCS			renames Ada.Text_Io.C_Streams;
	
	function Is_File_A_Tty (
		File : Ada.Text_Io.File_Type
	) return Boolean is
	begin
		return (
			Interfaces.C_Streams.Isatty (
				Interfaces.C_Streams.FileNo (
					Ada.Text_Io.C_Streams.C_Stream (File)
				)
			) > 0
		);
	end Is_File_A_Tty;

	Buffer_Size	: constant := 10240; 	-- 10k buffer size


	Buffer	: String (1 .. Buffer_Size) := (Others => ' ');
	Last	: Natural := Buffer'Last;

	Buffer_Address	: constant ICS.Voids := Buffer(Buffer'First)'Address;
	Element_Size	: constant := Character'Size / 8;

	Bytes_Read		: ICS.Size_t := 0;
	Bytes_Written   : ICS.Size_t := 0;

	Flush_Result	: Integer;

begin
	-- First, check whether Std_In is attached to a tty or is 
	-- something else.
	-- If stdin is a tty, then expecting ketboard user input
	-- else (not a tty) assuming that the OS is piping a file 
	--     to this procedure
	-- (Remember this is just an example and that it is prabably
	--  a bad assumption and oversimplification). 
	--

	if Is_File_A_Tty (TIO.Current_Input) then
	
	
		TIO.Put_Line (
			File => TIO.Standard_Error,
			Item => "Trying to show piping. So please pipe into this procedure"
		);
		TIO.Put_Line (
			File => TIO.Standard_Error,
			Item => "ie # ""cat test-file | ./standard_io_play > result-file"""
		);
	
	else 
	
		Std_In_Read : loop
		
			exit Std_In_Read when TIO.End_Of_File (TIO.Current_Input);
			
			-- Read using ICS ...

			Bytes_Read := ICS.Fread (
				Buffer	=> Buffer_Address,
				Size	=> Element_Size,
				Count	=> ICS.Size_t (Buffer'Length),
				Stream	=> TIOCS.C_Stream (TIO.Current_Input)
			);
			
			-- Do your thing to the buffer ... (Note the possibility of
			-- incompatible ranges for Natural (Bytes_Read) and subsequent
			-- buffer overflows).
			
			Processing : for Char in Buffer'First .. Natural (Bytes_Read) loop

				if Buffer(Char) = ASCII.Lf then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found LF"
					);
					
				elsif Buffer(Char) = ASCII.Cr then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found CR"
					);
					
				elsif Buffer(Char) = ASCII.Ht then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found TAB"
					);
				
				end if;

			end loop Processing;
			
			-- Write using ICS ...

			Bytes_Written := ICS.Fwrite (
				Buffer	=> Buffer_Address,
				Size	=> Element_Size,
				Count	=> ICS.Size_t (Bytes_Read),
				Stream	=> TIOCS.C_Stream (TIO.Current_Output)
			);

		end loop Std_In_Read;

		Flush_Result := ICS.Fflush (TIOCS.C_Stream (TIO.Current_Output));

	end if;


end Standard_IO_Play;


  reply	other threads:[~2001-08-24 23:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-08-24 21:36 Unix text handling on stdin David Starner
2001-08-24 23:44 ` sk [this message]
2001-08-25  2:56 ` sk
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox