home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / doc / mir / a_len.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-02  |  12.0 KB  |  377 lines

  1. /*
  2.  *  usage:  a_len [interval] file_name[s]
  3.  *
  4.  * A_LEN    Analyze the distribution of line lengths up to 1024 bytes
  5.  *          within any file.  The reporting interval (an integer from
  6.  *          1 to 100) is a count of the lengths that will be grouped
  7.  *          together.  For example, an interval of 10 means that
  8.  *          frequencies of length 0, length 1-10, length 11-20, etc.
  9.  *          are shown in the report.  The default interval is 10.  If
  10.  *          the first file name starts with numeric digits, show the
  11.  *          interval first!
  12.  *
  13.  *  input:  Any ASCII file[s].
  14.  *
  15.  *  output: file_name.len which reports the frequency of line lengths
  16.  *          occuring in the file.  Lengths exclude carriage returns and
  17.  *          line feeds.
  18.  *
  19.  *  writeup: MIR TUTORIAL ONE, topic 6
  20.  *
  21.  *  written:    Douglas Lowry   Feb 13 92
  22.  *  modified:   Douglas Lowry   Feb 14 92
  23.  *              Douglas Lowry   Mar 20 92  Cycle thru report names
  24.  *              Copyright (C) 1992 Marpex Inc.
  25.  *              Compiled with STACK = 8000
  26.  *  NOTE THE PROGRAM COMPILES MUCH SMALLER (10,000 INSTEAD OF 19,200 BYTES)
  27.  *  IF THE USE OF DOUBLE TYPE IS OMITTED IN THE "REPORT" FUNCTION.
  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 <sys\types.h>
  81. #include <sys\stat.h>
  82.  
  83. #define  repeat  for(;;)
  84.  
  85. typedef     enum bool
  86.     { FALSE = 0, TRUE = 1 }  Bool ;
  87.  
  88. #define     MAX_BYTES      2048    /*  # of bytes in input buffer  */
  89.  
  90.     void    process(), Usage_(), report(), non_exist() ;
  91.     char    *Cmdname_()     { return( "a_len" ) ; }
  92.  
  93. /*
  94.  *  MAIN -
  95.  */
  96.  
  97. main( argc, argv )
  98.     int     argc;
  99.     char    **argv;
  100. {
  101.     FILE    *fp, *fp_out;
  102.     char    fname[20],
  103.             c10 ;
  104.     int     interval,        /* argument 1 - 100             */
  105.             from,            /* argument # of first file name*/
  106.             file, len, i ;
  107.     long int     cum[ 1026 ]; /* accumulator for each byte    */
  108.                     /*  Those over 1024 are counted in [1025] */
  109.  
  110.     c10 = argv[1][0] ;
  111.     if( argc < 2 || c10 == '-' || c10 == '/' || c10 == '?' )
  112.         Usage_();
  113.  
  114.     interval = 10 ;
  115.     from = 1 ;
  116.     i = atoi( argv[1] ) ;
  117.     if( i > 0 && i < 101 )
  118.     {
  119.         interval = i ;
  120.         from = 2 ;
  121.     }
  122.     else if( i > 100 )
  123.         Usage_() ;
  124.  
  125.     for( file = from; file < argc ; file++ )
  126.     {
  127.         if(( fp = fopen( argv[ file ], "r+b" )) == NULL )
  128.         {
  129.             fprintf( stderr, "Can't open file %s\n", argv[ file ] );
  130.             exit( 1 );
  131.         }
  132.         process( fp, cum );
  133.         if( fclose( fp ))
  134.             fprintf( stderr, "Problem closing %s\n", argv[ file ] );
  135.  
  136.         sprintf( fname, "%s.len", argv[ file ] );
  137.         len = strlen( fname ) ;
  138.         for( i = 0 ; i < len ; i++ )
  139.         {
  140.             if( fname[i] == '.' )
  141.             {
  142.                 if( i != len - 3 )
  143.                     strncpy( &fname[i+1], "len", 3 );
  144.                 fname[i+4] = '\0' ;
  145.                 break ;
  146.             }
  147.         }
  148.  
  149.         non_exist( fname ) ;
  150.         if(( fp_out = fopen( fname, "w" )) == NULL )
  151.         {
  152.             fprintf( stderr, "Can't open file %s\n", fname );
  153.             exit( 1 );
  154.         }
  155.  
  156.         report( fp_out, cum, interval, fname ) ;
  157.  
  158.         if( fclose( fp_out ))
  159.             fprintf( stderr, "Problem closing %s\n", fname );
  160.     }
  161.  
  162.     exit( 0 );
  163. }
  164.     void
  165. Usage_()
  166. {
  167.     fprintf( stderr, "\nusage:  %s [interval] file_name[s]\n\n\
  168.         Analyze the distribution of line lengths up to 1024 bytes\n\
  169.         within any file.  The reporting interval (an integer from\n\
  170.         1 to 100) is a count of the lengths that will be grouped\n",
  171.             Cmdname_() );
  172.     fprintf( stderr,
  173. "        together.  For example, an interval of 10 means that\n\
  174.         frequencies of length 0, length 1-10, length 11-20, etc.\n\
  175.         are shown in the report.  The default interval is 10.  If\n\
  176.         the first file name starts with numeric digits, show the\n" );
  177.     fprintf( stderr,
  178. "        interval first!\n\n\
  179. input:  Any ASCII file[s].\n\n\
  180. output: file_name.len which reports the frequency of line lengths\n\
  181.         occuring in the file.  Lengths exclude carriage returns and\n\
  182.         line feeds.\n\n\
  183. writeup: MIR TUTORIAL ONE, topic 6\n\n" ) ;
  184.     exit( 1 ) ;
  185. }
  186. /*
  187.  *  PROCESS
  188.  */
  189.     void
  190. process( fp, cum )
  191.     FILE    *fp ;
  192.     long int     cum[ 1026 ]; /*  accumulator for each length   */
  193. {
  194.     char    line_in[ MAX_BYTES ] ;
  195.     int len, i ;
  196.     Bool    after_nl;   /*  after a new line        */
  197.  
  198.     for( i = 0 ; i < 1026 ; i++ )
  199.         cum[ i ] = 0 ;
  200.  
  201.     while( fgets( line_in, MAX_BYTES, fp ) != NULL )
  202.     {
  203.         len = strlen( line_in );
  204.         while( line_in[ len-1 ] == '\n' || line_in[ len-1 ] == '\015' )
  205.             len-- ;
  206.         if( len > MAX_BYTES - 4 )
  207.         {
  208.             fprintf( stderr, "FATAL... Line exceeds %d bytes.\n\n",
  209.                 len );
  210.             exit( 1 );
  211.         }
  212.         if( len > 1024 )
  213.             cum[ 1025 ]++ ;
  214.         else
  215.             cum[ len ]++ ;
  216.     }
  217.  
  218.     return;
  219. }
  220. /*
  221.  *  REPORT - Write the analysis
  222.  */
  223.     void
  224. report( fp_out, cum, interval, fname )
  225.     FILE    *fp_out ;
  226.     long int     cum[ 1026 ]; /* accumulator for each byte    */
  227.                     /*  Those over 1024 are counted in [1025] */
  228.     int     interval;        /* argument 1 - 100              */
  229.     char    fname[20];
  230. {
  231.     Bool        foul_up ;
  232.     double      pct,
  233.                 d_lines ;        /*  count of lines              */
  234.     long int    group_cum,       /*  frequency across interval   */
  235.                 lines ;
  236.     int         pt, i,
  237.                 low, high;       /* ends of interval             */
  238.  
  239.     foul_up = FALSE ;
  240.     lines = 0 ;
  241.     for( i = 0 ; i < 1026 ; i++ )
  242.         lines += cum[ i ] ;
  243.     d_lines = ( double ) lines ;
  244.  
  245.     if( interval == 1 )
  246.     {
  247.         if( cum[0] )
  248.         {
  249.             pct = 100.0 * (( double ) cum[0] / d_lines ) ;
  250.             fprintf( fp_out, "    0:%7ld  %4.1f%%\n", cum[0], pct ) ;
  251.         }
  252.  
  253.         for( pt = 1 ; pt < 1025 ; pt++ )
  254.         {
  255.             if( cum[ pt ] )
  256.             {
  257.                 pct = 100.0 * (( double ) cum[ pt ] / d_lines ) ;
  258.                 if( !fprintf( fp_out, " %4d:%7ld  %4.1f%%\n", pt, cum[pt],
  259.                             pct ))
  260.                 {
  261.                     foul_up = TRUE ;
  262.                     break ;
  263.                 }
  264.             }
  265.         }
  266.         if( cum[1025] )
  267.         {
  268.             pct = 100.0 * (( double ) cum[ 1025 ] / d_lines ) ;
  269.             fprintf( fp_out, "1025+:%7ld  %4.1f%%\n", cum[1025] ) ;
  270.         }
  271.     }
  272.     else    /*  wider interval      */
  273.     {
  274.         if( cum[0] )
  275.         {
  276.             pct = 100.0 * (( double ) cum[0] / d_lines ) ;
  277.             fprintf( fp_out, "         0:%7ld  %4.1f%%\n", cum[0], pct ) ;
  278.         }
  279.  
  280.         for( pt = 1 ; pt < 1025 ; pt++ )
  281.         {
  282.             low = pt ;
  283.             group_cum = 0 ;
  284.             for( i = 0 ; i < interval ; i++ )
  285.             {
  286.                 group_cum += cum[ pt++ ] ;
  287.                 if( pt > 1024 )
  288.                     break ;
  289.             }
  290.             high = pt - 1 ;
  291.             pt = high ;
  292.             if( group_cum )
  293.             {
  294.                 pct = 100.0 * (( double ) group_cum / d_lines ) ;
  295.                 if( !fprintf( fp_out, "%4d -%4d:%7ld  %4.1f%%\n", low,
  296.                         high, group_cum, pct ))
  297.                     foul_up = TRUE ;
  298.             }
  299.             if( foul_up )
  300.                 break ;
  301.         }
  302.  
  303.         if( group_cum )
  304.         {
  305.             pct = 100.0 * (( double ) group_cum / d_lines ) ;
  306.             fprintf( fp_out, "%4d -1024:%7ld  %4.1f%%\n", group_cum, pct );
  307.         }
  308.         if( cum[1025] )
  309.         {
  310.             pct = 100.0 * (( double ) cum[1025] / d_lines ) ;
  311.             fprintf( fp_out, " Over 1024:%7ld  %4.1f%%\n", cum[1025],pct );
  312.         }
  313.     }
  314.  
  315.     if( foul_up )
  316.         fprintf( stderr, "Unable to write report in file %s\n", fname );
  317.     else
  318.         fprintf( stderr, "\n%ld lines reported in file %s\n\n", lines,
  319.                     fname );
  320.  
  321.     return ;
  322. }
  323. /*
  324.  *  NON_EXIST   Test the existence of a file; if it exists,
  325.  *              substitute digits successively for the last
  326.  *              byte in the name until a non-existent file
  327.  *              is named, or until the last digit is '9'; do
  328.  *              the same with the second last byte, for 100
  329.  *              possible combinations
  330.  */
  331.     void
  332. non_exist( fname )
  333.     char    fname[] ;
  334. {
  335.     struct  stat    buf;
  336.     Bool            gotcha ;
  337.     int             result,
  338.                     decade,     /*  batch of 10 names   */
  339.                     len, i ;
  340.  
  341.     result = stat( fname, &buf );
  342.     if( !result )  /*  data obtained = that file exists */
  343.     {
  344.         len = strlen( fname ) ;
  345.  
  346.         for( decade = 0 ; decade < 10 ; decade++ )
  347.         {
  348.             gotcha = FALSE ;
  349.             if( decade )
  350.             {
  351.                 if( fname[len-2] == '.' )
  352.                     break ;     /*  Don't mess with one digit
  353.                                     name extension              */
  354.                 fname[ len - 2 ] = '0' + decade ;
  355.             }
  356.             fname[ len - 1 ] = '0' ;
  357.  
  358.             /*  Try names ending in 0 through 9     */
  359.  
  360.             for( i = 0 ; i < 10 ; i++ )
  361.             {
  362.                 result = stat( fname, &buf );
  363.                 if( result )
  364.                 {
  365.                     gotcha = TRUE ;
  366.                     break ;
  367.                 }
  368.                 if( i < 9 )
  369.                     fname[ len - 1 ] += 1 ;
  370.             }
  371.             if( gotcha )
  372.                 break ;
  373.         }
  374.  
  375.     }
  376.     return ;
  377. }