/*	PPVL_report

Report on the PVL statements found in a file label.


Use:

	PPVL_report [-options] [<filename>]

	  -options:

	    -Help   - this help message.
	    -Report - report the PVL statement contents of the file.
	    -Count  - count the number of parameters in the file.
	    -Values - add value counts to the parameter count listing.
	    -Find <name> - find the named parameter.
	      if <name> is @<filename> get the parameter names from the file.


Description:

The input file is processed by the PPVL module to obtain an aggregate (The
Container) of all PVL parameters found the in the file header. Then the file is
checked for the presence of a PDS EOL label (a PVL label block that is not in
the file header), which is appended to the aggregate if present.

If the input file is not specified, stdin is read by default. Note: EOL
labels in a file read from a pipe currently can not be accessed.

With the -report option (the default if no options are specified), all of the
PVL parameters found in the file are listed using formal PVL syntax (which may
be different than the syntax of the file).

The -count option provides a listing of the name of each aggregate parameter
and the number of parameters contained within it. The -values option adds to
the -count listing (i.e. the -count option is included with the -values option;
the do not need to be both specified) the name of each parameter and the number
of values it contains. At the end of these listings the total number of
parameters, and also values for the -values option, in the file is listed.

The -find option lists all occurances of parameters that match (completely -
not a pattern match - but without regard to case) the specified name, along
with all of the parameter's values. If the parameter is an aggregate its entire
contents are listed. If the name is immediately preceeded by the '@' character,
then it is used as the name of a file containing a list of parameter names, one
per line, to find.

Note that parameter names may specified as the full path that includes all
parent parameters (aggregates) starting with the file aggregate ('/') with
slash ('/') characters separating each parent in the path leading to the
desired parameter. Parameter names, including parent paths, that are not
anchored to the file aggregate (with a leading slash) may occur in multiple
locations. Parameter names specified by the user may be anchored or not.
Parameter names in program listings are always anchored with all parents in the
path included.
 

Author:

Bradford Castalia                       Castalia@Arizona.edu
Senior Systems Analyst                  (520) 621-6946
Planetary Image Research Laboratory     (520) 621-4824
Department of Planetary Sciences        FAX: (520) 621-9628
University of Arizona                   Space Sciences Bldg.
1629 E. University Blvd.                Room 429
Tucson, Arizona  85721-0092

"Build an image in your mind, fit yourself into it."
	The log of Cyradis seeress of Kell.


SCCS ID: @(#)PPVL_report.c	1.7 10/04/00
*/
static char		*SCCS_ID = "@(#)PPVL_report.c	1.7 10/04/00";

/*******************************************************************************

Copyright (C) 2000  Bradford Castalia, University of Arizona

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 of the License, 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; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


Bradford Castalia                       Castalia@Arizona.edu
Senior Systems Analyst                  http://PIRL.LPL.Arizona.edu/~castalia
Planetary Image Research Laboratory     520-621-4824
Department of Planetary Sciences        FAX: 520-621-9628
University of Arizona                   Space Sciences Bldg.
1629 E. University Blvd.                Room 429
Tucson, Arizona  85721-0092

"Build an image in your mind, fit yourself into it."
    The Log of Cyradis, Seeress of Kell.

*******************************************************************************/


#include	<ctype.h>

#include	"PPVL.h"

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif


static int
	report_listing = FALSE,
	count_listing  = FALSE,
	count_values   = 2;

char
	*command_name,
	*find_name = NULL,
	line[1024];

static void
	print_path
		(
		PPVL_Parameter	*The_Aggregate,
		PPVL_Parameter	*The_Parameter
		);



main
	(
	int		arg_count,
	char	**arg
	)
{
PPVL_Parameter
	*The_Aggregate,
	*The_Parameter = NULL,
	*The_Parent,
	**parameter;
FILE
	*The_File;
char
	*filename = NULL;
unsigned long
	total_scanned;
int
	count,
	total_values = 0;


/*	Command line arguments:
*/
command_name = *arg;

for (count = 1;
	 count < arg_count;
	 count++)
	{
	if (*arg[count] == '-')
		{
		switch (*(arg[count] + 1))
			{
			case 'R':
			case 'r':
				report_listing = TRUE;
				break;

			case 'C':
			case 'c':
				count_listing = TRUE;
				break;

			case 'V':
			case 'v':
				count_listing |= count_values;
				break;

			case 'F':
			case 'f':
				if (++count < arg_count)
					{
					find_name = arg[count];
					break;
					}
				fprintf (stderr, "%s: Missing name to find.\n",
					command_name);
				goto usage;

			case 'H':
			case 'h':
			case 'U':
			case 'u':
			usage:
				fprintf (stderr,
"usage: %s [-options] [<filename>]\n\
	-options:\n\
	  -Help   - this help message.\n\
	  -Report - report the PVL statement contents of the file.\n\
	  -Count  - count the number of parameters in the file.\n\
	  -Values - add value counts to the parameter count listing.\n\
	  -Find <name> - find the named parameter.\n\
	    if <name> is @<filename> get the parameter names from the file.\n",
					command_name);
				exit (1);

			default:
				fprintf (stderr, "%s: Unknown option switch \"%s\"\n",
					command_name, arg[count]);
				goto usage;
			}
		}
	else
		filename = arg[count];
	}

if (! report_listing && ! count_listing && ! find_name)
	report_listing = TRUE;


if (filename)
	{
	if (! (The_File = fopen (filename, "r")))
		{
		perror (command_name);
		fprintf (stderr, "\tUnable to open %s\n", filename);
		exit (1);
		}
	}
else
	The_File = stdin;


if (! (The_Aggregate = PPVL_read_aggregate (The_File, 0, &total_scanned)))
	{
	fprintf (stderr, "PPVL_read_aggregate failed: %s\n",
		PPVL_ERROR_MESSAGE);
	fprintf (stderr, "\tAfter scanning %lu characters.\n",
		total_scanned);
	exit (1);
	}


if (filename)
	printf ("File: %s\n",
		filename);

if (PPVL_errno)
	{
	if (PPVL_errno == PPVL_ERROR_SIZED_RECORDS)
		fprintf (stderr, "The file contains sized (variable length) records.\n");
	else
		fprintf (stderr, "Warning: %s\n",
			PPVL_ERROR_MESSAGE);
	}


/*	Check for a special EOL label appendange.
*/
PPVL_get_PDS_EOL (The_File, The_Aggregate);


if (The_File != stdin)
	fclose (The_File);


/*	Complete PPVL report listing.
*/
if (report_listing)
	PPVL_write_parameter (The_Aggregate, stdout, 0);


/*	Parameter and value counts report.
*/
if (count_listing)
	{
	printf ("\n        Count - Parent/Parameter names\n\n");
	printf ("%6d param%c - /\n",
		count = PPVL_count_parameters (The_Aggregate),
		(count == 1) ? ' ' : 's');

	/*	Sequentially select each aggregate.
	*/
	The_Parameter = PPVL_SEARCH_FROM_THE_TOP;
	while (The_Parameter = PPVL_find_parameter
			(
			The_Aggregate,
			The_Parameter,
			PPVL_SELECT_CLASS,
			(PPVL_Object *)PPVL_CLASS_AGGREGATE,
			&The_Parent
			))
		{
		printf ("%6d param%c - ",
			count = PPVL_count_parameters (The_Parameter),
			(count == 1) ? ' ' : 's');
		print_path (The_Aggregate, The_Parameter);
		printf ("\n");

		if ((count_listing & count_values) && count)
			{
			for (parameter = The_Parameter->content.parameters;
				*parameter;
			 	 parameter++)
				{
				if (! PPVL_Class_Is_Aggregate ((*parameter)->classification))
					{
					printf ("%6d value%c | ",
						count = PPVL_count_all_values ((*parameter)->content.value),
						(count == 1) ? ' ' : 's');
					print_path (The_Aggregate, *parameter);
					printf ("\n");
					total_values += count;
					}
				}
			}
		}
	printf ("\nTotal parameters = %d\n",
		PPVL_count_all_parameters (The_Aggregate));
	if (count_listing & count_values)
		printf ("    Total values = %d\n",
			total_values);
	printf ("\n");
	}


if (find_name)
	{
	printf ("\n");
	if (*find_name == '@')
		{
		/*	Read parameter names from the specified file.
		*/
		filename = ++find_name;
		if (! (The_File = fopen (filename, "r")))
			{
			perror (command_name);
			fprintf (stderr, "\tUnable to open parameter profile - %s\n",
				filename);
			exit (1);
			}
		fprintf (stderr, "Using parameter profile - %s\n\n",
			filename);
		}
	else
		{
		The_File = NULL;
		goto Parameter_search;
		}

	while (fgets (find_name = line, sizeof (line), The_File))
		{
		line[strlen (line) - 1] = '\0';		/* remove NL */

		/*	Skip leading white space.
		*/
		while (*find_name && isspace (*find_name))
			find_name++;
		if (! *find_name || *find_name == '#')
			continue;

		Parameter_search:
	
		for (count = 0,
			 The_Parameter = PPVL_SEARCH_FROM_THE_TOP;
			 The_Parameter = PPVL_find_parameter
				(
				The_Aggregate,
				The_Parameter,
				PPVL_SELECT_NAME,
				find_name,
				&The_Parent
				);
			 count++)
			{
			/*	Print the entire parent hierarchy (parameter path)
				and the parameter with its values.
			*/
			print_path (The_Aggregate, The_Parent);
			if (The_Parent != The_Aggregate)
				printf ("/");
			PPVL_write_parameter (The_Parameter, stdout, 0);
			}
		if (! count)
			printf ("Couldn't find parameter \"%s\".\n",
				find_name);

		if (! The_File)
			break;
		}
	}

exit (0);
}


void
print_path
	(
	PPVL_Parameter	*The_Aggregate,
	PPVL_Parameter	*The_Parameter
	)
{
PPVL_Parameter
	*parameter = The_Parameter;
char
	*parent_list[128],
	**parent_name;

if (The_Parameter == The_Aggregate)
	printf ("/");
else
	{
	/*	Get the entire parent hierarchy (parameter path).
	*/
	for (parent_name = parent_list;
		 parameter != The_Aggregate;
		 PPVL_find_parameter
			(
			The_Aggregate,
			PPVL_SEARCH_FROM_THE_TOP,
			PPVL_SELECT_PARAMETER,
			parameter,
			&parameter
			))
		*parent_name++ = parameter->name;

	/*	Print the parameter path.
	*/
	while (--parent_name >= parent_list)
		printf ("/%s",
			*parent_name);
	}
}
