IDZEBRA 2.2.8
mod_grs_marc.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4Zebra is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20#if HAVE_CONFIG_H
21#include <config.h>
22#endif
23#include <stdio.h>
24#include <ctype.h>
25#include <assert.h>
26
27#include <yaz/yaz-util.h>
28#include <yaz/snprintf.h>
29#include <yaz/marcdisp.h>
30#include <idzebra/recgrs.h>
31#include "marcomp.h"
32#include "inline.h"
33
34#define MARC_DEBUG 0
35#define MARCOMP_DEBUG 0
36
37struct marc_info {
38 char type[256];
39};
40
41static data1_node *grs_read_iso2709(struct grs_read_info *p, int marc_xml)
42{
43 struct marc_info *mi = (struct marc_info*) p->clientData;
44 char buf[100000];
45 int entry_p;
46 int record_length;
47 int indicator_length;
48 int identifier_length;
49 int base_address;
50 int end_of_directory;
51 int length_data_entry;
52 int length_starting;
53 int read_bytes;
54#if MARC_DEBUG
55 FILE *outf = stdout;
56#endif
57 data1_node *res_root, *res_top;
58 char *absynName;
59 data1_marctab *marctab;
60
61 if (p->stream->readf(p->stream, buf, 5) != 5)
62 return NULL;
63 while (*buf < '0' || *buf > '9')
64 {
65 int i;
66
67 yaz_log(YLOG_WARN, "MARC: Skipping bad byte %d (0x%02X)",
68 *buf & 0xff, *buf & 0xff);
69 for (i = 0; i < 4; i++)
70 buf[i] = buf[i+1];
71
72 if (p->stream->readf(p->stream, buf+4, 1) != 1)
73 return NULL;
74 }
75 record_length = atoi_n(buf, 5);
76 if (record_length < 25)
77 {
78 yaz_log(YLOG_WARN, "MARC record length < 25, is %d", record_length);
79 return NULL;
80 }
81
82 read_bytes = p->stream->readf(p->stream, buf+5, record_length-5);
83 if (read_bytes < record_length-5)
84 {
85 yaz_log(YLOG_WARN, "Couldn't read whole MARC record");
86 return NULL;
87 }
88 /* skip until we meet a record separator */
89 while (buf[record_length-1] != ISO2709_RS)
90 {
91 if (record_length > sizeof(buf)-2)
92 break;
93 read_bytes = p->stream->readf(p->stream, buf+record_length, 1);
94 if (read_bytes != 1)
95 break;
96 record_length++;
97 }
98 /* read one byte ahead to see if there is more ... */
99 read_bytes = p->stream->readf(p->stream, buf+record_length, 1);
100 if (read_bytes == 1)
101 {
102 off_t cur_offset = p->stream->tellf(p->stream);
103 if (p->stream->endf)
104 {
105 off_t end_offset = cur_offset - 1;
106 p->stream->endf(p->stream, &end_offset);
107 }
108 }
109
110 absynName = mi->type;
111 res_root = data1_mk_root(p->dh, p->mem, absynName);
112 if (!res_root)
113 {
114 yaz_log(YLOG_WARN, "cannot read MARC without an abstract syntax");
115 return 0;
116 }
117 if (marc_xml)
118 {
119 data1_node *lead;
120 const char *attr[] = { "xmlns", "http://www.loc.gov/MARC21/slim", 0};
121
122 res_top = data1_mk_tag(p->dh, p->mem, "record", attr, res_root);
123
124 lead = data1_mk_tag(p->dh, p->mem, "leader", 0, res_top);
125 data1_mk_text_n(p->dh, p->mem, buf, 24, lead);
126 }
127 else
128 res_top = data1_mk_tag(p->dh, p->mem, absynName, 0, res_root);
129
130 if ((marctab = data1_absyn_getmarctab(p->dh, res_root)))
131 {
132 memcpy(marctab->leader, buf, 24);
133 memcpy(marctab->implementation_codes, buf+6, 4);
134 marctab->implementation_codes[4] = '\0';
135 memcpy(marctab->user_systems, buf+17, 3);
136 marctab->user_systems[3] = '\0';
137 }
138
139 if (marctab && marctab->force_indicator_length >= 0)
140 indicator_length = marctab->force_indicator_length;
141 else
142 indicator_length = atoi_n(buf+10, 1);
143 if (marctab && marctab->force_identifier_length >= 0)
144 identifier_length = marctab->force_identifier_length;
145 else
146 identifier_length = atoi_n(buf+11, 1);
147 base_address = atoi_n(buf+12, 5);
148
149 length_data_entry = atoi_n(buf+20, 1);
150 length_starting = atoi_n(buf+21, 1);
151
152 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
153 {
154 int l = 3 + length_data_entry + length_starting;
155 if (entry_p + l >= record_length)
156 {
157 yaz_log(YLOG_WARN, "MARC: Directory offset %d: end of record.",
158 entry_p);
159 return 0;
160 }
161 /* check for digits in length info */
162 while (--l >= 3)
163 if (!isdigit(*(const unsigned char *) (buf + entry_p+l)))
164 break;
165 if (l >= 3)
166 {
167 /* not all digits, so stop directory scan */
168 yaz_log(YLOG_LOG, "MARC: Bad directory");
169 break;
170 }
171 entry_p += 3 + length_data_entry + length_starting;
172 }
173 end_of_directory = entry_p;
174 if (base_address != entry_p+1)
175 {
176 yaz_log(YLOG_WARN, "MARC: Base address does not follow directory");
177 }
178 for (entry_p = 24; entry_p != end_of_directory; )
179 {
180 int data_length;
181 int data_offset;
182 int end_offset;
183 int i, i0;
184 char tag[4];
185 data1_node *res;
186 data1_node *parent = res_top;
187
188 memcpy(tag, buf+entry_p, 3);
189 entry_p += 3;
190 tag[3] = '\0';
191
192 if (marc_xml)
193 res = parent;
194 else
195 res = data1_mk_tag_n(p->dh, p->mem, tag, 3, 0 /* attr */, parent);
196
197#if MARC_DEBUG
198 fprintf(outf, "%s ", tag);
199#endif
200 data_length = atoi_n(buf+entry_p, length_data_entry);
201 entry_p += length_data_entry;
202 data_offset = atoi_n(buf+entry_p, length_starting);
203 entry_p += length_starting;
204 i = data_offset + base_address;
205 end_offset = i+data_length-1;
206
207 if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
208 {
209 yaz_log(YLOG_WARN, "MARC: Bad offsets in data. Skipping rest");
210 break;
211 }
212
213 if (memcmp(tag, "00", 2) && indicator_length)
214 {
215 /* generate indicator node */
216 if (marc_xml)
217 {
218 const char *attr[10];
219 int j;
220
221 attr[0] = "tag";
222 attr[1] = tag;
223 attr[2] = 0;
224
225 res = data1_mk_tag(p->dh, p->mem, "datafield", attr, res);
226
227 for (j = 0; j < indicator_length; j++)
228 {
229 char str1[18], str2[2];
230 yaz_snprintf(str1, sizeof(str1), "ind%d", j+1);
231 str2[0] = buf[i+j];
232 str2[1] = '\0';
233
234 attr[0] = str1;
235 attr[1] = str2;
236
237 data1_tag_add_attr(p->dh, p->mem, res, attr);
238 }
239 }
240 else
241 {
242#if MARC_DEBUG
243 int j;
244#endif
245 res = data1_mk_tag_n(p->dh, p->mem, buf+i,
246 indicator_length, 0 /* attr */, res);
247#if MARC_DEBUG
248 for (j = 0; j < indicator_length; j++)
249 fprintf(outf, "%c", buf[j+i]);
250#endif
251 }
252 i += indicator_length;
253 }
254 else
255 {
256 if (marc_xml)
257 {
258 const char *attr[10];
259
260 attr[0] = "tag";
261 attr[1] = tag;
262 attr[2] = 0;
263
264 res = data1_mk_tag(p->dh, p->mem, "controlfield", attr, res);
265 }
266 }
267 parent = res;
268 /* traverse sub fields */
269 i0 = i;
270 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
271 {
272 if (memcmp (tag, "00", 2) && identifier_length)
273 {
274 int j;
275 data1_node *res;
276 if (marc_xml)
277 {
278 const char *attr[3];
279 char code[10];
280
281 for (j = 1; j < identifier_length && j < 9; j++)
282 code[j-1] = buf[i+j];
283 code[j-1] = 0;
284 attr[0] = "code";
285 attr[1] = code;
286 attr[2] = 0;
287 res = data1_mk_tag(p->dh, p->mem, "subfield",
288 attr, parent);
289 }
290 else
291 {
292 res = data1_mk_tag_n(p->dh, p->mem,
293 buf+i+1, identifier_length-1,
294 0 /* attr */, parent);
295 }
296#if MARC_DEBUG
297 fprintf (outf, " $");
298 for (j = 1; j < identifier_length; j++)
299 fprintf(outf, "%c", buf[j+i]);
300 fprintf(outf, " ");
301#endif
302 i += identifier_length;
303 i0 = i;
304 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
305 buf[i] != ISO2709_FS && i < end_offset)
306 {
307#if MARC_DEBUG
308 fprintf(outf, "%c", buf[i]);
309#endif
310 i++;
311 }
312 data1_mk_text_n(p->dh, p->mem, buf + i0, i - i0, res);
313 i0 = i;
314 }
315 else
316 {
317#if MARC_DEBUG
318 fprintf(outf, "%c", buf[i]);
319#endif
320 i++;
321 }
322 }
323 if (i > i0)
324 {
325 data1_mk_text_n(p->dh, p->mem, buf + i0, i - i0, parent);
326 }
327#if MARC_DEBUG
328 fprintf (outf, "\n");
329 if (i < end_offset)
330 fprintf(outf, "-- separator but not at end of field\n");
331 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
332 fprintf(outf, "-- no separator at end of field\n");
333#endif
334 }
335 return res_root;
336}
337
338/*
339 * Locate some data under this node. This routine should handle variants
340 * prettily.
341 */
342static char *get_data(data1_node *n, int *len)
343{
344 char *r;
345
346 while (n)
347 {
348 if (n->which == DATA1N_data)
349 {
350 int i;
351 *len = n->u.data.len;
352
353 for (i = 0; i < *len; i++)
354 if (!d1_isspace(n->u.data.data[i]))
355 break;
356 while (*len && d1_isspace(n->u.data.data[*len - 1]))
357 (*len)--;
358 *len = *len - i;
359 if (*len > 0)
360 return n->u.data.data + i;
361 }
362 if (n->which == DATA1N_tag)
363 n = n->child;
364 else if (n->which == DATA1N_data)
365 n = n->next;
366 else
367 break;
368 }
369 r = "";
370 *len = strlen(r);
371 return r;
372}
373
374static data1_node *lookup_subfield(data1_node *node, const char *name)
375{
376 data1_node *p;
377
378 for (p = node; p; p = p->next)
379 {
380 if (!yaz_matchstr(p->u.tag.tag, name))
381 return p;
382 }
383 return 0;
384}
385
387 const char *name)
388{
390
391 for (p = pisf; p; p = p->next)
392 {
393 if (!yaz_matchstr(p->name, name))
394 return p;
395 }
396 return 0;
397}
398
400 inline_subfield *pisf)
401{
402 mc_subfield *p;
403
404 for (p = psf; p && pisf; p = p->next)
405 {
406 if (p->which == MC_SF)
407 {
409
410 if (found)
411 {
412 if (strcmp(p->prefix, "_"))
413 {
414 wrbuf_puts(buf, " ");
415 wrbuf_puts(buf, p->prefix);
416 }
417 if (p->interval.start == -1)
418 {
419 wrbuf_puts(buf, found->data);
420 }
421 else
422 {
423 wrbuf_write(buf, found->data+p->interval.start,
424 p->interval.end-p->interval.start);
425 wrbuf_puts(buf, "");
426 }
427 if (strcmp(p->suffix, "_"))
428 {
429 wrbuf_puts(buf, p->suffix);
430 wrbuf_puts(buf, " ");
431 }
432#if MARCOMP_DEBUG
433 yaz_log(YLOG_LOG, "cat_inline_subfield(): add subfield $%s", found->name);
434#endif
435 pisf = found->next;
436 }
437 }
438 else if (p->which == MC_SFVARIANT)
439 {
440 inline_subfield *next;
441
442 do {
443 next = cat_inline_subfield(p->u.child, buf, pisf);
444 if (next == pisf)
445 break;
446 pisf = next;
447 } while (pisf);
448 }
449 else if (p->which == MC_SFGROUP)
450 {
451 mc_subfield *pp;
452 int found;
453
454 for (pp = p->u.child, found = 0; pp; pp = pp->next)
455 {
456 if (!yaz_matchstr(pisf->name, p->name))
457 {
458 found = 1;
459 break;
460 }
461 }
462 if (found)
463 {
464 wrbuf_puts(buf, " (");
465 pisf = cat_inline_subfield(p->u.child, buf, pisf);
466 wrbuf_puts(buf, ") ");
467 }
468 }
469 }
470 return pisf;
471}
472
473static void cat_inline_field(mc_field *pf, WRBUF buf, data1_node *subfield)
474{
475 if (!pf || !subfield)
476 return;
477
478 for (;subfield;)
479 {
480 int len;
481 inline_field *pif=NULL;
482 data1_node *psubf;
483
484 if (yaz_matchstr(subfield->u.tag.tag, "1"))
485 {
486 subfield = subfield->next;
487 continue;
488 }
489
490 psubf = subfield;
491 pif = inline_mk_field();
492 do
493 {
494 int i;
495 if ((i=inline_parse(pif, psubf->u.tag.tag, get_data(psubf, &len)))<0)
496 {
497 yaz_log(YLOG_WARN, "inline subfield ($%s): parse error",
498 psubf->u.tag.tag);
500 return;
501 }
502 psubf = psubf->next;
503 } while (psubf && yaz_matchstr(psubf->u.tag.tag, "1"));
504
505 subfield = psubf;
506
507 if (pif && !yaz_matchstr(pif->name, pf->name))
508 {
509 if (!pf->list && pif->list)
510 {
511 wrbuf_puts(buf, pif->list->data);
512 }
513 else
514 {
515 int ind1, ind2;
516
517 /*
518 check indicators
519 */
520
521 ind1 = (pif->ind1[0] == ' ') ? '_':pif->ind1[0];
522 ind2 = (pif->ind2[0] == ' ') ? '_':pif->ind2[0];
523
524 if (((pf->ind1[0] == '.') || (ind1 == pf->ind1[0])) &&
525 ((pf->ind2[0] == '.') || (ind2 == pf->ind2[0])))
526 {
527 cat_inline_subfield(pf->list, buf, pif->list);
528
529 /*
530 add separator for inline fields
531 */
532 if (wrbuf_len(buf))
533 {
534 wrbuf_puts(buf, "\n");
535 }
536 }
537 else
538 {
539 yaz_log(YLOG_WARN, "In-line field %s missed -- indicators do not match", pif->name);
540 }
541 }
542 }
544 }
545#if MARCOMP_DEBUG
546 yaz_log(YLOG_LOG, "cat_inline_field(): got buffer {%s}", wrbuf_cstr(buf));
547#endif
548}
549
550static data1_node *cat_subfield(mc_subfield *psf, WRBUF buf,
551 data1_node *subfield)
552{
553 mc_subfield *p;
554
555 for (p = psf; p && subfield; p = p->next)
556 {
557 if (p->which == MC_SF)
558 {
559 data1_node *found = lookup_subfield(subfield, p->name);
560
561 if (found)
562 {
563 int len;
564
565 if (strcmp(p->prefix, "_"))
566 {
567 wrbuf_puts(buf, " ");
568 wrbuf_puts(buf, p->prefix);
569 }
570
571 if (p->u.in_line)
572 {
573 cat_inline_field(p->u.in_line, buf, found);
574 }
575 else if (p->interval.start == -1)
576 {
577 wrbuf_puts(buf, get_data(found, &len));
578 }
579 else
580 {
581 wrbuf_write(buf, get_data(found, &len)+p->interval.start,
582 p->interval.end-p->interval.start);
583 wrbuf_puts(buf, "");
584 }
585 if (strcmp(p->suffix, "_"))
586 {
587 wrbuf_puts(buf, p->suffix);
588 wrbuf_puts(buf, " ");
589 }
590#if MARCOMP_DEBUG
591 yaz_log(YLOG_LOG, "cat_subfield(): add subfield $%s", found->u.tag.tag);
592#endif
593 subfield = found->next;
594 }
595 }
596 else if (p->which == MC_SFVARIANT)
597 {
598 data1_node *next;
599 do {
600 next = cat_subfield(p->u.child, buf, subfield);
601 if (next == subfield)
602 break;
603 subfield = next;
604 } while (subfield);
605 }
606 else if (p->which == MC_SFGROUP)
607 {
608 mc_subfield *pp;
609 int found;
610
611 for (pp = p->u.child, found = 0; pp; pp = pp->next)
612 {
613 if (!yaz_matchstr(subfield->u.tag.tag, pp->name))
614 {
615 found = 1;
616 break;
617 }
618 }
619 if (found)
620 {
621 wrbuf_puts(buf, " (");
622 subfield = cat_subfield(p->u.child, buf, subfield);
623 wrbuf_puts(buf, ") ");
624 }
625 }
626 }
627 return subfield;
628}
629
631 WRBUF buf, data1_node *field)
632{
633 data1_node *subfield;
634 int ind1, ind2;
635
636 if (!pf || !field)
637 return 0;
638
639
640 if (yaz_matchstr(field->u.tag.tag, pf->name))
641 return field->next;
642
643 subfield = field->child;
644
645 if (!subfield)
646 return field->next;
647
648 /*
649 check subfield without indicators
650 */
651
652 if (!pf->list && subfield->which == DATA1N_data)
653 {
654 int len;
655
656 if (pf->interval.start == -1)
657 {
658 wrbuf_puts(buf, get_data(field, &len));
659 }
660 else
661 {
662 wrbuf_write(buf, get_data(field, &len)+pf->interval.start,
663 pf->interval.end-pf->interval.start);
664 wrbuf_puts(buf, "");
665 }
666#if MARCOMP_DEBUG
667 yaz_log(YLOG_LOG, "cat_field(): got buffer {%s}", wrbuf_cstr(buf));
668#endif
669 return field->next;
670 }
671
672 /*
673 check indicators
674 */
675
676 ind1 = (subfield->u.tag.tag[0] == ' ') ? '_':subfield->u.tag.tag[0];
677 ind2 = (subfield->u.tag.tag[1] == ' ') ? '_':subfield->u.tag.tag[1];
678
679 if (!(
680 ((pf->ind1[0] == '.') || (ind1 == pf->ind1[0])) &&
681 ((pf->ind2[0] == '.') || (ind2 == pf->ind2[0]))
682 ))
683 {
684#if MARCOMP_DEBUG
685 yaz_log(YLOG_WARN, "Field %s missed -- does not match indicators", field->u.tag.tag);
686#endif
687 return field->next;
688 }
689
690 subfield = subfield->child;
691
692 if (!subfield)
693 return field->next;
694
695 cat_subfield(pf->list, buf, subfield);
696
697#if MARCOMP_DEBUG
698 yaz_log(YLOG_LOG, "cat_field(): got buffer {%s}", wrbuf_cstr(buf));
699#endif
700
701 return field->next;
702}
703
704static int is_empty(char *s)
705{
706 char *p = s;
707
708 for (p = s; *p; p++)
709 {
710 if (!isspace(*(unsigned char *)p))
711 return 0;
712 }
713 return 1;
714}
715
716static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt,
717 data1_node *root)
718{
719 data1_marctab *marctab = data1_absyn_getmarctab(p->dh, root);
720 data1_node *top = root->child;
721 data1_node *field;
722 mc_context *c;
723 mc_field *pf;
724 WRBUF buf;
725
726 c = mc_mk_context(mc_stmnt+3);
727
728 if (!c)
729 return;
730
731 pf = mc_getfield(c);
732
733 if (!pf)
734 {
736 return;
737 }
738 buf = wrbuf_alloc();
739#if MARCOMP_DEBUG
740 yaz_log(YLOG_LOG, "parse_data1_tree(): statement -{%s}", mc_stmnt);
741#endif
742 if (!yaz_matchstr(pf->name, "ldr"))
743 {
744 data1_node *new;
745#if MARCOMP_DEBUG
746 yaz_log(YLOG_LOG,"parse_data1_tree(): try LEADER from {%d} to {%d} positions",
747 pf->interval.start, pf->interval.end);
748#endif
749 if (marctab)
750 {
751 new = data1_mk_tag_n(p->dh, p->mem, mc_stmnt, strlen(mc_stmnt), 0, top);
752 data1_mk_text_n(p->dh, p->mem, marctab->leader+pf->interval.start,
753 pf->interval.end-pf->interval.start+1, new);
754 }
755 }
756 else
757 {
758 field=top->child;
759
760 while (field)
761 {
762 if (!yaz_matchstr(field->u.tag.tag, pf->name))
763 {
764 data1_node *new;
765 char *pb;
766#if MARCOMP_DEBUG
767 yaz_log(YLOG_LOG, "parse_data1_tree(): try field {%s}", field->u.tag.tag);
768#endif
769 wrbuf_rewind(buf);
770 wrbuf_puts(buf, "");
771
772 field = cat_field(p, pf, buf, field);
773
774 wrbuf_cstr(buf);
775 pb = wrbuf_buf(buf);
776 for (pb = strtok(pb, "\n"); pb; pb = strtok(NULL, "\n"))
777 {
778 if (!is_empty(pb))
779 {
780 new = data1_mk_tag_n(p->dh, p->mem, mc_stmnt, strlen(mc_stmnt), 0, top);
781 data1_mk_text_n(p->dh, p->mem, pb, strlen(pb), new);
782 }
783 }
784 }
785 else
786 {
787 field = field->next;
788 }
789 }
790 }
793 wrbuf_destroy(buf);
794}
795
797{
798 data1_node *root = grs_read_iso2709(p, 1);
799 data1_element *e;
800
801 if (!root)
802 return 0;
803
804 for (e = data1_absyn_getelements(p->dh, root); e; e=e->next)
805 {
806 data1_tag *tag = e->tag;
807
808 if (tag && tag->which == DATA1T_string &&
809 !yaz_matchstr(tag->value.string, "mc?"))
810 parse_data1_tree(p, tag->value.string, root);
811 }
812 return root;
813}
814
816{
817 data1_node *root = grs_read_iso2709(p, 0);
818 data1_element *e;
819
820 if (!root)
821 return 0;
822
823 for (e = data1_absyn_getelements(p->dh, root); e; e=e->next)
824 {
825 data1_tag *tag = e->tag;
826
827 if (tag && tag->which == DATA1T_string &&
828 !yaz_matchstr(tag->value.string, "mc?"))
829 parse_data1_tree(p, tag->value.string, root);
830 }
831 return root;
832}
833
834static void *init_marc(Res res, RecType rt)
835{
836 struct marc_info *p = xmalloc(sizeof(*p));
837 strcpy(p->type, "");
838 return p;
839}
840
841static ZEBRA_RES config_marc(void *clientData, Res res, const char *args)
842{
843 struct marc_info *p = (struct marc_info*) clientData;
844 if (strlen(args) < sizeof(p->type))
845 strcpy(p->type, args);
846 return ZEBRA_OK;
847}
848
849static void destroy_marc(void *clientData)
850{
851 struct marc_info *p = (struct marc_info*) clientData;
852 xfree (p);
853}
854
855
856static int extract_marc(void *clientData, struct recExtractCtrl *ctrl)
857{
858 return zebra_grs_extract(clientData, ctrl, grs_read_marc);
859}
860
861static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl)
862{
863 return zebra_grs_retrieve(clientData, ctrl, grs_read_marc);
864}
865
866static struct recType marc_type = {
867 0,
868 "grs.marc",
869 init_marc,
874};
875
876static int extract_marcxml(void *clientData, struct recExtractCtrl *ctrl)
877{
878 return zebra_grs_extract(clientData, ctrl, grs_read_marcxml);
879}
880
881static int retrieve_marcxml(void *clientData, struct recRetrieveCtrl *ctrl)
882{
883 return zebra_grs_retrieve(clientData, ctrl, grs_read_marcxml);
884}
885
886static struct recType marcxml_type = {
887 0,
888 "grs.marcxml",
889 init_marc,
894};
895
897#if IDZEBRA_STATIC_GRS_MARC
898idzebra_filter_grs_marc
899#else
901#endif
902
903[] = {
904 &marc_type,
906 0,
907};
908
909/*
910 * Local variables:
911 * c-basic-offset: 4
912 * c-file-style: "Stroustrup"
913 * indent-tabs-mode: nil
914 * End:
915 * vim: shiftwidth=4 tabstop=8 expandtab
916 */
917
void data1_tag_add_attr(data1_handle dh, NMEM nmem, data1_node *res, const char **attr)
Definition d1_read.c:286
data1_node * data1_mk_root(data1_handle dh, NMEM nmem, const char *name)
Definition d1_read.c:174
#define DATA1T_string
Definition data1.h:205
data1_element * data1_absyn_getelements(data1_handle dh, data1_node *root)
Definition d1_absyn.c:668
data1_node * data1_mk_tag_n(data1_handle dh, NMEM nmem, const char *tag, size_t len, const char **attr, data1_node *at)
Definition d1_read.c:259
#define DATA1N_tag
Definition data1.h:276
data1_node * data1_mk_text_n(data1_handle dh, NMEM mem, const char *buf, size_t len, data1_node *parent)
Definition d1_read.c:331
#define DATA1N_data
Definition data1.h:278
#define d1_isspace(c)
Definition data1.h:31
data1_node * data1_mk_tag(data1_handle dh, NMEM nmem, const char *tag, const char **attr, data1_node *at)
Definition d1_read.c:295
data1_marctab * data1_absyn_getmarctab(data1_handle dh, data1_node *root)
Definition d1_absyn.c:661
void inline_destroy_field(inline_field *p)
Definition inline.c:46
int inline_parse(inline_field *pif, const char *tag, const char *s)
Definition inline.c:97
inline_field * inline_mk_field(void)
Definition inline.c:30
void mc_destroy_field(mc_field *p)
Definition marcomp.c:204
mc_field * mc_getfield(mc_context *c)
Definition marcomp.c:214
mc_context * mc_mk_context(const char *s)
Definition marcomp.c:66
void mc_destroy_context(mc_context *c)
Definition marcomp.c:86
#define MC_SFGROUP
Definition marcomp.h:38
#define MC_SF
Definition marcomp.h:37
#define MC_SFVARIANT
Definition marcomp.h:39
static inline_subfield * cat_inline_subfield(mc_subfield *psf, WRBUF buf, inline_subfield *pisf)
RecType idzebra_filter[]
static ZEBRA_RES config_marc(void *clientData, Res res, const char *args)
static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl)
static int extract_marc(void *clientData, struct recExtractCtrl *ctrl)
static struct recType marcxml_type
static void destroy_marc(void *clientData)
static data1_node * cat_subfield(mc_subfield *psf, WRBUF buf, data1_node *subfield)
static inline_subfield * lookup_inline_subfield(inline_subfield *pisf, const char *name)
static int extract_marcxml(void *clientData, struct recExtractCtrl *ctrl)
static data1_node * lookup_subfield(data1_node *node, const char *name)
data1_node * grs_read_marc(struct grs_read_info *p)
static data1_node * grs_read_iso2709(struct grs_read_info *p, int marc_xml)
static char * get_data(data1_node *n, int *len)
static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt, data1_node *root)
data1_node * grs_read_marcxml(struct grs_read_info *p)
static void * init_marc(Res res, RecType rt)
static data1_node * cat_field(struct grs_read_info *p, mc_field *pf, WRBUF buf, data1_node *field)
static void cat_inline_field(mc_field *pf, WRBUF buf, data1_node *subfield)
static int retrieve_marcxml(void *clientData, struct recRetrieveCtrl *ctrl)
static struct recType marc_type
static int is_empty(char *s)
static FILE * outf
Definition readfile.c:38
int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
Definition recgrs.c:1072
int zebra_grs_extract(void *clientData, struct recExtractCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
Definition recgrs.c:936
off_t(* endf)(struct ZebraRecStream *s, off_t *offset)
set and get of record position
Definition recctrl.h:81
int(* readf)(struct ZebraRecStream *s, char *buf, size_t count)
read function
Definition recctrl.h:75
off_t(* tellf)(struct ZebraRecStream *s)
tell function
Definition recctrl.h:79
data1_tag * tag
Definition data1.h:245
struct data1_element * next
Definition data1.h:249
int force_indicator_length
Definition data1.h:153
char implementation_codes[5]
Definition data1.h:143
char leader[24]
Definition data1.h:155
char user_systems[4]
Definition data1.h:146
int force_identifier_length
Definition data1.h:154
struct data1_node * child
Definition data1.h:341
char * tag
Definition data1.h:296
char * data
Definition data1.h:307
struct data1_node * next
Definition data1.h:340
union data1_node::@2 u
int which
Definition data1.h:285
int which
Definition data1.h:206
union data1_tag::@1 value
char * string
Definition data1.h:210
data1_handle dh
Definition recgrs.h:31
struct ZebraRecStream * stream
Definition recgrs.h:28
void * clientData
Definition recgrs.h:29
struct inline_subfield * list
Definition inline.h:34
char * name
Definition inline.h:31
char * ind1
Definition inline.h:32
char * ind2
Definition inline.h:33
char * data
Definition inline.h:39
char * name
Definition inline.h:38
struct inline_subfield * next
Definition inline.h:40
char type[256]
char * ind1
Definition marcomp.h:56
struct mc_subfield * list
Definition marcomp.h:62
int start
Definition marcomp.h:59
char * ind2
Definition marcomp.h:57
int end
Definition marcomp.h:60
char * name
Definition marcomp.h:55
struct mc_field::@17 interval
struct mc_field * in_line
Definition marcomp.h:40
struct mc_subfield::@15 interval
char * prefix
Definition marcomp.h:29
union mc_subfield::@16 u
struct mc_subfield * child
Definition marcomp.h:41
int which
Definition marcomp.h:35
char * name
Definition marcomp.h:28
char * suffix
Definition marcomp.h:30
int start
Definition marcomp.h:32
struct mc_subfield * next
Definition marcomp.h:43
record extract for indexing
Definition recctrl.h:101
#define ZEBRA_OK
Definition util.h:82
short ZEBRA_RES
Common return type for Zebra API.
Definition util.h:80