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