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

  1. /*
  2.  *  usage:  a_pattrn  file_name  key  [ /x ] [ bytes_before ] > report
  3.  *              "/x" = include hex, show only 16 bytes instead of 40
  4.  * A_PATTRN List every occurrence of a key character or string in a file.
  5.  *          Show 3 (or "bytes_before", range 0 to 15) bytes prior to the
  6.  *          key each time.  Normally show a total of 40 bytes each time
  7.  *          the key is found; if the "/x" argument is set, show only 16
  8.  *          bytes, but in hex and ASCII both.  The key may be from 1 to
  9.  *          16 characters.  Within the key, any non-printing characters,
  10.  *          characters which may confuse DOS (> or < or |), linefeeds,
  11.  *          blanks, backslash, etc. must be shown in hex form...  a
  12.  *          backslash and 2 hex digits.  Examples:
  13.  *              a_pattrn herfile  \8E  >  herfile.8e
  14.  *              a_pattrn yourfile  *  7  >  yourfile.ast
  15.  *              a_pattrn myfile  Mother
  16.  *              a_pattrn hisfile  \94\05ke\ff  0  >  5char.pat
  17.  *
  18.  *  input:  Any file whatsoever.
  19.  *
  20.  *  output: One line for each occurrence of the target byte(s) in the file.
  21.  *          Sort the result to make patterns show up more clearly.
  22.  *
  23.  *  writeup: MIR TUTORIAL ONE, topic 5
  24.  *
  25.  *  Written:    Douglas Lowry    Jan 07 92
  26.  *  Modified:   Douglas Lowry    Apr 03 92  Modify arguments
  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 <stdlib.h>
  81. #include <dos.h>
  82. #include <ctype.h>
  83. #include <direct.h>
  84.  
  85. #define  BIGBUF     2048
  86. #define  repeat     for(;;)
  87.  
  88. typedef     enum    _bool
  89.         { FALSE = 0, TRUE = 1 } Bool ;
  90. /*
  91.  *  declarations
  92.  */
  93.  
  94.     void    process( ), Usage_( ), line_out( );
  95.     unsigned long int   xtol_n( );
  96.     char    *Cmdname_()     { return( "a_pattrn" ) ;    }
  97.  
  98. /*
  99.  *  MAIN -
  100.  */
  101.  
  102. main( argc, argv )
  103.     int argc;
  104.     char    **argv;
  105. {
  106.     FILE                *fp_in ;
  107.     Bool                ascii ;     /*  ASCII display only requested */
  108.     int                 len, i ;
  109.     unsigned long int   l_test ;
  110.     unsigned char       key[16];    /*  character requested by user  */
  111.     short int           precede,    /*  bytes before key to be shown */
  112.                         key_len,
  113.                         pt ;        /*  pointer within "key" argument*/
  114.  
  115. /*  usage:  a_pattrn  file_name  key  [ -x ] [ bytes_before ] > report*/
  116.  
  117.     if( argc < 3 || argc > 5 )
  118.         Usage_();
  119.  
  120.     if(( fp_in = fopen( argv[1], "r+b" )) == NULL )
  121.     {
  122.         fprintf( stderr, "Unable to open input file %s\n", argv[1] );
  123.         Usage_() ;
  124.     }
  125.  
  126.     pt = 0 ;
  127.     for( key_len = 0 ; key_len < 16 ; key_len++ )
  128.     {
  129.         if( !argv[2][pt] )
  130.             break ;
  131.         if( argv[2][pt] != 0x5c )    /*  not backslash = printable */
  132.         {
  133.             key[ key_len ] = ( unsigned char ) argv[2][pt] ;
  134.             pt++ ;
  135.         }
  136.         else
  137.         {
  138.             l_test = xtol_n( &argv[2][pt+1], 2 ) ;
  139.             if( l_test > 0xff )
  140.                 Usage_();
  141.             key[ key_len ] = ( unsigned char ) l_test ;
  142.             pt += 3 ;
  143.         }
  144.     }
  145.  
  146.     precede = 3 ;
  147.     ascii = TRUE ;
  148.  
  149.     for( i = 3; i < argc ; i++ )
  150.     {
  151.         if( islower( argv[i][1] ))
  152.             argv[i][1] = toupper( argv[i][1] ) ;
  153.         if( argv[i][1] == 'X' && ( argv[i][0] == '/' || argv[i][0] == '-' ))
  154.             ascii = FALSE ;
  155.         else
  156.         {
  157.             precede = atoi( argv[i] );
  158.             if( precede > 16 - key_len )
  159.                 precede = 16 - key_len ;
  160.             if( precede < 0 )
  161.                 precede = 0 ;
  162.         }
  163.     }
  164.  
  165.     process( key, key_len, ascii, precede, fp_in );
  166.  
  167.     fclose( fp_in );
  168.  
  169.     exit( 0 );
  170. }
  171.     void
  172. Usage_( )
  173. {
  174.     fprintf( stderr,
  175.         "usage:  %s file_name  key  [ /x ] [ bytes_before ] > report\n\
  176.              \"/x\" = include hex, show only 16 bytes instead of 40\n\
  177.         List every occurrence of a key character or string in a file.\n\
  178.         Show 3 (or \"bytes_before\", range 0 to 15) bytes prior to the\n",
  179.                 Cmdname_() );
  180.     fprintf( stderr,
  181. "        key each time.  Normally show a total of 40 bytes each time\n\
  182.         the key is found; if the \"/x\" argument is set, show only 16\n\
  183.         bytes, but in hex and ASCII both.  The key may be from 1 to\n\
  184.         16 characters.  Within the key, any non-printing characters,\n" );
  185.     fprintf( stderr,
  186. "        characters which may confuse DOS (> or < or |), linefeeds,\n\
  187.         blanks, backslash, etc. must be shown in hex form...  a\n\
  188.         backslash and 2 hex digits.  Examples:\n\
  189.             a_pattrn herfile  \8E  >  herfile.8e\n\
  190.             a_pattrn yourfile  *  7  >  yourfile.ast\n" ) ;
  191.     fprintf( stderr,
  192. "            a_pattrn myfile  Mother\n\
  193.             a_pattrn hisfile  \\94\\05ke\\ff  0  >  5char.pat\n\n\
  194. input:  Any file whatsoever.\n\n\
  195. output: One line for each occurrence of the target byte(s) in the file.\n\
  196.         Sort the result to make patterns show up more clearly.\n\n\
  197. writeup: MIR TUTORIAL ONE, topic 5\n" ) ;
  198.     exit( 1 );
  199. }
  200. /*
  201.  *  XTOL_N  Converts a specified number of bytes of hexadecimal string
  202.  *          to unsigned long integer.  Returns 0xffffffff if any
  203.  *          non-hex character is encountered within the byte count,
  204.  *          or if the byte count exceeds 8.
  205.  */
  206.     unsigned long int
  207. xtol_n( string, bytes )
  208.     unsigned char   string[] ;
  209.     short int       bytes ;
  210. {
  211.     int     pt ;
  212.     unsigned long int   test_l ;        /*  value of hex expression */
  213.     unsigned char       this_hex,       /*  value of one character  */
  214.                         uc ;
  215.  
  216.     if( !bytes )
  217.         return( 0 ) ;
  218.     if( bytes > 8 )
  219.         return( 0xffffffff );
  220.  
  221.     test_l = 0 ;
  222.     for( pt = 0 ; pt < bytes ; pt++ )
  223.     {
  224.         if( !isxdigit( string[ pt ] ))
  225.             return( 0xffffffff );
  226.         uc = ( unsigned char ) string[ pt ] ;
  227.         if( isdigit( uc ))
  228.             this_hex = uc - ( unsigned char ) '0' ;
  229.         else if( isupper( uc ))
  230.             this_hex = uc - ( unsigned char ) 'A' + 10 ;
  231.         else
  232.             this_hex = uc - ( unsigned char ) 'a' + 10 ;
  233.         test_l = ( test_l << 4 ) + ( unsigned long ) this_hex ;
  234.     }
  235.  
  236.     return( test_l );
  237. }
  238. /*
  239.  *  PROCESS -   Passes through 1 file looking for key, outputting
  240.  *      [preceding and] following characters when found.
  241.  */
  242.  
  243.     void
  244. process( key, key_len, ascii, precede, fp_in )
  245.     unsigned char       key[16];    /*  characters requested by user  */
  246.     short int           key_len,
  247.                         precede;    /*  bytes before key to be shown  */
  248.     Bool                ascii ;     /*  40 bytes ASCII, no hex display*/
  249.     FILE                *fp_in ;
  250. {
  251.     unsigned char       buffer[ BIGBUF ];
  252.     Bool                need_data,
  253.                         good_key ;  /*  found a match                */
  254.     long int            cum_byt;    /*  cumulative bytes into file   */
  255.     int                 length,     /*  of buffer contents           */
  256.                         pt,         /*  current byte in buffer       */
  257.                         display,    /*  16 or 40 bytes long          */
  258.                         adjust,
  259.                         i, j, pt2 ;
  260.  
  261.     cum_byt = adjust = 0;
  262.     need_data = TRUE ;
  263.     display = 16 ;
  264.     if( ascii )
  265.         display = 40 ;
  266.  
  267.     repeat
  268.     {
  269.         if( need_data )
  270.         {
  271.             length = fread( &buffer[ adjust ], sizeof( char ),
  272.                 ( BIGBUF - adjust ), fp_in );
  273.             length += adjust;
  274.             if( !length )
  275.                 break ;
  276.             if( adjust )
  277.                 pt = precede;
  278.             else
  279.                 pt = 0 ;
  280.             adjust = 0 ;
  281.             need_data = FALSE ;
  282.  
  283.             /*  After the end of last buffer in the file, */
  284.             /*  reduce any trailing bytes to NULLs.       */
  285.  
  286.             if( length < BIGBUF )
  287.             {
  288.                 for( i= length, j= 0 ; ( i < BIGBUF && j < display ) ;
  289.                                                             i++, j++ )
  290.                     buffer[i] = '\0' ;
  291.             }
  292.         }
  293.  
  294.         if( length < BIGBUF && pt == length )
  295.             break ;         /*  Normal exit         */
  296.  
  297.         if( pt + display + 1 > length && length == BIGBUF )
  298.         {
  299.             for( adjust = 0, j = pt - precede ; j < length ; j++, 
  300.                             adjust++ )
  301.                 buffer[ adjust ] = buffer[ j ] ;
  302.             need_data = TRUE ;
  303.             continue ;
  304.         }
  305.  
  306.         if( buffer[pt] != key[0] )
  307.         {
  308.             pt++ ;
  309.             cum_byt++ ;
  310.             continue;       /*  the most typical action */
  311.         }
  312.  
  313.         good_key = TRUE ;
  314.         for( pt2 = pt + 1, i = 1 ; i < key_len ; pt2++, i++ )
  315.         {
  316.             if( buffer[pt2] != key[i] )
  317.             {
  318.                 good_key = FALSE ;
  319.                 break ;
  320.             }
  321.         }
  322.         if( good_key )
  323.             line_out( cum_byt, &buffer[ pt - precede ], ascii ) ;
  324.         pt++ ;
  325.         cum_byt++ ;
  326.     }
  327.     return;
  328. }
  329. /*
  330.  *  LINE_OUT    Output an offset followed by 16 bytes, first in
  331.  *              hexadecimal, then in printable form, with periods
  332.  *              substituting for non-printable characters.  Where
  333.  *              ASCII only is requested, 40 bytes are output.
  334.  */
  335.     void
  336. line_out( offset, buf, ascii )
  337.     long int        offset ;
  338.     unsigned char   *buf ;
  339.     Bool            ascii ;
  340. {
  341.     int         display,
  342.                 i ;
  343.  
  344.     display = 16 ;
  345.     if( ascii )
  346.         display = 40 ;
  347.  
  348.     printf( "%08ld: ", offset );
  349.     if( !ascii )
  350.     {
  351.         for( i = 0 ; i < 16 ; i++ )
  352.             printf( "%02x ", buf[ i ] );
  353.     }
  354.     printf( "   " );
  355.     for( i = 0 ; i < display ; i++ )
  356.     {
  357.         if( isprint( buf[i] ))
  358.             putchar( buf[i] );
  359.         else
  360.             putchar( '.' );
  361.     }
  362.  
  363.     /*  If we test the output once per line, */
  364.     /*  that will catch any write errors.    */
  365.  
  366.     if( putchar( '\n' ) != '\n' )
  367.     {
  368.         fprintf( stderr, "FATAL... Unable to write output.\n\n" );
  369.         exit( 1 );
  370.     }
  371.  
  372.     return ;
  373. }
  374.