Commit 0dc96d28 authored by Dimitri van Heesch's avatar Dimitri van Heesch

Merge branch 'master' of github.com:doxygen/doxygen

parents b4d5ef17 cd68727a
......@@ -507,7 +507,7 @@ if test "$f_sqlite3" = YES; then
printf " Checking for sqlite3 ... "
if test "$f_sqlite3_path" = NO; then
sqlite3_hdr_dir="/usr/include /usr/local/include /opt/local/include"
sqlite3_lib_dir="/usr/lib /usr/local/lib /opt/local/lib /usr/lib/x86_64-linux-gnu"
sqlite3_lib_dir="/usr/lib /usr/local/lib /opt/local/lib /usr/lib/x86_64-linux-gnu /usr/lib64"
else
sqlite3_hdr_dir="$f_sqlite3_path/include"
sqlite3_lib_dir="$f_sqlite3_path/lib"
......
......@@ -2698,6 +2698,8 @@ class Receiver
<hr>
\section cmdfcurlyopen \\f{environment}{
\addindex \\f{
Marks the start of a formula that is in a specific environment.
\note The second \c { is optional and is only to help editors (such as \c Vim) to
do proper syntax highlighting by making the number of opening and closing braces
......@@ -2707,6 +2709,8 @@ class Receiver
<hr>
\section cmdfcurlyclose \\f}
\addindex \\f}
Marks the end of a formula that is in a specific environment.
\sa section \ref cmdfcurlyopen "\\f{" and section \ref formulas "formulas".
......@@ -3032,7 +3036,7 @@ class Receiver
\section cmdchardot \\.
\addindex \\\.
This command writes a dot (\c .) to the output. This can be useful to
This command writes a dot (`.`) to the output. This can be useful to
prevent ending a brief description when JAVADOC_AUTOBRIEF is enabled
or to prevent starting a numbered list when the dot follows a number at
the start of a line.
......@@ -3040,7 +3044,7 @@ class Receiver
<hr>
\section cmddcolon \\::
\addindex \\\::
\addindex \\::
This command writes a double colon (\c \::) to the output. This
character sequence has to be escaped in some cases, because it is used
to reference to documented entities.
......
......@@ -381,6 +381,8 @@
}
\newcommand{\doxyref}[3]{\textbf{#1} (\textnormal{#2}\,\pageref{#3})}
\newcommand{\lcurly}{\{}
\newcommand{\rcurly}{\}}
\newenvironment{DoxyCompactList}
{\begin{list}{}{
\setlength{\leftmargin}{0.5cm}
......
......@@ -52,6 +52,13 @@ struct CondCtx
bool skip;
};
struct CommentCtx
{
CommentCtx(int line)
: lineNr(line) {}
int lineNr;
};
static BufStr * g_inBuf;
static BufStr * g_outBuf;
static int g_inBufPos;
......@@ -64,6 +71,7 @@ static QCString g_fileName;
static int g_lineNr;
static int g_condCtx;
static QStack<CondCtx> g_condStack;
static QStack<CommentCtx> g_commentStack;
static QCString g_blockName;
static int g_lastCommentContext;
static bool g_inSpecialComment;
......@@ -256,8 +264,10 @@ void replaceComment(int offset);
{
g_pythonDocString = TRUE;
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
}
<Scan>![><!]/.*\n {
......@@ -269,7 +279,9 @@ void replaceComment(int offset);
{
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
}
<Scan>[Cc\*][><!]/.*\n {
......@@ -284,7 +296,9 @@ void replaceComment(int offset);
{
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
else
{
......@@ -378,8 +392,10 @@ void replaceComment(int offset);
<Scan>"/*"[*!]? { /* start of a C comment */
g_specialComment=(int)yyleng==3;
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
<Scan>"#"("#")? {
if (g_lang!=SrcLangExt_Python)
......@@ -390,7 +406,9 @@ void replaceComment(int offset);
{
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
}
<Scan>"--!" {
......@@ -402,7 +420,9 @@ void replaceComment(int offset);
{
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
}
<Scan>![><!] {
......@@ -414,7 +434,9 @@ void replaceComment(int offset);
{
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
}
<CComment>"{@code"/[ \t\n] {
......@@ -606,6 +628,7 @@ void replaceComment(int offset);
}
<CComment>"/"+"*" { /* nested C comment */
g_nestingCount++;
g_commentStack.push(new CommentCtx(g_lineNr));
copyToOutput(yytext,(int)yyleng);
}
<CComment>"*"+"/" { /* end of C comment */
......@@ -623,6 +646,7 @@ void replaceComment(int offset);
else
{
g_nestingCount--;
CommentCtx *ctx = g_commentStack.pop();
}
}
}
......@@ -951,6 +975,8 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
g_lineNr = 1;
g_condStack.clear();
g_condStack.setAutoDelete(TRUE);
g_commentStack.clear();
g_commentStack.setAutoDelete(TRUE);
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
isFixedForm = FALSE;
......@@ -962,7 +988,9 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
if (g_lang==SrcLangExt_Markdown)
{
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
}
else
{
......@@ -979,9 +1007,20 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
}
if (g_nestingCount>0 || (YY_START==CComment && g_lang!=SrcLangExt_Markdown))
{
QString tmp= "(probable line reference: ";
bool first = TRUE;
while (!g_commentStack.isEmpty())
{
CommentCtx *ctx = g_commentStack.pop();
if (!first) tmp += ", ";
tmp += QString::number(ctx->lineNr);
first = FALSE;
}
tmp += ")";
warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. "
"Nesting level %d",g_nestingCount+1); // add one for "normal" expected end of comment
"Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment
}
g_commentStack.clear();
if (Debug::isFlagSet(Debug::CommentCnv))
{
g_outBuf->at(g_outBuf->curPos())='\0';
......
......@@ -2686,6 +2686,15 @@ EXTRA_PACKAGES=times
the generated man pages. In case
the manual section does not start with a number, the number 3 is prepended.
The dot (.) at the beginning of the \c MAN_EXTENSION tag is optional.
]]>
</docs>
</option>
<option type='string' id='MAN_SUBDIR' format='string' defval='' depends='GENERATE_MAN'>
<docs>
<![CDATA[
The \c MAN_SUBDIR tag determines the name of the directory created within \c MAN_OUTPUT
in which the man pages are placed. If defaults to man followed by \c MAN_EXTENSION
with the initial . removed.
]]>
</docs>
</option>
......
......@@ -450,6 +450,10 @@
\textbf{#1} (\textnormal{#2}\,\pageref{#3})%
}
% Used by @addindex
\newcommand{\lcurly}{\{}
\newcommand{\rcurly}{\}}
% Used for syntax highlighting
\definecolor{comment}{rgb}{0.5,0.0,0.0}
\definecolor{keyword}{rgb}{0.0,0.5,0.0}
......
......@@ -44,6 +44,9 @@ static QCString escapeLabelName(const char *s)
case '%': result+="\\%"; break;
case '|': result+="\\texttt{\"|}"; break;
case '!': result+="\"!"; break;
case '{': result+="\\lcurly{}"; break;
case '}': result+="\\rcurly{}"; break;
case '~': result+="````~"; break; // to get it a bit better in index together with other special characters
default: result+=c;
}
}
......@@ -79,6 +82,8 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
case '|': m_t << "\\texttt{\"|}"; break;
case '[': m_t << "["; break;
case ']': m_t << "]"; break;
case '{': m_t << "\\lcurly{}"; break;
case '}': m_t << "\\rcurly{}"; break;
default: str[0]=c; filter(str); break;
}
}
......
......@@ -1375,8 +1375,10 @@ void LatexGenerator::startMemberDoc(const char *clname,
t << "}";
if (clname)
{
t << "!" << clname << "@{";
docify(clname);
t << "!";
escapeLabelName(clname);
t << "@{";
escapeMakeIndexChars(clname);
t << "}";
}
t << "}" << endl;
......@@ -2013,13 +2015,18 @@ void LatexGenerator::escapeLabelName(const char *s)
{
switch (c)
{
case '|': t << "\\texttt{\"|}"; break;
case '!': t << "\"!"; break;
case '%': t << "\\%"; break;
case '{': t << "\\lcurly{}"; break;
case '}': t << "\\rcurly{}"; break;
case '~': t << "````~"; break; // to get it a bit better in index together with other special characters
// NOTE: adding a case here, means adding it to while below as well!
default:
i=0;
// collect as long string as possible, before handing it to docify
result[i++]=c;
while ((c=*p) && c!='%')
while ((c=*p) && c!='|' && c!='!' && c!='%' && c!='{' && c!='}' && c!='~')
{
result[i++]=c;
p++;
......@@ -2042,16 +2049,20 @@ void LatexGenerator::escapeMakeIndexChars(const char *s)
{
switch (c)
{
case '!': t << "\"!"; break;
case '"': t << "\"\""; break;
case '@': t << "\"@"; break;
case '|': t << "\\texttt{\"|}"; break;
case '[': t << "["; break;
case ']': t << "]"; break;
case '{': t << "\\lcurly{}"; break;
case '}': t << "\\rcurly{}"; break;
// NOTE: adding a case here, means adding it to while below as well!
default:
i=0;
// collect as long string as possible, before handing it to docify
result[i++]=c;
while ((c=*p) && c!='"' && c!='@' && c!='[' && c!=']')
while ((c=*p) && c!='"' && c!='@' && c!='[' && c!=']' && c!='!' && c!='{' && c!='}' && c!='|')
{
result[i++]=c;
p++;
......
......@@ -64,9 +64,19 @@ static QCString getExtension()
return ext;
}
static QCString getSubdir()
{
QCString dir = Config_getString("MAN_SUBDIR");
if (dir.isEmpty())
{
dir = "man" + getExtension();
}
return dir;
}
ManGenerator::ManGenerator() : OutputGenerator()
{
dir=Config_getString("MAN_OUTPUT")+"/man" + getExtension();
dir=Config_getString("MAN_OUTPUT") + "/" + getSubdir();
firstCol=TRUE;
paragraph=TRUE;
col=0;
......@@ -106,10 +116,10 @@ void ManGenerator::init()
err("Could not create output directory %s\n",manOutput.data());
exit(1);
}
d.setPath(manOutput+"/man"+ext);
if (!d.exists() && !d.mkdir(manOutput+"/man"+ext))
d.setPath(manOutput + "/" + getSubdir());
if (!d.exists() && !d.mkdir(manOutput + "/" + getSubdir()))
{
err("Could not create output directory %s/man%s\n",manOutput.data(),ext.data());
err("Could not create output directory %s/%s\n",manOutput.data(), getSubdir().data());
exit(1);
}
createSubDirs(d);
......@@ -445,7 +455,7 @@ void ManGenerator::startDoxyAnchor(const char *,const char *manName,
FTextStream linkstream;
linkstream.setDevice(&linkfile);
//linkstream.setEncoding(QTextStream::UnicodeUTF8);
linkstream << ".so man" << getExtension() << "/" << buildFileName( manName ) << endl;
linkstream << ".so " << getSubdir() << "/" << buildFileName( manName ) << endl;
}
}
linkfile.close();
......
......@@ -77,9 +77,9 @@ const char *i_q_xrefs="INSERT OR REPLACE INTO xrefs "
static sqlite3_stmt *i_s_xrefs=0;
//////////////////////////////////////////////////////
const char *i_q_memberdef="INSERT OR REPLACE INTO memberdef "
"( refid, prot, static, const, explicit, inline, final, sealed, new, optional, required, virt, mutable, initonly, readable, writable, gettable, settable, accessor, addable, removable, raisable, name, type, definition, argsstring, scope, initializer, kind, id_bfile, bline, bcolumn, id_file, line, column)"
"( refid, prot, static, const, explicit, inline, final, sealed, new, optional, required, virt, mutable, initonly, readable, writable, gettable, settable, accessor, addable, removable, raisable, name, type, definition, argsstring, scope, initializer, kind, id_bodyfile, bodystart, bodyend, id_file, line, column, detaileddescription, briefdescription, inbodydescription)"
"VALUES "
"(:refid,:prot,:static,:const,:explicit,:inline,:final,:sealed,:new,:optional,:required,:virt,:mutable,:initonly,:readable,:writable,:gettable,:settable,:accessor,:addable,:removable,:raisable,:name,:type,:definition,:argsstring,:scope,:initializer,:kind,:id_bfile,:bline,:bcolumn,:id_file,:line,:column)";
"(:refid,:prot,:static,:const,:explicit,:inline,:final,:sealed,:new,:optional,:required,:virt,:mutable,:initonly,:readable,:writable,:gettable,:settable,:accessor,:addable,:removable,:raisable,:name,:type,:definition,:argsstring,:scope,:initializer,:kind,:id_bodyfile,:bodystart,:bodyend,:id_file,:line,:column,:detaileddescription,:briefdescription,:inbodydescription)";
const char *id_q_memberdef="SELECT id FROM memberdef WHERE refid=:refid and id is not null";
static sqlite3_stmt *id_s_memberdef=0;
static sqlite3_stmt *i_s_memberdef=0;
......@@ -202,12 +202,16 @@ const char * schema_queries[][2] =
"raisable INTEGER,"
"kind INTEGER,"
"refid TEXT NOT NULL,"
"id_bfile INTEGER,"
"bline INTEGER,"
"bcolumn INTEGER,"
"id_bodyfile INTEGER,"
"bodystart INTEGER,"
"bodyend INTEGER,"
"id_file INTEGER NOT NULL,"
"line INTEGER NOT NULL,"
"column INTEGER NOT NULL)"
"column INTEGER NOT NULL,"
"detaileddescription TEXT,"
"briefdescription TEXT,"
"inbodydescription TEXT"
")"
},
};
......@@ -692,6 +696,12 @@ static void generateSqlite3ForMember(sqlite3*db,MemberDef *md,Definition *def)
bindTextParameter(i_s_memberdef,":scope",md->getScopeString().data(),FALSE);
}
// Brief and detail description
bindTextParameter(i_s_memberdef,":briefdescription",md->briefDescription(),FALSE);
bindTextParameter(i_s_memberdef,":detaileddescription",md->documentation(),FALSE);
bindTextParameter(i_s_memberdef,":inbodydescription",md->inbodyDocumentation(),FALSE);
// File location
if (md->getDefLine() != -1)
{
......@@ -704,18 +714,16 @@ static void generateSqlite3ForMember(sqlite3*db,MemberDef *md,Definition *def)
if (md->getStartBodyLine()!=-1)
{
int id_bfile = insertFile(db,md->getBodyDef()->absFilePath());
if (id_bfile == -1)
int id_bodyfile = insertFile(db,md->getBodyDef()->absFilePath());
if (id_bodyfile == -1)
{
sqlite3_clear_bindings(i_s_memberdef);
}
else
{
bindIntParameter(i_s_memberdef,":id_ibfile",id_bfile);
bindIntParameter(i_s_memberdef,":bline",md->getStartBodyLine());
// XXX implement getStartBodyColumn
bindIntParameter(i_s_memberdef,":bcolumn",1);
bindIntParameter(i_s_memberdef,":id_bodyfile",id_bodyfile);
bindIntParameter(i_s_memberdef,":bodystart",md->getStartBodyLine());
bindIntParameter(i_s_memberdef,":bodyend",md->getEndBodyLine());
}
}
}
......@@ -837,19 +845,19 @@ static void generateSqlite3ForClass(sqlite3 *db, ClassDef *cd)
BaseClassDef *bcd;
for (bcli.toFirst();(bcd=bcli.current());++bcli)
{
bindTextParameter(i_s_basecompoundref,":refid",bcd->classDef->getOutputFileBase());
bindTextParameter(i_s_basecompoundref,":refid",bcd->classDef->getOutputFileBase(),FALSE);
bindIntParameter(i_s_basecompoundref,":prot",bcd->prot);
bindIntParameter(i_s_basecompoundref,":virt",bcd->virt);
if (!bcd->templSpecifiers.isEmpty())
{
bindTextParameter(i_s_basecompoundref,":base",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers));
bindTextParameter(i_s_basecompoundref,":base",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE);
}
else
{
bindTextParameter(i_s_basecompoundref,":base",bcd->classDef->displayName());
bindTextParameter(i_s_basecompoundref,":base",bcd->classDef->displayName(),FALSE);
}
bindTextParameter(i_s_basecompoundref,":derived",cd->displayName());
bindTextParameter(i_s_basecompoundref,":derived",cd->displayName(),FALSE);
if (-1==step(db,i_s_basecompoundref)) {
sqlite3_clear_bindings(i_s_basecompoundref);
continue;
......
#! /usr/bin/python
from xml.etree import cElementTree as ET
import os
import sqlite3
import sys
import getopt
# map XML attributes/elements to SQL rows
# --POC: iterate through the children and attributes of the memberdef elelement
# and search it in doxygen_sqlite3.db
g_conn=None
val=[]
def print_unprocessed_attributes(node):
for key in node.attrib:
print "WARNING: '%s' has unprocessed attr '%s'" % (node.tag,key)
def extract_attribute(node,attribute,pnl):
if not attribute in node.attrib:
return
pnl.append("%s = ?" % attribute)
val.append(node.attrib[attribute])
node.attrib.pop(attribute)
def extract_element(node,chld,pnl):
# deal with <tag />
if chld.text == None:
if len(chld.attrib)==0:
node.remove(chld)
return
a=chld.text.strip()
if not a == "":
pnl.append("%s =?" % chld.tag)
val.append(chld.text.strip())
else:
pnl.append("%s IS NULL OR %s = ''" % (chld.tag,chld.tag))
node.remove(chld)
def process_memberdef(node):
q=[]
for chld in node.getchildren():
if chld.tag == "referencedby":
continue
if chld.tag == "references":
continue
if chld.tag == "param":
continue
if chld.tag == "type":
continue
if chld.tag == "location":
extract_attribute(chld,"line",q)
extract_attribute(chld,"column",q)
extract_attribute(chld,"bodystart",q)
extract_attribute(chld,"bodyend",q)
q.append("id_bodyfile=(select id from files where name=?)")
val.append(chld.attrib["bodyfile"])
chld.attrib.pop("bodyfile")
q.append("id_file=(select id from files where name=?)")
val.append(chld.attrib["file"])
chld.attrib.pop("file")
print_unprocessed_attributes(chld)
if len(chld.attrib) == 0:
node.remove(chld)
else:
extract_element(node,chld,q)
for chld in node.getchildren():
print "WARNING: '%s' has unprocessed child elem '%s'" % (node.tag,chld.tag)
extract_attribute(node,"kind",q)
extract_attribute(node,"prot",q)
extract_attribute(node,"static",q)
extract_attribute(node,"mutable",q)
extract_attribute(node,"const",q)
extract_attribute(node,"virt",q)
extract_attribute(node,"explicit",q)
extract_attribute(node,"inline",q)
q.append("refid=?")
val.append(node.attrib['id'])
node.attrib.pop('id')
print_unprocessed_attributes(node)
query="SELECT * FROM memberdef WHERE %s" % " AND ".join(q)
r=[]
try:
r = g_conn.execute(query,val).fetchall()
except sqlite3.OperationalError,e:
print "SQL_ERROR:%s"%e
del val[:]
if not len(r) > 0:
print "TEST_ERROR: Member not found in SQL DB"
def load_xml(name):
context = ET.iterparse(name, events=("start", "end"))
event, root = context.next()
for event, elem in context:
if event == "end" and elem.tag == "memberdef":
process_memberdef(elem)
print "\n== Unprocessed XML =="
# ET.dump(root)
def open_db(dbname):
global g_conn
if dbname == None:
dbname = "doxygen_sqlite3.db"
if not os.path.isfile(dbname):
raise BaseException("No such file %s" % dbname )
g_conn = sqlite3.connect(dbname)
g_conn.execute('PRAGMA temp_store = MEMORY;')
g_conn.row_factory = sqlite3.Row
def main(argv):
try:
opts, args = getopt.getopt(argv, "hd:x:",["help"])
except getopt.GetoptError:
sys.exit(1)
dbname=None
xmlfile=None
for a, o in opts:
if a in ('-h', '--help'):
sys.exit(0)
elif a in ('-d'):
dbname=o
continue
elif a in ('-x'):
xmlfile=o
continue
open_db(dbname)
load_xml(xmlfile)
if __name__ == '__main__':
main(sys.argv[1:])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment