78ec862f1a 2011-02-23 kinaba: package tangentz; 78ec862f1a 2011-02-23 kinaba: import java.util.HashMap; 78ec862f1a 2011-02-23 kinaba: import java.util.Map; 78ec862f1a 2011-02-23 kinaba: import com.topcoder.client.contestant.ProblemComponentModel; 78ec862f1a 2011-02-23 kinaba: import com.topcoder.shared.language.Language; 78ec862f1a 2011-02-23 kinaba: import com.topcoder.shared.problem.*; f19d33f1b6 2011-02-23 kinaba: f19d33f1b6 2011-02-23 kinaba: // TZTester plugin f19d33f1b6 2011-02-23 kinaba: // http://www.topcoder.com/contest/classes/TZTester/TZTester.html f19d33f1b6 2011-02-23 kinaba: // customized by cafelier and naoya_t f19d33f1b6 2011-02-23 kinaba: f19d33f1b6 2011-02-23 kinaba: f19d33f1b6 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * @author TangentZ 78ec862f1a 2011-02-23 kinaba: * 78ec862f1a 2011-02-23 kinaba: * This tester class is for C++ only. It is based on PopsProcessor which is written for Java. 78ec862f1a 2011-02-23 kinaba: * It reads in all the given examples for a problem and generates the equivalent C++ code 78ec862f1a 2011-02-23 kinaba: * to test all the cases. The accumulated running time is 8 seconds, but it is easy to 78ec862f1a 2011-02-23 kinaba: * selectively run a specific case only. 78ec862f1a 2011-02-23 kinaba: * 78ec862f1a 2011-02-23 kinaba: * This tester will define three tags that can be embedded within PopsEdit/FileEdit code template: 78ec862f1a 2011-02-23 kinaba: * $WRITERCODE$ - place holder for writer code - will be blank if none found 78ec862f1a 2011-02-23 kinaba: * $PROBLEM$ - place holder for problem description as plain text 78ec862f1a 2011-02-23 kinaba: * // $RUNTEST$ - place holder for where to put the code that starts the test 78ec862f1a 2011-02-23 kinaba: * $TESTCODE$ - place holder for where to put the test code 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: public class TZTester 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // Map used to store my tags 78ec862f1a 2011-02-23 kinaba: private HashMap<String,String> m_Tags = new HashMap<String,String>(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Constants 78ec862f1a 2011-02-23 kinaba: private static final String k_WRITERCODE = "$WRITERCODE$"; 78ec862f1a 2011-02-23 kinaba: private static final String k_PROBLEM = "$PROBLEM$"; 78ec862f1a 2011-02-23 kinaba: private static final String k_RUNTEST = "$RUNTEST$"; 78ec862f1a 2011-02-23 kinaba: private static final String k_TESTCODE = "$TESTCODE$"; 78ec862f1a 2011-02-23 kinaba: private static final String k_VERSION = "\n// Powered by TZTester 1.01 [25-Feb-2003] : <cafelier&naoya_t>-custom"; 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Cut tags 78ec862f1a 2011-02-23 kinaba: private static final String k_BEGINCUT = "// BEGIN CUT HERE"; 78ec862f1a 2011-02-23 kinaba: private static final String k_ENDCUT = "// END CUT HERE"; 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Problem-related variables 78ec862f1a 2011-02-23 kinaba: private ProblemComponentModel m_Problem = null; 78ec862f1a 2011-02-23 kinaba: private Language m_Language = null; 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * PreProcess the source code 78ec862f1a 2011-02-23 kinaba: * 78ec862f1a 2011-02-23 kinaba: * First determines if it is saved code, writer code, or nothing and stores it in $WRITERCODE$ tag 78ec862f1a 2011-02-23 kinaba: * Secondly builds a main method with default test cases 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: public String preProcess(String Source, ProblemComponentModel Problem, Language Lang, Renderer Render) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // Set defaults for the tags in case we exit out early 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_WRITERCODE, ""); 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_PROBLEM, ""); 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_RUNTEST, "// *** WARNING *** $RUNTEST$ is not supported by this customized TZTester."); 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_TESTCODE, ""); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // If there is source and the source is NOT equal to the default solution, return it 78ec862f1a 2011-02-23 kinaba: if( Source.length()>0 && !Source.equals(Problem.getDefaultSolution()) ) 78ec862f1a 2011-02-23 kinaba: return Source; 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Check to see if the component has any signature 78ec862f1a 2011-02-23 kinaba: if( !Problem.hasSignature() ) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_TESTCODE, "// *** WARNING *** Problem has no signature defined for it"); 78ec862f1a 2011-02-23 kinaba: return ""; 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Get the test cases 78ec862f1a 2011-02-23 kinaba: TestCase[] TestCases = Problem.getTestCases(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Check to see if test cases are defined 78ec862f1a 2011-02-23 kinaba: if( TestCases==null || TestCases.length==0 ) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_TESTCODE, "// *** WARNING *** No test cases defined for this problem"); 78ec862f1a 2011-02-23 kinaba: return ""; 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Re-initialize the tags 78ec862f1a 2011-02-23 kinaba: m_Tags.clear(); 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_WRITERCODE, Problem.getDefaultSolution()); 78ec862f1a 2011-02-23 kinaba: try { m_Tags.put(k_PROBLEM, Render.toHTML(m_Language)); } catch (Exception Ex) { } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: m_Problem = Problem; 78ec862f1a 2011-02-23 kinaba: m_Language = Lang; 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate the test cases 78ec862f1a 2011-02-23 kinaba: generate_test_code(); 78ec862f1a 2011-02-23 kinaba: return ""; 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will cut the test methods above out 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: public String postProcess(String Source, Language Lang) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // Insert a version string 78ec862f1a 2011-02-23 kinaba: return Source + k_VERSION; 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will return my tags. This method is ALWAYS called after preProcess() 78ec862f1a 2011-02-23 kinaba: * 78ec862f1a 2011-02-23 kinaba: * @return a map of my tags 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: public Map getUserDefinedTags() 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: return m_Tags; 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will generate the code for the test cases. 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: private void generate_test_code() 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: DataType[] ParamTypes = m_Problem.getParamTypes(); 78ec862f1a 2011-02-23 kinaba: DataType ReturnType = m_Problem.getReturnType(); 78ec862f1a 2011-02-23 kinaba: TestCase[] Cases = m_Problem.getTestCases(); 78ec862f1a 2011-02-23 kinaba: StringBuffer Code = new StringBuffer(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // <<thanks to naoya_t>> Generate the timer function 78ec862f1a 2011-02-23 kinaba: Code.append("#include <ctime>\n"); 78ec862f1a 2011-02-23 kinaba: Code.append("double start_time; string timer()\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" { ostringstream os; os << \" (\" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << \" msec)\"; return os.str(); }\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate the vector output function 78ec862f1a 2011-02-23 kinaba: Code.append("template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" { os << \"{ \";\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" os << \'\\\"\' << *it << \'\\\"\' << (it+1==v.end() ? \"\" : \", \"); os << \" }\"; return os; }\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate the verification function 78ec862f1a 2011-02-23 kinaba: generate_verification_code(Code, ReturnType); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : new test code template 78ec862f1a 2011-02-23 kinaba: Code.append("#define CASE(N) {cerr << \"Test Case #\" << N << \"...\" << flush; start_time=clock();\n"); 78ec862f1a 2011-02-23 kinaba: Code.append("#define END "); 78ec862f1a 2011-02-23 kinaba: generate_verifier_call(Code, ParamTypes, ReturnType, Cases[0]); 78ec862f1a 2011-02-23 kinaba: Code.append("}\n"); 78ec862f1a 2011-02-23 kinaba: Code.append("int main(){\n\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate the individual test cases 78ec862f1a 2011-02-23 kinaba: for(int i=0; i<Cases.length; ++i) 78ec862f1a 2011-02-23 kinaba: generate_test_case(i, Code, ParamTypes, ReturnType, Cases[i]); 78ec862f1a 2011-02-23 kinaba: for(int i=0; i<2; ++i) 78ec862f1a 2011-02-23 kinaba: generate_blank_test_case(Cases.length+i, Code, ParamTypes, ReturnType, Cases[0]); 78ec862f1a 2011-02-23 kinaba: Code.append("\n}\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Insert the cut tags 78ec862f1a 2011-02-23 kinaba: Code.insert(0, k_BEGINCUT+"\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(k_ENDCUT); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Replace $TESTCODE$ 78ec862f1a 2011-02-23 kinaba: m_Tags.put(k_TESTCODE, Code.toString()); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will generate the code for verifying test cases. 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: private void generate_verification_code(StringBuffer Code, DataType ReturnType) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: String TypeString = ReturnType.getDescriptor(m_Language); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : new test code template 78ec862f1a 2011-02-23 kinaba: Code.append("void verify_case(const " + TypeString + "& Expected, const " + TypeString + "& Received) {\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Print "PASSED" or "FAILED" based on the result 78ec862f1a 2011-02-23 kinaba: // <<modified by naoya_t>> : double precision 78ec862f1a 2011-02-23 kinaba: if (TypeString.equals("double")) { 78ec862f1a 2011-02-23 kinaba: Code.append(" bool ok = (abs(Expected - Received) < 1e-9);\n"); 78ec862f1a 2011-02-23 kinaba: } else if (TypeString.equals("vector <double>")) { 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : vector<double> !!! 78ec862f1a 2011-02-23 kinaba: Code.append(" bool ok = true;\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" for(int i=0; i<Expected.size(); ++i)\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" if( abs(Expected[i]-Received[i]) >= 1e-9 )\n"); 78ec862f1a 2011-02-23 kinaba: Code.append(" ok = false;\n"); 78ec862f1a 2011-02-23 kinaba: } else { 78ec862f1a 2011-02-23 kinaba: Code.append(" bool ok = (Expected == Received);\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: Code.append(" if(ok) cerr << \"PASSED\" << timer() << endl; "); 78ec862f1a 2011-02-23 kinaba: Code.append(" else { cerr << \"FAILED\" << timer() << endl;\n "); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: if (ReturnType.getDimension() == 0) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: Code.append("cerr << \"\\to: \\\"\" << Expected << \'\\\"\' << endl "); 78ec862f1a 2011-02-23 kinaba: Code.append("<< \"\\tx: \\\"\" << Received << \'\\\"\' << endl; }"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: else 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: Code.append("cerr << \"\\to: \" << Expected << endl "); 78ec862f1a 2011-02-23 kinaba: Code.append("<< \"\\tx: \" << Received << endl; }"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: Code.append(" }\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will generate the code for one test case. 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: private void generate_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: String[] Inputs = Case.getInput(); 78ec862f1a 2011-02-23 kinaba: String Output = Case.getOutput(); 78ec862f1a 2011-02-23 kinaba: String Desc = ReturnType.getDescription(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /* 78ec862f1a 2011-02-23 kinaba: * Generate code for setting up individual test cases 78ec862f1a 2011-02-23 kinaba: * and calling the method with these parameters. 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : new test code template 78ec862f1a 2011-02-23 kinaba: Code.append("CASE("+Index+")\n"); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate each input variable separately 78ec862f1a 2011-02-23 kinaba: for (int I = 0; I < Inputs.length; ++I) { 78ec862f1a 2011-02-23 kinaba: Code.append("\t"); 78ec862f1a 2011-02-23 kinaba: generate_parameter(I, Code, ParamTypes[I], Inputs[I]); 78ec862f1a 2011-02-23 kinaba: Code.append("\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: // Generate the output variable as the last variable 78ec862f1a 2011-02-23 kinaba: Code.append("\t"); 78ec862f1a 2011-02-23 kinaba: generate_parameter(-1, Code, ReturnType, Output); 78ec862f1a 2011-02-23 kinaba: Code.append("\n"); 78ec862f1a 2011-02-23 kinaba: Code.append("END\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: private void generate_blank_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: String[] Inputs = Case.getInput(); 78ec862f1a 2011-02-23 kinaba: String Output = Case.getOutput(); 78ec862f1a 2011-02-23 kinaba: String Desc = ReturnType.getDescription(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: Code.append("CASE("+Index+")\n"); 78ec862f1a 2011-02-23 kinaba: for (int I = 0; I < Inputs.length; ++I) { 78ec862f1a 2011-02-23 kinaba: Code.append("\t"); 78ec862f1a 2011-02-23 kinaba: generate_parameter(I, Code, ParamTypes[I], ""); 78ec862f1a 2011-02-23 kinaba: Code.append("\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: Code.append("\t"); 78ec862f1a 2011-02-23 kinaba: generate_parameter(-1, Code, ReturnType, ""); 78ec862f1a 2011-02-23 kinaba: Code.append("\n"); 78ec862f1a 2011-02-23 kinaba: Code.append("END\n"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: private void generate_verifier_call(StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: String[] Inputs = Case.getInput(); 78ec862f1a 2011-02-23 kinaba: String Output = Case.getOutput(); 78ec862f1a 2011-02-23 kinaba: String Desc = ReturnType.getDescription(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: Code.append("verify_case(_, " 78ec862f1a 2011-02-23 kinaba: + m_Problem.getClassName() + "()." + m_Problem.getMethodName() + "("); 78ec862f1a 2011-02-23 kinaba: for(int i=0; i<Inputs.length; ++i) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: Code.append( m_Problem.getParamNames()[i] ); 78ec862f1a 2011-02-23 kinaba: if( i < Inputs.length-1 ) 78ec862f1a 2011-02-23 kinaba: Code.append(", "); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: Code.append("));"); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: /** 78ec862f1a 2011-02-23 kinaba: * This method will generate the required parameter as a unique variable. 78ec862f1a 2011-02-23 kinaba: */ 78ec862f1a 2011-02-23 kinaba: private void generate_parameter(int Index, StringBuffer Code, DataType ParamType, String Input) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : named parameters 78ec862f1a 2011-02-23 kinaba: String Name = (Index==-1 ? "_" : m_Problem.getParamNames()[Index]); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: String Desc = ParamType.getBaseName(); 78ec862f1a 2011-02-23 kinaba: 78ec862f1a 2011-02-23 kinaba: if (ParamType.getDimension() == 0) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // Just a scalar value, simply initialize it at declaration (long integers need an 'L' tagged on) 78ec862f1a 2011-02-23 kinaba: if (Desc.equals("long") || Desc.equals("Long")) 78ec862f1a 2011-02-23 kinaba: Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "LL; "); 78ec862f1a 2011-02-23 kinaba: else 78ec862f1a 2011-02-23 kinaba: Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "; "); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: else 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // <<modified by cafelier>> : empty array 78ec862f1a 2011-02-23 kinaba: if( Input.matches("^[\\s\\{\\}]+$") ) 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: Code.append(ParamType.getDescriptor(m_Language) + " " + Name + "; "); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: else 78ec862f1a 2011-02-23 kinaba: { 78ec862f1a 2011-02-23 kinaba: // Arrays need to be converted to vector<type> before passing 78ec862f1a 2011-02-23 kinaba: Code.append(ParamType.getBaseName().toLowerCase() + " " + Name + "_[] = " + Input + ";\n\t"); 78ec862f1a 2011-02-23 kinaba: Code.append(" "+ParamType.getDescriptor(m_Language) + " " + Name + "(" + Name + "_, " + Name + "_+sizeof("+Name+"_)/sizeof(*"+Name+"_)); "); 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: } 78ec862f1a 2011-02-23 kinaba: }