X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=ir-tcl.c;h=21e810028a581f2d16822d8a0731b19e44f6cd6c;hb=534e39b7986d6cbbfac1c99bcca97d8d1fb5e990;hp=68d04b4e7d190c5404410b8570f1830222ed465d;hpb=bbe888d936adcb31a74a64c0327bd7e14b56a766;p=ir-tcl-moved-to-github.git diff --git a/ir-tcl.c b/ir-tcl.c index 68d04b4..21e8100 100644 --- a/ir-tcl.c +++ b/ir-tcl.c @@ -5,7 +5,36 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: ir-tcl.c,v $ - * Revision 1.76 1996-02-20 16:09:51 adam + * Revision 1.83 1996-03-05 09:21:09 adam + * Bug fix: memory used by GRS records wasn't freed. + * Rewrote some of the error handling code - the connection is always + * closed before failback is called. + * If failback is defined the send APDU methods (init, search, ...) will + * return OK but invoke failback (as is the case if the write operation + * fails). + * Bug fix: ref_count in assoc object could grow if fraction of PDU was + * read. + * + * Revision 1.82 1996/02/29 15:30:21 adam + * Export of IrTcl functionality to extensions. + * + * Revision 1.81 1996/02/26 18:38:32 adam + * Work on export of set methods. + * + * Revision 1.80 1996/02/23 17:31:39 adam + * More functions made available to the wais tcl extension. + * + * Revision 1.79 1996/02/23 13:41:38 adam + * Work on public access to simple ir class system. + * + * Revision 1.78 1996/02/21 10:16:08 adam + * Simplified select handling. Only one function ir_tcl_select_set has + * to be externally defined. + * + * Revision 1.77 1996/02/20 17:52:58 adam + * Uses the YAZ oid system to name record syntax object identifiers. + * + * Revision 1.76 1996/02/20 16:09:51 adam * Bug fix: didn't set element set names stamp correctly on result * set records when element set names were set to the empty string. * @@ -278,22 +307,55 @@ #define CS_BLOCK 0 +#define IRTCL_GENERIC_FILES 0 + #include "ir-tclp.h" -typedef struct { - int type; - char *name; - int (*method) (void *obj, Tcl_Interp *interp, int argc, char **argv); -} IrTcl_Method; +static void ir_deleteDiags (IrTcl_Diagnostic **dst_list, int *dst_num); -typedef struct { - void *obj; - IrTcl_Method *tab; -} IrTcl_Methods; +static void ir_select_notify (ClientData clientData, int r, int w, int e); -static void ir_deleteDiags (IrTcl_Diagnostic **dst_list, int *dst_num); -static int do_disconnect (void *obj, Tcl_Interp *interp, - int argc, char **argv); +void ir_select_add (int fd, void *obj) +{ + ir_tcl_select_set (ir_select_notify, fd, obj, 1, 0, 0); +} + +void ir_select_add_write (int fd, void *obj) +{ + ir_tcl_select_set (ir_select_notify, fd, obj, 1, 1, 0); +} + +void ir_select_remove (int fd, void *obj) +{ + ir_tcl_select_set (NULL, fd, obj, 0, 0, 0); +} + +void ir_select_remove_write (int fd, void *obj) +{ + ir_tcl_select_set (ir_select_notify, fd, obj, 1, 0, 0); +} + +static void delete_IR_record (IrTcl_RecordList *rl) +{ + switch (rl->which) + { + case Z_NamePlusRecord_databaseRecord: + switch (rl->u.dbrec.type) + { + case VAL_GRS1: + ir_tcl_grs_del (&rl->u.dbrec.u.grs1); + break; + default: + } + free (rl->u.dbrec.buf); + break; + case Z_NamePlusRecord_surrogateDiagnostic: + ir_deleteDiags (&rl->u.surrogateDiagnostics.list, + &rl->u.surrogateDiagnostics.num); + break; + } + free (rl->elements); +} static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj, int no, int which, @@ -308,18 +370,7 @@ static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj, 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; - break; - case Z_NamePlusRecord_surrogateDiagnostic: - ir_deleteDiags (&rl->u.surrogateDiagnostics.list, - &rl->u.surrogateDiagnostics.num); - break; - } + delete_IR_record (rl); break; } } @@ -335,38 +386,15 @@ static IrTcl_RecordList *new_IR_record (IrTcl_SetObj *setobj, return rl; } -static struct { - enum oid_value value; - const char *name; -} IrTcl_recordSyntaxTab[] = { -{ VAL_UNIMARC, "UNIMARC" }, -{ VAL_INTERMARC, "INTERMARC" }, -{ VAL_CCF, "CCF" }, -{ VAL_USMARC, "USMARC" }, -{ VAL_UKMARC, "UKMARC" }, -{ VAL_NORMARC, "NORMARC" }, -{ VAL_LIBRISMARC, "LIBRISMARC" }, -{ VAL_DANMARC, "DANMARC" }, -{ VAL_FINMARC, "FINMARC" }, -{ VAL_MAB, "MAB" }, -{ VAL_CANMARC, "CANMARC" }, -{ VAL_SBN, "SBN" }, -{ VAL_PICAMARC, "PICAMARC" }, -{ VAL_AUSMARC, "AUSMARC" }, -{ VAL_IBERMARC, "IBERMARC" }, -{ VAL_SUTRS, "SUTRS" }, -{ VAL_GRS1, "GRS1" }, -{ 0, NULL } -}; - /* - * IrTcl_eval + * ir_tcl_eval */ -int IrTcl_eval (Tcl_Interp *interp, const char *command) +int ir_tcl_eval (Tcl_Interp *interp, const char *command) { char *tmp = ir_tcl_malloc (strlen(command)+1); int r; + logf (LOG_DEBUG, "Invoking %.17s ...", command); strcpy (tmp, command); r = Tcl_Eval (interp, tmp); if (r == TCL_ERROR) @@ -380,13 +408,21 @@ int IrTcl_eval (Tcl_Interp *interp, const char *command) /* * IrTcl_getRecordSyntaxStr: Return record syntax name of object id */ -static const char *IrTcl_getRecordSyntaxStr (enum oid_value value) +static char *IrTcl_getRecordSyntaxStr (enum oid_value value) { - int i; - for (i = 0; IrTcl_recordSyntaxTab[i].name; i++) - if (IrTcl_recordSyntaxTab[i].value == value) - return IrTcl_recordSyntaxTab[i].name; - return "USMARC"; + int *o; + struct oident ent, *entp; + + ent.proto = PROTO_Z3950; + ent.oclass = CLASS_RECSYN; + ent.value = value; + + o = oid_getoidbyent (&ent); + entp = oid_getentbyoid (o); + + if (!entp) + return ""; + return entp->desc; } /* @@ -394,11 +430,7 @@ static const char *IrTcl_getRecordSyntaxStr (enum oid_value value) */ static enum oid_value IrTcl_getRecordSyntaxVal (const char *name) { - int i; - for (i = 0; IrTcl_recordSyntaxTab[i].name; i++) - if (!strcmp (IrTcl_recordSyntaxTab[i].name, name)) - return IrTcl_recordSyntaxTab[i].value; - return 0; + return oid_getvalbyname (name); } static IrTcl_RecordList *find_IR_record (IrTcl_SetObj *setobj, int no) @@ -419,16 +451,7 @@ static void delete_IR_records (IrTcl_SetObj *setobj) for (rl = setobj->record_list; rl; rl = rl1) { - switch (rl->which) - { - case Z_NamePlusRecord_databaseRecord: - free (rl->u.dbrec.buf); - break; - case Z_NamePlusRecord_surrogateDiagnostic: - ir_deleteDiags (&rl->u.surrogateDiagnostics.list, - &rl->u.surrogateDiagnostics.num); - break; - } + delete_IR_record (rl); rl1 = rl->next; free (rl); } @@ -436,9 +459,9 @@ static void delete_IR_records (IrTcl_SetObj *setobj) } /* - * get_set_int: Set/get integer value + * ir_tcl_get_set_int: Set/get integer value */ -static int get_set_int (int *val, Tcl_Interp *interp, int argc, char **argv) +int ir_tcl_get_set_int (int *val, Tcl_Interp *interp, int argc, char **argv) { char buf[20]; @@ -453,9 +476,10 @@ static int get_set_int (int *val, Tcl_Interp *interp, int argc, char **argv) } /* - * ir_method: Search for method in table and invoke method handler + * ir_tcl_method: Search for method in table and invoke method handler */ -int ir_method (Tcl_Interp *interp, int argc, char **argv, IrTcl_Methods *tab) +int ir_tcl_method (Tcl_Interp *interp, int argc, char **argv, + IrTcl_Methods *tab, int *ret) { IrTcl_Methods *tab_i = tab; IrTcl_Method *t; @@ -469,45 +493,29 @@ int ir_method (Tcl_Interp *interp, int argc, char **argv, IrTcl_Methods *tab) } else if (!strcmp (t->name, argv[1])) - return (*t->method)(tab_i->obj, interp, argc, argv); + { + *ret = (*t->method)(tab_i->obj, interp, argc, argv); + return TCL_OK; + } if (argc <= 0) return TCL_OK; +#if 0 Tcl_AppendResult (interp, "Bad method: ", argv[1], ". Possible methods:", NULL); for (tab_i = tab; tab_i->tab; tab_i++) for (t = tab_i->tab; t->name; t++) Tcl_AppendResult (interp, " ", t->name, NULL); +#endif + *ret = TCL_ERROR; return TCL_ERROR; } /* - * ir_method_r: Get status for all readable elements + * ir_tcl_named_bits: get/set named bits */ -int ir_method_r (void *obj, Tcl_Interp *interp, int argc, char **argv, - IrTcl_Method *tab) -{ - char *argv_n[3]; - int argc_n; - - argv_n[0] = argv[0]; - argc_n = 2; - for (; tab->name; tab++) - if (tab->type) - { - argv_n[1] = tab->name; - Tcl_AppendResult (interp, "{", NULL); - (*tab->method)(obj, interp, argc_n, argv_n); - Tcl_AppendResult (interp, "} ", NULL); - } - return TCL_OK; -} - -/* - * ir_named_bits: get/set named bits - */ -int ir_named_bits (struct ir_named_entry *tab, Odr_bitmask *ob, - Tcl_Interp *interp, int argc, char **argv) +int ir_tcl_named_bits (struct ir_named_entry *tab, Odr_bitmask *ob, + Tcl_Interp *interp, int argc, char **argv) { struct ir_named_entry *ti; if (argc > 0) @@ -700,7 +708,7 @@ static int do_options (void *obj, Tcl_Interp *interp, ODR_MASK_SET (&p->options, 14); return TCL_OK; } - return ir_named_bits (options_tab, &p->options, interp, argc-2, argv+2); + return ir_tcl_named_bits (options_tab, &p->options, interp, argc-2, argv+2); } /* @@ -806,7 +814,7 @@ static int do_preferredMessageSize (void *obj, Tcl_Interp *interp, p->preferredMessageSize = 30000; return TCL_OK; } - return get_set_int (&p->preferredMessageSize, interp, argc, argv); + return ir_tcl_get_set_int (&p->preferredMessageSize, interp, argc, argv); } /* @@ -822,7 +830,7 @@ static int do_maximumRecordSize (void *obj, Tcl_Interp *interp, p->maximumRecordSize = 30000; return TCL_OK; } - return get_set_int (&p->maximumRecordSize, interp, argc, argv); + return ir_tcl_get_set_int (&p->maximumRecordSize, interp, argc, argv); } /* @@ -835,7 +843,7 @@ static int do_initResult (void *obj, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&p->initResult, interp, argc, argv); + return ir_tcl_get_set_int (&p->initResult, interp, argc, argv); } @@ -1077,7 +1085,7 @@ static int do_connect (void *obj, Tcl_Interp *interp, if ((r=cs_connect (p->cs_link, addr)) < 0) { interp->result = "connect fail"; - do_disconnect (p, NULL, 2, NULL); + ir_tcl_disconnect (p); return TCL_ERROR; } logf(LOG_DEBUG, "cs_connect() returned %d fd=%d", r, @@ -1101,7 +1109,7 @@ static int do_connect (void *obj, Tcl_Interp *interp, { p->state = IR_TCL_R_Idle; if (p->callback) - IrTcl_eval (p->interp, p->callback); + ir_tcl_eval (p->interp, p->callback); } } else @@ -1109,25 +1117,11 @@ static int do_connect (void *obj, Tcl_Interp *interp, return TCL_OK; } -/* - * do_disconnect: disconnect method on IR object +/* + * ir_tcl_disconnect: close connection */ -static int do_disconnect (void *obj, Tcl_Interp *interp, - int argc, char **argv) +void ir_tcl_disconnect (IrTcl_Obj *p) { - IrTcl_Obj *p = obj; - - if (argc == 0) - { - p->state = IR_TCL_R_Idle; - p->eventType = NULL; - p->hostname = 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); @@ -1164,6 +1158,28 @@ static int do_disconnect (void *obj, Tcl_Interp *interp, ir_tcl_del_q (p); } assert (!p->cs_link); +} + +/* + * do_disconnect: disconnect method on IR object + */ +static int do_disconnect (void *obj, Tcl_Interp *interp, + int argc, char **argv) +{ + IrTcl_Obj *p = obj; + + if (argc == 0) + { + p->state = IR_TCL_R_Idle; + p->eventType = NULL; + p->hostname = NULL; + p->cs_link = NULL; +#if IRTCL_GENERIC_FILES + p->csFile = 0; +#endif + return TCL_OK; + } + ir_tcl_disconnect (p); return TCL_OK; } @@ -1410,13 +1426,14 @@ static int do_databaseNames (void *obj, Tcl_Interp *interp, } p->num_databaseNames = argc - 2; p->databaseNames = - ir_tcl_malloc (sizeof(*p->databaseNames) * p->num_databaseNames); + ir_tcl_malloc (sizeof(*p->databaseNames) * (1+p->num_databaseNames)); for (i=0; inum_databaseNames; i++) { if (ir_tcl_strdup (interp, &p->databaseNames[i], argv[2+i]) == TCL_ERROR) return TCL_ERROR; } + p->databaseNames[i] = NULL; return TCL_OK; } @@ -1433,7 +1450,7 @@ static int do_replaceIndicator (void *obj, Tcl_Interp *interp, p->replaceIndicator = 1; return TCL_OK; } - return get_set_int (&p->replaceIndicator, interp, argc, argv); + return ir_tcl_get_set_int (&p->replaceIndicator, interp, argc, argv); } /* @@ -1490,7 +1507,7 @@ static int do_smallSetUpperBound (void *o, Tcl_Interp *interp, p->smallSetUpperBound = 0; return TCL_OK; } - return get_set_int (&p->smallSetUpperBound, interp, argc, argv); + return ir_tcl_get_set_int (&p->smallSetUpperBound, interp, argc, argv); } /* @@ -1506,7 +1523,7 @@ static int do_largeSetLowerBound (void *o, Tcl_Interp *interp, p->largeSetLowerBound = 2; return TCL_OK; } - return get_set_int (&p->largeSetLowerBound, interp, argc, argv); + return ir_tcl_get_set_int (&p->largeSetLowerBound, interp, argc, argv); } /* @@ -1522,7 +1539,7 @@ static int do_mediumSetPresentNumber (void *o, Tcl_Interp *interp, p->mediumSetPresentNumber = 0; return TCL_OK; } - return get_set_int (&p->mediumSetPresentNumber, interp, argc, argv); + return ir_tcl_get_set_int (&p->mediumSetPresentNumber, interp, argc, argv); } /* @@ -1577,6 +1594,11 @@ static int do_preferredRecordSyntax (void *obj, Tcl_Interp *interp, ir_tcl_malloc (sizeof(*p->preferredRecordSyntax)))) *p->preferredRecordSyntax = IrTcl_getRecordSyntaxVal (argv[2]); } + else if (argc == 2) + { + Tcl_AppendElement (interp, IrTcl_getRecordSyntaxStr + (*p->preferredRecordSyntax)); + } return TCL_OK; } @@ -1659,50 +1681,50 @@ static int do_mediumSetElementSetNames (void *obj, Tcl_Interp *interp, } 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 }, -{ 1, "maximumRecordSize", do_maximumRecordSize }, -{ 1, "implementationName", do_implementationName }, -{ 1, "implementationId", do_implementationId }, -{ 1, "implementationVersion", do_implementationVersion }, -{ 0, "targetImplementationName", do_targetImplementationName }, -{ 0, "targetImplementationId", do_targetImplementationId }, -{ 0, "targetImplementationVersion", do_targetImplementationVersion }, -{ 0, "userInformationField", do_userInformationField }, -{ 1, "idAuthentication", do_idAuthentication }, -{ 0, "options", do_options }, -{ 0, "init", do_init_request }, -{ 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} +{ "comstack", do_comstack, NULL }, +{ "protocol", do_protocol, NULL }, +{ "failback", do_failback, NULL }, +{ "failInfo", do_failInfo, NULL }, +{ "apduInfo", do_apduInfo, NULL }, +{ "logLevel", do_logLevel, NULL }, + +{ "eventType", do_eventType, NULL }, +{ "connect", do_connect, NULL }, +{ "protocolVersion", do_protocolVersion, NULL }, +{ "preferredMessageSize", do_preferredMessageSize, NULL }, +{ "maximumRecordSize", do_maximumRecordSize, NULL }, +{ "implementationName", do_implementationName, NULL }, +{ "implementationId", do_implementationId, NULL }, +{ "implementationVersion", do_implementationVersion, NULL }, +{ "targetImplementationName", do_targetImplementationName, NULL }, +{ "targetImplementationId", do_targetImplementationId, NULL }, +{ "targetImplementationVersion", do_targetImplementationVersion, NULL}, +{ "userInformationField", do_userInformationField, NULL}, +{ "idAuthentication", do_idAuthentication, NULL}, +{ "options", do_options, NULL}, +{ "init", do_init_request, NULL}, +{ "initResult", do_initResult, NULL}, +{ "disconnect", do_disconnect, NULL}, +{ "callback", do_callback, NULL}, +{ "initResponse", do_initResponse, NULL}, +{ "triggerResourceControl", do_triggerResourceControl, NULL}, +{ "initResponse", do_initResponse, NULL}, +{ NULL, NULL} }; static IrTcl_Method ir_set_c_method_tab[] = { -{ 0, "databaseNames", do_databaseNames}, -{ 0, "replaceIndicator", do_replaceIndicator}, -{ 0, "queryType", do_queryType }, -{ 0, "preferredRecordSyntax", do_preferredRecordSyntax }, -{ 0, "smallSetUpperBound", do_smallSetUpperBound}, -{ 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} +{ "databaseNames", do_databaseNames, NULL}, +{ "replaceIndicator", do_replaceIndicator, NULL}, +{ "queryType", do_queryType, NULL}, +{ "preferredRecordSyntax", do_preferredRecordSyntax, NULL}, +{ "smallSetUpperBound", do_smallSetUpperBound, NULL}, +{ "largeSetLowerBound", do_largeSetLowerBound, NULL}, +{ "mediumSetPresentNumber", do_mediumSetPresentNumber, NULL}, +{ "referenceId", do_referenceId, NULL}, +{ "elementSetNames", do_elementSetNames, NULL}, +{ "smallSetElementSetNames", do_smallSetElementSetNames, NULL}, +{ "mediumSetElementSetNames", do_mediumSetElementSetNames, NULL}, +{ NULL, NULL} }; /* @@ -1713,17 +1735,19 @@ static int ir_obj_method (ClientData clientData, Tcl_Interp *interp, { IrTcl_Methods tab[3]; IrTcl_Obj *p = clientData; + int r; if (argc < 2) - return ir_method_r (clientData, interp, argc, argv, ir_method_tab); - + return TCL_ERROR; + tab[0].tab = ir_method_tab; tab[0].obj = p; tab[1].tab = ir_set_c_method_tab; tab[1].obj = &p->set_inher; tab[2].tab = NULL; - - return ir_method (interp, argc, argv, tab); + + ir_tcl_method (interp, argc, argv, tab, &r); + return r; } /* @@ -1746,7 +1770,7 @@ static void ir_obj_delete (ClientData clientData) tab[1].obj = &obj->set_inher; tab[2].tab = NULL; - ir_method (NULL, -1, NULL, tab); + ir_tcl_method (NULL, -1, NULL, tab, NULL); ir_tcl_del_q (obj); odr_destroy (obj->odr_in); @@ -1756,10 +1780,11 @@ static void ir_obj_delete (ClientData clientData) } /* - * ir_obj_mk: IR Object creation + * ir_obj_init: IR Object initialization */ -static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp, - int argc, char **argv) +int ir_obj_init (ClientData clientData, Tcl_Interp *interp, + int argc, char **argv, ClientData *subData, + ClientData parentData) { IrTcl_Methods tab[3]; IrTcl_Obj *obj; @@ -1800,13 +1825,40 @@ static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp, tab[1].obj = &obj->set_inher; tab[2].tab = NULL; - if (ir_method (interp, 0, NULL, tab) == TCL_ERROR) + if (ir_tcl_method (interp, 0, NULL, tab, NULL) == TCL_ERROR) + { + Tcl_AppendResult (interp, "Failed to initialize ", argv[1], NULL); + return TCL_ERROR; + } + *subData = obj; + return TCL_OK; +} + + +/* + * ir_obj_mk: IR Object creation + */ +static int ir_obj_mk (ClientData clientData, Tcl_Interp *interp, + int argc, char **argv) +{ + ClientData subData; + int r = ir_obj_init (clientData, interp, argc, argv, &subData, 0); + + if (r == TCL_ERROR) return TCL_ERROR; Tcl_CreateCommand (interp, argv[1], ir_obj_method, - (ClientData) obj, ir_obj_delete); + subData, ir_obj_delete); return TCL_OK; } +IrTcl_Class ir_obj_class = { + "ir", + ir_obj_init, + ir_obj_method, + ir_obj_delete +}; + + /* ------------------------------------------------------- */ /* * do_search: Do search request @@ -2031,7 +2083,7 @@ static int do_resultCount (void *o, Tcl_Interp *interp, obj->resultCount = 0; return TCL_OK; } - return get_set_int (&obj->resultCount, interp, argc, argv); + return ir_tcl_get_set_int (&obj->resultCount, interp, argc, argv); } /* @@ -2044,7 +2096,7 @@ static int do_searchStatus (void *o, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&obj->searchStatus, interp, argc, argv); + return ir_tcl_get_set_int (&obj->searchStatus, interp, argc, argv); } /* @@ -2057,7 +2109,7 @@ static int do_presentStatus (void *o, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&obj->presentStatus, interp, argc, argv); + return ir_tcl_get_set_int (&obj->presentStatus, interp, argc, argv); } /* @@ -2074,7 +2126,8 @@ static int do_nextResultSetPosition (void *o, Tcl_Interp *interp, obj->nextResultSetPosition = 0; return TCL_OK; } - return get_set_int (&obj->nextResultSetPosition, interp, argc, argv); + return ir_tcl_get_set_int (&obj->nextResultSetPosition, interp, + argc, argv); } /* @@ -2113,7 +2166,8 @@ static int do_numberOfRecordsReturned (void *o, Tcl_Interp *interp, obj->numberOfRecordsReturned = 0; return TCL_OK; } - return get_set_int (&obj->numberOfRecordsReturned, interp, argc, argv); + return ir_tcl_get_set_int (&obj->numberOfRecordsReturned, interp, + argc, argv); } /* @@ -2552,26 +2606,26 @@ 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 }, - { 0, "setName", do_setName }, - { 0, "resultCount", do_resultCount }, - { 0, "numberOfRecordsReturned", do_numberOfRecordsReturned }, - { 0, "present", do_present }, - { 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 }, - { 0, NULL, NULL} + { "search", do_search, NULL}, + { "searchResponse", do_searchResponse, NULL}, + { "presentResponse", do_presentResponse, NULL}, + { "searchStatus", do_searchStatus, NULL}, + { "presentStatus", do_presentStatus, NULL}, + { "nextResultSetPosition", do_nextResultSetPosition, NULL}, + { "setName", do_setName, NULL}, + { "resultCount", do_resultCount, NULL}, + { "numberOfRecordsReturned", do_numberOfRecordsReturned, NULL}, + { "present", do_present, NULL}, + { "type", do_type, NULL}, + { "getMarc", do_getMarc, NULL}, + { "getSutrs", do_getSutrs, NULL}, + { "getGrs", do_getGrs, NULL}, + { "recordType", do_recordType, NULL}, + { "recordElements", do_recordElements, NULL}, + { "diag", do_diag, NULL}, + { "responseStatus", do_responseStatus, NULL}, + { "loadFile", do_loadFile, NULL}, + { NULL, NULL} }; /* @@ -2582,6 +2636,7 @@ static int ir_set_obj_method (ClientData clientData, Tcl_Interp *interp, { IrTcl_Methods tabs[3]; IrTcl_SetObj *p = clientData; + int r; if (argc < 2) { @@ -2594,7 +2649,8 @@ static int ir_set_obj_method (ClientData clientData, Tcl_Interp *interp, tabs[1].obj = &p->set_inher; tabs[2].tab = NULL; - return ir_method (interp, argc, argv, tabs); + ir_tcl_method (interp, argc, argv, tabs, &r); + return r; } /* @@ -2613,16 +2669,17 @@ static void ir_set_obj_delete (ClientData clientData) tabs[1].obj = &p->set_inher; tabs[2].tab = NULL; - ir_method (NULL, -1, NULL, tabs); + ir_tcl_method (NULL, -1, NULL, tabs, NULL); free (p); } /* - * ir_set_obj_mk: IR Set Object creation + * ir_set_obj_init: IR Set Object initialization */ -static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, - int argc, char **argv) +static int ir_set_obj_init (ClientData clientData, Tcl_Interp *interp, + int argc, char **argv, ClientData *subData, + ClientData parentData) { IrTcl_Methods tabs[3]; IrTcl_SetObj *obj; @@ -2634,33 +2691,30 @@ static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, } obj = ir_tcl_malloc (sizeof(*obj)); logf (LOG_DEBUG, "ir set create"); - if (argc == 3) + if (parentData) { - Tcl_CmdInfo parent_info; int i; IrTcl_SetCObj *dst; IrTcl_SetCObj *src; - if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info)) - { - interp->result = "No parent"; - return TCL_ERROR; - } - obj->parent = (IrTcl_Obj *) parent_info.clientData; + obj->parent = (IrTcl_Obj *) parentData; dst = &obj->set_inher; src = &obj->parent->set_inher; if ((dst->num_databaseNames = src->num_databaseNames)) + { dst->databaseNames = ir_tcl_malloc (sizeof (*dst->databaseNames) - * dst->num_databaseNames); + * (1+dst->num_databaseNames)); + for (i = 0; i < dst->num_databaseNames; i++) + if (ir_tcl_strdup (interp, &dst->databaseNames[i], + src->databaseNames[i]) == TCL_ERROR) + return TCL_ERROR; + dst->databaseNames[i] = NULL; + } else dst->databaseNames = NULL; - for (i = 0; i < dst->num_databaseNames; i++) - if (ir_tcl_strdup (interp, &dst->databaseNames[i], - src->databaseNames[i]) == TCL_ERROR) - return TCL_ERROR; if (ir_tcl_strdup (interp, &dst->queryType, src->queryType) == TCL_ERROR) return TCL_ERROR; @@ -2701,14 +2755,48 @@ static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, tabs[0].obj = obj; tabs[1].tab = NULL; - if (ir_method (interp, 0, NULL, tabs) == TCL_ERROR) + if (ir_tcl_method (interp, 0, NULL, tabs, NULL) == TCL_ERROR) return TCL_ERROR; + *subData = obj; + return TCL_OK; +} + +/* + * ir_set_obj_mk: IR Set Object creation + */ +static int ir_set_obj_mk (ClientData clientData, Tcl_Interp *interp, + int argc, char **argv) +{ + ClientData subData; + ClientData parentData = 0; + int r; + + if (argc == 3) + { + Tcl_CmdInfo parent_info; + if (!Tcl_GetCommandInfo (interp, argv[2], &parent_info)) + { + interp->result = "No parent"; + return TCL_ERROR; + } + parentData = parent_info.clientData; + } + r = ir_set_obj_init (clientData, interp, argc, argv, &subData, parentData); + if (r == TCL_ERROR) + return TCL_ERROR; Tcl_CreateCommand (interp, argv[1], ir_set_obj_method, - (ClientData) obj, ir_set_obj_delete); + subData, ir_set_obj_delete); return TCL_OK; } +IrTcl_Class ir_set_obj_class = { + "ir-set", + ir_set_obj_init, + ir_set_obj_method, + ir_set_obj_delete +}; + /* ------------------------------------------------------- */ /* @@ -2828,7 +2916,7 @@ static int do_stepSize (void *obj, Tcl_Interp *interp, p->stepSize = 0; return TCL_OK; } - return get_set_int (&p->stepSize, interp, argc, argv); + return ir_tcl_get_set_int (&p->stepSize, interp, argc, argv); } /* @@ -2844,7 +2932,7 @@ static int do_numberOfTermsRequested (void *obj, Tcl_Interp *interp, p->numberOfTermsRequested = 20; return TCL_OK; } - return get_set_int (&p->numberOfTermsRequested, interp, argc, argv); + return ir_tcl_get_set_int (&p->numberOfTermsRequested, interp, argc, argv); } @@ -2861,7 +2949,8 @@ static int do_preferredPositionInResponse (void *obj, Tcl_Interp *interp, p->preferredPositionInResponse = 1; return TCL_OK; } - return get_set_int (&p->preferredPositionInResponse, interp, argc, argv); + return ir_tcl_get_set_int (&p->preferredPositionInResponse, interp, + argc, argv); } /* @@ -2874,7 +2963,7 @@ static int do_scanStatus (void *obj, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&p->scanStatus, interp, argc, argv); + return ir_tcl_get_set_int (&p->scanStatus, interp, argc, argv); } /* @@ -2887,7 +2976,8 @@ static int do_numberOfEntriesReturned (void *obj, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&p->numberOfEntriesReturned, interp, argc, argv); + return ir_tcl_get_set_int (&p->numberOfEntriesReturned, interp, + argc, argv); } /* @@ -2900,7 +2990,7 @@ static int do_positionOfTerm (void *obj, Tcl_Interp *interp, if (argc <= 0) return TCL_OK; - return get_set_int (&p->positionOfTerm, interp, argc, argv); + return ir_tcl_get_set_int (&p->positionOfTerm, interp, argc, argv); } /* @@ -2961,16 +3051,16 @@ static int do_scanLine (void *obj, Tcl_Interp *interp, int argc, char **argv) } 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 }, - { 0, "scanStatus", do_scanStatus }, - { 0, "numberOfEntriesReturned", do_numberOfEntriesReturned }, - { 0, "positionOfTerm", do_positionOfTerm }, - { 0, "scanLine", do_scanLine }, - { 0, NULL, NULL} + { "scan", do_scan, NULL}, + { "scanResponse", do_scanResponse, NULL}, + { "stepSize", do_stepSize, NULL}, + { "numberOfTermsRequested", do_numberOfTermsRequested, NULL}, + { "preferredPositionInResponse", do_preferredPositionInResponse, NULL}, + { "scanStatus", do_scanStatus, NULL}, + { "numberOfEntriesReturned", do_numberOfEntriesReturned, NULL}, + { "positionOfTerm", do_positionOfTerm, NULL}, + { "scanLine", do_scanLine, NULL}, + { NULL, NULL} }; /* @@ -2980,6 +3070,7 @@ static int ir_scan_obj_method (ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { IrTcl_Methods tabs[2]; + int r; if (argc < 2) { @@ -2990,7 +3081,8 @@ static int ir_scan_obj_method (ClientData clientData, Tcl_Interp *interp, tabs[0].obj = clientData; tabs[1].tab = NULL; - return ir_method (interp, argc, argv, tabs); + ir_tcl_method (interp, argc, argv, tabs, &r); + return r; } /* @@ -3005,7 +3097,7 @@ static void ir_scan_obj_delete (ClientData clientData) tabs[0].obj = obj; tabs[1].tab = NULL; - ir_method (NULL, -1, NULL, tabs); + ir_tcl_method (NULL, -1, NULL, tabs, NULL); free (obj); } @@ -3036,7 +3128,7 @@ static int ir_scan_obj_mk (ClientData clientData, Tcl_Interp *interp, tabs[0].obj = obj; tabs[1].tab = NULL; - if (ir_method (interp, 0, NULL, tabs) == TCL_ERROR) + if (ir_tcl_method (interp, 0, NULL, tabs, NULL) == TCL_ERROR) return TCL_ERROR; Tcl_CreateCommand (interp, argv[1], ir_scan_obj_method, (ClientData) obj, ir_scan_obj_delete); @@ -3199,7 +3291,7 @@ static void ir_handleRecords (void *o, Z_Records *zrs, IrTcl_SetObj *setobj, 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); + ir_tcl_grs_mk (oe->u.grs1, &rl->u.dbrec.u.grs1); rl->u.dbrec.buf = NULL; } else @@ -3379,7 +3471,7 @@ static void ir_scanResponse (void *o, Z_ScanResponse *scanrs, /* * ir_select_read: handle incoming packages */ -void ir_select_read (ClientData clientData) +static void ir_select_read (ClientData clientData) { IrTcl_Obj *p = clientData; Z_APDU *apdu; @@ -3400,6 +3492,7 @@ void ir_select_read (ClientData clientData) return; } p->state = IR_TCL_R_Idle; + p->ref_count = 2; #if IRTCL_GENERIC_FILES ir_select_remove_write (p->csFile, p); #else @@ -3408,30 +3501,37 @@ void ir_select_read (ClientData clientData) if (r < 0) { logf (LOG_DEBUG, "cs_rcvconnect error"); + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_CONNECT; - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } - do_disconnect (p, NULL, 2, NULL); + ir_obj_delete (p); return; } - p->state = IR_TCL_R_Idle; if (p->callback) - IrTcl_eval (p->interp, p->callback); - if (p->cs_link && p->request_queue && p->state == IR_TCL_R_Idle) + ir_tcl_eval (p->interp, p->callback); + if (p->ref_count == 2 && p->cs_link && p->request_queue + && p->state == IR_TCL_R_Idle) ir_tcl_send_q (p, p->request_queue, "x"); + ir_obj_delete (p); return; } do { - /* 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); /* read incoming APDU */ - if ((r=cs_get (p->cs_link, &p->buf_in, &p->len_in)) <= 0) + if ((r=cs_get (p->cs_link, &p->buf_in, &p->len_in)) == 1) + { + logf(LOG_DEBUG, "PDU Fraction read"); + return ; + } + /* signal one more use of ir object - callbacks must not + release the ir memory (p pointer) */ + p->ref_count = 2; + if (r <= 0) { logf (LOG_DEBUG, "cs_get failed, code %d", r); #if IRTCL_GENERIC_FILES @@ -3439,21 +3539,16 @@ void ir_select_read (ClientData clientData) #else ir_select_remove (cs_fileno (p->cs_link), p); #endif - do_disconnect (p, NULL, 2, NULL); + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_READ; - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } /* 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; @@ -3463,12 +3558,12 @@ void ir_select_read (ClientData clientData) { logf (LOG_DEBUG, "cs_get failed: %s", odr_errmsg (odr_geterror (p->odr_in))); - do_disconnect (p, NULL, 2, NULL); + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_IN_APDU; p->apduOffset = odr_offset (p->odr_in); - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } /* release ir object now if failback deleted it */ ir_obj_delete (p); @@ -3518,11 +3613,11 @@ void ir_select_read (ClientData clientData) default: logf (LOG_WARN, "Received unknown APDU type (%d)", apdu->which); - do_disconnect (p, NULL, 2, NULL); + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_UNKNOWN_APDU; - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } return; } @@ -3531,9 +3626,9 @@ void ir_select_read (ClientData clientData) p->state = IR_TCL_R_Idle; if (apdu_call) - IrTcl_eval (p->interp, apdu_call); + ir_tcl_eval (p->interp, apdu_call); else if (rq->callback) - IrTcl_eval (p->interp, rq->callback); + ir_tcl_eval (p->interp, rq->callback); free (rq->buf_out); free (rq->callback); free (rq->object_name); @@ -3544,7 +3639,7 @@ void ir_select_read (ClientData clientData) ir_obj_delete (p); return; } - --(p->ref_count); + ir_obj_delete (p); } while (p->cs_link && cs_more (p->cs_link)); if (p->cs_link && p->request_queue && p->state == IR_TCL_R_Idle) ir_tcl_send_q (p, p->request_queue, "x"); @@ -3553,7 +3648,7 @@ void ir_select_read (ClientData clientData) /* * ir_select_write: handle outgoing packages - not yet written. */ -void ir_select_write (ClientData clientData) +static void ir_select_write (ClientData clientData) { IrTcl_Obj *p = clientData; int r; @@ -3565,31 +3660,32 @@ void ir_select_write (ClientData clientData) logf(LOG_DEBUG, "Connect handler"); r = cs_rcvconnect (p->cs_link); if (r == 1) + { + logf (LOG_DEBUG, "cs_rcvconnect returned 1"); return; + } p->state = IR_TCL_R_Idle; - if (r < 0) - { - logf (LOG_DEBUG, "cs_rcvconnect error"); + p->ref_count = 2; #if IRTCL_GENERIC_FILES - ir_select_remove_write (p->csFile, p); + ir_select_remove_write (p->csFile, p); #else - ir_select_remove_write (cs_fileno (p->cs_link), p); + ir_select_remove_write (cs_fileno (p->cs_link), p); #endif + if (r < 0) + { + logf (LOG_DEBUG, "cs_rcvconnect error"); + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_CONNECT; - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } - do_disconnect (p, NULL, 2, NULL); + ir_obj_delete (p); 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); + ir_tcl_eval (p->interp, p->callback); + ir_obj_delete (p); return; } rq = p->request_queue; @@ -3599,18 +3695,20 @@ void ir_select_write (ClientData clientData) if ((r=cs_put (p->cs_link, rq->buf_out, rq->len_out)) < 0) { logf (LOG_DEBUG, "cs_put write fail"); + p->ref_count = 2; + free (rq->buf_out); + rq->buf_out = NULL; + ir_tcl_disconnect (p); if (p->failback) { p->failInfo = IR_TCL_FAIL_WRITE; - IrTcl_eval (p->interp, p->failback); + ir_tcl_eval (p->interp, p->failback); } - free (rq->buf_out); - rq->buf_out = NULL; - do_disconnect (p, NULL, 2, NULL); + ir_obj_delete (p); } else if (r == 0) /* remove select bit */ { - logf(LOG_DEBUG, "Write completed"); + logf (LOG_DEBUG, "Write completed"); p->state = IR_TCL_R_Waiting; #if IRTCL_GENERIC_FILES ir_select_remove_write (p->csFile, p); @@ -3622,6 +3720,14 @@ void ir_select_write (ClientData clientData) } } +static void ir_select_notify (ClientData clientData, int r, int w, int e) +{ + if (r) + ir_select_read (clientData); + if (w) + ir_select_write (clientData); +} + /* ------------------------------------------------------- */ /*