Author: Slava Risenberg <slava@ezchip.com>

[447553] Added support for C code libhover metadata generated from
Doxygen

Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=447553
Signed-off-by: Slava Risenberg <slava@ezchip.com>
Change-Id: I5935495681a805270a40c6c986ed3385721ad9af
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/BuildFunctionInfos.java b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/BuildFunctionInfos.java
index 33245f6..89b6727 100644
--- a/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/BuildFunctionInfos.java
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/BuildFunctionInfos.java
@@ -1,5 +1,6 @@
 /*******************************************************************************
- * Copyright (c) 2009 Red Hat, Inc.
+ * Copyright (c) 2004, 2006, 2007, 2008, 2011, 2012 Red Hat, Inc.
+ * Copyright (c) 2015 Ezchip Semiconductor
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,14 +8,13 @@
  *
  * Contributors:
  *     Red Hat Incorporated - initial API and implementation
+ *     EZchip Semiconductor - adding support for Doxygen XML files as input
  *******************************************************************************/
 package org.eclipse.linuxtools.internal.cdt.libhover.utils;
 
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.ObjectOutputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -25,142 +25,17 @@
 
 import org.eclipse.core.filesystem.URIUtil;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.linuxtools.cdt.libhover.FunctionInfo;
-import org.eclipse.linuxtools.cdt.libhover.LibHoverInfo;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
 public class BuildFunctionInfos {
-
-    private Document document;
-    private LibHoverInfo hoverInfo = new LibHoverInfo();
-
-    public BuildFunctionInfos(Document document) {
-        this.document = document;
-    }
-
-    public Document getDocument() {
-        return document;
-    }
-
-    private FunctionInfo getFunctionInfoFromNode(String name, Node functionNode, Document document) {
-        FunctionInfo f = new FunctionInfo(name);
-        NamedNodeMap functionNodeMap = functionNode.getAttributes();
-        Node functionNodeReturntypeNode = functionNodeMap.item(0);
-        String functionNodeRtName = functionNodeReturntypeNode.getNodeName();
-
-        if (functionNodeRtName.equals("returntype")) { //$NON-NLS-1$
-
-            // return type
-
-            String functionNodeRtValue = functionNodeReturntypeNode.getNodeValue();
-            f.setReturnType(functionNodeRtValue);
-        }        // returntype
-
-        NodeList kids = functionNode.getChildNodes();
-        for (int fnk = 0; fnk < kids.getLength(); fnk++) {
-            Node kid = kids.item(fnk);
-            String kidName = kid.getNodeName();
-            if (kidName.equals("prototype")) { //$NON-NLS-1$
-
-                // prototype
-
-                String prototype = null;
-
-                NodeList parms = kid.getChildNodes();
-                for (int fnp = 0; fnp < parms.getLength(); fnp++) {
-                    Node parm = parms.item(fnp);
-                    String parmName =  parm.getNodeName();
-                    if (parmName.equals("parameter")) { //$NON-NLS-1$
-                        NamedNodeMap parmMap = parm.getAttributes();
-                        Node parmNode = parmMap.item(0);
-                        String parameter = parmNode.getNodeValue();
-                        prototype = (null == prototype) ? parameter : prototype
-                                + ", " + parameter; //$NON-NLS-1$
-                    }
-                }
-                f.setPrototype(prototype);
-            }    // prototype
-
-            else if (kidName.equals("headers")) { //$NON-NLS-1$
-
-                // headers
-
-                NodeList headers = kid.getChildNodes();
-                for (int fnh = 0; fnh < headers.getLength(); fnh++) {
-                    Node header = headers.item(fnh);
-                    String headerName =  header.getNodeName();
-                    if (headerName.equals("header")) { //$NON-NLS-1$
-                        NamedNodeMap headerMap = header.getAttributes();
-                        Node headerNode = headerMap.item(0);
-                        f.addHeader(headerNode.getNodeValue());
-                    }
-                }
-            }    // headers
-
-
-            else if (kidName.equals("groupsynopsis")) { //$NON-NLS-1$
-
-                // group synopsis
-
-                NamedNodeMap attr = kid.getAttributes();
-                Node idnode = attr.getNamedItem("id"); //$NON-NLS-1$
-                String id = idnode.getNodeValue();
-                if (id != null) {
-                    Element elem2 = document.getElementById(id);
-                    if (null != elem2) {
-                        NodeList synopsisNode = elem2.getElementsByTagName("synopsis"); //$NON-NLS-1$
-                        if (null != synopsisNode && synopsisNode.getLength() > 0) {
-                            Node synopsis = synopsisNode.item(0);
-                            Node textNode = synopsis.getLastChild();
-                            f.setDescription(textNode.getNodeValue());
-                        }
-                    }
-                }
-            } else if (kidName.equals("synopsis")) { //$NON-NLS-1$
-                // synopsis
-                Node textNode = kid.getLastChild();
-                f.setDescription(textNode.getNodeValue());
-            }
-        }
-        return f;
-    }
-
-    private void buildCPPInfo(String fileName) {
-        Document document = getDocument();
-        NodeList nl = document.getElementsByTagName("construct"); //$NON-NLS-1$
-        for (int i = 0; i < nl.getLength(); ++i) {
-            Node n = nl.item(i);
-            NamedNodeMap m = n.getAttributes();
-            Node id = m.getNamedItem("id"); //$NON-NLS-1$
-            if (id != null && id.getNodeValue().startsWith("function-")) { //$NON-NLS-1$
-                String name = id.getNodeValue().substring(9);
-                NodeList nl2 = n.getChildNodes();
-                for (int j = 0; j < nl2.getLength(); ++j) {
-                    Node n2 = nl2.item(j);
-                    if (n2.getNodeName().equals("function")) { //$NON-NLS-1$
-                        FunctionInfo f = getFunctionInfoFromNode(name, n2, document);
-                        hoverInfo.functions.put(name, f);
-                    }
-                }
-            }
-        }
-        try (FileOutputStream f = new FileOutputStream(fileName);
-            ObjectOutputStream out = new ObjectOutputStream(f)){
-            // Now, output the LibHoverInfo for caching later
-            out.writeObject(hoverInfo);
-        } catch(IOException e) {
-            e.printStackTrace();
-        }
-    }
+	
+    private static final String IS_DOXYGEN = "--doxygen"; //$NON-NLS-1$
 
     /**
      * @param args args[0] - URL or file name of xml document to parse
      *        args[1] - file name to place resultant serialized LibHoverInfo
+     *        args[2] - optional parameter in form of '--doxygen' whether provided XML file in doxygen format
      */
     public static void main(String[] args) {
         URI acDoc;
@@ -174,19 +49,18 @@
             } else {
                 docStream = new FileInputStream(p.toFile());
             }
+            
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             factory.setValidating(false);
             DocumentBuilder builder = factory.newDocumentBuilder();
             Document doc = builder.parse(docStream);
-            if (doc != null) {
-                BuildFunctionInfos d = new BuildFunctionInfos(doc);
-                d.buildCPPInfo(args[1]);
-            }
+            LibhoverInfoGenerator libhoverInfoGenerator = (args.length == 3 && IS_DOXYGEN.equals(args[2]))?new CDoxygenLibhoverGen(doc):new CXmlLibhoverGen(doc);
+        	libhoverInfoGenerator.generate(args[1]);
+            
             System.out.println("Built " + args[1] + " from " + args[0]); //$NON-NLS-1$ //$NON-NLS-2$
         } catch (URISyntaxException|SAXException|ParserConfigurationException|IOException e) {
             e.printStackTrace();
         }
 
     }
-
 }
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CDoxygenLibhoverGen.java b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CDoxygenLibhoverGen.java
new file mode 100644
index 0000000..9ae7ed5
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CDoxygenLibhoverGen.java
@@ -0,0 +1,667 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Red Hat, Inc.
+ * Copyright (c) 2015 Ezchip Semiconductor
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     EZchip Semiconductor - adding support for Doxygen XML files as input
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.cdt.libhover.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.linuxtools.cdt.libhover.ClassInfo;
+import org.eclipse.linuxtools.cdt.libhover.FunctionInfo;
+import org.eclipse.linuxtools.cdt.libhover.LibHoverInfo;
+import org.eclipse.linuxtools.cdt.libhover.MemberInfo;
+import org.eclipse.linuxtools.cdt.libhover.TypedefInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class CDoxygenLibhoverGen extends LibhoverInfoGenerator{
+
+    private static final String PROT3 = "prot";//$NON-NLS-1$
+	private static final String RETURN = "return";//$NON-NLS-1$
+	private static final String PARAMETERDESCRIPTION = "parameterdescription";//$NON-NLS-1$
+	private static final String PARAMETERNAME = "parametername";//$NON-NLS-1$
+	private static final String PARAMETERNAMELIST = "parameternamelist";//$NON-NLS-1$
+	private static final String PARAMETERITEM = "parameteritem";//$NON-NLS-1$
+	private static final String EXCEPTION = "exception";//$NON-NLS-1$
+	private static final String DEFINITION = "definition";//$NON-NLS-1$
+	private static final String TYPEDEF2 = "typedef";//$NON-NLS-1$
+	private static final String REFID2 = "refid";//$NON-NLS-1$
+	private static final String REF = "ref";//$NON-NLS-1$
+	private static final String PUBLIC_FUNC = "public-func";//$NON-NLS-1$
+	private static final String BASECOMPOUNDREF = "basecompoundref";//$NON-NLS-1$
+	private static final String INCLUDES = "includes";//$NON-NLS-1$
+	private static final String DECLNAME = "declname";//$NON-NLS-1$
+	private static final String TEMPLATEPARAMLIST = "templateparamlist";//$NON-NLS-1$
+	private static final String CLASS = "class";//$NON-NLS-1$
+	private static final String PUBLIC = "public";//$NON-NLS-1$
+	private static final String LOCATION = "location";//$NON-NLS-1$
+	private static final String SIMPLESECT = "simplesect";//$NON-NLS-1$
+	private static final String PARAMETERLIST = "parameterlist";//$NON-NLS-1$
+	private static final String DETAILEDDESCRIPTION = "detaileddescription";//$NON-NLS-1$
+	private static final String PARA = "para";//$NON-NLS-1$
+	private static final String BRIEFDESCRIPTION = "briefdescription";//$NON-NLS-1$
+	private static final String TYPE2 = "type";//$NON-NLS-1$
+	private static final String PARAM = "param";//$NON-NLS-1$
+	private static final String ARGSSTRING = "argsstring";//$NON-NLS-1$
+	private static final String NAME3 = "name";//$NON-NLS-1$
+	private static final String FUNCTION = "function";//$NON-NLS-1$
+	private static final String MEMBERDEF = "memberdef";//$NON-NLS-1$
+	private static final String FUNC = "func";//$NON-NLS-1$
+	private static final String SECTIONDEF = "sectiondef";//$NON-NLS-1$
+	private static final String COMPOUNDNAME = "compoundname";//$NON-NLS-1$
+	private static final String FILE = "file";//$NON-NLS-1$
+	private static final String COMPOUNDDEF = "compounddef";//$NON-NLS-1$
+	private static final String TYPEDEF = "typedef ";//$NON-NLS-1$
+	private Document document;
+    private Map<String, ClassInfo> classesById = new HashMap<>();
+
+    public CDoxygenLibhoverGen(Document document) {
+        this.document = document;
+    }
+
+    private String[] getTypedefTypes(String def) {
+        String[] result = null;
+        if (def.startsWith(TYPEDEF)) { 
+            int startIndex = 8;
+            int count = 0;
+            int i = def.length() - 1;
+            // To break up types, we look for first blank outside of a template, working backwards.
+            // We need to work backwards because the transformed type may contain actual numeric parameters
+            // which could use the shift operators and we won't know whether they are shift operators or
+            // template specifiers without some actual parsing.
+            while (i >= 0) {
+                char ch = def.charAt(i);
+                if (ch == '<') {
+                    --count;
+                } else if (ch == '>') {
+                    ++count;
+                }
+                // We look at last blank not in a template as being the delimeter between
+                // type name and definition.
+                if (count == 0 && ch == ' ') {
+                    startIndex = i + 1;
+                    break;
+                }
+                --i;
+            }
+            result = new String[2];
+            result[1] = def.substring(startIndex);
+            // Following is a bit of a hack knowing the docs don't add the namespace when the transformed
+            // type is in the same space
+            int namespace = result[1].indexOf("::"); //$NON-NLS-1$
+            if (namespace < 0) {
+                result[0] = def.substring(8, startIndex).trim();
+            } else {
+                result[0] = result[1].substring(0, namespace) + "::" + def.substring(8, startIndex).trim(); //$NON-NLS-1$
+            }
+        }
+        return result;
+    }
+
+    private String getElementText(Node node) {
+        StringBuffer d = new StringBuffer();
+        NodeList nl = node.getChildNodes();
+        for (int x = 0; x < nl.getLength(); ++x) {
+            Node text = nl.item(x);
+            if (text.getNodeType() == Node.TEXT_NODE) {
+                d.append(text.getNodeValue());
+            } else {
+                d.append(getElementText(text));
+            }
+        }
+        return d.toString();
+    }
+
+    private ClassInfo getClassInfo(LibHoverInfo libHoverInfo, String className) {
+        String typedefName = className.replaceAll("<.*>", "<>"); //$NON-NLS-1$ //$NON-NLS-2$
+        TypedefInfo typedef = libHoverInfo.typedefs.get(typedefName);
+        if (typedef != null) {
+            className = typedef.getTransformedType(className);  // Reset class name to typedef transformation
+        }
+        int index = className.indexOf('<');
+        // Check if it is a template reference.
+        if (index != -1) {
+            // It is.  We want to see if there are partial specific templates
+            // and we choose the first match.  If nothing matches our particular
+            // case, we fall back on the initial generic template.
+            ClassInfo info = libHoverInfo.classes.get(className.substring(0, index));
+            if (info == null)
+                return null;
+            ArrayList<ClassInfo> children = info.getChildren();
+            if (children != null && children.size() > 0) {
+                for (int x = 0; x < children.size(); ++x) {
+                    ClassInfo child = children.get(x);
+                    if (className.matches(child.getClassName())) {
+                        info = child;
+                        break;
+                    }
+                }
+            }
+            return info;
+        }
+        // Otherwise no template, just fetch the class info directly.
+        return libHoverInfo.classes.get(className);
+    }
+
+    @Override
+    public LibHoverInfo doGenerate(){
+    	LibHoverInfo libHoverInfo = new LibHoverInfo();
+        // Create a hash table of all the class nodes mapped by class name.  Trim any template info
+		// for the class name key value.
+		NodeList nl = document.getElementsByTagName(COMPOUNDDEF);  
+		for (int i = 0; i < nl.getLength(); ++i) {
+		    Node n = nl.item(i);
+		    NamedNodeMap attrs = n.getAttributes();
+		    Node kind = attrs.getNamedItem("kind");  //$NON-NLS-1$
+		    Node id = attrs.getNamedItem("id");  //$NON-NLS-1$
+		    Node prot = attrs.getNamedItem(PROT3); 
+		    
+		    // C functions
+		    if (id != null && kind != null && FILE.equals(kind.getNodeValue())) { 
+		        NodeList nl2 = n.getChildNodes();
+		        FunctionInfo fi = null;
+		        String include = null;
+		        for (int j = 0; j < nl2.getLength(); ++j) {
+		            Node n2 = nl2.item(j);
+		            String name2 = n2.getNodeName();
+		           
+		            if (COMPOUNDNAME.equals(name2)) { 
+		            	// compoundname for a file node is the filename 
+		            	// this can be a .c or .h file
+		            	String filename = getElementText(n2); 
+		            	if(filename.endsWith(".h")) { //$NON-NLS-1$
+		            		include = filename; 
+		            	}
+		            } else if (SECTIONDEF.equals(name2)) {  
+		                // We are only interested in functions 
+		                NamedNodeMap m = n2.getAttributes();
+		                if (m != null) {
+		                    Node kind2 = m.getNamedItem("kind");  //$NON-NLS-1$
+		                    if (kind2 != null && FUNC.equals(kind2.getNodeValue())) { 
+		                        NodeList pubfuncs = n2.getChildNodes();
+		                        int pubfuncLength = pubfuncs.getLength();
+		                        for (int j1 = 0; j1 < pubfuncLength; ++j1) {
+		                            Node n3 = pubfuncs.item(j1);
+		                            // Add all public member functions to the list of members
+		                            if (MEMBERDEF.equals(n3.getNodeName())) {  
+		                                NamedNodeMap m3 = n3.getAttributes();
+		                                if (m3 != null) {
+		                                    Node m3Kind = m3.getNamedItem("kind");  //$NON-NLS-1$
+		                                    if (m3Kind != null && FUNCTION.equals(m3Kind.getNodeValue())) { 
+		                                        String name = null;
+		                                        String type = null;
+		                                        String args = null;
+		                                        String desc = null;
+		                                        
+		                                        boolean briefDescriptionProcessed = false;
+		                                        boolean detailedDescriptionProcessed = false;
+                                            	boolean parameterListProcessed = false;
+                                            	boolean retValProcessed = false;
+                                            	boolean locationProcessed = false;
+                                            	
+		                                        ArrayList<String> parms = new ArrayList<>();
+		                                        NodeList nl4 = n3.getChildNodes();
+		                                        int memberLength = nl4.getLength();
+		                                        for (int k = 0; k < memberLength; ++k) {
+		                                            Node n4 = nl4.item(k);
+		                                            String n4Name = n4.getNodeName();
+		                                            if (TYPE2.equals(n4Name)) {  
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                type = "";  //$NON-NLS-1$
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (n5.getNodeType() == Node.TEXT_NODE)
+		                                                        type += n5.getNodeValue();                                                                
+		                                                }
+		                                            } else if (NAME3.equals(n4Name)) {  
+		                                                name = n4.getTextContent();
+		                                            } else if (ARGSSTRING.equals(n4Name)) {  
+		                                                args = getElementText(n4);
+		                                            } else if (PARAM.equals(n4Name)) {  
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (TYPE2.equals(n5.getNodeName())) { 
+		                                                        parms.add(getElementText(n5));
+		                                                    }
+		                                                }
+		                                            } else if (BRIEFDESCRIPTION.equals(n4Name) && !briefDescriptionProcessed ) {  
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (PARA.equals(n5.getNodeName())) { 
+		                                                        if (desc == null) {
+		                                                            desc = ""; //$NON-NLS-1$
+		                                                        }
+		                                                        desc += "<p>" + getElementText(n5) + "</p>";   //$NON-NLS-1$ //$NON-NLS-2$
+		                                                        briefDescriptionProcessed = true;
+		                                                    }
+		                                                }
+		                                            } else if (DETAILEDDESCRIPTION.equals(n4Name)) { 		                                          
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (n5.getNodeName().equals(PARA)) {  
+		                                                        if (desc == null)
+		                                                            desc = new String("");  //$NON-NLS-1$
+		                                                        NodeList nl6 = n5.getChildNodes();
+		                                                        Node n6 = nl6.item(0);
+		                                                        if (n6.getNodeType() == Node.TEXT_NODE && !detailedDescriptionProcessed){
+		                                                            desc += "<p>" + getElementText(n5) + "</p>";   //$NON-NLS-1$ //$NON-NLS-2$
+		                                                            detailedDescriptionProcessed = true;
+		                                                        } else {
+		                                                            for (int x2 = 0; x2 < nl6.getLength(); ++x2) {
+		                                                                n6 = nl6.item(x2);
+		                                                                if (PARAMETERLIST.equals(n6.getNodeName()) && !parameterListProcessed) { 
+		                                                                    desc += getParameters(n6, false);
+		                                                                    parameterListProcessed = true;
+		                                                                } else if (SIMPLESECT.equals(n6.getNodeName()) & !retValProcessed) { 
+		                                                                    desc += getReturn(n6);
+		                                                                    retValProcessed = true;
+		                                                                }
+		                                                            }
+		                                                        }
+		                                                    }
+		                                                }
+		                                            } else if (LOCATION.equals(n4Name) && !locationProcessed) { 
+		                                                // Location is after all descriptions so we can now add the function
+		                                                if (name != null) {
+		                                                	// Try to update existing function, in case information is split between .c and .h files
+		                                                	fi = libHoverInfo.functions.get(name);
+		                                                	if (fi == null) {
+		                                                		fi = new FunctionInfo(name);
+		                                                	}
+		                                                	if (type != null) {
+		                                                		fi.setReturnType(type);
+		                                                	}  
+		                                                	if (args != null) {
+		                                                        // Strip ()s, as the plugin adds them back in
+		                                                        if(args.charAt(0) == '(' && args.charAt(args.length() - 1) == ')')
+		                                                        	fi.setPrototype(args.substring(1, args.length() - 1));
+		                                                        else
+		                                                        	fi.setPrototype(args);
+		                                                	}
+		                                                	if (desc != null) {
+		                                                		fi.setDescription(desc);
+		                                                	}
+		                                                    if(include != null) {
+		                                                    	fi.addHeader(include);
+		                                                    }                                                                
+		                                                    //System.out.println(name + "|" + type +  "|" + args +  "|" + desc +  "|" + include);                                                                                                                                
+		                                                    libHoverInfo.functions.put(name, fi);
+		                                                    locationProcessed = true;
+		                                                }		                                                
+		                                                break;
+		                                            }
+		                                        }
+		                                    }
+		                                }
+		                            }
+		                        }
+		                    }
+		                }
+		            }
+		        }
+		    }
+		    	                
+		    // We are only interested in cataloging public classes.
+		    if (id != null && prot != null && PUBLIC.equals(prot.getNodeValue()) 
+		            && kind != null && CLASS.equals(kind.getNodeValue())) {  
+		        NodeList nl2 = n.getChildNodes();
+		        ClassInfo d = null;
+		        String hashName = null;
+		        for (int j = 0; j < nl2.getLength(); ++j) {
+		            Node n2 = nl2.item(j);
+		            String name2 = n2.getNodeName();
+		            if (name2.equals(COMPOUNDNAME)) {  
+		                String text = n2.getTextContent();
+		                if (text != null && !text.equals("")) { //$NON-NLS-1$
+		                    String className = text;
+		                    text = text.replaceAll("<\\s*", "<");   //$NON-NLS-1$ //$NON-NLS-2$
+		                    text = text.replaceAll("\\s*>", ">");   //$NON-NLS-1$ //$NON-NLS-2$
+		                    int index = text.indexOf('<');
+		                    hashName = text;
+		                    if (index > 0)
+		                        hashName = text.substring(0, index);
+		                    d = new ClassInfo(className, n);
+		                    classesById.put(id.getNodeValue(), d);
+		                    ClassInfo e = libHoverInfo.classes.get(hashName);
+		                    if (e != null) { /* We are dealing with a partial specific template...add it to list  */
+		                        if (!d.areTemplateParmsFilled())
+		                            d.setTemplateParms(getTemplateParms(n));
+		                        String[] templateParms = d.getTemplateParms();
+		                        // For each template parameter, replace with a generic regex so later we can compare
+		                        // and identify a match (e.g. A<_a, _b> and A<char, _b> are defined and we have an instance
+		                        // of A<char, int>.  We want to to match with A<char, _b> and replace all occurrences of "_b"
+		                        // with "int".  For speed, we assume that the template parameter is not a subset of any
+		                        // other variable (e.g. if _A is used, there is no __A or _AB).  If this proves untrue in
+		                        // any instance, more refinement of the initial value to replace will be required.
+		                        for (int k = 0; k < templateParms.length; ++k) {
+		                            text = text.replaceAll(templateParms[k], "[a-zA-Z0-9_: *]+");  //$NON-NLS-1$
+		                        }
+		                        d.setClassName(text);
+		                        e.addTemplate(d);
+		                    }
+		                    else
+		                        libHoverInfo.classes.put(hashName, d);
+		                }
+		            } else if (TEMPLATEPARAMLIST.equals(name2)) { 
+		                ArrayList<String> templates = new ArrayList<>();
+		                NodeList params = n2.getChildNodes();
+		                int paramsLength = params.getLength();
+		                for (int j2 = 0; j2 < paramsLength; ++j2) {
+		                    Node n3 = params.item(j2);
+		                    if (n3.getNodeName().equals(PARAM)) { 
+		                        NodeList types = n3.getChildNodes();
+		                        int typesLength = types.getLength();
+		                        for (int j3 = 0; j3 < typesLength; ++j3) {
+		                            Node n4 = types.item(j3);
+		                            if (DECLNAME.equals(n4.getNodeName())) {
+		                                templates.add(getElementText(n4));
+		                            }
+		                        }
+		                    }
+		                }
+		                String[] templateNames = new String[templates.size()];
+		                d.setTemplateParms(templates.toArray(templateNames));
+		            } else if (INCLUDES.equals(name2)) {  
+		                String include = getElementText(n2);
+		                if (d != null)
+		                    d.setInclude(include);
+		            } else if (BASECOMPOUNDREF.equals(name2)) { 
+		                // We have a base class.  If public, add it to the list of nodes to look at in case we don't find the member
+		                // in the current class definition.
+		                NamedNodeMap m = n2.getAttributes();
+		                if (m != null) {
+		                    Node refid = m.getNamedItem(REFID2);  
+		                    Node prot2 = m.getNamedItem(PROT3); 
+		                    if (prot2 != null && PUBLIC.equals(prot2.getNodeValue())) {  
+		                        ClassInfo baseClass = null;
+		                        if (refid != null) {
+		                            // If we have been given the id of the base class, fetch it directly
+		                            baseClass = classesById.get(refid.getNodeValue());
+		                        } else {
+		                            // We probably have a template that needs resolution
+		                            String baseClassName = n2.getTextContent();
+//                                        System.out.println("base class name is " + baseClassName);
+		                            baseClass = getClassInfo(libHoverInfo, baseClassName);
+		                        }
+		                        if (d != null && baseClass != null)
+		                            d.addBaseClass(baseClass);
+		                    }
+		                }
+		            } else if (SECTIONDEF.equals(name2)) {  
+		                // We are only interested in public member functions which are in their own section.
+		                NamedNodeMap m = n2.getAttributes();
+		                if (m != null) {
+		                    Node kind2 = m.getNamedItem("kind");  //$NON-NLS-1$
+		                    if (kind2 != null && PUBLIC_FUNC.equals(kind2.getNodeValue())) { 
+		                        NodeList pubfuncs = n2.getChildNodes();
+		                        int pubfuncLength = pubfuncs.getLength();
+		                        for (int j1 = 0; j1 < pubfuncLength; ++j1) {
+		                            Node n3 = pubfuncs.item(j1);
+		                            // Add all public member functions to the list of members
+		                            if (MEMBERDEF.equals(n3.getNodeName())) { 
+		                                NamedNodeMap m3 = n3.getAttributes();
+		                                if (m3 != null) {
+		                                    Node m3Kind = m3.getNamedItem("kind");  //$NON-NLS-1$
+		                                    if (m3Kind != null && FUNCTION.equals(m3Kind.getNodeValue())) {
+		                                        String name = null;
+		                                        String type = null;
+		                                        String args = null;
+		                                        String desc = null;
+		                                        ArrayList<String> parms = new ArrayList<>();
+		                                        NodeList nl4 = n3.getChildNodes();
+		                                        int memberLength = nl4.getLength();
+		                                        for (int k = 0; k < memberLength; ++k) {
+		                                            Node n4 = nl4.item(k);
+		                                            String n4Name = n4.getNodeName();
+		                                            if (TYPE2.equals(n4Name)) {  
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                type = "";  //$NON-NLS-1$
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (n5.getNodeType() == Node.TEXT_NODE)
+		                                                        type += n5.getNodeValue();
+		                                                    else if (REF.equals(n5.getNodeName())) {  
+		                                                        NamedNodeMap n5m = n5.getAttributes();
+		                                                        Node n5id = n5m.getNamedItem(REFID2);
+		                                                        if (n5id != null) {
+		                                                            String refid = n5id.getNodeValue();
+		                                                            ClassInfo refClass = classesById.get(refid);
+		                                                            if (refClass != null)
+		                                                                type += refClass.getClassName();
+		                                                        }
+		                                                    }
+		                                                }
+		                                            } else if (NAME3.equals(n4Name)) {  
+		                                                name = n4.getTextContent();
+		                                            } else if (ARGSSTRING.equals(n4Name)) {  
+		                                                args = getElementText(n4);
+		                                            } else if (PARAM.equals(n4Name)) { 
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (TYPE2.equals(n5.getNodeName())) { 
+		                                                        parms.add(getElementText(n5));
+		                                                    }
+		                                                }
+		                                            } else if (BRIEFDESCRIPTION.equals(n4Name)) { 
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (PARA.equals(n5.getNodeName())) {  
+		                                                        if (desc == null) {
+		                                                            desc = ""; //$NON-NLS-1$
+		                                                        }
+		                                                        desc += "<p>" + getElementText(n5) + "</p>";   //$NON-NLS-1$ //$NON-NLS-2$
+		                                                    }
+		                                                }
+		                                            } else if (DETAILEDDESCRIPTION.equals(n4Name)) {  
+		                                                NodeList nl5 = n4.getChildNodes();
+		                                                for (int x = 0; x < nl5.getLength(); ++x) {
+		                                                    Node n5 = nl5.item(x);
+		                                                    if (PARA.equals(n5.getNodeName())) {  
+		                                                        if (desc == null)
+		                                                            desc = new String("");  //$NON-NLS-1$
+		                                                        NodeList nl6 = n5.getChildNodes();
+		                                                        Node n6 = nl6.item(0);
+		                                                        if (n6.getNodeType() == Node.TEXT_NODE)
+		                                                            desc += "<p>" + getElementText(n5) + "</p>";   //$NON-NLS-1$ //$NON-NLS-2$
+		                                                        else {
+		                                                            for (int x2 = 0; x2 < nl6.getLength(); ++x2) {
+		                                                                n6 = nl6.item(x2);
+		                                                                if (PARAMETERLIST.equals(n6.getNodeName())) {
+		                                                                    desc += getParameters(n6, true);
+		                                                                } else if (SIMPLESECT.equals(n6.getNodeName())) {
+		                                                                    desc += getReturn(n6);
+		                                                                }
+		                                                            }
+		                                                        }
+		                                                    }
+		                                                }
+		                                            } else if (LOCATION.equals(n4Name)) { 
+		                                                // Location is after all descriptions so we can now add the member
+		                                                if (name != null) {
+		                                                    MemberInfo member = new MemberInfo(name);
+		                                                    member.setReturnType(type);
+		                                                    member.setPrototype(args);
+		                                                    member.setDescription(desc);
+		                                                    String[] argNames = new String[parms.size()];
+		                                                    member.setParamTypes(parms.toArray(argNames));
+		                                                    d.addMember(member);
+		                                                }
+		                                                break;
+		                                            }
+		                                        }
+		                                    }
+		                                }
+		                            }
+		                        }
+		                    }
+		                }
+		            }
+		        }
+		    }
+		}
+		// Create a hash table of all the typedefs.  Keep any template info.
+		nl = document.getElementsByTagName(MEMBERDEF);  
+		for (int i = 0; i < nl.getLength(); ++i) {
+		    Node n = nl.item(i);
+		    NamedNodeMap attrs = n.getAttributes();
+		    if (attrs != null) {
+		        Node kind = attrs.getNamedItem("kind");  //$NON-NLS-1$
+		        Node prot = attrs.getNamedItem(PROT3); 
+		        if (kind != null && TYPEDEF2.equals(kind.getNodeValue())  
+		                && prot != null && PUBLIC.equals(prot.getNodeValue())) {  
+		            NodeList list = n.getChildNodes();
+		            for (int x = 0; x < list.getLength(); ++x) {
+		                Node n2 = list.item(x);
+		                if (DEFINITION.equals(n2.getNodeName())) {  
+		                    String def = n2.getTextContent();
+		                    if (def != null && !def.equals("")) { //$NON-NLS-1$
+		                        def = def.replaceAll("<\\s*", "<");   //$NON-NLS-1$ //$NON-NLS-2$
+		                        def = def.replaceAll("\\s*>", ">");   //$NON-NLS-1$ //$NON-NLS-2$
+		                        String[] types = getTypedefTypes(def);
+		                        if(types == null){
+		                        	continue;
+		                        }
+		                        TypedefInfo d = new TypedefInfo(types[1], types[0]);
+		                        String hashName = d.getTypedefName();
+		                        int index = hashName.indexOf('<');
+		                        if (index > 0) {
+		                            String className = hashName.substring(0, index);
+		                            hashName = hashName.replaceAll("<.*>", "<>");   //$NON-NLS-1$ //$NON-NLS-2$
+		                            ClassInfo e = libHoverInfo.classes.get(className);
+		                            if (e == null)
+		                                break;
+		                            ArrayList<ClassInfo> children = e.getChildren();
+		                            if (children != null && children.size() > 0) {
+		                                for (int y = 0; y < children.size(); ++y) {
+		                                    ClassInfo child = children.get(y);
+		                                    String childName = child.getClassName().replaceAll("\\*", "\\\\*"); //$NON-NLS-1$ //$NON-NLS-2$
+		                                    childName = childName.replace("[]", "\\[\\]"); //$NON-NLS-1$ //$NON-NLS-2$
+		                                    if (types[1].matches(childName.concat("::.*"))) { //$NON-NLS-1$
+		                                        e = child;
+		                                        break;
+		                                    }
+		                                }
+		                            }
+		                            String[] templates = e.getTemplateParms();
+		                            d.copyTemplates(templates);
+
+		                            TypedefInfo f = libHoverInfo.typedefs.get(hashName);
+		                            if (f != null) {
+		                                String typedefName = d.getTypedefName();
+		                                for (int z = 0; z < templates.length; ++z) {
+		                                    typedefName = typedefName.replaceAll(templates[z], "[a-zA-Z0-9_: ]+"); //$NON-NLS-1$
+		                                }
+		                                d.setTypedefName(typedefName);
+		                                f.addTypedef(d);
+		                            }
+		                            else
+		                                libHoverInfo.typedefs.put(hashName, d);
+		                            break;
+		                        } else {
+		                            // Otherwise we have a non-template typedef name.  Just add it to the list.
+		                            libHoverInfo.typedefs.put(hashName, d);
+		                            break;
+		                        }
+		                    }
+		                }
+		            }
+		        }
+		    }
+		}	
+		
+		return libHoverInfo;
+    }
+
+    private String getParameters(Node n6, boolean addHyphen) {
+    	String desc = "<br><br><h3>Parameters:</h3>"; //$NON-NLS-1$
+    	NamedNodeMap m = n6.getAttributes();
+    	Node kind = m.getNamedItem("kind"); //$NON-NLS-1$
+    	if (kind != null && EXCEPTION.equals(kind.getNodeValue())) { 
+    		desc = "<br><br><h3>Exceptions:</h3>"; //$NON-NLS-1$
+        }       
+        NodeList nl = n6.getChildNodes();
+        for (int x = 0; x < nl.getLength(); ++x) {
+            Node n = nl.item(x);
+            if (PARAMETERITEM.equals(n.getNodeName())) {
+                NodeList nl2 = n.getChildNodes();
+                for (int y = 0; y < nl2.getLength(); ++y) {
+                    Node n2 = nl2.item(y);
+                    if (PARAMETERNAMELIST.equals(n2.getNodeName())) { 
+                        NodeList nl3 = n2.getChildNodes();
+                        for (int z = 0; z < nl3.getLength(); ++z) {
+                            Node n3 = nl3.item(z);
+                            if (PARAMETERNAME.equals(n3.getNodeName())) { 
+                                desc += getElementText(n3); 
+                                if(addHyphen) {
+                                	desc += " - ";//$NON-NLS-1$
+                                }
+                            }
+                        }
+                    } else if (PARAMETERDESCRIPTION.equals(n2.getNodeName())) { 
+                        desc += getElementText(n2) + "<br>"; //$NON-NLS-1$
+                    }
+
+                }
+            }
+        }
+        return desc;
+
+    }
+
+    private String getReturn(Node n6) {
+        String desc = ""; //$NON-NLS-1$
+        NamedNodeMap m = n6.getAttributes();
+        Node kind = m.getNamedItem("kind"); //$NON-NLS-1$
+        if (kind != null && RETURN.equals(kind.getNodeValue())) { 
+            desc += "<br><h3>Returns:</h3>" + getElementText(n6) + "<br>"; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        return desc;
+    }
+
+    private String[] getTemplateParms(Node classNode) {
+        Node n = null;
+        ArrayList<String> templateArray = new ArrayList<>();
+        NodeList list = classNode.getChildNodes();
+        for (int i = 0; i < list.getLength(); ++i) {
+            n = list.item(i);
+            if (TEMPLATEPARAMLIST.equals(n.getNodeName())) {  
+                break;
+            }
+        }
+        if (n != null) {
+            NodeList templateList = n.getChildNodes();
+            for (int j = 0; j < templateList.getLength(); ++j) {
+                Node p = templateList.item(j);
+                if (PARAM.equals(p.getNodeName())) {  
+                    NodeList paramList = p.getChildNodes();
+                    for (int k = 0; k < paramList.getLength(); ++k) {
+                        Node q = paramList.item(k);
+                        if (DECLNAME.equals(q.getNodeName())) {  
+                            String templateName = q.getTextContent();
+                            templateArray.add(templateName);
+                        }
+                    }
+                }
+            }
+        }
+        String[] templates = new String[templateArray.size()];
+        return templateArray.toArray(templates);
+    }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CXmlLibhoverGen.java b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CXmlLibhoverGen.java
new file mode 100644
index 0000000..283ea08
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/CXmlLibhoverGen.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Red Hat, Inc.
+ * Copyright (c) 2015 Ezchip Semiconductor
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     EZchip Semiconductor - adding support for Doxygen XML files as input
+ *     Red Hat Incorporated - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.cdt.libhover.utils;
+
+import org.eclipse.linuxtools.cdt.libhover.FunctionInfo;
+import org.eclipse.linuxtools.cdt.libhover.LibHoverInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class CXmlLibhoverGen extends LibhoverInfoGenerator{
+	
+	public CXmlLibhoverGen(Document document){
+		this.document = document;
+	}
+
+	private FunctionInfo getFunctionInfoFromNode(String name, Node functionNode, Document document) {
+        FunctionInfo f = new FunctionInfo(name);
+        NamedNodeMap functionNodeMap = functionNode.getAttributes();
+        Node functionNodeReturntypeNode = functionNodeMap.item(0);
+        String functionNodeRtName = functionNodeReturntypeNode.getNodeName();
+
+        if (functionNodeRtName.equals("returntype")) { //$NON-NLS-1$
+
+            // return type
+
+            String functionNodeRtValue = functionNodeReturntypeNode.getNodeValue();
+            f.setReturnType(functionNodeRtValue);
+        }        // returntype
+
+        NodeList kids = functionNode.getChildNodes();
+        for (int fnk = 0; fnk < kids.getLength(); fnk++) {
+            Node kid = kids.item(fnk);
+            String kidName = kid.getNodeName();
+            if (kidName.equals("prototype")) { //$NON-NLS-1$
+
+                // prototype
+
+                String prototype = null;
+
+                NodeList parms = kid.getChildNodes();
+                for (int fnp = 0; fnp < parms.getLength(); fnp++) {
+                    Node parm = parms.item(fnp);
+                    String parmName =  parm.getNodeName();
+                    if (parmName.equals("parameter")) { //$NON-NLS-1$
+                        NamedNodeMap parmMap = parm.getAttributes();
+                        Node parmNode = parmMap.item(0);
+                        String parameter = parmNode.getNodeValue();
+                        prototype = (null == prototype) ? parameter : prototype
+                                + ", " + parameter; //$NON-NLS-1$
+                    }
+                }
+                f.setPrototype(prototype);
+            }    // prototype
+
+            else if (kidName.equals("headers")) { //$NON-NLS-1$
+
+                // headers
+
+                NodeList headers = kid.getChildNodes();
+                for (int fnh = 0; fnh < headers.getLength(); fnh++) {
+                    Node header = headers.item(fnh);
+                    String headerName =  header.getNodeName();
+                    if (headerName.equals("header")) { //$NON-NLS-1$
+                        NamedNodeMap headerMap = header.getAttributes();
+                        Node headerNode = headerMap.item(0);
+                        f.addHeader(headerNode.getNodeValue());
+                    }
+                }
+            }    // headers
+
+
+            else if (kidName.equals("groupsynopsis")) { //$NON-NLS-1$
+
+                // group synopsis
+
+                NamedNodeMap attr = kid.getAttributes();
+                Node idnode = attr.getNamedItem("id"); //$NON-NLS-1$
+                String id = idnode.getNodeValue();
+                if (id != null) {
+                    Element elem2 = document.getElementById(id);
+                    if (null != elem2) {
+                        NodeList synopsisNode = elem2.getElementsByTagName("synopsis"); //$NON-NLS-1$
+                        if (null != synopsisNode && synopsisNode.getLength() > 0) {
+                            Node synopsis = synopsisNode.item(0);
+                            Node textNode = synopsis.getLastChild();
+                            f.setDescription(textNode.getNodeValue());
+                        }
+                    }
+                }
+            } else if (kidName.equals("synopsis")) { //$NON-NLS-1$
+                // synopsis
+                Node textNode = kid.getLastChild();
+                f.setDescription(textNode.getNodeValue());
+            }
+        }
+        return f;
+    }
+
+	@Override
+	protected LibHoverInfo doGenerate() {
+		LibHoverInfo hoverInfo = new LibHoverInfo();
+		
+        NodeList nl = document.getElementsByTagName("construct"); //$NON-NLS-1$
+        for (int i = 0; i < nl.getLength(); ++i) {
+            Node n = nl.item(i);
+            NamedNodeMap m = n.getAttributes();
+            Node id = m.getNamedItem("id"); //$NON-NLS-1$
+            if (id != null && id.getNodeValue().startsWith("function-")) { //$NON-NLS-1$
+                String name = id.getNodeValue().substring(9);
+                NodeList nl2 = n.getChildNodes();
+                for (int j = 0; j < nl2.getLength(); ++j) {
+                    Node n2 = nl2.item(j);
+                    if (n2.getNodeName().equals("function")) { //$NON-NLS-1$
+                        FunctionInfo f = getFunctionInfoFromNode(name, n2, document);
+                        hoverInfo.functions.put(name, f);
+                    }
+                }
+            }
+        }
+        
+        return hoverInfo;
+	}
+
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/LibhoverInfoGenerator.java b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/LibhoverInfoGenerator.java
new file mode 100644
index 0000000..ebd1ff2
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover/src/org/eclipse/linuxtools/internal/cdt/libhover/utils/LibhoverInfoGenerator.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EZChip Semiconductor
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Slava Risenberg <slava@ezchip.com> - adding support for Doxygen XML files as input
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.cdt.libhover.utils;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
+import org.eclipse.linuxtools.cdt.libhover.LibHoverInfo;
+import org.w3c.dom.Document;
+
+public abstract class LibhoverInfoGenerator {
+
+	protected Document document;
+
+	public void generate(String outputFile){
+		LibHoverInfo hoverInfo = doGenerate();
+		save(hoverInfo, outputFile);
+	}
+
+	protected abstract LibHoverInfo doGenerate();
+
+	protected void save(LibHoverInfo hoverInfo, String fileName){
+		try (FileOutputStream f = new FileOutputStream(fileName);
+				ObjectOutputStream out = new ObjectOutputStream(f)) {
+			out.writeObject(hoverInfo);
+		}catch(IOException ioException){
+			ioException.printStackTrace();
+		}
+	}
+}