/* #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>
#ifndef AMIGA
extern char *sprintf();
#endif
#endif

#ifdef AMIGA
#include <stdlib.h>
#else
#include <malloc.h>
#endif

#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);
}
