#!/bin/sh

# Copyright (c) 2004, 2005
# Kevin Atkinson
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without
# fee, provided that the above copyright notice appear in all copies
# and that both that copyright notice and this permission notice
# appear in supporting documentation.  Kevin Atkinson makes no
# representations about the suitability of this software for any
# purpose.  It is provided "as is" without express or implied
# warranty.

cmd=`basename "$0"`

# Output warning to stderr unless quiet mode enabled
warn ()
{
  if test -z "$quiet"; then echo "$cmd: $1" >&2 ; fi
}

# Output error to stderr and set "errors" flag
error ()
{
  echo "$cmd: $1" >&2
  errors=t
}

# Now do work of Zip, Compress or Decompress.
# Stdin and Stdout are already setup earlier by function zipsetio()
zipnow ()
{
  case $1 in
  d)
    prezip-bin -d
    ;;
  z)
    if test "$wordcomp"
    then
      if test "$sort"
      then
	tr "\000-\040" "\012" | LC_COLLATE=C sort -u | prezip-bin -c
      else
	prezip-bin -c
      fi
    else
      if test "$sort"
      then
	if test "$lfonly"
	then
	  LC_COLLATE=C sort -u | prezip-bin -z -l
	else
	  LC_COLLATE=C sort -u | prezip-bin -z
	fi
      else
	if test "$lfonly"
	then
	  prezip-bin -z -l
	else
	  prezip-bin -z
	fi
      fi
    fi
    ;;
  esac
  if test $? -eq 0
  then
    return 0
  else
    errors=t
    return 1
  fi
}

# Setup Stdin="$2" and Stdout="$3" and then call function zipnow()
# If no errors, remove (or $keep) file$2. If errors, remove file$3.
zipsetio ()
{
  if test -e "$3" -a ! "$force"
  then
    error "Output file $3 already exists."
    return 1
  fi
  if test -z "$stdout"
  then
    zipnow $1 < "$2" > "$3"
  else
    zipnow $1 < "$2"
  fi
  if test $? -eq 0
  then
    if test -z "$keep"; then rm "$2"; fi
    return 0
  else
    if test -z "$stdout"; then rm "$3"; fi
    return 1
  fi
}

# Start script main() here
case $cmd in
prezip)   mode=z ;;
preunzip) mode=d ;;
precat)   mode=d; stdout=t ;;
*)        mode=h ;;
esac

# Read all options on command line before processing
num=0
for p
do
  case $p in
  --*)
    parm=`expr "x$p" : '...\(.*\)'`
    case $parm in
    decompress	) mode=d ;;
    compress	) mode=z ;;
    wordcomp	) wordcomp=t ;;
    lfonly	) lfonly=t ;;
    keep	) keep=t ;;
    force	) force=t ;;
    stdout	) stdout=t ;;
    sort	) sort=t ;;
    nocwl	) nocwl=t ;;
    license	) mode=L ;;
    version	) mode=V ;;
    help	) mode=h ;;
    quiet	) quiet=t ;;
    *		) error "invalid option -- $parm";;
    esac
    ;;
  -* )
    p=`expr "x$p" : '..\(.*\)'`
    while test "$p"
    do
      parm=`expr "$p" : '\(.\)'`
      p=`expr "$p" : '.\(.*\)'`
      case $parm in
      d ) mode=d ;;
      z ) mode=z ;;
      w ) wordcomp=t ;;
      l ) lfonly=t ;;
      k ) keep=t ;;
      f ) force=t ;;
      c ) stdout=t ;;
      s ) sort=t ;;
      S ) nocwl=t ;;
      L ) mode=L ;;
      V ) mode=V ;;
      h ) mode=h ;;
      q ) quiet=t ;;
      * ) error "invalid option -- $parm";;
      esac
    done
    ;;
  * )
    num=`expr $num + 1`
    ;;
  esac
done

if test "$stdout"
then
  keep=t
fi 

if test "$errors"
then
  mode=h
fi

# Process files according to options set above
case $mode in
h )
  prezip-bin -V
  cat <<EOF

  usage $0 [-hdzwlLV] [-cfksSq] [file ...]

   -h --help        display Help
   -d --decompress  force Decompression
   -z --compress    force compression
   -L --license     display software License
   -V --version     display Version

   -c --stdout      decompress to standard output
   -f --force       force
   -k --keep        keep original input files (otherwise they are deleted)
   -s --sort        sort and remove duplicate words before compressing
   -S --nocwl       do not rename .wl suffix to .cwl (use .wl.pz instead)
   -q --quiet       suppress all warnings

  These option are usable only if compressing a file, otherwise ignored:
   -w --wordcomp    use "word-list-compress", not "prezip-bin" compression
   -l --lfonly      Convert EOL CRLF to LF before "prezip-bin" compression

  If invoked as "prezip" the default action is to compress.
             as "preunzip" the default action is to decompress.
             as "precat" the default action is to decompress to stdout.

  If no file name is given, then prezip will compress or decompress
  from standard input to standard output.

  Short flags can be combined so that "-c -s" is the same as "-cs".

  Prezip is _not_ a general purpose compressor.  It should only be used on
  sorted word lists or other similar text files.  It may likely _increase_
  the size of binary data.

  If "-w" is used then the file will be able to be decompressed using
  "word-list-compress" which is used by Aspell 0.50 and earlier.
  However, this format will lose all characters within {0x00...0x20},
  which includes the space, as they are treated as word separators.
  The newer "prezip-bin" format does not have this problem and can be
  used with any text file, not just word lists.

EOF
  ;;
L )
  prezip-bin -V
  cat <<EOF

  Copyright (c) 2004, 2005
  Kevin Atkinson

  Permission to use, copy, modify, distribute and sell this software
  and its documentation for any purpose is hereby granted without
  fee, provided that the above copyright notice appear in all copies
  and that both that copyright notice and this permission notice
  appear in supporting documentation.  Kevin Atkinson makes no
  representations about the suitability of this software for any
  purpose.  It is provided "as is" without express or implied
  warranty.

EOF
  ;;
V )
  prezip-bin -V
  ;;
d | z )
  if test $num -gt 0
  then
    for f
    do
      case $f in
      -* ) ;;
      * )
	if test \( -f "$f" -a ! -L "$f" \) \
		-o \( \( "$stdout" -o "$force" \) -a -L "$f" \)
	then
	  if test "$stdout"
	  then
	    zipsetio $mode "$f"
	  else
	    case $mode in
	    d )
	      dir=`dirname "$f"`
	      file=`basename "$f"`
	      base=`basename "$f" .pz`
	      base2=`basename "$f" .cwl`
	      if test "$file" != "$base"
	      then
		out="$dir/$base"
		zipsetio d "$f" "$out"
	      elif test "$file" != "$base2"
	      then
		out="$dir/$base2.wl"
		zipsetio d "$f" "$out"
	      elif test "$force"
	      then
		out="$f.out"
		warn "cannot guess original name - using \"$out\""
		zipsetio d "$f" "$out"
	      else
		warn "$f does not end in .pz or .cwl - file ignored"
	      fi
	      ;;
	    z )
	      dir=`dirname "$f"`
	      file=`basename "$f"`
	      base=`basename "$f" .wl`
	      if test "$nocwl" -o "$file" = "$base"
	      then
		zipsetio z "$f" "$f.pz"
	      else
		zipsetio z "$f" "$dir/$base.cwl"
	      fi
	      ;;
	    esac
	  fi
	elif test -e "$f"
	then
	  warn "$f is not a regular file - ignored"
	else
	  error "$f: No such file"
	fi
	;;
      esac
    done
  else
    case $mode in
    d ) zipnow d ;;
    z ) zipnow z ;;
    esac
  fi
  ;;
esac

if test "$errors"
then
  exit 1
else
  exit 0
fi
