/*
 * $Id: jexc_sys_class.c,v 1.4 2000/09/06 13:33:55 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"
#include "jexc_sys_class.h"

static int sys_cp_class_index(char *str);

enum jexc_sys_def_kind {
    SYS_DEF_END = 0,
    SYS_DEF_CLASS,
    SYS_DEF_METHOD,
    SYS_DEF_VAR,
    SYS_DEF_STATIC,
    SYS_DEF_IMPL
};

struct jexc_sys_def_entry {
    enum jexc_sys_def_kind tag;
    char *name;
    char *desc;		/* super in case of SYS_DEF_CLASS */
    int field_disp;
    char *method_cname;
};

cp_info sys_cp_info[MAX_SYS_CP];
int sys_cp_info_count = 0;

extern struct jexc_sys_def_entry jexc_sys_def_table[];

class_file *sys_class_create(char *name,char *super,
			     int n_field,int n_method,int n_interface);
int sys_cp_str_index(char *str);

void init_sys_class()
{
    class_file *cfp;
    method_info *mp;
    field_info *fp;
    struct jexc_sys_def_entry *p,*q,*pp;
    int n_method,n_field,n_interface;

    /* Object class is special */
    cfp = sys_class_create("java/lang/Object",NULL,0,4,0);

    cfp->methods[JEXC_CLINIT_METHOD].name_index = 
	sys_cp_str_index(Lang_Object_CLINIT_NAME);
    cfp->methods[JEXC_CLINIT_METHOD].desc_index = 
	sys_cp_str_index(Lang_Object_CLINIT_DESC);
    cfp->methods[JEXC_CLINIT_METHOD].cname = 
	Lang_Object_CLINIT_CNAME;

    cfp->methods[JEXC_INIT_METHOD].name_index = 
	sys_cp_str_index(Lang_Object_INIT_NAME);
    cfp->methods[JEXC_INIT_METHOD].desc_index = 
	sys_cp_str_index(Lang_Object_INIT_DESC);
    cfp->methods[JEXC_INIT_METHOD].cname = 
	Lang_Object_INIT_CNAME;

    cfp->methods[JEXC_TOSTRING_METHOD].name_index = 
	sys_cp_str_index(Lang_Object_toString_NAME);
    cfp->methods[JEXC_TOSTRING_METHOD].desc_index = 
	sys_cp_str_index(Lang_Object_toString_DESC);
    cfp->methods[JEXC_TOSTRING_METHOD].cname = 
	Lang_Object_toString_CNAME;

    cfp->methods[JEXC_EQUALS_METHOD].name_index = 
	sys_cp_str_index(Lang_Object_equals_NAME);
    cfp->methods[JEXC_EQUALS_METHOD].desc_index = 
	sys_cp_str_index(Lang_Object_equals_DESC);
    cfp->methods[JEXC_EQUALS_METHOD].cname = 
	Lang_Object_equals_CNAME;

    class_root = cfp;
    
    for(p = jexc_sys_def_table; p->tag != SYS_DEF_END; p = q){
	n_method = 0;
	n_field = 0;
	n_interface = 0;
	for(q = p+1; q->tag != SYS_DEF_CLASS && q->tag != SYS_DEF_END; q++){
	    switch(q->tag){
	    case SYS_DEF_METHOD:
		n_method++;
		break;
	    case SYS_DEF_IMPL:
		n_interface++;
		break;
	    case SYS_DEF_STATIC:
	    case SYS_DEF_VAR:
		 n_field++;	/* else SYS_DEF_VAR or SYS_DEF_STATIC */
		 break;
	    default: break;
	    }
	}
	cfp = sys_class_create(p->name,p->desc,n_field,n_method,n_interface);

	n_method = 0;
	n_field = 0;
	n_interface = 0; 
	for(pp = p+1; pp != q; pp++){
	    switch(pp->tag){
	    case SYS_DEF_METHOD:
		mp = &cfp->methods[n_method++];
		mp->name_index = sys_cp_str_index(pp->name);
		mp->desc_index = sys_cp_str_index(pp->desc);
		if(strcmp(pp->method_cname,"*") != 0)
		    mp->cname = pp->method_cname;
		break;
	    case SYS_DEF_IMPL:
		cfp->interfaces[n_interface++] = sys_cp_class_index(pp->name);
		break;
	    case SYS_DEF_STATIC:
		fp = &cfp->fields[n_field++];
		fp->is_static = TRUE;
		fp->name_index = sys_cp_str_index(pp->name);
		fp->desc_index = sys_cp_str_index(pp->desc);
		fp->disp = pp->field_disp;
		break;
	    case SYS_DEF_VAR:
		fp = &cfp->fields[n_field++];
		fp->is_static = FALSE;
		fp->name_index = sys_cp_str_index(pp->name);
		fp->desc_index = sys_cp_str_index(pp->desc);
		fp->disp = pp->field_disp;
		break;
	    default: break;
	    }
	}
    }
}

class_file *sys_class_create(char *name,char *super,int n_field,int n_method,
			     int n_interface)
{
    class_file *cfp;

    cfp = (class_file *)xmalloc(sizeof(class_file));

    if(class_tail == NULL){
	class_files = class_tail = cfp;
    } else {
	class_tail->link = cfp;
	class_tail = cfp;
    }

    cfp->is_system = TRUE;
    cfp->this_class_name = intern(name);
    if(super != NULL){
	if(strcmp(super,"*interface*") == 0){
	    cfp->super = class_root;
	    cfp->is_interface = TRUE;
	} else 
	    cfp->super = find_class(intern(super));
    }

    cfp->cp_info_table = sys_cp_info;	/* share cp info */

    cfp->method_count = n_method;
    if(n_method != 0)
	cfp->methods = (method_info *)xmalloc(sizeof(method_info)*n_method);

    cfp->field_count = n_field;
    if(n_field != 0)
	cfp->fields = (field_info *)xmalloc(sizeof(field_info)*n_field);

    cfp->interface_count = n_interface;
    if(n_interface != 0)
	cfp->interfaces = (int *)xmalloc(sizeof(int)*n_interface);

    return cfp;
}

int sys_cp_str_index(char *str)
{
    cp_info *cp;
    int i;

    i = sys_cp_info_count++;
    cp = &sys_cp_info[i];
    cp->tag = CONSTANT_utf8;
    cp->info.utf8.str = intern(str);
    cp->info.utf8.len = strlen(str);
    return i;
}

static int sys_cp_class_index(char *str)
{
    cp_info *cp;
    int i, str_i;
    
    str_i = sys_cp_str_index(str);
    i = sys_cp_info_count++;
    cp = &sys_cp_info[i];
    cp->tag = CONSTANT_Class;
    cp->info.class.name_index = str_i;
    cp->info.class.cfp = find_class(intern(str));
    return i;
}

struct jexc_sys_def_entry jexc_sys_def_table[] = {
    #include "jexc_sys_class.def.c"
    {SYS_DEF_END,NULL,NULL}
};

