#!/usr/bin/perl
#
# $Id: subst.pl,v 4.9 1998/11/15 10:59:01 mj Exp $
#
# Substitute directory names for FIDOGATE scripts
#

use strict;


if($#ARGV < 0) {
    print STDERR
      "usage:   subst.pl [-p] [-t TOPDIR] [-c CONFIG.MAKE] [-v] [-h] [-HC] source ...\n",
      "\n",
      "options:   -d              dump config parameters from config.make\n",
      "           -p              replace 1st line with \#!PERL\n",
      "           -o OPTS         PERL -OPTS\n",
      "           -c CONFIG.MAKE  use specified config.make\n",
      "           -t TOPDIR       set top dir (containing config.*)\n",
      "           -v              verbose\n",
      "           -h              generate paths.h\n",
      "           -H              generate cf_funcs.h\n",
      "           -C              generate cf_funcs.c\n",
      "           -A              generate cf_abbrev.c\n",
      "           -E              generate cf_env.c\n";
    exit 1;
}


use vars qw($opt_d $opt_p $opt_o $opt_c $opt_v $opt_h
	    $opt_H $opt_C $opt_A $opt_E $opt_t);
use Getopt::Std;

getopts('dpo:c:vhHCAEt:');


my $topdir = $opt_t ? $opt_t : ".";
my $config = $opt_c ? $opt_c : "$topdir/config.make";

my %macros;
my %macros_v;
my %subst;
my %macros;
my $perl;
my %abbrevs;



##### Write cf_funcs.h #######################################################

sub cf_funcs_h {
    my($key) = @_;

    my $lkey = $key;
    $lkey =~ tr/A-Z/a-z/;

    print
	"char *cf_p_$lkey(void);\n",
	"char *cf_s_$lkey(char *);\n";
}



##### Write cf_funcs.c #######################################################

sub cf_funcs_c {
    my($key) = @_;

    my $lkey = $key;
    $lkey =~ tr/A-Z/a-z/;

    print
	"/***** $key *****/\n";
    print
	"static char *cf_p_s_$lkey(char *s)\n",
	"{\n",
	"    static char *pval = NULL;\n",
	"    if(s)\n",
	"        pval = strsave(s);\n",
	"    if(! pval)\n",
	"    {\n",
	"	if( ! (pval = cf_get_string(\"$key\", TRUE)) )\n",
	"	    pval = DEFAULT_$key;\n",
	"	debug(8, \"config: $key %s\", pval);\n",
	"    }\n",
	"    return pval;\n",
	"}\n",
	"char *cf_p_$lkey(void)\n",
	"{\n",
	"    return cf_p_s_$lkey(NULL);\n",
	"}\n",
	"char *cf_s_$lkey(char *s)\n",
	"{\n",
	"    return cf_p_s_$lkey(s);\n",
	"}\n\n";
}



##### Write cf_env.c #########################################################

sub cf_env_c {
    my($key) = @_;

    my $lkey = $key;
    $lkey =~ tr/A-Z/a-z/;

    print
	"    if( (p = getenv(\"FIDOGATE_$key\")) )\n",
	"        cf_s_$lkey(p);\n";
}



##### Generate code ##########################################################
sub gen_code {
    my($name) = @_;

    my($s, $r);

    if($name eq "perl-default") {
	print "##Automatically generated by subst.pl, DO NOT EDIT!!!##\n";
	for $s (keys %macros) {
	    $r = $macros{$s};
	    $s =~ tr/A-Z/a-z/;
	    print "\t\"$s\", \"$r\",\n";
	}
    }

    if($name eq "perl-abbrev") {
	print "##Automatically generated by subst.pl, DO NOT EDIT!!!##\n";
	for $s (keys %abbrevs) {
	    $r = $abbrevs{$s};
	    $s =~ tr/A-Z/a-z/;
	    print "\t\"$r\", \"$s\",\n";
	}
    }
}


##### Read file, substitute, write to STDOUT #################################

my $first_file = 1;

sub do_file {
    my($name) = @_;

    local(*F);
    my($s, $r);

    open(F,"$name") || die "subst: can't open $name\n";
    # perl interpreter
    if($first_file && $opt_p) {
	$first_file = 0;
	$_ = <F>;
	print "#!$perl";
	print " $opt_o" if($opt_o);
	print "\n";
    }

    while(<F>) {
	# Generate code
	if( /^\s*<GEN ([A-Za-z_-]+)>\s*$/ ) {
	    &gen_code($1);
	    next;
	}

	# Include
	if( /^\s*<INCLUDE (.*)>\s*$/ ) {
	    &do_file("$topdir/$1");
	    next;
	}

	# Substitute
	for $s (keys %macros) {
	    $r = $macros{$s};
	    s/<$s>/$r/g;
	}
	for $s (keys %subst) {
	    $r = $subst{$s};
	    s/<$s>/$r/g;
	}
	
	print;
    }
    close(F);
}



##### Main ###################################################################

my ($s, $r, $o, $m, $ls, $f);

# Read config.make
open(P, "$config") || die "subst: can't open config.make\n";

while(<P>) {
    chop;
    next if( /^\s\#/ );
    s/\#.*$//;

    if( /^\s*DEFAULT_F_([A-Z0-9_]+)\s*=\s*(.*)\s*$/ ) {
	print "subst: $1=$2\n" if($opt_v);
	$macros{$1} = $2;
    }
    elsif( /^\s*DEFAULT_V_([A-Z0-9_]+)\s*=\s*(.*)\s*$/ ) {
	print "subst: $1=$2\n" if($opt_v);
	$macros{$1} = $2;
	$macros_v{$1} = 1;
    }
    elsif( /^\s*DEFAULT_A_([A-Z0-9_]+)\s*=\s*%(.)\s*$/ ) {
	print "subst: $1=%$2\n" if($opt_v);
	$abbrevs{$1} = $2;
    }
    elsif( /^\s*PERL\s*=\s*(.*)\s*$/ ) {
	print "subst: perl=$1\n" if($opt_v);
	$perl = $1;
    }
    elsif( /^\s*([A-Z0-9_]+)\s*=\s*(.*)\s*$/ ) {
	# all other macros in config.make
	$subst{$1} = $2 if(! $macros{$1});
    }
}
close(P);

# Resolve macros (only 1 level allowed)
for $s (keys %macros) {
    $r = $macros{$s};
    if( $r =~ /\$\((.*)\)/ ) {
	$o = $1;
	$m = $1;
	$m =~ s/^DEFAULT_(._)?//;
	$r =~ s/\$\($o\)/$macros{$m}/;
	$macros{$s} = $r;
	print "subst: $s=$r\n" if($opt_v);
    }
}



# Dump parameters
if($opt_d) {
    for $s (keys %macros) {
	print
	    "$s ", ($macros_v{$s} ? "(variable)" : "(fixed)"),
	    " = $macros{$s}\n";
    }
    for $s (keys %abbrevs) {
	print
	    "%$abbrevs{$s} = $s\n";
    }
    print "perl = $perl\n";

    exit 0;
}



# Write cf_funcs.h
if($opt_H) {
    print
	"/* Automatically generated by subst.pl --- DO NOT EDIT!!! */\n\n",
	"/*\n",
	" * FIDOGATE\n",
	" *\n",
	" * \$Id\$\n",
	" */\n\n";
    
    for $s (keys %macros) {
	&cf_funcs_h($s) if($macros_v{$s});
    }

    exit 0;
}



# Write cf_funcs.c
if($opt_C) {
    print
	"/* Automatically generated by subst.pl --- DO NOT EDIT!!! */\n\n",
	"/*\n",
	" * FIDOGATE\n",
	" *\n",
	" * \$Id\$\n",
	" */\n\n",
	"\#include \"fidogate.h\"\n\n";
    
    for $s (keys %macros) {
	&cf_funcs_c($s) if($macros_v{$s});
    }

    exit 0;
}



# Write paths.h
if($opt_h) {

    print
	"/* Automatically generated by subst.pl --- DO NOT EDIT!!! */\n\n",
	"/*\n",
	" * FIDOGATE\n",
	" *\n",
	" * \$Id\$\n",
	" */\n\n";

    for $s (keys %macros) {
	$r = $macros{$s};
	printf "#define DEFAULT_%-23s \"%s\"\n", $s, $r;
    }

    exit 0;
}



# Write cf_abbrev.c
if($opt_A) {
    print
	"/* Automatically generated by subst.pl --- DO NOT EDIT!!! */\n\n",
	"/*\n",
	" * FIDOGATE\n",
	" *\n",
	" * \$Id\$\n",
	" */\n\n";

    for $s (keys %abbrevs) {
	$ls = $s;
	$ls =~ tr/A-Z/a-z/;
	$r = $abbrevs{$s};
	printf "{ '$r', cf_p_$ls },\n", $s, $r;
    }

    exit 0;
}



# Write cf_env.c
if($opt_E) {
    print
	"/* Automatically generated by subst.pl --- DO NOT EDIT!!! */\n\n",
	"/*\n",
	" * FIDOGATE\n",
	" *\n",
	" * \$Id\$\n",
	" */\n\n";

    for $s (keys %macros) {
	&cf_env_c($s) if($macros_v{$s});
    }
    exit 0;
}



# Substitute
for $f (@ARGV) {
    &do_file($f);
}

exit 0;
