/********************************************************************/
/* Auxiliares.c */
/* */
/* */
/* Copyright (c) 1997-2006 Rafael Rico (rafael.rico@uah.es) */
/* */
/* Este fichero forma parte de ADD */
/* (Analizador de Dependencias de Datos) */
/* Version 5.10. */
/* */
/* */
/* ADD es software libre. Puede redistribuirlo y/o modificarlo */
/* bajo los términos de la Licencia Pública General de GNU */
/* según es publicada por la Free Software Foundation, bien bajo */
/* la versión 2 de dicha Licencia o bien (según su elección) */
/* bajo cualquier versión posterior. */
/* */
/* ADD se distribuye con la esperanza de que sea útil, */
/* pero SIN NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL */
/* implícita y sin garantizar la CONVENIENCIA PARA UN PROPÓSITO */
/* PARTICULAR. Véase la Licencia Pública General de GNU para */
/* más detalles. */
/* */
/* Debería haber recibido una copia de la Licencia Pública General */
/* junto con ADD. Si no ha sido así, escriba a la Free Software */
/* Foundation, Inc., 51 Franklin St, Fifth Floor, */
/* Boston, MA 02110-1301 EEUU. */
/* */
/* -------------------------- Historia --------------------------- */
/* */
/* $Id: Auxiliares.c,v 1.2 2006/02/28 14:54:21 rico Exp $ */
/* */
/* Revisión 1.2. 01/2006 */
/* Se añade la licencia GPL y documentación en estilo Javadoc */
/* */
/* Revisión 1.1. 09/2005 */
/* Versión inicial */
/* */
/********************************************************************/
/******************************************************************************/
/* 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; */
cantidad = (unsigned long)((configuracion.rango/100.00) * total_instrucciones);
if(configuracion.primera == 0) /* significa que manda el porcentaje de comienzo */
/* configuracion.primera = (unsigned long) 1 + (configuracion.comienzo * total_instrucciones)/100.00; */
configuracion.primera = (unsigned long) 1 + (configuracion.comienzo/100.00) * total_instrucciones;
/* 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; */
nuevopromedio = promedioanterior + (double)((valoractual - promedioanterior) / 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>