/*	$Id: umatrix.c,v 1.4 1997/05/01 18:15:14 sandro Exp $	*/

/*
 * Copyright (c) 1997
 *	Sandro Sigala, Brescia, Italy.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "matrici.h"
#include "umatrix.h"

#define MAXSTACKSIZE 36

Matrice stack[MAXSTACKSIZE];
int stacksize = 0;

void push(Matrice m)
{
	if (stacksize < MAXSTACKSIZE)
		stack[stacksize++] = m;
}

Matrice pop(void)
{
	if (stacksize > 0)
		return stack[--stacksize];
	else
		return NULL;
}

#define VOF(v) v ? getstr("vero") : getstr("falso")

int disp(char *funname, int n)
{
	if (stacksize >= n)
		return 1;
	fprintf(stderr, getstr("%s: numero elementi presenti sullo stack insufficiente (%d/%d).\n"), funname, n, stacksize);
	return 0;
}

void predicato(char *pr)
{
	int len;

	len = strlen(pr);
	if (!len) {
		fprintf(stderr, getstr("Predicato errato.\n"));
		return;
	}

	if (!strncmp(pr, getstr("?quadrata"), len)) {
		if (disp(getstr("?quadrata"), 1))
			printf(getstr("%s e` una matrice quadrata: %s.\n"),
			       stack[stacksize-1]->nome,
			       VOF(matr_quadrata_p(stack[stacksize-1])));
	} else if (!strncmp(pr, getstr("?rettangolare"), len)) {
		if (disp(getstr("?rettangolare"), 1))
			printf(getstr("%s e` una matrice rettangolare: %s.\n"),
			       stack[stacksize-1]->nome,
			       VOF(matr_rettangolare_p(stack[stacksize-1])));
	} else if (!strncmp(pr, getstr("?unita`"), len)) {
		if (disp(getstr("?unita`"), 1))
			printf(getstr("%s e` una matrice unita`: %s.\n"),
			       stack[stacksize-1]->nome,
			       VOF(matr_unita_p(stack[stacksize-1])));
	} else if (!strncmp(pr, getstr("?simmetrica"), len)) {
		if (disp(getstr("?simmetrica"), 1))
			printf(getstr("%s e` una matrice simmetrica: %s.\n"),
			       stack[stacksize-1]->nome,
			       VOF(matr_simmetrica_p(stack[stacksize-1])));
	} else if (!strncmp(pr, getstr("?stessotipo"), len)) {
		if (disp(getstr("?stessotipo"), 2))
			printf(getstr("%s e %s sono dello stesso tipo: %s.\n"),
			       stack[stacksize-1]->nome,
			       stack[stacksize-2]->nome,
			       VOF(matr_stesso_tipo_p(stack[stacksize-1],
						      stack[stacksize-2])));
	} else if (!strncmp(pr, getstr("?eguali"), len)) {
		if (disp(getstr("?eguali"), 2))
			printf(getstr("%s e %s sono eguali: %s.\n"),
			       stack[stacksize-1]->nome,
			       stack[stacksize-2]->nome,
			       VOF(matr_eguali_p(stack[stacksize-1],
						 stack[stacksize-2])));
	} else
		fprintf(stderr, getstr("Predicato errato.\n"));
}

char *readline(char *prompt)
{
	static char buf[128];
	printf(prompt); fflush(stdout);
	if (fgets(buf, 128, stdin) != NULL) {
		buf[strlen(buf)-1] = '\0';
		return buf;
	} else
		return NULL;
}

char *crea_nome(void)
{
	static char buf[10];
	sprintf(buf, "m%d", stacksize);
	return buf;
}

void funz_crea(void)
{
	push(matr_leggi(crea_nome()));
}

void funz_creacasuale(void)
{
	push(matr_leggi_casuale(crea_nome()));
}

void funz_creaunita(void)
{
	push(matr_leggi_unita(crea_nome()));
}

void funz_elimina(void)
{
	if (disp(getstr("elimina"), 1))
		matr_elimina(pop());
}

void funz_determinante(void)
{
	if (disp(getstr("determinante"), 1)) {
		double d;
		d = matr_determinante(stack[stacksize-1]);
		printf(getstr("Determinante di %s(%d ordine) = %f\n"),
		       stack[stacksize-1]->nome, stack[stacksize-1]->righe, d);
	}
}

void funz_parametri(void)
{
	int i;
	do {
		printf(getstr("Parametri correnti: lingua <%s>, stile <%s>\n"),
		       lingua == LINGUA_ITALIANA ? getstr("italiano") : getstr("inglese"),
		       stile == STILE_CLASSICO ? getstr("classico") : getstr("alternativo"));
		printf(getstr("\t1 - Cambia lingua\n"));
		printf(getstr("\t2 - Cambia stile\n"));
		printf(getstr("\t3 - Torna al menu precedente\n"));
		do i = leggi_long(getstr("Scelta")); while (i < 1 && i > 3);
		if (i == 1)
			lingua = lingua == LINGUA_ITALIANA ? LINGUA_INGLESE : LINGUA_ITALIANA;
		else if (i == 2)
			stile = stile == STILE_CLASSICO ? STILE_ALTERNATIVO : STILE_CLASSICO;
	} while (i != 3);
}

void funz_trasposta(void)
{
	Matrice m;

	if (disp(getstr("trasposta"), 1)) {
		if ((m = matr_trasposta(crea_nome(), stack[stacksize-1])) != NULL)
			push(m);
	}
}

void funz_somma(void)
{
	Matrice m;

	if (disp(getstr("somma"), 2)) {
		if ((m = matr_somma(crea_nome(), stack[stacksize-2], stack[stacksize-1])) != NULL)
			push(m);
	}
}

void funz_prodotto(void)
{
	Matrice m;

	if (disp(getstr("prodotto"), 2)) {
		if ((m = matr_prodotto(crea_nome(), stack[stacksize-2], stack[stacksize-1])) != NULL)
		    push(m);
	}
}

void funz_prodottopernumero(void)
{
	Matrice m;
	double d;

	if (disp(getstr("prodottopernumero"), 1)) {
		d = leggi_double(getstr("Numero"));
		if ((m = matr_prodotto_per_numero(crea_nome(), stack[stacksize-1], d)) != NULL)
		    push(m);
	}
}

void funz_aiuto(void)
{
	printf(aiuto_tbl[lingua]);

	if (stacksize > 0) {
		printf(getstr("Premere invio per continuare\n"));
		getchar();
	}
}

void shell(void)
{
	int i, len;
	char *cmd;

	for (;;) {
		struct { char *nome; void (*funz)(); } funz_tbl[] = {
			getstr("aiuto"), funz_aiuto,
			getstr("crea"), funz_crea,
			getstr("creacasuale"), funz_creacasuale,
			getstr("creaunita`"), funz_creaunita,
			getstr("determinante"), funz_determinante,
			getstr("elimina"), funz_elimina,
			getstr("parametri"), funz_parametri,
			getstr("prodotto"), funz_prodotto,
			getstr("prodottopernumero"), funz_prodottopernumero,
			getstr("somma"), funz_somma,
			getstr("trasposta"), funz_trasposta,
		};

		if (stacksize > 0) {
			printf(getstr("\nStack delle matrici:\n"));
			for (i = 0; i < stacksize; i++)
				matr_stampa(stack[i]);
		}

		if ((cmd = readline("uMatrix >>")) == NULL)
			break;
		else if (cmd[0] == '?')
			predicato(cmd);
		else if ((len = strlen(cmd)) == 0)
			continue;
		else if (!strncmp(cmd, getstr("esci"), len))
			break;
		else {
			for (i = 0; i < sizeof funz_tbl / sizeof funz_tbl[0]; i++)
				if (!strncmp(cmd, funz_tbl[i].nome, len)) {
					funz_tbl[i].funz();
					break;
				}
			if (i == sizeof funz_tbl / sizeof funz_tbl[0])
				fprintf(stderr, getstr("Comando errato (`aiuto' per maggiori informazioni)\n"));
		}
	}
}

int main(int argc, char **argv)
{
	srand(time(NULL));

	printf("uMatrix 1.1\n");
	printf("Copyright (c) 1997 Sandro Sigala <ssigala@globalnet.it>\n");
	printf(getstr("Digitare `aiuto' per maggiori informazioni\n\n"));

	shell();

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1