[comp.lang.perl] Tom Christiansen's man program no longer works with pl28

bll@seer.UUCP (Brad Lanam) (09/05/90)

    I just brought perl up to patchlevel 28, and everything except
Tom Christiansen's man program seems to work.  It can't seem to find
anything in the dbm database.  I rebuilt the database, but that didn't
help.  He uses those eval things...  I can't figure out how to print
out what is in the dbm array.

    Has anyone else had this problem?
    I'm running Xenix 2.3.2.

    Thanx
    -- Brad

--
Until the next disk seek...
   -- Brad Lanam    ...!uunet!{seeker|unisoft}!seer!bll    bll@seer.uucp
--

    The pertinent sections:

sub fetch {
    local($key,$root) = @_;
    local(%recursed);

    return $dbmopened{$root}
	? &quick_fetch($key,$dbm{$root})
	: &slow_fetch($key,$root);
}

sub quick_fetch {
    local($key,$array) = @_;
    local(@retlist) = ();
    local(@tmplist) = ();
    local($_, $entry);

#############  this line doesn't find a thing ##########

    return @retlist unless $entry = eval "\$$array".'{$key};';

    if ($@) { chop $@; die "bad eval: $@"; }

    @tmplist = split(/\002/, $entry);
    for (@tmplist) {
	if (/\001/) {
	    push(@retlist, $_);
	} else {
	    push(@retlist, &quick_fetch($_,$array))
		unless $recursed{$_}++;
	# explain and diction are near duplicate man pages referencing
	# each other, requiring this check.  one should be removed
	}
    }
    return @retlist;
}

# --------------------------------------------------------------------------
sub find_files {
    local($target) = @_;
    local($root, $entry);
    local(@retlist) = ();
    local(@tmplist) = ();
    local(@entries) = ();
    # globals: $vars, $called_before, %dbm

    $vars = 'dbm00';

    if (!$hard_way && !$called_before++) {
	# generate dbm names
	for $root (@MANPATH) {
	    $dbm{$root} = $vars++; # magic incr
	    $string = "dbmopen($dbm{$root},\"$root/whatis\",0644);";
	    unless (-f "$root/whatis.pag" && eval $string) {
		if ($@) {
		    chop $@;
		    warn "Can't eval $string: $@";
		} else {
		    warn "No dbm file for $root/whatis: $!\n";
		}
		$status = 1;
		next;
	    }
	    $dbmopened{$root} = 1;
	}
    }

    for $root (@MANPATH) {
	@tmplist = ();
	unless ($dbmopened{$root})  {
	    @tmplist = &slow_fetch($target,$root);
	} else {
	    @entries = &fetch($target,$root);
	    next if $#entries < 0;
	    for $entry (@entries) {
		($cmd, $page, $section, $desc) = split(/\001/, $entry);
		$target =~ s/([^\w])/\\$1/g;
		next unless $cmd =~ /$target/ || $page =~ /$target/;
		($stem) = $section =~ /^(.)/;

	    # Check that it exists
		if (-f "$root/man.$stem/$page.$section") {
		    push(@tmplist,  "$root/man.$stem/$page.$section");
	    # perhaps it is compressed ?
		} elsif (-f "$root/man.$stem.z/$page.$section") {
		    push(@tmplist,  "$root/man.$stem.z/$page.$section");
		} elsif (-f "$root/man.$stem/$page.$section.z") {
		    push(@tmplist,  "$root/man.$stem/$page.$section.z");
	    # perhaps a strange section (i.e. 1m)?
		} elsif (-f "$root/man.$section/$page.$section") {
		    push(@tmplist,  "$root/man.$section/$page.$section");
	    # perhaps a strange section (i.e. 1m) AND compressed?
		} elsif (-f "$root/man.$section.z/$page.$section") {
		    push(@tmplist,  "$root/man.$section.z/$page.$section");
		} elsif (-f "$root/man.$section/$page.$section.z") {
		    push(@tmplist,  "$root/man.$section/$page.$section.z");
		} else {
		    printf STDERR "%s: %s.%s has disappeared from %s/man%s\n",
				    $program, $page, $section, $root, $stem;
		    last;
		}
	    }
	}
	push(@retlist, sort bysection @tmplist);
    }
    return &trimdups(@retlist);
}
-- 
Until the next disk seek...
   -- Brad Lanam    ...!uunet!{seeker|unisoft}!seer!bll    bll@seer.uucp

nagel@wintermute.ics.uci.edu (Mark Nagel) (09/06/90)

bll@seer.UUCP (Brad Lanam) writes:

>    I just brought perl up to patchlevel 28, and everything except
>Tom Christiansen's man program seems to work.  It can't seem to find
>anything in the dbm database.  I rebuilt the database, but that didn't
>help.  He uses those eval things...  I can't figure out how to print
>out what is in the dbm array.

>    Has anyone else had this problem?
>    I'm running Xenix 2.3.2.

Yes.  I'm running pl28 on a Sequent Symmetry (Dynix 3.0.12) and it
also exhibits the same problem.  While in the debugger, I can print
keys(dbm00) and values(dbm00), but actually referencing
$dbm00{some_key} fails for whatever (valid) key is used.  I don't
think it is a bug in man, but a bug in dbm access under pl28.

--
Mark Nagel
UC Irvine Depertment of ICS   +----------------------------------------+
ARPA: nagel@ics.uci.edu       | If you improve something long enough   |
UUCP: ucbvax!ucivax!nagel     | eventually you will throw it away.     |

tchrist@convex.COM (Tom Christiansen) (09/06/90)

In article <578@seer.UUCP> bll@seer.UUCP (Brad Lanam) writes:
>
>    I just brought perl up to patchlevel 28, and everything except
>Tom Christiansen's man program seems to work.  It can't seem to find
>anything in the dbm database.  I rebuilt the database, but that didn't
>help.  He uses those eval things...  I can't figure out how to print
>out what is in the dbm array.

You should say 'those damn eval things.' :-)


>    Has anyone else had this problem?

Yes.  Here's mail I received on this.  I must shamefully admit that 
I've not gone to PL28 yet, so haven't seen it -- yet.  Maybe Larry 
can explain.


------- Forwarded Message

Date:         Fri, 17 Aug 90 14:44:48 METDST
From:         Jan Dj{rv <jhd@irfu.se>
Subject:      Perl PL 28 has made your man unoperational :-(
To:           tchrist@irfu.se (Tom Christiansen)



Hi,
I installed perl PL 28 today. After installation I did 'man perl'.
To my big surprise I get
	No dbm file for /usr/local/man/whatis: Permission denied
	No dbm file for /usr/contrib/man/whatis: Permission denied
	No dbm file for /usr/man/whatis: Permission denied

A bit of poking around shows that patch 22 disabled the ability to
dbmopen a file readonly. (I've sent Larry a letter about this, but since
the machine that supply me with News is down, nothing to comp.lang.perl).
Here's my patch in case you are interested:
*** hash.c.orig	Fri Aug 17 12:21:04 1990
- --- hash.c	Fri Aug 17 12:22:45 1990
***************
*** 538,543 ****
- --- 538,545 ----
  	tb->tbl_dbm = dbm_open(fname, O_RDWR|O_CREAT, mode);
      if (!tb->tbl_dbm)
  	tb->tbl_dbm = dbm_open(fname, O_RDWR, mode);
+     if (!tb->tbl_dbm)
+ 	tb->tbl_dbm = dbm_open(fname, O_RDONLY, mode);
  #else
      if (dbmrefcnt++)
  	fatal("Old dbm can only open one database");

Could you perhaps post something about it to c.l.p (if not already done by
somebody else) ?

OK, I tried it again:
% man perl
No manual entry for perl.

Rerun makewhatis. Same thing. Everything I try to man gives me
'No manual entry for ...'.

Have you seen any of this? Do you know whats going on?

In the meantime I'm back to non-perlian man :-(

	Jan D.
- -- 
 ------------------------------------------------------------------------
    Swedish Institute of Space Physics, S-755 91 Uppsala, Sweden
  Phone: (+46) 18-403005.  Telex: 76036 (IRFUPP S).  Fax: (+46) 18-403100 
   INTERNET: jhd@irfu.se     UUCP: ...!uunet!mcvax!sunic!irfu!jhd  
 ------------------------------------------------------------------------

------- End of Forwarded Message

--
 "UNIX was never designed to keep people from doing stupid things, because 
  that policy would also keep them from doing clever things." [Doug Gwyn]

jand@kuling.UUCP (Jan Dj{rv) (09/06/90)

In article <578@seer.UUCP> bll@seer.UUCP (Brad Lanam) writes:
>
>    I just brought perl up to patchlevel 28, and everything except
>Tom Christiansen's man program seems to work.  It can't seem to find
>anything in the dbm database.  I rebuilt the database, but that didn't
>help.  He uses those eval things...  I can't figure out how to print
>out what is in the dbm array.
>
>    Has anyone else had this problem?

The man program uses ndbm and PL 28 has problems with it. It's not anything
wrong with Tom's program, it's perl.

The first problem is that perl doesn't allow open of a dbm file readonly.
Here's my patch for that:
*** hash.c.Distributed	Fri Aug 17 12:26:43 1990
--- hash.c	Mon Aug 20 09:19:37 1990
***************
*** 538,543 ****
--- 538,545 ----
  	tb->tbl_dbm = dbm_open(fname, O_RDWR|O_CREAT, mode);
      if (!tb->tbl_dbm)
  	tb->tbl_dbm = dbm_open(fname, O_RDWR, mode);
+     if (!tb->tbl_dbm)
+ 	tb->tbl_dbm = dbm_open(fname, O_RDONLY, mode);
  #else
      if (dbmrefcnt++)
  	fatal("Old dbm can only open one database");
***************
*** 551,556 ****
--- 553,560 ----
      }
      tb->tbl_dbm = dbminit(fname) >= 0;
  #endif
+     if (!tb->tbl_array && tb->tbl_dbm != 0)
+ 	Newz(507,tb->tbl_array, tb->tbl_max + 1, HENT*);
      return tb->tbl_dbm != 0;
  }
  

The other problem (the one you encountered) was discovered by
Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>. I include his posting here.
With these two patches Tom's man works OK for me.

	Jan D.

Andrew Vignaux writes:

I think the problem is in the lazy array creation that went in in
pl.28.  hfetch() only creates the array if the access is an lval and
it hasn't been stored into already.  Unfortunately, dbm files can
already have stuff in them.  The local fix:

      if (!tb->tbl_array) {
! 	if (lval)
  	    Newz(503,tb->tbl_array, tb->tbl_max + 1, HENT*);

to

      if (!tb->tbl_array) {
! 	if (lval || tb->tbl_dbm)
  	    Newz(503,tb->tbl_array, tb->tbl_max + 1, HENT*);

works, but it means that

	dbmopen(FOO,"foo",0666); print defined(%FOO), "\n";

still prints 0.

Here's a completely unofficial patch that (I think) fixes this
problem.  I'm posting this because I can't believe I'm the only one
who depends on dbm files in perl.  I don't want to go back to 18
because of the lack of dbmopen(FOO, "foo", undef) ;-)

*** ./hash.c~	Tue Aug 14 21:17:53 1990
--- ./hash.c	Sat Aug 18 14:22:50 1990
***************
*** 551,556 ****
--- 551,558 ----
      }
      tb->tbl_dbm = dbminit(fname) >= 0;
  #endif
+     if (!tb->tbl_array && tb->tbl_dbm != 0)
+ 	Newz(507,tb->tbl_array, tb->tbl_max + 1, HENT*);
      return tb->tbl_dbm != 0;
  }


This fix also means that

	dbmopen(FOO,"foo",undef); print defined(%FOO), "\n";
and
	dbmopen(BAR,"bar",0666); print defined(%BAR), "\n";

prints 0 if "foo.dir" doesn't exist, or "bar.{dir,pag}" can't be
created.

Both "fixes" pass make test on a MORE/bsd hp300.

Andrew
-- 
Domain address: Andrew.Vignaux@comp.vuw.ac.nz