2 * Copyright (C) 1995-2006, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.39 2006-12-15 19:28:47 adam Exp $
10 * \brief Implements MARC conversion utilities
25 #include <yaz/marcdisp.h>
26 #include <yaz/wrbuf.h>
27 #include <yaz/yaz-util.h>
28 #include <yaz/nmem_xml.h>
31 #include <libxml/parser.h>
32 #include <libxml/tree.h>
35 /** \brief node types for yaz_marc_node */
36 enum YAZ_MARC_NODE_TYPE
39 YAZ_MARC_CONTROLFIELD,
44 /** \brief represets a data field */
45 struct yaz_marc_datafield {
48 struct yaz_marc_subfield *subfields;
51 /** \brief represents a control field */
52 struct yaz_marc_controlfield {
57 /** \brief a comment node */
58 struct yaz_marc_comment {
62 /** \brief MARC node */
63 struct yaz_marc_node {
64 enum YAZ_MARC_NODE_TYPE which;
66 struct yaz_marc_datafield datafield;
67 struct yaz_marc_controlfield controlfield;
71 struct yaz_marc_node *next;
74 /** \brief represents a subfield */
75 struct yaz_marc_subfield {
77 struct yaz_marc_subfield *next;
80 /** \brief the internals of a yaz_marc_t handle */
90 struct yaz_marc_node *nodes;
91 struct yaz_marc_node **nodes_pp;
92 struct yaz_marc_subfield **subfield_pp;
95 yaz_marc_t yaz_marc_create(void)
97 yaz_marc_t mt = (yaz_marc_t) xmalloc(sizeof(*mt));
98 mt->xml = YAZ_MARC_LINE;
100 mt->m_wr = wrbuf_alloc();
103 strcpy(mt->subfield_str, " $");
104 strcpy(mt->endline_str, "\n");
106 mt->nmem = nmem_create();
111 void yaz_marc_destroy(yaz_marc_t mt)
115 nmem_destroy(mt->nmem);
116 wrbuf_free(mt->m_wr, 1);
117 xfree(mt->leader_spec);
121 NMEM yaz_marc_get_nmem(yaz_marc_t mt)
126 static int marc_exec_leader(const char *leader_spec, char *leader,
130 static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt)
132 struct yaz_marc_node *n = nmem_malloc(mt->nmem, sizeof(*n));
135 mt->nodes_pp = &n->next;
140 void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
141 const xmlNode *ptr_data)
143 struct yaz_marc_node *n = yaz_marc_add_node(mt);
144 n->which = YAZ_MARC_CONTROLFIELD;
145 n->u.controlfield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
146 n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
151 void yaz_marc_add_comment(yaz_marc_t mt, char *comment)
153 struct yaz_marc_node *n = yaz_marc_add_node(mt);
154 n->which = YAZ_MARC_COMMENT;
155 n->u.comment = nmem_strdup(mt->nmem, comment);
158 void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...)
165 _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
169 vsnprintf(buf, sizeof(buf), fmt, ap);
171 vsprintf(buf, fmt, ap);
175 yaz_marc_add_comment(mt, buf);
179 int yaz_marc_get_debug(yaz_marc_t mt)
184 void yaz_marc_add_leader(yaz_marc_t mt, const char *leader, size_t leader_len)
186 struct yaz_marc_node *n = yaz_marc_add_node(mt);
187 n->which = YAZ_MARC_LEADER;
188 n->u.leader = nmem_strdupn(mt->nmem, leader, leader_len);
189 marc_exec_leader(mt->leader_spec, n->u.leader, leader_len);
192 void yaz_marc_add_controlfield(yaz_marc_t mt, const char *tag,
193 const char *data, size_t data_len)
195 struct yaz_marc_node *n = yaz_marc_add_node(mt);
196 n->which = YAZ_MARC_CONTROLFIELD;
197 n->u.controlfield.tag = nmem_strdup(mt->nmem, tag);
198 n->u.controlfield.data = nmem_strdupn(mt->nmem, data, data_len);
204 sprintf(msg, "controlfield:");
205 for (i = 0; i < 16 && i < data_len; i++)
206 sprintf(msg + strlen(msg), " %02X", data[i] & 0xff);
208 sprintf(msg + strlen(msg), " ..");
209 yaz_marc_add_comment(mt, msg);
213 void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
214 const char *indicator, size_t indicator_len)
216 struct yaz_marc_node *n = yaz_marc_add_node(mt);
217 n->which = YAZ_MARC_DATAFIELD;
218 n->u.datafield.tag = nmem_strdup(mt->nmem, tag);
219 n->u.datafield.indicator =
220 nmem_strdupn(mt->nmem, indicator, indicator_len);
221 n->u.datafield.subfields = 0;
223 /* make subfield_pp the current (last one) */
224 mt->subfield_pp = &n->u.datafield.subfields;
228 void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
229 const char *indicator, size_t indicator_len)
231 struct yaz_marc_node *n = yaz_marc_add_node(mt);
232 n->which = YAZ_MARC_DATAFIELD;
233 n->u.datafield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
234 n->u.datafield.indicator =
235 nmem_strdupn(mt->nmem, indicator, indicator_len);
236 n->u.datafield.subfields = 0;
238 /* make subfield_pp the current (last one) */
239 mt->subfield_pp = &n->u.datafield.subfields;
243 void yaz_marc_add_subfield(yaz_marc_t mt,
244 const char *code_data, size_t code_data_len)
251 sprintf(msg, "subfield:");
252 for (i = 0; i < 16 && i < code_data_len; i++)
253 sprintf(msg + strlen(msg), " %02X", code_data[i] & 0xff);
254 if (i < code_data_len)
255 sprintf(msg + strlen(msg), " ..");
256 yaz_marc_add_comment(mt, msg);
261 struct yaz_marc_subfield *n = nmem_malloc(mt->nmem, sizeof(*n));
262 n->code_data = nmem_strdupn(mt->nmem, code_data, code_data_len);
264 /* mark subfield_pp to point to this one, so we append here next */
265 *mt->subfield_pp = n;
266 mt->subfield_pp = &n->next;
270 int atoi_n_check(const char *buf, int size, int *val)
273 for (i = 0; i < size; i++)
274 if (!isdigit(i[(const unsigned char *) buf]))
276 *val = atoi_n(buf, size);
280 void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
281 int *indicator_length,
282 int *identifier_length,
284 int *length_data_entry,
285 int *length_starting,
286 int *length_implementation)
290 memcpy(leader, leader_c, 24);
292 if (!atoi_n_check(leader+10, 1, indicator_length))
295 "Indicator length at offset 10 should hold a digit."
298 *indicator_length = 2;
300 if (!atoi_n_check(leader+11, 1, identifier_length))
303 "Identifier length at offset 11 should hold a digit."
306 *identifier_length = 2;
308 if (!atoi_n_check(leader+12, 5, base_address))
311 "Base address at offsets 12..16 should hold a number."
315 if (!atoi_n_check(leader+20, 1, length_data_entry))
318 "Length data entry at offset 20 should hold a digit."
320 *length_data_entry = 4;
323 if (!atoi_n_check(leader+21, 1, length_starting))
326 "Length starting at offset 21 should hold a digit."
328 *length_starting = 5;
331 if (!atoi_n_check(leader+22, 1, length_implementation))
334 "Length implementation at offset 22 should hold a digit."
336 *length_implementation = 0;
342 yaz_marc_cprintf(mt, "Indicator length %5d", *indicator_length);
343 yaz_marc_cprintf(mt, "Identifier length %5d", *identifier_length);
344 yaz_marc_cprintf(mt, "Base address %5d", *base_address);
345 yaz_marc_cprintf(mt, "Length data entry %5d", *length_data_entry);
346 yaz_marc_cprintf(mt, "Length starting %5d", *length_starting);
347 yaz_marc_cprintf(mt, "Length implementation %5d", *length_implementation);
349 yaz_marc_add_leader(mt, leader, 24);
352 void yaz_marc_subfield_str(yaz_marc_t mt, const char *s)
354 strncpy(mt->subfield_str, s, sizeof(mt->subfield_str)-1);
355 mt->subfield_str[sizeof(mt->subfield_str)-1] = '\0';
358 void yaz_marc_endline_str(yaz_marc_t mt, const char *s)
360 strncpy(mt->endline_str, s, sizeof(mt->endline_str)-1);
361 mt->endline_str[sizeof(mt->endline_str)-1] = '\0';
364 /* try to guess how many bytes the identifier really is! */
365 static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
370 for (i = 1; i<5; i++)
373 size_t outbytesleft = sizeof(outbuf);
375 const char *inp = buf;
377 size_t inbytesleft = i;
378 size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
379 &outp, &outbytesleft);
380 if (r != (size_t) (-1))
381 return i; /* got a complete sequence */
383 return 1; /* giving up */
385 return 1; /* we don't know */
388 void yaz_marc_reset(yaz_marc_t mt)
390 nmem_reset(mt->nmem);
392 mt->nodes_pp = &mt->nodes;
396 int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr)
398 struct yaz_marc_node *n;
399 int identifier_length;
400 const char *leader = 0;
402 for (n = mt->nodes; n; n = n->next)
403 if (n->which == YAZ_MARC_LEADER)
405 leader = n->u.leader;
411 if (!atoi_n_check(leader+11, 1, &identifier_length))
414 for (n = mt->nodes; n; n = n->next)
418 case YAZ_MARC_COMMENT:
419 wrbuf_iconv_write(wr, mt->iconv_cd,
420 n->u.comment, strlen(n->u.comment));
421 wrbuf_puts(wr, ")\n");
431 int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
433 struct yaz_marc_node *n;
434 int identifier_length;
435 const char *leader = 0;
437 for (n = mt->nodes; n; n = n->next)
438 if (n->which == YAZ_MARC_LEADER)
440 leader = n->u.leader;
446 if (!atoi_n_check(leader+11, 1, &identifier_length))
449 for (n = mt->nodes; n; n = n->next)
451 struct yaz_marc_subfield *s;
454 case YAZ_MARC_DATAFIELD:
455 wrbuf_printf(wr, "%s %s", n->u.datafield.tag,
456 n->u.datafield.indicator);
457 for (s = n->u.datafield.subfields; s; s = s->next)
459 /* if identifier length is 2 (most MARCs),
460 the code is a single character .. However we've
461 seen multibyte codes, so see how big it really is */
462 size_t using_code_len =
463 (identifier_length != 2) ? identifier_length - 1
465 cdata_one_character(mt, s->code_data);
467 wrbuf_puts (wr, mt->subfield_str);
468 wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data,
470 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
471 wrbuf_iconv_puts(wr, mt->iconv_cd,
472 s->code_data + using_code_len);
473 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
476 wrbuf_puts (wr, mt->endline_str);
478 case YAZ_MARC_CONTROLFIELD:
479 wrbuf_printf(wr, "%s", n->u.controlfield.tag);
480 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
481 wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data);
482 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
484 wrbuf_puts (wr, mt->endline_str);
486 case YAZ_MARC_COMMENT:
488 wrbuf_iconv_write(wr, mt->iconv_cd,
489 n->u.comment, strlen(n->u.comment));
490 wrbuf_puts(wr, ")\n");
492 case YAZ_MARC_LEADER:
493 wrbuf_printf(wr, "%s\n", n->u.leader);
496 wrbuf_puts(wr, "\n");
500 int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
505 return yaz_marc_write_line(mt, wr);
506 case YAZ_MARC_MARCXML:
507 return yaz_marc_write_marcxml(mt, wr);
508 case YAZ_MARC_XCHANGE:
509 return yaz_marc_write_marcxchange(mt, wr, 0, 0); /* no format, type */
510 case YAZ_MARC_ISO2709:
511 return yaz_marc_write_iso2709(mt, wr);
513 return yaz_marc_write_check(mt, wr);
518 /** \brief common MARC XML/Xchange writer
520 \param wr WRBUF output
521 \param ns XMLNS for the elements
522 \param format record format (e.g. "MARC21")
523 \param type record type (e.g. "Bibliographic")
525 static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
530 struct yaz_marc_node *n;
531 int identifier_length;
532 const char *leader = 0;
534 for (n = mt->nodes; n; n = n->next)
535 if (n->which == YAZ_MARC_LEADER)
537 leader = n->u.leader;
543 if (!atoi_n_check(leader+11, 1, &identifier_length))
546 wrbuf_printf(wr, "<record xmlns=\"%s\"", ns);
548 wrbuf_printf(wr, " format=\"%.80s\"", format);
550 wrbuf_printf(wr, " type=\"%.80s\"", type);
551 wrbuf_printf(wr, ">\n");
552 for (n = mt->nodes; n; n = n->next)
554 struct yaz_marc_subfield *s;
558 case YAZ_MARC_DATAFIELD:
559 wrbuf_printf(wr, " <datafield tag=\"");
560 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
561 strlen(n->u.datafield.tag));
562 wrbuf_printf(wr, "\"");
563 if (n->u.datafield.indicator)
566 for (i = 0; n->u.datafield.indicator[i]; i++)
568 wrbuf_printf(wr, " ind%d=\"", i+1);
569 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
570 n->u.datafield.indicator+i, 1);
571 wrbuf_iconv_puts(wr, mt->iconv_cd, "\"");
574 wrbuf_printf(wr, ">\n");
575 for (s = n->u.datafield.subfields; s; s = s->next)
577 /* if identifier length is 2 (most MARCs),
578 the code is a single character .. However we've
579 seen multibyte codes, so see how big it really is */
580 size_t using_code_len =
581 (identifier_length != 2) ? identifier_length - 1
583 cdata_one_character(mt, s->code_data);
585 wrbuf_iconv_puts(wr, mt->iconv_cd, " <subfield code=\"");
586 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
587 s->code_data, using_code_len);
588 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
589 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
590 s->code_data + using_code_len,
591 strlen(s->code_data + using_code_len));
592 wrbuf_iconv_puts(wr, mt->iconv_cd, "</subfield>");
593 wrbuf_puts(wr, "\n");
595 wrbuf_printf(wr, " </datafield>\n");
597 case YAZ_MARC_CONTROLFIELD:
598 wrbuf_printf(wr, " <controlfield tag=\"");
599 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
600 strlen(n->u.controlfield.tag));
601 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
602 wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data);
603 wrbuf_iconv_puts(wr, mt->iconv_cd, "</controlfield>");
604 wrbuf_puts(wr, "\n");
606 case YAZ_MARC_COMMENT:
607 wrbuf_printf(wr, "<!-- ");
608 wrbuf_puts(wr, n->u.comment);
609 wrbuf_printf(wr, " -->\n");
611 case YAZ_MARC_LEADER:
612 wrbuf_printf(wr, " <leader>");
613 wrbuf_iconv_write_cdata(wr,
614 0 /* no charset conversion for leader */,
615 n->u.leader, strlen(n->u.leader));
616 wrbuf_printf(wr, "</leader>\n");
619 wrbuf_puts(wr, "</record>\n");
623 int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
625 if (!mt->leader_spec)
626 yaz_marc_modify_leader(mt, 9, "a");
627 return yaz_marc_write_marcxml_ns(mt, wr, "http://www.loc.gov/MARC21/slim",
631 int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
635 return yaz_marc_write_marcxml_ns(mt, wr,
636 "http://www.bs.dk/standards/MarcXchange",
640 int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
642 struct yaz_marc_node *n;
643 int indicator_length;
644 int identifier_length;
645 int length_data_entry;
647 int length_implementation;
649 const char *leader = 0;
650 WRBUF wr_dir, wr_head, wr_data_tmp;
653 for (n = mt->nodes; n; n = n->next)
654 if (n->which == YAZ_MARC_LEADER)
655 leader = n->u.leader;
659 if (!atoi_n_check(leader+10, 1, &indicator_length))
661 if (!atoi_n_check(leader+11, 1, &identifier_length))
663 if (!atoi_n_check(leader+20, 1, &length_data_entry))
665 if (!atoi_n_check(leader+21, 1, &length_starting))
667 if (!atoi_n_check(leader+22, 1, &length_implementation))
670 wr_data_tmp = wrbuf_alloc();
671 wr_dir = wrbuf_alloc();
672 for (n = mt->nodes; n; n = n->next)
675 struct yaz_marc_subfield *s;
679 case YAZ_MARC_DATAFIELD:
680 wrbuf_printf(wr_dir, "%.3s", n->u.datafield.tag);
681 data_length += indicator_length;
682 wrbuf_rewind(wr_data_tmp);
683 for (s = n->u.datafield.subfields; s; s = s->next)
685 /* write dummy IDFS + content */
686 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
687 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, s->code_data);
689 /* write dummy FS (makes MARC-8 to become ASCII) */
690 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
691 data_length += wrbuf_len(wr_data_tmp);
693 case YAZ_MARC_CONTROLFIELD:
694 wrbuf_printf(wr_dir, "%.3s", n->u.controlfield.tag);
696 wrbuf_rewind(wr_data_tmp);
697 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd,
698 n->u.controlfield.data);
699 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');/* field sep */
700 data_length += wrbuf_len(wr_data_tmp);
702 case YAZ_MARC_COMMENT:
704 case YAZ_MARC_LEADER:
709 wrbuf_printf(wr_dir, "%0*d", length_data_entry, data_length);
710 wrbuf_printf(wr_dir, "%0*d", length_starting, data_offset);
711 data_offset += data_length;
714 /* mark end of directory */
715 wrbuf_putc(wr_dir, ISO2709_FS);
717 /* base address of data (comes after leader+directory) */
718 base_address = 24 + wrbuf_len(wr_dir);
720 wr_head = wrbuf_alloc();
722 /* write record length */
723 wrbuf_printf(wr_head, "%05d", base_address + data_offset + 1);
724 /* from "original" leader */
725 wrbuf_write(wr_head, leader+5, 7);
726 /* base address of data */
727 wrbuf_printf(wr_head, "%05d", base_address);
728 /* from "original" leader */
729 wrbuf_write(wr_head, leader+17, 7);
731 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
732 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
733 wrbuf_free(wr_head, 1);
734 wrbuf_free(wr_dir, 1);
735 wrbuf_free(wr_data_tmp, 1);
737 for (n = mt->nodes; n; n = n->next)
739 struct yaz_marc_subfield *s;
743 case YAZ_MARC_DATAFIELD:
744 wrbuf_printf(wr, "%.*s", indicator_length,
745 n->u.datafield.indicator);
746 for (s = n->u.datafield.subfields; s; s = s->next)
748 wrbuf_putc(wr, ISO2709_IDFS);
749 wrbuf_iconv_puts(wr, mt->iconv_cd, s->code_data);
750 /* write dummy blank - makes MARC-8 to become ASCII */
751 wrbuf_iconv_putchar(wr, mt->iconv_cd, ' ');
754 wrbuf_putc(wr, ISO2709_FS);
756 case YAZ_MARC_CONTROLFIELD:
757 wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data);
758 /* write dummy blank - makes MARC-8 to become ASCII */
759 wrbuf_iconv_putchar(wr, mt->iconv_cd, ' ');
761 wrbuf_putc(wr, ISO2709_FS);
763 case YAZ_MARC_COMMENT:
765 case YAZ_MARC_LEADER:
769 wrbuf_printf(wr, "%c", ISO2709_RS);
774 int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
776 int s, r = yaz_marc_read_iso2709(mt, buf, bsize);
779 s = yaz_marc_write_mode(mt, wr); /* returns 0 for OK, -1 otherwise */
781 return -1; /* error */
782 return r; /* OK, return length > 0 */
785 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
786 char **result, int *rsize)
790 wrbuf_rewind(mt->m_wr);
791 r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
793 *result = wrbuf_buf(mt->m_wr);
795 *rsize = wrbuf_len(mt->m_wr);
799 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
805 void yaz_marc_debug(yaz_marc_t mt, int level)
811 void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
816 void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str)
818 struct yaz_marc_node *n;
820 for (n = mt->nodes; n; n = n->next)
821 if (n->which == YAZ_MARC_LEADER)
823 leader = n->u.leader;
824 memcpy(leader+off, str, strlen(str));
830 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
832 yaz_marc_t mt = yaz_marc_create();
837 r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr);
838 yaz_marc_destroy(mt);
843 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
845 return yaz_marc_decode(buf, wr, debug, bsize, 0);
849 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
851 yaz_marc_t mt = yaz_marc_create();
855 r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr);
859 fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf);
860 yaz_marc_destroy(mt);
865 int marc_display_ex (const char *buf, FILE *outf, int debug)
867 return marc_display_exl (buf, outf, debug, -1);
871 int marc_display (const char *buf, FILE *outf)
873 return marc_display_ex (buf, outf, 0);
876 int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
878 xfree(mt->leader_spec);
882 char dummy_leader[24];
883 if (marc_exec_leader(leader_spec, dummy_leader, 24))
885 mt->leader_spec = xstrdup(leader_spec);
890 static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
892 const char *cp = leader_spec;
897 int no_read = 0, no = 0;
899 no = sscanf(cp, "%d=%20[^,]%n", &pos, val, &no_read);
900 if (no < 2 || no_read < 3)
902 if (pos < 0 || pos >= size)
907 const char *vp = strchr(val+1, '\'');
913 if (len + pos > size)
915 memcpy(leader + pos, val+1, len);
917 else if (*val >= '0' && *val <= '9')
933 int yaz_marc_decode_formatstr(const char *arg)
936 if (!strcmp(arg, "marc"))
937 mode = YAZ_MARC_ISO2709;
938 if (!strcmp(arg, "marcxml"))
939 mode = YAZ_MARC_MARCXML;
940 if (!strcmp(arg, "marcxchange"))
941 mode = YAZ_MARC_XCHANGE;
942 if (!strcmp(arg, "line"))
943 mode = YAZ_MARC_LINE;
950 * indent-tabs-mode: nil
952 * vim: shiftwidth=4 tabstop=8 expandtab