/*
 * merge.c - merge a c source file with it's assembler output, the
 * program assumes that the compiler outputs ; Line # assembler
 * comments when a new line is translated
 */

#include <stdio.h>

#define	LINSIZ	255	/* max line size */
#define	NAMSIZ	80	/* max name size */
#define	TRUE	1
#define	FALSE	0

FILE *pcsrc, *pasmsrc, *poutput;		/* file pointers required */

char line [ LINSIZ ];				/* input line buffer */

char *fmterr = "merge: usage is: merge [-cqv] file [file file ... ]";
char *opnerr = "\nmerge: can't open";
char *endmsg = "file(s) merged";
char *opterr = "\nmerge: illegal option";

char file_c[ NAMSIZ ], file_a[ NAMSIZ ], file_o[ NAMSIZ ];

void mergeline( void ); /* inserted source lines handled here */
void writefail( void );	/* failure during writes handled here */

main( argc, argv )
int argc;
char *argv[];

{
	register long runcount, totlcount;
	auto long linecount;
	int c;
	int fcount = 0;
	short int VERBOSE = TRUE;
	short int COUNT	  = FALSE;

	if ( argc < 2 )
		_exit( fprintf( stderr, "%s\n", fmterr ) + 0x0C );
	
	while( --argc > 0 ) {

		++argv;		/* point at next parm */
		if( ( c = **argv ) == '-' || c == '/' )	/* process flag */
			while( c = *(++(*argv)) ) {
				switch( c ) {
				case 'c':
				case 'C':	/* count files */
					COUNT = TRUE;
					break;
				case 'Q':	/* be quiet on output */
				case 'q':	/* case not sensitive */
					VERBOSE = FALSE;
					break;
				case 'V':	/* may want verbose later */
				case 'v':
					VERBOSE = TRUE;
					break;
				default:
					fprintf( stderr, "%s %c", opterr, c);
					break;
				}
			}

		else {	/* use entry as file, should be past flags */

		strcpy( file_c, *argv );
		strcpy( file_o, *argv );
		strcpy( file_a, *argv );

		if ( strrchr( file_c, '.' ) != NULL ) {
			strcpy( file_c, strtok( *argv, "." ) );
			strcpy( file_a, file_c );
			strcpy( file_o, file_c );
		}
		
		strcat( file_c, ".C" );
		strcat( file_o, ".LST" );
		strcat( file_a, ".ASM" );

		/* file names are adjusted, now try to open each file   */
		/* and determine what occured, if ok, continue else end */

		if( !( pcsrc = fopen( file_c, "r" ) ) ) {
			fprintf( stderr, "%s %s", opnerr,strupr( file_c ) );
			continue;
		}
		if( !( pasmsrc = fopen (file_a, "r" ) ) ) {
			fprintf( stderr, "%s %s", opnerr, strupr( file_a ) );
			fclose( pcsrc );
			continue;
		}
		if( !( poutput = fopen( file_o, "w" ) ) ) {
			fprintf( stderr, "%s %s", opnerr, strupr( file_o ) );
			fclose( pcsrc );
			fclose( pasmsrc );
			continue;
		}

		fcount++;
		linecount = runcount = totlcount = 0L;

		printf( "\n%s", strupr( file_c ) );

		while( fgets( line, LINSIZ, pasmsrc ) ) {
			if( strncmp( line, "; Line", 6 ) ) {  /* do output */
				if( fputs( line, poutput ) == EOF )
					writefail();
				++totlcount;
				continue;		/* get next line */
			}
			linecount = atoi( &line[ 7 ] );	/* generate line */
			if( runcount < linecount )	/* if .C backlog */
				for( ; runcount < linecount;
						runcount++, totlcount++)
					mergeline();	/* catch up .C   */
			else {	/* output corresponding .c line */
				mergeline();
				runcount++;
				totlcount++;
			}
		}

		fclose( pcsrc );		/* close input files */
		fclose( pasmsrc );
		fclose( poutput );

		--runcount;
		--totlcount;

		if( VERBOSE )
			printf( " -- %ld, %ld", runcount, totlcount );
		} /* end of ELSE for if a flag ... */

	} /* end of main WHILE argc not zero */
	
	putchar( '\n' );
	if( COUNT && fcount )
		printf( "\n%d %s\n", fcount, endmsg );

	return 0;
}

void mergeline( void )
{
	fgets( line, LINSIZ, pcsrc );
	if( fputs( "; ", poutput ) == EOF )   /* delimiter for source line */
		writefail();
	if( fputs( line, poutput ) == EOF )
		writefail();

	return ;
}

char *wrterr = "\nmerge: can't write";

void writefail(void)
{
	/* output the failure message, and terminate execution */

	fprintf( stderr, "%s %s\n", wrterr, strupr( file_o ) );
	exit( 0x0C );
}