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}