home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / doc / mir / a_bytes.c < prev    next >
Text File  |  1992-07-02  |  12KB  |  367 lines

  1. /*
  2.  *  usage:  a_bytes [ /L ] file_name[s]
  3.  *
  4.  * A_BYTES  Analyze the bytes (characters) used within any file, report
  5.  *          the frequency of each byte present.  If the location flag /L
  6.  *          is set, include offsets of the first 8 occurrences of each
  7.  *          byte pattern present.
  8.  *
  9.  *  input:  Any file[s] whatsoever.
  10.  *
  11.  *  output: file_name.BYT which contains up to 256 lines, one line for
  12.  *          each different byte present.  The byte is shown first in
  13.  *          printable OR octal form, then the hexadecimal equivalent.
  14.  *          The third column is frequency.  The fourth column shows
  15.  *          percentage of total occurrences within the file.
  16.  *
  17.  *          If the /L locations option is selected, the output file is
  18.  *          name file_name.LOC and the offsets of the first up to 8
  19.  *          occurrences follow at the end of each line.
  20.  *
  21.  *  writeup: MIR TUTORIAL ONE, topic 5
  22.  *              Compiled with STACK = 16000
  23.  *
  24.  *  written:    Douglas Lowry   Jan 04 92
  25.  *  modified:   Douglas Lowry   Feb 15 92
  26.  *                              Mar 20 92  Ten alternative report names
  27.  *              Copyright (C) 1992 Marpex Inc.
  28.  *
  29.  *    The MIR (Mass Indexing and Retrieval) Tutorials explain detailed
  30.  *    usage and co-ordination of the MIR family of programs to analyze,
  31.  *    prepare and index databases (small through gigabyte size), and
  32.  *    how to build integrated retrieval software around the MIR search
  33.  *    engine.  The fifth of the five MIR tutorial series explains how
  34.  *    to extend indexing capability into leading edge search-related
  35.  *    technologies.  For more information, GO IBMPRO on CompuServe;
  36.  *    MIR files are in the DBMS library.  The same files are on the
  37.  *    Canada Remote Systems BBS.  A diskette copy of the Introduction
  38.  *    is available by mail ($10 US... check, Visa or Mastercard);
  39.  *    diskettes with Introduction, Tutorial ONE software and the
  40.  *    shareware Tutorial ONE text cost $29.  Shareware registration
  41.  *    for a tutorial is also $29.
  42.  *
  43.  *    E-mail...
  44.  *                Compuserve  71431,1337
  45.  *                Internet    doug.lowry%canrem.com
  46.  *                UUCP        canrem!doug.lowry
  47.  *                Others:     doug.lowry@canrem.uucp
  48.  *
  49.  *    FAX...                  416 963-5677
  50.  *
  51.  *    "Snail mail"...         Douglas Lowry, Ph.D.
  52.  *                            Marpex Inc.
  53.  *                            5334 Yonge Street, #1102
  54.  *                            North York, Ontario
  55.  *                            Canada  M2N 6M2
  56.  *
  57.  *    Related database consultation and preparation services are
  58.  *    available through:
  59.  *              Innotech Inc., 2001 Sheppard Avenue E., Suite #118,
  60.  *              North York, Ontario  Canada   M2J 4Z7
  61.  *              Tel.  416 492-3838   FAX  416 492-3843
  62.  *
  63.  *  This program is free software; you may redistribute it and/or
  64.  *  modify it under the terms of the GNU General Public License as
  65.  *  published by the Free Software Foundation; either version 2 of
  66.  *  the License, or (at your option) any later version.
  67.  *
  68.  *  This program is distributed in the hope that it will be useful,
  69.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  70.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  71.  *  GNU General Public License for more details.
  72.  *
  73.  *  You should have received a copy of the GNU General Public License
  74.  *  (file 05LICENS) along with this program; if not, write to the
  75.  *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  76.  *  USA.
  77.  */
  78.  
  79. #include <stdio.h>
  80. #include <fcntl.h>
  81. #include <sys\types.h>
  82. #include <sys\stat.h>
  83. #include <io.h>
  84.  
  85. #define  repeat  for(;;)
  86.  
  87. typedef     enum bool
  88.     { FALSE = 0, TRUE = 1 }  Bool ;
  89.  
  90. #define     INTAKE      2048    /*  # of bytes in input buffer  */
  91.  
  92.     void    process(), Usage_(), report(), non_exist() ;
  93.     char    *Cmdname_()     { return( "a_bytes" ) ; }
  94.  
  95. /*
  96.  *  MAIN -
  97.  */
  98.  
  99. main( argc, argv )
  100.     int     argc;
  101.     char    **argv;
  102. {
  103.     Bool    foul_up,
  104.             locations ;      /* requested by user            */
  105.     char    c10;             /* argv[1][0]                   */
  106.     int     fd,              /* file descriptor              */
  107.             file, bgn_at ;
  108.     long int     cum[ 256 ], /* accumulator for each byte    */
  109.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  110.  
  111.     locations = FALSE ;
  112.     if( argv[1][1] == 'l' )
  113.         argv[1][1] = 'L' ;
  114.     c10 = argv[1][0] ;
  115.     if(( c10 == '-' || c10 == '/' ) && argv[1][1] == 'L' )
  116.         locations = TRUE ;
  117.     else
  118.     {
  119.         if( argc == 1 || c10 == '-' || c10 == '/' || c10 == '?' )
  120.             Usage_();
  121.     }
  122.  
  123.     bgn_at = 1 ;
  124.     if( locations )
  125.         bgn_at = 2 ;
  126.  
  127.     for( file = bgn_at ; file < argc ; file++ )
  128.     {
  129.         if(( fd = open( argv[ file ], O_RDONLY | O_BINARY )) == -1 )
  130.         {
  131.             fprintf( stderr, "Can't open file %s\n", argv[ file ] );
  132.             exit( 1 );
  133.         }
  134.  
  135.         process( fd, cum, locn, locations );
  136.  
  137.         report( cum, locn, locations, argv[file] ) ;
  138.  
  139.         if( close( fd ))
  140.             fprintf( stderr, "Problem closing %s\n", argv[ file ] );
  141.     }
  142.  
  143.     exit( 0 );
  144. }
  145.     void
  146. Usage_()
  147. {
  148.     fprintf( stderr, "\nusage:  %s [ /L ] file_name[s]\n\n\
  149.         Analyze the bytes (characters) used within any file, report\n\
  150.         the frequency of each byte present.  If the location flag /L\n\
  151.         is set, include offsets of the first 8 occurrences of each\n",
  152.                 Cmdname_() );
  153.     fprintf( stderr, "        byte pattern present.\n\n\
  154. input:  Any file[s] whatsoever.\n\n\
  155. output: file_name.BYT which contains up to 256 lines, one line for\n\
  156.         each different byte present.  The byte is shown first in\n\
  157.         printable OR octal form, then the hexadecimal equivalent.\n" );
  158.     fprintf( stderr,
  159. "        The third column is frequency.  The fourth column shows\n\
  160.         percentage of total occurrences within the file.\n\n\
  161.         If the /L locations option is selected, the output file is\n\
  162.         name file_name.LOC and the offsets of the first up to 8\n\
  163.         occurrences follow at the end of each line.\n\n" ) ;
  164.     fprintf( stderr, "writeup: MIR TUTORIAL ONE, topic 5\n\n" );
  165.     exit( 1 ) ;
  166. }
  167. /*
  168.  *  PROCESS
  169.  */
  170.     void
  171. process( fd, cum, locn, locations )
  172.     int fd;                  /*  file descriptor     */
  173.     long int     cum[ 256 ], /*  accumulator for each byte   */
  174.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  175.     Bool    locations ;      /*  TRUE if selected by user    */
  176. {
  177.     unsigned char   buf_in[ INTAKE ];
  178.     register int    buf_len,
  179.             i;
  180.     long int     gross_locn,     /*  count of cumulative intakes */
  181.             fine_locn,
  182.             ct ;
  183.  
  184.     for( i = 0; i < 256 ; i++ )
  185.         cum[ i ] = 0;
  186.     gross_locn = 0 ;
  187.  
  188.     repeat
  189.     {
  190.         fine_locn = 0 ;
  191.         if ( ( buf_len = read( fd, buf_in, INTAKE ) ) == 0 )
  192.             break;
  193.  
  194.         for ( i= 0 ; i < buf_len ; i++ )
  195.         {
  196.             cum[ buf_in[ i ] ]++ ;
  197.             if( locations && cum[ buf_in[ i ] ] < 9 )
  198.             {
  199.                 ct = cum[ buf_in[ i ] ] - 1 ;
  200.                 locn[ buf_in [ i ] ][ ct ] = gross_locn + fine_locn ;
  201.             }
  202.             fine_locn++ ;
  203.         }
  204.  
  205.         gross_locn += buf_len ;
  206.     }
  207.  
  208.     return;
  209. }
  210. /*
  211.  *  REPORT - Output the data for analysis of one file
  212.  */
  213.     void
  214. report( cum, locn, locations, name_in )
  215.     long int     cum[ 256 ], /* accumulator for each byte    */
  216.             locn[ 256 ][ 8 ];  /*  offset of 8 occurrences of each */
  217.     Bool    locations ;      /*  TRUE if selected by user    */
  218.     char    name_in[] ;
  219. {
  220.     FILE    *fp_out ;
  221.     char    fname[20];
  222.     unsigned char   c;
  223.     double  pct,             /* % of occurrences             */
  224.             f_grand;         /* grand total bytes            */
  225.     Bool    foul_up ;
  226.     int     result,
  227.             len, i, j ;
  228.     long int   grand_total,
  229.             limit;           /*  up to 8 are tracked   */
  230.  
  231.     if( locations )
  232.         sprintf( fname, "%s.loc", name_in );
  233.     else
  234.         sprintf( fname, "%s.byt", name_in );
  235.     len = strlen( fname ) ;
  236.     for( i = 0 ; i < len ; i++ )
  237.     {
  238.         if( fname[i] == '.' )
  239.         {
  240.             if( i != len - 3 )
  241.             {
  242.                 if( locations )
  243.                     strncpy( &fname[i+1], "loc", 3 );
  244.                 else
  245.                     strncpy( &fname[i+1], "byt", 3 );
  246.             }
  247.             fname[i+4] = '\0' ;
  248.             break ;
  249.         }
  250.     }
  251.  
  252.     non_exist( fname ) ;
  253.  
  254.     if(( fp_out = fopen( fname, "w" )) == NULL )
  255.     {
  256.         fprintf( stderr, "Can't open file %s\n", fname );
  257.         return ;
  258.     }
  259.  
  260.     grand_total = 0;
  261.     foul_up = FALSE ;
  262.     for( i = 0; i < 256 ; i++ )
  263.         grand_total += cum[ i ];
  264.     f_grand = ( double ) grand_total ;
  265.  
  266.     for( i = 0; i < 256 ; i++ )
  267.     {
  268.         if( cum[ i ] )
  269.         {
  270.             c = ( unsigned char ) i;
  271.             pct = 100.0 * ( ( double ) cum[ i ] / f_grand ) ;
  272.  
  273.                 /*  For Unix version, next line should read
  274.                 if( i < 0x21 || i > 0x7e )          */
  275.  
  276.             if( i < 0x21 || i == 0x7f || i == 0xff )
  277.             {
  278.                 if( !fprintf( fp_out, "\\%03o [%02X]%7ld  %4.1f%%",
  279.                             i, i, cum[ i ], pct ) )
  280.                     foul_up = TRUE ;
  281.             }
  282.             else
  283.             {
  284.                 if( !fprintf( fp_out, "%c    [%02X]%7ld  %4.1f%%",
  285.                             c, i, cum[ i ], pct ))
  286.                     foul_up = TRUE ;
  287.             }
  288.             if( locations )
  289.             {
  290.                 fputc( ' ', fp_out );
  291.                 fputc( ' ', fp_out );
  292.                 limit = 8;
  293.                 if( cum[i] < 8 )
  294.                     limit = cum[i] ;
  295.                 for( j = 0 ; j < limit ; j++ )
  296.                     fprintf( fp_out, " %ld", locn[ i ][ j ] );
  297.             }
  298.             fputc( '\n', fp_out );
  299.         }
  300.     }
  301.  
  302.     if( foul_up )
  303.         fprintf( stderr, "Unable to write report in file %s\n", fname );
  304.     else
  305.         fprintf( stderr,
  306.             "\n\nInput size = %ld bytes.  Results are in file %s\n\n",
  307.                 grand_total, fname );
  308.     if( fclose( fp_out ))
  309.         fprintf( stderr, "Problem closing %s\n", fname );
  310.  
  311.     return ;
  312. }
  313. /*
  314.  *  NON_EXIST   Test the existence of a file; if it exists,
  315.  *              substitute digits successively for the last
  316.  *              byte in the name until a non-existent file
  317.  *              is named, or until the last digit is '9'; do
  318.  *              the same with the second last byte, for 100
  319.  *              possible combinations
  320.  */
  321.     void
  322. non_exist( fname )
  323.     char    fname[] ;
  324. {
  325.     struct  stat    buf;
  326.     Bool            gotcha ;
  327.     int             result,
  328.                     decade,     /*  batch of 10 names   */
  329.                     len, i ;
  330.  
  331.     result = stat( fname, &buf );
  332.     if( !result )  /*  data obtained = that file exists */
  333.     {
  334.         len = strlen( fname ) ;
  335.  
  336.         for( decade = 0 ; decade < 10 ; decade++ )
  337.         {
  338.             gotcha = FALSE ;
  339.             if( decade )
  340.             {
  341.                 if( fname[len-2] == '.' )
  342.                     break ;     /*  Don't mess with one digit
  343.                                     name extension              */
  344.                 fname[ len - 2 ] = '0' + decade ;
  345.             }
  346.             fname[ len - 1 ] = '0' ;
  347.  
  348.             /*  Try names ending in 0 through 9     */
  349.  
  350.             for( i = 0 ; i < 10 ; i++ )
  351.             {
  352.                 result = stat( fname, &buf );
  353.                 if( result )
  354.                 {
  355.                     gotcha = TRUE ;
  356.                     break ;
  357.                 }
  358.                 if( i < 9 )
  359.                     fname[ len - 1 ] += 1 ;
  360.             }
  361.             if( gotcha )
  362.                 break ;
  363.         }
  364.  
  365.     }
  366.     return ;
  367. }