import java.io.*;
import java.lang.*;

/**
 * 
 */
public class PreprocessedProgram {

	
	/**
	 *
	 */
	public PreprocessedProgram(String[] source) {
		new PreprocessedProgram(source, false);
	}


	/**
	 *
	 */
	public PreprocessedProgram(String[] source, boolean Info) {
		int i, j, k, l, m, n, o, org = 0, Offset = 0, line = 0;
		String SourceTmp[];
		boolean eof = false;
		Size = 0;
		ArrayOfVariable = new String[1024];		// nbre of symbol <= 1024
		ArrayOfVarAddress = new int[1024];		//to each Symbol equal an 'equivalence' ! i.e: an Offset or a Value.
		SourceTmp = new String[1024];
		ArrayOfLabel = new String[1024];		// nbre of symbol <= 1024
		ArrayOfLabelOffset = new int[1024];	
		ArrayOfEQU = new String[1024];			// nbre of symbol <= 1024
		ArrayOfEQUValue = new int[1024];
		VarSize = 0;
		LabelSize = 0;
		EQUSize = 0;
		String s = source[line];	
			
		try {	
	//	for(m = 0; m < source.length; m++) {
			while(!eof) {
				line++;
				if((s.trim()).indexOf(';') != 0 && (s.trim()).length() != 0) {

					i = s.indexOf(';'); 
					if((i != -1) && (s.length() != 0))
						s = s.substring(0,i);
					
						o = (s.toLowerCase()).indexOf("org");
						
						if(o != -1)
							org =  FindSymbol( (s.substring(o+3,s.length())).trim(), ArrayOfEQU, ArrayOfEQUValue);		
					
					if((s.indexOf(' ') != 0) && (s.indexOf('\t') != 0)) {		// it is a label or an EQU or a VARiable
						s = s.trim();
						j = s.indexOf(':');
						l = (s.toLowerCase()).indexOf("equ");
						n = (s.toLowerCase()).indexOf("var");
					
			
						if(j != -1) {								//it is a label
							ArrayOfLabelOffset[LabelSize] = org;
							
							ArrayOfLabel[LabelSize] = s.substring(0,j);
							LabelSize++;
						}
						else 	
							if(l != -1) {							// it is an EQU
								ArrayOfEQU[EQUSize] = (s.substring(0,l)).trim();
								ArrayOfEQUValue[EQUSize] = (Integer.decode((s.substring(l+3,s.length())).trim())).intValue();
								EQUSize++;
							}		
						else
							if(n != -1) {							// it is a VARiable
								ArrayOfVariable[VarSize] = (s.substring(0,n)).trim();
								ArrayOfVarAddress[VarSize] = (Integer.decode((s.substring(n+3,s.length())).trim())).intValue();
								VarSize++;
							}
					}
					else {
						SourceTmp[Size] = s.trim();
						if(o == -1)
								org++;
							Size++;
						
					}
				}
			s = source[line];
			}
		}
		catch (ArrayIndexOutOfBoundsException e) {};	
				
		Source = new String[Size];
		for(i = 0 ; i < Size ; i++)
			Source[i] = SourceTmp[i];
	
		if(Info) {	
				LabelSymb = new SymbolicInfos_std[LabelSize];
			for(i = 0 ; i < LabelSize ; i++)
					LabelSymb[i] = new SymbolicInfos_std(ArrayOfLabel[i], ArrayOfLabelOffset[i]);
					
				VariableSymb = new SymbolicInfos_std[VarSize];
			for(i = 0 ; i < VarSize ; i++)
					VariableSymb[i] = new SymbolicInfos_std(ArrayOfVariable[i], ArrayOfVarAddress[i]);
		}
		
	}


	public SymbolicInfos[] getLabelComplete() {
		return LabelSymb;	
	}	
	
	public SymbolicInfos[] getVariableComplete() {
		return VariableSymb;	
	}	
	

	public String[] PreprocessedSource() {
		return Source;
	}

	
	public String[] Variables() {
		return ArrayOfVariable;
	}

	public String[] Labels() {
		return ArrayOfLabel;
	}

	public String[] EQUs() {
		return ArrayOfEQU;
	}


	public int[] Addresses() {
		return ArrayOfVarAddress;
	}

	public int[] Offsets() {
		return ArrayOfLabelOffset;
	}

	public int[] EquValues() {
		return ArrayOfEQUValue;
	}


	public int Size() {
		return Size;
	}

	public int VarSize() {
		return VarSize;
	}

	public int LabelSize() {
		return LabelSize;
	}

	public int EQUSize() {
		return EQUSize;
	}


	protected static int FindSymbol(String Src, String[] Var, int[] Equ) {
		Integer j;
		try {
			j = Integer.decode(Src);
			return	j.intValue(); 
		}
		catch (NumberFormatException e) {
			int i;
			for(i = 0; i < Var.length; i++) {
				if(Src.compareTo(Var[i]) == 0)
					return Equ[i]; 
			}		
			return	0x666;		// not found <=> 0x666  bof....
		
		}
	}

	


	protected String Source[], ArrayOfVariable[], ArrayOfLabel[], ArrayOfEQU[];
	protected int Size, VarSize, LabelSize, EQUSize, ArrayOfVarAddress[],  ArrayOfLabelOffset[], ArrayOfEQUValue[];
	protected SymbolicInfos LabelSymb[], VariableSymb[];
}