summaryrefslogtreecommitdiffstats
path: root/Doc/reference/simple_stmts.rst
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2007-08-15 14:28:22 (GMT)
committerGeorg Brandl <georg@python.org>2007-08-15 14:28:22 (GMT)
commit116aa62bf54a39697e25f21d6cf6799f7faa1349 (patch)
tree8db5729518ed4ca88e26f1e26cc8695151ca3eb3 /Doc/reference/simple_stmts.rst
parent739c01d47b9118d04e5722333f0e6b4d0c8bdd9e (diff)
downloadcpython-116aa62bf54a39697e25f21d6cf6799f7faa1349.zip
cpython-116aa62bf54a39697e25f21d6cf6799f7faa1349.tar.gz
cpython-116aa62bf54a39697e25f21d6cf6799f7faa1349.tar.bz2
Move the 3k reST doc tree in place.
Diffstat (limited to 'Doc/reference/simple_stmts.rst')
-rw-r--r--Doc/reference/simple_stmts.rst825
1 files changed, 825 insertions, 0 deletions
diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst
new file mode 100644
index 0000000..fbc626f
--- /dev/null
+++ b/Doc/reference/simple_stmts.rst
@@ -0,0 +1,825 @@
+
+.. _simple:
+
+*****************
+Simple statements
+*****************
+
+.. index:: pair: simple; statement
+
+Simple statements are comprised within a single logical line. Several simple
+statements may occur on a single line separated by semicolons. The syntax for
+simple statements is:
+
+.. productionlist::
+ simple_stmt: `expression_stmt`
+ : | `assert_stmt`
+ : | `assignment_stmt`
+ : | `augmented_assignment_stmt`
+ : | `pass_stmt`
+ : | `del_stmt`
+ : | `return_stmt`
+ : | `yield_stmt`
+ : | `raise_stmt`
+ : | `break_stmt`
+ : | `continue_stmt`
+ : | `import_stmt`
+ : | `global_stmt`
+
+
+.. _exprstmts:
+
+Expression statements
+=====================
+
+.. index:: pair: expression; statement
+
+Expression statements are used (mostly interactively) to compute and write a
+value, or (usually) to call a procedure (a function that returns no meaningful
+result; in Python, procedures return the value ``None``). Other uses of
+expression statements are allowed and occasionally useful. The syntax for an
+expression statement is:
+
+.. productionlist::
+ expression_stmt: `expression_list`
+
+.. index:: pair: expression; list
+
+An expression statement evaluates the expression list (which may be a single
+expression).
+
+.. index::
+ builtin: repr
+ object: None
+ pair: string; conversion
+ single: output
+ pair: standard; output
+ pair: writing; values
+ pair: procedure; call
+
+In interactive mode, if the value is not ``None``, it is converted to a string
+using the built-in :func:`repr` function and the resulting string is written to
+standard output (see :func:`print`) on a line by itself. (Expression
+statements yielding ``None`` are not written, so that procedure calls do not
+cause any output.)
+
+
+.. _assert:
+
+Assert statements
+=================
+
+.. index::
+ statement: assert
+ pair: debugging; assertions
+
+Assert statements are a convenient way to insert debugging assertions into a
+program:
+
+.. productionlist::
+ assert_stmt: "assert" `expression` ["," `expression`]
+
+The simple form, ``assert expression``, is equivalent to ::
+
+ if __debug__:
+ if not expression: raise AssertionError
+
+The extended form, ``assert expression1, expression2``, is equivalent to ::
+
+ if __debug__:
+ if not expression1: raise AssertionError, expression2
+
+.. index::
+ single: __debug__
+ exception: AssertionError
+
+These equivalences assume that ``__debug__`` and :exc:`AssertionError` refer to
+the built-in variables with those names. In the current implementation, the
+built-in variable ``__debug__`` is ``True`` under normal circumstances,
+``False`` when optimization is requested (command line option -O). The current
+code generator emits no code for an assert statement when optimization is
+requested at compile time. Note that it is unnecessary to include the source
+code for the expression that failed in the error message; it will be displayed
+as part of the stack trace.
+
+Assignments to ``__debug__`` are illegal. The value for the built-in variable
+is determined when the interpreter starts.
+
+
+.. _assignment:
+
+Assignment statements
+=====================
+
+.. index::
+ pair: assignment; statement
+ pair: binding; name
+ pair: rebinding; name
+ object: mutable
+ pair: attribute; assignment
+
+Assignment statements are used to (re)bind names to values and to modify
+attributes or items of mutable objects:
+
+.. productionlist::
+ assignment_stmt: (`target_list` "=")+ (`expression_list` | `yield_expression`)
+ target_list: `target` ("," `target`)* [","]
+ target: `identifier`
+ : | "(" `target_list` ")"
+ : | "[" `target_list` "]"
+ : | `attributeref`
+ : | `subscription`
+ : | `slicing`
+
+(See section :ref:`primaries` for the syntax definitions for the last three
+symbols.)
+
+.. index:: pair: expression; list
+
+An assignment statement evaluates the expression list (remember that this can be
+a single expression or a comma-separated list, the latter yielding a tuple) and
+assigns the single resulting object to each of the target lists, from left to
+right.
+
+.. index::
+ single: target
+ pair: target; list
+
+Assignment is defined recursively depending on the form of the target (list).
+When a target is part of a mutable object (an attribute reference, subscription
+or slicing), the mutable object must ultimately perform the assignment and
+decide about its validity, and may raise an exception if the assignment is
+unacceptable. The rules observed by various types and the exceptions raised are
+given with the definition of the object types (see section :ref:`types`).
+
+.. index:: triple: target; list; assignment
+
+Assignment of an object to a target list is recursively defined as follows.
+
+* If the target list is a single target: The object is assigned to that target.
+
+* If the target list is a comma-separated list of targets: The object must be a
+ sequence with the same number of items as there are targets in the target list,
+ and the items are assigned, from left to right, to the corresponding targets.
+ (This rule is relaxed as of Python 1.5; in earlier versions, the object had to
+ be a tuple. Since strings are sequences, an assignment like ``a, b = "xy"`` is
+ now legal as long as the string has the right length.)
+
+Assignment of an object to a single target is recursively defined as follows.
+
+* If the target is an identifier (name):
+
+ .. index:: statement: global
+
+* If the name does not occur in a :keyword:`global` statement in the current
+ code block: the name is bound to the object in the current local namespace.
+
+* Otherwise: the name is bound to the object in the current global namespace.
+
+ .. index:: single: destructor
+
+ The name is rebound if it was already bound. This may cause the reference count
+ for the object previously bound to the name to reach zero, causing the object to
+ be deallocated and its destructor (if it has one) to be called.
+
+ .. % nested
+
+* If the target is a target list enclosed in parentheses or in square brackets:
+ The object must be a sequence with the same number of items as there are targets
+ in the target list, and its items are assigned, from left to right, to the
+ corresponding targets.
+
+ .. index:: pair: attribute; assignment
+
+* If the target is an attribute reference: The primary expression in the
+ reference is evaluated. It should yield an object with assignable attributes;
+ if this is not the case, :exc:`TypeError` is raised. That object is then asked
+ to assign the assigned object to the given attribute; if it cannot perform the
+ assignment, it raises an exception (usually but not necessarily
+ :exc:`AttributeError`).
+
+ .. index::
+ pair: subscription; assignment
+ object: mutable
+
+* If the target is a subscription: The primary expression in the reference is
+ evaluated. It should yield either a mutable sequence object (such as a list) or
+ a mapping object (such as a dictionary). Next, the subscript expression is
+ evaluated.
+
+ .. index::
+ object: sequence
+ object: list
+
+ If the primary is a mutable sequence object (such as a list), the subscript must
+ yield a plain integer. If it is negative, the sequence's length is added to it.
+ The resulting value must be a nonnegative integer less than the sequence's
+ length, and the sequence is asked to assign the assigned object to its item with
+ that index. If the index is out of range, :exc:`IndexError` is raised
+ (assignment to a subscripted sequence cannot add new items to a list).
+
+ .. index::
+ object: mapping
+ object: dictionary
+
+ If the primary is a mapping object (such as a dictionary), the subscript must
+ have a type compatible with the mapping's key type, and the mapping is then
+ asked to create a key/datum pair which maps the subscript to the assigned
+ object. This can either replace an existing key/value pair with the same key
+ value, or insert a new key/value pair (if no key with the same value existed).
+
+ .. index:: pair: slicing; assignment
+
+* If the target is a slicing: The primary expression in the reference is
+ evaluated. It should yield a mutable sequence object (such as a list). The
+ assigned object should be a sequence object of the same type. Next, the lower
+ and upper bound expressions are evaluated, insofar they are present; defaults
+ are zero and the sequence's length. The bounds should evaluate to (small)
+ integers. If either bound is negative, the sequence's length is added to it.
+ The resulting bounds are clipped to lie between zero and the sequence's length,
+ inclusive. Finally, the sequence object is asked to replace the slice with the
+ items of the assigned sequence. The length of the slice may be different from
+ the length of the assigned sequence, thus changing the length of the target
+ sequence, if the object allows it.
+
+(In the current implementation, the syntax for targets is taken to be the same
+as for expressions, and invalid syntax is rejected during the code generation
+phase, causing less detailed error messages.)
+
+WARNING: Although the definition of assignment implies that overlaps between the
+left-hand side and the right-hand side are 'safe' (for example ``a, b = b, a``
+swaps two variables), overlaps *within* the collection of assigned-to variables
+are not safe! For instance, the following program prints ``[0, 2]``::
+
+ x = [0, 1]
+ i = 0
+ i, x[i] = 1, 2
+ print x
+
+
+.. _augassign:
+
+Augmented assignment statements
+-------------------------------
+
+.. index::
+ pair: augmented; assignment
+ single: statement; assignment, augmented
+
+Augmented assignment is the combination, in a single statement, of a binary
+operation and an assignment statement:
+
+.. productionlist::
+ augmented_assignment_stmt: `target` `augop` (`expression_list` | `yield_expression`)
+ augop: "+=" | "-=" | "*=" | "/=" | "%=" | "**="
+ : | ">>=" | "<<=" | "&=" | "^=" | "|="
+
+(See section :ref:`primaries` for the syntax definitions for the last three
+symbols.)
+
+An augmented assignment evaluates the target (which, unlike normal assignment
+statements, cannot be an unpacking) and the expression list, performs the binary
+operation specific to the type of assignment on the two operands, and assigns
+the result to the original target. The target is only evaluated once.
+
+An augmented assignment expression like ``x += 1`` can be rewritten as ``x = x +
+1`` to achieve a similar, but not exactly equal effect. In the augmented
+version, ``x`` is only evaluated once. Also, when possible, the actual operation
+is performed *in-place*, meaning that rather than creating a new object and
+assigning that to the target, the old object is modified instead.
+
+With the exception of assigning to tuples and multiple targets in a single
+statement, the assignment done by augmented assignment statements is handled the
+same way as normal assignments. Similarly, with the exception of the possible
+*in-place* behavior, the binary operation performed by augmented assignment is
+the same as the normal binary operations.
+
+For targets which are attribute references, the initial value is retrieved with
+a :meth:`getattr` and the result is assigned with a :meth:`setattr`. Notice
+that the two methods do not necessarily refer to the same variable. When
+:meth:`getattr` refers to a class variable, :meth:`setattr` still writes to an
+instance variable. For example::
+
+ class A:
+ x = 3 # class variable
+ a = A()
+ a.x += 1 # writes a.x as 4 leaving A.x as 3
+
+
+.. _pass:
+
+The :keyword:`pass` statement
+=============================
+
+.. index:: statement: pass
+
+.. productionlist::
+ pass_stmt: "pass"
+
+.. index:: pair: null; operation
+
+:keyword:`pass` is a null operation --- when it is executed, nothing happens.
+It is useful as a placeholder when a statement is required syntactically, but no
+code needs to be executed, for example::
+
+ def f(arg): pass # a function that does nothing (yet)
+
+ class C: pass # a class with no methods (yet)
+
+
+.. _del:
+
+The :keyword:`del` statement
+============================
+
+.. index:: statement: del
+
+.. productionlist::
+ del_stmt: "del" `target_list`
+
+.. index::
+ pair: deletion; target
+ triple: deletion; target; list
+
+Deletion is recursively defined very similar to the way assignment is defined.
+Rather that spelling it out in full details, here are some hints.
+
+Deletion of a target list recursively deletes each target, from left to right.
+
+.. index::
+ statement: global
+ pair: unbinding; name
+
+Deletion of a name removes the binding of that name from the local or global
+namespace, depending on whether the name occurs in a :keyword:`global` statement
+in the same code block. If the name is unbound, a :exc:`NameError` exception
+will be raised.
+
+.. index:: pair: free; variable
+
+It is illegal to delete a name from the local namespace if it occurs as a free
+variable in a nested block.
+
+.. index:: pair: attribute; deletion
+
+Deletion of attribute references, subscriptions and slicings is passed to the
+primary object involved; deletion of a slicing is in general equivalent to
+assignment of an empty slice of the right type (but even this is determined by
+the sliced object).
+
+
+.. _return:
+
+The :keyword:`return` statement
+===============================
+
+.. index:: statement: return
+
+.. productionlist::
+ return_stmt: "return" [`expression_list`]
+
+.. index::
+ pair: function; definition
+ pair: class; definition
+
+:keyword:`return` may only occur syntactically nested in a function definition,
+not within a nested class definition.
+
+If an expression list is present, it is evaluated, else ``None`` is substituted.
+
+:keyword:`return` leaves the current function call with the expression list (or
+``None``) as return value.
+
+.. index:: keyword: finally
+
+When :keyword:`return` passes control out of a :keyword:`try` statement with a
+:keyword:`finally` clause, that :keyword:`finally` clause is executed before
+really leaving the function.
+
+In a generator function, the :keyword:`return` statement is not allowed to
+include an :token:`expression_list`. In that context, a bare :keyword:`return`
+indicates that the generator is done and will cause :exc:`StopIteration` to be
+raised.
+
+
+.. _yield:
+
+The :keyword:`yield` statement
+==============================
+
+.. index:: statement: yield
+
+.. productionlist::
+ yield_stmt: `yield_expression`
+
+.. index::
+ single: generator; function
+ single: generator; iterator
+ single: function; generator
+ exception: StopIteration
+
+The :keyword:`yield` statement is only used when defining a generator function,
+and is only used in the body of the generator function. Using a :keyword:`yield`
+statement in a function definition is sufficient to cause that definition to
+create a generator function instead of a normal function.
+
+When a generator function is called, it returns an iterator known as a generator
+iterator, or more commonly, a generator. The body of the generator function is
+executed by calling the generator's :meth:`__next__` method repeatedly until it
+raises an exception.
+
+When a :keyword:`yield` statement is executed, the state of the generator is
+frozen and the value of :token:`expression_list` is returned to
+:meth:`__next__`'s caller. By "frozen" we mean that all local state is
+retained, including the current bindings of local variables, the instruction
+pointer, and the internal evaluation stack: enough information is saved so that
+the next time :meth:`__next__` is invoked, the function can proceed exactly as
+if the :keyword:`yield` statement were just another external call.
+
+As of Python version 2.5, the :keyword:`yield` statement is now allowed in the
+:keyword:`try` clause of a :keyword:`try` ... :keyword:`finally` construct. If
+the generator is not resumed before it is finalized (by reaching a zero
+reference count or by being garbage collected), the generator-iterator's
+:meth:`close` method will be called, allowing any pending :keyword:`finally`
+clauses to execute.
+
+.. note::
+
+ In Python 2.2, the :keyword:`yield` statement is only allowed when the
+ ``generators`` feature has been enabled. It will always be enabled in Python
+ 2.3. This ``__future__`` import statement can be used to enable the feature::
+
+ from __future__ import generators
+
+
+.. seealso::
+
+ :pep:`0255` - Simple Generators
+ The proposal for adding generators and the :keyword:`yield` statement to Python.
+
+ :pep:`0342` - Coroutines via Enhanced Generators
+ The proposal that, among other generator enhancements, proposed allowing
+ :keyword:`yield` to appear inside a :keyword:`try` ... :keyword:`finally` block.
+
+
+.. _raise:
+
+The :keyword:`raise` statement
+==============================
+
+.. index:: statement: raise
+
+.. productionlist::
+ raise_stmt: "raise" [`expression` ["," `expression` ["," `expression`]]]
+
+.. index::
+ single: exception
+ pair: raising; exception
+
+If no expressions are present, :keyword:`raise` re-raises the last exception
+that was active in the current scope. If no exception is active in the current
+scope, a :exc:`TypeError` exception is raised indicating that this is an error
+(if running under IDLE, a :exc:`Queue.Empty` exception is raised instead).
+
+Otherwise, :keyword:`raise` evaluates the expressions to get three objects,
+using ``None`` as the value of omitted expressions. The first two objects are
+used to determine the *type* and *value* of the exception.
+
+If the first object is an instance, the type of the exception is the class of
+the instance, the instance itself is the value, and the second object must be
+``None``.
+
+If the first object is a class, it becomes the type of the exception. The second
+object is used to determine the exception value: If it is an instance of the
+class, the instance becomes the exception value. If the second object is a
+tuple, it is used as the argument list for the class constructor; if it is
+``None``, an empty argument list is used, and any other object is treated as a
+single argument to the constructor. The instance so created by calling the
+constructor is used as the exception value.
+
+.. index:: object: traceback
+
+If a third object is present and not ``None``, it must be a traceback object
+(see section :ref:`types`), and it is substituted instead of the current
+location as the place where the exception occurred. If the third object is
+present and not a traceback object or ``None``, a :exc:`TypeError` exception is
+raised. The three-expression form of :keyword:`raise` is useful to re-raise an
+exception transparently in an except clause, but :keyword:`raise` with no
+expressions should be preferred if the exception to be re-raised was the most
+recently active exception in the current scope.
+
+Additional information on exceptions can be found in section :ref:`exceptions`,
+and information about handling exceptions is in section :ref:`try`.
+
+
+.. _break:
+
+The :keyword:`break` statement
+==============================
+
+.. index:: statement: break
+
+.. productionlist::
+ break_stmt: "break"
+
+.. index::
+ statement: for
+ statement: while
+ pair: loop; statement
+
+:keyword:`break` may only occur syntactically nested in a :keyword:`for` or
+:keyword:`while` loop, but not nested in a function or class definition within
+that loop.
+
+.. index:: keyword: else
+
+It terminates the nearest enclosing loop, skipping the optional :keyword:`else`
+clause if the loop has one.
+
+.. index:: pair: loop control; target
+
+If a :keyword:`for` loop is terminated by :keyword:`break`, the loop control
+target keeps its current value.
+
+.. index:: keyword: finally
+
+When :keyword:`break` passes control out of a :keyword:`try` statement with a
+:keyword:`finally` clause, that :keyword:`finally` clause is executed before
+really leaving the loop.
+
+
+.. _continue:
+
+The :keyword:`continue` statement
+=================================
+
+.. index:: statement: continue
+
+.. productionlist::
+ continue_stmt: "continue"
+
+.. index::
+ statement: for
+ statement: while
+ pair: loop; statement
+ keyword: finally
+
+:keyword:`continue` may only occur syntactically nested in a :keyword:`for` or
+:keyword:`while` loop, but not nested in a function or class definition or
+:keyword:`finally` statement within that loop. [#]_ It continues with the next
+cycle of the nearest enclosing loop.
+
+
+.. _import:
+
+The :keyword:`import` statement
+===============================
+
+.. index::
+ statement: import
+ single: module; importing
+ pair: name; binding
+ keyword: from
+
+.. productionlist::
+ import_stmt: "import" `module` ["as" `name`] ( "," `module` ["as" `name`] )*
+ : | "from" `relative_module` "import" `identifier` ["as" `name`]
+ : ( "," `identifier` ["as" `name`] )*
+ : | "from" `relative_module` "import" "(" `identifier` ["as" `name`]
+ : ( "," `identifier` ["as" `name`] )* [","] ")"
+ : | "from" `module` "import" "*"
+ module: (`identifier` ".")* `identifier`
+ relative_module: "."* `module` | "."+
+ name: `identifier`
+
+Import statements are executed in two steps: (1) find a module, and initialize
+it if necessary; (2) define a name or names in the local namespace (of the scope
+where the :keyword:`import` statement occurs). The first form (without
+:keyword:`from`) repeats these steps for each identifier in the list. The form
+with :keyword:`from` performs step (1) once, and then performs step (2)
+repeatedly.
+
+In this context, to "initialize" a built-in or extension module means to call an
+initialization function that the module must provide for the purpose (in the
+reference implementation, the function's name is obtained by prepending string
+"init" to the module's name); to "initialize" a Python-coded module means to
+execute the module's body.
+
+.. index::
+ single: modules (in module sys)
+ single: sys.modules
+ pair: module; name
+ pair: built-in; module
+ pair: user-defined; module
+ module: sys
+ pair: filename; extension
+ triple: module; search; path
+
+The system maintains a table of modules that have been or are being initialized,
+indexed by module name. This table is accessible as ``sys.modules``. When a
+module name is found in this table, step (1) is finished. If not, a search for
+a module definition is started. When a module is found, it is loaded. Details
+of the module searching and loading process are implementation and platform
+specific. It generally involves searching for a "built-in" module with the
+given name and then searching a list of locations given as ``sys.path``.
+
+.. index::
+ pair: module; initialization
+ exception: ImportError
+ single: code block
+ exception: SyntaxError
+
+If a built-in module is found, its built-in initialization code is executed and
+step (1) is finished. If no matching file is found, :exc:`ImportError` is
+raised. If a file is found, it is parsed, yielding an executable code block. If
+a syntax error occurs, :exc:`SyntaxError` is raised. Otherwise, an empty module
+of the given name is created and inserted in the module table, and then the code
+block is executed in the context of this module. Exceptions during this
+execution terminate step (1).
+
+When step (1) finishes without raising an exception, step (2) can begin.
+
+The first form of :keyword:`import` statement binds the module name in the local
+namespace to the module object, and then goes on to import the next identifier,
+if any. If the module name is followed by :keyword:`as`, the name following
+:keyword:`as` is used as the local name for the module.
+
+.. index::
+ pair: name; binding
+ exception: ImportError
+
+The :keyword:`from` form does not bind the module name: it goes through the list
+of identifiers, looks each one of them up in the module found in step (1), and
+binds the name in the local namespace to the object thus found. As with the
+first form of :keyword:`import`, an alternate local name can be supplied by
+specifying ":keyword:`as` localname". If a name is not found,
+:exc:`ImportError` is raised. If the list of identifiers is replaced by a star
+(``'*'``), all public names defined in the module are bound in the local
+namespace of the :keyword:`import` statement..
+
+.. index:: single: __all__ (optional module attribute)
+
+The *public names* defined by a module are determined by checking the module's
+namespace for a variable named ``__all__``; if defined, it must be a sequence of
+strings which are names defined or imported by that module. The names given in
+``__all__`` are all considered public and are required to exist. If ``__all__``
+is not defined, the set of public names includes all names found in the module's
+namespace which do not begin with an underscore character (``'_'``).
+``__all__`` should contain the entire public API. It is intended to avoid
+accidentally exporting items that are not part of the API (such as library
+modules which were imported and used within the module).
+
+The :keyword:`from` form with ``*`` may only occur in a module scope. If the
+wild card form of import --- ``import *`` --- is used in a function and the
+function contains or is a nested block with free variables, the compiler will
+raise a :exc:`SyntaxError`.
+
+.. index::
+ keyword: from
+ statement: from
+
+.. index::
+ triple: hierarchical; module; names
+ single: packages
+ single: __init__.py
+
+**Hierarchical module names:** when the module names contains one or more dots,
+the module search path is carried out differently. The sequence of identifiers
+up to the last dot is used to find a "package"; the final identifier is then
+searched inside the package. A package is generally a subdirectory of a
+directory on ``sys.path`` that has a file :file:`__init__.py`. [XXX Can't be
+bothered to spell this out right now; see the URL
+http://www.python.org/doc/essays/packages.html for more details, also about how
+the module search works from inside a package.]
+
+.. %
+
+.. index:: builtin: __import__
+
+The built-in function :func:`__import__` is provided to support applications
+that determine which modules need to be loaded dynamically; refer to
+:ref:`built-in-funcs` for additional information.
+
+
+.. _future:
+
+Future statements
+-----------------
+
+.. index:: pair: future; statement
+
+A :dfn:`future statement` is a directive to the compiler that a particular
+module should be compiled using syntax or semantics that will be available in a
+specified future release of Python. The future statement is intended to ease
+migration to future versions of Python that introduce incompatible changes to
+the language. It allows use of the new features on a per-module basis before
+the release in which the feature becomes standard.
+
+.. productionlist:: *
+ future_statement: "from" "__future__" "import" feature ["as" name]
+ : ("," feature ["as" name])*
+ : | "from" "__future__" "import" "(" feature ["as" name]
+ : ("," feature ["as" name])* [","] ")"
+ feature: identifier
+ name: identifier
+
+A future statement must appear near the top of the module. The only lines that
+can appear before a future statement are:
+
+* the module docstring (if any),
+* comments,
+* blank lines, and
+* other future statements.
+
+The features recognized by Python 2.5 are ``absolute_import``, ``division``,
+``generators``, ``nested_scopes`` and ``with_statement``. ``generators`` and
+``nested_scopes`` are redundant in Python version 2.3 and above because they
+are always enabled.
+
+A future statement is recognized and treated specially at compile time: Changes
+to the semantics of core constructs are often implemented by generating
+different code. It may even be the case that a new feature introduces new
+incompatible syntax (such as a new reserved word), in which case the compiler
+may need to parse the module differently. Such decisions cannot be pushed off
+until runtime.
+
+For any given release, the compiler knows which feature names have been defined,
+and raises a compile-time error if a future statement contains a feature not
+known to it.
+
+The direct runtime semantics are the same as for any import statement: there is
+a standard module :mod:`__future__`, described later, and it will be imported in
+the usual way at the time the future statement is executed.
+
+The interesting runtime semantics depend on the specific feature enabled by the
+future statement.
+
+Note that there is nothing special about the statement::
+
+ import __future__ [as name]
+
+That is not a future statement; it's an ordinary import statement with no
+special semantics or syntax restrictions.
+
+Code compiled by calls to the builtin functions :func:`exec` and :func:`compile`
+that occur in a module :mod:`M` containing a future
+statement will, by default, use the new syntax or semantics associated with the
+future statement. This can, starting with Python 2.2 be controlled by optional
+arguments to :func:`compile` --- see the documentation of that function
+for details.
+
+A future statement typed at an interactive interpreter prompt will take effect
+for the rest of the interpreter session. If an interpreter is started with the
+:option:`-i` option, is passed a script name to execute, and the script includes
+a future statement, it will be in effect in the interactive session started
+after the script is executed.
+
+
+.. _global:
+
+The :keyword:`global` statement
+===============================
+
+.. index:: statement: global
+
+.. productionlist::
+ global_stmt: "global" `identifier` ("," `identifier`)*
+
+.. index:: triple: global; name; binding
+
+The :keyword:`global` statement is a declaration which holds for the entire
+current code block. It means that the listed identifiers are to be interpreted
+as globals. It would be impossible to assign to a global variable without
+:keyword:`global`, although free variables may refer to globals without being
+declared global.
+
+Names listed in a :keyword:`global` statement must not be used in the same code
+block textually preceding that :keyword:`global` statement.
+
+Names listed in a :keyword:`global` statement must not be defined as formal
+parameters or in a :keyword:`for` loop control target, :keyword:`class`
+definition, function definition, or :keyword:`import` statement.
+
+(The current implementation does not enforce the latter two restrictions, but
+programs should not abuse this freedom, as future implementations may enforce
+them or silently change the meaning of the program.)
+
+.. index::
+ builtin: exec
+ builtin: eval
+ builtin: compile
+
+**Programmer's note:** the :keyword:`global` is a directive to the parser. It
+applies only to code parsed at the same time as the :keyword:`global` statement.
+In particular, a :keyword:`global` statement contained in a string or code
+object supplied to the builtin :func:`exec` function does not affect the code
+block *containing* the function call, and code contained in such a string is
+unaffected by :keyword:`global` statements in the code containing the function
+call. The same applies to the :func:`eval` and :func:`compile` functions.
+
+.. rubric:: Footnotes
+
+.. [#] It may occur within an :keyword:`except` or :keyword:`else` clause. The
+ restriction on occurring in the :keyword:`try` clause is implementor's laziness
+ and will eventually be lifted.
+
+ candidates++;
}
- candidates++;
}
}
- }
- warn(root->fileName,root->startLine,
- "Warning: no matching class member found for"
- );
+ warn(root->fileName,root->startLine,
+ "Warning: no matching class member found for"
+ );
- if (root->tArgLists)
- {
- QListIterator<ArgumentList> alli(*root->tArgLists);
- ArgumentList *al;
- for (;(al=alli.current());++alli)
+ if (root->tArgLists)
{
- warn_cont(" template %s\n",tempArgListToString(al).data());
+ QListIterator<ArgumentList> alli(*root->tArgLists);
+ ArgumentList *al;
+ for (;(al=alli.current());++alli)
+ {
+ warn_cont(" template %s\n",tempArgListToString(al).data());
+ }
}
- }
- warn_cont(" %s\n",fullFuncDecl.data());
+ warn_cont(" %s\n",fullFuncDecl.data());
- if (candidates>0)
- {
- warn_cont("Possible candidates:\n");
- for (mni.toFirst();(md=mni.current());++mni)
+ if (candidates>0)
{
- ClassDef *cd=md->getClassDef();
- if (cd!=0 && cd->name()==className)
+ warn_cont("Possible candidates:\n");
+ for (mni.toFirst();(md=mni.current());++mni)
{
- if (md->templateArguments())
+ ClassDef *cd=md->getClassDef();
+ if (cd!=0 && cd->name()==className)
{
- warn_cont(" template %s\n",tempArgListToString(md->templateArguments()).data());
- }
- warn_cont(" ");
- if (md->typeString())
- {
- warn_cont("%s ",md->typeString());
+ if (md->templateArguments())
+ {
+ warn_cont(" template %s\n",tempArgListToString(md->templateArguments()).data());
+ }
+ warn_cont(" ");
+ if (md->typeString())
+ {
+ warn_cont("%s ",md->typeString());
+ }
+ QCString qScope = cd->qualifiedNameWithTemplateParameters();
+ if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data());
+ if (md->argsString()) warn_cont("%s",md->argsString());
+ warn_cont("\n");
}
- QCString qScope = cd->qualifiedNameWithTemplateParameters();
- if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data());
- if (md->argsString()) warn_cont("%s",md->argsString());
- warn_cont("\n");
}
}
}
}
+ else // member specialization
+ {
+ MemberDef::MemberType mtype=MemberDef::Function;
+ ArgumentList *tArgList = new ArgumentList;
+ // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
+ MemberDef *md=new MemberDef(
+ root->fileName,root->startLine,
+ funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,FALSE,
+ mtype,tArgList,root->argList);
+ //printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data());
+ if (root->tagInfo)
+ {
+ md->setAnchor(root->tagInfo->anchor);
+ md->setReference(root->tagInfo->tagName);
+ }
+ md->setMemberClass(cd);
+ md->setTemplateSpecialization(TRUE);
+ md->setDefinition(funcDecl);
+ md->enableCallGraph(root->callGraph);
+ md->setDocumentation(root->doc,root->docFile,root->docLine);
+ md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
+ md->setDocsForDefinition(!root->proto);
+ md->setPrototype(root->proto);
+ md->addSectionsToDefinition(root->anchors);
+ md->setBodySegment(root->bodyLine,root->endBodyLine);
+ bool ambig;
+ FileDef *fd=findFileDef(Doxygen::inputNameDict,root->fileName,ambig);
+ md->setBodyDef(fd);
+ md->setMemberSpecifiers(root->memSpec);
+ md->setMemberGroupId(root->mGrpId);
+ mn->append(md);
+ cd->insertMember(md);
+ md->setRefItems(root->sli);
+ }
}
else if (overloaded) // check if the function belongs to only one class
{
@@ -6683,7 +6721,7 @@ static void generateExampleDocs()
pd->docLine(), // startLine
pd, // context
0, // memberDef
- pd->documentation()+"\n\\include "+pd->name(), // docs
+ pd->documentation()+"\n\n\\include "+pd->name(), // docs
TRUE, // index words
TRUE, // is example
pd->name()
@@ -7073,7 +7111,7 @@ static void copyAndFilterFile(const char *fileName,BufStr &dest)
}
else
{
- QCString cmd=filterName+" "+fileName;
+ QCString cmd=filterName+" \""+fileName+"\"";
FILE *f=popen(cmd,"r");
if (!f)
{
@@ -7214,7 +7252,7 @@ static int readDir(QFileInfo *fi,
)
{
QDir dir((const char *)fi->absFilePath());
- dir.setFilter( QDir::Files | QDir::Dirs );
+ dir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden );
int totalSize=0;
//printf("readDir `%s'\n",fi->absFilePath().data());
//printf("killDict=%p count=%d\n",killDict,killDict->count());
@@ -7837,41 +7875,6 @@ void readConfiguration(int argc, char **argv)
setPerlModDoxyfile(configFileInfo.absFilePath());
Doxygen::xrefLists->setAutoDelete(TRUE);
-#if 0
- /* init the special lists */
- Doxygen::specialLists->insert("todo",
- new RefList("todo",
- "GENERATE_TODOLIST",
- theTranslator->trTodoList(),
- theTranslator->trTodo()
- //,BaseOutputDocInterface::Todo
- )
- );
- Doxygen::specialLists->insert("test",
- new RefList("test",
- "GENERATE_TESTLIST",
- theTranslator->trTestList(),
- theTranslator->trTest()
- //,BaseOutputDocInterface::Test
- )
- );
- Doxygen::specialLists->insert("bug",
- new RefList("bug",
- "GENERATE_BUGLIST",
- theTranslator->trBugList(),
- theTranslator->trBug()
- //,BaseOutputDocInterface::Bug
- )
- );
- Doxygen::specialLists->insert("deprecated",
- new RefList("deprecated",
- "GENERATE_DEPRECATEDLIST",
- theTranslator->trDeprecatedList(),
- theTranslator->trDeprecated()
- //,BaseOutputDocInterface::Deprecated
- )
- );
-#endif
}
@@ -7884,15 +7887,6 @@ void parseInput()
Doxygen::imageNameDict = new FileNameDict(257);
Doxygen::dotFileNameDict = new FileNameDict(257);
- //if (!Config_getString("DOC_URL").isEmpty())
- //{
- // Doxygen::tagDestinationDict.insert("_doc",new QCString(Config_getString("DOC_URL")));
- //}
- //if (!Config_getString("CGI_URL").isEmpty())
- //{
- // Doxygen::tagDestinationDict.insert("_cgi",new QCString(Config_getString("CGI_URL")+"/"+Config_getString("CGI_NAME")));
- //}
-
/**************************************************************************
* Initialize some global constants
**************************************************************************/
@@ -8313,16 +8307,16 @@ void parseInput()
findEnums(root);
findEnumDocumentation(root);
+ msg("Searching for members imported via using declarations...\n");
+ findUsingDeclImports(root);
+ findUsingDeclarations(root);
+
msg("Searching for member function documentation...\n");
findObjCMethodDefinitions(root);
findMemberDocumentation(root); // may introduce new members !
transferRelatedFunctionDocumentation();
transferFunctionDocumentation();
- msg("Searching for members imported via using declarations...\n");
- findUsingDeclImports(root);
- findUsingDeclarations(root);
-
msg("Building page list...\n");
buildPageList(root);
diff --git a/src/filedef.cpp b/src/filedef.cpp
index 2dabcc9..12c9872 100644
--- a/src/filedef.cpp
+++ b/src/filedef.cpp
@@ -222,7 +222,7 @@ void FileDef::writeDocumentation(OutputList &ol)
if (Config_getBool("SEARCHENGINE"))
{
Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase());
- Doxygen::searchIndex->addWord(localName().lower());
+ Doxygen::searchIndex->addWord(localName());
}
if (!Config_getString("GENERATE_TAGFILE").isEmpty())
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
index 54b0bbd..aa4ec5b 100644
--- a/src/groupdef.cpp
+++ b/src/groupdef.cpp
@@ -16,6 +16,7 @@
*/
#include <ctype.h>
+#include <qregexp.h>
#include "qtbc.h"
#include "groupdef.h"
#include "classdef.h"
@@ -457,14 +458,20 @@ void GroupDef::writeDocumentation(OutputList &ol)
//ol.disable(OutputGenerator::Man);
startFile(ol,getOutputFileBase(),name(),title);
startTitle(ol,getOutputFileBase());
- ol.docify(title);
+ ol.parseText(title);
addGroupListToTitle(ol,this);
endTitle(ol,getOutputFileBase(),title);
if (Config_getBool("SEARCHENGINE"))
{
Doxygen::searchIndex->setCurrentDoc(title,getOutputFileBase());
- Doxygen::searchIndex->addWord(localName().lower());
+ static QRegExp we("[a-zA-Z_][a-zA-Z_0-9]*");
+ int i=0,p=0,l=0;
+ while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
+ {
+ Doxygen::searchIndex->addWord(title.mid(i,l));
+ p=i+l;
+ }
}
if (Config_getBool("DETAILS_AT_TOP"))
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index 5b59560..e6017ba 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -26,9 +26,8 @@
#include "dot.h"
#include "message.h"
#include "config.h"
+#include "htmlgen.h"
-#define PREFRAG_START "<div class=\"fragment\"><pre>"
-#define PREFRAG_END "</pre></div>"
static QString htmlAttribsToString(const HtmlAttribList &attribs)
{
@@ -872,7 +871,7 @@ void HtmlDocVisitor::visitPost(DocParamSect *)
void HtmlDocVisitor::visitPre(DocParamList *pl)
{
if (m_hide) return;
- m_t << " <tr><td>";
+ m_t << " <tr><td valign=\"top\">";
if (pl->direction()!=DocParamSect::Unspecified)
{
m_t << "<tt>[";
@@ -890,7 +889,7 @@ void HtmlDocVisitor::visitPre(DocParamList *pl)
}
m_t << "]</tt>&nbsp;";
}
- m_t << "</td><td valign=top><em>";
+ m_t << "</td><td valign=\"top\"><em>";
QStrListIterator li(pl->parameters());
const char *s;
bool first=TRUE;
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index 69dd955..a17c256 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -42,12 +42,11 @@
#define DBG_HTML(x)
static const char *defaultStyleSheet =
-"H1 {\n"
-" text-align: center;\n"
+"BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {\n"
" font-family: Geneva, Arial, Helvetica, sans-serif;\n"
"}\n"
-"H2 {\n"
-" font-family: Geneva, Arial, Helvetica, sans-serif;\n"
+"H1 {\n"
+" text-align: center;\n"
"}\n"
"CAPTION { font-weight: bold }\n"
"DIV.qindex {\n"
@@ -93,10 +92,15 @@ static const char *defaultStyleSheet =
"A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }\n"
"A.el { text-decoration: none; font-weight: bold }\n"
"A.elRef { font-weight: bold }\n"
-"A.code { text-decoration: none; font-weight: normal; color: #1A419D}\n"
-"A.codeRef { font-weight: normal; color: #1A419D}\n"
+"A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}\n"
+"A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}\n"
+"A.codeRef:link { font-weight: normal; color: #0000FF}\n"
+"A.codeRef:visited { font-weight: normal; color: #0000FF}\n"
"A:hover { text-decoration: none; background-color: #f2f2ff }\n"
"DL.el { margin-left: -1cm }\n"
+".fragment {\n"
+" font-family: monospace\n"
+"}\n"
"PRE.fragment {\n"
" border: 1px solid #CCCCCC;\n"
" background-color: #f5f5f5;\n"
@@ -109,11 +113,12 @@ static const char *defaultStyleSheet =
" padding-top: 4px;\n"
" padding-bottom: 4px;\n"
"}\n"
-"DIV.fragment {\n"
-" border: 1px solid #CCCCCC;\n"
-" background-color: #f5f5f5;\n"
-" padding: 6px;\n"
-"}\n"
+//"DIV.fragment {\n"
+//" font-family: monospace\n"
+//" border: 1px solid #CCCCCC;\n"
+//" background-color: #f5f5f5;\n"
+//" padding: 6px;\n"
+//"}\n"
"DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }\n"
"TD.md { background-color: #F4F4FB; font-weight: bold; }\n"
"TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }\n"
@@ -123,7 +128,6 @@ static const char *defaultStyleSheet =
" margin-top: 12px;\n"
" margin-bottom: 6px;\n"
" font-weight: bold;\n"
-" font-family: Geneva, Arial, Helvetica, sans-serif;\n"
"}\n"
"DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px }\n"
"BODY {\n"
@@ -216,7 +220,6 @@ static const char *defaultStyleSheet =
" border-bottom-style: none;\n"
" border-left-style: none;\n"
" background-color: #FAFAFA;\n"
-" font-family: Geneva, Arial, Helvetica, sans-serif;\n"
" font-size: 12px;\n"
"}\n"
".memItemRight {\n"
@@ -235,7 +238,6 @@ static const char *defaultStyleSheet =
" border-bottom-style: none;\n"
" border-left-style: none;\n"
" background-color: #FAFAFA;\n"
-" font-family: Geneva, Arial, Helvetica, sans-serif;\n"
" font-size: 13px;\n"
"}\n"
".search { color: #003399;\n"
@@ -1535,7 +1537,7 @@ void HtmlGenerator::writeSearchPage()
t << "\n";
t << "function report_matches()\n";
t << "{\n";
- t << " return \"" << theTranslator->trSearchMatches() << " \";\n";
+ t << " return \"" << theTranslator->trSearchMatches() << " \";\n";
t << "}\n";
t << "\n";
t << search_script;
diff --git a/src/htmlgen.h b/src/htmlgen.h
index e63030a..9371970 100644
--- a/src/htmlgen.h
+++ b/src/htmlgen.h
@@ -21,6 +21,9 @@
#include "qtbc.h"
#include "outputgen.h"
+#define PREFRAG_START "<div class=\"fragment\"><pre class=\"fragment\">"
+#define PREFRAG_END "</pre></div>"
+
class QFile;
class HtmlGenerator : public OutputGenerator
@@ -112,8 +115,8 @@ class HtmlGenerator : public OutputGenerator
void writeRuler() { t << "<hr>"; }
void writeAnchor(const char *,const char *name)
{ t << "<a name=\"" << name <<"\"></a>"; }
- void startCodeFragment() { t << "<pre class=\"fragment\"><div>"; }
- void endCodeFragment() { t << "</div></pre>"; }
+ void startCodeFragment() { t << PREFRAG_START; }
+ void endCodeFragment() { t << PREFRAG_END; }
void writeLineNumber(const char *,const char *,const char *,int);
void startCodeLine() { col=0; }
void endCodeLine() { codify("\n"); }
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index 6bb1288..4fddfce 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -460,6 +460,7 @@ void ManDocVisitor::visitPre(DocSimpleList *)
{
if (m_hide) return;
m_indent+=2;
+ if (!m_firstCol) m_t << endl;
m_t << ".PD 0" << endl;
}
@@ -507,6 +508,7 @@ void ManDocVisitor::visitPre(DocHtmlList *)
{
if (m_hide) return;
m_indent+=2;
+ if (!m_firstCol) m_t << endl;
m_t << ".PD 0" << endl;
}
@@ -514,6 +516,7 @@ void ManDocVisitor::visitPost(DocHtmlList *)
{
if (m_hide) return;
m_indent-=2;
+ if (!m_firstCol) m_t << endl;
m_t << ".PP" << endl;
}
@@ -741,6 +744,7 @@ void ManDocVisitor::visitPost(DocSecRefList *)
{
if (m_hide) return;
m_indent-=2;
+ if (!m_firstCol) m_t << endl;
m_t << ".PP" << endl;
}
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 752e2d8..5c0570b 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -343,6 +343,7 @@ MemberDef::MemberDef(const char *df,int dl,
section=0;
groupAlias=0;
explExt=FALSE;
+ tspec=FALSE;
cachedAnonymousType=0;
maxInitLines=Config_getInt("MAX_INITIALIZER_LINES");
userInitLines=-1;
@@ -834,8 +835,8 @@ void MemberDef::writeDeclaration(OutputList &ol,
if (Config_getBool("SEARCHENGINE"))
{
Doxygen::searchIndex->setCurrentDoc(qualifiedName(),getOutputFileBase(),anchor());
- Doxygen::searchIndex->addWord(localName().lower());
- Doxygen::searchIndex->addWord(qualifiedName().lower());
+ Doxygen::searchIndex->addWord(localName());
+ Doxygen::searchIndex->addWord(qualifiedName());
}
Definition *d=0;
@@ -1248,7 +1249,6 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
htmlHelp->addIndexItem(cname,name(),cfname,anchor());
}
linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.left(i));
- //ol+=*vmd->enumDecl();
vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef());
linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.right(ldef.length()-i-l));
@@ -1310,7 +1310,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
else // definition gets it template parameters from its class
// (since no definition was found)
{
- if (cd)
+ if (cd && !isTemplateSpecialization())
{
QList<ArgumentList> tempParamLists;
cd->getTemplateParameterLists(tempParamLists);
@@ -1670,7 +1670,6 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
ol.parseText(reimplFromLine.right(
reimplFromLine.length()-markerPos-2)); // text right from marker
- ol.newParagraph();
}
else
{
@@ -1751,7 +1750,6 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
index=newIndex+matchLen;
}
ol.parseText(reimplInLine.right(reimplInLine.length()-index));
- ol.newParagraph();
}
}
// write the list of examples that use this member
@@ -2003,9 +2001,14 @@ void MemberDef::addListReference(Definition *)
}
}
}
- //printf("*** addListReference %s todo=%d test=%d bug=%d\n",name().data(),todoId(),testId(),bugId());
- addRefItem(xrefListItems(),memLabel,
- getOutputFileBase()+"#"+anchor(),memName,argsString());
+ if (xrefListItems())
+ {
+ addRefItem(xrefListItems(),memLabel,
+ getOutputFileBase()+"#"+anchor(),memName,argsString());
+ }
+ else
+ {
+ }
}
MemberList *MemberDef::getSectionList(Definition *d) const
diff --git a/src/memberdef.h b/src/memberdef.h
index 34c7164..2fa4a85 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -134,6 +134,7 @@ class MemberDef : public Definition
bool isWritable() const { return (memSpec&Entry::Writable)!=0; }
bool isImplementation() const { return m_implOnly; }
bool isExternal() const { return explExt; }
+ bool isTemplateSpecialization() const { return tspec; }
bool isObjCMethod() const;
bool isConstructor() const;
bool isDestructor() const;
@@ -151,22 +152,23 @@ class MemberDef : public Definition
bool isDocumentedFriendClass() const;
// set functions
- void setMemberType(MemberType t) { mtype=t; }
- void setDefinition(const char *d) { def=d; }
- void setFileDef(FileDef *fd) { fileDef=fd; }
+ void setMemberType(MemberType t) { mtype=t; }
+ void setDefinition(const char *d) { def=d; }
+ void setFileDef(FileDef *fd) { fileDef=fd; }
void setAnchor(const char *a);
- void setProtection(Protection p) { prot=p; }
- void setMemberSpecifiers(int s) { memSpec=s; }
- void mergeMemberSpecifiers(int s) { memSpec|=s; }
+ void setProtection(Protection p) { prot=p; }
+ void setMemberSpecifiers(int s) { memSpec=s; }
+ void mergeMemberSpecifiers(int s) { memSpec|=s; }
void setInitializer(const char *i);
- void setBitfields(const char *s) { bitfields = s; }
- void setMaxInitLines(int lines) { userInitLines=lines; }
+ void setBitfields(const char *s) { bitfields = s; }
+ void setMaxInitLines(int lines) { userInitLines=lines; }
void setMemberClass(ClassDef *cd);
void setSectionList(Definition *d,MemberList *sl);
void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs);
- void setExplicitExternal(bool b) { explExt=b; }
- void setReadAccessor(const char *r) { read=r; }
- void setWriteAccessor(const char *w) { write=w; }
+ void setExplicitExternal(bool b) { explExt=b; }
+ void setReadAccessor(const char *r) { read=r; }
+ void setWriteAccessor(const char *w) { write=w; }
+ void setTemplateSpecialization(bool b) { tspec=b; }
void makeRelated() { related=TRUE; }
@@ -348,6 +350,7 @@ class MemberDef : public Definition
GroupDef *group; // group in which this member is in
bool explExt; // member was explicitly declared external
+ bool tspec; // member is a template specialization
ClassDef *cachedAnonymousType; // if the member has an anonymous compound
// as its type then this is computed by
diff --git a/src/memberlist.cpp b/src/memberlist.cpp