/* Syntax: array ( type, N|argN ) */
static int
parse_array(struct protolib *plib, struct locus *loc,
	    char **str, struct arg_type_info *info)
{
	eat_spaces(str);
	if (parse_char(loc, str, '(') < 0)
		return -1;

	eat_spaces(str);
	int own;
	struct arg_type_info *elt_info
		= parse_lens(plib, loc, str, NULL, 0, &own, NULL);
	if (elt_info == NULL)
		return -1;

	eat_spaces(str);
	parse_char(loc, str, ',');

	eat_spaces(str);
	int own_length;
	struct expr_node *length = parse_argnum(loc, str, &own_length, 0);
	if (length == NULL) {
		if (own) {
			type_destroy(elt_info);
			free(elt_info);
		}
		return -1;
	}

	type_init_array(info, elt_info, own, length, own_length);

	eat_spaces(str);
	parse_char(loc, str, ')');
	return 0;
}
static struct arg_type_info *
parse_type(struct protolib *plib, struct locus *loc, char **str,
	   struct param **extra_param, size_t param_num,
	   int *ownp, int *forwardp)
{
	struct arg_type_info *info
		= parse_nonpointer_type(plib, loc, str, extra_param,
					param_num, ownp, forwardp);
	if (info == NULL)
		return NULL;

	while (1) {
		eat_spaces(str);
		if (**str == '*') {
			struct arg_type_info *outer = malloc(sizeof(*outer));
			if (outer == NULL) {
				if (*ownp) {
					type_destroy(info);
					free(info);
				}
				report_error(loc->filename, loc->line_no,
					     "malloc: %s", strerror(errno));
				return NULL;
			}
			type_init_pointer(outer, info, *ownp);
			*ownp = 1;
			(*str)++;
			info = outer;
		} else
			break;
	}
	return info;
}
Example #3
0
File: value.c Project: 5py/ltrace
void
value_set_type(struct value *value, struct arg_type_info *type, int own_type)
{
	if (value->own_type) {
		type_destroy(value->type);
		free(value->type);
	}
	value->type = type;
	value->own_type = own_type;
}
Example #4
0
static int
fetch_param_pack(enum tof type, struct process *proc,
                 struct fetch_context *context,
                 struct value_dict *arguments, struct param *param,
                 ssize_t *params_leftp)
{
    struct param_enum *e = param_pack_init(param, arguments);
    if (e == NULL)
        return -1;

    int ret = 0;
    while (1) {
        int insert_stop = 0;
        struct arg_type_info *info = malloc(sizeof(*info));
        if (info == NULL
                || param_pack_next(param, e, info, &insert_stop) < 0) {
fail:
            free(info);
            ret = -1;
            break;
        }

        if (insert_stop)
            fetch_param_stop(arguments, params_leftp);

        if (info->type == ARGTYPE_VOID) {
            type_destroy(info);
            free(info);
            break;
        }

        struct value val;
        if (fetch_simple_param(type, proc, context, arguments,
                               info, 1, &val) < 0)
            goto fail;

        int stop = 0;
        switch (param_pack_stop(param, e, &val)) {
        case PPCB_ERR:
            goto fail;
        case PPCB_STOP:
            stop = 1;
        case PPCB_CONT:
            break;
        }

        if (stop)
            break;
    }

    param_pack_done(param, e);
    return ret;
}
/* Syntax: struct ( type,type,type,... ) */
static int
parse_struct(struct protolib *plib, struct locus *loc,
	     char **str, struct arg_type_info *info,
	     int *forwardp)
{
	eat_spaces(str);

	if (**str == ';') {
		if (forwardp == NULL) {
			report_error(loc->filename, loc->line_no,
				     "Forward struct can be declared only "
				     "directly after a typedef.");
			return -1;
		}

		/* Forward declaration is currently handled as an
		 * empty struct.  */
		type_init_struct(info);
		*forwardp = 1;
		return 0;
	}

	if (parse_char(loc, str, '(') < 0)
		return -1;

	eat_spaces(str); // Empty arg list with whitespace inside

	type_init_struct(info);

	while (1) {
		eat_spaces(str);
		if (**str == 0 || **str == ')') {
			parse_char(loc, str, ')');
			return 0;
		}

		/* Field delimiter.  */
		if (type_struct_size(info) > 0)
			parse_char(loc, str, ',');

		eat_spaces(str);
		int own;
		struct arg_type_info *field
			= parse_lens(plib, loc, str, NULL, 0, &own, NULL);
		if (field == NULL || type_struct_add(info, field, own)) {
			type_destroy(info);
			return -1;
		}
	}
}
/* Syntax:
 *   enum (keyname[=value],keyname[=value],... )
 *   enum<type> (keyname[=value],keyname[=value],... )
 */
static int
parse_enum(struct protolib *plib, struct locus *loc, char **str,
	   struct arg_type_info **retp, int *ownp)
{
	/* Optional type argument.  */
	eat_spaces(str);
	if (**str == '[') {
		parse_char(loc, str, '[');
		eat_spaces(str);
		*retp = parse_nonpointer_type(plib, loc, str, NULL, 0, ownp, 0);
		if (*retp == NULL)
			return -1;

		if (!type_is_integral((*retp)->type)) {
			report_error(loc->filename, loc->line_no,
				     "integral type required as enum argument");
		fail:
			if (*ownp) {
				/* This also releases associated lens
				 * if any was set so far.  */
				type_destroy(*retp);
				free(*retp);
			}
			return -1;
		}

		eat_spaces(str);
		if (parse_char(loc, str, ']') < 0)
			goto fail;

	} else {
		*retp = type_get_simple(ARGTYPE_INT);
		*ownp = 0;
	}

	/* We'll need to set the lens, so unshare.  */
	if (unshare_type_info(loc, retp, ownp) < 0)
		goto fail;

	eat_spaces(str);
	if (parse_char(loc, str, '(') < 0)
		goto fail;

	struct enum_lens *lens = malloc(sizeof(*lens));
	if (lens == NULL) {
		report_error(loc->filename, loc->line_no,
			     "malloc enum lens: %s", strerror(errno));
		return -1;
	}

	lens_init_enum(lens);
	(*retp)->lens = &lens->super;
	(*retp)->own_lens = 1;

	long last_val = 0;
	while (1) {
		eat_spaces(str);
		if (**str == 0 || **str == ')') {
			parse_char(loc, str, ')');
			return 0;
		}

		/* Field delimiter.  XXX should we support the C
		 * syntax, where the enumeration can end in pending
		 * comma?  */
		if (lens_enum_size(lens) > 0)
			parse_char(loc, str, ',');

		eat_spaces(str);
		char *key = parse_ident(loc, str);
		if (key == NULL) {
		err:
			free(key);
			goto fail;
		}

		if (**str == '=') {
			++*str;
			eat_spaces(str);
			if (parse_int(loc, str, &last_val) < 0)
				goto err;
		}

		struct value *value = malloc(sizeof(*value));
		if (value == NULL)
			goto err;
		value_init_detached(value, NULL, *retp, 0);
		value_set_word(value, last_val);

		if (lens_enum_add(lens, key, 1, value, 1) < 0)
			goto err;

		last_val++;
	}

	return 0;
}
static int
parse_typedef(struct protolib *plib, struct locus *loc, char **str)
{
	(*str) += strlen("typedef");
	eat_spaces(str);
	char *name = parse_ident(loc, str);

	/* Look through the typedef list whether we already have a
	 * forward of this type.  If we do, it must be forward
	 * structure.  */
	struct named_type *forward = protolib_lookup_type(plib, name, true);
	if (forward != NULL
	    && (forward->info->type != ARGTYPE_STRUCT
		|| !forward->forward)) {
		report_error(loc->filename, loc->line_no,
			     "Redefinition of typedef '%s'", name);
	err:
		free(name);
		return -1;
	}

	// Skip = sign
	eat_spaces(str);
	if (parse_char(loc, str, '=') < 0)
		goto err;
	eat_spaces(str);

	int fwd = 0;
	int own = 0;
	struct arg_type_info *info
		= parse_lens(plib, loc, str, NULL, 0, &own, &fwd);
	if (info == NULL)
		goto err;

	struct named_type this_nt;
	named_type_init(&this_nt, info, own);
	this_nt.forward = fwd;

	if (forward == NULL) {
		if (protolib_add_named_type(plib, name, 1, &this_nt) < 0) {
			named_type_destroy(&this_nt);
			goto err;
		}
		return 0;
	}

	/* If we are defining a forward, make sure the definition is a
	 * structure as well.  */
	if (this_nt.info->type != ARGTYPE_STRUCT) {
		report_error(loc->filename, loc->line_no,
			     "Definition of forward '%s' must be a structure.",
			     name);
		named_type_destroy(&this_nt);
		goto err;
	}

	/* Now move guts of the actual type over to the forward type.
	 * We can't just move pointers around, because references to
	 * forward must stay intact.  */
	assert(this_nt.own_type);
	type_destroy(forward->info);
	*forward->info = *this_nt.info;
	forward->forward = 0;
	free(this_nt.info);
	free(name);
	return 0;
}