#ident	"@(#)smail/src:RELEASE-3_2_0_120:mkdriv.awk,v 1.12 2004/01/16 20:35:10 woods Exp"

#    Copyright (C) 1987, 1988 by Ronald S. Karr and Landon Curt Noll
#    Copyright (C) 1992  Ronald S. Karr
#
# See the file COPYING, distributed with smail, for restriction
# and warranty information.

# awk program used from the mkdrivtab.sh shell script for assistance in
# building the drivertab.[ch] files and makefiles for the directors/, routers/,
# transports/, lib/, and (eventually) lookup/ directories.
#
# This awk file takes care of parsing the driver configuration file (read on
# stdin) and producing on stdout directives and text which the shell can
# interpret to build the correct files.  The directives are always of the form
# '%string' and are used to indicate when the shell script should change state.
# The special '%indent' tag is used to indicated lines which should be indented.
#
# See mkdrivtab.sh for details on the input and output formats and for exactly
# how this awk script is used.

BEGIN {
	n_directors = 0;
	n_routers = 0;
	n_transports = 0;
	n_lookups = 0;
	n_dlibs = 0;
	n_rlibs = 0;
	n_tlibs = 0;
	n_llibs = 0;
	lheader[" "] = "";
}

$2 == "library" {
	type = $1;
	d = 0;
	r = 0;
	t = 0;
	l = 0;

	if (type == "director")
		d = 1;
	else if (type == "router")
		r = 1;
	else if (type == "transport")
		t = 1;
	else if (type == "lookup")
		l = 1;
	else {
		print "ERROR!  Unsupported driver type '" type "' for lib '" $2 "' encountered!";
		exit 1;
	}
	for (k = 3; k <= NF; k++) {
		if ($k ~ /^.*\.c$/) {
			if (d)
				dlib[++n_dlibs] = $k;
			else if (r)
				rlib[++n_rlibs] = $k;
			else if (t)
				tlib[++n_tlibs] = $k;
			else if (l)
				llib[++n_llibs] = $k;
		} else if ($k ~ /^.*\.h$/) {
			if (d)
				dheader[$k] = $k;
			else if (r)
				rheader[$k] = $k;
			else if (t)
				theader[$k] = $k;
			else if (l)
				lheader[$k] = $k;
		}
	}
	next;
}

$1 == "director" || $1 == "router" || $1 == "transport" {

	# first field is the driver type
	type = $1;

	d = 0;
	r = 0;
	t = 0;

	if (type == "director") {
		i = ++n_directors;
		d = 1;
		prefix = "dt";
	} else if (type == "router") {
		i = ++n_routers;
		r = 1;
		prefix = "rt";
	} else if (type == "transport") {
		i = ++n_transports;
		t = 1;
		prefix = "tp";
	}
	source = "";
	header = "";

	# second field is the driver name
	name = $2;

	cache = prefix "c_" name;
	driver = prefix "d_" name;
	finish = prefix "f_" name;
	builder = prefix "b_" name;
	dumper = prefix "p_" name;

	# handle any remaining fields....
	for (k = 3; k <= NF; k++) {
		if ($k == "nofinish")
			finish = "NULL";
		else if ($k == "nocache")
			cache = "NULL";
		else if ($k == "nobuilder")
			builder = "NULL";
		else if ($k == "nodumper")
			dumper = "NULL";
		else if ($k ~ /^source=..*\.c$/)
			source = substr($k, 8);
		else if ($k ~ /^header=./)
			header = substr($k, 8);
	}
	if (! source)
		source = name ".c";
	if (! header)
		header = substr(source, 1, length(source) - 2) ".h";

	if (d) {
		dname[i] = name;
		dcache[i] = cache;
		ddriver[i] = driver;
		dfinish[i] = finish;
		dbuilder[i] = builder;
		ddumper[i] = dumper;
		dsource[source] = source;
		dheader[header] = header;
	} else if (r) {
		rname[i] = name;
		rcache[i] = cache;
		rdriver[i] = driver;
		rfinish[i] = finish;
		rbuilder[i] = builder;
		rdumper[i] = dumper;
		rsource[source] = source;
		rheader[header] = header;
	} else if (t) {
		tname[i] = name;
		tcache[i] = cache;
		tdriver[i] = driver;
		tfinish[i] = finish;
		tbuilder[i] = builder;
		tdumper[i] = dumper;
		tsource[source] = source;
		theader[header] = header;
	}
}

$1 == "lookup" {
	name = $2;
	lname[++n_lookups] = name;
	source = "";
	header = "";
	for (k = 3; k <= NF; k++) {
		if ($k ~ /^source=..*\.c$/)
			source = substr($k, 8);
		else if ($k ~ /^header=./)
			header = substr($k, 8);
	}
	if (! source)
		source = name ".c";
	lsource[source] = source;
	if (header)
		lheader[header] = header;
}

END {
	for (i = 1; i <= n_directors; i++) {
		if (dcache[i] != "NULL")
			print "extern void " dcache[i] " __P((struct director *));";
		if (ddriver[i] != "NULL")
			print "extern struct addr *" ddriver[i] " __P((struct director *, struct addr *, struct addr **, struct addr **, struct addr **, struct addr **));";
		if (dfinish[i] != "NULL")
			print "extern void " dfinish[i] " __P((struct director *));";
		if (dbuilder[i] != "NULL")
			print "extern char *" dbuilder[i] " __P((struct director *, struct attribute *));";
		if (ddumper[i] != "NULL")
			print "extern void " ddumper[i] " __P((FILE *, struct director *));";
	}
	for (i = 1; i <= n_routers; i++) {
		if (rcache[i] != "NULL")
			print "extern void " rcache[i] " __P((struct router *));";
		if (rdriver[i] != "NULL")
			print "extern void " rdriver[i] " __P((struct router *, struct addr *, struct addr **, struct addr **, struct addr **));";
		if (rfinish[i] != "NULL")
			print "extern void " rfinish[i] " __P((struct router *));";
		if (rbuilder[i] != "NULL")
			print "extern char *" rbuilder[i] " __P((struct router *, struct attribute *));";
		if (rdumper[i] != "NULL")
			print "extern void " rdumper[i] " __P((FILE *, struct router *));";
	}
	for (i = 1; i <= n_transports; i++) {
		if (tcache[i] != "NULL")
			print "extern void " tcache[i] " __P((struct transport *));";
		if (tdriver[i] != "NULL")
			print "extern void " tdriver[i] " __P((struct addr *, struct addr **, struct addr **, struct addr **));";
		if (tfinish[i] != "NULL")
			print "extern void " tfinish[i] " __P((struct transport *));";
		if (tbuilder[i] != "NULL")
			print "extern char *" tbuilder[i] " __P((struct transport *, struct attribute *));";
		if (tdumper[i] != "NULL")
			print "extern void " tdumper[i] " __P((FILE *, struct transport *));";
	}
	for (i = 1; i <= n_lookups; i++) {
		if (lname[i] != "NULL") {
			print "extern int " lname[i] "_open" " __P((????));";
			print "extern void " lname[i] "_close" " __P((????));";
			print "extern int " lname[i] "_lookup" " __P((????));";
		}
	}
	print ""
	if (n_directors) {
		print "struct direct_driver direct_drivers[] = {";
		for (i = 1; i <= n_directors; i++) {
			printf("%%indent { \"%s\", %s, %s, %s, %s, %s },\n",	\
				dname[i], dcache[i], ddriver[i],		\
				dfinish[i], dbuilder[i], ddumper[i]);
		}
		printf "%%indent { NULL,NULL, NULL, NULL, NULL, NULL },\n};\n\n";
	}
	if (n_routers) {
		print "struct route_driver route_drivers[] = {"
		for (i = 1; i <= n_routers; i++) {
			printf("%%indent { \"%s\", %s, %s, %s, %s, %s },\n",	\
				rname[i], rcache[i], rdriver[i],		\
				rfinish[i], rbuilder[i], rdumper[i]);
		}
		printf "%%indent { NULL, NULL, NULL, NULL, NULL, NULL },\n};\n\n";
	}
	if (n_transports) {
		print "struct transport_driver transport_drivers[] = {";
		for (i = 1; i <= n_transports; i++) {
			printf("%%indent { \"%s\", %s, %s, %s, %s, %s },\n",	\
				tname[i], tcache[i], tdriver[i],		\
				tfinish[i], tbuilder[i], tdumper[i]);
		}
		printf "%%indent { NULL, NULL, NULL, NULL, NULL, NULL },\n};\n\n";
	}
	if (n_lookups) {
		print "struct lookup_proto lookup_protos[] = {";
		for (i = 1; i <= n_lookups; i++) {
			printf("%%indent ");
			printf("{ \"%s\", %s_open, %s_close, %s_lookup },\n",	\
				lname[i], lname[i], lname[i], lname[i]);
		}
		printf "%%indent { NULL, NULL, NULL, NULL, NULL },\n};\n";
	}

	# Next we write the guts of the drivertab.h file
	#
	print "%header_start";

	print "/*";
	print "** director driver definitions";
	print "*/";
	for (i = 1; i <= n_directors; i++) {
		macro = toupper(dname[i]);
		print "#define " macro "_DIRECTOR_DRV_NM\t\"" dname[i] "\"";
	}
	print "";
	print "/*";
	print "** router driver definitions";
	print "*/";
	for (i = 1; i <= n_routers; i++) {
		macro = toupper(rname[i]);
		print "#define " macro "_ROUTER_DRV_NM\t\"" rname[i] "\"";
	}
	print "";
	print "/*";
	print "** transport driver definitions";
	print "*/";
	for (i = 1; i <= n_transports; i++) {
		macro = toupper(tname[i]);
		print "#define " macro "_TRANSPORT_DRV_NM\t\"" tname[i] "\"";
	}
	print "";
	print "/*";
	print "** lookup driver definitions";
	print "*/";
	for (i = 1; i <= n_lookups; i++) {
		macro = toupper(lname[i]);
		print "#define " macro "_LOOKUP_DRV_NM\t\"" lname[i] "\"";
	}
	print "%header_end";

	# Now produce the driver directory makefile macro initializers, one for
	# each driver library sub-directory.
	#
	# These _must_ come last as with each group they cause the driver
	# script to modify its output filename.
	#
	# "The number 4 is the number which is the count of the types."
	# 
	for (step = 0; step < 4; step++) {
		d = 0;
		r = 0;
		t = 0;
		l = 0;
		if (step == 0) {
			if (n_directors == 0)
				continue;
			d = 1;
			type = "directors";
			target = "ddrivlib";
		} else if (step == 1) {
			if (n_routers == 0)
				continue;
			r = 1;
			type = "routers";
			target = "rdrivlib";
		} else if (step == 2) {
			if (n_transports == 0)
				continue;
			t = 1;
			type = "transports";
			target = "tdrivlib";
		} else {
			if (n_lookups == 0)
				continue;
			l = 1;
			type = "lookup";
			target = "ldrivlib";
		}
		print "%makefile_start " type;
		print "TARGET_LIB=" target ".a";
		printf("OBJ=");
		if (d) {
			for (s in dsource) {
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
			for (i = 1; i <= n_dlibs; i++) {
				s = dlib[i];
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
		}
		if (r) {
			for (s in rsource) {
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
			for (i = 1; i <= n_rlibs; i++) {
				s = rlib[i];
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
		}
		if (t) {
			for (s in tsource) {
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
			for (i = 1; i <= n_tlibs; i++) {
				s = tlib[i];
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
		}
		if (l) {
			for (s in lsource) {
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
			for (i = 1; i <= n_llibs; i++) {
				s = llib[i];
				printf(" %s.o", substr(s, 1, length(s)-2));
			}
		}
		printf("\nCSRC=");
		if (d) {
			for (s in dsource) {
				printf(" %s", s);
			}
			for (i = 1; i <= n_dlibs; i++) {
				printf(" %s", dlib[i]);
			}
		}
		if (r) {
			for (s in rsource) {
				printf(" %s", s);
			}
			for (i = 1; i <= n_rlibs; i++) {
				printf(" %s", rlib[i]);
			}
		}
		if (t) {
			for (s in tsource) {
				printf(" %s", s);
			}
			for (i = 1; i <= n_tlibs; i++) {
				printf(" %s", tlib[i]);
			}
		}
		if (l) {
			for (s in lsource) {
				printf(" %s", s);
			}
			for (i = 1; i <= n_llibs; i++) {
				printf(" %s", llib[i]);
			}
		}
		printf("\nHSRC=")
		if (d) for (s in dheader) {
			printf(" %s", s);
		}
		if (r) for (s in rheader) {
			printf(" %s", s);
		}
		if (t) for (s in theader) {
			printf(" %s", s);
		}
		if (l) for (s in lheader) {
			if (s != " ") {
				printf(" %s", s);
			}
		}
		printf("\n%%makefile_end\n");
	}
}

# Local Variables:
# c-file-style: "personal-awk"
# End:
