/*		parse_query_string.c		Sep 04			*/
/*	Takes a command-line argument "formatted like a JGOFS QUERY_	*/
/*    STRING".  If no argument, uses the value of the QUERY_STRING	*/
/*    env var.								*/
/*	Uses query_string_routines to divide the argument into pieces.	*/
/*	Reassembles those pieces into a string designed to be processed	*/
/*    by a perl program (or other reg exp engine)			*/
/*	May return other strings, but in original version does not	*/

/*    Output:								*/
/*	If the output matches /^\s*\*\*\*\s*ERROR\s*\*\*\*/
/*    (*** ERROR *** at the start of the string, w/various spaces	*/
/*    allowed), there has been an error of some kind (presumably	*/
/*    there will be more text).  The process exit status will be	*/
/*    non-zero as well.							*/
/*	Otherwise, 2 logical fields are output, separated by a space.	*/
/*    The first field does not have any spaces.  The 2nd field may.	*/
/*	The second field is a list of strings returned by this program	*/
/*    In the original version, 1 string is returned by this program.	*/
/*    That string is a list of "QUERY_STRING arguments"			*/
/*	The first field is a list of separator characters that can be	*/
/*    used to split and subsplit the 2nd field.  The first character	*/
/*    of this field is used to separate the strings returned by this	*/
/*    program.  The second character of this field is used to separate	*/
/*    the "QUERY_STRING argument return string" into individual		*/
/*    "QUERY_STRING arguments".  Future implementations may add more	*/
/*    separation characters						*/

/*    Sample usage:							*/
/*	Step 1:  Get program output (example ignores error situations)	*/
/*		$output = `/wherever/parse_query_string`;		*/
/*	Step 2:  Get separators						*/
/*		($separators,$rest) = split (/ /,$output,2);    	*/
/*	    If $rest is not defined, there was no QUERY_STRING		*/
/*	Step 3:  ID separators						*/
/*		($parse_query_return_sep,$query_string_arg_sep,@seps) =	*/
/*			split //,$separators;				*/
/*	Step 4:  Get parse_query_string returns				*/
/*		($query_string_arg_list,@other_returns) =		*/
/*			split /$parse_query_return_sep/,$rest;		*/
/*	Step 5:  Get "QUERY_STRING arguments"				*/
/*		@query_string_args =					*/
/*		  split /$query_string_arg_sep/,$query_string_arg_list;	*/

#define PQS_VERSION "parse_query_string version 1.0  27 Mar 2008"

/*  27 Mar 08  v 1.0  WJS						*/
/*	Apparently this was never used after it was written in 2004,	*/
/*    judged by the compilation warnings just now (one of which was a	*/
/*    typo that would have resulted in an unsatis ref.  Fix those	*/

#include "core.h"

  /*  PQS = parse_query_string; QS - QUERY_STRING			*/
  /*  The space is documented above, so changing it would invalidate	*/
  /*    everything, (given that we haven't bothered to make the defns	*/
  /*    below available to a perl program)				*/
  /*  The comma is the "traditional" QS separator, but nothing should	*/
  /*    break if that gets changed.					*/
  /*  The exclamation point will only get used if this program returns	*/
  /*    "more stuff", so it's kind of a less-desirable separator	*/
  /*  Defined as 1 character strings for coding convenience		*/
#define PQS_SEPARATORS_RETURN_ARGS_SEPARATOR " "
#define PREFERRED_PQS_RETURN_ARGS_SEPARATOR "!"
#define PREFERRED_QS_SEPARATOR ","

char **split_query_string();
Logical add_id_to_err();	/*  from utils.c			*/

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

void err(s,t)
char *s,*t;
{
  char *new_s,*new_t;
  add_id_to_err(&new_s,&new_t,s,t,PQS_VERSION);
  printf (" *** ERROR *** %s %s",new_s,new_t);
  exit(ERROR_EXIT_STATUS);	/* Defined in core.h			*/
}

char *pqs_return_vers()
/*  Routine exists mostly to force .h file version string into this	*/
/*  module, but we could call it if we want.  Note string must not be	*/
/*  global or we'll have conflicts if another routine similarly		*/
/*  includes the version string						*/
{
  static char version[] = PQS_VERSION"/"COREH_VERSION;
  return version;
}

Logical search_qs(pieces,search_char)
char **pieces;
char search_char;
/*  Return TRUE if search_char is in any of pieces			*/
{
  char **ptrptr;

  ptrptr = pieces;
  while (*ptrptr != NULL) {
    if (strchr(*ptrptr,search_char) != NULL) return TRUE;
    ptrptr++;
  }
  return FALSE;
}


int main(argc,argv)
int argc;
char *argv[];
{
  char *string_to_parse;
  char **pieces_of_query_string;
  int npieces;

    /*  List of separators in order of preference (after the "preferred	*/
    /*  ones).  Add/rearrange/delete at will				*/
  char separators[] = ",/|_-!@#$%^&*\?:;";
  char *pqs_return_args_separator,*qs_separator;

  char *ptr,*sep_ptr;
  char **ptrptr;

  if (argc > 2) err("Too many arguments.  Max = 1","");
  else string_to_parse = (argc == 1) ? getenv("QUERY_STRING") : argv[1];

  if (string_to_parse == NULL) {/* No QUERY_STRING (or null argv[0]!)	*/
    printf ("/");		/* Any non-space will do		*/
    exit (0);
  }

    /*  Can't have space in separators...				*/
  while (  (ptr = strchr(separators,*PQS_SEPARATORS_RETURN_ARGS_SEPARATOR))
	       != NULL
	)
    strcpy (ptr,ptr+1);

  pieces_of_query_string = split_query_string(string_to_parse,&npieces);

  sep_ptr = separators;
  pqs_return_args_separator = PREFERRED_PQS_RETURN_ARGS_SEPARATOR;
  while (*pqs_return_args_separator != '\0') {
    if (search_qs(pieces_of_query_string,*pqs_return_args_separator))
      pqs_return_args_separator = sep_ptr++;
    else
	/*  Search other potential return strings if/when they arise	*/
      break;
  }
  if (*pqs_return_args_separator == '\0') 
    err ("Cannot find character that is not in output set.  Character list = ",
	 separators);

    /*  pqs_return_args_separator cannot be in anything returned by	*/
    /*  this program, so once it's ID'ed, remove it from the candidate	*/
    /*  list								*/
  while (  (ptr = strchr(separators,*pqs_return_args_separator))
	       != NULL
	)
    strcpy (ptr,ptr+1);


    /*  Find a character not in any of the query string pieces		*/
  sep_ptr = separators;
  qs_separator = PREFERRED_QS_SEPARATOR;
  while (*qs_separator != '\0') {
    if (search_qs(pieces_of_query_string,*qs_separator))
      qs_separator = sep_ptr++;
    else
      break;
  }
  if (*qs_separator == '\0') 
    err ("Cannot find character that is not in output set.  Character list = ",
	 separators);

    /*  Find a character not in the next return string.  Note that	*/
    /*  qs_separator can be used here, too.				*/

  printf("%c%c%c",*pqs_return_args_separator,
		  *qs_separator,
		  *PQS_SEPARATORS_RETURN_ARGS_SEPARATOR);

  ptrptr = pieces_of_query_string;
  while (*(ptrptr+1) != NULL) {
    printf ("%s%c",*ptrptr,*qs_separator);
    ptrptr++;
  }
  printf ("%s",*ptrptr);

    /*  If more stuff is to be returned, print				*/
    /*  *pqs_return_args_separator here, then go on			*/

  exit(0);
}
