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(¶m); if (prototype_push_param(&fun, ¶m) < 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(¶m, type, own); if (prototype_push_param(&fun, ¶m) < 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; }