viernes, enero 10, 2014

FoxBin2Prg, el sucesor mejorado del scctext

[18/04/2015: Actualizado hasta la versión v1.19.42]

Por: Fernando D. Bozzo

Creo que sería un buen comienzo empezar este blog con una nota sobre FoxBin2Prg, un proyecto Open Source actualmente hospedado en CodePlex dentro del proyecto VFPX y que comencé a fines de noviembre de 2013, por la necesidad de no solo generar vistas texto de los binarios de Visual FoxPro 9 como ya hace el scctext, sino de mejorarlo a tal punto que para el Desarrollador sea como el código mismo, y que además permita ser usado para hacer Diff, Merge y de paso Backup del código.


Ventajas:

  • Genera archivos estilo "PRG" (no compilables), para comparación visual
  • Permite hacer cambios en la versión TEXTO tan fácil como modificar PRG
  • Todo el código de programa está en un solo EXE, para simplificar su copia y mantenimiento
  • Con las versiones TEXTO puedes regenerar los binarios originales, así que es útil como backup
  • Las extensiones usadas son configurables si se crea el archivo FOXBIN2PRG.CFG
  • Los métodos y propiedades de la versión TEXTO son ordenados alfabéticamente para acilitar su comparación
  • Tiene compatibilidad con el SccText(X) a nivel de parámetros, así puede ser usado como su sustituto con SourceSafe

Actualmente se soporta la conversión de archivos PJX,SCX,VCX,FRX,LBX,DBC,DBF y MNX, para los que genera versiones Texto con extensión PJ2,SC2,VC2,FR2,LB2,DC2,DB2 y MN2 que pueden ser reconfiguradas para compatibilizar con SourceSafe.

Ejemplo de archivo de configuración FOXBIN2PRG.CFG si necesita cambiar extensiones
extension: SC2=SCA
extension: VC2=VCA
extension: PJ2=PJA
...


Usando la versión "EXE": (útil para ser llamado por programas de 3ros)
FOXBIN2PRG.EXE "<path>\file.scx" ==> Genera la versión TEXT con extensión sc2
FOXBIN2PRG.EXE "<path>\file.sc2" ==> Regenera el binario con extensión scx


Usando la versión "PRG":
DO FOXBIN2PRG.PRG WITH "<path>\file.scx" ==> Genera la versión TEXT con extensión sc2
DO FOXBIN2PRG.PRG WITH "<path>\file.sc2" ==> Regenera el binario con extensión scx


Usando la versión "Objeto":
LOCAL loCnv AS c_foxbin2prg OF "FOXBIN2PRG.PRG"
loCnv = NEWOBJECT("c_foxbin2prg", "FOXBIN2PRG.PRG")
loCnv.Ejecutar( <params> )


El código generado


Para cada tipo de binario Fox hay una vista personalizada, pensada para sacarle el mayor provecho a cada uno. Por ejemplo, para los DBFs y DBCs (tablas y bases de datos nativas) se generan vistas estilo XML



y para el resto se genera código de programa y seudocódigo, que no compila, pero es tan fácil de leer como el código normal, con la ventaja de que en todos los casos se pueden hacer modificaciones que luego se trasladarán al binario regenerado.


Estructura de clases



Todo el código está en un único programa dividido en varias clases:
  • Una clase principal llamada c_foxbin2prg, de tipo session, que es la que recibe los parámetros
  • Una para el indicador de avance cuando se procesan varios archivos llamada frm_avance
  • Una para cada tipo de conversión específica, que es cargada por la clase principal y que están basadas o en c_conversor_bin_a_prg o en c_conversor_prg_a_bin
  • Unas cuántas de soporte basadas en cl_col_base y cl_cus_base para poder completar los datos de cada unidad o subunidad de información.
Por ejemplo, el conversor de DBF a texto, además de la clase conversora principal, utiliza:
  • Una clase para la información del DBF (cl_dbf_table)
  • Una clase para la información de campos (cl_dbf_field)
  • Una clase para la información de índices (cl_dbf_index)
  • 2 clases de colección (cl_dbf_fields y cl_dbf_indexes)

Funcionamiento


Cuando se pide convertir un VCX a VC2, ocurre lo siguiente:
  • La clase c_foxbin2prg recibe los parámetros de entrada en el método execute(), siendo el primero de ellos el nombre y ruta del archivo a convertir. En este paso también se hacen algunas validaciones
  • A continuación se llama al método convert(), que selecciona el conversor a utilizar de acuerdo al tipo de archivo pasado, en este caso es c_conversor_vcx_a_prg, se instancia la clase, se le pasan los datos necesarios y se invoca a su método Convertir()
  • El método Convertir() abre la librería VCX como una tabla en modo SHARED NOUPDATE con alias TABLABIN y a partir de allí se recorren todos los registros, invocando a métodos intermedios específicos para tipo de dato del VCX que irán analizando los datos del registro e irán generando cada uno su parte de información de texto, como la definición de la clase, el ordenamiento alfabético y definición de las propiedades al inicio, el ordenamiento alfabético y definición de los métodos, etc.
En los distintos métodos se va obteniendo, formateando y escribiendo trozos de código, y todo el código/texto generado se va guardando en una variable pública llamada C_FB2PRG_CODE, que al finalizar se escribe en el archivo VC2.

Cuando se pide regenerar un binario desde el VC2, ocurre lo siguiente:
  • Se realizan los dos primeros pasos del proceso antes descripto, pero instanciando la clase c_conversor_prg_a_vcx
  • En el método convert() se invoca a identifyExclusionBlocks() que analiza el código del VC2 buscando los #IF .F. y los TEXT..ENDTEXT, para saber que dentro de esos bloques no debe analizar nada
  • Se llama al método identifyCodeBlocks() que a su vez llama a los distintos métodos analyze que se encargan de analizar secciones específicas de código como los ADD_OBJECT, DEFINED_PAM (las propiedades, arrays y métodos definidos por el usuario), HIDDEN, INCLUDE, METADATA y demás secciones del código, cada una de las cuáles realiza un parseo específico para completar las propiedades del objeto de datos que le corresponde
  • Finalmente se invoca al método writeBinaryFile() que recorre toda la información recolectada antes y escribe el binario

Control de errores


El control de errores se basa en Try/Catch, donde cada método controlado se encarga de 2 cosas:
  1. Tratar el error, generar la información de Log necesaria y limpiar el entorno modificado (garbage collect)
  2. Relanzar el error hacia el nivel superior, que llegará finalmente hasta la capa más externa que es la clase principal, donde dependiendo del modo de llamada de foxbin2prg (EXE, PRG u Objeto) devolverá un tipo de información u otro.
Por ejemplo, en modo EXE se devuelve un código de error 1 como resultado de ejecución, valor que puede ser leido por un BAT o un script VBS con ERRORLEVEL para tomar alguna decisión o realizar alguna acción.


Parámetros


Finalmente, los distintos parámetros de entrada permiten configurar cómo se desea que funcione y actúe ante ciertas situaciones:
  • tc_InputFile: Nombre completo del archivo de entrada a convertir
  • tcType_na: Mantenido por compatibilidad con SourceSafe. Por ahora sin uso.
  • tcTextName_na: Mantenido por compatibilidad con SourceSafe. Por ahora sin uso.
  • tcGenText_na: Mantenido por compatibilidad con SourceSafe. Por ahora sin uso.
  • tcType_na: Mantenido por compatibilidad con SourceSafe. Por ahora sin uso.
  • tcDontShowErrors: Un "1" indica que no se quiere mostrar errores si llegaran a ocurrir. Esto es útil en un procesamiento batch, donde no se quiere que los errores interrumpan el proceso ya que se loguean a un archivo .LOG o .ERR que se puede revisar luego
  • tcDebug: Un "1" indica habilitar el modo de depuración, que solo se usa en modo desarrollo cuando se ejecuta el PRG y que permite que se abra una ventana de DEBUG para depurar el error en el mismo sitio donde ocurrió, inspeccionar las variables y ver lo que sea necesario. En tiempo de ejecución (EXE) solo habilita el modo de generación de LOG, que también se puede habilitar creando un archivo FoxBin2Prg.log junto al EXE
  • tcDontShowProgress: Un "1" indica que no se quiere mostrar una barra de progreso cuando se procesa un lote de archivos. Para un único archivo no se muestra esta barra de progreso.
  • tcOriginalFileName: Este parámetro fue uno de los últimos agregados, y está especialmente pensado para trabajar con herramientas SCM, donde la mayoría de las veces se generan los archivos en ubicaciones temporales (c:\temp) y con nombres temporales (fffds-44343-ffds5-fsdfe.vcx). Gracias a este parámetro el conversor sabe el nombre original del archivo y lo puede utilizar en sitios donde queda registrado, como la cabecera de los TX2 y algunas propiedades importantes. Por ejemplo el PJ2 tiene unas cuántas referencias a su nombre en distintas propiedades, que sin este parámetros tendrían un nombre temporal que impediría regenerar el binario con el nombre correcto.
  • tcRecompile: Indica si se debe recompilar, o no. Por defecto, desde la v1.19.4 ya no recompila, salvo que se indique '1' para recompilar desde el directorio del binario (como hacía antes) o un 'Path' para recompilar desde el mismo. Lo mejor es undicar el Path del proyecto PJX, ya que siempre que se usa un proyecto, los componentes que se agreguen se compilan desde esa ubicación relativa, y todos los arhivos se vinculan de forma relativa, como los Include (..\include\foxpro.h), que se se compilaran desde otra ubicación darían errores de compilación, que es lo que ocurría con el funcionamiento anterior de FoxBin2Prg cuando se referenciaban archivos externos de forma relativa.

 Link de descarga:
https://vfpx.codeplex.com/releases/view/116407

Conclusión

Omití varios detalles para no hacer el post muy largo, pero quería explicar un poco por encima el funcionamiento de este programa y su estructura. Probablemente en próximos posts hable sobre algunas particularidades más específicas y de algunas técnicas de programación utilizadas.

Hasta la próxima!


Artículos relacionados:
FoxBin2Prg: Detalle de vistas, datos de uso, configuraciones y más

1 comentario:

  1. Excelente, el trabajo que vienes realizando con la herramienta foxbin2prg, y en realidad si nos interesaría conocer más sobre las tecnicas de programación empleadas.

    ResponderEliminar