/*
 *   Copyright 2003-2004 The Apache Software Foundation.
// (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.apache.axis.tools.trace;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.axis.tools.common.BodyPart;
import org.apache.axis.tools.common.CParsingTool;
import org.apache.axis.tools.common.Configuration;
import org.apache.axis.tools.common.DirectoryTree;
import org.apache.axis.tools.common.FileActor;
import org.apache.axis.tools.common.FilePart;
import org.apache.axis.tools.common.InputCppSourceCode;
import org.apache.axis.tools.common.MethodPart;
import org.apache.axis.tools.common.ParsingException;
import org.apache.axis.tools.common.Utils;

/**
 * This class is a tool that adds entry/exit/catch trace to C and C++ 
 * source code. It contains a main program:-
 * 
 * usage: Java TraceInstrumentor -source <dir> -target <dir> -include <dir>
 */
public class TraceInstrumentor extends CParsingTool implements FileActor {
	private static Set cExtensions =
		new HashSet(Arrays.asList(new Object[] { "c", "cpp", "h", "hpp" }));

	private TraceInstrumentor(String[] args) throws Exception {
		super(args);
	}

	/**
	 * This method is called by the DirectoryTree with two files: the
	 * input (source) file and the output (target) file. This method parses 
	 * the source file and writes out the target files with trace in it.
	 * The depth is how deep in the source directory tree we are. Files are
	 * excluded if they are listed in the configuration because they shouldn't
	 * have trace added to them.
	 */
	public void actOnFile(File source, File target, int depth)
		throws Exception {
		String sourceName = source.getName();
		int dot = sourceName.lastIndexOf(".");
		String ext = new String();
		if (-1 != dot)
			ext = sourceName.substring(dot + 1);

		String targetName =
			DirectoryTree.maybeAppendSeparator(target.toString());
		File outputFile = new File(targetName + sourceName);

		if (cExtensions.contains(ext)
			&& !Configuration.fileExcluded(sourceName)) {
			Utils.outputDebugString("parsing " + source + "...");

			// create a tracer to the output file 
			Tracer output =
				new Tracer(new FileWriter(outputFile, false), depth, headers);

			// OK, now we have the output file let's read in the input file !
			FileReader fr = new FileReader(source);
			BufferedReader inputFile = new BufferedReader(fr);

			try {
				parseFile(
					new InputCppSourceCode(inputFile, source.getName()),
					output);
			} catch (ParsingException pe) {
				failed = true;
			}

			output.flush();
			output.close();
			inputFile.close();
		} else {
			System.out.println("excluding file " + source);
			FileInputStream fis = new FileInputStream(source);
			FileOutputStream fos = new FileOutputStream(outputFile);
			int b = fis.read();
			while (-1 != b) {
				fos.write(b);
				b = fis.read();
			}
		}
	}

	/**
	 * Parses the given file and adds trace to it, placing the newly traced code 
	 * into the outputfile
	 * 
	 * @param inputFile the input file reader
	 * @param outputFile the output file writer
	 */
	private void parseFile(InputCppSourceCode inputFile, Tracer outputFile)
		throws Exception {
		Iterator it = inputFile.getPartIterator();
		while (it.hasNext()) {
			FilePart fp = (FilePart) (it.next());
			if (fp.getType() == FilePart.METHOD) {
				MethodPart mp = (MethodPart) fp;
				outputFile.writeTrace(mp.getOriginalSignature() + "{");
				outputFile.traceEntry(mp.getSignature());
				BodyPart[] bps = mp.getBodyParts();

				int returnCount = 0,
					catchCount = 0,
					returnIndex = 0,
					catchIndex = 0;
				for (int i = 0; i < bps.length - 1; i++)
					if (bps[i].isReturn())
						returnCount++;
				for (int i = 0; i < bps.length - 1; i++)
					if (bps[i].isCatch())
						catchCount++;

				for (int i = 0; i < bps.length; i++) {
					outputFile.writeTrace(bps[i].getCodeFragment());
					if (bps[i].isReturn()) {
						if (returnCount > 1)
							returnIndex++;
						outputFile.traceExit(
							bps[i].getReturnValue(),
							returnIndex);
					} else if (bps[i].isCatch()) {
						if (catchCount > 1)
							catchIndex++;
						outputFile.traceCatch(
							bps[i].getCaughtValue(),
							catchIndex);
					} else if (i < bps.length - 1) {
						if (returnCount > 1)
							returnIndex++;
						outputFile.traceExit(returnIndex);
					}
				}
			} else {
				outputFile.writeTrace(fp.toString());
			}
		}
	}

	public static void main(String[] args) {
		boolean failed = false;
		try {
			TraceInstrumentor ti = new TraceInstrumentor(args);
			File source = ti.checkFile("-source");
			File target = ti.maybeCreateDirectory("-target");
			ti.headers = ti.preparseHeaders("-include");

			DirectoryTree tree = new DirectoryTree(ti, null);
			tree.walkTree(source, target, 0);
			failed = ti.failed;
		} catch (Exception exception) {
			exception.printStackTrace();
			failed = true;
		}

		if (failed) {
			Utils.outputDebugString("Finished! (but encountered problems)");
			System.exit(-2);
		} 
		Utils.outputDebugString("Finished!");
	}

	protected void printUsage() {
		System.out.println(
			"usage: Java TraceInstrumentor "
				+ "-config <file> -source <dir> "
				+ "-target <dir> -include <dir>");
	}

}
