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