checker.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  checker.tcl*/
00003 /* */
00004 /*  Code used inside of a checker interpreter to ensure correct usage of*/
00005 /*  doctools formatting commands.*/
00006 /* */
00007 /*  Copyright (c) 2003 Andreas Kupries <andreas_kupries@sourceforge.net>*/
00008 /*  Copyright (c) 2004 Andreas Kupries <andreas_kupries@sourceforge.net>*/
00009 
00010 /*  L10N*/
00011 
00012 package require msgcat
00013 
00014 ret  ::msgcat::mcunknown (type locale , type code) {
00015     return "unknown error code \"$code\" (for locale $locale)"
00016 }
00017 
00018 if {0} {
00019     puts stderr "Locale [::msgcat::mcpreferences]"
00020     foreach path [dt_search] {
00021     puts stderr "Catalogs: [::msgcat::mc
00022     }
00023 } else {
00024     foreach path [dt_search] {
00025     ::msgcat::mc
00026     }
00027 }
00028 
00029 /*  State, and checker commands.*/
00030 /*  -------------------------------------------------------------*/
00031 /* */
00032 /*  Note that the code below assumes that a command XXX provided by the*/
00033 /*  formatter engine is accessible under the name 'fmt_XXX'.*/
00034 /* */
00035 /*  -------------------------------------------------------------*/
00036 
00037 global state lstctx lstitem
00038 
00039 /*  --------------+-----------------------+----------------------*/
00040 /*  state       | allowed commands  | new state (if any)*/
00041 /*  --------------+-----------------------+----------------------*/
00042 /*  all except  | arg cmd opt comment   |*/
00043 /*   for "done" | syscmd method option  |*/
00044 /*      | widget fun type class |*/
00045 /*      | package var file uri  |*/
00046 /*      | strong emph namespace |*/
00047 /*  --------------+-----------------------+----------------------*/
00048 /*  manpage_begin   | manpage_begin     | header*/
00049 /*  --------------+-----------------------+----------------------*/
00050 /*  header  | moddesc titledesc | header*/
00051 /*      | copyright keywords    |*/
00052 /*      | require see_also  |*/
00053 /*      +-----------------------+-----------*/
00054 /*      | description       | body*/
00055 /*  --------------+-----------------------+----------------------*/
00056 /*  body        | section para list_end | body*/
00057 /*      | list_begin lst_item   |*/
00058 /*      | call bullet usage nl  |*/
00059 /*      | example see_also  |*/
00060 /*      | keywords sectref enum |*/
00061 /*      | arg_def cmd_def   |*/
00062 /*      | opt_def tkoption_def  |*/
00063 /*      | subsection        |*/
00064 /*      +-----------------------+-----------*/
00065 /*      | example_begin     | example*/
00066 /*      +-----------------------+-----------*/
00067 /*      | manpage_end       | done*/
00068 /*  --------------+-----------------------+----------------------*/
00069 /*  example | example_end       | body*/
00070 /*  --------------+-----------------------+----------------------*/
00071 /*  done        |           |*/
00072 /*  --------------+-----------------------+----------------------*/
00073 /* */
00074 /*  Additional checks*/
00075 /*  --------------------------------------+----------------------*/
00076 /*  list_begin/list_end         | Are allowed to nest.*/
00077 /*  --------------------------------------+----------------------*/
00078 /*  section             | Not allowed in list context*/
00079 /* */
00080 /*  arg_def             | Only in 'argument list'.*/
00081 /*  cmd_def             | Only in 'command list'.*/
00082 /*  nl para             | Only in list item context.*/
00083 /*  opt_def             | Only in 'option list'.*/
00084 /*  tkoption_def            | Only in 'tkoption list'.*/
00085 /*      def/call            | Only in 'definition list'.*/
00086 /*      enum                | Only in 'enum list'.*/
00087 /*      item/bullet         | Only in 'bullet list'.*/
00088 /*  --------------------------------------+----------------------*/
00089 
00090 /*  -------------------------------------------------------------*/
00091 /*  Helpers*/
00092 ret  Error (type code , optional text ={)} {
00093     global state lstctx lstitem
00094 
00095     # Problematic command with all arguments (we strip the "ck_" prefix!)
00096     # -*- future -*- count lines of input, maintain history buffer, use
00097     # -*- future -*- that to provide some context here.
00098 
00099     set cmd  [lindex [info level 1] 0]
00100     set args [lrange [info level 1] 1 end]
00101     if {$args != {}} {append cmd " [join $args]"}
00102 
00103     /*  Use a message catalog to map the error code into a legible message.*/
00104      msg =  [::msgcat::mc $code]
00105 
00106     if {$text != {}} {
00107      msg =  [string map [list @ $text] $msg]
00108     }
00109     dt_error "Manpage error ($code), \"$cmd\" : ${msg}."
00110     return
00111 }
00112 ret  Warn (type code , type args) {
00113     set msg [::msgcat::mc $code]
00114     foreach {off line col} [dt_where] break
00115     set msg [eval [linsert $args 0 format $msg]]
00116     set msg "In macro at line $line, column $col:\n$msg"
00117     set msg [split $msg \n]
00118     set prefix "DocTools Warning ($code): "
00119     dt_warning "$prefix[join $msg "\n$prefix"]"
00120     return
00121 }
00122 
00123 ret  Is    (type s) {global state ; return [string equal $state $s]}
00124 ret  IsNot (type s) {global state ; return [expr {![string equal $state $s]}]}
00125 ret  Go    (type s) {Log " >>\[$s\]" ; global state ; set state $s; return}
00126 ret  LPush (type l) {
00127     global lstctx lstitem
00128     set    lstctx [linsert $lstctx 0 $l $lstitem]
00129     return
00130 }
00131 ret  LPop () {
00132     global lstctx lstitem
00133     set    lstitem [lindex $lstctx 1]
00134     set    lstctx  [lrange $lstctx 2 end]
00135     return
00136 }
00137 ret  LSItem () {global lstitem ; set lstitem 1}
00138 ret  LIs  (type l) {global lstctx ; string equal $l [lindex $lstctx 0]}
00139 ret  LItem () {global lstitem ; return $lstitem}
00140 ret  LNest () {
00141     global lstctx
00142     expr {[llength $lstctx] / 2}
00143 }
00144 ret  LOpen () {
00145     global lstctx
00146     expr {$lstctx != {}}
00147 }
00148 global    lmap ldmap
00149 array  lmap =  {
00150     bullet   itemized    item     itemized
00151     arg      arguments   args     arguments
00152     opt      options     opts     options
00153     cmd      commands    cmds     commands
00154     enum     enumerated  tkoption tkoptions
00155 }
00156 array  ldmap =  {
00157     bullet   . arg . cmd . tkoption . opt .
00158 }
00159 ret  LMap (type what) {
00160     global lmap ldmap
00161     if {![info exists lmap($what)]} {
00162     return $what
00163     }
00164     if {[dt_deprecated] && [info exists ldmap($what)]} {
00165     Warn depr_ltype $what $lmap($what)
00166     }
00167     return $lmap($what)
00168 }
00169 ret  LValid (type what) {
00170     switch -exact -- $what {
00171     arguments   -
00172     commands    -
00173     definitions -
00174     enumerated  -
00175     itemized    -
00176     options     -
00177     tkoptions   {return 1}
00178     default     {return 0}
00179     }
00180 }
00181 
00182 ret  State () {global state ; return $state}
00183 ret  Enter (type cmd) {Log "\[[State]\] $cmd"}
00184 
00185 /* proc Log* {text} {puts -nonewline $text}*/
00186 /* proc Log  {text} {puts            $text}*/
00187 ret  Log* (type text) {}
00188 ret  Log  (type text) {}
00189 
00190 
00191 /*  -------------------------------------------------------------*/
00192 /*  Framing*/
00193 ret  ck_initialize () {
00194     global state   ; set state manpage_begin
00195     global lstctx  ; set lstctx [list]
00196     global lstitem ; set lstitem 0
00197     global sect    ; catch {unset sect} ; set sect() . ; unset sect()
00198     return
00199 }
00200 ret  ck_complete () {
00201     if {[Is done]} {
00202     if {![LOpen]} {
00203         return
00204     } else {
00205         Error end/open/list
00206     }
00207     } elseif {[Is example]} {
00208     Error end/open/example
00209     } else {
00210     Error end/open/mp
00211     }
00212     return
00213 }
00214 /*  -------------------------------------------------------------*/
00215 /*  Plain text*/
00216 ret  plain_text (type text) {
00217     # Only in body, not between list_begin and first item.
00218     # Ignore everything which is only whitespace ...
00219 
00220     set redux [string map [list " " "" "\t" "" "\n" ""] $text]
00221     if {$redux == {}} {return [fmt_plain_text $text]}
00222     if {[IsNot body] && [IsNot example]} {Error body}
00223     if {[LOpen] && ![LItem]} {Error nolisttxt}
00224     return [fmt_plain_text $text]
00225 }
00226 
00227 /*  -------------------------------------------------------------*/
00228 /*  Variable handling ...*/
00229 
00230 ret  vset (type var , type args) {
00231     switch -exact -- [llength $args] {
00232     0 {
00233         # Retrieve contents of variable VAR
00234         upvar #0 __$var data
00235         return $data
00236     }
00237     1 {
00238         # Set contents of variable VAR
00239         global __$var
00240         set    __$var [lindex $args 0]
00241         return "" ; # Empty string ! Nothing for output.
00242     }
00243     default {
00244         return -code error "wrong#args: set var ?value?"
00245     }
00246     }
00247 }
00248 
00249 /*  -------------------------------------------------------------*/
00250 /*  Formatting commands*/
00251 ret  manpage_begin (type title , type section , type version) {
00252     Enter manpage_begin
00253     if {[IsNot manpage_begin]} {Error mpbegin}
00254     Go header
00255     fmt_manpage_begin $title $section $version
00256 }
00257 ret  moddesc (type desc) {
00258     Enter moddesc
00259     if {[IsNot header]} {Error hdrcmd}
00260     fmt_moddesc $desc
00261 }
00262 ret  titledesc (type desc) {
00263     Enter titledesc
00264     if {[IsNot header]} {Error hdrcmd}
00265     fmt_titledesc $desc
00266 }
00267 ret  copyright (type text) {
00268     Enter copyright
00269     if {[IsNot header]} {Error hdrcmd}
00270     fmt_copyright $text
00271 }
00272 ret  manpage_end () {
00273     Enter manpage_end
00274     if {[IsNot body]} {Error bodycmd}
00275     Go done
00276     fmt_manpage_end
00277 }
00278 ret  require (type pkg , optional version ={)} {
00279     Enter require
00280     if {[IsNot header]} {Error reqcmd}
00281     fmt_require $pkg $version
00282 }
00283 ret  description () {
00284     Enter description
00285     if {[IsNot header]} {Error reqcmd}
00286     Go body
00287     fmt_description
00288 }
00289 
00290 global sect
00291 ret  __sid (type name) {
00292     # Identical to 'c_sectionId' in mpformats/_common.tcl
00293     regsub -all {[  ]+} [string tolower [string trim $name]] _ id
00294     regsub -all {"} $id _ id ; # "
00295     return $id
00296 }
00297 
00298 ret  section (type name) {
00299     global sect
00300 
00301     Enter section
00302     if {[IsNot body]} {Error bodycmd}
00303     if {[LOpen]}      {Error nolistcmd}
00304 
00305     set sid [__sid $name]
00306     if {[info exists sect($sid)]} {
00307     Warn sectambig $name
00308     }
00309     set sect($sid) .
00310 
00311     fmt_section $name
00312 }
00313 ret  subsection (type name) {
00314     global sect
00315 
00316     Enter subsection
00317     if {[IsNot body]} {Error bodycmd}
00318     if {[LOpen]}      {Error nolistcmd}
00319 
00320     set sid [__sid $name]
00321     if {[info exists sect($sid)]} {
00322     Warn sectambig $name
00323     }
00324     set sect($sid) .
00325 
00326     fmt_subsection $name
00327 }
00328 ret  para () {
00329     Enter para
00330     if {[IsNot body]} {Error bodycmd}
00331     if {[LOpen]}      {
00332     if {![LItem]} {Error nolisthdr}
00333     fmt_nl
00334     } else {
00335     fmt_para
00336     }
00337 }
00338 ret  list_begin (type what , optional hint ={)} {
00339     Enter "list_begin $what $hint"
00340     if {[IsNot body]}        {Error bodycmd}
00341     if {[LOpen] && ![LItem]} {Error nolisthdr}
00342      what =  [LMap $what]
00343     if {![LValid $what]}     {Error invalidlist $what}
00344     LPush        $what
00345     fmt_list_begin $what $hint
00346 }
00347 ret  list_end () {
00348     Enter list_end
00349     if {[IsNot body]} {Error bodycmd}
00350     if {![LOpen]}     {Error listcmd}
00351     LPop
00352     fmt_list_end
00353 }
00354 
00355 /*  Deprecated command, and its common misspellings. Canon is 'def'.*/
00356 ret  lst_item (optional text ={)} {
00357     if {[dt_deprecated]} {Warn depr_lstitem "\[lst_item\]"}
00358     def $text
00359 }
00360 ret  list_item (optional text ={)} {
00361     if {[dt_deprecated]} {Warn depr_lstitem "\[list_item\]"}
00362     def $text
00363 }
00364 ret  listitem  (optional text ={)} {
00365     if {[dt_deprecated]} {Warn depr_lstitem "\[listitem\]"}
00366     def $text
00367 }
00368 ret  lstitem   (optional text ={)} {
00369     if {[dt_deprecated]} {Warn depr_lstitem "\[lstitem\]"}
00370     def $text
00371 }
00372 ret  def (optional text ={)} {
00373     Enter def
00374     if {[IsNot body]}       {Error bodycmd}
00375     if {![LOpen]}           {Error listcmd}
00376     if {![LIs definitions]} {Error deflist}
00377     LSItem
00378     fmt_lst_item $text
00379 }
00380 ret  arg_def (type type , type name , optional mode ={)} {
00381     Enter arg_def
00382     if {[IsNot body]}       {Error bodycmd}
00383     if {![LOpen]}           {Error listcmd}
00384     if {![LIs arguments]}   {Error arg_list}
00385     LSItem
00386     fmt_arg_def $type $name $mode
00387 }
00388 ret  cmd_def (type command) {
00389     Enter cmd_def
00390     if {[IsNot body]}       {Error bodycmd}
00391     if {![LOpen]}           {Error listcmd}
00392     if {![LIs commands]}    {Error cmd_list}
00393     LSItem
00394     fmt_cmd_def $command
00395 }
00396 ret  opt_def (type name , optional arg ={)} {
00397     Enter opt_def
00398     if {[IsNot body]}       {Error bodycmd}
00399     if {![LOpen]}           {Error listcmd}
00400     if {![LIs options]}     {Error opt_list}
00401     LSItem
00402     fmt_opt_def $name $arg
00403 }
00404 ret  tkoption_def (type name , type dbname , type dbclass) {
00405     Enter tkoption_def
00406     if {[IsNot body]}       {Error bodycmd}
00407     if {![LOpen]}           {Error listcmd}
00408     if {![LIs tkoptions]}   {Error tkoption_list}
00409     LSItem
00410     fmt_tkoption_def $name $dbname $dbclass
00411 }
00412 ret  call (type cmd , type args) {
00413     Enter call
00414     if {[IsNot body]}       {Error bodycmd}
00415     if {![LOpen]}           {Error listcmd}
00416     if {![LIs definitions]} {Error deflist}
00417     LSItem
00418     eval [linsert $args 0 fmt_call $cmd]
00419 }
00420 /*  Deprecated. Use 'item'*/
00421 ret  bullet () {
00422     if {[dt_deprecated]} {Warn depr_bullet "\[bullet\]"}
00423     item
00424 }
00425 ret  item () {
00426     Enter item
00427     if {[IsNot body]}    {Error bodycmd}
00428     if {![LOpen]}        {Error listcmd}
00429     if {![LIs itemized]} {Error bulletlist}
00430     LSItem
00431     fmt_bullet
00432 }
00433 ret  enum () {
00434     Enter enum
00435     if {[IsNot body]}      {Error bodycmd}
00436     if {![LOpen]}          {Error listcmd}
00437     if {![LIs enumerated]} {Error enumlist}
00438     LSItem
00439     fmt_enum
00440 }
00441 ret  example (type code) {
00442     Enter example
00443     return [example_begin][plain_text ${code}][example_end]
00444 }
00445 ret  example_begin () {
00446     Enter example_begin
00447     if {[IsNot body]}        {Error bodycmd}
00448     if {[LOpen] && ![LItem]} {Error nolisthdr}
00449     Go example
00450     fmt_example_begin
00451 }
00452 ret  example_end () {
00453     Enter example_end
00454     if {[IsNot example]} {Error examplecmd}
00455     Go body
00456     fmt_example_end
00457 }
00458 ret  see_also (type args) {
00459     Enter see_also
00460     if {[Is done]} {Error nodonecmd}
00461     # if {[IsNot body]} {Error bodycmd}
00462     # if {[LOpen]}      {Error nolistcmd}
00463     eval [linsert $args 0 fmt_see_also]
00464 }
00465 ret  keywords (type args) {
00466     Enter keywords
00467     if {[Is done]} {Error nodonecmd}
00468     # if {[IsNot body]} {Error bodycmd}
00469     # if {[LOpen]}      {Error nolistcmd}
00470     eval [linsert $args 0 fmt_keywords]
00471 }
00472 /*  nl - Deprecated*/
00473 ret  nl () {
00474     if {[dt_deprecated]} {Warn depr_nl "\[nl\]"}
00475     para
00476 }
00477 ret  emph (type text) {
00478     if {[Is done]} {Error nodonecmd}
00479     fmt_emph $text
00480 }
00481 /*  strong - Deprecated*/
00482 ret  strong (type text) {
00483     if {[dt_deprecated]} {Warn depr_strong "\[strong\]"}
00484     emph $text
00485 }
00486 ret  arg (type text) {
00487     if {[Is done]} {Error nodonecmd}
00488     fmt_arg $text
00489 }
00490 ret  cmd (type text) {
00491     if {[Is done]} {Error nodonecmd}
00492     fmt_cmd $text
00493 }
00494 ret  opt (type text) {
00495     if {[Is done]} {Error nodonecmd}
00496     fmt_opt $text
00497 }
00498 ret  comment (type text) {
00499     if {[Is done]} {Error nodonecmd}
00500     return ; #fmt_comment $text
00501 }
00502 ret  sectref (type name , optional label ={)} {
00503     if {[IsNot body]}        {Error bodycmd}
00504     if {[LOpen] && ![LItem]} {Error nolisthdr}
00505     if {![string length $label]} { label =  $name}
00506     fmt_sectref $name $label
00507 }
00508 ret  syscmd (type text) {
00509     if {[Is done]} {Error nodonecmd}
00510     fmt_syscmd $text
00511 }
00512 ret  method (type text) {
00513     if {[Is done]} {Error nodonecmd}
00514     fmt_method $text
00515 }
00516 ret  option (type text) {
00517     if {[Is done]} {Error nodonecmd}
00518     fmt_option $text
00519 }
00520 ret  widget (type text) {
00521     if {[Is done]} {Error nodonecmd}
00522     widget $text
00523 }
00524 ret  fun (type text) {
00525     if {[Is done]} {Error nodonecmd}
00526     fmt_fun $text
00527 }
00528 ret  type (type text) {
00529     if {[Is done]} {Error nodonecmd}
00530     fmt_type $text
00531 }
00532 ret  package (type text) {
00533     if {[Is done]} {Error nodonecmd}
00534     fmt_package $text
00535 }
00536 ret  class (type text) {
00537     if {[Is done]} {Error nodonecmd}
00538     fmt_class $text
00539 }
00540 ret  var (type text) {
00541     if {[Is done]} {Error nodonecmd}
00542     fmt_var $text
00543 }
00544 ret  file (type text) {
00545     if {[Is done]} {Error nodonecmd}
00546     fmt_file $text
00547 }
00548 
00549 /*  Special case: We must not overwrite the builtin namespace command,*/
00550 /*  as it is required by the package "msgcat".*/
00551 ret  _namespace (type text) {
00552     if {[Is done]} {Error nodonecmd}
00553     fmt_namespace $text
00554 }
00555 ret  uri (type text , optional label ={)} {
00556     if {[Is done]} {Error nodonecmd}
00557     /*  The label argument is left out when undefined so that we can*/
00558     /*  control old formatters as well, if the input is not using uri*/
00559     /*  labels.*/
00560 
00561     if {$label == {}} {
00562     fmt_uri $text
00563     } else {
00564     fmt_uri $text $label
00565     }
00566 }
00567 ret  usage (type args) {
00568     if {[Is done]} {Error nodonecmd}
00569     eval fmt_usage $args
00570 }
00571 ret  const (type text) {
00572     if {[Is done]} {Error nodonecmd}
00573     fmt_const $text
00574 }
00575 ret  term (type text) {
00576     if {[Is done]} {Error nodonecmd}
00577     fmt_term $text
00578 }
00579 
00580 /*  -------------------------------------------------------------*/
00581 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1