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