/* 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. */ #include "typedef.h" /* * Original Author : Himanshu M. Thaker */ 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; /*************************************************************** * * and now, the subprogram that updates the dependancies. * *************************************************************** */ update_dependancies(tokens, file_name) struct token_holder *tokens; char *file_name; { struct token_holder *tk; struct package_ptrs *tmp_head_use, *tmp_use; struct packages *tmp_package; 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, *last_tmp_binding, *tmp_b; int current_type; /* * Current type has the meaning : * 0 - others * 1 - architecture * 2 - configuration * 3 - entity * 4 - package */ char token1[MAXTOKEN], token2[MAXTOKEN]; char x[MAXTOKEN]; int count; int found, just_had_config, do_not_use; tk = tokens; tmp_head_use = NULL; current_type = 0; just_had_config = FALSE; while (tk != NULL) { /*---- printf("note that token is '%s' '%s' '%s' '%s'\n", tk->keywrd, tk->var1, tk->var2, tk->token); ----*/ if (stringcmp(tk->keywrd,"USE") == 0) { if (stringcmp(tk->var1, "") == 0) { count = get_sub_token(tk->token, token1, token2); /*---- added the if clause below, to prevent adding work.all */ if ( (stringcmp(token2, "all") != 0) && (stringcmp(token1, "std") != 0) ) { /* * Note that if the temporary head for the "use" file data is * null, then we must assign the head to the first package_ptrs. * Else, search thru the tmp pointer stuff until we find * the end and do the assignment there. * Additional note : we only update the database for use clauses * that are not from the library "std". */ found = FALSE; if (tmp_head_use == NULL) { tmp_head_use = MALLOC(package_ptrs); tmp_use = tmp_head_use; } else { tmp_use = tmp_head_use; while (tmp_use->next != NULL) { if (stringcmp(tmp_use->pname, token2) == 0) found = TRUE; tmp_use = tmp_use->next; } /* * note that we must still check to see if the last package * pname matches, as the above checks all but the last. */ if (stringcmp(tmp_use->pname, token2) == 0) found = TRUE; if (!found) { tmp_use->next = MALLOC(package_ptrs); tmp_use = tmp_use->next; } } /* * Assign the fields pname and next. */ if (!found) { /* * if we had x.y or x.y.z, etc, then we must assign the yth field to * pname... ie. if we have work.pname or work.pname.all. */ if (count > 1) { tmp_use->pname = NMALLOC(strlen(token2)+1, char); strcpy(tmp_use->pname, token2); } else { tmp_use->pname = NMALLOC(strlen(token1)+1, char); strcpy(tmp_use->pname, token1); } tmp_use->next = NULL; tmp_use->pkg_ptr = NULL; tmp_use->libname = NULL; if (stringcmp(token1, "Work") == 0) tmp_use->work = TRUE; else { tmp_use->work = FALSE; tmp_use->libname = NMALLOC(strlen(token1)+1, char); strcpy(tmp_use->libname, token1); } /* * Now, search thru the package data base to see if we have parsed * the package name yet. If we have, then we must assign the pointer * to that package. Note that we must eventually have that pointer, * so, when we come across a package, we must search thru not only the * data bases for ARCHITECTURE and ENTITY, but temporary head also, * and update them. At the end, if we have not resolved all pointers, * then that is an error. */ tmp_package = header_package; found = FALSE; while ( (tmp_package != NULL) && !(found) ) { if ( (stringcmp(tmp_package->pname, tmp_use->pname) == 0) ) { found = TRUE; } if (!found) { tmp_package = tmp_package->next; } } if (found) tmp_use->pkg_ptr = tmp_package; else tmp_use->pkg_ptr = NULL; } /* of if (!found) */ } } else { /* * the else part of the check to see if var1 is blank is * invoked when we have a USE keywrd that specifies a configuration * or entity/architecture mapping to bind components, either * in the declarative region of the architecture, or in the * configuration specification section. * * Determine where this binding is occuring... */ if ( (current_type !=1) && (current_type != 2) ) { print_err("ERROR : file %s : USE clause encountered outside arch or config\n", file_name); return_code = -1; } else { tmp_binding = NULL; if (current_type == 1) { tmp_binding = tmp_arch->bind; } else /* if current_type == 2 */ { tmp_binding = tmp_config->bind; } if (stringcmp(tk->var2, "") == 0) { count = get_sub_token(tk->token, token1, token2); } else { count = get_sub_token(tk->var2, token1, token2); } if (count == 2) strcpy(x, token2); else strcpy(x, token1); found = FALSE; if (tmp_binding == NULL) { /* * Note that if this is the first one for that structure, then must * init the head appropriately. */ tmp_binding = MALLOC(binding_struct); if (current_type == 1) tmp_arch->bind = tmp_binding; else if (current_type == 2) tmp_config->bind = tmp_binding; } else { /* * else search thru the linked list to the end, and append the binding * structure there. */ last_tmp_binding = tmp_binding; while ( (!found) && (tmp_binding != NULL) ) { if (stringcmp(tk->var2, "") != 0) /* ie. is USE ENTITY */ { if (tmp_binding->ename != NULL) if (stringcmp(x, tmp_binding->ename) == 0) found = TRUE; } else /* ie. is USE CONFIGURATION */ { if (tmp_binding->cname != NULL) if (stringcmp(x, tmp_binding->cname) == 0) found = TRUE; } last_tmp_binding = tmp_binding; tmp_binding = tmp_binding->next; } if (!found) { last_tmp_binding->next = MALLOC(binding_struct); tmp_binding = last_tmp_binding->next; } } if (!found) { tmp_binding->ename = NULL; tmp_binding->aname = NULL; tmp_binding->cname = NULL; tmp_binding->entity = NULL; tmp_binding->arch = NULL; tmp_binding->config = NULL; tmp_binding->next = NULL; tmp_binding->work = TRUE; tmp_binding->libname = NULL; if (stringcmp(tk->var1, "CONFIGURATION") == 0) { /* * If we had USE CONFIGURATION, then the configuration name is * assigned to cname, and we must create a pointer to the config data. */ count = get_sub_token(tk->token, token1, token2); /* * strip off library name, if it exits (eg. work.config_name) */ if (count >= 2) { tmp_binding->cname = NMALLOC(strlen(token2)+1, char); strcpy(tmp_binding->cname, token2); if (stringcmp(token1, "Work") != 0) { tmp_binding->libname = NMALLOC(strlen(token1)+1, char); strcpy(tmp_binding->libname, token1); tmp_binding->work = FALSE; } } else { tmp_binding->cname = NMALLOC(strlen(tk->token)+1, char); strcpy(tmp_binding->cname, tk->token); } } else /* tk->var1 is ENTITY */ { /* * If we had USE ENTITY, then the entity name is assigned to ename, * the arch name to aname, and pointers to the entity and architecture * must be created. */ count = get_sub_token(tk->var2, token1, token2); if (count == 1) { tmp_binding->ename = NMALLOC(strlen(token1)+1,char); strcpy(tmp_binding->ename, token1); } else { tmp_binding->ename = NMALLOC(strlen(token2)+1,char); strcpy(tmp_binding->ename, token2); if (stringcmp(token1, "Work") != 0) { tmp_binding->libname = NMALLOC(strlen(token1)+1, char); strcpy(tmp_binding->libname, token1); tmp_binding->work = FALSE; } } tmp_binding->aname = NMALLOC(strlen(tk->token)+1, char); strcpy(tmp_binding->aname, tk->token); tmp_e = header_entity; found = FALSE; while ( (tmp_e != NULL) && (!found) ) { if ( stringcmp(tmp_e->ename, tmp_binding->ename) == 0 ) found = TRUE; else tmp_e = tmp_e->next; } if (found) tmp_binding->entity = tmp_e; tmp_a = header_arch; found = FALSE; while ( (tmp_a != NULL) && (!found) ) { /*---- printf("about to compare to ename '%s' and aname '%s'\n",tmp_a->ename, tmp_a->aname); ----*/ if ((stringcmp(tmp_a->ename, tmp_binding->ename) == 0) && (stringcmp(tmp_a->aname, tmp_binding->aname) == 0)) found = TRUE; else tmp_a = tmp_a->next; } if (found) { tmp_binding->arch = tmp_a; /*----printf("bound '%s(%s)' to arch '%s'\n",tmp_binding->entity, tmp_binding->aname, tmp_a->aname); */ } } /* of else if tk->var is ENTITY */ } } } } else if (stringcmp(tk->keywrd,"ARCHITECTURE") == 0) { if (tk->token != NULL) { /* * If we come across an architecture, and the token is not null... * (a token of null implies that during parsing, we determined that * the keyword architecture was not followed by "OF" (after the name * token, of course)...) */ current_type = 1; if (header_arch == NULL) { header_arch = MALLOC(arch_struct); tmp_arch = header_arch; } else { tmp_arch = header_arch; while (tmp_arch->next != NULL) { tmp_arch = tmp_arch->next; } tmp_arch->next = MALLOC(arch_struct); tmp_arch = tmp_arch->next; } /* * fill in fields aname, ename, faname, pkg, next. */ tmp_arch->aname = NMALLOC(strlen(tk->var1)+1, char); strcpy(tmp_arch->aname, tk->var1); count = get_sub_token(tk->token, token1, token2); if (count == 1) { tmp_arch->ename = NMALLOC(strlen(token1)+1, char); strcpy(tmp_arch->ename, token1); } else { tmp_arch->ename = NMALLOC(strlen(token2)+1, char); strcpy(tmp_arch->ename, token2); } tmp_arch->faname = NMALLOC(strlen(file_name)+1, char); strcpy(tmp_arch->faname, file_name); tmp_arch->used_by_toplevel = FALSE; tmp_arch->pkg = tmp_head_use; tmp_head_use = NULL; tmp_arch->entity = NULL; tmp_arch->config = NULL; tmp_arch->bind = NULL; tmp_arch->next = NULL; } } else if (stringcmp(tk->keywrd,"ENTITY") == 0) { current_type = 3; /* * If we come across an entity, we must first check to see if * we have any in the data base yet. If not, assign the first one * to the header. Else, assign the last one->next to this one. */ if (header_entity == NULL) { header_entity = MALLOC(entity_struct); tmp_entity = header_entity; } else { tmp_entity = header_entity; while (tmp_entity->next != NULL) { tmp_entity = tmp_entity->next; } tmp_entity->next = MALLOC(entity_struct); tmp_entity = tmp_entity->next; } /* * Now, fill in the field ename with tk->token, f_ename with the * name of the file we are parsing right now, the pointer to the * use stuff (pkg) to the tmp head, and the next field to null. * Note that if we have no use clauses, tmp_head_use will be null. * And, after we use it, we must reassign it to null; */ tmp_entity->ename = NMALLOC(strlen(tk->token)+1, char); strcpy(tmp_entity->ename, tk->token); tmp_entity->f_ename = NMALLOC(strlen(file_name)+1, char); strcpy(tmp_entity->f_ename, file_name); tmp_entity->pkg = tmp_head_use; tmp_entity->ports_exist = FALSE; tmp_entity->built = FALSE; tmp_entity->packaged = FALSE; tmp_entity->loose = TRUE; tmp_head_use = NULL; tmp_entity->next = NULL; } else if (stringcmp(tk->keywrd,"PORT") == 0) { if (current_type == 3) { tmp_entity->ports_exist = TRUE; } } else if (stringcmp(tk->keywrd,"CONFIGURATION") == 0) { current_type = 2; just_had_config = TRUE; /* * As usual, first determine if this is the first config... * create a new config set. */ if (header_config == NULL) { header_config = MALLOC(config_struct); tmp_config = header_config; } else { tmp_config = header_config; while (tmp_config->next != NULL) { tmp_config = tmp_config->next; } tmp_config->next = MALLOC(config_struct); tmp_config = tmp_config->next; } /* * Now, copy the configuration name to cname, the entity * name to ename, and the file name to fcname. */ tmp_config->cname = NULL; tmp_config->ename = NULL; tmp_config->aname = NULL; tmp_config->entity = NULL; tmp_config->arch = NULL; tmp_config->bind = NULL; tmp_config->next = NULL; count = get_sub_token(tk->var1, token1, token2); /* * strip library name of configuration name (eg. get rid of work, in * work.config_name) */ if (count >= 2) { tmp_config->cname = NMALLOC(strlen(token2)+1, char); strcpy(tmp_config->cname, token2); } else { tmp_config->cname = NMALLOC(strlen(tk->var1)+1, char); strcpy(tmp_config->cname, tk->var1); } /* * strip off library name (eg. work.ename, strip off work) */ count = get_sub_token(tk->token, token1, token2); if (count == 1) { tmp_config->ename = NMALLOC(strlen(token1)+1, char); strcpy(tmp_config->ename, token1); } else { tmp_config->ename = NMALLOC(strlen(token2)+1, char); strcpy(tmp_config->ename, token2); } tmp_config->fcname = NMALLOC(strlen(file_name)+1, char); strcpy(tmp_config->fcname, file_name); } else if (stringcmp(tk->keywrd,"FOR") == 0) { if (just_had_config == TRUE) { /* * If we just had the configuration keyword before, then this * FOR keyword identifies the architecture name. * **** Note that I am assuming that every configuration MUST * have an architecture name, and it immediately follows configuration. * I have seen this in most cases; however, the arch name could be * skipped, and the compiler then would choose the last compiled * arch. But, for this program, you MUST specify the arch name. */ tmp_config->aname = NMALLOC(strlen(tk->token)+1, char); strcpy(tmp_config->aname, tk->token); just_had_config = FALSE; } } else if (stringcmp(tk->keywrd,"PACKAGE") == 0) { current_type = 4; /* * First, check to see if this package already has a record * defined for it. This can happen in many cases, when the * package is in one file, and the package body is in another file. * If the package is found, then tmp_package will point to it. */ tmp_package = header_package; found = FALSE; while ( (tmp_package != NULL) && (!found) ) { if ( stringcmp(tmp_package->pname, tk->token) == 0 ) { found = TRUE; } else { tmp_package = tmp_package->next; } } /* * If we haven't created a record before, we must do so... * Remember, always check to see if the header has been created. */ if (!found) { if (header_package == NULL) { header_package = MALLOC(packages); tmp_package = header_package; } else { tmp_package = header_package; while (tmp_package->next != NULL) { tmp_package = tmp_package->next; } tmp_package->next = MALLOC(packages); tmp_package = tmp_package->next; } /* * As this is a new package that we have created, we must * initialze the package name. Also, the next field as always, * points to null as this is the end of the linked list. */ tmp_package->pname = NMALLOC(strlen(tk->token)+1, char); strcpy(tmp_package->pname, tk->token); tmp_package->f_pname = NULL; tmp_package->fpname = NULL; tmp_package->printed = FALSE; tmp_package->used_by_toplevel = FALSE; tmp_package->pkg = NULL; tmp_package->pkg_body = NULL; tmp_package->next = NULL; /* * Now, we must perform some back annotation. * Note that we need to update the package_ptrs for all * entity, and architecture declarations. This involves * searching thru the data base for all entity and architecture * package_ptrs. */ tmp_entity = header_entity; while (tmp_entity != NULL) { tmp_use = tmp_entity->pkg; while (tmp_use != NULL) { /* * Now, for this entity, go through the package pointer linked list. * If we have a package name match, AND the pointer has not been * initialized, then we point the package pointer to this package. * The reason that we do not update the pointer if it is init'd is * that we may have already encountered it before, and so should * not modify the first pointer existance. This occurs quite often * if we have encountered the package after we encounter the arch or * entity. */ if (tmp_use->pkg_ptr == NULL) { if (stringcmp(tmp_use->pname, tmp_package->pname) == 0) { tmp_use->pkg_ptr = tmp_package; } } tmp_use = tmp_use->next; } tmp_entity = tmp_entity->next; } /* * Now do the same code as above, but with arch... * note that we should really put this into a function, to save * in duplication of code... hint hint, for those days that you * have nothing better to do... */ tmp_arch = header_arch; while (tmp_arch != NULL) { tmp_use = tmp_arch->pkg; while (tmp_use != NULL) { if (tmp_use->pkg_ptr == NULL) { if (stringcmp(tmp_use->pname, tmp_package->pname) == 0) { tmp_use->pkg_ptr = tmp_package; } } tmp_use = tmp_use->next; } tmp_arch = tmp_arch->next; } } /* * if we have a package body, add the file name to the * fname field. Else, we have a package declaration, thus * add the file name to the f_name field. Note that if in * the process of adding the file name, we find that it already * has been defined, then we must inform the user of such. */ if (stringcmp(tk->var1, "BODY") == 0) { if ( (tmp_package->fpname != NULL) && (stringcmp(tmp_package->fpname, "") != 0) ) { sprintf(x, "WARNING : package body for %s from file %s\n", tmp_package->pname, tmp_package->fpname); print_err(x); print_err(" has previously been parsed... replaced.\n"); return_code = -1; } tmp_package->fpname = NMALLOC(strlen(file_name)+1, char); strcpy(tmp_package->fpname, file_name); tmp_package->pkg_body = tmp_head_use; tmp_head_use = NULL; } else { if ( (tmp_package->f_pname != NULL) && (stringcmp(tmp_package->f_pname, "") != 0) ) { sprintf(x, "WARNING : package for %s from file %s\n", tmp_package->pname, tmp_package->f_pname); print_err(x); print_err(" has previously been parsed... replaced.\n"); return_code = -1; } tmp_package->f_pname = NMALLOC(strlen(file_name)+1,char); strcpy(tmp_package->f_pname, file_name); tmp_package->pkg = tmp_head_use; tmp_head_use = NULL; } } tk = tk->next; } } /* * Now, the subprogram to get parts of a token, delimited by '.' */ int get_sub_token(tokenin, token1, token2) char *tokenin, *token1, *token2; { char temp_token[MAXTOKEN]; char *ptr; /* pointer to be used for testing end of token */ char *strtok(); int count; int found; count = 0; strcpy(temp_token, tokenin); /* * Until all tokens are parsed... */ found = FALSE; while (!found) { if (count == 0) ptr = strtok(temp_token, "."); else ptr = strtok(NULL, "."); if (ptr != NULL) { if (count == 0) strcpy(token1, ptr); else if (count == 1) strcpy(token2, ptr); count++; } else { found = TRUE; } } /*---printf("tokenin is %s and token1 is %s\n",tokenin, token1);*/ /*---printf(" and token2 is %s and count is %d\n",token2, count);*/ return(count); }