jdk/make/tools/GenerateCharacter/check_class.c.template
changeset 2 90ce3da70b43
child 1090 c5805b1672a6
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 /* This file was generated AUTOMATICALLY from a template file Wed Jun 17 10:43:47 PDT 1998 */
       
    27 
       
    28 /*-
       
    29  *      code for verifying the date in a ClassClass structure for internal
       
    30  *      consistency.
       
    31  */
       
    32 
       
    33 #include <ctype.h>
       
    34 
       
    35 #include "oobj.h"
       
    36 #include "interpreter.h"
       
    37 #include "bool.h"
       
    38 #include "utf.h"
       
    39 #include "tree.h"
       
    40 #include "sys_api.h"
       
    41 
       
    42 extern bool_t verify_class_codes(ClassClass *cb);
       
    43 
       
    44 static bool_t verify_constant_pool(ClassClass *cb);
       
    45 
       
    46 static bool_t is_legal_fieldname(ClassClass *cb, char *name, int type);
       
    47 static bool_t is_legal_method_signature(ClassClass *cb, char *name, char *signature);
       
    48 static bool_t is_legal_field_signature(ClassClass *cb, char *name, char *signature);
       
    49 
       
    50 static char *skip_over_fieldname(char *name, bool_t slash_okay);
       
    51 static char *skip_over_field_signature(char *name, bool_t void_okay);
       
    52 
       
    53 static void CCerror (ClassClass *cb, char *format, ...);
       
    54 
       
    55 
       
    56 /* Argument for is_legal_fieldname */
       
    57 enum { LegalClass, LegalField, LegalMethod };
       
    58 
       
    59 
       
    60 
       
    61 
       
    62 bool_t
       
    63 VerifyClass(ClassClass *cb)
       
    64 {
       
    65     bool_t result = TRUE;
       
    66     struct methodblock *mb;
       
    67     struct fieldblock *fb;
       
    68     int i;
       
    69     if (CCIs(cb, Verified)) 
       
    70 	return TRUE;
       
    71     if (!verify_constant_pool(cb)) 
       
    72         return FALSE;
       
    73     /* Make sure all the method names and signatures are okay */
       
    74     for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
       
    75 	char *name = mb->fb.name;
       
    76 	char *signature = mb->fb.signature;
       
    77 	if (! (is_legal_fieldname(cb, name, LegalMethod)  &&
       
    78 	       is_legal_method_signature(cb, name, signature)))
       
    79 	    result = FALSE;
       
    80     }
       
    81     /* Make sure all the field names and signatures are okay */
       
    82     for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++) {
       
    83 	if (!  (is_legal_fieldname(cb, fb->name, LegalField) &&
       
    84 		is_legal_field_signature(cb, fb->name, fb->signature))) 
       
    85 	    result = FALSE;
       
    86     }
       
    87     /* Make sure we are not overriding any final methods or classes*/
       
    88     if (cbIsInterface(cb)) { 
       
    89 	struct methodblock *mb;
       
    90 	if ((cbSuperclass(cb) == NULL) ||
       
    91 	    (cbSuperclass(cb) != classJavaLangObject)) { 
       
    92 	    CCerror(cb, "Interface %s has bad superclass", cbName(cb));
       
    93 	    result = FALSE;
       
    94 	}
       
    95 	for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
       
    96 	    if (mb->fb.access & ACC_STATIC) {
       
    97 		if (mb->fb.name[0] != '<') { 
       
    98 		    /* Only internal methods can be static */
       
    99 		    CCerror(cb, "Illegal static method %s in interface %s",
       
   100 			    mb->fb.name, cbName(cb));
       
   101 		    result = FALSE;
       
   102 		}
       
   103 	    }
       
   104 	}
       
   105     } else if (cbSuperclass(cb)) { 
       
   106 	ClassClass *super_cb;
       
   107 	unsigned bitvector_size = (unsigned)(cbMethodTableSize(cb) + 31) >> 5;
       
   108 	long *bitvector = sysCalloc(bitvector_size, sizeof(long));
       
   109 	for (super_cb = cbSuperclass(cb); ; super_cb = cbSuperclass(super_cb)) {
       
   110 	    if (cbAccess(super_cb) & ACC_FINAL) {
       
   111 		CCerror(cb, "Class %s is subclass of final class %s",
       
   112 			cbName(cb), cbName(super_cb));
       
   113 		result = FALSE;
       
   114 	    }
       
   115 	    mb = cbMethods(super_cb);
       
   116 	    for (i = cbMethodsCount(super_cb); --i >= 0; mb++) {
       
   117 		if (mb->fb.access & ACC_FINAL) {
       
   118 		    unsigned offset = mb->fb.u.offset;
       
   119 		    bitvector[offset >> 5] |= (1 << (offset & 0x1F));
       
   120 		}
       
   121 	    }
       
   122 	    if (cbSuperclass(super_cb) == NULL) break;
       
   123 	}
       
   124 	for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
       
   125 	    unsigned offset = mb->fb.u.offset;
       
   126 	    if ((offset > 0) 
       
   127 		   && bitvector[offset >> 5] & (1 << (offset & 0x1F))) {
       
   128 		CCerror(cb, "Class %s overrides final method %s.%s",
       
   129 			cbName(cb), mb->fb.name, mb->fb.signature);
       
   130 		result = FALSE;
       
   131 	    }
       
   132 	}
       
   133 	sysFree(bitvector);
       
   134     } else if (cb != classJavaLangObject) {
       
   135 	CCerror(cb, "Class %s does not have superclass", cbName(cb));
       
   136 	result = FALSE;
       
   137     }
       
   138 	
       
   139     if (result)
       
   140 	result = verify_class_codes(cb);
       
   141     if (result) 
       
   142 	CCSet(cb, Verified);
       
   143     return result;
       
   144 }
       
   145 
       
   146 
       
   147 static bool_t
       
   148 verify_constant_pool(ClassClass *cb)
       
   149 {
       
   150     union cp_item_type *cp = cbConstantPool(cb);
       
   151     long cp_count = cbConstantPoolCount(cb);
       
   152     unsigned char *type_table;
       
   153     int i, type;
       
   154     
       
   155     const int utf8_resolved = (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED);
       
   156 
       
   157     if (cp_count == 0) /* Primitive classes */
       
   158         return TRUE;
       
   159     type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
       
   160     /* Let's make two quick passes over the constant pool. The first one 
       
   161      * checks that everything is of the right type.            */
       
   162     for (i = 1; i < cp_count; i++) {
       
   163 	switch(type = type_table[i]) {
       
   164 	    case CONSTANT_String:
       
   165 	    case CONSTANT_Class: {
       
   166 		int index = cp[i].i;
       
   167 		if (   (index < 1) 
       
   168 		       || (index >= cp_count)
       
   169 		       || (type_table[index] != utf8_resolved)) {
       
   170 		    CCerror(cb, "Bad index in constant pool #%d", i);
       
   171 		    return FALSE;
       
   172 		}
       
   173 		break;
       
   174 	    }
       
   175 		
       
   176 	    case CONSTANT_String | CONSTANT_POOL_ENTRY_RESOLVED:
       
   177 		/* This can only happen if a string is the "initial" value of
       
   178 		 * some final static String.  We assume that the checking has
       
   179 		 * already been done.
       
   180 		 */
       
   181 		break;
       
   182 
       
   183 	    case CONSTANT_Fieldref:
       
   184 	    case CONSTANT_Methodref:
       
   185 	    case CONSTANT_InterfaceMethodref: 
       
   186 	    case CONSTANT_NameAndType: {
       
   187 		unsigned index = (unsigned)(cp[i].i);
       
   188 		int key1 = index >> 16;
       
   189 		int key2 = index & 0xFFFF;
       
   190 		if (key1 < 1 || key1 >= cp_count 
       
   191 		      || key2 < 1 || key2 >= cp_count) {
       
   192 		    CCerror(cb, "Bad index in constant pool #%d", i);
       
   193 		    return FALSE;
       
   194 		}
       
   195 		if (type == CONSTANT_NameAndType) {
       
   196 		    if (   (type_table[key1] != utf8_resolved) 
       
   197 			|| (type_table[key2] != utf8_resolved)) {
       
   198 			CCerror(cb, "Bad index in constant pool.");
       
   199 			return FALSE;
       
   200 		    }
       
   201 		} else {
       
   202 		    if (     ((type_table[key1] & CONSTANT_POOL_ENTRY_TYPEMASK) 
       
   203 			        != CONSTANT_Class)
       
   204 			  || ((type_table[key2] != CONSTANT_NameAndType))) {
       
   205 			CCerror(cb, "Bad index in constant pool #%d", i);
       
   206 			return FALSE;
       
   207 		    }
       
   208 		}
       
   209 		break;
       
   210 	    }
       
   211 		
       
   212 	    case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
       
   213 	    case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
       
   214 	    case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
       
   215 	    case CONSTANT_NameAndType | CONSTANT_POOL_ENTRY_RESOLVED:
       
   216 	        CCerror(cb, "Improperly resolved constant pool #%d", i);
       
   217 	        return FALSE;
       
   218 
       
   219 
       
   220 	    case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED:
       
   221 	    case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED:
       
   222 	    case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED:
       
   223 	    case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED:
       
   224 		break;
       
   225 
       
   226 	    case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED:
       
   227 	    case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED:
       
   228 		if ((i + 1 >= cp_count) || 
       
   229 		    (type_table[i + 1] != CONSTANT_POOL_ENTRY_RESOLVED)) {
       
   230 		    CCerror(cb, "Improper constant pool long/double #%d", i);
       
   231 		    return FALSE;
       
   232 		} else {
       
   233 		    i++;	
       
   234 		    break;	    
       
   235 		}
       
   236 
       
   237 	    case CONSTANT_Integer:
       
   238 	    case CONSTANT_Float:
       
   239 	    case CONSTANT_Long:
       
   240 	    case CONSTANT_Double:
       
   241 	    case CONSTANT_Utf8:
       
   242 	        CCerror(cb, "Improperly unresolved constant pool #%d", i);
       
   243 	        return FALSE;
       
   244 
       
   245 
       
   246 	    default:
       
   247 	        CCerror(cb, "Illegal constant pool type at #%d", i);
       
   248 	        return FALSE;
       
   249 
       
   250 
       
   251 	}
       
   252     }
       
   253     for (i = 1; i < cp_count; i++) {
       
   254 	switch(type = type_table[i]) {
       
   255 	    case CONSTANT_Class: {
       
   256 		int index = cp[i].i;
       
   257 		if (!is_legal_fieldname(cb, cp[index].cp, LegalClass)) 
       
   258 		    return FALSE;
       
   259 		break;
       
   260 	    }
       
   261 	      
       
   262 	    case CONSTANT_Fieldref:
       
   263 	    case CONSTANT_Methodref:
       
   264 	    case CONSTANT_InterfaceMethodref: {
       
   265 		unsigned index = (unsigned)(cp[i].i);
       
   266 		int name_type_index = index & 0xFFFF;
       
   267 		int name_type_key = cp[name_type_index].i;
       
   268 		int name_index = name_type_key >> 16;
       
   269 		int signature_index = name_type_key & 0xFFFF;
       
   270 		char *name = cp[name_index].cp;
       
   271 		char *signature = cp[signature_index].cp;
       
   272 
       
   273 		if (type == CONSTANT_Fieldref) {
       
   274 		    if (! (is_legal_fieldname(cb, name, LegalField) &&
       
   275 			   is_legal_field_signature(cb, name, signature)))
       
   276 		        return FALSE;
       
   277 		} else {
       
   278 		    if (! (is_legal_fieldname(cb, name, LegalMethod) &&
       
   279 			   is_legal_method_signature(cb, name, signature)))
       
   280 		        return FALSE;
       
   281 		}
       
   282 		break;
       
   283 	    }
       
   284 	}
       
   285     }
       
   286     return TRUE;
       
   287 }
       
   288 	    
       
   289 
       
   290 /* Return true if the entire second argument consists of a legal fieldname 
       
   291  * (or classname, if the third argument is LegalClass). 
       
   292  */
       
   293 
       
   294 static bool_t 
       
   295 is_legal_fieldname(ClassClass *cb, char *name, int type)
       
   296 {
       
   297     bool_t result;
       
   298     if (name[0] == '<') {
       
   299 	result = (type == LegalMethod) && 
       
   300 	         ((strcmp(name, "<init>") == 0) || 
       
   301 		  (strcmp(name, "<clinit>") == 0));
       
   302     } else {
       
   303 	char *p;
       
   304 	if (type == LegalClass && name[0] == SIGNATURE_ARRAY) {
       
   305 	    p = skip_over_field_signature(name, FALSE);
       
   306 	} else {
       
   307 	    p = skip_over_fieldname(name, type == LegalClass);
       
   308 	}
       
   309 	result = (p != 0 && p[0] == '\0');
       
   310     }
       
   311     if (!result) {
       
   312 	char *thing =    (type == LegalField) ? "Field" 
       
   313 	               : (type == LegalMethod) ? "Method" : "Class";
       
   314 			 
       
   315 	CCerror(cb, "Illegal %s name \"%s\"", thing, name);
       
   316 	return FALSE;
       
   317     } else {
       
   318         return TRUE;
       
   319     
       
   320     }
       
   321 }
       
   322 
       
   323 /* Return true if the entire string consists of a legal field signature */
       
   324 static bool_t 
       
   325 is_legal_field_signature(ClassClass *cb, char *fieldname, char *signature) 
       
   326 {
       
   327     char *p = skip_over_field_signature(signature, FALSE);
       
   328     if (p != 0 && p[0] == '\0') {
       
   329 	return TRUE;
       
   330     } else {
       
   331 	CCerror(cb, "Field \"%s\" has illegal signature \"%s\"", 
       
   332 	       fieldname, signature);
       
   333 	return FALSE;
       
   334     }
       
   335 }
       
   336 
       
   337 
       
   338 static bool_t 
       
   339 is_legal_method_signature(ClassClass *cb, char *methodname, char *signature)
       
   340 {
       
   341     char *p = signature;
       
   342     char *next_p;
       
   343     /* The first character must be a '(' */
       
   344     if (*p++ == SIGNATURE_FUNC) {
       
   345 	/* Skip over however many legal field signatures there are */
       
   346 	while ((next_p = skip_over_field_signature(p, FALSE)) != 0) 
       
   347 	    p = next_p;
       
   348 	/* The first non-signature thing better be a ')' */
       
   349 	if (*p++ == SIGNATURE_ENDFUNC) {
       
   350 	    if (methodname[0] == '<') {
       
   351 		/* All internal methods must return void */
       
   352 		if ((p[0] == SIGNATURE_VOID) && (p[1] == '\0'))
       
   353 		    return TRUE;
       
   354 	    } else {
       
   355 		/* Now, we better just have a return value. */
       
   356 		next_p =  skip_over_field_signature(p, TRUE);
       
   357 		if (next_p && next_p[0] == '\0')
       
   358 		    return TRUE;
       
   359 	    }
       
   360 	}
       
   361     }
       
   362     CCerror(cb, "Method \"%s\" has illegal signature \"%s\"", 
       
   363 	   methodname, signature);
       
   364     return FALSE;
       
   365 }
       
   366 	
       
   367   $$Tables
       
   368 
       
   369 /*
       
   370  * This code mirrors Character.isJavaIdentifierStart.  It determines whether
       
   371  * the specified character is a legal start of a Java identifier as per JLS.
       
   372  *
       
   373  * The parameter ch is the character to be tested; return 1 if the 
       
   374  * character is a letter, 0 otherwise.
       
   375  */
       
   376 #define isJavaIdentifierStart(ch) ($$Lookup(ch) & $$maskIsJavaIdentifierStart)
       
   377 
       
   378 /*
       
   379  * This code mirrors Character.isJavaIdentifierPart.  It determines whether
       
   380  * the specified character is a legal part of a Java identifier as per JLS.
       
   381  * 
       
   382  * The parameter ch is the character to be tested; return 1 if the
       
   383  * character is a digit, 0 otherwise.
       
   384  */  
       
   385 #define isJavaIdentifierPart(ch) ($$Lookup(ch) & $$maskIsJavaIdentifierPart)
       
   386 
       
   387 /* Take pointer to a string.  Skip over the longest part of the string that
       
   388  * could be taken as a fieldname.  Allow '/' if slash_okay is TRUE.
       
   389  *
       
   390  * Return a pointer to just past the fieldname.  Return NULL if no fieldname
       
   391  * at all was found, or in the case of slash_okay being true, we saw
       
   392  * consecutive slashes (meaning we were looking for a qualified path but
       
   393  * found something that was badly-formed). 
       
   394  */
       
   395 static char *
       
   396 skip_over_fieldname(char *name, bool_t slash_okay)
       
   397 {
       
   398     bool_t first;
       
   399     char *p;
       
   400     unicode last_ch = 0;
       
   401     for (p = name, first = TRUE; ; first = FALSE) {
       
   402 	char *old_p = p;
       
   403 	unicode ch = next_utf2unicode(&p);
       
   404 	if (isJavaIdentifierStart(ch) || (!first && isJavaIdentifierPart(ch)) 
       
   405 	      || (slash_okay && ch == '/' && !first)
       
   406 	      || ch == '_' || ch == '$') {
       
   407 	    if (ch == '/' && last_ch == '/') {
       
   408 		return 0;	/* Don't permit consecutive slashes */
       
   409 	    } else {
       
   410 		last_ch = ch;
       
   411 	    }
       
   412 	} else {
       
   413 	    return first ? 0 : old_p;
       
   414 	}
       
   415     }
       
   416 }
       
   417 
       
   418 /* Take pointer to a string.  Skip over the longest part of the string that
       
   419  * could be taken as a field signature.  Allow "void" if void_okay.
       
   420  *
       
   421  * Return a pointer to just past the signature.  Return NULL if no legal
       
   422  * signature is found.
       
   423  */
       
   424 
       
   425 static char *
       
   426 skip_over_field_signature(char *name, bool_t void_okay)
       
   427 {
       
   428     for (;;) {
       
   429 	switch (name[0]) {
       
   430             case SIGNATURE_VOID:
       
   431 		if (!void_okay) return 0;
       
   432 		/* FALL THROUGH */
       
   433             case SIGNATURE_BOOLEAN:
       
   434             case SIGNATURE_BYTE:
       
   435             case SIGNATURE_CHAR:
       
   436             case SIGNATURE_SHORT:
       
   437             case SIGNATURE_INT:
       
   438             case SIGNATURE_FLOAT:
       
   439             case SIGNATURE_LONG:
       
   440             case SIGNATURE_DOUBLE:
       
   441 		return name + 1;
       
   442 
       
   443 	    case SIGNATURE_CLASS: {
       
   444 		/* Skip over the classname, if one is there. */
       
   445 		char *p = skip_over_fieldname(name + 1, TRUE);
       
   446 		/* The next character better be a semicolon. */
       
   447 		if (p && p[0] == ';') 
       
   448 		    return p + 1;
       
   449 		return 0;
       
   450 	    }
       
   451 	    
       
   452 	    case SIGNATURE_ARRAY: 
       
   453 		/* The rest of what's there better be a legal signature.  */
       
   454 		name++;
       
   455 		void_okay = FALSE;
       
   456 		break;
       
   457 
       
   458 	    default:
       
   459 		return 0;
       
   460 	}
       
   461     }
       
   462 }
       
   463 
       
   464 
       
   465 static void 
       
   466 CCerror (ClassClass *cb, char *format, ...)
       
   467 {
       
   468     if (verbose) { 
       
   469 	va_list args;
       
   470 	jio_fprintf(stderr, "VERIFIER CLASS ERROR %s:\n", cbName(cb));
       
   471 	va_start(args, format);
       
   472 	    jio_vfprintf(stderr, format, args);        
       
   473 	va_end(args);
       
   474 	jio_fprintf(stderr, "\n");
       
   475     }
       
   476 }
       
   477 
       
   478 /* For use from outside the file.  Determine if the specified name is legal
       
   479  * UTF name for a classname.
       
   480  *
       
   481  * Note that this routine expects the internal form of qualified classes:
       
   482  * the dots should have been replaced by slashes.
       
   483  */
       
   484 bool_t IsLegalClassname(char *name, bool_t allowArrayClass) 
       
   485 { 
       
   486     char *p;
       
   487     if (name[0] == SIGNATURE_ARRAY) {
       
   488 	if (!allowArrayClass) {
       
   489 	    return FALSE;
       
   490 	} else { 
       
   491 	    /* Everything that's left better be a field signature */
       
   492 	    p = skip_over_field_signature(name, FALSE);
       
   493 	}
       
   494     } else {
       
   495 	/* skip over the fieldname.  Slashes are okay */
       
   496 	p = skip_over_fieldname(name, TRUE);
       
   497     }
       
   498     return (p != 0 && p[0] == '\0');
       
   499 }