diff --git a/.gitignore b/.gitignore index add8f5e..ccaa8eb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ temp/ ## Special Treat of CodeGen CodeGen.old/ -CodeGen/dest/*.txt +CodeGen/dest/*.hpp CodeGen/.* CodeGen/*.class diff --git a/CodeGen/CKCommonHelper.java b/CodeGen/CKCommonHelper.java index c54d716..00a32ee 100644 --- a/CodeGen/CKCommonHelper.java +++ b/CodeGen/CKCommonHelper.java @@ -1,8 +1,6 @@ import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStreamWriter; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; @@ -60,17 +58,65 @@ public class CKCommonHelper { } } - public static String getEnumUnderlayingType(boolean canUnsigned) { + /** + * Get underlying type of enum. + * @param canUnsigned The parameter stored in Enum_t that indiccate + * whether this enum can use unsigned int as its underlying type. + * @return The string form of its underlying type. + */ + public static String getEnumUnderlyingType(boolean canUnsigned) { return canUnsigned ? "uint32_t" : "int32_t"; } + + // =========== File Operations =========== + public static class InputFilePair { + public CharStream mAntlrStream; + public FileInputStream mUnderlyingStream; + } + public static InputFilePair openInputFile(String filename) throws Exception { + InputFilePair pair = new InputFilePair(); + pair.mUnderlyingStream = new FileInputStream(filename); + pair.mAntlrStream = CharStreams.fromStream(pair.mUnderlyingStream, StandardCharsets.UTF_8); + return pair; + } + + /** + * Get output file for writing. + * @param filename The name of file opening. + * @return An OutputStreamWriter. + * @throws Exception + */ public static OutputStreamWriter openOutputFile(String filename) throws Exception { FileOutputStream fs = new FileOutputStream(filename); return new OutputStreamWriter(fs, StandardCharsets.UTF_8); } + // =========== String Process =========== + + /** + * Escape String + * + * Escape all characters which are invalid in string quote. + * + * @param strl The string need to be escaped. + * @return The escaped string. + * @see removeEol + */ public static String escapeString(String strl) { - + return strl.replace("\\", "\\\\").replace("\t", "\\t").replace("\b", "\\b").replace("\n", "\\n") + .replace("\r", "\\r").replace("\f", "\\f").replace("\"", "\\\""); } - + + /** + * Remove all EOL (End of Line) characters. + * + * @param strl The string need to be processed. + * @return The string eliminated all EOL. + * @see escapeString + */ + public static String removeEol(String strl) { + return strl.replace("\n", "").replace("\r", ""); + } + } diff --git a/CodeGen/CKEnumParser.g4 b/CodeGen/CKEnumParser.g4 index 5b8551f..bfaff38 100644 --- a/CodeGen/CKEnumParser.g4 +++ b/CodeGen/CKEnumParser.g4 @@ -1,7 +1,7 @@ parser grammar CKEnumParser; options { tokenVocab = CKGeneralLexer; } -prog: enumBody+ ; +prog: enumBody* ; enumBody: CKGENERAL_TYPEDEF? CKGENERAL_ENUM CKGENERAL_ID CKGENERAL_LBRACKET entryPair+ diff --git a/CodeGen/CKEnumRunner.java b/CodeGen/CKEnumRunner.java index 58b1f5e..a6e062a 100644 --- a/CodeGen/CKEnumRunner.java +++ b/CodeGen/CKEnumRunner.java @@ -139,54 +139,125 @@ public class CKEnumRunner { } - public static class EnumProgWriter { - public static void writeEnums(OutputStreamWriter writer, CKCommonHelper.CKParts parts, List prog) - throws Exception { - CKIndentHelper indent = new CKIndentHelper(writer); - indent.puts("#pragma once"); - indent.puts("#include "); - indent.printf("namespace LibCmo::{} {{", CKCommonHelper.getCKPartsNamespace(parts)); - indent.inc(); - - // write enums + public static class EnumWriter { + private static void writeEnum(CKIndentHelper indent, List prog) throws Exception { for (Enum_t enum_t : prog) { // write enum comment indent.briefComment(enum_t.mEnumComment); // write enum start - indent.printf("enum class {} : {} {{", enum_t.mEnumName, - CKCommonHelper.getEnumUnderlayingType(enum_t.mCanUnsigned)); + indent.printf("enum class %s : %s {", enum_t.mEnumName, + CKCommonHelper.getEnumUnderlyingType(enum_t.mCanUnsigned)); indent.inc(); // write enum entries for (EnumEntry_t enumEntry_t : enum_t.mEntries) { // write entry self if (enumEntry_t.mEntryValue == null) { - indent.printf("{},", enumEntry_t.mEntryName); + indent.printf("%s,", enumEntry_t.mEntryName); } else { - indent.printf("{} = {},", enumEntry_t.mEntryName, enumEntry_t.mEntryValue); + indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue); } - + // write entry comment after member indent.afterMemberComment(enumEntry_t.mEntryComment); } // write enum tail indent.dec(); - indent.puts("}"); + indent.puts("};"); } + } + public static void writeEnums(OutputStreamWriter writer, List ck2_prog, List vxmath_prog) + throws Exception { + CKIndentHelper indent = new CKIndentHelper(writer); + indent.puts("#pragma once"); + indent.puts("#include "); + + indent.puts("namespace LibCmo::CK2 {"); + indent.inc(); + writeEnum(indent, ck2_prog); + indent.dec(); + indent.puts("}"); + + indent.puts("namespace LibCmo::VxMath {"); + indent.inc(); + writeEnum(indent, vxmath_prog); indent.dec(); indent.puts("}"); } - public static void writeComments(OutputStreamWriter writer, List prog) throws Exception { - CKIndentHelper indent = new CKIndentHelper(writer); + private static void writeAccessibleValue(CKIndentHelper indent, String parts, List prog) throws Exception { + for (Enum_t enum_t : prog) { + // write enum desc header + indent.printf("const EnumNameofArray {} {", + parts, enum_t.mEnumName, enum_t.mEnumName); + indent.inc(); + // write enum desc entries + for (EnumEntry_t enumEntry_t : enum_t.mEntries) { + indent.printf("{ LibCmo::%s::%s::%s, \"%s\" },", + parts, enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName); + } + + // write enum tail + indent.dec(); + indent.puts("};"); + } + } + + public static void writeAccessibleValues(OutputStreamWriter writer, List ck2_prog, List vxmath_prog) throws Exception { + CKIndentHelper indent = new CKIndentHelper(writer); + indent.puts("#pragma once"); + indent.puts("#include \"CKEnums.hpp\""); + indent.puts("#include "); + indent.puts("#include "); + indent.puts("#include "); + indent.puts("namespace Unvirt::AccessibleValue::EnumDesc {"); + indent.inc(); + + indent.puts("namespace CK2 {"); + indent.inc(); + writeAccessibleValue(indent, "CK2", ck2_prog); + indent.dec(); + indent.puts("}"); + + indent.puts("namespace VxMath {"); + indent.inc(); + writeAccessibleValue(indent, "VxMath", vxmath_prog); + indent.dec(); + indent.puts("}"); + + indent.dec(); + indent.puts("}"); } } - public static void Run(String infilename, String outfilename) { - + private static List getProg(String infile) throws Exception { + CKCommonHelper.InputFilePair pair = CKCommonHelper.openInputFile(infile); + CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream); + CommonTokenStream tokens = new CommonTokenStream(lexer); + CKEnumParser parser = new CKEnumParser(tokens); + + ParseTree tree = parser.prog(); + ParseTreeWalker walker = new ParseTreeWalker(); + EnumWalker worker = new EnumWalker(tokens); + walker.walk(worker, tree); + + pair.mUnderlyingStream.close(); + return worker.getResult(); + } + public static void run(String inCk2Enums, String inVxEnums, String outEnums, String outAccessibleValues) throws Exception { + List ck2prog = getProg(inCk2Enums); + List vxprog = getProg(inVxEnums); + + OutputStreamWriter fs = CKCommonHelper.openOutputFile(outEnums); + EnumWriter.writeEnums(fs, ck2prog, vxprog); + fs.close(); + + fs = CKCommonHelper.openOutputFile(outAccessibleValues); + EnumWriter.writeAccessibleValues(fs, ck2prog, vxprog); + fs.close(); } } diff --git a/CodeGen/CKIndentHelper.java b/CodeGen/CKIndentHelper.java index 01f6f9e..53deaed 100644 --- a/CodeGen/CKIndentHelper.java +++ b/CodeGen/CKIndentHelper.java @@ -3,6 +3,7 @@ import java.io.OutputStreamWriter; public class CKIndentHelper { public CKIndentHelper(OutputStreamWriter writer) { mIndent = 0; + mWriter = writer; } private int mIndent; @@ -35,13 +36,14 @@ public class CKIndentHelper { public void briefComment(String fmt) throws Exception { if (fmt == null) return; - printf("/**< {} */", fmt.replaceAll("[\\r\\n]+", "")); + puts("/**"); + puts(fmt); + puts(" */"); } public void afterMemberComment(String fmt) throws Exception { if (fmt == null) return; - mWriter.write("\t"); - mWriter.write(fmt); + mWriter.write(String.format("\t/**< %s */", CKCommonHelper.removeEol(fmt))); } } diff --git a/CodeGen/CKMainGen.java b/CodeGen/CKMainGen.java index dd9d241..64072d9 100644 --- a/CodeGen/CKMainGen.java +++ b/CodeGen/CKMainGen.java @@ -1 +1,7 @@ -// todo: WIP \ No newline at end of file + +public class CKMainGen { + public static void main(String[] args) throws Exception { + CKEnumRunner.run("src/CKENUMS.txt", "src/VXENUMS.txt", "dest/CKEnums.gen.hpp", "dest/AccessibleValue.gen.hpp"); + System.out.println("DONE!"); + } +} diff --git a/CodeGen/src/CKENUMS.txt b/CodeGen/src/CKENUMS.txt index a4d45d8..ca98642 100644 --- a/CodeGen/src/CKENUMS.txt +++ b/CodeGen/src/CKENUMS.txt @@ -1,11 +1,37 @@ -enum !CK_FILE_WRITEMODE +/************************************************* +{filename:CK_FILE_WRITEMODE} +Summary: Specify the way files are saved to disk (compression) + +Remarks : + + File write mode controls the format of a Virtools file when saved. More specifically it + controls whether compression is enabled and also if the Virtools Dev Interface specific data + should be stored in the file (if CKFILE_FORVIEWER flag is set , no interface data is saved) + +See also: CKContext::SetFileWriteMode,CKContext::GetFileWriteMode,CKContext::SetCompressionLevel,CKContext::SetGlobalImagesSaveOptions,CKContext::SetGlobalSoundsSaveOptions +*************************************************/ +typedef enum CK_FILE_WRITEMODE +{ CKFILE_UNCOMPRESSED =0, // Save data uncompressed CKFILE_CHUNKCOMPRESSED_OLD =1, // Obsolete CKFILE_EXTERNALTEXTURES_OLD=2, // Obsolete : use CKContext::SetGlobalImagesSaveOptions instead. CKFILE_FORVIEWER =4, // Don't save Interface Data within the file, the level won't be editable anymore in the interface CKFILE_WHOLECOMPRESSED =8, // Compress the whole file +} CK_FILE_WRITEMODE; -enum !CK_LOAD_FLAGS +/************************************************* +{filename:CK_LOAD_FLAGS} +Summary: Load Options. + +Remarks: ++ This options apply when loading a Virtools file +or a importing a 3D Model file. ++ They defines whether object geometry,only animations +or only behaviors should be loaded. ++ One can specify (using the CK_LOAD_AS_DYNAMIC_OBJECT) if +created CKObjects should be created as dynamic (See also Dynamic Objects) +See also : CKContext::Load,CKContext::CKSave +*************************************************/ +typedef enum CK_LOAD_FLAGS { CK_LOAD_ANIMATION =1<<0, // Load animations CK_LOAD_GEOMETRY =1<<1, // Load geometry. CK_LOAD_DEFAULT =CK_LOAD_GEOMETRY|CK_LOAD_ANIMATION, // Load animations & geometry @@ -16,8 +42,10 @@ enum !CK_LOAD_FLAGS CK_LOAD_CHECKDUPLICATES =1<<6, // Check object name unicity (The list of duplicates is stored in the CKFile class after a OpenFile call CK_LOAD_CHECKDEPENDENCIES =1<<7, // Check if every plugins needed are availables CK_LOAD_ONLYBEHAVIORS =1<<8, // +} CK_LOAD_FLAGS; -enum CK_FO_OPTIONS +// Options that will be used to create this object... + enum CK_FO_OPTIONS { CK_FO_DEFAULT = 0, // Default behavior : a new object will be created with the name stored in CKFileObject CK_FO_RENAMEOBJECT, // Renaming : a new object will be created with the name stored in CKFileObject + a integer value XXX to ensure its uniqueness CK_FO_REPLACEOBJECT, // Do not create a new object, instead use an existing one which CK_ID is given by CreatedObject @@ -25,8 +53,19 @@ enum CK_FO_OPTIONS CK_FO_DONTLOADOBJECT, // Object chunk will not be read either because it is a reference // or because the loaded object already exist in the current level // and the user choose to keep the existing one. + }; -enum CK_PLUGIN_TYPE +/************************************************* +{filename:CK_PLUGIN_TYPE} +Summary: Type identifier for a Virtools plugin. +Remarks: + + Each plugin must be given a type. + + This enumeration is used to identify a specific catagory + of plugin when using the CKPluginManager. + +See also: CKPluginManager,Creating New Plugins +*************************************************/ +typedef enum CK_PLUGIN_TYPE { CKPLUGIN_BITMAP_READER = 0, // The plugin is bitmap (textures,sprites) loader CKPLUGIN_SOUND_READER = 1, // Sound Reader Plugin CKPLUGIN_MODEL_READER = 2, // 3D Model Reader @@ -35,8 +74,9 @@ enum CK_PLUGIN_TYPE CKPLUGIN_RENDERENGINE_DLL = 5, // Render Engine plugin CKPLUGIN_MOVIE_READER = 6, // Movie (AVI,Mpeg) reader CKPLUGIN_EXTENSION_DLL = 7, // Generic extension (definition of new parameter types or operations for ex.) +} CK_PLUGIN_TYPE; -enum CK_STATECHUNK_DATAVERSION +enum CK_STATECHUNK_DATAVERSION { CHUNKDATA_OLDVERSION= 0, // Before any version was saved CHUNKDATA_BASEVERSION= 1, // First version CHUNK_WAVESOUND_VERSION2= 2, // Changes in wavesound format @@ -50,15 +90,17 @@ enum CK_STATECHUNK_DATAVERSION CHUNK_DEV_2_1= 10, // Changes in wavesound reading of inside, outside angles CHUNKDATA_CURRENTVERSION= CHUNK_DEV_2_1 , +}; -enum CK_STATECHUNK_CHUNKVERSION +enum CK_STATECHUNK_CHUNKVERSION { CHUNK_VERSIONBASE= 0, CHUNK_VERSION1= 4, // equal to file version : WriteObjectID => table CHUNK_VERSION2= 5, // add Manager Data CHUNK_VERSION3= 6, // New ConvertToBuffer / ReadFromBuffer (file system changed to reflect this ) CHUNK_VERSION4= 7, // New WriteObjectID when saving to a file +}; -enum CK_STATECHUNK_CHUNKOPTIONS +enum CK_STATECHUNK_CHUNKOPTIONS { CHNK_OPTION_IDS = 0x01, // IDS are stored inside chunk CHNK_OPTION_MAN = 0x02, // Managers ints are store inside chunk CHNK_OPTION_CHN = 0x04, // Sub chunk are stored inside chunk @@ -67,8 +109,20 @@ enum CK_STATECHUNK_CHUNKOPTIONS CHNK_OPTION_LISTBIG = 0x20, // List are store in big Endian ? CHNK_DONTDELETE_PTR = 0x40, // Data buffer stored in m_Buffer is not owned by CKStateChunk , it must not be deleted... CHNK_DONTDELETE_PARSER = 0x80, // m_Parser Ptr is not owned by CKStateChunk , it must not be deleted... +}; -enum !CK_OBJECT_FLAGS +/*************************************************** +{filename:CK_OBJECT_FLAGS} +Summary: CKObject Flags + +Remarks: ++ Flags specifying special settings for basic objects. ++ Some of this flags are shared with sub-classes such as CKParameterIn,CKParameterOut and CKBehaviorIO. ++ You rarely need to modify directly this flags through CKObject::SetFlags or CKObject::ModifyObjectFlags instead +you should always use the specific acces function (given between ()) which may need to perform additionnal operations. +See also: CKObject,CKObject::GetObjectFlags,CKObject::ModifyObjectFlags +*************************************************/ +typedef enum CK_OBJECT_FLAGS { CK_OBJECT_INTERFACEOBJ = 0x00000001, // Reserved for Inteface Use CK_OBJECT_PRIVATE = 0x00000002, // The object must not be displayed in interface (Lists,Level view,etc...),nor should it be saved. (CKObject::IsPrivate() CK_OBJECT_INTERFACEMARK = 0x00000004, @@ -110,3 +164,4 @@ enum !CK_OBJECT_FLAGS CKBEHAVIORLINK_RESERVED = 0x10000000, // This BehaviorIO is a behavior input (CKBehaviorIO::SetType} CKBEHAVIORLINK_ACTIVATEDLASTFRAME = 0x20000000, // This link had been activated last frame CK_OBJECT_BEHAVIORLINKMASK = 0x30000000, +} CK_OBJECT_FLAGS;