2 * Iso2709 record management
4 * Europagate, 1994-1995.
7 * Revision 1.14 1995/03/30 14:22:18 adam
8 * More work on new MARC anchor functions.
10 * Revision 1.13 1995/03/30 07:33:32 adam
11 * New 2709 function: iso2709_mk.
12 * First implementation of iso2709_a_insert.
14 * Revision 1.12 1995/03/29 16:08:56 adam
15 * Better error recovery when using bad records.
17 * Revision 1.11 1995/03/28 16:07:07 adam
18 * New function: iso2709_out. This function is the reverse of iso2709_cvt.
20 * Revision 1.10 1995/03/10 09:10:56 adam
21 * Removed dbc2709_cvt function. Makes heuristic guess for DBC2709 records.
23 * Revision 1.9 1995/03/08 12:36:39 adam
24 * New function: dbc2709_cvt.
26 * Revision 1.8 1995/03/08 12:03:15 adam
27 * Hack: When tags 00? are used, every separator (DC[1-3]) marks
28 * the end of the data field.
30 * Revision 1.7 1995/02/22 21:28:03 adam
33 * Revision 1.5 1995/02/22 15:24:14 adam
34 * Function iso2709_cvt makes a litte check for the format. It returns
35 * NULL if the buffer parameter can never be a MARC record.
37 * Revision 1.4 1995/02/15 17:45:44 adam
38 * Bug fix in iso2709 module.
40 * Revision 1.3 1995/02/10 17:05:18 adam
41 * New function iso2709_display to display MARC records in a
42 * line-by-line format. The iso2709_cvt function no longer
43 * prints the record to stderr.
45 * Revision 1.2 1995/02/10 16:50:32 adam
46 * Indicator field moved to 'struct iso2709_dir' from 'struct
48 * Function iso2709_rm implemented - to delete a MARC record.
50 * Revision 1.1.1.1 1995/02/09 17:27:11 adam
51 * Initial version of email gateway under CVS control.
63 static int atoin (const char *buf, int n)
69 val = val*10 + (*buf - '0');
75 static void strncpyx (char *d, const char *s, int n)
77 while (--n >= 0 && *s)
78 if (*s != ISO2709_IDFS)
88 char *iso2709_read (FILE *inf)
94 if (fread (length_str, 1, 5, inf) != 5)
96 size = atoin (length_str, 5);
99 if (!(buf = malloc (size+1)))
101 if (fread (buf+5, 1, size-5, inf) != (size-5))
106 memcpy (buf, length_str, 5);
111 Iso2709Rec iso2709_mk (void)
115 if (!(p = malloc (sizeof(*p))))
118 p->record_length = 0;
119 strncpyx (p->record_status, " ", 1);
120 strncpyx (p->implementation_codes, " ", 4);
121 p->indicator_length = 2;
122 p->identifier_length = 2;
124 strncpyx (p->user_systems, " ", 3);
125 p->length_data_entry = 4;
126 p->length_starting = 5;
127 p->length_implementation = 0;
128 strncpyx (p->future_use, " ", 1);
134 Iso2709Rec iso2709_cvt (const char *buf)
136 struct iso2709_dir **dpp, *dp;
140 if (!(p = malloc (sizeof(*p))))
143 /* deal with record label (24 characters) */
144 p->record_length = atoin (buf, 5);
145 strncpyx (p->record_status, buf+5, 1);
146 strncpyx (p->implementation_codes, buf+6, 4);
147 p->indicator_length = atoin (buf+10, 1);
148 p->identifier_length = atoin (buf+11, 1);
149 p->base_address = atoin (buf+12, 4);
150 strncpyx (p->user_systems, buf+17, 3);
152 if (p->record_length < 26)
157 p->length_data_entry = atoin (buf+20, 1);
158 p->length_starting = atoin (buf+21, 1);
159 p->length_implementation = atoin (buf+22, 1);
160 strncpyx (p->future_use, buf+23, 1);
162 /* deal with directory */
165 while (buf[pos] != ISO2709_FS)
167 if (!(*dpp = malloc (sizeof(**dpp))))
173 (*dpp)->fields = NULL;
174 strncpyx ((*dpp)->tag, buf+pos, 3);
176 (*dpp)->length = atoin (buf+pos, p->length_data_entry);
177 pos += p->length_data_entry;
178 (*dpp)->offset = atoin (buf+pos, p->length_starting);
179 pos += p->length_starting + p->length_implementation;
182 if (pos > p->record_length)
189 /* deal with datafields */
190 for (dp = p->directory; dp; dp = dp->next)
193 struct iso2709_field **fpp;
194 int dpos = pos+dp->offset;
195 int epos = pos+dp->offset+dp->length-1;
199 if (!(*fpp = malloc (sizeof(**fpp))))
207 if (p->indicator_length)
210 if (buf[dpos+p->indicator_length] != ISO2709_IDFS)
213 if (!memcmp (dp->tag, "00", 2))
217 else if (!memcmp (dp->tag, "00", 2))
219 if (identifier_flag && p->indicator_length)
221 if (!(dp->indicator = malloc (p->indicator_length+1)))
226 strncpyx (dp->indicator, buf+dpos, p->indicator_length);
227 dpos += p->indicator_length;
230 dp->indicator = NULL;
234 if (p->identifier_length && identifier_flag)
236 strncpyx ((*fpp)->identifier, buf+dpos+1,
237 p->identifier_length-1);
238 dpos_n = dpos += p->identifier_length;
239 while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_RS
240 && buf[dpos_n] != ISO2709_IDFS && dpos_n < epos)
245 *(*fpp)->identifier = '\0';
247 while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_RS
251 if (!((*fpp)->data = malloc (dpos_n - dpos + 1)))
256 strncpyx ((*fpp)->data, buf+dpos, dpos_n - dpos);
261 if (buf[dpos] != ISO2709_FS && buf[dpos] != ISO2709_RS)
262 fprintf (stderr, "Missing separator at end of field "
263 "in %s %s\n", dp->tag, (*fpp)->identifier);
266 if (buf[dpos] == ISO2709_FS || buf[dpos] == ISO2709_RS)
268 fprintf (stderr, "Unexpected separator inside field %s %s\n",
269 dp->tag, (*fpp)->identifier);
273 if (!(*fpp = malloc (sizeof(**fpp))))
284 void iso2709_rm (Iso2709Rec rec)
286 struct iso2709_dir *dir, *dir1;
288 for (dir = rec->directory; dir; dir = dir1)
290 struct iso2709_field *field, *field1;
292 for (field = dir->fields; field; field = field1)
295 field1 = field->next;
298 free (dir->indicator);