csharp-s6ts mdoc-tools_0.1-0
authorSparky6 <sparky6@core>
Mon, 13 Mar 2023 11:30:18 +0000 (12:30 +0100)
committerSparky6 <sparky6@core>
Mon, 13 Mar 2023 11:30:18 +0000 (12:30 +0100)
csharp/bin/mdoc [new file with mode: 0755]
csharp/mDoc/Program.cs [new file with mode: 0644]
csharp/mDocLib/Worker.cs [new file with mode: 0644]
csharp/mutil/XmlExtractor.cs [new file with mode: 0644]

diff --git a/csharp/bin/mdoc b/csharp/bin/mdoc
new file mode 100755 (executable)
index 0000000..e771ed2
--- /dev/null
@@ -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 (file)
index 0000000..39110a2
--- /dev/null
@@ -0,0 +1,40 @@
+// See https://aka.ms/new-console-template for more information\r
+\r
+using System;\r
+using mDoc;\r
+\r
+class mDocMain{\r
+    static int command_dispatch(string[] args) {\r
+\r
+        // check runtime parameters\r
+        if (args.Length < 2) throw new ApplicationException("mdoc needs 2 arguments.");\r
+        \r
+        string file = args[0];\r
+        string template = args[1];\r
+        \r
+        Worker w = new Worker();\r
+        return w.convert(file, template);\r
+    }\r
+    public static int Main(string[] argv){\r
+        Console.WriteLine("mdoc");\r
+\r
+        string usage = "mdoc <source> <target-format>";\r
+\r
+        if (argv.Length < 1) {\r
+            Console.WriteLine(usage);\r
+            return 1;\r
+        }\r
+\r
+        try {\r
+            int ret = command_dispatch(argv);\r
+            if (ret != 0) {\r
+                Console.WriteLine(usage);\r
+            }\r
+            return ret;\r
+        }\r
+        catch (Exception e) {\r
+            Console.WriteLine(e.ToString());\r
+            throw new Exception(e.ToString());\r
+        }\r
+    }\r
+}\r
diff --git a/csharp/mDocLib/Worker.cs b/csharp/mDocLib/Worker.cs
new file mode 100644 (file)
index 0000000..ab73c6b
--- /dev/null
@@ -0,0 +1,242 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Text.RegularExpressions;\r
+\r
+using mutil;\r
+\r
+namespace mDoc{\r
+\r
+public class Worker\r
+{\r
+    private XmlExtractor source;\r
+    private string target;\r
+    private StreamWriter outfile;\r
+    private XmlExtractor global_defs;\r
+    private XmlExtractor hierarc;\r
+   \r
+    private void print_tpl_text(Dictionary<string,string> attrs, string text) {\r
+         string rgx = @"\$\w+";\r
+         foreach (Match match in Regex.Matches(text, rgx)) {\r
+            string subst = attrs[match.Value.Substring(1)];\r
+            text = text.Replace(match.Value, subst);\r
+         }\r
+         outfile.Write(text);\r
+    }\r
+    private void process_file_layer() {\r
+\r
+        int ctl = XmlExtractor.EC_BEG;\r
+        string elem;\r
+        string doc_value;\r
+        string tpl_value;\r
+        string dummy;\r
+        Dictionary<string,string> sattrs = null;\r
+        Dictionary<string,string> tattrs = null;\r
+        object tpl_node = null;\r
+\r
+        // extract current data\r
+        source.getCurrentNodeData(out elem, out dummy, out sattrs);\r
+\r
+        // work only on copy\r
+        XmlExtractor globex = new XmlExtractor(global_defs.CurrentNode);\r
+\r
+        bool process_node = false;\r
+        bool hierarc_decend = false;\r
+        // check verbatim\r
+        if (elem == "verbatim" && sattrs["target"] == target) {\r
+            process_node = true;\r
+            // => no search for template data\r
+        }\r
+        else {\r
+            // search for template data\r
+            if (this.hierarc != null) tpl_node = this.hierarc.gotoChild(elem);\r
+            if (tpl_node != null) hierarc_decend = true;\r
+            else tpl_node = globex.gotoChild(elem);\r
+            if (tpl_node != null) process_node = true;\r
+        }\r
+        if (process_node) {\r
+            if (tpl_node != null) {\r
+                // process template pre node\r
+                XmlExtractor nodeex = new XmlExtractor(tpl_node);\r
+                object test_node = nodeex.gotoChild("pre");\r
+                if (test_node != null) {\r
+                    nodeex.getCurrentNodeData(out dummy, out tpl_value, out tattrs);\r
+                    print_tpl_text(sattrs, tpl_value);\r
+                    nodeex.toParent();\r
+                }\r
+            }\r
+            // process source node\r
+            string child_elem;\r
+            Dictionary<string,string> cattrs = null;\r
+            ctl = source.extractElement(ctl, out child_elem, out doc_value, out cattrs);\r
+            while (ctl != XmlExtractor.EC_END) {\r
+                if (doc_value != null) {\r
+                    // text_node\r
+                    outfile.Write(doc_value);\r
+                } else if (child_elem != null) {\r
+                    // tag node\r
+                    this.process_file_layer();\r
+                } else {\r
+                    throw new Exception("Neither text or tag?");\r
+                }\r
+                ctl = source.extractElement(ctl, out child_elem, out doc_value, out cattrs);\r
+            }\r
+            if (tpl_node != null) {\r
+                // process template post node\r
+                XmlExtractor nodeex = new XmlExtractor(tpl_node);\r
+                object test_node = nodeex.gotoChild("post");\r
+                if (test_node != null) {\r
+                    nodeex.getCurrentNodeData(out dummy, out tpl_value, out tattrs);\r
+                    print_tpl_text(sattrs, tpl_value);\r
+                    nodeex.toParent();\r
+                }\r
+            }\r
+            if (hierarc_decend) hierarc.toParent();\r
+            outfile.WriteLine();\r
+        } else {\r
+            Console.WriteLine("No template entry for node: "+elem);\r
+        }\r
+    }\r
+\r
+/*\r
+\r
+                 print_tpl_text(tpl_node, "pre");\r
+\r
+\r
+\r
+                // 2) chech for leading texts\r
+                process_definitions(elem, value, attrs, global_defs, Leading: true);\r
+                process_definitions(elem, value, attrs, hierarc, Leading: true);\r
+            }\r
+            \r
+\r
+\r
+            // so gehts nicht, die items können mehrfach vorkommen!\r
+\r
+            // check for hierarchical definition\r
+            object items = hiraex.gotoChild(elem);\r
+            if (items == null) {\r
+                // check for any global definition\r
+                items = globex.gotoChild(elem);\r
+            }\r
+            if (items != null) {\r
+                XmlExtractor itemex = new XmlExtractor(items, TextMode: true);\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+\r
+\r
+                # search for "first"\r
+                for item in items:\r
+                    if "position" in item["attrs"]:\r
+                        if item["attrs"]["position"] == "first":\r
+                            print (item["value"], end="", file=outfile)\r
+                # proceed working\r
+                for item in items:\r
+                    if not "position" in item["attrs"]:\r
+                        # determine line end\r
+                        end = "\n"\r
+                        if "end" in item["attrs"]:\r
+                            end = item["attrs"]["end"]\r
+                        # check "pre"\r
+                        if "pre" in item["attrs"]:\r
+                            text = item["attrs"]["pre"]\r
+                            if text.startswith(r"\n"):\r
+                                print (file=outfile)\r
+                                text = text[2:]\r
+                            print (text, end="", file=outfile)\r
+                        if "exec" in item["attrs"]:\r
+                            # call function\r
+                            store_current_node = source.currentNode\r
+                            l = {"out" : None, "source":source}\r
+                            exec(functions[item["attrs"]["exec"]], globals(), l)\r
+                            # proceed on previous position\r
+                            source.currentNode = store_current_node\r
+                            print (l["out"], file=outfile)\r
+                        else:\r
+                            # proceed working\r
+                            nexthiera = item["items"]\r
+                            if value:\r
+                                print (value, end="", file=outfile)\r
+                            process_file_layer(source, outfile, global_defs, nexthiera, functions, target)\r
+                        # check "post"\r
+                        if "post" in item["attrs"]:\r
+                            print (item["attrs"]["post"], end="", file=outfile)\r
+                        print (end=end, file=outfile)\r
+                # search for "last"\r
+                for item in items:\r
+                    if "position" in item["attrs"]:\r
+                        if item["attrs"]["position"] == "last":\r
+                            print (item["value"], end="", file=outfile)\r
+\r
+            (ctl,elem, value, attrs) = source.extractElement(ctl)\r
+*/\r
+    public int convert(string file, string tpl_file) {\r
+    \r
+        // open xml document\r
+        source = new XmlExtractor(TextMode: true);\r
+        source.openInput(file);\r
+\r
+        // goto root element\r
+        string elem;\r
+        string value;\r
+        Dictionary<string,string> attrs;\r
+        source.extractElement(XmlExtractor.EC_BEG, out elem, out value, out attrs);\r
+\r
+        // open template\r
+        XmlExtractor tple = new XmlExtractor(TextMode: true);\r
+        tple.openInput(tpl_file);\r
+        /*\r
+        functions_in_file = tpl["mdoc"][0]["items"]["functions"][0]["items"]["function"];\r
+        // compile functions\r
+        var functions = new Dictionary<string,string>();\r
+        for f in functions_in_file:\r
+            name = f["attrs"]["name"]\r
+            functions[name] = compile(f["value"], '<string>', "exec")\r
+        */\r
+        \r
+        tple.requireChild("mdoc");\r
+        tple.getCurrentNodeData(out elem, out value, out attrs);\r
+        string ext = attrs["extension"];\r
+\r
+        int cntl = XmlExtractor.EC_BEG;\r
+\r
+        cntl = tple.extractElement(cntl, out elem, out value, out attrs);\r
+        while (cntl != XmlExtractor.EC_END) {\r
+            if (elem == "global") this.global_defs = new XmlExtractor(tple.CurrentNode, TextMode: true);\r
+            else if (elem == "hierarchical") this.hierarc = new XmlExtractor(tple.CurrentNode, TextMode: true);\r
+            cntl = tple.extractElement(cntl, out elem, out value, out attrs);\r
+        }\r
+        \r
+        // open output file\r
+        //outname = re.sub(r"\.xml", "."+ext, file)\r
+        string outname = file.Substring(0,file.IndexOf(".")+1) + ext;\r
+        using ( outfile = new StreamWriter (outname)) {\r
+            process_file_layer();\r
+        }\r
+        return 0;\r
+    }\r
+}\r
+\r
+}\r
+\r
+/*\r
+from mutil.XmlExtractor import XmlExtractor\r
+from mutil import XmlExtractor as XMLE\r
+import re\r
+'''\r
+def outfirst(outfile, tpllayer, attrs, value):\r
+    if tpllayer["value"]:\r
+        ostr = tpllayer["value"]\r
+        if "$value" in ostr:\r
+            ostr = re.sub(r"\$value", value, ostr, flags=re.MULTILINE)\r
+        print (ostr, end="", file=outfile)\r
+\r
+def outlast(outfile, tpllayer, attrs, value):\r
+    if tpllayer["value"]:\r
+        print (file=outfile)\r
+'''\r
+        \r
+*/\r
diff --git a/csharp/mutil/XmlExtractor.cs b/csharp/mutil/XmlExtractor.cs
new file mode 100644 (file)
index 0000000..f8bdb51
--- /dev/null
@@ -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<string,string> attrs) { 
+               elem  = "";
+               value = null;
+               attrs = new Dictionary<string,string>();
+
+               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<string,string> attrs) {
+           elem = this.CurrentNode.Name;
+               value = null;
+               attrs = new Dictionary<string,string>();
+               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<string,string> 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;
+       }
+}
+}