/* #module    GloBldLab    "2-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 of 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:	GloBldLab
 *
 * Author:	R L Aurbach	CR&DS MIS Group    18-Aug-1986
 *
 * Function:
 *	Build the list of labels seen in the input file.  Also, if a file
 *	entry is seen, add it to the filelist.
 *
 * Modification History:
 *
 * Version     Initials	   Date		Description
 * ------------------------------------------------------------------------
 * 1-001	RLA	18-Aug-1986	Original Code
 * 1-002	RLA	26-Aug-1986	Fix problem with duplicate label 
 *					  detection.
 * 2-001	F.H.	17-May-1991	converted to portable C
 */
/*
 * Module GloBldLab - Module-Wide Data Description Section
 *
 * Include Files:
 */
#ifdef MSDOS
#include <stdlib.h>
#include <io.h>
#define F_OK		0	/* access(): File exists	*/
#else
#include <sys/file.h>
/* extern char *sprintf(); */
#endif
/* #include <malloc.h> */
#include <string.h>
#include <stdio.h>
#include "GloDef.h"
/*
 * Module Definitions:
 */
/*
 * Global Declarations:
 */
#ifdef MSDOS
int Glo_Build_LabLst(void);
#else
int Glo_Build_LabLst();
#endif
/*
 * Static Declarations:
 */
/*
 * External References:
 */
extern char		    infile[256];
extern STRING_PTR	    labels;
extern STRING_PTR	    filelist;
/*
 * Functions Called:
 */
#ifdef MSDOS
static void	glo_get_token(char *buffer, char *token);
static int	glo_get_next_file(char *token, int *ptr, char *spec);
#else
static void	glo_get_token();
static int	glo_get_next_file();
#endif
/*
 * Function Glo_Build_LabLst - Documentation Section
 *
 * Discussion:
 *	Read the input file and use its contents to build a list of labels for
 *	which glossary entries are needed.  If a file specification is seen
 *	during this operation, add the file to the filelist.
 *
 * Calling Synopsis:
 *	status = Glo_Build_LabLst ()
 *
 * Inputs:
 *	none
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	status	    ->	is a status code for the operation.  It is a boolean
 *			integer, passed by value.  If TRUE, the routine 
 *			completed normally.  If FALSE, an error occurred.
 *
 * Global Data:
 *	labels	    ->	the list of labels is created by this routine.
 *
 *	filelist    ->	if one or more files are seen by the routine, they are
 *			added to the file list.
 *
 * Files Used:
 *	The input file is read.
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status = TRUE	normal successful completion.
 *
 * Error Conditions:
 *	status = FALSE	an error occurred.  The reason for the error is written
 *			to SYS$OUTPUT.
 *
 * Algorithm:
 *	A. Open the input file.
 *	B. For each record in the file,
 *	    1. If it is an \indexentry,
 *	       or If it is a \glossaryentry, (TeX 3.0)
 *		a. Parse out the label.
 *		b. If the label does not already appear in the label list,
 *		    1. Build a STRING to contain the label.
 *		    2. Chain it into the label list.
 *	    2. If it is a \glofile,
 *		a. For each file in the list,
 *		    1. Parse out the file specification.
 *		    2. Build a STRING to contain the file specification.
 *		    3. Chain it into the file list.
 *	    3. Else,
 *		a. Ignore the record.
 *	C. Close the input file.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Build_LabLst - Code Section
 */
int Glo_Build_LabLst ()
{
/*
 * Local Declarations
 */
  int		    status;
  FILE	            *file;
  char	            linebf[linesz];
  char              label[linesz];
  int		    found;
  STRING_PTR	    new;
  STRING_PTR	    old;
  char	            spec[linesz];
  int               ptr;
  char              fname[256];
/*
 * Module Body
 */
/* Open the input file */
  (void)sprintf(fname,"%s.glo",infile);
  if ((file = fopen(fname, "r")) == NULL) {
    (void)printf("Could not open the input file\n");
    return (FALSE);
  }
/* For each record in the file,	*/
  status = TRUE;
  while (fgets(linebf, linesz, file) != 0) {
/*
 * If the record begins with \indexentry (or \glossaryentry), then it is
 * a record containing a label.  Process the label by parsing it out,
 * checking for duplicates, and if unique, building a label list entry for it.
 */
    if ((strncmp(linebf, "\\indexentry{", 12)) == 0) {
      glo_get_token(&linebf[12], label);
      if (strlen(label) == 0) continue;
      old = labels;
      found = FALSE;
      while (old != 0) {
	if (strcmp(label,old->desc) == 0) found = TRUE;
	if (old->next == 0) break;
	old = old->next;
      }
      if (!found) {
	new = (STRING_PTR) malloc(sizeof(STRING));
	if (new == 0) continue;
	new->next = 0;
	new->desc=strdup(label);
	if (old == 0) labels = new;
	else old->next = new;
      }
    }
    else if ((strncmp(linebf, "\\glossaryentry{", 15)) == 0) {
      glo_get_token(&linebf[15], label);
      if (strlen(label) == 0) continue;
      old = labels;
      found = FALSE;
      while (old != 0) {
	if (strcmp(label,old->desc) == 0) found = TRUE;
	if (old->next == 0) break;
	old = old->next;
      }
      if (!found) {
	new = (STRING_PTR) malloc(sizeof(STRING));
	if (new == 0) continue;
	new->next = 0;
	new->desc=strdup(label);
	if (old == 0) labels = new;
	else old->next = new;
      }
    }
/*
 * If the record begins with \glofile, then it is a record containing one or
 * more glossary definition file specifications.  For each specification, parse
 * it out and build a file list entry for it.
 */
    else if ((strncmp(linebf, "\\glofile{", 9)) == 0) {
      glo_get_token(&linebf[9], label);
      if (strlen(label) == 0) continue;
      ptr = 0;
      while (glo_get_next_file(label, &ptr, spec) != 0) {
	new = (STRING_PTR) malloc(sizeof(STRING));
	if (new == 0) continue;
	new->next = 0;
	new->desc=strdup(spec);
	old = filelist;
	if (old == 0) filelist = new;
	else {
	  while (old->next != 0) old = old->next;
/*@@@		old->next = file;*/
	}
      }
    }
/*
 * If the record begins with anything else, ignore it.
 */
    else continue;
  }
  (void)fclose(file);
  return (status);
}

/*
 * Function Glo_Get_Token - Documentation Section
 *
 * Discussion:
 *	Parse a token from the command line.  The token begins at the first
 *	character position in the buffer and ends with a "}".
 *
 * Calling Synopsis:
 *	Call Glo_Get_Token (buffer, token)
 *
 * Inputs:
 *	buffer	    ->	is an ASCIZ string containing the token to be found.
 *
 * Outputs:
 *	token	    ->	is an ASCIZ string into which the token is copied.
 *
 * Return Value:
 *	none
 *
 * Global Data:
 *	none
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	The token is returned.  
 *
 * Error Conditions:
 *	none
 *
 * Algorithm:
 *	A. Locate the trailing "}" or end of string.
 *	B. Copy the substring starting at the beginning of the buffer to the
 *	   end found to the token. 
 *	C. Null terminate the string.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Get_Token - Code Section
 */
static void	glo_get_token (buffer, token)
char	    *buffer;
char	    *token;
{
/*
 * Local Declarations
 */
  int		    len;	    /* Length of the substring		    */
/*
 * Module Body
 */
  len = strcspn(buffer, "}");
  (void)strncpy(token, buffer, len);
  token[len] = '\0';
}

/*
 * Function Glo_Get_Next_File - Documentation Section
 *
 * Discussion:
 *	Parse the next file specification out of the token list.  Files are
 *	separated by commas.  Return the length of the specification.
 *
 * Calling Synopsis:
 *	length = Glo_Get_Next_File (token, ptr, spec)
 *
 * Inputs:
 *	token	    ->	is an ASCIZ string containing the list of files.
 *
 *	ptr	    ->	is an integer (passed by reference) which is the 
 *			starting index in the token string for the search.
 *
 * Outputs:
 *	spec	    ->	is an ASCIZ string containing the next file spec.
 *
 * Return Value:
 *	length	    ->	is the length of the spec string.  A value of 0 
 *			indicates that there is no file spec.
 *
 * Global Data:
 *	none
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	length != 0	spec contains a file spec.  ptr is updated to point
 *			to the starting place for the next search.
 *	length == 0	no spec was found.
 *
 * Error Conditions:
 *	none
 *
 * Algorithm:
 *	A. Find the next "," in the string.
 *	B. Copy the substring into the output variable.
 *	C. Adjust the pointer.
 *	D. Return the length of the string.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Get_Next_File - Code Section
 */
static int	glo_get_next_file (token, ptr, spec)
char	    *token;
int	    *ptr;
char	    *spec;
{
/*
 * Local Declarations
 */
  int	length;
/*
 * Module Body
 */
  length = strcspn (&token[*ptr], ",");
  if (length != 0) {
    (void)strncpy (spec, &token[*ptr], length);
    spec[length] = 0;
    (*ptr) += length;
    if (token[*ptr] == ',') (*ptr)++;
  }
  return (length);
}
