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

#ifdef __USAGE
%C - convert ABN_... variables in abvars.h to #defines
	and adjust abdefines.h
%C

Exit status:
0 - Done
1 - Files were converted already
2 or greater - an error occured
#endif

#define N 120

char line[ N ], word[ N ], name[ N ], value[ N ], *pos;

int getline( FILE *fp ) {
	if ( fgets( line, sizeof(line), fp ) == 0 )
		return 0;
	if ( ( pos = strchr( line, '\n' ) ) != NULL )
		*pos = '\0';
	pos = line;
	return 1;
	}

int iscsymb( unsigned char c ) {
	return
		isalnum( c ) || c == '_';
	}

char *getsymb( void ) {
	unsigned char c; char *dst = word;
	while ( isspace( c = *pos ) )
		++pos;
	if ( c == '\0' )
		return NULL;
	*dst = c;
	if ( iscsymb(c) )
		while ( iscsymb( c = *++pos ) )
			*++dst = c;
	else
		++pos;
	*++dst = '\0';
	return word;
	}

void err( const char *txt ) {
	perror( txt );
	exit( 2 );
	}

FILE *opn( const char *fn, const char *fm ) {
	FILE *fp;
	if ( ( fp = fopen( fn, fm ) ) == NULL )
		err( fn );
	return fp;
	}

int issymb( const char *symb ) {
	return ! strcmp( word, symb );
	}

int expect( const char *symb ) {
	return
		getsymb()
		&&	issymb( symb );
	}

int convertible( void ) {
	do	if ( ! getsymb() )
			return 0;
		while	(	issymb( "int" )
				||	issymb( "const" )
				||	issymb( "extern" )
					);
	if	(	memcmp( word, "ABN_", 4 )
		&&	memcmp( word, "ABI_", 4 )
			)
		return 0;
	strcpy( name, word );
	if ( ! getsymb() )
		return 0;
	if ( issymb( ";" ) ) {
		value[0] = '\0';
		return 1;
		}
	else {
		if	(	! issymb( "=" )
			||	! getsymb()
				)
			return 0;
		strcpy( value, word );
		return expect( ";" );
	}	}

int exit_status = 1;

void convert( const char *fn ) {
	char *backup; int chgd = 0;
	FILE *in, *out;
	if ( ( backup = malloc( strlen(fn) + 3 ) ) == NULL ) {
		fputs( "No memory\n", stderr );
		exit( 2 );
		}
	strcat( strcpy( backup, fn ), ".b" );
	remove( backup );
	if ( rename( fn, backup ) )
		err( fn );
	in = opn( backup, "r" );
	out = opn( fn, "w" );
	fprintf( stderr, "Converting %s:\n", fn );
	while ( getline( in ) )
		if ( ! convertible() )
			fprintf( out, "%s\n", line );
		else {
			if ( value[0] != '\0' ) {
				fprintf( stderr, "%s = %s\n", name, value );
				fprintf( out, "#define %s\t%s\n", name, value );
				/* Was there anything after the final ';' ? */
				if ( getsymb() )
					fprintf( out, "%s%s\n", word, pos );
				}
			else {
				fprintf( stderr, "%s\n", name );
				if ( chgd == 0 )
					fprintf( out, "#include \"abvars.h\"\n\n" );
				}
			++chgd;
			exit_status = 0;
			}
	fclose( in );
	fclose( out );
	if ( chgd == 0 ) {
		fprintf( stderr, "No changes.\n" );
		remove( fn );
		rename( backup, fn );
		}
	else
		fprintf( stderr, "%d changes.\n", chgd );

	free( backup );
	}

int main( void ) {
	convert( "abvars.h" );
	convert( "abdefine.h" );
	return exit_status;
	}
