Annotation of ADD_ver_10/Source Code/Source Files/Auxiliares.c, revision 1.1
1.1 ! rico 1: /********************************************************************/
! 2: /* Auxiliares.c */
! 3: /* */
! 4: /* Copyright (c) 1997-2006 Rafael Rico (rafael.rico@uah.es) */
! 5: /* */
! 6: /* This file is part of ADD version 5.10. */
! 7: /* */
! 8: /* ADD is free software; you can redistribute it and/or modify */
! 9: /* it under the terms of the GNU General Public License as */
! 10: /* published by the Free Software Foundation; either version 2 of */
! 11: /* the License, or (at your option) any later version. */
! 12: /* */
! 13: /* ADD is distributed in the hope that it will be useful, */
! 14: /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
! 15: /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
! 16: /* GNU General Public License for more details. */
! 17: /* */
! 18: /* You should have received a copy of the GNU General Public */
! 19: /* License along with ADD; if not, write to the Free Software */
! 20: /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
! 21: /* 02111-1307 USA */
! 22: /* */
! 23: /* --------------------------- History --------------------------- */
! 24: /* */
! 25: /* Revision 1.3. 02/2006 */
! 26: /* Fix overflow error in expresion evaluating 'cantidad' */
! 27: /* */
! 28: /* Revision 1.2. 01/2006 */
! 29: /* Added GPL License and JavaDoc style documentation */
! 30: /* */
! 31: /* Revision 1.1. 09/2005 */
! 32: /* Initial Revision */
! 33: /* */
! 34: /********************************************************************/
! 35: /******************************************************************************/
! 36: /* MÓDULO: Auxiliares.c */
! 37: /* */
! 38: /* Este módulo contiene las funciones que crean ficheros. */
! 39: /******************************************************************************/
! 40: /* Fecha: 16 de septiembre de 2005 */
! 41: /******************************************************************************/
! 42:
! 43: #include <stdio.h>
! 44: #include <stdlib.h>
! 45: #include <string.h>
! 46: #include <ctype.h>
! 47:
! 48: #include "defines.h"
! 49: #include "tipos.h"
! 50: #include "auxiliares.h"
! 51:
! 52:
! 53: /* configuración */
! 54: extern struct argumentos configuracion;
! 55:
! 56: /* bases de datos */
! 57: extern unsigned int num_nemonicos;
! 58: extern operacion *nemonicos;
! 59: extern unsigned int num_simbolos;
! 60: extern operando *simbolos;
! 61: extern unsigned int num_tiempos;
! 62: extern tiempo *ciclos;
! 63:
! 64: extern unsigned int num_ubicaciones;
! 65: extern ubicacion *datos;
! 66:
! 67:
! 68:
! 69:
! 70: /* LISTAS Y BASES DE DATOS */
! 71:
! 72: /* funciones para manipular la base de datos */
! 73:
! 74: int BDBuscarCadena(int idtabla, int idcampo, char *cadena)
! 75: {
! 76: unsigned int i = 0; /* los registros de las bases de datos comienzan en el índice 0 */
! 77: int encontrado = NO;
! 78: char mensaje[MAX_LINE];
! 79:
! 80: switch (idtabla)
! 81: {
! 82: case TABLA_NEMONICOS:
! 83: switch (idcampo)
! 84: {
! 85: case CAMPO_NEMONICO:
! 86: while(i<num_nemonicos && encontrado == NO)
! 87: {
! 88: if (strcmp(nemonicos[i].nemonico, cadena)) i++; /* no encontrado */
! 89: else encontrado = SI; /* encontrado */
! 90: }
! 91: break;
! 92:
! 93: default:
! 94: /* emitir un error al fichero de log */
! 95: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Nemónicos");
! 96: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 97: break;
! 98: }
! 99: break;
! 100:
! 101: case TABLA_SIMBOLOS:
! 102: switch (idcampo)
! 103: {
! 104: case CAMPO_SIMBOLO:
! 105: while(i<num_simbolos && encontrado == NO)
! 106: {
! 107: if (strcmp(simbolos[i].simbolo, cadena)) i++; /* no encontrado */
! 108: else encontrado = SI; /* encontrado */
! 109: }
! 110: break;
! 111:
! 112: default:
! 113: /* emitir un error al fichero de log */
! 114: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Símbolos");
! 115: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 116: break;
! 117: }
! 118: break;
! 119:
! 120: case TABLA_CICLOS:
! 121: switch (idcampo)
! 122: {
! 123: case CAMPO_IDENTIFICADOR:
! 124: while(i<num_tiempos && encontrado == NO)
! 125: {
! 126: if (strcmp(ciclos[i].identificador, cadena)) i++; /* no encontrado */
! 127: else encontrado = SI; /* encontrado */
! 128: }
! 129: break;
! 130:
! 131: default:
! 132: /* emitir un error al fichero de log */
! 133: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ciclos");
! 134: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 135: break;
! 136: }
! 137: break;
! 138:
! 139: case TABLA_UBICACIONES:
! 140: switch (idcampo)
! 141: {
! 142: case CAMPO_NOMBRE:
! 143: while(i<num_ubicaciones && encontrado == NO)
! 144: {
! 145: if (strcmp(datos[i].nombre, cadena)) i++; /* no encontrado */
! 146: else encontrado = SI; /* encontrado */
! 147: }
! 148: break;
! 149:
! 150: default:
! 151: /* emitir un error al fichero de log */
! 152: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ubicaciones");
! 153: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 154: break;
! 155: }
! 156: break;
! 157:
! 158: default:
! 159: /* emitir un error al fichero de log */
! 160: sprintf(mensaje, "[BDBuscarCadena] La tabla especificada no existe");
! 161: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 162: break;
! 163: }
! 164: if(encontrado == NO) return(-1);
! 165: else return(i);
! 166: }
! 167:
! 168:
! 169: /* listas */
! 170: /* esta función añade un elemento a una lista */
! 171:
! 172: void AgregarElementoLista(char *lista, char *cadena)
! 173: {
! 174: if (lista[0] == '\0') strcpy (lista, cadena);
! 175: else {strcat (lista, ":"); strcat (lista, cadena);}
! 176: }
! 177:
! 178:
! 179:
! 180: /* esta función busca un elemento en una lista y devuelve el índice o 0 si no está */
! 181:
! 182: unsigned int BuscarElementoLista(char *lista, char *cadena)
! 183: {
! 184: char copialista[MAX_LISTA];
! 185: char *elemento; /* es un puntero a char para la función strtok */
! 186: unsigned int indice = 1;
! 187:
! 188: strcpy(copialista, lista);
! 189:
! 190: elemento = strtok(copialista, ":"); /* el separador de elementos de la lista es ':' */
! 191: while(elemento != NULL)
! 192: {
! 193: if(strcmp(elemento, cadena) == 0) return indice;
! 194: else indice++;
! 195:
! 196: /* capturo el siguiente campo */
! 197: elemento = strtok(NULL, ":");
! 198: }
! 199: return 0;
! 200: /* esta función se puede implementar también usando 'strstr' */
! 201: }
! 202:
! 203:
! 204:
! 205: /* esta función elimina un elemento de una lista */
! 206:
! 207: void EliminarElementoLista(char *lista, char *cadena)
! 208: {
! 209: char *puntero;
! 210: unsigned int indice1;
! 211: unsigned int indice2 = 1;
! 212:
! 213: puntero = lista;
! 214: indice1 = BuscarElementoLista(lista, cadena);
! 215:
! 216: if(indice1 == 0) return;
! 217:
! 218: while(indice2 != indice1)
! 219: {
! 220: if(*puntero == ':') indice2++;
! 221: puntero++;
! 222: }
! 223:
! 224: if(puntero != lista) /* el elemento no es el primero */
! 225: {
! 226: *(puntero - 1) = '\0'; /* corto la cadena en el separador antes del elemento */
! 227: if(*(puntero + strlen(cadena)) == ':') /* el elemento no es el último */
! 228: {
! 229: strcat(lista, (puntero + strlen(cadena)));
! 230: }
! 231: }
! 232: else strcpy(lista, (puntero + strlen(cadena) + 1));
! 233: }
! 234:
! 235:
! 236:
! 237: /* INICIALIZACIÓN DE DATOS */
! 238:
! 239: void IniciarTarjeta(fichainstruccion *tarjetaoperandos)
! 240: {
! 241: strcpy(tarjetaoperandos->nemonico, "");
! 242: strcpy(tarjetaoperandos->op1, "");
! 243: strcpy(tarjetaoperandos->op2, "");
! 244: strcpy(tarjetaoperandos->hexadecimal, "");
! 245: tarjetaoperandos->longitud = 0;
! 246: strcpy(tarjetaoperandos->prefijo, "");
! 247: tarjetaoperandos->salto = NO_SALTO;
! 248: tarjetaoperandos->ciclosALU = 0;
! 249: tarjetaoperandos->ciclosBIU = 0;
! 250: strcpy(tarjetaoperandos->leidoimpldatos, "");
! 251: strcpy(tarjetaoperandos->leidoimpldir, "");
! 252: strcpy(tarjetaoperandos->leidoimplpila, "");
! 253: strcpy(tarjetaoperandos->leidoimplestado, "");
! 254: strcpy(tarjetaoperandos->leidoexpldatos, "");
! 255: strcpy(tarjetaoperandos->leidoexpldir, "");
! 256: strcpy(tarjetaoperandos->leidoexplpila, "");
! 257: strcpy(tarjetaoperandos->leidoexplestado, "");
! 258: strcpy(tarjetaoperandos->escritoimpldatos, "");
! 259: strcpy(tarjetaoperandos->escritoimpldir, "");
! 260: strcpy(tarjetaoperandos->escritoimplpila, "");
! 261: strcpy(tarjetaoperandos->escritoimplestado, "");
! 262: strcpy(tarjetaoperandos->escritoexpldatos, "");
! 263: strcpy(tarjetaoperandos->escritoexpldir, "");
! 264: strcpy(tarjetaoperandos->escritoexplpila, "");
! 265: strcpy(tarjetaoperandos->escritoexplestado, "");
! 266: }
! 267:
! 268:
! 269:
! 270: /* HERRAMIENTAS */
! 271:
! 272: unsigned long TamanoFichero(char *fichero)
! 273: {
! 274: FILE *handle;
! 275: unsigned long tamano = 0;
! 276: char mensaje[MAX_LINE];
! 277:
! 278:
! 279: if((handle = fopen(fichero, "rb")) != NULL)
! 280: {
! 281: /*
! 282: sprintf(mensaje, "[TamañoFichero] El fichero '%s' se ha abierto con éxito", fichero);
! 283: Notificar(mensaje, NO_ERROR, ECO_NO);
! 284: */
! 285:
! 286: fseek(handle, 0L, SEEK_END);
! 287: tamano = ftell(handle);
! 288:
! 289: /* cierro el fichero */
! 290: if(fclose(handle))
! 291: {
! 292: sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido cerrar", fichero);
! 293: Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
! 294: }
! 295: }
! 296: else
! 297: {
! 298: sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido abrir", fichero);
! 299: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 300: }
! 301:
! 302: return tamano;
! 303: }
! 304:
! 305:
! 306:
! 307: void DeterminarRango()
! 308: {
! 309: unsigned long total_instrucciones; /* total en la traza */
! 310: unsigned long cantidad; /* cantidad a analizar */
! 311: char mensaje[MAX_LINE];
! 312:
! 313: /* calculo la cantidad de instrucciones en la traza a partir del tamaño del fichero */
! 314: total_instrucciones = TamanoFichero(configuracion.ficherodatos)/BYTES_POR_INSTRUCCION;
! 315:
! 316: /*
! 317: printf("Total instrucciones en '%s' = %lu\n", configuracion.ficherodatos, total_instrucciones);
! 318: _getch();
! 319: */
! 320:
! 321: if(configuracion.ultima == 0) /* significa que manda el rango */
! 322: {
! 323: /* cantidad = (unsigned long)(configuracion.rango * total_instrucciones)/100.00; */
! 324:
! 325: cantidad = (unsigned long)((configuracion.rango/100.00) * total_instrucciones);
! 326:
! 327:
! 328: if(configuracion.primera == 0) /* significa que manda el porcentaje de comienzo */
! 329:
! 330: /* configuracion.primera = (unsigned long) 1 + (configuracion.comienzo * total_instrucciones)/100.00; */
! 331:
! 332: configuracion.primera = (unsigned long) 1 + (configuracion.comienzo/100.00) * total_instrucciones;
! 333: /* la cuenta de instrucciones comienza en '1' */
! 334:
! 335: else if(configuracion.primera > total_instrucciones)
! 336: {
! 337: sprintf(mensaje, "[DeterminarRango] La primera instrucción está fuera del fichero de datos");
! 338: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 339: }
! 340: configuracion.ultima = configuracion.primera + cantidad;
! 341: if(configuracion.ultima > total_instrucciones) configuracion.ultima = total_instrucciones;
! 342: }
! 343:
! 344: cantidad = configuracion.ultima - configuracion.primera + 1;
! 345:
! 346: if(cantidad < configuracion.ventana)
! 347: {
! 348: sprintf(mensaje, "[DeterminarRango] El rango de análisis es demasiado pequeño");
! 349: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 350: }
! 351: }
! 352:
! 353:
! 354:
! 355:
! 356: /* ARITMÉTICAS */
! 357:
! 358: /* esta función calcula el nuevo valor promedio de una serie de datos */
! 359: /* a partir del valor anterior y del valor en curso (actual) */
! 360:
! 361: double CalcularNuevoPromedio (double promedioanterior, double valoractual, unsigned long n)
! 362: {
! 363: double nuevopromedio;
! 364:
! 365: /* nuevopromedio = ((n - 1) * promedioanterior + valoractual) / n; */
! 366:
! 367: nuevopromedio = promedioanterior + (double)((valoractual - promedioanterior) / n);
! 368:
! 369: return nuevopromedio;
! 370: }
! 371:
! 372:
! 373: /* esta función calcula el inverso normalizado y previene la división por 0 */
! 374:
! 375: double InversoNormalizado (unsigned int dimension, double valor)
! 376: {
! 377: double inverso;
! 378: char mensaje[MAX_LINE];
! 379:
! 380: if(valor == 0.0)
! 381: {
! 382: sprintf(mensaje, "[InversoNormalizado] El valor del denominador es nulo");
! 383: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 384: }
! 385:
! 386: if(dimension == 0)
! 387: {
! 388: sprintf(mensaje, "[InversoNormalizado] La dimensión de la normalización es nula");
! 389: Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
! 390: }
! 391:
! 392: inverso = dimension / valor;
! 393:
! 394: return inverso;
! 395: }
! 396:
! 397:
! 398:
! 399: /* FORMATO */
! 400:
! 401: /* esta función genera la cadena en lenguaje ensamblador de una instrucción */
! 402: /* a partir del prefijo, nemónico y operandos */
! 403: /* según un tipo de notación especificado (INTEL, ATT) */
! 404:
! 405: void CadenaEnsamblador(char *prefijo, char *nemonico, char *operando1, char *operando2, unsigned char notacion, char *cadena)
! 406: {
! 407: char auxiliar[2*MAX_NEMO + 2*MAX_OPE];
! 408:
! 409: switch(notacion)
! 410: {
! 411: case 0: /* notación de INTEL */
! 412:
! 413: sprintf(cadena, "%s%s", prefijo, prefijo[0]!='\0' ? " ":"");
! 414:
! 415: sprintf(auxiliar, "%s", nemonico);
! 416: strcat(cadena, auxiliar);
! 417:
! 418: sprintf(auxiliar, "%s%s", operando1[0]!='\0' ? " ":"", operando1);
! 419: strcat(cadena, auxiliar);
! 420:
! 421: sprintf(auxiliar, "%s%s%s", (operando1[0]!='\0' && operando2[0]!='\0') ? ",":"", operando2[0]!='\0' ? " ":"", operando2);
! 422: strcat(cadena, auxiliar);
! 423:
! 424: /* más elegante usar el índice que devuelve sprintf y sumarlo al puntero cadena */
! 425: /* sprintf(cadena + i, ""... */
! 426: break;
! 427:
! 428: case 1: /* notación ATT */
! 429: break;
! 430: }
! 431: }
! 432:
! 433:
! 434: /* esta función convierte una cadena hexadecimal a una secuencia de bytes */
! 435:
! 436: void ConvertirHex2Bin(char *cadenahex, unsigned char *secuencia, unsigned char maxformato)
! 437: {
! 438: int i;
! 439: char bytehex[3];
! 440: char mensaje[MAX_LINE];
! 441:
! 442: /* control de errores */
! 443: if(strlen(cadenahex)==0)
! 444: {
! 445: sprintf(mensaje, "[ConvertirHex2Bin] La cadena hexadecimal está vacía");
! 446: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 447: }
! 448: else if(strlen(cadenahex)%2!=0)
! 449: {
! 450: sprintf(mensaje, "[ConvertirHex2Bin] La cadena hexadecimal '%s' no contiene un número entero de bytes", cadenahex);
! 451: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 452: }
! 453:
! 454: /* relleno la secuencia de 2 instrucciones en binario con 0s */
! 455: /* (2 instrucciones de tamaño máximo 'maxformato') */
! 456: for(i=0; i<2*maxformato; i++) *(secuencia+i) = 0;
! 457:
! 458: do
! 459: {
! 460: for(i=0; i<2; i++)
! 461: {
! 462: bytehex[i]=*(cadenahex+i);
! 463: if(isxdigit(bytehex[i])==0) /* error -> dígito no hexadecimal */
! 464: {
! 465: sprintf(mensaje, "[ConvertirHex2Bin] El byte '%s' contiene un dígito no hexadecimal", cadenahex);
! 466: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 467: }
! 468: }
! 469: bytehex[3]='\0';
! 470: sscanf(bytehex, "%2X", secuencia);
! 471: secuencia++;
! 472: }
! 473: while(*(cadenahex+=2)!='\0');
! 474: }
! 475:
! 476: /* NOTA: otra posibilidad para esta función consiste en copiar la cadena hexadecimal */
! 477: /* en un array y recorrer con un puntero dicha cadena desde el final de 2 en 2 caracteres */
! 478: /* antes de decrementar el puntero se corta el array con un \0 para "ver" 2 dígitos */
! 479: /* hexadecimales cada vez; este método consume memoria para el array y para el puntero */
! 480: /* si no copio la cadena hexadecimal la pierdo al trocearla con \0 */
! 481:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>