Esempio n. 1
0
/**
 * Destroys a parser.
 */
void parser_destroy(struct parser *p) {
	struct parser_hook *h;
	parser_freeold(p);
	while (p->hooks) {
		h = p->hooks->next;
		clean_specs(p->hooks);
		mem_free(p->hooks);
		p->hooks = h;
	}
	mem_free(p);
}
Esempio n. 2
0
/* This is a bit long and should probably be refactored a bit. */
enum parser_error parser_parse(struct parser *p, const char *line) {
	char *cline;
	char *tok;
	struct parser_hook *h;
	struct parser_spec *s;
	struct parser_value *v;
	char *sp = NULL;

	assert(p);
	assert(line);

	parser_freeold(p);

	p->lineno++;
	p->colno = 1;
	p->fhead = NULL;
	p->ftail = NULL;

	/* Ignore empty lines and comments. */
	while (*line && (isspace(*line)))
		line++;
	if (!*line || *line == '#')
		return PARSE_ERROR_NONE;

	cline = string_make(line);

	tok = strtok(cline, ":");
	if (!tok) {
		mem_free(cline);
		p->error = PARSE_ERROR_MISSING_FIELD;
		return PARSE_ERROR_MISSING_FIELD;
	}

	h = findhook(p, tok);
	if (!h) {
		my_strcpy(p->errmsg, tok, sizeof(p->errmsg));
		p->error = PARSE_ERROR_UNDEFINED_DIRECTIVE;
		mem_free(cline);
		return PARSE_ERROR_UNDEFINED_DIRECTIVE;
	}

	/* There's a little bit of trickiness here to account for optional
	 * types. The optional flag has a bit assigned to it in the spec's type
	 * tag; we compute a temporary type for the spec with that flag removed
	 * and use that instead. */
	for (s = h->fhead; s; s = s->next)
	{
		int t = s->type & ~T_OPT;
		p->colno++;
		/* These types are tokenized on ':'; strings are not tokenized
		 * at all (i.e., they consume the remainder of the line) */
		if (t == T_INT || t == T_SYM || t == T_RAND || t == T_UINT) {
			tok = strtok(sp, ":");
			sp = NULL;
		} else if (t == T_CHAR) {
			tok = strtok(sp, "");
			if (tok)
				sp = tok + 2;
		} else {
			tok = strtok(sp, "");
			sp = NULL;
		}
		if (!tok)
		{
			if (!(s->type & T_OPT)) {
				my_strcpy(p->errmsg, s->name, sizeof(p->errmsg));
				p->error = PARSE_ERROR_MISSING_FIELD;
				mem_free(cline);
				return PARSE_ERROR_MISSING_FIELD;
			}
			break;
		}

		/* Allocate a value node, parse out its value, and link it into
		 * the value list. */
		v = mem_alloc(sizeof *v);
		v->spec.next = NULL;
		v->spec.type = s->type;
		v->spec.name = s->name;
		if (t == T_INT)
		{
			char *z = NULL;
			v->u.ival = strtol(tok, &z, 0);
			if (z == tok)
			{
				mem_free(v);
				mem_free(cline);
				my_strcpy(p->errmsg, s->name, sizeof(p->errmsg));
				p->error = PARSE_ERROR_NOT_NUMBER;
				return PARSE_ERROR_NOT_NUMBER;
			}
		}
		else if (t == T_UINT)
		{
			char *z = NULL;
			v->u.uval = strtoul(tok, &z, 0);
			if (z == tok || *tok == '-')
			{
				mem_free(v);
				mem_free(cline);
				my_strcpy(p->errmsg, s->name, sizeof(p->errmsg));
				p->error = PARSE_ERROR_NOT_NUMBER;
				return PARSE_ERROR_NOT_NUMBER;
			}
		}
		else if (t == T_CHAR)
		{
			v->u.cval = *tok;
		}
		else if (t == T_SYM || t == T_STR)
		{
			v->u.sval = string_make(tok);
		}
		else if (t == T_RAND)
		{
			if (!parse_random(tok, &v->u.rval))
			{
				mem_free(v);
				mem_free(cline);
				my_strcpy(p->errmsg, s->name, sizeof(p->errmsg));
				p->error = PARSE_ERROR_NOT_RANDOM;
				return PARSE_ERROR_NOT_RANDOM;
			}
		}
		if (!p->fhead)
			p->fhead = v;
		else
			p->ftail->spec.next = &v->spec;
		p->ftail = v;
	}

	mem_free(cline);

	p->error = h->func(p);
	return p->error;
}