27 #include <yaz/yaz-util.h>
28 #include <yaz/marcdisp.h>
34 #define MARCOMP_DEBUG 0
47 int identifier_length;
50 int length_data_entry;
52 int length_implementation;
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);
151 length_implementation = atoi_n(buf+22, 1);
153 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
155 int l = 3 + length_data_entry + length_starting;
156 if (entry_p + l >= record_length)
158 yaz_log(YLOG_WARN,
"MARC: Directory offset %d: end of record.",
164 if (!isdigit(*(
const unsigned char *) (buf + entry_p+l)))
169 yaz_log(YLOG_LOG,
"MARC: Bad directory");
172 entry_p += 3 + length_data_entry + length_starting;
174 end_of_directory = entry_p;
175 if (base_address != entry_p+1)
177 yaz_log(YLOG_WARN,
"MARC: Base address does not follow directory");
179 for (entry_p = 24; entry_p != end_of_directory; )
189 memcpy(tag, buf+entry_p, 3);
199 fprintf(
outf,
"%s ", tag);
201 data_length = atoi_n(buf+entry_p, length_data_entry);
202 entry_p += length_data_entry;
203 data_offset = atoi_n(buf+entry_p, length_starting);
204 entry_p += length_starting;
205 i = data_offset + base_address;
206 end_offset = i+data_length-1;
208 if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
210 yaz_log(YLOG_WARN,
"MARC: Bad offsets in data. Skipping rest");
214 if (memcmp(tag,
"00", 2) && indicator_length)
219 const char *attr[10];
228 for (j = 0; j < indicator_length; j++)
230 char str1[18], str2[2];
231 sprintf (str1,
"ind%d", j+1);
247 indicator_length, 0 , res);
249 for (j = 0; j < indicator_length; j++)
250 fprintf(
outf,
"%c", buf[j+i]);
253 i += indicator_length;
259 const char *attr[10];
271 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
273 if (memcmp (tag,
"00", 2) && identifier_length)
282 for (j = 1; j < identifier_length && j < 9; j++)
283 code[j-1] = buf[i+j];
294 buf+i+1, identifier_length-1,
298 fprintf (
outf,
" $");
299 for (j = 1; j < identifier_length; j++)
300 fprintf(
outf,
"%c", buf[j+i]);
303 i += identifier_length;
305 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
306 buf[i] != ISO2709_FS && i < end_offset)
309 fprintf(
outf,
"%c", buf[i]);
319 fprintf(
outf,
"%c", buf[i]);
329 fprintf (
outf,
"\n");
331 fprintf(
outf,
"-- separator but not at end of field\n");
332 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
333 fprintf(
outf,
"-- no separator at end of field\n");
352 *len = n->
u.
data.len;
354 for (i = 0; i < *len; i++)
361 return n->
u.
data.data + i;
379 for (p = node; p; p = p->
next)
381 if (!yaz_matchstr(p->
u.
tag.tag, name))
392 for (p = pisf; p; p = p->
next)
394 if (!yaz_matchstr(p->
name, name))
405 for (p = psf; p && pisf; p = p->
next)
413 if (strcmp(p->
prefix,
"_"))
415 wrbuf_puts(buf,
" ");
416 wrbuf_puts(buf, p->
prefix);
420 wrbuf_puts(buf, found->
data);
428 if (strcmp(p->
suffix,
"_"))
430 wrbuf_puts(buf, p->
suffix);
431 wrbuf_puts(buf,
" ");
434 yaz_log(YLOG_LOG,
"cat_inline_subfield(): add subfield $%s", found->
name);
455 for (pp = p->
u.
child, found = 0; pp; pp = pp->
next)
457 if (!yaz_matchstr(pisf->name, p->
name))
465 wrbuf_puts(buf,
" (");
467 wrbuf_puts(buf,
") ");
476 if (!pf || !subfield)
485 if (yaz_matchstr(subfield->
u.
tag.tag,
"1"))
487 subfield = subfield->
next;
498 yaz_log(YLOG_WARN,
"inline subfield ($%s): parse error",
504 }
while (psubf && yaz_matchstr(psubf->
u.
tag.tag,
"1"));
508 if (pif && !yaz_matchstr(pif->
name, pf->
name))
522 ind1 = (pif->
ind1[0] ==
' ') ?
'_':pif->
ind1[0];
523 ind2 = (pif->
ind2[0] ==
' ') ?
'_':pif->
ind2[0];
525 if (((pf->
ind1[0] ==
'.') || (ind1 == pf->
ind1[0])) &&
526 ((pf->
ind2[0] ==
'.') || (ind2 == pf->
ind2[0])))
535 wrbuf_puts(buf,
"\n");
540 yaz_log(YLOG_WARN,
"In-line field %s missed -- indicators do not match", pif->
name);
547 yaz_log(YLOG_LOG,
"cat_inline_field(): got buffer {%s}", wrbuf_cstr(buf));
556 for (p = psf; p && subfield; p = p->
next)
566 if (strcmp(p->
prefix,
"_"))
568 wrbuf_puts(buf,
" ");
569 wrbuf_puts(buf, p->
prefix);
578 wrbuf_puts(buf,
get_data(found, &len));
586 if (strcmp(p->
suffix,
"_"))
588 wrbuf_puts(buf, p->
suffix);
589 wrbuf_puts(buf,
" ");
592 yaz_log(YLOG_LOG,
"cat_subfield(): add subfield $%s", found->
u.
tag.tag);
594 subfield = found->
next;
602 if (next == subfield)
612 for (pp = p->
u.
child, found = 0; pp; pp = pp->
next)
614 if (!yaz_matchstr(subfield->u.tag.tag, pp->
name))
622 wrbuf_puts(buf,
" (");
624 wrbuf_puts(buf,
") ");
641 if (yaz_matchstr(field->
u.
tag.tag, pf->
name))
644 subfield = field->
child;
659 wrbuf_puts(buf,
get_data(field, &len));
668 yaz_log(YLOG_LOG,
"cat_field(): got buffer {%s}", wrbuf_cstr(buf));
677 ind1 = (subfield->
u.
tag.tag[0] ==
' ') ?
'_':subfield->
u.
tag.tag[0];
678 ind2 = (subfield->
u.
tag.tag[1] ==
' ') ?
'_':subfield->
u.
tag.tag[1];
681 ((pf->
ind1[0] ==
'.') || (ind1 == pf->
ind1[0])) &&
682 ((pf->
ind2[0] ==
'.') || (ind2 == pf->
ind2[0]))
686 yaz_log(YLOG_WARN,
"Field %s missed -- does not match indicators", field->
u.
tag.tag);
691 subfield = subfield->
child;
699 yaz_log(YLOG_LOG,
"cat_field(): got buffer {%s}", wrbuf_cstr(buf));
711 if (!isspace(*(
unsigned char *)p))
741 yaz_log(YLOG_LOG,
"parse_data1_tree(): statement -{%s}", mc_stmnt);
743 if (!yaz_matchstr(pf->
name,
"ldr"))
747 yaz_log(YLOG_LOG,
"parse_data1_tree(): try LEADER from {%d} to {%d} positions",
763 if (!yaz_matchstr(field->
u.
tag.tag, pf->
name))
768 yaz_log(YLOG_LOG,
"parse_data1_tree(): try field {%s}", field->
u.
tag.tag);
777 for (pb = strtok(pb,
"\n"); pb; pb = strtok(NULL,
"\n"))
837 struct marc_info *p = xmalloc(
sizeof(*p));
845 if (strlen(args) <
sizeof(p->
type))
846 strcpy(p->
type, args);
898 #if IDZEBRA_STATIC_GRS_MARC
899 idzebra_filter_grs_marc