/*   TextStat v1.10
 *
 *   A text analysis and word count program.
 *
 *   Written by Stefan Zeiger - 08/02/91
 *
 *   © 1991 by ! WIZARD WORKS !
 *
 *   This program is Freeware. It may only be distributed for non-commercial
 *   purposes, only for a little distribution fee (less or equal to the
 *   distribution fee, that Fred Fish wants for his AmigaLibDisks) , only
 *   with all files (TextStat, TextStat.doc, TextStat.c, LMKFile )
 *   together and only in unmodified form. See TextStat.doc for further
 *   information. Bug reports, donations, questions and suggestions to:
 *
 *    STANDARD MAIL : Stefan Zeiger
 *                    Seligenstaedter Weg 24
 *                    D-W-8756 Kahl
 *                    West Germany
 *    VOICE :         (49)-6188-2525
 */


#include <exec/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <ctype.h>


#define EQUAL 0


void cleanexit(int,ULONG),quicksort(int,int),quicksort2(int,int);


ULONG field[512],field2[512];
int index[512],index2[512];


void main(int argc,char **argv)
{
  ULONG alnum=0,alpha=0,ascii=0,cntrl=0,csym=0,csymf=0,digit=0;
  ULONG graph=0,lower=0,print=0,punct=0,upper=0,xdigit=0;
  ULONG words=0,letters=0,checksum=0,whites=0,nonwhites=0;
  int handle=-1,dummy=0,anzahl=1,i,flag=FALSE;
  char wert=1,*wert_p=&wert;
  UBYTE *message="\n\033[33mTextStat v1.10\033[31m\nWritten by Stefan Zeiger - ©1991 by ! WIZARD WORKS !\n";

  for(i=0;i<=255;i++) { field[i]=0; index[i]=i; }

  if(argc==1)
  {
    printf("No file specified.\n");
    cleanexit(handle,15L);
  }

  if(strcmp(argv[1],"?")==EQUAL)
  {
    printf(message);
    printf("Usage : %s <filename> [-a]\n\n",argv[0]);
    cleanexit(handle,15L);
  }

  if(argc>3)
  {
    printf("Too many arguments.\n");
    cleanexit(handle,15L);
  }

  if((strcmp(argv[2],"-a")!=EQUAL) && (argc==3))
  {
    printf("Unknown option.\n");
    cleanexit(handle,15L);
  }

  handle=open(argv[1],0,dummy);
  if(handle==-1)
  {
    printf("File not found.\n");
    cleanexit(handle,15L);
  }

  printf(message);
  printf("Analyzing file \'\033[32m%s\033[31m\'\n",argv[1]);

  while (anzahl==1)    /* The main loop */
  {
    anzahl=read(handle,wert_p,1);
    /* printf("%d\n",wert); */
    checksum+=wert;
    letters++;
    field[wert]++;
    if(wert==32)
    {
      whites++;
      if(flag==TRUE) { flag=FALSE; words++; }
    }
    else
    {
      nonwhites++;
      if(wert!=10) flag=TRUE;
    }
    if(wert==10) { if(flag==TRUE) { flag=FALSE; words++; } }

    if( isalnum (wert)) alnum  ++;
    if( isalpha (wert)) alpha  ++;
    if( isascii (wert)) ascii  ++;
    if( iscntrl (wert)) cntrl  ++;
    if( iscsym  (wert)) csym   ++;
    if( iscsymf (wert)) csymf  ++;
    if( isdigit (wert)) digit  ++;
    if( isgraph (wert)) graph  ++;
    if( islower (wert)) lower  ++;
    if( isprint (wert)) print  ++;
    if( ispunct (wert)) punct  ++;
    if( isupper (wert)) upper  ++;
    if( isxdigit(wert)) xdigit ++;

  }   /* End of the main loop */

  close(handle);

  if(strcmp(argv[2],"-a")==EQUAL)
  {
    printf("\n\033[32m DEC | ASC | COUNT  \n--------------------\033[31m\n");

    for(i=32;i<=127;i++)  printf("%3d  |  %c  |  %6lu\n",i,i,field[i]);
    for(i=161;i<=255;i++) printf("%3d  |  %c  |  %6lu\n",i,i,field[i]);
  }

  printf("\nLINES               : %9lu\n"  ,field[10]);
  printf(  "WORDS               : %9lu\n"  ,words);
  printf(  "CHARS               : %9lu\n"  ,letters);

  printf(  "ALPHANUMERIC CHARS  : %9lu\n"  ,alnum);
  printf(  "ALPHABETIC CHARS    : %9lu\n"  ,alpha);
  printf(  "ASCII CHARACTERS    : %9lu\n"  ,ascii);
  printf(  "PRINTABLE CHARS     : %9lu\n"  ,print);

  printf(  "WHITESPACES         : %9lu\n"  ,whites);
  printf(  "NON-WHITE CHARS     : %9lu\n"  ,nonwhites);

  printf(  "CONTROL CHARACTERS  : %9lu\n"  ,cntrl);
  printf(  "C SYMBOL CHARS      : %9lu\n"  ,csym);
  printf(  "C SYMBOL LEAD CHARS : %9lu\n"  ,csymf);
  printf(  "GRAPHIC CHARACTERS  : %9lu\n"  ,graph);
  printf(  "PUNCTUATION CHARS   : %9lu\n"  ,punct);

  printf(  "UPPER CASE CHARS    : %9lu\n"  ,upper);
  printf(  "LOWER CASE CHARS    : %9lu\n"  ,lower);

  printf(  "DECIMAL DIGIT CHARS : %9lu\n"  ,digit);
  printf(  "HEX DIGIT CHARS     : %9lu\n"  ,xdigit);

  printf(  "CHECKSUM            : %9lu\n\n",checksum);

  if(strcmp(argv[2],"-a")==EQUAL)
  {
    for(i=0;i<=255;i++) { field2[i]=field[i]; index2[i]=index[i]; }
    quicksort(0,255);
    printf("\033[32m DEC | ASC | COUNT  \n--------------------\033[31m\n");
    for(i=0;i<=255;i++)
    {
      if((index[i]>31 && index[i]<128) || index[i]>160)
        printf("%3d  |  %c  |  %6lu\n",index[i],index[i],field[i]);
    }
    for(i=0;i<=255;i++) { field[i]=field2[i]; index[i]=index2[i]; }
    for(i='A';i<='z';i++)
    {
      if(i>='a' && i<='z') field[i-'a'+'A']+=field[i];
    }
    quicksort(0,255);
    printf("\n\033[32m ASC | COUNT  \n---------------\033[31m\n");
    for(i=0;i<=255;i++)
    {
     if(index[i]>='A' && index[i]<='Z')
       printf("  %c  |  %6lu\n",index[i],field[i]);
    }
    printf("\n");
  }
  exit(0L);
}


void cleanexit(int handle,ULONG error)
{
  if(handle!=-1) close(handle);
  exit(error);
}


void quicksort(int start,int stop)
{
  int m,l,r;
  ULONG v,help;

  if(start<stop)
  {
    m=(start+stop)/2;
    v=field[m];
    l=start;
    r=stop;
    while(l<=r)
    {
      while(field[l]>v) l++;
      while(field[r]<v) r--;
      if(l<=r)
      {
        help=field[r];
        field[r]=field[l];
        field[l]=help;
        help=index[r];
        index[r]=index[l];
        index[l]=help;
        l++;
        r--;
      }
    }
    quicksort(start,r);
    quicksort(l,stop);
  }
}
