/* MSG: Extract strings from a C program	*
 * by Carlo Borreo				*
 * Last revision: 26Dec88			*/

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

#define check(F,M) { if (!(F)) error(M); }

void main( int argc, char *argv[] ) ;
void extract( FILE *f_in, FILE *f_out, FILE *f_msg ) ;
char in( FILE *f_in ) ;
char lookahead( FILE *f_in ) ;
void error( char *msg ) ;
void mustbe( char c ) ;
void showuse() ;

char *notbal = "Program not balanced" ;

int top = 0 ;
char stack[ 100 ] ;

int msgctr = 0 ;

void main( int argc, char *argv[] )
{
char *s ;
char name  [ 80 ] ;
char source[ 80 ] ;
char target[ 80 ] ;
FILE *f_in, *f_out, *f_msg ;
int i ;

if ( argc < 3 || *argv[ 1 ] == '?' )
	showuse() ;
check( f_msg= fopen( argv[ --argc ], "w" ), "Can't open message file" ) ;
for ( i = 1 ; i < argc ; i++ )
	{
	strcpy( name, argv[ i ] ) ;
	strlwr( name ) ;
	s = strstr( name, ".c" ) ;
	if ( s != NULL )
		*s = 0 ;
	sprintf( source, "%s.c", name ) ;
	sprintf( target, "%s.m", name ) ;
	f_in = fopen( source, "r" ) ;
	if ( f_in == NULL )
		{
		fprintf( stderr, "Cannot open file %s", source ) ;
		exit( 20 ) ;
		}
	f_out= fopen( target, "w" ) ;
	if ( f_out == NULL )
		{
		fprintf( stderr, "Cannot create file %s", target ) ;
		exit( 20 ) ;
		}
	extract( f_in, f_out, f_msg ) ;
	check( f_in != NULL, "Can't open read file" ) ;
	check( f_out!= NULL, "Can't open write file" ) ;

	printf( "Processing file %s\n", source ) ;
	extract( f_in, f_out, f_msg ) ;

	fclose( f_in  ) ;
	fclose( f_out ) ;
	}
fclose( f_msg ) ;
exit( 0 ) ;
}

void extract( FILE *f_in, FILE *f_out, FILE *f_msg )
{
register char c, x ;

while ( ( c = getc( f_in ) ) != EOF )
    switch ( c )
	{
	case '(':
	case '[':
	case '{':
		stack[ top++ ] = c ;
		putc( c, f_out ) ;
		break ;
	case ')':
		putc( c, f_out ) ;
		mustbe( '(' ) ;
		break ;
	case ']':
		putc( c, f_out ) ;
		mustbe( '[' ) ;
		break ;
	case '}':
		putc( c, f_out ) ;
		mustbe( '{' ) ;
		break ;
	case '\"':
		while ( ( x = in( f_in ) ) != c )
			{
			check( x != '\n', notbal ) ;
			putc( x, f_msg ) ;
			if ( x == '\\' ) putc( in( f_in ), f_msg ) ;
			}
		putc( '\n', f_msg ) ;
		fprintf( f_out, "msg[ %d ]", msgctr++ ) ;
		break ;
	case '\'':
		putc( c, f_out ) ;
		do
			{
			x = in( f_in ) ;
			check( x != '\n', notbal ) ;
			putc( x, f_out ) ;
			if ( x == '\\' ) putc( in( f_in ), f_out ) ;
			}
		while ( x != c ) ;
		break ;
	case '/':
		if ( lookahead( f_in ) == '*' )
			{
			top++ ;	/* set top to non-zero */
			putc( '/', f_out ) ;
			do
				{
				x = in( f_in ) ;
				putc( x, f_out ) ;
				}
			while ( x != '*' || lookahead( f_in ) != '/' ) ;
			x = in( f_in ) ;
			putc( x, f_out ) ;
			--top ;
			}
		else
			putc( c, f_out ) ;
		break ;
	default:
		putc( c, f_out ) ;
		break ;
	}
}

char in( FILE *f_in )
{
char c ;

c = getc( f_in ) ;
check( c != EOF, notbal ) ;
return c ;
}

char lookahead( FILE *f_in )
{
char c = getc( f_in ) ;

ungetc( c, f_in ) ;
return c ;
}

void error( char *msg )
{
fprintf( stderr, "\n\n*** MSG: %s ***\n\n", msg ) ;
exit( 20 ) ;
}

void mustbe( char c )
{
check( top && stack[ --top ] == c, notbal ) ;
}

void showuse()
{
fprintf( stderr, "\nMSG: Extract messages from a C program\n" ) ;
fprintf( stderr, "\nUsage:\n\tMSG file1.c .. fileN.c file.msg\n" ) ;
fprintf( stderr, "\nBy\n\tCarlo Borreo, Via G. Berio 34, I-18100 Imperia, Italy\n" ) ;
fprintf( stderr, "\tPh. +39/(0)183/21833\n\n" ) ;
exit( 20 ) ;
}
