diff --git a/CONFIG/config.fpw b/CONFIG/config.fpw index cc23e10..ef3f93b 100644 --- a/CONFIG/config.fpw +++ b/CONFIG/config.fpw @@ -1,10 +1,2 @@ -ALLOWEXTERNAL=OFF -RESOURCE=OFF SCREEN=OFF -_BLOWSER="" -_BUILDER="" -_REPORTBUILDER="" -_REPORTOUTPUT="" -_REPORTPREVIEW="" -_TASKPANE="" -_TOOLBOX="" +RESOURCE=OFF \ No newline at end of file diff --git a/FoxBin2PRGVersionFile.txt b/FoxBin2PRGVersionFile.txt index 8ffa60f..8c920f7 100644 --- a/FoxBin2PRGVersionFile.txt +++ b/FoxBin2PRGVersionFile.txt @@ -3,7 +3,7 @@ Lparameters toUpdateInfo Local lcNote With toUpdateInfo .VersionNumber = 'v1.19.46' - .VersionDate = Date(2015,07,28) + .VersionDate = Date(2015,09,01) .SourceFileUrl = 'http://vfpxrepository.com/dl/thorupdate/Projects/FoxBin2Prg/FoxBin2Prg.Zip' .Link = 'http://vfpx.codeplex.com/wikipage?title=FoxBin2PRG' @@ -17,12 +17,13 @@ Demo video using FoxBin2Prg with PlasticSCM: http://youtu.be/sE4wQ50Itqg Change History ------------------------------------------------------------- -2015/07/28 v1.19.46 +2015/09/01 v1.19.46 - Bug Fix: set_UserValue() method causes error when trying to get information about another error and the VFP binary table can not be opened (ie, because corrupted memo) - Feature: Added internal support for querying directory cfg information, with a new optional parameter, for API methods that require it (ie: get_Ext2FromExt, hasSupport*) - Feature: Convert FUNCTION to PROCEDURE for maintaining compatibility with the way that VFP save methods on binaries - New fb2p_diff.exe: Allow a quick Diff of VFP9 binaries, for those that don't need converting to text manually - Bug Fix: When processing a directory or a project with all the files, sometimes an "Alias already in use" error may occur (Dave Crozier) +- Bug Fix mnx: When menu options contains '&&' in their texts, menu binary is corrupted when regenerated (Walter Nichols) 2015/06/21 v1.19.45 diff --git a/TESTS/DATOS_READONLY/menu1.MNT b/TESTS/DATOS_READONLY/menu1.MNT index 0e068b5..d36224d 100644 Binary files a/TESTS/DATOS_READONLY/menu1.MNT and b/TESTS/DATOS_READONLY/menu1.MNT differ diff --git a/TESTS/DATOS_READONLY/menu1.mn2 b/TESTS/DATOS_READONLY/menu1.mn2 index 14c9144..106888d 100644 --- a/TESTS/DATOS_READONLY/menu1.mn2 +++ b/TESTS/DATOS_READONLY/menu1.mn2 @@ -14,28 +14,28 @@ * DEFINE MENU _MSYSMENU BAR -DEFINE PAD _43302YWGE OF _MSYSMENU PROMPT "Opción A con submenú" COLOR SCHEME 3 ; +DEFINE PAD _000000001 OF _MSYSMENU PROMPT "Opción A && submenú" COLOR SCHEME 3 ; NEGOTIATE NONE, LEFT ; KEY DEL, "Pulsar " ; SKIP FOR SKIP_FOR() ; - MESSAGE "Mensaje para Opción A con submenú" && Comentario + MESSAGE "Mensaje para Opción A con submenú" && Comentario's Opción A -ON PAD _43302YWGE OF _MSYSMENU ACTIVATE POPUP OpciónA_CS +ON PAD _000000001 OF _MSYSMENU ACTIVATE POPUP OpciónAsub *---------------------------------- - DEFINE POPUP OpciónA_CS MARGIN RELATIVE SHADOW COLOR SCHEME 4 - DEFINE BAR 1 OF OpciónA_CS PROMPT "Opción A-1" ; - PICTURE "..\..\foxunit\fxuacknowledgements.bmp" - ON BAR 1 OF OpciónA_CS ACTIVATE POPUP OpciónA1 + DEFINE POPUP OpciónAsub MARGIN RELATIVE SHADOW COLOR SCHEME 4 + DEFINE BAR 1 OF OpciónAsub PROMPT "Opción A-&&-1" ; + PICTURE "..\..\foxunit\fxuacknowledgements.bmp" && Comentario Opción A-1 + ON BAR 1 OF OpciónAsub ACTIVATE POPUP OpciónA1 *---------------------------------- DEFINE POPUP OpciónA1 MARGIN RELATIVE SHADOW COLOR SCHEME 4 - DEFINE BAR Shortcut_Menu_Title OF OpciónA1 PROMPT "OpciónA-1-Sub" ; - PICTURE "..\..\foxunit\fxuacknowledgements.bmp" - ON SELECTION BAR Shortcut_Menu_Title OF OpciónA1 wait window "Ejecuta Comando o función para Opción A-1" + DEFINE BAR Shortcut_Menu_Title OF OpciónA1 PROMPT "OpciónA-1-&&-Sub" ; + PICTURE "..\..\foxunit\fxuacknowledgements.bmp" && Comentario Opción A-1-sub con && trampa :) + ON SELECTION BAR Shortcut_Menu_Title OF OpciónA1 wait window "Ejecuta Comando o función 'trampa' para Opción A-&&-1" - DEFINE BAR 2 OF OpciónA_CS PROMPT "Opción A-2" - ON BAR 2 OF OpciónA_CS ACTIVATE POPUP OpciónA2Su + DEFINE BAR 2 OF OpciónAsub PROMPT "Opción A-2" && Comentario Opción A-2 + ON BAR 2 OF OpciónAsub ACTIVATE POPUP OpciónA2Su *---------------------------------- DEFINE POPUP OpciónA2Su MARGIN RELATIVE SHADOW COLOR SCHEME 4 @@ -65,14 +65,14 @@ ON PAD _43302YWGE OF _MSYSMENU ACTIVATE POPUP Opci SKIP FOR NOT glEnabled_Opc_A_2_Sub_3 ; PICTRES _mfi_sysprint ; MESSAGE "Message para Opción A-2-Sub.3 (Tipo Bar#)" && Comentarios para Opción A-2-Sub.3 - ON SELECTION POPUP OpciónA_CS *-- PROCEDURE Le cambié el nombre! + ON SELECTION POPUP OpciónAsub *-- PROCEDURE Le cambié el nombre! DEFINE PAD opc_b OF _MSYSMENU PROMPT "Opción B con comando" COLOR SCHEME 3 ; KEY CTRL+B, "Pulse CTRL+B" ; SKIP FOR NOT glEnabled_Opc_B ; - MESSAGE "Mensaje para Opción B con Command" && Comentario de la Opción b + MESSAGE "Mensaje para Opción B con Command && con trampa's" && Comentario's de la Opción b -ON SELECTION PAD opc_b OF _MSYSMENU WAIT WINDOW "Opción B" +ON SELECTION PAD opc_b OF _MSYSMENU WAIT WINDOW "Opción B y ma's trampas" ON SELECTION POPUP ALL DO MenuBarProc ON SELECTION MENU _MSYSMENU DO SELECTION_MENU__MSYSMENU_FB2P diff --git a/TESTS/DATOS_READONLY/menu1.mnx b/TESTS/DATOS_READONLY/menu1.mnx index 5b374f1..7608ce7 100644 Binary files a/TESTS/DATOS_READONLY/menu1.mnx and b/TESTS/DATOS_READONLY/menu1.mnx differ diff --git a/TESTS/ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata.prg b/TESTS/ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata.prg index da07d6b..c1b831f 100644 --- a/TESTS/ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata.prg +++ b/TESTS/ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata.prg @@ -45,7 +45,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata AS ******************************************************************************************************************************************* FUNCTION Evaluate_results LPARAMETERS toEx AS EXCEPTION, tnCodError_Esperado ; - , tcLinea, tcComentario, tlRetorno, tcLinea_Esperada, tcComentario_Esperado, tlRetorno_Esperado + , tcLinea, tcComentario, tlRetorno, tcLinea_Esperada, tcComentario_Esperado, tlRetorno_Esperado, tcLineaOriginal #IF .F. PUBLIC oFXU_LIB AS CL_FXU_CONFIG OF 'TESTS\fxu_lib_objetos_y_funciones_de_soporte.PRG' @@ -64,12 +64,14 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata AS tcLinea_Esperada = oFXU_LIB.mejorarPresentacionCaracteresEspeciales( tcLinea_Esperada ) tcComentario = oFXU_LIB.mejorarPresentacionCaracteresEspeciales( tcComentario ) tcComentario_Esperado = oFXU_LIB.mejorarPresentacionCaracteresEspeciales( tcComentario_Esperado ) + tcLineaOriginal = oFXU_LIB.mejorarPresentacionCaracteresEspeciales( tcLineaOriginal ) *-- Visualización de valores + THIS.messageout( ' Línea original = [' + tcLineaOriginal + ']' ) THIS.messageout( ' Linea = [' + TRANSFORM(tcLinea) + ']' ) THIS.messageout( ' Comentario = [' + TRANSFORM(tcComentario) + ']' ) - THIS.messageout( ' tlRetorno = [' + TRANSFORM(tlRetorno) + ']' ) + THIS.messageout( ' OnlyCommentAndNoMetadata? = [' + TRANSFORM(tlRetorno) + ']' ) *-- Evaluación de valores @@ -99,20 +101,22 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata AS *-- DATOS DE ENTRADA STORE 0 TO lnCodError - lcComentario = ' ' + CHR(9) + CHR(9) + 'con algunos comentarios ' lcLinea = ' ' + CHR(9) + CHR(9) + ' esta es una linea de código ' + CHR(9) + ' ' + lcComentario = ' ' + CHR(9) + CHR(9) + 'con algunos comentarios ' lcLineaOriginal = lcLinea + '&' + '&' + lcComentario + lcLineaOriginal = LTRIM(lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente *-- DATOS ESPERADOS STORE 0 TO lnCodError_Esperado - lcLinea_Esperada = lcLinea + lcLinea_Esperada = ALLTRIM(lcLinea, 0, CHR(9), ' ' ) lcComentario_Esperado = LTRIM(lcComentario) llRetorno_Esperado = .F. + lcLinea = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente *-- TEST - llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLineaOriginal, @lcComentario ) + llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLinea, @lcComentario ) - THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado ) + THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado, @lcLineaOriginal ) ENDFUNC @@ -128,27 +132,29 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata AS *-- DATOS DE ENTRADA STORE 0 TO lnCodError + lcLinea = ' * esta es una linea de código ' && Empieza con "*<", por lo que es metadata la línea lcComentario = ' con algunos comentarios ' - lcLinea = ' * esta es una linea de código ' lcLineaOriginal = lcLinea + '&' + '&' + lcComentario - lcLineaOriginal = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) + lcLineaOriginal = LTRIM(lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente *-- DATOS ESPERADOS STORE 0 TO lnCodError_Esperado - lcLinea_Esperada = ALLTRIM( lcLinea, 0, CHR(9), ' ' ) - lcComentario_Esperado = lcLinea_Esperada + *lcLinea_Esperada = LTRIM(lcLineaOriginal, 0, CHR(9), ' ' ) &&ALLTRIM( lcLinea, 0, CHR(9), ' ' ) + lcLinea_Esperada = ALLTRIM(lcLinea, 0, CHR(9), ' ' ) + lcComentario_Esperado = lcLinea_Esperada && Se espera la línea, porque es todo comentario llRetorno_Esperado = .F. + lcLinea = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente *-- TEST - llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLineaOriginal, @lcComentario ) + llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLinea, @lcComentario ) - THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLineaOriginal, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado ) + THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado, @lcLineaOriginal ) ENDFUNC ******************************************************************************************************************************************* - FUNCTION Deberia_DevolverSeparados_LineaDeCodigo_y_Valor_y_Retornar_True + FUNCTION Deberia_DevolverLaLineaDeCodigoComoComentario_y_Retornar_True LOCAL lnCodError, lcMenError, lnCodError_Esperado ; , lcLinea, lcLineaOriginal, lcComentario, lcLinea_Esperada, lcComentario_Esperado, llRetorno, llRetorno_Esperado ; , loEx AS EXCEPTION @@ -158,21 +164,84 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__lineIsOnlyCommentAndNoMetadata AS *-- DATOS DE ENTRADA STORE 0 TO lnCodError + lcLinea = ' * esta es una linea de código ' && Empieza con "*", por lo que es solo comentario la línea lcComentario = ' con algunos comentarios ' - lcLinea = ' * esta es una linea de código ' lcLineaOriginal = lcLinea + '&' + '&' + lcComentario lcLineaOriginal = LTRIM(lcLineaOriginal, 0, CHR(9), ' ') *-- DATOS ESPERADOS STORE 0 TO lnCodError_Esperado - lcLinea_Esperada = lcLinea + lcLinea_Esperada = ALLTRIM(lcLinea, 0, CHR(9), ' ' ) lcComentario_Esperado = LTRIM(lcComentario) llRetorno_Esperado = .T. + lcLinea = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente *-- TEST - llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLineaOriginal, @lcComentario ) + llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLinea, @lcComentario ) - THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado ) + THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado, @lcLineaOriginal ) + + ENDFUNC + + + ******************************************************************************************************************************************* + FUNCTION Deberia_DevolverSeparados_LineaDeCodigoQueIncluye_DobleAmpersand_y_Valor_y_Retornar_False + LOCAL lnCodError, lcMenError, lnCodError_Esperado ; + , lcLinea, lcLineaOriginal, lcComentario, lcLinea_Esperada, lcComentario_Esperado, llRetorno, llRetorno_Esperado ; + , loEx AS EXCEPTION + LOCAL loObj AS c_conversor_base OF "FOXBIN2PRG.PRG" + loObj = THIS.icObj + loEx = NULL + + *-- DATOS DE ENTRADA + STORE 0 TO lnCodError + lcLinea = [DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+]+'["bb]'+[+"Opción A&]+[&2"] && No debe confundir el '&&' del código con comentarios + lcComentario = [ Comentario Opción A-2] + lcLineaOriginal = lcLinea + '&' + '&' + lcComentario + lcLineaOriginal = LTRIM(lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente + + *-- DATOS ESPERADOS + STORE 0 TO lnCodError_Esperado + lcLinea_Esperada = ALLTRIM(lcLinea, 0, CHR(9), ' ' ) + lcComentario_Esperado = LTRIM(lcComentario) + llRetorno_Esperado = .F. + lcLinea = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente + + *-- TEST + llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLinea, @lcComentario, .F., .T. ) && Activando Deep Comment Analysis + + THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado, @lcLineaOriginal ) + + ENDFUNC + + + ******************************************************************************************************************************************* + FUNCTION Deberia_DevolverSeparados_LineaDeCodigoQueIncluye_DobleAmpersand_y_ComentarioConComillas_y_Retornar_False + LOCAL lnCodError, lcMenError, lnCodError_Esperado ; + , lcLinea, lcLineaOriginal, lcComentario, lcLinea_Esperada, lcComentario_Esperado, llRetorno, llRetorno_Esperado ; + , loEx AS EXCEPTION + LOCAL loObj AS c_conversor_base OF "FOXBIN2PRG.PRG" + loObj = THIS.icObj + loEx = NULL + + *-- DATOS DE ENTRADA + STORE 0 TO lnCodError + lcLinea = [DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+]+'["bb]'+[+"Opción A&]+[&2"] && No debe confundir el '&&' del código con comentarios + lcComentario = [ Comentario's Opción A-2] + lcLineaOriginal = lcLinea + '&' + '&' + lcComentario + lcLineaOriginal = LTRIM(lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente + + *-- DATOS ESPERADOS + STORE 0 TO lnCodError_Esperado + lcLinea_Esperada = ALLTRIM(lcLinea, 0, CHR(9), ' ' ) + lcComentario_Esperado = LTRIM(lcComentario) + llRetorno_Esperado = .F. + lcLinea = LTRIM( lcLineaOriginal, 0, CHR(9), ' ' ) && Este tratamiento lo hace set_Line normalmente + + *-- TEST + llRetorno = loObj.lineIsOnlyCommentAndNoMetadata( @lcLinea, @lcComentario, .F., .T. ) && Activando Deep Comment Analysis + + THIS.Evaluate_results( loEx, lnCodError_Esperado, @lcLinea, @lcComentario, @llRetorno, @lcLinea_Esperada, @lcComentario_Esperado, @llRetorno_Esperado, @lcLineaOriginal ) ENDFUNC diff --git a/foxbin2prg.exe b/foxbin2prg.exe index de42d41..4c826d0 100644 Binary files a/foxbin2prg.exe and b/foxbin2prg.exe differ diff --git a/foxbin2prg.prg b/foxbin2prg.prg index c69de09..d864dbf 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -173,6 +173,7 @@ * 22/06/2015 FDBOZZO v1.19.46 Bug Fix: Arreglo de bug en método set_UserValue() cuando se intenta obtener información de un error que no puede abrir la tabla (por ej, porque el memo está corrupto) * 22/06/2015 FDBOZZO v1.19.46 Mejora: Agregado soporte interno para consulta de información de cfg de directorio, mediante nuevo parámetro opcional, para los métodos API que lo requieren (por ej: get_Ext2FromExt, hasSupport*) * 29/07/2015 FDBOZZO v1.19.46 Bug Fix: Cuando se procesa un directorio o un proyecto con todos los archivos, a veces puede ocurrir el error "Alias already in use" (Dave Crozier) +* 01/09/2015 FDBOZZO v1.19.46 Bug Fix mnx: Cuando se usa '&&' en los textos de las opciones, se corrompe el binario del menú al regenerarlo (Walter Nichols) * * *--------------------------------------------------------------------------------------------------- @@ -263,6 +264,8 @@ * 09/06/2015 Lutz Scheffler Reporte bug v1.19.44: Cuando se procesan múltiples archivos PJ2, puede ocurrir un error de "variable llError no definida" (Arreglado en v1.19.45) * 13/06/2015 Matt Slay Reporte bug v1.19.44: Los proyectos PJX/PJ2 que referencian archivos de otras unidades de disco causan errores ne esos archivos al procesar con las opciones "*" o "*-" (Arreglado en v1.19.45) * 29/07/2015 Dave Crozier Reporte Bug v1.19.45: Cuando se procesa un directorio o un proyecto con todos los archivos, a veces puede ocurrir el error "Alias already in use" (Arreglado en v1.19.46) +* 29/07/2015 Walter Nicholls Mejora DBF-Data v1.19.45: Permitir exportar e importar datos de los DBF +* 28/08/2015 Walter Nicholls Reporte Bug: Cuando se usa '&&' en los textos de las opciones, se corrompe el binario del menú al regenerarlo (Arreglado en v1.19.46) * * *--------------------------------------------------------------------------------------------------- @@ -3792,22 +3795,88 @@ DEFINE CLASS c_foxbin2prg AS Session * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * tcLine (!@ IN/OUT) Línea a separar del comentario * tcComment (@? OUT) Comentario + * tlDeepCommentAnalysis (v? IN ) Indica realizar un análisis profundo de comentarios (para detectar casos complejos de código con '&&' embebido) *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, tcComment + LPARAMETERS tcLine as String, tcComment as String, tlDeepCommentAnalysis as Boolean LOCAL ln_AT_Cmt tcComment = '' ln_AT_Cmt = AT( '&'+'&', tcLine) IF ln_AT_Cmt > 0 - tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) - tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios + IF tlDeepCommentAnalysis THEN + LOCAL laSeparador(3,3), lcSeparadoresIzq, lcSeparadoresDer, lcStr, lnAT_Amp, lnAT1, lnAT2, lnLen, I, X + + lcStr = tcLine &&EVL(tcStr, [DEFINE BAR 2 OF OpciónAsub PROMPT "Opción A&]+[&2" &]+[& Comentario Opción A-2]) + laSeparador(1,1) = '"' + laSeparador(1,2) = '"' + laSeparador(1,3) = 2 + laSeparador(2,1) = "'" + laSeparador(2,2) = "'" + laSeparador(2,3) = 2 + laSeparador(3,1) = '[' + laSeparador(3,2) = ']' + laSeparador(3,3) = 1 + lcSeparadoresIzq = laSeparador(1,1) + laSeparador(2,1) + laSeparador(3,1) + lcSeparadoresDer = laSeparador(1,2) + laSeparador(2,2) + laSeparador(3,2) + lnLen = LEN(lcStr) + + *-- Anular subcadenas para luego encontrar comentarios '&&' (y analizar solo si existe al menos un '&&') + X = 1 + lnAT1 = AT(laSeparador(X,1), lcStr) + + *-- Funcionamiento: + *-- La anulación de subcadenas se hace comenzando desde la primer comilla doble ["], y luego se va + *-- cancelando hasta la siguiente. A partir de ahi, se busca carácter a carácter el siguiente separador + *-- izquierdo de cadena ( '"[ ), se busca su pareja derecha y se cancela el texto entre ambos. + *-- La anulación de subcadenas es temporal, solo para determinar la verdadera posición del comentario, + *-- por ejemplo, esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+["bb]+"Opción A&&2" && Comentario Opción A-2 + *-- se convierte temporalmente en esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT XX+var+XXXX+XXXXX+XXXXXXXXXXXXX && Comentario Opción A-2 + *-- lo que facilita encontrar el comentario '&&' real. + *-- Si se encuentra algún separador de cadena que no cierre, se genera un error 10 (Syntax Error). + IF lnAT1 > 0 THEN + FOR I = lnAT1+1 TO lnLen + IF X > 0 THEN + lnAT2 = AT(laSeparador(X,2), lcStr, laSeparador(X,3)) + + IF lnAT2 > 0 THEN + lcStr = STUFF(lcStr, lnAT1, lnAT2-lnAT1+1, REPLICATE('X',lnAT2-lnAT1+1)) + ELSE + ln_AT_Cmt = AT( '&'+'&', lcStr) + + IF ln_AT_Cmt = 0 OR ln_AT_Cmt < lnAT1 + *-- No tiene comentario '&&' real, o sí lo tiene y además contiene un delimitador de cadena como parte del comentario + EXIT + ELSE + ERROR 'Closing string delimiter <' + laSeparador(X,2) + '> not found: ' + tcLine + ENDIF + ENDIF + ENDIF + + *-- Verifico si el carácter es un separador de cadenas: '"[ + X = AT( SUBSTR(lcStr, I, 1), lcSeparadoresIzq) + + IF X > 0 THEN + lnAT1 = AT(laSeparador(X,1), lcStr) + ENDIF + ENDFOR + ENDIF + + ln_AT_Cmt = AT( '&'+'&', lcStr) + ENDIF && tlDeepCommentAnalysis + + IF ln_AT_Cmt > 0 + tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) + tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios + ENDIF + ENDIF RETURN (ln_AT_Cmt > 0) ENDPROC - PROCEDURE normalizeFileCapitalization LPARAMETERS tl_NormalizeInputFile, tcFileName @@ -5925,20 +5994,84 @@ DEFINE CLASS c_conversor_base AS Custom * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * tcLine (!@ IN/OUT) Línea a separar del comentario * tcComment (@? OUT) Comentario + * tlDeepCommentAnalysis (v? IN ) Indica realizar un análisis profundo de comentarios (para detectar casos complejos de código con '&&' embebido) *--------------------------------------------------------------------------------------------------- - * NOTA: Recordar que esta función suele usarse junto a Set_Line(), que quita TABS y espacios a la izquierda. - *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, tcComment + LPARAMETERS tcLine as String, tcComment as String, tlDeepCommentAnalysis as Boolean LOCAL ln_AT_Cmt tcComment = '' ln_AT_Cmt = AT( '&'+'&', tcLine) IF ln_AT_Cmt > 0 - tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) - tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios de la derecha de la línea de código + IF tlDeepCommentAnalysis THEN + LOCAL laSeparador(3,3), lcSeparadoresIzq, lcSeparadoresDer, lcStr, lnAT_Amp, lnAT1, lnAT2, lnLen, I, X + + lcStr = tcLine &&EVL(tcStr, [DEFINE BAR 2 OF OpciónAsub PROMPT "Opción A&]+[&2" &]+[& Comentario Opción A-2]) + laSeparador(1,1) = '"' + laSeparador(1,2) = '"' + laSeparador(1,3) = 2 + laSeparador(2,1) = "'" + laSeparador(2,2) = "'" + laSeparador(2,3) = 2 + laSeparador(3,1) = '[' + laSeparador(3,2) = ']' + laSeparador(3,3) = 1 + lcSeparadoresIzq = laSeparador(1,1) + laSeparador(2,1) + laSeparador(3,1) + lcSeparadoresDer = laSeparador(1,2) + laSeparador(2,2) + laSeparador(3,2) + lnLen = LEN(lcStr) + + *-- Anular subcadenas para luego encontrar comentarios '&&' (y analizar solo si existe al menos un '&&') + X = 1 + lnAT1 = AT(laSeparador(X,1), lcStr) + + *-- Funcionamiento: + *-- La anulación de subcadenas se hace comenzando desde la primer comilla doble ["], y luego se va + *-- cancelando hasta la siguiente. A partir de ahi, se busca carácter a carácter el siguiente separador + *-- izquierdo de cadena ( '"[ ), se busca su pareja derecha y se cancela el texto entre ambos. + *-- La anulación de subcadenas es temporal, solo para determinar la verdadera posición del comentario, + *-- por ejemplo, esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+["bb]+"Opción A&&2" && Comentario Opción A-2 + *-- se convierte temporalmente en esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT XX+var+XXXX+XXXXX+XXXXXXXXXXXXX && Comentario Opción A-2 + *-- lo que facilita encontrar el comentario '&&' real. + *-- Si se encuentra algún separador de cadena que no cierre, se genera un error 10 (Syntax Error). + IF lnAT1 > 0 THEN + FOR I = lnAT1+1 TO lnLen + IF X > 0 THEN + lnAT2 = AT(laSeparador(X,2), lcStr, laSeparador(X,3)) + + IF lnAT2 > 0 THEN + lcStr = STUFF(lcStr, lnAT1, lnAT2-lnAT1+1, REPLICATE('X',lnAT2-lnAT1+1)) + ELSE + ln_AT_Cmt = AT( '&'+'&', lcStr) + + IF ln_AT_Cmt = 0 OR ln_AT_Cmt < lnAT1 + *-- No tiene comentario '&&' real, o sí lo tiene y además contiene un delimitador de cadena como parte del comentario + EXIT + ELSE + ERROR 'Closing string delimiter <' + laSeparador(X,2) + '> not found: ' + tcLine + ENDIF + ENDIF + ENDIF + + *-- Verifico si el carácter es un separador de cadenas: '"[ + X = AT( SUBSTR(lcStr, I, 1), lcSeparadoresIzq) + + IF X > 0 THEN + lnAT1 = AT(laSeparador(X,1), lcStr) + ENDIF + ENDFOR + ENDIF + + ln_AT_Cmt = AT( '&'+'&', lcStr) + ENDIF && tlDeepCommentAnalysis + + IF ln_AT_Cmt > 0 + tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) + tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios + ENDIF + ENDIF - RELEASE tcLine, tcComment RETURN (ln_AT_Cmt > 0) ENDPROC @@ -6153,16 +6286,22 @@ DEFINE CLASS c_conversor_base AS Custom PROCEDURE lineIsOnlyCommentAndNoMetadata *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * tcLine (!@ IN/OUT) Línea a separar del comentario - * tcComment (@? OUT) Comentario + * tcLine (!@ IN/OUT) Línea a separar del comentario + * tcComment (@? OUT) Comentario + * tlDoNotSeparateLineAndComment (v? IN ) Indica o separar la línea de código del comentario + * tlDeepCommentAnalysis (v? IN ) Indica realizar un análisis profundo de comentarios (para detectar casos complejos de código con '&&' embebido) *--------------------------------------------------------------------------------------------------- * NOTA: Recordar que esta función suele usarse junto a Set_Line(), que quita TABS y espacios a la izquierda. *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, tcComment + LPARAMETERS tcLine as String, tcComment as String, tlDoNotSeparateLineAndComment as Boolean, tlDeepCommentAnalysis as Boolean LOCAL lllineIsOnlyCommentAndNoMetadata, ln_AT_Cmt WITH THIS AS c_conversor_base OF 'FOXBIN2PRG.PRG' - .get_SeparatedLineAndComment( @tcLine, @tcComment ) + IF tlDoNotSeparateLineAndComment + tcComment = '' + ELSE + .get_SeparatedLineAndComment( @tcLine, @tcComment, tlDeepCommentAnalysis ) + ENDIF DO CASE CASE LEFT(tcLine,2) == '*<' @@ -16588,20 +16727,84 @@ DEFINE CLASS CL_CUS_BASE AS CUSTOM * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * tcLine (!@ IN/OUT) Línea a separar del comentario * tcComment (@? OUT) Comentario + * tlDeepCommentAnalysis (v? IN ) Indica realizar un análisis profundo de comentarios (para detectar casos complejos de código con '&&' embebido) *--------------------------------------------------------------------------------------------------- - * NOTA: Recordar que esta función suele usarse junto a Set_Line(), que quita TABS y espacios a la izquierda. - *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, tcComment + LPARAMETERS tcLine as String, tcComment as String, tlDeepCommentAnalysis as Boolean LOCAL ln_AT_Cmt tcComment = '' ln_AT_Cmt = AT( '&'+'&', tcLine) IF ln_AT_Cmt > 0 - tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) - tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios de la derecha de la línea de código + IF tlDeepCommentAnalysis THEN + LOCAL laSeparador(3,3), lcSeparadoresIzq, lcSeparadoresDer, lcStr, lnAT_Amp, lnAT1, lnAT2, lnLen, I, X + + lcStr = tcLine &&EVL(tcStr, [DEFINE BAR 2 OF OpciónAsub PROMPT "Opción A&]+[&2" &]+[& Comentario Opción A-2]) + laSeparador(1,1) = '"' + laSeparador(1,2) = '"' + laSeparador(1,3) = 2 + laSeparador(2,1) = "'" + laSeparador(2,2) = "'" + laSeparador(2,3) = 2 + laSeparador(3,1) = '[' + laSeparador(3,2) = ']' + laSeparador(3,3) = 1 + lcSeparadoresIzq = laSeparador(1,1) + laSeparador(2,1) + laSeparador(3,1) + lcSeparadoresDer = laSeparador(1,2) + laSeparador(2,2) + laSeparador(3,2) + lnLen = LEN(lcStr) + + *-- Anular subcadenas para luego encontrar comentarios '&&' (y analizar solo si existe al menos un '&&') + X = 1 + lnAT1 = AT(laSeparador(X,1), lcStr) + + *-- Funcionamiento: + *-- La anulación de subcadenas se hace comenzando desde la primer comilla doble ["], y luego se va + *-- cancelando hasta la siguiente. A partir de ahi, se busca carácter a carácter el siguiente separador + *-- izquierdo de cadena ( '"[ ), se busca su pareja derecha y se cancela el texto entre ambos. + *-- La anulación de subcadenas es temporal, solo para determinar la verdadera posición del comentario, + *-- por ejemplo, esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+["bb]+"Opción A&&2" && Comentario Opción A-2 + *-- se convierte temporalmente en esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT XX+var+XXXX+XXXXX+XXXXXXXXXXXXX && Comentario Opción A-2 + *-- lo que facilita encontrar el comentario '&&' real. + *-- Si se encuentra algún separador de cadena que no cierre, se genera un error 10 (Syntax Error). + IF lnAT1 > 0 THEN + FOR I = lnAT1+1 TO lnLen + IF X > 0 THEN + lnAT2 = AT(laSeparador(X,2), lcStr, laSeparador(X,3)) + + IF lnAT2 > 0 THEN + lcStr = STUFF(lcStr, lnAT1, lnAT2-lnAT1+1, REPLICATE('X',lnAT2-lnAT1+1)) + ELSE + ln_AT_Cmt = AT( '&'+'&', lcStr) + + IF ln_AT_Cmt = 0 OR ln_AT_Cmt < lnAT1 + *-- No tiene comentario '&&' real, o sí lo tiene y además contiene un delimitador de cadena como parte del comentario + EXIT + ELSE + ERROR 'Closing string delimiter <' + laSeparador(X,2) + '> not found: ' + tcLine + ENDIF + ENDIF + ENDIF + + *-- Verifico si el carácter es un separador de cadenas: '"[ + X = AT( SUBSTR(lcStr, I, 1), lcSeparadoresIzq) + + IF X > 0 THEN + lnAT1 = AT(laSeparador(X,1), lcStr) + ENDIF + ENDFOR + ENDIF + + ln_AT_Cmt = AT( '&'+'&', lcStr) + ENDIF && tlDeepCommentAnalysis + + IF ln_AT_Cmt > 0 + tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) + tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios + ENDIF + ENDIF - RELEASE tcLine, tcComment RETURN (ln_AT_Cmt > 0) ENDPROC @@ -16699,20 +16902,84 @@ DEFINE CLASS CL_COL_BASE AS COLLECTION * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * tcLine (!@ IN/OUT) Línea a separar del comentario * tcComment (@? OUT) Comentario + * tlDeepCommentAnalysis (v? IN ) Indica realizar un análisis profundo de comentarios (para detectar casos complejos de código con '&&' embebido) *--------------------------------------------------------------------------------------------------- - * NOTA: Recordar que esta función suele usarse junto a Set_Line(), que quita TABS y espacios a la izquierda. - *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, tcComment + LPARAMETERS tcLine as String, tcComment as String, tlDeepCommentAnalysis as Boolean LOCAL ln_AT_Cmt tcComment = '' ln_AT_Cmt = AT( '&'+'&', tcLine) IF ln_AT_Cmt > 0 - tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) - tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios de la derecha de la línea de código + IF tlDeepCommentAnalysis THEN + LOCAL laSeparador(3,3), lcSeparadoresIzq, lcSeparadoresDer, lcStr, lnAT_Amp, lnAT1, lnAT2, lnLen, I, X + + lcStr = tcLine &&EVL(tcStr, [DEFINE BAR 2 OF OpciónAsub PROMPT "Opción A&]+[&2" &]+[& Comentario Opción A-2]) + laSeparador(1,1) = '"' + laSeparador(1,2) = '"' + laSeparador(1,3) = 2 + laSeparador(2,1) = "'" + laSeparador(2,2) = "'" + laSeparador(2,3) = 2 + laSeparador(3,1) = '[' + laSeparador(3,2) = ']' + laSeparador(3,3) = 1 + lcSeparadoresIzq = laSeparador(1,1) + laSeparador(2,1) + laSeparador(3,1) + lcSeparadoresDer = laSeparador(1,2) + laSeparador(2,2) + laSeparador(3,2) + lnLen = LEN(lcStr) + + *-- Anular subcadenas para luego encontrar comentarios '&&' (y analizar solo si existe al menos un '&&') + X = 1 + lnAT1 = AT(laSeparador(X,1), lcStr) + + *-- Funcionamiento: + *-- La anulación de subcadenas se hace comenzando desde la primer comilla doble ["], y luego se va + *-- cancelando hasta la siguiente. A partir de ahi, se busca carácter a carácter el siguiente separador + *-- izquierdo de cadena ( '"[ ), se busca su pareja derecha y se cancela el texto entre ambos. + *-- La anulación de subcadenas es temporal, solo para determinar la verdadera posición del comentario, + *-- por ejemplo, esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT ""+var+'aa'+["bb]+"Opción A&&2" && Comentario Opción A-2 + *-- se convierte temporalmente en esto: + *-- DEFINE BAR 2 OF OpciónAsub PROMPT XX+var+XXXX+XXXXX+XXXXXXXXXXXXX && Comentario Opción A-2 + *-- lo que facilita encontrar el comentario '&&' real. + *-- Si se encuentra algún separador de cadena que no cierre, se genera un error 10 (Syntax Error). + IF lnAT1 > 0 THEN + FOR I = lnAT1+1 TO lnLen + IF X > 0 THEN + lnAT2 = AT(laSeparador(X,2), lcStr, laSeparador(X,3)) + + IF lnAT2 > 0 THEN + lcStr = STUFF(lcStr, lnAT1, lnAT2-lnAT1+1, REPLICATE('X',lnAT2-lnAT1+1)) + ELSE + ln_AT_Cmt = AT( '&'+'&', lcStr) + + IF ln_AT_Cmt = 0 OR ln_AT_Cmt < lnAT1 + *-- No tiene comentario '&&' real, o sí lo tiene y además contiene un delimitador de cadena como parte del comentario + EXIT + ELSE + ERROR 'Closing string delimiter <' + laSeparador(X,2) + '> not found: ' + tcLine + ENDIF + ENDIF + ENDIF + + *-- Verifico si el carácter es un separador de cadenas: '"[ + X = AT( SUBSTR(lcStr, I, 1), lcSeparadoresIzq) + + IF X > 0 THEN + lnAT1 = AT(laSeparador(X,1), lcStr) + ENDIF + ENDFOR + ENDIF + + ln_AT_Cmt = AT( '&'+'&', lcStr) + ENDIF && tlDeepCommentAnalysis + + IF ln_AT_Cmt > 0 + tcComment = LTRIM( SUBSTR( tcLine, ln_AT_Cmt + 2 ) ) + tcLine = RTRIM( LEFT( tcLine, ln_AT_Cmt - 1 ), 0, CHR(9), ' ' ) && Quito TABS y espacios + ENDIF + ENDIF - RELEASE tcLine, tcComment RETURN (ln_AT_Cmt > 0) ENDPROC @@ -23018,10 +23285,10 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE DO CASE CASE lcFieldType == 'G' luValue = 'GENERAL FIELD NOT SUPPORTED' - CASE lcFieldType == 'W' - luValue = 'BLOB FIELD NOT SUPPORTED' - CASE lcFieldType == 'Q' - luValue = 'VARBINARY FIELD NOT SUPPORTED' + *CASE lcFieldType == 'W' + * luValue = 'BLOB FIELD NOT SUPPORTED' + *CASE lcFieldType == 'Q' + * luValue = 'VARBINARY FIELD NOT SUPPORTED' OTHERWISE luValue = EVALUATE(lcField) ENDCASE @@ -23034,7 +23301,7 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE ENDIF &&.Encode(luValue) <> luValue ENDCASE TEXT TO lcText TEXTMERGE NOSHOW flags 1+2 PRETEXT 1+2 additive - <<>> <<'<' + lcField + '>'>><>>> + <<>> <<'<' + lcField + '>'>><><<''>> ENDTEXT NEXT @@ -23786,7 +24053,7 @@ DEFINE CLASS CL_MENU AS CL_MENU_COL_BASE CASE EMPTY( tcLine ) LOOP - CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment ) + CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment, .F., .T. ) LOOP && Saltear comentarios CASE NOT llBloque_MenuType_Analizado AND LEFT( tcLine, LEN(C_MENUTYPE_I) ) == C_MENUTYPE_I @@ -24512,7 +24779,7 @@ DEFINE CLASS CL_MENU_BARPOP AS CL_MENU_COL_BASE CASE EMPTY( tcLine ) LOOP - CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment ) + CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment, .F., .T. ) LOOP && Saltear comentarios CASE LEFT( tcLine, LEN(C_MENUCODE_F) ) == C_MENUCODE_F @@ -24755,7 +25022,7 @@ DEFINE CLASS CL_MENU_OPTION AS CL_MENU_COL_BASE CASE EMPTY( tcLine ) LOOP - CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment ) + CASE toConversor.lineIsOnlyCommentAndNoMetadata( @tcLine, @lcComment, .F., .T. ) LOOP && Saltear comentarios CASE LEFT( tcLine, LEN(C_MENUCODE_F) ) == C_MENUCODE_F