#!/afs/athena/contrib/perl/p

$ATTACH_PATH =	'/bin/athena/attach';
$LOCKER =	'logos';
$CONFIG_MENU =	'/mit/logos/lib/config.menu';
$FINAL_FILE =	'/afs/.athena/contrib/consult/lib/olh/olh-tree.el';
$OUTPUT_FILE =	'/tmp/new-olh.el';
$ERR_FILE =	"/tmp/olh_gen_tmp.$$";
$ERRORS_TO =	'lwvanels';

$FATAL = 1;
$NORMAL = 0;

open(STDERR,">$ERR_FILE") || die ("Couldn't open $ERROUT: $!");

unlink('/mit/logos');
symlink('/afs/.athena.mit.edu/astaff/project/logos','/mit/logos');

unlink('/mit/olc-stock');
symlink('/afs/.athena.mit.edu/astaff/reference/olc_stock-answers','/mit/olc-stock');

if (! open(OUT,">$OUTPUT_FILE")) {
    print STDERR "Couldn't open $OUTPUT_FILE: $!\n";
    &punt($FATAL);
}

select(OUT);

&init_stuff;
&process_ng_file("",$CONFIG_MENU);

&do_menu_file("olh:top_menu",1);

&end_stuff;

&punt($NORMAL);

#----------------------------------------------------------------------------

sub init_stuff {
    $FILE_LOC =		0;
    $FILE_FORMAT =	1;
    $FILESYSTEM =	2;
    $LABEL =		3;
    $POINTER =		4;
    $TYPE =		5;

    $type_conv{"ez"} = "olh-convert-ez-format";
    $type_conv{"latex"} = "olh-convert-latex-format";
    $type_conv{"plain_text"} = "nil";
    $type_conv{"scribe_PS"} = "nil";
    $type_conv{"DIRHOOK"} = "nil";
    $type_conv{"MENU"} = "nil";
    $type_conv{""} = "nil";

    undef %db;
    print "(defvar olh-tree nil)\n\n";
    print "(setq olh-tree (quote\n";
}

sub end_stuff {
    print "))";
}

#----------------------------------------------------------------------------

sub struct {
    # Format is:
    #  - file location
    #  - file format
    #  - filesystem
    #  - label
    #  - pointer
    #  - type
    join("\n",@_);
}

sub follow_pointer {
    local(@foo) = split("\n",@_[0]);
    local(@bar);
    if ($foo[$POINTER] ne "") {
	if (defined($db{$foo[$POINTER]})) {
	    @bar = &unstruct($db{$foo[$POINTER]});
	} else {
	    print STDERR "Undefined pointer $foo[$POINTER] in node $foo[$LABEL]\n";
	}
	$foo[$FILE_LOC] = $bar[$FILE_LOC] if ($foo[$FILE_LOC] eq "");
	$foo[$FILE_FORMAT] = $bar[$FILE_FORMAT] if ($foo[$FILE_FORMAT] eq "");
	$foo[$FILESYSTEM] = $bar[$FILESYSTEM] if ($foo[$FILESYSTEM] eq "");
	$foo[$LABEL] = $bar[$LABEL] if ($foo[$LABEL] eq "");
	$foo[$TYPE] = $bar[$TYPE] if ($foo[$TYPE] eq "");
	$foo[$POINTER] = $bar[$POINTER];
    }
    @foo;
}

sub unstruct {
    split("\n",@_[0]);
}

#----------------------------------------------------------------------------

sub do_menu_file {
    local($menu_node_id,$what) = @_;
    local(*FD,$filename);
    local($keyword,$value);
    local($was_blank_line,$first);
    local($file_loc,$file_format,$locker,$label,$pointer,$type);
    local($node_id,@node_info);

    if ($what == 1) {
	@node_info = &follow_pointer($db{$menu_node_id});
	if ($node_info[$TYPE] ne "MENU") {
	    print STDERR "Node $menu_node_id is not a menu!\n";
	    return;
	}
	$filename = $node_info[$FILE_LOC];
	&attach_locker($node_info[$FILESYSTEM]);
    } else {
	$filename = $menu_node_id;
    }
    
    if (! open(FD,$filename)) {
	print STDERR "Couldn't open $filename: $!\n";
	&punt($FATAL);
    }

    $was_blank_line = 0;
    $first = 1;
    $file_loc = $file_format = $locker = $label = $pointer = $type = "";
    $node_id = "";

    while (<FD>) {
	chop;
	if (/^\s*$/) {
	    $was_blank_line = 1;
	    next;
	}

	($keyword,$value) = /^([\w-]+)\s+(.*)/;

	if ($was_blank_line) {
	    $was_blank_line = 0;
	    if ($first) {
		print "[\"$node_info[$LABEL]\" nil \"$filename\"\n(";
		$first = 0;
	    } else {
		$tmp = &struct($file_loc, $file_format,
			       $locker, $label, $pointer,
			       $type);
		@bar = &follow_pointer($tmp);
		if ($bar[$FILE_FORMAT] eq "MENU") {
		    if ($pointer ne "") {
			&do_menu_file($pointer,1);
		    } else {
			&do_menu_file($bar[$FILE_LOC],0);
		    }
		} elsif ($bar[$FILE_FORMAT] eq "DIRHOOK") {
		    printf ("[ \"%s\" nil \"%s\" \n(",
			    (($bar[$LABEL] eq "") ? "nil" : $bar[$LABEL]),
			    (($bar[$FILE_LOC] eq "") ? "nil" : $bar[$FILE_LOC]));
		    &do_dirhook($bar[$FILE_LOC]);
		    printf (") \"%s\" nil]\n",
			    (($bar[$FILESYSTEM] eq "") ? "nil" : $bar[$FILESYSTEM]));
		} else {
		    printf("[ \"%s\" nil \"%s\" entry \"%s\" %s]\n",
			   (($bar[$LABEL] eq "") ? "nil" : $bar[$LABEL]),
			   (($bar[$FILE_LOC] eq "") ? "nil" : $bar[$FILE_LOC]),
			   (($bar[$FILESYSTEM] eq "") ? "nil" : $bar[$FILESYSTEM]),
			   $type_conv{$bar[$FILE_FORMAT]});
		}
	    }
	    $file_loc = $file_format = $locker = $label = $pointer = $type = "";
	    $node_id = "";
	}
		    
	next if ($keyword eq "");

	# stuffing values into the right thing by keyword
	if ($keyword =~ /^type/) {
	    if ($type ne "") {
		print STDERR "Duplicate type $type in menu node $menu_node_id in file $filename\n";
	    }
	    $type = $value;
	    next;
	}
	if ($keyword =~ /^file-location/) {
	    if ($file_loc ne "") {
		print STDERR "Duplicate file-location $file_loc in node $node_id in file $filename\n";
	    }
	    $file_loc = $value;
	    $file_loc =~ tr/ //d;
	    next;
	}

	if ($keyword =~ /^file-format/) {
	    if ($file_format ne "") {
		print STDERR "Duplicate file_format $file_format in node $node_id in file $filename\n";
	    }
	    $file_format = $value;
	    $file_format =~ tr/ //d;
	    next;
	}
	if ($keyword =~ /^filesystem/) {
	    if ($locker ne "") {
		print STDERR "Duplicate filesystem $locker in node $node_id in file $filename\n";
	    }
	    $locker = $value;
	    $locker =~ tr/ //d;
	    next;
	}
	if ($keyword =~ /^label/) {
	    if ($label ne "") {
		print STDERR "Duplicate label $label in node $node_id in file $filename\n";
	    }
	    if ($value =~ /"/) { #"
		$value =~ s/"/\\"/g;
	    }
	    $label = $value;
	    next;
	}
	if ($keyword =~ /^pointer/) {
	    if ($pointer ne "") {
		print STDERR "Duplicate pointer $pointer in node $node_id in file $filename\n";
	    }
	    $pointer = $value;
	    $pointer =~ tr/ //d;
	    next;
	}
	next if ($keyword =~ /^do-keywords|^author|^maintainer|^primary-parent|^keywords/);
	print STDERR "punting keyword $keyword in file $filename\n";
    }
    close FD;

    if ($label ne "") {
	$tmp = &struct($file_loc, $file_format,
		       $locker, $label, $pointer,
		       $type);
	@bar = &follow_pointer($tmp);

	if ($bar[$FILE_FORMAT] eq "MENU") {
	    if ($pointer ne "") {
		&do_menu_file($pointer,1);
	    } else {
		&do_menu_file($bar[$FILE_LOC],0);
	    }
	} elsif ($bar[$FILE_FORMAT] eq "DIRHOOK") {
	    printf ("[ \"%s\" nil \"%s\" \n(",
		    (($bar[$LABEL] eq "") ? "nil" : $bar[$LABEL]),
		    (($bar[$FILE_LOC] eq "") ? "nil" : $bar[$FILE_LOC]));
	    &do_dirhook($bar[$FILE_LOC]);
	    printf (") \"%s\" nil]\n",
		    (($bar[$FILESYSTEM] eq "") ? "nil" : $bar[$FILESYSTEM]));
	} else {
	    printf("[ \"%s\" nil \"%s\" entry \"%s\" %s]\n",
		   (($bar[$LABEL] eq "") ? "nil" : $bar[$LABEL]),
		   (($bar[$FILE_LOC] eq "") ? "nil" : $bar[$FILE_LOC]),
		   (($bar[$FILESYSTEM] eq "") ? "nil" : $bar[$FILESYSTEM]),
		   $type_conv{$bar[$FILE_FORMAT]});
	}

    }
    printf (") \"%s\" nil]\n",
	    (($node_info[$FILESYSTEM] eq "") ? "nil" : $node_info[$FILESYSTEM]));
}

#----------------------------------------------------------------------------

sub process_ng_file {
    local($prefix,$filename) = @_;
    local(*FD);
    local($node_id);
    local($file_loc,$file_format,$locker,$label,$pointer,$type);
    local($keyword,$value);

    if (! open(FD,$filename)) {
	print STDERR "Couldn't open $filename: $!\n";
	&punt($FATAL);
    }

    $file_loc = $file_format = $locker = $label = $pointer = $type = "";
    $node_id = "";

    while (<FD>) {
	chop;
	next if (/^\s*$/);
	    
	($keyword,$value) = /^([\w-]+)\s+(.*)/;
	next if ($keyword eq "");

	# stuffing values into the right thing by keyword
	if ($keyword =~ /^type/) {
		
	    # write out previous information
	    if ($type ne "") {
		$db{$prefix . $node_id} = &struct($file_loc, $file_format,
						  $locker, $label, $pointer,
						  $type);
		if ($type eq "NODE GROUP MENU") { # 
		    &process_ng_file(($node_id . ":"), $file_loc);
		}
		$file_loc = $file_format = $locker = $label = $pointer =
		    $type = "";
		$node_id = "";
	    }

	    if ($type ne "") {
		print STDERR "Duplicate type $type in node $node_id in file $filename\n";
	    }
	    $type = $value;
	    next;
	}
	if ($keyword =~ /^file-location/) {
	    if ($file_loc ne "") {
		print STDERR "Duplicate file-location $file_loc in node $node_id in file $filename\n";
	    }
	    $file_loc = $value;
	    $file_loc =~ tr/ //d;
	    next;
	}

	if ($keyword =~ /^file-format/) {
	    if ($file_format ne "") {
		print STDERR "Duplicate file_format $file_format in node $node_id in file $filename\n";
	    }
	    $file_format = $value;
	    $file_format =~ tr/ //d;
	    next;
	}
	if ($keyword =~ /^filesystem/) {
	    if ($locker ne "") {
		print STDERR "Duplicate filesystem $locker in node $node_id in file $filename\n";
	    }
	    $locker = $value;
	    $locker =~ tr/ //d;
	    next;
	}
	if ($keyword =~ /^label/) {
	    if ($label ne "") {
		print STDERR "Duplicate label $label in node $node_id in file $filename\n";
	    }
	    if ($value =~ /"/) { #"
		$value =~ s/"/\\"/g;
	    }
	    $label = $value;
	    next;
	}
	if ($keyword =~ /^pointer/) {
	    if ($pointer ne "") {
		print STDERR "Duplicate pointer $pointer in node $node_id in file $filename\n";
	    }
	    $pointer = $value;
	    $pointer =~ tr/ //d;
	    next;
	}
	if ($keyword =~ /^node-id/) {
	    if ($node_id ne "") {
		print STDERR "Duplicate node id $node_id in node $node_id in file $filename\n";
	    }
	    $node_id = $value;
	    $node_id =~ tr/ //d;
	    next;
	}
	next if ($keyword =~ /^do-keywords|^author|^maintainer|^primary-parent|^keywords/);
	print STDERR "punting keyword $keyword\n";
    }
    close FD;

    if ($type ne "") {
	$db{$prefix . $node_id} = &struct($file_loc, $file_format, $locker, $label,
				$pointer,$type);
    }
}


#----------------------------------------------------------------------------

sub do_dirhook {
    local($current_dir) = @_;
    local($cur_menu_file) = $current_dir . "/.index";
    local(*INDEX);
    if (! open(INDEX,$cur_menu_file)) {
	print STDERR "Couldn't open $cur_menu_file: $!";
	&punt($FATAL);
    }

    while (<INDEX>) {
	next if /^\s*$/;
	local($type,$title,$loc) = split(/:/);
	$filename = $current_dir . "/$loc";
	$title =~ s/"/\\"/g;
	print "[\"$title\" nil \"$filename\" ";
	if ($type eq "entry") {
	    print "entry";
	} else {
	    print "\n(";
	    &do_dirhook($filename);
	    print ")";
	}
	print " \"olc-stock\" nil]\n";
    }
    close INDEX;
}

#----------------------------------------------------------------------------

sub punt {
    local($status) = @_;
    close(STDERR);
    close(OUT);

    if (! -z $ERR_FILE) {
	open(ERR_OUT,"| /usr/lib/sendmail -t");
	select(ERR_OUT);
	print "To: $ERRORS_TO\n";
	if ($status == $FATAL) {
	    print "Subject: FATAL ERROR IN OLH TREE BUILD\n\n";
	    print "***FATAL ERRORS: tree not replaced\n\n";
	} else {
	    print "Subject: Errors in OLH tree build\n\n";
	}

	open(FOO,$ERR_FILE);
	while(<FOO>) {
	    print;
	}
	close(FOO);
	close(ERR_OUT);
    }
    if ($status == $FATAL) {
	unlink($OUTPUT_FILE);
    } else {
	system('mv',$OUTPUT_FILE,$FINAL_FILE);
    }
    unlink($ERR_FILE);
    exit(0);
}

#----------------------------------------------------------------------------
sub attach_locker {
    local($locker) = @_;
    if (! $attached{$locker}) {
	$retval = system($ATTACH_PATH,'-q','-h',$LOCKER);
	$retval = int($retval/256);
	if ($retval != 0) {
	    print STDERR "Couldn't attach $LOCKER: error $retval\n";
	    exit 1;
	}
	$attached{$locker} = 1;
    }
}

#
# Local Variables:
# mode: perl
# End:
#
