Blame WWW/Library/Implementation/HTVMS_WaisProt.c

Packit f574b8
/*
Packit f574b8
 * $LynxId: HTVMS_WaisProt.c,v 1.9 2010/09/24 23:51:22 tom Exp $
Packit f574b8
 *
Packit f574b8
 *							  HTVMS_WAISProt.c
Packit f574b8
 *
Packit f574b8
 *	Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
Packit f574b8
 *
Packit f574b8
 *	31-May-1994 FM	Initial version.
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from WProt.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
Packit f574b8
 * 3.26.90	Harry Morris, morris@think.com
Packit f574b8
 * 3.30.90  Harry Morris
Packit f574b8
 * -	removed chunk code from WAISSearchAPDU,
Packit f574b8
 * -	added makeWAISQueryType1Query() and readWAISType1Query() which replace
Packit f574b8
 * makeWAISQueryTerms() and makeWAISQueryDocs().
Packit f574b8
 * 4.11.90  HWM - generalized conditional includes (see c-dialect.h)
Packit f574b8
 * - renamed makeWAISType1Query() to makeWAISTextQuery()
Packit f574b8
 * renamed readWAISType1Query() to readWAISTextQuery()
Packit f574b8
 * 5.29.90  TS - fixed bug in makeWAISQueryDocs
Packit f574b8
 * added CSTFreeWAISFoo functions
Packit f574b8
 */
Packit f574b8
Packit f574b8
#define _C_WAIS_protocol_
Packit f574b8
Packit f574b8
/*	This file implements the Z39.50 extensions required for WAIS
Packit f574b8
*/
Packit f574b8
Packit f574b8
#include <HTUtils.h>
Packit f574b8
#include <HTVMS_WaisUI.h>
Packit f574b8
#include <HTVMS_WaisProt.h>
Packit f574b8
Packit f574b8
#include <LYLeaks.h>
Packit f574b8
Packit f574b8
/* very rough estimates of the size of an object */
Packit f574b8
#define DefWAISInitResponseSize		(size_t)200
Packit f574b8
#define DefWAISSearchSize			(size_t)3000
Packit f574b8
#define DefWAISSearchResponseSize	(size_t)6000
Packit f574b8
#define DefWAISPresentSize			(size_t)1000
Packit f574b8
#define DefWAISPresentResponseSize	(size_t)6000
Packit f574b8
#define DefWAISDocHeaderSize		(size_t)500
Packit f574b8
#define DefWAISShortHeaderSize		(size_t)200
Packit f574b8
#define DefWAISLongHeaderSize		(size_t)800
Packit f574b8
#define DefWAISDocTextSize			(size_t)6000
Packit f574b8
#define DefWAISDocHeadlineSize		(size_t)500
Packit f574b8
#define DefWAISDocCodeSize			(size_t)500
Packit f574b8
Packit f574b8
#define RESERVE_SPACE_FOR_WAIS_HEADER(len)	\
Packit f574b8
     if (*len > 0)				\
Packit f574b8
	*len -= header_len;
Packit f574b8
Packit f574b8
#define S_MALLOC(type) (type*)s_malloc(sizeof(type))
Packit f574b8
#define S_MALLOC2(type) (type*)s_malloc(sizeof(type) * 2)
Packit f574b8
Packit f574b8
#define S_REALLOC2(type, ptr, num) (type*)s_realloc((char*)ptr, (sizeof(type) * (num + 2)))
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static unsigned long userInfoTagSize(data_tag tag,
Packit f574b8
				     unsigned long length)
Packit f574b8
/* return the number of bytes required to write the user info tag and
Packit f574b8
   length
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    /* calculate bytes required to represent tag.  max tag is 16K */
Packit f574b8
    size = writtenCompressedIntSize(tag);
Packit f574b8
    size += writtenCompressedIntSize(length);
Packit f574b8
Packit f574b8
    return (size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static char *writeUserInfoHeader(data_tag tag,
Packit f574b8
				 long infoSize,
Packit f574b8
				 long estHeaderSize,
Packit f574b8
				 char *buffer,
Packit f574b8
				 long *len)
Packit f574b8
/* write the tag and size, making sure the info fits.  return the true end
Packit f574b8
   of the info (after adjustment) note that the argument infoSize includes
Packit f574b8
   estHeaderSize.  Note that the argument len is the number of bytes remaining
Packit f574b8
   in the buffer.  Since we write the tag and size at the begining of the
Packit f574b8
   buffer (in space that we reserved) we don't want to pass len the calls which
Packit f574b8
   do that writing.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    long dummyLen = 100;	/* plenty of space for a tag and size */
Packit f574b8
    char *buf = buffer;
Packit f574b8
    long realSize = infoSize - estHeaderSize;
Packit f574b8
    long realHeaderSize = userInfoTagSize(tag, realSize);
Packit f574b8
Packit f574b8
    if (buffer == NULL || *len == 0)
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    /* write the tag */
Packit f574b8
    buf = writeTag(tag, buf, &dummyLen);
Packit f574b8
Packit f574b8
    /* see if the if the header size was correct. if not,
Packit f574b8
       we have to shift the info to fit the real header size */
Packit f574b8
    if (estHeaderSize != realHeaderSize) {	/* make sure there is enough space */
Packit f574b8
	CHECK_FOR_SPACE_LEFT(realHeaderSize - estHeaderSize, len);
Packit f574b8
	memmove(buffer + realHeaderSize, buffer + estHeaderSize, (size_t) (realSize));
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /* write the size */
Packit f574b8
    writeCompressedInteger(realSize, buf, &dummyLen);
Packit f574b8
Packit f574b8
    /* return the true end of buffer */
Packit f574b8
    return (buffer + realHeaderSize + realSize);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static char *readUserInfoHeader(data_tag *tag,
Packit f574b8
				unsigned long *num,
Packit f574b8
				char *buffer)
Packit f574b8
/* read the tag and size */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
Packit f574b8
    buf = readTag(tag, buf);
Packit f574b8
    buf = readCompressedInteger(num, buf);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISInitResponse *makeWAISInitResponse(long chunkCode,
Packit f574b8
				       long chunkIDLen,
Packit f574b8
				       char *chunkMarker,
Packit f574b8
				       char *highlightMarker,
Packit f574b8
				       char *deHighlightMarker,
Packit f574b8
				       char *newLineChars)
Packit f574b8
/* create a WAIS init response object */
Packit f574b8
{
Packit f574b8
    WAISInitResponse *init = S_MALLOC(WAISInitResponse);
Packit f574b8
Packit f574b8
    init->ChunkCode = chunkCode;	/* note: none are copied! */
Packit f574b8
    init->ChunkIDLength = chunkIDLen;
Packit f574b8
    init->ChunkMarker = chunkMarker;
Packit f574b8
    init->HighlightMarker = highlightMarker;
Packit f574b8
    init->DeHighlightMarker = deHighlightMarker;
Packit f574b8
    init->NewlineCharacters = newLineChars;
Packit f574b8
Packit f574b8
    return (init);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISInitResponse(WAISInitResponse *init)
Packit f574b8
/* free an object made with makeWAISInitResponse */
Packit f574b8
{
Packit f574b8
    s_free(init->ChunkMarker);
Packit f574b8
    s_free(init->HighlightMarker);
Packit f574b8
    s_free(init->DeHighlightMarker);
Packit f574b8
    s_free(init->NewlineCharacters);
Packit f574b8
    s_free(init);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeInitResponseInfo(InitResponseAPDU *init,
Packit f574b8
			    char *buffer,
Packit f574b8
			    long *len)
Packit f574b8
/* write an init response object */
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
Packit f574b8
					       DefWAISInitResponseSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    WAISInitResponse *info = (WAISInitResponse *) init->UserInformationField;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeNum(info->ChunkCode, DT_ChunkCode, buf, len);
Packit f574b8
    buf = writeNum(info->ChunkIDLength, DT_ChunkIDLength, buf, len);
Packit f574b8
    buf = writeString(info->ChunkMarker, DT_ChunkMarker, buf, len);
Packit f574b8
    buf = writeString(info->HighlightMarker, DT_HighlightMarker, buf, len);
Packit f574b8
    buf = writeString(info->DeHighlightMarker, DT_DeHighlightMarker, buf, len);
Packit f574b8
    buf = writeString(info->NewlineCharacters, DT_NewlineCharacters, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_UserInformationLength,
Packit f574b8
			      size,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readInitResponseInfo(void **info,
Packit f574b8
			   char *buffer)
Packit f574b8
/* read an init response object */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    long chunkCode, chunkIDLen;
Packit f574b8
    data_tag tag1;
Packit f574b8
    char *chunkMarker = NULL;
Packit f574b8
    char *highlightMarker = NULL;
Packit f574b8
    char *deHighlightMarker = NULL;
Packit f574b8
    char *newLineChars = NULL;
Packit f574b8
Packit f574b8
    chunkCode = chunkIDLen = UNUSED;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_ChunkCode:
Packit f574b8
	    buf = readNum(&chunkCode, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ChunkIDLength:
Packit f574b8
	    buf = readNum(&chunkIDLen, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ChunkMarker:
Packit f574b8
	    buf = readString(&chunkMarker, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_HighlightMarker:
Packit f574b8
	    buf = readString(&highlightMarker, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DeHighlightMarker:
Packit f574b8
	    buf = readString(&deHighlightMarker, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_NewlineCharacters:
Packit f574b8
	    buf = readString(&newLineChars, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    s_free(highlightMarker);
Packit f574b8
	    s_free(deHighlightMarker);
Packit f574b8
	    s_free(newLineChars);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *info = (void *) makeWAISInitResponse(chunkCode, chunkIDLen, chunkMarker,
Packit f574b8
					  highlightMarker, deHighlightMarker,
Packit f574b8
					  newLineChars);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISSearch *makeWAISSearch(char *seedWords,
Packit f574b8
			   DocObj **docs,
Packit f574b8
			   char **textList,
Packit f574b8
			   long dateFactor,
Packit f574b8
			   char *beginDateRange,
Packit f574b8
			   char *endDateRange,
Packit f574b8
			   long maxDocsRetrieved)
Packit f574b8
Packit f574b8
/* create a type 3 query object */
Packit f574b8
{
Packit f574b8
    WAISSearch *query = S_MALLOC(WAISSearch);
Packit f574b8
Packit f574b8
    query->SeedWords = seedWords;	/* not copied! */
Packit f574b8
    query->Docs = docs;		/* not copied! */
Packit f574b8
    query->TextList = textList;	/* not copied! */
Packit f574b8
    query->DateFactor = dateFactor;
Packit f574b8
    query->BeginDateRange = beginDateRange;
Packit f574b8
    query->EndDateRange = endDateRange;
Packit f574b8
    query->MaxDocumentsRetrieved = maxDocsRetrieved;
Packit f574b8
Packit f574b8
    return (query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISSearch(WAISSearch *query)
Packit f574b8
Packit f574b8
/* destroy an object made with makeWAISSearch() */
Packit f574b8
{
Packit f574b8
    void *ptr = NULL;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    s_free(query->SeedWords);
Packit f574b8
Packit f574b8
    if (query->Docs != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) query->Docs[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) query->Docs[++i])
Packit f574b8
	    freeDocObj((DocObj *) ptr);
Packit f574b8
    s_free(query->Docs);
Packit f574b8
Packit f574b8
    if (query->TextList != NULL)	/* XXX revisit when textlist is fully defined */
Packit f574b8
	for (i = 0, ptr = (void *) query->TextList[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) query->TextList[++i])
Packit f574b8
	    s_free(ptr);
Packit f574b8
    s_free(query->TextList);
Packit f574b8
Packit f574b8
    s_free(query->BeginDateRange);
Packit f574b8
    s_free(query->EndDateRange);
Packit f574b8
    s_free(query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
DocObj *makeDocObjUsingWholeDocument(any *docID,
Packit f574b8
				     char *type)
Packit f574b8
Packit f574b8
/* construct a document object using byte chunks - only for use by
Packit f574b8
   servers */
Packit f574b8
{
Packit f574b8
    DocObj *doc = S_MALLOC(DocObj);
Packit f574b8
Packit f574b8
    doc->DocumentID = docID;	/* not copied! */
Packit f574b8
    doc->Type = type;		/* not copied! */
Packit f574b8
    doc->ChunkCode = CT_document;
Packit f574b8
    return (doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
DocObj *makeDocObjUsingLines(any *docID,
Packit f574b8
			     char *type,
Packit f574b8
			     long start,
Packit f574b8
			     long end)
Packit f574b8
Packit f574b8
/* construct a document object using line chunks - only for use by
Packit f574b8
   servers */
Packit f574b8
{
Packit f574b8
    DocObj *doc = S_MALLOC(DocObj);
Packit f574b8
Packit f574b8
    doc->ChunkCode = CT_line;
Packit f574b8
    doc->DocumentID = docID;	/* not copied */
Packit f574b8
    doc->Type = type;		/* not copied! */
Packit f574b8
    doc->ChunkStart.Pos = start;
Packit f574b8
    doc->ChunkEnd.Pos = end;
Packit f574b8
    return (doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
DocObj *makeDocObjUsingBytes(any *docID,
Packit f574b8
			     char *type,
Packit f574b8
			     long start,
Packit f574b8
			     long end)
Packit f574b8
Packit f574b8
/* construct a document object using byte chunks - only for use by
Packit f574b8
   servers */
Packit f574b8
{
Packit f574b8
    DocObj *doc = S_MALLOC(DocObj);
Packit f574b8
Packit f574b8
    doc->ChunkCode = CT_byte;
Packit f574b8
    doc->DocumentID = docID;	/* not copied */
Packit f574b8
    doc->Type = type;		/* not copied! */
Packit f574b8
    doc->ChunkStart.Pos = start;
Packit f574b8
    doc->ChunkEnd.Pos = end;
Packit f574b8
    return (doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
DocObj *makeDocObjUsingParagraphs(any *docID,
Packit f574b8
				  char *type,
Packit f574b8
				  any *start,
Packit f574b8
				  any *end)
Packit f574b8
Packit f574b8
/* construct a document object using byte chunks - only for use by
Packit f574b8
   servers */
Packit f574b8
{
Packit f574b8
    DocObj *doc = S_MALLOC(DocObj);
Packit f574b8
Packit f574b8
    doc->ChunkCode = CT_paragraph;
Packit f574b8
    doc->DocumentID = docID;	/* not copied */
Packit f574b8
    doc->Type = type;
Packit f574b8
    doc->ChunkStart.ID = start;
Packit f574b8
    doc->ChunkEnd.ID = end;
Packit f574b8
    return (doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeDocObj(DocObj *doc)
Packit f574b8
Packit f574b8
/* free a docObj */
Packit f574b8
{
Packit f574b8
    freeAny(doc->DocumentID);
Packit f574b8
    s_free(doc->Type);
Packit f574b8
    if (doc->ChunkCode == CT_paragraph) {
Packit f574b8
	freeAny(doc->ChunkStart.ID);
Packit f574b8
	freeAny(doc->ChunkEnd.ID);
Packit f574b8
    }
Packit f574b8
    s_free(doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static char *writeDocObj(DocObj *doc,
Packit f574b8
			 char *buffer,
Packit f574b8
			 long *len)
Packit f574b8
Packit f574b8
/* write as little as we can about the doc obj */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
Packit f574b8
    /* we alwasy have to write the id, but its tag depends on if its a chunk */
Packit f574b8
    if (doc->ChunkCode == CT_document)
Packit f574b8
	buf = writeAny(doc->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    else
Packit f574b8
	buf = writeAny(doc->DocumentID, DT_DocumentIDChunk, buf, len);
Packit f574b8
Packit f574b8
    if (doc->Type != NULL)
Packit f574b8
	buf = writeString(doc->Type, DT_TYPE, buf, len);
Packit f574b8
Packit f574b8
    switch (doc->ChunkCode) {
Packit f574b8
    case CT_document:
Packit f574b8
	/* do nothing - there is no chunk data */
Packit f574b8
	break;
Packit f574b8
    case CT_byte:
Packit f574b8
    case CT_line:
Packit f574b8
	buf = writeNum(doc->ChunkCode, DT_ChunkCode, buf, len);
Packit f574b8
	buf = writeNum(doc->ChunkStart.Pos, DT_ChunkStartID, buf, len);
Packit f574b8
	buf = writeNum(doc->ChunkEnd.Pos, DT_ChunkEndID, buf, len);
Packit f574b8
	break;
Packit f574b8
    case CT_paragraph:
Packit f574b8
	buf = writeNum(doc->ChunkCode, DT_ChunkCode, buf, len);
Packit f574b8
	buf = writeAny(doc->ChunkStart.ID, DT_ChunkStartID, buf, len);
Packit f574b8
	buf = writeAny(doc->ChunkEnd.ID, DT_ChunkEndID, buf, len);
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	panic("Implementation error: unknown chuck type %ld",
Packit f574b8
	      doc->ChunkCode);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static char *readDocObj(DocObj **doc,
Packit f574b8
			char *buffer)
Packit f574b8
Packit f574b8
/* read whatever we have about the new document */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    data_tag tag;
Packit f574b8
Packit f574b8
    *doc = S_MALLOC(DocObj);
Packit f574b8
Packit f574b8
    tag = peekTag(buf);
Packit f574b8
    buf = readAny(&((*doc)->DocumentID), buf);
Packit f574b8
Packit f574b8
    if (tag == DT_DocumentID) {
Packit f574b8
	(*doc)->ChunkCode = CT_document;
Packit f574b8
	tag = peekTag(buf);
Packit f574b8
	if (tag == DT_TYPE)	/* XXX depends on DT_TYPE != what comes next */
Packit f574b8
	    buf = readString(&((*doc)->Type), buf);
Packit f574b8
	/* ChunkStart and ChunkEnd are undefined */
Packit f574b8
    } else if (tag == DT_DocumentIDChunk) {
Packit f574b8
	boolean readParagraphs = false;		/* for cleanup */
Packit f574b8
Packit f574b8
	tag = peekTag(buf);
Packit f574b8
	if (tag == DT_TYPE)	/* XXX depends on DT_TYPE != CT_FOO */
Packit f574b8
	    buf = readString(&((*doc)->Type), buf);
Packit f574b8
	buf = readNum(&((*doc)->ChunkCode), buf);
Packit f574b8
	switch ((*doc)->ChunkCode) {
Packit f574b8
	case CT_byte:
Packit f574b8
	case CT_line:
Packit f574b8
	    buf = readNum(&((*doc)->ChunkStart.Pos), buf);
Packit f574b8
	    buf = readNum(&((*doc)->ChunkEnd.Pos), buf);
Packit f574b8
	    break;
Packit f574b8
	case CT_paragraph:
Packit f574b8
	    buf = readAny(&((*doc)->ChunkStart.ID), buf);
Packit f574b8
	    buf = readAny(&((*doc)->ChunkEnd.ID), buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny((*doc)->DocumentID);
Packit f574b8
	    if (readParagraphs) {
Packit f574b8
		freeAny((*doc)->ChunkStart.ID);
Packit f574b8
		freeAny((*doc)->ChunkEnd.ID);
Packit f574b8
	    }
Packit f574b8
	    s_free(doc);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    } else {
Packit f574b8
	freeAny((*doc)->DocumentID);
Packit f574b8
	s_free(*doc);
Packit f574b8
	REPORT_READ_ERROR(buf);
Packit f574b8
    }
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeSearchInfo(SearchAPDU *query,
Packit f574b8
		      char *buffer,
Packit f574b8
		      long *len)
Packit f574b8
Packit f574b8
/* write out a WAIS query (type 1 or 3) */
Packit f574b8
{
Packit f574b8
    if (strcmp(query->QueryType, QT_TextRetrievalQuery) == 0) {
Packit f574b8
	return (writeAny((any *) query->Query, DT_Query, buffer, len));
Packit f574b8
    } else {
Packit f574b8
	unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
Packit f574b8
						   DefWAISSearchSize);
Packit f574b8
	char *buf = buffer + header_len;
Packit f574b8
	WAISSearch *info = (WAISSearch *) query->Query;
Packit f574b8
	unsigned long size;
Packit f574b8
	long i;
Packit f574b8
Packit f574b8
	RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
	buf = writeString(info->SeedWords, DT_SeedWords, buf, len);
Packit f574b8
Packit f574b8
	if (info->Docs != NULL) {
Packit f574b8
	    for (i = 0; info->Docs[i] != NULL; i++) {
Packit f574b8
		buf = writeDocObj(info->Docs[i], buf, len);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
Packit f574b8
	/* XXX text list */
Packit f574b8
Packit f574b8
	buf = writeNum(info->DateFactor,
Packit f574b8
		       DT_DateFactor,
Packit f574b8
		       buf,
Packit f574b8
		       len);
Packit f574b8
	buf = writeString(info->BeginDateRange,
Packit f574b8
			  DT_BeginDateRange,
Packit f574b8
			  buf,
Packit f574b8
			  len);
Packit f574b8
	buf = writeString(info->EndDateRange,
Packit f574b8
			  DT_EndDateRange,
Packit f574b8
			  buf,
Packit f574b8
			  len);
Packit f574b8
	buf = writeNum(info->MaxDocumentsRetrieved,
Packit f574b8
		       DT_MaxDocumentsRetrieved,
Packit f574b8
		       buf,
Packit f574b8
		       len);
Packit f574b8
Packit f574b8
	/* now write the header and size */
Packit f574b8
	size = buf - buffer;
Packit f574b8
	buf = writeUserInfoHeader(DT_UserInformationLength,
Packit f574b8
				  size,
Packit f574b8
				  header_len,
Packit f574b8
				  buffer,
Packit f574b8
				  len);
Packit f574b8
Packit f574b8
	return (buf);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readSearchInfo(void **info,
Packit f574b8
		     char *buffer)
Packit f574b8
Packit f574b8
/* read a WAIS query (type 1 or 3) */
Packit f574b8
{
Packit f574b8
    data_tag type = peekTag(buffer);
Packit f574b8
Packit f574b8
    if (type == DT_Query)	/* this is a type 1 query */
Packit f574b8
    {
Packit f574b8
	char *buf = buffer;
Packit f574b8
	any *query = NULL;
Packit f574b8
Packit f574b8
	buf = readAny(&query, buf);
Packit f574b8
	*info = (void *) query;
Packit f574b8
	return (buf);
Packit f574b8
    } else {			/* a type 3 query */
Packit f574b8
	char *buf = buffer;
Packit f574b8
	unsigned long size;
Packit f574b8
	unsigned long headerSize;
Packit f574b8
	data_tag tag1;
Packit f574b8
	char *seedWords = NULL;
Packit f574b8
	char *beginDateRange = NULL;
Packit f574b8
	char *endDateRange = NULL;
Packit f574b8
	long dateFactor, maxDocsRetrieved;
Packit f574b8
	char **textList = NULL;
Packit f574b8
	DocObj **docIDs = NULL;
Packit f574b8
	DocObj *doc = NULL;
Packit f574b8
	long docs = 0;
Packit f574b8
	long i;
Packit f574b8
	void *ptr = NULL;
Packit f574b8
Packit f574b8
	dateFactor = maxDocsRetrieved = UNUSED;
Packit f574b8
Packit f574b8
	buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
	headerSize = buf - buffer;
Packit f574b8
Packit f574b8
	while (buf < (buffer + size + headerSize)) {
Packit f574b8
	    data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	    switch (tag) {
Packit f574b8
	    case DT_SeedWords:
Packit f574b8
		buf = readString(&seedWords, buf);
Packit f574b8
		break;
Packit f574b8
	    case DT_DocumentID:
Packit f574b8
	    case DT_DocumentIDChunk:
Packit f574b8
		if (docIDs == NULL)	/* create a new doc list */
Packit f574b8
		{
Packit f574b8
		    docIDs = S_MALLOC2(DocObj *);
Packit f574b8
		} else {	/* grow the doc list */
Packit f574b8
		    docIDs = S_REALLOC2(DocObj *, docIDs, docs);
Packit f574b8
		}
Packit f574b8
		buf = readDocObj(&doc, buf);
Packit f574b8
		if (buf == NULL) {
Packit f574b8
		    s_free(seedWords);
Packit f574b8
		    s_free(beginDateRange);
Packit f574b8
		    s_free(endDateRange);
Packit f574b8
		    if (docIDs != NULL)
Packit f574b8
			for (i = 0, ptr = (void *) docIDs[i];
Packit f574b8
			     ptr != NULL;
Packit f574b8
			     ptr = (void *) docIDs[++i])
Packit f574b8
			    freeDocObj((DocObj *) ptr);
Packit f574b8
		    s_free(docIDs);
Packit f574b8
		    /* XXX should also free textlist when it is fully defined */
Packit f574b8
		}
Packit f574b8
		RETURN_ON_NULL(buf);
Packit f574b8
		docIDs[docs++] = doc;	/* put it in the list */
Packit f574b8
		docIDs[docs] = NULL;
Packit f574b8
		break;
Packit f574b8
	    case DT_TextList:
Packit f574b8
		/* XXX */
Packit f574b8
		break;
Packit f574b8
	    case DT_DateFactor:
Packit f574b8
		buf = readNum(&dateFactor, buf);
Packit f574b8
		break;
Packit f574b8
	    case DT_BeginDateRange:
Packit f574b8
		buf = readString(&beginDateRange, buf);
Packit f574b8
		break;
Packit f574b8
	    case DT_EndDateRange:
Packit f574b8
		buf = readString(&endDateRange, buf);
Packit f574b8
		break;
Packit f574b8
	    case DT_MaxDocumentsRetrieved:
Packit f574b8
		buf = readNum(&maxDocsRetrieved, buf);
Packit f574b8
		break;
Packit f574b8
	    default:
Packit f574b8
		s_free(seedWords);
Packit f574b8
		s_free(beginDateRange);
Packit f574b8
		s_free(endDateRange);
Packit f574b8
		if (docIDs != NULL)
Packit f574b8
		    for (i = 0, ptr = (void *) docIDs[i];
Packit f574b8
			 ptr != NULL;
Packit f574b8
			 ptr = (void *) docIDs[++i])
Packit f574b8
			freeDocObj((DocObj *) ptr);
Packit f574b8
		s_free(docIDs);
Packit f574b8
		/* XXX should also free textlist when it is fully defined */
Packit f574b8
		REPORT_READ_ERROR(buf);
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
Packit f574b8
	*info = (void *) makeWAISSearch(seedWords, docIDs, textList,
Packit f574b8
					dateFactor, beginDateRange, endDateRange,
Packit f574b8
					maxDocsRetrieved);
Packit f574b8
	return (buf);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentHeader *makeWAISDocumentHeader(any *docID,
Packit f574b8
					   long versionNumber,
Packit f574b8
					   long score,
Packit f574b8
					   long bestMatch,
Packit f574b8
					   long docLen,
Packit f574b8
					   long lines,
Packit f574b8
					   char **types,
Packit f574b8
					   char *source,
Packit f574b8
					   char *date,
Packit f574b8
					   char *headline,
Packit f574b8
					   char *originCity)
Packit f574b8
Packit f574b8
/* construct a standard document header, note that no fields are copied!
Packit f574b8
   if the application needs to save these fields, it should copy them,
Packit f574b8
   or set the field in this object to NULL before freeing it.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    WAISDocumentHeader *header = S_MALLOC(WAISDocumentHeader);
Packit f574b8
Packit f574b8
    header->DocumentID = docID;
Packit f574b8
    header->VersionNumber = versionNumber;
Packit f574b8
    header->Score = score;
Packit f574b8
    header->BestMatch = bestMatch;
Packit f574b8
    header->DocumentLength = docLen;
Packit f574b8
    header->Lines = lines;
Packit f574b8
    header->Types = types;
Packit f574b8
    header->Source = source;
Packit f574b8
    header->Date = date;
Packit f574b8
    header->Headline = headline;
Packit f574b8
    header->OriginCity = originCity;
Packit f574b8
Packit f574b8
    return (header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentHeader(WAISDocumentHeader *header)
Packit f574b8
{
Packit f574b8
    freeAny(header->DocumentID);
Packit f574b8
    doList((void **) header->Types, fs_free);	/* can't use the macro here ! */
Packit f574b8
    s_free(header->Types);
Packit f574b8
    s_free(header->Source);
Packit f574b8
    s_free(header->Date);
Packit f574b8
    s_free(header->Headline);
Packit f574b8
    s_free(header->OriginCity);
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentHeader(WAISDocumentHeader *header, char *buffer,
Packit f574b8
			      long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentHeaderGroup,
Packit f574b8
					       DefWAISDocHeaderSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size1;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(header->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(header->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeNum(header->Score, DT_Score, buf, len);
Packit f574b8
    buf = writeNum(header->BestMatch, DT_BestMatch, buf, len);
Packit f574b8
    buf = writeNum(header->DocumentLength, DT_DocumentLength, buf, len);
Packit f574b8
    buf = writeNum(header->Lines, DT_Lines, buf, len);
Packit f574b8
    if (header->Types != NULL) {
Packit f574b8
	long size;
Packit f574b8
	char *ptr = NULL;
Packit f574b8
	long i;
Packit f574b8
Packit f574b8
	buf = writeTag(DT_TYPE_BLOCK, buf, len);
Packit f574b8
	for (i = 0, size = 0, ptr = header->Types[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = header->Types[++i]) {
Packit f574b8
	    long typeSize = strlen(ptr);
Packit f574b8
Packit f574b8
	    size += writtenTagSize(DT_TYPE);
Packit f574b8
	    size += writtenCompressedIntSize(typeSize);
Packit f574b8
	    size += typeSize;
Packit f574b8
	}
Packit f574b8
	buf = writeCompressedInteger((unsigned long) size, buf, len);
Packit f574b8
	for (i = 0, ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
Packit f574b8
	    buf = writeString(ptr, DT_TYPE, buf, len);
Packit f574b8
    }
Packit f574b8
    buf = writeString(header->Source, DT_Source, buf, len);
Packit f574b8
    buf = writeString(header->Date, DT_Date, buf, len);
Packit f574b8
    buf = writeString(header->Headline, DT_Headline, buf, len);
Packit f574b8
    buf = writeString(header->OriginCity, DT_OriginCity, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size1 = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentHeaderGroup,
Packit f574b8
			      size1,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentHeader(WAISDocumentHeader **header, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size1;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID = NULL;
Packit f574b8
    long versionNumber, score, bestMatch, docLength, lines;
Packit f574b8
    char **types = NULL;
Packit f574b8
    char *source = NULL;
Packit f574b8
    char *date = NULL;
Packit f574b8
    char *headline = NULL;
Packit f574b8
    char *originCity = NULL;
Packit f574b8
Packit f574b8
    versionNumber = score = bestMatch = docLength = lines = UNUSED;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size1, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size1 + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Score:
Packit f574b8
	    buf = readNum(&score, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_BestMatch:
Packit f574b8
	    buf = readNum(&bestMatch, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentLength:
Packit f574b8
	    buf = readNum(&docLength, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Lines:
Packit f574b8
	    buf = readNum(&lines, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_TYPE_BLOCK:
Packit f574b8
	    {
Packit f574b8
		unsigned long size = -1;
Packit f574b8
		long numTypes = 0;
Packit f574b8
Packit f574b8
		buf = readTag(&tag, buf);
Packit f574b8
		buf = readCompressedInteger(&size, buf);
Packit f574b8
		while (size > 0) {
Packit f574b8
		    char *type = NULL;
Packit f574b8
		    char *originalBuf = buf;
Packit f574b8
Packit f574b8
		    buf = readString(&type, buf);
Packit f574b8
		    types = S_REALLOC2(char *, types, numTypes);
Packit f574b8
Packit f574b8
		    types[numTypes++] = type;
Packit f574b8
		    types[numTypes] = NULL;
Packit f574b8
		    size -= (buf - originalBuf);
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    /* FALLTHRU */
Packit f574b8
	case DT_Source:
Packit f574b8
	    buf = readString(&source, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Date:
Packit f574b8
	    buf = readString(&date, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Headline:
Packit f574b8
	    buf = readString(&headline, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_OriginCity:
Packit f574b8
	    buf = readString(&originCity, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    s_free(source);
Packit f574b8
	    s_free(date);
Packit f574b8
	    s_free(headline);
Packit f574b8
	    s_free(originCity);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *header = makeWAISDocumentHeader(docID, versionNumber, score, bestMatch,
Packit f574b8
				     docLength, lines, types, source, date, headline,
Packit f574b8
				     originCity);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentShortHeader *makeWAISDocumentShortHeader(any *docID,
Packit f574b8
						     long versionNumber,
Packit f574b8
						     long score,
Packit f574b8
						     long bestMatch,
Packit f574b8
						     long docLen,
Packit f574b8
						     long lines)
Packit f574b8
/* construct a short document header, note that no fields are copied!
Packit f574b8
   if the application needs to save these fields, it should copy them,
Packit f574b8
   or set the field in this object to NULL before freeing it.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    WAISDocumentShortHeader *header = S_MALLOC(WAISDocumentShortHeader);
Packit f574b8
Packit f574b8
    header->DocumentID = docID;
Packit f574b8
    header->VersionNumber = versionNumber;
Packit f574b8
    header->Score = score;
Packit f574b8
    header->BestMatch = bestMatch;
Packit f574b8
    header->DocumentLength = docLen;
Packit f574b8
    header->Lines = lines;
Packit f574b8
Packit f574b8
    return (header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentShortHeader(WAISDocumentShortHeader *header)
Packit f574b8
{
Packit f574b8
    freeAny(header->DocumentID);
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentShortHeader(WAISDocumentShortHeader *header, char *buffer,
Packit f574b8
				   long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentShortHeaderGroup,
Packit f574b8
					       DefWAISShortHeaderSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(header->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(header->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeNum(header->Score, DT_Score, buf, len);
Packit f574b8
    buf = writeNum(header->BestMatch, DT_BestMatch, buf, len);
Packit f574b8
    buf = writeNum(header->DocumentLength, DT_DocumentLength, buf, len);
Packit f574b8
    buf = writeNum(header->Lines, DT_Lines, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentShortHeaderGroup,
Packit f574b8
			      size,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentShortHeader(WAISDocumentShortHeader **header, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID = NULL;
Packit f574b8
    long versionNumber, score, bestMatch, docLength, lines;
Packit f574b8
Packit f574b8
    versionNumber = score = bestMatch = docLength = lines = UNUSED;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Score:
Packit f574b8
	    buf = readNum(&score, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_BestMatch:
Packit f574b8
	    buf = readNum(&bestMatch, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentLength:
Packit f574b8
	    buf = readNum(&docLength, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Lines:
Packit f574b8
	    buf = readNum(&lines, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *header = makeWAISDocumentShortHeader(docID, versionNumber, score, bestMatch,
Packit f574b8
					  docLength, lines);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentLongHeader *makeWAISDocumentLongHeader(any *docID,
Packit f574b8
						   long versionNumber,
Packit f574b8
						   long score,
Packit f574b8
						   long bestMatch,
Packit f574b8
						   long docLen,
Packit f574b8
						   long lines,
Packit f574b8
						   char **types,
Packit f574b8
						   char *source,
Packit f574b8
						   char *date,
Packit f574b8
						   char *headline,
Packit f574b8
						   char *originCity,
Packit f574b8
						   char *stockCodes,
Packit f574b8
						   char *companyCodes,
Packit f574b8
						   char *industryCodes)
Packit f574b8
/* construct a long document header, note that no fields are copied!
Packit f574b8
   if the application needs to save these fields, it should copy them,
Packit f574b8
   or set the field in this object to NULL before freeing it.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    WAISDocumentLongHeader *header = S_MALLOC(WAISDocumentLongHeader);
Packit f574b8
Packit f574b8
    header->DocumentID = docID;
Packit f574b8
    header->VersionNumber = versionNumber;
Packit f574b8
    header->Score = score;
Packit f574b8
    header->BestMatch = bestMatch;
Packit f574b8
    header->DocumentLength = docLen;
Packit f574b8
    header->Lines = lines;
Packit f574b8
    header->Types = types;
Packit f574b8
    header->Source = source;
Packit f574b8
    header->Date = date;
Packit f574b8
    header->Headline = headline;
Packit f574b8
    header->OriginCity = originCity;
Packit f574b8
    header->StockCodes = stockCodes;
Packit f574b8
    header->CompanyCodes = companyCodes;
Packit f574b8
    header->IndustryCodes = industryCodes;
Packit f574b8
Packit f574b8
    return (header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentLongHeader(WAISDocumentLongHeader *header)
Packit f574b8
{
Packit f574b8
    freeAny(header->DocumentID);
Packit f574b8
    doList((void **) header->Types, fs_free);	/* can't use the macro here! */
Packit f574b8
    s_free(header->Source);
Packit f574b8
    s_free(header->Date);
Packit f574b8
    s_free(header->Headline);
Packit f574b8
    s_free(header->OriginCity);
Packit f574b8
    s_free(header->StockCodes);
Packit f574b8
    s_free(header->CompanyCodes);
Packit f574b8
    s_free(header->IndustryCodes);
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentLongHeader(WAISDocumentLongHeader *header, char *buffer,
Packit f574b8
				  long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentLongHeaderGroup,
Packit f574b8
					       DefWAISLongHeaderSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size1;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(header->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(header->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeNum(header->Score, DT_Score, buf, len);
Packit f574b8
    buf = writeNum(header->BestMatch, DT_BestMatch, buf, len);
Packit f574b8
    buf = writeNum(header->DocumentLength, DT_DocumentLength, buf, len);
Packit f574b8
    buf = writeNum(header->Lines, DT_Lines, buf, len);
Packit f574b8
    if (header->Types != NULL) {
Packit f574b8
	long size;
Packit f574b8
	char *ptr = NULL;
Packit f574b8
	long i;
Packit f574b8
Packit f574b8
	buf = writeTag(DT_TYPE_BLOCK, buf, len);
Packit f574b8
	for (i = 0, size = 0, ptr = header->Types[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = header->Types[++i]) {
Packit f574b8
	    long typeSize = strlen(ptr);
Packit f574b8
Packit f574b8
	    size += writtenTagSize(DT_TYPE);
Packit f574b8
	    size += writtenCompressedIntSize(typeSize);
Packit f574b8
	    size += typeSize;
Packit f574b8
	}
Packit f574b8
	buf = writeCompressedInteger((unsigned long) size, buf, len);
Packit f574b8
	for (i = 0, ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
Packit f574b8
	    buf = writeString(ptr, DT_TYPE, buf, len);
Packit f574b8
    }
Packit f574b8
    buf = writeString(header->Source, DT_Source, buf, len);
Packit f574b8
    buf = writeString(header->Date, DT_Date, buf, len);
Packit f574b8
    buf = writeString(header->Headline, DT_Headline, buf, len);
Packit f574b8
    buf = writeString(header->OriginCity, DT_OriginCity, buf, len);
Packit f574b8
    buf = writeString(header->StockCodes, DT_StockCodes, buf, len);
Packit f574b8
    buf = writeString(header->CompanyCodes, DT_CompanyCodes, buf, len);
Packit f574b8
    buf = writeString(header->IndustryCodes, DT_IndustryCodes, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size1 = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentLongHeaderGroup,
Packit f574b8
			      size1,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentLongHeader(WAISDocumentLongHeader **header, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size1;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID;
Packit f574b8
    long versionNumber, score, bestMatch, docLength, lines;
Packit f574b8
    char **types;
Packit f574b8
    char *source, *date, *headline, *originCity, *stockCodes, *companyCodes, *industryCodes;
Packit f574b8
Packit f574b8
    docID = NULL;
Packit f574b8
    versionNumber =
Packit f574b8
	score =
Packit f574b8
	bestMatch =
Packit f574b8
	docLength =
Packit f574b8
	lines = UNUSED;
Packit f574b8
    types = NULL;
Packit f574b8
    source =
Packit f574b8
	date =
Packit f574b8
	headline =
Packit f574b8
	originCity =
Packit f574b8
	stockCodes =
Packit f574b8
	companyCodes =
Packit f574b8
	industryCodes = NULL;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size1, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size1 + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Score:
Packit f574b8
	    buf = readNum(&score, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_BestMatch:
Packit f574b8
	    buf = readNum(&bestMatch, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentLength:
Packit f574b8
	    buf = readNum(&docLength, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Lines:
Packit f574b8
	    buf = readNum(&lines, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_TYPE_BLOCK:
Packit f574b8
	    {
Packit f574b8
		unsigned long size = -1;
Packit f574b8
		long numTypes = 0;
Packit f574b8
Packit f574b8
		buf = readTag(&tag, buf);
Packit f574b8
		readCompressedInteger(&size, buf);
Packit f574b8
		while (size > 0) {
Packit f574b8
		    char *type = NULL;
Packit f574b8
		    char *originalBuf = buf;
Packit f574b8
Packit f574b8
		    buf = readString(&type, buf);
Packit f574b8
		    types = S_REALLOC2(char *, types, numTypes);
Packit f574b8
Packit f574b8
		    types[numTypes++] = type;
Packit f574b8
		    types[numTypes] = NULL;
Packit f574b8
		    size -= (buf - originalBuf);
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	    /* FALLTHRU */
Packit f574b8
	case DT_Source:
Packit f574b8
	    buf = readString(&source, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Date:
Packit f574b8
	    buf = readString(&date, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Headline:
Packit f574b8
	    buf = readString(&headline, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_OriginCity:
Packit f574b8
	    buf = readString(&originCity, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_StockCodes:
Packit f574b8
	    buf = readString(&stockCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_CompanyCodes:
Packit f574b8
	    buf = readString(&companyCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_IndustryCodes:
Packit f574b8
	    buf = readString(&industryCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    s_free(source);
Packit f574b8
	    s_free(date);
Packit f574b8
	    s_free(headline);
Packit f574b8
	    s_free(originCity);
Packit f574b8
	    s_free(stockCodes);
Packit f574b8
	    s_free(companyCodes);
Packit f574b8
	    s_free(industryCodes);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *header = makeWAISDocumentLongHeader(docID,
Packit f574b8
					 versionNumber,
Packit f574b8
					 score,
Packit f574b8
					 bestMatch,
Packit f574b8
					 docLength,
Packit f574b8
					 lines,
Packit f574b8
					 types,
Packit f574b8
					 source,
Packit f574b8
					 date,
Packit f574b8
					 headline,
Packit f574b8
					 originCity,
Packit f574b8
					 stockCodes,
Packit f574b8
					 companyCodes,
Packit f574b8
					 industryCodes);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISSearchResponse *
Packit f574b8
  makeWAISSearchResponse(
Packit f574b8
			    char *seedWordsUsed,
Packit f574b8
			    WAISDocumentHeader **docHeaders,
Packit f574b8
			    WAISDocumentShortHeader **shortHeaders,
Packit f574b8
			    WAISDocumentLongHeader **longHeaders,
Packit f574b8
			    WAISDocumentText **text,
Packit f574b8
			    WAISDocumentHeadlines **headlines,
Packit f574b8
			    WAISDocumentCodes **codes,
Packit f574b8
			    diagnosticRecord ** diagnostics)
Packit f574b8
{
Packit f574b8
    WAISSearchResponse *response = S_MALLOC(WAISSearchResponse);
Packit f574b8
Packit f574b8
    response->SeedWordsUsed = seedWordsUsed;
Packit f574b8
    response->DocHeaders = docHeaders;
Packit f574b8
    response->ShortHeaders = shortHeaders;
Packit f574b8
    response->LongHeaders = longHeaders;
Packit f574b8
    response->Text = text;
Packit f574b8
    response->Headlines = headlines;
Packit f574b8
    response->Codes = codes;
Packit f574b8
    response->Diagnostics = diagnostics;
Packit f574b8
Packit f574b8
    return (response);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISSearchResponse(WAISSearchResponse * response)
Packit f574b8
{
Packit f574b8
    void *ptr = NULL;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    s_free(response->SeedWordsUsed);
Packit f574b8
Packit f574b8
    if (response->DocHeaders != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->DocHeaders[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->DocHeaders[++i])
Packit f574b8
	    freeWAISDocumentHeader((WAISDocumentHeader *) ptr);
Packit f574b8
    s_free(response->DocHeaders);
Packit f574b8
Packit f574b8
    if (response->ShortHeaders != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->ShortHeaders[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->ShortHeaders[++i])
Packit f574b8
	    freeWAISDocumentShortHeader((WAISDocumentShortHeader *) ptr);
Packit f574b8
    s_free(response->ShortHeaders);
Packit f574b8
Packit f574b8
    if (response->LongHeaders != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->LongHeaders[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->LongHeaders[++i])
Packit f574b8
	    freeWAISDocumentLongHeader((WAISDocumentLongHeader *) ptr);
Packit f574b8
    s_free(response->LongHeaders);
Packit f574b8
Packit f574b8
    if (response->Text != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->Text[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->Text[++i])
Packit f574b8
	    freeWAISDocumentText((WAISDocumentText *) ptr);
Packit f574b8
    s_free(response->Text);
Packit f574b8
Packit f574b8
    if (response->Headlines != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->Headlines[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->Headlines[++i])
Packit f574b8
	    freeWAISDocumentHeadlines((WAISDocumentHeadlines *) ptr);
Packit f574b8
    s_free(response->Headlines);
Packit f574b8
Packit f574b8
    if (response->Codes != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->Codes[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->Codes[++i])
Packit f574b8
	    freeWAISDocumentCodes((WAISDocumentCodes *) ptr);
Packit f574b8
    s_free(response->Codes);
Packit f574b8
Packit f574b8
    if (response->Diagnostics != NULL)
Packit f574b8
	for (i = 0, ptr = (void *) response->Diagnostics[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = (void *) response->Diagnostics[++i])
Packit f574b8
	    freeDiag((diagnosticRecord *) ptr);
Packit f574b8
    s_free(response->Diagnostics);
Packit f574b8
Packit f574b8
    s_free(response);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeSearchResponseInfo(SearchResponseAPDU *query,
Packit f574b8
			      char *buffer,
Packit f574b8
			      long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
Packit f574b8
					       DefWAISSearchResponseSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    WAISSearchResponse *info = (WAISSearchResponse *) query->DatabaseDiagnosticRecords;
Packit f574b8
    unsigned long size;
Packit f574b8
    void *header = NULL;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeString(info->SeedWordsUsed, DT_SeedWordsUsed, buf, len);
Packit f574b8
Packit f574b8
    /* write out all the headers */
Packit f574b8
    if (info->DocHeaders != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->DocHeaders[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->DocHeaders[++i])
Packit f574b8
	    buf = writeWAISDocumentHeader((WAISDocumentHeader *) header, buf, len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->ShortHeaders != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->ShortHeaders[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->ShortHeaders[++i])
Packit f574b8
	    buf = writeWAISDocumentShortHeader((WAISDocumentShortHeader *) header,
Packit f574b8
					       buf,
Packit f574b8
					       len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->LongHeaders != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->LongHeaders[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->LongHeaders[++i])
Packit f574b8
	    buf = writeWAISDocumentLongHeader((WAISDocumentLongHeader *) header,
Packit f574b8
					      buf,
Packit f574b8
					      len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->Text != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->Text[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->Text[++i])
Packit f574b8
	    buf = writeWAISDocumentText((WAISDocumentText *) header, buf, len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->Headlines != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->Headlines[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->Headlines[++i])
Packit f574b8
	    buf = writeWAISDocumentHeadlines((WAISDocumentHeadlines *) header,
Packit f574b8
					     buf,
Packit f574b8
					     len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->Codes != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->Codes[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->Codes[++i])
Packit f574b8
	    buf = writeWAISDocumentCodes((WAISDocumentCodes *) header, buf, len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    if (info->Diagnostics != NULL) {
Packit f574b8
	for (i = 0, header = (void *) info->Diagnostics[i];
Packit f574b8
	     header != NULL;
Packit f574b8
	     header = (void *) info->Diagnostics[++i])
Packit f574b8
	    buf = writeDiag((diagnosticRecord *) header, buf, len);
Packit f574b8
    }
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_UserInformationLength,
Packit f574b8
			      size,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static void cleanUpWaisSearchResponse(char *buf,
Packit f574b8
				      char *seedWordsUsed,
Packit f574b8
				      WAISDocumentHeader **docHeaders,
Packit f574b8
				      WAISDocumentShortHeader **shortHeaders,
Packit f574b8
				      WAISDocumentLongHeader **longHeaders,
Packit f574b8
				      WAISDocumentText **text,
Packit f574b8
				      WAISDocumentHeadlines **headlines,
Packit f574b8
				      WAISDocumentCodes **codes,
Packit f574b8
				      diagnosticRecord ** diags)
Packit f574b8
/* if buf is NULL, we have just gotten a read error, and need to clean up
Packit f574b8
   any state we have built.  If not, then everything is going fine, and
Packit f574b8
   we should just hang loose
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    void *ptr = NULL;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    if (buf == NULL) {
Packit f574b8
	s_free(seedWordsUsed);
Packit f574b8
	if (docHeaders != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) docHeaders[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) docHeaders[++i])
Packit f574b8
		freeWAISDocumentHeader((WAISDocumentHeader *) ptr);
Packit f574b8
	s_free(docHeaders);
Packit f574b8
	if (shortHeaders != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) shortHeaders[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) shortHeaders[++i])
Packit f574b8
		freeWAISDocumentShortHeader((WAISDocumentShortHeader *) ptr);
Packit f574b8
	s_free(shortHeaders);
Packit f574b8
	if (longHeaders != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) longHeaders[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) longHeaders[++i])
Packit f574b8
		freeWAISDocumentLongHeader((WAISDocumentLongHeader *) ptr);
Packit f574b8
	s_free(longHeaders);
Packit f574b8
	if (text != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) text[i];
Packit f574b8
		 ptr != NULL;
Packit f574b8
		 ptr = (void *) text[++i])
Packit f574b8
		freeWAISDocumentText((WAISDocumentText *) ptr);
Packit f574b8
	s_free(text);
Packit f574b8
	if (headlines != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) headlines[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) headlines[++i])
Packit f574b8
		freeWAISDocumentHeadlines((WAISDocumentHeadlines *) ptr);
Packit f574b8
	s_free(headlines);
Packit f574b8
	if (codes != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) codes[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) codes[++i])
Packit f574b8
		freeWAISDocumentCodes((WAISDocumentCodes *) ptr);
Packit f574b8
	s_free(codes);
Packit f574b8
	if (diags != NULL)
Packit f574b8
	    for (i = 0, ptr = (void *) diags[i]; ptr != NULL;
Packit f574b8
		 ptr = (void *) diags[++i])
Packit f574b8
		freeDiag((diagnosticRecord *) ptr);
Packit f574b8
	s_free(diags);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readSearchResponseInfo(void **info,
Packit f574b8
			     char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    void *header = NULL;
Packit f574b8
    WAISDocumentHeader **docHeaders = NULL;
Packit f574b8
    WAISDocumentShortHeader **shortHeaders = NULL;
Packit f574b8
    WAISDocumentLongHeader **longHeaders = NULL;
Packit f574b8
    WAISDocumentText **text = NULL;
Packit f574b8
    WAISDocumentHeadlines **headlines = NULL;
Packit f574b8
    WAISDocumentCodes **codes = NULL;
Packit f574b8
    long numDocHeaders, numLongHeaders, numShortHeaders, numText, numHeadlines;
Packit f574b8
    long numCodes;
Packit f574b8
    char *seedWordsUsed = NULL;
Packit f574b8
    diagnosticRecord **diags = NULL;
Packit f574b8
    diagnosticRecord *diag = NULL;
Packit f574b8
    long numDiags = 0;
Packit f574b8
Packit f574b8
    numDocHeaders =
Packit f574b8
	numLongHeaders =
Packit f574b8
	numShortHeaders =
Packit f574b8
	numText =
Packit f574b8
	numHeadlines =
Packit f574b8
	numCodes = 0;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_SeedWordsUsed:
Packit f574b8
	    buf = readString(&seedWordsUsed, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DatabaseDiagnosticRecords:
Packit f574b8
	    if (diags == NULL)	/* create a new diag list */
Packit f574b8
	    {
Packit f574b8
		diags = S_MALLOC2(diagnosticRecord *);
Packit f574b8
	    } else {		/* grow the diag list */
Packit f574b8
		diags = S_REALLOC2(diagnosticRecord *, diags, numDiags);
Packit f574b8
	    }
Packit f574b8
	    buf = readDiag(&diag, buf);
Packit f574b8
	    diags[numDiags++] = diag;	/* put it in the list */
Packit f574b8
	    diags[numDiags] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentHeaderGroup:
Packit f574b8
	    if (docHeaders == NULL)	/* create a new header list */
Packit f574b8
	    {
Packit f574b8
		docHeaders = S_MALLOC2(WAISDocumentHeader *);
Packit f574b8
	    } else {		/* grow the doc list */
Packit f574b8
		docHeaders = S_REALLOC2(WAISDocumentHeader *, docHeaders, numDocHeaders);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentHeader((WAISDocumentHeader **) &header, buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    docHeaders[numDocHeaders++] =
Packit f574b8
		(WAISDocumentHeader *) header;	/* put it in the list */
Packit f574b8
	    docHeaders[numDocHeaders] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentShortHeaderGroup:
Packit f574b8
	    if (shortHeaders == NULL)	/* create a new header list */
Packit f574b8
	    {
Packit f574b8
		shortHeaders = S_MALLOC2(WAISDocumentShortHeader *);
Packit f574b8
	    } else {		/* grow the doc list */
Packit f574b8
		shortHeaders = S_REALLOC2(WAISDocumentShortHeader *,
Packit f574b8
					  shortHeaders,
Packit f574b8
					  numShortHeaders);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentShortHeader((WAISDocumentShortHeader **) &header,
Packit f574b8
					      buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    shortHeaders[numShortHeaders++] =
Packit f574b8
		(WAISDocumentShortHeader *) header;	/* put it in the list */
Packit f574b8
	    shortHeaders[numShortHeaders] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentLongHeaderGroup:
Packit f574b8
	    if (longHeaders == NULL)	/* create a new header list */
Packit f574b8
	    {
Packit f574b8
		longHeaders = S_MALLOC2(WAISDocumentLongHeader *);
Packit f574b8
	    } else {		/* grow the doc list */
Packit f574b8
		longHeaders = S_REALLOC2(WAISDocumentLongHeader *,
Packit f574b8
					 longHeaders,
Packit f574b8
					 numLongHeaders);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentLongHeader((WAISDocumentLongHeader **) &header,
Packit f574b8
					     buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    longHeaders[numLongHeaders++] =
Packit f574b8
		(WAISDocumentLongHeader *) header;	/* put it in the list */
Packit f574b8
	    longHeaders[numLongHeaders] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentTextGroup:
Packit f574b8
	    if (text == NULL)	/* create a new list */
Packit f574b8
	    {
Packit f574b8
		text = S_MALLOC2(WAISDocumentText *);
Packit f574b8
	    } else {		/* grow the list */
Packit f574b8
		text = S_REALLOC2(WAISDocumentText *, text, numText);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentText((WAISDocumentText **) &header, buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    text[numText++] =
Packit f574b8
		(WAISDocumentText *) header;	/* put it in the list */
Packit f574b8
	    text[numText] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentHeadlineGroup:
Packit f574b8
	    if (headlines == NULL)	/* create a new list */
Packit f574b8
	    {
Packit f574b8
		headlines = S_MALLOC2(WAISDocumentHeadlines *);
Packit f574b8
	    } else {		/* grow the list */
Packit f574b8
		headlines = S_REALLOC2(WAISDocumentHeadlines *, headlines, numHeadlines);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentHeadlines((WAISDocumentHeadlines **) &header,
Packit f574b8
					    buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    headlines[numHeadlines++] =
Packit f574b8
		(WAISDocumentHeadlines *) header;	/* put it in the list */
Packit f574b8
	    headlines[numHeadlines] = NULL;
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentCodeGroup:
Packit f574b8
	    if (codes == NULL)	/* create a new list */
Packit f574b8
	    {
Packit f574b8
		codes = S_MALLOC2(WAISDocumentCodes *);
Packit f574b8
	    } else {		/* grow the list */
Packit f574b8
		codes = S_REALLOC2(WAISDocumentCodes *, codes, numCodes);
Packit f574b8
	    }
Packit f574b8
	    buf = readWAISDocumentCodes((WAISDocumentCodes **) &header, buf);
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    RETURN_ON_NULL(buf);
Packit f574b8
	    codes[numCodes++] =
Packit f574b8
		(WAISDocumentCodes *) header;	/* put it in the list */
Packit f574b8
	    codes[numCodes] = NULL;
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    cleanUpWaisSearchResponse(buf,
Packit f574b8
				      seedWordsUsed,
Packit f574b8
				      docHeaders,
Packit f574b8
				      shortHeaders,
Packit f574b8
				      longHeaders,
Packit f574b8
				      text,
Packit f574b8
				      headlines,
Packit f574b8
				      codes,
Packit f574b8
				      diags);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *info = (void *) makeWAISSearchResponse(seedWordsUsed,
Packit f574b8
					    docHeaders,
Packit f574b8
					    shortHeaders,
Packit f574b8
					    longHeaders,
Packit f574b8
					    text,
Packit f574b8
					    headlines,
Packit f574b8
					    codes,
Packit f574b8
					    diags);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentText *makeWAISDocumentText(any *docID,
Packit f574b8
				       long versionNumber,
Packit f574b8
				       any *documentText)
Packit f574b8
{
Packit f574b8
    WAISDocumentText *docText = S_MALLOC(WAISDocumentText);
Packit f574b8
Packit f574b8
    docText->DocumentID = docID;
Packit f574b8
    docText->VersionNumber = versionNumber;
Packit f574b8
    docText->DocumentText = documentText;
Packit f574b8
Packit f574b8
    return (docText);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentText(WAISDocumentText *docText)
Packit f574b8
{
Packit f574b8
    freeAny(docText->DocumentID);
Packit f574b8
    freeAny(docText->DocumentText);
Packit f574b8
    s_free(docText);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentText(WAISDocumentText *docText, char *buffer,
Packit f574b8
			    long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentTextGroup,
Packit f574b8
					       DefWAISDocTextSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(docText->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(docText->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeAny(docText->DocumentText, DT_DocumentText, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentTextGroup, size, header_len, buffer, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentText(WAISDocumentText **docText, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID, *documentText;
Packit f574b8
    long versionNumber;
Packit f574b8
Packit f574b8
    docID = documentText = NULL;
Packit f574b8
    versionNumber = UNUSED;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_DocumentText:
Packit f574b8
	    buf = readAny(&documentText, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    freeAny(documentText);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *docText = makeWAISDocumentText(docID, versionNumber, documentText);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentHeadlines *makeWAISDocumentHeadlines(any *docID,
Packit f574b8
						 long versionNumber,
Packit f574b8
						 char *source,
Packit f574b8
						 char *date,
Packit f574b8
						 char *headline,
Packit f574b8
						 char *originCity)
Packit f574b8
{
Packit f574b8
    WAISDocumentHeadlines *docHeadline = S_MALLOC(WAISDocumentHeadlines);
Packit f574b8
Packit f574b8
    docHeadline->DocumentID = docID;
Packit f574b8
    docHeadline->VersionNumber = versionNumber;
Packit f574b8
    docHeadline->Source = source;
Packit f574b8
    docHeadline->Date = date;
Packit f574b8
    docHeadline->Headline = headline;
Packit f574b8
    docHeadline->OriginCity = originCity;
Packit f574b8
Packit f574b8
    return (docHeadline);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentHeadlines(WAISDocumentHeadlines *docHeadline)
Packit f574b8
{
Packit f574b8
    freeAny(docHeadline->DocumentID);
Packit f574b8
    s_free(docHeadline->Source);
Packit f574b8
    s_free(docHeadline->Date);
Packit f574b8
    s_free(docHeadline->Headline);
Packit f574b8
    s_free(docHeadline->OriginCity);
Packit f574b8
    s_free(docHeadline);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentHeadlines(WAISDocumentHeadlines *docHeadline, char *buffer,
Packit f574b8
				 long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentHeadlineGroup,
Packit f574b8
					       DefWAISDocHeadlineSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(docHeadline->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(docHeadline->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeString(docHeadline->Source, DT_Source, buf, len);
Packit f574b8
    buf = writeString(docHeadline->Date, DT_Date, buf, len);
Packit f574b8
    buf = writeString(docHeadline->Headline, DT_Headline, buf, len);
Packit f574b8
    buf = writeString(docHeadline->OriginCity, DT_OriginCity, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentHeadlineGroup,
Packit f574b8
			      size,
Packit f574b8
			      header_len,
Packit f574b8
			      buffer,
Packit f574b8
			      len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentHeadlines(WAISDocumentHeadlines **docHeadline, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID;
Packit f574b8
    long versionNumber;
Packit f574b8
    char *source, *date, *headline, *originCity;
Packit f574b8
Packit f574b8
    docID = NULL;
Packit f574b8
    versionNumber = UNUSED;
Packit f574b8
    source = date = headline = originCity = NULL;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Source:
Packit f574b8
	    buf = readString(&source, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Date:
Packit f574b8
	    buf = readString(&date, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_Headline:
Packit f574b8
	    buf = readString(&headline, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_OriginCity:
Packit f574b8
	    buf = readString(&originCity, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    s_free(source);
Packit f574b8
	    s_free(date);
Packit f574b8
	    s_free(headline);
Packit f574b8
	    s_free(originCity);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *docHeadline = makeWAISDocumentHeadlines(docID, versionNumber, source, date,
Packit f574b8
					     headline, originCity);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
WAISDocumentCodes *makeWAISDocumentCodes(any *docID,
Packit f574b8
					 long versionNumber,
Packit f574b8
					 char *stockCodes,
Packit f574b8
					 char *companyCodes,
Packit f574b8
					 char *industryCodes)
Packit f574b8
{
Packit f574b8
    WAISDocumentCodes *docCodes = S_MALLOC(WAISDocumentCodes);
Packit f574b8
Packit f574b8
    docCodes->DocumentID = docID;
Packit f574b8
    docCodes->VersionNumber = versionNumber;
Packit f574b8
    docCodes->StockCodes = stockCodes;
Packit f574b8
    docCodes->CompanyCodes = companyCodes;
Packit f574b8
    docCodes->IndustryCodes = industryCodes;
Packit f574b8
Packit f574b8
    return (docCodes);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeWAISDocumentCodes(WAISDocumentCodes *docCodes)
Packit f574b8
{
Packit f574b8
    freeAny(docCodes->DocumentID);
Packit f574b8
    s_free(docCodes->StockCodes);
Packit f574b8
    s_free(docCodes->CompanyCodes);
Packit f574b8
    s_free(docCodes->IndustryCodes);
Packit f574b8
    s_free(docCodes);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeWAISDocumentCodes(WAISDocumentCodes *docCodes,
Packit f574b8
			     char *buffer,
Packit f574b8
			     long *len)
Packit f574b8
{
Packit f574b8
    unsigned long header_len = userInfoTagSize(DT_DocumentCodeGroup,
Packit f574b8
					       DefWAISDocCodeSize);
Packit f574b8
    char *buf = buffer + header_len;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_WAIS_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writeAny(docCodes->DocumentID, DT_DocumentID, buf, len);
Packit f574b8
    buf = writeNum(docCodes->VersionNumber, DT_VersionNumber, buf, len);
Packit f574b8
    buf = writeString(docCodes->StockCodes, DT_StockCodes, buf, len);
Packit f574b8
    buf = writeString(docCodes->CompanyCodes, DT_CompanyCodes, buf, len);
Packit f574b8
    buf = writeString(docCodes->IndustryCodes, DT_IndustryCodes, buf, len);
Packit f574b8
Packit f574b8
    /* now write the header and size */
Packit f574b8
    size = buf - buffer;
Packit f574b8
    buf = writeUserInfoHeader(DT_DocumentCodeGroup, size, header_len, buffer, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readWAISDocumentCodes(WAISDocumentCodes **docCodes,
Packit f574b8
			    char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long headerSize;
Packit f574b8
    data_tag tag1;
Packit f574b8
    any *docID;
Packit f574b8
    long versionNumber;
Packit f574b8
    char *stockCodes, *companyCodes, *industryCodes;
Packit f574b8
Packit f574b8
    docID = NULL;
Packit f574b8
    versionNumber = UNUSED;
Packit f574b8
    stockCodes = companyCodes = industryCodes = NULL;
Packit f574b8
Packit f574b8
    buf = readUserInfoHeader(&tag1, &size, buf);
Packit f574b8
    headerSize = buf - buffer;
Packit f574b8
Packit f574b8
    while (buf < (buffer + size + headerSize)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_DocumentID:
Packit f574b8
	    buf = readAny(&docID, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_VersionNumber:
Packit f574b8
	    buf = readNum(&versionNumber, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_StockCodes:
Packit f574b8
	    buf = readString(&stockCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_CompanyCodes:
Packit f574b8
	    buf = readString(&companyCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_IndustryCodes:
Packit f574b8
	    buf = readString(&industryCodes, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(docID);
Packit f574b8
	    s_free(stockCodes);
Packit f574b8
	    s_free(companyCodes);
Packit f574b8
	    s_free(industryCodes);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    *docCodes = makeWAISDocumentCodes(docID, versionNumber, stockCodes,
Packit f574b8
				      companyCodes, industryCodes);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writePresentInfo(PresentAPDU * present GCC_UNUSED, char *buffer,
Packit f574b8
		       long *len GCC_UNUSED)
Packit f574b8
{
Packit f574b8
    /* The WAIS protocol doesn't use present info */
Packit f574b8
    return (buffer);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readPresentInfo(void **info,
Packit f574b8
		      char *buffer)
Packit f574b8
{
Packit f574b8
    /* The WAIS protocol doesn't use present info */
Packit f574b8
    *info = NULL;
Packit f574b8
    return (buffer);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writePresentResponseInfo(PresentResponseAPDU * response GCC_UNUSED, char *buffer,
Packit f574b8
			       long *len GCC_UNUSED)
Packit f574b8
{
Packit f574b8
    /* The WAIS protocol doesn't use presentResponse info */
Packit f574b8
    return (buffer);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readPresentResponseInfo(void **info,
Packit f574b8
			      char *buffer)
Packit f574b8
{
Packit f574b8
    /* The WAIS protocol doesn't use presentResponse info */
Packit f574b8
    *info = NULL;
Packit f574b8
    return (buffer);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* support for type 1 queries */
Packit f574b8
Packit f574b8
/* new use values (for the chunk types) */
Packit f574b8
#define	BYTE		"wb"
Packit f574b8
#define	LINE		"wl"
Packit f574b8
#define	PARAGRAPH	"wp"
Packit f574b8
#define DATA_TYPE	"wt"
Packit f574b8
Packit f574b8
/* WAIS supports the following semantics for type 1 queries:
Packit f574b8
Packit f574b8
     1.  retrieve the header/codes from a document:
Packit f574b8
Packit f574b8
	    System_Control_Number = docID
Packit f574b8
	    Data Type = type (optional)
Packit f574b8
	    And
Packit f574b8
Packit f574b8
     2.  retrieve a fragment of the text of a document:
Packit f574b8
Packit f574b8
	    System_Control_Number = docID
Packit f574b8
	    Data Type = type (optional)
Packit f574b8
	    And
Packit f574b8
		Chunk >= start
Packit f574b8
		And
Packit f574b8
		Chunk < end
Packit f574b8
		And
Packit f574b8
Packit f574b8
		Information from multiple documents may be requested by using
Packit f574b8
		groups of the above joined by:
Packit f574b8
Packit f574b8
	    OR
Packit f574b8
Packit f574b8
		( XXX does an OR come after every group but the first, or do they
Packit f574b8
	      all come at the end? )
Packit f574b8
Packit f574b8
	( XXX return type could be in the element set)
Packit f574b8
*/
Packit f574b8
Packit f574b8
static query_term **makeWAISQueryTerms(DocObj **docs)
Packit f574b8
/* given a null terminated list of docObjs, construct the appropriate
Packit f574b8
   query of the form given above
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    query_term **terms = NULL;
Packit f574b8
    long numTerms = 0;
Packit f574b8
    DocObj *doc = NULL;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    if (docs == NULL)
Packit f574b8
	return ((query_term **) NULL);
Packit f574b8
Packit f574b8
    terms = (query_term **) s_malloc((size_t) (sizeof(query_term *) * 1));
Packit f574b8
Packit f574b8
    terms[numTerms] = NULL;
Packit f574b8
Packit f574b8
    /* loop through the docs making terms for them all */
Packit f574b8
    for (i = 0, doc = docs[i]; doc != NULL; doc = docs[++i]) {
Packit f574b8
	any *type = NULL;
Packit f574b8
Packit f574b8
	if (doc->Type != NULL)
Packit f574b8
	    type = stringToAny(doc->Type);
Packit f574b8
Packit f574b8
	if (doc->ChunkCode == CT_document)	/* a whole document */
Packit f574b8
	{
Packit f574b8
	    terms = S_REALLOC2(query_term *, terms, numTerms + 2);
Packit f574b8
Packit f574b8
	    terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
Packit f574b8
						  EQUAL, IGNORE, IGNORE,
Packit f574b8
						  IGNORE, IGNORE, doc->DocumentID);
Packit f574b8
	    if (type != NULL) {
Packit f574b8
		terms[numTerms++] = makeAttributeTerm(DATA_TYPE, EQUAL,
Packit f574b8
						      IGNORE, IGNORE, IGNORE,
Packit f574b8
						      IGNORE, type);
Packit f574b8
		terms[numTerms++] = makeOperatorTerm(AND);
Packit f574b8
	    }
Packit f574b8
	    terms[numTerms] = NULL;
Packit f574b8
	} else {		/* a document fragment */
Packit f574b8
	    char chunk_att[ATTRIBUTE_SIZE];
Packit f574b8
	    any *startChunk = NULL;
Packit f574b8
	    any *endChunk = NULL;
Packit f574b8
Packit f574b8
	    terms = S_REALLOC2(query_term *, terms, numTerms + 6);
Packit f574b8
Packit f574b8
	    switch (doc->ChunkCode) {
Packit f574b8
	    case CT_byte:
Packit f574b8
	    case CT_line:
Packit f574b8
		{
Packit f574b8
		    char start[20], end[20];
Packit f574b8
Packit f574b8
		    (doc->ChunkCode == CT_byte) ?
Packit f574b8
			StrNCpy(chunk_att, BYTE, ATTRIBUTE_SIZE) :
Packit f574b8
			StrNCpy(chunk_att, LINE, ATTRIBUTE_SIZE);
Packit f574b8
		    sprintf(start, "%ld", doc->ChunkStart.Pos);
Packit f574b8
		    startChunk = stringToAny(start);
Packit f574b8
		    sprintf(end, "%ld", doc->ChunkEnd.Pos);
Packit f574b8
		    endChunk = stringToAny(end);
Packit f574b8
		}
Packit f574b8
		break;
Packit f574b8
	    case CT_paragraph:
Packit f574b8
		StrNCpy(chunk_att, PARAGRAPH, ATTRIBUTE_SIZE);
Packit f574b8
		startChunk = doc->ChunkStart.ID;
Packit f574b8
		endChunk = doc->ChunkEnd.ID;
Packit f574b8
		break;
Packit f574b8
	    default:
Packit f574b8
		/* error */
Packit f574b8
		break;
Packit f574b8
	    }
Packit f574b8
Packit f574b8
	    terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
Packit f574b8
						  EQUAL, IGNORE, IGNORE,
Packit f574b8
						  IGNORE,
Packit f574b8
						  IGNORE, doc->DocumentID);
Packit f574b8
	    if (type != NULL) {
Packit f574b8
		terms[numTerms++] = makeAttributeTerm(DATA_TYPE, EQUAL, IGNORE,
Packit f574b8
						      IGNORE, IGNORE, IGNORE,
Packit f574b8
						      type);
Packit f574b8
		terms[numTerms++] = makeOperatorTerm(AND);
Packit f574b8
	    }
Packit f574b8
	    terms[numTerms++] = makeAttributeTerm(chunk_att,
Packit f574b8
						  GREATER_THAN_OR_EQUAL,
Packit f574b8
						  IGNORE, IGNORE, IGNORE,
Packit f574b8
						  IGNORE,
Packit f574b8
						  startChunk);
Packit f574b8
	    terms[numTerms++] = makeOperatorTerm(AND);
Packit f574b8
	    terms[numTerms++] = makeAttributeTerm(chunk_att, LESS_THAN,
Packit f574b8
						  IGNORE, IGNORE, IGNORE,
Packit f574b8
						  IGNORE,
Packit f574b8
						  endChunk);
Packit f574b8
	    terms[numTerms++] = makeOperatorTerm(AND);
Packit f574b8
	    terms[numTerms] = NULL;
Packit f574b8
Packit f574b8
	    if (doc->ChunkCode == CT_byte || doc->ChunkCode == CT_line) {
Packit f574b8
		freeAny(startChunk);
Packit f574b8
		freeAny(endChunk);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
Packit f574b8
	freeAny(type);
Packit f574b8
Packit f574b8
	if (i != 0)		/* multiple independent queries, need a disjunction */
Packit f574b8
	{
Packit f574b8
	    terms = S_REALLOC2(query_term *, terms, numTerms);
Packit f574b8
Packit f574b8
	    terms[numTerms++] = makeOperatorTerm(OR);
Packit f574b8
	    terms[numTerms] = NULL;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (terms);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static DocObj **makeWAISQueryDocs(query_term **terms)
Packit f574b8
/* given a list of terms in the form given above, convert them to
Packit f574b8
   DocObjs.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    query_term *docTerm = NULL;
Packit f574b8
    query_term *fragmentTerm = NULL;
Packit f574b8
    DocObj **docs = NULL;
Packit f574b8
    DocObj *doc = NULL;
Packit f574b8
    long docNum, termNum;
Packit f574b8
Packit f574b8
    docNum = termNum = 0;
Packit f574b8
Packit f574b8
    docs = S_MALLOC(DocObj *);
Packit f574b8
Packit f574b8
    docs[docNum] = NULL;
Packit f574b8
Packit f574b8
    /* translate the terms into DocObjs */
Packit f574b8
    while (true) {
Packit f574b8
	query_term *typeTerm = NULL;
Packit f574b8
	char *type = NULL;
Packit f574b8
	long startTermOffset;
Packit f574b8
Packit f574b8
	docTerm = terms[termNum];
Packit f574b8
Packit f574b8
	if (docTerm == NULL)
Packit f574b8
	    break;		/* we're done converting */
Packit f574b8
Packit f574b8
	typeTerm = terms[termNum + 1];	/* get the lead Term if it exists */
Packit f574b8
Packit f574b8
	if (strcmp(typeTerm->Use, DATA_TYPE) == 0)	/* we do have a type */
Packit f574b8
	{
Packit f574b8
	    startTermOffset = 3;
Packit f574b8
	    type = anyToString(typeTerm->Term);
Packit f574b8
	} else {		/* no type */
Packit f574b8
	    startTermOffset = 1;
Packit f574b8
	    typeTerm = NULL;
Packit f574b8
	    type = NULL;
Packit f574b8
	}
Packit f574b8
Packit f574b8
	/* grow the doc list */
Packit f574b8
	docs = S_REALLOC2(DocObj *, docs, docNum);
Packit f574b8
Packit f574b8
	/* figure out what kind of docObj to build - and build it */
Packit f574b8
	fragmentTerm = terms[termNum + startTermOffset];
Packit f574b8
	if (fragmentTerm != NULL && fragmentTerm->TermType == TT_Attribute) {	/* build a document fragment */
Packit f574b8
	    query_term *startTerm = fragmentTerm;
Packit f574b8
	    query_term *endTerm = terms[termNum + startTermOffset + 2];
Packit f574b8
Packit f574b8
	    if (strcmp(startTerm->Use, BYTE) == 0) {	/* a byte chunk */
Packit f574b8
		doc = makeDocObjUsingBytes(duplicateAny(docTerm->Term),
Packit f574b8
					   type,
Packit f574b8
					   anyToLong(startTerm->Term),
Packit f574b8
					   anyToLong(endTerm->Term));
Packit f574b8
		log_write("byte");
Packit f574b8
	    } else if (strcmp(startTerm->Use, LINE) == 0) {	/* a line chunk */
Packit f574b8
		doc = makeDocObjUsingLines(duplicateAny(docTerm->Term),
Packit f574b8
					   type,
Packit f574b8
					   anyToLong(startTerm->Term),
Packit f574b8
					   anyToLong(endTerm->Term));
Packit f574b8
		log_write("line");
Packit f574b8
	    } else {
Packit f574b8
		log_write("chunk");	/* a paragraph chunk */
Packit f574b8
		doc = makeDocObjUsingParagraphs(duplicateAny(docTerm->Term),
Packit f574b8
						type,
Packit f574b8
						duplicateAny(startTerm->Term),
Packit f574b8
						duplicateAny(endTerm->Term));
Packit f574b8
	    }
Packit f574b8
	    termNum += (startTermOffset + 4);	/* point to next term */
Packit f574b8
	} else {		/* build a full document */
Packit f574b8
	    doc = makeDocObjUsingWholeDocument(duplicateAny(docTerm->Term),
Packit f574b8
					       type);
Packit f574b8
	    log_write("whole doc");
Packit f574b8
	    termNum += startTermOffset;		/* point to next term */
Packit f574b8
	}
Packit f574b8
Packit f574b8
	docs[docNum++] = doc;	/* insert the new document */
Packit f574b8
Packit f574b8
	docs[docNum] = NULL;	/* keep the doc list terminated */
Packit f574b8
Packit f574b8
	if (terms[termNum] != NULL)
Packit f574b8
	    termNum++;		/* skip the OR operator it necessary */
Packit f574b8
	else
Packit f574b8
	    break;		/* we are done */
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (docs);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
any *makeWAISTextQuery(DocObj **docs)
Packit f574b8
/* given a list of DocObjs, return an any whose contents is the corresponding
Packit f574b8
   type 1 query
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    any *buf = NULL;
Packit f574b8
    query_term **terms = NULL;
Packit f574b8
Packit f574b8
    terms = makeWAISQueryTerms(docs);
Packit f574b8
    buf = writeQuery(terms);
Packit f574b8
Packit f574b8
    doList((void **) terms, freeTerm);
Packit f574b8
    s_free(terms);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
DocObj **readWAISTextQuery(any *buf)
Packit f574b8
/* given an any whose contents are type 1 queries of the WAIS sort,
Packit f574b8
   construct a list of the corresponding DocObjs
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    query_term **terms = NULL;
Packit f574b8
    DocObj **docs = NULL;
Packit f574b8
Packit f574b8
    terms = readQuery(buf);
Packit f574b8
    docs = makeWAISQueryDocs(terms);
Packit f574b8
Packit f574b8
    doList((void **) terms, freeTerm);
Packit f574b8
    s_free(terms);
Packit f574b8
Packit f574b8
    return (docs);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
/* Customized free WAIS object routines:                                */
Packit f574b8
/*                                                                      */
Packit f574b8
/*   This set of procedures is for applications to free a WAIS object   */
Packit f574b8
/*   which was made with makeWAISFOO.                                   */
Packit f574b8
/*   Each procedure frees only the memory that was allocated in its     */
Packit f574b8
/*   associated makeWAISFOO routine, thus it's not necessary for the    */
Packit f574b8
/*   caller to assign nulls to the pointer fields of the WAIS object.  */
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISInitResponse(WAISInitResponse *init)
Packit f574b8
/* free an object made with makeWAISInitResponse */
Packit f574b8
{
Packit f574b8
    s_free(init);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISSearch(WAISSearch *query)
Packit f574b8
/* destroy an object made with makeWAISSearch() */
Packit f574b8
{
Packit f574b8
    s_free(query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeDocObj(DocObj *doc)
Packit f574b8
/* free a docObj */
Packit f574b8
{
Packit f574b8
    s_free(doc);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocumentHeader(WAISDocumentHeader *header)
Packit f574b8
{
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocumentShortHeader(WAISDocumentShortHeader *header)
Packit f574b8
{
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocumentLongHeader(WAISDocumentLongHeader *header)
Packit f574b8
{
Packit f574b8
    s_free(header);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISSearchResponse(WAISSearchResponse * response)
Packit f574b8
{
Packit f574b8
    s_free(response);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocumentText(WAISDocumentText *docText)
Packit f574b8
{
Packit f574b8
    s_free(docText);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocHeadlines(WAISDocumentHeadlines *docHeadline)
Packit f574b8
{
Packit f574b8
    s_free(docHeadline);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISDocumentCodes(WAISDocumentCodes *docCodes)
Packit f574b8
{
Packit f574b8
    s_free(docCodes);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void CSTFreeWAISTextQuery(any *query)
Packit f574b8
{
Packit f574b8
    freeAny(query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from WMessage.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 * 3.26.90
Packit f574b8
 */
Packit f574b8
Packit f574b8
/* This file is for reading and writing the wais packet header.
Packit f574b8
 * Morris@think.com
Packit f574b8
 */
Packit f574b8
Packit f574b8
/* to do:
Packit f574b8
 *  add check sum
Packit f574b8
 *  what do you do when checksum is wrong?
Packit f574b8
 */
Packit f574b8
Packit f574b8
/*---------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void readWAISPacketHeader(char *msgBuffer,
Packit f574b8
			  WAISMessage * header_struct)
Packit f574b8
{
Packit f574b8
    /* msgBuffer is a string containing at least HEADER_LENGTH bytes. */
Packit f574b8
Packit f574b8
    memmove(header_struct->msg_len, msgBuffer, (size_t) 10);
Packit f574b8
    header_struct->msg_type = char_downcase((unsigned long) msgBuffer[10]);
Packit f574b8
    header_struct->hdr_vers = char_downcase((unsigned long) msgBuffer[11]);
Packit f574b8
    memmove(header_struct->server, (void *) (msgBuffer + 12), (size_t) 10);
Packit f574b8
    header_struct->compression = char_downcase((unsigned long) msgBuffer[22]);
Packit f574b8
    header_struct->encoding = char_downcase((unsigned long) msgBuffer[23]);
Packit f574b8
    header_struct->msg_checksum = char_downcase((unsigned long) msgBuffer[24]);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*---------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* this modifies the header argument.  See wais-message.h for the different
Packit f574b8
 * options for the arguments.
Packit f574b8
 */
Packit f574b8
Packit f574b8
void writeWAISPacketHeader(char *header,
Packit f574b8
			   long dataLen,
Packit f574b8
			   long type,
Packit f574b8
			   char *server,
Packit f574b8
			   long compression,
Packit f574b8
			   long encoding,
Packit f574b8
			   long version)
Packit f574b8
/* Puts together the new wais before-the-z39-packet header. */
Packit f574b8
{
Packit f574b8
    char lengthBuf[11];
Packit f574b8
    char serverBuf[11];
Packit f574b8
Packit f574b8
    long serverLen = strlen(server);
Packit f574b8
Packit f574b8
    if (serverLen > 10)
Packit f574b8
	serverLen = 10;
Packit f574b8
Packit f574b8
    sprintf(lengthBuf, "%010ld", dataLen);
Packit f574b8
    StrNCpy(header, lengthBuf, 10);
Packit f574b8
Packit f574b8
    header[10] = type & 0xFF;
Packit f574b8
    header[11] = version & 0xFF;
Packit f574b8
Packit f574b8
    StrNCpy(serverBuf, server, serverLen);
Packit f574b8
    StrNCpy((char *) (header + 12), serverBuf, serverLen);
Packit f574b8
Packit f574b8
    header[22] = compression & 0xFF;
Packit f574b8
    header[23] = encoding & 0xFF;
Packit f574b8
    header[24] = '0';		/* checkSum(header + HEADER_LENGTH,dataLen);   XXX the result must be ascii */
Packit f574b8
}
Packit f574b8
Packit f574b8
/*---------------------------------------------------------------------*/