예제 #1
0
static VAttrList ReadAttrList (FILE *f)
{
    VAttrList sublist, list = VCreateAttrList ();
    VAttrRec *a;
    int ch = 0;
    size_t name_size;
    VBundle b;
    char buf[2], *str, name_buf[VMaxAttrNameLength + 1];

    /* Swallow a { marking the start of the attribute list: */
    if (fscanf (f, " %1s", buf) != 1 || buf[0] != '{') {
	VWarning ("VReadFile: Missing {");
	goto Fail;
    }

    /* For each attribute up to the next "}": */
    while (fscanf (f, " %[^}: \t\n]", name_buf) == 1) {
	name_size = strlen (name_buf);

	/* Read a : and the first character of the attribute's value: */
	if (fscanf (f, " %1s", buf) != 1 || buf[0] != ':' ||
	    fscanf (f, " %1s", buf) != 1) {
	    VWarning ("VReadFile: Invalid %s attribute", name_buf);
	    goto Fail;
	}

	/* The first character of the value tells us whether its an attribute
	   list, quoted string, or unquoted string: */
	if (buf[0] == '{') {

	    /* The attribute value is another list of attributes: */
	    ungetc ('{', f);
	    if (! (sublist = ReadAttrList (f)))
		goto Fail;
	    a = VMalloc (sizeof (VAttrRec) + name_size);
	    a->value = sublist;
	    a->repn = VAttrListRepn;

	} else {

	    /* The value doesn't start with '{' -- parse a word or string: */
	    if (! (str = ReadString (f, buf[0], name_buf)))
		goto Fail;
	    while ((ch = fgetc (f)) && (ch == ' ' || ch == '\t')) ;
	    ungetc (ch, f);

	    /* If the word is followed by an '{'... */
	    if (ch == '{') {

		/* ...then it's a typed value -- the word is it's type name
		   and the { is the start of it's attribute list value. */
		b = VCreateBundle (str, NULL, 0, NULL);
		if (! (sublist = ReadAttrList (f))) {
		    VFree (b);
		    goto Fail;
		}
		b->list = sublist;
		a = VMalloc (sizeof (VAttrRec) + name_size);
		a->repn = VBundleRepn;
		a->value = b;

	    } else {

		/* ...otherwise store it as a simple string value: */
		a = VMalloc (sizeof (VAttrRec) + name_size + strlen (str) + 1);
		a->repn = VStringRepn;
		a->value = a->name + name_size + 1;
		strcpy (a->value, str);
	    }
	    VFree(str);
	}

	/* Copy the attribute's name into the newly allocated node: */
	strcpy (a->name, name_buf);

	/* Place the new node on the end of the growing attribute list: */
	a->next = NULL;
	a->prev = list->prev;
	if (a->prev) a->prev->next = a;
	else list->next = a;
	list->prev = a;
    }

    /* Swallow the terminating "}": */
    if (fscanf (f, " %1s", buf) != 1 || buf[0] != '}') {
	VWarning ("VReadFile: Missing }");
Fail:	VDestroyAttrList (list);
	return NULL;
    }
    return list;
}
예제 #2
0
파일: Attr.c 프로젝트: Rollmops/via
VAttrList VCopyAttrList (VAttrList list)
{
    VAttrList new_list = VCreateAttrList ();
    size_t name_size, value_size;
    VAttrRec *old_a, *new_a;
    VBundle old_b, new_b;
    VTypeMethods *methods;

    /* For each node of the old list: */
    for (old_a = list->next; old_a; old_a = old_a->next) {

	/* Compute the amount of storage needed for a copy of the node: */
	name_size = strlen (old_a->name);
	value_size = (old_a->repn == VStringRepn) ?
	    strlen ((VStringConst) old_a->value) + 1 : 0;

	/* Allocate that size and fill in the node's value: */
	new_a = VMalloc (sizeof (VAttrRec) + name_size + value_size);
	strcpy (new_a->name, old_a->name);
	switch (new_a->repn = old_a->repn) {

	case VAttrListRepn:
	    new_a->value = VCopyAttrList (old_a->value);
	    break;

	case VBundleRepn:
	    old_b = old_a->value;
	    new_b = VCreateBundle (old_b->type_name,
				   VCopyAttrList (old_b->list),
				   old_b->length, NULL);
	    if (old_b->length > 0) {
		new_b->data = VMalloc (old_b->length);
		memcpy (new_b->data, old_b->data, old_b->length);
	    }
	    new_a->value = new_b;
	    break;

	case VPointerRepn:
	    new_a->value = old_a->value;
	    break;

	case VStringRepn:
	    new_a->value = (VPointer) (new_a->name + name_size + 1);
	    strcpy (new_a->value, old_a->value);
	    break;

	default:
	    if (methods = VRepnMethods (new_a->repn))
		new_a->value = (methods->copy) (old_a->value);
	    else VError ("VCopyAttrList: %s attribute has invalid repn %d",
			 old_a->name, old_a->repn);
	}

	/* Append it to the new list: */
	new_a->next = NULL;
	if (new_a->prev = new_list->prev)
	    new_a->prev->next = new_a;
	if (! new_list->next)
	    new_list->next = new_a;
	new_list->prev = new_a;
    }
    return new_list;
}