# Autoduck to doxygen documentation command conversion
import sys
import os
import re

usage = r"""
ducktodox.py <input_file> [<group>]
The input file will be converted and saved. A backup of the old file is made named input.old
"""

in_file = ""
group   = ""

num_args = len(sys.argv)
if num_args < 2:
	print usage
	sys.exit()
elif num_args == 3:
	group = sys.argv[2]
	
in_file = sys.argv[1]


# backup input file
os.system("cp -f %s %s.old" %(in_file, in_file))

# read file into mem
ifile = open(in_file)

input_data = ""

if ifile:
	input_data = ifile.read()
	ifile.close();
else:
	print "File not found\n", usage


# start replacing tags

# /* @emem *  ->  /**< * */
emem_pat = re.compile("/\*\s+?@emem ")
input_data = re.sub(emem_pat, "/**<", input_data)

doc_pat = re.compile("@doc")
input_data = re.sub(doc_pat, "{doc}", input_data)

# First we look for a sequence that looks like its beginning a
# documentation block like, /* @, and replace it with a doxygen
# style comment beginning, /**
# if a group is specified then ouput that as well
#docblock_pat = re.compile("(/\*[\s\n]*?)@");
docblock_pat = re.compile("(/\*+?[\s\n]*?\s+\**?[\s\n]*?)@")

if(len(group) > 0):
	input_data = re.sub(docblock_pat, "/**\n * \\\\ingroup " + group + "\n * @", input_data)
else:
	input_data = re.sub(docblock_pat, "/**\n * @", input_data)

# @rdec -> \retval
input_data = re.sub(r"""@rdesc""", "\\\\return", input_data)

# @func <f target> -> \ref target
pat = re.compile("@func\s+<f\s+(\w*)>")
input_data = re.sub(pat, "\\\\ref \g<1>", input_data)

# @xref <f target> -> \ref target
pat = re.compile("@xref\s+<f\s+(\w*)>")
input_data = re.sub(pat, "\\\\see \g<1>", input_data)

# @parm * -> \param <unknown> *
# @parm * | *1  | *2 -> \param *1 *2
# need some brains to get param from func header if we dont have it
param_pat = re.compile("@parm\s*?(.+)")
param_pat2 = re.compile("@parm\s*?([^\n\r\f\|]+)\s*?\|\s*?([^\n\r\f\|]+)\s*?\|\s*?([^\n\r\f\|]+)")
						
input_data = re.sub(param_pat2, "\\\\param \g<2> \g<3>", input_data)						
input_data = re.sub(param_pat , "\\\\param <unknown> \g<1>", input_data)

# @cb *1 | *2 -> \typedef *1 *2
cb_pat = re.compile("@cb\s+?<t\s+?(\w+?)>\s*?([\w*_]+?)\s*?\|\s*?(\w*?)\s*?\|")
input_data = re.sub(cb_pat, "\\\\typedef \g<1> \g<2> \g<3>\n", input_data);

# @type *1 | -> \typedef *1 \n
type_pat = re.compile("@type\s+?(.+?)\|")
input_data = re.sub(type_pat, "\\\\typedef \g<1>\n * ", input_data)

# @enum *1 | -> \enum *1 \n
enum_pat = re.compile("@enum\s+?(.+?)\|")
input_data = re.sub(enum_pat, "\\\\enum \g<1>\n * ", input_data)

# @struct *1 | -> \struct *1 \n
struct_pat = re.compile("@struct\s+?(.+?)\|")
struct_data = re.sub(struct_pat, "\\\\struct \g<1>\n * ", input_data)

# finally replace all remaining links links
typelink_pat = re.compile("<t\s+?(.+?)\s*?>")
funclink_pat = re.compile("<f\s+?(.+?)\s*?>")
input_data = re.sub(typelink_pat, "\\\\ref \g<1>", input_data)
input_data = re.sub(funclink_pat, "\\\\ref \g<1>", input_data)

header = "/**\n * \defgroup " + group + "\n */\n";

if len(group > 0):
	print header

print input_data
#out_file = in_file + ".txt"
#of = open(out_file, "w+")

#if len(group) > 0:
#	of.writelines(header)
	
of.writelines(input_data)
of.close()