File:  [Repository ATC2] / ADD_ver_10 / Source Code / Source Files / Auxiliares.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Feb 28 14:54:21 2006 UTC (18 years, 6 months ago) by rico
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/********************************************************************/
/*  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>