2 * IR toolkit for tcl/tk
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.29 1995-05-24 14:10:22 adam
8 * Work on idAuthentication, protocolVersion and options.
10 * Revision 1.28 1995/05/23 15:34:48 adam
11 * Many new settings, userInformationField, smallSetUpperBound, etc.
12 * A number of settings are inherited when ir-set is executed.
13 * This version is incompatible with the graphical test client (client.tcl).
15 * Revision 1.27 1995/05/11 15:34:47 adam
16 * Scan request changed a bit. This version works with RLG.
18 * Revision 1.26 1995/04/18 16:11:51 adam
19 * First version of graphical Scan. Some work on query-by-form.
21 * Revision 1.25 1995/04/17 09:37:17 adam
22 * Further development of scan.
24 * Revision 1.24 1995/04/11 14:16:42 adam
25 * Further work on scan. Response works. Entries aren't saved yet.
27 * Revision 1.23 1995/04/10 10:50:27 adam
28 * Result-set name defaults to suffix of ir-set name.
29 * Started working on scan. Not finished at this point.
31 * Revision 1.22 1995/03/31 10:43:03 adam
32 * More robust when getting bad MARC records.
34 * Revision 1.21 1995/03/31 08:56:37 adam
35 * New button "Search".
37 * Revision 1.20 1995/03/29 16:07:09 adam
38 * Bug fix: Didn't use setName in present request.
40 * Revision 1.19 1995/03/28 12:45:23 adam
41 * New ir method failback: called on disconnect/protocol error.
42 * New ir set/get method: protocol: SR / Z3950.
43 * Simple popup and disconnect when failback is invoked.
45 * Revision 1.18 1995/03/21 15:50:12 adam
48 * Revision 1.17 1995/03/21 13:41:03 adam
49 * Comstack cs_create not used too often. Non-blocking connect.
51 * Revision 1.16 1995/03/21 08:26:06 adam
52 * New method, setName, to specify the result set name (other than Default).
53 * New method, responseStatus, which returns diagnostic info, if any, after
54 * present response / search response.
56 * Revision 1.15 1995/03/20 15:24:07 adam
57 * Diagnostic records saved on searchResponse.
59 * Revision 1.14 1995/03/20 08:53:22 adam
60 * Event loop in tclmain.c rewritten. New method searchStatus.
62 * Revision 1.13 1995/03/17 18:26:17 adam
63 * Non-blocking i/o used now. Database names popup as cascade items.
65 * Revision 1.12 1995/03/17 15:45:00 adam
66 * Improved target/database setup.
68 * Revision 1.11 1995/03/16 17:54:03 adam
69 * Minor changes really.
71 * Revision 1.10 1995/03/15 16:14:50 adam
72 * Blocking arg in cs_create changed.
74 * Revision 1.9 1995/03/15 13:59:24 adam
77 * Revision 1.8 1995/03/15 08:25:16 adam
78 * New method presentStatus to check for error on present. Misc. cleanup
79 * of IRRecordList manipulations. Full MARC record presentation in
82 * Revision 1.7 1995/03/14 17:32:29 adam
83 * Presentation of full Marc record in popup window.
85 * Revision 1.6 1995/03/12 19:31:55 adam
86 * Pattern matching implemented when retrieving MARC records. More
87 * diagnostic functions.
89 * Revision 1.5 1995/03/10 18:00:15 adam
90 * Actual presentation in line-by-line format. RPN query support.
92 * Revision 1.4 1995/03/09 16:15:08 adam
93 * First presentRequest attempts. Hot-target list.
109 int (*method) (void *obj, Tcl_Interp *interp, int argc, char **argv);
113 static int do_disconnect (void *obj,Tcl_Interp *interp, int argc, char **argv);
115 static IRRecordList *new_IR_record (IRSetObj *setobj, int no, int which)
119 for (rl = setobj->record_list; rl; rl = rl->next)
125 case Z_NamePlusRecord_databaseRecord:
126 iso2709_rm (rl->u.marc.rec);
128 case Z_NamePlusRecord_surrogateDiagnostic:
129 free (rl->u.diag.addinfo);
130 rl->u.diag.addinfo = NULL;
138 rl = malloc (sizeof(*rl));
140 rl->next = setobj->record_list;
142 setobj->record_list = rl;
148 static IRRecordList *find_IR_record (IRSetObj *setobj, int no)
152 for (rl = setobj->record_list; rl; rl = rl->next)
159 * getsetint: Set/get integer value
161 static int get_set_int (int *val, Tcl_Interp *interp, int argc, char **argv)
167 if (Tcl_GetInt (interp, argv[2], val)==TCL_ERROR)
170 sprintf (buf, "%d", *val);
171 Tcl_AppendResult (interp, buf, NULL);
176 * mk_nonSurrogateDiagnostics: Make Tcl result with diagnostic info
178 static int mk_nonSurrogateDiagnostics (Tcl_Interp *interp,
185 Tcl_AppendElement (interp, "NSD");
186 sprintf (buf, "%d", condition);
187 Tcl_AppendElement (interp, buf);
188 cp = diagbib1_str (condition);
190 Tcl_AppendElement (interp, (char*) cp);
192 Tcl_AppendElement (interp, "");
194 Tcl_AppendElement (interp, (char*) addinfo);
196 Tcl_AppendElement (interp, "");
201 * get_parent_info: Returns information about parent object.
203 static int get_parent_info (Tcl_Interp *interp, const char *name,
204 Tcl_CmdInfo *parent_info,
207 char parent_name[128];
208 const char *csep = strrchr (name, '.');
213 interp->result = "missing .";
221 memcpy (parent_name, name, pos);
222 parent_name[pos] = '\0';
223 if (!Tcl_GetCommandInfo (interp, parent_name, parent_info))
225 interp->result = "No parent";
232 * ir_method: Search for method in table and invoke method handler
234 int ir_method (void *obj, Tcl_Interp *interp, int argc, char **argv,
235 IRMethod *tab, int sigerr)
238 for (t = tab; t->name; t++)
239 if (!strcmp (t->name, argv[1]))
240 return (*t->method)(obj, interp, argc, argv);
243 Tcl_AppendResult (interp, "Bad method. Possible values:", NULL);
244 for (t = tab; t->name; t++)
245 Tcl_AppendResult (interp, " ", t->name, NULL);
250 * ir_method_r: Get status for all readable elements
252 int ir_method_r (void *obj, Tcl_Interp *interp, int argc, char **argv,
260 for (; tab->name; tab++)
263 argv_n[1] = tab->name;
264 Tcl_AppendResult (interp, "{", NULL);
265 (*tab->method)(obj, interp, argc_n, argv_n);
266 Tcl_AppendResult (interp, "} ", NULL);
272 * ir_asc2bitmask: Ascii to ODR bitmask conversion
274 int ir_asc2bitmask (const char *asc, Odr_bitmask *ob)
276 const char *cp = asc + strlen(asc);
283 ODR_MASK_SET (ob, bitno);
290 * ir_named_bits: get/set named bits
292 int ir_named_bits (struct ir_named_entry *tab, Odr_bitmask *ob,
294 int argc, char **argv)
296 struct ir_named_entry *ti;
301 for (no = 0; no < argc; no++)
303 for (ti = tab; ti->name; ti++)
304 if (!strcmp (argv[no], ti->name))
306 ODR_MASK_SET (ob, ti->pos);
311 Tcl_AppendResult (interp, "Bad bit mask: ", argv[no], NULL);
317 for (ti = tab; ti->name; ti++)
318 if (ODR_MASK_GET (ob, ti->pos))
319 Tcl_AppendElement (interp, ti->name);
324 * ir_strdup: Duplicate string
326 int ir_strdup (Tcl_Interp *interp, char** p, const char *s)
328 *p = malloc (strlen(s)+1);
331 interp->result = "strdup fail";
339 * ir_malloc: Malloc function
341 void *ir_malloc (Tcl_Interp *interp, size_t size)
343 static char buf[128];
344 void *p = malloc (size);
348 sprintf (buf, "Malloc fail. %ld bytes requested", (long) size);
349 interp->result = buf;
355 /* ------------------------------------------------------- */
358 * do_init_request: init method on IR object
360 static int do_init_request (void *obj, Tcl_Interp *interp,
361 int argc, char **argv)
363 Z_APDU apdu, *apdup = &apdu;
370 interp->result = "not connected";
374 req.options = &p->options;
375 req.protocolVersion = &p->protocolVersion;
376 req.preferredMessageSize = &p->preferredMessageSize;
377 req.maximumRecordSize = &p->maximumRecordSize;
379 if (p->idAuthenticationGroupId)
381 Z_IdPass *pass = odr_malloc (p->odr_out, sizeof(*pass));
382 Z_IdAuthentication *auth = odr_malloc (p->odr_out, sizeof(*auth));
384 auth->which = Z_IdAuthentication_idPass;
385 auth->u.idPass = pass;
386 if (p->idAuthenticationGroupId && *p->idAuthenticationGroupId)
389 pass->groupId = p->idAuthenticationGroupId;
392 pass->groupId = NULL;
393 if (p->idAuthenticationUserId && *p->idAuthenticationUserId)
396 pass->userId = p->idAuthenticationUserId;
400 if (p->idAuthenticationPassword && *p->idAuthenticationPassword)
403 pass->password = p->idAuthenticationPassword;
406 pass->password = NULL;
407 req.idAuthentication = auth;
409 else if (!p->idAuthenticationOpen || !*p->idAuthenticationOpen)
410 req.idAuthentication = NULL;
413 Z_IdAuthentication *auth = odr_malloc (p->odr_out, sizeof(*auth));
415 auth->which = Z_IdAuthentication_open;
416 auth->u.open = p->idAuthenticationOpen;
417 req.idAuthentication = auth;
419 req.implementationId = p->implementationId;
420 req.implementationName = p->implementationName;
421 req.implementationVersion = "0.1";
422 req.userInformationField = 0;
424 apdu.u.initRequest = &req;
425 apdu.which = Z_APDU_initRequest;
427 if (!z_APDU (p->odr_out, &apdup, 0))
429 Tcl_AppendResult (interp, odr_errlist [odr_geterror (p->odr_out)],
431 odr_reset (p->odr_out);
434 p->sbuf = odr_getbuf (p->odr_out, &p->slen, NULL);
435 if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0)
437 interp->result = "cs_put failed in init";
438 do_disconnect (p, NULL, 0, NULL);
443 ir_select_add_write (cs_fileno(p->cs_link), p);
444 printf("Sent part of initializeRequest (%d bytes).\n", p->slen);
447 printf("Sent whole initializeRequest (%d bytes).\n", p->slen);
452 * do_protocolVersion: Set protocol Version
454 static int do_protocolVersion (void *obj, Tcl_Interp *interp,
455 int argc, char **argv)
457 static struct ir_named_entry version_tab[] = {
466 return ir_named_bits (version_tab, &p->protocolVersion,
467 interp, argc-2, argv+2);
471 * do_options: Set options
473 static int do_options (void *obj, Tcl_Interp *interp,
474 int argc, char **argv)
476 static struct ir_named_entry options_tab[] = {
480 { "resourceReport", 3 },
481 { "triggerResourceCtrl", 4},
482 { "resourceCtrl", 5},
486 { "extentedServices", 10},
487 { "level-1Segmentation", 11},
488 { "level-2Segmentation", 12},
489 { "concurrentOperations", 13},
490 { "namedResultSets", 14},
495 return ir_named_bits (options_tab, &p->options, interp, argc-2, argv+2);
499 * do_preferredMessageSize: Set/get preferred message size
501 static int do_preferredMessageSize (void *obj, Tcl_Interp *interp,
502 int argc, char **argv)
505 return get_set_int (&p->preferredMessageSize, interp, argc, argv);
509 * do_maximumRecordSize: Set/get maximum record size
511 static int do_maximumRecordSize (void *obj, Tcl_Interp *interp,
512 int argc, char **argv)
515 return get_set_int (&p->maximumRecordSize, interp, argc, argv);
519 * do_initResult: Get init result
521 static int do_initResult (void *obj, Tcl_Interp *interp,
522 int argc, char **argv)
526 return get_set_int (&p->initResult, interp, argc, argv);
531 * do_implementationName: Set/get Implementation Name.
533 static int do_implementationName (void *obj, Tcl_Interp *interp,
534 int argc, char **argv)
540 free (((IRObj*)obj)->implementationName);
541 if (ir_strdup (interp, &p->implementationName, argv[2])
545 Tcl_AppendResult (interp, p->implementationName,
551 * do_implementationId: Set/get Implementation Id.
553 static int do_implementationId (void *obj, Tcl_Interp *interp,
554 int argc, char **argv)
558 free (((IRObj*)obj)->implementationId);
559 if (ir_strdup (interp, &((IRObj*) obj)->implementationId, argv[2])
563 Tcl_AppendResult (interp, ((IRObj*)obj)->implementationId,
569 * do_targetImplementationName: Get Implementation Name of target.
571 static int do_targetImplementationName (void *obj, Tcl_Interp *interp,
572 int argc, char **argv)
576 Tcl_AppendResult (interp, p->targetImplementationName,
582 * do_targetImplementationId: Get Implementation Id of target
584 static int do_targetImplementationId (void *obj, Tcl_Interp *interp,
585 int argc, char **argv)
587 Tcl_AppendResult (interp, ((IRObj*)obj)->targetImplementationId,
593 * do_targetImplementationVersion: Get Implementation Version of target
595 static int do_targetImplementationVersion (void *obj, Tcl_Interp *interp,
596 int argc, char **argv)
598 Tcl_AppendResult (interp, ((IRObj*)obj)->targetImplementationVersion,
604 * do_idAuthentication: Set/get id Authentication
606 static int do_idAuthentication (void *obj, Tcl_Interp *interp,
607 int argc, char **argv)
613 free (p->idAuthenticationOpen);
614 free (p->idAuthenticationGroupId);
615 free (p->idAuthenticationUserId);
616 free (p->idAuthenticationPassword);
617 p->idAuthenticationOpen = NULL;
618 p->idAuthenticationGroupId = NULL;
619 p->idAuthenticationUserId = NULL;
620 p->idAuthenticationPassword = NULL;
624 if (ir_strdup (interp, &p->idAuthenticationOpen, argv[2])
630 if (ir_strdup (interp, &p->idAuthenticationGroupId, argv[2])
633 if (ir_strdup (interp, &p->idAuthenticationUserId, argv[3])
636 if (ir_strdup (interp, &p->idAuthenticationPassword, argv[4])
641 if (p->idAuthenticationOpen)
642 Tcl_AppendElement (interp, p->idAuthenticationOpen);
645 Tcl_AppendElement (interp, p->idAuthenticationGroupId ?
646 p->idAuthenticationGroupId : "");
647 Tcl_AppendElement (interp, p->idAuthenticationUserId ?
648 p->idAuthenticationUserId : "");
649 Tcl_AppendElement (interp, p->idAuthenticationPassword ?
650 p->idAuthenticationPassword : "");
656 * do_connect: connect method on IR object
658 static int do_connect (void *obj, Tcl_Interp *interp,
659 int argc, char **argv)
664 int protocol_type = CS_Z3950;
670 interp->result = "already connected";
673 if (!strcmp (p->protocol_type, "Z3950"))
674 protocol_type = CS_Z3950;
675 else if (!strcmp (p->protocol_type, "SR"))
676 protocol_type = CS_SR;
679 interp->result = "bad protocol type";
682 if (!strcmp (p->cs_type, "tcpip"))
684 p->cs_link = cs_create (tcpip_type, CS_BLOCK, protocol_type);
685 addr = tcpip_strtoaddr (argv[2]);
688 interp->result = "tcpip_strtoaddr fail";
691 printf ("tcp/ip connect %s\n", argv[2]);
694 else if (!strcmp (p->cs_type, "mosi"))
696 p->cs_link = cs_create (mosi_type, CS_BLOCK, protocol_type);
697 addr = mosi_strtoaddr (argv[2]);
700 interp->result = "mosi_strtoaddr fail";
703 printf ("mosi connect %s\n", argv[2]);
708 interp->result = "unknown comstack type";
711 if (ir_strdup (interp, &p->hostname, argv[2]) == TCL_ERROR)
713 if ((r=cs_connect (p->cs_link, addr)) < 0)
715 interp->result = "cs_connect fail";
716 do_disconnect (p, NULL, 0, NULL);
719 ir_select_add (cs_fileno (p->cs_link), p);
722 ir_select_add_write (cs_fileno (p->cs_link), p);
729 Tcl_Eval (p->interp, p->callback);
733 Tcl_AppendElement (interp, p->hostname);
738 * do_disconnect: disconnect method on IR object
740 static int do_disconnect (void *obj, Tcl_Interp *interp,
741 int argc, char **argv)
749 ir_select_remove_write (cs_fileno (p->cs_link), p);
750 ir_select_remove (cs_fileno (p->cs_link), p);
753 cs_close (p->cs_link);
756 assert (!p->cs_link);
761 * do_comstack: Set/get comstack method on IR object
763 static int do_comstack (void *o, Tcl_Interp *interp,
764 int argc, char **argv)
771 if (ir_strdup (interp, &obj->cs_type, argv[2]) == TCL_ERROR)
774 Tcl_AppendElement (interp, obj->cs_type);
779 * do_protocol: Set/get protocol method on IR object
781 static int do_protocol (void *o, Tcl_Interp *interp,
782 int argc, char **argv)
788 free (obj->protocol_type);
789 if (ir_strdup (interp, &obj->protocol_type, argv[2]) == TCL_ERROR)
792 Tcl_AppendElement (interp, obj->protocol_type);
797 * do_callback: add callback
799 static int do_callback (void *obj, Tcl_Interp *interp,
800 int argc, char **argv)
807 if (ir_strdup (interp, &p->callback, argv[2]) == TCL_ERROR)
815 * do_failback: add error handle callback
817 static int do_failback (void *obj, Tcl_Interp *interp,
818 int argc, char **argv)
825 if (ir_strdup (interp, &p->failback, argv[2]) == TCL_ERROR)
833 * do_databaseNames: specify database names
835 static int do_databaseNames (void *obj, Tcl_Interp *interp,
836 int argc, char **argv)
843 for (i=0; i<p->num_databaseNames; i++)
844 Tcl_AppendElement (interp, p->databaseNames[i]);
847 if (p->databaseNames)
849 for (i=0; i<p->num_databaseNames; i++)
850 free (p->databaseNames[i]);
851 free (p->databaseNames);
853 p->num_databaseNames = argc - 2;
854 if (!(p->databaseNames = ir_malloc (interp,
855 sizeof(*p->databaseNames) * p->num_databaseNames)))
857 for (i=0; i<p->num_databaseNames; i++)
859 if (ir_strdup (interp, &p->databaseNames[i], argv[2+i])
867 * do_replaceIndicator: Set/get replace Set indicator
869 static int do_replaceIndicator (void *obj, Tcl_Interp *interp,
870 int argc, char **argv)
874 return get_set_int (&p->replaceIndicator, interp, argc, argv);
878 * do_queryType: Set/Get query method
880 static int do_queryType (void *obj, Tcl_Interp *interp,
881 int argc, char **argv)
888 if (ir_strdup (interp, &p->queryType, argv[2]) == TCL_ERROR)
891 Tcl_AppendResult (interp, p->queryType, NULL);
896 * do_userInformationField: Get User information field
898 static int do_userInformationField (void *obj, Tcl_Interp *interp,
899 int argc, char **argv)
903 Tcl_AppendResult (interp, p->userInformationField, NULL);
908 * do_smallSetUpperBound: Set/get small set upper bound
910 static int do_smallSetUpperBound (void *o, Tcl_Interp *interp,
911 int argc, char **argv)
915 return get_set_int (&obj->smallSetUpperBound, interp, argc, argv);
919 * do_largeSetLowerBound: Set/get large set lower bound
921 static int do_largeSetLowerBound (void *o, Tcl_Interp *interp,
922 int argc, char **argv)
926 return get_set_int (&obj->largeSetLowerBound, interp, argc, argv);
930 * do_mediumSetPresentNumber: Set/get large set lower bound
932 static int do_mediumSetPresentNumber (void *o, Tcl_Interp *interp,
933 int argc, char **argv)
937 return get_set_int (&obj->mediumSetPresentNumber, interp, argc, argv);
941 static IRMethod ir_method_tab[] = {
942 { 1, "comstack", do_comstack },
943 { 1, "protocol", do_protocol },
944 { 0, "failback", do_failback },
946 { 1, "connect", do_connect },
947 { 0, "protocolVersion", do_protocolVersion },
948 { 1, "preferredMessageSize", do_preferredMessageSize },
949 { 1, "maximumRecordSize", do_maximumRecordSize },
950 { 1, "implementationName", do_implementationName },
951 { 1, "implementationId", do_implementationId },
952 { 0, "targetImplementationName", do_targetImplementationName },
953 { 0, "targetImplementationId", do_targetImplementationId },
954 { 0, "targetImplementationVersion", do_targetImplementationVersion },
955 { 0, "userInformationField", do_userInformationField },
956 { 1, "idAuthentication", do_idAuthentication },
957 { 0, "options", do_options },
958 { 0, "init", do_init_request },
959 { 0, "initResult", do_initResult },
960 { 0, "disconnect", do_disconnect },
961 { 0, "callback", do_callback },
965 static IRMethod ir_set_c_method_tab[] = {
966 { 0, "databaseNames", do_databaseNames},
967 { 0, "replaceIndicator", do_replaceIndicator},
968 { 0, "queryType", do_queryType },
969 { 0, "smallSetUpperBound", do_smallSetUpperBound},
970 { 0, "largeSetLowerBound", do_largeSetLowerBound},
971 { 0, "mediumSetPresentNumber", do_mediumSetPresentNumber},
976 * ir_obj_method: IR Object methods
978 static int ir_obj_method (ClientData clientData, Tcl_Interp *interp,
979 int argc, char **argv)
982 return ir_method_r (clientData, interp, argc, argv, ir_method_tab);
983 if (ir_method (clientData, interp, argc, argv,
984 ir_method_tab, 1) == TCL_OK)
986 return ir_method (&((IRObj*) clientData)->set_inher, interp,
987 argc, argv, ir_set_c_method_tab, 0);
991 * ir_obj_delete: IR Object disposal
993 static void ir_obj_delete (ClientData clientData)
995 free ( (void*) clientData);
998 static int ir_reset_inher (Tcl_Interp *interp, IRSetCObj *o)
1000 o->smallSetUpperBound = 0;
1001 o->largeSetLowerBound = 2;
1002 o->mediumSetPresentNumber = 0;
1003 o->replaceIndicator = 1;
1005 obj->databaseNames = NULL;
1006 obj->num_databaseNames = 0;
1008 o->num_databaseNames = 1;
1009 if (!(o->databaseNames =
1010 ir_malloc (interp, sizeof(*o->databaseNames))))
1012 if (ir_strdup (interp, &o->databaseNames[0], "Default")
1016 if (ir_strdup (interp, &o->queryType, "rpn") == TCL_ERROR)
1022 * ir_obj_mk: IR Object creation
1024 static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp,
1025 int argc, char **argv)
1032 interp->result = "wrong # args";
1035 if (!(obj = ir_malloc (interp, sizeof(*obj))))
1037 if (ir_strdup (interp, &obj->cs_type, "tcpip") == TCL_ERROR)
1039 if (ir_strdup (interp, &obj->protocol_type, "Z3950") == TCL_ERROR)
1041 obj->cs_link = NULL;
1042 obj->bib1.proto = PROTO_Z3950;
1043 obj->bib1.class = CLASS_ATTSET;
1044 obj->bib1.value = VAL_BIB1;
1046 obj->maximumRecordSize = 32768;
1047 obj->preferredMessageSize = 4096;
1048 obj->connectFlag = 0;
1050 obj->idAuthenticationOpen = NULL;
1051 obj->idAuthenticationGroupId = NULL;
1052 obj->idAuthenticationUserId = NULL;
1053 obj->idAuthenticationPassword = NULL;
1055 if (ir_strdup (interp, &obj->implementationName, "TCL/TK on YAZ")
1059 if (ir_strdup (interp, &obj->implementationId, "TCL/TK/YAZ")
1063 obj->targetImplementationName = NULL;
1064 obj->targetImplementationId = NULL;
1065 obj->targetImplementationVersion = NULL;
1066 obj->userInformationField = NULL;
1068 obj->hostname = NULL;
1070 obj->bibset = ccl_qual_mk ();
1071 if ((inf = fopen ("default.bib", "r")))
1073 ccl_qual_file (obj->bibset, inf);
1076 ODR_MASK_ZERO (&obj->protocolVersion);
1077 ODR_MASK_SET (&obj->protocolVersion, 0);
1078 ODR_MASK_SET (&obj->protocolVersion, 1);
1080 ODR_MASK_ZERO (&obj->options);
1081 ODR_MASK_SET (&obj->options, 0);
1082 ODR_MASK_SET (&obj->options, 1);
1083 ODR_MASK_SET (&obj->options, 7);
1084 ODR_MASK_SET (&obj->options, 14);
1086 obj->odr_in = odr_createmem (ODR_DECODE);
1087 obj->odr_out = odr_createmem (ODR_ENCODE);
1088 obj->odr_pr = odr_createmem (ODR_PRINT);
1090 obj->len_out = 10000;
1091 if (!(obj->buf_out = ir_malloc (interp, obj->len_out)))
1093 odr_setbuf (obj->odr_out, obj->buf_out, obj->len_out, 0);
1098 obj->callback = NULL;
1099 obj->failback = NULL;
1101 if (ir_reset_inher (interp, &obj->set_inher) == TCL_ERROR)
1103 Tcl_CreateCommand (interp, argv[1], ir_obj_method,
1104 (ClientData) obj, ir_obj_delete);
1108 /* ------------------------------------------------------- */
1110 * do_search: Do search request
1112 static int do_search (void *o, Tcl_Interp *interp,
1113 int argc, char **argv)
1115 Z_SearchRequest req;
1117 Z_APDU apdu, *apdup = &apdu;
1120 IRObj *p = obj->parent;
1126 interp->result = "wrong # args";
1129 if (!p->set_inher.num_databaseNames)
1131 interp->result = "no databaseNames";
1136 interp->result = "not connected";
1139 apdu.which = Z_APDU_searchRequest;
1140 apdu.u.searchRequest = &req;
1142 req.referenceId = 0;
1143 req.smallSetUpperBound = &p->set_inher.smallSetUpperBound;
1144 req.largeSetLowerBound = &p->set_inher.largeSetLowerBound;
1145 req.mediumSetPresentNumber = &p->set_inher.mediumSetPresentNumber;
1146 req.replaceIndicator = &p->set_inher.replaceIndicator;
1147 req.resultSetName = obj->setName ? obj->setName : "Default";
1148 req.num_databaseNames = p->set_inher.num_databaseNames;
1149 req.databaseNames = p->set_inher.databaseNames;
1151 for (r=0; r < p->set_inher.num_databaseNames; r++)
1153 printf (" %s", p->set_inher.databaseNames[r]);
1155 req.smallSetElementSetNames = 0;
1156 req.mediumSetElementSetNames = 0;
1157 req.preferredRecordSyntax = 0;
1160 if (!strcmp (p->set_inher.queryType, "rpn"))
1164 struct ccl_rpn_node *rpn;
1165 Z_RPNQuery *RPNquery;
1167 rpn = ccl_find_str(p->bibset, argv[2], &error, &pos);
1170 Tcl_AppendResult (interp, "CCL error: ", ccl_err_msg(error),NULL);
1173 ccl_pr_tree (rpn, stderr);
1174 fprintf (stderr, "\n");
1175 query.which = Z_Query_type_1;
1176 assert((RPNquery = ccl_rpn_query(rpn)));
1177 RPNquery->attributeSetId = oid_getoidbyent (&p->bib1);
1178 query.u.type_1 = RPNquery;
1181 else if (!strcmp (p->set_inher.queryType, "ccl"))
1183 query.which = Z_Query_type_2;
1184 query.u.type_2 = &ccl_query;
1185 ccl_query.buf = (unsigned char *) argv[2];
1186 ccl_query.len = strlen (argv[2]);
1191 interp->result = "unknown query method";
1194 if (!z_APDU (p->odr_out, &apdup, 0))
1196 interp->result = odr_errlist [odr_geterror (p->odr_out)];
1197 odr_reset (p->odr_out);
1200 p->sbuf = odr_getbuf (p->odr_out, &p->slen, NULL);
1201 if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0)
1203 interp->result = "cs_put failed in search";
1208 ir_select_add_write (cs_fileno(p->cs_link), p);
1209 printf("Sent part of searchRequest (%d bytes).\n", p->slen);
1213 printf ("Whole search request\n");
1219 * do_resultCount: Get number of hits
1221 static int do_resultCount (void *o, Tcl_Interp *interp,
1222 int argc, char **argv)
1226 return get_set_int (&obj->resultCount, interp, argc, argv);
1230 * do_searchStatus: Get search status (after search response)
1232 static int do_searchStatus (void *o, Tcl_Interp *interp,
1233 int argc, char **argv)
1237 return get_set_int (&obj->searchStatus, interp, argc, argv);
1241 * do_setName: Set result Set name
1243 static int do_setName (void *o, Tcl_Interp *interp,
1244 int argc, char **argv)
1250 free (obj->setName);
1251 if (ir_strdup (interp, &obj->setName, argv[2])
1255 Tcl_AppendElement (interp, obj->setName);
1260 * do_numberOfRecordsReturned: Get number of records returned
1262 static int do_numberOfRecordsReturned (void *o, Tcl_Interp *interp,
1263 int argc, char **argv)
1267 return get_set_int (&obj->numberOfRecordsReturned, interp, argc, argv);
1270 static int get_marc_fields(Tcl_Interp *interp, Iso2709Rec rec,
1271 int argc, char **argv)
1278 a = iso2709_a_mk (rec);
1279 while (iso2709_a_search (a, argv[4], argv[5], argv[6]))
1281 if (!(iso2709_a_info_field (a, NULL, NULL, NULL, &data)))
1283 Tcl_AppendElement (interp, data);
1291 static int get_marc_lines(Tcl_Interp *interp, Iso2709Rec rec,
1292 int argc, char **argv)
1303 a = iso2709_a_mk (rec);
1304 while (iso2709_a_search (a, argv[4], argv[5], argv[6]))
1306 if (!(iso2709_a_info_field (a, &tag, &indicator, &identifier, &data)))
1308 if (strcmp (tag, ptag))
1311 Tcl_AppendResult (interp, "}} ", NULL);
1313 Tcl_AppendResult (interp, "{", tag, " {} {", NULL);
1315 Tcl_AppendResult (interp, "{", tag, " {", indicator,
1320 Tcl_AppendResult (interp, "{{}", NULL);
1322 Tcl_AppendResult (interp, "{", identifier, NULL);
1323 Tcl_AppendElement (interp, data);
1324 Tcl_AppendResult (interp, "} ", NULL);
1328 Tcl_AppendResult (interp, "}} ", NULL);
1334 * do_recordType: Return record type (if any) at position.
1336 static int do_recordType (void *o, Tcl_Interp *interp, int argc, char **argv)
1344 sprintf (interp->result, "wrong # args");
1347 if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
1349 rl = find_IR_record (obj, offset);
1354 case Z_NamePlusRecord_databaseRecord:
1355 interp->result = "databaseRecord";
1357 case Z_NamePlusRecord_surrogateDiagnostic:
1358 interp->result = "surrogateDiagnostic";
1365 * do_recordDiag: Return diagnostic record info
1367 static int do_recordDiag (void *o, Tcl_Interp *interp, int argc, char **argv)
1376 sprintf (interp->result, "wrong # args");
1379 if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
1381 rl = find_IR_record (obj, offset);
1384 Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
1387 if (rl->which != Z_NamePlusRecord_surrogateDiagnostic)
1389 Tcl_AppendResult (interp, "No Diagnostic record at #", argv[2], NULL);
1392 sprintf (buf, "%d", rl->u.diag.condition);
1393 Tcl_AppendResult (interp, buf, " {",
1394 (rl->u.diag.addinfo ? rl->u.diag.addinfo : ""),
1400 * do_recordMarc: Get ISO2709 Record lines/fields
1402 static int do_recordMarc (void *o, Tcl_Interp *interp, int argc, char **argv)
1410 sprintf (interp->result, "wrong # args");
1413 if (Tcl_GetInt (interp, argv[2], &offset)==TCL_ERROR)
1415 rl = find_IR_record (obj, offset);
1418 Tcl_AppendResult (interp, "No record at #", argv[2], NULL);
1421 if (rl->which != Z_NamePlusRecord_databaseRecord)
1423 Tcl_AppendResult (interp, "No MARC record at #", argv[2], NULL);
1426 if (!strcmp (argv[3], "field"))
1427 return get_marc_fields (interp, rl->u.marc.rec, argc, argv);
1428 else if (!strcmp (argv[3], "line"))
1429 return get_marc_lines (interp, rl->u.marc.rec, argc, argv);
1432 Tcl_AppendResult (interp, "field/line expected", NULL);
1439 * do_responseStatus: Return response status (present or search)
1441 static int do_responseStatus (void *o, Tcl_Interp *interp,
1442 int argc, char **argv)
1446 if (!obj->recordFlag)
1448 Tcl_AppendElement (interp, "OK");
1453 case Z_Records_DBOSD:
1454 Tcl_AppendElement (interp, "DBOSD");
1457 return mk_nonSurrogateDiagnostics (interp, obj->condition,
1464 * do_present: Perform Present Request
1467 static int do_present (void *o, Tcl_Interp *interp,
1468 int argc, char **argv)
1471 IRObj *p = obj->parent;
1472 Z_APDU apdu, *apdup = &apdu;
1473 Z_PresentRequest req;
1480 if (Tcl_GetInt (interp, argv[2], &start) == TCL_ERROR)
1487 if (Tcl_GetInt (interp, argv[3], &number) == TCL_ERROR)
1494 interp->result = "not connected";
1498 obj->number = number;
1500 apdu.which = Z_APDU_presentRequest;
1501 apdu.u.presentRequest = &req;
1502 req.referenceId = 0;
1503 /* sprintf(setstring, "%d", setnumber); */
1505 req.resultSetId = obj->setName ? obj->setName : "Default";
1507 req.resultSetStartPoint = &start;
1508 req.numberOfRecordsRequested = &number;
1509 req.elementSetNames = 0;
1510 req.preferredRecordSyntax = 0;
1512 if (!z_APDU (p->odr_out, &apdup, 0))
1514 interp->result = odr_errlist [odr_geterror (p->odr_out)];
1515 odr_reset (p->odr_out);
1518 p->sbuf = odr_getbuf (p->odr_out, &p->slen, NULL);
1519 if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0)
1521 interp->result = "cs_put failed in present";
1526 ir_select_add_write (cs_fileno(p->cs_link), p);
1527 printf ("Part of present request, start=%d, num=%d (%d bytes)\n",
1528 start, number, p->slen);
1532 printf ("Whole present request, start=%d, num=%d (%d bytes)\n",
1533 start, number, p->slen);
1539 * do_loadFile: Load result set from file
1542 static int do_loadFile (void *o, Tcl_Interp *interp,
1543 int argc, char **argv)
1545 IRSetObj *setobj = o;
1552 interp->result = "wrong # args";
1555 inf = fopen (argv[2], "r");
1558 Tcl_AppendResult (interp, "Cannot open ", argv[2], NULL);
1561 while ((buf = iso2709_read (inf)))
1566 rec = iso2709_cvt (buf);
1569 rl = new_IR_record (setobj, no, Z_NamePlusRecord_databaseRecord);
1570 rl->u.marc.rec = rec;
1573 setobj->numberOfRecordsReturned = no-1;
1579 * ir_set_obj_method: IR Set Object methods
1581 static int ir_set_obj_method (ClientData clientData, Tcl_Interp *interp,
1582 int argc, char **argv)
1584 static IRMethod tab[] = {
1585 { 0, "search", do_search },
1586 { 0, "searchStatus", do_searchStatus },
1587 { 0, "setName", do_setName },
1588 { 0, "resultCount", do_resultCount },
1589 { 0, "numberOfRecordsReturned", do_numberOfRecordsReturned },
1590 { 0, "present", do_present },
1591 { 0, "recordType", do_recordType },
1592 { 0, "recordMarc", do_recordMarc },
1593 { 0, "recordDiag", do_recordDiag },
1594 { 0, "responseStatus", do_responseStatus },
1595 { 0, "loadFile", do_loadFile },
1601 interp->result = "wrong # args";
1604 if (ir_method (clientData, interp, argc, argv, tab, 1) == TCL_OK)
1606 return ir_method (&((IRSetObj *)clientData)->set_inher, interp, argc,
1607 argv, ir_set_c_method_tab, 0);
1611 * ir_set_obj_delete: IR Set Object disposal
1613 static void ir_set_obj_delete (ClientData clientData)
1615 free ( (void*) clientData);
1619 * ir_set_obj_mk: IR Set Object creation
1621 static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp,
1622 int argc, char **argv)
1626 if (argc < 2 || argc > 3)
1628 interp->result = "wrong # args";
1633 Tcl_CmdInfo parent_info;
1638 if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info))
1640 interp->result = "No parent";
1643 if (!(obj = ir_malloc (interp, sizeof(*obj))))
1645 obj->parent = (IRObj *) parent_info.clientData;
1647 dst = &obj->set_inher;
1648 src = &obj->parent->set_inher;
1650 dst->num_databaseNames = src->num_databaseNames;
1651 if (!(dst->databaseNames =
1652 ir_malloc (interp, sizeof (*dst->databaseNames)
1653 * dst->num_databaseNames)))
1655 for (i = 0; i < dst->num_databaseNames; i++)
1657 printf ("database %i %s\n", i, src->databaseNames[i]);
1658 if (ir_strdup (interp, &dst->databaseNames[i],
1659 src->databaseNames[i]) == TCL_ERROR)
1662 if (ir_strdup (interp, &dst->queryType, src->queryType)
1666 dst->smallSetUpperBound = src->smallSetUpperBound;
1667 dst->largeSetLowerBound = src->largeSetLowerBound;
1668 dst->mediumSetPresentNumber = src->mediumSetPresentNumber;
1669 printf ("ssu lsl msp %d %d %d\n", dst->smallSetUpperBound,
1670 dst->largeSetLowerBound, dst->mediumSetPresentNumber);
1674 if (ir_strdup (interp, &obj->setName, argv[2]) == TCL_ERROR)
1676 obj->record_list = NULL;
1677 obj->addinfo = NULL;
1678 Tcl_CreateCommand (interp, argv[1], ir_set_obj_method,
1679 (ClientData) obj, ir_set_obj_delete);
1683 /* ------------------------------------------------------- */
1686 * do_scan: Perform scan
1688 static int do_scan (void *o, Tcl_Interp *interp, int argc, char **argv)
1691 Z_APDU apdu, *apdup = &apdu;
1693 IRObj *p = obj->parent;
1695 struct ccl_rpn_node *rpn;
1700 interp->result = "wrong # args";
1703 if (!p->set_inher.num_databaseNames)
1705 interp->result = "no databaseNames";
1710 interp->result = "not connected";
1713 apdu.which = Z_APDU_scanRequest;
1714 apdu.u.scanRequest = &req;
1715 req.referenceId = NULL;
1716 req.num_databaseNames = p->set_inher.num_databaseNames;
1717 req.databaseNames = p->set_inher.databaseNames;
1718 req.attributeSet = oid_getoidbyent (&p->bib1);
1721 if (!(req.termListAndStartPoint =
1722 ir_malloc (interp, sizeof(*req.termListAndStartPoint))))
1724 req.termListAndStartPoint->num_attributes = 0;
1725 req.termListAndStartPoint->attributeList = NULL;
1726 if (!(req.termListAndStartPoint->term = ir_malloc (interp,
1729 req.termListAndStartPoint->term->which = Z_Term_general;
1730 if (!(req.termListAndStartPoint->term->u.general =
1731 ir_malloc (interp, sizeof(*req.termListAndStartPoint->
1734 if (ir_strdup (interp, &req.termListAndStartPoint->term->u.general->buf,
1735 argv[2]) == TCL_ERROR)
1737 req.termListAndStartPoint->term->u.general->len =
1738 req.termListAndStartPoint->term->u.general->size = strlen(argv[2]);
1740 rpn = ccl_find_str(p->bibset, argv[2], &r, &pos);
1743 Tcl_AppendResult (interp, "CCL error: ", ccl_err_msg (r), NULL);
1746 ccl_pr_tree (rpn, stderr);
1747 fprintf (stderr, "\n");
1748 if (!(req.termListAndStartPoint = ccl_scan_query (rpn)))
1751 req.stepSize = &obj->stepSize;
1752 req.numberOfTermsRequested = &obj->numberOfTermsRequested;
1753 req.preferredPositionInResponse = &obj->preferredPositionInResponse;
1754 printf ("stepSize=%d\n", *req.stepSize);
1755 printf ("numberOfTermsRequested=%d\n", *req.numberOfTermsRequested);
1756 printf ("preferredPositionInResponse=%d\n",
1757 *req.preferredPositionInResponse);
1759 if (!z_APDU (p->odr_out, &apdup, 0))
1761 interp->result = odr_errlist [odr_geterror (p->odr_out)];
1762 odr_reset (p->odr_out);
1765 p->sbuf = odr_getbuf (p->odr_out, &p->slen, NULL);
1766 if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0)
1768 interp->result = "cs_put failed in scan";
1773 ir_select_add_write (cs_fileno(p->cs_link), p);
1774 printf("Sent part of scanRequest (%d bytes).\n", p->slen);
1778 printf ("Whole scan request\n");
1784 * do_stepSize: Set/get replace Step Size
1786 static int do_stepSize (void *obj, Tcl_Interp *interp,
1787 int argc, char **argv)
1790 return get_set_int (&p->stepSize, interp, argc, argv);
1794 * do_numberOfTermsRequested: Set/get Number of Terms requested
1796 static int do_numberOfTermsRequested (void *obj, Tcl_Interp *interp,
1797 int argc, char **argv)
1800 return get_set_int (&p->numberOfTermsRequested, interp, argc, argv);
1805 * do_preferredPositionInResponse: Set/get preferred Position
1807 static int do_preferredPositionInResponse (void *obj, Tcl_Interp *interp,
1808 int argc, char **argv)
1811 return get_set_int (&p->preferredPositionInResponse, interp, argc, argv);
1815 * do_scanStatus: Get scan status
1817 static int do_scanStatus (void *obj, Tcl_Interp *interp,
1818 int argc, char **argv)
1821 return get_set_int (&p->scanStatus, interp, argc, argv);
1825 * do_numberOfEntriesReturned: Get number of Entries returned
1827 static int do_numberOfEntriesReturned (void *obj, Tcl_Interp *interp,
1828 int argc, char **argv)
1831 return get_set_int (&p->numberOfEntriesReturned, interp, argc, argv);
1835 * do_positionOfTerm: Get position of Term
1837 static int do_positionOfTerm (void *obj, Tcl_Interp *interp,
1838 int argc, char **argv)
1841 return get_set_int (&p->positionOfTerm, interp, argc, argv);
1845 * do_scanLine: get Scan Line (surrogate or normal) after response
1847 static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv)
1855 interp->result = "wrong # args";
1858 if (Tcl_GetInt (interp, argv[2], &i) == TCL_ERROR)
1860 if (!p->entries_flag || p->which != Z_ListEntries_entries || !p->entries
1861 || i >= p->num_entries || i < 0)
1863 switch (p->entries[i].which)
1865 case Z_Entry_termInfo:
1866 Tcl_AppendElement (interp, "T");
1867 if (p->entries[i].u.term.buf)
1868 Tcl_AppendElement (interp, p->entries[i].u.term.buf);
1870 Tcl_AppendElement (interp, "");
1871 sprintf (numstr, "%d", p->entries[i].u.term.globalOccurrences);
1872 Tcl_AppendElement (interp, numstr);
1874 case Z_Entry_surrogateDiagnostic:
1876 mk_nonSurrogateDiagnostics (interp, p->entries[i].u.diag.condition,
1877 p->entries[i].u.diag.addinfo);
1884 * ir_scan_obj_method: IR Scan Object methods
1886 static int ir_scan_obj_method (ClientData clientData, Tcl_Interp *interp,
1887 int argc, char **argv)
1889 static IRMethod tab[] = {
1890 { 0, "scan", do_scan },
1891 { 0, "stepSize", do_stepSize },
1892 { 0, "numberOfTermsRequested", do_numberOfTermsRequested },
1893 { 0, "preferredPositionInResponse", do_preferredPositionInResponse },
1894 { 0, "scanStatus", do_scanStatus },
1895 { 0, "numberOfEntriesReturned", do_numberOfEntriesReturned },
1896 { 0, "positionOfTerm", do_positionOfTerm },
1897 { 0, "scanLine", do_scanLine },
1903 interp->result = "wrong # args";
1906 return ir_method (clientData, interp, argc, argv, tab, 0);
1910 * ir_scan_obj_delete: IR Scan Object disposal
1912 static void ir_scan_obj_delete (ClientData clientData)
1914 free ( (void*) clientData);
1918 * ir_scan_obj_mk: IR Scan Object creation
1920 static int ir_scan_obj_mk (ClientData clientData, Tcl_Interp *interp,
1921 int argc, char **argv)
1923 Tcl_CmdInfo parent_info;
1928 interp->result = "wrong # args";
1931 if (get_parent_info (interp, argv[1], &parent_info, NULL) == TCL_ERROR)
1933 if (!(obj = ir_malloc (interp, sizeof(*obj))))
1937 obj->numberOfTermsRequested = 20;
1938 obj->preferredPositionInResponse = 1;
1940 obj->entries = NULL;
1941 obj->nonSurrogateDiagnostics = NULL;
1943 obj->parent = (IRObj *) parent_info.clientData;
1944 Tcl_CreateCommand (interp, argv[1], ir_scan_obj_method,
1945 (ClientData) obj, ir_scan_obj_delete);
1949 /* ------------------------------------------------------- */
1951 static void ir_initResponse (void *obj, Z_InitResponse *initrs)
1955 p->initResult = *initrs->result ? 1 : 0;
1956 if (!*initrs->result)
1957 printf("Connection rejected by target.\n");
1959 printf("Connection accepted by target.\n");
1961 free (p->targetImplementationId);
1962 ir_strdup (p->interp, &p->targetImplementationId,
1963 initrs->implementationId);
1964 free (p->targetImplementationName);
1965 ir_strdup (p->interp, &p->targetImplementationName,
1966 initrs->implementationName);
1967 free (p->targetImplementationVersion);
1968 ir_strdup (p->interp, &p->targetImplementationVersion,
1969 initrs->implementationVersion);
1971 p->maximumRecordSize = *initrs->maximumRecordSize;
1972 p->preferredMessageSize = *initrs->preferredMessageSize;
1974 memcpy (&p->options, initrs->options, sizeof(initrs->options));
1975 memcpy (&p->protocolVersion, initrs->protocolVersion,
1976 sizeof(initrs->protocolVersion));
1977 free (p->userInformationField);
1978 p->userInformationField = NULL;
1979 if (initrs->userInformationField)
1983 if (initrs->userInformationField->which == ODR_EXTERNAL_octet &&
1984 (p->userInformationField =
1986 initrs->userInformationField->u.octet_aligned->len)
1989 memcpy (p->userInformationField,
1990 initrs->userInformationField->u.octet_aligned->buf,
1992 (p->userInformationField)[len] = '\0';
1997 static void ir_handleRecords (void *o, Z_Records *zrs)
2000 IRSetObj *setobj = p->set_child;
2002 setobj->which = zrs->which;
2003 setobj->recordFlag = 1;
2004 if (zrs->which == Z_Records_NSD)
2006 const char *addinfo;
2008 setobj->numberOfRecordsReturned = 0;
2009 setobj->condition = *zrs->u.nonSurrogateDiagnostic->condition;
2010 free (setobj->addinfo);
2011 setobj->addinfo = NULL;
2012 addinfo = zrs->u.nonSurrogateDiagnostic->addinfo;
2013 if (addinfo && (setobj->addinfo = malloc (strlen(addinfo) + 1)))
2014 strcpy (setobj->addinfo, addinfo);
2015 printf ("Diagnostic response. %s (%d): %s\n",
2016 diagbib1_str (setobj->condition),
2018 setobj->addinfo ? setobj->addinfo : "");
2025 setobj->numberOfRecordsReturned =
2026 zrs->u.databaseOrSurDiagnostics->num_records;
2027 printf ("Got %d records\n", setobj->numberOfRecordsReturned);
2028 for (offset = 0; offset<setobj->numberOfRecordsReturned; offset++)
2030 rl = new_IR_record (setobj, setobj->start + offset,
2031 zrs->u.databaseOrSurDiagnostics->
2032 records[offset]->which);
2033 if (rl->which == Z_NamePlusRecord_surrogateDiagnostic)
2037 diagrec = zrs->u.databaseOrSurDiagnostics->
2038 records[offset]->u.surrogateDiagnostic;
2040 rl->u.diag.condition = *diagrec->condition;
2041 if (diagrec->addinfo && (rl->u.diag.addinfo =
2042 malloc (strlen (diagrec->addinfo)+1)))
2043 strcpy (rl->u.diag.addinfo, diagrec->addinfo);
2047 Z_DatabaseRecord *zr;
2050 zr = zrs->u.databaseOrSurDiagnostics->records[offset]
2052 oe = (Odr_external*) zr;
2053 if (oe->which == ODR_EXTERNAL_octet
2054 && zr->u.octet_aligned->len)
2056 const char *buf = (char*) zr->u.octet_aligned->buf;
2057 rl->u.marc.rec = iso2709_cvt (buf);
2060 rl->u.marc.rec = NULL;
2066 static void ir_searchResponse (void *o, Z_SearchResponse *searchrs)
2069 IRSetObj *setobj = p->set_child;
2070 Z_Records *zrs = searchrs->records;
2074 setobj->searchStatus = searchrs->searchStatus ? 1 : 0;
2075 setobj->resultCount = *searchrs->resultCount;
2076 printf ("Search response %d, %d hits\n",
2077 setobj->searchStatus, setobj->resultCount);
2079 ir_handleRecords (o, zrs);
2081 setobj->recordFlag = 0;
2084 printf ("Search response, no object!\n");
2088 static void ir_presentResponse (void *o, Z_PresentResponse *presrs)
2091 IRSetObj *setobj = p->set_child;
2092 Z_Records *zrs = presrs->records;
2094 printf ("Received presentResponse\n");
2096 ir_handleRecords (o, zrs);
2099 setobj->recordFlag = 0;
2100 printf ("No records!\n");
2104 static void ir_scanResponse (void *o, Z_ScanResponse *scanrs)
2107 IRScanObj *scanobj = p->scan_child;
2109 printf ("Received scanResponse\n");
2111 scanobj->scanStatus = *scanrs->scanStatus;
2112 printf ("scanStatus=%d\n", scanobj->scanStatus);
2114 if (scanrs->stepSize)
2115 scanobj->stepSize = *scanrs->stepSize;
2116 printf ("stepSize=%d\n", scanobj->stepSize);
2118 scanobj->numberOfEntriesReturned = *scanrs->numberOfEntriesReturned;
2119 printf ("numberOfEntriesReturned=%d\n", scanobj->numberOfEntriesReturned);
2121 if (scanrs->positionOfTerm)
2122 scanobj->positionOfTerm = *scanrs->positionOfTerm;
2124 scanobj->positionOfTerm = -1;
2125 printf ("positionOfTerm=%d\n", scanobj->positionOfTerm);
2127 free (scanobj->entries);
2128 scanobj->entries = NULL;
2129 free (scanobj->nonSurrogateDiagnostics);
2130 scanobj->nonSurrogateDiagnostics = NULL;
2132 if (scanrs->entries)
2137 scanobj->entries_flag = 1;
2138 scanobj->which = scanrs->entries->which;
2139 switch (scanobj->which)
2141 case Z_ListEntries_entries:
2142 scanobj->num_entries = scanrs->entries->u.entries->num_entries;
2143 scanobj->entries = malloc (scanobj->num_entries *
2144 sizeof(*scanobj->entries));
2145 for (i=0; i<scanobj->num_entries; i++)
2147 ze = scanrs->entries->u.entries->entries[i];
2148 scanobj->entries[i].which = ze->which;
2151 case Z_Entry_termInfo:
2152 if (ze->u.termInfo->term->which == Z_Term_general)
2154 int l = ze->u.termInfo->term->u.general->len;
2155 scanobj->entries[i].u.term.buf = malloc (1+l);
2156 memcpy (scanobj->entries[i].u.term.buf,
2157 ze->u.termInfo->term->u.general->buf,
2159 scanobj->entries[i].u.term.buf[l] = '\0';
2162 scanobj->entries[i].u.term.buf = NULL;
2163 if (ze->u.termInfo->globalOccurrences)
2164 scanobj->entries[i].u.term.globalOccurrences =
2165 *ze->u.termInfo->globalOccurrences;
2167 scanobj->entries[i].u.term.globalOccurrences = 0;
2169 case Z_Entry_surrogateDiagnostic:
2170 scanobj->entries[i].u.diag.addinfo =
2171 malloc (1+strlen(ze->u.surrogateDiagnostic->
2173 strcpy (scanobj->entries[i].u.diag.addinfo,
2174 ze->u.surrogateDiagnostic->addinfo);
2175 scanobj->entries[i].u.diag.condition =
2176 *ze->u.surrogateDiagnostic->condition;
2181 case Z_ListEntries_nonSurrogateDiagnostics:
2182 scanobj->num_diagRecs = scanrs->entries->
2183 u.nonSurrogateDiagnostics->num_diagRecs;
2184 scanobj->nonSurrogateDiagnostics = malloc (scanobj->num_diagRecs *
2185 sizeof(*scanobj->nonSurrogateDiagnostics));
2190 scanobj->entries_flag = 0;
2194 * ir_select_read: handle incoming packages
2196 void ir_select_read (ClientData clientData)
2198 IRObj *p = clientData;
2204 r = cs_rcvconnect (p->cs_link);
2208 ir_select_remove_write (cs_fileno (p->cs_link), p);
2211 printf ("cs_rcvconnect error\n");
2213 Tcl_Eval (p->interp, p->failback);
2214 do_disconnect (p, NULL, 0, NULL);
2218 Tcl_Eval (p->interp, p->callback);
2223 if ((r=cs_get (p->cs_link, &p->buf_in, &p->len_in)) <= 0)
2225 printf ("cs_get failed\n");
2226 ir_select_remove (cs_fileno (p->cs_link), p);
2228 Tcl_Eval (p->interp, p->failback);
2229 do_disconnect (p, NULL, 0, NULL);
2234 odr_setbuf (p->odr_in, p->buf_in, r, 0);
2235 printf ("cs_get ok, got %d\n", r);
2236 if (!z_APDU (p->odr_in, &apdu, 0))
2238 printf ("%s\n", odr_errlist [odr_geterror (p->odr_in)]);
2240 Tcl_Eval (p->interp, p->failback);
2241 do_disconnect (p, NULL, 0, NULL);
2246 case Z_APDU_initResponse:
2247 ir_initResponse (p, apdu->u.initResponse);
2249 case Z_APDU_searchResponse:
2250 ir_searchResponse (p, apdu->u.searchResponse);
2252 case Z_APDU_presentResponse:
2253 ir_presentResponse (p, apdu->u.presentResponse);
2255 case Z_APDU_scanResponse:
2256 ir_scanResponse (p, apdu->u.scanResponse);
2259 printf("Received unknown APDU type (%d).\n",
2262 Tcl_Eval (p->interp, p->failback);
2263 do_disconnect (p, NULL, 0, NULL);
2266 Tcl_Eval (p->interp, p->callback);
2267 } while (cs_more (p->cs_link));
2271 * ir_select_write: handle outgoing packages - not yet written.
2273 void ir_select_write (ClientData clientData)
2275 IRObj *p = clientData;
2278 printf ("In write handler.....\n");
2281 r = cs_rcvconnect (p->cs_link);
2287 printf ("cs_rcvconnect error\n");
2288 ir_select_remove_write (cs_fileno (p->cs_link), p);
2290 Tcl_Eval (p->interp, p->failback);
2291 do_disconnect (p, NULL, 0, NULL);
2294 ir_select_remove_write (cs_fileno (p->cs_link), p);
2296 Tcl_Eval (p->interp, p->callback);
2299 if ((r=cs_put (p->cs_link, p->sbuf, p->slen)) < 0)
2301 printf ("select write fail\n");
2303 Tcl_Eval (p->interp, p->failback);
2304 do_disconnect (p, NULL, 0, NULL);
2306 else if (r == 0) /* remove select bit */
2308 ir_select_remove_write (cs_fileno (p->cs_link), p);
2312 /* ------------------------------------------------------- */
2315 * ir_tcl_init: Registration of TCL commands.
2317 int ir_tcl_init (Tcl_Interp *interp)
2319 Tcl_CreateCommand (interp, "ir", ir_obj_mk, (ClientData) NULL,
2320 (Tcl_CmdDeleteProc *) NULL);
2321 Tcl_CreateCommand (interp, "ir-set", ir_set_obj_mk,
2322 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
2323 Tcl_CreateCommand (interp, "ir-scan", ir_scan_obj_mk,
2324 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);