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