ldAout.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # ldAout.tcl --
  2. #
  3. # This "tclldAout" procedure in this script acts as a replacement
  4. # for the "ld" command when linking an object file that will be
  5. # loaded dynamically into Tcl or Tk using pseudo-static linking.
  6. #
  7. # Parameters:
  8. # The arguments to the script are the command line options for
  9. # an "ld" command.
  10. #
  11. # Results:
  12. # The "ld" command is parsed, and the "-o" option determines the
  13. # module name.  ".a" and ".o" options are accumulated.
  14. # The input archives and object files are examined with the "nm"
  15. # command to determine whether the modules initialization
  16. # entry and safe initialization entry are present.  A trivial
  17. # C function that locates the entries is composed, compiled, and
  18. # its .o file placed before all others in the command; then
  19. # "ld" is executed to bind the objects together.
  20. #
  21. # RCS: @(#) $Id: ldAout.tcl,v 1.5 2001/09/28 01:21:53 dgp Exp $
  22. #
  23. # Copyright (c) 1995, by General Electric Company. All rights reserved.
  24. #
  25. # See the file "license.terms" for information on usage and redistribution
  26. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  27. #
  28. # This work was supported in part by the ARPA Manufacturing Automation
  29. # and Design Engineering (MADE) Initiative through ARPA contract
  30. # F33615-94-C-4400.
  31. proc tclLdAout {{cc {}} {shlib_suffix {}} {shlib_cflags none}} {
  32.     global env
  33.     global argv
  34.     if {[string equal $cc ""]} {
  35. set cc $env(CC)
  36.     }
  37.     # if only two parameters are supplied there is assumed that the
  38.     # only shlib_suffix is missing. This parameter is anyway available
  39.     # as "info sharedlibextension" too, so there is no need to transfer
  40.     # 3 parameters to the function tclLdAout. For compatibility, this
  41.     # function now accepts both 2 and 3 parameters.
  42.     if {[string equal $shlib_suffix ""]} {
  43. set shlib_cflags $env(SHLIB_CFLAGS)
  44.     } elseif {[string equal $shlib_cflags "none"]} {
  45. set shlib_cflags $shlib_suffix
  46.     }
  47.     # seenDotO is nonzero if a .o or .a file has been seen
  48.     set seenDotO 0
  49.     # minusO is nonzero if the last command line argument was "-o".
  50.     set minusO 0
  51.     # head has command line arguments up to but not including the first
  52.     # .o or .a file. tail has the rest of the arguments.
  53.     set head {}
  54.     set tail {}
  55.     # nmCommand is the "nm" command that lists global symbols from the
  56.     # object files.
  57.     set nmCommand {|nm -g}
  58.     # entryProtos is the table of _Init and _SafeInit prototypes found in the
  59.     # module.
  60.     set entryProtos {}
  61.     # entryPoints is the table of _Init and _SafeInit entries found in the
  62.     # module.
  63.     set entryPoints {}
  64.     # libraries is the list of -L and -l flags to the linker.
  65.     set libraries {}
  66.     set libdirs {}
  67.     # Process command line arguments
  68.     foreach a $argv {
  69. if {!$minusO && [regexp {.[ao]$} $a]} {
  70.     set seenDotO 1
  71.     lappend nmCommand $a
  72. }
  73. if {$minusO} {
  74.     set outputFile $a
  75.     set minusO 0
  76. } elseif {![string compare $a -o]} {
  77.     set minusO 1
  78. }
  79. if {[regexp {^-[lL]} $a]} {
  80.     lappend libraries $a
  81.     if {[regexp {^-L} $a]} {
  82. lappend libdirs [string range $a 2 end]
  83.     }
  84. } elseif {$seenDotO} {
  85.     lappend tail $a
  86. } else {
  87.     lappend head $a
  88. }
  89.     }
  90.     lappend libdirs /lib /usr/lib
  91.     # MIPS -- If there are corresponding G0 libraries, replace the
  92.     # ordinary ones with the G0 ones.
  93.     set libs {}
  94.     foreach lib $libraries {
  95. if {[regexp {^-l} $lib]} {
  96.     set lname [string range $lib 2 end]
  97.     foreach dir $libdirs {
  98. if {[file exists [file join $dir lib${lname}_G0.a]]} {
  99.     set lname ${lname}_G0
  100.     break
  101. }
  102.     }
  103.     lappend libs -l$lname
  104. } else {
  105.     lappend libs $lib
  106. }
  107.     }
  108.     set libraries $libs
  109.     # Extract the module name from the "-o" option
  110.     if {![info exists outputFile]} {
  111. error "-o option must be supplied to link a Tcl load module"
  112.     }
  113.     set m [file tail $outputFile]
  114.     if {[regexp {.a$} $outputFile]} {
  115. set shlib_suffix .a
  116.     } else {
  117. set shlib_suffix ""
  118.     }
  119.     if {[regexp {..*$} $outputFile match]} {
  120. set l [expr {[string length $m] - [string length $match]}]
  121.     } else {
  122. error "Output file does not appear to have a suffix"
  123.     }
  124.     set modName [string tolower $m 0 [expr {$l-1}]]
  125.     if {[regexp {^lib} $modName]} {
  126. set modName [string range $modName 3 end]
  127.     }
  128.     if {[regexp {[0-9.]*(_g0)?$} $modName match]} {
  129. set modName [string range $modName 0 [expr {[string length $modName]-[string length $match]-1}]]
  130.     }
  131.     set modName [string totitle $modName]
  132.     # Catalog initialization entry points found in the module
  133.     set f [open $nmCommand r]
  134.     while {[gets $f l] >= 0} {
  135. if {[regexp {T[  ]*_?([A-Z][a-z0-9_]*_(Safe)?Init(__FP10Tcl_Interp)?)$} $l trash symbol]} {
  136.     if {![regexp {_?([A-Z][a-z0-9_]*_(Safe)?Init)} $symbol trash s]} {
  137. set s $symbol
  138.     }
  139.     append entryProtos {extern int } $symbol { (); } n
  140.     append entryPoints {  } { { "} $s {", } $symbol { } } , n
  141. }
  142.     }
  143.     close $f
  144.     if {[string equal $entryPoints ""]} {
  145. error "No entry point found in objects"
  146.     }
  147.     # Compose a C function that resolves the initialization entry points and
  148.     # embeds the required libraries in the object code.
  149.     set C {#include <string.h>}
  150.     append C n
  151.     append C {char TclLoadLibraries_} $modName { [] =} n
  152.     append C {  "@LIBS: } $libraries {";} n
  153.     append C $entryProtos
  154.     append C {static struct } { n
  155.     append C {  char * name;} n
  156.     append C {  int (*value)();} n
  157.     append C } {dictionary [] = } { n
  158.     append C $entryPoints
  159.     append C {  0, 0 } n } ; n
  160.     append C {typedef struct Tcl_Interp Tcl_Interp;} n
  161.     append C {typedef int Tcl_PackageInitProc (Tcl_Interp *);} n
  162.     append C {Tcl_PackageInitProc *} n
  163.     append C TclLoadDictionary_ $modName { (symbol)} n
  164.     append C {    CONST char * symbol;} n
  165.     append C {
  166. {
  167.     int i;
  168.     for (i = 0; dictionary [i] . name != 0; ++i) {
  169. if (!strcmp (symbol, dictionary [i] . name)) {
  170.     return dictionary [i].value;
  171. }
  172.     }
  173.     return 0;
  174. }
  175.     }
  176.     append C n
  177.     # Write the C module and compile it
  178.     set cFile tcl$modName.c
  179.     set f [open $cFile w]
  180.     puts -nonewline $f $C
  181.     close $f
  182.     set ccCommand "$cc -c $shlib_cflags $cFile"
  183.     puts stderr $ccCommand
  184.     eval exec $ccCommand
  185.     # Now compose and execute the ld command that packages the module
  186.     if {[string equal $shlib_suffix ".a"]} {
  187. set ldCommand "ar cr $outputFile"
  188. regsub { -o} $tail {} tail
  189.     } else {
  190. set ldCommand ld
  191. foreach item $head {
  192.     lappend ldCommand $item
  193. }
  194.     }
  195.     lappend ldCommand tcl$modName.o
  196.     foreach item $tail {
  197. lappend ldCommand $item
  198.     }
  199.     puts stderr $ldCommand
  200.     eval exec $ldCommand
  201.     if {[string equal $shlib_suffix ".a"]} {
  202. exec ranlib $outputFile
  203.     }
  204.     # Clean up working files
  205.     exec /bin/rm $cFile [file rootname $cFile].o
  206. }