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>