765 lines
21 KiB
C
765 lines
21 KiB
C
/*
|
||
* CDE - Common Desktop Environment
|
||
*
|
||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||
*
|
||
* These libraries and programs are free software; you can
|
||
* redistribute them and/or modify them under the terms of the GNU
|
||
* Lesser General Public License as published by the Free Software
|
||
* Foundation; either version 2 of the License, or (at your option)
|
||
* any later version.
|
||
*
|
||
* These libraries and programs are distributed in the hope that
|
||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
* PURPOSE. See the GNU Lesser General Public License for more
|
||
* details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with these libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/* $XConsortium: Volumegen.c /main/4 1995/11/08 11:48:17 rswiston $ */
|
||
/************************************<+>*************************************
|
||
****************************************************************************
|
||
*
|
||
* File: Volumegen.c
|
||
*
|
||
* Project: Cache Creek (Rivers) Project
|
||
* Description: Source for the 'volumegen' portion of HelpTAG.
|
||
* Author: Brian Cripe
|
||
* Modifications by Mike Wilson
|
||
* Modifications to support non-topic IDs added by Dex Smith
|
||
* Language: C
|
||
*
|
||
* (C) Copyright 1992, Hewlett-Packard, all rights reserved.
|
||
*
|
||
****************************************************************************
|
||
************************************<+>*************************************/
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <fcntl.h>
|
||
#include <string.h>
|
||
#include <locale.h>
|
||
|
||
/* Local Includes */
|
||
#include "PstackI.h"
|
||
|
||
#define TRUE 1
|
||
#define FALSE 0
|
||
|
||
typedef int Boolean;
|
||
|
||
/* extern int errno; */
|
||
/* extern int sys_nerr; */
|
||
|
||
static void GenTopicList (
|
||
FILE *infile,
|
||
FILE *outfile);
|
||
|
||
static void GenTopicHeir(
|
||
FILE *infile,
|
||
FILE *outfile);
|
||
|
||
static void GenTopicLoc(
|
||
FILE *infile,
|
||
FILE *outfile);
|
||
|
||
static void GenHomeLocation(
|
||
FILE *outfile);
|
||
|
||
static void GenKeyWordList(
|
||
FILE *infile,
|
||
FILE *outfile);
|
||
|
||
static void MergeMetaInfo(
|
||
FILE *infile,
|
||
FILE *outfile);
|
||
|
||
static char *GetNextToken(
|
||
FILE *file,
|
||
Boolean delimIsSpace);
|
||
|
||
|
||
|
||
/* Volumegen Input file suffixes */
|
||
|
||
#define HEIR_FILE_SUFFIX ".tpc" /* The input filename suffix used for topic */
|
||
/* hierarchy files. */
|
||
#define TLOC_FILE_SUFFIX ".idt" /* The input filename suffix used for topic */
|
||
/* location files. */
|
||
|
||
#define IKEY_FILE_SUFFIX ".idx" /* The input filename suffix used for sorted*/
|
||
/* keyword file. */
|
||
#define IMETA_FILE_SUFFIX ".hmi" /* The input filename suffix used for meta */
|
||
/* information file. */
|
||
|
||
|
||
|
||
/* Volumegen Output file suffixes */
|
||
|
||
|
||
#define VOL_FILE_SUFFIX ".hv" /* The filename suffix used for volume */
|
||
/* file generated by volumegen. */
|
||
|
||
#define KEY_FILE_SUFFIX ".hvk" /* The filename suffix used for keyword */
|
||
/* file generated by volumegen. */
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: void main();
|
||
*
|
||
*
|
||
* Purpose: Program Main line body
|
||
*
|
||
*****************************************************************************/
|
||
void main (
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *fName;
|
||
FILE *tlocFile, *heirFile, *keyFile, *metaFile;
|
||
FILE *volFile, *keyWordFile;
|
||
|
||
setlocale(LC_ALL, "");
|
||
|
||
/* Make sure that an argument naming the volume was supplied. */
|
||
if (argc < 2) {
|
||
fprintf (stderr, "usage: %s <volume-name>\n", *argv);
|
||
exit (1);
|
||
}
|
||
|
||
/* Construct the name of the hierarchy file and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (HEIR_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, HEIR_FILE_SUFFIX);
|
||
if ((heirFile = fopen (fName, "r")) == NULL) {
|
||
fprintf (stderr,
|
||
"%s: error opening hierarchy file %s for reading\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
/* Construct the name of the topic location file and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (TLOC_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, TLOC_FILE_SUFFIX);
|
||
if ((tlocFile = fopen (fName, "r")) == NULL) {
|
||
fprintf (stderr,
|
||
"%s: error opening topic location file %s for reading\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
/* Construct the name of the keyword file and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (IKEY_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, IKEY_FILE_SUFFIX);
|
||
if ((keyFile = fopen (fName, "r")) == NULL) {
|
||
fprintf (stderr,
|
||
"%s: error opening keyword file %s for reading\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
|
||
/* Construct the name of the meta information file and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (IMETA_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, IMETA_FILE_SUFFIX);
|
||
if ((metaFile = fopen(fName, "r")) == NULL) {
|
||
fprintf (stderr,
|
||
"%s: error opening meta file %s for reading\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
|
||
/* Construct the name of the volume file (the one we are creating)
|
||
and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (VOL_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, VOL_FILE_SUFFIX);
|
||
if ((volFile = fopen (fName, "w")) == NULL) {
|
||
fprintf (stderr, "%s: error opening Volume file %s for writing\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
/* Construct the name of the keyword file (the one we are creating)
|
||
and open it. */
|
||
fName = malloc (strlen (*(argv+1)) + strlen (KEY_FILE_SUFFIX) + 1);
|
||
strcpy (fName, *(argv+1));
|
||
strcat (fName, KEY_FILE_SUFFIX);
|
||
if ((keyWordFile = fopen (fName, "w")) == NULL) {
|
||
fprintf (stderr, "%s: error opening Keyword file %s for writing\n",
|
||
*argv, fName);
|
||
perror (NULL);
|
||
exit (1);
|
||
}
|
||
|
||
|
||
/* Generate topic list and hierarchy */
|
||
GenTopicList (heirFile, volFile);
|
||
GenTopicHeir (heirFile, volFile);
|
||
|
||
/* Generate topic location table. */
|
||
GenTopicLoc(tlocFile, volFile);
|
||
|
||
|
||
/* Generate the keyword information */
|
||
GenKeyWordList(keyFile, keyWordFile);
|
||
|
||
|
||
/* Merge the Meta information */
|
||
MergeMetaInfo(metaFile, volFile);
|
||
|
||
/* Generate the Home Topic entry */
|
||
GenHomeLocation(volFile);
|
||
|
||
exit(0);
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void GenTopicList(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Generates the topic list in the <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void GenTopicList (
|
||
FILE *infile,
|
||
FILE *outfile)
|
||
{
|
||
char *token;
|
||
|
||
fseek (infile, 0, SEEK_SET);
|
||
|
||
fprintf (outfile, "# Topic List\n");
|
||
|
||
/* The output formatting is kind of tricky as we want to end every
|
||
line with a "\", except for the last line. Therefore each time
|
||
through the loop we print the "\\\n" for the previous line and
|
||
the body of the current line. */
|
||
fprintf (outfile, "*.topicList: ");
|
||
while ((token = GetNextToken (infile, TRUE)) != NULL) {
|
||
|
||
if ((strcmp (token, "{") != 0) && (strcmp (token, "}") != 0))
|
||
fprintf (outfile, "\\\n\t%s ", token);
|
||
|
||
free (token);
|
||
}
|
||
|
||
fprintf (outfile, "\n\n");
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void GenTopicHeir(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Generates the topic hierarchy in the <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void GenTopicHeir(
|
||
FILE *infile,
|
||
FILE *outfile)
|
||
{
|
||
char *token, *prevToken, *tempS;
|
||
|
||
PStack topicStack;
|
||
|
||
topicStack = PStackCreate();
|
||
fseek (infile, 0, SEEK_SET);
|
||
|
||
fprintf (outfile, "# Topic Hierarchy\n");
|
||
prevToken = NULL;
|
||
while ((token = GetNextToken (infile, TRUE)) != NULL) {
|
||
|
||
if (strcmp (token, "{") == 0)
|
||
PStackPush (topicStack, prevToken);
|
||
|
||
else if (strcmp (token, "}") == 0) {
|
||
if (prevToken != NULL)
|
||
free (prevToken);
|
||
|
||
free (PStackPop (topicStack));
|
||
}
|
||
|
||
else {
|
||
tempS = (char *) PStackPeek (topicStack);
|
||
if (tempS == NULL) {
|
||
tempS = "";
|
||
}
|
||
fprintf (outfile, "*.%s.parent:\t%s\n", token, tempS);
|
||
|
||
if (prevToken != NULL)
|
||
free (prevToken);
|
||
}
|
||
|
||
prevToken = token;
|
||
}
|
||
PStackDestroy (topicStack);
|
||
fprintf (outfile, "\n");
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void GenTopicLoc(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Generates the topic Location section in the
|
||
* <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void GenTopicLoc(
|
||
FILE *infile,
|
||
FILE *outfile)
|
||
{
|
||
char *topic, *topicFile, *topicPos;
|
||
|
||
char *trueTopicID = NULL;
|
||
char *locationIdNew = NULL;
|
||
char *idList = NULL;
|
||
|
||
fseek (infile, 0, SEEK_SET);
|
||
|
||
fprintf (outfile,
|
||
"# Topic Locations (file names, file positions, and non-topic IDs)\n");
|
||
|
||
/* Topic location files have a strict syntax where each line contains
|
||
either three tokens (the topic ID, the file containing the topic,
|
||
and the byte offset to the start of the topic), or two tokens (the
|
||
topic ID and a non-topic ID that occurs within the topic). The
|
||
first style (three tokens) is identified by the trailing ":" on the
|
||
topic ID. Similarly, the second style (two tokens) is identified by
|
||
the trailing ">" on the topic ID. If the file deviates from these
|
||
two variations of the syntax, the file is considered corrupt. */
|
||
|
||
while (1) {
|
||
if ((topic = GetNextToken (infile, TRUE)) == NULL)
|
||
break;
|
||
|
||
/* If the topic ID ends with ":", then we've found a primary entry. */
|
||
if (*(topic + strlen (topic) - 1) == ':')
|
||
{
|
||
/* Strip the ":" at the end of the topic ID */
|
||
*(topic + strlen (topic) - 1) = '\0';
|
||
|
||
/* if there was a previous trueTopicID, print it out */
|
||
if (trueTopicID != (char *)NULL && idList != (char *)NULL)
|
||
{
|
||
fprintf(outfile, "*.%s.locationIDs:\t%s\n",
|
||
trueTopicID, idList);
|
||
free (trueTopicID);
|
||
free (idList);
|
||
idList = (char *)NULL;
|
||
}
|
||
|
||
/* Save the new true topic. */
|
||
trueTopicID = malloc(strlen(topic) + 1);
|
||
strcpy(trueTopicID, topic);
|
||
|
||
if ((topicFile = GetNextToken (infile, TRUE)) == NULL)
|
||
break;
|
||
|
||
if ((topicPos = GetNextToken (infile, TRUE)) == NULL)
|
||
break;
|
||
|
||
fprintf (outfile, "*.%s.filename:\t%s\n", topic, topicFile);
|
||
fprintf (outfile, "*.%s.filepos:\t%s\n", topic, topicPos);
|
||
|
||
free (topicFile);
|
||
free (topicPos);
|
||
}
|
||
/* Else, if the id ends with ">", we've found a non-topic entry. */
|
||
else if (*(topic + strlen (topic) - 1) == '>')
|
||
{
|
||
/* Get the next token, its the non-topic ID. */
|
||
if ((locationIdNew = GetNextToken (infile, TRUE)) == NULL)
|
||
break;
|
||
|
||
/* If the ID list hasn't been started for this topic, start it. */
|
||
if (idList == (char *)NULL)
|
||
{
|
||
idList = malloc(strlen(locationIdNew) + 1);
|
||
strcpy(idList, locationIdNew);
|
||
}
|
||
/* Else, add the ID we've just found to the list. */
|
||
else
|
||
{
|
||
/* append the non-topic location ID to the list */
|
||
idList =
|
||
realloc(idList, strlen(idList) + strlen(locationIdNew) +2);
|
||
|
||
strcat(idList, " ");
|
||
strcat(idList, locationIdNew);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* If the token does not end with ":" or ">", we have a problem. */
|
||
printf("The <volume>%s file is corrupt!\n", TLOC_FILE_SUFFIX);
|
||
}
|
||
free (topic);
|
||
}
|
||
|
||
if (trueTopicID != (char *)NULL && idList != (char *)NULL)
|
||
{
|
||
fprintf(outfile, "*.%s.locationIDs:\t%s\n",
|
||
trueTopicID, idList);
|
||
free (trueTopicID);
|
||
free (idList);
|
||
}
|
||
|
||
fprintf (outfile, "\n\n");
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void GenKeyWordList(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Generates the keyword list using the <class>.idx file and
|
||
* writes the results to <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void GenKeyWordList(
|
||
FILE *infile,
|
||
FILE *outfile)
|
||
|
||
{
|
||
char *sortKey=NULL;
|
||
char *keyWordNew=NULL;
|
||
char *locationIdNew=NULL;
|
||
char *keyWordLast=NULL;
|
||
char *locationIdLast=NULL;
|
||
char *idList=NULL;
|
||
char *newList=NULL;
|
||
static char empty[] = "";
|
||
|
||
fseek (infile, 0, SEEK_SET);
|
||
|
||
fprintf (outfile, "# Keyword Index\n");
|
||
|
||
/* idx files (e.g. keyword) have a strict syntax where each line contains
|
||
* three tokens (the sort key, the keyword, and the locationID of the
|
||
* topic in which the keyword resides). Therefore it is an error if the
|
||
* number of tokens in the file is not an integral multiple of 3.
|
||
*/
|
||
|
||
|
||
fprintf (outfile, "*Keywords:\t\\\n");
|
||
|
||
while (1) {
|
||
|
||
/* We get the sortKey, but we don't use it */
|
||
if ((sortKey = GetNextToken (infile, FALSE)) == NULL)
|
||
break;
|
||
|
||
if ((keyWordNew = GetNextToken (infile, FALSE)) == NULL)
|
||
break;
|
||
|
||
if ((locationIdNew = GetNextToken (infile, FALSE)) == NULL)
|
||
break;
|
||
|
||
|
||
|
||
/* Check to see if we have the same keyword as before? */
|
||
if (keyWordLast && (strcmp (keyWordNew, keyWordLast) == 0))
|
||
{
|
||
|
||
/* We have a duplicate so add it to our previous keyword list */
|
||
idList =
|
||
realloc(idList, strlen(idList) + strlen(locationIdNew) + 2);
|
||
|
||
/* Add the new locationId to our current list */
|
||
strcat(idList, " ");
|
||
strcat(idList, locationIdNew);
|
||
|
||
}
|
||
else
|
||
if (keyWordLast != NULL)
|
||
{
|
||
/* Write out the lastList keyword list */
|
||
fprintf (outfile, "%s<\\\\>%s\\n\\\n", keyWordLast, idList);
|
||
|
||
/* Clean up our old values */
|
||
free(keyWordLast);
|
||
free(idList);
|
||
|
||
/* We have a new keyword, so create a new keyword list */
|
||
idList = malloc(strlen(locationIdNew) + 1);
|
||
strcpy(idList, locationIdNew);
|
||
keyWordLast = malloc(strlen(keyWordNew) + 1);
|
||
strcpy(keyWordLast, keyWordNew);
|
||
|
||
}
|
||
else
|
||
{
|
||
/* This is the first time in so we special case it */
|
||
/* Create our initial keyword list */
|
||
idList = malloc(strlen(locationIdNew) + 1);
|
||
strcpy(idList, locationIdNew);
|
||
keyWordLast = malloc(strlen(keyWordNew) + 1);
|
||
strcpy(keyWordLast, keyWordNew);
|
||
|
||
}
|
||
|
||
|
||
free (sortKey);
|
||
free (keyWordNew);
|
||
free (locationIdNew);
|
||
|
||
}
|
||
|
||
/* Write out the last keyword and idList */
|
||
if (!keyWordLast)
|
||
keyWordLast = empty;
|
||
if (!idList)
|
||
idList = empty;
|
||
fprintf (outfile, "%s<\\\\>%s\\n\n", keyWordLast, idList);
|
||
|
||
/* Clean up our old values */
|
||
if (keyWordLast != empty)
|
||
free(keyWordLast);
|
||
if (idList != empty)
|
||
free(idList);
|
||
|
||
fprintf (outfile, "\n\n");
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static char *GetAChar(FILE *file)
|
||
*
|
||
* Parameters: file from which to read a (possibly multibyte) character
|
||
*
|
||
*
|
||
* Return Value: pointer to (possibly multibyte) character
|
||
*
|
||
* Purpose: Read a (possibly multibyte) character from the file.
|
||
* Put the character byte(s) into local static storage,
|
||
* terminating the character with a null byte.
|
||
*
|
||
*****************************************************************************/
|
||
static char *GetAChar(FILE *ifile)
|
||
{
|
||
int c;
|
||
static char mbyte[32]; /* bigger than any possible multibyte char */
|
||
int length;
|
||
|
||
length = 0;
|
||
if (((c = getc(ifile)) == EOF) || (c == '\0'))
|
||
{
|
||
*mbyte = '\0';
|
||
return mbyte;
|
||
}
|
||
|
||
while (1)
|
||
{
|
||
mbyte[length++] = c;
|
||
mbyte[length] = '\0';
|
||
if (mblen(mbyte,length) != -1) return mbyte; /* hurray! */
|
||
if (length == MB_CUR_MAX)
|
||
{ /* reached max without a hit */
|
||
printf("An invalid multi-byte character was found in the input");
|
||
mbyte[0] = ' ';
|
||
mbyte[1] = '\0';
|
||
return mbyte;
|
||
}
|
||
if ((c = getc(ifile)) == EOF)
|
||
{ /* huh? */
|
||
printf("End-of-file found within a multi-byte character");
|
||
mbyte[0] = '\0';
|
||
return mbyte;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void MergeMetaInfo(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Merges the <class>.hmi meta information into the
|
||
* runtime volume file <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void MergeMetaInfo(FILE *infile, FILE *outfile)
|
||
{
|
||
|
||
char buff[BUFSIZ];
|
||
char *nextC;
|
||
char *writeC, *token;
|
||
|
||
fprintf (outfile, "# Meta Information\n");
|
||
fseek (infile, 0, SEEK_SET);
|
||
|
||
/* Clear out any initial white space that may be present */
|
||
while ((*(nextC = GetAChar(infile)) != '\0') &&
|
||
(mblen(nextC, MB_CUR_MAX) == 1) &&
|
||
isspace(*nextC))
|
||
;
|
||
|
||
/* place that initial nextC value */
|
||
fputs(nextC, outfile);
|
||
|
||
while (*(nextC = GetAChar(infile)))
|
||
fputs(nextC, outfile);
|
||
|
||
fputs("\n\n", outfile);
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static void GenHomeLocation(
|
||
* FILE *infile,
|
||
* FILE *outfile)
|
||
*
|
||
* Parameters: infile
|
||
* outfile
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Generates the topic Location section in the
|
||
* <class>.hv file.
|
||
*
|
||
*****************************************************************************/
|
||
static void GenHomeLocation(
|
||
FILE *outfile)
|
||
{
|
||
char *topic, *topicFile, *topicPos;
|
||
|
||
fprintf (outfile, "# Topic Home Locations\n");
|
||
fprintf (outfile, "*topTopic: _HOMETOPIC\n");
|
||
fprintf (outfile, "\n\n");
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
* Function: static char *GetNextToken(FILE *file)
|
||
*
|
||
* Parameters: WidgetClass
|
||
*
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: This function will return a token from the input streem.
|
||
* A boolean flag is passed in which instructs the function to
|
||
* use one of two token delimiters: " " or '\0'.
|
||
* (e.g. space or null char).
|
||
*****************************************************************************/
|
||
static char *GetNextToken(FILE *file, Boolean delimIsSpace)
|
||
{
|
||
char buff[BUFSIZ];
|
||
char *nextC;
|
||
char *writeC, *token;
|
||
int length;
|
||
|
||
while ((*(nextC = GetAChar(file)) != '\0') &&
|
||
((length = mblen(nextC, MB_CUR_MAX)) == 1) &&
|
||
isspace(*nextC))
|
||
;
|
||
|
||
if (*nextC == '\0')
|
||
return (NULL);
|
||
|
||
writeC = buff;
|
||
|
||
if (delimIsSpace)
|
||
{
|
||
do {
|
||
if (writeC < (buff + BUFSIZ - length - 1))
|
||
{
|
||
strcpy(writeC, nextC);
|
||
writeC += length;
|
||
}
|
||
nextC = GetAChar(file);
|
||
length = mblen(nextC, MB_CUR_MAX);
|
||
}
|
||
while ((length > 1) || ((*nextC != '\0') && !isspace(*nextC)));
|
||
}
|
||
else
|
||
{
|
||
do {
|
||
if (writeC < (buff + BUFSIZ - length - 1))
|
||
{
|
||
strcpy(writeC, nextC);
|
||
writeC += length;
|
||
}
|
||
nextC = GetAChar(file);
|
||
length = mblen(nextC, MB_CUR_MAX);
|
||
if ((length == 1) && (*nextC == '\036'))
|
||
*nextC = '\0';
|
||
}
|
||
while ((length > 1) || (*nextC != '\0'));
|
||
}
|
||
|
||
token = strdup(buff);
|
||
return token;
|
||
}
|