// file: pfil_parse_1.cc
//
 
// isip include files
//
#include "param_file.h"
#include "param_file_constants.h"
#include <integral_constants.h>
#include <string.h>

// method: pre_parse_cc
//
// arguments:
//  char_1 buffer: (input/output) parameter file text
//
// return: length of the buffer in characters
//
// this method pre parses the buffer to remove comments, and excess
// whitespace, handle literal characters and quotation marks, and
// checks to make sure that there are no hanging quotation marks
//
int_4 Param_file::pre_parse_cc(char_1* buffer) {
  
  char_1* buff_p;
  char_1* fixed_buff_p;
  int_1 state = PFIL_STATE_NO_GPI;
  static char_1 white_space[] = PFIL_WHITESPACE_SET;
  
  // buff_p: the pointer to the original buffer that is read from
  // fixed_buff_p: the pointer that is writen to.
  //
  // note: we can both read at buff_p and write at fixed_buff_p
  //       since buff_p >= fixed_buff_p and we always read before
  //       we write
  //
  buff_p = buffer;
  fixed_buff_p = buffer;

  while ( ((int_4)buff_p - (int_4)buffer) < PFIL_MAX_BUFFER_SIZE) {
    
    // branch on state
    //
    //-------------------------------------------------------------------
    // state: no good previous input (initial state)
    //-------------------------------------------------------------------
    //
    if (state == PFIL_STATE_NO_GPI) {

      // branch on input
      //

      // input is whitespace, no change of state
      // no output
      //
      if ((strchr((char*)white_space, (char)*buff_p) != (char*)NULL)||
	       (*buff_p == PFIL_NULL_CHR)||
	       (*buff_p == PFIL_NEWLINE_CHR)) {
	
	// nothing is done here
	//
      }

      // input is the terminal character, null valid statement
      //
      else if (*buff_p == terminator_char_d) {
	return ISIP_FALSE;
      }

      // input is comment operator, go into ngpi comment state
      // no output
      //
      else if (*buff_p == comment_char_d) {
	state = PFIL_STATE_COMMENT_OP_NO_GPI;
      }
      // input is quote operator, go into quote state
      // output
      //
      else if (*buff_p == PFIL_QUOTE_CHR) {
	state = PFIL_STATE_QUOTE_OP;
      }
      // input is literal operator, go into literal state
      // no output
      //
      else if (*buff_p == PFIL_LITERAL_CHR) {
	state = PFIL_STATE_LITERAL_OP;
      }
      // else copy character directly, go into gpi state
      //
      else {
	*fixed_buff_p = *buff_p;
	fixed_buff_p++;
	state = PFIL_STATE_GPI;
      }
      // end of state NO_GPI
      //
    }
    
    //-------------------------------------------------------------------
    // state: comment operator in ngpi state
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_COMMENT_OP_NO_GPI) {
      
      // go back to no gpi state on newline, stay in this state
      // if not, no output in either case
      //
      if (*buff_p == PFIL_NEWLINE_CHR) {
	state = PFIL_STATE_NO_GPI;
      }
      
      // end of state comment op no gpi
      //
    }
    
    //-------------------------------------------------------------------
    // state: literal operator
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_LITERAL_OP) {

      // regardless of input,
      // output the character and go to gpi state, 
      //
      *fixed_buff_p = *buff_p;
      fixed_buff_p++;
      state = PFIL_STATE_GPI;

      // end of state literal op
      //
    }
    
    //-------------------------------------------------------------------
    // state: gpi
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_GPI) {
      
      // branch on input
      //
      
      // literal character, go into literal state, no output
      //
      if (*buff_p == PFIL_LITERAL_CHR) {
	state = PFIL_STATE_LITERAL_OP;
      }
      // quote character, go into quote state, output quote
      //
      else if (*buff_p == PFIL_QUOTE_CHR) {
	state = PFIL_STATE_QUOTE_OP;
      }

      // comment operator, go into gpi comment state, output space
      //
      else if (*buff_p == comment_char_d) {
	*fixed_buff_p = PFIL_SPACE_CHR;
	fixed_buff_p++;
	state = PFIL_STATE_COMMENT_OP_GPI;
      }
      // terminal character, output it, return the length of the buffer
      //
      else if (*buff_p == terminator_char_d) {
	int_4 length;
	*fixed_buff_p = terminator_char_d;
	fixed_buff_p++;
	*fixed_buff_p = PFIL_NULL_CHR;
	length = (int_4)fixed_buff_p - (int_4)buffer; 
	return length;
      }

      // whitespace character, go to gpi/lws state, output space
      //
      else if ((strchr((char*)white_space, (char)*buff_p) != (char*)NULL)||
	       (*buff_p == PFIL_NULL_CHR)||
	       (*buff_p == PFIL_NEWLINE_CHR)) { 
	*fixed_buff_p = PFIL_SPACE_CHR;
	fixed_buff_p++;
	state = PFIL_STATE_GPI_LWS;
      }
      // else copy character directly, no change in state
      //
      else{
	*fixed_buff_p = *buff_p;
	fixed_buff_p++;
      }
      // end of state
      //
    }
    
    //-------------------------------------------------------------------
    // state: quotation operator
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_QUOTE_OP) {
      
      // branch on input
      //
      
      // quote operator again, output it and go to gpi state
      //
      if (*buff_p == PFIL_QUOTE_CHR) {
	state = PFIL_STATE_GPI;
      }
      // literal operator, go into quote literal state, no output
      //
      else if (*buff_p == PFIL_LITERAL_CHR) {
	state = PFIL_STATE_LITERAL_OP_IN_QUOTE;
      }
      // else stay in this state copying characters over
      //
      else{
	*fixed_buff_p = *buff_p;
	fixed_buff_p++;
      }
      // end of state
      //
    }
    
    //-------------------------------------------------------------------
    // state: literal operator for inside a quote
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_LITERAL_OP_IN_QUOTE) {
      
      // regardless of input,
      // output the character and go back to quote state, 
      //
      *fixed_buff_p = *buff_p;
      fixed_buff_p++;
      state = PFIL_STATE_QUOTE_OP;
      
      // end of state literal op
      //
    }
    
    //-------------------------------------------------------------------
    // state: good previous input, last input whitespace
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_GPI_LWS) {
      
      // branch on input
      //
      
      // terminal character, trim last whitespace and return buffer
      // no output
      //
      if (*buff_p == terminator_char_d) {
	*(fixed_buff_p-1) = terminator_char_d;
	*fixed_buff_p = PFIL_NULL_CHR;
	return (int_4)fixed_buff_p - (int_4)buffer;
      }
      
      // comment operator, go to comment state, no output
      //
      else if (*buff_p == comment_char_d) {
	state = PFIL_STATE_COMMENT_OP_GPI;
      }

      // more whitespace, stay in this state, output nothing
      //
      else if ((strchr((char*)white_space, (char)*buff_p) != (char*)NULL)||
	       (*buff_p == PFIL_NULL_CHR)||
	       (*buff_p == PFIL_NEWLINE_CHR)) {
	// do nothing
	//
      }
      // quote character, go to quote state, output quote
      //
      else if (*buff_p == PFIL_QUOTE_CHR) {
	state = PFIL_STATE_QUOTE_OP;
      }

      // literal operator, go to literal op state, no output
      //
      else if (*buff_p == PFIL_LITERAL_CHR) {
	state = PFIL_STATE_LITERAL_OP;
      }
      // else output character, go back to gpi state
      //
      else {
	*fixed_buff_p=*buff_p;
	fixed_buff_p++;
	state=PFIL_STATE_GPI;
      }
      //end of state gpi_lws
      //
    }
    
    //-------------------------------------------------------------------
    // state: comment
    //-------------------------------------------------------------------
    //
    else if (state == PFIL_STATE_COMMENT_OP_GPI) {
      

      // go back to gpi lws state on newline, 
      // no output
      //
      if (*buff_p == PFIL_NEWLINE_CHR) {
	state = PFIL_STATE_GPI_LWS;
      }

      // terminal character, trim last whitespace and return buffer
      // no output
      else if (*buff_p == terminator_char_d) {
	*(fixed_buff_p-1) = terminator_char_d;
	*fixed_buff_p = PFIL_NULL_CHR;
	return (int_4)fixed_buff_p - (int_4)buffer;
      }
      
      // eat comment characters with no output and staying in this state
      //
      else {
	// do nothing
	//
      }
      // end of state comment
      //
    }
    // end of state listings, do the things done each state
    //
    
    // increment the input buffer
    //
    buff_p++;
    
    // end of state loop
    //
  }
  
  // the only successful ways to exit is through certain inputs
  // in certain terminal states, if the program exits this loop
  // ungracefully, there is something wrong, return 0 length for the buffer
  //
  
  return ISIP_FALSE;

}
