#!/usr/bin/ksh93
################################################################
#### Program: wc_k93
#### 
#### Description: Counts lines, words and characters in an
#### input stream, file or files.
#### 
#### Author: Dana French (dfrench@mtxia.com)
#### 
#### Date: 07/22/2004
#### 
################################################################
function wc_k93 {
  typeset TRUE="0"
  typeset FALSE="1"
  typeset VERBOSE="${FALSE}"
  typeset VERYVERB="${FALSE}"
  typeset CNTLINES="${FALSE}"
  typeset CNTWORDS="${FALSE}"
  typeset CNTCHARS="${FALSE}"
  typeset DELIM="${IFS}"$'\r'
  typeset -R7 LCNT WCNT CCNT
  typeset -R7 LTOT WTOT CTOT
  typeset RESULT
  typeset TOTAL=""
  typeset FNAME=""
  typeset STDIN="${1:+${FALSE}}"
  STDIN="${STDIN:-${TRUE}}"

  while getopts ":d:lwcvV" OPTION
  do
    case "${OPTION}" in
        'd') DELIM="${OPTARG}";;
        'l') CNTLINES="${TRUE}";;
        'w') CNTWORDS="${TRUE}";;
        'c') CNTCHARS="${TRUE}";;
        'v') VERBOSE="${TRUE}";;
        'V') VERYVERB="${TRUE}";;
        '?') print "Syntax: wc [-l] [-w] [-c] [FILE]..." && exit 1
    esac
  done
 
  shift $(( ${OPTIND} - 1 ))

  (( VERYVERB == TRUE )) && set -x

  if (( CNTLINES == FALSE && CNTWORDS == FALSE && CNTCHARS == FALSE ))
  then
      (( VERBOSE == TRUE )) &&
          print -u 2 "No options specified, all output printed by default"
      CNTLINES="${TRUE}"
      CNTWORDS="${TRUE}"
      CNTCHARS="${TRUE}"
  fi

  typeset STDIN="${1:+${FALSE}}"
  STDIN="${STDIN:-${TRUE}}"

  if (( STDIN == TRUE ))
  then
      (( VERBOSE == TRUE )) && print -u 2 "Reading from standard input"
      TOTAL=$( wcLWC_k93 "${DELIM}" ${CNTLINES} ${CNTWORDS} ${CNTCHARS} )
      LCNT="${TOTAL%%:*}"
      WCNT="${TOTAL//*:(*):*/\1}"
      CCNT="${TOTAL##*:}"
      unset RESULT
      [[ "_${LCNT}" != _*([ ]) ]] && RESULT[0]="${LCNT}"
      [[ "_${WCNT}" != _*([ ]) ]] && RESULT[1]="${WCNT}"
      [[ "_${CCNT}" != _*([ ]) ]] && RESULT[2]="${CCNT}"
      print -- "${RESULT[*]}"
  else

    for FNAME in "${@}"
    do
      if [[ -f "${FNAME}" ]]
      then      
        (( VERBOSE == TRUE )) && print -u 2 "Reading from file \"${FNAME}\""

        exec 0<"${FNAME}"
          TOTAL=$( wcLWC_k93 "${DELIM}" ${CNTLINES} ${CNTWORDS} ${CNTCHARS} )
          LCNT="${TOTAL%%:*}"
          WCNT="${TOTAL//*:(*):*/\1}"
          CCNT="${TOTAL##*:}"
          unset RESULT
          [[ "_${LCNT}" != _*([ ]) ]] && RESULT[0]="${LCNT}"
          [[ "_${WCNT}" != _*([ ]) ]] && RESULT[1]="${WCNT}"
          [[ "_${CCNT}" != _*([ ]) ]] && RESULT[2]="${CCNT}"
          print -- "${RESULT[*]} ${FNAME}"
        exec 0<&-

        if (( ${#} > 1 ))
        then
          (( CNTLINES == TRUE )) &&
              (( LTOT = LTOT + LCNT  )) &&
              (( VERBOSE == TRUE )) &&
                 print -u 2 "Subtotal Lines: ${LTOT}"
          (( CNTWORDS == TRUE )) &&
              (( WTOT = WTOT + WCNT )) &&
              (( VERBOSE == TRUE )) &&
                 print -u 2 "Subtotal Words: ${WTOT}"
          (( CNTCHARS == TRUE )) &&
              (( CTOT = CTOT + CCNT  )) &&
              (( VERBOSE == TRUE )) &&
                 print -u 2 "Subtotal Chars: ${CTOT}"
        fi
      else
        print -u 2 "ERROR: \"${FNAME}\" does not exist or is not a regular file."
      fi
    done

    if (( ${#} > 1 ))
    then
        unset RESULT
        [[ "_${LTOT}" != _*([ ]) ]] && RESULT[0]="${LTOT}"
        [[ "_${WTOT}" != _*([ ]) ]] && RESULT[1]="${WTOT}"
        [[ "_${WTOT}" != _*([ ]) ]] && RESULT[2]="${CTOT}"
        print -- "${RESULT[*]} total"
    fi
  fi
  return 0
}
################################################################
function wcLWC_k93 {
    typeset TRUE="0"
    typeset FALSE="1"
    typeset DELIM="${1}"
    typeset CNTLINES="${2}"
    typeset CNTWORDS="${3}"
    typeset CNTCHARS="${4}"
    typeset LCNT WCNT CCNT
    typeset RESULT
    typeset LINE
    typeset ARRY

    while IFS="" read -r -- LINE
    do
        (( CNTLINES == TRUE )) && (( LCNT++ ))
        (( CNTCHARS == TRUE )) && (( CCNT = CCNT + ${#LINE} + 1 ))
        if (( CNTWORDS == TRUE ))
        then
            if [[ "_${LINE}" != _*([${IFS}]) ]]
            then
                LINE="${LINE//\*/\\\*}"
                LINE="${LINE//\?/\\\?}"
                IFS="${DELIM}"
                ARRY=( ${LINE} )
                IFS=$' \t\n'
                (( WCNT = WCNT + ${#ARRY[*]} ))
            fi
        fi
    done
    print "${LCNT}:${WCNT}:${CCNT}"
}
################################################################

wc_k93 ${*}