/* @(#)sb.c	1.6	2/10/93 */
/*******************************************************************************

This code was written and designed by 
Andrew Gene HALL of I.N. Services Pty. Ltd., Scarborough WA, Australia,
for the 
University of Western Australia, Crawley WA, Australia.

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

#include <stdio.h>
#include "utilitys.h"
#include "getopt.h"
#include "diagmesg.h"
#include "printsf.h"
#include "request_space.h"
#include "interpret.h"
#include "dictionary.h"

/* macros and constants */
#define FNAME_BUFFER_BLOCK 4

/* globals */
int		ARGc;	/* global version of argc */
char		**ARGv;	/* global version of argv */
Block_Seq	*beginning_of_BS = NULL;
Block_Seq	*input_sf = NULL;
Request_Seq	*requests = NULL;
Boolean         strip_stream = FALSE; /* CHANGE 17/6 */
int             line_max = 512 ; /* CHANGE 17/6 */

/* parser stuff */
extern FILE		*star_in;
extern int 		parse_star();
extern FILE		*request_in;

int	main(
int	argc,
char	*argv[])
{
/* agruement parsing variables */
/* char	ch;      CHANGE 9/3 */
int	ch;  /*  CHANGE 9/3 */
Boolean	errflag = FALSE;
FILE	*output_fp = stdout;
Block_Seq *	output_sf = NULL;
Boolean	there_are_dictionarys = FALSE;
char	**dict_file_buffer = NULL;
int	dict_file_count = -1;
int	Sizeof_dict_file_buffer = 0;
/* request control variables */
FILE *	tmp_request_fp = NULL;
char 	tmp_request_fname[L_tmpnam];
Boolean	filter_open = FALSE;
Boolean	there_are_requests = FALSE;
char	**reqfile_buffer = NULL;
int	reqfile_count = -1;
int	Sizeof_reqfile_buffer = 0;

   /* initialise the dictionary file buffer */
   if( !( dict_file_buffer = (char **)malloc( (Sizeof_dict_file_buffer += FNAME_BUFFER_BLOCK) * sizeof(char *)) ) )
      ERROR_MSG("Out of memory, for dict_file_buffer."); 
   /* initialise the request file buffer */
   if( !( reqfile_buffer = (char **)malloc( (Sizeof_reqfile_buffer += FNAME_BUFFER_BLOCK) * sizeof(char *)) ) )
      ERROR_MSG("Out of memory, for reqfile_buffer."); 

/* process command line options */
while(( ch = getopt( argc, argv, "d:e:fo:r:R:v:sl:")) != EOF)
   switch( ch ) {
   case 'd':
      Buffer_MSG( INFORM, "Data dictionary file is:");
      Buffer_MSG( INFORM, optarg);
      if( ++dict_file_count == Sizeof_dict_file_buffer )
         if( (dict_file_buffer = (char **)realloc( dict_file_buffer, 
             (Sizeof_dict_file_buffer += FNAME_BUFFER_BLOCK) * sizeof(char *))))
            dict_file_buffer[ dict_file_count ] = optarg;
         else 
            ERROR_MSG("Out of memory, for dict_file_buffer."); 
      else 
         dict_file_buffer[ dict_file_count ] = optarg;
      there_are_dictionarys = TRUE;
      break;

   case 'e':
      Buffer_MSG( INFORM, "All diagnostic messages are diverted to:");
      Buffer_MSG( INFORM, optarg);
      if((error_fp = fopen(optarg, "w")) == NULL) {
         error_fp = stderr;
         Buffer_MSG( ERROR, "Cannot open file for diagnostic messages:");
         Buffer_MSG( ERROR, optarg);
         exit(1);
      }
      break;

   case 'l':
      Buffer_MSG( INFORM, "Output line length set to : ");
      Buffer_MSG( INFORM, optarg);
      line_max = atoi(optarg);
      break;

   case 'f':
      Buffer_MSG( INFORM, "All Input is flushed through to output.");
      filter_open = TRUE;
      break;

   case 's':
      Buffer_MSG( INFORM, "Strip Request and Input Streams.");
      strip_stream = TRUE;
      break;

   case 'o':
      Buffer_MSG( INFORM, "Output is diverted to:");
      Buffer_MSG( INFORM, optarg);
      if((output_fp = fopen(optarg, "w")) == NULL) {
         output_fp = stdout;
         Buffer_MSG( ERROR, "Cannot open file for output:");
         Buffer_MSG( ERROR, optarg);
         exit(1);
      }
      break;

   case 'r':
      Buffer_MSG( INFORM, "Command line request:");
      Buffer_MSG( INFORM, optarg);
      if( ! tmp_request_fp )
        /* create a temporary request file */
        if( tmpnam(tmp_request_fname) ) {
           if((tmp_request_fp = fopen(tmp_request_fname, "w")) == NULL) {
              tmp_request_fp = NULL;
              Buffer_MSG( ERROR, "Cannot open temporary file for requests:");
              Buffer_MSG( ERROR, tmp_request_fname);
           }
           else
              if( ++reqfile_count == Sizeof_reqfile_buffer )
                 if( (reqfile_buffer = (char **)realloc( reqfile_buffer,
               (Sizeof_reqfile_buffer += FNAME_BUFFER_BLOCK) * sizeof(char *))))
                    reqfile_buffer[ reqfile_count ] = tmp_request_fname;
                 else 
                    ERROR_MSG("Out of memory, for reqfile_buffer."); 
              else 
                 reqfile_buffer[ reqfile_count ] = tmp_request_fname;
        }
        else
           Buffer_MSG( ERROR, "Could not create a unique temporary filename.");
      /* if the creation of the temp' file is unsuccessful then it got lost */
      fputs( optarg, tmp_request_fp );
      fputs( "\n", tmp_request_fp );
      there_are_requests = TRUE;
      break;

   case 'R':
      Buffer_MSG( INFORM, "Data request file is:");
      Buffer_MSG( INFORM, optarg);
      if( ++reqfile_count == Sizeof_reqfile_buffer )
         if( (reqfile_buffer = (char **)realloc( reqfile_buffer,
               (Sizeof_reqfile_buffer += FNAME_BUFFER_BLOCK) * sizeof(char *))))
            reqfile_buffer[ reqfile_count ] = optarg;
         else 
            ERROR_MSG("Out of memory, for reqfile_buffer."); 
      else 
         reqfile_buffer[ reqfile_count ] = optarg;
      there_are_requests = TRUE;
      break;

   case 'v':
      switch( optarg[0] ) {
      case 'n':
         if( (strcmp( optarg, "none") <= 0)) {
            Buffer_MSG( INFORM, "Switching Diagnostic reporting off.");
            current_level = NONE;
         } else {
            Buffer_MSG( ERROR, "Unknown argument to verbosity level:");
            Buffer_MSG( ERROR, optarg);
         }
         break;

      case 'e':
         if( (strcmp( optarg, "error") <= 0)) {
            Buffer_MSG( INFORM, "Reporting only Diagnostic Error messages.");
            current_level = ERROR;
         } else {
            Buffer_MSG( ERROR, "Unknown argument to verbosity level:");
            Buffer_MSG( ERROR, optarg);
         }
         break;

      case 'i':
         if( (strcmp( optarg, "inform") <= 0)) {
            Buffer_MSG( INFORM, "Reporting only Diagnostic Error and Inform messages.");
            current_level = INFORM;
         } else {
            Buffer_MSG( ERROR, "Unknown argument to verbosity level:");
            Buffer_MSG( ERROR, optarg);
         }
         break;

      case 'd':
         if( (strcmp( optarg, "debug") <= 0)) {
            Buffer_MSG( INFORM, "Reporting all Diagnostic messages.");
            current_level = DEBUG;
         } else {
            Buffer_MSG( ERROR, "Unknown argument to verbosity level:");
            Buffer_MSG( ERROR, optarg);
         }
         break;

      default:
         Buffer_MSG( ERROR, "Unknown argument to verbosity level:");
         Buffer_MSG( ERROR, optarg);
      }
      break;

   case '?':
      errflag = TRUE;
      break;

   default:
      Buffer_MSG( ERROR, "This option is not implemented yet:");
      { char buffer[3] = "-x"; buffer[1] = ch; Buffer_MSG( ERROR,  buffer ); }
      if( ! optarg ) { 
         Buffer_MSG( ERROR, "argument associated with option:");
         Buffer_MSG( ERROR, optarg);
      }
   }
/* tidy up the files */
if( tmp_request_fp ) fclose( tmp_request_fp );

/* flush the buffered messages */
Flush_MSG();

/* process any remaing arguments */
argc -= optind;
argv += optind;
{ int c = argc; char **v = argv;
if( c ) INFORM_MSG("Input files are :");
for( ; c-- > 0; ++v) INFORM_MSG(*v); 
}

/* handle the occurence of any errors */
if( errflag) {
   fprintf( stderr, "Usage: sb [-o output_file ] [-e error_file ] [-d dictionary_file ]\n");
   fprintf( stderr, "          [-r request ] [-R request_file ] [-v verbositiy_level ] [-f]\n");
   fprintf( stderr, "          [ input_file ... ]\n");
   exit(1);
}

/* redirect input from the command lines */
   if( argc ) {
      /* attempt to open the next file */
      if((star_in = fopen(*argv, "r")) == NULL) {
         /* error in opening the file */
         ERROR_MSG("Cannot open file for input:");
         ERROR_MSG(*argv);
      } else {
         /* input file opened successfully */
         INFORM_MSG("Input from:");
         INFORM_MSG(*argv);
         /* move pointers along */
         argc--; argv++;
      }
   }
   ARGc = argc; ARGv = argv;

   /* parse the input */
   if( parse_star() ) {
      ERROR_MSG("Could not parse the input.");
      exit(-1);
   }
   else {
      Boolean	valid_input = TRUE;

      input_sf = beginning_of_BS;
      if( there_are_dictionarys ) {
         /* parse and validate dictionary */
	 INFORM_MSG("Parsing the Dictionary.");
         ARGc = dict_file_count +1;
         ARGv = dict_file_buffer;
         beginning_of_BS = NULL;
         if( parse_star() ) {
            ERROR_MSG("Could not parse the dictionarys.");
            exit(-1);
         }
         else
            /* validate the input file against the dictionary */
            valid_input = dictionary_check( beginning_of_BS, input_sf );
         /* free up file space */
         free( dict_file_buffer );
         dict_file_count = -1;
         Sizeof_dict_file_buffer = 0;
      }
      if( valid_input )
        if( filter_open )
           output_sf = input_sf;
        else { if( there_are_requests ) {
           /* parse and perform requests */
           ARGc = reqfile_count +1;
           ARGv = reqfile_buffer;
           /* attempt to open the first file */
           if((request_in = fopen(*ARGv, "r")) == NULL) {
              /* error in opening the file */
              ERROR_MSG("Cannot open file for input:");
              ERROR_MSG(*ARGv);
           } else {
              /* input file opened successfully */
              INFORM_MSG("Input from:");
              INFORM_MSG(*ARGv);
              /* move pointers along */
              ARGc--; ARGv++;
           }
           if( parse_request() ) {
              ERROR_MSG("Could not parse the requests.");
              exit(-1);
           }
           else
              /* perform the requests */
              output_sf = requests_froma_RS( requests, input_sf, NULL,input_sf);
           /* free up file space */
           unlink( tmp_request_fname );
           free( reqfile_buffer );
           reqfile_count = -1;
           Sizeof_reqfile_buffer = 0;
        } }
      else
         ERROR_MSG("Input did not pass dictionary validation, no requests attempted.");
      
      /* write the output */
      fprint_Block_Seq(output_fp, output_sf);
   }
   exit(0);
}
