1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2009 Index Data
3 * See the file LICENSE for details.
7 * \file marc_read_line.c
8 * \brief Implements reading of MARC in line format
24 #include <yaz/marcdisp.h>
25 #include <yaz/wrbuf.h>
26 #include <yaz/yaz-util.h>
28 int yaz_gets(int (*getbyte)(void *client_data),
29 void (*ungetbyte)(int b, void *client_data),
34 int ch = getbyte(client_data);
36 while (ch != '\0' && ch != '\r' && ch != '\n')
40 ch = getbyte(client_data);
44 ch = getbyte(client_data);
45 if (ch != '\n' && ch != '\0')
46 ungetbyte(ch, client_data);
50 ch = getbyte(client_data);
51 if (ch != '\r' && ch != '\0')
52 ungetbyte(ch, client_data);
61 static int yaz_marc_line_gets(int (*getbyte)(void *client_data),
62 void (*ungetbyte)(int b, void *client_data),
69 more = yaz_gets(getbyte, ungetbyte, client_data, w);
78 int ch = getbyte(client_data);
82 ungetbyte(ch, client_data);
86 if (wrbuf_len(w) > 60 && wrbuf_buf(w)[wrbuf_len(w)-1] == '=')
87 wrbuf_cut_right(w, 1);
90 more = yaz_gets(getbyte, ungetbyte, client_data, w);
96 int yaz_marc_read_line(yaz_marc_t mt,
97 int (*getbyte)(void *client_data),
98 void (*ungetbyte)(int b, void *client_data),
101 int indicator_length;
102 int identifier_length;
104 int length_data_entry;
106 int length_implementation;
109 int header_created = 0;
110 WRBUF wrbuf_line = wrbuf_alloc();
114 while (yaz_marc_line_gets(getbyte, ungetbyte, client_data, wrbuf_line))
116 const char *line = wrbuf_cstr(wrbuf_line);
118 size_t line_len = strlen(line);
119 if (line_len == 0) /* empty line indicates end of record */
124 else if (line[0] == '$') /* indicates beginning/end of record */
129 else if (line[0] == '(') /* annotation, skip it */
131 else if (line_len == 24 && atoi_n_check(line, 5, &val) && val >= 24)
133 /* deal with header lines: 00366nam 22001698a 4500
138 yaz_marc_set_leader(mt, line,
144 &length_implementation);
147 else if (line_len > 5 && line[0] != ' ' && line[1] != ' '
148 && line[2] != ' ' && line[3] == ' ' )
150 /* deal with data/control lines: 245 12 ........ */
152 const char *datafield_start = line+6;
156 memcpy(tag, line, 3);
158 if (line_len >= 8) /* control - or datafield ? */
160 if (*datafield_start == ' ')
161 datafield_start++; /* skip blank after indicator */
163 if (strchr("$_*", *datafield_start))
165 marker_ch = *datafield_start;
166 if (datafield_start[2] == ' ')
167 marker_skip = 1; /* subfields has blank before data */
172 const char *leader = "01000cam 2200265 i 4500";
174 yaz_marc_set_leader(mt, leader,
180 &length_implementation);
185 { /* control field */
186 yaz_marc_add_controlfield(mt, tag, line+4, strlen(line+4));
190 const char *indicator = line+4;
191 int indicator_len = 2;
192 const char *cp = datafield_start;
194 yaz_marc_add_datafield(mt, tag, indicator, indicator_len);
200 assert(cp[0] == marker_ch);
203 while ((next = strchr(next, marker_ch)))
205 if ((next[1] >= 'A' && next[1] <= 'Z')
206 ||(next[1] >= 'a' && next[1] <= 'z'))
210 else if (next[2] == ' ')
217 len = next - cp - marker_skip;
221 /* remove ' ' after subfield marker */
222 char *cp_blank = strchr(cp, ' ');
226 while (cp_blank != cp)
228 cp_blank[0] = cp_blank[-1];
235 yaz_marc_add_subfield(mt, cp, len);
244 yaz_marc_cprintf(mt, "Ignoring line: %s", line);
247 wrbuf_destroy(wrbuf_line);
256 * c-file-style: "Stroustrup"
257 * indent-tabs-mode: nil
259 * vim: shiftwidth=4 tabstop=8 expandtab