/* Copyright (C) 1993 Bell-Northern Research This file is part of vmkr. Vmkr is distributed in the hope that it will be useful, but without any warranty. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Everyone is granted permission to copy, modify and redistribute vmkr, but only under the conditions described in the document "vmkr copying permission notice". An exact copy of the document is supposed to have been given to you along with vmkr so that you can know how you may redistribute it all. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* * Original Author : Himanshu M. Thaker * Comments : * This file contains the back annotate routines. See * the file "Internal Workings of Vmkr", for more details. */ #include "typedef.h" extern struct entity_struct *header_entity; extern struct arch_struct *header_arch; extern struct packages *header_package; extern struct config_struct *header_config; extern struct lib_names *header_lib; extern int return_code; extern int print_libs; /****************************************************** * * back_annotate updates the database * ****************************************************** */ back_annotate() { struct package_ptrs *tmp_use; struct entity_struct *tmp_entity, *tmp_e; struct arch_struct *tmp_arch, *tmp_a; struct config_struct *tmp_config, *tmp_c; struct binding_struct *tmp_binding, *tmp_b; struct package_ptrs *tmp_pkg; struct packages *tmp_package, *tt_package; int current_dir; int found; char tmp_token[MAXTOKEN]; /* * First, go thru all of the entities, and back annotate * 1) links from architectures to entities * - there could be multiple architectures per entity * - call it l.a->e * 2) links from arch bindings to entities * - could be multiple l.b->e links * 3) links from configurations to entities * - could be multiple l.c-e links * 4) links from config bindings to entities */ tmp_entity = header_entity; while (tmp_entity != NULL) { /* * for the entity data base... */ tmp_arch = header_arch; while (tmp_arch != NULL) { /* * search thru the arch database... */ if (stringcmp(tmp_arch->ename, tmp_entity->ename) == 0) { /* * if there is an ename match, create a link l.a->e */ tmp_arch->entity = tmp_entity; } tmp_binding = tmp_arch->bind; while (tmp_binding != NULL) { /* * now, the arch binding data... */ if (tmp_binding->ename != NULL) if (stringcmp(tmp_binding->ename, tmp_entity->ename) == 0) { /* * if enames match, then create a link l.b->e */ tmp_binding->entity = tmp_entity; } tmp_binding = tmp_binding->next; } tmp_arch = tmp_arch->next; } tmp_config = header_config; while (tmp_config != NULL) { /* * search thru the config database... */ if (stringcmp(tmp_config->ename, tmp_entity->ename) == 0) { tmp_config->entity = tmp_entity; } tmp_binding = tmp_config->bind; while (tmp_binding != NULL) { /* * now, the config binding data... */ if (tmp_binding->ename != NULL) if (stringcmp(tmp_binding->ename, tmp_entity->ename) == 0) { /* * if enames match, then create a link l.b->e */ tmp_binding->entity = tmp_entity; } tmp_binding = tmp_binding->next; } tmp_config = tmp_config->next; } tmp_entity = tmp_entity->next; } /* * Now, go thru the architecture linked list. * Note that we do not need to search for connections from * arch to entities, or from bindings (either arch or config) to * entities. */ tmp_arch = header_arch; while (tmp_arch != NULL) { /* * first search to make a connection from configs to archs * note that there could be more than one config per arch. * note that both the entity name and arch name have to match. */ tmp_config = header_config; while (tmp_config != NULL) { if ( (stringcmp(tmp_config->aname, tmp_arch->aname) == 0) && (stringcmp(tmp_config->ename, tmp_arch->ename) == 0) ) { if (tmp_config->arch != NULL) { sprintf(tmp_token, "WARNING : config '%s', arch '%s' entity '%s' from file %s\n", tmp_config->cname, tmp_config->aname, tmp_config->ename, tmp_config->fcname); print_err(tmp_token); print_err(" was already linked... replaced\n"); print_err(" This implies multiple identical arch/entity pairs\n"); return_code = -1; } /* * this list is double linked. */ tmp_config->arch = tmp_arch; tmp_arch->config = tmp_config; } /* * now, the config binding database... * note that this is with the arch name constant, searching thru * the config database. We have to do the reverse also, below. * note that again, both the ename, and the aname must match. */ tmp_binding = tmp_config->bind; while (tmp_binding != NULL) { if (tmp_binding->aname != NULL) if ( (stringcmp(tmp_binding->aname, tmp_arch->aname) == 0) && (stringcmp(tmp_binding->ename, tmp_arch->ename) == 0) ) { tmp_binding->arch = tmp_arch; } tmp_binding = tmp_binding->next; } tmp_config = tmp_config->next; } /* * now, go thru the arch binding database. * note that again, both the ename, and the aname must match. */ tmp_a = header_arch; while (tmp_a != NULL) { tmp_binding = tmp_a->bind; while (tmp_binding != NULL) { if (tmp_binding->aname != NULL) if ( (stringcmp(tmp_binding->aname, tmp_arch->aname) == 0) && (stringcmp(tmp_binding->ename, tmp_arch->ename) == 0) ) { tmp_binding->arch = tmp_arch; } tmp_binding = tmp_binding->next; } tmp_a = tmp_a->next; } tmp_arch = tmp_arch->next; } /* * finally, go thru the configuration linked list. */ tmp_config = header_config; while (tmp_config != NULL) { tmp_arch = header_arch; while (tmp_arch != NULL) { tmp_binding = tmp_arch->bind; while (tmp_binding != NULL) { /* * go thru the binding data of the arch list... * note that we have already done this for aname, ename. The * reason that we didn't do it for cname before, was that we * were varying cname and keeping aname constant... here we should * keep cname constant, and vary the arch data... */ if (tmp_binding->cname != NULL) { if (stringcmp(tmp_binding->cname, tmp_config->cname) == 0) { if (tmp_binding->config != NULL) { sprintf(tmp_token, "WARNING : binding to config '%s' already exists... replaced\n", tmp_binding->cname); print_err(tmp_token); sprintf(tmp_token, " in arch '%s' of file '%s'\n", tmp_arch->aname, tmp_arch->faname); print_err(tmp_token); return_code = -1; } tmp_binding->config = tmp_config; } } tmp_binding = tmp_binding->next; } tmp_arch = tmp_arch->next; } /* * finally, go thru the config binding data base. * Note that we need another config variable, as we must vary that * thru the whole linked list and the bindings, for every config * name. */ tmp_c = header_config; while (tmp_c != NULL) { tmp_binding = tmp_c->bind; while (tmp_binding != NULL) { if (tmp_binding->cname != NULL) { if (stringcmp(tmp_binding->cname, tmp_config->cname) == 0) { if (tmp_binding->config != NULL) { sprintf(tmp_token, "WARNING : binding to config '%s' already exists... replaced\n", tmp_binding->cname); print_err(tmp_token); return_code = -1; } tmp_binding->config = tmp_config; } } tmp_binding = tmp_binding->next; } tmp_c = tmp_c->next; } tmp_config = tmp_config->next; } /* * Finally, construct the library names linked list. */ tmp_arch = header_arch; while (tmp_arch != NULL) { /* * first, the architecture packages... */ tmp_pkg = tmp_arch->pkg; while (tmp_pkg != NULL) { if (tmp_pkg->work == FALSE) { current_dir = (tmp_pkg->pkg_ptr != NULL); install_lib_name(tmp_pkg->libname, current_dir); } tmp_pkg =tmp_pkg->next; } /* * now, the architecture binding structures... */ tmp_binding = tmp_arch->bind; while (tmp_binding != NULL) { if (tmp_binding->work == FALSE) { current_dir = (tmp_binding->entity != NULL); install_lib_name(tmp_binding->libname, current_dir); } tmp_binding =tmp_binding->next; } tmp_arch = tmp_arch->next; } /* * now the entity packages... */ tmp_entity = header_entity; while (tmp_entity != NULL) { tmp_pkg = tmp_entity->pkg; while (tmp_pkg != NULL) { if (tmp_pkg->work == FALSE) { current_dir = (tmp_pkg->pkg_ptr != NULL); install_lib_name(tmp_pkg->libname, current_dir); } tmp_pkg =tmp_pkg->next; } tmp_entity = tmp_entity->next; } /* * finally, the configuration binding structures... */ tmp_config = header_config; while (tmp_config != NULL) { tmp_binding = tmp_config->bind; while (tmp_binding != NULL) { if (tmp_binding->work == FALSE) { current_dir = (tmp_binding->config != NULL); install_lib_name(tmp_binding->libname, current_dir); } tmp_binding =tmp_binding->next; } tmp_config = tmp_config->next; } /* * now, we need to go through the package packages, * and install their libnames. */ tmp_package = header_package; while (tmp_package != NULL) { tmp_pkg = tmp_package->pkg; while (tmp_pkg != NULL) { if (tmp_pkg->work == FALSE) { current_dir = (tmp_pkg->pkg_ptr != NULL); install_lib_name(tmp_pkg->libname, current_dir); } tmp_pkg =tmp_pkg->next; } /* * remember that package bodies can also have dependencies on other * packages. */ tmp_pkg = tmp_package->pkg_body; while (tmp_pkg != NULL) { if (tmp_pkg->work == FALSE) { current_dir = (tmp_pkg->pkg_ptr != NULL); install_lib_name(tmp_pkg->libname, current_dir); } tmp_pkg =tmp_pkg->next; } tmp_package = tmp_package->next; } /* * Now, we need to go through all of the package dependencies * on other packages, and back annotate. */ tmp_package = header_package; while (tmp_package != NULL) { /* * for all of the packages, search through their dependencies */ tmp_pkg = tmp_package->pkg; while (tmp_pkg != NULL) { /* * search through their package dependencies */ found = FALSE; tt_package = header_package; while ( (!found) && (tt_package != NULL) ) { if (stringcmp(tt_package->pname, tmp_pkg->pname) == 0) { /* * if the package names match, then this package depends on the one * just found. */ tmp_pkg->pkg_ptr = tt_package; found = TRUE; } else tt_package = tt_package->next; } tmp_pkg = tmp_pkg->next; } tmp_pkg = tmp_package->pkg_body; while (tmp_pkg != NULL) { /* * search through their package body dependencies */ found = FALSE; tt_package = header_package; while ( (!found) && (tt_package != NULL) ) { if (stringcmp(tt_package->pname, tmp_pkg->pname) == 0) { /* * if the package names match, then this package depends on the one * just found. */ tmp_pkg->pkg_ptr = tt_package; found = TRUE; } else tt_package = tt_package->next; } tmp_pkg = tmp_pkg->next; } tmp_package = tmp_package->next; } } install_lib_name(libname, current_dir) char *libname; int current_dir; { struct lib_names *tmp_lib; int found; found = FALSE; tmp_lib = header_lib; if (tmp_lib == NULL) { /* * check to see if the header_lib has been initialized yet. */ header_lib = MALLOC(lib_names); tmp_lib = header_lib; } else { /* * if not, then check to see if the libname has already been installed */ while ( (tmp_lib->next != NULL) && (!found) ) { if (stringcmp(tmp_lib->lib, libname) == 0) found = TRUE; tmp_lib = tmp_lib->next; } /* * the above doesn't check the last tmp_lib entry... */ if (!found) if (stringcmp(tmp_lib->lib, libname) == 0) found = TRUE; /* * if not found, then we can MALLOC a new lib_names structure */ if (!found) { tmp_lib->next = MALLOC(lib_names); tmp_lib = tmp_lib->next; } } if (!found) { /* * If not found, then fill in the fields of tmp_lib */ tmp_lib->current_dir = current_dir; tmp_lib->lib = NMALLOC(strlen(libname)+1, char); strcpy(tmp_lib->lib, libname); tmp_lib->next = NULL; } } /* * The following procedure prints to standard error AND standard out. * This functionality can be changed later to just standard out, if * required. */ print_err(strg) char *strg; { fprintf(stderr, strg); printf(strg); }