On Wed, 01 Apr 2009, Szak�ts Viktor wrote:
> I've added clipper/rtlink recognition, but I miss the .lnk parser
> code, and to be frank I don't really know its exact details (used
> to use "FI hello1, hello2"), so if you happen to have some/any
> piece of such parser code I'll can tackle it to hbmk2.
I've just written such simple parser.
It does not check full syntax and try to only extract interesting parts:
file list, library list and output file name. Other commands are ignored.
It recognize comments and @included .lnk files.
It should work also with blinker .lnk scripts. I tried to merge both syntax.
I haven't made any deep analyzes of used syntax in both linkers and haven't
tried to replicate all existing and undocumented features but it should work
for valid .lnk scripts though probaly it can be confused by some extended
and not stripped commands. I was to lazy to add full list of blinker commands
to be sure they are well stripped. If user will report some problems with
example then we can update the parser if necessary.
Self contain code below. You can use it for some tests.
> How to name it? mingw / minimal / light / lite?
IMHO minimal. If possible it should have all .prg tools linked dynamically
to reduce the size.
best regards,
Przemek
proc main( ... )
local cCommandLine := "", cParam
local cFileOut := ""
local aFileList, aLibList
local lOK
set filecase lower
set dircase lower
set dirseparator "\"
/* take all parameters as rtlink/blinker ones
* here some local only parameters can be stripped if necessary
*/
for each cParam in hb_aParams()
cCommandLine += cParam + " "
next
altd()
lOK := rtlnk_process( cCommandLine, @cFileOut, @aFileList, @aLibList )
?
? iif( lOK, "linker parameters preporcessed correctly", ;
"error during preprocessing linker parameters" )
? "outputfile:", cFileOut
? "files: "
aeval( aFileList, {|f,i| iif( i > 1, qqout( ", " ), ), qqout( f ) } )
? "libraries: "
aeval( aLibList, {|f,i| iif( i > 1, qqout( ", " ), ), qqout( f ) } )
return
#define RTLNK_MODE_NONE 0
#define RTLNK_MODE_OUT 1
#define RTLNK_MODE_FILE 2
#define RTLNK_MODE_FILENEXT 3
#define RTLNK_MODE_LIB 4
#define RTLNK_MODE_LIBNEXT 5
#define RTLNK_MODE_SKIP 6
#define RTLNK_MODE_SKIPNEXT 7
static function rtlnk_read( cFileName, aPrevFiles )
local cFileBody
local cPath, cFile, cExt
local hFile
hb_FNameSplit( cFileName, @cPath, @cFile, @cExt )
if empty( cExt )
cExt := ".lnk"
endif
cFileName := hb_FNameMerge( cPath, cFile, ".lnk" )
/* it's blinker extnession, look for .lnk file in paths
* specified by LIB envvar
*/
if !hb_fileExists( cFileName ) .and. ;
!left( cFileName, 1 ) $ hb_osPathDelimiters() .and. ;
!substr( cFileName, 2, 1 ) == hb_osDriveSeparator()
for each cPath in hb_aTokens( getenv( "LIB" ), hb_osPathListSeparator() )
cFile := hb_FNameMerge( cPath, cFileName )
if hb_fileExists( cFile )
cFileName := cFile
exit
endif
next
endif
/* protection against recursive calls */
if ascan( aPrevFiles, { |x| x == cFileName } ) == 0
if ( hFile := fopen( cFileName ) ) != -1
cFileBody := space( fseek( hFile, 0, 2 ) )
fseek( hFile, 0, 0 )
if fread( hFile, @cFileBody, len( cFileBody ) ) != len( cFileBody )
cFileBody := NIL
endif
fclose( hFile )
endif
aadd( aPrevFiles, cFileName )
else
cFileBody := ""
endif
return cFileBody
static function rtlnk_process( cCommands, cFileOut, aFileList, aLibList, ;
aPrevFiles )
local nCh, nMode
local cLine, cWord
cCommands := strtran( strtran( cCommands, chr( 13 ) ), ",", " , " )
for each nCh in @cCommands
switch asc( nCh )
case 9
case 11
case 12
case asc( ";" )
nCh := " "
endswitch
next
nMode := RTLNK_MODE_NONE
if !valtype( aFileList ) == "A"
aFileList := {}
endif
if !valtype( aLibList ) == "A"
aLibList := {}
endif
if !valtype( aPrevFiles ) == "A"
aPrevFiles := {}
endif
for each cLine in hb_aTokens( cCommands, chr( 10 ) )
cLine := alltrim( cLine )
if !empty( cLine ) .and. !cLine = "#" .and. !cLine = "//"
if nMode == RTLNK_MODE_NONE
/* blinker extenssion */
if upper( cLine ) = "ECHO "
? "=>", substr( cLine, 6 )
loop
elseif upper( cLine ) = "BLINKER "
/* skip blinker commands */
loop
else /* TODO: add other blinker commands */
endif
endif
for each cWord in hb_aTokens( cLine )
if nMode == RTLNK_MODE_OUT
cFileOut := cWord
nMode := RTLNK_MODE_FILENEXT
elseif nMode == RTLNK_MODE_FILE
if !cWord == ","
if ascan( aFileList, { |x| x == cWord } ) == 0
aadd( aFileList, cWord )
endif
nMode := RTLNK_MODE_FILENEXT
endif
elseif nMode == RTLNK_MODE_LIB
if !cWord == ","
aadd( aLibList, cWord )
nMode := RTLNK_MODE_LIBNEXT
endif
elseif nMode == RTLNK_MODE_SKIP
if !cWord == ","
aadd( aLibList, cWord )
nMode := RTLNK_MODE_SKIPNEXT
endif
elseif cWord == ","
if nMode == RTLNK_MODE_FILENEXT
nMode := RTLNK_MODE_FILE
elseif nMode == RTLNK_MODE_LIBNEXT
nMode := RTLNK_MODE_LIB
elseif nMode == RTLNK_MODE_SKIPNEXT
nMode := RTLNK_MODE_SKIP
endif
elseif cWord = "@"
cWord := substr( cWord, 2 )
cCommands := rtlnk_read( @cWord, aPrevFiles )
if cCommands == NIL
? "cannot open:", cWord, "file."
return .f.
endif
if !rtlnk_process( cCommands, @cFileOut, @aFileList, @aLibList, ;
aPrevFiles )
return .f.
endif
else
cWord := upper( cWord )
if len( cWord ) >= 2
if "OUTPUT" = cWord
nMode := RTLNK_MODE_OUT
elseif "FILE" = cWord
nMode := RTLNK_MODE_FILE
elseif "LIBRARY" = cWord
nMode := RTLNK_MODE_LIB
elseif "MODULE" = cWord .or. ;
"EXCLUDE" = cWord .or. ;
"REFER" = cWord .or. ;
"INTO" = cWord
nMode := RTLNK_MODE_SKIP
endif
endif
endif
next
endif
next
return .t.
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour