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