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; }
static int fetch_simple_param(enum tof type, struct process *proc, struct fetch_context *context, struct value_dict *arguments, struct arg_type_info *info, int own, struct value *valuep) { /* Arrays decay into pointers per C standard. We check for * this here, because here we also capture arrays that come * from parameter packs. */ if (info->type == ARGTYPE_ARRAY) { struct arg_type_info *tmp = malloc(sizeof(*tmp)); if (tmp != NULL) { type_init_pointer(tmp, info, own); tmp->lens = info->lens; info = tmp; own = 1; } } struct value value; value_init(&value, proc, NULL, info, own); if (fetch_arg_next(context, type, proc, info, &value) < 0) return -1; if (val_dict_push_next(arguments, &value) < 0) { value_destroy(&value); return -1; } if (valuep != NULL) *valuep = value; return 0; }
int value_pass_by_reference(struct value *value) { assert(value != NULL); assert(value->type->type == ARGTYPE_STRUCT); struct arg_type_info *new_info = calloc(sizeof(*new_info), 1); if (new_info == NULL) return -1; int own; struct arg_type_info *orig; value_take_type(value, &orig, &own); type_init_pointer(new_info, orig, own); new_info->lens = orig->lens; value_set_type(value, new_info, 1); return 0; }
static int parse_string(struct protolib *plib, struct locus *loc, char **str, struct arg_type_info **retp, int *ownp) { struct arg_type_info *info = NULL; struct expr_node *length; int own_length; if (isdigit(CTYPE_CONV(**str))) { /* string0 is string[retval], length is zero(retval) * stringN is string[argN], length is zero(argN) */ long l; if (parse_int(loc, str, &l) < 0 || check_int(loc, l) < 0) return -1; struct expr_node *length_arg = malloc(sizeof(*length_arg)); if (length_arg == NULL) return -1; if (l == 0) expr_init_named(length_arg, "retval", 0); else expr_init_argno(length_arg, l - 1); length = build_zero_w_arg(length_arg, 1); if (length == NULL) { expr_destroy(length_arg); free(length_arg); return -1; } own_length = 1; } else { eat_spaces(str); if (**str == '[') { (*str)++; eat_spaces(str); length = parse_argnum(loc, str, &own_length, 1); if (length == NULL) return -1; eat_spaces(str); parse_char(loc, str, ']'); } else if (**str == '(') { /* Usage of "string" as lens. */ ++*str; eat_spaces(str); info = parse_type(plib, loc, str, NULL, 0, ownp, NULL); if (info == NULL) return -1; length = NULL; own_length = 0; eat_spaces(str); parse_char(loc, str, ')'); } else { /* It was just a simple string after all. */ length = expr_node_zero(); own_length = 0; } } /* String is a pointer to array of chars. */ if (info == NULL) { struct arg_type_info *info1 = malloc(sizeof(*info1)); struct arg_type_info *info2 = malloc(sizeof(*info2)); if (info1 == NULL || info2 == NULL) { free(info1); free(info2); fail: if (own_length) { assert(length != NULL); expr_destroy(length); free(length); } return -1; } type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0, length, own_length); type_init_pointer(info1, info2, 1); info = info1; *ownp = 1; } /* We'll need to set the lens, so unshare. */ if (unshare_type_info(loc, &info, ownp) < 0) /* If unshare_type_info failed, it must have been as a * result of cloning attempt because *OWNP was 0. * Thus we don't need to destroy INFO. */ goto fail; info->lens = &string_lens; info->own_lens = 0; *retp = info; return 0; }