/*
 *  EOLCon 1.3
 *
 *    Completed 5/26/92
 *    by Ernest Crvich
 *
 *
 *   HISTORY :
 *
 *     V1.3  (5/26/92)
 *	     Fixed a memory allocation bug.
 *		(tempbuf wasn't getting set
 *		 right in some cases)
 *	     Added option to REPLACE carriage
 *		returns by linefeeds.  This
 *		is for files that do not even
 *		contain ANY linefeeds at all
 *		originally (just CR's).  Thanks
 *		to the outrageous Pres in Belgium
 *		for alerting me to these types
 *		of files!
 *
 *     V1.2  (2/17/92)
 *	     Added option to make the output file
 *		be the same as the input file so
 *		you don't have to constantly
 *		create a new file, delete the old
 *		one, then rename the new one.
 *		The template for the options isn't
 *		very good, but this is a pretty
 *		cheesy program anyways.  :-)
 *		Finally, I released this version!
 *
 *
 *     V1.1  (7/17/91)
 *	     Added option to make end-of-line char
 *		any character the user wants, not
 *		just a linefeed or carriage return.
 *		I was really going to release this,
 *		but for many reasons never got to
 *		actually doing it.
 *
 *
 *     V1.0a (7/10/91)
 *	     Added option to let user define the
 *		size of the buffer used.  Again
 *		came extremely close to releasing
 *		this version, but decided to let
 *		time improve upon it just a bit
 *		more.
 *
 *
 *     V1.0  (6/28/91)
 *	     Original bare-bones converter.  I came
 *		*very* close to releasing this to
 *		the public, but decided it needed
 *		'something special' to warrant that
 *		kind of action.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LF '\012'
#define CR '\015'
#define CR_ADD '1'
#define CR_DEL '0'
#define LF_ADD '2'
#define TMP_NAME   "ThisFileBetterNotExist!!"

/*
 * Prototypes
 *
 */
void ConvertFile( FILE *, FILE *, char, char *, char *, unsigned int ) ;
void main( int, char *[] ) ;




void main( int argc, char *argv[] )
{
   char 	convert 	  ; /* the command character			  */
   int		scan_test	  ; /* tests for a valid command line buffer size */
   int		replace = 0	  ; /* did the user want to use the same files?   */
   unsigned int buffer	  = 10000 ; /* buffer size for input file memory	  */
   unsigned int tempbuf 	  ; /* buffer size for the working memory used	  */
   char 	*chstr		  ; /* where the bytes read in are stored	  */
   char 	*temp		  ; /* where the actual output bytes are put	  */
   FILE 	*infile 	  ; /* input file structure			  */
   FILE 	*outfile	  ; /* output file structure			  */


   if ((argc > 5) || (argc < 4))
      {
	 printf( "\nUsage : EOLCon <inputfile> <outputfile>" ) ;
	 printf( " <%c|%c|%c|x> [buffersize]\n\n", CR_DEL, CR_ADD, LF_ADD ) ;
	 printf( "        In which   %c          means delete all carriage returns\n", CR_DEL ) ;
	 printf( "                   %c          means add a carriage return\n", CR_ADD ) ;
	 printf( "                   %c          means replace carriage returns with linefeeds\n", LF_ADD ) ;
	 printf( "                   x          means add a character to the end of\n" ) ;
	 printf( "                              the line (any character you want)\n" ) ;
	 printf( "                              'EOLCon in out &' would put an\n" ) ;
	 printf( "                              ampersand at the end of each line.\n" ) ;
	 printf( "                   buffersize is the size (in bytes) of the I/O\n" ) ;
	 printf( "                              buffer.  Note that 3 times this may\n" ) ;
	 printf( "                              actually be allocated (optimized for\n" ) ;
	 printf( "                              speed rather than size)!\n" ) ;
	 printf( "                              Default size is 10000.\n\n" ) ;
	 printf( "        Note that you can keep the same filename if you put an\n" ) ;
	 printf( "             an asterisk (*) in place of <outputfile>.\n\n" ) ;
      }
   else
      {
	 convert = (char) *argv[3] ;
	 infile = fopen( argv[1], "r" ) ;
	 if (infile == NULL)
	    printf( "\nError opening input file.\n" ) ;
	 else
	    {
	       if (argc == 5)
		  scan_test = sscanf( argv[4], "%u", &buffer ) ;
	       if ((scan_test == 0) || (buffer == 0))
		  {
		     buffer = 10000 ;
		     printf( "\nInvalid buffer size...using default.\n" ) ;
		  }
	       chstr = (char *) malloc( buffer ) ;
	       if (chstr == NULL)
		  {
		     printf( "\nError allocating primary memory!\n" ) ;
		     printf( "Try using a smaller buffer.\n" ) ;
		  }
	       else
		  {
		     if (convert != CR_DEL)
			tempbuf = buffer * 2 ;
		     else
			tempbuf = buffer ;
		     temp = (char *) malloc( tempbuf ) ;
		     if (temp == NULL)
			{
			   printf( "\nError allocating secondary memory!\n" ) ;
			   printf( "Try using a smaller buffer.\n" ) ;
			}
		     else
			{
			   if (strcmp( argv[2], "*" ) == 0)
			      {
				 outfile = fopen( TMP_NAME, "w" ) ;
				 replace = 1 ;
			      }
			   else
			      outfile = fopen( argv[2], "w" ) ;
			   if (outfile == NULL)
			      printf( "Error opening output file.\n" ) ;
			   else
			      {
				 printf( "\nWorking...\n" ) ;
				 ConvertFile( infile, outfile, convert,
					      chstr, temp, buffer ) ;
				 printf( "All done.\n" ) ;
				 fclose( outfile ) ;
			      }
			   free( temp ) ;
			}
		     free( chstr ) ;
		  }
	       fclose( infile ) ;
	       if (replace)
		  {
		     remove( argv[1] ) ;
		     rename( TMP_NAME, argv[1] ) ;
		  }
	    }
      }
}




/*
 * ConvertFile
 *
 * Does the actual concatenation of
 * the characters (reads/writes) to
 * the file.
 *
 */
void ConvertFile( FILE *in, FILE *out, char convert,
		  char *chstr, char *temp, unsigned int buffer )
{
   int i, j ;
   int numread ;

   numread = fread( chstr, 1, buffer, in ) ;
   while (numread)
      {
	 j = 0 ;
	 for (i = 0; i < numread; ++i)
	    if ( (*(chstr + i) == CR) &&
		 ((convert == CR_ADD) || (convert == CR_DEL)) )
	       /* ignore it! */ ;
	    else
	       if ((*(chstr + i) == LF) && (convert == CR_ADD))
		  {
		     *(temp + (j++)) = CR ;
		     *(temp + (j++)) = *(chstr + i) ;
		  }
	       else
		  if ((*(chstr + i) == LF) && (convert != CR_DEL))
		     {
			*(temp + (j++)) = convert ;
			*(temp + (j++)) = *(chstr + i) ;
		     }
		  else
		     if ( (*(chstr + i) == CR) && (convert == LF_ADD) )
			*(temp + (j++)) = LF ;
		     else
			*(temp + (j++)) = *(chstr + i) ;
	 fwrite( temp, 1, j, out ) ;
	 numread = fread( chstr, 1, buffer, in ) ;
      }
}
