author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sat, 1 Nov 2014 14:18:19 +0000 (17:18 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Sat, 1 Nov 2014 14:18:19 +0000 (17:18 +0300) |
88 files changed:
diff --git a/LICENSE.txt b/LICENSE.txt
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,17 @@
+\r
+\r
+ MIDletPascal compiler\r
+ Copyright (C) 2009-2013 MIDletPascal project\r
+\r
+ This program is free software: you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation, either version 3 of the License, or\r
+ (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program. If not, see <http://www.gnu.org/licenses/>.\r
diff --git a/MPC.3.5.LINUX/Linux/mp3CC b/MPC.3.5.LINUX/Linux/mp3CC
new file mode 100644 (file)
index 0000000..de8ba17
Binary files /dev/null and b/MPC.3.5.LINUX/Linux/mp3CC differ
index 0000000..de8ba17
Binary files /dev/null and b/MPC.3.5.LINUX/Linux/mp3CC differ
diff --git a/MPC.3.5.LINUX/classgen/bytecode.c b/MPC.3.5.LINUX/classgen/bytecode.c
--- /dev/null
@@ -0,0 +1,145 @@
+/********************************************************************
+
+ bytecode.c - funcions for creating the bytecode
+
+ Niksa Orlic, 2004-06-11
+
+********************************************************************/
+
+#include "bytecode.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "../util/memory.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+//#include "../main/static_entry.h"
+
+extern int linenum;
+
+//extern FILE* yyin;
+//extern int fileSize;
+
+/*
+ Allocate a new bytecode
+*/
+bytecode *bytecode_create()
+{
+ bytecode *new_bytecode = (bytecode*) mem_alloc(sizeof(bytecode));
+
+ if (new_bytecode == NULL)
+ die(1);
+
+ new_bytecode->bytecode_allocated_size = 0;
+ new_bytecode->bytecode_pos = 0;
+
+ return new_bytecode;
+}
+
+/*
+ Destroy the bytecode
+*/
+void bytecode_destroy(bytecode *code)
+{
+ if (code->bytecode_allocated_size > 0)
+ mem_free(code->bytecode);
+
+ mem_free(code);
+}
+
+bytecode *bytecode_duplicate(bytecode *code)
+{
+ bytecode *new_bytecode = bytecode_create();
+ bytecode_append_bytecode(new_bytecode, code);
+
+ return new_bytecode;
+}
+
+
+/*
+ Appends a single byte to the bytecode
+*/
+void bytecode_append(bytecode *code, char c)
+{
+ //if (c == swap$)
+ //{
+ // int a = 1;
+ //}
+ if (code->bytecode_pos == code->bytecode_allocated_size)
+ {
+ if (code->bytecode_allocated_size == 0)
+ code->bytecode = (char*) mem_alloc(128);
+ else
+ code->bytecode = (char*) mem_realloc(code->bytecode,
+ code->bytecode_allocated_size + 128);
+
+ if (code->bytecode == NULL)
+ die(1);
+
+ code->bytecode_allocated_size += 128;
+ }
+
+ code->bytecode[code->bytecode_pos] = c;
+ code->bytecode_pos ++;
+}
+
+/*
+ Append one bytecode to another.
+*/
+void bytecode_append_bytecode(bytecode *dest, bytecode *src)
+{
+ if (src->bytecode_pos == 0)
+ return;
+
+ if (dest->bytecode_allocated_size == 0)
+ {
+ dest->bytecode_allocated_size += src->bytecode_pos;
+ dest->bytecode = (char*) mem_alloc(dest->bytecode_allocated_size);
+ }
+ else
+ {
+ dest->bytecode_allocated_size += src->bytecode_pos;
+ dest->bytecode = (char*) mem_realloc(dest->bytecode, dest->bytecode_allocated_size);
+ }
+
+ if (dest->bytecode == NULL)
+ die(1);
+
+ memcpy(dest->bytecode + dest->bytecode_pos, src->bytecode, src->bytecode_pos);
+ dest->bytecode_pos += src->bytecode_pos;
+}
+
+/*
+ Appends a short int to the bytecode
+*/
+void bytecode_append_short_int(bytecode *code, short int s)
+{
+ char ch;
+
+ ch = (char) (s >> 8);
+ bytecode_append(code, ch);
+
+ ch = (char) s;
+ bytecode_append(code, ch);
+}
+
+/*
+ Appends a long int to the bytecode
+*/
+void bytecode_append_long_int(bytecode *code, long int l)
+{
+ char ch;
+
+ ch = (char) (l >> 24);
+ bytecode_append(code, ch);
+
+ ch = (char) (l >> 16);
+ bytecode_append(code, ch);
+
+ ch = (char) (l >> 8);
+ bytecode_append(code, ch);
+
+ ch = (char) l;
+ bytecode_append(code, ch);
+}
diff --git a/MPC.3.5.LINUX/classgen/bytecode.h b/MPC.3.5.LINUX/classgen/bytecode.h
--- /dev/null
@@ -0,0 +1,235 @@
+/********************************************************************
+
+ bytecode.h - methods for handling the bytecode
+
+ Niksa Orlic, 2004-05-22
+
+********************************************************************/
+
+struct bytecode_struct
+{
+ int bytecode_pos;
+ int bytecode_allocated_size;
+ char *bytecode;
+};
+
+typedef struct bytecode_struct bytecode;
+
+bytecode *bytecode_create();
+void bytecode_destroy(bytecode *code);
+bytecode *bytecode_duplicate(bytecode*);
+
+void bytecode_append(bytecode *code, char c);
+void bytecode_append_short_int(bytecode *code, short int s);
+void bytecode_append_long_int(bytecode *code, long int l);
+void bytecode_append_bytecode(bytecode *dest, bytecode *src);
+
+/* Java bytecode mnemonics defines */
+enum Java_mnemonics
+{
+ nop$ = 0x00,
+ aconst_null$,
+ iconst_m1$,
+ iconst_0$,
+ iconst_1$,
+ iconst_2$,
+ iconst_3$,
+ iconst_4$,
+ iconst_5$,
+ lconst_0$,
+ lconst_1$,
+ fconst_0$,
+ fconst_1$,
+ fconst_2$,
+ dconst_0$,
+ dconst_1$,
+ bipush$,
+ sipush$,
+ ldc$,
+ ldc_w$,
+ ldc2_w$,
+ iload$,
+ lload$,
+ fload$,
+ dload$,
+ aload$,
+ iload_0$,
+ iload_1$,
+ iload_2$,
+ iload_3$,
+ lload_0$,
+ lload_1$,
+ lload_2$,
+ lload_3$,
+ fload_0$,
+ fload_1$,
+ fload_2$,
+ fload_3$,
+ dload_0$,
+ dload_1$,
+ dload_2$,
+ dload_3$,
+ aload_0$,
+ aload_1$,
+ aload_2$,
+ aload_3$,
+ iaload$,
+ laload$,
+ faload$,
+ daload$,
+ aaload$,
+ baload$,
+ caload$,
+ saload$,
+ istore$,
+ lstore$,
+ fstore$,
+ dstore$,
+ astore$,
+ istore_0$,
+ istore_1$,
+ istore_2$,
+ istore_3$,
+ lstore_0$,
+ lstore_1$,
+ lstore_2$,
+ lstore_3$,
+ fstore_0$,
+ fstore_1$,
+ fstore_2$,
+ fstore_3$,
+ dstore_0$,
+ dstore_1$,
+ dstore_2$,
+ dstore_3$,
+ astore_0$,
+ astore_1$,
+ astore_2$,
+ astore_3$,
+ iastore$,
+ lastore$,
+ fastore$,
+ dastore$,
+ aastore$,
+ bastore$,
+ castore$,
+ sastore$,
+ pop$,
+ pop2$,
+ dup$,
+ dup_x1$,
+ dup_x2$,
+ dup2$,
+ dup2_x1$,
+ dup2_x2$,
+ swap$,
+ iadd$,
+ ladd$,
+ fadd$,
+ dadd$,
+ isub$,
+ lsub$,
+ fsub$,
+ dsub$,
+ imul$,
+ lmul$,
+ fmul$,
+ dmul$,
+ idiv$,
+ ldiv$,
+ fdiv$,
+ ddiv$,
+ irem$,
+ lrem$,
+ frem$,
+ drem$,
+ ineg$,
+ lneg$,
+ fneg$,
+ dneg$,
+ ishl$,
+ lshl$,
+ ishr$,
+ lshr$,
+ iushr$,
+ lushr$,
+ iand$,
+ land$,
+ ior$,
+ lor$,
+ ixor$,
+ lxor$,
+ iinc$,
+ i2l$,
+ i2f$,
+ i2d$,
+ l2i$,
+ l2f$,
+ l2d$,
+ f2i$,
+ f2l$,
+ f2d$,
+ d2i$,
+ d2l$,
+ d2f$,
+ i2b$,
+ i2c$,
+ i2s$,
+ lcmp$,
+ fcmpl$,
+ fcmpg$,
+ dcmpl$,
+ dcmpg$,
+ ifeq$,
+ ifne$,
+ iflt$,
+ ifge$,
+ ifgt$,
+ ifle$,
+ if_icmpeq$,
+ if_icmpne$,
+ if_icmplt$,
+ if_icmpge$,
+ if_icmpgt$,
+ if_icmple$,
+ if_acmpeq$,
+ if_acmpne$,
+ goto$,
+ jsr$,
+ ret$,
+ tableswitch$,
+ lookupswitch$,
+ ireturn$,
+ lreturn$,
+ freturn$,
+ dreturn$,
+ areturn$,
+ return$,
+ getstatic$,
+ putstatic$,
+ getfield$,
+ putfield$,
+ invokevirtual$,
+ invokespecial$,
+ invokestatic$,
+ invokeinterface$,
+ xxxunusedxxx1$,
+ new$,
+ newarray$,
+ anewarray$,
+ arraylength$,
+ athrow$,
+ checkcast$,
+ instanceof$,
+ monitorenter$,
+ monitorexit$,
+ wide$,
+ multianewarray$,
+ ifnull$,
+ ifnonnull$,
+ goto_w$,
+ jsr_w$,
+
+ break_stmt$ = 250 /* used internally by the parser to mark break statment positions */
+};
+
diff --git a/MPC.3.5.LINUX/classgen/classgen.c b/MPC.3.5.LINUX/classgen/classgen.c
--- /dev/null
@@ -0,0 +1,645 @@
+/********************************************************************
+
+ classgen.c - methods for creating the .class binary file
+
+ Niksa Orlic, 2004-05-16
+
+********************************************************************/
+
+//#include "../util/message.h"
+#include "../util/error.h"
+#include "../util/strings.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+#include "../classgen/constant_pool.h"
+#include "../classgen/preverify.h"
+#include "../util/memory.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "classgen.h"
+
+extern char* output_path;
+extern int linenum;
+
+extern int detect_units_only;
+
+extern constant_pool *constants;
+extern int constant_pool_size;
+
+//extern int usesFloat;
+extern int mathType;
+
+char class_name[16];
+
+/*
+ Creates a class file for pascal record.
+*/
+void create_record_class(type *record)
+{
+ char class_file_name[16];
+ char *output_file_name;
+ char copy_sig[64];
+
+ FILE *record_file;
+
+ bytecode *init_method;
+ bytecode *copy_method;
+
+ /* save the previous constant pool state */
+ constant_pool *global_cp;
+ int global_cp_count;
+
+ global_cp = constants;
+ global_cp_count = constant_pool_size;
+
+ constants = NULL;
+ constant_pool_size = 0;
+
+ /* check for consistency */
+ if (record->type_class != record_type)
+ die(12);
+
+ sprintf(class_name, "R_%d", record->unique_record_ID);
+ sprintf(class_file_name, "%s.class", class_name);
+
+ if (!detect_units_only)
+ requires(3, class_file_name);
+
+ output_file_name = (char*) mem_alloc(strlen(output_path) +
+ strlen(class_file_name) + 5);
+ if (output_file_name == NULL)
+ die (1);
+
+ #ifdef WIN32
+ sprintf(output_file_name, "%s\\%s", output_path, class_file_name);
+ #endif
+ #ifdef UNIX
+ sprintf(output_file_name, "%s/%s", output_path, class_file_name);
+ #endif
+ record_file = fopen(output_file_name, "wb");
+ mem_free(output_file_name);
+
+ if (record_file == NULL)
+ die(3);
+
+ /* write the class file header */
+ create_class_file_header(record_file);
+
+ /* add some stuff into the constant pool */
+ cp_add_class(class_name);
+ cp_add_class("java/lang/Object");
+ cp_add_utf8("<init>");
+ cp_add_utf8("()V");
+ cp_add_utf8("Code");
+ cp_add_utf8("Copy");
+ sprintf(copy_sig, "(LR_%d;)LR_%d;", record->unique_record_ID, record->unique_record_ID);
+ cp_add_utf8(copy_sig);
+
+ create_record_fields(record);
+
+ /* create the bytecode for the init method */
+ init_method = bytecode_create();
+ create_init_method(record, init_method);
+
+ /* create the bytecode for the copy method */
+ copy_method = bytecode_create();
+ create_copy_method(record, copy_method);
+
+ /* write the constant pool into the file */
+ write_constant_pool(record_file);
+
+ /* write the access flags, set to ACC_PUBLIC and ACC_SUPER */
+ write_short_int(record_file, 0x0021);
+
+ /* write the index to constat pool with this class description */
+ write_short_int(record_file, cp_add_class(class_name));
+
+ /* write the index to constant pool with the super class description */
+ write_short_int(record_file, cp_add_class("java/lang/Object"));
+
+ /* we have no interfaces */
+ write_short_int(record_file, 0);
+
+ /* write the fields */
+ write_short_int(record_file, (short) type_list_length(record->elements_type_list));
+ write_record_fields(record_file, record);
+
+ /* we have <init> and Copy method */
+ write_short_int(record_file, 2);
+
+ /* write the init method */
+ write_init_method(record_file, init_method);
+
+ /* write the copy method */
+ write_copy_method(record, record_file, copy_method);
+
+ /* we have no attributes */
+ write_short_int(record_file, 0);
+
+ fclose(record_file);
+
+
+ /* restore the constant pool */
+ constants = global_cp;
+ constant_pool_size = global_cp_count;
+}
+
+
+/*
+ Writes a class file header into the output file
+*/
+void create_class_file_header(FILE *class_file)
+{
+ char magic[4] = { (char)0xCA, (char)0xFE, (char)0xBA, (char)0xBE };
+
+ fwrite(magic, 1, 4, class_file);
+
+ /* Write the minor version number 3 */
+ write_short_int(class_file, 0x0003);
+
+ /* Wrte the major version number 45 */
+ write_short_int(class_file, 0x002d);
+}
+
+
+/*
+ Creates entries into constant pool with names and types of
+ the elements of the structure.
+*/
+void create_record_fields(type *record)
+{
+ string_list *names;
+ type_list *types;
+ char descriptor[128];
+
+ names = record->elements_name_list;
+ types = record->elements_type_list;
+
+ while (names != NULL)
+ {
+ if (names->data != NULL)
+ {
+ lowercase(names->data->cstr);
+ get_field_descriptor(types->data, descriptor);
+ cp_add_nameandtype(names->data->cstr, descriptor);
+ }
+
+ names = names->next;
+ types = types->next;
+ }
+}
+
+
+/*
+ Writes the fields from the record into the
+ class file.
+*/
+void write_record_fields(FILE *class_file, type *record)
+{
+ string_list *names;
+ type_list *types;
+ char descriptor[128];
+ int field_num = 0;
+
+ names = record->elements_name_list;
+ types = record->elements_type_list;
+
+ while (names != NULL)
+ {
+ if (names->data != NULL)
+ {
+ /* write the access flags: ACC_PUBLIC */
+ write_short_int(class_file, 0x0001);
+
+ /* write the name index */
+ lowercase(names->data->cstr);
+ write_short_int(class_file, cp_add_utf8(names->data->cstr));
+
+ /* write the descriptor index */
+ get_field_descriptor(types->data, descriptor);
+ write_short_int(class_file, cp_add_utf8(descriptor));
+
+ /* we have no attributes */
+ write_short_int(class_file, 0);
+ }
+
+ names = names->next;
+ types = types->next;
+ field_num ++;
+ }
+}
+
+
+/*
+ Writes a short int in bigendian format. If
+ class_file is NULL, does nothing.
+*/
+void write_short_int(FILE *class_file, short int num)
+{
+ char ch;
+
+ if (class_file == NULL)
+ return;
+
+ ch = (char) (num >> 8);
+ fwrite(&ch, 1, 1, class_file);
+
+ ch = (char) num;
+ fwrite(&ch, 1, 1, class_file);
+}
+
+void write_long_int(FILE *class_file, long int num)
+{
+ char ch;
+
+ if (class_file == NULL)
+ return;
+
+ ch = (char) (num >> 24);
+ fwrite(&ch, 1, 1, class_file);
+
+ ch = (char) (num >> 16);
+ fwrite(&ch, 1, 1, class_file);
+
+ ch = (char) (num >> 8);
+ fwrite(&ch, 1, 1, class_file);
+
+ ch = (char) num;
+ fwrite(&ch, 1, 1, class_file);
+
+}
+
+short int read_short_int(FILE *class_file)
+{
+ short int return_value = 0;
+
+ return_value = fgetc(class_file) << 8;
+ return_value |= (fgetc(class_file) & 0x00FF);
+
+ return return_value;
+}
+
+long int read_long_int(FILE *class_file)
+{
+ long int return_value = 0;
+
+ return_value = fgetc(class_file) << 24;
+ return_value |= (fgetc(class_file) & 0x00FF) << 16;
+ return_value |= (fgetc(class_file) & 0x00FF) << 8;
+ return_value |= (fgetc(class_file) & 0x00FF);
+
+ return return_value;
+}
+
+/*
+ Construct a valid Java field descriptor for a given type.
+*/
+void get_field_descriptor(type *field_type, char *descriptor)
+{
+ switch (field_type->type_class)
+ {
+ case void_type:
+ sprintf(descriptor, "V");
+ break;
+
+ case integer_type:
+ case char_type:
+ case boolean_type:
+ sprintf(descriptor, "I");
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ sprintf(descriptor, "I");
+ else
+ sprintf(descriptor, "LReal;");
+ break;
+
+ case string_type:
+ sprintf(descriptor, "Ljava/lang/String;");
+ break;
+
+ case command_type:
+ sprintf(descriptor, "Ljavax/microedition/lcdui/Command;");
+ break;
+
+ case stream_type:
+ sprintf(descriptor, "Ljava/io/InputStream;");
+ break;
+
+ case record_store_type:
+ sprintf(descriptor, "Ljavax/microedition/rms/RecordStore;");
+ break;
+
+ case http_type:
+ sprintf(descriptor, "LH;");
+ break;
+
+ case alert_type:
+ sprintf(descriptor, "Ljavax/microedition/lcdui/AlertType;");
+ break;
+
+ case image_type:
+ sprintf(descriptor, "Ljavax/microedition/lcdui/Image;");
+ break;
+
+ case array_type:
+ {
+ char element_type[128];
+ int i, len;
+
+ get_field_descriptor(field_type->element_type, element_type);
+
+ len = type_list_length(field_type->dimensions_list);
+ for(i=0; i < len; i++)
+ {
+ descriptor[i] = '[';
+ }
+
+ descriptor[len] = '\0';
+
+ sprintf(descriptor + len, "%s", element_type);
+ }
+ break;
+
+ case record_type:
+ sprintf(descriptor, "LR_%d;", field_type->unique_record_ID);
+
+ break;
+
+ case error_type:
+ break;
+
+ default:
+ die(13);
+ }
+}
+
+/*
+ Creates the <init> method for records.
+*/
+void create_init_method(type *record, bytecode *code)
+{
+ type_list *type_it;
+ string_list *name_it;
+ int counter = 0;
+
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+ type_it = record->elements_type_list;
+ name_it = record->elements_name_list;
+
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/Object", "<init>", "()V"));
+
+
+ while (type_it != NULL)
+ {
+ if ((type_it->data != NULL) && (name_it->data != NULL))
+ {
+ block *code_wrapper;
+ identifier *type_wrapper;
+
+ code_wrapper = block_create(NULL, string_create());
+ code_wrapper->code = code;
+
+ type_wrapper = identifier_create();
+ type_wrapper->identifier_class = variable_name;
+ type_wrapper->variable_type = type_it->data;
+ type_wrapper->belongs_to_program_block = 1;
+
+ /* put 'this' to the stack */
+ bytecode_append(code, aload_0$);
+
+ /* create the code to initialize the variable */
+ initialize_variable(code_wrapper, type_wrapper, name_it->data->cstr, 0, class_name);
+
+ if (type_it->data->type_class == array_type)
+ add_error_message(446, name_it->data->cstr, "");
+
+ code_wrapper->code = bytecode_create();
+ block_destroy(code_wrapper);
+
+ type_wrapper->variable_type = type_create();
+ identifier_destroy(type_wrapper);
+ }
+
+ type_it = type_it->next;
+ if (name_it != NULL)
+ name_it = name_it->next;
+
+ counter ++;
+ }
+
+ bytecode_append(code, return$);
+}
+
+/*
+ Creates the Copy method for records.
+*/
+void create_copy_method(type *record, bytecode *code)
+{
+ char type_name[64];
+
+ type_list *type_it;
+ string_list *name_it;
+ int counter = 0;
+
+ if (code == NULL)
+ die(1);
+
+ sprintf(type_name, "R_%d", record->unique_record_ID);
+
+ /* create the code */
+ type_it = record->elements_type_list;
+ name_it = record->elements_name_list;
+
+ while (type_it != NULL)
+ {
+ if ((type_it->data != NULL) && (name_it->data != NULL))
+ {
+ lowercase(name_it->data->cstr);
+
+ if (type_it->data->type_class == record_type)
+ {
+ char copy_sig[64];
+ char type_descriptor[128];
+ get_field_descriptor(type_it->data, type_descriptor);
+
+ sprintf(copy_sig, "(LR_%d;)LR_%d;", record->unique_record_ID, record->unique_record_ID);
+
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, getfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, type_descriptor));
+
+ bytecode_append(code, aload_1$);
+ bytecode_append(code, getfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, type_descriptor));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref(type_name, "Copy", copy_sig));
+
+ }
+ else if (type_it->data->type_class == string_type)
+ {
+ bytecode_append(code, aload_0$);
+
+ bytecode_append(code, aload_1$);
+ bytecode_append(code, getfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, "Ljava/lang/String;"));
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("java/lang/String"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/String", "<init>", "(Ljava/lang/String;)V"));
+
+ bytecode_append(code, putfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, "Ljava/lang/String;"));
+ }
+ else if ((type_it->data->type_class == real_type) && (mathType != 1))
+ {
+ bytecode_append(code, aload_0$);
+
+ bytecode_append(code, aload_1$);
+ bytecode_append(code, getfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, "LReal;"));
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, putfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, "LReal;"));
+
+ }
+ else
+ {
+ char type_descriptor[128];
+ get_field_descriptor(type_it->data, type_descriptor);
+
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, aload_1$);
+
+ bytecode_append(code, getfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, type_descriptor));
+
+ bytecode_append(code, putfield$);
+ bytecode_append_short_int(code, cp_add_fieldref(type_name, name_it->data->cstr, type_descriptor));
+ }
+ }
+
+ type_it = type_it->next;
+ if (name_it != NULL)
+ name_it = name_it->next;
+
+ counter ++;
+ }
+
+ // return this
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, areturn$);
+}
+
+
+/*
+ Writes the <init> method to the file.
+*/
+void write_init_method(FILE *fp, bytecode *code)
+{
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name '<init>' */
+ write_short_int(fp, cp_add_utf8("<init>"));
+
+ /* write method descriptor '()V' */
+ write_short_int(fp, cp_add_utf8("()V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute 'Code' */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 10);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+}
+
+/*
+ Writes the Copy method to the file.
+*/
+void write_copy_method(type* record, FILE *fp, bytecode *code)
+{
+ char method_sig[64];
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name '<init>' */
+ write_short_int(fp, cp_add_utf8("Copy"));
+
+ /* write method descriptor (record)record */
+ sprintf(method_sig, "(LR_%d;)LR_%d;", record->unique_record_ID, record->unique_record_ID);
+ write_short_int(fp, cp_add_utf8(method_sig));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute 'Code' */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 10);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+}
diff --git a/MPC.3.5.LINUX/classgen/classgen.h b/MPC.3.5.LINUX/classgen/classgen.h
--- /dev/null
@@ -0,0 +1,31 @@
+/********************************************************************
+
+ classgen.h - methods for creating the .class binary file
+
+ Niksa Orlic, 2004-05-16
+
+********************************************************************/
+
+
+void create_record_class(type *record_type);
+
+void create_class_file_header(FILE *class_file);
+void write_record_constant_pool(FILE *class_file, type *record);
+void create_record_fields(type *record);
+void write_record_fields(FILE *class_file, type *record);
+void write_constant_pool_class(FILE *class_file, char *class_name);
+void write_constant_pool_utf8(FILE *class_file, char *string);
+void write_constant_pool_fieldref(FILE *class_file, int type_index, int name_index);
+void write_constant_pool_methodref(FILE *class_file, int, int, int);
+void get_field_descriptor(type *field_type, char *descriptor);
+void write_short_int(FILE *class_file, short int num);
+void write_long_int(FILE *class_file, long int num);
+
+short int read_short_int(FILE *class_file);
+long int read_long_int(FILE *class_file);
+
+void create_init_method(type *record, bytecode*);
+void write_init_method(FILE *class_file, bytecode*);
+void create_copy_method(type *record, bytecode*);
+void write_copy_method(type* record, FILE *class_file, bytecode*);
+void initialize_record_variable(bytecode *code, type *variable_type, int fieldref_index, int index);
diff --git a/MPC.3.5.LINUX/classgen/constant_pool.c b/MPC.3.5.LINUX/classgen/constant_pool.c
--- /dev/null
@@ -0,0 +1,449 @@
+/********************************************************************
+
+ constant_pool.c - methods for handling constant pool
+
+ Niksa Orlic, 2004-06-11
+
+********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "constant_pool.h"
+//#include "../util/message.h"
+#include "../util/error.h"
+#include "../util/strings.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+#include "../util/memory.h"
+
+#include "classgen.h"
+
+constant_pool *constants;
+int constant_pool_size = 0;
+
+/*
+ Insert a utf8 string into the constant pool table and return its index in the table.
+*/
+int cp_add_utf8(char *str)
+{
+ int i, j, len;
+ int size = 0;
+ constant_pool *entry;
+
+ /* check if the string already exists in the table */
+ for (i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 1)
+ && (strcmp(constants[i].data, str) == 0))
+ {
+ return i+1; /* the indexes for the constant pool are in range 1..N (not zero based) */
+ }
+ }
+
+ /* create a new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 1;
+
+ /* calculate the needeed size for the string */
+ len = strlen(str);
+ for (i=0; i<len; i++)
+ {
+ /* if ((unsigned char)str[i] > 127)
+ size += 2;
+ else*/
+ size ++;
+ }
+
+ entry->data = (char*) mem_alloc(size + 1);
+ entry->data_len = size;
+
+ if (entry->data == NULL)
+ die(1);
+
+ for(i=0, j=0; i<len; i++)
+ {
+ /* if ((unsigned char)str[i] <= 127)
+ {*/
+ entry->data[j] = str[i];
+ j++;
+ /* }
+ else
+ {
+ entry->data[j] = (char)0xC2 | (str[i]>>7)&0x01;
+ j++;
+ entry->data[j] = (str[i] & 0x3F) | 0x80;
+ j++;
+ }*/
+ }
+
+ entry->data[j] = '\0';
+
+ return constant_pool_size;
+}
+
+/*
+ Add a string entry into the constant pool.
+*/
+int cp_add_string(char *str)
+{
+ int i;
+ constant_pool *entry;
+
+ /* first add the utf8 constant */
+ int utf8_const = cp_add_utf8(str);
+
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 8)
+ && (constants[i].param1 == utf8_const))
+ {
+ return i+1;
+ }
+ }
+
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 8;
+ entry->param1 = utf8_const;
+
+ return constant_pool_size;
+}
+
+/*
+ Add an integer into the constant pool.
+*/
+int cp_add_integer(int data)
+{
+ int i;
+ constant_pool *entry;
+
+ /* check if the string already exists in the table */
+ for (i=0; i<constant_pool_size; i++)
+ {
+ if (constants[i].tag == 3)
+ {
+ int *p_value;
+ p_value = (int*)(constants[i].data);
+ if(*p_value == data)
+ return i+1; /* the indexes for the constant pool are in range 1..N (not zero based) */
+ }
+ }
+
+ /* create a new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 3;
+ entry->data = (char*) mem_alloc(sizeof(int));
+
+ if (entry->data == NULL)
+ die(1);
+
+ *((int*)(entry->data)) = data;
+
+ return constant_pool_size;
+}
+
+/*
+ Add a long constant into the constant pool
+*/
+int cp_add_long(long data)
+{
+ die(18);
+
+ return constant_pool_size;
+}
+
+/*
+ Add a float constant into the constant pool
+*/
+int cp_add_double(double data)
+{
+ die(18);
+
+ return constant_pool_size;
+}
+
+/*
+ Add a double constant into the constant pool
+*/
+int cp_add_float(float data)
+{
+ int i;
+ constant_pool *entry;
+
+ /* check if the string already exists in the table */
+ for (i=0; i<constant_pool_size; i++)
+ {
+ if (constants[i].tag == 6)
+ {
+ float *p_value;
+ p_value = (float*)(constants[i].data);
+ if(*p_value == data)
+ return i+1; /* the indexes for the constant pool are in range 1..N (not zero based) */
+ }
+ }
+
+ /* create a new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 6;
+ entry->data = (char*) mem_alloc(sizeof(float));
+
+ if (entry->data == NULL)
+ die(1);
+
+ *((float*)(entry->data)) = data;
+
+ return constant_pool_size;
+}
+
+
+/*
+ Adds a class information into the constants pool
+*/
+int cp_add_class(char *class_name)
+{
+ int i;
+ constant_pool *entry;
+
+ /* first add the utf8 constant */
+ int utf8_const = cp_add_utf8(class_name);
+
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 7)
+ && (constants[i].param1 == utf8_const))
+ {
+ return i+1;
+ }
+ }
+
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 7;
+ entry->param1 = utf8_const;
+
+ return constant_pool_size;
+}
+
+/*
+ Add name and type entry into the constant pool
+*/
+int cp_add_nameandtype(char *name, char *type)
+{
+ int i;
+ int name_index;
+ int type_index;
+ constant_pool *entry;
+
+ /* first add the utf8 constant */
+ name_index = cp_add_utf8(name);
+ type_index = cp_add_utf8(type);
+
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 12)
+ && (constants[i].param1 == name_index)
+ && (constants[i].param2 == type_index))
+ {
+ return i+1;
+ }
+ }
+
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 12;
+ entry->param1 = name_index;
+ entry->param2 = type_index;
+
+ return constant_pool_size;
+}
+
+/*
+ Adds the fieldref entry into the constant pool
+*/
+int cp_add_fieldref(char *class_name, char *name, char *type)
+{
+ int i;
+ int class_index;
+ int nameandtype_index;
+ constant_pool *entry;
+
+ /* first add the utf8 constant */
+ class_index = cp_add_class(class_name);
+ nameandtype_index = cp_add_nameandtype(name, type);
+
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 9)
+ && (constants[i].param1 == class_index)
+ && (constants[i].param2 == nameandtype_index))
+ {
+ return i+1;
+ }
+ }
+
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 9;
+ entry->param1 = class_index;
+ entry->param2 = nameandtype_index;
+
+ return constant_pool_size;
+}
+
+/*
+ Add the fieldref entry into the constant pool
+*/
+int cp_add_methodref(char *class_name, char *name, char *type)
+{
+ int i;
+ int class_index;
+ int nameandtype_index;
+ constant_pool *entry;
+
+ /* first add the utf8 constant */
+ class_index = cp_add_class(class_name);
+ nameandtype_index = cp_add_nameandtype(name, type);
+
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 10)
+ && (constants[i].param1 == class_index)
+ && (constants[i].param2 == nameandtype_index))
+ {
+ return i+1;
+ }
+ }
+
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 10;
+ entry->param1 = class_index;
+ entry->param2 = nameandtype_index;
+
+ return constant_pool_size;
+}
+
+/*
+ Add the interface entry into the constant pool
+*/
+int cp_add_interface(char *class_name, char *name, char *type)
+{
+ int i;
+ int class_index;
+ int nameandtype_index;
+ constant_pool *entry;
+ /* first add the utf8 constant */
+ class_index = cp_add_class(class_name);
+ nameandtype_index = cp_add_nameandtype(name, type);
+ /* search if the same string already exists */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ if ((constants[i].tag == 10) && (constants[i].param1 == class_index) && (constants[i].param2 == nameandtype_index))
+ return i+1;
+ }
+ /* create the new entry */
+ entry = cp_create_new_entry();
+ entry->tag = 11;
+ entry->param1 = class_index;
+ entry->param2 = nameandtype_index;
+ return constant_pool_size;
+}
+
+/*
+ Creates a new entry in the constant pool.
+*/
+constant_pool *cp_create_new_entry()
+{
+ constant_pool_size ++;
+
+ if (constant_pool_size == 1)
+ constants = (constant_pool*) mem_alloc(sizeof(constant_pool));
+ else
+ constants = (constant_pool*) mem_realloc(constants,
+ sizeof(constant_pool) * constant_pool_size);
+
+ if (constants == NULL)
+ die(1);
+
+ return &constants[constant_pool_size-1];
+}
+
+/*
+ Writes the constant pool to the disk
+*/
+void write_constant_pool(FILE *fp)
+{
+ int i;
+
+ /* write the constant pool count */
+ write_short_int(fp, (short)(constant_pool_size + 1));
+
+ /* write the constant pool entries */
+ for(i=0; i<constant_pool_size; i++)
+ {
+ /* write the tag */
+ char tag = constants[i].tag;
+
+ fwrite(&tag, 1, 1, fp);
+
+ switch (tag)
+ {
+ case 7: /* constant_class */
+ {
+ write_short_int(fp, constants[i].param1);
+ }
+ break;
+
+ case 9: /* fieldref */
+ case 10: /* methodref */
+ case 12: /* name and type */
+ {
+ write_short_int(fp, constants[i].param1);
+ write_short_int(fp, constants[i].param2);
+ }
+ break;
+
+ case 8: /* string */
+ {
+ write_short_int(fp, constants[i].param1);
+ }
+ break;
+
+ case 3: /* integer */
+ {
+ write_long_int(fp, *((int*)constants[i].data));
+ }
+ break;
+
+ case 4: /* float */
+ {
+ int *data;
+ data = (int*) constants[i].data;
+ write_long_int(fp, *data);
+ }
+ break;
+
+ case 1: /* Utf-8 */
+ {
+ write_short_int(fp, (short) constants[i].data_len);
+ fwrite(constants[i].data, 1, constants[i].data_len, fp);
+ }
+ break;
+
+ default:
+ die(16);
+ }
+ }
+}
diff --git a/MPC.3.5.LINUX/classgen/constant_pool.h b/MPC.3.5.LINUX/classgen/constant_pool.h
--- /dev/null
@@ -0,0 +1,33 @@
+/********************************************************************
+
+ constant_pool.h - methods for handling constant pool
+
+ Niksa Orlic, 2004-06-11
+
+********************************************************************/
+
+struct constant_pool_struct
+{
+ unsigned char tag;
+ unsigned short param1;
+ unsigned short param2;
+ char *data;
+ int data_len;
+};
+
+typedef struct constant_pool_struct constant_pool;
+
+int cp_add_string(char *str);
+int cp_add_utf8(char *str);
+int cp_add_class(char *class_name);
+int cp_add_integer(int data);
+int cp_add_long(long data);
+int cp_add_float(float data);
+int cp_add_double(double data);
+int cp_add_fieldref(char *class_name, char *name, char *type);
+int cp_add_methodref(char *class_name, char *name, char *type);
+int cp_add_interface(char *class_name, char *name, char *type);
+int cp_add_nameandtype(char *name, char *type);
+constant_pool *cp_create_new_entry();
+
+void write_constant_pool(FILE *fp);
diff --git a/MPC.3.5.LINUX/classgen/preverify.c b/MPC.3.5.LINUX/classgen/preverify.c
--- /dev/null
@@ -0,0 +1,1119 @@
+/********************************************************************
+
+ preverify.c - methods for preverifing class files
+
+ Niksa Orlic, 2004-05-16
+
+********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+//#include "../util/message.h"
+#include "../util/error.h"
+#include "../util/strings.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "constant_pool.h"
+#include "bytecode.h"
+#include "preverify.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "../util/memory.h"
+
+extern constant_pool *constants;
+extern int constant_pool_size;
+
+stack_map_list *pending_list;
+stack_map_list *output_list;
+
+
+stack_map_list *preverify_bytecode(bytecode *code, identifier *block_identifier)
+{
+ stack_map *map;
+ pending_list = NULL;
+ output_list = NULL;
+
+ /* go through the bytecode */
+ map = stack_map_create();
+ map->bytecode_offset = 0;
+ preverify_bytecode_from(map, code, block_identifier);
+ stack_map_destroy(map);
+
+ /* revisit the offsets in the pending list */
+ while (pending_list != NULL)
+ {
+ map = stack_map_list_get(&pending_list);
+ if (map == NULL)
+ break;
+
+ stack_map_list_append(&output_list, stack_map_duplicate(map));
+ preverify_bytecode_from(map, code, block_identifier);
+ stack_map_destroy(map);
+ }
+
+ output_list = sort_map_list(output_list);
+
+ return output_list;
+}
+
+
+/*
+ Sorts the list according to offsets
+*/
+stack_map_list* sort_map_list(stack_map_list *list)
+{
+ int range = 0;
+
+ stack_map_list *it;
+ stack_map_list *sorted_list = NULL;
+
+ /* repeat until the list is empty */
+ while (list != NULL)
+ {
+ /* find the next smallest number */
+ int smallest = 0x0fffffff;
+
+ it = list;
+ while (it != NULL)
+ {
+ if ((it->data->bytecode_offset < smallest)
+ && (it->data->bytecode_offset >= range))
+ smallest = it->data->bytecode_offset;
+ it = it->next;
+ }
+
+ if (smallest == 0x0fffffff)
+ break;
+
+ range = smallest + 1;
+
+ /* extract the smallest number into the output list */
+ it = list;
+ while (it != NULL)
+ {
+ if (it->data->bytecode_offset == smallest)
+ {
+ stack_map_list_append(&sorted_list, it->data);
+
+ break;
+ }
+ it = it->next;
+ }
+
+ }
+
+ return sorted_list;
+}
+
+
+/*
+ Preverifies the bytecode starting with the given stackmap
+*/
+void preverify_bytecode_from(stack_map *map, bytecode *code, identifier *block_identifier)
+{
+ int offset;
+ offset = map->bytecode_offset;
+
+ while (preverify_consume_bytecode(code, map, &offset, block_identifier))
+ {
+ /* do nothing */
+ }
+}
+
+
+/*
+ Reads one bytecode and updates stack map. Returns 0 if
+ 'return' bytocode is found, or 1 otherwise.
+
+ It seems that most of the jumps have nothing on the stack. The few
+ jumps that have something on the stack will only have integers.
+*/
+int preverify_consume_bytecode(bytecode *code, stack_map *map, int *offset, identifier *block_identifier)
+{
+ unsigned char opcode = code->bytecode[*offset];
+ switch ((unsigned char)(code->bytecode[*offset]))
+ {
+ case nop$:
+ (*offset) ++;
+ break;
+
+ case aconst_null$:
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Null, 0);
+ break;
+
+ case iconst_m1$:
+ case iconst_0$:
+ case iconst_1$:
+ case iconst_2$:
+ case iconst_3$:
+ case iconst_4$:
+ case iconst_5$:
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case lconst_0$:
+ case lconst_1$:
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Long, 0);
+ break;
+
+ case bipush$:
+ (*offset) += 2;
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case sipush$:
+ (*offset) += 3;
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case iload$:
+ (*offset) += 2;
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case lload$:
+ (*offset) += 2;
+ stack_map_push_entry(map, ITEM_Long, 0);
+ break;
+
+ case iload_0$:
+ case iload_1$:
+ case iload_2$:
+ case iload_3$:
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case lload_0$:
+ case lload_1$:
+ case lload_2$:
+ case lload_3$:
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Long, 0);
+ break;
+
+ case iaload$:
+ case baload$:
+ case caload$:
+ case saload$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case laload$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Long, 0);
+ break;
+
+ case istore$:
+ case lstore$:
+ case astore$:
+ (*offset) += 2;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case istore_0$:
+ case istore_1$:
+ case istore_2$:
+ case istore_3$:
+ case lstore_0$:
+ case lstore_1$:
+ case lstore_2$:
+ case lstore_3$:
+ case astore_0$:
+ case astore_1$:
+ case astore_2$:
+ case astore_3$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case iastore$:
+ case lastore$:
+ case fastore$:
+ case dastore$:
+ case aastore$:
+ case bastore$:
+ case castore$:
+ case sastore$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case pop$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case pop2$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case dup$:
+ {
+ stack_entry *entry;
+ (*offset) ++;
+ entry = stack_map_pop(map);
+ stack_map_push(map, entry);
+ stack_map_push(map, entry);
+ stack_entry_destroy(entry);
+ }
+ break;
+
+ case dup_x1$:
+ case dup_x2$:
+ {
+ stack_entry *e1, *e2;
+ (*offset) ++;
+ e1 = stack_map_pop(map);
+ e2 = stack_map_pop(map);
+ stack_map_push(map, e1);
+ stack_map_push(map, e2);
+ stack_map_push(map, e1);
+ stack_entry_destroy(e1);
+ stack_entry_destroy(e2);
+ }
+ break;
+
+ case dup2_x1$:
+ {
+ stack_entry *e1, *e2, *e3;
+ (*offset) ++;
+ e1 = stack_map_pop(map);
+ e2 = stack_map_pop(map);
+ e3 = stack_map_pop(map);
+ stack_map_push(map, e2);
+ stack_map_push(map, e1);
+ stack_map_push(map, e3);
+ stack_map_push(map, e2);
+ stack_map_push(map, e1);
+ stack_entry_destroy(e1);
+ stack_entry_destroy(e2);
+ stack_entry_destroy(e3);
+ }
+ break;
+
+ case swap$:
+ {
+ stack_entry *e1, *e2;
+ (*offset) ++;
+ e1 = stack_map_pop(map);
+ e2 = stack_map_pop(map);
+ stack_map_push(map, e1);
+ stack_map_push(map, e2);
+ stack_entry_destroy(e1);
+ stack_entry_destroy(e2);
+ }
+ break;
+
+ case iadd$:
+ case ladd$:
+ case fadd$:
+ case dadd$:
+ case isub$:
+ case lsub$:
+ case fsub$:
+ case dsub$:
+ case imul$:
+ case lmul$:
+ case fmul$:
+ case dmul$:
+ case idiv$:
+ case ldiv$:
+ case fdiv$:
+ case ddiv$:
+ case irem$:
+ case lrem$:
+ case frem$:
+ case drem$:
+ case iand$:
+ case land$:
+ case ior$:
+ case lor$:
+ case ixor$:
+ case lxor$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case ineg$:
+ case lneg$:
+ case fneg$:
+ case dneg$:
+ case i2b$:
+ case i2c$:
+ case i2s$:
+ (*offset) ++;
+ break;
+
+ case ishl$:
+ case lshl$:
+ case ishr$:
+ case lshr$:
+ case iushr$:
+ case lushr$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case iinc$:
+ (*offset) += 3;
+ break;
+
+ case i2l$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Long, 0);
+ break;
+
+ case l2i$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case lcmp$:
+ case fcmpl$:
+ case fcmpg$:
+ case dcmpl$:
+ case dcmpg$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case ifeq$:
+ case ifne$:
+ case iflt$:
+ case ifge$:
+ case ifgt$:
+ case ifle$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ process_jump(map, *offset - 1 + (int)((code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1])));
+ (*offset) ++;
+ (*offset) ++;
+ break;
+
+ case if_icmpeq$:
+ case if_icmpne$:
+ case if_icmplt$:
+ case if_icmpge$:
+ case if_icmpgt$:
+ case if_icmple$:
+ case if_acmpeq$:
+ case if_acmpne$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ process_jump(map, *offset - 1 + (int)((code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1])));
+ (*offset) ++;
+ (*offset) ++;
+ break;
+
+ case goto$:
+ {
+ (*offset) ++;
+ process_jump(map, *offset - 1 + (int)((code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1])));
+ return 0;
+ }
+ break;
+
+ case ireturn$:
+ case lreturn$:
+ case freturn$:
+ case dreturn$:
+ case areturn$:
+ stack_entry_destroy(stack_map_pop(map));
+ case return$:
+ return 0;
+
+ case aload$:
+ (*offset) += 2;
+ stack_map_push_local(map, block_identifier, (unsigned char) code->bytecode[*offset-1]);
+ break;
+
+ case aload_0$:
+ (*offset) ++;
+ stack_map_push_local(map, block_identifier, 0);
+ break;
+
+ case aload_1$:
+ (*offset) ++;
+ stack_map_push_local(map, block_identifier, 1);
+ break;
+
+ case aload_2$:
+ (*offset) ++;
+ stack_map_push_local(map, block_identifier, 2);
+ break;
+
+ case aload_3$:
+ (*offset) ++;
+ stack_map_push_local(map, block_identifier, 3);
+ break;
+
+ case aaload$:
+ {
+ char object_class[128];
+ stack_entry* entry;
+ int classname_index;
+ int delta = 1;
+
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+
+ entry = stack_map_pop(map);
+ classname_index = constants[entry->additional_data - 1].param1 - 1;
+ strncpy(object_class, constants[classname_index].data, constants[classname_index].data_len);
+ object_class[constants[classname_index].data_len] = '\0';
+
+ if (object_class[1] == 'L')
+ {
+ delta = 2;
+ object_class[strlen(object_class) - 1] = '\0';
+ }
+ stack_entry_destroy(entry);
+ stack_map_push_entry(map, ITEM_Object, cp_add_class(object_class + delta));
+ }
+ break;
+
+ case tableswitch$:
+ case lookupswitch$:
+ // TODO::
+ break;
+
+ case instanceof$:
+ (*offset) += 3;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case ldc$:
+ (*offset) ++;
+ (*offset) ++;
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+ break;
+
+ case ldc_w$:
+ (*offset) += 3;
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+ break;
+
+ case getstatic$:
+ {
+ int t;
+ (*offset) ++;
+ t = code->bytecode[*offset];
+ t = t << 8 | (unsigned char)(code->bytecode[(*offset) + 1]);
+ t = constants[t-1].param2;
+ t = constants[t-1].param2;
+ (*offset) += 2;
+ switch(constants[t-1].data[0])
+ {
+ case 'L':
+ case '[':
+ {
+ char *class_name = (char*) mem_alloc(sizeof(char) * strlen(constants[t-1].data));
+ strcpy(class_name, constants[t-1].data + 1);
+ class_name[strlen(constants[t-1].data) - 2] = '\0';
+ stack_map_push_entry(map, ITEM_Object, cp_add_class(class_name));
+ mem_free(class_name);
+ break;
+ }
+ // case '[':
+ // stack_map_push_entry(map, ITEM_Object, t);
+ // break;
+ case 'I':
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+ default:
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+
+ }
+ }
+ break;
+
+ case new$:
+ (*offset) += 3;
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+ break;
+
+ case getfield$:
+ (*offset) += 3;
+ break;
+
+ case putstatic$:
+ (*offset) += 3;
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case putfield$:
+ (*offset) += 3;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_entry_destroy(stack_map_pop(map));
+ break;
+
+ case invokevirtual$:
+ case invokespecial$:
+ case invokestatic$:
+ {
+ unsigned short int num;
+ int len, i = 0;
+ int oldstate, state = 0;
+ int count = 0;
+ int isVoid = 0;
+ char *descriptor;
+ char *class_name;
+ int state_machine_table[4][6] =
+ { /* ( ) L ; V else */
+ /* 0 */ { 1, -1, -1, -1, -1, -1 },
+ /* 1 */ {-1, 2, 3, -1, 1, 1 },
+ /* 2 */ {-1, -1, -1, -1, -1, -1 },
+ /* 3 */ { 3, 3, 3, 1, 3, 3 }
+ };
+
+ (*offset) ++;
+ num = (code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1]);
+ (*offset) += 2;
+
+ num = constants[num-1].param2;
+ num = constants[num-1].param2;
+ len = constants[num-1].data_len;
+ descriptor = constants[num-1].data;
+
+ while (i < len)
+ {
+ oldstate = state;
+
+ switch (descriptor[i])
+ {
+ case '(': state = state_machine_table[state][0]; break;
+ case ')': state = state_machine_table[state][1]; break;
+ case 'L': state = state_machine_table[state][2]; break;
+ case ';': state = state_machine_table[state][3]; break;
+ case 'V': state = state_machine_table[state][4]; break;
+ default : state = state_machine_table[state][5]; break;
+ }
+ i ++;
+
+ if ((state == 1) && (oldstate != 0))
+ count ++;
+
+ if (state == 2)
+ {
+ if (descriptor[i] == 'V')
+ isVoid = 1;
+
+ class_name = (char*) mem_alloc(len);
+
+ strcpy(class_name, descriptor + i);
+
+ break;
+ }
+ }
+
+ if (opcode != invokestatic$)
+ stack_entry_destroy(stack_map_pop(map));
+ while (count > 0)
+ {
+ stack_entry_destroy(stack_map_pop(map));
+ count --;
+ }
+
+ if (class_name[0] == 'L')
+ {
+ class_name[strlen(class_name) - 1] = '\0';
+ if (!isVoid)
+ stack_map_push_entry(map, ITEM_Object, cp_add_class(class_name+1));
+ }
+ else if (class_name[0] == 'I')
+ {
+ if (!isVoid)
+ stack_map_push_entry(map, ITEM_Integer,0);
+ }
+ else
+ {
+ if (!isVoid)
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+
+ }
+
+ mem_free(class_name);
+ }
+ break;
+
+
+ /*case invokestatic$:
+ {
+ unsigned short int num;
+ int len, i = 0;
+ int oldstate, state = 0;
+ int count = 0;
+ int isVoid = 0;
+ char *descriptor;
+ int state_machine_table[4][6] =
+ { /* ( ) L ; V else
+ /* 0 { 1, -1, -1, -1, -1, -1 },
+ /* 1 {-1, 2, 3, -1, 1, 1 },
+ /* 2 {-1, -1, -1, -1, -1, -1 },
+ /* 3 { 3, 3, 3, 1, 3, 3 }
+ };
+
+ (*offset) ++;
+ num = (code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1]);
+ (*offset) += 2;
+
+ num = constants[num-1].param2;
+ num = constants[num-1].param2;
+ len = constants[num-1].data_len;
+ descriptor = constants[num-1].data;
+
+ while (i < len)
+ {
+ oldstate = state;
+
+ switch (descriptor[i])
+ {
+ case '(': state = state_machine_table[state][0]; break;
+ case ')': state = state_machine_table[state][1]; break;
+ case 'L': state = state_machine_table[state][2]; break;
+ case ';': state = state_machine_table[state][3]; break;
+ case 'V': state = state_machine_table[state][4]; break;
+ default : state = state_machine_table[state][5]; break;
+ }
+ i ++;
+
+ if ((state == 1) && (oldstate != 0))
+ count ++;
+
+ if (state == 2)
+ {
+ if (descriptor[i] == 'V')
+ isVoid = 1;
+
+ break;
+ }
+ }
+
+ while (count > 0)
+ {
+ stack_entry_destroy(stack_map_pop(map));
+ count --;
+ }
+
+ if (!isVoid)
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+ }
+ break;*/
+
+
+ case newarray$:
+ (*offset) += 2;
+ break;
+
+ case anewarray$:
+ (*offset) += 3;
+ break;
+
+ case arraylength$:
+ (*offset) ++;
+ stack_entry_destroy(stack_map_pop(map));
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case multianewarray$:
+ {
+ unsigned int i, t, s;
+ (*offset) ++;
+ t = code->bytecode[*offset];
+ t = t << 8 | (unsigned char)(code->bytecode[(*offset) + 1]);
+ (*offset) += 2;
+ i = code->bytecode[*offset];
+ (*offset) ++;
+
+ s = i;
+ while (i>0)
+ {
+ stack_entry_destroy(stack_map_pop(map));
+ i --;
+ }
+
+ stack_map_push_entry(map, ITEM_NewObject, *offset - 4);
+ break;
+ }
+
+ case ifnull$:
+ case ifnonnull$:
+ stack_entry_destroy(stack_map_pop(map));
+ (*offset) ++;
+ process_jump(map, *offset - 1 + (int)((code->bytecode[*offset] << 8) | (unsigned char)(code->bytecode[(*offset) + 1])));
+ (*offset) ++;
+ (*offset) ++;
+ break;
+
+ default:
+ die(22);
+
+ }
+
+ return 1;
+}
+
+
+/*
+ When a branch instruction is found, adds the target offset into the list.
+*/
+void process_jump(stack_map *map, int position)
+{
+ stack_map *new_map;
+
+ /* check if the position is already in the pending or output list */
+ stack_map_list *it;
+ it = pending_list;
+
+ while (it != NULL)
+ {
+ if (it->data->bytecode_offset == position)
+ return;
+ it = it->next;
+ }
+
+ it = output_list;
+
+ while (it != NULL)
+ {
+ if (it->data->bytecode_offset == position)
+ return;
+ it = it->next;
+ }
+
+ /* if here, add the offset into the pendign list */
+ new_map = stack_map_duplicate(map);
+ new_map->bytecode_offset = position;
+ stack_map_list_append(&pending_list, new_map);
+}
+
+
+/*
+ Create anew stack_entry object.
+*/
+stack_entry* stack_entry_create()
+{
+ stack_entry *new_entry = (stack_entry*) mem_alloc(sizeof(stack_entry));
+
+ if (new_entry == NULL)
+ die(1);
+
+ return new_entry;
+}
+
+
+/*
+ Delete all data used by stack_entry
+*/
+void stack_entry_destroy(stack_entry *entry)
+{
+ mem_free(entry);
+}
+
+
+/*
+ Create a copy of the stack entry.
+*/
+stack_entry* stack_entry_duplicate(stack_entry *old_entry)
+{
+ stack_entry* new_entry = (stack_entry*) mem_alloc(sizeof(stack_entry));
+
+ if (new_entry == NULL)
+ die(1);
+
+ new_entry->item_type = old_entry->item_type;
+ new_entry->additional_data = old_entry->additional_data;
+
+ return new_entry;
+}
+
+
+/*
+ Create a stackmap object
+*/
+stack_map* stack_map_create()
+{
+ stack_map *new_map = (stack_map*) mem_alloc(sizeof(stack_map));
+
+ if (new_map == NULL)
+ die(1);
+
+ new_map->allocated_number_of_items = 0;
+ new_map->number_of_items = 0;
+
+ return new_map;
+}
+
+
+/*
+ Destroy the stack map
+*/
+void stack_map_destroy(stack_map *map)
+{
+ int i;
+ for (i=0; i<map->number_of_items; i++)
+ {
+ stack_entry_destroy(map->stack[i]);
+ }
+
+ if (map->allocated_number_of_items > 0)
+ mem_free(map->stack);
+
+ mem_free(map);
+}
+
+
+/*
+ Create a copy of the map
+*/
+stack_map* stack_map_duplicate(stack_map *old_map)
+{
+ int i;
+
+ stack_map *new_map = (stack_map*) mem_alloc(sizeof(stack_map));
+
+ if (new_map == NULL)
+ die(1);
+
+ new_map->number_of_items = old_map->number_of_items;
+ new_map->allocated_number_of_items = old_map->allocated_number_of_items;
+ new_map->bytecode_offset = old_map->bytecode_offset;
+
+ if (old_map->allocated_number_of_items > 0)
+ {
+ new_map->stack = (stack_entry**) mem_alloc(sizeof(stack_entry) * old_map->allocated_number_of_items);
+
+ if (new_map->stack == NULL)
+ die(1);
+ }
+
+ for (i=0; i<old_map->number_of_items; i++)
+ new_map->stack[i] = stack_entry_duplicate(old_map->stack[i]);
+
+ return new_map;
+}
+
+
+/*
+ Take the top element from the stack
+*/
+stack_entry* stack_map_pop(stack_map* map)
+{
+ stack_entry* top_element;
+
+ top_element = map->stack[map->number_of_items - 1];
+
+ map->number_of_items --;
+
+ return top_element;
+}
+
+
+/*
+ Add a new element to the top of the stack
+*/
+void stack_map_push(stack_map *map, stack_entry *entry)
+{
+ stack_map_push_entry(map, entry->item_type, entry->additional_data);
+}
+
+
+/*
+ Add a new element to the top of the stack.
+*/
+void stack_map_push_entry(stack_map *map, enum stack_item item_type, short int additional_data)
+{
+ stack_entry *new_entry = stack_entry_create();
+ new_entry->item_type = item_type;
+ new_entry->additional_data = additional_data;
+
+ /*
+ Do realloc or malloc if needeed
+ */
+ if (map->allocated_number_of_items <= map->number_of_items)
+ {
+ if (map->allocated_number_of_items == 0)
+ {
+ map->stack = (stack_entry**) mem_alloc(sizeof(stack_entry*));
+
+ if (map->stack == NULL)
+ die(1);
+
+ map->allocated_number_of_items = 1;
+ }
+ else
+ {
+ map->stack = (stack_entry**) mem_realloc(map->stack, sizeof(stack_entry*) * (map->allocated_number_of_items + 1));
+
+ if (map->stack == NULL)
+ die(1);
+
+ map->allocated_number_of_items ++;
+ }
+ }
+
+ map->number_of_items ++;
+ map->stack[map->number_of_items - 1] = new_entry;
+}
+
+void stack_map_list_destroy(stack_map_list*);
+
+/*
+ Push a local variable, determine its type
+*/
+void stack_map_push_local(stack_map *map, identifier *block_identifier, int localNum)
+{
+ type *variable_type = NULL;
+ char descriptor[256];
+ type_list *it;
+ int i = 0;
+
+ if (block_identifier == NULL)
+ {
+ /* if block is the root block, this should never happen */
+ stack_map_push_entry(map, ITEM_Bogus, 0);
+ return;
+ }
+
+ it = block_identifier->parameters;
+ while (it != NULL)
+ {
+ if (it->data == NULL)
+ break;
+
+ if (i == localNum)
+ {
+ variable_type = type_duplicate(it->data);
+ break;
+ }
+ i ++;
+ it = it->next;
+ }
+
+
+ if ((block_identifier->identifier_class == function_name)
+ && (variable_type == NULL))
+ {
+ if (i == localNum)
+ variable_type = type_duplicate(block_identifier->return_type);
+ i ++;
+ }
+
+ it = block_identifier->variables;
+ while ((it != NULL) && (variable_type == NULL))
+ {
+ if (it->data == NULL)
+ break;
+
+ if (i == localNum)
+ {
+ variable_type = type_duplicate(it->data);
+ break;
+ }
+ i ++;
+ it = it->next;
+ }
+
+ switch (variable_type->type_class)
+ {
+ case integer_type:
+ case real_type:
+ case char_type:
+ case boolean_type:
+ stack_map_push_entry(map, ITEM_Integer, 0);
+ break;
+
+ case array_type:
+ get_field_descriptor(variable_type, descriptor);
+ stack_map_push_entry(map, ITEM_Object, cp_add_class(descriptor));
+ break;
+
+ default:
+ get_field_descriptor(variable_type, descriptor);
+ descriptor[strlen(descriptor)-1] = '\0';
+ stack_map_push_entry(map, ITEM_Object, cp_add_class(descriptor+1));
+ break;
+ }
+
+ type_destroy(variable_type);
+
+}
+
+/*
+ Append data to the end of the list
+*/
+void stack_map_list_append(stack_map_list **list, stack_map* data)
+{
+ stack_map_list *it;
+
+ if (*list == NULL)
+ {
+ *list = (stack_map_list*)mem_alloc(sizeof(stack_map_list));
+ if (*list == NULL)
+ die(1);
+
+ (*list)->data = data;
+ (*list)->next = NULL;
+ return;
+ }
+
+ it = *list;
+
+ while (it->next != NULL)
+ it = it->next;
+
+ it->next = (stack_map_list*) mem_alloc(sizeof(stack_map_list));
+
+ if (it->next == NULL)
+ die(1);
+
+ it->next->data = data;
+ it->next->next = NULL;
+
+
+}
+
+
+/*
+ Get the first element from the list
+*/
+stack_map* stack_map_list_get(stack_map_list **list)
+{
+ stack_map_list *next;
+ stack_map *data;
+
+ if (*list == NULL)
+ return NULL;
+
+ next = (*list)->next;
+ data = (*list)->data;
+
+ *list = next;
+
+ return data;
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/classgen/preverify.h b/MPC.3.5.LINUX/classgen/preverify.h
--- /dev/null
@@ -0,0 +1,79 @@
+/********************************************************************
+
+ preverify.h - methods and structures for bytecode preverification
+
+ Niksa Orlic, 2004-08-18
+
+********************************************************************/
+
+
+/*** Preverifier structures ***/
+enum stack_item
+{
+ ITEM_Bogus = 0,
+ ITEM_Integer,
+ ITEM_Float,
+ ITEM_Double,
+ ITEM_Long,
+ ITEM_Null,
+ ITEM_InitObject,
+ ITEM_Object,
+ ITEM_NewObject
+};
+
+struct stack_entry_struct
+{
+ enum stack_item item_type;
+ short int additional_data;
+};
+
+typedef struct stack_entry_struct stack_entry;
+
+struct stack_map_struct
+{
+ int number_of_items;
+ int allocated_number_of_items;
+ stack_entry **stack;
+ int bytecode_offset;
+};
+
+typedef struct stack_map_struct stack_map;
+
+
+
+stack_entry* stack_entry_create();
+void stack_entry_destroy(stack_entry*);
+stack_entry* stack_entry_duplicate(stack_entry*);
+
+stack_map* stack_map_create();
+void stack_map_destroy(stack_map*);
+stack_map* stack_map_duplicate(stack_map*);
+
+stack_entry* stack_map_pop(stack_map*);
+void stack_map_push(stack_map*, stack_entry*);
+void stack_map_push_entry(stack_map*, enum stack_item, short int);
+void stack_map_push_local(stack_map*, identifier*, int);
+
+
+struct stack_map_list_struct
+{
+ struct stack_map_list_struct *next;
+ stack_map *data;
+};
+
+typedef struct stack_map_list_struct stack_map_list;
+
+void stack_map_list_destroy(stack_map_list*);
+
+void stack_map_list_append(stack_map_list**, stack_map*);
+stack_map* stack_map_list_get(stack_map_list**);
+
+
+/*** Preverifier methods ***/
+stack_map_list *preverify_bytecode(bytecode*, identifier *);
+int preverify_consume_bytecode(bytecode*, stack_map*, int *offset, identifier*);
+void process_jump(stack_map *map, int position);
+void preverify_bytecode_from(stack_map*, bytecode*, identifier*);
+stack_map_list* sort_map_list(stack_map_list*);
+
+
diff --git a/MPC.3.5.LINUX/lex/lex.yy.c b/MPC.3.5.LINUX/lex/lex.yy.c
--- /dev/null
@@ -0,0 +1,560 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tokens.h"
+#include "../util/strings.h"
+#include "../util/error.h"
+
+extern int mathType;
+extern int goverify;
+char charbuf[10240];
+char textbuf[10240];
+char strconst[10240];
+int charcount;
+FILE *yyin; //, *yyout; //source file
+char *yytext; //current token string
+string *string_constant;
+char char_constant;
+char boolean_constant;
+float real_constant;
+long int integer_constant;
+int linenum;
+int fileSize;
+char c;
+
+void yyrestart(char *fname) { //FILE *new_file){ //open source file
+ yyin = fopen(fname, "r");
+ if (yyin == NULL) die(5);
+ fseek(yyin, 0, SEEK_END);
+ fileSize = ftell(yyin);
+ fseek(yyin, 0, SEEK_SET);
+ charcount=0;
+ string_constant=&strconst;
+ yytext=&textbuf;
+ linenum=1;
+};
+
+char nextchar(){
+ int d;
+ if (charcount>0){
+ charcount--;
+ return charbuf[charcount];
+ }
+ d=fgetc(yyin);
+ if (d==10) linenum++;
+ if (d==EOF) return '\255';
+ return d;
+}
+
+void backchar(int c){ //put the char back to stream
+ charbuf[charcount]=c;
+ charcount++;
+};
+
+
+int yylex(){ //get token
+ int i,ncount,r;
+ char *p;
+ i = ftell(yyin);
+ compile_progress(i * 100 / fileSize);
+ do {
+ r=0;
+//lab:
+ //if (linenum==1059) {
+ // linenum=1059;
+ //}
+ p=yytext;
+ *p='\0';
+ c=nextchar();
+ while ((c<=' ')&&(c!='\255')) c=nextchar();
+ if (((c>='A') && (c<='Z')) || ((c>='a') && (c<='z')) || (c=='_')) {
+ while (((c>='A') && (c<='Z')) || ((c>='a') && (c<='z')) || ((c>='0') && (c<='9')) || (c=='_')) {
+ *p=c;
+ p=p+1;
+ c=nextchar();
+ }
+ backchar(c);
+ *p='\0';
+ lowercase(yytext);
+ if (strcmp(yytext, "begin") == 0) return KWD_BEGIN;
+ if (strcmp(yytext, "end") == 0) return KWD_END;
+ if (strcmp(yytext, "and") == 0) return OP_AND;
+ if (strcmp(yytext, "program") == 0) return KWD_PROGRAM;
+ if (strcmp(yytext, "procedure") == 0) return KWD_PROCEDURE;
+ if (strcmp(yytext, "function") == 0) return KWD_FUNCTION;
+ if (strcmp(yytext, "var") == 0) return KWD_VAR;
+ if (strcmp(yytext, "for") == 0) return KWD_FOR;
+ if (strcmp(yytext, "to") == 0) return KWD_TO;
+ if (strcmp(yytext, "downto") == 0) return KWD_DOWNTO;
+ if (strcmp(yytext, "do") == 0) return KWD_DO;
+ if (strcmp(yytext, "const") == 0) return KWD_CONST;
+ if (strcmp(yytext, "type") == 0) return KWD_TYPE;
+ if (strcmp(yytext, "if") == 0) return KWD_IF;
+ if (strcmp(yytext, "then") == 0) return KWD_THEN;
+ if (strcmp(yytext, "else") == 0) return KWD_ELSE;
+ if (strcmp(yytext, "case") == 0) return KWD_CASE;
+ if (strcmp(yytext, "of") == 0) return KWD_OF;
+ if (strcmp(yytext, "while") == 0) return KWD_WHILE;
+ if (strcmp(yytext, "repeat") == 0) return KWD_REPEAT;
+ if (strcmp(yytext, "until") == 0) return KWD_UNTIL;
+ if (strcmp(yytext, "forever") == 0) return KWD_FOREVER;
+ if (strcmp(yytext, "with") == 0) return KWD_WITH;
+ if (strcmp(yytext, "packed") == 0) return KWD_PACKED;
+ if (strcmp(yytext, "array") == 0) return KWD_ARRAY;
+ if (strcmp(yytext, "or") == 0) return OP_OR;
+ if (strcmp(yytext, "file") == 0) return KWD_FILE;
+ if (strcmp(yytext, "set") == 0) return KWD_SET;
+ if (strcmp(yytext, "record") == 0) return KWD_RECORD;
+ if (strcmp(yytext, "in") == 0) return OP_IN;
+ if (strcmp(yytext, "not") == 0) return OP_NOT;
+ if (strcmp(yytext, "xor") == 0) return OP_XOR;
+ if (strcmp(yytext, "forward") == 0) return KWD_FORWARD;
+ if (strcmp(yytext, "break") == 0) return KWD_BREAK;
+ if (strcmp(yytext, "uses") == 0) return KWD_USES;
+ if (strcmp(yytext, "unit") == 0) return KWD_UNIT;
+ if (strcmp(yytext, "interface") == 0) return KWD_INTERFACE;
+ if (strcmp(yytext, "implementation") == 0) return KWD_IMPLEMENTATION;
+ if (strcmp(yytext, "initialization") == 0) return KWD_INITIALIZATION;
+ if (strcmp(yytext, "finalization") == 0) return KWD_FINALIZATION;
+ if (strcmp(yytext, "mod") == 0) return OP_MOD;
+ if (strcmp(yytext, "div") == 0) return OP_DIV;
+ if (strcmp(yytext, "shr") == 0) return OP_SHR; //***
+ if (strcmp(yytext, "shl") == 0) return OP_SHL; //***
+ if (strcmp(yytext, "ushr") == 0) return OP_USHR; // j-a-s-d
+ if (strcmp(yytext, "inline") == 0) return KWD_INLINE; //***?
+ if (strcmp(yytext, "bytecode") == 0) return KWD_BYTECODE; // j-a-s-d
+ if (strcmp(yytext, "exit") == 0) return KWD_EXIT; // j-a-s-d
+ if (strcmp(yytext, "result") == 0) return KWD_RESULT; // j-a-s-d
+ //////
+ if (strcmp(yytext, "true") == 0) {boolean_constant=1; return CST_BOOLEAN;}
+ if (strcmp(yytext, "false") == 0) {boolean_constant=0; return CST_BOOLEAN;}
+ //////
+ return IDENTIFIER;
+ } else if ((c>='0') && (c<='9')) {
+ integer_constant=0;
+ while ((c>='0') && (c<='9')) {
+ integer_constant=integer_constant*10+c-48;
+ c=nextchar();
+ }
+ if (c!='.') {backchar(c); return CST_INTEGER;}
+ c=nextchar();
+ if (c=='.') {backchar(c);backchar(c);return CST_INTEGER;}
+ real_constant=(float)integer_constant;
+ ncount=1;
+ integer_constant=0;
+ while ((c>='0') && (c<='9')) {
+ integer_constant=integer_constant*10+c-48;
+ ncount++;
+ c=nextchar();
+ }
+ //real_constant=real_constant+(float)integer_constant/(10*ncount);
+ // j-a-s-d: little but important bugfix, it was corrupting the decimal part
+ real_constant+=(float)integer_constant/pow(10,--ncount);
+ /*
+ i=1;
+ j=0;
+ ncount=1;
+ real_constant=(float)integer_constant;
+ while (((c>='0') && (c<='9'))) {
+ j=j*10+c-48;
+ i++;
+ c=nextchar();
+ }
+ real_constant=real_constant+(j/(10*i));
+ */
+ backchar(c);
+ return CST_REAL;
+ } else if (c=='$') {
+ int ok;
+ integer_constant=0;
+ do {
+ c=nextchar();
+ ok=0;
+ if ((c>='0') && (c<='9')) {
+ integer_constant = integer_constant*16+c-48;
+ ok=1;
+ }
+ if ((c>='A') && (c<='Z')) {
+ integer_constant = integer_constant*16+10+c-65;
+ ok=1;
+ }
+ if ((c>='a') && (c<='z')) {
+ integer_constant = integer_constant*16+10+c-97;
+ ok=1;
+ }
+ } while (ok==1);
+ backchar(c);
+ return CST_INTEGER;
+ } else if (c=='/') {
+ c=nextchar();
+ if (c=='*') { // j-a-s-d: C-style /* */ multiline comments support
+ char ch=c;
+ while (!((c=='/')&&(ch=='*'))) {ch=c; c=nextchar();}
+ r=1;
+ } else
+ if (c=='/') {
+ while (c!=10) c=nextchar();
+ //goto lab;
+ r=1;
+ } else {
+ backchar(c);
+ return OP_SLASH;
+ }
+ } else if ((c=='\'')||(c=='\"')||(c=='#')) { // j-a-s-d: C-style double-quoted strings support
+ char o_c = c;
+ i=0;
+ do {
+ if (c=='#') {
+ c=nextchar();
+ integer_constant=0;
+ if (c=='$') {
+ int ok;
+ do {
+ c=nextchar();
+ ok=0;
+ if ((c>='0') && (c<='9')) {
+ integer_constant = integer_constant*16+c-48;
+ ok=1;
+ }
+ if ((c>='A') && (c<='Z')) {
+ integer_constant = integer_constant*16+10+c-65;
+ ok=1;
+ }
+ if ((c>='a') && (c<='z')) {
+ integer_constant = integer_constant*16+10+c-97;
+ ok=1;
+ }
+ } while (ok==1);
+ } else {
+ while (((c>='0') && (c<='9'))) {
+ integer_constant=integer_constant*10+c-48;
+ c=nextchar();
+ }
+ }
+ *p=(char)integer_constant;
+ p=p+1;
+ i=i+1;
+ } else {
+ c=nextchar();
+ while (c!=o_c) {
+ if (c==10) {
+ int current_token;
+ add_error_message(101, "", "");
+ do {
+ current_token = yylex();
+ } while ((current_token != END_OF_INPUT) && (current_token != SEMI_COLON));
+ break;
+ }
+rep: *p=c;
+ p=p+1;
+ i++;
+ c=nextchar();
+ }
+ c=nextchar();
+ if (c==o_c) goto rep;
+ }
+ } while ((c==o_c)||(c=='#'));
+ *p='\0';
+ backchar(c);
+ if (i==1) {p=p-1; char_constant=*p; return CST_CHAR;}
+ string_constant=string_from_cstr(yytext);
+ return CST_STRING;
+ } else if (c=='+') {
+ return OP_PLUS;
+ } else if (c=='-') {
+ return OP_MINUS;
+ } else if (c=='*') {
+ return OP_MULT;
+ } else if (c=='=') {
+ return OP_EQUAL;
+ } else if (c==';') {
+ return SEMI_COLON;
+ } else if (c==':') {
+ c=nextchar();
+ if (c=='=') return OP_ASSIGN;
+ backchar(c);
+ return COLON;
+ } else if (c=='<') {
+ c=nextchar();
+ if (c=='=') return OP_LESS_EQUAL;
+ if (c=='>') return OP_NOT_EQUAL;
+ if (c=='<') return OP_SHL;
+ backchar(c);
+ return OP_LESS;
+ } else if (c=='>') {
+ c=nextchar();
+ if (c=='=') return OP_GREATER_EQUAL;
+ if (c=='>') {
+ c=nextchar();
+ if (c=='>') return OP_USHR;
+ backchar(c);
+ return OP_SHR;
+ }
+ backchar(c);
+ return OP_GREATER;
+ } else if (c=='.') {
+ c=nextchar();
+ if (c=='.') return DOTDOT;
+ backchar(c);
+ return DOT;
+ } else if (c=='[') {
+ return OPEN_SQ_BR;
+ } else if (c==']') {
+ return CLOSE_SQ_BR;
+ } else if (c=='(') {
+ char ch;
+ c=nextchar();
+ if (c!='*') {
+ backchar(c);
+ return OPEN_BR;
+ }
+ ch=c;
+ while (!((c==')')&&(ch=='*'))) {ch=c; c=nextchar();}
+ //goto lab;
+ r=1;
+ } else if (c==')') {
+ return CLOSE_BR;
+ } else if (c==',') {
+ return COMMA;
+ } else if (c=='{') { //skip comment
+ c=nextchar();
+ // j-a-s-d: removing $R and $V to avoid ambiguities
+ /*
+ if (c=='$') {
+ c=nextchar();
+ if (c=='R') { //real type switch
+ c=nextchar();
+ if (c=='-') mathType=1;
+ if (c=='+') mathType=2;
+ }
+ if (c=='V') { //preverify_bytecode switch
+ c=nextchar();
+ if (c=='-') goverify=0;
+ if (c=='+') goverify=1;
+ }
+ }
+ */
+ while (c!='}') c=nextchar();
+ //goto lab;
+ r=1;
+ }
+ } while (r==1);
+ return END_OF_INPUT;
+}
+
+//#define CST_INTEGER 0
+//#define CST_REAL 1
+//#define CST_BOOLEAN 2
+//#define CST_CHAR 3
+//#define CST_STRING 4
+//
+//#define OP_MOD 5
+//#define OP_DIV 6
+//#define OP_PLUS 7
+//#define OP_MINUS 8
+//#define OP_MULT 9
+//#define OP_SLASH 10
+//#define OP_EQUAL 11
+//#define SEMI_COLON 18
+//#define COLON 19
+//#define OP_ASSIGN 20
+//#define OP_LESS 21
+//#define OP_GREATER 22
+//#define OP_LESS_EQUAL 23
+//#define OP_GREATER_EQUAL 24
+//#define OP_NOT_EQUAL 25
+//#define DOT 26
+//#define OPEN_SQ_BR 27
+//#define CLOSE_SQ_BR 28
+//#define OPEN_BR 34
+//#define CLOSE_BR 35
+//#define IDENTIFIER 57
+//#define COMMA 58
+//#define DOTDOT 59
+//#define END_OF_INPUT 100
+/*
+#define CST_INTEGER 0
+#define CST_REAL 1
+#define CST_BOOLEAN 2
+#define CST_CHAR 3
+#define CST_STRING 4
+#define OP_MOD 5
+#define OP_DIV 6
+#define OP_PLUS 7
+#define OP_MINUS 8
+#define OP_MULT 9
+#define OP_SLASH 10
+#define OP_EQUAL 11
+#define KWD_BEGIN 12
+#define KWD_END 13
+#define OP_AND 14
+#define KWD_PROGRAM 15
+#define KWD_PROCEDURE 16
+#define KWD_FUNCTION 17
+#define SEMI_COLON 18
+#define COLON 19
+#define OP_ASSIGN 20
+#define OP_LESS 21
+#define OP_GREATER 22
+#define OP_LESS_EQUAL 23
+#define OP_GREATER_EQUAL 24
+#define OP_NOT_EQUAL 25
+#define DOT 26
+#define OPEN_SQ_BR 27
+#define CLOSE_SQ_BR 28
+#define KWD_VAR 29
+#define KWD_FOR 30
+#define KWD_TO 31
+#define KWD_DOWNTO 32
+#define KWD_DO 33
+#define OPEN_BR 34
+#define CLOSE_BR 35
+#define KWD_CONST 36
+#define KWD_TYPE 37
+#define KWD_IF 38
+#define KWD_THEN 39
+#define KWD_ELSE 40
+#define KWD_CASE 41
+#define KWD_OF 42
+#define KWD_WHILE 43
+#define KWD_REPEAT 44
+#define KWD_UNTIL 45
+#define KWD_WITH 46
+#define KWD_PACKED 47
+#define KWD_ARRAY 48
+#define OP_OR 49
+#define KWD_FILE 50
+#define KWD_SET 51
+#define KWD_RECORD 52
+#define OP_IN 53
+#define OP_NOT 54
+#define OP_XOR 55
+#define KWD_FORWARD 56
+#define IDENTIFIER 57
+#define COMMA 58
+#define DOTDOT 59
+#define KWD_BREAK 60
+#define KWD_USES 61
+#define KWD_UNIT 62
+#define KWD_INTERFACE 63
+#define KWD_IMPLEMENTATION 64
+#define KWD_INITIALIZATION 65
+#define KWD_FINALIZATION 66
+#define END_OF_INPUT 100
+
+/*
+"mod" = (OP_MOD);
+"div" = (OP_DIV);
+"+" = (OP_PLUS);
+"-" = (OP_MINUS);
+"*" = (OP_MULT);
+"/" = (OP_SLASH);
+"=" = (OP_EQUAL);
+"begin" = (KWD_BEGIN);
+"end" = (KWD_END);
+"and" = (OP_AND);
+"program" = (KWD_PROGRAM);
+"procedure" = (KWD_PROCEDURE);
+"function" = (KWD_FUNCTION);
+";" = (SEMI_COLON);
+":" = (COLON);
+":=" = (OP_ASSIGN);
+"<" = (OP_LESS);
+">" = (OP_GREATER);
+"<=" = (OP_LESS_EQUAL);
+">=" = (OP_GREATER_EQUAL);
+"<>" = (OP_NOT_EQUAL);
+"." = (DOT);
+".." = (DOTDOT);
+"[" = (OPEN_SQ_BR);
+"]" = (CLOSE_SQ_BR);
+"var" = (KWD_VAR);
+"for" = (KWD_FOR);
+"to" = (KWD_TO);
+"downto" = (KWD_DOWNTO);
+"do" = (KWD_DO);
+"(" = (OPEN_BR);
+")" = (CLOSE_BR);
+"const" = (KWD_CONST);
+"type" = (KWD_TYPE);
+"if" = (KWD_IF);
+"then" = (KWD_THEN);
+"else" = (KWD_ELSE);
+"case" = (KWD_CASE);
+"of" = (KWD_OF);
+"while" = (KWD_WHILE);
+"repeat" = (KWD_REPEAT);
+"until" = (KWD_UNTIL);
+"with" = (KWD_WITH);
+"packed" = (KWD_PACKED);
+"array" = (KWD_ARRAY);
+"or" = (OP_OR);
+"file" = (KWD_FILE);
+"set" = (KWD_SET);
+"record" = (KWD_RECORD);
+"in" = (OP_IN);
+"not" = (OP_NOT);
+"xor" = (OP_XOR);
+"forward" = (KWD_FORWARD);
+"break" = (KWD_BREAK);
+"," = (COMMA);
+"uses" = (KWD_USES);
+"unit" = (KWD_UNIT);
+"interface" = (KWD_INTERFACE);
+"implementation" = (KWD_IMPLEMENTATION);
+"initialization" = (KWD_INITIALIZATION);
+"finalization" = (KWD_FINALIZATION);
+*/
+
+
+/*
+ c=nextchar();
+ i=0;
+rep:
+ while (c!='\'') {
+ *p=c;
+ p=p+1;
+ i++;
+ c=nextchar();
+ }
+ c=nextchar();
+ if (c=='\'') {*p=c; p=p+1; i=i+1; c=nextchar(); goto rep;}
+ if (c=='#') {
+ j=0;
+ c=nextchar();
+ while (((c>='0') && (c<='9'))) {
+ j=j*10+c-48;
+ c=nextchar();
+ }
+ *p=(char)j;
+ p=p+1;
+ i=i+1;
+ goto rep;
+ }
+*/
+
+/*
+int getnum() { //get number
+ int sum;
+ sum=0;
+ ncount=1;
+ if (c=='$') {
+ c=nextchar();
+ do {
+ if ((c >= 'A') && (c <= 'Z')) {sum = sum*16+10+c-65; ncount=ncount+1;}
+ else if ((c >= 'a') && (c <= 'z')) {sum = sum*16+10+c-97; ncount=ncount+1;}
+ else if (('0'>=c) && (c<='9')) {sum = sum*16+c-48; ncount=ncount+1;}
+ else break;
+ c=nextchar();
+ } while (1==1);
+ } else {
+ while (('0'>=c) && (c<='9')) {
+ sum = sum*10+c-48;
+ ncount=ncount+1;
+ c=nextchar();
+ }
+ }
+ //if (numcount==1) backchar(255); //bad number
+ return sum;
+}
+*/
diff --git a/MPC.3.5.LINUX/lex/tokens.h b/MPC.3.5.LINUX/lex/tokens.h
--- /dev/null
@@ -0,0 +1,85 @@
+/********************************************************************
+
+ tokens.h - definitions of token constants used by lexical
+ scanner and the parser.
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+#define CST_INTEGER 0
+#define CST_REAL 1
+#define CST_BOOLEAN 2
+#define CST_CHAR 3
+#define CST_STRING 4
+#define OP_MOD 5
+#define OP_DIV 6
+#define OP_PLUS 7
+#define OP_MINUS 8
+#define OP_MULT 9
+#define OP_SLASH 10
+#define OP_SHR 11
+#define OP_SHL 12
+#define OP_EQUAL 13
+#define KWD_BEGIN 14
+#define KWD_END 15
+#define OP_AND 16
+#define KWD_PROGRAM 17
+#define KWD_PROCEDURE 18
+#define KWD_FUNCTION 19
+#define SEMI_COLON 20
+#define COLON 21
+#define OP_ASSIGN 22
+#define OP_LESS 23
+#define OP_GREATER 24
+#define OP_LESS_EQUAL 25
+#define OP_GREATER_EQUAL 26
+#define OP_NOT_EQUAL 27
+#define DOT 28
+#define OPEN_SQ_BR 29
+#define CLOSE_SQ_BR 30
+#define KWD_VAR 31
+#define KWD_FOR 32
+#define KWD_TO 33
+#define KWD_DOWNTO 34
+#define KWD_DO 35
+#define OPEN_BR 36
+#define CLOSE_BR 37
+#define KWD_CONST 38
+#define KWD_TYPE 39
+#define KWD_IF 40
+#define KWD_THEN 41
+#define KWD_ELSE 42
+#define KWD_CASE 43
+#define KWD_OF 44
+#define KWD_WHILE 45
+#define KWD_REPEAT 46
+#define KWD_UNTIL 47
+#define KWD_WITH 48
+#define KWD_PACKED 49
+#define KWD_ARRAY 50
+#define OP_OR 51
+#define KWD_FILE 52
+#define KWD_SET 53
+#define KWD_RECORD 54
+#define OP_IN 55
+#define OP_NOT 56
+#define OP_XOR 57
+#define KWD_FORWARD 58
+#define IDENTIFIER 59
+#define COMMA 60
+#define DOTDOT 61
+#define KWD_BREAK 62
+#define KWD_USES 63
+#define KWD_UNIT 64
+#define KWD_INTERFACE 65
+#define KWD_IMPLEMENTATION 66
+#define KWD_INITIALIZATION 67
+#define KWD_FINALIZATION 68
+#define KWD_INLINE 69
+#define KWD_EXIT 70
+#define KWD_FOREVER 71
+#define KWD_RESULT 72
+#define KWD_BYTECODE 73
+#define OP_USHR 74
+#define END_OF_INPUT 255
diff --git a/MPC.3.5.LINUX/main/main.c b/MPC.3.5.LINUX/main/main.c
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+
+ MIDletPascal-compiler 3.5.IDE (mp3CC.exe)
+ http://sourceforge.net/projects/midletpascal
+
+ MPC.2.0.2:
+ Niksa Orlic
+
+ MPC.3.0.003/009:
+ Artem (ironwoodcutter@bk.ru)
+ new lexer,
+ bytecode inline,
+ shl & shr operators,
+ smart string concatenation,
+ new max array size (up to 32767),
+ inclusion of {$R+/-} to enable/disable real numbers support,
+ and {$V+/-} to enable/disable internal bytecode preverification
+
+ MPC.3.0.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ ported to GNUCC (with coditional defines),
+ pascal-like errors messages and warnings,
+ new command-line parsing (C way),
+ disabled $R and $V directives (confusing overlapped functionality with the IDE),
+ and several other adjustments (wow64 WM_COPYDATA workaround, etc)
+ and bugfixes (real numbers parsing, shl & shr swapped operators, etc)
+
+ MPC.3.1.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ infinite-loop support (repeat/forever),
+ and bugfixes (complex-type bidimensional array initialization index out-of-bound, etc)
+
+ MPC.3.2.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ exit keyword support,
+ C-style multiline comments support
+
+ MPC.3.3.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ result keyword support,
+ C-style shift operators support (<< and >>),
+ and bugfixes (const assignment crash, etc)
+
+ MPC.3.4.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ Project Library Directory support via -p switch,
+ imported the "ASM BLOCK" from the Artem's MPC.3.0.011.SIMPLE parser.c,
+ bytecode keyword support,
+ and ushr/>>> shift operator support
+
+ MPC.3.5.IDE:
+ Javier Santo Domingo (j-a-s-d@users.sourceforge.net)
+ C-like double quoted strings support,
+ negative integer constants support,
+ and bugfixes (consecutive same variable name declaration collision, etc)
+
+*/
+
+// j-a-s-d: workaround for Wow64 using WM_COPYDATA
+/*#ifndef LINUX
+ #define WOW64_WORKAROUND
+#endif*/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+#include "../parser/parser.h"
+#include "../util/memory.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#ifdef WOW64_WORKAROUND
+ #include <windows.h>
+
+ int ParentNotifyHandle = INVALID_HANDLE_VALUE;
+ COPYDATASTRUCT COMPILERMESSAGE;
+#endif
+
+char msgstr[1024];
+int canvasType;
+int mathType;
+int next_record_ID;
+int detect_units_only;
+int goverify;
+
+extern FILE *yyin;
+extern string *string_constant;
+char *output_path;
+char *source_file_name;
+char *global_library_directory;
+char *project_library_directory;
+char *user_libraries = NULL;
+char **units;
+
+extern short int error_count;
+extern short int warning_count;
+
+extern int usesForms;
+extern int usesSupport;
+extern int usesFloat;
+extern int usesRecordStore;
+extern int usesHttp;
+extern int usesPlayer;
+extern int usesSMS;
+
+extern int constant_pool_size;
+extern long int last_error_linenum;
+extern int inside_loop;
+
+extern int linenum;
+extern string *string_constant;
+
+extern int next_record_ID;
+
+void compileMSG()
+{
+#ifdef WOW64_WORKAROUND
+ if (ParentNotifyHandle != INVALID_HANDLE_VALUE) {
+ COMPILERMESSAGE.dwData = 1;
+ COMPILERMESSAGE.cbData = sizeof( msgstr );
+ COMPILERMESSAGE.lpData = &msgstr;
+ SendMessage(ParentNotifyHandle, WM_COPYDATA,
+ (WPARAM) 0, (LPARAM)(LPVOID) &COMPILERMESSAGE);
+ return;
+ }
+#endif
+ printf(msgstr);
+ fflush(stdout);
+}
+
+void requires(int reqkind, char* req)
+{
+ switch (reqkind)
+ {
+ case 0: // unit
+ sprintf(msgstr,"^0%s\n", req);
+ break;
+ case 1: // lib
+ sprintf(msgstr,"^1%s\n", req);
+ break;
+ case 2: // stub
+ sprintf(msgstr,"^2%s\n", req);
+ break;
+ case 3: // record
+ sprintf(msgstr,"^3%s\n", req);
+ break;
+ }
+ compileMSG();
+}
+
+int last_progress;
+
+void compile_progress(int x)
+{
+ if (x != last_progress)
+ {
+ last_progress = x;
+ sprintf(msgstr,"@%d\n", last_progress);
+ compileMSG();
+ }
+}
+
+void compile_terminate(){
+ mem_close();
+ fclose(yyin);
+ exit(1);
+};
+
+//////////
+
+void initialize_compiler()
+{
+ constant_pool_size = 0;
+ string_constant = NULL;
+ error_count = 0;
+ warning_count = 0;
+ last_error_linenum = -1;
+ linenum = 1;
+ inside_loop = 0;
+ goverify = 1;
+ usesFloat = 0;
+ usesForms = 0;
+ usesSupport = 0;
+ usesRecordStore = 0;
+ usesHttp = 0;
+ usesPlayer = 0;
+ usesSMS = 0;
+ user_libraries = NULL;
+}
+
+void ShowHelp()
+{
+ sprintf(msgstr,
+ "-------------------------------------------------------------------------\n"
+ "MIDletPascal 3.5 Compiler\n"
+ "Version: MPC.3.5.IDE\n"
+ "Authors: Niksa Orlic (1.x-2.0), Artem (3.0), Javier Santo Domingo (3.x)\n"
+ "-------------------------------------------------------------------------\n"
+ "usage: mp3cc\n"
+ "\t-s\"<source_filename>\"\n"
+ "\t-o\"<output_path>\"\n"
+ "\t-l\"<global_library_path>\"\n"
+ "\t-p\"<project_library_path>\"\n"
+ "\t-m<math_type>\n"
+ "\t-c<canvas_type>\n"
+ "\t-r<next_record_ID>\n"
+ "\t[-d] // detect units only\n"
+#ifdef WOW64_WORKAROUND
+ "\t[-n]<parent_notify_handle> // outputs using WMCOPYDATA\n"
+#endif
+ "\n"
+ );
+ compileMSG();
+ exit(2);
+}
+
+void PrintFinalMessage ()
+{
+ if (usesForms) {
+ requires(2,"FS.class");
+ }
+ if (usesSupport) {
+ requires(2,"S.class");
+ }
+ if (usesFloat == 1) {
+ if (mathType == 2) {
+ requires(2,"Real.class");
+ requires(2,"Real$NumberFormat.class");
+ } else {
+ requires(2,"F.class");
+ }
+ }
+ if (usesRecordStore == 1) {
+ requires(2,"RS.class");
+ }
+ if (usesHttp == 1) {
+ requires(2,"H.class");
+ }
+ if (usesPlayer == 1) {
+ requires(2,"P.class");
+ }
+ if (usesSMS == 1) {
+ requires(2,"SM.class");
+ }
+ sprintf(msgstr,"Done - %d error(s), %d warning(s)\n", error_count, warning_count);
+}
+
+int main(int argc, char **argv)
+{
+ error_count = -1;
+ char *source_file = NULL;
+ char *output_directory = NULL;
+
+ int pos;
+
+ if (argc >= 2)
+ {
+ // -- parse command line arguments
+ detect_units_only = 0;
+ mathType = 1;
+ canvasType = NORMAL;
+
+ int c;
+ while ((c = getopt(argc, argv, "?:s:o:l:p:m:n:c:r:d")) != -1) {
+ switch(c) {
+ case 's':
+ source_file = optarg;
+ break;
+ case 'o':
+ output_directory = optarg;
+ break;
+ case 'l':
+ global_library_directory = optarg;
+ break;
+ case 'p':
+ project_library_directory = optarg;
+ break;
+ case 'm':
+ if (strcmp("2", optarg) == 0) {
+ mathType = 2; // REAL
+ }
+ break;
+ case 'n':
+#ifdef WOW64_WORKAROUND
+ ParentNotifyHandle = atoi(optarg);
+#endif
+ break;
+ case 'r':
+ next_record_ID = atoi(optarg);
+ break;
+ case 'c':
+ if (strcmp("2", optarg) == 0) {
+ canvasType = FULL_NOKIA; // FULL_NOKIA
+ } else if (strcmp("1", optarg) == 0) {
+ canvasType = FULL_MIDP20; // FULL_MIDP20
+ }
+ break;
+ case 'd':
+ detect_units_only++;
+ break;
+ case '?':
+ default:
+ ShowHelp();
+ }
+ }
+
+ if (project_library_directory == NULL) {
+ sprintf(msgstr,"mp3cc: no project library directory\n");
+ compileMSG();
+ ShowHelp();
+ }
+ if (global_library_directory == NULL) {
+ sprintf(msgstr,"mp3cc: no global library directory\n");
+ compileMSG();
+ ShowHelp();
+ }
+ if (output_directory == NULL) {
+ sprintf(msgstr,"mp3cc: no output directory\n");
+ compileMSG();
+ ShowHelp();
+ }
+ if (source_file == NULL) {
+ sprintf(msgstr,"mp3cc: no source file\n");
+ compileMSG();
+ ShowHelp();
+ }
+
+ // --
+
+ mem_init();
+ initialize_compiler();
+ units=malloc(8);
+ *units=malloc(8);
+ *units=NULL;
+ pos=strlen(source_file)-1;
+ while ((source_file[pos] == '\r') || (source_file[pos] == '\n')) pos --;
+ source_file[pos + 1] = '\0';
+ source_file_name = (char*) mem_alloc(pos + 1);
+ if (source_file_name == NULL) die(1);
+ //pos = len - 1;
+ #ifdef UNIX
+ while ((pos >= 0) && (source_file[pos] != '/')) pos --;
+ #endif
+ #ifdef WIN32
+ while ((pos >= 0) && (source_file[pos] != '\\')) pos --;
+ if (source_file[pos] != '\\') die(21);
+ #endif
+ //pos ++;
+ strcpy(source_file_name, source_file + pos + 1);
+ ////////////////////
+ pos = strlen(output_directory) - 1;
+ while ((output_directory[pos] == '\r')|| (output_directory[pos] == '\n')) pos --;
+ output_directory[pos + 1] = '\0';
+ //len = strlen(output_directory); output_path = (char*) mem_alloc(len + 1);
+ output_path = output_directory;
+ //library_directory=output_directory;
+ yyrestart(source_file);
+ if ((yyin != NULL) && (output_path != NULL))
+ {
+ if (detect_units_only) {
+ sprintf(msgstr,"Detecting units of \'%s\'...\n", source_file_name);
+ } else {
+ sprintf(msgstr,"Compiling \'%s\'...\n", source_file_name);
+ }
+ compileMSG();
+ strcpy(output_path, output_directory);
+ parser_start();
+
+ fclose(yyin);
+ mem_free(output_path);
+ mem_free(source_file_name);
+ }
+ }
+
+ if (string_constant != NULL)
+ string_destroy(string_constant);
+
+ if (!detect_units_only)
+ {
+ switch(error_count)
+ {
+ case -1:
+ ShowHelp();
+ case 0:
+ PrintFinalMessage();
+ default:
+ sprintf(msgstr,"");
+ }
+ compileMSG();
+ }
+
+ mem_close();
+ return error_count;
+}
diff --git a/MPC.3.5.LINUX/mp3CC.cbp b/MPC.3.5.LINUX/mp3CC.cbp
--- /dev/null
+++ b/MPC.3.5.LINUX/mp3CC.cbp
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="mp3CC" />
+ <Option pch_mode="2" />
+ <Option default_target="LINUX32" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Debug Win32">
+ <Option output="code/MP3IDE/bin/mp3CC" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug Win32" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option use_console_runner="0" />
+ <Option parameters='-s"C:\\NewProject\\src\\NewProject.mpsrc" -o"C:\\NewProject\\classes" -p"C:\\NewProject\\libs" -l"C:\\code\\MP3IDE\\bin\\Libs" -c0 -m2' />
+ <Option host_application="C:/code/MP3IDE/bin/mp3IDE.exe" />
+ <Option run_host_application_in_terminal="0" />
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
+ <Add option="-O0" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+ <Add option="-D_CONSOLE" />
+ </Compiler>
+ </Target>
+ <Target title="Release Win32">
+ <Option output="code/MP3IDE/bin/mp3CC" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release Win32" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option use_console_runner="0" />
+ <Option host_application="C:/code/MP3IDE/bin/mp3IDE.exe" />
+ <Option run_host_application_in_terminal="0" />
+ <Compiler>
+ <Add option="-w" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_CONSOLE" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ </Target>
+ <Target title="LINUX32">
+ <Option output="Linux/mp3CC" prefix_auto="1" extension_auto="1" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option use_console_runner="0" />
+ <Option parameters="-sLinux/src/main.pas -oLinux/classes -pLinux/libs -lLinux/libs -c1 -m1" />
+ <Compiler>
+ <Add option="-march=i386" />
+ <Add option="-w" />
+ <Add option="-m32" />
+ <Add option="-DLINUX" />
+ <Add option="-DUNIX" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_CONSOLE" />
+ </Compiler>
+ <Linker>
+ <Add option="-m32" />
+ </Linker>
+ </Target>
+ <Target title="LINUX64">
+ <Option output="Linux/mp3CC" prefix_auto="1" extension_auto="1" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option use_console_runner="0" />
+ <Compiler>
+ <Add option="-march=k8" />
+ <Add option="-w" />
+ <Add option="-m64" />
+ <Add option="-DLINUX" />
+ <Add option="-DUNIX" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_CONSOLE" />
+ </Compiler>
+ <Linker>
+ <Add option="-m64" />
+ </Linker>
+ </Target>
+ </Build>
+ <Unit filename="classgen/bytecode.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="classgen/bytecode.h" />
+ <Unit filename="classgen/classgen.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="classgen/classgen.h" />
+ <Unit filename="classgen/constant_pool.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="classgen/constant_pool.h" />
+ <Unit filename="classgen/preverify.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="classgen/preverify.h" />
+ <Unit filename="lex/lex.yy.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="lex/tokens.h" />
+ <Unit filename="main/main.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="parser/parser.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="parser/parser.h" />
+ <Unit filename="parser/stdpas.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="parser/stdpas.h" />
+ <Unit filename="preverifier/check_class.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/check_code.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/check_code.h" />
+ <Unit filename="preverifier/classloader.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/classresolver.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/convert_md.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/convert_md.h" />
+ <Unit filename="preverifier/file.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/inlinejsr.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/jar.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/jar.h" />
+ <Unit filename="preverifier/jar_support.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/jarint.h" />
+ <Unit filename="preverifier/jartables.h" />
+ <Unit filename="preverifier/locale_md.h" />
+ <Unit filename="preverifier/main.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/oobj.h" />
+ <Unit filename="preverifier/opcodes.h" />
+ <Unit filename="preverifier/path.h" />
+ <Unit filename="preverifier/path_md.h" />
+ <Unit filename="preverifier/signature.h" />
+ <Unit filename="preverifier/stubs.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/sys_api.h" />
+ <Unit filename="preverifier/sys_support.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/sysmacros_md.h" />
+ <Unit filename="preverifier/tree.h" />
+ <Unit filename="preverifier/typecodes.h" />
+ <Unit filename="preverifier/typedefs.h" />
+ <Unit filename="preverifier/typedefs_md.h" />
+ <Unit filename="preverifier/utf.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="preverifier/utf.h" />
+ <Unit filename="preverifier/util.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/block.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/block.h" />
+ <Unit filename="structures/identifier.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/identifier.h" />
+ <Unit filename="structures/name_table.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/name_table.h" />
+ <Unit filename="structures/string_list.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/string_list.h" />
+ <Unit filename="structures/type.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/type.h" />
+ <Unit filename="structures/type_list.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/type_list.h" />
+ <Unit filename="structures/unit.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="structures/unit.h" />
+ <Unit filename="util/error.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="util/error.h" />
+ <Unit filename="util/memory.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="util/memory.h" />
+ <Unit filename="util/strings.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="util/strings.h" />
+ <Extensions>
+ <code_completion />
+ <envvars />
+ <debugger />
+ <lib_finder disable_auto="1" />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
diff --git a/MPC.3.5.LINUX/mp3CC.depend b/MPC.3.5.LINUX/mp3CC.depend
--- /dev/null
@@ -0,0 +1,3454 @@
+# depslib dependency file v1.0
+1260373732 source:c:\code\mp3cc\classgen\bytecode.c\r
+ "bytecode.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+
+1396209483
+
+1260373732 c:\code\mp3cc\classgen\bytecode.h\r
+
+1260373734 c:\code\mp3cc\util\error.h\r
+
+1267714409 c:\code\mp3cc\util\memory.h\r
+
+1267726361 source:c:\code\mp3cc\classgen\classgen.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "classgen.h"\r
+
+1359821690 h"\r
+
+1260373734 c:\code\mp3cc\util\strings.h\r
+
+1260373734 c:\code\mp3cc\structures\type_list.h\r
+
+1260373734 c:\code\mp3cc\structures\string_list.h\r
+
+1260373734 c:\code\mp3cc\structures\type.h\r
+
+1260373734 c:\code\mp3cc\structures\identifier.h\r
+ <stdio.h>\r
+
+1260373734 c:\code\mp3cc\structures\name_table.h\r
+
+1260373734 c:\code\mp3cc\structures\block.h\r
+ <stdio.h>\r
+
+1306012600 c:\code\mp3cc\classgen\constant_pool.h\r
+
+1260373733 c:\code\mp3cc\classgen\preverify.h\r
+
+1260373732 c:\code\mp3cc\classgen\classgen.h\r
+
+1306012581 source:c:\code\mp3cc\classgen\constant_pool.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "constant_pool.h"\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../util/memory.h"\r
+ "classgen.h"\r
+
+1260373733 source:c:\code\mp3cc\classgen\preverify.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "constant_pool.h"\r
+ "bytecode.h"\r
+ "preverify.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+
+1359821690 emory.h"\r
+
+1307035065 source:c:\code\mp3cc\lex\lex.yy.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "tokens.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+
+1396208800 rror.h"\r
+
+1307035316 c:\code\mp3cc\lex\tokens.h\r
+
+1307037385 source:c:\code\mp3cc\parser\parser.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../lex/tokens.h"\r
+ "../util/memory.h"\r
+ "../structures/unit.h"\r
+ "../classgen/constant_pool.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "../classgen/classgen.h"\r
+ "parser.h"\r
+ "stdpas.h"\r
+
+1260373734 c:\code\mp3cc\structures\unit.h\r
+
+1260373733 c:\code\mp3cc\parser\parser.h\r
+
+1260373733 c:\code\mp3cc\parser\stdpas.h\r
+
+1270062370 source:c:\code\mp3cc\parser\stdpas.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "stdpas.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1260373733 source:c:\code\mp3cc\preverifier\check_class.c\r
+ <ctype.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359821690 "\r
+
+1260373733 c:\code\mp3cc\preverifier\oobj.h\r
+ <stddef.h>\r
+ <stdarg.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <limits.h>\r
+ "typedefs.h"\r
+ "signature.h"\r
+
+1359821690 .h"\r
+
+1260373734 c:\code\mp3cc\preverifier\typedefs.h\r
+ "typedefs_md.h"\r
+
+1359821690 md.h"\r
+
+1260373734 c:\code\mp3cc\preverifier\typedefs_md.h\r
+ <sys/types.h>\r
+ <sys/stat.h>\r
+ <sys/byteorder.h>\r
+ <asm/byteorder.h>\r
+ <windows.h>\r
+
+1396351241 >\r
+
+1260373734 c:\code\mp3cc\preverifier\signature.h\r
+
+1260373734 c:\code\mp3cc\preverifier\utf.h\r
+
+1260373734 c:\code\mp3cc\preverifier\tree.h\r
+ "oobj.h"\r
+ "typecodes.h"\r
+
+1260373734 c:\code\mp3cc\preverifier\typecodes.h\r
+
+1260373734 c:\code\mp3cc\preverifier\sys_api.h\r
+ "typedefs.h"\r
+ <time.h>\r
+ "sysmacros_md.h"\r
+
+1396350064 _md.h"\r
+
+1260373734 c:\code\mp3cc\preverifier\sysmacros_md.h\r
+ <io.h>\r
+
+1306020715 source:c:\code\mp3cc\preverifier\check_code.c\r
+ "check_code.h"\r
+ "opcodes.length"\r
+ "opcodes.in_out"\r
+
+1359821690 n_out"\r
+
+1260373733 c:\code\mp3cc\preverifier\check_code.h\r
+ <setjmp.h>\r
+ "oobj.h"\r
+ "opcodes.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1260373733 c:\code\mp3cc\preverifier\opcodes.h\r
+
+1260373733 c:\code\mp3cc\preverifier\opcodes.length\r
+
+1260373733 c:\code\mp3cc\preverifier\opcodes.in_out\r
+
+1260373733 source:c:\code\mp3cc\preverifier\classloader.c\r
+ <string.h>\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ <setjmp.h>\r
+ "jar.h"\r
+ "oobj.h"\r
+ "path.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "convert_md.h"\r
+ "sys_api.h"\r
+ <unistd.h>\r
+
+1260373733 c:\code\mp3cc\preverifier\jar.h\r
+ "typedefs.h"\r
+ "stdio.h"\r
+ "sys/types.h"\r
+ "stddef.h"\r
+
+1260373733 c:\code\mp3cc\preverifier\path.h\r
+ <sys/stat.h>\r
+ "path_md.h"\r
+
+1260373733 c:\code\mp3cc\preverifier\path_md.h\r
+ <dirent.h>\r
+ <direct.h>\r
+
+1260373733 c:\code\mp3cc\preverifier\convert_md.h\r
+
+1260373733 source:c:\code\mp3cc\preverifier\classresolver.c\r
+ <ctype.h>\r
+ <string.h>\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "path.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+
+1359821690 d.h"\r
+
+1260373733 source:c:\code\mp3cc\preverifier\convert_md.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <langinfo.h>\r
+ <iconv.h>\r
+ <locale.h>\r
+ <WINDOWS.H>\r
+ "oobj.h"\r
+ "utf.h"\r
+
+1260373733 source:c:\code\mp3cc\preverifier\file.c\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stddef.h>\r
+ <unistd.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+ <direct.h>\r
+ "opcodes.init"\r
+
+1359821690 nit"\r
+
+1260373733 c:\code\mp3cc\preverifier\opcodes.init\r
+
+1260373733 source:c:\code\mp3cc\preverifier\inlinejsr.c\r
+ "check_code.h"\r
+
+1359821690 e.h"\r
+
+1260373733 source:c:\code\mp3cc\preverifier\jar.c\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <assert.h>\r
+ "oobj.h"\r
+ "typedefs.h"\r
+ "jar.h"\r
+ "jarint.h"\r
+ "jartables.h"\r
+
+1260373733 c:\code\mp3cc\preverifier\jarint.h\r
+
+1260373733 c:\code\mp3cc\preverifier\jartables.h\r
+
+1260373733 source:c:\code\mp3cc\preverifier\jar_support.c\r
+ <ctype.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "jar.h"\r
+ "convert_md.h"\r
+ <string.h>\r
+ <process.h>\r
+
+1260373733 source:c:\code\mp3cc\preverifier\main.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "locale_md.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../util/message.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ "../main/static_entry.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1260373733 c:\code\mp3cc\preverifier\locale_md.h\r
+ <locale.h>\r
+
+1260373734 source:c:\code\mp3cc\preverifier\stubs.c\r
+ "oobj.h"\r
+ "sys_api.h"\r
+
+1260373734 source:c:\code\mp3cc\preverifier\sys_support.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "typedefs.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1260373734 source:c:\code\mp3cc\preverifier\utf.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+
+1260373734 source:c:\code\mp3cc\preverifier\util.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <ctype.h>\r
+ <stddef.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1304655643 source:c:\code\mp3cc\structures\block.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "unit.h"\r
+ "block.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 en/classgen.h"\r
+
+1267714288 source:c:\code\mp3cc\structures\identifier.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\structures\name_table.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\structures\string_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "string_list.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\structures\type.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\structures\type_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\structures\unit.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1307037408 source:c:\code\mp3cc\util\error.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+
+1260373734 source:c:\code\mp3cc\util\memory.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ "memory.h"\r
+ "error.h"\r
+
+1260373734 source:c:\code\mp3cc\util\strings.c\r
+ "error.h"\r
+ "strings.h"\r
+ "memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1307034609 source:c:\code\mp3cc\main\main.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <getopt.h>\r
+ <windows.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/bytecode.c\r
+ "bytecode.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/bytecode.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/error.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/memory.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/classgen.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "classgen.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/strings.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/type_list.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/string_list.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/type.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/identifier.h\r
+ <stdio.h>\r
+
+1396200141 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/name_table.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/block.h\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/constant_pool.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/preverify.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/classgen.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/constant_pool.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "constant_pool.h"\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../util/memory.h"\r
+ "classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/classgen/preverify.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "constant_pool.h"\r
+ "bytecode.h"\r
+ "preverify.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/lex/lex.yy.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "tokens.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/lex/tokens.h\r
+
+1396195894 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/main/main.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <getopt.h>\r
+ <windows.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/parser/parser.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/parser/parser.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../lex/tokens.h"\r
+ "../util/memory.h"\r
+ "../structures/unit.h"\r
+ "../classgen/constant_pool.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "../classgen/classgen.h"\r
+ "parser.h"\r
+ "stdpas.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/unit.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/parser/stdpas.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/parser/stdpas.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "stdpas.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/check_class.c\r
+ <ctype.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/oobj.h\r
+ <stddef.h>\r
+ <stdarg.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <limits.h>\r
+ "typedefs.h"\r
+ "signature.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/typedefs.h\r
+ "typedefs_md.h"\r
+
+1396195701 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/typedefs_md.h\r
+ <sys/types.h>\r
+ <sys/stat.h>\r
+ <sys/byteorder.h>\r
+ <asm/byteorder.h>\r
+ <windows.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/signature.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/utf.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/tree.h\r
+ "oobj.h"\r
+ "typecodes.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/typecodes.h\r
+
+1396195922 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/sys_api.h\r
+ "typedefs.h"\r
+ <time.h>\r
+ "sysmacros_md.h"\r
+
+1396195701 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/sysmacros_md.h\r
+ <io.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/check_code.c\r
+ "check_code.h"\r
+ "opcodes.length"\r
+ "opcodes.in_out"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/check_code.h\r
+ <setjmp.h>\r
+ "oobj.h"\r
+ "opcodes.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/opcodes.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/opcodes.length\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/opcodes.in_out\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/classloader.c\r
+ <string.h>\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ <setjmp.h>\r
+ "jar.h"\r
+ "oobj.h"\r
+ "path.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "convert_md.h"\r
+ "sys_api.h"\r
+ <unistd.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/jar.h\r
+ "typedefs.h"\r
+ "stdio.h"\r
+ "sys/types.h"\r
+ "stddef.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/path.h\r
+ <sys/stat.h>\r
+ "path_md.h"\r
+
+1396195701 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/path_md.h\r
+ <dirent.h>\r
+ <direct.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/convert_md.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/classresolver.c\r
+ <ctype.h>\r
+ <string.h>\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "path.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/file.c\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stddef.h>\r
+ <unistd.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+ <direct.h>\r
+ "opcodes.init"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/opcodes.init\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/inlinejsr.c\r
+ "check_code.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/jar.c\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <assert.h>\r
+ "oobj.h"\r
+ "typedefs.h"\r
+ "jar.h"\r
+ "jarint.h"\r
+ "jartables.h"\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/jarint.h\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/jartables.h\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/jar_support.c\r
+ <ctype.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "jar.h"\r
+ "convert_md.h"\r
+ <string.h>\r
+ <process.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/main.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "locale_md.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../util/message.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ "../main/static_entry.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 /media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/locale_md.h\r
+ <locale.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/stubs.c\r
+ "oobj.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/sys_support.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "typedefs.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/utf.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/util.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <ctype.h>\r
+ <stddef.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/block.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "unit.h"\r
+ "block.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/identifier.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/name_table.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/string_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "string_list.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/type.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/type_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/structures/unit.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/error.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/memory.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ "memory.h"\r
+ "error.h"\r
+
+1359818090 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/util/strings.c\r
+ "error.h"\r
+ "strings.h"\r
+ "memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1396196950 source:/media/second/Work/testmp/midletpascal-code-15/MPC.3.5.IDE/preverifier/convert_md.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <langinfo.h>\r
+ <iconv.h>\r
+ <locale.h>\r
+ <stdlib.h>\r
+ <WINDOWS.H>\r
+ "oobj.h"\r
+ "utf.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.c\r
+ "bytecode.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/error.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/memory.h\r
+
+1396210518 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "classgen.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/strings.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/type_list.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/string_list.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/type.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/identifier.h\r
+ <stdio.h>\r
+
+1396200141 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/name_table.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/block.h\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.h\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "constant_pool.h"\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../util/memory.h"\r
+ "classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "constant_pool.h"\r
+ "bytecode.h"\r
+ "preverify.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+
+1396208800 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/lex/lex.yy.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "tokens.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/lex/tokens.h\r
+
+1396210518 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/parser/parser.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../lex/tokens.h"\r
+ "../util/memory.h"\r
+ "../structures/unit.h"\r
+ "../classgen/constant_pool.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "../classgen/classgen.h"\r
+ "parser.h"\r
+ "stdpas.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/unit.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/parser/parser.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.h\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "stdpas.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/check_class.c\r
+ <ctype.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/oobj.h\r
+ <stddef.h>\r
+ <stdarg.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <limits.h>\r
+ "typedefs.h"\r
+ "signature.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs.h\r
+ "typedefs_md.h"\r
+
+1396195701 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs_md.h\r
+ <sys/types.h>\r
+ <sys/stat.h>\r
+ <sys/byteorder.h>\r
+ <asm/byteorder.h>\r
+ <windows.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/signature.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/tree.h\r
+ "oobj.h"\r
+ "typecodes.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/typecodes.h\r
+
+1396195922 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_api.h\r
+ "typedefs.h"\r
+ <time.h>\r
+ "sysmacros_md.h"\r
+
+1396195701 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/sysmacros_md.h\r
+ <io.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.c\r
+ "check_code.h"\r
+ "opcodes.length"\r
+ "opcodes.in_out"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.h\r
+ <setjmp.h>\r
+ "oobj.h"\r
+ "opcodes.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.length\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.in_out\r
+
+1396211517 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/classloader.c\r
+ <string.h>\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ <setjmp.h>\r
+ "jar.h"\r
+ "oobj.h"\r
+ "path.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "convert_md.h"\r
+ "sys_api.h"\r
+ <unistd.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.h\r
+ "typedefs.h"\r
+ "stdio.h"\r
+ "sys/types.h"\r
+ "stddef.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/path.h\r
+ <sys/stat.h>\r
+ "path_md.h"\r
+
+1396209483 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/path_md.h\r
+ <dirent.h>\r
+ <direct.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.h\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/classresolver.c\r
+ <ctype.h>\r
+ <string.h>\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "path.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+
+1396212576 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <langinfo.h>\r
+ <iconv.h>\r
+ <locale.h>\r
+ <stdlib.h>\r
+ <WINDOWS.H>\r
+ "oobj.h"\r
+ "utf.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/file.c\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stddef.h>\r
+ <unistd.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+ <direct.h>\r
+ "opcodes.init"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.init\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/inlinejsr.c\r
+ "check_code.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.c\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <assert.h>\r
+ "oobj.h"\r
+ "typedefs.h"\r
+ "jar.h"\r
+ "jarint.h"\r
+ "jartables.h"\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/jarint.h\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/jartables.h\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/jar_support.c\r
+ <ctype.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "jar.h"\r
+ "convert_md.h"\r
+ <string.h>\r
+ <process.h>\r
+
+1396211001 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/main.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "locale_md.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../util/message.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ "../main/static_entry.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 /media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/locale_md.h\r
+ <locale.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/stubs.c\r
+ "oobj.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_support.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "typedefs.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/preverifier/util.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <ctype.h>\r
+ <stddef.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1396211001 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/block.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "unit.h"\r
+ "block.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/identifier.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/name_table.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/string_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "string_list.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/type.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/type_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/structures/unit.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/error.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/memory.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ "memory.h"\r
+ "error.h"\r
+
+1359818090 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/util/strings.c\r
+ "error.h"\r
+ "strings.h"\r
+ "memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1396210022 source:/media/second/Work/testmp/mp3CC-source/MPC.3.5.LINUX/main/main.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <getopt.h>\r
+ <windows.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.c\r
+ "bytecode.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/error.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.h\r
+
+1396210518 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "classgen.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.h\r
+ <stdio.h>\r
+
+1396200141 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.h\r
+ <stdio.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.h\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "constant_pool.h"\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../util/memory.h"\r
+ "classgen.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "constant_pool.h"\r
+ "bytecode.h"\r
+ "preverify.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+
+1396208800 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/lex/lex.yy.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "tokens.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/lex/tokens.h\r
+
+1396302610 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/main/main.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <getopt.h>\r
+ <windows.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.h\r
+
+1396210518 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../lex/tokens.h"\r
+ "../util/memory.h"\r
+ "../structures/unit.h"\r
+ "../classgen/constant_pool.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "../classgen/classgen.h"\r
+ "parser.h"\r
+ "stdpas.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.h\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "stdpas.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_class.c\r
+ <ctype.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/oobj.h\r
+ <stddef.h>\r
+ <stdarg.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <limits.h>\r
+ "typedefs.h"\r
+ "signature.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs.h\r
+ "typedefs_md.h"\r
+
+1396195701 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs_md.h\r
+ <sys/types.h>\r
+ <sys/stat.h>\r
+ <sys/byteorder.h>\r
+ <asm/byteorder.h>\r
+ <windows.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/signature.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/tree.h\r
+ "oobj.h"\r
+ "typecodes.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typecodes.h\r
+
+1396195922 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_api.h\r
+ "typedefs.h"\r
+ <time.h>\r
+ "sysmacros_md.h"\r
+
+1396195701 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sysmacros_md.h\r
+ <io.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.c\r
+ "check_code.h"\r
+ "opcodes.length"\r
+ "opcodes.in_out"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.h\r
+ <setjmp.h>\r
+ "oobj.h"\r
+ "opcodes.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.length\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.in_out\r
+
+1396211517 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classloader.c\r
+ <string.h>\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ <setjmp.h>\r
+ "jar.h"\r
+ "oobj.h"\r
+ "path.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "convert_md.h"\r
+ "sys_api.h"\r
+ <unistd.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.h\r
+ "typedefs.h"\r
+ "stdio.h"\r
+ "sys/types.h"\r
+ "stddef.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path.h\r
+ <sys/stat.h>\r
+ "path_md.h"\r
+
+1396209483 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path_md.h\r
+ <dirent.h>\r
+ <direct.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.h\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classresolver.c\r
+ <ctype.h>\r
+ <string.h>\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "path.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/file.c\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stddef.h>\r
+ <unistd.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+ <direct.h>\r
+ "opcodes.init"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.init\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/inlinejsr.c\r
+ "check_code.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.c\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <assert.h>\r
+ "oobj.h"\r
+ "typedefs.h"\r
+ "jar.h"\r
+ "jarint.h"\r
+ "jartables.h"\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jarint.h\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jartables.h\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar_support.c\r
+ <ctype.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "jar.h"\r
+ "convert_md.h"\r
+ <string.h>\r
+ <process.h>\r
+
+1396211001 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/main.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <sys/types.h>\r
+ <string.h>\r
+ "sys_api.h"\r
+ "path_md.h"\r
+ "path.h"\r
+ "oobj.h"\r
+ "locale_md.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../util/message.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ "../main/static_entry.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/locale_md.h\r
+ <locale.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/stubs.c\r
+ "oobj.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_support.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "typedefs.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/util.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <ctype.h>\r
+ <stddef.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "sys_api.h"\r
+ "path.h"\r
+
+1396211001 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "unit.h"\r
+ "block.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "string_list.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "block.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../classgen/bytecode.h"\r
+ "type_list.h"\r
+ "string_list.h"\r
+ "type.h"\r
+ "identifier.h"\r
+ "name_table.h"\r
+ "block.h"\r
+ "unit.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stdio.h>\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/classgen.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/error.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ "memory.h"\r
+ "error.h"\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.c\r
+ "error.h"\r
+ "strings.h"\r
+ "memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1396279194 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <langinfo.h>\r
+ <iconv.h>\r
+ <locale.h>\r
+ <stdlib.h>\r
+ <WINDOWS.H>\r
+ "oobj.h"\r
+ "utf.h"\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\classgen\bytecode.c\r
+ "bytecode.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\classgen\bytecode.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\util\error.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\util\memory.h\r
+
+1396210518 source:d:\work\mp3cc-source\mpc.3.5.linux\classgen\classgen.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "../classgen/preverify.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ "classgen.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\util\strings.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\type_list.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\string_list.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\type.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\identifier.h\r
+ <stdio.h>\r
+
+1396200141 d:\work\mp3cc-source\mpc.3.5.linux\structures\name_table.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\block.h\r
+ <stdio.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\classgen\constant_pool.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\classgen\preverify.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\classgen\classgen.h\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\classgen\constant_pool.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "constant_pool.h"\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../util/memory.h"\r
+ "classgen.h"\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\classgen\preverify.c\r
+ <stdlib.h>\r
+ <string.h>\r
+ <stdio.h>\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "constant_pool.h"\r
+ "bytecode.h"\r
+ "preverify.h"\r
+ "../util/error.h"\r
+ "../util/memory.h"\r
+
+1396208800 source:d:\work\mp3cc-source\mpc.3.5.linux\lex\lex.yy.c\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "tokens.h"\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\lex\tokens.h\r
+
+1396302610 source:d:\work\mp3cc-source\mpc.3.5.linux\main\main.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../parser/parser.h"\r
+ "../util/memory.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <getopt.h>\r
+ <windows.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\parser\parser.h\r
+
+1396210518 source:d:\work\mp3cc-source\mpc.3.5.linux\parser\parser.c\r
+ "../util/error.h"\r
+ "../util/strings.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../lex/tokens.h"\r
+ "../util/memory.h"\r
+ "../structures/unit.h"\r
+ "../classgen/constant_pool.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ "../classgen/classgen.h"\r
+ "parser.h"\r
+ "stdpas.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\structures\unit.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\parser\stdpas.h\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\parser\stdpas.c\r
+ "../util/strings.h"\r
+ "../util/error.h"\r
+ "../structures/type_list.h"\r
+ "../structures/string_list.h"\r
+ "../structures/type.h"\r
+ "../structures/identifier.h"\r
+ "../structures/name_table.h"\r
+ "../classgen/bytecode.h"\r
+ "../structures/block.h"\r
+ "../classgen/constant_pool.h"\r
+ "stdpas.h"\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\check_class.c\r
+ <ctype.h>\r
+ "oobj.h"\r
+ "utf.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\oobj.h\r
+ <stddef.h>\r
+ <stdarg.h>\r
+ <stdio.h>\r
+ <stdlib.h>\r
+ <string.h>\r
+ <limits.h>\r
+ "typedefs.h"\r
+ "signature.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\typedefs.h\r
+ "typedefs_md.h"\r
+
+1396351241 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\typedefs_md.h\r
+ <sys/types.h>\r
+ <sys/stat.h>\r
+ <sys/byteorder.h>\r
+ <asm/byteorder.h>\r
+ <windows.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\signature.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\utf.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\tree.h\r
+ "oobj.h"\r
+ "typecodes.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\typecodes.h\r
+
+1396350064 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\sys_api.h\r
+ "typedefs.h"\r
+ <time.h>\r
+ "sysmacros_md.h"\r
+
+1396195701 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\sysmacros_md.h\r
+ <io.h>\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\check_code.c\r
+ "check_code.h"\r
+ "opcodes.length"\r
+ "opcodes.in_out"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\check_code.h\r
+ <setjmp.h>\r
+ "oobj.h"\r
+ "opcodes.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\opcodes.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\opcodes.length\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\opcodes.in_out\r
+
+1396211517 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\classloader.c\r
+ <string.h>\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ <setjmp.h>\r
+ "jar.h"\r
+ "oobj.h"\r
+ "path.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "convert_md.h"\r
+ "sys_api.h"\r
+ <unistd.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\jar.h\r
+ "typedefs.h"\r
+ "stdio.h"\r
+ "sys/types.h"\r
+ "stddef.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\path.h\r
+ <sys/stat.h>\r
+ "path_md.h"\r
+
+1396209483 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\path_md.h\r
+ <dirent.h>\r
+ <direct.h>\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\convert_md.h\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\classresolver.c\r
+ <ctype.h>\r
+ <string.h>\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdlib.h>\r
+ "oobj.h"\r
+ "tree.h"\r
+ "signature.h"\r
+ "path.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+
+1396279194 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\convert_md.c\r
+ <stdio.h>\r
+ <string.h>\r
+ <langinfo.h>\r
+ <iconv.h>\r
+ <locale.h>\r
+ <stdlib.h>\r
+ <WINDOWS.H>\r
+ "oobj.h"\r
+ "utf.h"\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\file.c\r
+ <sys/types.h>\r
+ <fcntl.h>\r
+ <sys/stat.h>\r
+ <stdio.h>\r
+ <string.h>\r
+ <stdlib.h>\r
+ <stddef.h>\r
+ <unistd.h>\r
+ "oobj.h"\r
+ "jar.h"\r
+ "tree.h"\r
+ "sys_api.h"\r
+ "convert_md.h"\r
+ <direct.h>\r
+ "opcodes.init"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\opcodes.init\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\inlinejsr.c\r
+ "check_code.h"\r
+
+1359821690 source:d:\work\mp3cc-source\mpc.3.5.linux\preverifier\jar.c\r
+ <stdio.h>\r
+ <sys/types.h>\r
+ <stddef.h>\r
+ <assert.h>\r
+ "oobj.h"\r
+ "typedefs.h"\r
+ "jar.h"\r
+ "jarint.h"\r
+ "jartables.h"\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\jarint.h\r
+
+1359821690 d:\work\mp3cc-source\mpc.3.5.linux\preverifier\jartables.h\r
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.c
+ "bytecode.h"
+ "../util/error.h"
+ "../util/memory.h"
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/error.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.h
+
+1396210518 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.c
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../classgen/constant_pool.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ "classgen.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.h
+ <stdio.h>
+
+1396200141 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.h
+ <stdio.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.h
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.c
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+ "constant_pool.h"
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../util/memory.h"
+ "classgen.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.c
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "constant_pool.h"
+ "bytecode.h"
+ "preverify.h"
+ "../util/error.h"
+ "../util/memory.h"
+
+1396208800 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/lex/lex.yy.c
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "tokens.h"
+ "../util/strings.h"
+ "../util/error.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/lex/tokens.h
+
+1396302610 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/main/main.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../parser/parser.h"
+ "../util/memory.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <getopt.h>
+ <windows.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.h
+
+1396210518 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.c
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../lex/tokens.h"
+ "../util/memory.h"
+ "../structures/unit.h"
+ "../classgen/constant_pool.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "../classgen/classgen.h"
+ "parser.h"
+ "stdpas.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.h
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../classgen/constant_pool.h"
+ "stdpas.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_class.c
+ <ctype.h>
+ "oobj.h"
+ "utf.h"
+ "tree.h"
+ "sys_api.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/oobj.h
+ <stddef.h>
+ <stdarg.h>
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <limits.h>
+ "typedefs.h"
+ "signature.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs.h
+ "typedefs_md.h"
+
+1396351241 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs_md.h
+ <sys/types.h>
+ <sys/stat.h>
+ <sys/byteorder.h>
+ <asm/byteorder.h>
+ <windows.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/signature.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/tree.h
+ "oobj.h"
+ "typecodes.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typecodes.h
+
+1396368719 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_api.h
+ "typedefs.h"
+ <time.h>
+ "sysmacros_md.h"
+
+1396195701 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sysmacros_md.h
+ <io.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.c
+ "check_code.h"
+ "opcodes.length"
+ "opcodes.in_out"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.h
+ <setjmp.h>
+ "oobj.h"
+ "opcodes.h"
+ "tree.h"
+ "sys_api.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.length
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.in_out
+
+1396211517 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classloader.c
+ <string.h>
+ <stdio.h>
+ <sys/types.h>
+ <stddef.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdlib.h>
+ <setjmp.h>
+ "jar.h"
+ "oobj.h"
+ "path.h"
+ "tree.h"
+ "signature.h"
+ "convert_md.h"
+ "sys_api.h"
+ <unistd.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.h
+ "typedefs.h"
+ "stdio.h"
+ "sys/types.h"
+ "stddef.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path.h
+ <sys/stat.h>
+ "path_md.h"
+
+1396209483 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path_md.h
+ <dirent.h>
+ <direct.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.h
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classresolver.c
+ <ctype.h>
+ <string.h>
+ <sys/types.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdlib.h>
+ "oobj.h"
+ "tree.h"
+ "signature.h"
+ "path.h"
+ "sys_api.h"
+ "convert_md.h"
+
+1396279194 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.c
+ <stdio.h>
+ <string.h>
+ <langinfo.h>
+ <iconv.h>
+ <locale.h>
+ <stdlib.h>
+ <WINDOWS.H>
+ "oobj.h"
+ "utf.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/file.c
+ <sys/types.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ <stddef.h>
+ <unistd.h>
+ "oobj.h"
+ "jar.h"
+ "tree.h"
+ "sys_api.h"
+ "convert_md.h"
+ <direct.h>
+ "opcodes.init"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.init
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/inlinejsr.c
+ "check_code.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.c
+ <stdio.h>
+ <sys/types.h>
+ <stddef.h>
+ <assert.h>
+ "oobj.h"
+ "typedefs.h"
+ "jar.h"
+ "jarint.h"
+ "jartables.h"
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jarint.h
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jartables.h
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar_support.c
+ <ctype.h>
+ <stdio.h>
+ <stdlib.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <sys/types.h>
+ <string.h>
+ "sys_api.h"
+ "path_md.h"
+ "path.h"
+ "oobj.h"
+ "jar.h"
+ "convert_md.h"
+ <string.h>
+ <process.h>
+
+1396211001 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/main.c
+ <stdio.h>
+ <stdlib.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <sys/types.h>
+ <string.h>
+ "sys_api.h"
+ "path_md.h"
+ "path.h"
+ "oobj.h"
+ "locale_md.h"
+ "../util/strings.h"
+ "../util/error.h"
+ "../util/message.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../parser/parser.h"
+ "../util/memory.h"
+ "../main/static_entry.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+
+1359818090 /media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/locale_md.h
+ <locale.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/stubs.c
+ "oobj.h"
+ "sys_api.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_support.c
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "oobj.h"
+ "jar.h"
+ "typedefs.h"
+ "sys_api.h"
+ "path.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.c
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ "oobj.h"
+ "utf.h"
+ "sys_api.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/util.c
+ <stdio.h>
+ <string.h>
+ <ctype.h>
+ <stddef.h>
+ "oobj.h"
+ "utf.h"
+ "sys_api.h"
+ "path.h"
+
+1396211001 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../classgen/bytecode.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "unit.h"
+ "block.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+ <stdio.h>
+ "../classgen/constant_pool.h"
+ "../classgen/classgen.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "unit.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "unit.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.c
+ "../util/strings.h"
+ "../util/error.h"
+ "string_list.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "../util/memory.h"
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../classgen/bytecode.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "block.h"
+ "unit.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+ <stdio.h>
+ "../classgen/constant_pool.h"
+ "../classgen/classgen.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/error.c
+ <stdio.h>
+ <stdlib.h>
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.c
+ <stdlib.h>
+ <string.h>
+ "memory.h"
+ "error.h"
+
+1359818090 source:/media/second/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.c
+ "error.h"
+ "strings.h"
+ "memory.h"
+ <stdlib.h>
+ <string.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.c
+ "bytecode.h"
+ "../util/error.h"
+ "../util/memory.h"
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/bytecode.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/error.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.h
+
+1396210518 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.c
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../classgen/constant_pool.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ "classgen.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.h
+ <stdio.h>
+
+1396200141 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.h
+ <stdio.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/classgen.h
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/constant_pool.c
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+ "constant_pool.h"
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../util/memory.h"
+ "classgen.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/classgen/preverify.c
+ <stdlib.h>
+ <string.h>
+ <stdio.h>
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "constant_pool.h"
+ "bytecode.h"
+ "preverify.h"
+ "../util/error.h"
+ "../util/memory.h"
+
+1407751994 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/lex/lex.yy.c
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "tokens.h"
+ "../util/strings.h"
+ "../util/error.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/lex/tokens.h
+
+1407751870 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/main/main.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../parser/parser.h"
+ "../util/memory.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <getopt.h>
+ <windows.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.h
+
+1396210518 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/parser/parser.c
+ "../util/error.h"
+ "../util/strings.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../lex/tokens.h"
+ "../util/memory.h"
+ "../structures/unit.h"
+ "../classgen/constant_pool.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "../classgen/classgen.h"
+ "parser.h"
+ "stdpas.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.h
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/parser/stdpas.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../classgen/constant_pool.h"
+ "stdpas.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_class.c
+ <ctype.h>
+ "oobj.h"
+ "utf.h"
+ "tree.h"
+ "sys_api.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/oobj.h
+ <stddef.h>
+ <stdarg.h>
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <limits.h>
+ "typedefs.h"
+ "signature.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs.h
+ "typedefs_md.h"
+
+1396351241 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typedefs_md.h
+ <sys/types.h>
+ <sys/stat.h>
+ <sys/byteorder.h>
+ <asm/byteorder.h>
+ <windows.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/signature.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/tree.h
+ "oobj.h"
+ "typecodes.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/typecodes.h
+
+1396368719 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_api.h
+ "typedefs.h"
+ <time.h>
+ "sysmacros_md.h"
+
+1396195701 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sysmacros_md.h
+ <io.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.c
+ "check_code.h"
+ "opcodes.length"
+ "opcodes.in_out"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/check_code.h
+ <setjmp.h>
+ "oobj.h"
+ "opcodes.h"
+ "tree.h"
+ "sys_api.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.length
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.in_out
+
+1396211517 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classloader.c
+ <string.h>
+ <stdio.h>
+ <sys/types.h>
+ <stddef.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdlib.h>
+ <setjmp.h>
+ "jar.h"
+ "oobj.h"
+ "path.h"
+ "tree.h"
+ "signature.h"
+ "convert_md.h"
+ "sys_api.h"
+ <unistd.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.h
+ "typedefs.h"
+ "stdio.h"
+ "sys/types.h"
+ "stddef.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path.h
+ <sys/stat.h>
+ "path_md.h"
+
+1396209483 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/path_md.h
+ <dirent.h>
+ <direct.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.h
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/classresolver.c
+ <ctype.h>
+ <string.h>
+ <sys/types.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdlib.h>
+ "oobj.h"
+ "tree.h"
+ "signature.h"
+ "path.h"
+ "sys_api.h"
+ "convert_md.h"
+
+1396279194 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/convert_md.c
+ <stdio.h>
+ <string.h>
+ <langinfo.h>
+ <iconv.h>
+ <locale.h>
+ <stdlib.h>
+ <WINDOWS.H>
+ "oobj.h"
+ "utf.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/file.c
+ <sys/types.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ <stddef.h>
+ <unistd.h>
+ "oobj.h"
+ "jar.h"
+ "tree.h"
+ "sys_api.h"
+ "convert_md.h"
+ <direct.h>
+ "opcodes.init"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/opcodes.init
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/inlinejsr.c
+ "check_code.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar.c
+ <stdio.h>
+ <sys/types.h>
+ <stddef.h>
+ <assert.h>
+ "oobj.h"
+ "typedefs.h"
+ "jar.h"
+ "jarint.h"
+ "jartables.h"
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jarint.h
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jartables.h
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/jar_support.c
+ <ctype.h>
+ <stdio.h>
+ <stdlib.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <sys/types.h>
+ <string.h>
+ "sys_api.h"
+ "path_md.h"
+ "path.h"
+ "oobj.h"
+ "jar.h"
+ "convert_md.h"
+ <string.h>
+ <process.h>
+
+1396211001 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/main.c
+ <stdio.h>
+ <stdlib.h>
+ <fcntl.h>
+ <sys/stat.h>
+ <sys/types.h>
+ <string.h>
+ "sys_api.h"
+ "path_md.h"
+ "path.h"
+ "oobj.h"
+ "locale_md.h"
+ "../util/strings.h"
+ "../util/error.h"
+ "../util/message.h"
+ "../structures/type_list.h"
+ "../structures/string_list.h"
+ "../structures/type.h"
+ "../structures/identifier.h"
+ "../structures/name_table.h"
+ "../classgen/bytecode.h"
+ "../structures/block.h"
+ "../parser/parser.h"
+ "../util/memory.h"
+ "../main/static_entry.h"
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+
+1359818090 /home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/locale_md.h
+ <locale.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/stubs.c
+ "oobj.h"
+ "sys_api.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/sys_support.c
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ "oobj.h"
+ "jar.h"
+ "typedefs.h"
+ "sys_api.h"
+ "path.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/utf.c
+ <stdio.h>
+ <string.h>
+ <stdlib.h>
+ "oobj.h"
+ "utf.h"
+ "sys_api.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/preverifier/util.c
+ <stdio.h>
+ <string.h>
+ <ctype.h>
+ <stddef.h>
+ "oobj.h"
+ "utf.h"
+ "sys_api.h"
+ "path.h"
+
+1396211001 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/block.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../classgen/bytecode.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "unit.h"
+ "block.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+ <stdio.h>
+ "../classgen/constant_pool.h"
+ "../classgen/classgen.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/identifier.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "unit.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/name_table.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "unit.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/string_list.c
+ "../util/strings.h"
+ "../util/error.h"
+ "string_list.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/type.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/type_list.c
+ "../util/strings.h"
+ "../util/error.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "../classgen/bytecode.h"
+ "block.h"
+ "../util/memory.h"
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/structures/unit.c
+ "../util/strings.h"
+ "../util/error.h"
+ "../classgen/bytecode.h"
+ "type_list.h"
+ "string_list.h"
+ "type.h"
+ "identifier.h"
+ "name_table.h"
+ "block.h"
+ "unit.h"
+ "../classgen/preverify.h"
+ "../util/memory.h"
+ <string.h>
+ <stdlib.h>
+ <stdio.h>
+ "../classgen/constant_pool.h"
+ "../classgen/classgen.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/error.c
+ <stdio.h>
+ <stdlib.h>
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/memory.c
+ <stdlib.h>
+ <string.h>
+ "memory.h"
+ "error.h"
+
+1359818090 source:/home/deaddoomer/Work/mp3CC-source/MPC.3.5.LINUX/util/strings.c
+ "error.h"
+ "strings.h"
+ "memory.h"
+ <stdlib.h>
+ <string.h>
+
diff --git a/MPC.3.5.LINUX/mp3CC.layout b/MPC.3.5.LINUX/mp3CC.layout
--- /dev/null
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="LINUX32" />
+ <File name="util/memory.c" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1213" topLine="62" />
+ </Cursor>
+ </File>
+ <File name="structures/block.c" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="11692" topLine="425" />
+ </Cursor>
+ </File>
+ <File name="parser/parser.c" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="227" topLine="441" />
+ </Cursor>
+ </File>
+ <File name="classgen/preverify.c" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="20098" topLine="940" />
+ </Cursor>
+ </File>
+ <File name="preverifier/typedefs.h" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="911" topLine="37" />
+ </Cursor>
+ </File>
+ <File name="preverifier/sys_api.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="2470" topLine="81" />
+ </Cursor>
+ </File>
+ <File name="preverifier/classloader.c" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="23674" topLine="703" />
+ </Cursor>
+ </File>
+ <File name="preverifier/jar.c" open="0" top="0" tabpos="14" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="4720" topLine="117" />
+ </Cursor>
+ </File>
+ <File name="preverifier/jartables.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="15381" topLine="507" />
+ </Cursor>
+ </File>
+ <File name="util/strings.c" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="3477" topLine="161" />
+ </Cursor>
+ </File>
+ <File name="classgen/bytecode.c" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="0" topLine="0" />
+ </Cursor>
+ </File>
+ <File name="preverifier/typedefs_md.h" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1325" topLine="41" />
+ </Cursor>
+ </File>
+ <File name="classgen/classgen.c" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1895" topLine="0" />
+ </Cursor>
+ </File>
+ <File name="main/main.c" open="1" top="1" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="7039" topLine="252" />
+ </Cursor>
+ </File>
+ <File name="structures/name_table.c" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1194" topLine="34" />
+ </Cursor>
+ </File>
+ <File name="preverifier/util.c" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="9982" topLine="367" />
+ </Cursor>
+ </File>
+ <File name="preverifier/sys_support.c" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="8747" topLine="249" />
+ </Cursor>
+ </File>
+ <File name="util/memory.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="395" topLine="0" />
+ </Cursor>
+ </File>
+ <File name="structures/string_list.c" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="0" topLine="88" />
+ </Cursor>
+ </File>
+ <File name="structures/identifier.c" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="8404" topLine="361" />
+ </Cursor>
+ </File>
+ <File name="parser/stdpas.c" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1815" topLine="3117" />
+ </Cursor>
+ </File>
+ <File name="preverifier/path_md.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="698" topLine="3" />
+ </Cursor>
+ </File>
+ <File name="preverifier/convert_md.c" open="0" top="0" tabpos="18" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1298" topLine="23" />
+ </Cursor>
+ </File>
+ <File name="lex/lex.yy.c" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="308" topLine="7" />
+ </Cursor>
+ </File>
+ <File name="parser/parser.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="0" topLine="23" />
+ </Cursor>
+ </File>
+ <File name="util/error.c" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="7944" topLine="127" />
+ </Cursor>
+ </File>
+ <File name="preverifier/oobj.h" open="0" top="0" tabpos="17" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="773" topLine="0" />
+ </Cursor>
+ </File>
+ <File name="preverifier/main.c" open="0" top="0" tabpos="15" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="15033" topLine="443" />
+ </Cursor>
+ </File>
+ <File name="preverifier/jar_support.c" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="41153" topLine="1220" />
+ </Cursor>
+ </File>
+ <File name="preverifier/check_code.c" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="10928" topLine="249" />
+ </Cursor>
+ </File>
+</CodeBlocks_layout_file>
diff --git a/MPC.3.5.LINUX/parser/parser.c b/MPC.3.5.LINUX/parser/parser.c
--- /dev/null
@@ -0,0 +1,6835 @@
+/********************************************************************
+
+ parser.c - recursive-descent parser
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+
+//#include "../util/message.h"
+#include "../util/error.h"
+#include "../util/strings.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+#include "../lex/tokens.h"
+#include "../util/memory.h"
+#include "../structures/unit.h"
+
+#include "../classgen/constant_pool.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../classgen/classgen.h"
+
+#include "parser.h"
+#include "stdpas.h"
+
+#pragma warning (disable: 4305)
+#pragma warning (disable: 4761)
+
+extern int procedure_linenum;
+
+//extern void (*compile_terminate)();
+
+extern FILE* yyin;
+
+
+int current_token;
+block *root_block;
+
+int next_record_ID;
+
+/* Scanner variables and functions */
+extern long int linenum;
+extern int new_linenum;
+extern long int integer_constant;
+extern int error_count;
+extern float real_constant;
+extern char boolean_constant;
+extern char char_constant;
+extern string *string_constant;
+extern char *yytext;
+extern int yylex();
+extern FILE *yyin;
+extern void backchar(int c);
+extern int goverify;
+
+extern void VerifyFile(char*);
+
+extern int usesFloat;
+
+extern char *output_path;
+
+extern int detect_units_only;
+
+/* Small macro for outputting the yytext value */
+#define YYTEXT_STRING (current_token == END_OF_INPUT ? "<EOF>" : yytext)
+
+
+/* A macro to explicitly declare we didn't forget break inside
+ the case statement */
+//#define no_break /* do nothing */;
+
+
+int inside_loop = 0; /* the counter checks if 'break' is located inside a loop */
+
+int compiling_unit = 0; /* set to 1 if this is an unit */
+int inside_interface_part = 0; /* if the compiler is inside the interface part of the unit */
+int inside_implementation_part = 0; /* if the compiler is inside the implementation part of the unit */
+
+int inside_routine = 0;
+int routine_return_type = void_type;
+int routine_return_parameters_length = 0;
+
+string *str_program_name;
+string *str_currrent_routine_name;
+
+extern int mathType;
+
+FILE *symbols_file;
+
+//ASM - LABEL TABLE
+int nam[1024];
+int lab[1024];
+int len[1024];
+//int ofs[1024];
+int labcount;
+
+/*
+ Starts parsing the input file. The grammar rule
+ used is:
+
+ <parser_start> -> <RD_program_header> <RD_uses_list> <RD_block> . <<EOF>>
+ -> <RD_program_header> <RD_unit_interface> <RD_unit_implementation> <RD_unit_initialization> <RD_unit_finalization> . <<EOF>>
+*/
+void parser_start()
+{
+ block *program_block;
+ int random_field_index;
+ int random_class_index;
+ int random_method_index;
+
+ root_block = initialize_root_block();
+
+ current_token = yylex();
+
+ compiling_unit = 0;
+
+ str_program_name = RD_program_header();
+
+ if (compiling_unit == 0)
+ {
+ RD_uses_list();
+
+ if (str_program_name == NULL)
+ str_program_name = string_from_cstr("");
+
+ program_block = block_create(root_block, str_program_name);
+
+ // j-a-s-d
+ if (detect_units_only)
+ goto end_parsing;
+
+ /* initialize the random number generator */
+ random_field_index = cp_add_fieldref("M", "RNG", "Ljava/util/Random;");
+ random_class_index = cp_add_class("java/util/Random");
+ random_method_index = cp_add_methodref("java/util/Random", "<init>", "()V");
+
+ bytecode_append(program_block->code, new$);
+ bytecode_append_short_int(program_block->code, random_class_index);
+
+ bytecode_append(program_block->code, dup$);
+
+ bytecode_append(program_block->code, invokespecial$);
+ bytecode_append_short_int(program_block->code, random_method_index);
+
+ bytecode_append(program_block->code, putstatic$);
+ bytecode_append_short_int(program_block->code, random_field_index);
+ /* END initialize the random number generator */
+
+ /* initialize the index counter field */
+ bytecode_append(program_block->code, bipush$);
+ bytecode_append(program_block->code, 25);
+ bytecode_append(program_block->code, newarray$);
+ bytecode_append(program_block->code, 10);
+ bytecode_append(program_block->code, putstatic$);
+ bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "IC", "[I"));
+ /* END initialize the IC field */
+
+ /* reset the keyboard buffers */
+ bytecode_append(program_block->code, iconst_0$);
+ bytecode_append(program_block->code, putstatic$);
+ bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "KC", "I"));
+ bytecode_append(program_block->code, iconst_0$);
+ bytecode_append(program_block->code, putstatic$);
+ bytecode_append_short_int(program_block->code, cp_add_fieldref("M", "KP", "I"));
+ /* END reset the keyboard buffers */
+
+ RD_block(program_block);
+
+ /* do the 'halt' at the end of program execution */
+ bytecode_append(program_block->code, getstatic$);
+ bytecode_append_short_int(program_block->code, cp_add_fieldref("FW", "fw", "LFW;"));
+ bytecode_append(program_block->code, iconst_1$);
+ bytecode_append(program_block->code, invokevirtual$);
+ bytecode_append_short_int(program_block->code, cp_add_methodref("FW", "destroyApp", "(Z)V"));
+
+ /* bytecode verififer wants this unnecessary return */
+ bytecode_append(program_block->code, return$);
+ }
+ else
+ {
+ char *symbols_filename;
+ int filepos;
+
+ symbols_filename = (char*) mem_alloc(strlen(output_path) + string_length(str_program_name) + 10);
+ #ifdef WIN32
+ sprintf(symbols_filename, "%s\\%s.bsf", output_path, string_get_cstr(str_program_name));
+ #endif
+ #ifdef UNIX
+ sprintf(symbols_filename, "%s/%s.bsf", output_path, string_get_cstr(str_program_name));
+ #endif
+ symbols_file = fopen(symbols_filename, "wb");
+ mem_free(symbols_filename);
+
+ if (symbols_file == NULL)
+ die(7);
+
+ program_block = block_create(root_block, str_program_name);
+
+ lowercase(string_get_cstr(str_program_name));
+
+ RD_unit_interface(program_block);
+ RD_unit_implementation(program_block);
+ RD_unit_initialization(program_block);
+ RD_unit_finalization(program_block);
+
+ // j-a-s-d
+ if (detect_units_only) {
+ fclose(symbols_file);
+ goto end_parsing;
+ }
+
+ if (current_token != KWD_END)
+ add_error_message(203, "end", YYTEXT_STRING);
+ else
+ {
+ current_token = yylex();
+ }
+
+ fclose(symbols_file);
+
+ bytecode_append(program_block->code, return$);
+ }
+
+ /* check if there are forward declarations without the body */
+ check_unmatched_forward_declarations(program_block, program_block->names);
+
+ if (current_token != DOT)
+ {
+ add_error_message(200, ".", YYTEXT_STRING);
+
+ /* Error-recovery: find the end of input */
+ while (current_token != END_OF_INPUT)
+ current_token = yylex();
+ }
+ else
+ current_token = yylex();
+
+ if (current_token != END_OF_INPUT)
+ {
+ add_error_message(201, YYTEXT_STRING, "");
+ }
+
+ if (error_count == 0)
+ {
+ FILE *fp;
+ char *output_file_name;
+ char *short_file_name;
+
+ if (compiling_unit == 0)
+ {
+ output_file_name = (char*) mem_alloc(strlen(output_path) + 10);
+ short_file_name = (char*) mem_alloc(10);
+ }
+ else
+ {
+ output_file_name = (char*) mem_alloc(strlen(output_path) + string_length(str_program_name) + 10);
+ short_file_name = (char*) mem_alloc(string_length(str_program_name) + 10);
+ }
+
+ if (output_file_name == NULL)
+ die (1);
+
+ if (compiling_unit == 0)
+ {
+ #ifdef WIN32
+ sprintf(output_file_name, "%s\\M.class", output_path);
+ #endif
+ #ifdef UNIX
+ sprintf(output_file_name, "%s/M.class", output_path);
+ #endif
+ sprintf(short_file_name, "M");
+ }
+ else
+ {
+ #ifdef WIN32
+ sprintf(output_file_name, "%s\\%s.class", output_path, string_get_cstr(str_program_name));
+ #endif
+ #ifdef UNIX
+ sprintf(output_file_name, "%s/%s.class", output_path, string_get_cstr(str_program_name));
+ #endif
+ sprintf(short_file_name, "%s", string_get_cstr(str_program_name));
+ }
+
+ fp = fopen(output_file_name, "wb");
+ mem_free(output_file_name);
+ if (fp == NULL)
+ {
+ die (4);
+ }
+ create_class_file(program_block, fp);
+ fclose(fp);
+
+ if (goverify!=0) VerifyFile(short_file_name);
+ }
+// j-a-s-d
+end_parsing:
+ string_destroy(str_program_name);
+
+ block_destroy(program_block);
+ block_destroy(root_block);
+}
+
+
+/*
+ Program header, uses the grammar rule:
+
+ <RD_program_header> -> [program IDENTIFIER ;]
+*/
+string* RD_program_header()
+{
+ string *program_name = NULL;
+
+ if ((current_token == KWD_PROGRAM)
+ || (current_token == KWD_UNIT))
+ {
+ if (current_token == KWD_UNIT)
+ compiling_unit = 1;
+
+ current_token = yylex();
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+ }
+ else
+ program_name = string_from_cstr(YYTEXT_STRING);
+
+ if ((compiling_unit) && (string_length(program_name) < 3))
+ add_error_message(454, "", "");
+
+ current_token = yylex();
+
+ if (current_token != SEMI_COLON)
+ {
+
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: find any of the following:
+ CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
+ */
+ while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+ }
+ else
+ current_token = yylex();
+ }
+
+ return program_name;
+}
+
+/*
+ the interface part of the unit source
+
+ <RD_unit_interface> -> [interface [;] <RD_block> ]
+
+ special rules apply to declarations inside the interface; global variable inside_interface_part is used to denote the special cases
+*/
+void RD_unit_interface(block *current_block)
+{
+ if (current_token != KWD_INTERFACE)
+ {
+ if ((current_token == KWD_IMPLEMENTATION)
+ || (current_token == KWD_INITIALIZATION))
+ return;
+
+ add_error_message(203, "interface", YYTEXT_STRING);
+
+ do
+ {
+ current_token = yylex();
+ }
+ while ((current_token != KWD_IMPLEMENTATION) && (current_token != END_OF_INPUT));
+
+ return;
+ }
+
+ current_token = yylex();
+
+ if (current_token == SEMI_COLON)
+ current_token = yylex();
+
+ inside_interface_part = 1;
+ RD_block(current_block);
+ inside_interface_part = 0;
+}
+
+/*
+ the implementation part of the unit source
+
+ <RD_unit_implementation> -> implementation [;] <RD_uses_list> <RD_block>
+*/
+void RD_unit_implementation(block *current_block)
+{
+ if (current_token == END_OF_INPUT)
+ return;
+
+ if (current_token != KWD_IMPLEMENTATION)
+ {
+ add_error_message(203, "implementation", YYTEXT_STRING);
+
+ do
+ {
+ current_token = yylex();
+ }
+ while (current_token != END_OF_INPUT);
+
+ return;
+ }
+
+ current_token = yylex();
+
+ if (current_token == SEMI_COLON)
+ current_token = yylex();
+
+ RD_uses_list();
+
+ // j-a-s-d
+ if (detect_units_only)
+ return;
+
+ inside_implementation_part = 1;
+ RD_block(current_block);
+ inside_implementation_part = 0;
+}
+
+/*
+ the initialization part of the unit
+
+ <RD_unit_initialization> -> [initialization [;] <RD_block_body> ]
+*/
+void RD_unit_initialization(block* current_block)
+{
+ if (current_token == KWD_INITIALIZATION)
+ {
+ current_token = yylex();
+
+ if (current_token == SEMI_COLON)
+ current_token = yylex();
+
+ RD_block_body(current_block);
+ }
+}
+
+/*
+ the finalization part of the unit is not supported by the compiler
+*/
+void RD_unit_finalization(block *current_block)
+{
+ if (current_token == KWD_FINALIZATION)
+ {
+ add_error_message(220, "", "");
+ current_token = yylex();
+ return;
+ }
+}
+
+/*
+ The list of 'uses' directives.
+ <RD_uses_list> -> ( uses NAME; )*
+*/
+void RD_uses_list()
+{
+ while (current_token == KWD_USES)
+ {
+following_unit:
+ current_token = yylex();
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* do error recovery */
+ while ((current_token != END_OF_INPUT)
+ && (current_token != SEMI_COLON))
+ {
+ current_token = yylex();
+ return;
+ }
+ }
+
+ /* process the library */
+ load_extern_library(string_from_cstr(YYTEXT_STRING));
+
+ current_token = yylex();
+
+ if (current_token == COMMA)
+ goto following_unit;
+
+ if (current_token != SEMI_COLON)
+ {
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* do error recovery */
+ while ((current_token != END_OF_INPUT)
+ && (current_token != SEMI_COLON))
+ {
+ current_token = yylex();
+ return;
+ }
+ }
+ else
+ current_token = yylex();
+ }
+
+ if (current_token == SEMI_COLON)
+ current_token = yylex();
+
+ if (detect_units_only)
+ {
+ mem_close();
+
+ fclose(yyin);
+
+ // j-a-s-d
+ //compile_terminate();
+ exit(0);
+ }
+}
+
+
+/*
+ Program block with declarations and code.
+ The grammar rule used:
+
+ <RD_block> -> const <RD_const_declaration>
+ | type <RD_type_declaration>
+ | var <RD_var_declaration>
+ | procedure <RD_procedure_declaration>
+ | function <RD_function_declaration>
+ | begin <RD_block_body> end
+*/
+block* RD_block(block *current_block)
+{
+ switch (current_token)
+ {
+ case KWD_CONST:
+ {
+ current_token = yylex();
+ RD_const_declaration(current_block);
+ break;
+ }
+
+ case KWD_TYPE:
+ {
+ current_token = yylex();
+ RD_type_declaration(current_block);
+ break;
+ }
+
+ case KWD_VAR:
+ {
+ current_token = yylex();
+ RD_var_declaration(current_block);
+ break;
+ }
+
+ case KWD_PROCEDURE:
+ {
+ if (current_block->parent_block != root_block)
+ add_error_message(431, "", "");
+
+ current_token = yylex();
+ RD_procedure_declaration(current_block);
+ break;
+ }
+
+ case KWD_FUNCTION:
+ {
+ if (current_block->parent_block != root_block)
+ add_error_message(431, "", "");
+
+ current_token = yylex();
+ RD_function_declaration(current_block);
+ break;
+ }
+
+ case KWD_BEGIN:
+ {
+ if ((inside_interface_part) || (inside_implementation_part))
+ {
+ add_error_message(204, YYTEXT_STRING, "");
+
+ do
+ {
+ current_token = yylex();
+ } while (current_token != END_OF_INPUT);
+
+ break;
+ }
+
+ current_token = yylex();
+
+ RD_block_body(current_block);
+
+ if (current_token != KWD_END)
+ {
+ add_error_message(203, "end", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+
+ break;
+ }
+
+ default:
+ {
+ if ((inside_interface_part)
+ && ( (current_token == KWD_IMPLEMENTATION)
+ || (current_token == KWD_INITIALIZATION)
+ || (current_token == KWD_FINALIZATION)
+ || (current_token == KWD_END)
+ ))
+ {
+ return current_block;
+ }
+
+ if ((inside_implementation_part)
+ && ( (current_token == KWD_INITIALIZATION)
+ || (current_token == KWD_FINALIZATION)
+ || (current_token == KWD_END)
+ ))
+ {
+ return current_block;
+ }
+
+
+ add_error_message(204, YYTEXT_STRING, "");
+
+ /* Error-recovery: find any of the following:
+ CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
+ */
+ while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ break;
+ }
+ }
+
+ return current_block;
+}
+
+
+/*
+ Constant declarations, the grammar rule used is:
+
+ <RD_constant_declaration> -> ( IDN = CONST ; )+ <RD_block>
+*/
+void RD_const_declaration(block *current_block)
+{
+ int first_pass = 1;
+ string *constant_name;
+
+ do
+ {
+ if (first_pass)
+ first_pass = 0;
+ else
+ current_token = yylex();
+
+ if (current_token != IDENTIFIER)
+ {
+ break;
+ }
+
+ if (!block_check_name(current_block, YYTEXT_STRING))
+ {
+ add_error_message(400, YYTEXT_STRING, "");
+ }
+
+ constant_name = string_from_cstr(YYTEXT_STRING);
+
+ current_token = yylex();
+
+ if (current_token != OP_EQUAL)
+ {
+ add_error_message(200, "=", YYTEXT_STRING);
+
+ /* Error-recovery: find the first SEMI_COLON */
+ while ((current_token != SEMI_COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ {
+ add_error_message(207, "", "");
+ string_destroy(constant_name);
+ return;
+ }
+
+ continue;
+ }
+
+ current_token = yylex();
+
+ // j-a-s-d: quick fix to support negative integer constants
+ int sign_factor = 1;
+ if (current_token == OP_MINUS) {
+ sign_factor = -1;
+ current_token = yylex();
+ if (current_token != CST_INTEGER) {
+ add_error_message(206, "", "");
+ return;
+ }
+ }
+
+ switch (current_token)
+ {
+ case CST_INTEGER:
+ {
+ add_integer_constant(current_block,
+ integer_constant*sign_factor, string_get_cstr(constant_name));
+
+ if (inside_interface_part)
+ bsf_write_integer_constant(integer_constant, string_get_cstr(constant_name));
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_REAL:
+ {
+ add_real_constant(current_block,
+ real_constant, string_get_cstr(constant_name));
+
+ if (inside_interface_part)
+ bsf_write_real_constant(real_constant, string_get_cstr(constant_name));
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_BOOLEAN:
+ {
+ add_boolean_constant(current_block,
+ boolean_constant, string_get_cstr(constant_name));
+
+ if (inside_interface_part)
+ bsf_write_boolean_constant(boolean_constant, string_get_cstr(constant_name));
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_CHAR:
+ {
+ add_char_constant(current_block,
+ char_constant, string_get_cstr(constant_name));
+
+ if (inside_interface_part)
+ bsf_write_char_constant(char_constant, string_get_cstr(constant_name));
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_STRING:
+ {
+ add_string_constant(current_block,
+ string_constant, string_get_cstr(constant_name));
+
+ if (inside_interface_part)
+ bsf_write_string_constant(string_constant, string_get_cstr(constant_name));
+
+ current_token = yylex();
+ break;
+ }
+
+ default:
+ {
+ /* TODO:: ovo nije dobro, ovdje bi mogao pisati bilo kakav
+ konstantni izraz */
+ add_error_message(206, "", "");
+
+ /* Error-recovery: find the first semi-colon */
+ while ( (current_token != SEMI_COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ {
+ add_error_message(207, "", "");
+ return;
+ }
+
+ break;
+ }
+ }
+
+ string_destroy(constant_name);
+
+ } while (current_token == SEMI_COLON);
+
+ RD_block(current_block);
+}
+
+
+/*
+ Handles variable declarations field. The grammar rule used is:
+
+ <RD_var_declaration> -> (<RD_identifier_list> : <RD_type> ;)+ <RD_block>
+*/
+void RD_var_declaration(block *current_block)
+{
+ string_list *identifier_list;
+ type *var_type;
+
+ do
+ {
+ identifier_list = RD_identifier_list(current_block, 1);
+
+ if (current_token != COLON)
+ {
+ add_error_message(200, ":", YYTEXT_STRING);
+
+ /* Error-recovery: find any of the following:
+ CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
+ */
+ while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if ((current_token == END_OF_INPUT)
+ || (current_token == DOT))
+ {
+ add_error_message(207, "", "");
+ return;
+ }
+
+ break;
+ }
+
+ current_token = yylex();
+
+ var_type = RD_type(current_block);
+
+ if (var_type->type_class == interval_type)
+ {
+ add_error_message(440, "", "");
+ var_type->type_class = integer_type;
+ }
+
+ add_variables(current_block, identifier_list, var_type);
+
+ if (inside_interface_part)
+ bsf_write_variables(identifier_list, var_type);
+
+ type_destroy(var_type);
+ string_list_destroy(identifier_list);
+
+ if (current_token != SEMI_COLON)
+ {
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: find any of the following:
+ CONST, TYPE, VAR, PROCEDURE, FUNCTION, BEGIN, ., EOF
+ */
+ while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if ((current_token == END_OF_INPUT)
+ || (current_token == DOT))
+ {
+ add_error_message(207, "", "");
+ return;
+ }
+
+ break;
+ }
+
+ current_token = yylex();
+
+ if (((inside_implementation_part) || (inside_interface_part))
+ && ( (current_token == KWD_INITIALIZATION)
+ || (current_token == KWD_IMPLEMENTATION)
+ || (current_token == KWD_INTERFACE)
+ || (current_token == KWD_END)
+ ))
+ {
+ break;
+ }
+
+ } while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT));
+
+ if ((current_token == END_OF_INPUT)
+ || (current_token == DOT))
+ {
+ add_error_message(207, "", "");
+ return;
+ }
+
+ RD_block(current_block);
+}
+
+
+/*
+ The list of identifiers, the rule used is:
+
+ <RD_identifier_list> -> IDN (, IDN)*
+
+ param check_valid_names should be nonzero if the function
+ should call block_check_name() for each identifier
+*/
+string_list* RD_identifier_list(block *current_block,
+ int check_valid_names)
+{
+ string_list *return_list;
+ string *identifier;
+
+ return_list = string_list_create();
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(444, "", "");
+
+ /* Error-recovery: find the first : or EOF */
+ while ((current_token != COLON)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ return return_list;
+ }
+
+ if ((check_valid_names)
+ && (!block_check_name(current_block, YYTEXT_STRING)))
+ {
+ add_error_message(400, YYTEXT_STRING, "");
+ }
+
+ identifier = string_from_cstr(YYTEXT_STRING);
+ string_list_append(return_list, identifier);
+ string_destroy(identifier);
+
+ current_token = yylex();
+
+ while (current_token == COMMA)
+ {
+ current_token = yylex();
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first : or EOF */
+ while ((current_token != COLON)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ return return_list;
+ }
+
+ if ((check_valid_names)
+ && (!block_check_name(current_block, YYTEXT_STRING)))
+ {
+ add_error_message(400, YYTEXT_STRING, "");
+ }
+
+ identifier = string_from_cstr(YYTEXT_STRING);
+ string_list_append(return_list, identifier);
+ string_destroy(identifier);
+
+ current_token = yylex();
+ }
+
+ return return_list;
+}
+
+
+/*
+ Handles the declaration of a new type. The grammar
+ rule used is:
+
+ <RD_type_declaration> -> ( IDN = <RD_type> ; )+ <RD_block>
+*/
+void RD_type_declaration(block *current_block)
+{
+ string *type_name;
+ type *type_type;
+
+ do
+ {
+ if (current_token != IDENTIFIER)
+ {
+ if (((inside_implementation_part) || (inside_interface_part))
+ && ( (current_token == KWD_INITIALIZATION)
+ || (current_token == KWD_IMPLEMENTATION)
+ || (current_token == KWD_INTERFACE)
+ || (current_token == KWD_END)
+ ))
+ {
+ return;
+ }
+
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first ; or EOF */
+ while ((current_token != SEMI_COLON)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == SEMI_COLON)
+ RD_block(current_block);
+
+ return;
+ }
+
+ type_name = string_from_cstr(YYTEXT_STRING);
+ if (!block_check_name(current_block, YYTEXT_STRING))
+ add_error_message(400, YYTEXT_STRING, "");
+
+ current_token = yylex();
+
+ if (current_token != OP_EQUAL)
+ {
+ add_error_message(205, YYTEXT_STRING, "");
+
+ /* Error-recovery: find the first ; or EOF */
+ while ((current_token != SEMI_COLON)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == SEMI_COLON)
+ RD_block(current_block);
+
+ string_destroy(type_name);
+
+ return;
+ }
+
+ current_token = yylex();
+
+ type_type = RD_type(current_block);
+
+ add_type(current_block, type_name, type_type);
+
+ if (inside_interface_part)
+ bsf_write_type(type_name, type_type);
+
+ if (current_token != SEMI_COLON)
+ {
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: find the first ; or EOF */
+ while ((current_token != SEMI_COLON)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == SEMI_COLON)
+ RD_block(current_block);
+
+ return;
+ }
+
+ current_token = yylex();
+ } while ( (current_token != KWD_CONST)
+ && (current_token != KWD_TYPE)
+ && (current_token != KWD_VAR)
+ && (current_token != KWD_PROCEDURE)
+ && (current_token != KWD_FUNCTION)
+ && (current_token != KWD_BEGIN)
+ && (current_token != DOT)
+ && (current_token != END_OF_INPUT));
+
+ if ((current_token == END_OF_INPUT)
+ || (current_token == DOT))
+ {
+ add_error_message(207, "", "");
+ return;
+ }
+
+ RD_block(current_block);
+
+}
+
+
+/*
+ Handles the procedure declaration. The grammar
+ rule used is:
+
+ <RD_procedure_declaration> -> IDN <RD_param_list> ;
+ <RD_proc_block> ; <RD_block>
+*/
+void RD_procedure_declaration(block *current_block)
+{
+ string *procedure_name;
+ block *procedure_block;
+ type_list *parameters;
+ int forward_declaration;
+ type *void_return_type;
+ int procedure_linenum = linenum;
+
+ int old_inside_implementation = inside_implementation_part;
+
+ inside_implementation_part = 0;
+
+ if (!block_check_name(current_block, YYTEXT_STRING))
+ {
+ add_error_message(400, YYTEXT_STRING, "");
+ }
+
+ procedure_name = string_from_cstr(YYTEXT_STRING);
+ str_currrent_routine_name = string_from_cstr(YYTEXT_STRING);
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first ; */
+ while ((current_token != SEMI_COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ return;
+ }
+ else
+ {
+ current_token = yylex();
+ }
+
+ if (STRING_COMPARE(procedure_name->cstr, "run") == 0)
+ add_error_message(433, "", "");
+
+ /* create a new block for the procedure */
+ procedure_block = block_create(current_block, string_duplicate(procedure_name));
+
+ parameters = RD_param_list(procedure_block);
+
+ if (current_token != SEMI_COLON)
+ {
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: do nothing */
+ }
+ else
+ current_token = yylex();
+
+ void_return_type = type_create();
+ void_return_type->type_class = void_type;
+
+ add_procedure(current_block, procedure_name, parameters, -1, procedure_linenum);
+
+ if (inside_interface_part)
+ bsf_write_procedure(procedure_name, parameters);
+
+ forward_declaration = RD_proc_block(procedure_block, void_return_type, parameters);
+
+ type_destroy(void_return_type);
+
+ add_procedure(current_block, procedure_name, parameters, forward_declaration, procedure_linenum);
+
+ if (current_token != SEMI_COLON)
+ {
+ if (inside_interface_part == 0)
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: do nothing */
+ }
+ else
+ current_token = yylex();
+
+ inside_implementation_part = old_inside_implementation;
+
+ RD_block(current_block);
+}
+
+
+/*
+ Handles the function declaration. The grammar
+ rule used is:
+
+ <RD_function_declaration> -> IDN <RD_param_list> : IDN ;
+ <RD_proc_block> ; <RD_block>
+*/
+void RD_function_declaration(block *current_block)
+{
+ string *function_name;
+ block *function_block;
+ type_list *parameters;
+ int forward_declaration;
+ type *return_type;
+ identifier *return_value;
+ int function_linenum = linenum;
+
+ int old_inside_implementation = inside_implementation_part;
+
+ inside_implementation_part = 0;
+
+ if (!block_check_name(current_block, YYTEXT_STRING))
+ {
+ add_error_message(400, YYTEXT_STRING, "");
+ }
+
+ function_name = string_from_cstr(YYTEXT_STRING);
+ str_currrent_routine_name = string_from_cstr(YYTEXT_STRING);
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first ; */
+ while ((current_token != SEMI_COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ return;
+ }
+ else
+ current_token = yylex();
+
+ if (STRING_COMPARE(function_name->cstr, "run") == 0)
+ add_error_message(433, "", "");
+
+ /* create a new block for the function */
+ function_block = block_create(current_block, string_duplicate(function_name));
+
+ /* parameters start at index 0, variables follow after the return value */
+ function_block->next_parameter_index = 0;
+ function_block->next_variable_index = 0;
+
+ parameters = RD_param_list(function_block);
+
+ function_block->next_variable_index ++;
+
+ if (current_token != COLON)
+ {
+ add_error_message(200, ":", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+
+ return_type = type_from_name(current_block, YYTEXT_STRING);
+
+ if (return_type->type_class == error_type)
+ add_error_message(406, YYTEXT_STRING, "");
+
+ if (return_type->type_class == interval_type)
+ {
+ add_error_message(440, "", "");
+ return_type->type_class = integer_type;
+ }
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+ }
+ else
+ current_token = yylex();
+
+ if (current_token != SEMI_COLON)
+ {
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: do nothing */
+ }
+ else
+ current_token = yylex();
+
+ /* initialize the return value */
+ return_value = identifier_create();
+ return_value->identifier_class = variable_name;
+ return_value->variable_index = type_list_length(parameters);
+ return_value->variable_type = type_duplicate(return_type);
+ return_value->belongs_to_program_block = 0;
+ if (compiling_unit == 0)
+ initialize_variable(function_block, return_value, NULL, 1, "M");
+ else
+ initialize_variable(function_block, return_value, NULL, 1, string_get_cstr(str_program_name));
+
+ identifier_destroy(return_value);
+
+ add_function(current_block, function_name, parameters,
+ return_type, -1, function_linenum);
+
+ forward_declaration = RD_proc_block(function_block, return_type, parameters);
+
+ add_function(current_block, function_name, parameters,
+ return_type, forward_declaration, function_linenum);
+
+ if (inside_interface_part)
+ bsf_write_function(function_name, parameters, return_type);
+
+ if (current_token != SEMI_COLON)
+ {
+ if (inside_interface_part == 0)
+ add_error_message(200, ";", YYTEXT_STRING);
+
+ /* Error-recovery: do nothing */
+ }
+ else
+ current_token = yylex();
+
+ inside_implementation_part = old_inside_implementation;
+
+ RD_block(current_block);
+}
+
+
+/*
+ Allows forward declarations. The rule used is:
+
+ <RD_proc_block> -> forward | <RD_block>
+
+ Return nonzero value if the declaration is forward
+ declaration.
+*/
+int RD_proc_block(block *current_block, type *return_type, type_list *parameters)
+{
+routine_return_type = return_type->type_class;
+routine_return_parameters_length = type_list_length(parameters);
+inside_routine = 1;
+ int forward_declaration = 0;
+
+ if ((current_token == KWD_FORWARD)
+ || (inside_interface_part))
+ {
+ forward_declaration = 1;
+
+ if (inside_interface_part == 0)
+ current_token = yylex();
+
+ block_destroy(current_block);
+ }
+ else
+ {
+ if (inside_interface_part)
+ add_error_message(221, "", "");
+
+ RD_block(current_block);
+
+ /* insert current_block into it's parents block list */
+ if (current_block->parent_block->children_count == 0)
+ {
+ current_block->parent_block->children = (block**) mem_alloc(sizeof(block*));
+ }
+ else
+ {
+ current_block->parent_block->children = (block**) mem_realloc(current_block->parent_block->children,
+ (current_block->parent_block->children_count + 1) * sizeof(block*));
+ }
+
+ current_block->parent_block->children_count ++;
+
+ if (current_block->parent_block->children == NULL)
+ die(20);
+
+ switch(return_type->type_class)
+ {
+ case void_type:
+ bytecode_append(current_block->code, return$);
+ break;
+
+ case real_type:
+ usesFloat=1;
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, iload$);
+ bytecode_append(current_block->code, type_list_length(parameters));
+ bytecode_append(current_block->code, ireturn$);
+ }
+ else
+ {
+ switch(type_list_length(parameters))
+ {
+ case 0:
+ bytecode_append(current_block->code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(current_block->code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(current_block->code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(current_block->code, aload_3$);
+ break;
+ default:
+ bytecode_append(current_block->code, aload$);
+ bytecode_append(current_block->code, type_list_length(parameters));
+ }
+
+ bytecode_append(current_block->code, areturn$);
+ }
+ break;
+
+ case integer_type:
+ case boolean_type:
+ case char_type:
+ bytecode_append(current_block->code, iload$);
+ bytecode_append(current_block->code, type_list_length(parameters));
+ bytecode_append(current_block->code, ireturn$);
+ break;
+
+ case string_type:
+ case array_type:
+ case record_type:
+ case image_type:
+ case command_type:
+ case stream_type:
+ case record_store_type:
+ case http_type:
+ switch(type_list_length(parameters))
+ {
+ case 0:
+ bytecode_append(current_block->code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(current_block->code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(current_block->code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(current_block->code, aload_3$);
+ break;
+ default:
+ bytecode_append(current_block->code, aload$);
+ bytecode_append(current_block->code, type_list_length(parameters));
+ }
+
+ bytecode_append(current_block->code, areturn$);
+
+ break;
+ }
+
+ current_block->parent_block->children[current_block->parent_block->children_count-1] = current_block;
+ }
+inside_routine = 0;
+ return forward_declaration;
+}
+
+
+/*
+ Handles the declarations of parameters to a
+ procedure/function. The grammar rule used is:
+
+ <RD_param_list> -> empty
+ | "(" [var] <RD_identifier_list> : [IDN.]IDN (; [var] <RD_identifier_list> : [IDN.]IDN )+ ")"
+*/
+type_list* RD_param_list(block *current_block)
+{
+ type_list *parameter_list;
+ string_list *identifier_list;
+ type *parameters_type;
+ int is_parameter_variable;
+
+ int i, len;
+
+ parameter_list = type_list_create();
+
+ if (current_token == OPEN_BR)
+ {
+ do
+ {
+ current_token = yylex();
+
+ if (current_token == END_OF_INPUT)
+ {
+ add_error_message(207, "", "");
+ return parameter_list;
+ }
+
+ if (current_token == CLOSE_BR)
+ break;
+
+ is_parameter_variable = 0;
+
+ if (current_token == KWD_VAR)
+ {
+ is_parameter_variable = 1;
+ current_token = yylex();
+ add_warning_message(436, "", "");
+ }
+
+ identifier_list = RD_identifier_list(current_block, 0);
+
+ if (current_token != COLON)
+ {
+ add_error_message(200, ":", YYTEXT_STRING);
+
+ /* Error-recovery, find the ")" */
+ while (current_token != CLOSE_BR)
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ return parameter_list;
+
+ break;
+
+ }
+ else
+ current_token = yylex();
+
+ parameters_type = type_from_name(current_block, YYTEXT_STRING);
+
+ if (parameters_type->type_class == error_type)
+ {
+ /* check if the name is an unit name */
+ identifier *unit;
+
+ lowercase(YYTEXT_STRING);
+
+ unit = get_identifier(current_block, YYTEXT_STRING);
+
+ if (unit->identifier_class == unit_name)
+ {
+ identifier *type_identifier;
+
+ current_token = yylex();
+
+ if (current_token != DOT)
+ add_error_message(200, ".", YYTEXT_STRING);
+ else
+ current_token = yylex();
+
+ type_identifier = name_table_find(unit->unit_block->names, string_from_cstr(YYTEXT_STRING));
+
+ if (type_identifier == NULL)
+ add_error_message(455, YYTEXT_STRING, "");
+ else
+ parameters_type = type_identifier->defined_type;
+ }
+
+ identifier_destroy(unit);
+ }
+
+ if (parameters_type->type_class == interval_type)
+ {
+ add_error_message(440, "", "");
+ parameters_type->type_class = integer_type;
+ }
+
+ /* add the types into parameter_list */
+ len = string_list_length(identifier_list);
+ for(i=0; i<len; i++)
+ type_list_append(parameter_list, type_duplicate(parameters_type));
+
+ add_parameters(current_block, identifier_list, parameters_type,
+ is_parameter_variable);
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery */
+ if ((current_token != COMMA)
+ && (current_token != CLOSE_BR))
+ current_token = yylex();
+ }
+ else
+ current_token = yylex();
+
+ } while (current_token == SEMI_COLON);
+
+ if (current_token != CLOSE_BR)
+ {
+ add_error_message(208, YYTEXT_STRING, "");
+
+ /* Error-recovery: find the first ; */
+ while ((current_token != CLOSE_BR)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+ }
+
+ current_token = yylex();
+ }
+
+ return parameter_list;
+}
+
+/*
+ Handles the block of code. The grammar rule used is:
+
+ <RD_block_body> -> (<RD_statement> ; )+
+*/
+void RD_block_body(block *current_block)
+{
+ short int first_pass = 1;
+
+ do
+ {
+ if (first_pass)
+ first_pass = 0;
+ else
+ current_token = yylex();
+
+ RD_statement(current_block);
+
+ } while (current_token == SEMI_COLON);
+}
+
+
+/*
+ The statements rule:
+
+ <RD_statement> -> begin <RD_block_body> end
+ | empty (if current_token == end || current_token == until)
+ | if <RD_if_statement>
+ | case <RD_case_statement>
+ | while <RD_while_statement>
+ | repeat <RD_repeat_statement>
+ | for <RD_for_statement>
+ | with <RD_with_statement>
+ | <RD_assignment_or_procedure_call>
+ | break
+*/
+void RD_statement(block *current_block)
+{
+ switch (current_token)
+ {
+ case KWD_BEGIN:
+ {
+ current_token = yylex();
+ RD_block_body(current_block);
+
+ if (current_token != KWD_END)
+ {
+ add_error_message(203, "end", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ break;
+ }
+
+ case KWD_END: case KWD_UNTIL: case KWD_FOREVER:
+ {
+ return;
+ }
+
+ case KWD_EXIT:
+ {
+ if (inside_routine == 0) { // j-a-s-d: in the main block treat it as a Halt()
+ char *halt_text;
+ halt_text = malloc(strlen("halt") + 1);
+ strcpy(halt_text, "halt");
+ create_std_function_code(current_block->code, halt_text);
+ string_destroy(halt_text);
+ } else switch (routine_return_type) {
+ case void_type:
+ bytecode_append(current_block->code, return$);
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, iload$);
+ bytecode_append(current_block->code, routine_return_parameters_length);
+ bytecode_append(current_block->code, ireturn$);
+ }
+ else
+ {
+ switch(routine_return_parameters_length)
+ {
+ case 0:
+ bytecode_append(current_block->code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(current_block->code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(current_block->code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(current_block->code, aload_3$);
+ break;
+ default:
+ bytecode_append(current_block->code, aload$);
+ bytecode_append(current_block->code, routine_return_parameters_length);
+ }
+
+ bytecode_append(current_block->code, areturn$);
+ }
+ break;
+
+ case integer_type:
+ case boolean_type:
+ case char_type:
+ bytecode_append(current_block->code, iload$);
+ bytecode_append(current_block->code, routine_return_parameters_length);
+ bytecode_append(current_block->code, ireturn$);
+ break;
+
+ case string_type:
+ case array_type:
+ case record_type:
+ case image_type:
+ case command_type:
+ case stream_type:
+ case record_store_type:
+ case http_type:
+ switch(routine_return_parameters_length)
+ {
+ case 0:
+ bytecode_append(current_block->code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(current_block->code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(current_block->code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(current_block->code, aload_3$);
+ break;
+ default:
+ bytecode_append(current_block->code, aload$);
+ bytecode_append(current_block->code, routine_return_parameters_length);
+ }
+ bytecode_append(current_block->code, areturn$);
+ break;
+ }
+ current_token = yylex();
+ break;
+ }
+ case KWD_IF:
+ {
+ current_token = yylex();
+ RD_if_statement(current_block);
+ break;
+ }
+
+ case KWD_CASE:
+ {
+ current_token = yylex();
+ RD_case_statement(current_block);
+ break;
+ }
+
+ case KWD_WHILE:
+ {
+ current_token = yylex();
+ RD_while_statement(current_block);
+ break;
+ }
+
+ case KWD_REPEAT:
+ {
+ current_token = yylex();
+ RD_repeat_statement(current_block);
+ break;
+ }
+
+ case KWD_FOR:
+ {
+ current_token = yylex();
+ RD_for_statement(current_block);
+ break;
+ }
+
+ case KWD_WITH:
+ {
+ add_error_message(215, "", "");
+ current_token = yylex();
+ RD_with_statement(current_block);
+ break;
+ }
+
+ case IDENTIFIER:
+ case KWD_RESULT: // j-a-s-d
+ {
+ RD_assignment_or_procedure_call(current_block);
+ break;
+ }
+
+ case KWD_BREAK:
+ {
+ current_token = yylex();
+
+ if (inside_loop <= 0)
+ add_error_message(219, "", "");
+ else
+ {
+ bytecode_append(current_block->code, break_stmt$);
+ bytecode_append_short_int(current_block->code, 0);
+ }
+ break;
+ }
+
+ case KWD_BYTECODE:
+ {
+ RD_inline_body(current_block);
+ if (current_token != KWD_END) {
+ add_error_message(200, "end ", YYTEXT_STRING);
+ while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
+ current_token = yylex();
+ } else current_token = yylex();
+ break;
+ }
+
+ case KWD_INLINE:
+ {
+ add_warning_message(464, "", "");
+ current_token = yylex();
+ if (current_token == OPEN_BR) {
+ RD_inline_body(current_block);
+ if (current_token != CLOSE_BR) {
+ add_error_message(200, "<inline>) ", YYTEXT_STRING);
+ while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
+ current_token = yylex();
+ } else current_token = yylex();
+ } else {
+ add_error_message(200, "<inline>(", YYTEXT_STRING);
+ while ((current_token != SEMI_COLON) && (current_token != END_OF_INPUT))
+ current_token = yylex();
+ }
+ break;
+ }
+
+ default:
+ {
+ add_error_message(204, YYTEXT_STRING, "");
+ break;
+ }
+ }
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////// JAVA - ASM /////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ Handles the inline statement. The grammar rule
+ is:
+ <inline (byte)>
+ <inline (opcode)>
+ <inline (opcode int)>
+ <inline (opcode [[cp_type] 'param1', 'param2', 'param3'])>
+*/
+int RD_opcodes() {
+ if (strcmp(yytext, "nop") == 0) return 0x00; // íè÷åãî íå äåëàåò
+ if (strcmp(yytext, "aconst_null") == 0) return 0x01; // çàãðóçêà â ñòåê null ( ïóñòîé ññûëêè íà îáúåêò)
+ if (strcmp(yytext, "iconst_m1") == 0) return 0x02; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû -1
+ if (strcmp(yytext, "iconst_0") == 0) return 0x03; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 0}
+ if (strcmp(yytext, "iconst_1") == 0) return 0x04; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 1}
+ if (strcmp(yytext, "iconst_2") == 0) return 0x05; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 2}
+ if (strcmp(yytext, "iconst_3") == 0) return 0x06; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 3}
+ if (strcmp(yytext, "iconst_4") == 0) return 0x07; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 4}
+ if (strcmp(yytext, "iconst_5") == 0) return 0x08; // çàãðóçêà öåëî÷èñëåííîé êîíñòàíòû 5}
+ if (strcmp(yytext, "lconst_0") == 0) return 0x09; // çàãðóçêà äëèííîé öåëî÷èñëåííîé êîíñòàíòû 0}
+ if (strcmp(yytext, "lconst_1") == 0) return 0x0A; // çàãðóçêà äëèííîé öåëî÷èñëåííîé êîíñòàíòû 1}
+ if (strcmp(yytext, "fconst_0") == 0) return 0x0B; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 0}
+ if (strcmp(yytext, "fconst_1") == 0) return 0x0C; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 1}
+ if (strcmp(yytext, "fconst_2") == 0) return 0x0D; // çàãðóçêà âåùåñòâåííîãî ÷èñëà îäèíàðíîé òî÷íîñòè 2}
+ if (strcmp(yytext, "dconst_0") == 0) return 0x0E; // çàãðóçêà âåùåñòâåííîãî ÷èñëà äâîéíîé òî÷íîñòè 0}
+ if (strcmp(yytext, "dconst_1") == 0) return 0x0F; // çàãðóçêà âåùåñòâåííîãî ÷èñëà äâîéíîé òî÷íîñòè 1}
+ if (strcmp(yytext, "bipush") == 0) return 0x10; // [1]çàãðóçêà â ñòåê îäíîáàéòîâîãî öåëîãî ñî çíàêîì}
+ if (strcmp(yytext, "sipush") == 0) return 0x11; // [2+-]çàãðóçêà â ñòåê äâóõáàéòîâîãî öåëîãî ñî çíàêîì}
+ if (strcmp(yytext, "ldc1") == 0) return 0x12; // [1]çàãðóçêà â ñòåê ýëåìåíòà èç êîíñòàíòíîãî ïóëà}
+ if (strcmp(yytext, "ldc2") == 0) return 0x13; // [2]çàãðóçêà â ñòåê ýëåìåíòà èç êîíñòàíòíîãî ïóëà}
+ if (strcmp(yytext, "ldc2w") == 0) return 0x14; // [2]çàãðóçêà â ñòåê äëèííîãî öåëîãî èëè äâîéíîãî âåùåñòâåííîãî çíà÷åíèÿ èç êîíñòàíòíîãî ïóëà}
+ if (strcmp(yytext, "iload") == 0) return 0x15; // [1]çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "lload") == 0) return 0x16; // [1]çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "fload") == 0) return 0x17; // [1]çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "dload") == 0) return 0x18; // [1]çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "aload") == 0) return 0x19; // [1]çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "iload_0") == 0) return 0x1A; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "iload_1") == 0) return 0x1B; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "iload_2") == 0) return 0x1C; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "iload_3") == 0) return 0x1D; // çàãðóçêà öåëîãî èç ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "lload_0") == 0) return 0x1E; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "lload_1") == 0) return 0x1F; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "lload_2") == 0) return 0x20; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "lload_3") == 0) return 0x21; // çàãðóçêà äëèííîãî öåëîãî èç ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "fload_0") == 0) return 0x22; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "fload_1") == 0) return 0x23; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "fload_2") == 0) return 0x24; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "fload_3") == 0) return 0x25; // çàãðóçêà âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "dload_0") == 0) return 0x26; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "dload_1") == 0) return 0x27; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "dload_2") == 0) return 0x28; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "dload_3") == 0) return 0x29; // çàãðóçêà âåùåñòâåííîãî äâîéíîé òî÷íîñòè èç ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "aload_0") == 0) return 0x2A; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "aload_1") == 0) return 0x2B; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "aload_2") == 0) return 0x2C; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "aload_3") == 0) return 0x2D; // çàãðóçêà îáúåêòíîé ññûëêè èç ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "iaload") == 0) return 0x2E; // çàãðóçêà öåëîãî èç ìàññèâà}
+ if (strcmp(yytext, "laload") == 0) return 0x2F; // çàãðóçêà äëèííîãî öåëîãî èç ìàññèâà}
+ if (strcmp(yytext, "faload") == 0) return 0x30; // çàãðóçêà âåùåñòâåííîãî èç ìàññèâà}
+ if (strcmp(yytext, "daload") == 0) return 0x31; // çàãðóçêà äâîéíîãî âåùåñòâåííîãî èç ìàññèâà}
+ if (strcmp(yytext, "aaload") == 0) return 0x32; // çàãðóçêà îáúåêòíîé ññûëêè èç ìàññèâà}
+ if (strcmp(yytext, "baload") == 0) return 0x33; // çàãðóçêà áàéòà ñî çíàêîì èç ìàññèâà}
+ if (strcmp(yytext, "caload") == 0) return 0x34; // çàãðóçêà ñèìâîëà èç ìàññèâà}
+ if (strcmp(yytext, "saload") == 0) return 0x35; // çàãðóçêà êîðîòêîãî èç ìàññèâà}
+ if (strcmp(yytext, "istore") == 0) return 0x36; // [1]ñîõðàíåíèå öåëîãî çíà÷åíèÿ â ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "lstore") == 0) return 0x37; // [1]ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "fstore") == 0) return 0x38; // [1]ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "dstore") == 0) return 0x39; // [1]ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "astore") == 0) return 0x3A; // [1]ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé}
+ if (strcmp(yytext, "istore_0") == 0) return 0x3B; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "istore_1") == 0) return 0x3C; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "istore_2") == 0) return 0x3D; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "istore_3") == 0) return 0x3E; // ñîõðàíåíèå öåëîãî â ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "lstore_0") == 0) return 0x3F; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "lstore_1") == 0) return 0x40; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "lstore_2") == 0) return 0x41; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "lstore_3") == 0) return 0x42; // ñîõðàíåíèå äëèííîãî öåëîãî â ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "fstore_0") == 0) return 0x43; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "fstore_1") == 0) return 0x44; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "fstore_2") == 0) return 0x45; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "fstore_3") == 0) return 0x46; // ñîõðàíåíèå âåùåñòâåííîãî îäèíàðíîé òî÷íîñòè â ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "dstore_0") == 0) return 0x47; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "dstore_1") == 0) return 0x48; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "dstore_2") == 0) return 0x49; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "dstore_3") == 0) return 0x4A; // ñîõðàíåíèå äâîéíîãî âåùåñòâåííîãî â ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "astore_0") == 0) return 0x4B; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 0}
+ if (strcmp(yytext, "astore_1") == 0) return 0x4C; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 1}
+ if (strcmp(yytext, "astore_2") == 0) return 0x4D; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 2}
+ if (strcmp(yytext, "astore_3") == 0) return 0x4E; // ñîõðàíåíèå îáúåêòíîé ññûëêè â ëîêàëüíîé ïåðåìåííîé 3}
+ if (strcmp(yytext, "iastore") == 0) return 0x4F; // ñîõðàíåíèå â öåëî÷èñëåííîì ìàññèâå}
+ if (strcmp(yytext, "lastore") == 0) return 0x50; // ñîõðàíåíèå â ìàññèâå èç äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fastore") == 0) return 0x51; // ñîõðàíåíèå â ìàññèâå èç îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "dastore") == 0) return 0x52; // ñîõðàíåíèå â ìàññèâå èç äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "aastore") == 0) return 0x53; // ñîõðàíåíèå â ìàññèâå èç îáúåêòíûõ ññûëîê}
+ if (strcmp(yytext, "bastore") == 0) return 0x54; // ñîõðàíåíèå â ìàññèâå áàéòîâ ñî çíàêîì}
+ if (strcmp(yytext, "castore") == 0) return 0x55; // ñîõðàíåíèå â ñèìâîëüíîì ìàññèâå}
+ if (strcmp(yytext, "sastore") == 0) return 0x56; // ñîõðàíåíèå â ìàññèâå èç êîðîòêèõ öåëûõ}
+ if (strcmp(yytext, "pop") == 0) return 0x57; // èçâëå÷åíèå ñëîâà ñ âåðøèíû ñòåêà}
+ if (strcmp(yytext, "pop2") == 0) return 0x58; // èçâëå÷åíèå äâóõ ñëîâ ñ âåðøèíû ñòåêà}
+ if (strcmp(yytext, "dup") == 0) return 0x59; // äóáëèðîâàíèå ñëîâà íà âåðøèíå ñòåêà}
+ if (strcmp(yytext, "dup_x1") == 0) return 0x5A; // äóáëèðîâàíèå ñëîâî íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèè â ñòåê íà äâà ñëîâà íèæå}
+ if (strcmp(yytext, "dup_x2") == 0) return 0x5B; // äóáëèðîâàíèå âåðøèíû ñòåêà è ïîìåùåíèå êîïèè íà òðè ñëîâà íèæå}
+ if (strcmp(yytext, "dup2") == 0) return 0x5C; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà}
+ if (strcmp(yytext, "dup2_x1") == 0) return 0x5D; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèé íà äâà ñëîâà íèæå}
+ if (strcmp(yytext, "dup2_x2") == 0) return 0x5E; // äóáëèðîâàíèå äâóõ ñëîâ íà âåðøèíå ñòåêà è ïîìåùåíèå êîïèé íà òðè ñëîâà íèæå}
+ if (strcmp(yytext, "swap") == 0) return 0x5F; // îáìåí äâóõ ñëîâ íà âåðøèíå ñòåêà}
+ if (strcmp(yytext, "iadd") == 0) return 0x60; // ñëîæåíèå öåëûõ}
+ if (strcmp(yytext, "ladd") == 0) return 0x61; // ñëîæåíèå äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fadd") == 0) return 0x62; // ñëîæåíèå îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "dadd") == 0) return 0x63; // ñëîæåíèå äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "isub") == 0) return 0x64; // âû÷èòàíèå öåëûõ}
+ if (strcmp(yytext, "lsub") == 0) return 0x65; // âû÷èòàíèå äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fsub") == 0) return 0x66; // âû÷èòàíèå îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "dsub") == 0) return 0x67; // âû÷èòàíèå äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "imul") == 0) return 0x68; // óìíîæåíèå öåëûõ}
+ if (strcmp(yytext, "lmul") == 0) return 0x69; // óìíîæåíèå äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fmul") == 0) return 0x6A; // óìíîæåíèå îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "dmul") == 0) return 0x6B; // óìíîæåíèå äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "idiv") == 0) return 0x6C; // äåëåíèå öåëûõ}
+ if (strcmp(yytext, "ldiv") == 0) return 0x6D; // äåëåíèå äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fdiv") == 0) return 0x6E; // äåëåíèå îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "ddiv") == 0) return 0x6F; // äåëåíèå äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "irem") == 0) return 0x70; // îñòàòîê îò äåëåíèÿ öåëûõ}
+ if (strcmp(yytext, "lrem") == 0) return 0x71; // îñòàòîê îò äåëåíèÿ äëèííûõ öåëûõ}
+ if (strcmp(yytext, "frem") == 0) return 0x72; // îñòàòîê îò äåëåíèÿ îäèíàðíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "drem") == 0) return 0x73; // îñòàòîê îò äåëåíèÿ äâîéíûõ âåùåñòâåííûõ}
+ if (strcmp(yytext, "ineg") == 0) return 0x74; // îòðèöàíèå öåëîãî}
+ if (strcmp(yytext, "leg") == 0) return 0x75; // îòðèöàíèå äëèííîãî öåëîãî}
+ if (strcmp(yytext, "fneg") == 0) return 0x76; // îòðèöàíèå îäèíàðíîãî âåùåñòâåííîãî}
+ if (strcmp(yytext, "dneg") == 0) return 0x77; // îòðèöàíèå äâîéíîãî âåùåñòâåííîãî ÷èñëà}
+ if (strcmp(yytext, "ishl") == 0) return 0x78; // ñäâèã öåëîãî âëåâî}
+ if (strcmp(yytext, "lshl") == 0) return 0x79; // ñäâèã äëèííîãî öåëîãî âëåâî}
+ if (strcmp(yytext, "ishr") == 0) return 0x7A; // àðèôìåòè÷åñêèé ñäâèã öåëîãî âïðàâî}
+ if (strcmp(yytext, "lshr") == 0) return 0x7B; // àðèôìåòè÷åñêèé ñäâèã äëèííîãî öåëîãî âïðàâî}
+ if (strcmp(yytext, "iushr") == 0) return 0x7C; // ëîãè÷åñêèé ñäâèã öåëîãî âïðàâî}
+ if (strcmp(yytext, "lushr") == 0) return 0x7D; // ëîãè÷åñêèé ñäâèã äëèííîãî öåëîãî âïðàâî}
+ if (strcmp(yytext, "iand") == 0) return 0x7E; // ëîãè÷åñêîå È ñ îïåðàíäàìè öåëîãî òèïà}
+ if (strcmp(yytext, "land") == 0) return 0x7F; // ëîãè÷åñêîå È ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
+ if (strcmp(yytext, "ior") == 0) return 0x80; // ëîãè÷åñêîå ÈËÈ ñ öåëî÷èñëåííûìè îïåðàíäàìè}
+ if (strcmp(yytext, "lor") == 0) return 0x81; // ëîãè÷åñêîå ÈËÈ ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
+ if (strcmp(yytext, "ixor") == 0) return 0x82; // èñêëþ÷àþùåå ÈËÈ ñ öåëî÷èñëåííûìè îïåðàíäàìè}
+ if (strcmp(yytext, "lxor") == 0) return 0x83; // èñêëþ÷àþùåå ÈËÈ ñ îïåðàíäàìè äëèííîãî öåëîãî òèïà}
+ if (strcmp(yytext, "iinc") == 0) return 0x84; // [1,1+-]óâåëè÷åíèå ëîêàëüíîé ïåðåìåííîé íà êîíñòàíòó}
+ if (strcmp(yytext, "i2l") == 0) return 0x85; // ïðåîáðàçîâàíèå öåëîãî â äëèííîå öåëîå}
+ if (strcmp(yytext, "i2f") == 0) return 0x86; // öåëîå â âåùåñòâåííîå}
+ if (strcmp(yytext, "i2d") == 0) return 0x87; // öåëîå â äâîéíîå âåùåñòâåííîå}
+ if (strcmp(yytext, "l2i") == 0) return 0x88; // äëèííîå öåëîå â öåëîå}
+ if (strcmp(yytext, "l2f") == 0) return 0x89; // äëèííîå öåëîå â âåùåñòâåííîå}
+ if (strcmp(yytext, "l2d") == 0) return 0x8A; // äëèííîå öåëîå â äâîéíîå âåùåñòâåííîå}
+ if (strcmp(yytext, "f2i") == 0) return 0x8B; // âåùåñòâåííîå â öåëîå}
+ if (strcmp(yytext, "f2l") == 0) return 0x8C; // âåùåñòâåííîå â äëèííîå öåëîå}
+ if (strcmp(yytext, "f2d") == 0) return 0x8D; // âåùåñòâåííîå â äâîéíîå âåùåñòâåííîå}
+ if (strcmp(yytext, "d2i") == 0) return 0x8E; // äâîéíîå âåùåñòâåííîå â öåëîå}
+ if (strcmp(yytext, "d2l") == 0) return 0x8F; // äâîéíîå âåùåñòâåííîå â äëèííîå öåëîå}
+ if (strcmp(yytext, "d2f") == 0) return 0x90; // äâîéíîå âåùåñòâåííîå â âåùåñòâåííîå}
+ if (strcmp(yytext, "int2byte") == 0) return 0x91; // öåëîå â çíàêîâûé áàéò}
+ if (strcmp(yytext, "int2char") == 0) return 0x92; // öåëîå â ñèìâîë}
+ if (strcmp(yytext, "int2short") == 0) return 0x93; // öåëîå â êîðîòêîå}
+ if (strcmp(yytext, "lcmp") == 0) return 0x94; // ñðàâíåíèå äëèííûõ öåëûõ}
+ if (strcmp(yytext, "fcmpl") == 0) return 0x95; // ñðàâíåíèå âåùåñòâåííûõ îäèíàðíîé òî÷íîñòè (-1 ïðè NaN)}
+ if (strcmp(yytext, "fcmpg") == 0) return 0x96; // ñðàâíåíèå âåùåñòâåííûõ îäèíàðíîé òî÷íîñòè (1 ïðè NaN)}
+ if (strcmp(yytext, "dcmpl") == 0) return 0x97; // ñðàâíåíèå âåùåñòâåííûõ äâîéíîé òî÷íîñòè(-1 ïðè NaN)}
+ if (strcmp(yytext, "dcmpg") == 0) return 0x98; // ñðàâíåíèå âåùåñòâåííûõ äâîéíîé òî÷íîñòè(1 ïðè NaN)}
+ if (strcmp(yytext, "ifeq") == 0) return 0x99; // [2]ïåðåõîä, åñëè ðàâíî 0}
+ if (strcmp(yytext, "ifne") == 0) return 0x9A; // [2]ïåðåõîä, åñëè íå ðàâíî 0}
+ if (strcmp(yytext, "iflt") == 0) return 0x9B; // [2]ïåðåõîä, åñëè ìåíüøå 0}
+ if (strcmp(yytext, "ifge") == 0) return 0x9C; // [2]ïåðåõîä, åñëè áîëüøå èëè ðàâíî 0}
+ if (strcmp(yytext, "ifgt") == 0) return 0x9D; // [2]ïåðåõîä, åñëè áîëüøå 0}
+ if (strcmp(yytext, "ifle") == 0) return 0x9E; // [2]ïåðåõîä, åñëè ìåíüøå èëè ðàâíî 0}
+ if (strcmp(yytext, "if_icmpeq") == 0) return 0x9F; // [2]ïåðåõîä, åñëè öåëûå ðàâíû}
+ if (strcmp(yytext, "if_icmpne") == 0) return 0xA0; // [2]ïåðåõîä, åñëè öåëûå íå ðàâíû}
+ if (strcmp(yytext, "if_icmplt") == 0) return 0xA1; // [2]ïåðåõîä, åñëè öåëîå ìåíüøå 0}
+ if (strcmp(yytext, "if_icmpge") == 0) return 0xA2; // [2]ïåðåõîä, åñëè öåëîå áîëüøå èëè ðàâíî}
+ if (strcmp(yytext, "if_icmpgt") == 0) return 0xA3; // [2]ïåðåõîä, åñëè öåëîå áîëüøå 0}
+ if (strcmp(yytext, "if_icmple") == 0) return 0xA4; // [2]ïåðåõîä, åñëè öåëîå ìåíüøå èëè ðàâíî}
+ if (strcmp(yytext, "if_acmpeq") == 0) return 0xA5; // [2]ïåðåõîä, åñëè ññûëêè íà îáúåêò ðàâíû}
+ if (strcmp(yytext, "if_acmpne") == 0) return 0xA6; // [2]ïåðåõîä, åñëè ññûëêè íà îáúåêò íå ðàâíû}
+ if (strcmp(yytext, "goto") == 0) return 0xA7; // [2]ïåðåõîä íà}
+ if (strcmp(yytext, "jsr") == 0) return 0xA8; // [2]ïåðåõîä íà ïîäïðîãðàììó}
+ if (strcmp(yytext, "ret") == 0) return 0xA9; // [1]âîçâðàò èç ïîäïðîãðàììû}
+ if (strcmp(yytext, "tableswitch") == 0) return 0xAA; // [tbs] äîñòóï ê òàáëèöå ïåðåõîäà ïî èíäåêñó è ïåðåõîä}
+ if (strcmp(yytext, "lookupswitch") == 0) return 0xAB; // [lks] äîñòóï ê òàáëèöå ïåðåõîäà ïî ñðàâíåíèþ ñ êëþ÷îì è ïåðåõîä}
+ if (strcmp(yytext, "ireturn") == 0) return 0xAC; // âîçâðàò öåëîãî çíà÷åíèÿ ôóíêöèè}
+ if (strcmp(yytext, "lreturn") == 0) return 0xAD; // âîçâðàò äëèííîãî öåëîãî çíà÷åíèÿ ôóíêöèè}
+ if (strcmp(yytext, "freturn") == 0) return 0xAE; // âîçâðàò îäèíàðíîãî âåùåñòâåííîãî çíà÷åíèÿ ôóíêöèè}
+ if (strcmp(yytext, "dreturn") == 0) return 0xAF; // âîçâðàò äâîéíîãî âåùåñòâåííîãî çíà÷åíèÿ ôóíêöèè}
+ if (strcmp(yytext, "areturn") == 0) return 0xB0; // âîçâðàò îáúåêòíîé ññûëêè èç ôóíêöèè}
+ if (strcmp(yytext, "return") == 0) return 0xB1; // âîçâðàò(îïóñòîøàþùèé) èç ïðîöåäóðû}
+ if (strcmp(yytext, "getstatic") == 0) return 0xB2; // [2fld]ïîëó÷åíèå ñòàòè÷åñêîãî ïîëÿ êëàññà}
+ if (strcmp(yytext, "putstatic") == 0) return 0xB3; // [2fld]óñòàíîâêà ñòàòè÷åñêîãî ïîëÿ â êëàññå}
+ if (strcmp(yytext, "getfield") == 0) return 0xB4; // [2fld]ïåðåíîñ ïîëÿ èç îáúåêòà}
+ if (strcmp(yytext, "putfield") == 0) return 0xB5; // [2fld]óñòàíîâêà ïîëÿ â îáúåêòå}
+ if (strcmp(yytext, "invokevirtual") == 0) return 0xB6; // [2mtd],âûçûâàåò ìåòîä ýêçåìïëÿðà, îñíîâûâàÿñü íà òèïå âðåìåíè âûïîëíåíèÿ}
+ if (strcmp(yytext, "invokenonvirtual") == 0) return 0xB7; // [2mtd],âûçûâàåò ìåòîä ýêçåìïëÿðà, îñíîâûâàÿñü íà íå âèðòóàëüíîì òèïå}
+ if (strcmp(yytext, "invokestatic") == 0) return 0xB8; // [2mtd]âûçîâ ìåòîäà êëàññà (ñòàòè÷åñêîãî ìåòîäà)}
+ if (strcmp(yytext, "invokeinterface") == 0) return 0xB9; // [2,1,1]âûçûâàåò ìåòîä èíòåðôåéñà}
+ if (strcmp(yytext, "new") == 0) return 0xBB; // [2]ñîçäàåò íîâûé îáúåêò}
+ if (strcmp(yytext, "newarray") == 0) return 0xBC; // [1]atype> T_BOOLEAN=4,T_CHAR=5,T_FLOAT=6,T_DOUBLE=7,T_BYTE=8, T_SHORT=9,T_INT=9,T_LONG=11}
+ if (strcmp(yytext, "anewarray") == 0) return 0xBD; // [2class]îáúÿâëåíèå íîâîãî ìàññèâà èç ññûëîê íà îáúåêòû}
+ if (strcmp(yytext, "arraylength") == 0) return 0xBE; // âîçâðàùàåò äëèíó ìàññèâà}
+ if (strcmp(yytext, "athrow") == 0) return 0xBF; // ãåíåðàöèÿ îáðàáîòêè èëè îøèáêè}
+ if (strcmp(yytext, "checkcast") == 0) return 0xC0; // cs 2,ïðîâåðÿåò, ÷òî îáúåêò èìååò äàííûé òèï}
+ if (strcmp(yytext, "instanceof") == 0) return 0xC1; // [2class]îïðåäåëÿåò, èìååò ëè îáúåêò äàííûé òèï}
+ if (strcmp(yytext, "monitorenter") == 0) return 0xC2; // âõîä â êîíòðîëèðóåìóþ îáëàñòü êîäà}
+ if (strcmp(yytext, "monitorexit") == 0) return 0xC3; // âûõîä èç êîíòðîëèðóåìîé îáëàñòè êîäà}
+ if (strcmp(yytext, "wide") == 0) return 0xC4; // ðàñøèðåííûé èíäåêñ äëÿ äîñòóïà ê ëîêàëüíûì ïåðåìåííûì äëÿ êîìàíä çàãðóçêè, ñîõðàíåíèÿ è ïðèðàùåíè}
+ if (strcmp(yytext, "multianewarray") == 0) return 0xC5; // [2cp-index,1b]ðàçìåùåíèå íîâîãî ìíîãîìåðíîãî ìàññèâà}
+ if (strcmp(yytext, "ifnull") == 0) return 0xC6; // [2ofs]ïåðåõîä, åñëè ïóñòîé óêàçàòåëü}
+ if (strcmp(yytext, "ifnonnull") == 0) return 0xC7; // [2ofs]ïåðåõîä, åñëè íå ïóñòîé óêàçàòåëü}
+ if (strcmp(yytext, "goto_w") == 0) return 0xC8; // [4ofs]ïåðåõîä íà (ðàñøèðåííûé èíäåêñ)}
+ if (strcmp(yytext, "jsr_w") == 0) return 0xC9; // [4ofs]ïåðåõîä íà ïîäïðîãðàììó (ðàñøèðåííûé èíäåêñ)}
+ if (strcmp(yytext, "breakpoint") == 0) return 0xCA; // îñòàíîâêà è ïåðåäà÷à êîíòðîëÿ îáðàáîò÷èêó ïðåðûâàíèé}
+ if (strcmp(yytext, "ret_w") == 0) return 0xD1; // [2]âîçâðàò èç ïîäïðîãðàììû (ðàñøèðåííûé èíäåêñ)}
+ return 0xFF;
+ //0x10,0xBC 1b;
+ //0x11 2b+-;
+ //0x12 1b constpool-index;
+ //0x13 2b constpool-index(2byte-const);
+ //0x14 2b constpool-index(4byte-const);
+ //0xB2,0xB3,0xB4,0xB5 2b constpool-field;
+ //0xB6,0xB7,0xB8 2b constpool-method;
+ //0xB9 2b constpool-method; 1b; 1b;
+ //0xBB 2b constpool-index;
+ //0xC5 2b constpool-index; 1b;
+ //0xBD,0xC1 2b constpool-class;
+ //0xC0 2b constpool-string;
+ //0x15,0x16,0x17,0x18,0x19 1b locvar-index;
+ //0x36,0x37,0x38,0x39,0x3A 1b locvar-index;
+ //0x84 1b; 1b+-(locvar-add-const);
+ //0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xC6,0xC7 2b offs;
+ //0xC8 4b offs;
+ //0xC9 4b call;
+ //0xA8 2b call;
+ //0xA9 1b ret;
+ //0xD1 2b ret;
+ //0xC4 wide...;
+ //0xAA tableswitch...;
+ //0xAB loookupswitch...;
+ //îñòàëüíûå êîäû ïàðàìåòðîâ íå èìåþò...
+}
+
+int cp_index_body()
+{ //ðàçáîð ìîäèôèêàöèé ññûëîê íà ïàðàìåòðû êîíñòàíòíîãî ïóëà
+ char p1[512];
+ char p2[512];
+ if (current_token == IDENTIFIER)
+ {
+ if (strcmp(yytext, "int") == 0)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER) return cp_add_integer(integer_constant);
+ }
+ else if (strcmp(yytext, "utf8") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_utf8(yytext);
+ }
+ else if (strcmp(yytext, "str") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_string(yytext);
+ }
+ else if (strcmp(yytext, "class") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_class(yytext);
+ }
+ else if (strcmp(yytext, "nametype") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p1,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_nameandtype(p1, yytext);
+ }
+ }
+ } else if (strcmp(yytext, "field") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p1,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p2,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_fieldref(p1,p2,yytext);
+ }
+ }
+ }
+ }
+ }
+ else if (strcmp(yytext, "method") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p1,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p2,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_methodref(p1,p2,yytext);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (current_token == KWD_INTERFACE) //if (strcmp(yytext, "interface") == 0)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p1,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR))
+ {
+ strcpy(&p2,yytext);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_STRING)||(current_token == CST_CHAR)) return cp_add_interface(p1,p2,yytext);
+ }
+ }
+ }
+ }
+ }
+ return -1; //îøèáêà ðàçáîðà ïàðàìåòðîâ
+}
+
+
+int RD_inline_offs(block *current_block, int n, int addr)
+{
+ current_token = yylex();
+ if (current_token == CST_INTEGER) return (short)integer_constant; //NUMBER
+ if (current_token == COLON) //FIND LABEL
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ int i = labcount;
+ nam[0] = integer_constant;
+ if (integer_constant==111)
+ integer_constant=111;
+ len[0] = 0;
+ while ((nam[i] != integer_constant) || (len[i] != 0)) i--;
+ if (i>0) return lab[i]-addr;
+ //add find block
+ labcount++;
+ nam[labcount] = integer_constant;
+ len[labcount] = n; //offs-type: 2bytes / 4bytes
+ lab[labcount] = current_block->code->bytecode_pos;
+ return addr; //label no found
+ }
+ }
+ return 0; //error!
+}
+
+
+void RD_inline_body(block *current_block)
+{
+ int cp_index,opcode,err,addr,offs,i,j;
+ labcount=0;
+ err=0;
+ do {
+ current_token = yylex();
+ if (current_token == IDENTIFIER)
+ {
+ opcode=RD_opcodes();
+ bytecode_append(current_block->code, opcode);
+ ///////
+ switch (opcode)
+ {
+ case 0x10: //1byte;
+ case 0xBC:
+ case 0x15: //1b locvar-index;
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x36: //1b locvar-index;
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0xA9: //1b ret;
+ err=1;
+ current_token = yylex();
+ if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ err=0;
+ }
+ break;
+ case 0x84: //1b; 1b+-(locvar-add-const);
+ err=1;
+ current_token = yylex();
+ if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if ((current_token == CST_INTEGER) && (integer_constant>=0)&&(integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ err=0;
+ }
+ }
+ }
+ break;
+ case 0x11: //2b+-;
+ err=1;
+ current_token = yylex();
+ if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=65535))
+ {
+ bytecode_append_short_int(current_block->code, (short)integer_constant);
+ err=0;
+ }
+ break;
+ case 0x99: //2b offs;
+ case 0x9A:
+ case 0x9B:
+ case 0x9C:
+ case 0x9D:
+ case 0x9E:
+ case 0x9F:
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xC6:
+ case 0xC7:
+ case 0xA8: //2b call;
+ case 0xD1: //2b ret;
+ err=1;
+ addr = current_block->code->bytecode_pos-1;
+ offs = RD_inline_offs(current_block, 2, addr);
+ if (offs != 0)
+ {
+ if ((offs>=-32768) && (offs<=32767))
+ {
+ bytecode_append_short_int(current_block->code, (short)offs);
+ err=0;
+ }
+ }
+ //current_token = yylex();
+ //if ((current_token == CST_INTEGER) && (integer_constant>=0) && (integer_constant<=65535))
+ //{
+ // bytecode_append_short_int(current_block->code, (short)integer_constant);
+ // err=0;
+ //}
+ break;
+ case 0xC8: //4b offs;
+ case 0xC9: //4b call;
+ err=1;
+ addr = current_block->code->bytecode_pos-1;
+ offs = RD_inline_offs(current_block, 4, addr);
+ if (offs != 0)
+ {
+ bytecode_append_long_int(current_block->code, offs);
+ err=0;
+ }
+ //current_token = yylex();
+ //if (current_token == CST_INTEGER)
+ //{
+ // bytecode_append_long_int(current_block->code, integer_constant);
+ // err=0;
+ //}
+ break;
+ case 0x12: //1b constpool-index;
+ err=1;
+ current_token = yylex();
+ cp_index=cp_index_body();
+ if ((cp_index>=0) && (cp_index<=255))
+ {
+ bytecode_append(current_block->code, cp_index);
+ err=0;
+ }
+ break;
+ case 0xBB: //2b constpool-index;
+ err=1;
+ current_token = yylex();
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ break;
+ case 0xC5: //2b constpool-index; 1b;
+ err=1;
+ current_token = yylex();
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ if ((integer_constant>=0) && (integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ err=0;
+ }
+ }
+ }
+ }
+ break;
+ case 0xBD: //2b constpool-class;
+ case 0xC1:
+ err=1;
+ current_token = yylex();
+ if ((current_token == IDENTIFIER) && (strcmp(yytext, "class") == 0))
+ {
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ }
+ break;
+ case 0xC0: //2b constpool-string;
+ err=1;
+ current_token = yylex();
+ if (current_token == IDENTIFIER) //&& (strcmp(yytext, "str") == 0))
+ {
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ }
+ break;
+ case 0x13: //2b constpool-index(2byte-const);
+ case 0x14: //2b constpool-index(4byte-const);
+ err=1;
+ current_token = yylex();
+ //if ((current_token == IDENTIFIER) && (strcmp(yytext, "int") == 0))
+ //{
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ //}
+ break;
+ case 0xB2: //2b constpool-field;
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ err=1;
+ current_token = yylex();
+ if ((current_token == IDENTIFIER) && (strcmp(yytext, "field") == 0))
+ {
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ }
+ break;
+ case 0xB6: //2b constpool-method;
+ case 0xB7:
+ case 0xB8:
+ err=1;
+ current_token = yylex();
+ if ((current_token == IDENTIFIER) && (strcmp(yytext, "method") == 0))
+ {
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ err=0;
+ }
+ }
+ break;
+ case 0xB9: //2b constpool-method; 1b; 1b;
+ err=1;
+ current_token = yylex();
+ if (current_token == KWD_INTERFACE) //&& (strcmp(yytext, "interface") != 0))
+ {
+ cp_index=cp_index_body();
+ if (cp_index>=0)
+ {
+ bytecode_append_short_int(current_block->code, cp_index);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER) {
+ if ((integer_constant>=0) && (integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ if ((integer_constant>=0) && (integer_constant<=255))
+ {
+ bytecode_append(current_block->code, (char)integer_constant);
+ err=0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0xAA: //tableswitch...;
+ {
+ err=1;
+ addr = current_block->code->bytecode_pos-1;
+ while (current_block->code->bytecode_pos%4!=0) //4byte-align
+ bytecode_append(current_block->code, 0);
+ offs = RD_inline_offs(current_block, 4, addr);
+ if (offs != 0)
+ {
+ bytecode_append_long_int(current_block->code, offs); //default-offs
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ bytecode_append_long_int(current_block->code, integer_constant); //low-index
+ i=integer_constant;
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ bytecode_append_long_int(current_block->code, integer_constant); //high-index Length=high-low+1
+ j=integer_constant;
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ err=0;
+ for (; i<=j; i++)
+ {
+ offs = RD_inline_offs(current_block, 4, addr);
+ if (i<j)
+ {
+ current_token = yylex();
+ if (current_token != COMMA) offs = 0;
+ }
+ if (offs == 0) //bad label
+ {
+ add_error_message(462, 0, current_block->code->bytecode_pos);
+ err=1;
+ break;
+ }
+ bytecode_append_long_int(current_block->code, offs); //i-offs
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case 0xAB: //loookupswitch...;
+ {
+ err=1;
+ addr = current_block->code->bytecode_pos-1;
+ while (current_block->code->bytecode_pos%4!=0) //4byte-align
+ bytecode_append(current_block->code, 0);
+ offs = RD_inline_offs(current_block, 4, addr);
+ if (offs != 0)
+ {
+ bytecode_append_long_int(current_block->code, offs); //default-offs
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ bytecode_append_long_int(current_block->code, integer_constant); //length
+ i=integer_constant;
+ current_token = yylex();
+ if (current_token == COMMA)
+ {
+ err=0;
+ for (; i>0; i--)
+ {
+ offs = 0;
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ bytecode_append_long_int(current_block->code, integer_constant);
+ offs = RD_inline_offs(current_block, 4, addr);
+ if (i>1)
+ {
+ current_token = yylex();
+ if (current_token != COMMA) offs = 0;
+ }
+ }
+ if (offs == 0) //bad label
+ {
+ add_error_message(462, 0, current_block->code->bytecode_pos);
+ err=1;
+ break;
+ }
+ bytecode_append_long_int(current_block->code, offs); //i-offs
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ /*
+ case 0xC4: //wide;
+ break;
+ */
+ case 0xFF:
+ err=1;
+ break;
+ }
+ }
+ else if (current_token == CST_INTEGER)
+ {
+ if (integer_constant<=255) bytecode_append(current_block->code, (char)integer_constant);
+ else if (integer_constant<=65535) bytecode_append_short_int(current_block->code, (short)integer_constant);
+ else bytecode_append_long_int(current_block->code, integer_constant);
+ err=0;
+ }
+ else if (current_token == COLON) //SET LABEL
+ {
+ err=1;
+ current_token = yylex();
+ if (current_token == CST_INTEGER)
+ {
+ nam[0]=integer_constant;
+ len[0]=0;
+ i=labcount;
+ while ((nam[i]!=integer_constant) || (len[i]!=0)) i--;
+ if (i==0)
+ {
+ labcount++;
+ nam[labcount] = integer_constant;
+ len[labcount] = 0;
+ lab[labcount] = current_block->code->bytecode_pos;
+ err=0;
+ }
+ else
+ {
+ add_error_message(461, nam[i], current_block->code->bytecode_pos);
+ labcount=0;
+ }
+
+ }
+ }
+ else err=1;
+ /////////
+ if (err==0)
+ {
+ current_token = yylex();
+ if (current_token != SEMI_COLON) err=1;
+ }
+ } while (err==0);
+ //modify old label
+ for (i=labcount; i>0; i--) if (len[i]>0)
+ {
+ for (j=labcount; j>i; j--) if (len[j]==0) if (nam[i]==nam[j]) break;
+ if (j>i)
+ {
+ int k;
+ offs = 0;
+ for (k = lab[i]; k<lab[i]+len[i]; k++)
+ offs = (offs << 8) + (current_block->code->bytecode[k] & 0xff);
+ offs = lab[j]-offs;
+ for (k--; k>=lab[i]; k--)
+ {
+ current_block->code->bytecode[k] = (char)offs;
+ offs = offs>>8;
+ }
+ }
+ else add_error_message(460, nam[i], lab[i]);
+ }
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////// END JAVA - ASM ///////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+/*
+ Handles the if-then-[else] statement. The grammar rule
+ is:
+
+ <RD_if_statement> -> <RD_expression> then <RD_statement>
+ [ else <RD_statement> ]
+
+*/
+void RD_if_statement(block *current_block)
+{
+ type *expression_type;
+ long int jump_offset_position;
+ signed short int offset;
+
+ expression_type = RD_expression(current_block);
+
+ if ((expression_type->type_class != error_type) /* a simple error-recovery */
+ && (expression_type->type_class != boolean_type))
+ {
+ add_error_message(407, "boolean", "");
+ }
+
+ type_destroy(expression_type);
+
+ if (current_token != KWD_THEN)
+ {
+ add_error_message(216, YYTEXT_STRING, "");
+ }
+
+ current_token = yylex();
+
+ /* generate the code */
+ bytecode_append(current_block->code, ifeq$); /* branch if comparison with zero succedd */
+ jump_offset_position = current_block->code->bytecode_pos;
+ bytecode_append(current_block->code, 0); /* the place for offset of where to jump */
+ bytecode_append(current_block->code, 0);
+
+ RD_statement(current_block);
+
+ while (current_token == SEMI_COLON)
+ current_token = yylex();
+
+ if (current_token == KWD_ELSE)
+ {
+ /* set the address of the next instruction */
+ offset = (short) (current_block->code->bytecode_pos + 4 - jump_offset_position);
+ current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
+ current_block->code->bytecode[jump_offset_position+1] = (char) offset;
+
+ bytecode_append(current_block->code, goto$);
+ jump_offset_position = current_block->code->bytecode_pos;
+ bytecode_append(current_block->code, 0);
+ bytecode_append(current_block->code, 0);
+
+ current_token = yylex();
+
+ RD_statement(current_block);
+
+ /* set the adress of the next instruction */
+ offset = (short) (current_block->code->bytecode_pos - jump_offset_position + 1);
+ current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
+ current_block->code->bytecode[jump_offset_position+1] = (char) offset;
+ }
+ else
+ {
+ char *yycopy;
+ int i;
+
+ /* set the address of the next instruction */
+ offset = (short) (current_block->code->bytecode_pos - jump_offset_position + 1);
+ current_block->code->bytecode[jump_offset_position] = (char) (offset>>8);
+ current_block->code->bytecode[jump_offset_position+1] = (char) offset;
+
+ /* put the current token back to stream and preceed it with ';' */
+ yycopy = strdup(yytext);
+
+ for(i = strlen(yytext) - 1; i >= 0; i--)
+ backchar(yycopy[i]);
+ backchar(';');
+ free(yycopy);
+
+ current_token = yylex();
+ }
+}
+
+/*
+ The case-of statement. The rule used is:
+
+ <RD_case_statement> -> <RD_expression> OF
+ <RD_case_list> end
+*/
+void RD_case_statement(block *current_block)
+{
+ type *expression_type;
+ expression_type = RD_expression(current_block);
+
+ add_error_message(442, "", "");
+
+ if ((expression_type->type_class != error_type) /* a simple error-recovery */
+ && (expression_type->type_class != integer_type)
+ && (expression_type->type_class != char_type)
+ && (expression_type->type_class != string_type))
+ {
+ add_error_message(408, "", "");
+ }
+
+ if (current_token != KWD_OF)
+ {
+ add_error_message(203, "of", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ RD_case_list(current_block, expression_type);
+
+ if (current_token != KWD_END)
+ {
+ add_error_message(203, "end", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+ type_destroy(expression_type);
+}
+
+
+/*
+ The case expression's list.
+
+ <RD_case_list> -> ( CONST (, CONST)* : <RD_statement> )+
+*/
+void RD_case_list(block *current_block, type *case_type)
+{
+ short int first_pass = 1;
+
+ do
+ {
+ if (first_pass)
+ first_pass = 0;
+ else
+ current_token = yylex();
+
+ switch(current_token)
+ {
+ case CST_INTEGER:
+ {
+ if (case_type->type_class != integer_type)
+ {
+ string *expected_type_name;
+ expected_type_name = type_get_name(case_type);
+ add_error_message(409, string_get_cstr(expected_type_name), "integer");
+ string_destroy(expected_type_name);
+ }
+ current_token = yylex();
+ break;
+ }
+
+ case CST_REAL:
+ {
+ string *expected_type_name;
+ expected_type_name = type_get_name(case_type);
+ add_error_message(409, string_get_cstr(expected_type_name), "real");
+ string_destroy(expected_type_name);
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_BOOLEAN:
+ {
+
+ string *expected_type_name;
+ expected_type_name = type_get_name(case_type);
+ add_error_message(409, string_get_cstr(expected_type_name), "boolean");
+ string_destroy(expected_type_name);
+
+ current_token = yylex();
+ break;
+ }
+
+ case CST_CHAR:
+ {
+ if (case_type->type_class != char_type)
+ {
+ string *expected_type_name;
+ expected_type_name = type_get_name(case_type);
+ add_error_message(409, string_get_cstr(expected_type_name), "char");
+ string_destroy(expected_type_name);
+ }
+ current_token = yylex();
+ break;
+ }
+
+ case CST_STRING:
+ {
+ if (case_type->type_class != string_type)
+ {
+ string *expected_type_name;
+ expected_type_name = type_get_name(case_type);
+ add_error_message(409, string_get_cstr(expected_type_name), "string");
+ string_destroy(expected_type_name);
+ }
+ current_token = yylex();
+ break;
+ }
+
+ case IDENTIFIER:
+ {
+ /* find the constant type for the given identifier */
+ type *constant_type;
+
+ constant_type = get_constant_type(current_block, YYTEXT_STRING);
+
+ if (constant_type->type_class == error_type)
+ add_error_message(410, YYTEXT_STRING, "");
+ else
+ if (!type_equal(constant_type, case_type))
+ {
+ string *expected_type_name;
+ string *constant_type_name;
+
+ expected_type_name = type_get_name(case_type);
+ constant_type_name = type_get_name(constant_type);
+
+ add_error_message(409, string_get_cstr(expected_type_name), string_get_cstr(constant_type_name));
+
+ string_destroy(expected_type_name);
+ string_destroy(constant_type_name);
+ }
+
+ type_destroy(constant_type);
+
+ current_token = yylex();
+ break;
+ }
+
+ default:
+ {
+ add_error_message(206, "", "");
+
+ /* Error-recovery: find the first : */
+ while ((current_token != COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ return;
+
+ break;
+ }
+ }
+
+
+ } while (current_token == COMMA);
+
+ current_token = yylex();
+
+ if (current_token != COLON)
+ {
+ add_error_message(200, ":", YYTEXT_STRING);
+
+ /* Error-recovery: find the first : */
+ while ((current_token != COLON)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ return;
+ }
+
+ current_token = yylex();
+
+ RD_statement(current_block);
+}
+
+
+/*
+ The while-do statement.
+
+ <RD_while_statement> -> <RD_expression> do <RD_statement>
+*/
+void RD_while_statement(block *current_block)
+{
+ type *expression_type;
+ int pos1, pos2;
+ int jump_offset_position;
+ int jump_offset;
+ int break_pos1, break_pos2;
+
+ pos1 = current_block->code->bytecode_pos;
+
+ expression_type = RD_expression(current_block);
+
+ pos2 = current_block->code->bytecode_pos;
+ bytecode_append(current_block->code, ifeq$);
+ jump_offset_position = current_block->code->bytecode_pos;
+ bytecode_append_short_int(current_block->code, 0); /* make place for offset value */
+
+ if ((expression_type->type_class != error_type) /* a simple error-recovery */
+ && (expression_type->type_class != boolean_type))
+ {
+ add_error_message(407, "boolean", "");
+ }
+
+ type_destroy(expression_type);
+
+ if (current_token != KWD_DO)
+ {
+ add_error_message(203, "do", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+
+ inside_loop++;
+ break_pos1 = current_block->code->bytecode_pos;
+ RD_statement(current_block);
+ break_pos2 = current_block->code->bytecode_pos;
+ inside_loop --;
+
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
+
+ jump_offset = current_block->code->bytecode_pos - pos2;
+ current_block->code->bytecode[jump_offset_position] = (char)(jump_offset >> 8);
+ current_block->code->bytecode[jump_offset_position + 1] = (char) jump_offset;
+
+ transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
+}
+
+
+// j-a-s-d: besides
+//
+// current_token = yylex();
+//
+// bytecode_append(current_block->code, goto$);
+// bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
+//
+// transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
+//
+// is the exact implementation of forever,
+// the lesser impact implementation of repeat/forever to this MP compiler seems to be an "until false"
+
+type* RD_forever(block *current_block)
+{
+ type *return_type;
+ return_type = type_create();
+ bytecode_append(current_block->code, iconst_0$);
+ current_token = yylex();
+ return_type->type_class = boolean_type;
+ return return_type;
+}
+
+/*
+ The repeat-until statement.
+
+ <RD_repeat_statement> -> <RD_block_body> until <RD_expression>
+*/
+
+void RD_repeat_statement(block *current_block)
+{
+ type *expression_type;
+
+ int pos1;
+ int break_pos1, break_pos2;
+
+ pos1 = current_block->code->bytecode_pos;
+ inside_loop ++;
+ break_pos1 = current_block->code->bytecode_pos;
+ RD_block_body(current_block);
+ break_pos2 = current_block->code->bytecode_pos;
+ inside_loop --;
+
+ if (current_token == KWD_FOREVER)
+ {
+ expression_type = RD_forever(current_block);
+ } else {
+ if (current_token != KWD_UNTIL)
+ {
+ add_error_message(203, "until", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ expression_type = RD_expression(current_block);
+ }
+ /* generate the code */
+ bytecode_append(current_block->code, ifeq$);
+ bytecode_append_short_int(current_block->code, pos1 - current_block->code->bytecode_pos + 1);
+
+ if ((expression_type->type_class != error_type) /* a simple error-recovery */
+ && (expression_type->type_class != boolean_type))
+ {
+ add_error_message(407, "boolean", "");
+ }
+
+ transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
+
+ type_destroy(expression_type);
+}
+
+
+
+/*
+ The for statement.
+
+ <RD_for_statement> -> IDN := <RD_expression> (to | downto)
+ <RD_expression> do <RD_statement>
+*/
+void RD_for_statement(block *current_block)
+{
+ type *iterator_type;
+ type *expression1_type;
+ type *expression2_type;
+ identifier *iterator;
+ string *iterator_name;
+ int is_field;
+ int check_bytecode_pos;
+ int direction;
+ int evaluate_pos;
+ int break_pos1, break_pos2;
+
+ iterator_type = get_variable_type(current_block, YYTEXT_STRING);
+ iterator = get_identifier(current_block, YYTEXT_STRING);
+ iterator_name = string_from_cstr(YYTEXT_STRING);
+
+ if (iterator->identifier_class == unit_name)
+ {
+ add_error_message(456, "", "");
+ current_token = yylex();
+ current_token = yylex();
+ }
+
+ if ((iterator_type->type_class != integer_type)
+ && (iterator_type->type_class != char_type))
+ {
+ add_error_message(411, "", "");
+ }
+
+ if (current_token != IDENTIFIER)
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first := */
+ while ((current_token != OP_ASSIGN)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ if (current_token == END_OF_INPUT)
+ {
+ type_destroy(iterator_type);
+ string_destroy(iterator_name);
+ return;
+ }
+ }
+ else
+ current_token = yylex();
+
+ if (current_token != OP_ASSIGN)
+ {
+ add_error_message(209, YYTEXT_STRING, "");
+ }
+ else
+ current_token = yylex();
+
+ expression1_type = RD_expression(current_block);
+
+ is_field = iterator->belongs_to_program_block;
+ create_put_variable_bytecode(iterator, current_block->code, iterator_name->cstr, is_field);
+
+ if (!type_equal(iterator_type, expression1_type))
+ {
+ string *name1, *name2;
+ name1 = type_get_name(iterator_type);
+ name2 = type_get_name(expression1_type);
+
+ add_error_message(412, string_get_cstr(name1), string_get_cstr(name2));
+
+ string_destroy(name1);
+ string_destroy(name2);
+ }
+
+ switch (current_token)
+ {
+ case KWD_TO:
+ {
+ direction = 1;
+ current_token = yylex();
+ break;
+ }
+
+ case KWD_DOWNTO:
+ {
+ direction = -1;
+ current_token = yylex();
+ break;
+ }
+
+ default:
+ {
+ add_error_message(204, YYTEXT_STRING, "");
+ break;
+ }
+ }
+
+ evaluate_pos = current_block->code->bytecode_pos;
+ expression2_type = RD_expression(current_block);
+
+ create_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
+
+ check_bytecode_pos = current_block->code->bytecode_pos;
+ if (direction == 1)
+ bytecode_append(current_block->code, if_icmplt$);
+ else
+ bytecode_append(current_block->code, if_icmpgt$);
+
+ bytecode_append_short_int(current_block->code, 0);
+
+ if (!type_equal(iterator_type, expression2_type))
+ {
+ string *name1, *name2;
+ name1 = type_get_name(iterator_type);
+ name2 = type_get_name(expression2_type);
+
+ add_error_message(412, string_get_cstr(name1), string_get_cstr(name2));
+
+ string_destroy(name1);
+ string_destroy(name2);
+ }
+
+ if (current_token != KWD_DO)
+ {
+ add_error_message(203, "do", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+
+ inside_loop ++;
+ break_pos1 = current_block->code->bytecode_pos;
+ RD_statement(current_block);
+ break_pos2 = current_block->code->bytecode_pos;
+ inside_loop --;
+
+
+ // TODO:: moguca optimizacija za neke slucajeve sa iinc$ naredbom
+ create_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
+
+ if (direction == 1)
+ bytecode_append(current_block->code, iconst_1$);
+ else
+ bytecode_append(current_block->code, iconst_m1$);
+
+ bytecode_append(current_block->code, iadd$);
+
+ create_put_variable_bytecode(iterator, current_block->code, iterator_name->cstr, iterator->belongs_to_program_block);
+
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, evaluate_pos - current_block->code->bytecode_pos + 1);
+
+ current_block->code->bytecode[check_bytecode_pos + 1] = (char) ((current_block->code->bytecode_pos - check_bytecode_pos)>>8);
+ current_block->code->bytecode[check_bytecode_pos + 2] = (char) (current_block->code->bytecode_pos - check_bytecode_pos);
+
+
+ transform_break_stmts(current_block->code, break_pos1, break_pos2, current_block->code->bytecode_pos);
+
+ type_destroy(iterator_type);
+ type_destroy(expression1_type);
+ type_destroy(expression2_type);
+ string_destroy(iterator_name);
+}
+
+
+/*
+ Type declaration:
+
+ <RD_type> -> <RD_basic_type>
+ | [packed] array <RD_array_declaration>
+ | record <RD_record_declaration>
+ | file <RD_file_declaration>
+ | set <RD_set_declaration> currently unsupported !!!
+*/
+type* RD_type(block *current_block)
+{
+ switch (current_token)
+ {
+ case KWD_PACKED:
+ {
+ add_warning_message(210, "", "");
+ current_token = yylex();
+ if (current_token != KWD_ARRAY)
+ add_error_message(203, "array", YYTEXT_STRING);
+ //no_break;
+ }
+
+ case KWD_ARRAY:
+ {
+ current_token = yylex();
+ return RD_array_declaration(current_block);
+ }
+
+ case KWD_RECORD:
+ {
+ current_token = yylex();
+ return RD_record_declaration(current_block);
+ }
+
+ case KWD_FILE:
+ {
+ current_token = yylex();
+ return RD_file_declaration(current_block);
+ }
+
+ case KWD_SET:
+ {
+ type *error;
+ error = type_create();
+ error->type_class = error_type;
+ add_error_message(211, "", "");
+ current_token = yylex();
+ RD_set_declaration(current_block);
+ return error;
+ }
+
+ default:
+ {
+ return RD_basic_type(current_block);
+ break;
+ }
+ }
+}
+
+
+/*
+ Basic type:
+
+ <RD_basic_type> -> [IDN .] IDN
+ | CONST .. CONST
+ | "(" IDN (, IDN)* ")" enumerated types are not supported
+*/
+type* RD_basic_type(block *current_block)
+{
+ type *return_type;
+ return_type = type_create();
+ return_type->type_class = error_type;
+
+ switch (current_token)
+ {
+ case IDENTIFIER:
+ {
+ identifier* name;
+ type *declared_type;
+ declared_type = type_from_name(current_block, YYTEXT_STRING);
+
+ lowercase(YYTEXT_STRING);
+
+ name = get_identifier(current_block, YYTEXT_STRING);
+
+ if (name->identifier_class == unit_name)
+ {
+ identifier* type_identifier;
+
+ current_token = yylex();
+
+ if (current_token != DOT)
+ add_error_message(200, ".", YYTEXT_STRING);
+ else
+ current_token = yylex();
+
+ type_identifier = name_table_find_cstr(name->unit_block->names, YYTEXT_STRING);
+
+ if (type_identifier == NULL)
+ add_error_message(455, YYTEXT_STRING, "");
+ else
+ declared_type = type_duplicate(type_identifier->defined_type);
+ }
+
+ identifier_destroy(name);
+
+ if (declared_type->type_class != error_type)
+ {
+ type_destroy(return_type);
+ return_type = type_duplicate(declared_type);
+ current_token = yylex();
+ type_destroy(declared_type);
+ }
+ else
+ {
+ identifier *constant_identifier;
+ constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
+
+ type_destroy(declared_type);
+
+ if ((constant_identifier->identifier_class == constant_name)
+ && ((constant_identifier->constant_type->type_class == integer_type)
+ || (constant_identifier->constant_type->type_class == char_type)))
+ {
+ return_type->type_class = interval_type;
+ return_type->interval_base_type = constant_identifier->constant_type->type_class;
+
+ if (constant_identifier->constant_type->type_class == integer_type)
+ return_type->first_element = constant_identifier->constant_int_value;
+ else
+ return_type->first_element = constant_identifier->constant_int_value;
+
+ return_type->last_element = return_type->first_element + 1;
+
+ identifier_destroy(constant_identifier);
+
+ current_token = yylex();
+
+ if (current_token != DOTDOT)
+ {
+ add_error_message(213, YYTEXT_STRING, "");
+
+ /* Error-recovery */
+ while ((current_token != CLOSE_SQ_BR)
+ && (current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ break;
+ }
+
+ current_token = yylex();
+
+ if (current_token == IDENTIFIER)
+ {
+ constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
+
+ if ((constant_identifier->identifier_class != constant_name)
+ || (constant_identifier->constant_type->type_class != return_type->interval_base_type))
+ {
+ add_error_message(416, "", "");
+ }
+ else
+ {
+ if (return_type->interval_base_type == integer_type)
+ return_type->last_element = constant_identifier->constant_int_value;
+ else
+ return_type->last_element = constant_identifier->constant_int_value;
+ }
+
+ identifier_destroy(constant_identifier);
+ }
+ else if (current_token == CST_INTEGER)
+ {
+ if (return_type->interval_base_type != integer_type)
+ add_error_message(416, "", "");
+
+ return_type->last_element = integer_constant;
+ }
+ else if (current_token == CST_CHAR)
+ {
+ if (return_type->interval_base_type != char_type)
+ add_error_message(416, "", "");
+
+ return_type->last_element = char_constant;
+ }
+ else
+ {
+ add_error_message(416, "", "");
+ }
+
+ current_token = yylex();
+
+ }
+ else
+ {
+ add_error_message(415, YYTEXT_STRING, "");
+ current_token = yylex();
+ identifier_destroy(constant_identifier);
+ }
+ }
+
+
+
+ break;
+ }
+
+ case CST_INTEGER:
+ case CST_CHAR:
+ {
+ return_type->type_class = interval_type;
+
+ if (current_token == CST_INTEGER)
+ {
+ return_type->interval_base_type = integer_type;
+ return_type->first_element = integer_constant;
+ }
+ else
+ {
+ return_type->interval_base_type = char_type;
+ return_type->first_element = (long int) char_constant;
+ }
+
+ return_type->last_element = return_type->first_element + 1;
+
+ current_token = yylex();
+
+ if (current_token != DOTDOT)
+ {
+ add_error_message(213, YYTEXT_STRING, "");
+ }
+
+ current_token = yylex();
+
+ if ((current_token != IDENTIFIER)
+ && (current_token != CST_INTEGER)
+ && (current_token != CST_CHAR))
+ {
+ add_error_message(217, "", "");
+ }
+ else
+ {
+ if (current_token == IDENTIFIER)
+ {
+ type *constant_type;
+ identifier *constant_identifier;
+
+ constant_type = get_constant_type(current_block, YYTEXT_STRING);
+
+ if (constant_type->type_class != return_type->interval_base_type)
+ {
+ add_error_message(413, "", "");
+ }
+
+ type_destroy(constant_type);
+
+ constant_identifier = get_constant_identifier(current_block, YYTEXT_STRING);
+
+ if (constant_identifier->identifier_class != constant_name)
+ {
+ add_error_message(414, YYTEXT_STRING, "");
+ }
+ else
+ {
+ if (return_type->interval_base_type == integer_type)
+ return_type->last_element = constant_identifier->constant_int_value;
+ else
+ return_type->last_element = constant_identifier->constant_int_value;
+ }
+
+ identifier_destroy(constant_identifier);
+
+ }
+ else if (current_token == CST_INTEGER)
+ {
+ return_type->last_element = integer_constant;
+ }
+ else
+ {
+ return_type->last_element = (long int) char_constant;
+ }
+ }
+
+ current_token = yylex();
+
+ break;
+ }
+
+ case OPEN_BR:
+ {
+ int brack_count = 1;
+ add_error_message(212, "", "");
+
+ while (brack_count > 0)
+ {
+ current_token = yylex();
+
+ if (current_token == OPEN_BR)
+ brack_count ++;
+
+ if (current_token == CLOSE_BR)
+ brack_count --;
+
+ if (current_token == END_OF_INPUT)
+ return return_type;
+ }
+
+ current_token = yylex();
+
+ break;
+ }
+
+ default:
+ {
+ add_error_message(204, YYTEXT_STRING, "");
+ while ((current_token != CLOSE_SQ_BR)
+ && (current_token != SEMI_COLON)
+ && (current_token != END_OF_INPUT)
+ && (current_token != KWD_END))
+ {
+ current_token = yylex();
+ }
+
+ break;
+ }
+ }
+
+ return return_type;
+}
+
+
+/*
+ The declaration of an array.
+
+ <RD_array_declaration> -> "[" (<RD_basic_type> (, <RD_basic_type>)* )+ "]" of <RD_type>
+*/
+type* RD_array_declaration(block *current_block)
+{
+ type *new_type;
+ type *dimension;
+
+ new_type = type_create();
+ new_type->type_class = array_type;
+
+ new_type->dimensions_list = type_list_create();
+
+ if (current_token != OPEN_SQ_BR)
+ {
+ add_error_message(200, "[", YYTEXT_STRING);
+ }
+
+ do
+ {
+ current_token = yylex();
+
+ dimension = RD_basic_type(current_block);
+
+ if (dimension->type_class != interval_type)
+ {
+ add_error_message(430, "", "");
+ }
+
+ type_list_append(new_type->dimensions_list, dimension);
+ type_destroy(dimension);
+
+ if ((current_token != CLOSE_SQ_BR)
+ && (current_token != COMMA))
+ {
+ add_error_message(200, ",", YYTEXT_STRING);
+ }
+
+ if (current_token == END_OF_INPUT)
+ {
+ add_error_message(207, "", "");
+ type_destroy(new_type);
+ new_type = type_create();
+ new_type->type_class = error_type;
+ return new_type;
+ }
+
+ } while (current_token != CLOSE_SQ_BR);
+
+ current_token = yylex();
+
+ if (current_token != KWD_OF)
+ {
+ add_error_message(203, "of", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ new_type->element_type = RD_type(current_block);
+
+ return new_type;
+}
+
+
+/*
+ The declaration of a record.
+
+ <RD_record_declaration> -> <RD_identifier_list> ":" <RD_type>
+ ( <RD_identifier_list> ":" <RD_type> )* end
+*/
+type* RD_record_declaration(block *current_block)
+{
+ type *new_type;
+ string_list *identifier_list;
+ type *element_type;
+ int old_linenum, tmp;
+
+ short int first_pass = 1;
+
+ new_type = type_create();
+ new_type->type_class = record_type;
+ new_type->elements_name_list = string_list_create();
+ new_type->elements_type_list = type_list_create();
+ new_type->unique_record_ID = next_record_ID;
+
+ next_record_ID ++;
+
+ do
+ {
+ if (first_pass)
+ first_pass = 0;
+ else
+ current_token = yylex();
+
+ if ((current_token == KWD_END)
+ || (current_token == END_OF_INPUT))
+ break;
+
+ identifier_list = RD_identifier_list(current_block, 0);
+
+ if (current_token != COLON)
+ {
+ add_error_message(200, ":", YYTEXT_STRING);
+ }
+
+ old_linenum = linenum;
+ current_token = yylex();
+
+ element_type = RD_type(current_block);
+
+ if (element_type->type_class == interval_type)
+ {
+ add_error_message(440, "", "");
+ element_type->type_class = integer_type;
+ }
+
+ tmp = linenum;
+ linenum = old_linenum;
+
+ type_add_record(new_type, identifier_list, element_type);
+
+ linenum = tmp;
+
+ string_list_destroy(identifier_list);
+ type_destroy(element_type);
+
+ } while (current_token == SEMI_COLON);
+
+ if (current_token != KWD_END)
+ {
+ add_error_message(214, YYTEXT_STRING, "");
+ }
+
+ current_token = yylex();
+
+ create_record_class(new_type);
+
+ return new_type;
+}
+
+
+/*
+ The declaration of a file
+
+ <RD_file_declaration> -> of IDN
+*/
+type* RD_file_declaration(block *current_block)
+{
+ type *file_type;
+ file_type = type_create();
+ file_type->type_class = error_type;
+ if (current_token != KWD_OF)
+ {
+ add_error_message(203, "of", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+// !!!! TODO:: dodati podrsku za fajlove
+ current_token = yylex();
+ add_error_message(435, "", "");
+ return file_type;
+}
+
+
+/*
+ Sets are not supported yet, however, this rule is used
+ as an error-recovery rule if someone tries to use sets.
+
+ <RD_set_declaration> -> of <RD_basic_type>
+*/
+void RD_set_declaration(block *current_block)
+{
+ current_token = yylex();
+
+ RD_basic_type(current_block);
+}
+
+
+/*
+ Handle the expressions, the relational operators.
+
+ <RD_expression> -> <RD_sum> [<rel_operator> <RD_sum>]
+*/
+type* RD_expression(block *current_block)
+{
+ int old_linenum;
+ int old_token;
+ type *type1, *type2;
+
+ type1 = RD_sum(current_block);
+
+ if ((current_token == OP_LESS)
+ || (current_token == OP_LESS_EQUAL)
+ || (current_token == OP_GREATER_EQUAL)
+ || (current_token == OP_GREATER)
+ || (current_token == OP_EQUAL)
+ || (current_token == OP_NOT_EQUAL))
+ {
+ old_token = current_token;
+ current_token = yylex();
+
+ old_linenum = linenum;
+ type2 = RD_sum(current_block);
+
+ if ((type2->type_class != integer_type)
+ && (type2->type_class != real_type)
+ && (type2->type_class != char_type)
+ && (type2->type_class != string_type)
+ && (type2->type_class != boolean_type)
+ && (type2->type_class != error_type)
+ && (type2->type_class != command_type))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+ else
+ {
+ int cast;
+ cast = type_equal_cast(type1, type2);
+
+ if (cast == 0){
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ /* if operands need to be casted */
+ if ((type1->type_class == integer_type)
+ || (type2->type_class == integer_type))
+ {
+ if (cast != 1)
+ {
+ usesFloat=1;
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+ }
+
+ }
+ else
+ {
+ if ((cast == 2) || (cast == 3))
+ {
+ int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ /* string cast */
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+ }
+ }
+
+ if (cast == 3) /* return the real type if cast happened */
+ {
+ type *tmp;
+ tmp = type2;
+ type2 = type1;
+ type1 = tmp;
+ }
+
+ /* create the code */
+ if ((type1->type_class == integer_type)
+ || (type1->type_class == boolean_type)
+ || (type1->type_class == char_type)
+ || ((type1->type_class == real_type) && (mathType == 1)))
+ {
+ if (type1->type_class == real_type)
+ usesFloat = 1;
+
+ switch (old_token)
+ {
+ case OP_LESS:
+ bytecode_append(current_block->code, if_icmplt$);
+ break;
+ case OP_LESS_EQUAL:
+ bytecode_append(current_block->code, if_icmple$);
+ break;
+ case OP_GREATER_EQUAL:
+ bytecode_append(current_block->code, if_icmpge$);
+ break;
+ case OP_GREATER:
+ bytecode_append(current_block->code, if_icmpgt$);
+ break;
+ case OP_EQUAL:
+ bytecode_append(current_block->code, if_icmpeq$);
+ break;
+ case OP_NOT_EQUAL:
+ bytecode_append(current_block->code, if_icmpne$);
+ break;
+ }
+
+ /* create the rest of the jumping and setting the whatever code */
+ bytecode_append_short_int(current_block->code, 7);
+ bytecode_append(current_block->code, iconst_0$);
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, 4);
+ bytecode_append(current_block->code, iconst_m1$);
+ }
+
+ if ((type1->type_class == real_type) && (mathType != 1))
+ {
+ usesFloat = 1;
+ bytecode_append(current_block->code, invokevirtual$);
+
+ switch (old_token)
+ {
+ case OP_LESS:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "lessThan", "(LReal;)Z"));
+ break;
+ case OP_LESS_EQUAL:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "lessEqual", "(LReal;)Z"));
+ break;
+ case OP_GREATER_EQUAL:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "greaterEqual", "(LReal;)Z"));
+ break;
+ case OP_GREATER:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "greaterThan", "(LReal;)Z"));
+ break;
+ case OP_EQUAL:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "equalTo", "(LReal;)Z"));
+ break;
+ case OP_NOT_EQUAL:
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "notEqualTo", "(LReal;)Z"));
+ break;
+ }
+
+ /* create the rest of the jumping and setting the whatever code */
+ bytecode_append(current_block->code, ifne$);
+ bytecode_append_short_int(current_block->code, 7);
+ bytecode_append(current_block->code, iconst_0$);
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, 4);
+ bytecode_append(current_block->code, iconst_m1$);
+ }
+
+ if (type1->type_class == command_type)
+ {
+ if (old_token == OP_EQUAL)
+ {
+ bytecode_append(current_block->code, if_acmpeq$);
+ }
+ else if (old_token == OP_NOT_EQUAL)
+ {
+ bytecode_append(current_block->code, if_acmpne$);
+ }
+ else
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ /* create the rest of the jumping and setting the whatever code */
+ bytecode_append_short_int(current_block->code, 7);
+ bytecode_append(current_block->code, iconst_0$);
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, 4);
+ bytecode_append(current_block->code, iconst_m1$);
+ }
+
+ }
+
+ if (type1->type_class == string_type)
+ {
+ int method_index = cp_add_methodref("java/lang/String", "compareTo", "(Ljava/lang/String;)I");
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, method_index);
+
+ switch (old_token)
+ {
+ case OP_LESS:
+ bytecode_append(current_block->code, iflt$);
+ break;
+ case OP_LESS_EQUAL:
+ bytecode_append(current_block->code, ifle$);
+ break;
+ case OP_GREATER_EQUAL:
+ bytecode_append(current_block->code, ifge$);
+ break;
+ case OP_GREATER:
+ bytecode_append(current_block->code, ifgt$);
+ break;
+ case OP_EQUAL:
+ bytecode_append(current_block->code, ifeq$);
+ break;
+ case OP_NOT_EQUAL:
+ bytecode_append(current_block->code, ifne$);
+ break;
+ }
+
+ /* create the rest of the jumping and setting the whatever code */
+ bytecode_append_short_int(current_block->code, 7);
+ bytecode_append(current_block->code, iconst_0$);
+ bytecode_append(current_block->code, goto$);
+ bytecode_append_short_int(current_block->code, 4);
+ bytecode_append(current_block->code, iconst_m1$);
+ }
+
+ type_destroy(type2);
+ type_destroy(type1);
+ /* the type of comparison is boolean */
+ type1 = type_create();
+ type1->type_class = boolean_type;
+ }
+
+ return type1;
+}
+
+
+/*
+ Handle +, -, or, xor operators.
+
+ <RD_sum> -> <RD_mult> (<sum_operator> <RD_mult>)*
+*/
+type* RD_sum(block *current_block)
+{
+ int old_linenum;
+ int old_token;
+
+ type *type1, *type2;
+
+ type1 = RD_mult(current_block);
+
+ while ((current_token == OP_PLUS)
+ || (current_token == OP_MINUS)
+ || (current_token == OP_OR)
+ || (current_token == OP_XOR))
+ {
+ old_token = current_token;
+
+ current_token = yylex();
+
+ old_linenum = linenum;
+
+ type2 = RD_mult(current_block);
+
+ if (((type2->type_class != integer_type)
+ && (type2->type_class != real_type)
+ && (type2->type_class != char_type)
+ && (type2->type_class != string_type)
+ && (type2->type_class != boolean_type)
+ && (type2->type_class != error_type))
+ || ((type1->type_class == string_type)
+ && (old_token != OP_PLUS)))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+ else
+ {
+ int cast;
+
+ /* if first type is char, cast it to string */
+ if (type1->type_class == char_type)
+ {
+ int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
+
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+ bytecode_append(current_block->code, swap$);
+
+ type1->type_class = string_type;
+ }
+
+ cast = type_equal_cast(type1, type2);
+
+ if ((cast == 0) && (type1->type_class != string_type)){
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ /* if operands need to be casted */
+ if ((type1->type_class != string_type)
+ && (cast != 1))
+ {
+ usesFloat=1;
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ if (cast == 3) /* return the real type if cast happened */
+ {
+ type *tmp;
+ tmp = type2;
+ type2 = type1;
+ type1 = tmp;
+ }
+
+ }
+ }
+
+
+ if ((type1->type_class != integer_type)
+ && (type1->type_class != boolean_type)
+ && (type1->type_class != error_type)
+ && ((old_token == OP_OR) || (old_token == OP_XOR)))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ /* create the code */
+ if ((type1->type_class == integer_type)
+ || (type1->type_class == boolean_type)
+ || ((type1->type_class == real_type) && (mathType == 1)))
+ {
+ if (type1->type_class == real_type)
+ usesFloat = 1;
+
+ switch (old_token)
+ {
+ case OP_PLUS:
+ bytecode_append(current_block->code, iadd$);
+ break;
+ case OP_MINUS:
+ bytecode_append(current_block->code, isub$);
+ break;
+ case OP_OR:
+ bytecode_append(current_block->code, ior$);
+ break;
+ case OP_XOR:
+ bytecode_append(current_block->code, ixor$);
+ break;
+ }
+ }
+
+ if ((type1->type_class == real_type) && (mathType != 1))
+ {
+ usesFloat = 1;
+ if (old_token == OP_PLUS)
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "add", "(LReal;)V"));
+
+ }
+
+ if (old_token == OP_MINUS)
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "sub", "(LReal;)V"));
+
+ }
+ }
+
+ if ((type1->type_class == string_type)
+ && (old_token == OP_PLUS))
+ {
+ int class_index;
+ int init_index;
+ int append_index;
+ int append2_index;
+ int toString_index;
+
+ if (type2->type_class == real_type)
+ {
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "tS", "(I)Ljava/lang/String;"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "toString", "()Ljava/lang/String;"));
+ }
+ }
+
+ class_index = cp_add_class("java/lang/StringBuffer");
+ init_index = cp_add_methodref("java/lang/StringBuffer", "<init>", "()V");
+ append_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
+ toString_index = cp_add_methodref("java/lang/StringBuffer", "toString", "()Ljava/lang/String;");
+
+ switch(type2->type_class)
+ {
+ case string_type:
+ case real_type:
+ append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
+ break;
+ case integer_type:
+ append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(I)Ljava/lang/StringBuffer;");
+ break;
+ case char_type:
+ bytecode_append(current_block->code, i2c$);
+ append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(C)Ljava/lang/StringBuffer;");
+ break;
+ case boolean_type:
+ bytecode_append(current_block->code, i2b$);
+ append2_index = cp_add_methodref("java/lang/StringBuffer", "append", "(Z)Ljava/lang/StringBuffer;");
+ break;
+ default:
+ add_error_message(434, "", "");
+ }
+
+ bytecode_append(current_block->code, swap$);
+
+ /* create new string buffer */
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, class_index);
+ bytecode_append(current_block->code, dup$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, init_index);
+
+ /* append the first argument */
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, append_index);
+
+ /* append the second argument */
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, append2_index);
+
+ /* convert StringBuffer into the String */
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, toString_index);
+
+
+
+ type_destroy(type2);
+ }
+
+ }
+
+ return type1;
+}
+
+
+/*
+ Handle * / div mod and operators.
+
+ <RD_mult> -> <RD_not> (<mult_operator> <RD_not>)*
+*/
+type* RD_mult(block *current_block)
+{
+ int old_linenum;
+ int old_token;
+ type *type1, *type2;
+
+ type1 = RD_not(current_block);
+
+ while ((current_token == OP_MULT)
+ || (current_token == OP_SLASH)
+ || (current_token == OP_DIV)
+ || (current_token == OP_MOD)
+ || (current_token == OP_AND)
+ || (current_token == OP_SHR)
+ || (current_token == OP_SHL)
+ || (current_token == OP_USHR))
+ {
+ old_token = current_token;
+
+ current_token = yylex();
+
+ old_linenum = linenum;
+
+ type2 = RD_not(current_block);
+
+ if ((type2->type_class != integer_type)
+ && (type2->type_class != real_type)
+ && (type2->type_class != boolean_type)
+ && (type2->type_class != error_type))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+ else
+ {
+ int cast;
+ cast = type_equal_cast(type1, type2);
+
+ if (cast == 0){
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ if (cast != 1)
+ {
+ /* if operands need to be casted */
+ usesFloat=1;
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+
+ if (cast == 3)
+ bytecode_append(current_block->code, swap$);
+
+ if (cast == 3) /* return the real type if cast happened */
+ {
+ type *tmp;
+ tmp = type2;
+ type2 = type1;
+ type1 = tmp;
+ }
+ }
+ }
+
+ type_destroy(type2);
+
+ if ((type1->type_class == real_type)
+ && (old_token != OP_MULT)
+ && (old_token != OP_SLASH))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ if ((type1->type_class == boolean_type)
+ && (old_token != OP_AND))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ /* generate the code */
+ if (type1->type_class == integer_type)
+ {
+ switch(old_token)
+ {
+ case OP_MULT:
+ bytecode_append(current_block->code, imul$);
+ break;
+ case OP_SLASH:
+ case OP_DIV:
+ bytecode_append(current_block->code, idiv$);
+ break;
+ case OP_MOD:
+ bytecode_append(current_block->code, irem$);
+ break;
+ case OP_AND:
+ bytecode_append(current_block->code, iand$);
+ break;
+ ///////////
+ case OP_SHR:
+ bytecode_append(current_block->code, ishr$);
+ break;
+ case OP_SHL:
+ bytecode_append(current_block->code, ishl$);
+ break;
+ // j-a-s-d
+ case OP_USHR:
+ bytecode_append(current_block->code, iushr$);
+ break;
+ }
+ }
+
+ if (type1->type_class == real_type)
+ {
+ usesFloat = 1;
+ switch(old_token)
+ {
+ case OP_MULT:
+ {
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code,
+ cp_add_methodref("F", "M", "(II)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$); ///
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "mul", "(LReal;)V"));
+ }
+ }
+ break;
+ case OP_SLASH:
+ {
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code,
+ cp_add_methodref("F", "D", "(II)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "div", "(LReal;)V"));
+ }
+ }
+ break;
+ }
+ }
+
+ if ((type1->type_class == boolean_type)
+ && (old_token == OP_AND))
+ {
+ bytecode_append(current_block->code, iand$);
+ }
+ }
+
+ return type1;
+}
+
+
+/*
+ The not operator.
+
+ <RD_not> -> [not] <RD_neg>
+*/
+type* RD_not(block *current_block)
+{
+ type *type1;
+ int is_not = 0;
+ int old_linenum;
+
+ if (current_token == OP_NOT)
+ {
+ current_token = yylex();
+ is_not = 1;
+ }
+
+ old_linenum = linenum;
+
+ type1 = RD_neg(current_block);
+
+ /* generate the code */
+ if (is_not)
+ {
+ bytecode_append(current_block->code, iconst_m1$);
+ bytecode_append(current_block->code, ixor$);
+ }
+
+ if ((is_not)
+ && (type1->type_class != integer_type)
+ && (type1->type_class != boolean_type)
+ && (type1->type_class != error_type))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ return type1;
+}
+
+
+/*
+ The - sign operator.
+
+ <RD_neg> -> ["-"] <RD_value>
+*/
+type* RD_neg(block *current_block)
+{
+ type *type1;
+ int is_neg = 0;
+ int old_linenum;
+
+ if (current_token == OP_MINUS)
+ {
+ current_token = yylex();
+ is_neg = 1;
+ }
+
+ old_linenum = linenum;
+
+ type1 = RD_value(current_block);
+
+ /* generate the code */
+ if (is_neg)
+ {
+ if ((type1->type_class == integer_type)
+ || ((type1->type_class == real_type) && (mathType == 1)))
+ bytecode_append(current_block->code, ineg$);
+
+ if ((type1->type_class == real_type) && (mathType != 1))
+ {
+ usesFloat = 1;
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(current_block->code, dup$);
+ bytecode_append(current_block->code, invokevirtual$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "neg", "()V"));
+ }
+ }
+
+ if ((type1->type_class != real_type)
+ && (type1->type_class != integer_type)
+ && (type1->type_class != error_type)
+ && (is_neg))
+ {
+ new_linenum=old_linenum;
+ add_error_message(417, "", "");
+ }
+
+ return type1;
+}
+
+
+/*
+ The expression that calls a procedure or
+ assigns a value to a variable.
+
+ <RD_assignment_or_procedure_call>
+
+ -> IDN ["[" <RD_expression_list> "]" ] (. IDN ["[" <RD_expression_list> "]" ])* := <RD_expression>
+ -> IDN ["(" <RD_expression_list> ")"]
+
+*/
+void RD_assignment_or_procedure_call(block *current_block)
+{
+ identifier *name;
+ string *element_name;
+ char *identifier_text;
+
+ if (current_token == KWD_RESULT) { // j-a-s-d
+ if (inside_routine == 0) // result in main block
+ {
+ add_error_message(463, "result", "");
+ current_token = yylex();
+ return;
+ }
+ name = get_identifier(current_block, string_get_cstr(str_currrent_routine_name));
+ element_name = str_currrent_routine_name;
+ if (name->identifier_class == procedure_name) // result in procedure
+ {
+ add_error_message(463, "result", "");
+ current_token = yylex();
+ identifier_destroy(name);
+ string_destroy(element_name);
+ return;
+ }
+ } else {
+ name = get_identifier(current_block, YYTEXT_STRING);
+ element_name = string_from_cstr(YYTEXT_STRING);
+ }
+
+ procedure_linenum = linenum;
+
+ if ((current_token != IDENTIFIER) && (current_token != KWD_RESULT)) // j-a-s-d
+ {
+ add_error_message(202, "", "");
+
+ /* Error-recovery: find the first ";", end, "." or <<EOF>> */
+ while ((current_token != SEMI_COLON)
+ && (current_token != DOT)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ string_destroy(element_name);
+ return;
+ }
+
+
+ if ((name->identifier_class == none)
+ || (name->identifier_class == program_name)
+ || (name->identifier_class == constant_name)
+ || (name->identifier_class == type_name))
+ {
+
+ add_error_message(428, YYTEXT_STRING, "");
+ current_token = yylex();
+ identifier_destroy(name);
+ string_destroy(element_name);
+ return;
+ }
+
+ current_token = yylex();
+
+ if (name->identifier_class == unit_name)
+ {
+ identifier *unit_name;
+ type_list *params;
+ if (current_token != DOT)
+ {
+ add_error_message(200, ".", YYTEXT_STRING);
+ while (current_token != SEMI_COLON)
+ current_token = yylex();
+ return;
+ }
+
+ current_token = yylex();
+ unit_name = name_table_find(name->unit_block->names, string_from_cstr(YYTEXT_STRING));
+ identifier_text = malloc(strlen(YYTEXT_STRING) + 1);
+ strcpy(identifier_text, YYTEXT_STRING);
+ string_destroy(element_name);
+ element_name = string_from_cstr(YYTEXT_STRING);
+
+ if (unit_name == NULL)
+ {
+ add_error_message(453, YYTEXT_STRING, "");
+ add_error_message(200, ".", YYTEXT_STRING);
+ while (current_token != SEMI_COLON)
+ current_token = yylex();
+ return;
+ }
+
+ name = identifier_duplicate(unit_name);
+ current_token = yylex();
+
+ if (name->identifier_class == procedure_name)
+ goto procedure_call;
+ if (name->identifier_class == variable_name)
+ goto variable_lvalue;
+
+ add_error_message(457, YYTEXT_STRING, "");
+ }
+
+
+ /* the name belongs to a procedure */
+ if (name->identifier_class == procedure_name)
+ {
+procedure_call:
+ if (name->standard_function)
+ {
+ create_std_function_prefix(current_block->code, element_name->cstr);
+ }
+
+ if (type_list_length(name->parameters) == 0)
+ {
+ int br_depth = 0;
+ if (current_token == OPEN_BR)
+ {
+ add_error_message(419, "", "");
+ br_depth = 1;
+ while (br_depth > 0)
+ {
+ if ((current_token == END_OF_INPUT)
+ || (current_token == KWD_END))
+ {
+ identifier_destroy(name);
+ string_destroy(element_name);
+ return;
+ }
+
+ current_token = yylex();
+
+ if (current_token == OPEN_BR)
+ br_depth ++;
+
+ if (current_token == CLOSE_BR)
+ br_depth --;
+ }
+
+ current_token = yylex();
+ }
+ }
+ else
+ {
+ if (current_token != OPEN_BR)
+ {
+ add_error_message(420, "", "");
+ }
+ else
+ {
+ int compare_result;
+ int old_linenum;
+ type_list *parameter_list;
+ current_token = yylex();
+
+ old_linenum = linenum;
+
+ parameter_list = RD_expression_list_cast(current_block, name->parameters);
+
+ compare_result = type_list_different_parameter_cast(parameter_list, name->parameters);
+
+ if (compare_result == -1) {
+ new_linenum=old_linenum;
+ add_error_message(421, "", "");
+ }
+
+ if (compare_result > 0)
+ {
+ char par_num[4];
+ sprintf(par_num, "%d", compare_result);
+ new_linenum=old_linenum;
+ add_error_message(422, par_num, "");
+ }
+
+ type_list_destroy(parameter_list);
+
+ if (current_token != CLOSE_BR)
+ {
+ add_error_message(200, ")", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+ }
+ }
+
+ /* create the bytecode */
+ if (!name->standard_function)
+ {
+ /* the procedure is user-defined */
+ int methodref_index;
+ identifier *block_identifier;
+ type_list *it;
+ int pos;
+
+ char* descriptor = (char*) mem_alloc(5*1024);
+ if (descriptor == NULL)
+ die(1);
+ descriptor[0] = '(';
+
+ if (!name->unit_function)
+ {
+ block_identifier = name_table_find(current_block->names, element_name);
+
+ if (block_identifier == NULL)
+ block_identifier = name_table_find(current_block->parent_block->names, element_name);
+ }
+ else
+ {
+ block_identifier = name;
+ }
+
+ it = block_identifier->parameters;
+ pos = 1;
+
+ while(it != NULL)
+ {
+ if (it->data == NULL)
+ break;
+
+ get_field_descriptor(it->data, descriptor + pos);
+ pos = strlen(descriptor);
+ it = it->next;
+ }
+
+ descriptor[pos] = ')';
+ pos ++;
+ descriptor[pos] = '\0';
+
+ if (block_identifier->identifier_class == procedure_name)
+ strcat(descriptor, "V");
+ else
+ get_field_descriptor(block_identifier->return_type, descriptor + pos);
+
+
+ lowercase(element_name->cstr);
+ if (name->unit_function)
+ {
+ string *full_unit_name;
+
+ if (name->container_unit->is_library)
+ full_unit_name = string_from_cstr("Lib_");
+ else
+ full_unit_name = string_create();
+ string_append(full_unit_name, name->container_unit->unit_name);
+ methodref_index = cp_add_methodref(full_unit_name->cstr, element_name->cstr, descriptor);
+ string_destroy(full_unit_name);
+ }
+ else
+ {
+ if (compiling_unit == 0)
+ methodref_index = cp_add_methodref("M", element_name->cstr, descriptor);
+ else
+ methodref_index = cp_add_methodref(string_get_cstr(str_program_name), element_name->cstr, descriptor);
+ }
+ bytecode_append(current_block->code, invokestatic$); /* call */
+ bytecode_append_short_int(current_block->code, methodref_index);
+
+ mem_free(descriptor);
+ }
+ else
+ {
+ /* handle standard functions and procedures */
+ create_std_function_code(current_block->code, element_name->cstr);
+ }
+ }
+
+ /* if the identifier is the function name and that is not the name of the current
+ block, report an error */
+ if (name->identifier_class == function_name)
+ {
+ if (STRING_COMPARE(element_name->cstr, current_block->block_name->cstr) != 0)
+ {
+ add_error_message(432, element_name->cstr, "");
+ }
+ }
+
+ /* if an identifier is a valid l-value */
+ if ((name->identifier_class == variable_name)
+ || (name->identifier_class == parameter_name)
+ || (name->identifier_class == function_name)) /* function names are treated as variables for return values */
+ {
+ type *current_type;
+ type *new_type;
+ type *expression_type;
+ int assign_linenum;
+ int is_field = 0;
+ bytecode *get_bytecode;
+ bytecode *put_bytecode;
+variable_lvalue:
+ is_field = 0;
+ get_bytecode = bytecode_create();
+ put_bytecode = bytecode_create();
+
+ if (name->identifier_class == variable_name)
+ current_type = type_duplicate(name->variable_type);
+
+ if (name->identifier_class == parameter_name)
+ current_type = type_duplicate(name->parameter_type);
+
+ if (name->identifier_class == function_name)
+ current_type = type_duplicate(name->return_type);
+
+ /* create the get and put bytecodes */
+ is_field = name->belongs_to_program_block;
+
+ if (name->identifier_class == function_name)
+ is_field = 0;
+
+ create_variable_bytecode(name, get_bytecode, element_name->cstr, is_field);
+ create_put_variable_bytecode(name, put_bytecode, element_name->cstr, is_field);
+
+ identifier_destroy(name);
+ name = NULL;
+ string_destroy(element_name);
+ element_name = NULL;
+
+ while (current_token != OP_ASSIGN)
+ {
+ if ((current_token == SEMI_COLON)
+ || (current_token == KWD_END)
+ || (current_token == END_OF_INPUT))
+ {
+ add_error_message(218, "", "");
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ if (current_token == DOT)
+ {
+ int fieldref_index;
+ char record_name[15];
+ char field_descriptor[128];
+
+ current_token = yylex();
+
+ /* append the old get bytecode */
+ bytecode_append_bytecode(current_block->code, get_bytecode);
+
+ /* reset the bytecodes */
+ put_bytecode->bytecode_pos = 0;
+ get_bytecode->bytecode_pos = 0;
+
+ if (current_type->type_class != record_type)
+ {
+ add_error_message(424, "", "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ new_type = type_find_record_element(current_type, YYTEXT_STRING);
+
+ if (new_type == NULL)
+ {
+ add_error_message(447, YYTEXT_STRING, "");
+ }
+ else
+ {
+ /* create the new put and get bytecodes */
+ sprintf(record_name, "R_%d", current_type->unique_record_ID);
+ get_field_descriptor(new_type, field_descriptor);
+ lowercase(YYTEXT_STRING);
+ fieldref_index = cp_add_fieldref(record_name, YYTEXT_STRING, field_descriptor);
+
+ bytecode_append(get_bytecode, getfield$);
+ bytecode_append_short_int(get_bytecode, fieldref_index);
+
+ bytecode_append(put_bytecode, putfield$);
+ bytecode_append_short_int(put_bytecode, fieldref_index);
+
+
+ type_destroy(current_type);
+ current_type = new_type;
+ }
+
+
+ if (current_type == NULL)
+ {
+ add_error_message(425, YYTEXT_STRING, "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ current_token = yylex();
+ }
+ else if (current_token == OPEN_SQ_BR)
+ {
+ type_list *array_elements;
+ bytecode *tmp_code;
+ tmp_code = bytecode_create();
+
+ // ako je [, a zadnji je array, procitaj listu, usporedi, vrati slijedeci, skoci gore
+ if (current_type->type_class != array_type)
+ {
+ add_error_message(426, "", "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ current_token = yylex();
+
+ array_elements = RD_expression_list_array(current_block, tmp_code, current_type);
+
+ bytecode_append_bytecode(get_bytecode, tmp_code);
+ //bytecode_append_bytecode(put_bytecode, tmp_code);
+ bytecode_destroy(put_bytecode);
+ put_bytecode = bytecode_duplicate(get_bytecode);
+
+ replace_aaload_instruction(get_bytecode, current_type->element_type);
+
+ /* remove the last aaload from put bytecode, adjust the stack and create the
+ put bytecode */
+ put_bytecode->bytecode_pos --;
+ bytecode_append(put_bytecode, dup2_x1$);
+ bytecode_append(put_bytecode, pop2$);
+
+ switch(current_type->element_type->type_class)
+ {
+ case integer_type:
+ case boolean_type:
+ case char_type:
+ bytecode_append(put_bytecode, iastore$);
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ bytecode_append(put_bytecode, iastore$);
+ else
+ bytecode_append(put_bytecode, aastore$);
+ break;
+
+
+ case image_type:
+ case string_type:
+ case record_type:
+ case command_type:
+ case record_store_type:
+ case http_type:
+ case alert_type:
+ case stream_type:
+ bytecode_append(put_bytecode, aastore$);
+ break;
+
+ }
+
+ bytecode_destroy(tmp_code);
+
+ if (type_list_different_parameter_array(array_elements, current_type->dimensions_list) != 0)
+ {
+ char num1[6], num2[6];
+
+ sprintf(num1, "%d", type_list_length(current_type->dimensions_list));
+ sprintf(num2, "%d", type_list_length(array_elements));
+ add_error_message(427, num1, num2);
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ if (current_token != CLOSE_SQ_BR)
+ {
+ add_error_message(200, "]", YYTEXT_STRING);
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+
+ current_token = yylex();
+
+ new_type = type_duplicate(current_type->element_type);
+ type_destroy(current_type);
+
+ current_type = new_type;
+
+ type_list_destroy(array_elements);
+ }
+ else
+ {
+ add_error_message(204, YYTEXT_STRING, "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ return;
+ }
+ }
+
+ assign_linenum = linenum;
+
+ current_token = yylex();
+
+ expression_type = RD_expression(current_block);
+
+ if ((type_equal_cast(current_type, expression_type) != 1)
+ && (current_type->type_class == real_type))
+ {
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+ }
+
+ if ((type_equal_cast(current_type, expression_type) == 2)
+ && (current_type->type_class == string_type))
+ {
+ int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
+
+ /* string cast */
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+ }
+
+ bytecode_append_bytecode(current_block->code, put_bytecode);
+
+ if ((type_equal_cast(current_type, expression_type) != 1)
+ && (type_equal_cast(current_type, expression_type) != 2))
+ {
+ new_linenum=assign_linenum;
+ add_error_message(423, "", "");
+ }
+ else
+ if (current_type->type_class == array_type)
+ {
+ new_linenum=assign_linenum;
+ add_error_message(443, "", "");
+ }
+
+
+
+ type_destroy(expression_type);
+ type_destroy(current_type);
+ bytecode_destroy(get_bytecode);
+ bytecode_destroy(put_bytecode);
+ }
+
+ if (name != NULL)
+ identifier_destroy(name);
+
+ if (element_name != NULL)
+ string_destroy(element_name);
+}
+
+
+/*
+ The list of expressions, used when calling the function
+ or procedure.
+
+ <RD_expression_list> -> <RD_expression> (, <RD_expression>)*
+*/
+type_list* RD_expression_list(block *current_block)
+{
+ type_list *return_list;
+ type *expression_type;
+
+ return_list = type_list_create();
+
+ expression_type = RD_expression(current_block);
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+
+ while (current_token == COMMA)
+ {
+ current_token = yylex();
+
+ expression_type = RD_expression(current_block);
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+ }
+
+ return return_list;
+}
+
+/*
+ Same as the above, only the types are casted according to the second parameter
+*/
+type_list* RD_expression_list_cast(block *current_block, type_list *formal_params)
+{
+ type_list *return_list;
+ type *expression_type;
+ type_list *it;
+
+ it = formal_params;
+
+ return_list = type_list_create();
+
+ expression_type = RD_expression(current_block);
+
+ if ((it != NULL) && (it->data != NULL))
+ {
+ int cast;
+
+ cast = type_equal_cast(it->data, expression_type);
+
+ if ((cast == 2) && (it->data->type_class == string_type))
+ {
+ int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
+
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+ }
+
+ if ((cast == 2) && (it->data->type_class == real_type))
+ {
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+ }
+
+ it = it->next;
+ }
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+
+ while (current_token == COMMA)
+ {
+ current_token = yylex();
+
+ expression_type = RD_expression(current_block);
+
+ if ((it != NULL) && (it->data != NULL))
+ {
+ int cast;
+
+ cast = type_equal_cast(it->data, expression_type);
+
+ if ((cast == 2) && (it->data->type_class == string_type))
+ {
+ int method_index = cp_add_methodref("java/lang/String", "valueOf", "(C)Ljava/lang/String;");
+
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+ }
+
+ if ((cast == 2) && (it->data->type_class == real_type))
+ {
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup_x1$);
+ bytecode_append(current_block->code, swap$);
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(I)V"));
+ }
+ }
+
+ it = it->next;
+ }
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+ }
+
+ return return_list;
+}
+
+/*
+ Same as RD_expression_list, only aaload is generated after each element and the indices
+ are adjusted.For example, if array is [a..b], the a value must be substracted from the index
+*/
+type_list* RD_expression_list_array(block *current_block, bytecode *code, type *array_type)
+{
+ type_list *return_list;
+ type *expression_type;
+ bytecode *oldBytecode;
+
+ type_list *it;
+ it = array_type->dimensions_list;
+
+ oldBytecode = current_block->code;
+ current_block->code = code;
+
+ return_list = type_list_create();
+
+ expression_type = RD_expression(current_block);
+ adjust_indices(code, it->data);
+
+ if(it != NULL)
+ it = it->next;
+
+ bytecode_append(code, aaload$);
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+
+ while (current_token == COMMA)
+ {
+ current_token = yylex();
+
+ expression_type = RD_expression(current_block);
+ adjust_indices(code, it->data);
+
+ if(it != NULL)
+ it = it->next;
+ bytecode_append(code, aaload$);
+
+ type_list_append(return_list, expression_type);
+
+ type_destroy(expression_type);
+ }
+
+ current_block->code = oldBytecode;
+
+ return return_list;
+}
+
+
+/*
+ The with statement, currently not supported. This
+ function is used as an error recovery function.
+
+ <RD_with_statement> -> IDN (. IDN)* do <RD_statement>
+*/
+void RD_with_statement(block *current_block)
+{
+ /* simplified parsing */
+ while (current_token != KWD_DO)
+ {
+ if (current_token == END_OF_INPUT)
+ return;
+
+ current_token = yylex();
+ }
+
+ current_token = yylex();
+
+ RD_statement(current_block);
+}
+
+
+/*
+ Anything that has value: constant, identifier, identifier inside
+ a record or a function call.
+
+ <RD_value> -> CONST
+ | IDN [ "[" <RD_expression_list> "]" ] ( . IDN [ "[" <RD_expression_list> "]" ])*
+ | IDN [ "(" <RD_expression_list> ")"]
+ | "(" <RD_expression> ")"
+*/
+type* RD_value(block *current_block)
+{
+ type *return_type;
+ return_type = type_create();
+
+ return_type->type_class = error_type;
+
+ if (current_token == CST_INTEGER)
+ {
+ switch(integer_constant)
+ {
+ case -1:
+ bytecode_append(current_block->code, iconst_m1$);
+ break;
+ case 0:
+ bytecode_append(current_block->code, iconst_0$);
+ break;
+ case 1:
+ bytecode_append(current_block->code, iconst_1$);
+ break;
+ case 2:
+ bytecode_append(current_block->code, iconst_2$);
+ break;
+ case 3:
+ bytecode_append(current_block->code, iconst_3$);
+ break;
+ case 4:
+ bytecode_append(current_block->code, iconst_4$);
+ break;
+ case 5:
+ bytecode_append(current_block->code, iconst_5$);
+ break;
+ default:
+ {
+ if (abs(integer_constant) < 127)
+ {
+ bytecode_append(current_block->code, bipush$);
+ bytecode_append(current_block->code, (char)(integer_constant));
+ }
+ else if (abs(integer_constant) < 16000)
+ {
+ bytecode_append(current_block->code, sipush$);
+ bytecode_append_short_int(current_block->code, (short)(integer_constant));
+ }
+ else
+ {
+ int cp_index;
+ cp_index = cp_add_integer(integer_constant);
+ if (cp_index <= 255)
+ {
+ bytecode_append(current_block->code, ldc$);
+ bytecode_append(current_block->code, (char) cp_index);
+ }
+ else
+ {
+ bytecode_append(current_block->code, ldc_w$);
+ bytecode_append_short_int(current_block->code, (short) cp_index);
+ }
+ }
+ break;
+ }
+ }
+
+ current_token = yylex();
+ return_type->type_class = integer_type;
+ return return_type;
+ }
+
+ if (current_token == CST_REAL)
+ {
+ float cst;
+ int csti; /* the integer part */
+ int cstf; /* the fraction part */
+
+ /* calculate the exponent and the integer part */
+ cst = real_constant;
+
+ csti = (int)cst;
+ cstf = (cst - (int)cst)*100000;
+
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ /* put the integer part on the stack */
+ if (abs(csti) < 127)
+ {
+ bytecode_append(current_block->code, bipush$);
+ bytecode_append(current_block->code, csti);
+ }
+ else if (abs(csti) < 15000)
+ {
+ bytecode_append(current_block->code, sipush$);
+ bytecode_append_short_int(current_block->code, csti);
+ }
+ else
+ {
+ bytecode_append(current_block->code, ldc_w$);
+ bytecode_append_short_int(current_block->code, cp_add_integer(csti));
+ }
+
+ /* put the fraction part to the stack */
+ if (abs(cstf) < 127)
+ {
+ bytecode_append(current_block->code, bipush$);
+ bytecode_append(current_block->code, cstf);
+ }
+ else if (abs(cstf) < 15000)
+ {
+ bytecode_append(current_block->code, sipush$);
+ bytecode_append_short_int(current_block->code, cstf);
+ }
+ else
+ {
+ bytecode_append(current_block->code, ldc_w$);
+ bytecode_append_short_int(current_block->code, cp_add_integer(cstf));
+ }
+
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("F", "fI", "(II)I"));
+ }
+ else
+ {
+ char number[64];
+
+ bytecode_append(current_block->code, new$);
+ bytecode_append_short_int(current_block->code, cp_add_class("Real"));
+ bytecode_append(current_block->code, dup$);
+
+ sprintf(number, "%f", real_constant);
+ bytecode_append(current_block->code, ldc_w$);
+ bytecode_append_short_int(current_block->code, cp_add_string(number));
+
+ bytecode_append(current_block->code, invokespecial$);
+ bytecode_append_short_int(current_block->code, cp_add_methodref("Real", "<init>", "(Ljava/lang/String;)V"));
+ }
+
+ current_token = yylex();
+ return_type->type_class = real_type;
+ return return_type;
+ }
+
+ if (current_token == CST_BOOLEAN)
+ {
+ if (boolean_constant)
+ {
+ bytecode_append(current_block->code, iconst_m1$);
+ }
+ else
+ {
+ bytecode_append(current_block->code, iconst_0$);
+ }
+
+ current_token = yylex();
+ return_type->type_class = boolean_type;
+ return return_type;
+ }
+
+ if (current_token == CST_CHAR)
+ {
+ bytecode_append(current_block->code, bipush$);
+ bytecode_append(current_block->code, char_constant);
+
+ current_token = yylex();
+ return_type->type_class = char_type;
+ return return_type;
+ }
+
+ if (current_token == CST_STRING)
+ {
+ int cp_index;
+ cp_index = cp_add_string(string_constant->cstr);
+ if (cp_index <= 255)
+ {
+ bytecode_append(current_block->code, ldc$);
+ bytecode_append(current_block->code, (char) cp_index);
+ }
+ else
+ {
+ bytecode_append(current_block->code, ldc_w$);
+ bytecode_append_short_int(current_block->code, (short) cp_index);
+ }
+
+ current_token = yylex();
+ return_type->type_class = string_type;
+ return return_type;
+ }
+
+ if (current_token == IDENTIFIER)
+ {
+ identifier *name;
+ char *identifier_text;
+ identifier_text = (char*) mem_alloc(strlen(YYTEXT_STRING) + 1);
+ strcpy(identifier_text, YYTEXT_STRING);
+ lowercase(identifier_text);
+
+ name = get_identifier(current_block, identifier_text);
+
+ if ((name->identifier_class == none)
+ || (name->identifier_class == program_name)
+ || (name->identifier_class == type_name)
+ || (name->identifier_class == procedure_name))
+ {
+ add_error_message(429, YYTEXT_STRING, "");
+ current_token = yylex();
+ identifier_destroy(name);
+ mem_free(identifier_text);
+ return return_type;
+ }
+
+
+ current_token = yylex();
+
+ if (name->identifier_class == constant_name)
+ {
+constant_value:
+ create_constant_bytecode(name, current_block->code);
+ type_destroy(return_type);
+ return_type = type_duplicate(name->constant_type);
+ identifier_destroy(name);
+ mem_free(identifier_text);
+ return return_type;
+ }
+
+ /*
+ Parse the unit functions.
+ */
+ if (name->identifier_class == unit_name)
+ {
+ identifier *unit_name;
+
+ if (current_token != DOT)
+ {
+ add_error_message(200, ".", YYTEXT_STRING);
+ while (current_token != SEMI_COLON)
+ current_token = yylex();
+ return return_type;
+ }
+
+ current_token = yylex();
+ unit_name = name_table_find(name->unit_block->names, string_from_cstr(YYTEXT_STRING));
+ identifier_text = malloc(strlen(YYTEXT_STRING) + 1);
+ strcpy(identifier_text, YYTEXT_STRING);
+
+ if (unit_name == NULL)
+ {
+ add_error_message(453, YYTEXT_STRING, "");
+ add_error_message(200, ".", YYTEXT_STRING);
+ while (current_token != SEMI_COLON)
+ current_token = yylex();
+ return return_type;
+ }
+
+ name = identifier_duplicate(unit_name);
+ current_token = yylex();
+
+ if (name->identifier_class == function_name)
+ goto function_call;
+
+ if (name->identifier_class == constant_name)
+ goto constant_value;
+
+ if (name->identifier_class == variable_name)
+ goto variable_value;
+
+ add_error_message(458, YYTEXT_STRING, "");
+ }
+
+ if ((name->identifier_class == variable_name)
+ || (name->identifier_class == parameter_name))
+ {
+ type *current_type;
+ type *new_type;
+ int is_field;
+variable_value:
+ is_field = name->belongs_to_program_block;
+
+ if (name->identifier_class == variable_name)
+ {
+ create_variable_bytecode(name, current_block->code, identifier_text, is_field);
+ current_type = type_duplicate(name->variable_type);
+ }
+
+
+ if(name->identifier_class == parameter_name)
+ {
+ create_variable_bytecode(name, current_block->code, identifier_text, is_field);
+ current_type = type_duplicate(name->parameter_type);
+ }
+
+ mem_free(identifier_text);
+
+ identifier_destroy(name);
+
+ name = NULL;
+
+ while ((current_token == DOT)
+ || (current_token == OPEN_SQ_BR))
+ {
+ /* get an element from the record */
+ if (current_token == DOT)
+ {
+ char record_name[5];
+ char field_descriptor[128];
+ int fieldref_index;
+
+ if (current_type->type_class != record_type)
+ {
+ add_error_message(424, "", "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ return return_type;
+ }
+
+ current_token = yylex();
+
+ new_type = type_find_record_element(current_type, YYTEXT_STRING);
+ sprintf(record_name, "R_%d", current_type->unique_record_ID);
+ type_destroy(current_type);
+ current_type = new_type;
+
+ if (current_type == NULL)
+ {
+ add_error_message(425, YYTEXT_STRING, "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ return return_type;
+ }
+
+ lowercase(YYTEXT_STRING);
+ get_field_descriptor(new_type, field_descriptor);
+ fieldref_index = cp_add_fieldref(record_name, YYTEXT_STRING, field_descriptor);
+
+ bytecode_append(current_block->code, getfield$);
+ bytecode_append_short_int(current_block->code, fieldref_index);
+
+ current_token = yylex();
+ }
+ /* get an element from an array */
+ else if (current_token == OPEN_SQ_BR)
+ {
+ type_list *array_elements;
+
+ if (current_type->type_class != array_type)
+ {
+ add_error_message(426, "", "");
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ return return_type;
+ }
+
+ current_token = yylex();
+
+ array_elements = RD_expression_list_array(current_block, current_block->code, current_type);
+
+ /* replace the last aaload in the bytecode with the proper loading instruction */
+ replace_aaload_instruction(current_block->code, current_type->element_type);
+
+ if (type_list_different_parameter_array(array_elements, current_type->dimensions_list) != 0)
+ {
+ char num1[6], num2[6];
+
+ sprintf(num1, "%d", type_list_length(current_type->dimensions_list));
+ sprintf(num2, "%d", type_list_length(array_elements));
+ add_error_message(427, num1, num2);
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ return return_type;
+ }
+
+ if (current_token != CLOSE_SQ_BR)
+ {
+ add_error_message(200, "]", YYTEXT_STRING);
+
+ /* Error-recovery */
+ while ((current_token != SEMI_COLON)
+ && (current_token != KWD_END)
+ && (current_token != END_OF_INPUT))
+ {
+ current_token = yylex();
+ }
+
+ type_destroy(current_type);
+ return return_type;
+ }
+
+ current_token = yylex();
+
+ new_type = type_duplicate(current_type->element_type);
+ type_destroy(current_type);
+
+ current_type = new_type;
+
+ type_list_destroy(array_elements);
+ }
+
+ }
+
+ type_destroy(return_type);
+
+ return_type = current_type;
+
+ return return_type;
+ }
+
+function_call:
+
+ /* a function call */
+ if (name->identifier_class == function_name)
+ {
+ int methodref_index;
+ char *method_type;
+ int method_index;
+ method_type = (char*) mem_alloc(1024*5);
+
+ if (name->standard_function)
+ {
+ create_std_function_prefix(current_block->code, identifier_text);
+ }
+
+ if (type_list_length(name->parameters) == 0)
+ {
+ int br_depth = 0;
+ if (current_token == OPEN_BR)
+ {
+ add_error_message(419, "", "");
+ br_depth = 1;
+ while (br_depth > 0)
+ {
+ if ((current_token == END_OF_INPUT)
+ || (current_token == KWD_END))
+ {
+ identifier_destroy(name);
+ return return_type;
+ }
+
+ current_token = yylex();
+
+ if (current_token == OPEN_BR)
+ br_depth ++;
+
+ if (current_token == CLOSE_BR)
+ br_depth --;
+ }
+
+ current_token = yylex();
+ }
+
+ /* create the bytecode */
+ if (name->unit_function)
+ {
+ string *full_unit_name;
+ if (name->container_unit->is_library == 1)
+ full_unit_name = string_from_cstr("Lib_");
+ else
+ full_unit_name = string_create();
+ string_append(full_unit_name, name->container_unit->unit_name);
+
+ lowercase(identifier_text);
+ strcpy(method_type, "()");
+ get_field_descriptor(name->return_type, method_type + 2);
+ method_index = cp_add_methodref(full_unit_name->cstr,
+ identifier_text, method_type);
+ bytecode_append(current_block->code, invokestatic$);
+ bytecode_append_short_int(current_block->code, method_index);
+ string_destroy(full_unit_name);
+ }
+ else if (!name->standard_function)
+ {
+ /* the function is user-defined */
+ strcpy(method_type, "()");
+ get_field_descriptor(name->return_type, method_type + 2);
+ if (compiling_unit == 0)
+ methodref_index = cp_add_methodref("M", identifier_text, method_type);
+ else
+ methodref_index = cp_add_methodref(string_get_cstr(str_program_name), identifier_text, method_type);
+ bytecode_append(current_block->code, invokestatic$); /* call */
+ bytecode_append_short_int(current_block->code, methodref_index);
+ }
+ else
+ {
+ /* handle standard functions and procedures */
+ create_std_function_code(current_block->code, identifier_text);
+ }
+
+ type_destroy(return_type);
+
+ mem_free(identifier_text);
+ mem_free(method_type);
+
+ return_type = type_duplicate(name->return_type);
+
+ identifier_destroy(name);
+
+ return return_type;
+ }
+ else
+ {
+ int compare_result;
+ int old_linenum;
+ type_list *parameter_list;
+
+ if (current_token != OPEN_BR)
+ {
+ add_error_message(200, "(", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ old_linenum = linenum;
+
+ parameter_list = RD_expression_list_cast(current_block, name->parameters);
+
+ compare_result = type_list_different_parameter_cast(parameter_list, name->parameters);
+
+ if (compare_result == -1){
+ new_linenum=old_linenum;
+ add_error_message(421, "", "");
+ }
+
+ if (compare_result > 0)
+ {
+ char par_num[4];
+ sprintf(par_num, "%d", compare_result);
+ new_linenum=old_linenum;
+ add_error_message(422, par_num, "");
+ }
+
+ type_list_destroy(parameter_list);
+
+ if (current_token != CLOSE_BR)
+ {
+ add_error_message(200, ")", YYTEXT_STRING);
+ }
+ else
+ current_token = yylex();
+
+ type_destroy(return_type);
+
+ /* create the bytecode */
+ if (!name->standard_function)
+ {
+ {
+ int pos = 1;
+ type_list *it;
+
+ it = name->parameters;
+
+ method_type[0] = '(';
+
+ while (it != NULL)
+ {
+ if (it->data == NULL)
+ break;
+
+
+ get_field_descriptor(it->data, method_type + pos);
+ pos = strlen(method_type);
+
+ it = it->next;
+ }
+
+ strcat(method_type, ")");
+ }
+
+
+ get_field_descriptor(name->return_type, method_type + strlen(method_type));
+
+ if (name->unit_function)
+ {
+ string *full_unit_name;
+ if (name->container_unit->is_library == 1)
+ full_unit_name = string_from_cstr("Lib_");
+ else
+ full_unit_name = string_create();
+ string_append(full_unit_name, name->container_unit->unit_name);
+ lowercase(identifier_text);
+ methodref_index = cp_add_methodref(full_unit_name->cstr, identifier_text, method_type);
+ string_destroy(full_unit_name);
+ }
+ else
+ {
+ if (compiling_unit == 0)
+ methodref_index = cp_add_methodref("M", identifier_text, method_type);
+ else
+ methodref_index = cp_add_methodref(string_get_cstr(str_program_name), identifier_text, method_type);
+ }
+
+ bytecode_append(current_block->code, invokestatic$); /* call */
+ bytecode_append_short_int(current_block->code, methodref_index);
+ }
+ else
+ {
+ /* handle standard functions and procedures */
+ create_std_function_code(current_block->code, identifier_text);
+ }
+ /* END create the bytecode */
+
+ return_type = type_duplicate(name->return_type);
+
+ mem_free(identifier_text);
+ mem_free(method_type);
+
+ identifier_destroy(name);
+
+ return return_type;
+ }
+ }
+
+ mem_free(identifier_text);
+
+ return return_type;
+ }
+
+ /* brackets, priority change, no code generated in here */
+ if (current_token == OPEN_BR)
+ {
+ current_token = yylex();
+
+ type_destroy(return_type);
+ return_type = RD_expression(current_block);
+
+ if (current_token != CLOSE_BR)
+ {
+ add_error_message(200, ")", YYTEXT_STRING);
+ }
+
+ current_token = yylex();
+
+ return return_type;
+ }
+
+ add_error_message(204, YYTEXT_STRING, "");
+
+ return return_type;
+}
+
+
+/*
+ Create the bytecode that loads the given constant
+*/
+void create_constant_bytecode(identifier *item, bytecode *code)
+{
+ int cp_index;
+
+ switch(item->constant_type->type_class)
+ {
+ case integer_type:
+ cp_index = cp_add_integer(item->constant_int_value);
+ if (cp_index <= 255)
+ {
+ bytecode_append(code, ldc$);
+ bytecode_append(code, (char) cp_index);
+ }
+ else
+ {
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, (short) cp_index);
+ }
+ break;
+
+ case real_type:
+ {
+ float cst;
+ int csti; /* the integer part */
+ int cstf; /* the fraction part */
+
+ /* calculate the exponent and the integer part */
+ cst = item->constant_real_value;
+
+ csti = (int)cst;
+ cstf = (cst - (int)cst)*100000;
+
+ usesFloat = 1;
+
+ if (mathType == 1)
+ {
+ /* put the integer part on the stack */
+ if (abs(csti) < 127)
+ {
+ bytecode_append(code, bipush$);
+ bytecode_append(code, csti);
+ }
+ else if (abs(csti) < 15000)
+ {
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, csti);
+ }
+ else
+ {
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, cp_add_integer(csti));
+ }
+
+ /* put the fraction part to the stack */
+ if (abs(cstf) < 127)
+ {
+ bytecode_append(code, bipush$);
+ bytecode_append(code, cstf);
+ }
+ else if (abs(cstf) < 15000)
+ {
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, cstf);
+ }
+ else
+ {
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, cp_add_integer(cstf));
+ }
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "fI", "(II)I"));
+ }
+ else
+ {
+ char number[64];
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup$);
+
+ sprintf(number, "%f", real_constant);
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, cp_add_string(number));
+
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(Ljava/lang/String;)V"));
+
+ }
+
+
+
+ }
+ break;
+
+ case char_type:
+ cp_index = cp_add_integer(item->constant_int_value);
+ if (cp_index <= 255)
+ {
+ bytecode_append(code, ldc$);
+ bytecode_append(code, (char) cp_index);
+ }
+ else
+ {
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, (short) cp_index);
+ }
+ break;
+
+ case boolean_type:
+ if (item->constant_int_value)
+ {
+ bytecode_append(code, iconst_m1$);
+ }
+ else
+ {
+ bytecode_append(code, iconst_0$);
+ }
+ break;
+
+ case string_type:
+ cp_index = cp_add_string(item->constant_string_value->cstr);
+ if (cp_index <= 255)
+ {
+ bytecode_append(code, ldc$);
+ bytecode_append(code, (char) cp_index);
+ }
+ else
+ {
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, (short) cp_index);
+ }
+ break;
+ }
+}
+
+
+/*
+ Creates the code that loads the variable or parameter value to the stack
+*/
+void create_variable_bytecode(identifier *item, bytecode *code, char *name, int is_field)
+{
+ int index;
+ type *item_type;
+
+ /* if the block is program block, load field instead of variable */
+ if ((is_field) || (item->unit_function == 1))
+ {
+ if (item->identifier_class == variable_name)
+ {
+ char type_descriptor[128];
+
+ lowercase(name);
+ bytecode_append(code, getstatic$);
+ get_field_descriptor(item->variable_type, type_descriptor);
+
+ if (item->unit_function == 0)
+ {
+ if (compiling_unit == 0)
+ bytecode_append_short_int(code, cp_add_fieldref("M", name, type_descriptor));
+ else
+ bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(str_program_name), name, type_descriptor));
+ }
+ else
+ {
+ string *unit_name;
+
+ if (item->container_unit->is_library == 0)
+ unit_name = string_create();
+ else
+ unit_name = string_from_cstr("Lib_");
+
+ lowercase(string_get_cstr(item->container_unit->unit_name));
+
+ string_append(unit_name, item->container_unit->unit_name);
+
+ bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(unit_name), name, type_descriptor));
+
+ string_destroy(unit_name);
+ }
+ }
+
+ return;
+ }
+
+ if (item->identifier_class == variable_name)
+ {
+ index = item->variable_index;
+ item_type = item->variable_type;
+ }
+ else if (item->identifier_class == function_name)
+ {
+ /* this is used for error recovery and returning values form functions */
+ index = type_list_length(item->parameters);
+ item_type = item->return_type;
+ }
+ else if (item->identifier_class == parameter_name)
+ {
+ index = item->parameter_index;
+ item_type = item->parameter_type;
+ }
+ else
+ {
+ add_error_message(444, "", "");
+ return 0;
+ }
+
+ switch (item_type->type_class)
+ {
+ case integer_type:
+ case char_type:
+ case boolean_type:
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, iload_0$);
+ break;
+ case 1:
+ bytecode_append(code, iload_1$);
+ break;
+ case 2:
+ bytecode_append(code, iload_2$);
+ break;
+ case 3:
+ bytecode_append(code, iload_3$);
+ break;
+ default:
+ bytecode_append(code, iload$);
+ bytecode_append(code, index);
+ break;
+ }
+
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ {
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, iload_0$);
+ break;
+ case 1:
+ bytecode_append(code, iload_1$);
+ break;
+ case 2:
+ bytecode_append(code, iload_2$);
+ break;
+ case 3:
+ bytecode_append(code, iload_3$);
+ break;
+ default:
+ bytecode_append(code, iload$);
+ bytecode_append(code, index);
+ break;
+ }
+ }
+ else
+ {
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(code, aload_3$);
+ break;
+ default:
+ bytecode_append(code, aload$);
+ bytecode_append(code, index);
+ break;
+ }
+ }
+ break;
+
+ case string_type:
+ case record_type:
+ case array_type:
+ case image_type:
+ case command_type:
+ case stream_type:
+ case record_store_type:
+ case http_type:
+ case alert_type:
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, aload_0$);
+ break;
+ case 1:
+ bytecode_append(code, aload_1$);
+ break;
+ case 2:
+ bytecode_append(code, aload_2$);
+ break;
+ case 3:
+ bytecode_append(code, aload_3$);
+ break;
+ default:
+ bytecode_append(code, aload$);
+ bytecode_append(code, index);
+ break;
+ }
+
+ break;
+
+ default:
+ die(15);
+ }
+}
+
+/*
+ Creates the code that puts the variable or parameter value from the stack into memory
+*/
+void create_put_variable_bytecode(identifier *item, bytecode *code, char *name, int is_field)
+{
+ int index;
+ type *item_type;
+
+ if (item->identifier_class == variable_name)
+ {
+ index = item->variable_index;
+ item_type = item->variable_type;
+ }
+ else if (item->identifier_class == parameter_name)
+ {
+ index = item->parameter_index;
+ item_type = item->parameter_type;
+ }
+ else if (item->identifier_class == function_name)/* function name, it is return value variable */
+ {
+ index = type_list_length(item->parameters);
+ is_field = 0;
+ item_type = item->return_type;
+ }
+ else
+ {
+ add_error_message(444, "", "");
+ return;
+ }
+
+ /* if the value on the top of the stack is string, copy it */
+ if (item_type->type_class == string_type)
+ {
+ int class_index;
+ int method_index;
+
+ class_index = cp_add_class("java/lang/String");
+ method_index = cp_add_methodref("java/lang/String", "<init>", "(Ljava/lang/String;)V");
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class_index);
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method_index);
+ }
+
+ if ((item_type->type_class == real_type) && (mathType != 1))
+ {
+ int class_index;
+ int method_index;
+
+ usesFloat = 1;
+
+ class_index = cp_add_class("Real");
+ method_index = cp_add_methodref("Real", "<init>", "(LReal;)V");
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class_index);
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method_index);
+ }
+
+ /* if the value on the top of the stack is record type, copy it */
+ if (item_type->type_class == record_type)
+ {
+ int class_index;
+ int constructor_index;
+ int copy_index;
+
+ char type_name[16];
+ char copy_sig[64];
+
+ sprintf(type_name, "R_%d", item_type->unique_record_ID);
+ sprintf(copy_sig, "(L%s;)L%s;", type_name, type_name);
+
+ class_index = cp_add_class(type_name);
+ constructor_index = cp_add_methodref(type_name, "<init>", "()V");
+ copy_index = cp_add_methodref(type_name, "Copy", copy_sig);
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class_index);
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, constructor_index);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, copy_index);
+ }
+
+ /* if the block is program block, load field instead of variable */
+ if ((is_field) || (item->unit_function == 1))
+ {
+ if (item->identifier_class == variable_name)
+ {
+ char type_descriptor[128];
+
+ lowercase(name);
+ bytecode_append(code, putstatic$);
+ get_field_descriptor(item->variable_type, type_descriptor);
+
+ if (item->unit_function == 0)
+ {
+ if (compiling_unit == 0)
+ bytecode_append_short_int(code, cp_add_fieldref("M", name, type_descriptor));
+ else
+ bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(str_program_name), name, type_descriptor));
+ }
+ else
+ {
+ string *unit_name;
+
+ if (item->container_unit->is_library == 0)
+ unit_name = string_create();
+ else
+ unit_name = string_from_cstr("Lib_");
+
+ lowercase(string_get_cstr(item->container_unit->unit_name));
+
+ string_append(unit_name, item->container_unit->unit_name);
+
+ bytecode_append_short_int(code, cp_add_fieldref(string_get_cstr(unit_name), name, type_descriptor));
+
+ string_destroy(unit_name);
+ }
+ }
+
+ return;
+ }
+
+ switch (item_type->type_class)
+ {
+ case integer_type:
+ case char_type:
+ case boolean_type:
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, istore_0$);
+ break;
+ case 1:
+ bytecode_append(code, istore_1$);
+ break;
+ case 2:
+ bytecode_append(code, istore_2$);
+ break;
+ case 3:
+ bytecode_append(code, istore_3$);
+ break;
+ default:
+ bytecode_append(code, istore$);
+ bytecode_append(code, index);
+ break;
+ }
+
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ {
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, istore_0$);
+ break;
+ case 1:
+ bytecode_append(code, istore_1$);
+ break;
+ case 2:
+ bytecode_append(code, istore_2$);
+ break;
+ case 3:
+ bytecode_append(code, istore_3$);
+ break;
+ default:
+ bytecode_append(code, istore$);
+ bytecode_append(code, index);
+ break;
+ }
+ }
+ else
+ {
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(code, astore_3$);
+ break;
+ default:
+ bytecode_append(code, astore$);
+ bytecode_append(code, index);
+ break;
+ }
+ }
+ break;
+
+ case string_type:
+ case record_type:
+ case array_type:
+ case image_type:
+ case command_type:
+ case stream_type:
+ case record_store_type:
+ case http_type:
+ case alert_type:
+ switch(index)
+ {
+ case 0:
+ bytecode_append(code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(code, astore_3$);
+ break;
+ default:
+ bytecode_append(code, astore$);
+ bytecode_append(code, index);
+ break;
+ }
+
+ break;
+
+ default:
+ die(15);
+ }
+}
+
+/*
+ The last instruction in the bytecode is aaload; it should be replaced with
+ the iaload, faload, aload or something like that.
+*/
+void replace_aaload_instruction(bytecode *code, type *element_type)
+{
+ /* delete the last instruction */
+ code->bytecode_pos --;
+
+ /* create the new instruction */
+ switch(element_type->type_class)
+ {
+ case integer_type:
+ case boolean_type:
+ case char_type:
+ bytecode_append(code, iaload$);
+ break;
+
+ case real_type:
+ if (mathType == 1)
+ {
+ bytecode_append(code, iaload$);
+ }
+ else
+ {
+ bytecode_append(code, aaload$);
+ }
+ break;
+
+ case record_type:
+ case string_type:
+ case image_type:
+ case command_type:
+ case stream_type:
+ case record_store_type:
+ case http_type:
+ case alert_type:
+ bytecode_append(code, aaload$);
+ break;
+
+ default:
+ die(24);
+ }
+}
+
+/*
+ Creates the code that adjustes array indices
+*/
+void adjust_indices(bytecode *code, type *dimension)
+{
+ if (dimension == NULL)
+ return;
+
+ switch(dimension->first_element)
+ {
+ case -1:
+ bytecode_append(code, iconst_m1$);
+ break;
+ case 0:
+ //bytecode_append(code, iconst_0$);
+ break;
+ case 1:
+ bytecode_append(code, iconst_1$); break;
+ case 2:
+ bytecode_append(code, iconst_2$); break;
+ case 3:
+ bytecode_append(code, iconst_3$); break;
+ case 4:
+ bytecode_append(code, iconst_4$); break;
+ case 5:
+ bytecode_append(code, iconst_5$); break;
+ default:
+ if (dimension->first_element < 128)
+ {
+ bytecode_append(code, bipush$);
+ bytecode_append(code, dimension->first_element);
+ }
+ else
+ {
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, dimension->first_element);
+ }
+ }
+ if (dimension->first_element != 0)
+ bytecode_append(code, isub$);
+
+}
diff --git a/MPC.3.5.LINUX/parser/parser.h b/MPC.3.5.LINUX/parser/parser.h
--- /dev/null
@@ -0,0 +1,59 @@
+/********************************************************************
+
+ parser.h - recursive-descent parser declarations
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+
+void parser_start();
+string* RD_program_header();
+void RD_uses_list();
+block* RD_block(block*);
+void RD_const_declaration();
+void RD_var_declaration(block*);
+string_list* RD_identifier_list(block*, int);
+void RD_type_declaration(block*);
+void RD_procedure_declaration(block*);
+void RD_function_declaration(block*);
+int RD_proc_block(block*, type*, type_list*);
+type_list* RD_param_list(block*);
+void RD_block_body(block*);
+void RD_inline_body(block*);
+void RD_statement(block *);
+void RD_if_statement(block *);
+void RD_case_statement(block *);
+void RD_case_list(block*, type*);
+void RD_while_statement(block*);
+void RD_repeat_statement(block*);
+void RD_for_statement(block*);
+type* RD_type(block*);
+type* RD_basic_type(block*);
+type* RD_array_declaration(block*);
+type* RD_record_declaration(block*);
+type* RD_file_declaration(block*);
+void RD_set_declaration(block*);
+type* RD_expression(block*);
+type* RD_sum(block*);
+type* RD_mult(block*);
+type* RD_not(block*);
+type* RD_neg(block*);
+void RD_assignment_or_procedure_call(block*);
+type_list* RD_expression_list(block*);
+type_list* RD_expression_list_cast(block*, type_list*);
+type_list* RD_expression_list_array(block*, bytecode*, type*);
+void RD_with_statement(block*);
+type* RD_value(block*);
+
+void RD_unit_interface(block*);
+void RD_unit_implementation(block*);
+void RD_unit_initialization(block*);
+void RD_unit_finalization(block*);
+
+void create_constant_bytecode(identifier*, bytecode*);
+void create_variable_bytecode(identifier*, bytecode*, char*, int);
+void create_put_variable_bytecode(identifier*, bytecode*, char*, int);
+
+void replace_aaload_instruction(bytecode*, type*);
+void adjust_indices(bytecode *code, type *dimension);
diff --git a/MPC.3.5.LINUX/parser/stdpas.c b/MPC.3.5.LINUX/parser/stdpas.c
--- /dev/null
@@ -0,0 +1,3333 @@
+/********************************************************************
+
+ stdpas.c - initializes the parser/semantic checker with a
+ standard pascal types, constants etc.
+
+ Niksa Orlic, 2004-04-29
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+//#include "../main/static_entry.h"
+
+#include "../classgen/constant_pool.h"
+
+#include "stdpas.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#pragma warning (disable:4305)
+#pragma warning (disable:4761)
+
+int procedure_linenum;
+extern char *source_file_name;
+int usesForms = 0; /* set to 1 if FS.class should be added into the generated JAR file */
+int usesSupport = 0; /* set to 1 if S.class should be added into the generated JAR file */
+int usesFloat = 0; /* set to 1 if Float.class should be added into the generated JAR file */
+int usesRecordStore = 0; /* set to 1 if RS.class should be added into the generated JAR file */
+int usesHttp = 0; /* if H.class should be added */
+int usesPlayer = 0; /* if P.class should be used */
+int usesSMS = 0; /* if uses SM.class */
+extern int mathType;
+
+//int usesRegisteredFeature = 0;
+
+extern int canvasType;
+
+
+/*
+ Creates and initializes the root block
+ with standard pascal types, constants etc.
+*/
+block* initialize_root_block()
+{
+ block *root_block;
+
+ root_block = block_create(NULL, NULL);
+
+ add_std_types(root_block);
+ add_std_constants(root_block);
+ add_std_functions(root_block);
+
+ return root_block;
+}
+
+
+/*
+ Adds the standard pascal types into the block.
+*/
+void add_std_types(block *item)
+{
+ add_std_type(item, integer_type, "integer");
+ add_std_type(item, real_type, "real");
+ add_std_type(item, boolean_type, "boolean");
+ add_std_type(item, char_type, "char");
+ add_std_type(item, string_type, "string");
+ add_std_type(item, image_type, "image");
+ add_std_type(item, command_type, "command");
+ add_std_type(item, stream_type, "resource");
+ add_std_type(item, record_store_type, "recordstore");
+ add_std_type(item, http_type, "http");
+}
+
+/*
+ Adds some constants into the block
+*/
+void add_std_constants(block *item)
+{
+ add_real_constant(item, (float) 3.1415926535897932384626433832795, "pi");
+
+ /* key codes */
+ add_integer_constant(item, 0, "KE_NONE");
+ add_integer_constant(item, 0, "GA_NONE");
+
+ add_integer_constant(item, 1, "GA_UP");
+ add_integer_constant(item, 6, "GA_DOWN");
+ add_integer_constant(item, 2, "GA_LEFT");
+ add_integer_constant(item, 5, "GA_RIGHT");
+ add_integer_constant(item, 8, "GA_FIRE");
+ add_integer_constant(item, 9, "GA_GAMEA");
+ add_integer_constant(item, 10, "GA_GAMEB");
+ add_integer_constant(item, 11, "GA_GAMEC");
+ add_integer_constant(item, 12, "GA_GAMED");
+
+ add_integer_constant(item, 48, "KE_KEY0");
+ add_integer_constant(item, 49, "KE_KEY1");
+ add_integer_constant(item, 50, "KE_KEY2");
+ add_integer_constant(item, 51, "KE_KEY3");
+ add_integer_constant(item, 52, "KE_KEY4");
+ add_integer_constant(item, 53, "KE_KEY5");
+ add_integer_constant(item, 54, "KE_KEY6");
+ add_integer_constant(item, 55, "KE_KEY7");
+ add_integer_constant(item, 56, "KE_KEY8");
+ add_integer_constant(item, 57, "KE_KEY9");
+ add_integer_constant(item, 42, "KE_STAR");
+ add_integer_constant(item, 35, "KE_POUND");
+
+ /* font constants */
+ add_integer_constant(item, 0, "FONT_FACE_SYSTEM");
+ add_integer_constant(item, 32, "FONT_FACE_MONOSPACE");
+ add_integer_constant(item, 64, "FONT_FACE_PROPORTIONAL");
+
+ add_integer_constant(item, 8, "FONT_SIZE_SMALL");
+ add_integer_constant(item, 0, "FONT_SIZE_MEDIUM");
+ add_integer_constant(item, 16, "FONT_SIZE_LARGE");
+
+ add_integer_constant(item, 0, "FONT_STYLE_PLAIN");
+ add_integer_constant(item, 1, "FONT_STYLE_BOLD");
+ add_integer_constant(item, 2, "FONT_STYLE_ITALIC");
+ add_integer_constant(item, 4, "FONT_STYLE_UNDERLINED");
+
+ /* command constants */
+ add_integer_constant(item, 1, "CM_SCREEN");
+ add_integer_constant(item, 2, "CM_BACK");
+ add_integer_constant(item, 3, "CM_CANCEL");
+ add_integer_constant(item, 4, "CM_OK");
+ add_integer_constant(item, 5, "CM_HELP");
+ add_integer_constant(item, 6, "CM_STOP");
+ add_integer_constant(item, 7, "CM_EXIT");
+ add_integer_constant(item, 8, "CM_ITEM");
+
+ /* text field constants */
+ add_integer_constant(item, 0, "TF_ANY");
+ add_integer_constant(item, 1, "TF_EMAIL");
+ add_integer_constant(item, 2, "TF_NUMERIC");
+ add_integer_constant(item, 3, "TF_PHONENUMBER");
+ add_integer_constant(item, 4, "TF_URL");
+ add_integer_constant(item, 0x10000, "TF_PASSWORD");
+
+ /* choice constants */
+ add_integer_constant(item, 1, "CH_EXCLUSIVE");
+ add_integer_constant(item, 2, "CH_MULTIPLE");
+ add_integer_constant(item, 3, "CH_IMPLICIT");
+
+ /* http constants */
+ add_string_constant(item, string_from_cstr("GET"), "GET");
+ add_string_constant(item, string_from_cstr("HEAD"), "HEAD");
+ add_string_constant(item, string_from_cstr("POST"), "POST");
+
+ /* date field constants */
+ add_integer_constant(item, 1, "DF_DATE");
+ add_integer_constant(item, 2, "DF_TIME");
+ add_integer_constant(item, 3, "DF_DATE_TIME");
+
+ add_integer_constant(item, 1000, "EOF");
+}
+
+
+/*
+ Adds standard functions and procedures
+*/
+void add_std_functions(block *item)
+{
+
+ add_special_function(item, real_type, real_type, "sqrt");
+ add_special_function(item, real_type, integer_type, "trunc");
+// add_special_function(item, real_type, integer_type, "round");
+ add_special_function(item, real_type, real_type, "sin");
+ add_special_function(item, real_type, real_type, "cos");
+ add_special_function(item, real_type, real_type, "atan");
+ add_special_function(item, real_type, real_type, "log"); /* natural logarithm */
+ add_special_function(item, real_type, real_type, "exp");
+ add_special_function(item, real_type, real_type, "asin");
+ add_special_function(item, real_type, real_type, "acos");
+ add_special_function(item, real_type, real_type, "tan");
+ add_special_function(item, real_type, real_type, "toDegrees");
+ add_special_function(item, real_type, real_type, "toRadians");
+ add_special_function(item, real_type, real_type, "frac");
+ add_special_function2(item, real_type, real_type, real_type, "atan2");
+ add_special_function(item, real_type, real_type, "log10");
+ add_special_function2(item, real_type, real_type, real_type, "pow");
+ add_special_function2(item, string_type, integer_type, real_type, "stringToReal");
+ add_special_function(item, real_type, real_type, "rabs");
+
+ add_special_function(item, integer_type, integer_type, "sqr");
+ add_special_function(item, integer_type, integer_type, "abs");
+
+ add_special_function(item, integer_type, boolean_type, "odd");
+ add_special_function(item, integer_type, char_type, "chr");
+ add_special_function(item, char_type, integer_type, "ord");
+
+ add_special_function(item, void_type, void_type, "halt");
+ add_special_function(item, void_type, boolean_type, "isMidletPaused");
+
+ /* RNG functions */
+ add_special_function(item, void_type, void_type, "randomize");
+ add_special_function(item, integer_type, integer_type, "random");
+
+ /* string functions */
+ add_special_function(item, string_type, string_type, "upcase");
+ add_special_function(item, string_type, string_type, "locase");
+ add_special_function(item, string_type, integer_type, "length");
+ add_special_function3(item, string_type, integer_type, integer_type, string_type, "copy");
+ add_special_function2(item, string_type, string_type, integer_type, "pos");
+ add_special_function(item, string_type, integer_type, "stringToInteger");
+ add_special_function(item, integer_type, string_type, "integerToString");
+ add_special_function2(item, string_type, integer_type, char_type, "getChar");
+ add_special_function3(item, string_type, char_type, integer_type, string_type, "setChar");
+
+ /* midlet functions */
+ add_special_function(item, string_type, string_type, "getproperty");
+
+
+ /* time functions */
+ add_special_function(item, integer_type, void_type, "delay");
+ add_special_function(item, void_type, integer_type, "getRelativeTimeMs");
+ add_special_function(item, void_type, integer_type, "getCurrentTime");
+ add_special_function(item, integer_type, integer_type, "getDay");
+ add_special_function(item, integer_type, integer_type, "getMonth");
+ add_special_function(item, integer_type, integer_type, "getYear");
+ add_special_function(item, integer_type, integer_type, "getSecond");
+ add_special_function(item, integer_type, integer_type, "getMinute");
+ add_special_function(item, integer_type, integer_type, "getHour");
+ add_special_function(item, integer_type, integer_type, "getWeekDay");
+ add_special_function(item, integer_type, integer_type, "getYearDay");
+
+
+ /* music functions */
+ add_special_function3(item, integer_type, integer_type, integer_type, void_type, "playTone");
+
+
+ /* action functions */
+ add_special_function(item, void_type, integer_type, "getKeyPressed");
+ add_special_function(item, void_type, integer_type, "getKeyClicked");
+ add_special_function(item, integer_type, integer_type, "keyToAction");
+
+
+ /* image functions */
+ add_special_function(item, string_type, image_type, "loadImage");
+ add_special_function(item, image_type, integer_type, "getImageWidth");
+ add_special_function(item, image_type, integer_type, "getImageHeight");
+ add_special_function5(item, image_type, integer_type, integer_type, integer_type, integer_type, image_type, "imageFromImage");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, image_type, "imageFromCanvas");
+ add_special_function2(item, string_type, integer_type, image_type, "imageFromBuffer");
+
+ /* drawing functions */
+ add_special_function(item, void_type, void_type, "repaint");
+
+ add_special_function(item, void_type, integer_type, "getWidth");
+ add_special_function(item, void_type, integer_type, "getHeight");
+ add_special_function(item, void_type, boolean_type, "isColorDisplay");
+ add_special_function(item, void_type, integer_type, "getColorsNum");
+
+
+ add_special_function3(item, string_type, integer_type, integer_type, void_type, "drawText");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "setClip");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "drawLine");
+ add_special_function3(item, integer_type, integer_type, integer_type, void_type, "setColor");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "drawEllipse");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "fillEllipse");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "drawRect");
+ add_special_function4(item, integer_type, integer_type, integer_type, integer_type, void_type, "fillRect");
+ add_special_function6(item, integer_type, integer_type, integer_type, integer_type, integer_type, integer_type, void_type, "drawArc");
+ add_special_function2(item, integer_type, integer_type, void_type, "plot");
+ add_special_function(item, void_type, integer_type, "getColorRed");
+ add_special_function(item, void_type, integer_type, "getColorGreen");
+ add_special_function(item, void_type, integer_type, "getColorBlue");
+ add_special_function6(item, integer_type, integer_type, integer_type, integer_type, integer_type, integer_type, void_type, "drawRoundRect");
+ add_special_function6(item, integer_type, integer_type, integer_type, integer_type, integer_type, integer_type, void_type, "fillRoundRect");
+
+ add_special_function3(item, integer_type, integer_type, integer_type, void_type, "setFont");
+ add_special_function(item, void_type, void_type, "setDefaultFont");
+
+ add_special_function3(item, image_type, integer_type, integer_type, void_type, "drawImage");
+
+ add_special_function(item, string_type, integer_type, "getStringWidth");
+ add_special_function(item, string_type, integer_type, "getStringHeight");
+
+ /* debug functions */
+ add_special_function(item, string_type, void_type, "debug");
+ add_special_function(item, boolean_type, void_type, "assert");
+
+ /* command & form functions */
+ add_special_function3(item, string_type, integer_type, integer_type, command_type, "createCommand");
+ add_special_function(item, void_type, command_type, "getClickedCommand");
+ add_special_function(item, command_type, void_type, "addCommand");
+ add_special_function(item, command_type, void_type, "removeCommand");
+ add_special_function(item, void_type, command_type, "emptyCommand");
+
+ add_special_function(item, void_type, void_type, "showForm");
+ add_special_function(item, void_type, void_type, "showCanvas");
+
+ add_special_function(item, string_type, void_type, "setTicker");
+
+ add_special_function(item, void_type, void_type, "clearForm");
+ add_special_function(item, integer_type, void_type, "formRemove");
+ add_special_function(item, string_type, integer_type, "formAddString");
+ add_special_function(item, void_type, integer_type, "formAddSpace");
+ add_special_function(item, image_type, integer_type, "formAddImage");
+ add_special_function4(item, string_type, string_type, integer_type, integer_type, integer_type, "formAddTextField");
+ add_special_function4(item, string_type, boolean_type, integer_type, integer_type, integer_type, "formAddGauge");
+ add_special_function2(item, string_type, integer_type, integer_type, "formAddDateField");
+ add_special_function2(item, integer_type, integer_type, void_type, "formSetDate");
+ add_special_function(item, integer_type, integer_type, "formGetDate");
+
+ add_special_function2(item, string_type, integer_type, integer_type, "formAddChoice");
+
+ add_special_function(item, integer_type, integer_type, "formGetValue");
+ add_special_function(item, integer_type, string_type, "formGetText");
+ add_special_function2(item, integer_type, integer_type, void_type, "formSetValue");
+ add_special_function2(item, integer_type, string_type, void_type, "formSetText");
+
+ add_special_function2(item, integer_type, string_type, integer_type, "choiceAppendString");
+ add_special_function3(item, integer_type, string_type, image_type, integer_type, "choiceAppendStringImage");
+ add_special_function2(item, integer_type, integer_type, boolean_type, "choiceIsSelected");
+ add_special_function(item, integer_type, integer_type, "choiceGetSelectedIndex");
+
+ add_special_function(item, string_type, void_type, "setFormTitle");
+ add_special_function(item, void_type, void_type, "removeFormTitle");
+ add_special_function(item, void_type, string_type, "getFormTitle");
+
+ /* text box elements */
+ add_special_function4(item, string_type, string_type, integer_type, integer_type, void_type, "showTextBox");
+ add_special_function(item, void_type, string_type, "getTextBoxString");
+
+ /* alert elements */
+ add_special_function4(item, string_type, string_type, image_type, alert_type, void_type, "showAlert");
+ add_special_function(item, void_type, void_type, "playAlertSound");
+ add_special_function(item, void_type, alert_type, "ALERT_INFO");
+ add_special_function(item, void_type, alert_type, "ALERT_WARNING");
+ add_special_function(item, void_type, alert_type, "ALERT_ERROR");
+ add_special_function(item, void_type, alert_type, "ALERT_ALARM");
+ add_special_function(item, void_type, alert_type, "ALERT_CONFIRMATION");
+
+ /* menu functions */
+ add_special_function2(item, string_type, integer_type, void_type, "showMenu");
+ add_special_function(item, string_type, integer_type, "menuAppendString");
+ add_special_function2(item, string_type, image_type, integer_type, "menuAppendStringImage");
+ add_special_function(item, integer_type, boolean_type, "menuIsSelected");
+ add_special_function(item, void_type, integer_type, "menuGetSelectedIndex");
+
+
+ /* record store functions */
+ add_special_function(item, string_type, record_store_type, "openRecordStore");
+ add_special_function(item, record_store_type, void_type, "closeRecordStore");
+ add_special_function(item, string_type, void_type, "deleteRecordStore");
+ add_special_function2(item, record_store_type, integer_type, void_type, "deleteRecordStoreEntry");
+ add_special_function2(item, record_store_type, string_type, integer_type, "addRecordStoreEntry");
+ add_special_function2(item, record_store_type, integer_type, string_type, "readRecordStoreEntry");
+ add_special_function(item, record_store_type, integer_type, "getRecordStoreSize");
+ add_special_function3(item, record_store_type, string_type, integer_type, void_type, "modifyRecordStoreEntry");
+ add_special_function(item, record_store_type, integer_type, "getRecordStoreNextId");
+
+ /* http connectivity functions */
+ add_special_function2(item, http_type, string_type, boolean_type, "openHttp");
+ add_special_function(item, http_type, boolean_type, "isHttpOpen");
+ add_special_function(item, http_type, void_type, "closeHttp");
+ add_special_function3(item, http_type, string_type, string_type, void_type, "addHttpHeader");
+ add_special_function2(item, http_type, string_type, void_type, "setHttpMethod");
+ add_special_function(item, http_type, integer_type, "sendHttpMessage");
+ add_special_function2(item, http_type, string_type, string_type, "getHttpHeader");
+ add_special_function2(item, http_type, string_type, void_type, "addHttpBody");
+ add_special_function(item, http_type, string_type, "getHttpResponse");
+
+
+ /* resource-handling functions */
+ add_special_function(item, string_type, stream_type, "openResource");
+ add_special_function(item, stream_type, void_type, "closeResource");
+ add_special_function(item, stream_type, integer_type, "readByte");
+ add_special_function(item, stream_type, string_type, "readLine");
+ add_special_function(item, stream_type, boolean_type, "resourceAvailable");
+
+ /* player functions */
+ add_special_function2(item, string_type, string_type, boolean_type, "openPlayer");
+ add_special_function(item, void_type, boolean_type, "startPlayer");
+ add_special_function(item, void_type, void_type, "stopPlayer");
+ add_special_function(item, integer_type, boolean_type, "setPlayerCount");
+ add_special_function(item, void_type, integer_type, "getPlayerDuration");
+
+
+ /* SMS functions */
+ add_special_function2(item, string_type, string_type, boolean_type, "smsStartSend");
+ add_special_function(item, void_type, boolean_type, "smsIsSending");
+ add_special_function(item, void_type, boolean_type, "smsWasSuccessfull");
+
+}
+
+
+/*
+ Adds a single type into the block
+*/
+void add_std_type(block *item, enum en_type_class type_class, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = type_name;
+ descriptor->defined_type = type_create();
+ descriptor->defined_type->type_class = type_class;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Add a standard function
+*/
+void add_std_function(block *item, char *cstr_name, type_list *params, type *return_type)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = function_name;
+ descriptor->return_type = return_type;
+ descriptor->parameters = params;
+ descriptor->variables = NULL;
+ descriptor->standard_function = 1;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Add a standard procedure
+*/
+void add_std_procedure(block *item, char *cstr_name, type_list *params)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = procedure_name;
+ descriptor->parameters = params;
+ descriptor->variables = NULL;
+ descriptor->standard_function = 1;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Creates the 'prefix' code, the code that is executed before the arguments are evaluated
+*/
+void create_std_function_prefix(bytecode *code, char *name)
+{
+ lowercase(name);
+
+ if ( (strcmp(name, "drawtext") == 0)
+ || (strcmp(name, "drawline") == 0)
+ || (strcmp(name, "setcolor") == 0)
+ || (strcmp(name, "drawellipse") == 0)
+ || (strcmp(name, "fillellipse") == 0)
+ || (strcmp(name, "drawrect") == 0)
+ || (strcmp(name, "fillrect") == 0)
+ || (strcmp(name, "drawarc") == 0)
+ || (strcmp(name, "plot") == 0)
+ || (strcmp(name, "getcolorred") == 0)
+ || (strcmp(name, "getcolorblue") == 0)
+ || (strcmp(name, "getcolorgreen") == 0)
+ || (strcmp(name, "drawroundrect") == 0)
+ || (strcmp(name, "fillroundrect") == 0)
+ || (strcmp(name, "setfont") == 0)
+ || (strcmp(name, "setdefaultfont") == 0)
+ || (strcmp(name, "drawimage") == 0)
+ || (strcmp(name, "getstringheight") == 0)
+ || (strcmp(name, "setclip") == 0)
+ )
+ {
+ int field_index = cp_add_fieldref("M", "G", "Ljavax/microedition/lcdui/Graphics;");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ return;
+ }
+
+ if ( (strcmp(name, "getwidth") == 0)
+ || (strcmp(name, "getheight") == 0)
+ )
+ {
+ int field_index = cp_add_fieldref("M", "I", "Ljavax/microedition/lcdui/Image;");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ return;
+ }
+
+ if ((strcmp(name, "getsecond") == 0)
+ || (strcmp(name, "getminute") == 0)
+ || (strcmp(name, "gethour") == 0)
+ || (strcmp(name, "getday") == 0)
+ || (strcmp(name, "getmonth") == 0)
+ || (strcmp(name, "getyear") == 0)
+ || (strcmp(name, "getweekday") == 0)
+ || (strcmp(name, "getyearday") == 0)
+ )
+ {
+ int method1, class1;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ class1 = cp_add_class("java/util/Date");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method1);
+
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class1);
+
+ bytecode_append(code, dup$);
+
+ return;
+ }
+
+ if (strcmp(name, "createcommand") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/Command"));
+ bytecode_append(code, dup$);
+
+ return;
+ }
+
+ if ((strcmp(name, "vibrate") == 0)
+ || (strcmp(name, "iscolordisplay") == 0)
+ || (strcmp(name, "getcolorsnum") == 0))
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display",
+ "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+ return;
+ }
+
+ if (strcmp(name, "showtextbox") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/TextBox"));
+ bytecode_append(code, dup$);
+ return;
+ }
+
+ if (strcmp(name, "showalert") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/Alert"));
+ bytecode_append(code, dup$);
+ return;
+ }
+
+ if (strcmp(name, "showmenu") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/List"));
+ bytecode_append(code, dup$);
+ return;
+ }
+
+ if ((strcmp(name, "menuappendstring") == 0)
+ || (strcmp(name, "menuappendstringimage") == 0)
+ || (strcmp(name, "menuisselected") == 0)
+ || (strcmp(name, "menugetselectedindex") == 0))
+ {
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "L", "Ljavax/microedition/lcdui/List;"));
+ return;
+ }
+
+ if (strcmp(name, "stringtoreal") == 0)
+ {
+ if (mathType != 1)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup$);
+ }
+ }
+}
+
+
+/*
+ Create the bytecode for the standard function or procedure
+*/
+void create_std_function_code(bytecode *code, char *name)
+{
+ int count = 0;
+
+ lowercase(name);
+
+ switch(name[0])
+ {
+ case 'a': goto letter_a;
+ case 'b': goto letter_b;
+ case 'c': goto letter_c;
+ case 'd': goto letter_d;
+ case 'e': goto letter_e;
+ case 'f': goto letter_f;
+ case 'g': goto letter_g;
+ case 'h': goto letter_h;
+ case 'i': goto letter_i;
+ case 'j': goto letter_j;
+ case 'k': goto letter_k;
+ case 'l': goto letter_l;
+ case 'm': goto letter_m;
+ case 'n': goto letter_n;
+ case 'o': goto letter_o;
+ case 'p': goto letter_p;
+ case 'q': goto letter_q;
+ case 'r': goto letter_r;
+ case 's': goto letter_s;
+ case 't': goto letter_t;
+ case 'u': goto letter_u;
+ case 'v': goto letter_v;
+ case 'w': goto letter_w;
+ case 'x': goto letter_x;
+ case 'y': goto letter_y;
+ case 'z': goto letter_z;
+ }
+
+letter_a:
+ if (strcmp(name, "addhttpbody") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "o", "(Ljava/lang/String;)I"));
+ bytecode_append(code, pop$);
+ return;
+ }
+
+ if (strcmp(name, "addcommand") == 0)
+ {
+ if (canvasType == FULL_NOKIA)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+ bytecode_append(code, dup$);
+ bytecode_append(code, instanceof$);
+ bytecode_append_short_int(code, cp_add_class("com/nokia/mid/ui/FullCanvas"));
+
+ bytecode_append(code, ifne$);
+ bytecode_append_short_int(code, 10);
+
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "addCommand", "(Ljavax/microedition/lcdui/Command;)V"));
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 4);
+
+ bytecode_append(code, pop2$);
+ }
+ else
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "addCommand", "(Ljavax/microedition/lcdui/Command;)V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "addrecordstoreentry") == 0)
+ {
+ usesRecordStore = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code,
+ cp_add_methodref("RS", "L", "(Ljavax/microedition/rms/RecordStore;Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp(name, "assert") == 0)
+ {
+ char assert_text[128];
+ sprintf(assert_text, "Assertion failed at: %s:%d", source_file_name ,procedure_linenum);
+ bytecode_append(code, ifne$);
+ bytecode_append_short_int(code, 12);
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("java/lang/System", "out", "Ljava/io/PrintStream;"));
+ bytecode_append(code, ldc_w$);
+ bytecode_append_short_int(code, cp_add_string(assert_text));
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("java/io/PrintStream", "println", "(Ljava/lang/String;)V"));
+ return;
+ }
+
+ if (strcmp(name, "abs") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/Math", "abs", "(I)I");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "atan") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "atan", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "atan", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "atan2") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "atan2", "(II)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "atan2", "(LReal;)V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "asin") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "AS", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "asin", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "acos") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "AC", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "acos", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "addhttpheader") == 0)
+ {
+ usesHttp = 1;
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "L", "(Ljava/lang/String;Ljava/lang/String;)V"));
+ return;
+ }
+
+ if (strcmp(name, "alert_alarm") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("javax/microedition/lcdui/AlertType",
+ "ALARM", "Ljavax/microedition/lcdui/AlertType;"));
+ return;
+ }
+
+ if (strcmp(name, "alert_confirmation") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("javax/microedition/lcdui/AlertType",
+ "CONFIRMATION", "Ljavax/microedition/lcdui/AlertType;"));
+ return;
+ }
+
+ if (strcmp(name, "alert_error") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("javax/microedition/lcdui/AlertType",
+ "ERROR", "Ljavax/microedition/lcdui/AlertType;"));
+ return;
+ }
+
+ if (strcmp(name, "alert_info") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("javax/microedition/lcdui/AlertType",
+ "INFO", "Ljavax/microedition/lcdui/AlertType;"));
+ return;
+ }
+
+ if (strcmp(name, "alert_warning") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("javax/microedition/lcdui/AlertType",
+ "WARNING", "Ljavax/microedition/lcdui/AlertType;"));
+ return;
+ }
+
+letter_b:
+letter_c:
+
+ if (strcmp(name, "closeresource") == 0)
+ {
+ usesSupport = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "r", "(Ljava/io/InputStream;)V"));
+ return;
+ }
+
+ if (strcmp(name, "createcommand") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Command", "<init>", "(Ljava/lang/String;II)V");
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "cos") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "C", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "cos", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "chr") == 0)
+ {
+ /* do nothing since we represent chars and integers internally in the same way */
+ return;
+ }
+
+ if (strcmp(name, "copy") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/String", "substring", "(II)Ljava/lang/String;");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "clearform") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/Form"));
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("java/lang/String"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/String", "<init>", "()V"));
+
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "<init>", "(Ljava/lang/String;)V"));
+
+ bytecode_append(code, dup$);
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "setCommandListener", "(Ljavax/microedition/lcdui/CommandListener;)V"));
+
+ goto show_form;
+
+ return;
+ }
+
+ if(strcmp(name, "choiceappendstring") == 0)
+ {
+ usesForms = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "I", "(ILjava/lang/String;)I"));
+ return;
+ }
+
+ if(strcmp(name, "choiceappendstringimage") == 0)
+ {
+ usesForms = 1;
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "I", "(ILjava/lang/String;Ljavax/microedition/lcdui/Image;)I"));
+ return;
+ }
+
+ if(strcmp(name, "choiceisselected") == 0)
+ {
+ usesForms = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "L", "(II)I"));
+ return;
+ }
+
+ if (strcmp(name, ""))
+
+ if(strcmp(name, "choicegetselectedindex") == 0)
+ {
+ usesForms = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "L", "(I)I"));
+ return;
+ }
+
+ if (strcmp(name, "closerecordstore") == 0)
+ {
+ usesRecordStore = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("RS", "L", "(Ljavax/microedition/rms/RecordStore;)V"));
+ return;
+ }
+
+ if (strcmp(name, "closehttp") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "c", "()V"));
+ return;
+ }
+
+letter_d:
+ if (strcmp(name, "deleterecordstore") == 0)
+ {
+ usesRecordStore = 1;
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("RS", "L", "(Ljava/lang/String;)V"));
+ return;
+ }
+
+ if (strcmp(name, "deleterecordstoreentry") == 0)
+ {
+ usesRecordStore = 1;
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code,
+ cp_add_methodref("RS", "L", "(Ljavax/microedition/rms/RecordStore;I)V"));
+ return;
+ }
+
+ if (strcmp(name, "debug") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("java/lang/System", "out", "Ljava/io/PrintStream;"));
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("java/io/PrintStream", "println", "(Ljava/lang/String;)V"));
+ return;
+ }
+
+ if (strcmp(name, "delay") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/Thread", "sleep", "(J)V");
+
+ bytecode_append(code, i2l$);
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawtext") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawString", "(Ljava/lang/String;III)V");
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 20);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawline") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawLine", "(IIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawellipse") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawArc", "(IIIIII)V");
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 0);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 360);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawarc") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawArc", "(IIIIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawrect") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawRect", "(IIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawroundrect") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawRoundRect", "(IIIIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "drawimage") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "drawImage", "(Ljavax/microedition/lcdui/Image;III)V");
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 20);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+letter_e:
+ if (strcmp(name, "emptycommand") == 0)
+ {
+ bytecode_append(code, aconst_null$);
+ return;
+ }
+
+ if (strcmp(name, "exp") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "e", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "exp", "()V"));
+ }
+
+ return;
+ }
+
+letter_f:
+ if (strcmp(name, "frac") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 0x0FFF);
+ bytecode_append(code, iand$);
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "frac", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "fillellipse") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "fillArc", "(IIIIII)V");
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 0);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 360);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "fillrect") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "fillRect", "(IIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+
+ if (strcmp(name, "fillroundrect") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "fillRoundRect", "(IIIIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "formaddstring") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "append", "(Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp(name, "formaddimage") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "append", "(Ljavax/microedition/lcdui/Image;)I"));
+ return;
+ }
+
+ if (strcmp(name, "formadddatefield") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "dd", "(Ljava/lang/String;I)I"));
+ return;
+ }
+
+ if (strcmp(name, "formsetdate") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "dd", "(II)V"));
+ return;
+ }
+
+ if (strcmp(name, "formgetdate") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "dd", "(I)I"));
+ return;
+ }
+
+ if (strcmp(name, "formaddspace") == 0)
+ {
+ /* get Form */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ /* new Spacer */
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/Spacer"));
+
+ bytecode_append(code, dup$);
+
+ /* init spacer(10, 10)*/
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 10);
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Spacer", "<init>", "(II)V"));
+
+ /* form.append(Spacer)*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "append", "(Ljavax/microedition/lcdui/Item;)I"));
+ return;
+ }
+
+ if (strcmp(name, "formaddtextfield") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "Lj", "(Ljava/lang/String;Ljava/lang/String;II)I"));
+ return;
+ }
+
+ if (strcmp(name, "formaddgauge") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "Lj", "(Ljava/lang/String;III)I"));
+ return;
+ }
+
+ if (strcmp(name, "formremove") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "delete", "(I)V"));
+
+ return;
+ }
+
+ if (strcmp(name, "formaddchoice") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "Lj", "(Ljava/lang/String;I)I"));
+ return;
+ }
+
+ if (strcmp(name, "formgetvalue") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "Lja", "(I)I"));
+ return;
+ }
+
+ if (strcmp(name, "formsetvalue") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "Lja", "(II)V"));
+ return;
+ }
+
+ if (strcmp(name, "formgettext") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "ja", "(I)Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "formsettext") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "ja", "(ILjava/lang/String;)V"));
+ return;
+ }
+
+letter_g:
+ if (strcmp(name, "getformtitle") == 0)
+ {
+ usesForms = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("FS", "gft", "()Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "getrecordstorenextid") == 0)
+ {
+ usesRecordStore = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code,
+ cp_add_methodref("RS", "Lja", "(Ljavax/microedition/rms/RecordStore;)I"));
+ return;
+ }
+
+ if (strcmp(name, "getplayerduration") == 0)
+ {
+ usesPlayer = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("P", "c", "()I"));
+ return;
+ }
+
+ if (strcmp(name, "getchar") == 0)
+ {
+ usesSupport = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "gc", "(Ljava/lang/String;I)I"));
+ return;
+ }
+
+ if (strcmp(name, "getrecordstoresize") == 0)
+ {
+ usesRecordStore = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("RS", "j", "(Ljavax/microedition/rms/RecordStore;)I"));
+ return;
+ }
+
+ if (strcmp(name, "getclickedcommand") == 0)
+ {
+ /* return LC */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "LC", "Ljavax/microedition/lcdui/Command;"));
+
+ /* set LC = null */
+ bytecode_append(code, aconst_null$);
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "LC", "Ljavax/microedition/lcdui/Command;"));
+ return;
+ }
+
+ if (strcmp(name, "gettextboxstring") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "TB", "Ljavax/microedition/lcdui/TextBox;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/TextBox", "getString", "()Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "getrelativetimems") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/System", "currentTimeMillis", "()J");
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+ bytecode_append(code, l2i$);
+ return;
+ }
+
+ if (strcmp(name, "getcurrenttime") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/System", "currentTimeMillis", "()J");
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, ldiv$);
+ bytecode_append(code, l2i$);
+ return;
+ }
+
+ if (strcmp(name, "getday") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 5);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getweekday") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 7);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getyearday") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 6);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getmonth") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 2);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ bytecode_append(code, iconst_0$);
+ bytecode_append(code, iadd$);
+
+ return;
+ }
+
+ if (strcmp(name, "getyear") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 1);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getsecond") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 13);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getminute") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 12);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "gethour") == 0)
+ {
+ int method1, method2, method3, method4;
+ method1 = cp_add_methodref("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
+ method2 = cp_add_methodref("java/util/Calendar", "setTime", "(Ljava/util/Date;)V");
+ method3 = cp_add_methodref("java/util/Calendar", "get", "(I)I");
+ method4 = cp_add_methodref("java/util/Date", "<init>", "(J)V");
+
+ /* time as int-seconds traslate into millis-long */
+ bytecode_append(code, i2l$);
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, lmul$);
+
+ /* the stack is now: ..., Calendar, Calendar, Date, Date, Millis */
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, method4);
+
+ /* stack is now Calendar, Calendar, Date*/
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method2);
+
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 11);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method3);
+
+ return;
+ }
+
+ if (strcmp(name, "getkeypressed") == 0)
+ {
+ int field_index = cp_add_fieldref("M", "KP", "I");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getkeyclicked") == 0)
+ {
+ int field_index = cp_add_fieldref("M", "KC", "I");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+ bytecode_append(code, iconst_0$);
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getcolorred") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "getRedComponent", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getcolorgreen") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "getGreenComponent", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getcolorblue") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "getBlueComponent", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getwidth") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Image", "getWidth", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getheight") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Image", "getHeight", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getimagewidth") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Image", "getWidth", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "getimageheight") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Image", "getHeight", "()I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "getstringheight") == 0)
+ {
+ int method_index;
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "getFont", "()Ljavax/microedition/lcdui/Font;");
+ bytecode_append(code, pop$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ method_index = cp_add_methodref("javax/microedition/lcdui/Font", "getHeight", "()I");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "getstringwidth") == 0)
+ {
+ int method_index;
+ int field_index = cp_add_fieldref("M", "G", "Ljavax/microedition/lcdui/Graphics;");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "getFont", "()Ljavax/microedition/lcdui/Font;");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ bytecode_append(code, swap$);
+ method_index = cp_add_methodref("javax/microedition/lcdui/Font", "stringWidth", "(Ljava/lang/String;)I");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "getproperty") == 0)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/System", "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, ifnonnull$);
+ bytecode_append_short_int(code, 11);
+
+ /* if the returned string is null, create an empty string */
+ bytecode_append(code, pop$);
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("java/lang/String"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/String", "<init>", "()V"));
+ return;
+ }
+
+ if (strcmp(name, "getcolorsnum") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "numColors", "()I"));
+ return;
+ }
+
+ if (strcmp(name, "gethttpheader") == 0)
+ {
+ usesHttp = 1;
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "i", "(Ljava/lang/String;)Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "gethttpresponse") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "j", "()Ljava/lang/String;"));
+ return;
+ }
+
+letter_h:
+ if (strcmp(name, "halt") == 0)
+ {
+ int field_index;
+ int method_index;
+
+ field_index = cp_add_fieldref("FW", "fw", "LFW;");
+ method_index = cp_add_methodref("FW", "destroyApp", "(Z)V");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+ bytecode_append(code, iconst_1$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/Thread", "currentThread", "()Ljava/lang/Thread;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/Thread", "join", "()V"));
+
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 1000);
+ bytecode_append(code, i2l$);
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/Thread", "sleep", "(J)V"));
+
+ return;
+ }
+
+letter_i:
+ if (strcmp(name, "imagefromimage") == 0)
+ {
+ usesSupport = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "ii", "(Ljavax/microedition/lcdui/Image;IIII)Ljavax/microedition/lcdui/Image;"));
+ return;
+ }
+
+ if (strcmp(name, "imagefromcanvas") == 0)
+ {
+ usesSupport = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "ii", "(IIII)Ljavax/microedition/lcdui/Image;"));
+ return;
+ }
+
+ if (strcmp(name, "imagefrombuffer") == 0)
+ {
+ usesSupport = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "ii", "(Ljava/lang/String;I)Ljavax/microedition/lcdui/Image;"));
+ return;
+ }
+
+ if (strcmp(name, "integertostring") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("java/lang/StringBuffer"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/StringBuffer", "<init>", "()V"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/StringBuffer", "append", "(I)Ljava/lang/StringBuffer;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("java/lang/StringBuffer", "toString", "()Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "ismidletpaused") == 0)
+ {
+ int field_index = cp_add_fieldref("FW", "MP", "I");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ return;
+ }
+
+ if (strcmp(name, "ishttpopen") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "L", "()I"));
+ return;
+ }
+
+ if (strcmp(name, "iscolordisplay") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "isColor", "()Z"));
+
+ bytecode_append(code, ifeq$);
+ bytecode_append_short_int(code, 7);
+
+ bytecode_append(code, iconst_m1$);
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 4);
+
+ bytecode_append(code, iconst_0$);
+
+ return;
+ }
+
+letter_j:
+letter_k:
+ if (strcmp(name, "keytoaction") == 0)
+ {
+ int field_index = cp_add_fieldref("M", "T", "LM;");
+
+ /* check if the argument is zero, goto (1)*/
+ bytecode_append(code, dup$);
+ bytecode_append(code, ifeq$);
+ bytecode_append_short_int(code, 13);
+
+ /* otherwise call the getGameAction*/
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("M", "getGameAction", "(I)I"));
+
+ /* goto (2) */
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 5);
+
+ /* (1): pop the operands, push 0 to the stack */
+ bytecode_append(code, pop$);
+ bytecode_append(code, iconst_0$);
+
+ /* (2): continue */
+
+ return;
+ }
+
+letter_l:
+ if (strcmp(name, "log") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "log", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "ln", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "log10") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "log10", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "log10", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "length") == 0)
+ {
+ int method_index = cp_add_methodref("java/lang/String", "length", "()I");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "locase") == 0)
+ {
+ int init_index;
+ int class_index;
+ int method_index;
+
+ class_index = cp_add_class("java/lang/String");
+ init_index = cp_add_methodref("java/lang/String", "<init>", "(Ljava/lang/String;)V");
+ method_index = cp_add_methodref("java/lang/String", "toLowerCase", "()Ljava/lang/String;");
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class_index);
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, init_index);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "loadimage") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Image", "createImage", "(Ljava/lang/String;)Ljavax/microedition/lcdui/Image;");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+letter_m:
+ if (strcmp(name, "modifyrecordstoreentry") == 0)
+ {
+ usesRecordStore = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code,
+ cp_add_methodref("RS", "L", "(Ljavax/microedition/rms/RecordStore;Ljava/lang/String;I)V"));
+ return;
+ }
+
+
+ if (strcmp(name, "menuappendstring") == 0)
+ {
+ bytecode_append(code, aconst_null$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/List",
+ "append",
+ "(Ljava/lang/String;Ljavax/microedition/lcdui/Image;)I"));
+ return;
+ }
+
+ if (strcmp(name, "menuappendstringimage") == 0)
+ {
+ //usesRegisteredFeature = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/List",
+ "append",
+ "(Ljava/lang/String;Ljavax/microedition/lcdui/Image;)I"));
+ return;
+ }
+
+ if (strcmp(name, "menuisselected") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/List",
+ "isSelected",
+ "(I)Z"));
+
+ bytecode_append(code, ifeq$);
+ bytecode_append_short_int(code, 7);
+ bytecode_append(code, iconst_m1$);
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 4);
+ bytecode_append(code, iconst_0$);
+
+ return;
+ }
+
+ if (strcmp(name, "menugetselectedindex") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/List",
+ "getSelectedIndex",
+ "()I"));
+ return;
+ }
+
+
+
+letter_n:
+letter_o:
+
+ if (strcmp(name, "openplayer") == 0)
+ {
+ usesPlayer = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("P", "a", "(Ljava/lang/String;Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp(name, "openresource") == 0)
+ {
+ usesSupport = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "r", "(Ljava/lang/String;)Ljava/io/InputStream;"));
+ return;
+ }
+
+ if (strcmp(name, "ord") == 0)
+ {
+ /* do nothing, opposite of chr */
+ return;
+ }
+
+ if (strcmp(name, "openhttp") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "L", "(Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp(name, "odd") == 0)
+ {
+ /* just leave the last bit: if it is zero, the number is even and the 0 (false)
+ will be on the stack */
+ bytecode_append(code, iconst_1$);
+ bytecode_append(code, iand$);
+ bytecode_append(code, iconst_m1$);
+ bytecode_append(code, imul$);
+
+ return;
+ }
+
+ if (strcmp(name, "openrecordstore") == 0)
+ {
+ usesRecordStore = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("RS", "j", "(Ljava/lang/String;)Ljavax/microedition/rms/RecordStore;"));
+ return;
+ }
+
+letter_p:
+ if (strcmp(name, "playtone") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/media/Manager", "playTone", "(III)V");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "playalertsound") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "A", "Ljavax/microedition/lcdui/Alert;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Alert", "getType", "()Ljavax/microedition/lcdui/AlertType;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref(
+ "javax/microedition/lcdui/AlertType",
+ "playSound",
+ "(Ljavax/microedition/lcdui/Display;)Z"));
+
+ bytecode_append(code, pop$);
+ return;
+ }
+
+ if (strcmp(name, "pow") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "p", "(II)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "pow", "(LReal;)V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "pos") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/String", "indexOf", "(Ljava/lang/String;)I");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+ if (strcmp(name, "plot") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "fillRect", "(IIII)V");
+
+ bytecode_append(code, iconst_1$);
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+letter_q:
+letter_r:
+ if (strcmp(name, "removeformtitle") == 0)
+ {
+ /* get Form */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ /* set the form's title to null */
+ bytecode_append(code, aconst_null$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "setTitle", "(Ljava/lang/String;)V"));
+
+ return;
+ }
+
+ if (strcmp(name, "resourceavailable") == 0)
+ {
+ bytecode_append(code, aconst_null$);
+ bytecode_append(code, if_acmpeq$);
+ bytecode_append_short_int(code, 7);
+
+ bytecode_append(code, iconst_m1$);
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 4);
+
+ bytecode_append(code, iconst_0$);
+ return;
+ }
+
+ if (strcmp(name, "readbyte") == 0)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "rb", "(Ljava/io/InputStream;)I"));
+ return;
+ }
+
+ if (strcmp(name, "readline") == 0)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "nl", "(Ljava/io/InputStream;)Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "readrecordstoreentry") == 0)
+ {
+ usesRecordStore = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("RS", "j", "(Ljavax/microedition/rms/RecordStore;I)Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "round") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("java/lang/Math", "round", "(F)I");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "rabs") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "A", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "abs", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "randomize") == 0)
+ {
+ /* re-initialize the random number generator */
+ int random_field_index;
+ int random_class_index;
+ int random_method_index;
+
+ random_field_index = cp_add_fieldref("M", "RNG", "Ljava/util/Random;");
+ random_class_index = cp_add_class("java/util/Random");
+ random_method_index = cp_add_methodref("java/util/Random", "<init>", "()V");
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, random_class_index);
+
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, random_method_index);
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, random_field_index);
+ return;
+ }
+
+ if (strcmp(name, "random") == 0)
+ {
+ int rng_index;
+ int method_index;
+
+ rng_index = cp_add_fieldref("M", "RNG", "Ljava/util/Random;");
+ method_index = cp_add_methodref("java/util/Random", "nextInt", "()I");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, rng_index);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ // do abs
+ bytecode_append(code, iconst_m1$);
+ bytecode_append(code, iconst_1$);
+ bytecode_append(code, iushr$);
+ bytecode_append(code, iand$);
+
+ bytecode_append(code, swap$);
+ bytecode_append(code, irem$);
+
+ return;
+ }
+
+ if (strcmp(name, "removecommand") == 0)
+ {
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "removeCommand", "(Ljavax/microedition/lcdui/Command;)V"));
+ return;
+ }
+
+
+ if (strcmp(name, "repaint") == 0)
+ {
+ int method_index;
+ int field_index;
+
+ method_index = cp_add_methodref("M", "repaint", "()V");
+ field_index = cp_add_fieldref("M", "T", "LM;");
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, field_index);
+
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ method_index = cp_add_methodref("M", "serviceRepaints", "()V");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+letter_s:
+ if (strcmp(name, "setformtitle") == 0)
+ {
+ /* get Form */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ /* set the form's title */
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "setTitle", "(Ljava/lang/String;)V"));
+
+ return;
+ }
+
+ if (strcmp(name, "setclip") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "setClip", "(IIII)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp("smsstartsend", name) == 0)
+ {
+ usesSMS = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("SM", "send", "(Ljava/lang/String;Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp("smsissending", name) == 0)
+ {
+ usesSMS = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("SM", "IS", "()I"));
+ return;
+ }
+
+ if (strcmp("smswassuccessfull", name) == 0)
+ {
+ usesSMS = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("SM", "GS", "()I"));
+ return;
+ }
+
+ if (strcmp("startplayer", name) == 0)
+ {
+ usesPlayer = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("P", "a", "()I"));
+ return;
+ }
+
+ if (strcmp("stopplayer", name) == 0)
+ {
+ usesPlayer = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("P", "b", "()V"));
+ return;
+ }
+
+ if (strcmp("setplayercount", name) == 0)
+ {
+ usesPlayer = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("P", "a", "(I)I"));
+ return;
+ }
+
+ if (strcmp(name, "setchar") == 0)
+ {
+ usesSupport = 1;
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "gc", "(Ljava/lang/String;II)Ljava/lang/String;"));
+ return;
+ }
+
+ if (strcmp(name, "sqr") == 0)
+ {
+ bytecode_append(code, dup$);
+ bytecode_append(code, imul$);
+
+ return;
+ }
+
+ if (strcmp(name, "setticker") == 0)
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("javax/microedition/lcdui/Ticker"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Ticker", "<init>", "(Ljava/lang/String;)V"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, swap$);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Form", "setTicker", "(Ljavax/microedition/lcdui/Ticker;)V"));
+ return;
+ }
+
+ if (strcmp(name, "stringtointeger") == 0)
+ {
+ usesSupport = 1;
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("S", "parseInt", "(Ljava/lang/String;)I"));
+ return;
+ }
+
+ if (strcmp(name, "stringtoreal") == 0)
+ {
+ usesFloat = 1;
+ //usesRegisteredFeature = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "fI", "(Ljava/lang/String;I)I"));
+ }
+ else
+ {
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(Ljava/lang/String;I)V"));
+ }
+
+ return;
+ }
+
+
+ if (strcmp(name, "sqrt") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "S", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "sqrt", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "sin") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "s", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "sin", "()V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "setcolor") == 0)
+ {
+ int method_index;
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "setColor", "(III)V");
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+
+
+ if (strcmp(name, "setfont") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Font", "getFont", "(III)Ljavax/microedition/lcdui/Font;");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "setFont", "(Ljavax/microedition/lcdui/Font;)V");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+
+ if (strcmp(name, "setdefaultfont") == 0)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Font", "getDefaultFont", "()Ljavax/microedition/lcdui/Font;");
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, method_index);
+
+ method_index = cp_add_methodref("javax/microedition/lcdui/Graphics", "setFont", "(Ljavax/microedition/lcdui/Font;)V");
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+
+ return;
+ }
+
+ if (strcmp(name, "sethttpmethod") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "c", "(Ljava/lang/String;)V"));
+ return;
+ }
+
+ if (strcmp(name, "sendhttpmessage") == 0)
+ {
+ usesHttp = 1;
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("H", "o", "()I"));
+ return;
+ }
+
+ if (strcmp(name, "showform") == 0)
+ {
+show_form:
+ /*
+ Display.getDisplay(FW.fw).setCurrent(FW.F);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "setCurrent", "(Ljavax/microedition/lcdui/Displayable;)V"));
+
+ /*
+ FW.CD = FW.F;
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "F", "Ljavax/microedition/lcdui/Form;"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+ return;
+ }
+
+ if (strcmp(name, "showcanvas") == 0)
+ {
+ /*
+ Display.getDisplay(FW.fw).setCurrent(M.T);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "T", "LM;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "setCurrent", "(Ljavax/microedition/lcdui/Displayable;)V"));
+
+ /*
+ FW.CD = M.T;
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "T", "LM;"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+ return;
+ }
+
+
+ if (strcmp(name, "showtextbox") == 0)
+ {
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/TextBox", "<init>", "(Ljava/lang/String;Ljava/lang/String;II)V"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "TB", "Ljavax/microedition/lcdui/TextBox;"));
+
+ /*
+ Display.getDisplay(FW.fw).setCurrent(FW.TB);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "TB", "Ljavax/microedition/lcdui/TextBox;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "setCurrent", "(Ljavax/microedition/lcdui/Displayable;)V"));
+
+ /*
+ FW.CD = FW.TB;
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "TB", "Ljavax/microedition/lcdui/TextBox;"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+
+ /*
+ FW.TB.setCommandListener(FW.fw);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "TB", "Ljavax/microedition/lcdui/TextBox;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "setCommandListener", "(Ljavax/microedition/lcdui/CommandListener;)V"));
+
+ return;
+ }
+
+ if (strcmp(name, "showmenu") == 0)
+ {
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/List", "<init>", "(Ljava/lang/String;I)V"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "L", "Ljavax/microedition/lcdui/List;"));
+
+ /*
+ Display.getDisplay(FW.fw).setCurrent(FW.L);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "L", "Ljavax/microedition/lcdui/List;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "setCurrent", "(Ljavax/microedition/lcdui/Displayable;)V"));
+
+ /*
+ FW.CD = FW.L;
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "L", "Ljavax/microedition/lcdui/List;"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+
+ /*
+ FW.L.setCommandListener(FW.fw);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "L", "Ljavax/microedition/lcdui/List;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Displayable", "setCommandListener", "(Ljavax/microedition/lcdui/CommandListener;)V"));
+
+
+ return;
+ }
+
+
+ if (strcmp(name, "showalert") == 0)
+ {
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Alert", "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljavax/microedition/lcdui/Image;Ljavax/microedition/lcdui/AlertType;)V"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "A", "Ljavax/microedition/lcdui/Alert;"));
+
+ /*
+ Display.getDisplay(FW.fw).setCurrent(FW.A);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "getDisplay", "(Ljavax/microedition/midlet/MIDlet;)Ljavax/microedition/lcdui/Display;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "A", "Ljavax/microedition/lcdui/Alert;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "setCurrent", "(Ljavax/microedition/lcdui/Displayable;)V"));
+
+ /*
+ FW.CD = FW.A;
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "A", "Ljavax/microedition/lcdui/Alert;"));
+
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "CD", "Ljavax/microedition/lcdui/Displayable;"));
+
+ /*
+ FW.A.setCommandListener(FW.fw);
+ */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "A", "Ljavax/microedition/lcdui/Alert;"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("FW", "fw", "LFW;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Alert", "setCommandListener", "(Ljavax/microedition/lcdui/CommandListener;)V"));
+
+
+ return;
+ }
+
+letter_t:
+ if (strcmp(name, "trunc") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "tI", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "trunc", "()V"));
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "toInteger", "()I"));
+ }
+
+ return;
+ }
+
+
+ if (strcmp(name, "tan") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "tan", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+ bytecode_append(code, dup$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "tan", "()V"));
+ }
+
+ return;
+ }
+
+
+
+ if (strcmp(name, "todegrees") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "tD", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, dup$);
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 180);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "mul", "(I)V"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("Real", "PI", "LReal;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "div", "(LReal;)V"));
+ }
+
+ return;
+ }
+
+ if (strcmp(name, "toradians") == 0)
+ {
+ usesFloat = 1;
+ if (mathType == 1)
+ {
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("F", "tR", "(I)I"));
+ }
+ else
+ {
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, cp_add_class("Real"));
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "<init>", "(LReal;)V"));
+
+ bytecode_append(code, dup$);
+ bytecode_append(code, dup$);
+
+ bytecode_append(code, sipush$);
+ bytecode_append_short_int(code, 180);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "div", "(I)V"));
+
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("Real", "PI", "LReal;"));
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("Real", "mul", "(LReal;)V"));
+ }
+
+ return;
+ }
+letter_u:
+ if (strcmp(name, "upcase") == 0)
+ {
+ int init_index;
+ int class_index;
+ int method_index;
+
+ class_index = cp_add_class("java/lang/String");
+ init_index = cp_add_methodref("java/lang/String", "<init>", "(Ljava/lang/String;)V");
+ method_index = cp_add_methodref("java/lang/String", "toUpperCase", "()Ljava/lang/String;");
+
+ bytecode_append(code, new$);
+ bytecode_append_short_int(code, class_index);
+ bytecode_append(code, dup_x1$);
+ bytecode_append(code, swap$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, init_index);
+
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, method_index);
+ return;
+ }
+
+letter_v:
+ if (strcmp(name, "vibrate") == 0)
+ {
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Display", "vibrate", "(I)Z"));
+
+ bytecode_append(code, pop$);
+ return;
+ }
+letter_w:
+letter_x:
+letter_y:
+letter_z:
+
+ if (count == 0)
+ {
+ count ++;
+ goto letter_a;
+ }
+
+ die(25);
+}
+
+
+/*
+ Adds a function with 0 or 1 parameter
+*/
+void add_special_function(block *item, enum en_type_class parameter_en, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en;
+ return_type->type_class = return_type_en;
+ if (parameter_en != void_type)
+ type_list_append(params, param);
+ type_destroy(param);
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
+
+/*
+ Adds a function with 2 parameters
+*/
+void add_special_function2(block *item, enum en_type_class parameter_en1, enum en_type_class parameter_en2, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en1;
+ return_type->type_class = return_type_en;
+ type_list_append(params, param);
+ param->type_class = parameter_en2;
+ type_list_append(params, param);
+ type_destroy(param);
+
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
+
+/*
+ Adds a function with 3 parameters
+*/
+void add_special_function3(block *item, enum en_type_class parameter_en1, enum en_type_class parameter_en2, enum en_type_class parameter_en3, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en1;
+ return_type->type_class = return_type_en;
+ type_list_append(params, param);
+ param->type_class = parameter_en2;
+ type_list_append(params, param);
+ param->type_class = parameter_en3;
+ type_list_append(params, param);
+ type_destroy(param);
+
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
+
+/*
+ Adds a function with 4 parameters
+*/
+void add_special_function4(block *item, enum en_type_class parameter_en1, enum en_type_class parameter_en2, enum en_type_class parameter_en3, enum en_type_class parameter_en4, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en1;
+ return_type->type_class = return_type_en;
+ type_list_append(params, param);
+ param->type_class = parameter_en2;
+ type_list_append(params, param);
+ param->type_class = parameter_en3;
+ type_list_append(params, param);
+ param->type_class = parameter_en4;
+ type_list_append(params, param);
+ type_destroy(param);
+
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
+
+/*
+ Adds a function with 5 parameters
+*/
+void add_special_function5(block *item, enum en_type_class parameter_en1, enum en_type_class parameter_en2, enum en_type_class parameter_en3, enum en_type_class parameter_en4, enum en_type_class parameter_en5, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en1;
+ return_type->type_class = return_type_en;
+ type_list_append(params, param);
+ param->type_class = parameter_en2;
+ type_list_append(params, param);
+ param->type_class = parameter_en3;
+ type_list_append(params, param);
+ param->type_class = parameter_en4;
+ type_list_append(params, param);
+ param->type_class = parameter_en5;
+ type_list_append(params, param);
+ type_destroy(param);
+
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
+
+/*
+ Adds a function with 6 parameters
+*/
+void add_special_function6(block *item, enum en_type_class parameter_en1, enum en_type_class parameter_en2, enum en_type_class parameter_en3, enum en_type_class parameter_en4, enum en_type_class parameter_en5, enum en_type_class parameter_en6, enum en_type_class return_type_en, char *name)
+{
+ type_list *params;
+ type *param;
+ type *return_type;
+
+ params = type_list_create();
+ param = type_create();
+ return_type = type_create();
+ param->type_class = parameter_en1;
+ return_type->type_class = return_type_en;
+ type_list_append(params, param);
+ param->type_class = parameter_en2;
+ type_list_append(params, param);
+ param->type_class = parameter_en3;
+ type_list_append(params, param);
+ param->type_class = parameter_en4;
+ type_list_append(params, param);
+ param->type_class = parameter_en5;
+ type_list_append(params, param);
+ param->type_class = parameter_en6;
+ type_list_append(params, param);
+ type_destroy(param);
+
+ if (return_type_en == void_type)
+ add_std_procedure(item, name, params);
+ else
+ add_std_function(item, name, params, return_type);
+}
diff --git a/MPC.3.5.LINUX/parser/stdpas.h b/MPC.3.5.LINUX/parser/stdpas.h
--- /dev/null
@@ -0,0 +1,27 @@
+/********************************************************************
+
+ stdpas.h - initializes the parser/semantic checker with a
+ standard pascal types, constants etc.
+
+ Niksa Orlic, 2004-04-29
+
+********************************************************************/
+
+block* initialize_root_block();
+
+void add_std_types(block*);
+void add_std_constants(block*);
+void add_std_functions(block*);
+void add_std_type(block*, enum en_type_class , char*);
+void add_std_function(block*, char*, type_list*, type*);
+void add_std_procedure(block*, char*, type_list*);
+
+void create_std_function_code(bytecode*, char*);
+void create_std_function_prefix(bytecode*, char*);
+
+void add_special_function(block*, enum en_type_class, enum en_type_class, char*);
+void add_special_function2(block*, enum en_type_class, enum en_type_class, enum en_type_class, char*);
+void add_special_function3(block*, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, char*);
+void add_special_function4(block*, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, char*);
+void add_special_function5(block*, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, char*);
+void add_special_function6(block*, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, enum en_type_class, char*);
diff --git a/MPC.3.5.LINUX/preverifier/README.TXT b/MPC.3.5.LINUX/preverifier/README.TXT
--- /dev/null
@@ -0,0 +1,15 @@
+PREVERIFIER TOOL
+
+This directory contains the source code of the
+preverifier tool that is used for preprocessing
+Java class files for the KVM. The preprocessed
+class files are regular Java class files, but
+they contain some additional/modified information
+that will help speed up runtime verification.
+
+The preverifier implementation is derived from
+the J2SE class file verifier that was written
+originally for the "Classic" Java Virtual Machine.
+Therefore, the implementation style is quite
+different from the rest of the KVM codebase.
+
diff --git a/MPC.3.5.LINUX/preverifier/check_class.c b/MPC.3.5.LINUX/preverifier/check_class.c
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * @(#)check_class.c 1.6 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Verifies ClassClass structure.
+ * FILE: check_class.c
+ * OVERVIEW: Code for verifying the ClassClass structure for internal
+ * consistency.
+ * AUTHOR: Sheng Liang, Consumer & Embedded
+ * Initial implementation based on the Classic VM Verifier.
+ * Edited by Tasneem Sayeed, Java Consumer Technologies
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <ctype.h>
+
+#include "oobj.h"
+#include "utf.h"
+#include "tree.h"
+#include "sys_api.h"
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+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 };
+
+
+/*=========================================================================
+ * FUNCTION: VerifyClass
+ * OVERVIEW: Verifies a class given a pointer to the ClassClass struct.
+ * Returns true if the class is ok.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ *
+ * returns: boolean type
+ *=======================================================================*/
+bool_t
+VerifyClass(ClassClass *cb)
+{
+ verify_class_codes(cb);
+ return TRUE;
+ /*
+ bool_t result = TRUE;
+ struct methodblock *mb;
+ struct fieldblock *fb;
+ int i;
+ 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);
+ return result;*/
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_constant_pool
+ * OVERVIEW: Verifies the constant pool given a pointer to the
+ * ClassClass structure.
+ * Makes two quick passes over the constant pool. The first
+ * pass ensures that everything is of the right type.
+ * Returns true if the constant pool is ok.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ *
+ * returns: boolean type
+ *=======================================================================*/
+/*
+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;
+}
+ */
+
+/*=========================================================================
+ * FUNCTION: is_legal_fieldname
+ * OVERVIEW: Returns true if the given name within the given ClassClass
+ * structure consists of a legal fieldname or a classname
+ * if the third argument is LegalClass.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ * char*: legal field name or a classname
+ * int: type of name (class or field name)
+ *
+ * returns: boolean type
+ *=======================================================================*/
+#if 0
+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;
+
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: is_legal_field_signature
+ * OVERVIEW: Returns true if the entire given string within the given
+ * ClassClass structure consists of a legal field signature.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ * char*: field name
+ * char*: field signature
+ *
+ * returns: boolean type
+ *=======================================================================*/
+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;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: is_legal_method_signature
+ * OVERVIEW: Returns true if the entire given string within the given
+ * ClassClass structure consists of a legal method signature.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ * char*: method name
+ * char*: method signature
+ *
+ * returns: boolean type
+ *=======================================================================*/
+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;
+}
+
+#endif
+
+#if 0
+
+/*=========================================================================
+ * Automatic code generation tables
+ *=======================================================================*/
+ /* The following tables and code generated using: */
+ /* java GenerateCharacter -verbose -c -identifiers -spec UnicodeData-2.1.2.txt -template check_class.c.template -o check_class.c 8 4 4 */
+ /* The X table has 256 entries for a total of 256 bytes. */
+
+ static unsigned char X[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000 */
+ 7, 8, 9, 10, 11, 12, 13, 14, /* 0x0800 */
+ 15, 16, 7, 7, 7, 7, 7, 7, /* 0x1000 */
+ 7, 7, 7, 7, 7, 7, 17, 18, /* 0x1800 */
+ 19, 20, 7, 7, 7, 7, 7, 7, /* 0x2000 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0x2800 */
+ 21, 22, 7, 7, 7, 7, 7, 7, /* 0x3000 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0x3800 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0x4000 */
+ 7, 7, 7, 7, 7, 7, 23, 23, /* 0x4800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x5000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x5800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x6000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x6800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x7000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x7800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x8000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x8800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0x9000 */
+ 23, 23, 23, 23, 23, 23, 23, 24, /* 0x9800 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0xA000 */
+ 7, 7, 7, 7, 23, 23, 23, 23, /* 0xA800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0xB000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0xB800 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0xC000 */
+ 23, 23, 23, 23, 23, 23, 23, 23, /* 0xC800 */
+ 23, 23, 23, 23, 23, 23, 23, 25, /* 0xD000 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0xD800 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0xE000 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0xE800 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 0xF000 */
+ 7, 23, 26, 27, 23, 28, 29, 30 /* 0xF800 */
+ };
+
+ /* The Y table has 496 entries for a total of 496 bytes. */
+
+ static unsigned char Y[496] = {
+ 0, 0, 1, 2, 3, 4, 3, 5, /* 0 */
+ 0, 0, 6, 7, 8, 9, 8, 9, /* 0 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 1 */
+ 8, 8, 8, 8, 8, 8, 8, 10, /* 1 */
+ 8, 11, 0, 0, 0, 8, 8, 8, /* 2 */
+ 8, 8, 12, 13, 14, 14, 15, 0, /* 2 */
+ 16, 16, 16, 16, 17, 0, 18, 19, /* 3 */
+ 20, 8, 21, 8, 22, 23, 24, 25, /* 3 */
+ 26, 8, 8, 8, 8, 26, 8, 8, /* 4 */
+ 27, 8, 8, 8, 28, 8, 29, 30, /* 4 */
+ 0, 0, 0, 3, 8, 31, 3, 8, /* 5 */
+ 11, 32, 33, 34, 35, 8, 5, 36, /* 5 */
+ 0, 0, 3, 5, 37, 38, 2, 39, /* 6 */
+ 8, 8, 8, 40, 22, 41, 42, 2, /* 6 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
+ 43, 8, 8, 44, 45, 46, 47, 0, /* 8 */
+ 48, 49, 50, 51, 52, 53, 47, 25, /* 8 */
+ 54, 49, 50, 55, 56, 57, 58, 59, /* 9 */
+ 60, 21, 50, 61, 62, 0, 63, 0, /* 9 */
+ 48, 49, 50, 64, 65, 66, 67, 0, /* 10 */
+ 68, 69, 70, 71, 72, 73, 74, 0, /* 10 */
+ 75, 24, 50, 76, 77, 78, 67, 0, /* 11 */
+ 79, 24, 50, 76, 77, 80, 67, 0, /* 11 */
+ 79, 24, 50, 81, 82, 73, 67, 0, /* 12 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 12 */
+ 3, 8, 22, 83, 84, 2, 0, 0, /* 13 */
+ 85, 86, 87, 88, 89, 90, 0, 0, /* 13 */
+ 0, 91, 2, 92, 93, 8, 94, 32, /* 14 */
+ 95, 96, 45, 97, 0, 0, 0, 0, /* 14 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 15 */
+ 0, 0, 8, 8, 98, 8, 8, 99, /* 15 */
+ 8, 8, 8, 8, 8, 100, 8, 8, /* 16 */
+ 8, 8, 101, 8, 8, 8, 8, 94, /* 16 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 17 */
+ 8, 102, 8, 8, 8, 8, 8, 94, /* 17 */
+ 8, 103, 8, 8, 103, 104, 8, 105, /* 18 */
+ 8, 8, 8, 106, 107, 108, 109, 107, /* 18 */
+ 0, 0, 0, 110, 111, 0, 0, 110, /* 19 */
+ 0, 0, 109, 0, 0, 112, 113, 0, /* 19 */
+ 114, 115, 116, 117, 0, 0, 8, 8, /* 20 */
+ 36, 0, 0, 0, 0, 0, 0, 0, /* 20 */
+ 118, 0, 119, 120, 3, 8, 8, 8, /* 21 */
+ 8, 121, 3, 8, 8, 8, 8, 122, /* 21 */
+ 123, 8, 109, 3, 8, 8, 8, 8, /* 22 */
+ 22, 0, 0, 0, 0, 0, 0, 0, /* 22 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 23 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 23 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 24 */
+ 8, 8, 98, 0, 0, 0, 0, 0, /* 24 */
+ 8, 8, 8, 8, 8, 8, 8, 8, /* 25 */
+ 8, 8, 25, 0, 0, 0, 0, 0, /* 25 */
+ 8, 8, 105, 0, 0, 0, 0, 0, /* 26 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 26 */
+ 99, 124, 50, 125, 126, 8, 8, 8, /* 27 */
+ 8, 8, 8, 14, 0, 127, 8, 8, /* 27 */
+ 8, 8, 8, 105, 0, 8, 8, 8, /* 28 */
+ 8, 128, 8, 8, 11, 0, 0, 102, /* 28 */
+ 0, 0, 129, 130, 131, 0, 132, 133, /* 29 */
+ 8, 8, 8, 8, 8, 8, 8, 109, /* 29 */
+ 1, 2, 3, 4, 3, 5, 134, 8, /* 30 */
+ 8, 8, 8, 22, 135, 136, 137, 0 /* 30 */
+ };
+
+ /* The A table has 2208 entries for a total of 552 bytes. */
+
+ static unsigned long A[138] = {
+ 0x00000000, /* 0 */
+ 0x00000300, /* 1 */
+ 0x00055555, /* 2 */
+ 0xFFFFFFFC, /* 3 */
+ 0xC03FFFFF, /* 4 */
+ 0x003FFFFF, /* 5 */
+ 0x00300FF0, /* 6 */
+ 0x00300C00, /* 7 */
+ 0xFFFFFFFF, /* 8 */
+ 0xFFFF3FFF, /* 9 */
+ 0xFFF00FFF, /* 10 */
+ 0x0000FFFF, /* 11 */
+ 0x0003FFFF, /* 12 */
+ 0xFFC3FFFF, /* 13 */
+ 0x0000000F, /* 14 */
+ 0x000003FF, /* 15 */
+ 0x55555555, /* 16 */
+ 0x00000555, /* 17 */
+ 0x00000005, /* 18 */
+ 0x00300000, /* 19 */
+ 0xF33F3000, /* 20 */
+ 0xFFFFFFCF, /* 21 */
+ 0x3FFFFFFF, /* 22 */
+ 0x33303FFF, /* 23 */
+ 0xFFFFFFF3, /* 24 */
+ 0x000000FF, /* 25 */
+ 0xF3FFFFFC, /* 26 */
+ 0x0000154F, /* 27 */
+ 0x03C3C3FF, /* 28 */
+ 0xF0FFFFFF, /* 29 */
+ 0x000F0FFF, /* 30 */
+ 0x000C3FFF, /* 31 */
+ 0x55555554, /* 32 */
+ 0x55555545, /* 33 */
+ 0x45455555, /* 34 */
+ 0x00000114, /* 35 */
+ 0x0000003F, /* 36 */
+ 0x557FFFFF, /* 37 */
+ 0x00000015, /* 38 */
+ 0xFFFFFFFD, /* 39 */
+ 0x3FF0FFFF, /* 40 */
+ 0x41555CFF, /* 41 */
+ 0x05517D55, /* 42 */
+ 0xFFFFFC54, /* 43 */
+ 0x5D0FFFFF, /* 44 */
+ 0x05555555, /* 45 */
+ 0xFFFF0154, /* 46 */
+ 0x5555505F, /* 47 */
+ 0xC3FFFC54, /* 48 */
+ 0xFFFFFFC3, /* 49 */
+ 0xFFF3FFFF, /* 50 */
+ 0x510FF033, /* 51 */
+ 0x05414155, /* 52 */
+ 0xCF004000, /* 53 */
+ 0xC03FFC10, /* 54 */
+ 0x510F3CF3, /* 55 */
+ 0x05414015, /* 56 */
+ 0x33FC0000, /* 57 */
+ 0x55555000, /* 58 */
+ 0x000003F5, /* 59 */
+ 0xCCFFFC54, /* 60 */
+ 0x5D0FFCF3, /* 61 */
+ 0x05454555, /* 62 */
+ 0x55555003, /* 63 */
+ 0x5D0FF0F3, /* 64 */
+ 0x05414055, /* 65 */
+ 0xCF005000, /* 66 */
+ 0x5555500F, /* 67 */
+ 0xF03FFC50, /* 68 */
+ 0xF33C0FF3, /* 69 */
+ 0xF03F03C0, /* 70 */
+ 0x500FCFFF, /* 71 */
+ 0x05515015, /* 72 */
+ 0x00004000, /* 73 */
+ 0x55554000, /* 74 */
+ 0xF3FFFC54, /* 75 */
+ 0x500FFCFF, /* 76 */
+ 0x05515155, /* 77 */
+ 0x00001400, /* 78 */
+ 0xF3FFFC50, /* 79 */
+ 0x30001400, /* 80 */
+ 0x500FFFFF, /* 81 */
+ 0x05515055, /* 82 */
+ 0xC01555F7, /* 83 */
+ 0x15557FFF, /* 84 */
+ 0x0C33C33C, /* 85 */
+ 0xFFFCFF00, /* 86 */
+ 0x3CF0CCFC, /* 87 */
+ 0x0D4555F7, /* 88 */
+ 0x055533FF, /* 89 */
+ 0x0F055555, /* 90 */
+ 0x00050000, /* 91 */
+ 0x50044400, /* 92 */
+ 0xFFFCFFFF, /* 93 */
+ 0x000FFFFF, /* 94 */
+ 0x00555155, /* 95 */
+ 0x55544555, /* 96 */
+ 0x00045554, /* 97 */
+ 0x00000FFF, /* 98 */
+ 0x00003FFF, /* 99 */
+ 0xC00FFFFF, /* 100 */
+ 0xFFFF003F, /* 101 */
+ 0x00FFFFFF, /* 102 */
+ 0x0FFF0FFF, /* 103 */
+ 0xCCCCFFFF, /* 104 */
+ 0x0FFFFFFF, /* 105 */
+ 0x33FFF3FF, /* 106 */
+ 0x03FFF3F0, /* 107 */
+ 0x00FFF0FF, /* 108 */
+ 0x03FFFFFF, /* 109 */
+ 0xC0000000, /* 110 */
+ 0x00000003, /* 111 */
+ 0x01555555, /* 112 */
+ 0x00000004, /* 113 */
+ 0xFFF0C030, /* 114 */
+ 0x0FFF0CFF, /* 115 */
+ 0xFFF33300, /* 116 */
+ 0x0003FFCF, /* 117 */
+ 0x0000CC00, /* 118 */
+ 0x555FFFFC, /* 119 */
+ 0x00000FFC, /* 120 */
+ 0x3FD403FF, /* 121 */
+ 0x3F3FFFFF, /* 122 */
+ 0xFFFFFC00, /* 123 */
+ 0xD000FFC0, /* 124 */
+ 0x33FF3FFF, /* 125 */
+ 0xFFFFF3CF, /* 126 */
+ 0xFFFFFFC0, /* 127 */
+ 0xFFFFFFF0, /* 128 */
+ 0x00000055, /* 129 */
+ 0x000003C0, /* 130 */
+ 0xFC000000, /* 131 */
+ 0x000C0000, /* 132 */
+ 0xFFFFF33F, /* 133 */
+ 0xFFFFF000, /* 134 */
+ 0xFFF0FFF0, /* 135 */
+ 0x03F0FFF0, /* 136 */
+ 0x00003C0F /* 137 */
+ };
+
+ /* In all, the character property tables require 1304 bytes. */
+
+/*
+ * 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) (((A[Y[(X[ch>>8]<<4)|((ch>>4)&0xF)]]>>((ch&0xF)<<1))&3) & 0x2)
+
+/*
+ * 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) (((A[Y[(X[ch>>8]<<4)|((ch>>4)&0xF)]]>>((ch&0xF)<<1))&3) & 0x1)
+
+
+/*=========================================================================
+ * FUNCTION: skip_over_fieldname
+ * OVERVIEW: Skips over the longest part of the string that could be
+ * taken as a fieldname given a pointer to a string.
+ * Allows '/' if slash_okay parameter is true.
+ * Returns a pointer to just past the fieldname.
+ * Returns NULL if no fieldname is found, or in the case of
+ * slash_okay being TRUE, we may see consecutive slashes
+ * (meaning that we were looking for a qualified path, but
+ * found something that was badly-formed.)
+ * INTERFACE:
+ * parameters: char*: name
+ * boolean: slash_okay
+ *
+ * returns: char* field name or NULL
+ *=======================================================================*/
+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;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: skip_over_field_signature
+ * OVERVIEW: Skips over the longest part of the string that could be
+ * taken as a field signature given a pointer to a string.
+ * Allows "void" if void_okay parameter is true.
+ * Returns a pointer to just past the signature.
+ * Returns NULL if no legal signature is found.
+ * INTERFACE:
+ * parameters: char*: name
+ * boolean: void_okay
+ *
+ * returns: char* field signature or NULL
+ *=======================================================================*/
+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_LONG:
+ return name + 1;
+
+ case SIGNATURE_FLOAT:
+ case SIGNATURE_DOUBLE:
+ return no_floating_point ? NULL : 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 NULL;
+ }
+
+ case SIGNATURE_ARRAY:
+ /* The rest of what's there better be a legal signature. */
+ name++;
+ void_okay = FALSE;
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: CCerror
+ * OVERVIEW: Handles formating errors found during class file
+ * verification.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ * char *: format
+ *
+ * returns: nothing
+ *=======================================================================*/
+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");
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: IsLegalClassname
+ * OVERVIEW: Determines if the specified name is a legal UTF name for
+ * a class name.
+ * Note that this routine is intended for external use and
+ * expects the internal form of qualified classes
+ * (i.e. the dots should have been replaced by slashes.)
+ * INTERFACE:
+ * parameters: char*: name
+ * boolean: allowArrayClass
+ *
+ * returns: boolean type
+ *=======================================================================*/
+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');
+}
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/check_code.c b/MPC.3.5.LINUX/preverifier/check_code.c
--- /dev/null
@@ -0,0 +1,3970 @@
+/*
+ * @(#)check_code.c 1.26 02/09/27
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Verifies codes within a method block.
+ * FILE: check_code.c
+ * OVERVIEW: Verifies that the code within a method block does not
+ * exploit any security holes.
+ * AUTHOR: Sheng Liang, Consumer & Embedded
+ * Initial implementation based on the Classic VM Verifier.
+ * Edited by Tasneem Sayeed, Java Consumer Technologies
+ *=======================================================================*/
+
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include "check_code.h"
+
+#include "opcodes.length"
+#include "opcodes.in_out"
+
+//#include "winsock2.h"
+#define ntohl(x) (x)
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+#ifdef DEBUG_VERIFIER
+ int verify_verbose = 0;
+ static struct context_type *GlobalContext;
+#endif
+
+void rewriteCode(context_type *vcontext, struct methodblock *mb);
+static void verify_method(context_type *context, struct methodblock *mb);
+static void verify_field(context_type *context, struct fieldblock *fb);
+
+static void verify_opcode_operands (context_type *, int inumber, int offset);
+static void set_protected(context_type *, int inumber, int key, opcode_type);
+static bool_t isSuperClass(context_type *, fullinfo_type);
+
+static void initialize_exception_table(context_type *);
+static int instruction_length(unsigned char *iptr);
+static bool_t isLegalTarget(context_type *, int offset);
+static void verify_constant_pool_type(context_type *, int, unsigned);
+
+static void initialize_dataflow(context_type *);
+static void run_dataflow(context_type *context);
+static void check_register_values(context_type *context, int inumber);
+static void check_flags(context_type *context, int inumber);
+static void pop_stack(context_type *, int inumber, stack_info_type *);
+static void update_registers(context_type *, int inumber, register_info_type *);
+static void update_flags(context_type *, int inumber,
+ flag_type *new_and_flags, flag_type *new_or_flags);
+static void push_stack(context_type *, int inumber, stack_info_type *stack);
+
+static void merge_into_successors(context_type *, int inumber,
+ register_info_type *register_info,
+ stack_info_type *stack_info,
+ flag_type and_flags, flag_type or_flags);
+static void merge_into_one_successor(context_type *context,
+ int from_inumber, int inumber,
+ register_info_type *register_info,
+ stack_info_type *stack_info,
+ flag_type and_flags, flag_type or_flags,
+ bool_t isException);
+static void merge_stack(context_type *, int inumber, int to_inumber,
+ stack_info_type *);
+static void merge_registers(context_type *, int inumber, int to_inumber,
+ register_info_type *);
+static void merge_flags(context_type *context, int from_inumber, int to_inumber,
+ flag_type new_and_flags, flag_type new_or_flags);
+
+static stack_item_type *copy_stack(context_type *, stack_item_type *);
+static mask_type *copy_masks(context_type *, mask_type *masks, int mask_count);
+static mask_type *add_to_masks(context_type *, mask_type *, int , int);
+
+static fullinfo_type decrement_indirection(fullinfo_type);
+
+static fullinfo_type merge_fullinfo_types(context_type *context,
+ fullinfo_type a, fullinfo_type b,
+ bool_t assignment);
+static bool_t isAssignableTo(context_type *,fullinfo_type a, fullinfo_type b);
+
+static ClassClass *object_fullinfo_to_classclass(context_type *, fullinfo_type);
+
+
+#define NEW(type, count) \
+ ((type *)CCalloc(context, (count)*(sizeof(type)), FALSE))
+#define ZNEW(type, count) \
+ ((type *)CCalloc(context, (count)*(sizeof(type)), TRUE))
+
+static void CCinit(context_type *context);
+static void CCreinit(context_type *context);
+static void CCdestroy(context_type *context);
+static void *CCalloc(context_type *context, int size, bool_t zero);
+
+static char *cp_index_to_fieldname(context_type *context, int cp_index);
+static char *cp_index_to_signature(context_type *context, int cp_index);
+static fullinfo_type cp_index_to_class_fullinfo(context_type *, int, bool_t);
+
+static char signature_to_fieldtype(context_type *context,
+ char **signature_p, fullinfo_type *info);
+
+static void CCerror (context_type *, char *format, ...);
+
+#ifdef DEBUG_VERIFIER
+static void print_stack (context_type *, stack_info_type *stack_info);
+static void print_registers(context_type *, register_info_type *register_info);
+static void print_flags(context_type *, flag_type, flag_type);
+static void print_formatted_fieldname(context_type *context, int index);
+#endif
+
+
+/*
+ * Access local hash tables without locking. This extra level
+ * of naming is intended to emphasize the fact that locks are
+ * not held and also to do error handling. Although it is not
+ * strictly necessary, one should always use the "_Local"
+ * versions of these functions on the verifier's local hash
+ * tables.
+ */
+#define Str2IDFree_Local(localHashRoot) Str2IDFree(localHashRoot)
+
+
+/*=========================================================================
+ * FUNCTION: Str2ID_Local
+ * OVERVIEW: Access local hash tables without locking
+ * This extra level of naming is intended to emphasize the
+ * fact that locks are not held and also to do error handling.
+ * These functions could all be macros like Str2IDFree_Local(),
+ * except that Str2ID() and ID2Str() can run out of memory,
+ * and the code in this file makes it inconvenient to check
+ * for that. As an expedient, rather than throwing exceptions,
+ * Str2ID_Local() is a function that calls CCerror() if
+ * necessary.
+ * Returns the index given the string which corresponds to the
+ * hash table entry.
+ * INTERFACE:
+ * parameters: context_type *: context
+ * struct StrIDhash **: hash_ptr
+ * char *: s
+ * void ***: param
+ * int: Copy
+ *
+ * returns: unsigned short
+ *=======================================================================*/
+unsigned short
+Str2ID_Local(context_type *context, struct StrIDhash **hash_ptr, char *s,
+ void ***param, int Copy) {
+ unsigned short ret;
+ if ((ret = Str2ID(hash_ptr, s, param, Copy)) == 0) {
+// CCerror(context, "Out of memory");
+ }
+
+ return ret;
+}
+
+
+/*=========================================================================
+ * FUNCTION: ID2Str_Local
+ * OVERVIEW: Access local hash tables without locking
+ * This extra level of naming is intended to emphasize the
+ * fact that locks are not held and also to do error handling.
+ * These functions could all be macros like Str2IDFree_Local(),
+ * except that Str2ID() and ID2Str() can run out of memory,
+ * and the code in this file makes it inconvenient to check
+ * for that. As an expedient, rather than throwing exceptions,
+ * ID2Str_Local() is a function that calls CCerror() if
+ * necessary.
+ * Returns the string given the index which corresponds to the
+ * hash table entry.
+ * INTERFACE:
+ * parameters: context_type *: context
+ * struct StrIDhash *: h
+ * unsigned short: ID
+ * void ***: param
+ *
+ * returns: char *
+ *=======================================================================*/
+char *
+ID2Str_Local(context_type *context, struct StrIDhash *h, unsigned short ID,
+ void ***param) {
+ char *ret;
+ if ((ret = ID2Str(h, ID, param)) == 0) {
+// CCerror(context, "Out of memory");
+ }
+
+ return ret;
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_class_codes
+ * OVERVIEW: Verifies the code for each of the methods in a class.
+ * Invoked by verify_class().
+ * Returns true if the class codes are ok.
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ *
+ * returns: boolean type
+ *=======================================================================*/
+bool_t verify_class_codes(ClassClass *cb) {
+ context_type context_structure;
+ context_type *context = &context_structure;
+ bool_t result = TRUE;
+ void **addr;
+ int i;
+
+#ifdef DEBUG_VERIFIER
+ GlobalContext = context;
+#endif
+
+ /* Initialize the class-wide fields of the context. */
+ context->class = cb;
+
+ context->classHash = 0;
+ /* Zero method block field of the context, in case anyone calls CCerrror */
+ context->mb = 0;
+ context->superClasses = NULL; /* filled in later */
+
+ /* Don't call CCerror or anything that can call it above the setjmp! */
+ if (!setjmp(context->jump_buffer)) {
+ struct methodblock *mb;
+ struct fieldblock *fb;
+
+ CCinit(context); /* initialize heap; may throw */
+
+ context->object_info =
+ MAKE_CLASSNAME_INFO(context, JAVAPKG "Object", &addr);
+ *addr = classJavaLangObject;
+ context->string_info =
+ MAKE_CLASSNAME_INFO(context, JAVAPKG "String", &addr);
+ *addr = classJavaLangString;
+ context->throwable_info =
+ MAKE_CLASSNAME_INFO(context, JAVAPKG "Throwable", &addr);
+ *addr = classJavaLangThrowable;
+ context->currentclass_info =
+ MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), &addr);
+ *addr = cb;
+ if (cbSuperclass(cb) != 0) {
+ ClassClass *super = cbSuperclass(cb);
+ context->superclass_info =
+ MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(super), &addr);
+ *addr = super;
+ } else {
+ context->superclass_info = 0;
+ }
+
+ /* Look at each method */
+ for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++)
+ verify_field(context, fb);
+
+ unhand(context->class)->new_class_entries =
+ (char **)malloc((cbConstantPoolCount(context->class) * 3 + 100) * sizeof(char *));
+ unhand(context->class)->n_new_class_entries = 0;
+
+ for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++)
+ verify_method(context, mb);
+
+ unhand(context->class)->new_class_entries =
+ (char **)realloc(unhand(context->class)->new_class_entries,
+ unhand(context->class)->n_new_class_entries * sizeof(char *));
+
+ result = TRUE;
+ } else {
+ result = FALSE;
+ }
+
+ /* Cleanup */
+ Str2IDFree_Local(&context->classHash);
+
+#ifdef DEBUG_VERIFIER
+ GlobalContext = 0;
+#endif
+
+ if (context->superClasses != NULL) {
+ sysFree(context->superClasses);
+ }
+ CCdestroy(context); /* destroy heap */
+ return result;
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_field
+ * OVERVIEW: Verifies the field block within each method of a class
+ * file.
+ * Invoked by verify_class_codes().
+ * Returns true if the field block is ok.
+ * INTERFACE:
+ * parameters: pointer to the context_type structure.
+ * pointer to the field block
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static void
+verify_field(context_type *context, struct fieldblock *fb)
+{
+ int access_bits = fb->access;
+
+ if ( ((access_bits & ACC_PUBLIC) != 0) &&
+ ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) {
+ if (verbose) {
+ // jio_fprintf(stderr, "VERIFIER ERROR %s.%s:\n",
+ // cbName(fieldclass(fb)), fb->name);
+ // jio_fprintf(stderr, "Inconsistent access bits.");
+ }
+ longjmp(context->jump_buffer, 1);
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: get_type_name
+ * OVERVIEW: Retrieves the type name information given the item type.
+ * Used by get_type_code() which is invoked by verify_method()
+ * to retrieve the type code for the stack map entries.
+ * INTERFACE:
+ * parameters: pointer to the context_type structure.
+ * fullinfo_type: type
+ * char *: buf
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+get_type_name(context_type *context, fullinfo_type type, char *buf)
+{
+ int i;
+ int indirection = GET_INDIRECTION(type);
+ for (i = indirection; i-- > 0; )
+ *buf++ = '[';
+ switch (GET_ITEM_TYPE(type)) {
+ case ITEM_Integer:
+ *buf++ = 'I'; break;
+ case ITEM_Float:
+ *buf++ = 'F'; break;
+ case ITEM_Double:
+ *buf++ = 'D'; break;
+ case ITEM_Long:
+ *buf++ = 'J'; break;
+ case ITEM_Char:
+ *buf++ = 'C'; break;
+ case ITEM_Short:
+ *buf++ = 'S'; break;
+ case ITEM_Byte:
+ *buf++ = 'B'; break;
+ case ITEM_Boolean:
+ *buf++ = 'Z'; break;
+ case ITEM_Object: {
+ unsigned short extra = GET_EXTRA_INFO(type);
+ if (indirection) *buf++ = 'L';
+ if (extra == 0) {
+// panic("unexpected");
+ } else {
+ char *name = ID2Str_Local(context, context->classHash,
+ extra, 0);
+ strcpy(buf, name);
+ if (indirection) strcat(buf, ";");
+ }
+ return;
+ }
+ // default:
+ // panic("bad type");
+ }
+ *buf = '\0';
+}
+
+
+/*=========================================================================
+ * FUNCTION: check_class_constant
+ * OVERVIEW: Checks and returns the index corresponding to the given
+ * UTF8 constant entry within the constant pool.
+ * Returns -1 if none was found.
+ * Invoked by get_type_code().
+ * INTERFACE:
+ * parameters: pointer to the ClassClass structure.
+ * char *: utf8
+ *
+ * returns: long type
+ *=======================================================================*/
+long check_class_constant(ClassClass *cb, char *utf8)
+{
+ int i;
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ for (i = 0; i < cbConstantPoolCount(cb); i++) {
+ if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) &&
+ strcmp(utf8, cbName(constant_pool[i].clazz)) == 0) {
+ return i;
+ }
+ if (type_table[i] == CONSTANT_Class &&
+ strcmp(utf8, constant_pool[constant_pool[i].i].cp) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/*=========================================================================
+ * FUNCTION: get_type_code
+ * OVERVIEW: Retrieves the type code entry given the item type.
+ * Invoked by verify_method() to retrieve the type code
+ * for the stack map entries.
+ * INTERFACE:
+ * parameters: pointer to the context_type structure.
+ * fullinfo_type: type
+ *
+ * returns: struct map_entry
+ *=======================================================================*/
+struct map_entry get_type_code(context_type *context, fullinfo_type type)
+{
+ struct map_entry result = {0,0};
+ switch (type) {
+ case ITEM_Double_2:
+ case ITEM_Long_2:
+ case ITEM_Bogus:
+ result.type = CF_ITEM_Bogus;
+ return result;
+ case ITEM_Integer:
+ result.type = CF_ITEM_Integer;
+ return result;
+ case ITEM_Float:
+ result.type = CF_ITEM_Float;
+ return result;
+ case ITEM_Double:
+ result.type = CF_ITEM_Double;
+ return result;
+ case ITEM_Long:
+ result.type = CF_ITEM_Long;
+ return result;
+ case ITEM_InitObject:
+ result.type = CF_ITEM_InitObject;
+ return result;
+ default:
+ if (GET_ITEM_TYPE(type) == ITEM_NewObject) {
+ int inum = GET_EXTRA_INFO(type);
+ result.type = CF_ITEM_NewObject;
+ result.info = context->instruction_data[inum].offset;
+ return result;
+ } else if (GET_ITEM_TYPE(type) == ITEM_Object && GET_EXTRA_INFO(type) == 0) {
+ result.type = CF_ITEM_Null;
+ return result;
+ } else if (GET_ITEM_TYPE(type) == ITEM_Object || GET_INDIRECTION(type) > 0) {
+ char type_name[1024];
+ int i;
+ result.type = CF_ITEM_Object;
+ get_type_name(context, type, type_name);
+ i = check_class_constant(context->class, type_name);
+ if (i >= 0) {
+ result.info = i;
+ return result;
+ }
+ for (i = 0; i < unhand(context->class)->n_new_class_entries; i++) {
+ if (strcmp(type_name, unhand(context->class)->new_class_entries[i]) == 0) {
+ result.info = ~i;
+ return result;
+ }
+ }
+ {
+ int entries = unhand(context->class)->n_new_class_entries;
+ unhand(context->class)->new_class_entries[entries] = strdup(type_name);
+ result.info = ~entries;
+ unhand(context->class)->n_new_class_entries = entries + 1;
+ return result;
+ }
+ } else {
+ // panic("bad type code");
+ return result; /* not reached */
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_method
+ * OVERVIEW: Verifies the code for one method within a class file.
+ * Invoked by verify_class_codes().
+ * INTERFACE:
+ * parameters: pointer to the context_type structure.
+ * struct methodblock*: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+verify_method(context_type *context, struct methodblock *mb)
+{
+ int access_bits = mb->fb.access;
+ unsigned char *code;
+ int code_length;
+ short *code_data;
+ instruction_data_type *idata = 0;
+ int instruction_count;
+ int i, offset, inumber;
+ int exception_count;
+ int n_stack_maps, dead_count, jsr_count;
+
+ again:
+ code = mb->code;
+ code_length = mb->code_length;
+
+ /* CCerror can give method-specific info once this is set */
+ context->mb = mb;
+
+ CCreinit(context); /* initial heap */
+ code_data = NEW(short, code_length);
+
+#ifdef DEBUG_VERIFIER
+// if (verify_verbose) {
+// jio_fprintf(stdout, "Looking at %s.%s%s 0x%x\n",
+// cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature,
+// (long)mb);
+// }
+#endif
+
+ if (((access_bits & ACC_PUBLIC) != 0) &&
+ ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) {
+// CCerror(context, "Inconsistent access bits.");
+ }
+
+ if ((access_bits & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ /* not much to do for abstract or native methods */
+ return;
+ }
+
+ if (code_length >= 65535) {
+// CCerror(context, "Code of a method longer than 65535 bytes");
+ }
+
+ /* Run through the code. Mark the start of each instruction, and give
+ * the instruction a number */
+ for (i = 0, offset = 0; offset < code_length; i++) {
+ int length = instruction_length(&code[offset]);
+ int next_offset = offset + length;
+// if (length <= 0)
+// CCerror(context, "Illegal instruction found at offset %d", offset);
+// if (next_offset > code_length)
+// CCerror(context, "Code stops in the middle of instruction "
+// " starting at offset %d", offset);
+ code_data[offset] = i;
+ while (++offset < next_offset)
+ code_data[offset] = -1; /* illegal location */
+ }
+ instruction_count = i; /* number of instructions in code */
+
+ /* Allocate a structure to hold info about each instruction. */
+ idata = NEW(instruction_data_type, instruction_count);
+
+ /* Initialize the heap, and other info in the context structure. */
+ context->code = code;
+ context->instruction_data = idata;
+ context->code_data = code_data;
+ context->instruction_count = instruction_count;
+ context->handler_info = NEW(struct handler_info_type,
+ mb->exception_table_length);
+ context->bitmask_size = (mb->nlocals + (BITS_PER_INT - 1))/BITS_PER_INT;
+
+// if (instruction_count == 0)
+// CCerror(context, "Empty code");
+
+ for (inumber = 0, offset = 0; offset < code_length; inumber++) {
+ int length = instruction_length(&code[offset]);
+ instruction_data_type *this_idata = &idata[inumber];
+ this_idata->opcode = code[offset];
+ this_idata->offset = offset;
+ this_idata->length = length;
+ this_idata->stack_info.stack = NULL;
+ this_idata->stack_info.stack_size = UNKNOWN_STACK_SIZE;
+ this_idata->register_info.register_count = UNKNOWN_REGISTER_COUNT;
+ this_idata->changed = FALSE; /* no need to look at it yet. */
+ this_idata->protected = FALSE; /* no need to look at it yet. */
+ /* Added for inlinejsr */
+ this_idata->is_target = FALSE; /* no need to look at it yet. */
+ this_idata->and_flags = (flag_type) -1; /* "bottom" and value */
+ this_idata->or_flags = 0; /* "bottom" or value*/
+
+ /* This also sets up this_data->operand. It also makes the
+ * xload_x and xstore_x instructions look like the generic form. */
+ verify_opcode_operands(context, inumber, offset);
+ offset += length;
+ }
+
+
+ /* make sure exception table is reasonable. */
+ initialize_exception_table(context);
+ /* Set up first instruction, and start of exception handlers. */
+ initialize_dataflow(context);
+ /* Run data flow analysis on the instructions. */
+ context->redoJsr = FALSE;
+ run_dataflow(context);
+
+ for (inumber = 0; inumber < instruction_count; inumber++) {
+ instruction_data_type *this_idata = &idata[inumber];
+ if ( (this_idata->or_flags & FLAG_REACHED) &&
+ ((this_idata->opcode == opc_jsr) ||
+ (this_idata->opcode == opc_jsr_w)) &&
+ (this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION)) {
+ this_idata->changed = TRUE;
+ context->redoJsr = TRUE;
+ }
+ }
+ if (context->redoJsr) {
+ run_dataflow(context);
+ }
+
+
+ /* verify checked exceptions, if any */
+ if ((exception_count = mb->nexceptions) > 0) {
+ unsigned short *exceptions = mb->exceptions;
+ for (i = 0; i < (int)exception_count; i++) {
+ /* Make sure the constant pool item is CONSTANT_Class */
+ verify_constant_pool_type(context, (int)exceptions[i],
+ 1 << CONSTANT_Class);
+ }
+ }
+
+
+ dead_count = jsr_count = 0;
+ for (inumber = 0; inumber < instruction_count; inumber++) {
+ instruction_data_type *this_idata = &idata[inumber];
+ if ((this_idata->or_flags & FLAG_REACHED) == 0) {
+ dead_count++;
+ } else if (this_idata->opcode == opc_jsr ||
+ this_idata->opcode == opc_jsr_w) {
+ jsr_count++;
+ }
+ }
+ if (dead_count > 0 || jsr_count > 0) {
+ rewriteCode(context, mb);
+ goto again;
+ }
+
+ n_stack_maps = 0;
+ for (inumber = 0; inumber < instruction_count; inumber++) {
+ instruction_data_type *this_idata = &idata[inumber];
+ if (this_idata->is_target) {
+ n_stack_maps++;
+ }
+ }
+
+ mb->n_stack_maps = n_stack_maps;
+ mb->stack_maps =
+ (struct stack_map *)malloc(n_stack_maps * sizeof(struct stack_map));
+
+ n_stack_maps = 0;
+ for (inumber = 0; inumber < instruction_count; inumber++) {
+ instruction_data_type *this_idata = &idata[inumber];
+ if (this_idata->is_target) {
+ struct stack_info_type *stack_info = &this_idata->stack_info;
+ struct register_info_type *register_info = &this_idata->register_info;
+ int register_count = register_info->register_count;
+ struct stack_item_type *stack;
+ struct map_entry *new_entries;
+ int index, index2;
+
+
+ /* We may be allocating too big a structure if there are longs
+ * or doubles on the stack, but that's okay */
+ new_entries = (struct map_entry *)malloc(register_count * sizeof(struct map_entry));
+
+ for (index2 = 0, index = 0; index < register_count; index++) {
+ fullinfo_type info = register_info->registers[index];
+ if (info == ITEM_Double || info == ITEM_Long) {
+ if (index + 1 < register_count &&
+ register_info->registers[index + 1] == info+1) {
+ new_entries[index2++] = get_type_code(context, info);
+ index++;
+ } else {
+ new_entries[index2++] = get_type_code(context, ITEM_Bogus);
+ }
+ } else {
+ new_entries[index2++] = get_type_code(context, info);
+ }
+ }
+ mb->stack_maps[n_stack_maps].offset = this_idata->offset;
+ mb->stack_maps[n_stack_maps].locals = new_entries;
+ mb->stack_maps[n_stack_maps].nlocals = index2;
+
+
+ mb->stack_maps[n_stack_maps].nstacks = 0;
+ for (stack = stack_info->stack; stack; stack = stack->next) {
+ mb->stack_maps[n_stack_maps].nstacks++;
+ }
+ new_entries = (struct map_entry *)malloc(mb->stack_maps[n_stack_maps].nstacks * sizeof(struct map_entry));
+ index = 0;
+ for (stack = stack_info->stack; stack; stack = stack->next) {
+ new_entries[mb->stack_maps[n_stack_maps].nstacks - (++index)] =
+ get_type_code(context, stack->item);
+ }
+ mb->stack_maps[n_stack_maps].stacks = new_entries;
+
+ unhand(context->class)->has_stack_maps = 1;
+ n_stack_maps++;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_opcode_operands
+ * OVERVIEW: Verifies the operands of a single instruction given an
+ * instruction number and an offset.
+ * Also, for simplicity, move the operand into the ->operand
+ * field.
+ * Make sure that branches do not go into the middle
+ * of nowhere.
+ * Invoked by verify_method().
+ * INTERFACE:
+ * parameters: context_type *: context
+ * int: inumber
+ * int: offset
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+verify_opcode_operands(context_type *context, int inumber, int offset)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ short *code_data = context->code_data;
+ struct methodblock *mb = context->mb;
+ unsigned char *code = context->code;
+ opcode_type opcode = this_idata->opcode;
+ int var;
+
+ this_idata->operand.i = 0;
+ this_idata->operand2.i = 0;
+
+ switch (opcode) {
+
+ case opc_jsr:
+ /* instruction of ret statement */
+ this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION;
+ /* FALLTHROUGH */
+ case opc_ifeq: case opc_ifne: case opc_iflt:
+ case opc_ifge: case opc_ifgt: case opc_ifle:
+ case opc_ifnull: case opc_ifnonnull:
+ case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt:
+ case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple:
+ case opc_if_acmpeq: case opc_if_acmpne:
+ case opc_goto: {
+ /* Set the ->operand to be the instruction number of the target. */
+ int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];
+ int target = offset + jump;
+// if (!isLegalTarget(context, target))
+// CCerror(context, "Illegal target of jump or branch");
+ this_idata->operand.i = code_data[target];
+ break;
+ }
+
+ case opc_jsr_w:
+ /* instruction of ret statement */
+ this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION;
+ /* FALLTHROUGH */
+ case opc_goto_w: {
+ /* Set the ->operand to be the instruction number of the target. */
+ int jump = (((signed char)(code[offset+1])) << 24) +
+ (code[offset+2] << 16) + (code[offset+3] << 8) +
+ (code[offset + 4]);
+ int target = offset + jump;
+// if (!isLegalTarget(context, target))
+// CCerror(context, "Illegal target of jump or branch");
+ this_idata->operand.i = code_data[target];
+ break;
+ }
+
+ case opc_tableswitch:
+ case opc_lookupswitch: {
+ /* Set the ->operand to be a table of possible instruction targets. */
+ long *lpc = (long *) UCALIGN(code + offset + 1);
+ long *lptr;
+ int *saved_operand;
+ int keys;
+ int k, delta;
+ if (opcode == opc_tableswitch) {
+ keys = ntohl(lpc[2]) - ntohl(lpc[1]) + 1;
+ delta = 1;
+ } else {
+ keys = ntohl(lpc[1]); /* number of pairs */
+ delta = 2;
+ /* Make sure that the tableswitch items are sorted */
+ for (k = keys - 1, lptr = &lpc[2]; --k >= 0; lptr += 2) {
+ long this_key = ntohl(lptr[0]); /* NB: ntohl may be unsigned */
+ long next_key = ntohl(lptr[2]);
+// if (this_key >= next_key) {
+// CCerror(context, "Unsorted lookup switch");
+// }
+ }
+ }
+ /* This code has been changed for inlining. We know have the keys
+ * in the same order that they occur in the code, with the default
+ * key being the first one.
+ */
+ saved_operand = NEW(int, keys + 2);
+// if (!isLegalTarget(context, offset + ntohl(lpc[0])))
+// CCerror(context, "Illegal default target in switch");
+
+ saved_operand[0] = keys + 1; /* number of successors */
+ saved_operand[1] = code_data[offset + ntohl(lpc[0])]; /* default */
+
+ for (k = 0, lptr = &lpc[3]; k < keys; lptr += delta, k++) {
+ int target = offset + ntohl(lptr[0]);
+ // if (!isLegalTarget(context, target))
+ // CCerror(context, "Illegal branch in opc_tableswitch");
+ saved_operand[k + 2] = code_data[target];
+ }
+ this_idata->operand.ip = saved_operand;
+ break;
+ }
+
+ case opc_ldc: {
+ /* Make sure the constant pool item is the right type. */
+ int key = code[offset + 1];
+ int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) |
+ (1 << CONSTANT_String);
+ this_idata->operand.i = key;
+ verify_constant_pool_type(context, key, types);
+ break;
+ }
+
+ case opc_ldc_w: {
+ /* Make sure the constant pool item is the right type. */
+ int key = (code[offset + 1] << 8) + code[offset + 2];
+ int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) |
+ (1 << CONSTANT_String);
+ this_idata->operand.i = key;
+ verify_constant_pool_type(context, key, types);
+ break;
+ }
+
+ case opc_ldc2_w: {
+ /* Make sure the constant pool item is the right type. */
+ int key = (code[offset + 1] << 8) + code[offset + 2];
+ int types = (1 << CONSTANT_Double) | (1 << CONSTANT_Long);
+ this_idata->operand.i = key;
+ verify_constant_pool_type(context, key, types);
+ break;
+ }
+
+ case opc_getfield: case opc_putfield:
+ case opc_getstatic: case opc_putstatic: {
+ /* Make sure the constant pool item is the right type. */
+ int key = (code[offset + 1] << 8) + code[offset + 2];
+ this_idata->operand.i = key;
+ verify_constant_pool_type(context, key, 1 << CONSTANT_Fieldref);
+ if (opcode == opc_getfield || opcode == opc_putfield)
+ set_protected(context, inumber, key, opcode);
+ break;
+ }
+
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ case opc_invokeinterface: {
+ /* Make sure the constant pool item is the right type. */
+ int key = (code[offset + 1] << 8) + code[offset + 2];
+ char *methodname;
+ fullinfo_type clazz_info;
+ int kind = (opcode == opc_invokeinterface
+ ? 1 << CONSTANT_InterfaceMethodref
+ : 1 << CONSTANT_Methodref);
+ /* Make sure the constant pool item is the right type. */
+ verify_constant_pool_type(context, key, kind);
+ methodname = cp_index_to_fieldname(context, key);
+ clazz_info = cp_index_to_class_fullinfo(context, key, TRUE);
+ this_idata->operand.i = key;
+ this_idata->operand2.fi = clazz_info;
+ if (strcmp(methodname, "<init>") == 0) {
+// if (opcode != opc_invokespecial)
+// CCerror(context,
+// "Must call initializers using invokespecial");
+ this_idata->opcode = opc_invokeinit;
+ } else {
+// if (methodname[0] == '<')
+// CCerror(context, "Illegal call to internal method");
+ if (opcode == opc_invokespecial
+ && clazz_info != context->currentclass_info
+ && clazz_info != context->superclass_info) {
+ ClassClass *cb = context->class;
+ for (; ; cb = cbSuperclass(cb)) {
+ if (clazz_info == MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), 0))
+ break;
+ /* The optimizer make cause this to happen on local code */
+ if (cbSuperclass(cb) == 0) {
+ /* optimizer make cause this to happen on local code */
+ // if (cbLoader(cb) != 0)
+ // CCerror(context,
+ // "Illegal use of nonvirtual function call");
+ break;
+ }
+ }
+ }
+ }
+ if (opcode == opc_invokeinterface) {
+ char *signature = cp_index_to_signature(context, key);
+ unsigned int args1 = Signature2ArgsSize(signature) + 1;
+ unsigned int args2 = code[offset + 3];
+ if (args1 != args2) {
+ // CCerror(context,
+ // "Inconsistent args_size for opc_invokeinterface");
+ }
+ if (code[offset + 4] != 0) {
+ // CCerror(context,
+ // "Fourth operand byte of invokeinterface must be zero");
+ }
+ } else if (opcode == opc_invokevirtual
+ || opcode == opc_invokespecial)
+ set_protected(context, inumber, key, opcode);
+ break;
+ }
+
+
+ case opc_instanceof:
+ case opc_checkcast:
+ case opc_new:
+ case opc_anewarray:
+ case opc_multianewarray: {
+ /* Make sure the constant pool item is a class */
+ int key = (code[offset + 1] << 8) + code[offset + 2];
+ fullinfo_type target;
+ verify_constant_pool_type(context, key, 1 << CONSTANT_Class);
+ target = cp_index_to_class_fullinfo(context, key, FALSE);
+// if (GET_ITEM_TYPE(target) == ITEM_Bogus)
+// CCerror(context, "Illegal type");
+ switch(opcode) {
+ case opc_anewarray:
+ if ((GET_INDIRECTION(target)) >= MAX_ARRAY_DIMENSIONS)
+ CCerror(context, "Array with too many dimensions");
+ this_idata->operand.fi = MAKE_FULLINFO(GET_ITEM_TYPE(target),
+ GET_INDIRECTION(target) + 1,
+ GET_EXTRA_INFO(target));
+ break;
+ case opc_new:
+// if (WITH_ZERO_EXTRA_INFO(target) !=
+// MAKE_FULLINFO(ITEM_Object, 0, 0))
+// CCerror(context, "Illegal creation of multi-dimensional array");
+ /* operand gets set to the "unitialized object". operand2 gets
+ * set to what the value will be after it's initialized. */
+ this_idata->operand.fi = MAKE_FULLINFO(ITEM_NewObject, 0, inumber);
+ this_idata->operand2.fi = target;
+ break;
+ case opc_multianewarray:
+ this_idata->operand.fi = target;
+ this_idata->operand2.i = code[offset + 3];
+ // if ( (this_idata->operand2.i > (int)GET_INDIRECTION(target))
+ // || (this_idata->operand2.i == 0))
+ // CCerror(context, "Illegal dimension argument");
+ break;
+ default:
+ this_idata->operand.fi = target;
+ }
+ break;
+ }
+
+ case opc_newarray: {
+ /* Cache the result of the opc_newarray into the operand slot */
+ fullinfo_type full_info;
+ switch (code[offset + 1]) {
+ case T_INT:
+ full_info = MAKE_FULLINFO(ITEM_Integer, 1, 0); break;
+ case T_LONG:
+ full_info = MAKE_FULLINFO(ITEM_Long, 1, 0); break;
+ case T_FLOAT:
+ full_info = MAKE_FULLINFO(ITEM_Float, 1, 0); break;
+ case T_DOUBLE:
+ full_info = MAKE_FULLINFO(ITEM_Double, 1, 0); break;
+ case T_BYTE:
+ full_info = MAKE_FULLINFO(ITEM_Byte, 1, 0); break;
+ case T_BOOLEAN:
+ full_info = MAKE_FULLINFO(ITEM_Boolean, 1, 0); break;
+ case T_CHAR:
+ full_info = MAKE_FULLINFO(ITEM_Char, 1, 0); break;
+ case T_SHORT:
+ full_info = MAKE_FULLINFO(ITEM_Short, 1, 0); break;
+ default:
+ full_info = 0; /* make GCC happy */
+ // CCerror(context, "Bad type passed to opc_newarray");
+ }
+ this_idata->operand.fi = full_info;
+ break;
+ }
+
+ /* Fudge iload_x, aload_x, etc to look like their generic cousin. */
+ case opc_iload_0: case opc_iload_1: case opc_iload_2: case opc_iload_3:
+ this_idata->opcode = opc_iload;
+ var = opcode - opc_iload_0;
+ goto check_local_variable;
+
+ case opc_fload_0: case opc_fload_1: case opc_fload_2: case opc_fload_3:
+ this_idata->opcode = opc_fload;
+ var = opcode - opc_fload_0;
+ goto check_local_variable;
+
+ case opc_aload_0: case opc_aload_1: case opc_aload_2: case opc_aload_3:
+ this_idata->opcode = opc_aload;
+ var = opcode - opc_aload_0;
+ goto check_local_variable;
+
+ case opc_lload_0: case opc_lload_1: case opc_lload_2: case opc_lload_3:
+ this_idata->opcode = opc_lload;
+ var = opcode - opc_lload_0;
+ goto check_local_variable2;
+
+ case opc_dload_0: case opc_dload_1: case opc_dload_2: case opc_dload_3:
+ this_idata->opcode = opc_dload;
+ var = opcode - opc_dload_0;
+ goto check_local_variable2;
+
+ case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3:
+ this_idata->opcode = opc_istore;
+ var = opcode - opc_istore_0;
+ goto check_local_variable;
+
+ case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3:
+ this_idata->opcode = opc_fstore;
+ var = opcode - opc_fstore_0;
+ goto check_local_variable;
+
+ case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3:
+ this_idata->opcode = opc_astore;
+ var = opcode - opc_astore_0;
+ goto check_local_variable;
+
+ case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3:
+ this_idata->opcode = opc_lstore;
+ var = opcode - opc_lstore_0;
+ goto check_local_variable2;
+
+ case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3:
+ this_idata->opcode = opc_dstore;
+ var = opcode - opc_dstore_0;
+ goto check_local_variable2;
+
+ case opc_wide:
+ this_idata->opcode = code[offset + 1];
+ var = (code[offset + 2] << 8) + code[offset + 3];
+ switch(this_idata->opcode) {
+ case opc_lload: case opc_dload:
+ case opc_lstore: case opc_dstore:
+ goto check_local_variable2;
+ default:
+ goto check_local_variable;
+ }
+
+ case opc_iinc: /* the increment amount doesn't matter */
+ case opc_ret:
+ case opc_aload: case opc_iload: case opc_fload:
+ case opc_astore: case opc_istore: case opc_fstore:
+ var = code[offset + 1];
+ check_local_variable:
+ /* Make sure that the variable number isn't illegal. */
+ this_idata->operand.i = var;
+// if (var >= (int)mb->nlocals)
+// CCerror(context, "Illegal local variable number");
+ break;
+
+ case opc_lload: case opc_dload: case opc_lstore: case opc_dstore:
+ var = code[offset + 1];
+ check_local_variable2:
+ /* Make sure that the variable number isn't illegal. */
+ this_idata->operand.i = var;
+// if ((var + 1) >= (int)mb->nlocals)
+// CCerror(context, "Illegal local variable number");
+ break;
+
+ // default:
+// if (opcode >= opc_breakpoint)
+// CCerror(context, "Quick instructions shouldn't appear yet.");
+ break;
+ } /* of switch */
+}
+
+
+/*=========================================================================
+ * FUNCTION: set_protected
+ * OVERVIEW: Checks the field access to see if the instruction is
+ * protected, is private and is in the same class package,
+ * then the protected bit for the given instruction is set.
+ * Invoked by verify_operands_opcodes() to set protected bit
+ * for instructions of the following opcode types:
+ * opc_getfield, opc_putfield, and opc_invokevirtual.
+ * INTERFACE:
+ * parameters: context_type *: context
+ * int: instruction number
+ * int: key
+ * opcode_type: opcode
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+set_protected(context_type *context, int inumber, int key, opcode_type opcode)
+{
+ /* fullinfo_type clazz_info = cp_index_to_class_fullinfo(context, key, TRUE);
+ if (isSuperClass(context, clazz_info)) {
+ char *name = cp_index_to_fieldname(context, key);
+ char *signature = cp_index_to_signature(context, key);
+ unsigned ID = NameAndTypeToHash(name, signature);
+ ClassClass *calledClass =
+ object_fullinfo_to_classclass(context, clazz_info);
+ struct fieldblock *fb;
+
+ if (ID == 0) { // NameAndTypeToHash returns 0 if out of memory
+ // CCerror(context, "Out of memory");
+ return;
+ }
+ if (opcode != opc_invokevirtual && opcode != opc_invokespecial) {
+ int n = cbFieldsCount(calledClass);
+ fb = cbFields(calledClass);
+ for (; --n >= 0; fb++) {
+ if (fb->ID == ID) {
+ goto haveIt;
+ }
+ }
+ return;
+ } else {
+ struct methodblock *mb = cbMethods(calledClass);
+ int n = cbMethodsCount(calledClass);
+ for (; --n >= 0; mb++) {
+ if (mb->fb.ID == ID) {
+ fb = &mb->fb;
+ goto haveIt;
+ }
+ }
+ return;
+ }
+ haveIt:
+ if (IsProtected(fb->access)) {
+ if (IsPrivate(fb->access) ||
+ !IsSameClassPackage(calledClass, context->class))
+ context->instruction_data[inumber].protected = TRUE;
+ }
+ }*/
+}
+
+
+/*=========================================================================
+ * FUNCTION: isSuperClass
+ * OVERVIEW: Determines which of the classes are superclasses.
+ * Returns true if the given clazz_info corresponds to a
+ * a superclass.
+ * INTERFACE:
+ * parameters: context_type* : context
+ * fullinfo_type: clazz_info
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static bool_t
+isSuperClass(context_type *context, fullinfo_type clazz_info) {
+
+ //return TRUE;
+
+ fullinfo_type *fptr = context->superClasses;
+ if (fptr == NULL) {
+ ClassClass *cb;
+ fullinfo_type *gptr;
+ int i;
+ /* Count the number of superclasses. By counting ourselves, and
+ * not counting Object, we get the same number. */
+ for (i = 0, cb = context->class;
+ cb != classJavaLangObject;
+ i++, cb = cbSuperclass(cb));
+ /* Can't go on context heap since it survives more than one method */
+ context->superClasses = fptr
+ = sysMalloc(sizeof(fullinfo_type)*(i + 1));
+ if (fptr == 0) {
+ // CCerror(context, "Out of memory");
+ }
+ for (gptr = fptr, cb = context->class; cb != classJavaLangObject; ) {
+ void **addr;
+ cb = cbSuperclass(cb);
+ *gptr++ = MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), &addr);
+ *addr = cb;
+ }
+ *gptr = 0;
+ }
+ for (; *fptr != 0; fptr++) {
+ if (*fptr == clazz_info)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*=========================================================================
+ * FUNCTION: initialize_exception_table
+ * OVERVIEW: Initializes the exception table.
+ * Looks through each item on the exception table and ensures
+ * that each of the fields refers to a legal instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type structure.
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+initialize_exception_table(context_type *context)
+{
+ struct methodblock *mb = context->mb;
+ struct CatchFrame *exception_table = mb->exception_table;
+ struct handler_info_type *handler_info = context->handler_info;
+ short *code_data = context->code_data;
+ unsigned long code_length = mb->code_length;
+
+ int i;
+ for (i = mb->exception_table_length;
+ --i >= 0; exception_table++, handler_info++) {
+ unsigned long start = exception_table->start_pc;
+ unsigned long end = exception_table->end_pc;
+ unsigned long handler = exception_table->handler_pc;
+ unsigned catchType = exception_table->catchType;
+ stack_item_type *stack_item = NEW(stack_item_type, 1);
+ if (!( start < end && start >= 0
+ && isLegalTarget(context, start)
+ && (end == code_length || isLegalTarget(context, end)))) {
+ // CCerror(context, "Illegal exception table range");
+ }
+ if (!((handler > 0) && isLegalTarget(context, handler))) {
+ // CCerror(context, "Illegal exception table handler");
+ }
+
+ handler_info->start = code_data[start];
+ /* end may point to one byte beyond the end of bytecodes. */
+ handler_info->end = (end == context->mb->code_length) ?
+ context->instruction_count : code_data[end];
+ handler_info->handler = code_data[handler];
+ handler_info->stack_info.stack = stack_item;
+ handler_info->stack_info.stack_size = 1;
+
+ stack_item->next = NULL;
+ if (catchType != 0) {
+ union cp_item_type *cp = cbConstantPool(context->class);
+ char *classname;
+ verify_constant_pool_type(context, catchType, 1 << CONSTANT_Class);
+ classname = GetClassConstantClassName(cp, catchType);
+ stack_item->item = MAKE_CLASSNAME_INFO_WITH_COPY(context, classname, 0);
+ } else {
+ stack_item->item = context->throwable_info;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: instruction_length
+ * OVERVIEW: Given a pointer to an instruction, return its length.
+ * Use the table opcode_length[] which is automatically built.
+ * INTERFACE:
+ * parameters: pointer to the instruction
+ *
+ * returns: int type
+ *=======================================================================*/
+static int instruction_length(unsigned char *iptr)
+{
+ int instruction = *iptr;
+ switch (instruction) {
+ case opc_tableswitch: {
+ long *lpc = (long *) UCALIGN(iptr + 1);
+ int index = ntohl(lpc[2]) - ntohl(lpc[1]);
+ if ((index < 0) || (index > 65535)) {
+ return -1; /* illegal */
+ } else {
+ return (unsigned char *)(&lpc[index + 4]) - iptr;
+ }
+ }
+
+ case opc_lookupswitch: {
+ long *lpc = (long *) UCALIGN(iptr + 1);
+ int npairs = ntohl(lpc[1]);
+ if (npairs < 0 || npairs >= 8192)
+ return -1;
+ else
+ return (unsigned char *)(&lpc[2 * (npairs + 1)]) - iptr;
+ }
+
+ case opc_wide:
+ switch(iptr[1]) {
+ case opc_ret:
+ case opc_iload: case opc_istore:
+ case opc_fload: case opc_fstore:
+ case opc_aload: case opc_astore:
+ case opc_lload: case opc_lstore:
+ case opc_dload: case opc_dstore:
+ return 4;
+ case opc_iinc:
+ return 6;
+ default:
+ return -1;
+ }
+
+ default: {
+ /* A length of 0 indicates an error. */
+ int length = opcode_length[instruction];
+ return (length <= 0) ? -1 : length;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: isLegalTarget
+ * OVERVIEW: Given the target of a branch, make sure that it is a legal
+ * target. Returns true if it is a legal target of a branch.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: offset
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static bool_t
+isLegalTarget(context_type *context, int offset)
+{
+ struct methodblock *mb = context->mb;
+ int code_length = mb->code_length;
+ short *code_data = context->code_data;
+ return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
+}
+
+
+/*=========================================================================
+ * FUNCTION: verify_constant_pool_type
+ * OVERVIEW: Make sure that an element of the constant pool is really
+ * of the indicated type.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: index
+ * unsigned: mask
+ * returns: nothing
+ *=======================================================================*/
+static void
+verify_constant_pool_type(context_type *context, int index, unsigned mask)
+{
+ ClassClass *cb = context->class;
+ union cp_item_type *constant_pool = cbConstantPool(cb);
+ int nconstants = cbConstantPoolCount(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ unsigned type;
+
+ // if ((index <= 0) || (index >= nconstants))
+// CCerror(context, "Illegal constant pool index");
+
+ type = CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index);
+// if ((mask & (1 << type)) == 0)
+// CCerror(context, "Illegal type in constant pool");
+}
+
+
+/*=========================================================================
+ * Functions for Data Flow Analysis
+ *=======================================================================*/
+
+/*=========================================================================
+ * FUNCTION: initialize_dataflow
+ * OVERVIEW: Initialize for data flow analysis.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * returns: nothing
+ *=======================================================================*/
+static void
+initialize_dataflow(context_type *context)
+{
+ instruction_data_type *idata = context->instruction_data;
+ struct methodblock *mb = context->mb;
+ fullinfo_type *reg_ptr;
+ fullinfo_type full_info;
+ char *p;
+
+ /* Initialize the function entry, since we know everything about it. */
+ idata[0].stack_info.stack_size = 0;
+ idata[0].stack_info.stack = NULL;
+ idata[0].register_info.register_count = mb->args_size;
+ idata[0].register_info.registers = NEW(fullinfo_type, mb->args_size);
+ idata[0].register_info.mask_count = 0;
+ idata[0].register_info.masks = NULL;
+ idata[0].and_flags = 0; /* nothing needed */
+ idata[0].or_flags = FLAG_REACHED; /* instruction reached */
+ reg_ptr = idata[0].register_info.registers;
+
+ if ((mb->fb.access & ACC_STATIC) == 0) {
+ /* A non static method. If this is an <init> method, the first
+ * argument is an uninitialized object. Otherwise it is an object of
+ * the given class type. java.lang.Object.<init> is special since
+ * we don't call its superclass <init> method.
+ */
+ if (strcmp(mb->fb.name, "<init>") == 0
+ && context->currentclass_info != context->object_info) {
+ *reg_ptr++ = MAKE_FULLINFO(ITEM_InitObject, 0, 0);
+ idata[0].or_flags |= FLAG_NEED_CONSTRUCTOR;
+ } else {
+ *reg_ptr++ = context->currentclass_info;
+ }
+ }
+ /* Fill in each of the arguments into the registers. */
+ for (p = mb->fb.signature + 1; *p != SIGNATURE_ENDFUNC; ) {
+ char fieldchar = signature_to_fieldtype(context, &p, &full_info);
+ // if (no_floating_point && (fieldchar == 'D' || fieldchar == 'F')) {
+ // CCerror(context, "Floating point arguments not allowed");
+ // }
+ switch (fieldchar) {
+ case 'D': case 'L':
+ *reg_ptr++ = full_info;
+ *reg_ptr++ = full_info + 1;
+ break;
+ default:
+ *reg_ptr++ = full_info;
+ break;
+ }
+ }
+ p++; /* skip over right parenthesis */
+ if (*p == 'V') {
+ context->return_type = MAKE_FULLINFO(ITEM_Void, 0, 0);
+ } else {
+ signature_to_fieldtype(context, &p, &full_info);
+ context->return_type = full_info;
+ }
+
+ /* Indicate that we need to look at the first instruction. */
+ idata[0].changed = TRUE;
+}
+
+
+/*=========================================================================
+ * FUNCTION: run_dataflow
+ * OVERVIEW: Execute the data flow analysis as long as there are things
+ * to change.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * returns: nothing
+ *=======================================================================*/
+static void
+run_dataflow(context_type *context) {
+ struct methodblock *mb = context->mb;
+ int max_stack_size = mb->maxstack;
+ instruction_data_type *idata = context->instruction_data;
+ int icount = context->instruction_count;
+ bool_t work_to_do = TRUE;
+ int inumber;
+
+ /* Run through the loop, until there is nothing left to do. */
+ while (work_to_do) {
+ work_to_do = FALSE;
+ for (inumber = 0; inumber < icount; inumber++) {
+ instruction_data_type *this_idata = &idata[inumber];
+ if (this_idata->changed) {
+ register_info_type new_register_info;
+ stack_info_type new_stack_info;
+ flag_type new_and_flags, new_or_flags;
+
+ this_idata->changed = FALSE;
+ work_to_do = TRUE;
+ /* Make sure the registers and flags are appropriate */
+ check_register_values(context, inumber);
+ check_flags(context, inumber);
+
+ /* Make sure the stack can deal with this instruction */
+ pop_stack(context, inumber, &new_stack_info);
+
+ /* Update the registers and flags */
+ update_registers(context, inumber, &new_register_info);
+ update_flags(context, inumber, &new_and_flags, &new_or_flags);
+
+ /* Update the stack. */
+ push_stack(context, inumber, &new_stack_info);
+
+// if (new_stack_info.stack_size > max_stack_size)
+// CCerror(context, "Stack size too large");
+
+ /* Add the new stack and register information to any
+ * instructions that can follow this instruction. */
+ merge_into_successors(context, inumber,
+ &new_register_info, &new_stack_info,
+ new_and_flags, new_or_flags);
+ }
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: check_register_values
+ * OVERVIEW: Make sure that the registers contain a legitimate value
+ * for the given instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int inumber
+ * returns: nothing
+ *=======================================================================*/
+static void
+check_register_values(context_type *context, int inumber)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+ int operand = this_idata->operand.i;
+ int register_count = this_idata->register_info.register_count;
+ fullinfo_type *registers = this_idata->register_info.registers;
+ bool_t double_word = FALSE; /* default value */
+ int type;
+
+ switch (opcode) {
+ default:
+ return;
+ case opc_iload: case opc_iinc:
+ type = ITEM_Integer; break;
+ case opc_fload:
+ type = ITEM_Float; break;
+ case opc_aload:
+ type = ITEM_Object; break;
+ case opc_ret:
+ type = ITEM_ReturnAddress; break;
+ case opc_lload:
+ type = ITEM_Long; double_word = TRUE; break;
+ case opc_dload:
+ type = ITEM_Double; double_word = TRUE; break;
+ }
+ if (!double_word) {
+ fullinfo_type reg = registers[operand];
+ /* Make sure we don't have an illegal register or one with wrong type */
+ if (operand >= register_count) {
+ CCerror(context,
+ "Accessing value from uninitialized register %d", operand);
+ } else if (WITH_ZERO_EXTRA_INFO(reg) == MAKE_FULLINFO(type, 0, 0)) {
+ /* the register is obviously of the given type */
+ return;
+ } else if (GET_INDIRECTION(reg) > 0 && type == ITEM_Object) {
+ /* address type stuff be used on all arrays */
+ return;
+ } else if (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress) {
+// CCerror(context, "Cannot load return address from register %d",
+// operand);
+ /* alternatively
+ (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress)
+ && (opcode == opc_iload)
+ && (type == ITEM_Object || type == ITEM_Integer)
+ but this never occurs
+ */
+ } else if (reg == ITEM_InitObject && type == ITEM_Object) {
+ return;
+ } else if (WITH_ZERO_EXTRA_INFO(reg) ==
+ MAKE_FULLINFO(ITEM_NewObject, 0, 0) &&
+ type == ITEM_Object) {
+ return;
+ } else {
+// CCerror(context, "Register %d contains wrong type", operand);
+ }
+ } else {
+ /* Make sure we don't have an illegal register or one with wrong type */
+ if ((operand + 1) >= register_count) {
+// CCerror(context,
+// "Accessing value from uninitialized register pair %d/%d",
+// operand, operand+1);
+ } else {
+ if ((registers[operand] == MAKE_FULLINFO(type, 0, 0)) &&
+ (registers[operand + 1] == MAKE_FULLINFO(type + 1, 0, 0))) {
+ return;
+ } else {
+// CCerror(context, "Register pair %d/%d contains wrong type",
+// operand, operand+1);
+ }
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: check_flags
+ * OVERVIEW: Make sure that the flags contain legitimate values for this
+ * instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * returns: nothing
+ *=======================================================================*/
+static void
+check_flags(context_type *context, int inumber)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+}
+
+
+/*=========================================================================
+ * FUNCTION: pop_stack
+ * OVERVIEW: Make sure that the top of the stack contains reasonable
+ * values for the given instruction. The post-pop values of
+ * the stack and its size are returned in *new_stack_info.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * stack_info_type: *new_stack_info
+ * returns: nothing
+ *=======================================================================*/
+static void
+pop_stack(context_type *context, int inumber, stack_info_type *new_stack_info)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+ stack_item_type *stack = this_idata->stack_info.stack;
+ int stack_size = this_idata->stack_info.stack_size;
+ char *stack_operands, *p;
+ char buffer[257]; /* for holding manufactured argument lists */
+ fullinfo_type stack_extra_info_buffer[256]; /* save info popped off stack */
+ fullinfo_type *stack_extra_info = &stack_extra_info_buffer[256];
+ fullinfo_type full_info, put_full_info;
+
+ switch(opcode) {
+ default:
+ /* For most instructions, we just use a built-in table */
+ stack_operands = opcode_in_out[opcode][0];
+ break;
+
+ case opc_putstatic: case opc_putfield: {
+ /* The top thing on the stack depends on the signature of
+ * the object. */
+ int operand = this_idata->operand.i;
+ char *signature = cp_index_to_signature(context, operand);
+ char *ip = buffer;
+
+ if (opcode == opc_putfield)
+ *ip++ = 'A'; /* object for putfield */
+ *ip++ = signature_to_fieldtype(context, &signature, &put_full_info);
+ *ip = '\0';
+ stack_operands = buffer;
+ break;
+ }
+
+ case opc_invokevirtual: case opc_invokespecial:
+ case opc_invokeinit: /* invokespecial call to <init> */
+ case opc_invokestatic: case opc_invokeinterface: {
+ /* The top stuff on the stack depends on the method signature */
+ int operand = this_idata->operand.i;
+ char *signature = cp_index_to_signature(context, operand);
+ char *ip = buffer;
+ char *p;
+
+ if (opcode != opc_invokestatic)
+ /* First, push the object */
+ *ip++ = (opcode == opc_invokeinit ? '@' : 'A');
+ for (p = signature + 1; *p != SIGNATURE_ENDFUNC; ) {
+ *ip++ = signature_to_fieldtype(context, &p, &full_info);
+ // if (ip >= buffer + sizeof(buffer) - 1)
+ // CCerror(context, "Signature %s has too many arguments",
+ // signature);
+ }
+ *ip = 0;
+ stack_operands = buffer;
+ break;
+ }
+
+ case opc_multianewarray: {
+ /* Count can't be larger than 255. So can't overflow buffer */
+ int count = this_idata->operand2.i; /* number of ints on stack */
+ memset(buffer, 'I', count);
+ buffer[count] = '\0';
+ stack_operands = buffer;
+ break;
+ }
+
+ } /* of switch */
+
+ /* Run through the list of operands >>backwards<< */
+ for ( p = stack_operands + strlen(stack_operands);
+ p > stack_operands;
+ stack = stack->next) {
+ int type = *--p;
+ fullinfo_type top_type = stack ? stack->item : 0;
+ int size = (type == 'D' || type == 'L') ? 2 : 1;
+ *--stack_extra_info = top_type;
+// if (stack == NULL)
+// CCerror(context, "Unable to pop operand off an empty stack");
+ switch (type) {
+ case 'I':
+ // if (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0))
+ // CCerror(context, "Expecting to find integer on stack");
+ break;
+
+ case 'F':
+ // if (top_type != MAKE_FULLINFO(ITEM_Float, 0, 0))
+ // CCerror(context, "Expecting to find float on stack");
+ break;
+
+ case 'A': /* object or array */
+ if ( (GET_ITEM_TYPE(top_type) != ITEM_Object)
+ && (GET_INDIRECTION(top_type) == 0)) {
+ /* The thing isn't an object or an array. Let's see if it's
+ * one of the special cases */
+ if ( (WITH_ZERO_EXTRA_INFO(top_type) ==
+ MAKE_FULLINFO(ITEM_ReturnAddress, 0, 0))
+ && (opcode == opc_astore))
+ break;
+ if ( (GET_ITEM_TYPE(top_type) == ITEM_NewObject
+ || (GET_ITEM_TYPE(top_type) == ITEM_InitObject))
+ && ((opcode == opc_astore) || (opcode == opc_aload)))
+ break;
+
+ /* The 2nd edition VM of the specification allows field
+ * initializations before the superclass initializer,
+ * if the field is defined within the current class.
+ */
+ if ( (GET_ITEM_TYPE(top_type) == ITEM_InitObject)
+ && (opcode == opc_putfield)) {
+
+ int num_fields;
+ int key = this_idata->operand.i;
+ fullinfo_type clazz_info = cp_index_to_class_fullinfo(
+ context, key, TRUE);
+ char *name = cp_index_to_fieldname(context, key);
+ char *signature = cp_index_to_signature(context, key);
+ unsigned ID = NameAndTypeToHash(name, signature);
+
+ ClassClass *calledClass =
+ object_fullinfo_to_classclass(context, clazz_info);
+ struct fieldblock *fb;
+ if (ID == 0) {
+ /* NameAndTypeToHash returns 0
+ * if out of memory
+ */
+ // CCerror(context, "Out of memory");
+ break;
+ }
+ num_fields = cbFieldsCount(calledClass);
+ fb = cbFields(calledClass);
+ for (; --num_fields >= 0; fb++) {
+ if (fb->ID == ID) {
+ break;
+ }
+ }
+
+ if (num_fields != -1) {
+ top_type = context->currentclass_info;
+ *stack_extra_info = top_type;
+ break;
+ }
+ }
+ // CCerror(context, "Expecting to find object/array on stack");
+ }
+ break;
+
+ case '@': { /* unitialized object, for call to <init> */
+ int item_type = GET_ITEM_TYPE(top_type);
+ // if (item_type != ITEM_NewObject && item_type != ITEM_InitObject)
+ // CCerror(context,
+ // "Expecting to find unitialized object on stack");
+ break;
+ }
+
+ case 'O': /* object, not array */
+ // if (WITH_ZERO_EXTRA_INFO(top_type) !=
+ // MAKE_FULLINFO(ITEM_Object, 0, 0))
+ // CCerror(context, "Expecting to find object on stack");
+ break;
+
+ case 'a': /* integer, object, or array */
+ // if ( (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0))
+ // && (GET_ITEM_TYPE(top_type) != ITEM_Object)
+ // && (GET_INDIRECTION(top_type) == 0))
+ // CCerror(context,
+ // "Expecting to find object, array, or int on stack");
+ break;
+
+ case 'D': /* double */
+ // if (top_type != MAKE_FULLINFO(ITEM_Double, 0, 0))
+ // CCerror(context, "Expecting to find double on stack");
+ break;
+
+ case 'L': /* long */
+ // if (top_type != MAKE_FULLINFO(ITEM_Long, 0, 0))
+ // CCerror(context, "Expecting to find long on stack");
+ break;
+
+ case ']': /* array of some type */
+ if (top_type == NULL_FULLINFO) {
+ /* do nothing */
+ } else switch(p[-1]) {
+ case 'I': /* array of integers */
+ // if (top_type != MAKE_FULLINFO(ITEM_Integer, 1, 0) &&
+ // top_type != NULL_FULLINFO)
+ // CCerror(context,
+ // "Expecting to find array of ints on stack");
+ break;
+
+ case 'L': /* array of longs */
+ // if (top_type != MAKE_FULLINFO(ITEM_Long, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of longs on stack");
+ break;
+
+ case 'F': /* array of floats */
+ // if (top_type != MAKE_FULLINFO(ITEM_Float, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of floats on stack");
+ break;
+
+ case 'D': /* array of doubles */
+ // if (top_type != MAKE_FULLINFO(ITEM_Double, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of doubles on stack");
+ break;
+
+ case 'A': { /* array of addresses (arrays or objects) */
+ // int indirection = GET_INDIRECTION(top_type);
+ // if ((indirection == 0) ||
+ // ((indirection == 1) &&
+ // (GET_ITEM_TYPE(top_type) != ITEM_Object)))
+ // CCerror(context,
+ // "Expecting to find array of objects or arrays "
+ // "on stack");
+ break;
+ }
+
+ case 'b': /* array of bytes or boolean */
+ // if (top_type != MAKE_FULLINFO(ITEM_Byte, 1, 0) &&
+ // top_type != MAKE_FULLINFO(ITEM_Boolean, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of bytes or booleans on stack");
+ break;
+
+ case 'B': /* array of bytes */
+ // if (top_type != MAKE_FULLINFO(ITEM_Byte, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of bytes on stack");
+ break;
+
+ case 'Z': /* array of boolean */
+ // if (top_type != MAKE_FULLINFO(ITEM_Boolean, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of bytes on stack");
+ break;
+
+ case 'C': /* array of characters */
+ // if (top_type != MAKE_FULLINFO(ITEM_Char, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of chars on stack");
+ break;
+
+ case 'S': /* array of shorts */
+ // if (top_type != MAKE_FULLINFO(ITEM_Short, 1, 0))
+ // CCerror(context,
+ // "Expecting to find array of shorts on stack");
+ break;
+
+ case '?': /* any type of array is okay */
+ // if (GET_INDIRECTION(top_type) == 0)
+ // CCerror(context,
+ // "Expecting to find array on stack");
+ break;
+
+ default:
+ // CCerror(context, "Internal error #1");
+ sysAssert(FALSE);
+ break;
+ }
+ p -= 2; /* skip over [ <char> */
+ break;
+
+ case '1': case '2': case '3': case '4': /* stack swapping */
+ if (top_type == MAKE_FULLINFO(ITEM_Double, 0, 0)
+ || top_type == MAKE_FULLINFO(ITEM_Long, 0, 0)) {
+ if ((p > stack_operands) && (p[-1] == '+')) {
+ context->swap_table[type - '1'] = top_type + 1;
+ context->swap_table[p[-2] - '1'] = top_type;
+ size = 2;
+ p -= 2;
+ } else {
+ // CCerror(context,
+ // "Attempt to split long or double on the stack");
+ }
+ } else {
+ context->swap_table[type - '1'] = stack->item;
+ if ((p > stack_operands) && (p[-1] == '+'))
+ p--; /* ignore */
+ }
+ break;
+ case '+': /* these should have been caught. */
+ default:
+ // CCerror(context, "Internal error #2");
+ sysAssert(FALSE);
+ }
+ stack_size -= size;
+ }
+
+ /* For many of the opcodes that had an "A" in their field, we really
+ * need to go back and do a little bit more accurate testing. We can, of
+ * course, assume that the minimal type checking has already been done.
+ */
+ switch (opcode) {
+ default: break;
+ case opc_aastore: { /* array index object */
+ fullinfo_type array_type = stack_extra_info[0];
+ fullinfo_type object_type = stack_extra_info[2];
+ fullinfo_type target_type = decrement_indirection(array_type);
+ if (array_type == NULL_FULLINFO) {
+ break;
+ }
+ if ((WITH_ZERO_EXTRA_INFO(target_type) ==
+ MAKE_FULLINFO(ITEM_Object, 0, 0)) &&
+ (WITH_ZERO_EXTRA_INFO(object_type) ==
+ MAKE_FULLINFO(ITEM_Object, 0, 0))) {
+ /* I disagree. But other's seem to think that we should allow
+ * an assignment of any Object to any array of any Object type.
+ * There will be an runtime error if the types are wrong.
+ */
+ break;
+ }
+ // if (!isAssignableTo(context, object_type, target_type))
+ // CCerror(context, "Incompatible types for storing into array of "
+ // "arrays or objects");
+ break;
+ }
+
+ case opc_putfield:
+ case opc_getfield:
+ case opc_putstatic: {
+ int operand = this_idata->operand.i;
+ fullinfo_type stack_object = stack_extra_info[0];
+ if (opcode == opc_putfield || opcode == opc_getfield) {
+ if (!isAssignableTo(context,
+ stack_object,
+ cp_index_to_class_fullinfo(context, operand,
+ TRUE))) {
+ // CCerror(context,
+ // "Incompatible type for getting or setting field");
+ }
+ /* FY: Why is this commented out?? */
+ /*
+ if (this_idata->protected &&
+ !isAssignableTo(context, stack_object,
+ context->currentclass_info)) {
+ CCerror(context, "Bad access to protected data");
+ }*/
+ }
+ if (opcode == opc_putfield || opcode == opc_putstatic) {
+ int item = (opcode == opc_putfield ? 1 : 0);
+ if (!isAssignableTo(context,
+ stack_extra_info[item], put_full_info)) {
+ // CCerror(context, "Bad type in putfield/putstatic");
+ }
+ }
+ break;
+ }
+
+ case opc_athrow:
+// if (!isAssignableTo(context, stack_extra_info[0],
+// context->throwable_info)) {
+// CCerror(context, "Can only throw Throwable objects");
+// }
+ break;
+
+ case opc_aaload: { /* array index */
+ /* We need to pass the information to the stack updater */
+ fullinfo_type array_type = stack_extra_info[0];
+ context->swap_table[0] = decrement_indirection(array_type);
+ break;
+ }
+
+ case opc_invokevirtual: case opc_invokespecial:
+ case opc_invokeinit:
+ case opc_invokeinterface: case opc_invokestatic: {
+ int operand = this_idata->operand.i;
+ char *signature = cp_index_to_signature(context, operand);
+ int item;
+ char *p;
+ if (opcode == opc_invokestatic) {
+ item = 0;
+ } else if (opcode == opc_invokeinit) {
+ fullinfo_type init_type = this_idata->operand2.fi;
+ fullinfo_type object_type = stack_extra_info[0];
+ context->swap_table[0] = object_type; /* save value */
+ if (GET_ITEM_TYPE(stack_extra_info[0]) == ITEM_NewObject) {
+ /* We better be calling the appropriate init. Find the
+ * inumber of the "opc_new" instruction", and figure
+ * out what the type really is.
+ */
+ int new_inumber = GET_EXTRA_INFO(stack_extra_info[0]);
+ fullinfo_type target_type = idata[new_inumber].operand2.fi;
+ context->swap_table[1] = target_type;
+ // if (target_type != init_type) {
+ // CCerror(context, "Call to wrong initialization method");
+ // }
+ } else {
+ /* We better be calling super() or this(). */
+ if (init_type != context->superclass_info &&
+ init_type != context->currentclass_info) {
+ // CCerror(context, "Call to wrong initialization method");
+ }
+ context->swap_table[1] = context->currentclass_info;
+ }
+ item = 1;
+ } else {
+ fullinfo_type target_type = this_idata->operand2.fi;
+ fullinfo_type object_type = stack_extra_info[0];
+ if (!isAssignableTo(context, object_type, target_type)){
+ // CCerror(context,
+ // "Incompatible object argument for function call");
+ }
+ /* The specification of the structural constraints for
+ * invokespecial needs to be more stringent.
+ *
+ * If invokespecial is used to invoke an instance method
+ * that is not an instance initialization method, then the
+ * type of the class instance, which is the target of method
+ * invocation, must be assignment compatible with the
+ * current class.
+ */
+ if (opcode == opc_invokespecial
+ && !isAssignableTo(context, object_type,
+ context->currentclass_info)) {
+ /* Make sure object argument is assignment compatible
+ * to current class
+ */
+ // CCerror(context,
+ // "Incompatible object argument for invokespecial");
+ }
+
+ if (this_idata->protected
+ && !isAssignableTo(context, object_type,
+ context->currentclass_info)) {
+ /* This is ugly. Special dispensation. Arrays pretend to
+ implement public Object clone() even though they don't */
+ if ((target_type == context->object_info) &&
+ (GET_INDIRECTION(object_type) > 0) &&
+ (strcmp(cp_index_to_fieldname(context, this_idata->operand.i),
+ "clone") == 0)) {
+ } else {
+ // CCerror(context, "Bad access to protected data");
+ }
+ }
+ item = 1;
+ }
+ for (p = signature + 1; *p != SIGNATURE_ENDFUNC; item++)
+ if (signature_to_fieldtype(context, &p, &full_info) == 'A') {
+ if (!isAssignableTo(context,
+ stack_extra_info[item], full_info)) {
+ // CCerror(context, "Incompatible argument to function");
+ }
+ }
+
+ break;
+ }
+
+ case opc_return:
+// if (context->return_type != MAKE_FULLINFO(ITEM_Void, 0, 0))
+// CCerror(context, "Wrong return type in function");
+ break;
+
+ case opc_ireturn: case opc_lreturn: case opc_freturn:
+ case opc_dreturn: case opc_areturn: {
+ fullinfo_type target_type = context->return_type;
+ fullinfo_type object_type = stack_extra_info[0];
+ if (!isAssignableTo(context, object_type, target_type)) {
+// CCerror(context, "Wrong return type in function");
+ }
+ break;
+ }
+
+ case opc_new: {
+ /* Make sure that nothing on the stack already looks like what
+ * we want to create. I can't image how this could possibly happen
+ * but we should test for it anyway, since if it could happen, the
+ * result would be an unitialized object being able to masquerade
+ * as an initialized one.
+ */
+ stack_item_type *item;
+ for (item = stack; item != NULL; item = item->next) {
+ // if (item->item == this_idata->operand.fi) {
+ // CCerror(context,
+ // "Uninitialized object on stack at creating point");
+ // }
+ }
+ /* Info for update_registers */
+ context->swap_table[0] = this_idata->operand.fi;
+ context->swap_table[1] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+
+ break;
+ }
+ }
+ new_stack_info->stack = stack;
+ new_stack_info->stack_size = stack_size;
+}
+
+
+/*=========================================================================
+ * FUNCTION: update_registers
+ * OVERVIEW: Perform the operation on the registers, and return the
+ * updated results in new_register_count_p and new_registers.
+ * Note that the instruction has already been determined
+ * to be legal.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * register_info_type: pointer to new register info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+update_registers(context_type *context, int inumber,
+ register_info_type *new_register_info)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+ int operand = this_idata->operand.i;
+ int register_count = this_idata->register_info.register_count;
+ fullinfo_type *registers = this_idata->register_info.registers;
+ stack_item_type *stack = this_idata->stack_info.stack;
+ int mask_count = this_idata->register_info.mask_count;
+ mask_type *masks = this_idata->register_info.masks;
+
+ /* Use these as default new values. */
+ int new_register_count = register_count;
+ int new_mask_count = mask_count;
+ fullinfo_type *new_registers = registers;
+ mask_type *new_masks = masks;
+
+ enum { NONE, SINGLE, DOUBLE } access = NONE;
+ int i;
+
+ /* Remember, we've already verified the type at the top of the stack. */
+ switch (opcode) {
+ default: break;
+ case opc_istore: case opc_fstore: case opc_astore:
+ access = SINGLE;
+ goto continue_store;
+
+ case opc_lstore: case opc_dstore:
+ access = DOUBLE;
+ goto continue_store;
+
+ continue_store: {
+ /* We have a modification to the registers. Copy them if needed. */
+ fullinfo_type stack_top_type = stack->item;
+ int max_operand = operand + ((access == DOUBLE) ? 1 : 0);
+
+ if ( max_operand < register_count
+ && registers[operand] == stack_top_type
+ && ((access == SINGLE) ||
+ (registers[operand + 1]== stack_top_type + 1)))
+ /* No changes have been made to the registers. */
+ break;
+ new_register_count = MAX(max_operand + 1, register_count);
+ new_registers = NEW(fullinfo_type, new_register_count);
+ for (i = 0; i < register_count; i++)
+ new_registers[i] = registers[i];
+ for (i = register_count; i < new_register_count; i++)
+ new_registers[i] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ new_registers[operand] = stack_top_type;
+ if (access == DOUBLE)
+ new_registers[operand + 1] = stack_top_type + 1;
+ break;
+ }
+
+ case opc_iload: case opc_fload: case opc_aload:
+ case opc_iinc: case opc_ret:
+ access = SINGLE;
+ break;
+
+ case opc_lload: case opc_dload:
+ access = DOUBLE;
+ break;
+
+ case opc_jsr: case opc_jsr_w:
+ for (i = 0; i < new_mask_count; i++)
+ if (new_masks[i].entry == operand)
+ CCerror(context, "Recursive call to jsr entry");
+ if (context->redoJsr
+ && this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION) {
+ /* Do nothing */
+ } else {
+ new_masks = add_to_masks(context, masks, mask_count, operand);
+ new_mask_count++;
+ }
+ break;
+
+ case opc_invokeinit:
+ case opc_new: {
+ /* For invokeinit, an uninitialized object has been initialized.
+ * For new, all previous occurrences of an uninitialized object
+ * from the same instruction must be made bogus.
+ * We find all occurrences of swap_table[0] in the registers, and
+ * replace them with swap_table[1];
+ */
+ fullinfo_type from = context->swap_table[0];
+ fullinfo_type to = context->swap_table[1];
+
+ int i;
+ for (i = 0; i < register_count; i++) {
+ if (new_registers[i] == from) {
+ /* Found a match */
+ break;
+ }
+ }
+ if (i < register_count) { /* We broke out loop for match */
+ /* We have to change registers, and possibly a mask */
+ bool_t copied_mask = FALSE;
+ int k;
+ new_registers = NEW(fullinfo_type, register_count);
+ memcpy(new_registers, registers,
+ register_count * sizeof(registers[0]));
+ for ( ; i < register_count; i++) {
+ if (new_registers[i] == from) {
+ new_registers[i] = to;
+ for (k = 0; k < new_mask_count; k++) {
+ if (!IS_BIT_SET(new_masks[k].modifies, i)) {
+ if (!copied_mask) {
+ new_masks = copy_masks(context, new_masks,
+ mask_count);
+ copied_mask = TRUE;
+ }
+ SET_BIT(new_masks[k].modifies, i);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ } /* of switch */
+
+ if ((access != NONE) && (new_mask_count > 0)) {
+ int i, j;
+ for (i = 0; i < new_mask_count; i++) {
+ int *mask = new_masks[i].modifies;
+ if ((!IS_BIT_SET(mask, operand)) ||
+ ((access == DOUBLE) && !IS_BIT_SET(mask, operand + 1))) {
+ new_masks = copy_masks(context, new_masks, mask_count);
+ for (j = i; j < new_mask_count; j++) {
+ SET_BIT(new_masks[j].modifies, operand);
+ if (access == DOUBLE)
+ SET_BIT(new_masks[j].modifies, operand + 1);
+ }
+ break;
+ }
+ }
+ }
+
+ new_register_info->register_count = new_register_count;
+ new_register_info->registers = new_registers;
+ new_register_info->masks = new_masks;
+ new_register_info->mask_count = new_mask_count;
+}
+
+
+/*=========================================================================
+ * FUNCTION: update_flags
+ * OVERVIEW: Update the flags now that we have already determined
+ * the instruction to be legal and have already updated the
+ * registers.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * flag_type: pointer to new_and_flags
+ * flag_type: pointer to new_or_flags
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+update_flags(context_type *context, int inumber,
+ flag_type *new_and_flags, flag_type *new_or_flags)
+
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ flag_type and_flags = this_idata->and_flags;
+ flag_type or_flags = this_idata->or_flags;
+
+ /* Set the "we've done a constructor" flag */
+ if (this_idata->opcode == opc_invokeinit) {
+ fullinfo_type from = context->swap_table[0];
+ if (from == MAKE_FULLINFO(ITEM_InitObject, 0, 0))
+ and_flags |= FLAG_CONSTRUCTED;
+ }
+ *new_and_flags = and_flags;
+ *new_or_flags = or_flags;
+}
+
+
+/*=========================================================================
+ * FUNCTION: push_stack
+ * OVERVIEW: Perform the operation on the stack.
+ * Note that the instruction has already been determined
+ * to be legal.
+ * new_stack_size_p and new_stack_p point to the results after
+ * the pops have already been done. Do the pushes, and then
+ * put the results back there.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * stack_info_type: pointer to new stack info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+push_stack(context_type *context, int inumber, stack_info_type *new_stack_info)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+ int operand = this_idata->operand.i;
+
+ int stack_size = new_stack_info->stack_size;
+ stack_item_type *stack = new_stack_info->stack;
+ char *stack_results;
+
+ fullinfo_type full_info = 0;
+ char buffer[5], *p; /* actually [2] is big enough */
+
+ /* We need to look at all those opcodes in which either we can't tell the
+ * value pushed onto the stack from the opcode, or in which the value
+ * pushed onto the stack is an object or array. For the latter, we need
+ * to make sure that full_info is set to the right value.
+ */
+ switch(opcode) {
+ default:
+ stack_results = opcode_in_out[opcode][1];
+ break;
+
+ case opc_ldc: case opc_ldc_w: case opc_ldc2_w: {
+ /* Look to constant pool to determine correct result. */
+ union cp_item_type *cp = cbConstantPool(context->class);
+ unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ switch (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand)) {
+ case CONSTANT_Integer:
+ stack_results = "I"; break;
+ case CONSTANT_Float:
+ stack_results = "F"; break;
+ case CONSTANT_Double:
+ stack_results = "D"; break;
+ case CONSTANT_Long:
+ stack_results = "L"; break;
+ case CONSTANT_String:
+ stack_results = "A";
+ full_info = context->string_info;
+ break;
+ default:
+ // CCerror(context, "Internal error #3");
+ sysAssert(FALSE);
+ }
+ break;
+ }
+
+ case opc_getstatic: case opc_getfield: {
+ /* Look to signature to determine correct result. */
+ int operand = this_idata->operand.i;
+ char *signature = cp_index_to_signature(context, operand);
+#ifdef DEBUG_VERIFIER
+ if (verify_verbose) {
+ print_formatted_fieldname(context, operand);
+ }
+#endif
+ buffer[0] = signature_to_fieldtype(context, &signature, &full_info);
+ buffer[1] = '\0';
+ stack_results = buffer;
+ break;
+ }
+
+ case opc_invokevirtual: case opc_invokespecial:
+ case opc_invokeinit:
+ case opc_invokestatic: case opc_invokeinterface: {
+ /* Look to signature to determine correct result. */
+ int operand = this_idata->operand.i;
+ char *signature = cp_index_to_signature(context, operand);
+ char *result_signature = strchr(signature, SIGNATURE_ENDFUNC) + 1;
+ if (result_signature[0] == SIGNATURE_VOID) {
+ stack_results = "";
+ } else {
+ buffer[0] = signature_to_fieldtype(context, &result_signature,
+ &full_info);
+ buffer[1] = '\0';
+ stack_results = buffer;
+ }
+ break;
+ }
+
+ case opc_aconst_null:
+ stack_results = opcode_in_out[opcode][1];
+ full_info = NULL_FULLINFO; /* special NULL */
+ break;
+
+ case opc_new:
+ case opc_checkcast:
+ case opc_newarray:
+ case opc_anewarray:
+ case opc_multianewarray:
+ stack_results = opcode_in_out[opcode][1];
+ /* Conventionally, this result type is stored here */
+ full_info = this_idata->operand.fi;
+ if (no_floating_point && (opcode == opc_newarray)
+ && (full_info == MAKE_FULLINFO(ITEM_Float, 1, 0) ||
+ full_info == MAKE_FULLINFO(ITEM_Double, 1, 0))) {
+ // CCerror(context, "Cannot create floating point array");
+ }
+ break;
+
+ case opc_aaload:
+ stack_results = opcode_in_out[opcode][1];
+ /* pop_stack() saved value for us. */
+ full_info = context->swap_table[0];
+ break;
+
+ case opc_aload:
+ stack_results = opcode_in_out[opcode][1];
+ /* The register hasn't been modified, so we can use its value. */
+ full_info = this_idata->register_info.registers[operand];
+ break;
+ } /* of switch */
+
+ for (p = stack_results; *p != 0; p++) {
+ int type = *p;
+ stack_item_type *new_item = NEW(stack_item_type, 1);
+ new_item->next = stack;
+ stack = new_item;
+ switch (type) {
+ case 'I':
+ stack->item = MAKE_FULLINFO(ITEM_Integer, 0, 0); break;
+ case 'F':
+ // if (no_floating_point) {
+ // CCerror(context, "Floating point result not allowed");
+ // }
+ stack->item = MAKE_FULLINFO(ITEM_Float, 0, 0);
+ break;
+ case 'D':
+ // if (no_floating_point) {
+ // CCerror(context, "Floating point result not allowed");
+ // }
+ stack->item = MAKE_FULLINFO(ITEM_Double, 0, 0);
+ stack_size++;
+ break;
+ case 'L':
+ stack->item = MAKE_FULLINFO(ITEM_Long, 0, 0);
+ stack_size++; break;
+ case 'R':
+ stack->item = MAKE_FULLINFO(ITEM_ReturnAddress, 0, operand);
+ break;
+ case '1': case '2': case '3': case '4': {
+ /* Get the info saved in the swap_table */
+ fullinfo_type stype = context->swap_table[type - '1'];
+ stack->item = stype;
+ if (stype == MAKE_FULLINFO(ITEM_Long, 0, 0) ||
+ stype == MAKE_FULLINFO(ITEM_Double, 0, 0)) {
+ stack_size++; p++;
+ }
+ break;
+ }
+ case 'A':
+ /* full_info should have the appropriate value. */
+ sysAssert(full_info != 0);
+ stack->item = full_info;
+ break;
+ default:
+ // CCerror(context, "Internal error #4");
+ sysAssert(FALSE);
+
+ } /* switch type */
+ stack_size++;
+ } /* outer for loop */
+
+ if (opcode == opc_invokeinit) {
+ /* If there are any instances of "from" on the stack, we need to
+ * replace it with "to", since calling <init> initializes all versions
+ * of the object, obviously. */
+ fullinfo_type from = context->swap_table[0];
+ stack_item_type *ptr;
+ for (ptr = stack; ptr != NULL; ptr = ptr->next) {
+ if (ptr->item == from) {
+ fullinfo_type to = context->swap_table[1];
+ stack = copy_stack(context, stack);
+ for (ptr = stack; ptr != NULL; ptr = ptr->next)
+ if (ptr->item == from) ptr->item = to;
+ break;
+ }
+ }
+ }
+
+ new_stack_info->stack_size = stack_size;
+ new_stack_info->stack = stack;
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_into_successors
+ * OVERVIEW: Executed an instruction, and have determined the new
+ * registers and stack values. Look at all of the possibly
+ * subsequent instructions, and merge this stack value into
+ * theirs.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * stack_info_type: pointer to stack_info
+ * flag_type: and_flags
+ * flag_type: or_flags
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+merge_into_successors(context_type *context, int inumber,
+ register_info_type *register_info,
+ stack_info_type *stack_info,
+ flag_type and_flags, flag_type or_flags)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[inumber];
+ opcode_type opcode = this_idata->opcode;
+ int operand = this_idata->operand.i;
+ struct handler_info_type *handler_info = context->handler_info;
+ int handler_info_length = context->mb->exception_table_length;
+
+
+ int buffer[2]; /* default value for successors */
+ int *successors = buffer; /* table of successors */
+ int successors_count;
+ int i;
+
+ switch (opcode) {
+ default:
+ successors_count = 1;
+ buffer[0] = inumber + 1;
+ break;
+
+ case opc_ifeq: case opc_ifne: case opc_ifgt:
+ case opc_ifge: case opc_iflt: case opc_ifle:
+ case opc_ifnull: case opc_ifnonnull:
+ case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
+ case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
+ case opc_if_acmpeq: case opc_if_acmpne:
+ successors_count = 2;
+ buffer[0] = inumber + 1;
+ buffer[1] = operand;
+ idata[operand].is_target = TRUE; /* inlinejsr */
+ break;
+
+ case opc_jsr: case opc_jsr_w:
+ if (this_idata->operand2.i != UNKNOWN_RET_INSTRUCTION)
+ idata[this_idata->operand2.i].changed = TRUE;
+ /* FALLTHROUGH */
+ case opc_goto: case opc_goto_w:
+ successors_count = 1;
+ buffer[0] = operand;
+ idata[operand].is_target = TRUE; /* inlinejsr */
+ break;
+
+
+ case opc_ireturn: case opc_lreturn: case opc_return:
+ case opc_freturn: case opc_dreturn: case opc_areturn:
+ case opc_athrow:
+ /* The testing for the returns is handled in pop_stack() */
+ successors_count = 0;
+ break;
+
+ case opc_ret: {
+ /* This is slightly slow, but good enough for a seldom used instruction.
+ * The EXTRA_ITEM_INFO of the ITEM_ReturnAddress indicates the
+ * address of the first instruction of the subroutine. We can return
+ * to 1 after any instruction that jsr's to that instruction.
+ */
+ if (this_idata->operand2.ip == NULL) {
+ fullinfo_type *registers = this_idata->register_info.registers;
+ int called_instruction = GET_EXTRA_INFO(registers[operand]);
+ int i, count, *ptr;;
+ for (i = context->instruction_count, count = 0; --i >= 0; ) {
+ if (((idata[i].opcode == opc_jsr) ||
+ (idata[i].opcode == opc_jsr_w)) &&
+ (idata[i].operand.i == called_instruction))
+ count++;
+ }
+ this_idata->operand2.ip = ptr = NEW(int, count + 1);
+ *ptr++ = count;
+ for (i = context->instruction_count, count = 0; --i >= 0; ) {
+ if (((idata[i].opcode == opc_jsr) ||
+ (idata[i].opcode == opc_jsr_w)) &&
+ (idata[i].operand.i == called_instruction)) {
+ *ptr++ = i + 1;
+ idata[i + 1].is_target = TRUE; /* inlinejsr */
+ }
+ }
+ }
+ successors = this_idata->operand2.ip; /* use this instead */
+ successors_count = *successors++;
+ break;
+
+ }
+
+ case opc_tableswitch:
+ case opc_lookupswitch: {
+ int i;
+ successors = this_idata->operand.ip; /* use this instead */
+ successors_count = *successors++;
+ for (i = 0; i < successors_count; i++) {
+ idata[successors[i]].is_target = TRUE; /* inlinejsr */
+ }
+ break;
+ }
+
+ }
+
+
+
+ handler_info = context->handler_info;
+ for (i = handler_info_length; --i >= 0; handler_info++) {
+ if (handler_info->start <= inumber && handler_info->end > inumber) {
+ int handler = handler_info->handler;
+ idata[handler].is_target = TRUE; /* inlinejsr */
+ if (opcode != opc_invokeinit) {
+ merge_into_one_successor(context, inumber, handler,
+ &this_idata->register_info, /* old */
+ &handler_info->stack_info,
+ (flag_type) (and_flags
+ & this_idata->and_flags),
+ (flag_type) (or_flags
+ | this_idata->or_flags),
+ TRUE);
+ } else {
+ /* We need to be a little bit more careful with this
+ * instruction. Things could either be in the state before
+ * the instruction or in the state afterwards */
+ fullinfo_type from = context->swap_table[0];
+ flag_type temp_or_flags = or_flags;
+ if (from == MAKE_FULLINFO(ITEM_InitObject, 0, 0))
+ temp_or_flags |= FLAG_NO_RETURN;
+ merge_into_one_successor(context, inumber, handler,
+ &this_idata->register_info, /* old */
+ &handler_info->stack_info,
+ this_idata->and_flags,
+ this_idata->or_flags,
+ TRUE);
+ merge_into_one_successor(context, inumber, handler,
+ register_info,
+ &handler_info->stack_info,
+ and_flags, temp_or_flags, TRUE);
+ }
+ }
+ }
+ for (i = 0; i < successors_count; i++) {
+ int target = successors[i];
+// if (target >= context->instruction_count)
+/// CCerror(context, "Falling off the end of the code");
+ merge_into_one_successor(context, inumber, target,
+ register_info, stack_info, and_flags, or_flags,
+ FALSE);
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_into_one_successor
+ * OVERVIEW: Executed an instruction, and have determined a new
+ * set of registers and stack values for a given instruction.
+ * Merge this new set into the values that are already there.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: instruction number
+ * stack_info_type: pointer to stack_info
+ * flag_type: new_and_flags
+ * flag_type: new_or_flags
+ * boolean type: isException
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+merge_into_one_successor(context_type *context,
+ int from_inumber, int to_inumber,
+ register_info_type *new_register_info,
+ stack_info_type *new_stack_info,
+ flag_type new_and_flags, flag_type new_or_flags,
+ bool_t isException)
+{
+ instruction_data_type *idata = context->instruction_data;
+ register_info_type register_info_buf;
+ stack_info_type stack_info_buf;
+ instruction_data_type *this_idata = &idata[to_inumber];
+
+
+ /* All uninitialized objects are set to "bogus" when jsr and
+ * ret are executed. Thus uninitialized objects can't propagate
+ * into or out of a subroutine.
+ */
+ if (idata[from_inumber].opcode == opc_ret ||
+ idata[from_inumber].opcode == opc_jsr ||
+ idata[from_inumber].opcode == opc_jsr_w) {
+ int new_register_count = new_register_info->register_count;
+ fullinfo_type *new_registers = new_register_info->registers;
+ int i;
+ stack_item_type *item;
+
+ for (item = new_stack_info->stack; item != NULL; item = item->next) {
+ if (GET_ITEM_TYPE(item->item) == ITEM_NewObject) {
+ /* This check only succeeds for hand-contrived code.
+ * Efficiency is not an issue.
+ */
+ stack_info_buf.stack = copy_stack(context,
+ new_stack_info->stack);
+ stack_info_buf.stack_size = new_stack_info->stack_size;
+ new_stack_info = &stack_info_buf;
+ for (item = new_stack_info->stack; item != NULL;
+ item = item->next) {
+ if (GET_ITEM_TYPE(item->item) == ITEM_NewObject) {
+ item->item = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ }
+ }
+ break;
+ }
+ }
+ for (i = 0; i < new_register_count; i++) {
+ if (GET_ITEM_TYPE(new_registers[i]) == ITEM_NewObject) {
+ /* This check only succeeds for hand-contrived code.
+ * Efficiency is not an issue.
+ */
+ fullinfo_type *new_set = NEW(fullinfo_type,
+ new_register_count);
+ for (i = 0; i < new_register_count; i++) {
+ fullinfo_type t = new_registers[i];
+ new_set[i] = GET_ITEM_TYPE(t) != ITEM_NewObject ?
+ t : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ }
+ register_info_buf.register_count = new_register_count;
+ register_info_buf.registers = new_set;
+ register_info_buf.mask_count = new_register_info->mask_count;
+ register_info_buf.masks = new_register_info->masks;
+ new_register_info = ®ister_info_buf;
+ break;
+ }
+ }
+ }
+
+ /* Returning from a subroutine is somewhat ugly. The actual thing
+ * that needs to get merged into the new instruction is a joining
+ * of info from the ret instruction with stuff in the jsr instruction
+ */
+ if (idata[from_inumber].opcode == opc_ret && !isException) {
+ int new_register_count = new_register_info->register_count;
+ fullinfo_type *new_registers = new_register_info->registers;
+ int new_mask_count = new_register_info->mask_count;
+ mask_type *new_masks = new_register_info->masks;
+ int operand = idata[from_inumber].operand.i;
+ int called_instruction = GET_EXTRA_INFO(new_registers[operand]);
+ instruction_data_type *jsr_idata = &idata[to_inumber - 1];
+ register_info_type *jsr_reginfo = &jsr_idata->register_info;
+ if (jsr_idata->operand2.i != from_inumber) {
+ // if (jsr_idata->operand2.i != UNKNOWN_RET_INSTRUCTION)
+ // CCerror(context, "Multiple returns to single jsr");
+ jsr_idata->operand2.i = from_inumber;
+ }
+ if (jsr_reginfo->register_count == UNKNOWN_REGISTER_COUNT) {
+ /* We don't want to handle the returned-to instruction until
+ * we've dealt with the jsr instruction. When we get to the
+ * jsr instruction (if ever), we'll re-mark the ret instruction
+ */
+ ;
+ } else {
+ int register_count = jsr_reginfo->register_count;
+ fullinfo_type *registers = jsr_reginfo->registers;
+ int max_registers = MAX(register_count, new_register_count);
+ fullinfo_type *new_set = NEW(fullinfo_type, max_registers);
+ int *return_mask;
+ struct register_info_type new_new_register_info;
+ int i;
+ /* Make sure the place we're returning from is legal! */
+ for (i = new_mask_count; --i >= 0; )
+ if (new_masks[i].entry == called_instruction)
+ break;
+ // if (i < 0)
+ // CCerror(context, "Illegal return from subroutine");
+ /* pop the masks down to the indicated one. Remember the mask
+ * we're popping off. */
+ return_mask = new_masks[i].modifies;
+ new_mask_count = i;
+ for (i = 0; i < max_registers; i++) {
+ if (IS_BIT_SET(return_mask, i))
+ new_set[i] = i < new_register_count ?
+ new_registers[i] : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ else
+ new_set[i] = i < register_count ?
+ registers[i] : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ }
+ new_new_register_info.register_count = max_registers;
+ new_new_register_info.registers = new_set;
+ new_new_register_info.mask_count = new_mask_count;
+ new_new_register_info.masks = new_masks;
+
+ merge_stack(context, to_inumber - 1, to_inumber, new_stack_info);
+ merge_registers(context, to_inumber - 1, to_inumber,
+ &new_new_register_info);
+ /* ADDED FOR JSR_INFO. Is this correct?? */
+ merge_flags(context, from_inumber, to_inumber,
+ new_and_flags, new_or_flags);
+ }
+ } else {
+ merge_stack(context, from_inumber, to_inumber, new_stack_info);
+ merge_registers(context, from_inumber, to_inumber, new_register_info);
+ merge_flags(context, from_inumber, to_inumber,
+ new_and_flags, new_or_flags);
+ }
+
+
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_stack
+ * OVERVIEW: Used by merge_into_one_successor() for merging stack values
+ * from a given instruction to another specified instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: from instruction number
+ * int: to instruction number
+ * stack_info_type: pointer to new_stack_info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+merge_stack(context_type *context, int from_inumber, int to_inumber,
+ stack_info_type *new_stack_info)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[to_inumber];
+
+ int new_stack_size = new_stack_info->stack_size;
+ stack_item_type *new_stack = new_stack_info->stack;
+
+ int stack_size = this_idata->stack_info.stack_size;
+
+ if (stack_size == UNKNOWN_STACK_SIZE) {
+ /* First time at this instruction. Just copy. */
+ this_idata->stack_info.stack_size = new_stack_size;
+ this_idata->stack_info.stack = new_stack;
+ this_idata->changed = TRUE;
+ } else if (new_stack_size != stack_size) {
+// CCerror(context, "Inconsistent stack height %d != %d",
+// new_stack_size, stack_size);
+ } else {
+ stack_item_type *stack = this_idata->stack_info.stack;
+ stack_item_type *old, *new;
+ bool_t change = FALSE;
+ for (old = stack, new = new_stack; old != NULL;
+ old = old->next, new = new->next) {
+ if (!isAssignableTo(context, new->item, old->item)) {
+ change = TRUE;
+ break;
+ }
+ }
+ if (change) {
+ stack = copy_stack(context, stack);
+ for (old = stack, new = new_stack; old != NULL;
+ old = old->next, new = new->next) {
+ if (new == NULL) {
+ break;
+ }
+ old->item = merge_fullinfo_types(context, old->item, new->item,
+ FALSE);
+ if (GET_ITEM_TYPE(old->item) == ITEM_Bogus) {
+ // CCerror(context, "Mismatched stack types");
+ }
+ }
+ if (old != NULL || new != NULL) {
+ // CCerror(context, "Mismatched stack types");
+ }
+ this_idata->stack_info.stack = stack;
+ this_idata->changed = TRUE;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_registers
+ * OVERVIEW: Used by merge_into_one_successor() for merging registers
+ * from a given instruction to another specified instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: from instruction number
+ * int: to instruction number
+ * stack_info_type: pointer to new_stack_info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+merge_registers(context_type *context, int from_inumber, int to_inumber,
+ register_info_type *new_register_info)
+{
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[to_inumber];
+ register_info_type *this_reginfo = &this_idata->register_info;
+
+ int new_register_count = new_register_info->register_count;
+ fullinfo_type *new_registers = new_register_info->registers;
+ int new_mask_count = new_register_info->mask_count;
+ mask_type *new_masks = new_register_info->masks;
+
+
+ if (this_reginfo->register_count == UNKNOWN_REGISTER_COUNT) {
+ this_reginfo->register_count = new_register_count;
+ this_reginfo->registers = new_registers;
+ this_reginfo->mask_count = new_mask_count;
+ this_reginfo->masks = new_masks;
+ this_idata->changed = TRUE;
+ } else {
+ /* See if we've got new information on the register set. */
+ int register_count = this_reginfo->register_count;
+ fullinfo_type *registers = this_reginfo->registers;
+ int mask_count = this_reginfo->mask_count;
+ mask_type *masks = this_reginfo->masks;
+
+ bool_t copy = FALSE;
+ int i, j;
+ if (register_count > new_register_count) {
+ /* Any register larger than new_register_count is now bogus */
+ this_reginfo->register_count = new_register_count;
+ register_count = new_register_count;
+ this_idata->changed = TRUE;
+ }
+ for (i = 0; i < register_count; i++) {
+ fullinfo_type prev_value = registers[i];
+ if ((i < new_register_count)
+ ? (!isAssignableTo(context, new_registers[i], prev_value))
+ : (prev_value != MAKE_FULLINFO(ITEM_Bogus, 0, 0))) {
+ copy = TRUE;
+ break;
+ }
+ }
+
+ if (copy) {
+ /* We need a copy. So do it. */
+ fullinfo_type *new_set = NEW(fullinfo_type, register_count);
+ for (j = 0; j < i; j++)
+ new_set[j] = registers[j];
+ for (j = i; j < register_count; j++) {
+ if (i >= new_register_count)
+ new_set[j] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ else
+ new_set[j] = merge_fullinfo_types(context,
+ new_registers[j],
+ registers[j], FALSE);
+ }
+ /* Some of the end items might now be bogus. This step isn't
+ * necessary, but it may save work later. */
+ while ( register_count > 0
+ && GET_ITEM_TYPE(new_set[register_count-1]) == ITEM_Bogus)
+ register_count--;
+ this_reginfo->register_count = register_count;
+ this_reginfo->registers = new_set;
+ this_idata->changed = TRUE;
+ }
+ if (mask_count > 0) {
+ /* If the target instruction already has a sequence of masks, then
+ * we need to merge new_masks into it. We want the entries on
+ * the mask to be the longest common substring of the two.
+ * (e.g. a->b->d merged with a->c->d should give a->d)
+ * The bits set in the mask should be the or of the corresponding
+ * entries in each of the original masks.
+ */
+ int i, j, k;
+ int matches = 0;
+ int last_match = -1;
+ bool_t copy_needed = FALSE;
+ for (i = 0; i < mask_count; i++) {
+ int entry = masks[i].entry;
+ for (j = last_match + 1; j < new_mask_count; j++) {
+ if (new_masks[j].entry == entry) {
+ /* We have a match */
+ int *prev = masks[i].modifies;
+ int *new = new_masks[j].modifies;
+ matches++;
+ /* See if new_mask has bits set for "entry" that
+ * weren't set for mask. If so, need to copy. */
+ for (k = context->bitmask_size - 1;
+ !copy_needed && k >= 0;
+ k--)
+ if (~prev[k] & new[k])
+ copy_needed = TRUE;
+ last_match = j;
+ break;
+ }
+ }
+ }
+ if ((matches < mask_count) || copy_needed) {
+ /* We need to make a copy for the new item, since either the
+ * size has decreased, or new bits are set. */
+ mask_type *copy = NEW(mask_type, matches);
+ for (i = 0; i < matches; i++) {
+ copy[i].modifies = NEW(int, context->bitmask_size);
+ }
+ this_reginfo->masks = copy;
+ this_reginfo->mask_count = matches;
+ this_idata->changed = TRUE;
+ matches = 0;
+ last_match = -1;
+ for (i = 0; i < mask_count; i++) {
+ int entry = masks[i].entry;
+ for (j = last_match + 1; j < new_mask_count; j++) {
+ if (new_masks[j].entry == entry) {
+ int *prev1 = masks[i].modifies;
+ int *prev2 = new_masks[j].modifies;
+ int *new = copy[matches].modifies;
+ copy[matches].entry = entry;
+ for (k = context->bitmask_size - 1; k >= 0; k--)
+ new[k] = prev1[k] | prev2[k];
+ matches++;
+ last_match = j;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_flags
+ * OVERVIEW: Used by merge_into_one_successor() for merging flags
+ * from a given instruction to a specified instruction.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: from instruction number
+ * int: to instruction number
+ * flag_type: new_and_flags
+ * flag_type: new_or_flags
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+merge_flags(context_type *context, int from_inumber, int to_inumber,
+ flag_type new_and_flags, flag_type new_or_flags)
+{
+ /* Set this_idata->and_flags &= new_and_flags
+ this_idata->or_flags |= new_or_flags
+ */
+ instruction_data_type *idata = context->instruction_data;
+ instruction_data_type *this_idata = &idata[to_inumber];
+ flag_type this_and_flags = this_idata->and_flags;
+ flag_type this_or_flags = this_idata->or_flags;
+ flag_type merged_and = this_and_flags & new_and_flags;
+ flag_type merged_or = this_or_flags | new_or_flags;
+
+ if ((merged_and != this_and_flags) || (merged_or != this_or_flags)) {
+ this_idata->and_flags = merged_and;
+ this_idata->or_flags = merged_or;
+ this_idata->changed = TRUE;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: copy_stack
+ * OVERVIEW: Make a copy of a stack.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * stack_item_type: pointer to stack
+ *
+ * returns: pointer to stack_item_type
+ *=======================================================================*/
+static stack_item_type *
+copy_stack(context_type *context, stack_item_type *stack)
+{
+ int length;
+ stack_item_type *ptr;
+
+ /* Find the length */
+ for (ptr = stack, length = 0; ptr != NULL; ptr = ptr->next, length++);
+
+ if (length > 0) {
+ stack_item_type *new_stack = NEW(stack_item_type, length);
+ stack_item_type *new_ptr;
+ for ( ptr = stack, new_ptr = new_stack;
+ ptr != NULL;
+ ptr = ptr->next, new_ptr++) {
+ new_ptr->item = ptr->item;
+ new_ptr->next = new_ptr + 1;
+ }
+ new_stack[length - 1].next = NULL;
+ return new_stack;
+ } else {
+ return NULL;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: copy_masks
+ * OVERVIEW: Make a copy of the masks.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * mask_type: pointer to masks
+ * int: mask count
+ *
+ * returns: pointer to mask_type
+ *=======================================================================*/
+static mask_type *
+copy_masks(context_type *context, mask_type *masks, int mask_count)
+{
+ mask_type *result = NEW(mask_type, mask_count);
+ int bitmask_size = context->bitmask_size;
+ int *bitmaps = NEW(int, mask_count * bitmask_size);
+ int i;
+ for (i = 0; i < mask_count; i++) {
+ result[i].entry = masks[i].entry;
+ result[i].modifies = &bitmaps[i * bitmask_size];
+ memcpy(result[i].modifies, masks[i].modifies, bitmask_size * sizeof(int));
+ }
+ return result;
+}
+
+
+/*=========================================================================
+ * FUNCTION: add_to_masks
+ * OVERVIEW: Used by Update_registers for adding entries to masks for
+ * JSR instructions.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * mask_type: pointer to masks
+ * int: mask count
+ * int: d
+ *
+ * returns: pointer to mask_type
+ *=======================================================================*/
+static mask_type *
+add_to_masks(context_type *context, mask_type *masks, int mask_count, int d)
+{
+ mask_type *result = NEW(mask_type, mask_count + 1);
+ int bitmask_size = context->bitmask_size;
+ int *bitmaps = NEW(int, (mask_count + 1) * bitmask_size);
+ int i;
+ for (i = 0; i < mask_count; i++) {
+ result[i].entry = masks[i].entry;
+ result[i].modifies = &bitmaps[i * bitmask_size];
+ memcpy(result[i].modifies, masks[i].modifies, bitmask_size * sizeof(int));
+ }
+ result[mask_count].entry = d;
+ result[mask_count].modifies = &bitmaps[mask_count * bitmask_size];
+ memset(result[mask_count].modifies, 0, bitmask_size * sizeof(int));
+ return result;
+}
+
+
+/*=========================================================================
+ * Storage Management Operations
+ *=======================================================================*/
+
+/* We create our own storage manager, since we malloc lots of little items,
+ * and we do not want to keep track of them when they become free.
+ * It would have been nice if we had heaps, which could all be freed when
+ * done.
+ */
+
+#define CCSegSize 2000
+
+struct CCpool { /* a segment of allocated memory in the pool */
+ struct CCpool *next;
+ int segSize; /* almost always CCSegSize */
+ char space[CCSegSize];
+};
+
+
+/*=========================================================================
+ * FUNCTION: CCinit
+ * OVERVIEW: Initialize the context's heap.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void CCinit(context_type *context)
+{
+ struct CCpool *new = (struct CCpool *) sysMalloc(sizeof(struct CCpool));
+ /* Set context->CCroot to 0 if new == 0 to tell CCdestroy to lay off */
+ context->CCroot = context->CCcurrent = new;
+ if (new == 0) {
+ CCerror(context, "Out of memory");
+ }
+ new->next = NULL;
+ new->segSize = CCSegSize;
+ context->CCfree_size = CCSegSize;
+ context->CCfree_ptr = &new->space[0];
+}
+
+
+/*=========================================================================
+ * FUNCTION: CCreinit
+ * OVERVIEW: Reuse all the space that we have in the context's heap.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void CCreinit(context_type *context)
+{
+ struct CCpool *first = context->CCroot;
+ context->CCcurrent = first;
+ context->CCfree_size = CCSegSize;
+ context->CCfree_ptr = &first->space[0];
+}
+
+
+/*=========================================================================
+ * FUNCTION: CCdestroy
+ * OVERVIEW: Destroy the context's heap.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void CCdestroy(context_type *context)
+{
+ struct CCpool *this = context->CCroot;
+ while (this) {
+ struct CCpool *next = this->next;
+ sysFree(this);
+ this = next;
+ }
+ /* These two aren't necessary. But can't hurt either */
+ context->CCroot = context->CCcurrent = NULL;
+ context->CCfree_ptr = 0;
+}
+
+
+/*=========================================================================
+ * FUNCTION: CCalloc
+ * OVERVIEW: Allocate an object of the given size from the context's heap.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: size
+ * bool_t: zero
+ *
+ * returns: pointer to void
+ *=======================================================================*/
+static void *
+CCalloc(context_type *context, int size, bool_t zero)
+{
+
+ register char *p;
+ /* Round CC to the size of a pointer */
+ size = (size + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1);
+
+ if (context->CCfree_size < size) {
+ struct CCpool *current = context->CCcurrent;
+ struct CCpool *new;
+ if (size > CCSegSize) { /* we need to allocate a special block */
+ new = (struct CCpool *)sysMalloc(sizeof(struct CCpool) +
+ (size - CCSegSize));
+ if (new == 0) {
+ CCerror(context, "Out of memory");
+ }
+ new->next = current->next;
+ new->segSize = size;
+ current->next = new;
+ } else {
+ new = current->next;
+ if (new == NULL) {
+ new = (struct CCpool *) sysMalloc(sizeof(struct CCpool));
+ if (new == 0) {
+ CCerror(context, "Out of memory");
+ }
+ current->next = new;
+ new->next = NULL;
+ new->segSize = CCSegSize;
+ }
+ }
+ context->CCcurrent = new;
+ context->CCfree_ptr = &new->space[0];
+ context->CCfree_size = new->segSize;
+ }
+ p = context->CCfree_ptr;
+ context->CCfree_ptr += size;
+ context->CCfree_size -= size;
+ if (zero)
+ memset(p, 0, size);
+ return p;
+}
+
+
+/*=========================================================================
+ * FUNCTION: cp_index_to_signature
+ * OVERVIEW: Get the signature associated with a particular field or
+ * method in the constant pool.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: constant pool index
+ *
+ * returns: char * type
+ *=======================================================================*/
+static char *
+cp_index_to_signature(context_type *context, int cp_index)
+{
+ union cp_item_type *cp = cbConstantPool(context->class);
+ int index = cp[cp_index].i; /* value of Fieldref field */
+ int key2 = index & 0xFFFF; /* index to NameAndType */
+ int signature_index = cp[key2].i & 0xFFFF;
+ char *signature = cp[signature_index].cp;
+ return signature;
+}
+
+
+/*=========================================================================
+ * FUNCTION: cp_index_to_fieldname
+ * OVERVIEW: Get the fieldname for the specific index within the
+ * constant pool.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: constant pool index
+ *
+ * returns: char * type
+ *=======================================================================*/
+static char *
+cp_index_to_fieldname(context_type *context, int cp_index)
+{
+ union cp_item_type *cp = cbConstantPool(context->class);
+ int index = cp[cp_index].i; /* value of Fieldref field */
+ int key2 = index & 0xFFFF; /* index to NameAndType */
+ int name_index = cp[key2].i >> 16;
+ return cp[name_index].cp;
+}
+
+
+/*=========================================================================
+ * FUNCTION: cp_index_to_class_fullinfo
+ * OVERVIEW: Get the class associated with a particular field or
+ * method or class in the constant pool. If is_field is true,
+ * then it is a field or method. Otherwise, if false, it is a
+ * class.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: constant pool index
+ * bool_t: is_field
+ *
+ * returns: fullinfo_type
+ *=======================================================================*/
+static fullinfo_type
+cp_index_to_class_fullinfo(context_type *context, int cp_index, bool_t is_field)
+{
+ union cp_item_type *cp = cbConstantPool(context->class);
+ unsigned classkey = is_field ? (cp[cp_index].i >> 16) : cp_index;
+ char *classname = GetClassConstantClassName(cp, classkey);
+ if (classname[0] == SIGNATURE_ARRAY) {
+ fullinfo_type result;
+ /* This make recursively call us, in case of a class array */
+ signature_to_fieldtype(context, &classname, &result);
+ return result;
+ } else {
+ return MAKE_CLASSNAME_INFO_WITH_COPY(context, classname, 0);
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: CCerror
+ * OVERVIEW: Error handling
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * char: pointer to format
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+CCerror (context_type *context, char *format, ...)
+{
+/* va_list args;
+ struct methodblock *mb = context->mb;
+ printCurrentClassName();
+ if (mb != 0) {
+ jio_fprintf(stderr, "VERIFIER ERROR %s.%s%s:\n",
+ cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature);
+ } else {
+ jio_fprintf(stderr, "VERIFIER ERROR class %s (mb uninitialized):\n",
+ cbName(context->class));
+ }
+ va_start(args, format);
+ jio_vfprintf(stderr, format, args);
+ va_end(args);
+ jio_fprintf(stderr, "\n");
+ exit(1);*/
+}
+
+
+/*=========================================================================
+ * FUNCTION: signature_to_fieldtype
+ * OVERVIEW: Given the full info type for a field, returns the field type
+ * which corresponds to this signature.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * char: **signature_p
+ * fullinfo_type: *full_info_p
+ *
+ * returns: char
+ *=======================================================================*/
+static char
+signature_to_fieldtype(context_type *context,
+ char **signature_p, fullinfo_type *full_info_p)
+{
+ char *p = *signature_p;
+ fullinfo_type full_info = MAKE_FULLINFO(0, 0, 0);
+ char result;
+ int array_depth = 0;
+
+ for (;;) {
+ switch(*p++) {
+ default:
+ full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ result = 0;
+ break;
+
+ case SIGNATURE_BYTE:
+ full_info = (array_depth > 0)
+ ? MAKE_FULLINFO(ITEM_Byte, 0, 0)
+ : MAKE_FULLINFO(ITEM_Integer, 0, 0);
+ result = 'I';
+ break;
+
+ case SIGNATURE_BOOLEAN:
+ full_info = (array_depth > 0)
+ ? MAKE_FULLINFO(ITEM_Boolean, 0, 0)
+ : MAKE_FULLINFO(ITEM_Integer, 0, 0);
+ result = 'I';
+ break;
+
+ case SIGNATURE_CHAR:
+ full_info = (array_depth > 0)
+ ? MAKE_FULLINFO(ITEM_Char, 0, 0)
+ : MAKE_FULLINFO(ITEM_Integer, 0, 0);
+ result = 'I';
+ break;
+
+ case SIGNATURE_SHORT:
+ full_info = (array_depth > 0)
+ ? MAKE_FULLINFO(ITEM_Short, 0, 0)
+ : MAKE_FULLINFO(ITEM_Integer, 0, 0);
+ result = 'I';
+ break;
+
+ case SIGNATURE_INT:
+ full_info = MAKE_FULLINFO(ITEM_Integer, 0, 0);
+ result = 'I';
+ break;
+
+ case SIGNATURE_FLOAT:
+ full_info = MAKE_FULLINFO(ITEM_Float, 0, 0);
+ result = 'F';
+ break;
+
+ case SIGNATURE_DOUBLE:
+ full_info = MAKE_FULLINFO(ITEM_Double, 0, 0);
+ result = 'D';
+ break;
+
+ case SIGNATURE_LONG:
+ full_info = MAKE_FULLINFO(ITEM_Long, 0, 0);
+ result = 'L';
+ break;
+
+ case SIGNATURE_ARRAY:
+ array_depth++;
+ continue; /* only time we ever do the loop > 1 */
+
+ case SIGNATURE_CLASS: {
+ char buffer_space[256];
+ char *buffer = buffer_space;
+ char *finish = strchr(p, SIGNATURE_ENDCLASS);
+ int length = finish - p;
+ if (length + 1 > sizeof(buffer_space)) {
+ buffer = sysMalloc(length + 1);
+ if (buffer == 0) {
+ // CCerror(context, "Out of memory");
+ }
+ }
+ memcpy(buffer, p, length);
+ buffer[length] = '\0';
+ full_info = MAKE_CLASSNAME_INFO_WITH_COPY(context, buffer, 0);
+ result = 'A';
+ p = finish + 1;
+ if (buffer != buffer_space)
+ sysFree(buffer);
+ break;
+ }
+ } /* end of switch */
+ break;
+ }
+ *signature_p = p;
+ if (array_depth == 0 || result == 0) {
+ /* either not an array, or result is bogus */
+ *full_info_p = full_info;
+ return result;
+ } else {
+// if (array_depth > MAX_ARRAY_DIMENSIONS)
+// CCerror(context, "Array with too many dimensions");
+ *full_info_p = MAKE_FULLINFO(GET_ITEM_TYPE(full_info),
+ array_depth,
+ GET_EXTRA_INFO(full_info));
+ return 'A';
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: decrement_indirection
+ * OVERVIEW: Given an array type, create the type that has one less
+ * level of indirection.
+ * INTERFACE:
+ * parameters: fullinfo_type array_info
+ *
+ * returns: fullinfo_type
+ *=======================================================================*/
+static fullinfo_type
+decrement_indirection(fullinfo_type array_info)
+{
+ if (array_info == NULL_FULLINFO) {
+ return NULL_FULLINFO;
+ } else {
+ int type = GET_ITEM_TYPE(array_info);
+ int indirection = GET_INDIRECTION(array_info) - 1;
+ int extra_info = GET_EXTRA_INFO(array_info);
+ if ( (indirection == 0)
+ && ((type == ITEM_Short || type == ITEM_Byte || type == ITEM_Boolean || type == ITEM_Char)))
+ type = ITEM_Integer;
+ return MAKE_FULLINFO(type, indirection, extra_info);
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: isAssignableTo
+ * OVERVIEW: Given an object of the "from" type, determine if it can be
+ * assigned to an object of the "to" type.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * fullinfo_type: from
+ * fullinfo_type: to
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static bool_t isAssignableTo(context_type *context,
+ fullinfo_type from, fullinfo_type to)
+{
+ return (merge_fullinfo_types(context, from, to, TRUE) == to);
+}
+
+
+/*=========================================================================
+ * FUNCTION: merge_fullinfo_types
+ * OVERVIEW: Given two fullinfo_types, find their lowest common deno-
+ * minator. If the assignable_p argument is non-null, we are
+ * really just calling to find out if "<target> := <value>"
+ * is a legitimate assignment.
+ * We treat all interfaces as if they were of type '
+ * java/lang/Object, since the runtime will do the full
+ * checking.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * fullinfo_type: value
+ * fullinfo_type: target
+ * bool_t for_assignment
+ *
+ * returns: fullinfo_type
+ *=======================================================================*/
+static fullinfo_type
+merge_fullinfo_types(context_type *context,
+ fullinfo_type value, fullinfo_type target,
+ bool_t for_assignment)
+{
+ if (value == target) {
+ /* If they're identical, clearly just return what we've got */
+ return value;
+ }
+
+ /* Both must be either arrays or objects to go further */
+ if (GET_INDIRECTION(value) == 0 && GET_ITEM_TYPE(value) != ITEM_Object)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ if (GET_INDIRECTION(target) == 0 && GET_ITEM_TYPE(target) != ITEM_Object)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+
+ /* If either is NULL, return the other. */
+ if (value == NULL_FULLINFO)
+ return target;
+ else if (target == NULL_FULLINFO)
+ return value;
+
+ /* If either is java/lang/Object, that's the result. */
+ if (target == context->object_info)
+ return target;
+ else if (value == context->object_info) {
+ /* Minor hack. For assignments, Interface := Object, return Interface
+ * rather than Object, so that isAssignableTo() will get the right
+ * result. */
+ if (for_assignment && (WITH_ZERO_EXTRA_INFO(target) ==
+ MAKE_FULLINFO(ITEM_Object, 0, 0))) {
+ ClassClass *cb = object_fullinfo_to_classclass(context, target);
+ if (cb && cbIsInterface(cb))
+ return target;
+ }
+ return value;
+ }
+ if (GET_INDIRECTION(value) > 0 || GET_INDIRECTION(target) > 0) {
+ /* At least one is an array. Neither is java/lang/Object or NULL.
+ * Moreover, the types are not identical.
+ * The result must either be Object, or an array of some object type.
+ */
+ int dimen_value = GET_INDIRECTION(value);
+ int dimen_target = GET_INDIRECTION(target);
+
+ /* First, if either item's base type isn't ITEM_Object, promote it up
+ * to an object or array of object. If either is elemental, we can
+ * punt.
+ */
+ if (GET_ITEM_TYPE(value) != ITEM_Object) {
+ if (dimen_value == 0)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ dimen_value--;
+ value = MAKE_Object_ARRAY(dimen_value);
+
+ }
+ if (GET_ITEM_TYPE(target) != ITEM_Object) {
+ if (dimen_target == 0)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ dimen_target--;
+ target = MAKE_Object_ARRAY(dimen_target);
+ }
+ /* Both are now objects or arrays of some sort of object type */
+ if (dimen_value == dimen_target) {
+ /* Arrays of the same dimension. Merge their base types. */
+ fullinfo_type value_base = WITH_ZERO_INDIRECTION(value);
+ fullinfo_type target_base = WITH_ZERO_INDIRECTION(target);
+ fullinfo_type result_base =
+ merge_fullinfo_types(context, value_base, target_base,
+ for_assignment);
+ if (result_base == MAKE_FULLINFO(ITEM_Bogus, 0, 0))
+ /* bogus in, bogus out */
+ return result_base;
+ return MAKE_FULLINFO(ITEM_Object, dimen_value,
+ GET_EXTRA_INFO(result_base));
+ } else {
+ /* Arrays of different sizes. Return Object, with a dimension
+ * of the smaller of the two.
+ */
+ int dimen = dimen_value < dimen_target ? dimen_value : dimen_target;
+ return MAKE_Object_ARRAY(dimen);
+ }
+ } else {
+ /* Both are non-array objects. Neither is java/lang/Object or NULL */
+ ClassClass *cb_value, *cb_target, *cb_super_value, *cb_super_target;
+ void **addr;
+ int value_info;
+
+ /* Let's get the classes corresponding to each of these. Treat
+ * interfaces as if they were java/lang/Object. See hack note above. */
+ cb_target = object_fullinfo_to_classclass(context, target);
+ if (cb_target == 0)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ if (cbIsInterface(cb_target))
+ return for_assignment ? target : context->object_info;
+ cb_value = object_fullinfo_to_classclass(context, value);
+ if (cb_value == 0)
+ return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
+ if (cbIsInterface(cb_value))
+ return context->object_info;
+
+ /* If this is for assignment of target := value, we just need to see if
+ * cb_target is a superclass of cb_value. Save ourselves a lot of
+ * work.
+ */
+ if (for_assignment) {
+ for (cb_super_value = cb_value;
+ cbSuperclass(cb_super_value) != NULL;
+ cb_super_value = cbSuperclass(cb_super_value)) {
+ if (cb_super_value == cb_target) {
+ return target;
+ }
+ }
+ return context->object_info;
+ }
+
+ /* Find out whether cb_value or cb_target is deeper in the class
+ * tree by moving both toward the root, and seeing who gets there
+ * first. */
+ for (cb_super_value = cb_value, cb_super_target = cb_target;
+ cbSuperclass(cb_super_value) && cbSuperclass(cb_super_target); ) {
+ /* Optimization. If either hits the other when going up looking
+ * for a parent, then might as well return the parent immediately */
+ if (cb_super_value == cb_target)
+ return target;
+ if (cb_super_target == cb_value)
+ return value;
+ cb_super_value= cbSuperclass(cb_super_value);
+ cb_super_target = cbSuperclass(cb_super_target);
+ }
+ /* At most one of the following two while clauses will be executed.
+ * Bring the deeper of cb_target and cb_value to the depth of the
+ * shallower one.
+ */
+ while (cbSuperclass(cb_super_value)) { /* cb_value is deeper */
+ cb_super_value= cbSuperclass(cb_super_value);
+ cb_value= cbSuperclass(cb_value);
+ }
+ while (cbSuperclass(cb_super_target)) { /* cb_target is deeper */
+ cb_super_target= cbSuperclass(cb_super_target);
+ cb_target = cbSuperclass(cb_target);
+ }
+
+ /* Walk both up, maintaining equal depth, until a join is found. We
+ * know that we will find one. */
+ while (cb_value != cb_target) {
+ cb_value = cbSuperclass(cb_value);
+ cb_target = cbSuperclass(cb_target);
+ }
+ /* Get the info for this guy. We know its cb_value, so we should
+ * fill that in, while we're at it. */
+ value_info = Str2ID_Local(context, &context->classHash,
+ cbName(cb_value), &addr, TRUE);
+ *addr = cb_value;
+ return MAKE_FULLINFO(ITEM_Object, 0, value_info);
+ } /* both items are classes */
+}
+
+
+/*=========================================================================
+ * FUNCTION: object_fullinfo_to_classclass
+ * OVERVIEW: Given a fullinfo_type corresponding to an Object, return the
+ * pointer to the ClassClass structure of that type.
+ * Returns 0 for an illegal class.
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * fullinfo_type: classinfo
+ *
+ * returns: pointer to the ClassClass type
+ *=======================================================================*/
+static ClassClass *
+object_fullinfo_to_classclass(context_type *context, fullinfo_type classinfo)
+{
+ void **addr;
+ ClassClass *cb;
+
+ unsigned short info = GET_EXTRA_INFO(classinfo);
+ char *classname = ID2Str_Local(context, context->classHash, info, &addr);
+ if ((cb = *addr) != 0) {
+ return cb;
+ } else {
+ *addr = cb = FindClassFromClass(0, classname, FALSE, context->class);
+// if (cb == 0)
+// CCerror(context, "Cannot find class %s", classname);
+ return cb;
+ }
+}
+
+
+/*=========================================================================
+ * The functions below are for debugging the preverifier
+ *=======================================================================*/
+
+#ifdef DEBUG_VERIFIER
+
+static void print_fullinfo_type(context_type *, fullinfo_type, bool_t);
+
+
+/*=========================================================================
+ * FUNCTION: print_stack
+ * OVERVIEW: Prints stack information.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * stack_info: pointer to stack_info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+print_stack(context_type *context, stack_info_type *stack_info)
+{
+ stack_item_type *stack = stack_info->stack;
+ if (stack_info->stack_size == UNKNOWN_STACK_SIZE) {
+ jio_fprintf(stdout, "x");
+ } else {
+ jio_fprintf(stdout, "(");
+ for ( ; stack != 0; stack = stack->next)
+ print_fullinfo_type(context, stack->item, verify_verbose > 1);
+ jio_fprintf(stdout, ")");
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: print_registers
+ * OVERVIEW: Prints registers.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * register_info_type: pointer to register_info
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+print_registers(context_type *context, register_info_type *register_info)
+{
+ int register_count = register_info->register_count;
+ if (register_count == UNKNOWN_REGISTER_COUNT) {
+ jio_fprintf(stdout, "x");
+ } else {
+ fullinfo_type *registers = register_info->registers;
+ int mask_count = register_info->mask_count;
+ mask_type *masks = register_info->masks;
+ int i, j;
+
+ jio_fprintf(stdout, "{");
+ for (i = 0; i < register_count; i++)
+ print_fullinfo_type(context, registers[i], verify_verbose > 1);
+ jio_fprintf(stdout, "}");
+ for (i = 0; i < mask_count; i++) {
+ char *separator = "";
+ int *modifies = masks[i].modifies;
+ jio_fprintf(stdout, "<%d: ", masks[i].entry);
+ for (j = 0; j < context->mb->nlocals; j++)
+ if (IS_BIT_SET(modifies, j)) {
+ jio_fprintf(stdout, "%s%d", separator, j);
+ separator = ",";
+ }
+ jio_fprintf(stdout, ">");
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: print_flags
+ * OVERVIEW: Prints flags.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * flag_type: and_flags
+ * flag_type: or_flags
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+print_flags(context_type *context, flag_type and_flags, flag_type or_flags)
+{
+ if (and_flags != ((flag_type)-1) || or_flags != 0) {
+ jio_fprintf(stdout, "<%x %x>", and_flags, or_flags);
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: print_fullinfo_type
+ * OVERVIEW: Prints fullinfo_type information.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * fullinfo_type: type
+ * bool_t verbose
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+print_fullinfo_type(context_type *context, fullinfo_type type, bool_t verbose)
+{
+ int i;
+ int indirection = GET_INDIRECTION(type);
+ for (i = indirection; i-- > 0; )
+ jio_fprintf(stdout, "[");
+ switch (GET_ITEM_TYPE(type)) {
+ case ITEM_Integer:
+ jio_fprintf(stdout, "I"); break;
+ case ITEM_Float:
+ jio_fprintf(stdout, "F"); break;
+ case ITEM_Double:
+ jio_fprintf(stdout, "D"); break;
+ case ITEM_Double_2:
+ jio_fprintf(stdout, "d"); break;
+ case ITEM_Long:
+ jio_fprintf(stdout, "L"); break;
+ case ITEM_Long_2:
+ jio_fprintf(stdout, "l"); break;
+ case ITEM_ReturnAddress:
+ jio_fprintf(stdout, "a"); break;
+ case ITEM_Object:
+ if (!verbose) {
+ jio_fprintf(stdout, "A");
+ } else {
+ unsigned short extra = GET_EXTRA_INFO(type);
+ if (extra == 0) {
+ jio_fprintf(stdout, "/Null/");
+ } else {
+ char *name = ID2Str_Local(context, context->classHash,
+ extra, 0);
+ char *name2 = strrchr(name, '/');
+ jio_fprintf(stdout, "/%s/", name2 ? name2 + 1 : name);
+ }
+ }
+ break;
+ case ITEM_Char:
+ jio_fprintf(stdout, "C"); break;
+ case ITEM_Short:
+ jio_fprintf(stdout, "S"); break;
+ case ITEM_Byte:
+ jio_fprintf(stdout, "B"); break;
+ case ITEM_Boolean:
+ jio_fprintf(stdout, "Z"); break;
+ case ITEM_NewObject:
+ if (!verbose) {
+ jio_fprintf(stdout, "@");
+ } else {
+ int inum = GET_EXTRA_INFO(type);
+ fullinfo_type real_type =
+ context->instruction_data[inum].operand2.fi;
+ jio_fprintf(stdout, ">");
+ print_fullinfo_type(context, real_type, TRUE);
+ jio_fprintf(stdout, "<");
+ }
+ break;
+ case ITEM_InitObject:
+ jio_fprintf(stdout, verbose ? ">/this/<" : "@");
+ break;
+
+ default:
+ jio_fprintf(stdout, "?"); break;
+ }
+ for (i = indirection; i-- > 0; )
+ jio_fprintf(stdout, "]");
+}
+
+
+/*=========================================================================
+ * FUNCTION: print_formatted_fieldname
+ * OVERVIEW: Prints formatted fieldname associated with the given
+ * index within the constant pool.
+ *
+ * INTERFACE:
+ * parameters: pointer to the context_type
+ * int: index
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+print_formatted_fieldname(context_type *context, int index)
+{
+ union cp_item_type *constant_pool = cbConstantPool(context->class);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ unsigned type = CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index);
+
+ unsigned key = constant_pool[index].i;
+ unsigned classkey = key >> 16;
+ unsigned nametypekey = key & 0xFFFF;
+ unsigned nametypeindex = constant_pool[nametypekey].i;
+ unsigned fieldnameindex = nametypeindex >> 16;
+ unsigned fieldtypeindex = nametypeindex & 0xFFFF;
+ jio_fprintf(stdout, " <%s.%s%s%s>",
+ GetClassConstantClassName(constant_pool, classkey),
+ constant_pool[fieldnameindex].cp,
+ type == CONSTANT_Fieldref ? " " : "",
+ constant_pool[fieldtypeindex].cp);
+}
+
+#endif /*DEBUG_VERIFIER*/
+
diff --git a/MPC.3.5.LINUX/preverifier/check_code.h b/MPC.3.5.LINUX/preverifier/check_code.h
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * @(#)check_code.h 1.3 02/09/27
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#include <setjmp.h>
+
+#include "oobj.h"
+#include "opcodes.h"
+#include "tree.h"
+#include "sys_api.h"
+
+#define MAX_ARRAY_DIMENSIONS 255
+
+
+#define UNKNOWN_STACK_SIZE -1
+#define UNKNOWN_REGISTER_COUNT -1
+#define UNKNOWN_RET_INSTRUCTION -1
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#define BITS_PER_INT (CHAR_BIT * sizeof(int)/sizeof(char))
+#define SET_BIT(flags, i) (flags[(i)/BITS_PER_INT] |= \
+ ((unsigned)1 << ((i) % BITS_PER_INT)))
+#define IS_BIT_SET(flags, i) (flags[(i)/BITS_PER_INT] & \
+ ((unsigned)1 << ((i) % BITS_PER_INT)))
+
+typedef unsigned long fullinfo_type;
+typedef unsigned int *bitvector;
+
+#define GET_ITEM_TYPE(thing) ((thing) & 0x1F)
+#define GET_INDIRECTION(thing) (((thing) & 0xFFFF) >> 5)
+#define GET_EXTRA_INFO(thing) ((unsigned short)((thing) >> 16))
+#define WITH_ZERO_INDIRECTION(thing) ((thing) & ~(0xFFE0))
+#define WITH_ZERO_EXTRA_INFO(thing) ((thing) & 0xFFFF)
+
+#define MAKE_FULLINFO(type, indirect, extra) \
+ ((fullinfo_type)((type) + ((indirect) << 5) + ((extra) << 16)))
+#define MAKE_CLASSNAME_INFO(context, classname, addr) \
+ MAKE_FULLINFO(ITEM_Object, 0, \
+ Str2ID_Local(context, &context->classHash, (classname), (addr), FALSE))
+#define MAKE_CLASSNAME_INFO_WITH_COPY(context, classname, addr) \
+ MAKE_FULLINFO(ITEM_Object, 0, \
+ Str2ID_Local(context, &context->classHash, (classname), (addr), TRUE))
+#define MAKE_Object_ARRAY(indirect) \
+ (context->object_info + ((indirect) << 5))
+
+#define NULL_FULLINFO MAKE_FULLINFO(ITEM_Object, 0, 0)
+
+/* opc_invokespecial calls to <init> need to be treated special */
+#define opc_invokeinit 0x100
+
+struct context_type {
+ /* these fields are per class */
+ ClassClass *class; /* current class */
+ struct StrIDhash *classHash;
+ fullinfo_type object_info; /* fullinfo for java/lang/Object */
+ fullinfo_type string_info; /* fullinfo for java/lang/String */
+ fullinfo_type throwable_info; /* fullinfo for java/lang/Throwable */
+
+ fullinfo_type currentclass_info; /* fullinfo for context->class */
+ fullinfo_type superclass_info; /* fullinfo for superclass */
+
+ /* these fields are per method */
+ struct methodblock *mb; /* current method */
+ unsigned char *code; /* current code object */
+ short *code_data; /* offset to instruction number */
+ struct instruction_data_type *instruction_data; /* info about each */
+ struct handler_info_type *handler_info;
+ fullinfo_type *superClasses; /* null terminated superclasses */
+ int instruction_count; /* number of instructions */
+ fullinfo_type return_type; /* function return type */
+ fullinfo_type swap_table[4]; /* used for passing information */
+ int bitmask_size; /* words needed to hold bitmap of arguments */
+
+ /* Used by inliner */
+ bool_t redoJsr;
+
+ /* Used by the space allocator */
+ struct CCpool *CCroot, *CCcurrent;
+ char *CCfree_ptr;
+ int CCfree_size;
+
+ /* Jump here on any error. */
+ jmp_buf jump_buffer;
+};
+
+struct stack_info_type {
+ struct stack_item_type *stack;
+ int stack_size;
+};
+
+struct register_info_type {
+ int register_count; /* number of registers used */
+ fullinfo_type *registers;
+ int mask_count; /* number of masks in the following */
+ struct mask_type *masks;
+};
+
+struct mask_type {
+ int entry;
+ int *modifies;
+};
+
+typedef unsigned short flag_type;
+
+struct instruction_data_type {
+ opcode_type opcode; /* may turn into "canonical" opcode */
+ unsigned changed:1; /* has it changed */
+ unsigned protected:1; /* must accessor be a subclass of "this" */
+ unsigned is_target:1;
+
+ union {
+ int i; /* operand to the opcode */
+ int *ip;
+ fullinfo_type fi;
+ } operand, operand2;
+ fullinfo_type p;
+ struct stack_info_type stack_info;
+ struct register_info_type register_info;
+#define FLAG_REACHED 0x01 /* instruction reached */
+#define FLAG_NEED_CONSTRUCTOR 0x02 /* must call this.<init> or super.<init> */
+#define FLAG_NO_RETURN 0x04 /* must throw out of method */
+ flag_type or_flags; /* true for at least one path to this inst */
+#define FLAG_CONSTRUCTED 0x01 /* this.<init> or super.<init> called */
+ flag_type and_flags; /* true for all paths to this instruction */
+ unsigned short offset;
+ unsigned short length;
+};
+
+struct handler_info_type {
+ int start, end, handler;
+ struct stack_info_type stack_info;
+};
+
+struct stack_item_type {
+ fullinfo_type item;
+ struct stack_item_type *next;
+};
+
+
+typedef struct context_type context_type;
+typedef struct instruction_data_type instruction_data_type;
+typedef struct stack_item_type stack_item_type;
+typedef struct register_info_type register_info_type;
+typedef struct stack_info_type stack_info_type;
+typedef struct mask_type mask_type;
diff --git a/MPC.3.5.LINUX/preverifier/classloader.c b/MPC.3.5.LINUX/preverifier/classloader.c
--- /dev/null
@@ -0,0 +1,1783 @@
+/*
+ * @(#)classloader.c 1.37 02/09/27
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: class loader.
+ * FILE: classloader.c
+ * OVERVIEW: Routines for loading and resolving class definitions.
+ * These routines should not be depending upon the interpreter
+ * or the garbage collector.
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Modifications for JAR support and comments,
+ * Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#include "jar.h"
+#include "oobj.h"
+#include "path.h"
+#include "tree.h"
+#include "signature.h"
+#include "convert_md.h"
+
+#include "sys_api.h"
+
+#ifdef UNIX
+#include <unistd.h>
+#endif
+
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+char *stat_source(ClassClass *cb, struct stat *s, char *pathbuf, int maxlen);
+
+extern ClassClass *allocClassClass();
+
+extern bool_t JARfile;
+
+extern char * zipFileName;
+
+extern zip_t * getZipEntry(char *zipFile, int len);
+
+extern bool_t findJARDirectories(zip_t *entry, struct stat *statbuf);
+
+extern JAR_DataStreamPtr loadJARfile(zip_t *entry, const char* filename);
+
+
+/*=========================================================================
+ * FUNCTION: AddBinClass
+ * OVERVIEW: Used by createInternalClass1() and createFakeArrayClass()
+ * to add a class in the class table.
+ * INTERFACE:
+ * parameters: ClassClass: cb
+ *
+ * returns: nothing
+ *=======================================================================*/
+void
+AddBinClass(ClassClass * cb)
+{
+ register int left, right, middle, result, i;
+ char *name = cbName(cb);
+ struct Hjava_lang_ClassLoader *loader = cbLoader(cb);
+
+ BINCLASS_LOCK();
+ left = 0;
+ right = nbinclasses - 1;
+ result = 1;
+ while (left <= right) {
+ ClassClass *cb1;
+ middle = (left+right)/2;
+ cb1 = binclasses[middle];
+ result = strcmp(name, cbName(cb1));
+ if (result == 0) {
+ if (loader < cbLoader(cb1)) {
+ result = -1;
+ } else if (loader > cbLoader(cb1)) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ }
+ if (result < 0) {
+ right = middle-1;
+ } else if (result > 0) {
+ left = middle+1;
+ } else {
+ break;
+ }
+ }
+ if (result != 0) {
+ if (nbinclasses >= sizebinclasses) {
+ if (binclasses == 0)
+ binclasses = (ClassClass **)
+ sysMalloc(sizeof(ClassClass *) * (sizebinclasses = 50));
+ else
+ binclasses = (ClassClass **)
+ sysRealloc(binclasses, sizeof(ClassClass *)
+ * (sizebinclasses = nbinclasses * 2));
+ }
+ if (binclasses == 0)
+ goto unlock;
+ right++;
+ for (i = nbinclasses; i > right; i--) {
+ binclasses[i] = binclasses[i-1];
+ }
+ binclasses[right] = cb;
+ nbinclasses++;
+ }
+
+unlock:
+ BINCLASS_UNLOCK();
+}
+
+
+/*=========================================================================
+ * FUNCTION: DelBinClass
+ * OVERVIEW: Intended for allowing deletion of classes from the class
+ * table.
+ *
+ * INTERFACE:
+ * parameters: ClassClass: cb
+ *
+ * returns: nothing
+ *=======================================================================*/
+void
+DelBinClass(ClassClass * cb)
+{
+ register int i, j;
+ BINCLASS_LOCK();
+ for (i = nbinclasses; --i >= 0; )
+ if (binclasses[i] == cb) {
+ nbinclasses--;
+ for (j = i; j < nbinclasses; j++) {
+ binclasses[j] = binclasses[j+1];
+ }
+ break;
+ }
+ BINCLASS_UNLOCK();
+}
+
+
+/*=========================================================================
+ * FUNCTION: MakeClassSticky
+ * OVERVIEW: Used to lock certain system classes into memory during
+ * initialization.
+ *
+ * INTERFACE:
+ * parameters: ClassClass: cb
+ *
+ * returns: nothing
+ *=======================================================================*/
+void
+MakeClassSticky(ClassClass *cb)
+{
+ /* monitorEnter(obj_monitor(cb)); */
+ CCSet(cb, Sticky);
+ /* monitorExit(obj_monitor(cb)); */
+}
+
+
+/*=========================================================================
+ * FUNCTION: LoadClassFromFile
+ * OVERVIEW: Loads a .class file normally from disk or a null if it fails.
+ * When the interpreter requests for a file, it is actually
+ * looking for a classblock structure to be created, and the
+ * only way it can get one of those is by loading a compiled
+ * class.
+ * OpenCode() tries to open a .class file first. If it fails
+ * to open the file, it returns a non-zero status. If it
+ * returns a valid file descriptor, this usually means that
+ * this is a valid .class file.
+ * It then invokes createInternalClass() to actually create the
+ * internal representation of the class.
+ *
+ * INTERFACE:
+ * parameters: char*: file name
+ * char*: directory
+ * char*: class name
+ *
+ * returns: nothing
+ *=======================================================================*/
+ClassClass *
+LoadClassFromFile(char *fn, char *dir, char *class_name)
+{
+ extern int OpenCode(char *, char *, char *, struct stat*);
+ struct stat st;
+ ClassClass *cb = 0;
+ int codefd = -1;
+ unsigned char *external_class;
+ char *detail;
+
+ codefd = OpenCode(fn, NULL, dir, &st);
+
+ if (codefd < 0) /* open failed */
+ return 0;
+
+ /* Snarf the file into memory. */
+ external_class = (unsigned char *)sysMalloc(st.st_size);
+ if (external_class == 0)
+ goto failed;
+ if (sysRead(codefd, external_class, st.st_size) != st.st_size)
+ goto failed;
+ sysClose(codefd);
+ codefd = -1;
+
+ /* Create the internal class */
+ cb = allocClassClass();
+ if (cb == NULL ||
+ !createInternalClass(external_class, external_class + st.st_size,
+ cb, NULL, class_name, &detail)) {
+ sysFree(external_class);
+ goto failed;
+ }
+ sysFree(external_class);
+
+ if (verbose)
+ jio_fprintf(stderr, "[Loaded %s]\n", fn);
+
+ return cb;
+failed:
+ if (codefd >= 0)
+ sysClose(codefd);
+ if (cb != 0)
+ FreeClass(cb);
+ return 0;
+}
+
+
+/*=========================================================================
+ * FUNCTION: LoadClassFromZip
+ * TYPE: load class from a JAR or Zip file
+ * OVERVIEW: Called by LoadClassLocally for loading classes from a Zip.
+ *
+ * This function loads a .class file normally from a Zip or
+ * JAR file.
+ * It returns the class when it succeeds or NULL if it fails.
+ *
+ * INTERFACE:
+ * parameters: zip_t: zip file entry
+ * char*: class file name to search for loading
+ * returns: Pointer to ClassClass when it succeeds, or NULL if it fails.
+ *=======================================================================*/
+static ClassClass *
+LoadClassFromZip(zip_t *zipEntry, char *class_name)
+{
+ ClassClass *cb = 0;
+ JAR_DataStreamPtr jdstream = NULL;
+ unsigned char *external_class;
+ int data_length;
+ char *detail;
+
+ jdstream = loadJARfile (zipEntry, class_name);
+
+ if (jdstream == NULL)
+ goto failed;
+
+ external_class = jdstream->data;
+ data_length = jdstream->dataLen;
+
+ /* Create the internal class */
+ cb = allocClassClass();
+ if (cb == NULL ||
+ !createInternalClass(external_class, external_class + data_length,
+ cb, NULL, class_name, &detail)) {
+ goto failed;
+ }
+ if (jdstream != NULL) {
+ freeBytes(jdstream);
+ }
+
+ if (verbose) {
+ jio_fprintf(stderr, "[Loaded %s] from [%s]\n", class_name,
+ zipEntry->name);
+ }
+ return cb;
+failed:
+ if (cb != 0)
+ FreeClass(cb);
+ if (jdstream != NULL) {
+ freeBytes(jdstream);
+ }
+ return 0;
+}
+
+
+/*=========================================================================
+ * FUNCTION: LoadClassLocally
+ * OVERVIEW: Find a class file that is somewhere local, and not from a
+ * class loader.
+ * It still needs to be searched using the classpath.
+ *
+ * INTERFACE:
+ * parameters: char* : class file name
+ * returns: Pointer to ClassClass when it succeeds, or NULL if it fails.
+ *=======================================================================*/
+ClassClass *LoadClassLocally(char *name)
+{
+ ClassClass *cb = 0;
+ cpe_t **cpp;
+
+ if (name[0] == DIR_SEPARATOR || name[0] == SIGNATURE_ARRAY)
+ return 0;
+
+ for (cpp = sysGetClassPath(); cpp && *cpp != 0; cpp++) {
+ cpe_t *cpe = *cpp;
+ char *path;
+
+ if (cpe->type == CPE_DIR) {
+ path = (char *)sysMalloc(strlen(cpe->u.dir)
+ + sizeof(LOCAL_DIR_SEPARATOR)
+ + strlen(name)
+ + strlen(JAVAOBJEXT)
+ + 2); /* 2 is for the . and the \0 */
+ if (sprintf(path,
+ "%s%c%s." JAVAOBJEXT, cpe->u.dir,
+ LOCAL_DIR_SEPARATOR, name) == -1) {
+ sysFree(path);
+ return 0;
+ }
+ if ((cb = LoadClassFromFile(sysNativePath(path),
+ cpe->u.dir, name))) {
+ sysFree(path);
+ return cb;
+ }
+ } else if (cpe->type == CPE_ZIP) {
+ // if (JAR_DEBUG && verbose)
+ // jio_fprintf(stderr, "Loading classes from a ZIP file... \n");
+ if ((cb = LoadClassFromZip(cpe->u.zip, name))) {
+ return cb;
+ }
+ }
+
+ }
+ return cb;
+}
+
+
+/*=========================================================================
+ * FUNCTION: stat_source
+ * OVERVIEW: Unused by the Verifier, but it is too late to remove it now.
+ *
+ * INTERFACE:
+ * parameters: ClassClass *: cb
+ * struct stat*: s
+ * char*: pathbuf
+ * int: maxlen
+ * returns: char *, or NULL if it fails.
+ *=======================================================================*/
+char *
+stat_source(ClassClass *cb, struct stat *s, char *pathbuf, int maxlen)
+{
+#define NAMEBUFLEN 255
+ char nm[NAMEBUFLEN];
+ char *p, *q, *lp;
+ cpe_t **cpp;
+
+ /* don't bother searching if absolute */
+ /* REMIND: only here for compatibility */
+ if (sysIsAbsolute(cbSourceName(cb))) {
+ if (sysStat(cbSourceName(cb), s) == 0) {
+ if (jio_snprintf(pathbuf, maxlen, "%s", cbSourceName(cb)) == -1) {
+ return 0;
+ }
+ return pathbuf;
+ } else {
+ return 0;
+ }
+ }
+
+ /* parse the package name */
+ p = cbName(cb);
+ if (strlen(p) > NAMEBUFLEN - 1) {
+ return 0;
+ }
+ for (q = lp = nm ; *p ; p++) {
+ if (*p == DIR_SEPARATOR) {
+ *q++ = LOCAL_DIR_SEPARATOR;
+ lp = q;
+ } else {
+ *q++ = *p;
+ }
+ }
+
+ /* append the source file name */
+ p = cbSourceName(cb);
+ if (strlen(p) + (lp - nm) > NAMEBUFLEN - 1) {
+ return 0;
+ }
+ for (; *p ; p++) {
+ *lp++ = (*p == DIR_SEPARATOR ? LOCAL_DIR_SEPARATOR : *p);
+ }
+ *lp = '\0';
+
+ /* search the class path */
+ for (cpp = sysGetClassPath() ; cpp && *cpp != 0 ; cpp++) {
+ cpe_t *cpe = *cpp;
+ if (cpe->type == CPE_DIR) {
+ if (jio_snprintf(pathbuf, maxlen, "%s%c%s",
+ cpe->u.dir, LOCAL_DIR_SEPARATOR, nm) == -1) {
+ return 0;
+ }
+ if (sysStat(pathbuf, s) == 0) {
+ return pathbuf;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*=========================================================================
+ * Globals and externs for Internal Class representation
+ *=======================================================================*/
+struct CICmallocs {
+ struct CICmallocs *next;
+ void * alignment_padding;
+
+/* Whatever follows will be 8-byte aligned, if the structure itself is
+ 8-byte aligned. */
+};
+
+typedef struct CICmallocs CICmallocs;
+
+struct CICcontext {
+ unsigned char *ptr;
+ unsigned char *end_ptr;
+ ClassClass *cb;
+ jmp_buf jump_buffer;
+ char **detail;
+
+ int pass; /* two passes, 1 or 2 */
+ int malloc_size; /* space needed for everything other than <clinit> */
+ int clinit_size; /* space needed for the <clinit> method */
+ int in_clinit; /* indicates whether we are loading <clinit> method */
+
+ struct {
+ CICmallocs *mallocs; /* list of memory blocks used in the first pass */
+
+ void * alignment_padding;
+ /* Whatever follows will be 8-byte aligned */
+ } pass1;
+
+ struct {
+ char *malloc_buffer; /* used to hold everything other than <clinit> */
+ char *malloc_ptr; /* current point of allocation */
+
+ char *clinit_buffer; /* used to hold the <clinit> method */
+ char *clinit_ptr; /* current point of allocation */
+ } pass2;
+
+};
+
+typedef struct CICcontext CICcontext;
+
+static char *getAsciz(CICcontext *, bool_t);
+static char *getAscizFromClass(CICcontext *, int i);
+
+static unsigned char get1byte(CICcontext *);
+static unsigned short get2bytes(CICcontext *);
+static unsigned long get4bytes(CICcontext *);
+static void getNbytes(CICcontext *, int count, char *buffer);
+static void *allocNBytes(CICcontext *, int size);
+static void freeBuffers(CICcontext *);
+
+static void LoadConstantPool(CICcontext *);
+static void ReadInCode(CICcontext *, struct methodblock *);
+static void ReadLineTable(CICcontext *, struct methodblock *mb);
+static void ReadExceptions(CICcontext *, struct methodblock *);
+static void ReadLocalVars(CICcontext *, struct methodblock *mb);
+
+static void
+createInternalClass0(CICcontext *context, ClassClass *cb,
+ struct Hjava_lang_ClassLoader *loader, char *name);
+
+bool_t
+createInternalClass1(unsigned char *ptr, unsigned char *end_ptr,
+ ClassClass *cb, struct Hjava_lang_ClassLoader *loader,
+ char *name, char **detail);
+
+
+/*=========================================================================
+ * FUNCTION: createInternalClass
+ * OVERVIEW: Invoked by LoadClassFromFile() or LoadClassFromZip() to
+ * create an internal class. See createInternalClass1() for
+ * details.
+ *
+ * INTERFACE:
+ * parameters: unsigned char *: ptr
+ * unsigned char *: end_ptr
+ * ClassClass *: cb
+ * struct Hjava_lang_ClassLoader *: loader
+ * char *: name
+ * char **: detail
+ *
+ * returns: bool_t
+ *=======================================================================*/
+bool_t
+createInternalClass(unsigned char *ptr, unsigned char *end_ptr,
+ ClassClass *cb, struct Hjava_lang_ClassLoader *loader,
+ char *name, char **detail)
+{
+ bool_t res;
+ res = createInternalClass1(ptr, end_ptr, cb, loader, name, detail);
+
+ return res;
+}
+
+
+/*=========================================================================
+ * FUNCTION: JAVA_ERROR
+ * OVERVIEW: Verifier error processing function.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ * char * : name
+ *
+ * returns: nothing
+ *=======================================================================*/
+void JAVA_ERROR(CICcontext *context, char *name) {
+ printCurrentClassName();
+ *(context->detail) = name;
+ EE()->class_loading_msg = name;
+ fprintf(stderr, "Class loading error: %s\n", name);
+ exit(1);
+}
+
+
+/*=========================================================================
+ * FUNCTION: createInternalClass1
+ * OVERVIEW: Auxiliary function for creating an internal class.
+ * Invoked by createInternalClass().
+ *
+ * Creates an internal class file from the indicated data.
+ * It should be in a buffer for which the first byte is at
+ * *ptr and the last byte is just before *end_ptr.
+ * The class's classloader is indicated by the classloader
+ * argument.
+ *
+ * We go through the buffer twice. In the first pass, we
+ * determine the amount of storage needed by the class.
+ * We then allocate a single chunk of memory, free the
+ * temporary storage, and load from the buffer for the second
+ * time.
+ *
+ * Since all storage needed by the class initialization method
+ * <clinit> can be freed after the class is loaded, we count
+ * the <clinit> space needs separately and store the <clinit>
+ * method in a separate chunk of memory.
+ *
+ * INTERFACE:
+ * parameters: unsigned char *: ptr
+ * unsigned char *: end_ptr
+ * ClassClass *: cb
+ * struct Hjava_lang_ClassLoader *: loader
+ * char *: name
+ * char **: detail
+ *
+ * returns: bool_t
+ *=======================================================================*/
+bool_t
+createInternalClass1(unsigned char *ptr, unsigned char *end_ptr,
+ ClassClass *cb, struct Hjava_lang_ClassLoader *loader,
+ char *name, char **detail)
+{
+ struct CICcontext context_block;
+ struct CICcontext *context = &context_block;
+
+ /* Set up the context */
+ context->ptr = ptr;
+ context->end_ptr = end_ptr;
+ context->cb = cb;
+ context->detail = detail;
+
+ /* initialize the remaining fields of the context block */
+ context->pass = 0;
+ context->malloc_size = 0;
+ context->clinit_size = 0;
+ context->in_clinit = 0;
+ context->pass1.mallocs = 0;
+
+ context->pass2.malloc_buffer = NULL;
+ context->pass2.malloc_ptr = NULL;
+ context->pass2.clinit_buffer = NULL;
+ context->pass2.clinit_ptr = NULL;
+
+
+ if (setjmp(context->jump_buffer)) {
+
+ /* We've gotten an error of some sort
+ * See comments below about zeroing these
+ * two fields before freeing the temporary
+ * buffer.
+ */
+
+ cbConstantPool(cb) = NULL;
+ cbFields(cb) = NULL;
+
+ /* Zero out the method so that freeClass will
+ * not try to free the clinit method.
+ */
+
+ cbMethodsCount(cb) = 0;
+ freeBuffers(context);
+ return FALSE;
+ }
+
+ /* The first pass allows us to uncover any class format
+ * errors and find out the size of the buffer needed.
+ */
+
+ context->pass = 1;
+ createInternalClass0(context, cb, loader, name);
+
+ /* We must set the following two fields to zero before we free
+ * the temporary buffers, because markClassClass may scan a
+ * partially constructed class block in the second pass.
+ * If these two fields are set to zero, markClassClass will
+ * not scan the constant pool and field blocks, which may
+ * point to freed memory.
+ */
+
+ cbConstantPool(cb) = NULL;
+ cbFields(cb) = NULL;
+
+ /* Zero out the method so that freeClass will not try
+ * to free the clinit method.
+ */
+
+ cbMethodsCount(cb) = 0;
+ freeBuffers(context);
+
+ context->ptr = ptr; /* rewind the raw class data */
+
+ if (context->malloc_size > 0) {
+ context->pass2.malloc_buffer =
+ (char *)sysCalloc(1, context->malloc_size);
+
+ if (context->pass2.malloc_buffer == 0)
+ JAVA_ERROR(context, "out of memory");
+ }
+
+ if (context->clinit_size > 0) {
+ context->pass2.clinit_buffer =
+ (char *)sysCalloc(1, context->clinit_size * sizeof(char));
+
+ if (context->pass2.clinit_buffer == 0) {
+ sysFree(context->pass2.malloc_buffer);
+ JAVA_ERROR(context, "out of memory");
+ }
+ }
+
+ context->pass2.malloc_ptr = context->pass2.malloc_buffer;
+ context->pass2.clinit_ptr = context->pass2.clinit_buffer;
+
+ /* The second pass accomplishes the real task. */
+
+ context->pass = 2;
+ createInternalClass0(context, cb, loader, name);
+
+ /* Valid class - let's put it in the class table. */
+ AddBinClass(cb);
+
+ return TRUE;
+}
+
+
+/*=========================================================================
+ * FUNCTION: createInternalClass0
+ * OVERVIEW: Auxiliary function invoked by createInternalClass1() during
+ * the second pass to actually load the internal class file
+ * structures such as the constant pool, method blocks, field
+ * blocks and so on.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ * ClassClass *: cb
+ * struct Hjava_lang_ClassLoader *: loader
+ * char *: name
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+createInternalClass0(CICcontext *context, ClassClass *cb,
+ struct Hjava_lang_ClassLoader *loader, char *name)
+{
+ int i, j, len;
+ char buff[BUFSIZ];
+ char *UTFname = &buff[0];
+ union cp_item_type *constant_pool;
+ unsigned char *type_table;
+ int attribute_count;
+ unsigned fields_count;
+ struct methodblock *mb;
+ struct fieldblock *fb;
+ struct Classjava_lang_Class *ucb = unhand(cb);
+
+ int32_t tmp = get4bytes(context);
+ if (tmp != JAVA_CLASSFILE_MAGIC)
+ JAVA_ERROR(context, "Bad magic number");
+
+ ucb->minor_version = get2bytes(context);
+ ucb->major_version = get2bytes(context);
+ ucb->loader = loader;
+
+ /* Ignore version # so that the preverifier can work with JDK 1.4 onwards */
+ /*
+ if (ucb->major_version != JAVA_VERSION)
+ JAVA_ERROR(context, "Bad major version number");
+ */
+
+ LoadConstantPool(context);
+ constant_pool = ucb->constantpool;
+ type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+
+ ucb->access = get2bytes(context) & ACC_WRITTEN_FLAGS;
+
+ /* Get the name of the class */
+ i = get2bytes(context); /* index in constant pool of class */
+ ucb->name = getAscizFromClass(context, i);
+
+ /* Conversion for Japanese filenames */
+ len = native2utf8(name, UTFname, BUFSIZ);
+
+ if (name != NULL && strcmp(ucb->name, UTFname) != 0)
+ JAVA_ERROR(context, "Wrong name");
+ constant_pool[i].clazz = cb;
+ CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);
+
+ if (loader) {
+ /* We don't trust a classloader to do the right thing. . . */
+ ClassClass **pcb, **end_pcb;
+ char *name = ucb->name;
+// if (name == NULL || !IsLegalClassname(name, FALSE)) {
+// JAVA_ERROR(context, "Bad name");
+// }
+ BINCLASS_LOCK();
+ for (pcb = binclasses, end_pcb = pcb + nbinclasses;
+ pcb < end_pcb; pcb++) {
+ ClassClass *cb = *pcb;
+ if ((cbLoader(cb) == loader) && (strcmp(name, cbName(cb)) == 0))
+ break;
+ }
+ BINCLASS_UNLOCK();
+ if (pcb < end_pcb)
+ /* There's already a class with the same name and loader */
+ JAVA_ERROR(context, "Duplicate name");
+ }
+
+ /* Get the super class name. */
+ i = get2bytes(context); /* index in constant pool of class */
+ if (i > 0) {
+ ucb->super_name = getAscizFromClass(context, i);
+ ucb->superclass_idx = i;
+// if (!IsLegalClassname(ucb->super_name, FALSE)) {
+// JAVA_ERROR(context, "Bad superclass name");
+// }
+ }
+
+ i = ucb->implements_count = get2bytes(context);
+ if (i > 0) {
+ int j;
+ ucb->implements = allocNBytes(context, i * sizeof(short));
+ for (j = 0; j < i; j++) {
+ ucb->implements[j] = get2bytes(context);
+ }
+ }
+
+ fields_count = ucb->fields_count = get2bytes(context);
+ if (fields_count > 0)
+ ucb->fields = (struct fieldblock *)
+ allocNBytes(context, ucb->fields_count * sizeof(struct fieldblock));
+ for (i = fields_count, fb = ucb->fields; --i >= 0; fb++) {
+ fieldclass(fb) = cb;
+ fb->access = get2bytes(context) & ACC_WRITTEN_FLAGS;
+ fb->name = getAsciz(context, FALSE);
+ fb->signature = getAsciz(context, FALSE);
+ attribute_count = get2bytes(context);
+ for (j = 0; j < (int)attribute_count; j++) {
+ char *attr_name = getAsciz(context, FALSE);
+ int length = get4bytes(context);
+ if (strcmp(attr_name, "ConstantValue") == 0) {
+ if (fb->access & ACC_STATIC) {
+ if (length != 2) {
+ JAVA_ERROR(context, "Wrong size for VALUE attribute");
+ }
+ fb->access |= ACC_VALKNOWN;
+ /* we'll change this below */
+ fb->u.offset = get2bytes(context);
+ } else {
+ getNbytes(context, length, NULL);
+ }
+ } else if (strcmp(attr_name, "Deprecated") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad deprecated size");
+ }
+ fb->deprecated = TRUE;
+ } else if (strcmp(attr_name, "Synthetic") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad synthetic attribute size");
+ }
+ fb->synthetic = TRUE;
+ } else {
+ getNbytes(context, length, NULL);
+ }
+ }
+ /*
+ if (fb->access & ACC_STATIC) {
+ InitializeStaticVar(fb, context);
+ }
+ */
+ }
+
+ if ((ucb->methods_count = get2bytes(context)) > 0)
+ ucb->methods = (struct methodblock *)
+ allocNBytes(context, ucb->methods_count * sizeof(struct methodblock));
+
+ for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
+ fieldclass(&mb->fb) = cb;
+ mb->fb.access = get2bytes(context) & ACC_WRITTEN_FLAGS;
+ mb->fb.name = getAsciz(context, FALSE);
+ mb->fb.signature = getAsciz(context, FALSE);
+
+ if (strcmp(mb->fb.name, "<clinit>") == 0 &&
+ strcmp(mb->fb.signature, "()V") == 0)
+ context->in_clinit = TRUE;
+
+ mb->args_size = Signature2ArgsSize(mb->fb.signature)
+ + ((mb->fb.access & ACC_STATIC) ? 0 : 1);
+ if (mb->args_size > 255)
+ JAVA_ERROR(context, "Too many arguments");
+
+ attribute_count = get2bytes(context);
+ for (j = 0; j < attribute_count; j++) {
+ char *attr_name = getAsciz(context, FALSE);
+ if ((strcmp(attr_name, "Code") == 0)
+ && ((mb->fb.access & (ACC_NATIVE | ACC_ABSTRACT))==0)) {
+ ReadInCode(context, mb);
+ } else if (strcmp(attr_name, "Exceptions") == 0) {
+ ReadExceptions(context, mb);
+ } else {
+ int length = get4bytes(context);
+ if (strcmp(attr_name, "Deprecated") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad deprecated size");
+ }
+ mb->fb.deprecated = TRUE;
+ } else if (strcmp(attr_name, "Synthetic") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad synthetic attribute size");
+ }
+ mb->fb.synthetic = TRUE;
+ } else {
+ getNbytes(context, length, NULL);
+ }
+ }
+ }
+ context->in_clinit = FALSE;
+ }
+
+ /* See if there are class attributes */
+ attribute_count = get2bytes(context);
+ for (j = 0; j < attribute_count; j++) {
+ char *attr_name = getAsciz(context, FALSE);
+ int length = get4bytes(context);
+ if (strcmp(attr_name, "SourceFile") == 0) {
+ if (length != 2) {
+ JAVA_ERROR(context, "Wrong size for VALUE attribute");
+ }
+ ucb->source_name = getAsciz(context, FALSE);
+ } else if (strcmp(attr_name, "AbsoluteSourcePath") == 0) {
+ if (length == 2) {
+ ucb->absolute_source_name = getAsciz(context, FALSE);
+ } else
+ getNbytes(context, length, NULL);
+ } else if (strcmp(attr_name, "TimeStamp") == 0) {
+ if (length == 8) {
+ ucb->hasTimeStamp = TRUE;
+ ucb->timestamp.high = get4bytes(context);
+ ucb->timestamp.low = get4bytes(context);
+ } else {
+ getNbytes(context, length, NULL);
+ }
+ } else if (strcmp(attr_name, "Deprecated") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad deprecated size");
+ }
+ ucb->deprecated = TRUE;
+ } else if (strcmp(attr_name, "Synthetic") == 0) {
+ if (length > 0) {
+ JAVA_ERROR(context, "Bad synthetic attribute size");
+ }
+ ucb->synthetic = TRUE;
+ } else if (strcmp(attr_name, "InnerClasses") == 0) {
+ int count = get2bytes(context);
+ struct innerClasses *thisInnerClass = (struct innerClasses *)
+ allocNBytes(context, count * sizeof(struct innerClasses));
+ struct innerClasses *lastInnerClass = thisInnerClass + count;
+
+ if (count * 8 + 2 != length) {
+ JAVA_ERROR(context, "Bad length of InnerClasses attribute");
+ }
+
+ ucb->inner_classes_count = count;
+ ucb->inner_classes = thisInnerClass;
+
+ for ( ; thisInnerClass < lastInnerClass; thisInnerClass++) {
+ thisInnerClass->inner_class = get2bytes(context);
+ thisInnerClass->outer_class = get2bytes(context);
+ thisInnerClass->inner_name = getAsciz(context, TRUE);
+ thisInnerClass->access = get2bytes(context);
+ if (thisInnerClass->inner_class != 0) {
+ /* Make sure that inner_class really belongs to a CLASS */
+ getAscizFromClass(context, thisInnerClass->inner_class);
+ }
+ if (thisInnerClass->outer_class != 0) {
+ /* Make sure that outer_class really belongs to a CLASS */
+ getAscizFromClass(context, thisInnerClass->outer_class);
+ }
+ }
+ } else {
+ getNbytes(context, length, NULL);
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: createFakeArrayClass
+ * OVERVIEW: Invoked by Locked_FindArrayClassFromClass() for creating
+ * a fake array class that has the specified fields.
+ *
+ * INTERFACE:
+ * parameters: char *: name
+ * int : base type
+ * int : depth (array dimension)
+ * ClassClass * : base type if T_CLASS
+ * struct Hjava_lang_ClassLoader *: class loader
+ *
+ * returns: ClassClass *
+ *=======================================================================*/
+ClassClass *
+createFakeArrayClass(char *name, /* name */
+ int base_type, /* base_type */
+ int depth, /* array dimension */
+ ClassClass *inner_cb, /* base type if T_CLASS */
+ struct Hjava_lang_ClassLoader *loader)
+{
+ ClassClass *cb = allocClassClass();
+ Classjava_lang_Class *ucb = unhand(cb);
+ cp_item_type *constant_pool =
+ sysCalloc(CONSTANT_POOL_ARRAY_LENGTH,
+ (sizeof(cp_item_type) + sizeof(unsigned char)));
+ unsigned char *type_table = (unsigned char *)
+ (constant_pool + CONSTANT_POOL_ARRAY_LENGTH);
+ sysAssert(name[0] == SIGNATURE_ARRAY);
+ ucb->major_version = JAVA_VERSION;
+ ucb->minor_version = JAVA_MINOR_VERSION;
+ ucb->name = strdup(name);
+ ucb->super_name = JAVAPKG "Object";
+ ucb->constantpool = constant_pool;
+ ucb->constantpool_count = CONSTANT_POOL_ARRAY_LENGTH;
+ ucb->loader = loader;
+
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type = type_table;
+ constant_pool[CONSTANT_POOL_ARRAY_DEPTH_INDEX].i = depth;
+ constant_pool[CONSTANT_POOL_ARRAY_TYPE_INDEX].i = base_type;
+ type_table[CONSTANT_POOL_ARRAY_DEPTH_INDEX] =
+ CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED;
+ type_table[CONSTANT_POOL_ARRAY_TYPE_INDEX] =
+ CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED;
+
+ if (base_type == T_CLASS) {
+ /* Initialize the appropriate fields of the constant pool */
+ constant_pool[CONSTANT_POOL_ARRAY_CLASS_INDEX].clazz = inner_cb;
+ type_table[CONSTANT_POOL_ARRAY_CLASS_INDEX] =
+ CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED;
+ /* The class is public iff its base class is public */
+ ucb->access = ACC_FINAL | ACC_ABSTRACT |
+ (cbAccess(inner_cb) & ACC_PUBLIC);
+ } else {
+ /* Set the class field to something innocuous */
+ type_table[CONSTANT_POOL_ARRAY_CLASS_INDEX] =
+ CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED;
+ ucb->access = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC;
+ }
+ AddBinClass(cb);
+ return cb;
+}
+
+
+/*=========================================================================
+ * FUNCTION: createPrimitiveClass
+ * OVERVIEW: Creates a class block to represent a primitive type.
+ * NOTE: this is not added to the built-in class table, so
+ * it should only be called once per primitive type.
+ * See FindPrimitiveClass().
+ *
+ * INTERFACE:
+ * parameters: char *: name
+ * char : sig
+ * unsigned char: typecode
+ * unsigned char: slotsize
+ * unsigned char: elementsize
+ *
+ * returns: ClassClass *
+ *=======================================================================*/
+ClassClass *
+createPrimitiveClass(char *name, char sig, unsigned char typecode,
+ unsigned char slotsize, unsigned char elementsize)
+{
+ ClassClass *cb = allocClassClass();
+ Classjava_lang_Class *ucb = unhand(cb);
+
+ ucb->major_version = JAVA_VERSION;
+ ucb->minor_version = JAVA_MINOR_VERSION;
+ ucb->name = strdup(name);
+ ucb->super_name = JAVAPKG "Object";
+ ucb->constantpool = NULL;
+ ucb->constantpool_count = 0;
+ ucb->loader = NULL;
+ ucb->access = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC;
+
+ CCSet(cb, Primitive);
+ cbTypeSig(cb) = sig;
+ cbTypeCode(cb) = typecode;
+ cbSlotSize(cb) = slotsize;
+ cbElementSize(cb) = elementsize;
+ MakeClassSticky(cb);
+
+ return cb;
+}
+
+
+/*=========================================================================
+ * FUNCTION: LoadConstantPool
+ * OVERVIEW: Loads the constant pool given a pointer to the internal
+ * class file.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void LoadConstantPool(CICcontext *context)
+{
+ ClassClass *cb = context->cb;
+ int nconstants = get2bytes(context);
+ cp_item_type *constant_pool;
+ unsigned char *type_table;
+ int i;
+ Java8 t1;
+
+ if (nconstants > 16384) {
+ JAVA_ERROR(context, "Preverifier only "
+ "handles constant pool size up to 16K");
+ }
+
+ t1.x[0] = 0; /* shut off warning */
+ if (nconstants < CONSTANT_POOL_UNUSED_INDEX) {
+ JAVA_ERROR(context, "Illegal constant pool size");
+ }
+
+ constant_pool = (cp_item_type *)
+ allocNBytes(context, nconstants * sizeof(cp_item_type));
+ type_table = allocNBytes(context, nconstants * sizeof(char));
+
+ for (i = CONSTANT_POOL_UNUSED_INDEX; i < nconstants; i++) {
+ int type = get1byte(context);
+ CONSTANT_POOL_TYPE_TABLE_PUT(type_table, i, type);
+ switch (type) {
+ case CONSTANT_Utf8: {
+ int length = get2bytes(context);
+ char *result = allocNBytes(context, length + 1);
+ getNbytes(context, length, result);
+ result[length] = '\0';
+ constant_pool[i].cp = result;
+ CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);
+ break;
+ }
+
+ case CONSTANT_Class:
+ case CONSTANT_String:
+ constant_pool[i].i = get2bytes(context);
+ break;
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_NameAndType:
+ constant_pool[i].i = get4bytes(context);
+ break;
+
+ case CONSTANT_Float:
+ if (no_floating_point) {
+ panic("floating-point constants should not appear");
+ }
+
+ case CONSTANT_Integer:
+ constant_pool[i].i = get4bytes(context);
+ CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);
+ break;
+
+ case CONSTANT_Double:
+ if (no_floating_point) {
+ panic("floating-point constants should not appear");
+ }
+ case CONSTANT_Long: {
+ /* We ignore endian problems, and just load the two
+ * values. The verifier never actually cares what
+ * the actual value is.
+ */
+ constant_pool[i].i = get4bytes(context);
+ CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);
+ i++;
+ if (i >= nconstants) {
+ JAVA_ERROR(context, "illegal constant pool entry");
+ }
+ /* Indicate that the next object in the constant pool cannot
+ * be accessed independently.
+ */
+ constant_pool[i].i = get4bytes(context);
+ CONSTANT_POOL_TYPE_TABLE_PUT(type_table, i, 0);
+ CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);
+ break;
+ }
+
+ default:
+ JAVA_ERROR(context, "Illegal constant pool type");
+ }
+ }
+ /* It is important to only set these after everything is setup,
+ so that the GC sees a consistent state.*/
+ cbConstantPool(cb) = constant_pool;
+ cbConstantPoolCount(cb) = nconstants;
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type = type_table;
+}
+
+
+/*=========================================================================
+ * FUNCTION: ReadInCode
+ * OVERVIEW: Reads the code attributes given a pointer to the internal
+ * class file and a pointer to the method block structure.
+ * This includes line number and local variable tables.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ * struct methodblock *: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void ReadInCode(CICcontext *context, struct methodblock *mb)
+{
+ int attribute_length = get4bytes(context);
+ unsigned char *end_ptr = context->ptr + attribute_length;
+ int attribute_count;
+ int code_length;
+ int i;
+
+ if (cbMinorVersion(context->cb) == JAVA_VERSION &&
+ cbMinorVersion(context->cb) <= 2) {
+ mb->maxstack = get1byte(context);
+ mb->nlocals = get1byte(context);
+ code_length = mb->code_length = get2bytes(context);
+ } else {
+ mb->maxstack = get2bytes(context);
+ mb->nlocals = get2bytes(context);
+ code_length = mb->code_length = get4bytes(context);
+ }
+ if (mb->nlocals < mb->args_size)
+ JAVA_ERROR(context, "Arguments can't fit into locals");
+
+ if (code_length > 65535) {
+ JAVA_ERROR(context, "Byte code size exceeds 65535 bytes");
+ }
+
+ mb->code = allocNBytes(context, code_length);
+
+ getNbytes(context, code_length, (char *)mb->code);
+ if ((mb->exception_table_length = get2bytes(context)) > 0) {
+ unsigned exception_table_size = mb->exception_table_length
+ * sizeof(struct CatchFrame);
+ mb->exception_table = allocNBytes(context, exception_table_size);
+ for (i = 0; i < (int)mb->exception_table_length; i++) {
+ mb->exception_table[i].start_pc = get2bytes(context);
+ mb->exception_table[i].end_pc = get2bytes(context);
+ mb->exception_table[i].handler_pc = get2bytes(context);
+ mb->exception_table[i].catchType = get2bytes(context);
+ mb->exception_table[i].compiled_CatchFrame = NULL;
+ }
+ }
+ attribute_count = get2bytes(context);
+ for (i = 0; i < attribute_count; i++) {
+ char *name = getAsciz(context, FALSE);
+ if (strcmp(name, "LineNumberTable") == 0) {
+ ReadLineTable(context, mb);
+ } else if (strcmp(name, "LocalVariableTable") == 0) {
+ ReadLocalVars(context, mb);
+ } else {
+ int length = get4bytes(context);
+ getNbytes(context, length, NULL);
+ }
+ }
+ if (context->ptr != end_ptr)
+ JAVA_ERROR(context, "Code segment was wrong length");
+}
+
+
+/*=========================================================================
+ * FUNCTION: ReadLineTable
+ * OVERVIEW: Reads the line number table given a pointer to the internal
+ * class file and a pointer to the method block structure.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ * struct methodblock *: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void ReadLineTable(CICcontext *context, struct methodblock *mb)
+{
+ int attribute_length = get4bytes(context);
+ unsigned char *end_ptr = context->ptr + attribute_length;
+ int i;
+ if ((mb->line_number_table_length = get2bytes(context)) > 0) {
+ struct lineno *ln =
+ allocNBytes(context, mb->line_number_table_length *
+ sizeof(struct lineno));
+ mb->line_number_table = ln;
+ for (i = mb->line_number_table_length; --i >= 0; ln++) {
+ ln->pc = get2bytes(context);
+ ln->line_number = get2bytes(context);
+ }
+ }
+ if (context->ptr != end_ptr)
+ JAVA_ERROR(context, "Line number table was wrong length?");
+}
+
+
+
+/*=========================================================================
+ * FUNCTION: ReadLocalVars
+ * OVERVIEW: Reads the localvar table given a pointer to the internal
+ * class file and a pointer to the method block structure.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ * struct methodblock *: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void ReadLocalVars(CICcontext *context, struct methodblock *mb)
+{
+ int attribute_length = get4bytes(context);
+ unsigned char *end_ptr = context->ptr + attribute_length;
+ int i;
+ if ((mb->localvar_table_length = get2bytes(context)) > 0) {
+ struct localvar *lv =
+ allocNBytes(context, mb->localvar_table_length *
+ sizeof(struct localvar));
+ mb->localvar_table = lv;
+ for (i = mb->localvar_table_length; --i >= 0; lv++) {
+ lv->pc0 = get2bytes(context);
+ lv->length = get2bytes(context);
+ lv->name = getAsciz(context, FALSE);
+ lv->signature = getAsciz(context, FALSE);
+ lv->slot = get2bytes(context);
+ }
+ }
+ if (context->ptr != end_ptr)
+ JAVA_ERROR(context, "Local variables table was wrong length?");
+}
+
+
+/*=========================================================================
+ * FUNCTION: ReadExceptions
+ * OVERVIEW: Reads the Exception attribute given a pointer to the internal
+ * class file and a pointer to the method block structure.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: ptr
+ * struct methodblock *: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+ReadExceptions(CICcontext *context, struct methodblock *mb)
+{
+ int attribute_length = get4bytes(context);
+ unsigned char *end_ptr = context->ptr + attribute_length;
+ unsigned short nexceptions = get2bytes(context);
+
+ if ((mb->nexceptions = nexceptions) > 0) {
+ unsigned short *ep, *exceptions =
+ allocNBytes(context, nexceptions * sizeof (unsigned short));
+ mb->exceptions = ep = exceptions;
+ while (nexceptions-- > 0) {
+ *ep++ = get2bytes(context);
+ }
+ }
+ if (context->ptr != end_ptr)
+ JAVA_ERROR(context, "Exceptions attribute has wrong length");
+}
+
+
+/*=========================================================================
+ * FUNCTION: Signature2ArgsSize
+ * OVERVIEW: Returns the size of arguments given a pointer to a method
+ * signature.
+ *
+ * INTERFACE:
+ * parameters: char*: method_signature
+ *
+ * returns: unsigned
+ *=======================================================================*/
+unsigned Signature2ArgsSize(char *method_signature)
+{
+ char *p;
+ int args_size = 0;
+ for (p = method_signature; *p != SIGNATURE_ENDFUNC; p++) {
+ switch (*p) {
+ case SIGNATURE_FLOAT:
+ if (no_floating_point) {
+ panic("floating-point arguments should not appear");
+ }
+
+ case SIGNATURE_BOOLEAN:
+ case SIGNATURE_BYTE:
+ case SIGNATURE_CHAR:
+ case SIGNATURE_SHORT:
+ case SIGNATURE_INT:
+ args_size += 1;
+ break;
+
+ case SIGNATURE_CLASS:
+ args_size += 1;
+ while (*p != SIGNATURE_ENDCLASS) p++;
+ break;
+
+ case SIGNATURE_ARRAY:
+ args_size += 1;
+ while ((*p == SIGNATURE_ARRAY)) p++;
+ /* If an array of classes, skip over class name, too. */
+ if (*p == SIGNATURE_CLASS) {
+ while (*p != SIGNATURE_ENDCLASS)
+ p++;
+ }
+ break;
+
+ case SIGNATURE_DOUBLE:
+ if (no_floating_point) {
+ panic("floating-point arguments should not appear");
+ }
+
+ case SIGNATURE_LONG:
+ args_size += 2;
+ break;
+
+ case SIGNATURE_FUNC: /* ignore initial (, if given */
+ break;
+
+ default: /* Indicates an error. */
+ return 0;
+ }
+ }
+ return args_size;
+}
+
+
+/*=========================================================================
+ * FUNCTION: free_clinit_memory
+ * OVERVIEW: Frees clinit memory.
+ *
+ * INTERFACE:
+ * parameters: struct methodblock *: mb
+ *
+ * returns: nothing
+ *=======================================================================*/
+void free_clinit_memory(struct methodblock *mb)
+{
+ /* This function is somewhat a hack. It fixes the problem in 1.1.3
+ * and before. sysFree may be called on the wrong memory block if
+ * the exception attribute comes before the code attribute.
+ */
+ /* If there is no exceptions attribute, or if both have already
+ * been freed.
+ */
+ if (mb->exceptions == NULL) {
+ if (mb->code) {
+ sysFree(mb->code);
+ mb->code = NULL;
+ }
+ return;
+ }
+
+ /* If both attributes exist, free the one at the lower address */
+ if ((char *)mb->code < (char *)mb->exceptions)
+ sysFree(mb->code);
+ else
+ sysFree(mb->exceptions);
+
+ mb->code = NULL;
+ mb->exceptions = NULL;
+}
+
+
+/*=========================================================================
+ * FUNCTION: FreeClass
+ * OVERVIEW: Frees class.
+ *
+ * INTERFACE:
+ * parameters: ClassClass *: cb
+ *
+ * returns: nothing
+ *=======================================================================*/
+void FreeClass(ClassClass *cb)
+{
+ int i;
+ struct methodblock *mb;
+
+ for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
+ if (strcmp(mb->fb.name, "<clinit>") == 0 &&
+ strcmp(mb->fb.signature, "()V") == 0 &&
+ mb->code_length /* not external */ )
+ free_clinit_memory(mb);
+ }
+
+ sysFree(cbConstantPool(cb));
+
+ sysFree(cbMethodTableMem(cb));
+ sysFree(cbSlotTable(cb));
+
+ /* Interface method tables can be shared between child and
+ * super classes.
+ */
+ if (cbImplementsCount(cb) != 0 || cbIsInterface(cb))
+ sysFree(cbIntfMethodTable(cb));
+}
+
+
+/*=========================================================================
+ * FUNCTION: get1byte
+ * OVERVIEW: Gets one byte from the class file.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ *
+ * returns: value read or 0 if an error occurred.
+ *=======================================================================*/
+static unsigned char get1byte(CICcontext *context)
+{
+ unsigned char *ptr = context->ptr;
+ if (context->end_ptr - ptr < 1) {
+ JAVA_ERROR(context, "Truncated class file");
+ return 0;
+ } else {
+ unsigned char *ptr = context->ptr;
+ unsigned char value = ptr[0];
+ (context->ptr) += 1;
+ return value;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: get2bytes
+ * OVERVIEW: Gets two bytes from the class file.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ *
+ * returns: value read or 0 if an error occurred.
+ *=======================================================================*/
+static unsigned short get2bytes(CICcontext *context)
+{
+ unsigned char *ptr = context->ptr;
+ if (context->end_ptr - ptr < 2) {
+ JAVA_ERROR(context, "Truncated class file");
+ return 0;
+ } else {
+ unsigned short value = (ptr[0] << 8) + ptr[1];
+ (context->ptr) += 2;
+ return value;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: get4bytes
+ * OVERVIEW: Gets four bytes from the class file.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ *
+ * returns: value read or 0 if an error occurred.
+ *=======================================================================*/
+static unsigned long get4bytes(CICcontext *context)
+{
+ unsigned char *ptr = context->ptr;
+ if (context->end_ptr - ptr < 4) {
+ JAVA_ERROR(context, "Truncated class file");
+ return 0;
+ } else {
+ unsigned long value = (ptr[0] << 24) + (ptr[1] << 16) +
+ (ptr[2] << 8) + ptr[3];
+ (context->ptr) += 4;
+ return value;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: getNbytes
+ * OVERVIEW: Gets N bytes from the class file specified by the count
+ * parameter. If buffer is not null, it will also copy the
+ * count number of bytes read into the buffer as well.
+ * Note that this function seems to be always invoked with
+ * a NULL argument for the buffer, except when it loads the
+ * UTF8 entry from the constant pool and when the code
+ * attribute is loaded.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ * int: count
+ * char *: buffer
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void getNbytes(CICcontext *context, int count, char *buffer)
+{
+ unsigned char *ptr = context->ptr;
+ if (context->end_ptr - ptr < count)
+ JAVA_ERROR(context, "Truncated class file");
+ if (buffer != NULL)
+ memcpy(buffer, ptr, count);
+ (context->ptr) += count;
+}
+
+
+/*=========================================================================
+ * FUNCTION: getAsciz
+ * OVERVIEW: Reads the next two bytes and uses this value to look up for
+ * the corresponding constant pool entry.
+ * Returns null if the value is 0 and zeroOkay flag is set.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ * bool_t : zeroOkay
+ *
+ * returns: char * or NULL
+ *=======================================================================*/
+static char *getAsciz(CICcontext *context, bool_t zeroOkay)
+{
+ ClassClass *cb = context->cb;
+ union cp_item_type *constant_pool = cbConstantPool(cb);
+ int nconstants = cbConstantPoolCount(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+
+ int value = get2bytes(context);
+ if (value == 0 && zeroOkay) {
+ return NULL;
+ } else if ((value == 0) || (value >= nconstants) ||
+ type_table[value] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED))
+ JAVA_ERROR(context, "Illegal constant pool index");
+ return constant_pool[value].cp;
+}
+
+
+/*=========================================================================
+ * FUNCTION: getAscizFromClass
+ * OVERVIEW: Given the constant pool index, returns the name of the class
+ * which corresponds to this constant pool entry.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ * int: value
+ *
+ * returns: char * or NULL
+ *=======================================================================*/
+static char *getAscizFromClass(CICcontext *context, int value)
+{
+ ClassClass *cb = context->cb;
+ union cp_item_type *constant_pool = cbConstantPool(cb);
+ int nconstants = cbConstantPoolCount(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ if ((value > 0) && (value < nconstants)) {
+ if (type_table[value] == CONSTANT_Class) {
+ value = constant_pool[value].i;
+ if ((value <= 0) || (value >= nconstants) ||
+ (type_table[value] != (CONSTANT_Utf8 |
+ CONSTANT_POOL_ENTRY_RESOLVED)))
+ JAVA_ERROR(context, "Illegal constant pool index");
+ return constant_pool[value].cp;
+ } else if (type_table[value] == (CONSTANT_Class |
+ CONSTANT_POOL_ENTRY_RESOLVED)) {
+ ClassClass *cb = constant_pool[value].clazz;
+ return cbName(cb);
+ } else {
+ JAVA_ERROR(context, "Illegal constant pool index");
+ }
+ } else {
+ JAVA_ERROR(context, "Illegal constant pool index");
+ }
+ return NULL; /* not reached */
+}
+
+/* In order to avoid possible alignment errors, round up all sizes to
+ * multiples of eight.
+ */
+#define ROUNDUP_SIZE(s) while ((s) % 8 != 0) (s)++
+
+
+/*=========================================================================
+ * FUNCTION: allocNBytes
+ * OVERVIEW: Memory allocation function for internal class file
+ * structures.
+ * It calculates the number of allocations needed for the
+ * two passes, and the allocations required for the clinit
+ * method.
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ * int : size
+ *
+ * returns: void *
+ *=======================================================================*/
+static void *allocNBytes(CICcontext *context, int size)
+{
+ void *result;
+ if (context->pass == 1) {
+ /* The first pass
+ * A more sophisticated scheme could reduce the number of mallocs.
+ */
+ CICmallocs *mallocs =
+ (CICmallocs *)sysCalloc(1, sizeof(CICmallocs) + size);
+ if (mallocs == 0)
+ JAVA_ERROR(context, "out of memory");
+ result = (void *)(mallocs + 1);
+ mallocs->next = context->pass1.mallocs;
+ ROUNDUP_SIZE(size);
+ if (context->in_clinit)
+ context->clinit_size += size;
+ else
+ context->malloc_size += size;
+ context->pass1.mallocs = mallocs;
+ } else {
+ /* The second pass */
+
+ ROUNDUP_SIZE(size);
+
+#define ALLOC_BLOCK(ptr,buf,sizelimit) \
+ result = (ptr); \
+ (ptr) += (size); \
+ sysAssert((ptr) <= (buf) + (sizelimit))
+
+ if (context->in_clinit) {
+ /* Make sure that this clinit pointer is not null */
+ sysAssert(context->pass2.clinit_ptr != NULL);
+
+ ALLOC_BLOCK(context->pass2.clinit_ptr,
+ context->pass2.clinit_buffer,
+ context->clinit_size*sizeof(char));
+
+ } else {
+
+ /* Make sure that this malloc pointer is not null */
+ sysAssert(context->pass2.malloc_ptr != NULL);
+
+ ALLOC_BLOCK(context->pass2.malloc_ptr,
+ context->pass2.malloc_buffer,
+ context->malloc_size);
+ }
+ }
+ return result;
+}
+
+
+/*=========================================================================
+ * FUNCTION: freeBuffers
+ * OVERVIEW: Frees buffers allocated by allocNBytes().
+ *
+ * INTERFACE:
+ * parameters: CICcontext *: context
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void freeBuffers(CICcontext * context)
+{
+ if (context->pass == 1) {
+ CICmallocs *mallocs = context->pass1.mallocs;
+
+ while (mallocs) {
+ CICmallocs *tmp = mallocs;
+ mallocs = mallocs->next;
+ if (tmp != NULL) {
+ sysFree(tmp);
+ }
+ }
+ context->pass1.mallocs = 0;
+ } else { /* context->pass = 2 */
+
+/* Note: this code is here just for historical reasons. Actually, these
+ * buffers cannot really be freed here since the data in them is still
+ * pointed to by the class buffer (cb) and we are not yet done loading
+ * the class. If the class loading fails, FreeClass() will free the method
+ * blocks and the clinit memory.
+ */
+ if (context->pass2.malloc_buffer != NULL) {
+ sysFree(context->pass2.malloc_buffer);
+ /* Reset only if buffer was freed */
+ context->pass2.malloc_buffer = 0;
+ }
+
+ if (context->pass2.clinit_buffer != NULL) {
+ sysFree(context->pass2.clinit_buffer);
+ /* Initialize only if buffer was freed */
+ context->pass2.clinit_buffer = 0;
+ }
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: GetClassConstantClassName
+ * OVERVIEW: Returns class name corresponding to the constant pool entry
+ * for the given cpIndex. This is desirable in cases when we
+ * may simply be interested in the name of the class, but may
+ * not necessarily want to resolve the class reference if it
+ * isn't already.
+ *
+ * INTERFACE:
+ * parameters: cp_item_type *: constant pool
+ * int : index
+ *
+ * returns: char *: class name
+ *=======================================================================*/
+char *GetClassConstantClassName(cp_item_type *constant_pool, int index)
+{
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ switch(type_table[index]) {
+ case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED: {
+ ClassClass *cb = constant_pool[index].clazz;
+ return cbName(cb);
+ }
+
+ case CONSTANT_Class: {
+ int name_index = constant_pool[index].i;
+ return constant_pool[name_index].cp;
+ }
+
+ default:
+ return (char *)0;
+ }
+}
+
diff --git a/MPC.3.5.LINUX/preverifier/classresolver.c b/MPC.3.5.LINUX/preverifier/classresolver.c
--- /dev/null
@@ -0,0 +1,1269 @@
+/*
+ * @(#)classresolver.c 1.19 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: class resolver.c.
+ * FILE: classresolver.c
+ * OVERVIEW: Routines for loading and resolving class definitions.
+ * These routines should not be depending upon the interpreter
+ * or the garbage collector.
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Modifications for CLDC compliance checks,
+ * Tasneem Sayeed, Sun Microsystems
+ * Frank Yellin, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "oobj.h"
+#include "tree.h"
+#include "signature.h"
+#include "path.h"
+#include "sys_api.h"
+#include "convert_md.h"
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+ClassClass *classJavaLangObject;
+ClassClass *classJavaLangClass = 0;
+ClassClass *classJavaLangString;
+ClassClass *classJavaLangThrowable;
+ClassClass *classJavaLangError;
+ClassClass *classJavaLangException;
+ClassClass *classJavaLangRuntimeException;
+ClassClass *classJavaLangThreadDeath;
+
+ClassClass *interfaceJavaLangCloneable;
+ClassClass *interfaceJavaIoSerializable;
+
+bool_t inline_jsr_on = TRUE;
+
+static bool_t RunClinit(ClassClass * cb);
+
+static ClassClass *InitializeAndResolveClass(ClassClass *cb, bool_t resolve);
+static char *Locked_InitializeClass(ClassClass * cb, char **detail);
+static char *Locked_LinkClass(ClassClass * cb, char **detail);
+char * LinkClass(ClassClass *cb, char **detail);
+static ClassClass *FindLoadedClass(char *name,
+ struct Hjava_lang_ClassLoader *loader);
+static ClassClass *Locked_FindArrayClassFromClass(struct execenv *ee,
+ char *name,
+ ClassClass *from);
+static void InitPrimitiveClasses();
+
+/* An Explanation of Class-related Locks
+ *
+ * There are two global locks related to class loading:
+ *
+ * LOADCLASS_LOCK: ensures that only one thread is loading a class at
+ * a given time. This eliminates the possibility of two threads loading
+ * classes with the same name and same loader.
+ *
+ * BINCLASS_LOCK: ensures that only one thread is updating the global
+ * class table (binclasses). This lock is also grabbed by the GC to ensure
+ * that the GC always sees a valid global class table state.
+ *
+ * In addition, each class may have its own associated locks that are
+ * created with monitorEnter(). ResolveClass, for example, need to
+ * first grab this lock to ensure that the class is resolved only by
+ * one thread, rather than simultaneously by multiple threads.
+ */
+
+sys_mon_t *_loadclass_lock;
+sys_mon_t *_binclass_lock;
+
+static struct fieldblock **
+addslots(struct fieldblock ** fb, ClassClass * cb)
+{
+ long n = cbFieldsCount(cb);
+ struct fieldblock *sfb = cbFields(cb);
+ if (cbSuperclass(cb))
+ fb = addslots(fb, cbSuperclass(cb));
+ while (--n >= 0) {
+ *fb++ = sfb;
+ sfb++;
+ }
+ return fb;
+}
+
+int
+Locked_makeslottable(ClassClass * clb)
+{
+ ClassClass *sclb;
+ int nslots = 0;
+
+ if (cbSlotTable(clb)) {
+ return SYS_OK;
+ }
+ sclb = clb;
+ while (sclb) {
+ long n = cbFieldsCount(sclb);
+ struct fieldblock *fb = cbFields(sclb);
+ while (--n >= 0) {
+ nslots++;
+ fb++;
+ }
+ if (cbSuperclass(sclb) == 0) {
+ break;
+ }
+ sclb = cbSuperclass(sclb);
+ }
+ cbSlotTableSize(clb) = nslots;
+ if (nslots == 0) {
+ nslots++;
+ }
+ cbSlotTable(clb) = (struct fieldblock **)
+ sysMalloc(nslots * sizeof(struct fieldblock *));
+ if (cbSlotTable(clb) == 0) {
+ return SYS_NOMEM;
+ }
+ addslots(cbSlotTable(clb), clb);
+ return SYS_OK;
+}
+
+int
+makeslottable(ClassClass * clb)
+{
+ int result;
+ LOADCLASS_LOCK();
+ result = Locked_makeslottable(clb);
+ LOADCLASS_UNLOCK();
+ return result;
+}
+
+#if 0
+static char *
+copyclassname(char *src, char *dst)
+{
+ sysAssert(*src == SIGNATURE_CLASS);
+ src++;
+ while (*src && *src != SIGNATURE_ENDCLASS)
+ *dst++ = *src++;
+ *dst = 0;
+ return src;
+}
+#endif
+
+static char *
+ResolveFields(ClassClass *cb, unsigned slot)
+{
+ struct fieldblock *fb;
+ int size;
+
+ fb = cbFields(cb);
+ for (size = 0; size < (int) cbFieldsCount(cb); size++, fb++) {
+ char *signature = fieldsig(fb);
+ int size = (((signature[0] == SIGNATURE_LONG ||
+ signature[0] == SIGNATURE_DOUBLE)) ? 2 : 1);
+ fb->ID = NameAndTypeToHash(fb->name, signature);
+ if (fb->access & ACC_STATIC) {
+ /* Do nothing. Handled when the class is loaded. */
+ } else {
+ fb->u.offset = slot;
+ slot += size * sizeof(OBJECT);
+ }
+#ifdef UNUSED
+ if ((fb->access & (ACC_STATIC | ACC_TRANSIENT)) == 0) {
+ for (s = fieldname(fb); (c = *s++) != 0;)
+ thishash = thishash * 7 + c;
+ for (s = fieldsig(fb); (c = *s++) != 0;)
+ thishash = thishash * 7 + c;
+ }
+#endif
+ }
+ if (slot > 65535) {
+ return "java/lang/InternalError";
+ }
+
+ cbInstanceSize(cb) = slot;
+#ifdef UNUSED
+ cbThisHash(cb) = thishash;
+ if (cbSuperclass(cb))
+ cbTotalHash(cb) = thishash - cbTotalHash(unhand(cbSuperclass(cb)));
+ else
+ cbTotalHash(cb) = thishash;
+ if (cbTotalHash(cb) < N_TYPECODES)
+ cbTotalHash(cb) += N_TYPECODES;
+#endif
+ return NULL;
+}
+
+
+static char *
+ResolveMethods(ClassClass *cb)
+{
+ struct methodblock *mb;
+ int size;
+ struct methodtable *new_table;
+ struct methodblock **super_methods;
+ int mslot, super_methods_count;
+ void *ptr;
+ static unsigned finalizerID = 0;
+
+ if (finalizerID == 0)
+ finalizerID = NameAndTypeToHash(FINALIZER_METHOD_NAME,
+ FINALIZER_METHOD_SIGNATURE);
+ mb = cbMethods(cb);
+ for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
+ mb->fb.ID = NameAndTypeToHash(mb->fb.name, mb->fb.signature);
+ mb->fb.u.offset = 0;
+ mb->invoker = 0;
+ }
+
+ if (cbIsInterface(cb)) {
+ /* We don't really need to built a method table for interfaces. */
+ cbMethodTable(cb) = NULL;
+ cbMethodTableSize(cb) = 0;
+ mb = cbMethods(cb);
+ /* Each method's offset is its index in the interface */
+ for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
+ mb->fb.u.offset = size;
+ }
+ return NULL;
+ }
+
+ if (cbSuperclass(cb) != NULL) {
+ ClassClass *super = cbSuperclass(cb);
+ mslot = cbMethodTableSize(super);
+ super_methods = cbMethodTable(super)->methods;
+ super_methods_count = cbMethodTableSize(super);
+ /* Inherit one's parent's finalizer, if it has one */
+ cbFinalizer(cb) = cbFinalizer(cbSuperclass(cb));
+ } else {
+ mslot = 1;
+ super_methods = NULL;
+ super_methods_count = 0;
+ cbFinalizer(cb) = NULL;
+ }
+
+ mb = cbMethods(cb);
+ for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
+ unsigned long ID = mb->fb.ID;
+ struct methodblock **super_methods_p;
+ int count;
+
+ if ((mb->fb.access & ACC_STATIC) || (mb->fb.access & ACC_PRIVATE))
+ continue;
+ if (strcmp(mb->fb.name, "<init>") == 0)
+ continue;
+
+ /* If this item has its own finalizer method, grab it */
+ if (mb->fb.ID == finalizerID) {
+ if (no_finalizers) {
+ panic("finalize methods should not appear");
+ }
+ cbFinalizer(cb) = mb;
+ }
+
+ for (super_methods_p = super_methods, count = super_methods_count;
+ count > 0;
+ super_methods_p++, count--) {
+ if ((*super_methods_p != NULL) && ((*super_methods_p)->fb.ID == ID)) {
+ /* Private methods are not inherited outside of the class. */
+ if ((*super_methods_p)->fb.access & ACC_PRIVATE)
+ continue;
+ /* Package-private methods are not inherited outside of the
+ package. */
+ if (((*super_methods_p)->fb.access & ACC_PROTECTED) ||
+ ((*super_methods_p)->fb.access & ACC_PUBLIC) ||
+ IsSameClassPackage((*super_methods_p)->fb.clazz, cb)) {
+ mb->fb.u.offset = (*super_methods_p)->fb.u.offset;
+ break;
+ }
+ /*
+ jio_fprintf(stderr, "!!!%s.%s\n", cbName(cb), mb->fb.name);
+ */
+ }
+ }
+
+ if (mb->fb.u.offset == 0) {
+ mb->fb.u.offset = mslot;
+ mslot++;
+ }
+ }
+
+ if (mslot > 65535) {
+ return "java/lang/InternalError";
+ }
+
+ /*
+ * This should be the only place that method tables are
+ * allocated. We allocate more than we need here and mask the
+ * resulting pointer because the methodtable pointer field in
+ * object handles is overloaded and sometimes hold array types
+ * and array lengths. We must ensure that method table pointers
+ * are allocated on an appropriate boundary so we don't lose any
+ * address bits when we mask off the type portion of the pointer.
+ */
+ ptr = sysMalloc(sizeof(struct methodtable)
+ + (mslot - 1)* sizeof(struct methodblock *)
+ + FLAG_MASK);
+ if (ptr == NULL) {
+ CCSet(cb, Error);
+ return JAVAPKG "OutOfMemoryError";
+ }
+ cbMethodTableMem(cb) = ptr;
+ new_table = (struct methodtable *)((((long)ptr) + FLAG_MASK) & LENGTH_MASK);
+ new_table->classdescriptor = cb;
+ memset((char *)new_table->methods, 0, mslot * sizeof(struct methodblock *));
+ if (super_methods)
+ memcpy((char *) new_table->methods,
+ (char *) super_methods,
+ super_methods_count * sizeof(struct methodblock *));
+ mb = cbMethods(cb);
+ for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
+ int offset = (int)mb->fb.u.offset;
+ if (offset > 0) {
+ sysAssert(offset < mslot);
+ mt_slot(new_table, offset) = mb;
+ }
+ }
+ cbMethodTable(cb) = new_table;
+ cbMethodTableSize(cb) = mslot;
+
+ return NULL;
+}
+
+
+static char *
+ResolveInterfaces(ClassClass *cb, char **detail)
+{
+ const int ITEM_SIZE = sizeof(cbIntfMethodTable(cb)->itable[0]);
+ bool_t isInterface = cbIsInterface(cb);
+ if (cbImplementsCount(cb) == 0 && !isInterface) {
+ /* classes that don't implement their own interfaces can just inherit
+ * their parents imethodtable. */
+ if (cb == classJavaLangObject) {
+ /* We can preinitialize the imethodtable of java.lang.Object */
+ static struct imethodtable t = { 0 };
+ cbIntfMethodTable(cb) = &t;
+ } else {
+ ClassClass *super = cbSuperclass(cb);
+ cbIntfMethodTable(cb) = cbIntfMethodTable(super);
+ }
+ return NULL;
+ } else {
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ ClassClass *super = cbSuperclass(cb);
+ unsigned char *mallocSpace, *mallocSpaceEnd;
+ ClassClass *icb; /* temporary */
+ struct imethodtable *super_itable = cbIntfMethodTable(super);
+ struct imethodtable *this_itable = NULL;
+ int super_itable_count = super_itable->icount;
+ int i, j, k, icount, mcount;
+
+ /* Resolve all the interfaces that this class implements, and
+ * make sure that they all really are interfaces
+ *
+ * icount will total all the interfaces that this class implements,
+ * (include interfaces implemented by our superclass, and by
+ * interfaces that we implement.)
+ * mcount will total the total amount of space (in sizeof(long)) for
+ * which we'll have to allocate space for in the offsets table.
+ */
+ icount = super_itable_count + (isInterface ? 1 : 0);
+ mcount = 0;
+ for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
+ int interface_index = cbImplements(cb)[i];
+ struct imethodtable *sub_itable;
+
+ icb = constant_pool[interface_index].clazz;
+ if (!cbIsInterface(icb)) {
+ *detail = "Implementing class";
+ return JAVAPKG "IncompatibleClassChangeError";
+ }
+ sub_itable = cbIntfMethodTable(icb);
+ icount += sub_itable->icount;
+ if (!isInterface)
+ for (j = sub_itable->icount; --j >= 0; )
+ mcount += cbMethodsCount(sub_itable->itable[j].classdescriptor);
+ }
+
+ {
+ int this_itable_size =
+ offsetof(struct imethodtable, itable) + icount * ITEM_SIZE;
+ int offsets_size = mcount * sizeof(unsigned long);
+ mallocSpace = sysMalloc(this_itable_size + offsets_size);
+ if (mallocSpace == NULL) {
+ return JAVAPKG "OutOfMemoryError";
+ }
+ mallocSpaceEnd = mallocSpace + this_itable_size + offsets_size;
+ this_itable = (struct imethodtable *)mallocSpace;
+ mallocSpace += this_itable_size;
+ sysAssert(mallocSpace <= mallocSpaceEnd);
+ }
+
+ cbIntfMethodTable(cb) = this_itable;
+
+ /* Start filling in the table. */
+ icount = 0;
+ if (isInterface) {
+ this_itable->itable[icount].classdescriptor = cb;
+ this_itable->itable[icount].offsets = NULL;
+ icount++;
+ }
+ if (super_itable_count > 0) {
+ /* We can copy our superclass's offset table. The offsets
+ will stay the same. */
+ memcpy(&this_itable->itable[icount],
+ &super_itable->itable[0],
+ super_itable_count * ITEM_SIZE);
+ icount += super_itable_count;
+ }
+ for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
+ /* Add the interfaces that we implement, either directly, or
+ * because those interfaces implement other interfaces. */
+ int interface_index = cbImplements(cb)[i];
+ icb = constant_pool[interface_index].clazz;
+ memcpy(&this_itable->itable[icount],
+ &cbIntfMethodTable(icb)->itable[0],
+ cbIntfMethodTable(icb)->icount * ITEM_SIZE);
+ icount += cbIntfMethodTable(icb)->icount;
+ }
+ sysAssert(!isInterface || super_itable_count == 0);
+ /* Delete duplicates from the table. This is very rare, so it can
+ * be quite inefficient. */
+ for (i = (isInterface ? 1 : super_itable_count); i < icount; i++) {
+ icb = this_itable->itable[i].classdescriptor;
+ for (j = 0; j < i; j++) {
+ if (icb == this_itable->itable[j].classdescriptor) {
+ /* We have an overlap. Item i is a duplicate. Delete from
+ * the table */
+ for (k = i + 1; k < icount; k++)
+ this_itable->itable[k - 1] = this_itable->itable[k];
+ icount--;
+ i--; /* Reconsider this entry! */
+ break;
+ }
+ }
+ }
+ this_itable->icount = icount;
+ if (isInterface || cbIsAbstract(cb)) {
+ /* Nothing more to do for interfaces or abstract classes */
+ return NULL;
+ }
+
+ /* For each additional interface . . . */
+ for (i = super_itable_count; i < icount; i++) {
+ /* The table length is the number of interface methods */
+ ClassClass *intfi = this_itable->itable[i].classdescriptor;
+ int intfi_count = cbMethodsCount(intfi);
+ unsigned long *offsets = (unsigned long *)mallocSpace;
+ mallocSpace += intfi_count * sizeof(unsigned long);
+ sysAssert(mallocSpace <= mallocSpaceEnd);
+ this_itable->itable[i].offsets = offsets;
+ /* Look at each interface method */
+ for (j = 0; j < intfi_count; j++) {
+ struct methodblock *imb = cbMethods(intfi) + j;
+ if ((imb->fb.access & ACC_STATIC) != 0) {
+ sysAssert(!strcmp(imb->fb.name, "<clinit>"));
+ offsets[j] = 0;
+ } else {
+ /* Find the class method that implements the interface
+ * method */
+ unsigned ID = imb->fb.ID;
+ struct methodblock **mbt = cbMethodTable(cb)->methods;
+ for (k = cbMethodTableSize(cb) - 1; k >= 0; --k) {
+ struct methodblock *mb = mbt[k];
+ if (mb != NULL
+ && mb->fb.ID == ID && IsPublic(mb->fb.access)) {
+ offsets[j] = mb->fb.u.offset;
+ break;
+ }
+ }
+ /*
+ if (k == -1) {
+ *detail = "Unimplemented interface method";
+ return JAVAPKG "IncompatibleClassChangeError";
+ }
+ */
+ }
+ }
+ }
+ return NULL;
+ }
+}
+
+
+char *
+InitializeClass(ClassClass * cb, char **detail)
+{
+ char *result;
+ monitorEnter(obj_monitor(cb));
+ result = Locked_InitializeClass(cb, detail);
+ monitorExit(obj_monitor(cb));
+ return result;
+}
+
+
+char *
+ResolveClass(ClassClass *cb, char **detail)
+{
+ char *result;
+ if (CCIs(cb, Resolved))
+ return 0;
+ result = LinkClass(cb, detail);
+ if (result == 0) {
+ if (!RunClinit(cb)) {
+ result = JAVAPKG "ExceptionInInitializerError";
+ *detail = cbName(cb);
+ }
+ }
+ return result;
+}
+
+char *
+LinkClass(ClassClass *cb, char **detail)
+{
+ char *result;
+ if (CCIs(cb, Linked))
+ return 0;
+ monitorEnter(obj_monitor(cb));
+ result = Locked_LinkClass(cb, detail);
+ monitorExit(obj_monitor(cb));
+ return result;
+}
+
+/*
+ * Detect class circularities from InitializeClass()
+ */
+
+static void
+pushSeen(ExecEnv *ee, struct seenclass *seen)
+{
+ struct seenclass *prev = ee->seenclasses.next;
+ ee->seenclasses.next = seen;
+ seen->next = prev;
+}
+
+static void
+popSeen(ExecEnv *ee, struct seenclass *seen)
+{
+ if (seen != ee->seenclasses.next) /* paranoia */
+ panic("popSeen: corrupt seen class stack");
+ ee->seenclasses.next = ee->seenclasses.next->next;
+}
+
+static bool_t
+checkSeen(ExecEnv *ee, ClassClass *cb)
+{
+ struct seenclass *seen = ee->seenclasses.next;
+ while (seen) {
+ if (cb == seen->cb)
+ return TRUE;
+ seen = seen->next;
+ }
+ return FALSE;
+}
+
+static char *
+Locked_InitializeClass(ClassClass * cb, char **detail)
+{
+ ClassClass *super = 0;
+ char *ret = 0;
+ bool_t noLoader;
+ int i;
+ char buff[BUFSIZ];
+ char *nativeName = &buff[0];
+
+ if (CCIs(cb, Initialized))
+ return NULL;
+
+#ifndef TRIMMED
+ if (verbose)
+ jio_fprintf(stderr, "[Initializing %s]\n", cbName(cb));
+#endif
+
+ noLoader = (cbLoader(cb) == 0);
+ if (cbFieldsCount(cb) > 2000) {
+ return JAVAPKG "ClassFormatError";
+ }
+ if ((strcmp(cbName(cb), CLS_RESLV_INIT_CLASS) == 0) && noLoader) {
+ /* Temporarily disable class circularity checks */
+ ExecEnv *ee = EE();
+ struct seenclass *save = ee->seenclasses.next;
+ ee->seenclasses.next = NULL;
+ /* Note: don't bother restoring on (fatal) error during bootstrap */
+
+ classJavaLangClass = cb;
+ MakeClassSticky(cb);
+ classJavaLangString =
+ FindStickySystemClass(NULL, JAVAPKG "String", TRUE);
+ if (classJavaLangString == 0) {
+ *detail = JAVAPKG "String";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+/* classJavaLangThreadDeath =
+ FindStickySystemClass(NULL, JAVAPKG "ThreadDeath", TRUE);
+ if (classJavaLangThreadDeath == 0) {
+ *detail = JAVAPKG "ThreadDeath";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ */
+ classJavaLangThrowable =
+ FindStickySystemClass(NULL, JAVAPKG "Throwable", TRUE);
+ if (classJavaLangThrowable == 0) {
+ *detail = JAVAPKG "Throwable";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ /*
+ classJavaLangException =
+ FindStickySystemClass(NULL, JAVAPKG "Exception", TRUE);
+ if (classJavaLangException == 0) {
+ *detail = JAVAPKG "Exception";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ classJavaLangError =
+ FindStickySystemClass(NULL, JAVAPKG "Error", TRUE);
+ if (classJavaLangError == 0) {
+ *detail = JAVAPKG "Error";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ classJavaLangRuntimeException =
+ FindStickySystemClass(NULL, JAVAPKG "RuntimeException", TRUE);
+ if (classJavaLangRuntimeException == 0) {
+ *detail = JAVAPKG "RuntimeException";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ interfaceJavaLangCloneable =
+ FindStickySystemClass(NULL, JAVAPKG "Cloneable", TRUE);
+ if (interfaceJavaLangCloneable == 0) {
+ *detail = JAVAPKG "Cloneable";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ interfaceJavaIoSerializable =
+ FindStickySystemClass(NULL, "java/io/Serializable", TRUE);
+ if (interfaceJavaIoSerializable == 0) {
+ *detail = "java/io/Serializable";
+ return JAVAPKG "NoClassDefFoundError";
+ }
+*/
+ /* Restore stack for class circularity checks */
+ ee->seenclasses.next = save;
+
+ } else if ((strcmp(cbName(cb), CLS_RESLV_INIT_OBJECT) == 0) && noLoader){
+ classJavaLangObject = cb;
+ MakeClassSticky(classJavaLangObject);
+ }
+
+ if (noLoader) {
+ char *name = cbName(cb);
+ if (strcmp(name, CLS_RESLV_INIT_REF) == 0) {
+ CCSet(cb, SoftRef);
+ }
+ if (strncmp(name, "java/", 5) || strncmp(name, "sun/", 4)) {
+ CCSet(cb, SysLock);
+ }
+ }
+ if (cbSuperclass(cb) == NULL) {
+ if (cbSuperName(cb)) {
+ /* Check for class definition circularities */
+ ExecEnv *ee = EE();
+ struct seenclass this[1];
+ if (checkSeen(ee, cb)) {
+ *detail = cbName(cb);
+ CCSet(cb, Error);
+ return JAVAPKG "ClassCircularityError";
+ }
+ this->cb = cb;
+ this->next = NULL;
+ pushSeen(ee, this);
+
+ /* Conversion for Japanese file names */
+ utf2native(cbSuperName(cb), nativeName, BUFSIZ);
+
+ super = FindClassFromClass(ee, nativeName, FALSE, cb);
+
+ popSeen(ee, this);
+ if (super != NULL) {
+ sysAssert(CCIs(super, Initialized));
+ /* Don't allow a class to have a superclass it can't access */
+ if (!VerifyClassAccess(cb, super, FALSE)) {
+ super = NULL;
+ }
+ }
+ if (super != NULL) {
+ cbSuperclass(cb) = cbHandle(super);
+ if (CCIs(super, SoftRef))
+ CCSet(cb, SoftRef);
+ } else {
+ ret = JAVAPKG "NoClassDefFoundError";
+ *detail = cbSuperName(cb);
+ cbSuperclass(cb) = NULL;
+ CCSet(cb, Error);
+ }
+ } else if (cb == classJavaLangObject) {
+ cbSuperclass(cb) = 0;
+ } else {
+ *detail = cbName(cb);
+ return JAVAPKG "ClassFormatException";
+ }
+ }
+
+ for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
+ /* Be very careful, since not verified yet. . .
+ */
+ int interface_index = cbImplements(cb)[i];
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ ClassClass *icb;
+ int nconstants = cbConstantPoolCount(cb);
+ int iname_index;
+ char *iname;
+
+ if (interface_index <= 0 ||
+ interface_index >= nconstants ||
+ type_table[interface_index] != CONSTANT_Class ||
+ !(iname_index = constant_pool[interface_index].i) ||
+ iname_index <= 0 ||
+ iname_index >= nconstants ||
+ type_table[iname_index] !=
+ (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) {
+ *detail = "Bad interface index";
+ return JAVAPKG "ClassFormatError";
+ }
+
+ iname = constant_pool[iname_index].cp;
+// if (iname == NULL || !IsLegalClassname(iname, FALSE)) {
+// *detail = "Bad interface name";
+// return JAVAPKG "ClassFormatError";
+// }
+
+ {
+ ExecEnv *ee = EE();
+ struct seenclass this[1];
+ if (checkSeen(ee, cb)) {
+ *detail = cbName(cb);
+ CCSet(cb, Error);
+ return JAVAPKG "ClassCircularityError";
+ }
+ this->cb = cb;
+ this->next = NULL;
+ pushSeen(ee, this);
+ icb = FindClassFromClass(ee, iname, FALSE, cb);
+ popSeen(ee, this);
+ if (icb) {
+ constant_pool[interface_index].clazz = icb;
+ type_table[interface_index] |= CONSTANT_POOL_ENTRY_RESOLVED;
+ } else {
+ *detail = iname;
+ CCSet(cb, Error);
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ }
+ }
+
+ CCSet(cb, Initialized);
+
+ /* Make sure we know what classJavaLangClass is, and that it's method table
+ * is filled in.
+ */
+ if (classJavaLangClass == 0) {
+ classJavaLangClass =
+ FindClassFromClass(0, CLS_RESLV_INIT_CLASS, TRUE, cb);
+ if (classJavaLangClass == 0) {
+ return JAVAPKG "NoClassDefFoundError";
+ }
+ }
+
+ /* The following may not do anything useful if classJavaLangClass hasn't
+ * been completely resolved. But we clean up in ResolveClass
+ */
+
+ cbHandle(cb)->methods = cbMethodTable(classJavaLangClass);
+ return ret;
+}
+
+static char *
+Locked_LinkClass(ClassClass * cb, char **detail)
+{
+ ClassClass *super = 0;
+ unsigned slot = 0;
+ char *ret = 0;
+ int i;
+
+ if (CCIs(cb, Error)) {
+ *detail = cbName(cb);
+ return JAVAPKG "NoClassDefFoundError";
+ }
+
+ sysAssert(CCIs(cb, Initialized));
+
+ if (CCIs(cb, Linked)) {
+ return NULL;
+ }
+
+ if (cbSuperclass(cb)) {
+ /* If this object has a superclass. . . */
+ super = cbSuperclass(cb);
+ if (!CCIs(super, Linked)) {
+ if ((ret = LinkClass(super, detail)) != 0) {
+ CCSet(cb, Error);
+ return ret;
+ }
+ }
+ sysAssert(CCIs(super, Linked));
+ slot = cbInstanceSize(super);
+ }
+
+ for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
+ int interface_index = cbImplements(cb)[i];
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ ClassClass *icb;
+ icb = constant_pool[interface_index].clazz;
+ if (!CCIs(icb, Linked)) {
+ if ((ret = LinkClass(icb, detail)) != 0) {
+ CCSet(cb, Error);
+ return ret;
+ }
+ }
+ }
+
+ sysAssert(!CCIs(cb, Error));
+ sysAssert(!CCIs(cb, Linked));
+
+#ifndef TRIMMED
+ if (verbose)
+ jio_fprintf(stderr, "[Resolving %s]\n", cbName(cb));
+#endif
+ cbInstanceSize(cb) = -1;
+ if ((ret = ResolveFields(cb, slot))) { /* May return "InternalError" */
+ *detail = cbName(cb);
+ CCSet(cb, Error);
+ return ret;
+ }
+
+ if ((ret = ResolveMethods(cb))) {
+ /* May return "OutOfMemoryError" or "InternalError" */
+ *detail = cbName(cb);
+ CCSet(cb, Error);
+ return ret;
+ }
+
+ if ((ret = ResolveInterfaces(cb, detail))) { /* All sorts of errors */
+ CCSet(cb, Error);
+ return ret;
+ }
+
+ InitializeInvoker(cb);
+
+ if ((verifyclasses == VERIFY_ALL) ||
+ ((verifyclasses == VERIFY_REMOTE) && (cbLoader(cb) != NULL))) {
+ if (!VerifyClass(cb)) {
+ *detail = "";
+ return JAVAPKG "VerifyError";
+ }
+ }
+
+ CCSet(cb, Linked);
+
+ /* We need this for bootstrapping. We can't set the Handle's class block
+ * pointer in Object or Class until Class has been resolved.
+ */
+ if (cb == classJavaLangClass) {
+ int j;
+ ClassClass **pcb;
+ BINCLASS_LOCK();
+ for (j = nbinclasses, pcb = binclasses; --j >= 0; pcb++) {
+ cbHandle(*pcb)->methods = cbMethodTable(cb);
+ }
+ BINCLASS_UNLOCK();
+ InitPrimitiveClasses();
+ }
+ return NULL;
+}
+
+static bool_t
+RunClinit(ClassClass * cb)
+{
+
+ if (CCIs(cb, Resolved))
+ return TRUE;
+
+ if ((cbName(cb)[0] != SIGNATURE_ARRAY) && !cbIsPrimitive(cb)) {
+ /* Don't need to initialize or verify array or primitive classes */
+ return RunStaticInitializers(cb);
+ } else if (cbName(cb)[0] == SIGNATURE_ARRAY) {
+ ClassClass *inner_cb =
+ cbConstantPool(cb)[CONSTANT_POOL_ARRAY_CLASS_INDEX].clazz;
+ if (inner_cb) {
+ char *detail = 0;
+ char *ret = ResolveClass(inner_cb, &detail);
+ if (ret != NULL) {
+ if (!exceptionOccurred(EE())) {
+ SignalError(0, ret, detail);
+ }
+ CCSet(cb, Error);
+ return FALSE;
+ } else {
+ CCSet(cb, Resolved);
+ }
+ } else {
+ CCSet(cb, Resolved);
+ }
+ } else {
+ CCSet(cb, Resolved);
+ }
+ return TRUE;
+}
+
+
+/* Find an already loaded class with the given name. If no such class exists
+ * then return 0.
+ */
+
+#ifdef DEBUG
+void
+PrintLoadedClasses()
+{
+ int j;
+ ClassClass **pcb, *cb;
+ BINCLASS_LOCK();
+ pcb = binclasses;
+ for (j = nbinclasses; --j >= 0; pcb++) {
+ cb = *pcb;
+ jio_fprintf(stdout, "class=%s, 0x%x\n", cbName(cb), cbLoader(cb));
+ }
+ BINCLASS_UNLOCK();
+}
+#endif
+
+static ClassClass *
+FindLoadedClass(char *name, struct Hjava_lang_ClassLoader *loader)
+{
+ int left, right, middle, result;
+ ClassClass *cb = NULL;
+
+ BINCLASS_LOCK();
+ left = 0;
+ right = nbinclasses - 1;
+ result = 1;
+ while (left <= right) {
+ middle = (left + right)/2;
+ cb = binclasses[middle];
+ result = strcmp(name, cbName(cb));
+ if (result == 0) {
+ if (loader < cbLoader(cb)) {
+ result = -1;
+ } else if (loader > cbLoader(cb)) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ }
+ if (result < 0) {
+ right = middle - 1;
+ } else if (result > 0) {
+ left = middle + 1;
+ } else {
+ break;
+ }
+ }
+
+ BINCLASS_UNLOCK();
+ if (result == 0) {
+ return cb;
+ }
+ return NULL;
+}
+
+/* We attempt to resolve it, also, if the "resolve" argument is true.
+ * Otherwise, we only perform a minimal initialization on it, such that
+ * it points to its superclass, which points to its superclass. . . .
+ */
+
+static ClassClass *
+InitializeAndResolveClass(ClassClass *cb, bool_t resolve)
+{
+ char *err, *detail = NULL;
+ if ((err = InitializeClass(cb, &detail))) {
+ /* Check for underlying error already posted */
+ if (!exceptionOccurred(EE()))
+ SignalError(0, err, detail);
+ return 0;
+ }
+ if (resolve) {
+ err = ResolveClass(cb, &detail);
+ if (err) {
+ /* Check for underlying error already posted */
+ if (!exceptionOccurred(EE()))
+ SignalError(0, err, detail);
+ return 0;
+ }
+ }
+ return cb;
+}
+
+/* Find the class with the given name.
+ * If "resolve" is true, then we completely resolve the class. Otherwise,
+ * we only make sure that it points to its superclass, which points to its
+ * superclass, . . . .
+ */
+ClassClass *(*class_loader_func)(HObject *loader, char *name, long resolve) = 0;
+
+ClassClass *
+FindClass(struct execenv *ee, char *name, bool_t resolve)
+{
+ return FindClassFromClass(ee, name, resolve, 0);
+}
+
+
+/*
+ * lock_classes and unlock_classes are exported by the JIT interface,
+ * but no longer used anywhere else. It grabs both locks to ensure
+ * backward compatibility with 1.0.2.
+ */
+void
+lock_classes()
+{
+ LOADCLASS_LOCK();
+ BINCLASS_LOCK();
+}
+
+void
+unlock_classes()
+{
+ BINCLASS_UNLOCK();
+ LOADCLASS_UNLOCK();
+}
+
+extern char *output_path;
+
+extern ClassClass *
+LoadClassFromFile(char *fn, char *dir, char *class_name);
+
+ClassClass *
+FindClassFromClass(struct execenv *ee, char *name, bool_t resolve,
+ ClassClass *from)
+{
+ char fn[64];
+ sprintf(fn, "%s.class", name);
+ return LoadClassFromFile(fn, output_path, name);
+}
+
+/*
+ * FindStickySystemClass is a variant of FindClassFromClass that makes the
+ * class sticky (immune to class GC) if the class can be found. It is only
+ * used on system classes, i.e. classes with no class loader, so it's
+ * equivalent to FindClassFromClass with "from" argument 0. It returns 0
+ * if the class can't be found, and like FindClass assumes that the caller
+ * will deal with that. Note that until the class has been made sticky it
+ * must be kept somewhere where GC will find it.
+ */
+ClassClass *
+FindStickySystemClass(struct execenv *ee, char *name, bool_t resolve)
+{
+ ClassClass *cb;
+ if ((cb = FindClassFromClass(ee, name, resolve, 0)) != NULL) {
+ MakeClassSticky(cb);
+ }
+ return cb;
+}
+
+/* Find the array class with the specified name. */
+static ClassClass *
+Locked_FindArrayClassFromClass(struct execenv *ee, char *name,
+ ClassClass *from) {
+ struct Hjava_lang_ClassLoader *fromLoader =
+ (from == NULL) ? NULL : cbLoader(from);
+ char *name_p;
+ int depth, base_type;
+ ClassClass *cb;
+ struct Hjava_lang_ClassLoader *loader;
+ ClassClass *inner_cb;
+
+ sysAssert(name[0] == SIGNATURE_ARRAY);
+
+ if (fromLoader == NULL) {
+ /* quick optimization if we know that we don't need a class loader */
+ cb = FindLoadedClass(name, NULL);
+ if (cb != NULL)
+ return cb;
+ }
+
+
+
+ /* Strip off all the initial SIGNATURE_ARRAY's to determine the depth,
+ * and also what's left. When we're done, name_p points at the first
+ * non-character, and depth is the count of the array depth
+ */
+ for (name_p = name, depth = 0; *name_p == SIGNATURE_ARRAY;
+ name_p++, depth++);
+
+ /* Look at the character to determine what type of array we have. */
+ switch(*name_p++) {
+ case SIGNATURE_INT: base_type = T_INT; break;
+ case SIGNATURE_LONG: base_type = T_LONG; break;
+ case SIGNATURE_FLOAT: base_type = T_FLOAT; break;
+ case SIGNATURE_DOUBLE: base_type = T_DOUBLE; break;
+ case SIGNATURE_BOOLEAN:base_type = T_BOOLEAN; break;
+ case SIGNATURE_BYTE: base_type = T_BYTE; break;
+ case SIGNATURE_CHAR: base_type = T_CHAR; break;
+ case SIGNATURE_SHORT: base_type = T_SHORT; break;
+ case SIGNATURE_CLASS: base_type = T_CLASS; break;
+ default: return NULL; /* bad signature */
+ }
+ if (base_type == T_CLASS) {
+ char buffer_space[50];
+ char *buffer = buffer_space;
+ char *endChar = strchr(name_p, SIGNATURE_ENDCLASS);
+ int nameLength = endChar - name_p;
+ if (endChar == NULL || endChar[1] != '\0')
+ return NULL;
+ if (nameLength >= sizeof(buffer_space)) /* need bigger buffer */
+ buffer = sysMalloc(nameLength + 1);
+ memcpy(buffer, name_p, nameLength);
+ buffer[nameLength] = '\0';
+ inner_cb = FindClassFromClass(ee, buffer, FALSE, from);
+ if (buffer != buffer_space) /* free buffer, if we malloc'ed it */
+ sysFree(buffer);
+ if (inner_cb == NULL)
+ return NULL;
+ /* loader should either be fromLoader or NULL. */
+ loader = cbLoader(inner_cb);
+ } else {
+ if (*name_p != '\0') /* bad signature */
+ return NULL;
+ inner_cb = NULL;
+ loader = NULL;
+ }
+
+
+ LOADCLASS_LOCK();
+ cb = FindLoadedClass(name, loader);
+ if (cb == NULL) {
+ /* Create the fake array class corresponding to this.
+ */
+ cb = createFakeArrayClass(name, base_type, depth, inner_cb, loader);
+ }
+ LOADCLASS_UNLOCK();
+ return cb;
+}
+
+/*
+ * Convert a name and type to a hash code
+ *
+ * We make copies of all strings that go into the hash table
+ * in case the class that is the source of the strings being
+ * inserted is eventually unloaded.
+ */
+unsigned NameAndTypeToHash(char *name, char *type)
+{
+ extern struct StrIDhash *nameTypeHash;
+
+ unsigned name_key;
+ unsigned type_key;
+ unsigned ret;
+
+ NAMETYPEHASH_LOCK();
+ if (((name_key = Str2ID(&nameTypeHash, name, 0, TRUE)) == 0) ||
+ ((type_key = Str2ID(&nameTypeHash, type, 0, TRUE)) == 0)) {
+ SignalError(0, JAVAPKG "OutOfMemoryError", 0);
+ ret = 0;
+ } else {
+ ret = (name_key << 16) + type_key;
+ }
+ NAMETYPEHASH_UNLOCK();
+
+ return ret;
+}
+
+/*
+ * Pseudo-classes to represent primitive Java types.
+ */
+
+ClassClass *class_void;
+ClassClass *class_boolean;
+ClassClass *class_byte;
+ClassClass *class_char;
+ClassClass *class_short;
+ClassClass *class_int;
+ClassClass *class_long;
+ClassClass *class_float;
+ClassClass *class_double;
+
+struct primtype {
+ char *name;
+ char typesig;
+ unsigned char typecode;
+ unsigned char slotsize;
+ unsigned char elementsize;
+ ClassClass **cellp;
+} const primitive_types[] = {
+ { "void", SIGNATURE_VOID, T_VOID, 0, 0, &class_void },
+ { "boolean",SIGNATURE_BOOLEAN, T_BOOLEAN, 4, 1, &class_boolean },
+ { "byte", SIGNATURE_BYTE, T_BYTE, 4, 1, &class_byte },
+ { "char", SIGNATURE_CHAR, T_CHAR, 4, 2, &class_char },
+ { "short", SIGNATURE_SHORT, T_SHORT, 4, 2, &class_short },
+ { "int", SIGNATURE_INT, T_INT, 4, 4, &class_int },
+ { "long", SIGNATURE_LONG, T_LONG, 8, 8, &class_long },
+ { "float", SIGNATURE_FLOAT, T_FLOAT, 4, 4, &class_float },
+ { "double", SIGNATURE_DOUBLE, T_DOUBLE, 8, 8, &class_double }
+};
+
+#define PRIMITIVE_TYPE_COUNT \
+ (sizeof (primitive_types) / sizeof (primitive_types[0]))
+
+#define GET_PRIMITIVE_CLASS(nm) \
+ (class_##nm ? class_##nm : FindPrimitiveClass(#nm))
+
+ClassClass *
+FindPrimitiveClass(char *name)
+{
+ int i;
+ ClassClass *cb;
+ const struct primtype *p;
+
+ for (i = 0; i < PRIMITIVE_TYPE_COUNT; i++) {
+ p = &primitive_types[i];
+ if (strcmp(name, p->name) == 0) {
+ cb = *p->cellp;
+ if (cb == NULL) {
+ char *err, *detail = NULL;
+ cb = createPrimitiveClass(p->name, p->typesig, p->typecode,
+ p->slotsize, p->elementsize);
+ sysAssert(cb != NULL);
+ if ((err = InitializeClass(cb, &detail)) != NULL)
+ return NULL; /* XXX */
+ if ((err = ResolveClass(cb, &detail)) != NULL)
+ return NULL; /* XXX*/
+ *p->cellp = cb;
+ }
+ return cb;
+ }
+ }
+ return NULL;
+}
+
+static void
+InitPrimitiveClasses()
+{
+ int i;
+ for (i = 0; i < PRIMITIVE_TYPE_COUNT; i++)
+ FindPrimitiveClass(primitive_types[i].name);
+}
diff --git a/MPC.3.5.LINUX/preverifier/convert_md.c b/MPC.3.5.LINUX/preverifier/convert_md.c
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * @(#)convert_md.c 1.2 00/11/22
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+//#include <errno.h>
+#include <string.h>
+
+#ifdef UNIX
+#include <langinfo.h>
+#include <iconv.h>
+#include <locale.h>
+#include <stdlib.h>
+
+#define UTF8 "UTF-8"
+
+static iconv_t
+open_iconv(const char* to, const char* from) {
+ iconv_t ic = iconv_open(to, from);
+ if (ic == (iconv_t)-1) {
+// if (errno == EINVAL) {
+ //if (0)
+ /* There is a bug in some versions of Solaris in which
+ * nl_langinfo() returns a string beginning with ISO, but you
+ * have to remove the ISO before calling open_iconv.
+ */
+ // if (strncmp(from, "ISO", 3) == 0) {
+ // /* Try again, but with the ISO in front of the "from" */
+ // return open_iconv(to, from + 3);
+ // } else if (strncmp(to, "ISO", 3) == 0) {
+ // /* Try again, but with the ISO in front of the "to" */
+ // return open_iconv(to + 3, from);
+ // } else {
+ // fprintf(stderr, "%s to %s not supported on this platform\n",
+ // from, to);
+ // }
+ //} else {
+ // perror("iconv_open error: ");
+ //}
+ exit(1);
+ }
+ return ic;
+}
+
+static char*
+get_langinfo_codeset()
+{
+ static char *name = NULL;
+
+ if (name == NULL) {
+ name = nl_langinfo(CODESET);
+ if (name == NULL || strlen(name) == 0) {
+ name = "ISO8859-1";
+ }
+ }
+ return name;
+}
+
+int native2utf8(const char* from, char* to, int buflen) {
+ int ret;
+ size_t ileft, oleft;
+ char *langinfo_codeset = get_langinfo_codeset();
+ iconv_t ic;
+ if (strncmp(langinfo_codeset, UTF8, 5) == 0) {
+ /* don't invoke 'iconv' functions to do the
+ * conversion if it's already in UTF-8 encoding
+ */
+ memcpy(to, from, buflen);
+ return 0;
+ }
+
+ ic = open_iconv(UTF8, get_langinfo_codeset());
+ memset(to, 0, buflen);
+ ileft = strlen(from);
+ oleft = buflen;
+
+ ret = iconv(ic, &from, &ileft, &to, &oleft);
+ if (ret == (size_t)-1) {
+ fprintf(stderr, "native2utf8:Failed to convert (err=%d)\n", ret);
+ exit(1);
+ }
+ iconv_close(ic);
+
+ return buflen-oleft;
+}
+
+int utf2native(const char* from, char* to, int buflen) {
+ int ret;
+ size_t ileft, oleft;
+
+ char *langinfo_codeset = get_langinfo_codeset();
+ iconv_t ic;
+
+ if (strncmp(langinfo_codeset, UTF8, 5) == 0) {
+ /* Don't do the conversion if it's
+ * already in UTF-8 encoding
+ * Copy over the 'from' to 'to'.
+ */
+ memcpy(to, from, buflen);
+ return 0;
+ }
+
+ ic = open_iconv(get_langinfo_codeset(), UTF8);
+ memset(to, 0, buflen);
+ ileft = strlen(from);
+ oleft = buflen;
+
+ ret = iconv(ic, &from, &ileft, &to, &oleft);
+ if (ret == (size_t)-1) {
+ fprintf(stderr, "utf2native:Failed to convert (err=%d)\n", ret);
+ exit(1);
+ }
+ iconv_close(ic);
+
+ return buflen-oleft;
+}
+
+
+#endif
+#ifdef WIN32
+
+#include <WINDOWS.H>
+
+#include "oobj.h"
+#include "utf.h"
+
+int native2utf8(const char* from, char* to, int buflen) {
+ int len;
+ unsigned short unicode[BUFSIZ];
+ len = MultiByteToWideChar(CP_ACP, 0, from, -1, &unicode[0], BUFSIZ);
+ unicode2utf(&unicode[0], len-1, to, buflen);
+ return utfstrlen(to);
+}
+int utf2native(const char* from, char* to, int buflen) {
+ int len, len2;
+ unsigned short unicode[BUFSIZ];
+ utf2unicode((char*)from, &unicode[0], BUFSIZ, &len);
+ len2 = WideCharToMultiByte(CP_ACP, 0, &unicode[0], len, to,
+ buflen, NULL, NULL);
+ to[len2]=0;
+ return len2;
+}
+#endif
+
diff --git a/MPC.3.5.LINUX/preverifier/convert_md.h b/MPC.3.5.LINUX/preverifier/convert_md.h
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * @(#)convert_md.h 1.2 00/11/22
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _CONVERT_MD_
+#define _CONVERT_MD_
+
+extern int native2utf8(const char* from, char* to, int buflen);
+extern int utf2native(const char* from, char* to, int buflen);
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/file.c b/MPC.3.5.LINUX/preverifier/file.c
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ * @(#)file.c 1.40 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Operations on class files.
+ * FILE: file.c
+ * OVERVIEW: Routines for outputing the internal class file.
+ *
+ * AUTHOR(s): Original implementation,
+ * Sheng Liang, Sun Microsystems, Inc.
+ *
+ * Modifications for JAR support, debug support, CLDC compliance,
+ * Tasneem Sayeed, Sun Microsystems
+ *
+ * Added support for inner classes, fixes for stack maps, etc.
+ * Frank Yellin, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifdef UNIX
+#include <unistd.h>
+#endif
+
+#include "oobj.h"
+#include "jar.h"
+#include "tree.h"
+#include "sys_api.h"
+#include "convert_md.h"
+
+#ifdef WIN32
+#include <direct.h>
+#endif
+
+/* initialize opnames[256]; */
+#include "opcodes.init"
+
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+extern char *progname;
+extern bool_t JARfile;
+extern bool_t tmpDirExists;
+
+char *current_class_name = NULL;
+
+bool_t stack_map_on = TRUE;
+
+static char *PrintableClassname(char *classname);
+
+extern char tmp_dir[32];
+
+char *output_dir = "output";
+unsigned char *class_buf;
+int class_buf_size = 0;
+int class_index;
+int last_not_utf8_index;
+
+#define INIT_CLASS_BUF_SIZE 256
+
+void ensure_capacity(int sz)
+{
+ if (class_index + sz >= class_buf_size) {
+ while (class_index + sz >= class_buf_size) {
+ class_buf_size *= 2;
+ }
+ }
+ class_buf = (unsigned char *)realloc(class_buf, class_buf_size);
+}
+
+void write_u1(unsigned long u1)
+{
+ ensure_capacity(1);
+ class_buf[class_index++] = (unsigned char)u1;
+}
+
+void write_u2(unsigned long u2)
+{
+ ensure_capacity(2);
+ class_buf[class_index++] = (unsigned char)(u2 >> 8);
+ class_buf[class_index++] = (unsigned char)u2;
+}
+
+void write_u4(unsigned long u4)
+{
+ ensure_capacity(4);
+ class_buf[class_index++] = (unsigned char)(u4 >> 24);
+ class_buf[class_index++] = (unsigned char)(u4 >> 16);
+ class_buf[class_index++] = (unsigned char)(u4 >> 8);
+ class_buf[class_index++] = (unsigned char)u4;
+}
+
+int new_utf8_index(ClassClass *cb, int index)
+{
+ if (index > last_not_utf8_index) {
+ return index + unhand(cb)->n_new_class_entries;
+ } else {
+ return index;
+ }
+}
+
+unsigned long lookup_utf8(ClassClass *cb, char *utf8)
+{
+ int i;
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ int cpEntries, newEntries;
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ cpEntries = cbConstantPoolCount(cb);
+ newEntries = unhand(cb)->n_new_utf8_entries;
+ for (i = 0; i < cpEntries; i++) {
+ if (type_table[i] == (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED) &&
+ strcmp(utf8, constant_pool[i].cp) == 0) {
+ return new_utf8_index(cb, i);
+ }
+ }
+ for (i = 0; i < newEntries; i++) {
+ if (strcmp(unhand(cb)->new_utf8_entries[i], utf8) == 0) {
+ return i + cpEntries + unhand(cb)->n_new_class_entries;
+ }
+ }
+ unhand(cb)->new_utf8_entries[newEntries] = utf8;
+ unhand(cb)->n_new_utf8_entries = newEntries + 1;
+ return newEntries + cpEntries + unhand(cb)->n_new_class_entries;
+}
+
+
+unsigned long lookup_class(ClassClass *cb, char *name)
+{
+ int i;
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ for (i = 0; i < cbConstantPoolCount(cb); i++) {
+ if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) &&
+ strcmp(name, cbName(constant_pool[i].clazz)) == 0) {
+ return i;
+ }
+ if (type_table[i] == CONSTANT_Class &&
+ strcmp(name, constant_pool[constant_pool[i].i].cp) == 0) {
+ return i;
+ }
+ }
+// panic("class expected to be in constant pool: %s", name);
+ return 0;
+}
+
+int get_last_not_utf8_index(ClassClass *cb)
+{
+ int i;
+ int result;
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ for (i = 0, result = -1; i < cbConstantPoolCount(cb); i++) {
+ if (type_table[i] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) {
+ result = i;
+ }
+ }
+ return result;
+}
+
+void write_constant_pool_preverifier(ClassClass *cb)
+{
+ int i, j;
+ cp_item_type *constant_pool = cbConstantPool(cb);
+ unsigned char *type_table =
+ constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
+ unsigned int sealedValue;
+
+ last_not_utf8_index = get_last_not_utf8_index(cb);
+ if (stack_map_on && unhand(cb)->has_stack_maps) {
+ /* The maximum number of new utf8 entries we'll need is one
+ * for "StackMap", plus one for each of the new class entries.
+ * However, we bump the number to 2 in case we need to add another
+ * entry for the SourceFile attribute.
+ */
+ unhand(cb)->n_new_utf8_entries = 0;
+ unhand(cb)->new_utf8_entries =
+ (char **)malloc((unhand(cb)->n_new_class_entries + 2) *
+ sizeof(char *));
+ /* Put sure we have all the Utf8 entries that we need, so that
+ * we'll know the final size of the constant pool.
+ */
+ lookup_utf8(cb, "StackMap");
+ for (i = 0; i < unhand(cb)->n_new_class_entries; i++) {
+ lookup_utf8(cb, unhand(cb)->new_class_entries[i]);
+ }
+ } else {
+ unhand(cb)->n_new_utf8_entries = 0;
+ unhand(cb)->new_utf8_entries = NULL;
+ unhand(cb)->n_new_class_entries = 0;
+ if (unhand(cb)->new_class_entries != NULL) {
+ free(unhand(cb)->new_class_entries);
+ unhand(cb)->new_class_entries = NULL;
+ }
+ }
+ /* At this, we should not add have to create any more utf8 entries.
+ * We find the value of unhand(cb)->n_new_utf8_entries, and complain
+ * later if this value has changed.
+ */
+ sealedValue = unhand(cb)->n_new_utf8_entries;
+
+ write_u2(cbConstantPoolCount(cb) +
+ unhand(cb)->n_new_class_entries +
+ unhand(cb)->n_new_utf8_entries);
+
+ for (i = 1; i < cbConstantPoolCount(cb); i++) {
+ write_u1(type_table[i] & CONSTANT_POOL_ENTRY_TYPEMASK);
+ switch(type_table[i]) {
+ case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED:
+ write_u2(strlen(constant_pool[i].cp));
+ for (j = 0; j < (int)strlen(constant_pool[i].cp); j++) {
+ write_u1(constant_pool[i].cp[j]);
+ }
+ break;
+
+ case CONSTANT_Class:
+ case CONSTANT_String:
+ write_u2(new_utf8_index(cb, constant_pool[i].i));
+ break;
+
+ case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED:
+ write_u2(lookup_utf8(cb, cbName(constant_pool[i].clazz)));
+ break;
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ write_u2(constant_pool[i].i >> 16);
+ write_u2(constant_pool[i].i & 0xFFFF);
+ break;
+
+ case CONSTANT_NameAndType:
+ write_u2(new_utf8_index(cb, constant_pool[i].i >> 16));
+ write_u2(new_utf8_index(cb, constant_pool[i].i & 0xFFFF));
+ break;
+
+ case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED:
+ case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED:
+ write_u4(constant_pool[i].i);
+ break;
+
+ case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED:
+ case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED:
+ write_u4(constant_pool[i].i);
+ write_u4(constant_pool[i + 1].i);
+ i++;
+ break;
+
+ // default:
+ // panic("bad constant pool entry type: %d", type_table[i]);
+ }
+ if (i == last_not_utf8_index) {
+ /* Write extra CONSTANT_Class entries created by the stackmaps */
+ for (j = 0; j < unhand(cb)->n_new_class_entries; j++) {
+ char *classname = unhand(cb)->new_class_entries[j];
+ write_u1(CONSTANT_Class);
+ write_u2(lookup_utf8(cb, classname));
+ }
+ }
+ }
+ /* Write extra CONSTANT_Utf8 entries created by the stackmaps */
+ for (i = 0; i < unhand(cb)->n_new_utf8_entries; i++) {
+ char *string = unhand(cb)->new_utf8_entries[i];
+ int length = strlen(string);
+ write_u1(CONSTANT_Utf8);
+ write_u2(length);
+ for (j = 0; j < length; j++) {
+ write_u1(string[j]);
+ }
+ }
+ if (sealedValue != (unsigned int) unhand(cb)->n_new_utf8_entries) {
+ // panic("New utf8 entries have been added???");
+ }
+
+}
+
+void write_interfaces(ClassClass *cb)
+{
+ int i;
+ write_u2(cbImplementsCount(cb));
+ for (i = 0; i < cbImplementsCount(cb); i++) {
+ write_u2(cbImplements(cb)[i]);
+ }
+}
+
+void write_fields(ClassClass *cb)
+{
+ int i;
+ write_u2(cbFieldsCount(cb));
+ for (i = 0; i < cbFieldsCount(cb); i++) {
+ struct fieldblock *fb = &cbFields(cb)[i];
+ write_u2(fb->access & ACC_WRITTEN_FLAGS);
+ write_u2(lookup_utf8(cb, fb->name));
+ write_u2(lookup_utf8(cb, fb->signature));
+ /* Number of attributes we're about to output.
+ * Each item in the following sum is a boolean that returns 1 or 0.
+ */
+ write_u2( ((fb->access & ACC_VALKNOWN) != 0)
+ + (fb->synthetic != 0)
+ + (fb->deprecated != 0));
+ if (fb->access & ACC_VALKNOWN) {
+ write_u2(lookup_utf8(cb, "ConstantValue")); /* Attribute name */
+ write_u4(2); /* Length */
+ write_u2(fb->u.offset);
+ }
+ if (fb->deprecated) {
+ write_u2(lookup_utf8(cb, "Deprecated")); /* Attribute name */
+ write_u4(0); /* Length */
+ }
+ if (fb->synthetic) {
+ write_u2(lookup_utf8(cb, "Synthetic")); /* Attribute name */
+ write_u4(0); /* Length */
+ }
+ }
+}
+
+void write_stack_map(int nentries, struct map_entry *entries)
+{
+ int i;
+ for (i = 0; i < nentries; i++) {
+ struct map_entry *entry = entries + i;
+ write_u1(entry->type);
+ if (entry->type == CF_ITEM_NewObject) {
+ write_u2(entry->info);
+ }
+ if (entry->type == CF_ITEM_Object) {
+ /* This is ugly
+ * Non-negative entries refer to classes
+ * in the original constant pool.
+ * Negative entries, ~(entry->info) is the entry's index
+ * in the list of additional constant pool entries.
+ */
+ if (entry->info >= 0) {
+ write_u2(entry->info);
+ } else {
+ write_u2(last_not_utf8_index + 1 + ~entry->info);
+ }
+ }
+ }
+}
+
+int stack_map_size(int nentries, struct map_entry *entries)
+{
+ int i;
+ int result = 0;
+ for (i = 0; i < nentries; i++) {
+ struct map_entry *entry = entries + i;
+ result += 1;
+ if (entry->type == CF_ITEM_Object || entry->type == CF_ITEM_NewObject) {
+ result += 2;
+ }
+ }
+ return result;
+}
+
+void write_methods(ClassClass *cb)
+{
+ int i;
+ write_u2(cbMethodsCount(cb));
+ for (i = 0; i < cbMethodsCount(cb); i++) {
+ struct methodblock *mb = &cbMethods(cb)[i];
+ write_u2(mb->fb.access & ACC_WRITTEN_FLAGS);
+ write_u2(lookup_utf8(cb, mb->fb.name));
+ write_u2(lookup_utf8(cb, mb->fb.signature));
+
+ /* Attribute count
+ * Each item in the following sum is a boolean that returns 1 or 0.
+ */
+ write_u2( (mb->code_length > 0)
+ + (mb->nexceptions > 0)
+ + (mb->fb.synthetic != 0)
+ + (mb->fb.deprecated != 0));
+
+ if (mb->code_length > 0) {
+ int j;
+ int stack_map_attr_length = 0; /* Stack Map attribute length */
+ int line_no_attr_length = 0; /* line_number_table attr Length */
+ int localvar_attr_length = 0; /* localVar_table attr Length */
+ int code_attrs = 0; /* Attributes count for Code attribute */
+
+ if (stack_map_on && mb->n_stack_maps > 0) {
+ stack_map_attr_length = 8;
+ code_attrs++; /* increment code attributes */
+ for (j = 0; j < mb->n_stack_maps; j++) {
+ stack_map_attr_length += 6 +
+ stack_map_size(mb->stack_maps[j].nlocals,
+ mb->stack_maps[j].locals) +
+ stack_map_size(mb->stack_maps[j].nstacks,
+ mb->stack_maps[j].stacks);
+ }
+ }
+
+ /* attribute_name_index for "Code" attribute */
+ write_u2(lookup_utf8(cb, "Code"));
+ if (mb->line_number_table_length > 0) {
+ /* calculate the size of the line_number_table attribute */
+ /* Attribute length for line_number_table
+ * sizeof line_number_table(4) * no. of table entries + 8
+ * 8 bytes = 2 bytes for attr_name_index +
+ * 4 bytes for attr_length +
+ * 2 bytes for line_number_table_length
+ */
+ code_attrs++; /* increment code attributes */
+ line_no_attr_length = 4 * mb->line_number_table_length + 8;
+ }
+ if (mb->localvar_table_length > 0) {
+ /* calculate the size of the localvar_table attribute */
+ /* Attribute length for localvar_table
+ * sizeof localvar_table (10) * no. of table entries + 8
+ * 8 bytes = 2 bytes for attr_name_index +
+ * 4 bytes for attr_length +
+ * 2 bytes for line_number_table_length
+ */
+ code_attrs++; /* increment code attributes */
+ localvar_attr_length = 10 * mb->localvar_table_length + 8;
+ }
+
+ /* Attribute Length */
+ write_u4(12 + mb->code_length
+ + mb->exception_table_length * 8
+ + stack_map_attr_length
+ + line_no_attr_length
+ + localvar_attr_length);
+ write_u2(mb->maxstack);
+ write_u2(mb->nlocals);
+ write_u4(mb->code_length);
+ for (j = 0; j < (int)mb->code_length; j++) {
+ write_u1(mb->code[j]);
+ }
+ write_u2(mb->exception_table_length);
+ for (j = 0; j < (int)mb->exception_table_length; j++) {
+ write_u2(mb->exception_table[j].start_pc);
+ write_u2(mb->exception_table[j].end_pc);
+ write_u2(mb->exception_table[j].handler_pc);
+ write_u2(mb->exception_table[j].catchType);
+ }
+
+ /* Attributes count for Code attribute */
+ write_u2(code_attrs);
+
+ /* check if we have a valid line_number_table entries and
+ * if so, write out the pc and line_number entries.
+ */
+
+ if (mb->line_number_table_length > 0) {
+ /* line_number_table attribute exists */
+ /* attribute_name_index for "LineNumberTable" */
+ write_u2(lookup_utf8(cb, "LineNumberTable"));
+ /* Attribute length for line_number_table
+ * (exclude initial 6 bytes = 2 bytes for attr_name_index +
+ * 4 bytes for attr_length)
+ */
+ write_u4(line_no_attr_length - 6);
+ /* Length of line_number_table */
+ write_u2(mb->line_number_table_length);
+ /* write out the line_number_table entries */
+ for (j=0; j< (int) mb->line_number_table_length; j++) {
+ if (mb->line_number_table != NULL) {
+ write_u2(mb->line_number_table[j].pc);
+ write_u2(mb->line_number_table[j].line_number);
+ }
+ }
+ }
+
+ /* check if we have a valid localvar_table entries and
+ * if so, write out its entries
+ */
+
+ if (mb->localvar_table_length > 0) {
+ /* localvar_table attribute exists */
+ /* attribute_name_index for "LocalVariableTable" */
+ write_u2(lookup_utf8(cb, "LocalVariableTable"));
+
+ /* Attribute length for localvar_table
+ * (exclude initial 6 bytes = 2 bytes for attr_name_index +
+ * 4 bytes for attr_length)
+ */
+ write_u4(localvar_attr_length - 6);
+
+ /* Length of localvar_table */
+ write_u2(mb->localvar_table_length);
+
+ /* write out the localvar_table entries */
+ for (j=0; j< (int) mb->localvar_table_length; j++) {
+ if (mb->localvar_table != NULL) {
+ write_u2(mb->localvar_table[j].pc0);
+ write_u2(mb->localvar_table[j].length);
+ write_u2(lookup_utf8(cb,mb->localvar_table[j].name));
+ write_u2(lookup_utf8(cb,mb->localvar_table[j].signature));
+ write_u2(mb->localvar_table[j].slot);
+ }
+ }
+ }
+
+ if (stack_map_on && mb->n_stack_maps > 0) {
+ write_u2(lookup_utf8(cb, "StackMap"));
+ write_u4(stack_map_attr_length - 6);
+ write_u2(mb->n_stack_maps);
+ for (j = 0; j < mb->n_stack_maps; j++) {
+ write_u2(mb->stack_maps[j].offset);
+ write_u2(mb->stack_maps[j].nlocals);
+ write_stack_map(mb->stack_maps[j].nlocals,
+ mb->stack_maps[j].locals);
+ write_u2(mb->stack_maps[j].nstacks);
+ write_stack_map(mb->stack_maps[j].nstacks,
+ mb->stack_maps[j].stacks);
+ }
+ }
+ }
+ if (mb->nexceptions > 0) {
+ int j;
+ write_u2(lookup_utf8(cb, "Exceptions"));
+ write_u4(2 + mb->nexceptions * 2);
+ write_u2(mb->nexceptions);
+ for (j = 0; j < mb->nexceptions; j++) {
+ write_u2(mb->exceptions[j]);
+ }
+ }
+ if (mb->fb.deprecated) {
+ write_u2(lookup_utf8(cb, "Deprecated"));
+ write_u4(0); /* Length */
+ }
+ if (mb->fb.synthetic) {
+ write_u2(lookup_utf8(cb, "Synthetic"));
+ write_u4(0); /* Length */
+ }
+ }
+}
+
+void ensure_dir_exists(char *dir)
+{
+ struct stat stat_buf;
+ char *parent;
+ char *q;
+ if (dir[0] == 0) {
+ return;
+ }
+ parent = strdup(dir);
+ q = strrchr(parent, '/');
+ if (q) {
+ *q = 0;
+ ensure_dir_exists(parent);
+ }
+ if (stat(dir, &stat_buf) < 0) {
+ if (JAR_DEBUG && verbose) {
+ // jio_fprintf(stderr, "Creating output directory [%s]\n", dir);
+ }
+#ifdef WIN32
+ mkdir(dir);
+#endif
+#ifdef UNIX
+ mkdir(dir, 0755);
+#endif
+ }
+ free(parent);
+}
+
+void ensure_dir_writable(char *dir)
+{
+ struct stat stat_buf;
+
+ stat(dir, &stat_buf);
+ if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) { /* is dir ? */
+#ifdef WIN32
+ if (access(dir, 06) < 0) {
+#endif
+#ifdef UNIX
+ if (access(dir, R_OK | W_OK) < 0) {
+#endif
+ // panic("%s is write protected\n", dir);
+ }
+ } else {
+ // panic("%s is not a directory\n", dir);
+ }
+}
+
+extern char *output_path;
+
+void
+WriteClass(ClassClass *cb)
+{
+ int fd;
+ char fname[1024];
+ char buff[BUFSIZ];
+ char *nativeName = &buff[0];
+
+ class_buf = (unsigned char*)malloc(INIT_CLASS_BUF_SIZE);
+ if (class_buf == NULL) {
+ // panic("out of memory");
+ }
+ class_buf_size = INIT_CLASS_BUF_SIZE;
+
+ class_index = 0;
+
+ write_u4(0xcafebabe);
+
+ write_u2(cbMinorVersion(cb));
+ write_u2(cbMajorVersion(cb));
+
+ write_constant_pool_preverifier(cb);
+
+ write_u2(cbAccess(cb) & ACC_WRITTEN_FLAGS);
+
+ write_u2(lookup_class(cb, cbName(cb)));
+ write_u2(unhand(cb)->superclass_idx);
+ write_interfaces(cb);
+ write_fields(cb);
+ write_methods(cb);
+
+
+ /* Output number of attributes
+ * Each item in the following sum is a boolean that returns 1 or 0.
+ */
+ write_u2( (cbSourceName(cb) != NULL)
+ + (cbAbsoluteSourceName(cb) != NULL)
+ + (unhand(cb)->hasTimeStamp)
+ + (unhand(cb)->deprecated)
+ + (unhand(cb)->synthetic)
+ + (cbInnerClasses(cb) != NULL)
+ );
+ if (cbSourceName(cb) != NULL) {
+ /* write the source file attribute used for debugging purposes */
+ write_u2(lookup_utf8(cb, "SourceFile")); /* SourceFile attribute */
+ write_u4(2); /* Length */
+ /* CP entry containing the source name */
+ write_u2(lookup_utf8(cb, cbSourceName(cb)));
+ }
+ if (cbAbsoluteSourceName(cb) != NULL) {
+ /* write the source file attribute used for debugging purposes */
+ write_u2(lookup_utf8(cb, "AbsoluteSourcePath"));
+ write_u4(2);
+ write_u2(lookup_utf8(cb, cbAbsoluteSourceName(cb)));
+ }
+ if (unhand(cb)->hasTimeStamp) {
+ write_u2(lookup_utf8(cb, "TimeStamp"));
+ write_u4(8);
+ write_u4(cbTimestamp(cb).high);
+ write_u4(cbTimestamp(cb).low);
+ }
+ if (unhand(cb)->deprecated) {
+ write_u2(lookup_utf8(cb, "Deprecated")); /* attribute name */
+ write_u4(0); /* Length */
+ }
+ if (unhand(cb)->synthetic) {
+ write_u2(lookup_utf8(cb, "Synthetic")); /* attribute name */
+ write_u4(0); /* Length */
+ }
+
+ if (cbInnerClasses(cb) != NULL) {
+ int count = cbInnerClassesCount(cb);
+ struct innerClasses *thisInnerClass= cbInnerClasses(cb);
+ struct innerClasses *lastInnerClass = thisInnerClass + count;
+ write_u2(lookup_utf8(cb, "InnerClasses")); /* Attribute name */
+ write_u4(8 * count + 2); /* Length */
+ write_u2(count);
+ for ( ; thisInnerClass < lastInnerClass; thisInnerClass++) {
+ char *innerName = thisInnerClass->inner_name;
+ write_u2(thisInnerClass->inner_class);
+ write_u2(thisInnerClass->outer_class);
+ write_u2( (innerName != 0) ? lookup_utf8(cb, innerName) : 0);
+ write_u2(thisInnerClass->access);
+ }
+ }
+
+ /* Conversion for Japanese filenames */
+ utf2native(cbName(cb), nativeName, BUFSIZ);
+
+ // if (JARfile) {
+ /* classes need to be put in a JAR file */
+ // sprintf(fname, "%s/%s.class", tmp_dir, nativeName);
+ // } else {
+ sprintf(fname, "%s/%s.class", output_path, nativeName);
+// }
+
+ {
+ char *dir = strdup(fname);
+ char *q;
+
+ q = strrchr(dir, '/');
+ if (q) {
+ *q = 0;
+ ensure_dir_exists(dir);
+ ensure_dir_writable(dir);
+ }
+ free(dir);
+ }
+
+#ifdef UNIX
+ fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC , 0644);
+#endif
+#ifdef WIN32
+ fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+#endif
+
+ if (fd < 0) {
+ // panic("failed to open %s", fname);
+ }
+
+ tmpDirExists = TRUE; /* tmpDir exists with verified classes */
+ write(fd, class_buf, class_index);
+ close(fd);
+ free(class_buf);
+ class_buf_size = 0;
+}
+
+void
+VerifyFile(char *fn)
+{
+ /* If this is the first class, we'll run into problems if loading the
+ * class forces Object to be loaded, when then forces this class to
+ * be loaded. To prohibit such problems, we force Object to be loaded
+ */
+ FindClass(0, "java/lang/Object", TRUE);
+
+ {
+ ClassClass *cb = FindClass(0, fn, TRUE);
+ char *class_name = PrintableClassname(fn);
+
+ if (cb == NULL) {
+ errorCode = 1; /* set error status to indicate error */
+ // jio_fprintf(stderr, "Error loading class %s\n", class_name);
+ } else {
+ if (no_native_methods) {
+ /* Check for native methods in classes */
+ struct methodblock *mb;
+ int size;
+ mb = cbMethods(cb);
+ for (size=0; size < (int) cbMethodsCount(cb); size++, mb++) {
+ if (mb->fb.access & ACC_NATIVE) {
+ current_class_name = fn;
+ // panic("native methods should not appear");
+ }
+ }
+ }
+
+ VerifyClass(cb);
+
+ WriteClass(cb);
+ }
+ }
+}
+
+char *PrintableClassname(char *class_name)
+{
+ char *p;
+ static char class_copy[257];
+ strncpy(class_copy, class_name, 256);
+
+ /* Convert all slashes in the classname to periods */
+ for (p = class_copy; ((p = strchr(p, '/')) != 0); *p++ = '.');
+ return class_copy;
+}
+
+void printCurrentClassName(void)
+{
+ if (current_class_name) {
+ // fprintf(stderr, "Error preverifying class %s\n ",
+ // PrintableClassname(current_class_name));
+ }
+}
diff --git a/MPC.3.5.LINUX/preverifier/inlinejsr.c b/MPC.3.5.LINUX/preverifier/inlinejsr.c
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * @(#)inlinejsr.c 1.22 02/09/27
+ *
+ * Copyright 1995-2001 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: JSR inlining
+ * FILE: inlinejsr.c
+ * OVERVIEW: Routines for inlining of JSR and RET bytecodes.
+ *
+ * AUTHOR: Frank Yellin, Sun Microsystems, Inc.
+ * Edited by Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include "check_code.h"
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+/* Maximum byte code size is 64K. */
+#define MAX_CODE_SIZE 65535
+
+typedef struct SubrContext {
+ int id; /* id, for debugging */
+ int depth; /* depth of subroutine */
+ struct SubrContext *parent; /* subroutine of caller */
+ struct CodeRef *caller; /* jsr that got us there */
+ struct CodeRef *nextInstruction; /* first instruction following inlining */
+ int target;
+
+ struct SubrContext *next; /* linked list of all subr contexts */
+} SubrContext;
+
+
+/* global context, keep track of info when a method is rewritten */
+typedef struct JsrContext {
+ context_type *vcontext; /* The verifier's context */
+ struct CodeRef *codeRef; /* big array of codeRef's */
+ struct CodeRef *codeRefEnd; /* pointer to next codeRef to fill in */
+ int scontext_id; /* ID assigned to last SubrContext */
+ struct SubrContext *allSubrContexts; /* pointer to linked list */
+ struct CodeRef **mapping; /* maps inumbers CodeRef's */
+} JsrContext;
+
+/* A single instruction in the resulting stream */
+typedef struct CodeRef {
+ long inumber; /* instruction number in original code */
+ SubrContext *subroutine; /* subroutine call that this is part of */
+ enum { CRF_NORMAL, /* normal instruction */
+ CRF_SKIP, /* skip this instruction */
+ CRF_JSR_SIMPLE_GOTO, /* jsr to subroutine that doesn't return */
+ CRF_JSR_TARGETED_GOTO, /* jsr to subroutine that does return */
+ CRF_RET_SIMPLE_GOTO /* ret that's not at the end of subroutine */
+ } flags;
+ /* My offset in the new code */
+ int offset;
+ struct CodeRef *next; /* next codeRef with same "inumber" */
+} CodeRef;
+
+
+static bool_t matchSubroutine(JsrContext *, instruction_data_type*,
+ SubrContext *);
+static bool_t subroutineGoto(JsrContext *, SubrContext *, SubrContext *);
+
+
+static void
+rewriteOneSubroutine(JsrContext *context, SubrContext *subroutine);
+
+static void fixupCode(JsrContext*);
+static void fixupExceptionHandlers(JsrContext*);
+static void fixupLineNumberTable(JsrContext*);
+static void fixupVariableTable(JsrContext*);
+
+
+static void
+updateTarget(JsrContext *,
+ int inumber,
+ SubrContext* subroutine,
+ void* target, int offset, int size);
+
+
+void
+rewriteCode(context_type *vcontext, struct methodblock *mb)
+{
+ JsrContext context_buf;
+ JsrContext *context = &context_buf;
+
+#if MYDEBUG
+ printf("Starting %s.%s%s\n", cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature);
+#endif
+ /* Initialize the context */
+ memset(context, 0, sizeof(context));
+ context->vcontext = vcontext; /* The verifier context */
+ /* Allow up to MAX_CODE_SIZE instructions. */
+ context->codeRef = (CodeRef *)malloc(MAX_CODE_SIZE * sizeof(CodeRef));
+ context->codeRefEnd = context->codeRef;
+ /* Id (for debugging) of last subroutine structure created */
+ context->scontext_id = 0;
+ /* Keep a list of all subroutines, so that we can easily free() them */
+ context->allSubrContexts = NULL;
+ /* Make it easy to go from inumber to all CodeRef's that have that inumber*/
+ context->mapping = (CodeRef **)calloc(vcontext->instruction_count,
+ sizeof(CodeRef **));
+
+ /* Fill in context->codeRef with this routine. In line all subroutine
+ * calls, and delete all unreachable code */
+ rewriteOneSubroutine(context, NULL);
+
+ /* Modify mb->code and mb->code_length for the new code */
+ fixupCode(context);
+
+ /* Update the exception table */
+ if (mb->exception_table_length != 0) {
+ fixupExceptionHandlers(context);
+ }
+
+ /* Update the line number table */
+ if (mb->line_number_table_length != 0) {
+ fixupLineNumberTable(context);
+ }
+
+ /* Update the local variable table */
+ if (mb->localvar_table_length != 0) {
+ fixupVariableTable(context);
+ }
+
+ /* Clean up */
+ free(context->codeRef);
+ free(context->mapping);
+
+ /* Free all the subroutine contexts that we created */
+ while (context->allSubrContexts != NULL) {
+ SubrContext *this = context->allSubrContexts;
+ SubrContext *next = this->next;
+ free(this);
+ context->allSubrContexts = next;
+ }
+}
+
+static void
+rewriteOneSubroutine(JsrContext *context, SubrContext *subroutine)
+{
+ context_type *vcontext = context->vcontext;
+ int depth = subroutine ? subroutine->depth : 0;
+ instruction_data_type *idata = vcontext->instruction_data;
+ int instruction_count = vcontext->instruction_count;
+ CodeRef **mapping = context->mapping;
+
+ instruction_data_type *this_idata;
+ int inumber;
+ int count = 0;
+ CodeRef *retOpcode = NULL;
+
+
+ for ( inumber = 0, this_idata = idata;
+ inumber < instruction_count;
+ inumber++, this_idata++) {
+ if ( (this_idata->or_flags & FLAG_REACHED)
+ && (this_idata->register_info.mask_count == depth)
+ && ((depth == 0)
+ || matchSubroutine(context, this_idata, subroutine))) {
+
+ /* We have an instruction that is part of this subroutine */
+
+ CodeRef *codeRef = context->codeRefEnd++;
+#if MYDEBUG
+ printf("\t%d:\t%d (%d)\t%s (%d)\n",
+ (codeRef - context->codeRef), /* new instruction index */
+ inumber, (subroutine ? subroutine->id : 0),
+ (this_idata->opcode == 256
+ ? "invokeinit" : opnames[this_idata->opcode]),
+ this_idata->offset);
+#endif
+ codeRef->inumber = inumber;
+ codeRef->subroutine = subroutine;
+ codeRef->flags = CRF_NORMAL;
+ codeRef->next = mapping[inumber]; /* Add to inumber mapping */
+ mapping[inumber] = codeRef;
+
+ count++;
+
+ if (count == 1 && depth > 0) {
+ /* This is the first instruction included as part of the
+ * subroutine call. If it's the target of the jsr that got
+ * us here, then we can just "ignore" the jsr.
+ * Otherwise, we have to convert the 'jsr' into a 'goto'
+ */
+ CodeRef *caller = subroutine->caller;
+ if (inumber != idata[caller->inumber].operand.i) {
+ caller->flags = CRF_JSR_TARGETED_GOTO;
+ }
+ }
+
+ switch(this_idata->opcode) {
+ case opc_jsr: case opc_jsr_w:
+ if (this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION) {
+ /* We're calling a subroutine that doesn't return.
+ * The verifier has already made sure that the
+ * subroutine doesn't have a deeper depth.
+ * We turn the JSR into a goto */
+ codeRef->flags = CRF_JSR_SIMPLE_GOTO;
+ } else {
+ SubrContext *newSubr = malloc(sizeof(SubrContext));
+
+ /* In rare cases, we'll have to change this in the
+ * subroutine code */
+ codeRef->flags = CRF_SKIP;
+
+ /* Create a new subroutine, and inline it */
+ newSubr->id = ++context->scontext_id;
+ newSubr->caller = codeRef;
+ newSubr->target = this_idata->operand.i;
+ newSubr->depth = depth + 1;
+ newSubr->nextInstruction = NULL; /* unknown for now */
+ newSubr->parent = subroutine;
+ /* Add this to the list of all subroutine contexts */
+ newSubr->next = context->allSubrContexts;
+ context->allSubrContexts = newSubr;
+ /* Generate the code for this subroutine */
+ rewriteOneSubroutine(context, newSubr);
+ }
+ break;
+
+ case opc_ret:
+ if (retOpcode != NULL) {
+ /* There should only be one per subroutine */
+ panic("Multiple return opcodes??");
+ } else if (depth == 0) {
+ /* We're not in a subroutine */
+ panic("Ret at depth = 0");
+ }
+ retOpcode = codeRef;
+ /* Flags are set at the end of the loop, below */
+ break;
+
+ case opc_astore:
+ /* We discard any astore's that move a return address
+ * from the stack to a register.
+ */
+ if (GET_ITEM_TYPE(this_idata->stack_info.stack->item)
+ == ITEM_ReturnAddress) {
+ codeRef->flags = CRF_SKIP;
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+ }
+ }
+ if (depth > 0) {
+ subroutine->nextInstruction = context->codeRefEnd;
+ if (retOpcode != NULL) {
+ /* If the last instruction wasn't a 'ret', then we need to
+ * convert the 'ret' into a 'goto'.
+ */
+ if (context->codeRefEnd == retOpcode + 1) {
+ retOpcode->flags = CRF_SKIP;
+ } else {
+ retOpcode->flags = CRF_RET_SIMPLE_GOTO;
+ }
+ }
+ }
+}
+
+
+static void
+fixupCode(JsrContext *context)
+{
+ context_type *vcontext = context->vcontext;
+ instruction_data_type *idata = vcontext->instruction_data;
+ struct methodblock *mb = vcontext->mb;
+ unsigned char *oldCode = mb->code;
+ CodeRef *codeRefEnd = context->codeRefEnd;
+
+ unsigned char *newCode;
+ CodeRef *codeRef;
+ int pc;
+ long newCodeLength;
+
+ /* Assign offsets to each instruction. */
+#if MYDEBUG
+ printf("Assigning offsets\n");
+#endif
+ for (pc = 0, codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) {
+ instruction_data_type *this_idata = &idata[codeRef->inumber];
+ opcode_type opcode = this_idata->opcode;
+
+ codeRef->offset = pc;
+
+#if MYDEBUG
+ printf("\t%d:\t%d\tpc=%d\t%s (%d) %s\n",
+ (codeRef - context->codeRef),
+ (this_idata - vcontext->instruction_data),
+ pc,
+ (this_idata->opcode == 256
+ ? "invokeinit" : opnames[this_idata->opcode]),
+ this_idata->offset,
+ ((codeRef->flags == CRF_SKIP) ? " XX" : "")
+ );
+#endif
+
+ /* Now increment the pc, depending on the instruction */
+ if (codeRef->flags == CRF_SKIP) {
+ /* do nothing */
+ } else if (opcode == opc_tableswitch || opcode == opc_lookupswitch) {
+ /* This mysterious calculation works.
+ * The first term increments pc and then rounds it up to a
+ * multiple of 4. The second term is the size of the word-aligned
+ * values.
+ */
+ pc = ((pc + 1 + 3) & ~3) + ((this_idata->length - 1) & ~3);
+ } else if (opcode == opc_ret) {
+ /* We must be turning it into an opc_goto */
+ pc += 3;
+ } else {
+ pc += this_idata->length;
+ }
+ }
+
+ /* Create a new code object */
+ newCode = (unsigned char *)malloc(pc);
+ newCodeLength = pc;
+
+#if MYDEBUG
+ printf("Creating code of length %d\n", pc);
+#endif
+
+ for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) {
+ if (codeRef->flags != CRF_SKIP) {
+ instruction_data_type *this_idata = &idata[codeRef->inumber];
+ opcode_type opcode = this_idata->opcode;
+ int pc = codeRef->offset;
+ unsigned char *source = &oldCode[this_idata->offset];
+ unsigned char *target = &newCode[pc];
+
+#if MYDEBUG
+ printf("\t%d:\t%d\tpc=%d\t%s (%d) \n",
+ (codeRef - context->codeRef),
+ (this_idata - vcontext->instruction_data),
+ pc,
+ (this_idata->opcode == 256
+ ? "invokeinit" : opnames[this_idata->opcode]),
+ this_idata->offset
+ );
+#endif
+
+ switch(opcode) {
+ case opc_ifeq: case opc_ifne: case opc_iflt:
+ case opc_ifge: case opc_ifgt: case opc_ifle:
+ case opc_ifnull: case opc_ifnonnull:
+ case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt:
+ case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple:
+ case opc_if_acmpeq: case opc_if_acmpne:
+ case opc_goto: case opc_goto_w:
+ target[0] = source[0];
+ updateTarget(context, this_idata->operand.i,
+ codeRef->subroutine,
+ target + 1, pc, this_idata->length - 1);
+ break;
+
+ case opc_jsr: case opc_jsr_w:
+ target[0] = opc_goto;
+ if (codeRef->flags == CRF_JSR_SIMPLE_GOTO) {
+ updateTarget(context, this_idata->operand.i,
+ codeRef->subroutine,
+ target + 1, pc, this_idata->length - 1);
+ } else if (codeRef->flags == CRF_JSR_TARGETED_GOTO) {
+ updateTarget(context, this_idata->operand.i,
+ codeRef[1].subroutine,
+ target + 1, pc, this_idata->length - 1);
+ } else {
+ panic("Shouldn't have anything referring to jsr");
+ }
+ break;
+
+ case opc_ret:
+ if (codeRef->flags & CRF_RET_SIMPLE_GOTO) {
+ int gotoTarget =
+ codeRef->subroutine->nextInstruction->offset;
+ target[0] = opc_goto;
+ target[1] = (gotoTarget - pc) >> 8;
+ target[2] = (gotoTarget - pc);
+ } else {
+ panic("Shouldn't have anything referring to ret");
+ }
+ break;
+
+ default:
+ memcpy(target, source, this_idata->length);
+ break;
+
+
+ case opc_tableswitch:
+ case opc_lookupswitch: {
+ int *successors = this_idata->operand.ip;
+ int keys = successors[0] - 1; /* don't include default */
+ SubrContext *subroutine = codeRef->subroutine;
+ int i;
+
+ long *targetPtr, *sourcePtr;
+ target[0] = source[0];
+ target[1] = target[2] = target[3] = 0; /* clear alignment */
+
+ targetPtr = (long *)UCALIGN(target + 1);
+ sourcePtr = (long *)UCALIGN(source + 1);
+
+ /* Update the default target */
+ updateTarget(context, successors[1], subroutine,
+ targetPtr, pc, 4);
+ if (opcode == opc_tableswitch) {
+ targetPtr[1] = sourcePtr[1]; /* low */
+ targetPtr[2] = sourcePtr[2]; /* high */
+ for (i = 0; i < keys; i++) {
+ updateTarget(context, successors[2 + i], subroutine,
+ &targetPtr[3 + i], pc, 4);
+ }
+ } else {
+ targetPtr[1] = sourcePtr[1]; /* pairs */
+ for (i = 0; i < keys; i++) {
+ targetPtr[2 + (i << 1)] = sourcePtr[2 + (i << 1)];
+ updateTarget(context, successors[2 + i], subroutine,
+ &targetPtr[3 + (i << 1)], pc, 4);
+ }
+ }
+ break;
+
+ }
+ }
+ }
+ }
+ mb->code = newCode;
+ mb->code_length = newCodeLength;
+}
+
+static void fixupExceptionHandlers(JsrContext *context) {
+ const int catchFrameSize = sizeof(struct CatchFrame);
+ context_type *vcontext = context->vcontext;
+ struct methodblock *mb = vcontext->mb;
+
+ short *code_data = vcontext->code_data; /* maps offset to inumber */
+
+ CodeRef *codeRefEnd = context->codeRefEnd;
+
+ /* Structure to hold new catch frames */
+ struct CatchFrame *catchFrames = malloc(catchFrameSize * MAX_CODE_SIZE);
+ struct CatchFrame *currentCatchFrame = catchFrames;
+
+ CodeRef *hRef, *instRef;
+ unsigned long i;
+
+ /* Look at each exception handler */
+ for (i = 0; i < mb->exception_table_length; i++) {
+ struct CatchFrame *this_handler = &mb->exception_table[i];
+ int start_inumber = code_data[this_handler->start_pc];
+ int end_inumber = code_data[this_handler->end_pc];
+ int handler_inumber = code_data[this_handler->handler_pc];
+
+ /* First instruction that maps to the specified handler */
+ for (hRef = context->mapping[handler_inumber]
+ ; hRef != NULL; hRef = hRef->next) {
+ /* Find all instructions that go to this handler. */
+ bool_t wasMatch = FALSE;
+ for (instRef = context->codeRef; instRef < codeRefEnd; instRef++) {
+ if (instRef->flags != CRF_SKIP) {
+ bool_t thisMatch = instRef->inumber >= start_inumber
+ && instRef->inumber < end_inumber
+ && subroutineGoto(context,
+ instRef->subroutine,
+ hRef->subroutine);
+ if (thisMatch && !wasMatch) {
+ /* Start a new catch frame */
+ memcpy(currentCatchFrame, this_handler, catchFrameSize);
+ currentCatchFrame->handler_pc = hRef->offset;
+ currentCatchFrame->start_pc = instRef->offset;
+ wasMatch = TRUE;
+ } else if (wasMatch && !thisMatch) {
+ currentCatchFrame->end_pc = instRef->offset;
+ currentCatchFrame++;
+ wasMatch = FALSE;
+ }
+ }
+ }
+ if (wasMatch) {
+ /* We end the code still in the catch frame */
+ currentCatchFrame->end_pc = mb->code_length;
+ currentCatchFrame++;
+ }
+ }
+ }
+ /* free(mb->exception_table); */
+ mb->exception_table_length = currentCatchFrame - catchFrames;
+ mb->exception_table = realloc(catchFrames,
+ (char *)currentCatchFrame - (char *)catchFrames);
+
+}
+
+static void fixupLineNumberTable(JsrContext *context) {
+ context_type *vcontext = context->vcontext;
+ struct methodblock *mb = vcontext->mb;
+ int tableLength = mb->line_number_table_length;
+
+ instruction_data_type *idata = vcontext->instruction_data;
+ instruction_data_type *last_idata = &idata[vcontext->instruction_count - 1];
+ int oldCodeLength = last_idata->offset + last_idata->length;
+ struct lineno *lineTable = malloc(sizeof(struct lineno) * MAX_CODE_SIZE);
+ struct lineno *currentLineTableEntry = lineTable;
+ unsigned long *mapTable = calloc(sizeof(short *), oldCodeLength);
+ CodeRef *codeRefEnd = context->codeRefEnd;
+ CodeRef *codeRef;
+ int i, currentLineNumber;
+
+ {
+ unsigned long startPC, endPC, line, pc;
+
+ for (i = 0; i < tableLength - 1; i++) {
+ startPC = mb->line_number_table[i].pc;
+ endPC = mb->line_number_table[i + 1].pc;
+ line = mb->line_number_table[i].line_number;
+ for (pc = startPC; pc < endPC; pc++) {
+ mapTable[pc] = line;
+ }
+ }
+ startPC = mb->line_number_table[tableLength - 1].pc;
+ endPC = oldCodeLength;
+ line = mb->line_number_table[tableLength - 1].line_number;
+ for (pc = startPC; pc < endPC; pc++) {
+ mapTable[pc] = line;
+ }
+ }
+
+ currentLineNumber = -1;
+ for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) {
+ if (codeRef->flags != CRF_SKIP) {
+ instruction_data_type *this_idata = &idata[codeRef->inumber];
+ int thisLineNumber = mapTable[this_idata->offset];
+ if (thisLineNumber != currentLineNumber) {
+ currentLineTableEntry->line_number = thisLineNumber;
+ currentLineTableEntry->pc = codeRef->offset;
+ currentLineTableEntry++;
+ currentLineNumber = thisLineNumber;
+ }
+ }
+ }
+
+ free(mapTable);
+ mb->line_number_table = realloc(lineTable,
+ (char *)currentLineTableEntry -
+ (char *)lineTable);
+ mb->line_number_table_length = currentLineTableEntry - lineTable;
+}
+
+
+static void fixupVariableTable(JsrContext *context) {
+ context_type *vcontext = context->vcontext;
+ struct methodblock *mb = context->vcontext->mb;
+ instruction_data_type *idata = vcontext->instruction_data;
+ CodeRef *codeRefEnd = context->codeRefEnd;
+ CodeRef *codeRef;
+ unsigned long i;
+
+ struct localvar *localVars =
+ malloc(sizeof(struct localvar) * MAX_CODE_SIZE);
+ struct localvar *currentLocalVar = localVars;
+
+ for (i = 0; i < mb->localvar_table_length; i++) {
+ struct localvar *oldEntry = &mb->localvar_table[i];
+ int startPC = oldEntry->pc0;
+ int endPC = startPC + oldEntry->length; /* inclusive! */
+
+ bool_t was_matching = FALSE;
+
+ for (codeRef = context->codeRef; codeRef < codeRefEnd; codeRef++) {
+ if (codeRef->flags != CRF_SKIP) {
+ instruction_data_type *this_idata = &idata[codeRef->inumber];
+ bool_t is_matching = this_idata->offset >= startPC
+ && this_idata->offset <= endPC;
+ if (!was_matching && is_matching) {
+ memcpy(currentLocalVar, oldEntry, sizeof(struct localvar));
+ currentLocalVar->pc0 = codeRef->offset;
+ was_matching = TRUE;
+ } else if (was_matching && !is_matching) {
+ currentLocalVar->length =
+ codeRef[-1].offset - currentLocalVar->pc0;
+ currentLocalVar++;
+ was_matching = FALSE;
+ }
+ }
+ }
+ if (was_matching) {
+ currentLocalVar->length =
+ codeRefEnd[-1].offset - currentLocalVar->pc0;
+ currentLocalVar++;
+ }
+ }
+
+ /* free(mb->localvar_table); */
+ mb->localvar_table_length = currentLocalVar - localVars;
+ mb->localvar_table = realloc(localVars,
+ (char *)currentLocalVar - (char *)localVars);
+}
+
+
+static void
+updateTarget(JsrContext *context, int inumber,
+ SubrContext* subroutine, void* target, int offset, int size)
+{
+ CodeRef *codeRef;
+ for (codeRef = context->mapping[inumber];
+ codeRef != NULL;
+ codeRef = codeRef->next) {
+ if (subroutineGoto(context, subroutine, codeRef->subroutine)) {
+ int value = codeRef->offset - offset;
+ unsigned char *t = target;
+ if (size == 2) {
+ t[0] = value >> 8;
+ t[1] = value;
+ } else if (size == 4) {
+ t[0] = value >> 24;
+ t[1] = value >> 16;
+ t[2] = value >> 8;
+ t[3] = value;
+ } else {
+ panic("Bad value passed for size");
+ }
+ return;
+ }
+ }
+ panic("Cannot find value for updateTarget");
+}
+
+
+
+static bool_t
+subroutineGoto(JsrContext *context, SubrContext *from, SubrContext *to)
+{
+ if (to == NULL || to == from) {
+ return TRUE;
+ } else if (from == NULL || to->depth >= from->depth) {
+ return FALSE;
+ } else {
+ do { from = from->parent; } while (from->depth > to->depth);
+ return from == to;
+ }
+}
+
+
+static bool_t
+matchSubroutine(JsrContext *context,
+ instruction_data_type *this_idata,
+ SubrContext *subroutine)
+{
+ int depth = subroutine->depth;
+ int i;
+
+ for (i = depth - 1; i >= 0; --i) {
+ if (this_idata->register_info.masks[i].entry != subroutine->target) {
+ return FALSE;
+ }
+ subroutine = subroutine->parent;
+ }
+ return TRUE;
+}
+
diff --git a/MPC.3.5.LINUX/preverifier/jar.c b/MPC.3.5.LINUX/preverifier/jar.c
--- /dev/null
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of Sun
+ * Microsystems, Inc. ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Sun.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
+ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
+ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: JAR class loader.
+ * FILE: jar.c
+ * OVERVIEW: Routines for reading contents of a JAR file. The routines
+ * are optimized to reduce code size and run-time memory
+ * requirement so that they can run happily on small devices.
+ * AUTHOR: Frank Yellin, Sun Microsystems, Inc.
+ * Modifications for JAR support and comments,
+ * Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <assert.h>
+
+#include "oobj.h"
+#include "typedefs.h"
+#include "jar.h"
+#include "jarint.h"
+#include "jartables.h"
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+static bool_t decodeDynamicHuffmanTables(inflaterState *state,
+ HuffmanCodeTable **lcodesPtr,
+ HuffmanCodeTable **dcodesPtr);
+
+static HuffmanCodeTable *makeCodeTable(inflaterState *state,
+ unsigned char *codelen,
+ unsigned numElems,
+ unsigned maxQuickBits);
+
+
+static bool_t inflateHuffman(inflaterState *state, bool_t fixedHuffman);
+static bool_t inflateStored(inflaterState *state);
+
+
+/*===========================================================================
+ * FUNCTION: inflate
+ * TYPE: jar file decoding
+ * OVERVIEW Used for decoding JAR files given the compressed data source,
+ * compressed data length, buffer to store decompressed data and
+ * length of decompression buffer.
+ *
+ * INTERFACE:
+ * parameters: compressed data source, compressed data length,
+ * buffer to store decompressed data, decompression buffer size
+ * returns: TRUE if the data was encoded in a supported <method> and the
+ * size of the decoded data is exactly the same as <decompLen>
+ * FALSE if an error occurs
+ * NOTE:
+ * The caller of this method must insure that this function can safely get
+ * up to INFLATER_EXTRA_BYTES beyond compData + compLen without causing
+ * any problems.
+ * The inflater algorithm occasionally reads one more byte than it needs
+ * to. But it double checks that it doesn't actually care what's in that
+ * extra byte.
+ *===========================================================================*/
+
+
+/* Change some definitions so that this compiles nicely, even if it is
+ * compiled as part of something that requires real malloc() and free()
+ */
+#if !JAR_INFLATER_INSIDE_KVM
+# undef START_TEMPORARY_ROOTS
+# undef END_TEMPORARY_ROOTS
+# undef MAKE_TEMPORARY_ROOT
+# define START_TEMPORARY_ROOTS
+# define END_TEMPORARY_ROOTS
+# define MAKE_TEMPORARY_ROOT(x)
+# define mallocBytes(x) malloc(x)
+# define freeBytes(x) if (x == NULL) {} else free(x)
+#else
+# define freeBytes(x)
+#endif
+
+bool_t
+inflate(JarCompressedType compData, /* compressed data source */
+ int compLen, /* length of compressed data */
+ unsigned char *decompData, /* buffer to store decompressed data */
+ int decompLen) /* length of decompression buffer */
+{
+ inflaterState stateStruct;
+ bool_t result;
+/* Temporarily define state, so that LOAD_IN, LOAD_OUT, etc. macros work */
+#define state (&stateStruct)
+ stateStruct.out = decompData;
+ stateStruct.outStart = decompData;
+ stateStruct.outEnd = decompData + decompLen;
+
+ stateStruct.inFile = compData;
+ stateStruct.inData = 0;
+ stateStruct.inDataSize = 0;
+ stateStruct.inRemaining = compLen + INFLATER_EXTRA_BYTES;
+
+#ifdef JAR_DEBUG_FILE
+ {
+ static int length = 0;
+ if (length == 0) {
+ struct stat stat_buffer;
+ stat(JAR_DEBUG_FILE, &stat_buffer);
+ length = stat_buffer.st_size;;
+ }
+ if (length == decompLen) {
+ FILE *f = fopen(JAR_DEBUG_FILE, "rb");
+ state->jarDebugBytes = malloc(length);
+ fseek(f, 0, SEEK_SET);
+ fread(state->jarDebugBytes, sizeof(char), length, f);
+ fclose(f);
+ } else {
+ state->jarDebugBytes = NULL;
+ }
+ }
+#endif
+
+ for(;;) {
+ int type;
+ DECLARE_IN_VARIABLES
+
+ LOAD_IN;
+ NEEDBITS(3);
+ type = NEXTBITS(3);
+ DUMPBITS(3);
+ STORE_IN;
+
+ switch (type >> 1) {
+ default:
+ case BTYPE_INVALID:
+ ziperr("Invalid BTYPE");
+ result = FALSE;
+ break;
+
+ case BTYPE_NO_COMPRESSION:
+ result = inflateStored(state);
+ break;
+
+ case BTYPE_FIXED_HUFFMAN:
+ result = inflateHuffman(state, TRUE);
+ break;
+
+ case BTYPE_DYNA_HUFFMAN:
+ START_TEMPORARY_ROOTS
+ result = inflateHuffman(state, FALSE);
+ END_TEMPORARY_ROOTS
+ break;
+ }
+
+ if (!result || (type & 1)) {
+ break;
+ }
+ }
+
+ if (state->inRemaining + (state->inDataSize >> 3) != INFLATER_EXTRA_BYTES) {
+ ziperr("Error on the input bits");
+ result = FALSE;
+ } else if (state->out != state->outEnd) {
+ ziperr("Error on the output bits");
+ result = FALSE;
+ }
+
+#ifdef JAR_DEBUG_FILE
+ if (state->jarDebugBytes != NULL) {
+ free(state->jarDebugBytes);
+ }
+#endif
+
+ /* Remove temporary definition of state defined above */
+#undef state
+
+ return result;
+}
+
+
+/*=========================================================================
+ * FUNCTION: inflateStored
+ * TYPE: Huffman code Decoding helper function
+ * OVERVIEW: Used by inflate() for BTYPE_NO_COMPRESSION.
+ * INTERFACE:
+ * parameters: inflaterState: *state
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static bool_t
+inflateStored(inflaterState *state)
+{
+ DECLARE_IN_VARIABLES
+ DECLARE_OUT_VARIABLES
+ unsigned len, nlen;
+
+ LOAD_IN; LOAD_OUT;
+
+ DUMPBITS(inDataSize & 7); /* move to byte boundary */
+ NEEDBITS(32)
+ len = NEXTBITS(16);
+ DUMPBITS(16);
+ nlen = NEXTBITS(16);
+ DUMPBITS(16);
+
+ ASSERT(inDataSize == 0);
+
+ if (len + nlen != 0xFFFF) {
+ ziperr("Bad length field");
+ return FALSE;
+ } else if ((unsigned) inRemaining < len) {
+ ziperr("Input overflow");
+ return FALSE;
+ } else if (out + len > state->outEnd) {
+ ziperr("Output overflow");
+ return FALSE;
+ } else {
+ if (!COPY_N_BYTES(out, len)) {
+ ziperr("Bad Read");
+ return FALSE;
+ }
+ inRemaining -= len;
+ out += len;
+ }
+ STORE_IN;
+ STORE_OUT;
+ return TRUE;
+}
+
+
+/*=========================================================================
+ * FUNCTION: inflateHuffman
+ * TYPE: Huffman code Decoding helper function
+ * OVERVIEW: Used by inflate() for BTYPE_FIXED_HUFFMAN and BTYPE_DYNA_HUFFMAN.
+ * INTERFACE:
+ * parameters: inflaterState: *state
+ * bool_t: fixedHuffman
+ *
+ * returns: boolean type
+ *=======================================================================*/
+static bool_t
+inflateHuffman(inflaterState *state, bool_t fixedHuffman)
+{
+ DECLARE_IN_VARIABLES
+ DECLARE_OUT_VARIABLES
+ unsigned char *outStart = state->outStart;
+ unsigned char *outEnd = state->outEnd;
+
+ bool_t noerror = FALSE;
+ unsigned int quickDataSize = 0, quickDistanceSize = 0;
+ unsigned int code, litxlen;
+ HuffmanCodeTable *lcodes, *dcodes;
+
+ if (!fixedHuffman) {
+ if (!decodeDynamicHuffmanTables(state, &lcodes, &dcodes)) {
+ return FALSE;
+ }
+ quickDataSize = lcodes->h.quickBits;
+ quickDistanceSize = dcodes->h.quickBits;
+ }
+
+ LOAD_IN;
+ LOAD_OUT;
+
+ for (;;) {
+ if (inRemaining < 0) {
+ goto done_loop;
+ }
+ NEEDBITS(MAX_BITS + MAX_ZIP_EXTRA_LENGTH_BITS);
+
+ if (fixedHuffman) {
+ /* literal (hex)
+ * 0x100 - 0x117 7 0.0000.00 - 0.0101.11
+ * 0 - 8f 8 0.0110.000 - 1.0111.111
+ * 118 - 11f 8 1.1000.000 - 1.1000.111
+ * 90 - ff 9 1.1001.0000 - 1.1111.1111
+ */
+
+ /* Get 9 bits, and reverse them. */
+ code = NEXTBITS(9);
+ code = REVERSE_9BITS(code);
+ if (code < 0x060) {
+ /* A 7-bit code */
+ DUMPBITS(7);
+ litxlen = 0x100 + (code >> 2);
+ } else if (code < 0x190) {
+ DUMPBITS(8);
+ litxlen = (code >> 1) + ((code < 0x180) ? (0x000 - 0x030)
+ : (0x118 - 0x0c0));
+ } else {
+ DUMPBITS(9);
+ litxlen = 0x90 + code - 0x190;
+ }
+ } else {
+ GET_HUFFMAN_ENTRY(lcodes, quickDataSize, litxlen, done_loop);
+ }
+
+ if (litxlen <= 255) {
+ if (out < outEnd) {
+#ifdef JAR_DEBUG_FILE
+ if (state->jarDebugBytes && state->jarDebugBytes[out - outStart] != litxlen) {
+ ziperr("Dragon single byte");
+ }
+#endif
+ *out++ = litxlen;
+ } else {
+ goto done_loop;
+ }
+ } else if (litxlen == 256) { /* end of block */
+ noerror = TRUE;
+ goto done_loop;
+ } else if (litxlen > 285) {
+ ziperr("Invalid literal/length");
+ goto done_loop;
+ } else {
+ unsigned int n = litxlen - LITXLEN_BASE;
+ unsigned int length = ll_length_base[n];
+ unsigned int moreBits = ll_extra_bits[n];
+ unsigned int d0, distance;
+
+ /* The NEEDBITS(..) above took care of this */
+ length += NEXTBITS(moreBits);
+ DUMPBITS(moreBits);
+
+ NEEDBITS(MAX_BITS);
+ if (fixedHuffman) {
+ d0 = REVERSE_5BITS(NEXTBITS(5));
+ DUMPBITS(5);
+ } else {
+ GET_HUFFMAN_ENTRY(dcodes, quickDistanceSize, d0, done_loop);
+ }
+
+ if (d0 > MAX_ZIP_DISTANCE_CODE) {
+ ziperr("Bad distance code");
+ goto done_loop;
+ }
+
+ NEEDBITS(MAX_ZIP_EXTRA_DISTANCE_BITS)
+ distance = dist_base[d0];
+ moreBits = dist_extra_bits[d0];
+ distance += NEXTBITS(moreBits);
+ DUMPBITS(moreBits);
+
+ if (out - distance < outStart) {
+ ziperr("copy underflow");
+ goto done_loop;
+ } else if (out + length > outEnd) {
+ ziperr("Output overflow");
+ goto done_loop;
+ } else {
+ unsigned char *prev = out - distance;
+ unsigned char *end = out + length;
+ while (out != end) {
+#ifdef JAR_DEBUG_FILE
+ if (state->jarDebugBytes
+ && state->jarDebugBytes[out - outStart] != *prev) {
+ ziperr("Dragon copy error");
+ }
+#endif
+ *out++ = *prev++;
+ }
+ }
+ }
+ }
+
+ done_loop:
+ STORE_IN;
+ STORE_OUT;
+
+ if (!JAR_INFLATER_INSIDE_KVM && !fixedHuffman) {
+ freeBytes(lcodes);
+ freeBytes(dcodes);
+ }
+ return noerror;
+}
+
+
+/*=========================================================================
+ * FUNCTION: decodeDynamicHuffmanTables
+ * TYPE: Huffman code Decoding
+ * OVERVIEW: Used by inflateHuffman() for decoding dynamic Huffman tables.
+ * INTERFACE:
+ * parameters: inflaterState: *state
+ * HuffmanCodeTable: **lcodesPtr
+ * HuffmanCodeTable: **dcodesPtr
+ *
+ * returns: TRUE if successful in decoding or
+ * FALSE if an error occurs
+ *=======================================================================*/
+
+static bool_t
+decodeDynamicHuffmanTables(inflaterState *state,
+ HuffmanCodeTable **lcodesPtr,
+ HuffmanCodeTable **dcodesPtr) {
+ DECLARE_IN_VARIABLES
+
+ HuffmanCodeTable *ccodes = NULL;
+ HuffmanCodeTable *lcodes = NULL;
+ HuffmanCodeTable *dcodes = NULL;
+
+ int hlit, hdist, hclen;
+ int i;
+ unsigned int quickBits;
+ unsigned char codelen[286 + 32];
+ unsigned char *codePtr, *endCodePtr;
+
+ LOAD_IN;
+
+ /* 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) */
+ /* 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) */
+ /* 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) */
+ NEEDBITS(14);
+ hlit = 257 + NEXTBITS(5);
+ DUMPBITS(5);
+ hdist = 1 + NEXTBITS(5);
+ DUMPBITS(5);
+ hclen = 4 + NEXTBITS(4);
+ DUMPBITS(4);
+
+ /*
+ * (HCLEN + 4) x 3 bits: code lengths for the code length
+ * alphabet given just above, in the order: 16, 17, 18,
+ * 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ *
+ * These code lengths are interpreted as 3-bit integers
+ * (0-7); as above, a code length of 0 means the
+ * corresponding symbol (literal/length or distance code
+ * length) is not used.
+ */
+ memset(codelen, 0x0, 19);
+ for (i=0; i<hclen; i++) {
+ NEEDBITS(3); /* 3, plus 7 below */
+ if (inRemaining < 0) {
+ goto error;
+ }
+ codelen[(int)ccode_idx[i]] = (unsigned char) NEXTBITS(3);
+ DUMPBITS(3);
+ }
+
+ ccodes = makeCodeTable(state, codelen, 19, MAX_QUICK_CXD);
+ if (ccodes == NULL) {
+ goto error;
+ }
+ quickBits = ccodes->h.quickBits;
+
+ /*
+ * HLIT + 257 code lengths for the literal/length alphabet,
+ * encoded using the code length Huffman code.
+ *
+ * HDIST + 1 code lengths for the distance alphabet,
+ * encoded using the code length Huffman code.
+ *
+ * The code length repeat codes can cross from HLIT + 257 to the
+ * HDIST + 1 code lengths. In other words, all code lengths form
+ * a single sequence of HLIT + HDIST + 258 values.
+ */
+
+ memset(codelen, 0x0, sizeof(codelen));
+ for ( codePtr = codelen, endCodePtr = codePtr + hlit + hdist;
+ codePtr < endCodePtr; ) {
+ int val;
+
+ if (inRemaining < 0) {
+ goto error;
+ }
+
+ NEEDBITS(MAX_BITS + 7); /* 7 is max repeat bits below */
+ GET_HUFFMAN_ENTRY(ccodes, quickBits, val, error);
+
+ /*
+ * 0 - 15: Represent code lengths of 0 - 15
+ * 16: Copy the previous code length 3 - 6 times.
+ * 3 + (2 bits of length)
+ * 17: Repeat a code length of 0 for 3 - 10 times.
+ * 3 + (3 bits of length)
+ * 18: Repeat a code length of 0 for 11 - 138 times
+ * 11 + (7 bits of length)
+ */
+ if (val <= 15) {
+ *codePtr++ = val;
+ } else if (val <= 18) {
+ unsigned repeat = (val == 18) ? 11 : 3;
+ unsigned bits = (val == 18) ? 7 : (val - 14);
+
+ repeat += NEXTBITS(bits); /* The NEEDBITS is above */
+ DUMPBITS(bits);
+
+ if (codePtr + repeat > endCodePtr) {
+ ziperr("Bad repeat code");
+ }
+
+ if (val == 16) {
+ if (codePtr == codelen) {
+ ziperr("Bad repeat code");
+ goto error;
+ }
+ memset(codePtr, codePtr[-1], repeat);
+ } else {
+ /* The values have already been set to zero, above, so
+ * we don't have to do anything */
+ }
+ codePtr += repeat;
+ } else {
+ ziperr("Bad code-length code");
+ goto error;
+ }
+ }
+
+
+ lcodes = makeCodeTable(state, codelen, hlit, MAX_QUICK_LXL);
+ if (lcodes == NULL) {
+ goto error;
+ }
+
+ dcodes = makeCodeTable(state, codelen + hlit, hdist, MAX_QUICK_CXD);
+ if (dcodes == NULL) {
+ goto error;
+ }
+
+ *lcodesPtr = lcodes;
+ *dcodesPtr = dcodes;
+ STORE_IN;
+ if (!JAR_INFLATER_INSIDE_KVM) {
+ freeBytes(ccodes);
+ }
+ return TRUE;
+
+error:
+ if (!JAR_INFLATER_INSIDE_KVM) {
+ freeBytes(ccodes);
+ freeBytes(dcodes);
+ freeBytes(lcodes);
+ }
+ return FALSE;
+}
+
+
+/*=========================================================================
+ * FUNCTION: makeCodeTable
+ * TYPE: Huffman code table creation
+ * INTERFACE:
+ * parameters: inflaterState
+ * code length
+ * number of elements of the alphabet
+ * maxQuickBits
+ * returns: Huffman code table created if successful or
+ * NULL if an error occurs
+ *=======================================================================*/
+
+HuffmanCodeTable * makeCodeTable(
+ inflaterState *state,
+ unsigned char *codelen, /* Code lengths */
+ unsigned numElems, /* Number of elements of the alphabet */
+ unsigned maxQuickBits) /* If the length of a code is longer than
+ * <maxQuickBits> number of bits, the code is
+ * stored in the sequential lookup table
+ * instead of the quick lookup array. */
+{
+ unsigned int bitLengthCount[MAX_BITS + 1];
+ unsigned int codes[MAX_BITS + 1];
+ unsigned bits, minCodeLen = 0, maxCodeLen = 0;
+ const unsigned char *endCodeLen = codelen + numElems;
+ unsigned int code, quickMask;
+ unsigned char *p;
+
+ HuffmanCodeTable * table;
+ int mainTableLength, longTableLength, numLongTables;
+ int tableSize;
+ int j;
+
+ unsigned short *nextLongTable;
+
+ /* Count the number of codes for each code length */
+ memset(bitLengthCount, 0, sizeof(bitLengthCount));
+ for (p = codelen; p < endCodeLen; p++) {
+ bitLengthCount[*p]++;
+ }
+
+ if (bitLengthCount[0] == numElems) {
+ ziperr("Bad code table -- empty");
+ return NULL;
+ }
+
+ /* Find the minimum and maximum. It's faster to do it in a separate
+ * loop that goes 1..MAX_BITS, than in the above loop that looks at
+ * every code element */
+ code = minCodeLen = maxCodeLen = 0;
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ codes[bits] = code;
+ if (bitLengthCount[bits] != 0) {
+ if (minCodeLen == 0) minCodeLen = bits;
+ maxCodeLen = bits;
+ code += bitLengthCount[bits] << (MAX_BITS - bits);
+ }
+ }
+
+ if (INCLUDEDEBUGCODE) {
+ if (code != (1 << MAX_BITS)) {
+ code += (1 << (MAX_BITS - maxCodeLen));
+ if (code != (1 << MAX_BITS)) {
+ ziperr("Unexpected bit codes");
+ }
+ }
+ }
+
+ /* Calculate the size of the code table and allocate it. */
+ if (maxCodeLen <= maxQuickBits) {
+ /* We don't need any subtables. We may even be able to get
+ * away with a table smaller than maxCodeLen
+ */
+ maxQuickBits = maxCodeLen;
+ mainTableLength = (1 << maxCodeLen);
+ numLongTables = longTableLength = 0;
+ } else {
+ mainTableLength = (1 << maxQuickBits);
+ numLongTables = (1 << MAX_BITS) - codes[maxQuickBits + 1];
+ numLongTables = numLongTables >> (MAX_BITS - maxQuickBits);
+ longTableLength = 1 << (maxCodeLen - maxQuickBits);
+ }
+ ASSERT(mainTableLength == 1 << maxQuickBits);
+ tableSize = sizeof(HuffmanCodeTableHeader)
+ + (mainTableLength + numLongTables * longTableLength) *
+ sizeof(table->entries[0]);
+ table = (HuffmanCodeTable*)mallocBytes(tableSize);
+ nextLongTable = &table->entries[mainTableLength];
+ MAKE_TEMPORARY_ROOT(table);
+
+ memset(table, 0, tableSize);
+
+ table->h.maxCodeLen = maxCodeLen;
+ table->h.quickBits = maxQuickBits;
+
+ quickMask = (1 << maxQuickBits) - 1;
+
+ for (p = codelen; p < endCodeLen; p++) {
+ unsigned short huff;
+ bits = *p;
+ if (bits == 0) {
+ continue;
+ }
+ /* Get the next code of the current length */
+ code = codes[bits];
+ codes[bits] += 1 << (MAX_BITS - bits);
+ code = REVERSE_15BITS(code);
+ huff = ((p - codelen) << 4) + bits;
+ if (bits <= maxQuickBits) {
+ unsigned stride = 1 << bits;
+ for (j = code; j < mainTableLength; j += stride) {
+ table->entries[j] = huff;
+ }
+ } else {
+ unsigned short *thisLongTable;
+ unsigned stride = 1 << (bits - maxQuickBits);
+ unsigned int prefixCode = code & quickMask;
+ unsigned int suffixCode = code >> maxQuickBits;
+ if (table->entries[prefixCode] == 0) {
+ /* This in the first long code with the indicated prefix.
+ * Create a pointer to the subtable */
+ long delta = (char *)nextLongTable - (char *)table;
+ table->entries[prefixCode] = (unsigned short)(HUFFINFO_LONG_MASK | delta);
+ thisLongTable = nextLongTable;
+ nextLongTable += longTableLength;
+ } else {
+ long delta = table->entries[prefixCode] & ~HUFFINFO_LONG_MASK;
+ thisLongTable = (unsigned short *)((char *)table + delta);
+ }
+ for (j = suffixCode; j < longTableLength; j += stride) {
+ thisLongTable[j] = huff;
+ }
+ }
+ if (INCLUDEDEBUGCODE && inflateVerbose > 0) {
+ putchar(' ');
+
+ for (j = 15; j >= 0; j--) {
+ char c = (j >= (signed)bits) ? ' '
+ : (code & (1 << j)) ? '1' : '0';
+ putchar(c);
+ }
+ fprintf(stdout,
+ " Char = %02x, Code = %4x\n", (p - codelen), code);
+ }
+
+ }
+ ASSERT(nextLongTable == &table->entries[mainTableLength + numLongTables * longTableLength]);
+
+ return table;
+}
+
+
+#if INCLUDEDEBUGCODE
+
+/*=========================================================================
+ * FUNCTION: ziperr
+ * TYPE: zip error processing function
+ * OVERVIEW: Used by inflate() and other functions for zip error processing.
+ * INTERFACE:
+ * parameters: const char *message
+ *
+ * returns: nothing
+ *=======================================================================*/
+static void
+ziperr(const char *message) {
+ fprintf(stderr, "Zip Error: %s\n", message);
+}
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/jar.h b/MPC.3.5.LINUX/preverifier/jar.h
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of Sun
+ * Microsystems, Inc. ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Sun.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
+ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
+ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: KVM
+ * SUBSYSTEM: JAR file reader.
+ * FILE: jar.h
+ * OVERVIEW: Public header file for the JAR file reader module.
+ * The JAR DataStream API is used by the Pre-verifier for loading
+ * JAR files.
+ * AUTHOR: Tasneem Sayeed
+ *=======================================================================*/
+
+#ifndef _JAR_H_
+#define _JAR_H_
+
+#include "typedefs.h"
+#include "stdio.h"
+#include "sys/types.h"
+#include "stddef.h"
+
+
+/*
+ * Debug flag for JAR support
+ */
+#define JAR_DEBUG 0
+
+/*=========================================================================
+ * JAR file reader defines and macros
+ *=======================================================================*/
+
+/*
+ * Supported compression types
+ */
+#define STORED 0
+#define DEFLATED 8
+
+#define MAX_BITS 15 /* Maximum number of codes in Huffman Code Table */
+
+/*
+ * Header sizes including signatures
+ */
+#define LOCHDRSIZ 30
+#define CENHDRSIZ 46
+#define ENDHDRSIZ 22
+
+/*
+ * Header field access macros
+ */
+#define CH(b, n) ((long)(((unsigned char *)(b))[n]))
+#define SH(b, n) ((long)(CH(b, n) | (CH(b, n+1) << 8)))
+#define LG(b, n) ((long)(SH(b, n) | (SH(b, n+2) << 16)))
+
+#define GETSIG(b) LG(b, 0) /* signature */
+
+#define LOCSIG (('P' << 0) + ('K' << 8) + (3 << 16) + (4 << 24))
+#define CENSIG (('P' << 0) + ('K' << 8) + (1 << 16) + (2 << 24))
+#define ENDSIG (('P' << 0) + ('K' << 8) + (5 << 16) + (6 << 24))
+
+#define freeBytes(x) if (x == NULL) {} else free(x)
+
+
+/*
+ * Macros for getting local file header (LOC) fields
+ */
+#define LOCVER(b) SH(b, 4) /* version needed to extract */
+#define LOCFLG(b) SH(b, 6) /* encrypt flags */
+#define LOCHOW(b) SH(b, 8) /* compression method */
+#define LOCTIM(b) LG(b, 10) /* modification time */
+#define LOCCRC(b) LG(b, 14) /* uncompressed file crc-32 value */
+#define LOCSIZ(b) LG(b, 18) /* compressed size */
+#define LOCLEN(b) LG(b, 22) /* uncompressed size */
+#define LOCNAM(b) SH(b, 26) /* filename size */
+#define LOCEXT(b) SH(b, 28) /* extra field size */
+
+/*
+ * Macros for getting central directory header (CEN) fields
+ */
+#define CENVEM(b) SH(b, 4) /* version made by */
+#define CENVER(b) SH(b, 6) /* version needed to extract */
+#define CENFLG(b) SH(b, 8) /* general purpose bit flags */
+#define CENHOW(b) SH(b, 10) /* compression method */
+#define CENTIM(b) LG(b, 12) /* file modification time (DOS format) */
+#define CENCRC(b) LG(b, 16) /* crc of uncompressed data */
+#define CENSIZ(b) LG(b, 20) /* compressed size */
+#define CENLEN(b) LG(b, 24) /* uncompressed size */
+#define CENNAM(b) SH(b, 28) /* length of filename */
+#define CENEXT(b) SH(b, 30) /* length of extra field */
+#define CENCOM(b) SH(b, 32) /* file comment length */
+#define CENDSK(b) SH(b, 34) /* disk number start */
+#define CENATT(b) SH(b, 36) /* internal file attributes */
+#define CENATX(b) LG(b, 38) /* external file attributes */
+#define CENOFF(b) LG(b, 42) /* offset of local header */
+
+/*
+ * Macros for getting end of central directory header (END) fields
+ */
+#define ENDSUB(b) SH(b, 8) /* number of entries on this disk */
+#define ENDTOT(b) SH(b, 10) /* total number of entries */
+#define ENDSIZ(b) LG(b, 12) /* central directory size */
+#define ENDOFF(b) LG(b, 16) /* central directory offset */
+#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
+
+/*=========================================================================
+ * Macros for Huffman Codes used by the JAR file reader
+ *=======================================================================*/
+
+/*
+ * This is the algorithm for decoding Huffman-encoded
+ * data.
+ *
+ * loop (until end of block code recognized)
+ * decode literal/length value from input stream
+ * if value < 256
+ * copy value (literal byte) to output stream
+ * otherwise
+ * if value = end of block (256)
+ * break from loop
+ * otherwise (value = 257..285)
+ * decode distance from input stream
+ *
+ * move backwards distance bytes in the output
+ * stream, and copy length bytes from this
+ * position to the output stream.
+ * end loop
+ */
+#define BTYPE_NO_COMPRESSION 0x00
+#define BTYPE_FIXED_HUFFMAN 0x01 /* Fixed Huffman Code */
+#define BTYPE_DYNA_HUFFMAN 0x02 /* Dynamic Huffman code */
+#define BTYPE_INVALID 0x03 /* Invalid code */
+
+#define LITXLEN_BASE 257
+
+
+/*=========================================================================
+ * JAR DataStream API for reading and writing to/from JAR files
+ *=======================================================================*/
+
+#define JAR_READ 1 /* Mode for reading from a JAR data stream */
+#define JAR_WRITE 2 /* Mode for writing from a JAR data stream */
+#define JAR_RESOURCE 1 /* type of resource (see JAR_DataStream) */
+
+/*=========================================================================
+ * JAR Data Stream structure
+ *=======================================================================*/
+typedef struct JAR_DataStream {
+ unsigned char *data; /* data stream for reading/writing */
+ int type; /* indicates type of resource */
+ int dataLen; /* length of data stream */
+ int dataIndex; /* current position for reading */
+ int mode; /* mode for reading or writing */
+ /* mode must be either JAR_READ or JAR_WRITE */
+} JAR_DataStream;
+
+typedef struct JAR_DataStream* JAR_DataStreamPtr;
+
+/*=========================================================================
+ * Forward declarations for JAR DataStream API
+ *=======================================================================*/
+int JAR_ReadBytes(JAR_DataStream *ds, char *buf, int len);
+int JAR_WriteBytes(JAR_DataStream *ds, char *buf, int len);
+int JAR_SkipBytes(JAR_DataStream *ds, int len);
+
+/*=========================================================================
+ * Forward declarations for JAR file reader
+ *=======================================================================*/
+
+
+
+typedef FILE *JarCompressedType;
+/*
+typedef const unsigned char *JarCompressedType;
+*/
+
+bool_t inflate(JarCompressedType data, int compLen,
+ unsigned char *decompData, int decompLen);
+
+/* Any caller to inflate must ensure that it is safe to read at least
+ * this many bytes beyond compData + compLen
+ */
+#define INFLATER_EXTRA_BYTES 4
+
+
+/*
+ * Indicates whether JAR inflater is executed from KVM or a stand-alone
+ * program.
+ */
+#define JAR_INFLATER_INSIDE_KVM 0
+
+#endif /* _JAR_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/jar_support.c b/MPC.3.5.LINUX/preverifier/jar_support.c
--- /dev/null
@@ -0,0 +1,1347 @@
+/* * @(#)jar_support.c 1.24 01/07/19
+ *
+ * Copyright 1997, 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: JAR support routines for the verifier.
+ * FILE: jar_support.c
+ * OVERVIEW: JAR support routines for verifying class files from a ZIP or
+ * JAR file.
+ * Note that the JAR file reader used is based on the KVM
+ * implementation with some modifications.
+ * AUTHOR: Tasneem Sayeed, Java Consumer Technologies, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "sys_api.h"
+#include "path_md.h"
+#include "path.h"
+#include "oobj.h"
+#include "jar.h"
+#include "convert_md.h"
+
+#include <string.h>
+
+#ifdef WIN32
+#include <process.h>
+#endif
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+//extern int errno;
+char str_buffer[STRINGBUFFERSIZE]; /* shared string buffer */
+bool_t JARfile = FALSE; /* if true, indicates that output is in a
+ JAR file */
+extern bool_t tmpDirExists;
+ /* if true, indicates that a temp dir exists
+ with classes to be verified */
+char *zipFileName = NULL; /* stores name of the zip file */
+extern char tmp_dir[32]; /* temporary directory for storing
+ verified classes */
+extern char *output_dir; /* output directory */
+
+char manifestfile[1024]; /* used for saving the JAR manifest file name */
+
+extern void VerifyFile(register char *fn);
+
+
+/*=========================================================================
+ * FUNCTION: isJARfile
+ * OVERVIEW: Determines if the given file is a JAR or ZIP file.
+ * Returns true if the suffix ends with ".jar" or ".zip".
+ * INTERFACE:
+ * parameters: fn: name of the JAR file
+ * length: length of data, in bytes
+ * returns: boolean type
+ *=======================================================================*/
+bool_t
+isJARfile (char *fn, int length)
+{
+ char *suffix;
+
+
+ if (length >= 4 &&
+ (( suffix = fn + length - 4)[0] == '.') &&
+ ((( _toupper(suffix[1]) == 'Z') &&
+ ( _toupper(suffix[2]) == 'I') &&
+ ( _toupper(suffix[3]) == 'P')) ||
+ (( _toupper(suffix[1]) == 'J') &&
+ ( _toupper(suffix[2]) == 'A') &&
+ ( _toupper(suffix[3]) == 'R')))) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: isManifestfile
+ * OVERVIEW: Determines if the given file is a JAR Manifest file.
+ * Returns true if the file ends with "MANIFEST.MF".
+ * INTERFACE:
+ * parameters: fn: name of the JAR manifest file
+ * length: length of data, in bytes
+ * returns: boolean type
+ *=======================================================================*/
+bool_t
+isManifestfile (char *fn, int length)
+{
+ if ((length >= 11) &&
+ (strcmp(fn + length - 11, "MANIFEST.MF") == 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: ensure_tmpdir_exists
+ * OVERVIEW: Validates to ensure that the tmpdir exists using the
+ * system-specific directory delimiters.
+ *
+ * INTERFACE:
+ * parameters: char* dir name
+ * returns: nothing
+ *=======================================================================*/
+void ensure_tmpdir_exists(char *dir)
+{
+ struct stat stat_buf;
+ char *parent;
+ char *q;
+ if (dir[0] == 0) {
+ return;
+ }
+ parent = strdup(dir);
+ q = strrchr(parent, (char)LOCAL_DIR_SEPARATOR);
+ if (q) {
+ *q = 0;
+ ensure_tmpdir_exists(parent);
+ }
+ if (stat(dir, &stat_buf) < 0) {
+ if (JAR_DEBUG && verbose) {
+ jio_fprintf(stderr, "Creating output directory [%s]\n", dir);
+ }
+#ifdef WIN32
+ mkdir(dir);
+#endif
+#ifdef UNIX
+ mkdir(dir, 0755);
+#endif
+ }
+ free(parent);
+}
+
+
+/*=========================================================================
+ * FUNCTION: JARname2fname
+ * OVERVIEW: Converts JAR name to the system-specific file name with
+ * the correct directory delimiters.
+ *
+ * INTERFACE:
+ * parameters: char* source JAR name
+ * char* dest file name
+ * int size
+ * returns: char*
+ *=======================================================================*/
+char*
+JARname2fname(char *src, char *dst, int size) {
+ char *buf = dst;
+ for (; (--size > 0) && (*src != '\0') ; src++, dst++) {
+ if (*src == '/') {
+ *dst = (char)LOCAL_DIR_SEPARATOR;
+ } else {
+ *dst = *src;
+ }
+ }
+ dst++;
+ *dst = '\0';
+ return buf;
+}
+
+
+/*=========================================================================
+ * FUNCTION: getZipEntry
+ * OVERVIEW: Converts a zip file to a Zip entry type.
+ * INTERFACE:
+ * parameters: zipFile: name of the JAR file
+ * len: length of data, in bytes
+ * returns: zip entry type
+ *=======================================================================*/
+zip_t *
+getZipEntry (char *zipFile, int len) {
+ zip_t * zipEntry = NULL; /* for processing errors */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "getZipEntry: JAR file [%s] Size [%d]\n", zipFile, len);
+
+ /* create the zip entry for loading the ZIP file */
+ zipEntry = (zip_t *) sysMalloc(sizeof(zip_t) + len);
+ if (zipEntry == NULL) {
+ fprintf(stderr, "getZipEntry: Out of memory\n");
+ exit(1);
+ }
+
+ memcpy(zipEntry->name, zipFile, len);
+
+ zipEntry->name[len] = '\0';
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "getZipEntry: Zip Entry Name [%s]\n", zipEntry->name);
+
+
+ zipEntry->type = '\0';
+ return zipEntry;
+}
+
+
+/*=========================================================================
+ * FUNCTION: findJARDirectories
+ * OVERVIEW: Helper function used for JAR loading for locating JAR
+ * directories.
+ * It returns TRUE if it is successful in locating the
+ * JAR directory headers, false otherwise.
+ * If successful,
+ * entry->jar.locpos is set to the position of the first
+ * local header.
+ * entry->jar.cenpos is set to the position of the first
+ * central header.
+ *
+ * Note that *locpos pointer is the logical "0" of the file.
+ * All offsets extracted need to have this value added to them.
+ *
+ * INTERFACE:
+ * parameters: entry: zipFileEntry
+ * statbuf: pointer to the stat buffer
+ * returns: boolean type
+ *=======================================================================*/
+
+bool_t
+findJARDirectories(zip_t *entry, struct stat *statbuf)
+{
+ bool_t result = FALSE;
+ long length = statbuf->st_size;
+ long position, minPosition;
+ char *bp;
+ FILE *file;
+
+ char *buffer = str_buffer;
+ unsigned const int bufferSize = STRINGBUFFERSIZE;
+
+ /* Calculate the smallest possible position for the end header. It
+ * can be at most 0xFFFF + ENDHDRSIZ bytes from the end of the file, but
+ * the file must also have a local header and a central header
+ */
+ minPosition = length - (0xFFFF + ENDHDRSIZ);
+ if (minPosition < LOCHDRSIZ + CENHDRSIZ) {
+ minPosition = LOCHDRSIZ + CENHDRSIZ;
+ }
+
+ file = fopen(entry->name, "rb");
+ if (file == NULL) {
+ goto done;
+ }
+
+ /* Read in the last ENDHDRSIZ bytes into the buffer. 99% of the time,
+ * the file won't have a comment, and this is the only read we'll need */
+ if ( (fseek(file, -ENDHDRSIZ, SEEK_END) < 0)
+ || (fread(buffer, sizeof(char), ENDHDRSIZ, file) != ENDHDRSIZ)) {
+ goto done;
+ }
+ /* Get the position in the file stored into buffer[0] */
+ position = length - ENDHDRSIZ; /* Position in file of buffer[0] */
+ bp = buffer; /* Where to start looking */
+ for (;;) {
+ /* "buffer" contains a block of data from the file, starting at
+ * position "position" in the file.
+ * We investigate whether position + (bp - buffer) is the start
+ * of the end header in the zip file. This file position is at
+ * position bp in the buffer.
+ */
+ /* Use simplified version of Knuth Morris Pratt search algorithm. */
+ switch(bp[0]) {
+ case '\006': /* The header must start at least 3 bytes back */
+ bp -= 3; break;
+ case '\005': /* The header must start at least 2 bytes back */
+ bp -= 2; break;
+ case 'K': /* The header must start at least 1 byte back */
+ bp -= 1; break;
+ case 'P': /* Either this is the header, or the header must
+ * start at least 4 back
+ */
+ if (bp[1] == 'K' && bp[2] == 5 && bp[3] == 6) {
+ int endpos = position + (bp - buffer);
+ if (endpos + ENDHDRSIZ + ENDCOM(bp) == length) {
+ unsigned long cenpos = endpos - ENDSIZ(bp);
+ unsigned long locpos = cenpos - ENDOFF(bp);
+ entry->jar.cenpos = cenpos;
+ entry->jar.locpos = locpos;
+ result = TRUE;
+ goto done;
+ }
+ }
+ /* FALL THROUGH */
+ default: /* This char isn't in the header signature, so
+ * the header must start at least four chars back */
+ bp -= 4;
+ }
+
+ if (bp < buffer) {
+ /* We've moved outside our window into the file. We must
+ * move the window backwards */
+ int count = position - minPosition; /* Bytes left in file */
+ if (count == 0) {
+ /* Nothing left to read. Time to give up */
+ goto done;
+ } else {
+ /* up to ((bp - buffer) + ENDHDRSIZ) bytes in the buffer might
+ * still be part of the end header, so the most bytes we can
+ * actually read are
+ * bufferSize - ((bp - buffer) + ENDHDRSIZE).
+ */
+ int available = (bufferSize - ENDHDRSIZ) + (buffer - bp);
+ if (count > available) {
+ count = available;
+ }
+ }
+ /* Back up, while keeping our virtual position the same */
+ position -= count;
+ bp += count;
+ memmove(buffer + count, buffer, bufferSize - count);
+ if ( (fseek(file, position, SEEK_SET) < 0)
+ || (fread(buffer, sizeof(char), count, file) != (unsigned)count)) {
+ goto done;
+ }
+ }
+ } /* end of for loop */
+
+ done:
+ if (file != NULL) {
+ fclose(file);
+ }
+ return result;
+}
+
+
+/*=========================================================================
+ * FUNCTION: jarCRC32
+ * OVERVIEW: Returns the CRC of an array of bytes, using the same
+ * algorithm as used by the JAR reader.
+ * INTERFACE:
+ * parameters: data: pointer to the array of bytes
+ * length: length of data, in bytes
+ * returns: CRC
+ *=======================================================================*/
+
+static unsigned long
+jarCRC32(unsigned char *data, unsigned long length) {
+ unsigned long crc = 0xFFFFFFFF;
+ unsigned int j;
+ for ( ; length > 0; length--, data++) {
+ crc ^= *data;
+ for (j = 8; j > 0; --j) {
+ crc = (crc & 1) ? ((crc >> 1) ^ 0xedb88320) : (crc >> 1);
+ }
+ }
+ return ~crc;
+}
+
+
+/*=========================================================================
+ * FUNCTION: loadJARfile()
+ * TYPE: load JAR file
+ * OVERVIEW: Internal function used by openClassfileInternal().
+ *
+ * This function reads the specified class file from the JAR file. The
+ * result is returned as a JAR_DataStream*. NULL is returned if it
+ * cannot find the file, or there is some error.
+ *
+ * INTERFACE:
+ * parameters: entry: zip file entry for the JAR file
+ * filename: class file name to search for
+ * returns: JAR_DataStream* for saving the JAR file info, or NULL.
+ *=======================================================================*/
+
+JAR_DataStreamPtr
+loadJARfile(zip_t *entry, const char* filename)
+{
+ JAR_DataStreamPtr jdstream = NULL; /* result on error */
+ unsigned int filenameLength;
+ unsigned int nameLength;
+ char buff[BUFSIZ];
+ char *UTFfilename = &buff[0];
+ char *p = str_buffer; /* temporary storage */
+ int offset;
+ char *fname = NULL;
+ FILE *file = fopen(entry->name, "rb");
+ if (file == NULL) {
+ goto done;
+ }
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "loadJARfile: Opening zip file %s to search for [%s]\n",
+ entry->name, filename);
+
+ /* add the .class to the filename */
+
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "loadJARfile: Adding '.class' to %s size [%d]\n", filename, strlen(filename));
+
+ /* Conversion for Japanese filenames */
+ native2utf8(filename, UTFfilename, BUFSIZ);
+
+ /* allocate fname large enough to hold .class + '\0' terminator */
+ fname = (char *)malloc(strlen(UTFfilename) + 6 + 1);
+ sprintf(fname, "%s.class", UTFfilename);
+ filenameLength=strlen(fname);
+ fname[filenameLength]='\0';
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "loadJARfile: Searching for filename [%s]\n", fname);
+
+ /* Go to the start of the central headers */
+ offset = entry->jar.cenpos;
+ for (;;) {
+
+ if (/* Go to the next central header */
+ (fseek(file, offset, SEEK_SET) < 0)
+ /* Read the bytes */
+ || (fread(p, sizeof(char), CENHDRSIZ, file) != CENHDRSIZ)
+ /* Make sure it is a header */
+ || (GETSIG(p) != CENSIG)) {
+ goto done;
+ }
+
+ /* Get the nameLength */
+ nameLength = CENNAM(p);
+
+
+ if (nameLength == filenameLength) {
+ if (fread(p + CENHDRSIZ, sizeof(char), nameLength, file)
+ != nameLength) {
+ goto done;
+ }
+ if (memcmp(p + CENHDRSIZ, fname, nameLength) == 0) {
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "loadJARfile: Class name found [%s]...\n", fname);
+ break;
+ }
+ }
+
+ /* Set offset to the next central header */
+ offset += CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
+
+ } /* end loop */
+
+ /* p points at the central header for the file */
+ {
+ unsigned long decompLen = CENLEN(p); /* the decompressed length */
+ unsigned long compLen = CENSIZ(p); /* the compressed length */
+ unsigned long method = CENHOW(p); /* how it is stored */
+ unsigned long expectedCRC = CENCRC(p); /* expected CRC */
+ unsigned long actualCRC;
+
+ unsigned char *decompData;
+
+ /* Make sure file is not encrypted */
+ if ((CENFLG(p) & 1) == 1) {
+ fprintf(stderr, "Entry is encrypted");
+ goto done;
+ }
+
+
+ jdstream =
+ (JAR_DataStreamPtr)sysMalloc(sizeof(JAR_DataStream) + decompLen);
+ decompData = (unsigned char *)(jdstream + 1);
+
+ if (/* Go to the beginning of the LOC header */
+ (fseek(file, entry->jar.locpos + CENOFF(p), SEEK_SET) < 0)
+ /* Read it */
+ || (fread(p, sizeof(char), LOCHDRSIZ, file) != LOCHDRSIZ)
+ /* Skip over name and extension, if any */
+ || (fseek(file, LOCNAM(p) + LOCEXT(p), SEEK_CUR) < 0)) {
+ goto done;
+ }
+
+ switch (method) {
+ case STORED:
+ if (compLen != decompLen) {
+ return NULL;
+ }
+ fread(decompData, sizeof(char), decompLen, file);
+ break;
+
+ case DEFLATED: {
+ bool_t inflateOK;
+ inflateOK = inflate(file, compLen, decompData, decompLen);
+
+ if (!inflateOK) {
+ sysFree(jdstream);
+ jdstream = NULL;
+ }
+ break;
+ }
+
+ default:
+ sysFree(jdstream);
+ jdstream = NULL;
+ break;
+ }
+
+ actualCRC = jarCRC32(decompData, decompLen);
+ if (actualCRC != expectedCRC) {
+ printf("Unexpected CRC value");
+ }
+
+ done:
+ if (file != NULL) {
+ fclose(file);
+ }
+
+ if (fname != NULL) {
+ sysFree(fname);
+ }
+
+ if (jdstream != NULL) {
+
+ jdstream->type = JAR_RESOURCE;
+ jdstream->data = decompData;
+ jdstream->dataLen = decompLen;
+ jdstream->dataIndex = 0;
+ jdstream->mode = JAR_READ;
+ }
+ return jdstream;
+
+ }
+}
+
+
+/*=========================================================================
+ * FUNCTION: ReadFromZip()
+ * TYPE: Reads and verifies ZIP file entries
+ * OVERVIEW: Internal function used by ProcessInputs() and recurse_dir.
+ *
+ * This function reads all the Zip entries, and stores them temporarily in
+ * tmpdir. If the ZIP entry read is a class file, then VerifyFile is invoked
+ * to verify the class file. Otherwise, the file read is simply copied over
+ * temporarily to the tmpdir. These are later used for generating a new JAR
+ * file.
+ *
+ * INTERFACE:
+ * parameters: ZipEntry: name of the zip file entry.
+ * returns: nothing
+ *=======================================================================*/
+
+void
+ReadFromZip(zip_t *entry)
+{
+ unsigned int nameLength;
+ char *filename = NULL;
+ char *p = str_buffer; /* temporary storage */
+ int offset, nextOffset;
+ int fd;
+ int status;
+ JAR_DataStreamPtr jdstream = NULL;
+ struct stat stat_buf;
+ unsigned char *decompData;
+ unsigned long decompLen; /* the decompressed length */
+
+ FILE *file = fopen(entry->name, "rb");
+ if (file == NULL) {
+ goto done;
+ }
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ReadFromZip: Opened zip file to read classes \n");
+
+ /* initialize */
+ memset(manifestfile, 0, 1024);
+
+ /* Go to the start of the central headers */
+ offset = entry->jar.cenpos;
+ for (;;) {
+
+ if (/* Go to the next central header */
+ (fseek(file, offset, SEEK_SET) < 0)
+ /* Read the bytes */
+ || (fread(p, sizeof(char), CENHDRSIZ, file) != CENHDRSIZ)
+ /* Make sure it is a header */
+ || (GETSIG(p) != CENSIG)) {
+ goto done;
+ }
+ /* Get the nameLength */
+ nameLength = CENNAM(p);
+
+ if (fread(p + CENHDRSIZ, sizeof(char), nameLength, file)
+ != nameLength) {
+ goto done;
+ }
+
+
+ /* initialize the filename with nulls every time */
+
+ filename = (char *) sysCalloc(STRINGBUFFERSIZE, nameLength);
+
+ if (filename == NULL) {
+ fprintf(stderr, "ReadFromZip: Out of memory \n");
+ exit(1);
+ }
+
+ memcpy(filename, p + CENHDRSIZ, nameLength);
+
+
+ /* We have to calculate nextOffset now, because VerifyFile bashes
+ * str_buffer
+ */
+ nextOffset = offset + CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ReadFromZip: filename read %s\n", filename);
+
+ /* extract the .class from the filename */
+ if (nameLength > 6 &&
+ strcmp(filename + nameLength - 6, ".class") == 0) {
+ /* Verify the class file */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ReadFromZip: Extracted '.class' from %s\n", filename);
+
+ filename[nameLength-6] = 0;
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ReadFromZip: Verifying classfile %s\n", filename);
+
+ /* call VerifyFile to verify the class */
+ VerifyFile(filename);
+ } else {
+ /* Read and copy over the file to tmpdir */
+ /* p points at the central header for the file */
+ unsigned long compLen = CENSIZ(p); /* the compressed length */
+ unsigned long method = CENHOW(p); /* how it is stored */
+ unsigned long expectedCRC = CENCRC(p); /* expected CRC */
+ unsigned long actualCRC;
+
+ decompLen = CENLEN(p);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "READFROMZIP: Reading file [%s]...\n", filename);
+
+ /* Make sure file is not encrypted */
+ if ((CENFLG(p) & 1) == 1) {
+ jio_fprintf(stderr, "Entry is encrypted\n");
+ goto done;
+ }
+
+ jdstream =
+ (JAR_DataStreamPtr)sysMalloc(sizeof(JAR_DataStream) + decompLen);
+ decompData = (unsigned char *)(jdstream + 1);
+
+ if (/* Go to the beginning of the LOC header */
+ (fseek(file, entry->jar.locpos + CENOFF(p), SEEK_SET) < 0)
+ /* Read it */
+ || (fread(p, sizeof(char), LOCHDRSIZ, file) != LOCHDRSIZ)
+ /* Skip over name and extension, if any */
+ || (fseek(file, LOCNAM(p) + LOCEXT(p), SEEK_CUR) < 0)) {
+ goto done;
+ }
+
+ switch (method) {
+ case STORED:
+ if (compLen != decompLen) {
+ sysFree(jdstream);
+ jdstream = NULL;
+ goto done;
+ }
+ fread(decompData, sizeof(char), decompLen, file);
+ break;
+
+ case DEFLATED: {
+ bool_t inflateOK;
+ inflateOK = inflate(file, compLen, decompData, decompLen);
+
+ if (!inflateOK) {
+ sysFree(jdstream);
+ jdstream = NULL;
+ }
+ break;
+ }
+
+ default:
+ sysFree(jdstream);
+ jdstream = NULL;
+ break;
+ }
+
+ actualCRC = jarCRC32(decompData, decompLen);
+ if (actualCRC != expectedCRC) {
+ jio_fprintf(stderr, "Unexpected CRC value\n");
+ }
+
+ /* create the tempdir if it doesn't already exist */
+ {
+ char fname[1024]; /* file name restored from JAR */
+ char *dir;
+ char *q;
+ char *sfname = fname; /* system-specific file name */
+ char *dname = fname; /* destination file name */
+
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Reading filename [%s] from JAR \n", filename);
+
+ sprintf(fname, "%s%c%s", tmp_dir,
+ (char) LOCAL_DIR_SEPARATOR,
+ filename);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Before conversion: fname [%s] sfname [%s]\n",
+ fname, sfname);
+
+ /*
+ * convert JAR name to the system-specific file name
+ */
+
+ sfname = JARname2fname(fname, dname, strlen(fname)+1);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "After conversion: Converted [%s] to [%s]\n",
+ fname, sfname);
+
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Preparing to write file [%s]\n", sfname);
+
+ dir = strdup(sfname);
+ q = strrchr(dir, (char)LOCAL_DIR_SEPARATOR);
+ if (q) {
+ *q = 0;
+ ensure_tmpdir_exists(dir);
+ }
+ free(dir);
+
+
+ /* Attempt to stat or open only if this is NOT a directory */
+
+ if (!(sfname[strlen(sfname)-1] == (char)LOCAL_DIR_SEPARATOR)) {
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Attempting stat on dir [%s]\n", sfname);
+
+ status = stat(sfname, &stat_buf);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Status from stat of [%s] is %d\n", sfname, status);
+
+ /* Attempt to open only if the file does not already exist.
+ * This is indicated by the stat command returning -1.
+ * And this is not a directory.
+ */
+
+ if ((status < 0) || !(stat_buf.st_mode & S_IFDIR)) {
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Opening file [%s]\n", sfname);
+#ifdef UNIX
+ fd = open(sfname, O_WRONLY | O_CREAT | O_TRUNC , 0644);
+#endif
+
+#ifdef WIN32
+ fd = open(sfname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+#endif
+
+ if (fd < 0) {
+ panic("failed to open %s", sfname);
+ }
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Writing file [%s]...\n", sfname);
+
+ /* write the file to the tmpdir just created */
+ write(fd, decompData, decompLen);
+
+ /* check for the JAR Manifest.mf file */
+
+ if (isManifestfile(sfname, strlen(sfname))) {
+ /* save it for using it later to create
+ * the JAR file
+ */
+ memcpy(manifestfile, sfname + strlen(tmp_dir), strlen(sfname));
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "Saving JAR manifest file [%s]\n",
+ manifestfile);
+ }
+
+ close(fd);
+ }
+ }
+ }
+ if (jdstream != NULL) {
+ sysFree(jdstream);
+ jdstream = NULL;
+ }
+ }
+
+ /* Set offset to the next central header */
+ offset = nextOffset;
+ sysFree(filename);
+ filename = NULL;
+ }
+done:
+ if (file != NULL) {
+ fclose(file);
+ }
+
+ if (jdstream != NULL) {
+ jdstream->type = JAR_RESOURCE;
+ jdstream->data = decompData;
+ jdstream->dataLen = decompLen;
+ jdstream->dataIndex = 0;
+ jdstream->mode = JAR_READ;
+ }
+
+ if (filename != NULL)
+ sysFree(filename);
+}
+
+
+/*=========================================================================
+ * FUNCTION: remove_dir()
+ * TYPE: Handles removing files from recursive directories
+ * OVERVIEW: Internal function called by ProcessJARfile().
+ *
+ * This function reads a directory, searching for either another directory,
+ * or an individual class name that is to be removed using the remove()
+ * API call.
+ *
+ * INTERFACE:
+ * parameters: dirname name of the directory entry.
+ * pkgname name of the package
+ * returns: nothing
+ *=======================================================================*/
+static void remove_dir(char *dirname, char *pkgname)
+{
+ struct dirent *ent;
+ char buf[MAXPACKAGENAME];
+ char pkgbuf[MAXPACKAGENAME];
+ char tmpbuf[MAXPACKAGENAME];
+ char tmppkg[MAXPACKAGENAME];
+ char tmppkgbuf[MAXPACKAGENAME];
+ char *name = NULL;
+ DIR *dir = opendir(dirname);
+ int err = 0;
+ int status;
+
+ /* Initialize the buffers to 0 */
+ memset(buf, 0, sizeof(buf));
+ memset(pkgbuf, 0, sizeof(pkgbuf));
+ memset(tmpbuf, 0, sizeof(tmpbuf));
+ memset(tmppkg, 0, sizeof(tmppkg));
+ memset(tmppkgbuf, 0, sizeof(tmppkgbuf));
+
+ if (dir == NULL) {
+ fprintf(stderr, "Can't open dir %s\n", dirname);
+ exit(1);
+ }
+ for (ent = readdir(dir); ent; ent = readdir(dir)) {
+ struct stat stat_buf;
+ int len;
+ name = ent->d_name;
+
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+ continue;
+ }
+
+ strcpy(pkgbuf, pkgname);
+ if (pkgname[0] != 0) {
+ /* concatenate '/' to the package name */
+ sprintf(tmppkgbuf, "%s%c", pkgbuf, (char)LOCAL_DIR_SEPARATOR);
+ }
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "remove_dir: Reading filename [%s] from directory [%s]\n",
+ name, dirname);
+
+ /* we just have a class file that needs to be removed */
+
+ len = strlen(name);
+
+ /* append the dirname and name */
+ strcpy(buf, dirname);
+ strcat(buf, name);
+
+
+ status = stat(buf, &stat_buf);
+
+ if ((status == 0) && !(stat_buf.st_mode & S_IFDIR)) {
+ /* remove if this is a file and not a directory */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "remove_dir: Removing file [%s] \n", buf);
+
+ err = remove(buf);
+
+ if (JAR_DEBUG && verbose) {
+ jio_fprintf(stderr,
+ "remove_dir: remove() returned error %d\n", err);
+ }
+
+ } else {
+ strcat(tmppkgbuf, name);
+ stat(buf, &stat_buf);
+ len = strlen(buf);
+
+ if (stat_buf.st_mode & S_IFDIR) {
+ /* handle the recursive directory found */
+
+ sprintf(tmpbuf, "%s%c", buf, (char)LOCAL_DIR_SEPARATOR);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "remove_dir: Recursive dir, calling remove_dir [%s,%s]\n",
+ tmpbuf, tmppkgbuf);
+ remove_dir(tmpbuf, tmppkgbuf);
+ continue;
+ }
+ }
+
+ }
+
+ /* close the directory to free the dirp first */
+ closedir(dir);
+
+
+#ifdef WIN32
+ /* remove the trailing '\' from the directory */
+ {
+ int tmppkglen = strlen(dirname);
+ dirname[tmppkglen-1] = '\0';
+ }
+#endif
+
+ /* Remove the directory by calling rmdir() or remove() API as appropriate */
+
+ sprintf(tmppkg,"%s", dirname);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "remove_dir: Removing [%s]\n", tmppkg);
+
+#ifdef WIN32
+ err = rmdir(tmppkg);
+
+ if (JAR_DEBUG && verbose) {
+ if (err != 0) {
+ jio_fprintf(stderr,
+ "remove_dir: rmdir(%s) failed with error %d\n",
+ tmppkg, err);
+ }
+ }
+#endif
+
+#ifdef UNIX
+ err = remove (tmppkg);
+
+ if (JAR_DEBUG && verbose) {
+ if (err != 0) {
+ jio_fprintf(stderr,
+ "remove_dir: remove(%s) failed with error %d\n",
+ tmppkg, err);
+ }
+ }
+#endif
+
+}
+/*=========================================================================
+ * FUNCTION: ProcessJARfile()
+ * TYPE: Processes ZIP file entries
+ * OVERVIEW: Internal function called by ProcessInputs().
+ *
+ * This function processes a JAR file by first creating a zip entry for
+ * reading JAR directories, then calls ReadFromZip() to read the Zip
+ * class names and verifies them. It finally creates a new JAR file and
+ * places all the verified classes into it.
+ * It returns a boolean type to indicate if a valid JAR file was found
+ * and the contents of the JAR file were processed without errors.
+ *
+ * INTERFACE:
+ * parameters: buf: JAR file name.
+ * len: size of the file
+ * returns: boolean type
+ *=======================================================================*/
+bool_t ProcessJARfile(char *buf, int len) {
+
+ zip_t *zipEntry;
+ struct stat stat_buf;
+ char *fname = NULL;
+ char *buffer = NULL;
+ char *jarName = NULL;
+ char dirdelim = '\0'; /* directory delimiter */
+ int err = 0;
+ int tmpdir_len = 0;
+ int statcode;
+ char tmpdir_buf[MAXPACKAGENAME];
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ProcessJARfile: JAR file [%s] Size [%d]\n", buf, len);
+
+ statcode = stat(buf, &stat_buf);
+
+ /* Create the zip entry for searching the JAR directories.
+ * If the zip entry is NULL, it would indicate that we ran
+ * out of memory and would have exited already.
+ */
+
+ zipEntry = getZipEntry (buf, len);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "Searching for JAR directories...\n");
+
+
+ /* search for the JAR directories */
+ if (findJARDirectories(zipEntry, &stat_buf)) {
+ /* the JAR directories were found */
+
+ JARfile = TRUE;
+ zipFileName = buf;
+ if (JAR_DEBUG && verbose) {
+ jio_fprintf(stderr,
+ "ProcessJARfile: JAR directory [%s] found \n",
+ zipEntry->name);
+ }
+
+ zipEntry->type = 'j';
+
+ /* Read and Verify the classes from the ZIP file */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "ProcessJARfile: Verifying Zip class names...\n");
+
+ pushJarFileOntoClassPath(zipEntry);
+
+ ReadFromZip(zipEntry);
+
+ popClassPath();
+
+ /* Ensure that the output_dir also exists or create it if it
+ * does not already exist
+ */
+
+ if (output_dir != NULL) {
+ char *dir = strdup(output_dir);
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "ProcessJARfile: Checking if output [%s] exists\n",
+ output_dir);
+ ensure_dir_exists(dir);
+ ensure_dir_writable(dir);
+ free(dir);
+ }
+
+ /* Create a JAR file only if the input parameter was a JAR file,
+ * the tmp_dir was created with classes verified and an output
+ * dir also exists.
+ */
+
+ if (JARfile && tmpDirExists && tmp_dir && output_dir) {
+ const char *p;
+
+ /* Allocate enough space to hold the JAR name */
+ jarName = (char *)sysCalloc(len+32, len);
+
+ if (jarName == NULL) {
+ fprintf(stderr, "ProcessJARfile: Out of memory");
+ exit(1);
+ }
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "ProcessJARfile: Creating JAR file of verified classes...\n");
+ /* search for the last '/' to get the actual JAR file name */
+ for (p = buf+len; ;) {
+ --p;
+
+ if (*p == '/' || *p == '\\') {
+ dirdelim = *p;
+ memcpy(jarName, p+1, (len-1)-(p-buf));
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "ProcessJARfile: JAR file [%s]\n", jarName);
+ break;
+ }
+ if (p == buf) {
+ /* no directories in path, get the individual JAR name */
+ strncpy(jarName, buf, len);
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "ProcessJARfile: JAR filename [%s]\n", jarName);
+ break;
+ }
+ }
+
+ /* move the verified classes into a JAR file */
+
+ /* Be sure to allocate enough space to hold the sprintfs below */
+ fname = (char *)malloc(strlen(output_dir)+ len+32);
+
+ if (fname == NULL) {
+ fprintf(stderr, "ProcessJARfile: Out of memory");
+ exit(1);
+ }
+
+ if (dirdelim != '\0') {
+ sprintf(fname, "%s%c%s", output_dir,
+ dirdelim, jarName);
+ } else {
+ sprintf(fname, "%s%c%s", output_dir,
+ (char)LOCAL_DIR_SEPARATOR, jarName);
+ }
+
+ /* Be sure to allocate enough space to hold the sprintfs below */
+ /* The size here must be adjusted anytime the buffer used in the
+ * sprintfs is extended.
+ */
+
+ buffer = (char *)malloc(strlen(output_dir)+strlen(fname) +
+ strlen(tmp_dir) + strlen(manifestfile) +
+ strlen(tmp_dir) + 51);
+ if (buffer == NULL) {
+ fprintf(stderr, "ProcessJARfile: Out of memory");
+ exit(1);
+ }
+
+ if (verbose) {
+ if (isManifestfile(manifestfile, strlen(manifestfile))) {
+ /* use existing manifest if one exists */
+ sprintf(buffer, "jar -cvfm \"%s\" %s%c%s -C %s .",
+ fname, tmp_dir,
+ (char)LOCAL_DIR_SEPARATOR,
+ manifestfile, tmp_dir);
+
+ } else {
+
+ sprintf(buffer, "jar -cvfM \"%s\" -C %s .",
+ fname, tmp_dir);
+
+ }
+ } else {
+ /* Run jar in non-verbose mode, and log errors in a file */
+
+ if (isManifestfile(manifestfile, strlen(manifestfile))) {
+ /* use existing manifest if one exists */
+
+#ifdef UNIX
+ /* create JAR with existing manifest file */
+ /* Redirect errors and stdout to jarlog.txt */
+ sprintf(buffer,
+ "sh -c \"jar -cfm \\\"%s\\\" %s%c%s -C %s .\" > \"%s%c\"%s",
+ fname, tmp_dir, (char)LOCAL_DIR_SEPARATOR,
+ manifestfile, tmp_dir, output_dir,
+ (char)LOCAL_DIR_SEPARATOR,"jarlog.txt 2>&1");
+
+#else
+ sprintf(buffer,
+ "jar -cfm \"%s\" %s%c%s -C %s . ",
+ fname, tmp_dir, (char)LOCAL_DIR_SEPARATOR,
+ manifestfile, tmp_dir);
+#endif
+ } else {
+#ifdef UNIX
+ /* create JAR with no manifest since none exists */
+ /* Redirect errors and stdout to jarlog.txt */
+ sprintf(buffer,
+ "sh -c \"jar -cfM \\\"%s\\\" -C %s .\" > \"%s%c\"%s",
+ fname, tmp_dir, output_dir,
+ (char)LOCAL_DIR_SEPARATOR,"jarlog.txt 2>&1");
+#else
+ sprintf(buffer,
+ "jar -cfM \"%s\" -C %s . ",
+ fname, tmp_dir);
+#endif
+
+ }
+ }
+ if (verbose) {
+ jio_fprintf(stderr, "Executing command [%s]\n", buffer);
+ }
+
+#ifdef WIN32
+ /* system() function does not return the exit code of the child
+ * process under Windows98.
+ * The documentation states:
+ * "If command is not NULL, system returns the value that is
+ * returned by the command interpreter.".
+ * Thus it is probably a bug within 'command.com'.
+ * Note that _spawnlp correctly returns the exit status of the
+ * new process.
+ */
+ if (verbose) {
+ err = _spawnlp(_P_WAIT, "jar", "jar", buffer+4, NULL);
+ if (err != 0) {
+ fprintf(stderr, "%s\n", buffer);
+ perror("Error");
+ }
+ } else {
+ int cstderr;
+ int cstdout;
+ FILE *logfile;
+
+ /* Save stderr and stdout*/
+ if ((cstderr = dup(_fileno(stderr))) == -1) {
+ fprintf(stderr, "Cannot copy dup stderr\n");
+ }
+ if ((cstdout = dup(_fileno(stdout))) == -1) {
+ fprintf(stderr, "Cannot copy dup stdout\n");
+ }
+
+ sprintf(tmpdir_buf, "%s\\%s", output_dir, "jarlog.txt");
+ if ((logfile = fopen(tmpdir_buf, "w")) == NULL) {
+ fprintf(stderr, "Cannot create output file\n");
+ exit(1);
+ }
+
+ if (_dup2(_fileno(logfile), _fileno(stderr)) == -1) {
+ fprintf(stderr, "dup2 failed for stderr\n");
+ exit(1);
+ }
+
+ if (_dup2(_fileno(logfile), _fileno(stdout)) == -1) {
+ fprintf(stderr, "dup2 failed for stdout\n");
+ exit(1);
+ }
+
+ err = _spawnlp(_P_WAIT, "jar", "jar", buffer+4, NULL);
+ if (err != 0) {
+ fprintf(stderr, "%s\n", buffer);
+ perror("Error");
+ }
+
+ fflush(stderr);
+ fflush(stdout);
+ fclose(logfile);
+
+ /* Restore stderr and stdout */
+ _dup2(cstderr, _fileno(stderr));
+ _dup2(cstdout, _fileno(stdout));
+
+ memset(tmpdir_buf,0,sizeof(tmpdir_buf));
+ }
+#else
+ err = system(buffer);
+#endif
+
+ if (err != 0) {
+ /* jar file creation failed - return back the error */
+ fprintf(stderr, "JAR file creation failed with error %d\n", err);
+ if (!verbose)
+ fprintf(stderr,
+"The preverified classes if any are in %s. See jar log of errors in %s%c%s \n",
+ tmp_dir, output_dir, (char)LOCAL_DIR_SEPARATOR, "jarlog.txt");
+ } else {
+ if (!verbose) {
+ /* remove the jar log file if no error occurred */
+ char *jarfn = NULL;
+ int error;
+
+ jarfn = (char *)malloc(strlen(output_dir)+10+1+1);
+
+ if (jarfn == NULL) {
+ fprintf(stderr, "ProcessJARfile: Out of memory");
+ exit(1);
+ }
+
+ sprintf(jarfn, "%s%c%s", output_dir,
+ (char)LOCAL_DIR_SEPARATOR, "jarlog.txt");
+ error = remove(jarfn); /* remove the file */
+
+ if (jarfn != NULL)
+ sysFree(jarfn);
+ }
+
+ /* prepare to remove the tmp directory */
+ /* copy the tmp directory name to a buffer */
+ strcpy(tmpdir_buf, tmp_dir);
+ tmpdir_len = strlen(tmp_dir);
+
+ /* Append dir separator if it does not yet exist */
+ if (tmpdir_buf[tmpdir_len - 1] != LOCAL_DIR_SEPARATOR &&
+ tmpdir_buf[tmpdir_len - 1] != DIR_SEPARATOR) {
+ tmpdir_buf[tmpdir_len] = LOCAL_DIR_SEPARATOR;
+ tmpdir_buf[tmpdir_len + 1] = 0;
+ }
+
+ /* remove the tmp_dir and all its contents recursively */
+ remove_dir(tmpdir_buf, "");
+ } /* jar creation returned no error */
+ }
+ } else {
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "JAR directories not found for JAR file [%s]\n", buf);
+ if (fname != NULL)
+ sysFree(fname);
+ if (zipEntry != NULL)
+ sysFree(zipEntry);
+
+ return FALSE; /* could not locate JAR directories - invalid JAR file */
+ }
+
+ if (fname != NULL)
+ sysFree(fname);
+
+ if (zipEntry != NULL)
+ sysFree(zipEntry);
+
+ if (buffer != NULL)
+ sysFree(buffer);
+
+ if (jarName != NULL)
+ sysFree(jarName);
+
+ if ( err!=0 ) {
+ exit(errorCode = 1);
+ }
+
+ return JARfile;
+}
diff --git a/MPC.3.5.LINUX/preverifier/jarint.h b/MPC.3.5.LINUX/preverifier/jarint.h
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of Sun
+ * Microsystems, Inc. ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Sun.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
+ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
+ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: KVM
+ * SUBSYSTEM: JAR file reader.
+ * FILE: jarint.h
+ * OVERVIEW: Internal declarations for JAR file reader. This file should
+ * be included only by files in the core KVM.
+ * AUTHOR: Ioi Lam.
+ *=======================================================================*/
+
+#ifndef _JAR_INT_H_
+#define _JAR_INT_H_
+
+/*
+ * indicates whether JAR inflater uses standard i/o during decompression
+ */
+#define JAR_INFLATER_USES_STDIO 1
+
+/*
+ * The HuffmanCodeTable structure contains the dynamic huffman codes for
+ * the Code Length Codes or the Distance Codes. The structure is
+ * dynamically allocated. We just allocate enough space to contain all
+ * possible codes.
+ */
+
+typedef struct HuffmanCodeTableHeader {
+ unsigned short quickBits; /* quick bit size */
+ unsigned short maxCodeLen; /* Max number of bits in any code */
+} HuffmanCodeTableHeader;
+
+
+/* If this bit is set in a huffman entry, it means that this is not
+ * really an entry, but a pointer into the long codes table.
+ * The remaining 15 bits is the offset (in bytes) from the table header
+ * to first "long" entry representing this item.
+ */
+
+#define HUFFINFO_LONG_MASK 0x8000 /* high bit set */
+
+#define MAX_QUICK_CXD 6
+#define MAX_QUICK_LXL 9
+
+/* For debugging, the following can be set to the name of a file (in quotes).
+ * If we are decompressing something that is the exact same length as that
+ * file, this will check to make sure that the decompressed bytes look
+ * exactly the same as the bytes in the specified file.
+ * java/lang/String.class is a particularly useful file to try.
+ *
+ */
+
+#ifndef inflateVerbose
+#define inflateVerbose 0
+#endif
+
+#if INCLUDEDEBUGCODE
+ static void ziperr(const char * msg);
+# define ASSERT(x) assert((x))
+#else
+# define ziperr(msg)
+# define ASSERT(x) (void)0
+#endif
+
+
+/* A normal sized huffman code table with a 9-bit quick bit */
+typedef struct HuffmanCodeTable {
+ struct HuffmanCodeTableHeader h;
+ /* There are 1 << quickBit entries. 512 is just an example.
+ * For each entry:
+ * If the high bit is 0:
+ * Next 11 bits give the character
+ * Low 4 bits give the actual number of bits used
+ * If the high bit is 1:
+ * Next 15 bits give the offset (in bytes) from the header to
+ * the first long entry dealing with this long code.
+ */
+ unsigned short entries[512];
+} HuffmanCodeTable;
+
+
+/* A small sized huffman code table with a 9-bit quick bit. We have
+ * this so that we can initialize fixedHuffmanDistanceTable in jartables.h
+ */
+typedef struct shortHuffmanCodeTable {
+ struct HuffmanCodeTableHeader h;
+ unsigned short entries[32];
+} shortHuffmanCodeTable;
+
+
+typedef struct inflaterState {
+ /* The input stream */
+ JarCompressedType inFile;
+
+ int inRemaining; /* Number of bytes left that we can read */
+ unsigned int inDataSize; /* Number of good bits in inData */
+ unsigned long inData; /* Low inDataSize bits are from stream.
+ * High unused bits must be zero
+ */
+ /* The output stream */
+ unsigned char *out; /* Current output position */
+ unsigned char *outStart; /* Start and end of output buffer */
+ unsigned char *outEnd;
+#ifdef JAR_DEBUG_FILE
+ unsigned char *jarDebugBytes;
+#endif
+} inflaterState;
+
+
+/*=========================================================================
+ * Macros used internally
+ *=======================================================================*/
+
+/* Call this macro to make sure that we have at least "j" bits of
+ * input available
+ */
+
+#define NEEDBITS(j) { \
+ while (inDataSize < (j)) { \
+ inData |= ((unsigned long)NEXTBYTE) << inDataSize; \
+ inRemaining--; inDataSize += 8; \
+ } \
+ ASSERT(inDataSize <= 32); \
+}
+
+
+/* Return (without consuming) the next "j" bits of the input */
+#define NEXTBITS(j) \
+ (ASSERT((j) <= inDataSize), inData & ((1 << (j)) - 1))
+
+/* Consume (quietly) "j" bits of input, and make them no longer available
+ * to the user
+ */
+#define DUMPBITS(j) { \
+ ASSERT((j) <= inDataSize); \
+ inData >>= (j); \
+ inDataSize -= (j); \
+ }
+
+/* Read bits from the input stream and decode it using the specified
+ * table. The resulting decoded character is placed into "result".
+ * If there is a problem, we goto "errorLabel"
+ *
+ * For speed, we assume that quickBits = table->h.quickBits and that
+ * it has been cached into a variable.
+ */
+
+
+#define GET_HUFFMAN_ENTRY(table, quickBits, result, errorLabel) { \
+ unsigned int huff = table->entries[NEXTBITS(quickBits)]; \
+ if (huff & HUFFINFO_LONG_MASK) { \
+ long delta = (huff & ~HUFFINFO_LONG_MASK); \
+ unsigned short *table2 = (unsigned short *)((char *)table + delta); \
+ huff = table2[NEXTBITS(table->h.maxCodeLen) >> quickBits]; \
+ } \
+ if (huff == 0) { goto errorLabel; } \
+ DUMPBITS(huff & 0xF); \
+ result = huff >> 4; \
+ }
+
+
+#if JAR_INFLATER_USES_STDIO
+# define LOAD_INFILE_IF_NECESSARY
+# define STORE_INFILE_IF_NECESSARY
+# define INITIALIZE_INFILE_IF_NECESSARY = state->inFile
+# define NEXTBYTE fgetc(inFile)
+# define COPY_N_BYTES(buffer, n) (fread(buffer, 1, n, inFile) == n)
+
+#else
+# define LOAD_INFILE_IF_NECESSARY inFile = state->inFile;
+# define STORE_INFILE_IF_NECESSARY state->inFile = inFile;
+# define INITIALIZE_INFILE_IF_NECESSARY
+# define NEXTBYTE (*inFile++)
+# define COPY_N_BYTES(buffer, n) \
+ (memcpy(buffer, inFile, n), inFile += n, TRUE)
+#endif
+
+
+/* Copy values from the inflaterState structure to local variables */
+#define LOAD_IN \
+ LOAD_INFILE_IF_NECESSARY \
+ inData = state->inData; \
+ inDataSize = state->inDataSize; \
+ inRemaining = state->inRemaining;
+
+
+/* Copy values from local variables back to the inflaterState structure */
+#define STORE_IN \
+ STORE_INFILE_IF_NECESSARY \
+ state->inData = inData; \
+ state->inDataSize = inDataSize; \
+ state->inRemaining = inRemaining;
+
+
+#define DECLARE_IN_VARIABLES \
+ register JarCompressedType inFile INITIALIZE_INFILE_IF_NECESSARY; \
+ register unsigned long inData; \
+ register unsigned int inDataSize; \
+ register long inRemaining; \
+
+#define LOAD_OUT out = state->out;
+
+#define STORE_OUT state->out = out;
+
+#define DECLARE_OUT_VARIABLES \
+ register unsigned char *out;
+
+#endif /* JAR_INT_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/jartables.h b/MPC.3.5.LINUX/preverifier/jartables.h
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of Sun
+ * Microsystems, Inc. ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Sun.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
+ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
+ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+ * THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: KVM
+ * SUBSYSTEM: JAR file reader.
+ * FILE: jartables.h
+ * OVERVIEW: Public header file for the JAR file reader tables.
+ * AUTHOR: Ioi Lam
+ * Tasneem Sayeed
+ *=========================================================================*/
+
+#ifndef _KJARTABLES_H_
+#define _KJARTABLES_H_
+
+static const unsigned char ll_extra_bits[] = {
+ /* 257 */ 0, /* 3 */
+ /* 258 */ 0, /* 4 */
+ /* 259 */ 0, /* 5 */
+ /* 260 */ 0, /* 6 */
+ /* 261 */ 0, /* 7 */
+ /* 262 */ 0, /* 8 */
+ /* 263 */ 0, /* 9 */
+ /* 264 */ 0, /* 10 */
+ /* 265 */ 1, /* 11,12 */
+ /* 266 */ 1, /* 13,14 */
+
+ /* 267 */ 1, /* 15,16 */
+ /* 268 */ 1, /* 17,18 */
+ /* 269 */ 2, /* 19-22 */
+ /* 270 */ 2, /* 23-26 */
+ /* 271 */ 2, /* 27-30 */
+ /* 272 */ 2, /* 31-34 */
+ /* 273 */ 3, /* 35-42 */
+ /* 274 */ 3, /* 43-50 */
+ /* 275 */ 3, /* 51-58 */
+ /* 276 */ 3, /* 59-66 */
+
+ /* 277 */ 4, /* 67-82 */
+ /* 278 */ 4, /* 83-98 */
+ /* 279 */ 4, /* 99-114 */
+ /* 280 */ 4, /* 115-130 */
+ /* 281 */ 5, /* 131-162 */
+ /* 282 */ 5, /* 163-194 */
+ /* 283 */ 5, /* 195-226 */
+ /* 284 */ 5, /* 227-257 */
+ /* 285 */ 0, /* 258 */
+};
+
+#define MAX_ZIP_EXTRA_LENGTH_BITS 5
+
+static const unsigned short ll_length_base[] = {
+ /* 257 0 */ 3,
+ /* 258 0 */ 4,
+ /* 259 0 */ 5,
+ /* 260 0 */ 6,
+ /* 261 0 */ 7,
+ /* 262 0 */ 8,
+ /* 263 0 */ 9,
+ /* 264 0 */ 10,
+ /* 265 1 */ 11, /* - 12 */
+ /* 266 1 */ 13, /* - 14 */
+
+ /* 267 1 */ 15, /* - 16 */
+ /* 268 1 */ 17, /* - 18 */
+ /* 269 2 */ 19, /* - 22 */
+ /* 270 2 */ 23, /* - 26 */
+ /* 271 2 */ 27, /* - 30 */
+ /* 272 2 */ 31, /* - 34 */
+ /* 273 3 */ 35, /* - 42 */
+ /* 274 3 */ 43, /* - 50 */
+ /* 275 3 */ 51, /* - 58 */
+ /* 276 3 */ 59, /* - 66 */
+
+ /* 277 4 */ 67, /* - 82 */
+ /* 278 4 */ 83, /* - 98 */
+ /* 279 4 */ 99, /* - 114 */
+ /* 280 4 */ 115, /* - 130 */
+ /* 281 5 */ 131, /* - 162 */
+ /* 282 5 */ 163, /* - 194 */
+ /* 283 5 */ 195, /* - 226 */
+ /* 284 5 */ 227, /* - 257 */
+ /* 285 0 */ 258
+};
+
+
+static const unsigned char dist_extra_bits[] = {
+ /* 0 */ 0, /* 1 */
+ /* 1 */ 0, /* 2 */
+ /* 2 */ 0, /* 3 */
+ /* 3 */ 0, /* 4 */
+ /* 4 */ 1, /* 5,6 */
+ /* 5 */ 1, /* 7,8 */
+ /* 6 */ 2, /* 9-12 */
+ /* 7 */ 2, /* 13-16 */
+ /* 8 */ 3, /* 17-24 */
+ /* 9 */ 3, /* 25-32 */
+
+ /* 10 */ 4, /* 33-48 */
+ /* 11 */ 4, /* 49-64 */
+ /* 12 */ 5, /* 65-96 */
+ /* 13 */ 5, /* 97-128 */
+ /* 14 */ 6, /* 129-192 */
+ /* 15 */ 6, /* 193-256 */
+ /* 16 */ 7, /* 257-384 */
+ /* 17 */ 7, /* 385-512 */
+ /* 18 */ 8, /* 513-768 */
+ /* 19 */ 8, /* 769-1024 */
+
+ /* 20 */ 9, /* 1025-1536 */
+ /* 21 */ 9, /* 1537-2048 */
+ /* 22 */ 10, /* 2049-3072 */
+ /* 23 */ 10, /* 3073-4096 */
+ /* 24 */ 11, /* 4097-6144 */
+ /* 25 */ 11, /* 6145-8192 */
+ /* 26 */ 12, /* 8193-12288 */
+ /* 27 */ 12, /* 12289-16384 */
+ /* 28 */ 13, /* 16385-24576 */
+ /* 29 */ 13, /* 24577-32768 */
+};
+
+#define MAX_ZIP_EXTRA_DISTANCE_BITS 13
+#define MAX_ZIP_DISTANCE_CODE 29
+
+static const unsigned int dist_base[] = {
+ /* 0 0 */ 1,
+ /* 1 0 */ 2,
+ /* 2 0 */ 3,
+ /* 3 0 */ 4,
+ /* 4 1 */ 5, /* -6 */
+ /* 5 1 */ 7, /* -8 */
+ /* 6 2 */ 9, /* -12 */
+ /* 7 2 */ 13, /* -16 */
+ /* 8 3 */ 17, /* -24 */
+ /* 9 3 */ 25, /* -32 */
+
+ /* 10 4 */ 33, /* -48 */
+ /* 11 4 */ 49, /* -64 */
+ /* 12 5 */ 65, /* -96 */
+ /* 13 5 */ 97, /* -128 */
+ /* 14 6 */ 129, /* -192 */
+ /* 15 6 */ 193, /* -256 */
+ /* 16 7 */ 257, /* -384 */
+ /* 17 7 */ 385, /* -512 */
+ /* 18 8 */ 513, /* -768 */
+ /* 19 8 */ 769, /* -1024 */
+ /* 20 9 */ 1025, /* -1536 */
+ /* 21 9 */ 1537, /* -2048 */
+ /* 22 10 */ 2049, /* -3072 */
+ /* 23 10 */ 3073, /* -4096 */
+ /* 24 11 */ 4097, /* -6144 */
+ /* 25 11 */ 6145, /* -8192 */
+ /* 26 12 */ 8193, /* -12288 */
+ /* 27 12 */ 12289, /* -16384 */
+ /* 28 13 */ 16385, /* -24576 */
+ /* 29 13 */ 24577, /* -32768 */
+};
+
+
+/*
+ * The order in which the code lengths of the Code Length Alphabet is
+ * given. See section 3.2.7 of RFC 1951.
+ */
+
+static const char ccode_idx[] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+};
+
+/* A table for reversing 5 bits in a binary number */
+
+static const unsigned char reverse5[] = {
+ 0x0, 0x10, 0x8, 0x18, 0x4, 0x14, 0xc, 0x1c,
+ 0x2, 0x12, 0xa, 0x1a, 0x6, 0x16, 0xe, 0x1e,
+ 0x1, 0x11, 0x9, 0x19, 0x5, 0x15, 0xd, 0x1d,
+ 0x3, 0x13, 0xb, 0x1b, 0x7, 0x17, 0xf, 0x1f
+};
+
+#define REVERSE_5BITS(code) reverse5[code]
+#define REVERSE_9BITS(code) \
+ ((reverse5[((code) & 0x1F)] << 4) | reverse5[(code) >> 4])
+#define REVERSE_15BITS(code) \
+ ( (reverse5[code & 0x1F] << 10) | (reverse5[((code) >> 5) & 0x1F] << 5) \
+ | (reverse5[code >> 10]) )
+
+
+#define HUFFMAN_ENTRY(char, bits) ((char << 4) + bits)
+
+
+#ifdef USE_FIXED_HUFFMAN_CODE_TABLES
+
+/* The following tables are currently used, but they can be in
+ * releases that care for speed rather that size.
+ *
+ * "Fixed Huffman" can use the following tables, rather than doing the
+ * complicated calculations that it does.
+ */
+
+
+static const struct HuffmanCodeTable fixedHuffmanCodeTable = {
+ {
+ 7, /* min code length */
+ 9, /* max code length */
+ },
+ {
+ HUFFMAN_ENTRY(0x100, 7),
+ HUFFMAN_ENTRY('P', 8),
+ HUFFMAN_ENTRY(0x010, 8),
+ HUFFMAN_ENTRY(0x118, 8),
+ HUFFMAN_ENTRY(0x110, 7),
+ HUFFMAN_ENTRY('p', 8),
+ HUFFMAN_ENTRY('0', 8),
+ HUFFMAN_ENTRY(0x0c0, 9),
+ HUFFMAN_ENTRY(0x108, 7),
+ HUFFMAN_ENTRY('`', 8),
+ HUFFMAN_ENTRY(' ', 8),
+ HUFFMAN_ENTRY(0x0a0, 9),
+ HUFFMAN_ENTRY(0x000, 8),
+ HUFFMAN_ENTRY(0x080, 8),
+ HUFFMAN_ENTRY('@', 8),
+ HUFFMAN_ENTRY(0x0e0, 9),
+ HUFFMAN_ENTRY(0x104, 7),
+ HUFFMAN_ENTRY('X', 8),
+ HUFFMAN_ENTRY(0x018, 8),
+ HUFFMAN_ENTRY(0x090, 9),
+ HUFFMAN_ENTRY(0x114, 7),
+ HUFFMAN_ENTRY('x', 8),
+ HUFFMAN_ENTRY('8', 8),
+ HUFFMAN_ENTRY(0x0d0, 9),
+ HUFFMAN_ENTRY(0x10c, 7),
+ HUFFMAN_ENTRY('h', 8),
+ HUFFMAN_ENTRY('(', 8),
+ HUFFMAN_ENTRY(0x0b0, 9),
+ HUFFMAN_ENTRY(0x008, 8),
+ HUFFMAN_ENTRY(0x088, 8),
+ HUFFMAN_ENTRY('H', 8),
+ HUFFMAN_ENTRY(0x0f0, 9),
+ HUFFMAN_ENTRY(0x102, 7),
+ HUFFMAN_ENTRY('T', 8),
+ HUFFMAN_ENTRY(0x014, 8),
+ HUFFMAN_ENTRY(0x11c, 8),
+ HUFFMAN_ENTRY(0x112, 7),
+ HUFFMAN_ENTRY('t', 8),
+ HUFFMAN_ENTRY('4', 8),
+ HUFFMAN_ENTRY(0x0c8, 9),
+ HUFFMAN_ENTRY(0x10a, 7),
+ HUFFMAN_ENTRY('d', 8),
+ HUFFMAN_ENTRY('$', 8),
+ HUFFMAN_ENTRY(0x0a8, 9),
+ HUFFMAN_ENTRY(0x004, 8),
+ HUFFMAN_ENTRY(0x084, 8),
+ HUFFMAN_ENTRY('D', 8),
+ HUFFMAN_ENTRY(0x0e8, 9),
+ HUFFMAN_ENTRY(0x106, 7),
+ HUFFMAN_ENTRY('\\', 8),
+ HUFFMAN_ENTRY(0x01c, 8),
+ HUFFMAN_ENTRY(0x098, 9),
+ HUFFMAN_ENTRY(0x116, 7),
+ HUFFMAN_ENTRY('|', 8),
+ HUFFMAN_ENTRY('<', 8),
+ HUFFMAN_ENTRY(0x0d8, 9),
+ HUFFMAN_ENTRY(0x10e, 7),
+ HUFFMAN_ENTRY('l', 8),
+ HUFFMAN_ENTRY(',', 8),
+ HUFFMAN_ENTRY(0x0b8, 9),
+ HUFFMAN_ENTRY(0x00c, 8),
+ HUFFMAN_ENTRY(0x08c, 8),
+ HUFFMAN_ENTRY('L', 8),
+ HUFFMAN_ENTRY(0x0f8, 9),
+ HUFFMAN_ENTRY(0x101, 7),
+ HUFFMAN_ENTRY('R', 8),
+ HUFFMAN_ENTRY(0x012, 8),
+ HUFFMAN_ENTRY(0x11a, 8),
+ HUFFMAN_ENTRY(0x111, 7),
+ HUFFMAN_ENTRY('r', 8),
+ HUFFMAN_ENTRY('2', 8),
+ HUFFMAN_ENTRY(0x0c4, 9),
+ HUFFMAN_ENTRY(0x109, 7),
+ HUFFMAN_ENTRY('b', 8),
+ HUFFMAN_ENTRY('"', 8),
+ HUFFMAN_ENTRY(0x0a4, 9),
+ HUFFMAN_ENTRY(0x002, 8),
+ HUFFMAN_ENTRY(0x082, 8),
+ HUFFMAN_ENTRY('B', 8),
+ HUFFMAN_ENTRY(0x0e4, 9),
+ HUFFMAN_ENTRY(0x105, 7),
+ HUFFMAN_ENTRY('Z', 8),
+ HUFFMAN_ENTRY(0x01a, 8),
+ HUFFMAN_ENTRY(0x094, 9),
+ HUFFMAN_ENTRY(0x115, 7),
+ HUFFMAN_ENTRY('z', 8),
+ HUFFMAN_ENTRY(':', 8),
+ HUFFMAN_ENTRY(0x0d4, 9),
+ HUFFMAN_ENTRY(0x10d, 7),
+ HUFFMAN_ENTRY('j', 8),
+ HUFFMAN_ENTRY('*', 8),
+ HUFFMAN_ENTRY(0x0b4, 9),
+ HUFFMAN_ENTRY(0x00a, 8),
+ HUFFMAN_ENTRY(0x08a, 8),
+ HUFFMAN_ENTRY('J', 8),
+ HUFFMAN_ENTRY(0x0f4, 9),
+ HUFFMAN_ENTRY(0x103, 7),
+ HUFFMAN_ENTRY('V', 8),
+ HUFFMAN_ENTRY(0x016, 8),
+ HUFFMAN_ENTRY(0x11e, 8),
+ HUFFMAN_ENTRY(0x113, 7),
+ HUFFMAN_ENTRY('v', 8),
+ HUFFMAN_ENTRY('6', 8),
+ HUFFMAN_ENTRY(0x0cc, 9),
+ HUFFMAN_ENTRY(0x10b, 7),
+ HUFFMAN_ENTRY('f', 8),
+ HUFFMAN_ENTRY('&', 8),
+ HUFFMAN_ENTRY(0x0ac, 9),
+ HUFFMAN_ENTRY(0x006, 8),
+ HUFFMAN_ENTRY(0x086, 8),
+ HUFFMAN_ENTRY('F', 8),
+ HUFFMAN_ENTRY(0x0ec, 9),
+ HUFFMAN_ENTRY(0x107, 7),
+ HUFFMAN_ENTRY('^', 8),
+ HUFFMAN_ENTRY(0x01e, 8),
+ HUFFMAN_ENTRY(0x09c, 9),
+ HUFFMAN_ENTRY(0x117, 7),
+ HUFFMAN_ENTRY('~', 8),
+ HUFFMAN_ENTRY('>', 8),
+ HUFFMAN_ENTRY(0x0dc, 9),
+ HUFFMAN_ENTRY(0x10f, 7),
+ HUFFMAN_ENTRY('n', 8),
+ HUFFMAN_ENTRY('.', 8),
+ HUFFMAN_ENTRY(0x0bc, 9),
+ HUFFMAN_ENTRY(0x00e, 8),
+ HUFFMAN_ENTRY(0x08e, 8),
+ HUFFMAN_ENTRY('N', 8),
+ HUFFMAN_ENTRY(0x0fc, 9),
+ HUFFMAN_ENTRY(0x100, 7),
+ HUFFMAN_ENTRY('Q', 8),
+ HUFFMAN_ENTRY(0x011, 8),
+ HUFFMAN_ENTRY(0x119, 8),
+ HUFFMAN_ENTRY(0x110, 7),
+ HUFFMAN_ENTRY('q', 8),
+ HUFFMAN_ENTRY('1', 8),
+ HUFFMAN_ENTRY(0x0c2, 9),
+ HUFFMAN_ENTRY(0x108, 7),
+ HUFFMAN_ENTRY('a', 8),
+ HUFFMAN_ENTRY('!', 8),
+ HUFFMAN_ENTRY(0x0a2, 9),
+ HUFFMAN_ENTRY(0x001, 8),
+ HUFFMAN_ENTRY(0x081, 8),
+ HUFFMAN_ENTRY('A', 8),
+ HUFFMAN_ENTRY(0x0e2, 9),
+ HUFFMAN_ENTRY(0x104, 7),
+ HUFFMAN_ENTRY('Y', 8),
+ HUFFMAN_ENTRY(0x019, 8),
+ HUFFMAN_ENTRY(0x092, 9),
+ HUFFMAN_ENTRY(0x114, 7),
+ HUFFMAN_ENTRY('y', 8),
+ HUFFMAN_ENTRY('9', 8),
+ HUFFMAN_ENTRY(0x0d2, 9),
+ HUFFMAN_ENTRY(0x10c, 7),
+ HUFFMAN_ENTRY('i', 8),
+ HUFFMAN_ENTRY(')', 8),
+ HUFFMAN_ENTRY(0x0b2, 9),
+ HUFFMAN_ENTRY(0x009, 8),
+ HUFFMAN_ENTRY(0x089, 8),
+ HUFFMAN_ENTRY('I', 8),
+ HUFFMAN_ENTRY(0x0f2, 9),
+ HUFFMAN_ENTRY(0x102, 7),
+ HUFFMAN_ENTRY('U', 8),
+ HUFFMAN_ENTRY(0x015, 8),
+ HUFFMAN_ENTRY(0x11d, 8),
+ HUFFMAN_ENTRY(0x112, 7),
+ HUFFMAN_ENTRY('u', 8),
+ HUFFMAN_ENTRY('5', 8),
+ HUFFMAN_ENTRY(0x0ca, 9),
+ HUFFMAN_ENTRY(0x10a, 7),
+ HUFFMAN_ENTRY('e', 8),
+ HUFFMAN_ENTRY('%', 8),
+ HUFFMAN_ENTRY(0x0aa, 9),
+ HUFFMAN_ENTRY(0x005, 8),
+ HUFFMAN_ENTRY(0x085, 8),
+ HUFFMAN_ENTRY('E', 8),
+ HUFFMAN_ENTRY(0x0ea, 9),
+ HUFFMAN_ENTRY(0x106, 7),
+ HUFFMAN_ENTRY(']', 8),
+ HUFFMAN_ENTRY(0x01d, 8),
+ HUFFMAN_ENTRY(0x09a, 9),
+ HUFFMAN_ENTRY(0x116, 7),
+ HUFFMAN_ENTRY('}', 8),
+ HUFFMAN_ENTRY('=', 8),
+ HUFFMAN_ENTRY(0x0da, 9),
+ HUFFMAN_ENTRY(0x10e, 7),
+ HUFFMAN_ENTRY('m', 8),
+ HUFFMAN_ENTRY('-', 8),
+ HUFFMAN_ENTRY(0x0ba, 9),
+ HUFFMAN_ENTRY(0x00d, 8),
+ HUFFMAN_ENTRY(0x08d, 8),
+ HUFFMAN_ENTRY('M', 8),
+ HUFFMAN_ENTRY(0x0fa, 9),
+ HUFFMAN_ENTRY(0x101, 7),
+ HUFFMAN_ENTRY('S', 8),
+ HUFFMAN_ENTRY(0x013, 8),
+ HUFFMAN_ENTRY(0x11b, 8),
+ HUFFMAN_ENTRY(0x111, 7),
+ HUFFMAN_ENTRY('s', 8),
+ HUFFMAN_ENTRY('3', 8),
+ HUFFMAN_ENTRY(0x0c6, 9),
+ HUFFMAN_ENTRY(0x109, 7),
+ HUFFMAN_ENTRY('c', 8),
+ HUFFMAN_ENTRY('#', 8),
+ HUFFMAN_ENTRY(0x0a6, 9),
+ HUFFMAN_ENTRY(0x003, 8),
+ HUFFMAN_ENTRY(0x083, 8),
+ HUFFMAN_ENTRY('C', 8),
+ HUFFMAN_ENTRY(0x0e6, 9),
+ HUFFMAN_ENTRY(0x105, 7),
+ HUFFMAN_ENTRY('[', 8),
+ HUFFMAN_ENTRY(0x01b, 8),
+ HUFFMAN_ENTRY(0x096, 9),
+ HUFFMAN_ENTRY(0x115, 7),
+ HUFFMAN_ENTRY('{', 8),
+ HUFFMAN_ENTRY(';', 8),
+ HUFFMAN_ENTRY(0x0d6, 9),
+ HUFFMAN_ENTRY(0x10d, 7),
+ HUFFMAN_ENTRY('k', 8),
+ HUFFMAN_ENTRY('+', 8),
+ HUFFMAN_ENTRY(0x0b6, 9),
+ HUFFMAN_ENTRY(0x00b, 8),
+ HUFFMAN_ENTRY(0x08b, 8),
+ HUFFMAN_ENTRY('K', 8),
+ HUFFMAN_ENTRY(0x0f6, 9),
+ HUFFMAN_ENTRY(0x103, 7),
+ HUFFMAN_ENTRY('W', 8),
+ HUFFMAN_ENTRY(0x017, 8),
+ HUFFMAN_ENTRY(0x11f, 8),
+ HUFFMAN_ENTRY(0x113, 7),
+ HUFFMAN_ENTRY('w', 8),
+ HUFFMAN_ENTRY('7', 8),
+ HUFFMAN_ENTRY(0x0ce, 9),
+ HUFFMAN_ENTRY(0x10b, 7),
+ HUFFMAN_ENTRY('g', 8),
+ HUFFMAN_ENTRY('\'', 8),
+ HUFFMAN_ENTRY(0x0ae, 9),
+ HUFFMAN_ENTRY(0x007, 8),
+ HUFFMAN_ENTRY(0x087, 8),
+ HUFFMAN_ENTRY('G', 8),
+ HUFFMAN_ENTRY(0x0ee, 9),
+ HUFFMAN_ENTRY(0x107, 7),
+ HUFFMAN_ENTRY('_', 8),
+ HUFFMAN_ENTRY(0x01f, 8),
+ HUFFMAN_ENTRY(0x09e, 9),
+ HUFFMAN_ENTRY(0x117, 7),
+ HUFFMAN_ENTRY(0x07f, 8),
+ HUFFMAN_ENTRY('?', 8),
+ HUFFMAN_ENTRY(0x0de, 9),
+ HUFFMAN_ENTRY(0x10f, 7),
+ HUFFMAN_ENTRY('o', 8),
+ HUFFMAN_ENTRY('/', 8),
+ HUFFMAN_ENTRY(0x0be, 9),
+ HUFFMAN_ENTRY(0x00f, 8),
+ HUFFMAN_ENTRY(0x08f, 8),
+ HUFFMAN_ENTRY('O', 8),
+ HUFFMAN_ENTRY(0x0fe, 9),
+ HUFFMAN_ENTRY(0x100, 7),
+ HUFFMAN_ENTRY('P', 8),
+ HUFFMAN_ENTRY(0x010, 8),
+ HUFFMAN_ENTRY(0x118, 8),
+ HUFFMAN_ENTRY(0x110, 7),
+ HUFFMAN_ENTRY('p', 8),
+ HUFFMAN_ENTRY('0', 8),
+ HUFFMAN_ENTRY(0x0c1, 9),
+ HUFFMAN_ENTRY(0x108, 7),
+ HUFFMAN_ENTRY('`', 8),
+ HUFFMAN_ENTRY(' ', 8),
+ HUFFMAN_ENTRY(0x0a1, 9),
+ HUFFMAN_ENTRY(0x000, 8),
+ HUFFMAN_ENTRY(0x080, 8),
+ HUFFMAN_ENTRY('@', 8),
+ HUFFMAN_ENTRY(0x0e1, 9),
+ HUFFMAN_ENTRY(0x104, 7),
+ HUFFMAN_ENTRY('X', 8),
+ HUFFMAN_ENTRY(0x018, 8),
+ HUFFMAN_ENTRY(0x091, 9),
+ HUFFMAN_ENTRY(0x114, 7),
+ HUFFMAN_ENTRY('x', 8),
+ HUFFMAN_ENTRY('8', 8),
+ HUFFMAN_ENTRY(0x0d1, 9),
+ HUFFMAN_ENTRY(0x10c, 7),
+ HUFFMAN_ENTRY('h', 8),
+ HUFFMAN_ENTRY('(', 8),
+ HUFFMAN_ENTRY(0x0b1, 9),
+ HUFFMAN_ENTRY(0x008, 8),
+ HUFFMAN_ENTRY(0x088, 8),
+ HUFFMAN_ENTRY('H', 8),
+ HUFFMAN_ENTRY(0x0f1, 9),
+ HUFFMAN_ENTRY(0x102, 7),
+ HUFFMAN_ENTRY('T', 8),
+ HUFFMAN_ENTRY(0x014, 8),
+ HUFFMAN_ENTRY(0x11c, 8),
+ HUFFMAN_ENTRY(0x112, 7),
+ HUFFMAN_ENTRY('t', 8),
+ HUFFMAN_ENTRY('4', 8),
+ HUFFMAN_ENTRY(0x0c9, 9),
+ HUFFMAN_ENTRY(0x10a, 7),
+ HUFFMAN_ENTRY('d', 8),
+ HUFFMAN_ENTRY('$', 8),
+ HUFFMAN_ENTRY(0x0a9, 9),
+ HUFFMAN_ENTRY(0x004, 8),
+ HUFFMAN_ENTRY(0x084, 8),
+ HUFFMAN_ENTRY('D', 8),
+ HUFFMAN_ENTRY(0x0e9, 9),
+ HUFFMAN_ENTRY(0x106, 7),
+ HUFFMAN_ENTRY('\\', 8),
+ HUFFMAN_ENTRY(0x01c, 8),
+ HUFFMAN_ENTRY(0x099, 9),
+ HUFFMAN_ENTRY(0x116, 7),
+ HUFFMAN_ENTRY('|', 8),
+ HUFFMAN_ENTRY('<', 8),
+ HUFFMAN_ENTRY(0x0d9, 9),
+ HUFFMAN_ENTRY(0x10e, 7),
+ HUFFMAN_ENTRY('l', 8),
+ HUFFMAN_ENTRY(',', 8),
+ HUFFMAN_ENTRY(0x0b9, 9),
+ HUFFMAN_ENTRY(0x00c, 8),
+ HUFFMAN_ENTRY(0x08c, 8),
+ HUFFMAN_ENTRY('L', 8),
+ HUFFMAN_ENTRY(0x0f9, 9),
+ HUFFMAN_ENTRY(0x101, 7),
+ HUFFMAN_ENTRY('R', 8),
+ HUFFMAN_ENTRY(0x012, 8),
+ HUFFMAN_ENTRY(0x11a, 8),
+ HUFFMAN_ENTRY(0x111, 7),
+ HUFFMAN_ENTRY('r', 8),
+ HUFFMAN_ENTRY('2', 8),
+ HUFFMAN_ENTRY(0x0c5, 9),
+ HUFFMAN_ENTRY(0x109, 7),
+ HUFFMAN_ENTRY('b', 8),
+ HUFFMAN_ENTRY('"', 8),
+ HUFFMAN_ENTRY(0x0a5, 9),
+ HUFFMAN_ENTRY(0x002, 8),
+ HUFFMAN_ENTRY(0x082, 8),
+ HUFFMAN_ENTRY('B', 8),
+ HUFFMAN_ENTRY(0x0e5, 9),
+ HUFFMAN_ENTRY(0x105, 7),
+ HUFFMAN_ENTRY('Z', 8),
+ HUFFMAN_ENTRY(0x01a, 8),
+ HUFFMAN_ENTRY(0x095, 9),
+ HUFFMAN_ENTRY(0x115, 7),
+ HUFFMAN_ENTRY('z', 8),
+ HUFFMAN_ENTRY(':', 8),
+ HUFFMAN_ENTRY(0x0d5, 9),
+ HUFFMAN_ENTRY(0x10d, 7),
+ HUFFMAN_ENTRY('j', 8),
+ HUFFMAN_ENTRY('*', 8),
+ HUFFMAN_ENTRY(0x0b5, 9),
+ HUFFMAN_ENTRY(0x00a, 8),
+ HUFFMAN_ENTRY(0x08a, 8),
+ HUFFMAN_ENTRY('J', 8),
+ HUFFMAN_ENTRY(0x0f5, 9),
+ HUFFMAN_ENTRY(0x103, 7),
+ HUFFMAN_ENTRY('V', 8),
+ HUFFMAN_ENTRY(0x016, 8),
+ HUFFMAN_ENTRY(0x11e, 8),
+ HUFFMAN_ENTRY(0x113, 7),
+ HUFFMAN_ENTRY('v', 8),
+ HUFFMAN_ENTRY('6', 8),
+ HUFFMAN_ENTRY(0x0cd, 9),
+ HUFFMAN_ENTRY(0x10b, 7),
+ HUFFMAN_ENTRY('f', 8),
+ HUFFMAN_ENTRY('&', 8),
+ HUFFMAN_ENTRY(0x0ad, 9),
+ HUFFMAN_ENTRY(0x006, 8),
+ HUFFMAN_ENTRY(0x086, 8),
+ HUFFMAN_ENTRY('F', 8),
+ HUFFMAN_ENTRY(0x0ed, 9),
+ HUFFMAN_ENTRY(0x107, 7),
+ HUFFMAN_ENTRY('^', 8),
+ HUFFMAN_ENTRY(0x01e, 8),
+ HUFFMAN_ENTRY(0x09d, 9),
+ HUFFMAN_ENTRY(0x117, 7),
+ HUFFMAN_ENTRY('~', 8),
+ HUFFMAN_ENTRY('>', 8),
+ HUFFMAN_ENTRY(0x0dd, 9),
+ HUFFMAN_ENTRY(0x10f, 7),
+ HUFFMAN_ENTRY('n', 8),
+ HUFFMAN_ENTRY('.', 8),
+ HUFFMAN_ENTRY(0x0bd, 9),
+ HUFFMAN_ENTRY(0x00e, 8),
+ HUFFMAN_ENTRY(0x08e, 8),
+ HUFFMAN_ENTRY('N', 8),
+ HUFFMAN_ENTRY(0x0fd, 9),
+ HUFFMAN_ENTRY(0x100, 7),
+ HUFFMAN_ENTRY('Q', 8),
+ HUFFMAN_ENTRY(0x011, 8),
+ HUFFMAN_ENTRY(0x119, 8),
+ HUFFMAN_ENTRY(0x110, 7),
+ HUFFMAN_ENTRY('q', 8),
+ HUFFMAN_ENTRY('1', 8),
+ HUFFMAN_ENTRY(0x0c3, 9),
+ HUFFMAN_ENTRY(0x108, 7),
+ HUFFMAN_ENTRY('a', 8),
+ HUFFMAN_ENTRY('!', 8),
+ HUFFMAN_ENTRY(0x0a3, 9),
+ HUFFMAN_ENTRY(0x001, 8),
+ HUFFMAN_ENTRY(0x081, 8),
+ HUFFMAN_ENTRY('A', 8),
+ HUFFMAN_ENTRY(0x0e3, 9),
+ HUFFMAN_ENTRY(0x104, 7),
+ HUFFMAN_ENTRY('Y', 8),
+ HUFFMAN_ENTRY(0x019, 8),
+ HUFFMAN_ENTRY(0x093, 9),
+ HUFFMAN_ENTRY(0x114, 7),
+ HUFFMAN_ENTRY('y', 8),
+ HUFFMAN_ENTRY('9', 8),
+ HUFFMAN_ENTRY(0x0d3, 9),
+ HUFFMAN_ENTRY(0x10c, 7),
+ HUFFMAN_ENTRY('i', 8),
+ HUFFMAN_ENTRY(')', 8),
+ HUFFMAN_ENTRY(0x0b3, 9),
+ HUFFMAN_ENTRY(0x009, 8),
+ HUFFMAN_ENTRY(0x089, 8),
+ HUFFMAN_ENTRY('I', 8),
+ HUFFMAN_ENTRY(0x0f3, 9),
+ HUFFMAN_ENTRY(0x102, 7),
+ HUFFMAN_ENTRY('U', 8),
+ HUFFMAN_ENTRY(0x015, 8),
+ HUFFMAN_ENTRY(0x11d, 8),
+ HUFFMAN_ENTRY(0x112, 7),
+ HUFFMAN_ENTRY('u', 8),
+ HUFFMAN_ENTRY('5', 8),
+ HUFFMAN_ENTRY(0x0cb, 9),
+ HUFFMAN_ENTRY(0x10a, 7),
+ HUFFMAN_ENTRY('e', 8),
+ HUFFMAN_ENTRY('%', 8),
+ HUFFMAN_ENTRY(0x0ab, 9),
+ HUFFMAN_ENTRY(0x005, 8),
+ HUFFMAN_ENTRY(0x085, 8),
+ HUFFMAN_ENTRY('E', 8),
+ HUFFMAN_ENTRY(0x0eb, 9),
+ HUFFMAN_ENTRY(0x106, 7),
+ HUFFMAN_ENTRY(']', 8),
+ HUFFMAN_ENTRY(0x01d, 8),
+ HUFFMAN_ENTRY(0x09b, 9),
+ HUFFMAN_ENTRY(0x116, 7),
+ HUFFMAN_ENTRY('}', 8),
+ HUFFMAN_ENTRY('=', 8),
+ HUFFMAN_ENTRY(0x0db, 9),
+ HUFFMAN_ENTRY(0x10e, 7),
+ HUFFMAN_ENTRY('m', 8),
+ HUFFMAN_ENTRY('-', 8),
+ HUFFMAN_ENTRY(0x0bb, 9),
+ HUFFMAN_ENTRY(0x00d, 8),
+ HUFFMAN_ENTRY(0x08d, 8),
+ HUFFMAN_ENTRY('M', 8),
+ HUFFMAN_ENTRY(0x0fb, 9),
+ HUFFMAN_ENTRY(0x101, 7),
+ HUFFMAN_ENTRY('S', 8),
+ HUFFMAN_ENTRY(0x013, 8),
+ HUFFMAN_ENTRY(0x11b, 8),
+ HUFFMAN_ENTRY(0x111, 7),
+ HUFFMAN_ENTRY('s', 8),
+ HUFFMAN_ENTRY('3', 8),
+ HUFFMAN_ENTRY(0x0c7, 9),
+ HUFFMAN_ENTRY(0x109, 7),
+ HUFFMAN_ENTRY('c', 8),
+ HUFFMAN_ENTRY('#', 8),
+ HUFFMAN_ENTRY(0x0a7, 9),
+ HUFFMAN_ENTRY(0x003, 8),
+ HUFFMAN_ENTRY(0x083, 8),
+ HUFFMAN_ENTRY('C', 8),
+ HUFFMAN_ENTRY(0x0e7, 9),
+ HUFFMAN_ENTRY(0x105, 7),
+ HUFFMAN_ENTRY('[', 8),
+ HUFFMAN_ENTRY(0x01b, 8),
+ HUFFMAN_ENTRY(0x097, 9),
+ HUFFMAN_ENTRY(0x115, 7),
+ HUFFMAN_ENTRY('{', 8),
+ HUFFMAN_ENTRY(';', 8),
+ HUFFMAN_ENTRY(0x0d7, 9),
+ HUFFMAN_ENTRY(0x10d, 7),
+ HUFFMAN_ENTRY('k', 8),
+ HUFFMAN_ENTRY('+', 8),
+ HUFFMAN_ENTRY(0x0b7, 9),
+ HUFFMAN_ENTRY(0x00b, 8),
+ HUFFMAN_ENTRY(0x08b, 8),
+ HUFFMAN_ENTRY('K', 8),
+ HUFFMAN_ENTRY(0x0f7, 9),
+ HUFFMAN_ENTRY(0x103, 7),
+ HUFFMAN_ENTRY('W', 8),
+ HUFFMAN_ENTRY(0x017, 8),
+ HUFFMAN_ENTRY(0x11f, 8),
+ HUFFMAN_ENTRY(0x113, 7),
+ HUFFMAN_ENTRY('w', 8),
+ HUFFMAN_ENTRY('7', 8),
+ HUFFMAN_ENTRY(0x0cf, 9),
+ HUFFMAN_ENTRY(0x10b, 7),
+ HUFFMAN_ENTRY('g', 8),
+ HUFFMAN_ENTRY('\'', 8),
+ HUFFMAN_ENTRY(0x0af, 9),
+ HUFFMAN_ENTRY(0x007, 8),
+ HUFFMAN_ENTRY(0x087, 8),
+ HUFFMAN_ENTRY('G', 8),
+ HUFFMAN_ENTRY(0x0ef, 9),
+ HUFFMAN_ENTRY(0x107, 7),
+ HUFFMAN_ENTRY('_', 8),
+ HUFFMAN_ENTRY(0x01f, 8),
+ HUFFMAN_ENTRY(0x09f, 9),
+ HUFFMAN_ENTRY(0x117, 7),
+ HUFFMAN_ENTRY(0x07f, 8),
+ HUFFMAN_ENTRY('?', 8),
+ HUFFMAN_ENTRY(0x0df, 9),
+ HUFFMAN_ENTRY(0x10f, 7),
+ HUFFMAN_ENTRY('o', 8),
+ HUFFMAN_ENTRY('/', 8),
+ HUFFMAN_ENTRY(0x0bf, 9),
+ HUFFMAN_ENTRY(0x00f, 8),
+ HUFFMAN_ENTRY(0x08f, 8),
+ HUFFMAN_ENTRY('O', 8),
+ HUFFMAN_ENTRY(0x0ff, 9),
+ }
+};
+
+static const struct shortHuffmanCodeTable fixedHuffmanDistanceTable = {
+ {
+ 5, /* quick bits */
+ 5, /* max code length */
+ },
+ {
+ HUFFMAN_ENTRY(0x00, 5),
+ HUFFMAN_ENTRY(0x10, 5),
+ HUFFMAN_ENTRY(0x08, 5),
+ HUFFMAN_ENTRY(0x18, 5),
+ HUFFMAN_ENTRY(0x04, 5),
+ HUFFMAN_ENTRY(0x14, 5),
+ HUFFMAN_ENTRY(0x0c, 5),
+ HUFFMAN_ENTRY(0x1c, 5),
+ HUFFMAN_ENTRY(0x02, 5),
+ HUFFMAN_ENTRY(0x12, 5),
+ HUFFMAN_ENTRY(0x0a, 5),
+ HUFFMAN_ENTRY(0x1a, 5),
+ HUFFMAN_ENTRY(0x06, 5),
+ HUFFMAN_ENTRY(0x16, 5),
+ HUFFMAN_ENTRY(0x0e, 5),
+ HUFFMAN_ENTRY(0x1e, 5),
+ HUFFMAN_ENTRY(0x01, 5),
+ HUFFMAN_ENTRY(0x11, 5),
+ HUFFMAN_ENTRY(0x09, 5),
+ HUFFMAN_ENTRY(0x19, 5),
+ HUFFMAN_ENTRY(0x05, 5),
+ HUFFMAN_ENTRY(0x15, 5),
+ HUFFMAN_ENTRY(0x0d, 5),
+ HUFFMAN_ENTRY(0x1d, 5),
+ HUFFMAN_ENTRY(0x03, 5),
+ HUFFMAN_ENTRY(0x13, 5),
+ HUFFMAN_ENTRY(0x0b, 5),
+ HUFFMAN_ENTRY(0x1b, 5),
+ HUFFMAN_ENTRY(0x07, 5),
+ HUFFMAN_ENTRY(0x17, 5),
+ HUFFMAN_ENTRY(0x0f, 5),
+ HUFFMAN_ENTRY(0x1f, 5),
+ }
+};
+
+#endif
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/locale_md.h b/MPC.3.5.LINUX/preverifier/locale_md.h
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * @(#)locale_md.h 1.0 00/11/22
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LOCALE_MD_
+#define _LOCALE_MD_
+
+#include <locale.h>
+#define SET_DEFAULT_LOCALE setlocale(LC_ALL,"")
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/main.c b/MPC.3.5.LINUX/preverifier/main.c
--- /dev/null
@@ -0,0 +1,479 @@
+/* * @(#)main.c 1.6 00/08/26
+ *
+ * Copyright 1997, 1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: main program
+ * FILE: main.c
+ * OVERVIEW: Runs the Java class verifier.
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Modifications for JAR support, CLDC compliance, and comments,
+ * Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "sys_api.h"
+#include "path_md.h"
+#include "path.h"
+#include "oobj.h"
+//#include "jar.h"
+#include "locale_md.h"
+
+/*
+#include "../util/strings.h"
+#include "../util/error.h"
+#include "../util/message.h"
+#include "../structures/type_list.h"
+#include "../structures/string_list.h"
+#include "../structures/type.h"
+#include "../structures/identifier.h"
+#include "../structures/name_table.h"
+#include "../classgen/bytecode.h"
+#include "../structures/block.h"
+
+#include "../parser/parser.h"
+
+#include "../util/memory.h"
+
+#include "../main/static_entry.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+*/
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+char str_buffer[STRINGBUFFERSIZE]; /* shared string buffer */
+
+int processedfile = 0;
+int errorCode = 0; /* Error code returned by program */
+
+bool_t no_native_methods = FALSE;
+bool_t no_floating_point = FALSE;
+bool_t no_finalizers = FALSE;
+char tmp_dir[32]; /* temporary directory for storing
+ verified classes */
+extern char *output_dir; /* output directory */
+bool_t tmpDirExists = FALSE;
+
+extern void VerifyFile(register char *fn);
+//extern bool_t ProcessJARfile(char *buf, int len);
+//extern bool_t isJARfile(char *fn, int length);
+
+//static void usage(char *progname);
+
+
+/*=========================================================================
+ * FUNCTION: recurse_dir()
+ * TYPE: Handles recursive directories
+ * OVERVIEW: Internal function called by ProcessInputs().
+ *
+ * This function reads a directory, searching for either another directory,
+ * JAR file or an individual class name that is to be verified.
+ *
+ * INTERFACE:
+ * parameters: dirname name of the directory entry.
+ * pkgname name of the package
+ * returns: nothing
+ *=======================================================================*/
+/*
+static void recurse_dir(char *dirname, char *pkgname)
+{
+ struct dirent *ent;
+ char buf[MAXPACKAGENAME];
+ char pkgbuf[MAXPACKAGENAME];
+ DIR *dir = opendir(dirname);
+
+ if (dir == NULL) {
+ fprintf(stderr, "Can't open dir %s\n", dirname);
+ exit(1);
+ }
+ for (ent = readdir(dir); ent; ent = readdir(dir)) {
+ struct stat stat_buf;
+ char *name = ent->d_name;
+ int len;
+
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+ continue;
+ }
+
+ strcpy(pkgbuf, pkgname);
+ if (pkgname[0] != 0) {
+ strcat(pkgbuf, "/");
+ }
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "recurse_dir: Reading filename [%s] from directory [%s]\n",
+ name, dirname);
+
+ strcat(pkgbuf, name);
+
+ strcpy(buf, dirname);
+ strcat(buf, name);
+
+ stat(buf, &stat_buf);
+ len = strlen(buf);
+
+ if (stat_buf.st_mode & S_IFDIR) {
+ // handle the recursive directory found
+ strcat(buf, "/");
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "recurse_dir: Recursive directory found, calling recurse_dir ([%s] [%s])\n",
+ buf, pkgbuf);
+ recurse_dir(buf, pkgbuf);
+ continue;
+ } else if (isJARfile (buf, len)) {
+
+ //
+ // this directory contains a JAR file which contains
+ // the classes to be verified
+ //
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "recurse_dir: Found JAR file [%s] in dir!\n", buf);
+
+ if (!ProcessJARfile(buf, len)) {
+
+ fprintf(stderr, "Not a valid JAR file [%s]\n", buf);
+ exit(1);
+ }
+ }
+
+ // we just have a class file that needs verification
+
+ len = strlen(pkgbuf);
+ if (len > 6 && strcmp(pkgbuf + len - 6, ".class") == 0) {
+
+ pkgbuf[len - 6] = 0;
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "recurse_dir: Verifying Class [%s] \n", pkgbuf);
+ VerifyFile(pkgbuf);
+ }
+ }
+
+ closedir(dir);
+}
+*/
+
+/*=========================================================================
+ * FUNCTION: ProcessInputs()
+ * TYPE: Processes inputs
+ * OVERVIEW: Internal function called by main().
+ *
+ * This function processes input entries for specifying classes that are to
+ * be verified. The inputs may be in 3 forms: a directory, or nested
+ * directories, one or more JAR files, or one or more individual class files.
+ * If a directory entry is specified, it may also contain one or more JAR
+ * files, or one or more individual class files.
+ *
+ * INTERFACE:
+ * parameters: argname: directory, JAR file or an individual class file.
+ * returns: nothing
+ *=======================================================================*/
+/*
+static void ProcessInputs(char *argname)
+{
+ char buf[MAXPACKAGENAME];
+ struct stat stat_buf;
+ int res = stat(argname, &stat_buf);
+ int len;
+
+
+ strcpy(buf, argname);
+ len = strlen(argname);
+
+
+ if ((res == 0) && (stat_buf.st_mode & S_IFDIR)) {
+ /* Append dir separator if it does not yet exist.
+ if (buf[len - 1] != LOCAL_DIR_SEPARATOR &&
+ buf[len - 1] != DIR_SEPARATOR) {
+ buf[len] = DIR_SEPARATOR;
+ buf[len + 1] = 0;
+ }
+ pushDirectoryOntoClassPath(buf);
+ recurse_dir(buf, "");
+ popClassPath();
+ } else if ((res == 0) && (isJARfile (buf, len))) {
+ /* the classes to be verified are in a JAR file
+ if (!ProcessJARfile(buf, len)) {
+ fprintf(stderr, "Not a valid JAR file [%s]\n", buf);
+ exit(1);
+ }
+ } else {
+ char *p;
+ /* Convert all periods in the argname to slashes
+ for (p = buf; ((p = strchr(p, '.')) != 0); *p++ = '/');
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr,
+ "ProcessInputs: Verifying file [%s]\n", buf );
+ VerifyFile(buf);
+ }
+}*/
+
+
+/*=========================================================================
+ * FUNCTION: main()
+ * TYPE: Runs the verifier.
+ * OVERVIEW: Main function.
+ *
+ * This is the main function that invokes the Java class verifier.
+ *
+ * INTERFACE:
+ * parameters: argc: arg count.
+ * argv: arg value(s)
+ * returns: nothing
+ *=======================================================================*/
+/*
+int main(argc, argv)
+ register char **argv;
+{
+ char *progname;
+ char *argv0 = argv[0];
+
+ SET_DEFAULT_LOCALE;
+
+ if ((progname = strrchr(argv[0], LOCAL_DIR_SEPARATOR)) != 0) {
+ progname++;
+ } else {
+ progname = argv[0];
+ }
+
+ // initialize tmp_dir
+ memset(tmp_dir, 0, 32);
+
+ // initialize the seed for the random number
+ srand(time(NULL));
+
+ // generate a random temp directory name
+ sprintf(tmp_dir, "%s%d%c", "tmp", rand(), '\0');
+
+ while (--argc > 0)
+ if ((++argv)[0][0] == '-') {
+ if (strcmp(argv[0], "-verbose") == 0) {
+ extern bool_t verbose;
+ verbose = TRUE;
+#ifdef DEBUG_VERIFIER
+ } else if (strcmp(argv[0], "-verify-verbose") == 0) {
+ extern int verify_verbose;
+ verify_verbose++;
+#endif
+ } else if (strcmp(argv[0], "-cldc") == 0) {
+ no_native_methods = TRUE;
+ no_floating_point = TRUE;
+ no_finalizers = TRUE;
+ } else if (strcmp(argv[0], "-nofinalize") == 0) {
+ no_finalizers = TRUE;
+ } else if (strcmp(argv[0], "-nonative") == 0) {
+ no_native_methods = TRUE;
+ } else if (strcmp(argv[0], "-nofp") == 0) {
+ no_floating_point = TRUE;
+ } else if (strcmp(argv[0], "-Xns") == 0) {
+ extern bool_t stack_map_on;
+ stack_map_on = FALSE;
+ } else if (strcmp(argv[0], "-Xni") == 0) {
+ extern bool_t inline_jsr_on;
+ inline_jsr_on = FALSE;
+ } else if (strcmp(argv[0], "-d") == 0) {
+ output_dir = strdup(argv[1]);
+ argc--; argv++;
+ } else if (strcmp(argv[0], "-classpath") == 0) {
+ if (argc > 1) {
+ char *buf = (char *)malloc(strlen(argv[1]) + 32);
+ sprintf(buf, "CLASSPATH=%s", argv[1]);
+ putenv(buf);
+ argc--; argv++;
+ } else {
+ //fprintf(stderr,
+ // "-classpath requires class path specification\n");
+// usage(progname);
+ exit(1);
+ }
+ } else {
+ //fprintf(stderr, "%s: Illegal option %s\n\n", progname, argv[0]);
+// usage(progname);
+ exit(1);
+ }
+ } else if (argv[0][0] == '@') {
+ char *new_argv[MAXOPTIONS];
+ char *buffer;
+ int new_argc = 1;
+ char *token;
+ bool_t done = FALSE;
+ struct stat sbuf;
+ FILE *fp;
+ int buflen;
+ int filelength;
+ int i;
+
+ new_argv[0] = argv0;
+
+ fp = fopen(&argv[0][1], "rt");
+ if (fp == NULL) {
+ fprintf(stderr, "Can't open %s\n", &argv[0][1]);
+ exit(1);
+ }
+
+ // get the size of the file
+ stat(&argv[0][1], &sbuf);
+ filelength = sbuf.st_size;
+
+ // allocate the buffer
+ if ((buffer = (char *) malloc(filelength+1)) == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+
+ if (fgets(buffer, filelength+1, fp) != NULL) {
+ buflen = strlen(buffer);
+
+ if (DEBUG_READFROMFILE) {
+ fprintf(stderr, "Buffer = [%s]\n", buffer);
+ }
+ // get the first parameter
+ token = strtok(buffer, " \0\n\r\t\"");
+
+ // Search for parameters until none can be found
+ while (token != NULL && !done) {
+
+ if ((strcmp(token, "\n") == 0) ||
+ (strcmp(token, "\r") == 0) ||
+ (strcmp(token, "\t") == 0)) {
+ // <NL>, <CR> or <TAB>
+ done = TRUE;
+ } else {
+ // On Win32, it's possible to have a <CR> <LF>
+ // appended at the end of the token, which needs
+ // to be extracted before restoring the arg
+ //
+ char *p;
+ // Convert all <CR> <LF> to NULL
+ for (p = token; *p != '\0'; p++) {
+ if (*p == '\n' || *p == '\r')
+ *p = '\0';
+ }
+
+ // save the parameter
+ new_argv[new_argc++] = token;
+
+ if ((strcmp(token, "-classpath") == 0) ||
+ (strcmp(token, "-d") == 0)) {
+ // search for the beginning of a string literal
+ token = strtok(NULL, "\"");
+
+ } else { // get the next token
+ token = strtok(NULL," \0\n\r\t\"");
+ }
+ }
+ }
+
+ if (DEBUG_READFROMFILE) {
+ // print the arguments after restoring all of them
+ for (i=0; i < new_argc; i++)
+ fprintf(stderr, "new_argv[%d] = [%s]\n", i, new_argv[i]);
+ }
+ }
+
+ fclose(fp);
+ main(new_argc, new_argv);
+
+ if (buffer != NULL) {
+ free(buffer);
+ }
+ argc--; argv++;
+ } else {
+ processedfile++;
+ if (strlen(argv[0]) > MAXPACKAGENAME) {
+ // fprintf(stderr,
+ // "Package name for class exceeds max allowed size [1024]\n");
+// usage(progname);
+ exit(1);
+ }
+
+
+
+ ProcessInputs(argv[0]);
+ }
+ if (processedfile == 0) {
+ usage(progname);
+ exit(1);
+ }
+ return errorCode; // normal errorCode=0 indicates successful completion
+}*/
+/*
+static void usage(char *progname) {
+ fprintf(stderr, "Usage: %s [options] classnames|dirnames ...\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "where options include:\n");
+ fprintf(stderr, " -classpath <directories separated by '%c'>\n", (char)PATH_SEPARATOR);
+ fprintf(stderr, " Directories in which to look for classes\n");
+ fprintf(stderr, " -d <directory> Directory in which output is written (default is ./output/)\n");
+
+ fprintf(stderr, " -cldc Checks for existence of language features prohibited\n");
+ fprintf(stderr, " by CLDC (native methods, floating point and finalizers)\n");
+
+ fprintf(stderr, " -nofinalize No finalizers allowed\n");
+ fprintf(stderr, " -nonative No native methods allowed\n");
+ fprintf(stderr, " -nofp No floating point operations allowed\n");
+ fprintf(stderr, " @<filename> Read command line arguments from a text file\n");
+ fprintf(stderr, " Command line arguments must all be on a single line\n");
+ fprintf(stderr, " Directory names must be enclosed in double quotes (\")\n");
+
+ fprintf(stderr, "\n");
+}
+ */
+
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+//static
+int
+OpenCode(char *fn, char *sfn, char *dir, struct stat * st)
+{
+ long codefd;
+ char *fullname = (char*) malloc(strlen(fn) + strlen(dir) + 10);
+ #ifdef WIN32
+ sprintf(fullname, "%s\\%s", dir, fn);
+ #endif
+ #ifdef UNIX
+ sprintf(fullname, "%s/%s", dir, fn);
+ #endif
+ if (fn == 0 || (codefd = open(fullname, O_BINARY, 0644)) < 0
+ || fstat(codefd, st) < 0)
+ {
+ free(fullname);
+ return -2;
+ }
+ free(fullname);
+ return codefd;
+}
diff --git a/MPC.3.5.LINUX/preverifier/oobj.h b/MPC.3.5.LINUX/preverifier/oobj.h
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * @(#)oobj.h 1.5 00/04/12
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+/*
+ * Java object header format
+ */
+
+#ifndef _OOBJ_H_
+#define _OOBJ_H_
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "typedefs.h"
+#include "signature.h"
+
+#define JAVA_CLASSFILE_MAGIC 0xCafeBabe
+
+#define JAVASRCEXT "java"
+#define JAVASRCEXTLEN 4
+#define JAVAOBJEXT "class"
+#define JAVAOBJEXTLEN 5
+
+#define JAVA_VERSION 45
+#define JAVA_MINOR_VERSION 3
+#define ARRAYHEADER long alloclen
+
+/* The size (in bytes) of a statically allocated area that the
+ * verifier uses internally in various string operations.
+ */
+#ifndef STRINGBUFFERSIZE
+#define STRINGBUFFERSIZE 512
+#endif
+
+#define MAXOPTIONS 2048 /* maximum # of parameters */
+
+/* maximum size allowed for package name of a class file */
+#define MAXPACKAGENAME 1024
+
+#define MAXPATHLEN 255
+
+#define HandleTo(T) typedef struct H##T { Class##T *obj; struct methodtable *methods;} H##T
+
+
+typedef long OBJECT;
+typedef OBJECT Classjava_lang_Object;
+typedef OBJECT ClassObject;
+HandleTo(java_lang_Object);
+typedef Hjava_lang_Object JHandle;
+typedef Hjava_lang_Object HObject;
+
+typedef unsigned short unicode;
+
+extern unicode *str2unicode(char *, unicode *, long);
+extern char *int642CString(int64_t number, char *buf, int buflen);
+
+#define ALIGN(n) (((n)+3)&~3)
+#define UCALIGN(n) ((unsigned char *)ALIGN((int)(n)))
+
+struct Hjava_lang_Class; /* forward reference for some compilers */
+struct Classjava_lang_Class; /* forward reference for some compilers */
+
+typedef struct Classjava_lang_Class Classjava_lang_Class;
+
+HandleTo(java_lang_Class);
+typedef struct Hjava_lang_Class ClassClass;
+
+
+struct fieldblock {
+ ClassClass *clazz;
+ char *signature;
+ char *name;
+ unsigned long ID;
+ unsigned short access;
+ union {
+ unsigned long offset; /* info of data */
+ OBJECT static_value;
+ void *static_address;
+ } u;
+ unsigned deprecated:1;
+ unsigned synthetic:1;
+};
+
+#define fieldname(fb) ((fb)->name)
+#define fieldsig(fb) ((fb)->signature)
+#define fieldIsArray(fb) (fieldsig(fb)[0] == SIGNATURE_ARRAY)
+#define fieldIsClass(fb) (fieldsig(fb)[0] == SIGNATURE_CLASS)
+#define fieldclass(fb) ((fb)->clazz)
+
+struct execenv;
+
+#define VERIFIER_TOOL
+
+/* Includes/eliminates a large amount of optional debugging code
+ * (such as class and stack frame printing operations) in/from
+ * the system. By eliminating debug code, the system will be smaller.
+ * Inclusion of debugging code increases the size of the system but
+ * does not introduce any performance overhead unless calls to the
+ * debugging routines are added to the source code or various tracing
+ * options are turned on.
+ */
+
+#ifndef INCLUDEDEBUGCODE
+#define INCLUDEDEBUGCODE 0
+#endif
+
+#define DEBUG_VERIFIER 1
+#define DEBUG_READFROMFILE 0
+
+enum {
+ ITEM_Bogus,
+ ITEM_Void, /* only as a function return value */
+ ITEM_Integer,
+ ITEM_Float,
+ ITEM_Double,
+ ITEM_Double_2, /* 2nd word of double in register */
+ ITEM_Long,
+ ITEM_Long_2, /* 2nd word of long in register */
+ ITEM_InitObject, /* "this" is init method, before call
+ to super() */
+ ITEM_Object, /* Extra info field gives name. */
+ ITEM_NewObject, /* Like object, but uninitialized. */
+ ITEM_ReturnAddress, /* Extra info gives instr # of start pc */
+ /* The following three are only used within array types.
+ * Normally, we use ITEM_Integer, instead. */
+ ITEM_Boolean,
+ ITEM_Byte,
+ ITEM_Short,
+ ITEM_Char
+};
+
+/* These are the constants that appear in class files. */
+enum {
+ CF_ITEM_Bogus,
+ CF_ITEM_Integer,
+ CF_ITEM_Float,
+ CF_ITEM_Double,
+ CF_ITEM_Long,
+ CF_ITEM_Null,
+ CF_ITEM_InitObject,
+
+ CF_ITEM_Object,
+ CF_ITEM_NewObject,
+};
+
+struct map_entry {
+ unsigned char type;
+ long info;
+};
+
+struct stack_map {
+ int offset;
+ int nlocals;
+ struct map_entry *locals;
+ int nstacks;
+ struct map_entry *stacks;
+};
+
+struct methodblock {
+ struct fieldblock fb;
+ unsigned char *code; /* the code */
+ struct CatchFrame *exception_table;
+ struct lineno *line_number_table;
+ struct localvar *localvar_table;
+
+ unsigned long code_length;
+ unsigned long exception_table_length;
+ unsigned long line_number_table_length;
+ unsigned long localvar_table_length;
+
+ bool_t (*invoker)
+ (JHandle *o, struct methodblock *mb, int args_size, struct execenv *ee);
+ unsigned short args_size; /* total size of all arguments */
+ unsigned short maxstack; /* maximum stack usage */
+ unsigned short nlocals; /* maximum number of locals */
+ /* 2 spare bytes here */
+ void *CompiledCode; /* it's type is machine dependent */
+ void *CompiledCodeInfo; /* it's type is machine dependent */
+ long CompiledCodeFlags; /* machine dependent bits */
+ unsigned long inlining; /* possible inlining of code */
+ unsigned short nexceptions; /* number of checked exceptions */
+ unsigned short *exceptions; /* constant pool indices */
+ char *mp_marks;
+ int n_stack_maps;
+ struct stack_map *stack_maps;
+};
+
+struct HIOstream;
+
+struct methodtable {
+ ClassClass *classdescriptor;
+ struct methodblock *methods[1];
+};
+
+struct imethodtable {
+ int icount; /* number of interfaces to follow */
+ struct {
+ ClassClass *classdescriptor;
+ unsigned long *offsets; /* info of data */
+ } itable[1];
+};
+
+typedef struct {
+ char body[1];
+} ArrayOfByte;
+typedef ArrayOfByte ClassArrayOfByte;
+HandleTo(ArrayOfByte);
+
+typedef struct {
+ unicode body[1];
+} ArrayOfChar;
+typedef ArrayOfChar ClassArrayOfChar;
+HandleTo(ArrayOfChar);
+
+typedef struct {
+ signed short body[1];
+} ArrayOfShort;
+typedef ArrayOfShort ClassArrayOfShort;
+HandleTo(ArrayOfShort);
+
+typedef struct {
+ long body[1];
+} ArrayOfInt;
+typedef ArrayOfInt ClassArrayOfInt;
+HandleTo(ArrayOfInt);
+
+typedef struct {
+ int64_t body[1];
+} ArrayOfLong;
+typedef ArrayOfLong ClassArrayOfLong;
+HandleTo(ArrayOfLong);
+
+typedef struct {
+ float body[1];
+} ArrayOfFloat;
+typedef ArrayOfFloat ClassArrayOfFloat;
+HandleTo(ArrayOfFloat);
+
+typedef struct {
+ double body[1];
+} ArrayOfDouble;
+typedef ArrayOfDouble ClassArrayOfDouble;
+HandleTo(ArrayOfDouble);
+
+typedef struct {
+ JHandle *(body[1]);
+} ArrayOfArray;
+typedef ArrayOfArray ClassArrayOfArray;
+HandleTo(ArrayOfArray);
+
+typedef struct {
+ HObject *(body[1]);
+} ArrayOfObject;
+typedef ArrayOfObject ClassArrayOfObject;
+HandleTo(ArrayOfObject);
+
+typedef struct Hjava_lang_String HString;
+
+typedef struct {
+ HString *(body[1]);
+} ArrayOfString;
+typedef ArrayOfString ClassArrayOfString;
+HandleTo(ArrayOfString);
+
+
+/* Note: any handles in this structure must also have explicit
+ code in the ScanClasses() routine of the garbage collector
+ to mark the handle. */
+struct Classjava_lang_Class {
+ /* Things following here are saved in the .class file */
+ unsigned short major_version;
+ unsigned short minor_version;
+ char *name;
+ char *super_name;
+ char *source_name;
+ ClassClass *superclass;
+ ClassClass *HandleToSelf;
+ struct Hjava_lang_ClassLoader *loader;
+ struct methodblock *finalizer;
+
+ union cp_item_type *constantpool;
+ struct methodblock *methods;
+ struct fieldblock *fields;
+ short *implements;
+
+ struct methodtable *methodtable;
+ struct methodtable *methodtable_mem;
+ struct fieldblock **slottable;
+
+ int superclass_idx;
+
+ HString *classname;
+
+ union {
+ struct {
+ unsigned long thishash; /* unused */
+ unsigned long totalhash; /* unused */
+ } cbhash;
+ struct {
+ unsigned char typecode; /* VM typecode */
+ char typesig; /* signature constant */
+ unsigned char slotsize; /* (bytes) in slot */
+ unsigned char elementsize; /* (bytes) in array */
+ unsigned long xxspare;
+ } cbtypeinfo;
+ } hashinfo;
+
+ unsigned short constantpool_count; /* number of items in pool */
+ unsigned short methods_count; /* number of methods */
+ unsigned short fields_count; /* number of fields */
+ unsigned short implements_count; /* number of protocols */
+
+ unsigned short methodtable_size; /* the size of method table */
+ unsigned short slottbl_size; /* size of slottable */
+ unsigned short instance_size; /* (bytes) of an instance */
+
+ unsigned short access; /* how this class can be accesses */
+ unsigned short flags; /* see the CCF_* macros */
+ struct HArrayOfObject *signers;
+ struct imethodtable *imethodtable;
+
+ void *init_thread; /* EE of initializing thread */
+
+ ClassClass *last_subclass_of;
+ void *reserved_for_jit;
+ char *absolute_source_name;
+ struct { int high, low; } timestamp;
+ int n_new_class_entries;
+ char **new_class_entries;
+ int n_new_utf8_entries;
+ char **new_utf8_entries;
+ int has_stack_maps;
+
+ int inner_classes_count;
+ struct innerClasses *inner_classes;
+
+ unsigned deprecated:1;
+ unsigned synthetic:1;
+ unsigned hasTimeStamp:1;
+};
+
+struct innerClasses {
+ int inner_class;
+ int outer_class;
+ char *inner_name;
+ int access;
+};
+
+extern void FreeClass(ClassClass *cb);
+extern void MakeClassSticky(ClassClass *cb);
+
+#define cbAccess(cb) ((unhand(cb))->access)
+#define cbClassname(cb) ((unhand(cb))->classname)
+#define cbConstantPool(cb) ((unhand(cb))->constantpool)
+#define cbConstantPoolCount(cb) ((unhand(cb))->constantpool_count)
+#define cbFields(cb) ((unhand(cb))->fields)
+#define cbFieldsCount(cb) ((unhand(cb))->fields_count)
+#define cbFinalizer(cb) ((unhand(cb))->finalizer)
+#define cbFlags(cb) ((unhand(cb))->flags)
+#define cbHandle(cb) (cb)
+#define cbImplements(cb) ((unhand(cb))->implements)
+#define cbImplementsCount(cb) ((unhand(cb))->implements_count)
+#define cbInstanceSize(cb) ((unhand(cb))->instance_size)
+#define cbIntfMethodTable(cb) ((unhand(cb))->imethodtable)
+#define cbLastSubclassOf(cb) ((unhand(cb))->last_subclass_of)
+#define cbLoader(cb) ((unhand(cb))->loader)
+#define cbMajorVersion(cb) ((unhand(cb))->major_version)
+#define cbMethods(cb) ((unhand(cb))->methods)
+#define cbMethodsCount(cb) ((unhand(cb))->methods_count)
+#define cbMethodTable(cb) ((unhand(cb))->methodtable)
+#define cbMethodTableMem(cb) ((unhand(cb))->methodtable_mem)
+#define cbMethodTableSize(cb) ((unhand(cb))->methodtable_size)
+#define cbMinorVersion(cb) ((unhand(cb))->minor_version)
+#define cbName(cb) ((unhand(cb))->name)
+#define cbSigners(cb) ((unhand(cb))->signers)
+#define cbSlotTable(cb) ((unhand(cb))->slottable)
+#define cbSlotTableSize(cb) ((unhand(cb))->slottbl_size)
+#define cbSourceName(cb) ((unhand(cb))->source_name)
+#define cbSuperclass(cb) ((unhand(cb))->superclass)
+#define cbSuperName(cb) ((unhand(cb))->super_name)
+#define cbThisHash(cb) ((unhand(cb))->hashinfo.cbhash.thishash)
+#define cbTotalHash(cb) ((unhand(cb))->hashinfo.cbhash.totalhash)
+#define cbInitThread(cb) ((unhand(cb))->init_thread)
+#define cbInnerClasses(cb) ((unhand(cb))->inner_classes)
+#define cbInnerClassesCount(cb)((unhand(cb))->inner_classes_count)
+
+
+
+#define cbAbsoluteSourceName(cb) ((unhand(cb))->absolute_source_name)
+#define cbTimestamp(cb) ((unhand(cb))->timestamp)
+
+#define cbIsInterface(cb) ((cbAccess(cb) & ACC_INTERFACE) != 0)
+#define cbIsAbstract(cb) ((cbAccess(cb) & ACC_ABSTRACT) != 0)
+#define cbAccessNotAbstract(cb) ((unhand(cb))->access & ~ACC_ABSTRACT)
+
+/* These are currently only valid for primitive types */
+#define cbIsPrimitive(cb) (CCIs(cb, Primitive))
+#define cbTypeCode(cb) ((unhand(cb))->hashinfo.cbtypeinfo.typecode)
+#define cbTypeSig(cb) ((unhand(cb))->hashinfo.cbtypeinfo.typesig)
+#define cbSlotSize(cb) ((unhand(cb))->hashinfo.cbtypeinfo.slotsize)
+#define cbElementSize(cb) ((unhand(cb))->hashinfo.cbtypeinfo.elementsize)
+
+extern char *classname2string(char *str, char *dst, int size);
+
+#define twoword_static_address(fb) ((fb)->u.static_address)
+#define normal_static_address(fb) (&(fb)->u.static_value)
+
+/* ClassClass flags */
+#define CCF_IsSysLock 0x01 /* any instance treated as a "system" lock */
+#define CCF_IsResolved 0x02 /* has <clinit> been run? */
+#define CCF_IsError 0x04 /* Resolution caused an error */
+#define CCF_IsSoftRef 0x08 /* whether this is class Ref or subclass */
+#define CCF_IsInitialized 0x10 /* whether this is class has been inited */
+#define CCF_IsLinked 0x20 /* Has symbolic entries been linked */
+#define CCF_IsVerified 0x40 /* has the verifier been run */
+
+#define CCF_IsPrimitive 0x100 /* if pseudo-class for a primitive type */
+#define CCF_IsReferenced 0x200 /* Class is in use */
+#define CCF_IsSticky 0x400 /* Don't unload this class */
+
+#define CCIs(cb,flag) (((unhand(cb))->flags & CCF_Is##flag) != 0)
+#define CCSet(cb,flag) ((unhand(cb))->flags |= CCF_Is##flag)
+#define CCClear(cb,flag) ((unhand(cb))->flags &= ~CCF_Is##flag)
+
+/* map from pc to line number */
+struct lineno {
+ unsigned long pc,
+ line_number;
+};
+
+extern struct lineno *lntbl;
+extern long lntsize, lntused;
+
+/* Symbol table entry for local variables and parameters.
+ pc0/length defines the range that the variable is valid, slot
+ is the position in the local variable array in ExecEnv.
+ nameoff and sigoff are offsets into the string table for the
+ variable name and type signature. A variable is defined with
+ DefineVariable, and at that time, the node for that name is
+ stored in the localvar entry. When code generate is completed
+ for a particular scope, a second pass it made to replace the
+ src node entry with the correct length. */
+
+struct localvar {
+ long pc0; /* starting pc for this variable */
+ long length; /* -1 initially, end pc - pc when we're done */
+ char *name; /* */
+ char *signature;
+ long slot; /* local variable slot */
+};
+
+/* Try/catch is implemented as follows. On a per class basis,
+ there is a catch frame handler (below) for each catch frame
+ that appears in the source. It contains the pc range of the
+ corresponding try body, a pc to jump to in the event that that
+ handler is chosen, and a catchType which must match the object
+ being thrown if that catch handler is to be taken.
+
+ The list of catch frames are sorted by pc. If one range is
+ inside another, then outer most range (the one that encompasses
+ the other) appears last in the list. Therefore, it is possible
+ to search forward, and the first one that matches is the
+ innermost one.
+
+ Methods with catch handlers will layout the code without the
+ catch frames. After all the code is generated, the catch
+ clauses are generated and table entries are created.
+
+ When the class is complete, the table entries are dumped along
+ with the rest of the class. */
+
+struct CatchFrame {
+ long start_pc, end_pc; /* pc range of corresponding try block */
+ long handler_pc; /* pc of catch handler */
+ void* compiled_CatchFrame; /* space to be used by machine code */
+ short catchType; /* type of catch parameter */
+};
+
+#define MC_SUPER (1<<5)
+#define MC_NARGSMASK (MC_SUPER-1)
+#define MC_INT (0<<6)
+#define MC_FLOAT (1<<6)
+#define MC_VOID (2<<6)
+#define MC_OTHER (3<<6)
+#define MC_TYPEMASK (3<<6)
+
+enum {
+ CONSTANT_Utf8 = 1,
+ CONSTANT_Unicode, /* unused */
+ CONSTANT_Integer,
+ CONSTANT_Float,
+ CONSTANT_Long,
+ CONSTANT_Double,
+ CONSTANT_Class,
+ CONSTANT_String,
+ CONSTANT_Fieldref,
+ CONSTANT_Methodref,
+ CONSTANT_InterfaceMethodref,
+ CONSTANT_NameAndType
+};
+
+union cp_item_type {
+ int i;
+ float f;
+ char *cp;
+ unsigned char *type; /* for type table */
+ ClassClass *clazz;
+ struct methodblock *mb;
+ struct fieldblock *fb;
+ struct Hjava_lang_String *str;
+ void *p; /* for very rare occasions */
+};
+
+typedef union cp_item_type cp_item_type;
+
+#define CONSTANT_POOL_ENTRY_RESOLVED 0x80
+#define CONSTANT_POOL_ENTRY_TYPEMASK 0x7F
+#define CONSTANT_POOL_TYPE_TABLE_GET(cp,i) (((unsigned char *)(cp))[i])
+#define CONSTANT_POOL_TYPE_TABLE_PUT(cp,i,v) (CONSTANT_POOL_TYPE_TABLE_GET(cp,i) = (v))
+#define CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(cp,i) \
+ (CONSTANT_POOL_TYPE_TABLE_GET(cp,i) |= CONSTANT_POOL_ENTRY_RESOLVED)
+#define CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(cp,i) \
+ ((CONSTANT_POOL_TYPE_TABLE_GET(cp,i) & CONSTANT_POOL_ENTRY_RESOLVED) != 0)
+#define CONSTANT_POOL_TYPE_TABLE_GET_TYPE(cp,i) \
+ (CONSTANT_POOL_TYPE_TABLE_GET(cp,i) & CONSTANT_POOL_ENTRY_TYPEMASK)
+
+#define CONSTANT_POOL_TYPE_TABLE_INDEX 0
+#define CONSTANT_POOL_UNUSED_INDEX 1
+
+/* The following are used by the constant pool of "array" classes. */
+
+#define CONSTANT_POOL_ARRAY_DEPTH_INDEX 1
+#define CONSTANT_POOL_ARRAY_TYPE_INDEX 2
+#define CONSTANT_POOL_ARRAY_CLASS_INDEX 3
+#define CONSTANT_POOL_ARRAY_LENGTH 4
+
+/*
+ * Package shorthand: this isn't obviously the correct place.
+ */
+#define JAVAPKG "java/lang/"
+#define JAVAIOPKG "java/io/"
+#define JAVANETPKG "java/net/"
+
+#define unhand(o) ((o)->obj)
+
+
+extern ClassClass *classJavaLangClass; /* class java/lang/Class */
+extern ClassClass *classJavaLangObject; /* class java/lang/Object */
+extern ClassClass *classJavaLangString; /* class java/lang/String */
+
+extern ClassClass *classJavaLangThrowable;
+extern ClassClass *classJavaLangException;
+extern ClassClass *classJavaLangError;
+extern ClassClass *classJavaLangRuntimeException;
+extern ClassClass *classJavaLangThreadDeath;
+
+extern ClassClass *interfaceJavaLangCloneable; /* class java/lang/Cloneable */
+extern ClassClass *interfaceJavaIoSerializable; /* class java/io/Serializable */
+
+enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };
+
+extern int verifyclasses;
+extern bool_t verbose;
+extern char * const opnames[];
+
+int jio_snprintf(char *str, size_t count, const char *fmt, ...);
+int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
+
+int jio_printf(const char *fmt, ...);
+int jio_fprintf(FILE *, const char *fmt, ...);
+int jio_vfprintf(FILE *, const char *fmt, va_list args);
+
+struct StrIDhash;
+unsigned short Str2ID(struct StrIDhash **, char *, void ***, int);
+char *ID2Str(struct StrIDhash *, unsigned short, void ***);
+void Str2IDFree(struct StrIDhash **);
+
+unsigned NameAndTypeToHash(char *name, char *type);
+bool_t IsSameClassPackage(ClassClass *class1, ClassClass *class2);
+unsigned Signature2ArgsSize(char *method_signature);
+char *GetClassConstantClassName(cp_item_type *constant_pool, int index);
+ClassClass *FindClass(struct execenv *ee, char *name, bool_t resolve);
+ClassClass *FindClassFromClass(struct execenv *ee, char *name,
+ bool_t resolve, ClassClass *from);
+
+bool_t createInternalClass(unsigned char *bytes, unsigned char *limit,
+ ClassClass *cb, struct Hjava_lang_ClassLoader *,
+ char *utfname, char **detail);
+
+bool_t VerifyClass(ClassClass *cb);
+//bool_t IsLegalClassname(char *name, bool_t allowArrayClass);
+bool_t verify_class_codes(ClassClass *cb);
+
+struct execenv {
+ /* Detecting class circularities */
+ struct seenclass {
+ ClassClass *cb;
+ struct seenclass *next;
+ } seenclasses;
+
+ /* error message occurred during class loading */
+ char *class_loading_msg;
+};
+
+typedef struct execenv ExecEnv;
+
+extern ExecEnv * EE();
+
+ClassClass *FindStickySystemClass(struct execenv *, char *, bool_t resolve);
+bool_t VerifyClassAccess(ClassClass *, ClassClass *, bool_t);
+void InitializeInvoker(ClassClass *cb);
+bool_t RunStaticInitializers(ClassClass *cb);
+ClassClass *ClassLoaderFindClass(ExecEnv *ee,
+ struct Hjava_lang_ClassLoader *loader,
+ char *name, bool_t resolve);
+ClassClass *LoadClassLocally(char *name);
+ClassClass *createFakeArrayClass(char *name, int base_type, int depth,
+ ClassClass *inner_cb,
+ struct Hjava_lang_ClassLoader *);
+ClassClass *createPrimitiveClass(char *name, char sig, unsigned char typecode,
+ unsigned char slotsize, unsigned char elementsize);
+
+bool_t isJARfile(char *fn, int length);
+
+#define BINCLASS_LOCK()
+#define BINCLASS_UNLOCK()
+#define LOADCLASS_LOCK()
+#define LOADCLASS_UNLOCK()
+#define NAMETYPEHASH_LOCK()
+#define NAMETYPEHASH_UNLOCK()
+
+#define FINALIZER_METHOD_NAME "finalize"
+#define FINALIZER_METHOD_SIGNATURE "()V"
+
+#define CLS_RESLV_INIT_CLASS "java/lang/Class"
+#define CLS_RESLV_INIT_OBJECT "java/lang/Object"
+#define CLS_RESLV_INIT_REF "sun/misc/Ref"
+
+#define METHOD_FLAG_BITS 5
+#define FLAG_MASK ((1<<METHOD_FLAG_BITS)-1) /* valid flag bits */
+#define METHOD_MASK (~FLAG_MASK) /* valid mtable ptr bits */
+#define LENGTH_MASK METHOD_MASK
+
+#define mt_slot(methodtable, slot) (methodtable)->methods[slot]
+
+#define monitorEnter(m)
+#define monitorExit(m)
+
+#define exceptionOccurred(ee) 0
+void SignalError(struct execenv *, char *, char *);
+
+void panic(const char *format, ...);
+
+void printCurrentClassName(void);
+
+void ensure_dir_exists(char *dir);
+void ensure_dir_writable(char *dir);
+
+extern bool_t no_native_methods;
+extern bool_t no_floating_point;
+extern bool_t no_finalizers;
+
+extern int errorCode; /* status error returned by program*/
+ /* Set to 1 if any errors encountered
+ * during class verification in VerifyFile()
+ */
+#endif /* !_OOBJ_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/opcodes.h b/MPC.3.5.LINUX/preverifier/opcodes.h
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright 1995-2002 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+typedef enum {
+ opc_nop = 0,
+ opc_aconst_null = 1,
+ opc_iconst_m1 = 2,
+ opc_iconst_0 = 3,
+ opc_iconst_1 = 4,
+ opc_iconst_2 = 5,
+ opc_iconst_3 = 6,
+ opc_iconst_4 = 7,
+ opc_iconst_5 = 8,
+ opc_lconst_0 = 9,
+ opc_lconst_1 = 10,
+ opc_fconst_0 = 11,
+ opc_fconst_1 = 12,
+ opc_fconst_2 = 13,
+ opc_dconst_0 = 14,
+ opc_dconst_1 = 15,
+ opc_bipush = 16,
+ opc_sipush = 17,
+ opc_ldc = 18,
+ opc_ldc_w = 19,
+ opc_ldc2_w = 20,
+ opc_iload = 21,
+ opc_lload = 22,
+ opc_fload = 23,
+ opc_dload = 24,
+ opc_aload = 25,
+ opc_iload_0 = 26,
+ opc_iload_1 = 27,
+ opc_iload_2 = 28,
+ opc_iload_3 = 29,
+ opc_lload_0 = 30,
+ opc_lload_1 = 31,
+ opc_lload_2 = 32,
+ opc_lload_3 = 33,
+ opc_fload_0 = 34,
+ opc_fload_1 = 35,
+ opc_fload_2 = 36,
+ opc_fload_3 = 37,
+ opc_dload_0 = 38,
+ opc_dload_1 = 39,
+ opc_dload_2 = 40,
+ opc_dload_3 = 41,
+ opc_aload_0 = 42,
+ opc_aload_1 = 43,
+ opc_aload_2 = 44,
+ opc_aload_3 = 45,
+ opc_iaload = 46,
+ opc_laload = 47,
+ opc_faload = 48,
+ opc_daload = 49,
+ opc_aaload = 50,
+ opc_baload = 51,
+ opc_caload = 52,
+ opc_saload = 53,
+ opc_istore = 54,
+ opc_lstore = 55,
+ opc_fstore = 56,
+ opc_dstore = 57,
+ opc_astore = 58,
+ opc_istore_0 = 59,
+ opc_istore_1 = 60,
+ opc_istore_2 = 61,
+ opc_istore_3 = 62,
+ opc_lstore_0 = 63,
+ opc_lstore_1 = 64,
+ opc_lstore_2 = 65,
+ opc_lstore_3 = 66,
+ opc_fstore_0 = 67,
+ opc_fstore_1 = 68,
+ opc_fstore_2 = 69,
+ opc_fstore_3 = 70,
+ opc_dstore_0 = 71,
+ opc_dstore_1 = 72,
+ opc_dstore_2 = 73,
+ opc_dstore_3 = 74,
+ opc_astore_0 = 75,
+ opc_astore_1 = 76,
+ opc_astore_2 = 77,
+ opc_astore_3 = 78,
+ opc_iastore = 79,
+ opc_lastore = 80,
+ opc_fastore = 81,
+ opc_dastore = 82,
+ opc_aastore = 83,
+ opc_bastore = 84,
+ opc_castore = 85,
+ opc_sastore = 86,
+ opc_pop = 87,
+ opc_pop2 = 88,
+ opc_dup = 89,
+ opc_dup_x1 = 90,
+ opc_dup_x2 = 91,
+ opc_dup2 = 92,
+ opc_dup2_x1 = 93,
+ opc_dup2_x2 = 94,
+ opc_swap = 95,
+ opc_iadd = 96,
+ opc_ladd = 97,
+ opc_fadd = 98,
+ opc_dadd = 99,
+ opc_isub = 100,
+ opc_lsub = 101,
+ opc_fsub = 102,
+ opc_dsub = 103,
+ opc_imul = 104,
+ opc_lmul = 105,
+ opc_fmul = 106,
+ opc_dmul = 107,
+ opc_idiv = 108,
+ opc_ldiv = 109,
+ opc_fdiv = 110,
+ opc_ddiv = 111,
+ opc_irem = 112,
+ opc_lrem = 113,
+ opc_frem = 114,
+ opc_drem = 115,
+ opc_ineg = 116,
+ opc_lneg = 117,
+ opc_fneg = 118,
+ opc_dneg = 119,
+ opc_ishl = 120,
+ opc_lshl = 121,
+ opc_ishr = 122,
+ opc_lshr = 123,
+ opc_iushr = 124,
+ opc_lushr = 125,
+ opc_iand = 126,
+ opc_land = 127,
+ opc_ior = 128,
+ opc_lor = 129,
+ opc_ixor = 130,
+ opc_lxor = 131,
+ opc_iinc = 132,
+ opc_i2l = 133,
+ opc_i2f = 134,
+ opc_i2d = 135,
+ opc_l2i = 136,
+ opc_l2f = 137,
+ opc_l2d = 138,
+ opc_f2i = 139,
+ opc_f2l = 140,
+ opc_f2d = 141,
+ opc_d2i = 142,
+ opc_d2l = 143,
+ opc_d2f = 144,
+ opc_i2b = 145,
+ opc_i2c = 146,
+ opc_i2s = 147,
+ opc_lcmp = 148,
+ opc_fcmpl = 149,
+ opc_fcmpg = 150,
+ opc_dcmpl = 151,
+ opc_dcmpg = 152,
+ opc_ifeq = 153,
+ opc_ifne = 154,
+ opc_iflt = 155,
+ opc_ifge = 156,
+ opc_ifgt = 157,
+ opc_ifle = 158,
+ opc_if_icmpeq = 159,
+ opc_if_icmpne = 160,
+ opc_if_icmplt = 161,
+ opc_if_icmpge = 162,
+ opc_if_icmpgt = 163,
+ opc_if_icmple = 164,
+ opc_if_acmpeq = 165,
+ opc_if_acmpne = 166,
+ opc_goto = 167,
+ opc_jsr = 168,
+ opc_ret = 169,
+ opc_tableswitch = 170,
+ opc_lookupswitch = 171,
+ opc_ireturn = 172,
+ opc_lreturn = 173,
+ opc_freturn = 174,
+ opc_dreturn = 175,
+ opc_areturn = 176,
+ opc_return = 177,
+ opc_getstatic = 178,
+ opc_putstatic = 179,
+ opc_getfield = 180,
+ opc_putfield = 181,
+ opc_invokevirtual = 182,
+ opc_invokespecial = 183,
+ opc_invokestatic = 184,
+ opc_invokeinterface = 185,
+ opc_xxxunusedxxx = 186,
+ opc_new = 187,
+ opc_newarray = 188,
+ opc_anewarray = 189,
+ opc_arraylength = 190,
+ opc_athrow = 191,
+ opc_checkcast = 192,
+ opc_instanceof = 193,
+ opc_monitorenter = 194,
+ opc_monitorexit = 195,
+ opc_wide = 196,
+ opc_multianewarray = 197,
+ opc_ifnull = 198,
+ opc_ifnonnull = 199,
+ opc_goto_w = 200,
+ opc_jsr_w = 201,
+ opc_breakpoint = 202,
+ opc_ldc_quick = 203,
+ opc_ldc_w_quick = 204,
+ opc_ldc2_w_quick = 205,
+ opc_getfield_quick = 206,
+ opc_putfield_quick = 207,
+ opc_getfield2_quick = 208,
+ opc_putfield2_quick = 209,
+ opc_getstatic_quick = 210,
+ opc_putstatic_quick = 211,
+ opc_getstatic2_quick = 212,
+ opc_putstatic2_quick = 213,
+ opc_invokevirtual_quick = 214,
+ opc_invokenonvirtual_quick = 215,
+ opc_invokesuper_quick = 216,
+ opc_invokestatic_quick = 217,
+ opc_invokeinterface_quick = 218,
+ opc_invokevirtualobject_quick = 219,
+ opc_invokeignored_quick = 220,
+ opc_new_quick = 221,
+ opc_anewarray_quick = 222,
+ opc_multianewarray_quick = 223,
+ opc_checkcast_quick = 224,
+ opc_instanceof_quick = 225,
+ opc_invokevirtual_quick_w = 226,
+ opc_getfield_quick_w = 227,
+ opc_putfield_quick_w = 228,
+ opc_nonnull_quick = 229,
+ opc_first_unused_index = 230,
+ opc_software = 254,
+ opc_hardware = 255
+} opcode_type;
diff --git a/MPC.3.5.LINUX/preverifier/opcodes.in_out b/MPC.3.5.LINUX/preverifier/opcodes.in_out
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright 1995-2002 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+char * const opcode_in_out[][2] = {
+ {"", ""}, /* nop */
+ {"", "A"}, /* aconst_null */
+ {"", "I"}, /* iconst_m1 */
+ {"", "I"}, /* iconst_0 */
+ {"", "I"}, /* iconst_1 */
+ {"", "I"}, /* iconst_2 */
+ {"", "I"}, /* iconst_3 */
+ {"", "I"}, /* iconst_4 */
+ {"", "I"}, /* iconst_5 */
+ {"", "L"}, /* lconst_0 */
+ {"", "L"}, /* lconst_1 */
+ {"", "F"}, /* fconst_0 */
+ {"", "F"}, /* fconst_1 */
+ {"", "F"}, /* fconst_2 */
+ {"", "D"}, /* dconst_0 */
+ {"", "D"}, /* dconst_1 */
+ {"", "I"}, /* bipush */
+ {"", "I"}, /* sipush */
+ {"", "?"}, /* ldc */
+ {"", "?"}, /* ldc_w */
+ {"", "?"}, /* ldc2_w */
+ {"", "I"}, /* iload */
+ {"", "L"}, /* lload */
+ {"", "F"}, /* fload */
+ {"", "D"}, /* dload */
+ {"", "A"}, /* aload */
+ {"", "I"}, /* iload_0 */
+ {"", "I"}, /* iload_1 */
+ {"", "I"}, /* iload_2 */
+ {"", "I"}, /* iload_3 */
+ {"", "L"}, /* lload_0 */
+ {"", "L"}, /* lload_1 */
+ {"", "L"}, /* lload_2 */
+ {"", "L"}, /* lload_3 */
+ {"", "F"}, /* fload_0 */
+ {"", "F"}, /* fload_1 */
+ {"", "F"}, /* fload_2 */
+ {"", "F"}, /* fload_3 */
+ {"", "D"}, /* dload_0 */
+ {"", "D"}, /* dload_1 */
+ {"", "D"}, /* dload_2 */
+ {"", "D"}, /* dload_3 */
+ {"", "A"}, /* aload_0 */
+ {"", "A"}, /* aload_1 */
+ {"", "A"}, /* aload_2 */
+ {"", "A"}, /* aload_3 */
+ {"[I]I", "I"}, /* iaload */
+ {"[L]I", "L"}, /* laload */
+ {"[F]I", "F"}, /* faload */
+ {"[D]I", "D"}, /* daload */
+ {"[A]I", "A"}, /* aaload */
+ {"[b]I", "I"}, /* baload */
+ {"[C]I", "I"}, /* caload */
+ {"[S]I", "I"}, /* saload */
+ {"I", ""}, /* istore */
+ {"L", ""}, /* lstore */
+ {"F", ""}, /* fstore */
+ {"D", ""}, /* dstore */
+ {"A", ""}, /* astore */
+ {"I", ""}, /* istore_0 */
+ {"I", ""}, /* istore_1 */
+ {"I", ""}, /* istore_2 */
+ {"I", ""}, /* istore_3 */
+ {"L", ""}, /* lstore_0 */
+ {"L", ""}, /* lstore_1 */
+ {"L", ""}, /* lstore_2 */
+ {"L", ""}, /* lstore_3 */
+ {"F", ""}, /* fstore_0 */
+ {"F", ""}, /* fstore_1 */
+ {"F", ""}, /* fstore_2 */
+ {"F", ""}, /* fstore_3 */
+ {"D", ""}, /* dstore_0 */
+ {"D", ""}, /* dstore_1 */
+ {"D", ""}, /* dstore_2 */
+ {"D", ""}, /* dstore_3 */
+ {"A", ""}, /* astore_0 */
+ {"A", ""}, /* astore_1 */
+ {"A", ""}, /* astore_2 */
+ {"A", ""}, /* astore_3 */
+ {"[I]II", ""}, /* iastore */
+ {"[L]IL", ""}, /* lastore */
+ {"[F]IF", ""}, /* fastore */
+ {"[D]ID", ""}, /* dastore */
+ {"[A]IA", ""}, /* aastore */
+ {"[b]II", ""}, /* bastore */
+ {"[C]II", ""}, /* castore */
+ {"[S]II", ""}, /* sastore */
+ {"1", ""}, /* pop */
+ {"2+1", ""}, /* pop2 */
+ {"1", "11"}, /* dup */
+ {"21", "121"}, /* dup_x1 */
+ {"3+21", "1321"}, /* dup_x2 */
+ {"2+1", "2121"}, /* dup2 */
+ {"32+1", "21321"}, /* dup2_x1 */
+ {"4+32+1", "214321"}, /* dup2_x2 */
+ {"21", "12"}, /* swap */
+ {"II", "I"}, /* iadd */
+ {"LL", "L"}, /* ladd */
+ {"FF", "F"}, /* fadd */
+ {"DD", "D"}, /* dadd */
+ {"II", "I"}, /* isub */
+ {"LL", "L"}, /* lsub */
+ {"FF", "F"}, /* fsub */
+ {"DD", "D"}, /* dsub */
+ {"II", "I"}, /* imul */
+ {"LL", "L"}, /* lmul */
+ {"FF", "F"}, /* fmul */
+ {"DD", "D"}, /* dmul */
+ {"II", "I"}, /* idiv */
+ {"LL", "L"}, /* ldiv */
+ {"FF", "F"}, /* fdiv */
+ {"DD", "D"}, /* ddiv */
+ {"II", "I"}, /* irem */
+ {"LL", "L"}, /* lrem */
+ {"FF", "F"}, /* frem */
+ {"DD", "D"}, /* drem */
+ {"I", "I"}, /* ineg */
+ {"L", "L"}, /* lneg */
+ {"F", "F"}, /* fneg */
+ {"D", "D"}, /* dneg */
+ {"II", "I"}, /* ishl */
+ {"LI", "L"}, /* lshl */
+ {"II", "I"}, /* ishr */
+ {"LI", "L"}, /* lshr */
+ {"II", "I"}, /* iushr */
+ {"LI", "L"}, /* lushr */
+ {"II", "I"}, /* iand */
+ {"LL", "L"}, /* land */
+ {"II", "I"}, /* ior */
+ {"LL", "L"}, /* lor */
+ {"II", "I"}, /* ixor */
+ {"LL", "L"}, /* lxor */
+ {"", ""}, /* iinc */
+ {"I", "L"}, /* i2l */
+ {"I", "F"}, /* i2f */
+ {"I", "D"}, /* i2d */
+ {"L", "I"}, /* l2i */
+ {"L", "F"}, /* l2f */
+ {"L", "D"}, /* l2d */
+ {"F", "I"}, /* f2i */
+ {"F", "L"}, /* f2l */
+ {"F", "D"}, /* f2d */
+ {"D", "I"}, /* d2i */
+ {"D", "L"}, /* d2l */
+ {"D", "F"}, /* d2f */
+ {"I", "I"}, /* i2b */
+ {"I", "I"}, /* i2c */
+ {"I", "I"}, /* i2s */
+ {"LL", "I"}, /* lcmp */
+ {"FF", "I"}, /* fcmpl */
+ {"FF", "I"}, /* fcmpg */
+ {"DD", "I"}, /* dcmpl */
+ {"DD", "I"}, /* dcmpg */
+ {"I", ""}, /* ifeq */
+ {"I", ""}, /* ifne */
+ {"I", ""}, /* iflt */
+ {"I", ""}, /* ifge */
+ {"I", ""}, /* ifgt */
+ {"I", ""}, /* ifle */
+ {"II", ""}, /* if_icmpeq */
+ {"II", ""}, /* if_icmpne */
+ {"II", ""}, /* if_icmplt */
+ {"II", ""}, /* if_icmpge */
+ {"II", ""}, /* if_icmpgt */
+ {"II", ""}, /* if_icmple */
+ {"AA", ""}, /* if_acmpeq */
+ {"AA", ""}, /* if_acmpne */
+ {"", ""}, /* goto */
+ {"", "R"}, /* jsr */
+ {"", ""}, /* ret */
+ {"I", ""}, /* tableswitch */
+ {"I", ""}, /* lookupswitch */
+ {"I", ""}, /* ireturn */
+ {"L", ""}, /* lreturn */
+ {"F", ""}, /* freturn */
+ {"D", ""}, /* dreturn */
+ {"A", ""}, /* areturn */
+ {"", ""}, /* return */
+ {"", "?"}, /* getstatic */
+ {"?", ""}, /* putstatic */
+ {"A", "?"}, /* getfield */
+ {"?", ""}, /* putfield */
+ {"?", "?"}, /* invokevirtual */
+ {"?", "?"}, /* invokespecial */
+ {"?", "?"}, /* invokestatic */
+ {"?", "?"}, /* invokeinterface */
+ {"?", "?"}, /* xxxunusedxxx */
+ {"", "A"}, /* new */
+ {"I", "A"}, /* newarray */
+ {"I", "A"}, /* anewarray */
+ {"[?]", "I"}, /* arraylength */
+ {"O", ""}, /* athrow */
+ {"A", "A"}, /* checkcast */
+ {"A", "I"}, /* instanceof */
+ {"A", ""}, /* monitorenter */
+ {"A", ""}, /* monitorexit */
+ {"", ""}, /* wide */
+ {"?", "A"}, /* multianewarray */
+ {"A", ""}, /* ifnull */
+ {"A", ""}, /* ifnonnull */
+ {"", ""}, /* goto_w */
+ {"", "R"}, /* jsr_w */
+ {"", ""}, /* breakpoint */
+ {"", "?"}, /* ldc_quick */
+ {"", "?"}, /* ldc_w_quick */
+ {"", "?"}, /* ldc2_w_quick */
+ {"A", "?"}, /* getfield_quick */
+ {"?", ""}, /* putfield_quick */
+ {"A", "?"}, /* getfield2_quick */
+ {"?", ""}, /* putfield2_quick */
+ {"", "?"}, /* getstatic_quick */
+ {"?", ""}, /* putstatic_quick */
+ {"", "?"}, /* getstatic2_quick */
+ {"?", "_"}, /* putstatic2_quick */
+ {"?", "?"}, /* invokevirtual_quick */
+ {"?", "?"}, /* invokenonvirtual_quick */
+ {"?", "?"}, /* invokesuper_quick */
+ {"?", "?"}, /* invokestatic_quick */
+ {"?", "?"}, /* invokeinterface_quick */
+ {"?", "?"}, /* invokevirtualobject_quick */
+ {"?", "?"}, /* invokeignored_quick */
+ {"", "A"}, /* new_quick */
+ {"I", "A"}, /* anewarray_quick */
+ {"?", "A"}, /* multianewarray_quick */
+ {"A", "A"}, /* checkcast_quick */
+ {"A", "I"}, /* instanceof_quick */
+ {"?", "?"}, /* invokevirtual_quick_w */
+ {"A", "?"}, /* getfield_quick_w */
+ {"?", ""}, /* putfield_quick_w */
+ {"A", ""}, /* nonnull_quick */
+};
diff --git a/MPC.3.5.LINUX/preverifier/opcodes.init b/MPC.3.5.LINUX/preverifier/opcodes.init
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright 1995-2002 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+char * const opnames[256] = {
+ "nop",
+ "aconst_null",
+ "iconst_m1",
+ "iconst_0",
+ "iconst_1",
+ "iconst_2",
+ "iconst_3",
+ "iconst_4",
+ "iconst_5",
+ "lconst_0",
+ "lconst_1",
+ "fconst_0",
+ "fconst_1",
+ "fconst_2",
+ "dconst_0",
+ "dconst_1",
+ "bipush",
+ "sipush",
+ "ldc",
+ "ldc_w",
+ "ldc2_w",
+ "iload",
+ "lload",
+ "fload",
+ "dload",
+ "aload",
+ "iload_0",
+ "iload_1",
+ "iload_2",
+ "iload_3",
+ "lload_0",
+ "lload_1",
+ "lload_2",
+ "lload_3",
+ "fload_0",
+ "fload_1",
+ "fload_2",
+ "fload_3",
+ "dload_0",
+ "dload_1",
+ "dload_2",
+ "dload_3",
+ "aload_0",
+ "aload_1",
+ "aload_2",
+ "aload_3",
+ "iaload",
+ "laload",
+ "faload",
+ "daload",
+ "aaload",
+ "baload",
+ "caload",
+ "saload",
+ "istore",
+ "lstore",
+ "fstore",
+ "dstore",
+ "astore",
+ "istore_0",
+ "istore_1",
+ "istore_2",
+ "istore_3",
+ "lstore_0",
+ "lstore_1",
+ "lstore_2",
+ "lstore_3",
+ "fstore_0",
+ "fstore_1",
+ "fstore_2",
+ "fstore_3",
+ "dstore_0",
+ "dstore_1",
+ "dstore_2",
+ "dstore_3",
+ "astore_0",
+ "astore_1",
+ "astore_2",
+ "astore_3",
+ "iastore",
+ "lastore",
+ "fastore",
+ "dastore",
+ "aastore",
+ "bastore",
+ "castore",
+ "sastore",
+ "pop",
+ "pop2",
+ "dup",
+ "dup_x1",
+ "dup_x2",
+ "dup2",
+ "dup2_x1",
+ "dup2_x2",
+ "swap",
+ "iadd",
+ "ladd",
+ "fadd",
+ "dadd",
+ "isub",
+ "lsub",
+ "fsub",
+ "dsub",
+ "imul",
+ "lmul",
+ "fmul",
+ "dmul",
+ "idiv",
+ "ldiv",
+ "fdiv",
+ "ddiv",
+ "irem",
+ "lrem",
+ "frem",
+ "drem",
+ "ineg",
+ "lneg",
+ "fneg",
+ "dneg",
+ "ishl",
+ "lshl",
+ "ishr",
+ "lshr",
+ "iushr",
+ "lushr",
+ "iand",
+ "land",
+ "ior",
+ "lor",
+ "ixor",
+ "lxor",
+ "iinc",
+ "i2l",
+ "i2f",
+ "i2d",
+ "l2i",
+ "l2f",
+ "l2d",
+ "f2i",
+ "f2l",
+ "f2d",
+ "d2i",
+ "d2l",
+ "d2f",
+ "i2b",
+ "i2c",
+ "i2s",
+ "lcmp",
+ "fcmpl",
+ "fcmpg",
+ "dcmpl",
+ "dcmpg",
+ "ifeq",
+ "ifne",
+ "iflt",
+ "ifge",
+ "ifgt",
+ "ifle",
+ "if_icmpeq",
+ "if_icmpne",
+ "if_icmplt",
+ "if_icmpge",
+ "if_icmpgt",
+ "if_icmple",
+ "if_acmpeq",
+ "if_acmpne",
+ "goto",
+ "jsr",
+ "ret",
+ "tableswitch",
+ "lookupswitch",
+ "ireturn",
+ "lreturn",
+ "freturn",
+ "dreturn",
+ "areturn",
+ "return",
+ "getstatic",
+ "putstatic",
+ "getfield",
+ "putfield",
+ "invokevirtual",
+ "invokespecial",
+ "invokestatic",
+ "invokeinterface",
+ "xxxunusedxxx",
+ "new",
+ "newarray",
+ "anewarray",
+ "arraylength",
+ "athrow",
+ "checkcast",
+ "instanceof",
+ "monitorenter",
+ "monitorexit",
+ "wide",
+ "multianewarray",
+ "ifnull",
+ "ifnonnull",
+ "goto_w",
+ "jsr_w",
+ "breakpoint",
+ "ldc_quick",
+ "ldc_w_quick",
+ "ldc2_w_quick",
+ "getfield_quick",
+ "putfield_quick",
+ "getfield2_quick",
+ "putfield2_quick",
+ "getstatic_quick",
+ "putstatic_quick",
+ "getstatic2_quick",
+ "putstatic2_quick",
+ "invokevirtual_quick",
+ "invokenonvirtual_quick",
+ "invokesuper_quick",
+ "invokestatic_quick",
+ "invokeinterface_quick",
+ "invokevirtualobject_quick",
+ "invokeignored_quick",
+ "new_quick",
+ "anewarray_quick",
+ "multianewarray_quick",
+ "checkcast_quick",
+ "instanceof_quick",
+ "invokevirtual_quick_w",
+ "getfield_quick_w",
+ "putfield_quick_w",
+ "nonnull_quick",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "??",
+ "software",
+ "hardware",
+};
diff --git a/MPC.3.5.LINUX/preverifier/opcodes.length b/MPC.3.5.LINUX/preverifier/opcodes.length
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright 1995-2002 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+const short opcode_length[256] = {
+ 1, /* nop */
+ 1, /* aconst_null */
+ 1, /* iconst_m1 */
+ 1, /* iconst_0 */
+ 1, /* iconst_1 */
+ 1, /* iconst_2 */
+ 1, /* iconst_3 */
+ 1, /* iconst_4 */
+ 1, /* iconst_5 */
+ 1, /* lconst_0 */
+ 1, /* lconst_1 */
+ 1, /* fconst_0 */
+ 1, /* fconst_1 */
+ 1, /* fconst_2 */
+ 1, /* dconst_0 */
+ 1, /* dconst_1 */
+ 2, /* bipush */
+ 3, /* sipush */
+ 2, /* ldc */
+ 3, /* ldc_w */
+ 3, /* ldc2_w */
+ 2, /* iload */
+ 2, /* lload */
+ 2, /* fload */
+ 2, /* dload */
+ 2, /* aload */
+ 1, /* iload_0 */
+ 1, /* iload_1 */
+ 1, /* iload_2 */
+ 1, /* iload_3 */
+ 1, /* lload_0 */
+ 1, /* lload_1 */
+ 1, /* lload_2 */
+ 1, /* lload_3 */
+ 1, /* fload_0 */
+ 1, /* fload_1 */
+ 1, /* fload_2 */
+ 1, /* fload_3 */
+ 1, /* dload_0 */
+ 1, /* dload_1 */
+ 1, /* dload_2 */
+ 1, /* dload_3 */
+ 1, /* aload_0 */
+ 1, /* aload_1 */
+ 1, /* aload_2 */
+ 1, /* aload_3 */
+ 1, /* iaload */
+ 1, /* laload */
+ 1, /* faload */
+ 1, /* daload */
+ 1, /* aaload */
+ 1, /* baload */
+ 1, /* caload */
+ 1, /* saload */
+ 2, /* istore */
+ 2, /* lstore */
+ 2, /* fstore */
+ 2, /* dstore */
+ 2, /* astore */
+ 1, /* istore_0 */
+ 1, /* istore_1 */
+ 1, /* istore_2 */
+ 1, /* istore_3 */
+ 1, /* lstore_0 */
+ 1, /* lstore_1 */
+ 1, /* lstore_2 */
+ 1, /* lstore_3 */
+ 1, /* fstore_0 */
+ 1, /* fstore_1 */
+ 1, /* fstore_2 */
+ 1, /* fstore_3 */
+ 1, /* dstore_0 */
+ 1, /* dstore_1 */
+ 1, /* dstore_2 */
+ 1, /* dstore_3 */
+ 1, /* astore_0 */
+ 1, /* astore_1 */
+ 1, /* astore_2 */
+ 1, /* astore_3 */
+ 1, /* iastore */
+ 1, /* lastore */
+ 1, /* fastore */
+ 1, /* dastore */
+ 1, /* aastore */
+ 1, /* bastore */
+ 1, /* castore */
+ 1, /* sastore */
+ 1, /* pop */
+ 1, /* pop2 */
+ 1, /* dup */
+ 1, /* dup_x1 */
+ 1, /* dup_x2 */
+ 1, /* dup2 */
+ 1, /* dup2_x1 */
+ 1, /* dup2_x2 */
+ 1, /* swap */
+ 1, /* iadd */
+ 1, /* ladd */
+ 1, /* fadd */
+ 1, /* dadd */
+ 1, /* isub */
+ 1, /* lsub */
+ 1, /* fsub */
+ 1, /* dsub */
+ 1, /* imul */
+ 1, /* lmul */
+ 1, /* fmul */
+ 1, /* dmul */
+ 1, /* idiv */
+ 1, /* ldiv */
+ 1, /* fdiv */
+ 1, /* ddiv */
+ 1, /* irem */
+ 1, /* lrem */
+ 1, /* frem */
+ 1, /* drem */
+ 1, /* ineg */
+ 1, /* lneg */
+ 1, /* fneg */
+ 1, /* dneg */
+ 1, /* ishl */
+ 1, /* lshl */
+ 1, /* ishr */
+ 1, /* lshr */
+ 1, /* iushr */
+ 1, /* lushr */
+ 1, /* iand */
+ 1, /* land */
+ 1, /* ior */
+ 1, /* lor */
+ 1, /* ixor */
+ 1, /* lxor */
+ 3, /* iinc */
+ 1, /* i2l */
+ 1, /* i2f */
+ 1, /* i2d */
+ 1, /* l2i */
+ 1, /* l2f */
+ 1, /* l2d */
+ 1, /* f2i */
+ 1, /* f2l */
+ 1, /* f2d */
+ 1, /* d2i */
+ 1, /* d2l */
+ 1, /* d2f */
+ 1, /* i2b */
+ 1, /* i2c */
+ 1, /* i2s */
+ 1, /* lcmp */
+ 1, /* fcmpl */
+ 1, /* fcmpg */
+ 1, /* dcmpl */
+ 1, /* dcmpg */
+ 3, /* ifeq */
+ 3, /* ifne */
+ 3, /* iflt */
+ 3, /* ifge */
+ 3, /* ifgt */
+ 3, /* ifle */
+ 3, /* if_icmpeq */
+ 3, /* if_icmpne */
+ 3, /* if_icmplt */
+ 3, /* if_icmpge */
+ 3, /* if_icmpgt */
+ 3, /* if_icmple */
+ 3, /* if_acmpeq */
+ 3, /* if_acmpne */
+ 3, /* goto */
+ 3, /* jsr */
+ 2, /* ret */
+ 99, /* tableswitch */
+ 99, /* lookupswitch */
+ 1, /* ireturn */
+ 1, /* lreturn */
+ 1, /* freturn */
+ 1, /* dreturn */
+ 1, /* areturn */
+ 1, /* return */
+ 3, /* getstatic */
+ 3, /* putstatic */
+ 3, /* getfield */
+ 3, /* putfield */
+ 3, /* invokevirtual */
+ 3, /* invokespecial */
+ 3, /* invokestatic */
+ 5, /* invokeinterface */
+ 0, /* xxxunusedxxx */
+ 3, /* new */
+ 2, /* newarray */
+ 3, /* anewarray */
+ 1, /* arraylength */
+ 1, /* athrow */
+ 3, /* checkcast */
+ 3, /* instanceof */
+ 1, /* monitorenter */
+ 1, /* monitorexit */
+ 0, /* wide */
+ 4, /* multianewarray */
+ 3, /* ifnull */
+ 3, /* ifnonnull */
+ 5, /* goto_w */
+ 5, /* jsr_w */
+ 1, /* breakpoint */
+ 2, /* ldc_quick */
+ 3, /* ldc_w_quick */
+ 3, /* ldc2_w_quick */
+ 3, /* getfield_quick */
+ 3, /* putfield_quick */
+ 3, /* getfield2_quick */
+ 3, /* putfield2_quick */
+ 3, /* getstatic_quick */
+ 3, /* putstatic_quick */
+ 3, /* getstatic2_quick */
+ 3, /* putstatic2_quick */
+ 3, /* invokevirtual_quick */
+ 3, /* invokenonvirtual_quick */
+ 3, /* invokesuper_quick */
+ 3, /* invokestatic_quick */
+ 5, /* invokeinterface_quick */
+ 3, /* invokevirtualobject_quick */
+ 3, /* invokeignored_quick */
+ 3, /* new_quick */
+ 3, /* anewarray_quick */
+ 4, /* multianewarray_quick */
+ 3, /* checkcast_quick */
+ 3, /* instanceof_quick */
+ 3, /* invokevirtual_quick_w */
+ 3, /* getfield_quick_w */
+ 3, /* putfield_quick_w */
+ 1, /* nonnull_quick */
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+};
diff --git a/MPC.3.5.LINUX/preverifier/path.h b/MPC.3.5.LINUX/preverifier/path.h
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * @(#)path.h 1.6 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PATH_H_
+#define _PATH_H_
+
+#include <sys/stat.h>
+#include "path_md.h"
+
+typedef struct {
+ struct {
+ unsigned long locpos;
+ unsigned long cenpos;
+ } jar;
+ char type;
+ char name[1];
+} zip_t;
+
+/*
+ * Class path element, which is either a directory or zip file.
+ */
+typedef struct {
+ enum { CPE_DIR, CPE_ZIP } type;
+ union {
+ zip_t *zip;
+ char *dir;
+ } u;
+} cpe_t;
+
+cpe_t **sysGetClassPath(void);
+void pushDirectoryOntoClassPath(char* directory);
+void pushJarFileOntoClassPath(zip_t *zip);
+void popClassPath(void);
+
+bool_t
+findJARDirectories(zip_t *entry, struct stat *statbuf);
+
+#endif /* !_PATH_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/path_md.h b/MPC.3.5.LINUX/preverifier/path_md.h
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * @(#)path_md.h 1.4 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PATH_MD_H_
+#define _PATH_MD_H_
+
+#define DIR_SEPARATOR '/'
+
+#ifdef UNIX
+#define LOCAL_DIR_SEPARATOR '/'
+#define PATH_SEPARATOR ':'
+
+#include <dirent.h>
+#endif
+#ifdef WIN32
+
+#define LOCAL_DIR_SEPARATOR '\\'
+#define PATH_SEPARATOR ';'
+
+#include <direct.h>
+struct dirent {
+ char d_name[1024];
+};
+
+typedef struct {
+ struct dirent dirent;
+ char *path;
+ HANDLE handle;
+ WIN32_FIND_DATA find_data;
+} DIR;
+
+DIR *opendir(const char *dirname);
+struct dirent *readdir(DIR *dirp);
+int closedir(DIR *dirp);
+
+#endif
+
+#endif /* !_PATH_MD_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/signature.h b/MPC.3.5.LINUX/preverifier/signature.h
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * @(#)signature.h 1.2 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*
+ * The keyletters used in type signatures
+ */
+
+#ifndef _SIGNATURE_H_
+#define _SIGNATURE_H_
+
+#define SIGNATURE_ANY 'A'
+#define SIGNATURE_ARRAY '['
+#define SIGNATURE_BYTE 'B'
+#define SIGNATURE_CHAR 'C'
+#define SIGNATURE_CLASS 'L'
+#define SIGNATURE_ENDCLASS ';'
+#define SIGNATURE_ENUM 'E'
+#define SIGNATURE_FLOAT 'F'
+#define SIGNATURE_DOUBLE 'D'
+#define SIGNATURE_FUNC '('
+#define SIGNATURE_ENDFUNC ')'
+#define SIGNATURE_INT 'I'
+#define SIGNATURE_LONG 'J'
+#define SIGNATURE_SHORT 'S'
+#define SIGNATURE_VOID 'V'
+#define SIGNATURE_BOOLEAN 'Z'
+
+#define SIGNATURE_ANY_STRING "A"
+#define SIGNATURE_ARRAY_STRING "["
+#define SIGNATURE_BYTE_STRING "B"
+#define SIGNATURE_CHAR_STRING "C"
+#define SIGNATURE_CLASS_STRING "L"
+#define SIGNATURE_ENDCLASS_STRING ";"
+#define SIGNATURE_ENUM_STRING "E"
+#define SIGNATURE_FLOAT_STRING "F"
+#define SIGNATURE_DOUBLE_STRING "D"
+#define SIGNATURE_FUNC_STRING "("
+#define SIGNATURE_ENDFUNC_STRING ")"
+#define SIGNATURE_INT_STRING "I"
+#define SIGNATURE_LONG_STRING "J"
+#define SIGNATURE_SHORT_STRING "S"
+#define SIGNATURE_VOID_STRING "V"
+#define SIGNATURE_BOOLEAN_STRING "Z"
+
+
+
+#endif /* !_SIGNATURE_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/stubs.c b/MPC.3.5.LINUX/preverifier/stubs.c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * @(#)stubs.c 1.6 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Stubs.
+ * FILE: stubs.c
+ * OVERVIEW: Miscellaneous functions used during class loading, etc.
+ *
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Edited by Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include "oobj.h"
+#include "sys_api.h"
+
+void
+SignalError(struct execenv * ee, char *ename, char *DetailMessage)
+{
+ printCurrentClassName();
+ jio_fprintf(stderr, "%s", ename);
+ if (DetailMessage) {
+ jio_fprintf(stderr, ": %s\n", DetailMessage);
+ } else {
+ jio_fprintf(stderr, "\n");
+ }
+ exit(1);
+}
+
+bool_t
+VerifyClassAccess(ClassClass *current_class, ClassClass *new_class,
+ bool_t classloader_only)
+{
+ return TRUE;
+}
+
+/* This is called by FindClassFromClass when a class name is being requested
+ * by another class that was loaded via a classloader. For javah, we don't
+ * really care.
+ */
+
+ClassClass *
+ClassLoaderFindClass(struct execenv *ee,
+ struct Hjava_lang_ClassLoader *loader,
+ char *name, bool_t resolve)
+{
+ return NULL;
+}
+
+/* Get the execution environment
+ */
+ExecEnv *
+EE() {
+ static struct execenv lee;
+ return &lee;
+}
+
+bool_t RunStaticInitializers(ClassClass *cb)
+{
+ return TRUE;
+}
+
+void InitializeInvoker(ClassClass *cb)
+{
+}
+
+int verifyclasses = VERIFY_ALL;
+long nbinclasses, sizebinclasses;
+ClassClass **binclasses;
+bool_t verbose;
+struct StrIDhash *nameTypeHash;
+struct StrIDhash *stringHash;
+
+void *allocClassClass()
+{
+ ClassClass *cb = sysCalloc(1, sizeof(ClassClass));
+ Classjava_lang_Class *ucb = sysCalloc(1, sizeof(Classjava_lang_Class));
+
+ cb->obj = ucb;
+ ucb->HandleToSelf = cb;
+ return cb;
+}
+
+void DumpThreads() {}
diff --git a/MPC.3.5.LINUX/preverifier/sys_api.h b/MPC.3.5.LINUX/preverifier/sys_api.h
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * @(#)sys_api.h 1.6 02/09/27
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*
+ * System or Host dependent API. This defines the "porting layer" for
+ * POSIX.1 compliant operating systems.
+ */
+
+#ifndef _SYS_API_H_
+#define _SYS_API_H_
+
+/*
+ * typedefs_md.h includes basic types for this platform;
+ * any macros for HPI functions have been moved to "sysmacros_md.h"
+ */
+#include "typedefs.h"
+
+/*
+ * Miscellaneous system utility APIs that fall outside the POSIX.1
+ * spec.
+ *
+ * Until POSIX (P1003.1a) formerly P.4 is standard, we'll use our
+ * time struct definitions found in timeval.h.
+ */
+long sysGetMilliTicks(void);
+long sysTime(long *);
+int64_t sysTimeMillis(void);
+
+#include <time.h>
+struct tm * sysLocaltime(time_t *, struct tm*);
+struct tm * sysGmtime(time_t *, struct tm*);
+void sysStrftime(char *, int, char *, struct tm *);
+time_t sysMktime(struct tm*);
+
+/*
+ * System API for general allocations
+ */
+void * sysMalloc(size_t);
+void * sysRealloc(void*, size_t);
+void sysFree(void*);
+void * sysCalloc(size_t, size_t);
+#ifdef PAGED_HEAPS
+void * sysAllocBlock(size_t, void**);
+void sysFreeBlock(void *);
+#endif /* PAGED_HEAPS */
+
+/*
+ * System API for dynamic linking libraries into the interpreter
+ */
+char * sysInitializeLinker(void);
+int sysAddDLSegment(char *);
+void sysSaveLDPath(char *);
+long sysDynamicLink(char *);
+void sysBuildLibName(char *, int, char *, char *);
+int sysBuildFunName(char *, int, void *, int);
+long * sysInvokeNative(void *, void *, long *, char *, int, void *);
+
+/*
+ * System API for invoking the interpreter from native applications
+ */
+void sysGetDefaultJavaVMInitArgs(void *);
+int sysInitializeJavaVM(void *, void *);
+int sysFinalizeJavaVM(void *);
+void sysAttachThreadLock();
+void sysAttachThreadUnlock();
+
+/*
+ * System API for threads
+ */
+typedef struct sys_thread sys_thread_t;
+typedef struct sys_mon sys_mon_t;
+typedef void * stackp_t;
+
+int sysThreadBootstrap(sys_thread_t **, void *);
+void sysThreadInitializeSystemThreads(void);
+
+#ifdef UNIX
+int sysThreadCreate(long, uint flags, void *(*)(void *),
+ sys_thread_t **, void *);
+#else
+int sysThreadCreate(long, uint_t flags, void *(*)(void *),
+ sys_thread_t **, void *);
+#endif
+
+void sysThreadExit(void);
+sys_thread_t * sysThreadSelf(void);
+void sysThreadYield(void);
+int sysThreadVMSuspend(sys_thread_t *, sys_thread_t *);
+void sysThreadVMSuspendMe(void);
+int sysThreadVMUnsuspend(sys_thread_t *);
+int sysThreadSuspend(sys_thread_t *);
+int sysThreadResume(sys_thread_t *);
+int sysThreadSetPriority(sys_thread_t *, int);
+int sysThreadGetPriority(sys_thread_t *, int *);
+void * sysThreadStackPointer(sys_thread_t *);
+stackp_t sysThreadStackBase(sys_thread_t *);
+void sysThreadSetStackBase(sys_thread_t *, stackp_t);
+int sysThreadSingle(void);
+void sysThreadMulti(void);
+int sysThreadEnumerateOver(int (*)(sys_thread_t *, void *), void *);
+void sysThreadInit(sys_thread_t *, stackp_t);
+void * sysThreadGetBackPtr(sys_thread_t *);
+int sysThreadCheckStack(void);
+int sysInterruptsPending(void);
+void sysThreadPostException(sys_thread_t *, void *);
+void sysThreadDumpInfo(sys_thread_t *);
+void sysThreadInterrupt(sys_thread_t *);
+int sysThreadIsInterrupted(sys_thread_t *, long);
+int sysThreadAlloc(sys_thread_t **, stackp_t, void *);
+int sysThreadFree(sys_thread_t *);
+
+/*
+ * System API for monitors
+ */
+int sysMonitorSizeof(void);
+int sysMonitorInit(sys_mon_t *);
+int sysMonitorDestroy(sys_mon_t *);
+int sysMonitorEnter(sys_mon_t *);
+bool_t sysMonitorEntered(sys_mon_t *);
+int sysMonitorExit(sys_mon_t *);
+int sysMonitorNotify(sys_mon_t *);
+int sysMonitorNotifyAll(sys_mon_t *);
+int sysMonitorWait(sys_mon_t *, int, bool_t);
+void sysMonitorDumpInfo(sys_mon_t *);
+bool_t sysMonitorInUse(sys_mon_t *);
+
+#define SYS_OK 0
+#define SYS_ERR -1
+#define SYS_INTRPT -2 /* Operation was interrupted */
+#define SYS_TIMEOUT -3 /* A timer ran out */
+#define SYS_NOMEM -5 /* Ran out of memory */
+#define SYS_NORESOURCE -6 /* Ran out of some system resource */
+
+/*
+ * Symbolic constant to be used when waiting indefinitely on a condition
+ * variable
+ */
+#define SYS_TIMEOUT_INFINITY -1
+
+/*
+ * System API for raw memory allocation
+ */
+void * sysMapMem(long, long *);
+void * sysUnmapMem(void *, long, long *);
+void * sysCommitMem(void *, long, long *);
+void * sysDecommitMem(void *, long, long *);
+void * sysUncommitMem(void *, long, long *);
+
+/*
+ * System API for termination
+ */
+void sysExit(int);
+int sysAtexit(void (*func)(void));
+void sysAbort(void);
+
+/*
+ * System API for files
+ */
+extern int sysIsAbsolute(const char* path);
+extern int sysAccess(const char* pFile, int perm);
+
+extern int sysStat(const char *path, struct stat *sbuf);
+extern int sysFStat(int fd, struct stat * sbuf);
+
+extern int sysOpen(const char *name, int openMode, int filePerm);
+extern int sysClose(int fd);
+
+extern long sysSeek(int fd, long offset, int whence);
+extern int sysAvailable(int fd, long* bytes);
+extern size_t sysRead(int fd, void *buf, unsigned int nBytes);
+extern size_t sysWrite(int fd, const void *buf, unsigned int nBytes);
+
+extern int sysRename(const char* srcName, const char* dstName);
+extern int sysUnlink(const char* file);
+
+extern int sysMkdir(const char* path, int mode);
+extern int sysRmdir(const char* path);
+extern int sysCanonicalPath(char *path, char *result, int result_len);
+
+/*
+ * API support needed for various multiprocessor related synchronization
+ * primitives. Systems that don't use real threads can just define
+ * these to be 0 in their sysmacros_md.h.
+ */
+
+int sysIsMP();
+void sysMemoryFlush();
+void sysStoreBarrier();
+
+/*
+ * Include platform specific macros to override these
+ */
+#include "sysmacros_md.h"
+
+#endif /* !_SYS_API_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/sys_support.c b/MPC.3.5.LINUX/preverifier/sys_support.c
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * @(#)sys_support.c 1.7 01/01/18
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: System support functions
+ * FILE: sys_support.c
+ * OVERVIEW: Routines for system support functions. The routines
+ * are for retrieving system class path and for certain
+ * Windows specific file parsing functions.
+ *
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Modifications for JAR support and comments,
+ * Tasneem Sayeed, Sun Microsystems, Inc.
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+//#include <errno.h>
+
+#include "oobj.h"
+#include "jar.h"
+#include "typedefs.h"
+#include "sys_api.h"
+#include "path.h"
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+static cpe_t **saved_classpath;
+static cpe_t **saved_classpath_end;
+
+extern zip_t * getZipEntry(char *zipFile, int len);
+
+/*=========================================================================
+ * FUNCTION: sysGetClassPath
+ * OVERVIEW: Returns the system class path using the getenv() system
+ * call for retrieving the CLASSPATH environment.
+ * INTERFACE:
+ * parameters: none
+ *
+ * returns: Pointer to cpe_t struct ptr (see path.h)
+ *=======================================================================*/
+cpe_t **
+sysGetClassPath(void)
+{
+ struct stat sbuf;
+ int length;
+ zip_t *zipEntry;
+ bool_t includedDot = FALSE;
+
+ if (saved_classpath == 0) {
+ char *cps, *s;
+ int ncpe = 1;
+ cpe_t **cpp;
+ if ((cps = getenv("CLASSPATH")) == 0) {
+ cps = ".";
+ }
+ if ((cps = strdup(cps)) == 0) {
+ return 0;
+ }
+ for (s = cps; *s != '\0'; s++) {
+ if (*s == PATH_SEPARATOR) {
+ ncpe++;
+ }
+ }
+ /* We add 2 since we automatically append "." to the list, and we
+ * need a NULL element at the end.
+ * We add an extra 10 to allow pushing and popping of the classpath.
+ * Generally, we'll need two, at most, but we can afford to be
+ * a little extravagant.
+ */
+ cpp = saved_classpath = sysMalloc((ncpe + 2 + 10) * sizeof(cpe_t *));
+ if (cpp == 0) {
+ return 0;
+ }
+ while (cps && *cps) {
+ char *path = cps;
+ cpe_t *cpe;
+ if ((cps = strchr(cps, PATH_SEPARATOR)) != 0) {
+ *cps++ = '\0';
+ }
+ if (*path == '\0') {
+ path = ".";
+ }
+ cpe = sysMalloc(sizeof(cpe_t));
+ if (cpe == 0) {
+ return 0;
+ }
+ length = strlen(path);
+ if (JAR_DEBUG && verbose) {
+ jio_fprintf(stderr, "SysGetClassPath: Length : %d\n", length);
+ jio_fprintf(stderr, "SysGetClasspath: Path : %s\n", path);
+ }
+ if (stat(path, &sbuf) < 0) {
+ /* we don't have to do anything */
+ } else if (sbuf.st_mode & S_IFDIR) {
+ /* this is a directory */
+ cpe->type = CPE_DIR;
+ cpe->u.dir = path;
+ if (strcmp(path, ".") == 0) {
+ includedDot = TRUE;
+ }
+
+ /* restore only for a valid directory */
+ *cpp++ = cpe;
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "SysGetClassPath: Found directory [%s]\n", path);
+
+ } else if (isJARfile (path, length)) {
+ /* this looks like a JAR file */
+ /* initialize the zip structure */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "SysGetClassPath: Found .JAR file [%s]\n", path);
+
+ /* Create the zip entry for searching the JAR
+ * directories. If the zip entry is NULL, it
+ * would indicate that we ran out of memory
+ * and would have exited already.
+ */
+ zipEntry = getZipEntry(path, length);
+
+ /* search for the JAR directories */
+ if (findJARDirectories(zipEntry, &sbuf)) {
+ /* this is a JAR file - initialize the cpe */
+
+ if (JAR_DEBUG && verbose)
+ jio_fprintf(stderr, "SysGetClassPath: JAR directories OK in [%s]\n", zipEntry->name);
+
+ zipEntry->type = 'j';
+ cpe->type = CPE_ZIP;
+ cpe->u.zip = zipEntry;
+ /* restore entry only for a valid JAR */
+ *cpp++ = cpe;
+ }
+ }
+ }
+ if (!includedDot) {
+ cpe_t *cpe = sysMalloc(sizeof(cpe_t));
+ cpe->type = CPE_DIR;
+ cpe->u.dir = ".";
+ *cpp++ = cpe;
+ }
+ *cpp = 0;
+ saved_classpath_end = cpp;
+ }
+
+ return saved_classpath;
+}
+
+
+/* Puts this directory at the beginning of the class path */
+
+void
+pushDirectoryOntoClassPath(char* directory)
+{
+ cpe_t **ptr;
+
+ cpe_t *cpe = sysMalloc(sizeof(cpe_t));
+ cpe->type = CPE_DIR;
+ cpe->u.dir = directory;
+
+ sysGetClassPath(); /* just in case not done yet */
+
+ /* Note that saved_classpath_end points to the NULL at the end. */
+ saved_classpath_end++;
+ for (ptr = saved_classpath_end; ptr > saved_classpath; ptr--) {
+ ptr[0] = ptr[-1];
+ }
+ ptr[0] = cpe;
+}
+
+
+/* Puts this jar file at the beginning of the class path */
+
+void
+pushJarFileOntoClassPath(zip_t *zipEntry)
+{
+ cpe_t **ptr;
+
+ cpe_t *cpe = sysMalloc(sizeof(cpe_t));
+ cpe->type = CPE_ZIP;
+ cpe->u.zip = zipEntry;
+
+ sysGetClassPath(); /* just in case not done yet */
+
+ /* Note that saved_classpath_end points to the NULL at the end. */
+ saved_classpath_end++;
+ for (ptr = saved_classpath_end; ptr > saved_classpath; ptr--) {
+ ptr[0] = ptr[-1];
+ }
+ ptr[0] = cpe;
+}
+
+
+/* Pop the first element off the class path */
+void
+popClassPath()
+{
+ cpe_t **ptr;
+
+ sysFree(*saved_classpath);
+
+ --saved_classpath_end;
+ for (ptr = saved_classpath; ptr <= saved_classpath_end; ptr++) {
+ /* This copies all of the elements, including the NULL at the end */
+ ptr[0] = ptr[1];
+ }
+}
+
+
+/*=========================================================================
+ * Win32 file parsing functions
+ *=======================================================================*/
+
+#ifdef WIN32
+
+#undef DEBUG_PATH /* Define this to debug path code */
+
+#define isfilesep(c) ((c) == '/' || (c) == '\\')
+#define islb(c) (IsDBCSLeadByte((BYTE)(c)))
+
+
+/*=========================================================================
+ * FUNCTION: sysNativePath
+ * OVERVIEW: Converts a path name to native format. On win32, this
+ * involves forcing all separators to be '\\' rather than '/'
+ * (both are legal inputs, but Win95 sometimes rejects '/')
+ * and removing redundant separators. The input path is assumed
+ * to have been converted into the character encoding used by
+ * the local system. Because this might be a double-byte
+ * encoding, care is taken to treat double-byte lead characters
+ * correctly.
+ *
+ * INTERFACE:
+ * parameters: char *path
+ *
+ * returns: char *
+ *=======================================================================*/
+char *
+sysNativePath(char *path)
+{
+ char *src = path, *dst = path;
+ char *colon = NULL; /* If a drive specifier is found, this will
+ point to the colon following the drive
+ letter */
+
+ /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */
+ sysAssert(!islb('/') && !islb('\\') && !islb(':'));
+
+ /* Check for leading separators */
+ while (isfilesep(*src)) src++;
+ if (!islb(*src) && src[1] == ':') {
+ /* Remove leading separators if followed by drive specifier. This
+ hack is necessary to support file URLs containing drive
+ specifiers (e.g., "file://c:/path"). As a side effect,
+ "/c:/path" can be used as an alternative to "c:/path". */
+ *dst++ = *src++;
+ colon = dst;
+ *dst++ = ':'; src++;
+ } else {
+ src = path;
+ if (isfilesep(src[0]) && isfilesep(src[1])) {
+ /* UNC pathname: Retain first separator; leave src pointed at
+ second separator so that further separators will be collapsed
+ into the second separator. The result will be a pathname
+ beginning with "\\\\" followed (most likely) by a host name. */
+ src = dst = path + 1;
+ path[0] = '\\'; /* Force first separator to '\\' */
+ }
+ }
+
+ /* Remove redundant separators from remainder of path, forcing all
+ separators to be '\\' rather than '/' */
+ while (*src != '\0') {
+ if (isfilesep(*src)) {
+ *dst++ = '\\'; src++;
+ while (isfilesep(*src)) src++;
+ if (*src == '\0') { /* Check for trailing separator */
+ if (colon == dst - 2) break; /* "z:\\" */
+ if (dst == path + 1) break; /* "\\" */
+ if (dst == path + 2 && isfilesep(path[0])) {
+ /* "\\\\" is not collapsed to "\\" because "\\\\" marks the
+ beginning of a UNC pathname. Even though it is not, by
+ itself, a valid UNC pathname, we leave it as is in order
+ to be consistent with sysCanonicalPath() (below) as well
+ as the win32 APIs, which treat this case as an invalid
+ UNC pathname rather than as an alias for the root
+ directory of the current drive. */
+ break;
+ }
+ dst--; /* Path does not denote a root directory, so
+ remove trailing separator */
+ break;
+ }
+ } else {
+ if (islb(*src)) { /* Copy a double-byte character */
+ *dst++ = *src++;
+ if (*src) {
+ *dst++ = *src++;
+ }
+ } else { /* Copy a single-byte character */
+ *dst++ = *src++;
+ }
+ }
+ }
+
+ *dst = '\0';
+#ifdef DEBUG_PATH
+ jio_fprintf(stderr, "sysNativePath: %s\n", path);
+#endif /* DEBUG_PATH */
+ return path;
+}
+
+
+/*=========================================================================
+ * FUNCTION: opendir
+ * OVERVIEW: open directory given dir pointer.
+ *
+ * INTERFACE:
+ * parameters: const char *dirarg
+ *
+ * returns: Pointer to DIR structure
+ *=======================================================================*/
+DIR *
+opendir(const char *dirarg)
+{
+ DIR *dirp = (DIR *)sysMalloc(sizeof(DIR));
+ unsigned long fattr;
+ char alt_dirname[4] = { 0, 0, 0, 0 };
+ char dirname_buf[1024];
+ char *dirname = dirname_buf;
+
+ if (dirp == 0) {
+// errno = ENOMEM;
+ return 0;
+ }
+
+ strcpy(dirname, dirarg);
+ sysNativePath(dirname);
+
+ /*
+ * Win32 accepts "\" in its POSIX stat(), but refuses to treat it
+ * as a directory in FindFirstFile(). We detect this case here and
+ * prepend the current drive name.
+ */
+ if (dirname[1] == '\0' && dirname[0] == '\\') {
+ alt_dirname[0] = _getdrive() + 'A' - 1;
+ alt_dirname[1] = ':';
+ alt_dirname[2] = '\\';
+ alt_dirname[3] = '\0';
+ dirname = alt_dirname;
+ }
+
+ dirp->path = (char *)sysMalloc(strlen(dirname) + 5);
+ if (dirp->path == 0) {
+ sysFree(dirp);
+// errno = ENOMEM;
+ return 0;
+ }
+ strcpy(dirp->path, dirname);
+
+ fattr = GetFileAttributes(dirp->path);
+ if (fattr == 0xffffffff) {
+ sysFree(dirp->path);
+ sysFree(dirp);
+// errno = ENOENT;
+ return 0;
+ } else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ sysFree(dirp->path);
+ sysFree(dirp);
+// errno = ENOTDIR;
+ return 0;
+ }
+
+ /* Append "*.*", or possibly "\\*.*", to path */
+ if (dirp->path[1] == ':'
+ && (dirp->path[2] == '\0'
+ || (dirp->path[2] == '\\' && dirp->path[3] == '\0'))) {
+ /* No '\\' needed for cases like "Z:" or "Z:\" */
+ strcat(dirp->path, "*.*");
+ } else {
+ strcat(dirp->path, "\\*.*");
+ }
+
+ dirp->handle = FindFirstFile(dirp->path, &dirp->find_data);
+ if (dirp->handle == INVALID_HANDLE_VALUE) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+ sysFree(dirp->path);
+ sysFree(dirp);
+// errno = EACCES;
+ return 0;
+ }
+ }
+ return dirp;
+}
+
+
+/*=========================================================================
+ * FUNCTION: readdir
+ * OVERVIEW: read directory given pointer to DIR structure.
+ *
+ * INTERFACE:
+ * parameters: DIR *dirp
+ *
+ * returns: Pointer to dirent structure.
+ *=======================================================================*/
+struct dirent *
+readdir(DIR *dirp)
+{
+ if (dirp->handle == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);
+
+ if (!FindNextFile(dirp->handle, &dirp->find_data)) {
+ if (GetLastError() == ERROR_INVALID_HANDLE) {
+// errno = EBADF;
+ return 0;
+ }
+ FindClose(dirp->handle);
+ dirp->handle = INVALID_HANDLE_VALUE;
+ }
+
+ return &dirp->dirent;
+}
+
+
+/*=========================================================================
+ * FUNCTION: closedir
+ * OVERVIEW: close directory given pointer to DIR structure.
+ * Returns non-zero status if the close fails.
+ *
+ * INTERFACE:
+ * parameters: DIR: *dirp
+ *
+ * returns: int: status
+ *=======================================================================*/
+int
+closedir(DIR *dirp)
+{
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
+ if (!FindClose(dirp->handle)) {
+// errno = EBADF;
+ return -1;
+ }
+ dirp->handle = INVALID_HANDLE_VALUE;
+ }
+ sysFree(dirp->path);
+ sysFree(dirp);
+ return 0;
+}
+
+#endif
diff --git a/MPC.3.5.LINUX/preverifier/sysmacros_md.h b/MPC.3.5.LINUX/preverifier/sysmacros_md.h
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * @(#)sysmacros_md.h 1.5 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYSMACROS_MD_H_
+#define _SYSMACROS_MD_H_
+
+/*
+ * Because these are used directly as function ptrs, just redefine the name
+ */
+#define sysMalloc malloc
+#define sysFree free
+#define sysCalloc calloc
+#define sysRealloc realloc
+
+/* A macro for sneaking into a sys_mon_t to get the owner sys_thread_t */
+#define sysMonitorOwner(mid) ((mid)->monitor_owner)
+
+#ifdef DEBUG
+extern void DumpThreads(void);
+void panic (const char *, ...);
+#define sysAssert(expression) { \
+ if (!(expression)) { \
+ DumpThreads(); \
+ panic("\"%s\", line %d: assertion failure\n", __FILE__, __LINE__); \
+ } \
+}
+#else
+#define sysAssert(expression)
+#endif
+
+/*
+ * Case insensitive compare of ASCII strings
+ */
+#define sysStricmp(a, b) strcasecmp(a, b)
+
+/*
+ * File system macros
+ */
+#ifdef UNIX
+#define sysOpen(_path, _oflag, _mode) open(_path, _oflag, _mode)
+#define sysNativePath(path) (path)
+#endif
+#ifdef WIN32
+#include <io.h>
+#define sysOpen(_path, _oflag, _mode) open(_path, _oflag | O_BINARY, _mode)
+char *sysNativePath(char *);
+#endif
+#define sysRead(_fd, _buf, _n) read(_fd, _buf, _n)
+#define sysWrite(_fd, _buf, _n) write(_fd, _buf, _n)
+#define sysClose(_fd) close(_fd)
+#define sysAccess(_path, _mode) access(_path, _mode)
+#define sysStat(_path, _buf) stat(_path, _buf)
+#define sysMkdir(_path, _mode) mkdir(_path, _mode)
+#define sysUnlink(_path) unlink(_path)
+#define sysIsAbsolute(_path) (*(_path) == '/')
+#define sysCloseDir(_dir) closedir(_dir)
+#define sysOpenDir(_path) opendir(_path)
+#define sysRmdir(_dir) remove(_dir)
+#define sysSeek(fd, offset, whence) lseek(fd, offset, whence)
+#define sysRename(s, d) rename(s, d)
+
+#endif /*_SYSMACROS_MD_H_*/
diff --git a/MPC.3.5.LINUX/preverifier/tree.h b/MPC.3.5.LINUX/preverifier/tree.h
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * @(#)tree.h 1.3 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Definitions having to do with the program tree
+ */
+
+#ifndef _TREE_H_
+#define _TREE_H_
+
+#include "oobj.h" /* for the definition of unicode */
+#include "typecodes.h"
+
+extern int SkipSourceChecks;
+extern char *progname;
+extern ClassClass **binclasses;
+extern long nbinclasses, sizebinclasses;
+
+/* User specifiable attributes */
+#define ACC_PUBLIC 0x0001 /* visible to everyone */
+#define ACC_PRIVATE 0x0002 /* visible only to the defining class */
+#define ACC_PROTECTED 0x0004 /* visible to subclasses */
+#define ACC_STATIC 0x0008 /* instance variable is static */
+#define ACC_FINAL 0x0010 /* no further subclassing, overriding */
+#define ACC_SYNCHRONIZED 0x0020 /* wrap method call in monitor lock */
+#define ACC_SUPER 0x0020 /* funky handling of invokespecial */
+#define ACC_THREADSAFE 0x0040 /* can cache in registers */
+#define ACC_TRANSIENT 0x0080 /* not persistant */
+#define ACC_NATIVE 0x0100 /* implemented in C */
+#define ACC_INTERFACE 0x0200 /* class is an interface */
+#define ACC_ABSTRACT 0x0400 /* no definition provided */
+#define ACC_XXUNUSED1 0x0800 /* */
+
+#define ACC_WRITTEN_FLAGS 0x0FFF /* flags actually put in .class file */
+
+/* Other attributes */
+#define ACC_VALKNOWN 0x1000 /* constant with known value */
+#define ACC_DOCED 0x2000 /* documentation generated */
+#define ACC_MACHINE_COMPILED 0x4000 /* compiled to machine code */
+#define ACC_XXUNUSED3 0x8000 /* */
+
+#define IsPrivate(access) (((access) & ACC_PRIVATE) != 0)
+#define IsPublic(access) (((access) & ACC_PUBLIC) != 0)
+#define IsProtected(access) (((access) & ACC_PROTECTED) != 0)
+
+char *addstr(char *s, char *buf, char *limit, char term);
+char *addhex(long n, char *buf, char *limit);
+char *adddec(long n, char *buf, char *limit);
+
+#ifdef TRIMMED
+# undef DEBUG
+# undef STATS
+# define NOLOG
+#endif
+
+
+#endif /* !_TREE_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/typecodes.h b/MPC.3.5.LINUX/preverifier/typecodes.h
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * @(#)typecodes.h 1.2 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Type codes 6/12/91
+
+ This typecode system allows us to represent the type
+ of scalars in a uniform way. For instance, all integer types
+ have some bits in common, and are distinguished by a built-in
+ size field. Types without multiple sizes don't have a size field.
+
+ Scalars may only have sizes which are powers of 2. The size
+ field holds the log-based-2 of the object's size.
+
+ All run-time types can be encoded in 4 bits. There are more
+ compile- time types. These fit in 5 bits.
+ Schematically, we have:
+ +----+----+----+----+----+
+ | c | t | s |
+ +----+----+----+----+----+
+
+ Encoding is:
+ c t s type
+ -------------------------
+ 0 00 00 unassigned
+ 0 00 01 array
+ 0 00 10 class
+ 0 00 11 proxy (OBSOLETE)
+ 0 01 00 boolean (1 byte)
+ 0 01 01 char (2 bytes)
+ 0 01 1s float (single=1; double=2)
+ 0 1u xx integer (byte=0; short=1; int=2; long=3;
+ u=1 => unsigned)
+
+ For runtime types, the size of an object
+ is 1<<(t&3)
+
+ 1 00 00 typedef (compiler only)
+ 1 00 01 void (compiler only)
+ 1 00 10 func (compiler only)
+ 1 00 11 unknown (compiler only)
+ 1 01 00 error (compiler only)
+
+ Char and Boolean are not int's because they need a different signature,
+ so have to be distinguishable, even at runtime. We allow arrays
+ of objects, arrays(?), booleans, char, integers, and floats.
+ Note that the low-order two bits of all these gives the log of
+ the size, except for arrays, of course.
+
+ I would prefer not to have unsigned int in the language, but
+ don't want to make that decision at this level. We could come up
+ with a better encoding of boolean and char if there were no
+ unsigned.
+
+ The compile-only type values that could be confused with the
+ integer and float scalar types must not ever be used. Value 0 must
+ not be assigned a runtime type, as this is used for some sleazy
+ trickery in punning types and pointer. In fact, we even have a name
+ for it.
+*/
+
+/* If you change these typecodes, you'll have to fix the arrayinfo table
+ in gc.c and the {in,}direct_{load,store}_ops tables in
+ compiler/tree2code.c */
+
+#ifndef _TYPECODES_H_
+#define _TYPECODES_H_
+
+#define T_NORMAL_OBJECT 0
+#define T_XXUNUSEDXX1 1 /* Used to be T_ARRAY */
+#define T_CLASS 2
+#define T_BOOLEAN 4
+#define T_CHAR 5
+
+#define T_FLOATING 4 /* add log2 size to get correct code:
+ float has code 6,
+ double has code 7 */
+#define T_INTEGER 010
+#define T_UINTEGER 014
+
+#define T_MAXNUMERIC 020
+
+#define T_XXUNUSEDXX2 020
+#define T_VOID 021
+#define T_FUNC 022
+#define T_UNKNOWN 023
+#define T_ERROR 024
+
+/* for type construction */
+#define T_TMASK 034
+#define T_LMASK 003
+#define T_LSIZE 2
+#define T_MKTYPE( t, l ) ( ( (t)&T_TMASK ) | ( (l)&T_LMASK) )
+
+/* for type deconstruction */
+ /*
+ * Because we promise always to let ints and compile-only types be
+ * distinguished by the "t" and "s" bits above, we can simplify
+ * some of our predicates by masking out the "c" bit when testing
+ * for integers. Thus the T_TS_MASK...
+ */
+#define T_TS_MASK 034
+#define T_ISINTEGER(t) ( ((t)&030) == T_INTEGER )
+#define T_ISFLOATING(t) ( ((t)&036) == T_FLOAT )
+#define T_ISNUMERIC(t) ( (t) >= T_CHAR && (t) < T_MAXNUMERIC )
+#define T_SIZEFIELD(t) ((t)&T_LMASK)
+#define T_ELEMENT_SIZE(t) (1<<T_SIZEFIELD(t)) /* only for some!! */
+
+#define T_IS_BIG_TYPE(t) ((t == T_DOUBLE) || (t == T_LONG))
+#define T_TYPE_WORDS(t) (T_IS_BIG_TYPE(t) ? 2 : 1)
+
+/* nick-names for the usual scalar types */
+#define T_FLOAT T_MKTYPE(T_FLOATING,2)
+#define T_DOUBLE T_MKTYPE(T_FLOATING,3)
+#define T_BYTE T_MKTYPE(T_INTEGER,0)
+#define T_SHORT T_MKTYPE(T_INTEGER,1)
+#define T_INT T_MKTYPE(T_INTEGER,2)
+#define T_LONG T_MKTYPE(T_INTEGER,3)
+
+#ifdef NO_LONGER_USED
+/* We no longer support these types */
+#define T_UBYTE T_MKTYPE(T_UINTEGER,0)
+#define T_USHORT T_MKTYPE(T_UINTEGER,1)
+#define T_UINT T_MKTYPE(T_UINTEGER,2)
+#define T_ULONG T_MKTYPE(T_UINTEGER,3)
+
+#endif
+
+/* only a slight exaggeration */
+#define N_TYPECODES (1<<6)
+#define N_TYPEMASK (N_TYPECODES-1)
+
+#endif /* !_TYPECODES_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/typedefs.h b/MPC.3.5.LINUX/preverifier/typedefs.h
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * @(#)typedefs.h 1.4 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#include "typedefs_md.h" /* for int64_t */
+
+/*
+ * Macros to deal with the JavaVM's stack alignment. Many machines
+ * require doublewords to be double aligned. This union is used by
+ * code in math.h as a more portable way do alignment on machines
+ * that require it. This union and the macros that use it came from
+ * Netscape.
+ */
+
+typedef union Java8Str {
+ int32_t x[2];
+ double d;
+ int64_t l;
+ void *p;
+} Java8;
+
+
+#ifdef HAVE_ALIGNED_LONGLONGS
+#define GET_INT64(_t,_addr) ( ((_t).x[0] = ((int32_t*)(_addr))[0]), \
+ ((_t).x[1] = ((int32_t*)(_addr))[1]), \
+ (_t).l )
+#define SET_INT64(_t, _addr, _v) ( (_t).l = (_v), \
+ ((int32_t*)(_addr))[0] = (_t).x[0], \
+ ((int32_t*)(_addr))[1] = (_t).x[1] )
+#else
+#define GET_INT64(_t,_addr) (*(int64_t*)(_addr))
+#define SET_INT64(_t, _addr, _v) (*(int64_t*)(_addr) = (_v))
+#endif
+
+/* If double's must be aligned on doubleword boundaries then define this */
+#ifdef HAVE_ALIGNED_DOUBLES
+#define GET_DOUBLE(_t,_addr) ( ((_t).x[0] = ((int32_t*)(_addr))[0]), \
+ ((_t).x[1] = ((int32_t*)(_addr))[1]), \
+ (_t).d )
+#define SET_DOUBLE(_t, _addr, _v) ( (_t).d = (_v), \
+ ((int32_t*)(_addr))[0] = (_t).x[0], \
+ ((int32_t*)(_addr))[1] = (_t).x[1] )
+#else
+#define GET_DOUBLE(_t,_addr) (*(double*)(_addr))
+#define SET_DOUBLE(_t, _addr, _v) (*(double*)(_addr) = (_v))
+#endif
+
+/* If pointers are 64bits then define this */
+#ifdef HAVE_64BIT_POINTERS
+#define GET_HANDLE(_t,_addr) ( ((_t).x[0] = ((int32_t*)(_addr))[0]), \
+ ((_t).x[1] = ((int32_t*)(_addr))[1]), \
+ (_t).p )
+#define SET_HANDLE(_t, _addr, _v) ( (_t).p = (_v), \
+ ((int32_t*)(_addr))[0] = (_t).x[0], \
+ ((int32_t*)(_addr))[1] = (_t).x[1] )
+#else
+#define GET_HANDLE(_t,_addr) (*(JHandle*)(_addr))
+#define SET_HANDLE(_t, _addr, _v) (*(JHandle*)(_addr) = (_v))
+#endif
+
+#undef TRUE
+#undef FALSE
+
+typedef enum {
+ FALSE = 0,
+ TRUE = 1
+} bool_t;
+
+#endif /* !_TYPEDEFS_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/typedefs_md.h b/MPC.3.5.LINUX/preverifier/typedefs_md.h
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * @(#)typedefs_md.h 1.2 00/05/31
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TYPES_MD_H_
+#define _TYPES_MD_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef SOLARIS2
+/* don't redefine typedef's on Solaris 2.6 or Later */
+
+#if !defined(_ILP32) && !defined(_LP64)
+
+#ifndef _UINT64_T
+#define _UINT64_T
+typedef unsigned long long uint64_t;
+#define _UINT32_T
+typedef unsigned long uint32_t;
+#endif
+
+#ifndef _INT64_T
+#define _INT64_T
+typedef long long int64_t;
+#define _INT32_T
+typedef long int32_t;
+#endif
+
+#endif /* !defined(_ILP32) && !defined(_LP64) */
+#endif /* SOLARIS2 */
+
+#ifdef LINUX
+#ifndef _UINT64_T
+#define _UINT64_T
+typedef unsigned long long uint64_t;
+#define _UINT32_T
+typedef unsigned long uint32_t;
+#endif
+#endif /* LINUX */
+
+#ifdef WIN32
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+typedef long int32_t;
+typedef unsigned long uint32_t;
+typedef unsigned int uint_t;
+#endif
+
+/* use these macros when the compiler supports the long long type */
+
+#define ll_high(a) ((long)((a)>>32))
+#define ll_low(a) ((long)(a))
+#define int2ll(a) ((int64_t)(a))
+#define ll2int(a) ((int)(a))
+#define ll_add(a, b) ((a) + (b))
+#define ll_and(a, b) ((a) & (b))
+#define ll_div(a, b) ((a) / (b))
+#define ll_mul(a, b) ((a) * (b))
+#define ll_neg(a) (-(a))
+#define ll_not(a) (~(a))
+#define ll_or(a, b) ((a) | (b))
+#define ll_shl(a, n) ((a) << (n))
+#define ll_shr(a, n) ((a) >> (n))
+#define ll_sub(a, b) ((a) - (b))
+#define ll_ushr(a, n) ((unsigned long long)(a) >> (n))
+#define ll_xor(a, b) ((a) ^ (b))
+#define uint2ll(a) ((uint64_t)(unsigned long)(a))
+#define ll_rem(a,b) ((a) % (b))
+
+#define INT_OP(x,op,y) ((x) op (y))
+#define NAN_CHECK(l,r,x) x
+#define IS_NAN(x) isnand(x)
+
+
+/* On Intel these conversions have to be method calls and not typecasts.
+ See the win32 typedefs_md.h file */
+#if defined(i386) || defined (__i386)
+
+extern int32_t float2l(float f);
+extern int32_t double2l(double d);
+extern int64_t float2ll(float f);
+extern int64_t double2ll(double d);
+
+#else /* not i386 */
+
+#define float2l(f) (f)
+#define double2l(f) (f)
+#define float2ll(f) ((int64_t) (f))
+#define double2ll(f) ((int64_t) (f))
+
+#endif /* i386 */
+
+
+#define ll2float(a) ((float) (a))
+#define ll2double(a) ((double) (a))
+
+/* comparison operators */
+#define ll_ltz(ll) ((ll)<0)
+#define ll_gez(ll) ((ll)>=0)
+#define ll_eqz(a) ((a) == 0)
+#define ll_eq(a, b) ((a) == (b))
+#define ll_ne(a,b) ((a) != (b))
+#define ll_ge(a,b) ((a) >= (b))
+#define ll_le(a,b) ((a) <= (b))
+#define ll_lt(a,b) ((a) < (b))
+#define ll_gt(a,b) ((a) > (b))
+
+#define ll_zero_const ((int64_t) 0)
+#define ll_one_const ((int64_t) 1)
+
+extern void ll2str(int64_t a, char *s, char *limit);
+
+#ifdef ppc
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#endif
+
+#ifdef SOLARIS2
+#include <sys/byteorder.h>
+#endif
+
+#ifdef LINUX
+#include <asm/byteorder.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#endif /* !_TYPES_MD_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/utf.c b/MPC.3.5.LINUX/preverifier/utf.c
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * @(#)utf.c 1.5 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Unicode translators.
+ * FILE: utf.c
+ * OVERVIEW: Routines for Unicode -> UTF and UTF -> unicode translators.
+ *
+ * This file implements the unicode -> UTF and UTF -> unicode translators
+ * needed by the various parts of the compiler and interpreter.
+ *
+ * UTF strings are streams of bytes, in which unicode characters are encoded
+ * as follows:
+ * Unicode UTF
+ * 00000000 0jklmnop 0jklmnop
+ * 00000fgh ijklmnop 110fghij 10klmnop
+ * abcdefgh ijklmnop 1110abcd 10efghij 10klmnop
+ *
+ * unicode bytes with 7 or fewer significant bits MUST be converted using the
+ * first format. bytes with 11 or fewer bits MUST be converted using the
+ * second format.
+ *
+ * In JAVA/JAVAC, we deviate slightly from the above.
+ * 1) The null unicode character is represented using the 2-byte format
+ * 2) All UTF strings are null-terminated.
+ * In this way, we do not need to separately maintain a length field for the
+ * UTF string.
+ *
+ * Given a unicode string and its length, convert it to a utf string. But
+ * the result into the given buffer, whose length is buflength. The utf
+ * string should include a null terminator.
+ *
+ * If both buffer and buflength are 0, then malloc an appropriately sized
+ * buffer for the result.
+ *
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Edited by Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "oobj.h"
+#include "utf.h"
+#include "sys_api.h"
+
+char *unicode2utf(unicode *unistring, int length, char *buffer, int buflength)
+{
+ int i;
+ unicode *uniptr;
+ char *bufptr;
+ unsigned bufleft;
+
+ if ((buffer == 0) && (buflength == 0)) {
+ buflength = unicode2utfstrlen(unistring, length);
+ if ((buffer = (char *) sysMalloc(buflength)) == 0)
+ return 0;
+ }
+
+ bufleft = buflength - 1; /* take note of null now! */
+
+ for(i = length, uniptr = unistring, bufptr = buffer; --i >= 0; uniptr++) {
+ unicode ch = *uniptr;
+ if ((ch != 0) && (ch <=0x7f)) {
+ if ((int)(--bufleft) < 0) /* no space for character */
+ break;
+ *bufptr++ = (char)ch;
+ } else if (ch <= 0x7FF) {
+ /* 11 bits or less. */
+ unsigned char high_five = ch >> 6;
+ unsigned char low_six = ch & 0x3F;
+ if ((int)(bufleft -= 2) < 0) /* no space for character */
+ break;
+ *bufptr++ = high_five | 0xC0; /* 110xxxxx */
+ *bufptr++ = low_six | 0x80; /* 10xxxxxx */
+ } else {
+ /* possibly full 16 bits. */
+ char high_four = ch >> 12;
+ char mid_six = (ch >> 6) & 0x3F;
+ char low_six = ch & 0x3f;
+ if ((int)(bufleft -= 3) < 0) /* no space for character */
+ break;
+ *bufptr++ = high_four | 0xE0; /* 1110xxxx */
+ *bufptr++ = mid_six | 0x80; /* 10xxxxxx */
+ *bufptr++ = low_six | 0x80; /* 10xxxxxx*/
+ }
+ }
+ *bufptr = 0;
+ return buffer;
+}
+
+/* Return the number of characters that would be needed to hold the unicode
+ * string in utf. This INCLUDES the NULL!
+ */
+int unicode2utfstrlen(unicode *unistring, int unilength)
+{
+ int result_length = 1;
+
+ for (; unilength > 0; unistring++, unilength--) {
+ unicode ch = *unistring;
+ if ((ch != 0) && (ch <= 0x7f)) /* 1 byte */
+ result_length++;
+ else if (ch <= 0x7FF)
+ result_length += 2; /* 2 byte character */
+ else
+ result_length += 3; /* 3 byte character */
+ }
+ return result_length;
+}
+
+/* Give the number of unicode characters in a utf string */
+int utfstrlen(char *utfstring)
+{
+ int length;
+ for (length = 0; *utfstring != 0; length++)
+ next_utf2unicode(&utfstring);
+ return length;
+}
+
+/* Convert a utfstring to unicode in the buffer provided. Put at most
+ * max_length characters into the buffer. Whether or not we actually overflow
+ * the space, indicate the actual unicode length.
+ *
+ * Whether or not we overflow the space, return the actual number of
+ * characters that we used.
+ */
+
+void
+utf2unicode(char *utfstring, unicode *unistring,
+ int max_length, int *lengthp)
+{
+ int length_remaining = max_length;
+
+ while (length_remaining > 0 && *utfstring != 0) {
+ *unistring++ = next_utf2unicode(&utfstring);
+ length_remaining--;
+ }
+
+ if (length_remaining == 0) {
+ *lengthp = max_length + utfstrlen(utfstring);
+ } else {
+ *lengthp = max_length - length_remaining;
+ }
+}
+
+bool_t is_simple_utf(char *utfstring)
+{
+ unsigned char *ptr;
+ for (ptr = (unsigned char *)utfstring; *ptr != 0; ptr++) {
+ if (*ptr > 0x80) return FALSE;
+ }
+ return TRUE;
+}
+
+
+unicode next_utf2unicode(char **utfstring_ptr) {
+ unsigned char *ptr = (unsigned char *)(*utfstring_ptr);
+ unsigned char ch, ch2, ch3;
+ int length = 1; /* default length */
+ unicode result = 0x80; /* default bad result; */
+ switch ((ch = ptr[0]) >> 4) {
+ default:
+ result = ch;
+ break;
+
+ case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
+ /* Shouldn't happen. */
+ break;
+
+ case 0xC: case 0xD:
+ /* 110xxxxx 10xxxxxx */
+ if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
+ unsigned char high_five = ch & 0x1F;
+ unsigned char low_six = ch2 & 0x3F;
+ result = (high_five << 6) + low_six;
+ length = 2;
+ }
+ break;
+
+ case 0xE:
+ /* 1110xxxx 10xxxxxx 10xxxxxx */
+ if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
+ if (((ch3 = ptr[2]) & 0xC0) == 0x80) {
+ unsigned char high_four = ch & 0x0f;
+ unsigned char mid_six = ch2 & 0x3f;
+ unsigned char low_six = ch3 & 0x3f;
+ result = (((high_four << 6) + mid_six) << 6) + low_six;
+ length = 3;
+ } else {
+ length = 2;
+ }
+ }
+ break;
+ } /* end of switch */
+
+ *utfstring_ptr = (char *)(ptr + length);
+ return result;
+}
diff --git a/MPC.3.5.LINUX/preverifier/utf.h b/MPC.3.5.LINUX/preverifier/utf.h
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * @(#)utf.h 1.2 02/09/27
+ *
+ * Copyright 1995-1998 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Prototypes for the various UTF support functions.
+ */
+
+#ifndef _UTF_H_
+#define _UTF_H_
+
+char *unicode2utf(unicode *unistring, int length, char *buffer, int buflength);
+int unicode2utfstrlen(unicode *unistring, int unilength);
+int utfstrlen(char *utfstring);
+void utf2unicode(char *utfstring, unicode *unistring,
+ int max_length, int *lengthp);
+bool_t is_simple_utf(char *utfstring);
+
+unicode next_utf2unicode(char **utfstring);
+
+#endif /* !_UTF_H_ */
diff --git a/MPC.3.5.LINUX/preverifier/util.c b/MPC.3.5.LINUX/preverifier/util.c
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ * @(#)util.c 1.7 02/09/27
+ *
+ * Copyright 1995-1999 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information"). You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
+ * Use is subject to license terms.
+ */
+
+/*=========================================================================
+ * SYSTEM: Verifier
+ * SUBSYSTEM: Utility functions.
+ * FILE: util.c
+ * OVERVIEW: Utility routines needed by both the compiler and the interpreter.
+ *
+ * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
+ * Edited by Tasneem Sayeed, Sun Microsystems
+ *=======================================================================*/
+
+/*=========================================================================
+ * Include files
+ *=======================================================================*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#include "oobj.h"
+#include "utf.h"
+#include "sys_api.h"
+#include "path.h" /* DIR_SEPARATOR */
+
+/*=========================================================================
+ * Globals and extern declarations
+ *=======================================================================*/
+
+extern struct StrIDhash *nameTypeHash;
+extern struct StrIDhash *stringHash;
+
+unicode *
+str2unicode(char *str, unicode *ustr, long len)
+{
+ unicode *dst = ustr;
+
+ memset((char *) dst, 0, len * sizeof(*dst));
+ while (*str && --len >= 0)
+ *ustr++ = 0xff & *str++;
+ return dst;
+}
+
+void
+unicode2str(unicode *src, char *dst, long len)
+{
+ while (--len >= 0)
+ *dst++ = (char)(*src++);
+ *dst = '\0';
+}
+
+
+int
+jio_printf (const char *format, ...)
+{
+ int len;
+
+ va_list args;
+ va_start(args, format);
+ len = jio_vfprintf(stdout, format, args);
+ va_end(args);
+
+ return len;
+}
+
+int
+jio_fprintf (FILE *handle, const char *format, ...)
+{
+ int len;
+
+ va_list args;
+ va_start(args, format);
+ len = jio_vfprintf(handle, format, args);
+ va_end(args);
+
+ return len;
+}
+
+int
+jio_vfprintf (FILE *handle, const char *format, va_list args)
+{
+ return vfprintf(handle, format, args);
+}
+
+
+/*
+ * Print s null terminated C-style character string.
+ */
+void
+prints(char *s)
+{
+ jio_fprintf(stdout, "%s", s);
+}
+
+#undef HTSIZE /* Avoid conflict on PC */
+#define HTSIZE 2003 /* Default size -- must be prime */
+#define HTOVERFLOWPOINT(h) (h->size * 4 / 5)
+
+/*
+ * We store most of the result of the hash in hash_bits to quickly
+ * reject impossible matches because strcmp() is fairly expensive,
+ * especially when many strings will have common prefixes.
+ */
+typedef struct {
+ char *hash; /* the string for this entry */
+ unsigned is_malloced : 1; /* 1 if hash was malloced */
+ unsigned hash_bits : 31; /* low 31 bits of the hash */
+} StrIDhashSlot;
+
+typedef void (*hash_fn)(const char *s, unsigned *h1, unsigned *h2);
+
+typedef struct StrIDhash {
+ int size; /* number of entries */
+ hash_fn hash; /* hash function for this table */
+ struct StrIDhash *next; /* next bucket */
+ short used; /* number of full entries */
+ short baseid; /* ID for item in slot[0] */
+ void **params; /* param table, if needed */
+ StrIDhashSlot slot[1]; /* expanded to be number of slots */
+} StrIDhash;
+
+/* Hash a string into a primary and secondary hash value */
+static void
+default_hash(const char *s, unsigned *h1, unsigned *h2)
+{
+ int i;
+ unsigned raw_hash;
+ for (raw_hash = 0; (i = *s) != '\0'; ++s)
+
+ raw_hash = raw_hash * 37 + i;
+ *h1 = raw_hash;
+ *h2 = (raw_hash & 7) + 1; /* between 1 and 8 */
+}
+
+/* Create a hash table of the specified size */
+static StrIDhash *
+createHash(int entries)
+{
+ StrIDhash *h;
+ int size = offsetof(struct StrIDhash, slot) + (entries * sizeof(h->slot));
+ h = (StrIDhash *)sysCalloc(1, size);
+ if (h != NULL) {
+ h->size = entries;
+ h->hash = default_hash; /* only custom tables get something else */
+ h->next = NULL;
+ }
+ return h;
+}
+
+/*
+ * Given a string, return a unique 16 bit id number.
+ * If param isn't null, we also set up an array of void * for holding info
+ * about each object. The address of this void * is stored into param
+ * If CopyNeeded is true, then the name argument "s" must be dup'ed, since
+ * the current item is allocated on the stack.
+ *
+ * Note about returning 0 in the case of out of memory errors: 0 is *not*
+ * a valid ID! The out of memory error should be thrown by the calling code.
+ */
+unsigned short
+Str2ID(StrIDhash **hash_ptr, register char *s, void ***param,
+ int CopyNeeded)
+{
+ /*
+ * The database is a hash table. When the hash table overflows, a new
+ * hashtable is created chained onto the previous one. This is done so
+ * that we can use the hashtable slot index as the ID, without worrying
+ * about having the IDs change when the hashtable grows.
+ */
+ StrIDhash *h = *hash_ptr;
+ long i;
+ unsigned primary_hash;
+ unsigned secondary_hash;
+ unsigned hash_bits;
+ hash_fn current_hash_func = NULL;
+
+ if (h == NULL)
+ goto not_found;
+
+ /* Create the hash values */
+ current_hash_func = h->hash;
+ current_hash_func(s, &primary_hash, &secondary_hash);
+ hash_bits = primary_hash & ((1u << 31) - 1);
+
+ for (;;) {
+ char *s2;
+ int bucketSize = h->size;
+
+ /* See if the new hash table has a different hash function */
+ if (h->hash != current_hash_func) {
+ current_hash_func = h->hash;
+ current_hash_func(s, &primary_hash, &secondary_hash);
+ hash_bits = primary_hash & ((1u << 31) - 1);
+ }
+ i = primary_hash % bucketSize;
+
+ while ((s2 = h->slot[i].hash) != NULL) {
+ if (h->slot[i].hash_bits == hash_bits && strcmp(s2, s) == 0)
+ goto found_it;
+ if ((i -= secondary_hash) < 0)
+ i += bucketSize;
+ }
+ /* Not found in this table. Try the next table. */
+ if (h->next == NULL)
+ break;
+ h = h->next;
+ }
+
+not_found:
+ /* Either the hash table is empty, or the item isn't yet found. */
+ if (h == NULL || (h->used >= HTOVERFLOWPOINT(h))) {
+ /* Need to create a new bucket */
+ StrIDhash *next;
+ if (h && h->baseid > 30000 && *hash_ptr != stringHash) {
+ panic("16-bit string hash table overflow");
+ }
+ next = createHash(HTSIZE);
+ if (next == NULL) {
+ /* Calling code should signal OutOfMemoryError */
+ return 0;
+ }
+ if (h == NULL) {
+ /* Create a new table */
+ *hash_ptr = h = next;
+ h->baseid = 1; /* guarantee that no ID is 0 */
+ } else {
+ next->baseid = h->baseid + h->size;
+ h->next = next;
+ h = next;
+ }
+ if (h->hash != current_hash_func) {
+ current_hash_func = h->hash;
+ current_hash_func(s, &primary_hash, &secondary_hash);
+ hash_bits = primary_hash & ((1u << 31) - 1);
+ }
+ i = primary_hash % h->size;
+ }
+ if (CopyNeeded) {
+ char *d = strdup(s);
+ if (d == NULL) {
+ /* Calling code should signal OutOfMemoryError */
+ return 0;
+ }
+ s = d;
+ h->slot[i].is_malloced = 1;
+ }
+ h->slot[i].hash = s;
+ h->slot[i].hash_bits = hash_bits;
+ h->used++;
+
+found_it:
+ /* We have found or created slot "i" in hash bucket "h" */
+ if (param != NULL) {
+ if (h->params == NULL) {
+ h->params = sysCalloc(h->size, sizeof(void *));
+ if (h->params == NULL) {
+ /* Calling code should signal OutOfMemoryError */
+ return 0;
+ }
+ }
+ *param = &(h->params[i]);
+ }
+ return (unsigned short)(h->baseid + i);
+}
+
+/* Free an StrIDhash table and all the entries in it */
+void Str2IDFree(StrIDhash **hash_ptr)
+{
+ StrIDhash *hash = *hash_ptr;
+
+ while (hash != NULL) {
+ StrIDhash *next = hash->next;
+ StrIDhashSlot *ptr, *endPtr;
+ for (ptr = &hash->slot[0], endPtr = ptr + hash->size;
+ ptr < endPtr; ptr++) {
+ if (ptr->is_malloced)
+ sysFree(ptr->hash);
+ }
+ if (hash->params != NULL)
+ sysFree(hash->params);
+ sysFree(hash);
+ hash = next;
+ }
+ *hash_ptr = 0;
+}
+
+/*
+ * Call the callback function on every entry in the table. This
+ * should only be invoked holding the string hash table lock.
+ */
+void Str2IDCallback(StrIDhash **hash_ptr, void (*callback)(char *, void *))
+{
+ StrIDhash *hash, *next;
+ int i;
+
+ hash = *hash_ptr;
+ while (hash) {
+ void **params = hash->params;
+ next = hash->next;
+ for (i = 0; i < hash->size; i++) {
+ if (hash->slot[i].hash != 0) {
+ callback(hash->slot[i].hash, params ? params[i] : NULL);
+ }
+ }
+ hash = next;
+ }
+}
+
+/*
+ * Returns NULL in the case of an error.
+ */
+char *
+ID2Str(StrIDhash *h, unsigned short ID, void ***param)
+{
+ int entry;
+
+ while ((long)(ID - h->baseid) >= h->size) {
+ h = h->next;
+ }
+ entry = ID - h->baseid;
+ if (param != NULL) {
+ if (h->params == NULL) {
+ h->params = (void **)sysCalloc(h->size, sizeof(*param));
+ if (h->params == NULL) {
+ /* Calling code should signal OutOfMemoryError */
+ return NULL;
+ }
+ }
+ *param = &h->params[entry];
+ }
+ return h->slot[entry].hash;
+}
+
+char *
+addstr(char *s, char *buf, char *limit, char term)
+{
+ char c;
+ while ((c = *s) && c != term && buf < limit) {
+ *buf++ = c;
+ s++;
+ }
+ return buf;
+}
+
+char *
+unicode2rd(unicode *s, long len)
+{ /* unicode string to readable C string */
+#define CSTRLEN 40
+ static char buf[CSTRLEN+1];
+ char *dp = buf;
+ int c;
+ if (s == 0)
+ return "NULL";
+ *dp++ = '"';
+ while (--len>=0 && (c = *s++) != 0 && dp < buf + sizeof buf - 10)
+ if (040 <= c && c < 0177)
+ *dp++ = c;
+ else
+ switch (c) {
+ case '\n':
+ *dp++ = '\\';
+ *dp++ = 'n';
+ break;
+ case '\t':
+ *dp++ = '\\';
+ *dp++ = 't';
+ break;
+ case '\r':
+ *dp++ = '\\';
+ *dp++ = 'r';
+ break;
+ case '\b':
+ *dp++ = '\\';
+ *dp++ = 'b';
+ break;
+ case '\f':
+ *dp++ = '\\';
+ *dp++ = 'f';
+ break;
+ default:
+ /* Should not be possible to overflow, truncate if so */
+ (void) jio_snprintf(dp, CSTRLEN+1 - (dp - buf), "\\%X", c);
+ dp += strlen(dp);
+ break;
+ }
+ *dp++ = '"';
+ if (len >= 0 && c != 0)
+ *dp++ = '.', *dp++ = '.', *dp++ = '.';
+ *dp++ = 0;
+ return buf;
+}
+
+/*
+ * WARNING: out_of_memory() aborts the runtime! It should not be used
+ * except in the case of out of memory situations that are clearly not
+ * survivable, like running out of memory before the runtime is initialized.
+ * If the runtime has finished initializing and you run out of memory, you
+ * should throw an OutOfMemoryError instead.
+ */
+void
+out_of_memory()
+{
+ jio_fprintf(stderr, "**Out of memory, exiting**\n");
+ exit(1);
+}
+
+void
+panic(const char *format, ...)
+{
+ va_list ap;
+ char buf[256];
+
+ printCurrentClassName();
+ va_start(ap, format);
+
+ /* If buffer overflow, quietly truncate */
+ (void) jio_vsnprintf(buf, sizeof(buf), format, ap);
+
+ jio_fprintf(stdout, "\nERROR: %s\n", buf);
+
+ exit(1);
+}
+
+char *
+classname2string(char *src, char *dst, int size) {
+ char *buf = dst;
+ for (; (--size > 0) && (*src != '\0') ; src++, dst++) {
+ if (*src == '/') {
+ *dst = '.';
+ } else {
+ *dst = *src;
+ }
+ }
+ *dst = '\0';
+ return buf;
+}
+
+typedef struct InstanceData {
+ char *buffer;
+ char *end;
+} InstanceData;
+
+#define ERROR_RETVAL -1
+#undef SUCCESS
+#define SUCCESS 0
+#undef CheckRet
+#define CheckRet(x) { if ((x) == ERROR_RETVAL) return ERROR_RETVAL; }
+
+static int
+put_char(InstanceData *this, int c)
+{
+ if (iscntrl(0xff & c) && c != '\n' && c != '\t') {
+ c = '@' + (c & 0x1F);
+ if (this->buffer >= this->end) {
+ return ERROR_RETVAL;
+ }
+ *this->buffer++ = '^';
+ }
+ if (this->buffer >= this->end) {
+ return ERROR_RETVAL;
+ }
+ *this->buffer++ = c;
+ return SUCCESS;
+}
+
+static int
+format_string(InstanceData *this, char *str, int left_justify, int min_width,
+ int precision)
+{
+ int pad_length;
+ char *p;
+
+ if (str == 0) {
+ return ERROR_RETVAL;
+ }
+
+ if ((int)strlen(str) < precision) {
+ pad_length = min_width - strlen(str);
+ } else {
+ pad_length = min_width - precision;
+ }
+ if (pad_length < 0)
+ pad_length = 0;
+ if (left_justify) {
+ while (pad_length > 0) {
+ CheckRet(put_char(this, ' '));
+ --pad_length;
+ }
+ }
+
+ for (p = str; *p != '\0' && --precision >= 0; p++) {
+ CheckRet(put_char(this, *p));
+ }
+
+ if (!left_justify) {
+ while (pad_length > 0) {
+ CheckRet(put_char(this, ' '));
+ --pad_length;
+ }
+ }
+ return SUCCESS;
+}
+
+#define MAX_DIGITS 32
+
+static int
+format_number(InstanceData *this, long value, int format_type, int left_justify,
+ int min_width, int precision, bool_t zero_pad)
+{
+ int sign_value = 0;
+ unsigned long uvalue;
+ char convert[MAX_DIGITS+1];
+ int place = 0;
+ int pad_length = 0;
+ static char digits[] = "0123456789abcdef";
+ int base = 0;
+ bool_t caps = FALSE;
+ bool_t add_sign = FALSE;
+
+ switch (format_type) {
+ case 'o': case 'O':
+ base = 8;
+ break;
+ case 'd': case 'D':
+ add_sign = TRUE; /* fall through */
+ case 'u': case 'U':
+ base = 10;
+ break;
+ case 'X':
+ caps = TRUE; /* fall through */
+ case 'x':
+ base = 16;
+ break;
+ }
+ sysAssert(base > 0 && base <= 16);
+
+ uvalue = value;
+ if (add_sign) {
+ if (value < 0) {
+ sign_value = '-';
+ uvalue = -value;
+ }
+ }
+
+ do {
+ convert[place] = digits[uvalue % (unsigned)base];
+ if (caps) {
+ convert[place] = toupper(convert[place]);
+ }
+ place++;
+ uvalue = (uvalue / (unsigned)base);
+ if (place > MAX_DIGITS) {
+ return ERROR_RETVAL;
+ }
+ } while(uvalue);
+ convert[place] = 0;
+
+ pad_length = min_width - place;
+ if (pad_length < 0) {
+ pad_length = 0;
+ }
+ if (left_justify) {
+ if (zero_pad && pad_length > 0) {
+ if (sign_value) {
+ CheckRet(put_char(this, sign_value));
+ --pad_length;
+ sign_value = 0;
+ }
+ while (pad_length > 0) {
+ CheckRet(put_char(this, '0'));
+ --pad_length;
+ }
+ } else {
+ while (pad_length > 0) {
+ CheckRet(put_char(this, ' '));
+ --pad_length;
+ }
+ }
+ }
+ if (sign_value) {
+ CheckRet(put_char(this, sign_value));
+ }
+
+ while (place > 0 && --precision >= 0) {
+ CheckRet(put_char(this, convert[--place]));
+ }
+
+ if (!left_justify) {
+ while (pad_length > 0) {
+ CheckRet(put_char(this, ' '));
+ --pad_length;
+ }
+ }
+ return SUCCESS;
+}
+
+int
+jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ char *strvalue;
+ long value;
+ InstanceData this;
+ bool_t left_justify, zero_pad, long_flag, add_sign, fPrecision;
+ int min_width, precision, ch;
+
+ if (str == NULL) {
+ return ERROR_RETVAL;
+ }
+ str[0] = '\0';
+
+ this.buffer = str;
+ this.end = str + count - 1;
+ *this.end = '\0'; /* ensure null-termination in case of failure */
+
+ while ((ch = *fmt++) != 0) {
+ if (ch == '%') {
+ zero_pad = long_flag = add_sign = fPrecision = FALSE;
+ left_justify = TRUE;
+ min_width = 0;
+ precision = this.end - this.buffer;
+ next_char:
+ ch = *fmt++;
+ switch (ch) {
+ case 0:
+ return ERROR_RETVAL;
+ case '-':
+ left_justify = FALSE;
+ goto next_char;
+ case '0': /* set zero padding if min_width not set */
+ if (min_width == 0)
+ zero_pad = TRUE;
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ if (fPrecision == TRUE) {
+ precision = precision * 10 + (ch - '0');
+ } else {
+ min_width = min_width * 10 + (ch - '0');
+ }
+ goto next_char;
+ case '.':
+ fPrecision = TRUE;
+ precision = 0;
+ goto next_char;
+ case 'l':
+ long_flag = TRUE;
+ goto next_char;
+ case 's':
+ strvalue = va_arg(args, char *);
+ CheckRet(format_string(&this, strvalue, left_justify,
+ min_width, precision));
+ break;
+ case 'c':
+ ch = va_arg(args, int);
+ CheckRet(put_char(&this, ch));
+ break;
+ case '%':
+ CheckRet(put_char(&this, '%'));
+ break;
+ case 'd': case 'D':
+ case 'u': case 'U':
+ case 'o': case 'O':
+ case 'x': case 'X':
+ value = long_flag ? va_arg(args, long) : va_arg(args, int);
+ CheckRet(format_number(&this, value, ch, left_justify,
+ min_width, precision, zero_pad));
+ break;
+ default:
+ return ERROR_RETVAL;
+ }
+ } else {
+ CheckRet(put_char(&this, ch));
+ }
+ }
+ *this.buffer = '\0';
+ return strlen(str);
+}
+
+int
+jio_snprintf(char *str, size_t count, const char *fmt, ...)
+{
+ va_list args;
+ int len;
+
+ va_start(args, fmt);
+ len = jio_vsnprintf(str, count, fmt, args);
+ va_end(args);
+ return len;
+}
+
+/* Return true if the two classes are in the same class package */
+
+bool_t
+IsSameClassPackage(ClassClass *class1, ClassClass *class2)
+{
+ if (cbLoader(class1) != cbLoader(class2))
+ return FALSE;
+ else {
+ char *name1 = cbName(class1);
+ char *name2 = cbName(class2);
+ char *last_slash1 = strrchr(name1, DIR_SEPARATOR);
+ char *last_slash2 = strrchr(name2, DIR_SEPARATOR);
+ if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
+ /* One of the two doesn't have a package. Only return true
+ * if the other one also doesn't have a package. */
+ return (last_slash1 == last_slash2);
+ } else {
+ int length1, length2;
+ if (*name1 == SIGNATURE_ARRAY) {
+ do name1++; while (*name1 == SIGNATURE_ARRAY);
+ if (*name1 != SIGNATURE_CLASS) {
+ /* Something is terribly wrong. Shouldn't be here */
+ return FALSE;
+ }
+ name1++;
+ }
+ if (*name2 == SIGNATURE_ARRAY) {
+ do name2++; while (*name2 == SIGNATURE_ARRAY);
+ if (*name2 != SIGNATURE_CLASS) {
+ /* Something is terribly wrong. Shouldn't be here */
+ return FALSE;
+ }
+ name2++;
+ }
+ length1 = last_slash1 - name1;
+ length2 = last_slash2 - name2;
+ return ((length1 == length2)
+ && (strncmp(name1, name2, length1) == 0));
+ }
+ }
+}
diff --git a/MPC.3.5.LINUX/readme.txt b/MPC.3.5.LINUX/readme.txt
--- /dev/null
+++ b/MPC.3.5.LINUX/readme.txt
@@ -0,0 +1,10 @@
+This is the official MIDletPascal 3.5 compiler source code.
+
+To read the enhancements, adjustments, modifications and bugfixes that I made check the header comments of the main/main.c file.
+
+To get it working use Code::Blocks 8.02 (http://www.codeblocks.org/) and GCC.
+
+Enjoy,
+
+Javier Santo Domingo
+02.february.2013
diff --git a/MPC.3.5.LINUX/structures/block.c b/MPC.3.5.LINUX/structures/block.c
--- /dev/null
@@ -0,0 +1,3040 @@
+/********************************************************************
+
+ block.h - structures and functions used to hold program
+ block descriptions
+
+ Niksa Orlic, 2004-04-29
+
+********************************************************************/
+
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "../classgen/bytecode.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "unit.h"
+#include "block.h"
+#include "../classgen/preverify.h"
+
+#include "../util/memory.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../classgen/constant_pool.h"
+#include "../classgen/classgen.h"
+
+extern int linenum;
+extern int new_linenum;
+extern block* root_block;
+extern char *global_library_directory;
+extern char *project_library_directory;
+
+extern char *user_libraries;
+extern char **units;
+
+extern int detect_units_only;
+
+extern constant_pool *constants;
+extern int constant_pool_size;
+
+extern int usesFloat;
+extern int usesRecordStore;
+extern int usesHttp;
+
+extern int canvasType;
+
+extern int mathType;
+
+extern int compiling_unit;
+extern string* str_program_name;
+
+extern char* output_path;
+
+#pragma warning (disable:4305)
+#pragma warning (disable:4761)
+
+/*
+ Create an empty block
+*/
+block* block_create(block *parent_block, string *block_name)
+{
+ block *new_block;
+ new_block = (block*) mem_alloc(sizeof(block));
+
+ new_block->names = name_table_create();
+ new_block->parent_block = parent_block;
+ new_block->block_name = block_name; /* do not copy the name, just point to it */
+
+ new_block->next_variable_index = 0;
+ new_block->next_parameter_index = 0;
+
+ new_block->code = bytecode_create();
+
+ new_block->children_count = 0;
+
+ return new_block;
+}
+
+
+/*
+ Delete a block
+*/
+void block_destroy(block *item)
+{
+ int i;
+ name_table_destroy(item->names);
+ bytecode_destroy(item->code);
+
+ /* delete all of its children */
+ for(i=0; i<item->children_count; i++)
+ {
+ block_destroy(item->children[i]);
+ }
+
+ if (item->children_count > 0)
+ {
+ mem_free(item->children);
+ }
+
+ /* do not delete the item->block_name */
+ mem_free(item);
+}
+
+
+/*
+ Check if a given name is legal name for a
+ new identifier in a block.
+*/
+int block_check_name(block *item, char *cstr)
+{
+ int return_value = 1;
+
+ string *name;
+ identifier *descriptor;
+ name = string_from_cstr(cstr);
+
+ descriptor = name_table_find(item->names, name);
+
+ if (descriptor != NULL)
+ {
+ if (((descriptor->identifier_class == procedure_name)
+ || (descriptor->identifier_class == function_name))
+ && (descriptor->forward_declaration == 1))
+ return_value = 1;
+ else
+ return_value = 0;
+ }
+
+ /* check the root block's types - those types are protected */
+ if (return_value == 1)
+ {
+ while (item->parent_block != NULL)
+ item = item->parent_block;
+
+ descriptor = name_table_find(item->names, name);
+
+ if ((descriptor != NULL) && (descriptor->identifier_class == type_name))
+ return_value = 0;
+ }
+
+ string_destroy(name);
+
+ return return_value;
+}
+
+/*
+ Adds a single real constant into the block
+*/
+void add_real_constant(block *item, float value, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = constant_name;
+ descriptor->constant_type = type_create();
+ descriptor->constant_type->type_class = real_type;
+ descriptor->constant_real_value = value;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds a single integer constant into the block
+*/
+void add_integer_constant(block *item, long int value, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = constant_name;
+ descriptor->constant_type = type_create();
+ descriptor->constant_type->type_class = integer_type;
+ descriptor->constant_int_value = value;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds a single character constant into the block
+*/
+void add_char_constant(block *item, char value, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = constant_name;
+ descriptor->constant_type = type_create();
+ descriptor->constant_type->type_class = char_type;
+ descriptor->constant_int_value = value;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds a single boolean constant into the block
+*/
+void add_boolean_constant(block *item, char value, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = constant_name;
+ descriptor->constant_type = type_create();
+ descriptor->constant_type->type_class = boolean_type;
+ descriptor->constant_int_value = value;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds a single string constant into the block
+*/
+void add_string_constant(block *item, string *value, char *cstr_name)
+{
+ string *name;
+ identifier *descriptor;
+
+ name = string_from_cstr(cstr_name);
+ descriptor = identifier_create();
+ descriptor->identifier_class = constant_name;
+ descriptor->constant_type = type_create();
+ descriptor->constant_type->type_class = string_type;
+ descriptor->constant_string_value = string_duplicate(value);
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds variables into a block. The variable names are
+ located inside a string list, and a type for all
+ the variables is described in var_type parameter.
+*/
+void add_variables(block *item, string_list *identifier_list, type *var_type)
+{
+ string_list *it;
+ identifier *descriptor;
+ identifier *block_identifier;
+
+ it = identifier_list;
+
+ if (it->data == NULL)
+ {
+ type_destroy(var_type);
+ return;
+ }
+
+ if(item->parent_block != root_block)
+ {
+ block_identifier = name_table_find(item->parent_block->names, item->block_name);
+ if (block_identifier->variables == NULL)
+ block_identifier->variables = type_list_create();
+ }
+ else
+ block_identifier = NULL;
+
+ while (it != NULL)
+ {
+ // j-a-s-d: consecutive variable name collision fix
+ if (!block_check_name(item, it->data->cstr))
+ {
+ add_error_message(400, it->data->cstr, "");
+ }
+ descriptor = identifier_create();
+ descriptor->identifier_class = variable_name;
+ descriptor->variable_type = type_duplicate(var_type);
+ descriptor->variable_index = item->next_variable_index;
+ descriptor->belongs_to_program_block = (item->parent_block == root_block);
+ name_table_insert(item->names, string_duplicate(it->data), descriptor);
+
+ if (compiling_unit == 0)
+ initialize_variable(item, descriptor, it->data->cstr, 1, "M");
+ else
+ initialize_variable(item, descriptor, it->data->cstr, 1, string_get_cstr(str_program_name));
+
+ if (block_identifier != NULL)
+ type_list_append(block_identifier->variables, descriptor->variable_type);
+
+ item->next_variable_index ++;
+
+ it = it->next;
+ }
+
+}
+
+/*
+ Add a type into block. The name and type_type
+ are NOT copied.
+*/
+void add_type(block *item, string *name, type *type_type)
+{
+ identifier *descriptor;
+
+ descriptor = identifier_create();
+ descriptor->identifier_class = type_name;
+ descriptor->defined_type = type_type;
+ name_table_insert(item->names, name, descriptor);
+}
+
+
+/*
+ Adds a procedure declaration into the block
+*/
+void add_procedure(block *item, string *name, type_list *parameters,
+ int forward_declaration, int linenum)
+{
+ identifier *descriptor;
+
+ descriptor = name_table_find(item->names, name);
+
+ if (descriptor != NULL)
+ {
+ if ((forward_declaration != -1)
+ && (descriptor->forward_declaration != -1))
+ check_forward_declaration(descriptor, parameters,
+ forward_declaration, NULL);
+
+ if ((descriptor->forward_declaration == -1)
+ || (forward_declaration != -1))
+ descriptor->forward_declaration = forward_declaration;
+ }
+ else
+ {
+ descriptor = identifier_create();
+ descriptor->identifier_class = procedure_name;
+ descriptor->parameters = parameters;
+ descriptor->forward_declaration = forward_declaration;
+ descriptor->subprogram_linenum = linenum;
+ name_table_insert(item->names, name, descriptor);
+ }
+}
+
+
+/*
+ Adds a function declaration into the block
+*/
+void add_function(block *item, string *name, type_list *parameters,
+ type *return_type, int forward_declaration, int linenum)
+{
+ identifier *descriptor;
+
+ descriptor = name_table_find(item->names, name);
+
+ if (descriptor != NULL)
+ {
+ if ((forward_declaration != -1)
+ && (descriptor->forward_declaration != -1))
+ check_forward_declaration(descriptor, parameters,
+ forward_declaration, return_type);
+
+ if ((descriptor->forward_declaration == -1)
+ || (forward_declaration != -1))
+ descriptor->forward_declaration = forward_declaration;
+ }
+ else
+ {
+ descriptor = identifier_create();
+ descriptor->identifier_class = function_name;
+ descriptor->parameters = parameters;
+ descriptor->return_type = return_type;
+ descriptor->forward_declaration = forward_declaration;
+ descriptor->subprogram_linenum = linenum;
+ name_table_insert(item->names, name, descriptor);
+ }
+}
+
+
+/*
+ Loads (inserts) an external library into the project - load the class file and
+ enumerate all static functions.
+*/
+void load_extern_library(string* library_name)
+{
+ FILE *library_file = NULL;
+ FILE *symbol_file = NULL;
+ string *global_library_path;
+ string *project_library_path;
+ unit *library_unit;
+ identifier *unit_identifier;
+
+ lowercase(library_name->cstr);
+
+ /* create the full path to the library file */
+ /* global library directory */
+ global_library_path = string_from_cstr(global_library_directory);
+ #ifdef WIN32
+ string_append(global_library_path, string_from_cstr("\\Lib_"));
+ #endif
+ #ifdef UNIX
+ string_append(global_library_path, string_from_cstr("/Lib_"));
+ #endif
+ string_append(global_library_path, library_name);
+ string_append(global_library_path, string_from_cstr(".class"));
+ /* project library directory */
+ project_library_path = string_from_cstr(project_library_directory);
+ #ifdef WIN32
+ string_append(project_library_path, string_from_cstr("\\Lib_"));
+ #endif
+ #ifdef UNIX
+ string_append(project_library_path, string_from_cstr("/Lib_"));
+ #endif
+ string_append(project_library_path, library_name);
+ string_append(project_library_path, string_from_cstr(".class"));
+
+ if (name_table_find(root_block->names, library_name) != NULL)
+ {
+ add_error_message(450, string_get_cstr(library_name), "");
+ fclose(library_file);
+ goto lel_finally;
+ }
+
+ /* create a new unit object */
+ library_unit = unit_create(string_duplicate(library_name));
+ unit_identifier = identifier_create();
+ unit_identifier->identifier_class = unit_name;
+ unit_identifier->unit_block = library_unit;
+ name_table_insert(root_block->names, string_duplicate(library_name), unit_identifier);
+
+ /* try open the library file from the libraries directories */
+ library_file = fopen(project_library_path->cstr, "rb");
+ if (library_file == NULL)
+ {
+ library_file = fopen(global_library_path->cstr, "rb");
+ }
+ if (library_file == NULL)
+ {
+ /* if this fails, try to open an unit file */
+ char *filename = (char*)malloc(strlen(output_path) + string_length(library_name) + 10);
+
+ #ifdef WIN32
+ sprintf(filename, "%s\\%s.bsf", output_path, string_get_cstr(library_name));
+ #endif
+ #ifdef UNIX
+ sprintf(filename, "%s/%s.bsf", output_path, string_get_cstr(library_name));
+ #endif
+
+ symbol_file = fopen(filename, "rb");
+
+ free(filename);
+
+ if (symbol_file == NULL)
+ {
+ // j-a-s-d: if unit is not found it must stop only if compiling
+ if (!detect_units_only)
+ {
+ add_error_message(448, library_name->cstr, "");
+ goto lel_finally;
+ }
+
+ }
+
+ if (detect_units_only)
+ requires(0, library_name->cstr);
+ } else {
+ if (!detect_units_only)
+ requires(1, library_name->cstr);
+ }
+
+ /* read the library file */
+ if (library_file)
+ {
+ library_unit->is_library = 1;
+ if (detect_units_only == 0)
+ read_library_file(library_file, library_unit);
+ fclose(library_file);
+ }
+
+ if (symbol_file)
+ {
+ library_unit->is_library = 0;
+ if (detect_units_only == 0)
+ read_symbol_file(symbol_file, library_unit);
+ fclose(symbol_file);
+ }
+
+ unit_identifier->identifier_class = unit_name;
+ unit_identifier->unit_block = library_unit;
+
+ name_table_insert(root_block->names, library_name , unit_identifier);
+
+ if (library_file)
+ {
+ if (user_libraries == NULL)
+ {
+ user_libraries = malloc(library_name->length+1);
+ strcpy(user_libraries, library_name->cstr);
+ }
+ else
+ {
+ int len = strlen(user_libraries);
+ user_libraries = realloc(user_libraries, len + 3 + library_name->length);
+ user_libraries[strlen(user_libraries)] = ' ';
+ strcpy(user_libraries + len + 1, library_name->cstr);
+ }
+ }
+
+ if (symbol_file)
+ {
+save_unit_name:
+ if (*units == NULL)
+ {
+ *units = malloc(library_name->length+1);
+ strcpy(*units, library_name->cstr);
+ }
+ else
+ {
+ int len = strlen(*units);
+ *units = realloc(*units, len + 3 + library_name->length);
+ (*units)[len] = ' ';
+ strcpy(*units + len + 1, library_name->cstr);
+ }
+ }
+
+
+lel_finally:
+ string_destroy(library_name);
+ string_destroy(project_library_path);
+ string_destroy(global_library_path);
+}
+
+
+/*
+ Reads the library file.
+*/
+void read_library_file(FILE* library_file, unit* library_unit)
+{
+ int constant_pool_count;
+ struct constant_pool_struct *constant_pool;
+ int access_flags, this_class, super_class;
+ int interface_count, field_count, methods_count;
+ int i, j;
+
+ /* read and check magic number */
+ if ((fgetc(library_file) != 0xca)
+ || (fgetc(library_file) != 0xfe)
+ || (fgetc(library_file) != 0xba)
+ || (fgetc(library_file) != 0xbe)
+ )
+ {
+ add_error_message(449, "", "");
+ fclose(library_file);
+ die(6);
+ return;
+ }
+
+ /* skip major and minor count */
+ read_long_int(library_file);
+
+ /* read the number of constant pool entries */
+ constant_pool_count = read_short_int(library_file);
+
+ /* allocate and read the constant pool */
+ constant_pool = mem_alloc(sizeof(struct constant_pool_struct) * constant_pool_count);
+
+ for (i = 1; i<constant_pool_count; i++)
+ {
+ int tag;
+
+ tag = fgetc(library_file);
+ constant_pool[i].tag = tag;
+ constant_pool[i].data = NULL;
+
+ switch (tag)
+ {
+ case 7: /* ClassInfo */
+ case 8: /* StringInfo */
+ constant_pool[i].param1 = read_short_int(library_file);
+ break;
+ case 9: /* Fieldref */
+ case 10: /* Methodref */
+ case 11: /* Instanceref*/
+ case 12: /* NameAndType */
+ constant_pool[i].param1 = read_short_int(library_file);
+ constant_pool[i].param2 = read_short_int(library_file);
+ break;
+ case 3: /* Integer */
+ case 4: /* Float */
+ constant_pool[i].param1 = read_long_int(library_file);
+ break;
+ case 5: /* Long */
+ case 6: /* double */
+ constant_pool[i].param1 = read_long_int(library_file);
+ constant_pool[i].param2 = read_long_int(library_file);
+ break;
+
+ case 1: /* Utf8 */
+ constant_pool[i].data_len = read_short_int(library_file);
+ constant_pool[i].data = mem_alloc(sizeof(char) * constant_pool[i].data_len);
+ fread(constant_pool[i].data, 1, constant_pool[i].data_len, library_file);
+ break;
+
+ default:
+ add_error_message(449, "", "");
+ goto rlf_finally;
+ }
+ }
+
+ access_flags = read_short_int(library_file);
+ this_class= read_short_int(library_file);
+ super_class = read_short_int(library_file);
+
+ /* TODO:: check that this class has the proper name, no package etc. */
+ /* check access flags */
+ if ((access_flags & 0x0200) // ACC_INTERFACE
+ || (access_flags & 0x0400)) // ACC_ABSTRACT
+ {
+ add_error_message(451, "", "");
+ }
+
+ /* TODO:: are there some limitations on super class? */
+
+ /* skip over the implemented interfaces */
+ interface_count = read_short_int(library_file);
+ for(i=0; i<interface_count; i++)
+ {
+ read_short_int(library_file);
+ }
+
+ /* skip over the fields */
+ field_count = read_short_int(library_file);
+ for(i=0; i<field_count; i++)
+ {
+ int attributes_count;
+ read_short_int(library_file);
+ read_short_int(library_file);
+ read_short_int(library_file);
+ attributes_count = read_short_int(library_file);
+ for(j=0; j<attributes_count; j++)
+ {
+ int length;
+ read_short_int(library_file);
+ length = read_long_int(library_file);
+ fseek(library_file, length, SEEK_CUR);
+ }
+ }
+
+ /* read the methods and add them into the program scope */
+ methods_count = read_short_int(library_file);
+
+ for (i = 0; i<methods_count; i++)
+ {
+ short int method_access_flags;
+ short int method_name_index;
+ short int method_descriptor_index;
+ short int attributes_count;
+
+ method_access_flags = read_short_int(library_file);
+ method_name_index = read_short_int(library_file);
+ method_descriptor_index = read_short_int(library_file);
+
+ /* read the method's attributes */
+ attributes_count = read_short_int(library_file);
+
+ /* if the method is declared as 'public static' consider
+ adding it into the unit interface */
+ if(method_access_flags == 0x0009)
+ {
+ char *descriptor;
+ int parsing_return_type = 0;
+ identifier *method;
+ string *method_name;
+ int j;
+
+ method = identifier_create();
+ method->forward_declaration = 0;
+ method->standard_function = 0;
+ method->parameters = type_list_create();
+
+ /* check that method parameters and return value are OK */
+ descriptor = constant_pool[method_descriptor_index].data;
+
+ for(j = 1; j<constant_pool[method_descriptor_index].data_len; j++)
+ {
+ if (descriptor[j] == ')')
+ {
+ parsing_return_type = 1;
+ }
+ else
+ if ((descriptor[j] == 'L') && (strncmp(descriptor+j, "Ljava/lang/String;", 18) == 0))
+ {
+ type* new_type = type_create();
+ new_type->type_class = string_type;
+
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ j += 17;
+ }
+ else
+ if ((descriptor[j] == 'L') && (strncmp(descriptor+j, "Ljavax/microedition/lcdui/Image;", 32) == 0))
+ {
+ type* new_type = type_create();
+ new_type->type_class = image_type;
+
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ j += 31;
+ }
+ else
+ if ((descriptor[j] == 'L') && (strncmp(descriptor+j, "Ljavax/microedition/lcdui/Command;", 34) == 0))
+ {
+ type* new_type = type_create();
+ new_type->type_class = command_type;
+
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ j += 33;
+ }
+ else
+ if ((descriptor[j] == 'L') && (strncmp(descriptor+j, "Ljava/io/InputStream;", 21) == 0))
+ {
+ type* new_type = type_create();
+ new_type->type_class = stream_type;
+
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ j += 20;
+ }
+ else
+ if ((descriptor[j] == 'L') && (strncmp(descriptor+j, "Ljavax/microedition/rms/RecordStore;", 36) == 0))
+ {
+ type* new_type = type_create();
+ new_type->type_class = record_store_type;
+
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ j += 35;
+ }
+ else
+ if (descriptor[j] == 'I')
+ {
+ type* new_type = type_create();
+ new_type->type_class = integer_type;
+ if (!parsing_return_type)
+ type_list_append(method->parameters, new_type);
+ else
+ {
+ method->return_type = new_type;
+ method->identifier_class = function_name;
+ }
+ }
+ else
+ if ((descriptor[j] == 'V') && (parsing_return_type))
+ {
+ method->identifier_class = procedure_name;
+ }
+ else
+ {
+ add_error_message(452, "", "");
+ break;
+ }
+ }
+
+ method->unit_function = 1;
+ method->container_unit = library_unit;
+ method_name = string_create();
+ method_name->length = constant_pool[method_name_index].data_len;
+ method_name->cstr = malloc(method_name->length + 1);
+ strcpy(method_name->cstr, constant_pool[method_name_index].data);
+ method_name->cstr[method_name->length] = '\0';
+ name_table_insert(library_unit->names, method_name, method);
+ }
+
+ /* skip over all attributes */
+ for (j=0; j<attributes_count; j++)
+ {
+ long int length;
+ int name = read_short_int(library_file);
+ length = read_long_int(library_file);
+ fseek(library_file, length, SEEK_CUR);
+ }
+ }
+
+
+
+rlf_finally:
+ /* free the constant pool from the memory */
+ for (i = 1; i<constant_pool_count; i++)
+ {
+ if (constant_pool[i].data != NULL)
+ mem_free(constant_pool[i].data);
+ }
+
+ mem_free(constant_pool);
+
+}
+
+void read_symbol_file(FILE *symbol_file, struct unit_struct* library_unit)
+{
+ char tag;
+
+ while(fread(&tag, 1, 1, symbol_file) == 1)
+ {
+ switch(tag)
+ {
+ case 1:
+ { /* constant */
+ identifier *constant;
+ string* name;
+ char type;
+
+ constant = identifier_create();
+ constant->identifier_class = constant_name;
+ constant->unit_function = 1;
+ constant->container_unit = library_unit;
+
+ name = bsf_read_STRING(symbol_file);
+ fread(&type, 1, 1, symbol_file);
+
+ constant->constant_type = type_create();
+
+ switch (type)
+ {
+ case 1:
+ constant->constant_type->type_class = integer_type;
+ fread(&constant->constant_int_value, sizeof(int), 1, symbol_file);
+ break;
+ case 2:
+ constant->constant_type->type_class = real_type;
+ fread(&constant->constant_real_value, sizeof(float), 1, symbol_file);
+ break;
+ case 3:
+ constant->constant_type->type_class = boolean_type;
+ fread(&constant->constant_int_value, sizeof(char), 1, symbol_file);
+ break;
+ case 4:
+ constant->constant_type->type_class = char_type;
+ fread(&constant->constant_int_value, sizeof(char), 1, symbol_file);
+ break;
+ case 5:
+ constant->constant_type->type_class = string_type;
+ constant->constant_string_value = bsf_read_STRING(symbol_file);
+ break;
+ }
+
+ name_table_insert(library_unit->names, name, constant);
+ }
+ break;
+
+ case 2:
+ {
+ string *var_name;
+ type *var_type;
+ identifier *variable = identifier_create();
+
+ variable->identifier_class = variable_name;
+
+ var_name = bsf_read_STRING(symbol_file);
+ var_type = bsf_read_TYPE(symbol_file);
+
+ variable->variable_type = var_type;
+ variable->unit_function = 1;
+ variable->container_unit = library_unit;
+
+ name_table_insert(library_unit->names, var_name, variable);
+ }
+ break;
+
+ case 3:
+ {
+ string *name;
+ identifier *type_identifier = identifier_create();
+
+ type_identifier->identifier_class = type_name;
+
+ name = bsf_read_STRING(symbol_file);
+ type_identifier->defined_type = bsf_read_TYPE(symbol_file);
+ type_identifier->unit_function = 1;
+ type_identifier->container_unit = library_unit;
+
+ name_table_insert(library_unit->names, name, type_identifier);
+ }
+ break;
+
+ case 4:
+ {
+ string *name;
+ char params;
+ identifier* procedure = identifier_create();
+
+ procedure->forward_declaration = 0;
+ procedure->standard_function = 0;
+ procedure->identifier_class = procedure_name;
+ procedure->unit_function = 1;
+ procedure->container_unit = library_unit;
+ procedure->subprogram_linenum = 1;
+
+ procedure->parameters = type_list_create();
+
+ name = bsf_read_STRING(symbol_file);
+ fread(¶ms, 1, 1, symbol_file);
+
+ while (params > 0)
+ {
+ type_list_append(procedure->parameters, bsf_read_TYPE(symbol_file));
+ params --;
+ }
+
+ name_table_insert(library_unit->names, name, procedure);
+ }
+ break;
+
+ case 5:
+ {
+ string *name;
+ char params;
+ identifier* function = identifier_create();
+
+ function->forward_declaration = 0;
+ function->standard_function = 0;
+ function->identifier_class = function_name;
+ function->unit_function = 1;
+ function->container_unit = library_unit;
+ function->subprogram_linenum = 1;
+
+ function->parameters = type_list_create();
+
+ name = bsf_read_STRING(symbol_file);
+ function->return_type = bsf_read_TYPE(symbol_file);
+ fread(¶ms, 1, 1, symbol_file);
+
+ while (params > 0)
+ {
+ type_list_append(function->parameters, bsf_read_TYPE(symbol_file));
+ params --;
+ }
+
+ name_table_insert(library_unit->names, name, function);
+ }
+ break;
+ }
+ }
+}
+
+
+/*
+ Adds parameters names into block.
+*/
+void add_parameters(block *item, string_list *parameters_list,
+ type *parameters_type, int is_parameter_variable)
+{
+ string_list *it;
+ identifier *descriptor;
+
+ it = parameters_list;
+
+ if (it->data == NULL)
+ {
+ type_destroy(parameters_type);
+ return;
+ }
+
+ while (it != NULL)
+ {
+ descriptor = identifier_create();
+ descriptor->identifier_class = parameter_name;
+ descriptor->parameter_index = item->next_parameter_index;
+ item-> next_parameter_index ++;
+ descriptor->parameter_type = type_duplicate(parameters_type);
+ descriptor->is_parameter_variable = is_parameter_variable;
+ name_table_insert(item->names, string_duplicate(it->data), descriptor);
+
+ it = it->next;
+ }
+
+ item->next_variable_index = item->next_parameter_index;
+
+ type_destroy(parameters_type);
+}
+
+
+/*
+ Checks if a forward declaration corresponds to a real
+ function definition.
+
+ The identifier 'declaration' is a function or a
+ procedure that is forward.
+*/
+void check_forward_declaration(identifier *declaration,
+ type_list *parameters,
+ int forward_declaration,
+ type *return_type)
+{
+ int different_parameter;
+
+ if ((declaration->identifier_class != procedure_name)
+ && (declaration->identifier_class != function_name))
+ {
+ return;
+ }
+
+ if (forward_declaration)
+ {
+ add_error_message(401, "", "");
+ return;
+ }
+
+ if ((return_type == NULL) /* it is a procedure */
+ && (declaration->identifier_class == function_name))
+ add_error_message(402, "function", "");
+
+ if ((return_type != NULL) /* it is a function*/
+ && (declaration->identifier_class == procedure_name))
+ add_error_message(402, "procedure", "");
+
+ different_parameter = type_list_different_parameter(
+ parameters, declaration->parameters);
+
+ if (different_parameter == -1)
+ add_error_message(403, "", "");
+
+ if (different_parameter > 0)
+ {
+ char number[8];
+
+ sprintf(number, "%d", different_parameter);
+ add_error_message(404, number, "");
+ }
+
+ if (return_type != NULL)
+ {
+ if ((declaration->identifier_class != function_name) || (!type_equal(return_type, declaration->return_type)))
+ add_error_message(405, "", "");
+ }
+}
+
+
+/*
+ Checks if there is any identifier contained in the current block that is
+ forward function or procedure delcaration. If there is, report an error.
+*/
+void check_unmatched_forward_declarations(block *current_block, name_table *node)
+{
+ int i;
+ identifier *declaration;
+
+ if ((node == NULL) || (node->descriptor == NULL))
+ return;
+
+ declaration = node->descriptor;
+
+ if (
+ ((declaration->identifier_class == procedure_name) ||
+ (declaration->identifier_class == function_name))
+ && (declaration->forward_declaration == 1)
+ )
+ {
+ new_linenum=declaration->subprogram_linenum;
+ add_error_message(441, "", "");
+ }
+
+ check_unmatched_forward_declarations(current_block, node->left_child);
+ check_unmatched_forward_declarations(current_block, node->right_child);
+
+}
+
+
+/*
+ Uses a given name to access all the defined types.
+ Return a found type, or an error type if no type
+ was found.
+*/
+type *type_from_name(block *current_block, char *cstr)
+{
+ type *found_type;
+ string *name;
+ identifier *declaration;
+
+
+ found_type = type_create();
+ found_type->type_class = error_type;
+
+ name = string_from_cstr(cstr);
+
+ while (current_block != NULL)
+ {
+ declaration = name_table_find(current_block->names, name);
+
+ if (declaration != NULL)
+ {
+ if (declaration->identifier_class == type_name)
+ {
+ type_destroy(found_type);
+ found_type = type_duplicate(declaration->defined_type);
+ }
+
+ break;
+ }
+
+ current_block = current_block->parent_block;
+ }
+
+ string_destroy(name);
+ return found_type;
+}
+
+
+/*
+ Retuns the type of the constant given by its name,
+ or return error_type if cstr is not a constant name.
+*/
+type *get_constant_type(block *current_block, char *cstr)
+{
+ type *found_type;
+ string *name;
+ identifier *declaration;
+
+ found_type = type_create();
+ found_type->type_class = error_type;
+
+ name = string_from_cstr(cstr);
+
+ while (current_block != NULL)
+ {
+ declaration = name_table_find(current_block->names, name);
+
+ if (declaration != NULL)
+ {
+ if (declaration->identifier_class == constant_name)
+ {
+ type_destroy(found_type);
+ found_type = type_duplicate(declaration->constant_type);
+ }
+
+ break;
+ }
+
+ current_block = current_block->parent_block;
+ }
+
+ string_destroy(name);
+ return found_type;
+}
+
+
+/*
+ Return a copy of an identifier associated with a
+ constant of a given name, or a none identifier
+ if identifier is not a constant or not found.
+*/
+identifier *get_constant_identifier(block *current_block, char *cstr)
+{
+ string *name;
+ identifier *found_constant = NULL;
+ identifier *declaration;
+
+ name = string_from_cstr(cstr);
+
+ while (current_block != NULL)
+ {
+ declaration = name_table_find(current_block->names, name);
+
+ if (declaration != NULL)
+ {
+ if (declaration->identifier_class == constant_name)
+ found_constant = identifier_duplicate(declaration);
+
+ break;
+ }
+
+ current_block = current_block->parent_block;
+ }
+
+ string_destroy(name);
+
+ if (found_constant == NULL)
+ found_constant = identifier_create();
+
+ return found_constant;
+}
+
+
+/*
+ Return an identifier from a given name
+*/
+identifier *get_identifier(block *current_block, char *cstr)
+{
+ string *name;
+ identifier *found_identifier = NULL;
+ identifier *declaration;
+ name_table *name_table_it;
+
+ name = string_from_cstr(cstr);
+
+ while (current_block != NULL)
+ {
+ declaration = name_table_find(current_block->names, name);
+
+ if (declaration != NULL)
+ {
+ found_identifier = identifier_duplicate(declaration);
+
+ if (current_block->parent_block == root_block)
+ found_identifier->belongs_to_program_block = 1;
+ else
+ found_identifier->belongs_to_program_block = 0;
+
+ break;
+ }
+
+ current_block = current_block->parent_block;
+ }
+
+ string_destroy(name);
+
+ if (found_identifier != NULL)
+ return found_identifier;
+
+ /*
+ Search all units for a given identifier. If the same identifier is found
+ in more then one unit, output ambiguity error.
+ */
+ if (root_block->names->name != NULL)
+ {
+ name_table_it = root_block->names;
+
+ while (name_table_it != NULL)
+ {
+ identifier *descriptor = name_table_it->descriptor;
+
+ if (descriptor->identifier_class == unit_name)
+ {
+ /*
+ Search inside the unit for the given name
+ */
+ name_table *unit_table_it = descriptor->unit_block->names;
+
+ if (unit_table_it->name != NULL)
+ {
+ while (unit_table_it != NULL)
+ {
+ if(STRING_COMPARE(string_get_cstr(unit_table_it->name),
+ cstr) == 0)
+ {
+ if (found_identifier == NULL)
+ found_identifier = identifier_duplicate(unit_table_it->descriptor);
+ else
+ {
+ add_error_message(459, cstr, "");
+ found_identifier = NULL;
+ goto unit_search_done;
+ }
+ }
+
+
+ unit_table_it = unit_table_it->next;
+ }
+ }
+ }
+
+ name_table_it = name_table_it->next;
+ }
+ }
+
+unit_search_done:
+
+ if (found_identifier == NULL)
+ {
+ found_identifier = identifier_create();
+ found_identifier->belongs_to_program_block = 0;
+ }
+
+ return found_identifier;
+}
+
+
+/*
+ Returns the type of a variable given by its name.
+ Return an error type if no variable was found.
+*/
+type *get_variable_type(block *current_block, char *cstr)
+{
+ type *found_type;
+ string *name;
+ identifier *declaration;
+
+ found_type = type_create();
+ found_type->type_class = error_type;
+
+ name = string_from_cstr(cstr);
+
+ while (current_block != NULL)
+ {
+ declaration = name_table_find(current_block->names, name);
+
+ if (declaration != NULL)
+ {
+ if (declaration->identifier_class == variable_name)
+ found_type = type_duplicate(declaration->variable_type);
+
+ break;
+ }
+
+ current_block = current_block->parent_block;
+ }
+
+ string_destroy(name);
+ return found_type;
+}
+
+/*
+ Create the bytecode to initialize the new variable.
+*/
+void initialize_variable(block *item, identifier *variable, char *name, int is_static, char *class_name)
+{
+ int storeIntoField = 0;
+
+ /* if the variable belongs to the program block */
+ if (variable->belongs_to_program_block)
+ {
+ storeIntoField = 1;
+ }
+
+ switch(variable->variable_type->type_class)
+ {
+ case integer_type:
+ case char_type:
+ case boolean_type:
+ {
+ bytecode_append(item->code, iconst_0$);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, istore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, istore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, istore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, istore_3$);
+ break;
+ default:
+ bytecode_append(item->code, istore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break; // case integer_type
+
+ case real_type:
+ {
+ if (mathType == 1)
+ {
+ bytecode_append(item->code, iconst_0$);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, istore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, istore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, istore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, istore_3$);
+ break;
+ default:
+ bytecode_append(item->code, istore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ else
+ {
+ int method_index;
+ int class_index;
+
+ usesFloat = 1;
+
+ class_index = cp_add_class("Real");
+ method_index = cp_add_methodref("Real", "<init>", "()V");
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, (short)class_index);
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, (short)method_index);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, variable->variable_index);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+
+ case string_type:
+ {
+ int method_index;
+ int class_index;
+
+ class_index = cp_add_class("java/lang/String");
+ method_index = cp_add_methodref("java/lang/String", "<init>", "()V");
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, (short)class_index);
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, (short)method_index);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, variable->variable_index);
+ break;
+ }
+ }
+ }
+ break;
+
+ case image_type:
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Image", "createImage", "(II)Ljavax/microedition/lcdui/Image;");
+
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, invokestatic$);
+ bytecode_append_short_int(item->code, method_index);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break; // case image_type
+
+
+ case stream_type:
+ {
+ bytecode_append(item->code, aconst_null$);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break; // case stream_type
+
+ case command_type:
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Command", "<init>", "(Ljava/lang/String;II)V");
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class("javax/microedition/lcdui/Command"));
+ bytecode_append(item->code, dup$);
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class("java/lang/String"));
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, cp_add_methodref("java/lang/String", "<init>", "()V"));
+
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, method_index);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break; // case command_type
+
+ case http_type:
+ {
+ int method_index = cp_add_methodref("H", "<init>", "()V");
+ usesHttp = 1;
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class("H"));
+ bytecode_append(item->code, dup$);
+
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, method_index);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break; // case http_type
+
+ case record_store_type:
+ {
+ usesRecordStore = 1;
+ /* no initialization needeed */
+ }
+ break;
+
+ case array_type:
+ {
+ int count = 0;
+ type_list *it = variable->variable_type->dimensions_list;
+ char *descriptor;
+ descriptor = (char*) mem_alloc(1024);
+ if (descriptor == NULL)
+ die(1);
+
+ get_field_descriptor(variable->variable_type, descriptor);
+
+ /* put dimensions on to the stack */
+ while (it != NULL)
+ {
+ if (it->data != NULL)
+ {
+ int size;
+ size = it->data->last_element - it->data->first_element + 1;
+
+ if (size <= 0) {
+ add_error_message(437, "", "");
+ } else if (size <= 127) {
+ bytecode_append(item->code, bipush$);
+ bytecode_append(item->code, (char)size);
+ } else if (size <= 32767) {
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, (short)size);
+ } else {
+ add_error_message(438, "", "");
+ }
+ }
+ it = it->next;
+
+ count ++;
+ }
+
+ bytecode_append(item->code, multianewarray$);
+ bytecode_append_short_int(item->code, cp_add_class(descriptor));
+ bytecode_append(item->code, (char)count);
+
+ // NEW:
+ create_put_variable_bytecode(variable, item->code, name, storeIntoField);
+
+ if((variable->variable_type->element_type->type_class == record_type)
+ || (variable->variable_type->element_type->type_class == string_type)
+ || ((variable->variable_type->element_type->type_class == real_type) && (mathType != 1))
+ || (variable->variable_type->element_type->type_class == image_type)
+ || (variable->variable_type->element_type->type_class == command_type))
+ {
+ /* initialize the fields */
+ unsigned short int c = 0;
+ char descriptor[128];
+ unsigned short int num;
+ int *offsets;
+ int *dimensions_sizes; // j-a-s-d: OOB in initialization of complex-type multidimensional arrays bug fix
+ type_list *it = variable->variable_type->dimensions_list;
+
+ while (it != NULL)
+ {
+ it = it->next;
+ c ++;
+ }
+
+ if (variable->variable_type->element_type->type_class == real_type)
+ usesFloat = 1;
+
+ offsets = (int*) mem_alloc(c * sizeof(int));
+ dimensions_sizes = (int*) mem_alloc(c * sizeof(int)); // j-a-s-d: OOB in initialization of complex-type multidimensional arrays bug fix
+ num = c;
+
+ /* reset */
+ it = variable->variable_type->dimensions_list;
+ c = 0;
+ while (it != NULL)
+ {
+ if (it->data != NULL)
+ {
+ bytecode_append(item->code, getstatic$);
+ bytecode_append_short_int(item->code, cp_add_fieldref("M", "IC", "[I"));
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, c);
+ bytecode_append(item->code, iconst_0$);
+ bytecode_append(item->code, iastore$);
+
+ offsets[c] = item->code->bytecode_pos;
+ dimensions_sizes[c] = it->data->last_element-it->data->first_element; // j-a-s-d: OOB in initialization of complex-type multidimensional arrays bug fix
+ }
+ c++;
+ it = it->next;
+ }
+
+ /* load */
+ for(c=0; c<num; c++)
+ {
+ if ((c < (num-1)) || (c == 0))
+ {
+ // OLD: bytecode_append(item->code, dup$);
+ // NEW:
+ create_variable_bytecode(variable, item->code, name, storeIntoField);
+ }
+ bytecode_append(item->code, getstatic$);
+ bytecode_append_short_int(item->code, cp_add_fieldref("M", "IC", "[I"));
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, c);
+ bytecode_append(item->code, iaload$);
+ if (c < (num-1))
+ bytecode_append(item->code, aaload$);
+ }
+
+ /* new */
+ get_field_descriptor(variable->variable_type->element_type, descriptor);
+ descriptor[strlen(descriptor)-1] = '\0';
+
+ if (variable->variable_type->element_type->type_class == image_type)
+ {
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, invokestatic$);
+ bytecode_append_short_int(item->code, cp_add_methodref("javax/microedition/lcdui/Image", "createImage", "(II)Ljavax/microedition/lcdui/Image;"));
+ }
+ else if (variable->variable_type->element_type->type_class == command_type)
+ {
+ int method_index = cp_add_methodref("javax/microedition/lcdui/Command", "<init>", "(Ljava/lang/String;II)V");
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class("javax/microedition/lcdui/Command"));
+ bytecode_append(item->code, dup$);
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class("java/lang/String"));
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, cp_add_methodref("java/lang/String", "<init>", "()V"));
+
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, method_index);
+ }
+ else
+ {
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class(descriptor+1));
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, cp_add_methodref(descriptor+1, "<init>", "()V"));
+ }
+
+ bytecode_append(item->code, aastore$);
+
+ /* jump back */
+ it = variable->variable_type->dimensions_list;
+ c = num-1;
+ while (it != NULL)
+ {
+ if (it->data != NULL)
+ {
+ short int offset;
+ bytecode_append(item->code, getstatic$);
+ bytecode_append_short_int(item->code, cp_add_fieldref("M", "IC", "[I"));
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, c);
+ bytecode_append(item->code, iaload$);
+ bytecode_append(item->code, iconst_1$);
+ bytecode_append(item->code, iadd$);
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, c);
+ bytecode_append(item->code, swap$);
+ bytecode_append(item->code, iastore$);
+ /* the value is increased by one */
+
+ bytecode_append(item->code, getstatic$);
+ bytecode_append_short_int(item->code, cp_add_fieldref("M", "IC", "[I"));
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code, c);
+ bytecode_append(item->code, iaload$);
+ bytecode_append(item->code, sipush$);
+ bytecode_append_short_int(item->code,
+ //it->data->last_element-it->data->first_element);
+ dimensions_sizes[c]); // j-a-s-d: OOB in initialization of complex-type multidimensional arrays bug fix
+ bytecode_append(item->code, if_icmple$);
+ offset = offsets[c] - item->code->bytecode_pos + 1;
+ bytecode_append_short_int(item->code, offset);
+ }
+ c--;
+ it = it->next;
+ }
+
+ mem_free(offsets);
+ }
+
+ /*OLD: if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ } */
+
+ mem_free(descriptor);
+
+ break;
+ } // case array_type
+
+ case record_type:
+ {
+ char *descriptor;
+ descriptor = (char*) mem_alloc(1024);
+
+ if(descriptor == NULL)
+ die(1);
+
+ get_field_descriptor(variable->variable_type, descriptor);
+
+ descriptor[strlen(descriptor) - 1] = '\0';
+
+ bytecode_append(item->code, new$);
+ bytecode_append_short_int(item->code, cp_add_class(descriptor + 1));
+ bytecode_append(item->code, dup$);
+ bytecode_append(item->code, invokespecial$);
+ bytecode_append_short_int(item->code, cp_add_methodref(descriptor + 1, "<init>", "()V"));
+
+ mem_free(descriptor);
+
+ if (!storeIntoField)
+ {
+ switch(variable->variable_index)
+ {
+ case 0:
+ bytecode_append(item->code, astore_0$);
+ break;
+ case 1:
+ bytecode_append(item->code, astore_1$);
+ break;
+ case 2:
+ bytecode_append(item->code, astore_2$);
+ break;
+ case 3:
+ bytecode_append(item->code, astore_3$);
+ break;
+ default:
+ bytecode_append(item->code, astore$);
+ bytecode_append(item->code, (char)variable->variable_index);
+ break;
+ }
+ }
+ }
+ break;
+
+ case error_type:
+ break;
+
+ default:
+ {
+ die(14);
+ }
+ }
+
+
+ /* create the bytecode for storing data into the field */
+ if ((storeIntoField)
+ && (variable->variable_type->type_class != record_store_type)
+ && (variable->variable_type->type_class != array_type)) /* array initialization stores the variable */
+ {
+ int field_index;
+ char descriptor[512];
+ get_field_descriptor(variable->variable_type, descriptor);
+
+ if (name == NULL)
+ die(23);
+
+ lowercase(name);
+ field_index = cp_add_fieldref(class_name, name, descriptor);
+
+ if (is_static)
+ bytecode_append(item->code, putstatic$);
+ else
+ bytecode_append(item->code, putfield$);
+ bytecode_append_short_int(item->code, (short)field_index);
+ }
+}
+
+
+void transform_break_stmts(bytecode *code, int start_offset, int end_offset, int jump_pos)
+{
+ int jump_offset;
+ int pos = start_offset;
+
+ while (pos < end_offset)
+ {
+ if (((unsigned char)(code->bytecode[pos]) == (unsigned char)break_stmt$)
+ && ((pos + 2) < end_offset))
+ {
+ if ((code->bytecode[pos+1] == 0)
+ && (code->bytecode[pos+2] == 0))
+ {
+ jump_offset = jump_pos - pos;
+ code->bytecode[pos] = goto$;
+ code->bytecode[pos+1] = (jump_offset) >> 8;
+ code->bytecode[pos+2] = jump_offset;
+ }
+ }
+
+ pos ++;
+ }
+}
+
+
+/*
+ Writes the class file based on the information provided in the
+ root block.
+*/
+void create_class_file(block *program_block, FILE *fp)
+{
+ int this_class_index;
+ int super_class_index;
+ int i;
+
+ /*** Insert the additional data into the constant pool ***/
+ if (compiling_unit == 0)
+ {
+ this_class_index = cp_add_class("M");
+ switch (canvasType)
+ {
+ case NORMAL:
+ super_class_index = cp_add_class("javax/microedition/lcdui/Canvas");
+ break;
+ case FULL_NOKIA:
+ super_class_index = cp_add_class("com/nokia/mid/ui/FullCanvas");
+ break;
+ case FULL_MIDP20:
+ super_class_index = cp_add_class("javax/microedition/lcdui/game/GameCanvas");
+ break;
+ }
+ }
+ else
+ {
+ this_class_index = cp_add_class(string_get_cstr(str_program_name));
+ super_class_index = cp_add_class("java/lang/Object");
+ }
+
+
+ /* Insert the data needed by the methods into the constant pool */
+ write_method(program_block, NULL);
+ for(i=0; i<program_block->children_count; i++)
+ {
+ write_method(program_block->children[i], NULL);
+ }
+ write_block_fields(program_block->names, NULL);
+
+ if (compiling_unit == 0)
+ {
+ write_constructor(NULL);
+ write_paint_method(NULL);
+ write_run_method(NULL);
+ write_keypressed_method(NULL);
+ write_keyreleased_method(NULL);
+ }
+
+ /* add data to constant poll that is later needed */
+ cp_add_utf8("I");
+ cp_add_utf8("T");
+ cp_add_utf8("G");
+ cp_add_utf8("KC");
+ cp_add_utf8("KP");
+ cp_add_utf8("IC");
+ cp_add_utf8("[I");
+ cp_add_utf8("Ljavax/microedition/lcdui/Image;");
+ cp_add_utf8("LM;");
+ cp_add_class("M");
+ cp_add_utf8("Ljavax/microedition/lcdui/Graphics;");
+ cp_add_class("java/lang/Runnable");
+ cp_add_utf8("StackMap");
+
+ /*** Write data to the file ***/
+
+ /* write the header */
+ create_class_file_header(fp);
+
+ /* write constant pool */
+ write_constant_pool(fp);
+
+ /* write the access flags, set to ACC_PUBLIC and ACC_SUPER */
+ write_short_int(fp, 0x0021);
+
+ /* write the index to constat pool with this class description */
+ write_short_int(fp, (short)this_class_index);
+
+ /* write the index to constant pool with the super class description */
+ write_short_int(fp, (short)super_class_index);
+
+ if (compiling_unit == 0)
+ {
+ /* we have 1 interface */
+ write_short_int(fp, 1);
+
+ write_short_int(fp, cp_add_class("java/lang/Runnable"));
+ }
+ else
+ {
+ /* unit has 0 interfaces */
+ write_short_int(fp, 0);
+ }
+
+ /* write the fields (global variables in pascal) */
+ if (compiling_unit == 0)
+ {
+ write_short_int(fp, (short)(program_block->next_variable_index + 7));
+
+ /* write the RNG field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("RNG"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("Ljava/util/Random;"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the image (I) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("I"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("Ljavax/microedition/lcdui/Image;"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the this (T) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("T"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("LM;"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+
+ /* write the graphics (G) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("G"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("Ljavax/microedition/lcdui/Graphics;"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the key clicked (KC) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("KC"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("I"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the key pressed (KP) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("KP"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("I"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the INDEX COUNTER (IC) field */
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ write_short_int(fp, cp_add_utf8("IC"));
+
+ /* write the descriptor index */
+ write_short_int(fp, cp_add_utf8("[I"));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+ }
+ else
+ {
+ write_short_int(fp, (short)(program_block->next_variable_index));
+ }
+
+ write_block_fields(program_block->names, fp);
+
+
+ /* write the methods */
+ if (compiling_unit == 0)
+ {
+ /* write the methods count */
+ write_short_int(fp, (short)(program_block->children_count + 6));
+
+ /* write the constructor */
+ write_constructor(fp);
+
+ /* write the paint method */
+ write_paint_method(fp);
+
+ /* write the run method */
+ write_run_method(fp);
+
+ /* write the key pressed and key released methods */
+ write_keypressed_method(fp);
+ write_keyreleased_method(fp);
+ }
+ else
+ {
+ write_short_int(fp, (short)(program_block->children_count + 1));
+ }
+
+ /* write all other methods */
+ for(i=0; i<program_block->children_count; i++)
+ {
+ write_method(program_block->children[i], fp);
+ }
+
+ /* write the main (R) method - <clinit> for interfaces */
+ write_method(program_block, fp);
+
+
+ /* we have no attributes */
+ write_short_int(fp, 0);
+
+
+ // TODO: deallocate constant pool
+}
+
+
+/*
+ Writes the method to the file, if fp is NULL only add needeed
+ data to the constant pool
+*/
+void write_method(block *current_block, FILE *fp)
+{
+ identifier *block_identifier = NULL;
+ stack_map_list *map_list;
+ int code_attribute_length, code_attribute_length_offset;
+ int stack_map_attribute_offset;
+ int stack_map_size;
+ int stack_map_entries;
+ int tmp_offset;
+
+ /* write access flags, ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ if(current_block->parent_block == root_block)
+ {
+ /*** it is the main block ***/
+
+ /* write name index */
+ if (compiling_unit == 0)
+ write_short_int(fp, cp_add_utf8("R"));
+ else
+ write_short_int(fp, cp_add_utf8("<clinit>"));
+
+ /* write the descriptor */
+ write_short_int(fp, cp_add_utf8("()V"));
+ }
+ else
+ {
+ char *descriptor;
+ int pos = 1;
+ type_list *it;
+
+ descriptor = (char*) mem_alloc(5*1024);
+
+ if (descriptor == NULL)
+ die(1);
+
+ descriptor[0] = '(';
+
+ /*** procedure or function ***/
+
+ /* write name index */
+ lowercase(current_block->block_name->cstr);
+ write_short_int(fp, cp_add_utf8(current_block->block_name->cstr));
+
+ /* write the descriptor */
+ block_identifier = name_table_find(current_block->parent_block->names, current_block->block_name);
+
+ if ((block_identifier == NULL)
+ || (block_identifier->identifier_class != function_name
+ && block_identifier->identifier_class != procedure_name))
+ {
+ mem_free(descriptor);
+ die(17);
+ }
+
+ it = block_identifier->parameters;
+
+ while(it != NULL)
+ {
+ if (it->data == NULL)
+ break;
+
+ get_field_descriptor(it->data, descriptor + pos);
+ pos = strlen(descriptor);
+ it = it->next;
+ }
+
+ descriptor[pos] = ')';
+ pos ++;
+ descriptor[pos] = '\0';
+
+ if (block_identifier->identifier_class == procedure_name)
+ strcat(descriptor, "V");
+ else
+ get_field_descriptor(block_identifier->return_type, descriptor + pos);
+
+ write_short_int(fp, cp_add_utf8(descriptor));
+
+ mem_free(descriptor);
+ }
+
+//PREVERIFY map_list = preverify_bytecode(current_block->code, block_identifier);
+ map_list = NULL;
+
+
+ /* write the code */
+ write_short_int(fp, 2); /* attribute count */
+
+ write_short_int(fp, cp_add_utf8("Code"));
+ if (fp != NULL)
+ code_attribute_length_offset = ftell(fp);
+ write_long_int(fp, current_block->code->bytecode_pos + 12); /* update the size later when we know it */
+ code_attribute_length = current_block->code->bytecode_pos + 12;
+
+ write_short_int(fp, 32); /* max stack */
+
+ if (current_block->parent_block == root_block)
+ write_short_int(fp, 0); /* max locals for program block */
+ else
+ write_short_int(fp, current_block->next_variable_index + 2); /* max locals */
+
+ write_long_int(fp, current_block->code->bytecode_pos); /* code length */
+
+ if(fp != NULL)
+ fwrite(current_block->code->bytecode, current_block->code->bytecode_pos, 1, fp);
+
+ write_short_int(fp, 0);
+ if (map_list != NULL)
+ {
+ write_short_int(fp, 1); /* The Code has one attribute (The StackMap attribute) */
+
+ write_short_int(fp, cp_add_utf8("StackMap"));
+ if (fp != NULL)
+ stack_map_attribute_offset = ftell(fp);
+ write_long_int(fp, 0); /* attribute length */
+ write_short_int(fp, 0); /* number of entries; these two fields will be filled in later */
+
+ stack_map_size = 2;
+ stack_map_entries = 0;
+
+ do
+ {
+ int i;
+ stack_map *map = stack_map_list_get(&map_list);
+
+ if (map != NULL)
+ write_short_int(fp, (short)(map->bytecode_offset));
+ stack_map_size += 2;
+
+ /* write the locals */
+ if (current_block->parent_block == root_block)
+ {
+ write_short_int(fp, 0);
+ stack_map_size += 2;
+ }
+ else
+ {
+ identifier *block_identifier;
+
+ /* write the StackMap for locals */
+ block_identifier = name_table_find(current_block->parent_block->names, current_block->block_name);
+
+ write_short_int(fp, (short)current_block->next_variable_index);
+ stack_map_size += 2;
+
+ write_locals_stackmap(fp, block_identifier, &stack_map_size);
+ }
+
+ if (map == NULL)
+ break;
+
+ /* write the stack items */
+ write_short_int(fp, (short)map->number_of_items);
+ stack_map_size += 2;
+ for(i=0; i<map->number_of_items; i++)
+ {
+ if (fp != NULL)
+ {
+ fwrite(&(map->stack[i]->item_type), 1, 1, fp);
+ }
+
+ if ((map->stack[i]->item_type == ITEM_Object)
+ || (map->stack[i]->item_type == ITEM_NewObject))
+ {
+ write_short_int(fp, map->stack[i]->additional_data);
+ stack_map_size += 2;
+ }
+
+ stack_map_size ++;
+ }
+
+ stack_map_destroy(map);
+
+ stack_map_entries ++;
+
+ } while (map_list != NULL);
+
+ /* write the stack map size and the number of entries and
+ the code attribute length */
+ if (fp != NULL)
+ {
+ tmp_offset = ftell(fp);
+ fseek(fp, stack_map_attribute_offset, SEEK_SET);
+ write_long_int(fp, stack_map_size); /* attribute length */
+ write_short_int(fp, (short)stack_map_entries); /* number of entries */
+
+ fseek(fp, code_attribute_length_offset, SEEK_SET);
+ write_long_int(fp, code_attribute_length + 6 + stack_map_size);
+
+ fseek(fp, tmp_offset, SEEK_SET);
+ }
+ }
+ else
+ {
+ write_short_int(fp, 0);
+ }
+
+ /* write the Exceptions attribute */
+ write_short_int(fp, cp_add_utf8("Exceptions"));
+
+ write_long_int(fp, 4);
+
+ write_short_int(fp, 1);
+ write_short_int(fp, cp_add_class("java/lang/Exception"));
+
+}
+
+
+/*
+ Creates the code for the following method:
+
+ public void paint(Graphics g)
+ {
+ g.drawImage(IMG, 0, 0, Graphics.TOP|Graphics.LEFT);
+ }
+*/
+void write_paint_method(FILE *fp)
+{
+ bytecode *code = bytecode_create();
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+
+ /* PUSH param_1 */
+ bytecode_append(code, aload_1$);
+
+ /* PUSH (I) */
+ bytecode_append(code, getstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "I", "Ljavax/microedition/lcdui/Image;"));
+
+ /* PUSH 0; PUSH 0*/
+ bytecode_append(code, iconst_0$);
+ bytecode_append(code, iconst_0$);
+
+ /* PUSH Graphics.LEFT|Graphics.TOP */
+ bytecode_append(code, bipush$);
+ bytecode_append(code, 20);
+
+ /* invoke drawImage(Image, int, int, int) */
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code,
+ cp_add_methodref("javax/microedition/lcdui/Graphics", "drawImage", "(Ljavax/microedition/lcdui/Image;III)V"));
+
+ bytecode_append(code, return$);
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name */
+ write_short_int(fp, cp_add_utf8("paint"));
+
+ /* write method descriptor */
+ write_short_int(fp, cp_add_utf8("(Ljavax/microedition/lcdui/Graphics;)V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 10);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+}
+
+/*
+ Creates the code for the following method:
+
+ public void run()
+ {
+ R();
+ }
+*/
+void write_run_method(FILE *fp)
+{
+ char tag;
+
+ bytecode *code = bytecode_create();
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+ bytecode_append(code, invokestatic$);
+ bytecode_append_short_int(code, cp_add_methodref("M", "R", "()V"));
+
+ bytecode_append(code, goto$);
+ bytecode_append_short_int(code, 4);
+
+ bytecode_append(code, pop$); /* the exception handler */
+
+ bytecode_append(code, return$);
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name */
+ write_short_int(fp, cp_add_utf8("run"));
+
+ /* write method descriptor */
+ write_short_int(fp, cp_add_utf8("()V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 20 + 38); /* 38 = stackmap size */
+
+ /* write the max stack */
+ write_short_int(fp, 2);
+
+ /* max locals for program block */
+ write_short_int(fp, 1);
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ /* write exception table length*/
+ write_short_int(fp, 1);
+
+ /* write the exception table */
+ write_short_int(fp, 0);
+ write_short_int(fp, 3);
+ write_short_int(fp, 6);
+ write_short_int(fp, cp_add_class("java/lang/Exception"));
+
+
+ /* StackMap attribute */
+ write_short_int(fp, 1);
+
+ write_short_int(fp, cp_add_utf8("StackMap"));
+ write_long_int(fp, 32);
+
+ /* 2 frames*/
+ write_short_int(fp, 3);
+
+ /* write the frame 0 */
+ write_short_int(fp, 0);
+
+ /* write the locals */
+ write_short_int(fp, 1);
+ tag = 7;
+ if (fp != NULL)
+ fwrite(&tag, 1, 1, fp);
+ write_short_int(fp, cp_add_class("M"));
+
+
+ /* 0 stack entries */
+ write_short_int(fp, 0);
+
+ /* write the frame 1 */
+ write_short_int(fp, 6);
+
+ /* write the locals*/
+ write_short_int(fp, 1);
+ tag = 7;
+ if (fp != NULL)
+ fwrite(&tag, 1, 1, fp);
+ write_short_int(fp, cp_add_class("M"));
+
+ /* 1 stack entry */
+ write_short_int(fp, 1);
+ tag = 7;
+ if (fp != NULL)
+ fwrite(&tag, 1, 1, fp);
+ write_short_int(fp, cp_add_class("java/lang/Exception"));
+
+
+ /* write the frame 2 */
+ write_short_int(fp, 7);
+
+ /* write the locals */
+ write_short_int(fp, 1);
+ tag = 7;
+ if (fp != NULL)
+ fwrite(&tag, 1, 1, fp);
+ write_short_int(fp, cp_add_class("M"));
+
+ /* 0 stack entries */
+ write_short_int(fp, 0);
+
+}
+
+
+/*
+ Creates the code for the following methods:
+
+ public void keyPressed(int keyCode)
+ {
+ KC = keyCode;
+ KP = keyCode;
+ }
+
+ public void keyReleased(int keyCode)
+ {
+ KP = 0;
+ }
+*/
+void write_keypressed_method(FILE *fp)
+{
+ bytecode *code = bytecode_create();
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+ bytecode_append(code, iload_1$);
+ bytecode_append(code, dup$);
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "KC", "I"));
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "KP", "I"));
+
+ bytecode_append(code, return$);
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name */
+ write_short_int(fp, cp_add_utf8("keyPressed"));
+
+ /* write method descriptor */
+ write_short_int(fp, cp_add_utf8("(I)V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 2);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+}
+void write_keyreleased_method(FILE *fp)
+{
+ bytecode *code = bytecode_create();
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+ bytecode_append(code, iconst_0$);
+ bytecode_append(code, putstatic$);
+ bytecode_append_short_int(code, cp_add_fieldref("M", "KP", "I"));
+
+ bytecode_append(code, return$);
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name */
+ write_short_int(fp, cp_add_utf8("keyReleased"));
+
+ /* write method descriptor */
+ write_short_int(fp, cp_add_utf8("(I)V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 2);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+}
+
+
+/*
+ Creates the code for the class constructor.
+*/
+void write_constructor(FILE *fp)
+{
+ bytecode *code = bytecode_create();
+ if (code == NULL)
+ die(1);
+
+ /* create the code */
+ switch (canvasType)
+ {
+ case NORMAL:
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Canvas", "<init>", "()V"));
+ break;
+ case FULL_NOKIA:
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("com/nokia/mid/ui/FullCanvas", "<init>", "()V"));
+ break;
+ case FULL_MIDP20:
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, iconst_0$);
+ bytecode_append(code, invokespecial$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/game/GameCanvas", "<init>", "(Z)V"));
+
+ bytecode_append(code, aload_0$);
+ bytecode_append(code, iconst_1$);
+ bytecode_append(code, invokevirtual$);
+ bytecode_append_short_int(code, cp_add_methodref("javax/microedition/lcdui/Canvas", "setFullScreenMode", "(Z)V"));
+ break;
+ }
+
+ bytecode_append(code, return$);
+
+ /* write the method headers */
+
+ /* write access flags, ACC_PUBLIC */
+ write_short_int(fp, 0x0001);
+
+ /* write method name */
+ write_short_int(fp, cp_add_utf8("<init>"));
+
+ /* write method descriptor */
+ write_short_int(fp, cp_add_utf8("()V"));
+
+ /* write 1 attribute */
+ write_short_int(fp, 1);
+
+ /* write the Code attribute */
+ write_short_int(fp, cp_add_utf8("Code"));
+ write_long_int(fp, code->bytecode_pos + 12);
+
+ /* write the max stack */
+ write_short_int(fp, 10);
+
+ /* max locals for program block */
+ write_short_int(fp, 2);
+
+
+ /* code length */
+ write_long_int(fp, code->bytecode_pos);
+
+ /* write the code itself */
+ if (fp != NULL)
+ fwrite(code->bytecode, 1, code->bytecode_pos, fp);
+
+ bytecode_destroy(code);
+
+ write_short_int(fp, 0);
+ write_short_int(fp, 0);
+
+}
+
+
+/*
+ Write the variables from the block as fields into the
+ given class file. If fp==NULL only add constants into
+ the constant pool.
+*/
+void write_block_fields(name_table *names, FILE *fp)
+{
+ char descriptor[128];
+
+ if ((names->descriptor != NULL)
+ && (names->descriptor->identifier_class == variable_name))
+ {
+ /* access flags: ACC_PUBLIC and ACC_STATIC */
+ write_short_int(fp, 0x0001 | 0x0008);
+
+ /* write the name index */
+ lowercase(names->name->cstr);
+ write_short_int(fp, cp_add_utf8(names->name->cstr));
+
+ /* write the descriptor index */
+ get_field_descriptor(names->descriptor->variable_type, descriptor);
+ write_short_int(fp, cp_add_utf8(descriptor));
+
+ /* write 0 attributes */
+ write_short_int(fp, 0);
+ }
+
+ /* write the left child */
+ if ((names->descriptor != NULL)
+ && (names->left_child != NULL))
+ {
+ write_block_fields(names->left_child, fp);
+ }
+
+ /* write the right child */
+ if ((names->descriptor != NULL)
+ && (names->right_child != NULL))
+ {
+ write_block_fields(names->right_child, fp);
+ }
+}
+
+
+void write_locals_stackmap(FILE *fp, identifier *block_identifier, int *stack_map_size)
+{
+ type_list *it = block_identifier->parameters;
+ write_stackmap(fp, it, stack_map_size);
+
+ /* for functions, add the return value */
+ if (block_identifier->identifier_class == function_name)
+ {
+ it = type_list_create();
+ type_list_append(it, block_identifier->return_type);
+ write_stackmap(fp, it, stack_map_size);
+ type_list_destroy(it);
+ }
+
+ it = block_identifier->variables;
+ write_stackmap(fp, it, stack_map_size);
+}
+
+void write_stackmap(FILE *fp, type_list *it, int *stack_map_size)
+{
+
+ while (it != NULL)
+ {
+ char c;
+
+ if (it->data != NULL)
+ {
+ switch(it->data->type_class)
+ {
+ case integer_type:
+ case char_type:
+ case boolean_type:
+ c = 1;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ (*stack_map_size) ++;
+ break;
+
+ case real_type:
+ {
+ if (mathType == 1)
+ {
+ c = 1;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ (*stack_map_size) ++;
+ }
+ else
+ {
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("Real"));
+ (*stack_map_size) += 3;
+ }
+ }
+ break;
+
+ case string_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("java/lang/String"));
+ (*stack_map_size) += 3;
+ break;
+
+ case image_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("javax/microedition/lcdui/Image"));
+ (*stack_map_size) += 3;
+ break;
+
+ case command_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("javax/microedition/lcdui/Command"));
+ (*stack_map_size) += 3;
+ break;
+
+
+ case stream_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("java/io/InputStream"));
+ (*stack_map_size) += 3;
+ break;
+
+ case record_store_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("javax/microedition/rms/RecordStore"));
+ (*stack_map_size) += 3;
+ break;
+
+ case http_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("H"));
+ (*stack_map_size) += 3;
+ break;
+
+ case alert_type:
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class("Ljavax/microedition/lcdui/AlertType;"));
+ (*stack_map_size) += 3;
+ break;
+
+ case array_type:
+ {
+ char descriptor[512];
+ char element_type[128];
+ int i, len;
+
+ get_field_descriptor(it->data->element_type, element_type);
+
+ len = type_list_length(it->data->dimensions_list);
+ for(i=0; i < len; i++)
+ {
+ descriptor[i] = '[';
+ }
+
+ descriptor[len] = '\0';
+
+ sprintf(descriptor + len, "%s", element_type);
+
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ write_short_int(fp, cp_add_class(descriptor));
+ (*stack_map_size) += 3;
+ }
+ break;
+
+ case record_type:
+ {
+ char descriptor[16];
+ c = 7;
+ if (fp != NULL)
+ fwrite(&c, 1, 1, fp);
+ sprintf(descriptor, "R_%d", it->data->unique_record_ID);
+ write_short_int(fp, cp_add_class(descriptor));
+ (*stack_map_size) += 3;
+ }
+ break;
+ }
+ }
+
+ it = it->next;
+ }
+}
diff --git a/MPC.3.5.LINUX/structures/block.h b/MPC.3.5.LINUX/structures/block.h
--- /dev/null
@@ -0,0 +1,90 @@
+/********************************************************************
+
+ block.h - structures and functions used to hold program
+ block descriptions
+
+ Niksa Orlic, 2004-04-23
+
+********************************************************************/
+
+#include <stdio.h>
+
+/*
+ The structure to hold description for
+ one block;
+*/
+struct block_struct
+{
+ struct block_struct *parent_block;
+
+ name_table *names;
+
+ string *block_name;
+
+ int next_variable_index;
+ int next_parameter_index;
+
+ bytecode *code;
+
+ struct block_struct **children;
+ int children_count;
+};
+
+typedef struct block_struct block;
+
+/* canvas types */
+#define NORMAL 0
+#define FULL_MIDP20 1
+#define FULL_NOKIA 2
+
+
+block* block_create(block*, string*);
+void block_destroy(block*);
+
+int block_check_name(block*, char*);
+
+void add_real_constant(block*, float, char*);
+void add_integer_constant(block*, long int, char*);
+void add_char_constant(block*, char, char*);
+void add_boolean_constant(block*, char, char*);
+void add_string_constant(block*, string*, char*);
+
+void add_variables(block*, string_list*, type*);
+
+void add_type(block*, string*, type*);
+
+void add_procedure(block*, string*, type_list*, int, int);
+void add_function(block*, string*, type_list*,type*, int, int);
+
+void load_extern_library(string*);
+void read_library_file(FILE*, struct unit_struct*);
+void read_symbol_file(FILE*, struct unit_struct*);
+
+void add_parameters(block*, string_list*, type*, int);
+
+void check_forward_declaration(identifier*, type_list*,
+ int, type*);
+void check_unmatched_forward_declarations(block*, name_table*);
+
+void transform_break_stmts(bytecode*, int, int, int);
+
+type *type_from_name(block*, char*);
+type *get_constant_type(block*, char*);
+type *get_variable_type(block*, char*);
+identifier *get_constant_identifier(block*, char*);
+identifier *get_identifier(block*, char*);
+
+void initialize_variable(block*, identifier*, char*, int, char*);
+
+void create_class_file(block *root_block, FILE *fp);
+void write_method(block *current_block, FILE *fp);
+void write_block_fields(name_table *, FILE*);
+
+void write_paint_method(FILE *fp);
+void write_constructor(FILE *fp);
+void write_run_method(FILE *fp);
+void write_keypressed_method(FILE *fp);
+void write_keyreleased_method(FILE *fp);
+
+void write_locals_stackmap(FILE *fp, identifier *block_identifier, int* stack_map_size);
+void write_stackmap(FILE *fp, type_list *it, int *stack_map_size);
diff --git a/MPC.3.5.LINUX/structures/identifier.c b/MPC.3.5.LINUX/structures/identifier.c
--- /dev/null
@@ -0,0 +1,506 @@
+/********************************************************************
+
+ identifier.c - handling identifier descriptions
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "../classgen/bytecode.h"
+#include "block.h"
+#include "unit.h"
+#include "../util/memory.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+extern FILE* symbols_file;
+
+/*
+ Creates an empty identifier
+*/
+
+identifier *identifier_create()
+{
+ identifier *new_identifier;
+ new_identifier = (identifier*) mem_alloc(sizeof(identifier));
+
+ if (new_identifier == NULL)
+ die(1);
+
+ new_identifier->identifier_class = none;
+
+ new_identifier->standard_function = 0;
+
+ new_identifier->variables = NULL;
+
+ new_identifier->forward_declaration = 0;
+
+ new_identifier->unit_block = NULL;
+
+ new_identifier->unit_function = 0;
+ new_identifier->container_unit = NULL;
+
+ return new_identifier;
+}
+
+
+/*
+ Deletes an identifier
+*/
+void identifier_destroy(identifier *item)
+{
+ switch (item->identifier_class)
+ {
+ case constant_name:
+ {
+ if (item->constant_type->type_class == string_type)
+ string_destroy(item->constant_string_value);
+ type_destroy(item->constant_type);
+ break;
+ }
+
+ case variable_name:
+ {
+ if (item->variable_type != NULL)
+ type_destroy(item->variable_type);
+ break;
+ }
+
+ case type_name:
+ {
+ type_destroy(item->defined_type);
+ break;
+ }
+
+ case procedure_name:
+ {
+ type_list_destroy(item->parameters);
+ if (item->variables != NULL)
+ type_list_destroy(item->variables);
+ break;
+ }
+
+ case function_name:
+ {
+ type_destroy(item->return_type);
+ type_list_destroy(item->parameters);
+ if (item->variables != NULL)
+ type_list_destroy(item->variables);
+ break;
+ }
+
+ case parameter_name:
+ {
+ type_destroy(item->parameter_type);
+ break;
+ }
+
+ case unit_name:
+ {
+ unit_destroy(item->unit_block);
+ break;
+ }
+ }
+
+ mem_free(item);
+}
+
+/*
+ Create a copy of a given identifier
+*/
+identifier *identifier_duplicate(identifier *item)
+{
+ identifier *new_identifier;
+ new_identifier = (identifier*) mem_alloc(sizeof(identifier));
+
+ if (new_identifier == NULL)
+ die(1);
+
+ new_identifier->identifier_class = item->identifier_class;
+ new_identifier->unit_function = item->unit_function;
+
+ switch(new_identifier->identifier_class)
+ {
+ case constant_name:
+ {
+ new_identifier->constant_type = type_duplicate(item->constant_type);
+ switch(item->constant_type->type_class)
+ {
+ case integer_type:
+ {
+ new_identifier->constant_int_value = item->constant_int_value;
+ break;
+ }
+ case char_type:
+ {
+ new_identifier->constant_int_value = item->constant_int_value;
+ break;
+ }
+ case string_type:
+ {
+ new_identifier->constant_string_value = string_duplicate(item->constant_string_value);
+ break;
+ }
+ case boolean_type:
+ {
+ new_identifier->constant_int_value = item->constant_int_value;
+ break;
+ }
+ case real_type:
+ {
+ new_identifier->constant_real_value = item->constant_real_value;
+ break;
+ }
+ case command_type:
+ case record_store_type:
+ case http_type:
+ case image_type:
+ case stream_type:
+ case alert_type:
+ {
+ break;
+ }
+ default:
+ {
+ die(11);
+ }
+ }
+ break;
+ }
+
+ case variable_name:
+ {
+ new_identifier->variable_type = type_duplicate(item->variable_type);
+ new_identifier->variable_index = item->variable_index;
+ break;
+ }
+
+ case type_name:
+ {
+ new_identifier->defined_type = type_duplicate(item->defined_type);
+ break;
+ }
+
+ case procedure_name:
+ {
+ new_identifier->parameters = type_list_duplicate(item->parameters);
+ new_identifier->forward_declaration = item->forward_declaration;
+ new_identifier->standard_function = item->standard_function;
+ new_identifier->variables = type_list_duplicate(item->variables);
+ if (item->container_unit != NULL)
+ new_identifier->container_unit = unit_duplicate(item->container_unit);
+ else
+ new_identifier->container_unit = NULL;
+ break;
+ }
+
+ case function_name:
+ {
+ new_identifier->parameters = type_list_duplicate(item->parameters);
+ new_identifier->return_type = type_duplicate(item->return_type);
+ new_identifier->forward_declaration = item->forward_declaration;
+ new_identifier->standard_function = item->standard_function;
+ new_identifier->variables = type_list_duplicate(item->variables);
+ break;
+ }
+
+ case parameter_name:
+ {
+ new_identifier->parameter_type = type_duplicate(item->parameter_type);
+ new_identifier->is_parameter_variable = item->is_parameter_variable;
+ new_identifier->parameter_index = item->parameter_index;
+ break;
+ }
+
+ case unit_name:
+ {
+ new_identifier->unit_block = unit_duplicate(item->unit_block);
+ break;
+ }
+
+ }
+
+ if (item->container_unit != NULL)
+ new_identifier->container_unit = unit_duplicate(item->container_unit);
+ else
+ new_identifier->container_unit = NULL;
+
+ if (item->unit_block != NULL)
+ new_identifier->unit_block = unit_duplicate(item->unit_block);
+ else
+ new_identifier->unit_block = NULL;
+
+ return new_identifier;
+}
+
+void bsf_write_integer_constant(long int value, char* name)
+{
+ char tag = 1;
+ char type = 1;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(name);
+ fwrite(&type, 1, 1, symbols_file);
+ fwrite(&value, sizeof(long int), 1, symbols_file);
+}
+
+void bsf_write_real_constant(float value, char* name)
+{
+ char tag = 1;
+ char type = 2;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(name);
+ fwrite(&type, 1, 1, symbols_file);
+ fwrite(&value, sizeof(float), 1, symbols_file);
+}
+
+void bsf_write_boolean_constant(char value, char* name)
+{
+ char tag = 1;
+ char type = 3;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(name);
+ fwrite(&type, 1, 1, symbols_file);
+ fwrite(&value, sizeof(char), 1, symbols_file);
+}
+
+void bsf_write_char_constant(char value, char* name)
+{
+ char tag = 1;
+ char type = 4;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(name);
+ fwrite(&type, 1, 1, symbols_file);
+ fwrite(&value, sizeof(char), 1, symbols_file);
+}
+
+void bsf_write_string_constant(string* value, char* name)
+{
+ char tag = 1;
+ char type = 5;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(name);
+ fwrite(&type, 1, 1, symbols_file);
+
+ bsf_write_STRING(string_get_cstr(value));
+}
+
+void bsf_write_variables(string_list* names, type* var_type)
+{
+ string_list *it = names;
+
+ while ((it != NULL) && (it->data != NULL))
+ {
+ char tag = 2;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(string_get_cstr(it->data));
+ bsf_write_TYPE(var_type);
+ it = it->next;
+ }
+}
+
+void bsf_write_type(string* type_name, type* type_type)
+{
+ char tag = 3;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(string_get_cstr(type_name));
+ bsf_write_TYPE(type_type);
+}
+
+void bsf_write_procedure(string* name, type_list* parameters)
+{
+ type_list *it;
+ char params_count = 0;
+
+ char tag = 4;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(string_get_cstr(name));
+
+ params_count = type_list_length(parameters);
+ fwrite(¶ms_count, 1, 1, symbols_file);
+
+ it = parameters;
+
+ while ((it != NULL) && (it->data != NULL))
+ {
+ bsf_write_TYPE(it->data);
+ it = it->next;
+ }
+}
+
+void bsf_write_function(string* name, type_list* parameters, type* return_type)
+{
+ type_list *it;
+ char params_count = 0;
+
+ char tag = 5;
+ fwrite(&tag, 1, 1, symbols_file);
+ bsf_write_STRING(string_get_cstr(name));
+
+ bsf_write_TYPE(return_type);
+
+ params_count = type_list_length(parameters);
+ fwrite(¶ms_count, 1, 1, symbols_file);
+
+ it = parameters;
+
+ while ((it != NULL) && (it->data != NULL))
+ {
+ bsf_write_TYPE(it->data);
+ it = it->next;
+ }
+}
+
+void bsf_write_STRING(char* value)
+{
+ char len = strlen(value);
+ lowercase(value);
+ fwrite(&len, 1, 1, symbols_file);
+ fwrite(value, 1, len, symbols_file);
+}
+
+string* bsf_read_STRING(FILE* file)
+{
+ char length;
+ char *buffer;
+ string* string_value;
+
+ fread(&length, 1, 1, file);
+ buffer = (char*) malloc(length + 5);
+ fread(buffer, 1, length, file);
+ buffer[length] = '\0';
+ string_value = string_from_cstr(buffer);
+ free(buffer);
+
+ return string_value;
+}
+
+void bsf_write_TYPE(type* type_desc)
+{
+ // j-a-s-d
+ #ifdef __GNUC__
+ fwrite((char *)&type_desc->type_class, 1, 1, symbols_file);
+ #else
+ fwrite(&(char)type_desc->type_class, 1, 1, symbols_file);
+ #endif
+
+ if (type_desc->type_class == array_type)
+ {
+ char dimensions;
+ type_list *it;
+
+ bsf_write_TYPE(type_desc->element_type);
+
+ dimensions = type_list_length(type_desc->dimensions_list);
+ fwrite(&dimensions, 1, 1, symbols_file);
+
+ it = type_desc->dimensions_list;
+
+ while ((it != NULL) && (it->data != NULL))
+ {
+ bsf_write_TYPE(it->data);
+ it = it->next;
+ }
+ }
+
+ if (type_desc->type_class == record_type)
+ {
+ char elements;
+ string_list *name_it;
+ type_list *type_it;
+
+ elements = string_list_length(type_desc->elements_name_list);
+ fwrite(&elements, 1, 1, symbols_file);
+
+ name_it = type_desc->elements_name_list;
+ type_it = type_desc->elements_type_list;
+
+ while ((name_it != NULL) && (name_it->data != NULL))
+ {
+ bsf_write_STRING(string_get_cstr(name_it->data));
+ bsf_write_TYPE(type_it->data);
+
+ name_it = name_it->next;
+ type_it = type_it->next;
+ }
+
+ fwrite(&type_desc->unique_record_ID, 4, 1, symbols_file);
+ }
+
+ if (type_desc->type_class == interval_type)
+ {
+ // j-a-s-d
+ #ifdef __GNUC__
+ fwrite((char *)&type_desc->interval_base_type, 1, 1, symbols_file);
+ #else
+ fwrite(&(char)type_desc->interval_base_type, 1, 1, symbols_file);
+ #endif
+ fwrite(&type_desc->first_element, 4, 1, symbols_file);
+ fwrite(&type_desc->last_element, 4, 1, symbols_file);
+ }
+}
+
+type* bsf_read_TYPE(FILE* symbol_file)
+{
+ char type_class;
+
+ type* result_type = type_create();
+
+ fread(&type_class, 1, 1, symbol_file);
+ result_type->type_class = (enum en_type_class)type_class;
+
+ if (result_type->type_class == array_type)
+ {
+ char dimensions;
+
+ result_type->element_type = bsf_read_TYPE(symbol_file);
+ fread(&dimensions, 1, 1, symbol_file);
+
+ result_type->dimensions_list = type_list_create();
+
+ while (dimensions > 0)
+ {
+ type_list_append(result_type->dimensions_list, bsf_read_TYPE(symbol_file));
+ dimensions --;
+ }
+ }
+
+ if (result_type->type_class == record_type)
+ {
+ char elements;
+ fread(&elements, 1, 1, symbol_file);
+
+ result_type->elements_name_list = string_list_create();
+ result_type->elements_type_list = type_list_create();
+
+ while (elements > 0)
+ {
+ string_list_append(result_type->elements_name_list, bsf_read_STRING(symbol_file));
+ type_list_append(result_type->elements_type_list, bsf_read_TYPE(symbol_file));
+ elements --;
+ }
+
+ fread(&result_type->unique_record_ID, sizeof(int), 1, symbol_file);
+ }
+
+ if (result_type->type_class == interval_type)
+ {
+ char base_type_class;
+ fread(&base_type_class, 1, 1, symbol_file);
+
+ result_type->interval_base_type = (enum en_type_class)base_type_class;
+
+ fread(&result_type->first_element, sizeof(long int), 1, symbol_file);
+ fread(&result_type->last_element, sizeof(long int), 1, symbol_file);
+ }
+
+ return result_type;
+}
diff --git a/MPC.3.5.LINUX/structures/identifier.h b/MPC.3.5.LINUX/structures/identifier.h
--- /dev/null
@@ -0,0 +1,169 @@
+/********************************************************************
+
+ identifier.h - structures used to hold identifier descriptions
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+/*
+ When an unit compiles, it exports public symbols into
+
+ unit_name.bsf (binary symbol file)
+
+ The bsf file contains an array of symbol entries.
+
+ Symbols are divided into the following categories:
+
+ Constant
+ ---------
+ 1 byte identifier: set to 1 to indicate that it is an constant
+ STRING - symbol name
+ 1 byte to indicate the constant type, (1-integer, 2-real, 3-boolean, 4-char, 5-string)
+ value: if a constant is integer or float, this is 4-byte field
+ if a constant is string, then a STRING entry follows
+ if a constant is a boolean or a char, 1 byte follows
+
+ Variable
+ --------
+ 1 byte indentifier: set to 2 for variable
+ STRING - symbol name
+ TYPE - variable type
+
+ Type
+ ----
+ 1 byte identifier: set to 3 for type definition
+ STRING - symbol name
+ TYPE - the type description
+
+ Procedure
+ ---------
+ 1 byte identifier: set to 4 for procedures
+ STRING - name
+ 1 byte - the number of parameters (n)
+ TYPE[n] - parameters type
+
+ Function
+ --------
+ 1 byte identifier: set to 5 for functions
+ STRING - name
+ TYPE - return type
+ 1 byte - number of parameters
+ TYPE[n] - parameter types
+
+
+ Special fields used are:
+
+ STRING
+ ------
+ 1 byte containing the string length (n)
+ n bytes with the string data (NOT zero terminated)
+
+ TYPE
+ ----
+ 1 byte : type class, a value from en_type_class enumeration
+
+ if a type is an array: TYPE element_type
+ 1 byte dimensions num
+ TYPE[n] dimension interval types
+
+ if a type is a record: 1 byte number of elements
+ {STRING, TYPE} [n] for each element there is a pair name/type describing the member
+ 4 bytes record ID
+
+ if a type is an interval: 1 byte interval base type (from the en_type_class)
+ 4 bytes: starting value
+ 4 bytes: ending value
+
+*/
+
+#include <stdio.h>
+
+/*
+ The possible identifier classes
+*/
+enum en_identifier_class
+{
+ none,
+ program_name,
+ constant_name,
+ variable_name,
+ type_name,
+ procedure_name,
+ function_name,
+ parameter_name,
+ unit_name
+};
+
+
+/*
+ The structure used to hold the description of
+ a single identifier
+*/
+struct identifier_descriptor_struct
+{
+ enum en_identifier_class identifier_class;
+
+ /* for constants */
+ type *constant_type;
+ int constant_int_value;
+ float constant_real_value;
+ string *constant_string_value;
+
+ /* for variables */
+ type *variable_type;
+ int variable_index;
+
+ /* for types */
+ type *defined_type;
+
+ /* for procedures and functions */
+ type *return_type;
+ type_list *parameters; /* the list of formal parameters to the function, each one is identifier_descriptor */
+ type_list *variables; /* the list of names of variables */
+ int forward_declaration;
+ int standard_function;
+ int subprogram_linenum; /* the number of the first line of the subprogram */
+ int unit_function; /* used by all items that are defined inside an unit , 1 says that the item is inside a unit */
+ struct unit_struct *container_unit;
+
+ /* for parameters */
+ type *parameter_type;
+ short int is_parameter_variable;
+ int parameter_index;
+
+ /* for units */
+ struct unit_struct *unit_block;
+
+ /* this field is set in get_identifier function and is true
+ if this struct describes identifier directly located inside
+ the program block*/
+ int belongs_to_program_block;
+};
+
+
+typedef struct identifier_descriptor_struct identifier;
+
+identifier *identifier_create();
+void identifier_destroy(identifier*);
+identifier *identifier_duplicate(identifier*);
+
+struct type_struct;
+struct string_list_struct;
+struct string_struct;
+
+void bsf_write_integer_constant(long int value, char* name);
+void bsf_write_real_constant(float value, char* name);
+void bsf_write_boolean_constant(char value, char* name);
+void bsf_write_char_constant(char value, char* name);
+void bsf_write_string_constant(string* value, char* name);
+void bsf_write_variables(struct string_list_struct* names, struct type_struct* var_type);
+void bsf_write_type(string* type_name, struct type_struct* type_type);
+void bsf_write_procedure(string* name, type_list* parameters);
+void bsf_write_function(string* name, type_list* parameters, type* return_type);
+void bsf_write_STRING(char* value);
+void bsf_write_TYPE(type* type_desc);
+
+struct string_struct* bsf_read_STRING(FILE*);
+struct type_struct* bsf_read_TYPE(FILE*);
+
diff --git a/MPC.3.5.LINUX/structures/name_table.c b/MPC.3.5.LINUX/structures/name_table.c
--- /dev/null
@@ -0,0 +1,213 @@
+/********************************************************************
+
+ name-table.c - the functions used for name table handling. The
+ name table is a binary tree. The node's left child has the name
+ alphabetically before the name in the node, and the right child
+ has the name which is alphabetically after the name in the node.
+
+ Niksa Orlic, 2004-04-25
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "../classgen/bytecode.h"
+#include "block.h"
+#include "unit.h"
+#include "../util/memory.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+
+/*
+ Create an empty name table.
+*/
+name_table *name_table_create()
+{
+ name_table *new_item;
+ new_item = (name_table*) mem_alloc(sizeof(name_table));
+
+ if (new_item == NULL)
+ die(1);
+
+ new_item->left_child = NULL;
+ new_item->right_child = NULL;
+ new_item->name = NULL;
+ new_item->descriptor = NULL;
+
+ new_item->last = new_item;
+ new_item->next = NULL;
+
+ return new_item;
+}
+
+
+/*
+ Destroy an allocated name table and free all memory.
+*/
+void name_table_destroy(name_table *item)
+{
+ if (item == NULL)
+ return;
+
+ if (item->name != NULL)
+ string_destroy(item->name);
+
+ if (item->descriptor != NULL)
+ identifier_destroy(item->descriptor);
+
+ if (item->left_child != NULL)
+ name_table_destroy(item->left_child);
+
+ if (item->right_child != NULL)
+ name_table_destroy(item->right_child);
+}
+
+/*
+name_table *name_table_duplicate(name_table *item)
+{
+ name_table *new_item = mem_alloc(sizeof(name_table));
+
+ new_item->descriptor = identifier_duplicate(item->descriptor);
+ new_item->name = string_duplicate(item->name);
+
+ if (item->left_child != NULL)
+ new_item->left_child = name_table_duplicate(item->left_child);
+ else
+ new_item->left_child = NULL;
+
+ if (item->right_child != NULL)
+ new_item->right_child = name_table_duplicate(item->right_child);
+ else
+ new_item->right_child = NULL;
+
+ return new_item;
+}*/
+
+
+/*
+ Inserts an entry into the name table. The string and the descriptor are
+ not copied, only pointers to the string and descriptor are copied.
+*/
+void name_table_insert(name_table *root, string *name,
+ identifier *descriptor)
+{
+ int string_compare;
+ name_table *item, *new_item;
+
+ if (root == NULL)
+ return;
+
+ if (root->name == NULL)
+ {
+ /* the root item is empty, insert the value
+ into the root item */
+
+ root->name = name;
+ root->descriptor = descriptor;
+ return;
+ }
+
+
+ /* go through the tree to the first free element */
+ item = root;
+
+ do
+ {
+ string_compare = STRING_COMPARE(string_get_cstr(name), string_get_cstr(item->name));
+
+ if (string_compare == 0)
+ {
+ /* an error occured, just return */
+ return;
+ }
+
+ if (string_compare < 0)
+ {
+ if (item->left_child == NULL)
+ break;
+
+ item = item->left_child;
+ }
+
+ if (string_compare > 0)
+ {
+ if (item->right_child == NULL)
+ break;
+
+ item = item->right_child;
+ }
+ } while (1); /* until the break is called */
+
+ new_item = name_table_create();
+ new_item->name = name;
+ new_item->descriptor = descriptor;
+ new_item->next = NULL;
+
+ root->last->next = new_item;
+ root->last = new_item;
+
+ if (string_compare < 0)
+ item->left_child = new_item;
+
+ if (string_compare > 0)
+ item->right_child = new_item;
+
+}
+
+
+/*
+ Searches name table for an element with a given name.
+ Return the identifier descriptor if found or NULL if
+ not found.
+*/
+identifier* name_table_find(name_table *item, string *name)
+{
+ int string_compare;
+
+ while ((item != NULL) && (item->name != NULL))
+ {
+ string_compare = STRING_COMPARE(string_get_cstr(name), string_get_cstr(item->name));
+
+ if (string_compare == 0)
+ return item->descriptor;
+
+ if (string_compare < 0)
+ item = item->left_child;
+
+ if (string_compare > 0)
+ item = item->right_child;
+
+ }
+
+ return NULL;
+}
+
+identifier *name_table_find_cstr(name_table *item, char *name)
+{
+ int string_compare;
+
+ while ((item != NULL) && (item->name != NULL))
+ {
+ string_compare = STRING_COMPARE(name, string_get_cstr(item->name));
+
+ if (string_compare == 0)
+ return item->descriptor;
+
+ if (string_compare < 0)
+ item = item->left_child;
+
+ if (string_compare > 0)
+ item = item->right_child;
+
+ }
+
+ return NULL;
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/structures/name_table.h b/MPC.3.5.LINUX/structures/name_table.h
--- /dev/null
@@ -0,0 +1,40 @@
+/********************************************************************
+
+ name_table.h - structures and function prototypes for handling
+ names
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+struct name_table_struct
+{
+ string *name;
+ struct name_table_struct *left_child;
+ struct name_table_struct *right_child;
+
+ struct name_table_struct *last; // used only in the first item
+ struct name_table_struct *next;
+
+ identifier *descriptor;
+};
+
+typedef struct name_table_struct name_table;
+
+
+name_table *name_table_create();
+//name_table *name_table_duplicate(name_table*);
+void name_table_destroy(name_table *item);
+void name_table_insert(name_table *root, string *name,
+ identifier *descriptor);
+identifier* name_table_find(name_table *item, string *name);
+identifier *name_table_find_cstr(name_table *item, char *name);
+
+/*
+ Define the case insensitive string-compare routine.
+
+ _stricmp on MSVC
+ strcasecmp on gcc (I think)
+*/
+//#define STRING_COMPARE _stricmp
+#define STRING_COMPARE strcasecmp
diff --git a/MPC.3.5.LINUX/structures/string_list.c b/MPC.3.5.LINUX/structures/string_list.c
--- /dev/null
@@ -0,0 +1,128 @@
+/********************************************************************
+
+ string_list.c - function for handling string lists
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "string_list.h"
+
+
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ Create a new empty list
+*/
+string_list *string_list_create()
+{
+ string_list *new_list = (string_list*) mem_alloc(sizeof(string_list));
+
+ if (new_list == NULL)
+ die(1);
+
+ new_list->data = NULL;
+ new_list->next = NULL;
+
+ return new_list;
+}
+
+
+/*
+ Delete the list and the data in the list
+*/
+void string_list_destroy(string_list* item)
+{
+ string_list *it, *next;
+
+ it = item;
+ while (it != NULL)
+ {
+ next = it->next;
+
+ if (it->data != NULL)
+ string_destroy(it->data);
+
+ mem_free (it);
+
+ it = next;
+ }
+}
+
+/*
+ Creates a copy of the list, the data
+ values are also copied
+*/
+string_list *string_list_duplicate(string_list *item)
+{
+ string_list *new_list;
+
+ new_list = string_list_create();
+
+ if (item->data == NULL)
+ return new_list;
+
+ do
+ {
+ if(item->data == NULL)
+ break;
+
+ string_list_append(new_list, string_duplicate(item->data));
+ item = item->next;
+ } while (item != NULL);
+
+ return new_list;
+}
+
+
+/*
+ Add an element into the list, the data is
+ copied.
+*/
+void string_list_append(string_list *item, string *data)
+{
+ string_list *new_element;
+
+ if (item->data == NULL)
+ item->data = string_duplicate(data);
+ else
+ {
+ new_element = (string_list*) mem_alloc(sizeof(string_list));
+
+ if (new_element == NULL)
+ die(1);
+
+ new_element->data = string_duplicate(data);
+ new_element->next = NULL;
+
+ /* move to the end of the list */
+ while (item->next != NULL)
+ item = item->next;
+
+ item->next = new_element;
+ }
+}
+
+
+/*
+ Returns the number of elements in the list
+*/
+int string_list_length(string_list *item)
+{
+ int counter = 0;
+
+ if (item->data == NULL)
+ return counter;
+
+ do
+ {
+ item = item->next;
+ counter ++;
+ } while (item != NULL);
+
+ return counter;
+}
diff --git a/MPC.3.5.LINUX/structures/string_list.h b/MPC.3.5.LINUX/structures/string_list.h
--- /dev/null
@@ -0,0 +1,22 @@
+/********************************************************************
+
+ string_list.h - list of strings
+
+ Niksa Orlic, 2004-04-29
+
+********************************************************************/
+
+struct string_list_struct
+{
+ struct string_list_struct *next;
+ string *data;
+};
+
+typedef struct string_list_struct string_list;
+
+string_list *string_list_create();
+void string_list_destroy(string_list*);
+
+string_list *string_list_duplicate(string_list*);
+void string_list_append(string_list*, string*);
+int string_list_length(string_list*);
diff --git a/MPC.3.5.LINUX/structures/type.c b/MPC.3.5.LINUX/structures/type.c
--- /dev/null
@@ -0,0 +1,329 @@
+/********************************************************************
+
+ type.c - function for handling types in pascal
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "../classgen/bytecode.h"
+#include "block.h"
+#include "../util/memory.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+extern int linenum;
+
+/*
+ Create an empty type
+*/
+type* type_create()
+{
+ type *new_type;
+ new_type = (type*) mem_alloc(sizeof(type));
+
+ if (new_type == NULL)
+ die(1);
+
+ new_type->type_class = void_type;
+
+ return new_type;
+}
+
+
+/*
+ Deletes a type
+*/
+void type_destroy(type *item)
+{
+ if (item == NULL)
+ return;
+
+ switch(item->type_class)
+ {
+ case array_type:
+ {
+ type_list_destroy(item->dimensions_list);
+ type_destroy(item->element_type);
+ break;
+ }
+
+ case record_type:
+ {
+ type_list_destroy(item->elements_type_list);
+ string_list_destroy(item->elements_name_list);
+ break;
+ }
+ }
+
+ mem_free(item);
+}
+
+
+/*
+ Create a copy of a type
+*/
+type* type_duplicate(type *item)
+{
+ type *new_item;
+ new_item = (type*) mem_alloc(sizeof(type));
+
+ if (new_item == NULL)
+ die(1);
+
+ memcpy(new_item, item, sizeof(type));
+
+ if (new_item->type_class == array_type)
+ {
+ new_item->dimensions_list = type_list_duplicate(item->dimensions_list);
+ new_item->element_type = type_duplicate(item->element_type);
+ }
+
+ if (new_item->type_class == record_type)
+ {
+ new_item->elements_type_list = type_list_duplicate(item->elements_type_list);
+ new_item->elements_name_list = string_list_duplicate(item->elements_name_list);
+ new_item->unique_record_ID = item->unique_record_ID;
+ }
+
+ return new_item;
+}
+
+
+/*
+ Return a nonzero value if both types are equal.
+*/
+int type_equal(type *type1, type *type2)
+{
+ if (type1 == type2)
+ return 1;
+
+ if ((type1 == NULL) || (type2 == NULL))
+ return 0;
+
+ if (type1->type_class != type2->type_class)
+ return 0;
+
+ switch (type1->type_class)
+ {
+ case array_type:
+ {
+ if (!type_equal(type1->element_type, type2->element_type))
+ return 0;
+
+ if (type_list_different_parameter(type1->dimensions_list,
+ type2->dimensions_list) != 0)
+ return 0;
+
+ break;
+ }
+
+ case record_type:
+ {
+ return (type1->unique_record_ID == type2->unique_record_ID);
+
+ break;
+ }
+
+ case interval_type:
+ {
+ if (type1->interval_base_type != type2->interval_base_type)
+ return 0;
+
+ if (type1->first_element != type2->first_element)
+ return 0;
+
+ if (type1->last_element != type2->last_element)
+ return 0;
+
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ Return 0 if types are not equal; 1 if the types
+ are exactly the same, 2 if type1 is real and type2 int
+ or 3 if type2 is real and type1 int
+
+ Also, char can be casted into string
+*/
+int type_equal_cast(type *type1, type* type2)
+{
+ if (type_equal(type1, type2))
+ return 1;
+
+ if ((type1->type_class == real_type)
+ && (type2->type_class == integer_type))
+ return 2;
+
+ if ((type1->type_class == integer_type)
+ && (type2->type_class == real_type))
+ return 3;
+
+ if ((type1->type_class == string_type)
+ && (type2->type_class == char_type))
+ return 2;
+
+ if ((type1->type_class == char_type)
+ && (type2->type_class == string_type))
+ return 3;
+
+ return 0;
+}
+
+
+/*
+ Returns a name for any basic type, string 'unknown type' otherwise
+*/
+string *type_get_name(type *basic_type)
+{
+ switch(basic_type->type_class)
+ {
+ case integer_type:
+ return string_from_cstr("integer");
+
+ case real_type:
+ return string_from_cstr("real");
+
+ case boolean_type:
+ return string_from_cstr("boolean");
+
+ case char_type:
+ return string_from_cstr("char");
+
+ case image_type:
+ return string_from_cstr("image");
+
+ case command_type:
+ return string_from_cstr("command");
+
+ case stream_type:
+ return string_from_cstr("stream");
+
+ case string_type:
+ return string_from_cstr("string");
+
+ case array_type:
+ return string_from_cstr("array");
+
+ case record_type:
+ return string_from_cstr("record");
+
+ case record_store_type:
+ return string_from_cstr("recordStore");
+
+ case http_type:
+ return string_from_cstr("http");
+
+ case alert_type:
+ return string_from_cstr("alert type");
+
+ case interval_type:
+ return string_from_cstr("interval");
+
+ default:
+ return string_from_cstr("unknown type");
+ }
+
+ return NULL;
+}
+
+
+/*
+ Check if any name from element_names already exists in
+ item->elements_name_list
+*/
+void type_record_check_duplicate_names(type *item, string_list *element_names)
+{
+ string_list *item_list;
+
+ while (element_names != NULL)
+ {
+ if (element_names->data != NULL)
+ {
+ item_list = item->elements_name_list;
+
+ while (item_list != NULL)
+ {
+ if (item_list->data != NULL)
+ {
+ if (STRING_COMPARE(string_get_cstr(item_list->data),
+ string_get_cstr(element_names->data)) == 0)
+ {
+ add_error_message(418, string_get_cstr(item_list->data), "");
+ }
+ }
+
+ item_list = item_list->next;
+ }
+ }
+
+ element_names = element_names->next;
+ }
+}
+
+
+/*
+ Add elements into a record type
+*/
+void type_add_record(type *item, string_list *element_names, type *element_type)
+{
+ /* check for duplicate names in the names */
+ type_record_check_duplicate_names(item, element_names);
+
+ while (element_names != NULL)
+ {
+ if (element_names->data != NULL)
+ {
+ string_list_append(item->elements_name_list, element_names->data);
+ type_list_append(item->elements_type_list, element_type);
+ }
+
+ element_names = element_names->next;
+ }
+}
+
+
+/*
+ Returns the type of an element of a given record type identified
+ by a given name. In case of an error, NULL is returned.
+*/
+type* type_find_record_element(type *record, char *cstr)
+{
+ string_list *names;
+ type_list *types;
+
+ if (record->type_class != record_type)
+ return NULL;
+
+ names = record->elements_name_list;
+ types = record->elements_type_list;
+
+ while (names != NULL)
+ {
+ if (names->data != NULL)
+ {
+ if(STRING_COMPARE(cstr, string_get_cstr(names->data)) == 0)
+ {
+ return type_duplicate(types->data);
+ }
+ }
+
+ names = names->next;
+ types = types->next;
+ }
+
+ return NULL;
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/structures/type.h b/MPC.3.5.LINUX/structures/type.h
--- /dev/null
@@ -0,0 +1,74 @@
+/********************************************************************
+
+ type.h - structures used to hold descriptions of pascal types
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+
+/*
+ The possible type classes
+*/
+enum en_type_class
+{
+ error_type, /* used to detect errors */
+ void_type,
+ integer_type,
+ real_type,
+ char_type,
+ boolean_type,
+ string_type,
+ array_type,
+ record_type,
+ interval_type,
+ image_type,
+ command_type,
+ stream_type,
+ record_store_type,
+ http_type,
+ alert_type /* this is only an internal type, the user cannot declare variables to be alert_type */
+
+ /* add our own types */
+} en_type_class;
+
+/*
+ The structure to hold description for a single
+ type.
+*/
+struct type_struct
+{
+ enum en_type_class type_class;
+
+ /* for array types */
+ struct type_struct* element_type; /* the type of array elements */
+ type_list *dimensions_list; /* the type for each dimension */
+
+ /* for record type */
+ string_list *elements_name_list; /* the elements in record, their names */
+ type_list *elements_type_list; /* the elements in record, their types */
+ int unique_record_ID; /* the name that identifies the record */
+
+ /* for interval type */
+ enum en_type_class interval_base_type;
+ long int first_element;
+ long int last_element;
+};
+
+typedef struct type_struct type;
+
+
+type* type_create();
+void type_destroy(type*);
+
+type* type_duplicate(type*);
+
+int type_equal(type*, type*);
+int type_equal_cast(type*, type*);
+
+string *type_get_name(type*);
+
+void type_record_check_duplicate_names(type*, string_list*);
+void type_add_record(type*, string_list*, type*);
+
+type *type_find_record_element(type*, char*);
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/structures/type_list.c b/MPC.3.5.LINUX/structures/type_list.c
--- /dev/null
@@ -0,0 +1,236 @@
+/********************************************************************
+
+ type_list.c - function for handling type lists
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "../classgen/bytecode.h"
+#include "block.h"
+#include "../util/memory.h"
+
+#include <stdlib.h>
+
+/*
+ Create a new empty list
+*/
+type_list *type_list_create()
+{
+ type_list *new_list = (type_list*) mem_alloc(sizeof(type_list));
+
+ if (new_list == NULL)
+ die(1);
+
+ new_list->data = NULL;
+ new_list->next = NULL;
+
+ return new_list;
+}
+
+
+/*
+ Delete the list with all associated data
+*/
+void type_list_destroy(type_list* item)
+{
+ type_list *it, *next;
+ it = item;
+
+ while (it != NULL)
+ {
+ next = it->next;
+
+ if (it->data != NULL)
+ mem_free(it->data);
+
+ mem_free (it);
+
+ it = next;
+ }
+
+}
+
+/*
+ Creates a copy of the list, the data
+ values are also copied
+*/
+type_list *type_list_duplicate(type_list *item)
+{
+ type_list *new_list;
+
+ if (item == NULL)
+ return NULL;
+
+ new_list = type_list_create();
+
+ if ((item == NULL) ||(item->data == NULL))
+ return new_list;
+
+ do
+ {
+ type_list_append(new_list, item->data);
+ item = item->next;
+ } while (item != NULL);
+
+ return new_list;
+}
+
+
+/*
+ Add an element into the list, the data is
+ copied.
+*/
+void type_list_append(type_list *item, struct type_struct *data)
+{
+ type_list *new_element;
+
+ if (item->data == NULL)
+ item->data = type_duplicate(data);
+ else
+ {
+ new_element = (type_list*) mem_alloc(sizeof(type_list));
+
+ if (new_element == NULL)
+ die(1);
+
+ new_element->data = type_duplicate(data);
+ new_element->next = NULL;
+
+ /* move to the end of the list */
+ while (item->next != NULL)
+ item = item->next;
+
+ item->next = new_element;
+ }
+}
+
+
+/*
+ Returns the number of elements in the list
+*/
+int type_list_length(type_list *item)
+{
+ int counter = 0;
+
+ if (item->data == NULL)
+ return counter;
+
+ do
+ {
+ item = item->next;
+ counter ++;
+ } while (item != NULL);
+
+ return counter;
+}
+
+
+/*
+ Returns the index (starting with one) of the first
+ item in the list1 different than the parameetr in the list2,
+ 0 if the lists are equal, or -1 if the list1 is shorter than
+ the list2 and all elements in the list1 correspond to the first
+ n elements in the list2.
+*/
+int type_list_different_parameter(type_list *list1, type_list *list2)
+{
+ int counter = 1;
+
+ while (list1 != NULL)
+ {
+ if ((list2 == NULL)
+ || (list1->data == NULL)
+ || (list2->data == NULL)
+ || (!type_equal(list1->data, list2->data)))
+ {
+ if ((list2 != NULL)
+ && (list1->data == NULL)
+ && (list2->data == NULL))
+ return 0;
+
+ return counter;
+ }
+
+ counter ++;
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+
+ if (list2 != NULL)
+ return -1;
+
+ return 0;
+}
+
+/*
+ Same as the previous function, except that if the list1 element
+ can be casted into list2 element, it is OK !!!
+*/
+int type_list_different_parameter_cast(type_list *list1, type_list *list2)
+{
+ int counter = 1;
+
+ while (list1 != NULL)
+ {
+ if ((list2 == NULL)
+ || (list1->data == NULL)
+ || (list2->data == NULL)
+ || (type_equal_cast(list1->data, list2->data) == 0)
+ || (type_equal_cast(list1->data, list2->data) == 2))
+ {
+ if ((list2 != NULL)
+ && (list1->data == NULL)
+ && (list2->data == NULL))
+ return 0;
+
+ return counter;
+ }
+
+ counter ++;
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+
+ if (list2 != NULL)
+ return -1;
+
+ return 0;
+}
+
+/*
+ Same as the above, but compares interval base types against the types;
+ this is used when checking array dimensions
+*/
+int type_list_different_parameter_array(type_list *real_types, type_list *interval_types)
+{
+ int counter = 1;
+
+ while (real_types != NULL)
+ {
+ if ((interval_types == NULL)
+ || (real_types->data == NULL)
+ || (interval_types->data == NULL)
+ || (real_types->data->type_class != interval_types->data->interval_base_type))
+ {
+ return counter;
+ }
+
+ counter ++;
+ real_types = real_types->next;
+ interval_types = interval_types->next;
+ }
+
+ if (interval_types != NULL)
+ return -1;
+
+ return 0;
+}
diff --git a/MPC.3.5.LINUX/structures/type_list.h b/MPC.3.5.LINUX/structures/type_list.h
--- /dev/null
@@ -0,0 +1,28 @@
+/********************************************************************
+
+ type_list.h - functions to work with typelists
+
+ Niksa Orlic, 2004-04-28
+
+********************************************************************/
+
+
+
+struct type_list_struct
+{
+ struct type_list_struct *next;
+ struct type_struct *data;
+};
+
+typedef struct type_list_struct type_list;
+
+type_list *type_list_create();
+void type_list_destroy(type_list*);
+
+type_list *type_list_duplicate(type_list*);
+void type_list_append(type_list*, struct type_struct*);
+int type_list_length(type_list*);
+
+int type_list_different_parameter(type_list*, type_list*);
+int type_list_different_parameter_array(type_list*, type_list*);
+int type_list_different_parameter_cast(type_list*, type_list*);
diff --git a/MPC.3.5.LINUX/structures/unit.c b/MPC.3.5.LINUX/structures/unit.c
--- /dev/null
@@ -0,0 +1,75 @@
+/********************************************************************
+
+ block.h - structures and functions used to hold program
+ block descriptions
+
+ Niksa Orlic, 2005-03-30
+
+********************************************************************/
+
+#include "../util/strings.h"
+#include "../util/error.h"
+//#include "../util/message.h"
+#include "../classgen/bytecode.h"
+#include "type_list.h"
+#include "string_list.h"
+#include "type.h"
+#include "identifier.h"
+#include "name_table.h"
+#include "block.h"
+#include "unit.h"
+#include "../classgen/preverify.h"
+
+#include "../util/memory.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../classgen/constant_pool.h"
+#include "../classgen/classgen.h"
+
+
+/*
+ Create an empty unit from the given name.
+*/
+unit* unit_create(string *unit_name)
+{
+ unit *new_unit;
+ new_unit = (unit*)mem_alloc(sizeof(unit));
+
+ if (new_unit == NULL)
+ return NULL;
+
+ new_unit->unit_name = unit_name;
+ new_unit->names = name_table_create();
+ new_unit->is_library = 0;
+
+ return new_unit;
+}
+
+/*
+ Destroy a unit.
+*/
+void unit_destroy(unit *old_unit)
+{
+ string_destroy(old_unit->unit_name);
+
+ mem_free(old_unit);
+}
+
+
+/*
+ Duplicate a unit.
+*/
+unit* unit_duplicate(unit *item)
+{
+ unit *new_item;
+ new_item = (unit*) mem_alloc(sizeof(unit));
+
+ new_item->names = item->names;
+ new_item->unit_name = string_duplicate(item->unit_name);
+ new_item->is_library = item->is_library;
+
+ return new_item;
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/structures/unit.h b/MPC.3.5.LINUX/structures/unit.h
--- /dev/null
@@ -0,0 +1,21 @@
+/********************************************************************
+
+ unit.h - structures and functions used to hold unit
+ descriptions
+
+ Niksa Orlic, 2005-03-30
+
+********************************************************************/
+
+struct unit_struct
+{
+ name_table *names;
+ string *unit_name;
+ int is_library; /* set to 1 if it is an external library, or 0 if it is a plain unit */
+};
+
+typedef struct unit_struct unit;
+
+unit* unit_create(string*);
+void unit_destroy(unit*);
+unit* unit_duplicate(unit*);
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/util/error.c b/MPC.3.5.LINUX/util/error.c
--- /dev/null
@@ -0,0 +1,203 @@
+/********************************************************************
+
+ error.c - implementation of error-handling routines
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern char msgstr[1024];
+extern char *source_file_name;
+extern int linenum;
+
+char locbuf[1024];
+short int error_count = 0;
+long int last_error_linenum = -1;
+int new_linenum = 0;
+short int warning_count = 0;
+
+
+char *msg(int i){
+ switch(i)
+ {
+ // General messages
+ case 1: return "Out of memory";
+ case 2: return "Too many errors";
+ case 3: return "Cannot create record file";
+ case 4: return "Cannot create class file";
+ case 5: return "Cannot open source file";
+ case 6: return "Serious error occured, stopping compilation";
+ case 7: return "Cannot create binary symbol file";
+ case 10: return "Internal error #010";
+ case 11: return "Internal error #011";
+ case 12: return "Internal error #012";
+ case 13: return "Internal error #013";
+ case 14: return "Internal error #014";
+ case 15: return "Internal error #015";
+ case 16: return "Internal error #016";
+ case 17: return "Internal error #017";
+ case 18: return "Internal error #018";
+ case 19: return "Internal error #019";
+ case 20: return "Internal error #020";
+ case 21: return "Internal error #021";
+ case 22: return "Internal error #022";
+ case 23: return "Internal error #023";
+ case 24: return "Internal error #024";
+ case 25: return "Internal error #025";
+ case 26: return "Internal error #026 memory";
+ // Scanner errors
+ case 100: return "unknown character \'%s\', ignored";
+ case 101: return "newline in string constant";
+ case 102: return "error in preprocessor statement";
+ // Parser errors
+ case 200: return "character \'%s\' expected, \'%s\' found";
+ case 201: return "unexpected text \'%s\' after program end";
+ case 202: return "identifier (name) expected";
+ case 203: return "keyword \'%s\' expected, \'%s\' found";
+ case 204: return "unexpected token \'%s\'";
+ case 205: return "operator \'=\' expected, \'%s\' found";
+ case 206: return "constant expected";
+ case 207: return "unexpected end of file found";
+ case 208: return "error in parameter list on token \'%s\'";
+ case 209: return "operator \':=\' expected, \'%s\' found";
+ case 210: return "\'packed\' arrays not supported; ordinary array are used";
+ case 211: return "sets are not supported in this version";
+ case 212: return "enumerated types are not supported in this version";
+ case 213: return "operator \'..\' expected, \'%s\' found";
+ case 214: return "keyword \'end\' expected, \'%s\' found";
+ case 215: return "\'with\' is not supported in this version";
+ case 216: return "keyword \'then\' expected, \'%s\' found";
+ case 217: return "constant of type integer or char expected";
+ case 218: return "operator \':=\' expected";
+ case 219: return "\'break\' statemnt found outside of do-while, repeat-until or for loop";
+ case 220: return "compiler does ot support the \'finalization\' part of the unit";
+ case 221: return "procedures and functions may not contain body inside unit interface part";
+ // Semantic errors
+ case 400: return "identifier \'%s\' already defined";
+ case 401: return "method was already declared as forward";
+ case 402: return "a %s with the same name was declared as forward";
+ case 403: return "parameter list is shorter than the list in previous forward declaration";
+ case 404: return "parameter list differs on element %s from the list in previous forward declaration";
+ case 405: return "return type is different than the return type declared in the previous forward declaration";
+ case 406: return "unknown type \'%s\'";
+ case 407: return "%s type expected";
+ case 408: return "integer, char or string type expected";
+ case 409: return "constant of type %s expected, %s found";
+ case 410: return "\'%s\' is not a constant";
+ case 411: return "integer or char type expected";
+ case 412: return "%s type expected, %s type found";
+ case 413: return "wrong type in interval definition";
+ case 414: return "\'%s\' is not a constant";
+ case 415: return "type name or integer/char constant expected, \'%s\' found";
+ case 416: return "error in interval definition";
+ case 417: return "operand is wrong type";
+ case 418: return "name \'%s\' already exists in a record declaration";
+ case 419: return "procedure/function takes 0 arguments, brackets must be left out";
+ case 420: return "procedure/function takes more than 0 arguments, '(' expected";
+ case 421: return "parameter list is too short";
+ case 422: return "error on parameter %s";
+ case 423: return "left and right operands to \':=\' must have the same type";
+ case 424: return "\'.\' operator can only be used on record types";
+ case 425: return "the record does not contain element named \'%s\'";
+ case 426: return "\'[\' operator can only be used on array types";
+ case 427: return "error in array dimensions (array has %s dimensions, %s are specified)";
+ case 428: return "identifier \'%s\' is not procedure, function, variable or unit name";
+ case 429: return "identifier \'%s\' is not constant, function or variable name";
+ case 430: return "only interval types can be used for array indexes";
+ case 431: return "nested functions or procedures are not supported";
+ case 432: return "function \'%s\' cannot be called from here; procedure call or assignement expected";
+ case 433: return "\'run\' is reserved name and cannot be used as a function or procedure name";
+ case 434: return "only string, character, integer or boolean can be appended to string";
+ case 435: return "files are not supported in this version";
+ case 436: return "variable parameters are not supported and are ignored";
+ case 437: return "invalid interval";
+ case 438: return "interval too large";
+ case 439: return "only integer type can be used as string index";
+ case 440: return "variables of interval type are not supported";
+ case 441: return "only forward declaration supplied; the implementation is missing";
+ case 442: return "case statement is not supported in this version";
+ case 443: return "a value cannot be asigned to an array. This is a limitation of MIDletPascal";
+ case 444: return "unknown identifier";
+ case 445: return "name of the procedure/function has already been taken by another identifier";
+ case 446: return "arrays in records (\'%s\') are not implemented. This is a limitation of MIDletPascal";
+ case 447: return "unknown record element \'%s\'";
+ case 448: return "failed to load \'%s\' library/unit";
+ case 449: return "error reading external library file";
+ case 450: return "could not load library/unit \'%s\' because identifier of the same name already exists";
+ case 451: return "serious internal error in library";
+ case 452: return "library/unit contains a method with an incorrect argument type";
+ case 453: return "library/unit does not contain function \'%s\'";
+ case 454: return "unit name must contain at least 2 characters";
+ case 455: return "library/unit does not contain type \'%s\'";
+ case 456: return "iterator used in for-loop must not be defined inside a library/unit";
+ case 457: return "identifier \'%s\' is not a procedure or variable name";
+ case 458: return "identifier \'%s\' is not a function, variable or constant name";
+ case 459: return "identifier \'%s\' found in more units; use syntax 'unit_name'.'identifier' to resolve ambiguity";
+ case 460: return "inlined label \'%d\' (offs:%d) not found";
+ case 461: return "inlined label \'%d\' (offs:%d) already defined";
+ case 462: return "inlined label \'%d\' (offs:%d) tableswitch / loookupswitch";
+ case 463: return "keyword \'%s\' is not allowed here.";
+ case 464: return "use bytecode/end instead of inline() which might be deprecated";
+ }
+}
+
+
+/*
+ Terminate the program and output the error message
+*/
+
+void die(int i)
+{
+ sprintf(msgstr,"Fatal error: %s\n", msg(i));
+ compileMSG();
+ compile_terminate();
+}
+
+
+/*
+ Add an error message, if the total number of errors exceeds 100,
+ die
+*/
+void add_error_message(int num, char *additional_data1, char *additional_data2)
+{
+ if (new_linenum==0)
+ new_linenum=linenum;
+ if (new_linenum != last_error_linenum) {
+ // j-a-s-d
+ if (num < 100)
+ sprintf(locbuf, "[Compiler Error] %s(%d): E%d %s\n", source_file_name, new_linenum, num, msg(num));
+ else
+ sprintf(locbuf, "[Pascal Error] %s(%d): E%d %s\n", source_file_name, new_linenum, num, msg(num));
+
+ sprintf(msgstr, locbuf, additional_data1, additional_data2);
+ compileMSG();
+ error_count ++;
+ if (error_count > 100)
+ die(2);
+ last_error_linenum = new_linenum;
+ }
+ new_linenum=0;
+}
+
+
+/*
+ Add warning message, if the total number of errors exceeds 100,
+ die
+*/
+void add_warning_message(int num, char *additional_data1, char *additional_data2)
+{
+ if (new_linenum==0)
+ new_linenum=linenum;
+ // j-a-s-d
+ sprintf(locbuf, "[Pascal Warning] %s(%d): W%d %s\n", source_file_name, new_linenum, num, msg(num));
+
+ sprintf(msgstr, locbuf, additional_data1, additional_data2);
+ compileMSG();
+ warning_count ++;
+ if (warning_count > 100)
+ die(2);
+ new_linenum=0;
+}
diff --git a/MPC.3.5.LINUX/util/error.h b/MPC.3.5.LINUX/util/error.h
--- /dev/null
@@ -0,0 +1,24 @@
+/********************************************************************
+
+ error.h - declaration of error-handling routines
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+/*
+ Terminate the program and output the error message
+*/
+void die(int i/*char *message*/);
+
+
+/*
+ Adds an error message
+*/
+char *msg(int i);
+
+void add_error_message(/*char *message, long int linenum,*/ int num,
+ char *additional_data1, char *additional_data2);
+
+void add_warning_message(/*char *message, long int linenum,*/ int num,
+ char *additional_data1, char *additional_data2);
diff --git a/MPC.3.5.LINUX/util/memory.c b/MPC.3.5.LINUX/util/memory.c
--- /dev/null
@@ -0,0 +1,213 @@
+/********************************************************************
+
+ memory.c - memory handling routines
+
+ Niksa Orlic, 2005-03-22
+
+********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "memory.h"
+#include "error.h"
+//#include "message.h"
+
+#define SLOWLIST 1
+
+static memory_object* memory_object_list_begin = NULL;
+static memory_object* memory_object_list_end = NULL;
+
+
+/*
+ Initialize the list of memory objects
+*/
+void mem_init()
+{
+ memory_object_list_begin = (memory_object*)malloc(sizeof(memory_object));
+ memory_object_list_begin->next = NULL;
+ memory_object_list_begin->prev = NULL;
+ memory_object_list_begin->data = NULL;
+ memory_object_list_end = memory_object_list_begin;
+}
+
+/*
+ Clean up the list of memory objects
+*/
+void mem_close()
+{
+ memory_object *it = memory_object_list_begin;
+ memory_object *old_object;
+
+ while (it != NULL)
+ {
+ old_object = it;
+ it = it->next;
+#if SLOWLIST
+ if (old_object->data != NULL)
+ free(old_object->data);
+ free(old_object);
+#else
+ mem_free(old_object);
+#endif
+ }
+}
+
+/*
+ Allocate the new block of memory and append it into the list
+*/
+void* mem_alloc(size_t s)
+{
+#if SLOWLIST
+ memory_object *wrapper = (memory_object*)malloc(sizeof(memory_object));
+#else
+ memory_object *wrapper = (memory_object*)malloc(sizeof(memory_object) + s);
+#endif
+ if (wrapper == NULL)
+ return NULL;
+
+#if SLOWLIST
+ wrapper->data = malloc(s);
+ if (wrapper->data == NULL)
+ return NULL;
+#else
+ wrapper->data = (char*)wrapper + sizeof(memory_object);
+#endif
+
+ wrapper->next = NULL;
+ wrapper->prev = memory_object_list_end;
+ memory_object_list_end->next = wrapper;
+ memory_object_list_end = wrapper;
+
+ if (memory_object_list_end == NULL)
+ die(26);
+
+ return wrapper->data;
+}
+
+
+/*
+ Reallocate the new block of memory and append it into the list
+*/
+void* mem_realloc(char* old_block, int s)
+{
+ memory_object *wrapper;
+ memory_object *prev, *next;
+
+ void *new_block;
+
+ prev = next = NULL;
+
+#if SLOWLIST
+ /* find the block */
+ {
+ memory_object *it = memory_object_list_begin;
+
+ while (it != NULL)
+ {
+ if (it->data == old_block)
+ {
+ break;
+ }
+
+ it = it->next;
+ }
+
+ it->data = realloc(it->data, s);
+
+ return it->data;
+ }
+#else
+ prev = ((memory_object*)(old_block - sizeof(memory_object)))->prev;
+ next = ((memory_object*)(old_block - sizeof(memory_object)))->next;
+
+ new_block = realloc(old_block - sizeof(memory_object), sizeof(memory_object) + s);
+
+ if (new_block == NULL)
+ {
+ mem_free(old_block);
+ return NULL;
+ }
+
+ if ((old_block - sizeof(memory_object)) == new_block)
+ return old_block;
+
+ wrapper = (memory_object*) new_block;
+
+ if (prev != NULL)
+ prev->next = wrapper;
+ wrapper->prev = prev;
+
+ if (next != NULL)
+ next->prev = wrapper;
+ wrapper->next = next;
+
+ mem_free(old_block);
+
+ return wrapper->data;
+#endif
+}
+
+/*
+ Free the block of memory
+*/
+void mem_free(char* old_block)
+{
+ memory_object *prev, *next;
+
+ prev = next = NULL;
+
+ if (old_block == NULL)
+ return;
+
+#if SLOWLIST
+ /* find the block */
+ {
+ memory_object *it = memory_object_list_begin;
+
+ while (it != NULL)
+ {
+ if (it->data == old_block)
+ {
+ prev = it->prev;
+ next = it->next;
+
+ if (prev == NULL)
+ {
+ int a = 1;
+ }
+
+ free(old_block);
+ free(it);
+
+ break;
+ }
+
+ it = it->next;
+ }
+
+ if (it == NULL)
+ return;
+ }
+#else
+ prev = ((memory_object*)(old_block - sizeof(memory_object)))->prev;
+ next = ((memory_object*)(old_block - sizeof(memory_object)))->next;
+
+ free(old_block - sizeof(memory_object));
+#endif
+
+ if (prev != NULL)
+ prev->next = next;
+
+ if (next != NULL)
+ next->prev = prev;
+
+ if (next == NULL)
+ memory_object_list_end = prev;
+
+ if (memory_object_list_end == NULL)
+ {
+ int a = 1;
+ }
+
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/util/memory.h b/MPC.3.5.LINUX/util/memory.h
--- /dev/null
@@ -0,0 +1,30 @@
+/********************************************************************
+
+ memory.h - memory handling routines
+
+ Niksa Orlic, 2005-03-22
+
+********************************************************************/
+
+struct memory_object_struct
+{
+ struct memory_object_struct *next;
+ struct memory_object_struct *prev;
+ char *data;
+};
+
+typedef struct memory_object_struct memory_object;
+
+void mem_init();
+void mem_close();
+
+void* mem_alloc(size_t);
+
+// j-a-s-d
+#ifdef __GNUC__
+void* mem_realloc(char*, int);
+void mem_free(char*);
+#else
+void* mem_realloc(void*, int);
+void mem_free(void*);
+#endif
diff --git a/MPC.3.5.LINUX/util/strings.c b/MPC.3.5.LINUX/util/strings.c
--- /dev/null
@@ -0,0 +1,201 @@
+/********************************************************************
+
+ strings.c - implementation of a string-handling routines
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+#include "error.h"
+#include "strings.h"
+#include "memory.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ Create an empty string
+*/
+string* string_create()
+{
+ string *new_string;
+ new_string = (string*) mem_alloc(sizeof(string));
+
+ if (new_string == NULL)
+ die(1);
+
+ new_string->cstr = (char*) mem_alloc(sizeof(char) * 16);
+
+ if (new_string->cstr == NULL)
+ die(1);
+
+ new_string->cstr[0] = '\0';
+
+ new_string->length = 0;
+ new_string->allocated = 16;
+
+ return new_string;
+}
+
+
+/*
+ Create a copy of the string
+*/
+string* string_duplicate(string *str)
+{
+ string *new_string;
+ new_string = (string*) mem_alloc(sizeof(string));
+
+ if (new_string == NULL)
+ die(1);
+
+ new_string->cstr = (char*) mem_alloc(sizeof(char) * (str->allocated));
+
+ if (new_string->cstr == NULL)
+ die(1);
+
+ memcpy(new_string->cstr, str->cstr, str->length + 1); /* also copy the terminating NULL character */
+
+ new_string->allocated = str->allocated;
+ new_string->length = str->length;
+
+ return new_string;
+}
+
+
+/*
+ Create a string from a C-style string
+*/
+string* string_from_cstr(char *cstr)
+{
+ string *new_string;
+ new_string = (string*) mem_alloc(sizeof(string));
+
+ if (new_string == NULL)
+ die(1);
+
+ new_string->cstr = (char*) mem_alloc((strlen(cstr)+5) * sizeof(char));
+
+ if (new_string->cstr == NULL)
+ die(1);
+
+ strcpy(new_string->cstr, cstr);
+
+ new_string->allocated = strlen(cstr) + 5;
+ new_string->length = strlen(cstr);
+
+ return new_string;
+}
+
+
+/*
+ Free all memory used by the string
+*/
+void string_destroy(string *str)
+{
+ mem_free(str->cstr);
+ mem_free(str);
+}
+
+
+/*
+ Empties the given string
+*/
+void string_empty(string *str)
+{
+ str->length = 0;
+ str->cstr[0] = '\0';
+}
+
+
+/*
+ Append the second string to the first string
+*/
+void string_append(string *str1, string *str2)
+{
+ if (str1->length + str2->length + 1 >= str1->allocated)
+ {
+ str1->cstr = (char*) mem_realloc(str1->cstr, sizeof(char)*(str1->length + str2->length + 1));
+
+ if (str1->cstr == NULL)
+ die(1);
+
+ str1->allocated = str1->length + str2->length + 1;
+ }
+
+ memcpy(str1->cstr + str1->length,
+ str2->cstr,
+ str2->length);
+
+ str1->length = str1->length + str2->length;
+
+ str1->cstr[str1->length] = '\0';
+}
+
+
+/*
+ Append the C-style string to the string
+*/
+void string_append_cstr(string *str1, char *cstr2)
+{
+ short int cstr2_length;
+
+ if (str1 == NULL)
+ str1 = string_create();
+
+ cstr2_length = strlen(cstr2);
+
+ if (str1->length + cstr2_length + 1 >= str1->allocated)
+ {
+ str1->cstr = (char*) mem_realloc(str1->cstr, sizeof(char)*(str1->length + cstr2_length + 1));
+
+ if (str1->cstr == NULL)
+ die(1);
+
+ str1->allocated = str1->length + cstr2_length + 1;
+ }
+
+ memcpy(str1->cstr + str1->length,
+ cstr2,
+ cstr2_length);
+
+ str1->length = str1->length + cstr2_length;
+
+ str1->cstr[str1->length] = '\0';
+}
+
+
+/*
+ Get the C-style string from a given string
+*/
+char *string_get_cstr(string *str)
+{
+ return str->cstr;
+}
+
+
+/*
+ Get the string length
+*/
+short int string_length(string *str)
+{
+ return str->length;
+}
+
+/*
+ Translate the string into lowercase
+*/
+void lowercase(char *cstr)
+{
+ int i = 0;
+
+ while (cstr[i] != 0)
+ {
+ if ((cstr[i] >= 'A') && (cstr[i] <= 'Z'))
+ {
+ cstr[i] = cstr[i] | (char) 0x20;
+ }
+
+ i++;
+ }
+}
\ No newline at end of file
diff --git a/MPC.3.5.LINUX/util/strings.h b/MPC.3.5.LINUX/util/strings.h
--- /dev/null
@@ -0,0 +1,76 @@
+/********************************************************************
+
+ strings.h - declaration of a string-handling routines
+
+ Niksa Orlic, 2004-04-19
+
+********************************************************************/
+
+struct string_struct
+{
+ char *cstr;
+ short int length;
+ short int allocated;
+};
+
+typedef struct string_struct string;
+
+
+/*
+ Create an empty string
+*/
+string* string_create();
+
+
+/*
+ Create a copy of the string
+*/
+string* string_duplicate(string*);
+
+
+/*
+ Create a string from a C-style string
+*/
+string* string_from_cstr(char *cstr);
+
+
+/*
+ Free all memory used by the string
+*/
+void string_destroy(string*);
+
+
+/*
+ Empties the given string
+*/
+void string_empty(string*);
+
+
+/*
+ Append the second string to the first string
+*/
+void string_append(string*, string*);
+
+
+/*
+ Append the C-style string to the string
+*/
+void string_append_cstr(string*, char*);
+
+
+/*
+ Get the C-style string from a given string
+*/
+char* string_get_cstr(string*);
+
+
+/*
+ Get the string length
+*/
+short int string_length(string*);
+
+
+/*
+ Translates a string into lower case
+*/
+void lowercase(char *);
\ No newline at end of file
diff --git a/MPS.3.1/F.java b/MPS.3.1/F.java
--- /dev/null
+++ b/MPS.3.1/F.java
@@ -0,0 +1,435 @@
+/*
+ * Fixed-point aritmetika za MIDletPascal
+ * */
+
+public class F
+{
+
+ private F()
+ {
+ }
+
+ // fromInt
+ public static int fI(int i)
+ {
+ return i << 12;
+ }
+
+ // fromint
+ public static int fI(int a, int b)
+ {
+ StringBuffer s = new StringBuffer();
+ s.append(a);
+ s.append('.');
+ s.append(b);
+ return fI(s.toString(),10);
+ }
+
+ // fromInt
+ public static int fI(String s, int radix)
+ {
+ int i = 0;
+ if(s.charAt(0) == '-')
+ i = 1;
+ String s1 = "-1";
+ int j = s.indexOf('.');
+ if(j >= 0)
+ {
+ for(s1 = s.substring(j + 1, s.length()); s1.length() < 4; s1 = s1 + "0");
+ if(s1.length() > 4)
+ s1 = s1.substring(0, 4);
+ } else
+ {
+ j = s.length();
+ }
+ int k = Integer.parseInt(s.substring(i, j), radix);
+ int l = Integer.parseInt(s1, radix) + 1;
+ int i1 = (k << 12) + (l << 12) / 10000;
+ if(i == 1)
+ i1 = -i1;
+ return i1;
+ }
+
+ // toString
+ public static String tS(int i)
+ {
+ boolean flag = false;
+ if(i < 0)
+ {
+ flag = true;
+ i = -i;
+ }
+ int j = i >> 12;
+ int k = 10000 * (i & 0xfff) >> 12;
+ String s;
+ for(s = Integer.toString(k); s.length() < 4; s = "0" + s);
+ return (flag ? "-" : "") + Integer.toString(j) + "." + s;
+ }
+
+ // toInt
+ public static int tI(int i)
+ {
+ if(i >= 0)
+ i += 2048;
+ else
+ i -= 2048;
+ return i >> 12;
+ }
+
+ // div
+ public static int D(int i, int j)
+ {
+ boolean flag = false;
+ if(j == 4096)
+ return i;
+ if((j & 0xfff) == 0)
+ return i / (j >> 12);
+ if(i < 0)
+ {
+ i = -i;
+ flag = true;
+ }
+ if(j < 0)
+ {
+ j = -j;
+ if(flag)
+ flag = false;
+ else
+ flag = true;
+ }
+ byte byte0 = 0;
+ if(i > 0x64fff)
+ byte0 = 3;
+ if(i > 0x3e8fff)
+ byte0 = 4;
+ if(i > 0x7dffff)
+ byte0 = 6;
+ if(i > 0x1f4ffff)
+ byte0 = 8;
+ if(i > 0x7dfffff)
+ byte0 = 10;
+ if(byte0 > 0)
+ {
+ int k = 2 << byte0 - 1;
+ i += k;
+ j += k;
+ }
+ int l = (i << 12 - byte0) / (j >> byte0);
+ return flag ? -l : l;
+ }
+
+ // mult
+ public static int M(int i, int j)
+ {
+ boolean flag = false;
+ if((i & 0xfff) == 0)
+ return (i >> 12) * j;
+ if((j & 0xfff) == 0)
+ return i * (j >> 12);
+ if(i < 0 && j > 0 || i > 0 && j < 0)
+ flag = true;
+ if(i < 0)
+ i = -i;
+ if(j < 0)
+ j = -j;
+ byte byte0 = 0;
+ if(i > 0x64fff || j > 0x64fff)
+ byte0 = 2;
+ if(i > 0x3e8fff || j > 0x3e8fff)
+ byte0 = 4;
+ if(i > 0x271ffff || j > 0x271ffff)
+ byte0 = 6;
+ if(byte0 > 0)
+ {
+ int k = 2 << byte0 - 1;
+ i += k;
+ j += k;
+ }
+ int l = (i >> 12) * (j >> 12) << 12;
+ int i1 = (i & 0xfff) * (j & 0xfff) >> 12;
+ i1 += ((i & 0xfffff000) >> byte0) * ((j & 0xfff) >> byte0) >> 12 - (byte0 << 1);
+ l = l + i1 + (((i & 0xfff) >> byte0) * ((j & 0xfffff000) >> byte0) >> 12 - (byte0 << 1));
+ if(l < 0)
+ return 0;
+ else
+ return flag ? -l : l;
+ }
+
+ // abs
+ public static int A(int i)
+ {
+ if(i < 0)
+ return -i;
+ else
+ return i;
+ }
+
+ // sqrt
+ public static int S(int i, int j)
+ {
+ if(i < 0)
+ return 0;
+ if(i == 0)
+ return 0;
+ int k = i + 4096 >> 1;
+ for(int l = 0; l < j; l++)
+ k = k + D(i, k) >> 1;
+
+ if(k < 0)
+ return 0;
+ else
+ return k;
+ }
+
+ // sqrt
+ public static int S(int i)
+ {
+ byte byte0 = 8;
+ if(i > 0x64000)
+ byte0 = 12;
+ if(i > 0x3e8000)
+ byte0 = 16;
+ return S(i, byte0);
+ }
+
+ // sin
+ public static int s(int i)
+ {
+ int j = 0;
+ for(; i < 0; i += 25736);
+ if(i > 25736)
+ i %= 25736;
+ int k = (i * 10) / 714;
+ if(i != 0 && i != 6434 && i != 12868 && i != 19302 && i != 25736)
+ j = (i * 100) / 714 - k * 10;
+ if(k <= 90)
+ return sin_lookup(k, j);
+ if(k <= 180)
+ return sin_lookup(180 - k, j);
+ if(k <= 270)
+ return -sin_lookup(k - 180, j);
+ else
+ return -sin_lookup(360 - k, j);
+ }
+
+ private static int sin_lookup(int i, int j)
+ {
+ if(j > 0 && j < 10 && i < 90)
+ return SIN_TABLE[i] + ((SIN_TABLE[i + 1] - SIN_TABLE[i]) / 10) * j;
+ else
+ return SIN_TABLE[i];
+ }
+
+ // cos
+ public static int C(int i)
+ {
+ return s(i + 6435);
+ }
+
+ public static int tan(int i)
+ {
+ int j = D(s(i), C(i));
+ return j;
+ }
+
+ public static int cot(int i)
+ {
+ int j = D(fI(1), tan(i));
+ return j;
+ }
+
+ // asin
+ public static int AS(int i)
+ {
+ boolean flag = false;
+ if(i < 0)
+ flag = true;
+ if(A(i) > 4096)
+ return 0;
+ i = A(i);
+ int j = 0;
+ int k = SIN_TABLE.length;
+ for(int l = 0; l < SIN_TABLE.length; l++)
+ {
+ int i1 = A(i - SIN_TABLE[l]);
+ if(i1 < k)
+ {
+ k = i1;
+ j = l;
+ }
+ }
+
+ if(flag)
+ return -(j * 72);
+ else
+ return j * 72;
+ }
+
+ // acos
+ public static int AC(int i)
+ {
+ return 6434 - AS(i);
+ }
+
+ // exp
+ public static int e(int i)
+ {
+ int j = A(i) >> 12;
+ if(j > 13)
+ return 0;
+ int ai[] = {
+ 4096, 11134, 30266, 0x1415e, 0x36992, 0x9469c, 0x1936dc, 0x448a21, 0xba4f54, 0x1fa7158,
+ 0x560a774, 0xe9e2244, 0x27bc2ca9, 0x6c02d646
+ };
+ int k = ai[j];
+ int l = A(i) & 0xfff;
+ if(l > 0)
+ {
+ int i1 = 0;
+ int j1 = 4096;
+ int k1 = 1;
+ for(int l1 = 0; l1 < 6; l1++)
+ {
+ i1 += j1 / k1;
+ j1 = M(j1, l);
+ k1 *= l1 + 1;
+ }
+
+ k = M(k, i1);
+ }
+ if(i < 0)
+ return D(4096, k);
+ else
+ return k;
+ }
+
+ public static int log(int i)
+ {
+ if(i <= 0)
+ return 0;
+ int j = 0;
+ boolean flag = false;
+ int l;
+ for(l = 0; i > 8192; l++)
+ i >>= 1;
+
+ int i1 = l * 2839;
+ int j1 = 0;
+ i -= 4096;
+ for(int k1 = 1; k1 < 11; k1++)
+ {
+ int k;
+ if(j == 0)
+ k = i;
+ else
+ k = M(j, i);
+ if(k == 0)
+ break;
+ j1 += ((k1 % 2 != 0 ? 1 : -1) * k) / k1;
+ j = k;
+ }
+
+ return i1 + j1;
+ }
+
+ public static int log10(int i)
+ {
+ return D(log(i), log(2));
+ }
+
+ // pow
+ public static int p(int i, int j)
+ {
+ boolean flag = false;
+ int k = 1;
+ if(j < 0)
+ {
+ flag = true;
+ j = -j;
+ }
+ if(A(i) < 4096 && j > 12288)
+ {
+ k = e(M(log(i), j));
+ } else
+ {
+ k = pi(i, j >> 12);
+ if((j & 0xfff) != 0)
+ k = M(k, e(M(log(i), j & 0xfff)));
+ }
+ if(flag)
+ return D(4096, k);
+ else
+ return k;
+ }
+
+ private static int pi(int i, int j)
+ {
+ int k = 4096;
+ if(i == 0)
+ return 0;
+ for(int l = 0; l < j; l++)
+ k = M(k, i);
+
+ if(k < 0)
+ return 0;
+ else
+ return k;
+ }
+
+ // to degrees
+ public static int tD(int i)
+ {
+ return 180*D(i, PI);
+ }
+
+ // to radians
+ public static int tR(int i)
+ {
+ return M(i/180, PI);
+ }
+
+ public static int atan(int i)
+ {
+ return AC(D(fI(1), S(1+M(i, i))));
+ }
+
+ public static int atan2(int y, int x)
+ {
+ int res;
+ if (x == 0)
+ {
+ if (y == 0)
+ return 0;
+ if (y > 0)
+ return PI/2;
+ return -PI/2;
+ }
+
+ if (x>0)
+ return atan(D(y,x));
+
+ res = PI - atan(A(D(y,x)));
+
+ if (y>=0)
+ return res;
+ return -res;
+ }
+
+ public static final int MAX_VALUE = 0x7fffffff;
+ public static final int MIN_VALUE = 0x80000001;
+ public static final int E = 11134;
+ public static final int PI = 12868;
+ private static final int SIN_TABLE[] = {
+ 0, 71, 142, 214, 285, 357, 428, 499, 570, 641,
+ 711, 781, 851, 921, 990, 1060, 1128, 1197, 1265, 1333,
+ 1400, 1468, 1534, 1600, 1665, 1730, 1795, 1859, 1922, 1985,
+ 2048, 2109, 2170, 2230, 2290, 2349, 2407, 2464, 2521, 2577,
+ 2632, 2686, 2740, 2793, 2845, 2896, 2946, 2995, 3043, 3091,
+ 3137, 3183, 3227, 3271, 3313, 3355, 3395, 3434, 3473, 3510,
+ 3547, 3582, 3616, 3649, 3681, 3712, 3741, 3770, 3797, 3823,
+ 3849, 3872, 3895, 3917, 3937, 3956, 3974, 3991, 4006, 4020,
+ 4033, 4045, 4056, 4065, 4073, 4080, 4086, 4090, 4093, 4095,
+ 4096
+ };
+
+}
diff --git a/MPS.3.1/FS.java b/MPS.3.1/FS.java
--- /dev/null
+++ b/MPS.3.1/FS.java
@@ -0,0 +1,230 @@
+/*
+ * This class is used when Forms support is needeed
+ * */
+import javax.microedition.lcdui.*;
+
+public class FS
+{
+ /* add a textfiled into the form */
+ public static int Lj(String label, String text,
+ int maxSize, int constraints)
+ {
+ try
+ {
+ return FW.F.append(new TextField(label, text, maxSize, constraints));
+ }
+ catch (Exception E)
+ {
+ return -1;
+ }
+ }
+
+ /* add gauge */
+ public static int Lj(String label, int interactive,
+ int maxValue, int initialValue)
+ {
+ try
+ {
+ boolean inter = true;
+ if (interactive == 0)
+ inter = false;
+ // j-a-s-d: avoid AV false alarm
+ return FW.F.append(new Gauge(label, inter, maxValue, initialValue));
+ }
+ catch (Exception E)
+ {
+ return -1;
+ }
+ }
+
+ /* add choice group */
+ public static int Lj(String label, int type)
+ {
+ try
+ {
+ ChoiceGroup cg = new ChoiceGroup(label, type);
+ return FW.F.append(cg);
+ }
+ catch (Exception E)
+ {
+ return -1;
+ }
+ }
+
+ /* get int value from gauge */
+ public static int Lja(int itemNum)
+ {
+ try
+ {
+ Item it = FW.F.get(itemNum);
+ Gauge g = (Gauge)it;
+ return g.getValue();
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* set value to gauge */
+ public static void Lja(int itemNum, int value)
+ {
+ try
+ {
+ Item it = FW.F.get(itemNum);
+ Gauge g = (Gauge)it;
+ g.setValue(value);
+ }
+ catch(Exception e)
+ {
+ return;
+ }
+ }
+
+ /* get text from textfield */
+ public static String ja(int itemNum)
+ {
+ try
+ {
+ Item it = FW.F.get(itemNum);
+ TextField tf = (TextField)it;
+ return tf.getString();
+ }
+ catch(Exception e)
+ {
+ return "";
+ }
+ }
+
+ /* set text of field */
+ public static void ja(int itemNum, String text)
+ {
+ try
+ {
+ Item it = FW.F.get(itemNum);
+ TextField tf = (TextField)it;
+ tf.setString(text);
+ }
+ catch(Exception e)
+ {
+ return;
+ }
+ }
+
+ /* choice group append item (string, null) */
+ public static int I(int itemNum, String text)
+ {
+ try
+ {
+ ChoiceGroup cg = (ChoiceGroup)FW.F.get(itemNum);
+ return cg.append(text, null);
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* choice group append item (string, image) */
+ public static int I(int itemNum, String text, Image image)
+ {
+ try
+ {
+ ChoiceGroup cg = (ChoiceGroup)FW.F.get(itemNum);
+ return cg.append(text, image);
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* choice is selected item */
+ public static int L(int itemNum, int entryNum)
+ {
+ try
+ {
+ ChoiceGroup cg = (ChoiceGroup)FW.F.get(itemNum);
+ if (cg.isSelected(entryNum))
+ return -1;
+ else
+ return 0;
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* choice get selected item */
+ public static int L(int itemNum)
+ {
+ try
+ {
+ ChoiceGroup cg = (ChoiceGroup)FW.F.get(itemNum);
+ return cg.getSelectedIndex();
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* formAddDateField */
+ public static int dd(String title, int type)
+ {
+ try
+ {
+ DateField df = new DateField(title, type);
+ return FW.F.append(df);
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* formSetDate */
+ public static void dd(int index, int time)
+ {
+ try
+ {
+ DateField df = (DateField)FW.F.get(index);
+ df.setDate(new java.util.Date(((long)time) * 1000));
+ }
+ catch (Exception e)
+ {
+ return;
+ }
+ }
+
+ /* formGetDate*/
+ public static int dd(int index)
+ {
+ try
+ {
+ DateField df = (DateField)FW.F.get(index);
+ return (int) (df.getDate().getTime() / 1000);
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+ /* getFormTitle*/
+ public static String gft()
+ {
+ try
+ {
+ String title = FW.F.getTitle();
+ if (title == null)
+ title = "";
+ return title;
+ }
+ catch (Exception e)
+ {
+ return "";
+ }
+ }
+};
diff --git a/MPS.3.1/FW.java b/MPS.3.1/FW.java
--- /dev/null
+++ b/MPS.3.1/FW.java
@@ -0,0 +1,95 @@
+/*
+ * This is the framework file for the MIDLetPascal generated MIDlets
+ * The Pascal code is compiled into java class called M.
+ * */
+import javax.microedition.midlet.*;
+import javax.microedition.lcdui.*;
+
+public class FW extends MIDlet implements CommandListener
+{
+ public static FW fw = null;
+ public M m = null;
+ public boolean threadStarted = false;
+ public Display display;
+ public static int MP; // MidletPaused
+
+ // command & forms support
+ public static Form F;
+ public static Displayable CD;
+ public static Command LC;
+ public static List L;
+ public static Alert A;
+ public static TextBox TB;
+
+ public void startApp()
+ {
+ MP = 0;
+
+ display = Display.getDisplay(this);
+
+ fw = this;
+
+ LC = null;
+
+ if (m == null)
+ {
+ m = new M();
+
+ M.T = m;
+ M.I = Image.createImage(m.getWidth(), m.getHeight());
+ M.G = M.I.getGraphics();
+ M.KC = 0;
+ L = new List("", List.IMPLICIT);
+ A = new Alert("", "", null, AlertType.INFO);
+ TB = new TextBox("", "", 2, TextField.ANY);
+ display.setCurrent(m);
+ CD = m;
+ try
+ {
+ m.setCommandListener(this);
+ } catch (Exception e)
+ {
+ // do nothing, this catches the exception for NokiaAPI FullCanvas
+ }
+ F = new Form("");
+ F.setCommandListener(this);
+ }
+ else
+ {
+ m.repaint();
+ m.serviceRepaints();
+ }
+
+ if (! threadStarted)
+ {
+ new Thread(m).start();
+ threadStarted = true;
+ }
+ }
+
+ public void pauseApp()
+ {
+ MP = -1;
+ }
+
+
+ public void destroyApp(boolean unconditional)
+ {
+ m = null;
+ M.I = null;
+ M.G = null;
+ CD = null;
+ TB = null;
+ F = null;
+ A = null;
+ L = null;
+ fw = null;
+ LC = null;
+ notifyDestroyed();
+ }
+
+ public void commandAction(Command c, Displayable item) {
+ LC = c;
+ }
+
+}
diff --git a/MPS.3.1/H.java b/MPS.3.1/H.java
--- /dev/null
+++ b/MPS.3.1/H.java
@@ -0,0 +1,155 @@
+// The HTTP class for the MIDletPascal
+import javax.microedition.io.*;
+import java.io.*;
+
+public class H
+{
+ public HttpConnection c = null;
+ public OutputStream o = null;
+ public InputStream i = null;
+
+ // open a http connection
+ public int L(String url)
+ {
+ try
+ {
+ c = (HttpConnection)Connector.open(url);
+ o = c.openOutputStream();
+ return -1;
+ }
+ catch(Exception e)
+ {
+ c = null;
+ return 0;
+ }
+ }
+
+ // return true if the connection is open
+ public int L()
+ {
+ if (c != null)
+ return -1;
+ return 0;
+ }
+
+ // close the connection
+ public void c()
+ {
+ try
+ {
+ if (i != null)
+ {
+ i.close();
+ i = null;
+ }
+ if (o != null)
+ {
+ o.close();
+ o = null;
+ }
+ c.close();
+ c = null;
+ }
+ catch(Exception e)
+ {
+ c = null;
+ }
+ }
+
+ // add http header
+ public void L(String header, String value)
+ {
+ try
+ {
+ c.setRequestProperty(header, value);
+ }
+ catch(Exception e)
+ {}
+ }
+
+ // setRequestMethod :
+ // HEAD, POST, GET bi trebalo rijesiti kao string konstante
+ public void c(String method)
+ {
+ try
+ {
+ c.setRequestMethod(method);
+ }
+ catch(Exception e)
+ {}
+ }
+
+ // get header field
+ public String i(String header)
+ {
+ try
+ {
+ String value;
+ value = c.getHeaderField(header);
+
+ if (value == null)
+ value = "";
+
+ return value;
+ }
+ catch(Exception e)
+ {
+ return "";
+ }
+ }
+
+ // set message text
+ public int o(String message)
+ {
+ try
+ {
+ o.write(message.getBytes());
+
+ return -1;
+ }
+ catch(Exception e)
+ {
+ o = null;
+ return 0;
+ }
+ }
+
+ // getresponse code
+ // ovaj takodjer otvara konekciju i ceka dok se ne odgovori
+ public int o()
+ {
+ try
+ {
+ int code;
+ code = c.getResponseCode();
+ i = c.openInputStream();
+ return code;
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ // read the input data from the connection
+ public String j()
+ {
+ try
+ {
+ StringBuffer retval = new StringBuffer();
+ int c;
+
+ while ((c=i.read()) != -1)
+ {
+ retval.append((char)(char)c);
+ }
+
+ return retval.toString();
+ }
+ catch(Exception e)
+ {
+ return "";
+ }
+ }
+
+};
diff --git a/MPS.3.1/P.java b/MPS.3.1/P.java
--- /dev/null
+++ b/MPS.3.1/P.java
@@ -0,0 +1,101 @@
+/*
+ * The player class used for playing the music.
+ * */
+
+import javax.microedition.media.*;
+
+public class P
+{
+ public static Player p = null;
+
+ /* load music player */
+ public static int a(String resource, String type)
+ {
+ try
+ {
+ if (p != null)
+ {
+ p.close();
+ }
+ p = Manager.createPlayer(FW.fw.getClass().getResourceAsStream(resource), type);
+ p.realize();
+ p.prefetch();
+ }
+ catch (Exception e)
+ {
+ return 0;
+ }
+
+ return -1;
+ }
+
+ /* play */
+ public static int a()
+ {
+ try
+ {
+ if (p == null)
+ return 0;
+
+ p.start();
+ }
+ catch (Exception e)
+ {
+ return 0;
+ }
+
+ return -1;
+ }
+
+ /* stops playing the music */
+ public static void b()
+ {
+ try
+ {
+ if (p != null)
+ {
+ p.stop();
+ }
+ }
+ catch (Exception e)
+ {}
+ }
+
+ /* set loop count, -1 indefinitely */
+ public static int a(int x)
+ {
+ try
+ {
+ if (p != null)
+ {
+ if (p.getState() == Player.STARTED)
+ return 0;
+ p.setLoopCount(x);
+ return -1;
+ }
+
+ } catch (Exception e)
+ {
+ return 0;
+ }
+ return 0;
+ }
+
+ /* get duration time in milliseconds */
+ public static int c()
+ {
+ try
+ {
+ if (p != null)
+ {
+ return (int)(p.getDuration() / 1000);
+ }
+ else return -1;
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+}
diff --git a/MPS.3.1/README.txt b/MPS.3.1/README.txt
--- /dev/null
+++ b/MPS.3.1/README.txt
@@ -0,0 +1,9 @@
+For building this stubs, just call the java compiler and then the preverifier in the regular way.
+
+For example, assumbing you have both in the path, the WTK is in C:\WTK25, and that you have a subdirectory called "bin" to hold the preverified class output, for building the SM class you can do:
+
+javac -g:none -classpath c:\WTK25\lib\midpapi10.jar;c:\WTK25\lib\cldcapi10.jar;c:\WTK25\lib\wma11.jar -source 1.3 -target 1.1 SM.java
+preverify1.1 -nofp -nofinalize -nonative -classpath c:\WTK25\lib\midpapi10.jar;c:\WTK25\lib\cldcapi10.jar;c:\WTK25\lib\wma11.jar -d "bin" "SM"
+
+Enjoy,
+Javier Santo Domingo
diff --git a/MPS.3.1/RS.java b/MPS.3.1/RS.java
--- /dev/null
+++ b/MPS.3.1/RS.java
@@ -0,0 +1,125 @@
+// this is the class to implement record store functionality
+// for MIDletPascal
+import javax.microedition.rms.*;
+
+public class RS
+{
+ // open record store
+ public static RecordStore j(String name)
+ {
+ try
+ {
+ return RecordStore.openRecordStore(name, true);
+ }
+ catch(Exception e)
+ {
+ return null;
+ }
+ }
+
+
+ // closes record store
+ public static void L(RecordStore rs)
+ {
+ try
+ {
+ rs.closeRecordStore();
+ }
+ catch(Exception e)
+ {
+ }
+ }
+
+ // deletes a record store
+ public static void L(String name)
+ {
+ try
+ {
+ RecordStore.deleteRecordStore(name);
+ }
+ catch(Exception e)
+ {
+ }
+ }
+
+ // deletes a record from a record store
+ public static void L(RecordStore rs, int id)
+ {
+ try
+ {
+ rs.deleteRecord(id);
+ }
+ catch(Exception e)
+ {
+ }
+ }
+
+ // adds a record
+ public static int L(RecordStore rs, String data)
+ {
+ try
+ {
+ return rs.addRecord(data.getBytes(), 0, data.length());
+ }
+ catch(Exception e)
+ {
+ return -1;
+ }
+ }
+
+ // sets a data in the entry
+ public static void L(RecordStore rs, String data, int id)
+ {
+ try
+ {
+ rs.setRecord(id, data.getBytes(), 0, data.getBytes().length);
+ }
+ catch (Exception e)
+ {}
+ }
+
+ // returns the next record ID
+ public static int Lja(RecordStore rs)
+ {
+ try
+ {
+ return rs.getNextRecordID();
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+ // read the data from the record store
+ public static String j(RecordStore rs, int id)
+ {
+ try
+ {
+ byte[] res;
+ res = rs.getRecord(id);
+
+ if (res == null)
+ return "";
+
+ return new String(res);
+ }
+ catch(Exception e)
+ {
+ return "";
+ }
+ }
+
+ // return the number of records in the record store
+ public static int j(RecordStore rs)
+ {
+ try
+ {
+ return rs.getNumRecords();
+ }
+ catch(Exception e)
+ {
+ return 0;
+ }
+ }
+};
diff --git a/MPS.3.1/Real.java b/MPS.3.1/Real.java
--- /dev/null
+++ b/MPS.3.1/Real.java
@@ -0,0 +1,6020 @@
+
+
+
+
+
+
+/**
+ * <b>Java integer implementation of 63-bit precision floating point.</b>
+ * <br><i>Version 1.13</i>
+ *
+ * <p>Copyright 2003-2009 Roar Lauritzsen <roarl@pvv.org>
+ *
+ * <blockquote>
+ *
+ * <p>This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * <p>This library 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
+ * for more details.
+ *
+ * <p>The following link provides a copy of the GNU General Public License:
+ * <br> <a
+ * href="http://www.gnu.org/licenses/gpl.txt">http://www.gnu.org/licenses/gpl.txt</a>
+ * <br>If you are unable to obtain the copy from this address, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * </blockquote>
+ *
+ * <p><b>General notes</b>
+ * <ul>
+ *
+ * <li><code>Real</code> objects are not immutable, like Java
+ * <code>Double</code> or <code>BigDecimal</code>. This means that you
+ * should not think of a <code>Real</code> object as a "number", but rather
+ * as a "register holding a number". This design choice is done to encourage
+ * object reuse and limit garbage production for more efficient execution on
+ * e.g. a limited MIDP device. The design choice is reflected in the API,
+ * where an operation like {@link #add(Real) add} does not return a new
+ * object containing the result (as with {@link
+ * java.math.BigDecimal#add(java.math.BigDecimal) BigDecimal}), but rather
+ * adds the argument to the object itself, and returns nothing.
+ *
+ * <li>This library implements infinities and NaN (Not-a-Number) following
+ * the IEEE 754 logic. If an operation produces a result larger (in
+ * magnitude) than the largest representable number, a value representing
+ * positive or negative infinity is generated. If an operation produces a
+ * result smaller than the smallest representable number, a positive or
+ * negative zero is generated. If an operation is undefined, a NaN value is
+ * produced. Abnormal numbers are often fine to use in further
+ * calculations. In most cases where the final result would be meaningful,
+ * abnormal numbers accomplish this, e.g. atan(1/0)=π/2. In most cases
+ * where the final result is not meaningful, a NaN will be produced.
+ * <i>No exception is ever (deliberately) thrown.</i>
+ *
+ * <li>Error bounds listed under <a href="#method_detail">Method Detail</a>
+ * are calculated using William Rossi's <a
+ * href="http://dfp.sourceforge.net/">rossi.dfp.dfp</a> at 40 decimal digits
+ * accuracy. Error bounds are for "typical arguments" and may increase when
+ * results approach zero or
+ * infinity. The abbreviation {@link Math#ulp(double) ULP} means Unit in the
+ * Last Place. An error bound of ½ ULP means that the result is correctly
+ * rounded. The relative execution time listed under each method is the
+ * average from running on SonyEricsson T610 (R3C), K700i, and Nokia 6230i.
+ *
+ * <li>The library is not thread-safe. Static <code>Real</code> objects are
+ * used extensively as temporary values to avoid garbage production and the
+ * overhead of <code>new</code>. To make the library thread-safe, references
+ * to all these static objects must be replaced with code that instead
+ * allocates new <code>Real</code> objects in their place.
+ *
+ * <li>There is one bug that occurs again and again and is really difficult
+ * to debug. Although the pre-calculated constants are declared <code>static
+ * final</code>, Java cannot really protect the contents of the objects in
+ * the same way as <code>const</code>s are protected in C/C++. Consequently,
+ * you can accidentally change these values if you send them into a function
+ * that modifies its arguments. If you were to modify {@link #ONE Real.ONE}
+ * for instance, many of the succeeding calculations would be wrong because
+ * the same variable is used extensively in the internal calculations of
+ * Real.java.
+ *
+ * </ul>
+ */
+public final class Real
+{
+ /**
+ * The mantissa of a <code>Real</code>. <i>To maintain numbers in a
+ * normalized state and to preserve the integrity of abnormal numbers, it
+ * is discouraged to modify the inner representation of a
+ * <code>Real</code> directly.</i>
+ *
+ * <p>The number represented by a <code>Real</code> equals:<br>
+ * -1<sup>sign</sup> · mantissa · 2<sup>-62</sup> · 2<sup>exponent-0x40000000</sup>
+ *
+ * <p>The normalized mantissa of a finite <code>Real</code> must be
+ * between <code>0x4000000000000000L</code> and
+ * <code>0x7fffffffffffffffL</code>. Using a denormalized
+ * <code>Real</code> in <u>any</u> operation other than {@link
+ * #normalize()} may produce undefined results. The mantissa of zero and
+ * of an infinite value is <code>0x0000000000000000L</code>.
+ *
+ * <p>The mantissa of a NaN is any nonzero value. However, it is
+ * recommended to use the value <code>0x4000000000000000L</code>. Any
+ * other values are reserved for future extensions.
+ */
+ public long mantissa;
+ /**
+ * The exponent of a <code>Real</code>. <i>To maintain numbers in a
+ * normalized state and to preserve the integrity of abnormal numbers, it
+ * is discouraged to modify the inner representation of a
+ * <code>Real</code> directly.</i>
+ *
+ * <p>The exponent of a finite <code>Real</code> must be between
+ * <code>0x00000000</code> and <code>0x7fffffff</code>. The exponent of
+ * zero <code>0x00000000</code>.
+ *
+ * <p>The exponent of an infinite value and of a NaN is any negative
+ * value. However, it is recommended to use the value
+ * <code>0x80000000</code>. Any other values are reserved for future
+ * extensions.
+ */
+ public int exponent;
+ /**
+ * The sign of a <code>Real</code>. <i>To maintain numbers in a normalized
+ * state and to preserve the integrity of abnormal numbers, it is
+ * discouraged to modify the inner representation of a <code>Real</code>
+ * directly.</i>
+ *
+ * <p>The sign of a finite, zero or infinite <code>Real</code> is 0 for
+ * positive values and 1 for negative values. Any other values may produce
+ * undefined results.
+ *
+ * <p>The sign of a NaN is ignored. However, it is recommended to use the
+ * value <code>0</code>. Any other values are reserved for future
+ * extensions.
+ */
+ public byte sign;
+ /**
+ * Set to <code>false</code> during numerical algorithms to favor accuracy
+ * over prettyness. This flag is initially set to <code>true</code>.
+ *
+ * <p>The flag controls the operation of a subtraction of two
+ * almost-identical numbers that differ only in the last three bits of the
+ * mantissa. With this flag enabled, the result of such a subtraction is
+ * rounded down to zero. Probabilistically, this is the correct course of
+ * action in an overwhelmingly large percentage of calculations.
+ * However, certain numerical algorithms such as differentiation depend
+ * on keeping maximum accuracy during subtraction.
+ *
+ * <p>Note, that because of <code>magicRounding</code>,
+ * <code>a.sub(b)</code> may produce zero even though
+ * <code>a.equalTo(b)</code> returns <code>false</code>. This must be
+ * considered e.g. when trying to avoid division by zero.
+ */
+ public static boolean magicRounding = true;
+ /**
+ * A <code>Real</code> constant holding the exact value of 0. Among other
+ * uses, this value is used as a result when a positive underflow occurs.
+ */
+ public static final Real ZERO = new Real(0,0x00000000,0x0000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 1.
+ */
+ public static final Real ONE = new Real(0,0x40000000,0x4000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 2.
+ */
+ public static final Real TWO = new Real(0,0x40000001,0x4000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 3.
+ */
+ public static final Real THREE= new Real(0,0x40000001,0x6000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 5.
+ */
+ public static final Real FIVE = new Real(0,0x40000002,0x5000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 10.
+ */
+ public static final Real TEN = new Real(0,0x40000003,0x5000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 100.
+ */
+ public static final Real HUNDRED=new Real(0,0x40000006,0x6400000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of 1/2.
+ */
+ public static final Real HALF = new Real(0,0x3fffffff,0x4000000000000000L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to 1/3.
+ */
+ public static final Real THIRD= new Real(0,0x3ffffffe,0x5555555555555555L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to 1/10.
+ */
+ public static final Real TENTH= new Real(0,0x3ffffffc,0x6666666666666666L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to 1/100.
+ */
+ public static final Real PERCENT=new Real(0,0x3ffffff9,0x51eb851eb851eb85L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * square root of 2.
+ */
+ public static final Real SQRT2= new Real(0,0x40000000,0x5a827999fcef3242L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * square root of 1/2.
+ */
+ public static final Real SQRT1_2=new Real(0,0x3fffffff,0x5a827999fcef3242L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to 2π.
+ */
+ public static final Real PI2 = new Real(0,0x40000002,0x6487ed5110b4611aL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to π, the
+ * ratio of the circumference of a circle to its diameter.
+ */
+ public static final Real PI = new Real(0,0x40000001,0x6487ed5110b4611aL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to π/2.
+ */
+ public static final Real PI_2 = new Real(0,0x40000000,0x6487ed5110b4611aL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to π/4.
+ */
+ public static final Real PI_4 = new Real(0,0x3fffffff,0x6487ed5110b4611aL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to π/8.
+ */
+ public static final Real PI_8 = new Real(0,0x3ffffffe,0x6487ed5110b4611aL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to <i>e</i>,
+ * the base of the natural logarithms.
+ */
+ public static final Real E = new Real(0,0x40000001,0x56fc2a2c515da54dL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * natural logarithm of 2.
+ */
+ public static final Real LN2 = new Real(0,0x3fffffff,0x58b90bfbe8e7bcd6L);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * natural logarithm of 10.
+ */
+ public static final Real LN10 = new Real(0,0x40000001,0x49aec6eed554560bL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * base-2 logarithm of <i>e</i>.
+ */
+ public static final Real LOG2E= new Real(0,0x40000000,0x5c551d94ae0bf85eL);
+ /**
+ * A <code>Real</code> constant that is closer than any other to the
+ * base-10 logarithm of <i>e</i>.
+ */
+ public static final Real LOG10E=new Real(0,0x3ffffffe,0x6f2dec549b9438cbL);
+ /**
+ * A <code>Real</code> constant holding the maximum non-infinite positive
+ * number = 4.197e323228496.
+ */
+ public static final Real MAX = new Real(0,0x7fffffff,0x7fffffffffffffffL);
+ /**
+ * A <code>Real</code> constant holding the minimum non-zero positive
+ * number = 2.383e-323228497.
+ */
+ public static final Real MIN = new Real(0,0x00000000,0x4000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the value of NaN (not-a-number).
+ * This value is always used as a result to signal an invalid operation.
+ */
+ public static final Real NAN = new Real(0,0x80000000,0x4000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the value of positive infinity.
+ * This value is always used as a result to signal a positive overflow.
+ */
+ public static final Real INF = new Real(0,0x80000000,0x0000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the value of negative infinity.
+ * This value is always used as a result to signal a negative overflow.
+ */
+ public static final Real INF_N= new Real(1,0x80000000,0x0000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the value of negative zero. This
+ * value is used as a result e.g. when a negative underflow occurs.
+ */
+ public static final Real ZERO_N=new Real(1,0x00000000,0x0000000000000000L);
+ /**
+ * A <code>Real</code> constant holding the exact value of -1.
+ */
+ public static final Real ONE_N= new Real(1,0x40000000,0x4000000000000000L);
+ private static final int clz_magic = 0x7c4acdd;
+ private static final byte[] clz_tab =
+ { 31,22,30,21,18,10,29, 2,20,17,15,13, 9, 6,28, 1,
+ 23,19,11, 3,16,14, 7,24,12, 4, 8,25, 5,26,27, 0 };
+ /**
+ * Creates a new <code>Real</code> with a value of zero.
+ */
+ public Real() {
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value of another
+ * <code>Real</code>. See {@link #assign(Real)}.
+ *
+ * @param a the <code>Real</code> to assign.
+ */
+ public Real(Real a) {
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value of an integer. See
+ * {@link #assign(int)}.
+ *
+ * @param a the <code>int</code> to assign.
+ */
+ public Real(int a) {
+ assign(a);
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value of a long
+ * integer. See {@link #assign(long)}.
+ *
+ * @param a the <code>long</code> to assign.
+ */
+ public Real(long a) {
+ assign(a);
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value encoded in a
+ * <code>String</code> using base-10. See {@link #assign(String)}.
+ *
+ * @param a the <code>String</code> to assign.
+ */
+ public Real(String a) {
+ assign(a,10);
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value encoded in a
+ * <code>String</code> using the specified number base. See {@link
+ * #assign(String,int)}.
+ *
+ * @param a the <code>String</code> to assign.
+ * @param base the number base of <code>a</code>. Valid base values are 2,
+ * 8, 10 and 16.
+ */
+ public Real(String a, int base) {
+ assign(a,base);
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning a value by directly setting
+ * the fields of the internal representation. The arguments must represent
+ * a valid, normalized <code>Real</code>. This is the fastest way of
+ * creating a constant value. See {@link #assign(int,int,long)}.
+ *
+ * @param s {@link #sign} bit, 0 for positive sign, 1 for negative sign
+ * @param e {@link #exponent}
+ * @param m {@link #mantissa}
+ */
+ public Real(int s, int e, long m) {
+ { this.sign=(byte)s; this.exponent=e; this.mantissa=m; };
+ }
+ /**
+ * Creates a new <code>Real</code>, assigning the value previously encoded
+ * into twelve consecutive bytes in a byte array using {@link
+ * #toBytes(byte[],int) toBytes}. See {@link #assign(byte[],int)}.
+ *
+ * @param data byte array to decode into this <code>Real</code>.
+ * @param offset offset to start encoding from. The bytes
+ * <code>data[offset]...data[offset+11]</code> will be
+ * read.
+ */
+ public Real(byte [] data, int offset) {
+ assign(data,offset);
+ }
+ /**
+ * Assigns this <code>Real</code> the value of another <code>Real</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to assign.
+ */
+ public void assign(Real a) {
+ if (a == null) {
+ makeZero();
+ return;
+ }
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ }
+ /**
+ * Assigns this <code>Real</code> the value of an integer.
+ * All integer values can be represented without loss of accuracy.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = (double)a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to assign.
+ */
+ public void assign(int a) {
+ if (a==0) {
+ makeZero();
+ return;
+ }
+ sign = 0;
+ if (a<0) {
+ sign = 1;
+ a = -a; // Also works for 0x80000000
+ }
+ // Normalize int
+ int t=a; t|=t>>1; t|=t>>2; t|=t>>4; t|=t>>8; t|=t>>16;
+ t = clz_tab[(t*clz_magic)>>>27]-1;
+ exponent = 0x4000001E-t;
+ mantissa = ((long)a)<<(32+t);
+ }
+ /**
+ * Assigns this <code>Real</code> the value of a signed long integer.
+ * All long values can be represented without loss of accuracy.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = (double)a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>long</code> to assign.
+ */
+ public void assign(long a) {
+ sign = 0;
+ if (a<0) {
+ sign = 1;
+ a = -a; // Also works for 0x8000000000000000
+ }
+ exponent = 0x4000003E;
+ mantissa = a;
+ normalize();
+ }
+ /**
+ * Assigns this <code>Real</code> a value encoded in a <code>String</code>
+ * using base-10, as specified in {@link #assign(String,int)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Double.{@link Double#valueOf(String) valueOf}(a);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * ½-1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 80
+ * </td></tr></table>
+ *
+ * @param a the <code>String</code> to assign.
+ */
+ public void assign(String a) {
+ assign(a,10);
+ }
+ /**
+ * Assigns this <code>Real</code> a value encoded in a <code>String</code>
+ * using the specified number base. The string is parsed as follows:
+ *
+ * <ul>
+ * <li>If the string is <code>null</code> or an empty string, zero is
+ * assigned.
+ * <li>Leading spaces are ignored.
+ * <li>An optional sign, '+', '-' or '/', where '/' precedes a negative
+ * two's-complement number, reading: "an infinite number of 1-bits
+ * preceding the number".
+ * <li>Optional digits preceding the radix, in the specified base.
+ * <ul>
+ * <li>In base-2, allowed digits are '01'.
+ * <li>In base-8, allowed digits are '01234567'.
+ * <li>In base-10, allowed digits are '0123456789'.
+ * <li>In base-16, allowed digits are '0123456789ABCDEF'.
+ </ul>
+ * <li>An optional radix character, '.' or ','.
+ * <li>Optional digits following the radix.
+ * <li>The following spaces are ignored.
+ * <li>An optional exponent indicator, 'e'. If not base-16, or after a
+ * space, 'E' is also accepted.
+ * <li>An optional sign, '+' or '-'.
+ * <li>Optional exponent digits <i><b>in base-10</b></i>.
+ * </ul>
+ *
+ * <p><i>Valid examples:</i><br>
+ * base-2: <code>"-.110010101e+5"</code><br>
+ * base-8: <code>"+5462E-99"</code><br>
+ * base-10: <code>" 3,1415927"</code><br>
+ * base-16: <code>"/FFF800C.CCCE e64"</code>
+ *
+ * <p>The number is parsed until the end of the string or an unknown
+ * character is encountered, then silently returns even if the whole
+ * string has not been parsed. Please note that specifying an
+ * excessive number of digits in base-10 may in fact decrease the
+ * accuracy of the result because of the extra multiplications performed.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td>
+ * <td colspan="2">
+ * <code>this = Double.{@link Double#valueOf(String) valueOf}(a);
+ * // Works only for base-10</code>
+ * </td></tr><tr><td valign="top" rowspan="2"><i>
+ * Approximate error bound:</i>
+ * </td><td width="1%">base-10</td><td>
+ * ½-1 ULPs
+ * </td></tr><tr><td>2/8/16</td><td>
+ * ½ ULPs
+ * </td></tr><tr><td valign="top" rowspan="4"><i>
+ * Execution time relative to add: </i>
+ * </td><td width="1%">base-2</td><td>
+ * 54
+ * </td></tr><tr><td>base-8</td><td>
+ * 60
+ * </td></tr><tr><td>base-10</td><td>
+ * 80
+ * </td></tr><tr><td>base-16 </td><td>
+ * 60
+ * </td></tr></table>
+ *
+ * @param a the <code>String</code> to assign.
+ * @param base the number base of <code>a</code>. Valid base values are
+ * 2, 8, 10 and 16.
+ */
+ public void assign(String a, int base) {
+ if (a==null || a.length()==0) {
+ assign(ZERO);
+ return;
+ }
+ atof(a,base);
+ }
+ /**
+ * Assigns this <code>Real</code> a value by directly setting the fields
+ * of the internal representation. The arguments must represent a valid,
+ * normalized <code>Real</code>. This is the fastest way of assigning a
+ * constant value.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = (1-2*s) * m *
+ * Math.{@link Math#pow(double,double)
+ * pow}(2.0,e-0x400000e3);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @param s {@link #sign} bit, 0 for positive sign, 1 for negative sign
+ * @param e {@link #exponent}
+ * @param m {@link #mantissa}
+ */
+ public void assign(int s, int e, long m) {
+ sign = (byte)s;
+ exponent = e;
+ mantissa = m;
+ }
+ /**
+ * Assigns this <code>Real</code> a value previously encoded into into
+ * twelve consecutive bytes in a byte array using {@link
+ * #toBytes(byte[],int) toBytes}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.2
+ * </td></tr></table>
+ *
+ * @param data byte array to decode into this <code>Real</code>.
+ * @param offset offset to start encoding from. The bytes
+ * <code>data[offset]...data[offset+11]</code> will be
+ * read.
+ */
+ public void assign(byte [] data, int offset) {
+ sign = (byte)((data[offset+4]>>7)&1);
+ exponent = (((data[offset ]&0xff)<<24)+
+ ((data[offset +1]&0xff)<<16)+
+ ((data[offset +2]&0xff)<<8)+
+ ((data[offset +3]&0xff)));
+ mantissa = (((long)(data[offset+ 4]&0x7f)<<56)+
+ ((long)(data[offset+ 5]&0xff)<<48)+
+ ((long)(data[offset+ 6]&0xff)<<40)+
+ ((long)(data[offset+ 7]&0xff)<<32)+
+ ((long)(data[offset+ 8]&0xff)<<24)+
+ ((long)(data[offset+ 9]&0xff)<<16)+
+ ((long)(data[offset+10]&0xff)<< 8)+
+ ( (data[offset+11]&0xff)));
+ }
+ /**
+ * Encodes an accurate representation of this <code>Real</code> value into
+ * twelve consecutive bytes in a byte array. Can be decoded using {@link
+ * #assign(byte[],int)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.2
+ * </td></tr></table>
+ *
+ * @param data byte array to save this <code>Real</code> in.
+ * @param offset offset to start encoding to. The bytes
+ * <code>data[offset]...data[offset+11]</code> will be
+ * written.
+ */
+ public void toBytes(byte [] data, int offset) {
+ data[offset ] = (byte)(exponent>>24);
+ data[offset+ 1] = (byte)(exponent>>16);
+ data[offset+ 2] = (byte)(exponent>>8);
+ data[offset+ 3] = (byte)(exponent);
+ data[offset+ 4] = (byte)((sign<<7)+(mantissa>>56));
+ data[offset+ 5] = (byte)(mantissa>>48);
+ data[offset+ 6] = (byte)(mantissa>>40);
+ data[offset+ 7] = (byte)(mantissa>>32);
+ data[offset+ 8] = (byte)(mantissa>>24);
+ data[offset+ 9] = (byte)(mantissa>>16);
+ data[offset+10] = (byte)(mantissa>>8);
+ data[offset+11] = (byte)(mantissa);
+ }
+ /**
+ * Assigns this <code>Real</code> the value corresponding to a given bit
+ * representation. The argument is considered to be a representation of a
+ * floating-point value according to the IEEE 754 floating-point "single
+ * format" bit layout.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>float</code><i> code:</i></td><td>
+ * <code>this = Float.{@link Float#intBitsToFloat(int)
+ * intBitsToFloat}(bits);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @param bits a <code>float</code> value encoded in an <code>int</code>.
+ */
+ public void assignFloatBits(int bits) {
+ sign = (byte)(bits>>>31);
+ exponent = (bits>>23)&0xff;
+ mantissa = (long)(bits&0x007fffff)<<39;
+ if (exponent == 0 && mantissa == 0)
+ return; // Valid zero
+ if (exponent == 0 && mantissa != 0) {
+ // Degenerate small float
+ exponent = 0x40000000-126;
+ normalize();
+ return;
+ }
+ if (exponent <= 254) {
+ // Normal IEEE 754 float
+ exponent += 0x40000000-127;
+ mantissa |= 1L<<62;
+ return;
+ }
+ if (mantissa == 0)
+ makeInfinity(sign);
+ else
+ makeNan();
+ }
+ /**
+ * Assigns this <code>Real</code> the value corresponding to a given bit
+ * representation. The argument is considered to be a representation of a
+ * floating-point value according to the IEEE 754 floating-point "double
+ * format" bit layout.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Double.{@link Double#longBitsToDouble(long)
+ * longBitsToDouble}(bits);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @param bits a <code>double</code> value encoded in a <code>long</code>.
+ */
+ public void assignDoubleBits(long bits) {
+ sign = (byte)((bits>>63)&1);
+ exponent = (int)((bits>>52)&0x7ff);
+ mantissa = (bits&0x000fffffffffffffL)<<10;
+ if (exponent == 0 && mantissa == 0)
+ return; // Valid zero
+ if (exponent == 0 && mantissa != 0) {
+ // Degenerate small float
+ exponent = 0x40000000-1022;
+ normalize();
+ return;
+ }
+ if (exponent <= 2046) {
+ // Normal IEEE 754 float
+ exponent += 0x40000000-1023;
+ mantissa |= 1L<<62;
+ return;
+ }
+ if (mantissa == 0)
+ makeInfinity(sign);
+ else
+ makeNan();
+ }
+ /**
+ * Returns a representation of this <code>Real</code> according to the
+ * IEEE 754 floating-point "single format" bit layout.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>float</code><i> code:</i></td><td>
+ * <code>Float.{@link Float#floatToIntBits(float)
+ * floatToIntBits}(this)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.7
+ * </td></tr></table>
+ *
+ * @return the bits that represent the floating-point number.
+ */
+ public int toFloatBits() {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return 0x7fffffff; // nan
+ int e = exponent-0x40000000+127;
+ long m = mantissa;
+ // Round properly!
+ m += 1L<<38;
+ if (m<0) {
+ m >>>= 1;
+ e++;
+ if (exponent < 0) // Overflow
+ return (sign<<31)|0x7f800000; // inf
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || e > 254)
+ return (sign<<31)|0x7f800000; // inf
+ if ((this.exponent == 0 && this.mantissa == 0) || e < -22)
+ return (sign<<31); // zero
+ if (e <= 0) // Degenerate small float
+ return (sign<<31)|((int)(m>>>(40-e))&0x007fffff);
+ // Normal IEEE 754 float
+ return (sign<<31)|(e<<23)|((int)(m>>>39)&0x007fffff);
+ }
+ /**
+ * Returns a representation of this <code>Real</code> according to the
+ * IEEE 754 floating-point "double format" bit layout.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>Double.{@link Double#doubleToLongBits(double)
+ * doubleToLongBits}(this)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.7
+ * </td></tr></table>
+ *
+ * @return the bits that represent the floating-point number.
+ */
+ public long toDoubleBits() {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return 0x7fffffffffffffffL; // nan
+ int e = exponent-0x40000000+1023;
+ long m = mantissa;
+ // Round properly!
+ m += 1L<<9;
+ if (m<0) {
+ m >>>= 1;
+ e++;
+ if (exponent < 0)
+ return ((long)sign<<63)|0x7ff0000000000000L; // inf
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || e > 2046)
+ return ((long)sign<<63)|0x7ff0000000000000L; // inf
+ if ((this.exponent == 0 && this.mantissa == 0) || e < -51)
+ return ((long)sign<<63); // zero
+ if (e <= 0) // Degenerate small double
+ return ((long)sign<<63)|((m>>>(11-e))&0x000fffffffffffffL);
+ // Normal IEEE 754 double
+ return ((long)sign<<63)|((long)e<<52)|((m>>>10)&0x000fffffffffffffL);
+ }
+ /**
+ * Makes this <code>Real</code> the value of positive zero.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = 0;</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.2
+ * </td></tr></table>
+ */
+ public void makeZero() {
+ sign = 0;
+ mantissa = 0;
+ exponent = 0;
+ }
+ /**
+ * Makes this <code>Real</code> the value of zero with the specified sign.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = 0.0 * (1-2*s);</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.2
+ * </td></tr></table>
+ *
+ * @param s sign bit, 0 to make a positive zero, 1 to make a negative zero
+ */
+ public void makeZero(int s) {
+ sign = (byte)s;
+ mantissa = 0;
+ exponent = 0;
+ }
+ /**
+ * Makes this <code>Real</code> the value of infinity with the specified
+ * sign.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Double.{@link Double#POSITIVE_INFINITY POSITIVE_INFINITY}
+ * * (1-2*s);</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @param s sign bit, 0 to make positive infinity, 1 to make negative
+ * infinity
+ */
+ public void makeInfinity(int s) {
+ sign = (byte)s;
+ mantissa = 0;
+ exponent = 0x80000000;
+ }
+ /**
+ * Makes this <code>Real</code> the value of Not-a-Number (NaN).
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Double.{@link Double#NaN NaN};</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ */
+ public void makeNan() {
+ sign = 0;
+ mantissa = 0x4000000000000000L;
+ exponent = 0x80000000;
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * zero, <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this == 0)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object is
+ * zero, <code>false</code> otherwise.
+ */
+ public boolean isZero() {
+ return (exponent == 0 && mantissa == 0);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * infinite, <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>Double.{@link Double#isInfinite(double) isInfinite}(this)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object is
+ * infinite, <code>false</code> if it is finite or NaN.
+ */
+ public boolean isInfinity() {
+ return (exponent < 0 && mantissa == 0);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * Not-a-Number (NaN), <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>Double.{@link Double#isNaN(double) isNaN}(this)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object is
+ * NaN, <code>false</code> otherwise.
+ */
+ public boolean isNan() {
+ return (exponent < 0 && mantissa != 0);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * finite, <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(!Double.{@link Double#isNaN(double) isNaN}(this) &&
+ * !Double.{@link Double#isInfinite(double)
+ * isInfinite}(this))</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object is
+ * finite, <code>false</code> if it is infinite or NaN.
+ */
+ public boolean isFinite() {
+ // That is, non-infinite and non-nan
+ return (exponent >= 0);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * finite and nonzero, <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(!Double.{@link Double#isNaN(double) isNaN}(this) &&
+ * !Double.{@link Double#isInfinite(double) isInfinite}(this) &&
+ * (this!=0))</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object is
+ * finite and nonzero, <code>false</code> if it is infinite, NaN or
+ * zero.
+ */
+ public boolean isFiniteNonZero() {
+ // That is, non-infinite and non-nan and non-zero
+ return (exponent >= 0 && mantissa != 0);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code> is
+ * negative, <code>false</code> otherwise.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this < 0)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object
+ * is negative, <code>false</code> if it is positive or NaN.
+ */
+ public boolean isNegative() {
+ return sign!=0;
+ }
+ /**
+ * Calculates the absolute value.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#abs(double) abs}(this);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.2
+ * </td></tr></table>
+ */
+ public void abs() {
+ sign = 0;
+ }
+ /**
+ * Negates this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = -this;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.2
+ * </td></tr></table>
+ */
+ public void neg() {
+ if (!(this.exponent < 0 && this.mantissa != 0))
+ sign ^= 1;
+ }
+ /**
+ * Copies the sign from <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#abs(double)
+ * abs}(this)*Math.{@link Math#signum(double) signum}(a);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.2
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to copy the sign from.
+ */
+ public void copysign(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ sign = a.sign;
+ }
+ /**
+ * Readjusts the mantissa of this <code>Real</code>. The exponent is
+ * adjusted accordingly. This is necessary when the mantissa has been
+ * {@link #mantissa modified directly} for some purpose and may be
+ * denormalized. The normalized mantissa of a finite <code>Real</code>
+ * must have bit 63 cleared and bit 62 set. Using a denormalized
+ * <code>Real</code> in <u>any</u> other operation may produce undefined
+ * results.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.7
+ * </td></tr></table>
+ */
+ public void normalize() {
+ if ((this.exponent >= 0)) {
+ if (mantissa > 0)
+ {
+ int clz = 0;
+ int t = (int)(mantissa>>>32);
+ if (t == 0) { clz = 32; t = (int)mantissa; }
+ t|=t>>1; t|=t>>2; t|=t>>4; t|=t>>8; t|=t>>16;
+ clz += clz_tab[(t*clz_magic)>>>27]-1;
+ mantissa <<= clz;
+ exponent -= clz;
+ if (exponent < 0) // Underflow
+ makeZero(sign);
+ }
+ else if (mantissa < 0)
+ {
+ mantissa = (mantissa+1)>>>1;
+ exponent ++;
+ if (mantissa == 0) { // Ooops, it was 0xffffffffffffffffL
+ mantissa = 0x4000000000000000L;
+ exponent ++;
+ }
+ if (exponent < 0) // Overflow
+ makeInfinity(sign);
+ }
+ else // mantissa == 0
+ {
+ exponent = 0;
+ }
+ }
+ }
+ /**
+ * Readjusts the mantissa of a <code>Real</code> with extended
+ * precision. The exponent is adjusted accordingly. This is necessary when
+ * the mantissa has been {@link #mantissa modified directly} for some
+ * purpose and may be denormalized. The normalized mantissa of a finite
+ * <code>Real</code> must have bit 63 cleared and bit 62 set. Using a
+ * denormalized <code>Real</code> in <u>any</u> other operation may
+ * produce undefined results.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Approximate error bound:</i></td><td>
+ * 2<sup>-64</sup> ULPs (i.e. of a normal precision <code>Real</code>)
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.7
+ * </td></tr></table>
+ *
+ * @param extra the extra 64 bits of mantissa of this extended precision
+ * <code>Real</code>.
+ * @return the extra 64 bits of mantissa of the resulting extended
+ * precision <code>Real</code>.
+ */
+ public long normalize128(long extra) {
+ if (!(this.exponent >= 0))
+ return 0;
+ if (mantissa == 0) {
+ if (extra == 0) {
+ exponent = 0;
+ return 0;
+ }
+ mantissa = extra;
+ extra = 0;
+ exponent -= 64;
+ if (exponent < 0) { // Underflow
+ makeZero(sign);
+ return 0;
+ }
+ }
+ if (mantissa < 0) {
+ extra = (mantissa<<63)+(extra>>>1);
+ mantissa >>>= 1;
+ exponent ++;
+ if (exponent < 0) { // Overflow
+ makeInfinity(sign);
+ return 0;
+ }
+ return extra;
+ }
+ int clz = 0;
+ int t = (int)(mantissa>>>32);
+ if (t == 0) { clz = 32; t = (int)mantissa; }
+ t|=t>>1; t|=t>>2; t|=t>>4; t|=t>>8; t|=t>>16;
+ clz += clz_tab[(t*clz_magic)>>>27]-1;
+ if (clz == 0)
+ return extra;
+ mantissa = (mantissa<<clz)+(extra>>>(64-clz));
+ extra <<= clz;
+ exponent -= clz;
+ if (exponent < 0) { // Underflow
+ makeZero(sign);
+ return 0;
+ }
+ return extra;
+ }
+ /**
+ * Rounds an extended precision <code>Real</code> to the nearest
+ * <code>Real</code> of normal precision. Replaces the contents of this
+ * <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param extra the extra 64 bits of mantissa of this extended precision
+ * <code>Real</code>.
+ */
+ public void roundFrom128(long extra) {
+ mantissa += (extra>>63)&1;
+ normalize();
+ }
+ /**
+ * Returns <code>true</code> if this Java object is the same
+ * object as <code>a</code>. Since a <code>Real</code> should be
+ * thought of as a "register holding a number", this method compares the
+ * object references, not the contents of the two objects.
+ * This is very different from {@link #equalTo(Real)}.
+ *
+ * @param a the object to compare to this.
+ * @return <code>true</code> if this object is the same as <code>a</code>.
+ */
+ public boolean equals(Object a) {
+ return this==a;
+ }
+ private int compare(Real a) {
+ // Compare of normal floats, zeros, but not nan or equal-signed inf
+ if ((this.exponent == 0 && this.mantissa == 0) && (a.exponent == 0 && a.mantissa == 0))
+ return 0;
+ if (sign != a.sign)
+ return a.sign-sign;
+ int s = (this.sign==0) ? 1 : -1;
+ if ((this.exponent < 0 && this.mantissa == 0))
+ return s;
+ if ((a.exponent < 0 && a.mantissa == 0))
+ return -s;
+ if (exponent != a.exponent)
+ return exponent<a.exponent ? -s : s;
+ if (mantissa != a.mantissa)
+ return mantissa<a.mantissa ? -s : s;
+ return 0;
+ }
+ private boolean invalidCompare(Real a) {
+ return ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0) ||
+ ((this.exponent < 0 && this.mantissa == 0) && (a.exponent < 0 && a.mantissa == 0) && sign == a.sign));
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is equal to
+ * <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned. This method must not be confused with {@link #equals(Object)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this == a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * equal to the value represented by <code>a</code>. <code>false</code>
+ * otherwise, or if the numbers are incomparable.
+ */
+ public boolean equalTo(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) == 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is equal to
+ * the integer <code>a</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this == a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * equal to the integer <code>a</code>. <code>false</code>
+ * otherwise.
+ */
+ public boolean equalTo(int a) {
+ tmp0.assign(a);
+ return equalTo(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is not equal to
+ * <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned.
+ * This distinguishes <code>notEqualTo(a)</code> from the expression
+ * <code>!equalTo(a)</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this != a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is not
+ * equal to the value represented by <code>a</code>. <code>false</code>
+ * otherwise, or if the numbers are incomparable.
+ */
+ public boolean notEqualTo(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) != 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is not equal to
+ * the integer <code>a</code>.
+ * If this <code>Real</code> is NaN, <code>false</code> is always
+ * returned.
+ * This distinguishes <code>notEqualTo(a)</code> from the expression
+ * <code>!equalTo(a)</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this != a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is not
+ * equal to the integer <code>a</code>. <code>false</code>
+ * otherwise, or if this <code>Real</code> is NaN.
+ */
+ public boolean notEqualTo(int a) {
+ tmp0.assign(a);
+ return notEqualTo(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is less than
+ * <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this < a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * less than the value represented by <code>a</code>.
+ * <code>false</code> otherwise, or if the numbers are incomparable.
+ */
+ public boolean lessThan(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) < 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is less than
+ * the integer <code>a</code>.
+ * If this <code>Real</code> is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this < a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * less than the integer <code>a</code>. <code>false</code> otherwise,
+ * or if this <code>Real</code> is NaN.
+ */
+ public boolean lessThan(int a) {
+ tmp0.assign(a);
+ return lessThan(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is less than or
+ * equal to <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this <= a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * less than or equal to the value represented by <code>a</code>.
+ * <code>false</code> otherwise, or if the numbers are incomparable.
+ */
+ public boolean lessEqual(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) <= 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is less than or
+ * equal to the integer <code>a</code>.
+ * If this <code>Real</code> is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this <= a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * less than or equal to the integer <code>a</code>. <code>false</code>
+ * otherwise, or if this <code>Real</code> is NaN.
+ */
+ public boolean lessEqual(int a) {
+ tmp0.assign(a);
+ return lessEqual(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is greater than
+ * <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this > a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * greater than the value represented by <code>a</code>.
+ * <code>false</code> otherwise, or if the numbers are incomparable.
+ */
+ public boolean greaterThan(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) > 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is greater than
+ * the integer <code>a</code>.
+ * If this <code>Real</code> is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this > a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * greater than the integer <code>a</code>.
+ * <code>false</code> otherwise, or if this <code>Real</code> is NaN.
+ */
+ public boolean greaterThan(int a) {
+ tmp0.assign(a);
+ return greaterThan(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is greater than
+ * or equal to <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are infinities of
+ * the same sign or any of them is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this >= a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * greater than or equal to the value represented by <code>a</code>.
+ * <code>false</code> otherwise, or if the numbers are incomparable.
+ */
+ public boolean greaterEqual(Real a) {
+ if (invalidCompare(a))
+ return false;
+ return compare(a) >= 0;
+ }
+ /**
+ * Returns <code>true</code> if this <code>Real</code> is greater than
+ * or equal to the integer <code>a</code>.
+ * If this <code>Real</code> is NaN, <code>false</code> is always
+ * returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this >= a)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.7
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to compare to this.
+ * @return <code>true</code> if the value represented by this object is
+ * greater than or equal to the integer <code>a</code>.
+ * <code>false</code> otherwise, or if this <code>Real</code> is NaN.
+ */
+ public boolean greaterEqual(int a) {
+ tmp0.assign(a);
+ return greaterEqual(tmp0);
+ }
+ /**
+ * Returns <code>true</code> if the absolute value of this
+ * <code>Real</code> is less than the absolute value of
+ * <code>a</code>.
+ * If the numbers are incomparable, i.e. the values are both infinite
+ * or any of them is NaN, <code>false</code> is always returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(Math.{@link Math#abs(double) abs}(this) <
+ * Math.{@link Math#abs(double) abs}(a))</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.5
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to compare to this.
+ * @return <code>true</code> if the absolute of the value represented by
+ * this object is less than the absolute of the value represented by
+ * <code>a</code>.
+ * <code>false</code> otherwise, or if the numbers are incomparable.
+ */
+ public boolean absLessThan(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0) || (this.exponent < 0 && this.mantissa == 0))
+ return false;
+ if ((a.exponent < 0 && a.mantissa == 0))
+ return true;
+ if (exponent != a.exponent)
+ return exponent<a.exponent;
+ return mantissa<a.mantissa;
+ }
+ /**
+ * Multiplies this <code>Real</code> by 2 to the power of <code>n</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * This operation is faster than normal multiplication since it only
+ * involves adding to the exponent.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this *= Math.{@link Math#pow(double,double) pow}(2.0,n);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.3
+ * </td></tr></table>
+ *
+ * @param n the integer argument.
+ */
+ public void scalbn(int n) {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ exponent += n;
+ if (exponent < 0) {
+ if (n<0)
+ makeZero(sign); // Underflow
+ else
+ makeInfinity(sign); // Overflow
+ }
+ }
+ /**
+ * Calculates the next representable neighbour of this <code>Real</code>
+ * in the direction towards <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * If the two values are equal, nothing happens.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this += Math.{@link Math#ulp(double) ulp}(this)*Math.{@link
+ * Math#signum(double) signum}(a-this);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.8
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument.
+ */
+ public void nextafter(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) && (a.exponent < 0 && a.mantissa == 0) && sign == a.sign)
+ return;
+ int dir = -compare(a);
+ if (dir == 0)
+ return;
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ { this.mantissa = MIN.mantissa; this.exponent = MIN.exponent; this.sign = MIN.sign; };
+ sign = (byte)(dir<0 ? 1 : 0);
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ { this.mantissa = MAX.mantissa; this.exponent = MAX.exponent; this.sign = MAX.sign; };
+ sign = (byte)(dir<0 ? 0 : 1);
+ return;
+ }
+ if ((this.sign==0) ^ dir<0) {
+ mantissa ++;
+ } else {
+ if (mantissa == 0x4000000000000000L) {
+ mantissa <<= 1;
+ exponent--;
+ }
+ mantissa --;
+ }
+ normalize();
+ }
+ /**
+ * Calculates the largest (closest to positive infinity)
+ * <code>Real</code> value that is less than or equal to this
+ * <code>Real</code> and is equal to a mathematical integer.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#floor(double) floor}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.5
+ * </td></tr></table>
+ */
+ public void floor() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ if (exponent < 0x40000000) {
+ if ((this.sign==0))
+ makeZero(sign);
+ else {
+ exponent = ONE.exponent;
+ mantissa = ONE.mantissa;
+ // sign unchanged!
+ }
+ return;
+ }
+ int shift = 0x4000003e-exponent;
+ if (shift <= 0)
+ return;
+ if ((this.sign!=0))
+ mantissa += ((1L<<shift)-1);
+ mantissa &= ~((1L<<shift)-1);
+ if ((this.sign!=0))
+ normalize();
+ }
+ /**
+ * Calculates the smallest (closest to negative infinity)
+ * <code>Real</code> value that is greater than or equal to this
+ * <code>Real</code> and is equal to a mathematical integer.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#ceil(double) ceil}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.8
+ * </td></tr></table>
+ */
+ public void ceil() {
+ neg();
+ floor();
+ neg();
+ }
+ /**
+ * Rounds this <code>Real</code> value to the closest value that is equal
+ * to a mathematical integer. If two <code>Real</code> values that are
+ * mathematical integers are equally close, the result is the integer
+ * value with the largest magnitude (positive or negative). Replaces the
+ * contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#rint(double) rint}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.3
+ * </td></tr></table>
+ */
+ public void round() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ if (exponent < 0x3fffffff) {
+ makeZero(sign);
+ return;
+ }
+ int shift = 0x4000003e-exponent;
+ if (shift <= 0)
+ return;
+ mantissa += 1L<<(shift-1); // Bla-bla, this works almost
+ mantissa &= ~((1L<<shift)-1);
+ normalize();
+ }
+ /**
+ * Truncates this <code>Real</code> value to the closest value towards
+ * zero that is equal to a mathematical integer.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = (double)((long)this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.2
+ * </td></tr></table>
+ */
+ public void trunc() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ if (exponent < 0x40000000) {
+ makeZero(sign);
+ return;
+ }
+ int shift = 0x4000003e-exponent;
+ if (shift <= 0)
+ return;
+ mantissa &= ~((1L<<shift)-1);
+ normalize();
+ }
+ /**
+ * Calculates the fractional part of this <code>Real</code> by subtracting
+ * the closest value towards zero that is equal to a mathematical integer.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this -= (double)((long)this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.2
+ * </td></tr></table>
+ */
+ public void frac() {
+ if (!(this.exponent >= 0 && this.mantissa != 0) || exponent < 0x40000000)
+ return;
+ int shift = 0x4000003e-exponent;
+ if (shift <= 0) {
+ makeZero(sign);
+ return;
+ }
+ mantissa &= ((1L<<shift)-1);
+ normalize();
+ }
+ /**
+ * Converts this <code>Real</code> value to the closest <code>int</code>
+ * value towards zero.
+ *
+ * <p>If the value of this <code>Real</code> is too large, {@link
+ * Integer#MAX_VALUE} is returned. However, if the value of this
+ * <code>Real</code> is too small, <code>-Integer.MAX_VALUE</code> is
+ * returned, not {@link Integer#MIN_VALUE}. This is done to ensure that
+ * the sign will be correct if you calculate
+ * <code>-this.toInteger()</code>. A NaN is converted to 0.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(int)this</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @return an <code>int</code> representation of this <code>Real</code>.
+ */
+ public int toInteger() {
+ if ((this.exponent == 0 && this.mantissa == 0) || (this.exponent < 0 && this.mantissa != 0))
+ return 0;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ return ((this.sign==0)) ? 0x7fffffff : 0x80000001;
+ // 0x80000001, so that you can take -x.toInteger()
+ }
+ if (exponent < 0x40000000)
+ return 0;
+ int shift = 0x4000003e-exponent;
+ if (shift < 32) {
+ return ((this.sign==0)) ? 0x7fffffff : 0x80000001;
+ // 0x80000001, so that you can take -x.toInteger()
+ }
+ return (this.sign==0) ?
+ (int)(mantissa>>>shift) : -(int)(mantissa>>>shift);
+ }
+ /**
+ * Converts this <code>Real</code> value to the closest <code>long</code>
+ * value towards zero.
+ *
+ * <p>If the value of this <code>Real</code> is too large, {@link
+ * Long#MAX_VALUE} is returned. However, if the value of this
+ * <code>Real</code> is too small, <code>-Long.MAX_VALUE</code> is
+ * returned, not {@link Long#MIN_VALUE}. This is done to ensure that the
+ * sign will be correct if you calculate <code>-this.toLong()</code>.
+ * A NaN is converted to 0.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(long)this</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.5
+ * </td></tr></table>
+ *
+ * @return a <code>long</code> representation of this <code>Real</code>.
+ */
+ public long toLong() {
+ if ((this.exponent == 0 && this.mantissa == 0) || (this.exponent < 0 && this.mantissa != 0))
+ return 0;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ return ((this.sign==0))? 0x7fffffffffffffffL:0x8000000000000001L;
+ // 0x8000000000000001L, so that you can take -x.toLong()
+ }
+ if (exponent < 0x40000000)
+ return 0;
+ int shift = 0x4000003e-exponent;
+ if (shift < 0) {
+ return ((this.sign==0))? 0x7fffffffffffffffL:0x8000000000000001L;
+ // 0x8000000000000001L, so that you can take -x.toLong()
+ }
+ return (this.sign==0) ? (mantissa>>>shift) : -(mantissa>>>shift);
+ }
+ /**
+ * Returns <code>true</code> if the value of this <code>Real</code>
+ * represents a mathematical integer. If the value is too large to
+ * determine if it is an integer, <code>true</code> is returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>(this == (long)this)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the value represented by this object
+ * represents a mathematical integer, <code>false</code> otherwise.
+ */
+ public boolean isIntegral() {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return false;
+ if ((this.exponent == 0 && this.mantissa == 0) || (this.exponent < 0 && this.mantissa == 0))
+ return true;
+ if (exponent < 0x40000000)
+ return false;
+ int shift = 0x4000003e-exponent;
+ if (shift <= 0)
+ return true;
+ return (mantissa&((1L<<shift)-1)) == 0;
+ }
+ /**
+ * Returns <code>true</code> if the mathematical integer represented
+ * by this <code>Real</code> is odd. You <u>must</u> first determine
+ * that the value is actually an integer using {@link
+ * #isIntegral()}. If the value is too large to determine if the
+ * integer is odd, <code>false</code> is returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>((((long)this)&1) == 1)</code>
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.6
+ * </td></tr></table>
+ *
+ * @return <code>true</code> if the mathematical integer represented by
+ * this <code>Real</code> is odd, <code>false</code> otherwise.
+ */
+ public boolean isOdd() {
+ if (!(this.exponent >= 0 && this.mantissa != 0) ||
+ exponent < 0x40000000 || exponent > 0x4000003e)
+ return false;
+ int shift = 0x4000003e-exponent;
+ return ((mantissa>>>shift)&1) != 0;
+ }
+ /**
+ * Exchanges the contents of this <code>Real</code> and <code>a</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>tmp=this; this=a; a=tmp;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 0.5
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to exchange with this.
+ */
+ public void swap(Real a) {
+ long tmpMantissa=mantissa; mantissa=a.mantissa; a.mantissa=tmpMantissa;
+ int tmpExponent=exponent; exponent=a.exponent; a.exponent=tmpExponent;
+ byte tmpSign =sign; sign =a.sign; a.sign =tmpSign;
+ }
+ // Temporary values used by functions (to avoid "new" inside functions)
+ private static Real tmp0 = new Real(); // tmp for basic functions
+ private static Real recipTmp = new Real();
+ private static Real recipTmp2 = new Real();
+ private static Real sqrtTmp = new Real();
+ private static Real expTmp = new Real();
+ private static Real expTmp2 = new Real();
+ private static Real expTmp3 = new Real();
+ private static Real tmp1 = new Real();
+ private static Real tmp2 = new Real();
+ private static Real tmp3 = new Real();
+ private static Real tmp4 = new Real();
+ private static Real tmp5 = new Real();
+ /**
+ * Calculates the sum of this <code>Real</code> and <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this += a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * «« 1.0 »»
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to add to this.
+ */
+ public void add(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ if ((this.exponent < 0 && this.mantissa == 0) && (a.exponent < 0 && a.mantissa == 0) && sign != a.sign)
+ makeNan();
+ else
+ makeInfinity((this.exponent < 0 && this.mantissa == 0) ? sign : a.sign);
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent == 0 && this.mantissa == 0))
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ if ((this.exponent == 0 && this.mantissa == 0))
+ sign=0;
+ return;
+ }
+ byte s;
+ int e;
+ long m;
+ if (exponent > a.exponent ||
+ (exponent == a.exponent && mantissa>=a.mantissa))
+ {
+ s = a.sign;
+ e = a.exponent;
+ m = a.mantissa;
+ } else {
+ s = sign;
+ e = exponent;
+ m = mantissa;
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ }
+ int shift = exponent-e;
+ if (shift>=64)
+ return;
+ if (sign == s) {
+ mantissa += m>>>shift;
+ if (mantissa >= 0 && shift>0 && ((m>>>(shift-1))&1) != 0)
+ mantissa ++; // We don't need normalization, so round now
+ if (mantissa < 0) {
+ // Simplified normalize()
+ mantissa = (mantissa+1)>>>1;
+ exponent ++;
+ if (exponent < 0) { // Overflow
+ makeInfinity(sign);
+ return;
+ }
+ }
+ } else {
+ if (shift>0) {
+ // Shift mantissa up to increase accuracy
+ mantissa <<= 1;
+ exponent --;
+ shift --;
+ }
+ m = -m;
+ mantissa += m>>shift;
+ if (mantissa >= 0 && shift>0 && ((m>>>(shift-1))&1) != 0)
+ mantissa ++; // We don't need to shift down, so round now
+ if (mantissa < 0) {
+ // Simplified normalize()
+ mantissa = (mantissa+1)>>>1;
+ exponent ++; // Can't overflow
+ } else if (shift==0) {
+ // Operands have equal exponents => many bits may be cancelled
+ // Magic rounding: if result of subtract leaves only a few bits
+ // standing, the result should most likely be 0...
+ if (magicRounding && mantissa > 0 && mantissa <= 7) {
+ // If arguments were integers <= 2^63-1, then don't
+ // do the magic rounding anyway.
+ // This is a bit "post mortem" investigation but it happens
+ // so seldom that it's no problem to spend the extra time.
+ m = -m;
+ if (exponent == 0x4000003c || exponent == 0x4000003d ||
+ (exponent == 0x4000003e && mantissa+m > 0)) {
+ long mask = (1<<(0x4000003e-exponent))-1;
+ if ((mantissa & mask) != 0 || (m & mask) != 0)
+ mantissa = 0;
+ } else
+ mantissa = 0;
+ }
+ normalize();
+ } // else... if (shift>=1 && mantissa>=0) it should be a-ok
+ }
+ if ((this.exponent == 0 && this.mantissa == 0))
+ sign=0;
+ }
+ /**
+ * Calculates the sum of this <code>Real</code> and the integer
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this += a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.8
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to add to this.
+ */
+ public void add(int a) {
+ tmp0.assign(a);
+ add(tmp0);
+ }
+ /**
+ * Calculates the sum of this <code>Real</code> and <code>a</code> with
+ * extended precision. Replaces the contents of this <code>Real</code>
+ * with the result. Returns the extra mantissa of the extended precision
+ * result.
+ *
+ * <p>An extra 64 bits of mantissa is added to both arguments for extended
+ * precision. If any of the arguments are not of extended precision, use
+ * <code>0</code> for the extra mantissa.
+ *
+ * <p>Extended prevision can be useful in many situations. For instance,
+ * when accumulating a lot of very small values it is advantageous for the
+ * accumulator to have extended precision. To convert the extended
+ * precision value back to a normal <code>Real</code> for further
+ * processing, use {@link #roundFrom128(long)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this += a;</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2<sup>-62</sup> ULPs (i.e. of a normal precision <code>Real</code>)
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.0
+ * </td></tr></table>
+ *
+ * @param extra the extra 64 bits of mantissa of this extended precision
+ * <code>Real</code>.
+ * @param a the <code>Real</code> to add to this.
+ * @param aExtra the extra 64 bits of mantissa of the extended precision
+ * value <code>a</code>.
+ * @return the extra 64 bits of mantissa of the resulting extended
+ * precision <code>Real</code>.
+ */
+ public long add128(long extra, Real a, long aExtra) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return 0;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ if ((this.exponent < 0 && this.mantissa == 0) && (a.exponent < 0 && a.mantissa == 0) && sign != a.sign)
+ makeNan();
+ else
+ makeInfinity((this.exponent < 0 && this.mantissa == 0) ? sign : a.sign);
+ return 0;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ extra = aExtra;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0))
+ sign=0;
+ return extra;
+ }
+ byte s;
+ int e;
+ long m;
+ long x;
+ if (exponent > a.exponent ||
+ (exponent == a.exponent && mantissa>a.mantissa) ||
+ (exponent == a.exponent && mantissa==a.mantissa &&
+ (extra>>>1)>=(aExtra>>>1)))
+ {
+ s = a.sign;
+ e = a.exponent;
+ m = a.mantissa;
+ x = aExtra;
+ } else {
+ s = sign;
+ e = exponent;
+ m = mantissa;
+ x = extra;
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ extra = aExtra;
+ }
+ int shift = exponent-e;
+ if (shift>=127)
+ return extra;
+ if (shift>=64) {
+ x = m>>>(shift-64);
+ m = 0;
+ } else if (shift>0) {
+ x = (x>>>shift)+(m<<(64-shift));
+ m >>>= shift;
+ }
+ extra >>>= 1;
+ x >>>= 1;
+ if (sign == s) {
+ extra += x;
+ mantissa += (extra>>63)&1;
+ mantissa += m;
+ } else {
+ extra -= x;
+ mantissa -= (extra>>63)&1;
+ mantissa -= m;
+ // Magic rounding: if result of subtract leaves only a few bits
+ // standing, the result should most likely be 0...
+ if (mantissa == 0 && extra > 0 && extra <= 0x1f)
+ extra = 0;
+ }
+ extra <<= 1;
+ extra = normalize128(extra);
+ if ((this.exponent == 0 && this.mantissa == 0))
+ sign=0;
+ return extra;
+ }
+ /**
+ * Calculates the difference between this <code>Real</code> and
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>(To achieve extended precision subtraction, it is enough to call
+ * <code>a.{@link #neg() neg}()</code> before calling <code>{@link
+ * #add128(long,Real,long) add128}(extra,a,aExtra)</code>, since only
+ * the sign bit of <code>a</code> need to be changed.)
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this -= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.0
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to subtract from this.
+ */
+ public void sub(Real a) {
+ tmp0.mantissa = a.mantissa;
+ tmp0.exponent = a.exponent;
+ tmp0.sign = (byte)(a.sign^1);
+ add(tmp0);
+ }
+ /**
+ * Calculates the difference between this <code>Real</code> and the
+ * integer <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this -= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.4
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to subtract from this.
+ */
+ public void sub(int a) {
+ tmp0.assign(a);
+ sub(tmp0);
+ }
+ /**
+ * Calculates the product of this <code>Real</code> and <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this *= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.3
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to multiply to this.
+ */
+ public void mul(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ sign ^= a.sign;
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0))
+ makeNan();
+ else
+ makeZero(sign);
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ makeInfinity(sign);
+ return;
+ }
+ long a0 = mantissa & 0x7fffffff;
+ long a1 = mantissa >>> 31;
+ long b0 = a.mantissa & 0x7fffffff;
+ long b1 = a.mantissa >>> 31;
+ mantissa = a1*b1;
+ // If we're going to need normalization, we don't want to round twice
+ int round = (mantissa<0) ? 0 : 0x40000000;
+ mantissa += ((a0*b1 + a1*b0 + ((a0*b0)>>>31) + round)>>>31);
+ int aExp = a.exponent;
+ exponent += aExp-0x40000000;
+ if (exponent < 0) {
+ if (exponent == -1 && aExp < 0x40000000 && mantissa < 0) {
+ // Not underflow after all, it will be corrected in the
+ // normalization below
+ } else {
+ if (aExp < 0x40000000)
+ makeZero(sign); // Underflow
+ else
+ makeInfinity(sign); // Overflow
+ return;
+ }
+ }
+ // Simplified normalize()
+ if (mantissa < 0) {
+ mantissa = (mantissa+1)>>>1;
+ exponent ++;
+ if (exponent < 0) // Overflow
+ makeInfinity(sign);
+ }
+ }
+ /**
+ * Calculates the product of this <code>Real</code> and the integer
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this *= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.3
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to multiply to this.
+ */
+ public void mul(int a) {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if (a<0) {
+ sign ^= 1;
+ a = -a;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || a==0) {
+ if ((this.exponent < 0 && this.mantissa == 0))
+ makeNan();
+ else
+ makeZero(sign);
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0))
+ return;
+ // Normalize int
+ int t=a; t|=t>>1; t|=t>>2; t|=t>>4; t|=t>>8; t|=t>>16;
+ t = clz_tab[(t*clz_magic)>>>27];
+ exponent += 0x1F-t;
+ a <<= t;
+ if (exponent < 0) {
+ makeInfinity(sign); // Overflow
+ return;
+ }
+ long a0 = mantissa & 0x7fffffff;
+ long a1 = mantissa >>> 31;
+ long b0 = a & 0xffffffffL;
+ mantissa = a1*b0;
+ // If we're going to need normalization, we don't want to round twice
+ int round = (mantissa<0) ? 0 : 0x40000000;
+ mantissa += ((a0*b0 + round)>>>31);
+ // Simplified normalize()
+ if (mantissa < 0) {
+ mantissa = (mantissa+1)>>>1;
+ exponent ++;
+ if (exponent < 0) // Overflow
+ makeInfinity(sign);
+ }
+ }
+ /**
+ * Calculates the product of this <code>Real</code> and <code>a</code> with
+ * extended precision.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * Returns the extra mantissa of the extended precision result.
+ *
+ * <p>An extra 64 bits of mantissa is added to both arguments for
+ * extended precision. If any of the arguments are not of extended
+ * precision, use <code>0</code> for the extra mantissa. See also {@link
+ * #add128(long,Real,long)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this *= a;</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2<sup>-60</sup> ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 3.1
+ * </td></tr></table>
+ *
+ * @param extra the extra 64 bits of mantissa of this extended precision
+ * <code>Real</code>.
+ * @param a the <code>Real</code> to multiply to this.
+ * @param aExtra the extra 64 bits of mantissa of the extended precision
+ * value <code>a</code>.
+ * @return the extra 64 bits of mantissa of the resulting extended
+ * precision <code>Real</code>.
+ */
+ public long mul128(long extra, Real a, long aExtra) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return 0;
+ }
+ sign ^= a.sign;
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0))
+ makeNan();
+ else
+ makeZero(sign);
+ return 0;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ makeInfinity(sign);
+ return 0;
+ }
+ int aExp = a.exponent;
+ exponent += aExp-0x40000000;
+ if (exponent < 0) {
+ if (aExp < 0x40000000)
+ makeZero(sign); // Underflow
+ else
+ makeInfinity(sign); // Overflow
+ return 0;
+ }
+ long ffffffffL = 0xffffffffL;
+ long a0 = extra & ffffffffL;
+ long a1 = extra >>> 32;
+ long a2 = mantissa & ffffffffL;
+ long a3 = mantissa >>> 32;
+ long b0 = aExtra & ffffffffL;
+ long b1 = aExtra >>> 32;
+ long b2 = a.mantissa & ffffffffL;
+ long b3 = a.mantissa >>> 32;
+ a0 = ((a3*b0>>>2)+
+ (a2*b1>>>2)+
+ (a1*b2>>>2)+
+ (a0*b3>>>2)+
+ 0x60000000)>>>28;
+ //(a2*b0>>>34)+(a1*b1>>>34)+(a0*b2>>>34)+0x08000000)>>>28;
+ a1 *= b3;
+ b0 = a2*b2;
+ b1 *= a3;
+ a0 += ((a1<<2)&ffffffffL) + ((b0<<2)&ffffffffL) + ((b1<<2)&ffffffffL);
+ a1 = (a0>>>32) + (a1>>>30) + (b0>>>30) + (b1>>>30);
+ a0 &= ffffffffL;
+ a2 *= b3;
+ b2 *= a3;
+ a1 += ((a2<<2)&ffffffffL) + ((b2<<2)&ffffffffL);
+ extra = (a1<<32) + a0;
+ mantissa = ((a3*b3)<<2) + (a1>>>32) + (a2>>>30) + (b2>>>30);
+ extra = normalize128(extra);
+ return extra;
+ }
+ private void mul10() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ mantissa += (mantissa+2)>>>2;
+ exponent += 3;
+ if (mantissa < 0) {
+ mantissa = (mantissa+1)>>>1;
+ exponent++;
+ }
+ if (exponent < 0)
+ makeInfinity(sign); // Overflow
+ }
+ /**
+ * Calculates the square of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = this*this;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.1
+ * </td></tr></table>
+ */
+ public void sqr() {
+ sign = 0;
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ int e = exponent;
+ exponent += exponent-0x40000000;
+ if (exponent < 0) {
+ if (e < 0x40000000)
+ makeZero(sign); // Underflow
+ else
+ makeInfinity(sign); // Overflow
+ return;
+ }
+ long a0 = mantissa&0x7fffffff;
+ long a1 = mantissa>>>31;
+ mantissa = a1*a1;
+ // If we're going to need normalization, we don't want to round twice
+ int round = (mantissa<0) ? 0 : 0x40000000;
+ mantissa += ((((a0*a1)<<1) + ((a0*a0)>>>31) + round)>>>31);
+ // Simplified normalize()
+ if (mantissa < 0) {
+ mantissa = (mantissa+1)>>>1;
+ exponent ++;
+ if (exponent < 0) // Overflow
+ makeInfinity(sign);
+ }
+ }
+ private static long ldiv(long a, long b) {
+ // Calculate (a<<63)/b, where a<2**64, b<2**63, b<=a and a<2*b The
+ // result will always be 63 bits, leading to a 3-stage radix-2**21
+ // (very high radix) algorithm, as described here:
+ // S.F. Oberman and M.J. Flynn, "Division Algorithms and
+ // Implementations," IEEE Trans. Computers, vol. 46, no. 8,
+ // pp. 833-854, Aug 1997 Section 4: "Very High Radix Algorithms"
+ int bInv24; // Approximate 1/b, never more than 24 bits
+ int aHi24; // High 24 bits of a (sometimes 25 bits)
+ int next21; // The next 21 bits of result, possibly 1 less
+ long q; // Resulting quotient: round((a<<63)/b)
+ // Preparations
+ bInv24 = (int)(0x400000000000L/((b>>>40)+1));
+ aHi24 = (int)(a>>32)>>>8;
+ a <<= 20; // aHi24 and a overlap by 4 bits
+ // Now perform the division
+ next21 = (int)(((long)aHi24*(long)bInv24)>>>26);
+ a -= next21*b; // Bits above 2**64 will always be cancelled
+ // No need to remove remainder, this will be cared for in next block
+ q = next21;
+ aHi24 = (int)(a>>32)>>>7;
+ a <<= 21;
+ // Two more almost identical blocks...
+ next21 = (int)(((long)aHi24*(long)bInv24)>>>26);
+ a -= next21*b;
+ q = (q<<21)+next21;
+ aHi24 = (int)(a>>32)>>>7;
+ a <<= 21;
+ next21 = (int)(((long)aHi24*(long)bInv24)>>>26);
+ a -= next21*b;
+ q = (q<<21)+next21;
+ // Remove final remainder
+ if (a<0 || a>=b) { q++; a -= b; }
+ a <<= 1;
+ // Round correctly
+ if (a<0 || a>=b) q++;
+ return q;
+ }
+ /**
+ * Calculates the quotient of this <code>Real</code> and <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>(To achieve extended precision division, call
+ * <code>aExtra=a.{@link #recip128(long) recip128}(aExtra)</code> before
+ * calling <code>{@link #mul128(long,Real,long)
+ * mul128}(extra,a,aExtra)</code>.)
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this /= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.6
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to divide this with.
+ */
+ public void div(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ sign ^= a.sign;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ if ((a.exponent < 0 && a.mantissa == 0))
+ makeNan();
+ return;
+ }
+ if ((a.exponent < 0 && a.mantissa == 0)) {
+ makeZero(sign);
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ if ((a.exponent == 0 && a.mantissa == 0))
+ makeNan();
+ return;
+ }
+ if ((a.exponent == 0 && a.mantissa == 0)) {
+ makeInfinity(sign);
+ return;
+ }
+ exponent += 0x40000000-a.exponent;
+ if (mantissa < a.mantissa) {
+ mantissa <<= 1;
+ exponent--;
+ }
+ if (exponent < 0) {
+ if (a.exponent >= 0x40000000)
+ makeZero(sign); // Underflow
+ else
+ makeInfinity(sign); // Overflow
+ return;
+ }
+ if (a.mantissa == 0x4000000000000000L)
+ return;
+ mantissa = ldiv(mantissa,a.mantissa);
+ }
+ /**
+ * Calculates the quotient of this <code>Real</code> and the integer
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this /= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.6
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to divide this with.
+ */
+ public void div(int a) {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if (a<0) {
+ sign ^= 1;
+ a = -a;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0))
+ return;
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ if (a==0)
+ makeNan();
+ return;
+ }
+ if (a==0) {
+ makeInfinity(sign);
+ return;
+ }
+ long denom = a & 0xffffffffL;
+ long remainder = mantissa%denom;
+ mantissa /= denom;
+ // Normalizing mantissa and scaling remainder accordingly
+ int clz = 0;
+ int t = (int)(mantissa>>>32);
+ if (t == 0) { clz = 32; t = (int)mantissa; }
+ t|=t>>1; t|=t>>2; t|=t>>4; t|=t>>8; t|=t>>16;
+ clz += clz_tab[(t*clz_magic)>>>27]-1;
+ mantissa <<= clz;
+ remainder <<= clz;
+ exponent -= clz;
+ // Final division, correctly rounded
+ remainder = (remainder+denom/2)/denom;
+ mantissa += remainder;
+ if (exponent < 0) // Underflow
+ makeZero(sign);
+ }
+ /**
+ * Calculates the quotient of <code>a</code> and this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = a/this;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 3.1
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> to be divided by this.
+ */
+ public void rdiv(Real a) {
+ { recipTmp.mantissa = a.mantissa; recipTmp.exponent = a.exponent; recipTmp.sign = a.sign; };
+ recipTmp.div(this);
+ { this.mantissa = recipTmp.mantissa; this.exponent = recipTmp.exponent; this.sign = recipTmp.sign; };
+ }
+ /**
+ * Calculates the quotient of the integer <code>a</code> and this
+ * <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = a/this;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 3.9
+ * </td></tr></table>
+ *
+ * @param a the <code>int</code> to be divided by this.
+ */
+ public void rdiv(int a) {
+ tmp0.assign(a);
+ rdiv(tmp0);
+ }
+ /**
+ * Calculates the reciprocal of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = 1/this;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 2.3
+ * </td></tr></table>
+ */
+ public void recip() {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ makeZero(sign);
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ makeInfinity(sign);
+ return;
+ }
+ exponent = 0x80000000-exponent;
+ if (mantissa == 0x4000000000000000L) {
+ if (exponent < 0)
+ makeInfinity(sign); // Overflow
+ return;
+ }
+ exponent--;
+ mantissa = ldiv(0x8000000000000000L,mantissa);
+ }
+ /**
+ * Calculates the reciprocal of this <code>Real</code> with
+ * extended precision.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * Returns the extra mantissa of the extended precision result.
+ *
+ * <p>An extra 64 bits of mantissa is added for extended precision.
+ * If the argument is not of extended precision, use <code>0</code>
+ * for the extra mantissa. See also {@link #add128(long,Real,long)}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = 1/this;</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2<sup>-60</sup> ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 17
+ * </td></tr></table>
+ *
+ * @param extra the extra 64 bits of mantissa of this extended precision
+ * <code>Real</code>.
+ * @return the extra 64 bits of mantissa of the resulting extended
+ * precision <code>Real</code>.
+ */
+ public long recip128(long extra) {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return 0;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ makeZero(sign);
+ return 0;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ makeInfinity(sign);
+ return 0;
+ }
+ byte s = sign;
+ sign = 0;
+ // Special case, simple power of 2
+ if (mantissa == 0x4000000000000000L && extra == 0) {
+ exponent = 0x80000000-exponent;
+ if (exponent<0) // Overflow
+ makeInfinity(s);
+ return 0;
+ }
+ // Normalize exponent
+ int exp = 0x40000000-exponent;
+ exponent = 0x40000000;
+ // Save -A
+ { recipTmp.mantissa = this.mantissa; recipTmp.exponent = this.exponent; recipTmp.sign = this.sign; };
+ long recipTmpExtra = extra;
+ recipTmp.neg();
+ // First establish approximate result (actually 63 bit accurate)
+ recip();
+ // Perform one Newton-Raphson iteration
+ // Xn+1 = Xn + Xn*(1-A*Xn)
+ { recipTmp2.mantissa = this.mantissa; recipTmp2.exponent = this.exponent; recipTmp2.sign = this.sign; };
+ extra = mul128(0,recipTmp,recipTmpExtra);
+ extra = add128(extra,ONE,0);
+ extra = mul128(extra,recipTmp2,0);
+ extra = add128(extra,recipTmp2,0);
+ // Fix exponent
+ scalbn(exp);
+ // Fix sign
+ if (!isNan())
+ sign = s;
+ return extra;
+ }
+ /**
+ * Calculates the mathematical integer that is less than or equal to
+ * this <code>Real</code> divided by <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#floor(double) floor}(this/a);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 22
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument.
+ */
+ public void divf(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ if ((a.exponent < 0 && a.mantissa == 0))
+ makeNan();
+ return;
+ }
+ if ((a.exponent < 0 && a.mantissa == 0)) {
+ makeZero(sign);
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ if ((a.exponent == 0 && a.mantissa == 0))
+ makeNan();
+ return;
+ }
+ if ((a.exponent == 0 && a.mantissa == 0)) {
+ makeInfinity(sign);
+ return;
+ }
+ { tmp0.mantissa = a.mantissa; tmp0.exponent = a.exponent; tmp0.sign = a.sign; }; // tmp0 should be free
+ // Perform same division as with mod, and don't round up
+ long extra = tmp0.recip128(0);
+ extra = mul128(0,tmp0,extra);
+ if (((tmp0.sign!=0) && (extra < 0 || extra > 0x1f)) ||
+ (!(tmp0.sign!=0) && extra < 0 && extra > 0xffffffe0))
+ {
+ // For accurate floor()
+ mantissa++;
+ normalize();
+ }
+ floor();
+ }
+ private void modInternal(/*long thisExtra,*/ Real a, long aExtra) {
+ { tmp0.mantissa = a.mantissa; tmp0.exponent = a.exponent; tmp0.sign = a.sign; }; // tmp0 should be free
+ long extra = tmp0.recip128(aExtra);
+ extra = tmp0.mul128(extra,this,0/*thisExtra*/); // tmp0 == this/a
+ if (tmp0.exponent > 0x4000003e) {
+ // floor() will be inaccurate
+ makeZero(a.sign); // What else can be done? makeNan?
+ return;
+ }
+ if (((tmp0.sign!=0) && (extra < 0 || extra > 0x1f)) ||
+ (!(tmp0.sign!=0) && extra < 0 && extra > 0xffffffe0))
+ {
+ // For accurate floor() with a bit of "magical rounding"
+ tmp0.mantissa++;
+ tmp0.normalize();
+ }
+ tmp0.floor();
+ tmp0.neg(); // tmp0 == -floor(this/a)
+ extra = tmp0.mul128(0,a,aExtra);
+ extra = add128(0/*thisExtra*/,tmp0,extra);
+ roundFrom128(extra);
+ }
+ /**
+ * Calculates the value of this <code>Real</code> modulo <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The modulo in this case is defined as the remainder after subtracting
+ * <code>a</code> multiplied by the mathematical integer that is less than
+ * or equal to this <code>Real</code> divided by <code>a</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = this -
+ * a*Math.{@link Math#floor(double) floor}(this/a);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 27
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument.
+ */
+ public void mod(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ if ((a.exponent == 0 && a.mantissa == 0))
+ makeNan();
+ else
+ sign = a.sign;
+ return;
+ }
+ if ((a.exponent < 0 && a.mantissa == 0)) {
+ if (sign != a.sign)
+ makeInfinity(a.sign);
+ return;
+ }
+ if ((a.exponent == 0 && a.mantissa == 0)) {
+ makeZero(a.sign);
+ return;
+ }
+ modInternal(a,0);
+ }
+ /**
+ * Calculates the logical <i>AND</i> of this <code>Real</code> and
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>Semantics of bitwise logical operations exactly mimic those of
+ * Java's bitwise integer operators. In these operations, the
+ * internal binary representation of the numbers are used. If the
+ * values represented by the operands are not mathematical
+ * integers, the fractional bits are also included in the operation.
+ *
+ * <p>Negative numbers are interpreted as two's-complement,
+ * generalized to real numbers: Negating the number inverts all
+ * bits, including an infinite number of 1-bits before the radix
+ * point and an infinite number of 1-bits after the radix point. The
+ * infinite number of 1-bits after the radix is rounded upwards
+ * producing an infinite number of 0-bits, until the first 0-bit is
+ * encountered which will be switched to a 1 (rounded or not, these
+ * two forms are mathematically equivalent). For example, the number
+ * "1" negated, becomes (in binary form)
+ * <code>...1111110.111111....</code> Rounding of the infinite
+ * number of 1's after the radix gives the number
+ * <code>...1111111.000000...</code>, which is exactly the way we
+ * usually see "-1" as two's-complement.
+ *
+ * <p>This method calculates a negative value if and only
+ * if this and <code>a</code> are both negative.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>int</code><i> code:</i></td><td>
+ * <code>this &= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.5
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument
+ */
+ public void and(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ makeZero();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ if (!(this.exponent < 0 && this.mantissa == 0) && (this.sign!=0)) {
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ } else if (!(a.exponent < 0 && a.mantissa == 0) && (a.sign!=0))
+ ; // ASSIGN(this,this)
+ else if ((this.exponent < 0 && this.mantissa == 0) && (a.exponent < 0 && a.mantissa == 0) &&
+ (this.sign!=0) && (a.sign!=0))
+ ; // makeInfinity(1)
+ else
+ makeZero();
+ return;
+ }
+ byte s;
+ int e;
+ long m;
+ if (exponent >= a.exponent) {
+ s = a.sign;
+ e = a.exponent;
+ m = a.mantissa;
+ } else {
+ s = sign;
+ e = exponent;
+ m = mantissa;
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ }
+ int shift = exponent-e;
+ if (shift>=64) {
+ if (s == 0)
+ makeZero(sign);
+ return;
+ }
+ if (s != 0)
+ m = -m;
+ if ((this.sign!=0))
+ mantissa = -mantissa;
+ mantissa &= m>>shift;
+ sign = 0;
+ if (mantissa < 0) {
+ mantissa = -mantissa;
+ sign = 1;
+ }
+ normalize();
+ }
+ /**
+ * Calculates the logical <i>OR</i> of this <code>Real</code> and
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>See {@link #and(Real)} for an explanation of the
+ * interpretation of a <code>Real</code> in bitwise operations.
+ * This method calculates a negative value if and only
+ * if either this or <code>a</code> is negative.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>int</code><i> code:</i></td><td>
+ * <code>this |= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.6
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument
+ */
+ public void or(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent == 0 && this.mantissa == 0))
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ if (!(this.exponent < 0 && this.mantissa == 0) && (this.sign!=0))
+ ; // ASSIGN(this,this);
+ else if (!(a.exponent < 0 && a.mantissa == 0) && (a.sign!=0)) {
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ } else
+ makeInfinity(sign | a.sign);
+ return;
+ }
+ byte s;
+ int e;
+ long m;
+ if (((this.sign!=0) && exponent <= a.exponent) ||
+ ((a.sign==0) && exponent >= a.exponent))
+ {
+ s = a.sign;
+ e = a.exponent;
+ m = a.mantissa;
+ } else {
+ s = sign;
+ e = exponent;
+ m = mantissa;
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ }
+ int shift = exponent-e;
+ if (shift>=64 || shift<=-64)
+ return;
+ if (s != 0)
+ m = -m;
+ if ((this.sign!=0))
+ mantissa = -mantissa;
+ if (shift>=0)
+ mantissa |= m>>shift;
+ else
+ mantissa |= m<<(-shift);
+ sign = 0;
+ if (mantissa < 0) {
+ mantissa = -mantissa;
+ sign = 1;
+ }
+ normalize();
+ }
+ /**
+ * Calculates the logical <i>XOR</i> of this <code>Real</code> and
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>See {@link #and(Real)} for an explanation of the
+ * interpretation of a <code>Real</code> in bitwise operations.
+ * This method calculates a negative value if and only
+ * if exactly one of this and <code>a</code> is negative.
+ *
+ * <p>The operation <i>NOT</i> has been omitted in this library
+ * because it cannot be generalized to fractional numbers. If this
+ * <code>Real</code> represents a mathematical integer, the
+ * operation <i>NOT</i> can be calculated as "this <i>XOR</i> -1",
+ * which is equivalent to "this <i>XOR</i>
+ * <code>/FFFFFFFF.0000</code>".
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>int</code><i> code:</i></td><td>
+ * <code>this ^= a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.5
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument
+ */
+ public void xor(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0)) {
+ if ((this.exponent == 0 && this.mantissa == 0))
+ { this.mantissa = a.mantissa; this.exponent = a.exponent; this.sign = a.sign; };
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ makeInfinity(sign ^ a.sign);
+ return;
+ }
+ byte s;
+ int e;
+ long m;
+ if (exponent >= a.exponent) {
+ s = a.sign;
+ e = a.exponent;
+ m = a.mantissa;
+ } else {
+ s = sign;
+ e = exponent;
+ m = mantissa;
+ sign = a.sign;
+ exponent = a.exponent;
+ mantissa = a.mantissa;
+ }
+ int shift = exponent-e;
+ if (shift>=64)
+ return;
+ if (s != 0)
+ m = -m;
+ if ((this.sign!=0))
+ mantissa = -mantissa;
+ mantissa ^= m>>shift;
+ sign = 0;
+ if (mantissa < 0) {
+ mantissa = -mantissa;
+ sign = 1;
+ }
+ normalize();
+ }
+ /**
+ * Calculates the value of this <code>Real</code> <i>AND NOT</i>
+ * <code>a</code>. The opeation is read as "bit clear".
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>See {@link #and(Real)} for an explanation of the
+ * interpretation of a <code>Real</code> in bitwise operations.
+ * This method calculates a negative value if and only
+ * if this is negative and not <code>a</code> is negative.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>int</code><i> code:</i></td><td>
+ * <code>this &= ~a;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 1.5
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument
+ */
+ public void bic(Real a) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) || (a.exponent == 0 && a.mantissa == 0))
+ return;
+ if ((this.exponent < 0 && this.mantissa == 0) || (a.exponent < 0 && a.mantissa == 0)) {
+ if (!(this.exponent < 0 && this.mantissa == 0)) {
+ if ((this.sign!=0))
+ if ((a.sign!=0))
+ makeInfinity(0);
+ else
+ makeInfinity(1);
+ } else if ((a.sign!=0)) {
+ if ((a.exponent < 0 && a.mantissa == 0))
+ makeInfinity(0);
+ else
+ makeZero();
+ }
+ return;
+ }
+ int shift = exponent-a.exponent;
+ if (shift>=64 || (shift<=-64 && (this.sign==0)))
+ return;
+ long m = a.mantissa;
+ if ((a.sign!=0))
+ m = -m;
+ if ((this.sign!=0))
+ mantissa = -mantissa;
+ if (shift<0) {
+ if ((this.sign!=0)) {
+ if (shift<=-64)
+ mantissa = ~m;
+ else
+ mantissa = (mantissa>>(-shift)) & ~m;
+ exponent = a.exponent;
+ } else
+ mantissa &= ~(m<<(-shift));
+ } else
+ mantissa &= ~(m>>shift);
+ sign = 0;
+ if (mantissa < 0) {
+ mantissa = -mantissa;
+ sign = 1;
+ }
+ normalize();
+ }
+ private int compare(int a) {
+ tmp0.assign(a);
+ return compare(tmp0);
+ }
+ /**
+ * Calculates the square root of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#sqrt(double) sqrt}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 19
+ * </td></tr></table>
+ */
+ public void sqrt() {
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.2: December, 1990
+ * Copyright 1984, 1990 by Stephen L. Moshier
+ *
+ * sqrtl.c
+ *
+ * long double sqrtl(long double x);
+ */
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ sign=0;
+ return;
+ }
+ if ((this.sign!=0)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0))
+ return;
+ // Save X
+ { recipTmp.mantissa = this.mantissa; recipTmp.exponent = this.exponent; recipTmp.sign = this.sign; };
+ // normalize to range [0.5, 1)
+ int e = exponent-0x3fffffff;
+ exponent = 0x3fffffff;
+ // quadratic approximation, relative error 6.45e-4
+ { recipTmp2.mantissa = this.mantissa; recipTmp2.exponent = this.exponent; recipTmp2.sign = this.sign; };
+ { sqrtTmp.sign=(byte)1; sqrtTmp.exponent=0x3ffffffd; sqrtTmp.mantissa=0x68a7e193370ff21bL; };//-0.2044058315473477195990
+ mul(sqrtTmp);
+ { sqrtTmp.sign=(byte)0; sqrtTmp.exponent=0x3fffffff; sqrtTmp.mantissa=0x71f1e120690deae8L; };//0.89019407351052789754347
+ add(sqrtTmp);
+ mul(recipTmp2);
+ { sqrtTmp.sign=(byte)0; sqrtTmp.exponent=0x3ffffffe; sqrtTmp.mantissa=0x5045ee6baf28677aL; };//0.31356706742295303132394
+ add(sqrtTmp);
+ // adjust for odd powers of 2
+ if ((e&1) != 0)
+ mul(SQRT2);
+ // calculate exponent
+ exponent += e>>1;
+ // Newton iteratios:
+ // Yn+1 = (Yn + X/Yn)/2
+ for (int i=0; i<3; i++) {
+ { recipTmp2.mantissa = recipTmp.mantissa; recipTmp2.exponent = recipTmp.exponent; recipTmp2.sign = recipTmp.sign; };
+ recipTmp2.div(this);
+ add(recipTmp2);
+ scalbn(-1);
+ }
+ }
+ /**
+ * Calculates the reciprocal square root of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = 1/Math.{@link Math#sqrt(double) sqrt}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 21
+ * </td></tr></table>
+ */
+ public void rsqrt() {
+ sqrt();
+ recip();
+ }
+ /**
+ * Calculates the cube root of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The cube root of a negative value is the negative of the cube
+ * root of that value's magnitude.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#cbrt(double) cbrt}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 32
+ * </td></tr></table>
+ */
+ public void cbrt() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ byte s = sign;
+ sign = 0;
+ // Calculates recipocal cube root of normalized Real,
+ // not zero, nan or infinity
+ final long start = 0x5120000000000000L;
+ // Save -A
+ { recipTmp.mantissa = this.mantissa; recipTmp.exponent = this.exponent; recipTmp.sign = this.sign; };
+ recipTmp.neg();
+ // First establish approximate result
+ mantissa = start-(mantissa>>>2);
+ int expRmd = exponent==0 ? 2 : (exponent-1)%3;
+ exponent = 0x40000000-(exponent-0x40000000-expRmd)/3;
+ normalize();
+ if (expRmd>0) {
+ { recipTmp2.sign=(byte)0; recipTmp2.exponent=0x3fffffff; recipTmp2.mantissa=0x6597fa94f5b8f20bL; }; // cbrt(1/2)
+ mul(recipTmp2);
+ if (expRmd>1)
+ mul(recipTmp2);
+ }
+ // Now perform Newton-Raphson iteration
+ // Xn+1 = (4*Xn - A*Xn**4)/3
+ for (int i=0; i<4; i++) {
+ { recipTmp2.mantissa = this.mantissa; recipTmp2.exponent = this.exponent; recipTmp2.sign = this.sign; };
+ sqr();
+ sqr();
+ mul(recipTmp);
+ recipTmp2.scalbn(2);
+ add(recipTmp2);
+ mul(THIRD);
+ }
+ recip();
+ if (!(this.exponent < 0 && this.mantissa != 0))
+ sign = s;
+ }
+ /**
+ * Calculates the n'th root of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * For odd integer n, the n'th root of a negative value is the
+ * negative of the n'th root of that value's magnitude.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#pow(double,double)
+ * pow}(this,1/a);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 110
+ * </td></tr></table>
+ *
+ * @param n the <code>Real</code> argument.
+ */
+ public void nroot(Real n) {
+ if ((n.exponent < 0 && n.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if (n.compare(THREE)==0) {
+ cbrt(); // Most probable application of nroot...
+ return;
+ } else if (n.compare(TWO)==0) {
+ sqrt(); // Also possible, should be optimized like this
+ return;
+ }
+ boolean negative = false;
+ if ((this.sign!=0) && n.isIntegral() && n.isOdd()) {
+ negative = true;
+ abs();
+ }
+ { tmp2.mantissa = n.mantissa; tmp2.exponent = n.exponent; tmp2.sign = n.sign; }; // Copy to temporary location in case of x.nroot(x)
+ tmp2.recip();
+ pow(tmp2);
+ if (negative)
+ neg();
+ }
+ /**
+ * Calculates <code>sqrt(this*this+a*a)</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#hypot(double,double)
+ * hypot}(this,a);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 24
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument.
+ */
+ public void hypot(Real a) {
+ { tmp1.mantissa = a.mantissa; tmp1.exponent = a.exponent; tmp1.sign = a.sign; }; // Copy to temporary location in case of x.hypot(x)
+ tmp1.sqr();
+ sqr();
+ add(tmp1);
+ sqrt();
+ }
+ private void exp2Internal(long extra) {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ if ((this.sign!=0))
+ makeZero(0);
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ return;
+ }
+ // Extract integer part
+ { expTmp.mantissa = this.mantissa; expTmp.exponent = this.exponent; expTmp.sign = this.sign; };
+ expTmp.add(HALF);
+ expTmp.floor();
+ int exp = expTmp.toInteger();
+ if (exp > 0x40000000) {
+ makeInfinity(sign);
+ return;
+ }
+ if (exp < -0x40000000) {
+ makeZero(sign);
+ return;
+ }
+ // Subtract integer part (this is where we need the extra accuracy)
+ expTmp.neg();
+ add128(extra,expTmp,0);
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.7: May, 1998
+ * Copyright 1984, 1991, 1998 by Stephen L. Moshier
+ *
+ * exp2l.c
+ *
+ * long double exp2l(long double x);
+ */
+ // Now -0.5<X<0.5
+ // rational approximation
+ // exp2(x) = 1 + 2x P(x²)/(Q(x²) - x P(x²))
+ { expTmp2.mantissa = this.mantissa; expTmp2.exponent = this.exponent; expTmp2.sign = this.sign; };
+ expTmp2.sqr();
+ // P(x²)
+ { expTmp.sign=(byte)0; expTmp.exponent=0x40000005; expTmp.mantissa=0x793ace15b56b7fecL; };//60.614853552242266094567
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x4000000e; expTmp3.mantissa=0x764ef8cf96e29a13L; };//30286.971917562792508623
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000014; expTmp3.mantissa=0x7efa0173e820bf60L; };//2080384.3631901852422887
+ expTmp.add(expTmp3);
+ mul(expTmp);
+ // Q(x²)
+ expTmp.assign(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x4000000a; expTmp3.mantissa=0x6d549a6b4dc9abadL; };//1749.2876999891839021063
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000012; expTmp3.mantissa=0x5002d27836ba71c6L; };//327725.15434906797273099
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000016; expTmp3.mantissa=0x5b98206867dd59bfL; };//6002720.4078348487957118
+ expTmp.add(expTmp3);
+ expTmp.sub(this);
+ div(expTmp);
+ scalbn(1);
+ add(ONE);
+ // Scale by power of 2
+ scalbn(exp);
+ }
+ /**
+ * Calculates <i>e</i> raised to the power of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#exp(double) exp}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 31
+ * </td></tr></table>
+ */
+ public void exp() {
+ { expTmp.sign=(byte)0; expTmp.exponent=0x40000000; expTmp.mantissa=0x5c551d94ae0bf85dL; }; // log2(e)
+ long extra = mul128(0,expTmp,0xdf43ff68348e9f44L);
+ exp2Internal(extra);
+ }
+ /**
+ * Calculates 2 raised to the power of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#exp(double) exp}(this *
+ * Math.{@link Math#log(double) log}(2));</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 27
+ * </td></tr></table>
+ */
+ public void exp2() {
+ exp2Internal(0);
+ }
+ /**
+ * Calculates 10 raised to the power of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#exp(double) exp}(this *
+ * Math.{@link Math#log(double) log}(10));</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 31
+ * </td></tr></table>
+ */
+ public void exp10() {
+ { expTmp.sign=(byte)0; expTmp.exponent=0x40000001; expTmp.mantissa=0x6a4d3c25e68dc57fL; }; // log2(10)
+ long extra = mul128(0,expTmp,0x2495fb7fa6d7eda6L);
+ exp2Internal(extra);
+ }
+ private int lnInternal()
+ {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return 0;
+ if ((this.sign!=0)) {
+ makeNan();
+ return 0;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ makeInfinity(1);
+ return 0;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0))
+ return 0;
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.7: May, 1998
+ * Copyright 1984, 1990, 1998 by Stephen L. Moshier
+ *
+ * logl.c
+ *
+ * long double logl(long double x);
+ */
+ // normalize to range [0.5, 1)
+ int e = exponent-0x3fffffff;
+ exponent = 0x3fffffff;
+ // rational appriximation
+ // log(1+x) = x - x²/2 + x³ P(x)/Q(x)
+ if (this.compare(SQRT1_2) < 0) {
+ e--;
+ exponent++;
+ }
+ sub(ONE);
+ { expTmp2.mantissa = this.mantissa; expTmp2.exponent = this.exponent; expTmp2.sign = this.sign; };
+ // P(x)
+ { this.sign=(byte)0; this.exponent=0x3ffffff1; this.mantissa=0x5ef0258ace5728ddL; };//4.5270000862445199635215E-5
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x3ffffffe; expTmp3.mantissa=0x7fa06283f86a0ce8L; };//0.4985410282319337597221
+ add(expTmp3);
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000002; expTmp3.mantissa=0x69427d1bd3e94ca1L; };//6.5787325942061044846969
+ add(expTmp3);
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000004; expTmp3.mantissa=0x77a5ce2e32e7256eL; };//29.911919328553073277375
+ add(expTmp3);
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000005; expTmp3.mantissa=0x79e63ae1b0cd4222L; };//60.949667980987787057556
+ add(expTmp3);
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000005; expTmp3.mantissa=0x7239d65d1e6840d6L; };//57.112963590585538103336
+ add(expTmp3);
+ mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000004; expTmp3.mantissa=0x502880b6660c265fL; };//20.039553499201281259648
+ add(expTmp3);
+ // Q(x)
+ { expTmp.mantissa = expTmp2.mantissa; expTmp.exponent = expTmp2.exponent; expTmp.sign = expTmp2.sign; };
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000003; expTmp3.mantissa=0x7880d67a40f8dc5cL; };//15.062909083469192043167
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000006; expTmp3.mantissa=0x530c2d4884d25e18L; };//83.047565967967209469434
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000007; expTmp3.mantissa=0x6ee19643f3ed5776L; };//221.76239823732856465394
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000008; expTmp3.mantissa=0x4d465177242295efL; };//309.09872225312059774938
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000007; expTmp3.mantissa=0x6c36c4f923819890L; };//216.42788614495947685003
+ expTmp.add(expTmp3);
+ expTmp.mul(expTmp2);
+ { expTmp3.sign=(byte)0; expTmp3.exponent=0x40000005; expTmp3.mantissa=0x783cc111991239a3L; };//60.118660497603843919306
+ expTmp.add(expTmp3);
+ div(expTmp);
+ { expTmp3.mantissa = expTmp2.mantissa; expTmp3.exponent = expTmp2.exponent; expTmp3.sign = expTmp2.sign; };
+ expTmp3.sqr();
+ mul(expTmp3);
+ mul(expTmp2);
+ expTmp3.scalbn(-1);
+ sub(expTmp3);
+ add(expTmp2);
+ return e;
+ }
+ /**
+ * Calculates the natural logarithm (base-<i>e</i>) of this
+ * <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#log(double) log}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 51
+ * </td></tr></table>
+ */
+ public void ln() {
+ int exp = lnInternal();
+ expTmp.assign(exp);
+ expTmp.mul(LN2);
+ add(expTmp);
+ }
+ /**
+ * Calculates the base-2 logarithm of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#log(double) log}(this)/Math.{@link
+ * Math#log(double) log}(2);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 51
+ * </td></tr></table>
+ */
+ public void log2() {
+ int exp = lnInternal();
+ mul(LOG2E);
+ add(exp);
+ }
+ /**
+ * Calculates the base-10 logarithm of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#log10(double) log10}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 53
+ * </td></tr></table>
+ */
+ public void log10() {
+ int exp = lnInternal();
+ expTmp.assign(exp);
+ expTmp.mul(LN2);
+ add(expTmp);
+ mul(LOG10E);
+ }
+ /**
+ * Calculates the closest power of 10 that is less than or equal to this
+ * <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The base-10 exponent of the result is returned.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>int exp = (int)(Math.{@link Math#floor(double)
+ * floor}(Math.{@link Math#log10(double) log10}(this)));
+ * <br>this = Math.{@link Math#pow(double,double) pow}(10, exp);<br>
+ * return exp;</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 3.6
+ * </td></tr></table>
+ *
+ * @return the base-10 exponent
+ */
+ public int lowPow10() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return 0;
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ // Approximate log10 using exponent only
+ int e = exponent - 0x40000000;
+ if (e<0) // it's important to achieve floor(exponent*ln2/ln10)
+ e = -(int)(((-e)*0x4d104d43L+((1L<<32)-1)) >> 32);
+ else
+ e = (int)(e*0x4d104d43L >> 32);
+ // Now, e < log10(this) < e+1
+ { this.mantissa = TEN.mantissa; this.exponent = TEN.exponent; this.sign = TEN.sign; };
+ pow(e);
+ if ((this.exponent == 0 && this.mantissa == 0)) { // A *really* small number, then
+ { tmp3.mantissa = TEN.mantissa; tmp3.exponent = TEN.exponent; tmp3.sign = TEN.sign; };
+ tmp3.pow(e+1);
+ } else {
+ { tmp3.mantissa = this.mantissa; tmp3.exponent = this.exponent; tmp3.sign = this.sign; };
+ tmp3.mul10();
+ }
+ if (tmp3.compare(tmp2) <= 0) {
+ // First estimate of log10 was too low
+ e++;
+ { this.mantissa = tmp3.mantissa; this.exponent = tmp3.exponent; this.sign = tmp3.sign; };
+ }
+ return e;
+ }
+ /**
+ * Calculates the value of this <code>Real</code> raised to the power of
+ * <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p> Special cases:
+ * <ul>
+ * <li> if a is 0.0 or -0.0 then result is 1.0
+ * <li> if a is NaN then result is NaN
+ * <li> if this is NaN and a is not zero then result is NaN
+ * <li> if a is 1.0 then result is this
+ * <li> if |this| > 1.0 and a is +Infinity then result is +Infinity
+ * <li> if |this| < 1.0 and a is -Infinity then result is +Infinity
+ * <li> if |this| > 1.0 and a is -Infinity then result is +0
+ * <li> if |this| < 1.0 and a is +Infinity then result is +0
+ * <li> if |this| = 1.0 and a is ±Infinity then result is NaN
+ * <li> if this = +0 and a > 0 then result is +0
+ * <li> if this = +0 and a < 0 then result is +Inf
+ * <li> if this = -0 and a > 0, and odd integer then result is -0
+ * <li> if this = -0 and a < 0, and odd integer then result is -Inf
+ * <li> if this = -0 and a > 0, not odd integer then result is +0
+ * <li> if this = -0 and a < 0, not odd integer then result is +Inf
+ * <li> if this = +Inf and a > 0 then result is +Inf
+ * <li> if this = +Inf and a < 0 then result is +0
+ * <li> if this = -Inf and a not integer then result is NaN
+ * <li> if this = -Inf and a > 0, and odd integer then result is -Inf
+ * <li> if this = -Inf and a > 0, not odd integer then result is +Inf
+ * <li> if this = -Inf and a < 0, and odd integer then result is -0
+ * <li> if this = -Inf and a < 0, not odd integer then result is +0
+ * <li> if this < 0 and a not integer then result is NaN
+ * <li> if this < 0 and a odd integer then result is -(|this|<sup>a</sup>)
+ * <li> if this < 0 and a not odd integer then result is |this|<sup>a</sup>
+ * <li> else result is exp(ln(this)*a)
+ * </ul>
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#pow(double,double) pow}(this, a);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 110
+ * </td></tr></table>
+ *
+ * @param a the <code>Real</code> argument.
+ */
+ public void pow(Real a) {
+ if ((a.exponent == 0 && a.mantissa == 0)) {
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa != 0) || (a.exponent < 0 && a.mantissa != 0)) {
+ makeNan();
+ return;
+ }
+ if (a.compare(ONE)==0)
+ return;
+ if ((a.exponent < 0 && a.mantissa == 0)) {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.abs();
+ int test = tmp1.compare(ONE);
+ if (test>0) {
+ if ((a.sign==0))
+ makeInfinity(0);
+ else
+ makeZero();
+ } else if (test<0) {
+ if ((a.sign!=0))
+ makeInfinity(0);
+ else
+ makeZero();
+ } else {
+ makeNan();
+ }
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ if ((this.sign==0)) {
+ if ((a.sign==0))
+ makeZero();
+ else
+ makeInfinity(0);
+ } else {
+ if (a.isIntegral() && a.isOdd()) {
+ if ((a.sign==0))
+ makeZero(1);
+ else
+ makeInfinity(1);
+ } else {
+ if ((a.sign==0))
+ makeZero();
+ else
+ makeInfinity(0);
+ }
+ }
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ if ((this.sign==0)) {
+ if ((a.sign==0))
+ makeInfinity(0);
+ else
+ makeZero();
+ } else {
+ if (a.isIntegral()) {
+ if (a.isOdd()) {
+ if ((a.sign==0))
+ makeInfinity(1);
+ else
+ makeZero(1);
+ } else {
+ if ((a.sign==0))
+ makeInfinity(0);
+ else
+ makeZero();
+ }
+ } else {
+ makeNan();
+ }
+ }
+ return;
+ }
+ if (a.isIntegral() && a.exponent <= 0x4000001e) {
+ pow(a.toInteger());
+ return;
+ }
+ byte s=0;
+ if ((this.sign!=0)) {
+ if (a.isIntegral()) {
+ if (a.isOdd())
+ s = 1;
+ } else {
+ makeNan();
+ return;
+ }
+ sign = 0;
+ }
+ { tmp1.mantissa = a.mantissa; tmp1.exponent = a.exponent; tmp1.sign = a.sign; };
+ if (tmp1.exponent <= 0x4000001e) {
+ // For increased accuracy, exponentiate with integer part of
+ // exponent by successive squaring
+ // (I really don't know why this works)
+ { tmp2.mantissa = tmp1.mantissa; tmp2.exponent = tmp1.exponent; tmp2.sign = tmp1.sign; };
+ tmp2.floor();
+ { tmp3.mantissa = this.mantissa; tmp3.exponent = this.exponent; tmp3.sign = this.sign; };
+ tmp3.pow(tmp2.toInteger());
+ tmp1.sub(tmp2);
+ } else {
+ { tmp3.mantissa = ONE.mantissa; tmp3.exponent = ONE.exponent; tmp3.sign = ONE.sign; };
+ }
+ // Do log2 and maintain accuracy
+ int e = lnInternal();
+ { tmp2.sign=(byte)0; tmp2.exponent=0x40000000; tmp2.mantissa=0x5c551d94ae0bf85dL; }; // log2(e)
+ long extra = mul128(0,tmp2,0xdf43ff68348e9f44L);
+ tmp2.assign(e);
+ extra = add128(extra,tmp2,0);
+ // Do exp2 of this multiplied by (fractional part of) exponent
+ extra = tmp1.mul128(0,this,extra);
+ tmp1.exp2Internal(extra);
+ { this.mantissa = tmp1.mantissa; this.exponent = tmp1.exponent; this.sign = tmp1.sign; };
+ mul(tmp3);
+ if (!(this.exponent < 0 && this.mantissa != 0))
+ sign = s;
+ }
+ /**
+ * Calculates the value of this <code>Real</code> raised to the power of
+ * the integer <code>a</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#pow(double,double) pow}(this, a);</code>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 84
+ * </td></tr></table>
+ *
+ * @param a the integer argument.
+ */
+ public void pow(int a) {
+ // Calculate power of integer by successive squaring
+ boolean recp=false;
+ if (a < 0) {
+ a = -a; // Also works for 0x80000000
+ recp = true;
+ }
+ long extra = 0, expTmpExtra = 0;
+ { expTmp.mantissa = this.mantissa; expTmp.exponent = this.exponent; expTmp.sign = this.sign; };
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ for (; a!=0; a>>>=1) {
+ if ((a & 1) != 0)
+ extra = mul128(extra,expTmp,expTmpExtra);
+ expTmpExtra = expTmp.mul128(expTmpExtra,expTmp,expTmpExtra);
+ }
+ if (recp)
+ extra = recip128(extra);
+ roundFrom128(extra);
+ }
+ private void sinInternal() {
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.7: May, 1998
+ * Copyright 1985, 1990, 1998 by Stephen L. Moshier
+ *
+ * sinl.c
+ *
+ * long double sinl(long double x);
+ */
+ // X<PI/4
+ // polynomial approximation
+ // sin(x) = x + x³ P(x²)
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ tmp2.sqr();
+ { this.sign=(byte)1; this.exponent=0x3fffffd7; this.mantissa=0x6aa891c4f0eb2713L; };//-7.578540409484280575629E-13
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3fffffdf; tmp3.mantissa=0x58482311f383326cL; };//1.6058363167320443249231E-10
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3fffffe6; tmp3.mantissa=0x6b9914a35f9a00d8L; };//-2.5052104881870868784055E-8
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3fffffed; tmp3.mantissa=0x5c778e94cc22e47bL; };//2.7557319214064922217861E-6
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffff3; tmp3.mantissa=0x680680680629b28aL; };//-1.9841269841254799668344E-4
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3ffffff9; tmp3.mantissa=0x4444444444442b4dL; };//8.3333333333333225058715E-3
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffffd; tmp3.mantissa=0x555555555555554cL; };//-1.6666666666666666640255E-1
+ add(tmp3);
+ mul(tmp2);
+ mul(tmp1);
+ add(tmp1);
+ }
+ private void cosInternal() {
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.7: May, 1998
+ * Copyright 1985, 1990, 1998 by Stephen L. Moshier
+ *
+ * sinl.c
+ *
+ * long double cosl(long double x);
+ */
+ // X<PI/4
+ // polynomial approximation
+ // cos(x) = 1 - x²/2 + x**4 Q(x²)
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ tmp2.sqr();
+ { this.sign=(byte)0; this.exponent=0x3fffffd3; this.mantissa=0x6aaf461d37ccba1bL; };//4.7377507964246204691685E-14
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3fffffdb; tmp3.mantissa=0x64e4c907ac7a179bL; };//-1.147028484342535976567E-11
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3fffffe3; tmp3.mantissa=0x47bb632432cf29a8L; };//2.0876754287081521758361E-9
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3fffffea; tmp3.mantissa=0x49f93edd7ae32696L; };//-2.7557319214999787979814E-7
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3ffffff0; tmp3.mantissa=0x68068068063329f7L; };//2.4801587301570552304991E-5L
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffff6; tmp3.mantissa=0x5b05b05b05b03db3L; };//-1.3888888888888872993737E-3
+ add(tmp3);
+ mul(tmp2);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3ffffffb; tmp3.mantissa=0x555555555555554dL; };//4.1666666666666666609054E-2
+ add(tmp3);
+ mul(tmp2);
+ sub(HALF);
+ mul(tmp2);
+ add(ONE);
+ }
+ /**
+ * Calculates the trigonometric sine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The input value is treated as an angle measured in radians.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#sin(double) sin}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 28
+ * </td></tr></table>
+ */
+ public void sin() {
+ if (!(this.exponent >= 0 && this.mantissa != 0)) {
+ if (!(this.exponent == 0 && this.mantissa == 0))
+ makeNan();
+ return;
+ }
+ // Since sin(-x) = -sin(x) we can make sure that x > 0
+ boolean negative = false;
+ if ((this.sign!=0)) {
+ abs();
+ negative = true;
+ }
+ // Then reduce the argument to the range of 0 < x < pi*2
+ if (this.compare(PI2) > 0)
+ modInternal(PI2,0x62633145c06e0e69L);
+ // Since sin(pi*2 - x) = -sin(x) we can reduce the range 0 < x < pi
+ if (this.compare(PI) > 0) {
+ sub(PI2);
+ neg();
+ negative = !negative;
+ }
+ // Since sin(x) = sin(pi - x) we can reduce the range to 0 < x < pi/2
+ if (this.compare(PI_2) > 0) {
+ sub(PI);
+ neg();
+ }
+ // Since sin(x) = cos(pi/2 - x) we can reduce the range to 0 < x < pi/4
+ if (this.compare(PI_4) > 0) {
+ sub(PI_2);
+ neg();
+ cosInternal();
+ } else {
+ sinInternal();
+ }
+ if (negative)
+ neg();
+ if ((this.exponent == 0 && this.mantissa == 0))
+ abs(); // Remove confusing "-"
+ }
+ /**
+ * Calculates the trigonometric cosine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The input value is treated as an angle measured in radians.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#cos(double) cos}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 1 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 37
+ * </td></tr></table>
+ */
+ public void cos() {
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ return;
+ }
+ if ((this.sign!=0))
+ abs();
+ if (this.compare(PI_4) < 0) {
+ cosInternal();
+ } else {
+ add(PI_2);
+ sin();
+ }
+ }
+ /**
+ * Calculates the trigonometric tangent of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The input value is treated as an angle measured in radians.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#tan(double) tan}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 70
+ * </td></tr></table>
+ */
+ public void tan() {
+ { tmp4.mantissa = this.mantissa; tmp4.exponent = this.exponent; tmp4.sign = this.sign; };
+ tmp4.cos();
+ sin();
+ div(tmp4);
+ }
+ /**
+ * Calculates the trigonometric arc sine of this <code>Real</code>,
+ * in the range -π/2 to π/2.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#asin(double) asin}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 3 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 68
+ * </td></tr></table>
+ */
+ public void asin() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ sqr();
+ neg();
+ add(ONE);
+ rsqrt();
+ mul(tmp1);
+ atan();
+ }
+ /**
+ * Calculates the trigonometric arc cosine of this <code>Real</code>,
+ * in the range 0.0 to π.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#acos(double) acos}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 67
+ * </td></tr></table>
+ */
+ public void acos() {
+ boolean negative = (this.sign!=0);
+ abs();
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ sqr();
+ neg();
+ add(ONE);
+ sqrt();
+ div(tmp1);
+ atan();
+ if (negative) {
+ neg();
+ add(PI);
+ }
+ }
+ /**
+ * Calculates the trigonometric arc tangent of this <code>Real</code>,
+ * in the range -π/2 to π/2.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#atan(double) atan}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 37
+ * </td></tr></table>
+ */
+ public void atan() {
+ /*
+ * Adapted from:
+ * Cephes Math Library Release 2.7: May, 1998
+ * Copyright 1984, 1990, 1998 by Stephen L. Moshier
+ *
+ * atanl.c
+ *
+ * long double atanl(long double x);
+ */
+ if ((this.exponent == 0 && this.mantissa == 0) || (this.exponent < 0 && this.mantissa != 0))
+ return;
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ byte s = sign;
+ { this.mantissa = PI_2.mantissa; this.exponent = PI_2.exponent; this.sign = PI_2.sign; };
+ sign = s;
+ return;
+ }
+ byte s = sign;
+ sign = 0;
+ // range reduction
+ boolean addPI_2 = false;
+ boolean addPI_4 = false;
+ { tmp1.mantissa = SQRT2.mantissa; tmp1.exponent = SQRT2.exponent; tmp1.sign = SQRT2.sign; };
+ tmp1.add(ONE);
+ if (this.compare(tmp1) > 0) {
+ addPI_2 = true;
+ recip();
+ neg();
+ } else {
+ tmp1.sub(TWO);
+ if (this.compare(tmp1) > 0) {
+ addPI_4 = true;
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.add(ONE);
+ sub(ONE);
+ div(tmp1);
+ }
+ }
+ // Now |X|<sqrt(2)-1
+ // rational approximation
+ // atan(x) = x + x³ P(x²)/Q(x²)
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ tmp2.sqr();
+ mul(tmp2);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3fffffff; tmp3.mantissa=0x6f2f89336729c767L; };//-0.8686381817809218753544
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)1; tmp4.exponent=0x40000003; tmp4.mantissa=0x7577d35fd03083f3L; };//-14.683508633175792446076
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)1; tmp4.exponent=0x40000005; tmp4.mantissa=0x7ff42abff948a9f7L; };//-63.976888655834347413154
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)1; tmp4.exponent=0x40000006; tmp4.mantissa=0x63fd1f9f76d37cebL; };//-99.988763777265819915721
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)1; tmp4.exponent=0x40000005; tmp4.mantissa=0x65c9c9b0b55e5b62L; };//-50.894116899623603312185
+ tmp3.add(tmp4);
+ mul(tmp3);
+ { tmp3.mantissa = tmp2.mantissa; tmp3.exponent = tmp2.exponent; tmp3.sign = tmp2.sign; };
+ { tmp4.sign=(byte)0; tmp4.exponent=0x40000004; tmp4.mantissa=0x5bed73b744a72a6aL; };//22.981886733594175366172
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x40000007; tmp4.mantissa=0x47fed7d13d233b5cL; };//143.99096122250781605352
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x40000008; tmp4.mantissa=0x5a5c35f774e071d5L; };//361.44079386152023162701
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x40000008; tmp4.mantissa=0x61e4d84c2853d5e0L; };//391.57570175111990631099
+ tmp3.add(tmp4);
+ tmp3.mul(tmp2);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x40000007; tmp4.mantissa=0x4c5757448806c48eL; };//152.68235069887081006606
+ tmp3.add(tmp4);
+ div(tmp3);
+ add(tmp1);
+ if (addPI_2)
+ add(PI_2);
+ if (addPI_4)
+ add(PI_4);
+ if (s != 0)
+ neg();
+ }
+ /**
+ * Calculates the trigonometric arc tangent of this
+ * <code>Real</code> divided by <code>x</code>, in the range -π
+ * to π. The signs of both arguments are used to determine the
+ * quadrant of the result. Replaces the contents of this
+ * <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#atan2(double,double)
+ * atan2}(this,x);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 48
+ * </td></tr></table>
+ *
+ * @param x the <code>Real</code> argument.
+ */
+ public void atan2(Real x) {
+ if ((this.exponent < 0 && this.mantissa != 0) || (x.exponent < 0 && x.mantissa != 0) || ((this.exponent < 0 && this.mantissa == 0) && (x.exponent < 0 && x.mantissa == 0))) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0) && (x.exponent == 0 && x.mantissa == 0))
+ return;
+ byte s = sign;
+ byte s2 = x.sign;
+ sign = 0;
+ x.sign = 0;
+ div(x);
+ atan();
+ if (s2 != 0) {
+ neg();
+ add(PI);
+ }
+ sign = s;
+ }
+ /**
+ * Calculates the hyperbolic sine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#sinh(double) sinh}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 67
+ * </td></tr></table>
+ */
+ public void sinh() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.neg();
+ tmp1.exp();
+ exp();
+ sub(tmp1);
+ scalbn(-1);
+ }
+ /**
+ * Calculates the hyperbolic cosine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#cosh(double) cosh}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 66
+ * </td></tr></table>
+ */
+ public void cosh() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.neg();
+ tmp1.exp();
+ exp();
+ add(tmp1);
+ scalbn(-1);
+ }
+ /**
+ * Calculates the hyperbolic tangent of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#tanh(double) tanh}(this);</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 70
+ * </td></tr></table>
+ */
+ public void tanh() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.neg();
+ tmp1.exp();
+ exp();
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ tmp2.add(tmp1);
+ sub(tmp1);
+ div(tmp2);
+ }
+ /**
+ * Calculates the hyperbolic arc sine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 77
+ * </td></tr></table>
+ */
+ public void asinh() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ // Use symmetry to prevent underflow error for very large negative
+ // values
+ byte s = sign;
+ sign = 0;
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.sqr();
+ tmp1.add(ONE);
+ tmp1.sqrt();
+ add(tmp1);
+ ln();
+ if (!(this.exponent < 0 && this.mantissa != 0))
+ sign = s;
+ }
+ /**
+ * Calculates the hyperbolic arc cosine of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 75
+ * </td></tr></table>
+ */
+ public void acosh() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.sqr();
+ tmp1.sub(ONE);
+ tmp1.sqrt();
+ add(tmp1);
+ ln();
+ }
+ /**
+ * Calculates the hyperbolic arc tangent of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 57
+ * </td></tr></table>
+ */
+ public void atanh() {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.neg();
+ tmp1.add(ONE);
+ add(ONE);
+ div(tmp1);
+ ln();
+ scalbn(-1);
+ }
+ /**
+ * Calculates the factorial of this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ * The definition is generalized to all real numbers (not only integers),
+ * by using the fact that <code>(n!)={@link #gamma() gamma}(n+1)</code>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 15 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 8-190
+ * </td></tr></table>
+ */
+ public void fact() {
+ if (!(this.exponent >= 0))
+ return;
+ if (!this.isIntegral() || this.compare(ZERO)<0 || this.compare(200)>0)
+ {
+ // x<0, x>200 or not integer: fact(x) = gamma(x+1)
+ add(ONE);
+ gamma();
+ return;
+ }
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ while (tmp1.compare(ONE) > 0) {
+ mul(tmp1);
+ tmp1.sub(ONE);
+ }
+ }
+ /**
+ * Calculates the gamma function for this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 100+ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 190
+ * </td></tr></table>
+ */
+ public void gamma() {
+ if (!(this.exponent >= 0))
+ return;
+ // x<0: gamma(-x) = -pi/(x*gamma(x)*sin(pi*x))
+ boolean negative = (this.sign!=0);
+ abs();
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ // x<n: gamma(x) = gamma(x+m)/x*(x+1)*(x+2)*...*(x+m-1)
+ // n=20
+ { tmp2.mantissa = ONE.mantissa; tmp2.exponent = ONE.exponent; tmp2.sign = ONE.sign; };
+ boolean divide = false;
+ while (this.compare(20) < 0) {
+ divide = true;
+ tmp2.mul(this);
+ add(ONE);
+ }
+ // x>n: gamma(x) = exp((x-1/2)*ln(x) - x + ln(2*pi)/2 + 1/12x - 1/360x³
+ // + 1/1260x**5 - 1/1680x**7+1/1188x**9)
+ { tmp3.mantissa = this.mantissa; tmp3.exponent = this.exponent; tmp3.sign = this.sign; }; // x
+ { tmp4.mantissa = this.mantissa; tmp4.exponent = this.exponent; tmp4.sign = this.sign; };
+ tmp4.sqr(); // x²
+ // (x-1/2)*ln(x)-x
+ ln(); { tmp5.mantissa = tmp3.mantissa; tmp5.exponent = tmp3.exponent; tmp5.sign = tmp3.sign; }; tmp5.sub(HALF); mul(tmp5); sub(tmp3);
+ // + ln(2*pi)/2
+ { tmp5.sign=(byte)0; tmp5.exponent=0x3fffffff; tmp5.mantissa=0x759fc72192fad29aL; }; add(tmp5);
+ // + 1/12x
+ tmp5.assign( 12); tmp5.mul(tmp3); tmp5.recip(); add(tmp5); tmp3.mul(tmp4);
+ // - 1/360x³
+ tmp5.assign( 360); tmp5.mul(tmp3); tmp5.recip(); sub(tmp5); tmp3.mul(tmp4);
+ // + 1/1260x**5
+ tmp5.assign(1260); tmp5.mul(tmp3); tmp5.recip(); add(tmp5); tmp3.mul(tmp4);
+ // - 1/1680x**7
+ tmp5.assign(1680); tmp5.mul(tmp3); tmp5.recip(); sub(tmp5); tmp3.mul(tmp4);
+ // + 1/1188x**9
+ tmp5.assign(1188); tmp5.mul(tmp3); tmp5.recip(); add(tmp5);
+ exp();
+ if (divide)
+ div(tmp2);
+ if (negative) {
+ { tmp5.mantissa = tmp1.mantissa; tmp5.exponent = tmp1.exponent; tmp5.sign = tmp1.sign; }; // sin() uses tmp1
+ // -pi/(x*gamma(x)*sin(pi*x))
+ mul(tmp5);
+ tmp5.scalbn(-1); tmp5.frac(); tmp5.mul(PI2); // Fixes integer inaccuracy
+ tmp5.sin(); mul(tmp5); recip(); mul(PI); neg();
+ }
+ }
+ private void erfc1Internal() {
+ // 3 5 7 9
+ // 2 / x x x x // erfc(x) = 1 - ------ | x - --- + ---- - ---- + ---- - ... |
+ // sqrt(pi)\ 3 2!*5 3!*7 4!*9 /
+ //
+ long extra=0,tmp1Extra,tmp2Extra,tmp3Extra,tmp4Extra;
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; }; tmp1Extra = 0;
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ tmp2Extra = tmp2.mul128(0,tmp2,0);
+ tmp2.neg();
+ { tmp3.mantissa = ONE.mantissa; tmp3.exponent = ONE.exponent; tmp3.sign = ONE.sign; }; tmp3Extra = 0;
+ int i=1;
+ do {
+ tmp1Extra = tmp1.mul128(tmp1Extra,tmp2,tmp2Extra);
+ tmp4.assign(i);
+ tmp3Extra = tmp3.mul128(tmp3Extra,tmp4,0);
+ tmp4.assign(2*i+1);
+ tmp4Extra = tmp4.mul128(0,tmp3,tmp3Extra);
+ tmp4Extra = tmp4.recip128(tmp4Extra);
+ tmp4Extra = tmp4.mul128(tmp4Extra,tmp1,tmp1Extra);
+ extra = add128(extra,tmp4,tmp4Extra);
+ i++;
+ } while (exponent - tmp4.exponent < 128);
+ { tmp1.sign=(byte)1; tmp1.exponent=0x40000000; tmp1.mantissa=0x48375d410a6db446L; }; // -2/sqrt(pi)
+ extra = mul128(extra,tmp1,0xb8ea453fb5ff61a2L);
+ extra = add128(extra,ONE,0);
+ roundFrom128(extra);
+ }
+ private void erfc2Internal() {
+ // -x² -1
+ // e x / 1 3 3*5 3*5*7 // erfc(x) = -------- | 1 - --- + ------ - ------ + ------ - ... |
+ // sqrt(pi) \ 2x² 2 3 4 /
+ // (2x²) (2x²) (2x²)
+ // Calculate iteration stop criteria
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.sqr();
+ { tmp2.sign=(byte)0; tmp2.exponent=0x40000000; tmp2.mantissa=0x5c3811b4bfd0c8abL; }; // 1/0.694
+ tmp2.mul(tmp1);
+ tmp2.sub(HALF);
+ int digits = tmp2.toInteger(); // number of accurate digits = x*x/0.694-0.5
+ if (digits > 64)
+ digits = 64;
+ tmp1.scalbn(1);
+ int dxq = tmp1.toInteger()+1;
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ recip();
+ { tmp2.mantissa = this.mantissa; tmp2.exponent = this.exponent; tmp2.sign = this.sign; };
+ { tmp3.mantissa = this.mantissa; tmp3.exponent = this.exponent; tmp3.sign = this.sign; };
+ tmp3.sqr();
+ tmp3.neg();
+ tmp3.scalbn(-1);
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ { tmp4.mantissa = ONE.mantissa; tmp4.exponent = ONE.exponent; tmp4.sign = ONE.sign; };
+ int i=1;
+ do {
+ tmp4.mul(2*i-1);
+ tmp4.mul(tmp3);
+ add(tmp4);
+ i++;
+ } while (tmp4.exponent-0x40000000>-(digits+2) && 2*i-1<dxq);
+ mul(tmp2);
+ tmp1.sqr();
+ tmp1.neg();
+ tmp1.exp();
+ mul(tmp1);
+ { tmp1.sign=(byte)0; tmp1.exponent=0x3fffffff; tmp1.mantissa=0x48375d410a6db447L; }; // 1/sqrt(pi)
+ mul(tmp1);
+ }
+ /**
+ * Calculates the complementary error function for this <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>The complementary error function is defined as the integral from
+ * x to infinity of 2/√<span style="text-decoration:
+ * overline;">π</span> ·<i>e</i><sup>-t²</sup> dt. It is
+ * related to the error function, <i>erf</i>, by the formula
+ * erfc(x)=1-erf(x).
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2<sup>19</sup> ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 80-4900
+ * </td></tr></table>
+ */
+ public void erfc() {
+ if ((this.exponent < 0 && this.mantissa != 0))
+ return;
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ { this.mantissa = ONE.mantissa; this.exponent = ONE.exponent; this.sign = ONE.sign; };
+ return;
+ }
+ if ((this.exponent < 0 && this.mantissa == 0) || toInteger()>27281) {
+ if ((this.sign!=0)) {
+ { this.mantissa = TWO.mantissa; this.exponent = TWO.exponent; this.sign = TWO.sign; };
+ } else
+ makeZero(0);
+ return;
+ }
+ byte s = sign;
+ sign = 0;
+ { tmp1.sign=(byte)0; tmp1.exponent=0x40000002; tmp1.mantissa=0x570a3d70a3d70a3dL; }; // 5.44
+ if (this.lessThan(tmp1))
+ erfc1Internal();
+ else
+ erfc2Internal();
+ if (s != 0) {
+ neg();
+ add(TWO);
+ }
+ }
+ /**
+ * Calculates the inverse complementary error function for this
+ * <code>Real</code>.
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * 2<sup>19</sup> ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 240-5100
+ * </td></tr></table>
+ */
+ public void inverfc() {
+ if ((this.exponent < 0 && this.mantissa != 0) || (this.sign!=0) || this.greaterThan(TWO)) {
+ makeNan();
+ return;
+ }
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ makeInfinity(0);
+ return;
+ }
+ if (this.equalTo(TWO)) {
+ makeInfinity(1);
+ return;
+ }
+ int sign = ONE.compare(this);
+ if (sign==0) {
+ makeZero();
+ return;
+ }
+ if (sign<0) {
+ neg();
+ add(TWO);
+ }
+ // Using invphi to calculate inverfc, like this
+ // inverfc(x) = -invphi(x/2)/(sqrt(2))
+ scalbn(-1);
+ // Inverse Phi Algorithm (phi(Z)=P, so invphi(P)=Z)
+ // ------------------------------------------------
+ // Part 1: Numerical Approximation Method for Inverse Phi
+ // This accepts input of P and outputs approximate Z as Y
+ // Source:Odeh & Evans. 1974. AS 70. Applied Statistics.
+ // R = sqrt(Ln(1/(Q²)))
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.ln();
+ tmp1.mul(-2);
+ tmp1.sqrt();
+ // Y = -(R+((((P4*R+P3)*R+P2)*R+P1)*R+P0)/((((Q4*R+Q3)*R*Q2)*R+Q1)*R+Q0))
+ { tmp2.sign=(byte)1; tmp2.exponent=0x3ffffff1; tmp2.mantissa=0x5f22bb0fb4698674L; }; // P4=-0.0000453642210148
+ tmp2.mul(tmp1);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffffa; tmp3.mantissa=0x53a731ce1ea0be15L; }; // P3=-0.0204231210245
+ tmp2.add(tmp3);
+ tmp2.mul(tmp1);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffffe; tmp3.mantissa=0x579d2d719fc517f3L; }; // P2=-0.342242088547
+ tmp2.add(tmp3);
+ tmp2.mul(tmp1);
+ tmp2.add(-1); // P1=-1
+ tmp2.mul(tmp1);
+ { tmp3.sign=(byte)1; tmp3.exponent=0x3ffffffe; tmp3.mantissa=0x527dd3193bc8dd4cL; }; // P0=-0.322232431088
+ tmp2.add(tmp3);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x3ffffff7; tmp3.mantissa=0x7e5b0f681d161e7dL; }; // Q4=0.0038560700634
+ tmp3.mul(tmp1);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x3ffffffc; tmp4.mantissa=0x6a05ccf9917da0a8L; }; // Q3=0.103537752850
+ tmp3.add(tmp4);
+ tmp3.mul(tmp1);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x3fffffff; tmp4.mantissa=0x43fb32c0d3c14ec4L; }; // Q2=0.531103462366
+ tmp3.add(tmp4);
+ tmp3.mul(tmp1);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x3fffffff; tmp4.mantissa=0x4b56a41226f4ba95L; }; // Q1=0.588581570495
+ tmp3.add(tmp4);
+ tmp3.mul(tmp1);
+ { tmp4.sign=(byte)0; tmp4.exponent=0x3ffffffc; tmp4.mantissa=0x65bb9a7733dd5062L; }; // Q0=0.0993484626060
+ tmp3.add(tmp4);
+ tmp2.div(tmp3);
+ tmp1.add(tmp2);
+ tmp1.neg();
+ { sqrtTmp.mantissa = tmp1.mantissa; sqrtTmp.exponent = tmp1.exponent; sqrtTmp.sign = tmp1.sign; }; // sqrtTmp and tmp5 not used by erfc() and exp()
+ // Part 2: Refine to accuracy of erfc Function
+ // This accepts inputs Y and P (from above) and outputs Z
+ // (Using Halley's third order method for finding roots of equations)
+ // Q = erfc(-Y/sqrt(2))/2-P
+ { tmp5.mantissa = sqrtTmp.mantissa; tmp5.exponent = sqrtTmp.exponent; tmp5.sign = sqrtTmp.sign; };
+ tmp5.mul(SQRT1_2);
+ tmp5.neg();
+ tmp5.erfc();
+ tmp5.scalbn(-1);
+ tmp5.sub(this);
+ // R = Q*sqrt(2*pi)*e^(Y²/2)
+ { tmp3.mantissa = sqrtTmp.mantissa; tmp3.exponent = sqrtTmp.exponent; tmp3.sign = sqrtTmp.sign; };
+ tmp3.sqr();
+ tmp3.scalbn(-1);
+ tmp3.exp();
+ tmp5.mul(tmp3);
+ { tmp3.sign=(byte)0; tmp3.exponent=0x40000001; tmp3.mantissa=0x50364c7fd89c1659L; }; // sqrt(2*pi)
+ tmp5.mul(tmp3);
+ // Z = Y-R/(1+R*Y/2)
+ { this.mantissa = sqrtTmp.mantissa; this.exponent = sqrtTmp.exponent; this.sign = sqrtTmp.sign; };
+ mul(tmp5);
+ scalbn(-1);
+ add(ONE);
+ rdiv(tmp5);
+ neg();
+ add(sqrtTmp);
+ // calculate inverfc(x) = -invphi(x/2)/(sqrt(2))
+ mul(SQRT1_2);
+ if (sign>0)
+ neg();
+ }
+ //*************************************************************************
+ // Calendar conversions taken from
+ // http://www.fourmilab.ch/documents/calendar/
+ private static int floorDiv(int a, int b) {
+ if (a>=0)
+ return a/b;
+ return -((-a+b-1)/b);
+ }
+ private static int floorMod(int a, int b) {
+ if (a>=0)
+ return a%b;
+ return a+((-a+b-1)/b)*b;
+ }
+ private static boolean leap_gregorian(int year) {
+ return ((year % 4) == 0) &&
+ (!(((year % 100) == 0) && ((year % 400) != 0)));
+ }
+ // GREGORIAN_TO_JD -- Determine Julian day number from Gregorian
+ // calendar date -- Except that we use 1/1-0 as day 0
+ private static int gregorian_to_jd(int year, int month, int day) {
+ return ((366 - 1) +
+ (365 * (year - 1)) +
+ (floorDiv(year - 1, 4)) +
+ (-floorDiv(year - 1, 100)) +
+ (floorDiv(year - 1, 400)) +
+ ((((367 * month) - 362) / 12) +
+ ((month <= 2) ? 0 : (leap_gregorian(year) ? -1 : -2)) + day));
+ }
+ // JD_TO_GREGORIAN -- Calculate Gregorian calendar date from Julian
+ // day -- Except that we use 1/1-0 as day 0
+ private static int jd_to_gregorian(int jd) {
+ int wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad,
+ yindex, year, yearday, leapadj, month, day;
+ wjd = jd;
+ depoch = wjd - 366;
+ quadricent = floorDiv(depoch, 146097);
+ dqc = floorMod(depoch, 146097);
+ cent = floorDiv(dqc, 36524);
+ dcent = floorMod(dqc, 36524);
+ quad = floorDiv(dcent, 1461);
+ dquad = floorMod(dcent, 1461);
+ yindex = floorDiv(dquad, 365);
+ year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
+ if (!((cent == 4) || (yindex == 4)))
+ year++;
+ yearday = wjd - gregorian_to_jd(year, 1, 1);
+ leapadj = ((wjd < gregorian_to_jd(year, 3, 1)) ? 0
+ : (leap_gregorian(year) ? 1 : 2));
+ month = floorDiv(((yearday + leapadj) * 12) + 373, 367);
+ day = (wjd - gregorian_to_jd(year, month, 1)) + 1;
+ return (year*100+month)*100+day;
+ }
+ /**
+ * Converts this <code>Real</code> from "hours" to "days, hours,
+ * minutes and seconds".
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>The format converted to is encoded into the digits of the
+ * number (in decimal form):
+ * "<code>DDDDhh.mmss</code>". Here "<code>DDDD</code>," is number
+ * of days, "<code>hh</code>" is hours (0-23), "<code>mm</code>" is
+ * minutes (0-59) and "<code>ss</code>" is seconds
+ * (0-59). Additional digits represent fractions of a second.
+ *
+ * <p>If the number of hours of the input is greater or equal to
+ * 8784 (number of hours in year <code>0</code>), the format
+ * converted to is instead "<code>YYYYMMDDhh.mmss</code>". Here
+ * "<code>YYYY</code>" is the number of years since the imaginary
+ * year <code>0</code> in the Gregorian calendar, extrapolated back
+ * from year 1582. "<code>MM</code>" is the month (1-12) and
+ * "<code>DD</code>" is the day of the month (1-31). See a thorough
+ * discussion of date calculations <a
+ * href="http://midp-calc.sourceforge.net/Calc.html#DateNote">here</a>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * ?
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 19
+ * </td></tr></table>
+ */
+ public void toDHMS() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ boolean negative = (this.sign!=0);
+ abs();
+ int D,m;
+ long h;
+ h = toLong();
+ frac();
+ tmp1.assign(60);
+ mul(tmp1);
+ m = toInteger();
+ frac();
+ mul(tmp1);
+ // MAGIC ROUNDING: Check if we are 2**-16 sec short of a whole minute
+ // i.e. "seconds" > 59.999985
+ { tmp2.mantissa = ONE.mantissa; tmp2.exponent = ONE.exponent; tmp2.sign = ONE.sign; };
+ tmp2.scalbn(-16);
+ add(tmp2);
+ if (this.compare(tmp1) >= 0) {
+ // Yes. So set zero secs instead and carry over to mins and hours
+ { this.mantissa = ZERO.mantissa; this.exponent = ZERO.exponent; this.sign = ZERO.sign; };
+ m++;
+ if (m >= 60) {
+ m -= 60;
+ h++;
+ }
+ // Phew! That was close. From now on it is integer arithmetic...
+ } else {
+ // Nope. So try to undo the damage...
+ sub(tmp2);
+ }
+ D = (int)(h/24);
+ h %= 24;
+ if (D >= 366)
+ D = jd_to_gregorian(D);
+ add(m*100);
+ div(10000);
+ tmp1.assign(D*100L+h);
+ add(tmp1);
+ if (negative)
+ neg();
+ }
+ /**
+ * Converts this <code>Real</code> from "days, hours, minutes and
+ * seconds" to "hours".
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>The format converted from is encoded into the digits of the
+ * number (in decimal form):
+ * "<code>DDDDhh.mmss</code>". Here "<code>DDDD</code>" is number of
+ * days, "<code>hh</code>" is hours (0-23), "<code>mm</code>" is
+ * minutes (0-59) and "<code>ss</code>" is seconds
+ * (0-59). Additional digits represent fractions of a second.
+ *
+ * <p>If the number of days in the input is greater than or equal to
+ * 10000, the format converted from is instead
+ * "<code>YYYYMMDDhh.mmss</code>". Here "<code>YYYY</code>" is the
+ * number of years since the imaginary year <code>0</code> in the
+ * Gregorian calendar, extrapolated back from year
+ * 1582. "<code>MM</code>" is the month (1-12) and
+ * "<code>DD</code>" is the day of the month (1-31). If month or day
+ * is 0 it is treated as 1. See a thorough discussion of date
+ * calculations <a
+ * href="http://midp-calc.sourceforge.net/Calc.html#DateNote">here</a>.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * ?
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 19
+ * </td></tr></table>
+ */
+ public void fromDHMS() {
+ if (!(this.exponent >= 0 && this.mantissa != 0))
+ return;
+ boolean negative = (this.sign!=0);
+ abs();
+ int Y,M,D,m;
+ long h;
+ h = toLong();
+ frac();
+ tmp1.assign(100);
+ mul(tmp1);
+ m = toInteger();
+ frac();
+ mul(tmp1);
+ // MAGIC ROUNDING: Check if we are 2**-10 second short of 100 seconds
+ // i.e. "seconds" > 99.999
+ { tmp2.mantissa = ONE.mantissa; tmp2.exponent = ONE.exponent; tmp2.sign = ONE.sign; };
+ tmp2.scalbn(-10);
+ add(tmp2);
+ if (this.compare(tmp1) >= 0) {
+ // Yes. So set zero secs instead and carry over to mins and hours
+ { this.mantissa = ZERO.mantissa; this.exponent = ZERO.exponent; this.sign = ZERO.sign; };
+ m++;
+ if (m >= 100) {
+ m -= 100;
+ h++;
+ }
+ // Phew! That was close. From now on it is integer arithmetic...
+ } else {
+ // Nope. So try to undo the damage...
+ sub(tmp2);
+ }
+ D = (int)(h/100);
+ h %= 100;
+ if (D>=10000) {
+ M = D/100;
+ D %= 100;
+ if (D==0) D=1;
+ Y = M/100;
+ M %= 100;
+ if (M==0) M=1;
+ D = gregorian_to_jd(Y,M,D);
+ }
+ add(m*60);
+ div(3600);
+ tmp1.assign(D*24L+h);
+ add(tmp1);
+ if (negative)
+ neg();
+ }
+ /**
+ * Assigns this <code>Real</code> the current time. The time is
+ * encoded into the digits of the number (in decimal form), using the
+ * format "<code>hh.mmss</code>", where "<code>hh</code>" is hours,
+ * "<code>mm</code>" is minutes and "code>ss</code>" is seconds.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * ½ ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 8.9
+ * </td></tr></table>
+ */
+ public void time() {
+ long now = System.currentTimeMillis();
+ int h,m,s;
+ now /= 1000;
+ s = (int)(now % 60);
+ now /= 60;
+ m = (int)(now % 60);
+ now /= 60;
+ h = (int)(now % 24);
+ assign((h*100+m)*100+s);
+ div(10000);
+ }
+ /**
+ * Assigns this <code>Real</code> the current date. The date is
+ * encoded into the digits of the number (in decimal form), using
+ * the format "<code>YYYYMMDD00</code>", where "<code>YYYY</code>"
+ * is the year, "<code>MM</code>" is the month (1-12) and
+ * "<code>DD</code>" is the day of the month (1-31). The
+ * "<code>00</code>" in this format is a sort of padding to make it
+ * compatible with the format used by {@link #toDHMS()} and {@link
+ * #fromDHMS()}.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <i>none</i>
+ * </td></tr><tr><td><i>Error bound:</i></td><td>
+ * 0 ULPs
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 30
+ * </td></tr></table>
+ */
+ public void date() {
+ long now = System.currentTimeMillis();
+ now /= 86400000; // days
+ now *= 24; // hours
+ assign(now);
+ add(719528*24); // 1970-01-01 era
+ toDHMS();
+ }
+ //*************************************************************************
+ /**
+ * The seed of the first 64-bit CRC generator of the random
+ * routine. Set this value to control the generated sequence of random
+ * numbers. Should never be set to 0. See {@link #random()}.
+ * Initialized to mantissa of pi.
+ */
+ public static long randSeedA = 0x6487ed5110b4611aL;
+ /**
+ * The seed of the second 64-bit CRC generator of the random
+ * routine. Set this value to control the generated sequence of random
+ * numbers. Should never be set to 0. See {@link #random()}.
+ * Initialized to mantissa of e.
+ */
+ public static long randSeedB = 0x56fc2a2c515da54dL;
+ // 64 Bit CRC Generators
+ //
+ // The generators used here are not cryptographically secure, but
+ // two weak generators are combined into one strong generator by
+ // skipping bits from one generator whenever the other generator
+ // produces a 0-bit.
+ private static void advanceBit() {
+ randSeedA = (randSeedA<<1)^(randSeedA<0?0x1b:0);
+ randSeedB = (randSeedB<<1)^(randSeedB<0?0xb000000000000001L:0);
+ }
+ // Get next bits from the pseudo-random sequence
+ private static long nextBits(int bits) {
+ long answer = 0;
+ while (bits-- > 0) {
+ while (randSeedA >= 0)
+ advanceBit();
+ answer = (answer<<1) + (randSeedB < 0 ? 1 : 0);
+ advanceBit();
+ }
+ return answer;
+ }
+ /**
+ * Accumulate more randomness into the random number generator, to
+ * decrease the predictability of the output from {@link
+ * #random()}. The input should contain data with some form of
+ * inherent randomness e.g. System.currentTimeMillis().
+ *
+ * @param seed some extra randomness for the random number generator.
+ */
+ public static void accumulateRandomness(long seed) {
+ randSeedA ^= seed & 0x5555555555555555L;
+ randSeedB ^= seed & 0xaaaaaaaaaaaaaaaaL;
+ nextBits(63);
+ }
+ /**
+ * Calculates a pseudorandom number in the range [0, 1).
+ * Replaces the contents of this <code>Real</code> with the result.
+ *
+ * <p>The algorithm used is believed to be cryptographically secure,
+ * combining two relatively weak 64-bit CRC generators into a strong
+ * generator by skipping bits from one generator whenever the other
+ * generator produces a 0-bit. The algorithm passes the <a
+ * href="http://www.fourmilab.ch/random/">ent</a> test.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this = Math.{@link Math#random() random}();</code>
+ * </td></tr><tr><td><i>Approximate error bound:</i></td><td>
+ * -
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 81
+ * </td></tr></table>
+ */
+ public void random() {
+ sign = 0;
+ exponent = 0x3fffffff;
+ while (nextBits(1) == 0)
+ exponent--;
+ mantissa = 0x4000000000000000L+nextBits(62);
+ }
+ //*************************************************************************
+ private int digit(char a, int base, boolean twosComplement) {
+ int digit = -1;
+ if (a>='0' && a<='9')
+ digit = a-'0';
+ else if (a>='A' && a<='F')
+ digit = a-'A'+10;
+ if (digit >= base)
+ return -1;
+ if (twosComplement)
+ digit ^= base-1;
+ return digit;
+ }
+ private void shiftUp(int base) {
+ if (base==2)
+ scalbn(1);
+ else if (base==8)
+ scalbn(3);
+ else if (base==16)
+ scalbn(4);
+ else
+ mul10();
+ }
+ private void atof(String a, int base) {
+ makeZero();
+ int length = a.length();
+ int index = 0;
+ byte tmpSign = 0;
+ boolean compl = false;
+ while (index<length && a.charAt(index)==' ')
+ index++;
+ if (index<length && a.charAt(index)=='-') {
+ tmpSign=1;
+ index++;
+ } else if (index<length && a.charAt(index)=='+') {
+ index++;
+ } else if (index<length && a.charAt(index)=='/') {
+ // Input is twos complemented negative number
+ compl=true;
+ tmpSign=1;
+ index++;
+ }
+ int d;
+ while (index<length && (d=digit(a.charAt(index),base,compl))>=0) {
+ shiftUp(base);
+ add(d);
+ index++;
+ }
+ int exp=0;
+ if (index<length && (a.charAt(index)=='.' || a.charAt(index)==',')) {
+ index++;
+ while (index<length && (d=digit(a.charAt(index),base,compl))>=0) {
+ shiftUp(base);
+ add(d);
+ exp--;
+ index++;
+ }
+ }
+ if (compl)
+ add(ONE);
+ while (index<length && a.charAt(index)==' ')
+ index++;
+ if (index<length && (a.charAt(index)=='e' || a.charAt(index)=='E')) {
+ index++;
+ int exp2 = 0;
+ boolean expNeg = false;
+ if (index<length && a.charAt(index)=='-') {
+ expNeg = true;
+ index++;
+ } else if (index<length && a.charAt(index)=='+') {
+ index++;
+ }
+ while (index<length && a.charAt(index)>='0' &&
+ a.charAt(index)<='9')
+ {
+ // This takes care of overflows and makes inf or 0
+ if (exp2 < 400000000)
+ exp2 = exp2*10 + a.charAt(index) - '0';
+ index++;
+ }
+ if (expNeg)
+ exp2 = -exp2;
+ exp += exp2;
+ }
+ if (base==2)
+ scalbn(exp);
+ else if (base==8)
+ scalbn(exp*3);
+ else if (base==16)
+ scalbn(exp*4);
+ else {
+ if (exp > 300000000 || exp < -300000000) {
+ // Kludge to be able to enter very large and very small
+ // numbers without causing over/underflows
+ { tmp1.mantissa = TEN.mantissa; tmp1.exponent = TEN.exponent; tmp1.sign = TEN.sign; };
+ if (exp<0) {
+ tmp1.pow(-exp/2);
+ div(tmp1);
+ } else {
+ tmp1.pow(exp/2);
+ mul(tmp1);
+ }
+ exp -= exp/2;
+ }
+ { tmp1.mantissa = TEN.mantissa; tmp1.exponent = TEN.exponent; tmp1.sign = TEN.sign; };
+ if (exp<0) {
+ tmp1.pow(-exp);
+ div(tmp1);
+ } else if (exp>0) {
+ tmp1.pow(exp);
+ mul(tmp1);
+ }
+ }
+ sign = tmpSign;
+ }
+ //*************************************************************************
+ private void normalizeDigits(byte[] digits, int nDigits, int base) {
+ byte carry = 0;
+ boolean isZero = true;
+ for (int i=nDigits-1; i>=0; i--) {
+ if (digits[i] != 0)
+ isZero = false;
+ digits[i] += carry;
+ carry = 0;
+ if (digits[i] >= base) {
+ digits[i] -= base;
+ carry = 1;
+ }
+ }
+ if (isZero) {
+ exponent = 0;
+ return;
+ }
+ if (carry != 0) {
+ if (digits[nDigits-1] >= base/2)
+ digits[nDigits-2] ++; // Rounding, may be inaccurate
+ System.arraycopy(digits, 0, digits, 1, nDigits-1);
+ digits[0] = carry;
+ exponent++;
+ if (digits[nDigits-1] >= base) {
+ // Oh, no, not again!
+ normalizeDigits(digits, nDigits, base);
+ }
+ }
+ while (digits[0] == 0) {
+ System.arraycopy(digits, 1, digits, 0, nDigits-1);
+ digits[nDigits-1] = 0;
+ exponent--;
+ }
+ }
+ private int getDigits(byte[] digits, int base) {
+ if (base == 10)
+ {
+ { tmp1.mantissa = this.mantissa; tmp1.exponent = this.exponent; tmp1.sign = this.sign; };
+ tmp1.abs();
+ { tmp2.mantissa = tmp1.mantissa; tmp2.exponent = tmp1.exponent; tmp2.sign = tmp1.sign; };
+ int exp = exponent = tmp1.lowPow10();
+ exp -= 18;
+ boolean exp_neg = exp <= 0;
+ exp = Math.abs(exp);
+ if (exp > 300000000) {
+ // Kludge to be able to print very large and very small numbers
+ // without causing over/underflows
+ { tmp1.mantissa = TEN.mantissa; tmp1.exponent = TEN.exponent; tmp1.sign = TEN.sign; };
+ tmp1.pow(exp/2); // So, divide twice by not-so-extreme numbers
+ if (exp_neg)
+ tmp2.mul(tmp1);
+ else
+ tmp2.div(tmp1);
+ { tmp1.mantissa = TEN.mantissa; tmp1.exponent = TEN.exponent; tmp1.sign = TEN.sign; };
+ tmp1.pow(exp-(exp/2));
+ } else {
+ { tmp1.mantissa = TEN.mantissa; tmp1.exponent = TEN.exponent; tmp1.sign = TEN.sign; };
+ tmp1.pow(exp);
+ }
+ if (exp_neg)
+ tmp2.mul(tmp1);
+ else
+ tmp2.div(tmp1);
+ long a;
+ if (tmp2.exponent > 0x4000003e) {
+ tmp2.exponent--;
+ tmp2.round();
+ a = tmp2.toLong();
+ if (a >= 5000000000000000000L) { // Rounding up gave 20 digits
+ exponent++;
+ a /= 5;
+ digits[18] = (byte)(a%10);
+ a /= 10;
+ } else {
+ digits[18] = (byte)((a%5)*2);
+ a /= 5;
+ }
+ } else {
+ tmp2.round();
+ a = tmp2.toLong();
+ digits[18] = (byte)(a%10);
+ a /= 10;
+ }
+ for (int i=17; i>=0; i--) {
+ digits[i] = (byte)(a%10);
+ a /= 10;
+ }
+ digits[19] = 0;
+ return 19;
+ }
+ int accurateBits = 64;
+ int bitsPerDigit = base == 2 ? 1 : base == 8 ? 3 : 4;
+ if ((this.exponent == 0 && this.mantissa == 0)) {
+ sign = 0; // Two's complement cannot display -0
+ } else {
+ if ((this.sign!=0)) {
+ mantissa = -mantissa;
+ if (((mantissa >> 62)&3) == 3) {
+ mantissa <<= 1;
+ exponent--;
+ accurateBits--; // ?
+ }
+ }
+ exponent -= 0x40000000-1;
+ int shift = bitsPerDigit-1 -
+ floorMod(exponent, bitsPerDigit);
+ exponent = floorDiv(exponent, bitsPerDigit);
+ if (shift == bitsPerDigit-1) {
+ // More accurate to shift up instead
+ mantissa <<= 1;
+ exponent--;
+ accurateBits--;
+ }
+ else if (shift>0) {
+ mantissa = (mantissa+(1L<<(shift-1)))>>>shift;
+ if ((this.sign!=0)) {
+ // Need to fill in some 1's at the top
+ // (">>", not ">>>")
+ mantissa |= 0x8000000000000000L>>(shift-1);
+ }
+ }
+ }
+ int accurateDigits = (accurateBits+bitsPerDigit-1)/bitsPerDigit;
+ for (int i=0; i<accurateDigits; i++) {
+ digits[i] = (byte)(mantissa>>>(64-bitsPerDigit));
+ mantissa <<= bitsPerDigit;
+ }
+ digits[accurateDigits] = 0;
+ return accurateDigits;
+ }
+ private boolean carryWhenRounded(byte[] digits, int nDigits, int base) {
+ if (digits[nDigits] < base/2)
+ return false; // no rounding up, no carry
+ for (int i=nDigits-1; i>=0; i--)
+ if (digits[i] < base-1)
+ return false; // carry would not propagate
+ exponent++;
+ digits[0] = 1;
+ for (int i=1; i<digits.length; i++)
+ digits[i] = 0;
+ return true;
+ }
+ private void round(byte[] digits, int nDigits, int base) {
+ if (digits[nDigits] >= base/2) {
+ digits[nDigits-1]++;
+ normalizeDigits(digits, nDigits, base);
+ }
+ }
+ /**
+ * The number format used to convert <code>Real</code> values to
+ * <code>String</code> using {@link Real#toString(Real.NumberFormat)
+ * Real.toString()}. The default number format uses base-10, maximum
+ * precision, removal of trailing zeros and '.' as radix point.
+ *
+ * <p>Note that the fields of <code>NumberFormat</code> are not
+ * protected in any way, the user is responsible for setting the
+ * correct values to get a correct result.
+ */
+ public static class NumberFormat
+ {
+ /**
+ * The number base of the conversion. The default value is 10,
+ * valid options are 2, 8, 10 and 16. See {@link Real#and(Real)
+ * Real.and()} for an explanation of the interpretation of a
+ * <code>Real</code> in base 2, 8 and 16.
+ *
+ * <p>Negative numbers output in base-2, base-8 and base-16 are
+ * shown in two's complement form. This form guarantees that a
+ * negative number starts with at least one digit that is the
+ * maximum digit for that base, i.e. '1', '7', and 'F',
+ * respectively. A positive number is guaranteed to start with at
+ * least one '0'. Both positive and negative numbers are extended
+ * to the left using this digit, until {@link #maxwidth} is
+ * reached.
+ */
+ public int base = 10;
+ /**
+ * Maximum width of the converted string. The default value is 30.
+ * If the conversion of a <code>Real</code> with a given {@link
+ * #precision} would produce a string wider than
+ * <code>maxwidth</code>, <code>precision</code> is reduced until
+ * the number fits within the given width. If
+ * <code>maxwidth</code> is too small to hold the number with its
+ * sign, exponent and a <code>precision</code> of 1 digit, the
+ * string may become wider than <code>maxwidth</code>.
+ *
+ * <p>If <code>align</code> is set to anything but
+ * <code>ALIGN_NONE</code> and the converted string is shorter
+ * than <code>maxwidth</code>, the resulting string is padded with
+ * spaces to the specified width according to the alignment.
+ */
+ public int maxwidth = 30;
+ /**
+ * The precision, or number of digits after the radix point in the
+ * converted string when using the <i>FIX</i>, <i>SCI</i> or
+ * <i>ENG</i> format (see {@link #fse}). The default value is 16,
+ * valid values are 0-16 for base-10 and base-16 conversion, 0-21
+ * for base-8 conversion, and 0-63 for base-2 conversion.
+ *
+ * <p>The <code>precision</code> may be reduced to make the number
+ * fit within {@link #maxwidth}. The <code>precision</code> is
+ * also reduced if it is set higher than the actual numbers of
+ * significant digits in a <code>Real</code>. When
+ * <code>fse</code> is set to <code>FSE_NONE</code>, i.e. "normal"
+ * output, the precision is always at maximum, but trailing zeros
+ * are removed.
+ */
+ public int precision = 16;
+ /**
+ * The special output formats <i>FIX</i>, <i>SCI</i> or <i>ENG</i>
+ * are enabled with this field. The default value is
+ * <code>FSE_NONE</code>. Valid options are listed below.
+ *
+ * <p>Numbers are output in one of two main forms, according to
+ * this setting. The normal form has an optional sign, one or more
+ * digits before the radix point, and zero or more digits after the
+ * radix point, for example like this:<br>
+ * <code> 3.14159</code><br>
+ * The exponent form is like the normal form, followed by an
+ * exponent marker 'e', an optional sign and one or more exponent
+ * digits, for example like this:<br>
+ * <code> -3.4753e-13</code>
+ *
+ * <p><dl>
+ * <dt>{@link #FSE_NONE}
+ * <dd>Normal output. Numbers are output with maximum precision,
+ * trailing zeros are removed. The format is changed to
+ * exponent form if the number is larger than the number of
+ * significant digits allows, or if the resulting string would
+ * exceed <code>maxwidth</code> without the exponent form.
+ *
+ * <dt>{@link #FSE_FIX}
+ * <dd>Like normal output, but the numbers are output with a
+ * fixed number of digits after the radix point, according to
+ * {@link #precision}. Trailing zeros are not removed.
+ *
+ * <dt>{@link #FSE_SCI}
+ * <dd>The numbers are always output in the exponent form, with
+ * one digit before the radix point, and a fixed number of
+ * digits after the radix point, according to
+ * <code>precision</code>. Trailing zeros are not removed.
+ *
+ * <dt>{@link #FSE_ENG}
+ * <dd>Like the <i>SCI</i> format, but the output shows one to
+ * three digits before the radix point, so that the exponent is
+ * always divisible by 3.
+ * </dl>
+ */
+ public int fse = FSE_NONE;
+ /**
+ * The character used as the radix point. The default value is
+ * <code>'.'</code>. Theoretcally any character that does not
+ * otherwise occur in the output can be used, such as
+ * <code>','</code>.
+ *
+ * <p>Note that setting this to anything but <code>'.'</code> and
+ * <code>','</code> is not supported by any conversion method from
+ * <code>String</code> back to <code>Real</code>.
+ */
+ public char point = '.';
+ /**
+ * Set to <code>true</code> to remove the radix point if this is
+ * the last character in the converted string. This is the
+ * default.
+ */
+ public boolean removePoint = true;
+ /**
+ * The character used as the thousands separator. The default
+ * value is the character code <code>0</code>, which disables
+ * thousands-separation. Theoretcally any character that does not
+ * otherwise occur in the output can be used, such as
+ * <code>','</code> or <code>' '</code>.
+ *
+ * <p>When <code>thousand!=0</code>, this character is inserted
+ * between every 3rd digit to the left of the radix point in
+ * base-10 conversion. In base-16 conversion, the separator is
+ * inserted between every 4th digit, and in base-2 conversion the
+ * separator is inserted between every 8th digit. In base-8
+ * conversion, no separator is ever inserted.
+ *
+ * <p>Note that tousands separators are not supported by any
+ * conversion method from <code>String</code> back to
+ * <code>Real</code>, so use of a thousands separator is meant
+ * only for the presentation of numbers.
+ */
+ public char thousand = 0;
+ /**
+ * The alignment of the output string within a field of {@link
+ * #maxwidth} characters. The default value is
+ * <code>ALIGN_NONE</code>. Valid options are defined as follows:
+ *
+ * <p><dl>
+ * <dt>{@link #ALIGN_NONE}
+ * <dd>The resulting string is not padded with spaces.
+ *
+ * <dt>{@link #ALIGN_LEFT}
+ * <dd>The resulting string is padded with spaces on the right side
+ * until a width of <code>maxwidth</code> is reached, making the
+ * number left-aligned within the field.
+ *
+ * <dt>{@link #ALIGN_RIGHT}
+ * <dd>The resulting string is padded with spaces on the left side
+ * until a width of <code>maxwidth</code> is reached, making the
+ * number right-aligned within the field.
+ *
+ * <dt>{@link #ALIGN_CENTER}
+ * <dd>The resulting string is padded with spaces on both sides
+ * until a width of <code>maxwidth</code> is reached, making the
+ * number center-aligned within the field.
+ * </dl>
+ */
+ public int align = ALIGN_NONE;
+ /** Normal output {@linkplain #fse format} */
+ public static final int FSE_NONE = 0;
+ /** <i>FIX</i> output {@linkplain #fse format} */
+ public static final int FSE_FIX = 1;
+ /** <i>SCI</i> output {@linkplain #fse format} */
+ public static final int FSE_SCI = 2;
+ /** <i>ENG</i> output {@linkplain #fse format} */
+ public static final int FSE_ENG = 3;
+ /** No {@linkplain #align alignment} */
+ public static final int ALIGN_NONE = 0;
+ /** Left {@linkplain #align alignment} */
+ public static final int ALIGN_LEFT = 1;
+ /** Right {@linkplain #align alignment} */
+ public static final int ALIGN_RIGHT = 2;
+ /** Center {@linkplain #align alignment} */
+ public static final int ALIGN_CENTER = 3;
+ }
+ private String align(StringBuffer s, NumberFormat format) {
+ if (format.align == NumberFormat.ALIGN_LEFT) {
+ while (s.length()<format.maxwidth)
+ s.append(' ');
+ } else if (format.align == NumberFormat.ALIGN_RIGHT) {
+ while (s.length()<format.maxwidth)
+ s.insert(0,' ');
+ } else if (format.align == NumberFormat.ALIGN_CENTER) {
+ while (s.length()<format.maxwidth) {
+ s.append(' ');
+ if (s.length()<format.maxwidth)
+ s.insert(0,' ');
+ }
+ }
+ return s.toString();
+ }
+ private static byte[] ftoaDigits = new byte[65];
+ private static StringBuffer ftoaBuf = new StringBuffer(40);
+ private static StringBuffer ftoaExp = new StringBuffer(15);
+ /**
+ * This string holds the only valid characters to use in hexadecimal
+ * numbers. Equals <code>"0123456789ABCDEF"</code>.
+ * See {@link #assign(String,int)}.
+ */
+ public static final String hexChar = "0123456789ABCDEF";
+ private String ftoa(NumberFormat format) {
+ ftoaBuf.setLength(0);
+ if ((this.exponent < 0 && this.mantissa != 0)) {
+ ftoaBuf.append("nan");
+ return align(ftoaBuf,format);
+ }
+ if ((this.exponent < 0 && this.mantissa == 0)) {
+ ftoaBuf.append((this.sign!=0) ? "-inf":"inf");
+ return align(ftoaBuf,format);
+ }
+ int digitsPerThousand;
+ switch (format.base) {
+ case 2:
+ digitsPerThousand = 8;
+ break;
+ case 8:
+ digitsPerThousand = 1000; // Disable thousands separator
+ break;
+ case 16:
+ digitsPerThousand = 4;
+ break;
+ case 10:
+ default:
+ digitsPerThousand = 3;
+ break;
+ }
+ if (format.thousand == 0)
+ digitsPerThousand = 1000; // Disable thousands separator
+ { tmp4.mantissa = this.mantissa; tmp4.exponent = this.exponent; tmp4.sign = this.sign; };
+ int accurateDigits = tmp4.getDigits(ftoaDigits, format.base);
+ if (format.base == 10 && (exponent > 0x4000003e || !isIntegral()))
+ accurateDigits = 16; // Only display 16 digits for non-integers
+ int precision;
+ int pointPos = 0;
+ do
+ {
+ int width = format.maxwidth-1; // subtract 1 for decimal point
+ int prefix = 0;
+ if (format.base != 10)
+ prefix = 1; // want room for at least one "0" or "f/7/1"
+ else if ((tmp4.sign!=0))
+ width--; // subtract 1 for sign
+ boolean useExp = false;
+ switch (format.fse) {
+ case NumberFormat.FSE_SCI:
+ precision = format.precision+1;
+ useExp = true;
+ break;
+ case NumberFormat.FSE_ENG:
+ pointPos = floorMod(tmp4.exponent,3);
+ precision = format.precision+1+pointPos;
+ useExp = true;
+ break;
+ case NumberFormat.FSE_FIX:
+ case NumberFormat.FSE_NONE:
+ default:
+ precision = 1000;
+ if (format.fse == NumberFormat.FSE_FIX)
+ precision = format.precision+1;
+ if (tmp4.exponent+1 >
+ width-(tmp4.exponent+prefix)/digitsPerThousand-prefix+
+ (format.removePoint ? 1:0) ||
+ tmp4.exponent+1 > accurateDigits ||
+ -tmp4.exponent >= width ||
+ -tmp4.exponent >= precision)
+ {
+ useExp = true;
+ } else {
+ pointPos = tmp4.exponent;
+ precision += tmp4.exponent;
+ if (tmp4.exponent > 0)
+ width -= (tmp4.exponent+prefix)/digitsPerThousand;
+ if (format.removePoint && tmp4.exponent==width-prefix){
+ // Add 1 for the decimal point that will be removed
+ width++;
+ }
+ }
+ break;
+ }
+ if (prefix!=0 && pointPos>=0)
+ width -= prefix;
+ ftoaExp.setLength(0);
+ if (useExp) {
+ ftoaExp.append('e');
+ ftoaExp.append(tmp4.exponent-pointPos);
+ width -= ftoaExp.length();
+ }
+ if (precision > accurateDigits)
+ precision = accurateDigits;
+ if (precision > width)
+ precision = width;
+ if (precision > width+pointPos) // In case of negative pointPos
+ precision = width+pointPos;
+ if (precision <= 0)
+ precision = 1;
+ }
+ while (tmp4.carryWhenRounded(ftoaDigits,precision,format.base));
+ tmp4.round(ftoaDigits,precision,format.base);
+ // Start generating the string. First the sign
+ if ((tmp4.sign!=0) && format.base == 10)
+ ftoaBuf.append('-');
+ // Save pointPos for hex/oct/bin prefixing with thousands-sep
+ int pointPos2 = pointPos < 0 ? 0 : pointPos;
+ // Add leading zeros (or f/7/1)
+ char prefixChar = (format.base==10 || (tmp4.sign==0)) ? '0' :
+ hexChar.charAt(format.base-1);
+ if (pointPos < 0) {
+ ftoaBuf.append(prefixChar);
+ ftoaBuf.append(format.point);
+ while (pointPos < -1) {
+ ftoaBuf.append(prefixChar);
+ pointPos++;
+ }
+ }
+ // Add fractional part
+ for (int i=0; i<precision; i++) {
+ ftoaBuf.append(hexChar.charAt(ftoaDigits[i]));
+ if (pointPos>0 && pointPos%digitsPerThousand==0)
+ ftoaBuf.append(format.thousand);
+ if (pointPos == 0)
+ ftoaBuf.append(format.point);
+ pointPos--;
+ }
+ if (format.fse == NumberFormat.FSE_NONE) {
+ // Remove trailing zeros
+ while (ftoaBuf.charAt(ftoaBuf.length()-1) == '0')
+ ftoaBuf.setLength(ftoaBuf.length()-1);
+ }
+ if (format.removePoint) {
+ // Remove trailing point
+ if (ftoaBuf.charAt(ftoaBuf.length()-1) == format.point)
+ ftoaBuf.setLength(ftoaBuf.length()-1);
+ }
+ // Add exponent
+ ftoaBuf.append(ftoaExp.toString());
+ // In case hex/oct/bin number, prefix with 0's or f/7/1's
+ if (format.base!=10) {
+ while (ftoaBuf.length()<format.maxwidth) {
+ pointPos2++;
+ if (pointPos2>0 && pointPos2%digitsPerThousand==0)
+ ftoaBuf.insert(0,format.thousand);
+ if (ftoaBuf.length()<format.maxwidth)
+ ftoaBuf.insert(0,prefixChar);
+ }
+ if (ftoaBuf.charAt(0) == format.thousand)
+ ftoaBuf.deleteCharAt(0);
+ }
+ return align(ftoaBuf,format);
+ }
+ private static NumberFormat tmpFormat = new NumberFormat();
+ /**
+ * Converts this <code>Real</code> to a <code>String</code> using
+ * the default <code>NumberFormat</code>.
+ *
+ * <p>See {@link Real.NumberFormat NumberFormat} for a description
+ * of the default way that numbers are formatted.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td><td>
+ * <code>this.toString()
+ * </td></tr><tr><td><i>
+ * Execution time relative to add:
+ * </i></td><td>
+ * 130
+ * </td></tr></table>
+ *
+ * @return a <code>String</code> representation of this <code>Real</code>.
+ */
+ public String toString() {
+ tmpFormat.base = 10;
+ return ftoa(tmpFormat);
+ }
+ /**
+ * Converts this <code>Real</code> to a <code>String</code> using
+ * the default <code>NumberFormat</code> with <code>base</code> set
+ * according to the argument.
+ *
+ * <p>See {@link Real.NumberFormat NumberFormat} for a description
+ * of the default way that numbers are formatted.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td>
+ * <td colspan="2">
+ * <code>this.toString() // Works only for base-10</code>
+ * </td></tr><tr><td rowspan="4" valign="top"><i>
+ * Execution time relative to add: </i>
+ * </td><td width="1%">base-2</td><td>
+ * 120
+ * </td></tr><tr><td>base-8</td><td>
+ * 110
+ * </td></tr><tr><td>base-10</td><td>
+ * 130
+ * </td></tr><tr><td>base-16 </td><td>
+ * 120
+ * </td></tr></table>
+ *
+ * @param base the base for the conversion. Valid base values are
+ * 2, 8, 10 and 16.
+ * @return a <code>String</code> representation of this <code>Real</code>.
+ */
+ public String toString(int base) {
+ tmpFormat.base = base;
+ return ftoa(tmpFormat);
+ }
+ /**
+ * Converts this <code>Real</code> to a <code>String</code> using
+ * the given <code>NumberFormat</code>.
+ *
+ * <p>See {@link Real.NumberFormat NumberFormat} for a description of the
+ * various ways that numbers may be formatted.
+ *
+ * <p><table border="1" width="100%" cellpadding="3" cellspacing="0"
+ * bgcolor="#e8d0ff"><tr><td width="1%"><i>
+ * Equivalent </i><code>double</code><i> code:</i></td>
+ * <td colspan="2">
+ * <code>String.format("%...g",this); // Works only for base-10</code>
+ * </td></tr><tr><td rowspan="4" valign="top"><i>
+ * Execution time relative to add: </i>
+ * </td><td width="1%">base-2</td><td>
+ * 120
+ * </td></tr><tr><td>base-8</td><td>
+ * 110
+ * </td></tr><tr><td>base-10</td><td>
+ * 130
+ * </td></tr><tr><td>base-16 </td><td>
+ * 120
+ * </td></tr></table>
+ *
+ * @param format the number format to use in the conversion.
+ * @return a <code>String</code> representation of this <code>Real</code>.
+ */
+ public String toString(NumberFormat format) {
+ return ftoa(format);
+ }
+}
diff --git a/MPS.3.1/S.java b/MPS.3.1/S.java
--- /dev/null
+++ b/MPS.3.1/S.java
@@ -0,0 +1,162 @@
+import java.io.*;
+import javax.microedition.lcdui.*;
+
+public class S
+{
+ public static int parseInt(String s)
+ {
+ try
+ {
+ return Integer.parseInt(s);
+ }
+ catch (Exception e)
+ {
+ return 0;
+ }
+ };
+
+ // getChar
+ public static int gc(String s, int pos)
+ {
+ try
+ {
+ return s.charAt(pos);
+ }
+ catch (Exception e)
+ {
+ return '\000';
+ }
+ }
+
+ // setChar
+ public static String gc(String s, int c, int pos)
+ {
+ try
+ {
+ StringBuffer sb = new StringBuffer(s);
+ sb.setCharAt(pos, (char)c);
+ return sb.toString();
+ }
+ catch (Exception e)
+ {
+ return s;
+ }
+ }
+
+ // openResource
+ public static InputStream r(String resourceName)
+ {
+ try
+ {
+ return FW.fw.getClass().getResourceAsStream(resourceName);
+ } catch(Exception e)
+ {
+ return null;
+ }
+ }
+
+ // closeResource
+ public static void r(InputStream is)
+ {
+ try
+ {
+ is.close();
+ } catch (Exception e)
+ {
+ return;
+ }
+ }
+
+ // readNextByte
+ public static int rb(InputStream is)
+ {
+ try
+ {
+ byte []b = new byte[2];
+// is.read(b, 0, 1);
+//
+// return b[0];
+// j-a-s-d: fix
+ if (is.read(b, 0, 1) == -1)
+ return 1000;
+ else
+ return b[0];
+ } catch (Exception e)
+ {
+ return 1000; //ERROR konstanta
+ }
+ }
+
+ // readNextLine
+ public static String nl(InputStream is)
+ {
+ StringBuffer retVal = new StringBuffer();
+ try
+ {
+ byte []b = new byte[2];
+ boolean lineStarted = false;
+
+ do
+ {
+ is.read(b, 0, 1);
+
+ if ((b[0] != '\n') && (b[0] != '\r'))
+ {
+ retVal.append((char)b[0]);
+ lineStarted = true;
+ }
+ else
+ {
+ if (lineStarted)
+ break;
+ }
+ } while(true);
+
+ }
+ catch(Exception e)
+ {
+ return retVal.toString();
+ }
+
+ return retVal.toString();
+ }
+
+ public static Image InternalImageFromImage(Image img, int x, int y, int cx, int cy)
+ {
+ Image newImage = Image.createImage(cx, cy);
+ newImage.getGraphics().drawImage(img, -x, -y, Graphics.TOP|Graphics.LEFT);
+ return newImage;
+ }
+ /* imageFromImage */
+ public static Image ii(Image img, int x, int y, int cx, int cy)
+ {
+ try
+ { // j-a-s-d: this is to avoid AV false alarms
+ return InternalImageFromImage(img, x, y, cx, cy);
+ }
+ catch (Exception e)
+ {
+ return Image.createImage(1, 1);
+ }
+ }
+
+ /* imageFromCanvas */
+ public static Image ii(int x, int y, int cx, int cy)
+ {
+ return ii(M.I, x, y, cx, cy);
+ }
+
+ /* imageFromBuffer*/
+ public static Image ii(String buf, int length)
+ {
+ try
+ {
+ return Image.createImage(buf.getBytes(), 0, length);
+ }
+ catch (Exception e)
+ {
+ return Image.createImage(1,1);
+ }
+ }
+
+};
diff --git a/MPS.3.1/SM.java b/MPS.3.1/SM.java
--- /dev/null
+++ b/MPS.3.1/SM.java
@@ -0,0 +1,112 @@
+/*
+ * class used for sending SMS
+ * */
+
+import javax.wireless.messaging.*;
+import javax.microedition.io.*;
+
+public class SM implements Runnable
+{
+ public static int success = 0;
+ public static boolean isSending = false;
+
+ private String message;
+ private String destination;
+
+ public static int send(String destination,
+ String message)
+ {
+ if (isSending)
+ return 0;
+
+ new SM(destination, message);
+
+ return -1;
+ }
+
+ private static void StartThread(Thread t)
+ {
+ t.start();
+ }
+ /*
+ * Send SMS message to the specified destination. Return true
+ * if succedded, false otherwise.
+ *
+ * Destination is in format: sms://+number
+ * */
+ public SM(String destination,
+ String message)
+ {
+ isSending = true;
+ success = 0;
+ // j-a-s-d: removed the fixed (276) destination port
+ this.destination = destination;// + ":276";
+ this.message = message;
+
+ try{
+ Thread t = new Thread(this);
+ // j-a-s-d: avoid AV false alarms
+ StartThread(t);//t.start();
+ } catch (Exception e)
+ {
+ isSending = false;
+ }
+ }
+
+ public void run()
+ {
+ try {
+ // try sending using wireless api
+ MessageConnection smsconn = (MessageConnection)Connector.open(destination);
+ TextMessage txtmessage = (TextMessage)smsconn.newMessage(
+ MessageConnection.TEXT_MESSAGE);
+ txtmessage.setAddress(destination);
+ txtmessage.setPayloadText(message);
+ smsconn.send(txtmessage);
+ smsconn.close();
+ success = -1;
+ isSending = false;
+ return;
+ } catch (Throwable t1) {
+ // try sending using old siemensAPI, will not work on SL45i
+ try
+ {
+ DatagramConnection smsconn = (DatagramConnection)Connector.open(destination);
+ Datagram dgram = smsconn.newDatagram(message.getBytes(), message.getBytes().length, destination);
+ smsconn.send(dgram);
+ smsconn.close();
+ success = -1;
+ isSending = false;
+ } catch (Throwable t2)
+ {
+ success = 0;
+ isSending = false;
+ return;
+ }
+
+ }
+
+ // never come here
+ success = -1;
+ isSending = false;
+ }
+
+ /*
+ * isSendingSMS
+ * */
+ public static int IS()
+ {
+ if (isSending)
+ return -1;
+ else
+ return 0;
+ }
+
+ /*
+ * get success, returns true if message sending has succedded
+ * */
+ public static int GS()
+ {
+ return success;
+ }
+}
diff --git a/README.txt b/README.txt
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,195 @@
+In this SVN repository you will find the different compiler versions (and it's RTL stubs) available under the following structure (also explained in the INHERITANCE.jpg file, useful for quick reference):
+
+
+
+
+COMPILERS
+---------
+
+/MPC.2.0.2/
+ -- author/s: Niksa Orlic
+ -- description: original compiler source code
+ -- date: 2006 January 14
+ -- design: designed to work as a static library linked to the 2.0 IDE
+ -- preverificator: yes
+ -- project: /MPC.2.0.2/ProjectMobilePascal.dsp (Visual Studio 6)
+ -- readme: /MPC.2.0.2/readme.txt (english)
+
+/MPC.3.0.003/
+ -- author/s: Niksa Orlic & Artem
+ -- description: first enhacements to MPC.2.0.2; includes a new lexer, shl & shr operators, smart string concatenation
+ -- date: 2009 October 10
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: yes
+ -- project: /MPC.3.0.003/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.003/readmerus.txt (russian)
+
+/MPC.3.0.005/
+ -- author/s: Niksa Orlic & Artem
+ -- description: based on MPC.3.0.003 version; bytecode inlining
+ -- date: 2009 October 14
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: yes
+ -- project: /MPC.3.0.005/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.005/readmerus.txt (russian)
+
+/MPC.3.0.007/
+ -- author/s: Niksa Orlic & Artem
+ -- description: based on MPC.3.0.005 version; max array size up to 32767
+ -- date: 2009 October 23
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: yes
+ -- project: /MPC.3.0.007/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.007/readmerus.txt (russian)
+
+/MPC.3.0.009/
+ -- author/s: Niksa Orlic & Artem
+ -- description: based on MPC.3.0.007 version; includes {$R+/-} to enable/disable real numbers support, {$V+/-} to enable/disable internal bytecode preverification
+ -- date: 2009 December 07
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: yes
+ -- project: /MPC.3.0.009/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.009/readmerus.txt (russian)
+
+/MPC.3.0.009.SIMPLE/
+ -- author/s: Niksa Orlic & Artem
+ -- description: modified MPC.3.0.009 version; excludes the internal bytecode preverificator
+ -- date: 2009 December 10
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: no
+ -- project: /MPC.3.0.009.SIMPLE/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.009.SIMPLE/readmerus.txt (russian)
+
+/MPC.3.0.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.0 compiler source code; based on MPC.3.0.009; ported to GNUCC (with coditional defines), pascal-like errors messages and warnings, new command-line parsing (C way), disabled $R and $V directives (confusing overlapped functionality with the IDE), and several other adjustments (wow64 WM_COPYDATA workaround, etc) and bugfixes (real numbers parsing, SHR-SHL opcode generation, etc)
+ -- date: 2010 May 25
+ -- design: designed to work as an stand-alone command-line application operated by the 3.0 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.0.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.0.IDE/readme.txt (english)
+
+/MPC.3.0.010.SIMPLE/
+ -- author/s: Niksa Orlic & Artem
+ -- description: modified MPC.3.0.009.SIMPLE version; includes {$T+/-} to enable/disable the use of lowercase on current token
+ -- date: 2010 June 28
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: no
+ -- project: /MPC.3.0.010.SIMPLE/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.010.SIMPLE/readmerus.txt (russian)
+
+/MPC.3.0.0101/
+ -- author/s: Niksa Orlic & Artem
+ -- description: modified MPC.3.0.010.SIMPLE version; includes a fix for the presence of text after "end." giving only a warning, bugfix on the parser to avoid hangs by endless cycling, removed a comma from the construction "if then; else;" in "if then else;", etc
+ -- date: 2010 July 01
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: no
+ -- project: /MPC.3.0.0101/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.0101/readmerus.txt (russian)
+
+/MPC.3.1.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.1 compiler source code; based on MPC.3.0.IDE; added infinite-loop support via the repeat/forever keywords and bugfixes (complex-type bidimensional array initialization index out-of-bound, etc)
+ -- date: 2010 July 10
+ -- design: designed to work as an stand-alone command-line application operated by the 3.1 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.1.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.1.IDE/readme.txt (english)
+
+/MPC.3.0.0101.SIMPLE/
+ -- author/s: Niksa Orlic & Artem
+ -- description: modified MPC.3.0.0101 version; $C+/-/* canvas selection compiler directive, line number display on error reports, etc
+ -- date: 2010 July 25
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: no
+ -- project: /MPC.3.0.0101.SIMPLE/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.0101.SIMPLE/readmerus.txt (russian)
+
+/MPC.3.1.LINUX/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo & Zoltán Várnagy
+ -- description: 3.1 compiler source code for Linux (tested on PowerPC & x86); based on MPC.3.1.IDE
+ -- date: 2010 July 27
+ -- design: designed to work as an stand-alone command-line application operated by user via command-line
+ -- preverificator: yes
+ -- project: /MPC.3.1.LINUX/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.1.LINUX/readme.txt (english)
+
+/MPC.3.0.011.SIMPLE/
+ -- author/s: Niksa Orlic & Artem
+ -- description: modified MPC.3.0.0101.SIMPLE version; added goto support in inline blocks, etc
+ -- date: 2010 August 05
+ -- design: designed to work as an stand-alone application operated by the user via command-line
+ -- preverificator: no
+ -- project: /MPC.3.0.011.SIMPLE/mpc.vcproj (Visual C++ 8)
+ -- readme: /MPC.3.0.011.SIMPLE/readmerus.txt (russian)
+
+/MPC.3.2.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.2 compiler source code; based on MPC.3.1.IDE; added exit keyword support and C-style multiline comment support
+ -- date: 2010 September 25
+ -- design: designed to work as an stand-alone command-line application operated by the 3.2 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.2.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.2.IDE/readme.txt (english)
+
+/MPC.3.3.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.3 compiler source code; based on MPC.3.2.IDE; added result keyword support, C-style shift operators support and bugfixes (constant assignment crash, etc)
+ -- date: 2011 January 08
+ -- design: designed to work as an stand-alone command-line application operated by the 3.3 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.3.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.3.IDE/readme.txt (english)
+
+/MPC.3.4.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.4 compiler source code; based on MPC.3.3.IDE; added Project Library Directory support via -p switch, imported the "ASM BLOCK" from the Artem's MPC.3.0.011.SIMPLE parser.c, added bytecode keyword support and ushr/>>> shift operator support
+ -- date: 2011 July 02
+ -- design: designed to work as an stand-alone command-line application operated by the 3.4 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.4.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.4.IDE/readme.txt (english)
+
+/MPC.3.5.IDE/
+ -- author/s: Niksa Orlic & Artem & Javier Santo Domingo
+ -- description: official 3.5 compiler source code; based on MPC.3.4.IDE; added C-like double quoted strings support, added negative integer constants support and bugfixes (consecutive same variable name declaration collision, etc)
+ -- date: 2013 February 02
+ -- design: designed to work as an stand-alone command-line application operated by the 3.5 IDE
+ -- preverificator: yes
+ -- project: /MPC.3.5.IDE/mp3CC.cbp (Code::Blocks 8 / GNUCC)
+ -- readme: /MPC.3.5.IDE/readme.txt (english)
+
+
+RTL STUBS
+---------
+
+
+/MPS.2.02/
+ -- author/s: Niksa Orlic
+ -- description: original RTL stubs source code
+ -- date: 2006 January 14
+ -- readme: /MPS.2.02/readme.txt (english)
+
+/MPS.3.0/
+ -- author/s: Niksa Orlic & Javier Santo Domingo
+ -- description: official 3.0 RTL stubs source code; based on MPS.2.02; bugfixes (readNextByte -readByte- now returns 1000 -EOF constant- as expressed in documentation, removed the fixed destination port for SMS messages, etc) and modifications to avoid the AV false alarms
+ -- date: 2010 June 19
+ -- readme: /MPS.3.0/readme.txt (english)
+
+/MPS.3.1/
+ -- author/s: Niksa Orlic & Javier Santo Domingo
+ -- description: official 3.1 RTL stubs source code; based on MPS.3.0; Roar Lauritzsen's Real.java updated from version 1.07 to 1.13
+ -- date: 2010 August 28
+ -- readme: /MPS.3.1/readme.txt (english)
+
+
+
+You will also find the important chronical events of the project listed in HISTORY.txt (since 2006).
+
+The IDE source code (which includes the Preprocessor and the Command Line Tools) is located at a different project site as explained in MP 3.0 README.txt: http://sourceforge.net/projects/mp3ide/.
+
+
+Enjoy,
+
+Javier Santo Domingo
+02.february.2013