Annotation of ADD_ver_10/Source Code/Source Files/Main.c, revision 1.2

1.1       rico        1: /********************************************************************/
                      2: /*  Main.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: /*                                                                  */
        !            11: /*                                                                  */
        !            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.                               */
        !            17: /*                                                                  */
        !            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.                                                   */
        !            23: /*                                                                  */
        !            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: /********************************************************************/
                     40: 
                     41: /******************************************************************************/
                     42: /* MÓDULO: Main.c                                                             */
                     43: /*                                                                            */
                     44: /******************************************************************************/
                     45: /* Fecha: 19 de septiembre de 2005                                            */
                     46: /******************************************************************************/
                     47: 
                     48: #include <stdio.h>
                     49: #include <stdlib.h>
                     50: #include <string.h>
                     51: 
                     52: #include "defines.h"
                     53: #include "tipos.h"
                     54: #include "main.h"
                     55: 
                     56: /* configuración */
                     57: struct argumentos configuracion;
                     58: 
                     59: /* bases de datos */
                     60: unsigned int num_nemonicos;
                     61: operacion *nemonicos = NULL;
                     62: unsigned int num_simbolos;
                     63: operando *simbolos = NULL;
                     64: 
                     65: unsigned int num_tiempos;
                     66: tiempo *ciclos = NULL;
                     67: 
                     68: /* recuentos */
                     69: unsigned long int *contadornemonicos = NULL;
                     70: unsigned long int *contadorlecturas = NULL;
                     71: unsigned long int *contadorescrituras = NULL;
                     72: 
                     73: /* contadores de instrucciones y ventanas */
                     74: unsigned long instruccion, ventana;
                     75: 
                     76: /* otros resultados */
                     77: double cpimedio = 0.0;
                     78: double tiempoejecucion = 0.0;
                     79: unsigned long *distribucionpasos = NULL;
                     80: 
                     81: /* posibles ubicaciones de datos */
                     82: unsigned int num_ubicaciones;
                     83: ubicacion *datos = NULL;
                     84: 
                     85: /* análisis de dependencias de datos */
                     86: int *pizarra_escrituras = NULL;
                     87: int **pizarra_lecturas = NULL;
                     88: 
                     89: unsigned char *vector = NULL;
                     90: 
                     91: struct punterosD matriz;
                     92: unsigned char **matrizC = NULL;    /* matriz de caminos de dependencias */
                     93: char **OrdenParcial = NULL;        /* lista de instrucciones según orden parcial de D */
                     94: 
                     95: /* parámetros asociados a las matrices */ 
                     96: parametromatriz *pasos = NULL;
                     97: parametromatriz *mediapasos = NULL;
                     98: parametromatriz *grado = NULL;
                     99: parametromatriz *mediagrado = NULL;
                    100: parametromatriz *acoplo = NULL;
                    101: parametromatriz *mediaacoplo = NULL;
                    102: 
                    103: 
                    104: /* declaro aquí mismo algunas funciones sencillas para no repetir secuencias de código */
                    105: 
                    106: void ProcesarInstruccion(unsigned int ins, unsigned char secuencia[12], fichainstruccion *tarjetaoperandos)
                    107: {
                    108:     AnalizarOperandosIA16(secuencia, tarjetaoperandos);
                    109: 
                    110:     if(configuracion.recuentos == SI) ActualizarRecuentos(tarjetaoperandos);
                    111: 
                    112:     if(configuracion.cpi == SI) CalcularCiclosInstruccion(tarjetaoperandos);
                    113: 
                    114:     if(configuracion.CPImedio == SI) ActualizarCPImedio(tarjetaoperandos->ciclosALU, tarjetaoperandos->ciclosBIU);
                    115: 
                    116:     if(configuracion.dependencias == SI)
                    117:     {
                    118:         AnalizarDependencias(tarjetaoperandos, ins);
                    119: 
                    120:         AnotarEscrituras(tarjetaoperandos, ins);
                    121:         AnotarLecturas(tarjetaoperandos, ins);
                    122: 
                    123:         /* si tengo que calcular el tiempo de ejecución */
                    124:         /* debo construir un array con el tipo de instrucción */
                    125:         /* y su latencia en ciclos */
                    126:     }
                    127: }
                    128: 
                    129: void IniciarVentana()
                    130: {
                    131:     if(configuracion.dependencias == SI)
                    132:     {
                    133:         IniciarPizarras();
                    134:         IniciarVectorDependencias();
                    135:         IniciarMatricesDependencias();
                    136:         if(configuracion.ordenparcial == SI) IniciarListaOrdenParcial();
                    137:         if(configuracion.matrizcaminos == SI) IniciarMatrizCaminos();
                    138:         if(configuracion.pasoscomputacion == SI) IniciarVariableAgregada(pasos);
                    139:         if(configuracion.gradoparalelismo == SI) IniciarVariableAgregada(grado);;
                    140:         if(configuracion.acoplamiento == SI) IniciarVariableAgregada(acoplo);
                    141:     }
                    142: }
                    143: 
                    144: void ProcesarVentana()
                    145: {
                    146:     if(configuracion.dependencias == SI)
                    147:     {
                    148:         GenerarMatrizD();        /* a partir de las matrices desacopladas */
                    149: 
                    150:         /* EXTRAIGO INFORMACIÓN DE LAS MATRICES */
                    151:         /* lista orden parcial (la función también puede devolver pasos) */
                    152:         if(configuracion.ordenparcial == SI) ListaOrdenParcial(matriz.D, OrdenParcial);
                    153:         /* matriz de caminos (la función también puede devolver pasos) */
                    154:         if(configuracion.matrizcaminos == SI) CalcularMatrizCaminos(matriz.D, matrizC);
                    155:         /* pasos de computación */
                    156:         if(configuracion.pasoscomputacion == SI)
                    157:         {
                    158:             /* pasos de computación de todas las matrices de dependencias */
                    159:             CalcularPasosComputacion(pasos);
                    160:             if(configuracion.distribucionpasos == SI) ActualizarHistogramaPasos();
                    161:             /* valor medio de pasos de computación */
                    162:             CalcularPromedioVariableAgregada(mediapasos, pasos, ventana);
                    163:         }
                    164:         /* grado de paralelismo (a partir de los pasos de computación) */
                    165:         if(configuracion.gradoparalelismo == SI)
                    166:         {
                    167:             /* grado de paralelismo a partir de los pasos de computación */
                    168:             CalcularGradoParalelismoNormalizado(pasos, grado);
                    169:             /* valor medio del grado de paralelismo */
                    170:             CalcularPromedioVariableAgregada(mediagrado, grado, ventana);
                    171:         }
                    172:         /* acoplamiento */
                    173:         if(configuracion.acoplamiento == SI);
                    174:         {
                    175:             /* grado de paralelismo a partir de los pasos de computación */
                    176:             CalcularAcoplamiento(acoplo);
                    177:             /* valor medio del grado de paralelismo */
                    178:             CalcularPromedioVariableAgregada(mediaacoplo, acoplo, ventana);
                    179:         }        
                    180: 
                    181:         if(configuracion.tiempo == SI) tiempoejecucion = CalcularTiempo();
                    182:     }
                    183: }
                    184: 
                    185: void ReservarMemoriaAnalisisDependencias()
                    186: {
                    187:     CrearPizarras();
                    188:     
                    189:     CrearVectorDependencias();
                    190: 
                    191:     CrearMatricesDependencias();
                    192: 
                    193:     if(configuracion.ordenparcial == SI) CrearListaOrdenParcial();
                    194:     if(configuracion.matrizcaminos == SI) CrearMatrizCaminos();
                    195:     if(configuracion.pasoscomputacion == SI)
                    196:     {
                    197:         pasos = CrearVariableAgregada();
                    198:         IniciarVariableAgregada(pasos);
                    199:         mediapasos = CrearVariableAgregada();
                    200:         IniciarVariableAgregada(mediapasos);
                    201:         if(configuracion.distribucionpasos == SI) CrearHistogramaPasos();
                    202:     }
                    203:     if(configuracion.gradoparalelismo == SI);
                    204:     {
                    205:         grado = CrearVariableAgregada();
                    206:         IniciarVariableAgregada(grado);
                    207:         mediagrado = CrearVariableAgregada();
                    208:         IniciarVariableAgregada(mediagrado);
                    209:     }
                    210:     if(configuracion.acoplamiento == SI);
                    211:     {
                    212:         acoplo = CrearVariableAgregada();
                    213:         IniciarVariableAgregada(acoplo);
                    214:         mediaacoplo = CrearVariableAgregada();
                    215:         IniciarVariableAgregada(mediaacoplo);
                    216:     }
                    217: }
                    218: 
                    219: 
                    220: void LiberarMemoriaAnalisisDependencias()
                    221: {
                    222:     LiberarMemoriaPizarras();
                    223:     LiberarMemoriaVectorDependencias();
                    224:     LiberarMemoriaMatricesDependencias();
                    225: 
                    226:     if(configuracion.ordenparcial == SI) LiberarMemoriaListaOrdenParcial();
                    227:     if(configuracion.matrizcaminos == SI) LiberarMemoriaMatrizCaminos();
                    228: 
                    229:     if(configuracion.pasoscomputacion == SI) {free(pasos); free(mediapasos);}
                    230:     if(configuracion.gradoparalelismo == SI) {free(grado); free(mediagrado);};
                    231:     if(configuracion.acoplamiento == SI) {free(acoplo); free(mediaacoplo);};
                    232: 
                    233:     if(configuracion.distribucionpasos == SI) LiberarMemoriaHistogramaPasos();
                    234: }
                    235: 
                    236: 
                    237: 
                    238: 
                    239: 
                    240: void main(int argc, char *argv[])
                    241: {
                    242:     /* puntero al fichero origen de datos */
                    243:     FILE *origendatos;
                    244:     /* total instrucciones y ventanas a procesar */
                    245:     unsigned long total_ins, total_ven;    
                    246:     /* secuencia en bytes de 2 instrucciones consecutivas */
                    247:     unsigned char secuencia[2*BYTES_POR_INSTRUCCION];
                    248:     /* reservo espacio para una estructura de tipo ficha de instrucción */
                    249:     fichainstruccion tarjetaoperandos;
                    250:     
                    251:     unsigned int i, ins;
                    252:     char cadena[MAX_LINE];
                    253:     char mensaje[MAX_LINE];
                    254:     unsigned char salvarventana = NO;
                    255:     char listadoventanas[MAX_LINE];
                    256: 
                    257:     /* inicio los punteros de las matrices de dependencias a NULL */
                    258:     /* es una medida higiénica pero no necesaria ya que la reserva de memoria */
                    259:     /* correspondiente a la declaración se hace rellenando con 0s */
                    260: 
                    261:     /* ver si es posible con {NULL, NULL...} */
                    262:     IniciarPunterosMatrices();
                    263: 
                    264:     /* NOTIFICACIONES DE SUCESOS Y ERRORES */
                    265:     /* inicio el fichero que va a recibir las notificaciones */
                    266:     IniciarNotificaciones();
                    267: 
                    268:     /* CONFIGURACIÓN */
                    269:     /* cargo la configuración de la aplicación por defecto */
                    270:     CargarConfiguracionInicial();
                    271:     /* modifico la configuración de la aplicación en función de los argumentos */
                    272:     CapturarArgumentos(argc, argv);
                    273: 
                    274:     /* escribo la configuración en el fichero de notificaciones */
                    275:     if(configuracion.nivelnotificaciones != EX_CFG) NotificarConfiguracion();
                    276: 
                    277:     /* BASES DE DATOS */
                    278:     CargarBasesDatos();
                    279: 
                    280:     /* CALCULOS A REALIZAR */
                    281:     if(configuracion.recuentos == SI) CrearContadores();
                    282:     if(configuracion.dependencias == SI) ReservarMemoriaAnalisisDependencias();
                    283: 
                    284:     /* FICHEROS A CREAR */
                    285:     if(configuracion.volcarBD == SI) SalvarBasesDatos();
                    286:     if(configuracion.crearficheroconfig == SI) CrearFicheroConfiguracion();
                    287: 
                    288:     /* CABECERA EN LA PANTALLA */
                    289:     MostrarCabecera();
                    290: 
                    291:     /* PROCESAMIENTO */
                    292:     if(configuracion.origen == TRAZA)
                    293:     {
                    294:         /* determino el rango de instrucciones a analizar */
                    295:         DeterminarRango();
                    296:         /* determino el número total de instrucciones */
                    297:         total_ins = (unsigned long)(configuracion.ultima - configuracion.primera + 1);
                    298:         /* determino el número de ventanas de instrucciones */
                    299:         total_ven = (unsigned long)total_ins/configuracion.ventana;
                    300:         /* inicio los contadores */
                    301:         instruccion = 1;    /* cuento las instrucciones desde el '1' */
                    302:         ventana = 0;
                    303:         /* listado de ventanas a volcar */
                    304:         strcpy(listadoventanas, configuracion.volcarventana);
                    305:         
                    306:         /* abro el fichero de traza */
                    307:         if((origendatos  = fopen(configuracion.ficherodatos, "rb")) != NULL)
                    308:         {
                    309:             sprintf(mensaje, "[Main] El fichero '%s' se ha abierto con éxito", configuracion.ficherodatos);
                    310:             Notificar(mensaje, NO_ERROR, ECO_NO);
                    311: 
                    312:             /* sitúo el puntero del fichero en la instrucción de comienzo */
                    313:             fseek(origendatos, (configuracion.primera - 1) * BYTES_POR_INSTRUCCION, SEEK_SET);
                    314: 
                    315:             /* leo el formato de la primera instrucción a tratar */
                    316:             /* y lo coloco en la parte alta de la secuencia (2ª instrucción) */
                    317:             for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i+BYTES_POR_INSTRUCCION] = fgetc(origendatos);
                    318: 
                    319:             while(total_ven-ventana)
                    320:             {
                    321:                 ventana++;
                    322: 
                    323:                 /* indicar estado de procesamiento */
                    324:                 PresentarEstadoProcesamiento(total_ven, ventana);
                    325: 
                    326:                 IniciarVentana();                
                    327: 
                    328:                 /* ¿salvar información de la ventana en curso? */
                    329:                 if(listadoventanas[0] != '\0')        /* si el listado no es vacío */
                    330:                 {
                    331:                     sprintf(cadena, "%lu", ventana);
                    332:                     if(BuscarElementoLista(listadoventanas, cadena) != 0)
                    333:                     {
                    334:                         salvarventana = SI;
                    335:                         EliminarElementoLista(listadoventanas, cadena);
                    336:                         /* construyo una planilla con resultados de la ventana en curso */
                    337:                         IniciarFicheroVentana();
                    338:                     }
                    339:                     else salvarventana = NO;
                    340:                 }
                    341: 
                    342:                 for(ins=0; ins<configuracion.ventana; ins++, instruccion++)
                    343:                 {
                    344:                     /* paso el formato de la parte alta a la baja */
                    345:                     for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i] = secuencia[i+BYTES_POR_INSTRUCCION];
                    346:                     /* leo el formato de la instrucción siguiente desde la traza */
                    347:                     for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i+BYTES_POR_INSTRUCCION] = fgetc(origendatos);
                    348: 
                    349:                     ProcesarInstruccion(ins, secuencia, &tarjetaoperandos);
                    350:                     
                    351:                     if(configuracion.verinstruccion == SI) MostrarTarjeta(&tarjetaoperandos);
                    352: 
                    353:                     if(salvarventana == SI) Instruccion2FicheroVentana(&tarjetaoperandos);
                    354: 
                    355:                     /* _getch(); */
                    356:                 }
                    357:                 ProcesarVentana();
                    358: 
                    359:                 if(configuracion.verventana == SI) MostrarVentana();
                    360: 
                    361:                 /* salvo las matrices de la ventana en la planilla y sus parámetros */
                    362:                 if(salvarventana == SI) Matrices2FicheroVentana();
                    363:             }
                    364: 
                    365:             /* cierro el fichero de traza */
                    366:             if(fclose(origendatos))
                    367:             {
                    368:                 sprintf(mensaje, "[Main] El fichero '%s' no se ha podido cerrar", configuracion.ficherodatos);
                    369:                 Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
                    370:             }
                    371:             else
                    372:             {
                    373:                 sprintf(mensaje, "[Main] El fichero '%s' ha sido cerrado con éxito", configuracion.ficherodatos);
                    374:                 Notificar(mensaje, NO_ERROR, ECO_NO);
                    375:             }
                    376:         }
                    377:         else
                    378:         {
                    379:             sprintf(mensaje, "[Main] El fichero '%s' no se ha podido abrir", configuracion.ficherodatos);
                    380:             Notificar(mensaje, ERROR_SALIR, ECO_NO);
                    381:         }
                    382:     }
                    383: 
                    384:     else if(configuracion.origen == SECUENCIA)
                    385:     {
                    386:         /* abro el fichero de la secuencia */
                    387:         if((origendatos  = fopen(configuracion.ficherodatos, "r")) != NULL)
                    388:         {
                    389:             sprintf(mensaje, "[Main] El fichero '%s' se ha abierto con éxito", configuracion.ficherodatos);
                    390:             Notificar(mensaje, NO_ERROR, ECO_NO);
                    391: 
                    392:             /* cuento las instrucciones de la secuencia */
                    393:             ins = 0;
                    394:             while(!feof(origendatos))
                    395:             {
                    396:                 fgets (cadena, MAX_LINE, origendatos);
                    397:                 
                    398:                 if (cadena[0]!='\n' && cadena[0]!='#') ins++;
                    399:             }
                    400:             configuracion.primera = 1;
                    401:             configuracion.ultima = ins;
                    402: 
                    403:             /* determino el número total de instrucciones */
                    404:             total_ins = (unsigned long)(configuracion.ultima - configuracion.primera + 1);
                    405:             /* determino el número de ventanas de instrucciones */
                    406:             total_ven = (unsigned long)total_ins/configuracion.ventana;
                    407:             /* inicio los contadores */
                    408:             instruccion = 1;    /* cuento las instrucciones desde el '1' */
                    409:             ventana = 0;
                    410:             /* listado de ventanas a volcar */
                    411:             strcpy(listadoventanas, configuracion.volcarventana);
                    412: 
                    413: 
                    414:             /* coloco el puntero del fichero al principio */
                    415:             fseek(origendatos, 0L, SEEK_SET);
                    416: 
                    417:             /* comienzo el análisis de la secuencia */
                    418:             while(total_ven-ventana)
                    419:             {
                    420:                 ventana++;
                    421: 
                    422:                 /* indicar estado de procesamiento */
                    423:                 PresentarEstadoProcesamiento(total_ven, ventana);
                    424: 
                    425:                 IniciarVentana();
                    426: 
                    427:                 /* ¿salvar información de la ventana en curso? */
                    428:                 if(listadoventanas[0] != '\0')        /* si el listado no es vacío */
                    429:                 {
                    430:                     sprintf(cadena, "%lu", ventana);
                    431:                     if(BuscarElementoLista(listadoventanas, cadena) != 0)
                    432:                     {
                    433:                         salvarventana = SI;
                    434:                         EliminarElementoLista(listadoventanas, cadena);
                    435:                         /* construyo una planilla con resultados de la ventana en curso */
                    436:                         IniciarFicheroVentana();
                    437:                     }
                    438:                     else salvarventana = NO;
                    439:                 }
                    440: 
                    441:                 for(ins=0; ins<configuracion.ventana; ins++, instruccion++)
                    442:                 {
                    443:                     do
                    444:                     {
                    445:                         fgets (cadena, MAX_LINE, origendatos);
                    446:                     }
                    447:                     while (cadena[0]=='\n' || cadena[0]=='#');
                    448:                 
                    449:                     /* quito el caracter '\n' (0x0A) final de la cadena correspondiente a una línea de texto */
                    450:                     /* ¡OJO! si abro el fichero en modo binario el final de linea es "\r\n" (0x0D 0x0A) */
                    451:                     *(cadena+strlen(cadena)-1)='\0';
                    452: 
                    453:                     ConvertirHex2Bin(cadena, secuencia, BYTES_POR_INSTRUCCION);
                    454: 
                    455:                     ProcesarInstruccion(ins, secuencia, &tarjetaoperandos);
                    456: 
                    457:                     if(configuracion.verinstruccion == SI) MostrarTarjeta(&tarjetaoperandos);
                    458: 
                    459:                     /* salvo las instrucciones en la planilla de la ventana */
                    460:                     if(salvarventana == SI) Instruccion2FicheroVentana(&tarjetaoperandos);
                    461:                 }
                    462: 
                    463:                 ProcesarVentana();
                    464: 
                    465:                 if(configuracion.verventana == SI) MostrarVentana();
                    466: 
                    467:                 /* salvo las matrices de la ventana en la planilla y sus parámetros */
                    468:                 if(salvarventana == SI) Matrices2FicheroVentana();
                    469:             }
                    470: 
                    471:             /* cierro el fichero de la secuencia */
                    472:             if(fclose(origendatos))
                    473:             {
                    474:                 sprintf(mensaje, "[Main] El fichero '%s' no se ha podido cerrar", configuracion.ficherodatos);
                    475:                 Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
                    476:             }
                    477:             else
                    478:             {
                    479:                 sprintf(mensaje, "[Main] El fichero '%s' ha sido cerrado con éxito", configuracion.ficherodatos);
                    480:                 Notificar(mensaje, NO_ERROR, ECO_NO);
                    481:             }
                    482:         }
                    483:         else
                    484:         {
                    485:             sprintf(mensaje, "[Main] El fichero '%s' no se ha podido abrir", configuracion.ficherodatos);
                    486:             Notificar(mensaje, ERROR_SALIR, ECO_NO);
                    487:         }
                    488:     }
                    489: 
                    490:     else if(configuracion.origen == CADENAHEX)
                    491:     {
                    492:         instruccion = 1;
                    493:         ventana = 1;
                    494: 
                    495:         ConvertirHex2Bin(configuracion.cadenahex, secuencia, BYTES_POR_INSTRUCCION);
                    496: 
                    497:         AnalizarOperandosIA16(secuencia, &tarjetaoperandos);
                    498: 
                    499:         if(configuracion.cpi == SI) CalcularCiclosInstruccion(&tarjetaoperandos);
                    500: 
                    501:         /* if(configuracion.verinstruccion == SI) */
                    502:         /* muestro en la pantalla la información siempre */
                    503:         MostrarTarjeta(&tarjetaoperandos);
                    504:     }
                    505: 
                    506:     /* SALVAR RESULTADOS */
                    507:     /* salvo los resultados en un fichero de formato EXCEL */
                    508:     if(configuracion.origen != CADENAHEX) CrearFicheroResultados(configuracion.ficheroresultados);
                    509: 
                    510:     /* LIBERAR MEMORIA */
                    511:     /* al final hay que liberar toda la memoria reservada */
                    512:     LiberarMemoriaBasesDatos();
                    513:     if(configuracion.recuentos == SI) LiberarMemoriaContadores();
                    514:     if(configuracion.dependencias == SI) LiberarMemoriaAnalisisDependencias();
                    515: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>