From 563c3d8c6210eda3485d9c245147aab4fa106ad0 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 24 Jun 2021 12:54:04 -0700 Subject: [PATCH] new parse: write TS tooltip comments (#2850) * fix offsets inside struct arrays * style * fix index writing for arrays of structs * write TS context comments * cleanup --- .../src/com/rusefi/ConfigDefinition.java | 8 ++--- .../src/com/rusefi/newparse/ParseState.java | 7 ++-- .../layout/ArrayIterateScalarLayout.java | 9 +++--- .../layout/ArrayIterateStructLayout.java | 9 +++--- .../rusefi/newparse/layout/ArrayLayout.java | 5 +-- .../newparse/layout/BitGroupLayout.java | 8 ++++- .../rusefi/newparse/layout/EnumLayout.java | 8 +++-- .../com/rusefi/newparse/layout/Layout.java | 11 ++++--- .../rusefi/newparse/layout/ScalarLayout.java | 18 +++++++---- .../rusefi/newparse/layout/StringLayout.java | 9 ++++-- .../rusefi/newparse/layout/StructLayout.java | 5 +-- .../rusefi/newparse/layout/UnionLayout.java | 5 +-- .../rusefi/newparse/layout/UnusedLayout.java | 3 +- .../rusefi/newparse/outputs/TsMetadata.java | 28 ++++++++++++++++ .../com/rusefi/newparse/outputs/TsWriter.java | 32 +++++++++++++++++++ 15 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsMetadata.java create mode 100644 java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java diff --git a/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java b/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java index edd329fb2d..64e088845f 100644 --- a/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java +++ b/java_tools/configuration_definition/src/com/rusefi/ConfigDefinition.java @@ -2,6 +2,7 @@ package com.rusefi; import com.rusefi.generated.*; import com.rusefi.newparse.ParseState; +import com.rusefi.newparse.outputs.TsWriter; import com.rusefi.newparse.parsing.Definition; import com.rusefi.output.*; import com.rusefi.util.*; @@ -282,10 +283,9 @@ public class ConfigDefinition { // cPrintStream.close(); // Write tunerstudio layout - // PrintStream tsPrintStream = new PrintStream(new FileOutputStream(tsPath + "/test.ini")); - // StructLayout root = new StructLayout(0, "root", listener.getLastStruct()); - // root.writeTunerstudioLayout(tsPrintStream, new StructNamePrefixer()); - // tsPrintStream.close(); + // TsWriter writer = new TsWriter(); + // writer.writeTunerstudio(listener, "TODO", tsPath + "/test.ini"); + } BufferedReader definitionReader = new BufferedReader(new InputStreamReader(new FileInputStream(definitionInputFile), IoUtils.CHARSET.name())); diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java b/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java index e187d49c73..c25d9f193e 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/ParseState.java @@ -247,9 +247,10 @@ public class ParseState extends RusefiConfigGrammarBaseListener { if (ctx.fieldOption().size() == 0) { if (ctx.SemicolonedString() != null) { - options.comment = ctx.SemicolonedString().getText(); + String text = ctx.SemicolonedString().getText(); + options.comment = text.substring(1, text.length() - 1).trim(); } else if (ctx.SemicolonedSuffix() != null) { - options.comment = ctx.SemicolonedSuffix().getText(); + options.comment = ctx.SemicolonedSuffix().getText().substring(1).trim(); } else { options.comment = ""; } @@ -383,7 +384,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener { scope.structFields.add(group); } - String comment = ctx.SemicolonedSuffix() == null ? null : ctx.SemicolonedSuffix().getText(); + String comment = ctx.SemicolonedSuffix() == null ? null : ctx.SemicolonedSuffix().getText().substring(1).trim(); String trueValue = "\"true\""; String falseValue = "\"false\""; diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateScalarLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateScalarLayout.java index 4760115a50..9399a86051 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateScalarLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateScalarLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.*; import java.io.PrintStream; @@ -9,22 +10,22 @@ public class ArrayIterateScalarLayout extends ArrayLayout { super(prototype, length); } - private void emitOne(PrintStream ps, StructNamePrefixer prefixer, int offset, int idx) { + private void emitOne(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offset, int idx) { // Set element's position within the array this.prototypeLayout.setOffset(offset + this.prototypeLayout.getSize() * idx); // Put a 1-based index on the end of the name to distinguish in TS prefixer.setIndex(idx); - this.prototypeLayout.writeTunerstudioLayout(ps, prefixer, 0); + this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, 0); prefixer.clearIndex(); } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { // Time to iterate: emit one scalar per array element, with the name modified accordingly for (int i = 0; i < this.length; i++) { - emitOne(ps, prefixer, this.offset + offsetAdd, i); + emitOne(ps, meta, prefixer, this.offset + offsetAdd, i); } } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateStructLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateStructLayout.java index a9743ae6ab..776b985353 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateStructLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayIterateStructLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.*; import java.io.PrintStream; @@ -9,22 +10,22 @@ public class ArrayIterateStructLayout extends ArrayLayout { super(prototype, length); } - private void emitOne(PrintStream ps, StructNamePrefixer prefixer, int offset, int idx) { + private void emitOne(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offset, int idx) { // Set element's position within the array int offsetAdd = offset + this.prototypeLayout.getSize() * idx; // Put a 1-based index on the end of the name to distinguish in TS prefixer.setIndex(idx); - this.prototypeLayout.writeTunerstudioLayout(ps, prefixer, offsetAdd); + this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd); prefixer.clearIndex(); } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { // Time to iterate: emit one scalar per array element, with the name modified accordingly for (int i = 0; i < this.length; i++) { - emitOne(ps, prefixer, this.offset + offsetAdd, i); + emitOne(ps, meta, prefixer, this.offset + offsetAdd, i); } } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayLayout.java index b069b74d57..bae0c020c2 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ArrayLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.*; import java.io.PrintStream; @@ -55,8 +56,8 @@ public class ArrayLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { - this.prototypeLayout.writeTunerstudioLayout(ps, prefixer, offsetAdd, this.length); + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { + this.prototypeLayout.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd, this.length); } @Override diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/BitGroupLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/BitGroupLayout.java index 3f1421103a..23638b98a3 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/BitGroupLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/BitGroupLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.BitGroup; import com.rusefi.newparse.parsing.EnumField; import com.rusefi.newparse.parsing.Type; @@ -46,11 +47,14 @@ public class BitGroupLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { int actualOffset = this.offset + offsetAdd; for (int i = 0; i < bits.size(); i++) { BitLayout bit = bits.get(i); + + String name = prefixer.get(bit.name); + ps.print(prefixer.get(bit.name)); ps.print(" = bits, U32, "); ps.print(actualOffset); @@ -60,6 +64,8 @@ public class BitGroupLayout extends Layout { ps.print("], " + bit.falseValue + ", " + bit.trueValue); ps.println(); + + meta.addComment(name, bit.comment); } } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/EnumLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/EnumLayout.java index 4dfef117cd..a4f83cde64 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/EnumLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/EnumLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.EnumField; import com.rusefi.newparse.parsing.FieldOptions; import com.rusefi.newparse.parsing.Type; @@ -35,8 +36,9 @@ public class EnumLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { - ps.print(prefixer.get(this.name)); + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { + String name = prefixer.get(this.name); + ps.print(name); ps.print(" = bits, "); ps.print(this.type.tsType); ps.print(", "); @@ -62,6 +64,8 @@ public class EnumLayout extends Layout { } ps.println(); + + meta.addComment(name, this.options.comment); } @Override diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/Layout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/Layout.java index cdbb7b70cd..5e719cc74f 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/Layout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/Layout.java @@ -1,5 +1,7 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; + import java.io.PrintStream; public abstract class Layout { @@ -25,13 +27,13 @@ public abstract class Layout { return "offset = " + offset + " size = " + this.getSize(); } - public final void writeTunerstudioLayout(PrintStream ps) { - writeTunerstudioLayout(ps, new StructNamePrefixer(), 0); + public final void writeTunerstudioLayout(PrintStream ps, TsMetadata meta) { + writeTunerstudioLayout(ps, meta, new StructNamePrefixer(), 0); } - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) {} + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) {} - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int arrayLength) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd, int arrayLength) { throw new IllegalStateException("This type can't be in an array!"); } @@ -39,7 +41,6 @@ public abstract class Layout { ps.println("\t/**"); if (comment != null) { - comment = comment.replaceAll(";", ""); comment = comment.replaceAll("[+]", ""); comment = comment.replaceAll("\\n", "\n\t * "); if (comment.length() == 0) { diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ScalarLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ScalarLayout.java index 8cc7db219a..1340427595 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ScalarLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/ScalarLayout.java @@ -1,6 +1,7 @@ package com.rusefi.newparse.layout; import com.rusefi.ConfigDefinition; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.FieldOptions; import com.rusefi.newparse.parsing.ScalarField; import com.rusefi.newparse.parsing.Type; @@ -28,13 +29,16 @@ public class ScalarLayout extends Layout { return "Scalar " + type.cType + " " + super.toString(); } - private void printBeforeArrayLength(PrintStream ps, StructNamePrefixer prefixer, String fieldType, int offsetAdd) { - ps.print(prefixer.get(this.name)); + private void printBeforeArrayLength(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, String fieldType, int offsetAdd) { + String name = prefixer.get(this.name); + ps.print(name); ps.print(" = " + fieldType + ", "); ps.print(this.type.tsType); ps.print(", "); ps.print(this.offset + offsetAdd); ps.print(", "); + + meta.addComment(name, this.options.comment); } private void printAfterArrayLength(PrintStream ps) { @@ -44,17 +48,17 @@ public class ScalarLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd, int arrayLength) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd, int arrayLength) { if (arrayLength == 0) { // Skip zero length arrays, they may be used for dynamic padding but TS doesn't like them return; } else if (arrayLength == 1) { // For 1-length arrays, emit as a plain scalar instead - writeTunerstudioLayout(ps, prefixer, offsetAdd); + writeTunerstudioLayout(ps, meta, prefixer, offsetAdd); return; } - printBeforeArrayLength(ps, prefixer, "array", offsetAdd); + printBeforeArrayLength(ps, meta, prefixer, "array", offsetAdd); ps.print("["); ps.print(arrayLength); @@ -64,8 +68,8 @@ public class ScalarLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { - printBeforeArrayLength(ps, prefixer, "scalar", offsetAdd); + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { + printBeforeArrayLength(ps, meta, prefixer, "scalar", offsetAdd); printAfterArrayLength(ps); } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StringLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StringLayout.java index 462e1ee585..3b4a4aec39 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StringLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StringLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.StringField; import com.rusefi.newparse.parsing.UnusedField; @@ -31,14 +32,18 @@ public class StringLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { - ps.print(prefixer.get(this.name)); + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { + String name = prefixer.get(this.name); + ps.print(name); ps.print(" = string, ASCII, "); ps.print(this.offset + offsetAdd); ps.print(", "); ps.print(size); ps.println(); + + // TODO: write string comments + // meta.addComment(name, ??); } @Override diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StructLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StructLayout.java index f7612747ed..22c764d8e5 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StructLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/StructLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.*; import java.io.PrintStream; @@ -156,13 +157,13 @@ public class StructLayout extends Layout { @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { if (!this.noPrefix) { prefixer.push(this.name); } // print all children in sequence - this.children.forEach(c -> c.writeTunerstudioLayout(ps, prefixer, offsetAdd)); + this.children.forEach(c -> c.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd)); if (!this.noPrefix) { prefixer.pop(); diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnionLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnionLayout.java index 1f0adf54a4..57b4bf1edb 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnionLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnionLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.ArrayField; import com.rusefi.newparse.parsing.Field; import com.rusefi.newparse.parsing.ScalarField; @@ -56,9 +57,9 @@ public class UnionLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { // Simply write out all children - no container necessary as fields can overlap in TS - this.children.forEach(c -> c.writeTunerstudioLayout(ps, prefixer, offsetAdd)); + this.children.forEach(c -> c.writeTunerstudioLayout(ps, meta, prefixer, offsetAdd)); } @Override diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnusedLayout.java b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnusedLayout.java index 8b3b3d44b7..88192e5a1f 100644 --- a/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnusedLayout.java +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/layout/UnusedLayout.java @@ -1,5 +1,6 @@ package com.rusefi.newparse.layout; +import com.rusefi.newparse.outputs.TsMetadata; import com.rusefi.newparse.parsing.EnumField; import com.rusefi.newparse.parsing.Type; import com.rusefi.newparse.parsing.UnusedField; @@ -34,7 +35,7 @@ public class UnusedLayout extends Layout { } @Override - protected void writeTunerstudioLayout(PrintStream ps, StructNamePrefixer prefixer, int offsetAdd) { + protected void writeTunerstudioLayout(PrintStream ps, TsMetadata meta, StructNamePrefixer prefixer, int offsetAdd) { ps.println("; unused " + this.size + " bytes at offset " + (this.offset + offsetAdd)); } diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsMetadata.java b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsMetadata.java new file mode 100644 index 0000000000..dc193783a3 --- /dev/null +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsMetadata.java @@ -0,0 +1,28 @@ +package com.rusefi.newparse.outputs; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +public class TsMetadata { + private List comments = new ArrayList<>(); + public void addComment(String name, String comment) { + if (comment == null) { + return; + } + + comment = comment.trim(); + if (!comment.startsWith("+")) { + return; + } + + // Clip off leading +, and any leading/trailing whitespace + comment = comment.substring(1).trim(); + + comments.add("\t" + name + " = \"" + comment + "\""); + } + + public void writeComments(PrintStream ps) { + this.comments.stream().forEach(ps::println); + } +} diff --git a/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java new file mode 100644 index 0000000000..3c596ca483 --- /dev/null +++ b/java_tools/configuration_definition/src/com/rusefi/newparse/outputs/TsWriter.java @@ -0,0 +1,32 @@ +package com.rusefi.newparse.outputs; + +import com.rusefi.newparse.ParseState; +import com.rusefi.newparse.layout.StructLayout; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; + +public class TsWriter { + public void writeTunerstudio(ParseState parser, String inputFile, String outputFile) throws FileNotFoundException { + // Write to file! + PrintStream ps = new PrintStream(new FileOutputStream(outputFile)); + + writeLayoutAndComments(parser, ps); + + ps.close(); + } + + private void writeLayoutAndComments(ParseState parser, PrintStream ps) { + StructLayout root = new StructLayout(0, "root", parser.getLastStruct()); + TsMetadata meta = new TsMetadata(); + + // Print configuration layout + root.writeTunerstudioLayout(ps, meta); + ps.println("; total TS size = " + root.getSize()); + + // Print context help + ps.println("[SettingContextHelp]"); + meta.writeComments(ps); + } +}