00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 package require Tcl 8.2
00013 package require textutil::expander
00014
00015
00016
00017
00018
00019
00020
00021 namespace ::doctools {
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 variable commands [list \
00044 "cget" \
00045 "configure" \
00046 "destroy" \
00047 "format" \
00048 "map" \
00049 "search" \
00050 "warnings" \
00051 "parameters" \
00052 "param = " \
00053 ]
00054
00055
00056 namespace export new search help
00057
00058
00059
00060
00061
00062
00063
00064 variable paths [list]
00065 variable here [file dirname [info script]]
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 ret ::doctools::search (type path) {
00085 variable paths
00086
00087 if {![file exists $path]} {return -code error "doctools::search: path does not exist"}
00088 if {![file isdirectory $path]} {return -code error "doctools::search: path is not a directory"}
00089 if {![file readable $path]} {return -code error "doctools::search: path cannot be read"}
00090
00091 set paths [linsert $paths 0 $path]
00092 return
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 ret ::doctools::help () {
00107 return "formatting commands\n\
00108 * manpage_begin - begin of manpage\n\
00109 * moddesc - module description\n\
00110 * titledesc - manpage title\n\
00111 * copyright - copyright assignment\n\
00112 * manpage_end - end of manpage\n\
00113 * require - package requirement\n\
00114 * description - begin of manpage body\n\
00115 * section - begin new section of body\n\
00116 * subsection - begin new sub-section of body\n\
00117 * para - begin new paragraph\n\
00118 * list_begin - begin a list\n\
00119 * list_end - end of a list\n\
00120 * lst_item - begin item of definition list\n\
00121 * call - command definition, adds to synopsis\n\
00122 * usage - see above, without adding to synopsis\n\
00123 * bullet - begin item in bulleted list\n\
00124 * enum - begin item in enumerated list\n\
00125 * arg_def - begin item in argument list\n\
00126 * cmd_def - begin item in command list\n\
00127 * opt_def - begin item in option list\n\
00128 * tkoption_def - begin item in tkoption list\n\
00129 * example - example block\n\
00130 * example_begin - begin example\n\
00131 * example_end - end of example\n\
00132 * see_also - cross reference declaration\n\
00133 * keywords - keyword declaration\n\
00134 * nl - paragraph break in list items\n\
00135 * arg - semantic markup - argument\n\
00136 * cmd - semantic markup - command\n\
00137 * opt - semantic markup - optional data\n\
00138 * comment - semantic markup - comment\n\
00139 * sectref - semantic markup - section reference\n\
00140 * syscmd - semantic markup - system command\n\
00141 * method - semantic markup - object method\n\
00142 * namespace - semantic markup - namespace name\n\
00143 * option - semantic markup - option\n\
00144 * widget - semantic markup - widget\n\
00145 * fun - semantic markup - function\n\
00146 * type - semantic markup - data type\n\
00147 * package - semantic markup - package\n\
00148 * class - semantic markup - class\n\
00149 * var - semantic markup - variable\n\
00150 * file - semantic markup - file \n\
00151 * uri - semantic markup - uri (optional label)\n\
00152 * term - semantic markup - unspecific terminology\n\
00153 * const - semantic markup - constant value\n\
00154 * emph - emphasis\n\
00155 * strong - emphasis, deprecated, usage is discouraged\n\
00156 "
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 ret ::doctools::new (type name , type args) {
00171
00172 if { [llength [info commands ::$name]] } {
00173 return -code error "command \"$name\" already exists, unable to create doctools object"
00174 }
00175 if {[llength $args] % 2 == 1} {
00176 return -code error "wrong # args: doctools::new name ?opt val...??"
00177 }
00178
00179 # The arguments seem to be ok, setup the namespace for the object
00180
00181 namespace eval ::doctools::doctools$name {
00182 variable paths [list]
00183 variable format ""
00184 variable formatfile ""
00185 variable deprecated 0
00186 variable file ""
00187 variable module ""
00188 variable copyright ""
00189 variable format_ip ""
00190 variable chk_ip ""
00191 variable expander "[namespace current]::ex"
00192 variable ex_ok 0
00193 variable msg [list]
00194 variable param [list]
00195 variable map ; array set map {}
00196 }
00197
00198 # Create the command to manipulate the object
00199 # $name -> ::doctools::DoctoolsProc $name
00200 interp alias {} ::$name {} ::doctools::DoctoolsProc $name
00201
00202 # If the name was followed by arguments use them to configure the
00203 # object before returning its handle to the caller.
00204
00205 if {[llength $args] > 1} {
00206 # Use linsert trick to make the command a pure list.
00207 eval [linsert $args 0 _configure $name]
00208 }
00209 return $name
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 ret ::doctools::DoctoolsProc (type name , optional cmd ="" , type args) {
00230 # Do minimal args checks here
00231 if { [llength [info level 0]] == 2 } {
00232 error "wrong # args: should be \"$name option ?arg arg ...?\""
00233 }
00234
00235 # Split the args into command and args components
00236
00237 if { [llength [info commands ::doctools::_$cmd]] == 0 } {
00238 variable commands
00239 set optlist [join $commands ", "]
00240 set optlist [linsert $optlist "end-1" "or"]
00241 return -code error "bad option \"$cmd\": must be $optlist"
00242 }
00243 return [eval [list ::doctools::_$cmd $name] $args]
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 ret ::doctools::_cget (type name , type option) {
00261 _configure $name $option
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 ret ::doctools::_configure (type name , type args) {
00278 upvar ::doctools::doctools${name}::format_ip format_ip
00279 upvar ::doctools::doctools${name}::chk_ip chk_ip
00280 upvar ::doctools::doctools${name}::expander expander
00281 upvar ::doctools::doctools${name}::passes passes
00282
00283 if {[llength $args] == 0} {
00284 # Retrieve the current configuration.
00285
00286 upvar ::doctools::doctools${name}::file file
00287 upvar ::doctools::doctools${name}::module module
00288 upvar ::doctools::doctools${name}::format format
00289 upvar ::doctools::doctools${name}::copyright copyright
00290 upvar ::doctools::doctools${name}::deprecated deprecated
00291
00292 set res [list]
00293 lappend res -file $file
00294 lappend res -module $module
00295 lappend res -format $format
00296 lappend res -copyright $copyright
00297 lappend res -deprecated $deprecated
00298 return $res
00299
00300 } elseif {[llength $args] == 1} {
00301 # Query the value of one particular option.
00302
00303 switch -exact -- [lindex $args 0] {
00304 -file {
00305 upvar ::doctools::doctools${name}::file file
00306 return $file
00307 }
00308 -module {
00309 upvar ::doctools::doctools${name}::module module
00310 return $module
00311 }
00312 -copyright {
00313 upvar ::doctools::doctools${name}::copyright copyright
00314 return $copyright
00315 }
00316 -format {
00317 upvar ::doctools::doctools${name}::format format
00318 return $format
00319 }
00320 -deprecated {
00321 upvar ::doctools::doctools${name}::deprecated deprecated
00322 return $deprecated
00323 }
00324 default {
00325 return -code error \
00326 "doctools::_configure: Unknown option \"[lindex $args 0]\", expected\
00327 -copyright, -file, -module, -format, or -deprecated"
00328 }
00329 }
00330 } else {
00331 # Reconfigure the object.
00332
00333 if {[llength $args] % 2 == 1} {
00334 return -code error "wrong # args: doctools::_configure name ?opt val...??"
00335 }
00336
00337 foreach {option value} $args {
00338 switch -exact -- $option {
00339 -file {
00340 upvar ::doctools::doctools${name}::file file
00341 set file $value
00342 }
00343 -module {
00344 upvar ::doctools::doctools${name}::module module
00345 set module $value
00346 }
00347 -copyright {
00348 upvar ::doctools::doctools${name}::copyright copyright
00349 set copyright $value
00350 }
00351 -format {
00352 if {[catch {
00353 set fmtfile [LookupFormat $name $value]
00354 SetupFormatter $name $fmtfile
00355 upvar ::doctools::doctools${name}::format format
00356 set format $value
00357 } msg]} {
00358 return -code error "doctools::_configure: -format: $msg"
00359 }
00360 }
00361 -deprecated {
00362 if {![string is boolean $value]} {
00363 return -code error \
00364 "doctools::_configure: -deprecated expected a boolean, got \"$value\""
00365 }
00366 upvar ::doctools::doctools${name}::deprecated deprecated
00367 set deprecated $value
00368 }
00369 default {
00370 return -code error \
00371 "doctools::_configure: Unknown option \"$option\", expected\
00372 -copyright, -file, -module, -format, or -deprecated"
00373 }
00374 }
00375 }
00376 }
00377 return ""
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 ret ::doctools::_destroy (type name) {
00391 # Check the object for sub objects which have to destroyed before
00392 # the namespace is torn down.
00393 namespace eval ::doctools::doctools$name {
00394 if {$format_ip != ""} {interp delete $format_ip}
00395 if {$chk_ip != ""} {interp delete $chk_ip}
00396
00397 # Expander objects have no delete/destroy method. This would
00398 # be a leak if not for the fact that an expander object is a
00399 # namespace, and we have arranged to make it a sub namespace of
00400 # the doctools object. Therefore tearing down our object namespace
00401 # also cleans up the expander object.
00402 # if {$expander != ""} {$expander destroy}
00403
00404 }
00405 namespace delete ::doctools::doctools$name
00406 interp alias {} ::$name {}
00407 return
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 ret ::doctools::_map (type name , type sfname , type afname) {
00423 upvar ::doctools::doctools${name}::map map
00424 set map($sfname) $afname
00425 return
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 ret ::doctools::_format (type name , type text) {
00441 upvar ::doctools::doctools${name}::format format
00442 if {$format == ""} {
00443 return -code error "$name: No format was specified"
00444 }
00445
00446 upvar ::doctools::doctools${name}::format_ip format_ip
00447 upvar ::doctools::doctools${name}::chk_ip chk_ip
00448 upvar ::doctools::doctools${name}::ex_ok ex_ok
00449 upvar ::doctools::doctools${name}::expander expander
00450 upvar ::doctools::doctools${name}::passes passes
00451 upvar ::doctools::doctools${name}::msg warnings
00452
00453 if {!$ex_ok} {SetupExpander $name}
00454 if {$chk_ip == ""} {SetupChecker $name}
00455 # assert (format_ip != "")
00456
00457 set warnings [list]
00458 if {[catch {$format_ip eval fmt_initialize}]} {
00459 return -code error "Could not initialize engine"
00460 }
00461 set result ""
00462
00463 for {
00464 set p $passes ; set n 1
00465 } {
00466 $p > 0
00467 } {
00468 incr p -1 ; incr n
00469 } {
00470 if {[catch {$format_ip eval [list fmt_setup $n]}]} {
00471 catch {$format_ip eval fmt_shutdown}
00472 return -code error "Could not initialize pass $n of engine"
00473 }
00474 $chk_ip eval ck_initialize
00475
00476 if {[catch {set result [$expander expand $text]} msg]} {
00477 catch {$format_ip eval fmt_shutdown}
00478 # Filter for checker errors and reduce them to the essential message.
00479
00480 if {![regexp {^Error in} $msg]} {return -code error $msg}
00481 #set msg [join [lrange [split $msg \n] 2 end]]
00482
00483 if {![regexp {^--> \(FmtError\) } $msg]} {return -code error "Doctools $msg"}
00484 set msg [lindex [split $msg \n] 0]
00485 regsub {^--> \(FmtError\) } $msg {} msg
00486
00487 return -code error $msg
00488 }
00489
00490 $chk_ip eval ck_complete
00491 }
00492
00493 if {[catch {set result [$format_ip eval [list fmt_postprocess $result]]}]} {
00494 return -code error "Unable to post process final result"
00495 }
00496 if {[catch {$format_ip eval fmt_shutdown}]} {
00497 return -code error "Could not shut engine down"
00498 }
00499 return $result
00500
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 ret ::doctools::_search (type name , type path) {
00515 if {![file exists $path]} {return -code error "$name search: path does not exist"}
00516 if {![file isdirectory $path]} {return -code error "$name search: path is not a directory"}
00517 if {![file readable $path]} {return -code error "$name search: path cannot be read"}
00518
00519 upvar ::doctools::doctools${name}::paths paths
00520 set paths [linsert $paths 0 $path]
00521 return
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 ret ::doctools::_warnings (type name) {
00535 upvar ::doctools::doctools${name}::msg msg
00536 return $msg
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 ret ::doctools::_parameters (type name) {
00551 upvar ::doctools::doctools${name}::param param
00552 return $param
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 ret ::doctools::_setparam (type name , type param , type value) {
00568 upvar ::doctools::doctools${name}::format_ip format_ip
00569
00570 if {$format_ip == {}} {
00571 return -code error \
00572 "Unable to set parameters without a valid format"
00573 }
00574
00575 $format_ip eval [list fmt_varset $param $value]
00576 return
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 ret ::doctools::LookupFormat (type name , type format) {
00594 # Order of searching
00595 # 1) Is the name of the format an existing file ?
00596 # If yes, take this file.
00597 # 2) Look for the file in the directories given to the object itself..
00598 # 3) Look for the file in the standard directories of this package.
00599
00600 if {[file exists $format]} {
00601 return $format
00602 }
00603
00604 upvar ::doctools::doctools${name}::paths opaths
00605 foreach path $opaths {
00606 set f [file join $path fmt.$format]
00607 if {[file exists $f]} {
00608 return $f
00609 }
00610 }
00611
00612 variable paths
00613 foreach path $paths {
00614 set f [file join $path fmt.$format]
00615 if {[file exists $f]} {
00616 return $f
00617 }
00618 }
00619
00620 return -code error "Unknown format \"$format\""
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 ret ::doctools::SetupFormatter (type name , type format) {
00636
00637 # Create and initialize the interpreter first.
00638 # Use a transient variable. Interrogate the
00639 # engine and check its response. Bail out in
00640 # case of errors. Only if we pass the checks
00641 # we tear down the old engine and make the new
00642 # one official.
00643
00644 variable here
00645 set mpip [interp create -safe] ; # interpreter for the formatting engine
00646 $mpip eval [list set auto_path $::auto_path]
00647 #set mpip [interp create] ; # interpreter for the formatting engine
00648
00649 $mpip invokehidden source [file join $here api.tcl]
00650 #$mpip eval [list source [file join $here api.tcl]]
00651 interp alias $mpip dt_source {} ::doctools::Source $mpip [file dirname $format]
00652 interp alias $mpip dt_package {} ::doctools::Package $mpip
00653 interp alias $mpip file {} ::doctools::FileOp $mpip
00654 interp alias $mpip puts_stderr {} ::puts stderr
00655 $mpip invokehidden source $format
00656 #$mpip eval [list source $format]
00657
00658 # Check the engine for useability in doctools.
00659
00660 foreach api {
00661 fmt_numpasses
00662 fmt_initialize
00663 fmt_setup
00664 fmt_postprocess
00665 fmt_shutdown
00666 fmt_listvariables
00667 fmt_varset
00668 } {
00669 if {[$mpip eval [list info commands $api]] == {}} {
00670 interp delete $mpip
00671 error "$format error: API incomplete, cannot use this engine"
00672 }
00673 }
00674 if {[catch {
00675 set passes [$mpip eval fmt_numpasses]
00676 }]} {
00677 interp delete $mpip
00678 error "$format error: Unable to query for number of passes"
00679 }
00680 if {![string is integer $passes] || ($passes < 1)} {
00681 interp delete $mpip
00682 error "$format error: illegal number of passes \"$passes\""
00683 }
00684 if {[catch {
00685 set parameters [$mpip eval fmt_listvariables]
00686 }]} {
00687 interp delete $mpip
00688 error "$format error: Unable to query for list of parameters"
00689 }
00690
00691 # Passed the tests. Tear down existing engine,
00692 # and checker. The latter is destroyed because
00693 # of its aliases into the formatter, which are
00694 # now invalid. It will be recreated during the
00695 # next call of 'format'.
00696
00697 upvar ::doctools::doctools${name}::formatfile formatfile
00698 upvar ::doctools::doctools${name}::format_ip format_ip
00699 upvar ::doctools::doctools${name}::chk_ip chk_ip
00700 upvar ::doctools::doctools${name}::expander expander
00701 upvar ::doctools::doctools${name}::passes xpasses
00702 upvar ::doctools::doctools${name}::param xparam
00703
00704 if {$chk_ip != {}} {interp delete $chk_ip}
00705 if {$format_ip != {}} {interp delete $format_ip}
00706
00707 set chk_ip ""
00708 set format_ip ""
00709
00710 # Now link engine API into it.
00711
00712 interp alias $mpip dt_file {} ::doctools::GetFile $name
00713 interp alias $mpip dt_fileid {} ::doctools::GetFileId $name
00714 interp alias $mpip dt_module {} ::doctools::GetModule $name
00715 interp alias $mpip dt_copyright {} ::doctools::GetCopyright $name
00716 interp alias $mpip dt_format {} ::doctools::GetFormat $name
00717 interp alias $mpip dt_user {} ::doctools::GetUser $name
00718 interp alias $mpip dt_lnesting {} ::doctools::ListLevel $name
00719 interp alias $mpip dt_fmap {} ::doctools::MapFile $name
00720 interp alias $mpip file {} ::doctools::FileCmd
00721
00722 foreach cmd {cappend cget cis cname cpop cpush ctopandclear cset lb rb} {
00723 interp alias $mpip ex_$cmd {} $expander $cmd
00724 }
00725
00726 set format_ip $mpip
00727 set formatfile $format
00728 set xpasses $passes
00729 set xparam $parameters
00730 return
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 ret ::doctools::SetupChecker (type name) {
00745 # Create an interpreter for checking the usage of doctools formatting commands
00746 # and initialize it: Link it to the interpreter doing the formatting, the
00747 # expander object and the configuration information. All of which
00748 # is accessible through the token/handle (name of state/object array).
00749
00750 variable here
00751
00752 upvar ::doctools::doctools${name}::chk_ip chk_ip
00753 if {$chk_ip != ""} {return}
00754
00755 upvar ::doctools::doctools${name}::expander expander
00756 upvar ::doctools::doctools${name}::format_ip format_ip
00757
00758 set chk_ip [interp create] ; # interpreter hosting the formal format checker
00759
00760 # Make configuration available through command, then load the code base.
00761
00762 foreach {cmd ckcmd} {
00763 dt_search SearchPaths
00764 dt_deprecated Deprecated
00765 dt_error FmtError
00766 dt_warning FmtWarning
00767 dt_where Where
00768 } {
00769 interp alias $chk_ip $cmd {} ::doctools::$ckcmd $name
00770 }
00771 $chk_ip eval [list source [file join $here checker.tcl]]
00772
00773 # Simple expander commands are directly routed back into it, no
00774 # checking required.
00775
00776 foreach cmd {cappend cget cis cname cpop cpush ctopandclear cset lb rb} {
00777 interp alias $chk_ip $cmd {} $expander $cmd
00778 }
00779
00780 # Link the formatter commands into the checker. We use the prefix
00781 # 'fmt_' to distinguish them from the checking commands.
00782
00783 foreach cmd {
00784 manpage_begin moddesc titledesc copyright manpage_end require
00785 description section para list_begin list_end lst_item call
00786 bullet enum example example_begin example_end see_also
00787 keywords nl arg cmd opt comment sectref syscmd method option
00788 widget fun type package class var file uri usage term const
00789 arg_def cmd_def opt_def tkoption_def emph strong plain_text
00790 namespace subsection
00791 } {
00792 interp alias $chk_ip fmt_$cmd $format_ip fmt_$cmd
00793 }
00794 return
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 ret ::doctools::SetupExpander (type name) {
00808 upvar ::doctools::doctools${name}::ex_ok ex_ok
00809 if {$ex_ok} {return}
00810
00811 upvar ::doctools::doctools${name}::expander expander
00812 ::textutil::expander $expander
00813 $expander evalcmd [list ::doctools::Eval $name]
00814 $expander textcmd plain_text
00815 set ex_ok 1
00816 return
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 ret ::doctools::SearchPaths (type name) {
00831 upvar ::doctools::doctools${name}::paths opaths
00832 variable paths
00833
00834 set p $opaths
00835 foreach s $paths {lappend p $s}
00836 return $p
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 ret ::doctools::Deprecated (type name) {
00851 upvar ::doctools::doctools${name}::deprecated deprecated
00852 return $deprecated
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 ret ::doctools::FmtError (type name , type text) {
00867 return -code error "(FmtError) $text"
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 ret ::doctools::FmtWarning (type name , type text) {
00882 upvar ::doctools::doctools${name}::msg msg
00883 lappend msg $text
00884 return
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 ret ::doctools::Where (type name) {
00898 upvar ::doctools::doctools${name}::expander expander
00899 return [$expander where]
00900 }
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 ret ::doctools::Eval (type name , type macro) {
00914 upvar ::doctools::doctools${name}::chk_ip chk_ip
00915
00916 #puts stderr "\t\t$name [lindex [split $macro] 0]"
00917
00918 # Handle the [include] command directly
00919 if {[string match include* $macro]} {
00920 foreach {cmd filename} $macro break
00921 return [ExpandInclude $name $filename]
00922 }
00923
00924 # Rewrite the [namespace] command before passing it on.
00925 # "namespace" is a special command. The interpreter the validator
00926 # resides in uses the package "msgcat", which in turn uses the
00927 # builtin namespace. So the builtin cannot be simply
00928 # overwritten. We use a different name.
00929
00930 if {[string match namespace* $macro]} {
00931 set macro _$macro
00932 }
00933 return [$chk_ip eval $macro]
00934 }
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 ret ::doctools::ExpandInclude (type name , type path) {
00948 upvar ::doctools::doctools${name}::file file
00949
00950 set ipath [file join [file dirname $file] $path]
00951 if {![file exists $ipath]} {
00952 set ipath $path
00953 if {![file exists $ipath]} {
00954 return -code error "Unable to find include file \"$path\""
00955 }
00956 }
00957
00958 set chan [open $ipath r]
00959 set text [read $chan]
00960 close $chan
00961
00962 upvar ::doctools::doctools${name}::expander expander
00963
00964 return [$expander expand $text]
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 ret ::doctools::GetUser (type name) {
00978 global tcl_platform
00979 return $tcl_platform(user)
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 ret ::doctools::GetFile (type name) {
00993
00994 #puts stderr "GetFile $name"
00995
00996 upvar ::doctools::doctools${name}::file file
00997
00998 #puts stderr "ok $file"
00999 return $file
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 ret ::doctools::GetFileId (type name) {
01013 return [file rootname [file tail [GetFile $name]]]
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 ret ::doctools::FileCmd (type cmd , type args) {
01027 switch -exact -- $cmd {
01028 split {return [eval file split $args]}
01029 join {return [eval file join $args]}
01030 }
01031 return -code error "Illegal subcommand: $cmd $args"
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 ret ::doctools::GetModule (type name) {
01045 upvar ::doctools::doctools${name}::module module
01046 return $module
01047 }
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 ret ::doctools::GetCopyright (type name) {
01060 upvar ::doctools::doctools${name}::copyright copyright
01061 return $copyright
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 ret ::doctools::GetFormat (type name) {
01075 upvar ::doctools::doctools${name}::format format
01076 return $format
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 ret ::doctools::ListLevel (type name) {
01090 upvar ::doctools::doctools${name}::chk_ip chk_ip
01091 return [$chk_ip eval LNest]
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 ret ::doctools::MapFile (type name , type fname) {
01108 upvar ::doctools::doctools${name}::map map
01109
01110 #parray map
01111
01112 if {[info exists map($fname)]} {
01113 return $map($fname)
01114 }
01115 return $fname
01116 }
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 ret ::doctools::Source (type ip , type path , type file) {
01130 #puts stderr "$ip (source $path $file)"
01131
01132 $ip invokehidden source [file join $path [file tail $file]]
01133 #$ip eval [list source [file join $path [file tail $file]]]
01134 return
01135 }
01136
01137
01138 ret ::doctools::Locate (type p) {
01139 # @mdgen NODEP: doctools::__undefined__
01140 catch {package require doctools::__undefined__}
01141
01142 #puts stderr "auto_path = [join $::auto_path \n]"
01143
01144 # Check if requested package is in the list of loadable packages.
01145 # Then get the highest possible version, and then the index script
01146
01147 if {[lsearch -exact [package names] $p] < 0} {
01148 return -code error "Unknown package $p"
01149 }
01150
01151 set v [lindex [lsort -increasing [package versions $p]] end]
01152
01153 #puts stderr "Package $p = $v"
01154
01155 return [package ifneeded $p $v]
01156 }
01157
01158 ret ::doctools::FileOp (type ip , type args) {
01159 #puts stderr "$ip (file $args)"
01160 # -- FUTURE -- disallow unsafe operations --
01161
01162 return [eval [linsert $args 0 file]]
01163 }
01164
01165
01166 ret ::doctools::Package (type ip , type pkg) {
01167 #puts stderr "$ip package require $pkg"
01168
01169 set indexScript [Locate $pkg]
01170
01171 $ip expose source
01172 $ip expose load
01173 $ip eval $indexScript
01174 $ip hide source
01175 $ip hide load
01176 #$ip eval [list source [file join $path [file tail $file]]]
01177 return
01178 }
01179
01180
01181
01182
01183 namespace ::doctools {
01184
01185
01186
01187
01188
01189
01190
01191 catch {search [file join $here mpformats]}
01192 }
01193
01194 package provide doctools 1.3
01195