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 2008-04-06 (year-month-day) 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.BufferedWriter; 030import java.io.File; 031import java.io.FileOutputStream; 032import java.io.FileWriter; 033import java.io.IOException; 034import java.io.OutputStreamWriter; 035import java.text.ParseException; 036import java.util.Iterator; 037import java.util.LinkedList; 038import java.util.List; 039import java.util.Map; 040import java.util.Set; 041import java.util.TreeMap; 042 043import org.vishia.mainCmd.Report; 044import org.vishia.util.FileSystem; 045import org.vishia.zbnf.ZbnfParseResultItem; 046 047/**This class processes the first and second pass of translating Java to C of a java file. 048 * Parsing the content of the java file is done before it processed, see {@link Java2C_Main}. 049 * 050 * @author JcHartmut 051 * 052 */ 053public class GenerateFile implements iWriteContent 054{ 055 /**Version, history and license. 056 * <ul> 057 * <li>2014-08-16 Hartmut new: writes <code>#include "Fwc/fw_MemC.h"</code> in any header. 058 * <li>2014-08-16 Hartmut new: invoke {@link FirstPass#gatherAllDefinitions()} before {@link FirstPass#runFirstPass2(StringBuilder)}. 059 * <li>2008 Hartmut created: 060 * </ul> 061 * <br><br> 062 * <b>Copyright/Copyleft</b>: 063 * For this source the LGPL Lesser General Public License, 064 * published by the Free Software Foundation is valid. 065 * It means: 066 * <ol> 067 * <li> You can use this source without any restriction for any desired purpose. 068 * <li> You can redistribute copies of this source to everybody. 069 * <li> Every user of this source, also the user of redistribute copies 070 * with or without payment, must accept this license for further using. 071 * <li> But the LPGL is not appropriate for a whole software product, 072 * if this source is only a part of them. It means, the user 073 * must publish this part of source, 074 * but don't need to publish the whole source of the own product. 075 * <li> You can study and modify (improve) this source 076 * for own using or for redistribution, but you have to license the 077 * modified sources likewise under this LGPL Lesser General Public License. 078 * You mustn't delete this Copyright/Copyleft inscription in this source file. 079 * </ol> 080 * If you are intent to use this sources without publishing its usage, you can get 081 * a second license subscribing a special contract with the author. 082 * 083 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 084 */ 085 public final static String sVersion = "2014-09-05"; 086 087 private final Report report; 088 089 /**Name without path and extension of the c- and h-file from java file. */ 090 final String sFileNameC; 091 092 final JavaSrcTreeFile javaSrc; 093 094 /**Package where the Java file is stored, with <code>/</code> as separators and at end. 095 * This information is got in {@link #runFirstPass(ZbnfParseResultItem, LocalIdents, String, File)} 096 * from the <code>package</code>-declaration in the Java file. The dots <code>.</code> in Java file 097 * are translated to slash <code>/</code> here. 098 * */ 099 String sPkgIdent; 100 101 /**lines for c file mapping the definitions in the C-file before the content of the bodies, 102 * see {@link sClassC}. */ 103 private final StringBuilder uFileCDefinitions = new StringBuilder(10000) ; 104 105 /**lines for c file mapping the definitions in the C-file before the content of the bodies, 106 * see {@link sClassC}. */ 107 private final StringBuilder uFileCSecondPath = new StringBuilder(100000) ; 108 109 /**lines for c file mapping the definitions in the C-file before the content of the bodies, 110 * see {@link sClassC}. */ 111 private final StringBuilder uFileHDefinitions = new StringBuilder(10000) ; 112 113 /**lines for c file mapping the class content. */ 114 //private String sClassC = "" ; 115 116 private final JavaSources javaSources; 117 118 //private JavaSrcTreePkg itsPkg; 119 120 /**Copy of the reference from {@link #javaSrc}.{@link JavaSrcTreeFile#itsPkg}.{@link JavaSrcTreePkg.pkgIdents} 121 * for faster access. 122 */ 123 private final LocalIdents pkgIdents; 124 125 /**All Type identifier ({@link ClassData} which are visible at file level. It contains all classes 126 * which are imported in this file. It doesn't contain the package visible identifier, see 127 * 128 */ 129 private final LocalIdents fileLevelIdents = new LocalIdents("~/"); 130 131 /**Index of all classes from which an enhanced reference is need in this compilation unit. 132 * Enhanced references are used for backward references for garbage collection and to store 133 * an index to the method table. 134 * NOTE: the second part of Map, the Object, isn't necessary. Only the unique registering is necessary.*/ 135 private final Map<String, Object> usedEnhancedRefTypes = new TreeMap<String, Object>(); 136 137 /**Index of all classes from which an method-table reference is need in the header file. 138 * Method-table-references are used to work with dynamic call, 139 * the method table pointer and the instance pointer are contained there. 140 * NOTE: the second part of Map, the Object, isn't necessary. Only the unique registering is necessary.*/ 141 private final Map<String, Object> usedMtblRefTypesH = new TreeMap<String, Object>(); 142 143 /**Index of all classes from which an method-table reference is need in this compilation unit. 144 * Method-table-references are used to work with dynamic call, 145 * the method table pointer and the instance pointer are contained there. 146 * NOTE: the second part of Map, the Object, isn't necessary. Only the unique registering is necessary.*/ 147 private final Map<String, Object> usedMtblRefTypesC = new TreeMap<String, Object>(); 148 149 /**Index of all forward declared struct types. 150 * String: The struct name with _s if need 151 * Character: 'h' and 'c' for header and c-file. */ 152 private final Map<String, Character> usedStructForward = new TreeMap<String, Character>(); 153 154 /**The file descriptor for the structure file. 155 */ 156 private final File fileStruct; 157 158 /**List of all classes in the file. Inner classes are not stored here. 159 * Typically only one class is found in file. 160 * This information is used locally only at example to write all structure informations of classes in file*/ 161 private final List<ClassData> listClassInFile = new LinkedList<ClassData>(); 162 163 /**The interface to call a firstpass run of a needed type. */ 164 final RunRequiredFirstPass_ifc runRequiredFirstPass; 165 166 167 /**All include declarations necessary in the C-file of this java file. 168 * The list will be filled also while running the second path. 169 */ 170 private final TreeMap<String, String> includes = new TreeMap<String, String>(); 171 172 private final TreeMap<String, String> imports = new TreeMap<String, String>(); 173 174 /**List of all classes found in this file. This list is used to control, for which classes 175 * the second path is to be run. The list contains inner classes also. 176 * That is because inner classes are translated to plain <code>typedef struct...</code> and plan C-routines. 177 */ 178 final List<ClassData> listAllClassesForSecondPath = new LinkedList<ClassData>(); 179 180 181 /**True if the first pass runs. false on second pass. */ 182 private boolean isFirstPass; 183 184 185 186 187 /**initializes the instances with the given associations. */ 188 GenerateFile(JavaSources javaSources, JavaSrcTreeFile javaSrc 189 , RunRequiredFirstPass_ifc runRequiredFirstPass 190 , File fileStruct, Report report) 191 { this.fileStruct = fileStruct; 192 this.report = report; 193 this.javaSources = javaSources; 194 this.javaSrc = javaSrc; 195 this.pkgIdents = javaSrc.getPkgLevelTypes(); 196 this.sFileNameC = javaSrc.getFileNameC(); 197 this.runRequiredFirstPass = runRequiredFirstPass; 198 assert(sFileNameC !=null); 199 } 200 201 202 @Override public void setFirstPass(boolean isFirstPass) 203 { this.isFirstPass = isFirstPass; 204 } 205 206 /**Adds a text to the C-definition-code 207 */ 208 @Override public void writeCdefs(StringBuilder content) 209 { uFileCDefinitions.append(content); 210 } 211 212 /**Adds a text to the H-code 213 */ 214 @Override public void writeHdefs(StringBuilder content) 215 { uFileHDefinitions.append(content); 216 } 217 218 /**Adds a text to the C-code 219 * @see org.vishia.java2C.iWriteContent#writeClassC(java.lang.String) 220 */ 221 @Override public void writeClassC(String content) 222 { uFileCSecondPath.append( content); 223 } 224 225 /**Adds a text to the C-code 226 * @see org.vishia.java2C.iWriteContent#writeClassC(java.lang.StringBuilder) 227 */ 228 @Override public void writeClassC(StringBuilder content) 229 { uFileCSecondPath.append( content); 230 } 231 232 /**Adds a text to the Headerfile-code 233 * @see org.vishia.java2C.iWriteContent#writeClassH(java.lang.String) 234 */ 235 public void writeClassH(String line) 236 { uFileHDefinitions.append(line); 237 } 238 239 240 /**Adds a type to include the type-correspondent h-file in the c-file. */ 241 /* @see org.vishia.java2C.iWriteContent#addIncludeC(java.lang.String, java.lang.String) 242 */ 243 public void addIncludeC(String sFileName, String comment) 244 { if(sFileName == null) 245 stop(); 246 if(sFileName !=null //it is null on clazz_s0 247 && !sFileName.equals(this.sFileNameC)) //don't include itself. 248 { if(sFileName.equals("DispatcherThread")) 249 stop(); 250 if(includes.get(sFileName) == null) 251 { includes.put(sFileName, "c" + comment); //not put if addIncludesH will be called before. 252 } 253 } 254 } 255 256 /**Adds a type to include the type-correspondent h-file in the h-file. */ 257 public void addIncludeH(String sFileName, String comment) 258 { if(sFileName !=null //null on standard types 259 && !sFileName.equals(this.sFileNameC)) //don't include itself. 260 { if(sFileName.equals("MsgDispatcher_MSG")) 261 stop(); 262 includes.put(sFileName, "h" + comment); 263 } 264 } 265 266 267 268 private String unusedyet_getImport(String sType) 269 { return imports.get(sType); 270 } 271 272 273 274 275 276 277 /**Generates the content of all classes in the h-file with given ZBNF parse result item of the class. 278 * This routine is called from {@link Java2C_Main}. 279 * <br> 280 * First the h-file-content of all classes are generated into StringBuffer. If all runFirstPass 281 * of all found classes are done, the file will be written. First the necessary includes will be written 282 * in the destination h-file. Therefore the runFirstPass of all classes should be done before. 283 * 284 * @param resultItem The first result item of ZBNF parsing of the whole java-File. 285 * @param pkgIdents Global map of all classes of the whole translating process. 286 * @param sPathOut output path for the h- and c-file, with slash on end 287 * @throws IOException 288 * @throws ParseException 289 * @throws InstantiationException 290 * @throws IllegalAccessException 291 * @throws IllegalArgumentException 292 */ 293 void runFirstPassFile(ZbnfParseResultItem resultItem, String sPrefixClassCname, String sSuffixClassCname) 294 throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 295 { //while(resultItem != null) 296 ZbnfParseResultItem zbnfPkg = resultItem.getChild("PackageDefinition"); 297 { String pkg = ""; 298 Iterator<ZbnfParseResultItem> iterZbnfPkgName = zbnfPkg.iterChildren("packageClassName"); 299 while(iterZbnfPkgName.hasNext()) 300 { pkg += iterZbnfPkgName.next().getParsedString() + "/"; 301 } 302 sPkgIdent = pkg; //.substring(0, pkg.length()-1); //without last dot. 303 } 304 /**Copy all pkgIdents to fileLevelIdents initially, additional put the pkgIdents of import packages 305 * and Idents of all imported classes:*/ 306 { fileLevelIdents.putClassTypesAll(pkgIdents); 307 evaluateImports(resultItem); 308 } 309 String sourceOfClassData = this.javaSrc.getFileJava().getAbsolutePath(); 310 Iterator<ZbnfParseResultItem> iter= resultItem.iterChildren("classDefinition"); 311 while(iter != null && iter.hasNext()) 312 { resultItem = iter.next(); 313 String sSemantic = resultItem.getSemantic(); 314 boolean bInterface = sSemantic.equals("interfaceDefinition"); 315 if(sSemantic.equals("classDefinition") || bInterface) 316 { FirstPass genClass = new FirstPass(this, this, fileLevelIdents, runRequiredFirstPass, report); 317 StringBuilder uResult = new StringBuilder(10000); //will be increased if necessary. 318 ClassData classData = genClass.buildType( 319 uResult 320 , sourceOfClassData 321 , this 322 , sFileNameC 323 , sPkgIdent 324 , sPrefixClassCname, sSuffixClassCname 325 , resultItem //the ZbnfParseResultItem of the class 326 , false //write constructors, at least a default constructor 327 , "" 328 , null //no outer class 329 , listAllClassesForSecondPath //to add this class and sub classes if found 330 , bInterface 331 , null 332 , 'P' 333 ); 334 genClass.classData.completeTypesForInnerClasses(); 335 //Now run the first pass of the class. 336 genClass.gatherAllDefinitions(); 337 genClass.runFirstPass2(uResult); 338 339 writeClassH(uResult.toString()); //TODO inner classes in body: write in the C-file. 340 classData.reportContent(report, Report.fineInfo); 341 } 342 //resultItem = resultItem.next(null); 343 } 344 iter= resultItem.iterChildren("interfaceDefinition"); 345 while(iter != null && iter.hasNext()) 346 { resultItem = iter.next(); 347 String sSemantic = resultItem.getSemantic(); 348 if(sSemantic.equals("classDefinition") || sSemantic.equals("interfaceDefinition")) 349 { FirstPass genClass = new FirstPass(this, this, fileLevelIdents, runRequiredFirstPass, report); 350 StringBuilder uResult = new StringBuilder(10000); //will be increased if necessary. 351 ClassData classData = genClass.buildType 352 ( uResult, sourceOfClassData, this, sFileNameC, sPkgIdent, sPrefixClassCname, sSuffixClassCname 353 , resultItem //the ZbnfParseResultItem of the class 354 , true //don't write the default constructor 355 , "" 356 , null //no outer class 357 , listAllClassesForSecondPath //to add this class and sub classes if found 358 , true //interface 359 , null 360 , 'F' //intension: file level, Top-level-class 361 ); 362 //Now run the first pass of the class. 363 genClass.gatherAllDefinitions(); 364 genClass.runFirstPass2(uResult); 365 writeClassH(uResult.toString()); //TODO inner classes in body: write in the C-file. 366 classData.reportContent(report, Report.fineInfo); 367 } 368 } 369 370 /**created header and c file. */ 371 BufferedWriter fileH; //, fileC; 372 { String sPathOut = Java2C_Main.singleton.getPathOutHeader(); 373 FileSystem.mkDirPath(sPathOut + sFileNameC); //create directory if not exists. 374 fileH = new BufferedWriter(new FileWriter(new File(sPathOut + sFileNameC + ".h"))); 375 } 376 String sFileNameIncludedef = "__" + sFileNameC.replace('/', '_') + "_h__"; 377 378 fileH.write("/**************************************************************************\n"); 379 fileH.write(" * This file is generated by Java2C\n"); 380 fileH.write(" **copyright***************************************************************\n"); 381 fileH.write(" *************************************************************************/\n"); 382 fileH.write("#ifndef " + sFileNameIncludedef + "\n"); 383 fileH.write("#define " + sFileNameIncludedef + "\n"); 384 fileH.write("\n#include \"Fwc/fw_MemC.h\" //basic concept\n"); 385 fileH.write("\n#include \"Jc/ObjectJc.h\" //basic concept\n"); 386 fileH.write("\n#include \"Jc/StringJc.h\" //used often\n"); 387 fileH.write("\n#include \"Fwc/fw_Exception.h\" //basic concept\n"); 388 //fileH.write("\n#include \"" + Java2C_Main.singleton.getFileAllReferences() + "\"\n"); 389 390 Set<Map.Entry<String,Character>> listUsedStructForward = usedStructForward.entrySet(); 391 if(listUsedStructForward.size() >0) 392 { fileH.write("\n\n/* J2C: Forward declaration of struct ***********************************************/\n"); 393 for(Map.Entry<String, Character> usedType: listUsedStructForward) 394 { 395 fileH.write("struct " + usedType.getKey() + "_t;\n"); 396 } 397 } 398 399 Set<Map.Entry<String,Object>> listUsedEnhancedRefTypes = usedEnhancedRefTypes.entrySet(); 400 if(listUsedEnhancedRefTypes.size() >0) 401 { 402 fileH.write("\n\n/* J2C: Enhanced references *********************************************************"); 403 fileH.write("\n * In this part all here used enhanced references are defined conditionally."); 404 fileH.write("\n * The inclusion of all that header files isn't necessary, to prevent circular inclusion."); 405 fileH.write("\n * It is adequate a struct pointer forward declaration."); 406 fileH.write("\n */"); 407 for(Map.Entry<String,Object> usedType: listUsedEnhancedRefTypes) 408 { 409 String sRef = usedType.getKey(); 410 fileH.write("\n#ifndef " + sRef + "REFDEF"); 411 fileH.write("\n //J2C: definition of enhanced reference where it was need firstly: "); 412 fileH.write("\n #define " + sRef + "REFDEF"); 413 //fileH.write("\n typedef struct " + sRef + "REF_t { ObjectRefValuesJc refbase; struct " + sRef + "_t* ref; } " + sRef + "REF;"); 414 fileH.write("\n struct " + sRef + "_t;"); 415 /* 416 fileH.write("\n #ifdef STRUCT_REFJc"); 417 fileH.write("\n //J2C: macro STRUCT_REFJc should be defined in <fw_Platform_conventions.h> "); 418 fileH.write("\n typedef struct " + sRef + "REF_t STRUCT_REFJc(struct " + sRef + "_t) " + sRef + "REF;"); 419 fileH.write("\n #else"); 420 fileH.write("\n //J2C: simple reference instead enhanced reference if macro is not defined"); 421 fileH.write("\n #define " + sRef + "REF struct " + sRef + "_t* "); 422 fileH.write("\n #endif"); 423 */ 424 fileH.write("\n DEFINE_EnhancedRefJc(" + sRef + ");"); 425 fileH.write("\n#endif"); 426 } 427 fileH.write("\n"); 428 } 429 430 Set<Map.Entry<String,Object>> listUsedMtblRefTypes = usedMtblRefTypesH.entrySet(); 431 if(listUsedMtblRefTypes.size() >0) 432 { fileH.write("\n\n/* J2C: Method-table-references *********************************************************/"); 433 for(Map.Entry<String,Object> usedType: listUsedMtblRefTypes) 434 { 435 String sRef = usedType.getKey(); 436 fileH.write("\n#ifndef " + sRef + "MTBDEF"); 437 fileH.write("\n #define " + sRef + "MTBDEF"); 438 fileH.write("\n typedef struct " + sRef + "MTB_t { struct Mtbl_" + sRef + "_t const* mtbl; struct " + sRef + "_t* ref; } " + sRef + "MTB;"); 439 fileH.write("\n#endif\n"); 440 } 441 fileH.write("\n"); 442 } 443 444 445 446 //write includes: 447 if(sFileNameC.equals("MainController")) 448 stop(); 449 Set<Map.Entry<String, String>> listIncludeTypes = includes.entrySet(); 450 fileH.write("\n\n/* J2C: includes *********************************************************/\n"); 451 for(Map.Entry<String, String> entry: listIncludeTypes) 452 { String sType = entry.getKey(); 453 String sValue = entry.getValue(); 454 if(sValue.startsWith("h")) 455 { final String sComment = sValue.length() >1 ? " //" + sValue.substring(1) : ""; 456 fileH.write("#include \"" + sType + ".h\"" + sComment + "\n"); 457 } 458 } 459 460 //fileH.write(sIncludeH); 461 fileH.append(uFileHDefinitions); 462 fileH.write("#endif //" + sFileNameIncludedef + "\n"); 463 fileH.flush(); 464 465 } 466 467 468 469 void registerClassInFile(ClassData classData) 470 { 471 if(classData.getClassNameJava().equals(javaSrc.getTypeName())){ 472 /**The public class of the file is translated: set the classData. */ 473 javaSrc.setClassData(classData); 474 } else { 475 /**Additional classes in the file are found. They were unknown until now, register it. */ 476 pkgIdents.putClassType(classData); //replace JavaSrcFile with ClassData! 477 fileLevelIdents.putClassType(classData.sClassNameJava, classData); 478 } 479 listClassInFile.add(classData); 480 481 } 482 483 484 485 486 /**Generates the content of a class in the c-file. The class field {@link listAllClassesForSecondPath} 487 * is filled while running the first pass and contains all classes found in the java file. 488 * The ZBNF parse result item of each class is stored there. 489 * This routine is called from {@link Java2C_Main}. 490 * <br> 491 * First the c-file-content of all classes are generated into the StringBuffer {@link sClassC}. 492 * If all runSecondPass of all found classes are done, the file will be written. 493 * First the necessary includes will be written 494 * in the destination c-file. Therefore the runSecondPass of all classes should be done before. 495 * @param pkgIdents Global map of all classes of the whole translating process. 496 * @throws IOException 497 * @throws ParseException 498 * @throws InstantiationException 499 * @throws IllegalAccessException 500 * @throws IllegalArgumentException 501 */ 502 //void runSecondPass(TreeMap<String, ClassData> pkgIdents) throws IOException, ParseException 503 void runSecondPassFile() throws IOException, ParseException, IllegalArgumentException, IllegalAccessException, InstantiationException 504 { 505 506 507 //sClassC = ""; 508 509 for(ClassData classData: listAllClassesForSecondPath) 510 { ZbnfParseResultItem itemClass = classData.getParseResult(); 511 SecondPass genClass = new SecondPass(this, this, fileLevelIdents, classData, runRequiredFirstPass, report); 512 genClass.runSecondPassClass(itemClass, ""); 513 classData.relinquishParseResult(); 514 } 515 516 517 /**created c file. */ 518 BufferedWriter fileC; 519 String sPathOut = Java2C_Main.singleton.getPathOutCfiles(); 520 fileC = new BufferedWriter(new FileWriter(new File(sPathOut + sFileNameC + ".c"))); 521 fileC.write("/**************************************************************************\n"); 522 fileC.write(" * This file is generated by Java2C\n"); 523 fileC.write(" **copyright***************************************************************\n"); 524 fileC.write(" *************************************************************************/\n"); 525 fileC.write("#include \"" + sFileNameC + ".h\"\n"); 526 fileC.write("#include <string.h> //because using memset()\n"); 527 fileC.write("#include <Jc/ReflectionJc.h> //Reflection concept \n"); 528 fileC.write("#include <Fwc/fw_Exception.h> //basic stacktrace concept\n"); 529 fileC.flush(); 530 //write includes: 531 if(sFileNameC.equals("MainController")) 532 stop(); 533 Set<Map.Entry<String, String>> listIncludeTypes = includes.entrySet(); 534 for(Map.Entry<String, String> entry: listIncludeTypes) 535 { String sType = entry.getKey(); 536 String sValue = entry.getValue(); 537 if(sValue.startsWith("c")) 538 { final String sComment = sValue.length() >1 ? " //" + sValue.substring(1) : ""; 539 fileC.write("#include \"" + sType + ".h\"" + sComment + "\n"); 540 } 541 } 542 543 Set<Map.Entry<String,Character>> listUsedStructForward = usedStructForward.entrySet(); 544 if(listUsedStructForward.size() >0) 545 { fileC.write("\n\n/* J2C: Forward declaration of struct ***********************************************/\n"); 546 for(Map.Entry<String, Character> usedType: listUsedStructForward) 547 { char cFile = usedType.getValue().charValue(); 548 if(cFile == 'c'){ //write only that struct, which are new in C-file. 549 fileC.write("struct " + usedType.getKey() + "_t;\n"); 550 } 551 } 552 } 553 554 Set<Map.Entry<String,Object>> listUsedMtblRefTypes = usedMtblRefTypesC.entrySet(); 555 if(listUsedMtblRefTypes.size() >0) 556 { fileC.write("\n\n/* J2C: Method-table-references *********************************************************/"); 557 for(Map.Entry<String,Object> usedType: listUsedMtblRefTypes) 558 { 559 String sRef = usedType.getKey(); 560 fileC.write("\n#ifndef " + sRef + "MTBDEF"); 561 fileC.write("\n #define " + sRef + "MTBDEF"); 562 fileC.write("\n typedef struct " + sRef + "MTB_t { struct Mtbl_" + sRef + "_t const* mtbl; struct " + sRef + "_t* ref; } " + sRef + "MTB;"); 563 fileC.write("\n#endif\n"); 564 } 565 fileC.write("\n"); 566 } 567 fileC.append(uFileCDefinitions); 568 fileC.append(uFileCSecondPath); 569 fileC.flush(); 570 writeStructure(fileStruct, sFileNameC, listClassInFile, sPkgIdent); 571 } 572 573 574 575 576 577 578 /**If a type is used as enhanced reference in the code of the class, it is noted here. 579 * The information will be used to define the enhanced references in the Headerfile, 580 * it is also transformed to the stc file. (?) 581 * @param sRefType The referenced type. 582 */ 583 public void addEnhancedRefType(String sRefType) 584 { 585 usedEnhancedRefTypes.put(sRefType, sRefType); 586 } 587 588 /**If a type is used as method-table- reference in the code of the class, it is noted here. 589 * The information will be used to define the enhanced references in the Headerfile, 590 * it is also transformed to the stc file. (?) 591 * @param sRefType The referenced type. 592 */ 593 public void addMtblRefType(String sRefType, char intension) 594 { 595 if("b".indexOf(intension)>=0){ 596 usedMtblRefTypesC.put(sRefType, intension); 597 } else { 598 usedMtblRefTypesH.put(sRefType, intension); 599 } 600 } 601 602 @Override public void addStructForwardType(ClassData type) 603 { 604 if(isFirstPass){ 605 usedStructForward.put(type.getClassIdentName(), 'h'); 606 } else { 607 Character intensionSave = usedStructForward.get(type.getClassIdentName()); 608 if(intensionSave == null){ 609 //new forward struct declaration in second pass: 610 usedStructForward.put(type.getClassIdentName(), 'c'); 611 } 612 } 613 } 614 615 616 /** 617 * @param fileStructP 618 * @param sFilePathNameC Path and name for C,without extension 619 * @param listClassInFile 620 * @param sPkgIdent 621 * @throws IOException 622 */ 623 static void writeStructure(File fileStructP, String sFilePathNameC, List<ClassData> listClassInFile, String sPkgIdent) throws IOException 624 { 625 FileOutputStream fileOut = new FileOutputStream(fileStructP); 626 OutputStreamWriter streamOut = new OutputStreamWriter(fileOut, "UTF8"); 627 String sEncoding = streamOut.getEncoding(); 628 BufferedWriter out = new BufferedWriter(streamOut); 629 out.append("<?Java2C-stc www.vishia.org version=\"0.94\" encoding=\"" + sEncoding + "\" ?>\n"); 630 out.append("Structure of translated java-file \"" + sFilePathNameC + "\"\n"); 631 out.append("package " + sPkgIdent + ";\n"); 632 for(ClassData classData: listClassInFile) 633 { 634 classData.writeStructureClass(out,0); 635 636 } 637 out.close(); 638 639 } 640 641 642 643 644 645 646 647 void evaluateImports(ZbnfParseResultItem resultFile) 648 throws IOException, IllegalArgumentException, IllegalAccessException, InstantiationException, ParseException 649 { 650 List<ZbnfParseResultItem> itemsImport = resultFile.listChildren("importStatement"); 651 if(itemsImport!=null)for(ZbnfParseResultItem itemImport: itemsImport) 652 { List<ZbnfParseResultItem> listPkg = itemImport.listChildren("package"); 653 String sPkgPath = ""; 654 JavaSources.ClassDataOrJavaSrcFile pkgData = null; 655 //LocalIdents pkgTypes1 = pkgIdents; //start with own package, there are the commonly idents known too. 656 LocalIdents pkgTypes1 = Java2C_Main.getRootLevelIdents(); 657 LocalIdents fileLevelIdents1 = this.fileLevelIdents; 658 if(listPkg != null) //for... 659 for(ZbnfParseResultItem zbnfPkg: listPkg){ 660 String sPkg = zbnfPkg.getParsedString(); 661 sPkgPath += sPkg + "/"; 662 if(sPkgPath.equals("org/vishia/util/")) 663 stop(); 664 //pkgData = pkgTypes1.getTypeInfo(sPkg, fileLevelIdents1); //fileLevelIdents=null 665 //if(pkgData == null){ 666 // throw new ParseException("Package is unknown: " + sPkgPath, 0); 667 //} 668 //fileLevelIdents1 = null; 669 //pkgTypes1 = pkgData.getLocalIdents(sPkg); 670 } 671 ZbnfParseResultItem importClass = itemImport.getChild("class"); 672 if(importClass != null){ 673 String sClass = importClass.getParsedString(); 674 if(sClass.equals("StringPart")) 675 stop(); 676 String sImportClassPath = sPkgPath + sClass; 677 JavaSources.ClassDataOrJavaSrcFile typeClazz = 678 pkgTypes1.getTypeInfo(sImportClassPath, fileLevelIdents); //NOTE: The package path may be pkg-local too. 679 if(typeClazz == null){ 680 throw new ParseException("Class is unknown: " + sPkgPath + "/" + sClass, 0); 681 } 682 fileLevelIdents.putClassType(sClass, typeClazz); 683 } 684 else { 685 /**Import of a whole package: */ 686 pkgData = pkgTypes1.getTypeInfo(sPkgPath, null); 687 JavaSrcTreePkg pkgTree = pkgData.getJavaPkg(); 688 List<JavaSources.ClassDataOrJavaSrcFile> publicClasses = pkgTree.getPublicClasses(); 689 690 for(JavaSources.ClassDataOrJavaSrcFile type: publicClasses){ 691 String sNameType = type.getTypeName(); 692 fileLevelIdents.putClassType(sNameType, type); 693 } 694 } 695 } 696 } 697 698 699 700 701 @Override public String toString(){ return sFileNameC; } 702 703 /**It's a debug helper. The method is empty, but it is a mark to set a breakpoint. */ 704 void stop() 705 { //debug 706 } 707 708}