TCL Package Issue

Clovertech Forums Read Only Archives Cloverleaf Cloverleaf TCL Package Issue

  • Creator
    Topic
  • #55417
    Tom Righele
    Participant

      Hello all-

      We are migrating from Windows to Linux and I am having trouble with a custom package I installed called “xmlgen”. I put this in the cloverleafcis6.1integratortcllibX12lib folder and my pkgIndex.tcl looks like this:

      Code:


      package ifneeded X12ftp 1.0 [list tclPkgSetup $dir X12ftp 1.0 {{X12ftp.tcl source {::X12ftp::Append ::X12ftp::Cd ::X12ftp::Close ::X12ftp::Delete ::X12ftp::DisplayMsg ::X12ftp::FileSize ::X12ftp::Get ::X12ftp::List ::X12ftp::MkDir ::X12ftp::ModTime ::X12ftp::NList ::X12ftp::Newer ::X12ftp::Open ::X12ftp::Put ::X12ftp::Pwd ::X12ftp::Quote ::X12ftp::Reget ::X12ftp::Rename ::X12ftp::RmDir ::X12ftp::Type}}}]
      package ifneeded X12lib 1.0 [list tclPkgSetup $dir X12lib 1.0 {{X12lib.tcl source {::X12lib::buildGS ::X12lib::buildISA ::X12lib::getGroups ::X12lib::getTrans ::X12lib::joinX12 ::X12lib::splitX12}}}]
      package ifneeded X12pop3 1.0 [list tclPkgSetup $dir X12pop3 1.0 {{X12pop3.tcl source {}}}]
      package ifneeded X12Batch 1.0 [list source [file join $dir X12Batch.tcl]]
      package ifneeded xmlgen 1.0 [list source [file join $dir xmlgen.tcl]]

      However, in linux, when I tried to add this, I get an error message when testing. I tried using the hcitcl command to see if the package is being seen properly, but I now get this error message:

      hcitcl>package require xmlgen

      Error: /cloverleaf/cis6.1/integrator/[host]/tclprocs/tclIndex isn’t a proper Tcl index file

      When I do this for any other package, it picks up the version.

      Any idea? Do I need to update the tclIndex file somehow in order to have Cloverleaf pick up the xmlgen package?

      Thanks for your help!!

    Viewing 6 reply threads
    • Author
      Replies
      • #85250
        David Barr
        Participant

          You shouldn’t need to update the tclIndex to get a new package; pkgIndex.tcl should be enough. However, it looks like there may be another problem with your tclIndex. You should probably update it (cd /cloverleaf/cis6.1/integrator/[host]/tclprocs; mktclindex).

        • #85251
          Jeff Dinsmore
          Participant

            I don’t think that error is directly related to your xmlgen package.

            I believe it’s finding a file called tclIndex in the /cloverleaf/cis6.1/integrator/[host]/tclprocs/tclIndex directory – and it’s not a valid Tcl index file.

            I bet Tcl is hitting that file while cycling through its auto_path looking for the xmlgen package, but not when loading other packages.

            Jeff Dinsmore
            Chesapeake Regional Healthcare

          • #85252
            Tom Righele
            Participant

              Thank you all!! That seemed to do something, but this seems to have caused another problem I was not seeing before. It seems more like an issue with xmlgen.tcl. I am getting this error now:

              Error: invalid command name “setTagformat”

              This is a command from the xmlgen. The code is below. Is there something Linux does not read correctly in this TCL?

              Code:

              ########################################################################
              #
              #  xmlgen — generate XML by writing Tcl code
              #
              # (C) 2002 Harald Kirsch
              #
              # $Revision: 1.9 $, $Date: 2002/09/21 14:55:55 $
              ########################################################################
              package provide xmlgen [lindex {Revision: 1.0 } 1]

              namespace eval ::xmlgen {

               namespace export buffer channel declaretag esc put doTag
                   setTagformat
               
               ## will be elongated and trimmed back by (recursive) calls to doTag,
               ## i.e. by tag-procs. However, it is only used by makeTagAndBody.
               variable indent “”

               ## a regular expression used by makeTagAndBody to identify
               ## tag-arguments which are attribute-value pairs as well as to
               ## dissect them into these two parts. The attribute name must match
               ## the definition of ‘Name’ found in the XML spec:
               ##    http://www.w3c.org/TR/2000/REC-xml-20001006#NT-Name
               ## ‘CombiningChar’ and ‘Extender’ are not yet considered.
               variable attrre {^ *([A-Za-z_:][a-zA-Z0-9_.:-]*)=(.*)}

               ## A pattern used with [string match] to check if the first body
               ## argument of a markup proc is a control character which describes
               ## how to handle the body.
               set controlchars {[-!+.]}

               ## The following array specifies how to format the output. For every
               ## control character listed above it tells us what to put in front
               ## of the open and close tags — typically a newline and some
               ## indentation. Note that the respective strings are ran through
               ## [subst] in order to expand references to $indent. Consequently
               ## you must be careful to put other Tcl special characters into the
               ## string.
               array set tagformat {
                 -o {n$indent$tag} -c {$tag}
                 +o {n$indent$tag} +c {n$indent$tag}
                 !o {n$indent$tag} !c {n$indent$tag}
                 .o {$tag}          .c {$tag}
               }

               ## Output normally goes just to stdout, but proc buffer may be used
               ## to generate a context in which output is appended to this
               ## variable.
               ## NOTE: this is not thread-save if two threads operate in the same
               ## interpreter.
               variable buffer “”

               ## We want to replace the original puts by our own implementations
               ## depending on context. However, we need of course the original
               ## somewhere, so we keep it as tclputs. Then, initially, we make the
               ## “normal” ::puts an alias for the saved proc.

               ## EAS: This is very confusing and didn’t work on my system
               ## Left the original TCL puts alone and called our proc “putx” instead
               # rename ::puts ::xmlgen::tclputs
               # HK: no put, use just [put] for redirectable and channelable output.
               #interp alias {} ::putx   {}  ::xmlgen::putx

               ## The main output-generating function is [put]. In contrast to puts
               ## it takes several arguments which are simply [join]ed and no
               ## newline is automatically appended. When called in the context of
               ## [buffer] or [channel], the output is redirected either to a
               ## variable or another output channel than stdout respectively. The
               ## default is output to stdout.
               interp alias {} ::xmlgen::put   {} ::xmlgen::putStream stdout
              }

              proc ::xmlgen::putx-no-longer-needed-use-just-put {args} {
                 set i 0
                 if { “-nonewline” == [lindex $args $i] } {
                     set nl “”
                     incr i
                 } else {
                     set nl n
                 }

                 ## If there are still two args, the first is supposed to be an
                 ## explicit output channel and we leave it to the original puts to
                 ## handle that.
                 if { [llength $args]-$i != 1 } {
                     eval puts $args
                     return
                 }
                 variable buffer
                 append buffer [lindex $args $i] $nl

                 return
              }
               
              ## A version of [put] used when collecting output in a buffer.
              proc ::xmlgen::putBuf {args} {
               variable buffer
               
               append buffer [join $args]
               return
              }

              ## A version of [put] used when printing to a channel.
              proc ::xmlgen::putStream {channel args} {
               puts -nonewline $channel [join $args]
               return
              }

              ## Arranges for further output to be appended to variable bufname
              ## instead of being sent automatically to stdout
              proc ::xmlgen::buffer {bufname body} {
               ## save the current buffer locally
               variable buffer
               set keptBuffer $buffer
               set buffer {}

               ## stack the current redirection
               set keptPut [interp alias {} ::xmlgen::put]

               ## redirect [put]
               ## FIXME: Is it really necessary to work with the namespace-variable
               ## buffer to collect the output or could we do something like
               ##    interp …. {} xmlgen::putBuf $bufname
               ## Probably not, because then $bufname could not refer to a local
               ## variable of the calling function.
               interp alias {} ::xmlgen::put  {} ::xmlgen::putBuf

               ## run the body safely
               set err [catch {uplevel 1 $body}]
               
               ## Restore [put]
               eval interp alias {{}} ::xmlgen::put  {{}} $keptPut

               ## copy the collected buffer to the requested var and restore the
               ## previous buffer
               upvar $bufname b
               set b $buffer
               set buffer $keptBuffer
               if {$err} {
                 return -code error -errorinfo $::errorInfo
               }
               
               return
              }

              proc ::xmlgen::channel {chan body} {
               ## stack the current redirection
               set keptPut [interp alias {} ::xmlgen::put]

               ## redirect [put]
               interp alias {} ::xmlgen::put  {} ::xmlgen::putStream $chan

               ## run the body safely
               set err [catch {uplevel 1 $body}]
               
               ## Restore [put]
               eval interp alias {{}} ::xmlgen::put  {{}} $keptPut

               if {$err} {
                 return -code error -errorinfo $::errorInfo
               }
               
               return
              }

              ## See manual page for description of this function.
              proc ::xmlgen::makeTagAndBody {tagname l {specialAttributes {}} } {
               variable attrre
               variable indent
               variable controlchars

               ## If specialAttributes is set, we put those attributes into the
               ## array instead of assembling them into the tag.
               if {”$specialAttributes”==””} {
                 array set sAttr {}
               } else {
                 upvar $specialAttributes sAttr
               }
               
               ## Collect arguments as long as they look like attribute-value
               ## pairs, i.e. as long as they match $attrre.
               ## As a convenience, an argument which is the empty string is simply
               ## ignored. This allows optional, auto-generated attributes to be
               ## empty and skipped like in
               ##    if {…} {set align “”} else {set align “align=center”}
               ##    p $align – {Some text, sometimes centered}
               ## If $align==””, it will not stop attribute processing.
               ##
               set opentag “<$tagname"
               set L [llength $l]
               for {set i 0} {$i attr value]} break
                 if {[info exists sAttr($attr)] || “”==”$tagname”} {
                   set sAttr($attr) $value
                 } else {
                   append opentag ” $attr=”[esc $value]””
                 }
               }
               
               ## If there is at least one element left in $l, the first element of
               ## $l is already stored in arg. It could be the argument controlling
               ## how to handle the body.
               set haveControl 0; # see safety belt below
               set control .
               if {$i<$L} {
                 if {[string match $controlchars $arg]} {
                   set control $arg
                   incr i
                   set haveControl 1
                 } elseif {[string length $arg]==1} {
                   append emsg
               " starting the body with a single character is not allowed "
               "in order to guard against bugs"
                   return -code error $emsg
                 }
               }
               
               ## If there are elements left in $l they are joined into the
               ## body. Otherwise the body is empty and opentag and closetag need
               ## special handling.
               if {$i”
                 set closetag “”

                 ## Do some indenting.
                 set opentag [formatTag ${control}o $indent $opentag]
                 set closetag [formatTag ${control}c $indent $closetag]
                     
               } else {
                 ## Leave a space in front of “/>” for being able to use XHTML
                 ## with most HTML-browsers
                 set body {}
                 append opentag ” />”
                 set closetag “”
               }
               
               ## Put on the safety belt. If we did not have a control character
               ## and the body starts with a blank line, the author most probably
               ## just forgot the control character.
               if {!$haveControl && [regexp “^[t ]*n” $body]} {
                 append msg
              “body starts with newline but no control ”
              “character was given:”
                 set b [split $body n]
                 if {[llength $b]>3} {
                   append msg [join [lrange $b 0 3] n] ”  …”
                 } else {
                   append msg $body
                 }
                 return -code error $msg
               }
               
               return [list $opentag $control $body $closetag]
              }
              ########################################################################
              ## With the help of variable tagformat we put some indentation in
              ## front of a tag to make the output look nicer.
              proc ::xmlgen::formatTag {which indent tag} {
               variable tagformat
               return [subst $tagformat($which)]
              }
              ########################################################################
              ##
              ## Sets an element of variable tagformat in a controlled way, i.e. we
              ## test if the array index ‘which’ makes sense.
              ##
              proc ::xmlgen::setTagformat {which format} {
               variable tagformat
               variable controlchars
               if {![regexp “$controlchars[oc]” $which]} {
                 return -code error
              “the string `$which’ is not a valid target to format”
               }
               set tagformat($which) $format
              }
              ########################################################################
              ## Evaluate, substitute and print or just return the body
              ## enclosed in the given opentag and closetag.
              proc ::xmlgen::runbody {opentag control body closetag} {

               switch -exact — $control {
                 “!” {
                   variable indent
                   set ind $indent
                   append indent { }
                   uplevel 1 [list ::xmlgen::put $opentag]
                   uplevel 1 $body
                   uplevel 1 [list ::xmlgen::put $closetag]
                   set indent $ind
                 }
                 “+” {
                   set body [string trim $body “n t”]
                   uplevel 1 [list ::xmlgen::put $opentag]
                   uplevel 1 “::xmlgen::put [subst {$body}]”
                   uplevel 1 [list ::xmlgen::put $closetag]
                 }
                 “-” {
                   set body [string trim $body “n t”]
                   uplevel 1 [list ::xmlgen::put $opentag]
                   uplevel 1 [list ::xmlgen::put $body]
                   uplevel 1 [list ::xmlgen::put $closetag]
                 }
                 “.” {
                   return “$opentag$body$closetag”
                 }
                 default {
                   return -code error “unknown control string `$control'”
                 }
               }
               
               return
              }
              ########################################################################
               

              ## Generic function to handle a tag-proc and its arguments.
              proc ::xmlgen::doTag {tagname args} {
               variable tagAndBodyProc
               
               foreach {opentag control body closetag}
                   [makeTagAndBody $tagname $args] break
               
               set result [uplevel 1 [list ::xmlgen::runbody $opentag
                  $control $body $closetag]]

               return $result
              }

              ## Makes a tagname into a tag-proc by making it into an alias for
              ## doTag.
              proc ::xmlgen::declaretag {funcname {tagname {}}} {
               if {”$tagname”==””} {
                 set tagname $funcname
               }
               set ns [string trimright [uplevel 1 “namespace current”] :]
               interp alias {} [set ns]::$funcname   {} ::xmlgen::doTag $tagname
               
               return
              }

              ## Convert text so that it is safe to use it as an attribute value
              ## surrouned by double quotes as well as character data. See the
              ## definition of AttValue and CharData:
              ## http://www.w3c.org/TR/2000/REC-xml-20001006#NT-AttValue
              ## http://www.w3c.org/TR/2000/REC-xml-20001006#NT-CharData
              proc ::xmlgen::esc {args} {
               regsub -all “&” [eval concat $args] “\&” args
               regsub -all “” $args “\>” args
               regsub -all “”” $args “\"” args
               regsub -all “]” $args “\]” args
               
               return $args
              }

              ########################################################################

              Any help is much appreciated!

            • #85253
              Jeff Dinsmore
              Participant

                Import all exported ::xmlgen commands into the executing namespace:

                   namespace import ::xmlgen::*

                Then you can call the exported commands in the current namespace without the full command path:

                   setTagformat x y

                Or, you can call them directly with a full path to the command – even without the export in the xmlgen namespace.

                   ::xmlgen::setTagformat x y

                Jeff Dinsmore
                Chesapeake Regional Healthcare

              • #85254
                Tom Righele
                Participant

                  Thank you, but I am still having issues

                • #85255
                  Jeff Dinsmore
                  Participant

                    No. The line continuation should be fine.

                    I copied your code directly into a hcitcl shell and it interpreted it just fine – including the export of setTagformats.

                    So, I got to thinking that perhaps you have line terminations rather than the Unix/Linux standard .

                    I tested this theory by copying your code to a file and forcing line termination to .

                    I then sourced the file (source /tmp/xmlgen.tcl) into an hcitcl shell and it gave me this error:

                    Code:

                    hcitcl>source /tmp/xmlgen.tcl
                    Error: invalid command name “setTagformat”


                    Than means it’s interpreting that “setTagformat” as a standalone command rather than as a continuation of the previous line.

                    I then changed it to , sourced it again and it produced no error.

                    So, assuming you’re using some sort of FTP to copy the file to Linux from Windows, be sure you select “text” or something similar rather than “binary”.  This will translate from to during transmission.

                    I expect that’ll fix your error.

                    Jeff Dinsmore
                    Chesapeake Regional Healthcare

                  • #85256
                    Tom Righele
                    Participant

                      THANK YOU!!!! This fixed the issue, I sincerely appreciate your help Jeff! And this is good to know as we migrate other items from Linux.

                      -Tom

                  Viewing 6 reply threads
                  • The forum ‘Cloverleaf’ is closed to new topics and replies.