home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / misc_utils / scan / scan.c < prev    next >
C/C++ Source or Header  |  1991-03-09  |  12KB  |  424 lines

  1. /****************************************************************************
  2.  *    scan.c  Version 1.0                        
  3.  *
  4.  *    29 December 1990
  5.  *    Compiled with SAS/C 5.10  
  6.  *
  7.  *    Copyright © 1990 By Dan Fish
  8.  *    All rights reserved.
  9.  *
  10.  *    Permission is granted to freely redistribute this program provided 
  11.  *    the source code is included in the distribution and this copyright 
  12.  *    notice is unchanged.
  13.  *
  14.  ****************************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <fcntl.h>
  21. #include <exec/types.h>
  22. #include <intuition/intuition.h>
  23.  
  24. #include "ansicodes.h"
  25.  
  26. #define BUFFSIZE 2048L       /* length of I/O buffer */
  27. #define MAXFILELEN 80
  28. #define SPACEBAR 32
  29.  
  30. char *key[] = {
  31.         "NULLS     ","^A (SOH)  ","^B (STX)  ","^C (ETX)  ","^D (EOT)  ",
  32.         "^E (ENQ)  ","^F (ACK)  ","^G (BELL) ","Backspaces","Tabs      ",
  33.         "Line Feeds","Vert Tabs ","Formfeeds ","Returns   ","^N (SO)   ",
  34.         "^O (SI)   ","^P (DLE)  ","^Q (DC1)  ","^R (DC2)  ","^S (DC3)  ",
  35.         "^T (DC4)  ","^U (NAK)  ","^V (SYN)  ","^W (ETB)  ","^X (CAN)  ",
  36.         "^Y (EM)   ","^Z (SUB)  ","ESC       ","^\\ (FS)   ","^] (GS)   ",
  37.         "^^ (RS)   ","^- (US)   ","Spaces    " };
  38.  
  39.  
  40. char WindowTitle[] = "  ASCII     HEX    Count  Character   Percent";
  41. char *fname;
  42.  
  43. struct numlist {
  44.          long ascii;
  45.          long count;
  46.         };
  47. struct numlist num[256];
  48. struct numlist *numptr;
  49.  
  50. long temp[256];
  51.  
  52. long totalchars=0;
  53.  
  54. int diffchars=0, pages, page=1;
  55.  
  56. main (argc,argv)
  57. int argc;
  58. char *argv[];
  59. {
  60.  
  61.   void DisplayData();
  62.   void WriteData();
  63.   void GetData();
  64.   void BooBoo();
  65.   void Usage();
  66.   extern struct Window *mywindow;  /* Console window    */
  67.   extern short pagelen;  
  68.   char oname[MAXFILELEN+1];
  69.   
  70.   int in;
  71.   FILE *out;
  72.   int outfile = FALSE;
  73.   int sort = FALSE;
  74.   int loop;
  75.   
  76.   numptr=num;
  77.  
  78. /* parse the command line  */
  79.  
  80.  if (( argc<2) || (*argv[1] =='?') || argv[1][1] == '?')
  81.     {
  82.       Usage();
  83.       exit(10);
  84.     }   
  85.  
  86.  for (loop = argc-1; loop > 1; --loop)
  87.    if (!(argv[loop][0] == '-' ))  /* then it better be an output filename! */  
  88.     {
  89.      if(outfile)
  90.        BooBoo(3,(char *)NULL);                  /* already have an outfile! */
  91.      else { 
  92.        outfile = TRUE;
  93.        stccpy(oname,argv[loop],MAXFILELEN); }
  94.     }
  95.  
  96.  for (loop = argc-1; loop > 0; --loop)
  97.    if(argv[loop][0] == '-')  /* options */  
  98.     {
  99.      if(strpbrk(argv[loop],"sS") != (char *)NULL)
  100.        sort = TRUE;
  101.     }
  102.  
  103.  
  104.  if ((in = open(argv[1], O_RDONLY, NULL)) < 0)
  105.     BooBoo(1,argv[1]);
  106.  
  107.  
  108.  if(outfile)
  109.    if ((out = fopen(oname, "w")) == NULL)
  110.     {
  111.       close(in);
  112.       BooBoo(2,oname);
  113.     }
  114.  
  115.   fname=argv[1];
  116.  
  117.  GetData(in,sort);
  118.  
  119.  if(outfile)
  120.    WriteData(out);
  121.  else 
  122.    DisplayData();
  123.  
  124.  exit(0);
  125. }
  126.  
  127. /************************************************************************
  128. * Function : WriteData                            *
  129. * Arguments: fp - pointer to output file structure            *
  130. * Returns  : nothing                            *
  131. * Purpose  : Writes the data to an output file instead of the screen    *
  132. *************************************************************************/
  133.  
  134. void WriteData(fp)
  135. FILE *fp;
  136. {
  137.  char *Line();
  138.  int error=0;
  139.  register j;
  140.  fprintf(fp,"   File: %s     Total: %-6d     Different: %-3d\n\n",
  141.               fname,totalchars,diffchars);
  142.  
  143.  for(j = 0, numptr = num; j < diffchars; j++, numptr++)
  144.  {
  145.  error = fputs(Line(),fp);
  146.  if(error)
  147.    fprintf(stderr,"Scan: Error during write! Iteration = %3d, Ascii = %3d\n",
  148.            j,numptr->ascii);
  149.  error = fputs("\n",fp);
  150.  
  151.  }
  152.  
  153. fclose(fp); 
  154. }
  155.  
  156. /************************************************************************
  157. * Function : GetData                            *
  158. * Arguments: fh - file handle of input file                *
  159. *         sort - TRUE if output is to be sorted by frequency        *
  160. * Returns  : nothing                            *
  161. * Purpose  : Creates an array containing the number of each character     *
  162. *         found in the input file.  Sorts the array if applicable    *
  163. *************************************************************************/
  164. void GetData(fh,sort)
  165. int fh,sort;                 /*input file handle */
  166. {
  167.   int ch;
  168.   register j=0;
  169.   int frequency_sort();
  170.  
  171.   while ((ch = Fetch(fh)) != EOF)
  172.    {
  173.      temp[ch]++;    /* Increment the "temp[]" value that    */
  174.             /* corresponds to the ASCII value     */
  175.             /* of the character just read        */
  176.  
  177.      totalchars++;    /* Running tab on total # of char's    */
  178.    }
  179.  
  180. /* Create an array of only characters contained in the file by filtering */
  181. /* out all "temps[]" with a value of zero                 */
  182.  
  183.   while (j < 256)
  184.    {
  185.     if (temp[j] != 0)
  186.      {
  187.       num[diffchars].ascii = j;
  188.       num[diffchars].count = temp[j];
  189.       diffchars++;
  190.      }   
  191.     j++;
  192. }
  193.  
  194.  if (sort)
  195.   qsort((char *)num,diffchars+1,sizeof(struct numlist),frequency_sort);
  196.  
  197. }
  198.  
  199. /************************************************************************
  200. * Function : DisplayData                        *
  201. * Arguments: none                            *
  202. * Returns  : nothing                            *
  203. * Purpose  : Handles (or call functions to handle) all outputing of    *
  204. *         data to the screen.                    *
  205. *************************************************************************/
  206. void DisplayData()
  207. {
  208.   void mysetup();
  209.   extern short pagelen;
  210.   void DisplayLine();
  211.   void DisplayPage();
  212.   int getkey;
  213.  
  214.   char quit[] = {'q','Q','\x1b','\003','\0'}; /* Null terminated string of */
  215.                           /* characters that will end  */
  216.                                 /* the program               */
  217.     
  218.   mysetup();    /* Initialize the output console */
  219.   numptr = num;
  220.   cursor_off();
  221.  
  222.   if ((diffchars % pagelen)==0)  /* the number of different characters will  */
  223.    pages = diffchars/pagelen;    /* exactly fill a given number of pages     */
  224.   else
  225.    pages = (diffchars/pagelen)+1;/* gonna need an extra page     */
  226.  
  227.  
  228.   DisplayPage();             /* Display the first "pagelen" lines     */
  229.  
  230.   while(strchr(quit, getkey = getchar()) == (char *)NULL)
  231.      {
  232.       if (getkey == SPACEBAR && pages > 1)
  233.        {
  234.         if(numptr < &num[diffchars])  
  235.           DisplayPage();              /* display next page        */
  236.         else
  237.         {
  238.          numptr = num;    /* go back to first page */
  239.          DisplayPage();
  240.         }
  241.        }
  242.      }
  243.     return;
  244.    }
  245.  
  246. /************************************************************************
  247. * Function : DisplayLine                        *
  248. * Arguments: yval-- position on the screen where line is displayed    *
  249. * Returns  : nothing                            *
  250. * Purpose  : Output a line to the screen positioned at "yval". If     *
  251. *         "numptr->ascii" is non-printable, the line is highlighted    *       
  252. *************************************************************************/
  253. void DisplayLine(yval)
  254. int yval;
  255. {
  256.  char print;
  257.  char *Line();
  258.  put_cursor(1,yval);
  259.  if(!(print = isprint(numptr->ascii)))
  260.    setforecolor3(); 
  261.  printf("%s",Line());
  262.  if(!print)
  263.    set_normal();
  264. }
  265.  
  266. /************************************************************************
  267. * Function : *Line                            *
  268. * Arguments: None                            *
  269. * Returns  : pointer to buffer containing the formatted line        *
  270. * Purpose  : Format a line of information about character         *
  271. *         "numptr->ascii".  This information includes its         *
  272. *          ascii value, hex value, common reference, number of      *
  273. *         occurences and % of total                    *  
  274. *************************************************************************/
  275. char *Line()
  276. {
  277.  static char linebuff[80];
  278.  char tempbuff[20];
  279.  if (numptr->ascii < 33)
  280.    sprintf(tempbuff,"%10s ",key[numptr->ascii]);  /* a more familiar form */
  281.  else if(numptr->ascii > 127 && numptr->ascii < 160)
  282.     sprintf(tempbuff,"           ");
  283.  else
  284.     sprintf(tempbuff,"%-10c ",numptr->ascii);    /* the actual character */
  285.  
  286.  sprintf(linebuff,"  [%3d]    [%3x] %7d  ",numptr->ascii,numptr->ascii,
  287.          numptr->count);
  288.  
  289.  strcat(linebuff,tempbuff);
  290.  
  291.      sprintf(tempbuff,"%6.2f %%",
  292.         (((float)numptr->count)/((float)totalchars))*100.0); 
  293.  strcat(linebuff,tempbuff);
  294.  return(linebuff);
  295.  
  296. /************************************************************************
  297. * Function : DisplayPage                        *
  298. * Arguments: none                            *
  299. * Returns  : nothing                            *
  300. * Purpose  : Handles the screen formatting and display of an entire    *
  301. *            page of lines formatted by *Line().  Also displays     *
  302. *          filename and totalizer information at the bottom        *
  303. *************************************************************************/
  304. void DisplayPage()
  305. {
  306.   extern short pagelen;
  307.   void DisplayLine();
  308.   int j;
  309.   char filnam[29];
  310.  
  311.   for (j=0; j < pagelen; j++)        /* 22 lines per page */
  312.    {
  313.     if (numptr > &num[diffchars-1])    /* if this is the last character */
  314.       erase_eos();            /* get rid of any old junk left  */
  315.     else                 /* from the previous page        */
  316.      {
  317.       DisplayLine(j+1);        /* display the next line */
  318.       printf("\n");
  319.       numptr++;  /* increment pointer to next non-empty charval */
  320.      }
  321.    }
  322.  
  323.     stccpy(filnam,fname,27);         /* Ensure filename will fit on     */
  324.                     /* the last line!        */
  325.     cursor_bot();            
  326.     set_hilite();
  327.     printf(" Page %d of %d ",page,pages);
  328.     printf(" Total: %-6d ",totalchars);
  329.     printf(" Different: %-3d ",diffchars);
  330.     printf(" File: %s ",filnam);
  331.     set_normal();
  332.     page++;
  333.     if (page > pages)
  334.       page = 1;
  335. }
  336.  
  337. /************************************************************************
  338. * Function : Fetch                            *
  339. * Arguments: fh - file handle of file to read                *
  340. * Returns  : a character (int) or EOF                    *
  341. * Purpose  : Performs  buffered low-level file reading, refilling    * 
  342. *         buffer when last character has been "fetched"        *
  343. *         Returns EOF if no more characters in file            *
  344. *************************************************************************/
  345. Fetch(fh)
  346. int fh;                 /*input file handle */
  347. {
  348.   static unsigned char buffer[BUFFSIZE];    /* input buffer */
  349.   static short nextch = BUFFSIZE-1;
  350.   static short lastch = BUFFSIZE-1;
  351.  
  352.   if(++nextch >= lastch)        /* If buffer used up,  */
  353.    {                    /* refill it from file */
  354.      lastch = read(fh,buffer,BUFFSIZE);
  355.      nextch = 0;
  356.    }
  357.  
  358.   if (lastch == 0)            /* EOF, close up shop */
  359.    {
  360.      close(fh);
  361.      return(EOF);
  362.    }
  363.  
  364.   return((int)buffer[nextch]);        /* return next character */
  365. }
  366.  
  367. /************************************************************************
  368. * Function : Usage                            *
  369. * Arguments: none                            *
  370. * Returns  : nothing                            *
  371. * Purpose  : Displays the proper usage format                *
  372. *************************************************************************/
  373. void Usage()
  374. {
  375.   fprintf(stderr,"\x1b[5m");
  376.   fprintf(stderr,"\n\x1b[1;33m  Usage: \x1b[0m");
  377.   fprintf(stderr,"Scan <infile> [outfile] [-s] \x1b[0m\n\n");
  378. }
  379.  
  380. /************************************************************************
  381. * Function : BooBoo                            *
  382. * Arguments: cause - integer for determining the nature of the problem  *
  383. *            string - pointer to a character string for screen output    *
  384. * Returns  : nothing                            *
  385. * Purpose  : Displays an error message in the event of problems parsing *
  386. *         command line arguments or accessing files            *
  387. *************************************************************************/
  388. void BooBoo(cause,string)
  389. int cause;
  390. char *string;
  391. {
  392.   void Usage();
  393.  
  394.   fprintf(stderr,"\n\x1b[33m   Scan: \x1b[32m");
  395.   if (cause == 1)
  396.     fprintf(stderr,"Can't open \"%s\" for input! \n\n", string);
  397.   else if(cause == 2)
  398.     fprintf(stderr,"Can't open \"%s\" for output! \n\n", string);
  399.   else if(cause == 3)
  400.    {
  401.     fprintf(stderr,"Too many file names!\n");
  402.     Usage();
  403.    } 
  404.  fprintf(stderr,"\x1b[0m");
  405.  exit(-cause);
  406. }
  407.  
  408. /************************************************************************
  409. * Function : frequency_sort                        *
  410. * Arguments: two pointers to the items being compared            *
  411. * Purpose  : provides the sorting algorithm for qsort()            *
  412. *************************************************************************/
  413. int frequency_sort(num1,num2)
  414. struct numlist *num1,*num2;
  415. {
  416.  if (num1->count < num2->count)
  417.      return(1);
  418.  else if (num1->count == num2->count)
  419.      return(0);
  420.  else 
  421.      return(-1);
  422. }
  423.