/* GRAMMER ERROR FINDER PROGRAM                   */
/* r p sarna                                      */

/* !!!!!!!!!!!!!!! COPYLEFTED !!!!!!!!!!!!!!!!!!! */
/* !!!!!!!!!See notice below in code !!!!!!!!!!!! */

/* original version: 25 Sep 1990                  */

/* FINDS:                                         */
/*                                                */

#define VERSION "$Revision: 1.5 $"

#define YES 1
#define NO 2
#define TRUE 1
#define FALSE 0

#define COMMA ','
#define PERIOD '.'
#define LPAREN '('
#define RPAREN ')'
#define LBRACKET '['
#define RBRACKET ']'
#define LBRACE '{'
#define RBRACE '}'
#define ON 1
#define OFF 0

#define UNIXFLAG 0

#ifdef __UNIX__
#undef UNIXFLAG
#define UNIXFLAG 1
#endif
#ifdef __unix__
#undef UNIXFLAG
#define UNIXFLAG 1
#endif
#ifdef unix
#undef UNIXFLAG
#define UNIXFLAG 1
#endif
#ifdef UNIX
#undef UNIXFLAG
#define UNIXFLAG 1
#endif

#define MSDOSFLAG 0

#ifdef __MSDOS__
#undef MSDOSFLAG
#define MSDOSFLAG 1
#endif
#ifdef MSDOS
#undef MSDOSFLAG
#define MSDOSFLAG 1
#endif

/* the following, as well as all Amiga references by TCS 10/7/90 */
#define AMIGAFLAG 0

#ifdef AMIGA
#undef AMIGAFLAG
#define AMIGAFLAG 1
#endif
#ifdef amiga
#undef AMIGAFLAG
#define AMIGAFLAG 1
#endif
#ifdef __AMIGA__
#undef AMIGAFLAG
#define AMIGAFLAG 1
#endif
#ifdef __amiga__
#undef AMIGAFLAG
#define AMIGAFLAG 1
#endif

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

char id[] = "$Header: /u/red/programs/grammar/grammar.c,v 1.5 90/09/25 20:44:38 red Exp Locker: red $";

char copyleft1[] = "Copyright (c) 1990 R. P. Sarna.  All Rights Reserved";
char copyleft2[] = "Free distribution allowed if source also given";

char prevw[35];
char currw[35];

FILE *fopen();
FILE *ibuf;

void exit(int);
int makeupper(char);
int getword(void);
int isletter(char);
int givechar(void);
int issmall(char);
int lastchars(char *str, char *pat);

char newword[25];
long int nline;
int endsent;
int exclams;
int hyphens;
long int nword;
int verys;
int ands;
int adverbs;
int ings;
int passives;
int nsent;
int lastchar;
int begsent;
int vflag;	/* to throw away ventura stuff */
int tflag;	/* to check for word "that" */
  
float words_sent;
float adverbs_sent;
float ings_sent;
float exclams_sent;
float verys_sent;
float ands_sent;
float passives_sent;
float hyphens_sent;

void main(int argc, char **argv)
{
	int namearg;
	
	char tversion[30];
	char version[10];
	char dummy[19];

	vflag = FALSE;
	tflag = FALSE;
	newword[0] = '\0';
	nline = 0L;
	endsent = TRUE;
	begsent = TRUE;
	nsent = 1;
	exclams = 0;
	hyphens = 0;
	verys = 0;
	ands = 0;
	ings = 0;
	adverbs = 0;
	passives = 0;
	nword = 0;
	namearg = 1;

	prevw[0] = '\0';
					
	strcpy(tversion, VERSION);
	sscanf(tversion, "%s %s", dummy, version);
#if UNIXFLAG
	strcat(version, " (Unix)");
#endif
#if MSDOSFLAG
	strcat(version, " (MS-DOS)");
#endif
#if AMIGAFLAG
	strcat(version, " (Amiga)");
#endif

	if ((argv[1][0] == '-') && (argv[1][1] == 'h')) {
		printf("GRAMMAR\n");
		printf("     r p sarna   Version %s\n", version);
		printf("\nThis program checks for improper grammar.\n");
		printf("\nThe program looks for:");
		printf("\n   Repeated words.");
		printf("\n   Split infinitives.");
		printf("\n   Sentences beginning with AND or BUT.");
		printf("\n   Sentences ending with prepositions.");
		printf("\n   Use of the word VERY.");
		printf("\n   Use of the word THAT (with -t option).");
		printf("\n   Possible use of LIKE instead of AS.");
		printf("\n   Double negatives.");
		printf("\n   Some types of wordiness.");
		printf("\n   Improper pronoun use.\n");

#if UNIXFLAG
		printf("\nUsage: %s [-v -t] filename\n", argv[0]);
#else
		printf("\nUsage: grammar [-v -t] filename\n");
#endif
		printf(  "       (-v for Xerox Ventura Publisher files)\n");
		printf(  "       (-t to show lines with word THAT)\n");
		exit(1);
	}


	if ((argv[1][0] == '-') && (argv[1][1] == 'v')) {
		vflag = TRUE;
		namearg++;
	}
	if ((argv[2][0] == '-') && (argv[2][1] == 'v')) {
		vflag = TRUE;
		namearg++;
	}
	if ((argv[1][0] == '-') && (argv[1][1] == 't')) {
		tflag = TRUE;
		namearg++;
	}
	if ((argv[2][0] == '-') && (argv[2][1] == 't')) {
		tflag = TRUE;
		namearg++;
	}

	if (argc < (namearg + 1)) {
#if UNIXFLAG
		printf("\nUsage: %s [-v -t] filename", argv[0]);
		printf("\n    or %s -help\n", argv[0]);
#else
		printf("\nUsage: grammar [-v -t] filename");
		printf("\n    or grammar -help\n");
#endif
		exit(1);
	}

	if ((ibuf = fopen(argv[namearg], "r")) == NULL) {
#if UNIXFLAG
		fprintf(stderr, "error: %s: can't find %s\n", argv[0], argv[namearg]);
#else
		fprintf(stderr, "error: grammar: can't find %s\n", argv[namearg]);
#endif
		exit(1);
	}
	
	printf("\n\nGRAMMAR CHECKING PROGRAM  --  r p sarna  -- Ver. %s\n", version);
	printf(    "     Copyright (c) 1990 R. P. Sarna.  All Rights Reserved.\n");
	printf(    "        Free distribution allowed if source also given.\n");
	printf("\n-------------------------\n");

	while (getword() == TRUE) {
		strcpy(currw, newword);

		if (begsent) {
			if (!(strcmp(currw, "AND"))) 
			  printf("A sentence begins with AND in line %ld.\n",
			  nline);
			if (!(strcmp(currw, "BUT"))) 
			  printf("A sentence begins with BUT in line %ld.\n",
			  nline);
			begsent = FALSE;
		}
				
		if (endsent) begsent = TRUE;
			
		if (!(strcmp(prevw, currw)))
			printf("The word %s is repeated in line %ld.\n",
					currw, nline);
	
		if (!(strcmp(currw, "VERY"))) {
			printf("Is the use of the word VERY in line %ld necessary?\n", nline);
			verys++;
		}
	
		if (tflag)
			if (!(strcmp(currw, "THAT"))) {
				printf("Is the word THAT necessary in line %ld?\n", nline);
			};
	
		if ((!(strcmp(prevw, "LIKE"))) && (!(strcmp(currw, "I")))) {
			printf("Possible use of LIKE instead of AS in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "LIKE"))) && (!(strcmp(currw, "WE")))) {
			printf("Possible use of LIKE instead of AS in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "LIKE"))) && (!(strcmp(currw, "HE")))) {
			printf("Possibly AS should be used instead of LIKE in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "LIKE"))) && (!(strcmp(currw, "SHE")))) {
			printf("Possibly AS should be used instead of LIKE in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "LIKE"))) && (!(strcmp(currw, "THEY")))) {
			printf("Possibly AS should be used instead of LIKE in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "NOT"))) && (!(strcmp(currw, "HARDLY")))) {
			printf("The double negative NOT HARDLY is used in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "HARDLY"))) && (!(strcmp(currw, "NOT")))) {
			printf("The double negative HARDLY NOT is used in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "HARDLY"))) && (!(strcmp(currw, "EVER")))) {
			printf("The double negative HARDLY EVER is used in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "HARDLY"))) && (!(strcmp(currw, "NEVER")))) {
			printf("The double negative HARDLY NEVER is used in line %ld.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "NOTE"))) && (!(strcmp(currw, "THAT")))) {
			printf("The phrase NOTE THAT in line %ld may be excessively wordy.\n",
				nline);
		}
	
		if ((!(strcmp(prevw, "AS"))) && (!(strcmp(currw, "US")))) {
			printf("Use WE instead of %s in line %ld.\n",
				currw, nline);
		}
	
		if ((!(strcmp(prevw, "AS"))) && (!(strcmp(currw, "HIM")))) {
			printf("Use HE instead of %s in line %ld.\n",
				currw, nline);
		}
	
		if ((!(strcmp(prevw, "AS"))) && (!(strcmp(currw, "HER")))) {
			printf("Possible misuse of %s instead of SHE in line %ld.\n",
				currw, nline);
		}
	
		if ((!(strcmp(prevw, "THAN"))) && (!(strcmp(currw, "US")))) {
			printf("Use WE instead of %s in line %ld.\n",
				currw, nline);
		}
	
		if ((!(strcmp(prevw, "THAN"))) && (!(strcmp(currw, "HIM")))) {
			printf("Use HE instead of %s in line %ld.\n",
				currw, nline);
		}
	
		if ((!(strcmp(prevw, "THAN"))) && (!(strcmp(currw, "HER")))) {
			printf("Possibly use SHE instead of %s in line %ld.\n",
				currw, nline);
		}
	
		if ((endsent) && (!(strcmp(currw, "OF")))) {
			printf("A sentence ends with the preposition %s in line %ld.\n",
				currw, nline);
		}
	
		if ((endsent) && (!(strcmp(currw, "WITH")))) {
			printf("A sentence ends with the preposition %s in line %ld.\n",
				currw, nline);
		}

		if ((endsent) && (!(strcmp(currw, "TO")))) {
			printf("A sentence ends with the preposition %s in line %ld.\n",
				currw, nline);
		}

		if ((!(strcmp(prevw, "TO"))) && (lastchars(currw, "LY"))) {
			printf("%s %s appears to be a split infinitive in line %ld.\n",
				prevw, currw, nline);
		}
	
		if (!(strcmp(currw, "IS"))) passives++;
		if (!(strcmp(currw, "WAS"))) passives++;
		if (!(strcmp(currw, "WERE"))) passives++;
		if (!(strcmp(currw, "ARE"))) passives++;
		if (!(strcmp(currw, "AND"))) ands++;
		if (lastchars(currw, "ING")) ings++;
		if (lastchars(currw, "LY")) adverbs++;
		
		strcpy(prevw, currw);
	}
	printf("\n-------------------------\n");
	printf("Number of sentences: %d\n", nsent - 1);
	printf("Number of words: %d\n\n", nword);

	if (nsent < 1) nsent = 1;
	words_sent = (float)nword / (float)(nsent - 1);
	adverbs_sent = (float)adverbs / (float)(nsent - 1);
	ings_sent = (float)ings / (float)(nsent - 1);
	exclams_sent = (float)exclams / (float)(nsent - 1);
	verys_sent = (float)verys / (float)(nsent - 1);
	ands_sent = (float)ands / (float)(nsent - 1);
	passives_sent = (float)passives / (float)(nsent - 1);
	hyphens_sent = (float)hyphens / (float)(nsent - 1);
	
	printf("The average number of words per sentence is %0.3f\n", words_sent);
	printf("   For comparison: Steinbeck = 16.397  Hemingway = 15.782  BYTE = 22.000\n");

	printf("The average number of adverbs per sentence is %0.3f\n", adverbs_sent);
	printf("   For comparison: Steinbeck = 0.247  Hemingway = 0.253  BYTE = 0.328\n");

	printf("The average number of words ending in -ING per sentence is %0.3f\n", ings_sent);
	printf("   For comparison: Steinbeck = 0.342  Hemingway = 0.425  BYTE = 0.484\n");

	printf("The average number of exclamation points per sentence is %0.3f\n", exclams_sent);
	printf("   For comparison: Steinbeck = 0.000  Hemingway = 0.000  BYTE = 0.000\n");

	printf("The average number of uses of VERY per sentence is %0.3f\n", verys_sent);
	printf("   For comparison: Steinbeck = 0.027  Hemingway = 0.092  BYTE = 0.000\n");

	printf("The average number of uses of AND per sentence is %0.3f\n", ands_sent);
	printf("   For comparison: Steinbeck = 1.219  Hemingway = 0.609  BYTE = 0.688\n");

	printf("The average number of passive verbs per sentence is %0.3f\n", passives_sent);
	printf("   For comparison: Steinbeck = 0.233  Hemingway = 0.437  BYTE = 0.250\n");
	
	printf("The average number of hyphens per sentence is %0.3f\n", hyphens_sent);
	printf("   For comparison: Steinbeck = 0.000  Hemingway = 0.034  BYTE = 0.703\n");

	fclose(ibuf);
	exit(0);

}

/* ########## end of main() ########## */

int getword(void)
{
	static int c;
	char string[25];
	int p;
	
	if (endsent) endsent = FALSE;
	
	p = 0;
	if (c == '\n') nline++;
	while ((!isletter(c = givechar())) && (c != EOF));
	if (c == EOF) {
		newword[p] = '\0';
		return(FALSE);
	}
	if (isletter(c)) {
		newword[p] = makeupper(c);
		p++;
	}
	while (((c = givechar()) != EOF) && (isletter(c))) {
		newword[p] = makeupper(c);
		p++;
	}
	newword[p] = '\0';
	nword++;
	
	if (c == EOF) return(FALSE);
	return(TRUE);
}

int isletter(char c)
{
	if ((c >= 'A') && (c <= 'Z')) return(TRUE);
	if ((c >= 'a') && (c <= 'z')) return(TRUE);
	if ((c >= '0') && (c <= '9')) return(TRUE);

	if (c =='!') exclams++;
	if (c == '\n') nline++;
	if (c == '-') hyphens++;
	if ((c == '-') && (lastchar == '-')) hyphens = hyphens - 2;
	if (hyphens < 0) hyphens = 0;
	if ((c == '.') && (issmall(lastchar))) {
		nsent++;
		endsent = TRUE;
	}
	if ((c == '!') && (issmall(lastchar))) {
		nsent++;
		endsent = TRUE;
	}
	if ((c == '?') && (issmall(lastchar))) {
		nsent++;
		endsent = TRUE;
	}

	return(FALSE);

}

int makeupper(char c)
{
	if ((c >= 'a') && (c <= 'z')) c = c - ('a' - 'A');
	return(c);
}

int givechar(void)
{
	static int charin;
	
	lastchar = charin;
	charin = fgetc(ibuf);

	/* Throw away Ventura stuff (duplicate in case stacked
	   format commands): */
	if (vflag) {
		if (charin == '<') {
			while ((charin = fgetc(ibuf)) != '>');
			charin = fgetc(ibuf);
		}
		if (charin == '<') {
			while ((charin = fgetc(ibuf)) != '>');
			charin = fgetc(ibuf);
		}
		if (charin == '<') {
			while ((charin = fgetc(ibuf)) != '>');
			charin = fgetc(ibuf);
		}
		if (charin == '@') {
			while ((charin = fgetc(ibuf)) != '=');
			charin = fgetc(ibuf);
		}
		if (charin == '@') {
			while ((charin = fgetc(ibuf)) != '=');
			charin = fgetc(ibuf);
		}
		if (charin == '@') {
			while ((charin = fgetc(ibuf)) != '=');
			charin = fgetc(ibuf);
		}
	}
        /* end Ventura */

	return(charin);

}

int issmall(char x)
{
	if ((x >= 'a') && (x <= 'z')) return(TRUE);
	else return(FALSE);
	
}

int lastchars(char *str, char *pat)
{
	char *ps;
	char *pp;
	int flag;
	
	flag = TRUE;
	
	ps = (char *)((int)str + (strlen(str) - 1));
	pp = (char *)((int)pat + (strlen(pat) - 1));

	while ((ps >= str) && (pp >= pat)) {
		if (*ps != *pp) flag = FALSE;
		ps--;
		pp--;
	}
	return(flag);
	
}

