File : chomp2.bush


#!/usr/local/bin/bush
--
-- Morph
--
-- Program to convert one kind of text file to another
-- Created by Ken O. Burtch
--
-- Like chomp, but using pragma ada_95

pragma ada_95;
pragma restriction( no_external_commands );

procedure chomp2 is

-- Error codes

   error_syntax   : constant short_short_integer := 192;
   error_no_file  : constant short_short_integer := 193;
   error_internal : constant short_short_integer := 194;

-- Script Flags

   type text_types is ( unknown, dos, mac, unix, broken, binary, c, strip );
   -- conversions we can do

   target_type : text_types := unknown;
   verbose : boolean := true; -- was false

-- Files

   input      : file_type;
   sourcepath : string;
   output     : file_type;
   targetpath : string;

-- Misc

   textline   : string;
   len        : natural;
   ch         : character;
   out_cnt    : natural := 0;

   procedure usage is
   begin
     put( "usage: " );
     put( source_info.file );
     put_line( " -cdmsuv sourcefile targetfile" );
     new_line;
     put_line( "  Morph text files into different formats." );
     new_line;
     put_line( "  -d convert to MS-DOS or Windows (CR+LF)" );
     put_line( "  -m convert to Apple or Mac (CR)" );
     put_line( "  -u convert to UNIX or Linux (LF)" );
     put_line( "  -c convert to C or C++ (NUL)" );
     put_line( "  -s strip CR and LF" );
     put_line( "  -v verbose" );
   end usage;

begin

-- Usage

if command_line.argument_count < 3 then
   if command_line.argument_count > 0 then
      if command_line.argument(1) = "-h" or command_line.argument(1) = "--help" then
         usage;
         command_line.set_exit_status( 192 );
         return;
      end if;
   end if;
   put( standard_error, source_info.file );
   put_line( standard_error, ": use -h for help" );
   command_line.set_exit_status( error_syntax );
   return;
end if;

-- Process arguments

for i in 1..command_line.argument_count-2 loop
   if command_line.argument(i) = "-d" then
      if target_type /= unknown then
         put( standard_error, source_info.file );
         put( standard_error, ":" );
         put( standard_error, source_info.line );
         put_line( standard_error, ": more than 1 conversion" );
         command_line.set_exit_status( error_syntax );
         return;
      end if;
      target_type := dos;
   elsif command_line.argument(i) = "-m" then
      if target_type /= unknown then
         put( standard_error, source_info.file );
         put( standard_error, ":" );
         put( standard_error, source_info.line );
         put_line( standard_error, ": more than 1 conversion" );
         command_line.set_exit_status( error_syntax );
         return;
      end if;
      target_type := mac;
   elsif command_line.argument(i) = "-u" then
      if target_type /= unknown then
         put( standard_error, source_info.file );
         put( standard_error, ":" );
         put( standard_error, source_info.line );
         put_line( standard_error, ": more than 1 conversion" );
         command_line.set_exit_status( error_syntax );
         return;
      end if;
      target_type := unix;
   elsif command_line.argument(i) = "-c" then
      if target_type /= unknown then
         put( standard_error, source_info.file );
         put( standard_error, ":" );
         put( standard_error, source_info.line );
         put_line( standard_error, ": more than 1 conversion" );
         command_line.set_exit_status( error_syntax );
         return;
      end if;
      target_type := c;
   elsif command_line.argument(i) = "-s" then
      if target_type /= unknown then
         put( standard_error, source_info.file );
         put( standard_error, ":" );
         put( standard_error, source_info.line );
         put_line( standard_error, ": more than 1 conversion" );
         command_line.set_exit_status( error_syntax );
         return;
      end if;
      target_type := strip;
   elsif command_line.argument(i) = "-v" then
      verbose := true;
   else
      put( standard_error, source_info.file );
      put( standard_error, ":" );
      put( standard_error, source_info.line );
      put_line( standard_error, ": unknown option: " & command_line.argument(i) );
      command_line.set_exit_status( error_syntax );
      return;
   end if;
end loop;

-- Check files

sourcepath := command_line.argument(command_line.argument_count-1);
targetpath := command_line.argument(command_line.argument_count);
if not files.is_readable_file( sourcepath ) then
   put( standard_error, source_info.file );
   put( standard_error, ":" );
   put( standard_error, source_info.line );
   put_line( standard_error, ": " & sourcepath & " doesn't exist or is not readable" );
   command_line.set_exit_status( error_no_file );
   return;
end if;

-- Do it

create( output, out_file, targetpath );
open( input, in_file, sourcepath );
while not end_of_file( input ) loop
   -- strip end-of-line terminators
   -- Note: BUSH should do this automatically.
   textline := get_line( input );
   if verbose then
      put( standard_error, "<< " );
      put_line( standard_error, strings.to_escaped( textline ) );
   end if;
   len := strings.length( textline );
   ch := strings.element( textline, positive( len ) );
   if ch = ASCII.LF then
      textline := strings.delete( textline, positive(len), len );
      len := len - 1;
      ch := strings.element( textline, positive( len ) );
      if ch = ASCII.CR then
         textline := strings.delete( textline, positive( len ), len );
      end if;
  elsif ch = ASCII.CR then
      textline := strings.delete( textline, positive( len ), len );
  end if;
  -- now add the correct ones
  case target_type is
  when dos =>
       textline := textline & ASCII.CR & ASCII.LF;
  when mac =>
       textline := textline & ASCII.CR;
  when unix =>
       textline := textline & ASCII.LF;
  when c =>
       textline := textline & ASCII.NUL;
  when strip =>
       null;
  when others =>
       put( standard_error, source_info.file );
       put( standard_error, ":" );
       put( standard_error, source_info.line );
       put_line( standard_error,  ": internal error: target type in case" );

       command_line.set_exit_status( error_internal );
       return;
  end case;
  if verbose then
     put( standard_error, ">> " );
     put_line( standard_error, strings.to_escaped( textline ) );
  end if;
  len := strings.length( textline );
  out_cnt := out_cnt+len;
  put( output, textline ); -- NOT put_line
end loop;
close( input );
close( output );

if verbose then
   put( standard_error, "Wrote" );
   put( standard_error, out_cnt );
   put_line( standard_error, " chars" );
end if;
command_line.set_exit_status( 0 );

end chomp2;