From a5c4693922d02f65cf2413acd631bdc2b9f8ec4d Mon Sep 17 00:00:00 2001 From: fdbozzo Date: Thu, 31 Jul 2014 20:56:34 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Changeset:=20384=20fdbozzo=20-=2031/07/2014?= =?UTF-8?q?=2020:54:10:=20-=20Optimizaci=C3=B3n=20y=20normalizaci=C3=B3n?= =?UTF-8?q?=20de=20las=20propiedades=20y=20m=C3=A9todos=20que=20van=20en?= =?UTF-8?q?=20el=20memo=20PROTECTED=20para=20que=20no=20se=20repitan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- foxbin2prg.prg | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/foxbin2prg.prg b/foxbin2prg.prg index d0da57c..505d86d 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -8495,9 +8495,17 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ASORT( taProtected, 1, -1, 0, 1 ) ENDIF - FOR I = 1 TO tnProtected_Count - tcSortedMemo = tcSortedMemo + taProtected(I) + CR_LF + FOR I = tnProtected_Count TO 1 STEP -1 + *-- El ASCAN es para evitar valores repetidos, que se eliminarán. v1.19.29 + IF ASCAN( taProtected, taProtected(I), 1, -1, 0,1+2+4 ) = I + tcSortedMemo = tcSortedMemo + LOWER(taProtected(I)) + CR_LF + ELSE + ADEL( taProtected, I ) + tnProtected_Count = tnProtected_Count - 1 + ENDIF ENDFOR + + DIMENSION taProtected(tnProtected_Count) ENDIF RETURN From 75aecb59a133720596cf7e10aa38448140ad9c30 Mon Sep 17 00:00:00 2001 From: fdbozzo Date: Fri, 1 Aug 2014 00:33:58 +0200 Subject: [PATCH 2/5] =?UTF-8?q?Changeset:=20385=20fdbozzo=20-=2031/07/2014?= =?UTF-8?q?=2020:56:35:=20-=20Optimizaci=C3=B3n=20del=20m=C3=A9todo=20iden?= =?UTF-8?q?tificarBloquesDeExclusion=20-=20Uso=20del=20m=C3=A9todo=20ident?= =?UTF-8?q?ificarBloquesDeExclusion=20en=20SortMethod,=20sustituyendo=20c?= =?UTF-8?q?=C3=B3digo=20duplicado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- foxbin2prg.prg | 496 +++++++++++++++++++++++-------------------------- 1 file changed, 233 insertions(+), 263 deletions(-) diff --git a/foxbin2prg.prg b/foxbin2prg.prg index 505d86d..6dcb616 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -2378,13 +2378,16 @@ DEFINE CLASS c_conversor_base AS SESSION + [] ; + [] ; + [] ; + + [] ; + [] ; + [] ; + [] ; + [] ; + + [] ; + [] ; + [] ; + [] ; + + [] ; + [] ; + [] ; + [] ; @@ -2661,6 +2664,170 @@ DEFINE CLASS c_conversor_base AS SESSION ENDPROC + PROCEDURE currentLineIsPreviousLineContinuation + LPARAMETERS taCodeLines, I + + LOCAL lcPrevLine, llIsContinuation + *-- Analizo la línea anterior para saber si termina con ";" o "," y la actual es continuación + IF I > 1 + lcPrevLine = taCodeLines(I-1) + ELSE + lcPrevLine = '' + ENDIF + .get_SeparatedLineAndComment( @lcPrevLine ) + IF INLIST( RIGHT( lcPrevLine,1 ), ';', ',' ) && Esta línea es continuación de la anterior + llIsContinuation = .T. + ENDIF + RETURN llIsContinuation + ENDPROC + + + PROCEDURE elTextoEvaluadoEsElTokenIndicado + LPARAMETERS tcLine, ta_ID_Bloques, tnLen_IDFinBQ, X, tnIniFin + LOCAL llEncontrado, lcWord + + TRY + IF tnIniFin = 1 + *-- TOKENS DE INICIO + IF UPPER( LEFT( tcLine, LEN(ta_ID_Bloques(X,1)) ) ) == ta_ID_Bloques(X,1) + *-- Evaluar casos especiales + lcWord = UPPER( ALLTRIM(GETWORDNUM(tcLine,1) ) ) + + IF ta_ID_Bloques(X,1) == 'TEXT' AND NOT lcWord == 'TEXT' + EXIT + ENDIF + + llEncontrado = .T. + ENDIF + ELSE + *-- TOKENS DE FIN + IF LEFT( UPPER( tcLine ), tnLen_IDFinBQ ) == ta_ID_Bloques(X,2) && Fin de bloque encontrado (#ENDI, ENDTEXT, etc) + *-- Evaluar casos especiales + lcWord = UPPER( ALLTRIM(GETWORDNUM(tcLine,1) ) ) + + IF ta_ID_Bloques(X,2) == 'ENDT' AND NOT lcWord == LEFT( 'ENDTEXT', LEN(lcWord) ) + EXIT + ENDIF + + llEncontrado = .T. + ENDIF + ENDIF + ENDTRY + + RETURN llEncontrado + ENDPROC + + + PROCEDURE identificarBloquesDeExclusion + LPARAMETERS taCodeLines, tnCodeLines, ta_ID_Bloques, taBloquesExclusion, tnBloquesExclusion, taLineasDeExclusion + * LOS BLOQUES DE EXCLUSIÓN SON AQUELLOS QUE TIENEN TEXT/ENDTEXT OF #IF .F./#ENDIF Y SE USAN PARA NO BUSCAR + * INSTRUCCIONES COMO "DEFINE CLASS" O "PROCEDURE" EN LOS MISMOS. + *-------------------------------------------------------------------------------------------------------------- + * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) + * taCodeLines (!@ IN ) El array con las líneas del código de texto donde buscar + * tnCodeLines (@? IN ) Cantidad de líneas de código + * ta_ID_Bloques (@? IN ) Array de pares de identificadores (2 cols). Ej: '#IF .F.','#ENDI' ; 'TEXT','ENDTEXT' ; etc + * taBloquesExclusion (@? OUT) Array con las posiciones de los bloques (2 cols). Ej: 3,14 ; 23,58 ; etc + * tnBloquesExclusion (@? OUT) Cantidad de bloques de exclusión + * taLineasDeExclusion (@? OUT) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no + *-------------------------------------------------------------------------------------------------------------- + EXTERNAL ARRAY ta_ID_Bloques, taBloquesExclusion + + TRY + LOCAL lnBloques, I, X, lnPrimerID, lnLen_IDFinBQ, lnID_Bloques_Count, lcWord, lnAnidamientos, lcLine, lcPrevLine + DIMENSION taBloquesExclusion(1,2), taLineasDeExclusion(tnCodeLines) + STORE 0 TO tnBloquesExclusion, lnPrimerID, I, X, lnLen_IDFinBQ + + IF tnCodeLines > 1 + IF EMPTY(ta_ID_Bloques) + DIMENSION ta_ID_Bloques(2,2) + ta_ID_Bloques(1,1) = '#IF' + ta_ID_Bloques(1,2) = '#ENDI' + ta_ID_Bloques(2,1) = 'TEXT' + ta_ID_Bloques(2,2) = 'ENDT' + lnID_Bloques_Count = ALEN( ta_ID_Bloques, 1 ) + ENDIF + + *-- Búsqueda del ID de inicio de bloque + WITH THIS AS c_conversor_prg_a_bin OF 'FOXBIN2PRG.PRG' + FOR I = 1 TO tnCodeLines + * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' + lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) + + IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) + LOOP + ENDIF + + lnPrimerID = 0 + + FOR X = 1 TO lnID_Bloques_Count + lnLen_IDFinBQ = LEN( ta_ID_Bloques(X,2) ) + IF .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnPrimerID = X + lnAnidamientos = 1 + EXIT + ENDIF + ENDFOR + + IF lnPrimerID > 0 && Se ha identificado un ID de bloque excluyente + tnBloquesExclusion = tnBloquesExclusion + 1 + lnLen_IDFinBQ = LEN( ta_ID_Bloques(lnPrimerID,2) ) + DIMENSION taBloquesExclusion(tnBloquesExclusion,2) + taBloquesExclusion(tnBloquesExclusion,1) = I + taLineasDeExclusion(I) = .T. + + * Búsqueda del ID de fin de bloque + FOR I = I + 1 TO tnCodeLines + * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' + lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) + taLineasDeExclusion(I) = .T. + + IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) + LOOP + ENDIF + + DO CASE + CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnAnidamientos = lnAnidamientos + 1 + + CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 2 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnAnidamientos = lnAnidamientos - 1 + + IF lnAnidamientos = 0 + taBloquesExclusion(tnBloquesExclusion,2) = I + EXIT + ENDIF + ENDCASE + ENDFOR + + *-- Validación + IF EMPTY(taBloquesExclusion(tnBloquesExclusion,2)) + *ERROR 'No se ha encontrado el marcador de fin [' + ta_ID_Bloques(lnPrimerID,2) ; + + '] que cierra al marcador de inicio [' + ta_ID_Bloques(lnPrimerID,1) ; + + '] de la línea ' + TRANSFORM(taBloquesExclusion(tnBloquesExclusion,1)) + ERROR (TEXTMERGE(C_END_MARKER_NOT_FOUND_LOC)) + ENDIF + ENDIF + ENDFOR + ENDWITH && THIS + ENDIF + + CATCH TO loEx + IF THIS.l_Debug AND _VFP.STARTMODE = 0 + SET STEP ON + ENDIF + + THROW + + ENDTRY + + RETURN + ENDPROC + + PROCEDURE decode_SpecialCodes_1_31 *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) @@ -2890,6 +3057,64 @@ DEFINE CLASS c_conversor_base AS SESSION ENDFUNC + PROCEDURE get_ListNamesWithValuesFrom_InLine_MetadataTag + *-- OBTENGO EL ARRAY DE DATOS Y VALORES DE LA LINEA DE METADATOS INDICADA + *-- NOTA: Los valores NO PUEDEN contener comillas dobles en su valor, ya que generaría un error al parsearlos. + *-- Ejemplo: + *< FileMetadata: Type="V" Cpid="1252" Timestamp="1131901580" ID="1129207528" ObjRev="544" /> + *< OLE: Nombre="frm_form.Pageframe1.Page1.Cnt_controles_h.Olecontrol1" Parent="frm_form.Pageframe1.Page1.Cnt_controles_h" ObjName="Olecontrol1" Checksum="1685567300" Value="0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPg...ADAP7AAAA==" /> + *-------------------------------------------------------------------------------------------------------------- + * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) + * tcLineWithMetadata (!@ IN ) Línea con metadatos y un tag de metadatos + * taPropsAndValues (!@ OUT) Array a devolver con las propiedades y valores encontrados + * tnPropsAndValues_Count (!@ OUT) Cantidad de propiedades encontradas + * tcLeftTag (v! IN ) TAG de inicio de los metadatos + * tcRightTag (v! IN ) TAG de fin de los metadatos + *-------------------------------------------------------------------------------------------------------------- + LPARAMETERS tcLineWithMetadata, taPropsAndValues, tnPropsAndValues_Count, tcLeftTag, tcRightTag + EXTERNAL ARRAY taPropsAndValues + + LOCAL lcMetadatos, I, lnEqualSigns, lcNextVar, lcStr, lcVirtualMeta, lnPos1, lnPos2, lnLastPos, lnCantComillas + STORE '' TO lcVirtualMeta + STORE 0 TO lnPos1, lnPos2, lnLastPos, tnPropsAndValues_Count, I + + lcMetadatos = ALLTRIM( STREXTRACT( tcLineWithMetadata, tcLeftTag, tcRightTag, 1, 1) ) + lnCantComillas = OCCURS( '"', lcMetadatos ) + + IF lnCantComillas % 2 <> 0 && Valido que las comillas "" sean pares + *ERROR "Error de datos: No se puede parsear porque las comillas no son pares en la línea [" + lcMetadatos + "]" + ERROR (TEXTMERGE(C_DATA_ERROR_CANT_PARSE_UNPAIRING_DOUBLE_QUOTES_LOC)) + ENDIF + + lnLastPos = 1 + DIMENSION taPropsAndValues( lnCantComillas / 2, 2 ) + + *------------------------------------------------------------------------------------- + * IMPORTANTE!! + * ------------ + * SI SE SEPARAN LAS IGUALDADES CON ESPACIOS, ÉSTAS DEJAN DE RECONOCERSE!! (prop = "valor" en vez de prop="valor") + * TENER EN CUENTA AL GENERAR EL TEXTO O AL MODIFICARLO MANUALMENTE AL MERGEAR + *------------------------------------------------------------------------------------- + FOR I = 1 TO lnCantComillas STEP 2 + tnPropsAndValues_Count = tnPropsAndValues_Count + 1 + + * Type="V" Cpid="1252" + * ^ ^ => Posiciones del par de comillas dobles + lnPos1 = AT( '"', lcMetadatos, I ) + lnPos2 = AT( '"', lcMetadatos, I + 1 ) + + * Type="V" Cpid="1252" + * ^ ^ ^ => LastPos, lnPos1 y lnPos2 + taPropsAndValues(tnPropsAndValues_Count,1) = ALLTRIM( GETWORDNUM( SUBSTR( lcMetadatos, lnLastPos, lnPos1 - lnLastPos ), 1, '=' ) ) + taPropsAndValues(tnPropsAndValues_Count,2) = SUBSTR( lcMetadatos, lnPos1 + 1, lnPos2 - lnPos1 - 1 ) + + lnLastPos = lnPos2 + 1 + ENDFOR + + RETURN + ENDPROC + + PROCEDURE get_SeparatedLineAndComment *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) @@ -3587,19 +3812,15 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base + [] ; + [] ; + [] ; - + [] ; + [] ; - + [] ; + [] ; + [] ; + [] ; + [] ; + [] ; + [] ; - + [] ; + [] ; + [] ; - + [] ; + [] ; + [] ; + [] ; @@ -3664,235 +3885,6 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base ENDFUNC - ******************************************************************************************************************* - PROCEDURE get_ListNamesWithValuesFrom_InLine_MetadataTag - *-- OBTENGO EL ARRAY DE DATOS Y VALORES DE LA LINEA DE METADATOS INDICADA - *-- NOTA: Los valores NO PUEDEN contener comillas dobles en su valor, ya que generaría un error al parsearlos. - *-- Ejemplo: - *< FileMetadata: Type="V" Cpid="1252" Timestamp="1131901580" ID="1129207528" ObjRev="544" /> - *< OLE: Nombre="frm_form.Pageframe1.Page1.Cnt_controles_h.Olecontrol1" Parent="frm_form.Pageframe1.Page1.Cnt_controles_h" ObjName="Olecontrol1" Checksum="1685567300" Value="0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPg...ADAP7AAAA==" /> - *-------------------------------------------------------------------------------------------------------------- - * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * tcLineWithMetadata (!@ IN ) Línea con metadatos y un tag de metadatos - * taPropsAndValues (!@ OUT) Array a devolver con las propiedades y valores encontrados - * tnPropsAndValues_Count (!@ OUT) Cantidad de propiedades encontradas - * tcLeftTag (v! IN ) TAG de inicio de los metadatos - * tcRightTag (v! IN ) TAG de fin de los metadatos - *-------------------------------------------------------------------------------------------------------------- - LPARAMETERS tcLineWithMetadata, taPropsAndValues, tnPropsAndValues_Count, tcLeftTag, tcRightTag - EXTERNAL ARRAY taPropsAndValues - - LOCAL lcMetadatos, I, lnEqualSigns, lcNextVar, lcStr, lcVirtualMeta, lnPos1, lnPos2, lnLastPos, lnCantComillas - STORE '' TO lcVirtualMeta - STORE 0 TO lnPos1, lnPos2, lnLastPos, tnPropsAndValues_Count, I - - lcMetadatos = ALLTRIM( STREXTRACT( tcLineWithMetadata, tcLeftTag, tcRightTag, 1, 1) ) - lnCantComillas = OCCURS( '"', lcMetadatos ) - - IF lnCantComillas % 2 <> 0 && Valido que las comillas "" sean pares - *ERROR "Error de datos: No se puede parsear porque las comillas no son pares en la línea [" + lcMetadatos + "]" - ERROR (TEXTMERGE(C_DATA_ERROR_CANT_PARSE_UNPAIRING_DOUBLE_QUOTES_LOC)) - ENDIF - - lnLastPos = 1 - DIMENSION taPropsAndValues( lnCantComillas / 2, 2 ) - - *------------------------------------------------------------------------------------- - * IMPORTANTE!! - * ------------ - * SI SE SEPARAN LAS IGUALDADES CON ESPACIOS, ÉSTAS DEJAN DE RECONOCERSE!! (prop = "valor" en vez de prop="valor") - * TENER EN CUENTA AL GENERAR EL TEXTO O AL MODIFICARLO MANUALMENTE AL MERGEAR - *------------------------------------------------------------------------------------- - FOR I = 1 TO lnCantComillas STEP 2 - tnPropsAndValues_Count = tnPropsAndValues_Count + 1 - - * Type="V" Cpid="1252" - * ^ ^ => Posiciones del par de comillas dobles - lnPos1 = AT( '"', lcMetadatos, I ) - lnPos2 = AT( '"', lcMetadatos, I + 1 ) - - * Type="V" Cpid="1252" - * ^ ^ ^ => LastPos, lnPos1 y lnPos2 - taPropsAndValues(tnPropsAndValues_Count,1) = ALLTRIM( GETWORDNUM( SUBSTR( lcMetadatos, lnLastPos, lnPos1 - lnLastPos ), 1, '=' ) ) - taPropsAndValues(tnPropsAndValues_Count,2) = SUBSTR( lcMetadatos, lnPos1 + 1, lnPos2 - lnPos1 - 1 ) - - lnLastPos = lnPos2 + 1 - ENDFOR - - RETURN - ENDPROC - - - PROCEDURE elTextoEvaluadoEsElTokenIndicado - LPARAMETERS tcLine, ta_ID_Bloques, tnLen_IDFinBQ, X, tnIniFin - LOCAL llEncontrado, lcWord - - TRY - IF tnIniFin = 1 - *-- TOKENS DE INICIO - IF UPPER( LEFT( tcLine, LEN(ta_ID_Bloques(X,1)) ) ) == ta_ID_Bloques(X,1) - *-- Evaluar casos especiales - lcWord = UPPER( ALLTRIM(GETWORDNUM(tcLine,1) ) ) - - IF ta_ID_Bloques(X,1) == 'TEXT' AND NOT lcWord == 'TEXT' - EXIT - ENDIF - - llEncontrado = .T. - ENDIF - ELSE - *-- TOKENS DE FIN - IF LEFT( UPPER( tcLine ), tnLen_IDFinBQ ) == ta_ID_Bloques(X,2) && Fin de bloque encontrado (#ENDI, ENDTEXT, etc) - *-- Evaluar casos especiales - lcWord = UPPER( ALLTRIM(GETWORDNUM(tcLine,1) ) ) - - IF ta_ID_Bloques(X,2) == 'ENDT' AND NOT lcWord == LEFT( 'ENDTEXT', LEN(lcWord) ) - EXIT - ENDIF - - llEncontrado = .T. - ENDIF - ENDIF - ENDTRY - - RETURN llEncontrado - ENDPROC - - - PROCEDURE currentLineIsPreviousLineContinuation - LPARAMETERS taCodeLines, I - - LOCAL lcPrevLine, llIsContinuation - *-- Analizo la línea anterior para saber si termina con ";" o "," y la actual es continuación - IF I > 1 - lcPrevLine = taCodeLines(I-1) - ELSE - lcPrevLine = '' - ENDIF - .get_SeparatedLineAndComment( @lcPrevLine ) - IF INLIST( RIGHT( lcPrevLine,1 ), ';', ',' ) && Esta línea es continuación de la anterior - llIsContinuation = .T. - ENDIF - RETURN llIsContinuation - ENDPROC - - - PROCEDURE identificarBloquesDeExclusion - LPARAMETERS taCodeLines, tnCodeLines, ta_ID_Bloques, taBloquesExclusion, tnBloquesExclusion - * LOS BLOQUES DE EXCLUSIÓN SON AQUELLOS QUE TIENEN TEXT/ENDTEXT OF #IF .F./#ENDIF Y SE USAN PARA NO BUSCAR - * INSTRUCCIONES COMO "DEFINE CLASS" O "PROCEDURE" EN LOS MISMOS. - *-------------------------------------------------------------------------------------------------------------- - * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * taCodeLines (!@ IN ) El array con las líneas del código de texto donde buscar - * tnCodeLines (@? IN ) Cantidad de líneas de código - * ta_ID_Bloques (@? IN ) Array de pares de identificadores (2 cols). Ej: '#IF .F.','#ENDI' ; 'TEXT','ENDTEXT' ; etc - * taBloquesExclusion (@? OUT) Array con las posiciones de los bloques (2 cols). Ej: 3,14 ; 23,58 ; etc - * tnBloquesExclusion (@? OUT) Cantidad de bloques de exclusión - *-------------------------------------------------------------------------------------------------------------- - EXTERNAL ARRAY ta_ID_Bloques, taBloquesExclusion - - TRY - LOCAL lnBloques, I, X, lnPrimerID, lnLen_IDFinBQ, lnID_Bloques_Count, lcWord, lnAnidamientos, lcLine, lcPrevLine - DIMENSION taBloquesExclusion(1,2) - STORE 0 TO tnBloquesExclusion, lnPrimerID, I, X, lnLen_IDFinBQ - - IF tnCodeLines > 1 - IF EMPTY(ta_ID_Bloques) - DIMENSION ta_ID_Bloques(2,2) - ta_ID_Bloques(1,1) = '#IF' - ta_ID_Bloques(1,2) = '#ENDI' - ta_ID_Bloques(2,1) = 'TEXT' - ta_ID_Bloques(2,2) = 'ENDT' - lnID_Bloques_Count = ALEN( ta_ID_Bloques, 1 ) - ENDIF - - *-- Búsqueda del ID de inicio de bloque - WITH THIS AS c_conversor_prg_a_bin OF 'FOXBIN2PRG.PRG' - FOR I = 1 TO tnCodeLines - * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' - lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) - - IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) - LOOP - ENDIF - - lnPrimerID = 0 - - FOR X = 1 TO lnID_Bloques_Count - lnLen_IDFinBQ = LEN( ta_ID_Bloques(X,2) ) - IF .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnPrimerID = X - lnAnidamientos = 1 - EXIT - ENDIF - ENDFOR - - IF lnPrimerID > 0 && Se ha identificado un ID de bloque excluyente - *IF I > 1 - * *-- Analizo la línea anterior para saber si termina con ";" o "," y la actual es continuación - * lcPrevLine = taCodeLines(I-1) - * .get_SeparatedLineAndComment( @lcPrevLine ) - * IF INLIST( RIGHT( lcPrevLine,1 ), ';', ',' ) && Esta línea es continuación de la anterior - * LOOP - * ENDIF - *ENDIF - - tnBloquesExclusion = tnBloquesExclusion + 1 - lnLen_IDFinBQ = LEN( ta_ID_Bloques(lnPrimerID,2) ) - DIMENSION taBloquesExclusion(tnBloquesExclusion,2) - taBloquesExclusion(tnBloquesExclusion,1) = I - - * Búsqueda del ID de fin de bloque - FOR I = I + 1 TO tnCodeLines - * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' - lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) - - IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) - LOOP - ENDIF - - DO CASE - CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnAnidamientos = lnAnidamientos + 1 - - CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 2 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnAnidamientos = lnAnidamientos - 1 - - IF lnAnidamientos = 0 - taBloquesExclusion(tnBloquesExclusion,2) = I - EXIT - ENDIF - ENDCASE - ENDFOR - - *-- Validación - IF EMPTY(taBloquesExclusion(tnBloquesExclusion,2)) - *ERROR 'No se ha encontrado el marcador de fin [' + ta_ID_Bloques(lnPrimerID,2) ; - + '] que cierra al marcador de inicio [' + ta_ID_Bloques(lnPrimerID,1) ; - + '] de la línea ' + TRANSFORM(taBloquesExclusion(tnBloquesExclusion,1)) - ERROR (TEXTMERGE(C_END_MARKER_NOT_FOUND_LOC)) - ENDIF - ENDIF - ENDFOR - ENDWITH && THIS - ENDIF - - CATCH TO loEx - IF THIS.l_Debug AND _VFP.STARTMODE = 0 - SET STEP ON - ENDIF - - THROW - - ENDTRY - - RETURN - ENDPROC - - ******************************************************************************************************************* PROCEDURE analizarBloque_FoxBin2Prg *------------------------------------------------------ @@ -8653,8 +8645,9 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base *-- taCode[1] *-- Bloque de código del método en su posición original TRY - LOCAL lnLineCount, laLine(1), I, lnTextNodes, tcSorted, lnProtectedLine, lcMethod, lnLine_Len, lcLine, llProcOpen - LOCAL loEx AS EXCEPTION + LOCAL lnLineCount, laLine(1), I, lnTextNodes, tcSorted, lnProtectedLine, lcMethod, lnLine_Len, lcLine, llProcOpen ; + , laBloquesExclusion(1,2), lnBloquesExclusion, laLineasDeExclusion(1) ; + , loEx AS EXCEPTION DIMENSION taMethods(1,3) STORE '' TO taMethods, tcSorted, taCode tnMethodCount = 0 @@ -8699,6 +8692,9 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ENDIF ENDFOR + *-- Identifico los TEXT/ENDTEXT, #IF .F./#ENDIF + THIS.identificarBloquesDeExclusion( @laLine, lnLineCount, .F., @laBloquesExclusion, @lnBloquesExclusion, @laLineasDeExclusion ) + *-- Analyze and count line methods, get method names and consolidate block code FOR I = 1 TO lnLineCount IF toFoxBin2Prg.l_DropNullCharsFromCode @@ -8708,35 +8704,9 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base lnLine_Len = LEN( laLine(I) ) DO CASE - CASE UPPER( LEFT(laLine(I), 4) ) == 'TEXT' - lcLine = UPPER( CHRTRAN( laLine(I) , '&'+CHR(9)+CHR(0), ' ') ) + ' ' - IF lnLine_Len >= 4 AND LEFT(lcLine,5) == 'TEXT ' - *-- Es el comando TEXT - ELSE - *-- Es otra cosa (variable, etc) - taCode(tnMethodCount) = taCode(tnMethodCount) + laLine(I) + CR_LF - LOOP - ENDIF - - lnTextNodes = lnTextNodes + 1 + CASE laLineasDeExclusion(I) taCode(tnMethodCount) = taCode(tnMethodCount) + laLine(I) + CR_LF - - CASE UPPER( LEFT(laLine(I), 4) ) == 'ENDT' - lcLine = UPPER( CHRTRAN( laLine(I) , '&'+CHR(9)+CHR(0), ' ') ) + ' ' - IF lnLine_Len >= 7 AND LEFT(lcLine,8) == 'ENDTEXT ' ; - OR lnLine_Len >= 6 AND LEFT(lcLine,7) == 'ENDTEX ' ; - OR lnLine_Len >= 5 AND LEFT(lcLine,6) == 'ENDTE ' ; - OR lnLine_Len >= 4 AND LEFT(lcLine,5) == 'ENDT ' - *-- Es el comando ENDTEXT - ELSE - *-- Es otra cosa (variable, etc) - taCode(tnMethodCount) = taCode(tnMethodCount) + laLine(I) + CR_LF - LOOP - ENDIF - - lnTextNodes = lnTextNodes - 1 - taCode(tnMethodCount) = taCode(tnMethodCount) + laLine(I) + CR_LF - + CASE lnTextNodes = 0 AND UPPER( LEFT(laLine(I), 10) ) == 'PROCEDURE ' tnMethodCount = tnMethodCount + 1 DIMENSION taMethods(tnMethodCount, 3), taCode(tnMethodCount) From 5aa42ae538ad71847c10a19ec54a4f10a373e209 Mon Sep 17 00:00:00 2001 From: fdbozzo Date: Fri, 1 Aug 2014 01:16:33 +0200 Subject: [PATCH 3/5] =?UTF-8?q?Changeset:=20386=20fdbozzo=20-=2001/08/2014?= =?UTF-8?q?=2000:33:59:=20-=20Refactorizaci=C3=B3n=20de=20las=20llamadas?= =?UTF-8?q?=20a=20identificarBloquesDeExclusion=20y=20cambio=20de=20la=20v?= =?UTF-8?q?ariable=20aBloquesExclusion=20por=20la=20nueva=20aLineasExclusi?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...or_base__IdentificarBloquesDeExclusion.prg | 10 +- foxbin2prg.prg | 366 +++++++++--------- 2 files changed, 189 insertions(+), 187 deletions(-) diff --git a/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg b/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg index 45e898f..2aa01e7 100644 --- a/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg +++ b/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg @@ -81,7 +81,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laPos, @lnPos_Count ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) @@ -115,7 +115,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laPos, @lnPos_Count ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) @@ -151,7 +151,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laPos, @lnPos_Count ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) @@ -228,7 +228,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laPos, @lnPos_Count ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) @@ -281,7 +281,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laPos, @lnPos_Count ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) diff --git a/foxbin2prg.prg b/foxbin2prg.prg index 6dcb616..623586d 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -2718,116 +2718,6 @@ DEFINE CLASS c_conversor_base AS SESSION ENDPROC - PROCEDURE identificarBloquesDeExclusion - LPARAMETERS taCodeLines, tnCodeLines, ta_ID_Bloques, taBloquesExclusion, tnBloquesExclusion, taLineasDeExclusion - * LOS BLOQUES DE EXCLUSIÓN SON AQUELLOS QUE TIENEN TEXT/ENDTEXT OF #IF .F./#ENDIF Y SE USAN PARA NO BUSCAR - * INSTRUCCIONES COMO "DEFINE CLASS" O "PROCEDURE" EN LOS MISMOS. - *-------------------------------------------------------------------------------------------------------------- - * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * taCodeLines (!@ IN ) El array con las líneas del código de texto donde buscar - * tnCodeLines (@? IN ) Cantidad de líneas de código - * ta_ID_Bloques (@? IN ) Array de pares de identificadores (2 cols). Ej: '#IF .F.','#ENDI' ; 'TEXT','ENDTEXT' ; etc - * taBloquesExclusion (@? OUT) Array con las posiciones de los bloques (2 cols). Ej: 3,14 ; 23,58 ; etc - * tnBloquesExclusion (@? OUT) Cantidad de bloques de exclusión - * taLineasDeExclusion (@? OUT) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no - *-------------------------------------------------------------------------------------------------------------- - EXTERNAL ARRAY ta_ID_Bloques, taBloquesExclusion - - TRY - LOCAL lnBloques, I, X, lnPrimerID, lnLen_IDFinBQ, lnID_Bloques_Count, lcWord, lnAnidamientos, lcLine, lcPrevLine - DIMENSION taBloquesExclusion(1,2), taLineasDeExclusion(tnCodeLines) - STORE 0 TO tnBloquesExclusion, lnPrimerID, I, X, lnLen_IDFinBQ - - IF tnCodeLines > 1 - IF EMPTY(ta_ID_Bloques) - DIMENSION ta_ID_Bloques(2,2) - ta_ID_Bloques(1,1) = '#IF' - ta_ID_Bloques(1,2) = '#ENDI' - ta_ID_Bloques(2,1) = 'TEXT' - ta_ID_Bloques(2,2) = 'ENDT' - lnID_Bloques_Count = ALEN( ta_ID_Bloques, 1 ) - ENDIF - - *-- Búsqueda del ID de inicio de bloque - WITH THIS AS c_conversor_prg_a_bin OF 'FOXBIN2PRG.PRG' - FOR I = 1 TO tnCodeLines - * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' - lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) - - IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) - LOOP - ENDIF - - lnPrimerID = 0 - - FOR X = 1 TO lnID_Bloques_Count - lnLen_IDFinBQ = LEN( ta_ID_Bloques(X,2) ) - IF .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnPrimerID = X - lnAnidamientos = 1 - EXIT - ENDIF - ENDFOR - - IF lnPrimerID > 0 && Se ha identificado un ID de bloque excluyente - tnBloquesExclusion = tnBloquesExclusion + 1 - lnLen_IDFinBQ = LEN( ta_ID_Bloques(lnPrimerID,2) ) - DIMENSION taBloquesExclusion(tnBloquesExclusion,2) - taBloquesExclusion(tnBloquesExclusion,1) = I - taLineasDeExclusion(I) = .T. - - * Búsqueda del ID de fin de bloque - FOR I = I + 1 TO tnCodeLines - * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' - lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) - taLineasDeExclusion(I) = .T. - - IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) - LOOP - ENDIF - - DO CASE - CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnAnidamientos = lnAnidamientos + 1 - - CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 2 ) ; - AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) - lnAnidamientos = lnAnidamientos - 1 - - IF lnAnidamientos = 0 - taBloquesExclusion(tnBloquesExclusion,2) = I - EXIT - ENDIF - ENDCASE - ENDFOR - - *-- Validación - IF EMPTY(taBloquesExclusion(tnBloquesExclusion,2)) - *ERROR 'No se ha encontrado el marcador de fin [' + ta_ID_Bloques(lnPrimerID,2) ; - + '] que cierra al marcador de inicio [' + ta_ID_Bloques(lnPrimerID,1) ; - + '] de la línea ' + TRANSFORM(taBloquesExclusion(tnBloquesExclusion,1)) - ERROR (TEXTMERGE(C_END_MARKER_NOT_FOUND_LOC)) - ENDIF - ENDIF - ENDFOR - ENDWITH && THIS - ENDIF - - CATCH TO loEx - IF THIS.l_Debug AND _VFP.STARTMODE = 0 - SET STEP ON - ENDIF - - THROW - - ENDTRY - - RETURN - ENDPROC - - PROCEDURE decode_SpecialCodes_1_31 *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) @@ -3140,11 +3030,13 @@ DEFINE CLASS c_conversor_base AS SESSION *-- Si se indican más de 3 parámetros, evalúa el valor completo a través de las líneas de código (valores multi-línea) *-------------------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * taCodeLines (!@ IN ) El array con las líneas del código donde buscar - * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (!@ IN ) Array con las posiciones de inicio/fin de los bloques de exclusion - * tnBloquesExclusion (!@ IN ) Cantidad de bloques de exclusión - * toModulo (@? OUT) Objeto con toda la información del módulo analizado + * tcAsignacion (v! IN ) Asignación completa con variable, igualdad y valor + * tcPropName (@! OUT) Nombre de la variable + * tcValue (@? OUT) Valor + * toClase (v! IN ) + * taCodeLines (@! IN ) Líneas de código a analizar + * tnCodeLines (v! IN ) Cantidad de líneas de código + * I (@! IN/OUT) Línea actual *-------------------------------------------------------------------------------------------------------------- LPARAMETERS tcAsignacion, tcPropName, tcValue, toClase, taCodeLines, tnCodeLines, I LOCAL ln_AT_Cmt @@ -3197,25 +3089,135 @@ DEFINE CLASS c_conversor_base AS SESSION ******************************************************************************************************************* PROCEDURE identificarBloquesDeCodigo - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toModulo + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toModulo + ENDPROC + + + PROCEDURE identificarBloquesDeExclusion + LPARAMETERS taCodeLines, tnCodeLines, ta_ID_Bloques, taLineasExclusion, tnBloquesExclusion, taBloquesExclusion + * LOS BLOQUES DE EXCLUSIÓN SON AQUELLOS QUE TIENEN TEXT/ENDTEXT OF #IF/#ENDIF Y SE USAN PARA NO BUSCAR + * INSTRUCCIONES COMO "DEFINE CLASS" O "PROCEDURE" EN LOS MISMOS. + *-------------------------------------------------------------------------------------------------------------- + * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) + * taCodeLines (!@ IN ) El array con las líneas del código de texto donde buscar + * tnCodeLines (@? IN ) Cantidad de líneas de código + * ta_ID_Bloques (@? IN ) Array de pares de identificadores (2 cols). Ej: '#IF .F.','#ENDI' ; 'TEXT','ENDTEXT' ; etc + * taLineasExclusion (@? OUT) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no + * tnBloquesExclusion (@? OUT) Cantidad de bloques de exclusión + *-------------------------------------------------------------------------------------------------------------- + EXTERNAL ARRAY ta_ID_Bloques, taLineasExclusion + + TRY + LOCAL lnBloques, I, X, lnPrimerID, lnLen_IDFinBQ, lnID_Bloques_Count, lcWord, lnAnidamientos, lcLine, lcPrevLine + DIMENSION taLineasExclusion(tnCodeLines), taBloquesExclusion(1,2) + STORE 0 TO tnBloquesExclusion, lnPrimerID, I, X, lnLen_IDFinBQ + + IF tnCodeLines > 1 + IF EMPTY(ta_ID_Bloques) + DIMENSION ta_ID_Bloques(2,2) + ta_ID_Bloques(1,1) = '#IF' + ta_ID_Bloques(1,2) = '#ENDI' + ta_ID_Bloques(2,1) = 'TEXT' + ta_ID_Bloques(2,2) = 'ENDT' + lnID_Bloques_Count = ALEN( ta_ID_Bloques, 1 ) + ENDIF + + *-- Búsqueda del ID de inicio de bloque + WITH THIS AS c_conversor_prg_a_bin OF 'FOXBIN2PRG.PRG' + FOR I = 1 TO tnCodeLines + * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' + lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) + + IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) + LOOP + ENDIF + + lnPrimerID = 0 + + FOR X = 1 TO lnID_Bloques_Count + lnLen_IDFinBQ = LEN( ta_ID_Bloques(X,2) ) + IF .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnPrimerID = X + lnAnidamientos = 1 + EXIT + ENDIF + ENDFOR + + IF lnPrimerID > 0 && Se ha identificado un ID de bloque excluyente + tnBloquesExclusion = tnBloquesExclusion + 1 + lnLen_IDFinBQ = LEN( ta_ID_Bloques(lnPrimerID,2) ) + DIMENSION taBloquesExclusion(tnBloquesExclusion,2) + taBloquesExclusion(tnBloquesExclusion,1) = I + taLineasExclusion(I) = .T. + + * Búsqueda del ID de fin de bloque + FOR I = I + 1 TO tnCodeLines + * Reduzco los espacios. Ej: '#IF .F. && cmt' ==> '#IF .F.&&cmt' + lcLine = LTRIM( STRTRAN( STRTRAN( CHRTRAN( taCodeLines(I), CHR(9), ' ' ), ' ', ' ' ), ' ', ' ' ) ) + taLineasExclusion(I) = .T. + + IF .lineIsOnlyCommentAndNoMetadata( @lcLine ) + LOOP + ENDIF + + DO CASE + CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 1 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnAnidamientos = lnAnidamientos + 1 + + CASE .elTextoEvaluadoEsElTokenIndicado( @lcLine, @ta_ID_Bloques, lnLen_IDFinBQ, X, 2 ) ; + AND NOT THIS.currentLineIsPreviousLineContinuation( @taCodeLines, I ) + lnAnidamientos = lnAnidamientos - 1 + + IF lnAnidamientos = 0 + taBloquesExclusion(tnBloquesExclusion,2) = I + EXIT + ENDIF + ENDCASE + ENDFOR + + *-- Validación + IF EMPTY(taBloquesExclusion(tnBloquesExclusion,2)) + *ERROR 'No se ha encontrado el marcador de fin [' + ta_ID_Bloques(lnPrimerID,2) ; + + '] que cierra al marcador de inicio [' + ta_ID_Bloques(lnPrimerID,1) ; + + '] de la línea ' + TRANSFORM(taBloquesExclusion(tnBloquesExclusion,1)) + ERROR (TEXTMERGE(C_END_MARKER_NOT_FOUND_LOC)) + ENDIF + ENDIF + ENDFOR + ENDWITH && THIS + ENDIF + + CATCH TO loEx + IF THIS.l_Debug AND _VFP.STARTMODE = 0 + SET STEP ON + ENDIF + + THROW + + ENDTRY + + RETURN ENDPROC ******************************************************************************************************************* PROCEDURE lineaExcluida - LPARAMETERS tn_Linea, tnBloquesExclusion, taBloquesExclusion + LPARAMETERS tn_Linea, tnBloquesExclusion, taLineasExclusion - EXTERNAL ARRAY taBloquesExclusion - LOCAL X, llExcluida + EXTERNAL ARRAY taLineasExclusion + *LOCAL X, llExcluida - FOR X = 1 TO tnBloquesExclusion - IF BETWEEN( tn_Linea, taBloquesExclusion(X,1), taBloquesExclusion(X,2) ) - llExcluida = .T. - EXIT - ENDIF - ENDFOR + *FOR X = 1 TO tnBloquesExclusion + * IF BETWEEN( tn_Linea, taBloquesExclusion(X,1), taBloquesExclusion(X,2) ) + * llExcluida = .T. + * EXIT + * ENDIF + *ENDFOR - RETURN llExcluida + *RETURN llExcluida + RETURN taLineasExclusion(tn_Linea) ENDPROC @@ -4766,7 +4768,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base ******************************************************************************************************************* PROCEDURE analizarLineasDeProcedure LPARAMETERS toClase, toObjeto, tcLine, taCodeLines, I, tnCodeLines, tcProcedureAbierto, tc_Comentario ; - , taBloquesExclusion, tnBloquesExclusion + , taLineasExclusion, tnBloquesExclusion EXTERNAL ARRAY taCodeLines #IF .F. @@ -4789,7 +4791,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base FOR I = I + 1 TO tnCodeLines .set_Line( @tcLine, @taCodeLines, I ) - IF NOT .lineaExcluida( I, tnBloquesExclusion, @taBloquesExclusion ) ; + IF NOT .lineaExcluida( I, tnBloquesExclusion, @taLineasExclusion ) ; AND NOT .lineIsOnlyCommentAndNoMetadata( @tcLine, @tc_Comentario ) DO CASE @@ -5069,9 +5071,9 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base ******************************************************************************************************************* PROCEDURE analizarBloque_DEFINE_CLASS LPARAMETERS toModulo, toClase, tcLine, taCodeLines, I, tnCodeLines, tcProcedureAbierto ; - , taBloquesExclusion, tnBloquesExclusion, tc_Comentario + , taLineasExclusion, tnBloquesExclusion, tc_Comentario - EXTERNAL ARRAY taCodeLines, tnBloquesExclusion, taBloquesExclusion + EXTERNAL ARRAY taCodeLines, tnBloquesExclusion, taLineasExclusion #IF .F. LOCAL toModulo AS CL_MODULO OF 'FOXBIN2PRG.PRG' @@ -5123,7 +5125,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base LOOP CASE .analizarBloque_PROCEDURE( @toModulo, @toClase, @loObjeto, @tcLine, @taCodeLines, @I, @tnCodeLines ; - , @tcProcedureAbierto, @tc_Comentario, @taBloquesExclusion, @tnBloquesExclusion ) + , @tcProcedureAbierto, @tc_Comentario, @taLineasExclusion, @tnBloquesExclusion ) *-- OJO: Esta se analiza primero a propósito, solo porque no puede estar detrás de PROTECTED y HIDDEN STORE .T. TO llCLASSCOMMENTS_Completed ; , llCLASS_PROPERTY_Completed ; @@ -5479,7 +5481,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base ******************************************************************************************************************* PROCEDURE analizarBloque_PROCEDURE LPARAMETERS toModulo, toClase, toObjeto, tcLine, taCodeLines, I, tnCodeLines, tcProcedureAbierto ; - , tc_Comentario, taBloquesExclusion, tnBloquesExclusion + , tc_Comentario, taLineasExclusion, tnBloquesExclusion #IF .F. LOCAL toModulo AS CL_MODULO OF 'FOXBIN2PRG.PRG' @@ -5514,7 +5516,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base IF llBloqueEncontrado *-- Evalúo todo el contenido del PROCEDURE THIS.analizarLineasDeProcedure( @toClase, @toObjeto, @tcLine, @taCodeLines, @I, @tnCodeLines, @tcProcedureAbierto ; - , @tc_Comentario, @taBloquesExclusion, @tnBloquesExclusion ) + , @tc_Comentario, @taLineasExclusion, @tnBloquesExclusion ) ENDIF RETURN llBloqueEncontrado @@ -5617,18 +5619,18 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base PROCEDURE identificarBloquesDeCodigo *-------------------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * taCodeLines (!@ IN ) El array con las líneas del código donde buscar - * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (!@ IN ) Array con las posiciones de inicio/fin de los bloques de exclusion - * tnBloquesExclusion (!@ IN ) Cantidad de bloques de exclusión + * taCodeLines (@! IN ) El array con las líneas del código donde buscar + * tnCodeLines (@! IN ) Cantidad de líneas de código + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no + * tnBloquesExclusion (@! IN ) Cantidad de bloques de exclusión * toModulo (@? OUT) Objeto con toda la información del módulo analizado * * NOTA: * Como identificador se usa el nombre de clase o de procedimiento, según corresponda. *-------------------------------------------------------------------------------------------------------------- - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toModulo + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toModulo - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toModulo AS CL_MODULO OF 'FOXBIN2PRG.PRG' @@ -5657,7 +5659,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base .set_Line( @lcLine, @taCodeLines, I ) DO CASE - CASE .lineaExcluida( I, tnBloquesExclusion, @taBloquesExclusion ) ; + CASE .lineaExcluida( I, tnBloquesExclusion, @taLineasExclusion ) ; OR .lineIsOnlyCommentAndNoMetadata( @lcLine, @lc_Comentario ) && Excluida, vacía o solo Comentarios CASE NOT llFoxBin2Prg_Completed AND .analizarBloque_FoxBin2Prg( toModulo, @lcLine, @taCodeLines, @I, tnCodeLines ) @@ -5676,7 +5678,7 @@ DEFINE CLASS c_conversor_prg_a_bin AS c_conversor_base llINCLUDE_SCX_Completed = .T. CASE .analizarBloque_DEFINE_CLASS( @toModulo, @loClase, @lcLine, @taCodeLines, @I, tnCodeLines ; - , @lcProcedureAbierto, @taBloquesExclusion, @tnBloquesExclusion, @lc_Comentario ) + , @lcProcedureAbierto, @taLineasExclusion, @tnBloquesExclusion, @lc_Comentario ) *-- Puede haber varias ENDCASE @@ -5731,7 +5733,7 @@ DEFINE CLASS c_conversor_prg_a_vcx AS c_conversor_prg_a_bin TRY LOCAL lnCodError, lcLine, laCodeLines(1), lnCodeLines ; - , laBloquesExclusion(1,2), lnBloquesExclusion, I + , laLineasExclusion(1), lnBloquesExclusion, I WITH THIS AS c_conversor_prg_a_vcx OF 'FOXBIN2PRG.PRG' STORE 0 TO lnCodError, lnCodeLines @@ -5747,10 +5749,10 @@ DEFINE CLASS c_conversor_prg_a_vcx AS c_conversor_prg_a_bin .createClasslib() *-- Identifico los TEXT/ENDTEXT, #IF .F./#ENDIF - .identificarBloquesDeExclusion( @laCodeLines, lnCodeLines, .F., @laBloquesExclusion, @lnBloquesExclusion ) + .identificarBloquesDeExclusion( @laCodeLines, lnCodeLines, .F., @laLineasExclusion, @lnBloquesExclusion ) *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo de cada clase - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toModulo ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toModulo ) .escribirArchivoBin( @toModulo, toFoxBin2Prg ) ENDWITH && THIS @@ -5765,7 +5767,7 @@ DEFINE CLASS c_conversor_prg_a_vcx AS c_conversor_prg_a_bin FINALLY USE IN (SELECT("TABLABIN")) - RELEASE lnCodError, lcLine, laCodeLines, lnCodeLines, laBloquesExclusion, lnBloquesExclusion, I + RELEASE lnCodError, lcLine, laCodeLines, lnCodeLines, laLineasExclusion, lnBloquesExclusion, I ENDTRY RETURN @@ -6035,7 +6037,7 @@ DEFINE CLASS c_conversor_prg_a_scx AS c_conversor_prg_a_bin TRY LOCAL lnCodError, laCodeLines(1), lnCodeLines, lnFB2P_Version ; - , laBloquesExclusion(1,2), lnBloquesExclusion, I + , laLineasExclusion(1), lnBloquesExclusion, I WITH THIS AS c_conversor_prg_a_scx OF 'FOXBIN2PRG.PRG' STORE 0 TO lnCodError, lnCodeLines, lnFB2P_Version @@ -6050,10 +6052,10 @@ DEFINE CLASS c_conversor_prg_a_scx AS c_conversor_prg_a_bin .createForm() *-- Identifico los TEXT/ENDTEXT, #IF .F./#ENDIF - .identificarBloquesDeExclusion( @laCodeLines, lnCodeLines, .F., @laBloquesExclusion, @lnBloquesExclusion ) + .identificarBloquesDeExclusion( @laCodeLines, lnCodeLines, .F., @laLineasExclusion, @lnBloquesExclusion ) *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo de cada clase - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toModulo ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toModulo ) .escribirArchivoBin( @toModulo, toFoxBin2Prg ) ENDWITH && THIS @@ -6344,7 +6346,7 @@ DEFINE CLASS c_conversor_prg_a_pjx AS c_conversor_prg_a_bin #ENDIF TRY - LOCAL laCodeLines(1), lnCodeLines, laBloquesExclusion(1,2), lnBloquesExclusion, I + LOCAL laCodeLines(1), lnCodeLines, laLineasExclusion(1), lnBloquesExclusion, I WITH THIS AS c_conversor_prg_a_pjx OF 'FOXBIN2PRG.PRG' STORE 0 TO lnCodeLines @@ -6359,10 +6361,10 @@ DEFINE CLASS c_conversor_prg_a_pjx AS c_conversor_prg_a_bin .createProject() *-- Identifico los TEXT/ENDTEXT, #IF .F./#ENDIF - *.identificarBloquesDeExclusion( @laCodeLines, .F., @laBloquesExclusion, @lnBloquesExclusion ) + *.identificarBloquesDeExclusion( @laCodeLines, .F., @laLineasExclusion, @lnBloquesExclusion ) *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo de cada clase - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toProject ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toProject ) .escribirArchivoBin( @toProject, toFoxBin2Prg ) ENDWITH && THIS @@ -6377,7 +6379,7 @@ DEFINE CLASS c_conversor_prg_a_pjx AS c_conversor_prg_a_bin FINALLY USE IN (SELECT("TABLABIN")) - RELEASE laCodeLines, lnCodeLines, laBloquesExclusion, lnBloquesExclusion, I + RELEASE laCodeLines, lnCodeLines, laLineasExclusion, lnBloquesExclusion, I ENDTRY RETURN @@ -6511,19 +6513,19 @@ DEFINE CLASS c_conversor_prg_a_pjx AS c_conversor_prg_a_bin ******************************************************************************************************************* PROCEDURE identificarBloquesDeCodigo - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toProject + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toProject *-------------------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * taCodeLines (!@ IN ) El array con las líneas del código donde buscar - * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (!@ IN ) Array con las posiciones de inicio/fin de los bloques de exclusion - * tnBloquesExclusion (!@ IN ) Cantidad de bloques de exclusión + * taCodeLines (@! IN ) El array con las líneas del código donde buscar + * tnCodeLines (@! IN ) Cantidad de líneas de código + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no + * tnBloquesExclusion (@! IN ) Cantidad de bloques de exclusión * toProject (@? OUT) Objeto con toda la información del proyecto analizado * * NOTA: * Como identificador se usa el nombre de clase o de procedimiento, según corresponda. *-------------------------------------------------------------------------------------------------------------- - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toProject AS CL_PROJECT OF 'FOXBIN2PRG.PRG' @@ -7131,7 +7133,7 @@ DEFINE CLASS c_conversor_prg_a_frx AS c_conversor_prg_a_bin TRY LOCAL lnCodError, loEx AS EXCEPTION, laCodeLines(1), lnCodeLines, lnFB2P_Version ; - , laBloquesExclusion(1,2), lnBloquesExclusion, I + , laLineasExclusion(1), lnBloquesExclusion, I WITH THIS AS c_conversor_prg_a_frx OF 'FOXBIN2PRG.PRG' STORE 0 TO lnCodError, lnCodeLines @@ -7146,7 +7148,7 @@ DEFINE CLASS c_conversor_prg_a_frx AS c_conversor_prg_a_bin .createReport() *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo del reporte - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toReport ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toReport ) .escribirArchivoBin( @toReport, toFoxBin2Prg ) ENDWITH && THIS @@ -7265,19 +7267,19 @@ DEFINE CLASS c_conversor_prg_a_frx AS c_conversor_prg_a_bin ******************************************************************************************************************* PROCEDURE identificarBloquesDeCodigo - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toReport + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toReport *-------------------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * taCodeLines (!@ IN ) El array con las líneas del código donde buscar * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (@? IN ) Sin uso - * tnBloquesExclusion (@? IN ) Sin uso + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no + * tnBloquesExclusion (@? IN ) Cantidad de bloques de exclusion * toReport (@? OUT) Objeto con toda la información del reporte analizado * * NOTA: * Como identificador se usa el nombre de clase o de procedimiento, según corresponda. *-------------------------------------------------------------------------------------------------------------- - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toReport AS CL_REPORT OF 'FOXBIN2PRG.PRG' @@ -7558,7 +7560,7 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin #ENDIF TRY - LOCAL lnCodError, loEx AS EXCEPTION, laCodeLines(1), lnCodeLines, laBloquesExclusion(1,2), lnBloquesExclusion, I + LOCAL lnCodError, loEx AS EXCEPTION, laCodeLines(1), lnCodeLines, laLineasExclusion(1), lnBloquesExclusion, I STORE 0 TO lnCodError, lnCodeLines WITH THIS AS c_conversor_prg_a_dbf OF 'FOXBIN2PRG.PRG' @@ -7568,7 +7570,7 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin toFoxBin2Prg.doBackup( .F., .T., '', '', '' ) *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo del reporte - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toTable ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toTable ) .escribirArchivoBin( @toTable, @toFoxBin2Prg ) ENDWITH && THIS @@ -7753,12 +7755,12 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * taCodeLines (!@ IN ) El array con las líneas del código donde buscar * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (@? IN ) Sin uso + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no * tnBloquesExclusion (@? IN ) Sin uso * toTable (@? OUT) Objeto con toda la información de la tabla analizada *-------------------------------------------------------------------------------------------------------------- - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toTable - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toTable + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toTable AS CL_DBF_TABLE OF 'FOXBIN2PRG.PRG' @@ -7843,7 +7845,7 @@ DEFINE CLASS c_conversor_prg_a_dbc AS c_conversor_prg_a_bin TRY LOCAL lnCodError, loEx AS EXCEPTION, loReg, lcLine, laCodeLines(1), lnCodeLines ; - , laBloquesExclusion(1,2), lnBloquesExclusion, I + , laLineasExclusion(1), lnBloquesExclusion, I STORE 0 TO lnCodError, lnCodeLines STORE '' TO lcLine STORE NULL TO loReg, toModulo @@ -7858,7 +7860,7 @@ DEFINE CLASS c_conversor_prg_a_dbc AS c_conversor_prg_a_bin *.createTable() *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo del reporte - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toDatabase ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toDatabase ) .escribirArchivoBin( @toDatabase, toFoxBin2Prg ) ENDWITH && THIS @@ -7926,15 +7928,15 @@ DEFINE CLASS c_conversor_prg_a_dbc AS c_conversor_prg_a_bin * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * taCodeLines (!@ IN ) El array con las líneas del código donde buscar * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (@? IN ) Sin uso + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no * tnBloquesExclusion (@? IN ) Sin uso * toDatabase (@? OUT) Objeto con toda la información de la base de datos analizada * * NOTA: * Como identificador se usa el nombre de clase o de procedimiento, según corresponda. *-------------------------------------------------------------------------------------------------------------- - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toDatabase - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toDatabase + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toDatabase AS CL_DBC OF 'FOXBIN2PRG.PRG' @@ -8018,7 +8020,7 @@ DEFINE CLASS c_conversor_prg_a_mnx AS c_conversor_prg_a_bin TRY LOCAL lnCodError, loEx AS EXCEPTION, loReg, lcLine, laCodeLines(1), lnCodeLines ; - , laBloquesExclusion(1,2), lnBloquesExclusion + , laLineasExclusion(1), lnBloquesExclusion STORE 0 TO lnCodError, lnCodeLines STORE '' TO lcLine @@ -8032,7 +8034,7 @@ DEFINE CLASS c_conversor_prg_a_mnx AS c_conversor_prg_a_bin .createMenu() *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo del reporte - .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laBloquesExclusion, lnBloquesExclusion, @toMenu ) + .identificarBloquesDeCodigo( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toMenu ) .escribirArchivoBin( @toMenu ) ENDWITH && THIS @@ -8060,15 +8062,15 @@ DEFINE CLASS c_conversor_prg_a_mnx AS c_conversor_prg_a_bin * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) * taCodeLines (!@ IN ) El array con las líneas del código donde buscar * tnCodeLines (!@ IN ) Cantidad de líneas de código - * taBloquesExclusion (@? IN ) Sin uso + * taLineasExclusion (@! IN ) Array unidimensional con un .T. o .F. según la línea sea de exclusión o no * tnBloquesExclusion (@? IN ) Sin uso * toMenu (@? OUT) Objeto con toda la información del menú analizado * * NOTA: * Como identificador se usa el nombre de clase o de procedimiento, según corresponda. *-------------------------------------------------------------------------------------------------------------- - LPARAMETERS taCodeLines, tnCodeLines, taBloquesExclusion, tnBloquesExclusion, toMenu - EXTERNAL ARRAY taCodeLines, taBloquesExclusion + LPARAMETERS taCodeLines, tnCodeLines, taLineasExclusion, tnBloquesExclusion, toMenu + EXTERNAL ARRAY taCodeLines, taLineasExclusion #IF .F. LOCAL toMenu AS CL_MENU OF 'FOXBIN2PRG.PRG' @@ -8646,7 +8648,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base *-- Bloque de código del método en su posición original TRY LOCAL lnLineCount, laLine(1), I, lnTextNodes, tcSorted, lnProtectedLine, lcMethod, lnLine_Len, lcLine, llProcOpen ; - , laBloquesExclusion(1,2), lnBloquesExclusion, laLineasDeExclusion(1) ; + , laLineasExclusion(1), lnBloquesExclusion ; , loEx AS EXCEPTION DIMENSION taMethods(1,3) STORE '' TO taMethods, tcSorted, taCode @@ -8693,7 +8695,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base ENDFOR *-- Identifico los TEXT/ENDTEXT, #IF .F./#ENDIF - THIS.identificarBloquesDeExclusion( @laLine, lnLineCount, .F., @laBloquesExclusion, @lnBloquesExclusion, @laLineasDeExclusion ) + THIS.identificarBloquesDeExclusion( @laLine, lnLineCount, .F., @laLineasExclusion, @lnBloquesExclusion ) *-- Analyze and count line methods, get method names and consolidate block code FOR I = 1 TO lnLineCount @@ -8704,7 +8706,7 @@ DEFINE CLASS c_conversor_bin_a_prg AS c_conversor_base lnLine_Len = LEN( laLine(I) ) DO CASE - CASE laLineasDeExclusion(I) + CASE laLineasExclusion(I) taCode(tnMethodCount) = taCode(tnMethodCount) + laLine(I) + CR_LF CASE lnTextNodes = 0 AND UPPER( LEFT(laLine(I), 10) ) == 'PROCEDURE ' From b3fbfa3f5415db6d5c6c5e813bd33b38a0308468 Mon Sep 17 00:00:00 2001 From: fdbozzo Date: Fri, 1 Aug 2014 21:36:37 +0200 Subject: [PATCH 4/5] Changeset: 387 fdbozzo - 01/08/2014 01:16:35: - Agregados casos de prueba para comprobar el nuevo array aLineasExclusion --- ...or_base__IdentificarBloquesDeExclusion.prg | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg b/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg index 2aa01e7..0b50c40 100644 --- a/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg +++ b/TESTS/ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion.prg @@ -27,7 +27,7 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as ******************************************************************************************************************************************* FUNCTION Evaluate_results - LPARAMETERS taExpected_Pos, taPos, tnPos_Count + LPARAMETERS taExpected_Pos, taPos, tnPos_Count, taLineasExclusion_Esperadas, taLineasExclusion LOCAL loObj AS c_conversor_base OF "FOXBIN2PRG.PRG" loObj = THIS.icObj @@ -37,11 +37,24 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as RETURN .T. ENDIF + *-- INFORMACIÓN THIS.messageout( "Pares de posiciones esperados: " + TRANSFORM(tnPos_Count) ) FOR I = 1 TO tnPos_Count THIS.messageout( "Posición de Inicio/Fin esperados: " + TRANSFORM(taExpected_Pos(I,1)) + ',' + TRANSFORM(taExpected_Pos(I,2)) ) ENDFOR + + THIS.messageout( "" ) + + IF TYPE( "taLineasExclusion",1 ) = "A" + FOR I = 1 TO ALEN(taLineasExclusion_Esperadas,1) + THIS.messageout( "Línea de exclusión " + STR(I,2) + " esperada: " + TRANSFORM( taLineasExclusion_Esperadas(I) ) ; + + IIF( taLineasExclusion_Esperadas(I), ' <', '' ) ) + ENDFOR + ENDIF + + THIS.messageout( REPLICATE("*",80) ) + *-- TESTS THIS.assertequals( ALEN(taExpected_Pos,1), ALEN(taPos,1), "Posición de Inicio/Fin" ) FOR I = 1 TO tnPos_Count @@ -49,12 +62,17 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as , TRANSFORM(taPos(I,1)) + ',' + TRANSFORM(taPos(I,2)) ; , "Posición de Inicio/Fin" ) ENDFOR + + IF TYPE( "taLineasExclusion",1 ) = "A" + THIS.assertequalsarrays( @taLineasExclusion_Esperadas, @taLineasExclusion, "Líneas de Exclusión" ) + ENDIF ENDFUNC ******************************************************************************************************************************************* FUNCTION Deberia_ObtenerLaUbicacionDelBloque_IF_ENDIF_CuandoCodigoCon_IF_ENDIF_predominante_esEvaluado - LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(2,2) + LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(2,2) ; + , laLineasExclusion(10), laLineasExclusion_Esperadas(10) LOCAL loObj AS c_conversor_prg_a_bin OF "FOXBIN2PRG.PRG" loObj = THIS.icObj @@ -64,6 +82,12 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as laExpected_Pos(1,2) = 5 laExpected_Pos(2,1) = 7 laExpected_Pos(2,2) = 9 + laLineasExclusion_Esperadas( 3) = .T. + laLineasExclusion_Esperadas( 4) = .T. + laLineasExclusion_Esperadas( 5) = .T. + laLineasExclusion_Esperadas( 7) = .T. + laLineasExclusion_Esperadas( 8) = .T. + laLineasExclusion_Esperadas( 9) = .T. TEXT TO lcMethod NOSHOW TEXTMERGE FLAGS 1 PRETEXT 1+2+4 <> myMethod_B @@ -81,16 +105,18 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laLineasExclusion, @lnPos_Count, @laPos ) - THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) + *-- Evaluación de resultados + THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count, @laLineasExclusion_Esperadas, @laLineasExclusion ) ENDFUNC ******************************************************************************************************************************************* FUNCTION Deberia_ObtenerLaUbicacionDelBloque_IF_ENDIF_Externo_CuandoCodigoCon_IF_ENDIF_predominante_esEvaluado - LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(1,2) + LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(1,2) ; + , laLineasExclusion(10), laLineasExclusion_Esperadas(10) LOCAL loObj AS c_conversor_prg_a_bin OF "FOXBIN2PRG.PRG" loObj = THIS.icObj @@ -98,6 +124,13 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as STORE '' TO lcMethod laExpected_Pos(1,1) = 3 laExpected_Pos(1,2) = 9 + laLineasExclusion_Esperadas( 3) = .T. + laLineasExclusion_Esperadas( 4) = .T. + laLineasExclusion_Esperadas( 5) = .T. + laLineasExclusion_Esperadas( 6) = .T. + laLineasExclusion_Esperadas( 7) = .T. + laLineasExclusion_Esperadas( 8) = .T. + laLineasExclusion_Esperadas( 9) = .T. TEXT TO lcMethod NOSHOW TEXTMERGE FLAGS 1 PRETEXT 1+2+4 <> myMethod_B @@ -115,16 +148,18 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laLineasExclusion, @lnPos_Count, @laPos ) - THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) + *-- Evaluación de resultados + THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count, @laLineasExclusion_Esperadas, @laLineasExclusion ) ENDFUNC ******************************************************************************************************************************************* FUNCTION Deberia_ObtenerLaUbicacionDelBloque_TEXT_ENDTEXT_CuandoCodigoCon_TEXT_ENDTEXT_predominante_esEvaluado - LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(2,2) + LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(2,2) ; + , laLineasExclusion(10), laLineasExclusion_Esperadas(10) LOCAL loObj AS c_conversor_prg_a_bin OF "FOXBIN2PRG.PRG" loObj = THIS.icObj @@ -134,6 +169,12 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as laExpected_Pos(1,2) = 5 laExpected_Pos(2,1) = 7 laExpected_Pos(2,2) = 9 + laLineasExclusion_Esperadas( 3) = .T. + laLineasExclusion_Esperadas( 4) = .T. + laLineasExclusion_Esperadas( 5) = .T. + laLineasExclusion_Esperadas( 7) = .T. + laLineasExclusion_Esperadas( 8) = .T. + laLineasExclusion_Esperadas( 9) = .T. TEXT TO lcMethod NOSHOW TEXTMERGE FLAGS 1 PRETEXT 1+2+4 <> myMethod_B @@ -151,9 +192,10 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laLineasExclusion, @lnPos_Count, @laPos ) - THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) + *-- Evaluación de resultados + THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count, @laLineasExclusion_Esperadas, @laLineasExclusion ) ENDFUNC @@ -237,7 +279,8 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as ******************************************************************************************************************************************* FUNCTION Deberia_NoEncontrarBloque_TEXT_ENDTEXT_CuandoEvaluaUnaLineaQueComienzaConUnCampoLlamado_Text_YLineaAnteriorTerminaEn_Coma - LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(1,2) + LOCAL lcMethod, laLineas(1), lnLineas, laPos(1,2), lnPos_Count, laExpected_Pos(1,2) ; + , laLineasExclusion(29), laLineasExclusion_Esperadas(29) LOCAL loObj AS c_conversor_prg_a_bin OF "FOXBIN2PRG.PRG" loObj = THIS.icObj @@ -245,6 +288,9 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as STORE '' TO lcMethod laExpected_Pos(1,1) = 4 laExpected_Pos(1,2) = 15 + FOR I = 4 TO 15 + laLineasExclusion_Esperadas(I) = .T. + ENDFOR TEXT TO lcMethod NOSHOW TEXTMERGE FLAGS 1 PRETEXT 1+2+4 <> myMethod_B @@ -281,9 +327,10 @@ DEFINE CLASS ut__foxbin2prg__c_conversor_base__IdentificarBloquesDeExclusion as lnLineas = ALINES( laLineas, lcMethod ) *-- Test - loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , , @lnPos_Count, @laPos ) + loObj.identificarBloquesDeExclusion( @laLineas, lnLineas, , @laLineasExclusion, @lnPos_Count, @laPos ) - THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count ) + *-- Evaluación de resultados + THIS.Evaluate_results( @laExpected_Pos, @laPos, lnPos_Count, @laLineasExclusion_Esperadas, @laLineasExclusion ) ENDFUNC From 693d50f8e473fc8efaa4f34a2e858450ed3474e6 Mon Sep 17 00:00:00 2001 From: fdbozzo Date: Fri, 1 Aug 2014 21:38:08 +0200 Subject: [PATCH 5/5] Changeset: 388 fdbozzo - 01/08/2014 21:36:38: - EXE --- foxbin2prg.exe | Bin 443506 -> 442980 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/foxbin2prg.exe b/foxbin2prg.exe index 7329f6bc6e39187c005f9d724a3c0af273256adb..e954cebb74f1a1b5411082a40db0f7efa747c677 100644 GIT binary patch delta 14910 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 delta 15389 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