home *** CD-ROM | disk | FTP | other *** search
- /*
- * classMethod.c
- * Dictionary of classes, methods and fields.
- *
- * Copyright (c) 1996 Systems Architecture Research Centre,
- * City University, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
- */
-
- #define CDBG(s)
- #define MDBG(s)
- #define FDBG(s)
-
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <stdlib.h>
- #include "gtypes.h"
- #include "constants.h"
- #include "classMethod.h"
- #include "code.h"
- #include "access.h"
- #include "readClass.h"
- #include "baseClasses.h"
- #include "errors.h"
-
- extern strpair* initpair; /* Class init pair <clinit>()V */
- extern strpair* finalpair; /* Class finalize pair finalize()V */
- extern classes* classInitHead;
- extern int classInitLevel;
-
- static classes* classPool[CLASSHASHSZ];
- methods* methodList; /* For exception processing */
-
- static classes* internalAddClass(char*, char*, int, char*, classes*, int, constants*);
-
- classes*
- addClass(constIndex c, constIndex s, u2 flags, constants* pool)
- {
- char* str;
- char* sstr;
- classes* cl;
- classes* su;
- int basesize;
- char sig[MAXSIG];
-
- /* Find the name of the class */
- if (pool->tags[c] != CONSTANT_Class) {
- CDBG( printf("addClass: not a class.\n"); )
- return (0);
- }
- c = pool->data[c];
- if (pool->tags[c] != CONSTANT_Utf8) {
- CDBG( printf("addClass: not a Utf8.\n"); )
- return (0);
- }
- str = (uint8*)pool->data[c];
- assert(strlen(str) > 0);
-
- /* Build signature */
- if (str[0] != '[') {
- strcpy(sig, "L");
- strcat(sig, str);
- strcat(sig, ";");
- }
- else {
- strcpy(sig, str);
- }
-
- /* Find the name of the super class */
- if (s != 0) {
- if (pool->tags[s] != CONSTANT_Class) {
- CDBG( printf("addClass: not a class.\n"); )
- return (0);
- }
- s = pool->data[s];
- if (pool->tags[s] != CONSTANT_Utf8) {
- CDBG( printf("addClass: not a Utf8.\n"); )
- return (0);
- }
- sstr = (uint8*)pool->data[s];
- /* Make sure it's loaded in */
- su = lookupClass(sstr);
- if (su == 0) {
- return (0);
- }
- basesize = su->fsize;
- }
- else {
- su = 0;
- basesize = 0;
- sstr = 0;
- }
-
- CDBG( printf("Adding class %s (%x)\n", str, flags); )
-
- return (internalAddClass(str, addString(sig), flags, sstr, su, basesize, pool));
- }
-
- classes*
- internalAddClass(char* str, char* sig, int flags, char* sstr, classes* su, int basesize, constants* pool)
- {
- classes** clp;
- classes* cl;
- methodTable* mt;
- uint32 hash;
- int i;
-
- for (i = 0, hash = 0; str[i] != 0; i++) {
- hash = hash * 33 + str[i];
- }
- hash %= CLASSHASHSZ;
-
- clp = &classPool[hash];
- #ifdef DEBUG
- while (*clp != 0) {
- assert(str != (*clp)->name);
- clp = &(*clp)->next;
- }
- #endif
-
- /* Allocate a class - it's an object too! */
- cl = alloc_class();
- if (cl == 0) {
- return (0);
- }
- mt = (methodTable*)calloc(sizeof(methodTable), 1);
- if (mt == 0) {
- return (0);
- }
- mt->class = cl;
-
- cl->name = str;
- cl->sig = sig;
- cl->supername = sstr;
- cl->constants = pool;
- cl->methodList = 0;
- cl->fieldList = 0;
- cl->staticFieldList = 0;
- cl->superclass = su;
- cl->fsize = basesize;
- cl->sfsize = 0;
- cl->accflags = flags;
- cl->mtable = mt;
- cl->staticFields = 0;
- cl->interface = 0;
- cl->interface_len = 0;
- cl->state = CSTATE_OK;
- cl->final = false;
- /* Add into list */
- cl->next = *clp;
- *clp = cl;
-
- return (cl);
- }
-
- methods*
- addMethod(classes* c, method_info* m)
- {
- constIndex nc;
- constIndex sc;
- methods** mptr;
- methods* mt;
- constants* pool;
- strpair* pair;
-
- pool = c->constants;
-
- nc = m->name_index;
- if (pool->tags[nc] != CONSTANT_Utf8) {
- MDBG( printf("addMethod: no method name.\n"); )
- return (0);
- }
- sc = m->signature_index;
- if (pool->tags[sc] != CONSTANT_Utf8) {
- MDBG( printf("addMethod: no signature name.\n"); )
- return (0);
- }
- pair = addStringConstantPair((char*)pool->data[nc], (char*)pool->data[sc]);
- assert(pair != 0);
-
- /* Mark class for init if this is the class init method */
- if (pair == initpair) {
- c->state = CSTATE_NEEDINIT;
- }
- else if (pair == finalpair) {
- c->final = true;
- }
-
- /* Search down class for method name - don't allow duplicates */
- mptr = &c->methodList;
- #ifdef DEBUG
- while (*mptr != 0) {
- assert(pair != (*mptr)->pair);
- mptr = &(*mptr)->next;
- }
- #endif
-
- MDBG( printf("Adding method %s:%s%s (%x)\n", c->name, pool->data[nc], pool->data[sc], m->access_flags); )
-
- mt = (methods*)malloc(sizeof(methods));
- if (mt == 0) {
- return (0);
- }
- mt->pair = pair;
- mt->class = c;
- mt->accflags = m->access_flags;
- mt->code = 0;
- mt->insn = 0;
- mt->ncode = 0;
- mt->constants = pool;
- mt->stacksz = 0;
- mt->localsz = 0;
- mt->exception_table = 0;
- mt->exception_table_len = 0;
- mt->exception_next = 0;
- mt->tableswitches = 0;
- mt->lookupswitches = 0;
- countInsAndOuts((char*)pool->data[sc], &mt->ins, &mt->outs);
- mt->next = *mptr;
- *mptr = mt;
-
- return (mt);
- }
-
- fields*
- addField(classes* c, field_info* f)
- {
- constIndex nc;
- constIndex sc;
- fields** fptr;
- fields* ft;
- char* sig;
- constants* pool;
- int* optr;
-
- pool = c->constants;
-
- nc = f->name_index;
- if (pool->tags[nc] != CONSTANT_Utf8) {
- FDBG( printf("addField: no field name.\n"); )
- return (0);
- }
-
- /* Search down class for field name */
- if (f->access_flags & ACC_STATIC) {
- fptr = &c->staticFieldList;
- optr = &c->sfsize;
- }
- else {
- fptr = &c->fieldList;
- optr = &c->fsize;
- }
- #ifdef DEBUG
- while (*fptr != 0) {
- assert((char*)pool->data[nc] != (*fptr)->name);
- fptr = &(*fptr)->next;
- }
- #endif
-
- FDBG( printf("Adding field %s:%s\n", c->name, pool->data[nc]); )
-
- sc = f->signature_index;
- if (pool->tags[sc] != CONSTANT_Utf8) {
- FDBG( printf("addField: no signature name.\n"); )
- return (0);
- }
- sig = (char*)pool->data[sc];
-
- ft = (fields*)malloc(sizeof(fields));
- if (ft == 0) {
- return (0);
- }
- ft->name = (char*)pool->data[nc];
- ft->sig = sig;
- ft->class = c;
- ft->accflags = f->access_flags;
- ft->size = sizeofSig(&sig);
- ft->offset = *optr;
- (*optr) += ft->size;
- ft->next = *fptr;
- *fptr = ft;
-
- return (ft);
- }
-
- void
- addMethodCode(methods* m, Code* c)
- {
- m->code = c->code;
- m->codelen = c->code_length;
- m->stacksz = c->max_stack;
- m->localsz = c->max_locals;
- m->exception_table = c->exception_table;
- m->exception_table_len = c->exception_table_length;
- }
-
- void
- addInterfaces(classes* c, int inr, classes** inf)
- {
- assert(inr > 0);
-
- c->interface = inf;
- c->interface_len = inr;
- }
-
- /*
- * Lookup a named class, loading it if necessary.
- */
- classes*
- lookupClass(char* c)
- {
- classes* class;
-
- class = simpleLookupClass(c);
- if (class == 0) {
- /* Failed to find class, so must now load it */
- findClass(c);
-
- /* Once loaded, allocate the static data space */
- class = simpleLookupClass(c);
- assert(class != 0);
- if (class->sfsize > 0) {
- class->staticFields = (int*)calloc(class->sfsize, sizeof(int));
- assert(class->staticFields != 0);
- }
- }
- /* This class requires initialisation so place it at head of
- current init list. If already at head of an init list (not this
- one), then we have a recursive init which is an error */
- if (class->state == CSTATE_OK || class->state == classInitLevel) {
- /* Do nothing. */
- }
- else {
- assert(class->state <= classInitLevel);
- /* If already on a list, remove it */
- if (class->state != CSTATE_NEEDINIT) {
- if (class->prevInit == 0) {
- throwException(ClassCircularityError);
- }
- class->prevInit->nextInit = class->nextInit;
- if (class->nextInit != 0) {
- class->nextInit->prevInit = class->prevInit;
- }
- }
- /* Insert onto current list */
- class->state = classInitLevel;
- class->prevInit = 0;
- class->nextInit = classInitHead;
- if (classInitHead) {
- classInitHead->prevInit = class;
- }
- classInitHead = class;
- }
- return (class);
- }
-
- classes*
- simpleLookupClass(char* c)
- {
- uint32 hash;
- char* str;
- classes* clp;
-
- for (str = c, hash = 0; *str != 0; str++) {
- hash = hash * 33 + *str;
- }
- hash %= CLASSHASHSZ;
-
- clp = classPool[hash];
- while (clp != 0) {
- if (c == clp->name) {
- return (clp);
- }
- clp = clp->next;
- }
- return (0);
- }
-
- /*
- * Lookup a named field.
- */
- fields*
- lookupClassField(char* c, char* f, bool isStatic)
- {
- classes* clp;
- fields* fptr;
-
- /* Look for class */
- clp = lookupClass(c);
- if (clp == 0) {
- return (0);
- }
-
- /* Search down class for field name */
- if (isStatic) {
- fptr = clp->staticFieldList;
- }
- else {
- fptr = clp->fieldList;
- }
- while (fptr != 0) {
- if (f == fptr->name) {
- return (fptr);
- }
- fptr = fptr->next;
- }
- FDBG( printf("Class:field lookup failed %s:%s\n", c, f); )
- return (0);
- }
-
- /*
- * Determine the number of arguments and return values from the
- * method signature.
- */
- void
- countInsAndOuts(char* str, int* ins, int* outs)
- {
- *ins = sizeofSig(&str);
- *outs = sizeofSig(&str);
- }
-
- /*
- * Calculate size of data item based on signature.
- */
- int
- sizeofSig(char** strp)
- {
- int count;
- char* str;
-
- count = 0;
- for (str = *strp; *str != 0; str++) {
- switch (*str) {
- case '(':
- break;
- case ')':
- *strp = str+1;
- return (count);
- case 'I':
- case 'Z':
- case 'S':
- case 'B':
- case 'C':
- case 'F':
- count++;
- break;
- case 'D':
- case 'J':
- count += 2;
- break;
-
- case 'V':
- break;
- case '[':
- count++;
- str++;
- if (*str == 'L') {
- while (*str != ';') {
- str++;
- }
- }
- break;
- case 'L':
- count++;
- /* Skip to end of reference */
- while (*str != ';') {
- str++;
- }
- break;
- default:
- abort();
- }
- }
- *strp = str;
- return (count);
- }
-
- /*
- * Add this method to the method list so we can find it when
- * handling exceptions.
- */
- void
- establishMethod(methods* m)
- {
- m->exception_next = methodList;
- methodList = m;
- }
-
- /*
- * Lookup an array class.
- */
- classes*
- lookupArray(char* c)
- {
- classes* class;
-
- class = simpleLookupClass(c);
- if (class == 0) {
- class = internalAddClass(c, c, 0, 0, 0, 0, 0);
- CDBG( if (class == 0) {
- printf("Array Class %s not loaded.\n", c);
- } )
- }
- return (class);
- }
-