X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=ir-tcl.c;h=9eddd5f47ea5e70a9822917ae45e347333a28057;hb=c10f5ecfbd81e3a9bda4cca310e13b066a520f4a;hp=ddd1cbd5cc41c66f8973f16d9d973a22f730750d;hpb=8caa5a124f21ce80bd6a4a02576bf00d38096d32;p=ir-tcl-moved-to-github.git diff --git a/ir-tcl.c b/ir-tcl.c index ddd1cbd..9eddd5f 100644 --- a/ir-tcl.c +++ b/ir-tcl.c @@ -5,7 +5,93 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: ir-tcl.c,v $ - * Revision 1.51 1995-08-03 13:22:54 adam + * Revision 1.75 1996-02-19 15:41:53 adam + * Better log messages. + * Minor improvement of connect method. + * + * Revision 1.74 1996/02/05 17:58:03 adam + * Ported ir-tcl to use the beta releases of tcl7.5/tk4.1. + * + * Revision 1.73 1996/01/29 11:35:19 adam + * Bug fix: cs_type member renamed to comstackType to avoid conflict with + * cs_type macro defined by YAZ. + * + * Revision 1.72 1996/01/19 17:45:34 quinn + * Added debugging output + * + * Revision 1.71 1996/01/19 16:22:38 adam + * New method: apduDump - returns information about last incoming APDU. + * + * Revision 1.70 1996/01/10 09:18:34 adam + * PDU specific callbacks implemented: initRespnse, searchResponse, + * presentResponse and scanResponse. + * Bug fix in the command line shell (tclmain.c) - discovered on OSF/1. + * + * Revision 1.69 1996/01/04 16:12:12 adam + * Setting PDUType renamed to eventType. + * + * Revision 1.68 1996/01/04 11:05:22 adam + * New setting: PDUType - returns type of last PDU returned from the target. + * Fixed a bug in configure/Makefile. + * + * Revision 1.67 1996/01/03 09:00:51 adam + * Updated to use new version of Yaz (names changed to avoid C++ conflict). + * + * Revision 1.66 1995/11/28 17:26:39 adam + * Removed Carriage return from ir-tcl.c! + * Removed misc. debug logs. + * + * Revision 1.65 1995/11/28 13:53:00 quinn + * Windows port. + * + * Revision 1.64 1995/11/13 15:39:18 adam + * Bug fix: {small,medium}SetElementSetNames weren't set correctly. + * Bug fix: idAuthentication weren't set correctly. + * + * Revision 1.63 1995/11/13 09:55:39 adam + * Multiple records at a position in a result-set with differnt + * element specs. + * + * Revision 1.62 1995/10/18 17:20:33 adam + * Work on target setup in client.tcl. + * + * Revision 1.61 1995/10/18 16:42:42 adam + * New settings: smallSetElementSetNames and mediumSetElementSetNames. + * + * Revision 1.60 1995/10/18 15:43:31 adam + * In search: mediumSetElementSetNames and smallSetElementSetNames are + * set to elementSetNames. + * + * Revision 1.59 1995/10/17 12:18:58 adam + * Bug fix: when target connection closed, the connection was not + * properly reestablished. + * + * Revision 1.58 1995/10/16 17:00:55 adam + * New setting: elementSetNames. + * Various client improvements. Medium presentation format looks better. + * + * Revision 1.57 1995/09/21 13:11:51 adam + * Support of dynamic loading. + * Test script uses load command if necessary. + * + * Revision 1.56 1995/08/29 15:30:14 adam + * Work on GRS records. + * + * Revision 1.55 1995/08/28 09:43:25 adam + * Minor changes. configure only searches for yaz beta 3 and versions after + * that. + * + * Revision 1.54 1995/08/24 12:25:16 adam + * Modified to work with yaz 1.0b3. + * + * Revision 1.53 1995/08/04 12:49:26 adam + * Bug fix: reading uninitialized variable p. + * + * Revision 1.52 1995/08/04 11:32:38 adam + * More work on output queue. Memory related routines moved + * to mem.c + * + * Revision 1.51 1995/08/03 13:22:54 adam * Request queue. * * Revision 1.50 1995/07/20 08:09:49 adam @@ -182,7 +268,8 @@ #include #include -#include +#include +#include #include #define CS_BLOCK 0 @@ -200,26 +287,27 @@ typedef struct { IrTcl_Method *tab; } IrTcl_Methods; -static Tcl_Interp *irTcl_interp; - static void ir_deleteDiags (IrTcl_Diagnostic **dst_list, int *dst_num); static int do_disconnect (void *obj, Tcl_Interp *interp, int argc, char **argv); static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj, - int no, int which) + int no, int which, + const char *elements) { IrTcl_RecordList *rl; for (rl = setobj->record_list; rl; rl = rl->next) { - if (no == rl->no) + if (no == rl->no && (!rl->elements || !elements || + !strcmp(elements, rl->elements))) { + free (rl->elements); switch (rl->which) { case Z_NamePlusRecord_databaseRecord: - free (rl->u.dbrec.buf); - rl->u.dbrec.buf = NULL; + free (rl->u.dbrec.buf); + rl->u.dbrec.buf = NULL; break; case Z_NamePlusRecord_surrogateDiagnostic: ir_deleteDiags (&rl->u.surrogateDiagnostics.list, @@ -231,13 +319,13 @@ static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj, } if (!rl) { - rl = malloc (sizeof(*rl)); - assert (rl); + rl = ir_tcl_malloc (sizeof(*rl)); rl->next = setobj->record_list; rl->no = no; setobj->record_list = rl; } rl->which = which; + ir_tcl_strdup (NULL, &rl->elements, elements); return rl; } @@ -261,6 +349,7 @@ static struct { { VAL_AUSMARC, "AUSMARC" }, { VAL_IBERMARC, "IBERMARC" }, { VAL_SUTRS, "SUTRS" }, +{ VAL_GRS1, "GRS1" }, { 0, NULL } }; @@ -269,14 +358,9 @@ static struct { */ int IrTcl_eval (Tcl_Interp *interp, const char *command) { - char *tmp = malloc (strlen(command)+1); + char *tmp = ir_tcl_malloc (strlen(command)+1); int r; - if (!tmp) - { - logf (LOG_FATAL, "Out of memory in IrTcl_eval"); - exit (1); - } strcpy (tmp, command); r = Tcl_Eval (interp, tmp); if (r == TCL_ERROR) @@ -316,7 +400,9 @@ static IrTcl_RecordList *find_IR_record (IrTcl_SetObj *setobj, int no) IrTcl_RecordList *rl; for (rl = setobj->record_list; rl; rl = rl->next) - if (no == rl->no) + if (no == rl->no && + (!setobj->recordElements || !rl->elements || + !strcmp (setobj->recordElements, rl->elements))) return rl; return NULL; } @@ -330,15 +416,15 @@ static void delete_IR_records (IrTcl_SetObj *setobj) switch (rl->which) { case Z_NamePlusRecord_databaseRecord: - free (rl->u.dbrec.buf); + free (rl->u.dbrec.buf); break; case Z_NamePlusRecord_surrogateDiagnostic: ir_deleteDiags (&rl->u.surrogateDiagnostics.list, &rl->u.surrogateDiagnostics.num); break; - } - rl1 = rl->next; - free (rl); + } + rl1 = rl->next; + free (rl); } setobj->record_list = NULL; } @@ -370,12 +456,12 @@ int ir_method (Tcl_Interp *interp, int argc, char **argv, IrTcl_Methods *tab) for (tab_i = tab; tab_i->tab; tab_i++) for (t = tab_i->tab; t->name; t++) - if (argc <= 0) - { - if ((*t->method)(tab_i->obj, interp, argc, argv) == TCL_ERROR) - return TCL_ERROR; + if (argc <= 0) + { + if ((*t->method)(tab_i->obj, interp, argc, argv) == TCL_ERROR) + return TCL_ERROR; } - else + else if (!strcmp (t->name, argv[1])) return (*t->method)(tab_i->obj, interp, argc, argv); @@ -444,53 +530,6 @@ int ir_named_bits (struct ir_named_entry *tab, Odr_bitmask *ob, return TCL_OK; } -/* - * ir_strdup: Duplicate string - */ -int ir_strdup (Tcl_Interp *interp, char** p, const char *s) -{ - if (!s) - { - *p = NULL; - return TCL_OK; - } - *p = malloc (strlen(s)+1); - if (!*p) - { - interp->result = "strdup fail"; - return TCL_ERROR; - } - strcpy (*p, s); - return TCL_OK; -} - -/* - * ir_strdel: Delete string - */ -int ir_strdel (Tcl_Interp *interp, char **p) -{ - free (*p); - *p = NULL; - return TCL_OK; -} - -/* - * ir_malloc: Malloc function - */ -void *ir_malloc (Tcl_Interp *interp, size_t size) -{ - static char buf[128]; - void *p = malloc (size); - - if (!p) - { - sprintf (buf, "Malloc fail. %ld bytes requested", (long) size); - interp->result = buf; - return NULL; - } - return p; -} - static void set_referenceId (ODR o, Z_ReferenceId **dst, const char *src) { if (!src || !*src) @@ -498,9 +537,9 @@ static void set_referenceId (ODR o, Z_ReferenceId **dst, const char *src) else { *dst = odr_malloc (o, sizeof(**dst)); - (*dst)->size = (*dst)->len = strlen(src); - (*dst)->buf = odr_malloc (o, (*dst)->len); - memcpy ((*dst)->buf, src, (*dst)->len); + (*dst)->size = (*dst)->len = strlen(src); + (*dst)->buf = odr_malloc (o, (*dst)->len); + memcpy ((*dst)->buf, src, (*dst)->len); } } @@ -510,50 +549,15 @@ static void get_referenceId (char **dst, Z_ReferenceId *src) if (!src) { *dst = NULL; - return; + return; } - *dst = malloc (src->len+1); + *dst = ir_tcl_malloc (src->len+1); memcpy (*dst, src->buf, src->len); (*dst)[src->len] = '\0'; } /* ------------------------------------------------------- */ -#if 0 -/* - * ir-tcl_send_APDU: send APDU - */ -static int ir_tcl_send_APDU (Tcl_Interp *interp, IrTcl_Obj *p, Z_APDU *apdu, - const char *msg) -{ - int r; - - if (!z_APDU (p->odr_out, &apdu, 0)) - { - Tcl_AppendResult (interp, odr_errlist [odr_geterror (p->odr_out)], - NULL); - odr_reset (p->odr_out); - return TCL_ERROR; - } - p->sbuf = odr_getbuf (p->odr_out, &p->slen, NULL); - odr_reset (p->odr_out); - if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0) - { - sprintf (interp->result, "cs_put failed in %s", msg); - do_disconnect (p, NULL, 2, NULL); - return TCL_ERROR; - } - else if (r == 1) - { - ir_select_add_write (cs_fileno(p->cs_link), p); - logf (LOG_DEBUG, "Sent part of %s (%d bytes)", msg, p->slen); - } - else - logf (LOG_DEBUG, "Sent whole %s (%d bytes)", msg, p->slen); - return TCL_OK; -} -#endif - /* * do_init_request: init method on IR object */ @@ -568,7 +572,7 @@ static int do_init_request (void *obj, Tcl_Interp *interp, return TCL_OK; if (!p->cs_link) { - interp->result = "not connected"; + interp->result = "init: not connected"; return TCL_ERROR; } apdu = zget_APDU (p->odr_out, Z_APDU_initRequest); @@ -585,6 +589,8 @@ static int do_init_request (void *obj, Tcl_Interp *interp, Z_IdPass *pass = odr_malloc (p->odr_out, sizeof(*pass)); Z_IdAuthentication *auth = odr_malloc (p->odr_out, sizeof(*auth)); + logf (LOG_DEBUG, "using pass authentication"); + auth->which = Z_IdAuthentication_idPass; auth->u.idPass = pass; if (p->idAuthenticationGroupId && *p->idAuthenticationGroupId) @@ -607,6 +613,7 @@ static int do_init_request (void *obj, Tcl_Interp *interp, { Z_IdAuthentication *auth = odr_malloc (p->odr_out, sizeof(*auth)); + logf (LOG_DEBUG, "using open authentication"); auth->which = Z_IdAuthentication_open; auth->u.open = p->idAuthenticationOpen; req->idAuthentication = auth; @@ -616,7 +623,7 @@ static int do_init_request (void *obj, Tcl_Interp *interp, req->implementationVersion = p->implementationVersion; req->userInformationField = 0; - return ir_tcl_send_APDU (interp, p, apdu, "init"); + return ir_tcl_send_APDU (interp, p, apdu, "init", *argv); } /* @@ -632,8 +639,8 @@ static int do_protocolVersion (void *obj, Tcl_Interp *interp, if (argc <= 0) { ODR_MASK_ZERO (&p->protocolVersion); - ODR_MASK_SET (&p->protocolVersion, 0); - ODR_MASK_SET (&p->protocolVersion, 1); + ODR_MASK_SET (&p->protocolVersion, 0); + ODR_MASK_SET (&p->protocolVersion, 1); return TCL_OK; } if (argc == 3) @@ -680,17 +687,65 @@ static int do_options (void *obj, Tcl_Interp *interp, if (argc <= 0) { ODR_MASK_ZERO (&p->options); - ODR_MASK_SET (&p->options, 0); - ODR_MASK_SET (&p->options, 1); + ODR_MASK_SET (&p->options, 0); + ODR_MASK_SET (&p->options, 1); ODR_MASK_SET (&p->options, 4); - ODR_MASK_SET (&p->options, 7); - ODR_MASK_SET (&p->options, 14); - return TCL_OK; + ODR_MASK_SET (&p->options, 7); + ODR_MASK_SET (&p->options, 14); + return TCL_OK; } return ir_named_bits (options_tab, &p->options, interp, argc-2, argv+2); } /* + * do_apduInfo: Get APDU information + */ +static int do_apduInfo (void *obj, Tcl_Interp *interp, int argc, char **argv) +{ + char buf[16]; + FILE *apduf; + IrTcl_Obj *p = obj; + + if (argc <= 0) + return TCL_OK; + sprintf (buf, "%d", p->apduLen); + Tcl_AppendElement (interp, buf); + sprintf (buf, "%d", p->apduOffset); + Tcl_AppendElement (interp, buf); + if (!p->buf_in) + { + Tcl_AppendElement (interp, ""); + return TCL_OK; + } + apduf = fopen ("apdu.tmp", "w"); + if (!apduf) + { + Tcl_AppendElement (interp, ""); + return TCL_OK; + } + odr_dumpBER (apduf, p->buf_in, p->apduLen); + fclose (apduf); + if (!(apduf = fopen ("apdu.tmp", "r"))) + Tcl_AppendElement (interp, ""); + else + { + int c; + + Tcl_AppendResult (interp, " {", NULL); + while ((c = getc (apduf)) != EOF) + { + buf[0] = c; + buf[1] = '\0'; + Tcl_AppendResult (interp, buf, NULL); + } + fclose (apduf); + Tcl_AppendResult (interp, "}", NULL); + } + unlink ("apdu.tmp"); + return TCL_OK; +} + +/* * do_failInfo: Get fail information */ static int do_failInfo (void *obj, Tcl_Interp *interp, int argc, char **argv) @@ -701,7 +756,7 @@ static int do_failInfo (void *obj, Tcl_Interp *interp, int argc, char **argv) if (argc <= 0) { p->failInfo = 0; - return TCL_OK; + return TCL_OK; } sprintf (buf, "%d", p->failInfo); switch (p->failInfo) @@ -743,7 +798,7 @@ static int do_preferredMessageSize (void *obj, Tcl_Interp *interp, if (argc <= 0) { p->preferredMessageSize = 30000; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->preferredMessageSize, interp, argc, argv); } @@ -759,7 +814,7 @@ static int do_maximumRecordSize (void *obj, Tcl_Interp *interp, if (argc <= 0) { p->maximumRecordSize = 30000; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->maximumRecordSize, interp, argc, argv); } @@ -787,14 +842,14 @@ static int do_implementationName (void *obj, Tcl_Interp *interp, IrTcl_Obj *p = obj; if (argc == 0) - return ir_strdup (interp, &p->implementationName, + return ir_tcl_strdup (interp, &p->implementationName, "Index Data/IrTcl on YAZ"); else if (argc == -1) - return ir_strdel (interp, &p->implementationName); + return ir_tcl_strdel (interp, &p->implementationName); if (argc == 3) { free (p->implementationName); - if (ir_strdup (interp, &p->implementationName, argv[2]) + if (ir_tcl_strdup (interp, &p->implementationName, argv[2]) == TCL_ERROR) return TCL_ERROR; } @@ -811,9 +866,9 @@ static int do_implementationId (void *obj, Tcl_Interp *interp, IrTcl_Obj *p = obj; if (argc == 0) - return ir_strdup (interp, &p->implementationId, "YAZ (id=81)"); + return ir_tcl_strdup (interp, &p->implementationId, "YAZ (id=81)"); else if (argc == -1) - return ir_strdel (interp, &p->implementationId); + return ir_tcl_strdel (interp, &p->implementationId); Tcl_AppendResult (interp, p->implementationId, (char*) NULL); return TCL_OK; } @@ -827,10 +882,10 @@ static int do_implementationVersion (void *obj, Tcl_Interp *interp, IrTcl_Obj *p = obj; if (argc == 0) - return ir_strdup (interp, &p->implementationVersion, + return ir_tcl_strdup (interp, &p->implementationVersion, "YAZ: " YAZ_VERSION " / IrTcl: " IR_TCL_VERSION); else if (argc == -1) - return ir_strdel (interp, &p->implementationVersion); + return ir_tcl_strdel (interp, &p->implementationVersion); Tcl_AppendResult (interp, p->implementationVersion, (char*) NULL); return TCL_OK; } @@ -846,10 +901,10 @@ static int do_targetImplementationName (void *obj, Tcl_Interp *interp, if (argc == 0) { p->targetImplementationName = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->targetImplementationName); + return ir_tcl_strdel (interp, &p->targetImplementationName); Tcl_AppendResult (interp, p->targetImplementationName, (char*) NULL); return TCL_OK; } @@ -865,10 +920,10 @@ static int do_targetImplementationId (void *obj, Tcl_Interp *interp, if (argc == 0) { p->targetImplementationId = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->targetImplementationId); + return ir_tcl_strdel (interp, &p->targetImplementationId); Tcl_AppendResult (interp, p->targetImplementationId, (char*) NULL); return TCL_OK; } @@ -884,10 +939,10 @@ static int do_targetImplementationVersion (void *obj, Tcl_Interp *interp, if (argc == 0) { p->targetImplementationVersion = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->targetImplementationVersion); + return ir_tcl_strdel (interp, &p->targetImplementationVersion); Tcl_AppendResult (interp, p->targetImplementationVersion, (char*) NULL); return TCL_OK; } @@ -920,19 +975,23 @@ static int do_idAuthentication (void *obj, Tcl_Interp *interp, { if (argc == 3) { - if (ir_strdup (interp, &p->idAuthenticationOpen, argv[2]) + if (argv[2][0] && + ir_tcl_strdup (interp, &p->idAuthenticationOpen, argv[2]) == TCL_ERROR) return TCL_ERROR; } else if (argc == 5) { - if (ir_strdup (interp, &p->idAuthenticationGroupId, argv[2]) + if (argv[2][0] && + ir_tcl_strdup (interp, &p->idAuthenticationGroupId, argv[2]) == TCL_ERROR) return TCL_ERROR; - if (ir_strdup (interp, &p->idAuthenticationUserId, argv[3]) + if (argv[3][0] && + ir_tcl_strdup (interp, &p->idAuthenticationUserId, argv[3]) == TCL_ERROR) return TCL_ERROR; - if (ir_strdup (interp, &p->idAuthenticationPassword, argv[4]) + if (argv[4][0] && + ir_tcl_strdup (interp, &p->idAuthenticationPassword, argv[4]) == TCL_ERROR) return TCL_ERROR; } @@ -952,7 +1011,7 @@ static int do_idAuthentication (void *obj, Tcl_Interp *interp, * do_connect: connect method on IR object */ static int do_connect (void *obj, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { void *addr; IrTcl_Obj *p = obj; @@ -967,7 +1026,7 @@ static int do_connect (void *obj, Tcl_Interp *interp, interp->result = "already connected"; return TCL_ERROR; } - if (!strcmp (p->cs_type, "tcpip")) + if (!strcmp (p->comstackType, "tcpip")) { p->cs_link = cs_create (tcpip_type, CS_BLOCK, p->protocol_type); addr = tcpip_strtoaddr (argv[2]); @@ -978,7 +1037,7 @@ static int do_connect (void *obj, Tcl_Interp *interp, } logf (LOG_DEBUG, "tcp/ip connect %s", argv[2]); } - else if (!strcmp (p->cs_type, "mosi")) + else if (!strcmp (p->comstackType, "mosi")) { #if MOSI p->cs_link = cs_create (mosi_type, CS_BLOCK, p->protocol_type); @@ -997,21 +1056,39 @@ static int do_connect (void *obj, Tcl_Interp *interp, else { Tcl_AppendResult (interp, "Bad comstack type: ", - p->cs_type, NULL); + p->comstackType, NULL); return TCL_ERROR; } - if (ir_strdup (interp, &p->hostname, argv[2]) == TCL_ERROR) + if (ir_tcl_strdup (interp, &p->hostname, argv[2]) == TCL_ERROR) return TCL_ERROR; +#if IRTCL_GENERIC_FILES +#ifdef WINDOWS + p->csFile = Tcl_GetFile (cs_fileno(p->cs_link), TCL_WIN_SOCKET); +#else + p->csFile = Tcl_GetFile (cs_fileno(p->cs_link), TCL_UNIX_FD); +#endif +#endif if ((r=cs_connect (p->cs_link, addr)) < 0) { interp->result = "connect fail"; do_disconnect (p, NULL, 2, NULL); return TCL_ERROR; } + logf(LOG_DEBUG, "cs_connect() returned %d fd=%d", r, + cs_fileno(p->cs_link)); + p->eventType = "connect"; +#if IRTCL_GENERIC_FILES + ir_select_add (p->csFile, p); +#else ir_select_add (cs_fileno (p->cs_link), p); +#endif if (r == 1) { +#if IRTCL_GENERIC_FILES + ir_select_add_write (p->csFile, p); +#else ir_select_add_write (cs_fileno (p->cs_link), p); +#endif p->state = IR_TCL_R_Connecting; } else @@ -1021,6 +1098,8 @@ static int do_connect (void *obj, Tcl_Interp *interp, IrTcl_eval (p->interp, p->callback); } } + else + Tcl_AppendResult (interp, p->hostname, NULL); return TCL_OK; } @@ -1035,31 +1114,48 @@ static int do_disconnect (void *obj, Tcl_Interp *interp, if (argc == 0) { p->state = IR_TCL_R_Idle; + p->eventType = NULL; p->hostname = NULL; - p->cs_link = NULL; + p->cs_link = NULL; +#if IRTCL_GENERIC_FILES + p->csFile = 0; +#endif return TCL_OK; } if (p->hostname) { + logf(LOG_DEBUG, "Closing connection to %s", p->hostname); free (p->hostname); p->hostname = NULL; +#if IRTCL_GENERIC_FILES + ir_select_remove_write (p->csFile, p); + ir_select_remove (p->csFile, p); +#else ir_select_remove_write (cs_fileno (p->cs_link), p); ir_select_remove (cs_fileno (p->cs_link), p); +#endif + + odr_reset (p->odr_in); assert (p->cs_link); cs_close (p->cs_link); p->cs_link = NULL; +#if IRTCL_GENERIC_FILES + Tcl_FreeFile (p->csFile); + p->csFile = NULL; +#endif ODR_MASK_ZERO (&p->options); - ODR_MASK_SET (&p->options, 0); - ODR_MASK_SET (&p->options, 1); - ODR_MASK_SET (&p->options, 4); - ODR_MASK_SET (&p->options, 7); - ODR_MASK_SET (&p->options, 14); + ODR_MASK_SET (&p->options, 0); + ODR_MASK_SET (&p->options, 1); + ODR_MASK_SET (&p->options, 4); + ODR_MASK_SET (&p->options, 7); + ODR_MASK_SET (&p->options, 14); ODR_MASK_ZERO (&p->protocolVersion); - ODR_MASK_SET (&p->protocolVersion, 0); - ODR_MASK_SET (&p->protocolVersion, 1); + ODR_MASK_SET (&p->protocolVersion, 0); + ODR_MASK_SET (&p->protocolVersion, 1); + ir_tcl_del_q (p); } assert (!p->cs_link); return TCL_OK; @@ -1069,21 +1165,56 @@ static int do_disconnect (void *obj, Tcl_Interp *interp, * do_comstack: Set/get comstack method on IR object */ static int do_comstack (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_Obj *obj = o; if (argc == 0) - return ir_strdup (interp, &obj->cs_type, "tcpip"); + return ir_tcl_strdup (interp, &obj->comstackType, "tcpip"); else if (argc == -1) - return ir_strdel (interp, &obj->cs_type); + return ir_tcl_strdel (interp, &obj->comstackType); else if (argc == 3) { - free (obj->cs_type); - if (ir_strdup (interp, &obj->cs_type, argv[2]) == TCL_ERROR) + free (obj->comstackType); + if (ir_tcl_strdup (interp, &obj->comstackType, argv[2]) == TCL_ERROR) return TCL_ERROR; } - Tcl_AppendElement (interp, obj->cs_type); + Tcl_AppendElement (interp, obj->comstackType); + return TCL_OK; +} + +/* + * do_logLevel: Set log level + */ +static int do_logLevel (void *o, Tcl_Interp *interp, + int argc, char **argv) +{ + if (argc <= 2) + return TCL_OK; + if (argc == 3) + log_init (log_mask_str (argv[2]), "", NULL); + else if (argc == 4) + log_init (log_mask_str (argv[2]), argv[3], NULL); + else if (argc == 5) + log_init (log_mask_str (argv[2]), argv[3], argv[4]); + return TCL_OK; +} + + +/* + * do_eventType: Return type of last event + */ +static int do_eventType (void *obj, Tcl_Interp *interp, + int argc, char **argv) +{ + IrTcl_Obj *p = obj; + + if (argc <= 0) + { + p->eventType = NULL; + return TCL_OK; + } + Tcl_AppendElement (interp, p->eventType ? p->eventType : ""); return TCL_OK; } @@ -1092,28 +1223,27 @@ static int do_comstack (void *o, Tcl_Interp *interp, * do_callback: add callback */ static int do_callback (void *obj, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_Obj *p = obj; if (argc == 0) { p->callback = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->callback); + return ir_tcl_strdel (interp, &p->callback); if (argc == 3) { free (p->callback); - if (argv[2][0]) - { - if (ir_strdup (interp, &p->callback, argv[2]) == TCL_ERROR) + if (argv[2][0]) + { + if (ir_tcl_strdup (interp, &p->callback, argv[2]) == TCL_ERROR) return TCL_ERROR; - } - else - p->callback = NULL; - p->interp = interp; + } + else + p->callback = NULL; } return TCL_OK; } @@ -1129,26 +1259,53 @@ static int do_failback (void *obj, Tcl_Interp *interp, if (argc == 0) { p->failback = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->failback); + return ir_tcl_strdel (interp, &p->failback); else if (argc == 3) { free (p->failback); - if (argv[2][0]) - { - if (ir_strdup (interp, &p->failback, argv[2]) == TCL_ERROR) + if (argv[2][0]) + { + if (ir_tcl_strdup (interp, &p->failback, argv[2]) == TCL_ERROR) return TCL_ERROR; - } - else - p->failback = NULL; - p->interp = interp; + } + else + p->failback = NULL; } return TCL_OK; } /* + * do_initResponse: add init response handler + */ +static int do_initResponse (void *obj, Tcl_Interp *interp, + int argc, char **argv) +{ + IrTcl_Obj *p = obj; + + if (argc == 0) + { + p->initResponse = NULL; + return TCL_OK; + } + else if (argc == -1) + return ir_tcl_strdel (interp, &p->initResponse); + if (argc == 3) + { + free (p->initResponse); + if (argv[2][0]) + { + if (ir_tcl_strdup (interp, &p->initResponse, argv[2]) == TCL_ERROR) + return TCL_ERROR; + } + else + p->initResponse = NULL; + } + return TCL_OK; +} +/* * do_protocol: Set/get protocol method on IR object */ static int do_protocol (void *o, Tcl_Interp *interp, int argc, char **argv) @@ -1200,7 +1357,7 @@ static int do_triggerResourceControl (void *obj, Tcl_Interp *interp, return TCL_OK; if (!p->cs_link) { - interp->result = "not connected"; + interp->result = "triggerResourceControl: not connected"; return TCL_ERROR; } apdu = zget_APDU (p->odr_out, Z_APDU_triggerResourceControlRequest); @@ -1208,7 +1365,8 @@ static int do_triggerResourceControl (void *obj, Tcl_Interp *interp, *req->requestedAction = Z_TriggerResourceCtrl_cancel; req->resultSetWanted = &is_false; - return ir_tcl_send_APDU (interp, p, apdu, "triggerResourceControl"); + return ir_tcl_send_APDU (interp, p, apdu, "triggerResourceControl", + argv[0]); } /* @@ -1229,8 +1387,8 @@ static int do_databaseNames (void *obj, Tcl_Interp *interp, if (argc <= 0) { p->num_databaseNames = 0; - p->databaseNames = NULL; - return TCL_OK; + p->databaseNames = NULL; + return TCL_OK; } if (argc < 3) { @@ -1245,12 +1403,11 @@ static int do_databaseNames (void *obj, Tcl_Interp *interp, free (p->databaseNames); } p->num_databaseNames = argc - 2; - if (!(p->databaseNames = ir_malloc (interp, - sizeof(*p->databaseNames) * p->num_databaseNames))) - return TCL_ERROR; + p->databaseNames = + ir_tcl_malloc (sizeof(*p->databaseNames) * p->num_databaseNames); for (i=0; inum_databaseNames; i++) { - if (ir_strdup (interp, &p->databaseNames[i], argv[2+i]) + if (ir_tcl_strdup (interp, &p->databaseNames[i], argv[2+i]) == TCL_ERROR) return TCL_ERROR; } @@ -1268,7 +1425,7 @@ static int do_replaceIndicator (void *obj, Tcl_Interp *interp, if (argc <= 0) { p->replaceIndicator = 1; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->replaceIndicator, interp, argc, argv); } @@ -1277,18 +1434,18 @@ static int do_replaceIndicator (void *obj, Tcl_Interp *interp, * do_queryType: Set/Get query method */ static int do_queryType (void *obj, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetCObj *p = obj; if (argc == 0) - return ir_strdup (interp, &p->queryType, "rpn"); + return ir_tcl_strdup (interp, &p->queryType, "rpn"); else if (argc == -1) - return ir_strdel (interp, &p->queryType); + return ir_tcl_strdel (interp, &p->queryType); if (argc == 3) { free (p->queryType); - if (ir_strdup (interp, &p->queryType, argv[2]) == TCL_ERROR) + if (ir_tcl_strdup (interp, &p->queryType, argv[2]) == TCL_ERROR) return TCL_ERROR; } Tcl_AppendResult (interp, p->queryType, NULL); @@ -1306,10 +1463,10 @@ static int do_userInformationField (void *obj, Tcl_Interp *interp, if (argc == 0) { p->userInformationField = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->userInformationField); + return ir_tcl_strdel (interp, &p->userInformationField); Tcl_AppendResult (interp, p->userInformationField, NULL); return TCL_OK; } @@ -1318,14 +1475,14 @@ static int do_userInformationField (void *obj, Tcl_Interp *interp, * do_smallSetUpperBound: Set/get small set upper bound */ static int do_smallSetUpperBound (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetCObj *p = o; if (argc <= 0) { p->smallSetUpperBound = 0; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->smallSetUpperBound, interp, argc, argv); } @@ -1341,7 +1498,7 @@ static int do_largeSetLowerBound (void *o, Tcl_Interp *interp, if (argc <= 0) { p->largeSetLowerBound = 2; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->largeSetLowerBound, interp, argc, argv); } @@ -1357,7 +1514,7 @@ static int do_mediumSetPresentNumber (void *o, Tcl_Interp *interp, if (argc <= 0) { p->mediumSetPresentNumber = 0; - return TCL_OK; + return TCL_OK; } return get_set_int (&p->mediumSetPresentNumber, interp, argc, argv); } @@ -1366,7 +1523,7 @@ static int do_mediumSetPresentNumber (void *o, Tcl_Interp *interp, * do_referenceId: Set/Get referenceId */ static int do_referenceId (void *obj, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetCObj *p = obj; @@ -1376,11 +1533,11 @@ static int do_referenceId (void *obj, Tcl_Interp *interp, return TCL_OK; } else if (argc == -1) - return ir_strdel (interp, &p->referenceId); + return ir_tcl_strdel (interp, &p->referenceId); if (argc == 3) { free (p->referenceId); - if (ir_strdup (interp, &p->referenceId, argv[2]) == TCL_ERROR) + if (ir_tcl_strdup (interp, &p->referenceId, argv[2]) == TCL_ERROR) return TCL_ERROR; } Tcl_AppendResult (interp, p->referenceId, NULL); @@ -1411,18 +1568,99 @@ static int do_preferredRecordSyntax (void *obj, Tcl_Interp *interp, free (p->preferredRecordSyntax); p->preferredRecordSyntax = NULL; if (argv[2][0] && (p->preferredRecordSyntax = - malloc (sizeof(*p->preferredRecordSyntax)))) + ir_tcl_malloc (sizeof(*p->preferredRecordSyntax)))) *p->preferredRecordSyntax = IrTcl_getRecordSyntaxVal (argv[2]); } 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) + { + free (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) + { + free (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) + { + free (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[] = { { 1, "comstack", do_comstack }, { 1, "protocol", do_protocol }, { 0, "failback", do_failback }, { 0, "failInfo", do_failInfo }, +{ 0, "apduInfo", do_apduInfo }, +{ 0, "logLevel", do_logLevel }, +{ 0, "eventType", do_eventType }, { 1, "connect", do_connect }, { 0, "protocolVersion", do_protocolVersion }, { 1, "preferredMessageSize", do_preferredMessageSize }, @@ -1440,7 +1678,9 @@ static IrTcl_Method ir_method_tab[] = { { 0, "initResult", do_initResult }, { 0, "disconnect", do_disconnect }, { 0, "callback", do_callback }, +{ 0, "initResponse", do_initResponse }, { 0, "triggerResourceControl", do_triggerResourceControl }, +{ 0, "initResponse", do_initResponse }, { 0, NULL, NULL} }; @@ -1453,6 +1693,9 @@ static IrTcl_Method ir_set_c_method_tab[] = { { 0, "largeSetLowerBound", do_largeSetLowerBound}, { 0, "mediumSetPresentNumber", do_mediumSetPresentNumber}, { 0, "referenceId", do_referenceId }, +{ 0, "elementSetNames", do_elementSetNames }, +{ 0, "smallSetElementSetNames", do_smallSetElementSetNames }, +{ 0, "mediumSetElementSetNames", do_mediumSetElementSetNames }, { 0, NULL, NULL} }; @@ -1490,6 +1733,7 @@ static void ir_obj_delete (ClientData clientData) 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; @@ -1497,6 +1741,8 @@ static void ir_obj_delete (ClientData clientData) tab[2].tab = NULL; ir_method (NULL, -1, NULL, tab); + + ir_tcl_del_q (obj); odr_destroy (obj->odr_in); odr_destroy (obj->odr_out); odr_destroy (obj->odr_pr); @@ -1520,23 +1766,23 @@ static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp, interp->result = "wrong # args"; return TCL_ERROR; } - if (!(obj = ir_malloc (interp, sizeof(*obj)))) - 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); + 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); 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; @@ -1574,7 +1820,6 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) return TCL_OK; p = obj->parent; - p->set_child = o; if (argc != 3) { interp->result = "wrong # args"; @@ -1587,14 +1832,16 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) } if (!p->cs_link) { - interp->result = "not connected"; + interp->result = "search: not connected"; return TCL_ERROR; } apdu = zget_APDU (p->odr_out, Z_APDU_searchRequest); req = apdu->u.searchRequest; + obj->start = 1; + bib1.proto = p->protocol_type; - bib1.class = CLASS_ATTSET; + bib1.oclass = CLASS_ATTSET; bib1.value = VAL_BIB1; set_referenceId (p->odr_out, &req->referenceId, @@ -1610,14 +1857,12 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) 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]); - req->smallSetElementSetNames = 0; - req->mediumSetElementSetNames = 0; if (obj->set_inher.preferredRecordSyntax) { struct oident ident; ident.proto = p->protocol_type; - ident.class = CLASS_RECSYN; + 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, @@ -1625,15 +1870,40 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) } else req->preferredRecordSyntax = 0; - req->query = &query; - if (!strcmp (obj->set_inher.queryType, "rpn")) + if (obj->set_inher.smallSetElementSetNames && + *obj->set_inher.smallSetElementSetNames) { - Z_RPNQuery *RPNquery; - - RPNquery = p_query_rpn (p->odr_out, argv[2]); - if (!RPNquery) - { + 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; + + if (!strcmp (obj->set_inher.queryType, "rpn")) + { + Z_RPNQuery *RPNquery; + + RPNquery = p_query_rpn (p->odr_out, argv[2]); + if (!RPNquery) + { Tcl_AppendResult (interp, "Syntax error in query", NULL); return TCL_ERROR; } @@ -1654,7 +1924,7 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) if (error) { Tcl_AppendResult (interp, "CCL error: ", - ccl_err_msg(error), NULL); + ccl_err_msg(error), NULL); return TCL_ERROR; } ccl_pr_tree (rpn, stderr); @@ -1679,14 +1949,74 @@ static int do_search (void *o, Tcl_Interp *interp, int argc, char **argv) interp->result = "unknown query method"; return TCL_ERROR; } - return ir_tcl_send_APDU (interp, p, apdu, "search"); + 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) + { + free (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) + { + free (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_resultCount: Get number of hits */ static int do_resultCount (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetObj *obj = o; @@ -1699,7 +2029,7 @@ static int do_resultCount (void *o, Tcl_Interp *interp, * do_searchStatus: Get search status (after search response) */ static int do_searchStatus (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetObj *obj = o; @@ -1712,7 +2042,7 @@ static int do_searchStatus (void *o, Tcl_Interp *interp, * do_presentStatus: Get search status (after search/present response) */ static int do_presentStatus (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetObj *obj = o; @@ -1742,18 +2072,18 @@ static int do_nextResultSetPosition (void *o, Tcl_Interp *interp, * do_setName: Set result Set name */ static int do_setName (void *o, Tcl_Interp *interp, - int argc, char **argv) + int argc, char **argv) { IrTcl_SetObj *obj = o; if (argc == 0) - return ir_strdup (interp, &obj->setName, "Default"); + return ir_tcl_strdup (interp, &obj->setName, "Default"); else if (argc == -1) - return ir_strdel (interp, &obj->setName); + return ir_tcl_strdel (interp, &obj->setName); if (argc == 3) { free (obj->setName); - if (ir_strdup (interp, &obj->setName, argv[2]) + if (ir_tcl_strdup (interp, &obj->setName, argv[2]) == TCL_ERROR) return TCL_ERROR; } @@ -1789,14 +2119,14 @@ static int do_type (void *o, Tcl_Interp *interp, int argc, char **argv) if (argc == 0) { obj->record_list = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) { delete_IR_records (obj); - return TCL_OK; + return TCL_OK; } - if (argc < 3) + if (argc != 3) { sprintf (interp->result, "wrong # args"); return TCL_ERROR; @@ -1805,7 +2135,10 @@ static int do_type (void *o, Tcl_Interp *interp, int argc, char **argv) return TCL_ERROR; rl = find_IR_record (obj, offset); if (!rl) + { + logf (LOG_DEBUG, "No record at position %d", offset); return TCL_OK; + } switch (rl->which) { case Z_NamePlusRecord_databaseRecord: @@ -1830,13 +2163,13 @@ static int do_recordType (void *o, Tcl_Interp *interp, int argc, char **argv) if (argc == 0) { - return TCL_OK; + return TCL_OK; } else if (argc == -1) { - return TCL_OK; + return TCL_OK; } - if (argc < 3) + if (argc != 3) { sprintf (interp->result, "wrong # args"); return TCL_ERROR; @@ -1857,6 +2190,36 @@ static int do_recordType (void *o, Tcl_Interp *interp, int argc, char **argv) } /* + * 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) + { + sprintf (interp->result, "wrong # args"); + return TCL_ERROR; + } + if (argc == 3) + { + free (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) @@ -1894,7 +2257,7 @@ static int do_diag (void *o, Tcl_Interp *interp, int argc, char **argv) if (argc <= 0) return TCL_OK; - if (argc < 3) + if (argc != 3) { sprintf (interp->result, "wrong # args"); return TCL_ERROR; @@ -1959,7 +2322,7 @@ static int do_getSutrs (void *o, Tcl_Interp *interp, int argc, char **argv) if (argc <= 0) return TCL_OK; - if (argc < 3) + if (argc != 3) { sprintf (interp->result, "wrong # args"); return TCL_ERROR; @@ -1985,6 +2348,41 @@ static int do_getSutrs (void *o, Tcl_Interp *interp, int argc, char **argv) /* + * do_getGrs: Get a GRS1 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) + { + sprintf (interp->result, "wrong # args"); + 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_responseStatus: Return response status (present or search) */ static int do_responseStatus (void *o, Tcl_Interp *interp, @@ -1997,7 +2395,7 @@ static int do_responseStatus (void *o, Tcl_Interp *interp, obj->recordFlag = 0; obj->nonSurrogateDiagnosticNum = 0; obj->nonSurrogateDiagnosticList = NULL; - return TCL_OK; + return TCL_OK; } else if (argc == -1) { @@ -2013,7 +2411,7 @@ static int do_responseStatus (void *o, Tcl_Interp *interp, switch (obj->which) { case Z_Records_DBOSD: - Tcl_AppendElement (interp, "DBOSD"); + Tcl_AppendElement (interp, "DBOSD"); break; case Z_Records_NSD: Tcl_AppendElement (interp, "NSD"); @@ -2027,8 +2425,7 @@ static int do_responseStatus (void *o, Tcl_Interp *interp, * do_present: Perform Present Request */ -static int do_present (void *o, Tcl_Interp *interp, - int argc, char **argv) +static int do_present (void *o, Tcl_Interp *interp, int argc, char **argv) { IrTcl_SetObj *obj = o; IrTcl_Obj *p; @@ -2053,13 +2450,12 @@ static int do_present (void *o, Tcl_Interp *interp, } else number = 10; + p = obj->parent; if (!p->cs_link) { - interp->result = "not connected"; + interp->result = "present: not connected"; return TCL_ERROR; } - p = obj->parent; - p->set_child = obj; obj->start = start; obj->number = number; @@ -2079,7 +2475,7 @@ static int do_present (void *o, Tcl_Interp *interp, struct oident ident; ident.proto = p->protocol_type; - ident.class = CLASS_RECSYN; + 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, @@ -2087,8 +2483,22 @@ static int do_present (void *o, Tcl_Interp *interp, } else req->preferredRecordSyntax = 0; - - return ir_tcl_send_APDU (interp, p, apdu, "present"); + + 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); } /* @@ -2106,7 +2516,7 @@ static int do_loadFile (void *o, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - if (argc < 3) + if (argc != 3) { interp->result = "wrong # args"; return TCL_ERROR; @@ -2121,10 +2531,10 @@ static int do_loadFile (void *o, Tcl_Interp *interp, { IrTcl_RecordList *rl; - rl = new_IR_record (setobj, no, Z_NamePlusRecord_databaseRecord); + 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; + rl->u.dbrec.size = size; no++; } setobj->numberOfRecordsReturned = no-1; @@ -2134,6 +2544,8 @@ static int do_loadFile (void *o, Tcl_Interp *interp, static IrTcl_Method ir_set_method_tab[] = { { 0, "search", do_search }, + { 0, "searchResponse", do_searchResponse }, + { 0, "presentResponse", do_presentResponse }, { 0, "searchStatus", do_searchStatus }, { 0, "presentStatus", do_presentStatus }, { 0, "nextResultSetPosition", do_nextResultSetPosition }, @@ -2144,7 +2556,9 @@ static IrTcl_Method ir_set_method_tab[] = { { 0, "type", do_type }, { 0, "getMarc", do_getMarc }, { 0, "getSutrs", do_getSutrs }, + { 0, "getGrs", do_getGrs }, { 0, "recordType", do_recordType }, + { 0, "recordElements", do_recordElements }, { 0, "diag", do_diag }, { 0, "responseStatus", do_responseStatus }, { 0, "loadFile", do_loadFile }, @@ -2182,6 +2596,8 @@ static void ir_set_obj_delete (ClientData clientData) IrTcl_Methods tabs[3]; IrTcl_SetObj *p = 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; @@ -2207,9 +2623,9 @@ static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, interp->result = "wrong # args"; return TCL_ERROR; } - if (!(obj = ir_malloc (interp, sizeof(*obj)))) - return TCL_ERROR; - else if (argc == 3) + obj = ir_tcl_malloc (sizeof(*obj)); + logf (LOG_DEBUG, "ir set create"); + if (argc == 3) { Tcl_CmdInfo parent_info; int i; @@ -2226,28 +2642,41 @@ static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, dst = &obj->set_inher; src = &obj->parent->set_inher; - dst->num_databaseNames = src->num_databaseNames; - if (!(dst->databaseNames = - ir_malloc (interp, sizeof (*dst->databaseNames) - * dst->num_databaseNames))) - return TCL_ERROR; + if ((dst->num_databaseNames = src->num_databaseNames)) + dst->databaseNames = + ir_tcl_malloc (sizeof (*dst->databaseNames) + * dst->num_databaseNames); + else + dst->databaseNames = NULL; for (i = 0; i < dst->num_databaseNames; i++) - { - if (ir_strdup (interp, &dst->databaseNames[i], + if (ir_tcl_strdup (interp, &dst->databaseNames[i], src->databaseNames[i]) == TCL_ERROR) return TCL_ERROR; - } - if (ir_strdup (interp, &dst->queryType, src->queryType) + 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_strdup (interp, &dst->referenceId, src->referenceId) + 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 - = malloc (sizeof(*dst->preferredRecordSyntax)))) + = ir_tcl_malloc (sizeof(*dst->preferredRecordSyntax)))) *dst->preferredRecordSyntax = *src->preferredRecordSyntax; else dst->preferredRecordSyntax = NULL; @@ -2290,7 +2719,6 @@ static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv) if (argc <= 0) return TCL_OK; - p->scan_child = o; if (argc != 3) { interp->result = "wrong # args"; @@ -2299,16 +2727,16 @@ static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv) if (!p->set_inher.num_databaseNames) { interp->result = "no databaseNames"; - return TCL_ERROR; + return TCL_ERROR; } if (!p->cs_link) { - interp->result = "not connected"; - return TCL_ERROR; + interp->result = "scan: not connected"; + return TCL_ERROR; } bib1.proto = p->protocol_type; - bib1.class = CLASS_ATTSET; + bib1.oclass = CLASS_ATTSET; bib1.value = VAL_BIB1; apdu = zget_APDU (p->odr_out, Z_APDU_scanRequest); @@ -2323,7 +2751,7 @@ static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv) if (!(req->termListAndStartPoint = p_query_scan (p->odr_out, argv[2]))) { Tcl_AppendResult (interp, "Syntax error in query", NULL); - return TCL_ERROR; + return TCL_ERROR; } #else rpn = ccl_find_str(p->bibset, argv[2], &r, &pos); @@ -2346,7 +2774,37 @@ static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv) logf (LOG_DEBUG, "preferredPositionInResponse=%d", *req->preferredPositionInResponse); - return ir_tcl_send_APDU (interp, p, apdu, "scan"); + return ir_tcl_send_APDU (interp, p, apdu, "scan", *argv); +} + +/* + * 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) + { + free (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; } /* @@ -2448,25 +2906,25 @@ static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv) if (argc == 0) { p->entries_flag = 0; - p->entries = NULL; - p->nonSurrogateDiagnosticNum = 0; + p->entries = NULL; + p->nonSurrogateDiagnosticNum = 0; p->nonSurrogateDiagnosticList = 0; - return TCL_OK; + return TCL_OK; } else if (argc == -1) { p->entries_flag = 0; - /* release entries */ + /* release entries */ p->entries = NULL; ir_deleteDiags (&p->nonSurrogateDiagnosticList, &p->nonSurrogateDiagnosticNum); - return TCL_OK; + return TCL_OK; } if (argc != 3) { interp->result = "wrong # args"; - return TCL_ERROR; + return TCL_ERROR; } if (Tcl_GetInt (interp, argv[2], &i) == TCL_ERROR) return TCL_ERROR; @@ -2477,24 +2935,25 @@ static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv) { 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; + 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; + break; } return TCL_OK; } static IrTcl_Method ir_scan_method_tab[] = { { 0, "scan", do_scan }, + { 0, "scanResponse", do_scanResponse }, { 0, "stepSize", do_stepSize }, { 0, "numberOfTermsRequested", do_numberOfTermsRequested }, { 0, "preferredPositionInResponse", do_preferredPositionInResponse }, @@ -2559,11 +3018,9 @@ static int ir_scan_obj_mk (ClientData clientData, Tcl_Interp *interp, if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info)) { interp->result = "No parent"; - return TCL_ERROR; - } - if (!(obj = ir_malloc (interp, sizeof(*obj)))) return TCL_ERROR; - + } + obj = ir_tcl_malloc (sizeof(*obj)); obj->parent = (IrTcl_Obj *) parent_info.clientData; tabs[0].tab = ir_scan_method_tab; @@ -2592,13 +3049,13 @@ static void ir_initResponse (void *obj, Z_InitResponse *initrs) get_referenceId (&p->set_inher.referenceId, initrs->referenceId); free (p->targetImplementationId); - ir_strdup (p->interp, &p->targetImplementationId, + ir_tcl_strdup (p->interp, &p->targetImplementationId, initrs->implementationId); free (p->targetImplementationName); - ir_strdup (p->interp, &p->targetImplementationName, + ir_tcl_strdup (p->interp, &p->targetImplementationName, initrs->implementationName); free (p->targetImplementationVersion); - ir_strdup (p->interp, &p->targetImplementationVersion, + ir_tcl_strdup (p->interp, &p->targetImplementationVersion, initrs->implementationVersion); p->maximumRecordSize = *initrs->maximumRecordSize; @@ -2615,9 +3072,9 @@ static void ir_initResponse (void *obj, Z_InitResponse *initrs) if (initrs->userInformationField->which == ODR_EXTERNAL_octet && (p->userInformationField = - malloc ((len = - initrs->userInformationField->u.octet_aligned->len) - +1))) + ir_tcl_malloc ((len = + initrs->userInformationField-> + u.octet_aligned->len) +1))) { memcpy (p->userInformationField, initrs->userInformationField->u.octet_aligned->buf, @@ -2644,12 +3101,7 @@ static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_num, char *addinfo; *dst_num = num; - *dst_list = malloc (sizeof(**dst_list) * num); - if (!*dst_list) - { - *dst_num = 0; - return; - } + *dst_list = ir_tcl_malloc (sizeof(**dst_list) * num); for (i = 0; iwhich) @@ -2658,7 +3110,7 @@ static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_num, (*dst_list)[i].condition = *list[i]->u.defaultFormat->condition; addinfo = list[i]->u.defaultFormat->addinfo; if (addinfo && - ((*dst_list)[i].addinfo = malloc (strlen(addinfo)+1))) + ((*dst_list)[i].addinfo = ir_tcl_malloc (strlen(addinfo)+1))) strcpy ((*dst_list)[i].addinfo, addinfo); break; default: @@ -2668,10 +3120,10 @@ static void ir_handleDiags (IrTcl_Diagnostic **dst_list, int *dst_num, } } -static void ir_handleRecords (void *o, Z_Records *zrs) +static void ir_handleRecords (void *o, Z_Records *zrs, IrTcl_SetObj *setobj, + const char *elements) { IrTcl_Obj *p = o; - IrTcl_SetObj *setobj = p->set_child; int offset; IrTcl_RecordList *rl; @@ -2690,7 +3142,8 @@ static void ir_handleRecords (void *o, Z_Records *zrs) { rl = new_IR_record (setobj, setobj->start + offset, zrs->u.databaseOrSurDiagnostics-> - records[offset]->which); + records[offset]->which, + elements); if (rl->which == Z_NamePlusRecord_surrogateDiagnostic) { ir_handleDiags (&rl->u.surrogateDiagnostics.list, @@ -2702,45 +3155,43 @@ static void ir_handleRecords (void *o, Z_Records *zrs) else { Z_DatabaseRecord *zr; - Odr_external *oe; + Z_External *oe; struct oident *ident; zr = zrs->u.databaseOrSurDiagnostics->records[offset] ->u.databaseRecord; - oe = (Odr_external*) zr; - rl->u.dbrec.size = zr->u.octet_aligned->len; + oe = (Z_External*) zr; + rl->u.dbrec.size = zr->u.octet_aligned->len; - rl->u.dbrec.type = VAL_USMARC; 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 = malloc (rl->u.dbrec.size))) - memcpy (rl->u.dbrec.buf, buf, rl->u.dbrec.size); + 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 == ODR_EXTERNAL_single) + oe->which == Z_External_sutrs) { - Odr_oct *rc; - - logf (LOG_DEBUG, "Decoding SUTRS"); odr_setbuf (p->odr_in, (char*) oe->u.single_ASN1_type->buf, oe->u.single_ASN1_type->len, 0); - if (!z_SUTRS(p->odr_in, &rc, 0)) - { - logf (LOG_WARN, "Cannot decode SUTRS"); - rl->u.dbrec.buf = NULL; - } - else + if ((rl->u.dbrec.buf = ir_tcl_malloc (oe->u.sutrs->len+1))) { - if ((rl->u.dbrec.buf = malloc (rc->len+1))) - { - memcpy (rl->u.dbrec.buf, rc->buf, rc->len); - rl->u.dbrec.buf[rc->len] = '\0'; - } - rl->u.dbrec.size = rc->len; + 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_read_grs (oe->u.grs1, &rl->u.dbrec.u.grs1); + rl->u.dbrec.buf = NULL; } else rl->u.dbrec.buf = NULL; @@ -2768,17 +3219,16 @@ static void ir_handleRecords (void *o, Z_Records *zrs) } } -static void ir_searchResponse (void *o, Z_SearchResponse *searchrs) +static void ir_searchResponse (void *o, Z_SearchResponse *searchrs, + IrTcl_SetObj *setobj) { - IrTcl_Obj *p = o; - IrTcl_SetObj *setobj = p->set_child; Z_Records *zrs = searchrs->records; logf (LOG_DEBUG, "Received search response"); if (!setobj) { logf (LOG_DEBUG, "Search response, no object!"); - return; + return; } setobj->searchStatus = searchrs->searchStatus ? 1 : 0; get_referenceId (&setobj->set_inher.referenceId, searchrs->referenceId); @@ -2791,29 +3241,35 @@ static void ir_searchResponse (void *o, Z_SearchResponse *searchrs) logf (LOG_DEBUG, "Search response %d, %d hits", setobj->searchStatus, setobj->resultCount); if (zrs) - ir_handleRecords (o, zrs); + { + const char *es; + if (setobj->resultCount <= setobj->set_inher.smallSetUpperBound) + es = setobj->set_inher.smallSetElementSetNames; + else + es = setobj->set_inher.mediumSetElementSetNames; + ir_handleRecords (o, zrs, setobj, es); + } else setobj->recordFlag = 0; } -static void ir_presentResponse (void *o, Z_PresentResponse *presrs) +static void ir_presentResponse (void *o, Z_PresentResponse *presrs, + IrTcl_SetObj *setobj) { - IrTcl_Obj *p = o; - IrTcl_SetObj *setobj = p->set_child; Z_Records *zrs = presrs->records; logf (LOG_DEBUG, "Received present response"); if (!setobj) { logf (LOG_DEBUG, "Present response, no object!"); - return; + return; } setobj->presentStatus = *presrs->presentStatus; get_referenceId (&setobj->set_inher.referenceId, presrs->referenceId); setobj->nextResultSetPosition = *presrs->nextResultSetPosition; if (zrs) - ir_handleRecords (o, zrs); + ir_handleRecords (o, zrs, setobj, setobj->set_inher.elementSetNames); else { setobj->recordFlag = 0; @@ -2821,10 +3277,10 @@ static void ir_presentResponse (void *o, Z_PresentResponse *presrs) } } -static void ir_scanResponse (void *o, Z_ScanResponse *scanrs) +static void ir_scanResponse (void *o, Z_ScanResponse *scanrs, + IrTcl_ScanObj *scanobj) { IrTcl_Obj *p = o; - IrTcl_ScanObj *scanobj = p->scan_child; logf (LOG_DEBUG, "Received scanResponse"); @@ -2854,50 +3310,50 @@ static void ir_scanResponse (void *o, Z_ScanResponse *scanrs) 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; - scanobj->entries = malloc (scanobj->num_entries * - sizeof(*scanobj->entries)); + switch (scanobj->which) + { + case Z_ListEntries_entries: + scanobj->num_entries = scanrs->entries->u.entries->num_entries; + scanobj->entries = ir_tcl_malloc (scanobj->num_entries * + sizeof(*scanobj->entries)); for (i=0; inum_entries; i++) - { - ze = scanrs->entries->u.entries->entries[i]; + { + 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) - { + 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 = malloc (1+l); - memcpy (scanobj->entries[i].u.term.buf, - ze->u.termInfo->term->u.general->buf, + 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 + } + 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; + 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: + case Z_Entry_surrogateDiagnostic: ir_handleDiags (&scanobj->entries[i].u.diag.list, &scanobj->entries[i].u.diag.num, &ze->u.surrogateDiagnostic, 1); - break; - } - } + break; + } + } break; - case Z_ListEntries_nonSurrogateDiagnostics: + case Z_ListEntries_nonSurrogateDiagnostics: ir_handleDiags (&scanobj->nonSurrogateDiagnosticList, &scanobj->nonSurrogateDiagnosticNum, scanrs->entries->u.nonSurrogateDiagnostics-> @@ -2905,7 +3361,7 @@ static void ir_scanResponse (void *o, Z_ScanResponse *scanrs) scanrs->entries->u.nonSurrogateDiagnostics-> num_diagRecs); break; - } + } } else scanobj->entries_flag = 0; @@ -2919,9 +3375,15 @@ void ir_select_read (ClientData clientData) IrTcl_Obj *p = clientData; Z_APDU *apdu; int r; + IrTcl_Request *rq; + char *object_name; + Tcl_CmdInfo cmd_info; + const char *apdu_call; + logf(LOG_DEBUG, "Read handler fd=%d", cs_fileno(p->cs_link)); if (p->state == IR_TCL_R_Connecting) { + logf(LOG_DEBUG, "Connect handler"); r = cs_rcvconnect (p->cs_link); if (r == 1) { @@ -2929,7 +3391,11 @@ void ir_select_read (ClientData clientData) return; } p->state = IR_TCL_R_Idle; +#if IRTCL_GENERIC_FILES + ir_select_remove_write (p->csFile, p); +#else ir_select_remove_write (cs_fileno (p->cs_link), p); +#endif if (r < 0) { logf (LOG_DEBUG, "cs_rcvconnect error"); @@ -2941,100 +3407,137 @@ void ir_select_read (ClientData clientData) do_disconnect (p, NULL, 2, NULL); return; } + p->state = IR_TCL_R_Idle; if (p->callback) - IrTcl_eval (p->interp, p->callback); - if (p->cs_link && p->request_queue) + IrTcl_eval (p->interp, p->callback); + if (p->cs_link && p->request_queue && p->state == IR_TCL_R_Idle) ir_tcl_send_q (p, p->request_queue, "x"); return; } do { - /* signal one more use of ir object - callbacks must not - release the ir memory (p pointer) */ + /* signal one more use of ir object - callbacks must not + release the ir memory (p pointer) */ p->state = IR_TCL_R_Reading; - ++(p->ref_count); + ++(p->ref_count); + + /* read incoming APDU */ if ((r=cs_get (p->cs_link, &p->buf_in, &p->len_in)) <= 0) { logf (LOG_DEBUG, "cs_get failed, code %d", r); +#if IRTCL_GENERIC_FILES + ir_select_remove (p->csFile, p); +#else ir_select_remove (cs_fileno (p->cs_link), p); +#endif + do_disconnect (p, NULL, 2, NULL); if (p->failback) { p->failInfo = IR_TCL_FAIL_READ; IrTcl_eval (p->interp, p->failback); } - do_disconnect (p, NULL, 2, NULL); - - /* release ir object now if callback deleted it */ - ir_obj_delete (p); + /* release ir object now if callback deleted it */ + ir_obj_delete (p); return; } if (r == 1) + { + logf(LOG_DEBUG, "PDU Fraction read"); return ; + } + /* got complete APDU. Now decode */ + p->apduLen = r; + p->apduOffset = -1; odr_setbuf (p->odr_in, p->buf_in, r, 0); - logf (LOG_DEBUG, "cs_get ok, got %d", r); + logf (LOG_DEBUG, "cs_get ok, total size %d", r); if (!z_APDU (p->odr_in, &apdu, 0)) { - logf (LOG_DEBUG, "%s", odr_errlist [odr_geterror (p->odr_in)]); + logf (LOG_DEBUG, "cs_get failed: %s", + odr_errmsg (odr_geterror (p->odr_in))); + do_disconnect (p, NULL, 2, NULL); if (p->failback) { p->failInfo = IR_TCL_FAIL_IN_APDU; + p->apduOffset = odr_offset (p->odr_in); IrTcl_eval (p->interp, p->failback); } - do_disconnect (p, NULL, 2, NULL); - - /* release ir object now if failback deleted it */ - ir_obj_delete (p); + /* release ir object now if failback deleted it */ + ir_obj_delete (p); return; } - switch(apdu->which) + logf(LOG_DEBUG, "Decoded ok"); + /* handle APDU and invoke callback */ + rq = p->request_queue; + if (!rq) { - case Z_APDU_initResponse: - ir_initResponse (p, apdu->u.initResponse); - break; - case Z_APDU_searchResponse: - ir_searchResponse (p, apdu->u.searchResponse); - break; - case Z_APDU_presentResponse: - ir_presentResponse (p, apdu->u.presentResponse); - break; - case Z_APDU_scanResponse: - ir_scanResponse (p, apdu->u.scanResponse); - break; - default: - logf (LOG_WARN, "Received unknown APDU type (%d)", apdu->which); - if (p->failback) + logf (LOG_FATAL, "Internal error. No queue entry"); + exit (1); + } + object_name = rq->object_name; + logf (LOG_DEBUG, "getCommandInfo (%s)", object_name); + apdu_call = NULL; + if (Tcl_GetCommandInfo (p->interp, object_name, &cmd_info)) + { + switch(apdu->which) { - p->failInfo = IR_TCL_FAIL_UNKNOWN_APDU; - IrTcl_eval (p->interp, p->failback); + case Z_APDU_initResponse: + p->eventType = "init"; + ir_initResponse (p, apdu->u.initResponse); + apdu_call = p->initResponse; + break; + case Z_APDU_searchResponse: + p->eventType = "search"; + ir_searchResponse (p, apdu->u.searchResponse, + (IrTcl_SetObj *) cmd_info.clientData); + apdu_call = ((IrTcl_SetObj *) + cmd_info.clientData)->searchResponse; + break; + case Z_APDU_presentResponse: + p->eventType = "present"; + ir_presentResponse (p, apdu->u.presentResponse, + (IrTcl_SetObj *) cmd_info.clientData); + apdu_call = ((IrTcl_SetObj *) + cmd_info.clientData)->presentResponse; + break; + case Z_APDU_scanResponse: + p->eventType = "scan"; + ir_scanResponse (p, apdu->u.scanResponse, + (IrTcl_ScanObj *) cmd_info.clientData); + apdu_call = ((IrTcl_ScanObj *) + cmd_info.clientData)->scanResponse; + break; + default: + logf (LOG_WARN, "Received unknown APDU type (%d)", + apdu->which); + do_disconnect (p, NULL, 2, NULL); + if (p->failback) + { + p->failInfo = IR_TCL_FAIL_UNKNOWN_APDU; + IrTcl_eval (p->interp, p->failback); + } + return; } - do_disconnect (p, NULL, 2, NULL); } + p->request_queue = rq->next; + p->state = IR_TCL_R_Idle; + + if (apdu_call) + IrTcl_eval (p->interp, apdu_call); + else if (rq->callback) + IrTcl_eval (p->interp, rq->callback); + free (rq->buf_out); + free (rq->callback); + free (rq->object_name); + free (rq); odr_reset (p->odr_in); - if (p->request_queue) /* remove queue entry */ + if (p->ref_count == 1) { - IrTcl_Request *rq; - rq = p->request_queue; - p->request_queue = rq->next; - free (rq->buf_out); - free (rq); - if (!p->request_queue) - p->state = IR_TCL_R_Idle; - } - else - { - logf (LOG_FATAL, "Internal error. No queue entry"); - exit (1); + ir_obj_delete (p); + return; } - if (p->callback) - IrTcl_eval (p->interp, p->callback); - if (p->ref_count == 1) - { - ir_obj_delete (p); - return; - } - --(p->ref_count); + --(p->ref_count); } while (p->cs_link && cs_more (p->cs_link)); - if (p->cs_link && p->request_queue) + if (p->cs_link && p->request_queue && p->state == IR_TCL_R_Idle) ir_tcl_send_q (p, p->request_queue, "x"); } @@ -3047,9 +3550,10 @@ void ir_select_write (ClientData clientData) int r; IrTcl_Request *rq; - logf (LOG_DEBUG, "In write handler"); + logf (LOG_DEBUG, "Write handler fd=%d", cs_fileno(p->cs_link)); if (p->state == IR_TCL_R_Connecting) { + logf(LOG_DEBUG, "Connect handler"); r = cs_rcvconnect (p->cs_link); if (r == 1) return; @@ -3057,7 +3561,11 @@ void ir_select_write (ClientData clientData) if (r < 0) { logf (LOG_DEBUG, "cs_rcvconnect error"); +#if IRTCL_GENERIC_FILES + ir_select_remove_write (p->csFile, p); +#else ir_select_remove_write (cs_fileno (p->cs_link), p); +#endif if (p->failback) { p->failInfo = IR_TCL_FAIL_CONNECT; @@ -3066,28 +3574,22 @@ void ir_select_write (ClientData clientData) do_disconnect (p, NULL, 2, NULL); return; } +#if IRTCL_GENERIC_FILES + ir_select_remove_write (p->csFile, p); +#else ir_select_remove_write (cs_fileno (p->cs_link), p); +#endif if (p->callback) - IrTcl_eval (p->interp, p->callback); + IrTcl_eval (p->interp, p->callback); return; } -#if 0 - if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0) - { - logf (LOG_DEBUG, "select write fail"); - if (p->failback) - { - p->failInfo = IR_TCL_FAIL_WRITE; - IrTcl_eval (p->interp, p->failback); - } - do_disconnect (p, NULL, 2, NULL); - } -#else rq = p->request_queue; + if (!rq || !rq->buf_out) + return; assert (rq); if ((r=cs_put (p->cs_link, rq->buf_out, rq->len_out)) < 0) { - logf (LOG_DEBUG, "select write fail"); + logf (LOG_DEBUG, "cs_put write fail"); if (p->failback) { p->failInfo = IR_TCL_FAIL_WRITE; @@ -3097,11 +3599,15 @@ void ir_select_write (ClientData clientData) rq->buf_out = NULL; do_disconnect (p, NULL, 2, NULL); } -#endif else if (r == 0) /* remove select bit */ { + logf(LOG_DEBUG, "Write completed"); p->state = IR_TCL_R_Waiting; +#if IRTCL_GENERIC_FILES + ir_select_remove_write (p->csFile, p); +#else ir_select_remove_write (cs_fileno (p->cs_link), p); +#endif free (rq->buf_out); rq->buf_out = NULL; } @@ -3110,18 +3616,16 @@ void ir_select_write (ClientData clientData) /* ------------------------------------------------------- */ /* - * ir_tcl_init: Registration of TCL commands. + * Irtcl_init: Registration of TCL commands. */ -int ir_tcl_init (Tcl_Interp *interp) +int Irtcl_Init (Tcl_Interp *interp) { Tcl_CreateCommand (interp, "ir", ir_obj_mk, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand (interp, "ir-set", ir_set_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); - irTcl_interp = interp; + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); return TCL_OK; } -