1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2009 Index Data
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
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
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
25 #include <yaz/yaz-util.h>
29 static mc_token mc_gettoken(mc_context *c);
30 static void mc_ungettoken(mc_context *c);
31 static int mc_getval(mc_context *c);
32 static int mc_getdata(mc_context *c, char *s, int sz);
33 static void mc_getinterval(mc_context *c, int *start, int *end);
35 static mc_subfield *mc_mk_subfield(mc_subfield *parent);
36 static mc_field *mc_mk_field(void);
38 static struct mc_errmsg
45 {EMCF, "not complete field"},
46 {EMCSF, "not complete subfield"},
47 {EMCSFGROUP, "not closed GROUP"},
48 {EMCSFVAR, "not closed VARIANT"},
49 {EMCSFINLINE, "not closed IN-LINE"},
50 {EMCEND, "not correct errno"}
52 mc_errcode mc_errno(mc_context *c)
56 const char *mc_error(mc_errcode no)
58 if (no >= EMCOK && no<EMCEND)
59 return mc_errmsg[no].msg;
61 return mc_errmsg[EMCEND].msg;
63 mc_context *mc_mk_context(const char *s)
69 p = (mc_context*) xmalloc(sizeof(*p));
74 memset(p, 0, sizeof(*p));
83 void mc_destroy_context(mc_context *c)
87 mc_token mc_gettoken(mc_context *c)
89 if (c->offset >= c->len)
92 switch (*(c->data+c->offset))
94 case '{': c->crrtok = LVARIANT; break;
95 case '}': c->crrtok = RVARIANT; break;
96 case '(': c->crrtok = LGROUP; break;
97 case ')': c->crrtok = RGROUP; break;
98 case '<': c->crrtok = LINLINE; break;
99 case '>': c->crrtok = RINLINE; break;
100 case '$': c->crrtok = SUBFIELD; break;
101 case '[': c->crrtok = LINTERVAL; break;
102 case ']': c->crrtok = RINTERVAL; break;
104 if (isspace(*(unsigned char *) (c->data+c->offset))
105 || *(c->data+c->offset) == '\n')
112 c->crrval = *(c->data+c->offset);
116 fprintf(stderr, "gettoken(): offset: %d", c->offset);
117 if (c->crrtok == REGULAR)
118 fprintf(stderr, "<%c>", c->crrval);
119 fprintf(stderr, "\n");
124 void mc_ungettoken(mc_context *c)
129 int mc_getval(mc_context *c)
133 int mc_getdata(mc_context *c, char *s, int sz)
139 if (mc_gettoken(c)!=REGULAR)
150 void mc_getinterval(mc_context *c, int *start, int *end)
153 int start_pos, end_pos;
155 start_pos = end_pos = -1;
157 if (mc_gettoken(c) == LINTERVAL)
163 mc_token tok = mc_gettoken(c);
165 if (tok == RINTERVAL || tok == NOP)
168 buf[i] = mc_getval(c);
172 i = sscanf(buf, "%d-%d", &start_pos, &end_pos);
184 mc_field *mc_mk_field(void)
186 mc_field *p = (mc_field *)xmalloc(sizeof(*p));
190 memset(p, 0, sizeof(*p));
191 p->name = (char *)xmalloc(SZ_FNAME+1);
193 p->ind1 = (char *)xmalloc(SZ_IND+1);
195 p->ind2 = (char *)xmalloc(SZ_IND+1);
197 p->interval.start = p->interval.end = -1;
201 void mc_destroy_field(mc_field *p)
205 if (p->name) xfree(p->name);
206 if (p->ind1) xfree(p->ind1);
207 if (p->ind2) xfree(p->ind2);
208 if (p->list) mc_destroy_subfields_recursive(p->list);
211 mc_field *mc_getfield(mc_context *c)
219 c->errcode = EMCNOMEM;
223 if (mc_getdata(c, pf->name, SZ_FNAME) == SZ_FNAME)
225 mc_token nexttok = mc_gettoken(c);
229 if (nexttok == LINTERVAL)
231 mc_getinterval(c, &pf->interval.start, &pf->interval.end);
233 fprintf(stderr, "ineterval (%d)-(%d)\n", pf->interval.start,
238 if ((mc_getdata(c, pf->ind1, SZ_IND) == SZ_IND) &&
239 (mc_getdata(c, pf->ind2, SZ_IND) == SZ_IND))
241 pf->list = mc_getsubfields(c, 0);
247 mc_destroy_field(pf);
253 mc_subfield *mc_mk_subfield(mc_subfield *parent)
255 mc_subfield *p = (mc_subfield*)xmalloc(sizeof(*p));
259 memset(p, 0, sizeof(*p));
261 p->name = (char *)xmalloc(SZ_SFNAME+1);
263 p->prefix = (char *)xmalloc(SZ_PREFIX+1);
265 p->suffix = (char *)xmalloc(SZ_SUFFIX+1);
268 p->interval.start = p->interval.end = -1;
272 void mc_destroy_subfield(mc_subfield *p)
277 if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT)
280 mc_destroy_subfields_recursive(p->u.child);
282 else if (p->which == MC_SF)
285 mc_destroy_field(p->u.in_line);
287 if (p->name) xfree(p->name);
288 if (p->prefix) xfree(p->prefix);
289 if (p->suffix) xfree(p->suffix);
290 if (p->parent) p->parent->next = p->next;
293 void mc_destroy_subfields_recursive(mc_subfield *p)
298 mc_destroy_subfields_recursive(p->next);
300 if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT)
303 mc_destroy_subfields_recursive(p->u.child);
305 else if (p->which == MC_SF)
308 mc_destroy_field(p->u.in_line);
311 if (p->name) xfree(p->name);
312 if (p->prefix) xfree(p->prefix);
313 if (p->suffix) xfree(p->suffix);
314 if (p->parent) p->parent->next = 0;
317 mc_subfield *mc_getsubfields(mc_context *c, mc_subfield *parent)
320 mc_token tok = mc_gettoken(c);
327 if (!(psf = mc_mk_subfield(parent)))
329 c->errcode = EMCNOMEM;
333 psf->which = MC_SFGROUP;
334 psf->u.child = mc_getsubfields(c, psf);
336 if (mc_gettoken(c) == RGROUP)
337 psf->next = mc_getsubfields(c, psf);
340 c->errcode = EMCSFGROUP;
341 mc_destroy_subfield(psf);
345 else if (tok == LVARIANT)
347 if (!(psf = mc_mk_subfield(parent)))
349 c->errcode = EMCNOMEM;
353 psf->which = MC_SFVARIANT;
354 psf->u.child = mc_getsubfields(c, psf);
356 if (mc_gettoken(c) == RVARIANT)
357 psf->next = mc_getsubfields(c, psf);
360 c->errcode = EMCSFVAR;
361 mc_destroy_subfield(psf);
365 else if (tok == RGROUP || tok == RVARIANT || tok == RINLINE)
370 else if (tok == REGULAR)
372 if (!(psf = mc_mk_subfield(parent)))
374 c->errcode = EMCNOMEM;
380 if((mc_getdata(c, psf->prefix, SZ_PREFIX) == SZ_PREFIX) &&
381 (mc_gettoken(c) == SUBFIELD) &&
382 (mc_getdata(c, psf->name, SZ_SFNAME) == SZ_SFNAME))
384 mc_token tok = mc_gettoken(c);
388 if (tok == LINTERVAL)
390 mc_getinterval(c, &psf->interval.start, &psf->interval.end);
392 else if (tok == LINLINE)
395 psf->u.in_line = mc_getfield(c);
396 if (mc_gettoken(c) != RINLINE)
398 c->errcode = EMCSFINLINE;
399 mc_destroy_subfield(psf);
404 if (mc_getdata(c, psf->suffix, SZ_SUFFIX) == SZ_SUFFIX)
407 psf->next = mc_getsubfields(c, psf);
412 mc_destroy_subfield(psf);
422 * c-file-style: "Stroustrup"
423 * indent-tabs-mode: nil
425 * vim: shiftwidth=4 tabstop=8 expandtab