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

  1. /*
  2.  *  usage:  p_fixed  control_file  fixed_length_input > ASCII_output
  3.  *
  4.  *  P_FIXED Converts a fixed record length file to ASCII with field
  5.  *          numbers.  A control file governs field lengths and
  6.  *          handling of empty data.
  7.  *
  8.  *  input:  [1]  A control file as in P_FIXED.CTL (also appears at
  9.  *               end of source code).
  10.  *          [2]  The fixed length records data
  11.  *
  12.  *  output: ASCII output with one or more lines per field.  New records
  13.  *          are signalled by a line containing 000; all other lines
  14.  *          begin with a three digit field number.  Non-printable
  15.  *          characters are shown in hex format with leading backslash.
  16.  *          Additional processing may be needed to bring individual
  17.  *          fields into production indexing format.
  18.  *
  19.  *  writeup: MIR TUTORIAL ONE, topic 9
  20.  *
  21.  *  Written:    Douglas Lowry   May 11 92
  22.  *              Copyright (C) 1992 Marpex Inc.
  23.  *
  24.  *    The MIR (Mass Indexing and Retrieval) Tutorials explain detailed
  25.  *    usage and co-ordination of the MIR family of programs to analyze,
  26.  *    prepare and index databases (small through gigabyte size), and
  27.  *    how to build integrated retrieval software around the MIR search
  28.  *    engine.  The fifth of the five MIR tutorial series explains how
  29.  *    to extend indexing capability into leading edge search-related
  30.  *    technologies.  For more information, GO IBMPRO on CompuServe;
  31.  *    MIR files are in the DBMS library.  The same files are on the
  32.  *    Canada Remote Systems BBS.  A diskette copy of the Introduction
  33.  *    is available by mail ($10 US... check, Visa or Mastercard);
  34.  *    diskettes with Introduction, Tutorial ONE software and the
  35.  *    shareware Tutorial ONE text cost $29.  Shareware registration
  36.  *    for a tutorial is also $29.
  37.  *
  38.  *    E-mail...
  39.  *                Compuserve  71431,1337
  40.  *                Internet    doug.lowry%canrem.com
  41.  *                UUCP        canrem!doug.lowry
  42.  *                Others:     doug.lowry@canrem.uucp
  43.  *
  44.  *    FAX...                  416 963-5677
  45.  *
  46.  *    "Snail mail"...         Douglas Lowry, Ph.D.
  47.  *                            Marpex Inc.
  48.  *                            5334 Yonge Street, #1102
  49.  *                            North York, Ontario
  50.  *                            Canada  M2N 6M2
  51.  *
  52.  *    Related database consultation and preparation services are
  53.  *    available through:
  54.  *              Innotech Inc., 2001 Sheppard Avenue E., Suite #118,
  55.  *              North York, Ontario  Canada   M2J 4Z7
  56.  *              Tel.  416 492-3838   FAX  416 492-3843
  57.  *
  58.  *  This program is free software; you may redistribute it and/or
  59.  *  modify it under the terms of the GNU General Public License as
  60.  *  published by the Free Software Foundation; either version 2 of
  61.  *  the License, or (at your option) any later version.
  62.  *
  63.  *  This program is distributed in the hope that it will be useful,
  64.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  65.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  66.  *  GNU General Public License for more details.
  67.  *
  68.  *  You should have received a copy of the GNU General Public License
  69.  *  (file 05LICENS) along with this program; if not, write to the
  70.  *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  71.  *  USA.
  72.  */
  73.  
  74. #include <stdio.h>
  75. #include <ctype.h>
  76.  
  77.  
  78. #define     repeat      for(;;)
  79. #define     MAX_BYTES   2048
  80.  
  81. #define     BLANKS      1   /* retain field if blank    */
  82. #define     ZEROS       2   /* retain field if zeros    */
  83. #define     NULLS       4   /* retain field if nulls    */
  84. #define     L_BLANKS    8   /* retain leading blanks in field   */
  85. #define     L_ZEROS    16   /* retain leading zeros in field    */
  86. #define     T_BLANKS   32   /* retain trailing blanks in field  */
  87. #define     S_RIGHT    64   /* start byte right nybble only     */
  88. #define     E_LEFT    128   /* end byte left nybble only        */
  89.  
  90. /*
  91.  * declarations 
  92.  */
  93.  
  94. typedef     enum        _bool
  95.              { FALSE = 0, TRUE = 1 }  Bool;
  96.  
  97.     void        Usage_(), process();
  98.     Bool        load_ctl(), isolate() ;
  99.     char        *Cmdname_() {    return( "p_fixed" );  }
  100.  
  101. /*
  102.  *  Global variables
  103.  */
  104.     static unsigned char
  105.             flag[ 1000 ] ;  /*  Bits set for each field per define
  106.                                 statements above.  0 is unused.     */
  107.     static short int
  108.             rec_len,        /*  bytes in fixed length record */
  109.             bgn[ 1000 ],    /*  starting byte, each field */
  110.             fin[ 1000 ],    /*  ending ditto.  0 is used for
  111.                                             record length  */
  112.             high_fld ;      /*  highest active field      */
  113. /*
  114.  * MAIN
  115.  */
  116.  
  117. main( argc, argv )
  118.     int  argc;
  119.     char **argv;
  120. {
  121.     FILE    *fp ;
  122.     char    c10 ;
  123.  
  124. /*  usage:  p_fixed  control_file  fixed_length_input > ASCII_output */
  125.  
  126.     if( argc != 3 )
  127.         Usage_() ;
  128.     c10 = argv[1][0] ;
  129.     if( c10 == '-' || c10 == '/' || c10 == '?' )
  130.         Usage_() ;
  131.  
  132.     if(( fp = fopen( argv[1], "r" )) == NULL )
  133.     {
  134.         fprintf( stderr, "\nUnable to control file %s.\n", argv[1] );
  135.         Usage_();
  136.     }
  137.  
  138.     if( load_ctl( fp ))
  139.     {
  140.         fprintf( stderr, "FATAL errors in control file %s.\n", argv[1] );
  141.         fclose( fp ) ;
  142.         exit( 1 ) ;
  143.     }
  144.     fclose( fp ) ;
  145.  
  146.     if(( fp = fopen( argv[2], "rb" )) == NULL )
  147.     {
  148.         fprintf( stderr, "\nUnable to open data file %s.\n", argv[2] );
  149.         Usage_();
  150.     }
  151.  
  152.     process( fp ) ;
  153.  
  154.     fclose( fp );
  155.     exit( 0 );
  156. }
  157. /*
  158.  *  Usage
  159.  */
  160.     void
  161. Usage_()
  162. {
  163.     fprintf( stderr,
  164. "\nUsage:  %s  control_file  fixed_length_input > ASCII_output\n\n\
  165.         Converts a fixed record length file to ASCII with field\n\
  166.         numbers.  A control file governs field lengths and\n\
  167.         handling of empty data.\n\n\
  168. input:  [1]  A control file as in P_FIXED.CTL (also appears at\n\
  169.              end of source code).\n", Cmdname_() );
  170.     fprintf( stderr,
  171. "        [2]  The fixed length records data\n\n\
  172. output: ASCII output with one or more lines per field.  New records\n\
  173.         are signalled by a line containing 000; all other lines\n\
  174.         begin with a three digit field number.  Non-printable\n" ) ;
  175.     fprintf( stderr,
  176. "        characters are shown in hex format with leading backslash.\n\
  177.         Additional processing may be needed to bring individual\n\
  178.         fields into production indexing format.\n\n\
  179. writeup: MIR TUTORIAL ONE, topic 9\n\n" ) ;
  180.     exit( 1 ) ;
  181. }
  182. /*
  183.  *  LOAD_CTL
  184.  */
  185.     Bool
  186. load_ctl( fp )
  187.     FILE    *fp ;
  188. {
  189.     char    buf[ 90 ] ;
  190.     Bool    line_okay ;
  191.     int     line_item,      /*  token # within one line     */
  192.             from, upto,     /*  limits of a token           */
  193.             foul_ups,       /*  count of bad lines          */
  194.             fld,            /*  field number                */
  195.             len, pt, i ;
  196.  
  197.     high_fld = foul_ups = rec_len = 0 ;
  198.     for( i = 0 ; i < 1000 ; i++ )
  199.     {
  200.         flag[ i ] = 0 ;
  201.         bgn[ i ] = fin[ i ] = -1 ;
  202.     }
  203.  
  204.     while( fgets( buf, 80, fp ) != NULL )
  205.     {
  206.         len = strlen( buf ) - 1 ;
  207.         while( isspace( buf[ len -1 ] ))
  208.             len-- ;
  209.         buf[ len ] = '\0' ;
  210.         line_okay = TRUE ;
  211.         if( buf[0] == '\032' )
  212.             break ;
  213.         if( !len || buf[0] == '#' )
  214.             continue ;      /*  empty, or comment line  */
  215.  
  216.         for( i = 0 ; i < len ; i++ )
  217.         {
  218.             if( islower( buf[ i ] ))
  219.                 buf[ i ] = toupper( buf[ i ] ) ;
  220.         }
  221.         pt = -1 ;
  222.         line_item = 0 ;
  223.  
  224.         while( !isolate( buf, len, pt, &from, &upto ))
  225.         {
  226.             if( !line_item )
  227.             {
  228.                 fld = atoi( &buf[ from ] ) ;
  229.                 if( fld < 0 || fld > 999 )
  230.                 {
  231.                     fprintf( stderr,
  232. "FATAL... Control line should start with a field number between\n\
  233. 1 and 999.  Check your control file.\n\n" ) ;
  234.                     return( 1 ) ;
  235.                 }
  236.             }
  237.             else if( line_item == 1 )
  238.             {
  239.                 bgn[ fld ] = atoi( &buf[ from ] ) ;
  240.                 if( buf[ upto ] == 'R' )
  241.                     flag[ fld ] |= S_RIGHT ;
  242.             }
  243.             else if( line_item == 2 )
  244.             {
  245.                 fin[ fld ] = atoi( &buf[ from ] ) ;
  246.                 if( buf[ upto ] == 'L' )
  247.                     flag[ fld ] |= E_LEFT ;
  248.                 if( bgn[ fld ] > fin[ fld ] )
  249.                     line_okay = FALSE ;
  250.             }
  251.             else if( from == upto )
  252.             {
  253.                 if( buf[ from ] == 'B' )
  254.                     flag[ fld ] |= BLANKS ;
  255.                 else if( buf[ from ] == 'Z' )
  256.                     flag[ fld ] |= ZEROS ;
  257.                 else if( buf[ from ] == 'N' )
  258.                     flag[ fld ] |= NULLS ;
  259.                 else
  260.                     line_okay = FALSE ;
  261.             }
  262.             else if( upto == ( from + 1 ) &&  buf[ from ] == 'L' )
  263.             {
  264.                 if( buf[ upto ] == 'B' )
  265.                     flag[ fld ] |= L_BLANKS ;
  266.                 else if( buf[ upto ] == 'Z' )
  267.                     flag[ fld ] |= L_ZEROS ;
  268.                 else
  269.                     line_okay = FALSE ;
  270.             }
  271.             else if( upto == ( from + 1 ) &&  buf[ from ] == 'T' )
  272.             {
  273.                 if( buf[ upto ] == 'B' )
  274.                     flag[ fld ] |= T_BLANKS ;
  275.                 else
  276.                     line_okay = FALSE ;
  277.             }
  278.             else
  279.                 line_okay = FALSE ;
  280.  
  281.             if( !line_okay )
  282.             {
  283.                 fprintf( stderr,
  284.                     "Unexpected line in control file...\n\t%s\n", buf );
  285.                 if( foul_ups++ > 4 )
  286.                     return( 1 ) ;
  287.                 break ;
  288.             }
  289.             pt = upto ;
  290.             line_item++ ;
  291.         }
  292.  
  293.         /*  Finish off input line   */
  294.  
  295.         if( fld > high_fld )
  296.             high_fld = fld ;
  297.     }
  298.  
  299.     rec_len = fin[ 0 ] ;
  300.     if( rec_len > MAX_BYTES )
  301.     {
  302.         fprintf( stderr, "Record length exceeds %d bytes... recompile.\n",
  303.             MAX_BYTES ) ;
  304.         return( 1 ) ;
  305.     }
  306.     if( !rec_len )
  307.     {
  308.         fprintf( stderr, "Record length not specified... FATAL.\n" ) ;
  309.         return( 1 ) ;
  310.     }
  311.  
  312.     if( foul_ups )
  313.         return( 1 ) ;
  314.     return( 0 ) ;
  315. }
  316. /*
  317.  *  ISOLATE - Find limits of next token in a buffer
  318.  */
  319.     Bool
  320. isolate( buf, len, pt, from, upto )
  321.     char    buf[] ;
  322.     int     pt, len,
  323.             *from, *upto ;
  324. {
  325.     int     local_pt ;
  326.  
  327.     local_pt = pt + 1 ;
  328.     while( isspace( buf[ local_pt ] ) && buf[ local_pt ] )
  329.         local_pt++ ;
  330.  
  331.     if( local_pt > len - 1 )
  332.         return( 1 ) ;
  333.  
  334.     *from = local_pt ;
  335.  
  336.     while( !isspace( buf[ local_pt ] ) && buf[ local_pt ] )
  337.         local_pt++ ;
  338.  
  339.     *upto = local_pt - 1 ;
  340.  
  341.     return( 0 ) ;
  342. }
  343. /*
  344.  *  PROCESS
  345.  */
  346.     void
  347. process( fp )
  348.     FILE    *fp ;
  349. {
  350.     unsigned char   buf[ MAX_BYTES ],
  351.                     uc,
  352.                     first_save, last_save ;
  353.     long int        records ;
  354.     int             from, upto,
  355.                     fld,       /*  field number */
  356.                     len, i ;
  357.  
  358.     records = 0 ;
  359.  
  360.     while(( len = fread( buf, sizeof( char ), rec_len, fp )) > 0 )
  361.     {
  362.         if( len < rec_len )
  363.             break ;     /*  assuming end    */
  364.  
  365.         records++ ;
  366.  
  367.         if( !printf( "000 \n" ))
  368.         {
  369.             fprintf( stderr, "FATAL write error.\n\n" ) ;
  370.             exit( 1 ) ;     /*  error check once per record is enough */
  371.         }
  372.  
  373.         for( fld = 1 ; fld <= high_fld ; fld++ )
  374.         {
  375.             if( bgn[ fld ] == -1 )
  376.                 continue ;      /*  no such field       */
  377.  
  378.             if( flag[ fld ] & S_RIGHT )
  379.             {
  380.                 first_save = buf[ bgn[ fld ] ] ;
  381.                 buf[ bgn[ fld ] ] &= 0x0f ;
  382.             }
  383.             if( flag[ fld ] & E_LEFT )
  384.             {
  385.                 last_save = buf[ fin[ fld ] ] ;
  386.                 buf[ fin[ fld ] ] >>= 4 ;
  387.             }
  388.             from =  upto = -1 ;
  389.             for( i = bgn[ fld ] ; i <= fin[ fld ] ; i++ )
  390.             {
  391.                 uc = buf[ i ] ;
  392.                 if( uc == '\0' )
  393.                     continue ;
  394.                 if( uc == ' ' && !( flag[fld] & L_BLANKS ))
  395.                     continue;
  396.                 if( uc == '0' && !( flag[fld] & L_ZEROS ))
  397.                     continue;
  398.                 from = i ;
  399.                 break ;
  400.             }
  401.  
  402.             if( from > -1 )
  403.             {
  404.                 upto = fin[ fld ] ;
  405.                 if( !( flag[fld] & T_BLANKS ))
  406.                 {
  407.                     while( buf[ upto ] == ' ' )
  408.                         upto-- ;
  409.                 }
  410.             }
  411.             else        /*  no data found       */
  412.             {
  413.                 uc = buf[ bgn[ fld ] ] ;
  414.                 if( (( flag[fld] & BLANKS ) && uc == ' ' ) ||
  415.                     (( flag[fld] & ZEROS  ) && uc == '0' ) ||
  416.                     (( flag[fld] & NULLS  ) && uc == '\0' ) )
  417.                         from = upto = bgn[ fld ] ;  /*  1st char only */
  418.             }
  419.  
  420.             /*  print out result if data or retention  */
  421.  
  422.             if( from > -1 )
  423.             {
  424.                 printf( "%03d ", fld ) ;
  425.                 for( i = from ; i <= upto ; i++ )
  426.                 {
  427.                     if( isprint( buf[ i ] ) && buf[i] != '\\' )
  428.                         putchar( buf[ i ] ) ;
  429.                     else
  430.                         printf( "\\%02x", buf[i] ) ;
  431.                 }
  432.                 putchar( '\n' ) ;
  433.             }
  434.  
  435.             if( flag[ fld ] & S_RIGHT )
  436.                 buf[ bgn[ fld ] ] = first_save ;
  437.             if( flag[ fld ] & E_LEFT )
  438.                 buf[ fin[ fld ] ] = last_save ;
  439.         }
  440.     }
  441.  
  442.     putchar( '\032' ) ;
  443.  
  444.     fprintf( stderr, "Processed %ld records.\n\n", records ) ;
  445.     return ;
  446. }
  447. /*  P_FIXED.CTL     TEMPLATE  May 11, 1992
  448. #   Edit a copy of this file to use with P_FIXED.EXE in order
  449. #   to break out fixed length records.  Each line consists of
  450. #   three numbers and zero or more codes; each element is separated
  451. #   by one or more blanks.  The numbers are:
  452. #        field number
  453. #        start byte (followed by R if right half of byte only)
  454. #        end byte   (followed by L if left half of byte only)
  455. #   A special line must be included with field number 0, begin byte
  456. #   0, and end byte = last byte of record (i.e., record length - 1 ).
  457. #
  458. #   Comment lines may be included.  Each must start with #
  459. #
  460. #   The codes that follow the three numbers are:
  461. #       B   retain field if blank
  462. #       Z   retain field if zeros
  463. #       N   retain field if nulls
  464. #       LB  retain leading blanks in field
  465. #       LZ  retain leading zeros in field
  466. #       TB  retain trailing blanks in field
  467. #
  468.   0   0   345
  469.   1   0   11  B
  470.   2   12  15
  471.   3   16 26 TB
  472. etc.
  473. */