/*	beable.c	Replaces words in text with "beable",
			except for words on an exclusion list.
			Author:		acb
			Commenced:	10-3-1994

	This program is part of the Emperor Norton Utilities.
	All rites reversed.

	This program replaces all words or wordoids in the
	standard input with 'beable', or a user defined word.
	Exclusion lists can be set, specifying words which are
	left intact.

	i.e.;
	
	% beable
	The quick brown fox
	Beable beable beable beable

	% beable -b blah
	TIME HAS INERTIA.
	BLAH BLAH BLAH

	% beable -x unix amiga bites roolz
	Every one knows UNIX bites badly. The ***Amiga*** roolz d00d!
	Beable beable beable UNIX bites beable. Beable ***Amiga*** roolz beable!
	
 */

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

#define MAXUNBEABLE	32	/* # of words in exclusion list */
#define MAXWORDLENGTH	64	/* for the scientific community */
#define DEFBEABLE	"beable"

#define UPPERCASE	0
#define MixedCase	1
#define lowercase	2

char beable[3][MAXWORDLENGTH];

char unbeable[MAXUNBEABLE][MAXWORDLENGTH];
int num_unbeable=0;

/* init_beable() sets up beable[], filling it with beables of the 
   appropriate form */

void init_beable(char *b)
{
	int i, len;

	if (!b) b=DEFBEABLE;
	len = strlen(b);

	/*printf("strlen(%s) == %i\n", b, len);*/
	for(i=0; i<=len; i++) {
		beable[UPPERCASE][i] = (isupper(*b) ? *b : toupper(*b));
		beable[lowercase][i] = (isupper(*b) ? tolower(*b) : *b);
		beable[MixedCase][i] = (i) ? beable[lowercase][i] :
			beable[UPPERCASE][i];
		b++;
	};
	/*printf("%s %s %s\n", beable[0], beable[1], beable[2]);*/
};

/* seekword() seeks forward to the next word or wordoid, printing
   all characters encountered. */

void seekword()
{
	char c;

	while(!isalpha(c=getc(stdin)))  {
		if(c==EOF) exit(0);
		putchar(c);
	};
	ungetc(c, stdin);
};

/* handle_word handles a word, replacing it with "beable" if appropriate */

void handle_word()
{
	static char word[MAXWORDLENGTH];
	int word_length=0;
	char c;
	int is_exempt = 0;
	int i;

	while(isalpha(c=getchar()))
		word[word_length++]=c;

	word[word_length]='\0';

	ungetc(c, stdin);

	for(i=0; i<num_unbeable; i++) {
/*		printf("Comparing %s and %s\n", word, unbeable[i]);*/
		if(strcasecmp(word, unbeable[i])==0) {
			printf("%s", word);
			is_exempt = 1;
		};
	};

	if(!is_exempt)
		printf("%s", beable[isupper(word[0]) ? ( isupper(word[1]) 
			? UPPERCASE : MixedCase ) : lowercase ]);
};

void usage()
{
	printf("usage: beable [-x exclude1 exclude2..] [-b word]\n");
	exit(1);
};

void parse_params(int argc, char *argv[])
{
	char *beableword = NULL;
	int i=1;

	while(i<argc) {
		if(*(argv[i])!='-') usage();
		switch((argv[i])[1]) {
		case 'b':
			beableword = argv[++i];
			break;
		case 'x':
			while((i<argc) && (*(argv[i+1])!='-')) {
				strcpy(unbeable[num_unbeable++], argv[++i]);
				printf("%s added to exclusion list.\n", argv[i]);
				if(i+1>=argc) break;
			};
			break;
		default: usage();
		};
		i++;
	};
	init_beable(beableword);
};

main(int argc, char *argv[])
{
	parse_params(argc, argv);

	while(!feof(stdin)) {
		seekword();
		handle_word();
	};
};
