summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2005-10-20 19:59:25 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2005-10-20 19:59:25 (GMT)
commit3e0055f8c65c407e74ce476b8e2b1fb889723514 (patch)
tree169cce8c87033e15364b57de947073e6e9c34d59 /Objects
parent2cb94aba122b86dcda87d437eb36a860d14393d5 (diff)
downloadcpython-3e0055f8c65c407e74ce476b8e2b1fb889723514.zip
cpython-3e0055f8c65c407e74ce476b8e2b1fb889723514.tar.gz
cpython-3e0055f8c65c407e74ce476b8e2b1fb889723514.tar.bz2
Merge ast-branch to head
This change implements a new bytecode compiler, based on a transformation of the parse tree to an abstract syntax defined in Parser/Python.asdl. The compiler implementation is not complete, but it is in stable enough shape to run the entire test suite excepting two disabled tests.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/codeobject.c453
-rw-r--r--Objects/frameobject.c1
-rw-r--r--Objects/funcobject.c6
-rw-r--r--Objects/typeobject.c12
4 files changed, 461 insertions, 11 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
new file mode 100644
index 0000000..c5ddfd5
--- /dev/null
+++ b/Objects/codeobject.c
@@ -0,0 +1,453 @@
+#include "Python.h"
+#include "code.h"
+#include "structmember.h"
+
+#define NAME_CHARS \
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+
+/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
+
+static int
+all_name_chars(unsigned char *s)
+{
+ static char ok_name_char[256];
+ static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
+
+ if (ok_name_char[*name_chars] == 0) {
+ unsigned char *p;
+ for (p = name_chars; *p; p++)
+ ok_name_char[*p] = 1;
+ }
+ while (*s) {
+ if (ok_name_char[*s++] == 0)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+intern_strings(PyObject *tuple)
+{
+ int i;
+
+ for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
+ PyObject *v = PyTuple_GET_ITEM(tuple, i);
+ if (v == NULL || !PyString_CheckExact(v)) {
+ Py_FatalError("non-string found in code slot");
+ }
+ PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
+ }
+}
+
+
+PyCodeObject *
+PyCode_New(int argcount, int nlocals, int stacksize, int flags,
+ PyObject *code, PyObject *consts, PyObject *names,
+ PyObject *varnames, PyObject *freevars, PyObject *cellvars,
+ PyObject *filename, PyObject *name, int firstlineno,
+ PyObject *lnotab)
+{
+ PyCodeObject *co;
+ int i;
+ /* Check argument types */
+ if (argcount < 0 || nlocals < 0 ||
+ code == NULL ||
+ consts == NULL || !PyTuple_Check(consts) ||
+ names == NULL || !PyTuple_Check(names) ||
+ varnames == NULL || !PyTuple_Check(varnames) ||
+ freevars == NULL || !PyTuple_Check(freevars) ||
+ cellvars == NULL || !PyTuple_Check(cellvars) ||
+ name == NULL || !PyString_Check(name) ||
+ filename == NULL || !PyString_Check(filename) ||
+ lnotab == NULL || !PyString_Check(lnotab) ||
+ !PyObject_CheckReadBuffer(code)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ intern_strings(names);
+ intern_strings(varnames);
+ intern_strings(freevars);
+ intern_strings(cellvars);
+ /* Intern selected string constants */
+ for (i = PyTuple_Size(consts); --i >= 0; ) {
+ PyObject *v = PyTuple_GetItem(consts, i);
+ if (!PyString_Check(v))
+ continue;
+ if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
+ continue;
+ PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
+ }
+ co = PyObject_NEW(PyCodeObject, &PyCode_Type);
+ if (co != NULL) {
+ co->co_argcount = argcount;
+ co->co_nlocals = nlocals;
+ co->co_stacksize = stacksize;
+ co->co_flags = flags;
+ Py_INCREF(code);
+ co->co_code = code;
+ Py_INCREF(consts);
+ co->co_consts = consts;
+ Py_INCREF(names);
+ co->co_names = names;
+ Py_INCREF(varnames);
+ co->co_varnames = varnames;
+ Py_INCREF(freevars);
+ co->co_freevars = freevars;
+ Py_INCREF(cellvars);
+ co->co_cellvars = cellvars;
+ Py_INCREF(filename);
+ co->co_filename = filename;
+ Py_INCREF(name);
+ co->co_name = name;
+ co->co_firstlineno = firstlineno;
+ Py_INCREF(lnotab);
+ co->co_lnotab = lnotab;
+ }
+ return co;
+}
+
+
+#define OFF(x) offsetof(PyCodeObject, x)
+
+static PyMemberDef code_memberlist[] = {
+ {"co_argcount", T_INT, OFF(co_argcount), READONLY},
+ {"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
+ {"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
+ {"co_flags", T_INT, OFF(co_flags), READONLY},
+ {"co_code", T_OBJECT, OFF(co_code), READONLY},
+ {"co_consts", T_OBJECT, OFF(co_consts), READONLY},
+ {"co_names", T_OBJECT, OFF(co_names), READONLY},
+ {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY},
+ {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY},
+ {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY},
+ {"co_filename", T_OBJECT, OFF(co_filename), READONLY},
+ {"co_name", T_OBJECT, OFF(co_name), READONLY},
+ {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY},
+ {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY},
+ {NULL} /* Sentinel */
+};
+
+/* Helper for code_new: return a shallow copy of a tuple that is
+ guaranteed to contain exact strings, by converting string subclasses
+ to exact strings and complaining if a non-string is found. */
+static PyObject*
+validate_and_copy_tuple(PyObject *tup)
+{
+ PyObject *newtuple;
+ PyObject *item;
+ int i, len;
+
+ len = PyTuple_GET_SIZE(tup);
+ newtuple = PyTuple_New(len);
+ if (newtuple == NULL)
+ return NULL;
+
+ for (i = 0; i < len; i++) {
+ item = PyTuple_GET_ITEM(tup, i);
+ if (PyString_CheckExact(item)) {
+ Py_INCREF(item);
+ }
+ else if (!PyString_Check(item)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "name tuples must contain only "
+ "strings, not '%.500s'",
+ item->ob_type->tp_name);
+ Py_DECREF(newtuple);
+ return NULL;
+ }
+ else {
+ item = PyString_FromStringAndSize(
+ PyString_AS_STRING(item),
+ PyString_GET_SIZE(item));
+ if (item == NULL) {
+ Py_DECREF(newtuple);
+ return NULL;
+ }
+ }
+ PyTuple_SET_ITEM(newtuple, i, item);
+ }
+
+ return newtuple;
+}
+
+PyDoc_STRVAR(code_doc,
+"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\
+ varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\
+\n\
+Create a code object. Not for the faint of heart.");
+
+static PyObject *
+code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+ int argcount;
+ int nlocals;
+ int stacksize;
+ int flags;
+ PyObject *co = NULL;
+ PyObject *code;
+ PyObject *consts;
+ PyObject *names, *ournames = NULL;
+ PyObject *varnames, *ourvarnames = NULL;
+ PyObject *freevars = NULL, *ourfreevars = NULL;
+ PyObject *cellvars = NULL, *ourcellvars = NULL;
+ PyObject *filename;
+ PyObject *name;
+ int firstlineno;
+ PyObject *lnotab;
+
+ if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
+ &argcount, &nlocals, &stacksize, &flags,
+ &code,
+ &PyTuple_Type, &consts,
+ &PyTuple_Type, &names,
+ &PyTuple_Type, &varnames,
+ &filename, &name,
+ &firstlineno, &lnotab,
+ &PyTuple_Type, &freevars,
+ &PyTuple_Type, &cellvars))
+ return NULL;
+
+ if (argcount < 0) {
+ PyErr_SetString(
+ PyExc_ValueError,
+ "code: argcount must not be negative");
+ goto cleanup;
+ }
+
+ if (nlocals < 0) {
+ PyErr_SetString(
+ PyExc_ValueError,
+ "code: nlocals must not be negative");
+ goto cleanup;
+ }
+
+ ournames = validate_and_copy_tuple(names);
+ if (ournames == NULL)
+ goto cleanup;
+ ourvarnames = validate_and_copy_tuple(varnames);
+ if (ourvarnames == NULL)
+ goto cleanup;
+ if (freevars)
+ ourfreevars = validate_and_copy_tuple(freevars);
+ else
+ ourfreevars = PyTuple_New(0);
+ if (ourfreevars == NULL)
+ goto cleanup;
+ if (cellvars)
+ ourcellvars = validate_and_copy_tuple(cellvars);
+ else
+ ourcellvars = PyTuple_New(0);
+ if (ourcellvars == NULL)
+ goto cleanup;
+
+ co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
+ code, consts, ournames, ourvarnames,
+ ourfreevars, ourcellvars, filename,
+ name, firstlineno, lnotab);
+ cleanup:
+ Py_XDECREF(ournames);
+ Py_XDECREF(ourvarnames);
+ Py_XDECREF(ourfreevars);
+ Py_XDECREF(ourcellvars);
+ return co;
+}
+
+static void
+code_dealloc(PyCodeObject *co)
+{
+ Py_XDECREF(co->co_code);
+ Py_XDECREF(co->co_consts);
+ Py_XDECREF(co->co_names);
+ Py_XDECREF(co->co_varnames);
+ Py_XDECREF(co->co_freevars);
+ Py_XDECREF(co->co_cellvars);
+ Py_XDECREF(co->co_filename);
+ Py_XDECREF(co->co_name);
+ Py_XDECREF(co->co_lnotab);
+ PyObject_DEL(co);
+}
+
+static PyObject *
+code_repr(PyCodeObject *co)
+{
+ char buf[500];
+ int lineno = -1;
+ char *filename = "???";
+ char *name = "???";
+
+ if (co->co_firstlineno != 0)
+ lineno = co->co_firstlineno;
+ if (co->co_filename && PyString_Check(co->co_filename))
+ filename = PyString_AS_STRING(co->co_filename);
+ if (co->co_name && PyString_Check(co->co_name))
+ name = PyString_AS_STRING(co->co_name);
+ PyOS_snprintf(buf, sizeof(buf),
+ "<code object %.100s at %p, file \"%.300s\", line %d>",
+ name, co, filename, lineno);
+ return PyString_FromString(buf);
+}
+
+static int
+code_compare(PyCodeObject *co, PyCodeObject *cp)
+{
+ int cmp;
+ cmp = PyObject_Compare(co->co_name, cp->co_name);
+ if (cmp) return cmp;
+ cmp = co->co_argcount - cp->co_argcount;
+ if (cmp) goto normalize;
+ cmp = co->co_nlocals - cp->co_nlocals;
+ if (cmp) goto normalize;
+ cmp = co->co_flags - cp->co_flags;
+ if (cmp) goto normalize;
+ cmp = co->co_firstlineno - cp->co_firstlineno;
+ if (cmp) goto normalize;
+ cmp = PyObject_Compare(co->co_code, cp->co_code);
+ if (cmp) return cmp;
+ cmp = PyObject_Compare(co->co_consts, cp->co_consts);
+ if (cmp) return cmp;
+ cmp = PyObject_Compare(co->co_names, cp->co_names);
+ if (cmp) return cmp;
+ cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);
+ if (cmp) return cmp;
+ cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);
+ if (cmp) return cmp;
+ cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);
+ return cmp;
+
+ normalize:
+ if (cmp > 0)
+ return 1;
+ else if (cmp < 0)
+ return -1;
+ else
+ return 0;
+}
+
+static long
+code_hash(PyCodeObject *co)
+{
+ long h, h0, h1, h2, h3, h4, h5, h6;
+ h0 = PyObject_Hash(co->co_name);
+ if (h0 == -1) return -1;
+ h1 = PyObject_Hash(co->co_code);
+ if (h1 == -1) return -1;
+ h2 = PyObject_Hash(co->co_consts);
+ if (h2 == -1) return -1;
+ h3 = PyObject_Hash(co->co_names);
+ if (h3 == -1) return -1;
+ h4 = PyObject_Hash(co->co_varnames);
+ if (h4 == -1) return -1;
+ h5 = PyObject_Hash(co->co_freevars);
+ if (h5 == -1) return -1;
+ h6 = PyObject_Hash(co->co_cellvars);
+ if (h6 == -1) return -1;
+ h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
+ co->co_argcount ^ co->co_nlocals ^ co->co_flags;
+ if (h == -1) h = -2;
+ return h;
+}
+
+/* XXX code objects need to participate in GC? */
+
+PyTypeObject PyCode_Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "code",
+ sizeof(PyCodeObject),
+ 0,
+ (destructor)code_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)code_compare, /* tp_compare */
+ (reprfunc)code_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)code_hash, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ code_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ code_memberlist, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ code_new, /* tp_new */
+};
+
+/* All about c_lnotab.
+
+c_lnotab is an array of unsigned bytes disguised as a Python string. In -O
+mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped
+to source code line #s (when needed for tracebacks) via c_lnotab instead.
+The array is conceptually a list of
+ (bytecode offset increment, line number increment)
+pairs. The details are important and delicate, best illustrated by example:
+
+ byte code offset source code line number
+ 0 1
+ 6 2
+ 50 7
+ 350 307
+ 361 308
+
+The first trick is that these numbers aren't stored, only the increments
+from one row to the next (this doesn't really work, but it's a start):
+
+ 0, 1, 6, 1, 44, 5, 300, 300, 11, 1
+
+The second trick is that an unsigned byte can't hold negative values, or
+values larger than 255, so (a) there's a deep assumption that byte code
+offsets and their corresponding line #s both increase monotonically, and (b)
+if at least one column jumps by more than 255 from one row to the next, more
+than one pair is written to the table. In case #b, there's no way to know
+from looking at the table later how many were written. That's the delicate
+part. A user of c_lnotab desiring to find the source line number
+corresponding to a bytecode address A should do something like this
+
+ lineno = addr = 0
+ for addr_incr, line_incr in c_lnotab:
+ addr += addr_incr
+ if addr > A:
+ return lineno
+ lineno += line_incr
+
+In order for this to work, when the addr field increments by more than 255,
+the line # increment in each pair generated must be 0 until the remaining addr
+increment is < 256. So, in the example above, com_set_lineno should not (as
+was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to
+255, 0, 45, 255, 0, 45.
+*/
+
+int
+PyCode_Addr2Line(PyCodeObject *co, int addrq)
+{
+ int size = PyString_Size(co->co_lnotab) / 2;
+ unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);
+ int line = co->co_firstlineno;
+ int addr = 0;
+ while (--size >= 0) {
+ addr += *p++;
+ if (addr > addrq)
+ break;
+ line += *p++;
+ }
+ return line;
+}
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index bc8cae9..8ebf500 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -3,6 +3,7 @@
#include "Python.h"
+#include "code.h"
#include "compile.h"
#include "frameobject.h"
#include "opcode.h"
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index c0c91c9..85cef6f 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -2,7 +2,7 @@
/* Function object implementation */
#include "Python.h"
-#include "compile.h"
+#include "code.h"
#include "eval.h"
#include "structmember.h"
@@ -144,7 +144,9 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
Py_XINCREF(closure);
}
else {
- PyErr_SetString(PyExc_SystemError, "non-tuple closure");
+ PyErr_Format(PyExc_SystemError,
+ "expected tuple for closure, got '%.100s'",
+ closure->ob_type->tp_name);
return -1;
}
Py_XDECREF(((PyFunctionObject *) op) -> func_closure);
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 88c4a15..591c62b 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1737,20 +1737,14 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
goto bad_slots;
for (i = j = 0; i < nslots; i++) {
char *s;
- char buffer[256];
tmp = PyTuple_GET_ITEM(slots, i);
s = PyString_AS_STRING(tmp);
if ((add_dict && strcmp(s, "__dict__") == 0) ||
(add_weak && strcmp(s, "__weakref__") == 0))
continue;
- if (_Py_Mangle(PyString_AS_STRING(name),
- PyString_AS_STRING(tmp),
- buffer, sizeof(buffer)))
- {
- tmp = PyString_FromString(buffer);
- } else {
- Py_INCREF(tmp);
- }
+ tmp =_Py_Mangle(name, tmp);
+ if (!tmp)
+ goto bad_slots;
PyTuple_SET_ITEM(newslots, j, tmp);
j++;
}
&& md->getStartBodyLine()!=-1 && md->isLinkableInProject() &&
((nd && nd->isLinkableInProject()) ||
(fd->isLinkableInProject()) ||
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
index b508c1c..fdb12b0 100644
--- a/src/groupdef.cpp
+++ b/src/groupdef.cpp
@@ -163,7 +163,7 @@ void GroupDef::addMembersToMemberGroup()
void GroupDef::insertMember(MemberDef *md,bool docOnly)
{
- //fprintf(stderr, "GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
+ //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
MemberNameInfo *mni=0;
if ((mni=(*allMemberNameInfoSDict)[md->name()]))
{ // member with this name already found
@@ -630,7 +630,7 @@ void addGroupToGroups(Entry *root,GroupDef *subGroup)
/*! Add a member to the group with the highest priority */
void addMemberToGroups(Entry *root,MemberDef *md)
{
- //printf(" Root 0x%p = %s, md 0x%p %s\n", root, root->name.data(), md, md->name().data() );
+ //printf(" Root %p = %s, md %p=%s groups=%d\n", root, root->name.data(), md, md->name().data(), root->groups->count() );
QListIterator<Grouping> gli(*root->groups);
Grouping *g;
@@ -644,7 +644,8 @@ void addMemberToGroups(Entry *root,MemberDef *md)
(gd=Doxygen::groupSDict[g->groupname]) &&
g->pri >= pri)
{
- if( fgd && g->pri == pri ) {
+ if (fgd && g->pri==pri)
+ {
warn(root->fileName.data(), root->startLine,
"Warning: Member %s found in multiple %s groups! "
"The member will be put in group %s, and not in group %s",
@@ -657,14 +658,18 @@ void addMemberToGroups(Entry *root,MemberDef *md)
pri = g->pri;
}
}
+ //printf("fgd=%p\n",fgd);
// put member into group defined by this entry?
- if( fgd )
+ if (fgd)
{
GroupDef *mgd = md->getGroupDef();
+ //printf("mgd=%p\n",mgd);
bool insertit = FALSE;
if (mgd==0)
+ {
insertit = TRUE;
+ }
else if (mgd!=fgd)
{
bool moveit = FALSE;
@@ -672,40 +677,42 @@ void addMemberToGroups(Entry *root,MemberDef *md)
// move member from one group to another if
// - the new one has a higher priority
// - the new entry has the same priority, but with docs where the old one had no docs
- if( md->getGroupPri() < pri )
+ if (md->getGroupPri()<pri)
{
- moveit = TRUE;
+ moveit = TRUE;
}
else
{
- if( md->getGroupPri() == pri )
- {
-
- if( root->doc.length() != 0 && !md->getGroupHasDocs() )
- moveit = TRUE;
- else if( root->doc.length() != 0 && md->getGroupHasDocs() )
- {
- warn(md->getGroupFileName(),md->getGroupStartLine(),
- "Warning: Member documentation for %s found several times in %s groups!\n"
- "%s:%d: The member will remain in group %s, and won't be put into group %s",
- md->name().data(), Grouping::getGroupPriName( pri ),
- root->fileName.data(), root->startLine,
- mgd->name().data(),
- fgd->name().data()
- );
- }
- }
+ if (md->getGroupPri()==pri)
+ {
+ if (!root->doc.isEmpty() && !md->getGroupHasDocs())
+ {
+ moveit = TRUE;
+ }
+ else if (!root->doc.isEmpty() && md->getGroupHasDocs())
+ {
+ warn(md->getGroupFileName(),md->getGroupStartLine(),
+ "Warning: Member documentation for %s found several times in %s groups!\n"
+ "%s:%d: The member will remain in group %s, and won't be put into group %s",
+ md->name().data(), Grouping::getGroupPriName( pri ),
+ root->fileName.data(), root->startLine,
+ mgd->name().data(),
+ fgd->name().data()
+ );
+ }
+ }
}
- if( moveit )
+ if (moveit)
{
mgd->removeMember(md);
insertit = TRUE;
}
}
- if( insertit )
+ if (insertit)
{
+ //printf("insertMember\n");
fgd->insertMember(md);
md->setGroupDef(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
ClassDef *cd = md->getClassDefOfAnonymousType();
diff --git a/src/index.cpp b/src/index.cpp
index 47bdaab..b07200d 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -351,6 +351,21 @@ void endFile(OutputList &ol,bool external)
//----------------------------------------------------------------------------
+static bool classHasVisibleChildren(ClassDef *cd)
+{
+ if (cd->subClasses()->count()==0) return FALSE;
+ BaseClassList *bcl=cd->subClasses();
+ BaseClassListIterator bcli(*bcl);
+ for ( ; bcli.current() ; ++bcli)
+ {
+ if (bcli.current()->classDef->isVisibleInHierarchy())
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper,int level)
{
HtmlHelp *htmlHelp=0;
@@ -381,7 +396,8 @@ void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper,int level)
started=TRUE;
}
//printf("Passed...\n");
- bool hasChildren = !cd->visited && !hideSuper && cd->subClasses()->count()>0;
+ bool hasChildren = !cd->visited && !hideSuper && classHasVisibleChildren(cd);
+ //printf("tree4: Has children %s: %d\n",cd->name().data(),hasChildren);
if (cd->isLinkable())
{
//printf("Writing class %s\n",cd->displayName().data());
@@ -454,7 +470,8 @@ void writeClassTree(BaseClassList *cl,int level)
for ( ; cli.current() ; ++cli)
{
ClassDef *cd=cli.current()->classDef;
- if (cd->isVisibleInHierarchy() && !cd->visited)
+ if (cd->isVisibleInHierarchy() && hasVisibleRoot(cd->baseClasses()))
+ //if (cd->isVisibleInHierarchy() && !cd->visited)
{
if (!started)
{
@@ -462,7 +479,8 @@ void writeClassTree(BaseClassList *cl,int level)
if (hasFtvHelp) ftvHelp->incContentsDepth();
started=TRUE;
}
- bool hasChildren = cd->subClasses()->count()>0;
+ bool hasChildren = !cd->visited && classHasVisibleChildren(cd);
+ //printf("tree2: Has children %s: %d\n",cd->name().data(),hasChildren);
if (cd->isLinkable())
{
if (hasHtmlHelp)
@@ -499,7 +517,8 @@ void writeClassTreeNode(ClassDef *cd,bool hasHtmlHelp,bool hasFtvHelp,bool &star
{
started=TRUE;
}
- bool hasChildren = cd->subClasses()->count()>0;
+ bool hasChildren = classHasVisibleChildren(cd);
+ //printf("node: Has children %s: %d\n",cd->name().data(),hasChildren);
if (cd->isLinkable())
{
if (hasHtmlHelp)
@@ -583,7 +602,8 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started)
if (hasFtvHelp) ftvHelp->incContentsDepth();
started=TRUE;
}
- bool hasChildren = !cd->visited && cd->subClasses()->count()>0;
+ bool hasChildren = !cd->visited && classHasVisibleChildren(cd);
+ //printf("list: Has children %s: %d\n",cd->name().data(),hasChildren);
if (cd->isLinkable())
{
//printf("Writing class %s isLinkable()=%d isLinkableInProject()=%d cd->templateMaster()=%p\n",
@@ -2412,7 +2432,7 @@ void writeGroupTreeNode(OutputList &ol, GroupDef *gd,int level)
}
// write classes
- if(gd->classSDict->count()>0)
+ if (gd->classSDict->count()>0)
{
if(htmlHelp)
{
@@ -2616,19 +2636,11 @@ void writeGroupIndex(OutputList &ol)
writeGroupHierarchy(ol);
if (hasHtmlHelp)
{
- //writeGroupTree(ol); // KPW - modified to write hierarchial HMTL Help
- //if(!Config::instance()->get(""))
- //{
- htmlHelp->decContentsDepth();
- //}
+ htmlHelp->decContentsDepth();
}
if (hasFtvHelp)
{
- //writeGroupTree(ol); // KPW - modified to write hierarchial FTV Help
- //if(!Config::instance()->get(""))
- //{
- ftvHelp->decContentsDepth();
- //}
+ ftvHelp->decContentsDepth();
}
endFile(ol);
ol.popGeneratorState();
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index c02428c..f851e19 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -147,6 +147,10 @@ void LatexGenerator::init()
err("Could not open file %s for writing\n",fileName.data());
exit(1);
}
+ // inserted by KONNO Akihisa <konno@researchers.jp> 2002-03-05
+ QCString latex_command = Config_getString("LATEX_CMD_NAME");
+ QCString mkidx_command = Config_getString("MAKEINDEX_CMD_NAME");
+ // end insertion by KONNO Akihisa <konno@researchers.jp> 2002-03-05
QTextStream t(&file);
t << "all: refman.dvi" << endl
<< endl
@@ -194,16 +198,16 @@ void LatexGenerator::init()
<< endl
<< "refman.dvi: refman.tex doxygen.sty" << endl
<< "\techo \"Running latex...\"" << endl
- << "\tlatex refman.tex" << endl
+ << "\t" << latex_command << " refman.tex" << endl
<< "\techo \"Running makeindex...\"" << endl
- << "\tmakeindex refman.idx" << endl
+ << "\t" << mkidx_command << " refman.idx" << endl
<< "\techo \"Rerunning latex....\"" << endl
- << "\tlatex refman.tex" << endl
+ << "\t" << latex_command << " refman.tex" << endl
<< "\tlatex_count=5 ; \\" << endl
<< "\twhile egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\\" << endl
<< "\t do \\" << endl
<< "\t echo \"Rerunning latex....\" ;\\" << endl
- << "\t latex refman.tex ;\\" << endl
+ << "\t " << latex_command << " refman.tex ;\\" << endl
<< "\t latex_count=`expr $$latex_count - 1` ;\\" << endl
<< "\t done" << endl << endl
<< "clean:" << endl
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 69bcf9f..dfcea4a 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -380,11 +380,10 @@ MemberDef::~MemberDef()
void MemberDef::setReimplements(MemberDef *md)
{
- //if (m_templateMaster)
- //{
- // m_templateMaster->setReimplements(md);
- //}
- redefines=md;
+ //if (redefines==0) redefines = new MemberList;
+ //if (redefines->find(md)==-1) redefines->inSort(md);
+
+ redefines = md;
}
void MemberDef::insertReimplementedBy(MemberDef *md)
@@ -394,10 +393,13 @@ void MemberDef::insertReimplementedBy(MemberDef *md)
m_templateMaster->insertReimplementedBy(md);
}
if (redefinedBy==0) redefinedBy = new MemberList;
- if (redefinedBy->find(md)==-1) redefinedBy->inSort(md);
+ if (redefinedBy->findRef(md)==-1)
+ {
+ redefinedBy->inSort(md);
+ }
}
-MemberDef *MemberDef::reimplements() const
+MemberDef *MemberDef::reimplements() const
{
return redefines;
}
@@ -1315,7 +1317,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
}
MemberDef *bmd=reimplements();
- ClassDef *bcd=0;
+ ClassDef *bcd=0;
if (bmd && (bcd=bmd->getClassDef()))
{
// write class that contains a member that is reimplemented by this one
@@ -1342,7 +1344,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
if (bd==0) bd=bcd;
ol.writeObjectLink(bd->getReference(),bd->getOutputFileBase(),
bmd->anchor(),bcd->name());
-
+
//ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
// bmd->anchor(),bcd->name());
if ( bd->isLinkableInProject() )
@@ -1374,6 +1376,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
//ol.writeString(".");
}
+
MemberList *bml=reimplementedBy();
if (bml)
{
diff --git a/src/memberdef.h b/src/memberdef.h
index 78818b9..51c0f7c 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -164,7 +164,7 @@ class MemberDef : public Definition
// relation to other members
void setReimplements(MemberDef *md);
void insertReimplementedBy(MemberDef *md);
- MemberDef *reimplements() const;
+ MemberDef *reimplements() const;
MemberList *reimplementedBy() const;
// enumeration specific members
@@ -249,9 +249,9 @@ class MemberDef : public Definition
private:
ClassDef *classDef; // member of or related to
FileDef *fileDef; // member of file definition
- MemberDef *redefines; // the member that is redefined by this one
MemberDef *enumScope; // the enclosing scope, if this is an enum field
MemberDef *annEnumType; // the annonymous enum that is the type of this member
+ MemberDef *redefines; // the members that this member redefines
MemberList *redefinedBy; // the list of members that redefine this one
MemberDef *memDef; // member definition for this declaration
MemberDef *memDec; // member declaration for this definition
diff --git a/src/pre.l b/src/pre.l
index 6b8b20d..1878f14 100644
--- a/src/pre.l
+++ b/src/pre.l
@@ -1001,6 +1001,7 @@ static int yyread(char *buf,int max_size)
ID [a-z_A-Z][a-z_A-Z0-9]*
B [ \t]
BN [ \t\r\n]
+CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
%option noyywrap
@@ -1213,6 +1214,9 @@ BN [ \t\r\n]
g_defArgsStr+=yytext;
}
*/
+<FindDefineArgs>{CHARLIT} {
+ g_defArgsStr+=yytext;
+ }
<FindDefineArgs>\" {
g_defArgsStr+=*yytext;
BEGIN(ReadString);
diff --git a/src/translator_br.h b/src/translator_br.h
index 4959f89..e81ef2b 100644
--- a/src/translator_br.h
+++ b/src/translator_br.h
@@ -1009,7 +1009,7 @@ class TranslatorBrazilian: public Translator
"Se a tag \\c MAX_DOT_GRAPH_HEIGHT no arquivo de configuração tem o valor"
"200, o seguinte gráfo será gerado:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"As caixas no grafo acima tem as seguintes interpretações:\n"
"<ul>\n"
diff --git a/src/translator_cn.h b/src/translator_cn.h
index e0131d8..2e5d54f 100644
--- a/src/translator_cn.h
+++ b/src/translator_cn.h
@@ -951,7 +951,7 @@ class TranslatorChinese : public TranslatorAdapter_1_2_13
"\\endcode\n"
"Èç¹ûÔÚÅäÖÃÎļþÖÐÖ¸¶¨ÁË"CN_SPC"MAX_DOT_GRAPH_HEIGHT"CN_SPC"µÄֵΪ200£¬"
"ÔòDoxygen½«Éú³ÉÈçϵÄͼÐΣº"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"ÒÔÉÏͼÐÎÖеľØÐÎÓÐÈçϵĺ¬Ò壺\n"
"<ul>\n"
diff --git a/src/translator_cz.h b/src/translator_cz.h
index 07941bb..a0001ca 100644
--- a/src/translator_cz.h
+++ b/src/translator_cz.h
@@ -1211,7 +1211,7 @@ class TranslatorCzech : public Translator
"\\endcode\n"
"Pokud je položka \\c MAX_DOT_GRAPH_HEIGHT konfiguraèního souboru "
"nastavena na hodnotu 200, bude vygenerován následující graf:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Bloky (tj. uzly) v uvedeném grafu mají následující význam:\n"
"<ul>\n"
diff --git a/src/translator_de.h b/src/translator_de.h
index 3426f46..db3427e 100644
--- a/src/translator_de.h
+++ b/src/translator_de.h
@@ -1082,7 +1082,7 @@ class TranslatorGerman : public Translator
"\\endcode\n\n"
"Setzen des Tags \\c MAX_DOT_GRAPH_HEIGHT in der Konfigurationsdatei "
"auf 240 liefert den folgenden Graphen:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Die Rechtecke in obigem Graphen bedeuten:\n"
"<ul>\n"
diff --git a/src/translator_dk.h b/src/translator_dk.h
index 9e72516..55ee6bd 100644
--- a/src/translator_dk.h
+++ b/src/translator_dk.h
@@ -1055,7 +1055,7 @@ class TranslatorDanish : public TranslatorAdapter_1_2_7
"\\endcode\n"
"If the \\c MAX_DOT_GRAPH_HEIGHT tag in the configuration file "
"is set to 200 this will result in the following graph:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"The boxes in the above graph have the following meaning:\n"
"<ul>\n"
diff --git a/src/translator_en.h b/src/translator_en.h
index 35ee638..258f6a1 100644
--- a/src/translator_en.h
+++ b/src/translator_en.h
@@ -1072,7 +1072,7 @@ class TranslatorEnglish : public Translator
"\\endcode\n"
"If the \\c MAX_DOT_GRAPH_HEIGHT tag in the configuration file "
"is set to 240 this will result in the following graph:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"The boxes in the above graph have the following meaning:\n"
"<ul>\n"
diff --git a/src/translator_es.h b/src/translator_es.h
index fa35a76..49e47e7 100644
--- a/src/translator_es.h
+++ b/src/translator_es.h
@@ -947,7 +947,7 @@ class TranslatorSpanish : public TranslatorAdapter_1_2_7
"\\endcode\n"
"Si la etiqueta \\c MAX_DOT_GRAPH_HEIGHT en el archivo de configuración "
"tiene valor 200 resultará en el siguiente gráfico:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Las cajas en el gráfico arriba tienen el significado que sigue:\n"
"<ul>\n"
diff --git a/src/translator_fr.h b/src/translator_fr.h
index 3c6f5a3..4611501 100644
--- a/src/translator_fr.h
+++ b/src/translator_fr.h
@@ -939,7 +939,7 @@ class TranslatorFrench : public Translator
"\\endcode\n"
"Si la valeur 200 est attribuée au tag \\c MAX_DOT_GRAPH_HEIGHT "
"du fichier de configuration, cela génèrera le graphe suivant:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Les rectangles du graphe ci-dessus ont la signification suivante:\n"
"<ul>\n"
diff --git a/src/translator_gr.h b/src/translator_gr.h
index ce71bfd..35988b3 100644
--- a/src/translator_gr.h
+++ b/src/translator_gr.h
@@ -1043,7 +1043,7 @@ class TranslatorGreek : public TranslatorAdapter_1_2_11
"\\endcode\n"
"Áí ç åôéêÝôá \\c MAX_DOT_GRAPH_HEIGHT óôï áñ÷åßï ñõèìßóåùí "
"ôåèåß óôï 200 èá Ý÷ïõìå óáí áðïôÝëåóìá ôï áêüëïõèï äéÜãñáììá:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Ôá êïõôéÜ óôï ðáñáðÜíù äéÜãñáììá Ý÷ïõí ôçí áêüëïõèç óçìáóßá:\n"
"<ul>\n"
diff --git a/src/translator_hr.h b/src/translator_hr.h
index dbf26a7..100d53c 100644
--- a/src/translator_hr.h
+++ b/src/translator_hr.h
@@ -760,7 +760,7 @@ class TranslatorCroatian : public Translator
"\\endcode\n"
"Ako je \\c MAX_DOT_GRAPH_HEIGHT tag u konfiguracijskoj datoteci "
"postavljen na 200 gornje veze æe rezultirati grafikonom:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Pravokutnici imaju slijedeæe znaèenje:\n"
"<ul>\n"
diff --git a/src/translator_hu.h b/src/translator_hu.h
index d477b1e..7f1ea5c 100644
--- a/src/translator_hu.h
+++ b/src/translator_hu.h
@@ -936,7 +936,7 @@ class TranslatorHungarian : public TranslatorAdapter_1_2_1
"\\endcode\n"
"Ha a konfigurációs fájl \\c MAX_DOT_GRAPH_HEIGHT elemének értékét "
"200-ra állítjuk, az eredmény a következõ ábra lesz:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Az ábrán levõ dobozok jelentése:\n"
"<ul>\n"
diff --git a/src/translator_it.h b/src/translator_it.h
index f3ed770..3d49e6a 100644
--- a/src/translator_it.h
+++ b/src/translator_it.h
@@ -1060,7 +1060,7 @@ class TranslatorItalian : public Translator
"\\endcode\n"
"Se il tag \\c MAX_DOT_GRAPH_HEIGHT nel file di configurazione "
"è impostato a 200 verrà prodotto il grafo seguente:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"I riquadri nel grafo qui sopra hanno il seguente significato:\n"
"<ul>\n"
diff --git a/src/translator_jp.h b/src/translator_jp.h
index f3f028b..8f8df91 100644
--- a/src/translator_jp.h
+++ b/src/translator_jp.h
@@ -1010,7 +1010,7 @@ class TranslatorJapanese : public Translator
"\\endcode\n"
"ÀßÄê¥Õ¥¡¥¤¥ëÃæ¤Ç¡¢¥¿¥° \\c MAX_DOT_GRAPH_HEIGHT ¤¬ 200 ¤Ë¥»¥Ã¥È¤µ¤ì¤¿"
"¾ì¹ç¡¢¼¡¤Î¤è¤¦¤Ê¥°¥é¥Õ¤È¤Ê¤ê¤Þ¤¹¡£"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"¾å¤Î¥°¥é¥ÕÆâ¤Î¥Ü¥Ã¥¯¥¹¤Ë¤Ï¼¡¤Î¤è¤¦¤Ê°ÕÌ£¤¬¤¢¤ê¤Þ¤¹¡£\n"
"<ul>\n"
diff --git a/src/translator_kr.h b/src/translator_kr.h
index 98317d7..5d6d9eb 100644
--- a/src/translator_kr.h
+++ b/src/translator_kr.h
@@ -1010,7 +1010,7 @@ class TranslatorKorean : public TranslatorAdapter_1_2_13
"\\endcode\n"
"If the \\c MAX_DOT_GRAPH_HEIGHT tag in the configuration file "
"is set to 240 this will result in the following graph:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"The boxes in the above graph have the following meaning:\n"
"<ul>\n"
diff --git a/src/translator_nl.h b/src/translator_nl.h
index 147664c..631ed08 100644
--- a/src/translator_nl.h
+++ b/src/translator_nl.h
@@ -685,7 +685,7 @@ class TranslatorDutch : public Translator
"\\endcode\n"
"Als de \\c MAX_DOT_GRAPH_HEIGHT tag in the configuratie file "
"op 200 gezet is, zal het bestaande voorbeeld resulteren in de volgende graaf:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"De rechthoeken in the bovenstaande graaf hebben de volgende betekenis:\n"
"<ul>\n"
diff --git a/src/translator_no.h b/src/translator_no.h
index f888517..65a829c 100644
--- a/src/translator_no.h
+++ b/src/translator_no.h
@@ -742,7 +742,7 @@ class TranslatorNorwegian : public TranslatorAdapter_1_2_2
"\\endcode\n"
"If the \\c MAX_DOT_GRAPH_HEIGHT tag in the configuration file "
"is set to 200 this will result in the following graph:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"The boxes in the above graph have the following meaning:\n"
"<ul>\n"
diff --git a/src/translator_pl.h b/src/translator_pl.h
index ba2fa49..bee4553 100644
--- a/src/translator_pl.h
+++ b/src/translator_pl.h
@@ -938,7 +938,7 @@ class TranslatorPolish : public TranslatorAdapter_1_2_1
"\\endcode\n"
"Je¶li znacznik \\c MAX_DOT_GRAPH_HEIGHT w pliku konfiguracji "
"jest ustawiony na 200, odniesie to rezultat w nastêpuj±cym wykresie:"
- "<p><center><img src=\"graph_legend.png\"></center>\n"
+ "<p><center><img src=\"graph_legend."+Config_getEnum("DOT_IMAGE_FORMAT")+"\"></center>\n"
"<p>\n"
"Pude³ka w powy¿szym wykresie maj± nastêpuj±ce znaczenie:\n"
"<ul>\n"
diff --git a/src/translator_pt.h b/src/translator_pt.h