+ 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);
+ 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 = odr_createmem (ODR_PRINT);
+ 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;
+
+ 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, "search %s %s", *argv, argv[2]);
+ if (!obj->set_inher.num_databaseNames)
+ {
+ Tcl_AppendResult (interp, "no databaseNames", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ 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_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, argv[2]);
+ if (!RPNquery)
+ {
+ Tcl_AppendResult (interp, "query syntax error", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ 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, argv[2], &error, &pos);
+ if (error)
+ {
+ Tcl_AppendResult (interp, "ccl syntax error ", ccl_err_msg(error),
+ NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+#if 0
+ ccl_pr_tree (rpn, stderr);
+ fprintf (stderr, "\n");
+#endif
+ assert((RPNquery = ccl_rpn_query(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 *) argv[2];
+ ccl_query.len = strlen (argv[2]);
+ }
+ else
+ {
+ Tcl_AppendResult (interp, "invalid query method ",
+ obj->set_inher.queryType, NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
+ return ir_tcl_send_APDU (interp, p, apdu, "search", *argv);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * 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);