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