Add OID-database entries for the MARC, BIB-2 and ZeeRex attribute sets.
[yaz-moved-to-github.git] / util / marcdisp.c
1 /*
2  * Copyright (c) 1995-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: marcdisp.c,v 1.19 2002-03-18 18:11:45 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <yaz/marcdisp.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/yaz-util.h>
18
19 int yaz_marc_decode (const char *buf, WRBUF wr, int debug, int bsize, int xml)
20 {
21     int entry_p;
22     int record_length;
23     int indicator_length;
24     int identifier_length;
25     int base_address;
26     int length_data_entry;
27     int length_starting;
28     int length_implementation;
29
30     record_length = atoi_n (buf, 5);
31     if (record_length < 25)
32     {
33         if (debug)
34         {
35             char str[40];
36             
37             sprintf (str, "Record length %d - aborting\n", record_length);
38             wrbuf_puts (wr, str);
39         }
40         return -1;
41     }
42     /* ballout if bsize is known and record_length is than that */
43     if (bsize != -1 && record_length > bsize)
44         return -1;
45     if (isdigit(buf[10]))
46         indicator_length = atoi_n (buf+10, 1);
47     else
48         indicator_length = 2;
49     if (isdigit(buf[11]))
50         identifier_length = atoi_n (buf+11, 1);
51     else
52         identifier_length = 2;
53     base_address = atoi_n (buf+12, 5);
54
55     length_data_entry = atoi_n (buf+20, 1);
56     length_starting = atoi_n (buf+21, 1);
57     length_implementation = atoi_n (buf+22, 1);
58
59     if (xml)
60     {
61         char str[40];
62         int i;
63         wrbuf_puts (wr, "<iso2709\n");
64         sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
65         wrbuf_puts (wr, str);
66         sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
67         wrbuf_puts (wr, str);
68         for (i = 1; i<=19; i++)
69         {
70             sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
71             wrbuf_puts (wr, str);
72         }
73         wrbuf_puts (wr, ">\n");
74     }
75     if (debug)
76     {
77         char str[40];
78
79         if (xml)
80             wrbuf_puts (wr, "<!--\n");
81         sprintf (str, "Record length         %5d\n", record_length);
82         wrbuf_puts (wr, str);
83         sprintf (str, "Indicator length      %5d\n", indicator_length);
84         wrbuf_puts (wr, str);
85         sprintf (str, "Identifier length     %5d\n", identifier_length);
86         wrbuf_puts (wr, str);
87         sprintf (str, "Base address          %5d\n", base_address);
88         wrbuf_puts (wr, str);
89         sprintf (str, "Length data entry     %5d\n", length_data_entry);
90         wrbuf_puts (wr, str);
91         sprintf (str, "Length starting       %5d\n", length_starting);
92         wrbuf_puts (wr, str);
93         sprintf (str, "Length implementation %5d\n", length_implementation);
94         wrbuf_puts (wr, str);
95         if (xml)
96             wrbuf_puts (wr, "-->\n");
97     }
98
99     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
100     {
101         entry_p += 3+length_data_entry+length_starting;
102         if (entry_p >= record_length)
103             return -1;
104     }
105     base_address = entry_p+1;
106     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
107     {
108         int data_length;
109         int data_offset;
110         int end_offset;
111         int i, j;
112         char tag[4];
113         int identifier_flag = 1;
114
115         memcpy (tag, buf+entry_p, 3);
116         entry_p += 3;
117         tag[3] = '\0';
118         if (xml)
119         {
120             wrbuf_puts (wr, "<field tag=\"");
121             wrbuf_puts (wr, tag);
122             wrbuf_puts (wr, "\"");
123         }
124         else
125         {
126             if (debug)
127                 wrbuf_puts (wr, "Tag: ");
128             wrbuf_puts (wr, tag);
129             wrbuf_puts (wr, " ");
130         }
131         data_length = atoi_n (buf+entry_p, length_data_entry);
132         entry_p += length_data_entry;
133         data_offset = atoi_n (buf+entry_p, length_starting);
134         entry_p += length_starting;
135         i = data_offset + base_address;
136         end_offset = i+data_length-1;
137         
138         if (indicator_length < 4 && indicator_length > 0)
139         {
140             if (buf[i + indicator_length] != ISO2709_IDFS)
141                 identifier_flag = 0;
142         }
143         else if (!memcmp (tag, "00", 2))
144             identifier_flag = 0;
145         
146         if (identifier_flag)
147         {
148             if (debug && !xml)
149                 wrbuf_puts (wr, " Ind: ");
150             for (j = 0; j<indicator_length; j++, i++)
151             {
152                 if (xml)
153                 {
154                     char nostr[30];
155                     sprintf (nostr, " Indicator%d=\"%c\"", j+1, buf[i]);
156                     wrbuf_puts (wr, nostr);
157                 }
158                 else
159                     wrbuf_putc (wr, buf[i]);
160             }
161         }
162         if (xml)
163         {
164             wrbuf_puts (wr, ">");
165             if (identifier_flag)
166                 wrbuf_puts (wr, "\n");
167         }
168         else
169         {
170             if (debug && !xml)
171                 wrbuf_puts (wr, " Fields: ");
172         }
173         while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
174         {
175             if (identifier_flag)
176             {
177                 i++;
178                 if (xml)
179                 {
180                     wrbuf_puts (wr, "  <subfield code=\"");
181                     for (j = 1; j<identifier_length; j++, i++)
182                         wrbuf_putc (wr, buf[i]);
183                     wrbuf_puts (wr, "\">");
184                 }
185                 else
186                 {
187                     wrbuf_puts (wr, " $"); 
188                     for (j = 1; j<identifier_length; j++, i++)
189                         wrbuf_putc (wr, buf[i]);
190                     wrbuf_putc (wr, ' ');
191                 }
192                 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
193                        buf[i] != ISO2709_FS && i < end_offset)
194                 {
195                     wrbuf_putc (wr, buf[i]);
196                     i++;
197                 }
198                 if (xml)
199                     wrbuf_puts (wr, "</subfield>\n");
200             }
201             else
202             {
203                 wrbuf_putc (wr, buf[i]);
204                 i++;
205             }
206         }
207         if (!xml)
208             wrbuf_putc (wr, '\n');
209         if (i < end_offset)
210             wrbuf_puts (wr, "  <!-- separator but not at end of field -->\n");
211         if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
212             wrbuf_puts (wr, "  <!-- no separator at end of field -->\n");
213         if (xml)
214             wrbuf_puts (wr, "</field>\n");
215     }
216     if (xml)
217         wrbuf_puts (wr, "</iso2709>\n");
218     wrbuf_puts (wr, "");
219     return record_length;
220 }
221
222 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug,
223                         int bsize)
224 {
225     return yaz_marc_decode (buf, wr, debug, bsize, 0);
226 }
227
228 int marc_display_exl (const char *buf, FILE *outf, int debug, int length)
229 {
230     int record_length;
231
232     WRBUF wrbuf = wrbuf_alloc ();
233     record_length = marc_display_wrbuf (buf, wrbuf, debug, length);
234     if (!outf)
235         outf = stdout;
236     if (record_length > 0)
237         fwrite (wrbuf_buf(wrbuf), 1, wrbuf_len(wrbuf), outf);
238     wrbuf_free (wrbuf, 1);
239     return record_length;
240 }
241
242 int marc_display_ex (const char *buf, FILE *outf, int debug)
243 {
244     return marc_display_exl (buf, outf, debug, -1);
245 }
246
247 int marc_display (const char *buf, FILE *outf)
248 {
249     return marc_display_ex (buf, outf, 0);
250 }
251
252