/*
 * $Id: jexc_util.c,v 1.3 2000/09/05 15:08:57 m-hirano Exp $
 * $RWC_Release: Omni-1.6 $
 * $RWC_Copyright:
 *  Omni Compiler Software Version 1.5-1.6
 *  Copyright (C) 2002 PC Cluster Consortium
 *  
 *  This software is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version
 *  2.1 published by the Free Software Foundation.
 *  
 *  Omni Compiler Software Version 1.0-1.4
 *  Copyright (C) 1999, 2000, 2001.
 *   Tsukuba Research Center, Real World Computing Partnership, Japan.
 *  
 *  Please check the Copyright and License information in the files named
 *  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
 *  Software release kit.
 *  
 *  
 *  $
 */

#include "jexc.h"

struct opcode_info *opcode_infos[MAX_OPCODE];

void init_opcode_table()
{
    struct opcode_info *ip;
    for(ip = opcode_info_table; ip->name != NULL; ip++){
	opcode_infos[ip->opcode] = ip;
    }
}

char *get_cp_str(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_utf8){
	fatal("get_cp_str: not CONSTANT_utf8 (index=%d)\n",
		index);
    }
    return cp->info.utf8.str;
}

char *get_class_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Class){
	fatal("get_class_name: not CONSTANT_Class (index=%d)\n",
		index);
    }
    return get_cp_str(cfp,cp->info.class.name_index);
}

class_file *get_class(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Class){
	fatal("get_class: not CONSTANT_Class (index=%d)\n",
		index);
    }
    return cp->info.class.cfp;
}

class_file *get_field_class(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Fieldref){
	fatal("get_field_class not CONSTANT_Fieldref (index=%d)\n",
		index);
    }
    return get_class(cfp,cp->info.field.class_index);
}

char *get_field_class_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Fieldref){
	fatal("get_field_class_name not CONSTANT_Fieldref (index=%d)\n",
		index);
    }
    return get_class_name(cfp,cp->info.field.class_index);
}

char *get_field_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Fieldref){
	fatal("get_field_name: not CONSTANT_Fieldref (index=%d)\n",
		index);
    }
    return get_NameAndType_name(cfp,cp->info.field.name_index);
}

field_info *get_field(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Fieldref){
	fatal("get_field: not CONSTANT_Fieldref (index=%d)\n",
		index);
    }
    return cp->info.field.fp;
}

char *get_field_desc(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Fieldref){
	fatal("get_field_desc: not CONSTANT_Fieldref (index=%d)\n",
		index);
    }
    return get_NameAndType_desc(cfp,cp->info.field.name_index);
}

method_info *get_method(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Methodref &&
       cp->tag != CONSTANT_InterfaceMethodref){
	fatal("get_method: not CONSTANT_Methodref (index=%d)\n",
		index);
    }
    return cp->info.method.mp;
}

class_file *get_method_class(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Methodref &&
       cp->tag != CONSTANT_InterfaceMethodref){
	fatal("get_method_class not CONSTANT_Methodref (index=%d)\n",
		index);
    }
    return get_class(cfp,cp->info.method.class_index);
}

char *get_method_class_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Methodref &&
       cp->tag != CONSTANT_InterfaceMethodref){
	fatal("get_method_class_name: not CONSTANT_Methodref (index=%d)\n",
		index);
    }
    return get_class_name(cfp,cp->info.method.class_index);
}

char *get_method_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Methodref &&
       cp->tag != CONSTANT_InterfaceMethodref){
	fatal("get_method_name: not CONSTANT_Methodref (index=%d)\n",
		index);
    }
    return get_NameAndType_name(cfp,cp->info.method.name_index);
}

char *get_method_desc(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_Methodref &&
       cp->tag != CONSTANT_InterfaceMethodref){
	fatal("get_method_desc: not CONSTANT_Methodref (index=%d)\n",
		index);
    }
    return get_NameAndType_desc(cfp,cp->info.method.name_index);
}

char *get_NameAndType_desc(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_NameAndType){
	fatal("get_NameAndType_desc: not CONSTANT_NameAndType (index=%d)\n",
		index);
    }
    return get_cp_str(cfp,cp->info.name.desc_index);
}

char *get_NameAndType_name(class_file *cfp,int index)
{
    cp_info *cp;
    cp = &(cfp->cp_info_table[index]);
    if(cp->tag != CONSTANT_NameAndType){
	fatal("get_NameAndType_name: not CONSTANT_NameAndType (index=%d)\n",
		index);
    }
    return get_cp_str(cfp,cp->info.name.name_index);
}

int get_desc_narg(char *desc){
    int narg = 0;
    if(*desc++ != '(') goto err;
next:
    switch(*desc++){
    case 'B':
    case 'C':
    case 'F':
    case 'I':
    case 'S':
    case 'Z':
	narg++;
	goto next;
    case 'D':
    case 'J':
	narg += 2;
	goto next;
    case '[':
	goto next;
    case ')': 
	return narg;
    case 'L':
	narg++;
	while(*desc != '\0') if(*desc++ == ';') goto next;
	break;
    }
err:
    fatal("get_narg: bad method desc '%s'",desc);
    return 0;
}

/*
 * Data type
 */
DATA_TYPE get_desc_data_type(char *name)
{
    if(name[1] != '\0') return OBJECT;
    switch(name[0]){
    case 'B': /* byte */
	return BYTE;
    case 'Z':   /* boolean */
    case 'C':	/* char */
	return SHORT;
    case 'I': /* int */
	return INT;
    case 'D':
	return DOUBLE;
    case 'F':
	return FLOAT;
    case 'J':
	return LONG;
    case 'S':
	return SHORT;
    default:
	return OBJECT;
    }
}


char *attr_name(enum attr_kind k)
{
    switch(k){
    case ATTR_CODE: return "*CODE*";
    case ATTR_EXCEPTIONS: return "*EXCEPTIONS*";
    case ATTR_SYNTHETIC: return "*SYNTHETIC*";
    case ATTR_LINE_NO: return "*LINE_NO*";
    case ATTR_LOCAL_VAR: return "*LOCAL_VAR*";
    case ATTR_SOURCE_FILE: return "*SOURCE_FILE*";
    case ATTR_INNER_CLASS: return "*INNER_CLASS*";
    case ATTR_CONST_VAL: return "*CONST_VAL*";
    default: return "*ATTR_???*";
    }
}

struct opcode_info opcode_info_table[] =
{
#include "jvm-opcode.c"
    {0,NULL,NULL}  /* last entry */
};



	
