diff options
author | Petr Machata <pmachata@redhat.com> | 2012-12-17 04:37:57 +0100 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2013-03-08 22:55:25 +0100 |
commit | ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5b (patch) | |
tree | c88cfaa4857b798b09376d181f045617d42fe81b | |
parent | daefa4a03e16b56e54c6116cec44153aff9dd3b7 (diff) | |
download | ltrace-ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5b.tar.gz |
Introduce a module for managing prototypes and prototype libraries
This is to be used, eventually, for keeping one prototype library per DSO.
Right now we only have one prototype library, like before: g_prototypes.
Typedef submodule is not yet used, only prototypes are stored in the
protolib as of now.
The change in Makefile.am is actually an inclusion of prototype.{c,h}
followed by a rewrap of name lists.
-rw-r--r-- | Makefile.am | 77 | ||||
-rw-r--r-- | common.h | 10 | ||||
-rw-r--r-- | output.c | 99 | ||||
-rw-r--r-- | prototype.c | 263 | ||||
-rw-r--r-- | prototype.h | 155 | ||||
-rw-r--r-- | read_config_file.c | 137 |
6 files changed, 540 insertions, 201 deletions
diff --git a/Makefile.am b/Makefile.am index c3356de..db34382 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,36 +32,12 @@ AM_CPPFLAGS += \ noinst_LTLIBRARIES = \ libltrace.la -libltrace_la_SOURCES = \ - breakpoints.c \ - debug.c \ - demangle.c \ - dict.c \ - ltrace-elf.c \ - execute_program.c \ - handle_event.c \ - libltrace.c \ - options.c \ - output.c \ - proc.c \ - read_config_file.c \ - summary.c \ - library.c \ - filter.c \ - glob.c \ - type.c \ - value.c \ - value_dict.c \ - expr.c \ - fetch.c \ - vect.c \ - param.c \ - printf.c \ - zero.c \ - lens.c \ - lens_default.c \ - lens_enum.c \ - memstream.c +libltrace_la_SOURCES = breakpoints.c debug.c demangle.c dict.c \ + ltrace-elf.c execute_program.c handle_event.c libltrace.c \ + options.c output.c proc.c read_config_file.c summary.c \ + library.c filter.c glob.c type.c value.c value_dict.c expr.c \ + fetch.c vect.c param.c printf.c zero.c lens.c lens_default.c \ + lens_enum.c memstream.c prototype.c libltrace_la_LIBADD = \ $(libelf_LIBS) \ @@ -71,7 +47,6 @@ libltrace_la_LIBADD = \ $(libunwind_LIBS) \ sysdeps/libos.la - bin_PROGRAMS = \ ltrace @@ -81,40 +56,12 @@ ltrace_SOURCES = \ ltrace_LDADD = \ libltrace.la - -noinst_HEADERS = \ - backend.h \ - breakpoint.h \ - common.h \ - debug.h \ - defs.h \ - demangle.h \ - dict.h \ - forward.h \ - ltrace-elf.h \ - ltrace.h \ - options.h \ - output.h \ - proc.h \ - read_config_file.h \ - library.h \ - filter.h \ - glob.h \ - vect.h \ - type.h \ - value.h \ - value_dict.h \ - callback.h \ - expr.h \ - fetch.h \ - vect.h \ - param.h \ - printf.h \ - zero.h \ - lens.h \ - lens_default.h \ - lens_enum.h \ - memstream.h +noinst_HEADERS = backend.h breakpoint.h common.h debug.h defs.h \ + demangle.h dict.h forward.h ltrace-elf.h ltrace.h options.h \ + output.h proc.h read_config_file.h library.h filter.h glob.h \ + vect.h type.h value.h value_dict.h callback.h expr.h fetch.h \ + vect.h param.h printf.h zero.h lens.h lens_default.h \ + lens_enum.h memstream.h prototype.h dist_man1_MANS = ltrace.1 dist_man5_MANS = ltrace.conf.5 @@ -43,16 +43,6 @@ extern char * command; extern int exiting; /* =1 if we have to exit ASAP */ -struct prototype { - const char *name; - struct param *params; - struct arg_type_info *return_info; - int own_return_info; - size_t num_params; - struct prototype *next; -}; - -extern struct prototype *list_of_functions; extern char *PLTs_initialized_by_here; #include "options.h" @@ -34,7 +34,7 @@ #include <errno.h> #include <assert.h> -#include "common.h" +#include "output.h" #include "demangle.h" #include "fetch.h" #include "lens_default.h" @@ -43,6 +43,7 @@ #include "options.h" #include "param.h" #include "proc.h" +#include "prototype.h" #include "type.h" #include "value.h" #include "value_dict.h" @@ -152,58 +153,41 @@ get_unknown_type(void) static struct prototype * build_default_prototype(void) { - struct prototype *ret = malloc(sizeof(*ret)); - size_t i = 0; - if (ret == NULL) - goto err; - memset(ret, 0, sizeof(*ret)); + static struct prototype *ret = NULL; + if (ret != NULL) + return ret; - struct arg_type_info *unknown_type = get_unknown_type(); + static struct prototype proto; + prototype_init(&proto); - ret->return_info = unknown_type; - ret->own_return_info = 0; + struct arg_type_info *unknown_type = get_unknown_type(); + assert(unknown_type != NULL); + proto.return_info = unknown_type; + proto.own_return_info = 0; - ret->num_params = 4; - ret->params = malloc(sizeof(*ret->params) * ret->num_params); - if (ret->params == NULL) - goto err; + struct param unknown_param; + param_init_type(&unknown_param, unknown_type, 0); - for (i = 0; i < ret->num_params; ++i) - param_init_type(&ret->params[i], unknown_type, 0); + size_t i; + for (i = 0; i < 4; ++i) + if (prototype_push_param(&proto, &unknown_param) < 0) { + report_global_error("build_default_prototype: %s", + strerror(errno)); + prototype_destroy(&proto); + return NULL; + } + ret = &proto; return ret; - -err: - report_global_error("malloc: %s", strerror(errno)); - if (ret->params != NULL) { - while (i-- > 0) - param_destroy(&ret->params[i]); - free(ret->params); - } - - free(ret); - - return NULL; } static struct prototype * name2func(char const *name) { - struct prototype *tmp; - const char *str1, *str2; - - for (tmp = list_of_functions; tmp != NULL; tmp = tmp->next) { - str1 = tmp->name; - str2 = name; - if (!strcmp(str1, str2)) - return tmp; - } - - static struct prototype *def = NULL; - if (def == NULL) - def = build_default_prototype(); - - return def; + struct prototype *p = protolib_lookup_prototype(&g_prototypes, name); + if (p != NULL) + return p; + return build_default_prototype(); } void @@ -373,17 +357,38 @@ fetch_one_param(enum tof type, struct process *proc, abort(); } +struct fetch_one_param_data +{ + struct process *proc; + struct fetch_context *context; + struct value_dict *arguments; + ssize_t *params_leftp; + enum tof tof; +}; + +static enum callback_status +fetch_one_param_cb(struct prototype *proto, struct param *param, void *data) +{ + struct fetch_one_param_data *cb_data = data; + if (fetch_one_param(cb_data->tof, cb_data->proc, cb_data->context, + cb_data->arguments, param, + cb_data->params_leftp) < 0) + return CBS_STOP; + else + return CBS_CONT; +} + static int fetch_params(enum tof type, struct process *proc, struct fetch_context *context, struct value_dict *arguments, struct prototype *func, ssize_t *params_leftp) { - size_t i; - for (i = 0; i < func->num_params; ++i) - if (fetch_one_param(type, proc, context, arguments, - &func->params[i], params_leftp) < 0) - return -1; + struct fetch_one_param_data cb_data + = { proc, context, arguments, params_leftp, type }; + if (prototype_each_param(func, NULL, + &fetch_one_param_cb, &cb_data) != NULL) + return -1; /* Implicit stop at the end of parameter list. */ fetch_param_stop(arguments, params_leftp); diff --git a/prototype.c b/prototype.c new file mode 100644 index 0000000..0575dd3 --- /dev/null +++ b/prototype.c @@ -0,0 +1,263 @@ +/* + * This file is part of ltrace. + * Copyright (C) 2012 Petr Machata, Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <stdlib.h> +#include <string.h> + +#include "prototype.h" +#include "callback.h" +#include "param.h" +#include "type.h" + +struct protolib g_prototypes; + +void +prototype_init(struct prototype *proto) +{ + VECT_INIT(&proto->params, struct param); + + proto->return_info = NULL; + proto->own_return_info = 0; +} + +static void +param_destroy_cb(struct param *param, void *data) +{ + param_destroy(param); +} + +void +prototype_destroy(struct prototype *proto) +{ + if (proto == NULL) + return; + if (proto->own_return_info) { + type_destroy(proto->return_info); + free(proto->return_info); + } + + VECT_DESTROY(&proto->params, struct param, ¶m_destroy_cb, NULL); +} + +int +prototype_push_param(struct prototype *proto, struct param *param) +{ + return VECT_PUSHBACK(&proto->params, param); +} + +size_t +prototype_num_params(struct prototype *proto) +{ + return vect_size(&proto->params); +} + +void +prototype_destroy_nth_param(struct prototype *proto, size_t n) +{ + assert(n < prototype_num_params(proto)); + VECT_ERASE(&proto->params, struct param, n, n+1, + ¶m_destroy_cb, NULL); +} + +struct param * +prototype_get_nth_param(struct prototype *proto, size_t n) +{ + assert(n < prototype_num_params(proto)); + return VECT_ELEMENT(&proto->params, struct param, n); +} + +struct each_param_data { + struct prototype *proto; + enum callback_status (*cb)(struct prototype *, struct param *, void *); + void *data; +}; + +static enum callback_status +each_param_cb(struct param *param, void *data) +{ + struct each_param_data *cb_data = data; + return (cb_data->cb)(cb_data->proto, param, cb_data->data); +} + +struct param * +prototype_each_param(struct prototype *proto, struct param *start_after, + enum callback_status (*cb)(struct prototype *, + struct param *, void *), + void *data) +{ + struct each_param_data cb_data = { proto, cb, data }; + return VECT_EACH(&proto->params, struct param, start_after, + &each_param_cb, &cb_data); +} + +void +named_type_destroy(struct named_type *named) +{ + if (named->owned) { + type_destroy(named->info); + free(named->info); + } +} + +int +protolib_init(struct protolib *plib) +{ + plib->prototypes = dict_init(&dict_key2hash_string, + &dict_key_cmp_string); + if (plib->prototypes == NULL) + return -1; + + plib->named_types = dict_init(&dict_key2hash_string, + &dict_key_cmp_string); + if (plib->named_types == NULL) { + dict_clear(plib->prototypes); + return -1; + } + + VECT_INIT(&plib->imports, struct protolib *); + return 0; +} + +static void +prototype_entry_destroy(void *key, void *val, void *data) +{ + char *name = key; + struct prototype *proto = val; + free(name); + prototype_destroy(proto); +} + +static void +named_type_entry_destroy(void *key, void *val, void *data) +{ + char *name = key; + struct named_type *named = val; + free(name); + named_type_destroy(named); +} + +void +protolib_destroy(struct protolib *plib) +{ + VECT_DESTROY(&plib->imports, struct prototype *, NULL, NULL); + + dict_apply_to_all(plib->prototypes, prototype_entry_destroy, NULL); + dict_clear(plib->prototypes); + + dict_apply_to_all(plib->named_types, named_type_entry_destroy, NULL); + dict_clear(plib->named_types); +} + +static struct protolib ** +each_import(struct protolib *plib, struct protolib **start_after, + enum callback_status (*cb)(struct protolib **, void *), void *data) +{ + return VECT_EACH(&plib->imports, struct protolib *, + start_after, cb, data); +} + +static enum callback_status +is_or_imports(struct protolib **plibp, void *data) +{ + struct protolib *import = data; + if (*plibp == import + || each_import(*plibp, NULL, &is_or_imports, import) != NULL) + return CBS_STOP; + else + return CBS_CONT; +} + +int +protolib_add_import(struct protolib *plib, struct protolib *import) +{ + if (is_or_imports(&plib, import) == CBS_STOP) + return -2; + + return VECT_PUSHBACK(&plib->imports, import) < 0 ? -1 : 0; +} + +static int +enroll(struct dict *dict, const char *name, int own_name, void *value) +{ + assert(name != NULL); + + if (!own_name) { + name = strdup(name); + if (name == NULL) + return -1; + } + + if (dict_enter(dict, (void *)name, value) < 0) { + if (own_name) + free((void *)name); + return -1; + } + return 0; +} + +int +protolib_add_prototype(struct protolib *plib, const char *name, int own_name, + struct prototype *proto) +{ + return enroll(plib->prototypes, name, own_name, proto); +} + +int +protolib_add_named_type(struct protolib *plib, const char *name, int own_name, + struct named_type *named) +{ + return enroll(plib->named_types, name, own_name, named); +} + +struct lookup { + const char *name; + void *result; +}; + +static enum callback_status +lookup_prototype_rec(struct protolib **plibp, void *data) +{ + struct lookup *lookup = data; + + lookup->result = dict_find_entry((*plibp)->prototypes, lookup->name); + if (lookup->result != NULL) + return CBS_STOP; + + if (each_import(*plibp, NULL, &lookup_prototype_rec, lookup) != NULL) { + assert(lookup->result != NULL); + return CBS_STOP; + } + + return CBS_CONT; +} + +struct prototype * +protolib_lookup_prototype(struct protolib *plib, const char *name) +{ + struct lookup lookup = { name, NULL }; + if (lookup_prototype_rec(&plib, &lookup) == CBS_STOP) + assert(lookup.result != NULL); + else + assert(lookup.result == NULL); + return lookup.result; +} + +struct named_type * +protolib_lookup_type(struct protolib *plib, const char *name); diff --git a/prototype.h b/prototype.h new file mode 100644 index 0000000..7a75e2f --- /dev/null +++ b/prototype.h @@ -0,0 +1,155 @@ +/* + * This file is part of ltrace. + * Copyright (C) 2012 Petr Machata, Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef _PROTOTYPE_H_ +#define _PROTOTYPE_H_ + +#include "forward.h" +#include "dict.h" +#include "vect.h" + +/* Function prototype. */ +struct prototype { + /* Vector of struct param. */ + struct vect params; + + struct arg_type_info *return_info; + int own_return_info : 1; +}; + +/* Initialize a prototype PROTO. The name will be NAME, and the + * corresponding string will be owned and freed on destroy if + * OWN_NAME. */ +void prototype_init(struct prototype *proto); + +/* Destroy PROTO (but don't free the memory block pointed-to by + * PROTO). */ +void prototype_destroy(struct prototype *proto); + +/* Add new parameter PARAM to PROTO. The structure contents are + * copied and PARAM pointer itself is not owned by PROTO. */ +int prototype_push_param(struct prototype *proto, struct param *param); + +/* Return number of parameters of prototype. */ +size_t prototype_num_params(struct prototype *proto); + +/* Destroy N-th parameter from PROTO. N shall be smaller than the + * number of parameters. */ +void prototype_destroy_nth_param(struct prototype *proto, size_t n); + +/* Get N-th parameter of PROTO. N shall be smaller than the number of + * parameters. */ +struct param *prototype_get_nth_param(struct prototype *proto, size_t n); + +/* Iterate through the parameters of PROTO. See callback.h for notes + * on iteration interfaces. */ +struct param *prototype_each_param + (struct prototype *proto, struct param *start_after, + enum callback_status (*cb)(struct prototype *, struct param *, void *), + void *data); + +/* For storing type aliases. */ +struct named_type { + struct arg_type_info *info; + int forward : 1; + int owned : 1; +}; + +void named_type_destroy(struct named_type *named); + +/* One prototype library. */ +struct protolib { + /* Other libraries to look through if the definition is not + * found here. Note that due to the way imports are stored, + * there is no way to distinguish where exactly (at which + * place of the config file) the import was made. */ + struct vect imports; + + /* Dictionary of name->struct prototype. */ + struct dict *prototypes; + + /* Dictionary of name->struct named_type. */ + struct dict *named_types; +}; + +/* Initialize PLIB. Returns 0 on success or a negative value on + * failure. */ +int protolib_init(struct protolib *plib); + +/* Destroy PLIB. */ +void protolib_destroy(struct protolib *plib); + +/* Push IMPORT to PLIB. Returns 0 on success or a negative value on + * failure. In particular, -2 is returned if mutual import is + * detected. */ +int protolib_add_import(struct protolib *plib, struct protolib *import); + +/* Add a prototype PROTO to PLIB. Returns 0 on success or a negative + * value on failure. NAME is owned and released on PLIB destruction + * if OWN_NAME. */ +int protolib_add_prototype(struct protolib *plib, + const char *name, int own_name, + struct prototype *proto); + +/* Add a named type NAMED to PLIB. Returns 0 on success or a negative + * value on failure. NAME is owned and released on PLIB destruction + * if OWN_NAME. */ +int protolib_add_named_type(struct protolib *plib, + const char *name, int own_name, + struct named_type *named); + +/* Lookup prototype named NAME in PLIB. If none is found, look + * recursively in each of the imports. Returns the corresponding + * prototype, or NULL if none was found. */ +struct prototype *protolib_lookup_prototype(struct protolib *plib, + const char *name); + +/* Add a named type NAMED to PLIB. Returns 0 on success or a negative + * value on failure. */ +int protolib_add_type(struct protolib *plib, struct named_type *named); + +/* Lookup type named NAME in PLIB. If none is found, look recursively + * in each of the imports. Returns the corresponding type, or NULL if + * none was found. */ +struct named_type *protolib_lookup_type(struct protolib *plib, + const char *name); + +/* A cache of prototype libraries. Can load prototype libraries on + * demand. + * + * XXX ltrace should open one config per ABI, which maps long, int, + * etc. to uint32_t etc. It would also map char to either of + * {u,}int8_t. Other protolibs would have this as implicit import. + * That would mean that the cache needs ABI tagging--each ABI should + * have a separate prototype cache, because the types will potentially + * differ between the ABI's. protolib cache would then naturally be + * stored in the ABI object, when this is introduced. */ +struct protolib_cache { + /* Dictionary of filename->protolib. */ + struct dict *protolibs; +}; + + +/* Single global prototype library. + * XXX Eventually each struct library should have its own prototype + * library, so that there is one prototype library per DSO. */ +extern struct protolib g_prototypes; + +#endif /* _PROTOTYPE_H_ */ diff --git a/read_config_file.c b/read_config_file.c index f478656..52d23ea 100644 --- a/read_config_file.c +++ b/read_config_file.c @@ -39,6 +39,7 @@ #include "expr.h" #include "param.h" #include "printf.h" +#include "prototype.h" #include "zero.h" #include "type.h" #include "lens.h" @@ -508,21 +509,6 @@ parse_typedef(char **str) free(this_td); } -static void -destroy_fun(struct prototype *fun) -{ - size_t i; - if (fun == NULL) - return; - if (fun->own_return_info) { - type_destroy(fun->return_info); - free(fun->return_info); - } - for (i = 0; i < fun->num_params; ++i) - param_destroy(&fun->params[i]); - free(fun->params); -} - /* Syntax: struct ( type,type,type,... ) */ static int parse_struct(char **str, struct arg_type_info *info, @@ -1088,23 +1074,6 @@ parse_lens(char **str, struct param **extra_param, size_t param_num, int *ownp, } static int -add_param(struct prototype *fun, size_t *allocdp) -{ - size_t allocd = *allocdp; - /* XXX +1 is for the extra_param handling hack. */ - if ((fun->num_params + 1) >= allocd) { - allocd = allocd > 0 ? 2 * allocd : 8; - void *na = realloc(fun->params, sizeof(*fun->params) * allocd); - if (na == NULL) - return -1; - - fun->params = na; - *allocdp = allocd; - } - return 0; -} - -static int param_is_void(struct param *param) { return param->flavor == PARAM_FLAVOR_TYPE @@ -1124,8 +1093,24 @@ get_hidden_int(void) return info; } +static enum callback_status +void_to_hidden_int(struct prototype *proto, struct param *param, void *data) +{ + if (param_is_void(param)) { + report_warning(filename, 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; +} + static int -process_line(char *buf) +process_line(char *buf, struct protolib *plib) { char *str = buf; char *tmp; @@ -1145,17 +1130,20 @@ process_line(char *buf) struct prototype *fun = calloc(1, sizeof(*fun)); if (fun == NULL) { - report_error(filename, line_no, - "alloc function: %s", strerror(errno)); + report_error(filename, line_no, "%s", strerror(errno)); return -1; } + prototype_init(fun); + char *proto_name = NULL; int own; fun->return_info = parse_lens(&str, NULL, 0, &own, NULL); if (fun->return_info == NULL) { err: debug(3, " Skipping line %d", line_no); - destroy_fun(fun); + prototype_destroy(fun); + free(fun); + free(proto_name); return -1; } fun->own_return_info = own; @@ -1168,13 +1156,18 @@ process_line(char *buf) goto err; } *tmp = '\0'; - fun->name = strdup(str); + + proto_name = strdup(str); + if (proto_name == NULL) { + oom: + report_error(filename, line_no, "%s", strerror(errno)); + goto err; + } + str = tmp + 1; - debug(3, " name = %s", fun->name); + debug(3, " name = %s", proto_name); - size_t allocd = 0; struct param *extra_param = NULL; - int have_stop = 0; while (1) { @@ -1184,33 +1177,29 @@ process_line(char *buf) if (str[0] == '+') { if (have_stop == 0) { - if (add_param(fun, &allocd) < 0) - goto add_err; - param_init_stop - (&fun->params[fun->num_params++]); + struct param param; + param_init_stop(¶m); + if (prototype_push_param(fun, ¶m) < 0) + goto oom; have_stop = 1; } str++; } - if (add_param(fun, &allocd) < 0) { - add_err: - report_error(filename, line_no, "(re)alloc params: %s", - strerror(errno)); - goto err; - } - int own; + size_t param_num = prototype_num_params(fun) - have_stop; struct arg_type_info *type - = parse_lens(&str, &extra_param, - fun->num_params - have_stop, &own, NULL); + = parse_lens(&str, &extra_param, param_num, &own, NULL); if (type == NULL) { report_error(filename, line_no, "unknown argument type"); goto err; } - param_init_type(&fun->params[fun->num_params++], type, own); + struct param param; + param_init_type(¶m, type, own); + if (prototype_push_param(fun, ¶m) < 0) + goto oom; eat_spaces(&str); if (*str == ',') { @@ -1238,7 +1227,8 @@ process_line(char *buf) * latter is conservative, we can drop the argument * altogether, instead of fetching and then not showing it, * without breaking any observable behavior. */ - if (fun->num_params == 1 && param_is_void(&fun->params[0])) { + 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 @@ -1246,35 +1236,21 @@ process_line(char *buf) * extant uses are likely gone. */ report_warning(filename, line_no, "sole void parameter ignored"); - param_destroy(&fun->params[0]); - fun->num_params = 0; + prototype_destroy_nth_param(fun, 0); } else { - size_t i; - for (i = 0; i < fun->num_params; ++i) { - if (param_is_void(&fun->params[i])) { - report_warning - (filename, 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(&fun->params[i]); - param_init_type(&fun->params[i], type, 0); - } - } + prototype_each_param(fun, NULL, void_to_hidden_int, NULL); } if (extra_param != NULL) { - assert(fun->num_params < allocd); - memcpy(&fun->params[fun->num_params++], extra_param, - sizeof(*extra_param)); + prototype_push_param(fun, extra_param); free(extra_param); } - fun->next = list_of_functions; - list_of_functions = fun; + if (protolib_add_prototype(plib, proto_name, 1, fun) < 0) { + report_error(filename, line_no, "couldn't add prototype: %s", + strerror(errno)); + goto err; + } return 0; } @@ -1282,9 +1258,11 @@ process_line(char *buf) void init_global_config(void) { + protolib_init(&g_prototypes); + struct arg_type_info *info = malloc(2 * sizeof(*info)); if (info == NULL) { - fprintf(stderr, "Couldn't init global config: %s\n", + fprintf(stderr, "Couldn't allocate memory for aliases: %s.\n", strerror(errno)); exit(1); } @@ -1301,6 +1279,7 @@ init_global_config(void) void destroy_global_config(void) { + protolib_destroy(&g_prototypes); } void @@ -1320,7 +1299,7 @@ read_config_file(char *file) char *line = NULL; size_t len = 0; while (getline(&line, &len, stream) >= 0) - process_line(line); + process_line(line, &g_prototypes); free(line); fclose(stream); } |