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

📄 symtab.c

📁 linux 下的源代码分析阅读器 red hat公司新版
💻 C
📖 第 1 页 / 共 5 页
字号:
/*Copyright (c) 2000, Red Hat, Inc.This file is part of Source-Navigator.Source-Navigator is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public License as publishedby the Free Software Foundation; either version 2, or (at your option)any later version.Source-Navigator is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public License alongwith Source-Navigator; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330, Boston,MA 02111-1307, USA.*//* symtab.c:Contains formerly separate modules:   I. Symtab: symbol table maintenance routines.  II. Hash:  hash table functions: hash(), kwd_hash(), rehash() III. Intrins: handles recognition & data typing of intrinsic functions.    Copyright (C) 1992 by Robert K. Moniot.    This program is free software.  Permission is granted to    modify it and/or redistribute it, retaining this notice.    No guarantees accompany this software.*//*  I. Symtab		Symbol table routines for Fortran program checker.	  Shared functions defined:	   call_func(id,arg)	 Handles function invocations.	   call_subr(id,arg)	 Handles CALL statements.	   declare_type(id,datatype,size) Handles TYPE statements.	   def_arg_name(id)	 Handles func/subr argument lists.	   def_array_dim(id,arg) Handles dimensioning declarations.	   def_com_block(id)	 Handles common blocks and SAVE stmts.	   def_com_variable(id)	 Handles common block lists.       int def_curr_module(id)	 Identifies symbol as current module.     	   def_equiv_name(id)	 Initializes equivalence list items.	   def_ext_name(id)	 Handles external lists.	   def_function(datatype,size,id,args)	   		Installs function name in global table.	   def_intrins_name(id)  Handles intrinsic lists.	   def_parameter(id,value) Handles parameter_defn_item	   def_stmt_function(id) Declares a statement function.	   do_ASSIGN(id)	 Handles ASSIGN stmts.	   do_assigned_GOTO(id)	 Handles assigned GOTO.	   do_ENTRY(id,args,hashno) Processes ENTRY statement.	   do_RETURN(hashno,keyword) Processes RETURN statement.	   equivalence(id1,id2)	 equivalences two variables       int get_type(symt)	 Finds out data type of symbol, or uses implicit				 typing to establish its type.       int get_size(symt,type)	 Finds out size of symbol's datatype.	unsigned hash_lookup(s)	 Looks up identifier in hashtable.	   init_globals()	 Initializes global symbol info.	   init_symtab()	 Clears local symbol table & removes locals				 from stringspace. Also restores default				 implicit data typing. Gsymtab* install_global(t,datatype,storage_class) Installs indentifier in				global symbol table. Lsymtab* install_local(id,t,datatype,storage_class) Installs indentifier in				local symbol table.ArgListHeader* make_arg_array(t) Converts list of tokens into list of				 type-flag pairs.ArgListHeader* make_dummy_arg_array(t) Converts list of tokens into list of				 type-flag pairs.ArgListHeader* make_arrayless_alist() Sets up argument list header for				EXTERNAL decl or subprog as actual arg.ComListHeader* make_com_array(t) Converts list of common block tokens into				 list of dimen_info-type pairs.	   process_lists()	 Places pointer to linked list of arrays in				 global symbol table	   ref_array(id,subscrs) Handles array references	   ref_variable(id)	 Handles accessing variable name.	   set_implicit_type(type,size,c1,c2) Processes IMPLICIT statement.	   stmt_function_stmt(id) Finishes processing stmt func defn.    char * token_name(t)	 Returns ptr to token's symbol's name.	   use_actual_arg(id)	 Handles using a variable as actual arg.	   use_io_keyword(id_keywd,id_val,class) Handles i/o control specifier.	   use_lvalue(id)	 Handles assignment to a variable.	   use_parameter(id)	 Handles data_constant_value &				 data_repeat_factor.	   use_variable(id)	 Sets used-flag for a variable used in expr.*//*  private functions defined: arg_count(t)		Counts the number of arguments in a token list. call_external(symt,id,arg)	places token list of args into local symtab check_intrins_args(arg, defn) Checks call seq of intrinsic functions check_stmt_function_args(symt,id,arg)  ditto for statement functions find_intrinsic()		Looks up intrinsic functions in table find_io_keyword()		Looks up i/o control spec keywords reverse_tokenlist(t)		Reverses a linked list of tokens make_TL_head();		Initializes a tokenlist header*/#include <stdio.h>#include <string.h>#include <ctype.h>#define SYMTAB#include "ftnchek.h"#include "symtab.h"#include "fortran.h"#include "sn.h"#include "tcl.h"#include <stdlib.h>extern int current_module_hash;extern int current_record_hash;extern int report_local_vars;extern int cross_scope_type;extern	int	highlight;PRIVATEunsigned arg_count();PRIVATE voidcall_external(),check_intrins_args(),check_stmt_function_args();PRIVATE intfind_io_keyword();PRIVATE Token *reverse_tokenlist();PRIVATE TokenListHeader *	/* Initializes a tokenlist header */make_TL_head();PRIVATEArgListHeader *make_dummy_arg_array(),*make_arg_array(), *make_arrayless_alist();PRIVATEComListHeader *make_com_array();				/* Routines to allocate arglist and comlist				   stuff are external for Turbo C workaround,				   otherwise they are local.  */#ifdef T_ALLOC#define T_EXTERN extern#else#define T_EXTERN#endifT_EXTERN ArgListHeader *new_arglistheader();T_EXTERN ArgListElement *new_arglistelement();T_EXTERN ComListHeader *new_comlistheader();T_EXTERN ComListElement *new_comlistelement();PRIVATEIntrinsInfo *find_intrinsic();static char *datatype_name( int datatype );static void report( Token *id, int typ );static void print_func_argument_list( Token *t, char **buf);static void report_name( char *name, Token *id, char *buf );static void report_class_name( Token *id, char *cname, char *varn );static void * SN_calloc (int size1, int size2){	void * p;	p = (void*)ckalloc (size1*size2);	memset (p, 0, size1*size2);	return p;}PRIVATE unsignedarg_count(t)            /* Counts the number of arguments in a token list */	Token *t;{	unsigned count;	count = 0;	while(t != NULL){		count++;		t = t->next_token;	}	return(count);}			/* This routine handles the saving of arg lists which			   is done by call_func and call_subr.  Also called			   by def_namelist to save its variable list. */PRIVATE voidcall_external(symt,id,arg)	Lsymtab *symt;	Token *id,*arg;{       	TokenListHeader *TH_ptr;		/* Insert the new list onto linked list of token lists */      	TH_ptr= make_TL_head(id);	TH_ptr->tokenlist = (arg == NULL ? NULL: arg->next_token);	TH_ptr->next = symt->info.toklist;	symt->info.toklist = TH_ptr;} /*call_external*/voidcall_func(id,arg)	/* Process function invocation */	Token *id, *arg;{	int t, h=id->value.integer;	Lsymtab *symt;	Gsymtab *gsymt;	IntrinsInfo *defn;	if( (symt = (hashtab[h].loc_symtab)) == NULL){	   symt = install_local(id,h,type_UNDECL,class_SUBPROGRAM);       	   symt->info.toklist = NULL;	}	t = datatype_of(symt->type);		/* Symbol seen before: check it & change class */	if(storage_class_of(symt->type) == class_VAR) {	    symt->type = type_byte(class_SUBPROGRAM,t);	    symt->info.toklist = NULL;	  }		/* See if intrinsic.  If so, set flag, save info */    if(!symt->external && !symt->intrinsic		&& (defn = find_intrinsic(symt->name)) != NULL) {			/* First encounter with intrinsic fcn: store info */		symt->intrinsic = TRUE;		symt->info.intrins_info = defn;    }		/* Update set/used status of variables in arg list.  This		   is deferred to now to allow intrinsics to be treated		   as pure functions regardless of pure_function flag. */	if(arg != NULL) {	    Token *a=arg;	    int nonpure = symt->intrinsic?		(symt->info.intrins_info->intrins_flags&I_NONPURE)		: ! pure_functions;  	    while( (a=a->next_token) != NULL) {	      if(is_true(ID_EXPR,a->subclass)){		if( nonpure ) {			     /* Treat impure function like subroutine call */		  use_actual_arg(a);		  use_variable(a);		}		else {			     /* Pure-function invocation checks u-b-s */		  use_function_arg(a);		}	      }	    }	}		/* If intrinsic, do checking now.  Otherwise, save arg list		   to be checked later. */    if(symt->intrinsic) {			/* It is intrinsic: check it */	check_intrins_args(id,arg);    }    else {		/* It is not intrinsic: install in global table */      switch(storage_class_of(symt->type)) {	case class_SUBPROGRAM:	  symt->external = TRUE;	  if((!symt->argument) && (gsymt=(hashtab[h].glob_symtab)) == NULL) {		gsymt = install_global(h,type_UNDECL,class_SUBPROGRAM);		gsymt->info.arglist = NULL;	  }			/* store arg list in local table */	  call_external(symt,id,arg);	  break;	case class_STMT_FUNCTION:	  symt->external = TRUE;	  check_stmt_function_args(symt,id,arg);	  break;      }    }    symt->used_flag = TRUE;    symt->invoked_as_func = TRUE;} /*call_func*/voidcall_subr(id,arg)	/* Process call statements */	Token *id, *arg;{	int t, h=id->value.integer;	Lsymtab *symt;	Gsymtab *gsymt;#ifndef STANDARD_INTRINSICS	IntrinsInfo *defn;#endif	if( (symt = (hashtab[h].loc_symtab)) == NULL){	   symt = install_local(id,h,type_SUBROUTINE,class_SUBPROGRAM);   	   symt->info.toklist = NULL;	}	t=datatype_of(symt->type);		/* Symbol seen before: check it & change class */	if(t == type_UNDECL) {		t = type_SUBROUTINE;		symt->info.toklist = NULL;	}	symt->type = type_byte(class_SUBPROGRAM,t);	/* Since nonstandard intrinsics include some subroutines,	   see if it is in intrinsic list.  Or	   if declared intrinsic, then accept it as such and	   do checking now.  Otherwise, save arg list	   to be checked later. */#ifndef STANDARD_INTRINSICS    if(!symt->external && !symt->intrinsic		&& (defn = find_intrinsic(symt->name)) != NULL) {			/* First encounter with intrinsic fcn: store info */		symt->intrinsic = TRUE;		symt->info.intrins_info = defn;    }#endif    if(symt->intrinsic) {			/* It is intrinsic: check it */	check_intrins_args(id,arg);    }    else {		/* It is not intrinsic: install in global table */	symt->external = TRUE;	if((!symt->argument) && (gsymt=(hashtab[h].glob_symtab)) == NULL) {		gsymt = install_global(h,type_UNDECL,class_SUBPROGRAM);		gsymt->info.arglist = NULL;	}			/* store arg list in local table */	call_external(symt,id,arg);    }	symt->used_flag = TRUE;}/*call_subr*/		/* This routine catches syntax errors that have to		   wait till END is seen.  At the moment, only looks if		   CHARACTER*(*) declarations are put on the wrong thing.		   Has to wait since can use it for ENTRY pt.		   Also checks if things SAVED that shouldn't be.		 */voidcheck_loose_ends(curmodhash)     int curmodhash;    /* current_module_hash from fortran.y */{  int i;  for(i=0;i<loc_symtab_top;i++) {    if( datatype_of(loc_symtab[i].type) == type_STRING &&	loc_symtab[i].size == size_ADJUSTABLE &&       !(loc_symtab[i].argument ||	   loc_symtab[i].parameter ||	     loc_symtab[i].entry_point) ) {      syntax_error(NO_LINE_NUM,NO_COL_NUM,loc_symtab[i].name);      msg_tail("cannot be adjustable size in module");      msg_tail(hashtab[curmodhash].name);    }    if(loc_symtab[i].saved &&        (loc_symtab[i].common_var ||	 loc_symtab[i].argument ||	 loc_symtab[i].external ||	 loc_symtab[i].parameter ||	 loc_symtab[i].entry_point) ) {      syntax_error(NO_LINE_NUM,NO_COL_NUM,loc_symtab[i].name);      msg_tail("cannot be declared in SAVE statement in module");      msg_tail(hashtab[curmodhash].name);    }  }}		/* check out consistency of intrinsic argument list */PRIVATEvoidcheck_intrins_args(id, arg)	Token *id;	Token *arg;{	int h=id->value.integer;	Lsymtab *symt=hashtab[h].loc_symtab;	IntrinsInfo *defn=symt->info.intrins_info;	unsigned args_given = ((arg == NULL)?0:arg_count(arg->next_token));	int numargs;	unsigned short flags;	Token *t;	numargs = defn->num_args;	flags = defn->intrins_flags;			/* positive numargs: must agree */	if( (numargs >= 0 && (args_given != numargs))			/* 1 or 2 arguments allowed */	 || (numargs == I_1or2 && (args_given != 1 && args_given != 2))			/* numargs == -2: 2 or more */	 || (numargs == I_2up && (args_given < 2))			/* 0 or 1 argument allowed */	 || (numargs == I_0or1 && (args_given != 0 && args_given != 1)) ){		unsigned line_num,col_num;		if(arg==NULL) {line_num=id->line_num; col_num=id->col_num;}		else {line_num = arg->line_num; col_num = arg->col_num;}		syntax_error(line_num,col_num,		  "wrong number of arguments for intrinsic function");		msg_tail(defn->name);	}	if(arg != NULL) {	  Token *prev_t,	/* one operand in type propagation  */	         fake_op;	/* operator in binexpr_type call */	  arg->next_token = t = reverse_tokenlist(arg->next_token);				/* Copy type & size info into result */	  arg->class = t->class;	  arg->subclass = t->subclass;	  arg->size = t->size;	  prev_t = t;	  while(t != NULL) {	    if(intrins_arg_cmp(defn,t)) {				/* Propagate data type thru the list.				   Resulting type info is stored in				   args token.  */	      if(prev_t != t && ! (flags & I_MIXED_ARGS) ) {				/* Set up a pretend expr term for binexpr */		fake_op.class = ',';		fake_op.line_num = prev_t->line_num;		fake_op.col_num = prev_t->col_num;		binexpr_type(prev_t,&fake_op,t,arg);	      }	      prev_t = t;	    }	    t = t->next_token;	  }/* end while */	}/* end arg != NULL */}/* check_intrins_args */PRIVATEvoidcheck_stmt_function_args(symt,id,arg)	Lsymtab *symt;	Token *id,*arg;{	unsigned n1,n2,n;	int i;	Token *t1,*t2;	t1 = symt->info.toklist->tokenlist;	t2 = ((arg==NULL)? NULL: reverse_tokenlist(arg->next_token));	n1 = arg_count(t1);	n2 = arg_count(t2);	if(n1 != n2) {	    syntax_error(id->line_num,id->col_num,		"function invoked with incorrect number of arguments");	}	n = (n1 < n2? n1: n2);	for(i=0; i<n; i++) {#ifdef OLDSTUFF	    if( t1->class != t2->class) {		syntax_error(t2->line_num,t2->col_num,		  "function argument is of incorrect datatype");	    }#else	    stmt_fun_arg_cmp(symt,t1,t2);

⌨️ 快捷键说明

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