Informática


Analizador de programas escritos en Turbo Pascal Orientado a Objetos


Proyecto Fin de

Carrera I

Enunciado 2:

“Analizador de programas escritos en

Turbo Pascal Orientado a Objetos”

Indice:

Pag.

1. Introducción.

3

2. Especificación de Requerimientos Software de la aplicación a desarrollar.

4

3. Manual de Usuario.

12

4. Manual del Programador.

16

5. Listados del código fuente de la aplicación desarrollada.

23

6. Listados de las propiedades y eventos empleados en la aplicación.

48

7. Calendario del Proyecto

63

Introducción

Este proyecto consiste en implementar un explorador de código sobre un programa en Turbo Pascal Orientado a Objetos.

Para la ejecución de nuestro proyecto partimos de un programa en Pascal compilado y que funciona correctamente, por tanto no podemos ejecutar un programa escrito con otro compilador ni, por supuesto, uno que no funcione correctamente.

Partiendo de estos hechos, abrimos un programa fuente, y al ejecutar nuestro proyecto generamos un fichero de tipo registro con el formato dado, en el cual vamos introduciendo las clases, atributos, asociaciones, métodos, herencia ...

El proyecto ha sido implementado en Delphi, por tanto es necesario Windows para poder ejecutarlo (3.1 o superior). Decir que hemos utilizado una resolución de 800x600, con un color de alta calidad (high color). De no ser ejecutado bajo estas condiciones, algunas cosas pueden aparecer desplazadas de sitio, llegando incluso a no verse en pantalla, así como las fotografías no visualizarse con la calidad que nosotros deseáramos.

Junto al programa se adjuntan los consiguientes manuales, tanto de programador como de usuario, para intentar resolver los problemas que puedan surgir al utilizar el proyecto, así como analizar la forma en la que lo hemos implementado. De todos modos, el programa es muy fácil de manejar al funcionar bajo Windows y ser la interfaz muy simple.

Especificación de Requerimientos Software

del Proyecto Fin de Carrera I ( Enunciado 2 ).

1. Introducción.

1.1. Propósito.

El propósito del presente apartado es definir cuales son los requerimientos que debe tener un programa que analice el código fuente de una aplicación escrita en Turbo Pascal Orientado a Objetos y a partir del mismo genere el Modelo de Objetos correspondiente.

Esta especificación de requerimientos está destinada a ser leída tanto por los usuarios de la aplicación como por cualquier sujeto que tenga interés en saber como funciona el programa.

1.2. Ámbito.

El programa que vamos a describir puede clasificarse como una aplicación de análisis y depuración de programas desarrollados con el lenguaje Turbo Pascal Orientado a Objetos.

El presente producto analiza el código fuente de la aplicación en estudio y guarda los resultados de dicho análisis en una Base de Datos interna, a partir de la cual se podrá obtener el Modelo de Objetos de la misma y representarlo en el formato A DETERMINAR.

1.3. Definiciones, acrónimos y abreviaturas.

TPOO. Turbo Pascal Orientado a Objetos.

OMT. Modelo de Objetos.

BDA.. Base de Datos.

IEEE. Asociación internacional dedicada a la estandarización de procesos de fabricación y desarrollo.

API. Término con el que se conoce un documento asociado a un producto de desarrollo de aplicaciones en el que se explica detalladamente el mismo (Interfaz del Programador de Aplicaciones).

CUA. Documento desarrollado por IBM que normaliza el comportamiento de una aplicación de ventanas. [4]

Icono. Una imagen de bits miniatura que normalmente realiza una acción al ser seleccionada.

1.4. Referencias.

Para la realización de este texto se han tenido en cuenta los siguientes documentos:

[1] Guía del IEEE para la Especificación de Requerimientos de Software. Boletín de prácticas de la asignatura de Ing. del Software de la EUI, UPV. 1996.

[2] Object Modeling Technique. XXXXX

[3] El API de Windows se explica en muchos libros, pero una relación completa del mismo puede encontrarse en el archivo windows.h del paquete Borland C++.

[4] Lee Adams. Programación Avanzada en de Gráficos en C para Windows. McGraw-Hill / Interamericana de España, S.S. 1993. Pág. 24.

2. Descripción general.

A continuación vamos a ver los factores que afectan al producto y a sus requerimientos.

2.1. Perspectivas del producto.

El presente producto debe ser un programa en Borland Delphi para Windows y como tal debe cumplir todas las especificaciones de un programa que funcione bajo Windows, así como beneficiarse de las ventajas que ello supone, como es la sencillez de la interface con el usuario que tal sistema utiliza.

Por lo tanto el programa podrá ser ejecutado en cualquier estación de trabajo que funcione bajo el sistema Windows.

Como el programa a desarrollar es, básicamente, un analizador de código, ello permitirá que con la misma estructura de este programa se pueda generar otro semejante que trabaje sobre aplicaciones escritas en otros lenguajes similares al TPOO, como por ejemplo el TURBO C++ y el BORLAND C.

2.2. Funciones del producto.

Las funciones que debe realizar el producto las podemos clasificar en varios bloques:

a) Obtención de los datos necesarios para realizar el análisis.

- Obtención del código fuente del programa principal de la aplicación a estudiar.

- Obtención del código fuente de los distintos subprogramas que componen la aplicación a estudiar.

- Obtener los objetos de la aplicación a estudiar y almacenarlos en una BD para su utilización posterior.

- Obtener los atributos y métodos de dichos objetos y almacenarlos en una BD para su utilización posterior.

- Obtener los enlaces entre objetos de la aplicación y almacenarlos en una BD para su utilización posterior.

b) Almacenamiento del fichero de resultados.

- Almacenar en un fichero los datos contenidos en la BD.

- Almacenar en un fichero los datos de un archivo de texto que se utilizará para comprobar el buen funcionamiento de la aplicación.

c) Herramientas de ayuda en el uso de la aplicación.

- Imprimir tanto los datos obtenidos de la aplicación como el fichero de texto generado en el formato determinado.

- Configurar la impresora por defecto y el modo de impresión.

- Poder cambiar las opciones de representación del fichero de texto con los resultados en lo referente a colores y tipos de letra.

2.3. Características del usuario.

A continuación vamos a ver qué tipo de usuario van a usar el producto y como afectan estos a las funciones que debe realizar el producto.

En primer lugar aparecen los iniciados en la programación con TPOO que pueden usar el producto para la obtención rápida del Modelo de Objetos de una aplicación sobre la que estén trabajando. Este tipo de usuarios esperarán un tiempo de respuesta muy breve y la posibilidad de obtener el OMT de la aplicación que estén estudiando en el formato que ellos deseen, así como una copia impresa de los resultados, tanto del modelo como de la información obtenida de los objetos de la aplicación.

El otro tipo de usuarios serán aquellos que están comenzando con la programación en lenguaje TPOO y quieren obtener información fiable, es decir, corregida por un programa de análisis, de la aplicación que estén desarrollando.

Dado que el programa trabajará sobre aplicaciones ya acabadas y el proceso de análisis deberá ser rápido y prácticamente automático, la interacción con el usuario será poca y eso hace que el programa no tenga ningún tipo de limitación idiomática, por lo que puede fácilmente ser utilizado por usuarios extranjeros.

Cabe la posibilidad de hacer que el programa funcionara en otros tipos de máquinas con distintos sistemas operativos (MS-DOS, Linux, etc.) escribiéndolo en TP, tal modificación es bastante sencilla, ya que el Borland Delphi y el Turbo Pascal son muy similares. De esta forma se podría realizar todo el proceso de obtención del OMT desde la línea de comandos, lo cual daría más rapidez a la aplicación.

2.5. Supuestos y dependencias.

El presente producto depende enteramente de Windows y donde llega Windows 3.1 y sus futuras versiones (Win `95, Windows NT ...) debe poder llegar el programa, ya que debe cumplir todas las normas Windows expresadas en su API (Interfaz de para el Programador de Aplicaciones).

3. Requerimientos específicos.

3.1. Requerimientos funcionales.

3.1.1. Obtención del código fuente del programa principal de la aplicación a estudiar.

El programa a desarrollar deberá abrir el fichero fuente del programa principal de la aplicación que se estudie, para poder analizar el código de esta, así como aquellos otros módulos de código (unidades de programación) de los cuales se sirva.

3.1.2. Obtención del código fuente de los distintos subprogramas que componen la aplicación a estudiar.

El presente producto debe ser capaz de acceder al código fuente de aquellos subprogramas en los que se basa la aplicación que se estudie, para poder analizar también dicho código. Sin esta operación solo se podría analizar un bloque de código fuente, el del programa principal, perdiendo toda relación con las demás unidades en las cuales se apoye, por lo tanto, esta operación se deberá realizar sobre el programa principal y sobre cada uno de los subprogramas que utilice.

Esta función deberá tomar de la línea uses del código fuente de la unidad en estudio los nombres de las unidades en las cuales se basa, comprobar si esta disponible el código fuente de las mismas, para que en caso negativo sean ignoradas, y en caso de que exista pueda se analizado posteriormente.

3.1.3. Obtener los objetos de la aplicación a estudiar y almacenarlos en una BD para su utilización posterior.

La aplicación en una primera pasada del código en estudio deberá obtener los nombres de los objetos que se definan en la unidad estudiada y almacenarlos en un formato determinado en una BD.

Para ello bastará con estudiar las líneas donde se halla la instrucción Object de TPOO y comprobar si se trata o no de una herencia, a fin de poder incluir tal información en la BD, tomar el nombre y guardar la información obtenida en la BD.

3.1.4. Obtener los atributos y métodos de dichos objetos y pasar a almacenarlos en una BD para su utilización posterior.

En el lenguaje TPOO cuando se define un objeto, a continuación se definen los atributos y métodos propios de él, esto es lo que analizará nuestro programa, línea a línea en el código a estudiar.

Para ello se deberá tener en cuenta que cada nombre de atributo va seguido de dos puntos (:), a continuación el tipo de dato de que se trata (integer, real, string...) y finalmente un punto y coma (;). No hay que olvidar que varios atributos pueden ser definidos en la misma instrucción separando sus nombres con comas (,).

En lo referente a los métodos, estos siempre van precedidos de la instrucción procedure o function, por lo que su identificación aún es más simple.

Toda la información obtenida deberá guardarse en la BD incluyendo para cada método y atributo a qué objeto pertenece.

3.1.5. Obtener los enlaces entre objetos de la aplicación y pasar a almacenarlos en una BD para su utilización posterior.

Nuestra aplicación deberá ser capaz de identificar las relaciones entre los distintos objetos del código en estudio, es decir, deberá estudiar las llamadas que cada método del objeto hace a los otros objetos y comprobar si tal llamada es a un método propio o pertenece a otro objeto.

Esta función deberá leer cada línea de código, verificar si hay llamadas a los métodos asociados a objetos (objeto.método), extraer el objeto al cual se llama y comprobar si es el objeto al cual pertenece el método que se esta estudiando en ese momento. Si no lo es ya podremos decir que entre los dos objetos se establece una relación. Luego deberemos recorrer la lista de objetos de la BD para ver si el objeto al cual se llamaba esta en ella, en caso afirmativo solo estableceremos la relación entre los dos objetos, pero en caso negativo deberemos averiguar a que unidad pertenece ese objeto y analizarla posteriormente.

3.1.6. Almacenar en un fichero los datos contenidos en la BD.

La aplicación deberá disponer de capacidad para almacenar en un fichero los datos que haya almacenado en la BD interna, como fruto del análisis de un programa en TPOO. Dicha función deberá ser similar a las que utilizan los demás productos desarrollados para Windows, ya que al trabajar bajo ese entorno los usuarios están acostumbrados a emplear una interface que les resulta tan familiar.

3.1.7. Almacenar en un fichero los datos de un archivo de texto que se utilizará para comprobar el buen funcionamiento de la aplicación.

Además del fichero anterior y con el fin de evitar confusión a la hora de comprobar el correcto funcionamiento del programa, se creará un archivo de texto, visible desde la propia aplicación a traves de la apertura de un archivo, cuyo contenido será igual al del fichero de resultados pero esta vez en formato de texto.

3.1.8. Imprimir tanto los datos obtenidos de la aplicación como el fichero de texto generado en el formato determinado.

3.1.9. Configurar la impresora por defecto y el modo de impresión.

3.1.10. Poder cambiar las opciones de representación del fichero de texto con los resultados en lo referente a colores y tipos de letra.

3.2. Requerimientos de interfaces externos.

3.2.1. Interfaces de usuario.

En este apartado, vamos a hablar de los procesos existentes entre el ordenador y el usuario. Para ello abordaremos en primer lugar el comportamiento del producto en la pantalla.

El usuario pretende ver cuando ejecuta una aplicación Windows un comportamiento semejante al de todas las aplicaciones diseñadas para este sistema. Por ejemplo todas las aplicaciones permiten configurar la impresora, realizan llamadas a Windows y muestran un cuadro de dialogo común diseñado por el fabricante.

Analizador de programas escritos en Turbo Pascal Orientado a Objetos

Por ello, la aplicación contendrá cuadros de dialogo para acceder a los ficheros (obtener y almacenar), semejantes a los que ofrece Windows.

Otro aspecto a tener en cuenta, es que la aplicación deberá tener zonas de selección, iconos o botones que activen distintas acciones del programa. Los menús de la aplicación deben seguir el orden que encontramos en todas las aplicaciones y que esta plasmado en el documento CUA de IBM.

En cuanto a las entradas realizadas a través de teclado, debemos destacar algunos aspectos, como tener teclas de acceso rápido a los elementos del menú, así como a los elementos dentro de los cuadros de dialogo. Por supuesto deben respetarse los comportamientos estándares dentro de los cuadros de dialogo, como por ejemplo, usar la tecla <TAB> para avanzar los campos de textos.

3.2.2. Interfaces hardware.

Inicialmente, el presente producto puede usar todos los dispositivos que admite Windows. Hacer una lista de todo el hardware compatible Windows es demasiado extenso y contraproducente. Hay que destacar el concepto de independencia que aporta el desarrollo de programas bajo sistemas tan extendidos como Windows.

3.2.3. Interfaces software.

El producto que estamos describiendo se desarrolla bajo el sistema operativo MSDOS en su versión 6.2, y sobre dicho sistema, se ha usado Windows 3.1 como entorno sobre el que se va a ejecutar la aplicación. En ultima instancia, la aplicación usa las funciones de los interfaces de Windows y por tanto, realmente no depende de MSDOS. De hecho existen versiones superiores de Windows que son completos sistemas operativos, como Windows NT o Windows 95. En principio, el presente producto debe usar las funciones de los tres interfaces que presenta Windows 3.1. Dado que el API de Windows 3.1 posee cerca de 1000 funciones, a continuación se presenta una breve descripción de los más usuales.

3.4. Restricciones de diseño.

3.4.1. Estándares cumplidos.

Como ya se ha especificado, la aplicación desarrollada deberá cumplir todos los estándares propios del sistema Windows bajo el cual va a trabajar.

Manual de usuario

Como hemos mencionado anteriormente, la interfaz de usuario es muy sencilla de entender y manejar, aun así comentaremos brevemente el manejo de la aplicación.

Hemos dividido la pantalla en:

- Menú principal de aplicación.

- Barra de herramientas.

- Panel de controles.

- Tres cajas de edición.

Menú principal.

El menú principal de la aplicación consta de cuatro opciones, que pasamos a enumerar:

Fichero: En esta opción se incluye un submenú bastante estandard de todas las acciones que se suelen realizar con archivos. Estas son:

Abrir: Aparece la pantalla estandard de Windows para abrir ficheros y abre el fichero seleccionado, colocándolo en una de las cajas de edición.

Imprimir: Aparece la pantalla estandard de Windows para imprimir ficheros. Imprime el texto situado en la caja de edición activa (donde está el cursor). Las cajas se activan pinchando sobre ellas con el ratón.

Por problemas con el Delphi, para poder imprimir con un tamaño normal, hay que ampliar considerablemente el tamaño de la fuente.

Configurar impresoras: Aparece la pantalla estandard de Windows para configurar impresoras, pudiendo adaptar la impresión a la impresora que se posea.

Preferencias: En esta opción hay otro submenú, que tepermite cambiar el color de fondo y el estilo, color y tamaño de la fuente de la caja de edición activa en ese momento. También utilizamos las ventanas estandard de Windows.

Salir: Termina la aplicacion.

Ejecutar: Contiene un submenú con la opción Ejecución que permite ejecutar la aplicación. Esta opción no estará activa hasta que no se tenga un fichero abierto.

Ver Resultados: Contiene un submenú con la opción Visualizar Resultados que permite visualizar el fichero donde ha sido almacenada la ejecución de la aplicación. El submenú no estará activo hasta que no se haya ejecutado el programa.

Acerca de... : Contiene un submenú con la opción Acerca de... que visualiza los componentes que han realizado esta aplicación.

En todas las opciones se han incluido aceleradores de teclas para su manejo mediante teclado. La combinación a utilizar es la tecla <Alt> + la letra subrayada de la opción correspondiente.

Barra de herramientas.

En esta barra se incluyen cuatro botones que se corresponden con las subsiguientes opciones del menú principal. Estas son:

- Abrir fichero.

- Imprimir.

- Cambiar color, estilo y tamaño de fuente.

- Cambiar color de fondo.

De todos modos, al situar el ratón sobre cada uno de los botones, aparece un comentario explicativo de la función que desempeña.

Los botones de Imprimir y Cambiar color,estilo y tamaño de fuente no están habilitados hasta que no se abra ningún fichero.

Panel de Controles.

En este panel se incluyen tres botones que se corresponden con las subsiguientes opciones del menú principal. Son estas:

- Ejecutar.

- Visualizar.

- Salir.

El botón de Ejecutar no está habilitado hasta que no se abra ningún fichero y el de Visualizar hasta que no se ejecute la aplicación.

Cajas de Edición.

En la aplicación aparecen dos cajas de edición, inicialmente vacías. Al abrir un fichero, éste aparece en una de ellas. Cuando se ejecuta el programa, las unidades que explora van apareciendo en la otra caja de edición. Además existen etiquetas explicativas sobre cada caja.

Al pulsar la opción de Visualizar, aparece otra caja en la cual se situa el fichero con los resultados de la ejecución del programa.

Todas las cajas de edición son de sólo lectura, no pudiendo modificar ninguno de los archivos, pese a que el cursor aparezca en la que esté activa en cada momento.

Funcionamiento normal de la aplicación.

- Se abre el fichero a explorar.

- Aparece en una de las cajas de edición.

- Se ejecuta la aplicación. El programa pregunta la ruta y el nombre del archivo donde colocar el fichero de registros (los resultados). En caso de existir este archivo, pregunta si se desea sobreescribirlo. Si la ruta introducida no es válida, aparece un mensaje de error y vuelve a pedir una válida. A su vez graba un fichero imprimible en el directorio actual, con el nombre “datos.txt”.

- Si se desea, se visualizan los resultados, apareciendo éstos en otra caja de edición.

- El programa permite repetir estos pasos tantas veces como archivos se deseen explorar, saliendo cuando el usuario considere oportuno.

Manual del programador.

En este manual nos vamos a centrar única y exclusicamente a la explicación de la programación propia de Turbo Pascal, dejando un poco de lado la interfaz de usuario que ha sido implementada en Borland Delphi. De todos modos se adjuntan los listados correspondientes a las propiedades y eventes de todos y cada uno de los componentes de la aplicación (*.DFM).

A continuación pasamos a comentar el desarrollo del programa:

La aplicación “Explorador de codigo” consta de dos unidades que se corresponden con dos formularios.

La unidad “explorar” contiene el código principal de la aplicación y la unidad “acercade” contiene la implementación correspondiente a la ventana de Acerca de, por lo cual nos vamos a centrar en la primera.

Dicha unidad contine una clase “Texplorador” compuesta por los atributos y métodos que se corresponden con las posibles operaciones a realizar desde la interfaz de usuario. Obviaremos el comentario de estos atributos ya que no forma parte de la programación propiamente dicha sino que utilizan las facilidades visuales de Delphi. Si que comentaremos los métodos cuando entremos en la parte de implementación.

La estructura de datos que hemos utilizado es un registro que contiene todos los posibles elementos que nos podemos encontrar al explorar las clases de cada programa o unidad.

La estrutura básica es la siguiente:

elem_diag=record

case tipo_elemento(...............) of

tipo1: (atributo1, atributo2,...);

tipo2: (atributo1, atributo2,...);

tipo3: (atributo1, atributo2,...);

...

...

tipon: (atributo1, atributo2,...);

end;

end;

Los elementos que nos podemos encontrar son:

- programa.

- clase.

- atributo.

- métodos.

- especializaciones.

- asociaciones.

Para cada uno de estos elementos que formarán el archivo de salida se definen los siguientes atributos:

Programa: (nombre_pro:string);

donde nombre_pro es el nombre de la unidad o programa que estamos explorando.

Clase: (nombre_clase:string);

donde nombre_clase indica el nombre de cada clase que nos vamos encontrando.

Atributo: (nombre_atrib,tipo_atrib:string);

donde indican respectivamente el nombre y el tipo del atributo.

Método: (nombre_método:string; parametros:reg_parametros);

donde el primero corresponde al nombre del método y el segundo es el registro de parámetros que contiene.

Especialización: (superclase:string);

donde indicamos cuál es la clase padre.

Asociación: (con_clase:string);

donde indicamos la clase con la que está asociada.

Respecto a las variables utilizadas en la aplicación, creemos que quedan suficientemente explicadas en los comentarios del código. Lo único a destacar es que la variable fichero utiliza la estructura de datos comentada anteriormente por lo que contendrá los resultados de la exploración. También nos hemos declarado un fichero de texto auxiliar f para poder visualizar ordenadamente los resultados por pantalla e impresora. Hemos definido el vector registros para contener las posibles asociaciones que puedan surgir dentro de otro registro que se encuentre fuera de la clase.

Pasamos a comentar la implementación explicando cada uno de los procedimientos:

Procedure AbrirClick(Sender:TObject);

Abre el fichero seleccionado mediante la ventana Abrir de Windows y lo asignamos a nombre_fichero. Lo colocamos en la cajaedicion1. En path guardamos la ruta del fichero abierto para la posterior búsqueda de las demás unidades a explorar. El resto es para habilitar o deshabilitar los botones que sean oportunos y para mostrar las etiquetas. En este momento unidades_programa contiene la primera unidad que vamos a explorar (la que acabamos de abrir).

Procedure SalirClick(Sender:TObject);

Cierra la aplicación.

Procedure ColoresClick(Sender:TObject);

Cambia el color de fondo de la caja de edición seleccionada (la que tiene el cursor).

Procedure TiposdeLetraClick(Sender:TObject);

Cambia el color, estilo y tamaño de la fuente de la caja de edición seleccionada.

Procedure ImprimirClick(Sender:TObject);

Imprime el contenido de la caja de edición seleccionada. Como Delphi sólo permite imprimir objetos Canvas es necesario asignar cada línea de la caja de edición seleccionada a dicho objeto y desde ahí, mandarlo a impresora.

Procedure ConfigurarImpresorasClick(Sender:TObject);

Permite configurar la impresora que se vaya a utilizar.

Procedure AcercadeClick(Sender:TObject);

Muestra la ventana del Acerca de...

Procedure Leepalabra;

Introduce en palabra cada carácter que pueda formar parte de una palabra válida (consideramos caracteres válidos los que forman parte de este conjunto:

['0'..'9' , 'A'..'Z' , 'a'..'z' , 'ñ'..'Ñ' , '.' , '_' , '^'] ) y la convierte a minúscula (función ansilowercase).

Procedure Elimina_blancos;

Lee caracteres mientras que sean blancos.

Function Unidades:boolean;

Devuelve true cuando la unidad leída de la cláusula uses de un programa es predefinida de Turbo Pascal.

Function TipoAtributo:boolean;

Devuelve true cuando el tipo del atributo leído es predefinido de Turbo Pascal o definido por el usuario.

Function TipoRegistro(var auxi:string):boolean;

Cuando esta función toma el valor true devuelve en auxi la clase con la que está asociada. En el procedimiento Ejecucion explicaremos cuándo utilizamos el registro registro comentado en la estructura de datos.

Function repe:boolean;

Controla que no se introduzca dos veces la misma unidad en el vector unidades_programa, para no explorarla más de una vez.

Function Puntero:boolean;

Comprueba si la palabra leída se encuentra en el vector punteros, siendo éstas de tipo puntero y que están en el type de la unidad que está explorando.

Procedure InicializaVectores;

Este procedimiento borra lo que haya en los vectores puntero, tipos, asoc y registros, que son propios de la última unidad explorada, para introducir los de la nueva.

Function AsociacionRepe(pal:string):boolean;

Esta función comprueba si la palabra que le pasamos por parámetro, que es una asociacion, ya ha sido almacenada en el fichero de salida, con el fín de no almacenar más de una vez la misma asociación de una clase.

Procedure Ejecucion(nombre_fichero:string);

El funcionamiento de este procedimiento lo vamos a comentar secuencialmente, simulando el funcionamiento normal del programa.

-Recibe par parámetro el nombre del fichero a explorar.

-Mientras no encontremos las palabra implementación, var o begin leemos palabra:

- Si la palabra es program o unit, leemos el nombre del mismo y lo introducimos en los dos ficheros (el de registros y el de texto).

- Si la palabra es uses, vamos guardando en el vector unidades_programa las unidades que no son de librería, controlando que no se repitan.

- Si la palabra es const, guardamos en el vector tipos las constantes que haya definidas.

- Si la palabra es type, examinamos todo su contenido hasta encontrar la palabra implementation o var (esta segunda es para no examinar variables que no formen parte de la clase en la que nos encontremos).

Vamos leyendo palabras; si encontramos Object, en aux está el nombre de la clase por lo que ya podemos introducirlo en los ficheros.

Comprobamos si después del Object hay un paréntesis, lo que significaría que hay herencia y también introduciríamos la superclase en los ficheros. Vamos examinando los atributos y métodos de esta clase hasta encontrar un end que indica el fin de la misma. Cuando examinamos atributos, los almacenamos en el vector atributos hasta encontrar su tipo. Comprobamos si son definidos por el usuario o predefinidos de Turbo Pascal para introducir ambos (nombre y tipo del atributo) en los ficheros; de no ser así, es porque es una asociación, por tanto guardamos en los ficheros la clase con la que está asociada. Cuando examinamos métodos, introducimos en los ficheros su nombre así como los parámetros que tengan (con sus respectivos tipos).

Si la palabra encontrada no es Object es porque se trata de un tipo definido por el usuario, por lo que los vamos almacenando en el vector tipos. Como podemos encontrarnos una asociación dentro de los campos de un registro, ha sido necesario declarar el vector registro. Para su mayor comprensión situamos un ejemplo de esta situación a continuación:

nombrePtr=^nombreObj;

nombreObj=record

campo1:nombrePtr;

campo2:nombreclasePtr;

{nombreclasePtr hace referencia a una

clase}

end;

Dentro de otra clase habrá un atributo cuyo tipo será nombrePtr, por lo que utilizamos la función TipoRegistro que nos devolverá la clase con la que está asociada.

Procedure EjecucionClick(Sender:TObject);

Primero pregunta la ruta y nombre del fichero donde almacenar los resultados (fichero de registros). Si la ruta no existe da un mensaje de error y vuelve a pedirla de nuevo. Si ya existe el fichero, pregunta si se desea sobreescribirlo o no.

Asigna el fichero de registros al nombre que se acaba de introducir. Además asigna al fichero de texto f el nombre “datos.txt”, que será almacenado en el directorio actual. Va recorriendo el vector unidades_programa, pasándole cada nombre al procedimiento Ejecucion que recorrerá (conforme hemos explicado anteriormente) todas y cada una de las unidades que en él se encuentren.

Procedure FormCreate(Sender:TObject);

Inicializa los vectores unidades_Pascal y Tipos con las unidades y tipos predefinidos en Pascal. Activa la cajaedicion1.

Procedure VisualizarResultadosClick(Sender:TObject);

Asigna al fichero de texto f el nombre “datos.txt”. Hace más pequeña la cajaedicion1 y muestra cajaedicion3 donde irá añadiendo dicho fichero.

Procedure Cajaedicion1Click(Sender:TObject);

Activa cajaedicion1 y desactiva las otras dos.

Procedure Cajaedicion2Click(Sender:TObject);

Activa cajaedicion2 y desactiva las otras dos.

Procedure Cajaedicion3Click(Sender:TObject);

Activa cajaedicion3 y desactiva las otras dos.

NOTA:

En todos los procedimientos asociados a las pulsaciones sobre botones u opciones del menú, Delphi añade el parámetro Sender de tipo TObject. Esta último es la clase padre de todas las demás por defecto y el Sender se utiliza para indicar el objeto que en realidad activa este evento. Por ejemplo, si se pulsa un botón, el objeto Explorador es el que en realidad lo activa.

Nosotros no hemos utilizado esto para nada, pero lo hemos dejado por seguir la sintaxis de Delphi.

Listado del programa.

program Proyecto;

uses

Forms,

Explorar in 'EXPLORAR.PAS' {Explorador},

Acercade in 'ACERCADE.PAS' {AboutBox};

{$R *.RES}

begin

Application.CreateForm(TExplorador, Explorador);

Application.CreateForm(TAboutBox, AboutBox);

Application.Run;

end.

unit Explorar;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

Forms, Dialogs, Menus, StdCtrls, ExtCtrls, Buttons, Printers,Acercade;

type

TExplorador = class(TForm)

MenuPrincipal: TMainMenu;

Fichero1: TMenuItem;

Ejecutar: TMenuItem;

VerResultados: TMenuItem;

Imprimir: TMenuItem;

ConfigurarImpresoras: TMenuItem;

N2: TMenuItem;

Preferencias: TMenuItem;

Colores: TMenuItem;

Tiposdeletra: TMenuItem;

N3: TMenuItem;

Salir: TMenuItem;

BarraHerramientas: TPanel;

N4: TMenuItem;

Ayuda: TMenuItem;

ColorDialog1: TColorDialog;

FontDialog1: TFontDialog;

Ejecucion1: TMenuItem;

Acercade: TMenuItem;

PrintDialog1: TPrintDialog;

PrinterSetupDialog1: TPrinterSetupDialog;

Visualizarresultados: TMenuItem;

PanelPresentacion: TPanel;

CajaEdicion1: TMemo;

botonabrir: TSpeedButton;

botonimprimir: TSpeedButton;

PanelControles: TPanel;

botonejecutar: TButton;

botonvisualizar: TButton;

botonsalir: TButton;

botonfuente: TSpeedButton;

boton

Etiqueta1: TLabel;

Etiqueta2: TLabel;

Etiqueta3: TLabel;

N1: TMenuItem;

CajaEdicion2: TMemo;

etiqueta4: TLabel;

CajaEdicion3: TMemo;

AbrirFuente: TMenuItem;

OpenDialog1: TOpenDialog;

procedure AbrirClick(Sender: TObject);

procedure SalirClick(Sender: TObject);

procedure ColoresClick(Sender: TObject);

procedure TiposdeletraClick(Sender: TObject);

procedure ImprimirClick(Sender: TObject);

procedure ConfigurarImpresorasClick(Sender: TObject);

procedure AcercadeClick(Sender: TObject);

procedure Leepalabra;

procedure Elimina_blancos;

function Unidades:boolean;

function TipoAtributo:boolean;

function TipoRegistro(var auxi:string):boolean;

function repe:boolean;

function puntero:boolean;

procedure inicializavectores;

function AsociacionRepe(pal:string):boolean;

procedure Ejecucion(nombre_fichero:string);

procedure Ejecucion1Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure VisualizarresultadosClick(Sender: TObject);

procedure CajaEdicion1Click(Sender: TObject);

procedure CajaEdicion3Click(Sender: TObject);

procedure CajaEdicion2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

tipo_elemento=(programa,clase,atributo,metodo,especializacion,asociacion);

{ contiene los posibles elementos del fichero registro}

reg_parametros=record

nombre,tipo_para:string;

end;

{registro para guardar los parametros de cada metodo de las clases}

elemento=record

case tipo_elemento of

programa:(nombre_pro:string);

clase:(nombre_clase:string);

atributo:(nombre_atri,tipo_atri:string);

metodo:(nombre_metodo:string;tipo_met:boolean;parametros:reg_parametros);

especializacion:(superclase:string);

asociacion:(con_clase:string);

end;

{registro para almacenar el fichero de resultados}

regis=record

nom_reg,asoc:string;

end;

{registro para almacenar asociaciones que estén dentro de un campo del mismo}

var

f:textfile; {fichero de visualizacion de resultados}

ele:elemento; {variable de tipo registro}

explorador: TExplorador; {objeto}

fichero:file of elemento; {fichero de resultados}

fich:text; {fichero que contiene el codigo fuente que exploramos}

Nombre_fichero:string; {Nombre del fichero que vamos a explorar}

resultados:string; {Nombre del fichero en el cual almacenamos los resultados}

nom:string; {Nombre del fichero de visualización}

palabra:string; {almacenamos cada palabra que leemos del fichero fuente}

path:string; {continene la ruta donde se encuentran los ficheros a explorar}

c:char; {cada caracter que leemos del fichero fuente}

unidades_pascal:array[1..23] of string; {vector que contiene las unidades predefinidas del pascal}

unidades_programa:array[1..40] of string; {vector que contine las unidades que tenemos que explorar}

tipos:array[1..30] of string; {contiene tanto los tipos predefinidos como los definidos por el usuario}

atributos:array[1..10] of string; {guardamos los atributos que encontramos en cada clase}

punteros:array[1..10] of string; {almacenamos las clases que nos encontramos}

registros:array[1..10] of regis; {almacenamos asociaciones las cuales están en un campo del registro }

j,cont,ind:integer; {indices de los distintos vectores}

caja1,caja2,caja3:boolean; {variables para controlar que caja de edicion esta activa}

asoc:array[1..10] of string; {almacenamos las asociaciones que nos encontramos en cada programa}

implementation

{$R *.DFM}

procedure TExplorador.AbrirClick(Sender: TObject);

{Procedimiento mediante el cual abrimos el fichero fuente}

var

s:string; {variable auxiliar para el nombre de la etiqueta de la caja de edicion1}

begin

if OpenDialog1.Execute then {si pulsamos la opcion de Abrir}

begin

CajaEdicion1.Lines.LoadFromFile(OpenDialog1.Filename);

Nombre_fichero:=OpenDialog1.Filename;

unidades_programa[1]:=nombre_fichero;

path:=extractfilepath(unidades_programa[1]);

unidades_programa[1]:=extractfilename(unidades_programa[1]);

configurarimpresoras.enabled:=true;

ejecucion1.enabled:=true;

tiposdeletra.enabled:=true;

imprimir.enabled:=true;

colores.enabled:=true;

botonejecutar.enabled:=true;

botonimprimir.enabled:=true;

botonfuente.enabled:=true;

visualizarresultados.enabled:=false;

botonvisualizar.enabled:=false;

cajaedicion2.Clear;

s:=etiqueta1.Caption;

delete(s,22,255);

etiqueta1.Caption:=s+' "'+unidades_programa[1]+'"';

etiqueta2.Visible:=false;

cajaedicion3.visible:=false;

cajaedicion1.Width:=577;

end;

end;

procedure TExplorador.SalirClick(Sender: TObject);

{cierra la aplicación}

begin

Close;

end;

procedure TExplorador.ColoresClick(Sender: TObject);

{cambia el color de fondo de la caja de edición seleccionada}

begin

if ColorDialog1.Execute then

begin

if caja1 then

Cajaedicion1.Color:=ColorDialog1.Color;

if caja2 then

cajaedicion2.Color:=ColorDialog1.Color;

if caja3 then

cajaedicion3.Color:=ColorDialog1.Color;

end;

end;

procedure TExplorador.TiposdeletraClick(Sender: TObject);

{cambia el color, tipo y tamaño de letra de la caja de edición seleccionada}

begin

if FontDialog1.Execute then

begin

if caja1 then

cajaedicion1.Font:=FontDialog1.font;

if caja2 then

cajaedicion2.Font:=FontDialog1.font;

if caja3 then

cajaedicion3.Font:=FontDialog1.font;

end;

end;

procedure TExplorador.ImprimirClick(Sender: TObject);

{Imprimimos el contenido de la caja de edición seleccionada}

var

prn:system.text;

n:integer;

begin

if printDialog1.execute then

begin

if caja1 then

begin

printer.canvas.font:=cajaedicion1.font;

assignprn(prn);

rewrite(prn);

for n:=0 to cajaedicion1.lines.count-1 do

writeln(prn,cajaedicion1.lines[n]);

system.close(prn);

end;

if caja2 then

begin

printer.canvas.font:=cajaedicion2.font;

assignprn(prn);

rewrite(prn);

for n:=0 to cajaedicion2.lines.count-1 do

writeln(prn,cajaedicion2.lines[n]);

system.close(prn);

end;

if caja3 then

begin

printer.canvas.font:=cajaedicion3.font;

assignprn(prn);

rewrite(prn);

for n:=0 to cajaedicion3.lines.count-1 do

writeln(prn,cajaedicion3.lines[n]);

system.close(prn);

end;

end;

end;

procedure TExplorador.ConfigurarImpresorasClick(Sender: TObject);

{configuramos la impresora}

begin

printerSetupDialog1.execute;

end;

procedure TExplorador.AcercadeClick(Sender: TObject);

{llamamos a la unidad acercade para visualizarlo}

begin

aboutbox.Show;

end;

procedure TExplorador.Leepalabra;

{ procedimiento para ir leyendo palabras del fichero fuente }

var

i:integer;

begin

while (c in ['0'..'9','A'..'Z','a'..'z','ñ'..'Ñ','.','_','^'])=false do

read(fich,c);

i:=0;

palabra[i]:=c;

i:=i+1;

while c in ['0'..'9','A'..'Z','a'..'z','ñ'..'Ñ','.','_','^'] do

begin

palabra[i]:=c;

i:=i+1;

read(fich,c);

end;

delete(palabra,i,255);

palabra:=ansilowercase(palabra);

elimina_blancos;

end;

procedure TExplorador.elimina_blancos;

{leemos caracteres del fichero mientras encontremos espacios en blanco}

begin

while (c=' ') do

read(fich,c);

end;

function TExplorador.unidades:boolean;

{comprobamos si las unidades contenidas en el use del fichero fuente son

unidades predefinidas del pascal o no }

var

i:integer;

begin

unidades:=false;

for i:=1 to 23 do

if palabra=unidades_pascal[i] then

unidades:=true

end;

function TExplorador.TipoAtributo:boolean;

{comprobamos si el tipo de los atributos que vamos obteniendo del fichero fuente

son predefinidos del pascal o definidos por el usuario}

var

i:integer;

begin

tipoatributo:=false;

for i:=1 to cont do

if palabra=tipos[i] then

tipoatributo:=true

end;

function TExplorador.TipoRegistro(var auxi:string):boolean;

{esta funcion nos devuelve una asociación cuando la misma está en un campo

del registro}

var

i:integer;

begin

TipoRegistro:=false;

for i:=1 to ind do

if palabra=registros[i].nom_reg then

begin

TipoRegistro:=true;

auxi:=registros[i].asoc

end;

end;

function TExplorador.repe:boolean;

{comprobamos que las unidades que nos encontramos en los USES de los ficheros

fuentes que examinamos no hayan sido ya almacenadas en el vector de unidades

de programa}

var

i:integer;

begin

repe:=false;

for i:=1 to j-1 do

if (unidades_programa[i]=palabra) then

repe:=true;

end;

function TExplorador.puntero:boolean;

{ comprueba si la palabra que hemos leido es un puntero}

var

i:integer;

begin

puntero:=false;

for i:=0 to 20 do

if palabra=punteros[i] then

puntero:=true;

end;

procedure TExplorador.inicializavectores;

{ borra todo lo que haya en los vectores que utilizamos en el procedimiento

de ejecucion y que son independientes para cada unidad que exploramos }

var

i:integer;

begin

for i:=1 to ind do

begin

delete(registros[i].nom_reg,1,255);

delete(registros[i].asoc,1,255);

end;

for i:=1 to 10 do

delete(punteros[i],1,255);

for i:=1 to 10 do

delete(asoc[i],1,255);

for i:=13 to cont do

delete(tipos[i],1,255);

for i:=1 to 10 do

delete(atributos[i],1,255);

end;

function TExplorador.AsociacionRepe(pal:string):boolean;

{ comprueba si la asociación que le pasamos como parámetro ya ha sido almacenada

en el fichero, para no hacerlo más de una vez }

var

i:integer;

begin

AsociacionRepe:=false;

for i:=1 to 10 do

if pal=asoc[i] then

asociacionRepe:=true;

end;

procedure TExplorador.Ejecucion(nombre_fichero:string);

{este procedimiento va examinando cada unidad que le pasamos como parametro y

vamos construyendo el fichero de resultados}

var

i,n,k,a,p:integer;

esta_en,repetida:boolean;

aux,auxi,s:string;

begin

assignFile(fich,nombre_fichero);

reset(fich);

delete(palabra,1,255);

p:=1;

inicializavectores;

ind:=1;

while (ansicomparetext(palabra,'implementation')<>0) and (ansicomparetext(palabra,'var')<>0)

and (ansicomparetext(palabra,'begin')<>0) do

begin

leepalabra;

if (ansicomparetext(palabra,'program')=0) then

{escribimos en el fichero de salida el nombre del programa}

begin

leepalabra;

ele.nombre_pro:=palabra;

write(fichero,ele);

writeln(f,'Programa : ',palabra);

end;

if (ansicomparetext(palabra,'unit')=0) then

{escribimos en el fichero de salida el nombre de la unidad}

begin

leepalabra;

ele.nombre_pro:=palabra;

write(fichero,ele);

writeln(f,'Unit : ',palabra);

end;

if (ansicomparetext(palabra,'uses')=0) then

{almacenamos en el vector de unidades de programa el nombre de las

unidades que vamos encontrando, que no sean predefinidas del pascal,

para examinarlas posteriormente}

begin

while (c<>';') do

begin

leepalabra;

esta_en:=unidades;

if not esta_en then

begin

esta_en:=repe;

if not esta_en then

begin

unidades_programa[j]:=palabra;

j:=j+1;

end;

end;

end;

end;

if (ansicomparetext(palabra,'const')=0) then

{guardamos en el vector tipos las constantes definidas por el usuario}

begin

while (ansicomparetext(palabra,'type')<>0) and (ansicomparetext(palabra,'var')<>0) do

begin

if c<>'=' then

begin

leepalabra;

tipos[cont]:=palabra;

cont:=cont+1;

end

else

begin

leepalabra; { Lee el valor de la constante }

leepalabra; { Lee la siguiente palabra: otra constante, type o var }

end;

end;

end;

if (ansicomparetext(palabra,'type')=0) then

{vamos almacenando en el fichero de salida las distintas clases que nos vamos

encontrando, asi como atributos, métodos, asociaciones...}

begin

i:=0;

while (ansicomparetext(palabra,'implementation')<>0) and (ansicomparetext(palabra,'var')<>0) do

begin

aux:=palabra;

leepalabra;

if (ansicomparetext(palabra,'object')=0) then

{comprobamos si hemos encotrado una clase }

begin

i:=i+1;

ele.nombre_clase:=aux;

write(fichero,ele); {introducimos el nombre de la clase en el fichero}

writeln(f,'Clase: ',aux);

if (c='(') then {comprobamos si hay herencia}

begin

leepalabra;

ele.superclase:=palabra;

write(fichero,ele);

writeln(f,'Clase Padre: ',palabra);

end;

a:=0;

leepalabra;

while (ansicomparetext(palabra,'end')<>0) do

{vamos almacenando los metodos y atributos de la clase que hemos encontrado}

begin

n:=0;

if ( ansicomparetext (palabra,'procedure') <> 0 ) and ( ansicomparetext (palabra,'function') <> 0 ) then

{examinamos los atributos de la clase encontrada}

while ( (c=',') or (c=':') )do

if c=',' then

{almacenamos en el vector atributos aquellos que sean del mismo tipo}

begin

atributos[n]:=palabra;

n:=n+1;

leepalabra;

end

else { Se han encontrado ':' }

begin

atributos[n]:=palabra;

read(fich,c);

elimina_blancos;

delete(s,1,255);

if (c='(') or (c in ['0'..'9']) then

{comprobamos si son tipos definidos por el usuario}

begin

if c='(' then

begin

while (c<>')') do

begin

leepalabra;

s:=s+palabra+c;

end;

s:='('+s;

end

else

begin

s:=c;

leepalabra;

s:=s+palabra;

end;

for k:=1 to n do

begin

ele.nombre_atri:=atributos[n];

ele.tipo_atri:=s;

end;

write(fichero,ele);

{introducimos en el fichero de salida los atributos

y el tipo de los mismos}

writeln(f,'Atributo: ',atributos[n],': ',s);

end {del if}

else {el tipo de atributos no es definido por el usuario}

begin

leepalabra;

palabra:=ansilowercase(palabra);

esta_en:=TipoRegistro(auxi);

{comprobamos si existe una asociación}

if esta_en then

begin

repetida:=asociacionrepe(auxi);

if not repetida then

begin

asoc[p]:=auxi;

p:=p+1;

ele.con_clase:=auxi;

write(fichero,ele);

{almacenamos en el fichero de salida con que

clase esta asociada}

writeln(f,'Clase ',aux,' asociada con ',auxi);

end

end

else

begin

esta_en:=tipoatributo;

{comprobamos si el tipo de atributo es predefinido}

if esta_en then

begin

for k:=0 to n do

begin

ele.nombre_atri:=atributos[k];

ele.tipo_atri:=palabra;

write(fichero,ele);

{guardamos en fichero de salida los atributos

y el tipo de los mismos}

writeln(f,'Atributo: ',atributos[k],':',palabra);

end;

if palabra='record' then

repeat

leepalabra;

until palabra='end';

end

else

begin

repetida:=asociacionrepe(palabra);

if not repetida then

begin

asoc[p]:=palabra;

p:=p+1;

ele.con_clase:=palabra;

write(fichero,ele);

{introducimos en el fichero de salida la clase con

la que está asociada}

writeln(f,'Clase ',aux,' asociada con ',palabra);

end

end

end {del else sino está_en}

end {del else de tipo de atributos no definido por el usuario}

end {del primer else}

else

begin { Analisis de procedure y function }

leepalabra;

ele.nombre_metodo:=palabra;

write(fichero,ele);

{alamacenamos en el fichero de salida el nombre del método}

writeln(f,'Método: ',palabra);

if c='(' then

{vamos guardando en el fichero de salida los nombres y tipo

de atributos de cada metodo}

while c<>')' do

begin

leepalabra;

if (ansicomparetext(palabra,'var')<>0) then

while ( (c=',') or (c=':') )do

if c=',' then

begin

atributos[n]:=palabra;

n:=n+1;

leepalabra;

elimina_blancos;

end

else { Se han encontrado ':' }

begin

atributos[n]:=palabra;

leepalabra;

esta_en:=tipoatributo;

if esta_en then

for k:=0 to n do

begin

ele.parametros.nombre:=atributos[k];

ele.parametros.tipo_para:=palabra;

write(fichero,ele);

writeln(f,'Parámetro: ',atributos[k],':',palabra);

end

end

end {del while}

end ; {del else del analisis de procedure y function}

leepalabra;

end; {del while del end}

leepalabra;

end {del if del object}

else { guardamos el tipo que no es un objeto }

if (aux<>'type') then

{examinamos lo que hay en el type fuera de una clase}

begin

if palabra='record' then

{comprobamos si algun campo del registro es de tipo clase}

begin

while palabra<>'end' do

begin

while c<>';' do

leepalabra;

esta_en:=puntero;

if not esta_en then

begin

esta_en:=tipoatributo;

if not esta_en then

begin

registros[ind].asoc:=palabra;

ind:=ind+1;

end

end;

leepalabra;

end;

tipos[cont]:=aux;

cont:=cont+1;

end

else

begin

while (c<>')') and (c<>';') and (aux<>'end') do

leepalabra;

if aux<>'end' then

if palabra[1]<>'^' then

begin

tipos[cont]:=aux;

cont:=cont+1;

leepalabra;

end

else

begin

punteros[i]:=aux;

i:=i+1;

registros[ind].nom_reg:=aux;

leepalabra;

end;

end; {del else}

end {del if de aux<>type}

end; {del while de implementacion y var}

end; {del if del type}

end {del primer while del procedimiento}

end;

procedure TExplorador.Ejecucion1Click(Sender: TObject);

{llama al procedimiento ejecutar pasandole el nombre de la unidad a explorar}

var

i:integer;

nombre,re:string;

sobre:boolean;

begin

repeat

sobre:=true;

resultados:=Inputbox('Ruta fichero salida','Introduce la ruta del fichero de salida','c:\noname.reg');

{muestra por pantalla una caja de dialogo para introducir la ruta y nombre del fichero de salida}

re:=extractfilepath(resultados)+'*.*';

if fileexists(re) then

{comprueba si existe la ruta, de no ser así muestra un mensaje de error}

begin

if FileExists(resultados) then

{comprueba si el nombre del fichero introducido existe, en cuyo caso muestra un mensaje de error}

if MessageDlg('El fichero "'+ExtractFileName(resultados)+'" existe, ¿Desea sobreescribirlo?',mtInformation,

[mbYes,mbNo],0) = mrNo then

sobre:=false

end

else

begin

MessageDlg('¡ La ruta "'+resultados+'" no existe !',mtInformation,[mbOK],0);

sobre:=false;

end;

until (resultados<>'') and (sobre=true);

cajaedicion2.clear;

assignfile(fichero,resultados);

rewrite(fichero);

nom:='datos.txt';

assignfile(f,nom);

rewrite(f);

i:=1;

j:=2;

nombre:=path+unidades_programa[i];

repeat {llama al procedimiento ejecucion pasandole como parametro el nombre del fichero

a explorar, hasta recorrer todo el vector que contiene las unidades de programa}

ejecucion(nombre);

cajaedicion2.Lines.Add(unidades_programa[i]);

i:=i+1;

nombre:=path+unidades_programa[i]+'.pas';

until (i=j);

closefile(fichero);

closefile(f);

visualizarresultados.enabled:=true;

botonvisualizar.enabled:=true;

end;

procedure TExplorador.FormCreate(Sender: TObject);

{almacenamos en un vector las unidades y los tipos predefinidos del pascal}

begin

unidades_pascal[1]:='app';

unidades_pascal[2]:='colorsel';

unidades_pascal[3]:='dialogs';

unidades_pascal[4]:='dos';

unidades_pascal[5]:='drivers';

unidades_pascal[6]:='crt';

unidades_pascal[7]:='editors';

unidades_pascal[8]:='graph';

unidades_pascal[9]:='graph3';

unidades_pascal[10]:='histlist';

unidades_pascal[11]:='memory';

unidades_pascal[12]:='menus';

unidades_pascal[13]:='msgbox';

unidades_pascal[14]:='objects';

unidades_pascal[15]:='outline';

unidades_pascal[16]:='stdlg';

unidades_pascal[17]:='strings';

unidades_pascal[18]:='textview';

unidades_pascal[19]:='turbo3';

unidades_pascal[20]:='validate';

unidades_pascal[21]:='views';

unidades_pascal[22]:='wincrt';

unidades_pascal[23]:='windos';

tipos[1]:='integer';

tipos[2]:='boolean';

tipos[3]:='string';

tipos[4]:='real';

tipos[5]:='double';

tipos[6]:='array';

tipos[7]:='record';

tipos[8]:='word';

tipos[9]:='extended';

tipos[10]:='byte';

tipos[11]:='shorting';

tipos[12]:='longint';

cont:=13;

caja1:=true;

caja2:=false;

caja3:=false;

end;

procedure TExplorador.VisualizarresultadosClick(Sender: TObject);

{visualizamos en una caja de edición el fichero de texto que hemos ido creando

durante la ejecución de la aplicación}

var

s:string;

x:string;

begin

resultados:='datos.txt';

assignfile(f,resultados);

reset(f);

cajaedicion1.Width:=273;

cajaedicion3.clear;

x:=etiqueta2.Caption;

delete(x,18,255);

etiqueta2.Caption:=x+' "'+resultados+'"';

etiqueta2.Visible:=true;

cajaedicion3.Visible:=true;

while not eof(f) do

begin

readln(f,s);

cajaedicion3.Lines.Add(s);

end;

end;

procedure TExplorador.CajaEdicion1Click(Sender: TObject);

{activa la caja de edicion1}

begin

caja1:=true;

caja2:=false;

caja3:=false;

end;

procedure TExplorador.CajaEdicion3Click(Sender: TObject);

{activa la caja de edicion2}

begin

caja1:=false;

caja2:=false;

caja3:=true;

end;

procedure TExplorador.CajaEdicion2Click(Sender: TObject);

{activa la caja de edicion3}

begin

caja1:=false;

caja2:=true;

caja3:=false;

end;

END.

unit Acercade;

interface

uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, StdCtrls,

Buttons, ExtCtrls;

type

TAboutBox = class(TForm)

Panel1: TPanel;

OKButton: TBitBtn;

ProgramIcon: TImage;

ProductName: TLabel;

Version: TLabel;

Copyright: TLabel;

Comments: TLabel;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

procedure OKButtonClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

AboutBox: TAboutBox;

implementation

{$R *.DFM}

procedure TAboutBox.OKButtonClick(Sender: TObject);

begin

close

end;

end.

Listado de propiedades y eventos del programa.

Unidad Explorar

object Explorador: TExplorador

Left = 224

Top = 133

Width = 491

Height = 409

Caption = 'Explorador de código'

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = []

Menu = MenuPrincipal

PixelsPerInch = 96

WindowState = wsMaximized

OnCreate = FormCreate

TextHeight = 19

object BarraHerramientas: TPanel

Left = 0

Top = 0

Width = 483

Height = 41

Align = alTop

BevelOuter = bvNone

BorderStyle = bsSingle

Color = 10526880

Ctl3D = True

Locked = True

ParentCtl3D = False

ParentShowHint = False

ShowHint = True

TabOrder = 0

object botonabrir: TSpeedButton

Left = 8

Top = 8

Width = 25

Height = 25

Hint = 'Abrir'

Glyph.Data = {}

OnClick = AbrirClick

end

object botonimprimir: TSpeedButton

Left = 40

Top = 8

Width = 25

Height = 25

Hint = 'imprimir'

Enabled = False

Glyph.Data = {}

NumGlyphs = 2

OnClick = ImprimirClick

end

object botonfuente: TSpeedButton

Left = 72

Top = 8

Width = 25

Height = 25

Hint = 'fuente'

Enabled = False

Glyph.Data = {}

NumGlyphs = 2

OnClick = TiposdeletraClick

end

object botoncolor: TSpeedButton

Left = 104

Top = 8

Width = 25

Height = 25

Hint = 'color de fondo'

Glyph.Data = {}

Layout = blGlyphBottom

NumGlyphs = 2

OnClick = ColoresClick

end

end

object PanelPresentacion: TPanel

Left = 0

Top = 41

Width = 483

Height = 322

Align = alClient

Color = 10526880

Font.Color = clBlack

Font.Height = -20

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

TabOrder = 1

object Etiqueta1: TLabel

Left = 24

Top = 16

Width = 147

Height = 19

Caption = 'Codigo fuente fichero '

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object Etiqueta2: TLabel

Left = 336

Top = 16

Width = 118

Height = 19

Caption = 'Contenido fichero'

Color = 10526880

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentColor = False

ParentFont = False

Visible = False

end

object Etiqueta3: TLabel

Left = 616

Top = 256

Width = 82

Height = 15

Caption = 'CONTROLES:'

Font.Color = clBlack

Font.Height = -13

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object etiqueta4: TLabel

Left = 624

Top = 48

Width = 144

Height = 19

Caption = 'Unidades exploradas:'

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object CajaEdicion1: TMemo

Left = 24

Top = 48

Width = 577

Height = 449

Color = 15793151

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

Lines.Strings = (

'')

ParentFont = False

ReadOnly = True

ScrollBars = ssBoth

TabOrder = 0

OnClick = CajaEdicion1Click

end

object PanelControles: TPanel

Left = 640

Top = 280

Width = 121

Height = 193

BevelInner = bvLowered

BevelOuter = bvLowered

BevelWidth = 2

Color = 10526880

TabOrder = 1

object botonejecutar: TButton

Left = 16

Top = 24

Width = 89

Height = 33

Caption = 'EJECUTAR'

Enabled = False

Font.Color = clGray

Font.Height = -13

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

TabOrder = 0

OnClick = Ejecucion1Click

end

object botonvisualizar: TButton

Left = 16

Top = 80

Width = 89

Height = 33

Caption = 'VISUALIZAR'

Enabled = False

Font.Color = clBlack

Font.Height = -13

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

TabOrder = 1

OnClick = VisualizarresultadosClick

end

object botonsalir: TButton

Left = 16

Top = 136

Width = 89

Height = 33

Caption = 'SALIR'

Font.Color = clBlack

Font.Height = -13

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

TabOrder = 2

OnClick = SalirClick

end

end

object CajaEdicion2: TMemo

Left = 632

Top = 80

Width = 129

Height = 137

Color = 16777088

Font.Color = clBlack

Font.Height = -15

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

Lines.Strings = (

'')

ParentFont = False

ReadOnly = True

ScrollBars = ssBoth

TabOrder = 2

OnClick = CajaEdicion2Click

end

object CajaEdicion3: TMemo

Left = 328

Top = 48

Width = 273

Height = 449

Color = 15793151

Font.Color = clBlack

Font.Height = -16

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

Lines.Strings = (

'')

ParentFont = False

ScrollBars = ssBoth

TabOrder = 3

Visible = False

OnClick = CajaEdicion3Click

end

end

object MenuPrincipal: TMainMenu

Left = 216

Top = 104

object Fichero1: TMenuItem

Caption = '&Fichero'

object AbrirFuente: TMenuItem

Caption = '&Abrir Fuente'

OnClick = AbrirClick

end

object N1: TMenuItem

Caption = '-'

end

object Imprimir: TMenuItem

Caption = '&Imprimir'

Enabled = False

OnClick = ImprimirClick

end

object ConfigurarImpresoras: TMenuItem

Caption = 'Configurar I&mpresoras'

Enabled = False

OnClick = ConfigurarImpresorasClick

end

object N2: TMenuItem

Caption = '-'

end

object Preferencias: TMenuItem

Caption = '&Preferencias'

object Colores: TMenuItem

Caption = '&Color de fondo'

OnClick = ColoresClick

end

object Tiposdeletra: TMenuItem

Caption = '&Tipo y color de letra'

Enabled = False

OnClick = TiposdeletraClick

end

end

object N3: TMenuItem

Caption = '-'

end

object Salir: TMenuItem

Caption = '&Salir'

OnClick = SalirClick

end

end

object Ejecutar: TMenuItem

Caption = '&Ejecutar'

object Ejecucion1: TMenuItem

Caption = 'E&jecución'

Enabled = False

OnClick = Ejecucion1Click

end

end

object VerResultados: TMenuItem

Caption = '&Ver Resultados'

object Visualizarresultados: TMenuItem

Caption = 'Visualizar &resultados'

Enabled = False

OnClick = VisualizarresultadosClick

end

end

object N4: TMenuItem

end

object TMenuItem

end

object Ayuda: TMenuItem

Caption = '&Acerca de...'

object Acercade: TMenuItem

Caption = '&Acerca de ...'

OnClick = AcercadeClick

end

end

end

object OpenDialog1: TOpenDialog

Filter = 'Fichero fuente|*.pas'

Options = [ofNoChangeDir]

Left = 56

Top = 104

end

object ColorDialog1: TColorDialog

Left = 88

Top = 104

end

object FontDialog1: TFontDialog

Font.Color = clWindowText

Font.Height = -13

Font.Name = 'System'

Font.Style = []

MinFontSize = 0

MaxFontSize = 0

Left = 184

Top = 104

end

object PrintDialog1: TPrintDialog

Left = 152

Top = 104

end

object PrinterSetupDialog1: TPrinterSetupDialog

Left = 120

Top = 104

end

end

Unidad Acercade

object AboutBox: TAboutBox

Left = 169

Top = 105

ActiveControl = OKButton

BorderStyle = bsDialog

Caption = 'Acerca de...'

ClientHeight = 367

ClientWidth = 528

Font.Color = clBlack

Font.Height = -13

Font.Name = 'System'

Font.Style = [fsBold, fsItalic]

PixelsPerInch = 96

Position = poScreenCenter

TextHeight = 16

object Panel1: TPanel

Left = 8

Top = 8

Width = 513

Height = 313

BevelInner = bvRaised

BevelOuter = bvLowered

TabOrder = 0

object ProgramIcon: TImage

Left = 8

Top = 8

Width = 241

Height = 233

Picture.Data = {}

Stretch = True

IsControl = True

end

object ProductName: TLabel

Left = 264

Top = 16

Width = 226

Height = 16

Caption = 'PROYECTO FIN DE CARRERA 1'

Font.Color = clNavy

Font.Height = -13

Font.Name = 'MS LineDraw'

Font.Style = [fsBold]

ParentFont = False

IsControl = True

end

object Version: TLabel

Left = 264

Top = 64

Width = 99

Height = 13

Caption = 'COMPONENTES:'

Font.Color = clNavy

Font.Height = -12

Font.Name = 'MS Sans Serif'

Font.Style = [fsBold]

ParentFont = False

IsControl = True

end

object Copyright: TLabel

Left = 288

Top = 160

Width = 169

Height = 22

Caption = 'Rubén Andrés Calvo'

Font.Color = clPurple

Font.Height = -19

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

IsControl = True

end

object Comments: TLabel

Left = 288

Top = 192

Width = 185

Height = 25

Caption = 'Miguel López Gómez'

Font.Color = clPurple

Font.Height = -19

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

WordWrap = True

IsControl = True

end

object Label1: TLabel

Left = 288

Top = 96

Width = 204

Height = 22

Caption = 'Pepa Deogracia Guirado'

Font.Color = clPurple

Font.Height = -19

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object Label2: TLabel

Left = 288

Top = 128

Width = 200

Height = 22

Caption = 'Paco Martínez González'

Font.Color = clPurple

Font.Height = -19

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object Label3: TLabel

Left = 288

Top = 224

Width = 174

Height = 22

Caption = 'Marcelo Raso Mateo'

Font.Color = clPurple

Font.Height = -19

Font.Name = 'Times New Roman'

Font.Style = [fsBold]

ParentFont = False

end

object Label4: TLabel

Left = 24

Top = 272

Width = 191

Height = 16

Caption = 'Copyright 1996'

Font.Color = clGray

Font.Height = -13

Font.Name = 'Wide Latin'

Font.Style = []

ParentFont = False

end

end

object OKButton: TBitBtn

Left = 215

Top = 330

Width = 77

Height = 27

Font.Color = clBlack

Font.Height = -12

Font.Name = 'MS Sans Serif'

Font.Style = [fsBold]

ParentFont = False

TabOrder = 1

OnClick = OKButtonClick

Kind = bkOK

Margin = 2

Spacing = -1

IsControl = True

end

end

NOTA:

La propiedad Glyph no se ha incluido en el listado de propiedades y eventeos en su totalidad, por contener caracteres ASCII que carecen de información, además de ocupar un tamaño excesivo.




Descargar
Enviado por:Miguel Lopez Y Otros
Idioma: castellano
País: España

Te va a interesar