Exemplo n.º 1
0
static struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node) {
	struct rnnbitfield *bf = calloc(sizeof *bf, 1);
	bf->file = file;
	xmlAttr *attr = node->properties;
	int highok = 0, lowok = 0;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			bf->name = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "high")) {
			bf->high = getnumattrib(db, file, node->line, attr);
			highok = 1;
		} else if (!strcmp(attr->name, "low")) {
			bf->low = getnumattrib(db, file, node->line, attr);
			lowok = 1;
		} else if (!strcmp(attr->name, "pos")) {
			bf->high = bf->low = getnumattrib(db, file, node->line, attr);
			lowok = highok = 1;
		} else if (!strcmp(attr->name, "varset")) {
			bf->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "variants")) {
			bf->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!trytypeattr(db, file, node, attr, &bf->typeinfo)) {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for bitfield\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!trytypetag(db, file, chain, &bf->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
	if (!bf->name) {
		fprintf (stderr, "%s:%d: nameless bitfield\n", file, node->line);
		db->estatus = 1;
		return 0;
	} else if (!highok || !lowok || bf->high < bf->low) {
		fprintf (stderr, "%s:%d: bitfield has wrong placement\n", file, node->line);
		db->estatus = 1;
		return 0;
	} else {
		return bf;
	}
}
Exemplo n.º 2
0
static int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *attr, struct rnntypeinfo *ti) {
	if (!strcmp(attr->name, "shr")) {
		ti->shr = getnumattrib(db, file, node->line, attr);
		return 1;
	} else if (!strcmp(attr->name, "min")) {
		ti->min = getnumattrib(db, file, node->line, attr);
		ti->minvalid = 1;
		return 1;
	} else if (!strcmp(attr->name, "max")) {
		ti->max = getnumattrib(db, file, node->line, attr);
		ti->maxvalid = 1;
		return 1;
	} else if (!strcmp(attr->name, "align")) {
		ti->align = getnumattrib(db, file, node->line, attr);
		ti->alignvalid = 1;
		return 1;
	} else if (!strcmp(attr->name, "type")) {
		ti->name = strdup(getattrib(db, file, node->line, attr));;
		return 1;
	} else if (!strcmp(attr->name, "radix")) {
		ti->radix = getnumattrib(db, file, node->line, attr);
		ti->radixvalid = 1;
	}
	return 0;
}
Exemplo n.º 3
0
static int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
	char *c = getattrib(db, file, line, attr);
	if (!strcmp(c, "yes") || !strcmp(c, "1"))
		return 1;
	if (!strcmp(c, "no") || !strcmp(c, "0"))
		return 0;
	fprintf (stderr, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
	db->estatus = 1;
	return 0;
}
Exemplo n.º 4
0
static uint64_t getnumattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
	char *c = getattrib(db, file, line, attr);
	char *cc;
	uint64_t res;
	if (strchr(c, 'x') || strchr(c, 'X'))
		res = strtoull(c, &cc, 16);
	else
		res = strtoull(c, &cc, 10);
	if (*cc)  {
		fprintf (stderr, "%s:%d: invalid numeric value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
		db->estatus = 1;
	}
	return res;
}
Exemplo n.º 5
0
static struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node) {
	struct rnnvalue *val = calloc(sizeof *val, 1);
	val->file = file;
	xmlAttr *attr = node->properties;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			val->name = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "value")) {
			val->value = getnumattrib(db, file, node->line, attr);
			val->valvalid = 1;
		} else if (!strcmp(attr->name, "varset")) {
			val->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "variants")) {
			val->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
		} else {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for value\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
	if (!val->name) {
		fprintf (stderr, "%s:%d: nameless value\n", file, node->line);
		db->estatus = 1;
		return 0;
	} else {
		return val;
	}
}
Exemplo n.º 6
0
void main(int argc, char * argv[]) {
  int channel, rcvid, returncode;

  if(open("/sys/addressbook", O_PROC) != -1) {
    fprintf(stderr, "The addressbook service is already running.\n");
    exit(EXIT_FAILURE);
  }

  xmlfile = XMLloadFile(fpathname("data/addressbook.xml", getappdir(), 1));
  xmlelem = XMLgetNode(xmlfile, "xml");

  channel = makeChanP("/sys/addressbook");

  retexit(1);

  while(1) {
    rcvid = recvMsg(channel,(void *)&msg); 

    switch(msg->code) {
      case GET_ATTRIB:
        returncode = getattrib();
      break;
      case GET_ALL_LIST:
        returncode = getalllist();
      break;
      case MAKE_ENTRY:
        returncode = makeentry();
      break;
      case PUT_ATTRIB:
        returncode = putattrib();
      break;
      case DEL_ENTRY:
        returncode = deleteentry();
      break;
      case DEL_ATTRIB:
        returncode = deleteattrib();
      break;
      case IO_OPEN:
        if(*(int *)( ((char*)msg) +6) & (O_PROC|O_STAT))
          returncode = makeCon(rcvid, 1);
        else 
          returncode = -1;
      break;
    }

    replyMsg(rcvid, returncode);    
  }
} 
Exemplo n.º 7
0
static void parsegroup(struct rnndb *db, char *file, xmlNode *node) {
	xmlAttr *attr = node->properties;
	char *name = 0;
	int i;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			name = getattrib(db, file, node->line, attr);
		} else {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for group\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	if (!name) {
		fprintf (stderr, "%s:%d: nameless group\n", file, node->line);
		db->estatus = 1;
		return;
	}
	struct rnngroup *cur = 0;
	for (i = 0; i < db->groupsnum; i++)
		if (!strcmp(db->groups[i]->name, name)) {
			cur = db->groups[i];
			break;
		}
	if (!cur) {
		cur = calloc(sizeof *cur, 1);
		cur->name = strdup(name);
		ADDARRAY(db->groups, cur);
	}
	xmlNode *chain = node->children;
	while (chain) {
		struct rnndelem *delem;
		if (chain->type != XML_ELEMENT_NODE) {
		} else if ((delem = trydelem(db, file, chain))) {
			ADDARRAY(cur->subelems, delem);
		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in group: <%s>\n", file, chain->line, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
}
Exemplo n.º 8
0
static int trytop (struct rnndb *db, char *file, xmlNode *node) {
	if (!strcmp(node->name, "enum")) {
		parseenum(db, file, node);
		return 1;
	} else if (!strcmp(node->name, "bitset")) {
		parsebitset(db, file, node);
		return 1;
	} else if (!strcmp(node->name, "group")) {
		parsegroup(db, file, node);
		return 1;
	} else if (!strcmp(node->name, "domain")) {
		parsedomain(db, file, node);
		return 1;
	} else if (!strcmp(node->name, "spectype")) {
		parsespectype(db, file, node);
		return 1;
	} else if (!strcmp(node->name, "import")) {
		xmlAttr *attr = node->properties;
		char *subfile = 0;
		while (attr) {
			if (!strcmp(attr->name, "file")) {
				subfile = getattrib(db, file, node->line, attr);
			} else {
				fprintf (stderr, "%s:%d: wrong attribute \"%s\" for import\n", file, node->line, attr->name);
				db->estatus = 1;
			}
			attr = attr->next;
		}
		if (!subfile) {
			fprintf (stderr, "%s:%d: missing \"file\" attribute for import\n", file, node->line);
			db->estatus = 1;
		} else {
			rnn_parsefile(db, subfile);
		}
		return 1;
	} else if (!strcmp(node->name, "copyright")) {
		parsecopyright(db, file, node);
		return 1;
	}
	return 0;
}
Exemplo n.º 9
0
static void parsespectype(struct rnndb *db, char *file, xmlNode *node) {
	struct rnnspectype *res = calloc (sizeof *res, 1);
	res->file = file;
	xmlAttr *attr = node->properties;
	int i;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			res->name = strdup(getattrib(db, file, node->line, attr));
		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for spectype\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	if (!res->name) {
		fprintf (stderr, "%s:%d: nameless spectype\n", file, node->line);
		db->estatus = 1;
		return;
	}
	for (i = 0; i < db->spectypesnum; i++)
		if (!strcmp(db->spectypes[i]->name, res->name)) {
			fprintf (stderr, "%s:%d: duplicated spectype name %s\n", file, node->line, res->name);
			db->estatus = 1;
			return;
		}
	ADDARRAY(db->spectypes, res);
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in spectype: <%s>\n", file, chain->line, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
}
Exemplo n.º 10
0
static void parsecopyright(struct rnndb *db, char *file, xmlNode *node) {
	struct rnncopyright* copyright = &db->copyright;
	xmlAttr *attr = node->properties;
	while (attr) {
		if (!strcmp(attr->name, "year")) {
			unsigned firstyear = getnumattrib(db, file, node->line, attr);
			if(!copyright->firstyear || firstyear < copyright->firstyear)
				copyright->firstyear = firstyear;
		} else {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for copyright\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!strcmp(chain->name, "license"))
			if(copyright->license) {
				if(strcmp(copyright->license, node->content)) {
					fprintf(stderr, "fatal error: multiple different licenses specified!\n");
					abort(); /* TODO: do something better here, but headergen, xml2html, etc. should not produce anything in this case */
				}
			} else
				copyright->license = getcontent(chain);
		else if (!strcmp(chain->name, "author")) {
			struct rnnauthor* author = calloc(sizeof *author, 1);
			xmlAttr* authorattr = chain->properties;
			xmlNode *authorchild = chain->children;
			author->contributions = getcontent(chain);
			while (authorattr) {
				if (!strcmp(authorattr->name, "name"))
					author->name = strdup(getattrib(db, file, chain->line, authorattr));
				else if (!strcmp(authorattr->name, "email"))
					author->email = strdup(getattrib(db, file, chain->line, authorattr));
				else {
					fprintf (stderr, "%s:%d: wrong attribute \"%s\" for author\n", file, chain->line, authorattr->name);
					db->estatus = 1;
				}
				authorattr = authorattr->next;
			}
			while(authorchild)  {
				if (authorchild->type != XML_ELEMENT_NODE) {
				} else if (!strcmp(authorchild->name, "nick")) {
					xmlAttr* nickattr = authorchild->properties;
					char* nickname = 0;
					while(nickattr) {
						if (!strcmp(nickattr->name, "name"))
							nickname = strdup(getattrib(db, file, authorchild->line, nickattr));
						else {
							fprintf (stderr, "%s:%d: wrong attribute \"%s\" for nick\n", file, authorchild->line, nickattr->name);
							db->estatus = 1;
						}
						nickattr = nickattr->next;
					}
					if(!nickname) {
						fprintf (stderr, "%s:%d: missing \"name\" attribute for nick\n", file, authorchild->line);
						db->estatus = 1;
					} else
						ADDARRAY(author->nicknames, nickname);
				} else {
					fprintf (stderr, "%s:%d: wrong tag in author: <%s>\n", file, authorchild->line, authorchild->name);
					db->estatus = 1;
				}
				authorchild = authorchild->next;
			}
			ADDARRAY(copyright->authors, author);
		} else {
			fprintf (stderr, "%s:%d: wrong tag in copyright: <%s>\n", file, chain->line, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
}
Exemplo n.º 11
0
static void parsedomain(struct rnndb *db, char *file, xmlNode *node) {
	xmlAttr *attr = node->properties;
	char *name = 0;
	uint64_t size = 0; int width = 8;
	int bare = 0;
	char *prefixstr = 0;
	char *varsetstr = 0;
	char *variantsstr = 0;
	int i;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			name = getattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "bare")) {
			bare = getboolattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "size")) {
			size = getnumattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "width")) {
			width = getnumattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "prefix")) {
			prefixstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "varset")) {
			varsetstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "variants")) {
			variantsstr = strdup(getattrib(db, file, node->line, attr));
		} else {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for domain\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	if (!name) {
		fprintf (stderr, "%s:%d: nameless domain\n", file, node->line);
		db->estatus = 1;
		return;
	}
	struct rnndomain *cur = 0;
	for (i = 0; i < db->domainsnum; i++)
		if (!strcmp(db->domains[i]->name, name)) {
			cur = db->domains[i];
			break;
		}
	if (cur) {
		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
				strdiff(cur->varinfo.varsetstr, varsetstr) ||
				strdiff(cur->varinfo.variantsstr, variantsstr) ||
				cur->width != width ||
				cur->bare != bare ||
				(size && cur->size && size != cur->size)) {
			fprintf (stderr, "%s:%d: merge fail for domain %s\n", file, node->line, node->name);
			db->estatus = 1;
		} else {
			if (size)
				cur->size = size;
		}
	} else {
		cur = calloc(sizeof *cur, 1);
		cur->name = strdup(name);
		cur->bare = bare;
		cur->width = width;
		cur->size = size;
		cur->varinfo.prefixstr = prefixstr;
		cur->varinfo.varsetstr = varsetstr;
		cur->varinfo.variantsstr = variantsstr;
		cur->file = file;
		ADDARRAY(db->domains, cur);
	}
	xmlNode *chain = node->children;
	while (chain) {
		struct rnndelem *delem;
		if (chain->type != XML_ELEMENT_NODE) {
		} else if ((delem = trydelem(db, file, chain))) {
			ADDARRAY(cur->subelems, delem);
		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in domain: <%s>\n", file, chain->line, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
}
Exemplo n.º 12
0
static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
	if (!strcmp(node->name, "use-group")) {
		struct rnndelem *res = calloc(sizeof *res, 1);
		res->file = file;
		res->type = RNN_ETYPE_USE_GROUP;
		xmlAttr *attr = node->properties;
		while (attr) {
			if (!strcmp(attr->name, "name")) {
				res->name = strdup(getattrib(db, file, node->line, attr));
			} else {
				fprintf (stderr, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
				db->estatus = 1;
			}
			attr = attr->next;
		}
		if (!res->name) {
			fprintf (stderr, "%s:%d: nameless use-group\n", file, node->line);
			db->estatus = 1;
			return 0;
		}
		return res;
	} else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) {
		struct rnndelem *res = calloc(sizeof *res, 1);
		res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE);
		res->length = 1;
		res->file = file;
		xmlAttr *attr = node->properties;
		while (attr) {
			if (!strcmp(attr->name, "name")) {
				res->name = strdup(getattrib(db, file, node->line, attr));
			} else if (!strcmp(attr->name, "offset")) {
				res->offset = getnumattrib(db, file, node->line, attr);
			} else if (!strcmp(attr->name, "length")) {
				res->length = getnumattrib(db, file, node->line, attr);
			} else if (!strcmp(attr->name, "stride")) {
				res->stride = getnumattrib(db, file, node->line, attr);
			} else if (!strcmp(attr->name, "prefix")) {
				res->varinfo.prefixstr = strdup(getattrib(db, file, node->line, attr));
			} else if (!strcmp(attr->name, "varset")) {
				res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
			} else if (!strcmp(attr->name, "variants")) {
				res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
			} else {
				fprintf (stderr, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
				db->estatus = 1;
			}
			attr = attr->next;
		}
		xmlNode *chain = node->children;
		while (chain) {
			struct rnndelem *delem;
			if (chain->type != XML_ELEMENT_NODE) {
			} else if ((delem = trydelem(db, file, chain))) {
				ADDARRAY(res->subelems, delem);
			} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
				fprintf (stderr, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
				db->estatus = 1;
			}
			chain = chain->next;
		}

		/* Sanity checking */
		if (res->type == RNN_ETYPE_ARRAY && res->stride == 0) {
			fprintf(stderr, "%s: Array %s's stride is undefined. Aborting.\n", file, res->name);
			exit(-1);
		}
		return res;

	}
	int width;
	if (!strcmp(node->name, "reg8"))
		width = 8;
	else if (!strcmp(node->name, "reg16"))
		width = 16;
	else if (!strcmp(node->name, "reg32"))
		width = 32;
	else if (!strcmp(node->name, "reg64"))
		width = 64;
	else
		return 0;
	struct rnndelem *res = calloc(sizeof *res, 1);
	res->file = file;
	res->type = RNN_ETYPE_REG;
	res->width = width;
	res->length = 1;
	res->access = RNN_ACCESS_RW;
	xmlAttr *attr = node->properties;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			res->name = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "offset")) {
			res->offset = getnumattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "length")) {
			res->length = getnumattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "stride")) {
			res->stride = getnumattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "varset")) {
			res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "variants")) {
			res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "access")) {
			char *str = getattrib(db, file, node->line, attr);
			if (!strcmp(str, "r"))
				res->access = RNN_ACCESS_R;
			else if (!strcmp(str, "w"))
				res->access = RNN_ACCESS_W;
			else if (!strcmp(str, "rw"))
				res->access = RNN_ACCESS_RW;
			else
				fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str);
		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
	if (!res->name) {
		fprintf (stderr, "%s:%d: nameless register\n", file, node->line);
		db->estatus = 1;
		return 0;
	} else {
	}
	return res;
}
Exemplo n.º 13
0
static void parsebitset(struct rnndb *db, char *file, xmlNode *node) {
	xmlAttr *attr = node->properties;
	char *name = 0;
	int isinline = 0;
	int bare = 0;
	char *prefixstr = 0;
	char *varsetstr = 0;
	char *variantsstr = 0;
	int i;
	while (attr) {
		if (!strcmp(attr->name, "name")) {
			name = getattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "bare")) {
			bare = getboolattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "inline")) {
			isinline = getboolattrib(db, file, node->line, attr);
		} else if (!strcmp(attr->name, "prefix")) {
			prefixstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "varset")) {
			varsetstr = strdup(getattrib(db, file, node->line, attr));
		} else if (!strcmp(attr->name, "variants")) {
			variantsstr = strdup(getattrib(db, file, node->line, attr));
		} else {
			fprintf (stderr, "%s:%d: wrong attribute \"%s\" for bitset\n", file, node->line, attr->name);
			db->estatus = 1;
		}
		attr = attr->next;
	}
	if (!name) {
		fprintf (stderr, "%s:%d: nameless bitset\n", file, node->line);
		db->estatus = 1;
		return;
	}
	struct rnnbitset *cur = 0;
	for (i = 0; i < db->bitsetsnum; i++)
		if (!strcmp(db->bitsets[i]->name, name)) {
			cur = db->bitsets[i];
			break;
		}
	if (cur) {
		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
				strdiff(cur->varinfo.varsetstr, varsetstr) ||
				strdiff(cur->varinfo.variantsstr, variantsstr) ||
				cur->isinline != isinline || cur->bare != bare) {
			fprintf (stderr, "%s:%d: merge fail for bitset %s\n", file, node->line, node->name);
			db->estatus = 1;
		}
	} else {
		cur = calloc(sizeof *cur, 1);
		cur->name = strdup(name);
		cur->isinline = isinline;
		cur->bare = bare;
		cur->varinfo.prefixstr = prefixstr;
		cur->varinfo.varsetstr = varsetstr;
		cur->varinfo.variantsstr = variantsstr;
		cur->file = file;
		ADDARRAY(db->bitsets, cur);
	}
	xmlNode *chain = node->children;
	while (chain) {
		if (chain->type != XML_ELEMENT_NODE) {
		} else if (!strcmp(chain->name, "bitfield")) {
			struct rnnbitfield *bf = parsebitfield(db, file, chain);
			if (bf)
				ADDARRAY(cur->bitfields, bf);
		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
			fprintf (stderr, "%s:%d: wrong tag in bitset: <%s>\n", file, chain->line, chain->name);
			db->estatus = 1;
		}
		chain = chain->next;
	}
}