1 /* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
2 /****************************** tables.c ***************************************
4 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
6 See file COPYRIGHT for information on usage and disclaimer of warranties
8 Enth"alt Supportfunktionen f"ur:
9 - Lesen von JavaClass-Files
12 - zus"atzliche Support-Funktionen
14 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
15 Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
16 Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
18 Last Change: 1998/03/24
20 *******************************************************************************/
30 #include "threads/thread.h" /* schani */
31 #include "threads/locks.h"
34 bool runverbose = false;
36 int count_unicode_len = 0;
39 /******************************************************************************
40 ************************* Der Dateien-Sauger **********************************
41 *******************************************************************************
43 dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen,
44 einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
46 ******************************************************************************/
48 static FILE *classfile = NULL; /* File-handle der gerade gelesenen Datei */
49 static char *classpath = ""; /* Suchpfad f"ur die ClassFiles */
53 /************************** Funktion: suck_init ******************************
55 Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
58 ******************************************************************************/
60 void suck_init (char *cpath)
67 /************************** Funktion: suck_start ******************************
69 "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
70 Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
71 bis eine entsprechende Datei ( <classname>.class) gefunden wird.
73 ******************************************************************************/
75 bool suck_start (unicode *classname)
77 #define MAXFILENAME 1000 /* Maximale Langes des Dateinamens plus Pfad */
79 char filename[MAXFILENAME+10]; /* Platz fuer '.class' */
88 while ( *pathpos == ':' ) pathpos++;
91 while ( (*pathpos) && (*pathpos!=':') ) {
92 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
94 filename[filenamelen++] = *(pathpos++);
97 filename[filenamelen++] = '/';
99 for (i=0; i < classname -> length; i++) {
100 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
102 c = classname -> text [i];
103 if (c=='/') c = '/'; /* Slashes im Namen passen zu UNIX */
105 if ( c<=' ' || c>'z') {
110 filename[filenamelen++] = c;
113 strcpy (filename+filenamelen, ".class");
115 classfile = fopen(filename, "r");
123 sprintf (logtext,"Can not open class file '%s'", filename);
129 /************************** Funktion: suck_stop *******************************
131 Schlie"st die offene Datei wieder.
133 ******************************************************************************/
140 while ( fread (&dummy, 1,1, classfile) > 0) rest++;
142 sprintf (logtext,"There are %d access bytes at end of classfile",
153 /************************** Lesefunktionen ***********************************
155 Lesen von der Datei in verschieden grossen Paketen
156 (8,16,32,64-bit Integer oder Float)
158 *****************************************************************************/
160 void suck_nbytes (u1 *buffer, u4 len)
162 if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
166 void skip_nbytes (u4 len)
169 for (i=0; i<len; i++) suck_u1 ();
176 if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
183 if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
191 if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
192 return (b[0]<<8) + b[1];
205 if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
206 v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
222 return (hi<<32) + lo;
244 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
245 memcpy ( (u1*) (&f), buffer, 4);
247 suck_nbytes ( (u1*) (&f), 4 );
250 PANICIF (sizeof(float) != 4, "Incompatible float-format");
256 double suck_double ()
263 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
264 memcpy ( (u1*) (&d), buffer, 8);
266 suck_nbytes ( (u1*) (&d), 8 );
269 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
277 /******************************************************************************
278 ******************** Der Unicode-Symbol-Verwalter *****************************
279 *******************************************************************************
281 legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
282 das Eintragen neuer Symbole
284 ******************************************************************************/
288 #define UNICODESTART 2187 /* Startgr"osse: moeglichst gross und prim */
290 static u4 unicodeentries; /* Anzahl der Eintr"age in der Tabelle */
291 static u4 unicodehashsize; /* Gr"osse der Tabelle */
292 static unicode ** unicodehash; /* Zeiger auf die Tabelle selbst */
295 /*********************** Funktion: unicode_init ******************************
297 Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
300 *****************************************************************************/
307 count_unicode_len += sizeof(unicode*) * unicodehashsize;
311 unicodehashsize = UNICODESTART;
312 unicodehash = MNEW (unicode*, unicodehashsize);
313 for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
317 /*********************** Funktion: unicode_close *****************************
319 Gibt allen Speicher der Symboltabellen frei.
320 Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist,
321 Stringkonstanten (die mit 'unicode_setstringlink'
322 Unicode-Symbole gebunden wurden) wieder freizugeben
324 *****************************************************************************/
326 void unicode_close (stringdeleter del)
331 for (i=0; i<unicodehashsize; i++) {
334 unicode *nextu = u->hashlink;
336 if (u->string) del (u->string);
338 MFREE (u->text, u2, u->length);
343 MFREE (unicodehash, unicode*, unicodehashsize);
347 /********************* Funktion: unicode_display ******************************
349 Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
351 ******************************************************************************/
353 void unicode_display (unicode *u)
356 for (i=0; i < u->length; i++) {
358 if (c>=32 && c<=127) printf ("%c",c);
365 /********************* Funktion: unicode_sprint ******************************
367 Schreibt ein unicode-Symbol in einen C-String
369 ******************************************************************************/
371 void unicode_sprint (char *buffer, unicode *u)
374 for (i=0; i < u->length; i++) buffer[i] = u->text[i];
379 /********************* Funktion: unicode_fprint ******************************
381 Schreibt ein unicode-Symbol auf eine Datei aus
383 ******************************************************************************/
385 void unicode_fprint (FILE *file, unicode *u)
388 for (i=0; i < u->length; i++) putc (u->text[i], file);
392 /****************** interne Funktion: u_hashkey ******************************/
394 static u4 u_hashkey (u2 *text, u2 length)
399 for (i=0; i<length; i++) {
400 k ^= ( ((u4) (text[i])) << sh );
408 /*************** interne Funktion: u_reorganizehash **************************/
410 static void u_reorganizehash ()
415 u4 newhashsize = unicodehashsize*2;
416 unicode **newhash = MNEW (unicode*, newhashsize);
419 count_unicode_len += sizeof(unicode*) * unicodehashsize;
422 for (i=0; i<newhashsize; i++) newhash[i] = NULL;
424 for (i=0; i<unicodehashsize; i++) {
427 unicode *nextu = u -> hashlink;
428 u4 slot = (u->key) % newhashsize;
430 u->hashlink = newhash[slot];
437 MFREE (unicodehash, unicode*, unicodehashsize);
438 unicodehash = newhash;
439 unicodehashsize = newhashsize;
443 /****************** Funktion: unicode_new_u2 **********************************
445 Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
446 Funktion als u2-Array "ubergeben
448 ******************************************************************************/
450 unicode *unicode_new_u2 (u2 *text, u2 length)
452 u4 key = u_hashkey (text, length);
453 u4 slot = key % unicodehashsize;
454 unicode *u = unicodehash[slot];
459 if (u->length == length) {
460 for (i=0; i<length; i++) {
461 if (text[i] != u->text[i]) goto nomatch;
471 count_unicode_len += sizeof(unicode) + 2 * length;
477 u->text = MNEW (u2, length);
480 u->hashlink = unicodehash[slot];
481 unicodehash[slot] = u;
482 for (i=0; i<length; i++) u->text[i] = text[i];
486 if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
492 /********************* Funktion: unicode_new_char *****************************
494 Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
495 Funktion als C-String ( = char* ) "ubergeben
497 ******************************************************************************/
499 unicode *unicode_new_char (char *text)
501 #define MAXNEWCHAR 500
502 u2 buffer[MAXNEWCHAR];
506 while ( (c = *text) != '\0' ) {
507 if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
508 buffer[length++] = c;
511 return unicode_new_u2 (buffer, length);
515 /********************** Funktion: unicode_setclasslink ************************
517 H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
519 ******************************************************************************/
521 void unicode_setclasslink (unicode *u, classinfo *class)
523 PANICIF (u->class, "Attempt to attach class to already attached symbol");
527 /********************** Funktion: unicode_getclasslink ************************
529 Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
530 Wenn keine solche Klasse existiert, dann wird ein Fehler
533 ******************************************************************************/
535 classinfo *unicode_getclasslink (unicode *u)
537 PANICIF (!u->class, "Attempt to get unknown class-reference");
543 /********************* Funktion: unicode_unlinkclass *************************
545 Entfernt den Verweis auf eine Klasse wieder von einem Symbol
547 ******************************************************************************/
549 void unicode_unlinkclass (unicode *u)
551 PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
557 /******************* Funktion> unicode_setstringlink *********************
559 H"angt einen Verweis auf einen konstanten String an ein
562 *************************************************************************/
564 void unicode_setstringlink (unicode *u, java_objectheader *str)
566 PANICIF (u->string, "Attempt to attach string to already attached symbol");
571 /********************* Funktion: unicode_unlinkstring *************************
573 Entfernt den Verweis auf einen String wieder von einem Symbol
575 ******************************************************************************/
577 void unicode_unlinkstring (unicode *u)
579 PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
585 /*********************** Funktion: unicode_show ******************************
587 gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
588 (nur f"ur Debug-Zwecke)
590 *****************************************************************************/
597 printf ("UNICODE-HASH: %d slots for %d entries\n",
598 (int) unicodehashsize, (int) unicodeentries );
600 for (i=0; i<unicodehashsize; i++) {
603 printf ("SLOT %d: ", (int) i);
608 if (u->string) printf ("(string) ");
619 /******************************************************************************
620 *********************** Diverse Support-Funktionen ****************************
621 ******************************************************************************/
624 /******************** Funktion: desc_to_type **********************************
626 Findet zu einem gegebenen Typdescriptor den entsprechenden
629 ******************************************************************************/
631 u2 desc_to_type (unicode *descriptor)
633 if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
635 switch (descriptor->text[0]) {
640 case 'Z': return TYPE_INT;
641 case 'D': return TYPE_DOUBLE;
642 case 'F': return TYPE_FLOAT;
643 case 'J': return TYPE_LONG;
645 case '[': return TYPE_ADDRESS;
648 sprintf (logtext, "Invalid Type-Descriptor: ");
649 unicode_sprint (logtext+strlen(logtext), descriptor);
655 /********************** Funktion: desc_typesize *******************************
657 Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
658 der durch den Typdescriptor gegeben ist.
660 ******************************************************************************/
662 u2 desc_typesize (unicode *descriptor)
664 switch (desc_to_type(descriptor)) {
665 case TYPE_INT: return 4;
666 case TYPE_LONG: return 8;
667 case TYPE_FLOAT: return 4;
668 case TYPE_DOUBLE: return 8;
669 case TYPE_ADDRESS: return sizeof(voidptr);