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