File:  [Repository ATC2] / ADD_ver_10 / Attic / Auxiliares.c
Revision 1.1: download - view: text, annotated - select for diffs
Thu Jan 19 17:16:29 2006 UTC (18 years, 8 months ago) by rico
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/********************************************************************/
/*  Auxiliares.c                                                    */
/*                                                                  */
/*  Copyright (c) 1997-2006 Rafael Rico      (rafael.rico@uah.es)   */
/*                                                                  */
/*  This file is part of ADD version 5.10.                          */
/*                                                                  */
/*  ADD is free software; you can redistribute it and/or modify     */
/*  it under the terms of the GNU General Public License as         */
/*  published by the Free Software Foundation; either version 2 of  */
/*  the License, or (at your option) any later version.             */
/*                                                                  */
/*  ADD is distributed in the hope that it will be useful,          */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of  */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   */
/*  GNU General Public License for more details.                    */
/*                                                                  */
/*  You should have received a copy of the GNU General Public       */
/*  License along with ADD; if not, write to the Free Software      */
/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA        */
/*  02111-1307  USA                                                 */
/*                                                                  */
/*  --------------------------- History --------------------------- */
/*                                                                  */
/*  Revision 1.2. 01/2006                                           */
/*  Added GPL License and JavaDoc style documentation               */
/*                                                                  */
/*  Revision 1.1. 09/2005                                           */
/*  Initial Revision                                                */
/*                                                                  */
/********************************************************************/


/******************************************************************************/
/* MÓDULO: Auxiliares.c                                                       */
/*                                                                            */
/* Este módulo contiene las funciones que crean ficheros.                     */
/******************************************************************************/
/* Fecha: 16 de septiembre de 2005                                            */
/******************************************************************************/

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

#include "defines.h"
#include "tipos.h"
#include "auxiliares.h"


/* configuración */
extern struct argumentos configuracion;

/* bases de datos */
extern unsigned int num_nemonicos;
extern operacion *nemonicos;
extern unsigned int num_simbolos;
extern operando *simbolos;
extern unsigned int num_tiempos;
extern tiempo *ciclos;

extern unsigned int num_ubicaciones;
extern ubicacion *datos;




/* LISTAS Y BASES DE DATOS */

/* funciones para manipular la base de datos */

int BDBuscarCadena(int idtabla, int idcampo, char *cadena)
{
    unsigned int i = 0;    /* los registros de las bases de datos comienzan en el índice 0 */
    int encontrado = NO;
	char mensaje[MAX_LINE];

    switch (idtabla)
    {
        case TABLA_NEMONICOS:
        switch (idcampo)
        {
            case CAMPO_NEMONICO:
            while(i<num_nemonicos && encontrado == NO)
            {
                if (strcmp(nemonicos[i].nemonico, cadena)) i++;  /* no encontrado */
                else encontrado = SI;   /* encontrado */
            }
            break;

            default:
            /* emitir un error al fichero de log */
			sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Nemónicos");
			Notificar(mensaje, ERROR_SALIR, ECO_NO);
            break;
        }
        break;

        case TABLA_SIMBOLOS:
        switch (idcampo)
        {
            case CAMPO_SIMBOLO:
            while(i<num_simbolos && encontrado == NO)
            {
                if (strcmp(simbolos[i].simbolo, cadena)) i++;  /* no encontrado */
                else encontrado = SI;   /* encontrado */
            }
            break;

            default:
            /* emitir un error al fichero de log */
			sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Símbolos");
			Notificar(mensaje, ERROR_SALIR, ECO_NO);
            break;
        }
        break;

        case TABLA_CICLOS:
        switch (idcampo)
        {
            case CAMPO_IDENTIFICADOR:
            while(i<num_tiempos && encontrado == NO)
            {
                if (strcmp(ciclos[i].identificador, cadena)) i++;  /* no encontrado */
                else encontrado = SI;   /* encontrado */
            }
            break;

            default:
            /* emitir un error al fichero de log */
			sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ciclos");
			Notificar(mensaje, ERROR_SALIR, ECO_NO);
            break;
        }
        break;

        case TABLA_UBICACIONES:
        switch (idcampo)
        {
            case CAMPO_NOMBRE:
            while(i<num_ubicaciones && encontrado == NO)
            {
                if (strcmp(datos[i].nombre, cadena)) i++;  /* no encontrado */
                else encontrado = SI;   /* encontrado */
            }
            break;

            default:
            /* emitir un error al fichero de log */
			sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ubicaciones");
			Notificar(mensaje, ERROR_SALIR, ECO_NO);
            break;
        }
        break;

		default:
        /* emitir un error al fichero de log */
		sprintf(mensaje, "[BDBuscarCadena] La tabla especificada no existe");
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
		break;
    }
    if(encontrado == NO) return(-1);
    else return(i);
}


/* listas */
/* esta función añade un elemento a una lista */

void AgregarElementoLista(char *lista, char *cadena)
{
    if (lista[0] == '\0') strcpy (lista, cadena);
    else {strcat (lista, ":"); strcat (lista, cadena);}
}



/* esta función busca un elemento en una lista y devuelve el índice o 0 si no está */

unsigned int BuscarElementoLista(char *lista, char *cadena)
{
	char copialista[MAX_LISTA];
    char *elemento;           /* es un puntero a char para la función strtok */
	unsigned int indice = 1; 

	strcpy(copialista, lista);

	elemento = strtok(copialista, ":");    /* el separador de elementos de la lista es ':' */
    while(elemento != NULL)
    {
        if(strcmp(elemento, cadena) == 0) return indice;
		else indice++;

		/* capturo el siguiente campo */
        elemento = strtok(NULL, ":");
    }
	return 0;
/* esta función se puede implementar también usando 'strstr' */
}



/* esta función elimina un elemento de una lista */

void EliminarElementoLista(char *lista, char *cadena)
{
	char *puntero;
	unsigned int indice1;
	unsigned int indice2 = 1;
	
	puntero = lista;
	indice1 = BuscarElementoLista(lista, cadena);

	if(indice1 == 0) return;

	while(indice2 != indice1)
	{
		if(*puntero == ':') indice2++;
		puntero++;
	}

	if(puntero != lista)		/* el elemento no es el primero */
	{
		*(puntero - 1) = '\0';	/* corto la cadena en el separador antes del elemento */
		if(*(puntero + strlen(cadena)) == ':')	/* el elemento no es el último */
		{
			strcat(lista, (puntero + strlen(cadena)));
		}
	}
	else strcpy(lista, (puntero + strlen(cadena) + 1));
}



/* INICIALIZACIÓN DE DATOS */

void IniciarTarjeta(fichainstruccion *tarjetaoperandos)
{
	strcpy(tarjetaoperandos->nemonico, "");
    strcpy(tarjetaoperandos->op1, "");
    strcpy(tarjetaoperandos->op2, "");
    strcpy(tarjetaoperandos->hexadecimal, "");
    tarjetaoperandos->longitud = 0;
    strcpy(tarjetaoperandos->prefijo, "");
    tarjetaoperandos->salto = NO_SALTO;
    tarjetaoperandos->ciclosALU = 0;
    tarjetaoperandos->ciclosBIU = 0;
    strcpy(tarjetaoperandos->leidoimpldatos, "");
    strcpy(tarjetaoperandos->leidoimpldir, "");
    strcpy(tarjetaoperandos->leidoimplpila, "");
    strcpy(tarjetaoperandos->leidoimplestado, "");
    strcpy(tarjetaoperandos->leidoexpldatos, "");
    strcpy(tarjetaoperandos->leidoexpldir, "");
    strcpy(tarjetaoperandos->leidoexplpila, "");
    strcpy(tarjetaoperandos->leidoexplestado, "");
    strcpy(tarjetaoperandos->escritoimpldatos, "");
    strcpy(tarjetaoperandos->escritoimpldir, "");
    strcpy(tarjetaoperandos->escritoimplpila, "");
    strcpy(tarjetaoperandos->escritoimplestado, "");
    strcpy(tarjetaoperandos->escritoexpldatos, "");
    strcpy(tarjetaoperandos->escritoexpldir, "");
    strcpy(tarjetaoperandos->escritoexplpila, "");
    strcpy(tarjetaoperandos->escritoexplestado, "");
}



/* HERRAMIENTAS */

unsigned long TamanoFichero(char *fichero)
{
	FILE *handle;
	unsigned long tamano = 0;
	char mensaje[MAX_LINE];


	if((handle = fopen(fichero, "rb")) != NULL)
    {
        /*
		sprintf(mensaje, "[TamañoFichero] El fichero '%s' se ha abierto con éxito", fichero);
		Notificar(mensaje, NO_ERROR, ECO_NO);
		*/

		fseek(handle, 0L, SEEK_END);
		tamano = ftell(handle);

        /* cierro el fichero */
        if(fclose(handle))
		{
			sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido cerrar", fichero);
			Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
		}
    }
    else
	{
		sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido abrir", fichero);
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
	}

	return tamano;
}



void DeterminarRango()
{
	unsigned long total_instrucciones;	/* total en la traza */
	unsigned long cantidad;				/* cantidad a analizar */
	char mensaje[MAX_LINE];

	/* calculo la cantidad de instrucciones en la traza a partir del tamaño del fichero */ 
	total_instrucciones = TamanoFichero(configuracion.ficherodatos)/BYTES_POR_INSTRUCCION;

	/*
	printf("Total instrucciones en '%s' = %lu\n", configuracion.ficherodatos, total_instrucciones);
	_getch();
	*/

	if(configuracion.ultima == 0)	/* significa que manda el rango */
	{
		cantidad = (unsigned long)(configuracion.rango * total_instrucciones)/100.00;
		
		if(configuracion.primera == 0)	/* significa que manda el porcentaje de comienzo */
		configuracion.primera = (unsigned long) 1 + (configuracion.comienzo * total_instrucciones)/100.00;
		/* la cuenta de instrucciones comienza en '1' */

		else if(configuracion.primera > total_instrucciones)
		{
			sprintf(mensaje, "[DeterminarRango] La primera instrucción está fuera del fichero de datos");
			Notificar(mensaje, ERROR_SALIR, ECO_NO);
		}
		configuracion.ultima = configuracion.primera + cantidad;
		if(configuracion.ultima > total_instrucciones) configuracion.ultima = total_instrucciones;
	}

	cantidad = configuracion.ultima - configuracion.primera + 1;
	
	if(cantidad < configuracion.ventana)
	{
		sprintf(mensaje, "[DeterminarRango] El rango de análisis es demasiado pequeño");
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
	}
}




/* ARITMÉTICAS */

/* esta función calcula el nuevo valor promedio de una serie de datos */
/* a partir del valor anterior y del valor en curso (actual) */

double CalcularNuevoPromedio (double promedioanterior, double valoractual, unsigned long n)
{
	double nuevopromedio;

	nuevopromedio = ((n - 1) * promedioanterior + valoractual) / n;

	return nuevopromedio;
}


/* esta función calcula el inverso normalizado y previene la división por 0 */

double InversoNormalizado (unsigned int dimension, double valor)
{
	double inverso;
	char mensaje[MAX_LINE];

	if(valor == 0.0)
	{
		sprintf(mensaje, "[InversoNormalizado] El valor del denominador es nulo");
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
	}

	if(dimension == 0)
	{
		sprintf(mensaje, "[InversoNormalizado] La dimensión de la normalización es nula");
		Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
	}

	inverso = dimension / valor;

	return inverso;
}



/* FORMATO */

/* esta función genera la cadena en lenguaje ensamblador de una instrucción */
/* a partir del prefijo, nemónico y operandos */
/* según un tipo de notación especificado (INTEL, ATT) */

void CadenaEnsamblador(char *prefijo, char *nemonico, char *operando1, char *operando2, unsigned char notacion, char *cadena)
{
	char auxiliar[2*MAX_NEMO + 2*MAX_OPE];
	
	switch(notacion)
	{
		case 0:		/* notación de INTEL */

		sprintf(cadena, "%s%s", prefijo, prefijo[0]!='\0' ? " ":"");

		sprintf(auxiliar, "%s", nemonico);
		strcat(cadena, auxiliar);

		sprintf(auxiliar, "%s%s", operando1[0]!='\0' ? " ":"", operando1);
		strcat(cadena, auxiliar);

		sprintf(auxiliar, "%s%s%s", (operando1[0]!='\0' && operando2[0]!='\0') ? ",":"", operando2[0]!='\0' ? " ":"", operando2);
		strcat(cadena, auxiliar);

		/* más elegante usar el índice que devuelve sprintf y sumarlo al puntero cadena */
		/* sprintf(cadena + i, ""... */
		break;

		case 1:		/* notación ATT */
		break;
	}
}


/* esta función convierte una cadena hexadecimal a una secuencia de bytes */

void ConvertirHex2Bin(char *cadenahex, unsigned char *secuencia, unsigned char maxformato)
{
	int i;
	char bytehex[3];
	char mensaje[MAX_LINE];

	/* control de errores */
	if(strlen(cadenahex)==0)
	{
		sprintf(mensaje, "[ConvertirHex2Bin] La cadena hexadecimal está vacía");
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
	}
	else if(strlen(cadenahex)%2!=0)
	{
		sprintf(mensaje, "[ConvertirHex2Bin] La cadena hexadecimal '%s' no contiene un número entero de bytes", cadenahex);
		Notificar(mensaje, ERROR_SALIR, ECO_NO);
	}
	
	/* relleno la secuencia de 2 instrucciones en binario con 0s */
	/* (2 instrucciones de tamaño máximo 'maxformato') */
	for(i=0; i<2*maxformato; i++) *(secuencia+i) = 0;
	
	do
	{
		for(i=0; i<2; i++)
		{
			bytehex[i]=*(cadenahex+i);
			if(isxdigit(bytehex[i])==0)		/* error -> dígito no hexadecimal */
			{
				sprintf(mensaje, "[ConvertirHex2Bin] El byte '%s' contiene un dígito no hexadecimal", cadenahex);
				Notificar(mensaje, ERROR_SALIR, ECO_NO);
			}
		}
		bytehex[3]='\0';
		sscanf(bytehex, "%2X", secuencia);
		secuencia++;
	}
	while(*(cadenahex+=2)!='\0');
}

/* NOTA: otra posibilidad para esta función consiste en copiar la cadena hexadecimal */
/* en un array y recorrer con un puntero dicha cadena desde el final de 2 en 2 caracteres */
/* antes de decrementar el puntero se corta el array con un \0 para "ver" 2 dígitos */
/* hexadecimales cada vez; este método consume memoria para el array y para el puntero */
/* si no copio la cadena hexadecimal la pierdo al trocearla con \0 */


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>