Пример #1
0
Файл: xml.c Проект: imp/slist
static void
buf_add_node_attr(char **b, tgt_node_t *x)
{
	char		*buf;
	tgt_node_t	*n;
	int		len;

	/* ---- null byte and starting '<' character ---- */
	len = strlen(x->x_name) + 2;
	if ((buf = malloc(len)) == NULL)
		return;
	(void) snprintf(buf, len, "<%s", x->x_name);
	buf_add_str(b, buf);
	free(buf);

	for (n = x->x_attr; n; n = n->x_sibling) {
		len = strlen(n->x_name) + strlen(n->x_value) + 5;
		if ((buf = malloc(len)) == NULL)
			return;
		(void) snprintf(buf, len, " %s='%s'", n->x_name, n->x_value);
		buf_add_str(b, buf);
		free(buf);
	}
	buf_add_str(b, ">");
}
Пример #2
0
inline void crypt(ErlNifEnv* env, struct buf *rbuf, unsigned char *data, int len)
{
  int i;

  for (i = 0; i < len; i++) {
    switch (data[i]) {
    case '&':
      buf_add_str(env, rbuf, "&amp;", 5);
      break;
    case '<':
      buf_add_str(env, rbuf, "&lt;", 4);
      break;
    case '>':
      buf_add_str(env, rbuf, "&gt;", 4);
      break;
    case '"':
      buf_add_str(env, rbuf, "&quot;", 6);
      break;
    case '\'':
      buf_add_str(env, rbuf, "&apos;", 6);
      break;
    default:
      buf_add_char(env, rbuf, data[i]);
      break;
    };
  };
}
Пример #3
0
static int make_attrs(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM attrs)
{
  ErlNifBinary name, data;
  ERL_NIF_TERM head, tail;
  const ERL_NIF_TERM *tuple;
  int arity, ret = 1;
  
  while (enif_get_list_cell(env, attrs, &head, &tail)) {
    if (enif_get_tuple(env, head, &arity, &tuple)) {
      if (arity == 2) {
	if (enif_inspect_iolist_as_binary(env, tuple[0], &name) &&
	    enif_inspect_iolist_as_binary(env, tuple[1], &data)) {
	  buf_add_char(env, rbuf, ' ');
	  buf_add_str(env, rbuf, (char *)name.data, name.size);
	  buf_add_str(env, rbuf, "='", 2);
	  crypt(env, rbuf, data.data, data.size);
	  buf_add_char(env, rbuf, '\'');
	  attrs = tail;
	} else {
	  ret = 0;
	  break;
	};
      } else {
	ret = 0;
	break;
      };
    } else {
      ret = 0;
      break;
    };
  };
  
  return ret;
}
Пример #4
0
static void print_horizontal_tab_title(struct view *v, int idx)
{
	int skip = v->tt_width - v->tt_truncated_width;
	const char *filename = buffer_filename(v->buffer);
	char buf[16];

	if (skip > 0) {
		filename += u_skip_chars(filename, &skip);
	}

	snprintf(buf, sizeof(buf), "%c%d%s",
		obuf.x == 0 && idx > 0 ? '<' : ' ',
		idx + 1,
		buffer_modified(v->buffer) ? "+" : ":");

	if (v == v->window->view)
		set_builtin_color(BC_ACTIVETAB);
	else
		set_builtin_color(BC_INACTIVETAB);
	buf_add_str(buf);
	buf_add_str(filename);
	if (obuf.x == obuf.width - 1 && idx < v->window->views.count - 1)
		buf_put_char('>');
	else
		buf_put_char(' ');
}
Пример #5
0
static void print_vertical_tab_title(struct view *v, int idx, int width)
{
	const char *orig_filename = buffer_filename(v->buffer);
	const char *filename = orig_filename;
	int max = options.tab_bar_max_components;
	char buf[16];
	int skip;

	snprintf(buf, sizeof(buf), "%2d%s", idx + 1, buffer_modified(v->buffer) ? "+" : " ");
	if (max) {
		int i, count = 1;

		for (i = 0; filename[i]; i++) {
			if (filename[i] == '/')
				count++;
		}
		// ignore first slash because it does not separate components
		if (filename[0] == '/')
			count--;

		if (count > max) {
			// skip possible first slash
			for (i = 1; ; i++) {
				if (filename[i] == '/' && --count == max) {
					i++;
					break;
				}
			}
			filename += i;
		}
	} else {
		skip = strlen(buf) + u_str_width(filename) - width + 1;
		if (skip > 0)
			filename += u_skip_chars(filename, &skip);
	}
	if (filename != orig_filename) {
		// filename was shortened. add "<<" symbol
		long i = strlen(buf);
		u_set_char(buf, &i, 0xab);
		buf[i] = 0;
	}

	if (v == v->window->view)
		set_builtin_color(BC_ACTIVETAB);
	else
		set_builtin_color(BC_INACTIVETAB);
	buf_add_str(buf);
	buf_add_str(filename);
	buf_clear_eol();
}
Пример #6
0
void buf_add_xml (struct buf *buf, char c)
{
    if (c == '<') {
        buf_add_str(buf, "&lt;");
    } else if (c == '>') {
        buf_add_str(buf, "&gt;");
    } else if (c == '\"') {
        buf_add_str(buf, "&quot;");
    } else if (c == '\'') {
        buf_add_str(buf, "&apos;");
    } else if (c == '&') {
        buf_add_str(buf, "&amp;");
    } else {
        buf_add(buf, c);
    }
}
Пример #7
0
static ERL_NIF_TERM escape_cdata(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary input;
    ERL_NIF_TERM output;
    struct buf *rbuf;
    int i;

    if (argc != 1) {
        return enif_make_badarg(env);
    }

    // CData should be iolist() or binary()
    if (enif_is_binary(env, argv[0])) {
        if (!enif_inspect_binary(env, argv[0], &input)) {
            return enif_make_badarg(env);
        }
    } else {
        if (!enif_inspect_iolist_as_binary(env, argv[0], &input)) {
            return enif_make_badarg(env);
        }
    }

    rbuf = init_buf(env, EXML_CDATA_BUF_SIZE);

    for (i = 0; i < input.size; i++) {
        switch (input.data[i]) {
            case '&':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&amp;", 5);
                break;
            case '<':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&lt;", 4);
                break;
            case '>':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&gt;", 4);
                break;
            default:
                buf_add_char(env, EXML_CDATA_BUF_SIZE, rbuf, input.data[i]);
                break;
        };
    };

    unsigned char* data = enif_make_new_binary(env, rbuf->len, &output);
    memcpy(data, rbuf->b, rbuf->len);
    destroy_buf(env, rbuf);
    return output;
}
Пример #8
0
static ERL_NIF_TERM escape_attr(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary input;
    ERL_NIF_TERM output;
    struct buf *rbuf;
    int i;

    if (argc != 1) {
        return enif_make_badarg(env);
    }

    if (!enif_inspect_binary(env, argv[0], &input)) {
        return enif_make_badarg(env);
    }

    rbuf = init_buf(env, EXML_ATTR_BUF_SIZE);

    for (i = 0; i < input.size; i++) {
        switch (input.data[i]) {
            case '&':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&amp;", 5);
                break;
            case '<':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&lt;", 4);
                break;
            case '>':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&gt;", 4);
                break;
            case '"':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&quot;", 6);
                break;
            case '\'':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&apos;", 6);
                break;
            case '\t':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&#x9;", 5);
                break;
            case '\n':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&#xA;", 5);
                break;
            case '\r':
                buf_add_str(env, EXML_ATTR_BUF_SIZE, rbuf, "&#xD;", 5);
                break;
            default:
                buf_add_char(env, EXML_ATTR_BUF_SIZE, rbuf, input.data[i]);
                break;
        };
    };

    unsigned char *data = enif_make_new_binary(env, rbuf->len, &output);
    memcpy(data, rbuf->b, rbuf->len);
    destroy_buf(env, rbuf);
    return output;
}
Пример #9
0
static int make_element(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM el)
{
  ErlNifBinary cdata, name;
  const ERL_NIF_TERM *tuple;
  int arity, ret = 0;

  if (enif_get_tuple(env, el, &arity, &tuple)) {
    if (arity == 2) {
      if (!ENIF_COMPARE(tuple[0], atom_xmlcdata)) {
	if (enif_inspect_iolist_as_binary(env, tuple[1], &cdata)) {
	  crypt(env, rbuf, cdata.data, cdata.size);
	  ret = 1;
	};
      };
    };
    if (arity == 4) {
      if (!ENIF_COMPARE(tuple[0], atom_xmlelement)) {
	if (enif_inspect_iolist_as_binary(env, tuple[1], &name)) {
	  buf_add_char(env, rbuf, '<');
	  buf_add_str(env, rbuf, (char *)name.data, name.size);
	  ret = make_attrs(env, rbuf, tuple[2]);
	  if (ret) {
	    if (enif_is_empty_list(env, tuple[3])) {
	      buf_add_str(env, rbuf, "/>", 2);
	    } else {
	      buf_add_char(env, rbuf, '>');
	      ret = make_elements(env, rbuf, tuple[3]);
	      if (ret) {
		buf_add_str(env, rbuf, "</", 2);
		buf_add_str(env, rbuf, (char*)name.data, name.size);
		buf_add_char(env, rbuf, '>');
	      };
	    };
	  };
	};
      };
    };
  };
  
  return ret;
}
Пример #10
0
void update_git_open(void)
{
    int x = 0;
    int y = 0;
    int w = screen_w;
    int h = screen_h - 1;
    int max_y = git_open.scroll + h - 1;
    int i;

    if (h >= git_open.files.count)
        git_open.scroll = 0;
    if (git_open.scroll > git_open.selected)
        git_open.scroll = git_open.selected;
    if (git_open.selected > max_y)
        git_open.scroll += git_open.selected - max_y;

    buf_reset(x, w, 0);
    buf_move_cursor(0, 0);
    cmdline_x = print_command('/');
    buf_clear_eol();
    y++;

    for (i = 0; i < h; i++) {
        int file_idx = git_open.scroll + i;
        char *file;
        struct term_color color;

        if (file_idx >= git_open.files.count)
            break;

        file = git_open.files.ptrs[file_idx];
        obuf.x = 0;
        buf_move_cursor(x, y + i);

        color = *builtin_colors[BC_DEFAULT];
        if (file_idx == git_open.selected)
            mask_color(&color, builtin_colors[BC_SELECTION]);
        buf_set_color(&color);
        buf_add_str(file);
        buf_clear_eol();
    }
    set_builtin_color(BC_DEFAULT);
    for (; i < h; i++) {
        obuf.x = 0;
        buf_move_cursor(x, y + i);
        buf_clear_eol();
    }
}
Пример #11
0
Файл: xml.c Проект: imp/slist
/*
 * []----
 * | tgt_buf_add_tag_and_attr -- variant on tgt_buf_add_tag which also gives
 * |    attr
 * []----
 */
void
tgt_buf_add_tag_and_attr(char **b, char *str, char *attr)
{
	char	*buf;
	int	len;

	/*
	 * In addition to the 'str' and 'attr' strings the code will add
	 * three characters plus a null byte.
	 */
	len = strlen(str) + strlen(attr) + 4;
	if ((buf = malloc(len)) == NULL)
		return;

	(void) snprintf(buf, len, "<%s %s>", str, attr);
	buf_add_str(b, buf);
	free(buf);
}
Пример #12
0
Файл: xml.c Проект: imp/slist
/*
 * []----
 * | tgt_buf_add_tag -- adds string to buffer allocating space, sets up tags too
 * |
 * | Helper function to build a string by allocating memory as we go.
 * | If the string argument 'str' is defined to be a start or end tag
 * | as declared by 'type' argument add the appropriate characters.
 * []----
 */
void
tgt_buf_add_tag(char **b, const char *str, val_type_t type)
{
	char	*buf;
	int	len;

	/*
	 * We will add potentially up to 3 extra characters plus the NULL byte
	 */
	len = strlen(str) + 4;
	if ((buf = malloc(len)) == NULL)
		return;

	(void) snprintf(buf, len, "%s%s%s%s", type == Tag_String ? "" : "<",
	    type == Tag_End ? "/" : "", str, type == Tag_String ? "" : ">");
	buf_add_str(b, buf);
	free(buf);
}
Пример #13
0
void update_status_line(struct window *win)
{
    struct formatter f;
    char lbuf[256];
    char rbuf[256];
    int lw, rw;

    sf_init(&f, win);
    f.misc_status = format_misc_status(win);
    sf_format(&f, lbuf, sizeof(lbuf), options.statusline_left);
    sf_format(&f, rbuf, sizeof(rbuf), options.statusline_right);

    buf_reset(win->x, win->w, 0);
    buf_move_cursor(win->x, win->y + win->h - 1);
    set_builtin_color(BC_STATUSLINE);
    lw = u_str_width(lbuf);
    rw = u_str_width(rbuf);
    if (lw + rw <= win->w) {
        // both fit
        buf_add_str(lbuf);
        buf_set_bytes(' ', win->w - lw - rw);
        buf_add_str(rbuf);
    } else if (lw <= win->w && rw <= win->w) {
        // both would fit separately, draw overlapping
        buf_add_str(lbuf);
        obuf.x = win->w - rw;
        buf_move_cursor(win->x + win->w - rw, win->y + win->h - 1);
        buf_add_str(rbuf);
    } else if (lw <= win->w) {
        // left fits
        buf_add_str(lbuf);
        buf_clear_eol();
    } else if (rw <= win->w) {
        // right fits
        buf_set_bytes(' ', win->w - rw);
        buf_add_str(rbuf);
    } else {
        buf_clear_eol();
    }
}
Пример #14
0
int main (int argc, char *argv[])
{
    FILE *fpi = stdin, *fpo = stdout, *fpmap;
    struct mapper mapper;
    struct record record;
    struct map *map;
    struct field *field;
    struct buf *val_buf = buf_new(1024), *xml_buf = NULL;
    char *xml_key, *key_buf, prev_seq[9], seq[9], tag[4], ind1, ind2;
    int file_args = 0, array = 1, xml = 0, mapfile = 0, count = 0,
        first = 0, first_sub = 0, first_char, skip_sub = 0, c, i, j;

    tag[3] = '\0';

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "--usage") || !strcmp(argv[i], "--help") || !strcmp(argv[i], "-?")) {
            usage(argv[0], 0);
        } else if (!strcmp(argv[i], "--newline")) {
            array = 0;
        } else if (!strcmp(argv[i], "--xml")) {
            xml = 1;
        } else if (!strcmp(argv[i], "--json")) {
            xml = 0;
        } else if (!strcmp(argv[i], "--xmlkey")) {
            if (++i == argc) usage(argv[0], 1);
            xml_key = argv[i];
            xml_buf = buf_new(2048);
        } else if (!strcmp(argv[i], "--mapfile")) {
            if (++i == argc) usage(argv[0], 1);

            key_buf = malloc(256);

            if ((fpmap = fopen(argv[i], "r")) == NULL) {
                fprintf(stderr, "Can't open %s for reading\n", argv[i]);
                return 1;
            }

            if (!mapfile) {
                mapfile = 1;

                mapper.size = mapper.grow = 100;
                mapper.used = 0;
                mapper.maps = malloc(sizeof(struct map) * mapper.size);

                record.size = record.grow = 100;
                record.used = 0;
                record.fields = malloc(sizeof(struct field) * record.size);
                for (j = 0; j < record.size; j++) {
                    record.fields[j].val = buf_new(1024);
                }
            }

            while ((c = getc(fpmap)) != EOF) {
                if (isspace(c)) continue;
                if (c == '#') {
                    while (more(c = getc(fpmap)));
                    continue;
                }
                map = mapper.maps + mapper.used;
                map->key = NULL;
                map->tag[0] = c;
                map->tag[1] = getc(fpmap);
                map->tag[2] = getc(fpmap);
                if (isspace(c = getc(fpmap))) {
                    map->op = '\0';
                } else {
                    map->op = c;
                    fscanf(fpmap, "%s", map->subfields);
                }
                fscanf(fpmap, "%s", key_buf);
                for (j = 0; j < mapper.used; j++) {
                    if (!strcmp(mapper.maps[j].key, key_buf)) {
                        map->key = mapper.maps[j].key;
                        break;
                    }
                }
                if (!map->key) {
                    map->key = malloc(strlen(key_buf) + 1);
                    strcpy(map->key, key_buf);
                }

                mapper.used++;
                if (mapper.used == mapper.size) {
                    mapper.size += mapper.grow;
                    mapper.maps = realloc(mapper.maps, sizeof(struct map) * mapper.size);
                }
            }

            free(key_buf);
            fclose(fpmap);
        } else {
            switch (++file_args) {
            case 1:
                if ((fpi = fopen(argv[i], "r")) == NULL) {
                    fprintf(stderr, "Can't open %s for reading\n", argv[i]);
                    return 1;
                }
                break;
            case 2:
                if ((fpo = fopen(argv[i], "w")) == NULL) {
                    fprintf(stderr, "Can't open %s for writing\n", argv[i]);
                    return 1;
                }
                break;
            }
        }
    }

    if (xml) {
        fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?><collection xmlns=\"http://www.loc.gov/MARC21/slim\">", fpo);
    } else if (array) {
        fputs("[", fpo);
    }

    while ((c = getc(fpi)) != EOF) {
        if (isspace(c)) continue;
        seq[0] = c;
        for (i = 1; i < 9; ++i) seq[i] = getc(fpi);
        getc(fpi);
        for (i = 0; i < 3; ++i) tag[i] = getc(fpi);
        ind1 = getc(fpi);
        ind2 = getc(fpi);
        for (i = 0; i < 3; ++i) getc(fpi);
        val_buf->used = 0;
        while (more(c = getc(fpi))) buf_add(val_buf, c);
        buf_add(val_buf, '\0');

        if (!count || strncmp(seq, prev_seq, 9)) {
            if (count++) {
                if (xml_buf) {
                    buf_add_str(xml_buf, "</record>");
                    buf_add(xml_buf, '\0');
                }
                if (mapfile) {
                    fputs("{", fpo);
                    for (i = 0; i < record.used; i++) {
                        field = record.fields + i;
                        if (i) putc(',', fpo);
                        buf_add(field->val, '\0');
                        fprintf(fpo, "\"%s\":[%s]", field->key, field->val->str);
                    }
                    if (xml_buf) {
                        if (i) putc(',', fpo);
                        fprintf(fpo, "\"%s\":\"", xml_key);
                        put_json_str(xml_buf->str, fpo);
                        putc('\"', fpo);
                    }
                    fputs(array ? "},\n" : "}\n", fpo);
                    record.used = 0;
                } else if (xml) {
                    fputs("</record>\n", fpo);
                } else {
                    fputs(array ? "]},\n" : "]}\n", fpo);
                }
                if (xml_buf) {
                    xml_buf->used = 0;
                }
            }
        }

        for (i = 0; i < 9; ++i) prev_seq[i] = seq[i];

        if (mapfile) {
            for (i = 0; i < mapper.used; i++) {
                map = mapper.maps + i;
                if ((map->tag[0] == '*' || map->tag[0] == tag[0]) &&
                    (map->tag[1] == '*' || map->tag[1] == tag[1]) &&
                    (map->tag[2] == '*' || map->tag[2] == tag[2])) {
                    field = NULL;
                    for (j = 0; j < record.used; j++) {
                        field = record.fields + j;
                        if (field->key == map->key) {
                            break;
                        }
                        field = NULL;
                    }
                    if (!field) {
                        field = record.fields + record.used;
                        field->key = map->key;
                        field->val->used = 0;
                        record.used++;
                    }
                    skip_sub = 0;
                    first_char = 1;
                    for (j = 0; j < val_buf->used-1; j++) {
                        if (val_buf->str[j] == '$' && val_buf->str[j+1] == '$') {
                            j+= 2;
                            if ( (map->op == '+' && strchr(map->subfields, val_buf->str[j]) == NULL) ||
                                 (map->op == '-' && strchr(map->subfields, val_buf->str[j]) != NULL) ) {
                                skip_sub = 1;
                                continue;
                            }
                            skip_sub = 0;
                            j++;
                            if (j == val_buf->used-1) break;
                        }

                        if (!skip_sub) {
                            if (first_char) {
                                if (field->val->used) buf_add(field->val, ',');
                                buf_add(field->val, '"');
                                first_char = 0;
                            }
                            if (val_buf->str[j] == '"') buf_add(field->val, '\\');
                            if (val_buf->str[j] == '\\') buf_add(field->val, '\\');
                            buf_add(field->val, val_buf->str[j]);
                        }
                    }
                    if (!first_char) buf_add(field->val, '"');
                }
            }
        }

        if (!strncmp(tag, "FMT", 3)) continue;

        if (!strncmp(tag, "LDR", 3)) {
            if (xml_buf) {
                buf_add_str(xml_buf, "<record><leader>");
                buf_add_str(xml_buf, val_buf->str);
                buf_add_str(xml_buf, "</leader>");
            } else if (xml) {
                fprintf(fpo, "<record><leader>%s</leader>", val_buf->str);
            } else if (!mapfile) {
                fprintf(fpo, "{\"leader\":\"%s\",\"fields\":[", val_buf->str);
            }
            first = 1;
            continue;
        }

        if (first) {
            first = 0;
        } else if (!xml_buf && !xml && !mapfile) {
            putc(',', fpo);
        }

        if (tag[0] == '0' && tag[1] == '0') {
            if (xml_buf) {
                buf_add_str(xml_buf, "<controlfield tag=\"");
                for (i = 0; i < 3; i++) buf_add(xml_buf, tag[i]);
                buf_add_str(xml_buf, "\">");
                buf_add_xml_str(xml_buf, val_buf->str);
                buf_add_str(xml_buf, "</controlfield>");
            } else if (xml) {
                fprintf(fpo, "<controlfield tag=\"%3s\">", tag);
                for (i = 0; i < val_buf->used-1; i++) put_xml(val_buf->str[i], fpo);
                fputs("</controlfield>", fpo);
            } else if (!mapfile) {
                fprintf(fpo, "{\"%3s\":\"", tag);
                for (i = 0; i < val_buf->used-1; i++) put_json(val_buf->str[i], fpo);
                fputs("\"}", fpo);
            }
        } else {
            if (xml_buf) {
                buf_add_str(xml_buf, "<datafield tag=\"");
                for (i = 0; i < 3; i++) buf_add(xml_buf, tag[i]);
                buf_add_str(xml_buf, "\" ind1=\"");
                buf_add(xml_buf, ind1);
                buf_add_str(xml_buf, "\" ind2=\"");
                buf_add(xml_buf, ind2);
                buf_add_str(xml_buf, "\">");
            } else if (xml) {
                fprintf(fpo, "<datafield tag=\"%3s\" ind1=\"%c\" ind2=\"%c\">", tag, ind1, ind2);
            } else if (!mapfile) {
                fprintf(fpo, "{\"%3s\":{\"ind1\":\"%c\",\"ind2\":\"%c\",\"subfields\":[", tag, ind1, ind2);
            }
            first_sub = 1;
            for (i = 0; i < val_buf->used-1; i++) {
                if (val_buf->str[i] == '$' && val_buf->str[i+1] == '$') {
                    i+= 2;
                    if (first_sub) {
                        first_sub = 0;
                    } else {
                        if (xml_buf) {
                            buf_add_str(xml_buf, "</subfield>");
                        } else if (xml) {
                            fputs("</subfield>", fpo);
                        } else if (!mapfile) {
                            fputs("\"},", fpo);
                        }
                    }
                    if (xml_buf) {
                        buf_add_str(xml_buf, "<subfield code=\"");
                        buf_add(xml_buf, val_buf->str[i]);
                        buf_add_str(xml_buf, "\">");
                    } else if (xml) {
                        fprintf(fpo, "<subfield code=\"%c\">", val_buf->str[i]);
                    } else if (!mapfile) {
                        fprintf(fpo, "{\"%c\":\"", val_buf->str[i]);
                    }
                    continue;
                }
                if (xml_buf) {
                    buf_add_xml(xml_buf, val_buf->str[i]);
                } else if (xml) {
                    put_xml(val_buf->str[i], fpo);
                } else if (!mapfile) {
                    put_json(val_buf->str[i], fpo);
                }
            }
            if (!first_sub) {
                if (xml_buf) {
                    buf_add_str(xml_buf, "</subfield>");
                } else if (xml) {
                    fputs("</subfield>", fpo);
                } else if (!mapfile) {
                    fputs("\"}", fpo);
                }
            }
            if (xml_buf) {
                buf_add_str(xml_buf, "</datafield>");
            } else if (xml) {
                fputs("</datafield>", fpo);
            } else if (!mapfile) {
                fputs("]", fpo);
            }
        }
    }

    if (count && mapfile) {
        fputs("{", fpo);
        for (i = 0; i < record.used; i++) {
            field = record.fields + i;
            if (i) putc(',', fpo);
            buf_add(field->val, '\0');
            fprintf(fpo, "\"%s\":[%s]", field->key, field->val->str);
        }
        if (xml_buf) {
            if (i) putc(',', fpo);
            fprintf(fpo, "\"%s\":\"", xml_key);
            put_json_str(xml_buf->str, fpo);
            putc('\"', fpo);
        }
    }

    if (xml) {
        if (count) fputs("</record>", fpo);
        fputs("</collection>", fpo);
    } else {
        if (count) fputs("}", fpo);
        if (array) fputs("]", fpo);
    }

    fclose(fpi);
    fclose(fpo);

    return 0;
}