// Copyright (c) Corporation for National Research Initiatives
package org.python.compiler;
import java.util.*;
import java.io.*;
class Bytes
{
public byte[] data;
Bytes(ByteArrayOutputStream data) {
this.data = data.toByteArray();
}
public boolean equals(Object o) {
if (o instanceof Bytes) {
byte[] odata = ((Bytes)o).data;
int n = data.length;
if (odata.length != n)
return false;
for (int i=0; i<n; i++) {
if (data[i] != odata[i])
return false;
}
return true;
}
return false;
}
public int hashCode() {
int h = 0xa538;
int n = data.length;
for (int i=0; i<n; i++)
h = h ^ data[i];
return h;
}
}
public class ConstantPool
{
Hashtable constants;
int index;
DataOutputStream tdata;
ByteArrayOutputStream pool, tarray;
int[] sizes;
public ConstantPool() {
constants = new Hashtable();
index = 0;
pool = new ByteArrayOutputStream();
tarray = new ByteArrayOutputStream();
tdata = new DataOutputStream(tarray);
sizes = new int[256];
}
public void write(DataOutputStream stream) throws IOException {
stream.writeShort(index+1);
stream.write(pool.toByteArray());
}
public int addConstant(int slots) throws IOException {
//tarray.flush();
//byte[] data = tarray.toByteArray();
Bytes data = new Bytes(tarray);
tarray.reset();
Integer i = (Integer)constants.get(data);
if (i == null) {
pool.write(data.data);
i = new Integer(index);
constants.put(data, i);
if (index+1 >= sizes.length) {
int[] new_sizes = new int[sizes.length*2];
System.arraycopy(sizes, 0, new_sizes, 0, sizes.length);
sizes = new_sizes;
}
sizes[index+1] = slots;
index += slots;
}
//System.out.print("Constant: ");
//for(int j=0; j<data.length; j++)
// System.out.print(Integer.toString(data[j])+", ");
//System.out.println("");
return i.intValue()+1;
}
public int UTF8(String s) throws IOException {
tdata.writeByte(1);
tdata.writeUTF(s);
return addConstant(1);
}
public int Class(String s) throws IOException {
int c = UTF8(s);
tdata.writeByte(7);
tdata.writeShort(c);
return addConstant(1);
}
public int Fieldref(String c, String name, String type)
throws IOException
{
int ic = Class(c);
int nt = NameAndType(name, type);
tdata.writeByte(9);
tdata.writeShort(ic);
tdata.writeShort(nt);
int size = 1;
if (type.equals("D") || type.equals("J"))
size = 2;
int index = addConstant(1);
sizes[index] = size;
//System.out.println("field: "+c+", "+name+", "+type+": "+index);
return index;
}
public static int sigSize(String sig, boolean includeReturn) {
int stack = 0;
int i = 0;
char[] c = sig.toCharArray();
int n = c.length;
boolean ret=false;
boolean array=false;
while (++i<n) {
switch (c[i]) {
case ')':
if (!includeReturn)
return stack;
ret=true;
continue;
case '[':
array=true;
continue;
case 'V':
continue;
case 'D':
case 'J':
if (array) {
if (ret) stack += 1;
else stack -=1;
array = false;
} else {
if (ret) stack += 2;
else stack -=2;
}
break;
case 'L':
while (c[++i] != ';') {;}
default:
if (ret) stack++;
else stack--;
array = false;
}
}
return stack;
}
public int Methodref(String c, String name, String type)
throws IOException
{
int ic = Class(c);
int nt = NameAndType(name, type);
tdata.writeByte(10);
tdata.writeShort(ic);
tdata.writeShort(nt);
int index = addConstant(1);
sizes[index] = sigSize(type, true);
//System.out.println("method: "+c+", "+name+", "+type+": "+index);
return index;
}
public int InterfaceMethodref(String c, String name, String type)
throws IOException
{
int ic = Class(c);
int nt = NameAndType(name, type);
tdata.writeByte(11);
tdata.writeShort(ic);
tdata.writeShort(nt);
int index = addConstant(1);
sizes[index] = sigSize(type, true);
return index;
}
public int String(String s) throws IOException {
int i = UTF8(s);
tdata.writeByte(8);
tdata.writeShort(i);
return addConstant(1);
}
public int Integer(int i) throws IOException {
tdata.writeByte(3);
tdata.writeInt(i);
return addConstant(1);
}
public int Float(float f) throws IOException {
tdata.writeByte(4);
tdata.writeFloat(f);
return addConstant(1);
}
public int Long(long l) throws IOException {
tdata.writeByte(5);
tdata.writeLong(l);
return addConstant(2);
}
public int Double(double d) throws IOException {
tdata.writeByte(6);
tdata.writeDouble(d);
return addConstant(2);
}
public int NameAndType(String name, String type) throws IOException {
int n = UTF8(name);
int t = UTF8(type);
tdata.writeByte(12);
tdata.writeShort(n);
tdata.writeShort(t);
return addConstant(1);
}
public static void main(String[] args) throws Exception {
ConstantPool cp = new ConstantPool();
System.out.println("c: "+cp.Class("org/python/core/PyString"));
System.out.println("c: "+cp.Class("org/python/core/PyString"));
for (int i=0; i<args.length; i++)
System.out.println(args[i]+": "+sigSize(args[i], true));
}
}