DEADSOFTWARE

Patched for Linux
[mp3cc.git] / MPC.3.5.LINUX / preverifier / util.c
1 /*
2 * @(#)util.c 1.7 02/09/27
3 *
4 * Copyright 1995-1999 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
16 /*=========================================================================
17 * SYSTEM: Verifier
18 * SUBSYSTEM: Utility functions.
19 * FILE: util.c
20 * OVERVIEW: Utility routines needed by both the compiler and the interpreter.
21 *
22 * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
23 * Edited by Tasneem Sayeed, Sun Microsystems
24 *=======================================================================*/
26 /*=========================================================================
27 * Include files
28 *=======================================================================*/
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <stddef.h>
35 #include "oobj.h"
36 #include "utf.h"
37 #include "sys_api.h"
38 #include "path.h" /* DIR_SEPARATOR */
40 /*=========================================================================
41 * Globals and extern declarations
42 *=======================================================================*/
44 extern struct StrIDhash *nameTypeHash;
45 extern struct StrIDhash *stringHash;
47 unicode *
48 str2unicode(char *str, unicode *ustr, long len)
49 {
50 unicode *dst = ustr;
52 memset((char *) dst, 0, len * sizeof(*dst));
53 while (*str && --len >= 0)
54 *ustr++ = 0xff & *str++;
55 return dst;
56 }
58 void
59 unicode2str(unicode *src, char *dst, long len)
60 {
61 while (--len >= 0)
62 *dst++ = (char)(*src++);
63 *dst = '\0';
64 }
67 int
68 jio_printf (const char *format, ...)
69 {
70 int len;
72 va_list args;
73 va_start(args, format);
74 len = jio_vfprintf(stdout, format, args);
75 va_end(args);
77 return len;
78 }
80 int
81 jio_fprintf (FILE *handle, const char *format, ...)
82 {
83 int len;
85 va_list args;
86 va_start(args, format);
87 len = jio_vfprintf(handle, format, args);
88 va_end(args);
90 return len;
91 }
93 int
94 jio_vfprintf (FILE *handle, const char *format, va_list args)
95 {
96 return vfprintf(handle, format, args);
97 }
100 /*
101 * Print s null terminated C-style character string.
102 */
103 void
104 prints(char *s)
106 jio_fprintf(stdout, "%s", s);
109 #undef HTSIZE /* Avoid conflict on PC */
110 #define HTSIZE 2003 /* Default size -- must be prime */
111 #define HTOVERFLOWPOINT(h) (h->size * 4 / 5)
113 /*
114 * We store most of the result of the hash in hash_bits to quickly
115 * reject impossible matches because strcmp() is fairly expensive,
116 * especially when many strings will have common prefixes.
117 */
118 typedef struct {
119 char *hash; /* the string for this entry */
120 unsigned is_malloced : 1; /* 1 if hash was malloced */
121 unsigned hash_bits : 31; /* low 31 bits of the hash */
122 } StrIDhashSlot;
124 typedef void (*hash_fn)(const char *s, unsigned *h1, unsigned *h2);
126 typedef struct StrIDhash {
127 int size; /* number of entries */
128 hash_fn hash; /* hash function for this table */
129 struct StrIDhash *next; /* next bucket */
130 short used; /* number of full entries */
131 short baseid; /* ID for item in slot[0] */
132 void **params; /* param table, if needed */
133 StrIDhashSlot slot[1]; /* expanded to be number of slots */
134 } StrIDhash;
136 /* Hash a string into a primary and secondary hash value */
137 static void
138 default_hash(const char *s, unsigned *h1, unsigned *h2)
140 int i;
141 unsigned raw_hash;
142 for (raw_hash = 0; (i = *s) != '\0'; ++s)
144 raw_hash = raw_hash * 37 + i;
145 *h1 = raw_hash;
146 *h2 = (raw_hash & 7) + 1; /* between 1 and 8 */
149 /* Create a hash table of the specified size */
150 static StrIDhash *
151 createHash(int entries)
153 StrIDhash *h;
154 int size = offsetof(struct StrIDhash, slot) + (entries * sizeof(h->slot));
155 h = (StrIDhash *)sysCalloc(1, size);
156 if (h != NULL) {
157 h->size = entries;
158 h->hash = default_hash; /* only custom tables get something else */
159 h->next = NULL;
161 return h;
164 /*
165 * Given a string, return a unique 16 bit id number.
166 * If param isn't null, we also set up an array of void * for holding info
167 * about each object. The address of this void * is stored into param
168 * If CopyNeeded is true, then the name argument "s" must be dup'ed, since
169 * the current item is allocated on the stack.
171 * Note about returning 0 in the case of out of memory errors: 0 is *not*
172 * a valid ID! The out of memory error should be thrown by the calling code.
173 */
174 unsigned short
175 Str2ID(StrIDhash **hash_ptr, register char *s, void ***param,
176 int CopyNeeded)
178 /*
179 * The database is a hash table. When the hash table overflows, a new
180 * hashtable is created chained onto the previous one. This is done so
181 * that we can use the hashtable slot index as the ID, without worrying
182 * about having the IDs change when the hashtable grows.
183 */
184 StrIDhash *h = *hash_ptr;
185 long i;
186 unsigned primary_hash;
187 unsigned secondary_hash;
188 unsigned hash_bits;
189 hash_fn current_hash_func = NULL;
191 if (h == NULL)
192 goto not_found;
194 /* Create the hash values */
195 current_hash_func = h->hash;
196 current_hash_func(s, &primary_hash, &secondary_hash);
197 hash_bits = primary_hash & ((1u << 31) - 1);
199 for (;;) {
200 char *s2;
201 int bucketSize = h->size;
203 /* See if the new hash table has a different hash function */
204 if (h->hash != current_hash_func) {
205 current_hash_func = h->hash;
206 current_hash_func(s, &primary_hash, &secondary_hash);
207 hash_bits = primary_hash & ((1u << 31) - 1);
209 i = primary_hash % bucketSize;
211 while ((s2 = h->slot[i].hash) != NULL) {
212 if (h->slot[i].hash_bits == hash_bits && strcmp(s2, s) == 0)
213 goto found_it;
214 if ((i -= secondary_hash) < 0)
215 i += bucketSize;
217 /* Not found in this table. Try the next table. */
218 if (h->next == NULL)
219 break;
220 h = h->next;
223 not_found:
224 /* Either the hash table is empty, or the item isn't yet found. */
225 if (h == NULL || (h->used >= HTOVERFLOWPOINT(h))) {
226 /* Need to create a new bucket */
227 StrIDhash *next;
228 if (h && h->baseid > 30000 && *hash_ptr != stringHash) {
229 panic("16-bit string hash table overflow");
231 next = createHash(HTSIZE);
232 if (next == NULL) {
233 /* Calling code should signal OutOfMemoryError */
234 return 0;
236 if (h == NULL) {
237 /* Create a new table */
238 *hash_ptr = h = next;
239 h->baseid = 1; /* guarantee that no ID is 0 */
240 } else {
241 next->baseid = h->baseid + h->size;
242 h->next = next;
243 h = next;
245 if (h->hash != current_hash_func) {
246 current_hash_func = h->hash;
247 current_hash_func(s, &primary_hash, &secondary_hash);
248 hash_bits = primary_hash & ((1u << 31) - 1);
250 i = primary_hash % h->size;
252 if (CopyNeeded) {
253 char *d = strdup(s);
254 if (d == NULL) {
255 /* Calling code should signal OutOfMemoryError */
256 return 0;
258 s = d;
259 h->slot[i].is_malloced = 1;
260 }
261 h->slot[i].hash = s;
262 h->slot[i].hash_bits = hash_bits;
263 h->used++;
265 found_it:
266 /* We have found or created slot "i" in hash bucket "h" */
267 if (param != NULL) {
268 if (h->params == NULL) {
269 h->params = sysCalloc(h->size, sizeof(void *));
270 if (h->params == NULL) {
271 /* Calling code should signal OutOfMemoryError */
272 return 0;
275 *param = &(h->params[i]);
277 return (unsigned short)(h->baseid + i);
280 /* Free an StrIDhash table and all the entries in it */
281 void Str2IDFree(StrIDhash **hash_ptr)
283 StrIDhash *hash = *hash_ptr;
285 while (hash != NULL) {
286 StrIDhash *next = hash->next;
287 StrIDhashSlot *ptr, *endPtr;
288 for (ptr = &hash->slot[0], endPtr = ptr + hash->size;
289 ptr < endPtr; ptr++) {
290 if (ptr->is_malloced)
291 sysFree(ptr->hash);
293 if (hash->params != NULL)
294 sysFree(hash->params);
295 sysFree(hash);
296 hash = next;
298 *hash_ptr = 0;
301 /*
302 * Call the callback function on every entry in the table. This
303 * should only be invoked holding the string hash table lock.
304 */
305 void Str2IDCallback(StrIDhash **hash_ptr, void (*callback)(char *, void *))
307 StrIDhash *hash, *next;
308 int i;
310 hash = *hash_ptr;
311 while (hash) {
312 void **params = hash->params;
313 next = hash->next;
314 for (i = 0; i < hash->size; i++) {
315 if (hash->slot[i].hash != 0) {
316 callback(hash->slot[i].hash, params ? params[i] : NULL);
319 hash = next;
323 /*
324 * Returns NULL in the case of an error.
325 */
326 char *
327 ID2Str(StrIDhash *h, unsigned short ID, void ***param)
329 int entry;
331 while ((long)(ID - h->baseid) >= h->size) {
332 h = h->next;
334 entry = ID - h->baseid;
335 if (param != NULL) {
336 if (h->params == NULL) {
337 h->params = (void **)sysCalloc(h->size, sizeof(*param));
338 if (h->params == NULL) {
339 /* Calling code should signal OutOfMemoryError */
340 return NULL;
343 *param = &h->params[entry];
344 }
345 return h->slot[entry].hash;
348 char *
349 addstr(char *s, char *buf, char *limit, char term)
351 char c;
352 while ((c = *s) && c != term && buf < limit) {
353 *buf++ = c;
354 s++;
356 return buf;
359 char *
360 unicode2rd(unicode *s, long len)
361 { /* unicode string to readable C string */
362 #define CSTRLEN 40
363 static char buf[CSTRLEN+1];
364 char *dp = buf;
365 int c;
366 if (s == 0)
367 return "NULL";
368 *dp++ = '"';
369 while (--len>=0 && (c = *s++) != 0 && dp < buf + sizeof buf - 10)
370 if (040 <= c && c < 0177)
371 *dp++ = c;
372 else
373 switch (c) {
374 case '\n':
375 *dp++ = '\\';
376 *dp++ = 'n';
377 break;
378 case '\t':
379 *dp++ = '\\';
380 *dp++ = 't';
381 break;
382 case '\r':
383 *dp++ = '\\';
384 *dp++ = 'r';
385 break;
386 case '\b':
387 *dp++ = '\\';
388 *dp++ = 'b';
389 break;
390 case '\f':
391 *dp++ = '\\';
392 *dp++ = 'f';
393 break;
394 default:
395 /* Should not be possible to overflow, truncate if so */
396 (void) jio_snprintf(dp, CSTRLEN+1 - (dp - buf), "\\%X", c);
397 dp += strlen(dp);
398 break;
400 *dp++ = '"';
401 if (len >= 0 && c != 0)
402 *dp++ = '.', *dp++ = '.', *dp++ = '.';
403 *dp++ = 0;
404 return buf;
407 /*
408 * WARNING: out_of_memory() aborts the runtime! It should not be used
409 * except in the case of out of memory situations that are clearly not
410 * survivable, like running out of memory before the runtime is initialized.
411 * If the runtime has finished initializing and you run out of memory, you
412 * should throw an OutOfMemoryError instead.
413 */
414 void
415 out_of_memory()
417 jio_fprintf(stderr, "**Out of memory, exiting**\n");
418 exit(1);
421 void
422 panic(const char *format, ...)
424 va_list ap;
425 char buf[256];
427 printCurrentClassName();
428 va_start(ap, format);
430 /* If buffer overflow, quietly truncate */
431 (void) jio_vsnprintf(buf, sizeof(buf), format, ap);
433 jio_fprintf(stdout, "\nERROR: %s\n", buf);
435 exit(1);
438 char *
439 classname2string(char *src, char *dst, int size) {
440 char *buf = dst;
441 for (; (--size > 0) && (*src != '\0') ; src++, dst++) {
442 if (*src == '/') {
443 *dst = '.';
444 } else {
445 *dst = *src;
448 *dst = '\0';
449 return buf;
452 typedef struct InstanceData {
453 char *buffer;
454 char *end;
455 } InstanceData;
457 #define ERROR_RETVAL -1
458 #undef SUCCESS
459 #define SUCCESS 0
460 #undef CheckRet
461 #define CheckRet(x) { if ((x) == ERROR_RETVAL) return ERROR_RETVAL; }
463 static int
464 put_char(InstanceData *this, int c)
466 if (iscntrl(0xff & c) && c != '\n' && c != '\t') {
467 c = '@' + (c & 0x1F);
468 if (this->buffer >= this->end) {
469 return ERROR_RETVAL;
471 *this->buffer++ = '^';
473 if (this->buffer >= this->end) {
474 return ERROR_RETVAL;
476 *this->buffer++ = c;
477 return SUCCESS;
480 static int
481 format_string(InstanceData *this, char *str, int left_justify, int min_width,
482 int precision)
484 int pad_length;
485 char *p;
487 if (str == 0) {
488 return ERROR_RETVAL;
491 if ((int)strlen(str) < precision) {
492 pad_length = min_width - strlen(str);
493 } else {
494 pad_length = min_width - precision;
496 if (pad_length < 0)
497 pad_length = 0;
498 if (left_justify) {
499 while (pad_length > 0) {
500 CheckRet(put_char(this, ' '));
501 --pad_length;
505 for (p = str; *p != '\0' && --precision >= 0; p++) {
506 CheckRet(put_char(this, *p));
509 if (!left_justify) {
510 while (pad_length > 0) {
511 CheckRet(put_char(this, ' '));
512 --pad_length;
515 return SUCCESS;
518 #define MAX_DIGITS 32
520 static int
521 format_number(InstanceData *this, long value, int format_type, int left_justify,
522 int min_width, int precision, bool_t zero_pad)
524 int sign_value = 0;
525 unsigned long uvalue;
526 char convert[MAX_DIGITS+1];
527 int place = 0;
528 int pad_length = 0;
529 static char digits[] = "0123456789abcdef";
530 int base = 0;
531 bool_t caps = FALSE;
532 bool_t add_sign = FALSE;
534 switch (format_type) {
535 case 'o': case 'O':
536 base = 8;
537 break;
538 case 'd': case 'D':
539 add_sign = TRUE; /* fall through */
540 case 'u': case 'U':
541 base = 10;
542 break;
543 case 'X':
544 caps = TRUE; /* fall through */
545 case 'x':
546 base = 16;
547 break;
549 sysAssert(base > 0 && base <= 16);
551 uvalue = value;
552 if (add_sign) {
553 if (value < 0) {
554 sign_value = '-';
555 uvalue = -value;
559 do {
560 convert[place] = digits[uvalue % (unsigned)base];
561 if (caps) {
562 convert[place] = toupper(convert[place]);
564 place++;
565 uvalue = (uvalue / (unsigned)base);
566 if (place > MAX_DIGITS) {
567 return ERROR_RETVAL;
569 } while(uvalue);
570 convert[place] = 0;
572 pad_length = min_width - place;
573 if (pad_length < 0) {
574 pad_length = 0;
576 if (left_justify) {
577 if (zero_pad && pad_length > 0) {
578 if (sign_value) {
579 CheckRet(put_char(this, sign_value));
580 --pad_length;
581 sign_value = 0;
583 while (pad_length > 0) {
584 CheckRet(put_char(this, '0'));
585 --pad_length;
587 } else {
588 while (pad_length > 0) {
589 CheckRet(put_char(this, ' '));
590 --pad_length;
594 if (sign_value) {
595 CheckRet(put_char(this, sign_value));
598 while (place > 0 && --precision >= 0) {
599 CheckRet(put_char(this, convert[--place]));
602 if (!left_justify) {
603 while (pad_length > 0) {
604 CheckRet(put_char(this, ' '));
605 --pad_length;
608 return SUCCESS;
611 int
612 jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
614 char *strvalue;
615 long value;
616 InstanceData this;
617 bool_t left_justify, zero_pad, long_flag, add_sign, fPrecision;
618 int min_width, precision, ch;
620 if (str == NULL) {
621 return ERROR_RETVAL;
623 str[0] = '\0';
625 this.buffer = str;
626 this.end = str + count - 1;
627 *this.end = '\0'; /* ensure null-termination in case of failure */
629 while ((ch = *fmt++) != 0) {
630 if (ch == '%') {
631 zero_pad = long_flag = add_sign = fPrecision = FALSE;
632 left_justify = TRUE;
633 min_width = 0;
634 precision = this.end - this.buffer;
635 next_char:
636 ch = *fmt++;
637 switch (ch) {
638 case 0:
639 return ERROR_RETVAL;
640 case '-':
641 left_justify = FALSE;
642 goto next_char;
643 case '0': /* set zero padding if min_width not set */
644 if (min_width == 0)
645 zero_pad = TRUE;
646 case '1': case '2': case '3':
647 case '4': case '5': case '6':
648 case '7': case '8': case '9':
649 if (fPrecision == TRUE) {
650 precision = precision * 10 + (ch - '0');
651 } else {
652 min_width = min_width * 10 + (ch - '0');
654 goto next_char;
655 case '.':
656 fPrecision = TRUE;
657 precision = 0;
658 goto next_char;
659 case 'l':
660 long_flag = TRUE;
661 goto next_char;
662 case 's':
663 strvalue = va_arg(args, char *);
664 CheckRet(format_string(&this, strvalue, left_justify,
665 min_width, precision));
666 break;
667 case 'c':
668 ch = va_arg(args, int);
669 CheckRet(put_char(&this, ch));
670 break;
671 case '%':
672 CheckRet(put_char(&this, '%'));
673 break;
674 case 'd': case 'D':
675 case 'u': case 'U':
676 case 'o': case 'O':
677 case 'x': case 'X':
678 value = long_flag ? va_arg(args, long) : va_arg(args, int);
679 CheckRet(format_number(&this, value, ch, left_justify,
680 min_width, precision, zero_pad));
681 break;
682 default:
683 return ERROR_RETVAL;
685 } else {
686 CheckRet(put_char(&this, ch));
689 *this.buffer = '\0';
690 return strlen(str);
693 int
694 jio_snprintf(char *str, size_t count, const char *fmt, ...)
696 va_list args;
697 int len;
699 va_start(args, fmt);
700 len = jio_vsnprintf(str, count, fmt, args);
701 va_end(args);
702 return len;
705 /* Return true if the two classes are in the same class package */
707 bool_t
708 IsSameClassPackage(ClassClass *class1, ClassClass *class2)
710 if (cbLoader(class1) != cbLoader(class2))
711 return FALSE;
712 else {
713 char *name1 = cbName(class1);
714 char *name2 = cbName(class2);
715 char *last_slash1 = strrchr(name1, DIR_SEPARATOR);
716 char *last_slash2 = strrchr(name2, DIR_SEPARATOR);
717 if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
718 /* One of the two doesn't have a package. Only return true
719 * if the other one also doesn't have a package. */
720 return (last_slash1 == last_slash2);
721 } else {
722 int length1, length2;
723 if (*name1 == SIGNATURE_ARRAY) {
724 do name1++; while (*name1 == SIGNATURE_ARRAY);
725 if (*name1 != SIGNATURE_CLASS) {
726 /* Something is terribly wrong. Shouldn't be here */
727 return FALSE;
729 name1++;
731 if (*name2 == SIGNATURE_ARRAY) {
732 do name2++; while (*name2 == SIGNATURE_ARRAY);
733 if (*name2 != SIGNATURE_CLASS) {
734 /* Something is terribly wrong. Shouldn't be here */
735 return FALSE;
737 name2++;
739 length1 = last_slash1 - name1;
740 length2 = last_slash2 - name2;
741 return ((length1 == length2)
742 && (strncmp(name1, name2, length1) == 0));