From 93ce61f94d2ffef218be47197f569fb6c9268baa Mon Sep 17 00:00:00 2001 From: Sparky6 Date: Mon, 13 Mar 2023 12:30:18 +0100 Subject: [PATCH] csharp-s6ts --- csharp/bin/mdoc | 5 + csharp/mDoc/Program.cs | 40 ++++++ csharp/mDocLib/Worker.cs | 242 +++++++++++++++++++++++++++++++++++ csharp/mutil/XmlExtractor.cs | 109 ++++++++++++++++ 4 files changed, 396 insertions(+) create mode 100755 csharp/bin/mdoc create mode 100644 csharp/mDoc/Program.cs create mode 100644 csharp/mDocLib/Worker.cs create mode 100644 csharp/mutil/XmlExtractor.cs diff --git a/csharp/bin/mdoc b/csharp/bin/mdoc new file mode 100755 index 0000000..e771ed2 --- /dev/null +++ b/csharp/bin/mdoc @@ -0,0 +1,5 @@ +#!/bin/bash + +export MONO_PATH=/usr/lib/mdoc-tools +mono /usr/lib/mdoc-tools/mdoc.exe $* + diff --git a/csharp/mDoc/Program.cs b/csharp/mDoc/Program.cs new file mode 100644 index 0000000..39110a2 --- /dev/null +++ b/csharp/mDoc/Program.cs @@ -0,0 +1,40 @@ +// See https://aka.ms/new-console-template for more information + +using System; +using mDoc; + +class mDocMain{ + static int command_dispatch(string[] args) { + + // check runtime parameters + if (args.Length < 2) throw new ApplicationException("mdoc needs 2 arguments."); + + string file = args[0]; + string template = args[1]; + + Worker w = new Worker(); + return w.convert(file, template); + } + public static int Main(string[] argv){ + Console.WriteLine("mdoc"); + + string usage = "mdoc "; + + if (argv.Length < 1) { + Console.WriteLine(usage); + return 1; + } + + try { + int ret = command_dispatch(argv); + if (ret != 0) { + Console.WriteLine(usage); + } + return ret; + } + catch (Exception e) { + Console.WriteLine(e.ToString()); + throw new Exception(e.ToString()); + } + } +} diff --git a/csharp/mDocLib/Worker.cs b/csharp/mDocLib/Worker.cs new file mode 100644 index 0000000..ab73c6b --- /dev/null +++ b/csharp/mDocLib/Worker.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +using mutil; + +namespace mDoc{ + +public class Worker +{ + private XmlExtractor source; + private string target; + private StreamWriter outfile; + private XmlExtractor global_defs; + private XmlExtractor hierarc; + + private void print_tpl_text(Dictionary attrs, string text) { + string rgx = @"\$\w+"; + foreach (Match match in Regex.Matches(text, rgx)) { + string subst = attrs[match.Value.Substring(1)]; + text = text.Replace(match.Value, subst); + } + outfile.Write(text); + } + private void process_file_layer() { + + int ctl = XmlExtractor.EC_BEG; + string elem; + string doc_value; + string tpl_value; + string dummy; + Dictionary sattrs = null; + Dictionary tattrs = null; + object tpl_node = null; + + // extract current data + source.getCurrentNodeData(out elem, out dummy, out sattrs); + + // work only on copy + XmlExtractor globex = new XmlExtractor(global_defs.CurrentNode); + + bool process_node = false; + bool hierarc_decend = false; + // check verbatim + if (elem == "verbatim" && sattrs["target"] == target) { + process_node = true; + // => no search for template data + } + else { + // search for template data + if (this.hierarc != null) tpl_node = this.hierarc.gotoChild(elem); + if (tpl_node != null) hierarc_decend = true; + else tpl_node = globex.gotoChild(elem); + if (tpl_node != null) process_node = true; + } + if (process_node) { + if (tpl_node != null) { + // process template pre node + XmlExtractor nodeex = new XmlExtractor(tpl_node); + object test_node = nodeex.gotoChild("pre"); + if (test_node != null) { + nodeex.getCurrentNodeData(out dummy, out tpl_value, out tattrs); + print_tpl_text(sattrs, tpl_value); + nodeex.toParent(); + } + } + // process source node + string child_elem; + Dictionary cattrs = null; + ctl = source.extractElement(ctl, out child_elem, out doc_value, out cattrs); + while (ctl != XmlExtractor.EC_END) { + if (doc_value != null) { + // text_node + outfile.Write(doc_value); + } else if (child_elem != null) { + // tag node + this.process_file_layer(); + } else { + throw new Exception("Neither text or tag?"); + } + ctl = source.extractElement(ctl, out child_elem, out doc_value, out cattrs); + } + if (tpl_node != null) { + // process template post node + XmlExtractor nodeex = new XmlExtractor(tpl_node); + object test_node = nodeex.gotoChild("post"); + if (test_node != null) { + nodeex.getCurrentNodeData(out dummy, out tpl_value, out tattrs); + print_tpl_text(sattrs, tpl_value); + nodeex.toParent(); + } + } + if (hierarc_decend) hierarc.toParent(); + outfile.WriteLine(); + } else { + Console.WriteLine("No template entry for node: "+elem); + } + } + +/* + + print_tpl_text(tpl_node, "pre"); + + + + // 2) chech for leading texts + process_definitions(elem, value, attrs, global_defs, Leading: true); + process_definitions(elem, value, attrs, hierarc, Leading: true); + } + + + + // so gehts nicht, die items können mehrfach vorkommen! + + // check for hierarchical definition + object items = hiraex.gotoChild(elem); + if (items == null) { + // check for any global definition + items = globex.gotoChild(elem); + } + if (items != null) { + XmlExtractor itemex = new XmlExtractor(items, TextMode: true); + } + } + } + + + + + # search for "first" + for item in items: + if "position" in item["attrs"]: + if item["attrs"]["position"] == "first": + print (item["value"], end="", file=outfile) + # proceed working + for item in items: + if not "position" in item["attrs"]: + # determine line end + end = "\n" + if "end" in item["attrs"]: + end = item["attrs"]["end"] + # check "pre" + if "pre" in item["attrs"]: + text = item["attrs"]["pre"] + if text.startswith(r"\n"): + print (file=outfile) + text = text[2:] + print (text, end="", file=outfile) + if "exec" in item["attrs"]: + # call function + store_current_node = source.currentNode + l = {"out" : None, "source":source} + exec(functions[item["attrs"]["exec"]], globals(), l) + # proceed on previous position + source.currentNode = store_current_node + print (l["out"], file=outfile) + else: + # proceed working + nexthiera = item["items"] + if value: + print (value, end="", file=outfile) + process_file_layer(source, outfile, global_defs, nexthiera, functions, target) + # check "post" + if "post" in item["attrs"]: + print (item["attrs"]["post"], end="", file=outfile) + print (end=end, file=outfile) + # search for "last" + for item in items: + if "position" in item["attrs"]: + if item["attrs"]["position"] == "last": + print (item["value"], end="", file=outfile) + + (ctl,elem, value, attrs) = source.extractElement(ctl) +*/ + public int convert(string file, string tpl_file) { + + // open xml document + source = new XmlExtractor(TextMode: true); + source.openInput(file); + + // goto root element + string elem; + string value; + Dictionary attrs; + source.extractElement(XmlExtractor.EC_BEG, out elem, out value, out attrs); + + // open template + XmlExtractor tple = new XmlExtractor(TextMode: true); + tple.openInput(tpl_file); + /* + functions_in_file = tpl["mdoc"][0]["items"]["functions"][0]["items"]["function"]; + // compile functions + var functions = new Dictionary(); + for f in functions_in_file: + name = f["attrs"]["name"] + functions[name] = compile(f["value"], '', "exec") + */ + + tple.requireChild("mdoc"); + tple.getCurrentNodeData(out elem, out value, out attrs); + string ext = attrs["extension"]; + + int cntl = XmlExtractor.EC_BEG; + + cntl = tple.extractElement(cntl, out elem, out value, out attrs); + while (cntl != XmlExtractor.EC_END) { + if (elem == "global") this.global_defs = new XmlExtractor(tple.CurrentNode, TextMode: true); + else if (elem == "hierarchical") this.hierarc = new XmlExtractor(tple.CurrentNode, TextMode: true); + cntl = tple.extractElement(cntl, out elem, out value, out attrs); + } + + // open output file + //outname = re.sub(r"\.xml", "."+ext, file) + string outname = file.Substring(0,file.IndexOf(".")+1) + ext; + using ( outfile = new StreamWriter (outname)) { + process_file_layer(); + } + return 0; + } +} + +} + +/* +from mutil.XmlExtractor import XmlExtractor +from mutil import XmlExtractor as XMLE +import re +''' +def outfirst(outfile, tpllayer, attrs, value): + if tpllayer["value"]: + ostr = tpllayer["value"] + if "$value" in ostr: + ostr = re.sub(r"\$value", value, ostr, flags=re.MULTILINE) + print (ostr, end="", file=outfile) + +def outlast(outfile, tpllayer, attrs, value): + if tpllayer["value"]: + print (file=outfile) +''' + +*/ diff --git a/csharp/mutil/XmlExtractor.cs b/csharp/mutil/XmlExtractor.cs new file mode 100644 index 0000000..f8bdb51 --- /dev/null +++ b/csharp/mutil/XmlExtractor.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Xml; + +namespace mutil { + +public class XmlExtractor { + public const int EC_BEG = 1; // begin of subtree (current node descends) - in + public const int EC_CTN = 2; // continue with next sibling element - in / out: data of found element + public const int EC_END = 3; // subtree completion (current node ascends); no data - out + + + private XmlDocument docNode; + private bool textMode; + public XmlNode CurrentNode; + + public XmlExtractor(object BaseNode = null, bool TextMode = false) { + this.CurrentNode = (XmlNode)BaseNode; + this.textMode = TextMode; + } + + public void openInput(string input){ + this.docNode = new XmlDocument(); + this.docNode.Load(input); + this.CurrentNode = this.docNode; + } + + public void toTop(){ + this.CurrentNode = this.docNode; + } + public void toParent(){ + this.CurrentNode = this.CurrentNode.ParentNode; + } + public int extractElement(int extr_ctl, out string elem, out string value, out Dictionary attrs) { + elem = ""; + value = null; + attrs = new Dictionary(); + + XmlNode srh_node; + + if (extr_ctl == EC_BEG) { + srh_node = this.CurrentNode.FirstChild; + } else if (extr_ctl == EC_CTN) { + srh_node = this.CurrentNode.NextSibling; + } else { + return EC_END; + } + + // search for next element node + if (! this.textMode) { + while (srh_node != null) { + if (srh_node.NodeType != XmlNodeType.Element) { + srh_node = srh_node.NextSibling; + } else { + break; + } + } + } + + if (srh_node != null) { + // element node found: extract tag name, value and attributes + this.CurrentNode = srh_node; + this.getCurrentNodeData(out elem, out value, out attrs); + return EC_CTN; + } else { + // terminate / ascend subtree after child extraction + if (extr_ctl == EC_CTN) { + this.CurrentNode = this.CurrentNode.ParentNode; + } + return EC_END; + } + + } + public void getCurrentNodeData(out string elem, out string value, out Dictionary attrs) { + elem = this.CurrentNode.Name; + value = null; + attrs = new Dictionary(); + if (this.textMode) { + if (this.CurrentNode.NodeType == XmlNodeType.Text) value = this.CurrentNode.Value; + } + else { + if (this.CurrentNode.InnerText != null) value = this.CurrentNode.InnerText; + } + if (this.CurrentNode.Attributes != null) { + for (int att_idx = 0; att_idx < this.CurrentNode.Attributes.Count; att_idx++) { + var att_node = this.CurrentNode.Attributes[att_idx]; + attrs[att_node.Name] = this.CurrentNode.Attributes[att_idx].Value; + } + } + } + public XmlNode gotoChild(string name) { + // return True/False, if child node could be found + int cntl = EC_BEG; + string elem; + string value; + Dictionary attrs; + while ((cntl = this.extractElement(cntl, out elem, out value, out attrs)) != EC_END) { + if (elem == name) return this.CurrentNode; + } + return null; + } + public XmlNode requireChild(string name) { + // throws exception, if child not present + XmlNode child = this.gotoChild(name); + if (child == null) throw new Exception("Could not find node "+name); + return child; + } +} +} -- 2.20.1