private string EmitOutputBase(DisplayVerb display, WriteStatement writeStatement) { string r = ""; string className = "__CobolProgram"; DataDescription dde = null; //Build the format string and param types list... string fmt = ""; int objects = 0; ArrayList sources; if (display != null) { sources = display.Sources; } else { dde = GetDDEByName(writeStatement.RecordName.Name); if (dde == null) { Console.WriteLine("dde is NULL"); } r += " " + ILAddress(1) + "ldarg.0\n"; r += " " + ILAddress(5); r += "ldfld class [mscorlib]System.IO.StreamWriter " + className + "::_writer_" + ILIdentifier(dde.FSDE.Name.Name) + "\n"; sources = new ArrayList(); if (writeStatement.RecordName != null) { sources.Add(writeStatement.RecordName); } //TODO: What should be done when there are no FROM identifiers? } for (int i = 0; i < sources.Count; i++) { Source source = sources[i] as Source; if (IsGroup(source)) { Identifier id = source as Identifier; List <DataDescription> ddes = ListElements(id.Definition); foreach (DataDescription dd in ddes) { fmt += "{" + objects + ",-" + dd.Size + "}"; objects++; } } else { //TODO: //If the source specifies a substring, then that size should be used in the //brackets rather than the definition's size. Simply using the definition's //size breaks the 99 bottles output because the buffer variable is large //and we only want one character from it. //See testdisp.cbl and its output. if (source.GetType() == typeof(Identifier)) { Identifier id = source as Identifier; if (id.UsesSubstring) { Console.WriteLine("UsesSubstring = true : " + id.Name); fmt += "{" + objects + "}"; } else { //Console.WriteLine("UsesSubstring = false : "+id.Name); fmt += "{" + objects + ",-" + id.Definition.Size + "}"; } } else { fmt += "{" + objects + "}"; } objects++; } } //Load the format string... r += " " + ILAddress(5); r += "ldstr \"" + fmt + "\"\n"; //Create an array r += " " + ILAddress(5); r += "ldc.i4 " + objects + "\n"; r += " " + ILAddress(5); r += "newarr [mscorlib]System.Object\n"; //Load the values... int obj = 0; foreach (Source source in sources) { if (IsGroup(source)) { Identifier id = source as Identifier; //Plan: // 1. Load a format string based on all of the group element sizes (and types?) // 2. Load each element // 3. String.Format // 4. Build an object array of the elements // 5. Use the format string and array in WriteLine List <DataDescription> ddes = ListElements(id.Definition); foreach (DataDescription dd in ddes) { Identifier tmp = new Identifier(); tmp.Name = dd.Name; tmp.Definition = dd; r += " " + ILAddress(1) + "dup\n"; r += " " + ILAddress(5) + "ldc.i4 " + obj + "\n"; r += EmitLoadSource(tmp as Source, false, true); r += " " + ILAddress(1) + "stelem.ref\n"; obj++; } } else { r += " " + ILAddress(1) + "dup\n"; r += " " + ILAddress(5) + "ldc.i4 " + obj + "\n"; r += EmitLoadSource(source, false, true); r += " " + ILAddress(1) + "stelem.ref\n"; obj++; } } if (display != null) { //Call Write or WriteLine... r += " " + ILAddress(5); string parms = "string, object[]"; if (display.NoAdvancing) { r += "call void class [mscorlib]System.Console::Write(" + parms + ")"; } else { r += "call void class [mscorlib]System.Console::WriteLine(" + parms + ")"; } r += "\n"; } else { //Write... r += " " + ILAddress(5); r += "callvirt instance void class [mscorlib]System.IO.StreamWriter::WriteLine(string,object[])\n"; //Flush... r += " " + ILAddress(1) + "ldarg.0\n"; r += " " + ILAddress(5); r += "ldfld class [mscorlib]System.IO.StreamWriter " + className + "::_writer_" + ILIdentifier(dde.FSDE.Name.Name) + "\n"; r += " " + ILAddress(5); r += "callvirt instance void class [mscorlib]System.IO.StreamWriter::Flush()\n"; } return(r); }
private string EmitDisplayVerb(DisplayVerb display) { return(EmitOutputBase(display, null)); }