+/*
+ * do_databaseNames: specify database names
+ */
+static int do_databaseNames (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ int i;
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == -1)
+ {
+ for (i=0; i<p->num_databaseNames; i++)
+ xfree (p->databaseNames[i]);
+ xfree (p->databaseNames);
+ }
+ if (argc <= 0)
+ {
+ p->num_databaseNames = 0;
+ p->databaseNames = NULL;
+ return TCL_OK;
+ }
+ if (argc < 3)
+ {
+ for (i=0; i<p->num_databaseNames; i++)
+ Tcl_AppendElement (interp, p->databaseNames[i]);
+ return TCL_OK;
+ }
+ if (p->databaseNames)
+ {
+ for (i=0; i<p->num_databaseNames; i++)
+ xfree (p->databaseNames[i]);
+ xfree (p->databaseNames);
+ }
+ p->num_databaseNames = argc - 2;
+ p->databaseNames =
+ ir_tcl_malloc (sizeof(*p->databaseNames) * (1+p->num_databaseNames));
+ for (i=0; i<p->num_databaseNames; i++)
+ {
+ if (ir_tcl_strdup (interp, &p->databaseNames[i], argv[2+i])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ p->databaseNames[i] = NULL;
+ return TCL_OK;
+}
+
+/*
+ * do_replaceIndicator: Set/get replace Set indicator
+ */
+static int do_replaceIndicator (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc <= 0)
+ {
+ p->replaceIndicator = 1;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->replaceIndicator, interp, argc, argv);
+}
+
+/*
+ * do_queryType: Set/Get query method
+ */
+static int do_queryType (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ return ir_tcl_strdup (interp, &p->queryType, "rpn");
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->queryType);
+ if (argc == 3)
+ {
+ xfree (p->queryType);
+ if (ir_tcl_strdup (interp, &p->queryType, argv[2]) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult (interp, p->queryType, NULL);
+ return TCL_OK;
+}
+
+/*
+ * do_userInformationField: Get User information field
+ */
+static int do_userInformationField (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_Obj *p = obj;
+
+ if (argc == 0)
+ {
+ p->userInformationField = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->userInformationField);
+ Tcl_AppendResult (interp, p->userInformationField, NULL);
+ return TCL_OK;
+}
+
+/*
+ * do_smallSetUpperBound: Set/get small set upper bound
+ */
+static int do_smallSetUpperBound (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = o;
+
+ if (argc <= 0)
+ {
+ p->smallSetUpperBound = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->smallSetUpperBound, interp, argc, argv);
+}
+
+/*
+ * do_largeSetLowerBound: Set/get large set lower bound
+ */
+static int do_largeSetLowerBound (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = o;
+
+ if (argc <= 0)
+ {
+ p->largeSetLowerBound = 1;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->largeSetLowerBound, interp, argc, argv);
+}
+
+/*
+ * do_mediumSetPresentNumber: Set/get large set lower bound
+ */
+static int do_mediumSetPresentNumber (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = o;
+
+ if (argc <= 0)
+ {
+ p->mediumSetPresentNumber = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->mediumSetPresentNumber, interp, argc, argv);
+}
+
+/*
+ * do_referenceId: Set/Get referenceId
+ */
+static int do_referenceId (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ {
+ p->referenceId = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->referenceId);
+ if (argc == 3)
+ {
+ xfree (p->referenceId);
+ if (ir_tcl_strdup (interp, &p->referenceId, argv[2]) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult (interp, p->referenceId, NULL);
+ return TCL_OK;
+}
+
+/*
+ * do_preferredRecordSyntax: Set/get preferred record syntax
+ */
+static int do_preferredRecordSyntax (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ {
+ p->preferredRecordSyntax = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ xfree (p->preferredRecordSyntax);
+ p->preferredRecordSyntax = NULL;
+ return TCL_OK;
+ }
+ if (argc == 3)
+ {
+ xfree (p->preferredRecordSyntax);
+ p->preferredRecordSyntax = NULL;
+ if (argv[2][0] && (p->preferredRecordSyntax =
+ ir_tcl_malloc (sizeof(*p->preferredRecordSyntax))))
+ *p->preferredRecordSyntax = IrTcl_getRecordSyntaxVal (argv[2]);
+ }
+ else if (argc == 2)
+ {
+ Tcl_AppendElement
+ (interp,!p->preferredRecordSyntax ? "" :
+ IrTcl_getRecordSyntaxStr(*p->preferredRecordSyntax));
+ }
+ return TCL_OK;
+
+}
+
+/*
+ * do_elementSetNames: Set/Get element Set Names
+ */
+static int do_elementSetNames (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ {
+ p->elementSetNames = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->elementSetNames);
+ if (argc == 3)
+ {
+ xfree (p->elementSetNames);
+ if (ir_tcl_strdup (interp, &p->elementSetNames, argv[2]) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult (interp, p->elementSetNames, NULL);
+ return TCL_OK;
+}
+
+/*
+ * do_smallSetElementSetNames: Set/Get small Set Element Set Names
+ */
+static int do_smallSetElementSetNames (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ {
+ p->smallSetElementSetNames = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->smallSetElementSetNames);
+ if (argc == 3)
+ {
+ xfree (p->smallSetElementSetNames);
+ if (ir_tcl_strdup (interp, &p->smallSetElementSetNames,
+ argv[2]) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult (interp, p->smallSetElementSetNames, NULL);
+ return TCL_OK;
+}
+
+/*
+ * do_mediumSetElementSetNames: Set/Get medium Set Element Set Names
+ */
+static int do_mediumSetElementSetNames (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetCObj *p = obj;
+
+ if (argc == 0)
+ {
+ p->mediumSetElementSetNames = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &p->mediumSetElementSetNames);
+ if (argc == 3)
+ {
+ xfree (p->mediumSetElementSetNames);
+ if (ir_tcl_strdup (interp, &p->mediumSetElementSetNames,
+ argv[2]) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult (interp, p->mediumSetElementSetNames, NULL);
+ return TCL_OK;
+}
+
+static IrTcl_Method ir_method_tab[] = {
+{ "comstack", do_comstack, NULL },
+{ "protocol", do_protocol, NULL },
+{ "failback", do_failback, NULL },
+{ "failInfo", do_failInfo, NULL },
+{ "apduInfo", do_apduInfo, NULL },
+{ "logLevel", do_logLevel, NULL },
+
+{ "eventType", do_eventType, NULL },
+{ "connect", do_connect, NULL },
+{ "protocolVersion", do_protocolVersion, NULL },
+{ "preferredMessageSize", do_preferredMessageSize, NULL },
+{ "maximumRecordSize", do_maximumRecordSize, NULL },
+{ "implementationName", do_implementationName, NULL },
+{ "implementationId", do_implementationId, NULL },
+{ "implementationVersion", do_implementationVersion, NULL },
+{ "targetImplementationName", do_targetImplementationName, NULL },
+{ "targetImplementationId", do_targetImplementationId, NULL },
+{ "targetImplementationVersion", do_targetImplementationVersion, NULL},
+{ "userInformationField", do_userInformationField, NULL},
+{ "idAuthentication", do_idAuthentication, NULL},
+{ "options", do_options, NULL},
+{ "init", do_init_request, NULL},
+{ "initResult", do_initResult, NULL},
+{ "disconnect", do_disconnect, NULL},
+{ "callback", do_callback, NULL},
+{ "initResponse", do_initResponse, NULL},
+{ "triggerResourceControl", do_triggerResourceControl, NULL},
+{ "initResponse", do_initResponse, NULL},
+{ NULL, NULL}
+};
+
+static IrTcl_Method ir_set_c_method_tab[] = {
+{ "databaseNames", do_databaseNames, NULL},
+{ "replaceIndicator", do_replaceIndicator, NULL},
+{ "queryType", do_queryType, NULL},
+{ "preferredRecordSyntax", do_preferredRecordSyntax, NULL},
+{ "smallSetUpperBound", do_smallSetUpperBound, NULL},
+{ "largeSetLowerBound", do_largeSetLowerBound, NULL},
+{ "mediumSetPresentNumber", do_mediumSetPresentNumber, NULL},
+{ "referenceId", do_referenceId, NULL},
+{ "elementSetNames", do_elementSetNames, NULL},
+{ "smallSetElementSetNames", do_smallSetElementSetNames, NULL},
+{ "mediumSetElementSetNames", do_mediumSetElementSetNames, NULL},
+{ NULL, NULL}
+};
+
+/*
+ * ir_obj_method: IR Object methods
+ */
+static int ir_obj_method (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_Methods tab[3];
+ IrTcl_Obj *p = (IrTcl_Obj *) clientData;
+ int r;
+
+ if (argc < 2)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, "method args...\"", NULL);
+ return TCL_ERROR;
+ }
+
+ tab[0].tab = ir_method_tab;
+ tab[0].obj = p;
+ tab[1].tab = ir_set_c_method_tab;
+ tab[1].obj = &p->set_inher;
+ tab[2].tab = NULL;
+
+ if (ir_tcl_method (interp, argc, argv, tab, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tab);
+ return r;
+}
+
+/*
+ * ir_obj_delete: IR Object disposal
+ */
+static void ir_obj_delete (ClientData clientData)
+{
+ IrTcl_Obj *obj = (IrTcl_Obj *) clientData;
+ IrTcl_Methods tab[3];
+
+ --(obj->ref_count);
+ if (obj->ref_count > 0)
+ return;
+ assert (obj->ref_count == 0);
+
+ logf (LOG_DEBUG, "ir object delete");
+ tab[0].tab = ir_method_tab;
+ tab[0].obj = obj;
+ tab[1].tab = ir_set_c_method_tab;
+ tab[1].obj = &obj->set_inher;
+ tab[2].tab = NULL;
+
+ ir_tcl_method (NULL, -1, NULL, tab, NULL);
+
+ ir_tcl_del_q (obj);
+ odr_destroy (obj->odr_in);
+ odr_destroy (obj->odr_out);
+ if (obj->odr_pr)
+ {
+ obj->odr_pr->print = 0;
+ odr_destroy (obj->odr_pr);
+ }
+ xfree (obj);
+}
+
+/*
+ * ir_obj_init: IR Object initialization
+ */
+int ir_obj_init (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv, ClientData *subData,
+ ClientData parentData)
+{
+ IrTcl_Methods tab[3];
+ IrTcl_Obj *obj;
+#if CCL2RPN
+ FILE *inf;
+#endif
+
+ if (argc != 2)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " objName\"", NULL);
+ return TCL_ERROR;
+ }
+ obj = ir_tcl_malloc (sizeof(*obj));
+ obj->ref_count = 1;
+#if CCL2RPN
+ obj->bibset = ccl_qual_mk ();
+ if ((inf = fopen ("default.bib", "r")))
+ {
+ ccl_qual_file (obj->bibset, inf);
+ fclose (inf);
+ }
+#endif
+
+ logf (LOG_DEBUG, "ir object create %s", argv[1]);
+ obj->odr_in = odr_createmem (ODR_DECODE);
+ odr_choice_enable_bias (obj->odr_in, 0);
+ obj->odr_out = odr_createmem (ODR_ENCODE);
+ obj->odr_pr = 0;
+ if (odr_print_file)
+ {
+ obj->odr_pr = odr_createmem (ODR_PRINT);
+ odr_setprint(obj->odr_pr, odr_print_file);
+ }
+ obj->state = IR_TCL_R_Idle;
+ obj->interp = interp;
+
+ obj->len_in = 0;
+ obj->buf_in = NULL;
+ obj->request_queue = NULL;
+
+ tab[0].tab = ir_method_tab;
+ tab[0].obj = obj;
+ tab[1].tab = ir_set_c_method_tab;
+ tab[1].obj = &obj->set_inher;
+ tab[2].tab = NULL;
+
+ if (ir_tcl_method (interp, 0, NULL, tab, NULL) == TCL_ERROR)
+ {
+ Tcl_AppendResult (interp, "Failed to initialize ", argv[1], NULL);
+ return TCL_ERROR;
+ }
+ *subData = (ClientData) obj;
+ return TCL_OK;
+}
+
+
+/*
+ * ir_obj_mk: IR Object creation
+ */
+static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ ClientData subData;
+ int r = ir_obj_init (clientData, interp, argc, argv, &subData, 0);
+
+ if (r == TCL_ERROR)
+ return TCL_ERROR;
+ Tcl_CreateCommand (interp, argv[1], ir_obj_method,
+ subData, ir_obj_delete);
+ return TCL_OK;
+}
+
+IrTcl_Class ir_obj_class = {
+ "ir",
+ ir_obj_init,
+ ir_obj_method,
+ ir_obj_delete
+};
+
+
+/* ------------------------------------------------------- */
+/*
+ * do_search: Do search request
+ */
+static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ Z_SearchRequest *req;
+ Z_Query query;
+ Z_APDU *apdu;
+ Odr_oct ccl_query;
+ IrTcl_SetObj *obj = o;
+ IrTcl_Obj *p;
+ int r, code;
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ Tcl_DString ds;
+#endif
+ char *query_str;
+
+ 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;
+ }
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ query_str = Tcl_UtfToExternalDString(0, argv[2], -1, &ds);
+#else
+ query_str = argv[2];
+#endif
+ logf (LOG_DEBUG, "search %s %s", *argv, query_str);
+ if (!obj->set_inher.num_databaseNames)
+ {
+ Tcl_AppendResult (interp, "no databaseNames", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ if (!p->cs_link)
+ {
+ Tcl_AppendResult (interp, "not connected", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ apdu = zget_APDU (p->odr_out, Z_APDU_searchRequest);
+ req = apdu->u.searchRequest;
+
+ obj->start = 1;
+
+ set_referenceId (p->odr_out, &req->referenceId,
+ obj->set_inher.referenceId);
+
+ req->smallSetUpperBound = &obj->set_inher.smallSetUpperBound;
+ req->largeSetLowerBound = &obj->set_inher.largeSetLowerBound;
+ req->mediumSetPresentNumber = &obj->set_inher.mediumSetPresentNumber;
+ req->replaceIndicator = &obj->set_inher.replaceIndicator;
+ req->resultSetName = obj->setName ? obj->setName : "default";
+ logf (LOG_DEBUG, "Search, resultSetName %s", req->resultSetName);
+ req->num_databaseNames = obj->set_inher.num_databaseNames;
+ req->databaseNames = obj->set_inher.databaseNames;
+ for (r=0; r < obj->set_inher.num_databaseNames; r++)
+ logf (LOG_DEBUG, " Database %s", obj->set_inher.databaseNames[r]);
+ if (obj->set_inher.preferredRecordSyntax)
+ {
+ struct oident ident;
+
+ ident.proto = p->protocol_type;
+ ident.oclass = CLASS_RECSYN;
+ ident.value = *obj->set_inher.preferredRecordSyntax;
+ logf (LOG_DEBUG, "Preferred record syntax is %d", ident.value);
+ req->preferredRecordSyntax = odr_oiddup (p->odr_out,
+ oid_getoidbyent (&ident));
+ }
+ else
+ req->preferredRecordSyntax = 0;
+
+ if (obj->set_inher.smallSetElementSetNames &&
+ *obj->set_inher.smallSetElementSetNames)
+ {
+ Z_ElementSetNames *esn = odr_malloc (p->odr_out, sizeof(*esn));
+
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = obj->set_inher.smallSetElementSetNames;
+ req->smallSetElementSetNames = esn;
+ }
+ else
+ req->smallSetElementSetNames = NULL;
+
+ if (obj->set_inher.mediumSetElementSetNames &&
+ *obj->set_inher.mediumSetElementSetNames)
+ {
+ Z_ElementSetNames *esn = odr_malloc (p->odr_out, sizeof(*esn));
+
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = obj->set_inher.mediumSetElementSetNames;
+ req->mediumSetElementSetNames = esn;
+ }
+ else
+ req->mediumSetElementSetNames = NULL;
+
+ req->query = &query;
+
+ logf (LOG_DEBUG, "queryType %s", obj->set_inher.queryType);
+ if (!strcmp (obj->set_inher.queryType, "rpn"))
+ {
+ Z_RPNQuery *RPNquery;
+
+ RPNquery = p_query_rpn (p->odr_out, p->protocol_type, query_str);
+ if (!RPNquery)
+ {
+ Tcl_AppendResult (interp, "query syntax error", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ query.which = Z_Query_type_1;
+ query.u.type_1 = RPNquery;
+ }
+#if CCL2RPN
+ else if (!strcmp (obj->set_inher.queryType, "cclrpn"))
+ {
+ int error;
+ int pos;
+ struct ccl_rpn_node *rpn;
+ Z_RPNQuery *RPNquery;
+ oident bib1;
+
+ bib1.proto = p->protocol_type;
+ bib1.oclass = CLASS_ATTSET;
+ bib1.value = VAL_BIB1;
+
+ rpn = ccl_find_str(p->bibset, query_str, &error, &pos);
+ if (error)
+ {
+ Tcl_AppendResult (interp, "ccl syntax error ", ccl_err_msg(error),
+ NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+#if 0
+ ccl_pr_tree (rpn, stderr);
+ fprintf (stderr, "\n");
+#endif
+ RPNquery = ccl_rpn_query(p->odr_out, rpn);
+ RPNquery->attributeSetId = oid_getoidbyent (&bib1);
+ query.which = Z_Query_type_1;
+ query.u.type_1 = RPNquery;
+ }
+#endif
+ else if (!strcmp (obj->set_inher.queryType, "ccl"))
+ {
+ query.which = Z_Query_type_2;
+ query.u.type_2 = &ccl_query;
+ ccl_query.buf = (unsigned char *) query_str;
+ ccl_query.len = strlen (query_str);
+ }
+ else
+ {
+ Tcl_AppendResult (interp, "invalid query method ",
+ obj->set_inher.queryType, NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ code = ir_tcl_send_APDU (interp, p, apdu, "search", *argv);
+ out:
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ Tcl_DStringFree (&ds);
+#endif
+ return code;
+}
+
+/*
+ * do_searchResponse: add search response handler
+ */
+static int do_searchResponse (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->searchResponse = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->searchResponse);
+ if (argc == 3)
+ {
+ xfree (obj->searchResponse);
+ if (argv[2][0])
+ {
+ if (ir_tcl_strdup (interp, &obj->searchResponse, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ obj->searchResponse = NULL;
+ }
+ return TCL_OK;
+}
+
+/*
+ * do_presentResponse: add present response handler
+ */
+static int do_presentResponse (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->presentResponse = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->presentResponse);
+ if (argc == 3)
+ {
+ xfree (obj->presentResponse);
+ if (argv[2][0])
+ {
+ if (ir_tcl_strdup (interp, &obj->presentResponse, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ obj->presentResponse = NULL;
+ }
+ return TCL_OK;
+}
+
+/*
+ * 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,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc <= 0)
+ {
+ obj->resultCount = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&obj->resultCount, interp, argc, argv);
+}
+
+/*
+ * do_searchStatus: Get search status (after search response)
+ */
+static int do_searchStatus (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc <= 0)
+ return TCL_OK;
+ return ir_tcl_get_set_int (&obj->searchStatus, interp, argc, argv);
+}
+
+static void reset_searchResult (IrTcl_SetObj *setobj)
+{
+ int i;
+ for (i = 0; i<setobj->searchResult_num; i++)
+ xfree (setobj->searchResult_terms[i]);
+ xfree (setobj->searchResult_terms);
+ xfree (setobj->searchResult_count);
+ setobj->searchResult_terms = 0;
+ setobj->searchResult_num = 0;
+}
+
+
+/*
+ * do_searchResult Get USR:Search-Result1 (after search response)
+ */
+static int do_searchResult (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int i;
+
+ if (argc == 0)
+ {
+ obj->searchResult_num = 0;
+ obj->searchResult_terms = 0;
+ obj->searchResult_count = 0;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ reset_searchResult (obj);
+ return TCL_OK;
+ }
+ for (i = 0; i<obj->searchResult_num; i++)
+ {
+ char str[40];
+ sprintf (str, "%d", obj->searchResult_count[i]);
+ Tcl_AppendResult (interp, "{", NULL);
+ if (obj->searchResult_terms[i])
+ Tcl_AppendElement (interp, obj->searchResult_terms[i]);
+ else
+ Tcl_AppendElement (interp, "");
+ Tcl_AppendElement (interp, str);
+ Tcl_AppendResult (interp, "} ", NULL);
+ }
+ return TCL_OK;
+}
+
+/*
+ * do_presentStatus: Get search status (after search/present response)
+ */
+static int do_presentStatus (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc <= 0)
+ return TCL_OK;
+ return ir_tcl_get_set_int (&obj->presentStatus, interp, argc, argv);
+}
+
+/*
+ * 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)
+ */
+static int do_nextResultSetPosition (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc <= 0)
+ {
+ obj->nextResultSetPosition = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&obj->nextResultSetPosition, interp,
+ argc, argv);
+}
+
+/*
+ * do_setName: Set result Set name
+ */
+static int do_setName (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ return ir_tcl_strdup (interp, &obj->setName, "Default");
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->setName);
+ if (argc == 3)
+ {
+ xfree (obj->setName);
+ if (ir_tcl_strdup (interp, &obj->setName, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ Tcl_AppendElement (interp, obj->setName);
+ return TCL_OK;
+}
+
+/*
+ * do_numberOfRecordsReturned: Get number of records returned
+ */
+static int do_numberOfRecordsReturned (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc <= 0)
+ {
+ obj->numberOfRecordsReturned = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&obj->numberOfRecordsReturned, interp,
+ argc, argv);
+}
+
+/*
+ * do_type: Return type (if any) at position.
+ */
+static int do_type (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc == 0)
+ {
+ obj->record_list = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ delete_IR_records (obj);
+ return TCL_OK;
+ }
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ logf (LOG_DEBUG, "%s %s %s: no record", argv[0], argv[1], argv[2]);
+ return TCL_OK;
+ }
+ switch (rl->which)
+ {
+ case Z_NamePlusRecord_databaseRecord:
+ interp->result = "DB";
+ break;
+ case Z_NamePlusRecord_surrogateDiagnostic:
+ interp->result = "SD";
+ break;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * do_recordType: Return record type (if any) at position.
+ */
+static int do_recordType (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc == 0)
+ {
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ return TCL_OK;
+ }
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ logf (LOG_DEBUG, "%s %s %s: no record", argv[0], argv[1], argv[2]);
+ return TCL_OK;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendElement (interp, (char*)
+ IrTcl_getRecordSyntaxStr (rl->u.dbrec.type));
+ return TCL_OK;
+}
+
+/*
+ * set record elements (for record extraction)
+ */
+static int do_recordElements (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->recordElements = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (NULL, &obj->recordElements);
+ if (argc > 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " ?position?\"", NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3)
+ {
+ xfree (obj->recordElements);
+ return ir_tcl_strdup (NULL, &obj->recordElements,
+ (*argv[2] ? argv[2] : NULL));
+ }
+ Tcl_AppendResult (interp, obj->recordElements, NULL);
+ return TCL_OK;
+}
+
+/*
+ * ir_diagResult
+ */
+static int ir_diagResult (Tcl_Interp *interp, IrTcl_Diagnostic *list, int num)
+{
+ char buf[20];
+ int i;
+ const char *cp;
+
+ for (i = 0; i<num; i++)
+ {
+ sprintf (buf, "%d", list[i].condition);
+ Tcl_AppendElement (interp, buf);
+ cp = diagbib1_str (list[i].condition);
+ if (cp)
+ Tcl_AppendElement (interp, (char*) cp);
+ else
+ Tcl_AppendElement (interp, "");
+ if (list[i].addinfo)
+ Tcl_AppendElement (interp, (char*) list[i].addinfo);
+ else
+ Tcl_AppendElement (interp, "");
+ }
+ return TCL_OK;
+}
+
+/*
+ * do_diag: Return diagnostic record info
+ */
+static int do_diag (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_surrogateDiagnostic)
+ {
+ Tcl_AppendResult (interp, "No Diagnostic record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ return ir_diagResult (interp, rl->u.surrogateDiagnostics.list,
+ rl->u.surrogateDiagnostics.num);
+}
+
+/*
+ * do_getMarc: Get ISO2709 Record lines/fields
+ */
+static int do_getMarc (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc < 7)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position line|field tag ind field\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ return ir_tcl_get_marc (interp, rl->u.dbrec.buf, argc, argv);
+}
+
+/*
+ * do_getSutrs: Get SUTRS Record
+ */
+static int do_getSutrs (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (!rl->u.dbrec.buf || rl->u.dbrec.type != VAL_SUTRS)
+ return TCL_OK;
+ Tcl_AppendElement (interp, rl->u.dbrec.buf);
+ return TCL_OK;
+}
+
+/*
+ * do_getXml: Get XML Record
+ */
+static int do_getXml (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (!rl->u.dbrec.buf || rl->u.dbrec.type != VAL_TEXT_XML)
+ return TCL_OK;
+ Tcl_AppendElement (interp, rl->u.dbrec.buf);
+ return TCL_OK;
+}
+
+/*
+ * do_getGrs: Get a GRS-1 Record
+ */
+static int do_getGrs (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc < 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position ?(set,tag) (set,tag) ...?\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->u.dbrec.type != VAL_GRS1)
+ return TCL_OK;
+ return ir_tcl_get_grs (interp, rl->u.dbrec.u.grs1, argc, argv);
+}
+
+
+/*
+ * do_getExplain: Get an Explain Record
+ */
+static int do_getExplain (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ IrTcl_Obj *p = obj->parent;
+ void *rr;
+ Z_ext_typeent *etype;
+ int offset;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc < 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position ?mask? ...\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
+ return TCL_ERROR;
+ rl = find_IR_record (obj, offset);
+ if (!rl)
+ {
+ Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (rl->which != Z_NamePlusRecord_databaseRecord)
+ {
+ Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ if (!rl->u.dbrec.buf || rl->u.dbrec.type != VAL_EXPLAIN)
+ return TCL_OK;
+
+ if (!(etype = z_ext_getentbyref (VAL_EXPLAIN)))
+ 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, 0))
+ return TCL_OK;
+
+ if (etype->what != Z_External_explainRecord)
+ return TCL_OK;
+
+ return ir_tcl_get_explain (interp, rr, argc, argv);
+}
+
+/*
+ * do_responseStatus: Return response status (present or search)
+ */
+static int do_responseStatus (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->recordFlag = 0;
+ obj->nonSurrogateDiagnosticNum = 0;
+ obj->nonSurrogateDiagnosticList = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ ir_deleteDiags (&obj->nonSurrogateDiagnosticList,
+ &obj->nonSurrogateDiagnosticNum);
+ return TCL_OK;
+ }
+ if (!obj->recordFlag)
+ {
+ Tcl_AppendElement (interp, "OK");
+ return TCL_OK;
+ }
+ switch (obj->which)
+ {
+ case Z_Records_DBOSD:
+ Tcl_AppendElement (interp, "DBOSD");
+ break;
+ case Z_Records_NSD:
+ Tcl_AppendElement (interp, "NSD");
+ return ir_diagResult (interp, obj->nonSurrogateDiagnosticList,
+ obj->nonSurrogateDiagnosticNum);
+ case Z_Records_multipleNSD:
+ Tcl_AppendElement (interp, "NSD");
+ return ir_diagResult (interp, obj->nonSurrogateDiagnosticList,
+ obj->nonSurrogateDiagnosticNum);
+ }
+ return TCL_OK;
+}
+
+/*
+ * do_present: Perform Present Request
+ */
+
+static int do_present (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ IrTcl_Obj *p;
+ Z_APDU *apdu;
+ Z_PresentRequest *req;
+ int start;
+ int number;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc >= 3)
+ {
+ if (Tcl_GetInt (interp, argv[2], &start) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ start = 1;
+ if (argc >= 4)
+ {
+ if (Tcl_GetInt (interp, argv[3], &number) == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ number = 10;
+ logf (LOG_DEBUG, "present %s %d %d", *argv, start, number);
+ p = obj->parent;
+ if (!p->cs_link)
+ {
+ Tcl_AppendResult (interp, "not connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ obj->start = start;
+ obj->number = number;
+
+ apdu = zget_APDU (p->odr_out, Z_APDU_presentRequest);
+ req = apdu->u.presentRequest;
+
+ set_referenceId (p->odr_out, &req->referenceId,
+ obj->set_inher.referenceId);
+
+ req->resultSetId = obj->setName ? obj->setName : "Default";
+
+ req->resultSetStartPoint = &start;
+ req->numberOfRecordsRequested = &number;
+ if (obj->set_inher.preferredRecordSyntax)
+ {
+ struct oident ident;
+
+ ident.proto = p->protocol_type;
+ ident.oclass = CLASS_RECSYN;
+ ident.value = *obj->set_inher.preferredRecordSyntax;
+ logf (LOG_DEBUG, "Preferred record syntax is %d", ident.value);
+ req->preferredRecordSyntax = odr_oiddup (p->odr_out,
+ oid_getoidbyent (&ident));
+ }
+ else
+ req->preferredRecordSyntax = 0;
+
+ if (obj->set_inher.elementSetNames && *obj->set_inher.elementSetNames)
+ {
+ Z_ElementSetNames *esn = odr_malloc (p->odr_out, sizeof(*esn));
+ Z_RecordComposition *compo = odr_malloc (p->odr_out, sizeof(*compo));
+
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = obj->set_inher.elementSetNames;
+
+ req->recordComposition = compo;
+ compo->which = Z_RecordComp_simple;
+ compo->u.simple = esn;
+ }
+ else
+ req->recordComposition = NULL;
+ return ir_tcl_send_APDU (interp, p, apdu, "present", *argv);
+}
+
+#define IR_TCL_RECORD_ENCODING_ISO2709 1
+#define IR_TCL_RECORD_ENCODING_RAW 2
+
+typedef struct {
+ int encoding;
+ int syntax;
+ size_t size;
+} IrTcl_FileRecordHead;
+
+/*
+ * do_loadFile: Load result set from file
+ */
+static int do_loadFile (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *setobj = o;
+ FILE *inf;
+ size_t size;
+ int offset;
+ int start = 1;
+ int number = 30000;
+ char *buf;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc < 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " filename ?start? ?number?\"", NULL);
+ return TCL_ERROR;
+ }
+ if (argc > 3)
+ start = atoi (argv[3]);
+ if (argc > 4)
+ number = atoi (argv[4]);
+ offset = start;
+
+ inf = fopen (argv[2], "r");
+ if (!inf)
+ {
+ Tcl_AppendResult (interp, "Cannot open ", argv[2], NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ while (offset < (start+number))
+ {
+ IrTcl_FileRecordHead head;
+ IrTcl_RecordList *rl;
+
+ if (fread (&head, sizeof(head), 1, inf) < 1)
+ break;
+ rl = new_IR_record (setobj, offset,
+ Z_NamePlusRecord_databaseRecord,
+ (argc > 5) ? argv[5] : NULL);
+ rl->u.dbrec.type = head.syntax;
+ if (head.encoding == IR_TCL_RECORD_ENCODING_ISO2709)
+ {
+ if (!(buf = ir_tcl_fread_marc (inf, &size)))
+ break;
+ rl->u.dbrec.buf = buf;
+ rl->u.dbrec.size = size;
+ if (size != head.size)
+ {
+ fclose (inf);
+ Tcl_AppendResult (interp, "bad ISO2709 encoding", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ }
+ else if (head.encoding == IR_TCL_RECORD_ENCODING_RAW)
+ {
+ rl->u.dbrec.size = head.size;
+ rl->u.dbrec.buf = ir_tcl_malloc (head.size + 1);
+ if (fread (rl->u.dbrec.buf, rl->u.dbrec.size, 1, inf) < 1)
+ {
+ fclose (inf);
+ Tcl_AppendResult (interp, "bad raw encoding", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ rl->u.dbrec.buf[rl->u.dbrec.size] = '\0';
+ }
+ else
+ {
+ rl->u.dbrec.buf = NULL;
+ rl->u.dbrec.size = 0;
+ fclose (inf);
+ Tcl_AppendResult (interp, "bad encoding", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ offset++;
+ }
+ setobj->numberOfRecordsReturned = offset - start;
+ fclose (inf);
+ return TCL_OK;
+}
+
+/*
+ * do_saveFile: Save result set on file
+ */
+static int do_saveFile (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *setobj = o;
+ FILE *outf;
+ int offset;
+ int start = 1;
+ int number = 30000;
+ IrTcl_RecordList *rl;
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc < 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " filename ?start? ?number?\"", NULL);
+ return TCL_ERROR;
+ }
+ if (argc > 3)
+ start = atoi (argv[3]);
+ if (argc > 4)
+ number = atoi (argv[4]);
+ offset = start;
+
+ outf = fopen (argv[2], "w");
+ if (!outf)
+ {
+ Tcl_AppendResult (interp, "cannot open file", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ while (offset < (start+number) && (rl = find_IR_record (setobj, offset)))
+ {
+ if (rl->which == Z_NamePlusRecord_databaseRecord &&
+ rl->u.dbrec.buf && rl->u.dbrec.size)
+ {
+ IrTcl_FileRecordHead head;
+
+ head.encoding = IR_TCL_RECORD_ENCODING_RAW;
+ head.syntax = rl->u.dbrec.type;
+ head.size = rl->u.dbrec.size;
+ if (fwrite (&head, sizeof(head), 1, outf) < 1)
+ {
+ Tcl_AppendResult (interp, "cannot write", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ if (fwrite (rl->u.dbrec.buf, rl->u.dbrec.size, 1, outf) < 1)
+ {
+ Tcl_AppendResult (interp, "cannot write", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ }
+ offset++;
+ }
+ if (fclose (outf))
+ {
+ Tcl_AppendResult (interp, "cannot write ", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ return TCL_OK;
+}
+
+
+/* ------------------------------------------------------- */
+/*
+ * 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},
+ { "presentResponse", do_presentResponse, NULL},
+ { "searchStatus", do_searchStatus, NULL},
+ { "presentStatus", do_presentStatus, NULL},
+ { "nextResultSetPosition", do_nextResultSetPosition, NULL},
+ { "setName", do_setName, NULL},
+ { "resultCount", do_resultCount, NULL},
+ { "numberOfRecordsReturned", do_numberOfRecordsReturned, NULL},
+ { "present", do_present, NULL},
+ { "type", do_type, NULL},
+ { "getMarc", do_getMarc, NULL},
+ { "getSutrs", do_getSutrs, NULL},
+ { "getXml", do_getXml, NULL},
+ { "getGrs", do_getGrs, NULL},
+ { "getExplain", do_getExplain, NULL},
+ { "recordType", do_recordType, NULL},
+ { "recordElements", do_recordElements, NULL},
+ { "diag", do_diag, 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},
+ { "searchResult", do_searchResult, NULL},
+ { NULL, NULL}
+};
+
+/*
+ * ir_set_obj_method: IR Set Object methods
+ */
+static int ir_set_obj_method (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_Methods tabs[3];
+ IrTcl_SetObj *p = (IrTcl_SetObj *) clientData;
+ int r;
+
+ if (argc < 2)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " method args...\"", NULL);
+ return TCL_ERROR;
+ }
+ tabs[0].tab = ir_set_method_tab;
+ tabs[0].obj = p;
+ tabs[1].tab = ir_set_c_method_tab;
+ tabs[1].obj = &p->set_inher;
+ tabs[2].tab = NULL;
+
+ if (ir_tcl_method (interp, argc, argv, tabs, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tabs);
+ return r;
+}
+
+/*
+ * ir_set_obj_delete: IR Set Object disposal
+ */
+static void ir_set_obj_delete (ClientData clientData)
+{
+ IrTcl_Methods tabs[3];
+ IrTcl_SetObj *p = (IrTcl_SetObj *) clientData;
+
+ logf (LOG_DEBUG, "ir set delete");
+
+ tabs[0].tab = ir_set_method_tab;
+ tabs[0].obj = p;
+ tabs[1].tab = ir_set_c_method_tab;
+ tabs[1].obj = &p->set_inher;
+ tabs[2].tab = NULL;
+
+ ir_tcl_method (NULL, -1, NULL, tabs, NULL);
+
+ xfree (p);
+}
+
+/*
+ * ir_set_obj_init: IR Set Object initialization
+ */
+static int ir_set_obj_init (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv, ClientData *subData,
+ ClientData parentData)
+{
+ IrTcl_Methods tabs[3];
+ IrTcl_SetObj *obj;
+
+ if (argc < 2 || argc > 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ " objSetName ?objParent?\"", NULL);
+ return TCL_ERROR;
+ }
+ obj = ir_tcl_malloc (sizeof(*obj));
+ logf (LOG_DEBUG, "ir set create %s", argv[1]);
+ if (parentData)
+ {
+ int i;
+ IrTcl_SetCObj *dst;
+ IrTcl_SetCObj *src;
+
+ obj->parent = (IrTcl_Obj *) parentData;
+
+ dst = &obj->set_inher;
+ src = &obj->parent->set_inher;
+
+ if ((dst->num_databaseNames = src->num_databaseNames))
+ {
+ dst->databaseNames =
+ ir_tcl_malloc (sizeof (*dst->databaseNames)
+ * (1+dst->num_databaseNames));
+ for (i = 0; i < dst->num_databaseNames; i++)
+ if (ir_tcl_strdup (interp, &dst->databaseNames[i],
+ src->databaseNames[i]) == TCL_ERROR)
+ return TCL_ERROR;
+ dst->databaseNames[i] = NULL;
+ }
+ else
+ dst->databaseNames = NULL;
+ if (ir_tcl_strdup (interp, &dst->queryType, src->queryType)
+ == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (ir_tcl_strdup (interp, &dst->referenceId, src->referenceId)
+ == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (ir_tcl_strdup (interp, &dst->elementSetNames, src->elementSetNames)
+ == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (ir_tcl_strdup (interp, &dst->smallSetElementSetNames,
+ src->smallSetElementSetNames)
+ == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (ir_tcl_strdup (interp, &dst->mediumSetElementSetNames,
+ src->mediumSetElementSetNames)
+ == TCL_ERROR)
+ return TCL_ERROR;
+
+ if (src->preferredRecordSyntax &&
+ (dst->preferredRecordSyntax
+ = ir_tcl_malloc (sizeof(*dst->preferredRecordSyntax))))
+ *dst->preferredRecordSyntax = *src->preferredRecordSyntax;
+ else
+ dst->preferredRecordSyntax = NULL;
+ dst->replaceIndicator = src->replaceIndicator;
+ dst->smallSetUpperBound = src->smallSetUpperBound;
+ dst->largeSetLowerBound = src->largeSetLowerBound;
+ dst->mediumSetPresentNumber = src->mediumSetPresentNumber;
+ }
+ else
+ obj->parent = NULL;
+
+ tabs[0].tab = ir_set_method_tab;
+ tabs[0].obj = obj;
+ tabs[1].tab = NULL;
+
+ if (ir_tcl_method (interp, 0, NULL, tabs, NULL) == TCL_ERROR)
+ return TCL_ERROR;
+
+ *subData = (ClientData) obj;
+ return TCL_OK;
+}
+
+/*
+ * ir_set_obj_mk: IR Set Object creation
+ */
+static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ ClientData subData;
+ ClientData parentData = 0;
+ int r;
+
+ if (argc == 3)
+ {
+ Tcl_CmdInfo parent_info;
+ if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info))
+ {
+ Tcl_AppendResult (interp, "no object parent", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ parentData = parent_info.clientData;
+ }
+ r = ir_set_obj_init (clientData, interp, argc, argv, &subData, parentData);
+ if (r == TCL_ERROR)
+ return TCL_ERROR;
+ Tcl_CreateCommand (interp, argv[1], ir_set_obj_method,
+ subData, ir_set_obj_delete);
+ return TCL_OK;
+}
+
+IrTcl_Class ir_set_obj_class = {
+ "ir-set",
+ ir_set_obj_init,
+ ir_set_obj_method,
+ ir_set_obj_delete
+};
+
+/* ------------------------------------------------------- */
+
+/*
+ * do_scan: Perform scan
+ */
+static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv)
+{
+ Z_ScanRequest *req;
+ Z_APDU *apdu;
+ IrTcl_ScanObj *obj = o;
+ IrTcl_Obj *p = obj->parent;
+ char *start_term;
+ int code;
+#if CCL2RPN
+ oident bib1;
+ struct ccl_rpn_node *rpn;
+ int pos;
+ int r;
+#endif
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ Tcl_DString ds;
+#endif
+
+ if (argc <= 0)
+ return TCL_OK;
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " scanQuery\"", NULL);
+ return TCL_ERROR;
+ }
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ start_term = Tcl_UtfToExternalDString(0, argv[2], -1, &ds);
+#else
+ start_term = argv[2];
+#endif
+ logf (LOG_DEBUG, "scan %s %s", *argv, start_term);
+ if (!p->set_inher.num_databaseNames)
+ {
+ Tcl_AppendResult (interp, "no databaseNames", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ if (!p->cs_link)
+ {
+ Tcl_AppendResult (interp, "not connected", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+
+ apdu = zget_APDU (p->odr_out, Z_APDU_scanRequest);
+ req = apdu->u.scanRequest;
+
+ set_referenceId (p->odr_out, &req->referenceId, p->set_inher.referenceId);
+ req->num_databaseNames = p->set_inher.num_databaseNames;
+ req->databaseNames = p->set_inher.databaseNames;
+
+#if 1
+/* !CCL2RPN */
+ if (!(req->termListAndStartPoint =
+ p_query_scan (p->odr_out, p->protocol_type,
+ &req->attributeSet, start_term)))
+ {
+ Tcl_AppendResult (interp, "query syntax error", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+#else
+ rpn = ccl_find_str(p->bibset, start_term, &r, &pos);
+ if (r)
+ {
+ Tcl_AppendResult (interp, "ccl syntax error ", ccl_err_msg(r), NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
+ }
+ bib1.proto = p->protocol_type;
+ bib1.oclass = CLASS_ATTSET;
+ bib1.value = VAL_BIB1;
+
+ req->attributeSet = oid_getoidbyent (&bib1);
+ if (!(req->termListAndStartPoint = ccl_scan_query (p->odr_out, rpn)))
+ {
+ code = TCL_ERROR;
+ goto out;
+ }
+#endif
+ req->stepSize = &obj->stepSize;
+ req->numberOfTermsRequested = &obj->numberOfTermsRequested;
+ req->preferredPositionInResponse = &obj->preferredPositionInResponse;
+ logf (LOG_DEBUG, "stepSize=%d", *req->stepSize);
+ logf (LOG_DEBUG, "numberOfTermsRequested=%d",
+ *req->numberOfTermsRequested);
+ logf (LOG_DEBUG, "preferredPositionInResponse=%d",
+ *req->preferredPositionInResponse);
+
+ code = ir_tcl_send_APDU (interp, p, apdu, "scan", *argv);
+ out:
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ Tcl_DStringFree (&ds);
+#endif
+ return code;
+}
+
+/*
+ * do_scanResponse: add scan response handler
+ */
+static int do_scanResponse (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->scanResponse = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->scanResponse);
+ if (argc == 3)
+ {
+ xfree (obj->scanResponse);
+ if (argv[2][0])
+ {
+ if (ir_tcl_strdup (interp, &obj->scanResponse, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ obj->scanResponse = NULL;
+ }
+ return TCL_OK;
+}
+
+/*
+ * do_stepSize: Set/get replace Step Size
+ */
+static int do_stepSize (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+ if (argc <= 0)
+ {
+ p->stepSize = 0;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->stepSize, interp, argc, argv);
+}
+
+/*
+ * do_numberOfTermsRequested: Set/get Number of Terms requested
+ */
+static int do_numberOfTermsRequested (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+
+ if (argc <= 0)
+ {
+ p->numberOfTermsRequested = 20;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->numberOfTermsRequested, interp, argc, argv);
+}
+
+
+/*
+ * do_preferredPositionInResponse: Set/get preferred Position
+ */
+static int do_preferredPositionInResponse (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+
+ if (argc <= 0)
+ {
+ p->preferredPositionInResponse = 1;
+ return TCL_OK;
+ }
+ return ir_tcl_get_set_int (&p->preferredPositionInResponse, interp,
+ argc, argv);
+}
+
+/*
+ * do_scanStatus: Get scan status
+ */
+static int do_scanStatus (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+
+ if (argc <= 0)
+ return TCL_OK;
+ return ir_tcl_get_set_int (&p->scanStatus, interp, argc, argv);
+}
+
+/*
+ * do_numberOfEntriesReturned: Get number of Entries returned
+ */
+static int do_numberOfEntriesReturned (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+
+ if (argc <= 0)
+ return TCL_OK;
+ return ir_tcl_get_set_int (&p->numberOfEntriesReturned, interp,
+ argc, argv);
+}
+
+/*
+ * do_positionOfTerm: Get position of Term
+ */
+static int do_positionOfTerm (void *obj, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+
+ if (argc <= 0)
+ return TCL_OK;
+ return ir_tcl_get_set_int (&p->positionOfTerm, interp, argc, argv);
+}
+
+/*
+ * do_scanLine: get Scan Line (surrogate or normal) after response
+ */
+static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv)
+{
+ IrTcl_ScanObj *p = obj;
+ int i;
+ char numstr[20];
+
+ if (argc == 0)
+ {
+ p->entries_flag = 0;
+ p->entries = NULL;
+ p->nonSurrogateDiagnosticNum = 0;
+ p->nonSurrogateDiagnosticList = 0;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ {
+ p->entries_flag = 0;
+ /* release entries */
+ p->entries = NULL;
+
+ ir_deleteDiags (&p->nonSurrogateDiagnosticList,
+ &p->nonSurrogateDiagnosticNum);
+ return TCL_OK;
+ }
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt (interp, argv[2], &i) == TCL_ERROR)
+ return TCL_ERROR;
+ if (!p->entries_flag || !p->entries || i >= p->num_entries || i < 0)
+ return TCL_OK;
+ switch (p->entries[i].which)
+ {
+ case Z_Entry_termInfo:
+ Tcl_AppendElement (interp, "T");
+ if (p->entries[i].u.term.buf)
+ Tcl_AppendElement (interp, p->entries[i].u.term.buf);
+ else
+ Tcl_AppendElement (interp, "");
+ sprintf (numstr, "%d", p->entries[i].u.term.globalOccurrences);
+ Tcl_AppendElement (interp, numstr);
+ break;
+ case Z_Entry_surrogateDiagnostic:
+ Tcl_AppendElement (interp, "SD");
+ return ir_diagResult (interp, p->entries[i].u.diag.list,
+ p->entries[i].u.diag.num);
+ break;
+ }
+ return TCL_OK;
+}
+
+static IrTcl_Method ir_scan_method_tab[] = {
+ { "scan", do_scan, NULL},
+ { "scanResponse", do_scanResponse, NULL},
+ { "stepSize", do_stepSize, NULL},
+ { "numberOfTermsRequested", do_numberOfTermsRequested, NULL},
+ { "preferredPositionInResponse", do_preferredPositionInResponse, NULL},
+ { "scanStatus", do_scanStatus, NULL},
+ { "numberOfEntriesReturned", do_numberOfEntriesReturned, NULL},
+ { "positionOfTerm", do_positionOfTerm, NULL},
+ { "scanLine", do_scanLine, NULL},
+ { NULL, NULL}
+};
+
+/*
+ * ir_scan_obj_method: IR Scan Object methods
+ */
+static int ir_scan_obj_method (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_Methods tabs[2];
+ int r;
+
+ if (argc < 2)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " method args...\"", NULL);
+ return TCL_ERROR;
+ }
+ tabs[0].tab = ir_scan_method_tab;
+ tabs[0].obj = clientData;
+ tabs[1].tab = NULL;
+
+ if (ir_tcl_method (interp, argc, argv, tabs, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tabs);
+ return r;
+}
+
+/*
+ * ir_scan_obj_delete: IR Scan Object disposal
+ */
+static void ir_scan_obj_delete (ClientData clientData)
+{
+ IrTcl_Methods tabs[2];
+ IrTcl_ScanObj *obj = (IrTcl_ScanObj *) clientData;
+
+ tabs[0].tab = ir_scan_method_tab;
+ tabs[0].obj = obj;
+ tabs[1].tab = NULL;
+
+ ir_tcl_method (NULL, -1, NULL, tabs, NULL);
+ xfree (obj);
+}
+
+/*
+ * ir_scan_obj_mk: IR Scan Object creation
+ */
+static int ir_scan_obj_mk (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ Tcl_CmdInfo parent_info;
+ IrTcl_ScanObj *obj;
+ IrTcl_Methods tabs[2];
+
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ "objScanName objParentName\"", NULL);
+ return TCL_ERROR;
+ }
+ logf (LOG_DEBUG, "ir scan create %s", argv[1]);
+ if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info))
+ {
+ Tcl_AppendResult (interp, "no object parent", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ obj = ir_tcl_malloc (sizeof(*obj));
+ obj->parent = (IrTcl_Obj *) parent_info.clientData;
+
+ tabs[0].tab = ir_scan_method_tab;
+ tabs[0].obj = obj;
+ tabs[1].tab = NULL;
+
+ if (ir_tcl_method (interp, 0, NULL, tabs, NULL) == TCL_ERROR)
+ return TCL_ERROR;
+ Tcl_CreateCommand (interp, argv[1], ir_scan_obj_method,
+ (ClientData) obj, ir_scan_obj_delete);
+ return TCL_OK;
+}
+
+/* ------------------------------------------------------- */
+
+/*
+ * ir_log_init_proc: set yaz log level
+ */
+static int ir_log_init_proc (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ int lev;
+ if (argc <= 1 || argc > 4)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ " ?level ?prefix ?filename\"", NULL);
+ return TCL_OK;
+ }
+ lev = yaz_log_mask_str (argv[1]);
+ if (argc == 2)
+ yaz_log_init (lev, "", NULL);
+ else if (argc == 3)
+ yaz_log_init (lev, argv[2], NULL);
+ else
+ yaz_log_init (lev, argv[2], argv[3]);
+ if (lev & LOG_DEBUG)
+ odr_print_file = yaz_log_file();
+ else
+ odr_print_file = 0;
+ return TCL_OK;
+}
+
+/*
+ * ir_log_proc: log yaz message
+ */
+static int ir_log_proc (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ int mask;
+ if (argc != 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ " level string\"", NULL);
+ return TCL_OK;
+ }
+ mask = yaz_log_mask_str_x (argv[1], 0);
+ logf (LOG_DEBUG, "%s", argv[2]);
+ return TCL_OK;
+}
+
+
+/*
+ * 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)
+{
+ IrTcl_Obj *p = obj;
+
+ p->initResult = *initrs->result ? 1 : 0;
+ if (!*initrs->result)
+ logf (LOG_DEBUG, "Connection rejected by target");
+ else
+ logf (LOG_DEBUG, "Connection accepted by target");
+
+ get_referenceId (&p->set_inher.referenceId, initrs->referenceId);
+
+ xfree (p->targetImplementationId);
+ ir_tcl_strdup (p->interp, &p->targetImplementationId,
+ initrs->implementationId);
+ xfree (p->targetImplementationName);
+ ir_tcl_strdup (p->interp, &p->targetImplementationName,
+ initrs->implementationName);
+ xfree (p->targetImplementationVersion);
+ ir_tcl_strdup (p->interp, &p->targetImplementationVersion,
+ initrs->implementationVersion);
+
+ p->maximumRecordSize = *initrs->maximumRecordSize;
+ p->preferredMessageSize = *initrs->preferredMessageSize;