New function iso2709_display to display MARC records in a
[egate.git] / util / iso2709.c
1 /*
2    Iso2709 record management
3
4    Europagate, 1994-1995.
5
6    $Log: iso2709.c,v $
7    Revision 1.3  1995/02/10 17:05:18  adam
8    New function iso2709_display to display MARC records in a
9    line-by-line format. The iso2709_cvt function no longer
10    prints the record to stderr.
11
12  * Revision 1.2  1995/02/10  16:50:32  adam
13  * Indicator field moved to 'struct iso2709_dir' from 'struct
14  * iso2709_field'.
15  * Function iso2709_rm implemented - to delete a MARC record.
16  *
17  * Revision 1.1.1.1  1995/02/09  17:27:11  adam
18  * Initial version of email gateway under CVS control.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include <ctype.h>
27
28 #include <iso2709p.h>
29
30 static int atoin (const char *buf, int n)
31 {
32     int val = 0;
33     while (--n >= 0)
34     {
35         if (isdigit(*buf))
36             val = val*10 + (*buf - '0');
37         buf++;
38     }
39     return val;
40 }
41
42 static void strncpyx (char *d, const char *s, int n)
43 {
44     while (--n >= 0 && *s)
45         if (*s != ISO2709_IDFS)
46             *d++ = *s++;
47         else
48         {
49             *d++ = ' ';
50             s++;
51         }
52     *d = '\0';
53 #if 0
54     strncpy (d, s, n);
55     d[n] = '\0';
56 #endif
57 }
58
59 char *iso2709_read (FILE *inf)
60 {
61     char length_str[5];
62     int size;
63     char *buf;
64
65     if (fread (length_str, 1, 5, inf) != 5)
66         return NULL;
67     size = atoin (length_str, 5);
68     if (size <= 6)
69         return NULL;
70     if (!(buf = malloc (size+1)))
71         return NULL;
72     if (fread (buf+5, 1, size-5, inf) != (size-5))
73     {
74         free (buf);
75         return NULL;
76     }
77     memcpy (buf, length_str, 5);
78     buf[size] = '\0';
79     return buf;
80 }
81
82 Iso2709Rec iso2709_cvt (const char *buf)
83 {
84     struct iso2709_dir **dpp, *dp;
85     int pos = 24;
86     Iso2709Rec p;
87
88     if (!(p = malloc (sizeof(*p))))
89         return NULL;
90
91     /* deal with record label (24 characters) */
92     p->record_length = atoin (buf, 5);
93     strncpyx (p->record_status, buf+5, 1);
94     strncpyx (p->implementation_codes, buf+6, 4);
95     p->indicator_length = atoin (buf+10, 1);
96     p->identifier_length = atoin (buf+11, 1);
97     p->base_address = atoin (buf+12, 4);
98     strncpyx (p->user_systems, buf+17, 3);
99
100     p->length_data_entry = atoin (buf+20, 1);
101     p->length_starting = atoin (buf+21, 1);
102     p->length_implementation = atoin (buf+22, 1);
103     strncpyx (p->future_use, buf+23, 1);
104
105     /* deal with directory */
106     dpp = &p->directory;
107     *dpp = NULL;
108     while (buf[pos] != ISO2709_FS)
109     {
110         *dpp = malloc (sizeof(**dpp));
111         (*dpp)->next = NULL;
112         strncpyx ((*dpp)->tag, buf+pos, 3);
113         pos += 3;
114         (*dpp)->length = atoin (buf+pos, p->length_data_entry);
115         pos += p->length_data_entry;
116         (*dpp)->offset = atoin (buf+pos, p->length_starting);
117         pos += p->length_starting + p->length_implementation;
118
119         dpp = &(*dpp)->next;
120     }
121     pos++;
122     /* deal with datafields */
123     for (dp = p->directory; dp; dp = dp->next)
124     {
125         int tag00;
126         struct iso2709_field **fpp;
127         int dpos = pos+dp->offset;
128
129         fpp = &dp->fields;
130
131         *fpp = malloc (sizeof(**fpp));
132         (*fpp)->next = NULL;
133         if (p->indicator_length && memcmp (dp->tag, "00", 2))
134         {
135             dp->indicator = malloc (p->indicator_length+1);
136             strncpyx (dp->indicator, buf+dpos, p->indicator_length);
137             dpos += p->indicator_length;
138         }
139         else
140             dp->indicator = NULL;
141
142         if (memcmp (dp->tag, "00", 2))
143             tag00 = 0;
144         else
145             tag00 = 1;
146         while (1)
147         {
148             int dpos_n;
149             if (p->identifier_length && !tag00)
150             {
151                 (*fpp)->identifier = malloc (p->identifier_length+1);
152                 strncpyx ((*fpp)->identifier, buf+dpos+1,
153                           p->identifier_length-1);
154                 dpos += p->identifier_length;
155             }
156             else
157                 (*fpp)->identifier = NULL;
158
159             dpos_n = dpos;
160             while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_IDFS)
161                 dpos_n++;
162
163             (*fpp)->data = malloc (dpos_n - dpos + 1);
164             strncpyx ((*fpp)->data, buf+dpos, dpos_n - dpos);
165             dpos = dpos_n;
166             
167             if (buf[dpos] == ISO2709_FS)
168                 break;
169             
170             fpp = &(*fpp)->next;
171             *fpp = malloc (sizeof(**fpp));
172             (*fpp)->next = NULL;
173         }
174     }
175     return p;
176 }
177
178 void iso2709_rm (Iso2709Rec rec)
179 {
180     struct iso2709_dir *dir, *dir1;
181
182     for (dir = rec->directory; dir; dir = dir1)
183     {
184         struct iso2709_field *field, *field1;
185
186         for (field = dir->fields; field; field = field1)
187         {
188             free (field->identifier);
189             free (field->data);
190             field1 = field->next;
191             free (field);
192         }
193         free (dir->indicator);
194         dir1 = dir->next;
195         free (dir);
196     }
197 }