private Module FindModule(string className, string header)
        {
            UpdateSourceTagCache(header);
            string source = allSource[header];
            string tags   = allTags[header];

            // does this class have an exported name?
            bool            found = false;
            MatchCollection coll  = Regex.Matches(tags, @"^ClassName\t(\S+)\t/(.*?)/;""\tkind:(\S+)\t(?:namespace|class):(\S+)(?:\tinherits:(\S+))?(?:\ttyperef:none:(\w+)?)?", RegexOptions.Multiline);

            foreach (Match m in coll)
            {
                if (m.Groups[3].Captures[0].Value.Equals("function") &&
                    m.Groups[4].Captures[0].Value.EndsWith("::" + className))
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                // that's not a module
                return(null);
            }

            Match cs = Regex.Match(source, @"class\s+(?:\w+\s+)?" + className + @".*?" +
                                   @"static\s+const\s+char\s*\*\s*ClassName\s*\(\s*(?:void)?\s*\)\s*{\s*return\s*""(.*?)""\s*;", RegexOptions.Singleline);

            if (cs.Success)
            {
                return(AnalyzerData.GetModuleByExportedName(cs.Groups[1].Captures[0].Value));
            }
            Debug.WriteLine("Cannot find Module " + className + "'s ClassName in " + header);
            return(null);
        }
        private Module InvestigateModule(string name, string header)
        {
            UpdateSourceTagCache(header);
            string source = allSource[header];
            string tags   = allTags[header];

            // find the constructor
            Match m = Regex.Match(source, name + "::" + name + @".*?{(.*)}", RegexOptions.Singleline);

            if (m.Success)
            {
                string constrCode = m.Groups[1].Captures[0].Value;
                if (constrCode.Contains("SetCallback") || constrCode.Contains("SetCompatibleCall"))
                {
                    // that's some kind of module!
                    Module mod = new Module()
                    {
                        ClassName    = name,
                        SourceFile   = header,
                        ExportedName = null
                    };
                    AnalyzerData.AddModule(mod);
                    return(mod);
                }
            }
            return(null);
        }
        private void ParseOutput(string output)
        {
            //Regex r = new Regex(@"^([^\t]+)\t([^\t]+)\t\d+;.\tkind:([^\t]+)\tnamespace:([^\t]+)(?:\tinherits:(\S+))?\r\n$");
            //string ex = @"^(\S+)\t(\S+)\t\d+;.\tkind:(\S+)\tnamespace:(\S+)(?:\tinherits:(\S+))?$";
            string          ex      = @"^(\S+)\t(\S+)\t/(.*?)/;""\tkind:(\S+)\t(?:namespace|class):(\S+)(?:\tinherits:(\S+))?(?:\ttyperef:none:(\w+)?)?";
            MatchCollection matches = Regex.Matches(output, ex, RegexOptions.Multiline);

            if (matches.Count > 0)
            {
                foreach (Match m in matches)
                {
                    if (m.Groups[4].Captures[0].Value.Equals("class"))
                    {
                        Module mod = FindModule(m.Groups[1].Captures[0].Value, m.Groups[2].Captures[0].Value);
                        if (mod == null)
                        {
                            // could be a call
                            Call call = FindCall(m.Groups[1].Captures[0].Value, m.Groups[2].Captures[0].Value);
                            if (call == null)
                            {
                                // could be an abstract Module that sets call compatibility anyway!
                                mod = InvestigateModule(m.Groups[1].Captures[0].Value, m.Groups[2].Captures[0].Value);
                            }
                            else
                            {
                                call.ClassName  = m.Groups[5].Captures[0].Value + "::" + m.Groups[1].Captures[0].Value;
                                call.SourceFile = m.Groups[2].Captures[0].Value;
                                // calls do not support inheritance
                                //AnalyzerData.AddModule(mod);
                            }
                        }
                        if (mod != null)
                        {
                            mod.ClassName  = m.Groups[5].Captures[0].Value + "::" + m.Groups[1].Captures[0].Value;
                            mod.SourceFile = m.Groups[2].Captures[0].Value;
                            if (m.Groups[6].Captures.Count > 0)
                            {
                                string[] inherits = m.Groups[6].Captures[0].ToString().Split(new char[] { ',' });
                                foreach (string inh in inherits)
                                {
                                    Inheritance i = new Inheritance();
                                    i.name = inh;
                                    mod.Inherited.Add(i);
                                }
                            }
                            //AnalyzerData.AddModule(mod);
                        }
                    }
                }

                foreach (Match m in matches)
                {
                    if (m.Groups[4].Captures[0].Value.Equals("member"))
                    {
                        string container = m.Groups[5].Captures[0].Value;
                        Module parent    = AnalyzerData.GetModuleByClassName(container);
                        if (parent == null)
                        {
                            //Debug.WriteLine("Cannot find parent " + container + " of Member " + m.Groups[1].Captures[0].Value);
                        }
                        else
                        {
                            string mname = m.Groups[1].Captures[0].Value;
                            //Match localm = Regex.Match(m.Groups[3].Captures[0].Value, @"(.*?)\s+(?:\*)*"+mname+@"\s*(?:\[.*?\]\s*)?(?:\s*=.*?)?;");
                            if (m.Groups[7].Captures.Count > 0)
                            {
                                string mtype = m.Groups[7].Captures[0].Value;
                                if (Module.ClassMatches("megamol::core::CallerSlot", mtype))
                                {
                                    UnderstandCallerSlot(parent, mname, m.Groups[2].Captures[0].Value);
                                }
                                if (Module.ClassMatches("megamol::core::CalleeSlot", mtype))
                                {
                                    UnderstandCalleeSlot(parent, mname, m.Groups[2].Captures[0].Value);
                                }
                                if (Module.ClassMatches("megamol::core::param::ParamSlot", mtype))
                                {
                                    UnderstandParam(parent, mname, m.Groups[2].Captures[0].Value);
                                }
                            }
                        }
                    }
                }
            }
        }