home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / PSCRIPT / PSFIX.ZIP / PSFIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-01  |  14.3 KB  |  569 lines

  1. /*
  2.  *
  3.  *  psfix.c
  4.  *
  5.  */
  6.  
  7. /*
  8.  * This software is the property of the Smithsonian Astrophysical Observatory
  9.  * and the U.S. government. It may be freely distributed under the following
  10.  * conditions:
  11.  *         1. It is distributed in its current form, without alterations.
  12.  *         2. No monetary profit is made, under any circumstances.
  13.  *
  14.  *             Marc A. Murison
  15.  *             Smithsonian Astrophysical Observatory
  16.  *             60 Garden Street, MS 63
  17.  *             Cambridge, MA  02138
  18.  *
  19.  *             (617) 495-7079      murison@cfacx2.harvard.edu
  20.  */
  21.  
  22.  
  23. #include  "psfix.h"
  24.  
  25.  
  26. int main( int argc, char **argv )
  27. {
  28.     /* flags */
  29.     Flag    msg_flag, file_mode;
  30.     int        dirflag=0, EOF_flag;
  31.  
  32.     /* counters */
  33.     long    newlines=0, oldlines=0, char_count=0;
  34.     int        ncomment, paren_level;
  35.  
  36.     /* misc variables */
  37.     Boolean    status;
  38.     int        i, min_args;
  39.     int        l_bytes, length;
  40.     ulong    f_bytes;      /* bytes read from input file to file_buffer */
  41.  
  42.     /* file name character arrays and associated pointers */
  43.     static char    in_name[MAX_FNAME+1], out_name[MAX_FNAME+1];
  44.     static char    in_ext[5], out_ext[5];
  45.     static char    default_in_ext[5], default_out_ext[5];
  46.     File_Def    infile, outfile, dirfile;
  47.  
  48.  
  49.     /* buffers and buffer pointers */
  50.     static char    msg[80];
  51.     static char    *line_buffer, *line_buff_start, *line_buff_ptr;
  52.     static char    *file_buffer, *file_buff_ptr;
  53.  
  54.     /* other pointers */
  55.     static char    *scratch_ptr;
  56.  
  57.  
  58.  
  59.     /* say hi */
  60.     announce( VERSION, __DATE__ );
  61.  
  62.  
  63. /* parse the command line */
  64.     strcpy( default_in_ext, INEXT );
  65.     strcpy( default_out_ext, OUTEXT );
  66.     min_args  = 1;
  67.     file_mode = FBINARY;
  68.     status = cl_dir_in_out( argc, argv, min_args, usage, help, file_mode,
  69.                             default_in_ext, default_out_ext, in_name, 
  70.                             in_ext, out_name, out_ext, &infile, &outfile, 
  71.                             &dirfile, &dirflag );
  72.  
  73.     if( !status )  return 1;
  74.  
  75.  
  76. /* create buffers */
  77.     line_buffer = cvector( 0, MAX_LBUFF );
  78.     if( line_buffer == NULL ) {
  79.         errout( 1, stdout, "\nNot enough memory for line buffer!\n" );
  80.         fclose( infile.fp );
  81.         fclose( outfile.fp );
  82.         if( dirflag != 0 )  fclose( dirfile.fp );
  83.         return 1;
  84.     }
  85.  
  86.     file_buffer = (char *) malloc( (uint)MAX_FBUFF*sizeof(char) );
  87.     if( file_buffer == NULL ) {
  88.         errout( 1, stdout, "\nNot enough memory for file buffer!\n" );
  89.         fclose( infile.fp );
  90.         fclose( outfile.fp );
  91.         if( dirflag != 0 )  fclose( dirfile.fp );
  92.         return 1;
  93.     }
  94.  
  95.  
  96.  
  97. /* 
  98.  *
  99.  * process input file(s) 
  100.  *
  101.  */
  102.  
  103. /* initial output and initialize counters */
  104.     banner( infile.name, outfile.name, &char_count, &newlines, &oldlines );
  105.  
  106.     file_buff_ptr   = file_buffer;
  107.     line_buff_start = line_buffer;
  108.     line_buff_ptr   = line_buffer;
  109.     *file_buffer    = NULL;
  110.     *line_buffer    = NULL;
  111.     paren_level     = 0;
  112.  
  113.  
  114. /* fill the file buffer */
  115.     printf( "\r% % % % % reading input file % % % % %                   \r" );
  116.     f_bytes = pfill_file_buff( infile.fp, file_mode, MAX_FBUFF, file_buff_ptr,
  117.                                &EOF_flag, &ncomment, &paren_level );
  118.     printf( "\r                                       " );
  119.  
  120.  
  121. /* count the comment characters skipped */
  122.     char_count += ncomment;
  123.  
  124.  
  125.     if( f_bytes <= 0 ) {
  126.         if( f_bytes == 0 ) {
  127.             sprintf( msg, "\nfill_file_buff:  input file %s is empty!\n",
  128.                      &infile.name );
  129.             errout( 1, stdout, msg );
  130.         }
  131.         fclose( infile.fp );
  132.         fclose( outfile.fp );
  133.         if( dirflag != 0 )
  134.             fclose( dirfile.fp );
  135.         return 1;
  136.     }
  137.  
  138.  
  139.  
  140. /* top of processing loop */
  141.     msg_flag = TRUE;
  142.     status   = TRUE;
  143.     while( status ) {
  144.  
  145. /* some screen output */
  146.         if( newlines % OUTP_INTVL  ==  0 ) {
  147. #if __MSDOS__
  148.             printf(
  149.                 "\r"
  150.                 "\xba Input line: %-5li  Output line: %-5li"
  151.                 "  Character: %-7li \xba\r",
  152.                 oldlines, newlines, char_count );
  153. #else
  154.             printf(
  155.                 "\r"
  156.                 "| Input line: %-5li  Output line: %-5li"
  157.                 "  Character: %-7li |\r",
  158.                 oldlines, newlines, char_count );
  159. #endif
  160.         }
  161.  
  162.  
  163. /* fill line buffer with MAX_CHARS bytes from file buffer */
  164.         if( (length = strlen(line_buff_start))  <  MAX_CHARS ) {
  165.             f_bytes = MAX_FBUFF;
  166.             l_bytes = MAX_CHARS - length;
  167.             scratch_ptr = line_buff_start + length;
  168.             pfill_line_buff( infile.fp, file_mode, file_buffer, &file_buff_ptr, 
  169.                              f_bytes, l_bytes, scratch_ptr, msg_flag, 
  170.                              &EOF_flag, &ncomment, &paren_level );
  171.             char_count += ncomment;
  172.         }
  173.  
  174.  
  175. /* process and output the line buffer contents */
  176.         process_line_buffer( line_buff_start, &line_buff_ptr, &outfile,
  177.                              &char_count, &newlines, &oldlines, &EOF_flag );
  178.  
  179.  
  180. /* are we done with this input file yet? */
  181.         if( EOF_flag  &&  feof(infile.fp) ) {
  182.             /* clean up final output */
  183. #if __MSDOS__
  184.             printf( "\r"
  185.                     "\xba Input line: %-5li  Output line: %-5li"
  186.                     "  Character: %-7li \xba",
  187.                     oldlines, newlines, char_count );
  188.             printf( "\n\xc8" );
  189.             for( i=0; i < 59; i++ )  printf( "\xcd" );
  190.             printf( "\xbc\n" );
  191. #else
  192.             printf(
  193.                 "\r"
  194.                 "| Input line: %-5li  Output line: %-5li  Character: %-7li |",
  195.                 oldlines, newlines, char_count );
  196.             printf( "\n" );
  197.             for( i=0; i < 61; i++ )  printf( "-" );
  198.             printf( "\n" );
  199. #endif
  200.  
  201.             fclose( infile.fp );
  202.             fclose( outfile.fp );
  203.             if( dirflag ) {
  204.                 status = get_next_file( &dirfile, &infile, &outfile,
  205.                                 file_mode, default_in_ext, in_name, in_ext, 
  206.                                 out_name, out_ext );
  207.  
  208.                 if( status ) {
  209.                     /* initial output and reset counters */
  210.                     banner( infile.name, outfile.name, &char_count,
  211.                             &newlines, &oldlines );
  212.  
  213.                     /* reset pointers */
  214.                     file_buff_ptr     = file_buffer;
  215.                     line_buff_ptr     = line_buffer;
  216.                     *line_buff_ptr    = NULL;
  217.                     *file_buff_ptr    = NULL;
  218.                     EOF_flag          = 0;
  219.                 }
  220.  
  221.             } else {
  222.  
  223.                 status = 0;
  224.  
  225.             }
  226.         }
  227.     }        /* end of processing loop */
  228.  
  229.  
  230. /* clean up */
  231.  
  232. #if __MSDOS__
  233.     if( dirflag  ||  char_count > 100000L )
  234.         errout( 1, stdout, "\n\nDone\n" );
  235. #else
  236.     if( dirflag  ||  char_count > 100000 )
  237.         errout( 1, stdout, "\n\nDone\n\n" );
  238. #endif
  239.  
  240.  
  241.     free( file_buffer );
  242.     free_cvector( line_buffer, 0 );
  243.     return 0;
  244. }
  245.  
  246.  
  247.  
  248. /*-----------------------------------------------------------------------------
  249.  * Process the contents of the line buffer and output the result to
  250.  * outfile.
  251.  *
  252.  * If either an EOF or a NULL byte are encountered, then EOF_flag is set
  253.  * to 1, via the pointer *EOF_flag; otherwise EOF_flag is set to 0. If
  254.  * a newline character is encountered, the counter oldlines, pointed
  255.  * to by *oldlines, is incremented (to keep track of input lines
  256.  * processed). As each byte is read, char_count (pointed to by
  257.  * *char_count) is incremented to keep count of total input bytes
  258.  * processed. As new lines are written to the output file, counter newlines
  259.  * (via *newlines) is incremented.
  260.  *---------------------------------------------------------------------------*/
  261. void process_line_buffer( char *line_buff_start, char **line_buff,
  262.                           File_Def *outfile, long *char_count, long *newlines,
  263.                           long *oldlines, int *EOF_flag )
  264. {
  265.     int            i, length;
  266.     char        c;
  267.     static char    scratch[MAX_LBUFF], *sp;
  268.     char        *lp;
  269.  
  270.  
  271.     *EOF_flag = 0;
  272.  
  273. /* filter the first MAX_CHARS or less bytes of line buffer */
  274.     lp = line_buff_start;
  275.     sp = scratch;
  276.     for( i=0; i < MAX_CHARS; i++ ) {
  277.  
  278.         c = *lp++;
  279.  
  280.         /* all done with this file */
  281.         if( c == EOF  ||  c == NULL ) {
  282.             (*oldlines)++;                /* count the last line */
  283.             *EOF_flag = 1;
  284.             break;
  285.         }
  286.  
  287.         ++(*char_count);
  288.         
  289.         if( c == CR ) {
  290.             if( *lp == LF ) {            /* end of input line */
  291.                 lp++;                    /* skip over LF */
  292.                 (*char_count)++;
  293.                 (*oldlines)++;
  294.                 break;
  295.             } else {                    /* lone cr */
  296.                 *(sp++) = BLANK;
  297.             }
  298.         } else if( c == TAB ) {            /* replace tabs */
  299.             *(sp++) = BLANK;
  300.         } else {                        /* normal character */
  301.             *(sp++) = c;
  302.         }
  303.     }
  304.     *sp = NULL;
  305.  
  306.  
  307. /* now move back to a space */
  308.     length = strlen( scratch );
  309.     if( length == MAX_CHARS ) {            /* do only if line is long enough */
  310.         i = length - 1;
  311.         sp = scratch + i;                /* point to last character */
  312.         while( i > 0  &&  *sp != BLANK ) {
  313.             --i;
  314.             --length;
  315.             --sp;
  316.             --(*char_count);
  317.         }
  318.         /* keep going until a non-space, so spaces are at start of next line */
  319.         while( i > 0  &&  *sp == BLANK ) {
  320.             --i;
  321.             --length;
  322.             --sp;
  323.             --(*char_count);
  324.         }
  325.         /* if no spaces at all, quit */
  326.         if( i == 0 ) {
  327.             printf( "\a\n\nError!"
  328.                     "\nUnable to break input line number %li "
  329.                     "into pieces less than %i bytes!"
  330.                     "\nOffending piece of text is"
  331.                     "\n%s"
  332.                     "\nCheck last line of output file for context.",
  333.                     *oldlines, MAX_CHARS, scratch );
  334.             fprintf( outfile->fp, "%s\n", scratch );
  335.             fflush( outfile->fp );
  336.             fclose( outfile->fp );
  337.             exit(1);
  338.         }
  339.     }
  340.  
  341.  
  342. /* write a new line to output file */
  343.     sp = scratch;
  344.     for( i = 0;  i < length;  i++ ) {
  345.         if( putc(*sp, outfile->fp) == EOF )  disk_full( outfile );
  346.         ++sp;
  347.     }
  348.     if( putc(CR, outfile->fp) == EOF  ||  putc(LF, outfile->fp) == EOF )
  349.         disk_full( outfile );
  350.  
  351.     (*newlines)++;
  352.  
  353.  
  354. /* set up to read next input record to the line buffer */
  355.  
  356. /* transfer leftovers to beginning of line_buffer, and return */
  357.     *line_buff = lp;                /* save new line_buffer position */
  358.     lp = line_buff_start;
  359.     strcpy( lp, sp );
  360.     strcat( lp, *line_buff );
  361.     *line_buff = line_buff_start;    /* update line_buff_ptr in main */
  362. }
  363.  
  364.  
  365.  
  366. /*-----------------------------------------------------------------------------
  367.  *
  368.  * disk full error out
  369.  *
  370.  *---------------------------------------------------------------------------*/
  371. void disk_full( File_Def *file )
  372. {
  373.     int i;
  374.     
  375. #if __MSDOS__
  376.             printf( "\n\xc8" );
  377.             for( i=0; i < 59; i++ )  printf( "\xcd" );
  378.             printf( "\xbc\n" );
  379. #else
  380.             printf( "\n" );
  381.             for( i=0; i < 61; i++ )  printf( "-" );
  382.             printf( "\n" );
  383. #endif
  384.             printf( "\a\nError writing to %s!  Disk full?\n", file->name );
  385.             exit(1);
  386. }
  387.  
  388.  
  389.  
  390. /*-----------------------------------------------------------------------------
  391.  *
  392.  * announce new filename
  393.  *
  394.  *---------------------------------------------------------------------------*/
  395. void banner( char infile_name[], char outfile_name[], long *char_count,
  396.              long *newlines, long *oldlines )
  397. {
  398.     int  i;
  399.  
  400.     *newlines   = 0;
  401.     *oldlines   = 0;
  402.     *char_count = 0;
  403.  
  404. #if __MSDOS__
  405.  
  406.     /* top line */
  407.     printf( "\n\xc9" );
  408.     for( i=0; i < 31; i++ )  printf( "\xcd" );
  409.     printf( "\xbb" );
  410.  
  411.     /* text */
  412.     printf( "\n\xba  Input file:  %-15s \xba"
  413.             "\n\xba Output file:  %-15s \xba",
  414.             infile_name, outfile_name );
  415.  
  416.     /* separator line */
  417.     printf( "\n\xcc" );
  418.     for( i=0; i < 31; i++ )  printf( "\xcd" );
  419.     printf( "\xca" );
  420.     for( i=0; i < 27; i++ )  printf( "\xcd" );
  421.     printf( "\xbb\n" );
  422.  
  423. #else
  424.  
  425.     printf( "\n-----------------------"
  426.             "\n|  Input file:  %-15s |"
  427.             "\n| Output file:  %-15s |"
  428.             "\n", infile_name, outfile_name  );
  429.     for( i=0; i < 61; i++ )  printf( "-" );
  430.     printf( "\n" );
  431.  
  432. #endif
  433. }
  434.  
  435.  
  436.  
  437. /*-----------------------------------------------------------------------------
  438.  * ulong pfill_file_buff( FILE *infile, int ftype, long Nmax,
  439.  *                        char *buff, int *EOF_flag, int *ncomment,
  440.  *                        int *paren_level )
  441.  *
  442.  * modified version of fill_file_buff in strlib.c 
  443.  * (this version strips PostScript comments)
  444.  *---------------------------------------------------------------------------*/
  445. ulong    pfill_file_buff( FILE *infile, int ftype, ulong Nmax, char *buff,
  446.                          int *EOF_flag, int *ncomment, int *paren_level )
  447. {
  448.     ulong    i;
  449.     int        c;
  450.     char    *p;
  451.  
  452.  
  453.     if( ftype != FTEXT  &&  ftype != FBINARY ) {
  454.         errout( 1, stdout, "\nfill_file_buff:  Invalid ftype!\n\n" );
  455.         *EOF_flag = 1;
  456.         return 0;
  457.     }
  458.  
  459.  
  460.     *EOF_flag = FALSE;
  461.     p = buff;
  462.     i = 0;
  463.     *ncomment = 0;
  464.     while( i < Nmax ) {
  465.         c = getc( infile );
  466.         ++i;
  467.  
  468.         /* check parentheses nesting level (for comment stripping decision) */
  469.         if( c == '('  &&  *(p-1) != BSLASH )  ++(*paren_level);
  470.         if( c == ')'  &&  *(p-1) != BSLASH )  --(*paren_level);
  471.  
  472.         /* strip P.S. comments */
  473.         if( c == '%'  &&  *paren_level == 0 ) {
  474.             ++i;
  475.             ++(*ncomment);
  476.             while( ( c = getc(infile) ) != CR  
  477.                     &&  c != LF  &&  c != EOF )  { ++i;  ++(*ncomment); }
  478.         }
  479.  
  480.         /* check end of file */
  481.         if( c == EOF ) {
  482.             *EOF_flag = TRUE;
  483.             break;
  484.         }
  485.  
  486.         /* write character to file buffer */
  487.         *p++ = c;
  488.     }
  489.  
  490.     *p = NULL;
  491.  
  492.     return i;
  493. }
  494.  
  495.  
  496.  
  497. /*-----------------------------------------------------------------------------
  498.  * uint pfill_line_buff( FILE *infile, int ftype, char file_buffer,
  499.  *                        char **file_buff_ptr_ptr, ulong Fbytes, uint Lbytes,
  500.  *                        char *line_buff_ptr, int msg_flag, int *EOF_flag,
  501.  *                      int  *ncomment, int *paren_level )
  502.  *
  503.  * a modified version of fill_line_buff in strlib.c
  504.  *---------------------------------------------------------------------------*/
  505. uint    pfill_line_buff( FILE *infile, int ftype, char file_buffer[],
  506.                          char **file_buff_ptr_ptr, ulong Fbytes, uint Lbytes,
  507.                          char *line_buff_ptr, int msg_flag, int *EOF_flag,
  508.                          int  *ncomment, int *paren_level )
  509. {
  510.     uint    n;
  511.     ulong    k;
  512.     char    *file_buff_ptr;
  513.  
  514.  
  515. /* try to move Lbytes bytes */
  516.     file_buff_ptr = *file_buff_ptr_ptr;
  517.     k = append_buff( file_buff_ptr, Lbytes, line_buff_ptr );
  518.     n = (uint) k;
  519.     *file_buff_ptr_ptr += n;
  520.     *ncomment = 0;
  521.  
  522. /* if not enough bytes were copied, get more from the input file */
  523.     if( n != Lbytes ) {
  524.         *file_buffer       = NULL;
  525.         file_buff_ptr      = file_buffer;
  526.         *file_buff_ptr_ptr = file_buff_ptr;
  527.         if( !feof(infile) ) {
  528.             if( msg_flag ) {
  529.                 printf( "\r % % % % % Reading input file "
  530.                         "% % % % %                    \r" );
  531.             }
  532.             k = pfill_file_buff( infile, ftype, Fbytes, file_buff_ptr,
  533.                                  EOF_flag, ncomment, paren_level );
  534.             if( msg_flag ) {
  535.                 printf( "\r                              "
  536.                         "                             \r" );
  537.             }
  538.             /* finish filling the line buffer */
  539.             line_buff_ptr += n;
  540.             k  = append_buff( file_buff_ptr, Lbytes - n, line_buff_ptr );
  541.             n += (uint) k  +  *ncomment;
  542.             *file_buff_ptr_ptr += (int) k;
  543.             
  544.         } else {        /* already at end of file on entry into this routine */
  545.         
  546.             *EOF_flag = 1;
  547.  
  548.         }
  549.     }
  550.  
  551.     return n;
  552. }
  553.  
  554.  
  555.  
  556. /*-----------------------------------------------------------------------------
  557.  *
  558.  * generic error output
  559.  *
  560.  *---------------------------------------------------------------------------*/
  561. void  errout( Boolean bell, FILE *device, char *errstring )
  562. {
  563.     if( bell )  putc( BELL, device );
  564.     fprintf( device, "%s", errstring );
  565.     return;
  566. }
  567.  
  568.  
  569.