IDZEBRA  2.2.7
mod_grs_marc.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <assert.h>
26 
27 #include <yaz/yaz-util.h>
28 #include <yaz/snprintf.h>
29 #include <yaz/marcdisp.h>
30 #include <idzebra/recgrs.h>
31 #include "marcomp.h"
32 #include "inline.h"
33 
34 #define MARC_DEBUG 0
35 #define MARCOMP_DEBUG 0
36 
37 struct marc_info {
38  char type[256];
39 };
40 
41 static data1_node *grs_read_iso2709(struct grs_read_info *p, int marc_xml)
42 {
43  struct marc_info *mi = (struct marc_info*) p->clientData;
44  char buf[100000];
45  int entry_p;
46  int record_length;
47  int indicator_length;
48  int identifier_length;
49  int base_address;
50  int end_of_directory;
51  int length_data_entry;
52  int length_starting;
53  int read_bytes;
54 #if MARC_DEBUG
55  FILE *outf = stdout;
56 #endif
57  data1_node *res_root, *res_top;
58  char *absynName;
59  data1_marctab *marctab;
60 
61  if (p->stream->readf(p->stream, buf, 5) != 5)
62  return NULL;
63  while (*buf < '0' || *buf > '9')
64  {
65  int i;
66 
67  yaz_log(YLOG_WARN, "MARC: Skipping bad byte %d (0x%02X)",
68  *buf & 0xff, *buf & 0xff);
69  for (i = 0; i < 4; i++)
70  buf[i] = buf[i+1];
71 
72  if (p->stream->readf(p->stream, buf+4, 1) != 1)
73  return NULL;
74  }
75  record_length = atoi_n(buf, 5);
76  if (record_length < 25)
77  {
78  yaz_log(YLOG_WARN, "MARC record length < 25, is %d", record_length);
79  return NULL;
80  }
81 
82  read_bytes = p->stream->readf(p->stream, buf+5, record_length-5);
83  if (read_bytes < record_length-5)
84  {
85  yaz_log(YLOG_WARN, "Couldn't read whole MARC record");
86  return NULL;
87  }
88  /* skip until we meet a record separator */
89  while (buf[record_length-1] != ISO2709_RS)
90  {
91  if (record_length > sizeof(buf)-2)
92  break;
93  read_bytes = p->stream->readf(p->stream, buf+record_length, 1);
94  if (read_bytes != 1)
95  break;
96  record_length++;
97  }
98  /* read one byte ahead to see if there is more ... */
99  read_bytes = p->stream->readf(p->stream, buf+record_length, 1);
100  if (read_bytes == 1)
101  {
102  off_t cur_offset = p->stream->tellf(p->stream);
103  if (p->stream->endf)
104  {
105  off_t end_offset = cur_offset - 1;
106  p->stream->endf(p->stream, &end_offset);
107  }
108  }
109 
110  absynName = mi->type;
111  res_root = data1_mk_root(p->dh, p->mem, absynName);
112  if (!res_root)
113  {
114  yaz_log(YLOG_WARN, "cannot read MARC without an abstract syntax");
115  return 0;
116  }
117  if (marc_xml)
118  {
119  data1_node *lead;
120  const char *attr[] = { "xmlns", "http://www.loc.gov/MARC21/slim", 0};
121 
122  res_top = data1_mk_tag(p->dh, p->mem, "record", attr, res_root);
123 
124  lead = data1_mk_tag(p->dh, p->mem, "leader", 0, res_top);
125  data1_mk_text_n(p->dh, p->mem, buf, 24, lead);
126  }
127  else
128  res_top = data1_mk_tag(p->dh, p->mem, absynName, 0, res_root);
129 
130  if ((marctab = data1_absyn_getmarctab(p->dh, res_root)))
131  {
132  memcpy(marctab->leader, buf, 24);
133  memcpy(marctab->implementation_codes, buf+6, 4);
134  marctab->implementation_codes[4] = '\0';
135  memcpy(marctab->user_systems, buf+17, 3);
136  marctab->user_systems[3] = '\0';
137  }
138 
139  if (marctab && marctab->force_indicator_length >= 0)
140  indicator_length = marctab->force_indicator_length;
141  else
142  indicator_length = atoi_n(buf+10, 1);
143  if (marctab && marctab->force_identifier_length >= 0)
144  identifier_length = marctab->force_identifier_length;
145  else
146  identifier_length = atoi_n(buf+11, 1);
147  base_address = atoi_n(buf+12, 5);
148 
149  length_data_entry = atoi_n(buf+20, 1);
150  length_starting = atoi_n(buf+21, 1);
151 
152  for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
153  {
154  int l = 3 + length_data_entry + length_starting;
155  if (entry_p + l >= record_length)
156  {
157  yaz_log(YLOG_WARN, "MARC: Directory offset %d: end of record.",
158  entry_p);
159  return 0;
160  }
161  /* check for digits in length info */
162  while (--l >= 3)
163  if (!isdigit(*(const unsigned char *) (buf + entry_p+l)))
164  break;
165  if (l >= 3)
166  {
167  /* not all digits, so stop directory scan */
168  yaz_log(YLOG_LOG, "MARC: Bad directory");
169  break;
170  }
171  entry_p += 3 + length_data_entry + length_starting;
172  }
173  end_of_directory = entry_p;
174  if (base_address != entry_p+1)
175  {
176  yaz_log(YLOG_WARN, "MARC: Base address does not follow directory");
177  }
178  for (entry_p = 24; entry_p != end_of_directory; )
179  {
180  int data_length;
181  int data_offset;
182  int end_offset;
183  int i, i0;
184  char tag[4];
185  data1_node *res;
186  data1_node *parent = res_top;
187 
188  memcpy(tag, buf+entry_p, 3);
189  entry_p += 3;
190  tag[3] = '\0';
191 
192  if (marc_xml)
193  res = parent;
194  else
195  res = data1_mk_tag_n(p->dh, p->mem, tag, 3, 0 /* attr */, parent);
196 
197 #if MARC_DEBUG
198  fprintf(outf, "%s ", tag);
199 #endif
200  data_length = atoi_n(buf+entry_p, length_data_entry);
201  entry_p += length_data_entry;
202  data_offset = atoi_n(buf+entry_p, length_starting);
203  entry_p += length_starting;
204  i = data_offset + base_address;
205  end_offset = i+data_length-1;
206 
207  if (data_length <= 0 || data_offset < 0 || end_offset >= record_length)
208  {
209  yaz_log(YLOG_WARN, "MARC: Bad offsets in data. Skipping rest");
210  break;
211  }
212 
213  if (memcmp(tag, "00", 2) && indicator_length)
214  {
215  /* generate indicator node */
216  if (marc_xml)
217  {
218  const char *attr[10];
219  int j;
220 
221  attr[0] = "tag";
222  attr[1] = tag;
223  attr[2] = 0;
224 
225  res = data1_mk_tag(p->dh, p->mem, "datafield", attr, res);
226 
227  for (j = 0; j < indicator_length; j++)
228  {
229  char str1[18], str2[2];
230  yaz_snprintf(str1, sizeof(str1), "ind%d", j+1);
231  str2[0] = buf[i+j];
232  str2[1] = '\0';
233 
234  attr[0] = str1;
235  attr[1] = str2;
236 
237  data1_tag_add_attr(p->dh, p->mem, res, attr);
238  }
239  }
240  else
241  {
242 #if MARC_DEBUG
243  int j;
244 #endif
245  res = data1_mk_tag_n(p->dh, p->mem, buf+i,
246  indicator_length, 0 /* attr */, res);
247 #if MARC_DEBUG
248  for (j = 0; j < indicator_length; j++)
249  fprintf(outf, "%c", buf[j+i]);
250 #endif
251  }
252  i += indicator_length;
253  }
254  else
255  {
256  if (marc_xml)
257  {
258  const char *attr[10];
259 
260  attr[0] = "tag";
261  attr[1] = tag;
262  attr[2] = 0;
263 
264  res = data1_mk_tag(p->dh, p->mem, "controlfield", attr, res);
265  }
266  }
267  parent = res;
268  /* traverse sub fields */
269  i0 = i;
270  while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
271  {
272  if (memcmp (tag, "00", 2) && identifier_length)
273  {
274  int j;
275  data1_node *res;
276  if (marc_xml)
277  {
278  const char *attr[3];
279  char code[10];
280 
281  for (j = 1; j < identifier_length && j < 9; j++)
282  code[j-1] = buf[i+j];
283  code[j-1] = 0;
284  attr[0] = "code";
285  attr[1] = code;
286  attr[2] = 0;
287  res = data1_mk_tag(p->dh, p->mem, "subfield",
288  attr, parent);
289  }
290  else
291  {
292  res = data1_mk_tag_n(p->dh, p->mem,
293  buf+i+1, identifier_length-1,
294  0 /* attr */, parent);
295  }
296 #if MARC_DEBUG
297  fprintf (outf, " $");
298  for (j = 1; j < identifier_length; j++)
299  fprintf(outf, "%c", buf[j+i]);
300  fprintf(outf, " ");
301 #endif
302  i += identifier_length;
303  i0 = i;
304  while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
305  buf[i] != ISO2709_FS && i < end_offset)
306  {
307 #if MARC_DEBUG
308  fprintf(outf, "%c", buf[i]);
309 #endif
310  i++;
311  }
312  data1_mk_text_n(p->dh, p->mem, buf + i0, i - i0, res);
313  i0 = i;
314  }
315  else
316  {
317 #if MARC_DEBUG
318  fprintf(outf, "%c", buf[i]);
319 #endif
320  i++;
321  }
322  }
323  if (i > i0)
324  {
325  data1_mk_text_n(p->dh, p->mem, buf + i0, i - i0, parent);
326  }
327 #if MARC_DEBUG
328  fprintf (outf, "\n");
329  if (i < end_offset)
330  fprintf(outf, "-- separator but not at end of field\n");
331  if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
332  fprintf(outf, "-- no separator at end of field\n");
333 #endif
334  }
335  return res_root;
336 }
337 
338 /*
339  * Locate some data under this node. This routine should handle variants
340  * prettily.
341  */
342 static char *get_data(data1_node *n, int *len)
343 {
344  char *r;
345 
346  while (n)
347  {
348  if (n->which == DATA1N_data)
349  {
350  int i;
351  *len = n->u.data.len;
352 
353  for (i = 0; i < *len; i++)
354  if (!d1_isspace(n->u.data.data[i]))
355  break;
356  while (*len && d1_isspace(n->u.data.data[*len - 1]))
357  (*len)--;
358  *len = *len - i;
359  if (*len > 0)
360  return n->u.data.data + i;
361  }
362  if (n->which == DATA1N_tag)
363  n = n->child;
364  else if (n->which == DATA1N_data)
365  n = n->next;
366  else
367  break;
368  }
369  r = "";
370  *len = strlen(r);
371  return r;
372 }
373 
374 static data1_node *lookup_subfield(data1_node *node, const char *name)
375 {
376  data1_node *p;
377 
378  for (p = node; p; p = p->next)
379  {
380  if (!yaz_matchstr(p->u.tag.tag, name))
381  return p;
382  }
383  return 0;
384 }
385 
387  const char *name)
388 {
389  inline_subfield *p;
390 
391  for (p = pisf; p; p = p->next)
392  {
393  if (!yaz_matchstr(p->name, name))
394  return p;
395  }
396  return 0;
397 }
398 
400  inline_subfield *pisf)
401 {
402  mc_subfield *p;
403 
404  for (p = psf; p && pisf; p = p->next)
405  {
406  if (p->which == MC_SF)
407  {
408  inline_subfield *found = lookup_inline_subfield(pisf, p->name);
409 
410  if (found)
411  {
412  if (strcmp(p->prefix, "_"))
413  {
414  wrbuf_puts(buf, " ");
415  wrbuf_puts(buf, p->prefix);
416  }
417  if (p->interval.start == -1)
418  {
419  wrbuf_puts(buf, found->data);
420  }
421  else
422  {
423  wrbuf_write(buf, found->data+p->interval.start,
424  p->interval.end-p->interval.start);
425  wrbuf_puts(buf, "");
426  }
427  if (strcmp(p->suffix, "_"))
428  {
429  wrbuf_puts(buf, p->suffix);
430  wrbuf_puts(buf, " ");
431  }
432 #if MARCOMP_DEBUG
433  yaz_log(YLOG_LOG, "cat_inline_subfield(): add subfield $%s", found->name);
434 #endif
435  pisf = found->next;
436  }
437  }
438  else if (p->which == MC_SFVARIANT)
439  {
440  inline_subfield *next;
441 
442  do {
443  next = cat_inline_subfield(p->u.child, buf, pisf);
444  if (next == pisf)
445  break;
446  pisf = next;
447  } while (pisf);
448  }
449  else if (p->which == MC_SFGROUP)
450  {
451  mc_subfield *pp;
452  int found;
453 
454  for (pp = p->u.child, found = 0; pp; pp = pp->next)
455  {
456  if (!yaz_matchstr(pisf->name, p->name))
457  {
458  found = 1;
459  break;
460  }
461  }
462  if (found)
463  {
464  wrbuf_puts(buf, " (");
465  pisf = cat_inline_subfield(p->u.child, buf, pisf);
466  wrbuf_puts(buf, ") ");
467  }
468  }
469  }
470  return pisf;
471 }
472 
473 static void cat_inline_field(mc_field *pf, WRBUF buf, data1_node *subfield)
474 {
475  if (!pf || !subfield)
476  return;
477 
478  for (;subfield;)
479  {
480  int len;
481  inline_field *pif=NULL;
482  data1_node *psubf;
483 
484  if (yaz_matchstr(subfield->u.tag.tag, "1"))
485  {
486  subfield = subfield->next;
487  continue;
488  }
489 
490  psubf = subfield;
491  pif = inline_mk_field();
492  do
493  {
494  int i;
495  if ((i=inline_parse(pif, psubf->u.tag.tag, get_data(psubf, &len)))<0)
496  {
497  yaz_log(YLOG_WARN, "inline subfield ($%s): parse error",
498  psubf->u.tag.tag);
500  return;
501  }
502  psubf = psubf->next;
503  } while (psubf && yaz_matchstr(psubf->u.tag.tag, "1"));
504 
505  subfield = psubf;
506 
507  if (pif && !yaz_matchstr(pif->name, pf->name))
508  {
509  if (!pf->list && pif->list)
510  {
511  wrbuf_puts(buf, pif->list->data);
512  }
513  else
514  {
515  int ind1, ind2;
516 
517  /*
518  check indicators
519  */
520 
521  ind1 = (pif->ind1[0] == ' ') ? '_':pif->ind1[0];
522  ind2 = (pif->ind2[0] == ' ') ? '_':pif->ind2[0];
523 
524  if (((pf->ind1[0] == '.') || (ind1 == pf->ind1[0])) &&
525  ((pf->ind2[0] == '.') || (ind2 == pf->ind2[0])))
526  {
527  cat_inline_subfield(pf->list, buf, pif->list);
528 
529  /*
530  add separator for inline fields
531  */
532  if (wrbuf_len(buf))
533  {
534  wrbuf_puts(buf, "\n");
535  }
536  }
537  else
538  {
539  yaz_log(YLOG_WARN, "In-line field %s missed -- indicators do not match", pif->name);
540  }
541  }
542  }
544  }
545 #if MARCOMP_DEBUG
546  yaz_log(YLOG_LOG, "cat_inline_field(): got buffer {%s}", wrbuf_cstr(buf));
547 #endif
548 }
549 
550 static data1_node *cat_subfield(mc_subfield *psf, WRBUF buf,
551  data1_node *subfield)
552 {
553  mc_subfield *p;
554 
555  for (p = psf; p && subfield; p = p->next)
556  {
557  if (p->which == MC_SF)
558  {
559  data1_node *found = lookup_subfield(subfield, p->name);
560 
561  if (found)
562  {
563  int len;
564 
565  if (strcmp(p->prefix, "_"))
566  {
567  wrbuf_puts(buf, " ");
568  wrbuf_puts(buf, p->prefix);
569  }
570 
571  if (p->u.in_line)
572  {
573  cat_inline_field(p->u.in_line, buf, found);
574  }
575  else if (p->interval.start == -1)
576  {
577  wrbuf_puts(buf, get_data(found, &len));
578  }
579  else
580  {
581  wrbuf_write(buf, get_data(found, &len)+p->interval.start,
582  p->interval.end-p->interval.start);
583  wrbuf_puts(buf, "");
584  }
585  if (strcmp(p->suffix, "_"))
586  {
587  wrbuf_puts(buf, p->suffix);
588  wrbuf_puts(buf, " ");
589  }
590 #if MARCOMP_DEBUG
591  yaz_log(YLOG_LOG, "cat_subfield(): add subfield $%s", found->u.tag.tag);
592 #endif
593  subfield = found->next;
594  }
595  }
596  else if (p->which == MC_SFVARIANT)
597  {
598  data1_node *next;
599  do {
600  next = cat_subfield(p->u.child, buf, subfield);
601  if (next == subfield)
602  break;
603  subfield = next;
604  } while (subfield);
605  }
606  else if (p->which == MC_SFGROUP)
607  {
608  mc_subfield *pp;
609  int found;
610 
611  for (pp = p->u.child, found = 0; pp; pp = pp->next)
612  {
613  if (!yaz_matchstr(subfield->u.tag.tag, pp->name))
614  {
615  found = 1;
616  break;
617  }
618  }
619  if (found)
620  {
621  wrbuf_puts(buf, " (");
622  subfield = cat_subfield(p->u.child, buf, subfield);
623  wrbuf_puts(buf, ") ");
624  }
625  }
626  }
627  return subfield;
628 }
629 
631  WRBUF buf, data1_node *field)
632 {
633  data1_node *subfield;
634  int ind1, ind2;
635 
636  if (!pf || !field)
637  return 0;
638 
639 
640  if (yaz_matchstr(field->u.tag.tag, pf->name))
641  return field->next;
642 
643  subfield = field->child;
644 
645  if (!subfield)
646  return field->next;
647 
648  /*
649  check subfield without indicators
650  */
651 
652  if (!pf->list && subfield->which == DATA1N_data)
653  {
654  int len;
655 
656  if (pf->interval.start == -1)
657  {
658  wrbuf_puts(buf, get_data(field, &len));
659  }
660  else
661  {
662  wrbuf_write(buf, get_data(field, &len)+pf->interval.start,
663  pf->interval.end-pf->interval.start);
664  wrbuf_puts(buf, "");
665  }
666 #if MARCOMP_DEBUG
667  yaz_log(YLOG_LOG, "cat_field(): got buffer {%s}", wrbuf_cstr(buf));
668 #endif
669  return field->next;
670  }
671 
672  /*
673  check indicators
674  */
675 
676  ind1 = (subfield->u.tag.tag[0] == ' ') ? '_':subfield->u.tag.tag[0];
677  ind2 = (subfield->u.tag.tag[1] == ' ') ? '_':subfield->u.tag.tag[1];
678 
679  if (!(
680  ((pf->ind1[0] == '.') || (ind1 == pf->ind1[0])) &&
681  ((pf->ind2[0] == '.') || (ind2 == pf->ind2[0]))
682  ))
683  {
684 #if MARCOMP_DEBUG
685  yaz_log(YLOG_WARN, "Field %s missed -- does not match indicators", field->u.tag.tag);
686 #endif
687  return field->next;
688  }
689 
690  subfield = subfield->child;
691 
692  if (!subfield)
693  return field->next;
694 
695  cat_subfield(pf->list, buf, subfield);
696 
697 #if MARCOMP_DEBUG
698  yaz_log(YLOG_LOG, "cat_field(): got buffer {%s}", wrbuf_cstr(buf));
699 #endif
700 
701  return field->next;
702 }
703 
704 static int is_empty(char *s)
705 {
706  char *p = s;
707 
708  for (p = s; *p; p++)
709  {
710  if (!isspace(*(unsigned char *)p))
711  return 0;
712  }
713  return 1;
714 }
715 
716 static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt,
717  data1_node *root)
718 {
719  data1_marctab *marctab = data1_absyn_getmarctab(p->dh, root);
720  data1_node *top = root->child;
721  data1_node *field;
722  mc_context *c;
723  mc_field *pf;
724  WRBUF buf;
725 
726  c = mc_mk_context(mc_stmnt+3);
727 
728  if (!c)
729  return;
730 
731  pf = mc_getfield(c);
732 
733  if (!pf)
734  {
736  return;
737  }
738  buf = wrbuf_alloc();
739 #if MARCOMP_DEBUG
740  yaz_log(YLOG_LOG, "parse_data1_tree(): statement -{%s}", mc_stmnt);
741 #endif
742  if (!yaz_matchstr(pf->name, "ldr"))
743  {
744  data1_node *new;
745 #if MARCOMP_DEBUG
746  yaz_log(YLOG_LOG,"parse_data1_tree(): try LEADER from {%d} to {%d} positions",
747  pf->interval.start, pf->interval.end);
748 #endif
749  if (marctab)
750  {
751  new = data1_mk_tag_n(p->dh, p->mem, mc_stmnt, strlen(mc_stmnt), 0, top);
752  data1_mk_text_n(p->dh, p->mem, marctab->leader+pf->interval.start,
753  pf->interval.end-pf->interval.start+1, new);
754  }
755  }
756  else
757  {
758  field=top->child;
759 
760  while (field)
761  {
762  if (!yaz_matchstr(field->u.tag.tag, pf->name))
763  {
764  data1_node *new;
765  char *pb;
766 #if MARCOMP_DEBUG
767  yaz_log(YLOG_LOG, "parse_data1_tree(): try field {%s}", field->u.tag.tag);
768 #endif
769  wrbuf_rewind(buf);
770  wrbuf_puts(buf, "");
771 
772  field = cat_field(p, pf, buf, field);
773 
774  wrbuf_cstr(buf);
775  pb = wrbuf_buf(buf);
776  for (pb = strtok(pb, "\n"); pb; pb = strtok(NULL, "\n"))
777  {
778  if (!is_empty(pb))
779  {
780  new = data1_mk_tag_n(p->dh, p->mem, mc_stmnt, strlen(mc_stmnt), 0, top);
781  data1_mk_text_n(p->dh, p->mem, pb, strlen(pb), new);
782  }
783  }
784  }
785  else
786  {
787  field = field->next;
788  }
789  }
790  }
791  mc_destroy_field(pf);
793  wrbuf_destroy(buf);
794 }
795 
797 {
798  data1_node *root = grs_read_iso2709(p, 1);
799  data1_element *e;
800 
801  if (!root)
802  return 0;
803 
804  for (e = data1_absyn_getelements(p->dh, root); e; e=e->next)
805  {
806  data1_tag *tag = e->tag;
807 
808  if (tag && tag->which == DATA1T_string &&
809  !yaz_matchstr(tag->value.string, "mc?"))
810  parse_data1_tree(p, tag->value.string, root);
811  }
812  return root;
813 }
814 
816 {
817  data1_node *root = grs_read_iso2709(p, 0);
818  data1_element *e;
819 
820  if (!root)
821  return 0;
822 
823  for (e = data1_absyn_getelements(p->dh, root); e; e=e->next)
824  {
825  data1_tag *tag = e->tag;
826 
827  if (tag && tag->which == DATA1T_string &&
828  !yaz_matchstr(tag->value.string, "mc?"))
829  parse_data1_tree(p, tag->value.string, root);
830  }
831  return root;
832 }
833 
834 static void *init_marc(Res res, RecType rt)
835 {
836  struct marc_info *p = xmalloc(sizeof(*p));
837  strcpy(p->type, "");
838  return p;
839 }
840 
841 static ZEBRA_RES config_marc(void *clientData, Res res, const char *args)
842 {
843  struct marc_info *p = (struct marc_info*) clientData;
844  if (strlen(args) < sizeof(p->type))
845  strcpy(p->type, args);
846  return ZEBRA_OK;
847 }
848 
849 static void destroy_marc(void *clientData)
850 {
851  struct marc_info *p = (struct marc_info*) clientData;
852  xfree (p);
853 }
854 
855 
856 static int extract_marc(void *clientData, struct recExtractCtrl *ctrl)
857 {
858  return zebra_grs_extract(clientData, ctrl, grs_read_marc);
859 }
860 
861 static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl)
862 {
863  return zebra_grs_retrieve(clientData, ctrl, grs_read_marc);
864 }
865 
866 static struct recType marc_type = {
867  0,
868  "grs.marc",
869  init_marc,
870  config_marc,
871  destroy_marc,
872  extract_marc,
874 };
875 
876 static int extract_marcxml(void *clientData, struct recExtractCtrl *ctrl)
877 {
878  return zebra_grs_extract(clientData, ctrl, grs_read_marcxml);
879 }
880 
881 static int retrieve_marcxml(void *clientData, struct recRetrieveCtrl *ctrl)
882 {
883  return zebra_grs_retrieve(clientData, ctrl, grs_read_marcxml);
884 }
885 
886 static struct recType marcxml_type = {
887  0,
888  "grs.marcxml",
889  init_marc,
890  config_marc,
891  destroy_marc,
894 };
895 
896 RecType
897 #if IDZEBRA_STATIC_GRS_MARC
898 idzebra_filter_grs_marc
899 #else
901 #endif
902 
903 [] = {
904  &marc_type,
905  &marcxml_type,
906  0,
907 };
908 
909 /*
910  * Local variables:
911  * c-basic-offset: 4
912  * c-file-style: "Stroustrup"
913  * indent-tabs-mode: nil
914  * End:
915  * vim: shiftwidth=4 tabstop=8 expandtab
916  */
917 
data1_node * data1_mk_tag(data1_handle dh, NMEM nmem, const char *tag, const char **attr, data1_node *at)
Definition: d1_read.c:295
data1_node * data1_mk_root(data1_handle dh, NMEM nmem, const char *name)
Definition: d1_read.c:174
void data1_tag_add_attr(data1_handle dh, NMEM nmem, data1_node *res, const char **attr)
Definition: d1_read.c:286
#define DATA1T_string
Definition: data1.h:205
data1_element * data1_absyn_getelements(data1_handle dh, data1_node *root)
Definition: d1_absyn.c:668
#define DATA1N_tag
Definition: data1.h:276
#define DATA1N_data
Definition: data1.h:278
#define d1_isspace(c)
Definition: data1.h:31
data1_node * data1_mk_tag_n(data1_handle dh, NMEM nmem, const char *tag, size_t len, const char **attr, data1_node *at)
Definition: d1_read.c:259
data1_node * data1_mk_text_n(data1_handle dh, NMEM mem, const char *buf, size_t len, data1_node *parent)
Definition: d1_read.c:331
data1_marctab * data1_absyn_getmarctab(data1_handle dh, data1_node *root)
Definition: d1_absyn.c:661
void inline_destroy_field(inline_field *p)
Definition: inline.c:46
int inline_parse(inline_field *pif, const char *tag, const char *s)
Definition: inline.c:97
inline_field * inline_mk_field(void)
Definition: inline.c:30
void mc_destroy_field(mc_field *p)
Definition: marcomp.c:204
mc_field * mc_getfield(mc_context *c)
Definition: marcomp.c:214
void mc_destroy_context(mc_context *c)
Definition: marcomp.c:86
mc_context * mc_mk_context(const char *s)
Definition: marcomp.c:66
#define MC_SFGROUP
Definition: marcomp.h:38
#define MC_SF
Definition: marcomp.h:37
#define MC_SFVARIANT
Definition: marcomp.h:39
data1_node * grs_read_marcxml(struct grs_read_info *p)
Definition: mod_grs_marc.c:796
RecType idzebra_filter[]
Definition: mod_grs_marc.c:903
static ZEBRA_RES config_marc(void *clientData, Res res, const char *args)
Definition: mod_grs_marc.c:841
static char * get_data(data1_node *n, int *len)
Definition: mod_grs_marc.c:342
static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl)
Definition: mod_grs_marc.c:861
static int extract_marc(void *clientData, struct recExtractCtrl *ctrl)
Definition: mod_grs_marc.c:856
static void * init_marc(Res res, RecType rt)
Definition: mod_grs_marc.c:834
static struct recType marcxml_type
Definition: mod_grs_marc.c:886
static void destroy_marc(void *clientData)
Definition: mod_grs_marc.c:849
static int extract_marcxml(void *clientData, struct recExtractCtrl *ctrl)
Definition: mod_grs_marc.c:876
data1_node * grs_read_marc(struct grs_read_info *p)
Definition: mod_grs_marc.c:815
static inline_subfield * lookup_inline_subfield(inline_subfield *pisf, const char *name)
Definition: mod_grs_marc.c:386
static data1_node * lookup_subfield(data1_node *node, const char *name)
Definition: mod_grs_marc.c:374
static data1_node * cat_field(struct grs_read_info *p, mc_field *pf, WRBUF buf, data1_node *field)
Definition: mod_grs_marc.c:630
#define MARC_DEBUG
Definition: mod_grs_marc.c:34
static data1_node * cat_subfield(mc_subfield *psf, WRBUF buf, data1_node *subfield)
Definition: mod_grs_marc.c:550
static void parse_data1_tree(struct grs_read_info *p, const char *mc_stmnt, data1_node *root)
Definition: mod_grs_marc.c:716
static inline_subfield * cat_inline_subfield(mc_subfield *psf, WRBUF buf, inline_subfield *pisf)
Definition: mod_grs_marc.c:399
static void cat_inline_field(mc_field *pf, WRBUF buf, data1_node *subfield)
Definition: mod_grs_marc.c:473
static int retrieve_marcxml(void *clientData, struct recRetrieveCtrl *ctrl)
Definition: mod_grs_marc.c:881
static struct recType marc_type
Definition: mod_grs_marc.c:866
static data1_node * grs_read_iso2709(struct grs_read_info *p, int marc_xml)
Definition: mod_grs_marc.c:41
static int is_empty(char *s)
Definition: mod_grs_marc.c:704
static FILE * outf
Definition: readfile.c:38
int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
Definition: recgrs.c:1072
int zebra_grs_extract(void *clientData, struct recExtractCtrl *p, data1_node *(*grs_read)(struct grs_read_info *))
Definition: recgrs.c:936
off_t(* endf)(struct ZebraRecStream *s, off_t *offset)
set and get of record position
Definition: recctrl.h:81
int(* readf)(struct ZebraRecStream *s, char *buf, size_t count)
read function
Definition: recctrl.h:75
off_t(* tellf)(struct ZebraRecStream *s)
tell function
Definition: recctrl.h:79
data1_tag * tag
Definition: data1.h:245
struct data1_element * next
Definition: data1.h:249
char leader[24]
Definition: data1.h:155
struct data1_node * child
Definition: data1.h:341
char * tag
Definition: data1.h:296
char * data
Definition: data1.h:307
struct data1_node * next
Definition: data1.h:340
union data1_node::@2 u
int which
Definition: data1.h:285
int which
Definition: data1.h:206
union data1_tag::@1 value
char * string
Definition: data1.h:210
data1_handle dh
Definition: recgrs.h:31
struct ZebraRecStream * stream
Definition: recgrs.h:28
void * clientData
Definition: recgrs.h:29
NMEM mem
Definition: recgrs.h:30
struct inline_subfield * list
Definition: inline.h:34
char * name
Definition: inline.h:31
char * ind1
Definition: inline.h:32
char * ind2
Definition: inline.h:33
char * data
Definition: inline.h:39
char * name
Definition: inline.h:38
struct inline_subfield * next
Definition: inline.h:40
char type[256]
Definition: mod_grs_marc.c:38
char * ind1
Definition: marcomp.h:56
struct mc_subfield * list
Definition: marcomp.h:62
int start
Definition: marcomp.h:59
char * ind2
Definition: marcomp.h:57
int end
Definition: marcomp.h:60
char * name
Definition: marcomp.h:55
struct mc_field::@17 interval
struct mc_field * in_line
Definition: marcomp.h:40
int end
Definition: marcomp.h:33
struct mc_subfield::@15 interval
char * prefix
Definition: marcomp.h:29
union mc_subfield::@16 u
struct mc_subfield * child
Definition: marcomp.h:41
int which
Definition: marcomp.h:35
char * name
Definition: marcomp.h:28
char * suffix
Definition: marcomp.h:30
int start
Definition: marcomp.h:32
struct mc_subfield * next
Definition: marcomp.h:43
record extract for indexing
Definition: recctrl.h:101
Definition: res.c:46
#define ZEBRA_OK
Definition: util.h:82
short ZEBRA_RES
Common return type for Zebra API.
Definition: util.h:80