/* * chr.h - Part characteristics * * Copyright 2012 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include "util.h" #include "lang.h" #include "relop.h" #include "param.h" #include "chr.h" const struct format *field_find(const char *name, const struct field *tail) { while (tail) { if (tail->name == name) return tail->fmt; tail = tail->prev; } return NULL; } /* ----- Construction of the field hierarchy ------------------------------- */ struct field *new_field(const char *name, const struct format *fmt, const struct field *prev) { struct field *field; if (field_find(name, prev)) yyerrorf("duplicate field \"%s\"", name); field = alloc_type(struct field); field->name = name; field->fmt = fmt; field->sel = NULL; field->any.fields = NULL; field->any.rules = NULL; field->next = NULL; field->prev = NULL; return field; } struct selector *new_selector(void) { struct selector *sel; sel = alloc_type(struct selector); sel->cond = NULL; sel->act.fields = NULL; sel->act.rules = NULL; sel->next = NULL; return sel; } struct condition *new_condition(enum relop relop, const char *word) { struct condition *cond; cond = alloc_type(struct condition); cond->value.u.s = word; cond->relop = relop; cond->next = NULL; return cond; } void field_finalize(struct field *field) { const struct selector *sel; struct condition *cond; for (sel = field->sel; sel; sel = sel->next) for (cond = sel->cond; cond; cond = cond->next) if (!evaluate(field->fmt, cond->value.u.s, &cond->value)) yyerrorf("invalid value in selection"); /* @@@ indicate exact location */ } /* ----- Dumping ----------------------------------------------------------- */ #define INDENT 8 static void dump_fields(FILE *file, const struct field *field, int level); static void dump_set_decl(FILE *file, const struct names *first_name) { const char *name; name = nameset_rev_lookup(first_name); assert(name); fprintf(file, "<%s>", name); } static void dump_field_decl(FILE *file, const struct field *field) { if (field->fmt->ops == ¶m_ops_name) fprintf(file, "*"); else if (field->fmt->ops == ¶m_ops_set) dump_set_decl(file, field->fmt->u.set); else if (field->fmt->ops == ¶m_ops_abs) fprintf(file, "#%s", field->fmt->u.abs); else if (field->fmt->ops == ¶m_ops_rel) fprintf(file, "%%%s", field->fmt->u.rel->u.abs); else abort(); } static void dump_action(FILE *file, const struct action *act, int level) { const struct field *field; if (act->fields) { fprintf(file, " {"); for (field = act->fields; field; field = field->next) { fprintf(file, " %s=", field->name); dump_field_decl(file, field); } fprintf(file, " }\n"); } else { fprintf(file, "\n"); } dump_fields(file, act->rules, level+1); } static void dump_one_field(FILE *file, const struct field *field, int level) { const struct selector *sel; const struct condition *cond; fprintf(file, "%*s%s=", level*INDENT, "", field->name); dump_field_decl(file, field); fprintf(file, " {\n"); for (sel = field->sel; sel; sel = sel->next) { fprintf(file, "%*s", level*INDENT+INDENT/2, ""); for (cond = sel->cond; cond; cond = cond->next) { if (cond != sel->cond) fprintf(file, "|"); if (cond->relop != rel_eq) dump_relop(file, cond->relop); dump(file, field->fmt, &cond->value); } fprintf(file, ": "); dump_action(file, &sel->act, level); } if (field->any.fields || field->any.rules) { fprintf(file, "%*s*:", level*INDENT+INDENT/2, ""); dump_action(file, &field->any, level); } fprintf(file, "%*s}\n", level*INDENT, ""); } static void dump_fields(FILE *file, const struct field *field, int level) { while (field) { dump_one_field(file, field, level); field = field->next; } } void field_dump(FILE *file, const struct field *field) { dump_fields(file, field, 0); }