001/**************************************************************************** 002 * Copyright/Copyleft: 003 * 004 * For this source the LGPL Lesser General Public License, 005 * published by the Free Software Foundation is valid. 006 * It means: 007 * 1) You can use this source without any restriction for any desired purpose. 008 * 2) You can redistribute copies of this source to everybody. 009 * 3) Every user of this source, also the user of redistribute copies 010 * with or without payment, must accept this license for further using. 011 * 4) But the LPGL ist not appropriate for a whole software product, 012 * if this source is only a part of them. It means, the user 013 * must publish this part of source, 014 * but don't need to publish the whole source of the own product. 015 * 5) You can study and modify (improve) this source 016 * for own using or for redistribution, but you have to license the 017 * modified sources likewise under this LGPL Lesser General Public License. 018 * You mustn't delete this Copyright/Copyleft inscription in this source file. 019 * 020 * @author JcHartmut: hartmut.schorrig@vishia.de 021 * @version 0.82 022 * list of changes: 023 * 2008-04-06 JcHartmut: some correction 024 * 2008-03-15 JcHartmut: creation 025 * 026 ****************************************************************************/ 027package org.vishia.java2C; 028 029import java.io.File; 030import java.io.FileNotFoundException; 031import java.io.IOException; 032import java.text.ParseException; 033import java.util.Iterator; 034import java.util.LinkedList; 035import java.util.List; 036import java.util.Map; 037import java.util.Set; 038import java.util.TreeMap; 039 040import org.vishia.java2C.ClassData.InitInfoVariable; 041import org.vishia.mainCmd.Report; 042import org.vishia.zbnf.ZbnfParseResultItem; 043 044/**This class processes the first pass of translating Java to C of a detect class in a java file. 045 * Parsing the content of the java file is done before, see {@link GenerateFile}. 046 * In the first pass all declared elements of a class are captured and store in the {@link ClassData}. 047 * 048 * @author JcHartmut 049 * 050 */ 051public class FirstPass extends GenerateClass 052{ 053 054 /**Version, history and license. 055 * <ul> 056 * <li>2014-08-16 Hartmut new: call {@link ClassData#completeOverriddenMethods()} as last action of {@link #write_HeaderContent(StringBuilder, GenerateFile, ZbnfParseResultItem, boolean, String, ClassData, ClassData[])}. 057 * <li>2014-08-16 Hartmut new: {@link #gatherAllDefinitions()} before running {@link #runFirstPass2(StringBuilder)} because for generation methods as C-MACROs (#define) 058 * all definitions of variables should be known. 059 * <li>2014-08-16 Hartmut new: @Java4C.exclude for varariable definitions. 060 * <li>2014-01-12 Hartmut new: The 'Java4C.inline' annotation is realized. It generates a define for C. 061 * TODO: While generating the statements of a inline method other methods are not known yet in the {@link ClassData} 062 * because there are not registered yet calling {@link #gen_methodHeadAndRegisterMethod(ZbnfParseResultItem, int, ClassData, ClassData, String, FieldData, FieldData[], boolean, boolean)}. 063 * First all methods should be registered. After them the header file should be generated. 064 * Yet called methods should be declared before calling methods in the Java source. 065 * <li>2014-01-10 Hartmut chg: second parameter 'classMethodBody' in gen_methodHeadAndRegisterMethod(...) 066 * is identical with 'classContainsMethod' usually, but not if it is a ctor of an inner non static class. 067 * The bug, class variable are not known in a inner ctor, are resolved therewith. 068 * <li>2008 Hartmut created: 069 * </ul> 070 * <br><br> 071 * <b>Copyright/Copyleft</b>: 072 * For this source the LGPL Lesser General Public License, 073 * published by the Free Software Foundation is valid. 074 * It means: 075 * <ol> 076 * <li> You can use this source without any restriction for any desired purpose. 077 * <li> You can redistribute copies of this source to everybody. 078 * <li> Every user of this source, also the user of redistribute copies 079 * with or without payment, must accept this license for further using. 080 * <li> But the LPGL ist not appropriate for a whole software product, 081 * if this source is only a part of them. It means, the user 082 * must publish this part of source, 083 * but don't need to publish the whole source of the own product. 084 * <li> You can study and modify (improve) this source 085 * for own using or for redistribution, but you have to license the 086 * modified sources likewise under this LGPL Lesser General Public License. 087 * You mustn't delete this Copyright/Copyleft inscription in this source file. 088 * </ol> 089 * If you are intent to use this sources without publishing its usage, you can get 090 * a second license subscribing a special contract with the author. 091 * 092 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 093 */ 094 public final static String sVersion = "2014-08-17"; 095 096 097 098 099 100 private List<FirstPass> innerClasses; 101 102 private ZbnfParseResultItem zbnfClass; 103 104 /**Created on {@link #gatherAllDefinitions(GenerateFile, ZbnfParseResultItem)}, used in {@link #runFirstPass2(StringBuilder)} 105 * 106 */ 107 private StatementBlock statementBlockClassLevel; 108 109 boolean bDontWriteCtor; 110 111 /**initializes the instances with the given associations. */ 112 //FirstPass(iWriteContent writeContent, TreeMap<String, ClassData> pkgIdents, RunRequiredFirstPass_ifc runRequiredFirstPass) 113 FirstPass(iWriteContent writeContent, GenerateFile parentGenerateFile 114 , LocalIdents fileLevelIdents, RunRequiredFirstPass_ifc runRequiredFirstPass 115 , Report log 116 ) 117 { super(writeContent, parentGenerateFile, fileLevelIdents, runRequiredFirstPass, log, true); 118 } 119 120 121 /**Builds the type information of the given class or interface and recursively 122 * all of its inner classes and interfaces. This creates the {@link ClassData} 123 * of the class or interface. It is the first pass of the translation. 124 * <br><br> 125 * All internal classes and interfaces are detect, this method is called recursively with it. 126 * @param sourceOfClassDataP Info for message on errors, where the ClassData comes from. 127 * The name of the class will be added in form "sourceOfClassDataP-className" then. 128 * @param fileContainsClass The generation environment 129 * @param sFileName Name of the file for C without extension .c or .h, not the Java-filename 130 * It is stored in the created ClassData of the class 131 * to allow the generating of a include statement, if another class uses this class. 132 * @param sPkgIdent Package where the Java file is found. With <code>/</code> as Separator and at end. 133 * @param sPrefix To Build the Classname for C 134 * @param sPostfix To Build the Classname for C. 135 * @param zbnfClass parse result of <code>class::=</code> 136 * @param sOuterClassName "" or the name of the outer class. 137 * The name of the outer class is set as prefix of the name of the struct in C 138 * @param outerClassData The outer class data or null, to register the inner class in a outer. 139 * @param listAllClassesForSecondPath List to add the detect ClassData. 140 * The list is used as input for running the second path of classes. 141 * See {@link GenerateFile.itemsClassesForSecondPath}. 142 * @param bInterface 143 * @param identsParent 144 * @return 145 * @throws IOException 146 * @throws ParseException 147 * @throws IllegalArgumentException 148 * @throws IllegalAccessException 149 * @throws InstantiationException 150 */ 151 /** 152 * @param uResult 153 * @param sourceOfClassDataP 154 * @param fileContainsClass 155 * @param sFileNameC 156 * @param sPkgIdent 157 * @param sPrefixClassCname 158 * @param sSuffixClassCname 159 * @param zbnfClass 160 * @param bDontWriteCtor 161 * @param sOuterClassName 162 * @param outerClassData 163 * @param listAllClassesForSecondPath 164 * @param bInterface 165 * @param classBase 166 * @param intension C: inner class, P: file-level (primary) class, Y: class level anonymous, 167 * other: anonymous inner class at statement block level 168 * @return 169 * @throws IOException 170 * @throws ParseException 171 * @throws IllegalArgumentException 172 * @throws IllegalAccessException 173 * @throws InstantiationException 174 */ 175 ClassData buildType 176 ( StringBuilder uResult 177 , String sourceOfClassDataP 178 , GenerateFile fileContainsClass 179 , String sFileNameC 180 , String sPkgIdent 181 , String sPrefixClassCname, String sSuffixClassCname 182 , ZbnfParseResultItem zbnfClass 183 , boolean bDontWriteCtor 184 , String sOuterClassName 185 , ClassData outerClassData 186 , List<ClassData> listAllClassesForSecondPath 187 , boolean bInterface 188 , ClassData classBase 189 , char intension 190 //, String sFirstInterfaceType 191 ) 192 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 193 { 194 this.zbnfClass = zbnfClass; 195 this.bDontWriteCtor = bDontWriteCtor; 196 ZbnfParseResultItem itemClassDescription = zbnfClass.getChild("description"); 197 /**true if the class has the modifier static, Java-syntax: */ 198 boolean bStaticClass = zbnfClass.getChild("static")!=null; 199 boolean bAbstractClass = zbnfClass.getChild("abstract")!=null; 200 /**true if the class isn't handled by GC, it is a java2c-annotation: */ 201 boolean bStaticInstance = itemClassDescription != null 202 && itemClassDescription.getChild("staticInstance")!= null; 203 boolean bFinal = zbnfClass.getChild("final")!= null; 204 ZbnfParseResultItem itemClassIdent = zbnfClass.getChild("classident"); 205 /**itemClassIdent is null if it is an anonymous class. */ 206 final String sClassNameLocal; 207 if(itemClassIdent !=null){ 208 sClassNameLocal =itemClassIdent.getParsedString(); 209 } else { 210 /**Anonymous inner class: the variable name is given with the param sPrefixName. 211 * Build a className specially, the source code doesn't contain a class name.*/ 212 sClassNameLocal = sPrefixClassCname; 213 } 214 if(sClassNameLocal.equals("TestThread")) 215 stop(); 216 //The sourceOfClassData ist build with path/file.java-className-innerClassname 217 final String sourceOfClassData = sourceOfClassDataP + "-" + sClassNameLocal; 218 final String sClassNameC; 219 final String sClassNameJava; 220 221 LocalIdents localIdentsTypes = outerClassData !=null ? outerClassData.classLevelIdents 222 : fileLevelIdents; 223 final ClassData firstInterface; 224 final ClassData superClazz; 225 if(classBase != null && !classBase.isInterface()){ 226 superClazz = classBase; 227 firstInterface = null; 228 } else { 229 superClazz = zbnfResultSuperclass(zbnfClass, itemClassDescription, outerClassData); 230 firstInterface = classBase; //may be null 231 } 232 ClassData[] ifcClassData = zbnfResultInterfaces(zbnfClass, itemClassDescription, localIdentsTypes, firstInterface); 233 234 String sProp = "+"; 235 if(bStaticInstance){sProp +="static+"; } 236 if(bFinal){sProp +="final+"; } 237 if(bAbstractClass){sProp +="abstract+"; } 238 if(bInterface){sProp +="interface+"; } 239 if(outerClassData != null) 240 { //sClassNameC = outerClassData.getClassIdentName() + "__" + sClassNameLocal; 241 if(!bStaticClass){ sProp += "nonStaticInner+"; } 242 sClassNameC = sClassNameLocal + "_" + outerClassData.getClassIdentName(); //+ sOuterClassName; 243 sClassNameJava = sClassNameLocal; //// 244 Java2C_Main.singleton.console.reportln(Report.debug, "Java2C-FirstPass.buildType-inner: src=" + sourceOfClassData 245 + ", name=" + sClassNameC); 246 //NOTE: use sClassName for classData from outer class "__" + read from itemClassIdent 247 classData = new ClassData(sourceOfClassData, fileContainsClass, sFileNameC, sPkgIdent, sClassNameJava, sClassNameC + "_s" 248 , "XX", 'L', outerClassData, superClazz, ifcClassData, zbnfClass 249 , '*', sProp, intension); 250 //An inner class is known in the outer by name. This type is known also in all other inner classes. 251 //Therefore it is part of the classlevelIdents. 252 outerClassData.classLevelIdents.putClassType(sClassNameLocal, classData); 253 //The inner class is known to completion idents after running its first pass 254 //and to build the stc-file. 255 outerClassData.addInnerClass(classData); 256 } 257 else 258 { //NOTE: use sClassName for classData only read from itemClassIdent 259 //NOTE: if sSuffixClassCname == null, then the full class name is given as prefix. 260 // The suffix may be empty. The suffix is != null but empty if "prefix*" is written in the config file. 261 sClassNameC = sPrefixClassCname + (sSuffixClassCname != null ? sClassNameLocal + sSuffixClassCname : ""); 262 sClassNameJava = sClassNameLocal; 263 Java2C_Main.singleton.console.reportln(Report.debug, "Java2C-FirstPass.buildType: src=" + sourceOfClassData 264 + ", name=" + sClassNameC); 265 classData = new ClassData(sourceOfClassData, fileContainsClass, sFileNameC, sPkgIdent, sClassNameJava, sClassNameC + "_s" 266 , "XX", 'L', null, superClazz, ifcClassData, zbnfClass 267 , '*', sProp, intension); 268 //Put in list of this package. 269 //A non-inner class is known in the package by name. Store it to find out later in package by name. */ 270 fileLevelIdents.putClassType(sClassNameLocal, classData); 271 //Register the class just now, to prevent circular call of first pass 272 // if an one-another internal usage of a class as reference is programmed in Java. */ 273 fileContainsClass.registerClassInFile(classData); //TODO check also from inner classes??? 274 275 } 276 //store the classData to run the second pass later. 277 if(listAllClassesForSecondPath!=null){ 278 listAllClassesForSecondPath.add(classData); //to process in the second path sorted per file 279 } 280 // 281 //run the buildType for all inner classes, so that all inner types are knwon, 282 //before the class-definitions are processed. The inner types may be used for declarations in outer 283 //not in the order of writing in the java-source-file. 284 List<ZbnfParseResultItem> listSubClasses = zbnfClass.listChildren("classDefinition"); 285 if(listSubClasses != null) 286 { innerClasses = new LinkedList<FirstPass>(); 287 for(ZbnfParseResultItem itemSubClasses : listSubClasses) { 288 FirstPass innerClassFirst = new FirstPass(writeContent, fileContainsClass, fileLevelIdents, runRequiredFirstPass, log); 289 innerClasses.add(innerClassFirst); 290 innerClassFirst.buildType(uResult, sourceOfClassData, fileContainsClass, sFileNameC, sPkgIdent, null, null 291 , itemSubClasses, bInterface, sClassNameLocal, classData , listAllClassesForSecondPath 292 , false, null, 'C' 293 ); 294 } } 295 // 296 //classData.needFinalize(); //set it as default. TODO 297 return classData; 298 } 299 300 301 302 /**Gathers all definitions in this Java source and writes it to the ClassLevelIdents. It is before any inline methods are evaluated. 303 * @throws IOException 304 * @throws ParseException 305 * @throws InstantiationException 306 * @throws IllegalAccessException 307 * @throws IllegalArgumentException 308 * @throws FileNotFoundException 309 * 310 */ 311 void gatherAllDefinitions() 312 throws FileNotFoundException, IllegalArgumentException, IllegalAccessException, InstantiationException, ParseException, IOException 313 { 314 if(innerClasses != null) 315 { for(FirstPass genClass: innerClasses) { 316 genClass.gatherAllDefinitions(); 317 } } 318 319 //The statement block for any usage for classLevel variables. 320 statementBlockClassLevel = new StatementBlock(this,classData.classLevelIdents, true, false, 1); 321 List<ZbnfParseResultItem> listVariables = zbnfClass.listChildren("variableDefinition"); 322 if(listVariables != null) 323 for(ZbnfParseResultItem itemVariable : listVariables) 324 { if(itemVariable.getChild("exclude")==null && itemVariable.getChild("static")== null) 325 { //only non static members. 326 { String sVariableName = itemVariable.getChild("variableName").getParsedString(); 327 if(sVariableName.equals("stressTest")) 328 stop(); 329 } 330 ZbnfParseResultItem zbnfVariableDescription = itemVariable.getChild("description"); //may be null. 331 CCodeData sDef = gen_variableDefinition( 332 itemVariable, zbnfVariableDescription 333 , classData.classLevelIdents 334 , statementBlockClassLevel 335 , classData.getVariablesToInit() 336 , 'C' 337 ); 338 statementBlockClassLevel.fieldsNonStatic.add(sDef); 339 } 340 } 341 if(listVariables != null)for(ZbnfParseResultItem itemVariable : listVariables) 342 { if(itemVariable.getChild("exclude")==null && itemVariable.getChild("static")!= null) 343 { //only static members. 344 ZbnfParseResultItem zbnfVariableDescription = itemVariable.getChild("description"); //may be null. 345 { String sVariableName = itemVariable.getChild("variableName").getParsedString(); 346 if(sVariableName.equals("empty")) 347 stop(); 348 } 349 List<InitInfoVariable> variablesToInit = classData.getVariablesToInit(); //maybe add the variable there. 350 CCodeData sDef = gen_variableDefinition( 351 itemVariable, zbnfVariableDescription 352 , classData.classLevelIdents 353 , statementBlockClassLevel 354 , variablesToInit 355 , 's'); 356 statementBlockClassLevel.fieldsStatic.add(sDef); 357 } 358 } 359 360 } 361 362 363 364 365 366 /**Generates the content of a class in the h-file with given ZBNF parse result item of the class. 367 * This is the second part of the first pass of translation. 368 * This routine is called from {@link GenerateFile}. 369 * <ul> 370 * <li>The detected class-fields are written in a struct in the h-File. 371 * <li> The static-fields are written in h-file as extern declaration. 372 * <li> The constructors are written as forward declaration in h-file of routines ctor... 373 * <li> The methods are written as forward declaration in h-file. 374 * </ul> 375 * For fields, the initial values are detected and stored in {@link ClassData#listVariablesToInit}. 376 * This action is done inside the called routine {@link GenerateClass#gen_variableDefinition(ZbnfParseResultItem, LocalIdents, List, char, ClassData[])}. 377 * <br> 378 * The method heads are generated calling {@link #write_methodDeclaration(ZbnfParseResultItem, String, LocalIdents)}. 379 * @param uResult 380 * @throws IllegalArgumentException 381 * @throws IOException 382 * @throws ParseException 383 * @throws IllegalAccessException 384 * @throws InstantiationException 385 */ 386 void runFirstPass2(StringBuilder uResult 387 ) throws IllegalArgumentException, IOException, ParseException, IllegalAccessException, InstantiationException 388 { 389 //Then run the first pass of inner classes. 390 if(innerClasses != null) 391 { for(FirstPass genClass: innerClasses) { 392 genClass.runFirstPass2(uResult); 393 } } 394 395 Java2C_Main.singleton.console.reportln(Report.debug, "Java2C-FirstPass.runFirstPass2: name=" + classData.sClassNameC); 396 397 if(classData.getClassNameJava().equals("ExpandedDataStruct")) 398 stop(); 399 //setInitialTypeIdentifiers(); 400 401 /**Generate content of header: */ 402 { List<ZbnfParseResultItem> listSubInterfaces = zbnfClass.listChildren("interfaceDefinition"); 403 if(listSubInterfaces != null) 404 { for(ZbnfParseResultItem itemSubInterfaces : listSubInterfaces) 405 { write_Interface(itemSubInterfaces, classData.sClassNameJava + "__", classData, uResult); 406 } } 407 } 408 409 /**Inner classes will be written before, The types {@link ClassData} are known. 410 * now generate the classdata-content of the own class. 411 * This call may call recursive this method if some other files should be translated. 412 * */ 413 write_HeaderContent(uResult, classData.fileContainsClass, zbnfClass, bDontWriteCtor, classData.sClassNameC, classData.getSuperClassData(), classData.getInterfaces()); 414 //writeContent.writeClassH(uHeader.toString()); //TODO inner classes in body: write in the C-file. 415 // 416 /**The identifier of the outer class are known yet, 417 * it should be transported to all non-static inner classes too 418 * because they should be known there: */ 419 if(classData.sClassNameJava.equals("MainController")) 420 stop(); 421 //After finishing the first pass, all indentifiers are known. The inner classes are built before. 422 //But all identifiers of the outer class should be known to run the second pass. 423 //Therefore they are completed now. 424 classData.completeFieldIdentsForInnerClasses(); 425 426 } 427 428 429 430 /**Gets the superClass from ZBNF parse result item. 431 * @param zbnfClass The parse result item of <code>classDefinition::=...</code> 432 * @param zbnfDescription The parse result item of <code>< description>... test_description::=</code> 433 * inside the <code>classDefinition::=...</code> 434 * @param outerClassData a given outerclass 435 * @return The ClassData of the superClass. It is {@link Java2C_Main.CRuntimeJavalikeClassData#clazzObjectJc} 436 * if no superclass is given in Java-code (no <code>extends ...</code>). 437 * It is null if the description contains <code>@java2c=noObject.</code> and no other superclass is given. 438 * @throws FileNotFoundException The Superclass may be translated yet nested, it may be cause some errors. 439 * @throws IllegalArgumentException Errors see {@link #runFirstPassClass(GenerateFile, String, String, String, String, ZbnfParseResultItem, String, ClassData, List, boolean, LocalIdents)}. 440 * @throws IOException 441 * @throws IllegalAccessException 442 * @throws InstantiationException 443 * @throws ParseException 444 */ 445 ClassData zbnfResultSuperclass(ZbnfParseResultItem zbnfClass, ZbnfParseResultItem zbnfDescription, ClassData outerClassData) 446 throws FileNotFoundException, IllegalArgumentException, IOException, IllegalAccessException, InstantiationException, ParseException 447 { final ClassData superClazz; 448 boolean bNoObject = zbnfDescription != null && zbnfDescription.getChild("noObject")!= null; 449 if(bNoObject) 450 stop(); 451 final ZbnfParseResultItem zbnfSuperClass = zbnfClass.getChild("Superclass"); 452 if(zbnfSuperClass != null) 453 { String sSuperClass = zbnfSuperClass.getParsedString(); 454 stop(); 455 if(outerClassData != null) 456 { /*If there is an outer class, the superclass may be part of them or may be known in the file. */ 457 //superClazz = outerClassData.classLevelIdents.getTypeContingentlyRunFirstPass(sSuperClass, runRequiredFirstPass); 458 superClazz = outerClassData.classLevelIdents.getType(sSuperClass, fileLevelIdents); 459 } 460 else { 461 //superClazz = fileLevelIdents.getTypeContingentlyRunFirstPass(sSuperClass, runRequiredFirstPass); 462 superClazz = fileLevelIdents.getType(sSuperClass, null); 463 } 464 } 465 else 466 { 467 superClazz = bNoObject ? null : CRuntimeJavalikeClassData.clazzObjectJc; 468 } 469 return superClazz; 470 } 471 472 473 474 475 476 /**Gets the interfaces from ZBNF parse result item. 477 * @param zbnfClass The parse result item of <code>classDefinition::=...</code> 478 * @param zbnfDescription The parse result item of <code>< description>... test_description::=</code> 479 * inside the <code>classDefinition::=...</code> 480 * @param outerClassData a given outerclass 481 * @param sFirstInterface name of the interface for anonymous classes 482 * @return Array of ClassData[] of all Interfaces. If the class hasn't interfaces, it is null. 483 * @throws FileNotFoundException The Superclass may be translated yet nested, it may be cause some errors. 484 * @throws IllegalArgumentException Errors see {@link #runFirstPassClass(GenerateFile, String, String, String, String, ZbnfParseResultItem, String, ClassData, List, boolean, LocalIdents)}. 485 * @throws IOException 486 * @throws IllegalAccessException 487 * @throws InstantiationException 488 * @throws ParseException 489 */ 490 private ClassData[] zbnfResultInterfaces 491 ( ZbnfParseResultItem zbnfClass, ZbnfParseResultItem zbnfDescription 492 , LocalIdents localIdentsIfcType 493 // , ClassData outerClassData 494 , ClassData firstInterface) 495 throws FileNotFoundException, IllegalArgumentException, IOException, IllegalAccessException, InstantiationException, ParseException 496 { final ClassData[] interfaceClazzes; 497 int ixIfc = firstInterface !=null ? 1 : 0; 498 final List<ZbnfParseResultItem> zbnflistInterfaces = zbnfClass.listChildren("ImplementedInterface"); 499 if(zbnflistInterfaces != null){ 500 interfaceClazzes = new ClassData[zbnflistInterfaces.size() + ixIfc]; //+1 if sFirstInterface given. 501 for(ZbnfParseResultItem zbnfInterface: zbnflistInterfaces) 502 { String sIdentInterface = zbnfInterface.getParsedString(); 503 //if(outerClassData != null) 504 { /*If there is an outer class, the superclass may be part of them or may be known in the file. */ 505 //interfaceClazzes[ixIfc] = outerClassData.classLevelIdents.getType(sIdentInterface, fileLevelIdents); 506 } 507 //else { 508 //interfaceClazzes[ixIfc] = fileLevelIdents.getTypeContingentlyRunFirstPass(sIdentInterface, runRequiredFirstPass); 509 ClassData ifcClass = localIdentsIfcType.getType(sIdentInterface, fileLevelIdents); 510 if(ifcClass == null) 511 throw new IllegalArgumentException("unknown class: " + sIdentInterface); 512 interfaceClazzes[ixIfc] = ifcClass; 513 //} 514 ixIfc +=1; 515 } 516 } 517 else 518 { if(ixIfc ==1){ interfaceClazzes = new ClassData[1]; 519 } else { interfaceClazzes = null; 520 } 521 } 522 if(firstInterface !=null){ 523 interfaceClazzes[0] = firstInterface; 524 } 525 return interfaceClazzes; 526 } 527 528 529 530 531 532 533 534 535 /**Write out the header part of the class. 536 * It writes: 537 * <pre> 538 * /*@CLASS_C NAME @@@@@@@@@@@@@@@@@@@@@* / 539 * typedef struct NAME_t 540 * { union base_{ ObjectJc object; SUPER super; IFC IFC; } base 541 * VARIABLETYPE VARIABLENAME; 542 * } NAME_s; 543 * 544 * typedef struct NAME_Y_t { ObjectArrayJc head; " + NAME + "_s data[50]; } NAME_Y;"); 545 * 546 * extern_C struct ClassJc_t const reflection_NAME_s; 547 * 548 * extern STATICVARIABLEDEF NAME; 549 * 550 * ...etc TODO 551 * </pre> 552 * @param uHeader The buffer for output. 553 * @param fileContainsClass The calling instance. 554 * @param zbnfClass The parse result item of the class definition. 555 * @param bDontWriteCtor if it is an interface or anonymous class. 556 * @param sClassNameC The name, it is dissolved already from zbnfClass 557 * @param superClazz The superclass or ObjectJc or null 558 * @param ifcClassData null or interfaces 559 * 560 * @throws FileNotFoundException 561 * @throws IllegalArgumentException 562 * @throws ParseException 563 * @throws IOException 564 * @throws IllegalAccessException 565 * @throws InstantiationException 566 */ 567 private void write_HeaderContent 568 ( StringBuilder uHeader 569 , GenerateFile fileContainsClass 570 , ZbnfParseResultItem zbnfClass 571 , boolean bDontWriteCtor 572 , String XXXsClassNameC 573 , ClassData superClazz 574 , ClassData[] ifcClassData 575 ) 576 throws FileNotFoundException, IllegalArgumentException, ParseException, IOException, IllegalAccessException, InstantiationException 577 { String sClassNameC = classData.getClassIdentName(); 578 uHeader.append("\n\n/*@CLASS_C " + sClassNameC + " @@@@@@@@@@@@@@@@@@@@@@@@*/"); 579 uHeader.append("\n\ntypedef struct " + sClassNameC + "_t\n{ "); 580 ClassData superClass = classData.getSuperClassData(); 581 if(superClass != null || ifcClassData != null) 582 { uHeader.append("\n union { "); 583 if(superClass !=null){ 584 final String sNameSuper; sNameSuper = (superClass).sClassNameC; 585 if(superClass.isBasedOnObject() || sNameSuper.equals("ObjectJc")) 586 { /**either the superclass based on or is an Object: */ 587 uHeader.append("ObjectJc object; "); 588 } 589 if(!sNameSuper.equals("ObjectJc")) 590 { uHeader.append(sNameSuper + " super;"); 591 fileContainsClass.addIncludeH(superClazz.sFileName, "superclass"); 592 } 593 } 594 if(ifcClassData != null) for(ClassData ifc: ifcClassData) 595 { String sNameIfc_s = ifc.sClassNameC; 596 String sNameIfc = ifc.getClassIdentName(); 597 uHeader.append(sNameIfc_s+ " " + sNameIfc +";"); //Type and name are identical 598 fileContainsClass.addIncludeH(ifc.sFileName, "interface"); 599 } 600 uHeader.append("} base; "); 601 } 602 else 603 stop(); 604 ClassData outerClass = classData.getOuterClass(); 605 //if( outerClass !=null) ////TODO next is correct. 606 if(classData.isNonStaticInner) 607 { /*implicit reference to the outer class: */ 608 uHeader.append("\n struct " + outerClass.getClassIdentName() + "_t* outer; //J2C: Reference to outer class, implicit in Java"); 609 } 610 //if(outerClass ) 611 612 if(sClassNameC.equals("ImplIfc_TestAll")) 613 stop(); 614 615 //process the class Content, write all class variable in the struct 616 for(CCodeData sDef: statementBlockClassLevel.fieldsNonStatic) { 617 uHeader.append("\n " + sDef.cCode); 618 619 } 620 621 uHeader.append("\n} " + sClassNameC + "_s;\n \n"); 622 uHeader.append("\n#define sizeof_" + sClassNameC + "_s sizeof(" + sClassNameC + "_s)\n"); 623 624 uHeader.append("\n\n/**J2c: Definitions of the enhanced reference. It's conditinally because it may be defined in a included header before. */"); 625 uHeader.append("\n#ifndef " + sClassNameC + "REFDEF"); 626 uHeader.append("\n //J2C: definition of enhanced reference where it was need firstly: "); 627 uHeader.append("\n #define " + sClassNameC + "REFDEF"); 628 uHeader.append("\n struct " + sClassNameC + "_t;"); 629 /* 630 uHeader.append("\n #ifdef STRUCT_REFJc"); 631 uHeader.append("\n //J2C: macro STRUCT_REFJc should be defined in <fw_Platform_conventions.h> "); 632 uHeader.append("\n typedef struct " + sClassNameC + "REF_t STRUCT_REFJc(struct " + sClassNameC + "_t) " + sClassNameC + "REF;"); 633 uHeader.append("\n #else"); 634 uHeader.append("\n //J2C: simple reference instead enhanced reference if macro is not defined"); 635 uHeader.append("\n #define " + sClassNameC + "REF struct " + sClassNameC + "_t* "); 636 uHeader.append("\n #endif"); 637 */ 638 uHeader.append("\n DEFINE_EnhancedRefJc(" + sClassNameC + ");"); 639 uHeader.append("\n#endif"); 640 uHeader.append("\n\n/**J2c: Definitions of the array forms. NOTE: The number of elements are a helper for debug, the really used number depends on the memory size! */"); 641 uHeader.append("\ntypedef struct " + sClassNameC + "_X_t { ObjectArrayJc head; " + sClassNameC + "REF data[50]; } " + sClassNameC + "_X;"); 642 uHeader.append("\ntypedef struct " + sClassNameC + "_Y_t { ObjectArrayJc head; " + sClassNameC + "_s data[50]; } " + sClassNameC + "_Y;"); 643 644 uHeader.append("\n\n extern_C struct ClassJc_t const reflection_" + sClassNameC + "_s;\n \n"); 645 646 uHeader.append("\n\n/**CONST_Type useable as initializer for embedded/stack-instances*/\n"); 647 uHeader.append("#define CONST_").append(sClassNameC).append("(OBJP) { CONST_ObjectJc(sizeof(") 648 .append(sClassNameC).append("_s), OBJP, &reflection_").append(sClassNameC).append("_s), 0 }\n\n"); 649 650 uHeader.append("/**J2C: finalize declaration. It is called by Garbage collector and inside other finalized methods.\n") 651 .append(" * It should be called by the user if the instance is removed. */\n") 652 .append("void finalize_") 653 .append(sClassNameC); 654 if(classData.isBasedOnObject()){ 655 uHeader.append("_F(ObjectJc* othis, ThCxt* _thCxt);\n\n"); 656 } else { 657 uHeader.append("_F(").append(sClassNameC).append("_s* thiz, ThCxt* _thCxt);\n\n"); 658 } 659 660 //process the class Content, write all class variable in the struct 661 for(CCodeData sDef: statementBlockClassLevel.fieldsStatic) { 662 if(sDef.identInfo.modeStatic=='d'){ 663 uHeader.append("\n" + sDef.cCode); 664 }else{ 665 uHeader.append("\n extern " + sDef.cCode); 666 } 667 668 } 669 uHeader.append("\n\n"); 670 671 if(!bDontWriteCtor){ 672 writeCtor(zbnfClass, outerClass, uHeader); 673 } 674 675 { List<ZbnfParseResultItem> listMethods = zbnfClass.listChildren("methodDefinition"); 676 if(listMethods != null) 677 { 678 for(ZbnfParseResultItem itemMethod : listMethods) 679 { String sName = itemMethod.getChild("name").getParsedString(); 680 //register the method with following "?" to test if it is ambiguous. 681 classData.testAndSetAmbiguousnessOfMethod(sName); 682 } 683 for(ZbnfParseResultItem itemMethod : listMethods) 684 { boolean bExclude = itemMethod.getChild("exclude") !=null; 685 if(!bExclude){ 686 boolean bInline; 687 ZbnfParseResultItem zbnfBody = itemMethod.getChild("methodbody"); 688 if(zbnfBody !=null){ 689 List<ZbnfParseResultItem> listStatements = zbnfBody.listChildren(); 690 bInline = itemMethod.getChild("inline") !=null 691 ; //|| listStatements !=null && listStatements.size() ==1 && listStatements.get(0).getChild("return")!=null; 692 //note: bDefine if the method contains only the return statement. 693 } else { 694 bInline = false; 695 } 696 if(bInline){ 697 write_methodInline(itemMethod, sClassNameC, classData.classLevelIdents, uHeader); 698 } else { 699 write_methodDeclaration(itemMethod, sClassNameC, classData.classLevelIdents, uHeader); 700 } 701 } 702 } 703 } 704 } 705 706 if(classData.isFinalizeNeed()){ 707 /**Finalize is not written in Java, but need because enhanced references: */ 708 classData.addMethod("finalize", "finalize", Method.modeOverrideable, CRuntimeJavalikeClassData.clazz_void.classTypeInfo); 709 } 710 if(classData.inheritanceInfo != null){ 711 classData.completeInheritanceWithOwnMethods(); 712 } 713 //check all super implementations whether methods exists. 714 classData.completeOverriddenMethods(); 715 716 if(classData.isBasedOnObject()){ 717 write_Mtbl(uHeader); 718 } 719 write_ClassCpp(uHeader); 720 } 721 722 723 724 725 /** 726 * @param zbnfClass 727 * @param outerClass 728 * @param uHeader 729 * @throws IllegalArgumentException 730 * @throws IOException 731 * @throws ParseException 732 * @throws IllegalAccessException 733 * @throws InstantiationException 734 */ 735 private void writeCtor(ZbnfParseResultItem zbnfClass, ClassData outerClass 736 //, boolean bInterface 737 , StringBuilder uHeader 738 ) 739 throws IllegalArgumentException, IOException, ParseException, IllegalAccessException, InstantiationException 740 { 741 /**Generate ctor. */ 742 final ClassData classOfCtor; // 743 final ClassData outerClassOfCtor; //TODO check classOfCtor-usage. 744 final String sNameCtor; // = classData.isBasedOnObject()? "ctorO" : "ctorM"; 745 int modeCtor = Method.modeCtor; 746 if(classData.isNonStaticInner){ 747 stop(); 748 /**Register the ctor in the outer class, because the ctor is a method of the outer class, using this.new Type. */ 749 classOfCtor = outerClass; 750 modeCtor |= Method.modeCtorNonStatic; 751 sNameCtor = (classData.isBasedOnObject()? "ctorO_" : "ctorM_") + classData.getClassNameJava(); 752 //outerClassOfCtor = outerClass; 753 } else { 754 /**Register the ctor as static method in the class, where it constructs. */ 755 classOfCtor = classData; 756 sNameCtor = classData.isBasedOnObject()? "ctorO" : "ctorM"; 757 } 758 //if(!bInterface) 759 { List<ZbnfParseResultItem> listConstructors = zbnfClass.listChildren("constructorDefinition"); 760 if(listConstructors != null) 761 { boolean bArgumentSensitive = (listConstructors.size() >1); 762 for(ZbnfParseResultItem zbnfConstructor : listConstructors) 763 { Method method = gen_methodHeadAndRegisterMethod( 764 zbnfConstructor 765 , modeCtor 766 , classOfCtor //may be outer class if it is a non-static inner class 767 , classData //ClassData for the method body 768 , sNameCtor 769 , classData.classTypeInfo //return-type 770 , null //argTypes-array uninitialized, because zbnfConstructor is given. 771 , bArgumentSensitive 772 , false 773 ); 774 uHeader.append(method.gen_MethodForwardDeclaration()); 775 ClassData.MethodWithZbnfItem methodDef = classOfCtor.new MethodWithZbnfItem(method, zbnfConstructor, null, 'c'); 776 classData.methodsWithZbnf.add(methodDef); 777 } 778 } 779 else 780 { //no constructor found, create a default constructor because all variable initializations should be done. 781 Method method = gen_methodHeadAndRegisterMethod( 782 null 783 , modeCtor 784 , classOfCtor //may be outer class if it is a non-static inner class 785 , classData //ClassData for the method body 786 , sNameCtor 787 , classData.classTypeInfo //return-type 788 , null //argTypes-array uninitialized, because it haven't args. 789 , false //bArgumentSensitive = false. Only one. 790 , false 791 ); 792 uHeader.append(method.gen_MethodForwardDeclaration()); 793 ClassData.MethodWithZbnfItem methodDef = classOfCtor.new MethodWithZbnfItem(method, null, null, 'c'); 794 classData.methodsWithZbnf.add(methodDef); 795 } 796 //uHeader.append("\n\n" + "void finalize_" + sClassNameC + "(ObjectJc* yObj, ThCxt* _thCxt);\n\n"); 797 } 798 } 799 800 801 private void write_Mtbl(StringBuilder uHeader) 802 { 803 String sClassIdentName = classData.getClassIdentName(); 804 String sClassName_s = classData.getClassCtype_s(); 805 boolean isObject; 806 uHeader.append("\n\n/* J2C: Method table contains all dynamic linked (virtual) methods"); 807 uHeader.append("\n * of the class and all super classes and interfaces. */"); 808 uHeader.append("\n extern const char sign_Mtbl_" + sClassIdentName + "[]; //marker for methodTable check"); 809 uHeader.append("\ntypedef struct Mtbl_" + sClassIdentName + "_t"); 810 uHeader.append("\n{ "); 811 String sMtbl = classData.gen_MethodTableDefinitionContent(); //from this class and all its super classes and interfaces. 812 uHeader.append(sMtbl); 813 uHeader.append("\n} Mtbl_" + sClassIdentName + ";\n\n"); 814 } 815 816 817 818 819 820 private void write_ClassCpp(StringBuilder uHeader) 821 { 822 String sClassIdentName = classData.getClassIdentName(); 823 String sClassName_s = classData.getClassCtype_s(); 824 boolean isObject; 825 uHeader.append("\n\n#if defined(__CPLUSPLUSJcpp) && defined(__cplusplus)"); 826 uHeader.append("\n/* J2C: The C++-class-definition. */"); 827 uHeader.append("\nclass " + sClassIdentName + " : private " + sClassIdentName + "_s" ); 828 uHeader.append("\n{ public:"); 829 String sMethods = classData.gen_ClassCppDefinitionContent(writeContent); //from this class and all its super classes and interfaces. 830 uHeader.append(sMethods); 831 uHeader.append("\n};\n\n"); 832 uHeader.append("#endif /*__CPLUSPLUSJcpp*/\n\n"); 833 } 834 835 836 837 838 839 /**Generates the content of an interface in c- and h-file. 840 * @throws InstantiationException 841 * @throws IllegalAccessException 842 * @throws IllegalArgumentException */ 843 void write_Interface(ZbnfParseResultItem itemClass, String sOuterClassName 844 , ClassData outerClassData, StringBuilder uHeader) 845 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 846 { 847 //ZbnfParseResultItem resultItem = resultItemClass.nextSkipIntoComponent(resultItemClass); 848 849 ZbnfParseResultItem itemClassIdent = itemClass.getChild("classident"); 850 if(itemClassIdent == null) 851 throw new IllegalArgumentException("<$?classident> not found in " + itemClass.toString()); 852 ZbnfParseResultItem itemDescription = itemClass.getChild("description"); 853 if(itemDescription != null) 854 { write_Description(itemDescription, uHeader); 855 } 856 857 858 String sClassName = sOuterClassName + itemClassIdent.getParsedString(); 859 uHeader.append("typedef struct " + sClassName + "_t /*interface*/\n{"); 860 uHeader.append("ObjectJc object;"); 861 862 if(sClassName == null) throw new ParseException("no className found", 0); 863 864 Iterator<ZbnfParseResultItem> iterMethod = itemClass.iterChildren("methodDefinition"); 865 if(iterMethod != null) 866 { while(iterMethod.hasNext()) 867 { ZbnfParseResultItem itemMethod = iterMethod.next(); 868 write_methodDeclaration(itemMethod, sClassName, classData.classLevelIdents, uHeader); 869 } } 870 871 uHeader.append("\n} " + sClassName + "_i;\n \n"); 872 873 List<ZbnfParseResultItem> listSubClasses = itemClass.listChildren("classDefinition"); 874 if(listSubClasses != null) 875 { for(ZbnfParseResultItem itemSubClasses : listSubClasses) 876 { //runFirstPass(itemSubClasses, sClassName + "__", itemsxxx); 877 } 878 } 879 } 880 881 882 883 /**writes a method-forward-declaration in Headerfile and registers the method to generate definition. 884 * It calls 885 * 886 * @param zbnfMethod with syntax methodDefinition::=. 887 * @throws IOException 888 * @throws ParseException 889 * @throws InstantiationException 890 * @throws IllegalAccessException 891 * @throws IllegalArgumentException 892 */ 893 public void write_methodDeclaration(ZbnfParseResultItem zbnfMethod, String sClassName 894 , LocalIdents localIdents, StringBuilder uHeader) 895 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 896 { String sNameJava = zbnfMethod.getChild("name").getParsedString(); 897 if(sNameJava.equals("getData")) 898 stop(); 899 //if(!sName.equals("finalize")) //NOTE: finalize Method see write_finalizeDefinition() 900 { 901 //Method method = classData.searchMethod(sName + "?", null); 902 boolean bArgumentSensitive = classData.isAmbiguousnessMethod(sNameJava); //method.isAmbigous(); 903 ZbnfParseResultItem itemType = zbnfMethod.getChild("type"); 904 ZbnfParseResultItem zbnfDescription = zbnfMethod.getChild("description"); 905 ZbnfParseResultItem zbnfReturnDescription = zbnfDescription == null ? null : zbnfDescription.getChild("returnDescription"); 906 boolean bReturnNew = zbnfDescription != null && zbnfDescription.getChild("return-new")!= null; 907 char definitionCondition = bReturnNew ? 'n' : 'r'; 908 FieldData methodType = createFieldInfo(null, itemType, zbnfReturnDescription, zbnfMethod, null, localIdents, null, null, 'a', definitionCondition); 909 if(methodType.modeAccess=='&' || methodType.modeArrayElement=='&') 910 { /**A variable-definition of TypeMTB of the type is needed in this source. 911 * Registers the type for the class. 912 * The reference will be defined in the dst.h or dst.c at first. */ 913 classData.addMtblRefType(methodType.typeClazz.getClassIdentName(), 'a'); //to define the REF-Type. 914 } 915 Method method = gen_methodHeadAndRegisterMethod( 916 zbnfMethod 917 , 0 918 , classData 919 , classData 920 , sNameJava 921 , methodType //return-type 922 , null //argTypes-array uninitialized, because zbnfMethod is given. 923 , bArgumentSensitive 924 , false 925 ); 926 if(sNameJava.equals("finalize")){ 927 /**NOTE: finalize Method see write_finalizeDefinition()*/ 928 classData.setBodyForFinalize(zbnfMethod); 929 } 930 else { 931 uHeader.append(method.gen_MethodForwardDeclaration()); 932 } 933 ClassData.MethodWithZbnfItem methodDef = classData.new MethodWithZbnfItem(method, zbnfMethod, null, 'm'); 934 classData.methodsWithZbnf.add(methodDef); 935 936 } 937 } 938 939 940 941 942 /**writes a method-forward-declaration in Headerfile and registers the method to generate definition. 943 * It calls 944 * 945 * @param zbnfMethod with syntax methodDefinition::=. 946 * @throws IOException 947 * @throws ParseException 948 * @throws InstantiationException 949 * @throws IllegalAccessException 950 * @throws IllegalArgumentException 951 */ 952 public void write_methodInline(ZbnfParseResultItem zbnfMethod, String sClassName 953 , LocalIdents localIdents, StringBuilder uHeader) 954 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 955 { String sNameJava = zbnfMethod.getChild("name").getParsedString(); 956 if(sNameJava.equals("toString")) 957 stop(); 958 //Method method = classData.searchMethod(sName + "?", null); 959 boolean bArgumentSensitive = classData.isAmbiguousnessMethod(sNameJava); //method.isAmbigous(); 960 ZbnfParseResultItem itemType = zbnfMethod.getChild("type"); 961 ZbnfParseResultItem zbnfDescription = zbnfMethod.getChild("description"); 962 ZbnfParseResultItem zbnfReturnDescription = zbnfDescription == null ? null : zbnfDescription.getChild("returnDescription"); 963 boolean bReturnNew = zbnfDescription != null && zbnfDescription.getChild("return-new")!= null; 964 char definitionCondition = bReturnNew ? 'n' : 'r'; 965 FieldData methodType = createFieldInfo(null, itemType, zbnfReturnDescription, zbnfMethod, null, localIdents, null, null, 'a', definitionCondition); 966 Method method = gen_methodHeadAndRegisterMethod( 967 zbnfMethod 968 , Method.modeNoThCxt //a define does not need a ThCtx-Parameter 969 , classData 970 , classData 971 , sNameJava 972 , methodType //return-type 973 , null //argTypes-array uninitialized, because zbnfMethod is given. 974 , bArgumentSensitive 975 , true 976 ); 977 uHeader.append(method.gen_MethodDefinition()); 978 ZbnfParseResultItem zbnfBody = zbnfMethod.getChild("methodbody"); 979 StatementBlock statementBlockMethodFrame = new StatementBlock(this, method.getMethodIdents(), true, true, 1); 980 List<ZbnfParseResultItem> listStatements = zbnfBody.listChildren(); 981 if(listStatements.size() >=1){ 982 //only return statement ? 983 ZbnfParseResultItem zstm = listStatements.get(0); 984 ZbnfParseResultItem zret = zstm.getChild("return"); 985 ZbnfParseResultItem zretVal = zret == null ? null : zret.getChild("value"); 986 if(zretVal !=null){ 987 uHeader.append("("); 988 final CCodeData retValue = statementBlockMethodFrame.gen_value(zretVal, zbnfDescription, zbnfMethod, method.returnType.modeStatic=='r', 'e'); 989 String sRetValue = method.returnType.testAndcast(retValue, '.'); 990 uHeader.append(sRetValue); 991 uHeader.append(")"); 992 } else { 993 //uHeader.append("{ \\\n"); 994 String statements = statementBlockMethodFrame.gen_statementBlock(zbnfBody, null, 0, CRuntimeJavalikeClassData.clazz_void.classTypeInfo, this, 'h');; 995 uHeader.append(statements); 996 //uHeader.append("}\n"); 997 } 998 } else { 999 stop(); 1000 } 1001 uHeader.append("\n"); 1002 //String sBody = gen_statementBlock(zbnfBody, 1, statementBlockMethodFrame, method.returnType, 'm'); //it is a statementBlock 1003 1004 //ClassData.MethodWithZbnfItem methodDef = classData.new MethodWithZbnfItem(method, zbnfMethod, null, 'm'); 1005 //classData.methodsWithZbnf.add(methodDef); 1006 1007 } 1008 1009 1010 1011 1012 /**Generates a method head with syntax <code>methodDefinition::=</code> from given ZBNF parse result item 1013 * and registers the method in the classData. The ambiguousness of the method should be tested before this call, 1014 * but the unambiguous method name for C is built here: Methods with equal names but different parameter types 1015 * are different methods. 1016 * 1017 * @param zbnfMethod Zbnf item defined in <code><methodDefinition></code> 1018 * or <code><constructorDefinition></code>. The head hasn't an own zbnf-result item. 1019 * The following contained elements are tested: 1020 * <ul> 1021 * <li><code><description></code>, calling {@link #get_shortDescription(ZbnfParseResultItem)} 1022 * <li><code><static></code> defined in <code>Modifier::=<?></code> 1023 * <li><code><argumentList></code>, calling {@link #gen_methodArguments(ZbnfParseResultItem, LocalIdents, char, String[], List)} 1024 * </ul> 1025 * If this argument is null, a default constructor is generated. 1026 * @param modeMethod start value for {@link Method#mode}, addtional bits are set from zbnfMethod 1027 * Especially checked: {@link Method#modeCtor}, {@link Method#modeCtorNonStatic} 1028 * xxx@param ctor '.' if it isn't a ctor, 'C'-static ctor of class 'n'-ctor of non-static inner class. 'y'-ctor of anonymous class 1029 * @param classContainsMethod environment class, for non-static constructors the outer class. 1030 * @param classMethodBody 1031 * @param sMethodNameJava Name of the method, "ctorO" if a constructor from given ObjectJc should be generated. 1032 * @param typeReturn Type of the method, get outside because this routine is also used to generate constructors. 1033 * On constructor generation this argument should be equal the environment class type. 1034 * @param argTypes 1035 * @param bArgumentSensitive true than more as one method with the same Java-name exists. 1036 * It is tested before calling {@link ClassData#isAmbiguousnessMethod(String)}. 1037 * The C-name of the method is built regarding the type of the arguments. 1038 * @param bDefine 1039 * @return The created Method. It contains the head definition in one line in its private attribute 1040 * {@link Method#sMethodFormalListDefiniton} 1041 * promoted in {@link Method#gen_MethodForwardDeclaration()} and 1042 * {@link Method#gen_MethodHeadDefinition()}. 1043 * @throws IOException 1044 * @throws ParseException 1045 * @throws InstantiationException 1046 * @throws IllegalAccessException 1047 * @throws IllegalArgumentException 1048 */ 1049 Method gen_methodHeadAndRegisterMethod 1050 ( ZbnfParseResultItem zbnfMethod 1051 , int modeMethod 1052 , ClassData classContainsMethod 1053 , ClassData classMethodBody 1054 , String sMethodNameJava 1055 , FieldData typeReturn 1056 , FieldData[] argTypes 1057 , boolean bArgumentSensitive 1058 , boolean bDefine 1059 ) 1060 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 1061 { LocalIdents methodIdents = new LocalIdents(classMethodBody.classLevelIdents, null); 1062 ZbnfParseResultItem zbnfDescription = zbnfMethod == null ? null : zbnfMethod.getChild("description"); 1063 String sDescription = zbnfMethod!=null ? get_shortDescription(zbnfDescription) : "Default constructor. "; 1064 //assert(classOfMethod == classData); //the argument classOfMethod is unnecessary. 1065 String sNameUnambiguous = sMethodNameJava; 1066 String sArguments; 1067 String sClassName = classContainsMethod.getClassIdentName(); 1068 String sMethodClassType_s = classContainsMethod.getClassCtype_s(); 1069 if(sMethodNameJava.equals("specifyLengthElement")) // && sClassName.equals("LogMessageFile_MSG")) 1070 stop(); 1071 final boolean isStatic = (zbnfMethod !=null && zbnfMethod.getChild("static") != null) 1072 || (((modeMethod & Method.modeCtor) !=0) && ((modeMethod & Method.modeCtorNonStatic)==0)); 1073 final boolean bFinal = zbnfMethod ==null || zbnfMethod.getChild("final")!=null; 1074 if(bFinal) 1075 stop(); 1076 int modifier = modeMethod; 1077 if( classContainsMethod.isInterface() 1078 ||( !sMethodNameJava.startsWith("ctor") 1079 && !bFinal //final keyword on method 1080 && !isStatic 1081 && !classContainsMethod.isFinal //if the class is final, its methods can't be overridden 1082 ) ) 1083 { //dynamic called method. 1084 modifier |= Method.modeOverrideable; 1085 } 1086 if(isStatic){ //static keyword or static ctor 1087 modifier |= Method.modeStatic; 1088 } 1089 if(zbnfDescription != null){ 1090 //if(zbnfDescription.getChild("override-able")!= null){ modifier |= Method.modeOverrideable;} 1091 if(zbnfDescription.getChild("return-this")!= null) { modifier |= Method.modeReturnThis; } 1092 if(zbnfDescription.getChild("return-new")!= null) { modifier |= Method.modeReturnNew; } 1093 if(zbnfDescription.getChild("noStacktrace")!= null) { modifier |= (Method.modeNoStacktrace | Method.modeNoThCxt); } 1094 if(zbnfDescription.getChild("noThCxt")!= null) { modifier |= Method.modeNoThCxt; } 1095 } 1096 if(argTypes == null && zbnfMethod!=null) //not the default constructor 1097 { //NOTE: call without zbnfMethod if a default ctor is created. 1098 String[] sArgSensitive = bArgumentSensitive ? new String[1] : null; 1099 List<FieldData> listArgTypes = new LinkedList<FieldData>(); //more than 30 args are not expected. 1100 char intensionArgument = 'a'; //(intension == 'h') ? 'A' : 'a'; //declaration or definition list. 1101 sArguments = gen_methodArguments(zbnfMethod, methodIdents, intensionArgument, sArgSensitive, listArgTypes); 1102 if(bArgumentSensitive && sArgSensitive[0].length() >0) 1103 { sNameUnambiguous += "_" + sArgSensitive[0]; 1104 } 1105 if(listArgTypes != null && listArgTypes.size() >0) 1106 { argTypes = new FieldData[listArgTypes.size()]; 1107 listArgTypes.toArray(argTypes); 1108 } 1109 else 1110 { argTypes = null; 1111 } 1112 } 1113 else if(argTypes != null){ 1114 StringBuilder uArguments = new StringBuilder(100); 1115 String sSeparator = ""; 1116 for(FieldData argType: argTypes){ 1117 uArguments.append(sSeparator).append(argType.getTypeName()).append(" ").append(argType.getName()); 1118 sSeparator = ", "; 1119 } 1120 sArguments = uArguments.toString(); 1121 } else { 1122 sArguments = ""; 1123 } 1124 1125 final Method methodData = classContainsMethod.addMethod( sMethodNameJava, sNameUnambiguous 1126 , modifier, typeReturn, argTypes); 1127 1128 methodData.setMethodIdents(methodIdents); //classLevelIdents plus arguments. 1129 String sTypeReturn = typeReturn.gen_Declaration(writeContent); 1130 String sMethodHead = "("; //use the really name. 1131 String sSep = ", "; 1132 //if(sMethodNameJava.equals("ctorO")) 1133 if( (modeMethod & Method.modeCtor) != 0) //if it is a ctor 1134 { if((modeMethod & Method.modeCtorNonStatic) != 0){ 1135 //ctor of non-static or anonymous class 1136 sMethodHead += "struct " + classContainsMethod.getClassIdentName() + "_t* outer, "; 1137 } 1138 //ClassData outerClass = classData.getOuterClass(); 1139 //if(outerClass!=null && !classData.isStaticInner){ 1140 // sMethodHead += outerClass.getClassCtype_s() + "* ythis, "; 1141 //} 1142 if(classData.isBasedOnObject()){ 1143 sMethodHead += "ObjectJc* othis"; 1144 } else { 1145 sMethodHead += "MemC mthis"; 1146 } 1147 } 1148 else if(methodData.firstDeclaringClass.isInterface()) 1149 { /**An overridden method of an interface-declared method. */ 1150 sMethodHead += "ObjectJc* ithis"; //Note: all interface methods are called with an Object-reference. 1151 } 1152 else if(methodData.firstDeclaringClass != classContainsMethod) 1153 { /**An overridden method of an superclass-declared method. */ 1154 sMethodHead += methodData.firstDeclaringClass.getClassCtype_s() + "* ithis"; 1155 } 1156 else if(!isStatic) 1157 { sMethodHead += sMethodClassType_s + "* thiz"; 1158 } 1159 else 1160 { sMethodHead += "/*static*/ "; 1161 sSep = ""; 1162 } 1163 if(sArguments.length() >0){ 1164 sMethodHead += sSep + sArguments; 1165 sSep = ", "; 1166 } 1167 if(methodData.need_thCxt){ 1168 sMethodHead += sSep + "ThCxt* _thCxt)"; 1169 } 1170 else{ 1171 sMethodHead += ")"; 1172 } 1173 1174 methodData.setMethodHeadDefiniton(sDescription, sTypeReturn, sMethodHead); 1175 1176 return methodData; 1177 } 1178 1179 1180 1181 1182 1183 /**Generates the formal argument list of a method used both by generating method declaration or method definition. 1184 * @param zbnfMethod Zbnf item defined in <code>argumentList::=<?>...</code>. 1185 * @param localIdents The known identificators of the calling environment, the type identificators are used especially. 1186 * This parameter is used calling {@link #gen_variableDefinition(ZbnfParseResultItem, LocalIdents, List, char intension, ClassData[])} 1187 * inside with the parameters of the head. If the intension=='a' (Method definition in C-File),the parameter-variables are added to the localIdents. 1188 * @param intension Intension of call: 'A'-declaration in h-File, 'a'-definition in c-file, passing on <code>gen_variableDefinition()</code>. 1189 * @param retArgSensitiveName [0] is filled with the short name of arg types if not null. 1190 * @param retArgTypes The list is filled with the detect argument types, used for argument sensitive method call. 1191 * @return String of formal arguments. 1192 * @throws ParseException 1193 * @throws InstantiationException 1194 * @throws IllegalAccessException 1195 * @throws IOException 1196 * @throws IllegalArgumentException 1197 * @throws FileNotFoundException 1198 */ 1199 String gen_methodArguments 1200 ( ZbnfParseResultItem zbnfMethod 1201 , LocalIdents localIdents 1202 , char intension 1203 , String[] retArgSensitiveName 1204 , List<FieldData> retArgTypes 1205 ) 1206 throws ParseException, FileNotFoundException, IllegalArgumentException, IOException, IllegalAccessException, InstantiationException 1207 { final Map<String, ZbnfParseResultItem> indexParamDescription; 1208 ZbnfParseResultItem zbnfDescription = zbnfMethod.getChild("description"); 1209 if(zbnfDescription != null) /**Creates a Map sorted by parameter name with param description: */ 1210 { final List<ZbnfParseResultItem> listZbnfParamDescription = zbnfDescription.listChildren("param"); 1211 if(listZbnfParamDescription != null) 1212 { indexParamDescription = new TreeMap<String, ZbnfParseResultItem>(); 1213 for(ZbnfParseResultItem zbnfParamDescription: listZbnfParamDescription) 1214 { String sName = zbnfParamDescription.getChild("variableName").getParsedString(); 1215 indexParamDescription.put(sName, zbnfParamDescription); 1216 } 1217 } 1218 else { indexParamDescription = null; } 1219 } 1220 else { indexParamDescription = null; } 1221 1222 Iterator<ZbnfParseResultItem> iterParam = zbnfMethod.iterChildren("argument"); 1223 boolean bArgumentSensitive = (retArgSensitiveName != null); 1224 String sArgs = ""; 1225 String sArgSensitiveName = ""; 1226 String sArgSeparator = ""; 1227 if(iterParam != null) 1228 { byte idxArg = 0; 1229 boolean bFirst = true; 1230 while(iterParam.hasNext()) 1231 { ZbnfParseResultItem zbnfParam = iterParam.next(); 1232 String sName = zbnfParam.getChild("variableName").getParsedString(); 1233 ZbnfParseResultItem zbnfParamDescription = indexParamDescription == null ? null : indexParamDescription.get(sName); 1234 if(zbnfParamDescription != null) 1235 stop(); 1236 if(sName.equals("args")) 1237 stop(); 1238 CCodeData codeArg = gen_variableDefinition( 1239 zbnfParam 1240 , zbnfParamDescription 1241 , localIdents 1242 , null //blockEnvironment unused because no intial values possible. 1243 , null 1244 , intension 1245 ); 1246 //sArgs += sArgSeparator + sArg; 1247 if(bFirst){ 1248 bFirst = false; 1249 } else { 1250 sArgs += ", "; 1251 } 1252 sArgs += codeArg.cCode; 1253 if(bArgumentSensitive) 1254 { //sArgSensitiveName += typeVariable[0].sArgSensitiveName; 1255 sArgSensitiveName += codeArg.identInfo.typeClazz.sArgSensitiveName; 1256 int dimension = codeArg.identInfo.getDimensionArray(); 1257 while(dimension >0) 1258 { dimension -=1; 1259 sArgSensitiveName += "Y"; //array 1260 } 1261 } 1262 if(retArgTypes != null) { retArgTypes.add(codeArg.identInfo); } 1263 idxArg +=1; 1264 sArgSeparator = ", "; 1265 } 1266 } 1267 if(bArgumentSensitive){ retArgSensitiveName[0] = sArgSensitiveName; } 1268 return sArgs; 1269 } 1270 1271 1272 1273 1274 1275 1276}