⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgsymtab.c

📁 这是一个Linux下的集成开发环境
💻 C
📖 第 1 页 / 共 4 页
字号:
	}      }    }  }}	/* Returns TRUE unless block is SAVED by any module, or declared by	   the actual main program or in a BLOCK DATA subprogram. */PRIVATE intblock_is_volatile(clist,main_module)     ComListHeader *clist;     Gsymtab *main_module;{  int t;  while(clist != NULL) {    if( clist->saved ||       (t=datatype_of(clist->module->type)) == type_BLOCK_DATA       || (t == type_PROGRAM && clist->module == main_module)) {      return FALSE;    }    clist = clist->next;  }  return TRUE;} /* If block declared by module, returns pointer to the comlist    header which describes it.  Otherwise returns NULL. */PRIVATE ComListHeader *com_declared_by(comblock,module)     Gsymtab *comblock,*module;{  ComListHeader *clist=comblock->info.comlist;  while(clist != NULL) {    if(clist->module == module) {      if(clist->saved) {	com_tree_error = TRUE;	/* not so, but causes bailout */      }      return clist;    }    clist = clist->next;  }  return NULL;}		/* Checks whether common block can become undefined		   between activations of some module that declares it.		   Should only be done for blocks that are volatile, i.e.		   that are not SAVED or declared in main or block_data.		   Rules used are:		     (1) Block is declared in two subtrees whose roots		         are called by a given module, and not in			 the given module itself or above.		     (2) Block is declared and elements accessed in a module		         called by a given module, and not declared in the			 module itself or above.  (Module that declares it but			 does not access elements, can be holding the			 block active for its children.)		   Since Rule 2 is likely to be wrong often due to Ftnchek's		   lack of knowledge about whether a routine is invoked		   more than once, it is suppressed for now.		*/PRIVATE ComListHeader *com_tree_check(comblock,module,level)     Gsymtab *comblock,*module;     int level;{  ComListHeader *clist;	/* The following only protects against recursion.  It is not	   a full-fledged cycle detector just a stopper. */  if(level > numvisited) {    fprintf(list_fd,	    "\nWarning: Call tree has a cycle containing module %s\n",	    module->name);    com_tree_error = TRUE;    return NULL;  }		/* If this module declares the block, return its clist */  if( (clist=com_declared_by(comblock,module)) != NULL) {#ifdef DEBUG_SAVE      fprintf(list_fd,"\n%s declared by %s",comblock->name,module->name);#endif    return clist;  }  else {	/* Otherwise see if it is declared in subtree */    int any_child_declares_it;    ComListHeader *declaring_clist, *this_clist;    ChildList *child_list;    any_child_declares_it=FALSE;    declaring_clist=NULL;				/* Scan list of children */    child_list = (module->internal_entry?module->link.module:module)		   ->link.child_list;    while(child_list != NULL) {      this_clist = com_tree_check(comblock,child_list->child,level+1);				/* Error was detected below: bail out */      if(com_tree_error) {	return NULL;      }      else if(this_clist != NULL) {				/* Subtree contains the block */	if(any_child_declares_it			   /* Rule 1 */#ifdef COMTREE_RULE_2	   || (this_clist->any_used || this_clist->any_set) /* Rule 2 */#endif	){	  fprintf(list_fd,    "\nWarning: Common block %s may become undefined between activations",	    comblock->name);	  fprintf(list_fd,"\n    ");	  com_error_locate(this_clist);	  if(declaring_clist != NULL && declaring_clist != this_clist) {	    fprintf(list_fd,"\n    ");	    com_error_locate(declaring_clist);	  }	  fprintf(list_fd,"\n        ");	  fprintf(list_fd,		  "during activation of module %s",		  module->name);	  com_tree_error = TRUE;	  return NULL;	}	else {	  any_child_declares_it = TRUE;	  declaring_clist = this_clist;	}      }      child_list = child_list->next;    }		/* If any subtree declares it, say so */    return declaring_clist;  }}				/* Depth-first search of call tree */PRIVATE voidvisit_child(gsymt,level)     Gsymtab *gsymt;     int level;{  static char fmt[]="%000s";	/* Variable format for indenting names */  ChildList *child_list;  if(print_call_tree) {    fprintf(list_fd,"\n");    if(level > 0) {      sprintf(fmt,"%%%ds",level*4); /* indent 4 spaces per nesting level */      fprintf(list_fd,fmt,"");    }    fprintf(list_fd,"%s",gsymt->name);  }				/* Visit its unvisited children.  Note				   that children of internal entry are				   taken as those of its superior module.				 */  child_list = (gsymt->internal_entry?gsymt->link.module:gsymt)		   ->link.child_list;				/* If already visited, do not visit its				   children, but give note to reader if it				   has some. */  if(gsymt->visited) {    if(print_call_tree && child_list != NULL)      fprintf(list_fd," (see above)");  }  else {				/* Mark node as visited */    gsymt->visited = TRUE;				/* Record that containing module				   is visited via this entry point*/    if(gsymt->internal_entry)      gsymt->link.module->visited_somewhere = TRUE;    else      gsymt->visited_somewhere = TRUE;    ++level;			/* move to next level */    while(child_list != NULL) {      visit_child(child_list->child,level);      child_list = child_list->next;    }  }}/*** visit_child_reflistSame as visit_child, except it does a breadth-first search of the calltree, and prints the results in the form of a who-calls-who list.Contributed by: Gerome Emmanuel : Esial Troisieme annee		Projet commun Esial / Ecole des mines		INERIS		E-mail: gerome@mines.u-nancy.frDate received: 20-APR-1993Modified slightly to make it compatible as alternative to call-tree andto make output format consistent.***/PRIVATE voidvisit_child_reflist(gsymt)     Gsymtab *gsymt;{  ChildList *child_list;  child_list = (gsymt->internal_entry?gsymt->link.module:gsymt)                   ->link.child_list;                                /* If already visited, do not visit its                                   children, but give note to reader if it                                   has some. */  if(!gsymt->visited) {                                /* Mark node as visited */    gsymt->visited = TRUE;                                /* Record that containing module                                   is visited via this entry point*/    if(gsymt->internal_entry)      gsymt->link.module->visited_somewhere = TRUE;    else      gsymt->visited_somewhere = TRUE;    if(print_ref_list)		/* Print callees neatly if desired */    {#ifdef DYNAMIC_TABLES		/* tables will be mallocked at runtime */      Gsymtab  **gsymlist;#else      Gsymtab  *gsymlist[GLOBSYMTABSZ];#endif      ChildList *child_list2;      unsigned numcalls;#ifdef DYNAMIC_TABLES      if( (gsymlist=(Gsymtab **)SN_calloc(glob_symtab_top,sizeof(Gsymtab *)))	 == (Gsymtab **)NULL) {	  oops_message(OOPS_FATAL,NO_LINE_NUM,NO_COL_NUM,		       "Cannot malloc space for reference list");      }#endif      fprintf(list_fd,"\n%s calls:",gsymt->name);      numcalls = 0;      child_list2 = child_list;      while(child_list2 != NULL)	  {	    gsymlist[numcalls++] = child_list2->child;	    child_list2 = child_list2->next;	  }      if(numcalls == (unsigned)0)	    fprintf(list_fd," none");      else {	    fprintf(list_fd,"\n");	    print_modules(numcalls,gsymlist);      }#ifdef DYNAMIC_TABLES      (void) cfree(gsymlist);#endif    }    while(child_list != NULL) {      visit_child_reflist(child_list->child);      child_list = child_list->next;    }  }}PRIVATE voidprint_crossrefs(){#ifdef DYNAMIC_TABLES		/* tables will be mallocked at runtime */      Gsymtab  **gsymlist, **modulelist;#else  Gsymtab  *gsymlist[GLOBSYMTABSZ], *modulelist[GLOBSYMTABSZ];#endif  ArgListHeader *args;  int  i,numentries;  unsigned numcalls;#ifdef DYNAMIC_TABLES      if( (gsymlist=(Gsymtab **)SN_calloc(glob_symtab_top,sizeof(Gsymtab *)))	 == (Gsymtab **)NULL ||	 (modulelist=(Gsymtab **)SN_calloc(glob_symtab_top,sizeof(Gsymtab *)))	 == (Gsymtab **)NULL) {	  oops_message(OOPS_FATAL,NO_LINE_NUM,NO_COL_NUM,		       "Cannot malloc space for crossref list");      }#endif				/* Gather up all relevant subprograms */  for(i=0,numentries=0; i<glob_symtab_top; i++) {    if(storage_class_of(glob_symtab[i].type) == class_SUBPROGRAM       && (glob_symtab[i].visited || !glob_symtab[i].library_module)) {      gsymlist[numentries++] = &glob_symtab[i];    }  }  if(numentries > 0) {    fprintf(list_fd,"\n\n        Cross-reference list:\n");				/* Sort the subprograms */    sort_gsymbols(gsymlist,numentries);				/* Print their callers */    for(i=0; i<numentries; i++) {      fprintf(list_fd,"\n%s",gsymlist[i]->name);      numcalls=0;      args = gsymlist[i]->info.arglist;      while(args != NULL) {		/* Gather up callers */	if(!args->is_defn) {				/* (eliminate duplicates) */	  if(numcalls==(unsigned) 0 || args->module != modulelist[numcalls-1])	    modulelist[numcalls++] = args->module;	}	args = args->next;      }      if(numcalls == (unsigned) 0)	fprintf(list_fd," not called");      else {	fprintf(list_fd," called by:\n");	sort_gsymbols(modulelist,numcalls); /* Sort the callers */	print_modules(numcalls,modulelist);      }    }    fprintf(list_fd,"\n");  }#ifdef DYNAMIC_TABLES      (void) cfree(gsymlist);      (void) cfree(modulelist);#endif}	/* Topological sort of the call tree.  Based closely on algorithm	   on page 314 of Horowitz and Sahni, Fundamentals of Data	   Structures.  Returns TRUE if successful, FALSE if failed	   due to a cycle being detected.	 */PRIVATE void print_cycle_nodes(); /* Routine for error diagnostics */PRIVATE inttoposort(gsymt,nsym)     Gsymtab gsymt[];     int nsym;{  int i,num_nodes;  unsigned node_count;  ChildList *child_list;#ifdef DYNAMIC_TABLES		/* tables will be mallocked at runtime */  int *parent_count;  Gsymtab **node_list;#else  int parent_count[GLOBSYMTABSZ];  Gsymtab *node_list[GLOBSYMTABSZ];#endif#ifdef DYNAMIC_TABLES      if( (parent_count=(int *)SN_calloc(glob_symtab_top,sizeof(int)))	 == (int *)NULL ||	 (node_list=(Gsymtab **)SN_calloc(glob_symtab_top,sizeof(Gsymtab *)))	 == (Gsymtab **)NULL) {	  oops_message(OOPS_FATAL,NO_LINE_NUM,NO_COL_NUM,		       "Cannot malloc space for module sort");      }#endif			/* Initialize array of links/counts */  for(i=0; i<nsym; i++)    parent_count[i] = 0;	/* In-order of module as node */			/* Traverse child lists, incrementing their			   parent counts.			 */  for(i=0,num_nodes=0; i<nsym; i++) {    if(gsymt[i].visited_somewhere) { /* skip entry pts and com blocks */      ++num_nodes;      child_list = gsymt[i].link.child_list;      while(child_list != NULL) {	++parent_count[child_list->child - gsymt]; /* index into table */	child_list = child_list->next;      }    }  }  {				/* Start of the sort */    int top=0;    int j,k;    for(i=0; i<nsym; i++) {      if(gsymt[i].visited_somewhere && parent_count[i] == 0) {	parent_count[i] = top;	/* Link now-parentless module into stack */	top = i+1;      }    }    for(i=0,node_count=0; i<num_nodes; i++) {      if(top == 0) {	if(print_topo_sort) {	  fprintf(list_fd,"\nCall tree has a cycle");	  print_cycle_nodes(gsymt,nsym,node_list,node_count,parent_count);	}	break;      }      j = top-1;      top = parent_count[j];	/* Recover the link */				/* Print the next module */      if(print_topo_sort) {	node_list[node_count++] = &gsymt[j];	parent_count[j] = -1;      }			/* Decrease parent count of its children */      child_list = gsymt[j].link.child_list;      while(child_list != NULL) {	k = child_list->child - gsymt;	if(--parent_count[k] == 0) { /* Now parentless? Stack it*/	  parent_count[k] = top;	  top = k+1;	}	child_list = child_list->next;      }    }  }/*end sort*/  if(print_topo_sort && node_count > 0) {    fprintf(list_fd,"\nList of called modules in prerequisite order:\n");    print_modules(node_count,node_list);    fprintf(list_fd,"\n");  }#ifdef DYNAMIC_TABLES  (void) cfree(parent_count);  (void) cfree(node_list);#endif  return (node_count==num_nodes);	/* Success = TRUE */}		/* Traces back to find nodes not listed in topological		   sort.  They are the cycle nodes and their descendants.		 */PRIVATE voidprint_cycle_nodes(gsymt,nsym,node_list,node_count,parent_count)     Gsymtab gsymt[];     int nsym;     Gsymtab *node_list[];     unsigned node_count;     int parent_count[];{  int i;  int k=node_count;  for(i=0; i<nsym; i++) {    if(gsymt[i].visited_somewhere) {      if(parent_count[i] != -1)	/* Not tagged */	node_list[k++] = &gsymt[i];    }  }  if(k > node_count)    fprintf(list_fd," containing some of the following modules:\n");  print_modules(k-node_count,node_list+node_count);}				/* Insertion sort of child list.				   Also removes duplicates which				   can be introduced via multiple				   defns or via project files. */PRIVATE voidsort_child_list(child_list)     ChildList *child_list;{  ChildList *front,*prev,*next;  Gsymtab *temp;  prev = NULL;  while(child_list != NULL) {			/* Scan thru list for lexicographically lowest name */    front=child_list;    for(next=child_list->next; next != NULL; next = next->next) {      if(strcmp(front->child->name,next->child->name) > 0) {	front = next;      }    }			/* Swap child pointers so front is first */    if(front != child_list) {      temp = front->child;      front->child = child_list->child;      child_list->child = temp;    }			/* If duplicate, remove from list */    if(prev != NULL && prev->child == child_list->child)      prev->next = child_list->next;    else      prev = child_list;    child_list = child_list->next;  }}PRIVATE voidsort_gsymbols ( glist,n )   /* bubble sort, same as sort_symbols */	Gsymtab *glist[];	int n;{	int i,j,swaps;	for (i=0; i<n; i++ ){	    swaps = 0;	    for  (j=n-1; j>=i+1; j--){		if ((strcmp (glist[j-1]->name, glist[j]->name)) >0) {		    swap_gsymptrs(&glist[j-1], &glist[j] );		    swaps++;		}	    }	    if (swaps == 0) break;	}}PRIVATE voidswap_gsymptrs (x_ptr, y_ptr)    /* swap pointers */	Gsymtab **x_ptr,**y_ptr;{	Gsymtab *temp = *x_ptr;	*x_ptr = *y_ptr;	*y_ptr = temp;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -