#!/usr/bin/env python
#
# Copyright 2014, NICTA
#
# This software may be distributed and modified according to the terms of
# the BSD 2-Clause license. Note that NO WARRANTY is provided.
# See "LICENSE_BSD2.txt" for details.
#
# @TAG(NICTA_BSD)
#

# Script for generating latex from doxygen-generated xml files.
# The generatetd latex files are compatible with the seL4 manual.

import xml.dom.minidom
import argparse
import sys
import os
import re

# Dict mapping characters to their escape sequence in latex
LATEX_ESCAPE_PATTERNS = {
    "_": "\\_",
}
LATEX_ESCAPE_REGEX = re.compile('|'.join(LATEX_ESCAPE_PATTERNS.keys()))

# Return a string with latex special characters escaped
def latex_escape(string):
    return LATEX_ESCAPE_REGEX.sub(lambda p: LATEX_ESCAPE_PATTERNS[p.group()], string)

# Return the first node with a given tag inside parent
def get_node(parent, tagname):
    return parent.getElementsByTagName(tagname)[0]

# Return a string containing a concatenation of a nodes text node
# children, recursing into non-text nodes or escaping latex if
# necessary.
def get_text(node, recur=False, escape=True):
    output = ""
    for n in node.childNodes:
        if n.nodeType == xml.dom.Node.TEXT_NODE:
            if escape:
                output += latex_escape(n.data)
            else:
                output += n.data
        elif recur:
            output += get_text(n, True, escape)

    return output

# Parse a paragraph node, handling special doxygen node types
# that may appear inside a paragraph.
def parse_para(para_node, ref_dict={}):
    output = ""
    for n in para_node.childNodes:
        if n.nodeType == xml.dom.Node.TEXT_NODE:
            output += latex_escape(n.data)
        elif n.tagName == "para":
            output += parse_para(n, ref_dict)
        elif n.tagName == "computeroutput":
            output += "\\texttt{%s}" % get_text(n)
        elif n.tagName == "texttt":
            output += "\\texttt{%s}" % latex_escape(n.getAttribute("text"))
        elif len(ref_dict) != 0 and n.tagName == "ref":
            refid = n.getAttribute("refid")
            ref = ref_dict[refid]
            output += "\\apifunc{%(name)s}{%(label)s}" % ref
        elif n.tagName == "nameref":
            name = n.getAttribute("name")
            ref = ref_dict[name]
            output += "\\apifunc{%(name)s}{%(label)s}" % ref
        elif n.tagName == "autoref":
            output += "\\autoref{sec:%s}" % n.getAttribute("sec")