#!/usr/bin/tclsh8.4
array set defaults {
acat {-s cp866 -d koi8-r -l crlf}
wcat {-s cp1251 -d koi8-r -l crlf}
mcat {-s macCyrillic -d koi8-r -l cr}
icat {-s iso8859-5 -d koi8-r -l lf}
}

proc help {} {
  puts "Usage ucat options \[files\]
  where options may be:
  -s charset  - set source charset
  -d charset - set destination charset
  -l mode - set input eol translation mode (one of cr, crlf, lf)
  -r - reverese input output
  Allowed charset:
  [encoding names]"
  exit 1
}

if [info exists defaults([file tail $argv0])] {
  set argv [concat $defaults([file tail $argv0]) $argv]
}
set index 0

proc next_key {list raise_Error} {
  upvar $list l
  if {$raise_Error && ![llength $l]} {
    puts stderr "Option requires an argument"
    exit 1
  }  
  set val [lindex $l 0]
  set l [lrange $l 1 end]
 
  return $val
}

proc do_file {f} {
  global incharset outcharset inlf outlf
  fconfigure $f -encoding $incharset -translation $inlf
  while {![eof $f]} {
    puts -nonewline  [read $f 4096]
  }  
}
set reverse 0
set incharset utf-8 
set outcharset [encoding system]
set inlf auto
switch $tcl_platform(platform) {
  unix { set outlf lf }
  windows {set outlf crlf}
  mac {set outlf cr}
  default {set outlf lf}
}  
while {[llength [set key [next_key argv 0]]]} {
   if {$key=="-" || ![string match -* $key]} {
      set argv [concat $key $argv]
      break
   }
   switch -exact -- $key {
     -s { set incharset [next_key argv 1] }
     -d {set outcharset [next_key argv 1]}
     -r {set reverse 1}
     -l {set inlf [next_key argv 1]}
     default {
       puts stderr "Invalid option $key"
       help
     }
   }
}

if $reverse {
  set tmp $incharset
  set incharset $outcharset
  set outcharset $tmp
  set tmp $inlf
  set inlf $outlf
  set outlf $tmp
}

fconfigure stdout -encoding $outcharset -translation $outlf
if {$outcharset=="unicode"} {
  puts -nonewline "\uFEFF"
}  
if {![llength $argv]} {
   do_file stdin
} else {
  foreach file $argv {
     if {$file=="-"} {
       do_file stdin
     } else {
       if [catch {open $file} f] {
          puts stderr "$file: $f"
	  exit 1
       }
       do_file $f
       close $f
     }
  }
}  
