#module    IdxParse    "1-001"
/*
 ***********************************************************************
 *                                                                     *
 * The software was developed at the Monsanto Company and is provided  *
 * "as-is".  Monsanto Company and the auther disclaim all warranties   *
 * on the software, including without limitation, all implied warran-  *
 * ties or merchantabilitiy and fitness.                               *
 *                                                                     *
 * This software does not contain any technical data or information    *
 * that is proprietary in nature.  It may be copied, modified, and     *
 * distributed on a non-profit basis and with the inclusion of this    *
 * notice.                                                             *
 *                                                                     *
 ***********************************************************************
 */

/*+
 * Module Name:	IdxParse
 *
 * Author:	R L Aurbach	CR&DS MIS Group    26-Apr-1986
 *
 * Function:
 *	Parse an input line produced by LaTeX \index command into a form usable
 *	for the generation of an automatic index.
 *
 * Modification History:
 *
 * Version     Initials	   Date		Description
 * ------------------------------------------------------------------------
 * 1-001	RLA	26-Apr-1986	Original Code
-*/

/*
 * Module IdxParse - Module-Wide Data Description Section
 *
 * Include Files:
 */
#include	    descrip
#include	    stdio
#include	    "IdxDef.H"

/*
 * Module Definitions:
 */
#define		    TRUE	1
#define		    FALSE	0

/*
 * Global Declarations:
 */

/*
 * Static Declarations:
 */
    static char	    *ptr;		/* pointer to token buffer	    */
    static int	    index;		/* index into token buffer	    */
    static int	    brace_ct;		/* brace counter		    */
    static int	    math_mode;		/* math mode flag		    */
    static int	    ignore;		/* ignore characters flag	    */
    static int	    item_parse;		/* parsing item-list flag	    */
    static int	    page_parse;		/* parsing page-no flag		    */

/*
 * External References:
 */

/*
 * Functions Called:
 */

/*+
 * Function Idx_Parse - Documentation Section
 *
 * Discussion:
 *	Parse an input line which is of the general form
 *	    \indexentry{token_1>token_2>token_3}{page_no}
 *	into tokens for "token_1", "token_2", "token_3", and "page_no".
 *	Handle missing tokens and allow for imbedded LaTeX commands.
 *
 * Calling Synopsis:
 *	Call Idx_Parse (linebf, token_1, token_2, token_3, page_no, token_ct)
 *
 * Inputs:
 *	linebf	    ->	is the input string containing the line to parse.  
 *			ASCIZ string passed by reference.
 *
 * Outputs:
 *	token_1	    ->	is the first token seen (if any).
 *			ASCIZ string passed by reference.
 *
 *	token_2	    ->	is the second token seen (if any).
 *			ASCIZ string passed by reference.
 *
 *	token_3	    ->	is the third token seen (if any).
 *			ASCIZ string passed by reference.
 *
 *	page_no	    ->	is the page number token (should always be present).
 *			ASCIZ string passed by refernce.
 *
 *	token_ct    ->	is the number of tokens seen.
 *			Integer passed by reference.
 *
 * Return Value:
 *	none
 *
 * Global Data:
 *	none
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	returns with the record processed.
 *
 * Error Conditions:
 *	none

 *
 * Algorithm:
 *	A. Initialize variables.
 *	B. Find the { at the end of \indexentry.
 *	C. Until end of line,
 *	    1. Switch on character:
 *		a. '{'
 *		    1. If last char was not '\', 
 *			A. increment brace counter.
 *		    2. If brace counter > 1, 
 *			A. insert character in current token.
 *		b. '}'
 *		    1. If last char was not '\', 
 *			A. decrement brace counter.
 *		    2. If brace counter > 1,
 *			A. insert character in current token.
 *		    3. Else,
 *			A. Close current token.
 *			B. If we are doing item tokens,
 *			    1. Switch to processing page-no token.
 *			C. Else,
 *			    1. Switch to ignoring characters.
 *		c. '$'
 *		    1. If last char was not '\',
 *			A. toggle math-mode flag.
 *		    2. Insert character in current token.
 *		d. '>'
 *		    1. If math-mode flag set,
 *			A. Insert character in current token.
 *		    2. Else,
 *			B. Close token and select next.
 *		e. Otherwise
 *		    1. Insert character in current token.
 *
 * Special Notes:
 *	This logic is designed to:
 *	    * copy sequences such as \{, \}, and $>$ from the input stream
 *	      into tokens without recognizing them as token delimiters.
 *	    * allow sequences such as {\bf text} in token without recognizing
 *	      the special characters as delimiters.
 *	    * allow up to three levels of index and one level of page-no,
 *	      ignoring all other characters (which shouldn't exist...)
-*/

/*
 * Function Idx_Parse - Code Section
 */

void	idx_parse (linebf, token_1, token_2, token_3, page_no, token_ct)

    char	*linebf;	    /* Input string to be parsed	*/
    char	*token_1;	    /* First token string		*/
    char	*token_2;	    /* Second token string		*/
    char	*token_3;	    /* Third token string		*/
    char	*page_no;	    /* Page number token string		*/
    int		*token_ct;	    /* Number of item tokens seen	*/
{
/*
 * Local Declarations
 */
    int		i;		    /* linebf counter			*/
    void	insert_character(); /* declare function			*/
/*
 * Module Body
 */

/* Initialize assorted variables, flags, etc.				*/

token_1[0] = '\0';
token_2[0] = '\0';
token_3[0] = '\0';
page_no[0] = '\0';
*token_ct  = 0;

i = 0;
ptr = 0;
index = 0;
brace_ct = 0;
math_mode = FALSE;
ignore = TRUE;
item_parse = FALSE;
page_parse = FALSE;

/* Now position the linebf index at the first character after "\indexentry" */

if (linebf[0] != '\\')				    return;
if (strncmp(&linebf[1], "indexentry{", 11) != 0)    return;

/* Loop through all of the characters on the line			    */

for (i = 11; linebf[i] != '\0'; i++)
    {
    switch (linebf[i])
	{
	case '{' :  if (ignore)
			{
			if (item_parse || page_parse)	break;
			else				ignore = FALSE;
			}
		    insert_character(linebf[i]);
		    if (linebf[i-1] != '\\')
			{
			brace_ct++;
			if (brace_ct == 1)
			    {
			    index = 0;
			    math_mode = FALSE;
			    if (!item_parse)
				{
				item_parse = TRUE;
				ptr = token_1;
				*token_ct = 1;
				break;
				}
			    if (!page_parse)
				{
				item_parse = FALSE;
				page_parse = TRUE;
				ptr = page_no;
				break;
				}
			    }
			}
		    break;

	case '}' :  if (ignore)	    break;
		    if (linebf[i-1] != '\\')	brace_ct--;
		    if (brace_ct == 0)
			{
			ptr[index] = '\0';
			if (page_parse)	    ignore = TRUE;
			}
		    insert_character(linebf[i]);
		    break;

	case '$' :  if (ignore)	    break;
		    if (math_mode)  math_mode = FALSE;
		    else	    math_mode = TRUE;
		    insert_character(linebf[i]);
		    break;

	case '>' :  if (ignore)	    break;
		    if (math_mode)  insert_character(linebf[i]);
		    else
			{
			if (index == 0)	break;
			ptr[index] = '\0';
			index = 0;
			switch (*token_ct)
			    {
			    case 1 :	ptr = token_2;  *token_ct = 2; break;
			    case 2 :	ptr = token_3;  *token_ct = 3; break;
			    }
			}
		    break;

	default :   if (!ignore)    insert_character(linebf[i]); break;
	}
    }
}

/*+
 * Function Insert_Character - Documentation Section
 *
 * Discussion:
 *	Conditionally insert the character into the current token buffer.
 *	The conditions for insertion are:
 *	    1. Ignore = FALSE.
 *	    2. Brace_Ct > 0;
 *	    3. Ptr != 0.
 *
 * Calling Synopsis:
 *	Call Insert_Character (ch)
 *
 * Inputs:
 *	ch	    ->	is the character to be inserted, passed by value.
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	none
 *
 * Global Data:
 *	Ptr	    ->	is the pointer to the token buffer where the character
 *			is insered.
 *	Index	    ->	is the array index into Ptr.  It is post-indexed.
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	none
 *
 * Error Conditions:
 *	none
 *
 * Algorithm:
 *	A. If the conditions (specified above) are met,
 *	    1. insert the character in the buffer.
 *	    2. increment the indexM.
 *
 * Special Notes:
 *	none
-*/

/*
 * Function Insert_Character - Code Section
 */

static void	insert_character (ch)

    char	ch;
{
/*
 * Local Declarations
 */

/*
 * Module Body
 */

if (!ignore && (brace_ct > 0) && (ptr != 0))
    ptr[index++] = ch;
}
