page/pluginmgr.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  ### ### ### ######### ######### #########*/
00003 
00004 /*  This package provides custom plugin management specific to PAGE. It*/
00005 /*  is built on top of the generic plugin management framework (See*/
00006 /*  ---> pluginmgr).*/
00007 
00008 /*  ### ### ### ######### ######### #########*/
00009 /*  Requisites*/
00010 
00011 package require fileutil
00012 package require pluginmgr           ; /*  Generic plugin management framework*/
00013 
00014 namespace ::page::pluginmgr {}
00015 
00016 /*  ### ### ### ######### ######### #########*/
00017 /*  API (Public, exported)*/
00018 
00019 ret  ::page::pluginmgr::reportvia (type cmd) {
00020     variable reportcmd $cmd
00021     return
00022 }
00023 
00024 ret  ::page::pluginmgr::log (type cmd) {
00025     variable reader
00026     variable writer
00027     variable transforms
00028 
00029     set     iplist {}
00030     lappend iplist [$reader interpreter]
00031     lappend iplist [$writer interpreter]
00032     foreach t $transforms {
00033     lappend iplist [$t interpreter]
00034     }
00035 
00036     if {$cmd eq ""} {
00037     # No logging. Disable with empty command,
00038     # to allow the system to completely remove
00039     # them from the bytecode (= No execution
00040     # overhead).
00041 
00042     foreach ip $iplist {
00043         $ip eval [list proc page_log_error   args {}]
00044         $ip eval [list proc page_log_warning args {}]
00045         $ip eval [list proc page_log_info    args {}]
00046     }
00047     } else {
00048     # Activate logging. Make the commands in
00049     # the interpreters aliases to us.
00050 
00051     foreach ip $iplist {
00052         interp alias $ip page_log_error   {} ${cmd}::error
00053         interp alias $ip page_log_warning {} ${cmd}::warning
00054         interp alias $ip page_log_info    {} ${cmd}::info
00055     }
00056     }
00057     return
00058 }
00059 
00060 ret  ::page::pluginmgr::reader (type name) {
00061     variable reader
00062 
00063     $reader load $name
00064     return [$reader do page_roptions]
00065 }
00066 
00067 ret  ::page::pluginmgr::rconfigure (type dict) {
00068     variable reader
00069     foreach {k v} $dict {
00070     $reader do page_rconfigure $k $v
00071     }
00072     return
00073 }
00074 
00075 ret  ::page::pluginmgr::rtimeable () {
00076     variable reader
00077     return [$reader do page_rfeature timeable]
00078 }
00079 
00080 ret  ::page::pluginmgr::rtime () {
00081     variable reader
00082     $reader do page_rtime
00083     return
00084 }
00085 
00086 ret  ::page::pluginmgr::rgettime () {
00087     variable reader
00088     return [$reader do page_rgettime]
00089 }
00090 
00091 ret  ::page::pluginmgr::rhelp () {
00092     variable reader
00093     return [$reader do page_rhelp]
00094 }
00095 
00096 ret  ::page::pluginmgr::rlabel () {
00097     variable reader
00098     return [$reader do page_rlabel]
00099 }
00100 
00101 ret  ::page::pluginmgr::read (type read , type eof , optional complete ={)} {
00102     variable reader
00103 
00104     #interp alias $ip page_read {} {*}$read
00105     /* interp alias $ip page_eof  {} {*}$eof*/
00106 
00107      ip =  [$reader interpreter]
00108     eval [linsert $read 0 interp alias $ip page_read {}]
00109     eval [linsert $eof  0 interp alias $ip page_eof  {}]
00110 
00111     if {![llength $complete]} {
00112     interp alias $ip page_read_done {} ::page::pluginmgr::Nop
00113     } else {
00114     eval [linsert $complete  0 interp alias $ip page_read_done  {}]
00115     }
00116 
00117     return [$reader do page_rrun]
00118 }
00119 
00120 ret  ::page::pluginmgr::writer (type name) {
00121     variable writer
00122 
00123     $writer load $name
00124     return [$writer do page_woptions]
00125 }
00126 
00127 ret  ::page::pluginmgr::wconfigure (type dict) {
00128     variable writer
00129     foreach {k v} $dict {
00130     $writer do page_wconfigure $k $v
00131     }
00132     return
00133 }
00134 
00135 ret  ::page::pluginmgr::wtimeable () {
00136     variable writer
00137     return [$writer do page_wfeature timeable]
00138 }
00139 
00140 ret  ::page::pluginmgr::wtime () {
00141     variable writer
00142     $writer do page_wtime
00143     return
00144 }
00145 
00146 ret  ::page::pluginmgr::wgettime () {
00147     variable writer
00148     return [$writer do page_wgettime]
00149 }
00150 
00151 ret  ::page::pluginmgr::whelp () {
00152     variable writer
00153     return [$writer do page_whelp]
00154 }
00155 
00156 ret  ::page::pluginmgr::wlabel () {
00157     variable writer
00158     return [$writer do page_wlabel]
00159 }
00160 
00161 ret  ::page::pluginmgr::write (type chan , type data) {
00162     variable writer
00163 
00164     $writer do page_wrun $chan $data
00165     return
00166 }
00167 
00168 ret  ::page::pluginmgr::transform (type name) {
00169     variable transform
00170     variable transforms
00171 
00172     $transform load $name
00173 
00174     set id [llength $transforms]
00175     set opt [$transform do page_toptions]
00176     lappend transforms [$transform clone]
00177 
00178     return [list $id $opt]
00179 }
00180 
00181 ret  ::page::pluginmgr::tconfigure (type id , type dict) {
00182     variable transforms
00183 
00184     set t [lindex $transforms $id]
00185 
00186     foreach {k v} $dict {
00187     $t do page_tconfigure $k $v
00188     }
00189     return
00190 }
00191 
00192 ret  ::page::pluginmgr::ttimeable (type id) {
00193     variable transforms
00194     set t [lindex $transforms $id]
00195     return [$t do page_tfeature timeable]
00196 }
00197 
00198 ret  ::page::pluginmgr::ttime (type id) {
00199     variable transforms
00200     set t [lindex $transforms $id]
00201     $t do page_ttime
00202     return
00203 }
00204 
00205 ret  ::page::pluginmgr::tgettime (type id) {
00206     variable transforms
00207     set t [lindex $transforms $id]
00208     return [$t do page_tgettime]
00209 }
00210 
00211 ret  ::page::pluginmgr::thelp (type id) {
00212     variable transforms
00213     set t [lindex $transforms $id]
00214     return [$t do page_thelp]
00215 }
00216 
00217 ret  ::page::pluginmgr::tlabel (type id) {
00218     variable transforms
00219     set t [lindex $transforms $id]
00220     return [$t do page_tlabel]
00221 }
00222 
00223 ret  ::page::pluginmgr::transform_do (type id , type data) {
00224     variable transforms
00225     variable reader
00226 
00227     set t [lindex $transforms $id]
00228 
00229     return [$t do page_trun $data]
00230 }
00231 
00232 ret  ::page::pluginmgr::configuration (type name) {
00233     variable config
00234 
00235     if {[file exists $name]} {
00236     # Try as plugin first. On failure read it as list of options,
00237     # separated by spaces and tabs, and possibly quoted with
00238     # quotes and double-quotes.
00239 
00240     if {[catch {$config load $name}]} {
00241         set ch      [open $name r]
00242         set options [::read $ch]
00243         close $ch
00244 
00245         set def {}
00246         while {[string length $options]} {
00247         if {[regsub "^\[ \t\n\]+" $options {} options]} {
00248             # Skip whitespace
00249             continue
00250         }
00251         if {[regexp -indices {^'(([^']|(''))*)'} \
00252             $options -> word]} {
00253             foreach {__ end} $word break
00254             lappend def [string map {'' '} [string range $options 1 $end]]
00255             set options [string range $options [incr end 2] end]
00256         } elseif {[regexp -indices {^"(([^"]|(""))*)"} \
00257             $options -> word]} {
00258             foreach {__ end} $word break
00259             lappend def [string map {{""} {"}} [string range $options 1 $end]]
00260             set options [string range $options [incr end 2] end]
00261         } elseif {[regexp -indices "^(\[^ \t\n\]+)" \
00262             $options -> word]} {
00263             foreach {__ end} $word break
00264             lappend def [string range $options 0 $end]
00265             set options [string range $options [incr end] end]
00266         }
00267         }
00268         return $def
00269     }
00270     } else {
00271     $config load $name
00272     }
00273     set def [$config do page_cdefinition]
00274     $config unload
00275     return $def
00276 }
00277 
00278 ret  ::page::pluginmgr::report (type level , type text , optional from ={) {to {}}} {
00279     variable replevel
00280     variable reportcmd
00281     uplevel /* 0 [linsert $reportcmd end $replevel($level) $text $from $to]*/
00282     return
00283 }
00284 
00285 /*  ### ### ### ######### ######### #########*/
00286 /*  Internals*/
00287 
00288 /*  Data structures*/
00289 /** 
00290  *# - reader    | Instances of pluginmgr configured for input,
00291  *# - transform | transformational, and output plugins. The
00292  *# - writer    | manager for transforms is actually a template
00293  *#             | from which the actual instances are cloned.
00294  */
00295 
00296 /*  - reportcmd | Callback for reporting of input error and warnings.*/
00297 /*  - replevel  | Mapping from chosen level to the right-padded text*/
00298 /*              | to use.*/
00299 
00300 namespace ::page::pluginmgr {
00301     variable  replevel
00302     array  replevel =  {
00303     info    {info   }
00304     warning {warning}
00305     error   {error  }
00306     }
00307 }
00308 
00309 ret  ::page::pluginmgr::Initialize () {
00310     InitializeReporting
00311     InitializeConfig
00312     InitializeReader
00313     InitializeTransform
00314     InitializeWriter
00315     return
00316 }
00317 
00318 ret  ::page::pluginmgr::InitializeReader () {
00319     variable commands
00320     variable reader_api
00321     variable reader [pluginmgr RD \
00322         -setup   ::page::pluginmgr::InitializeReaderIp \
00323         -pattern page::reader::* \
00324         -api     $reader_api \
00325         -cmdip   {} \
00326         -cmds    $commands]
00327 
00328     # The page_log_* commands are set later, when it is known if
00329     # logging is active or not, as their implementation depends on
00330     # this.
00331 
00332     pluginmgr::paths $reader page::reader
00333     return
00334 }
00335 
00336 ret  ::page::pluginmgr::InitializeReaderIp (type p , type ip) {
00337     interp eval $ip {
00338     package provide page::plugin         1.0
00339     package provide page::plugin::reader 1.0
00340     }
00341     interp alias $ip puts  {} puts
00342     interp alias $ip open  {} ::page::pluginmgr::AliasOpen $ip
00343     interp alias $ip write {} ::page::pluginmgr::WriteFile $ip
00344     return
00345 }
00346 
00347 ret  ::page::pluginmgr::InitializeWriter () {
00348     variable commands
00349     variable writer_api
00350     variable writer [pluginmgr WR \
00351         -setup   ::page::pluginmgr::InitializeWriterIp \
00352         -pattern page::writer::* \
00353         -api     $writer_api \
00354         -cmdip   {} \
00355         -cmds    $commands]
00356 
00357     # The page_log_* commands are set later, when it is known if
00358     # logging is active or not, as their implementation depends on
00359     # this.
00360 
00361     pluginmgr::paths $writer page::writer
00362     return
00363 }
00364 
00365 ret  ::page::pluginmgr::InitializeWriterIp (type p , type ip) {
00366     interp eval $ip {
00367     package provide page::plugin         1.0
00368     package provide page::plugin::writer 1.0
00369     }
00370     interp alias $ip puts  {} puts
00371     interp alias $ip open  {} ::page::pluginmgr::AliasOpen $ip
00372     interp alias $ip write {} ::page::pluginmgr::WriteFile $ip
00373     return
00374 }
00375 
00376 ret  ::page::pluginmgr::InitializeTransform () {
00377     variable transforms {}
00378     variable commands
00379     variable transform_api
00380     variable transform [pluginmgr TR \
00381         -setup   ::page::pluginmgr::InitializeTransformIp \
00382         -pattern page::transform::* \
00383         -api     $transform_api \
00384         -cmdip   {} \
00385         -cmds    $commands]
00386 
00387     # The page_log_* commands are set later, when it is known if
00388     # logging is active or not, as their implementation depends on
00389     # this.
00390 
00391     pluginmgr::paths $transform page::transform
00392     return
00393 }
00394 
00395 ret  ::page::pluginmgr::InitializeTransformIp (type p , type ip) {
00396     interp eval $ip {
00397     package provide page::plugin            1.0
00398     package provide page::plugin::transform 1.0
00399     }
00400     interp alias $ip puts  {} puts
00401     interp alias $ip open  {} ::page::pluginmgr::AliasOpen $ip
00402     interp alias $ip write {} ::page::pluginmgr::WriteFile $ip
00403     return
00404 }
00405 
00406 ret  ::page::pluginmgr::InitializeConfig () {
00407     variable config [pluginmgr CO \
00408         -pattern page::config::* \
00409         -api {page_cdefinition}]
00410 
00411     pluginmgr::paths $config page::config
00412     return
00413 }
00414 
00415 ret  ::page::pluginmgr::InitializeReporting () {
00416     variable reportcmd ::page::pluginmgr::ReportStderr
00417     return
00418 }
00419 
00420 ret  ::page::pluginmgr::ReportStderr (type level , type text , type from , type to) {
00421     # from = epsilon | list (line col)
00422     # to   = epsilon | list (line col)
00423     # line = 5 digits, col = 3 digits
00424 
00425     if {
00426     ($text eq "") &&
00427     ![llength $from] &&
00428     ![llength $to]
00429     } {
00430     puts stderr ""
00431     return
00432     }
00433 
00434     puts -nonewline stderr $level
00435     WriteLocation $from
00436     if {![llength $to]} {
00437     puts -nonewline stderr { }
00438     } {
00439     puts -nonewline stderr {-}
00440     }
00441     WriteLocation $to
00442     puts -nonewline stderr " "
00443     puts -nonewline stderr $text
00444     puts stderr ""
00445     return
00446 }
00447 
00448 ret  ::page::pluginmgr::WriteLocation (type loc) {
00449     if {![llength $loc]} {
00450     set text {         }
00451     } else {
00452     set line [lindex $loc 0]
00453     set col  [lindex $loc 1]
00454     set text {}
00455     if {![string length $line]} {
00456         append text _____
00457     } else {
00458         append text [string map {{ } _} [format %5d $line]]
00459     }
00460     append text @
00461     if {![string length $col]} {
00462         append text ___
00463     } else {
00464         append text [string map {{ } _} [format %3d $col]]
00465     }
00466     }
00467     puts -nonewline stderr $text
00468     return
00469 }
00470 
00471 ret  ::page::pluginmgr::AliasOpen (type slave , type file , optional acc ={) {perm {}}} {
00472 
00473     if {$acc eq ""} { acc =  r}
00474 
00475     ::safe::Log $slave =============================================
00476     ::safe::Log $slave "open $file $acc $perm"
00477 
00478     if {[regexp {[wa+]|(WRONLY)|(RDWR)|(APPEND)|(CREAT)|(TRUNC)} $acc]} {
00479     /*  Do not allow write acess.*/
00480     ::safe::Log $slave "permission denied"
00481     ::safe::Log $slave 0/============================================
00482     return -code error "permission denied"
00483     }
00484 
00485     if {[catch { file =  [::safe::TranslatePath $slave $file]} msg]} {
00486     ::safe::Log $slave $msg
00487     ::safe::Log $slave "permission denied"
00488     ::safe::Log $slave 1/============================================
00489     return -code error "permission denied"
00490     }
00491     
00492     /*  check that the path is in the access path of that slave*/
00493 
00494     if {[catch {::safe::FileInAccessPath $slave $file} msg]} {
00495     ::safe::Log $slave $msg
00496     ::safe::Log $slave "permission denied"
00497     ::safe::Log $slave 2/============================================
00498     return -code error "permission denied"
00499     }
00500 
00501     /*  do the checks on the filename :*/
00502 
00503     if {[catch {::safe::CheckFileName $slave $file} msg]} {
00504     ::safe::Log $slave "$file: $msg"
00505     ::safe::Log $slave "$msg"
00506     ::safe::Log $slave 3/============================================
00507     return -code error $msg
00508     }
00509 
00510     if {[catch {::interp invokehidden $slave open $file $acc} msg]} {
00511     ::safe::Log $slave "Caught: $msg"
00512     ::safe::Log $slave "script error"
00513     ::safe::Log $slave 4/============================================
00514     return -code error "script error"
00515     }
00516 
00517     ::safe::Log $slave =/============================================
00518     return $msg
00519 
00520 }
00521 
00522 ret  ::page::pluginmgr::Nop (type args) {}
00523 
00524 ret  ::page::pluginmgr::WriteFile (type slave , type file , type text) {
00525     if {[file pathtype $file] ne "relative"} {
00526     set file [file join [pwd] [file tail $fail]]
00527     }
00528     file mkdir [file dirname $file]
00529     fileutil::writeFile      $file $text
00530     return
00531 }
00532 
00533 /*  ### ### ### ######### ######### #########*/
00534 /*  Initialization*/
00535 
00536 namespace ::page::pluginmgr {
00537 
00538     /*  List of functions in the various plugin APIs*/
00539 
00540     variable reader_api {
00541     page_rhelp
00542     page_rlabel
00543     page_roptions
00544     page_rconfigure
00545     page_rrun
00546     page_rfeature
00547     }
00548     variable writer_api {
00549     page_whelp
00550     page_wlabel
00551     page_woptions
00552     page_wconfigure
00553     page_wrun
00554     page_wfeature
00555     }
00556     variable transform_api {
00557     page_thelp
00558     page_tlabel
00559     page_toptions
00560     page_tconfigure
00561     page_trun
00562     page_tfeature
00563     }
00564     variable commands {
00565     page_info    {::page::pluginmgr::report info}
00566     page_warning {::page::pluginmgr::report warning}
00567     page_error   {::page::pluginmgr::report error}
00568     }
00569 }
00570 
00571 ::page::pluginmgr::Initialize
00572 
00573 /*  ### ### ### ######### ######### #########*/
00574 /*  Ready*/
00575 
00576 package provide page::pluginmgr 0.2
00577 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1