jdk/make/tools/GenerateCharacter/check_class.c.template
changeset 2 90ce3da70b43
child 1090 c5805b1672a6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/tools/GenerateCharacter/check_class.c.template	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* This file was generated AUTOMATICALLY from a template file Wed Jun 17 10:43:47 PDT 1998 */
+
+/*-
+ *      code for verifying the date in a ClassClass structure for internal
+ *      consistency.
+ */
+
+#include <ctype.h>
+
+#include "oobj.h"
+#include "interpreter.h"
+#include "bool.h"
+#include "utf.h"
+#include "tree.h"
+#include "sys_api.h"
+
+extern bool_t verify_class_codes(ClassClass *cb);
+
+static bool_t verify_constant_pool(ClassClass *cb);
+
+static bool_t is_legal_fieldname(ClassClass *cb, char *name, int type);
+static bool_t is_legal_method_signature(ClassClass *cb, char *name, char *signature);
+static bool_t is_legal_field_signature(ClassClass *cb, char *name, char *signature);
+
+static char *skip_over_fieldname(char *name, bool_t slash_okay);
+static char *skip_over_field_signature(char *name, bool_t void_okay);
+
+static void CCerror (ClassClass *cb, char *format, ...);
+
+
+/* Argument for is_legal_fieldname */
+enum { LegalClass, LegalField, LegalMethod };
+
+
+
+
+bool_t
+VerifyClass(ClassClass *cb)
+{
+    bool_t result = TRUE;
+    struct methodblock *mb;
+    struct fieldblock *fb;
+    int i;
+    if (CCIs(cb, Verified)) 
+	return TRUE;
+    if (!verify_constant_pool(cb)) 
+        return FALSE;
+    /* Make sure all the method names and signatures are okay */
+    for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
+	char *name = mb->fb.name;
+	char *signature = mb->fb.signature;
+	if (! (is_legal_fieldname(cb, name, LegalMethod)  &&
+	       is_legal_method_signature(cb, name, signature)))
+	    result = FALSE;
+    }
+    /* Make sure all the field names and signatures are okay */
+    for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++) {
+	if (!  (is_legal_fieldname(cb, fb->name, LegalField) &&
+		is_legal_field_signature(cb, fb->name, fb->signature))) 
+	    result = FALSE;
+    }
+    /* Make sure we are not overriding any final methods or classes*/
+    if (cbIsInterface(cb)) { 
+	struct methodblock *mb;
+	if ((cbSuperclass(cb) == NULL) ||
+	    (cbSuperclass(cb) != classJavaLangObject)) { 
+	    CCerror(cb, "Interface %s has bad superclass", cbName(cb));
+	    result = FALSE;
+	}
+	for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
+	    if (mb->fb.access & ACC_STATIC) {
+		if (mb->fb.name[0] != '<') { 
+		    /* Only internal methods can be static */
+		    CCerror(cb, "Illegal static method %s in interface %s",
+			    mb->fb.name, cbName(cb));
+		    result = FALSE;
+		}
+	    }
+	}
+    } else if (cbSuperclass(cb)) { 
+	ClassClass *super_cb;
+	unsigned bitvector_size = (unsigned)(cbMethodTableSize(cb) + 31) >> 5;
+	long *bitvector = sysCalloc(bitvector_size, sizeof(long));
+	for (super_cb = cbSuperclass(cb); ; super_cb = cbSuperclass(super_cb)) {
+	    if (cbAccess(super_cb) & ACC_FINAL) {
+		CCerror(cb, "Class %s is subclass of final class %s",
+			cbName(cb), cbName(super_cb));
+		result = FALSE;
+	    }
+	    mb = cbMethods(super_cb);
+	    for (i = cbMethodsCount(super_cb); --i >= 0; mb++) {
+		if (mb->fb.access & ACC_FINAL) {
+		    unsigned offset = mb->fb.u.offset;
+		    bitvector[offset >> 5] |= (1 << (offset & 0x1F));
+		}
+	    }
+	    if (cbSuperclass(super_cb) == NULL) break;
+	}
+	for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
+	    unsigned offset = mb->fb.u.offset;
+	    if ((offset > 0) 
+		   && bitvector[offset >> 5] & (1 << (offset & 0x1F))) {
+		CCerror(cb, "Class %s overrides final method %s.%s",
+			cbName(cb), mb->fb.name, mb->fb.signature);
+		result = FALSE;
+	    }
+	}
+	sysFree(bitvector);
+    } else if (cb != classJavaLangObject) {
+	CCerror(cb, "Class %s does not have superclass", cbName(cb));
+	result = FALSE;
+    }
+	
+    if (result)
+	result = verify_class_codes(cb);
+    if (result) 
+	CCSet(cb, Verified);
+    return result;
+}
+
+
+static bool_t
+verify_constant_pool(ClassClass *cb)
+{
+    union cp_item_type *cp = cbConstantPool(cb);
+    long cp_count = cbConstantPoolCount(cb);
+    unsigned char *type_table;
+    int i, type;
+    
+    const int utf8_resolved = (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED);
+
+    if (cp_count == 0) /* Primitive classes */
+        return TRUE;
+    type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+    /* Let's make two quick passes over the constant pool. The first one 
+     * checks that everything is of the right type.            */
+    for (i = 1; i < cp_count; i++) {
+	switch(type = type_table[i]) {
+	    case CONSTANT_String:
+	    case CONSTANT_Class: {
+		int index = cp[i].i;
+		if (   (index < 1) 
+		       || (index >= cp_count)
+		       || (type_table[index] != utf8_resolved)) {
+		    CCerror(cb, "Bad index in constant pool #%d", i);
+		    return FALSE;
+		}
+		break;
+	    }
+		
+	    case CONSTANT_String | CONSTANT_POOL_ENTRY_RESOLVED:
+		/* This can only happen if a string is the "initial" value of
+		 * some final static String.  We assume that the checking has
+		 * already been done.
+		 */
+		break;
+
+	    case CONSTANT_Fieldref:
+	    case CONSTANT_Methodref:
+	    case CONSTANT_InterfaceMethodref: 
+	    case CONSTANT_NameAndType: {
+		unsigned index = (unsigned)(cp[i].i);
+		int key1 = index >> 16;
+		int key2 = index & 0xFFFF;
+		if (key1 < 1 || key1 >= cp_count 
+		      || key2 < 1 || key2 >= cp_count) {
+		    CCerror(cb, "Bad index in constant pool #%d", i);
+		    return FALSE;
+		}
+		if (type == CONSTANT_NameAndType) {
+		    if (   (type_table[key1] != utf8_resolved) 
+			|| (type_table[key2] != utf8_resolved)) {
+			CCerror(cb, "Bad index in constant pool.");
+			return FALSE;
+		    }
+		} else {
+		    if (     ((type_table[key1] & CONSTANT_POOL_ENTRY_TYPEMASK) 
+			        != CONSTANT_Class)
+			  || ((type_table[key2] != CONSTANT_NameAndType))) {
+			CCerror(cb, "Bad index in constant pool #%d", i);
+			return FALSE;
+		    }
+		}
+		break;
+	    }
+		
+	    case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_NameAndType | CONSTANT_POOL_ENTRY_RESOLVED:
+	        CCerror(cb, "Improperly resolved constant pool #%d", i);
+	        return FALSE;
+
+
+	    case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED:
+		break;
+
+	    case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED:
+	    case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED:
+		if ((i + 1 >= cp_count) || 
+		    (type_table[i + 1] != CONSTANT_POOL_ENTRY_RESOLVED)) {
+		    CCerror(cb, "Improper constant pool long/double #%d", i);
+		    return FALSE;
+		} else {
+		    i++;	
+		    break;	    
+		}
+
+	    case CONSTANT_Integer:
+	    case CONSTANT_Float:
+	    case CONSTANT_Long:
+	    case CONSTANT_Double:
+	    case CONSTANT_Utf8:
+	        CCerror(cb, "Improperly unresolved constant pool #%d", i);
+	        return FALSE;
+
+
+	    default:
+	        CCerror(cb, "Illegal constant pool type at #%d", i);
+	        return FALSE;
+
+
+	}
+    }
+    for (i = 1; i < cp_count; i++) {
+	switch(type = type_table[i]) {
+	    case CONSTANT_Class: {
+		int index = cp[i].i;
+		if (!is_legal_fieldname(cb, cp[index].cp, LegalClass)) 
+		    return FALSE;
+		break;
+	    }
+	      
+	    case CONSTANT_Fieldref:
+	    case CONSTANT_Methodref:
+	    case CONSTANT_InterfaceMethodref: {
+		unsigned index = (unsigned)(cp[i].i);
+		int name_type_index = index & 0xFFFF;
+		int name_type_key = cp[name_type_index].i;
+		int name_index = name_type_key >> 16;
+		int signature_index = name_type_key & 0xFFFF;
+		char *name = cp[name_index].cp;
+		char *signature = cp[signature_index].cp;
+
+		if (type == CONSTANT_Fieldref) {
+		    if (! (is_legal_fieldname(cb, name, LegalField) &&
+			   is_legal_field_signature(cb, name, signature)))
+		        return FALSE;
+		} else {
+		    if (! (is_legal_fieldname(cb, name, LegalMethod) &&
+			   is_legal_method_signature(cb, name, signature)))
+		        return FALSE;
+		}
+		break;
+	    }
+	}
+    }
+    return TRUE;
+}
+	    
+
+/* Return true if the entire second argument consists of a legal fieldname 
+ * (or classname, if the third argument is LegalClass). 
+ */
+
+static bool_t 
+is_legal_fieldname(ClassClass *cb, char *name, int type)
+{
+    bool_t result;
+    if (name[0] == '<') {
+	result = (type == LegalMethod) && 
+	         ((strcmp(name, "<init>") == 0) || 
+		  (strcmp(name, "<clinit>") == 0));
+    } else {
+	char *p;
+	if (type == LegalClass && name[0] == SIGNATURE_ARRAY) {
+	    p = skip_over_field_signature(name, FALSE);
+	} else {
+	    p = skip_over_fieldname(name, type == LegalClass);
+	}
+	result = (p != 0 && p[0] == '\0');
+    }
+    if (!result) {
+	char *thing =    (type == LegalField) ? "Field" 
+	               : (type == LegalMethod) ? "Method" : "Class";
+			 
+	CCerror(cb, "Illegal %s name \"%s\"", thing, name);
+	return FALSE;
+    } else {
+        return TRUE;
+    
+    }
+}
+
+/* Return true if the entire string consists of a legal field signature */
+static bool_t 
+is_legal_field_signature(ClassClass *cb, char *fieldname, char *signature) 
+{
+    char *p = skip_over_field_signature(signature, FALSE);
+    if (p != 0 && p[0] == '\0') {
+	return TRUE;
+    } else {
+	CCerror(cb, "Field \"%s\" has illegal signature \"%s\"", 
+	       fieldname, signature);
+	return FALSE;
+    }
+}
+
+
+static bool_t 
+is_legal_method_signature(ClassClass *cb, char *methodname, char *signature)
+{
+    char *p = signature;
+    char *next_p;
+    /* The first character must be a '(' */
+    if (*p++ == SIGNATURE_FUNC) {
+	/* Skip over however many legal field signatures there are */
+	while ((next_p = skip_over_field_signature(p, FALSE)) != 0) 
+	    p = next_p;
+	/* The first non-signature thing better be a ')' */
+	if (*p++ == SIGNATURE_ENDFUNC) {
+	    if (methodname[0] == '<') {
+		/* All internal methods must return void */
+		if ((p[0] == SIGNATURE_VOID) && (p[1] == '\0'))
+		    return TRUE;
+	    } else {
+		/* Now, we better just have a return value. */
+		next_p =  skip_over_field_signature(p, TRUE);
+		if (next_p && next_p[0] == '\0')
+		    return TRUE;
+	    }
+	}
+    }
+    CCerror(cb, "Method \"%s\" has illegal signature \"%s\"", 
+	   methodname, signature);
+    return FALSE;
+}
+	
+  $$Tables
+
+/*
+ * This code mirrors Character.isJavaIdentifierStart.  It determines whether
+ * the specified character is a legal start of a Java identifier as per JLS.
+ *
+ * The parameter ch is the character to be tested; return 1 if the 
+ * character is a letter, 0 otherwise.
+ */
+#define isJavaIdentifierStart(ch) ($$Lookup(ch) & $$maskIsJavaIdentifierStart)
+
+/*
+ * This code mirrors Character.isJavaIdentifierPart.  It determines whether
+ * the specified character is a legal part of a Java identifier as per JLS.
+ * 
+ * The parameter ch is the character to be tested; return 1 if the
+ * character is a digit, 0 otherwise.
+ */  
+#define isJavaIdentifierPart(ch) ($$Lookup(ch) & $$maskIsJavaIdentifierPart)
+
+/* Take pointer to a string.  Skip over the longest part of the string that
+ * could be taken as a fieldname.  Allow '/' if slash_okay is TRUE.
+ *
+ * Return a pointer to just past the fieldname.  Return NULL if no fieldname
+ * at all was found, or in the case of slash_okay being true, we saw
+ * consecutive slashes (meaning we were looking for a qualified path but
+ * found something that was badly-formed). 
+ */
+static char *
+skip_over_fieldname(char *name, bool_t slash_okay)
+{
+    bool_t first;
+    char *p;
+    unicode last_ch = 0;
+    for (p = name, first = TRUE; ; first = FALSE) {
+	char *old_p = p;
+	unicode ch = next_utf2unicode(&p);
+	if (isJavaIdentifierStart(ch) || (!first && isJavaIdentifierPart(ch)) 
+	      || (slash_okay && ch == '/' && !first)
+	      || ch == '_' || ch == '$') {
+	    if (ch == '/' && last_ch == '/') {
+		return 0;	/* Don't permit consecutive slashes */
+	    } else {
+		last_ch = ch;
+	    }
+	} else {
+	    return first ? 0 : old_p;
+	}
+    }
+}
+
+/* Take pointer to a string.  Skip over the longest part of the string that
+ * could be taken as a field signature.  Allow "void" if void_okay.
+ *
+ * Return a pointer to just past the signature.  Return NULL if no legal
+ * signature is found.
+ */
+
+static char *
+skip_over_field_signature(char *name, bool_t void_okay)
+{
+    for (;;) {
+	switch (name[0]) {
+            case SIGNATURE_VOID:
+		if (!void_okay) return 0;
+		/* FALL THROUGH */
+            case SIGNATURE_BOOLEAN:
+            case SIGNATURE_BYTE:
+            case SIGNATURE_CHAR:
+            case SIGNATURE_SHORT:
+            case SIGNATURE_INT:
+            case SIGNATURE_FLOAT:
+            case SIGNATURE_LONG:
+            case SIGNATURE_DOUBLE:
+		return name + 1;
+
+	    case SIGNATURE_CLASS: {
+		/* Skip over the classname, if one is there. */
+		char *p = skip_over_fieldname(name + 1, TRUE);
+		/* The next character better be a semicolon. */
+		if (p && p[0] == ';') 
+		    return p + 1;
+		return 0;
+	    }
+	    
+	    case SIGNATURE_ARRAY: 
+		/* The rest of what's there better be a legal signature.  */
+		name++;
+		void_okay = FALSE;
+		break;
+
+	    default:
+		return 0;
+	}
+    }
+}
+
+
+static void 
+CCerror (ClassClass *cb, char *format, ...)
+{
+    if (verbose) { 
+	va_list args;
+	jio_fprintf(stderr, "VERIFIER CLASS ERROR %s:\n", cbName(cb));
+	va_start(args, format);
+	    jio_vfprintf(stderr, format, args);        
+	va_end(args);
+	jio_fprintf(stderr, "\n");
+    }
+}
+
+/* For use from outside the file.  Determine if the specified name is legal
+ * UTF name for a classname.
+ *
+ * Note that this routine expects the internal form of qualified classes:
+ * the dots should have been replaced by slashes.
+ */
+bool_t IsLegalClassname(char *name, bool_t allowArrayClass) 
+{ 
+    char *p;
+    if (name[0] == SIGNATURE_ARRAY) {
+	if (!allowArrayClass) {
+	    return FALSE;
+	} else { 
+	    /* Everything that's left better be a field signature */
+	    p = skip_over_field_signature(name, FALSE);
+	}
+    } else {
+	/* skip over the fieldname.  Slashes are okay */
+	p = skip_over_fieldname(name, TRUE);
+    }
+    return (p != 0 && p[0] == '\0');
+}