/*
* IR toolkit for tcl/tk
- * (c) Index Data 1995
+ * (c) Index Data 1995-2000
* See the file LICENSE for details.
- * Sebastian Hammer, Adam Dickmeiss
*
* $Log: ir-tcl.c,v $
- * Revision 1.91 1996-07-03 13:31:11 adam
+ * Revision 1.116 2001-02-09 11:58:04 adam
+ * Updated for Tcl8.1 and higher where internal encoding is UTF-8.
+ *
+ * Revision 1.115 2000/09/13 12:18:49 adam
+ * Logging utility patch (YAZ version 1.7).
+ *
+ * Revision 1.114 1999/05/17 20:37:41 adam
+ * Fixed problem with ASN code.
+ *
+ * Revision 1.113 1999/04/20 10:01:46 adam
+ * Modified calls to ODR encoders/decoders (name argument).
+ *
+ * Revision 1.112 1999/03/22 06:51:34 adam
+ * Implemented sort.
+ *
+ * Revision 1.111 1999/02/11 11:30:09 adam
+ * Updated for WIN32.
+ *
+ * Revision 1.110 1998/10/20 15:15:31 adam
+ * Changed scan response handler.
+ *
+ * Revision 1.109 1998/10/13 21:23:26 adam
+ * Fixed searchStatus method.
+ *
+ * Revision 1.108 1998/10/12 11:48:08 adam
+ * Removed printf call.
+ *
+ * Revision 1.107 1998/06/10 13:00:46 adam
+ * Added ir-version command.
+ *
+ * Revision 1.106 1998/05/20 12:25:35 adam
+ * Fixed bug that occurred in rare cases when encoding of incoming
+ * records failed.
+ *
+ * Revision 1.105 1998/04/02 14:31:08 adam
+ * This version works with compiled ASN.1 code.
+ *
+ * Revision 1.104 1998/02/27 14:26:07 adam
+ * Changed client so that it still works if target sets numberOfRecords
+ * in response to an illegal value.
+ *
+ * Revision 1.103 1997/11/19 11:22:10 adam
+ * Object identifiers can be accessed in GRS-1 records.
+ *
+ * Revision 1.102 1997/09/17 12:22:40 adam
+ * Changed to use YAZ version 1.4. The new comstack utility, cs_straddr,
+ * is used.
+ *
+ * Revision 1.101 1997/09/09 10:19:53 adam
+ * New MSV5.0 port with fewer warnings.
+ *
+ * Revision 1.100 1997/05/01 15:04:05 adam
+ * Added ir-log command.
+ *
+ * Revision 1.99 1997/04/30 07:24:47 adam
+ * Spell fix of an error message.
+ *
+ * Revision 1.98 1997/04/13 18:57:20 adam
+ * Better error reporting and aligned with Tcl/Tk style.
+ * Rework of notifier code with Tcl_File handles.
+ *
+ * Revision 1.97 1996/11/14 17:11:07 adam
+ * Added Explain documentaion.
+ *
+ * Revision 1.96 1996/10/08 13:02:50 adam
+ * When dealing with records, odr_choice_enable_bias function is used to
+ * prevent decoding of externals.
+ *
+ * Revision 1.95 1996/09/13 10:51:49 adam
+ * Bug fix: ir_tcl_select_set called Tcl_GetFile at disconnect.
+ *
+ * Revision 1.94 1996/08/21 13:32:53 adam
+ * Implemented saveFile method and extended loadFile method to work with it.
+ *
+ * Revision 1.93 1996/08/16 15:07:45 adam
+ * First work on Explain.
+ *
+ * Revision 1.92 1996/08/09 15:33:07 adam
+ * Modified the code to use tk4.1/tcl7.5 patch level 1. The time-driven
+ * polling is no longer activated on Windows since asynchrounous I/O works
+ * better.
+ *
+ * Revision 1.91 1996/07/03 13:31:11 adam
* The xmalloc/xfree functions from YAZ are used to manage memory.
*
* Revision 1.90 1996/06/27 14:21:00 adam
#include <stdlib.h>
#include <stdio.h>
+#ifdef WIN32
+
+#else
#include <unistd.h>
+#endif
#include <time.h>
#include <assert.h>
#include "ir-tclp.h"
+#if defined(__WIN32__)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+
+/*
+ * VC++ has an alternate entry point called DllMain, so we need to rename
+ * our entry point.
+ */
+
+# if defined(_MSC_VER)
+# define EXPORT(a,b) __declspec(dllexport) a b
+# define DllEntryPoint DllMain
+# else
+# if defined(__BORLANDC__)
+# define EXPORT(a,b) a _export b
+# else
+# define EXPORT(a,b) a b
+# endif
+# endif
+#else
+# define EXPORT(a,b) a b
+#endif
+
+static char *wrongArgs = "wrong # args: should be \"";
+
+static int ir_tcl_error_exec (Tcl_Interp *interp, int argc, char **argv)
+{
+ int i;
+ Tcl_AppendResult (interp, " while executing ", NULL);
+ for (i = 0; i<argc; i++)
+ Tcl_AppendResult (interp, (i ? " " : "\""), argv[i], NULL);
+ Tcl_AppendResult (interp, "\"", NULL);
+ return TCL_ERROR;
+}
+
+
static void ir_deleteDiags (IrTcl_Diagnostic **dst_list, int *dst_num);
static void ir_select_notify (ClientData clientData, int r, int w, int e);
break;
}
xfree (rl->u.dbrec.buf);
+ rl->u.dbrec.buf = NULL;
break;
case Z_NamePlusRecord_surrogateDiagnostic:
ir_deleteDiags (&rl->u.surrogateDiagnostics.list,
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)
r = Tcl_Eval (interp, tmp);
if (r == TCL_ERROR)
{
- logf (LOG_WARN, "Tcl error in line %d: %s", interp->errorLine,
- interp->result);
+ const char *errorInfo = Tcl_GetVar (interp, "errorInfo", 0);
+ logf (LOG_WARN, "Tcl error in line %d: %s\n%s", interp->errorLine,
+ interp->result, errorInfo ? errorInfo : "<null>");
}
Tcl_FreeResult (interp);
xfree (tmp);
return TCL_OK;
}
+
+/*
+ * ir_tcl_method_error
+ */
+int ir_tcl_method_error (Tcl_Interp *interp, int argc, char **argv,
+ IrTcl_Methods *tab)
+{
+ IrTcl_Methods *tab_i = tab;
+ IrTcl_Method *t;
+
+ Tcl_AppendResult (interp, "bad method: \"", *argv, " ", argv[1],
+ "\"\nmethod should be of:", NULL);
+ for (tab_i = tab; tab_i->tab; tab_i++)
+ for (t = tab_i->tab; t->name; t++)
+ Tcl_AppendResult (interp, " ", t->name, NULL);
+ return TCL_ERROR;
+}
+
/*
* ir_tcl_method: Search for method in table and invoke method handler
*/
if (argc <= 0)
return TCL_OK;
-#if 0
- Tcl_AppendResult (interp, "Bad method: ", argv[1],
- ". Possible methods:", NULL);
- for (tab_i = tab; tab_i->tab; tab_i++)
- for (t = tab_i->tab; t->name; t++)
- Tcl_AppendResult (interp, " ", t->name, NULL);
-#endif
*ret = TCL_ERROR;
return TCL_ERROR;
}
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 TCL_ERROR;
+ Tcl_AppendResult (interp, "bad bit mask ", argv[no], NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
}
return TCL_OK;
logf (LOG_DEBUG, "init %s", *argv);
if (!p->cs_link)
{
- interp->result = "init: not connected";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "not connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
apdu = zget_APDU (p->odr_out, Z_APDU_initRequest);
req = apdu->u.initRequest;
if (argc == 0)
return ir_tcl_strdup (interp, &p->implementationVersion,
- "YAZ: " YAZ_VERSION " / IrTcl: " IR_TCL_VERSION);
+ "YAZ: " YAZ_VERSION
+#ifdef IR_TCL_VERSION
+ " / Irtcl: " IR_TCL_VERSION
+#endif
+ );
else if (argc == -1)
return ir_tcl_strdel (interp, &p->implementationVersion);
Tcl_AppendResult (interp, p->implementationVersion, (char*) NULL);
if (argc <= 0)
return TCL_OK;
- if (argc == 3)
+ if (argc > 3)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " ?hostname?\"", NULL);
+ return TCL_ERROR;
+ }
+ else if (argc < 3)
+ {
+ Tcl_AppendResult (interp, p->hostname, NULL);
+ }
+ else
{
logf (LOG_DEBUG, "connect %s %s", *argv, argv[2]);
if (p->hostname)
{
- interp->result = "already connected";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "already connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
if (!strcmp (p->comstackType, "tcpip"))
{
p->cs_link = cs_create (tcpip_type, CS_BLOCK, p->protocol_type);
- addr = tcpip_strtoaddr (argv[2]);
- if (!addr)
- {
- interp->result = "tcpip_strtoaddr fail";
- return TCL_ERROR;
- }
logf (LOG_DEBUG, "tcp/ip connect %s", argv[2]);
}
else if (!strcmp (p->comstackType, "mosi"))
{
#if MOSI
p->cs_link = cs_create (mosi_type, CS_BLOCK, p->protocol_type);
- addr = mosi_strtoaddr (argv[2]);
- if (!addr)
- {
- interp->result = "mosi_strtoaddr fail";
- return TCL_ERROR;
- }
logf (LOG_DEBUG, "mosi connect %s", argv[2]);
#else
- interp->result = "MOSI support not there";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "mosi not supported", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
#endif
}
else
{
- Tcl_AppendResult (interp, "Bad comstack type: ",
+ Tcl_AppendResult (interp, "bad comstack type ",
p->comstackType, NULL);
- return TCL_ERROR;
+ return ir_tcl_error_exec (interp, argc, argv);
}
if (ir_tcl_strdup (interp, &p->hostname, argv[2]) == TCL_ERROR)
return TCL_ERROR;
p->eventType = "connect";
+ addr = cs_straddr (p->cs_link, argv[2]);
+ if (!addr)
+ {
+ ir_tcl_disconnect (p);
+ Tcl_AppendResult (interp, "cs_straddr fail", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
+ }
if ((r=cs_connect (p->cs_link, addr)) < 0)
{
- interp->result = "connect fail";
ir_tcl_disconnect (p);
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "connect fail", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
ir_select_add (cs_fileno (p->cs_link), p);
if (r == 1)
ir_tcl_eval (p->interp, p->callback);
}
}
- else
- Tcl_AppendResult (interp, p->hostname, NULL);
return TCL_OK;
}
logf(LOG_DEBUG, "Closing connection to %s", p->hostname);
xfree (p->hostname);
p->hostname = NULL;
- ir_select_remove_write (cs_fileno (p->cs_link), p);
+ assert (p->cs_link);
ir_select_remove (cs_fileno (p->cs_link), p);
odr_reset (p->odr_in);
- assert (p->cs_link);
+#if TCL_MAJOR_VERSION == 8
+ cs_fileno(p->cs_link) = -1;
+#endif
cs_close (p->cs_link);
p->cs_link = NULL;
if (argc <= 2)
return TCL_OK;
if (argc == 3)
- log_init (log_mask_str (argv[2]), "", NULL);
+ yaz_log_init (yaz_log_mask_str (argv[2]), "", NULL);
else if (argc == 4)
- log_init (log_mask_str (argv[2]), argv[3], NULL);
+ yaz_log_init (yaz_log_mask_str (argv[2]), argv[3], NULL);
else if (argc == 5)
- log_init (log_mask_str (argv[2]), argv[3], argv[4]);
+ yaz_log_init (yaz_log_mask_str (argv[2]), argv[3], argv[4]);
return TCL_OK;
}
p->protocol_type = PROTO_SR;
else
{
- Tcl_AppendResult (interp, "Bad protocol: ", argv[2], NULL);
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "bad protocol ", argv[2], NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
return TCL_OK;
}
return TCL_OK;
if (!p->cs_link)
{
- interp->result = "triggerResourceControl: not connected";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "not connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
apdu = zget_APDU (p->odr_out, Z_APDU_triggerResourceControlRequest);
req = apdu->u.triggerResourceControlRequest;
int argc, char **argv)
{
IrTcl_Methods tab[3];
- IrTcl_Obj *p = clientData;
+ 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].obj = &p->set_inher;
tab[2].tab = NULL;
- ir_tcl_method (interp, argc, argv, tab, &r);
+ if (ir_tcl_method (interp, argc, argv, tab, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tab);
return r;
}
*/
static void ir_obj_delete (ClientData clientData)
{
- IrTcl_Obj *obj = clientData;
+ IrTcl_Obj *obj = (IrTcl_Obj *) clientData;
IrTcl_Methods tab[3];
--(obj->ref_count);
if (argc != 2)
{
- interp->result = "wrong # args";
+ Tcl_AppendResult (interp, wrongArgs, *argv, " objName\"", NULL);
return TCL_ERROR;
}
obj = ir_tcl_malloc (sizeof(*obj));
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;
Tcl_AppendResult (interp, "Failed to initialize ", argv[1], NULL);
return TCL_ERROR;
}
- *subData = obj;
+ *subData = (ClientData) obj;
return TCL_OK;
}
Odr_oct ccl_query;
IrTcl_SetObj *obj = o;
IrTcl_Obj *p;
- int r;
+ 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)
{
- logf (LOG_DEBUG, "search %s", *argv);
- interp->result = "wrong # args";
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1], "query\"",
+ NULL);
return TCL_ERROR;
}
- logf (LOG_DEBUG, "search %s %s", *argv, argv[2]);
+#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)
{
- interp->result = "no databaseNames";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "no databaseNames", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
}
if (!p->cs_link)
{
- interp->result = "search: not connected";
- return TCL_ERROR;
+ 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;
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";
+ 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;
{
Z_RPNQuery *RPNquery;
- RPNquery = p_query_rpn (p->odr_out, p->protocol_type, argv[2]);
+ RPNquery = p_query_rpn (p->odr_out, p->protocol_type, query_str);
if (!RPNquery)
{
- Tcl_AppendResult (interp, "Syntax error in query", NULL);
- return TCL_ERROR;
+ 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;
bib1.oclass = CLASS_ATTSET;
bib1.value = VAL_BIB1;
- rpn = ccl_find_str(p->bibset, argv[2], &error, &pos);
+ rpn = ccl_find_str(p->bibset, query_str, &error, &pos);
if (error)
{
- Tcl_AppendResult (interp, "CCL error: ",
- ccl_err_msg(error), NULL);
- return TCL_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
- assert((RPNquery = ccl_rpn_query(rpn)));
+ RPNquery = ccl_rpn_query(p->odr_out, rpn);
RPNquery->attributeSetId = oid_getoidbyent (&bib1);
query.which = Z_Query_type_1;
query.u.type_1 = RPNquery;
{
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]);
+ ccl_query.buf = (unsigned char *) query_str;
+ ccl_query.len = strlen (query_str);
}
else
{
- interp->result = "unknown query method";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "invalid query method ",
+ obj->set_inher.queryType, NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
}
- return ir_tcl_send_APDU (interp, p, apdu, "search", *argv);
+ 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_sortResponse: add sort response handler
+ */
+static int do_sortResponse (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+
+ if (argc == 0)
+ {
+ obj->sortResponse = NULL;
+ return TCL_OK;
+ }
+ else if (argc == -1)
+ return ir_tcl_strdel (interp, &obj->sortResponse);
+ if (argc == 3)
+ {
+ xfree (obj->sortResponse);
+ if (argv[2][0])
+ {
+ if (ir_tcl_strdup (interp, &obj->sortResponse, argv[2])
+ == TCL_ERROR)
+ return TCL_ERROR;
+ }
+ else
+ obj->sortResponse = NULL;
+ }
+ return TCL_OK;
+}
+
+/*
* do_resultCount: Get number of hits
*/
static int do_resultCount (void *o, Tcl_Interp *interp,
}
/*
+ * do_sortStatus: Get sort status (after sort response)
+ */
+static int do_sortStatus (void *o, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ IrTcl_SetObj *obj = o;
+ char *res;
+
+ if (argc <= 0)
+ {
+ obj->sortStatus = Z_SortStatus_failure;
+ return TCL_OK;
+ }
+ switch (obj->sortStatus)
+ {
+ case Z_SortStatus_success:
+ res = "success"; break;
+ case Z_SortStatus_partial_1:
+ res = "partial"; break;
+ case Z_SortStatus_failure:
+ res = "failure"; break;
+ default:
+ res = "unknown"; break;
+ }
+ Tcl_AppendElement (interp, res);
+ return TCL_OK;
+}
+
+/*
* do_nextResultSetPosition: Get next result set position
* (after search/present response)
*/
}
if (argc != 3)
{
- sprintf (interp->result, "wrong # args");
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
return TCL_ERROR;
}
if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
rl = find_IR_record (obj, offset);
if (!rl)
{
- logf (LOG_DEBUG, "No record at position %d", offset);
+ logf (LOG_DEBUG, "%s %s %s: no record", argv[0], argv[1], argv[2]);
return TCL_OK;
}
switch (rl->which)
}
if (argc != 3)
{
- sprintf (interp->result, "wrong # args");
+ 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 ir_tcl_strdel (NULL, &obj->recordElements);
if (argc > 3)
{
- sprintf (interp->result, "wrong # args");
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " ?position?\"", NULL);
return TCL_ERROR;
}
if (argc == 3)
return TCL_OK;
if (argc != 3)
{
- sprintf (interp->result, "wrong # args");
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
return TCL_ERROR;
}
if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
return TCL_OK;
if (argc < 7)
{
- sprintf (interp->result, "wrong # args");
+ 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_OK;
if (argc != 3)
{
- sprintf (interp->result, "wrong # args");
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " position\"", NULL);
return TCL_ERROR;
}
if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
Tcl_AppendResult (interp, "No DB record at #", argv[2], NULL);
return TCL_ERROR;
}
- if (rl->u.dbrec.type != VAL_SUTRS)
+ 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_getGrs: Get a GRS1 Record
+ * do_getGrs: Get a GRS-1 Record
*/
static int do_getGrs (void *o, Tcl_Interp *interp, int argc, char **argv)
{
return TCL_OK;
if (argc < 3)
{
- sprintf (interp->result, "wrong # args");
+ 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)
/*
+ * 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,
p = obj->parent;
if (!p->cs_link)
{
- interp->result = "present: not connected";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "not connected", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
-
obj->start = start;
obj->number = number;
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 no = 1;
+ int offset;
+ int start = 1;
+ int number = 30000;
char *buf;
-
+
if (argc <= 0)
return TCL_OK;
- if (argc != 3)
+ if (argc < 3)
{
- interp->result = "wrong # args";
+ 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 TCL_ERROR;
+ return ir_tcl_error_exec (interp, argc, argv);
}
- while ((buf = ir_tcl_fread_marc (inf, &size)))
+ while (offset < (start+number))
{
+ IrTcl_FileRecordHead head;
IrTcl_RecordList *rl;
- rl = new_IR_record (setobj, no, Z_NamePlusRecord_databaseRecord, "F");
- rl->u.dbrec.type = VAL_USMARC;
- rl->u.dbrec.buf = buf;
- rl->u.dbrec.size = size;
- no++;
+ 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 = no-1;
+ 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},
{ "getMarc", do_getMarc, NULL},
{ "getSutrs", do_getSutrs, 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},
{ NULL, NULL}
};
int argc, char **argv)
{
IrTcl_Methods tabs[3];
- IrTcl_SetObj *p = clientData;
+ IrTcl_SetObj *p = (IrTcl_SetObj *) clientData;
int r;
if (argc < 2)
{
- interp->result = "wrong # args";
+ Tcl_AppendResult (interp, wrongArgs, *argv, " method args...\"", NULL);
return TCL_ERROR;
}
tabs[0].tab = ir_set_method_tab;
tabs[1].obj = &p->set_inher;
tabs[2].tab = NULL;
- ir_tcl_method (interp, argc, argv, tabs, &r);
+ if (ir_tcl_method (interp, argc, argv, tabs, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tabs);
return r;
}
static void ir_set_obj_delete (ClientData clientData)
{
IrTcl_Methods tabs[3];
- IrTcl_SetObj *p = clientData;
+ IrTcl_SetObj *p = (IrTcl_SetObj *) clientData;
logf (LOG_DEBUG, "ir set delete");
if (argc < 2 || argc > 3)
{
- interp->result = "wrong # args";
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ " objSetName ?objParent?\"", NULL);
return TCL_ERROR;
}
obj = ir_tcl_malloc (sizeof(*obj));
if (ir_tcl_method (interp, 0, NULL, tabs, NULL) == TCL_ERROR)
return TCL_ERROR;
- *subData = obj;
+ *subData = (ClientData) obj;
return TCL_OK;
}
Tcl_CmdInfo parent_info;
if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info))
{
- interp->result = "No parent";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "no object parent", NULL);
+ return ir_tcl_error_exec (interp, argc, argv);
}
parentData = parent_info.clientData;
}
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)
{
- interp->result = "wrong # args";
+ Tcl_AppendResult (interp, wrongArgs, *argv, " ", argv[1],
+ " scanQuery\"", NULL);
return TCL_ERROR;
}
- logf (LOG_DEBUG, "scan %s %s", *argv, argv[2]);
+#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)
{
- interp->result = "no databaseNames";
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "no databaseNames", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
}
if (!p->cs_link)
{
- interp->result = "scan: not connected";
- return TCL_ERROR;
+ 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);
#if !CCL2RPN
if (!(req->termListAndStartPoint =
p_query_scan (p->odr_out, p->protocol_type,
- &req->attributeSet, argv[2])))
+ &req->attributeSet, start_term)))
{
- Tcl_AppendResult (interp, "Syntax error in query", NULL);
- return TCL_ERROR;
+ Tcl_AppendResult (interp, "query syntax error", NULL);
+ code = ir_tcl_error_exec (interp, argc, argv);
+ goto out;
}
#else
- rpn = ccl_find_str(p->bibset, argv[2], &r, &pos);
+ rpn = ccl_find_str(p->bibset, start_term, &r, &pos);
if (r)
{
- Tcl_AppendResult (interp, "CCL error: ", ccl_err_msg (r), NULL);
- return TCL_ERROR;
+ 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 (rpn)))
- return TCL_ERROR;
+ if (!(req->termListAndStartPoint = ccl_scan_query (p->odr_out, rpn)))
+ {
+ code = TCL_ERROR;
+ goto out;
+ }
#endif
req->stepSize = &obj->stepSize;
req->numberOfTermsRequested = &obj->numberOfTermsRequested;
logf (LOG_DEBUG, "preferredPositionInResponse=%d",
*req->preferredPositionInResponse);
- return ir_tcl_send_APDU (interp, p, apdu, "scan", *argv);
+ 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;
}
/*
}
if (argc != 3)
{
- interp->result = "wrong # args";
+ 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->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)
{
if (argc < 2)
{
- interp->result = "wrong # args";
+ 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;
- ir_tcl_method (interp, argc, argv, tabs, &r);
+ if (ir_tcl_method (interp, argc, argv, tabs, &r) == TCL_ERROR)
+ return ir_tcl_method_error (interp, argc, argv, tabs);
return r;
}
static void ir_scan_obj_delete (ClientData clientData)
{
IrTcl_Methods tabs[2];
- IrTcl_ScanObj *obj = clientData;
+ IrTcl_ScanObj *obj = (IrTcl_ScanObj *) clientData;
tabs[0].tab = ir_scan_method_tab;
tabs[0].obj = obj;
if (argc != 3)
{
- interp->result = "wrong # args";
+ 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))
{
- interp->result = "No parent";
- return TCL_ERROR;
+ 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;
/* ------------------------------------------------------- */
+/*
+ * ir_log_init_proc: set yaz log level
+ */
+static int ir_log_init_proc (ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv)
+{
+ if (argc <= 1 || argc > 4)
+ {
+ Tcl_AppendResult (interp, wrongArgs, *argv,
+ " ?level ?prefix ?filename\"", NULL);
+ return TCL_OK;
+ }
+ if (argc == 2)
+ yaz_log_init (yaz_log_mask_str (argv[1]), "", NULL);
+ else if (argc == 3)
+ yaz_log_init (yaz_log_mask_str (argv[1]), argv[2], NULL);
+ else
+ yaz_log_init (yaz_log_mask_str (argv[1]), argv[2], argv[3]);
+ 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;
}
static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_num,
- Z_DiagRec **list, int 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);
{
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);
}
}
-static void ir_handleRecords (void *o, Z_Records *zrs, IrTcl_SetObj *setobj,
+static void ir_handleDBRecord (IrTcl_Obj *p, IrTcl_RecordList *rl,
+ Z_External *oe)
+{
+ 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;
+
+ if ((ident = oid_getentbyoid (oe->direct_reference)))
+ rl->u.dbrec.type = ident->value;
+ else
+ rl->u.dbrec.type = VAL_USMARC;
+
+ if (ident && (oe->which == Z_External_single ||
+ oe->which == Z_External_octet)
+ && (etype = z_ext_getentbyref (ident->value)))
+ {
+ void *rr;
+
+ 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, 0))
+ {
+ rl->u.dbrec.type = VAL_NONE;
+ return;
+ }
+ switch (etype->what)
+ {
+ case Z_External_sutrs:
+ logf (LOG_DEBUG, "Z_External_sutrs");
+ oe->u.sutrs = rr;
+ if ((rl->u.dbrec.buf = ir_tcl_malloc (oe->u.sutrs->len+1)))
+ {
+ memcpy (rl->u.dbrec.buf, oe->u.sutrs->buf,
+ oe->u.sutrs->len);
+ rl->u.dbrec.buf[oe->u.sutrs->len] = '\0';
+ }
+ rl->u.dbrec.size = oe->u.sutrs->len;
+ break;
+ case Z_External_grs1:
+ logf (LOG_DEBUG, "Z_External_grs1");
+ oe->u.grs1 = rr;
+ ir_tcl_grs_mk (oe->u.grs1, &rl->u.dbrec.u.grs1);
+ break;
+ case Z_External_explainRecord:
+ logf (LOG_DEBUG, "Z_External_explainRecord");
+ if ((rl->u.dbrec.buf = ir_tcl_malloc (rl->u.dbrec.size)))
+ {
+ memcpy (rl->u.dbrec.buf, oe->u.octet_aligned->buf,
+ rl->u.dbrec.size);
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (oe->which == Z_External_octet && rl->u.dbrec.size > 0)
+ {
+ char *buf = (char*) oe->u.octet_aligned->buf;
+ if ((rl->u.dbrec.buf = ir_tcl_malloc (rl->u.dbrec.size)))
+ memcpy (rl->u.dbrec.buf, buf, rl->u.dbrec.size);
+ }
+ else if (rl->u.dbrec.type == VAL_SUTRS &&
+ oe->which == Z_External_sutrs)
+ {
+ if ((rl->u.dbrec.buf = ir_tcl_malloc (oe->u.sutrs->len+1)))
+ {
+ memcpy (rl->u.dbrec.buf, oe->u.sutrs->buf,
+ oe->u.sutrs->len);
+ rl->u.dbrec.buf[oe->u.sutrs->len] = '\0';
+ }
+ rl->u.dbrec.size = oe->u.sutrs->len;
+ }
+ else if (rl->u.dbrec.type == VAL_GRS1 &&
+ oe->which == Z_External_grs1)
+ {
+ ir_tcl_grs_mk (oe->u.grs1, &rl->u.dbrec.u.grs1);
+ }
+ }
+}
+
+static void ir_handleZRecords (void *o, Z_Records *zrs, IrTcl_SetObj *setobj,
const char *elements)
{
IrTcl_Obj *p = o;
&setobj->nonSurrogateDiagnosticNum);
if (zrs->which == Z_Records_DBOSD)
{
- setobj->numberOfRecordsReturned =
- zrs->u.databaseOrSurDiagnostics->num_records;
- logf (LOG_DEBUG, "Got %d records", setobj->numberOfRecordsReturned);
- for (offset = 0; offset<setobj->numberOfRecordsReturned; offset++)
+ int num_rec = zrs->u.databaseOrSurDiagnostics->num_records;
+
+ if (num_rec != setobj->numberOfRecordsReturned)
+ {
+ logf (LOG_WARN, "numberOfRecordsReturned=%d but num records=%d",
+ setobj->numberOfRecordsReturned, num_rec);
+ setobj->numberOfRecordsReturned = num_rec;
+ }
+
+ for (offset = 0; offset < num_rec; offset++)
{
- rl = new_IR_record (setobj, setobj->start + offset,
- zrs->u.databaseOrSurDiagnostics->
- records[offset]->which,
+ Z_NamePlusRecord *znpr = zrs->u.databaseOrSurDiagnostics->
+ records[offset];
+
+ rl = new_IR_record (setobj, setobj->start + offset, znpr->which,
elements);
if (rl->which == Z_NamePlusRecord_surrogateDiagnostic)
- {
ir_handleDiags (&rl->u.surrogateDiagnostics.list,
&rl->u.surrogateDiagnostics.num,
- &zrs->u.databaseOrSurDiagnostics->
- records[offset]->u.surrogateDiagnostic,
+ &znpr->u.surrogateDiagnostic,
1);
- }
else
- {
- Z_DatabaseRecord *zr;
- Z_External *oe;
- struct oident *ident;
-
- zr = zrs->u.databaseOrSurDiagnostics->records[offset]
- ->u.databaseRecord;
- oe = (Z_External*) zr;
- rl->u.dbrec.size = zr->u.octet_aligned->len;
-
- if ((ident = oid_getentbyoid (oe->direct_reference)))
- rl->u.dbrec.type = ident->value;
- else
- rl->u.dbrec.type = VAL_USMARC;
-
- if (oe->which == ODR_EXTERNAL_octet && rl->u.dbrec.size > 0)
- {
- char *buf = (char*) zr->u.octet_aligned->buf;
- if ((rl->u.dbrec.buf = ir_tcl_malloc (rl->u.dbrec.size)))
- memcpy (rl->u.dbrec.buf, buf, rl->u.dbrec.size);
- }
- else if (rl->u.dbrec.type == VAL_SUTRS &&
- oe->which == Z_External_sutrs)
- {
- odr_setbuf (p->odr_in, (char*) oe->u.single_ASN1_type->buf,
- oe->u.single_ASN1_type->len, 0);
- if ((rl->u.dbrec.buf = ir_tcl_malloc (oe->u.sutrs->len+1)))
- {
- memcpy (rl->u.dbrec.buf, oe->u.sutrs->buf,
- oe->u.sutrs->len);
- rl->u.dbrec.buf[oe->u.sutrs->len] = '\0';
- }
- rl->u.dbrec.size = oe->u.sutrs->len;
- }
- else if (rl->u.dbrec.type == VAL_GRS1 &&
- oe->which == Z_External_grs1)
- {
- ir_tcl_grs_mk (oe->u.grs1, &rl->u.dbrec.u.grs1);
- rl->u.dbrec.buf = NULL;
- }
- else
- rl->u.dbrec.buf = NULL;
- }
+ ir_handleDBRecord (p, rl,
+ (Z_External*) (znpr->u.databaseRecord));
}
}
else if (zrs->which == Z_Records_multipleNSD)
}
else
{
+#ifdef ASN_COMPILED
+ Z_DiagRec dr, *dr_p = &dr;
+ dr.which = Z_DiagRec_defaultFormat;
+ dr.u.defaultFormat = zrs->u.nonSurrogateDiagnostic;
+#else
+ Z_DiagRec *dr_p = zrs->u.nonSurrogateDiagnostic;
+#endif
logf (LOG_DEBUG, "NonSurrogateDiagnostic");
+
setobj->numberOfRecordsReturned = 0;
ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
&setobj->nonSurrogateDiagnosticNum,
- &zrs->u.nonSurrogateDiagnostic,
- 1);
+ &dr_p, 1);
}
}
logf (LOG_DEBUG, "Search response, no object!");
return;
}
- setobj->searchStatus = searchrs->searchStatus ? 1 : 0;
+ setobj->searchStatus = *searchrs->searchStatus;
get_referenceId (&setobj->set_inher.referenceId, searchrs->referenceId);
setobj->resultCount = *searchrs->resultCount;
if (searchrs->presentStatus)
setobj->presentStatus = *searchrs->presentStatus;
+ else
+ setobj->presentStatus = Z_RES_NONE;
if (searchrs->nextResultSetPosition)
setobj->nextResultSetPosition = *searchrs->nextResultSetPosition;
es = setobj->set_inher.smallSetElementSetNames;
else
es = setobj->set_inher.mediumSetElementSetNames;
- ir_handleRecords (o, zrs, setobj, es);
+ setobj->numberOfRecordsReturned = *searchrs->numberOfRecordsReturned;
+ ir_handleZRecords (o, zrs, setobj, es);
}
else
+ {
+ setobj->numberOfRecordsReturned = 0;
setobj->recordFlag = 0;
+ }
}
get_referenceId (&setobj->set_inher.referenceId, presrs->referenceId);
setobj->nextResultSetPosition = *presrs->nextResultSetPosition;
if (zrs)
- ir_handleRecords (o, zrs, setobj, setobj->set_inher.elementSetNames);
+ {
+ setobj->numberOfRecordsReturned = *presrs->numberOfRecordsReturned;
+ ir_handleZRecords (o, zrs, setobj, setobj->set_inher.elementSetNames);
+ }
else
{
+ setobj->numberOfRecordsReturned = 0;
setobj->recordFlag = 0;
logf (LOG_DEBUG, "No records!");
}
xfree (scanobj->entries);
scanobj->entries = NULL;
-
+ scanobj->num_entries = 0;
+ scanobj->entries_flag = 0;
+
ir_deleteDiags (&scanobj->nonSurrogateDiagnosticList,
&scanobj->nonSurrogateDiagnosticNum);
if (scanrs->entries)
{
int i;
- Z_Entry *ze;
+ Z_Entry **ze;
scanobj->entries_flag = 1;
- scanobj->which = scanrs->entries->which;
- switch (scanobj->which)
- {
- case Z_ListEntries_entries:
- scanobj->num_entries = scanrs->entries->u.entries->num_entries;
+ if (scanrs->entries)
+ {
+ scanobj->num_entries = scanrs->entries->num_entries;
scanobj->entries = ir_tcl_malloc (scanobj->num_entries *
- sizeof(*scanobj->entries));
- for (i=0; i<scanobj->num_entries; i++)
- {
- ze = scanrs->entries->u.entries->entries[i];
- scanobj->entries[i].which = ze->which;
- switch (ze->which)
- {
- case Z_Entry_termInfo:
- if (ze->u.termInfo->term->which == Z_Term_general)
- {
- int l = ze->u.termInfo->term->u.general->len;
- scanobj->entries[i].u.term.buf = ir_tcl_malloc (1+l);
- memcpy (scanobj->entries[i].u.term.buf,
- ze->u.termInfo->term->u.general->buf,
- l);
- scanobj->entries[i].u.term.buf[l] = '\0';
- }
- else
- scanobj->entries[i].u.term.buf = NULL;
- if (ze->u.termInfo->globalOccurrences)
- scanobj->entries[i].u.term.globalOccurrences =
- *ze->u.termInfo->globalOccurrences;
- else
- scanobj->entries[i].u.term.globalOccurrences = 0;
- break;
- case Z_Entry_surrogateDiagnostic:
- ir_handleDiags (&scanobj->entries[i].u.diag.list,
- &scanobj->entries[i].u.diag.num,
- &ze->u.surrogateDiagnostic,
- 1);
- break;
- }
- }
- break;
- case Z_ListEntries_nonSurrogateDiagnostics:
- ir_handleDiags (&scanobj->nonSurrogateDiagnosticList,
+ sizeof(*scanobj->entries));
+ ze = scanrs->entries->entries;
+ }
+ for (i=0; i<scanobj->num_entries; i++, ze++)
+ {
+ scanobj->entries[i].which = (*ze)->which;
+ switch ((*ze)->which)
+ {
+ case Z_Entry_termInfo:
+ if ((*ze)->u.termInfo->term->which == Z_Term_general)
+ {
+ int l = (*ze)->u.termInfo->term->u.general->len;
+ scanobj->entries[i].u.term.buf = ir_tcl_malloc (1+l);
+ memcpy (scanobj->entries[i].u.term.buf,
+ (*ze)->u.termInfo->term->u.general->buf,
+ l);
+ scanobj->entries[i].u.term.buf[l] = '\0';
+ }
+ else
+ scanobj->entries[i].u.term.buf = NULL;
+ if ((*ze)->u.termInfo->globalOccurrences)
+ scanobj->entries[i].u.term.globalOccurrences =
+ *(*ze)->u.termInfo->globalOccurrences;
+ else
+ scanobj->entries[i].u.term.globalOccurrences = 0;
+ break;
+ case Z_Entry_surrogateDiagnostic:
+ ir_handleDiags (&scanobj->entries[i].u.diag.list,
+ &scanobj->entries[i].u.diag.num,
+ &(*ze)->u.surrogateDiagnostic,
+ 1);
+ break;
+ }
+ }
+ if (scanrs->entries->nonsurrogateDiagnostics)
+ ir_handleDiags (&scanobj->nonSurrogateDiagnosticList,
&scanobj->nonSurrogateDiagnosticNum,
- scanrs->entries->u.nonSurrogateDiagnostics->
- diagRecs,
- scanrs->entries->u.nonSurrogateDiagnostics->
- num_diagRecs);
- break;
- }
+ scanrs->entries->nonsurrogateDiagnostics,
+ scanrs->entries->num_nonsurrogateDiagnostics);
}
- else
- scanobj->entries_flag = 0;
+}
+
+
+static void ir_sortResponse (void *o, Z_SortResponse *sortrs,
+ IrTcl_SetObj *setobj)
+{
+ IrTcl_Obj *p = o;
+
+ logf (LOG_DEBUG, "Received sortResponse");
+
+ if (!setobj)
+ return;
+
+ purge_IR_records (setobj);
+
+ get_referenceId (&p->set_inher.referenceId, sortrs->referenceId);
+
+ setobj->sortStatus = *sortrs->sortStatus;
+
+ ir_deleteDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum);
+#ifdef ASN_COMPILED
+ if (sortrs->diagnostics)
+ ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum,
+ sortrs->diagnostics,
+ sortrs->num_diagnostics);
+#else
+ if (sortrs->diagnostics)
+ ir_handleDiags (&setobj->nonSurrogateDiagnosticList,
+ &setobj->nonSurrogateDiagnosticNum,
+ sortrs->diagnostics->diagRecs,
+ sortrs->diagnostics->num_diagRecs);
+#endif
}
/*
*/
static void ir_select_read (ClientData clientData)
{
- IrTcl_Obj *p = clientData;
+ IrTcl_Obj *p = (IrTcl_Obj *) clientData;
Z_APDU *apdu;
int r;
IrTcl_Request *rq;
p->failInfo = IR_TCL_FAIL_CONNECT;
ir_tcl_eval (p->interp, p->failback);
}
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return;
}
if (p->callback)
if (p->ref_count == 2 && p->cs_link && p->request_queue
&& p->state == IR_TCL_R_Idle)
ir_tcl_send_q (p, p->request_queue, "x");
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return;
}
do
if (r <= 0)
{
logf (LOG_DEBUG, "cs_get failed, code %d", r);
- ir_select_remove (cs_fileno (p->cs_link), p);
ir_tcl_disconnect (p);
if (p->failback)
{
ir_tcl_eval (p->interp, p->failback);
}
/* release ir object now if callback deleted it */
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return;
}
/* got complete APDU. Now decode */
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)));
ir_tcl_eval (p->interp, p->failback);
}
/* release ir object now if failback deleted it */
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return;
}
/* handle APDU and invoke callback */
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);
odr_reset (p->odr_in);
if (p->ref_count == 1)
{
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return;
}
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
} while (p->cs_link && cs_more (p->cs_link));
if (p->cs_link && p->request_queue && p->state == IR_TCL_R_Idle)
ir_tcl_send_q (p, p->request_queue, "x");
*/
static int ir_select_write (ClientData clientData)
{
- IrTcl_Obj *p = clientData;
+ IrTcl_Obj *p = (IrTcl_Obj *) clientData;
int r;
IrTcl_Request *rq;
p->failInfo = IR_TCL_FAIL_CONNECT;
ir_tcl_eval (p->interp, p->failback);
}
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return 2;
}
if (p->callback)
ir_tcl_eval (p->interp, p->callback);
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
return 2;
}
rq = p->request_queue;
p->failInfo = IR_TCL_FAIL_WRITE;
ir_tcl_eval (p->interp, p->failback);
}
- ir_obj_delete (p);
+ ir_obj_delete ((ClientData) p);
}
else if (r == 0) /* remove select bit */
{
}
}
-/* ------------------------------------------------------- */
+/*----------------------------------------------------------- */
+/*
+ * DllEntryPoint --
+ *
+ * This wrapper function is used by Windows to invoke the
+ * initialization code for the DLL. If we are compiling
+ * with Visual C++, this routine will be renamed to DllMain.
+ * routine.
+ *
+ * Results:
+ * Returns TRUE;
+ *
+ * Side effects:
+ * None.
+ */
+
+#ifdef __WIN32__
+BOOL APIENTRY
+DllEntryPoint(hInst, reason, reserved)
+ HINSTANCE hInst; /* Library instance handle. */
+ DWORD reason; /* Reason this function is being called. */
+ LPVOID reserved; /* Not used. */
+{
+ return TRUE;
+}
+#endif
+/* ------------------------------------------------------- */
/*
* Irtcl_init: Registration of TCL commands.
*/
-int Irtcl_Init (Tcl_Interp *interp)
+EXPORT (int,Irtcl_Init) (Tcl_Interp *interp)
{
Tcl_CreateCommand (interp, "ir", ir_obj_mk, (ClientData) NULL,
(Tcl_CmdDeleteProc *) NULL);
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand (interp, "ir-scan", ir_scan_obj_mk,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand (interp, "ir-log-init", ir_log_init_proc,
+ (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;
}