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

Reply via email to