/*
* IR toolkit for tcl/tk
- * (c) Index Data 1995-1997
+ * (c) Index Data 1995-1999
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: ir-tcl.c,v $
- * Revision 1.103 1997-11-19 11:22:10 adam
+ * Revision 1.114 1999-05-17 20:37:41 adam
+ * Fixed problem with ASN code.
+ *
+ * Revision 1.113 1999/04/20 10:01:46 adam
+ * Modified calls to ODR encoders/decoders (name argument).
+ *
+ * Revision 1.112 1999/03/22 06:51:34 adam
+ * Implemented sort.
+ *
+ * Revision 1.111 1999/02/11 11:30:09 adam
+ * Updated for WIN32.
+ *
+ * Revision 1.110 1998/10/20 15:15:31 adam
+ * Changed scan response handler.
+ *
+ * Revision 1.109 1998/10/13 21:23:26 adam
+ * Fixed searchStatus method.
+ *
+ * Revision 1.108 1998/10/12 11:48:08 adam
+ * Removed printf call.
+ *
+ * Revision 1.107 1998/06/10 13:00:46 adam
+ * Added ir-version command.
+ *
+ * Revision 1.106 1998/05/20 12:25:35 adam
+ * Fixed bug that occurred in rare cases when encoding of incoming
+ * records failed.
+ *
+ * Revision 1.105 1998/04/02 14:31:08 adam
+ * This version works with compiled ASN.1 code.
+ *
+ * Revision 1.104 1998/02/27 14:26:07 adam
+ * Changed client so that it still works if target sets numberOfRecords
+ * in response to an illegal value.
+ *
+ * Revision 1.103 1997/11/19 11:22:10 adam
* Object identifiers can be accessed in GRS-1 records.
*
* Revision 1.102 1997/09/17 12:22:40 adam
#include <stdlib.h>
#include <stdio.h>
-#ifdef WINDOWS
+#ifdef WIN32
#else
#include <unistd.h>
xfree (rl->elements);
}
+static void purge_IR_records (IrTcl_SetObj *setobj)
+{
+ IrTcl_RecordList *rl;
+ while ((rl = setobj->record_list))
+ {
+ setobj->record_list = rl->next;
+ delete_IR_record (rl);
+ xfree (rl);
+ }
+}
+
static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj,
int no, int which,
const char *elements)
ODR_MASK_ZERO (ob);
for (no = 0; no < argc; no++)
{
+ int ok = 0;
for (ti = tab; ti->name; ti++)
- if (!strcmp (argv[no], ti->name))
+ if (!strcmp(argv[no], "@all") || !strcmp (argv[no], ti->name))
{
ODR_MASK_SET (ob, ti->pos);
- break;
+ ok = 1;
}
- if (!ti->name)
+ if (!ok)
{
Tcl_AppendResult (interp, "bad bit mask ", argv[no], NULL);
return ir_tcl_error_exec (interp, argc, argv);
}
/*
+ * do_sortResponse: add sort response handler
+ */
+static int do_sortResponse (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->sortResponse = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->sortResponse);
+ if (argc == 3)
+ {
+ xfree (obj->sortResponse);
+ if (argv[2][0])
+ {
+ if (ir_tcl_strdup (interp, &obj->sortResponse, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ obj->sortResponse = NULL;
+ }
+ return TCL_OK;
+}
+
+/*
* do_resultCount: Get number of hits
*/
static int do_resultCount (void *o, Tcl_Interp *interp,
}
/*
+ * do_sortStatus: Get sort status (after sort response)
+ */
+static int do_sortStatus (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ char *res;
+
+ if (argc <= 0)
+ {
+ obj->sortStatus = Z_SortStatus_failure;
+ return TCL_OK;
+ }
+ switch (obj->sortStatus)
+ {
+ case Z_SortStatus_success:
+ res = "success"; break;
+ case Z_SortStatus_partial_1:
+ res = "partial"; break;
+ case Z_SortStatus_failure:
+ res = "failure"; break;
+ default:
+ res = "unknown"; break;
+ }
+ Tcl_AppendElement (interp, res);
+ return TCL_OK;
+}
+
+/*
* do_nextResultSetPosition: Get next result set position
* (after search/present response)
*/
return TCL_OK;
assert (rl->u.dbrec.buf);
odr_setbuf (p->odr_in, rl->u.dbrec.buf, rl->u.dbrec.size, 0);
- if (!(*etype->fun)(p->odr_in, &rr, 0))
+ if (!(*etype->fun)(p->odr_in, (char **) &rr, 0, 0))
return TCL_OK;
if (etype->what != Z_External_explainRecord)
}
+/* ------------------------------------------------------- */
+/*
+ * do_sort: Do sort request
+ */
+static int do_sort (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ Z_SortRequest *req;
+ Z_APDU *apdu;
+ IrTcl_SetObj *obj = o;
+ IrTcl_Obj *p;
+ char sort_string[64], sort_flags[64];
+ char *arg;
+ int off;
+ Z_SortKeySpecList *sksl;
+ int oid[OID_SIZE];
+ oident bib1;
+
+ if (argc <= 0)
+ return TCL_OK;
+
+ p = obj->parent;
+ assert (argc > 1);
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1], "query\"",
+ NULL);
+ return TCL_ERROR;
+ }
+ logf (LOG_DEBUG, "sort %s %s", *argv, argv[2]);
+ if (!p->cs_link)
+ {
+ Tcl_AppendResult (interp, "not connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ apdu = zget_APDU (p->odr_out, Z_APDU_sortRequest);
+ sksl = (Z_SortKeySpecList *) odr_malloc (p->odr_out, sizeof(*sksl));
+ req = apdu->u.sortRequest;
+
+ set_referenceId (p->odr_out, &req->referenceId,
+ obj->set_inher.referenceId);
+
+#ifdef ASN_COMPILED
+ req->num_inputResultSetNames = 1;
+ req->inputResultSetNames = (Z_InternationalString **)
+ odr_malloc (p->odr_out, sizeof(*req->inputResultSetNames));
+ req->inputResultSetNames[0] = obj->setName;
+#else
+ req->inputResultSetNames =
+ (Z_StringList *)odr_malloc (p->odr_out,
+ sizeof(*req->inputResultSetNames));
+ req->inputResultSetNames->num_strings = 1;
+ req->inputResultSetNames->strings =
+ (char **)odr_malloc (p->odr_out,
+ sizeof(*req->inputResultSetNames->strings));
+ req->inputResultSetNames->strings[0] = obj->setName;
+#endif
+
+ req->sortedResultSetName = (char *) obj->setName;
+
+
+ req->sortSequence = sksl;
+ sksl->num_specs = 0;
+ sksl->specs = (Z_SortKeySpec **)
+ odr_malloc (p->odr_out, sizeof(sksl->specs) * 20);
+
+ bib1.proto = PROTO_Z3950;
+ bib1.oclass = CLASS_ATTSET;
+ bib1.value = VAL_BIB1;
+ arg = argv[2];
+ while ((sscanf (arg, "%63s %63s%n", sort_string, sort_flags, &off)) == 2
+ && off > 1)
+ {
+ int i;
+ char *sort_string_sep;
+ Z_SortKeySpec *sks = (Z_SortKeySpec *)
+ odr_malloc (p->odr_out, sizeof(*sks));
+ Z_SortKey *sk = (Z_SortKey *)
+ odr_malloc (p->odr_out, sizeof(*sk));
+
+ arg += off;
+ sksl->specs[sksl->num_specs++] = sks;
+ sks->sortElement = (Z_SortElement *)
+ odr_malloc (p->odr_out, sizeof(*sks->sortElement));
+ sks->sortElement->which = Z_SortElement_generic;
+ sks->sortElement->u.generic = sk;
+
+ if ((sort_string_sep = strchr (sort_string, '=')))
+ {
+ Z_AttributeElement *el = (Z_AttributeElement *)
+ odr_malloc (p->odr_out, sizeof(*el));
+ sk->which = Z_SortKey_sortAttributes;
+ sk->u.sortAttributes =
+ (Z_SortAttributes *)
+ odr_malloc (p->odr_out, sizeof(*sk->u.sortAttributes));
+ sk->u.sortAttributes->id = oid_ent_to_oid(&bib1, oid);
+ sk->u.sortAttributes->list =
+ (Z_AttributeList *)
+ odr_malloc (p->odr_out, sizeof(*sk->u.sortAttributes->list));
+ sk->u.sortAttributes->list->num_attributes = 1;
+ sk->u.sortAttributes->list->attributes =
+ (Z_AttributeElement **)odr_malloc (p->odr_out,
+ sizeof(*sk->u.sortAttributes->list->attributes));
+ sk->u.sortAttributes->list->attributes[0] = el;
+ el->attributeSet = 0;
+ el->attributeType = (int *)
+ odr_malloc (p->odr_out, sizeof(*el->attributeType));
+ *el->attributeType = atoi (sort_string);
+ el->which = Z_AttributeValue_numeric;
+ el->value.numeric = (int *)
+ odr_malloc (p->odr_out, sizeof(*el->value.numeric));
+ *el->value.numeric = atoi (sort_string_sep + 1);
+ }
+ else
+ {
+ sk->which = Z_SortKey_sortField;
+ sk->u.sortField = (char *)odr_malloc (p->odr_out, strlen(sort_string)+1);
+ strcpy (sk->u.sortField, sort_string);
+ }
+ sks->sortRelation = (int *)
+ odr_malloc (p->odr_out, sizeof(*sks->sortRelation));
+ *sks->sortRelation = Z_SortRelation_ascending;
+ sks->caseSensitivity = (int *)
+ odr_malloc (p->odr_out, sizeof(*sks->caseSensitivity));
+ *sks->caseSensitivity = Z_SortCase_caseSensitive;
+
+#ifdef ASN_COMPILED
+ sks->which = Z_SortKeySpec_null;
+ sks->u.null = odr_nullval ();
+#else
+ sks->missingValueAction = NULL;
+#endif
+
+ for (i = 0; sort_flags[i]; i++)
+ {
+ switch (sort_flags[i])
+ {
+ case 'a':
+ case 'A':
+ case '>':
+ *sks->sortRelation = Z_SortRelation_descending;
+ break;
+ case 'd':
+ case 'D':
+ case '<':
+ *sks->sortRelation = Z_SortRelation_ascending;
+ break;
+ case 'i':
+ case 'I':
+ *sks->caseSensitivity = Z_SortCase_caseInsensitive;
+ break;
+ case 'S':
+ case 's':
+ *sks->caseSensitivity = Z_SortCase_caseSensitive;
+ break;
+ }
+ }
+ }
+ if (!sksl->num_specs)
+ {
+ printf ("Missing sort specifications\n");
+ return -1;
+ }
+ return ir_tcl_send_APDU (interp, p, apdu, "sort", *argv);
+}
+
static IrTcl_Method ir_set_method_tab[] = {
{ "search", do_search, NULL},
{ "searchResponse", do_searchResponse, NULL},
{ "responseStatus", do_responseStatus, NULL},
{ "loadFile", do_loadFile, NULL},
{ "saveFile", do_saveFile, NULL},
+ { "sort", do_sort, NULL },
+ { "sortResponse", do_sortResponse, NULL},
+ { "sortStatus", do_sortStatus, NULL},
{ NULL, NULL}
};
}
if (Tcl_GetInt (interp, argv[2], &i) == TCL_ERROR)
return TCL_ERROR;
- if (!p->entries_flag || p->which != Z_ListEntries_entries || !p->entries
- || i >= p->num_entries || i < 0)
+ if (!p->entries_flag || !p->entries || i >= p->num_entries || i < 0)
return TCL_OK;
switch (p->entries[i].which)
{
}
+/*
+ * ir_version: log ir version
+ */
+static int ir_version (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ Tcl_AppendElement (interp, IR_TCL_VERSION);
+ Tcl_AppendElement (interp, YAZ_VERSION);
+ return TCL_OK;
+}
+
+
/* ------------------------------------------------------- */
static void ir_initResponse (void *obj, Z_InitResponse *initrs)
{
Z_DiagRec **list, int num)
{
int i;
- char *addinfo;
+ char *addinfo = NULL;
*dst_num = num;
*dst_list = ir_tcl_malloc (sizeof(**dst_list) * num);
{
case Z_DiagRec_defaultFormat:
(*dst_list)[i].condition = *list[i]->u.defaultFormat->condition;
+#ifdef ASN_COMPILED
+ switch (list[i]->u.defaultFormat->which)
+ {
+ case Z_DefaultDiagFormat_v2Addinfo:
+ addinfo = list[i]->u.defaultFormat->u.v2Addinfo;
+ break;
+ case Z_DefaultDiagFormat_v3Addinfo:
+ addinfo = list[i]->u.defaultFormat->u.v3Addinfo;
+ break;
+ }
+#else
addinfo = list[i]->u.defaultFormat->addinfo;
+#endif
if (addinfo &&
((*dst_list)[i].addinfo = ir_tcl_malloc (strlen(addinfo)+1)))
strcpy ((*dst_list)[i].addinfo, addinfo);
{
struct oident *ident;
Z_ext_typeent *etype;
-
+
+ logf (LOG_DEBUG, "handleDBRecord size=%d", oe->u.octet_aligned->len);
rl->u.dbrec.size = oe->u.octet_aligned->len;
rl->u.dbrec.buf = NULL;
odr_setbuf (p->odr_in, (char*) oe->u.octet_aligned->buf,
oe->u.octet_aligned->len, 0);
- if (!(*etype->fun)(p->odr_in, &rr, 0))
+ if (!(*etype->fun)(p->odr_in, (char **) &rr, 0, 0))
+ {
+ rl->u.dbrec.type = VAL_NONE;
return;
+ }
switch (etype->what)
{
case Z_External_sutrs:
&setobj->nonSurrogateDiagnosticNum);
if (zrs->which == Z_Records_DBOSD)
{
- int num_rec = setobj->numberOfRecordsReturned;
+ int num_rec = zrs->u.databaseOrSurDiagnostics->num_records;
+
+ if (num_rec != setobj->numberOfRecordsReturned)
+ {
+ logf (LOG_WARN, "numberOfRecordsReturned=%d but num records=%d",
+ setobj->numberOfRecordsReturned, num_rec);
+ setobj->numberOfRecordsReturned = num_rec;
+ }
- if (num_rec > zrs->u.databaseOrSurDiagnostics->num_records)
- num_rec = zrs->u.databaseOrSurDiagnostics->num_records;
- logf (LOG_DEBUG, "Got %d records", num_rec);
for (offset = 0; offset < num_rec; offset++)
{
Z_NamePlusRecord *znpr = zrs->u.databaseOrSurDiagnostics->
}
else
{
+#ifdef ASN_COMPILED
+ Z_DiagRec dr, *dr_p = &dr;
+ dr.which = Z_DiagRec_defaultFormat;
+ dr.u.defaultFormat = zrs->u.nonSurrogateDiagnostic;
+#else
+ Z_DiagRec *dr_p = zrs->u.nonSurrogateDiagnostic;
+#endif
logf (LOG_DEBUG, "NonSurrogateDiagnostic");
+
setobj->numberOfRecordsReturned = 0;
ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
&setobj->nonSurrogateDiagnosticNum,
- &zrs->u.nonSurrogateDiagnostic,
- 1);
+ &dr_p, 1);
}
}
logf (LOG_DEBUG, "Search response, no object!");
return;
}
- setobj->searchStatus = searchrs->searchStatus ? 1 : 0;
+ setobj->searchStatus = *searchrs->searchStatus;
get_referenceId (&setobj->set_inher.referenceId, searchrs->referenceId);
setobj->resultCount = *searchrs->resultCount;
if (searchrs->presentStatus)
setobj->presentStatus = *searchrs->presentStatus;
+ else
+ setobj->presentStatus = Z_RES_NONE;
if (searchrs->nextResultSetPosition)
setobj->nextResultSetPosition = *searchrs->nextResultSetPosition;
xfree (scanobj->entries);
scanobj->entries = NULL;
-
+ scanobj->num_entries = 0;
+ scanobj->entries_flag = 0;
+
ir_deleteDiags (&scanobj->nonSurrogateDiagnosticList,
&scanobj->nonSurrogateDiagnosticNum);
if (scanrs->entries)
{
int i;
- Z_Entry *ze;
+ Z_Entry **ze;
scanobj->entries_flag = 1;
- scanobj->which = scanrs->entries->which;
- switch (scanobj->which)
- {
- case Z_ListEntries_entries:
- scanobj->num_entries = scanrs->entries->u.entries->num_entries;
+ if (scanrs->entries)
+ {
+ scanobj->num_entries = scanrs->entries->num_entries;
scanobj->entries = ir_tcl_malloc (scanobj->num_entries *
- sizeof(*scanobj->entries));
- for (i=0; i<scanobj->num_entries; i++)
- {
- ze = scanrs->entries->u.entries->entries[i];
- scanobj->entries[i].which = ze->which;
- switch (ze->which)
- {
- case Z_Entry_termInfo:
- if (ze->u.termInfo->term->which == Z_Term_general)
- {
- int l = ze->u.termInfo->term->u.general->len;
- scanobj->entries[i].u.term.buf = ir_tcl_malloc (1+l);
- memcpy (scanobj->entries[i].u.term.buf,
- ze->u.termInfo->term->u.general->buf,
- l);
- scanobj->entries[i].u.term.buf[l] = '\0';
- }
- else
- scanobj->entries[i].u.term.buf = NULL;
- if (ze->u.termInfo->globalOccurrences)
- scanobj->entries[i].u.term.globalOccurrences =
- *ze->u.termInfo->globalOccurrences;
- else
- scanobj->entries[i].u.term.globalOccurrences = 0;
- break;
- case Z_Entry_surrogateDiagnostic:
- ir_handleDiags (&scanobj->entries[i].u.diag.list,
- &scanobj->entries[i].u.diag.num,
- &ze->u.surrogateDiagnostic,
- 1);
- break;
- }
- }
- break;
- case Z_ListEntries_nonSurrogateDiagnostics:
- ir_handleDiags (&scanobj->nonSurrogateDiagnosticList,
+ sizeof(*scanobj->entries));
+ ze = scanrs->entries->entries;
+ }
+ for (i=0; i<scanobj->num_entries; i++, ze++)
+ {
+ scanobj->entries[i].which = (*ze)->which;
+ switch ((*ze)->which)
+ {
+ case Z_Entry_termInfo:
+ if ((*ze)->u.termInfo->term->which == Z_Term_general)
+ {
+ int l = (*ze)->u.termInfo->term->u.general->len;
+ scanobj->entries[i].u.term.buf = ir_tcl_malloc (1+l);
+ memcpy (scanobj->entries[i].u.term.buf,
+ (*ze)->u.termInfo->term->u.general->buf,
+ l);
+ scanobj->entries[i].u.term.buf[l] = '\0';
+ }
+ else
+ scanobj->entries[i].u.term.buf = NULL;
+ if ((*ze)->u.termInfo->globalOccurrences)
+ scanobj->entries[i].u.term.globalOccurrences =
+ *(*ze)->u.termInfo->globalOccurrences;
+ else
+ scanobj->entries[i].u.term.globalOccurrences = 0;
+ break;
+ case Z_Entry_surrogateDiagnostic:
+ ir_handleDiags (&scanobj->entries[i].u.diag.list,
+ &scanobj->entries[i].u.diag.num,
+ &(*ze)->u.surrogateDiagnostic,
+ 1);
+ break;
+ }
+ }
+ if (scanrs->entries->nonsurrogateDiagnostics)
+ ir_handleDiags (&scanobj->nonSurrogateDiagnosticList,
&scanobj->nonSurrogateDiagnosticNum,
- scanrs->entries->u.nonSurrogateDiagnostics->
- diagRecs,
- scanrs->entries->u.nonSurrogateDiagnostics->
- num_diagRecs);
- break;
- }
+ scanrs->entries->nonsurrogateDiagnostics,
+ scanrs->entries->num_nonsurrogateDiagnostics);
}
- else
- scanobj->entries_flag = 0;
+}
+
+
+static void ir_sortResponse (void *o, Z_SortResponse *sortrs,
+ IrTcl_SetObj *setobj)
+{
+ IrTcl_Obj *p = o;
+
+ logf (LOG_DEBUG, "Received sortResponse");
+
+ if (!setobj)
+ return;
+
+ purge_IR_records (setobj);
+
+ get_referenceId (&p->set_inher.referenceId, sortrs->referenceId);
+
+ setobj->sortStatus = *sortrs->sortStatus;
+
+ ir_deleteDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum);
+#ifdef ASN_COMPILED
+ if (sortrs->diagnostics)
+ ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum,
+ sortrs->diagnostics,
+ sortrs->num_diagnostics);
+#else
+ if (sortrs->diagnostics)
+ ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum,
+ sortrs->diagnostics->diagRecs,
+ sortrs->diagnostics->num_diagRecs);
+#endif
}
/*
p->apduOffset = -1;
odr_setbuf (p->odr_in, p->buf_in, r, 0);
logf (LOG_DEBUG, "cs_get ok, total size %d", r);
- if (!z_APDU (p->odr_in, &apdu, 0))
+ if (!z_APDU (p->odr_in, &apdu, 0, 0))
{
logf (LOG_DEBUG, "cs_get failed: %s",
odr_errmsg (odr_geterror (p->odr_in)));
apdu_call = ((IrTcl_ScanObj *)
cmd_info.clientData)->scanResponse;
break;
+ case Z_APDU_sortResponse:
+ p->eventType = "sort";
+ ir_sortResponse (p, apdu->u.sortResponse,
+ (IrTcl_SetObj *) cmd_info.clientData);
+ apdu_call = ((IrTcl_SetObj *)
+ cmd_info.clientData)->sortResponse;
+ break;
default:
logf (LOG_WARN, "Received unknown APDU type (%d)",
apdu->which);
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand (interp, "ir-log", ir_log_proc,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand (interp, "ir-version", ir_version, (ClientData) NULL,
+ (Tcl_CmdDeleteProc *) NULL);
nmem_init ();
return TCL_OK;
}