rem: scope ? scope : NULL,in_access_val,ret_type,arg_types);
add: scope ? scope : "NULL", in_access_val,ret_type,arg_types);
context: search_for_symbol(char *global_class_name,char *local_class_name,	char *name,char *arg_types,int db_type,char *scope,char *ret_type,	char *macro_value,int exact){	DB	*dbp;	DBT	key;	DBT	data;	int	length;	char	in_access_val[80];	char	sym_type[50];	char param_args[2048];	char	*bufval;	LongString buf;	LongString rounded_arg_types;	LongString cls_name;	LongString tmp;	int	flag;	int	cmp = 1;	int	fetch;	int arg_types_len;	int num;	char **fields;#if BUG_TRACE	static	FILE	*trace_fp;	if (!trace_fp)	{		trace_fp = fopen("/tmp/dbutils.log","w+");		chmod("/tmp/dbutils.log",0666);	}#endif /* BUG_TRACE */	LongStringInit(&buf,0);	LongStringInit(&rounded_arg_types,0);	LongStringInit(&cls_name,0);	LongStringInit(&tmp,0);	if (db_type == PAF_CLASS_TREE)	{		dbp = db_class_tree;	}	else	{		dbp = db_syms[db_type];	}	if (!dbp)		return FALSE;	if (db_type == PAF_CLASS_TREE)	{		buf.copystrings(&buf,			local_class_name				? local_class_name				: global_class_name, DB_FLDSEP_STR,			name,                    DB_FLDSEP_STR,			arg_types ? arg_types : NULL,			NULL);		length = buf.len + 1;	}	else	{		buf.appendstrings (&buf,name, DB_FLDSEP_STR, NULL);		length = buf.len;	}	bufval = buf.buf;	arg_types_len = arg_types ? strlen(arg_types) : 0;	key.data = (void *)bufval;	key.size = (u_int)length;	data.data = NULL;	data.size = 0;	fetch = dbp->seq(dbp,&key,&data,R_CURSOR);#if BUG_TRACE	fprintf(trace_fp,"Search for: <%s> return: %d ARGS: <%s>\n",		 buf.buf,		 fetch,		 arg_types ? arg_types : "NULL");#endif /* BUG_TRACE */	if (fetch == -1)		/* Error */	{		RETURN_FROM_SEARCH(FALSE);	}	if (fetch == 1 || (int)key.size <  length ||		memcmp(buf.buf,key.data,length) != 0)	{		if (db_type == PAF_CLASS_TREE && !exact && arg_types)		{#if !OPT_CLASS_TREE			DB	*db_md = db_syms[PAF_MBR_FUNC_DCL];#endif /* !OPT_CLASS_TREE */			char	*cl_nm_p;			int Round;			/* If might happen that we cannot find a method			 * because of typecasting problems. In this case, we			 * check whether the fetched or the previous			 * record matches the target method name. */			cls_name.copystrings(&cls_name,				local_class_name					? local_class_name					: global_class_name, DB_FLDSEP_STR,				name,                    DB_FLDSEP_STR,				NULL);			length = cls_name.len;			cl_nm_p = cls_name.buf;			rounded_arg_types.makespace (&rounded_arg_types, arg_types_len);			rounded_arg_types.len = RemoveIgnoredWords(rounded_arg_types.buf,arg_types);#if !OPT_CLASS_TREE			/* Search for the method in the current class, (not in base classes) */			if (db_md)			{				int function_avail = 0;				for (Round = 1; Round < LEVELS; Round++)				{					key.data = (void *)cl_nm_p;					key.size = (u_int)length;					data.data = NULL;					data.size = 0;					/* search for method in the base class! */					for (flag = R_CURSOR; db_md->seq(db_md, &key, &data, flag)== 0; flag = R_NEXT)					{						/* Still target class and method name ? */						if ((int)key.size < length + 1 || memcmp (cl_nm_p, key.data, length) != 0)							break;						function_avail = 1;						/*						 * Format:						 *						 *          <line> <access> <return type> <parameters> <parameter names>						 */						my_SplitList (data.data, &num, &fields, DB_FLDSEP_CHR);						if (num >= 4)						{							MY_STRNCPY (in_access_val, fields[1], sizeof (in_access_val));							MY_STRNCPY (ret_type,      fields[2], 1024); /* FIXME. */							MY_STRNCPY (param_args,    fields[3], sizeof (param_args));						}						else						{							in_access_val[0] = 0;							ret_type     [0] = 0;							param_args   [0] = 0;						}						ckfree ((char*)fields);												tmp.makespace (&tmp,data.size);						tmp.len = RemoveIgnoredWords (tmp.buf, param_args);#if BUG_TRACE						fprintf(trace_fp,"method type: <%s> <%s> <%s>\n",							tmp.buf,cl_nm_p,(char *)data.data);#endif /* BUG_TRACE */						if (tmp.len == rounded_arg_types.len &&							memcmp(tmp.buf,rounded_arg_types.buf,tmp.len) == 0)						{							/* method found and arguments are similar. */							memcpy(arg_types, param_args, strlen (param_args)+1);							if (scope)							{								sscanf(cl_nm_p,"%s",scope);								MY_DEBUG ((Output, "sscanf used by cl_nm_p <%s> Scope <%s>\n", cl_nm_p, scope));							}#if BUG_TRACE							fprintf(trace_fp,"1 scope: <%s> access: <%s> ret_type: <%s> arg_types: <%s>\n",								scope ? scope : NULL,in_access_val,ret_type,arg_types);#endif /* BUG_TRACE */							RETURN_FROM_SEARCH(PAF_MBR_FUNC_DEF);						}					}				}				/*				 * If method is availiable, we don't search in base classes,				 * we just take the first method of the class.				 */				if (function_avail)				{					key.data = (void *)cl_nm_p;					key.size = (u_int)length;					data.data = NULL;					data.size = 0;					if (db_md->seq (db_md, &key, &data, R_CURSOR) != 0)					{						RETURN_FROM_SEARCH(FALSE);					}					/*					 * format:					 *          <line> <access> <return type> <parameters> <parameter names>					 */					my_SplitList (data.data, &num, &fields, DB_FLDSEP_CHR);					if (num >= 4)					{						MY_STRNCPY (in_access_val, fields[1], sizeof (in_access_val));						MY_STRNCPY (ret_type,      fields[2], 1024);						MY_STRNCPY (arg_types,     fields[3], 10000);					}					else					{						in_access_val[0] = 0;						ret_type     [0] = 0;						arg_types    [0] = 0;					}					ckfree ((char*)fields);					if (scope)					{						sscanf(cl_nm_p,"%s",scope);						MY_DEBUG ((Output, "sscanf used 2 by cl_nm_p <%s> scope <%s>\n", cl_nm_p, scope));					}#if BUG_TRACE					fprintf(trace_fp,"2 scope: <%s> access: <%s> ret_type: <%s> arg_types: <%s>\n",						scope ? scope : NULL,in_access_val,ret_type,arg_types);#endif /* BUG_TRACE */					RETURN_FROM_SEARCH(PAF_MBR_FUNC_DEF);				}			}#endif /* !OPT_CLASS_TREE */			/* Search for the method in the base classes with similar parameters! */			for (Round = 1; Round < LEVELS; Round++)			{				/* search method exactly in the base classes */				key.data  = (void *)cl_nm_p;				key.size  = (u_int)length;				data.data = NULL;				data.size = 0;				for (flag = R_CURSOR; dbp->seq(dbp, &key, &data, flag)== 0; flag = R_NEXT)				{					/* Still the method being searching for ? */					if ((int)key.size < length + 1 || memcmp (cl_nm_p, key.data, length) != 0)						break;					tmp.makespace(&tmp,key.size);					tmp.len = RemoveIgnoredWords (tmp.buf,(char *)key.data + length);					if (tmp.len == rounded_arg_types.len &&						memcmp(tmp.buf,rounded_arg_types.buf,tmp.len) == 0)					{						/* It will copy the terminating '\0' too. */						memcpy(arg_types, (char*)key.data + length, key.size - length);						/*						 * format						 *						 *           <scope> <type> <access> <return type> <parameters> <parameter names>						 */						my_SplitList (data.data, &num, &fields, DB_FLDSEP_CHR);						if (num >= 4)						{							MY_STRNCPY (scope,         fields[0], sizeof(scope));							MY_STRNCPY (sym_type,      fields[1], sizeof(sym_type));							MY_STRNCPY (in_access_val, fields[2], sizeof(in_access_val));							MY_STRNCPY (ret_type,      fields[3], 1024);						}						else						{							scope        [0] = 0;							sym_type     [0] = 0;							in_access_val[0] = 0;							ret_type     [0] = 0;						}						ckfree ((char*)fields);						#if BUG_TRACE						fprintf(trace_fp,"3 scope: <%s> access: <%s> ret_type: <%s> arg_types: <%s>\n",							scope ? scope : NULL,in_access_val,ret_type,arg_types);#endif /* BUG_TRACE */						RETURN_FROM_SEARCH(PAF_MBR_FUNC_DEF);					}				}			}			/* No method matches the argument list, thus we just take the			 * first one.			 */			key.data  = (void *)cl_nm_p;			key.size  = (u_int)length;			data.data = NULL;			data.size = 0;			if (dbp->seq(dbp, &key, &data, R_CURSOR) != 0 ||				(int)key.size < length || memcmp(cl_nm_p, key.data, length) != 0)			{				RETURN_FROM_SEARCH(FALSE);			}			/* The terminating '\0' will be copied too. */			memcpy(arg_types,(char*)key.data + length,key.size - length);		}		else		{			RETURN_FROM_SEARCH(FALSE);		}	}	if (db_type == PAF_CLASS_TREE)	{		LongString pars;		LongStringInit(&pars,0);		pars.split (&pars, data.data, data.size-1, FALSE, DB_FLDSEP_CHR, 4);		memcpy(scope, pars.field_value[0], pars.field_size[0]);		scope[pars.field_size[0]] = '\0';		memcpy(sym_type, pars.field_value[1], pars.field_size[1]);		sym_type[pars.field_size[1]] = '\0';		memcpy (in_access_val, pars.field_value[2], pars.field_size[2]);		in_access_val[pars.field_size[2]] = '\0';		memcpy(ret_type,			pars.field_value[3],			pars.field_size[3]);		ret_type[pars.field_size[3]] = '\0';		pars.free(&pars);		if (sym_type[0] == SN_GetSymbolType(PAF_MBR_VAR_DEF)[0])		/* "iv" ? */		{			RETURN_FROM_SEARCH(PAF_MBR_VAR_DEF);		}#if BUG_TRACE		fprintf(trace_fp,"4 name: <%s> scope: <%s> access: <%s> ret_type: <%s> arg_types: <%s>\n",			buf.buf,			scope ? scope : NULL,			in_access_val,			ret_type,			arg_types ? arg_types : "NULL");#endif /* BUG_TRACE */		/* At this point we might return a method with wrong		 * argument list, but it is still better than saying that		 * the method is not known.		 */		RETURN_FROM_SEARCH(PAF_MBR_FUNC_DEF);	}	/* If we are searching for a function we have to check its	 * input arguments' types. (ANSI).	 */	fetch = 0;	do	{		/* Parse for example: line.col attr {struct fp *} {unsigned char *,const int} */		*in_access_val = '\0';		*ret_type = '\0';				/*		 * Field has the format, separated with DB_FLDSEP_CHR:		 *		 *    <line> <access> <return type> <paramaeter list> <parameter variables>		 *		 */		my_SplitList (data.data, &num, &fields, DB_FLDSEP_CHR);		if (num >= 4)		{			MY_STRNCPY (in_access_val, fields[1], sizeof (in_access_val));			MY_STRNCPY (ret_type,      fields[2], 1024);			MY_STRNCPY (param_args,    fields[3], sizeof (param_args));			if (arg_types && arg_types_len == (int)strlen(param_args) &&				memcmp (param_args, arg_types, arg_types_len) == 0)			{				ckfree ((char*)fields);				cmp = 0;				break;			}			else				cmp = 1;		}		ckfree ((char*)fields);	} while(arg_types &&		(fetch = dbp->seq(dbp,&key,&data,R_NEXT)) == 0 &&		(int)key.size >= length &&		(cmp = memcmp(bufval,key.data,length)) == 0);#define	MACRO_XREF 1#if MACRO_XREF	/* If the macro name and its contents are identical, we don't	 * return the contents because that could cause an end less loop.	 */	if (db_type == PAF_MACRO_DEF && macro_value)	{		strcpy(macro_value, ret_type);	}#endif /* MACRO_XREF */	if (arg_types)	{		/*		 * Here we take the last found function with its arguments.		 */		strcpy (arg_types, param_args);	}#if BUG_TRACE		fprintf(trace_fp,"5 func: <%s> access: <%s> ret_type: <%s> arg_types: <%s>\n",			buf.buf,in_access_val,ret_type,arg_types ? arg_types : "NULL");		fflush(trace_fp);#endif /* BUG_TRACE */	if (exact && arg_types && (fetch != 0 || cmp != 0))	{		RETURN_FROM_SEARCH(FALSE);	}	/* At this point we might return a function with wrong	 * argument list, but it is still better than saying that	 * the function is not known.	 */	RETURN_FROM_SEARCH(db_type);}