doctoc.tcl

Go to the documentation of this file.
00001 /*  doctoc.tcl --*/
00002 /* */
00003 /*  Implementation of doctoc objects for Tcl.*/
00004 /* */
00005 /*  Copyright (c) 2003-2007 Andreas Kupries <andreas_kupries@sourceforge.net>*/
00006 /* */
00007 /*  See the file "license.terms" for information on usage and redistribution*/
00008 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00009 /*  */
00010 /*  RCS: @(#) $Id: doctoc.tcl,v 1.14 2007/08/20 20:11:59 andreas_kupries Exp $*/
00011 
00012 package require Tcl 8.2
00013 package require textutil::expander
00014 
00015 /*  @mdgen OWNER: api_toc.tcl*/
00016 /*  @mdgen OWNER: checker_toc.tcl*/
00017 /*  @mdgen OWNER: mpformats/*.tcl*/
00018 /*  @mdgen OWNER: mpformats/*.msg*/
00019 /*  @mdgen OWNER: mpformats/toc.**/
00020 
00021 namespace ::doctools {}
00022 namespace ::doctools::toc {
00023     /*  Data storage in the doctools::toc module*/
00024     /*  -------------------------------*/
00025     /* */
00026     /*  One namespace per object, containing*/
00027     /*   1) A list of additional search paths for format definition files.*/
00028     /*      This list extends the list of standard paths known to the module.*/
00029     /*      The paths in the list are searched before the standard paths.*/
00030     /*   2) Configuration information*/
00031     /*      a) string:  The format to use when converting the input.*/
00032     /*   4) Name of the interpreter used to perform the syntax check of the*/
00033     /*      input (= allowed order of formatting commands).*/
00034     /*   5) Name of the interpreter containing the code coming from the format*/
00035     /*      definition file.*/
00036     /*   6) Name of the expander object used to interpret the input to convert.*/
00037 
00038     /*  commands is the list of subcommands recognized by the doctoc objects*/
00039     variable commands [list     \
00040         "cget"          \
00041         "configure"         \
00042         "destroy"           \
00043         "format"            \
00044         "map"           \
00045         "search"            \
00046         "warnings"                  \
00047         "parameters"                \
00048         "param = "                  \
00049         ]
00050 
00051     /*  Only export the toplevel commands*/
00052     namespace export new search help
00053 
00054     /*  Global data*/
00055 
00056     /*   1) List of standard paths to look at when searching for a format*/
00057     /*      definition. Extensible.*/
00058     /*   2) Location of this file in the filesystem*/
00059 
00060     variable paths [list]
00061     variable here [file dirname [info script]]
00062 }
00063 
00064 /*  ::doctools::toc::search --*/
00065 /* */
00066 /*  Extend the list of paths used when searching for format definition files.*/
00067 /* */
00068 /*  Arguments:*/
00069 /*  path    Path to add to the list. The path has to exist, has to be a*/
00070 /*                directory, and has to be readable.*/
00071 /* */
00072 /*  Results:*/
00073 /*  None.*/
00074 /* */
00075 /*  Sideeffects:*/
00076 /*  The specified path is added to the front of the list of search*/
00077 /*  paths. This means that the new path is search before the*/
00078 /*  standard paths set at module initialization time.*/
00079 
00080 ret  ::doctools::toc::search (type path) {
00081     variable paths
00082 
00083     if {![file exists      $path]} {return -code error "doctools::toc::search: path does not exist"}
00084     if {![file isdirectory $path]} {return -code error "doctools::toc::search: path is not a directory"}
00085     if {![file readable    $path]} {return -code error "doctools::toc::search: path cannot be read"}
00086 
00087     set paths [linsert $paths 0 $path]
00088     return
00089 }
00090 
00091 /*  ::doctools::toc::help --*/
00092 /* */
00093 /*  Return a string containing short help*/
00094 /*  regarding the existing formatting commands.*/
00095 /* */
00096 /*  Arguments:*/
00097 /*  None.*/
00098 /* */
00099 /*  Results:*/
00100 /*  A string.*/
00101 
00102 ret  ::doctools::toc::help () {
00103     return "formatting commands\n\
00104         * toc_begin      - begin of table of contents\n\
00105         * toc_end        - end of toc\n\
00106         * division_start - begin of toc division\n\
00107         * division_end   - end of toc division\n\
00108         * item           - toc element\n\
00109         * vset           - set/get variable values\n\
00110         * include        - insert external file\n\
00111         * lb, rb         - left/right brackets\n\
00112         "
00113 }
00114 
00115 /*  ::doctools::toc::new --*/
00116 /* */
00117 /*  Create a new doctoc object with a given name. May configure the object.*/
00118 /* */
00119 /*  Arguments:*/
00120 /*  name    Name of the doctoc object.*/
00121 /*  args    Options configuring the new object.*/
00122 /* */
00123 /*  Results:*/
00124 /*  name    Name of the doctools created*/
00125 
00126 ret  ::doctools::toc::new (type name , type args) {
00127         if { [llength [info commands ::$name]] } {
00128     return -code error "command \"$name\" already exists, unable to create doctoc object"
00129     }
00130     if {[llength $args] % 2 == 1} {
00131     return -code error "wrong # args: doctools::new name ?opt val...??"
00132     }
00133 
00134     # The arguments seem to be ok, setup the namespace for the object
00135 
00136     namespace eval ::doctools::toc::doctoc$name {
00137     variable paths      [list]
00138     variable file       ""
00139     variable format     ""
00140     variable formatfile ""
00141     variable format_ip  ""
00142     variable chk_ip     ""
00143     variable expander   "[namespace current]::ex"
00144     variable ex_ok      0
00145     variable msg        [list]
00146     variable map ;      array set map {}
00147     variable param      [list]
00148     }
00149 
00150     # Create the command to manipulate the object
00151     #                 $name -> ::doctools::toc::DocTocProc $name
00152     interp alias {} ::$name {} ::doctools::toc::DocTocProc $name
00153 
00154     # If the name was followed by arguments use them to configure the
00155     # object before returning its handle to the caller.
00156 
00157     if {[llength $args] > 1} {
00158     # Use linsert trick to make the command a pure list.
00159     eval [linsert $args 0 _configure $name]
00160     }
00161     return $name
00162 }
00163 
00164 /* */
00165 /*  Private functions follow*/
00166 
00167 /*  ::doctools::toc::DocTocProc --*/
00168 /* */
00169 /*  Command that processes all doctoc object commands.*/
00170 /*  Dispatches any object command to the appropriate internal*/
00171 /*  command implementing its functionality.*/
00172 /* */
00173 /*  Arguments:*/
00174 /*  name    Name of the doctoc object to manipulate.*/
00175 /*  cmd Subcommand to invoke.*/
00176 /*  args    Arguments for subcommand.*/
00177 /* */
00178 /*  Results:*/
00179 /*  Varies based on command to perform*/
00180 
00181 ret  ::doctools::toc::DocTocProc (type name , optional cmd ="" , type args) {
00182     # Do minimal args checks here
00183     if { [llength [info level 0]] == 2 } {
00184     error "wrong # args: should be \"$name option ?arg arg ...?\""
00185     }
00186     
00187     # Split the args into command and args components
00188 
00189     if { [llength [info commands ::doctools::toc::_$cmd]] == 0 } {
00190     variable commands
00191     set optlist [join $commands ", "]
00192     set optlist [linsert $optlist "end-1" "or"]
00193     return -code error "bad option \"$cmd\": must be $optlist"
00194     }
00195     return [eval [list ::doctools::toc::_$cmd $name] $args]
00196 }
00197 
00198 /* */
00199 /*  Method implementations follow (these are also private commands)*/
00200 
00201 /*  ::doctools::toc::_cget --*/
00202 /* */
00203 /*  Retrieve the current value of a particular option*/
00204 /* */
00205 /*  Arguments:*/
00206 /*  name    Name of the doctoc object to query*/
00207 /*  option  Name of the option whose value we are asking for.*/
00208 /* */
00209 /*  Results:*/
00210 /*  The value of the option*/
00211 
00212 ret  ::doctools::toc::_cget (type name , type option) {
00213     _configure $name $option
00214 }
00215 
00216 /*  ::doctools::toc::_configure --*/
00217 /* */
00218 /*  Configure a doctoc object, or query its configuration.*/
00219 /* */
00220 /*  Arguments:*/
00221 /*  name    Name of the doctoc object to configure*/
00222 /*  args    Options and their values.*/
00223 /* */
00224 /*  Results:*/
00225 /*  None if configuring the object.*/
00226 /*  A list of all options and their values if called without arguments.*/
00227 /*  The value of one particular option if called with a single argument.*/
00228 
00229 ret  ::doctools::toc::_configure (type name , type args) {
00230     if {[llength $args] == 0} {
00231     # Retrieve the current configuration.
00232 
00233     upvar ::doctools::toc::doctoc${name}::file    file
00234     upvar ::doctools::toc::doctoc${name}::format  format
00235 
00236     set     res [list]
00237     lappend res -file       $file
00238     lappend res -format     $format
00239     return $res
00240 
00241     } elseif {[llength $args] == 1} {
00242     # Query the value of one particular option.
00243 
00244     switch -exact -- [lindex $args 0] {
00245         -file {
00246         upvar ::doctools::toc::doctoc${name}::file file
00247         return $file
00248         }
00249         -format {
00250         upvar ::doctools::toc::doctoc${name}::format format
00251         return $format
00252         }
00253         default {
00254         return -code error \
00255             "doctools::toc::_configure: Unknown option \"[lindex $args 0]\", expected\
00256             -file, or -format"
00257         }
00258     }
00259     } else {
00260     # Reconfigure the object.
00261 
00262     if {[llength $args] % 2 == 1} {
00263         return -code error "wrong # args: doctools::toc::_configure name ?opt val...??"
00264     }
00265 
00266     foreach {option value} $args {
00267         switch -exact -- $option {
00268         -file {
00269             upvar ::doctools::toc::doctoc${name}::file file
00270             set file $value
00271         }
00272         -format {
00273             if {[catch {
00274             set fmtfile [LookupFormat $name $value]
00275             SetupFormatter $name $fmtfile
00276             upvar ::doctools::toc::doctoc${name}::format format
00277             set format $value
00278             } msg]} {
00279             return -code error "doctools::toc::_configure: -format: $msg"
00280             }
00281         }
00282         default {
00283             return -code error \
00284                 "doctools::toc::_configure: Unknown option \"$option\", expected\
00285                 -file, or -format"
00286         }
00287         }
00288     }
00289     }
00290     return ""
00291 }
00292 
00293 /*  ::doctools::toc::_destroy --*/
00294 /* */
00295 /*  Destroy a doctoc object, including its associated command and data storage.*/
00296 /* */
00297 /*  Arguments:*/
00298 /*  name    Name of the doctoc object to destroy.*/
00299 /* */
00300 /*  Results:*/
00301 /*  None.*/
00302 
00303 ret  ::doctools::toc::_destroy (type name) {
00304     # Check the object for sub objects which have to destroyed before
00305     # the namespace is torn down.
00306     namespace eval ::doctools::toc::doctoc$name {
00307     if {$format_ip != ""} {interp delete $format_ip}
00308     if {$chk_ip    != ""} {interp delete $chk_ip}
00309 
00310     # Expander objects have no delete/destroy method. This would
00311     # be a leak if not for the fact that an expander object is a
00312     # namespace, and we have arranged to make it a sub namespace of
00313     # the doctoc object. Therefore tearing down our object namespace
00314     # also cleans up the expander object.
00315     # if {$expander != ""} {$expander destroy}
00316 
00317     }
00318     namespace delete ::doctools::toc::doctoc$name
00319     interp alias {} ::$name {}
00320     return
00321 }
00322 
00323 /*  ::doctools::toc::_map --*/
00324 /* */
00325 /*  Add a mapping from symbolic to actual filename to the object.*/
00326 /* */
00327 /*  Arguments:*/
00328 /*  name    Name of the doctoc object to use*/
00329 /*  sfname  Symbolic filename to map*/
00330 /*  afname  Actual filename*/
00331 /* */
00332 /*  Results:*/
00333 /*  None.*/
00334 
00335 ret  ::doctools::toc::_map (type name , type sfname , type afname) {
00336     upvar ::doctools::toc::doctoc${name}::map map
00337     set map($sfname) $afname
00338     return
00339 }
00340 
00341 /*  ::doctools::toc::_format --*/
00342 /* */
00343 /*  Convert some text in doctools format*/
00344 /*  according to the configuration in the object.*/
00345 /* */
00346 /*  Arguments:*/
00347 /*  name    Name of the doctoc object to use*/
00348 /*  text    Text to convert.*/
00349 /* */
00350 /*  Results:*/
00351 /*  The conversion result.*/
00352 
00353 ret  ::doctools::toc::_format (type name , type text) {
00354     upvar ::doctools::toc::doctoc${name}::format format
00355     if {$format == ""} {
00356     return -code error "$name: No format was specified"
00357     }
00358 
00359     upvar ::doctools::toc::doctoc${name}::format_ip format_ip
00360     upvar ::doctools::toc::doctoc${name}::chk_ip    chk_ip
00361     upvar ::doctools::toc::doctoc${name}::ex_ok     ex_ok
00362     upvar ::doctools::toc::doctoc${name}::expander  expander
00363     upvar ::doctools::toc::doctoc${name}::passes    passes
00364     upvar ::doctools::toc::doctoc${name}::msg       warnings
00365 
00366     if {!$ex_ok}       {SetupExpander  $name}
00367     if {$chk_ip == ""} {SetupChecker   $name}
00368     # assert (format_ip != "")
00369 
00370     set warnings [list]
00371     if {[catch {$format_ip eval toc_initialize}]} {
00372     return -code error "Could not initialize engine"
00373     }
00374     set result ""
00375 
00376     for {
00377     set p $passes ; set n 1
00378     } {
00379     $p > 0
00380     } {
00381     incr p -1 ; incr n
00382     } {
00383     if {[catch {$format_ip eval [list toc_setup $n]}]} {
00384         catch {$format_ip eval toc_shutdown}
00385         return -code error "Could not initialize pass $n of engine"
00386     }
00387     $chk_ip eval ck_initialize
00388 
00389     if {[catch {set result [$expander expand $text]} msg]} {
00390         catch {$format_ip eval toc_shutdown}
00391         # Filter for checker errors and reduce them to the essential message.
00392 
00393         if {![regexp {^Error in} $msg]}          {return -code error $msg}
00394         #set msg [join [lrange [split $msg \n] 2 end]]
00395 
00396         if {![regexp {^--> \(FmtError\) } $msg]} {return -code error "Doctoc $msg"}
00397         set msg [lindex [split $msg \n] 0]
00398         regsub {^--> \(FmtError\) } $msg {} msg
00399 
00400         return -code error $msg
00401     }
00402 
00403     $chk_ip eval ck_complete
00404     }
00405 
00406     if {[catch {set result [$format_ip eval [list toc_postprocess $result]]}]} {
00407     return -code error "Unable to post process final result"
00408     }
00409     if {[catch {$format_ip eval toc_shutdown}]} {
00410     return -code error "Could not shut engine down"
00411     }
00412     return $result
00413 
00414 }
00415 
00416 /*  ::doctools::toc::_search --*/
00417 /* */
00418 /*  Add a search path to the object.*/
00419 /* */
00420 /*  Arguments:*/
00421 /*  name    Name of the doctoc object to extend*/
00422 /*  path    Search path to add.*/
00423 /* */
00424 /*  Results:*/
00425 /*  None.*/
00426 
00427 ret  ::doctools::toc::_search (type name , type path) {
00428     if {![file exists      $path]} {return -code error "$name search: path does not exist"}
00429     if {![file isdirectory $path]} {return -code error "$name search: path is not a directory"}
00430     if {![file readable    $path]} {return -code error "$name search: path cannot be read"}
00431 
00432     upvar ::doctools::toc::doctoc${name}::paths paths
00433     set paths [linsert $paths 0 $path]
00434     return
00435 }
00436 
00437 /*  ::doctools::toc::_warnings --*/
00438 /* */
00439 /*  Return the warning accumulated during the last invocation of 'format'.*/
00440 /* */
00441 /*  Arguments:*/
00442 /*  name    Name of the doctoc object to query*/
00443 /* */
00444 /*  Results:*/
00445 /*  A list of warnings.*/
00446 
00447 ret  ::doctools::toc::_warnings (type name) {
00448     upvar ::doctools::toc::doctoc${name}::msg msg
00449     return $msg
00450 }
00451 
00452 /*  ::doctools::_parameters --*/
00453 /* */
00454 /*  Returns a list containing the parameters provided*/
00455 /*  by the selected formatting engine.*/
00456 /* */
00457 /*  Arguments:*/
00458 /*  name    Name of the doctools object to query*/
00459 /* */
00460 /*  Results:*/
00461 /*  A list of parameter names*/
00462 
00463 ret  ::doctools::toc::_parameters (type name) {
00464     upvar ::doctools::toc::doctoc${name}::param param
00465     return $param
00466 }
00467 
00468 /*  ::doctools::_setparam --*/
00469 /* */
00470 /*  Set a named engine parameter to a value.*/
00471 /* */
00472 /*  Arguments:*/
00473 /*  name    Name of the doctools object to query*/
00474 /*  param   Name of the parameter to set.*/
00475 /*  value   Value to set the parameter to.*/
00476 /* */
00477 /*  Results:*/
00478 /*  None.*/
00479 
00480 ret  ::doctools::toc::_setparam (type name , type param , type value) {
00481     upvar ::doctools::toc::doctoc${name}::format_ip format_ip
00482 
00483     if {$format_ip == {}} {
00484     return -code error \
00485         "Unable to set parameters without a valid format"
00486     }
00487 
00488     $format_ip eval [list toc_varset $param $value]
00489     return
00490 }
00491 
00492 /* */
00493 /*  Support commands*/
00494 
00495 /*  ::doctools::toc::LookupFormat --*/
00496 /* */
00497 /*  Search a format definition file based upon its name*/
00498 /* */
00499 /*  Arguments:*/
00500 /*  name    Name of the doctoc object to use*/
00501 /*  format  Name of the format to look for.*/
00502 /* */
00503 /*  Results:*/
00504 /*  The file containing the format definition*/
00505 
00506 ret  ::doctools::toc::LookupFormat (type name , type format) {
00507     # Order of searching
00508     # 1) Is the name of the format an existing file ?
00509     #    If yes, take this file.
00510     # 2) Look for the file in the directories given to the object itself..
00511     # 3) Look for the file in the standard directories of this package.
00512 
00513     if {[file exists $format]} {
00514     return $format
00515     }
00516 
00517     upvar ::doctools::toc::doctoc${name}::paths opaths
00518     foreach path $opaths {
00519     set f [file join $path toc.$format]
00520     if {[file exists $f]} {
00521         return $f
00522     }
00523     }
00524 
00525     variable paths
00526     foreach path $paths {
00527     set f [file join $path toc.$format]
00528     if {[file exists $f]} {
00529         return $f
00530     }
00531     }
00532 
00533     return -code error "Unknown format \"$format\""
00534 }
00535 
00536 /*  ::doctools::toc::SetupFormatter --*/
00537 /* */
00538 /*  Create and initializes an interpreter containing a*/
00539 /*  formatting engine*/
00540 /* */
00541 /*  Arguments:*/
00542 /*  name    Name of the doctoc object to manipulate*/
00543 /*  format  Name of file containing the code of the engine*/
00544 /* */
00545 /*  Results:*/
00546 /*  None.*/
00547 
00548 ret  ::doctools::toc::SetupFormatter (type name , type format) {
00549 
00550     # Create and initialize the interpreter first.
00551     # Use a transient variable. Interrogate the
00552     # engine and check its response. Bail out in
00553     # case of errors. Only if we pass the checks
00554     # we tear down the old engine and make the new
00555     # one official.
00556 
00557     variable here
00558     set mpip [interp create -safe] ; # interpreter for the formatting engine
00559     #set mpip [interp create] ; # interpreter for the formatting engine
00560 
00561     $mpip invokehidden source [file join $here api_toc.tcl]
00562     #$mpip eval [list source [file join $here api_toc.tcl]]
00563     interp alias $mpip dt_source   {} ::doctools::toc::Source $mpip [file dirname $format]
00564     interp alias $mpip dt_package  {} ::doctools::Package $mpip
00565     interp alias $mpip file        {} ::doctools::FileOp  $mpip
00566     interp alias $mpip puts_stderr {} ::puts stderr
00567     $mpip invokehidden source $format
00568     #$mpip eval [list source $format]
00569 
00570     # Check the engine for useability in doctools.
00571 
00572     foreach api {
00573     toc_numpasses
00574     toc_initialize
00575     toc_setup
00576     toc_postprocess
00577     toc_shutdown
00578     toc_listvariables
00579     toc_varset
00580     } {
00581     if {[$mpip eval [list info commands $api]] == {}} {
00582         interp delete $mpip
00583         error "$format error: API incomplete, cannot use this engine"
00584     }
00585     }
00586     if {[catch {
00587     set passes [$mpip eval toc_numpasses]
00588     }]} {
00589     interp delete $mpip
00590     error "$format error: Unable to query for number of passes"
00591     }
00592     if {![string is integer $passes] || ($passes < 1)} {
00593     interp delete $mpip
00594     error "$format error: illegal number of passes \"$passes\""
00595     }
00596     if {[catch {
00597     set parameters [$mpip eval toc_listvariables]
00598     }]} {
00599     interp delete $mpip
00600     error "$format error: Unable to query for list of parameters"
00601     }
00602 
00603     # Passed the tests. Tear down existing engine,
00604     # and checker. The latter is destroyed because
00605     # of its aliases into the formatter, which are
00606     # now invalid. It will be recreated during the
00607     # next call of 'format'.
00608 
00609     upvar ::doctools::toc::doctoc${name}::formatfile formatfile
00610     upvar ::doctools::toc::doctoc${name}::format_ip  format_ip
00611     upvar ::doctools::toc::doctoc${name}::chk_ip     chk_ip
00612     upvar ::doctools::toc::doctoc${name}::expander   expander
00613     upvar ::doctools::toc::doctoc${name}::passes     xpasses
00614     upvar ::doctools::toc::doctoc${name}::param      xparam
00615 
00616     if {$chk_ip != {}}    {interp delete $chk_ip}
00617     if {$format_ip != {}} {interp delete $format_ip}
00618 
00619     set chk_ip    ""
00620     set format_ip ""
00621 
00622     # Now link engine API into it.
00623 
00624     interp alias $mpip dt_format    {} ::doctools::toc::GetFormat    $name
00625     interp alias $mpip dt_user      {} ::doctools::toc::GetUser      $name
00626     interp alias $mpip dt_fmap      {} ::doctools::toc::MapFile      $name
00627 
00628     foreach cmd {cappend cget cis cname cpop cpush cset lb rb} {
00629     interp alias $mpip ex_$cmd {} $expander $cmd
00630     }
00631 
00632     set format_ip  $mpip
00633     set formatfile $format
00634     set xpasses    $passes
00635     set xparam     $parameters
00636     return
00637 }
00638 
00639 /*  ::doctools::toc::SetupChecker --*/
00640 /* */
00641 /*  Create and initializes an interpreter for checking the usage of*/
00642 /*  doctoc formatting commands*/
00643 /* */
00644 /*  Arguments:*/
00645 /*  name    Name of the doctoc object to manipulate*/
00646 /* */
00647 /*  Results:*/
00648 /*  None.*/
00649 
00650 ret  ::doctools::toc::SetupChecker (type name) {
00651     # Create an interpreter for checking the usage of doctoc formatting commands
00652     # and initialize it: Link it to the interpreter doing the formatting, the
00653     # expander object and the configuration information. All of which
00654     # is accessible through the token/handle (name of state/object array).
00655 
00656     variable here
00657 
00658     upvar ::doctools::toc::doctoc${name}::chk_ip    chk_ip
00659     if {$chk_ip != ""} {return}
00660 
00661     upvar ::doctools::toc::doctoc${name}::expander  expander
00662     upvar ::doctools::toc::doctoc${name}::format_ip format_ip
00663 
00664     set chk_ip [interp create] ; # interpreter hosting the formal format checker
00665 
00666     # Make configuration available through command, then load the code base.
00667 
00668     foreach {cmd ckcmd} {
00669     dt_search     SearchPaths
00670     dt_error      FmtError
00671     dt_warning    FmtWarning
00672     } {
00673     interp alias $chk_ip $cmd {} ::doctools::toc::$ckcmd $name
00674     }
00675     $chk_ip eval [list source [file join $here checker_toc.tcl]]
00676 
00677     # Simple expander commands are directly routed back into it, no
00678     # checking required.
00679 
00680     foreach cmd {cappend cget cis cname cpop cpush cset lb rb} {
00681     interp alias $chk_ip $cmd {} $expander $cmd
00682     }
00683 
00684     # Link the formatter commands into the checker. We use the prefix
00685     # 'fmt_' to distinguish them from the checking commands.
00686 
00687     foreach cmd {
00688     toc_begin toc_end division_start division_end item
00689     comment plain_text
00690     } {
00691     interp alias $chk_ip fmt_$cmd $format_ip fmt_$cmd
00692     }
00693     return
00694 }
00695 
00696 /*  ::doctools::toc::SetupExpander --*/
00697 /* */
00698 /*  Create and initializes the expander for input*/
00699 /* */
00700 /*  Arguments:*/
00701 /*  name    Name of the doctoc object to manipulate*/
00702 /* */
00703 /*  Results:*/
00704 /*  None.*/
00705 
00706 ret  ::doctools::toc::SetupExpander (type name) {
00707     upvar ::doctools::toc::doctoc${name}::ex_ok    ex_ok
00708     if {$ex_ok} {return}
00709 
00710     upvar ::doctools::toc::doctoc${name}::expander expander
00711     ::textutil::expander $expander
00712     $expander evalcmd [list ::doctools::toc::Eval $name]
00713     $expander textcmd plain_text
00714     set ex_ok 1
00715     return
00716 }
00717 
00718 /*  ::doctools::toc::SearchPaths --*/
00719 /* */
00720 /*  API for checker. Returns list of search paths for format*/
00721 /*  definitions. Used to look for message catalogs as well.*/
00722 /* */
00723 /*  Arguments:*/
00724 /*  name    Name of the doctoc object to query.*/
00725 /* */
00726 /*  Results:*/
00727 /*  None.*/
00728 
00729 ret  ::doctools::toc::SearchPaths (type name) {
00730     upvar ::doctools::toc::doctoc${name}::paths opaths
00731     variable paths
00732 
00733     set p $opaths
00734     foreach s $paths {lappend p $s}
00735     return $p
00736 }
00737 
00738 /*  ::doctools::toc::FmtError --*/
00739 /* */
00740 /*  API for checker. Called when an error occurred.*/
00741 /* */
00742 /*  Arguments:*/
00743 /*  name    Name of the doctoc object to query.*/
00744 /*  text    Error message*/
00745 /* */
00746 /*  Results:*/
00747 /*  None.*/
00748 
00749 ret  ::doctools::toc::FmtError (type name , type text) {
00750     return -code error "(FmtError) $text"
00751 }
00752 
00753 /*  ::doctools::toc::FmtWarning --*/
00754 /* */
00755 /*  API for checker. Called when a warning was generated*/
00756 /* */
00757 /*  Arguments:*/
00758 /*  name    Name of the doctoc object*/
00759 /*  text    Warning message*/
00760 /* */
00761 /*  Results:*/
00762 /*  None.*/
00763 
00764 ret  ::doctools::toc::FmtWarning (type name , type text) {
00765     upvar ::doctools::toc::doctoc${name}::msg msg
00766     lappend msg $text
00767     return
00768 }
00769 
00770 /*  ::doctools::toc::Eval --*/
00771 /* */
00772 /*  API for expander. Routes the macro invocations*/
00773 /*  into the checker interpreter*/
00774 /* */
00775 /*  Arguments:*/
00776 /*  name    Name of the doctoc object to query.*/
00777 /* */
00778 /*  Results:*/
00779 /*  None.*/
00780 
00781 ret  ::doctools::toc::Eval (type name , type macro) {
00782     upvar ::doctools::toc::doctoc${name}::chk_ip chk_ip
00783 
00784     # Handle the [include] command directly
00785     if {[string match include* $macro]} {
00786     foreach {cmd filename} $macro break
00787     return [ExpandInclude $name $filename]
00788     }
00789 
00790     return [$chk_ip eval $macro]
00791 }
00792 
00793 /*  ::doctools::toc::ExpandInclude --*/
00794 /* */
00795 /*  Handle inclusion of files.*/
00796 /* */
00797 /*  Arguments:*/
00798 /*  name    Name of the doctoc object to query.*/
00799 /*  path    Name of file to include and expand.*/
00800 /* */
00801 /*  Results:*/
00802 /*  None.*/
00803 
00804 ret  ::doctools::toc::ExpandInclude (type name , type path) {
00805     # Look for the file relative to the directory of the
00806     # main file we are converting. If that fails try to
00807     # use the current working directory. Throw an error
00808     # if the file couldn't be found.
00809 
00810     upvar ::doctools::toc::doctoc${name}::file file
00811 
00812     set ipath [file join [file dirname $file] $path]
00813     if {![file exists $ipath]} {
00814     set ipath $path
00815     if {![file exists $ipath]} {
00816         return -code error "Unable to fine include file \"$path\""
00817     }
00818     }
00819 
00820     set    chan [open $ipath r]
00821     set    text [read $chan]
00822     close $chan
00823 
00824     upvar ::doctools::toc::doctoc${name}::expander  expander
00825 
00826     return [$expander expand $text]
00827 }
00828 
00829 /*  ::doctools::toc::GetUser --*/
00830 /* */
00831 /*  API for formatter. Returns name of current user*/
00832 /* */
00833 /*  Arguments:*/
00834 /*  name    Name of the doctoc object to query.*/
00835 /* */
00836 /*  Results:*/
00837 /*  String, name of current user.*/
00838 
00839 ret  ::doctools::toc::GetUser (type name) {
00840     global  tcl_platform
00841     return $tcl_platform(user)
00842 }
00843 
00844 /*  ::doctools::toc::GetFormat --*/
00845 /* */
00846 /*  API for formatter. Returns format information*/
00847 /* */
00848 /*  Arguments:*/
00849 /*  name    Name of the doctoc object to query.*/
00850 /* */
00851 /*  Results:*/
00852 /*  Format information*/
00853 
00854 ret  ::doctools::toc::GetFormat (type name) {
00855     upvar ::doctools::toc::doctoc${name}::format format
00856     return $format
00857 }
00858 
00859 /*  ::doctools::toc::MapFile --*/
00860 /* */
00861 /*  API for formatter. Maps symbolic to actual filename in a toc*/
00862 /*  item. If no mapping is found it is assumed that the symbolic*/
00863 /*  name is also the actual name.*/
00864 /* */
00865 /*  Arguments:*/
00866 /*  name    Name of the doctoc object to query.*/
00867 /*  fname   Symbolic name of the file.*/
00868 /* */
00869 /*  Results:*/
00870 /*  Actual name of the file.*/
00871 
00872 ret  ::doctools::toc::MapFile (type name , type fname) {
00873     upvar ::doctools::toc::doctoc${name}::map map
00874     if {[info exists map($fname)]} {
00875     return $map($fname)
00876     }
00877     return $fname
00878 }
00879 
00880 /*  ::doctools::toc::Source --*/
00881 /* */
00882 /*  API for formatter. Used by engine to ask for*/
00883 /*  additional script files support it.*/
00884 /* */
00885 /*  Arguments:*/
00886 /*  name    Name of the doctoc object to change.*/
00887 /* */
00888 /*  Results:*/
00889 /*  Boolean flag.*/
00890 
00891 ret  ::doctools::toc::Source (type ip , type path , type file) {
00892     $ip invokehidden source [file join $path [file tail $file]]
00893     #$ip eval [list source [file join $path [file tail $file]]]
00894     return
00895 }
00896 
00897 /* ------------------------------------*/
00898 /*  Module initialization*/
00899 
00900 namespace ::doctools::toc {
00901     /*  Reverse order of searching. First to search is specified last.*/
00902 
00903     /*  FOO/doctoc.tcl*/
00904     /*  => FOO/mpformats*/
00905 
00906     /* catch {search [file join $here                lib doctools mpformats]}*/
00907     /* catch {search [file join [file dirname $here] lib doctools mpformats]}*/
00908     catch {search [file join $here                             mpformats]}
00909 }
00910 
00911 package provide doctools::toc 0.3
00912 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1