package s3.services.simplejit.optimization;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import ovm.core.repository.TypeCodes;
import ovm.util.HashMap;
import ovm.util.HashSet;
import ovm.util.Iterator;

/**
 * A standalone parser for the output written by ResultWriter.
 */
public class SimpleJITRegisterAllocatorResultParser {

    public static void main(String[] args) {
	ResultParser.main(args);
    }

    public static class ResultParser {
	private static class ResultEntry {
	    String algorithm;
	    String method;
	    /* the weighted spill costs, the indices are the register
	     * number */
	    int[] intRegsWSC;
	    int[] refRegsWSC;
	    int[] longRegsWSC;
	    int[] floatRegsWSC;
	    int[] doubleRegsWSC;
	    int[] returnAddressRegsWSC;
	    long allocationTime;
	    ResultEntry(String algorithm,
			String method,
			int[] intr,
			int[] refr,
			int[] longr,
			int[] floatr,
			int[] doubler,
			int[] rar,
			long allocationTime) {
		this.algorithm = algorithm;
		this.method = method;
		intRegsWSC = intr;
		refRegsWSC = refr;
		longRegsWSC = longr;
		floatRegsWSC = floatr;
		doubleRegsWSC = doubler;
		returnAddressRegsWSC = rar;
		this.allocationTime = allocationTime;
	    }
	    long getAllocationTime() {
		return allocationTime;
	    }
	    int[] accumulatedIntRegsWSC() {
		int[] ret = new int[intRegsWSC.length];
		System.arraycopy(intRegsWSC, 0, 
				 ret, 0,
				 intRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] accumulatedRefRegsWSC() {
		int[] ret = new int[refRegsWSC.length];
		System.arraycopy(refRegsWSC, 0, 
				 ret, 0,
				 refRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] accumulatedLongRegsWSC() {
		int[] ret = new int[longRegsWSC.length];
		System.arraycopy(longRegsWSC, 0, 
				 ret, 0,
				 longRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] accumulatedFloatRegsWSC() {
		int[] ret = new int[floatRegsWSC.length];
		System.arraycopy(floatRegsWSC, 0, 
				 ret, 0,
				 floatRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] accumulatedDoubleRegsWSC() {
		int[] ret = new int[doubleRegsWSC.length];
		System.arraycopy(doubleRegsWSC, 0, 
				 ret, 0,
				 doubleRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] accumulatedReturnAddressRegsWSC() {
		int[] ret = new int[returnAddressRegsWSC.length];
		System.arraycopy(returnAddressRegsWSC, 0, 
				 ret, 0,
				 returnAddressRegsWSC.length);
		for(int i = 1; i < ret.length; i++) {
		    ret[i] += ret[i - 1];
		}
		return ret;
	    }
	    int[] reverseAccumulatedIntRegsWSC() {
		int total = 0;
		for(int i = 0; i < intRegsWSC.length; i++)
		    total += intRegsWSC[i];
		int[] accum = accumulatedIntRegsWSC();
		int[] ret = new int[intRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    int[] reverseAccumulatedRefRegsWSC() {
		int total = 0;
		for(int i = 0; i < refRegsWSC.length; i++)
		    total += refRegsWSC[i];
		int[] accum = accumulatedRefRegsWSC();
		int[] ret = new int[refRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    int[] reverseAccumulatedLongRegsWSC() {
		int total = 0;
		for(int i = 0; i < longRegsWSC.length; i++)
		    total += longRegsWSC[i];
		int[] accum = accumulatedLongRegsWSC();
		int[] ret = new int[longRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    int[] reverseAccumulatedFloatRegsWSC() {
		int total = 0;
		for(int i = 0; i < floatRegsWSC.length; i++)
		    total += floatRegsWSC[i];
		int[] accum = accumulatedFloatRegsWSC();
		int[] ret = new int[floatRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    int[] reverseAccumulatedDoubleRegsWSC() {
		int total = 0;
		for(int i = 0; i < doubleRegsWSC.length; i++)
		    total += doubleRegsWSC[i];
		int[] accum = accumulatedDoubleRegsWSC();
		int[] ret = new int[doubleRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    int[] reverseAccumulatedReturnAddressRegsWSC() {
		int total = 0;
		for(int i = 0; i < returnAddressRegsWSC.length; i++)
		    total += returnAddressRegsWSC[i];
		int[] accum = accumulatedReturnAddressRegsWSC();
		int[] ret = new int[returnAddressRegsWSC.length];
		for(int i = 0; i < ret.length; i++) {
		    ret[i] = total - accum[i];
		}
		return ret;
	    }
	    public int hashCode() {
		return method.hashCode();
	    }
	    public boolean equals(Object o) {
		if (o == null 
		    || (! (o instanceof ResultEntry)))
		    return false;
		ResultEntry other = (ResultEntry)o;
		return method.equals(other.method);
	    }
	    public static String toHorizontalString
		(ResultEntry[] entries) {
		if (entries.length <= 0)
		    throw new Error();
		// Check whether all entries have the same method name
		String method = null;
		int intNRegMax = 0;
		int refNRegMax = 0;
		int longNRegMax = 0;
		int floatNRegMax = 0;
		int doubleNRegMax = 0;
		int raNRegMax = 0;
		for(int i = 0; i < entries.length; i++) {
		    if (method != null) {
			if (! method.equals(entries[i].method))
			    throw new Error();
		    } else {
			method = entries[i].method;
		    }
		    int intm = entries[i].intRegsWSC.length;
		    if (intm > intNRegMax)
			intNRegMax = intm;
		    int refm = entries[i].refRegsWSC.length;
		    if (refm > refNRegMax)
			refNRegMax = refm;
		    int longm = entries[i].longRegsWSC.length;
		    if (longm > longNRegMax)
			longNRegMax = longm;
		    int floatm = entries[i].floatRegsWSC.length;
		    if (floatm > floatNRegMax)
			floatNRegMax = floatm;
		    int doublem = entries[i].doubleRegsWSC.length;
		    if (doublem > doubleNRegMax)
			doubleNRegMax = doublem;
		    int ram = entries[i].returnAddressRegsWSC.length;
		    if (ram > raNRegMax)
			raNRegMax = ram;
		}
		String[] intRegList = new String[intNRegMax];
		String[] refRegList = new String[refNRegMax];
		String[] longRegList = new String[longNRegMax];
		String[] floatRegList = new String[floatNRegMax];
		String[] doubleRegList = new String[doubleNRegMax];
		String[] returnAddressRegList = new String[raNRegMax];

		String[] allocationTimeList = new String[entries.length];

		for(int i = 0; i < intRegList.length; i++)
		    intRegList[i] = "";
		for(int i = 0; i < refRegList.length; i++)
		    refRegList[i] = "";
		for(int i = 0; i < longRegList.length; i++)
		    longRegList[i] = "";
		for(int i = 0; i < floatRegList.length; i++)
		    floatRegList[i] = "";
		for(int i = 0; i < doubleRegList.length; i++)
		    doubleRegList[i] = "";
		for(int i = 0; i < returnAddressRegList.length; i++)
		    returnAddressRegList[i] = "";

		String algoLine = "";
		for(int i = 0; i < entries.length; i++) {
		    ResultEntry e = entries[i];
		    allocationTimeList[i] = String.valueOf(e.getAllocationTime());
		    algoLine += e.algorithm + "\t";
		    int[] regsI = e.intRegsWSC;
		    int[] acc_regsI = e.accumulatedIntRegsWSC();
		    for(int j = 0; j < intRegList.length; j++) {
			if (j < regsI.length)
			    intRegList[j] += adjustWidth(regsI[j] + "(" + acc_regsI[j] + ")") + "\t";
			else
			    intRegList[j] += adjustWidth("") + "\t";
		    }
		    int[] regsA = e.refRegsWSC;
		    int[] acc_regsA = e.accumulatedRefRegsWSC();
		    for(int j = 0; j < refRegList.length; j++) {
			if (j < regsA.length)
			    refRegList[j] += adjustWidth(regsA[j] + "(" + acc_regsA[j] + ")") + "\t";
			else
			    refRegList[j] += adjustWidth("") + "\t";
		    }
		    int[] regsJ = e.longRegsWSC;
		    int[] acc_regsJ = e.accumulatedLongRegsWSC();
		    for(int j = 0; j < longRegList.length; j++) {
			if (j < regsJ.length)
			    longRegList[j] += adjustWidth(regsJ[j] + "(" + acc_regsJ[j] + ")") + "\t";
			else
			    longRegList[j] += adjustWidth("") + "\t";
		    }
		    int[] regsF = e.floatRegsWSC;
		    int[] acc_regsF = e.accumulatedFloatRegsWSC();
		    for(int j = 0; j < floatRegList.length; j++) {
			if (j < regsF.length)
			    floatRegList[j] += adjustWidth(regsF[j] + "(" + acc_regsF[j] + ")") + "\t";
			else
			    floatRegList[j] += adjustWidth("") + "\t";
		    }
		    int[] regsD = e.doubleRegsWSC;
		    int[] acc_regsD = e.accumulatedDoubleRegsWSC();
		    for(int j = 0; j < doubleRegList.length; j++) {
			if (j < regsD.length)
			    doubleRegList[j] += adjustWidth(regsD[j] + "(" + acc_regsD[j] + ")") + "\t";
			else
			    doubleRegList[j] += adjustWidth("") + "\t";
		    }
		    int[] regsU = e.returnAddressRegsWSC;
		    int[] acc_regsU = e.accumulatedReturnAddressRegsWSC();
		    for(int j = 0; j < returnAddressRegList.length; j++) {
			if (j < regsU.length)
			    returnAddressRegList[j] += adjustWidth(regsU[j] + "(" + acc_regsU[j] + ")") + "\t";
			else
			    returnAddressRegList[j] += adjustWidth("") + "\t";
		    }
		}
		String intLine = "I\n" + stringArray2String(intRegList);
		String refLine = "A\n" + stringArray2String(refRegList);
		String longLine = "J\n" + stringArray2String(longRegList);
		String floatLine = "F\n" + stringArray2String(floatRegList);
		String doubleLine = "D\n" + stringArray2String(doubleRegList);
		String raLine = "U\n" + stringArray2String(returnAddressRegList);
		String allocationTimeLine = stringArray2StringOneLine(allocationTimeList);

		return method + "\n"
		    + algoLine + "\n"
		    + intLine + refLine + longLine + floatLine 
		    + doubleLine + raLine + "\n\t" + allocationTimeLine;
	    }
	    private static String stringArray2StringOneLine(String[] arr) {
		String ret = "";
		for(int i = 0; i < arr.length; i++)
		    ret += arr[i] + "\t";
		return ret;
	    }
	    private static String stringArray2String(String[] arr) {
		String ret = "";
		for(int i = 0; i < arr.length; i++)
		    ret += i + "\t" + arr[i] + "\n";
		return ret;
	    }
	    private static int WIDTH = 16;
	    private static String adjustWidth(String str) {
		int len = str.length();
		int to_append = WIDTH - len;
		if (to_append >= 0)
		    for(int i = 0; i < to_append; i++)
			str += " ";
		else
		    throw new Error();
		return str;
	    }
	    private static String adjustWidth(String str, int WIDTH) {
		int len = str.length();
		int to_append = WIDTH - len;
		if (to_append >= 0)
		    for(int i = 0; i < to_append; i++)
			str += " ";
		else
		    throw new Error();
		return str;
	    }
	}
	private static class ReachedEndOfStream 
	    extends Exception {
	    ReachedEndOfStream() {
		super();
	    }
	}
	private static BufferedReader result_stream;
	private static HashSet methodSet;

	public static void main(String[] args) {
	    if (args.length == 0) {
		System.err.println
		    ("Usage : java ResultParser file1 file2 ...");
		System.exit(1);
	    }
	    methodSet = new HashSet();
	    ResultParser[] parsers = new ResultParser[args.length];
	    for(int i = 0; i < args.length; i++) {
		String filename = args[i];
		try {
		    result_stream =
			new BufferedReader
			(new FileReader(filename));
		} catch (IOException e) {
		    e.printStackTrace();
		    System.exit(1);
		}
		parsers[i] = new ResultParser(args[i]);
		parsers[i].parse();
	    }
	    for(Iterator it = methodSet.iterator();
		it.hasNext(); ) {
		String m = (String)it.next();
		ResultEntry[] entries = new ResultEntry[args.length];
		for(int i = 0; i < args.length; i++) {
		    entries[i] = (ResultEntry)
			parsers[i].resultMap.get(m);
		    if (entries[i] == null) 
			throw new Error(args[i] + " lacks " + m);
		}
		String oneMethodResult = 
		    ResultEntry.toHorizontalString(entries);
		System.err.println(oneMethodResult);
	    }
	    int intNRegMax = 0;
	    int refNRegMax = 0;
	    int longNRegMax = 0;
	    int floatNRegMax = 0;
	    int doubleNRegMax = 0;
	    int raNRegMax = 0;
	    for(Iterator it = methodSet.iterator();
		it.hasNext(); ) {
		String m = (String)it.next();
		ResultEntry[] entries = new ResultEntry[args.length];
		for(int i = 0; i < args.length; i++) {
		    entries[i] = (ResultEntry)
			parsers[i].resultMap.get(m);
		    if (entries[i] == null) 
			throw new Error(args[i] + " lacks " + m);
		    int nr_I = entries[i].intRegsWSC.length;
		    if (nr_I > intNRegMax) intNRegMax = nr_I;
		    int nr_A = entries[i].refRegsWSC.length;
		    if (nr_A > refNRegMax) refNRegMax = nr_A;
		    int nr_J = entries[i].longRegsWSC.length;
		    if (nr_J > longNRegMax) longNRegMax = nr_J;
		    int nr_F = entries[i].floatRegsWSC.length;
		    if (nr_F > floatNRegMax) floatNRegMax = nr_F;
		    int nr_D = entries[i].doubleRegsWSC.length;
		    if (nr_D > doubleNRegMax) doubleNRegMax = nr_D;
		    int nr_U = entries[i].returnAddressRegsWSC.length;
		    if (nr_U > raNRegMax) raNRegMax = nr_U;
		}
	    }

	    String algoLine = "";
	    for(int i = 0; i < args.length; i++) {
		algoLine += args[i] + "\t\t";
	    }
	    System.err.println("I:\n");
	    System.err.println(algoLine);
	    int[] total_acc_I = new int[args.length];
	    long[] total_allocation_time_I = new long[args.length];
	    for(Iterator it = methodSet.iterator();
		it.hasNext(); ) {
		String m = (String)it.next();
		for(int j = 0; j < args.length; j++) {
		    ResultEntry entry = (ResultEntry)
			parsers[j].resultMap.get(m);
		    total_allocation_time_I[j] += entry.getAllocationTime();
		    int[] acc = entry.accumulatedIntRegsWSC();
		    if (acc.length > 0) {
			total_acc_I[j] += acc[acc.length - 1];
		    }
		}
	    }
	    String allocationTimeLine = "\t";
	    for(int j = 0; j < args.length; j++) {
		allocationTimeLine += total_allocation_time_I[j] + "\t";
	    }
	    System.err.println(allocationTimeLine);

	    for(int i = 0; i < intNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] intRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedIntRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    intRegsWSC[j] += entry.intRegsWSC[i];
			} else {
			    if (acc.length > 0) {
				sum_of_WSC[j] += acc[acc.length - 1];
			    }
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
//		    sumLine += adjustWidth(String.valueOf(total_acc_I[j] - sum_of_WSC[j])) + "\t";
  		    sumLine += adjustWidth(String.valueOf(intRegsWSC[j])) + "\t"
  			+ adjustWidth(String.valueOf(sum_of_WSC[j])) + "\t"
 			+ adjustWidth(String.valueOf(total_acc_I[j] - sum_of_WSC[j])) + "\t"
  			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8) + "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }

	    System.err.println("A:\n");
	    System.err.println(algoLine);
	    for(int i = 0; i < refNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] refRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedRefRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    refRegsWSC[j] += entry.refRegsWSC[i];
			} else {
			    sum_of_WSC[j] += acc[acc.length - 1];
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
		    sumLine += adjustWidth(String.valueOf(refRegsWSC[j])) + "\t"
			+ adjustWidth(String.valueOf(sum_of_WSC[j])) + "\t"
			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8)
			+ "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }

	    System.err.println("J:\n");
	    System.err.println(algoLine);
	    for(int i = 0; i < longNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] longRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedLongRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    longRegsWSC[j] += entry.longRegsWSC[i];
			} else {
			    sum_of_WSC[j] += acc[acc.length - 1];
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
		    sumLine += adjustWidth(String.valueOf(longRegsWSC[j])) + "\t"
			+ adjustWidth(String.valueOf(sum_of_WSC[j]))  + "\t"
			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8)
			+ "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }

	    System.err.println("F:\n");
	    System.err.println(algoLine);
	    for(int i = 0; i < floatNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] floatRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedFloatRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    floatRegsWSC[j] += entry.floatRegsWSC[i];
			} else {
			    sum_of_WSC[j] += acc[acc.length - 1];
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
		    sumLine += adjustWidth(String.valueOf(floatRegsWSC[j])) + "\t"
			+ adjustWidth(String.valueOf(sum_of_WSC[j]))  + "\t"
			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8)
			+ "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }

	    System.err.println("D:\n");
	    System.err.println(algoLine);
	    for(int i = 0; i < doubleNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] doubleRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    ResultEntry[] entries = new ResultEntry[args.length];
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedDoubleRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    doubleRegsWSC[j] += entry.doubleRegsWSC[i];
			} else {
			    sum_of_WSC[j] += acc[acc.length - 1];
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
		    sumLine += adjustWidth(String.valueOf(doubleRegsWSC[j])) + "\t"
			+ adjustWidth(String.valueOf(sum_of_WSC[j]))  + "\t"
			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8)
			+ "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }

	    System.err.println("U:\n");
	    System.err.println(algoLine);
	    for(int i = 0; i < raNRegMax; i++) {
		int[] sum_of_WSC = new int[args.length];
		int[] nmethods_that_need_i_registers = new int[args.length];
		int[] returnAddressRegsWSC = new int[args.length];
		for(Iterator it = methodSet.iterator();
		    it.hasNext(); ) {
		    String m = (String)it.next();
		    for(int j = 0; j < args.length; j++) {
			ResultEntry entry = (ResultEntry)
			    parsers[j].resultMap.get(m);
			int[] acc = entry.accumulatedReturnAddressRegsWSC();
			if (i < acc.length) {
			    sum_of_WSC[j] += acc[i];
			    nmethods_that_need_i_registers[j]++;
			    returnAddressRegsWSC[j] += entry.returnAddressRegsWSC[i];
			} else {
			    sum_of_WSC[j] += acc[acc.length - 1];
			}
		    }
		}
		String sumLine = "";
		for(int j = 0; j < args.length; j++) {
		    sumLine += adjustWidth(String.valueOf(returnAddressRegsWSC[j])) + "\t"
			+ adjustWidth(String.valueOf(sum_of_WSC[j]))  + "\t"
			+ adjustWidth("" + nmethods_that_need_i_registers[j], 8)
			+ "\t";
		}
		System.err.println(i + "\t" + sumLine);
	    }
	}

	private static int WIDTH = 10;
	private static String adjustWidth(String str) {
	    int len = str.length();
	    int to_append = WIDTH - len;
	    if (to_append >= 0)
		for(int i = 0; i < to_append; i++)
		    str += " ";
	    else
		throw new Error();
	    return str;
	}
	private static String adjustWidth(String str, int WIDTH) {
	    int len = str.length();
	    int to_append = WIDTH - len;
	    if (to_append >= 0)
		for(int i = 0; i < to_append; i++)
		    str += " ";
	    else
		throw new Error();
	    return str;
	}

	private HashMap resultMap;
	private String algorithm;
	private ResultParser(String algorithm) {
	    resultMap = new HashMap();
	    this.algorithm = algorithm;
	}
	private void parse() {
	    while (true) {
		try {
		    ResultEntry entry = parseOneEntry(algorithm);
		    resultMap.put(entry.method, entry);
		    methodSet.add(entry.method);
		} catch (ReachedEndOfStream e) {
		    break;
		} catch (IOException e) {
		    e.printStackTrace();
		    System.exit(1);
		}
	    }
	}
	private ResultEntry parseOneEntry(String algorithm) 
	    throws ReachedEndOfStream, IOException {
	    String typeContext = checkEnd(result_stream.readLine()).trim();
	    String method = checkNull(result_stream.readLine()).trim();
	    int[] intRegsWSC = parseOneRegSet(TypeCodes.INT);
	    int[] refRegsWSC = parseOneRegSet(TypeCodes.REFERENCE);
	    int[] longRegsWSC = parseOneRegSet(TypeCodes.LONG);
	    int[] floatRegsWSC = parseOneRegSet(TypeCodes.FLOAT);
	    int[] doubleRegsWSC = parseOneRegSet(TypeCodes.DOUBLE);
	    int[] raRegs = parseOneRegSet(TypeCodes.RETURNADDRESS);
	    result_stream.readLine();
	    long allocationTime = parseLong();
	    result_stream.readLine();
	    return new ResultEntry(algorithm,
				   typeContext + " : " + method,
				   intRegsWSC,
				   refRegsWSC,
				   longRegsWSC,
				   floatRegsWSC,
				   doubleRegsWSC,
				   raRegs,
				   allocationTime);
	}

	private long parseLong() {
	    try {
		return Long.parseLong(checkNull(result_stream.readLine()).trim());
	    } catch (Throwable t) {
		t.printStackTrace();
		System.exit(1);
	    }
	    return 0L;
	}

	private int[] parseOneRegSet(char typeCode) {
	    try {
		String typeCodeString = String.valueOf(typeCode);
		String tc = checkNull(result_stream.readLine()).trim();
		if (! tc.equals(typeCodeString)) {
		    System.err.println("[" + tc + "]");
		    throw new Error(tc + " != " + typeCodeString + "\n"
				    + "tc.length = " + tc.length() + " "
				    + "typeCodeString.length = " + typeCodeString.length());
		}
		int nreg = Integer
		    .parseInt(checkNull(result_stream.readLine()).trim());
		int[] regs = new int[nreg];
		for(int i = 0; i < nreg; i++) {
		    regs[i] = Integer
			.parseInt(checkNull(result_stream.readLine()).trim());
		}
		return regs;
	    } catch (Throwable t) {
		t.printStackTrace();
		System.exit(1);
	    }
	    return null;
	}
	private String checkEnd(String s) 
	    throws ReachedEndOfStream {
	    if (s == null)
		throw new ReachedEndOfStream();
	    return s;
	}
	private String checkNull(String s) {
	    if (s == null)
		throw new Error();
	    return s;
	}
    }
}
