Beispiel #1
0
void param_list_destroy(param_list* list)
{
	param* prm = list->head;
	param* next;

	while (prm != NULL) {
		next = prm->next;
		param_destroy(prm);
		prm = next;
	}

	managed_free(list);
}
static enum callback_status
void_to_hidden_int(struct prototype *proto, struct param *param, void *data)
{
	struct locus *loc = data;
	if (param_is_void(param)) {
		report_warning(loc->filename, loc->line_no,
			       "void parameter assumed to be 'hide(int)'");

		static struct arg_type_info *type = NULL;
		if (type == NULL)
			type = get_hidden_int();
		param_destroy(param);
		param_init_type(param, type, 0);
	}
	return CBS_CONT;
}
void param_finish (void) /* {{{ */
{
  param_destroy (pl_global);
  pl_global = NULL;
} /* }}} void param_finish */
static int
process_line(struct protolib *plib, struct locus *loc, char *buf)
{
	char *str = buf;
	char *tmp;

	debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
	eat_spaces(&str);

	/* A comment or empty line.  */
	if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
		return 0;

	if (strncmp(str, "typedef", 7) == 0) {
		parse_typedef(plib, loc, &str);
		return 0;
	}

	struct prototype fun;
	prototype_init(&fun);

	struct param *extra_param = NULL;
	char *proto_name = NULL;
	int own;
	fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
	if (fun.return_info == NULL) {
	err:
		debug(3, " Skipping line %d", loc->line_no);

		if (extra_param != NULL) {
			param_destroy(extra_param);
			free(extra_param);
		}

		prototype_destroy(&fun);
		free(proto_name);
		return -1;
	}
	fun.own_return_info = own;
	debug(4, " return_type = %d", fun.return_info->type);

	eat_spaces(&str);
	tmp = start_of_arg_sig(str);
	if (tmp == NULL) {
		report_error(loc->filename, loc->line_no, "syntax error");
		goto err;
	}
	*tmp = '\0';

	proto_name = strdup(str);
	if (proto_name == NULL) {
	oom:
		report_error(loc->filename, loc->line_no,
			     "%s", strerror(errno));
		goto err;
	}

	str = tmp + 1;
	debug(3, " name = %s", proto_name);

	int have_stop = 0;

	while (1) {
		eat_spaces(&str);
		if (*str == ')')
			break;

		if (str[0] == '+') {
			if (have_stop == 0) {
				struct param param;
				param_init_stop(&param);
				if (prototype_push_param(&fun, &param) < 0)
					goto oom;
				have_stop = 1;
			}
			str++;
		}

		int own;
		size_t param_num = prototype_num_params(&fun) - have_stop;
		struct arg_type_info *type
			= parse_lens(plib, loc, &str, &extra_param,
				     param_num, &own, NULL);
		if (type == NULL) {
			report_error(loc->filename, loc->line_no,
				     "unknown argument type");
			goto err;
		}

		struct param param;
		param_init_type(&param, type, own);
		if (prototype_push_param(&fun, &param) < 0)
			goto oom;

		eat_spaces(&str);
		if (*str == ',') {
			str++;
			continue;
		} else if (*str == ')') {
			continue;
		} else {
			if (str[strlen(str) - 1] == '\n')
				str[strlen(str) - 1] = '\0';
			report_error(loc->filename, loc->line_no,
				     "syntax error around \"%s\"", str);
			goto err;
		}
	}

	/* We used to allow void parameter as a synonym to an argument
	 * that shouldn't be displayed.  But backends really need to
	 * know the exact type that they are dealing with.  The proper
	 * way to do this these days is to use the hide lens.
	 *
	 * So if there are any voids in the parameter list, show a
	 * warning and assume that they are ints.  If there's a sole
	 * void, assume the function doesn't take any arguments.  The
	 * latter is conservative, we can drop the argument
	 * altogether, instead of fetching and then not showing it,
	 * without breaking any observable behavior.  */
	if (prototype_num_params(&fun) == 1
	    && param_is_void(prototype_get_nth_param(&fun, 0))) {
		if (0)
			/* Don't show this warning.  Pre-0.7.0
			 * ltrace.conf often used this idiom.  This
			 * should be postponed until much later, when
			 * extant uses are likely gone.  */
			report_warning(loc->filename, loc->line_no,
				       "sole void parameter ignored");
		prototype_destroy_nth_param(&fun, 0);
	} else {
		prototype_each_param(&fun, NULL, void_to_hidden_int, loc);
	}

	if (extra_param != NULL) {
		prototype_push_param(&fun, extra_param);
		free(extra_param);
		extra_param = NULL;
	}

	if (protolib_add_prototype(plib, proto_name, 1, &fun) < 0) {
		report_error(loc->filename, loc->line_no,
			     "couldn't add prototype: %s",
			     strerror(errno));
		goto err;
	}

	return 0;
}