[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SEUL: sdoc handlerstacks



Sorry for the technical nature of this. I want to get it out of my
system so I can go back to working on the survey. My head is too full
right now.

Omega, you wanted handler stacks for sdoc. That means that for each
tag, there is an array of handlers defined. The handler "on the top
of the stack" will be used to deal with a given tag, and all other
handlers for that tag will be hidden. When that "top" handler decides
it's done, it removes itself, and then the one underneath becomes the
top one.

Currently there exists a $HandlerDefault, which is a generic handler
function that tries to do the right thing. We will want to reconsider
how we want tags with no "live" handlers to act, but that isn't my
problem yet. Tell me how you want it to work, Omega.

Following are proposed redefinitions of the abstraction functions for
dealing with handlers. The modifications are trivial for the most part.
It will *ALWAYS* be the case that if $HandlerCode{$tagname} is defined,
it has at least one handler registered. So if you're not going to use
my abstractions, please respect that restriction or you will suffer a
thousand deaths from confusion.

I'll let you integrate them into sdoc if you like them, Omega. Currently
each element of the handler stack consists of the entire script of what
will be done, and this script is recompiled each time. As you said, this
sucks. But you're going to change over to packages (foo::Handlers::bar)
soon, so I'll let you deal with that one as well.

I've decided that $HandlerSingle{} will not become a stack. I can
change this if you really want the functionality, but it makes the
error-checking a bit more complex.

Caveats:
* I haven't run any of this. But it should work. ;)
* This isn't terribly fast. But you knew that.

And finally: omega, can you separate the seul-pub and seul-pub-www
archives on the majordomo archive server? Your mh dotfiles are
messing up.

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

sub Register_Handler { # returns 0 on failure, nonzero on success
  my ($tagname, $filename, $single) = @_;
  my ($file, $retval);
  my ($tmphandler);

  if ($filename =~ /^\//) {
    # we have an absolute path
    Debug(8,"loading absolute $filename");
    $file = "$filename";
  } else {
    if (-f "$env_lib/$filename") {
      Debug(8,"loading relative $env_lib/$filename");
      $file = "$env_lib/$filename";
      $retval = 2; # means got lib
    } elsif (-f "$default_lib/$filename") {
      Debug(8,"loading relative $default_lib/$filename");
      $file = "$default_lib/$filename";
      $retval = 1; # means got default
    } else {
      Warn("file $filename could not be found");
      return(0); # argh!!
    }
  }

  $tmphandler = ReadFile($file);
  return(0)
    if (not defined $tmphandler);

  push @{ $HandlerCode{$tagname} }, $tmphandler;
  $HandlerSingle{$tagname} = $single;

  Debug(7,"handler $filename for tag $tagname loaded, .
    scalar @{ $HandlerCode{$tagname} } . " now present");

  return($retval); # success
}

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

sub Unregister_Handler { # returns 0 on failure, nonzero on success
  my ($tagname) = @_;

  # already empty?
  return(0)
    if(not exists $HandlerCode{$tagname});
#    if(not exists $HandlerCode{$tagname} or $#{ $HandlerCode{$tagname} } < 0);

  # This will work fine even if it's empty
  pop(@{ $HandlerCode{$tagname} }); 

  Debug(7,"Handler removed for tag $tagname, " .
     scalar @{ $HandlerCode{$tagname} } . " remain");

  if($#{ $HandlerCode{$tagname} } < 0) {
    delete $HandlerCode{$tagname};
  }

  return(1); # success

}

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

sub handler {
  local ($tagname, $params, $text, $tagpaired) = @_;
  local $prelude = '';
  local $postlude = '';
  my($errval) = 1;

#  foreach $var (keys %params) {
#    &Debug("Handler: Param '$var' is val '$params{$var}'.");
#  }

  if (exists $HandlerCode{$tagname}) {
    $errval = eval "$HandlerCode{$tagname}[scalar @{ $HandlerCode{$tagname} }]";
    &Debug(7,"HANDLER '$tagname' finished, returning '$text', error $errval");
  } else {
    if(defined $HandlerDefault) {
      $errval = eval "$HandlerDefault";
      &Debug(7,"Default HANDLER '$tagname' finished, returning '$text', error $errval");
    } else {
      # No default handler function. Just do something useful.

      if ($HandlerSingle{$tagname} == $tagpaired) {
         Warn("tag $tagname is unpaired, but is supposed to be paired");
      }

      $prelude = "<$tagname";
      if ($params) {
          $prelude .= " $params";
      }
      $prelude .= ">";
      if($tagpaired) {
        $postlude = "</$tagname>";
        $errval = 2;
      } else {
        $text = $prelude;
        $errval = 0;
      }

      &Debug(7,"Inlined default HANDLER '$tagname' finished.");

    }
  }
  Warn "Handler for tag '$tagname' failed: $@" if $@;

#  $text = do "doc-types/$headerparams{'doc-type'}/$tagname";

  return($prelude, $text, $postlude, $errval);

}

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

# And a mostly meaningless patch inside Parse():

           } # end while
           $text = $preinsidetext.$text; # back up,
           # fall through. No endtag.

-          if (defined $HandlerCode{$tag}) {
+          if (exists $HandlerCode{$tag}) {
                  # it's defined to be paired, no endtag. Oops.
                  die "No matched tag '$tag' for defined tag.";
           } else { # use default. It's ok if there's no inside.