/* $Id: marcomp.c,v 1.2 2003/02/28 14:34:37 adam Exp $ marcomp.c - compiler of MARC statements. */ #include #include #include #include #include #include "marcomp.h" static mc_token mc_gettoken(mc_context *c); static void mc_ungettoken(mc_context *c); static int mc_getval(mc_context *c); static int mc_getdata(mc_context *c, char *s, int sz); static void mc_getinterval(mc_context *c, int *start, int *end); static mc_subfield *mc_mk_subfield(mc_subfield *parent); static mc_field *mc_mk_field(void); static struct mc_errmsg { mc_errcode code; const char *msg; } mc_errmsg[] = { {EMCOK, "OK"}, {EMCNOMEM, "NO mem"}, {EMCF, "not complete field"}, {EMCSF, "not complete subfield"}, {EMCSFGROUP, "not closed GROUP"}, {EMCSFVAR, "not closed VARIANT"}, {EMCSFINLINE, "not closed IN-LINE"}, {EMCEND, "not correct errno"} }; mc_errcode mc_errno(mc_context *c) { return c->errcode; } const char *mc_error(mc_errcode no) { if (no >= EMCOK && noerrcode = EMCOK; p->data = s; p->len = strlen(s); p->crrtok = NOP; } return p; } void mc_destroy_context(mc_context *c) { if (c) xfree(c); } mc_token mc_gettoken(mc_context *c) { if (c->offset >= c->len) return NOP; switch (*(c->data+c->offset)) { case '{': c->crrtok = LVARIANT; break; case '}': c->crrtok = RVARIANT; break; case '(': c->crrtok = LGROUP; break; case ')': c->crrtok = RGROUP; break; case '<': c->crrtok = LINLINE; break; case '>': c->crrtok = RINLINE; break; case '$': c->crrtok = SUBFIELD; break; case '[': c->crrtok = LINTERVAL; break; case ']': c->crrtok = RINTERVAL; break; default: if (isspace(*(c->data+c->offset)) || *(c->data+c->offset) == '\n') { c->crrtok = NOP; } else { c->crrtok = REGULAR; c->crrval = *(c->data+c->offset); } } #ifdef DEBUG fprintf(stderr, "gettoken(): offset: %d", c->offset); if (c->crrtok == REGULAR) fprintf(stderr, "<%c>", c->crrval); fprintf(stderr, "\n"); #endif c->offset++; return c->crrtok; } void mc_ungettoken(mc_context *c) { if (c->offset > 0) c->offset--; } int mc_getval(mc_context *c) { return c->crrval; } int mc_getdata(mc_context *c, char *s, int sz) { int i; for (i=0; iname = (char *)xmalloc(SZ_FNAME+1); *p->name = '\0'; p->ind1 = (char *)xmalloc(SZ_IND+1); *p->ind1 = '\0'; p->ind2 = (char *)xmalloc(SZ_IND+1); *p->ind2 = '\0'; p->interval.start = p->interval.end = -1; } return p; } void mc_destroy_field(mc_field *p) { if (!p) return; if (p->name) xfree(p->name); if (p->ind1) xfree(p->ind1); if (p->ind2) xfree(p->ind2); if (p->list) mc_destroy_subfields_recursive(p->list); xfree(p); } mc_field *mc_getfield(mc_context *c) { mc_field *pf; pf = mc_mk_field(); if (!pf) { c->errcode = EMCNOMEM; return 0; } if (mc_getdata(c, pf->name, SZ_FNAME) == SZ_FNAME) { mc_token nexttok = mc_gettoken(c); mc_ungettoken(c); if (nexttok == LINTERVAL) { mc_getinterval(c, &pf->interval.start, &pf->interval.end); #ifdef DEBUG fprintf(stderr, "ineterval (%d)-(%d)\n", pf->interval.start, pf->interval.end); #endif } if ((mc_getdata(c, pf->ind1, SZ_IND) == SZ_IND) && (mc_getdata(c, pf->ind2, SZ_IND) == SZ_IND)) { pf->list = mc_getsubfields(c, 0); } } else { c->errcode = EMCF; mc_destroy_field(pf); return 0; } return pf; } mc_subfield *mc_mk_subfield(mc_subfield *parent) { mc_subfield *p = (mc_subfield*)xmalloc(sizeof(*p)); if (p) { memset(p, 0, sizeof(*p)); p->which = MC_SF; p->name = (char *)xmalloc(SZ_SFNAME+1); *p->name = '\0'; p->prefix = (char *)xmalloc(SZ_PREFIX+1); *p->prefix = '\0'; p->suffix = (char *)xmalloc(SZ_SUFFIX+1); *p->suffix = '\0'; p->parent = parent; p->interval.start = p->interval.end = -1; } return p; } void mc_destroy_subfield(mc_subfield *p) { if (!p) return; if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT) { if (p->u.child) mc_destroy_subfields_recursive(p->u.child); } else if (p->which == MC_SF) { if (p->u.in_line) mc_destroy_field(p->u.in_line); } if (p->name) xfree(p->name); if (p->prefix) xfree(p->prefix); if (p->suffix) xfree(p->suffix); if (p->parent) p->parent->next = p->next; xfree(p); } void mc_destroy_subfields_recursive(mc_subfield *p) { if (!p) return; mc_destroy_subfields_recursive(p->next); if (p->which == MC_SFGROUP || p->which == MC_SFVARIANT) { if (p->u.child) mc_destroy_subfields_recursive(p->u.child); } else if (p->which == MC_SF) { if (p->u.in_line) mc_destroy_field(p->u.in_line); } if (p->name) xfree(p->name); if (p->prefix) xfree(p->prefix); if (p->suffix) xfree(p->suffix); if (p->parent) p->parent->next = 0; xfree(p); } mc_subfield *mc_getsubfields(mc_context *c, mc_subfield *parent) { mc_subfield *psf=0; mc_token tok = mc_gettoken(c); if (tok == NOP) return 0; if (tok == LGROUP) { if (!(psf = mc_mk_subfield(parent))) { c->errcode = EMCNOMEM; return 0; } psf->which = MC_SFGROUP; psf->u.child = mc_getsubfields(c, psf); if (mc_gettoken(c) == RGROUP) psf->next = mc_getsubfields(c, psf); else { c->errcode = EMCSFGROUP; mc_destroy_subfield(psf); return 0; } } else if (tok == LVARIANT) { if (!(psf = mc_mk_subfield(parent))) { c->errcode = EMCNOMEM; return 0; } psf->which = MC_SFVARIANT; psf->u.child = mc_getsubfields(c, psf); if (mc_gettoken(c) == RVARIANT) psf->next = mc_getsubfields(c, psf); else { c->errcode = EMCSFVAR; mc_destroy_subfield(psf); return 0; } } else if (tok == RGROUP || tok == RVARIANT || tok == RINLINE) { mc_ungettoken(c); return 0; } else if (tok == REGULAR) { if (!(psf = mc_mk_subfield(parent))) { c->errcode = EMCNOMEM; return 0; } mc_ungettoken(c); if((mc_getdata(c, psf->prefix, SZ_PREFIX) == SZ_PREFIX) && (mc_gettoken(c) == SUBFIELD) && (mc_getdata(c, psf->name, SZ_SFNAME) == SZ_SFNAME)) { mc_token tok = mc_gettoken(c); mc_ungettoken(c); if (tok == LINTERVAL) { mc_getinterval(c, &psf->interval.start, &psf->interval.end); } else if (tok == LINLINE) { mc_gettoken(c); psf->u.in_line = mc_getfield(c); if (mc_gettoken(c) != RINLINE) { c->errcode = EMCSFINLINE; mc_destroy_subfield(psf); return 0; } } if (mc_getdata(c, psf->suffix, SZ_SUFFIX) == SZ_SUFFIX) { psf->which = MC_SF; psf->next = mc_getsubfields(c, psf); } else { c->errcode = EMCSF; mc_destroy_subfield(psf); return 0; } } } return psf; }