diff --git a/TESTS/ut__foxbin2prg.prg b/TESTS/ut__foxbin2prg.prg index 7e069c4..979ed91 100644 --- a/TESTS/ut__foxbin2prg.prg +++ b/TESTS/ut__foxbin2prg.prg @@ -1272,6 +1272,120 @@ DEFINE CLASS ut__foxbin2prg AS FxuTestCase OF FxuTestCase.prg ENDFUNC + ******************************************************************************************************************************************* + FUNCTION Deberia_GenerarUnArchivo_SC2_DesdeUnBinarioQueContieneNullsEnElCodigo_SinLosNulls + LOCAL lnCodError, lnCodError_Esperado ; + , lc_File, lc_OutputFile, lc_OutputFileTx2, lc_OutputFileBak, lcExt2, lcFileName, lnNulls, lnNulls_Esperados ; + , lcParent, lcClass, lcObjName, loReg_Esperado ; + , loCtl AS f_optiongroup OF "TESTS\DATOS_READONLY\LIB_CONTROLES.VCX" ; + , loCnv AS c_foxbin2prg OF "FOXBIN2PRG.PRG" ; + , loEx AS EXCEPTION + #IF .F. + PUBLIC oFXU_LIB AS CL_FXU_CONFIG OF 'TESTS\fxu_lib_objetos_y_funciones_de_soporte.PRG' + #ENDIF + + TRY + loEx = NULL + loCnv = NEWOBJECT("c_foxbin2prg", "FOXBIN2PRG.PRG") + loCnv.EvaluarConfiguracion( '', '', '1', '1', '1', '4', '1', '0' ) + *loCnv.l_DropNullCharsFromCode = .T. + *loCnv.l_Test = .T. + + + *-- DATOS DE ENTRADA + STORE 0 TO lnCodError, lnCodError_Esperado, lnNulls, lnNulls_Esperados + lcFileName = 'f_nullchars_incode.scx' + lnNulls_Esperados = 0 + + *-- Copio la librería en DATOS_TEST + lc_File = UPPER(lcFileName) + lcExt2 = loCnv.Get_Ext2FromExt( JUSTEXT( lc_File ) ) + lc_OutputFile = FORCEPATH( lc_File, oFXU_LIB.cPathDatosTest ) + lc_OutputFileTx2 = FORCEEXT( FORCEPATH( lc_File, oFXU_LIB.cPathDatosTest ), lcExt2 ) + lc_OutputFileBak = lc_OutputFileTx2 + '.bak' + + oFXU_LIB.copiarArchivosParaTest( FORCEEXT( lc_File, LEFT( JUSTEXT(lc_File),2 ) + '?' ) ) + COPY FILE (lc_OutputFileTx2) TO (lc_OutputFileBak) + + *-- Genero TX2 + loCnv.Ejecutar( lc_OutputFile, .F., .F., .F., '1', '0', '1', '', '', .T., '', SYS(5)+CURDIR() ) + lnNulls = OCCURS( CHR(0), FILETOSTR( lc_OutputFileTx2 ) ) + + *-- Comparo resultados + THIS.messageout( "Se comprueba si el archivo texto generado contiene NULLs" ) + THIS.messageout( "NULLs esperados: " + TRANSFORM(lnNulls_Esperados) ) + THIS.messageout( "NULLs encontrados: " + TRANSFORM(lnNulls) ) + THIS.assertequals( lnNulls_Esperados, lnNulls, "COMPROBACIÓN THE NULLS" ) + + + CATCH TO loEx + THIS.Evaluate_results( loEx, lnCodError_Esperado, lc_OutputFile, lcParent, lcClass, lcObjName, loReg_Esperado ) + + FINALLY + STORE NULL TO loCnv, loCtl + RELEASE loCnv, loCtl + ENDTRY + + ENDFUNC + + + ******************************************************************************************************************************************* + FUNCTION Deberia_GenerarUnArchivo_SC2_DesdeUnBinarioQueContieneNullsEnElCodigo_ConLosNulls + LOCAL lnCodError, lnCodError_Esperado ; + , lc_File, lc_OutputFile, lc_OutputFileTx2, lc_OutputFileBak, lcExt2, lcFileName, lnNulls, lnNulls_Esperados ; + , lcParent, lcClass, lcObjName, loReg_Esperado ; + , loCtl AS f_optiongroup OF "TESTS\DATOS_READONLY\LIB_CONTROLES.VCX" ; + , loCnv AS c_foxbin2prg OF "FOXBIN2PRG.PRG" ; + , loEx AS EXCEPTION + #IF .F. + PUBLIC oFXU_LIB AS CL_FXU_CONFIG OF 'TESTS\fxu_lib_objetos_y_funciones_de_soporte.PRG' + #ENDIF + + TRY + loEx = NULL + loCnv = NEWOBJECT("c_foxbin2prg", "FOXBIN2PRG.PRG") + loCnv.EvaluarConfiguracion( '', '', '1', '1', '1', '4', '1', '0' ) + loCnv.l_DropNullCharsFromCode = .F. + *loCnv.l_Test = .T. + + + *-- DATOS DE ENTRADA + STORE 0 TO lnCodError, lnCodError_Esperado, lnNulls, lnNulls_Esperados + lcFileName = 'f_nullchars_incode.scx' + lnNulls_Esperados = 2 + + *-- Copio la librería en DATOS_TEST + lc_File = UPPER(lcFileName) + lcExt2 = loCnv.Get_Ext2FromExt( JUSTEXT( lc_File ) ) + lc_OutputFile = FORCEPATH( lc_File, oFXU_LIB.cPathDatosTest ) + lc_OutputFileTx2 = FORCEEXT( FORCEPATH( lc_File, oFXU_LIB.cPathDatosTest ), lcExt2 ) + lc_OutputFileBak = lc_OutputFileTx2 + '.bak' + + oFXU_LIB.copiarArchivosParaTest( FORCEEXT( lc_File, LEFT( JUSTEXT(lc_File),2 ) + '?' ) ) + COPY FILE (lc_OutputFileTx2) TO (lc_OutputFileBak) + + *-- Genero TX2 + loCnv.Ejecutar( lc_OutputFile, .F., .F., .F., '1', '0', '1', '', '', .T., '', SYS(5)+CURDIR() ) + lnNulls = OCCURS( CHR(0), FILETOSTR( lc_OutputFileTx2 ) ) + + *-- Comparo resultados + THIS.messageout( "Se comprueba si el archivo texto generado contiene NULLs" ) + THIS.messageout( "NULLs esperados: " + TRANSFORM(lnNulls_Esperados) ) + THIS.messageout( "NULLs encontrados: " + TRANSFORM(lnNulls) ) + THIS.assertequals( lnNulls_Esperados, lnNulls, "COMPROBACIÓN THE NULLS" ) + + + CATCH TO loEx + THIS.Evaluate_results( loEx, lnCodError_Esperado, lc_OutputFile, lcParent, lcClass, lcObjName, loReg_Esperado ) + + FINALLY + STORE NULL TO loCnv, loCtl + RELEASE loCnv, loCtl + ENDTRY + + ENDFUNC + + ******************************************************************************************************************************************* FUNCTION Evaluate_TX2_Output_Test LPARAMETERS tcFileName diff --git a/foxbin2prg.prg b/foxbin2prg.prg index a9754df..7d7cffb 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -90,6 +90,7 @@ * 14/06/2014 FDBOZZO v1.19.24 Arreglo bug vcx/scx: Un campo de tabla llamado "text" que comienza la línea puede confundirse con la estructura TEXT/ENDTEXT y reconocer mal el resto del código * 16/06/2014 FDBOZZO v1.19.25 Mejora: Agregado soporte de configuraciones (CFG) por directorio que, si existen, se usan en lugar del principal (Mario Peschke) * 17/06/2014 FDBOZZO v1.19.25 Mejora: Si durante la generación de binarios o de textos se producen errores, mostrar un mensaje avisando de ello (Pedro Gutiérrez M.) +* 06/07/2014 FDBOZZO v1.19.26 Mejora: Cuando se convierten binarios a texto, los CHR(0) pasan también, pudiendo provocar falsa detección como binario. Se agrega opción para quitar los NULLs. (Matt Slay) * * *--------------------------------------------------------------------------------------------------- @@ -124,6 +125,7 @@ * 13/06/2014 Mario Peschke REPORTE BUG vcx/scx v1.19.23: Los campos de tabla con nombre "text" a veces provocan corrupción del binario generado (Arreglado en v1.19.24) * 16/06/2014 Mario Peschke MEJORA v1.19.24: Agregado soporte de configuraciones (CFG) por directorio que, si existen, se usan en lugar del CFG principal (Agregado en v1.19.25) * 17/06/2014 Pedro Gutiérrez M. MEJORA v1.19.24: Si durante la generación de binarios o de textos se producen errores, mostrar un mensaje avisando de ello (Agregado en v1.19.25) +* 02/07/2014 Matt Slay MEJORA v1.19.25: Se filtran algunos CHR(0) de los binarios al tx2, provocando que a veces no sea reconocido como texto. Deberían poderse quitar los NULLs (Arreglado en v1.19.26) * * *--------------------------------------------------------------------------------------------------- @@ -277,6 +279,7 @@ LPARAMETERS tc_InputFile, tcType, tcTextName, tlGenText, tcDontShowErrors, tcDeb #DEFINE C_TAB CHR(9) #DEFINE C_CR CHR(13) #DEFINE C_LF CHR(10) +#DEFINE C_NULL_CHAR CHR(0) #DEFINE CR_LF C_CR + C_LF #DEFINE C_MPROPHEADER REPLICATE( CHR(1), 517 ) *-- Fin / End @@ -444,6 +447,7 @@ DEFINE CLASS c_foxbin2prg AS CUSTOM + [] ; + [] ; + [] ; + + [] ; + [] ; + [] ; + [] ; @@ -514,6 +518,7 @@ DEFINE CLASS c_foxbin2prg AS CUSTOM l_ShowErrors = .T. l_ShowProgress = .T. l_AllowMultiConfig = .T. + l_DropNullCharsFromCode = .T. l_Recompile = .T. l_NoTimestamps = .T. l_ClearUniqueID = .T. @@ -1145,21 +1150,28 @@ DEFINE CLASS c_foxbin2prg AS CUSTOM lcValue = ALLTRIM( SUBSTR( laConfig(I), 15 ) ) IF NOT INLIST( TRANSFORM(tcClearUniqueID), '0', '1' ) AND INLIST( lcValue, '0', '1' ) THEN tcClearUniqueID = lcValue - .writeLog( JUSTFNAME(lcConfigFile) + ' > ClearUniqueID: ' + TRANSFORM(ALLTRIM( SUBSTR( laConfig(I), 15 )) ) ) + .writeLog( JUSTFNAME(lcConfigFile) + ' > ClearUniqueID: ' + TRANSFORM(lcValue) ) ENDIF CASE LEFT( laConfig(I), 20 ) == LOWER('OptimizeByFilestamp:') lcValue = ALLTRIM( SUBSTR( laConfig(I), 21 ) ) IF NOT INLIST( TRANSFORM(tcOptimizeByFilestamp), '0', '1' ) AND INLIST( lcValue, '0', '1' ) THEN tcOptimizeByFilestamp = lcValue - .writeLog( JUSTFNAME(lcConfigFile) + ' > OptimizeByFilestamp: ' + TRANSFORM(ALLTRIM( SUBSTR( laConfig(I), 21 )) ) ) + .writeLog( JUSTFNAME(lcConfigFile) + ' > OptimizeByFilestamp: ' + TRANSFORM(lcValue) ) ENDIF CASE LEFT( laConfig(I), 17 ) == LOWER('AllowMultiConfig:') lcValue = ALLTRIM( SUBSTR( laConfig(I), 18 ) ) IF INLIST( lcValue, '0', '1' ) THEN .l_AllowMultiConfig = ( TRANSFORM(lcValue) == '1' ) - .writeLog( JUSTFNAME(lcConfigFile) + ' > AllowMultiConfig: ' + TRANSFORM(ALLTRIM( SUBSTR( laConfig(I), 18 )) ) ) + .writeLog( JUSTFNAME(lcConfigFile) + ' > AllowMultiConfig: ' + TRANSFORM(lcValue) ) + ENDIF + + CASE LEFT( laConfig(I), 22 ) == LOWER('DropNullCharsFromCode:') + lcValue = ALLTRIM( SUBSTR( laConfig(I), 23 ) ) + IF INLIST( lcValue, '0', '1' ) THEN + .l_DropNullCharsFromCode = ( TRANSFORM(lcValue) == '1' ) + .writeLog( JUSTFNAME(lcConfigFile) + ' > DropNullCharsFromCode: ' + TRANSFORM(lcValue) ) ENDIF CASE LEFT( laConfig(I), 23 ) == LOWER('PJX_Conversion_Support:') @@ -1251,14 +1263,15 @@ DEFINE CLASS c_foxbin2prg AS CUSTOM ENDIF .writeLog( '---' ) - .writeLog( '> l_ShowProgress: ' + TRANSFORM(.l_ShowProgress) ) - .writeLog( '> l_ShowErrors: ' + TRANSFORM(.l_ShowErrors) ) - .writeLog( '> l_Recompile: ' + TRANSFORM(.l_Recompile) + ' (' + EVL(tcRecompile,'') + ')' ) - .writeLog( '> l_NoTimestamps: ' + TRANSFORM(.l_NoTimestamps) ) - .writeLog( '> l_ClearUniqueID: ' + TRANSFORM(.l_ClearUniqueID) ) - .writeLog( '> l_Debug: ' + TRANSFORM(.l_Debug) ) - .writeLog( '> n_ExtraBackupLevels: ' + TRANSFORM(.n_ExtraBackupLevels) ) - .writeLog( '> l_OptimizeByFilestamp: ' + TRANSFORM(.l_OptimizeByFilestamp) ) + .writeLog( '> l_ShowProgress: ' + TRANSFORM(.l_ShowProgress) ) + .writeLog( '> l_ShowErrors: ' + TRANSFORM(.l_ShowErrors) ) + .writeLog( '> l_Recompile: ' + TRANSFORM(.l_Recompile) + ' (' + EVL(tcRecompile,'') + ')' ) + .writeLog( '> l_NoTimestamps: ' + TRANSFORM(.l_NoTimestamps) ) + .writeLog( '> l_ClearUniqueID: ' + TRANSFORM(.l_ClearUniqueID) ) + .writeLog( '> l_Debug: ' + TRANSFORM(.l_Debug) ) + .writeLog( '> n_ExtraBackupLevels: ' + TRANSFORM(.n_ExtraBackupLevels) ) + .writeLog( '> l_OptimizeByFilestamp: ' + TRANSFORM(.l_OptimizeByFilestamp) ) + .writeLog( '> l_DropNullCharsFromCode: ' + TRANSFORM(.l_DropNullCharsFromCode) ) lo_CFG = NULL RELEASE lo_CFG @@ -8119,16 +8132,20 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ******************************************************************************************************************* PROCEDURE get_ADD_OBJECT_METHODS LPARAMETERS toRegObj, toRegClass, tcMethods, taMethods, taCode, tnMethodCount ; - , taPropsAndComments, tnPropsAndComments_Count, taProtected, tnProtected_Count + , taPropsAndComments, tnPropsAndComments_Count, taProtected, tnProtected_Count ; + , toFoxBin2Prg EXTERNAL ARRAY taPropsAndComments, taProtected + #IF .F. + LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' + #ENDIF TRY LOCAL lcMethodName WITH THIS AS c_conversor_bin_a_prg OF 'FOXBIN2PRG.PRG' .SortMethod( toRegObj.METHODS, @taMethods, @taCode, '', @tnMethodCount ; - , @taPropsAndComments, tnPropsAndComments_Count, @taProtected, tnProtected_Count ) + , @taPropsAndComments, tnPropsAndComments_Count, @taProtected, tnProtected_Count, @toFoxBin2Prg ) *-- Ubico los métodos protegidos y les cambio la definición. *-- Los métodos se deben generar con la ruta completa, porque si no es imposible saber a que objeto corresponden, @@ -8510,11 +8527,14 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ******************************************************************************************************************* PROCEDURE SortMethod LPARAMETERS tcMethod, taMethods, taCode, tcSorted, tnMethodCount, taPropsAndComments, tnPropsAndComments_Count ; - , taProtected, tnProtected_Count + , taProtected, tnProtected_Count, toFoxBin2Prg *-- 29/10/2013 Fernando D. Bozzo *-- Se tiene en cuenta la posibilidad de que haya un PROC/ENDPROC dentro de un TEXT/ENDTEXT *-- cuando es usado en un generador de código o similar. EXTERNAL ARRAY taMethods, taCode, taPropsAndComments, taProtected + #IF .F. + LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' + #ENDIF *-- ESTRUCTURA DE LOS ARRAYS CREADOS: *-- taMethods[1,3] @@ -8538,6 +8558,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base DIMENSION laLine(1), taMethods(1,3) STORE '' TO laLine, taMethods, taCode STORE 0 TO tnMethodCount, lnTextNodes + lnLineCount = ALINES(laLine, m.tcMethod) && NO aplicar nungún formato ni limpieza, que es el CÓDIGO FUENTE *-- Delete beginning empty lines before first "PROCEDURE", that is the first not empty line. @@ -8569,6 +8590,10 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base *-- Analyze and count line methods, get method names and consolidate block code FOR I = 1 TO lnLineCount + IF toFoxBin2Prg.l_DropNullCharsFromCode + laLine(I) = CHRTRAN( laLine(I), C_NULL_CHAR, '' ) + ENDIF + lnLine_Len = LEN( laLine(I) ) DO CASE @@ -8777,7 +8802,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ******************************************************************************************************************* PROCEDURE write_ALL_OBJECT_METHODS - LPARAMETERS tcMethods, taPropsAndComments, tnPropsAndComments_Count, taProtected, tnProtected_Count + LPARAMETERS tcMethods, taPropsAndComments, tnPropsAndComments_Count, taProtected, tnProtected_Count, toFoxBin2Prg *-- Finalmente, todos los métodos los ordeno y escribo juntos LOCAL laMethods(1), laCode(1), lnMethodCount, I, lcMethods @@ -8788,7 +8813,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base WITH THIS AS c_conversor_bin_a_prg OF 'FOXBIN2PRG.PRG' .SortMethod( @tcMethods, @laMethods, @laCode, '', @lnMethodCount ; - , @taPropsAndComments, tnPropsAndComments_Count, @taProtected, tnProtected_Count ) + , @taPropsAndComments, tnPropsAndComments_Count, @taProtected, tnProtected_Count, @toFoxBin2Prg ) FOR I = 1 TO lnMethodCount *-- Genero los métodos indentados @@ -9850,7 +9875,7 @@ DEFINE CLASS c_conversor_vcx_a_prg AS c_conversor_bin_a_prg DIMENSION laMethods(1,3) laMethods = '' .SortMethod( loRegClass.METHODS, @laMethods, @laCode, '', @lnMethodCount ; - , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count, @toFoxBin2Prg ) .write_CLASS_METHODS( @lnMethodCount, @laMethods, @laCode, @laProtected, @laPropsAndComments ) @@ -9878,10 +9903,11 @@ DEFINE CLASS c_conversor_vcx_a_prg AS c_conversor_bin_a_prg ENDIF .get_ADD_OBJECT_METHODS( @loRegObj, @loRegClass, @lcMethods, @laMethods, @laCode, @lnMethodCount ; - , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count, @toFoxBin2Prg ) ENDSCAN - .write_ALL_OBJECT_METHODS( @lcMethods, @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + .write_ALL_OBJECT_METHODS( @lcMethods, @laPropsAndComments, lnPropsAndComments_Count, @laProtected ; + , lnProtected_Count, @toFoxBin2Prg ) GOTO RECORD (lnRecno) ENDSCAN @@ -10087,7 +10113,7 @@ DEFINE CLASS c_conversor_scx_a_prg AS c_conversor_bin_a_prg DIMENSION laMethods(1,3) laMethods = '' .SortMethod( loRegClass.METHODS, @laMethods, @laCode, '', @lnMethodCount ; - , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count, @toFoxBin2Prg ) .write_CLASS_METHODS( @lnMethodCount, @laMethods, @laCode, @laProtected, @laPropsAndComments ) @@ -10117,10 +10143,11 @@ DEFINE CLASS c_conversor_scx_a_prg AS c_conversor_bin_a_prg ENDIF .get_ADD_OBJECT_METHODS( @loRegObj, @loRegClass, @lcMethods, @laMethods, @laCode, @lnMethodCount ; - , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + , @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count, @toFoxBin2Prg ) ENDSCAN - .write_ALL_OBJECT_METHODS( @lcMethods, @laPropsAndComments, lnPropsAndComments_Count, @laProtected, lnProtected_Count ) + .write_ALL_OBJECT_METHODS( @lcMethods, @laPropsAndComments, lnPropsAndComments_Count, @laProtected ; + , lnProtected_Count, @toFoxBin2Prg ) GOTO RECORD (lnRecno) ENDSCAN