# $Id: postcompile.pl,v 1.2 91/07/16 03:27:14 tchrist Exp Locker: tchrist $

sub postload {
    local($debug) = $Debug || defined $ENV{'debug_load'};

    local($__fun__) = $__whowasi__ || die("dunno who i was!");
    local($__addr__);

    die("No address for $__fun__") 
	unless $__addr__ = $Func_Addrs{$__fun__};

    die("$__fun__ should already be loaded") 
	if $__addr__ < $Data_Start;

    die("can't load $__fun__ from $__fun__ on <DATA>: $!") 
	unless seek(DATA,$__fun__,0);

    warn(sprintf("(autoloading %s from byte %07o)\n", $__fun__, $__addr__))
		    if $debug;

    seek(DATA,$__addr__,0);

    local($__code__,$_);

    while (<DATA>) {
        $__code__ .= $_;
        last if /^\}/;
    }

    die "No /^sub\\s$__fun__/in code at $__addr__:\n$__code__\n" 
	unless $__code__ =~ /^sub\s+$__fun__/;

    local($tmp) = substr($_stub{$__fun__}, 7*4, 4);   
    substr($_stub{$__fun__}, 7*4, 4) = substr($_main{$__fun__}, 7*4, 4);
    substr($_main{$__fun__}, 7*4, 4) = $tmp;

    eval $__code__;

    $@ && die(sprintf(
		    "code for %s (addr %07o) didn't eval: %s\n CODE:\n%s",
		    $__fun__, $Func_Addrs{$__fun__}, $@, $__code__
		)
	    );

    &$__fun__;
}

sub fetch_function_addrs {
    local($count);
    local($_);
    local($hischecksum, $mychecksum);
    local($update);


    local($ADDR_CACHE) = $ENV{ADDR_CACHE} || shift || "$0.addrs";

    local($debug) = $Debug || defined $ENV{'debug_load'};

    $Data_Start = tell(DATA);

    print STDERR "gathering functions form $ADDR_CACHE: " if $debug;

    seek(DATA,0,0) || die "can't seek on DATA: $!";

    { local($/); $mychecksum = unpack("%16C*", <DATA>); }

    local($_) = '';

    if (((stat(DATA))[9] > (stat("$ADDR_CACHE.pag")))[9]) {
	print STDERR "addrcache out of date "  if $debug;
	$update++;
    }
    elsif (!dbmopen(%Func_Addrs, $ADDR_CACHE, undef)) {
	print STDERR "can't dbmopen addrcache $ADDR_CACHE for read: $! " 
	    if $debug;
	$update++;
    } 
    else {
	$hischecksum = $Func_Addrs{'%CHECKSUM'};
        if ($mychecksum != $hischecksum) {
	    print STDERR "checksum mismatch "  if $debug;
	    $update++;
	} else {
	    $count = 'already loaded';
	} 
    } 

    if ($update && !dbmopen(%Func_Addrs, $ADDR_CACHE, 0644)) {
	print STDERR "can't dbmopen addrcache $ADDR_CACHE for write: $! " 
	    if $debug;
    } 


    if ($update) {
	seek(DATA,0,0);
	%Func_Addrs = ();

	for (local($told); <DATA>; $told = tell) {
	    next unless /^\s*sub\s+((\w+')?(\w+))/;
	    warn "duplicate func $1 @ $told" if defined $Func_Addrs{$1};
	    $Func_Addrs{$1} = $told;
	    $count++;
	}

	$Func_Addrs{'%CHECKSUM'} = $mychecksum;

	reset 'F';  # XXX just blew away the F vars
    }

    print STDERR "found $count functions\n" if $debug;

    seek(DATA,$Data_Start,0);

}
