/* zliczanie wystąpień wyrazów w tekscie. przykład zastosowania drzewa
   binarnego.

   lekcja informatyki, druga klasa.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <limits.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

#define DELIM		"`~!@#$%^&*()-_+=|\\<>,./?;:[]{}'\"\n\r\t "
#define BUFSIZE		1024

static const char rcsid[] =
  "$Id: wyrazy.c,v 1.1.1.1 2001/05/21 15:36:41 venglin Exp $";

// definicja typu

typedef struct
{
	char *wyraz;
	int ile;
	struct wezel *lewy;
	struct wezel *prawy;
} wezel;

// funkcja konwertujaca duze litery na male w stringu :)

char *lowcase(s)
register char *s;
{
	char *ss = s;
	
	for (; *s = tolower(*s); ++s);
	return(ss);
}

// wygodna funkcja do bezpiecznego wyskakiwania z programu

void cleanup(code)
int code;
{
	if (code > 0) printf("Przechwycono sygnal: %d.\n
			Wykonywanie przerwane.\n", code);
	exit(code);
}

// funkcja wstawiajaca wyraz do struktury lub zmieniajaca pole 'liczba'

wezel *wstaw(d, wyraz)
wezel *d;
char *wyraz;
{
	int x;

	if (!d)
	{
		d = (wezel *)malloc(sizeof(wezel));
		
		if (!d)
		{
			perror("malloc()");
			cleanup(-1);
		}

		d->wyraz = strdup(wyraz);
		d->ile = 1;
		d->lewy = d->prawy = NULL;
	}

	else
		if (!(x = strcmp(wyraz, d->wyraz)))
			d->ile++;

		else if (x < 0)
			d->lewy = wstaw(d->lewy, wyraz);
		else
			d->prawy = wstaw(d->prawy, wyraz);

	return d;
}

// funkcja drukujaca na ekranie zawartosc drzewa

void pokaz(d)
wezel *d;
{
	if (d)
	{
		pokaz(d->lewy);
		printf("%4d %s\n", d->ile, d->wyraz);
		pokaz(d->prawy);
	}
}

// funkcja wczytujaca dany plik

void czytaj(nazwa)
char *nazwa;
{
	FILE *plik;
	char *wyraz, buf[BUFSIZE];
	wezel *d = NULL;

	if (!strcmp(nazwa, "-"))
		plik = stdin;
	else
	{

		if ((plik = fopen(nazwa, "r")) == NULL)
		{
			perror("fopen()");
			cleanup(-1);
		}
	}

	while(fgets(buf, sizeof(buf), plik))
	{
		for (wyraz = strtok(buf, DELIM);
		wyraz;
		wyraz = strtok(NULL, DELIM))
			d = wstaw(d, lowcase(wyraz));
	}

	pokaz(d);

	(void)fclose(plik);
	return;
}

// funkcja main()

int main(argc, argv)
int argc;
char **argv;
{
        signal(SIGHUP, cleanup);
	signal(SIGINT, cleanup);
	signal(SIGQUIT, cleanup);
	signal(SIGTERM, cleanup);
	signal(SIGSEGV, cleanup);
	signal(SIGBUS, cleanup);

	if (argc < 2)
	{
		fprintf(stderr, "usage: %s plik1 [plik2] [...]\n", argv[0]);
		cleanup(-1);
	}

	while (--argc > 0)
		czytaj(*++argv);

	exit(0);
}

