Diff for /loncom/homework/Attic/lonproblem.pm between versions 1.2 and 1.3

version 1.2, 2000/02/22 21:32:17 version 1.3, 2000/04/12 20:06:16
Line 13  use Apache::File; Line 13  use Apache::File;
 # ================================================================ Main Handler  # ================================================================ Main Handler
   
 sub handler {  sub handler {
 my $r=shift;    my $r=shift;
 my @parsecontents;    my @parsecontents;
 my $parsestring;    my $parsestring;
 my $outstring;    my $outstring;
     
 {    {
   my $fh=Apache::File->new($r->filename);      my $fh=Apache::File->new($r->filename);
   @parsecontents=<$fh>;      @parsecontents=<$fh>;
 }    }
     
 $parsestring=join('',@parsecontents);    $parsestring=join('',@parsecontents);
     
 print "<form>";    print "<form>";
     
 &xmlparse($r,$parsestring,'web');    &xmlparse($r,$parsestring,'web');
     
 print "\n---------------\n";    print "\n---------------\n";
 print "<form>";    print "<form>";
 &xmlparse($r,$parsestring,'edit');    &xmlparse($r,$parsestring,'edit');
 $outstring=xmlparse($parsestring,'modified');    $outstring=xmlparse($parsestring,'modified');
 print "\n---------------\n$outstring\n";    print "\n---------------\n$outstring\n";
 return 1; #change to ok    return 1; #change to ok
 }  }
   
 # =============================================================================  # =============================================================================
Line 43  return 1; #change to ok Line 43  return 1; #change to ok
 # =============================================================================  # =============================================================================
   
 sub xmlparse {  sub xmlparse {
     
 my ($r,$parsestring,$target) = @_;    my ($r,$parsestring,$target) = @_;
     
 my $safeeval   = new Safe 'Script';    my $safeeval   = new Safe 'Script';
     
 my $parsereval = new Safe 'Parser';    my $parsereval = new Safe 'Parser';
     
 my $parser=HTML::TokeParser->new(\$parsestring);    my $parser=HTML::TokeParser->new(\$parsestring);
     
 my $outtext='';    my $outtext='';
     
 # ---------------------------------------------------------------- Handled tags  # ---------------------------------------------------------------- Handled tags
   
 my %toptoplevel  = ( 'problem'    => 'Problem',    my %toptoplevel  = ( 'problem'    => 'Problem',
                      'entryform'  => 'Entry Form',         'entryform'  => 'Entry Form',
                      'survey'     => 'Survey',         'survey'     => 'Survey',
                      'graded'     => 'Manually Graded' );         'graded'     => 'Manually Graded' );
     
     
 # --------------------------------------------------------------- Toplevel Tags  # --------------------------------------------------------------- Toplevel Tags
   
 my %topleveltags = ( 'block'   => 'Condition Block',    my %topleveltags = ( 'block'   => 'Condition Block',
                      'part'    => 'Problem Part';         'part'    => 'Problem Part',
                      'include' => 'Include Section',         'include' => 'Include Section',
                      'answer'  => 'Answerfield';         'answer'  => 'Answerfield',
                      'script'  => 'Script',          'script'  => 'Script', 
                      'outtext' => 'Text Block' );         'outtext' => 'Text Block' );
     
 # ---------------------------------------------------------- Preregistered Tags  # ---------------------------------------------------------- Preregistered Tags
   
 my %includetags  = ( 'scriptlib' => 'Script Library',    my %includetags  = ( 'scriptlib' => 'Script Library',
                      'parserlib' => 'Parser Library' );         'parserlib' => 'Parser Library' );
   # -------------------------------------------------------------Answer type Tags
   
 # -------------------------------------------------------------------- All Tags    my %answertags   = ( 'capaanswer' => 'CAPA Standard Answers');
   
 my %xmltags      = ( %includetags, %topleveltags, %toptoplevel );  # -------------------------------------------------------------------- All Tags
   
 my $toplevel     = '';  
 my $above        = '';  
   
     my %xmltags      = ( %includetags, %topleveltags, %toptoplevel, %answertags );
     
     my $toplevel     = '';
     my $above        = '';
     
 # --------------------------------------------------- Depth counter for editing  # --------------------------------------------------- Depth counter for editing
   
 my @depthcounter=();    my @depthcounter=();
 my $depth=-1;    my $depth=-1;
 my $olddepth=-1;    my $olddepth=-1;
   
 # ----------------------------------------------------------------------- Stack  # ----------------------------------------------------------------------- Stack
   
 my @stack=('');    my @stack=('');
   
 # -------------------------------------------------------------- Init $saveeval  # -------------------------------------------------------------- Init $saveeval
   
 &init_safeeval($safeeval);    &init_safeeval($safeeval);
   
 # ---------------------------------------------------------- Parse $parsestring  # ---------------------------------------------------------- Parse $parsestring
   
 my $token;    my $token;
   
 while ($token=$parser->get_token) {    while ($token=$parser->get_token) {n
 # =============================================================================  # =============================================================================
    if ($token->[0] eq 'S') {      if ($token->[0] eq 'S') {
 # =================================================================== Start Tag  # =================================================================== Start Tag
 # --------------------------------------------------------------- Depth Counter  # --------------------------------------------------------------- Depth Counter
       if (defined($xmltags{$token->[1]})) {        if (defined($xmltags{$token->[1]})) {
          if ($depth<$olddepth-1) {   if ($depth<$olddepth-1) {
             $#depthcounter--;    $#depthcounter--;
             $olddepth=$depth;    $olddepth=$depth;
          }   }
          $depth++;   $depth++;
          $depthcounter[$depth]++;   $depthcounter[$depth]++;
          if ($depthcounter[$depth]==1) {   if ($depthcounter[$depth]==1) {
             $olddepth=$depth;    $olddepth=$depth;
          }   }
       }          }  
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
   
   
       if ($target eq 'web') {        if ($target eq 'web') {
          my $sub="start_$token->[1]";   my $sub="start_$token->[1]";
          {   {
            no strict 'refs';    no strict 'refs';
            if (defined (&$sub)) {     if (defined (&$sub)) { 
               &$sub($r,$token,$parser,$safeeval,\@stack);       &$sub($r,$token,$parser,$safeeval,\@stack); 
            } else {    } else {
               $stack[$#stack].=$token->[4];      $stack[$#stack].=$token->[4];
            }    }
          }   }
       }        }
         
       if ($target eq 'edit') {        if ($target eq 'edit') {
          my $depthlabel=join('_',@depthcounter);   my $depthlabel=join('_',@depthcounter);
          if (defined($xmltags{$token->[1]})) {   if (defined($xmltags{$token->[1]})) {
             if (defined($topleveltags{$token->[1]})) {    if (defined($topleveltags{$token->[1]})) {
                &insertmenu($r,$xmltags{$token->[1]},      &insertmenu($r,$xmltags{$token->[1]},
                            $depthlabel,\%topleveltags);   $depthlabel,\%topleveltags);
               $toplevel=$token->[1];      $toplevel=$token->[1];
             } else {    } else {
                 if ($toplevel eq 'answer') {      if ($toplevel eq 'answer') {
                    &insertmenu($r,$xmltags{$token->[1]},        &insertmenu($r,$xmltags{$token->[1]},
                                $depthlabel,\%answertags);    $depthlabel,\%answertags);
                 }      }
             }    }
             my $sub="start_edit_$token->[1]";    my $sub="start_edit_$token->[1]";
             {    {
               no strict 'refs';      no strict 'refs';
               if (defined (&$sub)) {       if (defined (&$sub)) { 
                  &$sub($r,$token,$parser,$xmltags{$token->[1]},        &$sub($r,$token,$parser,$xmltags{$token->[1]},
                        $depthlabel,$above,\%answertypes,\@stack);       $depthlabel,$above,\%answertypes,\@stack); 
               }      }
             }     } 
          } else {   } else {
             $stack[$#stack].=$token->[4];    $stack[$#stack].=$token->[4];
          }   }
       }        }
         
       if ($target eq 'modified') {        if ($target eq 'modified') {
       }        }
   
 # =============================================================================  # =============================================================================
    } elsif ($token->[0] eq 'E') {      } elsif ($token->[0] eq 'E') {
 # ===================================================================== End Tag  # ===================================================================== End Tag
   
       if ($target eq 'web') {        if ($target eq 'web') {
          my $sub="end_$token->[1]";   my $sub="end_$token->[1]";
          {   {
            no strict 'refs';    no strict 'refs';
            if (defined (&$sub)) {     if (defined (&$sub)) { 
               &$sub($r,$token,$parser,$safeeval,\@stack);      &$sub($r,$token,$parser,$safeeval,\@stack);
            } else {    } else {
               $stack[$#stack].=$token->[2];      $stack[$#stack].=$token->[2];
            }    }
          }   }
       }        }
         
       if ($target eq 'edit') {        if ($target eq 'edit') {
          if (defined($xmltags{$token->[1]})) {   if (defined($xmltags{$token->[1]})) {
             my $sub="end_edit_$token->[1]";    my $sub="end_edit_$token->[1]";
             {    {
               no strict 'refs';      no strict 'refs';
               if (defined (&$sub)) {       if (defined (&$sub)) { 
                  &$sub($r,$token,$above,\@stack);         &$sub($r,$token,$above,\@stack); 
               }      }
             }     } 
          }    } 
       }        }
         
       if ($target eq 'modified') {        if ($target eq 'modified') {
       }        }
 # --------------------------------------------------------------- Depth Counter  # --------------------------------------------------------------- Depth Counter
       if (defined($xmltags{$token->[1]})) { $depth--; }        if (defined($xmltags{$token->[1]})) { $depth--; }
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
 # =============================================================================  # =============================================================================
    } elsif ($token->[0] eq 'T') {      } elsif ($token->[0] eq 'T') {
 # ================================================================= Parsed Text  # ================================================================= Parsed Text
       $stack[$#stack].=$token->[1];        $stack[$#stack].=$token->[1];
    }      }
 }    }
   
 return $outtext;    return $outtext;
 }  }
 # =============================================================================  # =============================================================================
   
Line 212  return $outtext; Line 216  return $outtext;
 # ------------------------------------------------- Helper Routines for Editing  # ------------------------------------------------- Helper Routines for Editing
   
 sub rawprint {  sub rawprint {
    my ($r,$data)=@_;    my ($r,$data)=@_;
    $r->print($data);    $r->print($data);
 }  }
   
 sub insertmenu {  sub insertmenu {
    my ($r,$description,$depthlabel,$xmltagsref)=@_;    my ($r,$description,$depthlabel,$xmltagsref)=@_;
    &rawprint($r,'<br><table bgcolor="#DDDD33" width="100%"><tr><td>');    &rawprint($r,'<br><table bgcolor="#DDDD33" width="100%"><tr><td>');
    &rawprint($r,"\n".'<select name="mod_menu_'.$depthlabel.'">'."\n");    &rawprint($r,"\n".'<select name="mod_menu_'.$depthlabel.'">'."\n");
    &rawprint($r,'<option value="no_changes" selected>(no changes)</option>');    &rawprint($r,'<option value="no_changes" selected>(no changes)</option>');
    &rawprint($r,"\n".    &rawprint($r,"\n".
                 '<option value="delete">Delete '.$description.      '<option value="delete">Delete '.$description.
                                                ' Below</option>');      ' Below</option>');
    my $key;    my $key;
    foreach $key (keys %$xmltagsref) {    foreach $key (keys %$xmltagsref) {
       &rawprint($r,"\n".      &rawprint($r,"\n".
                    '<option value="insert_'.$key.'">Insert '.        '<option value="insert_'.$key.'">Insert '.
                    $$xmltagsref{$key}.'</option>');        $$xmltagsref{$key}.'</option>');
    }    }
    &rawprint($r,"\n".'</select></td></tr></table><br>'."\n");    &rawprint($r,"\n".'</select></td></tr></table><br>'."\n");
 }  }
   
 # =============================================================================  # =============================================================================
Line 240  sub insertmenu { Line 244  sub insertmenu {
 # -------------------------------------------- Initialize routines in $safeeval  # -------------------------------------------- Initialize routines in $safeeval
   
 sub init_safeeval {  sub init_safeeval {
    my $safeeval=shift;    my $safeeval=shift;
    my $initprg=<<'ENDINIT';     my $initprg=<<'ENDINIT'; 
   
 # -------------------------------------------- Initializations inside $safeeval  # -------------------------------------------- Initializations inside $safeeval
   
 $e=25;    $e=25;
 $c=20;    $c=20;
   
 ENDINIT    ENDINIT
 # ---------------------------------------------------------------- Execute that  # ---------------------------------------------------------------- Execute that
    $safeeval->reval($initprg);      $safeeval->reval($initprg);
 }  }
   
 # ----------------------------------------------- Routines that use Safe Spaces  # ----------------------------------------------- Routines that use Safe Spaces
   
 sub printout {  sub printout {
    my ($r,$data,$safespace)=@_;    my ($r,$data,$safespace)=@_;
    $r->print($safespace->reval('return qq('.$data.');'));    $r->print($safespace->reval('return qq('.$data.');'));
 }  }
   
 sub runfile {  sub runfile {
    my ($r,$filename,$safespace)=@_;    my ($r,$filename,$safespace)=@_;
    my $includefile;    my $includefile;
    if ($filename=~/^\//) {    if ($filename=~/^\//) {
        $includefile=$filename;      $includefile=$filename;
    } else {    } else {
        $includefile=$r->dir_config('lonIncludes');      $includefile=$r->dir_config('lonIncludes');
        $includefile.='/'.$filename;      $includefile.='/'.$filename;
    }    }
    if (-e $includefile) {    if (-e $includefile) {
       $safespace->rdo($includefile);      $safespace->rdo($includefile);
    }       }   
 }  }
   
 sub run {  sub run {
    my ($expression,$safespace)=@_;    my ($expression,$safespace)=@_;
    $safespace->reval($expression);       $safespace->reval($expression);   
 }  }
   
 sub booleanexpr {  sub booleanexpr {
    my ($expression,$safespace)=@_;    my ($expression,$safespace)=@_;
    return $safespace->reval('return '.$expression.';');    return $safespace->reval('return '.$expression.';');
 }  }
   
   
Line 290  sub booleanexpr { Line 294  sub booleanexpr {
 # =============================================================================  # =============================================================================
   
 sub start_block {  sub start_block {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    if (!booleanexpr($token->[2]{'condition'},$safeeval)) {    if (!booleanexpr($token->[2]{'condition'},$safeeval)) {
       my $blockdepth=0;      my $blockdepth=0;
       my $nexttoken;      my $nexttoken;
       while ($nexttoken=$parser->get_tag()) {       while ($nexttoken=$parser->get_tag()) { 
          if ($nexttoken->[0] eq 'block') { $blockdepth++ };        if ($nexttoken->[0] eq 'block') { $blockdepth++ };
          if ($nexttoken->[0] eq '/block') {        if ($nexttoken->[0] eq '/block') {
             if ($blockdepth==0) {    if ($blockdepth==0) { 
                return;     return; 
             } else {   } else {
                $blockdepth--;    $blockdepth--;
             }   }
          }  
       }        }
    }      }
    return;    }
     return;
 }  }
   
 sub start_script {  sub start_script {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    $stackref->[$#$stackref+1]='';    $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_script {  sub end_script {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    &run($stackref->[$#$stackref],$safeeval);    &run($stackref->[$#$stackref],$safeeval);
    $#$stackref--;    $#$stackref--;
 }  }
   
 sub start_outtext {  sub start_outtext {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    $stackref->[$#$stackref+1]='';    $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_outtext {  sub end_outtext {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    &printout($r,$stackref->[$#$stackref],$safeeval);    &printout($r,$stackref->[$#$stackref],$safeeval);
    $#$stackref--;    $#$stackref--;
 }  }
   
 sub start_inlinetext {  sub start_inlinetext {
    &start_outtext(@_);    &start_outtext(@_);
 }  }
   
 sub end_inlinetext {  sub end_inlinetext {
    &end_outtext(@_);    &end_outtext(@_);
 }  }
   
 sub start_scriptlib {  sub start_scriptlib {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    &runfile($r,$parser->get_text('/scriptlib'),$safeeval);    &runfile($r,$parser->get_text('/scriptlib'),$safeeval);
 }  }
   
 sub start_parserlib {  sub start_parserlib {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    &runfile($r,$parser->get_text('/parserlib'),$parsereval);    &runfile($r,$parser->get_text('/parserlib'),$parsereval);
 }  }
   
   
 sub start_answer {  sub start_answer {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    $stackref->[$#$stackref+1]='<answer>::'.    $stackref->[$#$stackref+1]='<answer>::'.
      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});         join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});   
    $stackref->[$#$stackref+1]='';    $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_answer {  sub end_answer {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    my @itemtexts;    my @itemtexts;
    my @itemargs;    my @itemargs;
    my $stackpointer=$#$stackref;    my $stackpointer=$#$stackref;
    while (($stackref->[$stackpointer]!~'<answer>::') && ($stackpointer>0)) {     while (($stackref->[$stackpointer]!~'<answer>::') && ($stackpointer>0)) { 
       $stackpointer--;       $stackpointer--; 
    }    }
    my %answerargs=split(/:/,$stackref->[$stackpointer]);    my %answerargs=split(/:/,$stackref->[$stackpointer]);
 }  }
   
 sub start_item {  sub start_item {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;    my ($r,$token,$parser,$safeeval,$stackref)=@_;
    $stackref->[$#$stackref+1]='<item>::'.    $stackref->[$#$stackref+1]='<item>::'.
      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});         join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});   
    $stackref->[$#$stackref+1]='';    $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_item {}  sub end_item {}
Line 381  sub end_item {} Line 385  sub end_item {}
 # =============================================================================  # =============================================================================
   
 sub start_edit_outtext {  sub start_edit_outtext {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;        $stackref)=@_;
    &rawprint($r,"\n<h3>$description</h3>".    &rawprint($r,"\n<h3>$description</h3>".
      '<textarea rows="10" cols="80" name="data_'.$depthlabel.'">');      '<textarea rows="10" cols="80" name="data_'.$depthlabel.'">');
    $stackref->[$#$stackref+1]='';    $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_edit_outtext {  sub end_edit_outtext {
    my ($r,$token,$above,$stackref)=@_;    my ($r,$token,$above,$stackref)=@_;
    &rawprint($r,$stackref->[$#$stackref]."</textarea>\n");       &rawprint($r,$stackref->[$#$stackref]."</textarea>\n");   
    $#$stackref--;    $#$stackref--;
 }  }
   
 sub start_edit_script {  sub start_edit_script {
    &start_edit_outtext(@_);    &start_edit_outtext(@_);
 }  }
   
 sub end_edit_script {  sub end_edit_script {
    &end_edit_outtext(@_);    &end_edit_outtext(@_);
 }  }
   
 sub start_edit_inlinetext {  sub start_edit_inlinetext {
    &start_edit_outtext(@_);    &start_edit_outtext(@_);
 }  }
   
 sub end_edit_inlinetext {  sub end_edit_inlinetext {
    &end_edit_inlinetext(@_);    &end_edit_inlinetext(@_);
 }  }
   
 sub start_edit_block {  sub start_edit_block {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;        $stackref)=@_;
    my $bgcolor=$depthlabel;    my $bgcolor=$depthlabel;
    $bgcolor=~s/\_//g;    $bgcolor=~s/\_//g;
    $bgcolor=substr(length($bgcolor),-1,1);    $bgcolor=substr(length($bgcolor),-1,1);
    $bgcolor=~tr/1-5/A-E/;    $bgcolor=~tr/1-5/A-E/;
    $bgcolor=$bgcolor.'FFF'.$bgcolor.'A';    $bgcolor=$bgcolor.'FFF'.$bgcolor.'A';
    &rawprint($r,"\n".'<br><table border="2" cellpadding="10" bgcolor="#'.    &rawprint($r,"\n".'<br><table border="2" cellpadding="10" bgcolor="#'.
                 $bgcolor.      $bgcolor.
                 '" width="100%"><tr><td><h3>'.$description.'</h3>');      '" width="100%"><tr><td><h3>'.$description.'</h3>');
 }  }
   
 sub end_edit_block {  sub end_edit_block {
    my ($r,$token,$above,$stackref)=@_;    my ($r,$token,$above,$stackref)=@_;
    &rawprint($r,"\n".'</td></tr></table><br>');    &rawprint($r,"\n".'</td></tr></table><br>');
 }  }
   
 sub start_edit_answer {  sub start_edit_answer {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;        $stackref)=@_;
    start_edit_block(@_);    start_edit_block(@_);
    $above=$token->[2]{'type'};    $above=$token->[2]{'type'};
    &rawprint($r,"\n".'<select name="mod_type_'.$depthlabel.'">');    &rawprint($r,"\n".'<select name="mod_type_'.$depthlabel.'">');
    my $key;    my $key;
    foreach $key (keys %$answertyperef) {    foreach $key (keys %$answertyperef) {
       &rawprint($r,"\n".'<option value="'.$key.'"');      &rawprint($r,"\n".'<option value="'.$key.'"');
       if ($above eq $key) { &rawprint($r,' selected'); }      if ($above eq $key) { &rawprint($r,' selected'); }
       &rawprint($r,'>'.$$answertyperef{$key}.'</option>');      &rawprint($r,'>'.$$answertyperef{$key}.'</option>');
    }    }
    &rawprint($r,"\n".'</select>'."\n");    &rawprint($r,"\n".'</select>'."\n");
 }  }
   
 sub end_edit_answer {  sub end_edit_answer {
    my ($r,$token,$above,$stackref)=@_;    my ($r,$token,$above,$stackref)=@_;
    end_edit_block(@_);    end_edit_block(@_);
 }  }
   
 sub start_edit_include {  sub start_edit_include {
     start_edit_block(@_);    start_edit_block(@_);
 }  }
   
 sub end_edit_include {  sub end_edit_include {
     end_edit_block(@_);    end_edit_block(@_);
 }  }
   
 sub start_edit_problem {  sub start_edit_problem {
     start_edit_block(@_);    start_edit_block(@_);
 }  }
   
 sub end_edit_problem {  sub end_edit_problem {
     end_edit_block(@_);    end_edit_block(@_);
 }  }
   
 1;  1;
 __END__  __END__
     
   
   
   

Removed from v.1.2  
changed lines
  Added in v.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>