/* Copyright (C) 2003 Damir Zucic */

/*=============================================================================

				parse_pattern.c

Purpose:
	Parse the pattern. Pattern consists of residue name sets; each
	set contains a number of residue names.

Input:
	(1) Pointer to RuntimeS structure.
	(2) Pointer to the string which contains the pattern.

Output:
	(1) Sequence stored to the pattern buffer.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

Notes:
	(1) The pattern is expected in three letters code.  One letter
	    code may be  missinterpreted as  valid three letters code.
	    To each position a set of residues is assigned.  Use slash
	    to separate sets.

	(2) Space, comma, tab and semicolon may be used as separators.

========includes:============================================================*/

#include <stdio.h>

#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "commands.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

char		*ExtractToken_ (char *, int, char *, char *);

/*======parse pattern:=======================================================*/

int ParsePattern_ (RuntimeS *runtimeSP, char *stringP)
{
int		max_length, i;
char		*remaining_stringP;
char		tokenA[STRINGSIZE];
int		setI = 0;
int		residue_names_in_setN = 0;
int		global_residueI = 0;
char		*P;
char		*remaining_substringP;
char		subtokenA[SHORTSTRINGSIZE];

/* The maximal residue name length: */
max_length = RESNAMESIZE - 1;

/* Reset the pattern length: */
runtimeSP->pattern_length = 0;

/* Zero initialize the pattern buffer: */
for (i = 0; i < (int) runtimeSP->pattern_buffer_size; i++)
	{
	*(runtimeSP->patternP + i) = '\0';
	}

/* Reset the array with the number of residues per set: */
for (i = 0; i < MAX_PATT_LENGTH; i++)
	{
	runtimeSP->namesNA[i] = 0;
	}

/* Reset the total number of residues in pattern: */
runtimeSP->residues_in_patternN = 0;

/* Extract the tokens separated by slash, newline and */
/* end of line. These tokens are called residue sets. */
remaining_stringP = stringP;
while ((remaining_stringP = ExtractToken_ (tokenA, STRINGSIZE,
					   remaining_stringP, "/\n")) != NULL)
	{
	/* If this token contains wildcard, treat this set */
	/* as the set  which  contains  only  one element: */
	if (strstr (tokenA, "*") != NULL)
		{
		/* Copy the residue name to the pattern buffer: */
		P = runtimeSP->patternP + max_length * global_residueI;
		*P = '*';

		/* This set contains only one residue name: */
		runtimeSP->namesNA[setI] = 1;
		}

	/* Reset the local number of residue names in set: */
	residue_names_in_setN = 0;
	
	/* Parse the token to subtokens, separated by space, comma, */
	/* semicolon, tab, newline and end of line. These subtokens */
	/* should contain valid residue names (three letters code). */
	remaining_substringP = tokenA;
	while ((remaining_substringP = ExtractToken_ (subtokenA,
						      SHORTSTRINGSIZE,
						      remaining_substringP,
						      " ,;\t\n")) != NULL)
		{
		/* Check the residue name size: */
		if ((int) strlen (subtokenA) > max_length)
			{
			sprintf (runtimeSP->messageA,
				 "Residue name %s too long!",
				 subtokenA);
			runtimeSP->message_length =
					strlen (runtimeSP->messageA);
			return -1;
			}

		/* Copy the residue name to the pattern buffer: */
		P = runtimeSP->patternP + max_length * global_residueI;
		strcpy (P, subtokenA);

		/* Increment the local number of residue names in set: */
		residue_names_in_setN++;

		/* Do not allow too many residue names in this set: */
		if (residue_names_in_setN >= MAX_NAMES_IN_SET)
			{
			sprintf (runtimeSP->messageA,
				 "Too many residues in set!");
			runtimeSP->message_length = 
					strlen (runtimeSP->messageA);
			return -2;
			}

		/* Increment the global (cumulative) residue index: */
		global_residueI++;

		/* Do not allow array overflow: */
		if (global_residueI >= MAX_RES_IN_PATT)
			{
			sprintf (runtimeSP->messageA, "Too many residues!");
			runtimeSP->message_length =
					strlen (runtimeSP->messageA);
			return -3;
			}
		}

	/* Store the number of residues in this set: */
	runtimeSP->namesNA[setI] = residue_names_in_setN;

	/* Increment the residue set index: */
	setI++;

	/* Do not allow array overflow: */
	if (setI >= MAX_PATT_LENGTH)
		{
		sprintf (runtimeSP->messageA, "Pattern is too long!");
		runtimeSP->message_length = strlen (runtimeSP->messageA);
		return -4;
		}
	}

/* Store the total number of sets (the pattern length): */
runtimeSP->pattern_length = setI;

/* Store the total number of residues in pattern: */
runtimeSP->residues_in_patternN = global_residueI;

/* Return positive value on success: */
return 1;
}

/*===========================================================================*/


