2009-06-22 20:38 UTC+0600 April White (april users.sourceforge.net)
* examples/hbextern/hbextern.prg
* significant re-implementation
; with no params will work like original version
; processes source files with LF terminators
; params to control: recursion, include 'conditions',
include classes, include class methods/etc
; execute with -? or --help
This commit is contained in:
@@ -17,6 +17,15 @@
|
||||
past entries belonging to author(s): Viktor Szakats.
|
||||
*/
|
||||
|
||||
2009-06-22 20:38 UTC+0600 April White (april users.sourceforge.net)
|
||||
* examples/hbextern/hbextern.prg
|
||||
* significant re-implementation
|
||||
; with no params will work like original version
|
||||
; processes source files with LF terminators
|
||||
; params to control: recursion, include 'conditions',
|
||||
include classes, include class methods/etc
|
||||
; execute with -? or --help
|
||||
|
||||
2009-06-23 02:19 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
|
||||
* utils/hbmk2/hbmk2.prg
|
||||
* Restored HB_COMPILE() first parameter. This time it's 'harbour'
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
#include "directry.ch"
|
||||
#include "fileio.ch"
|
||||
|
||||
ANNOUNCE HB_GTSYS
|
||||
REQUEST HB_GT_CGI_DEFAULT
|
||||
|
||||
// Remark this line when BEGINDUMP/ENDDUMP #pragma's
|
||||
// are not used anymore in Harbour core and RTL .prg files:
|
||||
// #define PRG_CAN_HAVE_HB_FUNC
|
||||
@@ -68,162 +71,574 @@
|
||||
|
||||
#ifdef __PLATFORM__UNIX
|
||||
#define PATH_SEPARATOR "/"
|
||||
#define BASE_DIR "../../source/"
|
||||
#define BASE_DIR "../../"
|
||||
#else
|
||||
#define PATH_SEPARATOR "\"
|
||||
#define BASE_DIR "..\..\source\"
|
||||
#define BASE_DIR "..\..\"
|
||||
#endif
|
||||
|
||||
// List of known files which does not contain any real public function.
|
||||
// (always write the LOWERCASE file name)
|
||||
STATIC s_aSkipList := { "profiler.prg" }
|
||||
STATIC s_aSkipFiles := { "profiler.prg" }
|
||||
STATIC s_aSkipDirs := { "tests", "example", "examples", "sample", "samples", ".svn", "%HB_ARCHITECTURE%", "codepage" }
|
||||
STATIC s_aSkipNames := { "MAIN" } // Init with names you want to skip
|
||||
STATIC s_aMethodAsProcedure := {}
|
||||
STATIC s_aConditions := {}
|
||||
|
||||
PROCEDURE MAIN()
|
||||
LOCAL aDirs :={ BASE_DIR + "debug", ;
|
||||
BASE_DIR + "pp" , ;
|
||||
BASE_DIR + "rdd" , ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "dbfcdx", ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "dbfdbt", ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "dbffpt", ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "dbfntx", ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "hbsix" , ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "hsx" , ;
|
||||
BASE_DIR + "rdd" + PATH_SEPARATOR + "nulsys", ;
|
||||
BASE_DIR + "rtl" , ;
|
||||
BASE_DIR + "vm" }
|
||||
LOCAL i, nOutput
|
||||
#define sw_BaseDir 1
|
||||
#define sw_Target 2
|
||||
#define sw_Verbose 3
|
||||
#define sw_Recursive 4
|
||||
#define sw_Case 5
|
||||
#define sw_ExcludeDuplicates 6
|
||||
#define sw_ExcludeEmptyFiles 7
|
||||
#define sw_ExcludeClasses 8
|
||||
#define sw_ExcludeClassMethods 9
|
||||
#define sw_ExcludeConditionals 10
|
||||
#define sw_ConditionalDepth 11
|
||||
#define sw_MimicHBExtern 12
|
||||
#define sw_ExcludeParams 13
|
||||
#define sw_SwitchesN 13
|
||||
|
||||
STATIC s_aSwitches[ sw_SwitchesN ]
|
||||
|
||||
PROCEDURE MAIN( ... )
|
||||
LOCAL aArgs := hb_AParams()
|
||||
LOCAL aDirs, i, nOutput, arg, cArgName
|
||||
|
||||
SET DATE FORMAT TO "yyyy-mm-dd"
|
||||
? "Processing files:"
|
||||
nOutput := FCREATE( "hbextern.ch_" )
|
||||
IF nOutput > 0
|
||||
FWRITE( nOutput, "// NOTE: Machine generated on: " + DTOC( DATE() ) + EOL + ;
|
||||
"// This output should be edited by hand after extraction." + EOL + EOL )
|
||||
FOR i := 1 TO LEN( aDirs )
|
||||
FWRITE( nOutput, EOL + "// " + REPLICATE( "-", 60 ) + EOL )
|
||||
FWRITE( nOutput, "// Files from: " + aDirs[ i ] + EOL + EOL )
|
||||
ProcessDir( nOutput, aDirs[i] + PATH_SEPARATOR + "*.c" , aDirs[ i ], .F. )
|
||||
ProcessDir( nOutput, aDirs[i] + PATH_SEPARATOR + "*.prg", aDirs[ i ], .T. )
|
||||
NEXT
|
||||
FWRITE( nOutput, EOL + "// " + REPLICATE( "-", 60 ) + EOL + EOL )
|
||||
FCLOSE( nOutput )
|
||||
|
||||
s_aSwitches[ sw_BaseDir ] := BASE_DIR
|
||||
s_aSwitches[ sw_Target ] := "hbextern.ch_"
|
||||
s_aSwitches[ sw_Verbose ] := 2
|
||||
s_aSwitches[ sw_Recursive ] := .F.
|
||||
s_aSwitches[ sw_Case ] := 1
|
||||
s_aSwitches[ sw_ExcludeDuplicates ] := .T.
|
||||
s_aSwitches[ sw_ExcludeEmptyFiles ] := .F.
|
||||
s_aSwitches[ sw_ExcludeClasses ] := .T.
|
||||
s_aSwitches[ sw_ExcludeClassMethods ] := .T.
|
||||
s_aSwitches[ sw_ExcludeConditionals ] := .T.
|
||||
s_aSwitches[ sw_ConditionalDepth ] := 0
|
||||
s_aSwitches[ sw_MimicHBExtern ] := .T.
|
||||
s_aSwitches[ sw_ExcludeParams ] := .T.
|
||||
|
||||
FOR EACH arg IN aArgs
|
||||
IF .NOT. Empty(arg)
|
||||
IF ( i := At( "=", arg ) ) == 0
|
||||
cArgName = arg
|
||||
arg = ""
|
||||
ELSE
|
||||
cArgName = SubStr(arg, 1, i - 1)
|
||||
arg = SubStr( arg, i + 1)
|
||||
ENDIF
|
||||
|
||||
DO CASE
|
||||
CASE cArgName == "-?" .OR. cArgName == "--help"
|
||||
ShowHelp()
|
||||
RETURN
|
||||
CASE cArgName == "-source" ; s_aSwitches[ sw_BaseDir ] := arg + IIf(SubStr(arg, -1, 1) == PATH_SEPARATOR, "", PATH_SEPARATOR)
|
||||
CASE cArgName == "-target" ; s_aSwitches[ sw_Target ] := arg
|
||||
CASE cArgName == "-recurse" .OR. ;
|
||||
cArgName == "-recursive" ; s_aSwitches[ sw_Recursive ] := ( arg == "+" .OR. arg == "1" .OR. arg == "yes" )
|
||||
CASE cArgName == "-skipdirs"
|
||||
s_aSkipDirs := FileToArray( arg )
|
||||
CASE cArgName == "-skipfiles"; s_aSkipFiles := FileToArray( arg )
|
||||
CASE cArgName == "-silent" ; s_aSwitches[ sw_Verbose ] := 0
|
||||
CASE cArgName == "-verbose"
|
||||
DO CASE
|
||||
CASE arg == "silent"; s_aSwitches[ sw_Verbose ] := 0
|
||||
CASE arg == "minimum"; s_aSwitches[ sw_Verbose ] := 1
|
||||
CASE arg == "maximum"; s_aSwitches[ sw_Verbose ] := 2
|
||||
OTHERWISE ; s_aSwitches[ sw_Verbose ] := 2
|
||||
END CASE
|
||||
CASE cArgName == "-case"
|
||||
DO CASE
|
||||
CASE arg == "upper"; s_aSwitches[ sw_Case ] := 1
|
||||
CASE arg == "lower"; s_aSwitches[ sw_Case ] := 2
|
||||
CASE arg == "unchanged"; s_aSwitches[ sw_Case ] := 0
|
||||
OTHERWISE ; s_aSwitches[ sw_Case ] := 1
|
||||
END CASE
|
||||
CASE cArgName == "-exclude" .OR. cArgName == "-include"
|
||||
DO CASE
|
||||
CASE arg == "all"
|
||||
s_aSwitches[ sw_ExcludeDuplicates ] := ( cArgName == "-exclude" )
|
||||
s_aSwitches[ sw_ExcludeEmptyFiles ] := ( cArgName == "-exclude" )
|
||||
s_aSwitches[ sw_ExcludeClasses ] := ( cArgName == "-exclude" )
|
||||
s_aSwitches[ sw_ExcludeClassMethods ] := ( cArgName == "-exclude" )
|
||||
s_aSwitches[ sw_ExcludeConditionals ] := ( cArgName == "-exclude" )
|
||||
s_aSwitches[ sw_ExcludeParams ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "duplicates" ; s_aSwitches[ sw_ExcludeDuplicates ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "empty-files" ; s_aSwitches[ sw_ExcludeEmptyFiles ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "classes" ; s_aSwitches[ sw_ExcludeClasses ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "class-methods" ; s_aSwitches[ sw_ExcludeClassMethods ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "conditionals" ; s_aSwitches[ sw_ExcludeConditionals ] := ( cArgName == "-exclude" )
|
||||
CASE arg == "params" ; s_aSwitches[ sw_ExcludeParams ] := ( cArgName == "-exclude" )
|
||||
OTHERWISE
|
||||
END CASE
|
||||
OTHERWISE
|
||||
END CASE
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
FOR i := 1 to Len(s_aSkipDirs)
|
||||
IF SubStr( s_aSkipDirs[i], 1, 1 ) == "%"
|
||||
s_aSkipDirs[i] := GetEnv( SubStr( s_aSkipDirs[i], 2, Len( s_aSkipDirs[i] ) - 1 ) )
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
AAdd( s_aSkipDirs, "." )
|
||||
AAdd( s_aSkipDirs, ".." )
|
||||
|
||||
s_aSwitches[ sw_MimicHBExtern ] := ;
|
||||
( ;
|
||||
s_aSwitches[ sw_ExcludeClasses ] .AND. ;
|
||||
s_aSwitches[ sw_ExcludeClassMethods ] ;
|
||||
)
|
||||
|
||||
IF s_aSwitches[ sw_ExcludeClasses ] .AND. .NOT. s_aSwitches[ sw_ExcludeClassMethods ]
|
||||
s_aSwitches[ sw_ExcludeClassMethods ] := .T.
|
||||
ENDIF
|
||||
? "Done."
|
||||
|
||||
IF s_aSwitches[ sw_Recursive ]
|
||||
|
||||
aDirs :={ ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "contrib", ;
|
||||
}
|
||||
|
||||
ELSE
|
||||
|
||||
aDirs :={ ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "debug", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "pp", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "dbfcdx", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "dbffpt", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "dbfnsx", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "dbfntx", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "hbsix", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "hsx", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "nulsys", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rdd" + PATH_SEPARATOR + "usrrdd", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "rtl", ;
|
||||
s_aSwitches[ sw_BaseDir ] + "source" + PATH_SEPARATOR + "vm", ;
|
||||
}
|
||||
|
||||
ENDIF
|
||||
|
||||
IF s_aSwitches[ sw_Verbose ] > 0; ? "Processing files:" ; ENDIF
|
||||
|
||||
#define YesOrNo(b) IIf((b), "Yes", "No")
|
||||
|
||||
nOutput := FCreate( s_aSwitches[ sw_Target ] )
|
||||
IF nOutput > 0
|
||||
FWrite( nOutput, "// NOTE: Machine generated on: " + DTOC( DATE() ) + EOL + ;
|
||||
"// This output should be edited by hand after extraction." + EOL + EOL )
|
||||
FWrite( nOutput, ;
|
||||
"/*" + EOL + ;
|
||||
" BaseDir" + "=" + s_aSwitches[ sw_BaseDir ] + EOL + ;
|
||||
" Recursive" + "=" + YesOrNo( s_aSwitches[ sw_Recursive ] ) + EOL + ;
|
||||
" Verbose" + "=" + { "silent", "minimum", "maximum" }[ s_aSwitches[ sw_Verbose ] + 1 ] + EOL + ;
|
||||
" Case" + "=" + { "unchanged", "upper", "lower" }[ s_aSwitches[ sw_Case ] + 1 ] + EOL + ;
|
||||
" Exclude duplicates" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeDuplicates ] ) + EOL + ;
|
||||
" Exclude empty files" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeEmptyFiles ] ) + EOL + ;
|
||||
" Exclude classes" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeClasses ] ) + EOL + ;
|
||||
" Exclude class methods" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeClassMethods ] ) + EOL + ;
|
||||
" Exclude conditionals" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeConditionals ] ) + EOL + ;
|
||||
" Exclude params" + "=" + YesOrNo( s_aSwitches[ sw_ExcludeParams ] ) + EOL + ;
|
||||
" Mimic HBExtern" + "=" + YesOrNo( s_aSwitches[ sw_MimicHBExtern ] ) + EOL + ;
|
||||
"*/" + EOL + ;
|
||||
EOL ;
|
||||
)
|
||||
FOR i := 1 TO LEN( aDirs )
|
||||
IF .NOT. Empty(aDirs[i])
|
||||
ProcessDir( nOutput, aDirs[i] )
|
||||
ENDIF
|
||||
NEXT
|
||||
FWrite( nOutput, EOL + "// " + Replicate( "-", 60 ) + EOL + EOL )
|
||||
|
||||
IF Len(s_aMethodAsProcedure) > 0
|
||||
FWrite( nOutput, "/*" + EOL + "Class methods defined as 'procedure':" + EOL )
|
||||
AEval(s_aMethodAsProcedure, {|ac| FWrite( nOutput, " " + ac[1] + " " + ac[2] + EOL ) } )
|
||||
FWrite( nOutput, "*/" + EOL + EOL )
|
||||
ENDIF
|
||||
|
||||
FClose( nOutput )
|
||||
ENDIF
|
||||
|
||||
IF s_aSwitches[ sw_Verbose ] > 0 ; ? "Done." ; ? ; END
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE ProcessDir( nOutput, cFiles, cDir, lPRG )
|
||||
STATIC PROCEDURE ShowHelp()
|
||||
LOCAL aHelp := { ;
|
||||
"Syntax: ", ;
|
||||
" hbextern [options]", ;
|
||||
"options:", ;
|
||||
" -source=<folder> // source folder, default is .." + PATH_SEPARATOR + "..", ;
|
||||
" -target=<filename> // target file, default is hbextern.ch_", ;
|
||||
" -recurse=[yes|no] // perform recursively, default is no", ;
|
||||
" -skipdirs=<filename> // configuration file of folders to bypass, default:", ;
|
||||
{|| AEval( s_aSkipDirs, {|c| OutStd( IIf( Empty(c), "", " " + c ) + hb_osNewLine() ) } ) }, ;
|
||||
" -skipfiles=<filename> // configuration file of files to bypass, default:", ;
|
||||
{|| AEval( s_aSkipFiles, {|c| OutStd( IIf( Empty(c), "", " " + c ) + hb_osNewLine() ) } ) }, ;
|
||||
" -verbose=[silent|minimum|maximum] // verbose operation, default is maximum", ;
|
||||
" -silent // synonym for verbose=silent", ;
|
||||
" -case=[upper|lower|unchanged] // output case, default is upper", ;
|
||||
" -include=<switch> // sets <switch> on", ;
|
||||
" -exclude=<switch> // sets <switch> off", ;
|
||||
"switches:", ;
|
||||
" all // all switches are set", ;
|
||||
" duplicates // default is on", ;
|
||||
" empty-files // default is off", ;
|
||||
" classes // default is off", ;
|
||||
" class-methods // default is off", ;
|
||||
" conditionals // default is off", ;
|
||||
" params // default is off", ;
|
||||
/* " ", */ ;
|
||||
}
|
||||
|
||||
// using hbmk2 style
|
||||
AEval( aHelp, {|x| IIf( ValType( x ) == "B", Eval( x ), OutStd( IIf( Empty(x), "", x ) + hb_osNewLine() ) ) } )
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE ProcessDir( nOutput, cDir )
|
||||
LOCAL i, nLen, aFiles
|
||||
|
||||
aFiles := DIRECTORY( cFiles )
|
||||
IF s_aSwitches[ sw_Verbose ] > 0 ; ? cDir ; ENDIF
|
||||
|
||||
IF .NOT. s_aSwitches[ sw_ExcludeEmptyFiles ]
|
||||
FWrite( nOutput, EOL + "// " + Replicate( "-", 60 ) + EOL )
|
||||
FWrite( nOutput, "// Files from: " + cDir + EOL + EOL )
|
||||
ENDIF
|
||||
|
||||
cDir += PATH_SEPARATOR
|
||||
|
||||
aFiles := Directory( cDir + "*.*", "D" )
|
||||
IF ( nLen := LEN( aFiles ) ) > 0
|
||||
ASORT( aFiles,,, {|x,y| x[ F_NAME ] < y[ F_NAME ] } )
|
||||
// Sort C files before PRG files before folders; this mimics HBExtern
|
||||
ASort( aFiles,,, {|x,y| ;
|
||||
IIf( x[ F_ATTR ] == "D", Chr(255), SubStr( x[ F_NAME ], At( ".", x[ F_NAME ] ) ) ) + x[ F_NAME ] < IIf( y[ F_ATTR ] == "D", Chr(255), SubStr( y[ F_NAME ], At( ".", y[ F_NAME ] ) ) ) + y[ F_NAME ] ;
|
||||
} )
|
||||
FOR i := 1 TO nLen
|
||||
ProcessFile( nOutput, cDir + PATH_SEPARATOR + aFiles[ i ][ 1 ], lPRG )
|
||||
IF aFiles[ i ][F_ATTR ] == "D"
|
||||
IF s_aSwitches[ sw_Recursive ] .AND. ;
|
||||
AScan( s_aSkipDirs, {|d| Lower(d) == Lower( aFiles[ i ][ F_NAME ] ) } ) == 0
|
||||
ProcessDir( nOutput, cDir + aFiles[ i ][ F_NAME ] )
|
||||
ENDIF
|
||||
ELSEIF Upper( SubStr( aFiles[ i ][ F_NAME ], -4 ) ) == ".PRG"
|
||||
ProcessFile( nOutput, cDir + aFiles[ i ][ F_NAME ], .T. )
|
||||
ELSEIF Upper( SubStr( aFiles[ i ][ F_NAME ], -2 ) ) == ".C"
|
||||
ProcessFile( nOutput, cDir + aFiles[ i ][ F_NAME ], .F. )
|
||||
ENDIF
|
||||
NEXT
|
||||
ENDIF
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION FileToArray( cFile )
|
||||
LOCAL nH
|
||||
LOCAL aResult := {}
|
||||
|
||||
nH := FOpen( cFile )
|
||||
IF nH > 0
|
||||
FileEval( nH, 255, {|c| AAdd( aResult, c ) } )
|
||||
FClose( nH )
|
||||
ELSE
|
||||
IF s_aSwitches[ sw_Verbose ] > 0 ; ? "Could not open [" + cFile + "], error" + hb_ntos( nH ) ; ENDIF
|
||||
END
|
||||
|
||||
RETURN aResult
|
||||
|
||||
STATIC PROCEDURE ProcessFile( nOutput, cFile, lPRG )
|
||||
LOCAL nH
|
||||
LOCAL bOutputHeader
|
||||
LOCAL cHeader
|
||||
|
||||
// Skip known files which does not contain any real public function
|
||||
IF ASCAN( s_aSkipList, {|c| c $ lower( cFile ) } ) > 0
|
||||
IF AScan( s_aSkipFiles, {|c| lower(c) $ lower( cFile ) } ) > 0
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
? cFile
|
||||
FWRITE( nOutput, "//" + EOL + "// symbols from file: " + cFile + EOL + "//" + EOL )
|
||||
nH := FOPEN( cFile )
|
||||
IF nH > 0
|
||||
FILEEVAL( nH, 255, EOL, {|c| Processline( nOutput, c, lPRG ) } )
|
||||
FCLOSE( nH )
|
||||
IF s_aSwitches[ sw_Verbose ] > 1 ; ? cFile ; ENDIF
|
||||
|
||||
cHeader := "//" + EOL + "// symbols from file: " + cFile + EOL + "//" + EOL
|
||||
|
||||
IF .NOT. s_aSwitches[ sw_ExcludeEmptyFiles ]
|
||||
FWrite( nOutput, cHeader )
|
||||
bOutputHeader := .F.
|
||||
ELSE
|
||||
bOutputHeader := .T.
|
||||
ENDIF
|
||||
|
||||
nH := FOpen( cFile )
|
||||
IF nH > 0
|
||||
FileEval( nH, 255, {|c| ProcessLine( nOutput, cFile, c, lPRG, @bOutputHeader, @cHeader ) } )
|
||||
FClose( nH )
|
||||
FWrite( nOutput, Replicate( "#endif" + EOL, s_aSwitches[ sw_ConditionalDepth ] ) )
|
||||
s_aSwitches[ sw_ConditionalDepth ] := 0
|
||||
ELSE
|
||||
IF s_aSwitches[ sw_Verbose ] > 0 ; ? "Could not process [" + cFile + "], error " + hb_ntos(nH) ; ENDIF
|
||||
ENDIF
|
||||
|
||||
ASize( s_aConditions, 0 )
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE ProcessLine( nOutput, cLine, lPRG )
|
||||
LOCAL nPos, nLen
|
||||
STATIC FUNCTION Parse(cVar, xDelimiter)
|
||||
LOCAL cResult
|
||||
LOCAL idx
|
||||
|
||||
IF ValType(xDelimiter) == "N"
|
||||
cResult := SubStr( cVar, 1, xDelimiter )
|
||||
cVar := SubStr( cVar, xDelimiter + 1 )
|
||||
ELSE
|
||||
IF ( idx := At( xDelimiter, cVar ) ) == 0
|
||||
cResult := cVar
|
||||
cVar := ""
|
||||
ELSE
|
||||
cResult := SubStr( cVar, 1, idx - 1 )
|
||||
cVar := SubStr( cVar, idx + Len(xDelimiter) )
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
RETURN cResult
|
||||
|
||||
STATIC FUNCTION Split(cVar, cDelimiter)
|
||||
LOCAL aResult := {}
|
||||
LOCAL clVar := cVar
|
||||
|
||||
DO WHILE Len(clVar) > 0
|
||||
AAdd(aResult, Parse( @clVar, cDelimiter ) )
|
||||
ENDDO
|
||||
|
||||
RETURN aResult
|
||||
|
||||
STATIC FUNCTION RemoveComments(cLine)
|
||||
LOCAL cResult := Trim(cLine)
|
||||
LOCAL idx
|
||||
LOCAL idx2
|
||||
|
||||
IF SubStr( cLine, 1, 1 ) == "*" .OR. SubStr( cLine, 1, 2 ) == "&&"
|
||||
cResult := ""
|
||||
ELSEIF ( idx := At( "//", cResult ) ) > 0
|
||||
cResult := SubStr( cResult, 1, idx - 1 )
|
||||
END
|
||||
|
||||
DO WHILE ( idx := At( "/*", cResult ) ) > 0
|
||||
IF ( idx2 := At( "*/", cResult ) ) == 0 ; idx2 := Len(cResult) ; ENDIF
|
||||
cResult := SubStr( cResult, 1, idx - 1 ) + SubStr( cResult, idx2 + 2 )
|
||||
ENDDO
|
||||
|
||||
RETURN cResult
|
||||
|
||||
|
||||
STATIC PROCEDURE ProcessLine( nOutput, cFile, cLine, lPRG, bOutputHeader, cHeader )
|
||||
STATIC s_cMethodType, s_lVisible, s_FullLine := ""
|
||||
LOCAL nPos, nLen, aUnits
|
||||
|
||||
cLine := AllTrim( cLine )
|
||||
IF empty( cLine )
|
||||
IF Empty( cLine )
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
IF lPRG // PRG source file (FUNC, PROC)
|
||||
IF SubStr( cLine, -1, 1 ) == IIf( lPRG, ";", "\" )
|
||||
s_FullLine += AllTrim( SubStr( cLine, 1, Len( cLine ) - 1 ) )
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
IF upper( SubStr( cLine, 1, 4 ) ) == "FUNC" .or. upper( SubStr( cLine, 1, 4 ) ) == "PROC"
|
||||
IF ( nPos := AT( " ", cLine ) ) > 4
|
||||
cLine := s_FullLine + cLine
|
||||
s_FullLine := ""
|
||||
|
||||
IF lPRG // PRG source file (FUNC, PROC, CLASS)
|
||||
|
||||
IF .NOT. s_aSwitches[ sw_ExcludeConditionals ] .AND. SubStr( cLine, 1, 1 ) == "#"
|
||||
IF SubStr( cLine, 1, 2 ) == "# "
|
||||
cLine := "#" + LTrim( SubStr( cLine, 2 ) )
|
||||
ENDIF
|
||||
|
||||
IF .F.
|
||||
/*
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#include" ) ) ) == "#include"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#define" ) ) ) == "#define"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#undef" ) ) ) == "#undef"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#pragma " ) ) ) == "#pragma "
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#command" ) ) ) == "#command"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#xcommand" ) ) ) == "#xcommand"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#translate" ) ) ) == "#translate"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#xtrans" ) ) ) == "#xtrans"
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#error " ) ) ) == "#error "
|
||||
*/
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#if" ) ) ) == "#if"
|
||||
AAdd( s_aConditions, cLine )
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#elif" ) ) ) == "#elif"
|
||||
s_aConditions[ Len( s_aConditions ) ] := cLine
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#else" ) ) ) == "#else"
|
||||
IF s_aSwitches[ sw_ConditionalDepth ] > 0
|
||||
FWrite( nOutput, "#else" + EOL )
|
||||
ENDIF
|
||||
s_aConditions[ Len( s_aConditions ) ] := cLine
|
||||
ELSEIF Lower( SubStr( cLine, 1, Len( "#endif" ) ) ) == "#endif"
|
||||
IF s_aSwitches[ sw_ConditionalDepth ] > 0
|
||||
FWrite( nOutput, "#endif" + EOL )
|
||||
s_aSwitches[ sw_ConditionalDepth ]--
|
||||
ENDIF
|
||||
ASize( s_aConditions, Len( s_aConditions ) - 1 )
|
||||
//~ ELSE
|
||||
//~ ? cLine
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF Upper( SubStr( cLine, 1, Len( "FUNC " ) ) ) == "FUNC " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "PROC " ) ) ) == "PROC " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "FUNCTION " ) ) ) == "FUNCTION " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "PROCEDURE " ) ) ) == "PROCEDURE " .OR. ;
|
||||
.NOT. s_aSwitches[ sw_ExcludeClasses ] .AND. ;
|
||||
( ;
|
||||
Upper( SubStr( cLine, 1, Len( "CLASS " ) ) ) == "CLASS " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "CREATE CLASS " ) ) ) == "CREATE CLASS " ;
|
||||
) .OR. ;
|
||||
.F.
|
||||
|
||||
DO CASE
|
||||
CASE Upper( SubStr( cLine, 1, Len( "CLASS " ) ) ) == "CLASS "
|
||||
s_cMethodType := "CLASS"
|
||||
s_lVisible := .T. // TODO: what is the default visibility of methods
|
||||
CASE Upper( SubStr( cLine, 1, Len( "CREATE CLASS " ) ) ) == "CREATE CLASS "
|
||||
s_cMethodType := "CLASS"
|
||||
cLine := SubStr( cLine, Len("CREATE ") + 1 )
|
||||
s_lVisible := .T. // TODO: what is the default visibility of methods
|
||||
OTHERWISE
|
||||
s_cMethodType = Upper( SubStr( cLine, 1, 4 ) )
|
||||
END
|
||||
|
||||
aUnits := Split(RemoveComments(cLine), " ")
|
||||
IF Upper( SubStr( cLine, 1, Len( "PROC" ) ) ) == "PROC" .AND. Len(aUnits) > 1 .AND. Upper( aUnits[ Len( aUnits ) - 1 ] ) == "CLASS"
|
||||
AAdd(s_aMethodAsProcedure, { cFile, cLine } )
|
||||
ELSEIF ( nPos := AT( " ", cLine ) ) > 4
|
||||
cLine := LTrim( SubStr( cLine, nPos ) )
|
||||
nLen := len( cLine )
|
||||
FOR nPos := 1 TO nLen
|
||||
IF SubStr( cLine, nPos, 1 ) $ " (;/&" + Chr( 9 )
|
||||
--nPos
|
||||
EXIT
|
||||
ENDIF
|
||||
IF SubStr( cLine, nPos, 1 ) $ " (;/&" + Chr( 9 )
|
||||
--nPos
|
||||
EXIT
|
||||
ENDIF
|
||||
NEXT
|
||||
WriteSymbol( nOutput, SubStr( cLine, 1, nPos ) )
|
||||
WriteSymbol( nOutput, SubStr( cLine, 1, nPos ), s_cMethodType + " " + RemoveComments( SubStr( cLine, nPos + 1 ) ), @bOutputHeader, @cHeader )
|
||||
ENDIF
|
||||
ELSEIF s_cMethodType == "CLASS"
|
||||
cLine := RemoveComments(cLine)
|
||||
IF Upper( SubStr( cLine, 1, Len( "HIDDEN:" ) ) ) == "HIDDEN:"
|
||||
s_lVisible := .F.
|
||||
ELSEIF Upper( SubStr( cLine, 1, Len( "EXPORTED:" ) ) ) == "EXPORTED:"
|
||||
s_lVisible := .T.
|
||||
ELSEIF Upper( SubStr( cLine, 1, Len( "VAR " ) ) ) == "VAR " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "DATA " ) ) ) == "DATA " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "METHOD " ) ) ) == "METHOD " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "ACCESS " ) ) ) == "ACCESS " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "ASSIGN " ) ) ) == "ASSIGN " .OR. ;
|
||||
Upper( SubStr( cLine, 1, Len( "FRIEND " ) ) ) == "FRIEND "
|
||||
IF s_lVisible .AND. .NOT. s_aSwitches[ sw_ExcludeClassMethods ]
|
||||
cLine := Parse( @cLine, " INIT " )
|
||||
cLine := Parse( @cLine, " INLINE " )
|
||||
cLine := Trim( cLine )
|
||||
WriteSymbol( nOutput, " " + cLine, ""/*s_cMethodType*/, @bOutputHeader, @cHeader ) // SubStr( cLine, 1, nPos ), s_cMethodType )
|
||||
ENDIF
|
||||
ELSEIF Upper( SubStr( cLine, 1, Len( "ENDCLASS" ) ) ) == "ENDCLASS"
|
||||
s_cMethodType := ""
|
||||
ENDIF
|
||||
|
||||
ENDIF
|
||||
|
||||
#ifdef PRG_CAN_HAVE_HB_FUNC
|
||||
ENDIF
|
||||
#else
|
||||
ELSE // C source file (HB_FUNC)
|
||||
#endif
|
||||
#ENDIF
|
||||
|
||||
IF SubStr( cLine, 1, 8 ) == "HB_FUNC("
|
||||
cLine := SubStr( cLine, 9 )
|
||||
IF ( nPos := AT( ")", cLine ) ) > 0
|
||||
WriteSymbol( nOutput, AllTrim( SubStr( cLine, 1, nPos - 1 ) ) )
|
||||
WriteSymbol( nOutput, AllTrim( SubStr( cLine, 1, nPos - 1 ) ), "C function", @bOutputHeader, @cHeader )
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
#ifndef PRG_CAN_HAVE_HB_FUNC
|
||||
ENDIF
|
||||
#endif
|
||||
#ENDIF
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE FileEval( nHandle, nMaxLine, bBlock )
|
||||
LOCAL cBuffer
|
||||
|
||||
STATIC PROCEDURE FileEval( nHandle, nMaxLine, cDelim, bBlock )
|
||||
LOCAL cBuffer := ""
|
||||
FSeek( nHandle, 0 )
|
||||
|
||||
FSEEK( nHandle, 0 )
|
||||
|
||||
DO WHILE FReadLn( nHandle, @cBuffer, nMaxLine, cDelim )
|
||||
EVAL( bBlock, cBuffer )
|
||||
DO WHILE FReadLn( nHandle, @cBuffer, nMaxLine )
|
||||
Eval( bBlock, cBuffer )
|
||||
ENDDO
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION FReadLn( nHandle, cBuffer, nMaxLine )
|
||||
STATIC s_aEOL := { chr(13) + chr(10), chr(10), chr(13) }
|
||||
LOCAL cLine, nSavePos, nEol, nNumRead, nLenEol, idx
|
||||
|
||||
STATIC FUNCTION FReadLn( nHandle, cBuffer, nMaxLine, cDelim )
|
||||
LOCAL cLine, nSavePos, nEol, nNumRead
|
||||
|
||||
cLine := space( nMaxLine )
|
||||
cBuffer := ""
|
||||
nSavePos := FSEEK( nHandle, 0, FS_RELATIVE )
|
||||
nNumRead := FREAD( nHandle, @cLine, nMaxLine )
|
||||
IF ( nEol := AT( cDelim, substr( cLine, 1, nNumRead ) ) ) == 0
|
||||
cBuffer := cLine
|
||||
|
||||
nSavePos := FSeek( nHandle, 0, FS_RELATIVE )
|
||||
cLine := space( nMaxLine )
|
||||
nNumRead := FRead( nHandle, @cLine, Len( cLine ) )
|
||||
cLine := SubStr( cLine, 1, nNumRead )
|
||||
|
||||
nEol := 0
|
||||
FOR idx := 1 To Len(s_aEOL)
|
||||
// TOFIX: if the last character is CR check if next character is LF
|
||||
IF ( nEol := At( s_aEOL[ idx ], cLine ) ) > 0
|
||||
nLenEol := Len( s_aEOL[ idx ] ) - 1
|
||||
Exit
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
IF nEol == 0
|
||||
cBuffer := cLine
|
||||
ELSE
|
||||
cBuffer := SubStr( cLine, 1, nEol - 1 )
|
||||
FSEEK( nHandle, nSavePos + nEol + 1, FS_SET )
|
||||
cBuffer := SubStr( cLine, 1, nEol - 1 )
|
||||
FSeek( nHandle, nSavePos + nEol + nLenEol, FS_SET )
|
||||
ENDIF
|
||||
|
||||
RETURN nNumRead != 0
|
||||
|
||||
STATIC PROCEDURE WriteSymbol( nOutput, cLine, cMethodType, bOutputHeader, cHeader )
|
||||
IF Len( cLine ) > 0
|
||||
IF s_aSwitches[ sw_Case ] == 1
|
||||
cLine := Upper( cLine )
|
||||
ELSEIF s_aSwitches[ sw_Case ] == 2
|
||||
cLine := Lower( cLine )
|
||||
ENDIF
|
||||
IF AScan( s_aSkipNames , {|c| Upper(c) == Upper(cLine) } ) == 0
|
||||
IF bOutputHeader
|
||||
FWrite( nOutput, cHeader )
|
||||
bOutputHeader := .F.
|
||||
ENDIF
|
||||
|
||||
STATIC PROCEDURE WriteSymbol( nOutput, cLine )
|
||||
STATIC s_aNames := { "MAIN" } // Init with names you want to skip
|
||||
IF s_aSwitches[ sw_ExcludeDuplicates ]
|
||||
AAdd( s_aSkipNames, cLine )
|
||||
ENDIF
|
||||
|
||||
IF len( cLine ) > 0
|
||||
cLine := upper( cLine )
|
||||
IF ASCAN( s_aNames, {|c| c == cLine } ) == 0
|
||||
AADD( s_aNames, cLine )
|
||||
FWRITE( nOutput, "EXTERNAL " + cLine + EOL )
|
||||
IF cMethodType <> "C function"
|
||||
IF s_aSwitches[ sw_ConditionalDepth ] == 0
|
||||
AEval( s_aConditions, {|c| s_aSwitches[ sw_ConditionalDepth ]++, FWrite( nOutput, c + EOL ) } )
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF s_aSwitches[ sw_MimicHBExtern ].OR. Empty(cMethodType) .OR. s_aSwitches[ sw_ExcludeClassMethods ]
|
||||
cMethodType = ""
|
||||
ELSEIF .NOT. s_aSwitches[ sw_ExcludeClassMethods ]
|
||||
cMethodType = " // " + cMethodType
|
||||
ENDIF
|
||||
|
||||
FWrite( nOutput, "EXTERNAL " + cLine + cMethodType + EOL )
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
|
||||
Reference in New Issue
Block a user