private void GenerateMainSource(string mainSource, string mainImage, IEnumerable<Dictionary<string, string>> assemblies, IEnumerable<Dictionary<string, string>> configurations, Dictionary<string, string> machineConfig)
{
using (StreamWriter sourceWriter = new StreamWriter(mainSource))
{
// Output header for the main source
sourceWriter.WriteLine("// This source code was produced by the Monobjc Tools, DO NOT EDIT !!!");
sourceWriter.WriteLine();
sourceWriter.WriteLine("#include <stdlib.h>");
if (this.Compress) {
sourceWriter.WriteLine("#include <zlib.h>");
}
sourceWriter.WriteLine("#include <mono/metadata/assembly.h>");
sourceWriter.WriteLine("#include \"monobjc.h\"");
sourceWriter.WriteLine();
sourceWriter.WriteLine("#ifdef RECEIGEN");
sourceWriter.WriteLine("#define RUNNER mono_main");
sourceWriter.WriteLine("#include \"receigen.h\"");
sourceWriter.WriteLine("#endif");
sourceWriter.WriteLine();
// Output the custom structure
sourceWriter.WriteLine("// Structure for MonoBundledAssemblyExt");
sourceWriter.WriteLine("typedef struct {");
sourceWriter.WriteLine("\tconst char *name;");
sourceWriter.WriteLine("\tconst unsigned char *data;");
sourceWriter.WriteLine("\tconst unsigned int size;");
sourceWriter.WriteLine("\tconst unsigned char *zip_data;");
sourceWriter.WriteLine("\tconst unsigned int zip_size;");
sourceWriter.WriteLine("} MonoBundledAssemblyExt;");
sourceWriter.WriteLine();
// Output the symbols for the assemblies
this.Logger.LogInfo("Output symbols for assemblies (" + assemblies.Count() + ")");
sourceWriter.WriteLine("// Symbols for assemblies");
foreach (Dictionary<string, string> dictionary in assemblies)
{
sourceWriter.WriteLine("extern const unsigned char {0}[];", dictionary[KEY_SYMBOL]);
}
sourceWriter.WriteLine();
// Output the symbols for the configuration
this.Logger.LogInfo("Output symbols for configuration (" + configurations.Count() + ")");
sourceWriter.WriteLine("// Symbols for configurations");
foreach (Dictionary<string, string> dictionary in configurations)
{
sourceWriter.WriteLine("extern const char {0}[];", dictionary[KEY_SYMBOL]);
}
sourceWriter.WriteLine();
// Output the symbol for the machine configuration
sourceWriter.WriteLine("// Symbol for machine configuration");
this.Logger.LogInfo("Output symbol for machine configuration");
if (machineConfig != null)
{
sourceWriter.WriteLine("extern const char {0}[];", machineConfig[KEY_SYMBOL]);
}
sourceWriter.WriteLine();
// Output the bundle for each assembly
this.Logger.LogInfo("Output bundle for assemblies (" + assemblies.Count() + ")");
sourceWriter.WriteLine("// Bundle for assemblies");
foreach (Dictionary<string, string> dictionary in assemblies)
{
if (this.Compress) {
sourceWriter.WriteLine("static MonoBundledAssemblyExt bundle_{0} = {{ \"{1}\", NULL, {2}, {0}, {3} }};", dictionary[KEY_SYMBOL], dictionary[KEY_NAME], dictionary[KEY_INPUT_SIZE], dictionary[KEY_OUTPUT_SIZE]);
} else {
sourceWriter.WriteLine("static MonoBundledAssemblyExt bundle_{0} = {{ \"{1}\", {0}, {2}, NULL, 0 }};", dictionary[KEY_SYMBOL], dictionary[KEY_NAME], dictionary[KEY_INPUT_SIZE]);
}
}
sourceWriter.WriteLine();
// Output the inflate function
if (this.Compress) {
sourceWriter.WriteLine("int bundle_inflate(MonoBundledAssemblyExt *bundle) {");
sourceWriter.WriteLine("\tif (!bundle->zip_data) {");
sourceWriter.WriteLine("\t\treturn 0;");
sourceWriter.WriteLine("\t}");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\tbundle->data = (const unsigned char *) malloc(bundle->size);");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\tint ret;");
sourceWriter.WriteLine("\tz_stream strm = { 0 };");
sourceWriter.WriteLine("\tret = inflateInit(&strm);");
sourceWriter.WriteLine("\tif (ret != Z_OK) {");
sourceWriter.WriteLine("\t\treturn ret;");
sourceWriter.WriteLine("\t}");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\tstrm.next_in = (Bytef *) bundle->zip_data;");
sourceWriter.WriteLine("\tstrm.avail_in = (uInt) bundle->zip_size;");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\twhile(1) {");
sourceWriter.WriteLine("\t\tstrm.next_out = (Bytef *) bundle->data;");
sourceWriter.WriteLine("\t\tstrm.avail_out = (uInt) bundle->size;");
sourceWriter.WriteLine("\t\tret = inflate(&strm, Z_NO_FLUSH);");
sourceWriter.WriteLine("\t\tif (ret == Z_STREAM_END) {");
sourceWriter.WriteLine("\t\t\tbreak;");
sourceWriter.WriteLine("\t\t}");
sourceWriter.WriteLine("\t\tif (ret != Z_OK) {");
sourceWriter.WriteLine("\t\t\treturn ret;");
sourceWriter.WriteLine("\t\t}");
sourceWriter.WriteLine("\t}");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\tret = inflateEnd(&strm);");
sourceWriter.WriteLine("\tif (ret != Z_OK) {");
sourceWriter.WriteLine("\t\treturn ret;");
sourceWriter.WriteLine("\t}");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\treturn 0;");
sourceWriter.WriteLine("}");
sourceWriter.WriteLine();
}
// Output the main image
sourceWriter.WriteLine("static char *image_name = \"{0}\";", mainImage);
sourceWriter.WriteLine();
// Output the main method
sourceWriter.WriteLine("int main(int argc, char* argv[]) {");
sourceWriter.WriteLine("\tint i;");
sourceWriter.WriteLine();
int i = 0;
sourceWriter.WriteLine("\tMonoBundledAssemblyExt *bundled[{0}];", assemblies.Count() + 1);
foreach (Dictionary<string, string> dictionary in assemblies)
{
if (this.Compress) {
sourceWriter.WriteLine("\tbundle_inflate(&bundle_{1});", i, dictionary[KEY_SYMBOL]);
}
sourceWriter.WriteLine("\tbundled[{0}] = &bundle_{1};", i, dictionary[KEY_SYMBOL]);
i++;
}
sourceWriter.WriteLine("\tbundled[{0}] = NULL;", i);
sourceWriter.WriteLine("\t");
sourceWriter.WriteLine("\t// Disabled shared area");
sourceWriter.WriteLine("\tsetenv(\"MONO_DISABLE_SHARED_AREA\", \"1\", 1);");
sourceWriter.WriteLine("\t");
sourceWriter.WriteLine("\t// Shift the arguments to include the image name");
sourceWriter.WriteLine("\tchar **newargs = (char **) malloc (sizeof(char *) * (argc + 2));");
sourceWriter.WriteLine("\tnewargs [0] = argv[0];");
sourceWriter.WriteLine("\tnewargs [1] = image_name;");
sourceWriter.WriteLine("\tfor(i = 1; i < argc; i++) {");
sourceWriter.WriteLine("\t\tnewargs[i+1] = argv [i];");
sourceWriter.WriteLine("\t}");
sourceWriter.WriteLine("\tnewargs[++i] = NULL;");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\t// Registers the configurations and the assemblies");
if (machineConfig != null)
{
sourceWriter.WriteLine("\tmono_register_machine_config({0});", machineConfig[KEY_SYMBOL]);
}
foreach (Dictionary<string, string> dictionary in configurations)
{
sourceWriter.WriteLine("\tmono_register_config_for_assembly(\"{0}\", {1});", dictionary[KEY_ASSEMBLY], dictionary[KEY_SYMBOL]);
}
sourceWriter.WriteLine("\tmono_register_bundled_assemblies((const MonoBundledAssembly **) bundled);");
sourceWriter.WriteLine();
sourceWriter.WriteLine("\t// Invoke the Mono runtime");
sourceWriter.WriteLine("#ifdef RECEIGEN");
sourceWriter.WriteLine("\treturn CheckReceiptAndRun(argc + 1, newargs);");
sourceWriter.WriteLine("#else");
sourceWriter.WriteLine("\treturn mono_main(argc + 1, newargs);");
sourceWriter.WriteLine("#endif");
sourceWriter.WriteLine("}");
}
}