Annotation of ADD_ver_10/Auxiliares.c, revision 1.2
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: /* */
1.2 ! rico 25: /* Revision 1.3. 02/2006 */
! 26: /* Fix overflow error in expresion evaluating 'cantidad' */
! 27: /* */
1.1 rico 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;
1.2 ! rico 78: char mensaje[MAX_LINE];
1.1 rico 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 */
1.2 ! rico 95: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Nemónicos");
! 96: Notificar(mensaje, ERROR_SALIR, ECO_NO);
1.1 rico 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 */
1.2 ! rico 114: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Símbolos");
! 115: Notificar(mensaje, ERROR_SALIR, ECO_NO);
1.1 rico 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 */
1.2 ! rico 133: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ciclos");
! 134: Notificar(mensaje, ERROR_SALIR, ECO_NO);
1.1 rico 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 */
1.2 ! rico 152: sprintf(mensaje, "[BDBuscarCadena] El campo no existe en la Tabla Ubicaciones");
! 153: Notificar(mensaje, ERROR_SALIR, ECO_NO);
1.1 rico 154: break;
155: }
156: break;
157:
1.2 ! rico 158: default:
1.1 rico 159: /* emitir un error al fichero de log */
1.2 ! rico 160: sprintf(mensaje, "[BDBuscarCadena] La tabla especificada no existe");
! 161: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 162: break;
1.1 rico 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: {
1.2 ! rico 184: char copialista[MAX_LISTA];
1.1 rico 185: char *elemento; /* es un puntero a char para la función strtok */
1.2 ! rico 186: unsigned int indice = 1;
1.1 rico 187:
1.2 ! rico 188: strcpy(copialista, lista);
1.1 rico 189:
1.2 ! rico 190: elemento = strtok(copialista, ":"); /* el separador de elementos de la lista es ':' */
1.1 rico 191: while(elemento != NULL)
192: {
193: if(strcmp(elemento, cadena) == 0) return indice;
1.2 ! rico 194: else indice++;
1.1 rico 195:
1.2 ! rico 196: /* capturo el siguiente campo */
1.1 rico 197: elemento = strtok(NULL, ":");
198: }
1.2 ! rico 199: return 0;
1.1 rico 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: {
1.2 ! rico 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));
1.1 rico 233: }
234:
235:
236:
237: /* INICIALIZACIÓN DE DATOS */
238:
239: void IniciarTarjeta(fichainstruccion *tarjetaoperandos)
240: {
1.2 ! rico 241: strcpy(tarjetaoperandos->nemonico, "");
1.1 rico 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: {
1.2 ! rico 274: FILE *handle;
! 275: unsigned long tamano = 0;
! 276: char mensaje[MAX_LINE];
1.1 rico 277:
278:
1.2 ! rico 279: if((handle = fopen(fichero, "rb")) != NULL)
1.1 rico 280: {
281: /*
1.2 ! rico 282: sprintf(mensaje, "[TamañoFichero] El fichero '%s' se ha abierto con éxito", fichero);
! 283: Notificar(mensaje, NO_ERROR, ECO_NO);
! 284: */
1.1 rico 285:
1.2 ! rico 286: fseek(handle, 0L, SEEK_END);
! 287: tamano = ftell(handle);
1.1 rico 288:
289: /* cierro el fichero */
290: if(fclose(handle))
1.2 ! rico 291: {
! 292: sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido cerrar", fichero);
! 293: Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
! 294: }
1.1 rico 295: }
296: else
1.2 ! rico 297: {
! 298: sprintf(mensaje, "[TamañoFichero] El fichero '%s' no se ha podido abrir", fichero);
! 299: Notificar(mensaje, ERROR_SALIR, ECO_NO);
! 300: }
1.1 rico 301:
1.2 ! rico 302: return tamano;
1.1 rico 303: }
304:
305:
306:
307: void DeterminarRango()
308: {
1.2 ! rico 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: }
1.1 rico 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: {
1.2 ! rico 363: double nuevopromedio;
! 364:
! 365: /* nuevopromedio = ((n - 1) * promedioanterior + valoractual) / n; */
1.1 rico 366:
1.2 ! rico 367: nuevopromedio = promedioanterior + (double)((valoractual - promedioanterior) / n);
1.1 rico 368:
1.2 ! rico 369: return nuevopromedio;
1.1 rico 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: {
1.2 ! rico 377: double inverso;
! 378: char mensaje[MAX_LINE];
1.1 rico 379:
1.2 ! rico 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: }
1.1 rico 391:
1.2 ! rico 392: inverso = dimension / valor;
1.1 rico 393:
1.2 ! rico 394: return inverso;
1.1 rico 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: {
1.2 ! rico 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: }
1.1 rico 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: {
1.2 ! rico 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');
1.1 rico 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>