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

  1. /*
  2.  *  Usage - head  file_name [ line_count ] [/a][/t] > text
  3.  *
  4.  *  HEAD    Displays in printable format the first line_count lines
  5.  *          within a file; the default is 10 lines.  This clone of
  6.  *          the UNIX HEAD and TAIL utilities provides a quick check on
  7.  *          the likely contents of a file.  If the "/a" option is used,
  8.  *          accented characters are treated as printable text.  If
  9.  *          "/t" is specified, the display is of the TAIL of the
  10.  *          file, the LAST line_count lines.
  11.  *
  12.  *  input:  Normally an ASCII text file.
  13.  *
  14.  *  output: The specified number of lines is either displayed on the
  15.  *          screen or sent to a file.  Each non-printable character is
  16.  *          replaced by an ^ symbol.  If any line length exceeds 120
  17.  *          characters, a warning is issued.  If any line length exceeds
  18.  *          1024 or the file includes null bytes, the program advises
  19.  *          that the target file is not ASCII text.
  20.  *
  21.  *  writeup: MIR TUTORIAL ONE, topic 5
  22.  *
  23.  *  Written:    Douglas Lowry   Jan 10 92
  24.  *  Modified:   Douglas Lowry   May 11 92  Correct re small files
  25.  *              Copyright (C) 1992 Marpex Inc.
  26.  *
  27.  *    The MIR (Mass Indexing and Retrieval) Tutorials explain detailed
  28.  *    usage and co-ordination of the MIR family of programs to analyze,
  29.  *    prepare and index databases (small through gigabyte size), and
  30.  *    how to build integrated retrieval software around the MIR search
  31.  *    engine.  The fifth of the five MIR tutorial series explains how
  32.  *    to extend indexing capability into leading edge search-related
  33.  *    technologies.  For more information, GO IBMPRO on CompuServe;
  34.  *    MIR files are in the DBMS library.  The same files are on the
  35.  *    Canada Remote Systems BBS.  A diskette copy of the Introduction
  36.  *    is available by mail ($10 US... check, Visa or Mastercard);
  37.  *    diskettes with Introduction, Tutorial ONE software and the
  38.  *    shareware Tutorial ONE text cost $29.  Shareware registration
  39.  *    for a tutorial is also $29.
  40.  *
  41.  *    E-mail...
  42.  *                Compuserve  71431,1337
  43.  *                Internet    doug.lowry%canrem.com
  44.  *                UUCP        canrem!doug.lowry
  45.  *                Others:     doug.lowry@canrem.uucp
  46.  *
  47.  *    FAX...                  416 963-5677
  48.  *
  49.  *    "Snail mail"...         Douglas Lowry, Ph.D.
  50.  *                            Marpex Inc.
  51.  *                            5334 Yonge Street, #1102
  52.  *                            North York, Ontario
  53.  *                            Canada  M2N 6M2
  54.  *
  55.  *    Related database consultation and preparation services are
  56.  *    available through:
  57.  *              Innotech Inc., 2001 Sheppard Avenue E., Suite #118,
  58.  *              North York, Ontario  Canada   M2J 4Z7
  59.  *              Tel.  416 492-3838   FAX  416 492-3843
  60.  *
  61.  *  This program is free software; you may redistribute it and/or
  62.  *  modify it under the terms of the GNU General Public License as
  63.  *  published by the Free Software Foundation; either version 2 of
  64.  *  the License, or (at your option) any later version.
  65.  *
  66.  *  This program is distributed in the hope that it will be useful,
  67.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  68.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  69.  *  GNU General Public License for more details.
  70.  *
  71.  *  You should have received a copy of the GNU General Public
  72.  *  License (file 05LICENS) along with this program; if not,
  73.  *  write to the Free Software Foundation, Inc., 675 Mass Ave,
  74.  *  Cambridge, MA 02139, USA.
  75.  */
  76.  
  77. #include <stdio.h>
  78. #include <ctype.h>
  79. #include <io.h>
  80.  
  81. #define     MAX_BYTES   1024
  82.  
  83. #define     repeat      for(;;)
  84.  
  85. typedef     enum        _bool
  86.             { FALSE = 0, TRUE = 1 }  Bool;
  87. /*
  88.  *  declarations
  89.  */
  90.  
  91.     void    Usage_(), process();
  92.     Bool    locate() ;
  93.     char    *Cmdname_() {   return( "head" );    }
  94.  
  95. /*
  96.  *  MAIN
  97.  */
  98.  
  99. main( argc, argv )
  100.     int argc;
  101.     char    **argv;
  102. {
  103.     char    c10 ;       /*  argv[1][0]                        */
  104.     FILE    *fp ;
  105.     Bool    accent,     /*  user wants accented chars to show */
  106.             tail,       /*  show last lines, not first lines  */
  107.             tag ;       /*  argument is a tag (-.. or /..)    */
  108.     int     i ;
  109.     long int    line_ct ;
  110.  
  111.  /*  Usage - head  file_name [ line_count ] [/a][/t] > text  */
  112.  
  113.     c10 = argv[1][0] ;
  114.     if( argc < 2 || argc > 5 || c10 == '-' || c10 == '/' || c10 == '?' )
  115.         Usage_();
  116.  
  117.     if(( fp = fopen( argv[1], "rb" )) == NULL )
  118.     {
  119.         fprintf( stderr, "Can't open file %s\n", argv[1] ) ;
  120.         Usage_() ;
  121.     }
  122.  
  123.     line_ct = 10 ;
  124.     accent = tail = FALSE ;
  125.     for( i = 2 ; i < argc ; i++ )
  126.     {
  127.         tag = FALSE ;
  128.         if( argv[i][0] == '-' || argv[i][0] == '/' )
  129.             tag = TRUE ;
  130.         if( islower( argv[i][1] ))
  131.             argv[i][1] = toupper( argv[i][1] ) ;
  132.         if( tag && argv[i][1] == 'A' )
  133.             accent = TRUE ;
  134.         else if( tag && argv[i][1] == 'T' )
  135.             tail = TRUE ;
  136.         else
  137.         {
  138.             line_ct = atol( argv[i] );
  139.             if( line_ct < 1 )
  140.                 line_ct = 10 ;
  141.         }
  142.     }
  143.  
  144.     process( fp, line_ct, accent, tail );
  145.  
  146.     fclose( fp ) ;
  147.     exit( 0 );
  148. }
  149. /*
  150.  *  Usage
  151.  */
  152.     void
  153. Usage_()
  154. {
  155.     fprintf( stderr,
  156.     "usage:  %s  file_name [ line_count ] [/a][/t] > text\n\n\
  157.         Displays in printable format the first line_count lines\n\
  158.         within a file; the default is 10 lines.  This clone of\n\
  159.         the UNIX HEAD and TAIL utilities provides a quick check on\n",
  160.             Cmdname_() );
  161.     fprintf( stderr,
  162. "        the likely contents of a file.  If the \"/a\" option is used,\n\
  163.         accented characters are treated as printable text.  If\n\
  164.         \"/t\" is specified, the display is of the TAIL of the\n\
  165.         file, the LAST line_count lines.\n\n" ) ;
  166.     fprintf( stderr,
  167. "input:  Normally an ASCII text file.\n\n\
  168. output: The specified number of lines is either displayed on the\n\
  169.         screen or sent to a file.  Each non-printable character is\n\
  170.         replaced by an ^ symbol.  If any line length exceeds 120\n\
  171.         characters, a warning is issued.  If any line length exceeds\n" );
  172.     fprintf( stderr,
  173. "        1024 or the file includes null bytes, the program advises\n\
  174.         that the target file is not ASCII text.\n\n\
  175. writeup: MIR TUTORIAL ONE, topic 5\n\n" ) ;
  176.     exit( 1 ) ;
  177. }
  178.  
  179. #define     NON_PRINT       0
  180. #define     WHITE_SPACE     1
  181. #define     PUNCTUATION     2
  182. #define     DIGIT           3
  183. #define     CONSONANT       4
  184. #define     VOWEL           5
  185. #define     HI_CONSONANT    6
  186. #define     HI_VOWEL        7
  187. #define     TYPE_CT         8       /*  count of above types    */
  188.  
  189. /*
  190.  * PROCESS
  191.  */
  192.     void
  193. process( fp, line_ct, accent, tail )
  194.     FILE    *fp ;
  195.     long int     line_ct ;
  196.     Bool    accent,     /*  user wants accented chars to show */
  197.             tail ;      /*  show last lines, not first lines  */
  198. {
  199.    unsigned char   table[256] = {
  200.          0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* ctls */
  201.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ctls */
  202. /*      bl  !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /     */
  203.          1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2,
  204. /*       0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?     */
  205.          3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
  206. /*       @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O     */
  207.          4, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,
  208. /*       P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^  _     */
  209.          4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 2, 2, 2, 2, 2,
  210. /*       `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o     */
  211.          2, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,
  212. /*       p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~  NULL  */
  213.          4, 4, 4, 4, 4, 5, 4, 4, 4, 5, 4, 2, 2, 2, 2, 0,
  214. /*       Ç  ü  é  â  ä  à  å  ç  ê  ë  è  ï  î  ì  Ä  Å     */
  215.          6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7,
  216. /*       É  æ  Æ  ô  ö  ò  û  ù  ÿ  Ö  Ü  ¢  £  ¥  ₧  ƒ     */
  217.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0,
  218. /*       á  í  ó  ú  ñ  Ñ  ª  º  ¿  ⌐  ¬  ½  ¼  ¡  «  »     */
  219.          7, 7, 7, 7, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  220.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  221.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  222.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  223.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  224.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  225.             };
  226.     unsigned char   line_in[ MAX_BYTES ] ;
  227.     Bool            printable,      /*  file is ASCII text      */
  228.                     at_eof ;        /*  at end of file          */
  229.     long int        over_120,       /*  To warn re line length  */
  230.                     line_no;
  231.     int             ch,             /*  one character           */
  232.                     len, i ;
  233.  
  234.     over_120 = 0 ;
  235.     printable = TRUE ;
  236.     at_eof = FALSE ;
  237.  
  238.     if( tail )
  239.     {
  240.         if( !locate( fp, line_ct ))
  241.             return ;
  242.     }
  243.  
  244.     for( line_no = 0 ; line_no < line_ct ; line_no++ )
  245.     {
  246.         for( len = 0 ; len < MAX_BYTES ; len++ )
  247.         {
  248.             if(( ch = fgetc( fp )) == EOF )
  249.             {
  250.                 if( feof( fp ))
  251.                 {
  252.                     at_eof = TRUE ;
  253.                     break ;
  254.                 }
  255.             }
  256.             if( isprint( ch ) || ch == '\t' )
  257.                 line_in[ len ] = ch ;
  258.             else if( !ch )
  259.             {
  260.                 printable = FALSE ;
  261.                 break ;
  262.             }
  263.             else if( ch == '\n' )
  264.                 break ;
  265.             else if( ch == '\015' || ch == '\032' )
  266.                 len-- ;     /*  delete carriage return, EOF     */
  267.             else if( !accent )
  268.                 line_in[ len ] = '^' ;
  269.             else if( table[ch] == NON_PRINT )
  270.                 line_in[ len ] = '^' ;
  271.             else
  272.                 line_in[ len ] = ch ;
  273.         }
  274.         line_in[ len ] = '\0' ;
  275.  
  276.         if( len > MAX_BYTES - 2 || !printable )
  277.         {
  278.             fprintf( stderr,
  279. "\nNot printable ASCII.  Use f_print filter for display.\n" ) ;
  280.             fclose( fp ) ;
  281.             Usage_();
  282.         }
  283.         if( len > 120 )
  284.             over_120++ ;
  285.  
  286.         if( puts( line_in ))
  287.         {
  288.             fprintf( stderr, "Unable to write... FATAL.\n\n" ) ;
  289.             exit( 1 ) ;
  290.         }
  291.  
  292.         if( at_eof )
  293.             break ;
  294.     }
  295.  
  296.     if( over_120 )
  297.         fprintf( stderr, "\n*** %d LINES OVER 120 BYTES LONG ***\n\n",
  298.                 over_120 ) ;
  299.     return ;
  300. }
  301. /*
  302.  *  LOCATE - Find beginning point for the last line_ct lines
  303.  */
  304.     Bool
  305. locate( fp, line_ct )
  306.     FILE    *fp ;
  307.     long int     line_ct ;
  308. {
  309.     unsigned char   buf[ MAX_BYTES ] ;
  310.     Bool        gotcha ;    /*  found desired offset    */
  311.     long int    line_no,
  312.                 buf_len,
  313.                 fil_len,
  314.                 bgn_at ;    /*  offset of buffer start */
  315.     int         i ;
  316.  
  317.     fil_len = filelength( fileno( fp )) ;
  318.     if( fil_len < 1 )
  319.         return( FALSE ) ;
  320.     bgn_at = fil_len ;
  321.     line_no = 0 ;
  322.     gotcha = FALSE ;
  323.  
  324.     while( !gotcha )
  325.     {
  326.         bgn_at -= MAX_BYTES ;
  327.         if( bgn_at < 0 )
  328.             bgn_at = 0 ;
  329.         if( fseek( fp, bgn_at, SEEK_SET ))
  330.         {
  331.             fprintf( stderr, "Unable to position file.  FATAL!\n\n" );
  332.             return( FALSE ) ;
  333.         }
  334.         buf_len = fread( buf, sizeof( char ), MAX_BYTES, fp ) ;
  335.         if( fil_len >= MAX_BYTES && buf_len < MAX_BYTES )
  336.         {
  337.             fprintf( stderr, "Trouble reading back in file.  FATAL!\n\n" );
  338.             return( FALSE ) ;
  339.         }
  340.  
  341.         for( i = buf_len - 1 ; i > -1 ; i-- )
  342.         {
  343.             if( buf[i] == '\n' )
  344.             {
  345.                 if( ++line_no > line_ct )
  346.                 {
  347.                     bgn_at += ( i + 1 ) ;
  348.                     gotcha = TRUE ;
  349.                     break ;
  350.                 }
  351.             }
  352.             if( !buf[i] )    /*  null byte   */
  353.             {
  354.                 fprintf( stderr,
  355. "\nNot printable ASCII.  Use f_print filter for display.\n" ) ;
  356.                 fclose( fp ) ;
  357.                 Usage_();
  358.             }
  359.             if( !bgn_at )
  360.             {
  361.                 gotcha = TRUE ;
  362.                 break ;     /*  Must start at beginning     */
  363.             }
  364.         }
  365.     }
  366.  
  367.     if( fseek( fp, bgn_at, SEEK_SET ))
  368.     {
  369.         fprintf( stderr, "Unable to position file.  FATAL!\n\n" );
  370.         return( FALSE ) ;
  371.     }
  372.  
  373.     return( TRUE ) ;
  374. }