+ wrbuf_iconv_reset(wr, mt->iconv_cd);
+}
+
+static int marc_exec_leader(const char *leader_spec, char *leader,
+ size_t size);
+
+
+static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt)
+{
+ struct yaz_marc_node *n = (struct yaz_marc_node *)
+ nmem_malloc(mt->nmem, sizeof(*n));
+ n->next = 0;
+ *mt->nodes_pp = n;
+ mt->nodes_pp = &n->next;
+ return n;
+}
+
+#if YAZ_HAVE_XML2
+void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
+ const xmlNode *ptr_data)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_CONTROLFIELD;
+ n->u.controlfield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
+ n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
+}
+#endif
+
+
+void yaz_marc_add_comment(yaz_marc_t mt, char *comment)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_COMMENT;
+ n->u.comment = nmem_strdup(mt->nmem, comment);
+}
+
+void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+
+ va_start(ap, fmt);
+ yaz_vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ yaz_marc_add_comment(mt, buf);
+ va_end (ap);
+}
+
+int yaz_marc_get_debug(yaz_marc_t mt)
+{
+ return mt->debug;
+}
+
+void yaz_marc_add_leader(yaz_marc_t mt, const char *leader, size_t leader_len)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_LEADER;
+ n->u.leader = nmem_strdupn(mt->nmem, leader, leader_len);
+ marc_exec_leader(mt->leader_spec, n->u.leader, leader_len);
+}
+
+void yaz_marc_add_controlfield(yaz_marc_t mt, const char *tag,
+ const char *data, size_t data_len)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_CONTROLFIELD;
+ n->u.controlfield.tag = nmem_strdup(mt->nmem, tag);
+ n->u.controlfield.data = nmem_strdupn(mt->nmem, data, data_len);
+ if (mt->debug)
+ {
+ size_t i;
+ char msg[80];
+
+ sprintf(msg, "controlfield:");
+ for (i = 0; i < 16 && i < data_len; i++)
+ sprintf(msg + strlen(msg), " %02X", data[i] & 0xff);
+ if (i < data_len)
+ sprintf(msg + strlen(msg), " ..");
+ yaz_marc_add_comment(mt, msg);
+ }
+}
+
+void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
+ const char *indicator, size_t indicator_len)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_DATAFIELD;
+ n->u.datafield.tag = nmem_strdup(mt->nmem, tag);
+ n->u.datafield.indicator =
+ nmem_strdupn(mt->nmem, indicator, indicator_len);
+ n->u.datafield.subfields = 0;
+
+ /* make subfield_pp the current (last one) */
+ mt->subfield_pp = &n->u.datafield.subfields;
+}
+
+#if YAZ_HAVE_XML2
+void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
+ const char *indicator, size_t indicator_len)
+{
+ struct yaz_marc_node *n = yaz_marc_add_node(mt);
+ n->which = YAZ_MARC_DATAFIELD;
+ n->u.datafield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
+ n->u.datafield.indicator =
+ nmem_strdupn(mt->nmem, indicator, indicator_len);
+ n->u.datafield.subfields = 0;
+
+ /* make subfield_pp the current (last one) */
+ mt->subfield_pp = &n->u.datafield.subfields;
+}
+#endif
+
+void yaz_marc_add_subfield(yaz_marc_t mt,
+ const char *code_data, size_t code_data_len)
+{
+ if (mt->debug)
+ {
+ size_t i;
+ char msg[80];
+
+ sprintf(msg, "subfield:");
+ for (i = 0; i < 16 && i < code_data_len; i++)
+ sprintf(msg + strlen(msg), " %02X", code_data[i] & 0xff);
+ if (i < code_data_len)
+ sprintf(msg + strlen(msg), " ..");
+ yaz_marc_add_comment(mt, msg);
+ }
+
+ if (mt->subfield_pp)
+ {
+ 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;
+ }
+}
+
+int atoi_n_check(const char *buf, int size, int *val)
+{
+ int i;
+ for (i = 0; i < size; i++)
+ if (!isdigit(i[(const unsigned char *) buf]))
+ return 0;
+ *val = atoi_n(buf, size);
+ return 1;
+}