scc-snap2html(1)



NAME


	scc-snap2html - converts a SCC-snapshot to HTML-format

RELEASE


	scc	1.23.185

SYNOPSIS


	scc-snap2html [ -h|--help ] [ -s|--standalone ] <hostname>

DESCRIPTION


	This program reads a SCC-snapshot from stdin and converts it to 
	HTML-format on stdout. The hierarchical classification in the snapshot
	is converted to a hierarchical menu to the corresponding data. Refer to
	scc(4) for a detailed description of a SCC-snapshot.

	The resulting html-code only contains text and can be viewed with a 
	browser like lynx.

	The snapshot contains DIV-tags with the following nested classes:
	    - SCC_SNAP
	        - SCC_SNAP_NAV
	        - SCC_SNAP_MENU
	        - SCC_SNAP_ENTRY
	        - SCC_SNAP_STATS
	        - SCC_SNAP_HELP
	The sylesheet style.css in /var/opt/scc/data controls the markup.

OPTIONS


	-h|--help       Display the syntax and exit.
	-s|--standalone Embed the stylesheet in the html-data and do not
	                show "external" links to logbook and index.html.
	                Use this option before transferring the html
	                version of the snapshot to a user.

ARGUMENTS


	<name>		name of the host to convert the SCC-snapshot for

DIAGNOSTICS


	This program writes the following message to stderr:

	Syntax error, use: scc-snap2html [ -h|--help ] [ -s|--standalone ] <name>
	A syntax error was detected and reported.

	scc-snap2html: insufficient permissions to write in data directory: <data_dir>
	To run this program, log in as the owner of the directory.

RETURN VALUE


	Upon completion, the program returns one of the following values:

		0 successful completion
		1 Syntax error
		2 Runtime error

EXTERNAL INFLUENCES


	Use environment variable SCC_DATA to specify an alternative directory
	for the SCC data files. Should be an absolute path.

COPYRIGHT


	scc-snap2html is free software under the terms of the GNU General Public
	License. Copyright (C) 2001-2004 Open Challenge B.V.,
	2004-2005 OpenEyeT Professional Services, 2005-2015 QNH.

FILES


	/var/opt/scc/data/style.css - stylesheet for snapshot (and logbook)

SEE ALSO


	scc(1), scc-cmp(1), scc-collect(1), scc-log(1), scc-log2html(1),
	scc-plugin(1), scc-snap2html(1), scc(4), scc(5)

VERSION


	$Revision: 5917 $

)	;;
	echo "${ProgName}: alternative SCC_DATA (${SCC_DATA}) should be an absolute path" >&2
xit 2;;
ac

port TMPDIR=${SCC_TMP}
port TMP=${SCC_TMP}

port SHELL=/bin/sh

Perform the security settings before calling any program.
TH=/sbin:/usr/sbin:/usr/bin:/bin;	export PATH

ask 077

[ ! -w ${SCC_DATA} ]
en
cho "${ProgName}: insufficient permissions to write in data directory: ${SCC_DATA}" >&2
xit 2


${SCC_TMP}

D_LINE="${ProgName} [ -h|--help ] [ -s|--standalone ] <name>"
NTAX_ERROR="Syntax error, use: ${CMD_LINE}"

andalone=""
ile [ $# -gt 0 ]

ase "${1}" in
s|--standalone)	standalone="yes"
		shift 1;;
h|--help)		echo "${CMD_LINE}"
		exit 0;;
*)			echo "${SYNTAX_ERROR}" >&2
		exit 1;;
)			break;;
sac
ne

[ $# -ne 1 ]
en
cho "${SYNTAX_ERROR}" >&2
xit 1


${SCC_BIN}/scc_modules/scc_utils

-r ${SCC_CONF}/scc-localize ] && . ${SCC_CONF}/scc-localize

ndom="$(get_RANDOM)"
port TMP_FILE=${SCC_TMP}/scc_html_$$_${random}
port TMP_STATS=${SCC_TMP}/scc_tmp_stats_$$_${random}
port IND_FILE=${SCC_TMP}/scc_ind_$$_${random}
port HLP_CLASSES=${SCC_TMP}/scc_help_c_$$_${random}
port HLP_USED=${SCC_TMP}/scc_help_u_$$_${random}
port STAT_DATA=${SCC_TMP}/scc_stats_$$_${random}

ap 'rm -f ${TMP_FILE} ${TMP_STATS} ${IND_FILE} ${HLP_CLASSES} ${HLP_USED} ${STAT_DATA}' 0
ap "exit 2" 1 2 3 15

e_process_data()
{

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.
ed	-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'			|
wk '/^fix:|^var:|^hlp:|^stats:/	{ print; next }
				{ print "fix:unexpected data::" $0 }'
}

P_NAME="<A NAME=cfg_top></A>"
L_SEP="&nbsp;&nbsp;&nbsp;&nbsp;"
P_URL="<A HREF=\"#cfg_top\">Top</A>${URL_SEP}"

Generate the heading of the HTML file.
n_header()
{
cho '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
cho "<HTML lang=\"en\">"

cho "<HEAD>"
f [ -z "${standalone}" ]
hen
echo '<LINK HREF="style.css" REL="stylesheet" TYPE="text/css">'
lse
if [ -f "${SCC_DATA}/style.css" ]
then
	echo '<style TYPE="text/css">'
	cat "${SCC_DATA}/style.css"
	echo "</style>"
fi
i
cho "<TITLE>Configuration: ${1}</TITLE>"
cho "</HEAD>"

cho "<BODY>"
cho "<DIV class=SCC_SNAP>";
cho "${TOP_NAME}"
cho "<H1>"
cho "	Configuration: ${1}"
cho "</H1>"

cho "<DIV class=SCC_SNAP_NAV>";

DO NOT CHANGE THE FOLLOWING HTML-CODE WITHOUT CONSULTING scc.cgi IN scc-srv

cho "<H2>"
f [ -z "${standalone}" ]
hen
echo "	<A HREF=\"index.html\">Home</A>${URL_SEP}"
echo "	<A HREF=\"scc.${1}.log.html\">Logbook</A>${URL_SEP}"
i
f [ -s ${STAT_DATA} ]
hen
echo "	<A HREF=\"#statistics\">Statistics</A>${URL_SEP}"
i
cho "	<A HREF=\"#legend\">Legend</A>"
cho "</H2>"
cho "</DIV><!-- class=SCC_SNAP_NAV -->";
}

epare_help()
{

Get all the help classifications from the snap-shot.

ed	-n		\
-e 's/::.*//'	\
-e 's/\/_/g'	\
-e '/^hlp:/p' ${TMP_FILE} 2>/dev/null		|
ort -u >${HLP_CLASSES}
}

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

Generate the entire hierarchical menu from the classifications in the data
n_menu()
{
cho "<DIV class=SCC_SNAP_MENU>";

Get all the hierarchical classifications from the snap-shot.


Do not sort, we depend on the order of the collect-script.

rep "^[fv][ia][xr]:"			|
ed	-e 's/^var://'	\
-e 's/^fix://'	\
-e 's/::.*//'	\
-e 's/\/_/g'			|
wk -F: '{
# Make sure that each classification is treated once
if ( done[ $0 ] )
{
	next;
}
done[ $0 ] = 1;

# 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++ )
{
	if ( level == 1 )
	{
		prev_id = 11;
		class = $1;
	}
	else
	{
		prev_id = id[ class ];
		class = sprintf( "%s:%s", class, $level );
	}
	if ( ! id[ class ] )
	{
		# One line may cause several new submenus.
		id[ class ] = ( 10 * NR ) + level;

		# Use broad, fixed width numbers to enable usage of busybox sort to order the data.
		printf( "%03.3d:%010.10d:%010.10d:%s\n", level, prev_id, NR, class );
		
	}
}
' -				|
ort				|
wk -F: '/^hlp:/	{
			# Format of the data is:
			# hlp:<classification>::<data>
			class = $2;
			for ( i = 3; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
			{
				class = sprintf( "%s_%s", class, $i );
			}
			gsub( /[^A-Za-z0-9_.-]/, "_", class );		# W3C restrictions and no ":".
			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 "<H3>"

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

		print "	" u;			# Reference to TOP
		if ( help_avail[ url ] )
		{
			printf( "	<A HREF=\"#hlp_%s\" TITLE=\"%s\">Help</A>%s", url, url, s );
			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( /[^A-Za-z0-9_.-]/, "_", url );	# W3C restrictions and no ":".
			title = url;
			sub( "^cfg_", "", title );
			printf( "	<A HREF=\"#%s\" TITLE=\"%s\">%s</A> - \n", url, title, $i );
		}
		print "	" $i;

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

	url = $4;
	for ( i = 5; i <= NF; i++ )
	{
		url = sprintf( "%s_%s", url, $i );
	}
	gsub( /[^A-Za-z0-9_.-]/, "_", url );		# W3C restrictions and no ":".
	printf( "		<A HREF=\"#cfg_%s\" TITLE=\"%s\">%s</A><BR>\n", url, url, $NF );
}'				\
	s="${URL_SEP}"		\
	t="${HLP_USED}"		\
	u="${TOP_URL}"		\
		${HLP_CLASSES}	\
		-
cho "</DIV><!-- class=SCC_SNAP_MENU -->";
}

Generate all the data
n_data()
{
elp_classes="${1}"
ata="${2}"

cho "<DIV class=SCC_SNAP_ENTRY>";

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 "${help_classes}"

awk -F":" '/^fix:|^var:/	{
	# Get the classification, ignore the first part: fix/var.
	class = $2;
	for ( i = 3; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
	{
		class = sprintf( "%s - %s", class, $i );
	}
	if ( ! id[ class ] )
	{
		id[ class ] = NR;
		printf( "%010.10d:%010.10d:%s:%s", NR, 0, class, $2 );
		for ( i = 3; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
		{
			printf( ":%s", $i );
		}
		print "";
	}
	# Use broad, fixed width numbers to enable usage of busybox sort to order the data.
	printf( "%010.10d:%010.10d:%s\n", id[ class ], NR, $0 );
}' "${data}"			|
sort
						|
wk -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( "<H3>%s", u );

	# Check whether help-info is available.
	class="hlp";
	for ( i = 4; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
	{
		class=sprintf( "%s:%s", class, $i );
	}
	if ( help_avail[ class ] )
	{
		gsub( /[^A-Za-z0-9_.-]/, "_", class );		# W3C restrictions and no ":".
		title = class;
		sub( "^hlp_", "", title );
		printf( "<A HREF=\"#%s\" TITLE=\"%s\">Help</A>%s", class, title, s );
		print class >>t;
	}

	class=$4;
	for ( i = 5; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
	{
		class=sprintf( "%s_%s", class, $i );
	}
	gsub( /[^A-Za-z0-9_.-]/, "_", class );		# W3C restrictions and no ":".
	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; ( depth < NF ) && ( length( $(depth + 1) ) > 0 ); depth++ )
	{
		if (length( tag ) == 0 )
		{
			tag = $depth;
		}
		else
		{
			tag = sprintf( "%s_%s", tag, $depth );
		}
		gsub( /[^A-Za-z0-9_.-]/, "_", tag );	# W3C restrictions and no ":".
		printf( "%s<A HREF=\"#cfg_%s\" TITLE=\"%s\">%s</A>\n", sep, tag, tag, $depth );
		sep = " - ";
	}
	print "	" sep $depth;

	print "</H3>";
	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( "<span class=\"scc_var\">" );
	var_font_end="</span>"
}

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 );
	sub( /^[ 	]*/, "", $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; ( i <= NF ) && ( 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;

ND	{
	print "</PRE>"
}'	s="${URL_SEP}"			\
	t="${HLP_USED}"			\
	u="${TOP_URL}"			\
		-
cho "</DIV><!-- class=SCC_SNAP_ENTRY -->";
}

Show all the help-info
n_help()
{

Determine the available classes.

cho "<DIV class=SCC_SNAP_HELP>";

wk -F: '
^hlp_/		{
		hlp_used[ $0 ] = 1;
		next;
	}
^hlp:/		{
		class=$0;
		sub( /::.*/, "", class );
		gsub( /[^A-Za-z0-9_.-]/, "_", class );		# W3C restrictions and no ":".
		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( "<H3>%s", u );
			back="cfg";
			for ( i = 2; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
			{
				back=sprintf( "%s_%s", back, $i );
			}
			gsub( /[^A-Za-z0-9_.-]/, "_", back );		# W3C restrictions and no ":".
			title = back;
			sub( "^cfg_", "", title );
			printf( "<A HREF=\"#%s\" TITLE=\"%s\">Back</A>&nbsp;&nbsp;&nbsp;&nbsp;", back, title );
			printf( "%s", $2 );
			for ( i = 3; ( i <= NF ) && ( length( $i ) > 0 ); i++ )
			{
				printf( " - %s", $i );
			}
			print "</H3>";
			print "<PRE>"
		}

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

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

cho "</DIV><!-- class=SCC_SNAP_HELP -->";
}

Generate the legend and terminate the html file
n_trailer()
{
cho "<HR>"
cho "<H2>${TOP_URL}<A NAME=legend>Legend</A></H2>"
cho "<P>"
cho "Fix data in the snapshot has a default color."
cho "Variable data in the snapshot has a specific <span class=\"scc_var\">color</span>."
cho "</P>"

cho "<HR>"
cho "<P>Generated by SCC version 1.23.185 (&copy; <A HREF=\"http://www.qnh.eu\">QNH</A>) on $(date)</P>"

cho "</DIV><!-- class=SCC_SNAP -->";
cho "</BODY>"
cho "</HTML>"
}

Generate statistics from data in the snapshot.
n_stats()
{

Generate the statistics sub-menu with the Profiling and the Class counters.


cho "<DIV class=SCC_SNAP_STATS>";
cho "<HR>"
cho "<H3><A NAME=statistics>Statistics</A>${URL_SEP}"
cho "	${TOP_URL}"
cho "	<A HREF=\"#stats_profiling\">Profiling</A>${URL_SEP}"
cho "	<A HREF=\"#stats_classes\">Class counters</A>"
cho "</H3>"
cho "<HR>"

cho "<H4><A NAME=stats_profiling></A>Profiling${URL_SEP}${TOP_URL}<A HREF=\"#statistics\">Statistics</A></H4>"

Format of profiling data:

stats:profiling::<time>:<total_time>:<partial_time>:<module>:<label>
wk -F:	'/^stats:profiling::/	{
				if ( profiling_hdr == 0 )
				{
					class="Odd";
					print "<TABLE CLASS=SCC SUMMARY=\"Performance of SCC modules\" BORDER CELLSPACING=1 CELLPADDING=1>"
					print "<THEAD>";
					printf( "<TR class=%s>\n", class );
					print "	<TH>Time</TH>";
					print "	<TH>Total seconds</TH>";
					print "	<TH>Module seconds</TH>";
					print "	<TH>Module</TH>";
					print "	<TH>Label</TH>";
					print "</TR>";
					print "</THEAD>";
					print "<TBODY>";

					profiling_hdr = 1;
				}

				if ( class != "Odd" )
				{
					class = "Odd";
				}
				else
				{
					class = "Even";
				}
				printf( "<TR class=%s>\n", class );
				print "	<TD class=Odd>" $4 "</TD>";
				print "	<TD class=Even align=right>" $5 "</TD>";
				print "	<TD class=Odd align=right>" $6 "</TD>";
				print "	<TD class=Even>" $7 "</TD>";
				if ( length( $8 ) == 0 )
				{
					$8 = "&nbsp;";
				}
				print "	<TD class=Odd>" $8 "</TD>";
				print "</TR>";
				next;
			}
END	{
		if ( profiling_hdr > 0 )
		{
			print "</TBODY>";
			print "</TABLE>"
		}
	}' ${1}

cho "<H4><A NAME=stats_classes>Classes</A>${URL_SEP}${TOP_URL}<A HREF=\"#statistics\">Statistics</A></H4>"
cho "<P>Help-info is excluded from the fix/var and class counters.</P>"

Format of fix_var data:

stats:fix_var::<lavel>:<cnt>:<perc>
wk -F:	'/^stats:fix_var::/	{
				if ( profiling_hdr == 0 )
				{
					class="Odd";
					print "<TABLE CLASS=SCC SUMMARY=\"Counters for fix and var data\" BORDER CELLSPACING=1 CELLPADDING=1>"
					print "<THEAD>";
					printf( "<TR class=%s>\n", class );
					print "	<TH>Category</TH>";
					print "	<TH>Count</TH>";
					print "	<TH>Percentage</TH>";
					print "</TR>";
					print "</THEAD>";
					print "<TBODY>";

					profiling_hdr = 1;
				}

				if ( class != "Odd" )
				{
					class = "Odd";
				}
				else
				{
					class = "Even";
				}
				printf( "<TR class=%s>\n", class );
				print "	<TD class=Odd>" $4 "</TD>";
				print "	<TD class=Even align=right>" $5 "</TD>";
				print "	<TD class=Odd align=right>" $6 "</TD>";
				print "</TR>";
				next;
			}
END	{
		if ( profiling_hdr > 0 )
		{
			print "</TBODY>";
			print "</TABLE>"
		}
	}' ${1}

cho "<BR>"

Format of classes data:

stats:classes::<main>:<sub>:<main_cnt>:<main_perc>:<sub_cnt>:<sub_perc>
wk -F:	'/^stats:classes::/	{
				if ( profiling_hdr == 0 )
				{
					class="Odd";
					print "<TABLE CLASS=SCC SUMMARY=\"Counters for first two levels of classifications\" BORDER CELLSPACING=1 CELLPADDING=1>"
					print "<THEAD>";
					printf( "<TR class=%s>\n", class );
					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>";
					print "</THEAD>";
					print "<TBODY>";

					profiling_hdr = 1;
				}


				if ( $4 != prev_main )
				{
					if ( class != "Odd" )
					{
						class = "Odd";
					}
					else
					{
						class = "Even";
					}
					# display only main label, count and perc.
					main_url = $4;
					gsub( /[^A-Za-z0-9_.-]/, "_", main_url );		# W3C restrictions and no ":".
					printf( "<TR class=%s>\n", class );
					printf( "	<TD class=Odd><A HREF=\"#cfg_%s\" TITLE=\"%s\">%s</A></TD>\n", main_url, main_url, $4 );
					print   "	<TD class=Even> &nbsp; </TD>";
					print   "	<TD class=Odd align=right>" $6 "</TD>";
					print   "	<TD class=Even align=right>" $7 "</TD>";
					print   "	<TD class=Odd> &nbsp; </TD>";
					print   "	<TD class=Even> &nbsp; </TD>";
					print "</TR>";
					
					prev_main = $4;
				}
				if ( length( $5 ) > 0 )
				{
					if ( class != "Odd" )
					{
						class = "Odd";
					}
					else
					{
						class = "Even";
					}

					sub_url = sprintf( "%s_%s", prev_main, $5 );
					gsub( /[^A-Za-z0-9_.-]/, "_", sub_url );		# W3C restrictions and no ":".

					printf( "<TR class=%s>\n", class );
					print   "	<TD class=Odd> &nbsp; </TD>";
					printf( "	<TD class=Even><A HREF=\"#cfg_%s\" TITLE=\"%s\">%s</A></TD>\n", sub_url, sub_url, $5 );
					print   "	<TD class=Odd> &nbsp; </TD>";
					print   "	<TD class=Even> &nbsp; </TD>";
					print   "	<TD class=Odd align=right>" $8 "</TD>";
					print   "	<TD class=Even align=right>" $9 "</TD>";
					print "</TR>";
				}
				next;
			}
END	{
		if ( profiling_hdr > 0 )
		{
			print "</TBODY>";
			print "</TABLE>"
		}
	}' ${1}

cho "</DIV><!-- class=SCC_SNAP_STATS -->";
}

e_process_data		>${TMP_FILE}
ep "^stats:"	<${TMP_FILE}	>${STAT_DATA}
epare_help	<${TMP_FILE}	>${HLP_CLASSES}

Generate the entire HTML file:
(
en_header ${1}					# No input required
en_menu	<${TMP_FILE}			# also writes in ${HLP_USED}
en_data "${HLP_CLASSES}" "${TMP_FILE}"
f [ -s ${STAT_DATA} ]
hen
gen_stats ${STAT_DATA}
i
at ${HLP_USED} ${TMP_FILE} | gen_help
en_trailer					# No input required
)

it 0