blob: 74f0863c98a0823416920f70c174dd4ef6b61cec [file] [log] [blame]
/*
* 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>");
}
}