/* 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; }
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; }
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; }