diff --git a/parser/parser.h b/parser/parser.h index efb57467e..74291e9ae 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -242,7 +242,7 @@ extern void dump_expanded_symtab(void); /* parser_alias.c */ extern int new_alias(const char *from, const char *to); -extern void replace_aliases(struct cod_entry *list); +extern void replace_aliases(void *list); extern void free_aliases(void); /* parser_merge.c */ diff --git a/parser/parser_alias.c b/parser/parser_alias.c new file mode 100644 index 000000000..ed0d2f443 --- /dev/null +++ b/parser/parser_alias.c @@ -0,0 +1,168 @@ +/* $Id: parser_symtab.c 565 2007-04-11 09:12:51Z jrjohansen $ */ + +/* + * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + * NOVELL (All rights reserved) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License published by the Free Software Foundation. + * + * 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, contact Novell, Inc. + */ + +#define _GNU_SOURCE /* for tdestroy(3) */ +#include +#include +#include +#include +#include +#include +#define _(s) gettext(s) + +#include "immunix.h" +#include "parser.h" + +struct alias_rule { + char *from; + char *to; +}; + +static void *alias_table; + +static int compare_alias(const void *a, const void *b) +{ + char *a_name = ((struct alias_rule *) a)->from; + char *b_name = ((struct alias_rule *) b)->from; + return strcmp(a_name, b_name); +} + +static struct alias_rule *lookup_alias(const char *alias) +{ + struct alias_rule tmp = { alias, NULL} , **lookup; + + lookup = (struct alias_rule **) tfind(&tmp, alias_table, (comparison_fn_t) &compare_alias); + if (!lookup) + return NULL; + + return *lookup; +} + +int new_alias(const char *from, const char *to) +{ + struct alias_rule *alias, **result; + + alias = malloc(sizeof(struct alias_rule)); + if (!alias) { + PERROR("Failed to allocate memory: %s\n", strerror(errno)); + goto fail; + } + memset(alias, 0, sizeof(*alias)); + alias->from = strdup(from); + if (!alias->from) { + PERROR("Failed to allocate memory: %s\n", strerror(errno)); + goto fail; + } + alias->to = strdup(to); + if (!alias->to) { + PERROR("Failed to allocate memory: %s\n", strerror(errno)); + goto fail; + } + + result = (struct alias_rule **) tsearch(alias, &alias_table, (comparison_fn_t) &compare_alias); + if (!result) { + PERROR("Failed to allocate memory: %s\n", strerror(errno)); + goto fail; + } + + if (*result != alias) { + /* already existing alias */ + PERROR("'%s' is already defined\n", from); + goto fail; + } + + return 1; + +fail: + if (alias) { + if (alias->from) + free(alias->from); + if (alias->to) + free(alias->to); + free(alias); + } + return 0; +} + +static char *do_alias(struct alias_rule *alias, const char *target) +{ + int len = strlen(target) - strlen(alias->from) + strlen(alias->to); + char *new = malloc(len + 1); + if (!new) { + PERROR("Failed to allocate memory: %s\n", strerror(errno)); + return NULL; + } + sprintf(new, "%s%s", alias->to, target + strlen(alias->from)); +//fprintf(stderr, "replaced alias: from: %s, to: %s, name: %s\n %s\n", alias->from, alias->to, target, new); + return new; +} + +static struct cod_entry *target_list; + +static void process_entries(const void *nodep, VISIT value, int __unused level) +{ + struct alias_rule **t = (struct alias_rule **) nodep; + struct cod_entry *entry; + int len; + + if (value == preorder || value == endorder) + return; + + len = strlen((*t)->from); + + list_for_each(target_list, entry) { + if (entry->mode & (AA_SHARED_PERMS & AA_PTRACE_PERMS)) + continue; + if (entry->name && strncmp((*t)->from, entry->name, len) == 0) { + char *new = do_alias(*t, entry->name); + if (!new) + return; + free(entry->name); + entry->name = new; + } + if (entry->link_name && + strncmp((*t)->from, entry->link_name, len) == 0) { + char *new = do_alias(*t, entry->link_name); + if (!new) + return; + free(entry->link_name); + entry->link_name = new; + } + } +} + +void replace_aliases(void *list) +{ + target_list = list; + twalk(alias_table, process_entries); +} + +static void free_alias(void *nodep) +{ + struct alias_rule *t = (struct alias_rule *)nodep; + free(t->from); + free(t->to); + free(t); +} + +void free_aliases(void) +{ + if (alias_table) + tdestroy(alias_table, &free_alias); +}