2 * Copyright (c) 1995-1997, Index Data.
3 * See the file LICENSE for details.
4 * Sebastian Hammer, Adam Dickmeiss
6 * $Log: d1_expout.c,v $
7 * Revision 1.7 1997-12-09 16:18:16 adam
8 * Work on EXPLAIN schema. First implementation of sub-schema facility
11 * Revision 1.6 1997/11/24 11:33:56 adam
12 * Using function odr_nullval() instead of global ODR_NULLVAL when
15 * Revision 1.5 1997/11/19 10:30:06 adam
18 * Revision 1.4 1997/11/18 09:51:08 adam
19 * Removed element num_children from data1_node. Minor changes in
22 * Revision 1.3 1997/09/17 12:10:36 adam
25 * Revision 1.2 1995/12/14 16:28:30 quinn
28 * Revision 1.1 1995/12/14 11:09:51 quinn
51 static int is_numeric_tag (ExpHandle *eh, data1_node *c)
53 if (!c || c->which != DATA1N_tag)
55 if (!c->u.tag.element)
57 logf(LOG_WARN, "Tag %s is local", c->u.tag.tag);
60 if (c->u.tag.element->tag->which != DATA1T_numeric)
62 logf(LOG_WARN, "Tag %s is not numeric", c->u.tag.tag);
65 if (eh->select && !c->u.tag.node_selected)
67 return c->u.tag.element->tag->value.numeric;
70 static int is_data_tag (ExpHandle *eh, data1_node *c)
72 if (!c || c->which != DATA1N_data)
74 if (eh->select && !c->u.tag.node_selected)
79 static int *f_integer(ExpHandle *eh, data1_node *c)
85 if (!is_data_tag (eh, c) || c->u.data.len > 63)
87 r = odr_malloc(eh->o, sizeof(*r));
88 sprintf(intbuf, "%.*s", 63, c->u.data.data);
93 static char *f_string(ExpHandle *eh, data1_node *c)
98 if (!is_data_tag (eh, c))
100 r = odr_malloc(eh->o, c->u.data.len+1);
101 memcpy(r, c->u.data.data, c->u.data.len);
102 r[c->u.data.len] = '\0';
106 static bool_t *f_bool(ExpHandle *eh, data1_node *c)
112 if (!is_data_tag (eh, c) || c->u.data.len > 63)
114 tf = odr_malloc (eh->o, sizeof(*tf));
115 sprintf(intbuf, "%.*s", c->u.data.len, c->u.data.data);
120 static Odr_oid *f_oid(ExpHandle *eh, data1_node *c, oid_class oclass)
124 oid_value value_for_this;
127 if (!is_data_tag (eh, c) || c->u.data.len > 63)
129 sprintf(oidstr, "%.*s", c->u.data.len, c->u.data.data);
130 value_for_this = oid_getvalbyname(oidstr);
131 if (value_for_this == VAL_NONE)
132 return NULL; /* fix */
137 ident.oclass = oclass;
138 ident.proto = PROTO_Z3950;
139 ident.value = value_for_this;
141 oid_ent_to_oid (&ident, oid_this);
143 return odr_oiddup (eh->o, oid_this);
146 static Z_IntUnit *f_intunit(ExpHandle *eh, data1_node *c)
152 static Z_HumanString *f_humstring(ExpHandle *eh, data1_node *c)
155 Z_HumanStringUnit *u;
158 if (!is_data_tag (eh, c))
160 r = odr_malloc(eh->o, sizeof(*r));
162 r->strings = odr_malloc(eh->o, sizeof(Z_HumanStringUnit*));
163 r->strings[0] = u = odr_malloc(eh->o, sizeof(*u));
165 u->text = odr_malloc(eh->o, c->u.data.len+1);
166 memcpy(u->text, c->u.data.data, c->u.data.len);
167 u->text[c->u.data.len] = '\0';
171 static Z_CommonInfo *f_commonInfo(ExpHandle *eh, data1_node *n)
173 Z_CommonInfo *res = odr_malloc(eh->o, sizeof(*res));
177 res->dateChanged = 0;
179 res->humanStringLanguage = 0;
182 for (c = n->child; c; c = c->next)
184 switch (is_numeric_tag (eh, c))
186 case 601: res->dateAdded = f_string(eh, c); break;
187 case 602: res->dateChanged = f_string(eh, c); break;
188 case 603: res->expiry = f_string(eh, c); break;
189 case 604: res->humanStringLanguage = f_string(eh, c); break;
195 Z_QueryTypeDetails *f_queryTypeDetails (ExpHandle *eh, data1_node *n)
201 Odr_oid **f_oid_seq (ExpHandle *eh, data1_node *n, int *num, oid_class oclass)
208 for (c = n->child ; c; c = c->next)
210 if (is_numeric_tag (eh, c) != 1000)
216 res = odr_malloc (eh->o, sizeof(*res) * (*num));
217 for (c = n->child, i = 0 ; c; c = c->next)
219 if (is_numeric_tag (eh, c) != 1000)
221 res[i++] = f_oid (eh, c, oclass);
226 char **f_string_seq (ExpHandle *eh, data1_node *n, int *num)
233 for (c = n->child ; c; c = c->next)
235 if (!is_numeric_tag (eh, c) != 1001)
241 res = odr_malloc (eh->o, sizeof(*res) * (*num));
242 for (c = n->child, i = 0 ; c; c = c->next)
244 if (!is_numeric_tag (eh, c) != 1001)
246 res[i++] = f_string (eh, c);
251 char **f_humstring_seq (ExpHandle *eh, data1_node *n, int *num)
258 Z_RpnCapabilities *f_rpnCapabilities (ExpHandle *eh, data1_node *c)
260 Z_RpnCapabilities *res = odr_malloc (eh->o, sizeof(*res));
262 res->num_operators = 0;
263 res->operators = NULL;
264 res->resultSetAsOperandSupported = eh->false_value;
265 res->restrictionOperandSupported = eh->false_value;
266 res->proximity = NULL;
267 /* fix */ /* 550 - 560 */
271 Z_QueryTypeDetails **f_queryTypesSupported (ExpHandle *eh, data1_node *c,
275 Z_QueryTypeDetails **res;
279 for (n = c->child; n; n = n->next)
281 if (is_numeric_tag(eh, n) != 519)
283 /* fix */ /* 518 and 520 */
288 res = odr_malloc (eh->o, *num * sizeof(*res));
290 for (n = c->child; n; n = n->next)
292 if (is_numeric_tag(eh, n) == 519)
294 res[i] = odr_malloc (eh->o, sizeof(**res));
295 res[i]->which = Z_QueryTypeDetails_rpn;
296 res[i]->u.rpn = f_rpnCapabilities (eh, n);
301 /* fix */ /* 518 and 520 */
306 static Z_AccessInfo *f_accessInfo(ExpHandle *eh, data1_node *n)
308 Z_AccessInfo *res = odr_malloc(eh->o, sizeof(*res));
311 res->num_queryTypesSupported = 0;
312 res->queryTypesSupported = 0;
313 res->num_diagnosticsSets = 0;
314 res->diagnosticsSets = 0;
315 res->num_attributeSetIds = 0;
316 res->attributeSetIds = 0;
317 res->num_schemas = 0;
319 res->num_recordSyntaxes = 0;
320 res->recordSyntaxes = 0;
321 res->num_resourceChallenges = 0;
322 res->resourceChallenges = 0;
323 res->restrictedAccess = 0;
325 res->num_variantSets = 0;
326 res->variantSets = 0;
327 res->num_elementSetNames = 0;
328 res->elementSetNames = 0;
329 res->num_unitSystems = 0;
330 res->unitSystems = 0;
332 for (c = n->child; c; c = c->next)
334 switch (is_numeric_tag (eh, c))
337 res->queryTypesSupported =
338 f_queryTypesSupported (eh, c, &res->num_queryTypesSupported);
341 res->diagnosticsSets =
342 f_oid_seq(eh, c, &res->num_diagnosticsSets, CLASS_DIAGSET);
345 res->attributeSetIds =
346 f_oid_seq(eh, c, &res->num_attributeSetIds, CLASS_ATTSET);
350 f_oid_seq(eh, c, &res->num_schemas, CLASS_SCHEMA);
353 res->recordSyntaxes =
354 f_oid_seq (eh, c, &res->num_recordSyntaxes, CLASS_RECSYN);
357 res->resourceChallenges =
358 f_oid_seq (eh, c, &res->num_resourceChallenges, CLASS_RESFORM);
360 case 513: res->restrictedAccess = NULL; break; /* fix */
361 case 514: res->costInfo = NULL; break; /* fix */
364 f_oid_seq (eh, c, &res->num_variantSets, CLASS_VARSET);
367 res->elementSetNames =
368 f_string_seq (eh, c, &res->num_elementSetNames);
371 res->unitSystems = f_string_seq (eh, c, &res->num_unitSystems);
378 static int *f_recordCount(ExpHandle *eh, data1_node *c, int *which)
380 int *r= odr_malloc(eh->o, sizeof(*r));
385 if (!is_numeric_tag (eh, c))
387 if (c->u.tag.element->tag->value.numeric == 210)
388 *wp = Z_Exp_RecordCount_actualNumber;
389 else if (c->u.tag.element->tag->value.numeric == 211)
390 *wp = Z_Exp_RecordCount_approxNumber;
393 if (!c->child || c->child->which != DATA1N_data)
395 sprintf(intbuf, "%.*s", 63, c->child->u.data.data);
400 static Z_ContactInfo *f_contactInfo(ExpHandle *eh, data1_node *n)
406 static Z_DatabaseList *f_databaseList(ExpHandle *eh, data1_node *n)
412 for (c = n->child; c; c = c->next)
414 if (!is_numeric_tag (eh, c) != 102)
421 res = odr_malloc (eh->o, sizeof(*res));
423 res->num_databases = i;
424 res->databases = odr_malloc (eh->o, sizeof(*res->databases) * i);
426 for (c = n->child; c; c = c->next)
428 if (!is_numeric_tag (eh, c) != 102)
430 res->databases[i++] = f_string (eh, c);
435 static Z_TargetInfo *f_targetInfo(ExpHandle *eh, data1_node *n)
437 Z_TargetInfo *res = odr_malloc(eh->o, sizeof(*res));
444 res->namedResultSets = 0;
445 res->multipleDbSearch = 0;
446 res->maxResultSets = 0;
447 res->maxResultSize = 0;
449 res->timeoutInterval = 0;
450 res->welcomeMessage = 0;
451 res->contactInfo = 0;
452 res->description = 0;
453 res->num_nicknames = 0;
456 res->paymentAddr = 0;
458 res->num_dbCombinations = 0;
459 res->dbCombinations = 0;
460 res->num_addresses = 0;
462 res->commonAccessInfo = 0;
464 for (c = n->child; c; c = c->next)
468 if (!is_numeric_tag (eh, c))
470 switch (c->u.tag.element->tag->value.numeric)
472 case 600: res->commonInfo = f_commonInfo(eh, c); break;
473 case 102: res->name = f_string(eh, c); break;
474 case 103: res->recentNews = f_humstring(eh, c); break;
475 case 104: res->icon = NULL; break; /* fix */
476 case 105: res->namedResultSets = f_bool(eh, c); break;
477 case 106: res->multipleDbSearch = f_bool(eh, c); break;
478 case 107: res->maxResultSets = f_integer(eh, c); break;
479 case 108: res->maxResultSize = f_integer(eh, c); break;
480 case 109: res->maxTerms = f_integer(eh, c); break;
481 case 110: res->timeoutInterval = f_intunit(eh, c); break;
482 case 111: res->welcomeMessage = f_humstring(eh, c); break;
483 case 112: res->contactInfo = f_contactInfo(eh, c); break;
484 case 113: res->description = f_humstring(eh, c); break;
486 res->num_nicknames = 0;
487 for (n = c->child; n; n = n->next)
489 if (is_numeric_tag(eh, n) != 102)
491 (res->num_nicknames)++;
493 if (res->num_nicknames)
495 odr_malloc (eh->o, res->num_nicknames
496 * sizeof(*res->nicknames));
497 for (n = c->child; n; n = n->next)
499 if (is_numeric_tag(eh, n) != 102)
501 res->nicknames[i++] = f_string (eh, n);
504 case 115: res->usageRest = f_humstring(eh, c); break;
505 case 116: res->paymentAddr = f_humstring(eh, c); break;
506 case 117: res->hours = f_humstring(eh, c); break;
508 res->num_dbCombinations = 0;
509 for (n = c->child; n; n = n->next)
511 if (!is_numeric_tag(eh, n) != 605)
513 (res->num_dbCombinations)++;
515 if (res->num_dbCombinations)
516 res->dbCombinations =
517 odr_malloc (eh->o, res->num_dbCombinations
518 * sizeof(*res->dbCombinations));
519 for (n = c->child; n; n = n->next)
521 if (!is_numeric_tag(eh, n) != 605)
523 res->dbCombinations[i++] = f_databaseList (eh, n);
526 case 119: res->addresses = 0; break; /* fix */
527 case 500: res->commonAccessInfo = f_accessInfo(eh, c); break;
530 if (!res->namedResultSets)
531 res->namedResultSets = eh->false_value;
532 if (!res->multipleDbSearch)
533 res->multipleDbSearch = eh->false_value;
537 static Z_DatabaseInfo *f_databaseInfo(ExpHandle *eh, data1_node *n)
539 Z_DatabaseInfo *res = odr_malloc(eh->o, sizeof(*res));
544 res->explainDatabase = 0;
545 res->num_nicknames = 0;
550 res->titleString = 0;
551 res->num_keywords = 0;
553 res->description = 0;
554 res->associatedDbs = 0;
556 res->disclaimers = 0;
558 res->recordCount = 0;
559 res->defaultOrder = 0;
560 res->avRecordSize = 0;
561 res->maxRecordSize = 0;
565 res->updateInterval = 0;
567 res->proprietary = 0;
568 res->copyrightText = 0;
569 res->copyrightNotice = 0;
570 res->producerContactInfo = 0;
571 res->supplierContactInfo = 0;
572 res->submissionContactInfo = 0;
575 for (c = n->child; c; c = c->next)
579 switch (is_numeric_tag (eh, c))
581 case 600: res->commonInfo = f_commonInfo(eh, c); break;
582 case 102: res->name = f_string(eh, c); break;
583 case 226: res->explainDatabase = odr_nullval(); break;
585 res->num_nicknames = 0;
586 for (n = c->child; n; n = n->next)
588 if (!is_numeric_tag(eh, n) ||
589 n->u.tag.element->tag->value.numeric != 102)
591 (res->num_nicknames)++;
593 if (res->num_nicknames)
595 odr_malloc (eh->o, res->num_nicknames
596 * sizeof(*res->nicknames));
597 for (n = c->child; n; n = n->next)
599 if (!is_numeric_tag(eh, n) ||
600 n->u.tag.element->tag->value.numeric != 102)
602 res->nicknames[i++] = f_string (eh, n);
605 case 104: res->icon = 0; break; /* fix */
606 case 201: res->userFee = f_bool(eh, c); break;
607 case 202: res->available = f_bool(eh, c); break;
608 case 203: res->titleString = f_humstring(eh, c); break;
610 res->num_keywords = 0;
611 for (n = c->child; n; n = n->next)
613 if (!is_numeric_tag(eh, n) != 1000)
615 (res->num_keywords)++;
617 if (res->num_keywords)
619 odr_malloc (eh->o, res->num_keywords
620 * sizeof(*res->keywords));
621 for (n = c->child; n; n = n->next)
623 if (!is_numeric_tag(eh, n) != 1000)
625 res->keywords[i++] = f_humstring (eh, n);
628 case 113: res->description = f_humstring(eh, c); break;
630 res->associatedDbs = f_databaseList (eh, c);
633 res->subDbs = f_databaseList (eh, c);
635 case 207: res->disclaimers = f_humstring(eh, c); break;
636 case 103: res->news = f_humstring(eh, c); break;
637 case 209: res->recordCount =
638 f_recordCount(eh, c, &res->recordCount_which); break;
639 case 212: res->defaultOrder = f_humstring(eh, c); break;
640 case 213: res->avRecordSize = f_integer(eh, c); break;
641 case 214: res->maxRecordSize = f_integer(eh, c); break;
642 case 215: res->hours = f_humstring(eh, c); break;
643 case 216: res->bestTime = f_humstring(eh, c); break;
644 case 217: res->lastUpdate = f_string(eh, c); break;
645 case 218: res->updateInterval = f_intunit(eh, c); break;
646 case 219: res->coverage = f_humstring(eh, c); break;
647 case 220: res->proprietary = f_bool(eh, c); break;
648 case 221: res->copyrightText = f_humstring(eh, c); break;
649 case 222: res->copyrightNotice = f_humstring(eh, c); break;
650 case 223: res->producerContactInfo = f_contactInfo(eh, c); break;
651 case 224: res->supplierContactInfo = f_contactInfo(eh, c); break;
652 case 225: res->submissionContactInfo = f_contactInfo(eh, c); break;
653 case 500: res->accessInfo = f_accessInfo(eh, c); break;
657 res->userFee = eh->false_value;
659 res->available = eh->true_value;
663 Z_ExplainRecord *data1_nodetoexplain (data1_handle dh, data1_node *n,
667 Z_ExplainRecord *res = odr_malloc(o, sizeof(*res));
672 eh.false_value = odr_malloc(eh.o, sizeof(eh.false_value));
674 eh.true_value = odr_malloc(eh.o, sizeof(eh.true_value));
677 assert(n->which == DATA1N_root);
678 if (strcmp(n->u.root.type, "explain"))
680 logf(LOG_WARN, "Attempt to convert a non-Explain record");
686 logf(LOG_WARN, "Explain record should have one exactly one child");
689 switch (is_numeric_tag (&eh, n))
692 res->which = Z_Explain_targetInfo;
693 if (!(res->u.targetInfo = f_targetInfo(&eh, n)))
697 res->which = Z_Explain_databaseInfo;
698 if (!(res->u.databaseInfo = f_databaseInfo(&eh, n)))
702 logf(LOG_WARN, "Unknown explain category");