blob: cb66a6c09c9ce27a72be49bb7bcceb258b21c05e [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.common;
import java.util.ArrayList;
/**
* A C or C++ method from a piece of source code. The method has a signature and
* a body (the bit between the braces).
*/
public class MethodPart extends FilePart {
private Signature signature;
private String body;
MethodPart(String s, Signature signature, String body) {
super(s, METHOD);
this.signature = signature;
this.body = body;
}
public Signature getSignature() {
return signature;
}
public String getOriginalSignature() {
return signature.getOriginal();
}
/**
* Returns the method body as code snippets, each ending with a place
* where a trace statement belongs. The end of the first code snippet is
* where the entry trace should go. The end of every other snippet is
* a return from the method.
*/
public BodyPart[] getBodyParts() throws ParsingException {
String b = body; // Don't alter field member
if (b.startsWith("{"))
b = b.substring(1);
// Add in trace exit at all the return statements in the method.
ArrayList al = new ArrayList();
int idxR = Utils.indexOf(b, "return");
int idxC = Utils.indexOf(b, "catch");
while (-1 != idxR || -1 != idxC) {
if (-1 == idxC || (-1 != idxR && idxR < idxC)) {
String frag = b.substring(0, idxR);
String rest = b.substring(idxR + "return".length());
int semicolon = Utils.indexOf(rest, ';');
if (-1==semicolon) Utils.rude("Missing semicolon in "+signature);
String retVal = rest.substring(0, semicolon);
BodyPart bp = new BodyPart(frag, retVal);
al.add(bp);
b = b.substring(idxR + "return".length() + retVal.length() + 1);
} else {
String frag = b.substring(0, idxC);
String rest = b.substring(idxC);
int brace = Utils.indexOf(rest, "{");
if (-1==brace) Utils.rude("Missing open brace in "+signature);
Signature signature = new Signature(rest.substring(0,brace));
frag = frag + rest.substring(0,brace+1);
BodyPart bp = new BodyPart(frag, signature.getParameters()[0]);
al.add(bp);
b = rest.substring(brace+1);
}
idxR = Utils.indexOf(b, "return");
idxC = Utils.indexOf(b, "catch");
}
// Add in trace exit before the last } if there are no returns in
// the method or there is code after the last return and the method
// returns void.
// int f1(){try{return f2();}catch(Exception& e){throw;}}
// has code after the last return but having a traceexit before the
// last brace wouldn't compile since the method returns an int. We
// cope with this by only adding in a traceexit before the last brace
// if the method returns void. That may mean we add in an unreachable
// traceexit which may give a compiler warning, but that should be
// benign.
//
// TODO: Not quite good enough for
// void f(int a){if(a){printf("a");}else{printf("!a");return;}}
// as a trace exit is needed before the last } in case a>0 but
// void f(int a){if(a){printf("a");return;}else{printf("!a");return;}}
// would give compiler warnings about unreachable code if a trace
// exit is added before the last brace. This could be tricky to fix.
if ((0 == al.size() || -1 != Utils.indexOf(b, ';'))
&& null == signature.getReturnType().getType()) {
int last = b.lastIndexOf('}');
if (-1==last) Utils.rude("Missing end brace in "+signature);
String b2 = b.substring(0, last);
al.add(new BodyPart(b2));
b = b.substring(last);
}
// The final body part is the last }
al.add(new BodyPart(b));
BodyPart[] bps = new BodyPart[al.size()];
System.arraycopy(al.toArray(), 0, bps, 0, al.size());
return bps;
}
}