+/************* functions for reading classdata ********************************
+
+ getting classdata in blocks of variable size
+ (8,16,32,64-bit integer or float)
+
+*******************************************************************************/
+
+static char *classpath = ""; /* searchpath for classfiles */
+static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
+static u1 *classbuf_pos; /* current position in classfile buffer */
+static int classbuffer_size; /* size of classfile-data */
+
+/* transfer block of classfile data into a buffer */
+#define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len);classbuf_pos+=len;
+
+/* skip block of classfile data */
+#define skip_nbytes(len) classbuf_pos += len;
+
+#define suck_u1() (*++classbuf_pos)
+#define suck_s8() (s8) suck_u8()
+#define suck_s2() (s2) suck_u2()
+#define suck_s4() (s4) suck_u4()
+#define suck_s1() (s1) suck_u1()
+#define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
+#define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
+
+/* get u8 from classfile data */
+static u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+ u8 lo,hi;
+ hi = suck_u4();
+ lo = suck_u4();
+ return (hi<<32) + lo;
+#else
+ u8 v;
+ v.high = suck_u4();
+ v.low = suck_u4();
+ return v;
+#endif
+}
+
+/* get float from classfile data */
+static float suck_float ()
+{
+ float f;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[4];
+ u2 i;
+ for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+ memcpy ( (u1*) (&f), buffer, 4);
+#else
+ suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+ PANICIF (sizeof(float) != 4, "Incompatible float-format");
+
+ return f;
+}
+
+/* get double from classfile data */
+static double suck_double ()
+{
+ double d;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[8];
+ u2 i;
+ for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+ memcpy ( (u1*) (&d), buffer, 8);
+#else
+ suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+ PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+
+ return d;
+}
+
+/************************** function: suck_init ******************************
+
+ called once at startup, sets the searchpath for the classfiles
+
+******************************************************************************/
+
+void suck_init (char *cpath)
+{
+ classpath = cpath;
+ classbuffer = NULL;
+}
+
+
+/************************** function: suck_start ******************************
+
+ open file for the specified class and the read classfile data,
+ all directory of the searchpath are used to find the classfile
+ ( <classname>.class)
+
+******************************************************************************/
+
+
+bool suck_start (utf *classname)
+{
+#define MAXFILENAME 1000 /* maximum length of a filename */
+
+ char filename[MAXFILENAME+10]; /* room for '.class' */
+ char *pathpos; /* position in searchpath */
+ FILE *classfile;
+ u2 filenamelen;
+ u2 c;
+
+ if (classbuffer) /* classbuffer already valid */
+ return true;
+
+ pathpos = classpath;
+
+ while (*pathpos) {
+ /* pointer to the next utf8-character */
+ char *utf_ptr = classname->text;
+
+ /* skip path separator */
+ while ( *pathpos == ':' ) pathpos++;
+
+ /* extract directory from searchpath */
+ filenamelen=0;
+ while ( (*pathpos) && (*pathpos!=':') ) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+
+ filename[filenamelen++] = *(pathpos++);
+ }
+
+ filename[filenamelen++] = '/';
+
+ /* add classname to filename */
+ while (utf_ptr<utf_end(classname)) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+
+ c = *utf_ptr++;
+ if (c=='/') c = '/';
+ else {
+ if ( c<=' ' || c>'z') {
+ /* invalid character */
+ c = '?';
+ }
+ }
+
+ filename[filenamelen++] = c;
+ }
+
+ /* add suffix */
+ strcpy (filename+filenamelen, ".class");
+
+ classfile = fopen(filename, "r");
+ if (classfile) {
+ /* file exists */
+ struct stat buffer;
+ int err;
+
+ /* determine size of classfile */
+ err = stat (filename, &buffer);
+
+ if (!err) {
+ /* read classfile data */
+ classbuffer_size = buffer.st_size;
+ classbuffer = MNEW(u1,classbuffer_size);
+ classbuf_pos = classbuffer-1;
+ fread(classbuffer, 1, classbuffer_size, classfile);
+ fclose(classfile);
+ return true;
+ }
+ }
+ }
+
+ sprintf (logtext,"Can not open class file '%s'", filename);
+ error();
+
+ return false;
+}
+
+
+/************************** function: suck_stop *******************************
+
+ free memory for buffer with classfile data
+
+******************************************************************************/
+
+void suck_stop ()
+{
+ /* determine number of bytes of classdata not retrieved by suck-operations */
+ int classdata_left = (classbuffer+classbuffer_size)-classbuf_pos-1;
+
+ if (classdata_left>0) {
+ /* surplus */
+ sprintf (logtext,"There are %d access bytes at end of classfile",
+ classdata_left);
+ dolog();
+ }