genStubs.tcl

Go to the documentation of this file.
00001 /*  genStubs.tcl --*/
00002 /* */
00003 /*  This script generates a set of stub files for a given*/
00004 /*  interface.  */
00005 /*  */
00006 /* */
00007 /*  Copyright (c) 1998-1999 by Scriptics Corporation.*/
00008 /*  See the file "license.terms" for information on usage and redistribution*/
00009 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00010 /*  */
00011 /*  RCS: @(#) $Id: genStubs.tcl,v 1.1 2002/09/26 18:32:58 andreas_kupries Exp $*/
00012 
00013 namespace genStubs {
00014     /*  libraryName --*/
00015     /* */
00016     /*  The name of the entire library.  This value is used to compute*/
00017     /*  the USE_*_STUB_PROCS macro and the name of the init file.*/
00018 
00019     variable libraryName "UNKNOWN"
00020 
00021     /*  interfaces --*/
00022     /* */
00023     /*  An array indexed by interface name that is used to maintain*/
00024     /*    the set of valid interfaces.  The value is empty.*/
00025 
00026     array  interfaces =  {}
00027 
00028     /*  curName --*/
00029     /* */
00030     /*  The name of the interface currently being defined.*/
00031 
00032     variable curName "UNKNOWN"
00033 
00034     /*  hooks --*/
00035     /* */
00036     /*  An array indexed by interface name that contains the set of*/
00037     /*  subinterfaces that should be defined for a given interface.*/
00038 
00039     array  hooks =  {}
00040 
00041     /*  stubs --*/
00042     /* */
00043     /*  This three dimensional array is indexed first by interface name,*/
00044     /*  second by platform name, and third by a numeric offset or the*/
00045     /*  constant "lastNum".  The lastNum entry contains the largest*/
00046     /*  numeric offset used for a given interface/platform combo.  Each*/
00047     /*  numeric offset contains the C function specification that*/
00048     /*  should be used for the given entry in the stub table.  The spec*/
00049     /*  consists of a list in the form returned by parseDecl.*/
00050 
00051     array  stubs =  {}
00052 
00053     /*  outDir --*/
00054     /* */
00055     /*  The directory where the generated files should be placed.*/
00056 
00057     variable outDir .
00058 }
00059 
00060 /*  genStubs::library --*/
00061 /* */
00062 /*  This function is used in the declarations file to set the name*/
00063 /*  of the library that the interfaces are associated with (e.g. "tcl").*/
00064 /*  This value will be used to define the inline conditional macro.*/
00065 /* */
00066 /*  Arguments:*/
00067 /*  name    The library name.*/
00068 /* */
00069 /*  Results:*/
00070 /*  None.*/
00071 
00072 ret  genStubs::library (type name) {
00073     variable libraryName $name
00074 }
00075 
00076 /*  genStubs::interface --*/
00077 /* */
00078 /*  This function is used in the declarations file to set the name*/
00079 /*  of the interface currently being defined.*/
00080 /* */
00081 /*  Arguments:*/
00082 /*  name    The name of the interface.*/
00083 /* */
00084 /*  Results:*/
00085 /*  None.*/
00086 
00087 ret  genStubs::interface (type name) {
00088     variable curName $name
00089     variable interfaces
00090 
00091     set interfaces($name) {}
00092     return
00093 }
00094 
00095 /*  genStubs::hooks --*/
00096 /* */
00097 /*  This function defines the subinterface hooks for the current*/
00098 /*  interface.*/
00099 /* */
00100 /*  Arguments:*/
00101 /*  names   The ordered list of interfaces that are reachable through the*/
00102 /*      hook vector.*/
00103 /* */
00104 /*  Results:*/
00105 /*  None.*/
00106 
00107 ret  genStubs::hooks (type names) {
00108     variable curName
00109     variable hooks
00110 
00111     set hooks($curName) $names
00112     return
00113 }
00114 
00115 /*  genStubs::declare --*/
00116 /* */
00117 /*  This function is used in the declarations file to declare a new*/
00118 /*  interface entry.*/
00119 /* */
00120 /*  Arguments:*/
00121 /*  index       The index number of the interface.*/
00122 /*  platform    The platform the interface belongs to.  Should be one*/
00123 /*          of generic, win, unix, or mac.*/
00124 /*  decl        The C function declaration, or {} for an undefined*/
00125 /*          entry.*/
00126 /* */
00127 /*  Results:*/
00128 /*  None.*/
00129 
00130 ret  genStubs::declare (type args) {
00131     variable stubs
00132     variable curName
00133 
00134     if {[llength $args] != 3} {
00135     puts stderr "wrong # args: declare $args"
00136     }
00137     lassign $args index platformList decl
00138 
00139     # Check for duplicate declarations, then add the declaration and
00140     # bump the lastNum counter if necessary.
00141 
00142     foreach platform $platformList {
00143     if {[info exists stubs($curName,$platform,$index)]} {
00144         puts stderr "Duplicate entry: declare $args"
00145     }
00146     }
00147     regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
00148     set decl [parseDecl $decl]
00149 
00150     foreach platform $platformList {
00151     if {$decl != ""} {
00152         set stubs($curName,$platform,$index) $decl
00153         if {![info exists stubs($curName,$platform,lastNum)] \
00154             || ($index > $stubs($curName,$platform,lastNum))} {
00155         set stubs($curName,$platform,lastNum) $index
00156         }
00157     }
00158     }
00159     return
00160 }
00161 
00162 /*  genStubs::rewriteFile --*/
00163 /* */
00164 /*  This function replaces the machine generated portion of the*/
00165 /*  specified file with new contents.  It looks for the !BEGIN! and*/
00166 /*  !END! comments to determine where to place the new text.*/
00167 /* */
00168 /*  Arguments:*/
00169 /*  file    The name of the file to modify.*/
00170 /*  text    The new text to place in the file.*/
00171 /* */
00172 /*  Results:*/
00173 /*  None.*/
00174 
00175 ret  genStubs::rewriteFile (type file , type text) {
00176     if {![file exist $file]} {
00177     puts stderr "Cannot find file: $file"
00178     return
00179     }
00180     set in [open ${file} r]
00181     set out [open ${file}.new w]
00182 
00183     # Always write out the file with LF termination
00184     fconfigure $out -translation lf
00185 
00186     while {![eof $in]} {
00187     set line [gets $in]
00188     if {[regexp {!BEGIN!} $line]} {
00189         break
00190     }
00191     puts $out $line
00192     }
00193     puts $out "/* !BEGIN!: Do not edit below this line. */"
00194     puts $out $text
00195     while {![eof $in]} {
00196     set line [gets $in]
00197     if {[regexp {!END!} $line]} {
00198         break
00199     }
00200     }
00201     puts $out "/* !END!: Do not edit above this line. */"
00202     puts -nonewline $out [read $in]
00203     close $in
00204     close $out
00205     file rename -force ${file}.new ${file}
00206     return
00207 }
00208 
00209 /*  genStubs::addPlatformGuard --*/
00210 /* */
00211 /*  Wrap a string inside a platform #ifdef.*/
00212 /* */
00213 /*  Arguments:*/
00214 /*  plat    Platform to test.*/
00215 /* */
00216 /*  Results:*/
00217 /*  Returns the original text inside an appropriate #ifdef.*/
00218 
00219 ret  genStubs::addPlatformGuard (type plat , type text) {
00220     switch $plat {
00221     win {
00222         return "#ifdef __WIN32__\n${text}#endif /* __WIN32__ */\n"
00223     }
00224     unix {
00225         return "#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */\n${text}#endif /* UNIX */\n"
00226     }           
00227     mac {
00228         return "#ifdef MAC_TCL\n${text}#endif /* MAC_TCL */\n"
00229     }
00230     }
00231     return "$text"
00232 }
00233 
00234 /*  genStubs::emitSlots --*/
00235 /* */
00236 /*  Generate the stub table slots for the given interface.  If there*/
00237 /*  are no generic slots, then one table is generated for each*/
00238 /*  platform, otherwise one table is generated for all platforms.*/
00239 /* */
00240 /*  Arguments:*/
00241 /*  name    The name of the interface being emitted.*/
00242 /*  textVar The variable to use for output.*/
00243 /* */
00244 /*  Results:*/
00245 /*  None.*/
00246 
00247 ret  genStubs::emitSlots (type name , type textVar) {
00248     variable stubs
00249     upvar $textVar text
00250 
00251     forAllStubs $name makeSlot 1 text {"    void *reserved$i;\n"}
00252     return
00253 }
00254 
00255 /*  genStubs::parseDecl --*/
00256 /* */
00257 /*  Parse a C function declaration into its component parts.*/
00258 /* */
00259 /*  Arguments:*/
00260 /*  decl    The function declaration.*/
00261 /* */
00262 /*  Results:*/
00263 /*  Returns a list of the form {returnType name args}.  The args*/
00264 /*  element consists of a list of type/name pairs, or a single*/
00265 /*  element "void".  If the function declaration is malformed*/
00266 /*  then an error is displayed and the return value is {}.*/
00267 
00268 ret  genStubs::parseDecl (type decl) {
00269     if {![regexp {^(.*)\((.*)\)$} $decl all prefix args]} {
00270     puts stderr "Malformed declaration: $decl"
00271     return
00272     }
00273     set prefix [string trim $prefix]
00274     if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
00275     puts stderr "Bad return type: $decl"
00276     return
00277     }
00278     set rtype [string trim $rtype]
00279     foreach arg [split $args ,] {
00280     lappend argList [string trim $arg]
00281     }
00282     if {![string compare [lindex $argList end] "..."]} {
00283     if {[llength $argList] != 2} {
00284         puts stderr "Only one argument is allowed in varargs form: $decl"
00285     }
00286     set arg [parseArg [lindex $argList 0]]
00287     if {$arg == "" || ([llength $arg] != 2)} {
00288         puts stderr "Bad argument: '[lindex $argList 0]' in '$decl'"
00289         return
00290     }
00291     set args [list TCL_VARARGS $arg]
00292     } else {
00293     set args {}
00294     foreach arg $argList {
00295         set argInfo [parseArg $arg]
00296         if {![string compare $argInfo "void"]} {
00297         lappend args "void"
00298         break
00299         } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
00300         lappend args $argInfo
00301         } else {
00302         puts stderr "Bad argument: '$arg' in '$decl'"
00303         return
00304         }
00305     }
00306     }
00307     return [list $rtype $fname $args]
00308 }
00309 
00310 /*  genStubs::parseArg --*/
00311 /* */
00312 /*  This function parses a function argument into a type and name.*/
00313 /* */
00314 /*  Arguments:*/
00315 /*  arg The argument to parse.*/
00316 /* */
00317 /*  Results:*/
00318 /*  Returns a list of type and name with an optional third array*/
00319 /*  indicator.  If the argument is malformed, returns "".*/
00320 
00321 ret  genStubs::parseArg (type arg) {
00322     if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
00323     if {$arg == "void"} {
00324         return $arg
00325     } else {
00326         return
00327     }
00328     }
00329     set result [list [string trim $type] $name]
00330     if {$array != ""} {
00331     lappend result $array
00332     }
00333     return $result
00334 }
00335 
00336 /*  genStubs::makeDecl --*/
00337 /* */
00338 /*  Generate the prototype for a function.*/
00339 /* */
00340 /*  Arguments:*/
00341 /*  name    The interface name.*/
00342 /*  decl    The function declaration.*/
00343 /*  index   The slot index for this function.*/
00344 /* */
00345 /*  Results:*/
00346 /*  Returns the formatted declaration string.*/
00347 
00348 ret  genStubs::makeDecl (type name , type decl , type index) {
00349     lassign $decl rtype fname args
00350 
00351     append text "/* $index */\n"
00352     set line "EXTERN $rtype"
00353     set count [expr {2 - ([string length $line] / 8)}]
00354     append line [string range "\t\t\t" 0 $count]
00355     set pad [expr {24 - [string length $line]}]
00356     if {$pad <= 0} {
00357     append line " "
00358     set pad 0
00359     }
00360     append line "$fname _ANSI_ARGS_("
00361 
00362     set arg1 [lindex $args 0]
00363     switch -exact $arg1 {
00364     void {
00365         append line "(void)"
00366     }
00367     TCL_VARARGS {
00368         set arg [lindex $args 1]
00369         append line "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
00370     }
00371     default {
00372         set sep "("
00373         foreach arg $args {
00374         append line $sep
00375         set next {}
00376         append next [lindex $arg 0] " " [lindex $arg 1] \
00377             [lindex $arg 2]
00378         if {[string length $line] + [string length $next] \
00379             + $pad > 76} {
00380             append text $line \n
00381             set line "\t\t\t\t"
00382             set pad 28
00383         }
00384         append line $next
00385         set sep ", "
00386         }
00387         append line ")"
00388     }
00389     }
00390     append text $line
00391     
00392     append text ");\n"
00393     return $text
00394 }
00395 
00396 /*  genStubs::makeMacro --*/
00397 /* */
00398 /*  Generate the inline macro for a function.*/
00399 /* */
00400 /*  Arguments:*/
00401 /*  name    The interface name.*/
00402 /*  decl    The function declaration.*/
00403 /*  index   The slot index for this function.*/
00404 /* */
00405 /*  Results:*/
00406 /*  Returns the formatted macro definition.*/
00407 
00408 ret  genStubs::makeMacro (type name , type decl , type index) {
00409     lassign $decl rtype fname args
00410 
00411     set lfname [string tolower [string index $fname 0]]
00412     append lfname [string range $fname 1 end]
00413 
00414     set text "#ifndef $fname\n#define $fname"
00415     set arg1 [lindex $args 0]
00416     set argList ""
00417     switch -exact $arg1 {
00418     void {
00419         set argList "()"
00420     }
00421     TCL_VARARGS {
00422     }
00423     default {
00424         set sep "("
00425         foreach arg $args {
00426         append argList $sep [lindex $arg 1]
00427         set sep ", "
00428         }
00429         append argList ")"
00430     }
00431     }
00432     append text " \\\n\t(${name}StubsPtr->$lfname)"
00433     append text " /* $index */\n#endif\n"
00434     return $text
00435 }
00436 
00437 /*  genStubs::makeStub --*/
00438 /* */
00439 /*  Emits a stub function definition.*/
00440 /* */
00441 /*  Arguments:*/
00442 /*  name    The interface name.*/
00443 /*  decl    The function declaration.*/
00444 /*  index   The slot index for this function.*/
00445 /* */
00446 /*  Results:*/
00447 /*  Returns the formatted stub function definition.*/
00448 
00449 ret  genStubs::makeStub (type name , type decl , type index) {
00450     lassign $decl rtype fname args
00451 
00452     set lfname [string tolower [string index $fname 0]]
00453     append lfname [string range $fname 1 end]
00454 
00455     append text "/* Slot $index */\n" $rtype "\n" $fname
00456 
00457     set arg1 [lindex $args 0]
00458 
00459     if {![string compare $arg1 "TCL_VARARGS"]} {
00460     lassign [lindex $args 1] type argName 
00461     append text " TCL_VARARGS_DEF($type,$argName)\n\{\n"
00462     append text "    " $type " var;\n    va_list argList;\n"
00463     if {[string compare $rtype "void"]} {
00464         append text "    " $rtype " resultValue;\n"
00465     }
00466     append text "\n    var = (" $type ") TCL_VARARGS_START(" \
00467         $type "," $argName ",argList);\n\n    "
00468     if {[string compare $rtype "void"]} {
00469         append text "resultValue = "
00470     }
00471     append text "(" $name "StubsPtr->" $lfname "VA)(var, argList);\n"
00472     append text "    va_end(argList);\n"
00473     if {[string compare $rtype "void"]} {
00474         append text "return resultValue;\n"
00475     }
00476     append text "\}\n\n"
00477     return $text
00478     }
00479 
00480     if {![string compare $arg1 "void"]} {
00481     set argList "()"
00482     set argDecls ""
00483     } else {
00484     set argList ""
00485     set sep "("
00486     foreach arg $args {
00487         append argList $sep [lindex $arg 1]
00488         append argDecls "    " [lindex $arg 0] " " \
00489             [lindex $arg 1] [lindex $arg 2] ";\n"
00490         set sep ", "
00491     }
00492     append argList ")"
00493     }
00494     append text $argList "\n" $argDecls "{\n    "
00495     if {[string compare $rtype "void"]} {
00496     append text "return "
00497     }
00498     append text "(" $name "StubsPtr->" $lfname ")" $argList ";\n}\n\n"
00499     return $text
00500 }
00501 
00502 /*  genStubs::makeSlot --*/
00503 /* */
00504 /*  Generate the stub table entry for a function.*/
00505 /* */
00506 /*  Arguments:*/
00507 /*  name    The interface name.*/
00508 /*  decl    The function declaration.*/
00509 /*  index   The slot index for this function.*/
00510 /* */
00511 /*  Results:*/
00512 /*  Returns the formatted table entry.*/
00513 
00514 ret  genStubs::makeSlot (type name , type decl , type index) {
00515     lassign $decl rtype fname args
00516 
00517     set lfname [string tolower [string index $fname 0]]
00518     append lfname [string range $fname 1 end]
00519 
00520     set text "    "
00521     append text $rtype " (*" $lfname ") _ANSI_ARGS_("
00522 
00523     set arg1 [lindex $args 0]
00524     switch -exact $arg1 {
00525     void {
00526         append text "(void)"
00527     }
00528     TCL_VARARGS {
00529         set arg [lindex $args 1]
00530         append text "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
00531     }
00532     default {
00533         set sep "("
00534         foreach arg $args {
00535         append text $sep [lindex $arg 0] " " [lindex $arg 1] \
00536             [lindex $arg 2]
00537         set sep ", "
00538         }
00539         append text ")"
00540     }
00541     }
00542     
00543     append text "); /* $index */\n"
00544     return $text
00545 }
00546 
00547 /*  genStubs::makeInit --*/
00548 /* */
00549 /*  Generate the prototype for a function.*/
00550 /* */
00551 /*  Arguments:*/
00552 /*  name    The interface name.*/
00553 /*  decl    The function declaration.*/
00554 /*  index   The slot index for this function.*/
00555 /* */
00556 /*  Results:*/
00557 /*  Returns the formatted declaration string.*/
00558 
00559 ret  genStubs::makeInit (type name , type decl , type index) {
00560     append text "    " [lindex $decl 1] ", /* " $index " */\n"
00561     return $text
00562 }
00563 
00564 /*  genStubs::forAllStubs --*/
00565 /* */
00566 /*  This function iterates over all of the platforms and invokes*/
00567 /*  a callback for each slot.  The result of the callback is then*/
00568 /*  placed inside appropriate platform guards.*/
00569 /* */
00570 /*  Arguments:*/
00571 /*  name        The interface name.*/
00572 /*  slotProc    The proc to invoke to handle the slot.  It will*/
00573 /*          have the interface name, the declaration,  and*/
00574 /*          the index appended.*/
00575 /*  onAll       If 1, emit the skip string even if there are*/
00576 /*          definitions for one or more platforms.*/
00577 /*  textVar     The variable to use for output.*/
00578 /*  skipString  The string to emit if a slot is skipped.  This*/
00579 /*          string will be subst'ed in the loop so "$i" can*/
00580 /*          be used to substitute the index value.*/
00581 /* */
00582 /*  Results:*/
00583 /*  None.*/
00584 
00585 ret  genStubs::forAllStubs (type name , type slotProc , type onAll , type textVar \
00586     , optional skipString ={"/* Slot =$i is =reserved */\n")} {
00587     variable stubs
00588     upvar $textVar text
00589 
00590     set plats [array names stubs $name,*,lastNum]
00591     if {[info exists stubs($name,generic,lastNum)]} {
00592     /*  Emit integrated stubs block*/
00593      lastNum =  -1
00594     foreach plat [array names stubs $name,*,lastNum] {
00595         if {$stubs($plat) > $lastNum} {
00596          lastNum =  $stubs($plat)
00597         }
00598     }
00599     for { i =  0} {$i <= $lastNum} {incr i} {
00600          slots =  [array names stubs $name,*,$i]
00601          emit =  0
00602         if {[info exists stubs($name,generic,$i)]} {
00603         if {[llength $slots] > 1} {
00604             puts stderr "platform entry duplicates generic entry: $i"
00605         }
00606         append text [$slotProc $name $stubs($name,generic,$i) $i]
00607          emit =  1
00608         } elseif {[llength $slots] > 0} {
00609         foreach plat {unix win mac} {
00610             if {[info exists stubs($name,$plat,$i)]} {
00611             append text [addPlatformGuard $plat \
00612                 [$slotProc $name $stubs($name,$plat,$i) $i]]
00613              emit =  1
00614             } elseif {$onAll} {
00615             append text [eval {addPlatformGuard $plat} $skipString]
00616              emit =  1
00617             }
00618         }
00619         }
00620         if {$emit == 0} {
00621         eval {append text} $skipString
00622         }
00623     }
00624     
00625     } else {
00626     /*  Emit separate stubs blocks per platform*/
00627     foreach plat {unix win mac} {
00628         if {[info exists stubs($name,$plat,lastNum)]} {
00629          lastNum =  $stubs($name,$plat,lastNum)
00630          temp =  {}
00631         for { i =  0} {$i <= $lastNum} {incr i} {
00632             if {![info exists stubs($name,$plat,$i)]} {
00633             eval {append temp} $skipString
00634             } else {
00635             append temp [$slotProc $name $stubs($name,$plat,$i) $i]
00636             }
00637         }
00638         append text [addPlatformGuard $plat $temp]
00639         }
00640     }
00641     }
00642 
00643 }
00644 
00645 /*  genStubs::emitDeclarations --*/
00646 /* */
00647 /*  This function emits the function declarations for this interface.*/
00648 /* */
00649 /*  Arguments:*/
00650 /*  name    The interface name.*/
00651 /*  textVar The variable to use for output.*/
00652 /* */
00653 /*  Results:*/
00654 /*  None.*/
00655 
00656 ret  genStubs::emitDeclarations (type name , type textVar) {
00657     variable stubs
00658     upvar $textVar text
00659 
00660     append text "\n/*\n * Exported function declarations:\n */\n\n"
00661     forAllStubs $name makeDecl 0 text
00662     return
00663 }
00664 
00665 /*  genStubs::emitMacros --*/
00666 /* */
00667 /*  This function emits the inline macros for an interface.*/
00668 /* */
00669 /*  Arguments:*/
00670 /*  name    The name of the interface being emitted.*/
00671 /*  textVar The variable to use for output.*/
00672 /* */
00673 /*  Results:*/
00674 /*  None.*/
00675 
00676 ret  genStubs::emitMacros (type name , type textVar) {
00677     variable stubs
00678     variable libraryName
00679     upvar $textVar text
00680 
00681     set upName [string toupper $libraryName]
00682     append text "\n#if defined(USE_${upName}_STUBS) && !defined(USE_${upName}_STUB_PROCS)\n"
00683     append text "\n/*\n * Inline function declarations:\n */\n\n"
00684     
00685     forAllStubs $name makeMacro 0 text
00686 
00687     append text "\n#endif /* defined(USE_${upName}_STUBS) && !defined(USE_${upName}_STUB_PROCS) */\n"
00688     return
00689 }
00690 
00691 /*  genStubs::emitHeader --*/
00692 /* */
00693 /*  This function emits the body of the <name>Decls.h file for*/
00694 /*  the specified interface.*/
00695 /* */
00696 /*  Arguments:*/
00697 /*  name    The name of the interface being emitted.*/
00698 /* */
00699 /*  Results:*/
00700 /*  None.*/
00701 
00702 ret  genStubs::emitHeader (type name) {
00703     variable outDir
00704     variable hooks
00705 
00706     set capName [string toupper [string index $name 0]]
00707     append capName [string range $name 1 end]
00708 
00709     emitDeclarations $name text
00710 
00711     if {[info exists hooks($name)]} {
00712     append text "\ntypedef struct ${capName}StubHooks {\n"
00713     foreach hook $hooks($name) {
00714         set capHook [string toupper [string index $hook 0]]
00715         append capHook [string range $hook 1 end]
00716         append text "    struct ${capHook}Stubs *${hook}Stubs;\n"
00717     }
00718     append text "} ${capName}StubHooks;\n"
00719     }
00720     append text "\ntypedef struct ${capName}Stubs {\n"
00721     append text "    int magic;\n"
00722     append text "    struct ${capName}StubHooks *hooks;\n\n"
00723 
00724     emitSlots $name text
00725 
00726     append text "} ${capName}Stubs;\n"
00727 
00728     append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
00729     append text "extern ${capName}Stubs *${name}StubsPtr;\n"
00730     append text "#ifdef __cplusplus\n}\n#endif\n"
00731 
00732     emitMacros $name text
00733 
00734     rewriteFile [file join $outDir ${name}Decls.h] $text
00735     return
00736 }
00737 
00738 /*  genStubs::emitStubs --*/
00739 /* */
00740 /*  This function emits the body of the <name>Stubs.c file for*/
00741 /*  the specified interface.*/
00742 /* */
00743 /*  Arguments:*/
00744 /*  name    The name of the interface being emitted.*/
00745 /* */
00746 /*  Results:*/
00747 /*  None.*/
00748 
00749 ret  genStubs::emitStubs (type name) {
00750     variable outDir
00751 
00752     append text "\n/*\n * Exported stub functions:\n */\n\n"
00753     forAllStubs $name makeStub 0 text
00754 
00755     rewriteFile [file join $outDir ${name}Stubs.c] $text
00756     return    
00757 }
00758 
00759 /*  genStubs::emitInit --*/
00760 /* */
00761 /*  Generate the table initializers for an interface.*/
00762 /* */
00763 /*  Arguments:*/
00764 /*  name        The name of the interface to initialize.*/
00765 /*  textVar     The variable to use for output.*/
00766 /* */
00767 /*  Results:*/
00768 /*  Returns the formatted output.*/
00769 
00770 ret  genStubs::emitInit (type name , type textVar) {
00771     variable stubs
00772     variable hooks
00773     upvar $textVar text
00774 
00775     set capName [string toupper [string index $name 0]]
00776     append capName [string range $name 1 end]
00777 
00778     if {[info exists hooks($name)]} {
00779     append text "\nstatic ${capName}StubHooks ${name}StubHooks = \{\n"
00780     set sep "    "
00781     foreach sub $hooks($name) {
00782         append text $sep "&${sub}Stubs"
00783         set sep ",\n    "
00784     }
00785     append text "\n\};\n"
00786     }
00787     append text "\n${capName}Stubs ${name}Stubs = \{\n"
00788     append text "    TCL_STUB_MAGIC,\n"
00789     if {[info exists hooks($name)]} {
00790     append text "    &${name}StubHooks,\n"
00791     } else {
00792     append text "    NULL,\n"
00793     }
00794     
00795     forAllStubs $name makeInit 1 text {"    NULL, /* $i */\n"}
00796 
00797     append text "\};\n"
00798     return
00799 }
00800 
00801 /*  genStubs::emitInits --*/
00802 /* */
00803 /*  This function emits the body of the <name>StubInit.c file for*/
00804 /*  the specified interface.*/
00805 /* */
00806 /*  Arguments:*/
00807 /*  name    The name of the interface being emitted.*/
00808 /* */
00809 /*  Results:*/
00810 /*  None.*/
00811 
00812 ret  genStubs::emitInits () {
00813     variable hooks
00814     variable outDir
00815     variable libraryName
00816     variable interfaces
00817 
00818     # Assuming that dependencies only go one level deep, we need to emit
00819     # all of the leaves first to avoid needing forward declarations.
00820 
00821     set leaves {}
00822     set roots {}
00823     foreach name [lsort [array names interfaces]] {
00824     if {[info exists hooks($name)]} {
00825         lappend roots $name
00826     } else {
00827         lappend leaves $name
00828     }
00829     }
00830     foreach name $leaves {
00831     emitInit $name text
00832     }
00833     foreach name $roots {
00834     emitInit $name text
00835     }
00836 
00837     rewriteFile [file join $outDir ${libraryName}StubInit.c] $text
00838 }
00839 
00840 /*  genStubs::init --*/
00841 /* */
00842 /*  This is the main entry point.*/
00843 /* */
00844 /*  Arguments:*/
00845 /*  None.*/
00846 /* */
00847 /*  Results:*/
00848 /*  None.*/
00849 
00850 ret  genStubs::init () {
00851     global argv argv0
00852     variable outDir
00853     variable interfaces
00854 
00855     if {[llength $argv] < 2} {
00856     puts stderr "usage: $argv0 outDir declFile ?declFile...?"
00857     exit 1
00858     }
00859 
00860     set outDir [lindex $argv 0]
00861 
00862     foreach file [lrange $argv 1 end] {
00863     source $file
00864     }
00865 
00866     foreach name [lsort [array names interfaces]] {
00867     puts "Emitting $name"
00868     emitHeader $name
00869     }
00870 
00871     emitInits
00872 }
00873 
00874 /*  lassign --*/
00875 /* */
00876 /*  This function emulates the TclX lassign command.*/
00877 /* */
00878 /*  Arguments:*/
00879 /*  valueList   A list containing the values to be assigned.*/
00880 /*  args        The list of variables to be assigned.*/
00881 /* */
00882 /*  Results:*/
00883 /*  Returns any values that were not assigned to variables.*/
00884 
00885 ret  lassign (type valueList , type args) {
00886   if {[llength $args] == 0} {
00887       error "wrong # args: lassign list varname ?varname..?"
00888   }
00889 
00890   uplevel [list foreach $args $valueList {break}]
00891   return [lrange $valueList [llength $args] end]
00892 }
00893 
00894 genStubs::init
00895 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1