/*****
* miniparse.c : Example usage of XmHTML's HTML parser
*
* This file Version	$Revision$
*
* Creation date:		Thu Dec  4 20:19:37 GMT+0100 1997
* Last modification: 	$Date$
* By:					$Author$
* Current State:		$State$
*
* Author:				newt
* (C)Copyright 1995-1996 Ripley Software Development
* All Rights Reserved
*
* This file is part of the XmHTML Widget Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****/
/*****
* ChangeLog 
* $Log$
*****/ 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "miniparse.h"

/*** External Function Prototype Declarations ***/

/*** Public Variable Declarations ***/

/*** Private Datatype Declarations ****/

/*** Private Function Prototype Declarations ****/

/*** Private Variable Declarations ***/
static String output_file_prefix, input_file;
static int input_file_len, nloops;
static Boolean notext, write_files;
static struct timeval start_time;

static void
writeFiles(XmHTMLObject *output)
{
	if(!write_files)
		return;

	/* Parser output */
	ParserWriteOutputToFile(output, output_file_prefix, notext);

	/* html output for live testing with other browsers */
	ParserWriteHTMLOutputToFile(output, output_file_prefix, notext);
}

void
AutoCorrectCallback(int on_stack, int p_inserted, int p_removed)
{
	printf("-------------------\n");
	printf("AutoCorrect statistics:\n");
	printf("Elements left on stack : %i\n", on_stack);
	printf("Elements inserted : %i\n", p_inserted);
	printf("Elements ignored  : %i\n", p_removed);
	printf("-------------------\n");
}

Boolean
DocumentCallback(XmHTMLObject *output, Boolean html32, Boolean verified,
	Boolean balanced, int loop_count, int text_len)
{
	/* print some parser statistics */
	printf("-------------------\n");
	printf("Statistics for pass %i:\n", loop_count+1);
	printf("\tinput file     : %s\n", input_file);
	printf("\tinput size     : %i\n", input_file_len);
	printf("\tBytes parsed   : %i\n", text_len);
	printf("\tHTML elements  : %i\n", parsed_object_count);
	printf("\ttext elements  : %i\n", parsed_text_object_count);
	printf("\tTotal elements : %i\n",
		parsed_object_count + parsed_text_object_count);
	printf("\tErrors found   : %i\n", parser_errors);

	printf("\tHTML3.2 conform: %s\n", html32 ? "Yes" : "No");
	printf("\tverified       : %s\n", verified ? "Yes" : "No");
	printf("\tbalanced       : %s\n", balanced ? "Yes" : "No");

	/* end time */
	if(parser_verification_timings)
	{
		int secs, usecs;
		struct timeval end_time;

		gettimeofday(&end_time, NULL);
		secs = (int)(end_time.tv_sec - start_time.tv_sec);
		usecs = (int)(end_time.tv_usec - start_time.tv_usec);
		if(usecs < 0) usecs *= -1;
		printf("\tProcessing time: %i.%i seconds\n", secs, usecs);
	}
	printf("-------------------\n");
	fflush(stdout);

	writeFiles(output);

	if(!balanced && loop_count < nloops)
	{
		/* set new start time */
		if(parser_verification_timings)
			gettimeofday(&start_time, NULL);

		/* make another pass */
		return(True);
	}
	return(False);
}


static void
usage(String progname)
{
	printf("Usage: %s <html-doc> [options]\n", progname);

	printf("\nOptions:\n"
	"-debug          : show debug information (mostly parser states).\n"
	"-notext         : only output HTML tags in output file.\n"
	"-nowarn         : disable bad HTML warnings.\n"
	"-nowrite        : don't generate any output files.\n"
	"-nostrict       : loosen HTML 3.2 checking.\n"
	"-notimings      : don't do timings.\n"
	"-nloop [number] : maximum number of parser passes. Default is 5.\n"
	"\nOutput file prefix is name of input file (paths stripped).\n");

	exit(EXIT_FAILURE);
}


int
main(int argc, char **argv)
{
	FILE *fp;
	int i, j;
	char *buffer;
	XmHTMLObject *output;

	if(argc == 1)
		usage(argv[0]);

	/* default settings */
	notext			= False;
	write_files		= True;
	parser_warnings	= True;
	parser_strict_checking = True;
	parser_debug	= False;
	parser_verification_timings = True;
	nloops = 5;

	for(i = 1; i < argc; i++)
	{
		if(argv[i][0] == '-')
		{
			switch(argv[i][1])
			{
				case 'n':
					if(!strcmp(argv[i], "-notext"))
						notext = True;
					else if(!strcmp(argv[i], "-nowarn"))
						parser_warnings = False;
					else if(!strcmp(argv[i], "-nowrite"))
						write_files = False;
					else if(!strcmp(argv[i], "-nostrict"))
						parser_strict_checking = False;
					else if(!strcmp(argv[i], "-notimings"))
						parser_verification_timings = False;
					else if(!strcmp(argv[i], "-nloop"))
					{
						if(i+1 == argc || argv[i+1][0] == '-')
						{
							fprintf(stderr, "bad or missing arg for -nloop.\n");
							usage(argv[0]);
						}
						nloops = atoi(argv[i+1]);
						i++;
					}
					else
					{
						fprintf(stderr, "unknown flag %s\n", argv[i]);
						usage(argv[0]);
					}
					break;
				case 'd':
					if(!strcmp(argv[i], "-debug"))
						parser_debug = True;
					else
					{
						fprintf(stderr, "Unknown flag %s\n", argv[0]);
						usage(argv[0]);
					}
					break;
				default:
					fprintf(stderr, "Unknown flag %s\n", argv[0]);
					usage(argv[0]);
					break;
			}
		}
		else
			input_file = argv[i];
	}
	if(input_file == NULL)
	{
		fprintf(stderr, "HTMLparse: no file given\n");
		exit(EXIT_FAILURE);
	}

	/* get proper output file prefix */
	/* first walk to last slash */
	for(i = strlen(input_file)-1; i && input_file[i] != '/'; i--);
	if(i)
		i++;
	j = 0;
	for(; i != strlen(input_file) && input_file[i] != '.'; i++, j++);
	{
		output_file_prefix = strdup(&input_file[i - j]);
		output_file_prefix[j] = '\0';
	}

	if((fp = fopen(input_file, "r")) == NULL)
	{
		perror(input_file);
		exit(EXIT_FAILURE);
	}

	fseek(fp, 0, SEEK_END);
	input_file_len = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	if((buffer = (char*)malloc(input_file_len+1)) == NULL)
	{
		fprintf(stderr, "Fatal: malloc failed for %i bytes.\n", input_file_len);
		fclose(fp);
		exit(EXIT_FAILURE);
	}
	/* read it */
	if((i = fread(buffer, 1, input_file_len, fp)) != input_file_len)
		fprintf(stderr, "Warning: did not read entire file (read %i while "
			"%i should have been read.\n", i, input_file_len); 

	/* NULL terminate!! */
	buffer[input_file_len] = '\0';

	/* close it */
	fclose(fp);

	/* set start time */
	if(parser_verification_timings)
		gettimeofday(&start_time, NULL);

	/* set external callbacks */
	parser_document_callback = DocumentCallback;
	parser_autocorrect_callback = AutoCorrectCallback;

	/* Parse input text */
	output = _XmHTMLparseHTML(input_file, NULL, buffer, NULL);

	/* free buffer */
	free(buffer);

	/* Free the list */
	if(parser_verification_timings)
		gettimeofday(&start_time, NULL);

	_XmHTMLFreeObjects(output);

	if(parser_verification_timings)
	{
		struct timeval end_time;
		int secs, usecs;

		gettimeofday(&end_time, NULL);
		secs = (int)(end_time.tv_sec - start_time.tv_sec);
		usecs = (int)(end_time.tv_usec - start_time.tv_usec);
		if(usecs < 0) usecs *= -1;

		printf("-------------------\n");
		printf("_XmHTMLFreeObjects done in %i.%i seconds\n", secs, usecs);
		printf("-------------------\n");
		fflush(stdout);
	}
	return(EXIT_SUCCESS);
}
