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.
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 |