X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=ir-tcl.c;h=66eebf379ded6abb842aab770e0818d6896c63f1;hb=cdd0717baa6ed75b645c1c0bcabec5fa59335cf3;hp=d24437f1ead058cd89d23b7aad9e0be5a20fad94;hpb=47a7d820033bfdf3334f209cb4b4c17aca8bdd92;p=ir-tcl-moved-to-github.git diff --git a/ir-tcl.c b/ir-tcl.c index d24437f..66eebf3 100644 --- a/ir-tcl.c +++ b/ir-tcl.c @@ -1,11 +1,42 @@ /* * IR toolkit for tcl/tk - * (c) Index Data 1995-1998 + * (c) Index Data 1995-1999 * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * * $Log: ir-tcl.c,v $ - * Revision 1.104 1998-02-27 14:26:07 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. * @@ -372,7 +403,7 @@ #include #include -#ifdef WINDOWS +#ifdef WIN32 #else #include @@ -469,6 +500,17 @@ static void delete_IR_record (IrTcl_RecordList *rl) 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) @@ -650,13 +692,14 @@ int ir_tcl_named_bits (struct ir_named_entry *tab, Odr_bitmask *ob, 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); @@ -2190,6 +2233,36 @@ static int do_presentResponse (void *o, Tcl_Interp *interp, } /* + * 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, @@ -2232,6 +2305,35 @@ static int do_presentStatus (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) */ @@ -2613,7 +2715,7 @@ static int do_getExplain (void *o, Tcl_Interp *interp, int argc, char **argv) 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, (char **) &rr, 0)) + if (!(*etype->fun)(p->odr_in, (char **) &rr, 0, 0)) return TCL_OK; if (etype->what != Z_External_explainRecord) @@ -2900,6 +3002,171 @@ static int do_saveFile (void *o, Tcl_Interp *interp, } +/* ------------------------------------------------------- */ +/* + * 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}, @@ -2922,6 +3189,9 @@ static IrTcl_Method ir_set_method_tab[] = { { "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} }; @@ -3329,8 +3599,7 @@ static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv) } 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) { @@ -3482,6 +3751,18 @@ static int ir_log_proc (ClientData clientData, Tcl_Interp *interp, } +/* + * 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) { @@ -3545,7 +3826,7 @@ static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_num, Z_DiagRec **list, int num) { int i; - char *addinfo; + char *addinfo = NULL; *dst_num = num; *dst_list = ir_tcl_malloc (sizeof(**dst_list) * num); @@ -3556,7 +3837,19 @@ static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_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); @@ -3576,7 +3869,8 @@ static void ir_handleDBRecord (IrTcl_Obj *p, IrTcl_RecordList *rl, { 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; @@ -3593,8 +3887,11 @@ static void ir_handleDBRecord (IrTcl_Obj *p, IrTcl_RecordList *rl, odr_setbuf (p->odr_in, (char*) oe->u.octet_aligned->buf, oe->u.octet_aligned->len, 0); - if (!(*etype->fun)(p->odr_in, (char **) &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: @@ -3703,12 +4000,19 @@ static void ir_handleZRecords (void *o, Z_Records *zrs, IrTcl_SetObj *setobj, } 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); } } @@ -3723,11 +4027,13 @@ static void ir_searchResponse (void *o, Z_SearchResponse *searchrs, 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; @@ -3805,67 +4111,95 @@ static void ir_scanResponse (void *o, Z_ScanResponse *scanrs, 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; inum_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; inum_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 } /* @@ -3945,7 +4279,7 @@ static void ir_select_read (ClientData clientData) 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))); @@ -4000,6 +4334,13 @@ static void ir_select_read (ClientData clientData) 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); @@ -4159,6 +4500,8 @@ EXPORT (int,Irtcl_Init) (Tcl_Interp *interp) (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; }