#!/bin/sh

# Shell script to convert collected configuration data to HTML-format.
# Copyright (C) 2001-2004 Open Challenge B.V.
# Copyright (C) 2004-2005 OpenEyeT Professional Services.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.
# If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contact information: www.OpenEyeT.nl/scc/index.html 

# SCC-release:	1.6.26
# file-version:	$Revision: 1.69 $


ProgName=${0##*/};			export ProgName

if [ $# -ne 1 ]
then
	echo "Syntax error, use ${ProgName} <name>" >&2
	exit 1
fi

SCC_BIN=/opt/scc/bin
SCC_TOP=/var/opt/scc
export SCC_BIN SCC_TOP

export SCC_DATA=${SCC_TOP}/data
export SCC_TMP=${SCC_TOP}/tmp
export SCC_CONF=/etc/opt/scc/conf

export TMPDIR=${SCC_TMP}
export TMP=${SCC_TMP}

export SHELL=/bin/sh
export LANG=C

umask 077

PATH=/sbin:/usr/sbin:/usr/bin:/bin;	export PATH

# Use the following utilities for SunOS.
if [ -x /usr/ccs/bin/what ]
then
	alias what=/usr/ccs/bin/what
fi
if [ -x /usr/xpg4/bin/awk ]
then
	alias awk=/usr/xpg4/bin/awk
fi
if [ -x /usr/xpg4/bin/grep ]
then
	alias grep=/usr/xpg4/bin/grep
fi
if [ -x /usr/xpg4/bin/tr ]
then
	alias tr=/usr/xpg4/bin/tr
fi

cd ${SCC_TMP}

export TMP_FILE=${SCC_TMP}/scc_html_$$
export IND_FILE=${SCC_TMP}/scc_ind_$$
export HLP_CLASSES=${SCC_TMP}/scc_help_c_$$
export HLP_USED=${SCC_TMP}/scc_help_u_$$

trap "rm -f ${TMP_FILE} ${IND_FILE} ${HLP_CLASSES} ${HLP_USED}" 0
trap "exit 2" 1 2 3 15

# Replace special HTML-characters in input.
# Anything that does not start with fix: or var: is unexpected.
# Remove the special tags used by scc-collect and scc-log to
# detect and handle changes in user modules.
sed	-e '/^var:MoDuLe:start::/d'	\
	-e '/^var:MoDuLe:end::/d'	\
	-e 's/&/\&amp;/g'		\
	-e 's/</\&lt;/g'		\
	-e 's/>/\&gt;/g'		\
	-e "s/'/\&#39;/g"		\
	-e 's/"/\&quot;/g'			|
awk '/^fix:|^var:|^hlp:/	{ print; next }
				{ print "fix:unexpected data::" $0 }' >${TMP_FILE}

TOP_NAME="<A NAME=cfg_top></A>"
TOP_URL="<A HREF=#cfg_top>Top</A>&nbsp;&nbsp;&nbsp;&nbsp;"

echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
echo "<HTML>"

echo "<HEAD>"
echo '<LINK HREF="style.css" REL="stylesheet" TYPE="text/css">'
echo "<TITLE>Configuration: ${1}</TITLE>"
echo "</HEAD>"

echo "<BODY>"
echo "${TOP_NAME}"
echo "<H1>"
echo "	Configuration: ${1}"
echo "</H1>"

# DO NOT CHANGE THE FOLLOWING HTML-CODE WITHOUT CONSULTING scc.cgi IN scc-srv
echo "<H4>"
echo "	<A HREF=index.html>Home</A>&nbsp;&nbsp;&nbsp;&nbsp;"
echo "	<A HREF=scc.${1}.log.html>Logbook</A>"
echo "	&nbsp;&nbsp;&nbsp;&nbsp;<A HREF=#statistics>Statistics</A>"
echo "	&nbsp;&nbsp;&nbsp;&nbsp;<A HREF=#legend>Legend</A>"
echo "</H4>"

# Get all the help classifications from the snap-shot.
sed	-n		\
	-e 's/::.*//'	\
	-e 's/\\/_/g'	\
	-e '/^hlp:/p' ${TMP_FILE} 2>/dev/null		|
sort -u >${HLP_CLASSES}

# Initialize the file containing the classifications of the help-info that is referenced.
>${HLP_USED}

# Get all the hierarchical classifications from the snap-shot.
# Do not sort, we depend on the order of the collect-script.
grep "^[fv][ia][xr]:" ${TMP_FILE}	|
sed	-e 's/^var://'	\
	-e 's/^fix://'	\
	-e 's/::.*//'	\
	-e 's/\\/_/g'			|
uniq					|
awk -F: '{
	# Format of the input is (for level 3 classification):
	# a:b:c
	# Generate:
	# - level 1 menu item: a
	# - level 2 menu item: a:b
	# - level 3 menu item: a:b:c
	# Each line of output has the following format:
	# <level>:<id of parent menu>:<id of menu-item>:<classification>
	for ( level = 1; level <= NF; level++ )
	{
		prev_class = class;
		if ( level == 1 )
		{
			class = $1;
		}
		else
		{
			class = sprintf( "%s:%s", class, $level );
		}
		if ( ! id[ class ] )
		{
			# One line may cause several new submenus.
			id[ class ] = ( 10 * NR ) + level;
			print level ":" id[ prev_class] ":" NR ":" class;
		}
	}
}' -				|
sort -t: -n -k 1 -k 2 -k 3	|
awk -F: '/^hlp:/	{
				# Format of the data is:
				# hlp:<classification>::<data>
				class = $2;
				for ( i = 3; length( $i ) > 0; i++ )
				{
					class = sprintf( "%s_%s", class, $i );
				}
				gsub( /[: 	\\]/, "_", class );
				help_avail[ class ] = 1;
				next;
			}
	{
		# Format of the data is:
		# <level>:<submenu-id>:<line-number>:<classification>
		if ( $1 != prev_level )
		{
			prev_level=$1;
			if ( NR > 1 )
			{
				print "<HR>";
			}
		}

		if ( ( $1 > 1 ) && ( $2 != prev_menu ) )
		{
			# Produce the heading of a submenu (name, top-reference, optional help, label).
			print "<H4>"

			# Produce the name of this submenu.
			url = $4;
			for ( i = 5; i < NF; i++ )
			{
				url = sprintf( "%s_%s", url, $i );
			}
			gsub( /[: 	\\]/, "_", url );
			printf( "	<A NAME=\"cfg_%s\"></A>\n", url );

			print "	" u;			# Reference to TOP
			if ( help_avail[ url ] )
			{
				printf( "	<A HREF=\"#hlp_%s\">Help</A>&nbsp;&nbsp;&nbsp;&nbsp;", url );
				print "hlp_" url >>t;	# Indicate that this help-info is referenced.
			}

			# Produce references to parent menus.
			url = "#cfg"
			for ( i = 4; i < ( NF - 1 ); i++ )
			{
				url = sprintf( "%s_%s", url, $i );
				gsub( /[: 	\\]/, "_", url );
				printf( "	<A HREF=\"%s\">%s</A> - \n", url, $i );
			}
			print "	" $i;

			print "</H4>"
			prev_menu = $2;
		}

		url = $4;
		for ( i = 5; i <= NF; i++ )
		{
			url = sprintf( "%s_%s", url, $i );
		}
		gsub( /[: 	\\]/, "_", url );
		printf( "		<A HREF=\"#cfg_%s\">%s</A><BR>\n", url, $NF );
	}'				\
		t="${HLP_USED}"		\
		u="${TOP_URL}"		\
			${HLP_CLASSES}	\
			-

# The entire menu-structure has been built.
# Show all the data.
# To "group" all data per classification, we rewrite the snapshot.
# - each "new" classification is prefixed by the line:
#	<first-line-number>:0:<class>
# - each line of a snapshot is extended with:
#	<first-line-number-of-classification>:<line-number>:<data>
# By sorting the resulting file, all data with the same classifications are
# grouped together, while the order of the lines within a classification
# is preserved from the original snapshot.
(
	cat ${HLP_CLASSES}

	awk -F":" '/^fix:|^var:/	{
		# Get the classification, ignore the first part: fix/var.
		class = $2;
		for ( i = 3; length( $i ) > 0; i++ )
		{
			class = sprintf( "%s - %s", class, $i );
		}
		if ( ! id[ class ] )
		{
			id[ class ] = NR;
			printf( "%d:0:%s:%s", NR, class, $2 );
			for ( i = 3; length( $i ) > 0; i++ )
			{
				printf( ":%s", $i );
			}
			print "";
		}
		printf( "%d:%d:%s\n", id[ class ], NR, $0 );
	}' ${TMP_FILE}			|
	sort -t: -n -k 1 -k 2
)						|
awk -F":" '\
/^hlp/		{
			# Syntax of each line:
			#hlp:<classification>
			help_avail[ $0 ]=1;
			next;
		}
/^[0-9]/	{
	# Here we process the snapshot, prefixed with two numbers to group all data.
	if ( $2 == 0 )
	{
		# This is the start of a new classification.
		# Format is: <id>:<0>:<header of classification>:<classification>
		if ( started )
		{
			print "</PRE>"
			general=0;
		}
		started = 1;
		print "<HR>"

		printf( "<H4>%s", u );

		# Check whether help-info is available.
		class="hlp";
		for ( i = 4; length( $i ) > 0; i++ )
		{
			class=sprintf( "%s:%s", class, $i );
		}
		if ( help_avail[ class ] )
		{
			gsub( /[: 	\\]/, "_", class );
			printf( "<A HREF=\"#%s\">Help</A>&nbsp;&nbsp;&nbsp;&nbsp;", class );
			print class >>t;
		}

		class=$4;
		for ( i = 5; length( $i ) > 0; i++ )
		{
			class=sprintf( "%s_%s", class, $i );
		}
		gsub( /[ 	\\]/, "_", class );

		printf( "<A NAME=\"cfg_%s\"></A>", class );	# Produce the name of this sub-menu/data

		# References to all previous menus in the hierarchy.
		tag = "";
		sep = "";
		for ( depth = 4; length( $(depth + 1) ) > 0; depth++ )
		{
			tag = sprintf( "%s_%s", tag, $depth );
			gsub( /[ 	\\]/, "_", tag );
			printf( "%s<A HREF=\"#cfg%s\">%s</A>\n", sep, tag, $depth );
			sep = " - ";
		}
		print "	" sep $depth;

		print "</H4>";
		print "<PRE>"
		if ( $3 == "general" )
		{
			general=1;
		}
		next;
	}

	# Format is: <id>:<line-number>:<classification>::<data>
	if ( $3 == "hlp" )
	{
		next;	# help-info is processed later in this program.
	}

	# Show var-data in a different color.
	var_font_start=""
	var_font_end=""
	if ( ( $3 != "fix" ) && ( c != "no_color" ) )
	{
		var_font_start=sprintf( "<FONT color=%s>", c );
		var_font_end="</FONT>"
	}

	if ( general )
	{
		# Format of the data is:
		#<classID>:<lineNR>:fix_or_var:general::<label>:<data>
		#1         2        3          4       5 6      7
		printf( "%s", var_font_start );
		gsub( /^[ 	]*/, "", $7 );	# align data with ":" after the label
		printf( "%-25s: %s", $6, $7 );
		for ( i = 8; i <= NF; i++ )
		{
			printf( ":%s", $i );
		}
		print var_font_end;
	}
	else
	{
		# Format of the data is:
		#<classID>:<lineNR>:fix_or_var:<class>::<data>
		#1         2        3          4        
		# We only want to display the data, ignore leading fields.
		for ( i = 4; length( $i ) > 0; i++ )
		{ }
		i++;		# skip ::

		# Dennis Bieling indicated that sprintf cannot be used on Debian for lines containing too many fields.
		if ( length( $i ) > 0 || i < NF )
		{
			printf( "%s%s", var_font_start, $i );
			for ( i++; i <= NF; i++ )
			{
				printf( ":%s", $i );
			}
			printf( "%s\n", var_font_end );
		}
		else
		{
			print "&nbsp;";
		}
	}
	next;
}
END	{
		print "</PRE>"
	}'	c="${SCC_VAR_COLOR:-purple}"	\
		t="${HLP_USED}"			\
		u="${TOP_URL}"			\
			-
# Edit scc-localize to change the default setting of ${SCC_VAR_COLOR}.

# Calculate and show the statistics.
echo "<HR>"
echo "<H4>${TOP_URL}<A NAME=statistics>Statistics</A></H4>"

echo "<P>Help-info is excluded from the statistics.</P>"

awk -F:	'/^fix/	{ fix_cnt+=1; }
	/^var/	{ var_cnt+=1; }
		{
			c=sprintf( "%s:%s", $2, $3 );
			main_cnt[ $2 ] += 1;
			sub_cnt[ c ] += 1;
		}
END	{
		main_cnt[ "general:" ] += 4;	# start/stop/runtime added by scc-log
		total = NR + 4;			# start/stop/runtime added by scc-log

		var_cnt += 4;
		printf( "%s::%d:%d:%d:%d\n", "fix", total, 100, fix_cnt, 0.5 + ( 100 * fix_cnt ) / total );
		printf( "%s::%d:%d:%d:%d\n", "var", total, 100, var_cnt, 0.5 + ( 100 * var_cnt ) / total );

		for ( s in sub_cnt )
		{
			split( s, part, ":" );
			main_counter = main_cnt[ part[ 1 ] ];
			printf( "%s:%d:%d:%d:%d\n", \
				s, main_counter, 0.5 + ( 100 * main_counter ) / total,  \
				sub_cnt[ s ], 0.5 + ( 100 * sub_cnt[ s ]) / main_counter );
		}
	}' ${TMP_FILE}							|
sort -t: -k 3nr -k 1,1 -k 5nr						|
awk -F: '/^fix:/	{
				print "<TABLE SUMMARY=fix_var_counts BORDER CELLSPACING=1 CELLPADDING=1>"
				print "<TR>";
				print "	<TH>Category</TH>";
				print "	<TH>Count</TH>";
				print "	<TH>Percentage</TH>";
				print "</TR>";

				print "<TR>";
				print "	<TD>" $1 "</TD>";
				print "	<TD align=right>" $5 "</TD>";
				print "	<TD align=right>" $6 "</TD>";
				print "</TR>";
                                next;
                        }
        /^var:/		{
				print "<TR>";
				print "	<TD>" $1 "</TD>";
				print "	<TD align=right>" $5 "</TD>";
				print "	<TD align=right>" $6 "</TD>";
				print "</TR>";
				print "<TR>";
				print "	<TD>" "total" "</TD>";
				print "	<TD align=right>" $3 "</TD>";
				print "	<TD align=right>" $4 "</TD>";
				print "</TR>";
				print "</TABLE>"
                                next;
                        }
        {
                if ( header_done == 0 )
                {
			print "<BR>"
			print "<TABLE SUMMARY=class_counts BORDER CELLSPACING=1 CELLPADDING=1>"
			print "<TR>"
			print "	<TH>Main class</TH>"
			print "	<TH>Sub class</TH>"
			print "	<TH>Main cnt</TH>"
			print "	<TH>Main perc</TH>"
			print "	<TH>Sub cnt</TH>"
			print "	<TH>Sub perc</TH>"
			print "</TR>"

                        header_done = 1;
                }

                if ( $1 != prev )
                {
			# Print the main-count
			print "<TR>"
			print "	<TD>" $1 "</TD>"
			print "	<TD> &nbsp; </TD>"
			print "	<TD align=right>" $3 "</TD>"
			print "	<TD align=right>" $4 "</TD>"
			print "	<TD> &nbsp; </TD>"
			print "	<TD> &nbsp; </TD>"
			print "</TR>"
                        prev = $1;
                }
                if ( length( $2 ) > 0 )
                {
			# Print the sub-count
			print "<TR>"
			print "	<TD> &nbsp; </TD>"
			print "	<TD>" $2 "</TD>"
			print "	<TD> &nbsp; </TD>"
			print "	<TD> &nbsp; </TD>"
			print "	<TD align=right>" $5 "</TD>"
			print "	<TD align=right>" $6 "</TD>"
			print "</TR>"
                }
        }'

echo "</TABLE>";

# Show all the help-info
# Determine the available classes.
awk -F: '\
/^hlp_/		{
			hlp_used[ $0 ] = 1;
			next;
		}
/^hlp:/		{
			class=$0;
			sub( /::.*/, "", class );
			gsub( /[: 	\\]/, "_", class );
			if ( ! hlp_used[ class ] )
			{
				next;
			}

			if ( class != prev_class )
			{
				if ( length( prev_class ) )
				{
					print "</PRE>";
					# Some config files can be checked more than once.
					# Show the helpinfo only once to avoid double definition of NAME entry.
					hlp_used[ prev_class ] = 0;
				}
				prev_class=class;

				print "<HR>";
				printf( "<A NAME=\"%s\"></A>\n", class );

				printf( "<H4>%s", u );
				back="#cfg";
				for ( i = 2; length( $i ) > 0; i++ )
				{
					back=sprintf( "%s_%s", back, $i );
				}
				gsub( /[: 	\\]/, "_", back );
				printf( "<A HREF=\"%s\">Back</A>&nbsp;&nbsp;&nbsp;&nbsp;", back );
				printf( "%s", $2 );
				for ( i = 3; length( $i ) > 0; i++ )
				{
					printf( " - %s", $i );
				}
				print "</H4>";
				print "<PRE>"
			}

			# Ignore the classification.
			for ( i = 1; length( $i ) > 0; i++ )
			{ }
			i++;		# skip ::

			data=$i
			for ( i++; i <= NF; i++ )
			{
				data=sprintf( "%s:%s", data, $i );
			}
			print data;
		}
	END	{
			if ( length( prev_class ) )
			{
				print "</PRE>"
			}
		}' u="${TOP_URL}" ${HLP_USED} ${TMP_FILE}

echo "<HR>"
echo "<H4>${TOP_URL}<A NAME=legend>Legend</A></H4>"
echo "<P>"
echo "Fix data in the snapshot has a default color."
echo "Variable data in the snapshot has a specific <font color=${SCC_VAR_COLOR:-purple}>color</font>."
echo "</P>"

echo "<HR>"
echo "<P>Generated by SCC (&copy; <A HREF=http://www.OpenEyeT.nl>OpenEyeT Professional Services</A>) on $(date)</P>"

echo "</BODY>"
echo "</HTML>"

exit 0
