03bb37c1ff60b94d31124541135e7c737b4f794e
[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.17 2002-02-01 14:50:29 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 marc_display_wrbuf (const char *buf, WRBUF wr, int debug,
20                         int bsize)
21 {
22     int entry_p;
23     int record_length;
24     int indicator_length;
25     int identifier_length;
26     int base_address;
27     int length_data_entry;
28     int length_starting;
29     int length_implementation;
30
31     record_length = atoi_n (buf, 5);
32     if (record_length < 25)
33     {
34         if (debug)
35         {
36             char str[40];
37             
38             sprintf (str, "Record length %d - aborting\n", record_length);
39             wrbuf_puts (wr, str);
40         }
41         return -1;
42     }
43     /* ballout if bsize is known and record_length is than that */
44     if (bsize != -1 && record_length > bsize)
45         return -1;
46     if (isdigit(buf[10]))
47         indicator_length = atoi_n (buf+10, 1);
48     else
49         indicator_length = 2;
50     if (isdigit(buf[11]))
51         identifier_length = atoi_n (buf+11, 1);
52     else
53         identifier_length = 2;
54     base_address = atoi_n (buf+12, 5);
55
56     length_data_entry = atoi_n (buf+20, 1);
57     length_starting = atoi_n (buf+21, 1);
58     length_implementation = atoi_n (buf+22, 1);
59
60     if (debug)
61     {
62         char str[40];
63         sprintf (str, "Record length         %5d\n", record_length);
64         wrbuf_puts (wr, str);
65         sprintf (str, "Indicator length      %5d\n", indicator_length);
66         wrbuf_puts (wr, str);
67         sprintf (str, "Identifier length     %5d\n", identifier_length);
68         wrbuf_puts (wr, str);
69         sprintf (str, "Base address          %5d\n", base_address);
70         wrbuf_puts (wr, str);
71         sprintf (str, "Length data entry     %5d\n", length_data_entry);
72         wrbuf_puts (wr, str);
73         sprintf (str, "Length starting       %5d\n", length_starting);
74         wrbuf_puts (wr, str);
75         sprintf (str, "Length implementation %5d\n", length_implementation);
76         wrbuf_puts (wr, str);
77     }
78     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
79     {
80         entry_p += 3+length_data_entry+length_starting;
81         if (entry_p >= record_length)
82             return -1;
83     }
84     base_address = entry_p+1;
85     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
86     {
87         int data_length;
88         int data_offset;
89         int end_offset;
90         int i, j;
91         char tag[4];
92         int identifier_flag = 1;
93
94         memcpy (tag, buf+entry_p, 3);
95         entry_p += 3;
96         tag[3] = '\0';
97         if (debug)
98             wrbuf_puts (wr, "Tag: ");
99         wrbuf_puts (wr, tag);
100         wrbuf_puts (wr, " ");
101         data_length = atoi_n (buf+entry_p, length_data_entry);
102         entry_p += length_data_entry;
103         data_offset = atoi_n (buf+entry_p, length_starting);
104         entry_p += length_starting;
105         i = data_offset + base_address;
106         end_offset = i+data_length-1;
107         
108         if (indicator_length < 4 && indicator_length > 0)
109         {
110             if (buf[i + indicator_length] != ISO2709_IDFS)
111                 identifier_flag = 0;
112         }
113         else if (!memcmp (tag, "00", 2))
114             identifier_flag = 0;
115         
116         if (identifier_flag)
117         {
118             if (debug)
119                 wrbuf_puts (wr, " Ind: ");
120             for (j = 0; j<indicator_length; j++, i++)
121                 wrbuf_putc (wr, buf[i]);
122         }
123         if (debug)
124             wrbuf_puts (wr, " Fields: ");
125         while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
126         {
127             if (identifier_flag)
128             {
129                 i++;
130                 wrbuf_puts (wr, " $"); 
131                 for (j = 1; j<identifier_length; j++, i++)
132                     wrbuf_putc (wr, buf[i]);
133                 wrbuf_putc (wr, ' ');
134                 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
135                        buf[i] != ISO2709_FS && i < end_offset)
136                 {
137                     wrbuf_putc (wr, buf[i]);
138                     i++;
139                 }
140             }
141             else
142             {
143                 wrbuf_putc (wr, buf[i]);
144                 i++;
145             }
146         }
147         wrbuf_putc (wr, '\n');
148         if (i < end_offset)
149             wrbuf_puts (wr, "-- separator but not at end of field\n");
150         if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
151             wrbuf_puts (wr, "-- no separator at end of field\n");
152     }
153     wrbuf_puts (wr, "");
154     return record_length;
155 }
156
157 int marc_display_exl (const char *buf, FILE *outf, int debug, int length)
158 {
159     int record_length;
160
161     WRBUF wrbuf = wrbuf_alloc ();
162     record_length = marc_display_wrbuf (buf, wrbuf, debug, length);
163     if (!outf)
164         outf = stdout;
165     if (record_length > 0)
166         fwrite (wrbuf_buf(wrbuf), 1, wrbuf_len(wrbuf), outf);
167     wrbuf_free (wrbuf, 1);
168     return record_length;
169 }
170
171
172 int marc_display_ex (const char *buf, FILE *outf, int debug)
173 {
174     return marc_display_exl (buf, outf, debug, -1);
175 }
176
177 int marc_display (const char *buf, FILE *outf)
178 {
179     return marc_display_ex (buf, outf, 0);
180 }
181
182