+ struct yaz_marc_subfield *n = (struct yaz_marc_subfield *)
+ nmem_malloc(mt->nmem, sizeof(*n));
+ n->code_data = nmem_strdupn(mt->nmem, code_data, code_data_len);
+ n->next = 0;
+ /* mark subfield_pp to point to this one, so we append here next */
+ *mt->subfield_pp = n;
+ mt->subfield_pp = &n->next;
+ }
+}
+
+static void check_ascii(yaz_marc_t mt, char *leader, int offset,
+ int ch_default)
+{
+ if (leader[offset] < ' ' || leader[offset] > 127)
+ {
+ yaz_marc_cprintf(mt,
+ "Leader character at offset %d is non-ASCII. "
+ "Setting value to '%c'", offset, ch_default);
+ leader[offset] = ch_default;
+ }
+}
+
+void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
+ int *indicator_length,
+ int *identifier_length,
+ int *base_address,
+ int *length_data_entry,
+ int *length_starting,
+ int *length_implementation)
+{
+ char leader[24];
+
+ memcpy(leader, leader_c, 24);
+
+ check_ascii(mt, leader, 5, 'a');
+ check_ascii(mt, leader, 6, 'a');
+ check_ascii(mt, leader, 7, 'a');
+ check_ascii(mt, leader, 8, '#');
+ check_ascii(mt, leader, 9, '#');
+ if (!atoi_n_check(leader+10, 1, indicator_length) || *indicator_length == 0)
+ {
+ yaz_marc_cprintf(mt, "Indicator length at offset 10 should"
+ " hold a number 1-9. Assuming 2");
+ leader[10] = '2';
+ *indicator_length = 2;
+ }
+ if (!atoi_n_check(leader+11, 1, identifier_length) || *identifier_length == 0)
+ {
+ yaz_marc_cprintf(mt, "Identifier length at offset 11 should "
+ " hold a number 1-9. Assuming 2");
+ leader[11] = '2';
+ *identifier_length = 2;
+ }
+ if (!atoi_n_check(leader+12, 5, base_address))
+ {
+ yaz_marc_cprintf(mt, "Base address at offsets 12..16 should"
+ " hold a number. Assuming 0");
+ *base_address = 0;
+ }
+ check_ascii(mt, leader, 17, '#');
+ check_ascii(mt, leader, 18, '#');
+ check_ascii(mt, leader, 19, '#');
+ if (!atoi_n_check(leader+20, 1, length_data_entry) ||
+ *length_data_entry < 3)
+ {
+ yaz_marc_cprintf(mt, "Length data entry at offset 20 should"
+ " hold a number 3-9. Assuming 4");
+ *length_data_entry = 4;
+ leader[20] = '4';
+ }
+ if (!atoi_n_check(leader+21, 1, length_starting) || *length_starting < 4)
+ {
+ yaz_marc_cprintf(mt, "Length starting at offset 21 should"
+ " hold a number 4-9. Assuming 5");
+ *length_starting = 5;
+ leader[21] = '5';
+ }
+ if (!atoi_n_check(leader+22, 1, length_implementation))
+ {
+ yaz_marc_cprintf(mt, "Length implementation at offset 22 should"
+ " hold a number. Assuming 0");
+ *length_implementation = 0;
+ leader[22] = '0';
+ }
+ check_ascii(mt, leader, 23, '0');
+
+ if (mt->debug)
+ {
+ yaz_marc_cprintf(mt, "Indicator length %5d", *indicator_length);
+ yaz_marc_cprintf(mt, "Identifier length %5d", *identifier_length);
+ yaz_marc_cprintf(mt, "Base address %5d", *base_address);
+ yaz_marc_cprintf(mt, "Length data entry %5d", *length_data_entry);
+ yaz_marc_cprintf(mt, "Length starting %5d", *length_starting);
+ yaz_marc_cprintf(mt, "Length implementation %5d", *length_implementation);
+ }
+ yaz_marc_add_leader(mt, leader, 24);
+}
+
+void yaz_marc_subfield_str(yaz_marc_t mt, const char *s)
+{
+ strncpy(mt->subfield_str, s, sizeof(mt->subfield_str)-1);
+ mt->subfield_str[sizeof(mt->subfield_str)-1] = '\0';
+}
+
+void yaz_marc_endline_str(yaz_marc_t mt, const char *s)
+{
+ strncpy(mt->endline_str, s, sizeof(mt->endline_str)-1);
+ mt->endline_str[sizeof(mt->endline_str)-1] = '\0';
+}
+
+/* try to guess how many bytes the identifier really is! */
+static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
+{
+ if (mt->iconv_cd)
+ {
+ size_t i;
+ for (i = 1; i<5; i++)
+ {
+ char outbuf[12];
+ size_t outbytesleft = sizeof(outbuf);
+ char *outp = outbuf;
+ const char *inp = buf;
+
+ size_t inbytesleft = i;
+ size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
+ &outp, &outbytesleft);
+ yaz_iconv(mt->iconv_cd, 0, 0, &outp, &outbytesleft);
+ if (r != (size_t) (-1))
+ return i; /* got a complete sequence */
+ }
+ return 1; /* giving up */