27 #include <yaz/yaz-util.h>
28 #include <yaz/snprintf.h>
29 #include <yaz/marcdisp.h>
35 #define MARCOMP_DEBUG 0
48 int identifier_length;
51 int length_data_entry;
63 while (*buf < '0' || *buf >
'9')
67 yaz_log(YLOG_WARN,
"MARC: Skipping bad byte %d (0x%02X)",
68 *buf & 0xff, *buf & 0xff);
69 for (i = 0; i < 4; i++)
75 record_length = atoi_n(buf, 5);
76 if (record_length < 25)
78 yaz_log(YLOG_WARN,
"MARC record length < 25, is %d", record_length);
83 if (read_bytes < record_length-5)
85 yaz_log(YLOG_WARN,
"Couldn't read whole MARC record");
89 while (buf[record_length-1] != ISO2709_RS)
91 if (record_length >
sizeof(buf)-2)
105 off_t end_offset = cur_offset - 1;
110 absynName = mi->
type;
114 yaz_log(YLOG_WARN,
"cannot read MARC without an abstract syntax");
120 const char *attr[] = {
"xmlns",
"http://www.loc.gov/MARC21/slim", 0};
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';
139 if (marctab && marctab->force_indicator_length >= 0)
140 indicator_length = marctab->force_indicator_length;
142 indicator_length = atoi_n(buf+10, 1);
143 if (marctab && marctab->force_identifier_length >= 0)
144 identifier_length = marctab->force_identifier_length;
146 identifier_length = atoi_n(buf+11, 1);
147 base_address = atoi_n(buf+12, 5);
149 length_data_entry = atoi_n(buf+20, 1);
150 length_starting = atoi_n(buf+21, 1);
152 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
154 int l = 3 + length_data_entry + length_starting;
155 if (entry_p + l >= record_length)
157 yaz_log(YLOG_WARN,
"MARC: Directory offset %d: end of record.",
163 if (!isdigit(*(
const unsigned char *) (buf + entry_p+l)))
168 yaz_log(YLOG_LOG,
"MARC: Bad directory");
171 entry_p += 3 + length_data_entry + length_starting;
173 end_of_directory = entry_p;
174 if (base_address != entry_p+1)
176 yaz_log(YLOG_WARN,
"MARC: Base address does not follow directory");
178 for (entry_p = 24; entry_p != end_of_directory; )
188 memcpy(tag, buf+entry_p, 3);
198 fprintf(
outf,
"%s ", tag);
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;
207 if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
209 yaz_log(YLOG_WARN,
"MARC: Bad offsets in data. Skipping rest");
213 if (memcmp(tag,
"00", 2) && indicator_length)
218 const char *attr[10];
227 for (j = 0; j < indicator_length; j++)
229 char str1[18], str2[2];
230 yaz_snprintf(str1,
sizeof(str1),
"ind%d", j+1);
246 indicator_length, 0 , res);
248 for (j = 0; j < indicator_length; j++)
249 fprintf(
outf,
"%c", buf[j+i]);
252 i += indicator_length;
258 const char *attr[10];
270 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
272 if (memcmp (tag,
"00", 2) && identifier_length)
281 for (j = 1; j < identifier_length && j < 9; j++)
282 code[j-1] = buf[i+j];
293 buf+i+1, identifier_length-1,
297 fprintf (
outf,
" $");
298 for (j = 1; j < identifier_length; j++)
299 fprintf(
outf,
"%c", buf[j+i]);
302 i += identifier_length;
304 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
305 buf[i] != ISO2709_FS && i < end_offset)
308 fprintf(
outf,
"%c", buf[i]);
318 fprintf(
outf,
"%c", buf[i]);
328 fprintf (
outf,
"\n");
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");
351 *len = n->
u.
data.len;
353 for (i = 0; i < *len; i++)
360 return n->
u.
data.data + i;
378 for (p = node; p; p = p->
next)
380 if (!yaz_matchstr(p->
u.
tag.tag, name))
391 for (p = pisf; p; p = p->
next)
393 if (!yaz_matchstr(p->
name, name))
404 for (p = psf; p && pisf; p = p->
next)
412 if (strcmp(p->
prefix,
"_"))
414 wrbuf_puts(buf,
" ");
415 wrbuf_puts(buf, p->
prefix);
419 wrbuf_puts(buf, found->
data);
427 if (strcmp(p->
suffix,
"_"))
429 wrbuf_puts(buf, p->
suffix);
430 wrbuf_puts(buf,
" ");
433 yaz_log(YLOG_LOG,
"cat_inline_subfield(): add subfield $%s", found->
name);
454 for (pp = p->
u.
child, found = 0; pp; pp = pp->
next)
456 if (!yaz_matchstr(pisf->
name, p->
name))
464 wrbuf_puts(buf,
" (");
466 wrbuf_puts(buf,
") ");
475 if (!pf || !subfield)
484 if (yaz_matchstr(subfield->
u.
tag.tag,
"1"))
486 subfield = subfield->
next;
497 yaz_log(YLOG_WARN,
"inline subfield ($%s): parse error",
503 }
while (psubf && yaz_matchstr(psubf->
u.
tag.tag,
"1"));
507 if (pif && !yaz_matchstr(pif->
name, pf->
name))
521 ind1 = (pif->
ind1[0] ==
' ') ?
'_':pif->
ind1[0];
522 ind2 = (pif->
ind2[0] ==
' ') ?
'_':pif->
ind2[0];
524 if (((pf->
ind1[0] ==
'.') || (ind1 == pf->
ind1[0])) &&
525 ((pf->
ind2[0] ==
'.') || (ind2 == pf->
ind2[0])))
534 wrbuf_puts(buf,
"\n");
539 yaz_log(YLOG_WARN,
"In-line field %s missed -- indicators do not match", pif->
name);
546 yaz_log(YLOG_LOG,
"cat_inline_field(): got buffer {%s}", wrbuf_cstr(buf));
555 for (p = psf; p && subfield; p = p->
next)
565 if (strcmp(p->
prefix,
"_"))
567 wrbuf_puts(buf,
" ");
568 wrbuf_puts(buf, p->
prefix);
577 wrbuf_puts(buf,
get_data(found, &len));
585 if (strcmp(p->
suffix,
"_"))
587 wrbuf_puts(buf, p->
suffix);
588 wrbuf_puts(buf,
" ");
591 yaz_log(YLOG_LOG,
"cat_subfield(): add subfield $%s", found->
u.
tag.tag);
593 subfield = found->
next;
601 if (next == subfield)
611 for (pp = p->
u.
child, found = 0; pp; pp = pp->
next)
613 if (!yaz_matchstr(subfield->
u.
tag.tag, pp->
name))
621 wrbuf_puts(buf,
" (");
623 wrbuf_puts(buf,
") ");
640 if (yaz_matchstr(field->
u.
tag.tag, pf->
name))
643 subfield = field->
child;
658 wrbuf_puts(buf,
get_data(field, &len));
667 yaz_log(YLOG_LOG,
"cat_field(): got buffer {%s}", wrbuf_cstr(buf));
676 ind1 = (subfield->
u.
tag.tag[0] ==
' ') ?
'_':subfield->
u.
tag.tag[0];
677 ind2 = (subfield->
u.
tag.tag[1] ==
' ') ?
'_':subfield->
u.
tag.tag[1];
680 ((pf->
ind1[0] ==
'.') || (ind1 == pf->
ind1[0])) &&
681 ((pf->
ind2[0] ==
'.') || (ind2 == pf->
ind2[0]))
685 yaz_log(YLOG_WARN,
"Field %s missed -- does not match indicators", field->
u.
tag.tag);
690 subfield = subfield->
child;
698 yaz_log(YLOG_LOG,
"cat_field(): got buffer {%s}", wrbuf_cstr(buf));
710 if (!isspace(*(
unsigned char *)p))
740 yaz_log(YLOG_LOG,
"parse_data1_tree(): statement -{%s}", mc_stmnt);
742 if (!yaz_matchstr(pf->
name,
"ldr"))
746 yaz_log(YLOG_LOG,
"parse_data1_tree(): try LEADER from {%d} to {%d} positions",
762 if (!yaz_matchstr(field->
u.
tag.tag, pf->
name))
767 yaz_log(YLOG_LOG,
"parse_data1_tree(): try field {%s}", field->
u.
tag.tag);
776 for (pb = strtok(pb,
"\n"); pb; pb = strtok(NULL,
"\n"))
836 struct marc_info *p = xmalloc(
sizeof(*p));
844 if (strlen(args) <
sizeof(p->
type))
845 strcpy(p->
type, args);
897 #if IDZEBRA_STATIC_GRS_MARC
898 idzebra_filter_grs_marc
data1_node * data1_mk_tag(data1_handle dh, NMEM nmem, const char *tag, const char **attr, data1_node *at)
data1_node * data1_mk_root(data1_handle dh, NMEM nmem, const char *name)
void data1_tag_add_attr(data1_handle dh, NMEM nmem, data1_node *res, const char **attr)
data1_element * data1_absyn_getelements(data1_handle dh, data1_node *root)
data1_node * data1_mk_tag_n(data1_handle dh, NMEM nmem, const char *tag, size_t len, const char **attr, data1_node *at)
data1_node * data1_mk_text_n(data1_handle dh, NMEM mem, const char *buf, size_t len, data1_node *parent)
data1_marctab * data1_absyn_getmarctab(data1_handle dh, data1_node *root)
void inline_destroy_field(inline_field *p)
int inline_parse(inline_field *pif, const char *tag, const char *s)
inline_field * inline_mk_field(void)
void mc_destroy_field(mc_field *p)
mc_field * mc_getfield(mc_context *c)
void mc_destroy_context(mc_context *c)
mc_context * mc_mk_context(const char *s)
data1_node * grs_read_marcxml(struct grs_read_info *p)
static ZEBRA_RES config_marc(void *clientData, Res res, const char *args)
static char * get_data(data1_node *n, int *len)
static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl)
static int extract_marc(void *clientData, struct recExtractCtrl *ctrl)
static void * init_marc(Res res, RecType rt)
static struct recType marcxml_type
static void destroy_marc(void *clientData)
static int extract_marcxml(void *clientData, struct recExtractCtrl *ctrl)
data1_node * grs_read_marc(struct grs_read_info *p)
static inline_subfield * lookup_inline_subfield(inline_subfield *pisf, const char *name)
static data1_node * lookup_subfield(data1_node *node, const char *name)
static data1_node * cat_field(struct grs_read_info *p, mc_field *pf, WRBUF buf, data1_node *field)
static data1_node * cat_subfield(mc_subfield *psf, WRBUF buf, data1_node *subfield)
static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt, data1_node *root)
static inline_subfield * cat_inline_subfield(mc_subfield *psf, WRBUF buf, inline_subfield *pisf)
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 data1_node * grs_read_iso2709(struct grs_read_info *p, int marc_xml)
static int is_empty(char *s)
int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
int zebra_grs_extract(void *clientData, struct recExtractCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
off_t(* endf)(struct ZebraRecStream *s, off_t *offset)
set and get of record position
int(* readf)(struct ZebraRecStream *s, char *buf, size_t count)
read function
off_t(* tellf)(struct ZebraRecStream *s)
tell function
struct data1_element * next
struct data1_node * child
union data1_tag::@1 value
struct ZebraRecStream * stream
struct inline_subfield * list
struct inline_subfield * next
struct mc_subfield * list
struct mc_field::@17 interval
struct mc_field * in_line
struct mc_subfield::@15 interval
struct mc_subfield * child
struct mc_subfield * next
short ZEBRA_RES
Common return type for Zebra API.