#!/usr/bin/perl
#
# def2envvar [outfile]
#
# This routine chews up a list of C  #define  statements  that  define
# compile-time  constants,  and  converts them into variables with the
# same initial values. The data is read from stdin and the transformed
# data  is  written  to  stdout, so that you can use it from vi with a
# command like:
#   !3}def2envvar
# or
#   :.,+25!def2envvar
#
# We also produce a list of statements to look for the same symbols in
# the environment, and assign the value to the variable.   Consider  a
# program with hard-wired with hard-wired constants like:
#
#   #define VERSION            "1.2"  /* version */
#   #define REVISION           "2"    /* revison */
#   #define VDATE      "Sep 29 1996"  /* version date */
#   #define MAINTITLE1          18
#   #define SUBTITLE1           15
#   #define SUBSUBTITLE1        12
#   #define ASKIP1              0.4 * CM
#
# This program will convert these lines to:
#
#   char* VERSION      = "1.2";	/* version */
#   int   MAINTITLE1   = 18;
#   float ASKIP1       = 0.4 * CM;
#
# It will also produce a file loadEnv.c that looke like:
#
# #include <stdio.h>
# loadEnv()
# { extern char* getenv();
#   char* pp;
#   int   ii;
#   float ff;
#   if (pp = getenv("VERSION")) {
#   	VERSION = pp;
#   }
#   if (pp = getenv("MAINTITLE1")) {
#   	if (sscanf(pp,"%d",&ii) > 0) MAINTITLE1 = ii;
#   }
#   if (pp = getenv("ASKIP1")) {
#   	if (sscanf(pp,"%ff",&ff) > 0) ASKIP1 = ff * CM;
#   }
# }
#
# The latter is a rather limited case; it only recognizes  expressions
# that  contain  a  numeric value (int or float), possibly followed by
# some junk that is simply carried along.  This suffices for the cases
# that I've dealt with so far.
#
# Note  that  the  variables pp, ii and ff are fixed; if they conflict
# with other variables, well, tough.
#
# AUTHOR: John Chambers <jc@trillian.mit.edu>

$| = 1;
$stat = 0;
($me = $0) =~ s".*/"";
$D = $ENV{"D_$me"} || 0;
$F = $ARGV[0] || "loadEnv.c";

open(F,">$F") || die "$me: Can't write $F [$!]\n";
print F "#include \"local.h\"\n";
print F "\n";
print F "loadEnv() \n";
print F "{	extern char* getenv();\n";
print F "	char* pp;\n";
print F "	int   ii;\n";
print F "	float ff;\n";

for $l (<>) {
	if ($l =~ /#define\s+(\w+)\s+(.*)$/) {
		&cmd($1,$2);
	} else {
		print $l;
	}
}
print F "}\n";

exit $stat;


sub cmd {
	local($sym,$val,$cmt) = @_;

	if ($val =~ /^(.*)(\s+\/\*.*\*\/)\s*$/) {
		$val = $1;
		$cmt = $2;
	}
	$val =~ s/\s+$//;
	if ($val =~ /^"/) {
		print "char*	$sym = $val;$cmt\n";
		print F "	if (pp = getenv(\"$sym\")) {\n";
		print F "		extern char* $sym;\n";
		print F "		$sym = pp;\n";
		print F "	}\n";
	} elsif ($val =~ /^'/) {
		print "char	$sym = $val;$cmt\n";
	} elsif ($val =~ /^(\d+)(\.*\d*)(.*)/) {	# Number.
		if ($2) {	# Float
			print "float	$sym = $val;$cmt\n";
			print F "	if (pp = getenv(\"$sym\")) {\n";
			print F "		extern float $sym;\n";
			print F "		if (sscanf(pp,\"%f\",&ff) > 0) $sym = ff$3;\n";
			print F "	}\n";
		} else {	# Int
			print "int	$sym = $val;$cmt\n";
			print F "	if (pp = getenv(\"$sym\")) {\n";
			print F "		extern int $sym;\n";
			print F "		if (sscanf(pp,\"%d\",&ii) > 0) $sym = ii$3;\n";
			print F "	}\n";
		}
	} else {
		print "#define $sym $val	$cmt\n";
	}
}
