source: trunk/gsdl/packages/d2m/MARC2709.c@ 10435

Last change on this file since 10435 was 10385, checked in by kjdon, 19 years ago

a few changes to get it compiling on windows

  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/* ------------------------------------------------------------------- */
2/* MARC2709 : Converts a "line format MARC record" into ISO 2709 */
3/* */
4/* Input string requirements: */
5/* 1. New MARC tag is indicated by MARC tag in pos 1-3 */
6/* (may be preceded by *). Indicator follows in next 2 */
7/* bytes. */
8/* 2. Continuation line is indicated by blank in col 1 */
9/* 3. End-of-record (^) may or may not be present */
10/* */
11/* author : Ole Husby */
12/* updated : 1998-09-30 */
13/* ------------------------------------------------------------------- */
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <ctype.h>
19
20#define NORMARC 12
21
22#define SUBFIELD_CODE "\x1f"
23#define FIELD_TERMINATOR "\x1e"
24#define RECORD_TERMINATOR "\x1d"
25
26#define INDICATOR_COUNT '2'
27#define SUBFIELD_CODE_COUNT '2'
28#define LENGTH_OF_LENGTH_OF_FIELD '4'
29#define LENGTH_OF_STARTING_CHARACTER_POSITION '5'
30#define UNUSED " "
31#define TAG001 "001"
32#define TAG008 "008"
33#define SKIP 41
34
35static char out_record[10240],
36 leader[24+1],
37 directory[10240],
38 field_001[32],
39 field_008[40+2],
40 data_field[10240];
41
42
43static char logline[128];
44static char rstr[6], dollar, dollarstring[2];
45static int skip;
46
47static char direlem[300][12+1];
48static int dircntr;
49
50union LDR {
51 char ldr_string[24+1];
52 struct {
53 char record_length[5],
54 record_status,
55 record_type,
56 bibliographic_level,
57 unused1[2],
58 indicator_count,
59 subfield_code_count,
60 base_adress[5],
61 unused2[3],
62 entry1,
63 entry2,
64 entry3,
65 entry4;
66 } ltab;
67 } ldr;
68
69static int startet = 0;
70
71
72
73/* ------------------------------------------------------------------- */
74/* Compare function for qsort */
75/* ------------------------------------------------------------------- */
76
77int cmp(const void *a, const void *b)
78{
79 return strcmp((char*)a, (char*)b);
80}
81
82
83
84
85/* ------------------------------------------------------------------- */
86/* Convert integer to string of fixed length. Right justified padded */
87/* with zeros. Returns NULL if error */
88/* ------------------------------------------------------------------- */
89
90char *itoal(int n, int len)
91{
92 char *r;
93 r = (char *) rstr;
94
95 switch (len)
96 {
97 case 4 : sprintf(r, "%04d", n); break;
98 case 5 : sprintf(r, "%05d", n); break;
99 default : return NULL;
100 }
101
102 r[len] = '\0';
103
104 return r;
105}
106
107
108
109/* ------------------------------------------------------------------- */
110/* One 001 subfield is put into field_001 */
111/* ------------------------------------------------------------------- */
112
113static int make_001(char *data, char subfield)
114{
115 int len;
116
117 startet = 0;
118 switch (subfield)
119 {
120 case ' ' : break;
121 case 'a' : break;
122 default : return 1;
123 }
124
125 while (data[0] == ' ') data++;
126 strcpy(field_001, data);
127
128 len = strlen(data) + 1;
129 skip = SKIP + len;
130
131 sprintf(directory, "00100%2d000000080041000%2d", len, len);
132 return 1;
133}
134
135
136
137/* ------------------------------------------------------------------- */
138/* One subfield string is appended to data_field */
139/* ------------------------------------------------------------------- */
140
141static int out_subfield(char *data, char *ftag, char subfield, char nextsubfield)
142{
143 int len, subint;
144 char subreplace, *p, *up;
145
146 while (data[strlen(data) -1] == ' ')
147 data[strlen(data) -1] = '\0'; /* strip trailing blanks */
148
149 if (subfield == '3') /* always discard $3 */
150 return 1;
151
152 if (strcmp(ftag, TAG001) == 0) /* 001 data treatment */
153 {
154 make_001(data, subfield);
155 return 1;
156 }
157
158 if (strcmp(ftag, TAG008) == 0) /* 008 data treatment */
159 {
160 strncpy(field_008, data, strlen(data));
161 return 1;
162 }
163
164 if (subfield != ' ') /* handle subfield code */
165 {
166 strcat(data_field, SUBFIELD_CODE);
167 len = strlen(data_field);
168 data_field[len] = subfield;
169 data_field[len + 1] = '\0';
170 }
171
172 while(data[0] == ' ') data++; /* strip leading blanks */
173 if (!data) return 0;
174
175 strcat(data_field, data); /* append data */
176
177 return 1;
178}
179
180
181
182/* ------------------------------------------------------------------- */
183/* One MARC field is split into subfields and given to output */
184/* ------------------------------------------------------------------- */
185
186static int out_field(char *data, char *ftag, char *find)
187{
188 char lnumber[5], snumber[6];
189 int fStart, fLen, moresubs;
190 char subfield[5120], *sub, subcode, *nextsub, nextsubcode;
191 char *v, subfield_v[32];
192
193 if (!startet) return 1;
194
195 if ((strncmp(ftag, "00", 2) == 0) &&
196 (strcmp(ftag, TAG001) != 0) &&
197 (strcmp(ftag, TAG008) != 0))
198 return 1;
199
200 fStart = strlen(data_field);
201
202 if (strncmp(data, " $", 3) == 0) data +=2; /* possible if 008 */
203
204 if (data[0] != dollar) /* Dollar sign missing */
205 {
206 if (strncmp(ftag,"00",2) != 0) return 0; /* only allowed if tag=00x */
207
208 if (strcmp(ftag, TAG001) == 0) /* 001: skip leading blanks */
209 while (data[0] == ' ')
210 data++;
211
212 subcode = ' ';
213 nextsubcode = ' ';
214
215 if (!out_subfield(data, ftag, subcode, nextsubcode))
216 return 0;
217 return 1;
218 }
219
220 else
221 {
222 data++;
223
224 if (!data) return 0;
225
226 if (strncmp(ftag,"00",2) != 0) /* append indicators */
227 strcat(data_field, find);
228
229 sub = strtok(data, dollarstring); /* first subfield */
230 if (!sub)
231 return 0;
232
233/* printf("--- %s\n", sub); */
234
235 subcode = sub[0];
236 sub++;
237
238 moresubs = 1;
239
240 while (moresubs) /* loop while more subflds */
241 {
242 nextsub = strtok(NULL, dollarstring); /* next subfld */
243 if (nextsub)
244 {
245/* printf("--- %s\n", nextsub); */
246 nextsubcode = nextsub[0];
247 nextsub++;
248 }
249 else
250 nextsubcode = ' ';
251
252 if (sub)
253 {
254 if (!out_subfield(sub, ftag, subcode, nextsubcode))
255 return 0;
256/* printf("Denne |%c| Neste |%c|\n", subcode, nextsubcode); */
257 }
258
259 if (nextsub)
260 {
261 subcode = nextsubcode;
262 sub = nextsub;
263 }
264 else
265 moresubs = 0;
266 }
267 }
268
269 if (strcmp(ftag,TAG001) == 0 || strcmp(ftag,TAG008) == 0)
270 return 1; /* directory ready */
271
272 strcat(data_field, FIELD_TERMINATOR); /* terminate data field */
273 fLen = strlen(data_field) - fStart; /* length of field */
274
275 strcpy(lnumber,itoal(fLen,4)); /* convert to 4digit str */
276 if (!lnumber) return 0;
277 strcpy(snumber,itoal(fStart + skip,5)); /* convert start */
278 if (!snumber) return 0;
279
280 strcpy(direlem[dircntr], ftag); /* start direlem with tag */
281 strcat(direlem[dircntr], lnumber); /* append length to dir */
282 strcat(direlem[dircntr], snumber); /* append start to dir */
283 dircntr++;
284
285 return 1;
286}
287
288
289
290/* ------------------------------------------------------------------- */
291/* Main program */
292/* ------------------------------------------------------------------- */
293
294char *MARC2709(char *record, int last, int first, char recstatus,
295 char rectype, char biblevel)
296{
297 static char buffer[10240], field_data[5120], tag[4], ind[3];
298 char alen[3], *cp, *buf = buffer, *cq, logline[128];
299 int prelen, ii;
300 int lastchar, Last, First, x, more;
301 int SOF, digits, newField;
302
303 char test[6];
304
305 strcpy(buf, record);
306
307 Last = First = 0; /* initialize */
308 if (last > 0) /* Last : linelength if */
309 { /* fixed */
310 Last = last; /* First: starting col */
311 First = first; /* for cont. line */
312 }
313
314 prelen = 5;
315 dollar = '$';
316 strcpy(dollarstring, "$");
317
318 data_field[0] = '\0';
319 directory[0] = '\0';
320 strcpy(field_001, " ");
321 strcpy(field_008, " ");
322 out_record[0] = '\0';
323 dircntr = 0;
324 startet = 0;
325
326 /* initialize directory with 9 bytes for 001 */
327
328 sprintf(directory, "001001000000008004100010", alen, alen);
329 skip = SKIP + 10;
330
331 more = 1;
332 while (more) /* loop until EOR */
333 {
334 x = 0; /* x counts bytes */
335
336 for (cp = buf; *cp && *cp != '\n'; cp++) x++; /* read until LF */
337
338 if (!*cp) /* EOR */
339 more = 0;
340 else
341 cp++;
342
343 SOF = 0;
344
345 if (buf[0] == '^') break; /* "EOR-line" */
346 if (buf[0] == '*') /* skip leading * */
347 {
348 buf++;
349 x--;
350 SOF = 1;
351 }
352
353 if (x == 0) continue; /* empty line */
354
355 digits = 1; /* test if first 3 */
356 for (ii = 0; ii < 3; ii++) /* bytes are digits */
357 if (!isdigit(buf[ii]))
358 {
359 digits = 0;
360 break;
361 }
362
363 newField = 0;
364
365 if (SOF)
366 {
367 if (!digits) continue; /* illegal line */
368 else newField = 1;
369 }
370 else
371 if (digits) newField = 1;
372
373
374 if (newField) /* start of new field */
375 {
376 if (!out_field(field_data, tag, ind)) /* output prev. field */
377 return NULL;
378
379 startet = 1;
380 field_data[0] = '\0'; /* reset field buffer */
381 strncpy(tag, buf, 3); /* keep MARC tag */
382 buf += 3;
383 x -=3;
384
385 if (strncmp(tag, "00", 2) != 0)
386 {
387 strncpy(ind, buf, 2); /* keep indicator */
388 buf += 2; /* if not control field */
389 x -= 2;
390 }
391
392 strncat(field_data, buf, x); /* keep data */
393
394 /* strip trailing blanks */
395 while (field_data[strlen(field_data) -1] == ' ')
396 {
397 field_data[strlen(field_data) -1] = '\0';
398 x--;
399 }
400
401 if (Last && x == (Last - prelen)) /* full line */
402 lastchar = 1;
403 else
404 lastchar = 0;
405 }
406
407 else /* continuation line */
408 {
409 if (Last)
410 {
411 cq = buf + First - 1; /* skip fixed nmbr chars */
412 x -= (First - 1);
413 if (!lastchar && cq[0] != ' ' /* and insert one blank */
414 && cq[0] != dollar)
415 strcat(field_data, " "); /* if needed */
416 }
417 else
418 {
419 for (cq = buf; *cq == ' '; cq++) x--; /* skip leading blanks */
420 strcat(field_data, " "); /* insert one blank */
421 }
422
423 strncat(field_data, cq, x); /* append data */
424 /* strip trail. blanks */
425 while (field_data[strlen(field_data) -1] == ' ')
426 {
427 field_data[strlen(field_data) -1] = '\0';
428 x--;
429 }
430
431 if (Last && x == (Last - 5)) /* full line */
432 lastchar = 1;
433 else lastchar = 0;
434
435 }
436
437 while (field_data[strlen(field_data) -1] == ' ')
438 field_data[strlen(field_data) - 1] = '\0'; /* rm trailing blanks */
439 buf = cp;
440 }
441
442 if (!out_field(field_data, tag, ind)) /* output last field */
443 return NULL;
444
445 /* terminate field_001 */
446 strcat(field_001, FIELD_TERMINATOR);
447
448 field_008[40] = '\0'; /* terminate field_008 */
449 strcat(field_008, FIELD_TERMINATOR);
450
451 /* sort directory elem. */
452 qsort ((void *) direlem, dircntr, sizeof(direlem[0]), cmp);
453 for (ii = 0; ii < dircntr; ii++)
454 strcat(directory, direlem[ii]); /* append to directory */
455
456 strcat(directory, FIELD_TERMINATOR); /* terminate dictionary */
457
458 strcat(data_field, RECORD_TERMINATOR); /* terminate data */
459
460 x = 24 + strlen(directory); /* construct leader */
461
462 strcpy(test, itoal(x,5));
463
464 strncpy(ldr.ltab.base_adress, test, 5);
465
466 x += (strlen(data_field)
467 + strlen(field_001)
468 + strlen(field_008));
469
470 strcpy(test, itoal(x,5));
471
472 strncpy(ldr.ltab.record_length, test, 5);
473
474 ldr.ltab.record_status = recstatus;
475 ldr.ltab.record_type = rectype;
476 ldr.ltab.bibliographic_level = biblevel;
477 ldr.ltab.indicator_count = INDICATOR_COUNT;
478 ldr.ltab.subfield_code_count = SUBFIELD_CODE_COUNT;
479 strncpy(ldr.ltab.unused1,UNUSED,2);
480 strncpy(ldr.ltab.unused2,UNUSED,3);
481 ldr.ltab.entry1 = LENGTH_OF_LENGTH_OF_FIELD;
482 ldr.ltab.entry2 = LENGTH_OF_STARTING_CHARACTER_POSITION;
483 ldr.ltab.entry3 = '0';
484 ldr.ltab.entry4 = '0';
485
486 ldr.ldr_string[24] = '\0';
487
488 strcpy(out_record, ldr.ldr_string); /* put together record */
489 strcat(out_record, directory);
490 strcat(out_record, field_001);
491 strcat(out_record, field_008);
492 strcat(out_record, data_field);
493
494 return out_record;
495}
Note: See TracBrowser for help on using the repository browser.