2
# STUBS handling -- Code generation: Writing the initialization code for IMPORTers.
4
# (c) 2011 Andreas Kupries http://wiki.tcl.tk/andreas%20kupries
6
# A stubs table is represented by a dictionary value.
7
# A gen is a variable holding a stubs table value.
9
# # ## ### ##### ######## #############
12
package require Tcl 8.4
13
package require stubs::gen
14
package require stubs::container
15
package require lassign84
17
namespace eval ::stubs::gen::lib::g {
18
namespace import ::stubs::gen::*
21
namespace eval ::stubs::gen::lib::c {
22
namespace import ::stubs::container::*
25
# # ## ### ##### ######## #############
28
proc ::stubs::gen::lib::gen {table} {
29
# Assuming that dependencies only go one level deep, we need to
30
# emit all of the leaves first to avoid needing forward
35
# Assuming that dependencies only go one level deep, we emit all
36
# of the leaves first to avoid needing forward declarations.
41
foreach name [lsort [c::interfaces $table]] {
42
if {[c::hooks? $table $name]} {
53
foreach name [concat $leaves $roots] {
54
set capName [g::cap $name]
56
# POLISH - format the variables code block aligned using
57
# maxlength of interface names.
58
lappend headers "\#include \"${name}Decls.h\""
59
lappend variables "const ${capName}Stubs* ${name}StubsPtr;"
61
# Check if this is a hook. If yes it needs additional setup.
62
set parent [Parent $table $name]
63
if {$parent eq ""} continue
64
lappend hooks " ${name}StubsPtr = ${parent}StubsPtr->hooks->${name}Stubs;"
67
set pname [c::library? $table] ; # FUTURE: May be separate from the library
69
set name [string map {:: _} [c::library? $table]]
70
set capName [g::cap $name]
71
set upName [string toupper $name]
73
set headers [Block $headers]
74
set variables [Block $variables]
75
set hooks [Block $hooks]
90
proc ::stubs::gen::lib::Block {list} {
91
if {![llength $list]} { return "" }
92
return \n[join $list \n]\n
95
proc ::stubs::gen::lib::make@ {basedir table} {
96
make [path $basedir [c::library? $table]] $table
99
proc ::stubs::gen::lib::make {path table} {
101
puts -nonewline $c [gen $table]
106
proc ::stubs::gen::lib::path {basedir name} {
107
return [file join $basedir ${name}StubLib.c]
113
proc ::stubs::gen::lib::Parent {table name} {
114
# Check if this interface is a hook for some other interface.
115
# TODO: Make this a container API command.
116
foreach intf [c::interfaces $table] {
117
if {[c::hooks? $table $intf] &&
118
([lsearch -exact [c::hooksof $table $intf] $name] >= 0)} {
126
namespace eval ::stubs::gen::lib {
127
#checker exclude warnShadowVar
128
variable template [string map {{
134
* Stub object that will be statically linked into extensions that wish
139
* We need to ensure that we use the stub macros so that this file contains
140
* no references to any of the stub functions. This will make it possible
141
* to build an extension that references @CAP@_InitStubs but doesn't end up
142
* including the rest of the stub functions.
145
#ifndef USE_TCL_STUBS
146
#define USE_TCL_STUBS
148
#undef USE_TCL_STUB_PROCS
152
#ifndef USE_@UP@_STUBS
153
#define USE_@UP@_STUBS
155
#undef USE_@UP@_STUB_PROCS
158
* Ensure that @CAP@_InitStubs is built as an exported symbol. The other stub
159
* functions should be built as non-exported symbols.
162
#undef TCL_STORAGE_CLASS
163
#define TCL_STORAGE_CLASS DLLEXPORT
167
*----------------------------------------------------------------------
171
* Checks that the correct version of @CAP@ is loaded and that it
172
* supports stubs. It then initialises the stub table pointers.
175
* The actual version of @CAP@ that satisfies the request, or
176
* NULL to indicate that an error occurred.
179
* Sets the stub table pointers.
181
*----------------------------------------------------------------------
184
#ifdef @CAP@_InitStubs
185
#undef @CAP@_InitStubs
189
@CAP@_InitStubs(Tcl_Interp *interp, CONST char *version, int exact)
191
CONST char *actualVersion;
193
actualVersion = Tcl_PkgRequireEx(interp, "@PKG@", version,
194
exact, (ClientData *) &@@StubsPtr);
195
if (!actualVersion) {
200
Tcl_SetResult(interp,
201
"This implementation of @CAP@ does not support stubs",
206
return (char*) actualVersion;
210
namespace export gen make@ make rewrite@ rewrite path
213
# # ## ### ##### ######## #############
214
package provide stubs::gen::lib 1