IDZEBRA  2.1.2
marcomp.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 <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include <yaz/yaz-util.h>
29 
30 #include "marcomp.h"
31 
33 static void mc_ungettoken(mc_context *c);
34 static int mc_getval(mc_context *c);
35 static int mc_getdata(mc_context *c, char *s, int sz);
36 static void mc_getinterval(mc_context *c, int *start, int *end);
37 
38 static mc_subfield *mc_mk_subfield(mc_subfield *parent);
39 static mc_field *mc_mk_field(void);
40 
41 static struct mc_errmsg
42 {
44  const char *msg;
45 } mc_errmsg[] = {
46 {EMCOK, "OK"},
47 {EMCNOMEM, "NO mem"},
48 {EMCF, "not complete field"},
49 {EMCSF, "not complete subfield"},
50 {EMCSFGROUP, "not closed GROUP"},
51 {EMCSFVAR, "not closed VARIANT"},
52 {EMCSFINLINE, "not closed IN-LINE"},
53 {EMCEND, "not correct errno"}
54 };
56 {
57  return c->errcode;
58 }
59 const char *mc_error(mc_errcode no)
60 {
61  if (no >= EMCOK && no<EMCEND)
62  return mc_errmsg[no].msg;
63  else
64  return mc_errmsg[EMCEND].msg;
65 }
66 mc_context *mc_mk_context(const char *s)
67 {
68  mc_context *p=0;
69 
70  if (s && strlen(s))
71  {
72  p = (mc_context*) xmalloc(sizeof(*p));
73 
74  if (!p)
75  return 0;
76 
77  memset(p, 0, sizeof(*p));
78  p->errcode = EMCOK;
79  p->data = s;
80  p->len = strlen(s);
81  p->crrtok = NOP;
82  }
83 
84  return p;
85 }
87 {
88  if (c) xfree(c);
89 }
91 {
92  if (c->offset >= c->len)
93  return NOP;
94 
95  switch (*(c->data+c->offset))
96  {
97  case '{': c->crrtok = LVARIANT; break;
98  case '}': c->crrtok = RVARIANT; break;
99  case '(': c->crrtok = LGROUP; break;
100  case ')': c->crrtok = RGROUP; break;
101  case '<': c->crrtok = LINLINE; break;
102  case '>': c->crrtok = RINLINE; break;
103  case '$': c->crrtok = SUBFIELD; break;
104  case '[': c->crrtok = LINTERVAL; break;
105  case ']': c->crrtok = RINTERVAL; break;
106  default:
107  if (isspace(*(unsigned char *) (c->data+c->offset))
108  || *(c->data+c->offset) == '\n')
109  {
110  c->crrtok = NOP;
111  }
112  else
113  {
114  c->crrtok = REGULAR;
115  c->crrval = *(c->data+c->offset);
116  }
117  }
118 #ifdef DEBUG
119  fprintf(stderr, "gettoken(): offset: %d", c->offset);
120  if (c->crrtok == REGULAR)
121  fprintf(stderr, "<%c>", c->crrval);
122  fprintf(stderr, "\n");
123 #endif
124  c->offset++;
125  return c->crrtok;
126 }
128 {
129  if (c->offset > 0)
130  c->offset--;
131 }
133 {
134  return c->crrval;
135 }
136 int mc_getdata(mc_context *c, char *s, int sz)
137 {
138  int i;
139 
140  for (i=0; i<sz; i++)
141  {
142  if (mc_gettoken(c)!=REGULAR)
143  {
144  mc_ungettoken(c);
145  break;
146  }
147  s[i] = mc_getval(c);
148  }
149  s[i] = '\0';
150 
151  return i;
152 }
153 void mc_getinterval(mc_context *c, int *start, int *end)
154 {
155  char buf[6+1];
156  int start_pos, end_pos;
157 
158  start_pos = end_pos = -1;
159 
160  if (mc_gettoken(c) == LINTERVAL)
161  {
162  int i;
163 
164  for (i=0;i<6;i++)
165  {
166  mc_token tok = mc_gettoken(c);
167 
168  if (tok == RINTERVAL || tok == NOP)
169  break;
170 
171  buf[i] = mc_getval(c);
172  }
173 
174  buf[i] = '\0';
175  i = sscanf(buf, "%d-%d", &start_pos, &end_pos);
176 
177  if (i == 1)
178  end_pos = start_pos;
179  else if ( i == 0)
180  {
181  start_pos = 0;
182  }
183  }
184  *start = start_pos;
185  *end = end_pos;
186 }
188 {
189  mc_field *p = (mc_field *)xmalloc(sizeof(*p));
190 
191  if (p)
192  {
193  memset(p, 0, sizeof(*p));
194  p->name = (char *)xmalloc(SZ_FNAME+1);
195  *p->name = '\0';
196  p->ind1 = (char *)xmalloc(SZ_IND+1);
197  *p->ind1 = '\0';
198  p->ind2 = (char *)xmalloc(SZ_IND+1);
199  *p->ind2 = '\0';
200  p->interval.start = p->interval.end = -1;
201  }
202  return p;
203 }
205 {
206  if (!p)
207  return;
208  if (p->name) xfree(p->name);
209  if (p->ind1) xfree(p->ind1);
210  if (p->ind2) xfree(p->ind2);
212  xfree(p);
213 }
215 {
216  mc_field *pf;
217 
218  pf = mc_mk_field();
219 
220  if (!pf)
221  {
222  c->errcode = EMCNOMEM;
223  return 0;
224  }
225 
226  if (mc_getdata(c, pf->name, SZ_FNAME) == SZ_FNAME)
227  {
228  mc_token nexttok = mc_gettoken(c);
229 
230  mc_ungettoken(c);
231 
232  if (nexttok == LINTERVAL)
233  {
234  mc_getinterval(c, &pf->interval.start, &pf->interval.end);
235 #ifdef DEBUG
236  fprintf(stderr, "ineterval (%d)-(%d)\n", pf->interval.start,
237  pf->interval.end);
238 #endif
239  }
240 
241  if ((mc_getdata(c, pf->ind1, SZ_IND) == SZ_IND) &&
242  (mc_getdata(c, pf->ind2, SZ_IND) == SZ_IND))
243  {
244  pf->list = mc_getsubfields(c, 0);
245  }
246  }
247  else
248  {
249  c->errcode = EMCF;
250  mc_destroy_field(pf);
251  return 0;
252  }
253 
254  return pf;
255 }
257 {
258  mc_subfield *p = (mc_subfield*)xmalloc(sizeof(*p));
259 
260  if (p)
261  {
262  memset(p, 0, sizeof(*p));
263  p->which = MC_SF;
264  p->name = (char *)xmalloc(SZ_SFNAME+1);
265  *p->name = '\0';
266  p->prefix = (char *)xmalloc(SZ_PREFIX+1);
267  *p->prefix = '\0';
268  p->suffix = (char *)xmalloc(SZ_SUFFIX+1);
269  *p->suffix = '\0';
270  p->parent = parent;
271  p->interval.start = p->interval.end = -1;
272  }
273  return p;
274 }
276 {
277  if (!p)
278  return;
279 
280  if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT)
281  {
282  if (p->u.child)
284  }
285  else if (p->which == MC_SF)
286  {
287  if (p->u.in_line)
289  }
290  if (p->name) xfree(p->name);
291  if (p->prefix) xfree(p->prefix);
292  if (p->suffix) xfree(p->suffix);
293  if (p->parent) p->parent->next = p->next;
294  xfree(p);
295 }
297 {
298  if (!p)
299  return;
300 
302 
303  if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT)
304  {
305  if (p->u.child)
307  }
308  else if (p->which == MC_SF)
309  {
310  if (p->u.in_line)
312  }
313 
314  if (p->name) xfree(p->name);
315  if (p->prefix) xfree(p->prefix);
316  if (p->suffix) xfree(p->suffix);
317  if (p->parent) p->parent->next = 0;
318  xfree(p);
319 }
321 {
322  mc_subfield *psf=0;
323  mc_token tok = mc_gettoken(c);
324 
325  if (tok == NOP)
326  return 0;
327 
328  if (tok == LGROUP)
329  {
330  if (!(psf = mc_mk_subfield(parent)))
331  {
332  c->errcode = EMCNOMEM;
333  return 0;
334  }
335 
336  psf->which = MC_SFGROUP;
337  psf->u.child = mc_getsubfields(c, psf);
338 
339  if (mc_gettoken(c) == RGROUP)
340  psf->next = mc_getsubfields(c, psf);
341  else
342  {
343  c->errcode = EMCSFGROUP;
344  mc_destroy_subfield(psf);
345  return 0;
346  }
347  }
348  else if (tok == LVARIANT)
349  {
350  if (!(psf = mc_mk_subfield(parent)))
351  {
352  c->errcode = EMCNOMEM;
353  return 0;
354  }
355 
356  psf->which = MC_SFVARIANT;
357  psf->u.child = mc_getsubfields(c, psf);
358 
359  if (mc_gettoken(c) == RVARIANT)
360  psf->next = mc_getsubfields(c, psf);
361  else
362  {
363  c->errcode = EMCSFVAR;
364  mc_destroy_subfield(psf);
365  return 0;
366  }
367  }
368  else if (tok == RGROUP || tok == RVARIANT || tok == RINLINE)
369  {
370  mc_ungettoken(c);
371  return 0;
372  }
373  else if (tok == REGULAR)
374  {
375  if (!(psf = mc_mk_subfield(parent)))
376  {
377  c->errcode = EMCNOMEM;
378  return 0;
379  }
380 
381  mc_ungettoken(c);
382 
383  if((mc_getdata(c, psf->prefix, SZ_PREFIX) == SZ_PREFIX) &&
384  (mc_gettoken(c) == SUBFIELD) &&
385  (mc_getdata(c, psf->name, SZ_SFNAME) == SZ_SFNAME))
386  {
387  mc_token tok = mc_gettoken(c);
388 
389  mc_ungettoken(c);
390 
391  if (tok == LINTERVAL)
392  {
393  mc_getinterval(c, &psf->interval.start, &psf->interval.end);
394  }
395  else if (tok == LINLINE)
396  {
397  mc_gettoken(c);
398  psf->u.in_line = mc_getfield(c);
399  if (mc_gettoken(c) != RINLINE)
400  {
401  c->errcode = EMCSFINLINE;
402  mc_destroy_subfield(psf);
403  return 0;
404  }
405  }
406 
407  if (mc_getdata(c, psf->suffix, SZ_SUFFIX) == SZ_SUFFIX)
408  {
409  psf->which = MC_SF;
410  psf->next = mc_getsubfields(c, psf);
411  }
412  else
413  {
414  c->errcode = EMCSF;
415  mc_destroy_subfield(psf);
416  return 0;
417  }
418  }
419  }
420  return psf;
421 }
422 /*
423  * Local variables:
424  * c-basic-offset: 4
425  * c-file-style: "Stroustrup"
426  * indent-tabs-mode: nil
427  * End:
428  * vim: shiftwidth=4 tabstop=8 expandtab
429  */
430 
mc_errcode code
Definition: marcomp.c:43
static mc_field * mc_mk_field(void)
Definition: marcomp.c:187
struct mc_subfield * list
Definition: marcomp.h:62
struct mc_field * in_line
Definition: marcomp.h:40
int start
Definition: marcomp.h:32
struct mc_field::@17 interval
mc_errcode errcode
Definition: marcomp.h:99
static mc_subfield * mc_mk_subfield(mc_subfield *parent)
Definition: marcomp.c:256
const char * msg
Definition: marcomp.c:44
struct mc_subfield * next
Definition: marcomp.h:43
Definition: marcomp.h:67
int offset
Definition: marcomp.h:94
#define MC_SF
Definition: marcomp.h:37
static int mc_getval(mc_context *c)
Definition: marcomp.c:132
char * name
Definition: marcomp.h:28
#define SZ_IND
Definition: marcomp.h:48
void mc_destroy_subfield(mc_subfield *p)
Definition: marcomp.c:275
Definition: marcomp.h:85
int crrval
Definition: marcomp.h:96
mc_token
Definition: marcomp.h:65
char * prefix
Definition: marcomp.h:29
#define SZ_SFNAME
Definition: marcomp.h:49
#define MC_SFVARIANT
Definition: marcomp.h:39
Definition: marcomp.h:84
Definition: marcomp.h:71
const char * data
Definition: marcomp.h:102
Definition: marcomp.h:72
mc_token crrtok
Definition: marcomp.h:97
#define MC_SFGROUP
Definition: marcomp.h:38
Definition: marcomp.h:82
mc_errcode
Definition: marcomp.h:80
union mc_subfield::@16 u
int end
Definition: marcomp.h:33
void mc_destroy_subfields_recursive(mc_subfield *p)
Definition: marcomp.c:296
const char * mc_error(mc_errcode no)
Definition: marcomp.c:59
mc_subfield * mc_getsubfields(mc_context *c, mc_subfield *parent)
Definition: marcomp.c:320
int len
Definition: marcomp.h:101
char * name
Definition: marcomp.h:55
static void end(struct zebra_register *reg, void *set_handle)
Definition: rank1.c:156
mc_context * mc_mk_context(const char *s)
Definition: marcomp.c:66
#define SZ_FNAME
Definition: marcomp.h:47
Definition: marcomp.h:89
static int mc_getdata(mc_context *c, char *s, int sz)
Definition: marcomp.c:136
char * ind1
Definition: marcomp.h:56
mc_field * mc_getfield(mc_context *c)
Definition: marcomp.c:214
char * ind2
Definition: marcomp.h:57
int start
Definition: marcomp.h:59
char * suffix
Definition: marcomp.h:30
#define SZ_SUFFIX
Definition: marcomp.h:51
static mc_token mc_gettoken(mc_context *c)
Definition: marcomp.c:90
void mc_destroy_context(mc_context *c)
Definition: marcomp.c:86
struct mc_subfield::@15 interval
#define SZ_PREFIX
Definition: marcomp.h:50
static void mc_ungettoken(mc_context *c)
Definition: marcomp.c:127
int end
Definition: marcomp.h:60
struct mc_subfield * child
Definition: marcomp.h:41
mc_errcode mc_errno(mc_context *c)
Definition: marcomp.c:55
struct mc_subfield * parent
Definition: marcomp.h:44
static void mc_getinterval(mc_context *c, int *start, int *end)
Definition: marcomp.c:153
int which
Definition: marcomp.h:35
void mc_destroy_field(mc_field *p)
Definition: marcomp.c:204