Merge branch 'master' into C

This commit is contained in:
Vadim Zeitlin 2019-07-24 20:26:50 +02:00
commit 55741f9e31
1702 changed files with 57386 additions and 21599 deletions

View file

@ -28,6 +28,7 @@ extern "C" {
extern int cparse_cplusplusout;
extern int cparse_start_line;
extern String *cparse_unknown_directive;
extern int scan_doxygen_comments;
extern void Swig_cparse_cplusplus(int);
extern void Swig_cparse_cplusplusout(int);
@ -61,7 +62,7 @@ extern "C" {
extern void cparse_normalize_void(Node *);
extern Parm *Swig_cparse_parm(String *s);
extern ParmList *Swig_cparse_parms(String *s, Node *file_line_node);
extern Node *new_node(const_String_or_char_ptr tag);
extern Node *Swig_cparse_new_node(const_String_or_char_ptr tag);
/* templ.c */
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
@ -78,4 +79,7 @@ extern "C" {
#define SWIG_WARN_NODE_END(Node) \
if (wrnfilter) Swig_warnfilter(wrnfilter,0); \
}
#define COMPOUND_EXPR_VAL(dtype) \
((dtype).type == T_CHAR || (dtype).type == T_WCHAR ? (dtype).rawval : (dtype).val)
#endif

View file

@ -50,6 +50,57 @@ static int last_brace = 0;
static int last_id = 0;
static int rename_active = 0;
/* Doxygen comments scanning */
int scan_doxygen_comments = 0;
int isStructuralDoxygen(String *s) {
static const char* const structuralTags[] = {
"addtogroup",
"callgraph",
"callergraph",
"category",
"def",
"defgroup",
"dir",
"example",
"file",
"headerfile",
"internal",
"mainpage",
"name",
"nosubgrouping",
"overload",
"package",
"page",
"protocol",
"relates",
"relatesalso",
"showinitializer",
"weakgroup",
};
unsigned n;
char *slashPointer = Strchr(s, '\\');
char *atPointer = Strchr(s,'@');
if (slashPointer == NULL && atPointer == NULL)
return 0;
else if(slashPointer == NULL)
slashPointer = atPointer;
slashPointer++; /* skip backslash or at sign */
for (n = 0; n < sizeof(structuralTags)/sizeof(structuralTags[0]); n++) {
const size_t len = strlen(structuralTags[n]);
if (strncmp(slashPointer, structuralTags[n], len) == 0) {
/* Take care to avoid false positives with prefixes of other tags. */
if (slashPointer[len] == '\0' || isspace(slashPointer[len]))
return 1;
}
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_cparse_cplusplus()
* ----------------------------------------------------------------------------- */
@ -367,10 +418,70 @@ static int yylook(void) {
case SWIG_TOKEN_COMMENT:
{
String *cmt = Scanner_text(scan);
char *loc = Char(cmt);
if ((strncmp(loc,"/*@SWIG",7) == 0) && (loc[Len(cmt)-3] == '@')) {
Scanner_locator(scan, cmt);
typedef enum {
DOX_COMMENT_PRE = -1,
DOX_COMMENT_NONE,
DOX_COMMENT_POST
} comment_kind_t;
comment_kind_t existing_comment = DOX_COMMENT_NONE;
/* Concatenate or skip all consecutive comments at once. */
do {
String *cmt = Scanner_text(scan);
char *loc = Char(cmt);
if ((strncmp(loc, "/*@SWIG", 7) == 0) && (loc[Len(cmt)-3] == '@')) {
Scanner_locator(scan, cmt);
}
if (scan_doxygen_comments) { /* else just skip this node, to avoid crashes in parser module*/
/* Check for all possible Doxygen comment start markers while ignoring
comments starting with a row of asterisks or slashes just as
Doxygen itself does. */
if (Len(cmt) > 3 && loc[0] == '/' &&
((loc[1] == '/' && ((loc[2] == '/' && loc[3] != '/') || loc[2] == '!')) ||
(loc[1] == '*' && ((loc[2] == '*' && loc[3] != '*') || loc[2] == '!')))) {
comment_kind_t this_comment = loc[3] == '<' ? DOX_COMMENT_POST : DOX_COMMENT_PRE;
if (existing_comment != DOX_COMMENT_NONE && this_comment != existing_comment) {
/* We can't concatenate together Doxygen pre- and post-comments. */
break;
}
if (this_comment == DOX_COMMENT_POST || !isStructuralDoxygen(loc)) {
String *str;
int begin = this_comment == DOX_COMMENT_POST ? 4 : 3;
int end = Len(cmt);
if (loc[end - 1] == '/' && loc[end - 2] == '*') {
end -= 2;
}
str = NewStringWithSize(loc + begin, end - begin);
if (existing_comment == DOX_COMMENT_NONE) {
yylval.str = str;
Setline(yylval.str, Scanner_start_line(scan));
Setfile(yylval.str, Scanner_file(scan));
} else {
Append(yylval.str, str);
}
existing_comment = this_comment;
}
}
}
do {
tok = Scanner_token(scan);
} while (tok == SWIG_TOKEN_ENDLINE);
} while (tok == SWIG_TOKEN_COMMENT);
Scanner_pushtoken(scan, tok, Scanner_text(scan));
switch (existing_comment) {
case DOX_COMMENT_PRE:
return DOXYGENSTRING;
case DOX_COMMENT_NONE:
break;
case DOX_COMMENT_POST:
return DOXYGENPOSTSTRING;
}
}
break;
@ -907,6 +1018,8 @@ int yylex(void) {
return (ID);
case POUND:
return yylex();
case SWIG_TOKEN_COMMENT:
return yylex();
default:
return (l);
}

File diff suppressed because it is too large Load diff

View file

@ -30,8 +30,10 @@ static void add_parms(ParmList *p, List *patchlist, List *typelist) {
while (p) {
SwigType *ty = Getattr(p, "type");
SwigType *val = Getattr(p, "value");
SwigType *name = Getattr(p, "name");
Append(typelist, ty);
Append(typelist, val);
Append(typelist, name);
Append(patchlist, val);
p = nextSibling(p);
}
@ -49,32 +51,31 @@ void Swig_cparse_debug_templates(int x) {
* template parameters
* ----------------------------------------------------------------------------- */
static int cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) {
static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) {
static int expanded = 0;
int ret;
String *nodeType;
if (!n)
return 0;
return;
nodeType = nodeType(n);
if (Getattr(n, "error"))
return 0;
return;
if (Equal(nodeType, "template")) {
/* Change the node type back to normal */
if (!expanded) {
expanded = 1;
set_nodeType(n, Getattr(n, "templatetype"));
ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
expanded = 0;
return ret;
return;
} else {
/* Called when template appears inside another template */
/* Member templates */
set_nodeType(n, Getattr(n, "templatetype"));
ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
set_nodeType(n, "template");
return ret;
return;
}
} else if (Equal(nodeType, "cdecl")) {
/* A simple C declaration */
@ -131,7 +132,7 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String
{
Node *cn = firstChild(n);
while (cn) {
cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cn = nextSibling(cn);
}
}
@ -177,25 +178,30 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String
add_parms(Getattr(n, "parms"), cpatchlist, typelist);
add_parms(Getattr(n, "throws"), cpatchlist, typelist);
} else if (Equal(nodeType, "destructor")) {
String *name = Getattr(n, "name");
if (name) {
if (strchr(Char(name), '<'))
Append(patchlist, Getattr(n, "name"));
else
Append(name, templateargs);
}
name = Getattr(n, "sym:name");
if (name) {
if (strchr(Char(name), '<')) {
String *sn = Copy(tname);
Setattr(n, "sym:name", sn);
Delete(sn);
} else {
Replace(name, tname, rname, DOH_REPLACE_ANY);
/* We only need to patch the dtor of the template itself, not the destructors of any nested classes, so check that the parent of this node is the root
* template node, with the special exception for %extend which adds its methods under an intermediate node. */
Node* parent = parentNode(n);
if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) {
String *name = Getattr(n, "name");
if (name) {
if (strchr(Char(name), '<'))
Append(patchlist, Getattr(n, "name"));
else
Append(name, templateargs);
}
name = Getattr(n, "sym:name");
if (name) {
if (strchr(Char(name), '<')) {
String *sn = Copy(tname);
Setattr(n, "sym:name", sn);
Delete(sn);
} else {
Replace(name, tname, rname, DOH_REPLACE_ANY);
}
}
/* Setattr(n,"sym:name",name); */
Append(cpatchlist, Getattr(n, "code"));
}
/* Setattr(n,"sym:name",name); */
Append(cpatchlist, Getattr(n, "code"));
} else if (Equal(nodeType, "using")) {
String *uname = Getattr(n, "uname");
if (uname && strchr(Char(uname), '<')) {
@ -217,11 +223,10 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String
add_parms(Getattr(n, "throws"), cpatchlist, typelist);
cn = firstChild(n);
while (cn) {
cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cn = nextSibling(cn);
}
}
return 0;
}
static
@ -306,7 +311,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
/* Printf(stdout,"targs = '%s'\n", templateargs);
Printf(stdout,"rname = '%s'\n", rname);
Printf(stdout,"tname = '%s'\n", tname); */
cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
cparse_template_expand(n, n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
/* Set the name */
{

View file

@ -112,12 +112,12 @@ void cparse_normalize_void(Node *n) {
}
/* -----------------------------------------------------------------------------
* new_node()
* Swig_cparse_new_node()
*
* Create an empty parse node, setting file and line number information
* ----------------------------------------------------------------------------- */
Node *new_node(const_String_or_char_ptr tag) {
Node *Swig_cparse_new_node(const_String_or_char_ptr tag) {
Node *n = NewHash();
set_nodeType(n,tag);
Setfile(n,cparse_file);

View file

@ -81,8 +81,8 @@ static void InitPools() {
* ---------------------------------------------------------------------- */
int DohCheck(const DOH *ptr) {
register Pool *p = Pools;
register char *cptr = (char *) ptr;
Pool *p = Pools;
char *cptr = (char *) ptr;
while (p) {
if ((cptr >= p->pbeg) && (cptr < p->pend)) {
#ifdef DOH_DEBUG_MEMORY_POOLS

View file

@ -141,15 +141,15 @@ static int String_cmp(DOH *so1, DOH *so2) {
static int String_equal(DOH *so1, DOH *so2) {
String *s1 = (String *) ObjData(so1);
String *s2 = (String *) ObjData(so2);
register int len = s1->len;
int len = s1->len;
if (len != s2->len) {
return 0;
} else {
register char *c1 = s1->str;
register char *c2 = s2->str;
char *c1 = s1->str;
char *c2 = s2->str;
#if 0
register int mlen = len >> 2;
register int i = mlen;
int mlen = len >> 2;
int i = mlen;
for (; i; --i) {
if (*(c1++) != *(c2++))
return 0;
@ -180,11 +180,11 @@ static int String_hash(DOH *so) {
if (s->hashkey >= 0) {
return s->hashkey;
} else {
register char *c = s->str;
register unsigned int len = s->len > 50 ? 50 : s->len;
register unsigned int h = 0;
register unsigned int mlen = len >> 2;
register unsigned int i = mlen;
char *c = s->str;
unsigned int len = s->len > 50 ? 50 : s->len;
unsigned int h = 0;
unsigned int mlen = len >> 2;
unsigned int i = mlen;
for (; i; --i) {
h = (h << 5) + *(c++);
h = (h << 5) + *(c++);
@ -463,9 +463,9 @@ static int String_seek(DOH *so, long offset, int whence) {
{
#if 0
register int sp = s->sp;
register char *tc = s->str;
register int len = s->len;
int sp = s->sp;
char *tc = s->str;
int len = s->len;
while (sp != nsp) {
int prev = sp + inc;
if (prev >= 0 && prev <= len && tc[prev] == '\n')
@ -473,8 +473,8 @@ static int String_seek(DOH *so, long offset, int whence) {
sp += inc;
}
#else
register int sp = s->sp;
register char *tc = s->str;
int sp = s->sp;
char *tc = s->str;
if (inc > 0) {
while (sp != nsp) {
if (tc[++sp] == '\n')
@ -508,12 +508,12 @@ static long String_tell(DOH *so) {
static int String_putc(DOH *so, int ch) {
String *s = (String *) ObjData(so);
register int len = s->len;
register int sp = s->sp;
int len = s->len;
int sp = s->sp;
s->hashkey = -1;
if (sp >= len) {
register int maxsize = s->maxsize;
register char *tc = s->str;
int maxsize = s->maxsize;
char *tc = s->str;
if (len > (maxsize - 2)) {
maxsize *= 2;
tc = (char *) DohRealloc(tc, maxsize);
@ -679,7 +679,7 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co
int noquote = 0;
char *c, *s, *t, *first;
char *q, *q2;
register char *base;
char *base;
int i;
/* Figure out if anything gets replaced */

View file

@ -0,0 +1,170 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxycommands.h
*
* Part of the Doxygen comment translation module of SWIG.
* ----------------------------------------------------------------------------- */
#ifndef DOXYGENCOMMANDS_H
#define DOXYGENCOMMANDS_H
// doxy commands are not processed inside this block
const char *CMD_HTML_ONLY = "htmlonly";
// doxy commands are not processed inside this block
const char *CMD_VERBATIM = "verbatim";
const char *CMD_LATEX_1 = "f$";
const char *CMD_LATEX_2 = "f{";
const char *CMD_LATEX_3 = "f[";
const char *CMD_END_HTML_ONLY = "endhtmlonly";
const char *CMD_END_VERBATIM = "endverbatim";
const char *CMD_END_LATEX_1 = "f$";
const char *CMD_END_LATEX_2 = "f}";
const char *CMD_END_LATEX_3 = "f]";
const char *sectionIndicators[] = {
"attention", "author", "authors", "brief", "bug", "cond", "date",
"deprecated", "details", "else", "elseif", "endcond", "endif",
"exception", "if", "ifnot", "invariant", "note", "par", "param",
"tparam", "post", "pre", "remarks", "remark", "result", "return",
"returns", "retval", "sa", "see", "since", "test", "throw", "throws",
"todo", "version", "warning", "xrefitem"
};
const int sectionIndicatorsSize = sizeof(sectionIndicators) / sizeof(*sectionIndicators);
/* All of the doxygen commands divided up by how they are parsed */
const char *simpleCommands[] = {
// the first line are escaped chars, except \~, which is a language ID command.
"n", "$", "@", "\\", "&", "~", "<", ">", "#", "%", "\"", ".", "::",
"endcond",
"callgraph", "callergraph", "showinitializer", "hideinitializer", "internal",
"nosubgrouping", "public", "publicsection", "private", "privatesection",
"protected", "protectedsection", "tableofcontents"
};
const int simpleCommandsSize = sizeof(simpleCommands) / sizeof(*simpleCommands);
const char *commandWords[] = {
"a", "b", "c", "e", "em", "p", "def", "enum", "package", "relates",
"namespace", "relatesalso", "anchor", "dontinclude", "include",
"includelineno", "copydoc", "copybrief", "copydetails", "verbinclude",
"htmlinclude", "extends", "implements", "memberof", "related", "relatedalso",
"cite"
};
const int commandWordsSize = sizeof(commandWords) / sizeof(*commandWords);
const char *commandLines[] = {
"addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip",
"until", "property"
};
const int commandLinesSize = sizeof(commandLines) / sizeof(*commandLines);
const char *commandParagraph[] = {
"partofdescription", "result", "return", "returns", "remarks", "remark",
"since", "test", "sa", "see", "pre", "post", "details", "invariant",
"deprecated", "date", "note", "warning", "version", "todo", "bug",
"attention", "brief", "author", "authors", "copyright", "short"
};
const int commandParagraphSize = sizeof(commandParagraph) / sizeof(*commandParagraph);
const char *commandEndCommands[] = {
CMD_HTML_ONLY, "latexonly", "manonly", "xmlonly", "link", "rtfonly"
};
const int commandEndCommandsSize = sizeof(commandEndCommands) / sizeof(*commandEndCommands);
const char *commandWordParagraphs[] = {
"param", "tparam", "throw", "throws", "retval", "exception", "example"
};
const int commandWordParagraphsSize = sizeof(commandWordParagraphs) / sizeof(*commandWordParagraphs);
const char *commandWordLines[] = {
"page", "subsection", "subsubsection", "section", "paragraph", "defgroup",
"snippet", "mainpage"
};
const int commandWordLinesSize = sizeof(commandWordLines) / sizeof(*commandWordLines);
const char *commandWordOWordOWords[] = {
"category", "class", "protocol", "interface", "struct", "union"
};
const int commandWordOWordOWordsSize = sizeof(commandWordOWordOWords) / sizeof(*commandWordOWordOWords);
const char *commandOWords[] = {
"dir", "file", "cond"
};
const int commandOWordsSize = sizeof(commandOWords) / sizeof(*commandOWords);
const char *commandErrorThrowings[] = {
"annotatedclassstd::list", "classhierarchy", "define", "functionindex", "header",
"headerfilestd::list", "inherit", "l", "postheader", "endcode", "enddot", "endmsc", "endhtmlonly",
"endlatexonly", "endmanonly", "endlink", "endverbatim", "endxmlonly", "f]", "f}", "endif", "else",
"endrtfonly"
};
const int commandErrorThrowingsSize = sizeof(commandErrorThrowings) / sizeof(*commandErrorThrowings);
const char *commandUniques[] = {
"xrefitem", "arg", "ingroup", "par", "headerfile", "overload", "weakgroup", "ref", "subpage", "dotfile", "image", "addtogroup", "li",
"if", "ifnot", "elseif", "else", "mscfile", "code", CMD_VERBATIM, "f{", "f[", "f$", "dot", "msc"
};
const int commandUniquesSize = sizeof(commandUniques) / sizeof(*commandUniques);
// These HTML commands are transformed when producing output in other formats.
// Other commands are left intact, but '<' and '> are replaced with entities in HTML
// output. So <varName> appears as &lt;varName&gt; in HTML output. The same
// behavior must be repeated by SWIG. See Doxygen doc for the list of commands.
// '<' is prepended to distinguish HTML tags from Doxygen commands.
const char *commandHtml[] = {
"<a", "<b", "<blockquote", "<body", "<br", "<center", "<caption", "<code", "<dd", "<dfn",
"<div", "<dl", "<dt", "<em", "<form", "<hr", "<h1", "<h2", "<h3", "<i", "<input", "<img",
"<li", "<meta", "<multicol", "<ol", "<p", "<pre", "<small", "<span", "<strong",
"<sub", "<sup", "<table", "<td", "<th", "<tr", "<tt", "<kbd", "<ul", "<var"
};
const int commandHtmlSize = sizeof(commandHtml) / sizeof(*commandHtml);
// Only entities which are translatable to plain text are used here. Others
// are copied unchanged to output.
const char *commandHtmlEntities[] = {
"&copy", // (C)
"&trade", // (TM)
"&reg", // (R)
"&lt", // less-than symbol
"&gt", // greater-than symbol
"&amp", // ampersand
"&apos", // single quotation mark (straight)
"&quot", // double quotation mark (straight)
"&lsquo", // left single quotation mark
"&rsquo", // right single quotation mark
"&ldquo", // left double quotation mark
"&rdquo", // right double quotation mark
"&ndash", // n-dash (for numeric ranges, e.g. 28)
"&mdash", // --
"&nbsp", //
"&times", // x
"&minus", // -
"&sdot", // .
"&sim", // ~
"&le", // <=
"&ge", // >=
"&larr", // <--
"&rarr" // -->
};
const int commandHtmlEntitiesSize = sizeof(commandHtmlEntities) / sizeof(*commandHtmlEntities);
#endif

View file

@ -0,0 +1,69 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxyentity.cxx
*
* Part of the Doxygen comment translation module of SWIG.
* ----------------------------------------------------------------------------- */
#include "doxyentity.h"
#include <iostream>
using std::cout;
DoxygenEntity::DoxygenEntity(const std::string &typeEnt):typeOfEntity(typeEnt), isLeaf(true) {
}
/* Basic node for commands that have
* only 1 item after them
* example: \b word
* OR holding a std::string
*/
DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const std::string &param1) : typeOfEntity(typeEnt), data(param1), isLeaf(true) {
}
/* Nonterminal node
* contains
*/
DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList) : typeOfEntity(typeEnt), isLeaf(false), entityList(entList) {
}
void DoxygenEntity::printEntity(int level) const {
int thisLevel = level;
if (isLeaf) {
for (int i = 0; i < thisLevel; i++) {
cout << "\t";
}
cout << "Node Leaf Command: '" << typeOfEntity << "', ";
if (!data.empty()) {
cout << "Node Data: '" << data << "'";
}
cout << std::endl;
} else {
for (int i = 0; i < thisLevel; i++) {
cout << "\t";
}
cout << "Node Command: '" << typeOfEntity << "'" << std::endl;
thisLevel++;
for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) {
p->printEntity(thisLevel);
}
}
}

View file

@ -0,0 +1,45 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxyentity.h
*
* Part of the Doxygen comment translation module of SWIG.
* ----------------------------------------------------------------------------- */
#ifndef DOXYGENENTITY_H_
#define DOXYGENENTITY_H_
#include <string>
#include <list>
class DoxygenEntity;
typedef std::list<DoxygenEntity> DoxygenEntityList;
typedef DoxygenEntityList::iterator DoxygenEntityListIt;
typedef DoxygenEntityList::const_iterator DoxygenEntityListCIt;
/*
* Structure to represent a doxygen comment entry
*/
class DoxygenEntity {
public:
std::string typeOfEntity;
std::string data;
bool isLeaf;
DoxygenEntityList entityList;
DoxygenEntity(const std::string &typeEnt);
DoxygenEntity(const std::string &typeEnt, const std::string &param1);
DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList);
void printEntity(int level) const;
};
#endif

File diff suppressed because it is too large Load diff

372
Source/Doxygen/doxyparser.h Normal file
View file

@ -0,0 +1,372 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxyparser.h
* ----------------------------------------------------------------------------- */
#ifndef DOXYGENPARSER_H_
#define DOXYGENPARSER_H_
#include <string>
#include <list>
#include <map>
#include <vector>
#include <set>
#include "swig.h"
#include "doxyentity.h"
class DoxygenParser {
private:
enum DoxyCommandEnum {
NONE = -1,
SIMPLECOMMAND,
COMMANDWORD,
COMMANDLINE,
COMMANDPARAGRAPH,
COMMANDENDCOMMAND,
COMMANDWORDPARAGRAPH,
COMMANDWORDLINE,
COMMANDWORDOWORDWORD,
COMMANDOWORD,
COMMANDERRORTHROW,
COMMANDUNIQUE,
COMMAND_HTML,
COMMAND_HTML_ENTITY,
COMMAND_ALIAS,
COMMAND_IGNORE,
END_LINE,
PARAGRAPH_END,
PLAINSTRING,
COMMAND
};
/** This class contains parts of Doxygen comment as a token. */
class Token {
public:
DoxyCommandEnum m_tokenType;
std::string m_tokenString; /* the data , such as param for @param */
Token(DoxyCommandEnum tType, std::string tString) : m_tokenType(tType), m_tokenString(tString) {
}
std::string toString() const {
switch (m_tokenType) {
case END_LINE:
return "{END OF LINE}";
case PARAGRAPH_END:
return "{END OF PARAGRAPH}";
case PLAINSTRING:
return "{PLAINSTRING :" + m_tokenString + "}";
case COMMAND:
return "{COMMAND : " + m_tokenString + "}";
default:
return "";
}
}
};
typedef std::vector<Token> TokenList;
typedef TokenList::const_iterator TokenListCIt;
typedef TokenList::iterator TokenListIt;
TokenList m_tokenList;
TokenListCIt m_tokenListIt;
typedef std::map<std::string, DoxyCommandEnum> DoxyCommandsMap;
typedef DoxyCommandsMap::iterator DoxyCommandsMapIt;
/*
* Map of Doxygen commands to determine if a string is a
* command and how it needs to be parsed
*/
static DoxyCommandsMap doxygenCommands;
static std::set<std::string> doxygenSectionIndicators;
bool m_isVerbatimText; // used to handle \htmlonly and \verbatim commands
bool m_isInQuotedString;
Node *m_node;
std::string m_fileName;
int m_fileLineNo;
/*
* Return the end command for a command appearing in "ignore" feature or empty
* string if this is a simple command and not a block one.
*/
std::string getIgnoreFeatureEndCommand(const std::string &theCommand) const;
/*
* Helper for getting the value of doxygen:ignore feature or its argument.
*/
String *getIgnoreFeature(const std::string &theCommand, const char *argument = NULL) const;
/*
* Whether to print lots of debug info during parsing
*/
bool noisy;
/*
*Changes a std::string to all lower case
*/
std::string stringToLower(const std::string &stringToConvert);
/*
* isSectionIndicator returns a boolean if the command is a section indicator
* This is a helper method for finding the end of a paragraph
* by Doxygen's terms
*/
bool isSectionIndicator(const std::string &smallString);
/*
* Determines how a command should be handled (what group it belongs to
* for parsing rules
*/
DoxyCommandEnum commandBelongs(const std::string &theCommand);
/*
*prints the parse tree
*/
void printTree(const std::list<DoxygenEntity> &rootList);
/**
* Returns true if the next token is end of line token. This is important
* when single word commands like \c are at the end of line.
*/
bool isEndOfLine();
/**
* Skips spaces, tabs, and end of line tokens.
*/
void skipWhitespaceTokens();
/**
* Removes all spaces and tabs from beginning end end of string.
*/
std::string trim(const std::string &text);
/*
* Returns string of the next token if the next token is PLAINSTRING. Returns
* empty string otherwise.
*/
std::string getNextToken();
/*
* Returns the next word ON THE CURRENT LINE ONLY
* if a new line is encountered, returns a blank std::string.
* Updates the iterator if successful.
*/
std::string getNextWord();
/*
* Returns the next word, which is not necessarily on the same line.
* Updates the iterator if successful.
*/
std::string getNextWordInComment();
/*
* Returns the location of the end of the line as
* an iterator.
*/
TokenListCIt getOneLine(const TokenList &tokList);
/*
* Returns a properly formatted std::string
* up til ANY command or end of line is encountered.
*/
std::string getStringTilCommand(const TokenList &tokList);
/*
* Returns a properly formatted std::string
* up til the command specified is encountered
*/
//TODO check that this behaves properly for formulas
std::string getStringTilEndCommand(const std::string &theCommand, const TokenList &tokList);
/*
* Returns the end of a Paragraph as an iterator-
* Paragraph is defined in Doxygen to be a paragraph of text
* separated by either a structural command or a blank line
*/
TokenListCIt getEndOfParagraph(const TokenList &tokList);
/*
* Returns the end of a section, defined as the first blank line OR first
* encounter of the same command. Example of this behaviour is \arg.
* If no end is encountered, returns the last token of the std::list.
*/
TokenListCIt getEndOfSection(const std::string &theCommand, const TokenList &tokList);
/*
* This method is for returning the end of a specific form of doxygen command
* that begins with a \command and ends in \endcommand
* such as \code and \endcode. The proper usage is
* progressTilEndCommand("endcode", tokenList);
* If the end is never encountered, it returns the end of the std::list.
*/
TokenListCIt getEndCommand(const std::string &theCommand, const TokenList &tokList);
/*
* A special method for commands such as \arg that end at the end of a
* paragraph OR when another \arg is encountered
//TODO getTilAnyCommand
TokenListCIt getTilAnyCommand(const std::string &theCommand, const TokenList &tokList);
*/
/**
* This methods skips end of line token, if it is the next token to be
* processed. It is called with comment commands which have args till the
* end of line, such as 'addtogroup' or 'addindex'.
* It is up to translator to specific language to decide whether
* to insert eol or not. For example, if a command is ignored in target
* language, new lines may make formatting ugly (Python).
*/
void skipEndOfLine();
/*
* Method for Adding a Simple Command
* Format: @command
* Plain commands, such as newline etc, they contain no other data
* \n \\ \@ \& \$ \# \< \> \%
*/
void addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList);
/*
* CommandWord
* Format: @command <word>
* Commands with a single WORD after then such as @b
* "a", "b", "c", "e", "em", "p", "def", "enum", "example", "package",
* "relates", "namespace", "relatesalso","anchor", "dontinclude", "include",
* "includelineno"
*/
void addCommandWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* CommandLine
* Format: @command (line)
* Commands with a single LINE after then such as @var
* "addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip",
* "until", "property"
*/
void addCommandLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* CommandParagraph
* Format: @command {paragraph}
* Commands with a single paragraph after then such as @return
* "return", "remarks", "since", "test", "sa", "see", "pre", "post",
* "details", "invariant", "deprecated", "date", "note", "warning",
* "version", "todo", "bug", "attention", "brief", "arg", "author"
*/
void addCommandParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Command EndCommand
* Format: @command and ends at @endcommand
* Commands that take in a block of text such as @code:
* "code", "dot", "msc", "f$", "f[", "f{environment}{", "htmlonly",
* "latexonly", "manonly", "verbatim", "xmlonly", "cond", "if", "ifnot",
* "link"
* Returns 1 if success, 0 if the endcommand is never encountered.
*/
void addCommandEndCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* CommandWordParagraph
* Format: @command <word> {paragraph}
* Commands such as param
* "param", "tparam", "throw", "throws", "retval", "exception"
*/
void addCommandWordParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* CommandWordLine
* Format: @command <word> (line)
* Commands such as param
* "page", "subsection", "subsubsection", "section", "paragraph", "defgroup"
*/
void addCommandWordLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Command Word Optional Word Optional Word
* Format: @command <word> [<header-file>] [<header-name>]
* Commands such as class
* "category", "class", "protocol", "interface", "struct", "union"
*/
void addCommandWordOWordOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Command Optional Word
* Format: @command [<word>]
* Commands such as dir
* "dir", "file", "cond"
*/
void addCommandOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Commands that should not be encountered (such as PHP only)
* goes til the end of line then returns
*/
void addCommandErrorThrow(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
void addCommandHtml(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
void addCommandHtmlEntity(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
*Adds the unique commands- different process for each unique command
*/
void addCommandUnique(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Replace the given command with its predefined alias expansion.
*/
void aliasCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* Simply ignore the given command, possibly with the word following it or
* until the matching end command.
*/
void ignoreCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
/*
* The actual "meat" of the doxygen parser. Calls the correct addCommand...()
* function.
*/
void addCommand(const std::string &commandString, const TokenList &tokList, DoxygenEntityList &doxyList);
DoxygenEntityList parse(TokenListCIt endParsingIndex, const TokenList &tokList, bool root = false);
/*
* Fill static doxygenCommands and sectionIndicators containers
*/
void fillTables();
/** Processes comment when \htmlonly and \verbatim commands are encountered. */
size_t processVerbatimText(size_t pos, const std::string &line);
bool processEscapedChars(size_t &pos, const std::string &line);
void processWordCommands(size_t &pos, const std::string &line);
void processHtmlTags(size_t &pos, const std::string &line);
void processHtmlEntities(size_t &pos, const std::string &line);
/** Processes comment outside \htmlonly and \verbatim commands. */
size_t processNormalComment(size_t pos, const std::string &line);
void tokenizeDoxygenComment(const std::string &doxygenComment, const std::string &fileName, int fileLine);
void printList();
void printListError(int warningType, const std::string &message);
typedef std::vector<std::string> StringVector;
typedef StringVector::const_iterator StringVectorCIt;
StringVector split(const std::string &text, char separator);
bool isStartOfDoxyCommentChar(char c);
bool addDoxyCommand(DoxygenParser::TokenList &tokList, const std::string &cmd);
public:
DoxygenParser(bool noisy = false);
virtual ~DoxygenParser();
DoxygenEntityList createTree(Node *node, String *documentation);
};
#endif

View file

@ -0,0 +1,69 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxytranslator.cxx
*
* Module to return documentation for nodes formatted for various documentation
* systems.
* ----------------------------------------------------------------------------- */
#include "doxytranslator.h"
DoxygenTranslator::DoxygenTranslator(int flags) : m_flags(flags), parser((flags &debug_parser) != 0) {
}
DoxygenTranslator::~DoxygenTranslator() {
}
bool DoxygenTranslator::hasDocumentation(Node *node) {
return getDoxygenComment(node) != NULL;
}
String *DoxygenTranslator::getDoxygenComment(Node *node) {
return Getattr(node, "doxygen");
}
/**
* Indent all lines in the comment by given indentation string
*/
void DoxygenTranslator::extraIndentation(String *comment, const_String_or_char_ptr indentationString) {
if (indentationString || Len(indentationString) > 0) {
int len = Len(comment);
bool trailing_newline = len > 0 && *(Char(comment) + len - 1) == '\n';
Insert(comment, 0, indentationString);
String *replace = NewStringf("\n%s", indentationString);
Replaceall(comment, "\n", replace);
if (trailing_newline) {
len = Len(comment);
Delslice(comment, len - 2, len); // Remove added trailing spaces on last line
}
Delete(replace);
}
}
String *DoxygenTranslator::getDocumentation(Node *node, const_String_or_char_ptr indentationString) {
if (!hasDocumentation(node)) {
return NewString("");
}
String *documentation = makeDocumentation(node);
extraIndentation(documentation, indentationString);
return documentation;
}
void DoxygenTranslator::printTree(const DoxygenEntityList &entityList) {
for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) {
p->printEntity(0);
}
}

View file

@ -0,0 +1,90 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* doxytranslator.h
*
* Module to return documentation for nodes formatted for various documentation
* systems.
* ----------------------------------------------------------------------------- */
#ifndef DOXYGENTRANSLATOR_H_
#define DOXYGENTRANSLATOR_H_
#include "swig.h"
#include "doxyentity.h"
#include "doxyparser.h"
#include <list>
#include <string>
/*
* This is a base class for translator classes. It defines the basic interface
* for translators, which convert Doxygen comments into alternative formats for
* target languages.
*/
class DoxygenTranslator {
public:
/*
* Bit flags for the translator ctor.
*
* Derived classes may define additional flags.
*/
enum {
// Use DoxygenParser in "noisy" mode.
debug_parser = 1,
// Output results of translating Doxygen comments.
debug_translator = 2
};
/*
* Constructor
*/
DoxygenTranslator(int flags = 0);
/*
* Virtual destructor.
*/
virtual ~DoxygenTranslator();
/*
* Return the documentation for a given node formated for the correct
* documentation system.
*/
String *getDocumentation(Node *node, const_String_or_char_ptr indentationString);
/*
* Returns truem is the specified node has comment attached.
*/
bool hasDocumentation(Node *node);
/*
* Get original comment string in Doxygen-format.
*/
String *getDoxygenComment(Node *node);
protected:
// The flags passed to the ctor.
const int m_flags;
DoxygenParser parser;
/*
* Returns the documentation formatted for a target language.
*/
virtual String *makeDocumentation(Node *node) = 0;
/*
* Prints the details of a parsed entity list to stdout (for debugging).
*/
void printTree(const DoxygenEntityList &entityList);
void extraIndentation(String *comment, const_String_or_char_ptr indentationString);
};
#endif

845
Source/Doxygen/javadoc.cxx Normal file
View file

@ -0,0 +1,845 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* javadoc.cxx
* ----------------------------------------------------------------------------- */
#include "javadoc.h"
#include "doxyparser.h"
#include <iostream>
#include <vector>
#include <list>
#include "swigmod.h"
#define APPROX_LINE_LENGTH 64 // characters per line allowed
#define TAB_SIZE 8 // current tab size in spaces
//TODO {@link} {@linkplain} {@docRoot}, and other useful doxy commands that are not a javadoc tag
// define static tables, they are filled in JavaDocConverter's constructor
std::map<std::string, std::pair<JavaDocConverter::tagHandler, std::string> > JavaDocConverter::tagHandlers;
using std::string;
using std::list;
using std::vector;
void JavaDocConverter::fillStaticTables() {
if (tagHandlers.size()) // fill only once
return;
/*
* Some translation rules:
*
* @ and \ must be escaped for both Java and Python to appear on output: \@, \\,
* while Doxygen produces output in both cases.
* Rule: @ and \ with space on the right should get to output.
*
* :: remains intact, even in class::method(). But you can use class#method also
* in C++ comment and it is properly translated to C++ output (changed by doxygen to ::)
* and Java output (remains #).
* Rule: SWIG type system can't be used to convert C::m to C#m, because in Java it is C.m
* Use string replacement :: --> # in tag see and links.
*
* HTML tags must be translated - remain in Java, to markdown in Python
*
* Unknown HTML tags, for example <x> is translated to &lt;x&gt; by doxygen, while
* Java src is <x> and therefore invisible on output - browser ignores unknown command.
* This is handy in syntax descriptions, for example: more <fileName>.
*
* Standalone < and > need not be translated, they are rendered properly in
* all three outputs.
*
* ., %, and " need not to be translated
*
* entities must be translated - remain in Java, something meaningful in Python (&lt, ...)
*
* - Python
* - add comments also to auto-generated methods like equals(), delete() in Java,
* and methods for std::vector(), ...
* Commenting methods of std types is simple - add comment to std_*.i file.
*/
// these commands insert HTML tags
tagHandlers["a"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
tagHandlers["arg"] = make_pair(&JavaDocConverter::handleTagHtml, "li");
tagHandlers["b"] = make_pair(&JavaDocConverter::handleTagHtml, "b");
tagHandlers["c"] = make_pair(&JavaDocConverter::handleTagHtml, "code");
tagHandlers["cite"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
tagHandlers["e"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
tagHandlers["em"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
tagHandlers["li"] = make_pair(&JavaDocConverter::handleTagHtml, "li");
tagHandlers["p"] = make_pair(&JavaDocConverter::handleTagHtml, "code");
// these commands insert just a single char, some of them need to be escaped
tagHandlers["$"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["@"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["\\"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["<"] = make_pair(&JavaDocConverter::handleTagChar, "&lt;");
tagHandlers[">"] = make_pair(&JavaDocConverter::handleTagChar, "&gt;");
tagHandlers["&"] = make_pair(&JavaDocConverter::handleTagChar, "&amp;");
tagHandlers["#"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["%"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["~"] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["\""] = make_pair(&JavaDocConverter::handleTagChar, "&quot;");
tagHandlers["."] = make_pair(&JavaDocConverter::handleTagChar, "");
tagHandlers["::"] = make_pair(&JavaDocConverter::handleTagChar, "");
// these commands are stripped out
tagHandlers["attention"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["anchor"] = make_pair(&JavaDocConverter::handleTagAnchor, "");
tagHandlers["brief"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["bug"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["date"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["details"] = make_pair(&JavaDocConverter::handleParagraph, "");
// this command is inserts text accumulated after cmd htmlonly -
// see DoxygenParser - CMD_HTML_ONLY.
tagHandlers["htmlonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["invariant"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["latexonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["manonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["partofdescription"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["rtfonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["short"] = make_pair(&JavaDocConverter::handleParagraph, "");
tagHandlers["xmlonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
// these commands are kept as-is, they are supported by JavaDoc
tagHandlers["author"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["authors"] = make_pair(&JavaDocConverter::handleTagSame, "author");
tagHandlers["deprecated"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["exception"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["package"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["param"] = make_pair(&JavaDocConverter::handleTagParam, "");
tagHandlers["tparam"] = make_pair(&JavaDocConverter::handleTagParam, "");
tagHandlers["ref"] = make_pair(&JavaDocConverter::handleTagRef, "");
tagHandlers["result"] = make_pair(&JavaDocConverter::handleTagSame, "return");
tagHandlers["return"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["returns"] = make_pair(&JavaDocConverter::handleTagSame, "return");
//tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSame, "");
//tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSame, "see");
tagHandlers["since"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["throws"] = make_pair(&JavaDocConverter::handleTagSame, "");
tagHandlers["throw"] = make_pair(&JavaDocConverter::handleTagSame, "throws");
tagHandlers["version"] = make_pair(&JavaDocConverter::handleTagSame, "");
// these commands have special handlers
tagHandlers["code"] = make_pair(&JavaDocConverter::handleTagExtended, "code");
tagHandlers["cond"] = make_pair(&JavaDocConverter::handleTagMessage, "Conditional comment: ");
tagHandlers["copyright"] = make_pair(&JavaDocConverter::handleTagMessage, "Copyright: ");
tagHandlers["else"] = make_pair(&JavaDocConverter::handleTagIf, "Else: ");
tagHandlers["elseif"] = make_pair(&JavaDocConverter::handleTagIf, "Else if: ");
tagHandlers["endcond"] = make_pair(&JavaDocConverter::handleTagMessage, "End of conditional comment.");
// space in second arg prevents Javadoc to treat '@ example' as command. File name of
// example is still informative to user.
tagHandlers["example"] = make_pair(&JavaDocConverter::handleTagSame, " example");
tagHandlers["if"] = make_pair(&JavaDocConverter::handleTagIf, "If: ");
tagHandlers["ifnot"] = make_pair(&JavaDocConverter::handleTagIf, "If not: ");
tagHandlers["image"] = make_pair(&JavaDocConverter::handleTagImage, "");
tagHandlers["link"] = make_pair(&JavaDocConverter::handleTagLink, "");
tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSee, "");
tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSee, "");
tagHandlers["note"] = make_pair(&JavaDocConverter::handleTagMessage, "Note: ");
tagHandlers["overload"] = make_pair(&JavaDocConverter::handleTagMessage,
"This is an overloaded member function, provided for"
" convenience. It differs from the above function only in what" " argument(s) it accepts.");
tagHandlers["par"] = make_pair(&JavaDocConverter::handleTagPar, "");
tagHandlers["remark"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: ");
tagHandlers["remarks"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: ");
tagHandlers["todo"] = make_pair(&JavaDocConverter::handleTagMessage, "TODO: ");
tagHandlers["verbatim"] = make_pair(&JavaDocConverter::handleTagExtended, "literal");
// \f commands output literal Latex formula, which is still better than nothing.
tagHandlers["f$"] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
tagHandlers["f["] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
tagHandlers["f{"] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
tagHandlers["warning"] = make_pair(&JavaDocConverter::handleTagMessage, "Warning: ");
// this command just prints it's contents
// (it is internal command of swig's parser, contains plain text)
tagHandlers["plainstd::string"] = make_pair(&JavaDocConverter::handlePlainString, "");
tagHandlers["plainstd::endl"] = make_pair(&JavaDocConverter::handleNewLine, "");
tagHandlers["n"] = make_pair(&JavaDocConverter::handleNewLine, "");
// HTML tags
tagHandlers["<a"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<a");
tagHandlers["<b"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<b");
tagHandlers["<blockquote"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<blockquote");
tagHandlers["<body"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<body");
tagHandlers["<br"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<br");
tagHandlers["<center"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<center");
tagHandlers["<caption"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<caption");
tagHandlers["<code"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<code");
tagHandlers["<dd"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dd");
tagHandlers["<dfn"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dfn");
tagHandlers["<div"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<div");
tagHandlers["<dl"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dl");
tagHandlers["<dt"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dt");
tagHandlers["<em"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<em");
tagHandlers["<form"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<form");
tagHandlers["<hr"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<hr");
tagHandlers["<h1"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h1");
tagHandlers["<h2"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h2");
tagHandlers["<h3"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h3");
tagHandlers["<i"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<i");
tagHandlers["<input"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<input");
tagHandlers["<img"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<img");
tagHandlers["<li"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<li");
tagHandlers["<meta"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<meta");
tagHandlers["<multicol"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<multicol");
tagHandlers["<ol"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<ol");
tagHandlers["<p"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<p");
tagHandlers["<pre"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<pre");
tagHandlers["<small"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<small");
tagHandlers["<span"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<span");
tagHandlers["<strong"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<strong");
tagHandlers["<sub"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<sub");
tagHandlers["<sup"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<sup");
tagHandlers["<table"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<table");
tagHandlers["<td"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<td");
tagHandlers["<th"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<th");
tagHandlers["<tr"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<tr");
tagHandlers["<tt"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<tt");
tagHandlers["<kbd"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<kbd");
tagHandlers["<ul"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<ul");
tagHandlers["<var"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<var");
// HTML entities
tagHandlers["&copy"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&copy");
tagHandlers["&trade"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&trade");
tagHandlers["&reg"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&reg");
tagHandlers["&lt"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&lt");
tagHandlers["&gt"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&gt");
tagHandlers["&amp"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&amp");
tagHandlers["&apos"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&apos");
tagHandlers["&quot"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&quot");
tagHandlers["&lsquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&lsquo");
tagHandlers["&rsquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rsquo");
tagHandlers["&ldquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ldquo");
tagHandlers["&rdquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rdquo");
tagHandlers["&ndash"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ndash");
tagHandlers["&mdash"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&mdash");
tagHandlers["&nbsp"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&nbsp");
tagHandlers["&times"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&times");
tagHandlers["&minus"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&minus");
tagHandlers["&sdot"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&sdot");
tagHandlers["&sim"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&sim");
tagHandlers["&le"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&le");
tagHandlers["&ge"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ge");
tagHandlers["&larr"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&larr");
tagHandlers["&rarr"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rarr");
}
JavaDocConverter::JavaDocConverter(int flags) :
DoxygenTranslator(flags) {
fillStaticTables();
}
/**
* Formats comment lines by inserting '\n *' at to long lines and tabs for
* indent. Currently it is disabled, which means original comment format is
* preserved. Experience shows, that this is usually better than breaking
* lines automatically, especially because original line endings are not removed,
* which results in short lines. To be useful, this function should have much
* better algorithm.
*/
std::string JavaDocConverter::formatCommand(std::string unformattedLine, int indent) {
std::string formattedLines;
return unformattedLine; // currently disabled
std::string::size_type lastPosition = 0;
std::string::size_type i = 0;
int isFirstLine = 1;
while (i != std::string::npos && i < unformattedLine.length()) {
lastPosition = i;
if (isFirstLine) {
i += APPROX_LINE_LENGTH;
} else {
i += APPROX_LINE_LENGTH - indent * TAB_SIZE;
}
i = unformattedLine.find(" ", i);
if (i > 0 && i + 1 < unformattedLine.length()) {
if (!isFirstLine)
for (int j = 0; j < indent; j++) {
formattedLines.append("\t");
} else {
isFirstLine = 0;
}
formattedLines.append(unformattedLine.substr(lastPosition, i - lastPosition + 1));
formattedLines.append("\n *");
}
}
if (lastPosition < unformattedLine.length()) {
if (!isFirstLine) {
for (int j = 0; j < indent; j++) {
formattedLines.append("\t");
}
}
formattedLines.append(unformattedLine.substr(lastPosition, unformattedLine.length() - lastPosition));
}
return formattedLines;
}
/**
* Returns true, if the given parameter exists in the current node
* (for example param is a name of function parameter). If feature
* 'doxygen:nostripparams' is set, then this method always returns
* true - parameters are copied to output regardless of presence in
* function params list.
*/
bool JavaDocConverter::paramExists(std::string param) {
if (GetFlag(currentNode, "feature:doxygen:nostripparams")) {
return true;
}
ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
for (Parm *p = plist; p;) {
if (Getattr(p, "name") && Char(Getattr(p, "name")) == param) {
return true;
}
/* doesn't seem to work always: in some cases (especially for 'self' parameters)
* tmap:in is present, but tmap:in:next is not and so this code skips all the parameters
*/
//p = Getattr(p, "tmap:in") ? Getattr(p, "tmap:in:next") : nextSibling(p);
p = nextSibling(p);
}
Delete(plist);
return false;
}
std::string JavaDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
std::string translatedComment;
if (doxygenEntity.isLeaf) {
return translatedComment;
}
for (DoxygenEntityListIt p = doxygenEntity.entityList.begin(); p != doxygenEntity.entityList.end(); p++) {
translateEntity(*p, translatedComment);
translateSubtree(*p);
}
return translatedComment;
}
/**
* Checks if a handler for the given tag exists, and calls it.
*/
void JavaDocConverter::translateEntity(DoxygenEntity &tag, std::string &translatedComment) {
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
it = tagHandlers.find(tag.typeOfEntity);
if (it != tagHandlers.end()) {
(this->*(it->second.first))(tag, translatedComment, it->second.second);
} else {
// do NOT print warning, since there are many tags, which are not
// translatable - many warnings hide important ones
// addError(WARN_DOXYGEN_COMMAND_ERROR, "Unknown doxygen or HTML tag: " + tag.typeOfEntity);
}
}
void JavaDocConverter::handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
translatedComment += "<a id=\"" + translateSubtree(tag) + "\"></a>";
}
void JavaDocConverter::handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
if (tag.entityList.size()) { // do not include empty tags
std::string tagData = translateSubtree(tag);
// wrap the thing, ignoring whitespace
size_t wsPos = tagData.find_last_not_of("\n\t ");
if (wsPos != std::string::npos)
translatedComment += "<" + arg + ">" + tagData.substr(0, wsPos + 1) + "</" + arg + ">" + tagData.substr(wsPos + 1);
else
translatedComment += "<" + arg + ">" + translateSubtree(tag) + "</" + arg + "> ";
}
}
void JavaDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end html tag, for example "</ul>
translatedComment += "</" + arg.substr(1) + ">";
} else {
translatedComment += arg + htmlTagArgs + ">";
}
}
void JavaDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, std::string &arg) {
// html entities can be preserved for Java
translatedComment += arg + ';';
}
void JavaDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, std::string &) {
// <br> tag is added, because otherwise to much text is joined
// into same paragraph by javadoc. For example, doxy list:
// - item one
// - item two
// becomes one paragraph with surrounding text without newlines.
// This way we get to many empty lines in javadoc output, but this
// is still better than joined lines. Possibility for improvements
// exists.
translatedComment += "<br>\n * ";
}
void JavaDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
// escape it if we need to, else just print
if (arg.size())
translatedComment += arg;
else
translatedComment += tag.typeOfEntity;
}
// handles tags which are the same in Doxygen and Javadoc.
void JavaDocConverter::handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
if (arg.size())
tag.typeOfEntity = arg;
translatedComment += formatCommand(std::string("@" + tag.typeOfEntity + " " + translateSubtree(tag)), 2);
}
void JavaDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
translatedComment += formatCommand(translateSubtree(tag), 0);
}
void JavaDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
translatedComment += tag.data;
// if (tag.data.size() && tag.data[tag.data.size()-1] != ' ')
// translatedComment += " ";
}
void JavaDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
translatedComment += arg + " ";
for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
translatedComment += it->data;
}
}
void JavaDocConverter::handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
std::string dummy;
translatedComment += "{@" + arg + " ";
handleParagraph(tag, translatedComment, dummy);
translatedComment += "}";
}
void JavaDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
std::string dummy;
translatedComment += arg;
if (tag.entityList.size()) {
translatedComment += tag.entityList.begin()->data;
tag.entityList.pop_front();
translatedComment += " {" + translateSubtree(tag) + "}";
}
}
void JavaDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
std::string dummy;
translatedComment += formatCommand(arg, 0);
handleParagraph(tag, translatedComment, dummy);
}
void JavaDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
if (tag.entityList.size() < 2)
return;
std::string file;
std::string title;
std::list<DoxygenEntity>::iterator it = tag.entityList.begin();
if (it->data != "html")
return;
it++;
file = it->data;
it++;
if (it != tag.entityList.end())
title = it->data;
translatedComment += "<img src=" + file;
if (title.size())
translatedComment += " alt=" + title;
// the size indication is supported for Latex only in Doxygen, see manual
translatedComment += "/>";
}
void JavaDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
std::string dummy;
translatedComment += "<p";
if (tag.entityList.size()) {
translatedComment += " alt=\"" + tag.entityList.begin()->data + "\"";
translatedComment += ">";
tag.entityList.pop_front();
handleParagraph(tag, translatedComment, dummy);
}
translatedComment += "</p>";
}
void JavaDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
std::string dummy;
if (!tag.entityList.size())
return;
if (!paramExists(tag.entityList.begin()->data))
return;
translatedComment += "@param ";
translatedComment += tag.entityList.begin()->data;
tag.entityList.pop_front();
handleParagraph(tag, translatedComment, dummy);
}
void JavaDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
std::string dummy;
if (!tag.entityList.size())
return;
// we translate to link, although \page is not supported in Java, but
// reader at least knows what to look at. Also for \anchor tag on the same
// page this link works.
string anchor = tag.entityList.begin()->data;
tag.entityList.pop_front();
string anchorText = anchor;
if (!tag.entityList.empty()) {
anchorText = tag.entityList.begin()->data;
}
translatedComment += "<a href=\"#" + anchor + "\">" + anchorText + "</a>";
}
string JavaDocConverter::convertLink(string linkObject) {
if (GetFlag(currentNode, "feature:doxygen:nolinktranslate"))
return linkObject;
// find the params in function in linkObject (if any)
size_t lbracePos = linkObject.find('(', 0);
size_t rbracePos = linkObject.find(')', 0);
if (lbracePos == string::npos || rbracePos == string::npos || lbracePos >= rbracePos)
return "";
string paramsStr = linkObject.substr(lbracePos + 1,
rbracePos - lbracePos - 1);
// strip the params, to fill them later
string additionalObject = linkObject.substr(rbracePos + 1, string::npos);
linkObject = linkObject.substr(0, lbracePos);
// find all the params
vector<string> params;
size_t lastPos = 0, commaPos = 0;
while (true) {
commaPos = paramsStr.find(',', lastPos);
if (commaPos == string::npos)
commaPos = paramsStr.size();
string param = paramsStr.substr(lastPos, commaPos - lastPos);
// if any param type is empty, we are failed
if (!param.size())
return "";
params.push_back(param);
lastPos = commaPos + 1;
if (lastPos >= paramsStr.size())
break;
}
linkObject += "(";
for (size_t i = 0; i < params.size(); i++) {
// translate c/c++ type string to swig's type
// i e 'int **arr[100][10]' -> 'a(100).a(10).p.p.int'
// also converting arrays to pointers
string paramStr = params[i];
String *swigType = NewString("");
// handle const qualifier
if (paramStr.find("const") != string::npos)
SwigType_add_qualifier(swigType, "const");
// handle pointers, references and arrays
for (int j = (int)params[i].size() - 1; j >= 0; j--) {
// skip all the [...] blocks, write 'p.' for every of it
if (paramStr[j] == ']') {
while (j >= 0 && paramStr[j] != '[')
j--;
// no closing brace
if (j < 0)
return "";
SwigType_add_pointer(swigType);
continue;
} else if (paramStr[j] == '*')
SwigType_add_pointer(swigType);
else if (paramStr[j] == '&')
SwigType_add_reference(swigType);
else if (isalnum(paramStr[j])) {
size_t typeNameStart = paramStr.find_last_of(' ', j + 1);
if (typeNameStart == string::npos)
typeNameStart = 0;
else
typeNameStart++;
Append(swigType, paramStr.substr(typeNameStart, j - typeNameStart + 1).c_str());
break;
}
}
// make dummy param list, to lookup typemaps for it
Parm *dummyParam = NewParm(swigType, "", 0);
Swig_typemap_attach_parms("jstype", dummyParam, NULL);
Language::instance()->replaceSpecialVariables(0, Getattr(dummyParam, "tmap:jstype"), dummyParam);
//Swig_print(dummyParam, 1);
linkObject += Char(Getattr(dummyParam, "tmap:jstype"));
if (i != params.size() - 1)
linkObject += ",";
Delete(dummyParam);
Delete(swigType);
}
linkObject += ")";
return linkObject + additionalObject;
}
void JavaDocConverter::handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
std::string dummy;
if (!tag.entityList.size())
return;
string linkObject = convertLink(tag.entityList.begin()->data);
if (!linkObject.size())
linkObject = tag.entityList.begin()->data;
tag.entityList.pop_front();
translatedComment += "{@link ";
translatedComment += linkObject + " ";
handleParagraph(tag, translatedComment, dummy);
translatedComment += "}";
}
void JavaDocConverter::handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
std::string dummy;
if (!tag.entityList.size())
return;
// tag.entity list contains contents of the @see paragraph. It should contain
// one link (references) to method with or without parameters. Doxygen supports
// arbitrary text and types mixed, but this feature is not supported here.
// :: or # may be used as a separator between class name and method name.
list<DoxygenEntity>::iterator it;
string methodRef;
for (it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
if (it->typeOfEntity == "plainstd::endl") {
// handleNewLine(*it, translatedComment, dummy);
continue;
}
// restore entities which may be used in C++ type declaration
if (it->typeOfEntity == "&amp") {
methodRef += '&';
} else if (it->typeOfEntity == "&lt") {
methodRef += '<';
} else if (it->typeOfEntity == "&gt") {
methodRef += '>';
} else {
methodRef += it->data;
}
}
// replace :: with #, but only if it appears before left brace
size_t lbrace = methodRef.find('(');
size_t dblColon = methodRef.find("::");
if (dblColon < lbrace) {
methodRef = methodRef.substr(0, dblColon) + '#' + methodRef.substr(dblColon + 2);
}
translatedComment += "@see ";
string linkObject = convertLink(methodRef);
if (!linkObject.size()) {
linkObject = methodRef;
}
translatedComment += linkObject;
}
/* This function moves all line endings at the end of child entities
* out of the child entities to the parent.
* For example, entity tree:
-root
|-param
|-paramText
|-endline
should be turned to
-root
|-param
|-paramText
|-endline
*
*/
int JavaDocConverter::shiftEndlinesUpTree(DoxygenEntity &root, int level) {
DoxygenEntityListIt it = root.entityList.begin();
while (it != root.entityList.end()) {
// remove line endings
int ret = shiftEndlinesUpTree(*it, level + 1);
// insert them after this element
it++;
for (int i = 0; i < ret; i++) {
root.entityList.insert(it, DoxygenEntity("plainstd::endl"));
}
}
// continue only if we are not root
if (!level) {
return 0;
}
int removedCount = 0;
while (!root.entityList.empty()
&& root.entityList.rbegin()->typeOfEntity == "plainstd::endl") {
root.entityList.pop_back();
removedCount++;
}
return removedCount;
}
/**
* This makes sure that all comment lines contain '*'. It is not mandatory in doxygen,
* but highly recommended for Javadoc. '*' in empty lines are indented according
* to indentation of the first line. Indentation of non-empty lines is not
* changed - garbage in garbage out.
*/
std::string JavaDocConverter::indentAndInsertAsterisks(const string &doc) {
size_t idx = doc.find('\n');
size_t indent = 0;
bool singleLineComment = idx == string::npos;
// Detect indentation.
// The first line in comment is the one after '/**', which may be
// spaces and '\n' or the text. In any case it is not suitable to detect
// indentation, so we have to skip the first '\n'.
// However, if there is just one line, then use that line to detect indentation.
if (idx != string::npos) {
size_t nonspaceIdx = doc.find_first_not_of(" \t", idx + 1);
if (nonspaceIdx != string::npos) {
indent = nonspaceIdx - idx;
}
}
if (indent == 0) {
// we can't indent the first line less than 0
indent = 1;
}
// Create the first line of Javadoc comment.
string indentStr(indent - 1, ' ');
string translatedStr = indentStr + "/**";
if (indent > 1) {
// remove the first space, so that '*' will be aligned
translatedStr = translatedStr.substr(1);
}
translatedStr += doc;
// insert '*' before each comment line, if it does not have it
idx = translatedStr.find('\n');
while (idx != string::npos) {
size_t nonspaceIdx = translatedStr.find_first_not_of(" \t", idx + 1);
if (nonspaceIdx != string::npos && translatedStr[nonspaceIdx] != '*') {
// line without '*' found - is it empty?
if (translatedStr[nonspaceIdx] != '\n') {
// add '* ' to each line without it
translatedStr = translatedStr.substr(0, nonspaceIdx) + "* " + translatedStr.substr(nonspaceIdx);
//printf(translatedStr.c_str());
} else {
// we found empty line, replace it with indented '*'
translatedStr = translatedStr.substr(0, idx + 1) + indentStr + "* " + translatedStr.substr(nonspaceIdx);
}
}
idx = translatedStr.find('\n', nonspaceIdx);
}
// Add the last comment line properly indented
size_t nonspaceEndIdx = translatedStr.find_last_not_of(" \t");
if (nonspaceEndIdx != string::npos) {
if (translatedStr[nonspaceEndIdx] != '\n') {
if (!singleLineComment)
translatedStr += '\n';
} else {
// remove trailing spaces
translatedStr = translatedStr.substr(0, nonspaceEndIdx + 1);
}
}
translatedStr += indentStr + "*/\n";
return translatedStr;
}
String *JavaDocConverter::makeDocumentation(Node *node) {
String *documentation = getDoxygenComment(node);
if (documentation == NULL) {
return NewString("");
}
if (GetFlag(node, "feature:doxygen:notranslate")) {
string doc = Char(documentation);
string translatedStr = indentAndInsertAsterisks(doc);
return NewString(translatedStr.c_str());
}
DoxygenEntityList entityList = parser.createTree(node, documentation);
// entityList.sort(CompareDoxygenEntities()); sorting currently not used,
if (m_flags & debug_translator) {
std::cout << "---RESORTED LIST---" << std::endl;
printTree(entityList);
}
// store the current node
// (currently just to handle params)
currentNode = node;
std::string javaDocString = "/**\n * ";
DoxygenEntity root("root", entityList);
shiftEndlinesUpTree(root);
// strip line endings at the beginning
while (!root.entityList.empty()
&& root.entityList.begin()->typeOfEntity == "plainstd::endl") {
root.entityList.pop_front();
}
// and at the end
while (!root.entityList.empty()
&& root.entityList.rbegin()->typeOfEntity == "plainstd::endl") {
root.entityList.pop_back();
}
javaDocString += translateSubtree(root);
javaDocString += "\n */\n";
if (m_flags & debug_translator) {
std::cout << "\n---RESULT IN JAVADOC---" << std::endl;
std::cout << javaDocString;
}
return NewString(javaDocString.c_str());
}
void JavaDocConverter::addError(int warningType, const std::string &message) {
Swig_warning(warningType, "", 0, "Doxygen parser warning: %s. \n", message.c_str());
}

169
Source/Doxygen/javadoc.h Normal file
View file

@ -0,0 +1,169 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* javadoc.h
*
* Module to return documentation for nodes formatted for JavaDoc
* ----------------------------------------------------------------------------- */
#ifndef JAVADOCCONVERTER_H_
#define JAVADOCCONVERTER_H_
#include "doxytranslator.h"
#include <map>
/*
* A class to translate doxygen comments into JavaDoc style comments.
*/
class JavaDocConverter : public DoxygenTranslator {
public:
JavaDocConverter(int flags = 0);
String *makeDocumentation(Node *node);
protected:
/*
* Used to properly format JavaDoc-style command
*/
std::string formatCommand(std::string unformattedLine, int indent);
/*
* Translate every entity in a tree.
*/
std::string translateSubtree(DoxygenEntity &doxygenEntity);
/*
* Translate one entity with the appropriate handler, according
* to the tagHandlers
*/
void translateEntity(DoxygenEntity &tag, std::string &translatedComment);
/*
* Fix all endlines location, etc
*/
int shiftEndlinesUpTree(DoxygenEntity &root, int level = 0);
/*
* Convert params in link-objects and references
*/
std::string convertLink(std::string linkObject);
/*
* Typedef for the function that handles one tag
* arg - some string argument to easily pass it through lookup table
*/
typedef void (JavaDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/**
* Copies verbatim args of the tag to output, used for commands like \f$, ...
*/
void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/** Creates anchor link. */
void handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Wrap the command data with the html tag
* arg - html tag, with no braces
*/
void handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/* Handles HTML tags recognized by Doxygen, like <A ...>, <ul>, <table>, ... */
void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/* Handles HTML entities recognized by Doxygen, like &lt;, &copy;, ... */
void handleHtmlEntity(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Just prints new line
*/
void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Print the name of tag to the output, used for escape-commands
* arg - html-escaped variant, if not provided the command data is used
*/
void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Do not translate and print as-is
* arg - the new tag name, if it needs to be renamed
*/
void handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Print only the content and strip original tag
*/
void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Print only data part of code
*/
void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Print extended Javadoc command, like {@code ...} or {@literal ...}
* arg - command name
*/
void handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Print the if-elseif-else-endif section
*/
void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Prints the specified message, than the contents of the tag
* arg - message
*/
void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Insert <img src=... /> tag if the 'format' field is specified as 'html'
*/
void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Insert <p alt='title'>...</p>
*/
void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Insert \@param command, if it is really a function param
*/
void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Writes link for \ref tag.
*/
void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &);
/*
* Insert {@link...} command, and handle all the <link-object>s correctly
* (like converting types of params, etc)
*/
void handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
/*
* Insert @see command, and handle all the <link-object>s correctly
* (like converting types of params, etc)
*/
void handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
private:
Node *currentNode;
// this contains the handler pointer and one string argument
static std::map<std::string, std::pair<tagHandler, std::string> > tagHandlers;
void fillStaticTables();
bool paramExists(std::string param);
std::string indentAndInsertAsterisks(const std::string &doc);
void addError(int warningType, const std::string &message);
};
#endif

911
Source/Doxygen/pydoc.cxx Normal file
View file

@ -0,0 +1,911 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* pydoc.cxx
*
* Module to return documentation for nodes formatted for PyDoc
* ----------------------------------------------------------------------------- */
#include "pydoc.h"
#include "doxyparser.h"
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
#include "swigmod.h"
// define static tables, they are filled in PyDocConverter's constructor
PyDocConverter::TagHandlersMap PyDocConverter::tagHandlers;
std::map<std::string, std::string> PyDocConverter::sectionTitles;
using std::string;
// Helper class increasing the provided indent string in its ctor and decreasing
// it in its dtor.
class IndentGuard {
public:
// One indent level.
static const char *Level() {
return " ";
}
// Default ctor doesn't do anything and prevents the dtor from doing anything// too and should only be used when the guard needs to be initialized// conditionally as Init() can then be called after checking some condition.// Otherwise, prefer to use the non default ctor below.
IndentGuard() {
m_initialized = false;
}
// Ctor takes the output to determine the current indent and to remove the
// extra indent added to it in the dtor and the variable containing the indent
// to use, which must be used after every new line by the code actually
// updating the output.
IndentGuard(string &output, string &indent) {
Init(output, indent);
}
// Really initializes the object created using the default ctor.
void Init(string &output, string &indent) {
m_output = &output;
m_indent = &indent;
const string::size_type lastNonSpace = m_output->find_last_not_of(' ');
if (lastNonSpace == string::npos) {
m_firstLineIndent = m_output->length();
} else if ((*m_output)[lastNonSpace] == '\n') {
m_firstLineIndent = m_output->length() - (lastNonSpace + 1);
} else {
m_firstLineIndent = 0;
}
// Notice that the indent doesn't include the first line indent because it's
// implicit, i.e. it is present in the input and so is copied into the
// output anyhow.
*m_indent = Level();
m_initialized = true;
}
// Get the indent for the first line of the paragraph, which is smaller than
// the indent for the subsequent lines.
string getFirstLineIndent() const {
return string(m_firstLineIndent, ' ');
}
~IndentGuard() {
if (!m_initialized)
return;
m_indent->clear();
// Get rid of possible remaining extra indent, e.g. if there were any trailing
// new lines: we shouldn't add the extra indent level to whatever follows
// this paragraph.
static const size_t lenIndentLevel = strlen(Level());
if (m_output->length() > lenIndentLevel) {
const size_t start = m_output->length() - lenIndentLevel;
if (m_output->compare(start, string::npos, Level()) == 0)
m_output->erase(start);
}
}
private:
string *m_output;
string *m_indent;
string::size_type m_firstLineIndent;
bool m_initialized;
IndentGuard(const IndentGuard &);
IndentGuard &operator=(const IndentGuard &);
};
// Return the indent of the given multiline string, i.e. the maximal number of
// spaces present in the beginning of all its non-empty lines.
static size_t determineIndent(const string &s) {
size_t minIndent = static_cast<size_t>(-1);
for (size_t lineStart = 0; lineStart < s.length();) {
const size_t lineEnd = s.find('\n', lineStart);
const size_t firstNonSpace = s.find_first_not_of(' ', lineStart);
// If inequality doesn't hold, it means that this line contains only spaces
// (notice that this works whether lineEnd is valid or string::npos), in
// which case it doesn't matter when determining the indent.
if (firstNonSpace < lineEnd) {
// Here we can be sure firstNonSpace != string::npos.
const size_t lineIndent = firstNonSpace - lineStart;
if (lineIndent < minIndent)
minIndent = lineIndent;
}
if (lineEnd == string::npos)
break;
lineStart = lineEnd + 1;
}
return minIndent;
}
static void trimWhitespace(string &s) {
const string::size_type lastNonSpace = s.find_last_not_of(' ');
if (lastNonSpace == string::npos)
s.clear();
else
s.erase(lastNonSpace + 1);
}
// Erase the first character in the string if it is a newline
static void eraseLeadingNewLine(string &s) {
if (!s.empty() && s[0] == '\n')
s.erase(s.begin());
}
// Erase the last character in the string if it is a newline
static void eraseTrailingNewLine(string &s) {
if (!s.empty() && s[s.size() - 1] == '\n')
s.erase(s.size() - 1);
}
// Check the generated docstring line by line and make sure that any
// code and verbatim blocks have an empty line preceding them, which
// is necessary for Sphinx. Additionally, this strips any empty lines
// appearing at the beginning of the docstring.
static string padCodeAndVerbatimBlocks(const string &docString) {
std::string result;
std::istringstream iss(docString);
// Initialize to false because there is no previous line yet
bool lastLineWasNonBlank = false;
for (string line; std::getline(iss, line); result += line) {
if (!result.empty()) {
// Terminate the previous line
result += '\n';
}
const size_t pos = line.find_first_not_of(" \t");
if (pos == string::npos) {
lastLineWasNonBlank = false;
} else {
if (lastLineWasNonBlank &&
(line.compare(pos, 13, ".. code-block") == 0 ||
line.compare(pos, 7, ".. math") == 0)) {
// Must separate code or math blocks from the previous line
result += '\n';
}
lastLineWasNonBlank = true;
}
}
return result;
}
/* static */
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) {
return make_pair(handler, std::string());
}
/* static */
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler, const char *arg) {
return make_pair(handler, arg);
}
void PyDocConverter::fillStaticTables() {
if (tagHandlers.size()) // fill only once
return;
// table of section titles, they are printed only once
// for each group of specified doxygen commands
sectionTitles["author"] = "Author: ";
sectionTitles["authors"] = "Authors: ";
sectionTitles["copyright"] = "Copyright: ";
sectionTitles["deprecated"] = "Deprecated: ";
sectionTitles["example"] = "Example: ";
sectionTitles["note"] = "Notes: ";
sectionTitles["remark"] = "Remarks: ";
sectionTitles["remarks"] = "Remarks: ";
sectionTitles["warning"] = "Warning: ";
// sectionTitles["sa"] = "See also: ";
// sectionTitles["see"] = "See also: ";
sectionTitles["since"] = "Since: ";
sectionTitles["todo"] = "TODO: ";
sectionTitles["version"] = "Version: ";
tagHandlers["a"] = make_handler(&PyDocConverter::handleTagWrap, "*");
tagHandlers["b"] = make_handler(&PyDocConverter::handleTagWrap, "**");
// \c command is translated as single quotes around next word
tagHandlers["c"] = make_handler(&PyDocConverter::handleTagWrap, "``");
tagHandlers["cite"] = make_handler(&PyDocConverter::handleTagWrap, "'");
tagHandlers["e"] = make_handler(&PyDocConverter::handleTagWrap, "*");
// these commands insert just a single char, some of them need to be escaped
tagHandlers["$"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["@"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["\\"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["<"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers[">"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["&"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["#"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["%"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["~"] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["\""] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["."] = make_handler(&PyDocConverter::handleTagChar);
tagHandlers["::"] = make_handler(&PyDocConverter::handleTagChar);
// these commands are stripped out, and only their content is printed
tagHandlers["attention"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["author"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["authors"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["brief"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["bug"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["code"] = make_handler(&PyDocConverter::handleCode);
tagHandlers["copyright"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["date"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["deprecated"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["details"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["em"] = make_handler(&PyDocConverter::handleParagraph, " ");
tagHandlers["example"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&PyDocConverter::handleTagException);
tagHandlers["htmlonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["invariant"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["latexonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["link"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["manonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["note"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["p"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["partofdescription"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["rtfonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["remark"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["remarks"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["sa"] = make_handler(&PyDocConverter::handleTagMessage, "See also: ");
tagHandlers["see"] = make_handler(&PyDocConverter::handleTagMessage, "See also: ");
tagHandlers["since"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["short"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["todo"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["version"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["verbatim"] = make_handler(&PyDocConverter::handleVerbatimBlock);
tagHandlers["warning"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["xmlonly"] = make_handler(&PyDocConverter::handleParagraph);
// these commands have special handlers
tagHandlers["arg"] = make_handler(&PyDocConverter::handleTagMessage, "* ");
tagHandlers["cond"] = make_handler(&PyDocConverter::handleTagMessage, "Conditional comment: ");
tagHandlers["else"] = make_handler(&PyDocConverter::handleTagIf, "Else: ");
tagHandlers["elseif"] = make_handler(&PyDocConverter::handleTagIf, "Else if: ");
tagHandlers["endcond"] = make_handler(&PyDocConverter::handleTagMessage, "End of conditional comment.");
tagHandlers["if"] = make_handler(&PyDocConverter::handleTagIf, "If: ");
tagHandlers["ifnot"] = make_handler(&PyDocConverter::handleTagIf, "If not: ");
tagHandlers["image"] = make_handler(&PyDocConverter::handleTagImage);
tagHandlers["li"] = make_handler(&PyDocConverter::handleTagMessage, "* ");
tagHandlers["overload"] = make_handler(&PyDocConverter::handleTagMessage,
"This is an overloaded member function, provided for"
" convenience.\nIt differs from the above function only in what" " argument(s) it accepts.");
tagHandlers["par"] = make_handler(&PyDocConverter::handleTagPar);
tagHandlers["param"] = tagHandlers["tparam"] = make_handler(&PyDocConverter::handleTagParam);
tagHandlers["ref"] = make_handler(&PyDocConverter::handleTagRef);
tagHandlers["result"] = tagHandlers["return"] = tagHandlers["returns"] = make_handler(&PyDocConverter::handleTagReturn);
// this command just prints it's contents
// (it is internal command of swig's parser, contains plain text)
tagHandlers["plainstd::string"] = make_handler(&PyDocConverter::handlePlainString);
tagHandlers["plainstd::endl"] = make_handler(&PyDocConverter::handleNewLine);
tagHandlers["n"] = make_handler(&PyDocConverter::handleNewLine);
// \f commands output literal Latex formula, which is still better than nothing.
tagHandlers["f$"] = tagHandlers["f["] = tagHandlers["f{"] = make_handler(&PyDocConverter::handleMath);
// HTML tags
tagHandlers["<a"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_A);
tagHandlers["<b"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
tagHandlers["<blockquote"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_A, "Quote: ");
tagHandlers["<body"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<br"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "\n");
// there is no formatting for this tag as it was deprecated in HTML 4.01 and
// not used in HTML 5
tagHandlers["<center"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<caption"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<code"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "``");
tagHandlers["<dl"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<dd"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
tagHandlers["<dt"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<dfn"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<div"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<em"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
tagHandlers["<form"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<hr"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "--------------------------------------------------------------------\n");
tagHandlers["<h1"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "# ");
tagHandlers["<h2"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "## ");
tagHandlers["<h3"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "### ");
tagHandlers["<i"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "*");
tagHandlers["<input"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<img"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "Image:");
tagHandlers["<li"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "* ");
tagHandlers["<meta"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<multicol"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<ol"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<p"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "\n");
tagHandlers["<pre"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<small"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<span"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "'");
tagHandlers["<strong"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
// make a space between text and super/sub script.
tagHandlers["<sub"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
tagHandlers["<sup"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
tagHandlers["<table"] = make_handler(&PyDocConverter::handleDoxyHtmlTagNoParam);
tagHandlers["<td"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_td);
tagHandlers["<th"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_th);
tagHandlers["<tr"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_tr);
tagHandlers["<tt"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<kbd"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<ul"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
tagHandlers["<var"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "*");
// HTML entities
tagHandlers["&copy"] = make_handler(&PyDocConverter::handleHtmlEntity, "(C)");
tagHandlers["&trade"] = make_handler(&PyDocConverter::handleHtmlEntity, " TM");
tagHandlers["&reg"] = make_handler(&PyDocConverter::handleHtmlEntity, "(R)");
tagHandlers["&lt"] = make_handler(&PyDocConverter::handleHtmlEntity, "<");
tagHandlers["&gt"] = make_handler(&PyDocConverter::handleHtmlEntity, ">");
tagHandlers["&amp"] = make_handler(&PyDocConverter::handleHtmlEntity, "&");
tagHandlers["&apos"] = make_handler(&PyDocConverter::handleHtmlEntity, "'");
tagHandlers["&quot"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
tagHandlers["&lsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "`");
tagHandlers["&rsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "'");
tagHandlers["&ldquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
tagHandlers["&rdquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
tagHandlers["&ndash"] = make_handler(&PyDocConverter::handleHtmlEntity, "-");
tagHandlers["&mdash"] = make_handler(&PyDocConverter::handleHtmlEntity, "--");
tagHandlers["&nbsp"] = make_handler(&PyDocConverter::handleHtmlEntity, " ");
tagHandlers["&times"] = make_handler(&PyDocConverter::handleHtmlEntity, "x");
tagHandlers["&minus"] = make_handler(&PyDocConverter::handleHtmlEntity, "-");
tagHandlers["&sdot"] = make_handler(&PyDocConverter::handleHtmlEntity, ".");
tagHandlers["&sim"] = make_handler(&PyDocConverter::handleHtmlEntity, "~");
tagHandlers["&le"] = make_handler(&PyDocConverter::handleHtmlEntity, "<=");
tagHandlers["&ge"] = make_handler(&PyDocConverter::handleHtmlEntity, ">=");
tagHandlers["&larr"] = make_handler(&PyDocConverter::handleHtmlEntity, "<--");
tagHandlers["&rarr"] = make_handler(&PyDocConverter::handleHtmlEntity, "-->");
}
PyDocConverter::PyDocConverter(int flags):
DoxygenTranslator(flags), m_tableLineLen(0), m_prevRowIsTH(false) {
fillStaticTables();
}
// Return the type as it should appear in the output documentation.
static std::string getPyDocType(Node *n, const_String_or_char_ptr lname = "") {
std::string type;
String *s = Swig_typemap_lookup("doctype", n, lname, 0);
if (!s) {
if (String *t = Getattr(n, "type"))
s = SwigType_str(t, "");
}
if (!s)
return type;
if (Language::classLookup(s)) {
// In Python C++ namespaces are flattened, so remove all but last component
// of the name.
String *const last = Swig_scopename_last(s);
// We are not actually sure whether it's a documented class or not, but
// there doesn't seem to be any harm in making it a reference if it isn't,
// while there is a lot of benefit in having a hyperlink if it is.
type = ":py:class:`";
type += Char(last);
type += "`";
Delete(last);
} else {
type = Char(s);
}
Delete(s);
return type;
}
std::string PyDocConverter::getParamType(std::string param) {
std::string type;
ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
for (Parm *p = plist; p; p = nextSibling(p)) {
String *pname = Getattr(p, "name");
if (Char(pname) != param)
continue;
type = getPyDocType(p, pname);
break;
}
Delete(plist);
return type;
}
std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
std::string translatedComment;
if (doxygenEntity.isLeaf)
return translatedComment;
std::string currentSection;
std::list<DoxygenEntity>::iterator p = doxygenEntity.entityList.begin();
while (p != doxygenEntity.entityList.end()) {
std::map<std::string, std::string>::iterator it;
it = sectionTitles.find(p->typeOfEntity);
if (it != sectionTitles.end()) {
if (it->second != currentSection) {
currentSection = it->second;
translatedComment += currentSection;
}
}
translateEntity(*p, translatedComment);
translateSubtree(*p);
p++;
}
return translatedComment;
}
void PyDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) {
// check if we have needed handler and call it
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
it = tagHandlers.find(doxyEntity.typeOfEntity);
if (it != tagHandlers.end())
(this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second);
}
void PyDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
translatedComment += translateSubtree(tag);
}
void PyDocConverter::handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
string verb = translateSubtree(tag);
eraseLeadingNewLine(verb);
// Remove the last newline to prevent doubling the newline already present after \endverbatim
trimWhitespace(verb); // Needed to catch trailing newline below
eraseTrailingNewLine(verb);
translatedComment += verb;
}
void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
IndentGuard indent;
// Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones.
const bool inlineFormula = tag.typeOfEntity == "f$";
string formulaNL;
if (inlineFormula) {
translatedComment += ":math:`";
} else {
indent.Init(translatedComment, m_indent);
trimWhitespace(translatedComment);
const string formulaIndent = indent.getFirstLineIndent();
translatedComment += formulaIndent;
translatedComment += ".. math::\n";
formulaNL = '\n';
formulaNL += formulaIndent;
formulaNL += m_indent;
translatedComment += formulaNL;
}
std::string formula;
handleTagVerbatim(tag, formula, arg);
// It is important to ensure that we have no spaces around the inline math
// contents, so strip them.
const size_t start = formula.find_first_not_of(" \t\n");
const size_t end = formula.find_last_not_of(" \t\n");
if (start != std::string::npos) {
for (size_t n = start; n <= end; n++) {
if (formula[n] == '\n') {
// New lines must be suppressed in inline maths and indented in the block ones.
if (!inlineFormula)
translatedComment += formulaNL;
} else {
// Just copy everything else.
translatedComment += formula[n];
}
}
}
if (inlineFormula) {
translatedComment += "`";
}
}
void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
IndentGuard indent(translatedComment, m_indent);
trimWhitespace(translatedComment);
// Use the current indent for the code-block line itself.
translatedComment += indent.getFirstLineIndent();
// Go out on a limb and assume that examples in the C or C++ sources use C++.
// In the worst case, we'll highlight C code using C++ syntax which is not a
// big deal (TODO: handle Doxygen code command language argument).
translatedComment += ".. code-block:: c++\n\n";
// Specify the level of extra indentation that will be used for
// subsequent lines within the code block. Note that the correct
// "starting indentation" is already present in the input, so we
// only need to add the desired code block indentation.
string codeIndent = m_indent;
std::string code;
handleTagVerbatim(tag, code, arg);
// Try and remove leading newline, which is present for block \code
// command:
eraseLeadingNewLine(code);
translatedComment += codeIndent;
for (size_t n = 0; n < code.length(); n++) {
if (code[n] == '\n') {
// Don't leave trailing white space, this results in PEP8 validation
// errors in Python code (which are performed by our own unit tests).
trimWhitespace(translatedComment);
translatedComment += '\n';
// Ensure that we indent all the lines by the code indent.
translatedComment += codeIndent;
} else {
// Just copy everything else.
translatedComment += code[n];
}
}
trimWhitespace(translatedComment);
// For block commands, the translator adds the newline after
// \endcode, so try and compensate by removing the last newline from
// the code text:
eraseTrailingNewLine(translatedComment);
}
void PyDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
translatedComment += tag.data;
}
void PyDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
translatedComment += arg;
for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
translatedComment += it->data;
}
}
void PyDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
translatedComment += arg;
handleParagraph(tag, translatedComment);
}
void PyDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
translatedComment += tag.typeOfEntity;
}
void PyDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
translatedComment += arg;
if (tag.entityList.size()) {
translatedComment += tag.entityList.begin()->data;
tag.entityList.pop_front();
translatedComment += " {" + translateSubtree(tag) + "}";
}
}
void PyDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
translatedComment += "Title: ";
if (tag.entityList.size())
translatedComment += tag.entityList.begin()->data;
tag.entityList.pop_front();
handleParagraph(tag, translatedComment);
}
void PyDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
if (tag.entityList.size() < 2)
return;
tag.entityList.pop_front();
translatedComment += "Image: ";
translatedComment += tag.entityList.begin()->data;
tag.entityList.pop_front();
if (tag.entityList.size())
translatedComment += "(" + tag.entityList.begin()->data + ")";
}
void PyDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
if (tag.entityList.size() < 2)
return;
IndentGuard indent(translatedComment, m_indent);
DoxygenEntity paramNameEntity = *tag.entityList.begin();
tag.entityList.pop_front();
const std::string &paramName = paramNameEntity.data;
const std::string paramType = getParamType(paramName);
if (!paramType.empty()) {
translatedComment += ":type " + paramName + ": " + paramType + "\n";
translatedComment += indent.getFirstLineIndent();
}
translatedComment += ":param " + paramName + ":";
handleParagraph(tag, translatedComment);
}
void PyDocConverter::handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
IndentGuard indent(translatedComment, m_indent);
const std::string pytype = getPyDocType(currentNode);
if (!pytype.empty()) {
translatedComment += ":rtype: ";
translatedComment += pytype;
translatedComment += "\n";
translatedComment += indent.getFirstLineIndent();
}
translatedComment += ":return: ";
handleParagraph(tag, translatedComment);
}
void PyDocConverter::handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
IndentGuard indent(translatedComment, m_indent);
translatedComment += ":raises: ";
handleParagraph(tag, translatedComment);
}
void PyDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
if (!tag.entityList.size())
return;
string anchor = tag.entityList.begin()->data;
tag.entityList.pop_front();
string anchorText = anchor;
if (!tag.entityList.empty()) {
anchorText = tag.entityList.begin()->data;
}
translatedComment += "'" + anchorText + "'";
}
void PyDocConverter::handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
if (tag.entityList.size()) { // do not include empty tags
std::string tagData = translateSubtree(tag);
// wrap the thing, ignoring whitespace
size_t wsPos = tagData.find_last_not_of("\n\t ");
if (wsPos != std::string::npos && wsPos != tagData.size() - 1)
translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1);
else
translatedComment += arg + tagData + arg;
}
}
void PyDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end html tag, for example "</ul>
// translatedComment += "</" + arg.substr(1) + ">";
} else {
translatedComment += arg + htmlTagArgs;
}
}
void PyDocConverter::handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end html tag, for example "</ul>
} else {
translatedComment += arg;
}
}
void PyDocConverter::handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end html tag, "</a>
translatedComment += " (" + m_url + ')';
m_url.clear();
} else {
m_url.clear();
size_t pos = htmlTagArgs.find('=');
if (pos != string::npos) {
m_url = htmlTagArgs.substr(pos + 1);
}
translatedComment += arg;
}
}
void PyDocConverter::handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end html tag, for example "</em>
translatedComment += arg;
} else {
translatedComment += arg;
}
}
void PyDocConverter::handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
std::string htmlTagArgs = tag.data;
size_t nlPos = translatedComment.rfind('\n');
if (htmlTagArgs == "/") {
// end tag, </tr> appends vertical table line '|'
translatedComment += '|';
if (nlPos != string::npos) {
size_t startOfTableLinePos = translatedComment.find_first_not_of(" \t", nlPos + 1);
if (startOfTableLinePos != string::npos) {
m_tableLineLen = translatedComment.size() - startOfTableLinePos;
}
}
} else {
if (m_prevRowIsTH) {
// if previous row contained <th> tag, add horizontal separator
// but first get leading spaces, because they'll be needed for the next row
size_t numLeadingSpaces = translatedComment.size() - nlPos - 1;
translatedComment += string(m_tableLineLen, '-') + '\n';
if (nlPos != string::npos) {
translatedComment += string(numLeadingSpaces, ' ');
}
m_prevRowIsTH = false;
}
}
}
void PyDocConverter::handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end tag, </th> is ignored
} else {
translatedComment += '|';
m_prevRowIsTH = true;
}
}
void PyDocConverter::handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
std::string htmlTagArgs = tag.data;
if (htmlTagArgs == "/") {
// end tag, </td> is ignored
} else {
translatedComment += '|';
}
}
void PyDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg) {
// html entities
translatedComment += arg;
}
void PyDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, const std::string &) {
trimWhitespace(translatedComment);
translatedComment += "\n";
if (!m_indent.empty())
translatedComment += m_indent;
}
String *PyDocConverter::makeDocumentation(Node *n) {
String *documentation;
std::string pyDocString;
// store the node, we may need it later
currentNode = n;
// for overloaded functions we must concat documentation for underlying overloads
if (Getattr(n, "sym:overloaded")) {
// rewind to the first overload
while (Getattr(n, "sym:previousSibling"))
n = Getattr(n, "sym:previousSibling");
std::vector<std::string> allDocumentation;
// minimal indent of any documentation comments, not initialized yet
size_t minIndent = static_cast<size_t>(-1);
// for each real method (not a generated overload) append the documentation
string oneDoc;
while (n) {
documentation = getDoxygenComment(n);
if (!Swig_is_generated_overload(n) && documentation) {
currentNode = n;
if (GetFlag(n, "feature:doxygen:notranslate")) {
String *comment = NewString("");
Append(comment, documentation);
Replaceall(comment, "\n *", "\n");
oneDoc = Char(comment);
Delete(comment);
} else {
std::list<DoxygenEntity> entityList = parser.createTree(n, documentation);
DoxygenEntity root("root", entityList);
oneDoc = translateSubtree(root);
}
// find the minimal indent of this documentation comment, we need to
// ensure that the entire comment is indented by it to avoid the leading
// parts of the other lines being simply discarded later
const size_t oneIndent = determineIndent(oneDoc);
if (oneIndent < minIndent)
minIndent = oneIndent;
allDocumentation.push_back(oneDoc);
}
n = Getattr(n, "sym:nextSibling");
}
// construct final documentation string
if (allDocumentation.size() > 1) {
string indentStr;
if (minIndent != static_cast<size_t>(-1))
indentStr.assign(minIndent, ' ');
std::ostringstream concatDocString;
for (size_t realOverloadCount = 0; realOverloadCount < allDocumentation.size(); realOverloadCount++) {
if (realOverloadCount != 0) {
// separate it from the preceding one.
concatDocString << "\n" << indentStr << "|\n\n";
}
oneDoc = allDocumentation[realOverloadCount];
trimWhitespace(oneDoc);
concatDocString << indentStr << "*Overload " << (realOverloadCount + 1) << ":*\n" << oneDoc;
}
pyDocString = concatDocString.str();
} else if (allDocumentation.size() == 1) {
pyDocString = *(allDocumentation.begin());
}
}
// for other nodes just process as normal
else {
documentation = getDoxygenComment(n);
if (documentation != NULL) {
if (GetFlag(n, "feature:doxygen:notranslate")) {
String *comment = NewString("");
Append(comment, documentation);
Replaceall(comment, "\n *", "\n");
pyDocString = Char(comment);
Delete(comment);
} else {
std::list<DoxygenEntity> entityList = parser.createTree(n, documentation);
DoxygenEntity root("root", entityList);
pyDocString = translateSubtree(root);
}
}
}
// if we got something log the result
if (!pyDocString.empty()) {
// remove the last '\n' since additional one is added during writing to file
eraseTrailingNewLine(pyDocString);
// ensure that a blank line occurs before code or math blocks
pyDocString = padCodeAndVerbatimBlocks(pyDocString);
if (m_flags & debug_translator) {
std::cout << "\n---RESULT IN PYDOC---" << std::endl;
std::cout << pyDocString;
std::cout << std::endl;
}
}
return NewString(pyDocString.c_str());
}

203
Source/Doxygen/pydoc.h Normal file
View file

@ -0,0 +1,203 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* pydoc.h
*
* Module to return documentation for nodes formatted for PyDoc
* ----------------------------------------------------------------------------- */
#ifndef PYDOCCONVERTER_H_
#define PYDOCCONVERTER_H_
#include <list>
#include <string>
#include "swig.h"
#include "doxyentity.h"
#include "doxytranslator.h"
#define DOC_STRING_LENGTH 64 // characters per line allowed
#define DOC_PARAM_STRING_LENGTH 30 // characters reserved for param name / type
class PyDocConverter : public DoxygenTranslator {
public:
PyDocConverter(int flags = 0);
String *makeDocumentation(Node *node);
protected:
size_t m_tableLineLen;
bool m_prevRowIsTH;
std::string m_url;
/*
* Translate every entity in a tree, also manages sections
* display. Prints title for every group of tags that have
* a section title associated with them
*/
std::string translateSubtree(DoxygenEntity &doxygenEntity);
/*
* Translate one entity with the appropriate handler, according
* to the tagHandlers
*/
void translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment);
/*
* Typedef for the function that handles one tag
* arg - some string argument to easily pass it through lookup table
*/
typedef void (PyDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Wrap the command data with the some string
* arg - string to wrap with, like '_' or '*'
*/
void handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Just prints new line
*/
void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Print the name of tag to the output, used for escape-commands
*/
void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Format the contents of the \exception tag or its synonyms.
*/
void handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Print only the content and strip original tag
*/
void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
/*
* Handle Doxygen verbatim tag
*/
void handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
/*
* Handle one of the Doxygen formula-related tags.
*/
void handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Handle a code snippet.
*/
void handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Print only data part of code
*/
void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/**
* Copies verbatim args of the tag to output, used for commands like \f$, ...
*/
void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Print the if-elseif-else-endif section
*/
void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Prints the specified message, than the contents of the tag
* arg - message
*/
void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Insert 'Title: ...'
*/
void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Insert 'Image: ...'
*/
void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Format nice param description with type information
*/
void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Format the contents of the \return tag or its synonyms.
*/
void handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Writes text for \ref tag.
*/
void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/* Handles HTML tags recognized by Doxygen, like <A ...>, <ul>, <table>, ... */
void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/** Does not output params of HTML tag, for example in <table border='1'>
* 'border=1' is not written to output.
*/
void handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/** Translates tag <a href = "url">text</a> to: text ("url"). */
void handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/*
* Handles HTML tags, which are translated to markdown-like syntax, for example
* <i>text</i> --> _text_. Appends arg for start HTML tag and end HTML tag.
*/
void handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/* Handles HTML table, tag <tr> */
void handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/* Handles HTML table, tag <th> */
void handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/* Handles HTML table, tag <td> */
void handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
/* Handles HTML entities recognized by Doxygen, like &lt;, &copy;, ... */
void handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg);
/*
* Simple helper function that calculates correct parameter type
* of the node stored in 'currentNode'
* If param with specified name is not found, empty string is returned
*/
std::string getParamType(std::string name);
private:
// temporary thing, should be refactored somehow
Node *currentNode;
// Extra indent for the current paragraph, must be output after each new line.
std::string m_indent;
// this contains the handler pointer and one string argument
typedef std::map<std::string, std::pair<tagHandler, std::string> >TagHandlersMap;
static TagHandlersMap tagHandlers;
// this contains the sections tittles, like 'Arguments:' or 'Notes:', that are printed only once
static std::map<std::string, std::string> sectionTitles;
// Helper functions for fillStaticTables(): make a new tag handler object.
TagHandlersMap::mapped_type make_handler(tagHandler handler);
TagHandlersMap::mapped_type make_handler(tagHandler handler, const char *arg);
void fillStaticTables();
};
#endif

View file

@ -18,6 +18,8 @@
* Even though symbolic constants are used in the SWIG source, this is
* not always the case in SWIG interface files. Do not change the
* numbers in this file.
*
* This file is used as the input for generating Lib/swigwarn.swg.
* ----------------------------------------------------------------------------- */
#ifndef SWIGWARN_H_
@ -93,8 +95,8 @@
#define WARN_PARSE_EXTEND_NAME 326
#define WARN_CPP11_LAMBDA 340
#define WARN_CPP11_ALIAS_DECLARATION 341
#define WARN_CPP11_ALIAS_TEMPLATE 342
#define WARN_CPP11_ALIAS_DECLARATION 341 /* redundant now */
#define WARN_CPP11_ALIAS_TEMPLATE 342 /* redundant now */
#define WARN_CPP11_VARIADIC_TEMPLATE 343
#define WARN_IGNORE_OPERATOR_NEW 350 /* new */
@ -153,6 +155,7 @@
#define WARN_TYPE_INCOMPLETE 402
#define WARN_TYPE_ABSTRACT 403
#define WARN_TYPE_REDEFINED 404
#define WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405
#define WARN_TYPEMAP_SOURCETARGET 450
#define WARN_TYPEMAP_CHARLEAK 451
@ -207,6 +210,18 @@
#define WARN_LANG_ILLEGAL_DESTRUCTOR 521
#define WARN_LANG_EXTEND_CONSTRUCTOR 522
#define WARN_LANG_EXTEND_DESTRUCTOR 523
#define WARN_LANG_EXPERIMENTAL 524
#define WARN_LANG_DIRECTOR_FINAL 525
/* -- Doxygen comments -- */
#define WARN_DOXYGEN_UNKNOWN_COMMAND 560
#define WARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT 561
#define WARN_DOXYGEN_COMMAND_EXPECTED 562
#define WARN_DOXYGEN_HTML_ERROR 563
#define WARN_DOXYGEN_COMMAND_ERROR 564
#define WARN_DOXYGEN_UNKNOWN_CHARACTER 565
#define WARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE 566
/* -- Reserved (600-799) -- */
@ -215,9 +230,9 @@
/* Feel free to claim any number in this space that's not currently being used. Just make sure you
add an entry here */
#define WARN_D_TYPEMAP_CTYPE_UNDEF 700
#define WARN_D_TYPEMAP_CTYPE_UNDEF 700
#define WARN_D_TYPEMAP_IMTYPE_UNDEF 701
#define WARN_D_TYPEMAP_DTYPE_UNDEF 702
#define WARN_D_TYPEMAP_DTYPE_UNDEF 702
#define WARN_D_MULTIPLE_INHERITANCE 703
#define WARN_D_TYPEMAP_CLASSMOD_UNDEF 704
#define WARN_D_TYPEMAP_DBODY_UNDEF 705

View file

@ -13,6 +13,7 @@ AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \
-I$(SOURCE_DIR)/Include \
-I$(SOURCE_DIR)/DOH \
-I$(SOURCE_DIR)/CParse \
-I$(SOURCE_DIR)/Doxygen \
-I$(SOURCE_DIR)/Preprocessor \
-I$(SOURCE_DIR)/Swig \
-I$(SOURCE_DIR)/Modules
@ -34,12 +35,18 @@ eswig_SOURCES = CParse/cscanner.c \
DOH/memory.c \
DOH/string.c \
DOH/void.c \
Modules/allegrocl.cxx \
Doxygen/doxyentity.cxx \
Doxygen/doxyentity.h \
Doxygen/doxyparser.cxx \
Doxygen/doxyparser.h \
Doxygen/doxytranslator.cxx \
Doxygen/doxytranslator.h \
Doxygen/javadoc.cxx \
Doxygen/javadoc.h \
Doxygen/pydoc.cxx \
Doxygen/pydoc.h \
Modules/allocate.cxx \
Modules/browser.cxx \
Modules/cffi.cxx \
Modules/chicken.cxx \
Modules/clisp.cxx \
Modules/contract.cxx \
Modules/c.cxx \
Modules/csharp.cxx \
@ -54,25 +61,20 @@ eswig_SOURCES = CParse/cscanner.c \
Modules/lang.cxx \
Modules/lua.cxx \
Modules/main.cxx \
Modules/modula3.cxx \
Modules/module.cxx \
Modules/mzscheme.cxx \
Modules/nested.cxx \
Modules/nested.cxx \
Modules/ocaml.cxx \
Modules/octave.cxx \
Modules/overload.cxx \
Modules/perl5.cxx \
Modules/php.cxx \
Modules/pike.cxx \
Modules/python.cxx \
Modules/r.cxx \
Modules/ruby.cxx \
Modules/s-exp.cxx \
Modules/scilab.cxx \
Modules/swigmain.cxx \
Modules/tcl8.cxx \
Modules/typepass.cxx \
Modules/uffi.cxx \
Modules/utils.cxx \
Modules/xml.cxx \
Preprocessor/cpp.c \
@ -91,8 +93,8 @@ eswig_SOURCES = CParse/cscanner.c \
Swig/stype.c \
Swig/symbol.c \
Swig/tree.c \
Swig/typeobj.c \
Swig/typemap.c \
Swig/typeobj.c \
Swig/typesys.c \
Swig/wrapfunc.c
@ -122,7 +124,7 @@ distclean-local:
# swig executable as a way of checking before and after the 'beautifying'.
# Single files can be beautified with the beautify-file target, eg: 'make beautify-file INDENTFILE=chosenfile.c'
SWIGTYPEDEFS=-T bool -T File -T DohObjInfo -T Parm -T Language -T List -T Typetab -T ModuleFactory -T ErrorMessageFormat -T Symtab -T Hash -T Scanner -T String -T DohBase -T Node -T String_or_char -T SwigType -T Dispatcher -T Wrapper -T DohStringMethods -T DohFileMethods -T DohListMethods -T DohHashMethods -T DOH -T DohIterator -T ParmList -T FILE -T HashNode -T DOHObj_or_char -T DOHFile -T DOHString -T DOHString_or_char -T UpcallData
SWIGTYPEDEFS=-T bool -T File -T DohObjInfo -T Parm -T Language -T List -T TargetLanguageModule -T Typetab -T ModuleFactory -T ErrorMessageFormat -T Symtab -T Hash -T Scanner -T String -T DohBase -T Node -T String_or_char -T SwigType -T Dispatcher -T Wrapper -T DohStringMethods -T DohFileMethods -T DohListMethods -T DohHashMethods -T DOH -T DohIterator -T ParmList -T FILE -T HashNode -T DOHObj_or_char -T DOHFile -T DOHString -T DOHString_or_char -T UpcallData
INDENTBAKSDIR=../IndentBaks
beautify:

View file

@ -471,7 +471,7 @@ void add_defined_foreign_type(Node *n, int overwrite = 0, String *k = 0,
// a synonym type was found (held in variable 'match')
// Printf(stderr, "setting primary synonym of %p to %p\n", new_node, match);
if (new_node == match)
Printf(stderr, "Hey-4 * - '%s' is a synonym of iteself!\n", Getattr(new_node, "name"));
Printf(stderr, "Hey-4 * - '%s' is a synonym of itself!\n", Getattr(new_node, "name"));
Setattr(new_node, "allegrocl:synonym-of", match);
// Printf(stderr,"*** 4\n");
add_linked_type(new_node);
@ -1685,285 +1685,6 @@ int ALLEGROCL::top(Node *n) {
return SWIG_OK;
}
/* very shamelessly 'borrowed' from overload.cxx, which
keeps the below Swig_overload_rank() code to itself.
We don't need a dispatch function in the C++ wrapper
code; we want it over on the lisp side. */
#define Swig_overload_rank Allegrocl_swig_overload_rank
#define MAX_OVERLOAD 256
/* Overload "argc" and "argv" */
// String *argv_template_string;
// String *argc_template_string;
struct Overloaded {
Node *n; /* Node */
int argc; /* Argument count */
ParmList *parms; /* Parameters used for overload check */
int error; /* Ambiguity error */
};
/* -----------------------------------------------------------------------------
* Swig_overload_rank()
*
* This function takes an overloaded declaration and creates a list that ranks
* all overloaded methods in an order that can be used to generate a dispatch
* function.
* Slight difference in the way this function is used by scripting languages and
* statically typed languages. The script languages call this method via
* Swig_overload_dispatch() - where wrappers for all overloaded methods are generated,
* however sometimes the code can never be executed. The non-scripting languages
* call this method via Swig_overload_check() for each overloaded method in order
* to determine whether or not the method should be wrapped. Note the slight
* difference when overloading methods that differ by const only. The
* scripting languages will ignore the const method, whereas the non-scripting
* languages ignore the first method parsed.
* ----------------------------------------------------------------------------- */
static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
Overloaded nodes[MAX_OVERLOAD];
int nnodes = 0;
Node *o = Getattr(n, "sym:overloaded");
Node *c;
if (!o)
return 0;
c = o;
while (c) {
if (Getattr(c, "error")) {
c = Getattr(c, "sym:nextSibling");
continue;
}
/* if (SmartPointer && Getattr(c,"cplus:staticbase")) {
c = Getattr(c,"sym:nextSibling");
continue;
} */
/* Make a list of all the declarations (methods) that are overloaded with
* this one particular method name */
if (Getattr(c, "wrap:name")) {
nodes[nnodes].n = c;
nodes[nnodes].parms = Getattr(c, "wrap:parms");
nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
nodes[nnodes].error = 0;
nnodes++;
}
c = Getattr(c, "sym:nextSibling");
}
/* Sort the declarations by required argument count */
{
int i, j;
for (i = 0; i < nnodes; i++) {
for (j = i + 1; j < nnodes; j++) {
if (nodes[i].argc > nodes[j].argc) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
}
}
}
/* Sort the declarations by argument types */
{
int i, j;
for (i = 0; i < nnodes - 1; i++) {
if (nodes[i].argc == nodes[i + 1].argc) {
for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
Parm *p1 = nodes[i].parms;
Parm *p2 = nodes[j].parms;
int differ = 0;
int num_checked = 0;
while (p1 && p2 && (num_checked < nodes[i].argc)) {
// Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
if (checkAttribute(p1, "tmap:in:numinputs", "0")) {
p1 = Getattr(p1, "tmap:in:next");
continue;
}
if (checkAttribute(p2, "tmap:in:numinputs", "0")) {
p2 = Getattr(p2, "tmap:in:next");
continue;
}
String *t1 = Getattr(p1, "tmap:typecheck:precedence");
String *t2 = Getattr(p2, "tmap:typecheck:precedence");
if ((!t1) && (!nodes[i].error)) {
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
"Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
nodes[i].error = 1;
} else if ((!t2) && (!nodes[j].error)) {
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
nodes[j].error = 1;
}
if (t1 && t2) {
int t1v, t2v;
t1v = atoi(Char(t1));
t2v = atoi(Char(t2));
differ = t1v - t2v;
} else if (!t1 && t2)
differ = 1;
else if (t1 && !t2)
differ = -1;
else if (!t1 && !t2)
differ = -1;
num_checked++;
if (differ > 0) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
break;
} else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
t1 = Getattr(p1, "ltype");
if (!t1) {
t1 = SwigType_ltype(Getattr(p1, "type"));
if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
SwigType_add_pointer(t1);
}
Setattr(p1, "ltype", t1);
}
t2 = Getattr(p2, "ltype");
if (!t2) {
t2 = SwigType_ltype(Getattr(p2, "type"));
if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
SwigType_add_pointer(t2);
}
Setattr(p2, "ltype", t2);
}
/* Need subtype check here. If t2 is a subtype of t1, then we need to change the
order */
if (SwigType_issubtype(t2, t1)) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
if (Strcmp(t1, t2) != 0) {
differ = 1;
break;
}
} else if (differ) {
break;
}
if (Getattr(p1, "tmap:in:next")) {
p1 = Getattr(p1, "tmap:in:next");
} else {
p1 = nextSibling(p1);
}
if (Getattr(p2, "tmap:in:next")) {
p2 = Getattr(p2, "tmap:in:next");
} else {
p2 = nextSibling(p2);
}
}
if (!differ) {
/* See if declarations differ by const only */
String *d1 = Getattr(nodes[i].n, "decl");
String *d2 = Getattr(nodes[j].n, "decl");
if (d1 && d2) {
String *dq1 = Copy(d1);
String *dq2 = Copy(d2);
if (SwigType_isconst(d1)) {
Delete(SwigType_pop(dq1));
}
if (SwigType_isconst(d2)) {
Delete(SwigType_pop(dq2));
}
if (Strcmp(dq1, dq2) == 0) {
if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
if (script_lang_wrapping) {
// Swap nodes so that the const method gets ignored (shadowed by the non-const method)
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
differ = 1;
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
"using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore")) {
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
"using %s instead.\n", Swig_name_decl(nodes[i].n));
}
}
}
nodes[j].error = 1;
} else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
differ = 1;
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
"using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore")) {
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
"using %s instead.\n", Swig_name_decl(nodes[i].n));
}
}
}
nodes[j].error = 1;
}
}
Delete(dq1);
Delete(dq2);
}
}
if (!differ) {
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
"as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore")) {
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
"using %s instead.\n", Swig_name_decl(nodes[i].n));
}
}
nodes[j].error = 1;
}
}
}
}
}
}
List *result = NewList();
{
int i;
for (i = 0; i < nnodes; i++) {
if (nodes[i].error)
Setattr(nodes[i].n, "overload:ignore", "1");
Append(result, nodes[i].n);
// Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms));
// Swig_print_node(nodes[i].n);
}
}
return result;
}
/* end shameless borrowing */
int any_varargs(ParmList *pl) {
Parm *p;
@ -2722,6 +2443,13 @@ int ALLEGROCL::functionWrapper(Node *n) {
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
emit_return_variable(n, t, f);
if (CPlusPlus) {

View file

@ -197,15 +197,17 @@ class Allocate:public Dispatcher {
// Found a polymorphic method.
// Mark the polymorphic method, in case the virtual keyword was not used.
Setattr(n, "storage", "virtual");
if (both_have_public_access || both_have_protected_access) {
if (!is_non_public_base(inclass, b))
Setattr(n, "override", base); // Note C# definition of override, ie access must be the same
} else if (!both_have_private_access) {
// Different access
if (this_wrapping_protected_members || base_wrapping_protected_members)
if (!Getattr(b, "feature:interface")) { // interface implementation neither hides nor overrides
if (both_have_public_access || both_have_protected_access) {
if (!is_non_public_base(inclass, b))
Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different
Setattr(n, "override", base); // Note C# definition of override, ie access must be the same
}
else if (!both_have_private_access) {
// Different access
if (this_wrapping_protected_members || base_wrapping_protected_members)
if (!is_non_public_base(inclass, b))
Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different
}
}
// Try and find the most base's covariant return type
SwigType *most_base_covariant_type = Getattr(base, "covariant");
@ -502,7 +504,7 @@ class Allocate:public Dispatcher {
in emit.cxx
and is either constructued from the "feature:catches" feature
and is either constructed from the "feature:catches" feature
or copied from the node "throws" list.
*/
String *scatchlist = Getattr(n, "feature:catches");

View file

@ -543,6 +543,14 @@ int CFFI::functionWrapper(Node *n) {
cleanupFunction(n, f, parms);
/* See if there is any return cleanup code */
String *tm = 0;
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
if (!is_void_return) {
Printf(f->code, " return lresult;\n");
}

View file

@ -547,7 +547,7 @@ int CHICKEN::functionWrapper(Node *n) {
}
emit_return_variable(n, d, f);
/* Insert the argumetn output code */
/* Insert the argument output code */
Printv(f->code, argout, NIL);
/* Output cleanup code */
@ -1456,7 +1456,7 @@ String *CHICKEN::chickenPrimitiveName(String *name) {
if (value)
return value;
else {
Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existant primitive name %s\n", name);
Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existent primitive name %s\n", name);
return NewString("#f");
}
}

View file

@ -68,8 +68,8 @@ class CSHARP:public Language {
String *module_baseclass; //inheritance for module class from %pragma
String *imclass_interfaces; //interfaces for intermediary class class from %pragma
String *module_interfaces; //interfaces for module class from %pragma
String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
String *module_class_modifiers; //class modifiers for module class overriden by %pragma
String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
String *module_class_modifiers; //class modifiers for module class overridden by %pragma
String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
String *director_callback_typedefs; // Director function pointer typedefs for callbacks
@ -683,7 +683,7 @@ public:
String *filen = NewStringf("%s%s.cs", dir, name);
File *f = NewFile(filen, "w", SWIG_output_files());
if (!f) {
FileErrorDisplay(f);
FileErrorDisplay(filen);
SWIG_exit(EXIT_FAILURE);
}
Append(filenames_list, Copy(filen));
@ -1384,7 +1384,7 @@ public:
// Wrap C/C++ enums with constant integers or use the typesafe enum pattern
SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
Setattr(n, "type", typemap_lookup_type);
const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF);
String *return_type = Copy(tm);
substituteClassname(typemap_lookup_type, return_type);
@ -1584,11 +1584,23 @@ public:
* ----------------------------------------------------------------------------- */
virtual int insertDirective(Node *n) {
int ret = SWIG_OK;
String *code = Getattr(n, "code");
String *section = Getattr(n, "section");
Replaceall(code, "$module", module_class_name);
Replaceall(code, "$imclassname", imclass_name);
Replaceall(code, "$dllimport", dllimport);
return Language::insertDirective(n);
if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
if (proxy_class_code) {
Swig_typemap_replace_embedded_typemap(code, n);
int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
}
} else {
ret = Language::insertDirective(n);
}
return ret;
}
/* -----------------------------------------------------------------------------
@ -1720,7 +1732,7 @@ public:
Replaceall(cptr_method_name, ".", "_");
Replaceall(cptr_method_name, "$interfacename", interface_name);
String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name);
String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
Delete(upcast_method_name);
@ -1861,46 +1873,70 @@ public:
typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
NIL);
// C++ destructor is wrapped by the Dispose method
// Note that the method name is specified in a typemap attribute called methodname
// C++ destructor is wrapped by the Finalize and Dispose methods
const char *tmap_method = derived ? "csdestruct_derived" : "csdestruct";
const String *tm = typemapExists(n, tmap_method, typemap_lookup_type);
if (tm) {
Swig_error(Getfile(tm), Getline(tm),
"A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
tmap_method, proxy_class_name);
}
tmap_method = "csfinalize";
tm = typemapExists(n, tmap_method, typemap_lookup_type);
if (tm) {
Swig_error(Getfile(tm), Getline(tm),
"A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
tmap_method, proxy_class_name);
}
tmap_method = derived ? "csdisposing_derived" : "csdisposing";
String *destruct = NewString("");
const String *tm = NULL;
attributes = NewHash();
String *destruct_methodname = NULL;
String *destruct_methodmodifiers = NULL;
const String *destruct_methodname = NULL;
const String *destruct_methodmodifiers = NULL;
const String *destruct_parameters = NULL;
if (derived) {
tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers");
tm = typemapLookup(n, "csdisposing_derived", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdisposing_derived:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing_derived:methodmodifiers");
destruct_parameters = Getattr(attributes, "tmap:csdisposing_derived:parameters");
} else {
tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers");
tm = typemapLookup(n, "csdisposing", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdisposing:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing:methodmodifiers");
destruct_parameters = Getattr(attributes, "tmap:csdisposing:parameters");
}
if (tm && *Char(tm)) {
if (!destruct_methodname) {
Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in %s typemap for %s\n", tmap_method, proxy_class_name);
}
if (!destruct_methodmodifiers) {
Swig_error(Getfile(n), Getline(n),
"No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
"No methodmodifiers attribute defined in %s typemap for %s.\n", tmap_method, proxy_class_name);
}
if (!destruct_parameters)
destruct_parameters = empty_string;
}
// Emit the Finalize and Dispose methods
if (tm) {
// Finalize method
if (*Char(destructor_call)) {
Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL);
}
// Dispose method
// Finalize and Dispose methods
Printv(proxy_class_def, typemapLookup(n, derived ? "csdispose_derived" : "csdispose", typemap_lookup_type, WARN_NONE), NIL);
// Dispose(bool disposing) method
Printv(destruct, tm, NIL);
if (*Char(destructor_call))
Replaceall(destruct, "$imcall", destructor_call);
else
Replaceall(destruct, "$imcall", "throw new global::System.MethodAccessException(\"C++ destructor does not have public access\")");
if (*Char(destruct))
Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
NIL);
if (*Char(destruct)) {
Printv(proxy_class_def, "\n ", NIL);
const String *methodmods = Getattr(n, "destructmethodmodifiers");
if (methodmods)
Printv(proxy_class_def, methodmods, NIL);
else
Printv(proxy_class_def, destruct_methodmodifiers, " ", derived ? "override" : "virtual", NIL);
Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ") ", destruct, "\n", NIL);
}
}
if (*Char(interface_upcasts))
Printv(proxy_class_def, interface_upcasts, NIL);
@ -1917,7 +1953,7 @@ public:
String *methid = Getattr(udata, "class_methodidx");
String *overname = Getattr(udata, "overname");
Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirectorMethod%s);\n", methid, proxy_class_name, methid, overname);
}
String *director_connect_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name);
@ -2044,34 +2080,6 @@ public:
}
}
/* ----------------------------------------------------------------------
* calculateDirectBase()
* ---------------------------------------------------------------------- */
void calculateDirectBase(Node* n) {
Node* direct_base = 0;
// C++ inheritance
Node *attributes = NewHash();
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
Delete(attributes);
if (!purebase_replace) {
if (List *baselist = Getattr(n, "bases")) {
Iterator base = First(baselist);
while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface")))
base = Next(base);
direct_base = base.item;
}
if (!direct_base && purebase_notderived)
direct_base = symbolLookup(const_cast<String*>(pure_baseclass));
} else {
direct_base = symbolLookup(const_cast<String*>(pure_baseclass));
}
Setattr(n, "direct_base", direct_base);
}
/* ----------------------------------------------------------------------
* classHandler()
* ---------------------------------------------------------------------- */
@ -2157,7 +2165,6 @@ public:
emitInterfaceDeclaration(n, interface_name, interface_class_code);
Delete(output_directory);
}
calculateDirectBase(n);
}
Language::classHandler(n);
@ -2224,37 +2231,6 @@ public:
--nesting_depth;
}
/* Output the downcast method, if necessary. Note: There's no other really
good place to put this code, since Abstract Base Classes (ABCs) can and should have
downcasts, making the constructorHandler() a bad place (because ABCs don't get to
have constructors emitted.) */
if (GetFlag(n, "feature:csdowncast")) {
String *downcast_method = Swig_name_member(getNSpace(), proxy_class_name, "SWIGDowncast");
String *wname = Swig_name_wrapper(downcast_method);
String *norm_name = SwigType_namestr(Getattr(n, "name"));
Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method);
Wrapper *dcast_wrap = NewWrapper();
Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname);
Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
Printf(dcast_wrap->code, " return jresult;\n");
Printf(dcast_wrap->code, "}\n");
Wrapper_print(dcast_wrap, f_wrappers);
DelWrapper(dcast_wrap);
Delete(norm_name);
Delete(wname);
Delete(downcast_method);
}
if (f_interface) {
Printv(f_interface, interface_class_code, "}\n", NIL);
addCloseNamespace(nspace, f_interface);
@ -2426,21 +2402,8 @@ public:
Printf(function_code, " %s ", methodmods);
if (!is_smart_pointer()) {
// Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
if (Node *base_ovr = Getattr(n, "override")) {
if (GetFlag(n, "isextendmember"))
if (Getattr(n, "override"))
Printf(function_code, "override ");
else {
Node* base = parentNode(base_ovr);
bool ovr = false;
for (Node* direct_base = Getattr(parentNode(n), "direct_base"); direct_base; direct_base = Getattr(direct_base, "direct_base")) {
if (direct_base == base) { // "override" only applies if the base was not discarded (e.g. in case of multiple inheritance or via "ignore")
ovr = true;
break;
}
}
Printf(function_code, ovr ? "override " : "virtual ");
}
}
else if (checkAttribute(n, "storage", "virtual"))
Printf(function_code, "virtual ");
if (Getattr(n, "hides"))
@ -2843,7 +2806,8 @@ public:
/* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
Hash *attributes = NewHash();
String *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"),
String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
String *construct_tm = Copy(typemapLookup(n, "csconstruct", typemap_lookup_type,
WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
if (construct_tm) {
if (!feature_director) {
@ -2921,7 +2885,11 @@ public:
if (proxy_flag) {
Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
if (methodmods)
Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
}
return SWIG_OK;
}
@ -3602,6 +3570,24 @@ public:
return tm;
}
/* -----------------------------------------------------------------------------
* typemapExists()
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
* tmap_method - typemap method name
* type - typemap type to lookup
* returns found typemap or NULL if not found
* ----------------------------------------------------------------------------- */
const String *typemapExists(Node *n, const_String_or_char_ptr tmap_method, SwigType *type) {
Node *node = NewHash();
Setattr(node, "type", type);
Setfile(node, Getfile(n));
Setline(node, Getline(n));
const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
Delete(node);
return tm;
}
/* -----------------------------------------------------------------------------
* canThrow()
* Determine whether the code in the typemap can throw a C# exception.
@ -3764,16 +3750,13 @@ public:
Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr);
Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
}
else {
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
} else {
Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
}
// TODO: if statement not needed?? - Java too
Printf(code_wrap->code, " if (director) {\n");
Printf(code_wrap->code, " director->swig_connect_director(");
Printf(code_wrap->code, " director->swig_connect_director(");
for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
UpcallData *udata = Getitem(dmethods_seq, i);
@ -3790,7 +3773,6 @@ public:
Printf(code_wrap->def, ") {\n");
Printf(code_wrap->code, ");\n");
Printf(imclass_class_code, ");\n");
Printf(code_wrap->code, " }\n");
Printf(code_wrap->code, "}\n");
Wrapper_print(code_wrap, f_wrappers);
@ -3856,7 +3838,7 @@ public:
qualified_return = SwigType_rcaststr(returntype, "c_result");
if (!is_void && !ignored_method) {
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
@ -3876,15 +3858,17 @@ public:
/* If returning a reference, initialize the pointer to a sane
default - if a C# exception occurs, then the pointer returns
something other than a NULL-initialized reference. */
String *non_ref_type = Copy(returntype);
SwigType *noref_type = SwigType_del_reference(Copy(returntype));
String *noref_ltype = SwigType_lstr(noref_type, 0);
String *return_ltype = SwigType_lstr(returntype, 0);
/* Remove reference and const qualifiers */
Replaceall(non_ref_type, "r.", "");
Replaceall(non_ref_type, "q(const).", "");
Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
Delete(non_ref_type);
Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
Printf(w->code, "c_result = &result_default;\n");
Delete(return_ltype);
Delete(noref_ltype);
Delete(noref_type);
}
Delete(base_typename);
@ -3916,9 +3900,13 @@ public:
Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
}
Printf(callback_def, " private %s SwigDirector%s(", tm, overloaded_name);
if (!ignored_method)
Printf(director_delegate_definitions, " public delegate %s", tm);
Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name);
if (!ignored_method) {
const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers");
String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public "));
Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm);
Delete(modifiers);
}
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
}
@ -3942,7 +3930,7 @@ public:
Swig_typemap_attach_parms("ctype", l, 0);
Swig_typemap_attach_parms("imtype", l, 0);
Swig_typemap_attach_parms("cstype", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("csdirectorin", l, 0);
Swig_typemap_attach_parms("directorargout", l, w);
@ -3961,7 +3949,11 @@ public:
}
Delete(super_call);
} else {
Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
if (!is_void)
Printf(w->code, "return %s;", qualified_return);
else if (!ignored_method)
Printf(w->code, "return;\n");
}
if (!ignored_method)
@ -4119,15 +4111,19 @@ public:
/* header declaration, start wrapper definition */
String *target;
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Add any exception specifications to the methods in the director class
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = NULL;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0;
@ -4336,7 +4332,7 @@ public:
/* constructor */
{
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
String *call = Swig_csuperclass_call(0, basetype, superparms);
Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
@ -4349,7 +4345,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -4445,9 +4441,12 @@ public:
String *dirclassname = directorClassName(current_class);
Wrapper *w = NewWrapper();
if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname);
Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname);
if (Getattr(n, "noexcept")) {
Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
} else if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
} else {
Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);

View file

@ -717,9 +717,20 @@ public:
* D::insertDirective()
* --------------------------------------------------------------------------- */
virtual int insertDirective(Node *n) {
int ret = SWIG_OK;
String *code = Getattr(n, "code");
String *section = Getattr(n, "section");
replaceModuleVariables(code);
return Language::insertDirective(n);
if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
if (proxy_class_body_code) {
Swig_typemap_replace_embedded_typemap(code, n);
Printv(proxy_class_body_code, code, NIL);
}
} else {
ret = Language::insertDirective(n);
}
return ret;
}
/* ---------------------------------------------------------------------------
@ -978,7 +989,7 @@ public:
// Smart pointer classes do not mirror the inheritance hierarchy of the
// underlying types, so aliasing the base class methods in is not required
// for them.
// DMD BUG: We have to emit the alias after the last function becasue
// DMD BUG: We have to emit the alias after the last function because
// taking a delegate in the overload checking code fails otherwise
// (http://d.puremagic.com/issues/show_bug.cgi?id=4860).
if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() &&
@ -1216,8 +1227,9 @@ public:
// Insert the dconstructor typemap (replacing $directorconnect as needed).
Hash *attributes = NewHash();
String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor",
Getattr(n, "name"), WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
typemap_lookup_type, WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
if (construct_tm) {
const bool use_director = (parentNode(n) && Swig_directorclass(n));
if (!use_director) {
@ -1287,7 +1299,12 @@ public:
virtual int destructorHandler(Node *n) {
Language::destructorHandler(n);
String *symname = Getattr(n, "sym:name");
Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL);
const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
if (methodmods)
Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
return SWIG_OK;
}
@ -1465,7 +1482,7 @@ public:
}
Delete(attributes);
// Retrive the override value set via %dconstvalue, if any.
// Retrieve the override value set via %dconstvalue, if any.
String *override_value = Getattr(n, "feature:d:constvalue");
if (override_value) {
Printf(constants_code, "%s;\n", override_value);
@ -1964,7 +1981,7 @@ public:
qualified_return = SwigType_rcaststr(returntype, "c_result");
if (!is_void && !ignored_method) {
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
@ -1984,15 +2001,17 @@ public:
/* If returning a reference, initialize the pointer to a sane
default - if a D exception occurs, then the pointer returns
something other than a NULL-initialized reference. */
String *non_ref_type = Copy(returntype);
SwigType *noref_type = SwigType_del_reference(Copy(returntype));
String *noref_ltype = SwigType_lstr(noref_type, 0);
String *return_ltype = SwigType_lstr(returntype, 0);
/* Remove reference and const qualifiers */
Replaceall(non_ref_type, "r.", "");
Replaceall(non_ref_type, "q(const).", "");
Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
Delete(non_ref_type);
Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
Printf(w->code, "c_result = &result_default;\n");
Delete(return_ltype);
Delete(noref_ltype);
Delete(noref_type);
}
Delete(base_typename);
@ -2047,7 +2066,7 @@ public:
Swig_typemap_attach_parms("ctype", l, 0);
Swig_typemap_attach_parms("imtype", l, 0);
Swig_typemap_attach_parms("dtype", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("ddirectorin", l, 0);
Swig_typemap_attach_parms("directorargout", l, w);
@ -2066,7 +2085,11 @@ public:
}
Delete(super_call);
} else {
Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
if (!is_void)
Printf(w->code, "return %s;", qualified_return);
else if (!ignored_method)
Printf(w->code, "return;\n");
}
if (!ignored_method)
@ -2197,15 +2220,19 @@ public:
/* header declaration, start wrapper definition */
String *target;
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Add any exception specifications to the methods in the director class
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = NULL;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0;
@ -2417,7 +2444,7 @@ public:
/* constructor */
{
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
String *call = Swig_csuperclass_call(0, basetype, superparms);
String *classtype = SwigType_namestr(Getattr(n, "name"));
@ -2432,7 +2459,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -2472,9 +2499,12 @@ public:
String *dirclassname = directorClassName(current_class);
Wrapper *w = NewWrapper();
if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname);
Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname);
if (Getattr(n, "noexcept")) {
Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
} else if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
} else {
Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
@ -3244,17 +3274,20 @@ private:
// attribute called »methodname«.
const String *tm = NULL;
String *dispose_methodname;
String *dispose_methodmodifiers;
const String *dispose_methodname;
const String *dispose_methodmodifiers;
const String *dispose_parameters;
attributes = NewHash();
if (derived) {
tm = lookupCodeTypemap(n, "ddispose_derived", typemap_lookup_type, WARN_NONE, attributes);
dispose_methodname = Getattr(attributes, "tmap:ddispose_derived:methodname");
dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose_derived:methodmodifiers");
dispose_parameters = Getattr(attributes, "tmap:ddispose_derived:parameters");
} else {
tm = lookupCodeTypemap(n, "ddispose", typemap_lookup_type, WARN_NONE, attributes);
dispose_methodname = Getattr(attributes, "tmap:ddispose:methodname");
dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose:methodmodifiers");
dispose_parameters = Getattr(attributes, "tmap:ddispose:parameters");
}
if (tm && *Char(tm)) {
@ -3268,6 +3301,8 @@ private:
"No methodmodifiers attribute defined in ddispose%s typemap for %s.\n",
(derived ? "_derived" : ""), proxy_class_name);
}
if (!dispose_parameters)
dispose_parameters = empty_string;
}
if (tm) {
@ -3288,9 +3323,13 @@ private:
}
if (*Char(dispose_code)) {
Printv(body, "\n", dispose_methodmodifiers,
(derived ? " override" : ""), " void ", dispose_methodname, "() ",
dispose_code, "\n", NIL);
Printv(body, "\n", NIL);
const String *methodmods = Getattr(n, "destructmethodmodifiers");
if (methodmods)
Printv(body, methodmods, NIL);
else
Printv(body, dispose_methodmodifiers, (derived ? " override" : ""), NIL);
Printv(body, " void ", dispose_methodname, "(", dispose_parameters, ") ", dispose_code, "\n", NIL);
}
}
@ -3545,10 +3584,9 @@ private:
Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name);
Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
Printf(code_wrap->code, " if (director) {\n");
Printf(code_wrap->code, " director->swig_connect_director(dobj");
Printf(code_wrap->code, " director->swig_connect_director(dobj");
for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
UpcallData *udata = Getitem(dmethods_seq, i);
@ -3562,7 +3600,6 @@ private:
Printf(code_wrap->def, ") {\n");
Printf(code_wrap->code, ");\n");
Printf(im_dmodule_code, ") %s;\n", connect_name);
Printf(code_wrap->code, " }\n");
Printf(code_wrap->code, "}\n");
Wrapper_print(code_wrap, f_wrappers);
@ -4321,7 +4358,7 @@ private:
*
* Determines whether the class the passed function node belongs to overrides
* all the overlaods for the passed function node defined somewhere up the
* inheritance hierachy.
* inheritance hierarchy.
* --------------------------------------------------------------------------- */
bool areAllOverloadsOverridden(Node *n) const {
List *base_list = Getattr(parentNode(n), "bases");
@ -4346,7 +4383,7 @@ private:
}
// We try to find at least a single overload which exists in the base class
// so we can progress up the inheritance hierachy even if there have been
// so we can progress up the inheritance hierarchy even if there have been
// new overloads introduced after the topmost class.
Node *base_function = NULL;
String *symname = Getattr(n, "sym:name");
@ -4372,7 +4409,7 @@ private:
!(Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode())) {
// If the base class function is »protected« and were are not in
// director mode, it is not emitted to the base class and thus we do
// not count it. Otherwise, we would run into issues if the visiblity
// not count it. Otherwise, we would run into issues if the visibility
// of some functions was changed from protected to public in a child
// class with the using directive.
continue;

View file

@ -15,12 +15,12 @@
#include "swigmod.h"
/* Swig_csuperclass_call()
/* -----------------------------------------------------------------------------
* Swig_csuperclass_call()
*
* Generates a fully qualified method call, including the full parameter list.
* e.g. "base::method(i, j)"
*
*/
* ----------------------------------------------------------------------------- */
String *Swig_csuperclass_call(String *base, String *method, ParmList *l) {
String *call = NewString("");
@ -44,12 +44,12 @@ String *Swig_csuperclass_call(String *base, String *method, ParmList *l) {
return call;
}
/* Swig_class_declaration()
/* -----------------------------------------------------------------------------
* Swig_class_declaration()
*
* Generate the start of a class/struct declaration.
* e.g. "class myclass"
*
*/
* ----------------------------------------------------------------------------- */
String *Swig_class_declaration(Node *n, String *name) {
if (!name) {
@ -61,18 +61,22 @@ String *Swig_class_declaration(Node *n, String *name) {
return result;
}
/* -----------------------------------------------------------------------------
* Swig_class_name()
* ----------------------------------------------------------------------------- */
String *Swig_class_name(Node *n) {
String *name;
name = Copy(Getattr(n, "sym:name"));
return name;
}
/* Swig_director_declaration()
/* -----------------------------------------------------------------------------
* Swig_director_declaration()
*
* Generate the full director class declaration, complete with base classes.
* e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
*
*/
* ----------------------------------------------------------------------------- */
String *Swig_director_declaration(Node *n) {
String *classname = Swig_class_name(n);
@ -87,6 +91,10 @@ String *Swig_director_declaration(Node *n) {
}
/* -----------------------------------------------------------------------------
* Swig_method_call()
* ----------------------------------------------------------------------------- */
String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) {
String *func;
int i = 0;
@ -115,153 +123,67 @@ String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) {
return func;
}
/* Swig_method_decl
/* -----------------------------------------------------------------------------
* Swig_method_decl()
*
* Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities
* and modified to generate full (or partial) type qualifiers for method declarations,
* local variable declarations, and return value casting. More importantly, it merges
* parameter type information with actual parameter names to produce a complete method
* declaration that fully mirrors the original method declaration.
*
* There is almost certainly a saner way to do this.
*
* This function needs to be cleaned up and possibly split into several smaller
* functions. For instance, attaching default names to parameters should be done in a
* separate function.
*
*/
* Return a stringified version of a C/C++ declaration.
* ----------------------------------------------------------------------------- */
String *Swig_method_decl(SwigType *rettype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values) {
String *result;
List *elements;
String *element = 0, *nextelement;
int is_const = 0;
int nelements, i;
int is_func = 0;
String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args) {
String *result = NewString("");
bool conversion_operator = Strstr(id, "operator ") != 0 && !return_base_type;
Parm *parm = args;
int arg_idx = 0;
if (id) {
result = NewString(Char(id));
} else {
result = NewString("");
}
elements = SwigType_split(decl);
nelements = Len(elements);
if (nelements > 0) {
element = Getitem(elements, 0);
}
for (i = 0; i < nelements; i++) {
if (i < (nelements - 1)) {
nextelement = Getitem(elements, i + 1);
} else {
nextelement = 0;
while (parm) {
String *type = Getattr(parm, "type");
String *name = Getattr(parm, "name");
if (!name && Cmp(type, "void")) {
name = NewString("");
Printf(name, "arg%d", arg_idx++);
Setattr(parm, "name", name);
}
if (SwigType_isqualifier(element)) {
int skip = 0;
DOH *q = 0;
if (!strip) {
q = SwigType_parm(element);
if (!Cmp(q, "const")) {
is_const = 1;
is_func = SwigType_isfunction(nextelement);
if (is_func)
skip = 1;
skip = 1;
}
if (!skip) {
Insert(result, 0, " ");
Insert(result, 0, q);
}
Delete(q);
}
} else if (SwigType_isfunction(element)) {
Parm *parm;
String *p;
Append(result, "(");
parm = args;
while (parm != 0) {
String *type = Getattr(parm, "type");
String *name = Getattr(parm, "name");
if (!name && Cmp(type, "void")) {
name = NewString("");
Printf(name, "arg%d", arg_idx++);
Setattr(parm, "name", name);
}
if (!name) {
name = NewString("");
}
p = SwigType_str(type, name);
Append(result, p);
String *value = Getattr(parm, "value");
if (values && (value != 0)) {
Printf(result, " = %s", value);
}
parm = nextSibling(parm);
if (parm != 0)
Append(result, ", ");
}
Append(result, ")");
} else if (rettype) { // This check is intended for conversion operators to a pointer/reference which needs the pointer/reference ignoring in the declaration
if (SwigType_ispointer(element)) {
Insert(result, 0, "*");
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
} else if (SwigType_ismemberpointer(element)) {
String *q;
q = SwigType_parm(element);
Insert(result, 0, "::*");
Insert(result, 0, q);
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
Delete(q);
} else if (SwigType_isreference(element)) {
Insert(result, 0, "&");
} else if (SwigType_isarray(element)) {
DOH *size;
Append(result, "[");
size = SwigType_parm(element);
Append(result, size);
Append(result, "]");
Delete(size);
} else {
if (Strcmp(element, "v(...)") == 0) {
Insert(result, 0, "...");
} else {
String *bs = SwigType_namestr(element);
Insert(result, 0, " ");
Insert(result, 0, bs);
Delete(bs);
}
}
}
element = nextelement;
parm = nextSibling(parm);
}
Delete(elements);
String *rettype = Copy(decl);
String *quals = SwigType_pop_function_qualifiers(rettype);
String *qualifiers = 0;
if (quals)
qualifiers = SwigType_str(quals, 0);
if (is_const) {
if (is_func) {
Append(result, " ");
Append(result, "const");
} else {
Insert(result, 0, "const ");
}
}
String *popped_decl = SwigType_pop_function(rettype);
if (return_base_type)
Append(rettype, return_base_type);
Chop(result);
if (rettype) {
Insert(result, 0, " ");
if (!conversion_operator) {
SwigType *rettype_stripped = SwigType_strip_qualifiers(rettype);
String *rtype = SwigType_str(rettype, 0);
Insert(result, 0, rtype);
Append(result, rtype);
if (SwigType_issimple(rettype_stripped) && return_base_type)
Append(result, " ");
Delete(rtype);
Delete(rettype_stripped);
}
if (id)
Append(result, id);
String *args_string = default_args ? ParmList_str_defaultargs(args) : ParmList_str(args);
Printv(result, "(", args_string, ")", NIL);
if (qualifiers)
Printv(result, " ", qualifiers, NIL);
// Reformat result to how it has been historically
Replaceall(result, ",", ", ");
Replaceall(result, "=", " = ");
Delete(args_string);
Delete(popped_decl);
Delete(qualifiers);
Delete(quals);
Delete(rettype);
return result;
}
@ -272,6 +194,7 @@ String *Swig_method_decl(SwigType *rettype, SwigType *decl, const_String_or_char
* to add an extra dynamic_cast to call the public C++ wrapper in the director class.
* Also for non-static protected members when the allprotected option is on.
* ----------------------------------------------------------------------------- */
void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) {
// TODO: why is the storage element removed in staticmemberfunctionHandler ??
if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) ||
@ -290,13 +213,13 @@ void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) {
}
}
/* ------------------------------------------------------------
/* -----------------------------------------------------------------------------
* Swig_director_parms_fixup()
*
* For each parameter in the C++ member function, copy the parameter name
* to its "lname"; this ensures that Swig_typemap_attach_parms() will do
* the right thing when it sees strings like "$1" in "directorin" typemaps.
* ------------------------------------------------------------ */
* ----------------------------------------------------------------------------- */
void Swig_director_parms_fixup(ParmList *parms) {
Parm *p;

View file

@ -12,6 +12,7 @@
* ----------------------------------------------------------------------------- */
#include "swigmod.h"
#include "cparse.h"
/* -----------------------------------------------------------------------------
* emit_return_variable()
@ -112,9 +113,8 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
/* This is compatibility code to deal with the deprecated "ignore" typemap */
Parm *p = l;
Parm *np;
String *tm;
while (p) {
tm = Getattr(p, "tmap:in");
String *tm = Getattr(p, "tmap:in");
if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
Replaceall(tm, "$target", Getattr(p, "lname"));
Printv(f->code, tm, "\n", NIL);
@ -134,7 +134,6 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
/* Perform a sanity check on "in" and "freearg" typemaps. These
must exactly match to avoid chaos. If a mismatch occurs, we
nuke the freearg typemap */
{
Parm *p = l;
Parm *npin, *npfreearg;
@ -189,13 +188,45 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
p = lp;
while (p) {
if (SwigType_isvarargs(Getattr(p, "type"))) {
// Mark the head of the ParmList that it has varargs
Setattr(l, "emit:varargs", lp);
//Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type"));
break;
}
p = nextSibling(p);
}
}
}
/*
* An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent
* target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer
* are seen as equivalent types in the target language.
*/
{
Parm *p = l;
while (p) {
String *tm = Getattr(p, "tmap:typecheck");
if (tm) {
String *equivalent = Getattr(p, "tmap:typecheck:equivalent");
if (equivalent) {
String *precedence = Getattr(p, "tmap:typecheck:precedence");
if (precedence && Strcmp(precedence, "0") != 0)
Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0));
SwigType *cpt = Swig_cparse_type(equivalent);
if (cpt) {
Setattr(p, "equivtype", cpt);
Delete(cpt);
} else {
Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0));
}
}
p = Getattr(p, "tmap:typecheck:next");
} else {
p = nextSibling(p);
}
}
}
}
/* -----------------------------------------------------------------------------
@ -300,7 +331,8 @@ int emit_num_required(ParmList *parms) {
/* -----------------------------------------------------------------------------
* emit_isvarargs()
*
* Checks if a function is a varargs function
* Checks if a ParmList is a parameter list containing varargs.
* This function requires emit_attach_parmmaps to have been called beforehand.
* ----------------------------------------------------------------------------- */
int emit_isvarargs(ParmList *p) {
@ -311,6 +343,28 @@ int emit_isvarargs(ParmList *p) {
return 0;
}
/* -----------------------------------------------------------------------------
* emit_isvarargs_function()
*
* Checks for varargs in a function/constructor (can be overloaded)
* ----------------------------------------------------------------------------- */
bool emit_isvarargs_function(Node *n) {
bool has_varargs = false;
Node *over = Getattr(n, "sym:overloaded");
if (over) {
for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) {
if (ParmList_has_varargs(Getattr(sibling, "parms"))) {
has_varargs = true;
break;
}
}
} else {
has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false;
}
return has_varargs;
}
/* -----------------------------------------------------------------------------
* void emit_mark_vararg_parms()
*
@ -454,29 +508,29 @@ String *emit_action(Node *n) {
if (catchlist) {
int unknown_catch = 0;
int has_varargs = 0;
Printf(eaction, "}\n");
Printf(eaction, "}");
for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
if (em) {
SwigType *et = Getattr(ep, "type");
SwigType *etr = SwigType_typedef_resolve_all(et);
if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
Printf(eaction, "catch(%s) {", SwigType_str(et, "_e"));
Printf(eaction, " catch(%s) {", SwigType_str(et, "_e"));
} else if (SwigType_isvarargs(etr)) {
Printf(eaction, "catch(...) {");
Printf(eaction, " catch(...) {");
has_varargs = 1;
} else {
Printf(eaction, "catch(%s) {", SwigType_str(et, "&_e"));
Printf(eaction, " catch(%s) {", SwigType_str(et, "&_e"));
}
Printv(eaction, em, "\n", NIL);
Printf(eaction, "}\n");
Printf(eaction, "}");
} else {
Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
unknown_catch = 1;
}
}
if (unknown_catch && !has_varargs) {
Printf(eaction, "catch(...) { throw; }\n");
Printf(eaction, " catch(...) {\nthrow;\n}");
}
}

View file

@ -125,6 +125,8 @@ class GO:public Language {
String *prefix_option;
// -fgo-pkgpath option.
String *pkgpath_option;
// Prefix for translating %import directive to import statements.
String *import_prefix;
// Whether to use a shared library.
bool use_shlib;
// Name of shared library to import.
@ -199,11 +201,12 @@ class GO:public Language {
public:
GO():package(NULL),
module(NULL),
cgo_flag(false),
cgo_flag(true),
gccgo_flag(false),
go_prefix(NULL),
prefix_option(NULL),
pkgpath_option(NULL),
import_prefix(NULL),
use_shlib(false),
soname(NULL),
intgo_type_size(0),
@ -269,6 +272,9 @@ private:
} else if (strcmp(argv[i], "-cgo") == 0) {
Swig_mark_arg(i);
cgo_flag = true;
} else if (strcmp(argv[i], "-no-cgo") == 0) {
Swig_mark_arg(i);
cgo_flag = false;
} else if (strcmp(argv[i], "-gccgo") == 0) {
Swig_mark_arg(i);
gccgo_flag = true;
@ -290,6 +296,15 @@ private:
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-import-prefix") == 0) {
if (argv[i + 1]) {
import_prefix = NewString(argv[i + 1]);
Swig_mark_arg(i);
Swig_mark_arg(i + 1);
i++;
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-use-shlib") == 0) {
Swig_mark_arg(i);
use_shlib = true;
@ -615,6 +630,12 @@ private:
Language::top(n);
if (directorsEnabled()) {
// Insert director runtime into the f_runtime file (make it occur before %header section)
Swig_insert_file("director_common.swg", f_c_runtime);
Swig_insert_file("director.swg", f_c_runtime);
}
Delete(go_imports);
// Write out definitions for the types not defined by SWIG.
@ -734,7 +755,11 @@ private:
if (modname) {
if (!Getattr(go_imports, modname)) {
Setattr(go_imports, modname, modname);
Printv(f_go_imports, "import \"", modname, "\"\n", NULL);
Printv(f_go_imports, "import \"", NULL);
if (import_prefix) {
Printv(f_go_imports, import_prefix, "/", NULL);
}
Printv(f_go_imports, modname, "\"\n", NULL);
}
imported_package = modname;
saw_import = true;
@ -990,7 +1015,7 @@ private:
* overname: The overload string for overloaded function.
* wname: The SWIG wrapped name--the name of the C function.
* base: A list of the names of base classes, in the case where this
* is is a vritual method not defined in the current class.
* is a virtual method not defined in the current class.
* parms: The parameters.
* result: The result type.
* is_static: Whether this is a static method or member.
@ -2445,7 +2470,8 @@ private:
}
String *code = Copy(Getattr(n, "wrap:action"));
Replaceall(code, Getattr(parms, "lname"), current);
Replace(code, Getattr(parms, "lname"), current, DOH_REPLACE_ANY | DOH_REPLACE_ID);
Delete(current);
Printv(actioncode, code, "\n", NULL);
}
@ -2598,6 +2624,14 @@ private:
Replaceall(f->code, "$cleanup", cleanup);
Delete(cleanup);
/* See if there is any return cleanup code */
String *tm;
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
}
@ -2797,34 +2831,53 @@ private:
return SWIG_NOWRAP;
}
String *get = NewString("");
Printv(get, Swig_cresult_name(), " = ", NULL);
char quote;
if (Getattr(n, "wrappedasconstant")) {
quote = '\0';
} else if (SwigType_type(type) == T_CHAR) {
quote = '\'';
} else if (SwigType_type(type) == T_STRING) {
Printv(get, "(char *)", NULL);
quote = '"';
String *rawval = Getattr(n, "rawval");
if (rawval && Len(rawval)) {
// Based on Swig_VargetToFunction
String *nname = NewStringf("(%s)", rawval);
String *call;
if (SwigType_isclass(type)) {
call = NewStringf("%s", nname);
} else {
call = SwigType_lcaststr(type, nname);
}
String *cres = Swig_cresult(type, Swig_cresult_name(), call);
Setattr(n, "wrap:action", cres);
Delete(nname);
Delete(call);
Delete(cres);
} else {
quote = '\0';
String *get = NewString("");
Printv(get, Swig_cresult_name(), " = ", NULL);
char quote;
if (Getattr(n, "wrappedasconstant")) {
quote = '\0';
} else if (SwigType_type(type) == T_CHAR) {
quote = '\'';
} else if (SwigType_type(type) == T_STRING) {
Printv(get, "(char *)", NULL);
quote = '"';
} else {
quote = '\0';
}
if (quote != '\0') {
Printf(get, "%c", quote);
}
Printv(get, Getattr(n, "value"), NULL);
if (quote != '\0') {
Printf(get, "%c", quote);
}
Printv(get, ";\n", NULL);
Setattr(n, "wrap:action", get);
Delete(get);
}
if (quote != '\0') {
Printf(get, "%c", quote);
}
Printv(get, Getattr(n, "value"), NULL);
if (quote != '\0') {
Printf(get, "%c", quote);
}
Printv(get, ";\n", NULL);
Setattr(n, "wrap:action", get);
String *sname = Copy(symname);
if (class_name) {
Append(sname, "_");
@ -3829,12 +3882,11 @@ private:
String *cxx_director_name = NewString("SwigDirector_");
Append(cxx_director_name, class_name);
String *decl = Swig_method_decl(NULL, Getattr(n, "decl"),
cxx_director_name, first_parm, 0, 0);
String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
Printv(f_c_directors_h, " ", decl, ";\n", NULL);
Delete(decl);
decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0, 0);
decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL);
Delete(decl);
@ -4559,7 +4611,7 @@ private:
Append(upcall_method_name, overname);
}
SwigType *rtype = Getattr(n, "classDirectorMethods:type");
String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0, 0);
String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0);
Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
Delete(upcall_decl);
@ -5007,13 +5059,13 @@ private:
// Declare the method for the director class.
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0, 0);
String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0);
Printv(f_c_directors_h, " virtual ", decl, NULL);
Delete(decl);
String *qname = NewString("");
Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), NULL);
decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0, 0);
decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0);
Printv(w->def, decl, NULL);
Delete(decl);
Delete(qname);
@ -5030,7 +5082,19 @@ private:
Printv(w->def, " {\n", NULL);
if (SwigType_type(result) != T_VOID) {
Wrapper_add_local(w, "c_result", SwigType_lstr(result, "c_result"));
if (!SwigType_isclass(result)) {
if (!(SwigType_ispointer(result) || SwigType_isreference(result))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(result, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(result, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
}
}
if (!is_ignored) {
@ -5464,6 +5528,8 @@ private:
*--------------------------------------------------------------------*/
String *buildThrow(Node *n) {
if (Getattr(n, "noexcept"))
return NewString("noexcept");
ParmList *throw_parm_list = Getattr(n, "throws");
if (!throw_parm_list && !Getattr(n, "throw"))
return NULL;
@ -5893,7 +5959,7 @@ private:
*
* Given a C/C++ name, return a name in Go which will be exported.
* If the first character is an upper case letter, this returns a
* copy of its argment. If the first character is a lower case
* copy of its argument. If the first character is a lower case
* letter, this forces it to upper case. Otherwise, this prepends
* 'X'.
* ---------------------------------------------------------------------- */
@ -6213,9 +6279,9 @@ private:
Setattr(undefined_enum_types, t, ret);
Delete(tt);
}
} else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) {
} else if (SwigType_isfunctionpointer(t) || SwigType_isfunction(t)) {
ret = NewString("_swig_fnptr");
} else if (SwigType_ismemberpointer(type)) {
} else if (SwigType_ismemberpointer(t)) {
ret = NewString("_swig_memberptr");
} else if (SwigType_issimple(t)) {
Node *cn = classLookup(t);
@ -6932,9 +6998,11 @@ extern "C" Language *swig_go(void) {
const char * const GO::usage = "\
Go Options (available with -go)\n\
-cgo - Generate cgo input files\n\
-gccgo - Generate code for gccgo rather than 6g/8g\n\
-no-cgo - Do not generate cgo input files\n\
-gccgo - Generate code for gccgo rather than gc\n\
-go-pkgpath <p> - Like gccgo -fgo-pkgpath option\n\
-go-prefix <p> - Like gccgo -fgo-prefix option\n\
-import-prefix <p> - Prefix to add to %import directives\n\
-intgosize <s> - Set size of Go int type--32 or 64 bits\n\
-package <name> - Set name of the Go package to <name>\n\
-use-shlib - Force use of a shared library\n\

View file

@ -151,12 +151,14 @@ void Swig_interface_propagate_methods(Node *n) {
for (Node *child = firstChild(n); child; child = nextSibling(child)) {
if (Getattr(child, "interface:owner"))
break; // at the end of the list are newly appended methods
if (checkAttribute(child, "name", name)) {
String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0;
Delete(decl);
if (identically_overloaded_method)
break;
if (Cmp(nodeType(child), "cdecl") == 0) {
if (checkAttribute(child, "name", name)) {
String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0;
Delete(decl);
if (identically_overloaded_method)
break;
}
}
}
}

View file

@ -15,6 +15,7 @@
#include <limits.h> // for INT_MAX
#include "cparse.h"
#include <ctype.h>
#include "javadoc.h"
/* Hash type used for upcalls from C/C++ */
typedef DOH UpcallData;
@ -46,7 +47,9 @@ class JAVA:public Language {
bool global_variable_flag; // Flag for when wrapping a global variable
bool old_variable_names; // Flag for old style variable names in the intermediary class
bool member_func_flag; // flag set when wrapping a member function
bool doxygen; //flag for converting found doxygen to javadoc
bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx
String *imclass_name; // intermediary class name
String *module_class_name; // module class name
String *constants_interface_name; // constants interface name
@ -72,8 +75,8 @@ class JAVA:public Language {
String *module_baseclass; //inheritance for module class from %pragma
String *imclass_interfaces; //interfaces for intermediary class class from %pragma
String *module_interfaces; //interfaces for module class from %pragma
String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
String *module_class_modifiers; //class modifiers for module class overriden by %pragma
String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
String *module_class_modifiers; //class modifiers for module class overridden by %pragma
String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
String *imclass_directors; // Intermediate class director code
@ -120,6 +123,8 @@ public:
global_variable_flag(false),
old_variable_names(false),
member_func_flag(false),
doxygen(false),
comment_creation_chatter(false),
imclass_name(NULL),
module_class_name(NULL),
constants_interface_name(NULL),
@ -164,11 +169,15 @@ public:
director_multiple_inheritance = 0;
director_language = 1;
}
~JAVA() {
delete doxygenTranslator;
}
/* -----------------------------------------------------------------------------
* constructIntermediateClassName()
*
* Construct the fully qualified name of the intermidiate class and set
* Construct the fully qualified name of the intermediate class and set
* the full_imclass_name attribute accordingly.
* ----------------------------------------------------------------------------- */
void constructIntermediateClassName(Node *n) {
@ -256,6 +265,8 @@ public:
SWIG_library_directory("java");
int doxygen_translator_flags = 0;
// Look for certain command line options
for (int i = 1; i < argc; i++) {
if (argv[i]) {
@ -277,6 +288,16 @@ public:
Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
Swig_mark_arg(i);
proxy_flag = true;
} else if ((strcmp(argv[i], "-doxygen") == 0)) {
Swig_mark_arg(i);
doxygen = true;
scan_doxygen_comments = true;
} else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) {
Swig_mark_arg(i);
doxygen_translator_flags |= DoxygenTranslator::debug_translator;
} else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) {
Swig_mark_arg(i);
doxygen_translator_flags |= DoxygenTranslator::debug_parser;
} else if ((strcmp(argv[i], "-noproxy") == 0)) {
Swig_mark_arg(i);
proxy_flag = false;
@ -300,6 +321,9 @@ public:
}
}
}
if (doxygen)
doxygenTranslator = new JavaDocConverter(doxygen_translator_flags);
// Add a symbol to the parser for conditional compilation
Preprocessor_define("SWIGJAVA 1", 0);
@ -567,6 +591,13 @@ public:
if (module_imports)
Printf(f_module, "%s\n", module_imports);
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
if (comment_creation_chatter)
Printf(f_module, "/* This was generated from top() */\n");
Printv(f_module, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
if (Len(module_class_modifiers) > 0)
Printf(f_module, "%s ", module_class_modifiers);
Printf(f_module, "%s ", module_class_name);
@ -1246,6 +1277,14 @@ public:
if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
if (comment_creation_chatter)
Printf(enum_code, "/* This was generated from enumDeclaration() */\n");
Printv(enum_code, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
String *scope = getCurrentScopeName(nspace);
if (!addSymbol(symname, n, scope))
return SWIG_ERROR;
@ -1265,9 +1304,17 @@ public:
Replaceall(enum_code, "$static ", "");
Delete(scope);
} else {
// Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
if (symname && !Getattr(n, "unnamedinstance"))
Printf(constants_code, " // %s \n", symname);
// Translate and write javadoc comment for the enum itself if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(constants_code, "/* This was generated from enumDeclaration() */\n");
Printf(constants_code, Char(doxygen_comments));
Printf(constants_code, "\n");
Delete(doxygen_comments);
}
}
// Emit each enum item
@ -1418,12 +1465,24 @@ public:
}
if (!addSymbol(symname, n, scope))
return SWIG_ERROR;
if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
if (!GetFlag(n, "firstenumitem"))
Printf(enum_code, ",\n");
}
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n");
Printv(enum_code, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
// Wrap (non-anonymous) C/C++ enum with a proper Java enum
// Emit the enum item.
if (!GetFlag(n, "firstenumitem"))
Printf(enum_code, ",\n");
Printf(enum_code, " %s", symname);
if (Getattr(n, "enumvalue")) {
String *value = enumValue(n);
@ -1497,6 +1556,15 @@ public:
String *constants_code = NewString("");
Swig_save("constantWrapper", n, "value", NIL);
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(constants_code, "/* This was generated from constantWrapper() */\n");
Printv(constants_code, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
@ -1612,10 +1680,22 @@ public:
* ----------------------------------------------------------------------------- */
virtual int insertDirective(Node *n) {
int ret = SWIG_OK;
String *code = Getattr(n, "code");
String *section = Getattr(n, "section");
Replaceall(code, "$module", module_class_name);
Replaceall(code, "$imclassname", imclass_name);
return Language::insertDirective(n);
if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
if (proxy_class_code) {
Swig_typemap_replace_embedded_typemap(code, n);
int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
}
} else {
ret = Language::insertDirective(n);
}
return ret;
}
/* -----------------------------------------------------------------------------
@ -1796,7 +1876,7 @@ public:
Replaceall(cptr_method_name, ".", "_");
Replaceall(cptr_method_name, "$interfacename", interface_name);
String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name);
String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
Delete(upcast_method_name);
Delete(cptr_method_name);
@ -1924,13 +2004,24 @@ public:
// Pure Java interfaces
const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
if (*Char(interface_list) && *Char(pure_interfaces))
Append(interface_list, ", ");
Append(interface_list, pure_interfaces);
// Start writing the proxy class
if (!has_outerclass) // Import statements
Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
else
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
if (comment_creation_chatter)
Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n");
Printv(proxy_class_def, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
if (has_outerclass)
Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
" $javaclassname", // Class name and bases
@ -1944,16 +2035,19 @@ public:
String *destruct = NewString("");
const String *tm = NULL;
attributes = NewHash();
String *destruct_methodname = NULL;
String *destruct_methodmodifiers = NULL;
const String *destruct_methodname = NULL;
const String *destruct_methodmodifiers = NULL;
const String *destruct_parameters = NULL;
if (derived) {
tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters");
} else {
tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters");
}
if (tm && *Char(tm)) {
if (!destruct_methodname) {
@ -1962,6 +2056,8 @@ public:
if (!destruct_methodmodifiers) {
Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
}
if (!destruct_parameters)
destruct_parameters = empty_string;
}
// Emit the finalize and delete methods
if (tm) {
@ -1975,8 +2071,15 @@ public:
Replaceall(destruct, "$jnicall", destructor_call);
else
Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
if (*Char(destruct))
Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", NIL);
if (*Char(destruct)) {
Printv(proxy_class_def, "\n ", NIL);
const String *methodmods = Getattr(n, "destructmethodmodifiers");
if (methodmods)
Printv(proxy_class_def, methodmods, NIL);
else
Printv(proxy_class_def, destruct_methodmodifiers, NIL);
Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL);
}
}
if (*Char(interface_upcasts))
Printv(proxy_class_def, interface_upcasts, NIL);
@ -2260,39 +2363,6 @@ public:
--nesting_depth;
}
/* Output the downcast method, if necessary. Note: There's no other really
good place to put this code, since Abstract Base Classes (ABCs) can and should have
downcasts, making the constructorHandler() a bad place (because ABCs don't get to
have constructors emitted.) */
if (GetFlag(n, "feature:javadowncast")) {
String *downcast_method = Swig_name_member(getNSpace(), getClassPrefix(), "SWIGDowncast");
String *jniname = makeValidJniName(downcast_method);
String *wname = Swig_name_wrapper(jniname);
String *norm_name = SwigType_namestr(Getattr(n, "name"));
Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method);
Wrapper *dcast_wrap = NewWrapper();
Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname);
Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
Printf(dcast_wrap->code, " return jresult;\n");
Printf(dcast_wrap->code, "}\n");
Wrapper_print(dcast_wrap, f_wrappers);
DelWrapper(dcast_wrap);
Delete(norm_name);
Delete(wname);
Delete(jniname);
Delete(downcast_method);
}
if (f_interface) {
Printv(f_interface, interface_class_code, "}\n", NIL);
Delete(f_interface);
@ -2438,6 +2508,15 @@ public:
setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
}
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n");
Printv(function_code, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
/* Start generating the proxy function */
const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
@ -2445,7 +2524,7 @@ public:
if (static_flag)
Printf(function_code, "static ");
Printf(function_code, "%s %s(", return_type, proxy_function_name);
if (is_interface)
Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
@ -2565,8 +2644,6 @@ public:
Printf(imcall, ")");
Printf(function_code, ")");
if (is_interface)
Printf(interface_class_code, ");\n");
// Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
@ -2624,8 +2701,13 @@ public:
Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
}
if (is_interface) {
Printf(interface_class_code, ")");
generateThrowsClause(n, interface_class_code);
Printf(interface_class_code, ";\n");
}
generateThrowsClause(n, function_code);
Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
Printf(function_code, " %s\n\n", tm ? tm : empty_string);
Printv(proxy_class_code, function_code, NIL);
Delete(pre_code);
@ -2670,6 +2752,15 @@ public:
tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
Printf(im_return_type, "%s", tm);
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(function_code, "/* This was generated from constructionhandler() */\n");
Printv(function_code, Char(doxygen_comments), NIL);
Delete(doxygen_comments);
}
Printf(function_code, " %s %s(", methodmods, proxy_class_name);
Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
@ -2778,7 +2869,8 @@ public:
/* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
Hash *attributes = NewHash();
String *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"),
String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type,
WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
if (construct_tm) {
if (!feature_director) {
@ -2848,6 +2940,9 @@ public:
if (proxy_flag) {
Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
generateThrowsClause(n, destructor_throws_clause);
const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
if (methodmods)
Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
}
return SWIG_OK;
}
@ -2931,6 +3026,15 @@ public:
String *pre_code = NewString("");
String *post_code = NewString("");
// Translate and write javadoc comment if flagged
if (doxygen && doxygenTranslator->hasDocumentation(n)) {
String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
if (comment_creation_chatter)
Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n");
Printv(function_code, doxygen_comments, NIL);
Delete(doxygen_comments);
}
if (l) {
if (SwigType_type(Getattr(l, "type")) == T_VOID) {
l = nextSibling(l);
@ -3083,7 +3187,7 @@ public:
}
generateThrowsClause(n, function_code);
Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
Printf(function_code, " %s\n\n", tm ? tm : empty_string);
Printv(module_class_code, function_code, NIL);
Delete(pre_code);
@ -3748,18 +3852,16 @@ public:
Printf(code_wrap->code, " (void)jcls;\n");
Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
}
else {
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
Printf(code_wrap->code, " (void)jcls;\n");
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
}
Printf(code_wrap->code, " if (director) {\n");
Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
"(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
Printf(code_wrap->code, " }\n");
Printf(code_wrap->code, "}\n");
Wrapper_print(code_wrap, f_wrappers);
@ -3778,8 +3880,17 @@ public:
Printf(code_wrap->def,
"SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
jnipackage, jni_imclass_name, changeown_jnimethod_name);
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
if (Len(smartptr)) {
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
} else {
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
}
Printf(code_wrap->code, " (void)jcls;\n");
Printf(code_wrap->code, " if (director) {\n");
Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
@ -3960,15 +4071,17 @@ public:
/* If returning a reference, initialize the pointer to a sane
default - if a Java exception occurs, then the pointer returns
something other than a NULL-initialized reference. */
String *non_ref_type = Copy(returntype);
SwigType *noref_type = SwigType_del_reference(Copy(returntype));
String *noref_ltype = SwigType_lstr(noref_type, 0);
String *return_ltype = SwigType_lstr(returntype, 0);
/* Remove reference and const qualifiers */
Replaceall(non_ref_type, "r.", "");
Replaceall(non_ref_type, "q(const).", "");
Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
Delete(non_ref_type);
Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
Printf(w->code, "c_result = &result_default;\n");
Delete(return_ltype);
Delete(noref_ltype);
Delete(noref_type);
}
Delete(base_typename);
@ -4059,7 +4172,7 @@ public:
Swig_typemap_attach_parms("out", l, 0);
Swig_typemap_attach_parms("jni", l, 0);
Swig_typemap_attach_parms("jtype", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("javadirectorin", l, 0);
Swig_typemap_attach_parms("directorargout", l, w);
@ -4258,11 +4371,11 @@ public:
/* header declaration, start wrapper definition */
String *target;
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
@ -4281,6 +4394,10 @@ public:
}
}
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0;
@ -4387,7 +4504,7 @@ public:
for (p = l; p;) {
if ((tm = Getattr(p, "tmap:directorargout"))) {
addThrows(n, "tmap:directorargout", p);
Replaceall(tm, "$result", "jresult");
Replaceall(tm, "$result", makeParameterName(n, p, i, false));
Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
Printv(w->code, tm, "\n", NIL);
p = Getattr(p, "tmap:directorargout:next");
@ -4472,9 +4589,9 @@ public:
if (!directorexcept) {
directorexcept = NewString("");
Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n");
Printf(directorexcept, "if ($error) {\n");
Printf(directorexcept, " jenv->ExceptionClear();$directorthrowshandlers\n");
Printf(directorexcept, " throw Swig::DirectorException(jenv, $error);\n");
Printf(directorexcept, "if ($error) {");
Printf(directorexcept, "$directorthrowshandlers\n");
Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n");
Printf(directorexcept, "}\n");
} else {
directorexcept = Copy(directorexcept);
@ -4573,7 +4690,7 @@ public:
/* constructor */
{
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
String *call = Swig_csuperclass_call(0, basetype, superparms);
String *classtype = SwigType_namestr(Getattr(n, "name"));
@ -4587,7 +4704,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -4659,9 +4776,12 @@ public:
String *dirClassName = directorClassName(current_class);
Wrapper *w = NewWrapper();
if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw ();\n", dirClassName);
Printf(w->def, "%s::~%s() throw () {\n", dirClassName, dirClassName);
if (Getattr(n, "noexcept")) {
Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName);
Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName);
} else if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw();\n", dirClassName);
Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName);
} else {
Printf(f_directors_h, " virtual ~%s();\n", dirClassName);
Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName);
@ -4864,6 +4984,9 @@ extern "C" Language *swig_java(void) {
const char *JAVA::usage = "\
Java Options (available with -java)\n\
-doxygen - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\
-debug-doxygen-parser - Display doxygen parser module debugging information\n\
-debug-doxygen-translator - Display doxygen translator module debugging information\n\
-nopgcpp - Suppress premature garbage collection prevention parameter\n\
-noproxy - Generate the low-level functional interface instead\n\
of proxy classes\n\

View file

@ -33,6 +33,7 @@ static bool js_template_enable_debug = false;
#define GETTER "getter"
#define SETTER "setter"
#define PARENT "parent"
#define PARENT_MANGLED "parent_mangled"
#define CTOR "ctor"
#define CTOR_WRAPPERS "ctor_wrappers"
#define CTOR_DISPATCHERS "ctor_dispatchers"
@ -262,7 +263,7 @@ protected:
virtual int createNamespace(String *scope);
virtual Hash *createNamespaceEntry(const char *name, const char *parent);
virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
virtual int emitNamespaces() = 0;
@ -462,10 +463,10 @@ int JAVASCRIPT::fragmentDirective(Node *n) {
// and register them at the emitter.
String *section = Getattr(n, "section");
if (Equal(section, "templates")) {
if (Equal(section, "templates") && !ImportMode) {
emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code"));
} else {
Swig_fragment_register(n);
return Language::fragmentDirective(n);
}
return SWIG_OK;
@ -552,7 +553,7 @@ void JAVASCRIPT::main(int argc, char *argv[]) {
emitter = swig_javascript_create_V8Emitter();
Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0);
SWIG_library_directory("javascript/v8");
// V8 API is C++, so output must be C++ compatibile even when wrapping C code
// V8 API is C++, so output must be C++ compatible even when wrapping C code
if (!cparse_cplusplus) {
Swig_cparse_cplusplusout(1);
}
@ -664,7 +665,7 @@ int JSEmitter::initialize(Node * /*n */ ) {
Delete(namespaces);
}
namespaces = NewHash();
Hash *global_namespace = createNamespaceEntry("exports", 0);
Hash *global_namespace = createNamespaceEntry("exports", 0, 0);
Setattr(namespaces, "::", global_namespace);
current_namespace = global_namespace;
@ -993,7 +994,7 @@ int JSEmitter::emitDtor(Node *n) {
Also, there is a problem where destructor_action is always true for me, even when not requesting %extend as above.
So this code doesn't actually quite work as I expect. The end result is that the code still works because
destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is wierd.
destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is weird.
I think there is a deeper underlying SWIG issue because I don't think it should be char*. However, it doesn't really matter for free.
Maybe the fix for the destructor_action always true problem is that this is supposed to be embedded in the if(Extend) block above.
@ -1124,7 +1125,7 @@ int JSEmitter::emitConstant(Node *n) {
Template t_getter(getTemplate("js_getter"));
// call the variable methods as a constants are
// registred in same way
// registered in same way
enterVariable(n);
state.variable(GETTER, wname);
// TODO: why do we need this?
@ -1354,6 +1355,11 @@ void JSEmitter::emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params) {
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Printf(wrapper->code, "%s\n", tm);
Delete(tm);
}
}
int JSEmitter::switchNamespace(Node *n) {
@ -1423,19 +1429,20 @@ int JSEmitter::createNamespace(String *scope) {
}
assert(parent_namespace != 0);
Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name")));
Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name")), Char(Getattr(parent_namespace, "name_mangled")));
Setattr(namespaces, scope, new_namespace);
Delete(parent_scope);
return SWIG_OK;
}
Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent) {
Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent, const char *parent_mangled) {
Hash *entry = NewHash();
String *name = NewString(_name);
Setattr(entry, NAME, Swig_scopename_last(name));
Setattr(entry, NAME_MANGLED, Swig_name_mangle(name));
Setattr(entry, PARENT, NewString(parent));
Setattr(entry, PARENT_MANGLED, NewString(parent_mangled));
Delete(name);
return entry;
@ -1462,7 +1469,7 @@ protected:
virtual int enterClass(Node *n);
virtual int exitClass(Node *n);
virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
virtual Hash *createNamespaceEntry(const char *name, const char *parent);
virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
virtual int emitNamespaces();
private:
@ -1768,8 +1775,8 @@ int JSCEmitter::exitClass(Node *n) {
return SWIG_OK;
}
Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent) {
Hash *entry = JSEmitter::createNamespaceEntry(name, parent);
Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled) {
Hash *entry = JSEmitter::createNamespaceEntry(name, parent, parent_mangled);
Setattr(entry, "functions", NewString(""));
Setattr(entry, "values", NewString(""));
return entry;
@ -1781,8 +1788,7 @@ int JSCEmitter::emitNamespaces() {
Hash *entry = it.item;
String *name = Getattr(entry, NAME);
String *name_mangled = Getattr(entry, NAME_MANGLED);
String *parent = Getattr(entry, PARENT);
String *parent_mangled = Swig_name_mangle(parent);
String *parent_mangled = Getattr(entry, PARENT_MANGLED);
String *functions = Getattr(entry, "functions");
String *variables = Getattr(entry, "values");
@ -2032,7 +2038,7 @@ int V8Emitter::exitClass(Node *n) {
.pretty_print(f_init_inheritance);
Delete(base_name_mangled);
}
// emit registeration of class template
// emit registration of class template
Template t_register = getTemplate("jsv8_register_class");
t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
.replace("$jsname", state.clazz(NAME))
@ -2201,7 +2207,7 @@ int V8Emitter::emitNamespaces() {
String *name = Getattr(entry, NAME);
String *name_mangled = Getattr(entry, NAME_MANGLED);
String *parent = Getattr(entry, PARENT);
String *parent_mangled = Swig_name_mangle(parent);
String *parent_mangled = Getattr(entry, PARENT_MANGLED);
bool do_create = true;
bool do_register = true;
@ -2422,7 +2428,7 @@ Template & Template::trim() {
/* -----------------------------------------------------------------------------
* Template& Template::replace(const String* pattern, const String* repl) :
*
* replaces all occurences of a given pattern with a given replacement.
* replaces all occurrences of a given pattern with a given replacement.
*
* - pattern: the pattern to be replaced
* - repl: the replacement string

View file

@ -81,7 +81,6 @@ extern int AddExtern;
/* import modes */
#define IMPORT_MODE 1
#define IMPORT_MODULE 2
/* ----------------------------------------------------------------------
* Dispatcher::emit_one()
@ -308,15 +307,12 @@ int Dispatcher::namespaceDeclaration(Node *n) {
return defaultHandler(n);
}
/* Allocators */
Language::Language():
none_comparison(NewString("$arg != 0")),
director_ctor_code(NewString("")),
director_prot_ctor_code(0),
symtabs(NewHash()),
classtypes(NewHash()),
enumtypes(NewHash()),
overloading(0),
multiinput(0),
cplus_runtime(0),
@ -337,12 +333,12 @@ directors(0) {
director_language = 0;
assert(!this_);
this_ = this;
doxygenTranslator = NULL;
}
Language::~Language() {
Delete(symtabs);
Delete(classtypes);
Delete(enumtypes);
Delete(director_ctor_code);
Delete(none_comparison);
this_ = 0;
@ -625,7 +621,8 @@ int Language::constantDirective(Node *n) {
* ---------------------------------------------------------------------- */
int Language::fragmentDirective(Node *n) {
Swig_fragment_register(n);
if (!(Getattr(n, "emitonly") && ImportMode))
Swig_fragment_register(n);
return SWIG_OK;
}
@ -870,7 +867,7 @@ int Language::cDeclaration(Node *n) {
} else {
// Found an unignored templated method that has an empty template instantiation (%template())
// Ignore it unless it has been %rename'd
if (Strncmp(symname, "__dummy_", 8) == 0) {
if (Strncmp(symname, "__dummy_", 8) == 0 && Cmp(storage, "typedef") != 0) {
SetFlag(n, "feature:ignore");
Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number,
"%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n));
@ -1084,6 +1081,8 @@ int Language::functionHandler(Node *n) {
globalfunctionHandler(n);
InClass = oldInClass;
} else {
// This is a member function, set a flag so the documentation type is correct
SetFlag(n, "memberfunction");
Node *explicit_n = 0;
if (directorsEnabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) {
bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
@ -1145,7 +1144,9 @@ int Language::globalfunctionHandler(Node *n) {
Delete(cbname);
}
Setattr(n, "parms", nonvoid_parms(parms));
String *call = Swig_cfunction_call(name, parms);
String *extendname = Getattr(n, "extendname");
String *call = Swig_cfunction_call(extendname ? extendname : name, parms);
String *cres = Swig_cresult(type, Swig_cresult_name(), call);
Setattr(n, "wrap:action", cres);
Delete(cres);
@ -1267,9 +1268,13 @@ int Language::memberfunctionHandler(Node *n) {
if (GetFlag(n, "explicitcall"))
DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL;
Swig_MethodToFunction(n, NSpace, ClassType, Getattr(n, "template") ? SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type,
is_member_director(CurrentClass, n));
int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
int flags = Getattr(n, "template") ? extendmember | SmartPointer : Extend | SmartPointer | DirectorExtraCall;
Swig_MethodToFunction(n, NSpace, ClassType, flags, director_type, is_member_director(CurrentClass, n));
Setattr(n, "sym:name", fname);
/* Explicitly save low-level and high-level documentation names */
Setattr(n, "doc:low:name", fname);
Setattr(n, "doc:high:name", symname);
functionWrapper(n);
@ -1321,12 +1326,18 @@ int Language::staticmemberfunctionHandler(Node *n) {
if (!defaultargs && code) {
/* Hmmm. An added static member. We have to create a little wrapper for this */
Swig_add_extension_code(n, cname, parms, type, code, CPlusPlus, 0);
String *mangled_cname = Swig_name_mangle(cname);
Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0);
Setattr(n, "extendname", mangled_cname);
Delete(mangled_cname);
}
}
Setattr(n, "name", cname);
Setattr(n, "sym:name", mrename);
/* Explicitly save low-level and high-level documentation names */
Setattr(n, "doc:low:name", mrename);
Setattr(n, "doc:high:name", symname);
if (cb) {
String *cbname = NewStringf(cb, symname);
@ -1883,6 +1894,8 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
}
if (!checkAttribute(nn, "storage", "virtual"))
continue;
if (GetFlag(nn, "final"))
continue;
/* we need to add methods(cdecl) and destructor (to check for throw decl) */
int is_destructor = (Cmp(nodeType, "destructor") == 0);
if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
@ -1943,7 +1956,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
generation of 'empty' director classes.
But this has to be done outside the previous 'for'
an the recursive loop!.
and the recursive loop!.
*/
if (n == parent) {
int len = Len(vm);
@ -2072,7 +2085,7 @@ int Language::classDirectorConstructors(Node *n) {
needed, since there is a public constructor already defined.
(scottm) This code is needed here to make the director_abstract +
test generate compilable code (Example2 in director_abastract.i).
test generate compilable code (Example2 in director_abstract.i).
(mmatus) This is very strange, since swig compiled with gcc3.2.3
doesn't need it here....
@ -2098,7 +2111,7 @@ int Language::classDirectorMethods(Node *n) {
Node *item = Getitem(vtable, i);
String *method = Getattr(item, "methodNode");
String *fqdname = Getattr(item, "fqdname");
if (GetFlag(method, "feature:nodirector"))
if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final"))
continue;
String *wrn = Getattr(method, "feature:warnfilter");
@ -2145,8 +2158,8 @@ int Language::classDirectorDestructor(Node *n) {
File *f_directors = Swig_filebyname("director");
File *f_directors_h = Swig_filebyname("director_h");
if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() throw () {\n}\n\n", DirectorClassName, DirectorClassName);
Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() throw() {\n}\n\n", DirectorClassName, DirectorClassName);
} else {
Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName);
@ -2187,6 +2200,16 @@ int Language::classDirector(Node *n) {
String *using_protected_members_code = NewString("");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
Node *nodeType = Getattr(ni, "nodeType");
if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) {
String *classtype = Getattr(n, "classtype");
SWIG_WARN_NODE_BEGIN(ni);
Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor %s is final, %s cannot be a director class.\n", Swig_name_decl(ni), classtype);
SWIG_WARN_NODE_END(ni);
SetFlag(n, "feature:nodirector");
Delete(vtable);
Delete(using_protected_members_code);
return SWIG_OK;
}
bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
if (isNonVirtualProtectedAccess(ni)) {
@ -2785,7 +2808,9 @@ int Language::constructorHandler(Node *n) {
Setattr(n, "handled_as_constructor", "1");
}
Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend, DirectorClassName);
int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
int flags = Getattr(n, "template") ? extendmember : Extend;
Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, flags, DirectorClassName);
Setattr(n, "sym:name", mrename);
functionWrapper(n);
Delete(mrename);
@ -3256,11 +3281,13 @@ Node *Language::symbolLookup(const String *s, const_String_or_char_ptr scope) {
* Tries to locate a class from a type definition
* ----------------------------------------------------------------------------- */
Node *Language::classLookup(const SwigType *s) const {
Node *Language::classLookup(const SwigType *s) {
static Hash *classtypes = 0;
Node *n = 0;
/* Look in hash of cached values */
n = Getattr(classtypes, s);
n = classtypes ? Getattr(classtypes, s) : 0;
if (!n) {
Symtab *stab = 0;
SwigType *ty1 = SwigType_typedef_resolve_all(s);
@ -3288,6 +3315,14 @@ Node *Language::classLookup(const SwigType *s) const {
break;
if (Strcmp(nodeType(n), "class") == 0)
break;
Node *sibling = n;
while (sibling) {
sibling = Getattr(sibling, "csym:nextSibling");
if (sibling && Strcmp(nodeType(sibling), "class") == 0)
break;
}
if (sibling)
break;
n = parentNode(n);
if (!n)
break;
@ -3300,7 +3335,7 @@ Node *Language::classLookup(const SwigType *s) const {
}
if (n) {
/* Found a match. Look at the prefix. We only allow
the cases where where we want a proxy class for the particular type */
the cases where we want a proxy class for the particular type */
bool acceptable_prefix =
(Len(prefix) == 0) || // simple type (pass by value)
(Strcmp(prefix, "p.") == 0) || // pointer
@ -3315,6 +3350,8 @@ Node *Language::classLookup(const SwigType *s) const {
}
if (acceptable_prefix) {
SwigType *cs = Copy(s);
if (!classtypes)
classtypes = NewHash();
Setattr(classtypes, cs, n);
Delete(cs);
} else {
@ -3341,10 +3378,12 @@ Node *Language::classLookup(const SwigType *s) const {
* ----------------------------------------------------------------------------- */
Node *Language::enumLookup(SwigType *s) {
static Hash *enumtypes = 0;
Node *n = 0;
/* Look in hash of cached values */
n = Getattr(enumtypes, s);
n = enumtypes ? Getattr(enumtypes, s) : 0;
if (!n) {
Symtab *stab = 0;
SwigType *lt = SwigType_ltype(s);
@ -3385,6 +3424,8 @@ Node *Language::enumLookup(SwigType *s) {
if (n) {
/* Found a match. Look at the prefix. We only allow simple types. */
if (Len(prefix) == 0) { /* Simple type */
if (!enumtypes)
enumtypes = NewHash();
Setattr(enumtypes, Copy(s), n);
} else {
n = 0;
@ -3505,7 +3546,7 @@ int Language::need_nonpublic_ctor(Node *n) {
Note: given all the complications here, I am always in favor to
always enable 'dirprot', since is the C++ idea of protected
members, and use %ignore for the method you don't whan to add in
members, and use %ignore for the method you don't want to add in
the director class.
*/
if (directorsEnabled()) {
@ -3581,7 +3622,7 @@ String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter)
String *arg = 0;
String *pn = Getattr(p, "name");
// Use C parameter name unless it is a duplicate or an empty parameter name
// Check if parameter name is a duplicate.
int count = 0;
ParmList *plist = Getattr(n, "parms");
while (plist) {
@ -3589,8 +3630,14 @@ String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter)
count++;
plist = nextSibling(plist);
}
String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
// If the parameter has no name at all or has a non-unique name, replace it with "argN".
if (!pn || count > 1) {
arg = NewStringf("arg%d", arg_num);
} else {
// Otherwise, try to use the original C name, but modify it if necessary to avoid conflicting with the language keywords.
arg = Swig_name_make(p, 0, pn, 0, 0);
}
if (setter && Cmp(arg, "self") != 0) {
// Some languages (C#) insist on calling the input variable "value" while
@ -3765,7 +3812,7 @@ int Language::abstractClassTest(Node *n) {
if (dirabstract) {
if (is_public(dirabstract)) {
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),
"Director class '%s' is abstract, abstract method '%s' is not accesible, maybe due to multiple inheritance or 'nodirector' feature\n",
"Director class '%s' is abstract, abstract method '%s' is not accessible, maybe due to multiple inheritance or 'nodirector' feature\n",
SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name"));
} else {
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),

View file

@ -141,7 +141,7 @@ private:
// This variable holds the name of the current class in Lua. Usually it is
// the same as C++ class name, but rename directives can change it.
String *proxy_class_name;
// This is a so calld fully qualified symname - the above proxy class name
// This is a so called fully qualified symname - the above proxy class name
// prepended with class namespace. If class Lua name is the same as class C++ name,
// then it is basically C++ fully qualified name with colons replaced with dots.
String *full_proxy_class_name;
@ -1359,7 +1359,7 @@ public:
String *rt = Copy(getClassType());
SwigType_add_pointer(rt);
// Adding class to apropriate namespace
// Adding class to appropriate namespace
registerClass(nspace, wrap_class_name);
Hash *nspaceHash = getCArraysHash(nspace);
@ -1461,7 +1461,7 @@ public:
assert(proxy_class_name);
assert(full_proxy_class_name);
// Then print class isntance part
// Then print class instance part
Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_proxy_class_name, "_bases[] = {", base_class, "0};\n", NIL);
Delete(base_class);
Printv(f_wrappers, "static const char *swig_", mangled_full_proxy_class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
@ -1755,7 +1755,7 @@ public:
*
* This is to convert the string of Lua code into a proper string, which can then be
* emitted into the C/C++ code.
* Basically is is a lot of search & replacing of odd sequences
* Basically it is a lot of search & replacing of odd sequences
* ---------------------------------------------------------------------------- */
void escapeCode(String *str) {
@ -1770,7 +1770,7 @@ public:
/* -----------------------------------------------------------------------------
* rawGetCArraysHash(String *name)
*
* A small helper to hide impelementation of how CArrays hashes are stored
* A small helper to hide implementation of how CArrays hashes are stored
* ---------------------------------------------------------------------------- */
Hash *rawGetCArraysHash(const_String_or_char_ptr name) {
@ -2110,7 +2110,7 @@ public:
// variable in resulting file
getCArraysHash(0);
}
// Because we cant access directly 'symtabs', instead we access
// Because we can't directly access 'symtabs', instead we access
// top-level scope and look on all scope pseudo-symbols in it.
Hash *top_scope = symbolScopeLookup("");
assert(top_scope);
@ -2193,7 +2193,7 @@ public:
String *luaCurrentSymbolNSpace() {
String *scope = 0;
// If ouside class, than NSpace is used.
// If outside class, than NSpace is used.
// If inside class, but current[NO_CPP], then this is friend function. It belongs to NSpace
if (!getCurrentClass() || current[NO_CPP]) {
scope = getNSpace();

View file

@ -38,14 +38,15 @@ int NoExcept = 0;
int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime
/* Suppress warning messages for private inheritance, preprocessor evaluation etc...
WARN_PP_EVALUATION 202
WARN_PARSE_PRIVATE_INHERIT 309
WARN_TYPE_ABSTRACT 403
WARN_LANG_OVERLOAD_CONST 512
WARN_PARSE_BUILTIN_NAME 321
WARN_PARSE_REDUNDANT 322
WARN_PP_EVALUATION 202
WARN_PARSE_PRIVATE_INHERIT 309
WARN_PARSE_BUILTIN_NAME 321
WARN_PARSE_REDUNDANT 322
WARN_TYPE_ABSTRACT 403
WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405
WARN_LANG_OVERLOAD_CONST 512
*/
#define EXTRA_WARNINGS "202,309,403,512,321,322"
#define EXTRA_WARNINGS "202,309,403,405,512,321,322"
extern "C" {
extern String *ModuleName;
@ -64,7 +65,7 @@ static const char *usage1 = (const char *) "\
-copyctor - Automatically generate copy constructors wherever possible\n\
-cpperraswarn - Treat the preprocessor #error statement as #warning (default)\n\
-cppext <ext> - Change file extension of generated C++ files to <ext>\n\
(default is cxx, except for PHP which uses cpp)\n\
(default is cxx)\n\
-copyright - Display copyright notices\n\
-debug-classes - Display information about the classes found in the interface\n\
-debug-module <n>- Display module parse tree at stages 1-4, <n> is a csv list of stages\n\
@ -96,7 +97,7 @@ static const char *usage2 = (const char *) "\
-Fmicrosoft - Display error/warning messages in Microsoft format\n\
-Fstandard - Display error/warning messages in commonly used format\n\
-fvirtual - Compile in virtual elimination mode\n\
-help - This output\n\
-help - Display help\n\
-I- - Don't search the current directory\n\
-I<dir> - Look for SWIG files in directory <dir>\n\
-ignoremissing - Ignore missing include files\n\
@ -129,14 +130,14 @@ static const char *usage3 = (const char *) "\
";
static const char *usage4 = (const char *) "\
-O - Enable the optimization options: \n\
-fastdispatch -fvirtual \n\
-O - Enable the optimization options:\n\
-fastdispatch -fvirtual\n\
-o <outfile> - Set name of C/C++ output file to <outfile>\n\
-oh <headfile> - Set name of C++ output header file for directors to <headfile>\n\
-outcurrentdir - Set default output dir to current dir instead of input file's path\n\
-outdir <dir> - Set language specific files output directory to <dir>\n\
-pcreversion - Display PCRE version information\n\
-small - Compile in virtual elimination & compact mode\n\
-small - Compile in virtual elimination and compact mode\n\
-swiglib - Report location of SWIG library and exit\n\
-templatereduce - Reduce all the typedefs in templates\n\
-v - Run in verbose mode\n\
@ -154,10 +155,14 @@ Options can also be defined using the SWIG_FEATURES environment variable, for ex
$ export SWIG_FEATURES\n\
$ swig -python interface.i\n\
\n\
is equivalent to: \n\
is equivalent to:\n\
\n\
$ swig -Wall -python interface.i \n\
$ swig -Wall -python interface.i\n\
\n\
Arguments may also be passed in a file, separated by whitespace. For example:\n\
\n\
$ echo \"-Wall -python interface.i\" > args.txt\n\
$ swig @args.txt\n\
\n";
// Local variables
@ -454,7 +459,7 @@ static void SWIG_dump_runtime() {
SWIG_exit(EXIT_SUCCESS);
}
void SWIG_getoptions(int argc, char *argv[]) {
static void getoptions(int argc, char *argv[]) {
int i;
// Get options
for (i = 1; i < argc; i++) {
@ -873,7 +878,7 @@ void SWIG_getoptions(int argc, char *argv[]) {
}
}
int SWIG_main(int argc, char *argv[], Language *l) {
int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) {
char *c;
/* Initialize the SWIG core */
@ -885,7 +890,9 @@ int SWIG_main(int argc, char *argv[], Language *l) {
// Initialize the preprocessor
Preprocessor_init();
lang = l;
// Set lang to a dummy value if no target language was specified so we
// can process options enough to handle -version, etc.
lang = tlm ? tlm->fac() : new Language;
// Set up some default symbols (available in both SWIG interface files
// and C files)
@ -918,9 +925,9 @@ int SWIG_main(int argc, char *argv[], Language *l) {
Wrapper_director_protected_mode_set(1);
// Inform the parser if the nested classes should be ignored unless explicitly told otherwise via feature:flatnested
ignore_nested_classes = l->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0;
ignore_nested_classes = lang->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0;
kwargs_supported = l->kwargsSupport() ? 1 : 0;
kwargs_supported = lang->kwargsSupport() ? 1 : 0;
// Create Library search directories
@ -949,7 +956,7 @@ int SWIG_main(int argc, char *argv[], Language *l) {
/* Check for SWIG_FEATURES environment variable */
SWIG_getoptions(argc, argv);
getoptions(argc, argv);
// Define the __cplusplus symbol
if (CPlusPlus)
@ -962,6 +969,7 @@ int SWIG_main(int argc, char *argv[], Language *l) {
Printf(stdout, "\nNote: 'swig -<lang> -help' displays options for a specific target language.\n\n");
SWIG_exit(EXIT_SUCCESS); // Exit if we're in help mode
}
// Check all of the options to make sure we're cool.
// Don't check for an input file if -external-runtime is passed
Swig_check_options(external_runtime ? 0 : 1);
@ -1057,7 +1065,7 @@ int SWIG_main(int argc, char *argv[], Language *l) {
char *cfile = Char(input_file);
if (cfile && cfile[0] == '-') {
Printf(stderr, "Unable to find option or file '%s', ", input_file);
Printf(stderr, "use 'swig -help' for more information.\n");
Printf(stderr, "Use 'swig -help' for more information.\n");
} else {
Printf(stderr, "Unable to find file '%s'.\n", input_file);
}
@ -1066,6 +1074,13 @@ int SWIG_main(int argc, char *argv[], Language *l) {
Swig_warning(WARN_DEPRECATED_INPUT_FILE, "SWIG", 1, "Use of the include path to find the input file is deprecated and will not work with ccache. Please include the path when specifying the input file.\n"); // so that behaviour is like c/c++ compilers
}
}
if (!tlm) {
Printf(stderr, "No target language specified.\n");
Printf(stderr, "Use 'swig -help' for more information.\n");
SWIG_exit(EXIT_FAILURE);
}
if (!no_cpp) {
fclose(df);
Printf(fs, "%%include <swig.swg>\n");
@ -1300,6 +1315,13 @@ int SWIG_main(int argc, char *argv[], Language *l) {
// Check the extension for a c/c++ file. If so, we're going to declare everything we see as "extern"
ForceExtern = check_extension(input_file);
if (tlm->status == Experimental) {
Swig_warning(WARN_LANG_EXPERIMENTAL, "SWIG", 1, "Experimental target language. "
"Target language %s specified by %s is an experimental language. "
"Please read about SWIG experimental languages, http://swig.org/Doc4.0/Introduction.html#Introduction_experimental_status.\n",
tlm->help ? tlm->help : "", tlm->name);
}
lang->top(top);
if (browse) {

View file

@ -219,8 +219,8 @@ private:
String *module_baseclass; //inheritance for module class from %pragma
String *m3raw_interfaces; //interfaces for intermediary class class from %pragma
String *module_interfaces; //interfaces for module class from %pragma
String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma
String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma
String *m3raw_class_modifiers; //class modifiers for intermediary class overridden by %pragma
String *m3wrap_modifiers; //class modifiers for module class overridden by %pragma
String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
String *destructor_call; //C++ destructor call if any
@ -822,7 +822,7 @@ MODULA3():
Printf(file, "\n");
Printf(file, "int main (int argc, char *argv[]) {\n");
Printf(file, "\
/*This progam must work for floating point numbers and integers.\n\
/*This program must work for floating point numbers and integers.\n\
Thus all numbers are converted to double precision floating point format.*/\n");
scanConstant(file, n);
Printf(file, " return 0;\n");
@ -3214,7 +3214,7 @@ MODULA3():
tm = Getattr(p, "tmap:m3wrapargvar");
if (tm != NIL) {
/* exceptions that may be raised but can't be catched,
/* exceptions that may be raised but can't be caught,
thus we won't count them in num_exceptions */
addImports(m3wrap_impl.import, "m3wrapargvar", p);
addThrows(throws_hash, "m3wrapargvar", p);

View file

@ -1,59 +0,0 @@
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* module.cxx
*
* This file is responsible for the module system.
* ----------------------------------------------------------------------------- */
#include "swigmod.h"
struct Module {
ModuleFactory fac;
char *name;
Module *next;
Module(const char *n, ModuleFactory f) {
fac = f;
name = new char[strlen(n) + 1];
strcpy(name, n);
next = 0;
} ~Module() {
delete[]name;
}
};
static Module *modules = 0;
/* -----------------------------------------------------------------------------
* void Swig_register_module()
*
* Register a module.
* ----------------------------------------------------------------------------- */
void Swig_register_module(const char *n, ModuleFactory f) {
Module *m = new Module(n, f);
m->next = modules;
modules = m;
}
/* -----------------------------------------------------------------------------
* Language *Swig_find_module()
*
* Given a command line option, locates the factory function.
* ----------------------------------------------------------------------------- */
ModuleFactory Swig_find_module(const char *name) {
Module *m = modules;
while (m) {
if (strcmp(m->name, name) == 0) {
return m->fac;
}
m = m->next;
}
return 0;
}

View file

@ -17,12 +17,10 @@
static const char *usage = "\
Mzscheme Options (available with -mzscheme)\n\
-declaremodule - Create extension that declares a module\n\
-dynamic-load <library>,[library,...] - Do not link with these libraries, dynamic load\n\
them\n\
-noinit - Do not emit scheme_initialize, scheme_reload,\n\
scheme_module_name functions\n\
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
-declaremodule - Create extension that declares a module\n\
-dynamic-load <lib>,[lib,...] - Do not link with these libraries, dynamic load them\n\
-noinit - Do not emit module initialization code\n\
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
";
static String *fieldnames_tab = 0;
@ -223,7 +221,6 @@ public:
Wrapper *f = NewWrapper();
String *proc_name = NewString("");
String *source = NewString("");
String *target = NewString("");
String *arg = NewString("");
String *cleanup = NewString("");
@ -314,10 +311,9 @@ public:
String *ln = Getattr(p, "lname");
// Produce names of source and target
Clear(source);
Clear(target);
Clear(arg);
Printf(source, "argv[%d]", i);
String *source = NewStringf("argv[%d]", i);
Printf(target, "%s", ln);
Printv(arg, Getattr(p, "name"), NIL);
@ -341,6 +337,7 @@ public:
if (i >= numreq) {
Printf(f->code, "}\n");
}
Delete(source);
}
/* Insert constraint checking code */
@ -439,9 +436,8 @@ public:
sprintf(temp, "%d", numargs);
if (exporting_destructor) {
Printf(init_func_def, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname);
} else {
Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs);
}
Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs);
} else {
if (!Getattr(n, "sym:nextSibling")) {
/* Emit overloading dispatch function */
@ -457,6 +453,7 @@ public:
Printv(df->def, "static Scheme_Object *\n", dname, "(int argc, Scheme_Object **argv) {", NIL);
Printv(df->code, dispatch, "\n", NIL);
Printf(df->code, "scheme_signal_error(\"No matching function for overloaded '%s'\");\n", iname);
Printf(df->code, "return NULL;\n", iname);
Printv(df->code, "}\n", NIL);
Wrapper_print(df, f_wrappers);
Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, dname, proc_name, 0, maxargs);
@ -467,7 +464,6 @@ public:
}
Delete(proc_name);
Delete(source);
Delete(target);
Delete(arg);
Delete(outarg);
@ -528,7 +524,7 @@ public:
Replaceall(tm, "$source", "argv[0]");
Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "argv[0]");
/* Printv(f->code, tm, "\n",NIL); */
Replaceall(tm, "$argnum", "1");
emit_action_code(n, f->code, tm);
} else {
throw_unhandled_mzscheme_type_error(t);
@ -765,7 +761,7 @@ public:
/* ------------------------------------------------------------
* validIdentifer()
* validIdentifier()
* ------------------------------------------------------------ */
virtual int validIdentifier(String *s) {

View file

@ -68,7 +68,7 @@ public:
director_prot_ctor_code = NewString("");
Printv(director_prot_ctor_code,
"if ( $comparison ) { /* subclassed */\n",
" $director_new \n", "} else {\n", " failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL);
" $director_new \n", "} else {\n", " caml_failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL);
director_multiple_inheritance = 1;
director_language = 1;
}
@ -167,6 +167,12 @@ public:
return declaration;
}
void emitBanner(File *f) {
Printf(f, "(* ----------------------------------------------------------------------------\n");
Swig_banner_target_lang(f, " *");
Printf(f, " * ---------------------------------------------------------------------------- *)\n\n");
}
/* ------------------------------------------------------------
* top()
*
@ -196,6 +202,7 @@ public:
* use %module(directors="1") modulename at the start of the
* interface file to enable director generation.
*/
String *mod_docstring = NULL;
{
Node *module = Getattr(n, "module");
if (module) {
@ -210,6 +217,7 @@ public:
if (Getattr(options, "sizeof")) {
generate_sizeof = 1;
}
mod_docstring = Getattr(options, "docstring");
}
}
}
@ -310,9 +318,19 @@ public:
FileErrorDisplay(mlifilen);
SWIG_exit(EXIT_FAILURE);
}
emitBanner(f_mlout);
emitBanner(f_mliout);
Language::top(n);
if (mod_docstring) {
if (Len(mod_docstring)) {
Printv(f_mliout, "(** ", mod_docstring, " *)\n", NIL);
}
Delete(mod_docstring);
mod_docstring = NULL;
}
Printf(f_enum_to_int, ") | _ -> (C_int (get_int v))\n" "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n", module);
Printf(f_mlibody, "val enum_to_int : c_enum_type -> c_obj -> Swig.c_obj\n");
@ -417,6 +435,29 @@ public:
return SwigType_isarray(SwigType_typedef_resolve_all(t));
}
virtual int membervariableHandler(Node *n) {
String *symname = Getattr(n, "sym:name");
Language::membervariableHandler(n);
String *mname = Swig_name_member(NSPACE_TODO, classname, symname);
String *getname = Swig_name_get(NSPACE_TODO, mname);
String *mangled_getname = mangleNameForCaml(getname);
Delete(getname);
if (!GetFlag(n, "feature:immutable")) {
String *setname = Swig_name_set(NSPACE_TODO, mname);
String *mangled_setname = mangleNameForCaml(setname);
Delete(setname);
Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else _%s args) ;\n", symname, mangled_getname, mangled_setname);
Delete(mangled_setname);
} else {
Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else C_void) ;\n", symname, mangled_getname);
}
Delete(mangled_getname);
Delete(mname);
return SWIG_OK;
}
/* ------------------------------------------------------------
* functionWrapper()
* Create a function declaration and register it with the interpreter.
@ -432,7 +473,6 @@ public:
Wrapper *f = NewWrapper();
String *proc_name = NewString("");
String *source = NewString("");
String *target = NewString("");
String *arg = NewString("");
String *cleanup = NewString("");
@ -447,6 +487,8 @@ public:
int destructor = (!Cmp(nodeType, "destructor"));
String *overname = 0;
bool isOverloaded = Getattr(n, "sym:overloaded") ? true : false;
// For overloaded functions, only the dispatch function needs to be exposed in the ml and mli files.
bool expose_func = !isOverloaded || !Getattr(n, "sym:nextSibling");
// Make a wrapper name for this
String *wname = Swig_name_wrapper(iname);
@ -470,33 +512,19 @@ public:
Printv(proc_name, "_", iname, NIL);
String *mangled_name = mangleNameForCaml(proc_name);
if (classmode && in_constructor) { // Emit constructor for object
if (classmode && in_constructor && expose_func) { // Emit constructor for object
String *mangled_name_nounder = NewString((char *) (Char(mangled_name)) + 1);
Printf(f_class_ctors_end, "let %s clst = _%s clst\n", mangled_name_nounder, mangled_name_nounder);
Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name_nounder);
Delete(mangled_name_nounder);
} else if (classmode && in_destructor) {
Printf(f_class_ctors, " \"~\", %s ;\n", mangled_name);
} else if (classmode && !in_constructor && !in_destructor && !static_member_function) {
} else if (classmode && !in_constructor && !in_destructor && !static_member_function &&
!Getattr(n, "membervariableHandler:sym:name") && expose_func) {
String *opname = Copy(Getattr(n, "memberfunctionHandler:sym:name"));
Replaceall(opname, "operator ", "");
if (strstr(Char(mangled_name), "__get__")) {
String *set_name = Copy(mangled_name);
if (!GetFlag(n, "feature:immutable")) {
Replaceall(set_name, "__get__", "__set__");
Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else %s args) ;\n", opname, mangled_name, set_name);
Delete(set_name);
} else {
Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else C_void) ;\n", opname, mangled_name);
}
} else if (strstr(Char(mangled_name), "__set__")) {
; /* Nothing ... handled by the case above */
} else {
Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name);
}
Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name);
Delete(opname);
}
@ -515,16 +543,6 @@ public:
// adds local variables
Wrapper_add_local(f, "args", "CAMLparam1(args)");
Wrapper_add_local(f, "ret", "SWIG_CAMLlocal2(swig_result,rv)");
Wrapper_add_local(f, "_v", "int _v = 0");
if (isOverloaded) {
Wrapper_add_local(f, "i", "int i");
Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)");
Wrapper_add_local(f, "argv", "CAML_VALUE *argv");
Printv(f->code,
"argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n"
"for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL);
}
d = SwigType_typedef_qualified(d);
emit_parameter_variables(l, f);
@ -534,7 +552,18 @@ public:
numargs = emit_num_arguments(l);
numreq = emit_num_required(l);
if (!isOverloaded) {
if (numargs > 0) {
if (numreq > 0) {
Printf(f->code, "if (caml_list_length(args) < %d || caml_list_length(args) > %d) {\n", numreq, numargs);
} else {
Printf(f->code, "if (caml_list_length(args) > %d) {\n", numargs);
}
Printf(f->code, "caml_invalid_argument(\"Incorrect number of arguments passed to '%s'\");\n}\n", iname);
} else {
Printf(f->code, "if (caml_list_length(args) > 0) caml_invalid_argument(\"'%s' takes no arguments\");\n", iname);
}
}
Printf(f->code, "swig_result = Val_unit;\n");
// Now write code to extract the parameters (this is super ugly)
@ -550,10 +579,9 @@ public:
pt = SwigType_typedef_qualified(pt);
// Produce names of source and target
Clear(source);
Clear(target);
Clear(arg);
Printf(source, "caml_list_nth(args,%d)", i);
String *source = NewStringf("caml_list_nth(args,%d)", i);
Printf(target, "%s", ln);
Printv(arg, Getattr(p, "name"), NIL);
@ -577,6 +605,7 @@ public:
if (i >= numreq) {
Printf(f->code, "}\n");
}
Delete(source);
}
/* Insert constraint checking code */
@ -676,6 +705,14 @@ public:
Printv(f->code, tm, "\n", NIL);
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
// Free any memory allocated by the function being wrapped..
if ((tm = Swig_typemap_lookup("swig_result", n, Swig_cresult_name(), 0))) {
@ -685,8 +722,6 @@ public:
// Wrap things up (in a manner of speaking)
Printv(f->code, tab4, "swig_result = caml_list_append(swig_result,rv);\n", NIL);
if (isOverloaded)
Printv(f->code, "free(argv);\n", NIL);
Printv(f->code, tab4, "CAMLreturn(swig_result);\n", NIL);
Printv(f->code, "}\n", NIL);
@ -703,7 +738,6 @@ public:
"free(argv);\n" "CAMLreturn(%s(args));\n",
&maxargs);
Wrapper_add_local(df, "_v", "int _v = 0");
Wrapper_add_local(df, "argv", "CAML_VALUE *argv");
/* Undifferentiate name .. this is the dispatch function */
@ -717,8 +751,19 @@ public:
Printv(df->code,
"argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n"
"for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL);
Printv(df->code, dispatch, "\n", NIL);
Printf(df->code, "failwith(\"No matching function for overloaded '%s'\");\n", iname);
Printv(df->code, dispatch, "\nfree(argv);\n", NIL);
Node *sibl = n;
while (Getattr(sibl, "sym:previousSibling"))
sibl = Getattr(sibl, "sym:previousSibling");
String *protoTypes = NewString("");
do {
String *fulldecl = Swig_name_decl(sibl);
Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
Delete(fulldecl);
} while ((sibl = Getattr(sibl, "sym:nextSibling")));
Printf(df->code, "caml_failwith(\"Wrong number or type of arguments for overloaded function '%s'.\\n\""
"\n\" Possible C/C++ prototypes are:\\n\"%s);\n", iname, protoTypes);
Delete(protoTypes);
Printv(df->code, "}\n", NIL);
Wrapper_print(df, f_wrappers);
@ -727,19 +772,20 @@ public:
}
}
Printf(f_mlbody,
"external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n"
"let %s arg = match %s_f (fnhelper arg) with\n"
" [] -> C_void\n"
"| [x] -> (if %s then Gc.finalise \n"
" (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n"
"| lst -> C_list lst ;;\n", mangled_name, wname, mangled_name, mangled_name, newobj ? "true" : "false");
if (expose_func) {
Printf(f_mlbody, "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n", mangled_name, wname);
Printf(f_mlbody, "let %s arg = match %s_f (%s(fnhelper arg)) with\n", mangled_name, mangled_name,
in_constructor && Swig_directorclass(getCurrentClass()) ? "director_core_helper " : "");
Printf(f_mlbody, " [] -> C_void\n"
"| [x] -> (if %s then Gc.finalise \n"
" (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n"
"| lst -> C_list lst ;;\n", newobj ? "true" : "false");
}
if (!classmode || in_constructor || in_destructor || static_member_function)
if ((!classmode || in_constructor || in_destructor || static_member_function) && expose_func)
Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name);
Delete(proc_name);
Delete(source);
Delete(target);
Delete(arg);
Delete(outarg);
@ -753,10 +799,11 @@ public:
* variableWrapper()
*
* Create a link to a C variable.
* This creates a single function _wrap_swig_var_varname().
* This creates a single function _wrap_varname().
* This function takes a single optional argument. If supplied, it means
* we are setting this variable to some value. If omitted, it means we are
* simply evaluating this variable. In the set case we return C_void.
* simply evaluating this variable. We return the value of the variable
* in both cases.
*
* symname is the name of the variable with respect to C. This
* may need to differ from the original name in the case of enums.
@ -772,9 +819,6 @@ public:
String *proc_name = NewString("");
String *tm;
String *tm2 = NewString("");
String *argnum = NewString("0");
String *arg = NewString("SWIG_Field(args,0)");
Wrapper *f;
if (!name) {
@ -794,14 +838,16 @@ public:
// evaluation function names
String *var_name = Swig_name_wrapper(iname);
// Build the name for scheme.
// Build the name for OCaml.
Printv(proc_name, iname, NIL);
Setattr(n, "wrap:name", proc_name);
Printf(f->def, "SWIGEXT CAML_VALUE %s(CAML_VALUE args) {\n", var_name);
// Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
Wrapper_add_local(f, "swig_result", "CAML_VALUE swig_result");
Wrapper_add_local(f, "args", "CAMLparam1(args)");
Wrapper_add_local(f, "swig_result", "SWIG_CAMLlocal1(swig_result)");
Printf(f->code, "swig_result = Val_unit;\n");
if (!GetFlag(n, "feature:immutable")) {
/* Check for a setting of the variable value */
@ -810,13 +856,12 @@ public:
Replaceall(tm, "$source", "args");
Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "args");
/* Printv(f->code, tm, "\n",NIL); */
emit_action_code(n, f->code, tm);
} else if ((tm = Swig_typemap_lookup("in", n, name, 0))) {
Replaceall(tm, "$source", "args");
Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "args");
Printv(f->code, tm, "\n", NIL);
emit_action_code(n, f->code, tm);
} else {
throw_unhandled_ocaml_type_error(t, "varin/in");
}
@ -834,12 +879,12 @@ public:
Replaceall(tm, "$source", name);
Replaceall(tm, "$target", "swig_result");
Replaceall(tm, "$result", "swig_result");
Printf(f->code, "%s\n", tm);
emit_action_code(n, f->code, tm);
} else {
throw_unhandled_ocaml_type_error(t, "varout/out");
}
Printf(f->code, "\nreturn swig_result;\n");
Printf(f->code, "\nCAMLreturn(swig_result);\n");
Printf(f->code, "}\n");
Wrapper_print(f, f_wrappers);
@ -860,9 +905,6 @@ public:
Delete(var_name);
Delete(proc_name);
Delete(argnum);
Delete(arg);
Delete(tm2);
DelWrapper(f);
return SWIG_OK;
}
@ -890,10 +932,9 @@ public:
virtual int constantWrapper(Node *n) {
String *name = Getattr(n, "feature:symname");
SwigType *type = Getattr(n, "type");
String *value = Getattr(n, "value");
String *rawval = Getattr(n, "rawval");
String *value = rawval ? rawval : Getattr(n, "value");
SwigType *qname = Getattr(n, "qualified:name");
String *rvalue = NewString("");
String *temp = 0;
if (qname)
value = qname;
@ -905,31 +946,8 @@ public:
}
// See if there's a typemap
Printv(rvalue, value, NIL);
if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) {
temp = Copy(rvalue);
Clear(rvalue);
Printv(rvalue, "\"", temp, "\"", NIL);
Delete(temp);
}
if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) {
temp = Copy(rvalue);
Clear(rvalue);
Printv(rvalue, "'", temp, "'", NIL);
Delete(temp);
}
// Create variable and assign it a value
Printf(f_header, "static %s = ", SwigType_lstr(type, name));
bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
if ((SwigType_type(type) == T_STRING)) {
Printf(f_header, "\"%s\";\n", value);
} else if (SwigType_type(type) == T_CHAR && !is_enum_item) {
Printf(f_header, "\'%s\';\n", value);
} else {
Printf(f_header, "%s;\n", value);
}
Printf(f_header, "static %s = %s;\n", SwigType_str(type, name), value);
SetFlag(n, "feature:immutable");
variableWrapper(n);
return SWIG_OK;
@ -1096,11 +1114,12 @@ public:
int classHandler(Node *n) {
String *name = Getattr(n, "name");
classname = Getattr(n, "sym:name");
if (!name)
return SWIG_OK;
String *mangled_sym_name = mangleNameForCaml(name);
String *mangled_name = mangleNameForCaml(name);
String *this_class_def = NewString(f_classtemplate);
String *name_normalized = normalizeTemplatedClassName(name);
String *old_class_ctors = f_class_ctors;
@ -1109,7 +1128,6 @@ public:
bool sizeof_feature = generate_sizeof && isSimpleType(name);
classname = mangled_sym_name;
classmode = true;
int rv = Language::classHandler(n);
classmode = false;
@ -1117,15 +1135,15 @@ public:
if (sizeof_feature) {
Printf(f_wrappers,
"SWIGEXT CAML_VALUE _wrap_%s_sizeof( CAML_VALUE args ) {\n"
" CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_sym_name, name_normalized);
" CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_name, name_normalized);
Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", classname, mangled_sym_name);
Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", mangled_name, mangled_name);
}
/* Insert sizeof operator for concrete classes */
if (sizeof_feature) {
Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", classname, "_sizeof ())) ;\n", NIL);
Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", mangled_name, "_sizeof ())) ;\n", NIL);
}
/* Handle up-casts in a nice way */
List *baselist = Getattr(n, "bases");
@ -1144,7 +1162,7 @@ public:
}
}
Replaceall(this_class_def, "$classname", classname);
Replaceall(this_class_def, "$classname", mangled_name);
Replaceall(this_class_def, "$normalized", name_normalized);
Replaceall(this_class_def, "$realname", name);
Replaceall(this_class_def, "$baselist", base_classes);
@ -1157,7 +1175,7 @@ public:
Multiwrite(this_class_def);
Setattr(n, "ocaml:ctor", classname);
Setattr(n, "ocaml:ctor", mangled_name);
return rv;
}
@ -1396,8 +1414,7 @@ public:
pure_virtual = true;
}
}
Wrapper_add_local(w, "swig_result", "CAMLparam0();\n" "SWIG_CAMLlocal2(swig_result,args)");
Printf(w->locals, "CAMLparam0();\n");
/* determine if the method returns a pointer */
is_pointer = SwigType_ispointer_return(decl);
@ -1408,44 +1425,88 @@ public:
String *pclassname = NewStringf("SwigDirector_%s", classname);
String *qualified_name = NewStringf("%s::%s", pclassname, name);
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
Printf(w->def, "%s {", target);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
/* header declaration */
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
Printf(declaration, " virtual %s;", target);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Get any exception classes in the throws typemap
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = 0;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
Parm *p;
int gencomma = 0;
Append(w->def, " throw(");
Append(declaration, " throw(");
if (throw_parm_list)
Swig_typemap_attach_parms("throws", throw_parm_list, 0);
for (p = throw_parm_list; p; p = nextSibling(p)) {
if (Getattr(p, "tmap:throws")) {
if (gencomma++) {
Append(w->def, ", ");
Append(declaration, ", ");
}
String *str = SwigType_str(Getattr(p, "type"), 0);
Append(w->def, str);
Append(declaration, str);
Delete(str);
}
}
Append(w->def, ")");
Append(declaration, ")");
}
Append(w->def, " {");
Append(declaration, ";\n");
/* declare method return value
* if the return value is a reference or const reference, a specialized typemap must
* handle it, including declaration of c_result ($result).
*/
if (!is_void) {
if (!(ignored_method && !pure_virtual)) {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
}
}
if (ignored_method) {
if (!pure_virtual) {
if (!is_void)
Printf(w->code, "return ");
String *super_call = Swig_method_call(super, l);
Printf(w->code, "%s;\n", super_call);
if (is_void)
Printf(w->code, "%s;\n", super_call);
else
Printf(w->code, "CAMLreturn_type(%s);\n", super_call);
Delete(super_call);
} else {
Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
SwigType_namestr(name));
}
} else {
Wrapper_add_local(w, "swig_result", "SWIG_CAMLlocal2(swig_result, args)");
/* attach typemaps to arguments (C/C++ -> Ocaml) */
String *arglist = NewString("");
Swig_director_parms_fixup(l);
Swig_typemap_attach_parms("in", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("directorargout", l, w);
Parm *p;
@ -1555,10 +1616,12 @@ public:
/* wrap complex arguments to values */
Printv(w->code, wrap_args, NIL);
/* pass the method call on to the Python object */
/* pass the method call on to the OCaml object */
Printv(w->code,
"swig_result = caml_swig_alloc(1,C_list);\n" "SWIG_Store_field(swig_result,0,args);\n" "args = swig_result;\n" "swig_result = Val_unit;\n", 0);
Printf(w->code, "swig_result = " "callback3(*caml_named_value(\"swig_runmethod\")," "swig_get_self(),copy_string(\"%s\"),args);\n", Getattr(n, "name"));
Printf(w->code, "static CAML_VALUE *swig_ocaml_func_val = NULL;\n" "if (!swig_ocaml_func_val) {\n");
Printf(w->code, " swig_ocaml_func_val = caml_named_value(\"swig_runmethod\");\n }\n");
Printf(w->code, "swig_result = caml_callback3(*swig_ocaml_func_val,swig_get_self(),caml_copy_string(\"%s\"),args);\n", Getattr(n, "name"));
/* exception handling */
tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
if (!tm) {
@ -1574,7 +1637,7 @@ public:
/*
* Python method may return a simple object, or a tuple.
* for in/out aruments, we have to extract the appropriate values from the
* for in/out arguments, we have to extract the appropriate values from the
* argument list, then marshal everything back to C/C++ (return value and
* output arguments).
*/
@ -1633,6 +1696,8 @@ public:
Printf(w->code, "CAMLreturn_type(*c_result);\n");
}
}
} else {
Printf(w->code, "CAMLreturn0;\n");
}
Printf(w->code, "}\n");
@ -1698,7 +1763,7 @@ public:
Wrapper *w = NewWrapper();
String *call;
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, classname, parms, 0);
call = Swig_csuperclass_call(0, basetype, superparms);
Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
Delete(target);
@ -1709,7 +1774,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, classname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -1799,9 +1864,9 @@ public:
}
String *runtimeCode() {
String *s = Swig_include_sys("ocaml.swg");
String *s = Swig_include_sys("ocamlrun.swg");
if (!s) {
Printf(stderr, "*** Unable to open 'ocaml.swg'\n");
Printf(stderr, "*** Unable to open 'ocamlrun.swg'\n");
s = NewString("");
}
return s;

View file

@ -19,10 +19,8 @@ static String *op_prefix = 0;
static const char *usage = "\
Octave Options (available with -octave)\n\
-cppcast - Enable C++ casting operators (default)\n\
-globals <name> - Set <name> used to access C global variables [default: 'cvar']\n\
Use '.' to load C global variables into module namespace\n\
-nocppcast - Disable C++ casting operators\n\
-opprefix <str> - Prefix <str> for global operator functions [default: 'op_']\n\
\n";
@ -92,8 +90,7 @@ public:
}
virtual void main(int argc, char *argv[]) {
int cppcast = 1;
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if (strcmp(argv[i], "-help") == 0) {
@ -116,12 +113,13 @@ public:
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-cppcast") == 0) {
cppcast = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
cppcast = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-cppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
Swig_mark_arg(i);
SWIG_exit(EXIT_FAILURE);
}
}
}
@ -130,8 +128,6 @@ public:
global_name = NewString("cvar");
if (!op_prefix)
op_prefix = NewString("op_");
if(cppcast)
Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
SWIG_library_directory("octave");
Preprocessor_define("SWIGOCTAVE 1", 0);
@ -139,7 +135,7 @@ public:
SWIG_typemap_lang("octave");
allow_overloading();
// Octave API is C++, so output must be C++ compatibile even when wrapping C code
// Octave API is C++, so output must be C++ compatible even when wrapping C code
if (!cparse_cplusplus)
Swig_cparse_cplusplusout(1);
}
@ -422,13 +418,14 @@ public:
* The "lname" attribute in each parameter in plist will be contain a parameter name
* ----------------------------------------------------------------------------- */
void addMissingParameterNames(ParmList *plist, int arg_offset) {
void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
Parm *p = plist;
int i = arg_offset;
while (p) {
if (!Getattr(p, "lname")) {
String *pname = Swig_cparm_name(p, i);
Delete(pname);
String *name = makeParameterName(n, p, i);
Setattr(p, "lname", name);
Delete(name);
}
i++;
p = nextSibling(p);
@ -440,14 +437,14 @@ public:
ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p;
Parm *pnext;
int start_arg_num = is_wrapping_class() ? 1 : 0;
int arg_num = is_wrapping_class() ? 1 : 0;
addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
Swig_typemap_attach_parms("in", plist, 0);
Swig_typemap_attach_parms("doc", plist, 0);
for (p = plist; p; p = pnext) {
for (p = plist; p; p = pnext, arg_num++) {
String *tm = Getattr(p, "tmap:in");
if (tm) {
@ -469,9 +466,10 @@ public:
value = Getattr(p, "tmap:doc:value");
}
name = name ? name : Getattr(p, "name");
name = name ? name : Getattr(p, "lname");
name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword
String *made_name = 0;
if (!name) {
name = made_name = makeParameterName(n, p, arg_num);
}
type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value");
@ -507,7 +505,7 @@ public:
Delete(type_str);
Delete(tex_name);
Delete(name);
Delete(made_name);
}
if (pdocs)
Setattr(n, "feature:pdocs", pdocs);
@ -1234,7 +1232,7 @@ public:
Wrapper *w = NewWrapper();
String *call;
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, classname, parms, 0);
call = Swig_csuperclass_call(0, basetype, superparms);
Printf(w->def, "%s::%s: %s," "\nSwig::Director(static_cast<%s*>(this)) { \n", classname, target, call, basetype);
Append(w->def, "}\n");
@ -1246,7 +1244,7 @@ public:
// constructor header
{
String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, classname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -1310,17 +1308,21 @@ public:
String *pclassname = NewStringf("SwigDirector_%s", classname);
String *qualified_name = NewStringf("%s::%s", pclassname, name);
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
// header declaration
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Get any exception classes in the throws typemap
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = 0;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
@ -1355,11 +1357,19 @@ public:
// declare method return value
// if the return value is a reference or const reference, a specialized typemap must
// handle it, including declaration of c_result ($result).
if (!is_void) {
if (!(ignored_method && !pure_virtual)) {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
}
}
@ -1381,7 +1391,7 @@ public:
Swig_director_parms_fixup(l);
Swig_typemap_attach_parms("in", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("directorargout", l, w);
Parm *p;

View file

@ -185,7 +185,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
nodes[j] = t;
break;
} else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
t1 = Getattr(p1, "ltype");
t1 = Getattr(p1, "equivtype");
t1 = t1 ? t1 : Getattr(p1, "ltype");
if (!t1) {
t1 = SwigType_ltype(Getattr(p1, "type"));
if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
@ -193,7 +194,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
}
Setattr(p1, "ltype", t1);
}
t2 = Getattr(p2, "ltype");
t2 = Getattr(p2, "equivtype");
t2 = t2 ? t2 : Getattr(p2, "ltype");
if (!t2) {
t2 = SwigType_ltype(Getattr(p2, "type"));
if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
@ -231,9 +233,21 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
}
if (!differ) {
/* See if declarations differ by const only */
String *d1 = Getattr(nodes[i].n, "decl");
String *d2 = Getattr(nodes[j].n, "decl");
if (d1 && d2) {
String *decl1 = Getattr(nodes[i].n, "decl");
String *decl2 = Getattr(nodes[j].n, "decl");
if (decl1 && decl2) {
/* Remove ref-qualifiers. Note that rvalue ref-qualifiers are already ignored and
* it is illegal to overload a function with and without ref-qualifiers. So with
* all the combinations of ref-qualifiers and cv-qualifiers, we just detect
* the cv-qualifier (const) overloading. */
String *d1 = Copy(decl1);
String *d2 = Copy(decl2);
if (SwigType_isreference(d1) || SwigType_isrvalue_reference(d1)) {
Delete(SwigType_pop(d1));
}
if (SwigType_isreference(d2) || SwigType_isrvalue_reference(d2)) {
Delete(SwigType_pop(d2));
}
String *dq1 = Copy(d1);
String *dq2 = Copy(d2);
if (SwigType_isconst(d1)) {
@ -428,7 +442,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *
/* Loop over the functions */
bool emitcheck = 1;
bool emitcheck = true;
for (i = 0; i < nfunc; i++) {
int fn = 0;
Node *ni = Getitem(dispatch, i);
@ -504,7 +518,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *
if (tml)
Replaceid(tml, Getattr(pl, "lname"), "_v");
if (!tml || Cmp(tm, tml))
emitcheck = 1;
emitcheck = true;
//printf("tmap: %s[%d] (%d) => %s\n\n",
// Char(Getattr(nk, "sym:name")),
// l, emitcheck, tml?Char(tml):0);
@ -596,7 +610,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *
/*
Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586).
*/
String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
static String *overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
int i, j;
*maxargs = 1;
@ -639,6 +653,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *
// printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
bool emitcheck = false;
int num_braces = 0;
bool test = (Len(coll) > 0 && num_arguments);
if (test) {
@ -659,7 +674,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *
/* if all the wrappers have the same type check on this
argument we can optimize it out */
bool emitcheck = 0;
emitcheck = false;
for (int k = 0; k < Len(coll) && !emitcheck; k++) {
Node *nk = Getitem(coll, k);
Parm *pk = Getattr(nk, "wrap:parms");
@ -681,7 +696,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *
if (tml)
Replaceid(tml, Getattr(pl, "lname"), "_v");
if (!tml || Cmp(tm, tml))
emitcheck = 1;
emitcheck = true;
//printf("tmap: %s[%d] (%d) => %s\n\n",
// Char(Getattr(nk, "sym:name")),
// l, emitcheck, tml?Char(tml):0);
@ -738,8 +753,8 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *
for ( /* empty */ ; num_braces > 0; num_braces--)
Printf(f, "}\n");
String *lfmt = ReplaceFormat(fmt, num_arguments);
// The language module may want to generate different code for last overloaded function called (with same number of arguments)
String *lfmt = ReplaceFormat(!emitcheck && fmt_fastdispatch ? fmt_fastdispatch : fmt, num_arguments);
Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
Printf(f, "}\n"); /* braces closes "if" for this method */
@ -756,10 +771,10 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *
return f;
}
String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
return Swig_overload_dispatch_fast(n, fmt, maxargs);
return overload_dispatch_fast(n, fmt, maxargs, fmt_fastdispatch);
}
int i, j;

View file

@ -16,11 +16,9 @@
#include <ctype.h>
static const char *usage = "\
Perl5 Options (available with -perl5)\n\
Perl 5 Options (available with -perl5)\n\
-compat - Compatibility mode\n\
-const - Wrap constants as constants and not variables (implies -proxy)\n\
-cppcast - Enable C++ casting operators\n\
-nocppcast - Disable C++ casting operators, useful for generating bugs\n\
-nopm - Do not generate the .pm file\n\
-noproxy - Don't create proxy classes\n\
-proxy - Create proxy classes\n\
@ -148,7 +146,6 @@ public:
virtual void main(int argc, char *argv[]) {
int i = 1;
int cppcast = 1;
SWIG_library_directory("perl5");
@ -189,25 +186,22 @@ public:
} else if (strcmp(argv[i],"-v") == 0) {
Swig_mark_arg(i);
verbose++;
} else if (strcmp(argv[i], "-cppcast") == 0) {
cppcast = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
cppcast = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-compat") == 0) {
compat = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-help") == 0) {
fputs(usage, stdout);
} else if (strcmp(argv[i], "-cppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
Swig_mark_arg(i);
SWIG_exit(EXIT_FAILURE);
}
}
}
if (cppcast) {
Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
}
Preprocessor_define("SWIGPERL 1", 0);
// SWIGPERL5 is deprecated, and no longer documented.
Preprocessor_define("SWIGPERL5 1", 0);
@ -900,6 +894,15 @@ public:
Printf(f->code, "%s\n", tm);
}
if (director_method) {
if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$input", Swig_cresult_name());
Replaceall(tm, "$result", "ST(argvi)");
Printf(f->code, "%s\n", tm);
Delete(tm);
}
}
Printv(f->code, "XSRETURN(argvi);\n", "fail:\n", cleanup, "SWIG_croak_null();\n" "}\n" "}\n", NIL);
/* Add the dXSARGS last */
@ -2018,7 +2021,7 @@ public:
Wrapper *w = NewWrapper();
String *call;
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, classname, parms, 0);
call = Swig_csuperclass_call(0, basetype, superparms);
Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call);
Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
@ -2031,7 +2034,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, classname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -2080,16 +2083,20 @@ public:
String *pclassname = NewStringf("SwigDirector_%s", classname);
String *qualified_name = NewStringf("%s::%s", pclassname, name);
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
/* header declaration */
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Get any exception classes in the throws typemap
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = 0;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
@ -2125,17 +2132,26 @@ public:
* if the return value is a reference or const reference, a specialized typemap must
* handle it, including declaration of c_result ($result).
*/
if (!is_void) {
if (!(ignored_method && !pure_virtual)) {
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
}
if (!ignored_method) {
String *pres = NewStringf("SV *%s", Swig_cresult_name());
Wrapper_add_local(w, Swig_cresult_name(), pres);
Delete(pres);
}
}
if (!is_void && !ignored_method) {
String *pres = NewStringf("SV *%s", Swig_cresult_name());
Wrapper_add_local(w, Swig_cresult_name(), pres);
Delete(pres);
}
if (ignored_method) {
@ -2158,7 +2174,7 @@ public:
/* remove the wrapper 'w' since it was producing spurious temps */
Swig_typemap_attach_parms("in", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("directorargout", l, w);
Wrapper_add_local(w, "SP", "dSP");
@ -2332,7 +2348,7 @@ public:
/*
* Python method may return a simple object, or a tuple.
* for in/out aruments, we have to extract the appropriate PyObjects from the tuple,
* for in/out arguments, we have to extract the appropriate PyObjects from the tuple,
* then marshal everything back to C/C++ (return value and output arguments).
*
*/
@ -2486,9 +2502,12 @@ public:
Delete(mangle);
Delete(ptype);
if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() throw () {%s}\n\n", DirectorClassName, DirectorClassName, body);
if (Getattr(n, "noexcept")) {
Printf(f_directors_h, " virtual ~%s() noexcept;\n", DirectorClassName);
Printf(f_directors, "%s::~%s() noexcept {%s}\n\n", DirectorClassName, DirectorClassName, body);
} else if (Getattr(n, "throw")) {
Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() throw() {%s}\n\n", DirectorClassName, DirectorClassName, body);
} else {
Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() {%s}\n\n", DirectorClassName, DirectorClassName, body);

File diff suppressed because it is too large Load diff

View file

@ -261,10 +261,9 @@ public:
rename = strip(name);
Printf(f_classInit, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
break;
case CLASS_CONST:
assert(false); // shouldn't have gotten here for CLASS_CONST nodes
default:
assert(false); // what is this?
case CLASS_CONST: // shouldn't have gotten here for CLASS_CONST nodes
default: // what is this?
assert(false);
}
Delete(rename);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -131,12 +131,10 @@ enum autodoc_t {
static const char *usage = "\
Ruby Options (available with -ruby)\n\
-autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
-cppcast - Enable C++ casting operators (default)\n\
-globalmodule - Wrap everything into the global module\n\
-initname <name>- Set entry function to Init_<name> (used by `require')\n\
-minherit - Attempt to support multiple inheritance\n\
-noautorename - Disable renaming of classes and methods (default)\n\
-nocppcast - Disable C++ casting operators, useful for generating bugs\n\
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
";
@ -257,32 +255,22 @@ private:
autodoc = make_autodoc(n, ad_type);
have_auto = (autodoc && Len(autodoc) > 0);
}
// If there is more than one line then make docstrings like this:
//
// This is line1
// And here is line2 followed by the rest of them
//
// otherwise, put it all on a single line
//
if (have_auto || have_ds)
doc = NewString("/*");
if (have_auto && have_ds) { // Both autodoc and docstring are present
doc = NewString("");
Printv(doc, "\n", autodoc, "\n", str, NIL);
Printv(doc, "\n", autodoc, "\n", str, "\n", NIL);
} else if (!have_auto && have_ds) { // only docstring
if (Strchr(str, '\n') == 0) {
doc = NewString(str);
} else {
doc = NewString("");
Printv(doc, str, NIL);
}
Printv(doc, str, NIL);
} else if (have_auto && !have_ds) { // only autodoc
if (Strchr(autodoc, '\n') == 0) {
doc = NewStringf("%s", autodoc);
} else {
doc = NewString("");
Printv(doc, "\n", autodoc, NIL);
}
} else
Printv(doc, "\n", autodoc, "\n", NIL);
} else {
doc = NewString("");
}
if (have_auto || have_ds)
Append(doc, "*/\n");
// Save the generated strings in the parse tree in case they are used later
// by post processing tools
@ -302,13 +290,14 @@ private:
* The "lname" attribute in each parameter in plist will be contain a parameter name
* ----------------------------------------------------------------------------- */
void addMissingParameterNames(ParmList *plist, int arg_offset) {
void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
Parm *p = plist;
int i = arg_offset;
while (p) {
if (!Getattr(p, "lname")) {
String *pname = Swig_cparm_name(p, i);
Delete(pname);
String *name = makeParameterName(n, p, i);
Setattr(p, "lname", name);
Delete(name);
}
i++;
p = nextSibling(p);
@ -327,10 +316,10 @@ private:
Parm *p;
Parm *pnext;
int lines = 0;
int start_arg_num = is_wrapping_class() ? 1 : 0;
int arg_num = is_wrapping_class() ? 1 : 0;
const int maxwidth = 80;
addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
Swig_typemap_attach_parms("in", plist, 0);
Swig_typemap_attach_parms("doc", plist, 0);
@ -340,7 +329,7 @@ private:
return doc;
}
for (p = plist; p; p = pnext) {
for (p = plist; p; p = pnext, arg_num++) {
String *tm = Getattr(p, "tmap:in");
if (tm) {
@ -363,9 +352,10 @@ private:
}
// Note: the generated name should be consistent with that in kwnames[]
name = name ? name : Getattr(p, "name");
name = name ? name : Getattr(p, "lname");
name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword
String *made_name = 0;
if (!name) {
name = made_name = makeParameterName(n, p, arg_num);
}
type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value");
@ -416,7 +406,7 @@ private:
Printf(doc, "=%s", value);
}
Delete(type_str);
Delete(name);
Delete(made_name);
}
if (pdocs)
Setattr(n, "feature:pdocs", pdocs);
@ -436,7 +426,7 @@ private:
String *make_autodoc(Node *n, autodoc_t ad_type) {
int extended = 0;
// If the function is overloaded then this funciton is called
// If the function is overloaded then this function is called
// for the last one. Rewind to the first so the docstrings are
// in order.
while (Getattr(n, "sym:previousSibling"))
@ -522,7 +512,7 @@ private:
last_mode = ad_type;
last_autodoc = Copy(methodName);
String *doc = NewString("/*\n");
String *doc = NewString("");
int counter = 0;
bool skipAuto = false;
Node* on = n;
@ -762,7 +752,6 @@ private:
n = Getattr(n, "sym:nextSibling");
}
Append(doc, "\n*/\n");
Delete(full_name);
Delete(class_name);
Delete(super_names);
@ -844,7 +833,6 @@ public:
virtual void main(int argc, char *argv[]) {
int cppcast = 1;
int autorename = 0;
/* Set location of SWIG library */
@ -883,12 +871,6 @@ public:
multipleInheritance = true;
director_multiple_inheritance = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-cppcast") == 0) {
cppcast = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
cppcast = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-autorename") == 0) {
autorename = 1;
Swig_mark_arg(i);
@ -907,15 +889,17 @@ public:
}
} else if (strcmp(argv[i], "-help") == 0) {
Printf(stdout, "%s\n", usage);
} else if (strcmp(argv[i], "-cppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
Swig_mark_arg(i);
SWIG_exit(EXIT_FAILURE);
}
}
}
if (cppcast) {
/* Turn on cppcast mode */
Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
}
if (autorename) {
/* Turn on the autorename mode */
Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0);
@ -1316,7 +1300,13 @@ public:
Iterator alias = First(aliases);
while (alias.item) {
if (Len(alias.item) > 0) {
if (multipleInheritance) {
if (current == NO_CPP) {
if (useGlobalModule) {
Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL);
} else {
Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL);
}
} else if (multipleInheritance) {
Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
} else {
Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
@ -1419,9 +1409,8 @@ public:
case DESTRUCTOR:
case CLASS_CONST:
case STATIC_VAR:
assert(false); // Should not have gotten here for these types
default:
assert(false);
assert(false); // Should not have gotten here for these types
}
defineAliases(n, iname);
@ -2926,7 +2915,7 @@ public:
Wrapper *w = NewWrapper();
String *call;
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
String *target = Swig_method_decl(0, decl, classname, parms, 0);
call = Swig_csuperclass_call(0, basetype, superparms);
Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
Delete(target);
@ -2937,7 +2926,7 @@ public:
/* constructor header */
{
String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
String *target = Swig_method_decl(0, decl, classname, parms, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
@ -3047,7 +3036,7 @@ public:
if (argc > 0) {
Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args);
} else {
Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, NULL);\n", Swig_cresult_name(), methodName);
Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName);
}
if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
}
@ -3103,16 +3092,20 @@ public:
String *pclassname = NewStringf("SwigDirector_%s", classname);
String *qualified_name = NewStringf("%s::%s", pclassname, name);
SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
Printf(w->def, "%s", target);
Delete(qualified_name);
Delete(target);
/* header declaration */
target = Swig_method_decl(rtype, decl, name, l, 0, 1);
target = Swig_method_decl(rtype, decl, name, l, 1);
Printf(declaration, " virtual %s", target);
Delete(target);
// Get any exception classes in the throws typemap
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = 0;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
@ -3151,9 +3144,19 @@ public:
* if the return value is a reference or const reference, a specialized typemap must
* handle it, including declaration of c_result ($result).
*/
if (!is_void) {
if (!(ignored_method && !pure_virtual)) {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);
}
}
@ -3175,7 +3178,7 @@ public:
Swig_director_parms_fixup(l);
Swig_typemap_attach_parms("in", l, 0);
Swig_typemap_attach_parms("directorin", l, 0);
Swig_typemap_attach_parms("directorin", l, w);
Swig_typemap_attach_parms("directorargout", l, w);
char source[256];
@ -3288,7 +3291,7 @@ public:
}
/* declare Ruby return value */
String *value_result = NewStringf("VALUE %s", Swig_cresult_name());
String *value_result = NewStringf("VALUE SWIGUNUSED %s", Swig_cresult_name());
Wrapper_add_local(w, Swig_cresult_name(), value_result);
Delete(value_result);

View file

@ -18,13 +18,14 @@ static const int SCILAB_VARIABLE_NAME_CHAR_MAX = SCILAB_IDENTIFIER_NAME_CHAR_MAX
static const char *usage = (char *) " \
Scilab options (available with -scilab)\n \
-builder - Generate a Scilab builder script\n \
-buildercflags <cflags> - Add <cflags> to the builder compiler flags\n \
-builderflagscript <file> - Set the Scilab script <file> to use by builder to configure the build flags\n \
-builderldflags <ldflags> - Add <ldflags> to the builder linker flags\n \
-buildersources <files> - Add the (comma separated) files <files> to the builder sources\n \
-builderverbositylevel <level> - Set the builder verbosity level to <level> (default 0: off, 2: high)\n \
-gatewayxml <gateway_id> - Generate gateway xml with the given <gateway_id>\n \
-builder - Generate a Scilab builder script\n \
-buildercflags <cflags> - Add <cflags> to the builder compiler flags\n \
-builderflagscript <file> - Set the Scilab script <file> to use by builder to configure the build flags\n \
-builderldflags <ldflags> - Add <ldflags> to the builder linker flags\n \
-buildersources <files> - Add the (comma separated) files <files> to the builder sources\n \
-builderverbositylevel <level> - Set the builder verbosity level to <level> (default 0: off, 2: high)\n \
-gatewayxml <gateway_id> - Generate gateway xml with the given <gateway_id>\n \
-targetversion <scilab_major_version> - Generate for Scilab target (major) version (default: 5)\n \
\n";
@ -39,6 +40,8 @@ protected:
String *variablesCode;
int targetVersion;
bool generateBuilder;
File *builderFile;
String *builderCode;
@ -71,6 +74,7 @@ public:
* ----------------------------------------------------------------------*/
virtual void main(int argc, char *argv[]) {
targetVersion = 5;
generateBuilder = false;
sourceFileList = NewList();
@ -95,48 +99,54 @@ public:
/* Manage command line arguments */
for (int argIndex = 1; argIndex < argc; argIndex++) {
if (argv[argIndex] != NULL) {
if (strcmp(argv[argIndex], "-help") == 0) {
Printf(stdout, "%s\n", usage);
} else if (strcmp(argv[argIndex], "-builder") == 0) {
Swig_mark_arg(argIndex);
generateBuilder = true;
createLoader = false;
} else if (strcmp(argv[argIndex], "-buildersources") == 0) {
if (argv[argIndex + 1] != NULL) {
Swig_mark_arg(argIndex);
char *sourceFile = strtok(argv[argIndex + 1], ",");
while (sourceFile != NULL) {
Insert(sourceFileList, Len(sourceFileList), sourceFile);
sourceFile = strtok(NULL, ",");
}
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-buildercflags") == 0) {
Swig_mark_arg(argIndex);
if (argv[argIndex + 1] != NULL) {
Insert(cflags, Len(cflags), argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-builderldflags") == 0) {
Swig_mark_arg(argIndex);
if (argv[argIndex + 1] != NULL) {
Insert(ldflags, Len(ldflags), argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) {
Swig_mark_arg(argIndex);
verboseBuildLevel = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
} else if (strcmp(argv[argIndex], "-builderflagscript") == 0) {
Swig_mark_arg(argIndex);
buildFlagsScript = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
} else if (strcmp(argv[argIndex], "-gatewayxml") == 0) {
Swig_mark_arg(argIndex);
createGatewayXML = true;
gatewayID = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
if (strcmp(argv[argIndex], "-help") == 0) {
Printf(stdout, "%s\n", usage);
} else if (strcmp(argv[argIndex], "-builder") == 0) {
Swig_mark_arg(argIndex);
generateBuilder = true;
createLoader = false;
} else if (strcmp(argv[argIndex], "-buildersources") == 0) {
if (argv[argIndex + 1] != NULL) {
Swig_mark_arg(argIndex);
char *sourceFile = strtok(argv[argIndex + 1], ",");
while (sourceFile != NULL) {
Insert(sourceFileList, Len(sourceFileList), sourceFile);
sourceFile = strtok(NULL, ",");
}
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-buildercflags") == 0) {
Swig_mark_arg(argIndex);
if (argv[argIndex + 1] != NULL) {
Insert(cflags, Len(cflags), argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-builderldflags") == 0) {
Swig_mark_arg(argIndex);
if (argv[argIndex + 1] != NULL) {
Insert(ldflags, Len(ldflags), argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
} else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) {
Swig_mark_arg(argIndex);
verboseBuildLevel = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
} else if (strcmp(argv[argIndex], "-builderflagscript") == 0) {
Swig_mark_arg(argIndex);
buildFlagsScript = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
} else if (strcmp(argv[argIndex], "-gatewayxml") == 0) {
Swig_mark_arg(argIndex);
createGatewayXML = true;
gatewayID = NewString(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
} else if (strcmp(argv[argIndex], "-targetversion") == 0) {
if (argv[argIndex + 1] != NULL) {
Swig_mark_arg(argIndex);
targetVersion = atoi(argv[argIndex + 1]);
Swig_mark_arg(argIndex + 1);
}
}
}
}
@ -412,7 +422,7 @@ public:
emit_return_variable(node, functionReturnType, wrapper);
/* Return the function value if necessary */
String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, "result", wrapper, functionActionCode);
String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode);
if (functionReturnTypemap) {
// Result is actually the position of output value on stack
if (Len(functionReturnTypemap) > 0) {
@ -471,6 +481,13 @@ public:
}
}
/* See if there is any return cleanup code */
String *tm;
if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(wrapper->code, "%s\n", tm);
Delete(tm);
}
/* Close the function(ok) */
Printv(wrapper->code, "return SWIG_OK;\n", NIL);
@ -479,7 +496,7 @@ public:
/* Add the failure cleanup code */
/* TODO */
/* Final substititions if applicable */
/* Final substitutions if applicable */
Replaceall(wrapper->code, "$symname", functionName);
/* Set CheckInputArgument and CheckOutputArgument input arguments */
@ -777,57 +794,61 @@ public:
/* -----------------------------------------------------------------------
* checkIdentifierName()
* Truncates (and displays a warning) for too long identifier names
* (applies on functions, variables, constants...)
* (Scilab identifiers names are limited to 24 chars max)
* If Scilab target version is lower than 6:
* truncates (and displays a warning) too long member identifier names
* (applies on members of structs, classes...)
* (Scilab 5 identifier names are limited to 24 chars max)
* ----------------------------------------------------------------------- */
String *checkIdentifierName(String *name, int char_size_max) {
String *scilabIdentifierName;
if (Len(name) > char_size_max) {
scilabIdentifierName = DohNewStringWithSize(name, char_size_max);
Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
"Identifier name '%s' exceeds 24 characters and has been truncated to '%s'.\n", name, scilabIdentifierName);
} else
if (targetVersion <= 5) {
if (Len(name) > char_size_max) {
scilabIdentifierName = DohNewStringWithSize(name, char_size_max);
Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
"Identifier name '%s' exceeds 24 characters and has been truncated to '%s'.\n", name, scilabIdentifierName);
} else
scilabIdentifierName = name;
return scilabIdentifierName;
} else {
scilabIdentifierName = DohNewString(name);
}
return scilabIdentifierName;
}
/* -----------------------------------------------------------------------
* checkMemberIdentifierName()
* Truncates (and displays a warning) too long member identifier names
* (applies on members of structs, classes...)
* (Scilab identifiers names are limited to 24 chars max)
* If Scilab target version is lower than 6:
* truncates (and displays a warning) too long member identifier names
* (applies on members of structs, classes...)
* (Scilab 5 identifier names are limited to 24 chars max)
* ----------------------------------------------------------------------- */
void checkMemberIdentifierName(Node *node, int char_size_max) {
if (targetVersion <= 5) {
String *memberName = Getattr(node, "sym:name");
Node *containerNode = parentNode(node);
String *containerName = Getattr(containerNode, "sym:name");
int lenContainerName = Len(containerName);
int lenMemberName = Len(memberName);
String *memberName = Getattr(node, "sym:name");
if (lenContainerName + lenMemberName + 1 > char_size_max) {
int lenScilabMemberName = char_size_max - lenContainerName - 1;
Node *containerNode = parentNode(node);
String *containerName = Getattr(containerNode, "sym:name");
int lenContainerName = Len(containerName);
int lenMemberName = Len(memberName);
if (lenContainerName + lenMemberName + 1 > char_size_max) {
int lenScilabMemberName = char_size_max - lenContainerName - 1;
if (lenScilabMemberName > 0) {
String *scilabMemberName = DohNewStringWithSize(memberName, lenScilabMemberName);
Setattr(node, "sym:name", scilabMemberName);
Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
"Wrapping functions names for member '%s.%s' will exceed 24 characters, "
"so member name has been truncated to '%s'.\n", containerName, memberName, scilabMemberName);
} else
Swig_error(input_file, line_number,
"Wrapping functions names for member '%s.%s' will exceed 24 characters, "
"please rename the container of member '%s'.\n", containerName, memberName, containerName);
if (lenScilabMemberName > 0) {
String *scilabMemberName = DohNewStringWithSize(memberName, lenScilabMemberName);
Setattr(node, "sym:name", scilabMemberName);
Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
"Wrapping functions names for member '%s.%s' will exceed 24 characters, "
"so member name has been truncated to '%s'.\n", containerName, memberName, scilabMemberName);
} else {
Swig_error(input_file, line_number,
"Wrapping functions names for member '%s.%s' will exceed 24 characters, "
"please rename the container of member '%s'.\n", containerName, memberName, containerName);
}
}
}
}
/* -----------------------------------------------------------------------
* addHelperFunctions()
* ----------------------------------------------------------------------- */
@ -1006,8 +1027,14 @@ public:
Printf(gatewayHeader, "\n");
gatewayHeaderV6 = NewString("");
Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
Printf(gatewayHeaderV6, "extern \"C\" {\n");
Printf(gatewayHeaderV6, "#endif\n");
Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n");
Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n");
Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
Printf(gatewayHeaderV6, "}\n");
Printf(gatewayHeaderV6, "#endif\n");
Printf(gatewayHeaderV6, "\n");
Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName);
Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");

View file

@ -26,79 +26,64 @@
can be dynamically loaded in future versions. */
extern "C" {
Language *swig_tcl(void);
Language *swig_python(void);
Language *swig_perl5(void);
Language *swig_ruby(void);
Language *swig_c(void);
Language *swig_csharp(void);
Language *swig_d(void);
Language *swig_go(void);
Language *swig_guile(void);
Language *swig_modula3(void);
Language *swig_mzscheme(void);
Language *swig_java(void);
Language *swig_php(void);
Language *swig_php4(void);
Language *swig_javascript(void);
Language *swig_lua(void);
Language *swig_mzscheme(void);
Language *swig_ocaml(void);
Language *swig_octave(void);
Language *swig_pike(void);
Language *swig_sexp(void);
Language *swig_xml(void);
Language *swig_chicken(void);
Language *swig_csharp(void);
Language *swig_allegrocl(void);
Language *swig_lua(void);
Language *swig_clisp(void);
Language *swig_cffi(void);
Language *swig_uffi(void);
Language *swig_perl5(void);
Language *swig_php(void);
Language *swig_python(void);
Language *swig_r(void);
Language *swig_c(void);
Language *swig_ruby(void);
Language *swig_scilab(void);
Language *swig_go(void);
Language *swig_d(void);
Language *swig_javascript(void);
Language *swig_tcl(void);
Language *swig_xml(void);
}
struct swig_module {
const char *name;
ModuleFactory fac;
const char *help;
};
/* Association of command line options to language modules.
Place an entry for new language modules here, keeping the
list sorted alphabetically. */
static swig_module modules[] = {
{"-allegrocl", swig_allegrocl, "ALLEGROCL"},
{"-c", swig_c, "C"},
{"-chicken", swig_chicken, "CHICKEN"},
{"-clisp", swig_clisp, "CLISP"},
{"-cffi", swig_cffi, "CFFI"},
{"-csharp", swig_csharp, "C#"},
{"-d", swig_d, "D"},
{"-go", swig_go, "Go"},
{"-guile", swig_guile, "Guile"},
{"-java", swig_java, "Java"},
{"-javascript", swig_javascript, "Javascript"},
{"-lua", swig_lua, "Lua"},
{"-modula3", swig_modula3, "Modula 3"},
{"-mzscheme", swig_mzscheme, "Mzscheme"},
{"-ocaml", swig_ocaml, "Ocaml"},
{"-octave", swig_octave, "Octave"},
{"-perl", swig_perl5, "Perl"},
{"-perl5", swig_perl5, 0},
{"-php", swig_php, "PHP"},
{"-php4", swig_php4, 0},
{"-php5", swig_php, 0},
{"-pike", swig_pike, "Pike"},
{"-python", swig_python, "Python"},
{"-r", swig_r, "R (aka GNU S)"},
{"-ruby", swig_ruby, "Ruby"},
{"-scilab", swig_scilab, "Scilab"},
{"-sexp", swig_sexp, "Lisp S-Expressions"},
{"-tcl", swig_tcl, "Tcl"},
{"-tcl8", swig_tcl, 0},
{"-uffi", swig_uffi, "Common Lisp / UFFI"},
{"-xml", swig_xml, "XML"},
{NULL, NULL, NULL}
static TargetLanguageModule modules[] = {
{"-allegrocl", NULL, "ALLEGROCL", Disabled},
{"-c", swig_c, "C", Experimental},
{"-chicken", NULL, "CHICKEN", Disabled},
{"-clisp", NULL, "CLISP", Disabled},
{"-cffi", NULL, "CFFI", Disabled},
{"-csharp", swig_csharp, "C#", Supported},
{"-d", swig_d, "D", Supported},
{"-go", swig_go, "Go", Supported},
{"-guile", swig_guile, "Guile", Supported},
{"-java", swig_java, "Java", Supported},
{"-javascript", swig_javascript, "Javascript", Supported},
{"-lua", swig_lua, "Lua", Supported},
{"-modula3", NULL, "Modula 3", Disabled},
{"-mzscheme", swig_mzscheme, "MzScheme/Racket", Experimental},
{"-ocaml", swig_ocaml, "OCaml", Experimental},
{"-octave", swig_octave, "Octave", Supported},
{"-perl", swig_perl5, NULL, Supported},
{"-perl5", swig_perl5, "Perl 5", Supported},
{"-php", swig_php, NULL, Supported},
{"-php5", NULL, "PHP 5", Disabled},
{"-php7", swig_php, "PHP 7", Supported},
{"-pike", NULL, "Pike", Disabled},
{"-python", swig_python, "Python", Supported},
{"-r", swig_r, "R (aka GNU S)", Supported},
{"-ruby", swig_ruby, "Ruby", Supported},
{"-scilab", swig_scilab, "Scilab", Supported},
{"-sexp", NULL, "Lisp S-Expressions", Disabled},
{"-tcl", swig_tcl, NULL, Supported},
{"-tcl8", swig_tcl, "Tcl 8", Supported},
{"-uffi", NULL, "Common Lisp / UFFI", Disabled},
{"-xml", swig_xml, "XML", Supported},
{NULL, NULL, NULL, Disabled}
};
#ifdef MACSWIG
@ -106,10 +91,6 @@ static swig_module modules[] = {
#include <SIOUX.h>
#endif
#ifndef SWIG_LANG
#define SWIG_LANG "-python"
#endif
//-----------------------------------------------------------------
// main()
//
@ -119,13 +100,14 @@ static swig_module modules[] = {
void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) {
if (!env) {
*nargc = oargc;
*nargv = oargv;
*nargv = (char **)malloc(sizeof(char *) * (oargc + 1));
memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1));
return;
}
int argc = 1;
int arge = oargc + 1024;
char **argv = (char **) malloc(sizeof(char *) * (arge));
char **argv = (char **) malloc(sizeof(char *) * (arge + 1));
char *buffer = (char *) malloc(2048);
char *b = buffer;
char *be = b + 1023;
@ -147,49 +129,139 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch
for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) {
argv[argc] = oargv[i];
}
argv[argc] = NULL;
*nargc = argc;
*nargv = argv;
}
static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) {
int new_argc = *argc;
char **new_argv = *argv;
size_t option_len = end - start;
// Preserve the NULL pointer at argv[argc]
new_argv = (char **)realloc(new_argv, (new_argc + 2) * sizeof(char *));
memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index));
new_argc++;
new_argv[index] = (char *)malloc(option_len + 1);
memcpy(new_argv[index], start, option_len);
new_argv[index][option_len] = '\0';
*argc = new_argc;
*argv = new_argv;
}
static void merge_options_files(int *argc, char ***argv) {
static const int BUFFER_SIZE = 4096;
char buffer[BUFFER_SIZE];
int i;
int insert;
char **new_argv = *argv;
int new_argc = *argc;
FILE *f;
i = 1;
while (i < new_argc) {
if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) {
char c;
char *b;
char *be = &buffer[BUFFER_SIZE];
int quote = 0;
bool escape = false;
new_argc--;
memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i));
insert = i;
b = buffer;
while ((c = fgetc(f)) != EOF) {
if (escape) {
if (b != be) {
*b = c;
++b;
}
escape = false;
} else if (c == '\\') {
escape = true;
} else if (!quote && (c == '\'' || c == '"')) {
quote = c;
} else if (quote && c == quote) {
quote = 0;
} else if (isspace(c) && !quote) {
if (b != buffer) {
insert_option(&new_argc, &new_argv, insert, buffer, b);
insert++;
b = buffer;
}
} else if (b != be) {
*b = c;
++b;
}
}
if (b != buffer)
insert_option(&new_argc, &new_argv, insert, buffer, b);
fclose(f);
} else {
++i;
}
}
*argv = new_argv;
*argc = new_argc;
}
int main(int margc, char **margv) {
int i;
Language *dl = 0;
ModuleFactory fac = 0;
const TargetLanguageModule *language_module = 0;
int argc;
char **argv;
SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv);
merge_options_files(&argc, &argv);
#ifdef MACSWIG
SIOUXSettings.asktosaveonclose = false;
argc = ccommand(&argv);
#endif
/* Register built-in modules */
for (i = 0; modules[i].name; i++) {
Swig_register_module(modules[i].name, modules[i].fac);
}
Swig_init_args(argc, argv);
/* Get options */
for (i = 1; i < argc; i++) {
if (argv[i]) {
fac = Swig_find_module(argv[i]);
if (fac) {
dl = (fac) ();
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nolang") == 0) {
dl = new Language;
bool is_target_language_module = false;
for (int j = 0; modules[j].name; j++) {
if (strcmp(modules[j].name, argv[i]) == 0) {
language_module = &modules[j];
is_target_language_module = true;
break;
}
}
if (is_target_language_module) {
Swig_mark_arg(i);
if (language_module->status == Disabled) {
if (language_module->help)
Printf(stderr, "Target language option %s (%s) is no longer supported.\n", language_module->name, language_module->help);
else
Printf(stderr, "Target language option %s is no longer supported.\n", language_module->name);
SWIG_exit(EXIT_FAILURE);
}
} else if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
if (strcmp(argv[i], "--help") == 0)
strcpy(argv[i], "-help");
Printf(stdout, "Target Language Options\n");
Printf(stdout, "Supported Target Language Options\n");
for (int j = 0; modules[j].name; j++) {
if (modules[j].help) {
if (modules[j].help && modules[j].status == Supported) {
Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
}
}
Printf(stdout, "\nExperimental Target Language Options\n");
for (int j = 0; modules[j].name; j++) {
if (modules[j].help && modules[j].status == Experimental) {
Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
}
}
@ -197,14 +269,8 @@ int main(int margc, char **margv) {
}
}
}
if (!dl) {
fac = Swig_find_module(SWIG_LANG);
if (fac) {
dl = (fac) ();
}
}
int res = SWIG_main(argc, argv, dl);
int res = SWIG_main(argc, argv, language_module);
return res;
}

View file

@ -214,8 +214,8 @@ public:
virtual Hash* symbolAddScope(const_String_or_char_ptr scope);
virtual Hash* symbolScopeLookup(const_String_or_char_ptr scope);
virtual Hash* symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope);
virtual Node *classLookup(const SwigType *s) const; /* Class lookup */
virtual Node *enumLookup(SwigType *s); /* Enum lookup */
static Node *classLookup(const SwigType *s); /* Class lookup */
static Node *enumLookup(SwigType *s); /* Enum lookup */
virtual int abstractClassTest(Node *n); /* Is class really abstract? */
virtual int is_assignable(Node *n); /* Is variable assignable? */
virtual String *runtimeCode(); /* returns the language specific runtime code */
@ -342,10 +342,11 @@ protected:
/* Director language module */
int director_language;
/* Used to translate Doxygen comments to target documentation format */
class DoxygenTranslator *doxygenTranslator;
private:
Hash *symtabs; /* symbol tables */
Hash *classtypes;
Hash *enumtypes;
int overloading;
int multiinput;
int cplus_runtime;
@ -353,7 +354,21 @@ private:
static Language *this_;
};
int SWIG_main(int, char **, Language *);
extern "C" {
void SWIG_typemap_lang(const char *);
typedef Language *(*ModuleFactory) (void);
}
enum Status {Disabled, Experimental, Supported};
struct TargetLanguageModule {
const char *name;
ModuleFactory fac;
const char *help;
Status status;
};
int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm);
void emit_parameter_variables(ParmList *l, Wrapper *f);
void emit_return_variable(Node *n, SwigType *rt, Wrapper *f);
void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */
@ -368,15 +383,15 @@ List *SWIG_output_files();
void SWIG_library_directory(const char *);
int emit_num_arguments(ParmList *);
int emit_num_required(ParmList *);
int emit_isvarargs(ParmList *);
int emit_isvarargs(ParmList *p);
bool emit_isvarargs_function(Node *n);
void emit_attach_parmmaps(ParmList *, Wrapper *f);
void emit_mark_varargs(ParmList *l);
String *emit_action(Node *n);
int emit_action_code(Node *n, String *wrappercode, String *action);
void Swig_overload_check(Node *n);
String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *);
String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *, const_String_or_char_ptr fmt_fastdispatch = 0);
String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *);
String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *);
List *Swig_overload_rank(Node *n, bool script_lang_wrapping);
SwigType *cplus_value_type(SwigType *t);
@ -385,20 +400,12 @@ String *Swig_csuperclass_call(String *base, String *method, ParmList *l);
String *Swig_class_declaration(Node *n, String *name);
String *Swig_class_name(Node *n);
String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms);
String *Swig_method_decl(SwigType *rtype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values);
String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args);
String *Swig_director_declaration(Node *n);
void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
void Swig_director_parms_fixup(ParmList *parms);
/* directors.cxx end */
extern "C" {
void SWIG_typemap_lang(const char *);
typedef Language *(*ModuleFactory) (void);
}
void Swig_register_module(const char *name, ModuleFactory fac);
ModuleFactory Swig_find_module(const char *name);
/* Utilities */
int is_public(Node *n);

View file

@ -15,7 +15,7 @@
#include "cparse.h"
static const char *usage = "\
Tcl 8 Options (available with -tcl)\n\
Tcl 8 Options (available with -tcl8)\n\
-itcl - Enable ITcl support\n\
-nosafe - Leave out SafeInit module function.\n\
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
@ -76,7 +76,6 @@ public:
* ------------------------------------------------------------ */
virtual void main(int argc, char *argv[]) {
int cppcast = 1;
SWIG_library_directory("tcl");
@ -106,22 +105,19 @@ public:
} else if (strcmp(argv[i], "-nosafe") == 0) {
nosafe = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-cppcast") == 0) {
cppcast = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
cppcast = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-help") == 0) {
fputs(usage, stdout);
} else if (strcmp(argv[i], "-cppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-nocppcast") == 0) {
Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
Swig_mark_arg(i);
SWIG_exit(EXIT_FAILURE);
}
}
}
if (cppcast) {
Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
}
Preprocessor_define("SWIGTCL 1", 0);
// SWIGTCL8 is deprecated, and no longer documented.
Preprocessor_define("SWIGTCL8 1", 0);

View file

@ -187,8 +187,10 @@ class TypePass:private Dispatcher {
ilist = alist = NewList();
Append(ilist, bcls);
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
}
}
}
break;
@ -209,8 +211,10 @@ class TypePass:private Dispatcher {
ilist = alist = NewList();
Append(ilist, bcls);
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
}
}
} else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
@ -566,6 +570,10 @@ class TypePass:private Dispatcher {
SwigType_typedef_class(rname);
Delete(rname);
/* SwigType_typedef_class(name); */
} else if (Strcmp(ttype, "cdecl") == 0) {
String *rname = SwigType_typedef_resolve_all(name);
SwigType_typedef_class(rname);
Delete(rname);
}
return SWIG_OK;
}
@ -1195,10 +1203,7 @@ class TypePass:private Dispatcher {
} else if (Strcmp(ntype, "enum") == 0) {
SwigType_typedef_using(Getattr(n, "uname"));
} else if (Strcmp(ntype, "template") == 0) {
/*
Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname"));
SwigType_typedef_using(Getattr(n, "uname"));
*/
}
}
}

View file

@ -363,23 +363,24 @@ int UFFI::classHandler(Node *n) {
for (c = firstChild(n); c; c = nextSibling(c)) {
SwigType *type = Getattr(c, "type");
SwigType *decl = Getattr(c, "decl");
type = Copy(type);
SwigType_push(type, decl);
String *lisp_type;
if (type) {
type = Copy(type);
SwigType_push(type, decl);
String *lisp_type;
if (Strcmp(nodeType(c), "cdecl")) {
Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name);
Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type"));
SWIG_exit(EXIT_FAILURE);
if (Strcmp(nodeType(c), "cdecl")) {
Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name);
Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type"));
SWIG_exit(EXIT_FAILURE);
}
/* Printf(stdout, "Converting %s in %s\n", type, name); */
lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name"));
Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type);
Delete(lisp_type);
}
/* Printf(stdout, "Converting %s in %s\n", type, name); */
lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name"));
Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type);
Delete(lisp_type);
}
// Language::classHandler(n);

View file

@ -59,7 +59,7 @@ int is_non_virtual_protected_access(Node *n) {
// When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done.
// However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded()
// which calls is_non_virtual_protected_access. So commented out below.
// Moving the director vtable creation into into Typepass should solve this problem.
// Moving the director vtable creation into Typepass should solve this problem.
if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/)
result = 1;
}

View file

@ -144,8 +144,8 @@ public:
Xml_print_kwargs(Getattr(obj, k));
} else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) {
Xml_print_parmlist(Getattr(obj, k));
} else if (Cmp(k, "catchlist") == 0) {
Xml_print_parmlist(Getattr(obj, k), "catchlist");
} else if (Cmp(k, "catchlist") == 0 || Cmp(k, "templateparms") == 0) {
Xml_print_parmlist(Getattr(obj, k), Char(k));
} else {
DOH *o;
print_indent(0);

View file

@ -109,6 +109,19 @@ static String *cpp_include(const_String_or_char_ptr fn, int sysfile) {
return s;
}
static int is_digits(const String *str) {
const char *s = Char(str);
int isdigits = (*s != 0);
while (*s) {
if (!isdigit(*s)) {
isdigits = 0;
break;
}
s++;
}
return isdigits;
}
List *Preprocessor_depend(void) {
return dependencies;
}
@ -607,6 +620,34 @@ static List *find_args(String *s, int ismacro, String *macro_name) {
skip_tochar(s, '\'', str);
c = Getc(s);
continue;
} else if (c == '/') {
/* Ensure comments are ignored by eating up the characters */
c = Getc(s);
/* Handle / * ... * / type comments (multi-line) */
if (c == '*') {
while ((c = Getc(s)) != EOF) {
if (c == '*') {
c = Getc(s);
if (c == '/' || c == EOF)
break;
}
}
c = Getc(s);
continue;
}
/* Handle // ... type comments (single-line) */
if (c == '/') {
while ((c = Getc(s)) != EOF) {
if (c == '\n') {
break;
}
}
c = Getc(s);
continue;
}
/* ensure char is available in the stream as this was not a comment*/
Ungetc(c, s);
c = '/';
}
if ((c == ',') && (level == 0))
break;
@ -623,13 +664,8 @@ static List *find_args(String *s, int ismacro, String *macro_name) {
goto unterm;
}
Chop(str);
if (Len(args) || Len(str))
Append(args, str);
Append(args, str);
Delete(str);
/* if (Len(str) && (c != ')'))
Append(args,str); */
if (c == ')')
return args;
c = Getc(s);
@ -800,11 +836,24 @@ static String *expand_macro(String *name, List *args, String *line_file) {
Delete(vararg);
}
}
if (args && margs && Len(margs) == 0 && Len(args) == 1 && Len(Getitem(args, 0)) == 0) {
/* FOO() can invoke a macro defined as FOO(X) as well as one defined FOO().
*
* Handle this by removing the only argument if it's empty and the macro
* expects no arguments.
*
* We don't need to worry about varargs here - a varargs macro will always have
* Len(margs) >= 1, since the varargs are put in the final macro argument.
*/
Delitem(args, 0);
}
/* If there are arguments, see if they match what we were given */
if (args && (margs) && (Len(margs) != Len(args))) {
if (Len(margs) > (1 + isvarargs))
if (args && (!margs || Len(margs) != Len(args))) {
if (margs && Len(margs) > (1 + isvarargs))
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
else if (Len(margs) == (1 + isvarargs))
else if (margs && Len(margs) == (1 + isvarargs))
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name);
else
Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name);
@ -813,7 +862,7 @@ static String *expand_macro(String *name, List *args, String *line_file) {
}
/* If the macro expects arguments, but none were supplied, we leave it in place */
if (!args && (margs) && Len(margs) > 0) {
if (!args && margs) {
macro_level--;
return NewString(name);
}
@ -905,19 +954,21 @@ static String *expand_macro(String *name, List *args, String *line_file) {
namelen = Len(aname);
a = strstr(s, name);
while (a) {
char ca = a[namelen + 1];
char ca = a[namelen];
if (!isidchar((int) ca)) {
/* Matched the entire vararg name, not just a prefix */
t = a - 1;
if (*t == '\002') {
t--;
while (t >= s) {
if (isspace((int) *t))
t--;
else if (*t == ',') {
*t = ' ';
} else
break;
if (a > s) {
t = a - 1;
if (*t == '\002') {
t--;
while (t >= s) {
if (isspace((int) *t))
t--;
else if (*t == ',') {
*t = ' ';
} else
break;
}
}
}
}
@ -1139,10 +1190,6 @@ static DOH *Preprocessor_replace(DOH *s) {
args = find_args(s, 1, id);
macro_additional_lines = Getline(s) - line;
assert(macro_additional_lines >= 0);
if (!Len(args)) {
Delete(args);
args = 0;
}
} else {
args = 0;
}
@ -1431,7 +1478,7 @@ String *Preprocessor_parse(String *s) {
break;
case 41: /* Build up the name of the preprocessor directive */
if ((isspace(c) || (!isalpha(c)))) {
if ((isspace(c) || (!isidchar(c)))) {
Clear(value);
Clear(comment);
if (c == '\n') {
@ -1450,7 +1497,7 @@ String *Preprocessor_parse(String *s) {
Putc(c, id);
break;
case 42: /* Strip any leading space before preprocessor value */
case 42: /* Strip any leading space after the preprocessor directive (before preprocessor value) */
if (isspace(c)) {
if (c == '\n') {
Ungetc(c, s);
@ -1459,7 +1506,7 @@ String *Preprocessor_parse(String *s) {
break;
}
state = 43;
/* no break intended here */
/* FALL THRU */
case 43:
/* Get preprocessor value */
@ -1770,6 +1817,8 @@ String *Preprocessor_parse(String *s) {
Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level);
} else if (Equal(id, "")) {
/* Null directive */
} else if (is_digits(id)) {
/* A gcc linemarker of the form '# linenum filename flags' (resulting from running gcc -E) */
} else {
/* Ignore unknown preprocessor directives which are inside an inactive
* conditional (github issue #394). */

View file

@ -188,12 +188,22 @@ static int reduce_op() {
sp--;
break;
case SWIG_TOKEN_SLASH:
stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
sp -= 2;
if (stack[sp].value != 0) {
stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
sp -= 2;
} else {
errmsg = "Division by zero in expression";
return 0;
}
break;
case SWIG_TOKEN_PERCENT:
stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
sp -= 2;
if (stack[sp].value != 0) {
stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
sp -= 2;
} else {
errmsg = "Modulo by zero in expression";
return 0;
}
break;
case SWIG_TOKEN_LSHIFT:
stack[sp - 2].value = stack[sp - 2].value << stack[sp].value;
@ -309,6 +319,10 @@ int Preprocessor_expr(DOH *s, int *error) {
stack[sp].value = 0;
stack[sp].svalue = 0;
stack[sp].op = EXPR_VALUE;
} else if ((token == SWIG_TOKEN_FLOAT) || (token == SWIG_TOKEN_DOUBLE)) {
errmsg = "Floating point constant in preprocessor expression";
*error = 1;
return 0;
} else
goto syntax_error;
break;

View file

@ -277,7 +277,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) {
SwigType_del_rvalue_reference(tvalue);
tycode = SwigType_type(tvalue);
if (tycode != T_USER) {
/* plain primitive type, we copy the the def value */
/* plain primitive type, we copy the def value */
String *lstr = SwigType_lstr(tvalue, defname);
defvalue = NewStringf("%s = %s", lstr, qvalue);
Delete(lstr);
@ -1024,6 +1024,15 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas
}
}
if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) {
String *memory_header = NewString("<memory>");
Setfile(memory_header, Getfile(n));
Setline(memory_header, Getline(n));
Swig_fragment_emit(memory_header);
self = NewString("std::move(*this).");
Delete(memory_header);
}
call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);

View file

@ -106,13 +106,16 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c
}
if (warnall || wrn) {
String *formatted_filename = format_filename(filename);
String *full_message = NewString("");
if (wnum) {
Printf(stderr, wrn_wnum_fmt, formatted_filename, line, wnum);
Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum);
} else {
Printf(stderr, wrn_nnum_fmt, formatted_filename, line);
Printf(full_message, wrn_nnum_fmt, formatted_filename, line);
}
Printf(stderr, "%s", msg);
Printf(full_message, "%s", msg);
Printv(stderr, full_message, NIL);
nwarning++;
Delete(full_message);
Delete(formatted_filename);
}
Delete(out);
@ -128,6 +131,7 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c
void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
va_list ap;
String *formatted_filename = NULL;
String *full_message = NULL;
if (silence)
return;
@ -136,14 +140,17 @@ void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ..
va_start(ap, fmt);
formatted_filename = format_filename(filename);
full_message = NewString("");
if (line > 0) {
Printf(stderr, err_line_fmt, formatted_filename, line);
Printf(full_message, err_line_fmt, formatted_filename, line);
} else {
Printf(stderr, err_eof_fmt, formatted_filename);
Printf(full_message, err_eof_fmt, formatted_filename);
}
vPrintf(stderr, fmt, ap);
vPrintf(full_message, fmt, ap);
Printv(stderr, full_message, NIL);
va_end(ap);
nerrors++;
Delete(full_message);
Delete(formatted_filename);
}

View file

@ -106,10 +106,10 @@ void Swig_extend_append_previous(Node *cls, Node *am) {
set_nextSibling(n,0);
/* typemaps and fragments need to be prepended */
if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0))) {
if (!pe) pe = new_node("extend");
if (!pe) pe = Swig_cparse_new_node("extend");
appendChild(pe, n);
} else {
if (!ae) ae = new_node("extend");
if (!ae) ae = Swig_cparse_new_node("extend");
appendChild(ae, n);
}
n = ne;

View file

@ -523,7 +523,7 @@ String *Swig_string_ucase(String *s) {
/* We insert a underscore when:
1. Lower case char followed by upper case char
getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo
2. Number proceded by char and not end of string
2. Number preceded by char and not end of string
get2D > get_2d; get22D > get_22d; GET2D > get_2d
but:
asFloat2 > as_float2
@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) {
/* -----------------------------------------------------------------------------
* Swig_scopename_prefix()
* Swig_scopename_split()
*
* Take a qualified name like "A::B::C" and return the scope name.
* In this case, "A::B". Returns NULL if there is no base.
* Take a qualified name like "A::B::C" and splits off the last name.
* In this case, returns "C" as last and "A::B" as prefix.
* Always returns non NULL for last, but prefix may be NULL if there is no prefix.
* ----------------------------------------------------------------------------- */
void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
}
}
/* -----------------------------------------------------------------------------
* Swig_scopename_prefix()
*
* Take a qualified name like "A::B::C" and return the scope name.
* In this case, "A::B". Returns NULL if there is no base.
* ----------------------------------------------------------------------------- */
String *Swig_scopename_prefix(const String *s) {
char *tmp = Char(s);
@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) {
}
}
/* -----------------------------------------------------------------------------
* Swig_scopename_tolist()
*
* Take a qualified scope name like "A::B::C" and convert it to a list.
* In this case, return a list of 3 elements "A", "B", "C".
* Returns an empty list if the input is empty.
* ----------------------------------------------------------------------------- */
List *Swig_scopename_tolist(const String *s) {
List *scopes = NewList();
String *name = Len(s) == 0 ? 0 : NewString(s);
while (name) {
String *last = 0;
String *prefix = 0;
Swig_scopename_split(name, &prefix, &last);
Insert(scopes, 0, last);
Delete(last);
Delete(name);
name = prefix;
}
Delete(name);
return scopes;
}
/* -----------------------------------------------------------------------------
* Swig_scopename_check()
*
@ -1117,19 +1149,17 @@ int Swig_scopename_check(const String *s) {
*
* Printf(stderr,"%(command:sed 's/[a-z]/\U\\1/' <<<)s","hello") -> Hello
* ----------------------------------------------------------------------------- */
#if defined(HAVE_POPEN)
# if defined(_MSC_VER)
# define popen _popen
# define pclose _pclose
# else
extern FILE *popen(const char *command, const char *type);
extern int pclose(FILE *stream);
#if defined(_MSC_VER)
# define popen _popen
# define pclose _pclose
# if !defined(HAVE_POPEN)
# define HAVE_POPEN 1
# endif
#else
# if defined(_MSC_VER)
# define HAVE_POPEN 1
# define popen _popen
# define pclose _pclose
# if !defined(_WIN32)
/* These Posix functions are not ISO C and so are not always defined in stdio.h */
extern FILE *popen(const char *command, const char *type);
extern int pclose(FILE *stream);
# endif
#endif
@ -1208,7 +1238,7 @@ String *Swig_string_rstrip(String *s) {
String *suffix = NewStringf(fmt, cs+1);
int suffix_len = Len(suffix);
if (0 == Strncmp(cs+len-suffix_len, suffix, suffix_len)) {
int copy_len = len-suffix_len-(ce+1-cs);
int copy_len = len-suffix_len-(int)(ce+1-cs);
ns = NewStringWithSize(ce+1, copy_len);
} else {
ns = NewString(ce+1);
@ -1454,6 +1484,17 @@ String *Swig_pcre_version(void) {
#endif
/* ------------------------------------------------------------
* Swig_is_generated_overload()
* Check if the function is an automatically generated
* overload created because a method has default parameters.
* ------------------------------------------------------------ */
int Swig_is_generated_overload(Node *n) {
Node *base_method = Getattr(n, "sym:overloaded");
Node *default_args = Getattr(n, "defaultargs");
return ((base_method != NULL) && (default_args != NULL) && (base_method == default_args));
}
/* -----------------------------------------------------------------------------
* Swig_init()
*

View file

@ -404,7 +404,17 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType
}
Delete(cls);
}
/* A template-based class lookup, check name first */
/* Lookup a name within a templated-based class */
if (!rn) {
String *t_name = SwigType_istemplate_templateprefix(prefix);
if (t_name) {
Clear(tname);
Printf(tname, "%s::%s", t_name, name);
rn = name_object_get(namehash, tname, decl, ncdecl);
Delete(t_name);
}
}
/* Lookup a template-based name within a class */
if (!rn) {
String *t_name = SwigType_istemplate_templateprefix(name);
if (t_name)
@ -429,8 +439,8 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType
rn = name_object_get(namehash, name, decl, ncdecl);
}
if (!rn && Swig_scopename_check(name)) {
String *nprefix = NewStringEmpty();
String *nlast = NewStringEmpty();
String *nprefix = 0;
String *nlast = 0;
Swig_scopename_split(name, &nprefix, &nlast);
rn = name_object_get(namehash, nlast, decl, ncdecl);
Delete(nlast);
@ -569,8 +579,8 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d
if (name && SwigType_istemplate(name)) {
String *nodetype = nodeType(node);
if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
String *nprefix = NewStringEmpty();
String *nlast = NewStringEmpty();
String *nprefix = 0;
String *nlast = 0;
String *tprefix;
Swig_scopename_split(name, &nprefix, &nlast);
tprefix = SwigType_templateprefix(nlast);
@ -789,6 +799,8 @@ static int need_name_warning(Node *n) {
need = 0;
} else if (Getattr(n, "templatetype")) {
need = 0;
} else if (GetFlag(n, "parsing_template_declaration")) {
need = 0;
}
return need;
}
@ -1043,7 +1055,7 @@ static void name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, S
Setattr(nameobj, "decl", decl);
if (nname && Len(nname))
Setattr(nameobj, "targetname", nname);
/* put the new nameobj at the beginnig of the list, such that the
/* put the new nameobj at the beginning of the list, such that the
last inserted rule take precedence */
Insert(name_list, 0, nameobj);
} else {
@ -1365,12 +1377,15 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne
}
/* Create a name applying rename/namewarn if needed */
static String *apply_rename(String *newname, int fullname, String *prefix, String *name) {
/* Create a name for the given node applying rename/namewarn if needed */
static String *apply_rename(Node* n, String *newname, int fullname, String *prefix, String *name) {
String *result = 0;
if (newname && Len(newname)) {
if (Strcmp(newname, "$ignore") == 0) {
result = Copy(newname);
/* $ignore doesn't apply to parameters and while it's rare to explicitly write %ignore directives for them they could be caught by a wildcard ignore using
regex match, just ignore the attempt to ignore them in this case */
if (!Equal(nodeType(n), "parm"))
result = Copy(newname);
} else {
char *cnewname = Char(newname);
if (cnewname) {
@ -1419,8 +1434,8 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname,
if (name && n && SwigType_istemplate(name)) {
String *nodetype = nodeType(n);
if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
String *nprefix = NewStringEmpty();
String *nlast = NewStringEmpty();
String *nprefix = 0;
String *nlast = 0;
String *tprefix;
Swig_scopename_split(name, &nprefix, &nlast);
tprefix = SwigType_templateprefix(nlast);
@ -1468,7 +1483,7 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname,
if (rn) {
String *newname = Getattr(rn, "name");
int fullname = GetFlag(rn, "fullname");
result = apply_rename(newname, fullname, prefix, name);
result = apply_rename(n, newname, fullname, prefix, name);
}
if (result && !Equal(result, name)) {
/* operators in C++ allow aliases, we look for them */
@ -1492,13 +1507,19 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname,
int fullname = GetFlag(wrn, "fullname");
if (result)
Delete(result);
result = apply_rename(rename, fullname, prefix, name);
result = apply_rename(n, rename, fullname, prefix, name);
if ((msg) && (Len(msg))) {
if (!Getmeta(nname, "already_warned")) {
if (n) {
SWIG_WARN_NODE_BEGIN(n);
Swig_warning(0, Getfile(n), Getline(n), "%s\n", msg);
SWIG_WARN_NODE_END(n);
/* Parameter renaming is not fully implemented. Mainly because there is no C/C++ syntax to
* for %rename to fully qualify a function's parameter name from outside the function. Hence it
* is not possible to implemented targetted warning suppression on one parameter in one function. */
int suppress_parameter_rename_warning = Equal(nodeType(n), "parm");
if (!suppress_parameter_rename_warning) {
SWIG_WARN_NODE_BEGIN(n);
Swig_warning(0, Getfile(n), Getline(n), "%s\n", msg);
SWIG_WARN_NODE_END(n);
}
} else {
Swig_warning(0, Getfile(name), Getline(name), "%s\n", msg);
}
@ -1638,12 +1659,13 @@ String *Swig_name_str(Node *n) {
if (SwigType_istemplate(name)) {
String *nodetype = nodeType(n);
if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
String *nprefix = NewStringEmpty();
String *nlast = NewStringEmpty();
String *nprefix = 0;
String *nlast = 0;
String *tprefix;
Swig_scopename_split(name, &nprefix, &nlast);
tprefix = SwigType_templateprefix(nlast);
Delete(nlast);
Delete(nprefix);
Delete(name);
name = tprefix;
}
@ -1669,6 +1691,7 @@ String *Swig_name_str(Node *n) {
* "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate()"
* "MyNameSpace::ABC::ABC(int,double)"
* "MyNameSpace::ABC::constmethod(int) const"
* "MyNameSpace::ABC::refqualifiermethod(int) const &"
* "MyNameSpace::ABC::variablename"
*
* ----------------------------------------------------------------------------- */
@ -1678,11 +1701,22 @@ String *Swig_name_decl(Node *n) {
String *decl;
qname = Swig_name_str(n);
decl = NewStringf("%s", qname);
if (checkAttribute(n, "kind", "variable"))
decl = NewStringf("%s", qname);
else
decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : "");
if (!checkAttribute(n, "kind", "variable")) {
String *d = Getattr(n, "decl");
Printv(decl, "(", ParmList_errorstr(Getattr(n, "parms")), ")", NIL);
if (SwigType_isfunction(d)) {
SwigType *decl_temp = Copy(d);
SwigType *qualifiers = SwigType_pop_function_qualifiers(decl_temp);
if (qualifiers) {
String *qualifiers_string = SwigType_str(qualifiers, 0);
Printv(decl, " ", qualifiers_string, NIL);
Delete(qualifiers_string);
}
Delete(decl_temp);
}
}
Delete(qname);

View file

@ -254,3 +254,19 @@ int ParmList_has_defaultargs(ParmList *p) {
}
return 0;
}
/* ---------------------------------------------------------------------
* ParmList_has_varargs()
*
* Returns 1 if the parameter list passed in has varargs.
* Otherwise returns 0.
* ---------------------------------------------------------------------- */
int ParmList_has_varargs(ParmList *p) {
Parm *lp = 0;
while (p) {
lp = p;
p = nextSibling(p);
}
return lp ? SwigType_isvarargs(Getattr(lp, "type")) : 0;
}

View file

@ -749,11 +749,18 @@ static int look(Scanner *s) {
}
if (Strcmp( str_delimiter, end_delimiter )==0) {
Delete( end_delimiter ); /* Correct end delimiter )XXXX" occured */
int len = Len(s->text);
Delslice(s->text, len - 2 - Len(str_delimiter), len); /* Delete ending )XXXX" */
Delslice(s->text, 0, Len(str_delimiter) + 1); /* Delete starting XXXX( */
Delete( end_delimiter ); /* Correct end delimiter )XXXX" occurred */
Delete( str_delimiter );
str_delimiter = 0;
return SWIG_TOKEN_STRING;
} else { /* Incorrect end delimiter occured */
} else { /* Incorrect end delimiter occurred */
if (c == 0) {
Swig_error(cparse_file, cparse_start_line, "Unterminated raw string, started with R\"%s( is not terminated by )%s\"\n", str_delimiter, str_delimiter);
return SWIG_TOKEN_ERROR;
}
retract( s, i );
Delete( end_delimiter );
}
@ -931,10 +938,14 @@ static int look(Scanner *s) {
retract(s, 1);
state = 1000;
}
else if (c == '\'') { /* Definitely u, U or L char */
retract(s, 1);
state = 77;
}
else if (c == 'R') { /* Possibly CUSTOM DELIMITER u, U, L string */
state = 73;
}
else if (c == '8') { /* Possibly u8 string */
else if (c == '8') { /* Possibly u8 string/char */
state = 71;
}
else {
@ -954,7 +965,7 @@ static int look(Scanner *s) {
}
break;
case 71: /* Possibly u8 string */
case 71: /* Possibly u8 string/char */
if ((c = nextchar(s)) == 0) {
state = 76;
}
@ -962,6 +973,10 @@ static int look(Scanner *s) {
retract(s, 1); /* Definitely u8 string */
state = 1000;
}
else if (c=='\'') {
retract(s, 1); /* Definitely u8 char */
state = 77;
}
else if (c=='R') {
state = 74; /* Possibly CUSTOM DELIMITER u8 string */
}
@ -1114,27 +1129,29 @@ static int look(Scanner *s) {
break;
case 82:
if ((c = nextchar(s)) == 0) {
retract(s, 1);
return SWIG_TOKEN_INT;
Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
return SWIG_TOKEN_ERROR;
}
if ((isdigit(c)) || (c == '-') || (c == '+'))
state = 86;
else {
retract(s, 2);
return (SWIG_TOKEN_INT);
Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
return SWIG_TOKEN_ERROR;
}
break;
case 820:
/* Like case 82, but we've seen a decimal point. */
if ((c = nextchar(s)) == 0) {
retract(s, 1);
return SWIG_TOKEN_DOUBLE;
Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
return SWIG_TOKEN_ERROR;
}
if ((isdigit(c)) || (c == '-') || (c == '+'))
state = 86;
else {
retract(s, 2);
return (SWIG_TOKEN_DOUBLE);
Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
return SWIG_TOKEN_ERROR;
}
break;
case 83:
@ -1143,8 +1160,12 @@ static int look(Scanner *s) {
return SWIG_TOKEN_INT;
if (isdigit(c))
state = 84;
else if ((c == 'e') || (c == 'E'))
state = 82;
else if ((c == 'x') || (c == 'X'))
state = 85;
else if ((c == 'b') || (c == 'B'))
state = 850;
else if (c == '.')
state = 81;
else if ((c == 'l') || (c == 'L')) {
@ -1162,6 +1183,10 @@ static int look(Scanner *s) {
return SWIG_TOKEN_INT;
if (isdigit(c))
state = 84;
else if (c == '.')
state = 81;
else if ((c == 'e') || (c == 'E'))
state = 82;
else if ((c == 'l') || (c == 'L')) {
state = 87;
} else if ((c == 'u') || (c == 'U')) {
@ -1177,6 +1202,10 @@ static int look(Scanner *s) {
return SWIG_TOKEN_INT;
if (isxdigit(c))
state = 85;
else if (c == '.') /* hexadecimal float */
state = 860;
else if ((c == 'p') || (c == 'P')) /* hexadecimal float */
state = 820;
else if ((c == 'l') || (c == 'L')) {
state = 87;
} else if ((c == 'u') || (c == 'U')) {
@ -1186,7 +1215,37 @@ static int look(Scanner *s) {
return SWIG_TOKEN_INT;
}
break;
case 850:
/* This is a binary number */
if ((c = nextchar(s)) == 0)
return SWIG_TOKEN_INT;
if ((c == '0') || (c == '1'))
state = 850;
else if ((c == 'l') || (c == 'L')) {
state = 87;
} else if ((c == 'u') || (c == 'U')) {
state = 88;
} else {
retract(s, 1);
return SWIG_TOKEN_INT;
}
break;
case 860:
/* hexadecimal float */
if ((c = nextchar(s)) == 0) {
Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
return SWIG_TOKEN_ERROR;
}
if (isxdigit(c))
state = 860;
else if ((c == 'p') || (c == 'P'))
state = 820;
else {
retract(s, 2);
Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
return SWIG_TOKEN_ERROR;
}
break;
case 86:
/* Rest of floating point number */

View file

@ -44,8 +44,8 @@
* 'z.' = Rvalue reference (&&)
* 'a(n).' = Array of size n [n]
* 'f(..,..).' = Function with arguments (args)
* 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
* 'm(qual).' = Pointer to member (qual::*)
* 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
* 'm(cls).' = Pointer to member (cls::*)
*
* The encoding follows the order that you might describe a type in words.
* For example "p.a(200).int" is "A pointer to array of int's" and
@ -62,6 +62,22 @@
*
* Replace(t,"q(const).","",DOH_REPLACE_ANY)
*
* More examples:
*
* String Encoding C++ Example
* --------------- -----------
* p.f(bool).r.q(const).long const long & (*)(bool)
* m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const
* r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int)
* m(Funcs).z.q(const).f(bool).long long (Funcs::*)(bool) const &&
*
* Function decl examples:
*
* f(bool). long a(bool);
* r.f(bool). long b(bool) &;
* z.f(bool). long c(bool) &&;
* z.q(const).f(bool). long d(bool) const &&;
*
* For the most part, this module tries to minimize the use of special
* characters (*, [, <, etc...) in its type encoding. One reason for this
* is that SWIG might be extended to encode data in formats such as XML
@ -372,7 +388,7 @@ SwigType *SwigType_default_create(const SwigType *ty) {
* and is very close to the type deduction used in partial template class
* specialization matching in that the most specialized type is always chosen.
* SWIGTYPE is used as the generic type. The basic idea is to repeatedly call
* this function to find a deduced type unless until nothing matches.
* this function to find a deduced type until nothing matches.
*
* The type t must have already been converted to the default type via a call to
* SwigType_default_create() before calling this function.
@ -528,6 +544,7 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
String *element = 0;
String *nextelement;
String *forwardelement;
SwigType *member_function_qualifiers = 0;
List *elements;
int nelements, i;
@ -560,11 +577,13 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
forwardelement = 0;
}
if (SwigType_isqualifier(element)) {
DOH *q = 0;
q = SwigType_parm(element);
Insert(result, 0, " ");
Insert(result, 0, q);
Delete(q);
if (!member_function_qualifiers) {
DOH *q = 0;
q = SwigType_parm(element);
Insert(result, 0, " ");
Insert(result, 0, q);
Delete(q);
}
} else if (SwigType_ispointer(element)) {
Insert(result, 0, "*");
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
@ -580,16 +599,28 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
Insert(result, 0, "(");
Append(result, ")");
}
{
String *next3elements = NewStringEmpty();
int j;
for (j = i + 1; j < i + 4 && j < nelements; j++) {
Append(next3elements, Getitem(elements, j));
}
if (SwigType_isfunction(next3elements))
member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
Delete(next3elements);
}
Delete(q);
} else if (SwigType_isreference(element)) {
Insert(result, 0, "&");
if (!member_function_qualifiers)
Insert(result, 0, "&");
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
} else if (SwigType_isrvalue_reference(element)) {
Insert(result, 0, "&&");
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
if (!member_function_qualifiers)
Insert(result, 0, "&&");
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
@ -613,6 +644,14 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
Append(result, ",");
}
Append(result, ")");
if (member_function_qualifiers) {
String *p = SwigType_str(member_function_qualifiers, 0);
Append(result, " ");
Append(result, p);
Delete(p);
Delete(member_function_qualifiers);
member_function_qualifiers = 0;
}
Delete(parms);
} else {
if (strcmp(Char(element), "v(...)") == 0) {
@ -645,6 +684,7 @@ SwigType *SwigType_ltype(const SwigType *s) {
int nelements, i;
int firstarray = 1;
int notypeconv = 0;
int ignore_member_function_qualifiers = 0;
result = NewStringEmpty();
tc = Copy(s);
@ -671,6 +711,7 @@ SwigType *SwigType_ltype(const SwigType *s) {
tc = td;
}
}
elements = SwigType_split(tc);
nelements = Len(elements);
@ -680,14 +721,33 @@ SwigType *SwigType_ltype(const SwigType *s) {
/* when we see a function, we need to preserve the following types */
if (SwigType_isfunction(element)) {
notypeconv = 1;
ignore_member_function_qualifiers = 0;
}
if (SwigType_isqualifier(element)) {
/* Do nothing. Ignore */
if (ignore_member_function_qualifiers) {
/* cv-qualifiers and ref-qualifiers up until the f() element have already been added */
} else if (SwigType_isqualifier(element)) {
/* swallow cv-qualifiers */
} else if (SwigType_ispointer(element)) {
Append(result, element);
firstarray = 0;
} else if (SwigType_ismemberpointer(element)) {
Append(result, element);
{
String *next3elements = NewStringEmpty();
int j;
for (j = i + 1; j < i + 4 && j < nelements; j++) {
Append(next3elements, Getitem(elements, j));
}
if (SwigType_isfunction(next3elements)) {
SwigType *member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
/* compilers won't let us cast from a member function without qualifiers to one with qualifiers, so the qualifiers are kept in the ltype */
if (member_function_qualifiers)
Append(result, member_function_qualifiers);
Delete(member_function_qualifiers);
ignore_member_function_qualifiers = 1;
}
Delete(next3elements);
}
firstarray = 0;
} else if (SwigType_isreference(element)) {
if (notypeconv) {
@ -727,13 +787,14 @@ SwigType *SwigType_ltype(const SwigType *s) {
}
/* -----------------------------------------------------------------------------
* SwigType_lstr(DOH *s, DOH *id)
* SwigType_lstr()
*
* Produces a type-string that is suitable as a lvalue in an expression.
* That is, a type that can be freely assigned a value without violating
* any C assignment rules.
*
* - Qualifiers such as 'const' and 'volatile' are stripped.
* Except for member function cv-qualifiers and ref-qualifiers.
* - Arrays are converted into a *single* pointer (i.e.,
* double [][] becomes double *).
* - References are converted into a pointer.
@ -763,6 +824,7 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
String *element = 0;
String *nextelement;
String *forwardelement;
String *member_function_qualifiers = 0;
SwigType *td, *tc = 0;
const SwigType *rs;
List *elements;
@ -777,7 +839,10 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
if (SwigType_isconst(s)) {
tc = Copy(s);
Delete(SwigType_pop(tc));
rs = tc;
if (SwigType_ismemberpointer(tc))
rs = s;
else
rs = tc;
} else {
rs = s;
}
@ -816,12 +881,14 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
forwardelement = 0;
}
if (SwigType_isqualifier(element)) {
DOH *q = 0;
q = SwigType_parm(element);
Insert(result, 0, " ");
Insert(result, 0, q);
Delete(q);
clear = 0;
if (!member_function_qualifiers) {
DOH *q = 0;
q = SwigType_parm(element);
Insert(result, 0, " ");
Insert(result, 0, q);
Delete(q);
clear = 0;
}
} else if (SwigType_ispointer(element)) {
Insert(result, 0, "*");
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
@ -834,28 +901,42 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
Insert(result, 0, "::*");
q = SwigType_parm(element);
Insert(result, 0, q);
Delete(q);
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
{
String *next3elements = NewStringEmpty();
int j;
for (j = i + 1; j < i + 4 && j < nelements; j++) {
Append(next3elements, Getitem(elements, j));
}
if (SwigType_isfunction(next3elements))
member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
Delete(next3elements);
}
firstarray = 0;
Delete(q);
} else if (SwigType_isreference(element)) {
Insert(result, 0, "&");
if (!member_function_qualifiers) {
Insert(result, 0, "&");
if (!isfunction)
isreference = 1;
}
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
if (!isfunction)
isreference = 1;
} else if (SwigType_isrvalue_reference(element)) {
Insert(result, 0, "&&");
if (!member_function_qualifiers) {
Insert(result, 0, "&&");
if (!isfunction)
isreference = 1;
}
if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
if (!isfunction)
isreference = 1;
clear = 0;
} else if (SwigType_isarray(element)) {
DOH *size;
@ -885,6 +966,15 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
}
Append(result, ")");
Delete(parms);
if (member_function_qualifiers) {
String *p = SwigType_str(member_function_qualifiers, 0);
Append(result, " ");
Append(result, p);
Delete(p);
Delete(member_function_qualifiers);
member_function_qualifiers = 0;
clear = 0;
}
isfunction = 1;
} else {
String *bs = SwigType_namestr(element);
@ -1220,6 +1310,7 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
Putc(',', nt);
}
tsuffix = SwigType_templatesuffix(e);
SwigType_typename_replace(tsuffix, pat, rep);
Printf(nt, ")>%s", tsuffix);
Delete(tsuffix);
Clear(e);
@ -1228,13 +1319,24 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
Delete(tparms);
}
} else if (Swig_scopename_check(e)) {
String *first, *rest;
first = Swig_scopename_first(e);
rest = Swig_scopename_suffix(e);
SwigType_typename_replace(rest, pat, rep);
SwigType_typename_replace(first, pat, rep);
String *first = 0;
String *rest = 0;
Swig_scopename_split(e, &first, &rest);
/* Swig_scopename_split doesn't handle :: prefix very well ... could do with a rework */
if (Strncmp(rest, "::", 2) == 0) {
String *tmp = NewString(Char(rest) + 2);
Clear(rest);
Printv(rest, tmp, NIL);
Delete(tmp);
assert(!first);
}
Clear(e);
Printv(e, first, "::", rest, NIL);
if (first)
SwigType_typename_replace(first, pat, rep);
SwigType_typename_replace(rest, pat, rep);
Printv(e, first ? first : "", "::", rest, NIL);
Delete(first);
Delete(rest);
}

View file

@ -136,6 +136,7 @@ extern "C" {
extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms);
extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms);
extern SwigType *SwigType_pop_function(SwigType *t);
extern SwigType *SwigType_pop_function_qualifiers(SwigType *t);
extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node);
extern List *SwigType_split(const SwigType *t);
extern String *SwigType_pop(SwigType *t);
@ -187,7 +188,7 @@ extern "C" {
extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t);
extern SwigType *SwigType_alttype(const SwigType *t, int ltmap);
/* --- Type-system managment --- */
/* --- Type-system management --- */
extern void SwigType_typesystem_init(void);
extern int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name);
extern int SwigType_typedef_class(const_String_or_char_ptr name);
@ -326,6 +327,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern String *Swig_scopename_last(const String *s);
extern String *Swig_scopename_first(const String *s);
extern String *Swig_scopename_suffix(const String *s);
extern List *Swig_scopename_tolist(const String *s);
extern int Swig_scopename_check(const String *s);
extern String *Swig_string_lower(String *s);
extern String *Swig_string_upper(String *s);
@ -333,7 +335,9 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern void Swig_offset_string(String *s, int number);
extern String *Swig_pcre_version(void);
extern void Swig_init(void);
extern int Swig_value_wrapper_mode(int mode);
extern int Swig_is_generated_overload(Node *n);
typedef enum { EMF_STANDARD, EMF_MICROSOFT } ErrorMessageFormat;
@ -400,6 +404,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern);
extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat);
extern void Swig_typemap_clear_apply(ParmList *pattern);
extern void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node);
extern void Swig_typemap_debug(void);
extern void Swig_typemap_search_debug_set(void);
extern void Swig_typemap_used_debug_set(void);

View file

@ -24,6 +24,7 @@ extern ParmList *CopyParmListMax(ParmList *, int count);
extern int ParmList_len(ParmList *);
extern int ParmList_numrequired(ParmList *);
extern int ParmList_has_defaultargs(ParmList *p);
extern int ParmList_has_varargs(ParmList *p);
/* Output functions */
extern String *ParmList_str(ParmList *);

View file

@ -50,7 +50,7 @@ extern void Scanner_locator(Scanner *, String *loc);
#define SWIG_TOKEN_COLON 12 /* : */
#define SWIG_TOKEN_DCOLON 13 /* :: */
#define SWIG_TOKEN_DCOLONSTAR 14 /* ::* */
#define SWIG_TOKEN_ID 15 /* identifer */
#define SWIG_TOKEN_ID 15 /* identifier */
#define SWIG_TOKEN_FLOAT 16 /* 3.1415F */
#define SWIG_TOKEN_DOUBLE 17 /* 3.1415 */
#define SWIG_TOKEN_INT 18 /* 314 */

View file

@ -210,9 +210,10 @@ void Swig_symbol_print_tables_summary(void) {
* symbol_print_symbols()
* ----------------------------------------------------------------------------- */
static void symbol_print_symbols(const char *symboltabletype) {
static void symbol_print_symbols(const char *symboltabletype, const char *nextSibling) {
Node *table = symtabs;
Iterator ki = First(table);
int show_pointers = 0;
while (ki.key) {
String *k = ki.key;
Printf(stdout, "===================================================\n");
@ -222,10 +223,20 @@ static void symbol_print_symbols(const char *symboltabletype) {
Iterator it = First(symtab);
while (it.key) {
String *symname = it.key;
Printf(stdout, " %s (%s)\n", symname, nodeType(it.item));
/*
Printf(stdout, " %s - %p (%s)\n", symname, it.item, Getattr(it.item, "name"));
*/
Printf(stdout, " %s (%s)", symname, nodeType(it.item));
if (show_pointers)
Printf(stdout, " %p", it.item);
Printf(stdout, "\n");
{
Node *sibling = Getattr(it.item, nextSibling);
while (sibling) {
Printf(stdout, " %s (%s)", symname, nodeType(sibling));
if (show_pointers)
Printf(stdout, " %p", sibling);
Printf(stdout, "\n");
sibling = Getattr(sibling, nextSibling);
}
}
it = Next(it);
}
}
@ -241,7 +252,7 @@ static void symbol_print_symbols(const char *symboltabletype) {
void Swig_symbol_print_symbols(void) {
Printf(stdout, "SYMBOLS start =======================================\n");
symbol_print_symbols("symtab");
symbol_print_symbols("symtab", "sym:nextSibling");
Printf(stdout, "SYMBOLS finish =======================================\n");
}
@ -253,7 +264,7 @@ void Swig_symbol_print_symbols(void) {
void Swig_symbol_print_csymbols(void) {
Printf(stdout, "CSYMBOLS start =======================================\n");
symbol_print_symbols("csymtab");
symbol_print_symbols("csymtab", "csym:nextSibling");
Printf(stdout, "CSYMBOLS finish =======================================\n");
}
@ -518,7 +529,6 @@ void Swig_symbol_inherit(Symtab *s) {
void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
Node *append = 0;
Node *cn;
/* There are a few options for weak symbols. A "weak" symbol
is any symbol that can be replaced by another symbol in the C symbol
@ -600,7 +610,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
Setattr(ccurrent, name, n);
}
/* Multiple entries in the C symbol table. We append to to the symbol table */
/* Multiple entries in the C symbol table. We append to the symbol table */
if (append) {
Node *fn, *pn = 0;
cn = Getattr(ccurrent, name);
@ -691,7 +701,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
* ----------------------------------------------------------------------------- */
Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
Hash *c, *cn, *cl = 0;
Hash *c, *cl = 0;
SwigType *decl, *ndecl;
String *cstorage, *nstorage;
int nt = 0, ct = 0;
@ -757,10 +767,9 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
(1) A conflict between a class/enum and a typedef declaration is okay.
In this case, the symbol table entry is set to the class/enum declaration
itself, not the typedef.
(2) A conflict between namespaces is okay--namespaces are open
(3) Otherwise, overloading is only allowed for functions
(4) This special case is okay: a class template instantiated with same name as the template's name
*/
/* Check for namespaces */
@ -778,6 +787,25 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
Setattr(n, "sym:previousSibling", pcl);
return n;
}
/* Special case: class template instantiated with same name as the template's name eg: %template(X) X<int>; */
if (Equal(nodeType(c), "template")) {
String *nt1 = Getattr(c, "templatetype");
String *nt2 = nodeType(n);
if (Equal(nt1, "class") && Equal(nt1, nt2)) {
if (Getattr(n, "template")) {
/* Finally check that another %template with same name doesn't already exist */
if (!Getattr(c, "sym:nextSibling")) {
Setattr(c, "sym:nextSibling", n);
Setattr(n, "sym:symtab", current_symtab);
Setattr(n, "sym:name", symname);
Setattr(n, "sym:previousSibling", c);
return n;
}
}
}
}
if (Getattr(n, "allows_typedef"))
nt = 1;
if (Getattr(c, "allows_typedef"))
@ -858,7 +886,7 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
String *nt = Getattr(n, "nodeType");
int n_template = Equal(nt, "template") && Checkattr(n, "templatetype", "cdecl");
int n_plain_cdecl = Equal(nt, "cdecl");
cn = c;
Node *cn = c;
pn = 0;
while (cn) {
decl = Getattr(cn, "decl");
@ -1011,8 +1039,8 @@ static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symt
return 0;
if (!prefix) {
Node *n;
String *bname;
String *prefix;
String *bname = 0;
String *prefix = 0;
Swig_scopename_split(name, &prefix, &bname);
n = symbol_lookup_qualified(bname, symtab, prefix, local, checkfunc);
Delete(bname);
@ -1907,19 +1935,37 @@ SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) {
int len = Len(elements);
int i;
#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
static Hash *deftype_cache = 0;
String *scopetype = tscope ? NewStringf("%s::%s", Getattr(tscope, "name"), type)
static Hash *s_cache = 0;
Hash *scope_cache;
/* The lookup depends on the current scope and potential namespace qualification.
Looking up x in namespace y is not the same as looking up x::y in outer scope.
-> we use a 2-level hash: first scope and then symbol. */
String *scope_name = tscope
? Swig_symbol_qualifiedscopename(tscope)
: Swig_symbol_qualifiedscopename(current_symtab);
String *type_name = tscope
? NewStringf("%s::%s", Getattr(tscope, "name"), type)
: NewStringf("%s::%s", Swig_symbol_getscopename(), type);
if (!deftype_cache) {
deftype_cache = NewHash();
if (!scope_name) scope_name = NewString("::");
if (!s_cache) {
s_cache = NewHash();
}
if (scopetype) {
String *cres = Getattr(deftype_cache, scopetype);
scope_cache = Getattr(s_cache, scope_name);
if (scope_cache) {
String *cres = Getattr(scope_cache, type_name);
if (cres) {
Append(result, cres);
Delete(scopetype);
#ifdef SWIG_DEBUG
Printf(stderr, "cached deftype %s(%s) -> %s\n", type, scope_name, result);
#endif
Delete(type_name);
Delete(scope_name);
return result;
}
} else {
scope_cache = NewHash();
Setattr(s_cache, scope_name, scope_cache);
Delete(scope_name);
}
#endif
@ -2019,8 +2065,8 @@ SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) {
}
Delete(elements);
#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
Setattr(deftype_cache, scopetype, result);
Delete(scopetype);
Setattr(scope_cache, type_name, result);
Delete(type_name);
#endif
return result;

View file

@ -75,9 +75,11 @@ void Swig_print_node(Node *obj) {
if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) ||
(Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) {
/* Do nothing */
} else if (Cmp(k, "parms") == 0 || Cmp(k, "wrap:parms") == 0) {
} else if (Cmp(k, "kwargs") == 0 || Cmp(k, "parms") == 0 || Cmp(k, "wrap:parms") == 0 ||
Cmp(k, "pattern") == 0 || Cmp(k, "templateparms") == 0 || Cmp(k, "throws") == 0) {
print_indent(2);
Printf(stdout, "%-12s - %s\n", k, ParmList_str_defaultargs(Getattr(obj, k)));
/* Differentiate parameter lists by displaying within single quotes */
Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(Getattr(obj, k)));
} else {
DOH *o;
const char *trunc = "";

View file

@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper
static Hash *typemaps;
/* -----------------------------------------------------------------------------
* typemap_identifier_fix()
*
* Create a type that can be used as a hash key lookup independent of the various
* ways a template parameter list can be defined. This is achieved by fully
* resolving the template parameters.
*
* This is a copy and modification of feature_identifier_fix in parser.y.
* ----------------------------------------------------------------------------- */
static SwigType *typemap_identifier_fix(const SwigType *s) {
String *tp = SwigType_istemplate_templateprefix(s);
if (tp) {
String *ts, *ta, *tq, *tr;
ts = SwigType_templatesuffix(s);
ta = SwigType_templateargs(s);
tq = Swig_symbol_type_qualify(ta, 0);
tr = SwigType_typedef_resolve_all(ta);
Append(tp,tr);
Append(tp,ts);
Delete(ts);
Delete(ta);
Delete(tq);
Delete(tr);
return tp;
} else {
return NewString(s);
}
}
static Hash *get_typemap(const SwigType *type) {
Hash *tm = 0;
SwigType *dtype = 0;
SwigType *hashtype;
if (SwigType_istemplate(type)) {
String *ty = Swig_symbol_template_deftype(type, 0);
SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0);
dtype = Swig_symbol_type_qualify(ty, 0);
type = dtype;
Delete(ty);
@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) {
Hash *new_tm = 0;
assert(*tmhash == 0);
if (SwigType_istemplate(type)) {
SwigType *rty = SwigType_typedef_resolve_all(type);
SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0);
String *tyq = Swig_symbol_type_qualify(ty, 0);
hashtype = SwigType_remove_global_scope_prefix(tyq);
@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type
SwigType *oldctype = ctype;
ctype = SwigType_typedef_resolve(ctype_unstripped);
Delete(oldctype);
Delete(ctype_unstripped);
ctype_unstripped = Copy(ctype);
}
}
@ -1876,6 +1908,21 @@ static List *split_embedded_typemap(String *s) {
return args;
}
/* -----------------------------------------------------------------------------
* Swig_typemap_replace_embedded_typemap()
*
* For special variable macro $typemap(...) expansion outside of typemaps.
* Only limited usage works as most typemap special variables ($1, $input etc)
* are not expanded correctly outside of typemaps.
* ----------------------------------------------------------------------------- */
void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node) {
Setfile(s, Getfile(file_line_node));
Setline(s, Getline(file_line_node));
Replaceall(s, "$typemap", "$TYPEMAP");
replace_embedded_typemap(s, 0, 0, file_line_node);
}
/* -----------------------------------------------------------------------------
* replace_embedded_typemap()
*

View file

@ -43,12 +43,12 @@
* All type constructors are denoted by a trailing '.':
*
* 'p.' = Pointer (*)
* 'r.' = Reference (&)
* 'z.' = Rvalue reference (&&)
* 'r.' = Reference or ref-qualifier (&)
* 'z.' = Rvalue reference or ref-qualifier (&&)
* 'a(n).' = Array of size n [n]
* 'f(..,..).' = Function with arguments (args)
* 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
* 'm(qual).' = Pointer to member (qual::*)
* 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
* 'm(cls).' = Pointer to member (cls::*)
*
* The complete type representation for varargs is:
* 'v(...)'
@ -183,9 +183,10 @@ SwigType *SwigType_del_element(SwigType *t) {
* SwigType_pop()
*
* Pop one type element off the type.
* Example: t in: q(const).p.Integer
* t out: p.Integer
* result: q(const).
* For example:
* t in: q(const).p.Integer
* t out: p.Integer
* result: q(const).
* ----------------------------------------------------------------------------- */
SwigType *SwigType_pop(SwigType *t) {
@ -771,7 +772,6 @@ SwigType *SwigType_array_type(const SwigType *ty) {
* Functions
*
* SwigType_add_function()
* SwigType_del_function()
* SwigType_isfunction()
* SwigType_pop_function()
*
@ -795,14 +795,36 @@ SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
return t;
}
/* -----------------------------------------------------------------------------
* SwigType_pop_function()
*
* Pop and return the function from the input type leaving the function's return
* type, if any.
* For example:
* t in: q(const).f().p.
* t out: p.
* result: q(const).f().
* ----------------------------------------------------------------------------- */
SwigType *SwigType_pop_function(SwigType *t) {
SwigType *f = 0;
SwigType *g = 0;
char *c = Char(t);
if (strncmp(c, "q(", 2) == 0) {
if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
/* Remove ref-qualifier */
f = SwigType_pop(t);
c = Char(t);
}
if (strncmp(c, "q(", 2) == 0) {
/* Remove cv-qualifier */
String *qual = SwigType_pop(t);
if (f) {
SwigType_push(qual, f);
Delete(f);
}
f = qual;
c = Char(t);
}
if (strncmp(c, "f(", 2)) {
printf("Fatal error. SwigType_pop_function applied to non-function.\n");
abort();
@ -814,14 +836,54 @@ SwigType *SwigType_pop_function(SwigType *t) {
return g;
}
/* -----------------------------------------------------------------------------
* SwigType_pop_function_qualifiers()
*
* Pop and return the function qualifiers from the input type leaving the rest of
* function declaration. Returns NULL if no qualifiers.
* For example:
* t in: r.q(const).f().p.
* t out: f().p.
* result: r.q(const)
* ----------------------------------------------------------------------------- */
SwigType *SwigType_pop_function_qualifiers(SwigType *t) {
SwigType *qualifiers = 0;
char *c = Char(t);
if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
/* Remove ref-qualifier */
String *qual = SwigType_pop(t);
qualifiers = qual;
c = Char(t);
}
if (strncmp(c, "q(", 2) == 0) {
/* Remove cv-qualifier */
String *qual = SwigType_pop(t);
if (qualifiers) {
SwigType_push(qual, qualifiers);
Delete(qualifiers);
}
qualifiers = qual;
}
assert(Strncmp(t, "f(", 2) == 0);
return qualifiers;
}
int SwigType_isfunction(const SwigType *t) {
char *c;
if (!t) {
return 0;
}
c = Char(t);
if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
/* Might be a function with a ref-qualifier, skip over */
c += 2;
if (!*c)
return 0;
}
if (strncmp(c, "q(", 2) == 0) {
/* Might be a 'const' function. Try to skip over the 'const' */
/* Might be a function with a cv-qualifier, skip over */
c = strchr(c, '.');
if (c)
c++;

View file

@ -42,10 +42,15 @@
* "name" - Scope name
* "qname" - Fully qualified typename
* "typetab" - Type table containing typenames and typedef information
* For a given key in the typetab table, the value is a fully
* qualified name if not pointing to itself.
* "symtab" - Hash table of symbols defined in a scope
* "inherit" - List of inherited scopes
* "parent" - Parent scope
*
* The contents of these tables can be viewed for debugging using the -debug-typedef
* option which calls SwigType_print_scope().
*
* Typedef information is stored in the "typetab" hash table. For example,
* if you have these declarations:
*
@ -53,8 +58,7 @@
* typedef A B;
* typedef B *C;
*
* typetab is built as follows:
*
* typetab in scope '' contains:
* "A" : "int"
* "B" : "A"
* "C" : "p.B"
@ -67,31 +71,76 @@
* ---> a(40).p.p.A (B --> A)
* ---> a(40).p.p.int (A --> int)
*
*
* Using declarations are stored in the "typetab" hash table. For example,
*
* namespace NN {
* struct SS {};
* }
* namespace N {
* struct S {};
* using NN::SS;
* }
* using N::S;
*
* typetab in scope '' contains:
* "S" : "N::S"
*
* and typetab in scope 'N' contains:
* "SS" : "NN::SS"
* "S" : "S"
*
*
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if
* you have this:
*
* class Foo {
* public:
* typedef int Integer;
* };
* class Foo {
* public:
* typedef int Integer;
* };
* struct Bar : public Foo {
* void blah(Integer x);
* };
*
* class Bar : public Foo {
* void blah(Integer x);
* };
* In this case typetab in scope '' contains:
* "Foo" : "Foo"
* "Bar" : "Bar"
* and scope 'Foo' contains:
* "Integer" : "int"
* and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
*
* The argument type of Bar::blah will be set to Foo::Integer.
*
*
* The scope-inheritance mechanism is used to manage C++ using directives.
*
* namespace XX {
* class CC {};
* }
* namespace X {
* class C {};
* using namespace XX;
* }
* using namespace X;
*
* typetab in scope '' inherits from 'X'
* typetab in scope 'X' inherits from 'XX' and contains:
* "C" : "C"
* typetab in scope 'XX' contains:
* "CC" : "CC"
*
*
* The scope-inheritance mechanism is used to manage C++ namespace aliases.
* For example, if you have this:
*
* namespace Foo {
* typedef int Integer;
* }
* namespace Foo {
* typedef int Integer;
* }
*
* namespace F = Foo;
* namespace F = Foo;
*
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally,
* "F::" will merely be an empty scope that refers to Foo. SWIG will never
* In this case, F is defined as a scope that "inherits" from Foo. Internally,
* F will merely be an empty scope that points to Foo. SWIG will never
* place new type information into a namespace alias---attempts to do so
* will generate a warning message (in the parser) and will place information into
* Foo instead.
@ -166,6 +215,7 @@ void SwigType_typesystem_init() {
* ----------------------------------------------------------------------------- */
int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
/* Printf(stdout, "typedef %s %s\n", type, name); */
if (Getattr(current_typetab, name))
return -1; /* Already defined */
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
@ -248,10 +298,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) {
ttab = NewHash();
Setattr(s, "typetab", ttab);
/* Build fully qualified name and */
/* Build fully qualified name */
qname = SwigType_scope_name(s);
#if 1
{
/* TODO: only do with templates? What happens with non-templates with code below? */
String *stripped_qname;
stripped_qname = SwigType_remove_global_scope_prefix(qname);
/* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
Setattr(scopes, stripped_qname, s);
Setattr(s, "qname", qname);
/*
Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
*/
Delete(stripped_qname);
}
#else
Printf(stdout, "SwigType_new_scope %s\n", qname);
Setattr(scopes, qname, s);
Setattr(s, "qname", qname);
#endif
Delete(qname);
current_scope = s;
@ -418,12 +484,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
Typetab *s_orig = s;
String *nnameprefix = 0;
static int check_parent = 1;
int is_template = 0;
if (Getmark(s))
return 0;
Setmark(s, 1);
if (SwigType_istemplate(nameprefix)) {
is_template = SwigType_istemplate(nameprefix);
if (is_template) {
nnameprefix = SwigType_typedef_resolve_all(nameprefix);
nameprefix = nnameprefix;
}
@ -437,10 +505,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
} else {
full = NewString(nameprefix);
}
if (Getattr(scopes, full)) {
s = Getattr(scopes, full);
} else {
s = 0;
s = Getattr(scopes, full);
if (!s && is_template) {
/* try look up scope with all the unary scope operators within the template parameter list removed */
SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
s = Getattr(scopes, full_stripped);
Delete(full_stripped);
}
Delete(full);
if (s) {
@ -500,7 +570,7 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
List *inherit;
Typetab *parent;
/* if (!s) return 0; *//* now is checked bellow */
/* if (!s) return 0; *//* now is checked below */
/* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
if (!Getmark(s)) {
@ -541,8 +611,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
/* -----------------------------------------------------------------------------
* template_parameters_resolve()
*
* For use with templates only. The template parameters are resolved. If none
* of the parameters can be resolved, zero is returned.
* For use with templates only. Attempts to resolve one template parameter.
*
* If one of the template parameters can be resolved, the type is returned with
* just the one parameter resolved and the remaining parameters left as is.
* If none of the template parameters can be resolved, zero is returned.
* ----------------------------------------------------------------------------- */
static String *template_parameters_resolve(const String *base) {
@ -574,14 +647,15 @@ static String *template_parameters_resolve(const String *base) {
if ((i + 1) < sz)
Append(type, ",");
}
Append(type, ")>");
Append(type, suffix);
Delete(suffix);
Delete(tparms);
if (!rep) {
if (rep) {
Append(type, ")>");
Append(type, suffix);
} else {
Delete(type);
type = 0;
}
Delete(suffix);
Delete(tparms);
return type;
}
@ -592,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) {
/* -----------------------------------------------------------------------------
* SwigType_typedef_resolve()
*
* Given a type declaration, this function looks to reduce/resolve the type via a
* typedef (including via C++ using declarations).
*
* If it is able to find a typedef, the resolved type is returned. If no typedef
* is found NULL is returned. The type name is resolved in the current scope.
* The type returned is not always fully qualified for the global scope, it is
* valid for use in the current scope. If the current scope is global scope, a
* fully qualified type should be returned.
*
* Some additional notes are in Doc/Manual/Extending.html.
* ----------------------------------------------------------------------------- */
/* #define SWIG_DEBUG */
@ -718,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
}
}
if (!type && SwigType_istemplate(base)) {
String *tprefix = SwigType_templateprefix(base);
String *rtprefix = SwigType_typedef_resolve(tprefix);
/* We're looking for a using declaration on the template prefix to resolve the template prefix
* in another scope. Using declaration do not have template parameters. */
if (rtprefix && !SwigType_istemplate(rtprefix)) {
String *tsuffix = SwigType_templatesuffix(base);
String *targs = SwigType_templateargs(base);
type = NewString(rtprefix);
newtype = 1;
Append(type, targs);
Append(type, tsuffix);
Delete(targs);
Delete(tsuffix);
Delete(rtprefix);
}
Delete(tprefix);
}
if (type && (Equal(base, type))) {
if (newtype)
Delete(type);
@ -735,10 +839,8 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
newtype = 1;
type = template_parameters_resolve(base);
}
if (namebase)
Delete(namebase);
if (nameprefix)
Delete(nameprefix);
Delete(namebase);
Delete(nameprefix);
} else {
if (SwigType_isfunction(base)) {
List *parms;
@ -911,6 +1013,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
return Copy(r);
}
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
#endif
/* Recursively resolve the typedef */
r = NewString(t);
while ((n = SwigType_typedef_resolve(r))) {
@ -931,6 +1036,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
Delete(key);
Delete(rr);
}
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
#endif
return r;
}
@ -938,8 +1046,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
/* -----------------------------------------------------------------------------
* SwigType_typedef_qualified()
*
* Given a type declaration, this function tries to fully qualify it according to
* typedef scope rules.
* Given a type declaration, this function tries to fully qualify it so that the
* resulting type can be used in the global scope. The type name is resolved in
* the current scope.
*
* It provides a fully qualified name, not necessarily a fully expanded name.
* When a using declaration or using directive is found the type may not be fully
* expanded, but it will be resolved and fully qualified for use in the global scope.
*
* This function is for looking up scopes to qualify a type. It does not resolve
* C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
*
* If the unary scope operator (::) is used as a prefix to the type to denote global
* scope, it is left in place.
* ----------------------------------------------------------------------------- */
@ -1000,20 +1117,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
out of the current scope */
Typetab *cs = current_scope;
while (cs) {
String *qs = SwigType_scope_name(cs);
if (Len(qs)) {
Append(qs, "::");
}
Append(qs, e);
if (Getattr(scopes, qs)) {
if (cs) {
Typetab *found_scope = SwigType_find_scope(cs, e);
if (found_scope) {
String *qs = SwigType_scope_name(found_scope);
Clear(e);
Append(e, qs);
Delete(qs);
break;
}
Delete(qs);
cs = Getattr(cs, "parent");
}
}
}
@ -1029,10 +1140,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Parm *p;
List *parms;
ty = Swig_symbol_template_deftype(e, current_symtab);
/*
String *dt = Swig_symbol_template_deftype(e, current_symtab);
ty = Swig_symbol_type_qualify(dt, 0);
*/
e = ty;
parms = SwigType_parmlist(e);
tprefix = SwigType_templateprefix(e);
@ -1099,9 +1206,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Delete(tprefix);
Delete(qprefix);
Delete(parms);
/*
Delete(dt);
*/
}
Append(result, e);
Delete(ty);
@ -1181,7 +1285,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) {
String *defined_name = 0;
/* Printf(stdout,"using %s\n", name); */
/* Printf(stdout, "using %s\n", name); */
if (!Swig_scopename_check(name))
return -1; /* Not properly qualified */
@ -1436,7 +1540,7 @@ SwigType *SwigType_alttype(const SwigType *t, int local_tmap) {
}
} else {
if (SwigType_issimple(td) && SwigType_istemplate(td)) {
use_wrapper = !n || !GetFlag(n, "feature:novaluewrapper");
use_wrapper = 1;
}
}
}