+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * configure.in (ENABLE_NUNIT_TESTS): New.
+ * runtime/Makefile.am (check-local): Use it to disable nunit
+ tests. Ensure that the test dlls are always built, however.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile.am (dist-hook): Ensure we use the 'default' profile.
+ * mono/Makefile.am (HANDLES): New. Disable 'handles' dir on Win32.
+ (SUBDIRS): Use it. Move 'cil' before 'metadata'.
+ * runtime/Makefile.am (install-exec): Pass
+ RUNTIME_HAS_CONSISTENT_GACDIR to the mcs/ build.
+
2004-12-01 Neale Ferguson <Neale.Ferguson@SoftwareAG-usa.com>
* configure.in : Add a flag for systems which pass parameters in
# Distribute the 'mcs' tree too
dist-hook:
test -d $(distdir)/mcs || mkdir $(distdir)/mcs
- d=`cd $(distdir)/mcs && pwd`; cd $(mcs_topdir) && $(MAKE) distdir=$$d dist-recursive
+ d=`cd $(distdir)/mcs && pwd`; cd $(mcs_topdir) && $(MAKE) PROFILE=default distdir=$$d dist-recursive
pkgconfigdir = $(libdir)/pkgconfig
if JIT_SUPPORTED
AC_SUBST(ICU_CFLAGS)
AC_SUBST(ICU_LIBS)
+AC_ARG_ENABLE(nunit-tests, [ --enable-nunit-tests Run the nunit tests of the class library on 'make check'])
+AM_CONDITIONAL(ENABLE_NUNIT_TESTS, [test x$enable_nunit_tests = xyes])
+
TARGET="unknown"
ACCESS_UNALIGNED="yes"
--- /dev/null
+
+SSAPRE stands for "SSA based Partial Redundancy Elimination".
+
+The algorithm is explained in this paper:
+
+Partial Redundancy Elimination in SSA Form (1999)
+Robert Kennedy, Sun Chan, SHIN-MING LIU, RAYMOND LO, PENG TU, FRED CHOW
+ACM Transactions on Programming Languages and Systems
+
+http://citeseer.ist.psu.edu/kennedy99partial.html
+
+In this document I give a gentle introduction to the concept of "partial"
+redundancies, and I explain the basic design decisions I took in implementing
+SSAPRE, but the paper is essential to understand the code.
+
+Partial Redundancy Elimination (or PRE) is an optimization that (guess what?)
+tries to remove redundant computations.
+It achieves this by saving the result of "not redundant" evaluations of
+expressions into appositely created temporary variables, so that "redundant"
+evaluations can be replaced by a load from the appropriate variable.
+
+Of course, on register starved architectures (x86) a temporary could cost more
+than the evaluation itself... PRE guarantees that the live range of the
+introduced variables is the minimal possible, but the added pressure on the
+register allocator can be an issue.
+
+The nice thing about PRE is that it not only removes "full" redundancies, but
+also "partial" ones.
+A full redundancy is easy to spot, and straightforward to handle, like in the
+following example (in every example here, the "expression" is "a + b"):
+
+int FullRedundancy1 (int a, int b) {
+ int v1 = a + b;
+ int v2 = a + b;
+ return v1 + v2;
+}
+
+PRE would transform it like this:
+
+int FullRedundancy1 (int a, int b) {
+ int t = a + b;
+ int v1 = t;
+ int v2 = t;
+ return v1 + v2;
+}
+
+Of course, either a copy propagation pass or a register allocator smart enough
+to remove unneeded variables would be necessary afterwords.
+
+Another example of full redundancy is the following:
+
+int FullRedundancy2 (int a, int b) {
+ int v1;
+
+ if (a >= 0) {
+ v1 = a + b; // BB1
+ } else {
+ a = -a; // BB2
+ v1 = a + b;
+ }
+
+ int v2 = a + b; // BB3
+ return v1 + v2;
+}
+
+Here the two expressions in BB1 and BB2 are *not* the same thing (a is
+modified in BB2), but both are redundant with the expression in BB3, so the
+code can be transformed like this:
+
+int FullRedundancy2 (int a, int b) {
+ int v1;
+ int t;
+
+ if (a >= 0) {
+ t = a + b; // BB1
+ v1 = t;
+ } else {
+ a = -a; // BB2
+ t = a + b;
+ v1 = t;
+ }
+
+ int v2 = t; // BB3
+ return v1 + v2;
+}
+
+Note that there are still two occurrences of the expression, while it can be
+easily seen that one (at the beginning of BB3) would suffice.
+This, however, is not a redundancy for PRE, because there is no path in the
+CFG where the expression is evaluated twice.
+Maybe this other kind of redundancy (which affects code size, and not the
+computations that are actually performed) would be eliminated by code hoisting,
+but I should check it; anyway, it is not a PRE related thing.
+
+An example of partial redundancy, on the other hand, is the following:
+
+int PartialRedundancy (int a, int b) {
+ int v1;
+
+ if (a >= 0) {
+ v1 = a + b; // BB1
+ } else {
+ v1 = 0; // BB2
+ }
+
+ int v2 = a + b; // BB3
+ return v1 + v2;
+}
+
+The redundancy is partial because the expression is computed more than once
+along some path in the CFG, not all paths.
+In fact, on the path BB1 - BB3 the expression is computed twice, but on the
+path BB2 - BB3 it is computed only once.
+In this case, PRE must insert new occurrences of the expression in order to
+obtain a full redundancy, and then use temporary variables as before.
+Adding a computation in BB2 would do the job.
+
+One nice thing about PRE is that loop invariants can be seen as partial
+redundancies.
+The idea is that you can get into the loop from two locations: from before the
+loop (at the 1st iteration), and from inside the loop itself (at any other
+iteration). If there is a computation inside the loop that is in fact a loop
+invariant, PRE will spot this, and will handle the BB before the loop as a
+place where to insert a new computation to get a full redundancy.
+At this point, the computation inside the loop would be replaced by an use of
+the temporary stored before the loop, effectively performing "loop invariant
+code motion".
+
+Now, this is what PRE does to the code.
+
+But how does it work?
+
+In "classic" solutions, PRE is formulated as a data flow analysis problem.
+The Muchnick provides a detailed description of the algorithm in this way (it
+is by far the most complex problem of this kind in the whole book).
+The point is that this algorithm does not exploit the SSA form.
+In fact, it has to perform all that amount of data flow analysis exactly
+because it does not take advantage of the work already done if you have put
+the program into SSA form.
+
+The SSAPRE algorithm, on the other hand, is designed with SSA in mind.
+It fully exploits the properties of SSA variables, it also explicitly reuses
+some data structures that must have been computed when building the SSA form,
+and takes great care to output its code in that form already (which means that
+the temporaries it introduces are already "versioned", with all the phi
+variables correctly placed).
+
+The main concept used in this algorithm is the "Factored Redundancy Graph" (or
+FRG in short). Basically, for each given expression, this graph shows all its
+occurrences in the program, and redundant ones are linked to their
+"representative occurrence" (the 1st occurrence met in a CFG traversal).
+The central observation is that the FRG is "factored" because each expression
+occurrence has exactly one representative occurrence, in the same way as the
+SSA form is a "factored" use-definition graph (each use is related to exactly
+one definition).
+And in fact building the FRG is much like building an SSA representation, with
+PHI nodes and all.
+By the way, I use "PHI" for "PHI expression occurrences", and "phi" for the
+usual phi definitions in SSA, because the paper uses an uppercase phi greek
+letter for PHI occurrences (while the lowercase one is standard in SSA).
+
+The really interesting point is that the FRG for a given expression has exactly
+the same "shape" of the use-definition graph for the temporary var that must
+be introduced to remove the redundancy, and this is why SSAPRE can easily emit
+its output code in correct SSA form.
+
+One particular characteristic of the SSAPRE algorithm is that it is "sparse",
+in the sense that it operates on expressions individually, looking only at the
+specific nodes it needs. This is in contrast to the classical way of solving
+data flow analysis problems, which is to operate globally, using data
+structures that work "in parallel" on all the entities they operate on (in
+practice bit sets, with for instance one bit per variable, or one bit per
+expression occurrence, you get the idea). This is handy (it exploits the
+parallelism of bit operations), but in general setting up those data
+structures is time consuming, and if the number of the things represented by
+the bits is not fixed in advance the code can get quite messy (bit sets must
+become growable).
+Moreover, applying special handling to individual expressions becomes a very
+tricky thing.
+
+SSAPRE, on the other hand, looks at the whole program (method in our case) only
+once, when it scans the code to collect (and classify) all expression
+occurrences.
+From here on, it operates on one expression at a time, looking only at its
+specific data structures (which, for each expression, are much smaller than
+the whole program, so the operations are fast).
+
+This approach has another advantage: the data structures used to operate on
+one expressions can be recycled when operating on other expressions, making
+the memory usage of the compiler lower, and (also important) avoiding losing
+time with memory allocations at all.
+This reflects directly on the design of those data structures.
+We can better see these advantages following which data structures are used
+during the application of SSAPRE to a method.
+
+The steps that are performed are the following:
+
+ * Initialization: scan the whole program, collect all the occurrences, and
+ build a worklist of expressions to be processed (each worklist entry
+ describes all the occurrences of the given expression).
+Here the data structures are the following:
+- One struct (the working area), containing the worklist and other
+ "global" data. The worklist itself contains an entry for each expression
+ which in turn has an entry for each occurrence.
+- One "info" struct for each BB, containing interesting dominance and CFG
+ related properties of the BB.
+
+Then, for each entry in the worklist, these operations are performed:
+
+ * PHI placement: find where the PHI nodes of the FRG must be placed.
+ * Renaming: assign appropriate "redundancy classes" to all occurrences (it
+ is like assigning variable versions when building an SSA form).
+ * Analyze: compute various flags in PHI nodes (which are the only places
+ that define where additional computations may be added).
+ This conceptually is composed of two data flow analysis passes, which in
+ practice only scan the PHI nodes in the FRG, not the whole code, so they
+ are not that heavy.
+ * Finalize: make so that the FRG is exactly like the use-def graph for the
+ temporary that will be introduced (it generally must be reshaped a bit
+ according to the flags computed in the previous step).
+ This is also made of two steps, but more for implementation reasons than
+ for conceptual ones.
+ * Code motion: actually update the code using the FRG.
+Here, what's needed is the following:
+- PHI occurrences (and some flags sbout them)
+- PHI argument occurrences (and some flags sbout them)
+- The renaming stack
+In practice, one can observe that each BB can have at most one PHI (we work
+on one expression at a time), and also one PHI argument (which we consider
+occurring at the end of the BB). Therefore, we do not have separate structures
+for these, but store them directly in the BB infos (which are kept for the
+whole SSAPRE invocation).
+The renaming stack is managed directly as a list of occurrences, with
+special handling for PHI nodes (which, being represented directly by their
+BB, are not "occurrences").
+
+
+So far, the only two missing things (with respect to SSAPRE in the paper) are
+unneeded PHIs eliminantion and the handling of "composite" expressions.
+Otherwise, the implementation is complete.
+
+Other interesting issues are:
+- SSAPRE has the assumption that:
+ - each SSA variable is related to one "original" (not SSA) variable, and
+ - no more than one version of each originsl variable is live at the same time
+ in the CFG.
+ It would be better to relax these assumptions.
+- SSAPRE operates on "syntactic" redundancies, not on "values".
+ GVNPRE (or other means of merging GVN) would be a nice alternative, see
+ "http://www.cs.purdue.edu/homes/vandrutj/papers/thesis.pdf".
- # $Id: alpha_mach_dep.S,v 1.1 2003/03/31 14:33:59 martin Exp $
+ # $Id$
.arch ev6
.text
# Created: 1993-05-16
# Public domain
-# $Id: mkinstalldirs,v 1.1 2003/03/31 14:34:30 martin Exp $
+# $Id$
errstatus=0
dirmode=""
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * library.make,
+ profiles/default.make,
+ profiles/basic.make : use PLATFORM_PATH_SEPARATOR.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * profiles/basic.make (MCS): Run the INTERNAL_MCS.
+ (USE_BOOT_COMPILE): Remove.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * library.make (gacdir_flag): New. Disable /gacdir flag if
+ RUNTIME_HAS_CONSISTENT_GACDIR flag is set.
+ (install-local): Use it.
+
2004-11-30 Raja R Harinath <rharinath@novell.com>
* executable.make (makefrag): Make profile-specific.
endif
gacutil = $(topdir)/tools/gacutil/gacutil.exe
-GACUTIL = MONO_PATH="$(topdir)/class/lib/default:$$MONO_PATH" $(RUNTIME) $(gacutil)
+GACUTIL = MONO_PATH="$(topdir)/class/lib/default$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(gacutil)
ifdef NO_SIGN_ASSEMBLY
SN = :
else
sn = $(topdir)/class/lib/net_1_1_bootstrap/sn.exe
-SN = MONO_PATH="$(topdir)/class/lib/net_1_1_bootstrap:$$MONO_PATH" $(RUNTIME) $(sn)
+SN = MONO_PATH="$(topdir)/class/lib/net_1_1_bootstrap/$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(sn)
SNFLAGS = -q -R
endif
else
+# If RUNTIME_HAS_CONSISTENT_GACDIR is set, it implies that the internal GACDIR
+# of the runtime is the same as the GACDIR we want. So, we don't need to pass it
+# to gacutil. Note that the GACDIR we want may not be the same as the value of
+# GACDIR set above, since the user could have overridden the value of $(prefix).
+#
+# This makes a difference only when we're building from the mono/ tree, since we
+# have to ensure that the internal GACDIR of the in-tree runtime matches where we
+# install the DLLs.
+
+ifndef RUNTIME_HAS_CONSISTENT_GACDIR
+gacdir_flag = /gacdir $(GACDIR)
+endif
+
install-local: $(gacutil)
- $(GACUTIL) /i $(the_lib) /f /gacdir $(GACDIR) /root $(GACROOT) /package $(FRAMEWORK_VERSION)
+ $(GACUTIL) /i $(the_lib) /f $(gacdir_flag) /root $(GACROOT) /package $(FRAMEWORK_VERSION)
uninstall-local: $(gacutil)
$(GACUTIL) /u $(LIBRARY_NAME:.dll=)
# Platform-specific makefile rules. This one's for linux.
#
-PLATFORM_DEBUG_FLAGS = -g
+PLATFORM_DEBUG_FLAGS = -debug
PLATFORM_MCS_FLAGS =
PLATFORM_RUNTIME = $(RUNTIME)
PLATFORM_CORLIB = mscorlib.dll
# -*- makefile -*-
BOOTSTRAP_MCS = $(EXTERNAL_MCS)
-MCS = false
+MCS = MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_MCS)
PROFILE_MCS_FLAGS = -d:NET_1_1 -d:ONLY_1_1 -d:BOOTSTRAP_WITH_OLDLIB
-USE_BOOT_COMPILE = yes
NO_SIGN_ASSEMBLY = yes
NO_TEST = yes
NO_INSTALL = yes
# in the MONO_PATH too).
ifdef PLATFORM_MONO_NATIVE
-BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/net_1_1_bootstrap:$$MONO_PATH" $(RUNTIME) $(topdir)/class/lib/net_1_1_bootstrap/mcs.exe
-MCS = MONO_PATH="$(topdir)/class/lib/$(PROFILE):$$MONO_PATH" $(INTERNAL_MCS)
-MBAS = MONO_PATH="$(topdir)/class/lib/$(PROFILE):$$MONO_PATH" $(INTERNAL_MBAS)
+BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/net_1_1_bootstrap$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(topdir)/class/lib/net_1_1_bootstrap/mcs.exe
+MCS = MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_MCS)
+MBAS = MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_MBAS)
else
BOOTSTRAP_MCS = $(EXTERNAL_MCS)
MCS = $(PLATFORM_RUNTIME) $(BOOTSTRAP_MCS) /lib:$(topdir)/class/lib/$(PROFILE)
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (basic_SUBDIRS): Add second-pass System, too.
+ (basic_files): Add System.Xml.dll.
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Makefile : now we need System.Xml.dll for basic bootstrapping.
+
2004-11-25 Raja R Harinath <rharinath@novell.com>
* Makefile (DISTFILES): Add public and private keys.
System \
$(MONO_CSHARP_DEBUGGER)
-basic_SUBDIRS := corlib System
+basic_SUBDIRS := corlib System System.XML System
net_1_1_bootstrap_SUBDIRS := $(bootstrap_dirs) Mono.Security
net_2_0_bootstrap_SUBDIRS := $(bootstrap_dirs)
all-local $(STD_TARGETS:=-local):
@:
-basic_files = mcs.exe mscorlib.dll System.dll
+basic_files = mcs.exe mscorlib.dll System.dll System.Xml.dll
DIST_PROFILE_DIRS = basic net_1_1_bootstrap default net_2_0_bootstrap net_2_0
+2004-12-03 Marek Safar <marek.safar@seznam.cz>
+
+ * System.Windows.Forms.dll.sources: Add ThreadExceptionDialog.cs
+
+2004-12-03 Marek Safar <marek.safar@seznam.cz>
+
+ * Makefile: Added System.Drawing.dll deps for tests.
+
+ * System.Windows.Forms_test.dll.sources: New test files.
+
+2004-12-02 Peter Bartok <pbartok@novell.com>
+
+ * SWF.csproj: Added Jackson's fresly minted TreeView files to
+ build list
+
2004-12-01 Jackson Harper <jackson@ximian.com>
* System.Windows.Forms.dll.sources: Add TreeNode love to the build.
EXTRA_DISTFILES = \
README
-
+\r
+TEST_MCS_FLAGS = /r:System.Drawing.dll
include ../../build/library.make
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "System.Windows.Forms\NodeLabelEditEventArgs.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\NodeLabelEditEventHandler.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "System.Windows.Forms\NumericUpDown.cs"\r
SubType = "Component"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "System.Windows.Forms\OpenTreeNodeEnumerator.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "System.Windows.Forms\Orientation.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "System.Windows.Forms\OwnerDrawPropertyBag.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "System.Windows.Forms\PaintEventArgs.cs"\r
SubType = "Code"\r
SubType = "Component"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeNode.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeNodeCollection.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeView.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeViewAction.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeViewCancelEventArgs.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeViewCancelEventHandler.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeViewEventArgs.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
+ <File\r
+ RelPath = "System.Windows.Forms\TreeViewEventHandler.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "System.Windows.Forms\TrackBar.cs"\r
SubType = "Component"\r
System.Windows.Forms/ThemeEngine.cs
System.Windows.Forms/ThemeGtk.cs
System.Windows.Forms/ThemeWin32Classic.cs
+System.Windows.Forms/ThreadExceptionDialog.cs
System.Windows.Forms/TickStyle.cs
System.Windows.Forms/Timer.cs
System.Windows.Forms/TODOAttribute.cs
public static void OnThreadException(Exception t) {
if (Application.ThreadException != null) {
Application.ThreadException(null, new ThreadExceptionEventArgs(t));
- } else {
- XplatUI.HandleException(t);
+ return;
+ }
+
+ // TODO: Missing implementation
+ //if (SystemInformation.UserInteractive)
+ {
+ Form form = new ThreadExceptionDialog (t);
+ form.ShowDialog ();
}
+ //else
+ Console.WriteLine (t.ToString ());
}
public static void RemoveMessageFilter(IMessageFilter filter) {
+2004-12-03 Jordi Mas i Hernandez <jordi@ximian.com>
+
+ * ListBox.cs: implemented clipping, selection single and multiple,
+ bug fixing
+
+2004-12-03 Ravindra <rkumar@novell.com>
+
+ * ListView.cs (ListView_KeyDown):
+ * ListView.cs (ListView_KeyUp): Fixed multiple selection handling
+ when CTRL key is pressed.
+ * ListViewItem.cs (Selected): Fixed setting the property.
+
+2004-12-03 Marek Safar <marek.safar@seznam.cz>
+\r
+ * Application.cs (OnThreadException): Use ThreadExceptionDialog.\r
+
+ * Form.cs: Add ActiveForm, FormBorderStyle, MaximizeBox,\r
+ MinimizeBox, ShowInTaskbar, TopMost properties.\r
+\r
+ * ThreadExceptionDialog.cs: Implemented (disabled TextBox until\r
+ will be implemented).
+\r
+2004-12-03 Marek Safar <marek.safar@seznam.cz>
+
+ * OwnerDrawPropertyBag.cs: New internal parameterless ctor.
+
+ * TreeNode.cs: Implemented ICloneable, Fixed to pass my simple
+ tests.
+
+ * TreeNodeCollection.cs: Add exception throwing for Add,AddRange.
+
+ * TreeView.cs: BackColor is Colors.Window.
+
+2004-12-01 Jackson Harper <jackson@ximian.com>
+
+ * TreeView.cs: When resizing the tree if the user is making it
+ smaller we don't get expose events, so we need to handle adding
+ the horizontal scrollbar in the size changed handler as well as
+ the expose handler.
+
2004-12-02 Jordi Mas i Hernandez <jordi@ximian.com>
* DrawItemState.cs: fixes wrong enum values
#region Local Variables
internal bool closing;
+ [Flags]
+ enum Flags {
+ ShowInTaskbar = 0x0001,
+ MaximizeBox = 0x0002,
+ MinimizeBox = 0x0004,
+ TopMost = 0x0008
+ }
+
+ Flags flags = Flags.ShowInTaskbar | Flags.MaximizeBox | Flags.MinimizeBox;
+ FormBorderStyle formBorderStyle = FormBorderStyle.Sizable;
private static bool autoscale;
private static Size autoscale_base_size;
private bool is_modal;
cp = base.CreateParams;\r
\r
cp.Style = (int)(WindowStyles.WS_OVERLAPPEDWINDOW |
- WindowStyles.WS_VISIBLE |
- WindowStyles.WS_CLIPSIBLINGS |
- WindowStyles.WS_CLIPCHILDREN);
+ WindowStyles.WS_VISIBLE |
+ WindowStyles.WS_CLIPSIBLINGS |
+ WindowStyles.WS_CLIPCHILDREN);
cp.Width = 250;
cp.Height = 250;
#region Public Static Properties
+
+ public static Form ActiveForm {\r
+ get {\r
+ //FIXME: create next driver call\r
+ return null;\r
+ }\r
+ }\r
+
#endregion // Public Static Properties
#region Public Instance Properties
}
}
+ public FormBorderStyle FormBorderStyle {\r
+ get {\r
+ return formBorderStyle;\r
+ }\r
+ set {\r
+ formBorderStyle = value;\r
+ Invalidate ();\r
+ }\r
+ }\r
+
+
public bool KeyPreview {
get {
return key_preview;
}
}
+ public bool MaximizeBox {\r
+ get {\r
+ return (flags & Flags.MaximizeBox) != 0;\r
+ }\r
+ set {\r
+ if (value)\r
+ flags &= ~Flags.MaximizeBox;\r
+ else\r
+ flags |= Flags.MaximizeBox;\r
+ }\r
+ }
+
public MainMenu Menu {
get {
return menu;
}
}
+ public bool MinimizeBox {\r
+ get {\r
+ return (flags & Flags.MinimizeBox) != 0;\r
+ }\r
+ set {\r
+ if (value)\r
+ flags &= ~Flags.MinimizeBox;\r
+ else\r
+ flags |= Flags.MinimizeBox;\r
+ }\r
+ }
+
public bool Modal {
get {
return is_modal;
}
}
+ public bool ShowInTaskbar {\r
+ get {\r
+ return (flags & Flags.ShowInTaskbar) != 0;\r
+ }\r
+ set {\r
+ if (value)\r
+ flags &= ~Flags.ShowInTaskbar;\r
+ else\r
+ flags |= Flags.ShowInTaskbar;\r
+ }\r
+ }\r
+
public FormStartPosition StartPosition {
get {
return start_position;
}
}
}
+
+ public bool TopMost {\r
+ get {\r
+ return (flags & Flags.TopMost) != 0;\r
+ }\r
+ set {\r
+ if (TopMost == value)\r
+ return;\r
+\r
+ if (value)\r
+ flags &= ~Flags.TopMost;\r
+ else\r
+ flags |= Flags.TopMost;\r
+\r
+ XplatUI.SetTopmost(window.Handle, owner != null ? owner.window.Handle : IntPtr.Zero, TopMost);
+ }\r
+ }\r
+
#endregion // Public Instance Properties
#region Protected Instance Properties
cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;
cp.Style |= (int)WindowStyles.WS_CLIPCHILDREN;
+ if (ShowInTaskbar)
+ cp.ExStyle |= (int)WindowStyles.WS_EX_APPWINDOW;
+ if (MaximizeBox)
+ cp.Style |= (int)WindowStyles.WS_MAXIMIZEBOX;
+ if (MinimizeBox)
+ cp.Style |= (int)WindowStyles.WS_MINIMIZEBOX;
+
return cp;
}
}
{
internal int item_height; /* Item's height */
internal int top_item; /* First item that we show the in the current page */
+ internal int last_item; /* Last visible item */
internal int page_size; /* Number of listbox items per page. In MultiColumn listbox indicates items per column */
internal Rectangle textdrawing_rect; /* Displayable Client Rectangle minus the scrollbars and with IntegralHeight calculated*/
internal bool show_verticalsb; /* Is Vertical scrollbar show it? */
public ListBoxInfo ()
{
+ last_item = 0;
item_height = 0;
top_item = 0;
page_size = 0;
internal class ListBoxItem
{
internal object obj;
- internal Rectangle rect;
internal bool Selected;
public ListBoxItem ()
{
obj = null;
- Selected = true;
+ Selected = false;
}
public ListBoxItem (object obj)
{
this.obj = obj;
- Selected = true;
+ Selected = false;
}
}
private VScrollBar vscrollbar_ctrl;
private HScrollBar hscrollbar_ctrl;
+ private bool control_pressed = true;
+
public ListBox ()
{
border_style = BorderStyle.Fixed3D; \r
hscrollbar_ctrl.Maximum = 0;
hscrollbar_ctrl.Visible = false;
hscrollbar_ctrl.ValueChanged += new EventHandler (HorizontalScrollEvent);
+
+ /* Events */
+ MouseDown += new MouseEventHandler (OnMouseDownLB);
}
#region Events
if (selected_index == value)
return;
+ if (value < -1 || value >= Items.Count)
+ throw new ArgumentOutOfRangeException ("Index of out range");
+
+ UnSelectItem (selected_index);
+ SelectItem (value);
selected_index = value;
- Refresh ();
+ OnSelectedIndexChanged (new EventArgs ());
+
}
}
public override string Text {
get {
return "";
- //throw new NotImplementedException ();
+
}
set {
throw new NotImplementedException ();
public void ClearSelected ()
{
- throw new NotImplementedException ();
+ foreach (int i in selected_indices)
+ UnSelectItem (selected_indices[i]);
+
+ selected_indices.ClearIndices ();
+ selected_items.ClearObjects ();
}
protected virtual ObjectCollection CreateItemCollection ()
public int IndexFromPoint (Point p)
{
- throw new NotImplementedException ();
+ return IndexFromPoint (p.X, p.Y);
}
- public int IndexFromPoint (int x, int y)
+ // Only returns visible points
+ public int IndexFromPoint (int x, int y)
{
- throw new NotImplementedException ();
+ for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
+ if (GetItemRectangle (i).Contains (x,y) == true)
+ return i;
+ }
+
+ return -1;
}
protected override void OnChangeUICues(UICuesEventArgs e)
protected virtual void OnDrawItem (DrawItemEventArgs e)
{
+ if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable))
+ DrawItem (this, e);
+
+ if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
+ e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
+ (ThemeEngine.Current.ColorHilight), e.Bounds);
+
+ e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
+ ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHilightText),
+ e.Bounds, string_format);
+ }
+ else {
+ e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
+ (e.BackColor), e.Bounds);
+
+ e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
+ ThemeEngine.Current.ResPool.GetSolidBrush (e.ForeColor),
+ e.Bounds, string_format);
+ }
+
+
+
}
{
base.OnResize (e);
UpdateInternalClientRect (ClientRectangle);
- }
+ }
protected override void OnSelectedIndexChanged (EventArgs e)
- {
- base.OnSelectedIndexChanged (e);
-
+ {
+ if (SelectedIndexChanged != null)
+ SelectedIndexChanged (this, e);
}
protected override void OnSelectedValueChanged (EventArgs e)
throw new NotImplementedException ();
}
- public void SetSelected (int index,bool value)
+ public void SetSelected (int index, bool value)
{
throw new NotImplementedException ();
}
listbox_info.textdrawing_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
listbox_info.textdrawing_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
listbox_info.textdrawing_rect.Height -= ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle);
- listbox_info.textdrawing_rect.Height -= ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
listbox_info.textdrawing_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
- listbox_info.textdrawing_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
if (listbox_info.show_verticalsb)
listbox_info.textdrawing_rect.Width -= vscrollbar_ctrl.Width;
}
}
+ LBoxInfo.last_item = LastVisibleItem ();
}
- internal void Draw ()
+ internal void Draw (Rectangle clip)
{
- // IntegralHeight has effect, we also have to paint the unused area
- if (ClientRectangle.Height > listbox_info.client_rect.Height) {
- Region area = new Region (ClientRectangle);
- area.Exclude (listbox_info.client_rect);
+
+ if (LBoxInfo.textdrawing_rect.Contains (clip) == false) {
+ // IntegralHeight has effect, we also have to paint the unused area
+ if (ClientRectangle.Height > listbox_info.client_rect.Height) {
+ Region area = new Region (ClientRectangle);
+ area.Exclude (listbox_info.client_rect);
+
+ DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
+ area.GetBounds (DeviceContext));
+ }
- DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
- area.GetBounds (DeviceContext));
+ DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), LBoxInfo.textdrawing_rect);
+ ThemeEngine.Current.DrawListBoxDecorations (DeviceContext, this);
}
- DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), LBoxInfo.textdrawing_rect);
-
- // Draw items
- int y = LBoxInfo.textdrawing_rect.Y;
- int top_y = LBoxInfo.textdrawing_rect.Y + LBoxInfo.textdrawing_rect.Height;
- Rectangle item_rect = new Rectangle ();
- item_rect.X = LBoxInfo.textdrawing_rect.X;
- item_rect.Height = LBoxInfo.item_height;
+ if (Items.Count > 0) {
+ Rectangle item_rect;
+ DrawItemState state = DrawItemState.None;
- if (MultiColumn)
- item_rect.Width = ColumnWidthInternal;
- else
- item_rect.Width = LBoxInfo.textdrawing_rect.Width;
+ for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
+ item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
- for (int i = LBoxInfo.top_item; i < Items.Count; i++) {
- item_rect.Y = y;
- DrawListBoxItem (DeviceContext, i, item_rect);
- y += LBoxInfo.item_height;
+ if (clip.IntersectsWith (item_rect) == false)
+ continue;
- if (MultiColumn) {
+ /* Draw item */
+ state = DrawItemState.None;
- if (y + LBoxInfo.item_height > top_y) {
- if (item_rect.X + ColumnWidthInternal > LBoxInfo.textdrawing_rect.Width)
- break;
-
- item_rect.X += ColumnWidthInternal;
- y = LBoxInfo.textdrawing_rect.Y;
+ if ((Items.GetListBoxItem (i)).Selected) {
+ state |= DrawItemState.Selected;
}
+ OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
+ i, state, ForeColor, BackColor));
}
- else
- if (IntegralHeight)
- if (y > top_y)
- break;
- else
- if (y + LBoxInfo.item_height> top_y)
- break;
-
}
-
- ThemeEngine.Current.DrawListBoxDecorations (DeviceContext, this);
}
- private void DrawListBoxItem (Graphics dc, int elem, Rectangle rect)
+ // Converts a GetItemRectangle to a one that we can display
+ private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
{
- dc.DrawString (Items[elem].ToString (), Font,
- ThemeEngine.Current.ResPool.GetSolidBrush (ForeColor),
- rect, string_format);
+ Rectangle item_rect;
+ Rectangle first_item_rect = GetItemRectangle (first_displayble);
+ item_rect = GetItemRectangle (index);
+ item_rect.X -= first_item_rect.X;
+ item_rect.Y -= first_item_rect.Y;
+
+ item_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
+ item_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
+ item_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
+
+ return item_rect;
}
// Value Changed
private void HorizontalScrollEvent (object sender, EventArgs e)
{
- LBoxInfo.top_item = listbox_info.page_size * hscrollbar_ctrl.Value;
+ LBoxInfo.top_item = listbox_info.page_size * hscrollbar_ctrl.Value;
+ LBoxInfo.last_item = LastVisibleItem ();
Refresh ();
}
+ private int LastVisibleItem ()
+ {
+ Rectangle item_rect;
+ int top_y = LBoxInfo.textdrawing_rect.Y + LBoxInfo.textdrawing_rect.Height;
+ int i = 0;
+
+ for (i = LBoxInfo.top_item; i < Items.Count; i++) {
+
+ item_rect = GetItemRectangle (i);
+
+ if (MultiColumn) {
+
+ if (item_rect.X > LBoxInfo.textdrawing_rect.Width)
+ return i - 1;
+ }
+ else {
+ if (IntegralHeight) {
+ if (item_rect.Y + item_rect.Height > top_y)
+ return i - 1;
+ }
+ else {
+ if (item_rect.Y > top_y)
+ return i - 1;
+ }
+ }
+ }
+
+ return i;
+ }
+
+ private void OnMouseDownLB (object sender, MouseEventArgs e)
+ {
+ int index = IndexFromPoint (e.X, e.Y);
+ if (index == -1) return;
+
+ switch (SelectionMode) {
+ case SelectionMode.None: // Do nothing
+ break;
+ case SelectionMode.One: {
+ SelectedIndex = index;
+ break;
+ }
+
+ case SelectionMode.MultiSimple: {
+ if (selected_index == -1) {
+ SelectedIndex = index;
+ } else {
+
+ if ((Items.GetListBoxItem (index)).Selected)
+ UnSelectItem (index);
+ else {
+ SelectItem (index);
+ OnSelectedIndexChanged (new EventArgs ());
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
private void OnPaintLB (PaintEventArgs pevent)
{
if (Width <= 0 || Height <= 0 || Visible == false)
return;
/* Copies memory drawing buffer to screen*/
- Draw ();
- pevent.Graphics.DrawImage (ImageBuffer, 0, 0);
+ Draw (pevent.ClipRectangle);
+ pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
}
internal void RellocateScrollBars ()
{
-
if (listbox_info.show_verticalsb) {
vscrollbar_ctrl.Size = new Size (vscrollbar_ctrl.Width,
CalcClientArea ();
}
+ // Add an item in the Selection array and marks it visually as selected
+ void SelectItem (int index)
+ {
+ if (index == -1)
+ return;
+
+ Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
+ (Items.GetListBoxItem (index)).Selected = true;
+ selected_indices.AddIndex (index);
+ selected_items.AddObject (Items[index]);
+ Invalidate (invalidate);
+ }
+
+ // Removes an item in the Selection array and marks it visually as unselected
+ void UnSelectItem (int index)
+ {
+ if (index == -1)
+ return;
+
+ Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
+ (Items.GetListBoxItem (index)).Selected = false;
+ selected_indices.RemoveIndex (index);
+ selected_items.RemoveObject (Items[index]);
+ Invalidate (invalidate);
+ }
+
// Updates the scrollbar's position with the new items and inside area
internal void UpdateItemInfo (bool adding, int first, int last)
{
}
}
- if (adding) {
+ if (MultiColumn == false) {
+ /* Calc the longest items for non multicolumn listboxes */
+ if ((first == -1 && last == -1) || (adding == false)) {
+
+ SizeF size;
+ for (int i = 0; i < Items.Count; i++) {
+ size = DeviceContext.MeasureString (Items[i].ToString(), Font);
- }
- else { /* Removing */
+ if ((int) size.Width > listbox_info.max_itemwidth)
+ listbox_info.max_itemwidth = (int) size.Width;
+ }
+ }
+ else {
+ if (adding) {
+ SizeF size;
+ for (int i = first; i < last + 1; i++) {
+ size = DeviceContext.MeasureString (Items[i].ToString(), Font);
+
+ if ((int) size.Width > listbox_info.max_itemwidth)
+ listbox_info.max_itemwidth = (int) size.Width;
+ }
+ }
+ }
}
+ UpdateShowHorizontalScrollBar ();
Refresh ();
}
{
bool show = false;
bool enabled = true;
- bool large_item = false;
if (MultiColumn) { /* Horizontal scrollbar is always shown in Multicolum mode */
} else { /* If large item*/
- if (large_item && HorizontalScrollbar) {
-
+ if (listbox_info.max_itemwidth > listbox_info.client_rect.Width && HorizontalScrollbar) {
+ show = true;
+ hscrollbar_ctrl.Maximum = listbox_info.max_itemwidth;
}
-
}
if (hscrollbar_ctrl.Enabled != enabled)
enabled = false;
}
}
-
+
if (vscrollbar_ctrl.Enabled != enabled)
vscrollbar_ctrl.Enabled = enabled;
// Value Changed
private void VerticalScrollEvent (object sender, EventArgs e)
- {
+ {
LBoxInfo.top_item = /*listbox_info.page_size + */ vscrollbar_ctrl.Value;
+ LBoxInfo.last_item = LastVisibleItem ();
Refresh ();
}
#endregion Private Methods
-
/*
ListBox.ObjectCollection
*/
private int AddItem (object item)
{
object_items.Add (item);
- listbox_items.Add (null);
+ listbox_items.Add (new ListBox.ListBoxItem ());
return object_items.Count - 1;
}
/*
ListBox.SelectedIndexCollection
-
- The idea is to get all the data for this collection from
- the ListBox SelectedObjectCollection object
-
*/
public class SelectedIndexCollection : IList, ICollection, IEnumerable
{
private ListBox owner;
- private ArrayList items = new ArrayList ();
+ private ArrayList indices = new ArrayList ();
public SelectedIndexCollection (ListBox owner)
{
#region Public Properties
public virtual int Count {
- get { return owner.SelectedItems.Count; }
+ get { return indices.Count; }
}
public virtual bool IsReadOnly {
}
public int this [int index] {
- get { throw new NotImplementedException (); }
+ get {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException ("Index of out range");
+
+ return (int) indices[index];
+ }
}
bool ICollection.IsSynchronized {
#region Public Methods
public bool Contains (int selectedIndex)
{
- throw new NotImplementedException ();
+ return indices.Contains (selectedIndex);
}
public virtual void CopyTo (Array dest, int index)
{
- throw new NotImplementedException ();
+ indices.CopyTo (dest, index);
}
public virtual IEnumerator GetEnumerator ()
{
- throw new NotImplementedException ();
+ return indices.GetEnumerator ();
}
int IList.Add (object obj)
int IList.IndexOf (object selectedIndex)
{
- return IndexOf ((int)selectedIndex);
+ return IndexOf ((int) selectedIndex);
}
void IList.Insert (int index, object value)
}
object IList.this[int index]{
- get {throw new NotImplementedException (); }
+ get {return indices[index]; }
set {throw new NotImplementedException (); }
}
public int IndexOf (int selectedIndex)
{
- throw new NotSupportedException ();
+ return indices.IndexOf (selectedIndex);
}
#endregion Public Methods
+ #region Private Methods
+ internal void AddIndex (int index)
+ {
+ indices.Add (indices);
+ }
+
+ internal void RemoveIndex (int index)
+ {
+ indices.Remove (indices);
+ }
+
+ internal void ClearIndices ()
+ {
+ indices.Clear ();
+ }
+
+ #endregion Private Methods
+
}
/*
public class SelectedObjectCollection : IList, ICollection, IEnumerable
{
private ListBox owner;
- private ArrayList items = new ArrayList ();
+ private ArrayList object_items = new ArrayList ();
public SelectedObjectCollection (ListBox owner)
{
#region Public Properties
public virtual int Count {
- get { return items.Count; }
+ get { return object_items.Count; }
}
public virtual bool IsReadOnly {
}
bool ICollection.IsSynchronized {
- get { return false; }
+ get { return true; }
}
object ICollection.SyncRoot {
}
object IList.this[int index] {
- get { return items [index]; }
- set { items [index] = value; }
+ get { return object_items[index]; }
+ set { throw new NotSupportedException (); }
}
#endregion Public Properties
#region Public Methods
public virtual bool Contains (object selectedObject)
{
- return items.Contains (selectedObject);
+ return object_items.Contains (selectedObject);
}
public virtual void CopyTo (Array dest, int index)
{
- throw new NotImplementedException ();
+ object_items.CopyTo (dest, index);
}
int IList.Add (object value)
int IList.IndexOf (object selectedIndex)
{
- throw new NotImplementedException ();
+ return IndexOf ((int) selectedIndex);
}
\r
void IList.Insert (int index, object value)
\r
public int IndexOf (int selectedIndex)
{
- throw new NotImplementedException ();
+ return object_items.IndexOf (selectedIndex);
}
public virtual IEnumerator GetEnumerator ()
{
- throw new NotImplementedException ();
+ return object_items.GetEnumerator ();
}
#endregion Public Methods
+ #region Private Methods
+ internal void AddObject (object obj)
+ {
+ object_items.Add (obj);
+ }
+
+ internal void RemoveObject (object obj)
+ {
+ object_items.Remove (obj);
+ }
+
+ internal void ClearObjects ()
+ {
+ object_items.Clear ();
+ }
+
+ #endregion Private Methods
+
}
}
private void ListView_KeyDown (object sender, KeyEventArgs ke)
{
- if (!ke.Handled && ke.Control) {
+ if (!ke.Handled && ke.KeyCode == Keys.ControlKey) {
this.ctrl_pressed = true;
ke.Handled = true;
}
private void ListView_KeyUp (object sender, KeyEventArgs ke)
{
- if (!ke.Handled && ke.Control) {
+ if (!ke.Handled && ke.KeyCode == Keys.ControlKey) {
this.ctrl_pressed = false;
ke.Handled = true;
}
if (this.clicked_item != null) {
this.clicked_item.Selected = true;
-
- // Raise the event if it is a new selection
- if (this.clicked_item != this.last_clicked_item)
- this.OnSelectedIndexChanged (new EventArgs ());
+ // Raise the event
+ this.OnSelectedIndexChanged (new EventArgs ());
this.Redraw (false);
}
ListViewItem item = this.GetItemAt (hit.X, hit.Y);
if (item != null) {
- if (this.CanMultiselect == false &&
- this.selected_items.Count > 0) {
- this.selected_items.Clear ();
- this.selected_indices.list.Clear ();
- }
-
item.Selected = true;
- this.selected_items.list.Add (item);
- this.selected_indices.list.Add (item.Index);
-
- if (this.CanMultiselect)
- this.OnSelectedIndexChanged (new EventArgs ());
+ // Raise the event
+ this.OnSelectedIndexChanged (new EventArgs ());
this.Redraw (false);
}
public bool Selected {
get { return selected; }
set {
- if (value != selected) {
- selected = value;
+ if (owner != null) {
+ if (owner.CanMultiselect == false &&
+ owner.SelectedItems.Count > 0) {
+ owner.SelectedItems.Clear ();
+ owner.SelectedIndices.list.Clear ();
+ }
- if (owner != null) {
- if (owner.CanMultiselect == false &&
- owner.SelectedItems.Count > 0) {
- owner.SelectedItems.Clear ();
- owner.SelectedIndices.list.Clear ();
- }
- if (selected) {
- //do we need !owner.SelectedItems.Contains (this))
- owner.SelectedItems.list.Add (this);
- owner.SelectedIndices.list.Add (this.Index);
- }
- else {
- owner.SelectedItems.list.Remove (this);
- owner.SelectedIndices.list.Remove (this.Index);
- }
+ selected = value;
+ if (selected) {
+ //do we need !owner.SelectedItems.Contains (this))
+ owner.SelectedItems.list.Add (this);
+ owner.SelectedIndices.list.Add (this.Index);
+ }
+ else {
+ owner.SelectedItems.list.Remove (this);
+ owner.SelectedIndices.list.Remove (this.Index);
}
}
}
private Color back_color;
private Font font;
+ internal OwnerDrawPropertyBag ()
+ {
+ fore_color = back_color = Color.Empty;
+ }
+
private OwnerDrawPropertyBag (Color fore_color, Color back_color, Font font)
{
this.fore_color = fore_color;
--- /dev/null
+//
+// System.Windows.Forms.ThreadExceptionDialog.cs
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Autors:
+// Marek Safar marek.safar@seznam.cz
+//
+// Copyright (C) Novell Inc., 2004
+
+// COMPLETE - BUT DISABLED TEXTBOX
+
+using System;
+using System.Text;
+using System.Reflection;
+
+namespace System.Windows.Forms
+{
+ public class ThreadExceptionDialog: Form
+ {
+ Exception e;
+ bool details;
+
+ private System.Windows.Forms.Button buttonIgnore;
+ private System.Windows.Forms.Button buttonAbort;
+ private System.Windows.Forms.Button buttonDetails;
+ private System.Windows.Forms.Label labelException;
+ private System.Windows.Forms.Label label1;
+#if TEXTBOX
+ private System.Windows.Forms.TextBox textBoxDetails;
+#endif
+ private System.Windows.Forms.Label helpText;
+
+ private void InitializeComponent()
+ {
+ this.helpText = new System.Windows.Forms.Label();
+ this.buttonAbort = new System.Windows.Forms.Button();
+ this.buttonIgnore = new System.Windows.Forms.Button();
+ this.buttonDetails = new System.Windows.Forms.Button();
+ this.labelException = new System.Windows.Forms.Label();
+#if TEXTBOX
+ this.textBoxDetails = new System.Windows.Forms.TextBox();
+#endif
+ this.label1 = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // helpText
+ //
+ this.helpText.Location = new System.Drawing.Point(60, 8);
+ this.helpText.Name = "helpText";
+ this.helpText.Size = new System.Drawing.Size(356, 40);
+ this.helpText.TabIndex = 0;
+ this.helpText.Text = "An unhandled exception has occurred in you application. If you click Ignore the a" +
+ "pplication will ignore this error and attempt to continue. If you click Abort, t" +
+ "he application will quit immediately.";
+ //
+ // buttonAbort
+ //
+ this.buttonAbort.DialogResult = System.Windows.Forms.DialogResult.Abort;
+ this.buttonAbort.Location = new System.Drawing.Point(332, 112);
+ this.buttonAbort.Name = "buttonAbort";
+ this.buttonAbort.Size = new System.Drawing.Size(85, 23);
+ this.buttonAbort.TabIndex = 4;
+ this.buttonAbort.Text = "&Abort";
+ this.buttonAbort.Click += new System.EventHandler(this.buttonAbort_Click);
+ //
+ // buttonIgnore
+ //
+ this.buttonIgnore.DialogResult = System.Windows.Forms.DialogResult.Ignore;
+ this.buttonIgnore.Location = new System.Drawing.Point(236, 112);
+ this.buttonIgnore.Name = "buttonIgnore";
+ this.buttonIgnore.Size = new System.Drawing.Size(85, 23);
+ this.buttonIgnore.TabIndex = 3;
+ this.buttonIgnore.Text = "&Ignore";
+ //
+ // buttonDetails
+ //
+ this.buttonDetails.Location = new System.Drawing.Point(140, 112);
+ this.buttonDetails.Name = "buttonDetails";
+ this.buttonDetails.Size = new System.Drawing.Size(85, 23);
+ this.buttonDetails.TabIndex = 2;
+ this.buttonDetails.Text = "Show &Details";
+ this.buttonDetails.Click += new System.EventHandler(this.buttonDetails_Click);
+ //
+ // labelException
+ //
+ this.labelException.Location = new System.Drawing.Point(60, 64);
+ this.labelException.Name = "labelException";
+ this.labelException.Size = new System.Drawing.Size(356, 32);
+ this.labelException.TabIndex = 1;
+ //
+ // textBoxDetails
+ //
+#if TEXTBOX
+ this.textBoxDetails.Location = new System.Drawing.Point(8, 168);
+ this.textBoxDetails.Multiline = true;
+ this.textBoxDetails.Name = "textBoxDetails";
+ this.textBoxDetails.ReadOnly = true;
+ this.textBoxDetails.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBoxDetails.Size = new System.Drawing.Size(408, 196);
+ this.textBoxDetails.TabIndex = 5;
+ this.textBoxDetails.TabStop = false;
+ this.textBoxDetails.Text = "";
+ this.textBoxDetails.WordWrap = false;
+#endif
+ //
+ // label1
+ //
+ this.label1.Location = new System.Drawing.Point(8, 148);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(100, 16);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Exception details";
+ //
+ // ThreadExceptionDialog
+ //
+ this.AcceptButton = this.buttonIgnore;
+ this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+ this.CancelButton = this.buttonAbort;
+ this.ClientSize = new System.Drawing.Size(428, 374);
+ this.Controls.Add(this.label1);
+#if TEXTBOX
+ this.Controls.Add(this.textBoxDetails);
+#endif
+ this.Controls.Add(this.labelException);
+ this.Controls.Add(this.buttonDetails);
+ this.Controls.Add(this.buttonIgnore);
+ this.Controls.Add(this.buttonAbort);
+ this.Controls.Add(this.helpText);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "ThreadExceptionDialog";
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.TopMost = true;
+ this.ResumeLayout(false);
+ }
+
+ public ThreadExceptionDialog (Exception e)
+ {
+ this.e = e;
+ InitializeComponent ();
+
+ this.labelException.Text = e.Message;
+ if (Form.ActiveForm != null)
+ this.Text = Form.ActiveForm.Text;
+ else
+ this.Text = "Mono";
+ this.buttonAbort.Enabled = Application.AllowQuit;
+ RefreshDetails ();
+ FillExceptionDetails ();
+ }
+
+ void buttonDetails_Click(object sender, System.EventArgs e)
+ {
+ details = !details;
+ RefreshDetails ();
+ }
+
+ void FillExceptionDetails ()
+ {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (e.ToString ());
+ sb.Append (Environment.NewLine + Environment.NewLine);
+ sb.Append ("Loaded assemblies:" + Environment.NewLine + Environment.NewLine);
+
+ foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ()) {
+ AssemblyName an = a.GetName ();
+ sb.AppendFormat ("Name:\t{0}" + Environment.NewLine, an.Name);
+ sb.AppendFormat ("Version:\t{0}" + Environment.NewLine, an.Version);
+ sb.AppendFormat ("Location:\t{0}" + Environment.NewLine, an.CodeBase);
+ sb.Append (Environment.NewLine);
+ }
+#if TEXTBOX
+ textBoxDetails.Text = sb.ToString ();
+#endif
+ }
+
+ void RefreshDetails ()
+ {
+ if (details) {
+ buttonDetails.Text = "Hide &Details";
+ Height = 410;
+ return;
+ }
+ buttonDetails.Text = "Show &Details";
+ Height = 180;
+ }
+
+ void buttonAbort_Click(object sender, System.EventArgs e)
+ {
+ Application.Exit ();
+ }
+ }
+}
namespace System.Windows.Forms {
[Serializable]
- public class TreeNode : MarshalByRefObject /*, ICloneable, ISerializable */ {
+ public class TreeNode : MarshalByRefObject, ICloneable /*, ISerializable */ {
private TreeView tree_view;
internal TreeNode parent;
private string text;
private int image_index = -1;
- private int selected_image_index;
- private string full_path;
+ private int selected_image_index = -1;
internal TreeNodeCollection nodes;
private bool is_expanded = true;
public TreeNode (string text, int image_index, int selected_image_index) : this (text)
{
this.image_index = image_index;
- this.selected_image_index = image_index;
+ this.selected_image_index = selected_image_index;
}
public TreeNode (string text, int image_index, int selected_image_index,
}
}
+ #region ICloneable Members
+
+ public object Clone()
+ {
+ TreeNode tn = new TreeNode (text, image_index, selected_image_index);
+ if (nodes != null) {
+ foreach (TreeNode child in nodes)
+ tn.Nodes.Add ((TreeNode)child.Clone ());
+ }
+ tn.Tag = tag;
+ tn.Checked = Checked;
+ if (prop_bag != null)
+ tn.prop_bag = OwnerDrawPropertyBag.Copy (prop_bag);
+ return tn;
+ }
+
+ #endregion
+
public TreeNode Parent {
get {
if (tree_view != null && tree_view.root_node == parent)
}
public Color BackColor {
- get { return prop_bag.BackColor; }
- set { prop_bag.BackColor = value; }
+ get {
+ return prop_bag == null ? Color.Empty : prop_bag.BackColor;
+ }
+ set {
+ if (prop_bag == null)
+ prop_bag = new OwnerDrawPropertyBag ();
+ prop_bag.BackColor = value;
+ }
}
public Color ForeColor {
- get { return prop_bag.ForeColor; }
- set { prop_bag.ForeColor = value; }
+ get {
+ return prop_bag == null ? Color.Empty : prop_bag.ForeColor;
+ }
+ set {
+ if (prop_bag == null)
+ prop_bag = new OwnerDrawPropertyBag ();
+ prop_bag.ForeColor = value;
+ }
}
public Font NodeFont {
- get { return prop_bag.Font; }
- set { prop_bag.Font = value; }
+ get {
+ return prop_bag == null ? null : prop_bag.Font;
+ }
+ set {
+ if (prop_bag == null)
+ prop_bag = new OwnerDrawPropertyBag ();
+ prop_bag.Font = value;
+ }
}
public TreeNodeCollection Nodes {
public string FullPath {
get {
- if (full_path != null)
- return full_path;
+ if (tree_view == null)
+ throw new Exception ("No TreeView associated");
StringBuilder builder = new StringBuilder ();
- string ps = (TreeView == null ? "/" : TreeView.PathSeparator);
- for (int i = 0; i < nodes.Count; i++) {
- builder.Append (nodes [i].Text);
- if (i - 1 != nodes.Count)
- builder.Append (ps);
- }
- full_path = builder.ToString ();
- return full_path;
+ BuildFullPath (builder);
+ return builder.ToString ();
}
}
+ bool BuildFullPath (StringBuilder path)
+ {
+ if (parent == null)
+ return false;
+
+ if (parent.BuildFullPath (path))
+ path.Append (tree_view.PathSeparator);
+
+ path.Append (text);
+ return true;
+ }
+
public bool IsExpanded {
get { return is_expanded; }
}
public TreeNode LastNode {
get {
- return Nodes [Nodes.Count - 1];
+ return (nodes == null || nodes.Count == 0) ? null : nodes [nodes.Count - 1];
}
}
public virtual int Add (TreeNode node)
{
+ if (node == null)
+ throw new ArgumentNullException("node");
+
if (owner != null && owner.TreeView != null && owner.TreeView.Sorted)
return AddSorted (node);
SetData (node);
public virtual void AddRange (TreeNode [] nodes)
{
+ if (nodes == null)
+ throw new ArgumentNullException("node");
+
// We can't just use Array.Copy because the nodes also
// need to have some properties set when they are added.
for (int i = 0; i < nodes.Length; i++)
}
public override Color BackColor {
- get { return base.BackColor; }
+ get { return SystemColors.Window; }
set { base.BackColor = value; }
}
foreach (TreeNode node in nodes) {
DrawNode (node, ref depth, ref node_count, item_height,
- font, ref visible_node_count, height, fill.Width);
+ font, ref visible_node_count, height);
depth = 0;
}
- if (add_hscroll)
+ if (max_node_width > ClientRectangle.Width) {
+ add_hscroll = true;
AddHorizontalScrollBar ();
+ }
if (add_vscroll)
AddVerticalScrollBar (node_count, vclip);
}
private void DrawNode (TreeNode node, ref int depth, ref int node_count, int item_height,
- Font font, ref int visible_node_count, int max_height, int max_width)
+ Font font, ref int visible_node_count, int max_height)
{
node_count++;
int x = (!show_root_lines && node.Parent != null ? depth - 1 : depth) * indent;
y += item_height + 1;
}
- if (node.Bounds.Right > max_width) {
- add_hscroll = true;
- if (node.Bounds.Right > max_node_width)
- max_node_width = node.Bounds.Right;
- }
+ if (node.Bounds.Right > max_node_width)
+ max_node_width = node.Bounds.Right;
depth++;
if (node.IsExpanded) {
for (int i = 0; i < _n_count; i++) {
int tdepth = depth;
DrawNode (node.nodes [i], ref tdepth, ref node_count, item_height,
- font, ref visible_node_count, max_height, max_width);
+ font, ref visible_node_count, max_height);
}
}
{
vbar.Maximum = total_nodes;
int height = ClientRectangle.Height;
-
+
vbar.LargeChange = height / ItemHeight;
if (add_hscroll)
private void SizeChangedHandler (object sender, EventArgs e)
{
+
+ if (max_node_width > ClientRectangle.Width) {
+ add_hscroll = true;
+ AddHorizontalScrollBar ();
+ }
+
if (vbar != null) {
vbar.Left = Right - vbar.Width;
vbar.Height = Height;
System.Windows.Forms/TestImageIndexConverter.cs
+System.Windows.Forms/TreeNodeTest.cs
+System.Windows.Forms/TreeViewTest.cs
string s = new TreeNode ("").FullPath;
}
- [Test, Ignore ("TODO")]
+ [Test]
public void FullPathTest ()
{
TreeNode tn_1 = new TreeNode ("A");
TreeNode tn_2 = new TreeNode ("B");
tn_2.Nodes.Add (tn_1);
- Assert.AreEqual (@"A\B", tn_1.FullPath);
+ TreeView tv = new TreeView ();
+ tv.Nodes.Add (tn_1);
+ tv.Nodes [0].Nodes.Add (tn_2);
+
+ Assert.AreEqual ("A", tn_1.FullPath, "#1");
+ Assert.AreEqual ("A", tv.Nodes[0].FullPath, "#2");
+ Assert.AreEqual (@"A\B", tn_2.FullPath, "#3");
+ tv.PathSeparator = "_separator_";
+ Assert.AreEqual ("A_separator_B", tn_2.FullPath, "#4");
}
[Test]
public void CloneTest ()
{
- // TODO: Add draw oriented fields will be implemented
-
TreeNode orig = new TreeNode ("text", 2, 3, new TreeNode [] { new TreeNode ("child", 22, 33) });
orig.Tag = FlatStyle.Flat;
orig.Checked = true;
+ orig.BackColor = System.Drawing.Color.AliceBlue;
+ orig.ForeColor = System.Drawing.Color.Beige;
+
TreeNode clone = (TreeNode)orig.Clone ();
Assert.AreEqual ("text", clone.Text, "#1");
Assert.AreEqual (2, clone.ImageIndex, "#2");
Assert.IsTrue (clone.Checked, "#6");
Assert.AreEqual ("child", clone.Nodes [0].Text, "#10");
Assert.AreEqual (22, clone.Nodes [0].ImageIndex, "#11");
+ Assert.AreEqual (System.Drawing.Color.AliceBlue, clone.BackColor, "#12");
+ Assert.AreEqual (System.Drawing.Color.Beige, clone.ForeColor, "#13");
}
}
\ No newline at end of file
--- /dev/null
+using System;
+using NUnit.Framework;
+using System.Windows.Forms;
+using System.Drawing;
+
+[TestFixture]
+public class TreeViewTest {
+
+ [Test]
+ public void DefaultCtor ()
+ {
+ TreeView tv = new TreeView ();
+ Assert.AreEqual (121, tv.Width, "#1");
+ Assert.AreEqual (97, tv.Height, "#2");
+ //Assert.AreEqual (BorderStyle.Fixed3D, tv.BorderStyle, "#3");
+
+ // Windows specific
+ Assert.AreEqual (SystemColors.Window, tv.BackColor);
+ }
+
+ [Test]
+ public void SimpleShowTest ()
+ {
+ Form f = new Form ();
+ TreeView tv = new TreeView ();
+ //tv.BorderStyle = BorderStyle.FixedSingle;
+ tv.Location = new Point (20, 20);
+ //tv.Text = "adssssss";
+
+ f.Controls.Add (tv);
+ f.Show ();
+ }
+}
public bool Equals(dbl that) { return d == that.d; }\r
}\r
\r
-#if FIXME\r
[Test]\r
public void GenericC()\r
{\r
Assert.AreEqual(0, h.Compare(s, t));\r
Assert.IsTrue(h.Compare(s, u) < 0);\r
}\r
-#endif\r
\r
\r
[Test]\r
}\r
\r
\r
-#if FIXME\r
[Test]\r
public void GenericCViaBuilder()\r
{\r
Assert.AreEqual(0, h.Compare(s, t));\r
Assert.IsTrue(h.Compare(s, u) < 0);\r
}\r
-#endif\r
\r
}\r
\r
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * hashing/HashTableTests.cs: Disabled some tests which make
+ assumptions about the ordering of elements in the hashtable. They
+ also do not work on Windows.
+ * hashing/HashBagTests.cs: Likewise.
+ * hashing/HashDictionaryTests.cs: Likewise.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * arrays/SortedArrayTests.cs: Removed the exception message from
+ the [ExpectedException(typeof(ArgumentOutOfRangeException))].
+
+ * trees/RedBlackTreeSetTests.cs: Likewise.
+ * trees/Bag.cs: Likewise.
+
2004-11-26 Martin Baulig <martin@ximian.com>
* */*.cs: Added some more `#if FIXME's to comment out tests which
[Test]\r
public void MapEtc()\r
{\r
-#if FIXME\r
ArrayList<double> dbl = (ArrayList<double>)view.Map(new Mapper<int,double>(delegate(int i){return i/10.0;}));\r
\r
Assert.IsTrue(dbl.Check());\r
list = (ArrayList<int>)view.FindAll(new Filter<int>(delegate(int i){return i%4==1;}));\r
Assert.IsTrue(list.Check());\r
Assert.IsTrue(IC.eq(list, 1, 1, 5, 9));\r
-#endif\r
}\r
\r
\r
}\r
\r
\r
-#if FIXME\r
[TestFixture]\r
public class Combined\r
{\r
Assert.IsFalse(lst.RemoveWithReturn(ref p));\r
}\r
}\r
-#endif\r
\r
[TestFixture]\r
public class Sorting\r
[Test]\r
public void MapEtc()\r
{\r
-#if FIXME\r
ArrayList<double> dbl = (ArrayList<double>)view.Map(new Mapper<int,double>(delegate(int i){return i/10.0;}));\r
\r
Assert.IsTrue(dbl.Check());\r
\r
Assert.IsTrue(list2.Check());\r
Assert.IsTrue(IC.eq(list2, 1, 5, 9));\r
-#endif\r
}\r
\r
\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -2.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow1()\r
{\r
tree.Predecessor(-2);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was 0.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow2()\r
{\r
tree.Predecessor(0);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -1.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakPredecessorTooLow1()\r
{\r
tree.WeakPredecessor(-1);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 38.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh1()\r
{\r
tree.Successor(38);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh2()\r
{\r
tree.Successor(39);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakSuccessorTooHigh1()\r
{\r
tree.WeakSuccessor(39);\r
\r
namespace MultiOps\r
{\r
-#if FIXME\r
[TestFixture]\r
public class AddAll\r
{\r
[TearDown]\r
public void Dispose() { array = null; }\r
}\r
-#endif\r
\r
\r
\r
\r
\r
\r
-#if FIXME_THREADING_TESTS\r
namespace Sync\r
{\r
[TestFixture]\r
public void Dispose() { tree = null; }\r
}\r
}\r
-#endif\r
\r
\r
\r
using MSG = System.Collections.Generic;\r
namespace nunit.hashtable.bag\r
{\r
-#if FIXME\r
[TestFixture]\r
public class Combined\r
{\r
Assert.IsFalse(lst.RemoveWithReturn(ref p));\r
}\r
}\r
-#endif\r
\r
\r
-#if FIXME\r
[TestFixture]\r
public class CollectionOrSink\r
{\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void RemoveAllCopies()\r
{\r
hashbag.Add(5);hashbag.Add(7);hashbag.Add(5);\r
[TearDown]\r
public void Dispose() { hashbag = null; }\r
}\r
-#endif\r
\r
\r
-#if FIXME\r
[TestFixture]\r
public class ArrayTest\r
{\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void CopyTo()\r
{\r
//Note: for small ints the itemhasher is the identity!\r
hashbag.CopyTo(a, 9);\r
}\r
}\r
-#endif\r
\r
\r
-#if FIXME\r
[TestFixture]\r
public class HashingEquals\r
{\r
Assert.IsTrue(h1.Equals(h2));\r
}\r
}\r
-#endif\r
}\r
#endif\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void Keys()\r
{\r
MSG.IEnumerator<string> keys = dict.Keys.GetEnumerator();\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void Values()\r
{\r
MSG.IEnumerator<string> values = dict.Values.GetEnumerator();\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void NormalUse()\r
{\r
Assert.IsTrue(dictenum.MoveNext());\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void Apply()\r
{\r
int sum = 0;\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void CopyTo()\r
{\r
//Note: for small ints the itemhasher is the identity!\r
\r
\r
[Test]\r
+ [Ignore("This is also failing on windows. Martin")]\r
public void RemoveAllCopies()\r
{\r
hashset.Add(5);hashset.Add(7);hashset.Add(5);\r
public void Dispose() { hashset = null; }\r
}\r
\r
-#if FIXME\r
[TestFixture]\r
public class Combined\r
{\r
Assert.IsFalse(lst.RemoveWithReturn(ref p));\r
}\r
}\r
-#endif\r
}\r
\r
\r
}\r
\r
\r
-#if FIXME\r
[TestFixture]\r
public class Combined\r
{\r
Assert.IsFalse(lst.RemoveWithReturn(ref p));\r
}\r
}\r
-#endif\r
\r
[TestFixture]\r
public class Inserting\r
[Test]\r
public void MapEtc()\r
{\r
-#if FIXME\r
LinkedList<double> dbl = (LinkedList<double>)view.Map(new Mapper<int,double>(delegate(int i){return i/10.0;}));\r
\r
Assert.IsTrue(dbl.Check());\r
\r
Assert.IsTrue(list2.Check());\r
Assert.IsTrue(IC.eq(list2, 1, 5, 9));\r
-#endif\r
}\r
\r
\r
[Test]\r
public void MapEtc()\r
{\r
-#if FIXME\r
LinkedList<double> dbl = (LinkedList<double>)view.Map(new Mapper<int,double>(delegate(int i){return i/10.0;}));\r
\r
Assert.IsTrue(dbl.Check());\r
list = (LinkedList<int>)view.FindAll(new Filter<int>(delegate(int i){return i%4==1;}));\r
Assert.IsTrue(list.Check());\r
Assert.IsTrue(IC.eq(list, 1, 1, 5, 9));\r
-#endif\r
}\r
\r
\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -2.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow1()\r
{\r
tree.Predecessor(-2);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was 0.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow2()\r
{\r
tree.Predecessor(0);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -2.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakPredecessorTooLow1()\r
{\r
tree.WeakPredecessor(-2);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 38.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh1()\r
{\r
tree.Successor(38);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh2()\r
{\r
tree.Successor(39);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakSuccessorTooHigh1()\r
{\r
tree.WeakSuccessor(39);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -2.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow1()\r
{\r
tree.Predecessor(-2);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was 0.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void PredecessorTooLow2()\r
{\r
tree.Predecessor(0);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Below minimum of set\r\nParameter name: item\r\nActual value was -2.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakPredecessorTooLow1()\r
{\r
tree.WeakPredecessor(-2);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 38.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh1()\r
{\r
tree.Successor(38);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void SuccessorTooHigh2()\r
{\r
tree.Successor(39);\r
\r
\r
[Test]\r
- [ExpectedException(typeof(ArgumentOutOfRangeException), "Above maximum of set\r\nParameter name: item\r\nActual value was 39.")]\r
+ [ExpectedException(typeof(ArgumentOutOfRangeException))]\r
public void WeakSuccessorTooHigh1()\r
{\r
tree.WeakSuccessor(39);\r
\r
\r
\r
-#if FIXME_THREADING_TESTS\r
namespace Sync\r
{\r
[TestFixture]\r
public void Dispose() { tree = null; }\r
}\r
}\r
-#endif\r
\r
\r
namespace Hashing\r
//
// Copyright (c) 2002 Chew Keong TAN
// All rights reserved.
-
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
r2.Normalize ();
- if (r2 < x) {
+ if (r2 <= x) {
Kernel.MinusEq (x, r2);
} else {
BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
+2004-12-03 Sebastien Pouliot <sebastien@ximian.com>
+
+ * BigInteger.cs: Fix issue #70169 in ModPow when modulus is a power of
+ two.
+
2004-10-19 Sebastien Pouliot <sebastien@ximian.com>
* BigInteger.cs: Fix issue #68452 when Randomize was being called on a
Assert.AreEqual (0, bi.BitCount (), "after randomize");
Assert.AreEqual (new BigInteger (0), bi, "Zero");
}
- }
+
+ [Test]\r
+ public void ModPow_0_Even ()\r
+ {
+ BigInteger x = new BigInteger (1);
+ BigInteger y = new BigInteger (0);
+ BigInteger z = x.ModPow (y, 1024);
+ Assert.AreEqual ("1", z.ToString (), "1 pow 0 == 1");
+ }\r
+\r
+ [Test]\r
+ public void ModPow_Big_Even ()\r
+ {\r
+ // http://gcc.gnu.org/ml/java/2001-01/msg00150.html\r
+ BigInteger x = BigInteger.Parse ("222556259477882361118129720038750144464896096345697329917462180806109470940281821580712930114298080816996240075704780895407778416354633927929850543336844729388676722554712356733107888579404671103423966348754128720372408391573576775380281687780687492527566938517625657849775850241884119610654472761291507970934");\r
+ BigInteger y = BigInteger.Parse ("110319153937683287453746757581772092163629769182044007837690319614087550020383807943886070460712008994638849038231331120616035703719955147238394349941968802357224177878230564379014395900786093465543114548034361805469457605783731382574787980771957640613447628351175959168798011343064123908688343944150028709336");\r
+ BigInteger z = BigInteger.Parse ("211455809992703561445401788842734346323873054957006050135582190157359001703882707072169880651159563587522668850959539052488297197610540840476872693108381476249027986010074543599432542677282684917897250864056294311624311681558854158430574409491081490219256907243905496547813878640883064959346343865887971384185");\r
+ BigInteger a = z.ModPow (x, y);\r
+ Assert.AreEqual ("89040229313686098274750802637193802904787850353791629688385431482589769348345172944539658366893587456857347312314974124445695423885005533414559099801699612294235861570065774222911180890417009385455826560773741520297884850460324781620974467560905975577765401911117379967692495136423710471201230243826129276993", a.ToString ());\r
+ }\r
+\r
+ [Test]\r
+ public void ModPow_2 ()\r
+ {\r
+ // #70169\r
+ BigInteger b = new BigInteger (10);\r
+ BigInteger m = new BigInteger (32);\r
+ // after 40 we start loosing double precision and result will differ\r
+ for (int i=1; i < 40; i++) {\r
+ BigInteger e = new BigInteger (i);\r
+ BigInteger r = e.ModPow (b, m);\r
+ long expected = (long) System.Math.Pow (i, 10) % 32;\r
+ Assert.AreEqual (expected.ToString (), r.ToString (), i.ToString ());\r
+ }\r
+ }\r
+ }\r
}
+2004-12-03 Sebastien Pouliot <sebastien@ximian.com>
+
+ * BigIntegerTest.cs: Added tests for ModPow when power is 0, for a
+ known case that was faling in classpath and when modulo is a power of
+ two (bug #70169).
+
2004-10-19 Sebastien Pouliot <sebastien@ximian.com>
* BigIntegerTest.cs: New. General unit tests for BigInteger.
+2004-12-01 Jackson Harper <jackson@ximian.com>
+
+ * PEAPI.cs: Allow DataConstants underlying type to be set.
+
2004-07-29 Martin Baulig <martin@ximian.com>
* PEAPI.cs (Module.Guid): New public property.
private uint dataOffset = 0;\r
\r
internal DataConstant() { }\r
-\r
+
public uint DataOffset {\r
get { return dataOffset; }\r
set { dataOffset = value; }\r
this.val = val;\r
size = (uint)val.Length;\r
}\r
-\r
+
+ public Type Type {
+ get { return type; }
+ set { type = value; }
+ }
+
internal sealed override uint GetBlobIndex(MetaData md) {\r
if (!addedToBlobHeap) {\r
blobIndex = md.AddToBlobHeap(val);\r
+2004-12-03 Sureshkumar T <tsureshkumar@novell.com>
+
+ * OdbcParameter.cs: Fixed a null reference exception when a
+ parameter is created and its value is not set. #68750.
+
2004-11-26 Sureshkumar T <tsureshkumar@novell.com>
* OdbcParameter.cs: Fixed Parameter Size property as well as
}\r
\r
private void setBuffer() {\r
- // Load buffer with new value\r
- if (odbcType == OdbcType.Int)\r
- intbuf = (int)ParamValue;\r
- else {\r
+ // Load buffer with new value
+ if (odbcType == OdbcType.Int)
+ intbuf = ParamValue == null ? new int () : (int) ParamValue;
+ else {\r
string paramValueString = ParamValue.ToString();\r
// Treat everything else as a string\r
// Init string buffer\r
+2004-12-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * SoapHttpClientProtocol.cs: dispose the StreamReader that wraps the
+ response stream.
+
2004-09-15 Lluis Sanchez Gual <lluis@novell.com>
* Methods.cs: Use the service namespace as the base for the soap action.
\r
// Deserialize the response\r
\r
- StreamReader reader = new StreamReader (stream, encoding, false);\r
- XmlTextReader xml_reader = new XmlTextReader (reader);\r
-\r
SoapHeaderCollection headers;\r
object content;\r
\r
- WebServiceHelper.ReadSoapMessage (xml_reader, type_info, msi.Use, msi.ResponseSerializer, out content, out headers);\r
+ using (StreamReader reader = new StreamReader (stream, encoding, false)) {
+ XmlTextReader xml_reader = new XmlTextReader (reader);
+
+ WebServiceHelper.ReadSoapMessage (xml_reader, type_info, msi.Use, msi.ResponseSerializer,
+ out content, out headers);
+ }
+
\r
if (content is Fault)\r
{\r
+2004-12-02 Lluis Sanchez Gual <lluis@novell.com>
+
+ * System.Web.dll.sources: Added new files:
+ System.Web.UI.WebControls/Menu.cs
+ System.Web.UI.WebControls/MenuEventArgs.cs
+ System.Web.UI.WebControls/MenuEventHandler.cs
+ System.Web.UI.WebControls/MenuItem.cs
+ System.Web.UI.WebControls/MenuItemBinding.cs
+ System.Web.UI.WebControls/MenuItemBindingCollection.cs
+ System.Web.UI.WebControls/MenuItemCollection.cs
+ System.Web.UI.WebControls/MenuItemStyle.cs
+ System.Web.UI.WebControls/MenuItemStyleCollection.cs
+
2004-12-02 Lluis Sanchez Gual <lluis@novell.com>
* Makefile: Added more TreeView resources.
+2004-12-03 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MenuEventArgs.cs: Changed to sealed.
+ * TreeView.cs: Minor fix.
+ * Menu.cs, MenuItemBindingCollection.cs, MenuItemCollection.cs,
+ MenuItemStyle.cs, MenuItemBinding.cs, MenuItem.cs,
+ MenuItemStyleCollection.cs: Initial Menu code.
+
2004-12-02 Lluis Sanchez Gual <lluis@novell.com>
* TreeNodeBindingCollection.cs, TreeNodeStyleCollection.cs:
--- /dev/null
+//
+// System.Web.UI.WebControls.Menu.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Text;
+using System.ComponentModel;
+using System.Web.UI;
+using System.Web.Handlers;
+using System.Collections.Specialized;
+using System.IO;
+
+namespace System.Web.UI.WebControls
+{
+ public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
+ {
+ MenuItemCollection items;
+ MenuItemBindingCollection dataBindings;
+ MenuItem selectedItem;
+ Hashtable bindings;
+
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
+ [Editor ("System.Web.UI.Design.MenuItemBindingsEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public virtual MenuItemBindingCollection DataBindings {
+ get {
+ if (dataBindings == null) {
+ dataBindings = new MenuItemBindingCollection ();
+ if (IsTrackingViewState)
+ ((IStateManager)dataBindings).TrackViewState();
+ }
+ return dataBindings;
+ }
+ }
+
+ [DefaultValue (500)]
+ public virtual int DisappearAfter {
+ get {
+ object o = ViewState ["DisappearAfter"];
+ if (o != null) return (int)o;
+ return 500;
+ }
+ set {
+ ViewState["DisappearAfter"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [UrlProperty]
+ [WebCategory ("Appearance")]
+ [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public virtual string DynamicBottomSeparatorImageUrl {
+ get {
+ object o = ViewState ["dbsiu"];
+ if (o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState["dbsiu"] = value;
+ }
+ }
+
+/* [DefaultValue (true)]
+ public virtual bool DynamicEnableDefaultPopOutImage {
+ get {
+ object o = ViewState ["dedpoi"];
+ if (o != null) return (bool)o;
+ return true;
+ }
+ set {
+ ViewState["dedpoi"] = value;
+ }
+ }
+*/
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Editor ("System.Web.UI.Design.MenuItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public virtual MenuItemCollection Items {
+ get {
+ if (items == null) {
+ items = new MenuItemCollection (this);
+ if (IsTrackingViewState)
+ ((IStateManager)items).TrackViewState();
+ }
+ return items;
+ }
+ }
+
+ [DefaultValue ('/')]
+ public virtual char PathSeparator {
+ get {
+ object o = ViewState ["PathSeparator"];
+ if(o != null) return (char)o;
+ return '/';
+ }
+ set {
+ ViewState ["PathSeparator"] = value;
+ }
+ }
+
+ [Browsable (false)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ public MenuItem SelectedItem {
+ get { return selectedItem; }
+ }
+
+ internal void SetSelectedItem (MenuItem item)
+ {
+ if (selectedItem == item) return;
+ if (selectedItem != null)
+ selectedItem.SelectedFlag = false;
+ selectedItem = item;
+ selectedItem.SelectedFlag = true;
+ // OnSelectedItemChanged (new MenuItemEventArgs (selectedItem));
+ }
+
+ public MenuItem FindItem (string valuePath)
+ {
+ if (valuePath == null) throw new ArgumentNullException ("valuePath");
+ string[] path = valuePath.Split (PathSeparator);
+ int n = 0;
+ MenuItemCollection col = Items;
+ bool foundBranch = true;
+ while (col.Count > 0 && foundBranch) {
+ foundBranch = false;
+ foreach (MenuItem item in col) {
+ if (item.Value == path [n]) {
+ if (++n == path.Length) return item;
+ col = item.ChildItems;
+ foundBranch = true;
+ break;
+ }
+ }
+ }
+ return null;
+ }
+
+ string GetBindingKey (string dataMember, int depth)
+ {
+ return dataMember + " " + depth;
+ }
+
+ internal MenuItemBinding FindBindingForItem (string type, int depth)
+ {
+ if (bindings == null) return null;
+
+ MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
+ if (bin != null) return bin;
+
+ bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
+ if (bin != null) return bin;
+
+ bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
+ if (bin != null) return bin;
+
+ bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
+ return bin;
+ }
+
+ protected internal override void PerformDataBinding ()
+ {
+ base.PerformDataBinding ();
+ HierarchicalDataSourceView data = GetData ("");
+ IHierarchicalEnumerable e = data.Select ();
+ foreach (object obj in e) {
+ IHierarchyData hdata = e.GetHierarchyData (obj);
+ MenuItem item = new MenuItem ();
+ item.Bind (hdata);
+ Items.Add (item);
+ }
+ }
+
+ void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
+ {
+ }
+
+ protected override void TrackViewState()
+ {
+ EnsureDataBound ();
+
+ base.TrackViewState();
+ if (dataBindings != null) {
+ ((IStateManager)dataBindings).TrackViewState ();
+ }
+ if (items != null) {
+ ((IStateManager)items).TrackViewState();;
+ }
+ }
+
+ protected override object SaveViewState()
+ {
+ object[] states = new object [2];
+ states[0] = base.SaveViewState();
+ states[1] = (dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState());
+ states[2] = (items == null ? null : ((IStateManager)items).SaveViewState());
+
+ for (int i = states.Length - 1; i >= 0; i--) {
+ if (states [i] != null)
+ return states;
+ }
+
+ return null;
+ }
+
+ protected override void LoadViewState (object savedState)
+ {
+ if (savedState == null)
+ return;
+
+ object [] states = (object []) savedState;
+ base.LoadViewState (states[0]);
+
+ if (states[1] != null)
+ ((IStateManager)dataBindings).LoadViewState(states[8]);
+ if (states[2] != null)
+ ((IStateManager)Items).LoadViewState(states[9]);
+ }
+
+ protected override void RenderContents (HtmlTextWriter writer)
+ {
+ writer.WriteLine ("This is a menu");
+ }
+
+ }
+}
+
+#endif
namespace System.Web.UI.WebControls
{
- public class MenuEventArgs : CommandEventArgs
+ public sealed class MenuEventArgs : CommandEventArgs
{
private MenuItem item;
private object source;
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItem.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Text;
+using System.ComponentModel;
+using System.Web.UI;
+
+namespace System.Web.UI.WebControls
+{
+ [ParseChildrenAttribute (true, "ChildItems")]
+ public sealed class MenuItem: IStateManager, ICloneable
+ {
+ StateBag ViewState = new StateBag ();
+ MenuItemCollection items;
+ bool marked;
+ Menu menu;
+ MenuItem parent;
+ int index;
+ string path;
+ int depth = -1;
+
+ IHierarchyData hierarchyData;
+ bool gotBinding;
+ MenuItemBinding binding;
+ PropertyDescriptorCollection boundProperties;
+
+ public MenuItem ()
+ {
+ }
+
+ public MenuItem (string text)
+ {
+ Text = text;
+ }
+
+ public MenuItem (string text, string value)
+ {
+ Text = text;
+ Value = value;
+ }
+
+ public MenuItem (string text, string value, string imageUrl)
+ {
+ Text = text;
+ Value = value;
+ ImageUrl = imageUrl;
+ }
+
+ public MenuItem (string text, string value, string imageUrl, string navigateUrl, string target)
+ {
+ Text = text;
+ Value = value;
+ ImageUrl = imageUrl;
+ NavigateUrl = navigateUrl;
+ Target = target;
+ }
+
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [Browsable (false)]
+ public int Depth {
+ get {
+ if (depth != -1) return depth;
+ depth = 0;
+ MenuItem nod = parent;
+ while (nod != null) {
+ depth++;
+ nod = nod.parent;
+ }
+ return depth;
+ }
+ }
+
+ void ResetPathData ()
+ {
+ path = null;
+ depth = -1;
+ gotBinding = false;
+ }
+
+ internal Menu Menu {
+ get { return menu; }
+ set {
+ if (SelectedFlag) {
+ if (value != null)
+ value.SetSelectedItem (this);
+ else if (menu != null)
+ menu.SetSelectedItem (null);
+ }
+ menu = value;
+ if (items != null)
+ items.SetMenu (menu);
+ ResetPathData ();
+ }
+ }
+
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [DefaultValue (false)]
+ [Browsable (false)]
+ public bool DataBound {
+ get { return hierarchyData != null; }
+ }
+
+ [DefaultValue (null)]
+ [Browsable (false)]
+ public object DataItem {
+ get {
+ if (hierarchyData == null) throw new InvalidOperationException ("MenuItem is not data bound.");
+ return hierarchyData.Item;
+ }
+ }
+
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [DefaultValue ("")]
+ [Browsable (false)]
+ public string DataPath {
+ get {
+ if (hierarchyData == null) throw new InvalidOperationException ("MenuItem is not data bound.");
+ return hierarchyData.Path;
+ }
+ }
+
+ [MergableProperty (false)]
+ [Browsable (false)]
+ [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
+ public MenuItemCollection ChildItems {
+ get {
+ if (items == null) {
+ if (DataBound)
+ FillBoundChildren ();
+ else
+ items = new MenuItemCollection (this);
+
+ if (((IStateManager)this).IsTrackingViewState)
+ ((IStateManager)items).TrackViewState();
+ }
+ return items;
+ }
+ }
+
+ [DefaultValue ("")]
+ [UrlProperty]
+ [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public string ImageUrl {
+ get {
+ object o = ViewState ["ImageUrl"];
+ if (o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ if (bin.ImageUrlField != "")
+ return (string) GetBoundPropertyValue (bin.ImageUrlField);
+ return bin.ImageUrl;
+ }
+ }
+ return "";
+ }
+ set {
+ ViewState ["ImageUrl"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [UrlProperty]
+ [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public string NavigateUrl {
+ get {
+ object o = ViewState ["NavigateUrl"];
+ if (o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ if (bin.NavigateUrlField != "")
+ return (string) GetBoundPropertyValue (bin.NavigateUrlField);
+ return bin.NavigateUrl;
+ }
+ }
+ return "";
+ }
+ set {
+ ViewState ["NavigateUrl"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ public string Target {
+ get {
+ object o = ViewState ["Target"];
+ if(o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ if (bin.TargetField != "")
+ return (string) GetBoundPropertyValue (bin.TargetField);
+ return bin.Target;
+ }
+ }
+ return "";
+ }
+ set {
+ ViewState ["Target"] = value;
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ public string Text {
+ get {
+ object o = ViewState ["Text"];
+ if (o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ string text;
+ if (bin.TextField != "")
+ text = (string) GetBoundPropertyValue (bin.TextField);
+ else if (bin.Text != "")
+ text = bin.Text;
+ else
+ text = hierarchyData.ToString ();
+
+ if (bin.FormatString.Length != 0)
+ text = string.Format (bin.FormatString, text);
+ return text;
+ }
+ return hierarchyData.ToString ();
+ }
+ return "";
+ }
+ set {
+ ViewState ["Text"] = value;
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ public string ToolTip {
+ get {
+ object o = ViewState ["ToolTip"];
+ if(o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ if (bin.ToolTipField != "")
+ return (string) GetBoundPropertyValue (bin.ToolTipField);
+ return bin.ToolTip;
+ }
+ }
+ return "";
+ }
+ set {
+ ViewState ["ToolTip"] = value;
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ public string Value {
+ get {
+ object o = ViewState ["Value"];
+ if(o != null) return (string)o;
+ if (DataBound) {
+ MenuItemBinding bin = GetBinding ();
+ if (bin != null) {
+ if (bin.ValueField != "")
+ return (string) GetBoundPropertyValue (bin.ValueField);
+ if (bin.Value != "")
+ return bin.Value;
+ }
+ return hierarchyData.ToString ();
+ }
+ return "";
+ }
+ set {
+ ViewState ["Value"] = value;
+ }
+ }
+
+ [DefaultValue (false)]
+ public bool Selected {
+ get {
+ return SelectedFlag;
+ }
+ set {
+ if (menu != null) {
+ if (!value && menu.SelectedItem == this)
+ menu.SetSelectedItem (null);
+ else if (value)
+ menu.SetSelectedItem (this);
+ }
+ else
+ SelectedFlag = value;
+ }
+ }
+
+ internal bool SelectedFlag {
+ get {
+ object o = ViewState ["Selected"];
+ if(o != null) return (bool)o;
+ return false;
+ }
+ set {
+ ViewState ["Selected"] = value;
+ }
+ }
+
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [Browsable (false)]
+ public MenuItem Parent {
+ get { return parent; }
+ }
+
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ [Browsable (false)]
+ public string ValuePath {
+ get {
+ if (menu == null) return Value;
+
+ StringBuilder sb = new StringBuilder (Value);
+ MenuItem item = parent;
+ while (item != null) {
+ sb.Insert (0, menu.PathSeparator);
+ sb.Insert (0, item.Value);
+ item = item.Parent;
+ }
+ return sb.ToString ();
+ }
+ }
+
+ internal int Index {
+ get { return index; }
+ set { index = value; ResetPathData (); }
+ }
+
+ internal void SetParent (MenuItem item) {
+ parent = item;
+ ResetPathData ();
+ }
+
+ internal string Path {
+ get {
+ if (path != null) return path;
+ StringBuilder sb = new StringBuilder (index.ToString());
+ MenuItem item = parent;
+ while (item != null) {
+ sb.Insert (0, '_');
+ sb.Insert (0, item.Index.ToString ());
+ item = item.Parent;
+ }
+ path = sb.ToString ();
+ return path;
+ }
+ }
+
+ internal bool HasChildData {
+ get { return items != null; }
+ }
+
+ void IStateManager.LoadViewState (object savedState)
+ {
+ if (savedState == null)
+ return;
+
+ object[] states = (object[]) savedState;
+ ViewState.LoadViewState (states [0]);
+
+ if (menu != null && SelectedFlag)
+ menu.SetSelectedItem (this);
+
+ if (states [1] != null)
+ ((IStateManager)ChildItems).LoadViewState (states [1]);
+ }
+
+ object IStateManager.SaveViewState ()
+ {
+ object[] states = new object[2];
+ states[0] = ViewState.SaveViewState();
+ states[1] = (items == null ? null : ((IStateManager)items).SaveViewState());
+
+ for (int i = 0; i < states.Length; i++) {
+ if (states [i] != null)
+ return states;
+ }
+ return null;
+ }
+
+ void IStateManager.TrackViewState ()
+ {
+ if (marked) return;
+ marked = true;
+ ViewState.TrackViewState();
+
+ if (items != null)
+ ((IStateManager)items).TrackViewState ();
+ }
+
+ bool IStateManager.IsTrackingViewState
+ {
+ get { return marked; }
+ }
+
+ internal void SetDirty ()
+ {
+ ViewState.SetDirty ();
+ }
+
+ object ICloneable.Clone ()
+ {
+ MenuItem nod = new MenuItem ();
+ foreach (DictionaryEntry e in ViewState)
+ nod.ViewState [(string)e.Key] = e.Value;
+
+ foreach (ICloneable c in ChildItems)
+ nod.ChildItems.Add ((MenuItem)c.Clone ());
+
+ return nod;
+ }
+
+ internal void Bind (IHierarchyData hierarchyData)
+ {
+ this.hierarchyData = hierarchyData;
+ }
+
+ MenuItemBinding GetBinding ()
+ {
+ if (menu == null) return null;
+ if (gotBinding) return binding;
+ binding = menu.FindBindingForItem (hierarchyData.Type, Depth);
+ gotBinding = true;
+ return binding;
+ }
+
+ object GetBoundPropertyValue (string name)
+ {
+ if (boundProperties == null) {
+ ICustomTypeDescriptor desc = hierarchyData as ICustomTypeDescriptor;
+ if (desc == null)
+ throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
+ boundProperties = desc.GetProperties ();
+ }
+
+ PropertyDescriptor prop = boundProperties.Find (name, true);
+ if (prop == null)
+ throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
+ return prop.GetValue (hierarchyData);
+ }
+
+ void FillBoundChildren ()
+ {
+ items = new MenuItemCollection (this);
+ if (!hierarchyData.HasChildren) return;
+
+ IHierarchicalEnumerable e = hierarchyData.GetChildren ();
+ foreach (object obj in e) {
+ IHierarchyData hdata = e.GetHierarchyData (obj);
+ MenuItem item = new MenuItem ();
+ item.Bind (hdata);
+ items.Add (item);
+ }
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItemBinding.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Web.UI;
+using System.ComponentModel;
+
+namespace System.Web.UI.WebControls
+{
+ [DefaultProperty ("TextField")]
+ public sealed class MenuItemBinding: IStateManager, ICloneable, IDataSourceViewSchemaAccessor
+ {
+ StateBag ViewState = new StateBag ();
+
+ [DefaultValue ("")]
+ public string DataMember {
+ get {
+ object o = ViewState ["DataMember"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["DataMember"] = value;
+ }
+ }
+
+ [DefaultValue (-1)]
+ public int Depth {
+ get {
+ object o = ViewState ["Depth"];
+ if (o != null) return (int) o;
+ return -1;
+ }
+ set {
+ ViewState ["Depth"] = value;
+ }
+ }
+
+ [DefaultValue (true)]
+ public bool Enabled {
+ get {
+ object o = ViewState ["Enabled"];
+ if (o != null) return (bool) o;
+ return true;
+ }
+ set {
+ ViewState ["Enabled"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string EnabledField {
+ get {
+ object o = ViewState ["EnabledField"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["EnabledField"] = value;
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ public string FormatString {
+ get {
+ object o = ViewState ["FormatString"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["FormatString"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [UrlProperty]
+ [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public string ImageUrl {
+ get {
+ object o = ViewState ["ImageUrl"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["ImageUrl"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string ImageUrlField {
+ get {
+ object o = ViewState ["ImageUrlField"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["ImageUrlField"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [UrlProperty]
+ [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+ public string NavigateUrl {
+ get {
+ object o = ViewState ["NavigateUrl"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["NavigateUrl"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string NavigateUrlField {
+ get {
+ object o = ViewState ["NavigateUrlField"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["NavigateUrlField"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ public string Target {
+ get {
+ object o = ViewState ["Target"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["Target"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string TargetField {
+ get {
+ object o = ViewState ["TargetField"];
+ if (o != null) return (string) o;
+ return "";
+ }
+ set {
+ ViewState ["TargetField"] = value;
+ }
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ [WebSysDescription ("The display text of the menu item.")]
+ public string Text {
+ get {
+ object o = ViewState ["Text"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["Text"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string TextField {
+ get {
+ object o = ViewState ["TextField"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["TextField"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [Localizable (true)]
+ public string ToolTip {
+ get {
+ object o = ViewState ["ToolTip"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["ToolTip"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string ToolTipField {
+ get {
+ object o = ViewState ["ToolTipField"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["ToolTipField"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [Localizable (true)]
+ public string Value {
+ get {
+ object o = ViewState ["Value"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["Value"] = value;
+ }
+ }
+
+ [DefaultValue ("")]
+ [TypeConverter ("System.Web.UI.Design.DataSourceViewSchemaConverter, " + Consts.AssemblySystem_Design)]
+ public string ValueField {
+ get {
+ object o = ViewState ["ValueField"];
+ if(o != null) return (string)o;
+ return "";
+ }
+ set {
+ ViewState ["ValueField"] = value;
+ }
+ }
+
+ void IStateManager.LoadViewState (object savedState)
+ {
+ ViewState.LoadViewState (savedState);
+ }
+
+ object IStateManager.SaveViewState ()
+ {
+ return ViewState.SaveViewState();
+ }
+
+ void IStateManager.TrackViewState ()
+ {
+ ViewState.TrackViewState ();
+ }
+
+ bool IStateManager.IsTrackingViewState {
+ get { return ViewState.IsTrackingViewState; }
+ }
+
+ [MonoTODO]
+ object IDataSourceViewSchemaAccessor.DataSourceViewSchema {
+ get { throw new NotImplementedException (); }
+ set { throw new NotImplementedException (); }
+ }
+
+ object ICloneable.Clone ()
+ {
+ MenuItemBinding bin = new MenuItemBinding ();
+ foreach (DictionaryEntry e in ViewState)
+ bin.ViewState [(string)e.Key] = e.Value;
+ return bin;
+ }
+
+ internal void SetDirty ()
+ {
+ foreach (string key in ViewState.Keys)
+ ViewState.SetItemDirty (key, true);
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItemBindingCollection.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Web.UI;
+
+namespace System.Web.UI.WebControls
+{
+ public sealed class MenuItemBindingCollection: StateManagedCollection
+ {
+ static Type[] types = new Type[] { typeof (MenuItemBinding) };
+
+ internal MenuItemBindingCollection ()
+ {
+ }
+
+ public int Add (MenuItemBinding binding)
+ {
+ return ((IList)this).Add (binding);
+ }
+
+ public bool Contains (MenuItemBinding binding)
+ {
+ return ((IList)this).Contains (binding);
+ }
+
+ public void CopyTo (MenuItemBinding[] array, int index)
+ {
+ ((IList)this).CopyTo (array, index);
+ }
+
+ protected override object CreateKnownType (int index)
+ {
+ return new MenuItemBinding ();
+ }
+
+ protected override Type[] GetKnownTypes ()
+ {
+ return types;
+ }
+
+ public int IndexOf (MenuItemBinding binding)
+ {
+ return ((IList)this).IndexOf (binding);
+ }
+
+ public void Insert (int index, MenuItemBinding binding)
+ {
+ ((IList)this).Insert (index, binding);
+ }
+
+ public void Remove (MenuItemBinding binding)
+ {
+ ((IList)this).Remove (binding);
+ }
+
+ public void RemoveAt (int index)
+ {
+ ((IList)this).RemoveAt (index);
+ }
+
+ public MenuItemBinding this [int i] {
+ get { return (MenuItemBinding) ((IList)this) [i]; }
+ set { ((IList)this) [i] = value; }
+ }
+
+ protected override void SetDirtyObject (object o)
+ {
+ ((MenuItemBinding)o).SetDirty ();
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItemCollection.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Web.UI;
+using System.Collections;
+
+namespace System.Web.UI.WebControls
+{
+ public sealed class MenuItemCollection: ICollection, IEnumerable, IStateManager
+ {
+ MenuItem[] originalItems;
+ ArrayList items = new ArrayList ();
+ Menu menu;
+ MenuItem parent;
+ bool marked;
+ bool dirty;
+
+ public MenuItemCollection ()
+ {
+ }
+
+ public MenuItemCollection (MenuItem owner)
+ {
+ this.parent = owner;
+ this.menu = owner.Menu;
+ }
+
+ internal MenuItemCollection (Menu menu)
+ {
+ this.menu = menu;
+ }
+
+ internal void SetMenu (Menu menu)
+ {
+ this.menu = menu;
+ foreach (MenuItem item in items)
+ item.Menu = menu;
+ }
+
+ public MenuItem this [int i] {
+ get { return (MenuItem) items [i]; }
+ }
+
+ public void Add (MenuItem child)
+ {
+ child.Index = items.Add (child);
+ child.Menu = menu;
+ child.SetParent (parent);
+ if (marked) {
+ ((IStateManager)child).TrackViewState ();
+ child.SetDirty ();
+ dirty = true;
+ }
+ }
+
+ public void AddAt (int index, MenuItem child)
+ {
+ items.Insert (index, child);
+ child.Index = index;
+ child.Menu = menu;
+ child.SetParent (parent);
+ for (int n=index+1; n<items.Count; n++)
+ ((MenuItem)items[n]).Index = n;
+ if (marked) {
+ ((IStateManager)child).TrackViewState ();
+ child.SetDirty ();
+ dirty = true;
+ }
+ }
+
+ public void Clear ()
+ {
+ if (menu != null || parent != null) {
+ foreach (MenuItem nod in items) {
+ nod.Menu = null;
+ nod.SetParent (null);
+ }
+ }
+ items.Clear ();
+ dirty = true;
+ }
+
+ public bool Contains (MenuItem child)
+ {
+ return items.Contains (child);
+ }
+
+ public void CopyTo (Array itemArray, int index)
+ {
+ items.CopyTo (itemArray, index);
+ }
+
+ public void CopyTo (MenuItem[] itemArray, int index)
+ {
+ items.CopyTo (itemArray, index);
+ }
+
+ public IEnumerator GetEnumerator ()
+ {
+ return items.GetEnumerator ();
+ }
+
+ public int IndexOf (MenuItem item)
+ {
+ return items.IndexOf (item);
+ }
+
+ public void Remove (MenuItem item)
+ {
+ int i = IndexOf (item);
+ if (i == -1) return;
+ items.RemoveAt (i);
+ if (menu != null)
+ item.Menu = null;
+ dirty = true;
+ }
+
+ public void RemoveAt (int index)
+ {
+ MenuItem item = (MenuItem) items [index];
+ items.RemoveAt (index);
+ if (menu != null)
+ item.Menu = null;
+ dirty = true;
+ }
+
+ public int Count {
+ get { return items.Count; }
+ }
+
+ public bool IsSynchronized {
+ get { return false; }
+ }
+
+ public object SyncRoot {
+ get { return items; }
+ }
+
+ void System.Collections.ICollection.CopyTo (Array array, int index)
+ {
+ items.CopyTo (array, index);
+ }
+
+ void IStateManager.LoadViewState (object state)
+ {
+ if (state == null) return;
+ object[] its = (object[]) state;
+
+ dirty = (bool)its [0];
+
+ if (dirty)
+ items.Clear ();
+
+ for (int n=1; n<its.Length; n++) {
+ Pair pair = (Pair) its [n];
+ int oi = (int) pair.First;
+ MenuItem item;
+ if (oi != -1) item = originalItems [oi];
+ else item = new MenuItem ();
+ if (dirty) Add (item);
+ ((IStateManager)item).LoadViewState (pair.Second);
+ }
+ }
+
+ object IStateManager.SaveViewState ()
+ {
+ object[] state = null;
+ bool hasData = false;
+
+ if (dirty) {
+ state = new object [items.Count + 1];
+ state [0] = true;
+ for (int n=0; n<items.Count; n++) {
+ MenuItem item = items[n] as MenuItem;
+ int oi = Array.IndexOf (originalItems, item);
+ object ns = ((IStateManager)item).SaveViewState ();
+ if (ns != null) hasData = true;
+ state [n + 1] = new Pair (oi, ns);
+ }
+ } else {
+ ArrayList list = new ArrayList ();
+ for (int n=0; n<items.Count; n++) {
+ MenuItem item = items[n] as MenuItem;
+ object ns = ((IStateManager)item).SaveViewState ();
+ if (ns != null) {
+ hasData = true;
+ list.Add (new Pair (n, ns));
+ }
+ }
+ if (hasData) {
+ list.Insert (0, false);
+ state = list.ToArray ();
+ }
+ }
+
+ if (hasData)
+ return state;
+ else
+ return null;
+ }
+
+ void IStateManager.TrackViewState ()
+ {
+ marked = true;
+ originalItems = new MenuItem [items.Count];
+ for (int n=0; n<items.Count; n++) {
+ originalItems [n] = (MenuItem) items [n];
+ ((IStateManager)originalItems [n]).TrackViewState ();
+ }
+ }
+
+ bool IStateManager.IsTrackingViewState {
+ get { return marked; }
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItemStyle.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Web.UI;
+using System.ComponentModel;
+
+namespace System.Web.UI.WebControls
+{
+ public class MenuItemStyle: Style
+ {
+ private static int HORZ_PADD = (0x01 << 16);
+ private static int SPACING = (0x01 << 17);
+ private static int VERT_PADD = (0x01 << 18);
+
+ [DefaultValue (0)]
+ [NotifyParentProperty (true)]
+ public int HorizontalPadding {
+ get {
+ if(IsSet(HORZ_PADD))
+ return (int)(ViewState["HorizontalPadding"]);
+ return 0;
+ }
+ set {
+ ViewState["HorizontalPadding"] = value;
+ Set(HORZ_PADD);
+ }
+ }
+
+ [DefaultValue (0)]
+ [NotifyParentProperty (true)]
+ public int VerticalPadding {
+ get {
+ if(IsSet(VERT_PADD))
+ return (int)(ViewState["VerticalPadding"]);
+ return 0;
+ }
+ set {
+ ViewState["VerticalPadding"] = value;
+ Set(VERT_PADD);
+ }
+ }
+
+ [DefaultValue (0)]
+ [NotifyParentProperty (true)]
+ public int ItemSpacing {
+ get {
+ if(IsSet(SPACING))
+ return (int)(ViewState["ItemSpacing"]);
+ return 0;
+ }
+ set {
+ ViewState["ItemSpacing"] = value;
+ Set(SPACING);
+ }
+ }
+
+ protected internal override bool IsEmpty {
+ get { return base.IsEmpty; }
+ }
+
+ public override void CopyFrom (Style s)
+ {
+ if (s == null || s.IsEmpty)
+ return;
+
+ base.CopyFrom (s);
+ MenuItemStyle from = s as MenuItemStyle;
+ if (from == null)
+ return;
+
+ if (from.IsSet (HORZ_PADD))
+ HorizontalPadding = from.HorizontalPadding;
+
+ if (from.IsSet (SPACING))
+ ItemSpacing = from.ItemSpacing;
+
+ if (from.IsSet (VERT_PADD))
+ VerticalPadding = from.VerticalPadding;
+ }
+
+ public override void MergeWith(Style s)
+ {
+ if(s != null && !s.IsEmpty)
+ {
+ if (IsEmpty) {
+ CopyFrom (s);
+ return;
+ }
+ base.MergeWith(s);
+
+ MenuItemStyle with = s as MenuItemStyle;
+ if (with == null) return;
+
+ if (with.IsSet(HORZ_PADD) && !IsSet(HORZ_PADD)) {
+ HorizontalPadding = with.HorizontalPadding;
+ }
+ if (with.IsSet(SPACING) && !IsSet(SPACING)) {
+ ItemSpacing = with.ItemSpacing;
+ }
+ if (with.IsSet(VERT_PADD) && !IsSet(VERT_PADD)) {
+ VerticalPadding = with.VerticalPadding;
+ }
+ }
+ }
+
+ public override void Reset()
+ {
+ if(IsSet(HORZ_PADD))
+ ViewState.Remove("HorizontalPadding");
+ if(IsSet(SPACING))
+ ViewState.Remove("ItemSpacing");
+ if(IsSet(VERT_PADD))
+ ViewState.Remove("VerticalPadding");
+ base.Reset();
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.MenuItemStyleCollection.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Web.UI;
+
+namespace System.Web.UI.WebControls
+{
+ public sealed class MenuItemStyleCollection: StateManagedCollection
+ {
+ static Type[] types = new Type[] { typeof (MenuItemStyle) };
+
+ internal MenuItemStyleCollection ()
+ {
+ }
+
+ public int Add (MenuItemStyle style)
+ {
+ return ((IList)this).Add (style);
+ }
+
+ public bool Contains (MenuItemStyle style)
+ {
+ return ((IList)this).Contains (style);
+ }
+
+ public void CopyTo (MenuItemStyle[] array, int index)
+ {
+ ((IList)this).CopyTo (array, index);
+ }
+
+ protected override object CreateKnownType (int index)
+ {
+ return new MenuItemStyle ();
+ }
+
+ protected override Type[] GetKnownTypes ()
+ {
+ return types;
+ }
+
+ public int IndexOf (MenuItemStyle style)
+ {
+ return ((IList)this).IndexOf (style);
+ }
+
+ public void Insert (int index, MenuItemStyle style)
+ {
+ ((IList)this).Insert (index, style);
+ }
+
+ public void Remove (MenuItemStyle style)
+ {
+ ((IList)this).Remove (style);
+ }
+
+ public void RemoveAt (int index)
+ {
+ ((IList)this).RemoveAt (index);
+ }
+
+ public MenuItemStyle this [int i] {
+ get { return (MenuItemStyle) ((IList)this) [i]; }
+ set { ((IList)this) [i] = value; }
+ }
+
+ protected override void SetDirtyObject (object o)
+ {
+ ((MenuItemStyle)o).SetDirty ();
+ }
+ }
+}
+
+#endif
bool foundBranch = true;
while (col.Count > 0 && foundBranch) {
foundBranch = false;
- foreach (TreeNode node in Nodes) {
+ foreach (TreeNode node in col) {
if (node.Value == path [n]) {
if (++n == path.Length) return node;
col = node.ChildNodes;
((IStateManager)Nodes).LoadViewState(states[9]);
}
- [MonoTODO]
void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
{
string[] args = eventArgument.Split ('|');
System.Web.UI.WebControls/LogoutAction.cs
System.Web.UI.WebControls/MailMessageEventArgs.cs
System.Web.UI.WebControls/MailMessageEventHandler.cs
+System.Web.UI.WebControls/Menu.cs
+System.Web.UI.WebControls/MenuEventArgs.cs
+System.Web.UI.WebControls/MenuEventHandler.cs
+System.Web.UI.WebControls/MenuItem.cs
+System.Web.UI.WebControls/MenuItemBinding.cs
+System.Web.UI.WebControls/MenuItemBindingCollection.cs
+System.Web.UI.WebControls/MenuItemCollection.cs
+System.Web.UI.WebControls/MenuItemStyle.cs
+System.Web.UI.WebControls/MenuItemStyleCollection.cs
System.Web.UI.WebControls/MonthChangedEventArgs.cs
System.Web.UI.WebControls/MonthChangedEventHandler.cs
System.Web.UI.WebControls/ObjectDataSourceDisposingEventArgs.cs
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * System.Xml.dll.sources : added DTMXPathDocument2.cs,
+ DTMXPathDocumentBuilder2.cs, DTMXPathDocumentWriter2.cs,
+ DTMXPathDocumentWriter2.cs and DTMXPathNode2.cs.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile: Remove support for being in bootstrap build.
+
2004-12-01 Atsushi Enomoto <atsushi@ximian.com>
* System.Xml.dll.sources: removed old IXPathChangeNavigable.cs,
SCARY_LIB=/lib:$(prefix)/lib /noconfig
endif
-ifdef USE_BOOT_COMPILE
-LIBRARY_COMPILE = $(BOOT_COMPILE)
-endif
-
LIB_MCS_FLAGS = $(SCARY_LIB) /unsafe /r:$(corlib) /r:System.dll /nowarn:0162 /nowarn:0618 /nowarn:0612
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DTMXPathNavigator.cs : added more constant fields to utility class.
+
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DTMXPathDocument2.cs,
+ DTMXPathNavigator2.cs,
+ DTMXPathDocumentBuilder2.cs,
+ DTMXPathDocumentWriter2.cs,
+ DTMXPathNode2.cs : added new implementation that uses string pool
+ and eliminates string field inside struct (IF we use struct).
+
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DTMXPathDocumentWriter.cs : Fix for DTM_CLASS switch that does not
+ allow unadjusted arrays.
+
2004-11-30 Atsushi Enomoto <atsushi@ximian.com>
* DTMXPathDocumentWriter.cs,
--- /dev/null
+//
+// Mono.Xml.XPath.DTMXPathDocument2
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C) 2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+ class DTMXPathDocument2 : IXPathNavigable
+ {
+
+#region ctor.
+
+ public DTMXPathDocument2 (XmlNameTable nameTable,
+ DTMXPathLinkedNode2 [] nodes,
+ DTMXPathAttributeNode2 [] attributes,
+ DTMXPathNamespaceNode2 [] namespaces,
+ string [] atomicStringPool,
+ string [] nonAtomicStringPool,
+ Hashtable idTable)
+ {
+ this.nameTable = nameTable;
+ this.nodes = nodes;
+ this.attributes = attributes;
+ this.namespaces = namespaces;
+ this.atomicStringPool = atomicStringPool;
+ this.nonAtomicStringPool = nonAtomicStringPool;
+ this.idTable = idTable;
+
+ root = new DTMXPathNavigator2 (this,
+ nameTable,
+ nodes,
+ attributes,
+ namespaces,
+ atomicStringPool,
+ nonAtomicStringPool,
+ idTable);
+ }
+
+#endregion
+
+
+#region Methods
+ public XPathNavigator CreateNavigator ()
+ {
+ return root.Clone ();
+ }
+
+#endregion
+
+ readonly XmlNameTable nameTable;
+
+ // Root XPathNavigator.
+ readonly DTMXPathNavigator2 root;
+
+#region Immutable tree fields
+
+ readonly DTMXPathLinkedNode2 [] nodes;
+ readonly DTMXPathAttributeNode2 [] attributes;
+ readonly DTMXPathNamespaceNode2 [] namespaces;
+
+ // String pool
+ readonly string [] atomicStringPool;
+ readonly string [] nonAtomicStringPool;
+
+ // idTable [string value] -> int nodeId
+ readonly Hashtable idTable;
+
+#endregion
+
+ }
+}
+
--- /dev/null
+//
+// Mono.Xml.XPath.DTMXPathDocumentBuilder2
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C)2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+ class DTMXPathDocumentBuilder2
+ {
+ public DTMXPathDocumentBuilder2 (string url)
+ : this (url, XmlSpace.None, 200)
+ {
+ }
+
+ public DTMXPathDocumentBuilder2 (string url, XmlSpace space)
+ : this (url, space, 200)
+ {
+ }
+
+ public DTMXPathDocumentBuilder2 (string url, XmlSpace space, int defaultCapacity)
+ {
+ XmlReader r = null;
+ try {
+ r = new XmlTextReader (url);
+ Init (r, space, defaultCapacity);
+ } finally {
+ if (r != null)
+ r.Close ();
+ }
+ }
+
+ public DTMXPathDocumentBuilder2 (XmlReader reader)
+ : this (reader, XmlSpace.None, 200)
+ {
+ }
+
+ public DTMXPathDocumentBuilder2 (XmlReader reader, XmlSpace space)
+ : this (reader, space, 200)
+ {
+ }
+
+ public DTMXPathDocumentBuilder2 (XmlReader reader, XmlSpace space, int defaultCapacity)
+ {
+ Init (reader, space, defaultCapacity);
+ }
+
+ private void Init (XmlReader reader, XmlSpace space, int defaultCapacity)
+ {
+ this.xmlReader = reader;
+ this.validatingReader = reader as XmlValidatingReader;
+ lineInfo = reader as IXmlLineInfo;
+ this.xmlSpace = space;
+ this.nameTable = reader.NameTable;
+ nodeCapacity = defaultCapacity;
+ attributeCapacity = nodeCapacity;
+ nsCapacity = 10;
+ idTable = new Hashtable ();
+
+ nodes = new DTMXPathLinkedNode2 [nodeCapacity];
+ attributes = new DTMXPathAttributeNode2 [attributeCapacity];
+ namespaces = new DTMXPathNamespaceNode2 [nsCapacity];
+ atomicStringPool = new string [20];
+ nonAtomicStringPool = new string [20];
+
+ Compile ();
+ }
+
+ XmlReader xmlReader;
+ XmlValidatingReader validatingReader;
+ XmlSpace xmlSpace;
+ XmlNameTable nameTable;
+ IXmlLineInfo lineInfo;
+ int nodeCapacity;
+ int attributeCapacity;
+ int nsCapacity;
+
+ // Linked Node
+ DTMXPathLinkedNode2 [] nodes;
+
+ // Attribute
+ DTMXPathAttributeNode2 [] attributes;
+
+ // NamespaceNode
+ DTMXPathNamespaceNode2 [] namespaces;
+
+ // String pool
+ string [] atomicStringPool;
+ string [] nonAtomicStringPool;
+
+ // idTable [string value] -> int nodeId
+ Hashtable idTable;
+
+ int nodeIndex;
+ int attributeIndex;
+ int nsIndex;
+ int parentForFirstChild;
+
+ // for attribute processing; should be reset per each element.
+ int firstAttributeIndex;
+ int lastNsIndexInCurrent;
+ int attrIndexAtStart;
+ int nsIndexAtStart;
+
+ int prevSibling;
+ int lastNsInScope;
+ bool skipRead = false;
+
+ public DTMXPathDocument2 CreateDocument ()
+ {
+ return new DTMXPathDocument2 (nameTable,
+ nodes,
+ attributes,
+ namespaces,
+ atomicStringPool,
+ nonAtomicStringPool,
+ idTable
+ );
+ }
+
+ public void Compile ()
+ {
+ // string pool index 0 to 3 are fixed.
+ atomicStringPool [0] = nonAtomicStringPool [0] = "";
+ atomicStringPool [1] = nonAtomicStringPool [1] = null;
+ atomicStringPool [2] = nonAtomicStringPool [2] = XmlNamespaces.XML;
+ atomicStringPool [3] = nonAtomicStringPool [3] = XmlNamespaces.XMLNS;
+
+ // index 0 is dummy. No node (including Root) is assigned to this index
+ // So that we can easily compare index != 0 instead of index < 0.
+ // (Difference between jnz or jbe in 80x86.)
+ AddNode (0, 0, 0, 0, XPathNodeType.All, 0, false, 0, 0, 0, 0, 0, 0, 0, 0);
+ nodeIndex++;
+ AddAttribute (0, 0, 0, 0, 0, 0, 0);
+ AddNsNode (0, 0, 0, 0);
+ nsIndex++;
+ AddNsNode (1, AtomicIndex ("xml"), AtomicIndex (XmlNamespaces.XML), 0);
+
+ // add root.
+ AddNode (0, 0, 0, -1, XPathNodeType.Root, AtomicIndex (xmlReader.BaseURI), false, 0, 0, 0, 0, 0, 1, 0, 0);
+
+ this.nodeIndex = 1;
+ this.lastNsInScope = 1;
+ this.parentForFirstChild = nodeIndex;
+
+ while (!xmlReader.EOF)
+ Read ();
+ SetNodeArrayLength (nodeIndex + 1);
+ SetAttributeArrayLength (attributeIndex + 1);
+ SetNsArrayLength (nsIndex + 1);
+
+ int i;
+ for (i = 3; i < atomicStringPool.Length; i++) {
+ if (atomicStringPool [i] == null)
+ break;
+ }
+ string [] newArr = new string [i];
+ Array.Copy (atomicStringPool, newArr, i);
+ atomicStringPool = newArr;
+
+ for (i = 3; i < nonAtomicStringPool.Length; i++) {
+ if (nonAtomicStringPool [i] == null)
+ break;
+ }
+ newArr = new string [i];
+ Array.Copy (nonAtomicStringPool, newArr, i);
+ nonAtomicStringPool = newArr;
+
+ xmlReader = null; // It is no more required.
+ }
+
+ public void Read ()
+ {
+ if (!skipRead)
+ if (!xmlReader.Read ())
+ return;
+ skipRead = false;
+ int parent = nodeIndex;
+
+ if (nodes [nodeIndex].Depth >= xmlReader.Depth) {
+ // if not, then current node is parent.
+ while (xmlReader.Depth <= nodes [parent].Depth)
+ parent = nodes [parent].Parent;
+ }
+
+ prevSibling = nodeIndex;
+ switch (xmlReader.NodeType) {
+ case XmlNodeType.Element:
+ case XmlNodeType.CDATA:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Comment:
+ case XmlNodeType.Text:
+ case XmlNodeType.ProcessingInstruction:
+ if (parentForFirstChild >= 0)
+ prevSibling = 0;
+ else
+ while (nodes [prevSibling].Depth != xmlReader.Depth)
+ prevSibling = nodes [prevSibling].Parent;
+
+ nodeIndex++;
+
+ if (prevSibling != 0)
+ nodes [prevSibling].NextSibling = nodeIndex;
+ if (parentForFirstChild >= 0)
+ nodes [parent].FirstChild = nodeIndex;
+ break;
+ case XmlNodeType.Whitespace:
+ if (xmlSpace == XmlSpace.Preserve)
+ goto case XmlNodeType.Text;
+ else
+ goto default;
+ case XmlNodeType.EndElement:
+ parentForFirstChild = -1;
+ return;
+ default:
+ // No operations. Doctype, EntityReference,
+ return;
+ }
+
+ parentForFirstChild = -1; // Might be changed in ProcessElement().
+
+ string value = null;
+ XPathNodeType nodeType = xmlReader.NodeType == XmlNodeType.Whitespace ?
+ XPathNodeType.Whitespace : XPathNodeType.Text;
+
+ switch (xmlReader.NodeType) {
+ case XmlNodeType.Element:
+ ProcessElement (parent, prevSibling);
+ break;
+ case XmlNodeType.CDATA:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Text:
+ case XmlNodeType.Whitespace:
+ if (value == null)
+ skipRead = true;
+ AddNode (parent,
+ 0,
+ prevSibling,
+ xmlReader.Depth,
+ nodeType,
+ AtomicIndex (xmlReader.BaseURI),
+ xmlReader.IsEmptyElement,
+ AtomicIndex (xmlReader.LocalName), // for PI
+ AtomicIndex (xmlReader.NamespaceURI), // for PI
+ AtomicIndex (xmlReader.Prefix),
+ value == null ? 0 : NonAtomicIndex (value),
+ AtomicIndex (xmlReader.XmlLang),
+ nsIndex,
+ lineInfo != null ? lineInfo.LineNumber : 0,
+ lineInfo != null ? lineInfo.LinePosition : 0);
+ // this code is tricky, but after ReadString() invokation,
+ // xmlReader is moved to next node!!
+ if (value == null)
+ nodes [nodeIndex].Value = NonAtomicIndex (xmlReader.ReadString ());
+ break;
+ case XmlNodeType.Comment:
+ value = xmlReader.Value;
+ nodeType = XPathNodeType.Comment;
+ goto case XmlNodeType.Text;
+ case XmlNodeType.ProcessingInstruction:
+ value = xmlReader.Value;
+ nodeType = XPathNodeType.ProcessingInstruction;
+ goto case XmlNodeType.Text;
+ }
+ }
+
+ private void ProcessElement (int parent, int previousSibling)
+ {
+ WriteStartElement (parent, previousSibling);
+
+ // process namespaces and attributes.
+ if (xmlReader.MoveToFirstAttribute ()) {
+ do {
+ string prefix = xmlReader.Prefix;
+ string ns = xmlReader.NamespaceURI;
+ if (ns == XmlNamespaces.XMLNS)
+ ProcessNamespace ((prefix == null || prefix == String.Empty) ? "" : xmlReader.LocalName, xmlReader.Value);
+ else
+ ProcessAttribute (prefix, xmlReader.LocalName, ns, xmlReader.Value);
+
+ } while (xmlReader.MoveToNextAttribute ());
+ xmlReader.MoveToElement ();
+ }
+
+ CloseStartElement ();
+ }
+
+ private void PrepareStartElement (int previousSibling)
+ {
+ firstAttributeIndex = 0;
+ lastNsIndexInCurrent = 0;
+ attrIndexAtStart = attributeIndex;
+ nsIndexAtStart = nsIndex;
+
+ while (namespaces [lastNsInScope].DeclaredElement == previousSibling) {
+ lastNsInScope = namespaces [lastNsInScope].NextNamespace;
+ }
+ }
+
+ private void WriteStartElement (int parent, int previousSibling)
+ {
+ PrepareStartElement (previousSibling);
+
+ AddNode (parent,
+ 0, // dummy:firstAttribute
+ previousSibling,
+ xmlReader.Depth,
+ XPathNodeType.Element,
+ AtomicIndex (xmlReader.BaseURI),
+ xmlReader.IsEmptyElement,
+ AtomicIndex (xmlReader.LocalName),
+ AtomicIndex (xmlReader.NamespaceURI),
+ AtomicIndex (xmlReader.Prefix),
+ 0, // Element has no internal value.
+ AtomicIndex (xmlReader.XmlLang),
+ lastNsInScope,
+ lineInfo != null ? lineInfo.LineNumber : 0,
+ lineInfo != null ? lineInfo.LinePosition : 0);
+
+ }
+
+ private void CloseStartElement ()
+ {
+ if (attrIndexAtStart != attributeIndex)
+ nodes [nodeIndex].FirstAttribute = attrIndexAtStart + 1;
+ if (nsIndexAtStart != nsIndex) {
+ nodes [nodeIndex].FirstNamespace = nsIndex;
+ lastNsInScope = nsIndex;
+ }
+
+ if (!nodes [nodeIndex].IsEmptyElement)
+ parentForFirstChild = nodeIndex;
+ }
+
+ private void ProcessNamespace (string prefix, string ns)
+ {
+ nsIndex++;
+
+ int nextTmp = lastNsIndexInCurrent == 0 ? nodes [nodeIndex].FirstNamespace : lastNsIndexInCurrent;
+
+ this.AddNsNode (nodeIndex,
+ AtomicIndex (prefix),
+ AtomicIndex (ns),
+ nextTmp);
+ lastNsIndexInCurrent = nsIndex;
+ }
+
+ private void ProcessAttribute (string prefix, string localName, string ns, string value)
+ {
+ attributeIndex ++;
+
+ this.AddAttribute (nodeIndex,
+ AtomicIndex (localName),
+ AtomicIndex (ns),
+ prefix != null ? AtomicIndex (prefix) : 0,
+ NonAtomicIndex (value),
+ lineInfo != null ? lineInfo.LineNumber : 0,
+ lineInfo != null ? lineInfo.LinePosition : 0);
+ if (firstAttributeIndex == 0)
+ firstAttributeIndex = attributeIndex;
+ else
+ attributes [attributeIndex - 1].NextAttribute = attributeIndex;
+
+ // Identity infoset
+ if (validatingReader != null) {
+ XmlSchemaDatatype dt = validatingReader.SchemaType as XmlSchemaDatatype;
+ if (dt == null) {
+ XmlSchemaType xsType = validatingReader.SchemaType as XmlSchemaType;
+ if (xsType != null)
+ dt = xsType.Datatype;
+ }
+ if (dt != null && dt.TokenizedType == XmlTokenizedType.ID)
+ idTable.Add (value, nodeIndex);
+ }
+ }
+
+ private int AtomicIndex (string s)
+ {
+ if (s == "")
+ return 0;
+ if (s == null)
+ return 1;
+ int i = 2;
+ for (; i < atomicStringPool.Length; i++) {
+ if (atomicStringPool [i] == null) {
+ atomicStringPool [i] = s;
+ return i;
+ }
+ else if (Object.ReferenceEquals (s,
+ atomicStringPool [i]))
+ return i;
+ }
+ string [] newArr = new string [i * 2];
+ Array.Copy (atomicStringPool, newArr, i);
+ atomicStringPool = newArr;
+ atomicStringPool [i] = s;
+ return i;
+ }
+
+ private int NonAtomicIndex (string s)
+ {
+ if (s == "")
+ return 0;
+ if (s == null)
+ return 1;
+ int i = 2;
+ for (; i < nonAtomicStringPool.Length; i++) {
+ if (nonAtomicStringPool [i] == null) {
+ nonAtomicStringPool [i] = s;
+ return i;
+ }
+ else if (s == nonAtomicStringPool [i])
+ return i;
+ }
+ string [] newArr = new string [i * 2];
+ Array.Copy (nonAtomicStringPool, newArr, i);
+ nonAtomicStringPool = newArr;
+ nonAtomicStringPool [i] = s;
+ return i;
+ }
+
+ private void SetNodeArrayLength (int size)
+ {
+ DTMXPathLinkedNode2 [] newArr = new DTMXPathLinkedNode2 [size];
+ Array.Copy (nodes, newArr, System.Math.Min (size, nodes.Length));
+ nodes = newArr;
+ }
+
+ private void SetAttributeArrayLength (int size)
+ {
+ DTMXPathAttributeNode2 [] newArr =
+ new DTMXPathAttributeNode2 [size];
+ Array.Copy (attributes, newArr, System.Math.Min (size, attributes.Length));
+ attributes = newArr;
+ }
+
+ private void SetNsArrayLength (int size)
+ {
+ DTMXPathNamespaceNode2 [] newArr =
+ new DTMXPathNamespaceNode2 [size];
+ Array.Copy (namespaces, newArr, System.Math.Min (size, namespaces.Length));
+ namespaces = newArr;
+ }
+
+ // Here followings are skipped: firstChild, nextSibling,
+ public void AddNode (int parent, int firstAttribute, int previousSibling, int depth, XPathNodeType nodeType, int baseUri, bool isEmptyElement, int localName, int ns, int prefix, int value, int xmlLang, int namespaceNode, int lineNumber, int linePosition)
+ {
+ if (nodes.Length < nodeIndex + 1) {
+ nodeCapacity *= 4;
+ SetNodeArrayLength (nodeCapacity);
+ }
+
+#if DTM_CLASS
+ nodes [nodeIndex] = new DTMXPathLinkedNode2 ();
+#endif
+ nodes [nodeIndex].FirstChild = 0; // dummy
+ nodes [nodeIndex].Parent = parent;
+ nodes [nodeIndex].FirstAttribute = firstAttribute;
+ nodes [nodeIndex].PreviousSibling = previousSibling;
+ nodes [nodeIndex].NextSibling = 0; // dummy
+ nodes [nodeIndex].Depth = depth;
+ nodes [nodeIndex].NodeType = nodeType;
+ nodes [nodeIndex].BaseURI = baseUri;
+ nodes [nodeIndex].IsEmptyElement = isEmptyElement;
+ nodes [nodeIndex].LocalName = localName;
+ nodes [nodeIndex].NamespaceURI = ns;
+ nodes [nodeIndex].Prefix = prefix;
+ nodes [nodeIndex].Value = value;
+ nodes [nodeIndex].XmlLang = xmlLang;
+ nodes [nodeIndex].FirstNamespace = namespaceNode;
+ nodes [nodeIndex].LineNumber = lineNumber;
+ nodes [nodeIndex].LinePosition = linePosition;
+ }
+
+ // Followings are skipped: nextAttribute,
+ public void AddAttribute (int ownerElement, int localName, int ns, int prefix, int value, int lineNumber, int linePosition)
+ {
+ if (attributes.Length < attributeIndex + 1) {
+ attributeCapacity *= 4;
+ SetAttributeArrayLength (attributeCapacity);
+ }
+
+#if DTM_CLASS
+ attributes [attributeIndex] = new DTMXPathAttributeNode2 ();
+#endif
+ attributes [attributeIndex].OwnerElement = ownerElement;
+ attributes [attributeIndex].LocalName = localName;
+ attributes [attributeIndex].NamespaceURI = ns;
+ attributes [attributeIndex].Prefix = prefix;
+ attributes [attributeIndex].Value = value;
+ attributes [attributeIndex].LineNumber = lineNumber;
+ attributes [attributeIndex].LinePosition = linePosition;
+ }
+
+ // Followings are skipped: nextNsNode (may be next attribute in the same element, or ancestors' nsNode)
+ public void AddNsNode (int declaredElement, int name, int ns, int nextNs)
+ {
+ if (namespaces.Length < nsIndex + 1) {
+ nsCapacity *= 4;
+ SetNsArrayLength (nsCapacity);
+ }
+
+#if DTM_CLASS
+ namespaces [nsIndex] = new DTMXPathNamespaceNode2 ();
+#endif
+ namespaces [nsIndex].DeclaredElement = declaredElement;
+ namespaces [nsIndex].Name = name;
+ namespaces [nsIndex].Namespace = ns;
+ namespaces [nsIndex].NextNamespace = nextNs;
+ }
+ }
+}
+
int writerDepth;
WriteState state;
bool openNamespace;
+ bool isClosed;
public DTMXPathDocument CreateDocument ()
{
+ if (!isClosed)
+ Close ();
return new DTMXPathDocument (nameTable,
nodes,
attributes,
SetNodeArrayLength (nodeIndex + 1);
SetAttributeArrayLength (attributeIndex + 1);
SetNsArrayLength (nsIndex + 1);
+ isClosed = true;
}
public override void Flush ()
--- /dev/null
+//
+// Mono.Xml.XPath.DTMXPathDocumentWriter2
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C) 2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+ class DTMXPathDocumentWriter2 : XmlWriter
+ {
+ public DTMXPathDocumentWriter2 (XmlNameTable nt, int defaultCapacity)
+ {
+ nameTable = nt == null ? new NameTable () : nt;
+ nodeCapacity = defaultCapacity;
+ attributeCapacity = nodeCapacity;
+ nsCapacity = 10;
+ idTable = new Hashtable ();
+
+ nodes = new DTMXPathLinkedNode2 [nodeCapacity];
+ attributes = new DTMXPathAttributeNode2 [attributeCapacity];
+ namespaces = new DTMXPathNamespaceNode2 [nsCapacity];
+
+ atomicStringPool = new string [20];
+ nonAtomicStringPool = new string [20];
+
+ Init ();
+ }
+
+ XmlNameTable nameTable;
+ int nodeCapacity;
+ int attributeCapacity;
+ int nsCapacity;
+
+ // Linked Node
+ DTMXPathLinkedNode2 [] nodes;
+
+ // Attribute
+ DTMXPathAttributeNode2 [] attributes;
+
+ // NamespaceNode
+ DTMXPathNamespaceNode2 [] namespaces;
+
+ // String pool
+ string [] atomicStringPool;
+ string [] nonAtomicStringPool;
+
+ // idTable [string value] -> int nodeId
+ Hashtable idTable;
+
+ int nodeIndex;
+ int attributeIndex;
+ int nsIndex;
+ int parentForFirstChild;
+
+ // for attribute processing; should be reset per each element.
+ int firstAttributeIndex;
+ int lastNsIndexInCurrent;
+ int attrIndexAtStart;
+ int nsIndexAtStart;
+
+ int prevSibling;
+ int lastNsInScope;
+
+ // They are only used in Writer
+ int writerDepth;
+ WriteState state;
+ bool openNamespace;
+ bool isClosed;
+
+ public DTMXPathDocument2 CreateDocument ()
+ {
+ if (!isClosed)
+ Close ();
+ return new DTMXPathDocument2 (nameTable,
+ nodes,
+ attributes,
+ namespaces,
+ atomicStringPool,
+ nonAtomicStringPool,
+ idTable
+ );
+ }
+
+ public void Init ()
+ {
+ // string pool index 0 to 3 are fixed.
+ atomicStringPool [0] = nonAtomicStringPool [0] = "";
+ atomicStringPool [1] = nonAtomicStringPool [1] = null;
+ atomicStringPool [2] = nonAtomicStringPool [2] = XmlNamespaces.XML;
+ atomicStringPool [3] = nonAtomicStringPool [3] = XmlNamespaces.XMLNS;
+
+ // index 0 is dummy. No node (including Root) is assigned to this index
+ // So that we can easily compare index != 0 instead of index < 0.
+ // (Difference between jnz or jbe in 80x86.)
+ AddNode (0, 0, 0, 0, XPathNodeType.All, "", false, "", "", "", "", "", 0, 0, 0);
+ nodeIndex++;
+ AddAttribute (0, "", "", "", "", 0, 0);
+ AddNsNode (0, "", "", 0);
+ nsIndex++;
+ AddNsNode (1, "xml", XmlNamespaces.XML, 0);
+
+ // add root.
+ AddNode (0, 0, 0, -1, XPathNodeType.Root, "", false, "", "", "", "", "", 1, 0, 0);
+
+ this.nodeIndex = 1;
+ this.lastNsInScope = 1;
+ this.parentForFirstChild = nodeIndex;
+
+ state = WriteState.Content;
+ }
+
+ private int GetParentIndex ()
+ {
+ if (parentForFirstChild >= 0)
+ return parentForFirstChild;
+
+ int parent = nodeIndex;
+ if (nodes [nodeIndex].Depth >= writerDepth) {
+ // if not, then current node is parent.
+ while (writerDepth <= nodes [parent].Depth)
+ parent = nodes [parent].Parent;
+ }
+ return parent;
+ }
+
+ private int GetPreviousSiblingIndex ()
+ {
+ int prevSibling = nodeIndex;
+ if (parentForFirstChild >= 0)
+ prevSibling = 0;
+ else
+ while (nodes [prevSibling].Depth != writerDepth)
+ prevSibling = nodes [prevSibling].Parent;
+ return prevSibling;
+ }
+
+ private void UpdateTreeForAddition ()
+ {
+ int parent = GetParentIndex ();
+ prevSibling = GetPreviousSiblingIndex ();
+
+ nodeIndex++;
+
+ if (prevSibling != 0)
+ nodes [prevSibling].NextSibling = nodeIndex;
+ if (parentForFirstChild >= 0)
+ nodes [parent].FirstChild = nodeIndex;
+
+ parentForFirstChild = -1;
+ }
+
+ private void CloseStartElement ()
+ {
+ if (attrIndexAtStart != attributeIndex)
+ nodes [nodeIndex].FirstAttribute = attrIndexAtStart + 1;
+ if (nsIndexAtStart != nsIndex) {
+ nodes [nodeIndex].FirstNamespace = nsIndex;
+ lastNsInScope = nsIndex;
+ }
+
+ if (!nodes [nodeIndex].IsEmptyElement)
+ parentForFirstChild = nodeIndex;
+\r
+ state = WriteState.Content;\r
+ writerDepth++;
+ }
+
+ #region Adding Nodes
+
+ private int AtomicIndex (string s)
+ {
+ if (s == "")
+ return 0;
+ if (s == null)
+ return 1;
+ int i = 2;
+ for (; i < atomicStringPool.Length; i++) {
+ if (atomicStringPool [i] == null) {
+ atomicStringPool [i] = s;
+ return i;
+ }
+ else if (Object.ReferenceEquals (s,
+ atomicStringPool [i]))
+ return i;
+ }
+ string [] newArr = new string [i * 2];
+ Array.Copy (atomicStringPool, newArr, i);
+ atomicStringPool = newArr;
+ atomicStringPool [i] = s;
+ return i;
+ }
+
+ private int NonAtomicIndex (string s)
+ {
+ if (s == "")
+ return 0;
+ if (s == null)
+ return 1;
+ int i = 2;
+ for (; i < nonAtomicStringPool.Length; i++) {
+ if (nonAtomicStringPool [i] == null) {
+ nonAtomicStringPool [i] = s;
+ return i;
+ }
+ else if (s == nonAtomicStringPool [i])
+ return i;
+ }
+ string [] newArr = new string [i * 2];
+ Array.Copy (nonAtomicStringPool, newArr, i);
+ nonAtomicStringPool = newArr;
+ nonAtomicStringPool [i] = s;
+ return i;
+ }
+
+ private void SetNodeArrayLength (int size)
+ {
+ DTMXPathLinkedNode2 [] newArr = new DTMXPathLinkedNode2 [size];
+ Array.Copy (nodes, newArr, System.Math.Min (size, nodes.Length));
+ nodes = newArr;
+ }
+
+ private void SetAttributeArrayLength (int size)
+ {
+ DTMXPathAttributeNode2 [] newArr =
+ new DTMXPathAttributeNode2 [size];
+ Array.Copy (attributes, newArr, System.Math.Min (size, attributes.Length));
+ attributes = newArr;
+ }
+
+ private void SetNsArrayLength (int size)
+ {
+ DTMXPathNamespaceNode2 [] newArr =
+ new DTMXPathNamespaceNode2 [size];
+ Array.Copy (namespaces, newArr, System.Math.Min (size, namespaces.Length));
+ namespaces = newArr;
+ }
+
+ // Here followings are skipped: firstChild, nextSibling,
+ public void AddNode (int parent, int firstAttribute, int previousSibling, int depth, XPathNodeType nodeType, string baseUri, bool isEmptyElement, string localName, string ns, string prefix, string value, string xmlLang, int namespaceNode, int lineNumber, int linePosition)
+ {
+ if (nodes.Length < nodeIndex + 1) {
+ nodeCapacity *= 4;
+ SetNodeArrayLength (nodeCapacity);
+ }
+
+#if DTM_CLASS
+ nodes [nodeIndex] = new DTMXPathLinkedNode2 ();
+#endif
+ nodes [nodeIndex].FirstChild = 0; // dummy
+ nodes [nodeIndex].Parent = parent;
+ nodes [nodeIndex].FirstAttribute = firstAttribute;
+ nodes [nodeIndex].PreviousSibling = previousSibling;
+ nodes [nodeIndex].NextSibling = 0; // dummy
+ nodes [nodeIndex].Depth = depth;
+ nodes [nodeIndex].NodeType = nodeType;
+ nodes [nodeIndex].BaseURI = AtomicIndex (baseUri);
+ nodes [nodeIndex].IsEmptyElement = isEmptyElement;
+ nodes [nodeIndex].LocalName = AtomicIndex (localName);
+ nodes [nodeIndex].NamespaceURI = AtomicIndex (ns);
+ nodes [nodeIndex].Prefix = AtomicIndex (prefix);
+ nodes [nodeIndex].Value = NonAtomicIndex (value);
+ nodes [nodeIndex].XmlLang = AtomicIndex (xmlLang);
+ nodes [nodeIndex].FirstNamespace = namespaceNode;
+ nodes [nodeIndex].LineNumber = lineNumber;
+ nodes [nodeIndex].LinePosition = linePosition;
+ }
+
+ // Followings are skipped: nextAttribute,
+ public void AddAttribute (int ownerElement, string localName, string ns, string prefix, string value, int lineNumber, int linePosition)
+ {
+ if (attributes.Length < attributeIndex + 1) {
+ attributeCapacity *= 4;
+ SetAttributeArrayLength (attributeCapacity);
+ }
+
+#if DTM_CLASS
+ attributes [attributeIndex] = new DTMXPathAttributeNode2 ();
+#endif
+ attributes [attributeIndex].OwnerElement = ownerElement;
+ attributes [attributeIndex].LocalName = AtomicIndex (localName);
+ attributes [attributeIndex].NamespaceURI = AtomicIndex (ns);
+ attributes [attributeIndex].Prefix = AtomicIndex (prefix);
+ attributes [attributeIndex].Value = NonAtomicIndex (value);
+ attributes [attributeIndex].LineNumber = lineNumber;
+ attributes [attributeIndex].LinePosition = linePosition;
+ }
+
+ // Followings are skipped: nextNsNode (may be next attribute in the same element, or ancestors' nsNode)
+ public void AddNsNode (int declaredElement, string name, string ns, int nextNs)
+ {
+ if (namespaces.Length < nsIndex + 1) {
+ nsCapacity *= 4;
+ SetNsArrayLength (nsCapacity);
+ }
+
+#if DTM_CLASS
+ namespaces [nsIndex] = new DTMXPathNamespaceNode2 ();
+#endif
+ namespaces [nsIndex].DeclaredElement = declaredElement;
+ namespaces [nsIndex].Name = AtomicIndex (name);
+ namespaces [nsIndex].Namespace = AtomicIndex (ns);
+ namespaces [nsIndex].NextNamespace = nextNs;
+ }
+ #endregion
+
+ #region XmlWriter methods
+ // They are not supported
+ public override string XmlLang { get { return null; } }
+ public override XmlSpace XmlSpace { get { return XmlSpace.None; } }
+
+ public override WriteState WriteState { get { return state; } }
+
+ public override void Close ()
+ {
+ // Fixup arrays
+ SetNodeArrayLength (nodeIndex + 1);
+ SetAttributeArrayLength (attributeIndex + 1);
+ SetNsArrayLength (nsIndex + 1);
+ isClosed = true;
+ }
+
+ public override void Flush ()
+ {
+ // do nothing
+ }
+
+ public override string LookupPrefix (string ns)
+ {
+ int tmp = nsIndex;
+ while (tmp != 0) {
+ if (atomicStringPool [namespaces [tmp].Namespace] == ns)
+ return atomicStringPool [namespaces [tmp].Name];
+ tmp = namespaces [tmp].NextNamespace;
+ }
+ return null;
+ }
+\r
+ public override void WriteCData (string data)\r
+ {\r
+ AddTextNode (data);\r
+ }\r
+\r
+ private void AddTextNode (string data)\r
+ {\r
+ switch (state) {\r
+ case WriteState.Element:\r
+ CloseStartElement ();\r
+ break;\r
+ case WriteState.Content:\r
+ break;\r
+ default:\r
+ throw new InvalidOperationException ("Invalid document state for CDATA section: " + state);\r
+ }\r
+\r
+ // When text after text, just add the value, and return.\r
+ if (nodes [nodeIndex].Depth == writerDepth) {\r
+ switch (nodes [nodeIndex].NodeType) {\r
+ case XPathNodeType.Text:\r
+ case XPathNodeType.SignificantWhitespace:
+ string value = nonAtomicStringPool [nodes [nodeIndex].Value] + data;
+ nodes [nodeIndex].Value = NonAtomicIndex (value);\r
+ if (IsWhitespace (value))\r
+ nodes [nodeIndex].NodeType = XPathNodeType.SignificantWhitespace;\r
+ else\r
+ nodes [nodeIndex].NodeType = XPathNodeType.Text;\r
+ return;\r
+ }\r
+ }\r
+\r
+ int parent = GetParentIndex ();\r
+ UpdateTreeForAddition ();\r
+
+ AddNode (parent,
+ 0, // attribute
+ prevSibling,
+ writerDepth,
+ XPathNodeType.Text,
+ null,
+ false,
+ null,
+ String.Empty,
+ String.Empty,
+ data,
+ null,
+ 0, // nsIndex
+ 0, // line info
+ 0);
+ }\r
+\r
+ private void CheckTopLevelNode ()\r
+ {\r
+ switch (state) {\r
+ case WriteState.Element:\r
+ CloseStartElement ();\r
+ break;\r
+ case WriteState.Content:\r
+ case WriteState.Prolog:\r
+ case WriteState.Start:\r
+ break;\r
+ default:\r
+ throw new InvalidOperationException ("Invalid document state for CDATA section: " + state);\r
+ }\r
+ }\r
+\r
+ public override void WriteComment (string data)\r
+ {\r
+ CheckTopLevelNode ();\r
+\r
+ int parent = GetParentIndex ();\r
+ UpdateTreeForAddition ();\r
+
+ AddNode (parent,
+ 0, // attribute
+ prevSibling,
+ writerDepth,
+ XPathNodeType.Comment,
+ null,
+ false,
+ null,
+ String.Empty,
+ String.Empty,
+ data,
+ null,
+ 0, // nsIndex
+ 0, // line info
+ 0);
+ }\r
+\r
+ public override void WriteProcessingInstruction (string name, string data)\r
+ {\r
+ CheckTopLevelNode ();\r
+\r
+ int parent = GetParentIndex ();\r
+ UpdateTreeForAddition ();\r
+
+ AddNode (parent,
+ 0, // attribute
+ prevSibling,
+ writerDepth,
+ XPathNodeType.ProcessingInstruction,
+ null,
+ false,
+ name,
+ String.Empty,
+ String.Empty,
+ data,
+ null,
+ 0, // nsIndex
+ 0, // line info
+ 0);
+ }\r
+\r
+ public override void WriteWhitespace (string data)\r
+ {\r
+ CheckTopLevelNode ();\r
+\r
+ int parent = GetParentIndex ();\r
+ UpdateTreeForAddition ();\r
+
+ AddNode (parent,
+ 0, // attribute
+ prevSibling,
+ writerDepth,
+ XPathNodeType.Whitespace,
+ null,
+ false,
+ null,
+ String.Empty,
+ String.Empty,
+ data,
+ null,
+ 0, // nsIndex
+ 0, // line info
+ 0);
+ }\r
+\r
+ public override void WriteStartDocument ()\r
+ {\r
+ // do nothing\r
+ }\r
+\r
+ public override void WriteStartDocument (bool standalone)\r
+ {\r
+ // do nothing\r
+ }\r
+\r
+ public override void WriteEndDocument ()\r
+ {\r
+ // do nothing\r
+ }\r
+\r
+ public override void WriteStartElement (string prefix, string localName, string ns)\r
+ {\r
+ switch (state) {\r
+ case WriteState.Element:\r
+ CloseStartElement ();\r
+ break;\r
+ case WriteState.Start:\r
+ case WriteState.Prolog:\r
+ case WriteState.Content:\r
+ break;\r
+ default:\r
+ throw new InvalidOperationException ("Invalid document state for writing element: " + state);\r
+ }\r
+\r
+ int parent = GetParentIndex ();\r
+ UpdateTreeForAddition ();\r
+
+ WriteStartElement (parent, prevSibling, prefix, localName, ns);
+ state = WriteState.Element;
+ }\r
+
+ private void WriteStartElement (int parent, int previousSibling, string prefix, string localName, string ns)
+ {
+ PrepareStartElement (previousSibling);
+
+ AddNode (parent,
+ 0, // dummy:firstAttribute
+ previousSibling,
+ writerDepth,
+ XPathNodeType.Element,
+ null,
+ false,
+ localName,
+ ns,
+ prefix,
+ "", // Element has no internal value.
+ null,
+ lastNsInScope,
+ 0,
+ 0);
+ }
+
+ private void PrepareStartElement (int previousSibling)
+ {
+ firstAttributeIndex = 0;
+ lastNsIndexInCurrent = 0;
+ attrIndexAtStart = attributeIndex;
+ nsIndexAtStart = nsIndex;
+
+ while (namespaces [lastNsInScope].DeclaredElement == previousSibling) {
+ lastNsInScope = namespaces [lastNsInScope].NextNamespace;
+ }
+ }
+\r
+ public override void WriteEndElement ()\r
+ {\r
+ WriteEndElement (false);\r
+ }\r
+\r
+ public override void WriteFullEndElement ()\r
+ {\r
+ WriteEndElement (true);\r
+ }\r
+\r
+ private void WriteEndElement (bool full)\r
+ {\r
+ switch (state) {\r
+ case WriteState.Element:\r
+ CloseStartElement ();\r
+ break;\r
+ case WriteState.Content:\r
+ break;\r
+ default:\r
+ throw new InvalidOperationException ("Invalid state for writing EndElement: " + state);\r
+ }\r
+ parentForFirstChild = -1;\r
+ if (nodes [nodeIndex].NodeType == XPathNodeType.Element) {\r
+ if (!full)\r
+ nodes [nodeIndex].IsEmptyElement = true;\r
+ }\r
+\r
+ writerDepth--;\r
+ }\r
+\r
+ public override void WriteStartAttribute (string prefix, string localName, string ns)\r
+ {\r
+ if (state != WriteState.Element)\r
+ throw new InvalidOperationException ("Invalid document state for attribute: " + state);\r
+\r
+ state = WriteState.Attribute;\r
+ if (ns == XmlNamespaces.XMLNS)
+ ProcessNamespace ((prefix == null || prefix == String.Empty) ? "" : localName, String.Empty); // dummy: Value should be completed
+ else
+ ProcessAttribute (prefix, localName, ns, String.Empty); // dummy: Value should be completed
+ }\r
+\r
+ private void ProcessNamespace (string prefix, string ns)
+ {
+ nsIndex++;
+
+ int nextTmp = lastNsIndexInCurrent == 0 ? nodes [nodeIndex].FirstNamespace : lastNsIndexInCurrent;
+
+ this.AddNsNode (nodeIndex,
+ prefix,
+ ns,
+ nextTmp);
+ lastNsIndexInCurrent = nsIndex;
+ openNamespace = true;
+ }
+
+ private void ProcessAttribute (string prefix, string localName, string ns, string value)
+ {
+ attributeIndex ++;
+
+ this.AddAttribute (nodeIndex,
+ localName,
+ ns,
+ prefix != null ? prefix : String.Empty,
+ value,
+ 0,
+ 0);
+ if (firstAttributeIndex == 0)
+ firstAttributeIndex = attributeIndex;
+ else
+ attributes [attributeIndex - 1].NextAttribute = attributeIndex;
+ }
+
+ public override void WriteEndAttribute ()\r
+ {\r
+ if (state != WriteState.Attribute)\r
+ throw new InvalidOperationException ();\r
+\r
+ openNamespace = false;\r
+ state = WriteState.Element;\r
+ }\r
+\r
+ public override void WriteString (string text)\r
+ {\r
+ if (WriteState == WriteState.Attribute) {
+ if (openNamespace) {\r
+ string value = atomicStringPool [namespaces [nsIndex].Namespace] + text;
+ namespaces [nsIndex].Namespace = AtomicIndex (value);
+ } else {\r
+ string value = nonAtomicStringPool [attributes [attributeIndex].Value] + text;
+ attributes [attributeIndex].Value = NonAtomicIndex (value);
+ }\r
+ }\r
+ else\r
+ AddTextNode (text);\r
+ }\r
+\r
+ // Well, they cannot be supported, but actually used to\r
+ // disable-output-escaping = "true"\r
+ public override void WriteRaw (string data)\r
+ {\r
+ WriteString (data);\r
+ }\r
+
+ public override void WriteRaw (char [] data, int start, int len)\r
+ {\r
+ WriteString (new string (data, start, len));\r
+ }\r
+\r
+ public override void WriteName (string name)\r
+ {\r
+ WriteString (name);\r
+ }\r
+\r
+ public override void WriteNmToken (string name)\r
+ {\r
+ WriteString (name);\r
+ }\r
+\r
+ public override void WriteBase64 (byte [] buffer, int index, int count)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }
+
+ public override void WriteBinHex (byte [] buffer, int index, int count)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }\r
+\r
+ public override void WriteChars (char [] buffer, int index, int count)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }\r
+\r
+ public override void WriteCharEntity (char c)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }\r
+\r
+ public override void WriteDocType (string name, string pub, string sys, string intSubset)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }\r
+
+ public override void WriteEntityRef (string name)
+ {
+ throw new NotSupportedException ();\r
+ }
+
+ public override void WriteQualifiedName (string localName, string ns)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }\r
+\r
+ public override void WriteSurrogateCharEntity (char high, char low)\r
+ {\r
+ throw new NotSupportedException ();\r
+ }
+
+ private bool IsWhitespace (string data)
+ {
+ for (int i = 0; i < data.Length; i++) {
+ switch (data [i]) {
+ case ' ':
+ case '\r':
+ case '\n':
+ case '\t':
+ continue;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }\r
+ #endregion
+ }
+}
{
public const string XML = "http://www.w3.org/XML/1998/namespace";
public const string XMLNS = "http://www.w3.org/2000/xmlns/";
+ public const int IndexXML = 2;
+ public const int IndexXMLNS = 3;
}
}
--- /dev/null
+//
+// Mono.Xml.XPath.DTMXPathNavigator2
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C) 2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+ class DTMXPathNavigator2 : XPathNavigator, IXmlLineInfo
+ {
+
+ public DTMXPathNavigator2 (DTMXPathDocument2 document,
+ XmlNameTable nameTable,
+ DTMXPathLinkedNode2 [] nodes,
+ DTMXPathAttributeNode2 [] attributes,
+ DTMXPathNamespaceNode2 [] namespaces,
+ string [] atomicStringPool,
+ string [] nonAtomicStringPool,
+ Hashtable idTable)
+ {
+ this.nodes = nodes;
+ this.attributes = attributes;
+ this.namespaces = namespaces;
+ this.atomicStringPool = atomicStringPool;
+ this.nonAtomicStringPool = nonAtomicStringPool;
+ this.idTable = idTable;
+ this.nameTable = nameTable;
+ this.MoveToRoot ();
+ this.document = document;
+ }
+
+ // Copy constructor including position informations.
+ public DTMXPathNavigator2 (DTMXPathNavigator2 org)
+ : this (org.document, org.nameTable,
+ org.nodes, org.attributes, org.namespaces,
+ org.atomicStringPool, org.nonAtomicStringPool,
+ org.idTable)
+ {
+ currentIsNode = org.currentIsNode;
+ currentIsAttr = org.currentIsAttr;
+
+ currentNode = org.currentNode;
+ currentAttr = org.currentAttr;
+ currentNs = org.currentNs;
+ }
+
+ XmlNameTable nameTable;
+
+ // Created XPathDocument. This is used to identify the origin of the navigator.
+ DTMXPathDocument2 document;
+
+ DTMXPathLinkedNode2 [] nodes;// = new DTMXPathLinkedNode [0];
+ DTMXPathAttributeNode2 [] attributes;// = new DTMXPathAttributeNode [0];
+ DTMXPathNamespaceNode2 [] namespaces;// = new DTMXPathNamespaceNode [0];
+
+ // String pool
+ string [] atomicStringPool;
+ string [] nonAtomicStringPool;
+
+ // ID table
+ Hashtable idTable;
+
+ bool currentIsNode;
+ bool currentIsAttr;
+
+ int currentNode;
+ int currentAttr;
+ int currentNs;
+
+ StringBuilder valueBuilder;
+
+#region Ctor
+
+ internal DTMXPathNavigator2 (XmlNameTable nt)
+ {
+ this.nameTable = nt;
+ }
+
+#endregion
+
+#region Properties
+
+ public override string BaseURI {
+ get { return atomicStringPool [nodes [currentNode].BaseURI]; }
+ }
+
+ public override bool HasAttributes {
+ get { return currentIsNode ? nodes [currentNode].FirstAttribute != 0 : false; }
+ }
+
+ public override bool HasChildren {
+ get { return currentIsNode ? nodes [currentNode].FirstChild != 0 : false; }
+ }
+
+ public override bool IsEmptyElement {
+ get { return currentIsNode ? nodes [currentNode].IsEmptyElement : false; }
+ }
+
+ int IXmlLineInfo.LineNumber {
+ get {
+ return currentIsAttr ? attributes [currentAttr].LineNumber :
+ nodes [currentNode].LineNumber;
+ }
+ }
+
+ int IXmlLineInfo.LinePosition {
+ get {
+ return currentIsAttr ? attributes [currentAttr].LinePosition :
+ nodes [currentNode].LinePosition;
+ }
+ }
+
+ public override string LocalName {
+ get {
+ if (currentIsNode)
+ return atomicStringPool [nodes [currentNode].LocalName];
+ else if (currentIsAttr)
+ return atomicStringPool [attributes [currentAttr].LocalName];
+ else
+ return atomicStringPool [namespaces [currentNs].Name];
+ }
+ }
+
+ // It maybe scarcely used, so I decided to compute it always.
+ public override string Name {
+ get {
+ string prefix;
+ string localName;
+ if (currentIsNode) {
+ prefix = atomicStringPool [nodes [currentNode].Prefix];
+ localName = atomicStringPool [nodes [currentNode].LocalName];
+ } else if (currentIsAttr) {
+ prefix = atomicStringPool [attributes [currentAttr].Prefix];
+ localName = atomicStringPool [attributes [currentAttr].LocalName];
+ } else
+ return atomicStringPool [namespaces [currentNs].Name];
+
+ if (prefix != "")
+ return prefix + ':' + localName;
+ else
+ return localName;
+ }
+ }
+
+ public override string NamespaceURI {
+ get {
+ if (currentIsNode)
+ return atomicStringPool [nodes [currentNode].NamespaceURI];
+ if (currentIsAttr)
+ return atomicStringPool [attributes [currentAttr].NamespaceURI];
+ return String.Empty;
+ }
+ }
+
+ public override XmlNameTable NameTable {
+ get { return nameTable; }
+ }
+
+ public override XPathNodeType NodeType {
+ get {
+ if (currentIsNode)
+ return nodes [currentNode].NodeType;
+ else if (currentIsAttr)
+ return XPathNodeType.Attribute;
+ else
+ return XPathNodeType.Namespace;
+ }
+ }
+
+ public override string Prefix {
+ get {
+ if (currentIsNode)
+ return atomicStringPool [nodes [currentNode].Prefix];
+ else if (currentIsAttr)
+ return atomicStringPool [attributes [currentAttr].Prefix];
+ return String.Empty;
+ }
+ }
+
+ public override string Value {
+ get {
+ if (currentIsAttr)
+ return nonAtomicStringPool [attributes [currentAttr].Value];
+ else if (!currentIsNode)
+ return atomicStringPool [namespaces [currentNs].Namespace];
+
+ switch (nodes [currentNode].NodeType) {
+ case XPathNodeType.Comment:
+ case XPathNodeType.ProcessingInstruction:
+ case XPathNodeType.Text:
+ case XPathNodeType.Whitespace:
+ case XPathNodeType.SignificantWhitespace:
+ return nonAtomicStringPool [nodes [currentNode].Value];
+ }
+
+ // Element
+ if (valueBuilder == null)
+ valueBuilder = new StringBuilder ();
+ else
+ valueBuilder.Length = 0;
+
+ int iter = nodes [currentNode].FirstChild;
+ int depth = nodes [currentNode].Depth;
+ while (iter < nodes.Length && nodes [iter].Depth > depth) {
+ switch (nodes [iter].NodeType) {
+ case XPathNodeType.Comment:
+ case XPathNodeType.ProcessingInstruction:
+ break;
+ default:
+ valueBuilder.Append (nonAtomicStringPool [nodes [iter].Value]);
+ break;
+ }
+ iter++;
+ }
+
+ return valueBuilder.ToString ();
+ }
+ }
+
+ public override string XmlLang {
+ get { return atomicStringPool [nodes [currentNode].XmlLang]; }
+ }
+
+#endregion
+
+#region Methods
+
+ public override XPathNavigator Clone ()
+ {
+ return new DTMXPathNavigator2 (this);
+ }
+
+ public override XmlNodeOrder ComparePosition (XPathNavigator nav)
+ {
+ DTMXPathNavigator2 another = nav as DTMXPathNavigator2;
+
+ if (another == null || another.document != this.document)
+ return XmlNodeOrder.Unknown;
+
+ if (currentNode > another.currentNode)
+ return XmlNodeOrder.After;
+ else if (currentNode < another.currentNode)
+ return XmlNodeOrder.Before;
+
+ // another may attr or ns,
+ // and this may be also attr or ns.
+ if (another.currentIsAttr) {
+ if (this.currentIsAttr) {
+ if (currentAttr > another.currentAttr)
+ return XmlNodeOrder.After;
+ else if (currentAttr < another.currentAttr)
+ return XmlNodeOrder.Before;
+ else
+ return XmlNodeOrder.Same;
+ } else
+ return XmlNodeOrder.Before;
+ } else if (!another.currentIsNode) {
+ if (!this.currentIsNode) {
+ if (currentNs > another.currentNs)
+ return XmlNodeOrder.After;
+ else if (currentNs < another.currentNs)
+ return XmlNodeOrder.Before;
+ else
+ return XmlNodeOrder.Same;
+ } else
+ return XmlNodeOrder.Before;
+ } else
+ return !another.currentIsNode ? XmlNodeOrder.Before : XmlNodeOrder.Same;
+ }
+
+ private int findAttribute (string localName, string namespaceURI)
+ {
+ if (currentIsNode && nodes [currentNode].NodeType == XPathNodeType.Element) {
+ int cur = nodes [currentNode].FirstAttribute;
+ while (cur != 0) {
+ if (atomicStringPool [attributes [cur].LocalName] == localName && atomicStringPool [attributes [cur].NamespaceURI] == namespaceURI)
+ return cur;
+ cur = attributes [cur].NextAttribute;
+ }
+ }
+ return 0;
+ }
+
+ public override string GetAttribute (string localName,
+ string namespaceURI)
+ {
+ int attr = findAttribute (localName, namespaceURI);
+ return (attr != 0) ? nonAtomicStringPool [attributes [attr].Value] : String.Empty;
+ }
+
+ public override string GetNamespace (string name)
+ {
+ if (currentIsNode && nodes [currentNode].NodeType == XPathNodeType.Element) {
+ int nsNode = nodes [currentNode].FirstNamespace;
+ while (nsNode != 0) {
+ if (atomicStringPool [namespaces [nsNode].Name] == name)
+ return atomicStringPool [namespaces [nsNode].Namespace];
+ nsNode = namespaces [nsNode].NextNamespace;
+ }
+ }
+ return String.Empty;
+ }
+
+ bool IXmlLineInfo.HasLineInfo ()
+ {
+ return true;
+ }
+
+ public override bool IsDescendant (XPathNavigator nav)
+ {
+ DTMXPathNavigator2 another = nav as DTMXPathNavigator2;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ // Maybe we can improve here more efficiently by
+ // comparing node indices.
+ if (another.currentNode == currentNode)
+ return !another.currentIsNode;
+ int tmp = nodes [another.currentNode].Parent;
+ while (tmp != 0) {
+ if (tmp == currentNode)
+ return true;
+ tmp = nodes [tmp].Parent;
+ }
+ return false;
+ }
+
+ public override bool IsSamePosition (XPathNavigator other)
+ {
+ DTMXPathNavigator2 another = other as DTMXPathNavigator2;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ if (this.currentNode != another.currentNode ||
+ this.currentIsAttr != another.currentIsAttr ||
+ this.currentIsNode != another.currentIsNode)
+ return false;
+
+ if (currentIsAttr)
+ return this.currentAttr == another.currentAttr;
+ else if (!currentIsNode)
+ return this.currentNs == another.currentNs;
+ return true;
+ }
+
+ public override bool MoveTo (XPathNavigator other)
+ {
+ DTMXPathNavigator2 another = other as DTMXPathNavigator2;
+
+ if (another == null || another.document != this.document)
+ return false;
+
+ this.currentNode = another.currentNode;
+ this.currentAttr = another.currentAttr;
+ this.currentNs = another.currentNs;
+ this.currentIsNode = another.currentIsNode;
+ this.currentIsAttr = another.currentIsAttr;
+ return true;
+ }
+
+ public override bool MoveToAttribute (string localName,
+ string namespaceURI)
+ {
+ int attr = findAttribute (localName, namespaceURI);
+ if (attr == 0)
+ return false;
+
+ currentAttr = attr;
+ currentIsAttr = true;
+ currentIsNode = false;
+ return true;
+ }
+
+ public override bool MoveToFirst ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int cur = nodes [currentNode].PreviousSibling;
+ if (cur == 0)
+ return false;
+
+ int next = cur;
+ while (next != 0) {
+ cur = next;
+ next = nodes [cur].PreviousSibling;
+ }
+ currentNode = cur;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override bool MoveToFirstAttribute ()
+ {
+ if (!currentIsNode)
+ return false;
+
+ int first = nodes [currentNode].FirstAttribute;
+ if (first == 0)
+ return false;
+
+ currentAttr = first;
+ currentIsAttr = true;
+ currentIsNode = false;
+ return true;
+ }
+
+ public override bool MoveToFirstChild ()
+ {
+ if (!currentIsNode)
+ return false;
+
+ int first = nodes [currentNode].FirstChild;
+ if (first == 0)
+ return false;
+
+ currentNode = first;
+ return true;
+ }
+
+ private bool moveToSpecifiedNamespace (int cur,
+ XPathNamespaceScope namespaceScope)
+ {
+ if (cur == 0)
+ return false;
+
+ if (namespaceScope == XPathNamespaceScope.Local &&
+ namespaces [cur].DeclaredElement != currentNode)
+ return false;
+
+ if (namespaceScope != XPathNamespaceScope.All
+ && namespaces [cur].Namespace == XmlNamespaces.IndexXML)
+ return false;
+
+ if (cur != 0) {
+ moveToNamespace (cur);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ public override bool MoveToFirstNamespace (
+ XPathNamespaceScope namespaceScope)
+ {
+ if (!currentIsNode)
+ return false;
+ int cur = nodes [currentNode].FirstNamespace;
+ return moveToSpecifiedNamespace (cur, namespaceScope);
+ }
+
+ // Note that this support is extension to XPathDocument.
+ // XPathDocument does not support ID reference.
+ public override bool MoveToId (string id)
+ {
+ if (idTable.ContainsKey (id)) {
+ currentNode = (int) idTable [id];
+ currentIsNode = true;
+ currentIsAttr = false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private void moveToNamespace (int nsNode)
+ {
+ currentIsNode = currentIsAttr = false;
+ currentNs = nsNode;
+ }
+
+ public override bool MoveToNamespace (string name)
+ {
+ int cur = nodes [currentNode].FirstNamespace;
+ if (cur == 0)
+ return false;
+
+ while (cur != 0) {
+ if (atomicStringPool [namespaces [cur].Name] == name) {
+ moveToNamespace (cur);
+ return true;
+ }
+ cur = namespaces [cur].NextNamespace;
+ }
+ return false;
+ }
+
+ public override bool MoveToNext ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int next = nodes [currentNode].NextSibling;
+ if (next == 0)
+ return false;
+ currentNode = next;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override bool MoveToNextAttribute ()
+ {
+ if (!currentIsAttr)
+ return false;
+
+ int next = attributes [currentAttr].NextAttribute;
+ if (next == 0)
+ return false;
+ currentAttr = next;
+ return true;
+ }
+
+ public override bool MoveToNextNamespace (
+ XPathNamespaceScope namespaceScope)
+ {
+ if (currentIsAttr || currentIsNode)
+ return false;
+
+ int cur = namespaces [currentNs].NextNamespace;
+ return moveToSpecifiedNamespace (cur, namespaceScope);
+ }
+
+ public override bool MoveToParent ()
+ {
+ if (!currentIsNode) {
+ currentIsNode = true;
+ currentIsAttr = false;
+ return true;
+ }
+
+ int parent = nodes [currentNode].Parent;
+ if (parent == 0) // It is root itself.
+ return false;
+
+ currentNode = parent;
+ return true;
+ }
+
+ public override bool MoveToPrevious ()
+ {
+ if (currentIsAttr)
+ return false;
+
+ int previous = nodes [currentNode].PreviousSibling;
+ if (previous == 0)
+ return false;
+ currentNode = previous;
+ currentIsNode = true;
+ return true;
+ }
+
+ public override void MoveToRoot ()
+ {
+ currentNode = 1; // root is 1.
+ currentIsNode = true;
+ currentIsAttr = false;
+ }
+
+#endregion
+ }
+}
--- /dev/null
+//
+// Mono.Xml.XPath.DTMXPathNode2.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C) 2004 Novell Inc
+//
+// These classes represent each node of DTMXPathNavigator.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath
+{
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+#if DTM_CLASS
+ class DTMXPathLinkedNode2
+#else
+ struct DTMXPathLinkedNode2
+#endif
+ {
+ public int FirstChild;
+ public int Parent;
+ public int PreviousSibling;
+ public int NextSibling;
+ public int FirstAttribute;
+ public int FirstNamespace;
+ public int Depth;
+ public XPathNodeType NodeType;
+ public int BaseURI;
+ public bool IsEmptyElement;
+ public int LocalName;
+ public int NamespaceURI;
+ public int Prefix;
+ public int Value;
+ public int XmlLang;
+ public int LineNumber;
+ public int LinePosition;
+ }
+
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+#if DTM_CLASS
+ class DTMXPathAttributeNode2
+#else
+ struct DTMXPathAttributeNode2
+#endif
+ {
+ public int OwnerElement;
+ public int NextAttribute;
+ public int LocalName;
+ public int NamespaceURI;
+ public int Prefix;
+ public int Value;
+ public int LineNumber;
+ public int LinePosition;
+ }
+
+#if OUTSIDE_SYSTEM_XML
+ public
+#else
+ internal
+#endif
+#if DTM_CLASS
+ class DTMXPathNamespaceNode2
+#else
+ struct DTMXPathNamespaceNode2
+#endif
+ {
+ public int DeclaredElement;
+ public int NextNamespace;
+ public int Name;
+ public int Namespace;
+ }
+}
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XmlSchemaObject.cs : added Parent.
+ * XmlSchema.cs,
+ XmlSchemaElement.cs,
+ XmlSchemaAttribute.cs,
+ XmlSchemaAttributeGroup.cs,
+ XmlSchemaGroup.cs,
+ XmlSchemaComplexType.cs,
+ XmlSchemaSequence.cs,
+ XmlSchemaChoice.cs,
+ XmlSchemaAll.cs,
+ XmlSchemaIdentityConstraint.cs,
+ XmlSchemaComplexContent.cs,
+ XmlSchemaSimpleContent.cs,
+ XmlSchemaSimpleContentExtension.cs,
+ XmlSchemaSimpleContentRestriction.cs,
+ XmlSchemaComplexContentExtension.cs,
+ XmlSchemaComplexContentRestriction.cs,
+ XmlSchemaSimpleType.cs,
+ XmlSchemaSimpleTypeRestriction.cs,
+ XmlSchemaSimpleTypeList.cs,
+ XmlSchemaSimpleTypeUnion.cs : Fill Parent on Compilation.
+
+ * XmlSchemaException.cs,
+ XmlSchemaInferenceException.cs,
+ XmlSchemaValidationException.cs : added SecurityPermissionAttribute.
+
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XmlSchemaComplexType.cs : simplify Compile().
+
2004-11-25 Atsushi Enomoto <atsushi@ximian.com>
* XmlSchemaElement.cs,
// Compile the content of this schema
compilationItems = new XmlSchemaObjectCollection ();
- for (int i = 0; i < Items.Count; i++)
+ for (int i = 0; i < Items.Count; i++) {
+#if NET_2_0
+ Items [i].Parent = this;
+#endif
compilationItems.Add (Items [i]);
+ }
if (this == rootSchema)
handledUris = new Hashtable ();
// First, we run into inclusion schemas to collect
// compilation target items into compiledItems.
for (int i = 0; i < Includes.Count; i++) {
+#if NET_2_0
+ Includes [i].Parent = this;
+#endif
XmlSchemaExternal ext = Includes [i] as XmlSchemaExternal;
if (ext == null) {
error (handler, String.Format ("Object of Type {0} is not valid in Includes Property of XmlSchema", Includes [i].GetType().Name));
\r
foreach(XmlSchemaObject obj in Items)\r
{\r
+#if NET_2_0\r
+ obj.Parent = this;\r
+#endif\r
+\r
XmlSchemaElement elem = obj as XmlSchemaElement;\r
if(elem != null)\r
{\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (schemaType != null)\r
+ schemaType.Parent = this;\r
+#endif\r
+\r
errorCount = 0;\r
\r
if(ParentIsSchema || isRedefineChild)//a\r
\r
if(this.AnyAttribute != null)\r
{\r
+#if NET_2_0\r
+ this.AnyAttribute.Parent = this;\r
+#endif\r
errorCount += this.AnyAttribute.Compile(h, schema);\r
}\r
\r
foreach(XmlSchemaObject obj in Attributes)\r
{\r
+#if NET_2_0\r
+ obj.Parent = this;\r
+#endif\r
+\r
if(obj is XmlSchemaAttribute)\r
{\r
XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;\r
\r
foreach(XmlSchemaObject obj in Items)\r
{\r
+#if NET_2_0\r
+ obj.Parent = this;\r
+#endif\r
+\r
if(obj is XmlSchemaElement ||\r
obj is XmlSchemaGroupRef ||\r
obj is XmlSchemaChoice ||\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (Content != null)\r
+ Content.Parent = this;\r
+#endif\r
+\r
if (isRedefinedComponent) {\r
if (Annotation != null)\r
Annotation.isRedefinedComponent = true;\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (Particle != null)\r
+ Particle.Parent = this;\r
+ if (AnyAttribute != null)\r
+ AnyAttribute.Parent = this;\r
+ foreach (XmlSchemaObject obj in Attributes)\r
+ obj.Parent = this;\r
+#endif\r
+\r
if (this.isRedefinedComponent) {\r
if (Annotation != null)\r
Annotation.isRedefinedComponent = true;\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (Particle != null)\r
+ Particle.Parent = this;\r
+ if (AnyAttribute != null)\r
+ AnyAttribute.Parent = this;\r
+ foreach (XmlSchemaObject obj in Attributes)\r
+ obj.Parent = this;\r
+#endif\r
+\r
if (this.isRedefinedComponent) {\r
if (Annotation != null)\r
Annotation.isRedefinedComponent = true;\r
if (this.IsComplied (schema.CompilationId))\r
return errorCount;\r
\r
+#if NET_2_0\r
+ if (ContentModel != null)\r
+ ContentModel.Parent = this;\r
+ if (Particle != null)\r
+ Particle.Parent = this;\r
+ if (AnyAttribute != null)\r
+ AnyAttribute.Parent = this;\r
+ foreach (XmlSchemaObject obj in Attributes)\r
+ obj.Parent = this;\r
+#endif\r
+\r
ValidatedIsAbstract = isAbstract;\r
\r
if (isRedefinedComponent) {\r
}\r
else\r
{\r
- if(Particle is XmlSchemaGroupRef)\r
- {\r
- XmlSchemaGroupRef xsgr = (XmlSchemaGroupRef)Particle;\r
- errorCount += xsgr.Compile(h,schema);\r
- }\r
- else if(Particle is XmlSchemaAll)\r
- {\r
- XmlSchemaAll xsa = (XmlSchemaAll)Particle;\r
- errorCount += xsa.Compile(h,schema);\r
- }\r
- else if(Particle is XmlSchemaChoice)\r
- {\r
- XmlSchemaChoice xsc = (XmlSchemaChoice)Particle;\r
- errorCount += xsc.Compile(h,schema);\r
- }\r
- else if(Particle is XmlSchemaSequence)\r
- {\r
- XmlSchemaSequence xss = (XmlSchemaSequence)Particle;\r
- errorCount += xss.Compile(h,schema);\r
- }\r
+ if (Particle != null)\r
+ errorCount += Particle.Compile (h, schema);\r
\r
if(this.anyAttribute != null)\r
{\r
return 0;\r
InitPostCompileInformations ();\r
this.schema = schema;\r
+#if NET_2_0\r
+ if (SchemaType != null)\r
+ SchemaType.Parent = this;\r
+ foreach (XmlSchemaObject obj in Constraints)\r
+ obj.Parent = this;\r
+#endif\r
\r
if(this.defaultValue != null && this.fixedValue != null)\r
error(h,"both default and fixed can't be present");\r
using System;\r
using System.Globalization;\r
using System.Runtime.Serialization;\r
-\r
+using System.Security.Permissions;\r
\r
namespace System.Xml.Schema\r
{\r
#endif\r
\r
// Methods\r
+#if NET_2_0\r
+ [SecurityPermission (SecurityAction.LinkDemand,\r
+ Flags=SecurityPermissionFlag.SerializationFormatter)]\r
+#endif\r
public override void GetObjectData(SerializationInfo info, StreamingContext context)\r
{\r
base.GetObjectData (info, context);\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (Particle != null)\r
+ Particle.Parent = this;\r
+#endif\r
+\r
if(Name == null)\r
error(h,"Required attribute name must be present");\r
else if(!XmlSchemaUtil.CheckNCName(this.name)) \r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (Selector != null)\r
+ Selector.Parent = this;\r
+ foreach (XmlSchemaObject obj in Fields)\r
+ obj.Parent = this;\r
+#endif\r
+\r
if(Name == null)\r
error(h,"Required attribute name must be present");\r
else if(!XmlSchemaUtil.CheckNCName(this.name)) \r
using System;
using System.Runtime.Serialization;
+using System.Security.Permissions;
using System.Xml;
namespace System.Xml.Schema
{
}
+#if NET_2_0
+ [SecurityPermission (SecurityAction.LinkDemand,
+ Flags=SecurityPermissionFlag.SerializationFormatter)]
+#endif
public override void GetObjectData (
SerializationInfo info, StreamingContext context)
{
internal bool isRedefinedComponent;\r
internal XmlSchemaObject redefinedObject;\r
\r
+#if NET_2_0\r
+ private XmlSchemaObject parent;\r
+#endif\r
+\r
+\r
protected XmlSchemaObject()\r
{\r
namespaces = new XmlSerializerNamespaces();\r
set{ sourceUri = value; } \r
}\r
\r
+#if NET_2_0\r
+ [XmlIgnore]\r
+ public XmlSchemaObject Parent {\r
+ get { return parent; }\r
+ set { parent = value; }\r
+ }\r
+#endif\r
+\r
// Undocumented Property\r
[XmlNamespaceDeclarations]\r
public XmlSerializerNamespaces Namespaces \r
\r
foreach(XmlSchemaObject obj in Items)\r
{\r
+#if NET_2_0\r
+ obj.Parent = this;\r
+#endif\r
if(obj is XmlSchemaElement ||\r
obj is XmlSchemaGroupRef ||\r
obj is XmlSchemaChoice ||\r
}\r
else\r
{\r
+#if NET_2_0\r
+ Content.Parent = this;\r
+#endif\r
if(Content is XmlSchemaSimpleContentRestriction)\r
{\r
XmlSchemaSimpleContentRestriction xscr = (XmlSchemaSimpleContentRestriction) Content;\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (AnyAttribute != null)\r
+ AnyAttribute.Parent = this;\r
+ foreach (XmlSchemaObject obj in Attributes)\r
+ obj.Parent = this;\r
+#endif\r
+\r
if (this.isRedefinedComponent) {\r
if (Annotation != null)\r
Annotation.isRedefinedComponent = true;\r
// If this is already compiled this time, simply skip.\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
+#if NET_2_0\r
+ if (BaseType != null)\r
+ BaseType.Parent = this;\r
+ if (AnyAttribute != null)\r
+ AnyAttribute.Parent = this;\r
+ foreach (XmlSchemaObject obj in Attributes)\r
+ obj.Parent = this;\r
+#endif\r
\r
if (this.isRedefinedComponent) {\r
if (Annotation != null)\r
// If this is already compiled this time, simply skip.\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
+#if NET_2_0\r
+ if (Content != null)\r
+ Content.Parent = this;\r
+#endif\r
\r
errorCount = 0;\r
\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (ItemType != null)\r
+ ItemType.Parent = this;\r
+#endif\r
+\r
errorCount = 0;\r
\r
if(ItemType != null && !ItemTypeName.IsEmpty)\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ if (BaseType != null)\r
+ BaseType.Parent = this;\r
+ foreach (XmlSchemaObject obj in Facets)\r
+ obj.Parent = this;\r
+#endif\r
+\r
errorCount = 0;\r
\r
if(this.baseType != null && !this.BaseTypeName.IsEmpty)\r
if (this.IsComplied (schema.CompilationId))\r
return 0;\r
\r
+#if NET_2_0\r
+ foreach (XmlSchemaObject obj in BaseTypes)\r
+ obj.Parent = this;\r
+#endif\r
+\r
errorCount = 0;\r
\r
int count = BaseTypes.Count;\r
using System;
using System.Globalization;
using System.Runtime.Serialization;
-
+using System.Security.Permissions;
namespace System.Xml.Schema
{
{
}
+#if NET_2_0
+ [SecurityPermission (SecurityAction.LinkDemand,
+ Flags=SecurityPermissionFlag.SerializationFormatter)]
+#endif
+ public override void GetObjectData (
+ SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData (info, context);
+ }
}
}
+2004-12-04 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XPathDocument.cs : switch to DTMXPathNavigator2 which fully
+ eliminated string fields from struct.
+ (When we switch from struct to class, revert this change to use
+ DTMXPathNavigator, since class-based DTMXPathNavigator2 is rather
+ wasting processing speed.)
+
2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
* Iterator.cs : when PredicateIterator has a numeric predicate, it
using System.Xml.Serialization;
using Mono.Xml.XPath;
+//using InternalBuilder = Mono.Xml.XPath.DTMXPathDocumentBuilder;
+//using InternalDocument = Mono.Xml.XPath.DTMXPathDocument;
+using InternalBuilder = Mono.Xml.XPath.DTMXPathDocumentBuilder2;
+using InternalDocument = Mono.Xml.XPath.DTMXPathDocument2;
+
namespace System.Xml.XPath
{
#if NET_2_0obsolete
}
XPathDocument2Editable editable;
- DTMXPathDocument dtm;
+ InternalDocument dtm;
XmlSchemaSet schemas;
if (useEditable)
InitializeEditable (reader, space, acceptChangesOnLoad);
else
- dtm = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
+ dtm = new InternalBuilder (reader, space).CreateDocument ();
}
private void InitializeEditable (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
public class XPathDocument : IXPathNavigable
{
- DTMXPathDocument document;
+ IXPathNavigable document;
public XPathDocument (Stream stream)
{
private void Initialize (XmlReader reader, XmlSpace space)
{
- document = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
+ document = new InternalBuilder (reader, space).CreateDocument ();
}
private void Initialize (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
{
- document = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
+ document = new InternalBuilder (reader, space).CreateDocument ();
}
public XPathNavigator CreateNavigator ()
Mono.Xml.XPath/DTMXPathDocumentWriter.cs
Mono.Xml.XPath/DTMXPathNavigator.cs
Mono.Xml.XPath/DTMXPathNode.cs
+Mono.Xml.XPath/DTMXPathDocument2.cs
+Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs
+Mono.Xml.XPath/DTMXPathDocumentWriter2.cs
+Mono.Xml.XPath/DTMXPathNavigator2.cs
+Mono.Xml.XPath/DTMXPathNode2.cs
Mono.Xml.XPath/IdPattern.cs
Mono.Xml.XPath/KeyPattern.cs
Mono.Xml.XPath/LocationPathPattern.cs
+2004-12-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * XmlTextReader.cs: don't use \0 as buffer terminator.
+ * XmlInputStream.cs: s/Array.Copy/Buffer.BlockCopy/.
+
2004-11-30 Atsushi Enomoto <atsushi@ximian.com>
* DTDReader.cs : Consideration on parameter entity was missing for
{
int ret;
if (count <= bufLength - bufPos) { // all from buffer
- Array.Copy (this.buffer, bufPos, buffer, offset, count);
+ Buffer.BlockCopy (this.buffer, bufPos, buffer, offset, count);
bufPos += count;
ret = count;
} else {
int bufRest = bufLength - bufPos;
if (bufLength > bufPos) {
- Array.Copy (this.buffer, bufPos, buffer, offset, bufRest);
+ Buffer.BlockCopy (this.buffer, bufPos, buffer, offset, bufRest);
bufPos += bufRest;
}
ret = bufRest +
else
return PeekChar ();
}
- else
- return peekChars [peekCharsIndex] != 0 ?
- peekChars [peekCharsIndex] : -1;
+
+ return peekChars [peekCharsIndex];
}
private int ReadChar ()
{
peekCharsIndex = 0;
peekCharsLength = reader.Read (peekChars, 0, peekCharCapacity);
- if (peekCharsLength == 0)
- return false;
- // set EOF
- if (peekCharsLength < peekCharCapacity)
- peekChars [peekCharsLength] = (char) 0;
- return true;
+ return (peekCharsLength != 0);
}
private string ExpandSurrogateChar (int ch)
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * xslttest.cs : improved. See "mono xslttest.exe -?" for details.
+ * Makefile : modified "make test" to "make run-test" and output
+ results into TestResult.Xml that contains all results.
+ * README : updated as well.
+
2004-01-28 Atsushi Enomoto <atsushi@ximian.com>
* xslttest.cs : Now it tests against XPathDocument. Reduced error msgs.
xslt-testsuite-01.zip :
wget http://www.oasis-open.org/committees/download.php/1937/xslt-testsuite-01.zip
-test :
- $(RUNTIME) xslttest.exe
+run-test :
+ $(RUNTIME) xslttest.exe --report:TestResult.xml --xml --details --outall
# Be careful to use this!
# clean :
"make" will do what you need (downloading test archive, expanding,
compiling test runner.
-"make test" will do the actual tests.
+"make run-test" will do the actual tests.
If you want to create reference output files by yourself, compile
prepare.cs and run it on Microsoft.NET (it requires cygwin).
{
public class XsltTest
{
- public static void Main ()
+ static bool reportDetails;
+ static bool reportAsXml;
+ static bool useDomStyle;
+ static bool useDomInstance;
+ static bool generateOutput;
+ static bool whitespaceStyle;
+ static bool whitespaceInstance;
+ static bool stopImmediately;
+ static bool outputAll;
+ static readonly ArrayList skipTargets;
+ static string explicitTarget;
+ static TextWriter reportOutput = Console.Out;
+ static XmlTextWriter reportXmlWriter;
+
+ static XsltTest ()
{
+ skipTargets = new ArrayList (new string [] {
+"attribset15.xsl",
+"lre12.xsl",
+"namespace23.xsl", // under .NET, XPathDocument behavior is different from dom
+"namespace40.xsl",
+"namespace42.xsl",
+"namespace43.xsl",
+"namespace48.xsl",
+"namespace60.xsl",
+"namespace73.xsl",
+"namespace106.xsl",
// output22,77: not-supported encoding, but MS passes...?
// output72.xsl: should not pass
- ArrayList expectedExceptions = new ArrayList
-(new string [] {"attribset15.xsl", "lre12.xsl", "namespace40.xsl", "namespace42.xsl", "namespace43.xsl",
-"namespace48.xsl", "namespace60.xsl", "namespace73.xsl", "namespace106.xsl",
-"output22.xsl", "output72.xsl", "output77.xsl"});
+"output22.xsl",
+"output72.xsl",
+"output77.xsl"
+ });
+ }
+
+ static void Usage ()
+ {
+ Console.WriteLine (@"mono xslttest.exe [options] [targetFileMatch] -report:reportfile
+
+ Options:
+ --details : Output detailed output differences.
+ --dom : use XmlDocument for both stylesheet and input source.
+ --domxsl : use XmlDocument for stylesheet.
+ --domsrc : use XmlDocument for input source.
+ --generate : generate output files specified in catalog.
+ Use this feature only when you want to update
+ reference output.
+ --outall : Output fine results as OK (omitted by default).
+ --stoponerror : stops the test process and throw detailed
+ error if happened.
+ --ws : preserve spaces for both stylesheet and input source.
+ --wsxsl : preserve spaces for stylesheet.
+ --wssrc : preserve spaces for input source.
+ --xml : report into xml output.
+ --report : write reports into specified file.
+
+ FileMatch:
+ arbitrary string that specifies part of file name.
+ (no * or ? available)
+");
+ }
+
+ public static void Main (string [] args)
+ {
+ try {
+ RunMain (args);
+ } catch (Exception ex) {
+ reportOutput.WriteLine (ex);
+ } finally {
+ reportOutput.Close ();
+ }
+ }
+
+ static void RunMain (string [] args)
+ {
+ foreach (string arg in args) {
+ switch (arg) {
+ case "-?":
+ Usage ();
+ return;
+ case "--dom":
+ useDomStyle = true;
+ useDomInstance = true;
+ break;
+ case "--domxsl":
+ useDomStyle = true;
+ break;
+ case "--domsrc":
+ useDomInstance = true;
+ break;
+ case "--details":
+ reportDetails = true;
+ break;
+ case "--generate":
+ generateOutput = true;
+ break;
+ case "--outall":
+ outputAll = true;
+ break;
+ case "--stoponerror":
+ stopImmediately = true;
+ break;
+ case "--ws":
+ whitespaceStyle = true;
+ whitespaceInstance = true;
+ break;
+ case "--wsxsl":
+ whitespaceStyle = true;
+ break;
+ case "--wssrc":
+ whitespaceInstance = true;
+ break;
+ case "--xml":
+ reportAsXml = true;
+ break;
+ default:
+ if (arg.StartsWith ("--report:")) {
+ string reportFile = arg.Substring (9);
+ if (reportFile.Length < 0) {
+ Usage ();
+ Console.WriteLine ("Error: --report option requires filename.");
+ return;
+ }
+ reportOutput = new StreamWriter (reportFile);
+ break;
+ }
+ if (arg.StartsWith ("--")) {
+ Usage ();
+ return;
+ }
+ explicitTarget = arg;
+ break;
+ }
+ }
+
+ if (reportAsXml) {
+ reportXmlWriter = new XmlTextWriter (reportOutput);
+ reportXmlWriter.Formatting = Formatting.Indented;
+ reportXmlWriter.WriteStartElement ("test-results");
+ }
+
+ if (explicitTarget != null)
+ Console.WriteLine ("The specified target is "
+ + explicitTarget);
XmlDocument whole = new XmlDocument ();
whole.Load (@"testsuite/TESTS/Xalan_Conformance_Tests/catalog.xml");
-Console.WriteLine ("Started: " + DateTime.Now.ToString ("yyyyMMdd-HHmmss.fff"));
- foreach (XmlElement testCase in whole.SelectNodes ("test-suite/test-catalog/test-case")) {
+
+ Console.WriteLine ("Started: " +
+ DateTime.Now.ToString ("yyyyMMdd-HHmmss.fff"));
+
+ foreach (XmlElement testCase in whole.SelectNodes (
+ "test-suite/test-catalog/test-case")) {
string stylesheetBase = null;
try {
string filePath = testCase.SelectSingleNode ("file-path").InnerText;
string path = @"testsuite/TESTS/Xalan_Conformance_Tests/" + filePath + "/";
- foreach (XmlElement scenario in testCase.SelectNodes ("scenario")) {
- XslTransform trans = new XslTransform ();
- stylesheetBase = scenario.SelectSingleNode ("input-file[@role='principal-stylesheet']").InnerText;
- string stylesheet = path + stylesheetBase;
- string srcxml = path + scenario.SelectSingleNode ("input-file[@role='principal-data']").InnerText;
-//if (srcxml.IndexOf ("attribset") < 0)
-// continue;
-if (expectedExceptions.Contains (stylesheetBase))
- continue;
- XmlTextReader stylextr = new XmlTextReader (stylesheet);
- XmlValidatingReader stylexvr = new XmlValidatingReader (stylextr);
-// XmlDocument styledoc = new XmlDocument ();
-// styledoc.Load (stylesheet);
- trans.Load (stylesheet);
-// trans.Load (styledoc);
- XmlTextReader xtr = new XmlTextReader (srcxml);
- XmlValidatingReader xvr = new XmlValidatingReader (xtr);
- xvr.ValidationType = ValidationType.None;
-// XmlDocument input = new XmlDocument ();
-// input.Load (xvr);
-// input.Load (xtr);
- XPathDocument input = new XPathDocument (xvr);
- StringWriter sw = new StringWriter ();
- trans.Transform (input, null, sw);
- string outfile = path + scenario.SelectSingleNode ("output-file[@role='principal']").InnerText;
- if (!File.Exists (outfile)) {
-// Console.WriteLine ("Reference output file does not exist.");
- continue;
- }
- StreamReader sr = new StreamReader (outfile);
- string reference_out = sr.ReadToEnd ();
- string actual_out = sw.ToString ();
- if (reference_out != actual_out)
-#if true
- Console.WriteLine ("Different: " + testCase.GetAttribute ("id"));
-#else
- Console.WriteLine ("Different: " +
- testCase.GetAttribute ("id") +
- "\n" +
- actual_out + "\n-------------------\n" + reference_out + "\n");
-#endif
+ foreach (XmlElement scenario in
+ testCase.SelectNodes ("scenario")) {
+ RunTest (scenario, path, stylesheetBase);
}
-// } catch (NotSupportedException ex) {
} catch (Exception ex) {
- if (expectedExceptions.Contains (stylesheetBase))
+ if (skipTargets.Contains (stylesheetBase))
continue;
- Console.WriteLine ("Exception: " + testCase.GetAttribute ("id") + ": " + ex.Message);
+ if (stopImmediately)
+ throw;
+ Report (testCase, "Exception: " + testCase.GetAttribute ("id") + ": " + ex.Message);
}
}
Console.WriteLine ("Finished: " + DateTime.Now.ToString ("yyyyMMdd-HHmmss.fff"));
+ if (reportAsXml)
+ reportXmlWriter.WriteEndElement (); // test-results
+ }
+
+ static void RunTest (XmlElement scenario, string path, string stylesheetBase)
+ {
+ XslTransform trans = new XslTransform ();
+ stylesheetBase = scenario.SelectSingleNode ("input-file[@role='principal-stylesheet']").InnerText;
+ string stylesheet = path + stylesheetBase;
+ string srcxml = path + scenario.SelectSingleNode ("input-file[@role='principal-data']").InnerText;
+
+ if (explicitTarget != null && stylesheetBase.IndexOf (explicitTarget) < 0)
+ return;
+ if (skipTargets.Contains (stylesheetBase))
+ return;
+
+ XmlTextReader stylextr = new XmlTextReader (stylesheet);
+ XmlValidatingReader stylexvr = new XmlValidatingReader (stylextr);
+ if (useDomStyle) {
+ XmlDocument styledoc = new XmlDocument ();
+ if (whitespaceStyle)
+ styledoc.PreserveWhitespace = true;
+ styledoc.Load (stylesheet);
+ trans.Load (styledoc);
+ } else
+ trans.Load (new XPathDocument (
+ stylesheet,
+ whitespaceStyle ? XmlSpace.Preserve :
+ XmlSpace.Default));
+
+ string outfile = path + scenario.SelectSingleNode ("output-file[@role='principal']").InnerText;
+
+ XmlTextReader xtr = new XmlTextReader (srcxml);
+ XmlValidatingReader xvr = new XmlValidatingReader (xtr);
+ xvr.ValidationType = ValidationType.None;
+ IXPathNavigable input = null;
+ if (useDomInstance) {
+ XmlDocument dom = new XmlDocument ();
+ if (whitespaceInstance)
+ dom.PreserveWhitespace = true;
+ dom.Load (xvr);
+ input = dom;
+ } else {
+ input = new XPathDocument (xvr,
+ whitespaceStyle ? XmlSpace.Preserve :
+ XmlSpace.Default);
+ }
+ StringWriter sw = new StringWriter ();
+ trans.Transform (input, null, sw);
+ if (generateOutput) {
+ StreamWriter fw = new StreamWriter (outfile,
+ false, Encoding.UTF8);
+ fw.Write (sw.ToString ());
+ fw.Close ();
+ // ... and don't run comparison
+ return;
+ }
+
+ if (!File.Exists (outfile)) {
+ // Reference output file does not exist.
+ return;
+ }
+ StreamReader sr = new StreamReader (outfile);
+ string reference_out = sr.ReadToEnd ();
+ string actual_out = sw.ToString ();
+ if (reference_out != actual_out)
+ Report (scenario.ParentNode as XmlElement,
+ reference_out, actual_out);
+ else if (outputAll)
+ Report (scenario.ParentNode as XmlElement,
+ "OK");
+ }
+
+ static void Report (XmlElement testcase, string message)
+ {
+ if (reportAsXml) {
+ reportXmlWriter.WriteStartElement ("testcase");
+ reportXmlWriter.WriteAttributeString ("id",
+ testcase.GetAttribute ("id"));
+ reportXmlWriter.WriteString (message);
+ reportXmlWriter.WriteEndElement ();
+ }
+ else
+ reportOutput.WriteLine (message);
+ }
+
+ static void Report (XmlElement testCase,
+ string reference_out, string actual_out)
+ {
+ string baseMessage = reportAsXml ? "Different." :
+ "Different: " + testCase.GetAttribute ("id");
+ if (!reportDetails)
+ Report (testCase, baseMessage);
+ else
+ Report (testCase, baseMessage +
+ "\n Actual*****\n" +
+ actual_out +
+ "\n-------------------\nReference*****\n" +
+ reference_out +
+ "\n");
}
}
}
+2004-12-03 Geoff Norton <gnorton@customerdna.com>
+
+ * System.IO/SearchPattern.cs: Have IsMatch(string)
+ call IsMatch(string, bool) to avoid setting a instance variable in a
+ method that logically should not be changing it.
+
+2004-12-02 Geoff Norton <gnorton@customerdna.com>
+
+ * System.IO/KeventWatcher.cs: Add IDisposable to our kevent struct
+ so the disposer gets called. Fixes a small memory leak. Dont monitor
+ LastAccessedTime for changed files, as this will cause AppUnloading in XSP
+ when global.asax is accessed after creation. Use a case-insensitive IsMatch
+ to deal with OSX Case-aware/Case-insensitive filesystem.
+ * System.IO/SearchPattern.cs: Add a overload to IsMatch to explicitly set
+ the ignore field for OSX case-aware yet case-insensitive filesystem. This
+ allows monitoring of global.asax to happen properly.
+
2004-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* System_test.dll.sources: added CookieContainerTest.cs.
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * DeflateStream.cs, GzipStream.cs, CompressionMode.cs: Make class public.
+
2004-11-10 Martin Baulig <martin@ximian.com>
* DeflateStream.cs, GzipStream.cs: `System.IO.Stream.Length' doesn't
#if NET_2_0
namespace System.IO.Compression {
- enum CompressionMode {
+ public enum CompressionMode {
Decompress=0, // Decompress the given stream.
Compress=1 // Compress the given stream.
};
using System.Runtime.Remoting.Messaging;
namespace System.IO.Compression {
- class DeflateStream : Stream
+ public class DeflateStream : Stream
{
private Stream compressedStream;
private CompressionMode mode;
using System.Runtime.Remoting.Messaging;
namespace System.IO.Compression {
- class GzipStream : Stream
+ public class GzipStream : Stream
{
private DeflateStream deflateStream;
namespace System.IO {
- struct kevent {
+ struct kevent : IDisposable {
public int ident;
public short filter;
public ushort flags;
foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
if (data.DirEntries.ContainsKey (fsi.FullName) && (fsi is FileInfo)) {
KeventFileData entry = (KeventFileData) data.DirEntries [fsi.FullName];
- if ( (entry.LastWriteTime != fsi.LastWriteTime) || (entry.LastAccessTime != fsi.LastAccessTime) ) {
+ if (entry.LastWriteTime != fsi.LastWriteTime) {
filename = fsi.Name;
fa = FileAction.Modified;
data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
}
}
- if (!fsw.Pattern.IsMatch(filename))
+ if (!fsw.Pattern.IsMatch(filename, true))
return;
lock (fsw) {
Compile (pattern);
}
- public bool IsMatch (string text)
+ // OSX has a retarded case-insensitive yet case-aware filesystem
+ // so we need a overload in here for the Kqueue watcher
+ public bool IsMatch (string text, bool ignorecase)
{
if (!hasWildcard)
- return (String.Compare (pattern, text, ignore) == 0);
+ return (String.Compare (pattern, text, ignorecase) == 0);
return Match (ops, text, 0);
}
+ public bool IsMatch (string text)
+ {
+ return IsMatch (text, ignore);
+ }
+
public bool HasWildcard {
get { return hasWildcard; }
}
+2004-12-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * NetworkStream.cs: Write should ensure that writes all the contents
+ of the buffer. Fixes bug #70123. Besos para Miguelito.
+
2004-10-14 Dick Porter <dick@ximian.com>
* Socket.cs (Sockets ): Set Accept()ed socket blocking status to
try {
retval = socket.BeginReceive (buffer, offset, size, 0, callback, state);
- } catch {
- throw new IOException ("BeginReceive failure");
+ } catch (Exception e) {
+ throw new IOException ("BeginReceive failure", e);
}
return retval;
throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
try {
- socket.Send (buffer, offset, size, 0);
+ int count = 0;
+ while (size - count > 0) {
+ count += socket.Send (buffer, offset + count, size - count, 0);
+ }
} catch (Exception e) {
throw new IOException ("Write failure", e);
}
+2004-12-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * WebConnection.cs: handle errors on chunked streams. Fixes bug #66858.
+ * ChunkStream.cs: added error checking all over.
+
+ * HttpWebRequest.cs: throw the exception received in SetResponseError
+ if we already have a response.
+ (SetRequestData): Don't nest the exception if it's a WebException.
+
+2004-12-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * WebConnection.cs: remove prevStream and don't set busy to false in
+ HandleError. prevStream is not needed any more and setting 'busy' so
+ early might let a request skip the queue.
+
+ * WebConnectionGroup.cs: decrement the indexer when removing a dead
+ reference from the arraylist.
+
+ * WebConnectionStream.cs:
+ (ReadAll): call NextRead if it has not been called before even when
+ we have completed the request. Reuse the read buffer when reading a
+ response of unknown size. Increase the buffer to 8kB.
+ (BeginRead): increase pendingReads earlier and even when reading from
+ the internal buffer.
+ (EndRead): decrease pendingReads later and always.
+
2004-12-01 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* CookieContainer.cs: style, fixed checks for properties, implemented
public void WriteAndReadBack (byte [] buffer, int offset, int size, ref int read)
{
- Write (buffer, offset, offset+read);
+ if (offset + read > 0)
+ Write (buffer, offset, offset+read);
read = Read (buffer, offset, size);
}
c = (char) buffer [offset++];
if (c == '\r') {
if (sawCR)
- throw new ProtocolViolationException ("2 CR found");
+ ThrowProtocolViolation ("2 CR found");
sawCR = true;
continue;
if (!gotit)
saved.Append (c);
+
+ if (saved.Length > 20)
+ ThrowProtocolViolation ("chunk size too long.");
}
- if (!sawCR || c != '\n')
+ if (!sawCR || c != '\n') {
+ if (offset < size)
+ ThrowProtocolViolation ("Missing \\n");
+
+ try {
+ if (saved.Length > 0)
+ chunkSize = Int32.Parse (saved.ToString (), NumberStyles.HexNumber);
+ } catch (Exception) {
+ ThrowProtocolViolation ("Cannot parse chunk size.");
+ }
+
return State.None;
+ }
chunkRead = 0;
- chunkSize = Int32.Parse (saved.ToString (), NumberStyles.HexNumber);
+ try {
+ chunkSize = Int32.Parse (saved.ToString (), NumberStyles.HexNumber);
+ } catch (Exception) {
+ ThrowProtocolViolation ("Cannot parse chunk size.");
+ }
+
if (chunkSize == 0)
return State.Trailer;
{
if (!sawCR) {
if ((char) buffer [offset++] != '\r')
- throw new ProtocolViolationException ("Expecting \\r");
+ ThrowProtocolViolation ("Expecting \\r");
sawCR = true;
if (offset == size)
return State.BodyFinished;
}
- if ((char) buffer [offset++] != '\n')
- throw new ProtocolViolationException ("Expecting \\n");
+ if (sawCR && (char) buffer [offset++] != '\n')
+ ThrowProtocolViolation ("Expecting \\n");
return State.None;
}
}
}
- if (st < 4)
+ if (st < 4) {
+ if (offset < size)
+ ThrowProtocolViolation ("Error reading trailer.");
+
return State.Trailer;
+ }
StringReader reader = new StringReader (saved.ToString ());
string line;
return State.None;
}
+
+ static void ThrowProtocolViolation (string message)
+ {
+ WebException we = new WebException (message, null, WebExceptionStatus.ServerProtocolViolation, null);
+ throw we;
+ }
}
}
internal void SetResponseError (WebExceptionStatus status, Exception e, string where)
{
+ string msg = String.Format ("Error getting response stream ({0}): {1}", where, status);
+ if (webResponse != null) {
+ if (e is WebException)
+ throw e;
+ throw new WebException (msg, e, status, null);
+ }
+
WebAsyncResult r = asyncRead;
if (r == null)
r = asyncWrite;
if (r != null) {
- string msg = String.Format ("Error getting response stream ({0}): {1}", where, status);
- WebException wexc = new WebException (msg, e, status, null);
+ WebException wexc;
+ if (e is WebException) {
+ wexc = (WebException) e;
+ } else {
+ wexc = new WebException (msg, e, status, null);
+ }
r.SetCompleted (false, wexc);
r.DoCallback ();
asyncRead = null;
EventHandler abortHandler;
ReadState readState;
internal WebConnectionData Data;
- WebConnectionStream prevStream;
bool chunkedRead;
ChunkStream chunkStream;
AutoResetEvent goAhead;
while (true) {
int n = stream.Read (buffer, 0, 256);
+ if (n == 0) {
+ HandleError (WebExceptionStatus.ServerProtocolViolation, null, "ReadHeders");
+ return false;
+ }
+
ms.Write (buffer, 0, n);
int start = 0;
string str = null;
{
status = st;
lock (this) {
- busy = false;
if (st == WebExceptionStatus.RequestCanceled)
Data = new WebConnectionData ();
}
stream.ReadBufferOffset = pos;
stream.ReadBufferSize = nread;
} else if (cnc.chunkStream == null) {
- cnc.chunkStream = new ChunkStream (cnc.buffer, pos, nread, data.Headers);
+ try {
+ cnc.chunkStream = new ChunkStream (cnc.buffer, pos, nread, data.Headers);
+ } catch (Exception e) {
+ cnc.HandleError (WebExceptionStatus.ServerProtocolViolation, e, "ReadDone5");
+ return;
+ }
} else {
cnc.chunkStream.ResetBuffer ();
- cnc.chunkStream.Write (cnc.buffer, pos, nread);
+ try {
+ cnc.chunkStream.Write (cnc.buffer, pos, nread);
+ } catch (Exception e) {
+ cnc.HandleError (WebExceptionStatus.ServerProtocolViolation, e, "ReadDone6");
+ return;
+ }
}
data.stream = stream;
if (cnc.queue.Count > 0) {
stream.ReadAll ();
} else {
- cnc.prevStream = stream;
stream.CheckComplete ();
}
}
internal EventHandler SendRequest (HttpWebRequest request)
{
lock (this) {
- if (prevStream != null && socket != null && socket.Connected) {
- prevStream.ReadAll ();
- prevStream = null;
- }
-
if (!busy) {
busy = true;
ThreadPool.RegisterWaitForSingleObject (goAhead, initConn,
{
lock (queue) {
if (queue.Count > 0) {
- prevStream = null;
SendRequest ((HttpWebRequest) queue.Dequeue ());
}
}
goAhead.Set ();
lock (queue) {
if (queue.Count > 0) {
- prevStream = null;
SendRequest ((HttpWebRequest) queue.Dequeue ());
}
}
try {
result = nstream.BeginRead (buffer, offset, size, cb, state);
} catch (Exception) {
- status = WebExceptionStatus.ReceiveFailure;
+ HandleError (WebExceptionStatus.ReceiveFailure, null, "chunked BeginRead");
throw;
}
}
if (wr.InnerAsyncResult != null)
nbytes = nstream.EndRead (wr.InnerAsyncResult);
- chunkStream.WriteAndReadBack (wr.Buffer, wr.Offset, wr.Size, ref nbytes);
- while (nbytes == 0 && chunkStream.WantMore) {
- int size = chunkStream.ChunkLeft;
- if (size <= 0) // not read chunk size yet
- size = 1024;
- else if (size > 16384)
- size = 16384;
-
- byte [] morebytes = new byte [size];
- int nread;
- nread = nstream.Read (morebytes, 0, size);
- chunkStream.Write (morebytes, 0, nread);
- morebytes = null;
- nbytes += chunkStream.Read (wr.Buffer, wr.Offset + nbytes,
- wr.Size - nbytes);
+ bool done = (nbytes == 0);
+ try {
+ chunkStream.WriteAndReadBack (wr.Buffer, wr.Offset, wr.Size, ref nbytes);
+ if (!done && nbytes == 0 && chunkStream.WantMore)
+ nbytes = EnsureRead (wr.Buffer, wr.Offset, wr.Size);
+ } catch (Exception e) {
+ if (e is WebException)
+ throw e;
+
+ throw new WebException ("Invalid chunked data.", e,
+ WebExceptionStatus.ServerProtocolViolation, null);
}
+
+ if ((done || nbytes == 0) && chunkStream.WantMore) {
+ HandleError (WebExceptionStatus.ReceiveFailure, null, "chunked EndRead");
+ throw new WebException ("Read error", null, WebExceptionStatus.ReceiveFailure, null);
+ }
+
return nbytes;
}
return nstream.EndRead (result);
}
+ // To be called on chunkedRead when we can read no data from the ChunkStream yet
+ int EnsureRead (byte [] buffer, int offset, int size)
+ {
+ byte [] morebytes = null;
+ int nbytes = 0;
+ while (nbytes == 0 && chunkStream.WantMore) {
+ int localsize = chunkStream.ChunkLeft;
+ if (localsize <= 0) // not read chunk size yet
+ localsize = 1024;
+ else if (localsize > 16384)
+ localsize = 16384;
+
+ if (morebytes == null || morebytes.Length < localsize)
+ morebytes = new byte [localsize];
+
+ int nread = nstream.Read (morebytes, 0, localsize);
+ if (nread <= 0)
+ return 0; // Error
+
+ chunkStream.Write (morebytes, 0, nread);
+ nbytes += chunkStream.Read (buffer, offset + nbytes, size - nbytes);
+ }
+
+ return nbytes;
+ }
+
bool CompleteChunkedRead()
{
if (!chunkedRead || chunkStream == null)
int nbytes = nstream.Read (buffer, 0, buffer.Length);
if (nbytes <= 0)
return false; // Socket was disconnected
- chunkStream.Write(buffer, 0, nbytes);
+
+ chunkStream.Write (buffer, 0, nbytes);
}
return true;
int result = 0;
try {
- if (!chunkedRead || chunkStream.WantMore)
+ bool done = false;
+ if (!chunkedRead) {
result = nstream.Read (buffer, offset, size);
+ done = (result == 0);
+ }
+
+ if (chunkedRead) {
+ try {
+ chunkStream.WriteAndReadBack (buffer, offset, size, ref result);
+ if (!done && result == 0 && chunkStream.WantMore)
+ result = EnsureRead (buffer, offset, size);
+ } catch (Exception e) {
+ HandleError (WebExceptionStatus.ReceiveFailure, e, "chunked Read1");
+ throw;
+ }
- if (chunkedRead)
- chunkStream.WriteAndReadBack (buffer, offset, size, ref result);
+ if ((done || result == 0) && chunkStream.WantMore) {
+ HandleError (WebExceptionStatus.ReceiveFailure, null, "chunked Read2");
+ throw new WebException ("Read error", null, WebExceptionStatus.ReceiveFailure, null);
+ }
+ }
} catch (Exception e) {
HandleError (WebExceptionStatus.ReceiveFailure, e, "Read");
}
if (cnc == null) {
connections.RemoveAt (i);
count--;
+ i--;
continue;
}
internal void ReadAll ()
{
- if (!isRead || totalRead >= contentLength || nextReadCalled)
+ if (!isRead || totalRead >= contentLength || nextReadCalled) {
+ if (!nextReadCalled) {
+ nextReadCalled = true;
+ cnc.NextRead ();
+ }
return;
+ }
pending.WaitOne ();
lock (this) {
if (contentLength == Int32.MaxValue) {
MemoryStream ms = new MemoryStream ();
- if (readBuffer != null && diff > 0)
+ byte [] buffer = null;
+ if (readBuffer != null && diff > 0) {
ms.Write (readBuffer, readBufferOffset, diff);
+ if (readBufferSize >= 8192)
+ buffer = readBuffer;
+ }
+
+ if (buffer == null)
+ buffer = new byte [8192];
- byte [] buffer = new byte [2048];
int read;
- while ((read = cnc.Read (buffer, 0, 2048)) != 0)
+ while ((read = cnc.Read (buffer, 0, buffer.Length)) != 0)
ms.Write (buffer, 0, read);
b = ms.GetBuffer ();
if (size < 0 || offset < 0 || length < offset || length - offset < size)
throw new ArgumentOutOfRangeException ();
+ lock (this) {
+ pendingReads++;
+ pending.Reset ();
+ }
+
WebAsyncResult result = new WebAsyncResult (cb, state, buffer, offset, size);
if (totalRead >= contentLength) {
result.SetCompleted (true, -1);
result.NBytes = copy;
}
- lock (this) {
- pendingReads++;
- pending.Reset ();
- }
-
if (cb != null)
cb = new AsyncCallback (CallbackWrapper);
if (!result.IsCompleted) {
int nbytes = cnc.EndRead (result.InnerAsyncResult);
- lock (this) {
- pendingReads--;
- if (pendingReads == 0)
- pending.Set ();
- }
-
bool finished = (nbytes == -1);
if (finished && result.NBytes > 0)
nbytes = 0;
contentLength = totalRead;
}
- if (totalRead >= contentLength && !nextReadCalled) {
- nextReadCalled = true;
- cnc.NextRead ();
+ lock (this) {
+ pendingReads--;
+ if (pendingReads == 0)
+ pending.Set ();
}
+ if (totalRead >= contentLength && !nextReadCalled)
+ ReadAll ();
+
return result.NBytes;
}
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * System.IO.Compression/GzipStreamTest.cs: Fix compile errors.
+ * System.IO.Compression/GzipStreamTest.cs: Likewise.
+
2004-10-04 Raja R Harinath <rharinath@novell.com>
* System.IO.Compression/DeflateStreamTest.cs: NET_2_0 only.
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * VBCodeProviderTest.cs: Change namespace to
+ MonoTests.Microsoft.VisualBasic.
+
2004-11-19 Raja R Harinath <rharinath@novell.com>
* VBCodeProviderTest.cs (CreateCompiler): Be more verbose about
using System.Diagnostics;\r
using System.IO;\r
\r
-namespace MonoTests.System.Microsoft.VisualBasic\r
+namespace MonoTests.Microsoft.VisualBasic\r
{\r
\r
enum OsType {\r
}\r
\r
if (MyVBCodeCompilerResults.Errors.Count != 0) {
- System.Console.WriteLine (MyVBCodeCompilerResults);
+ Console.WriteLine (MyVBCodeCompilerResults);
Assert ("#JW31 - Hello world compilation: " + MyOutStr, false);\r
}
byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
MemoryStream backing = new MemoryStream (data);
DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
- decompressing.Length = 20;
+ decompressing.SetLength (20);
}
[Test]
byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
MemoryStream backing = new MemoryStream (data);
DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
- int length = decompressing.Length;
+ long length = decompressing.Length;
}
[Test]
byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
MemoryStream backing = new MemoryStream (data);
DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
- int position = decompressing.Position;
+ long position = decompressing.Position;
}
}
}
byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
MemoryStream backing = new MemoryStream (data);
GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
- decompressing.Length = 20;
+ decompressing.SetLength (20);
}
[Test]
byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
MemoryStream backing = new MemoryStream (data);
GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
- int length = decompressing.Length;
+ long length = decompressing.Length;
}
[Test]
byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
MemoryStream backing = new MemoryStream (data);
GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
- int position = decompressing.Position;
+ long position = decompressing.Position;
}
}
}
//
// Copyright (c) 2002 Chew Keong TAN
// All rights reserved.
-
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
r2.Normalize ();
- if (r2 < x) {
+ if (r2 <= x) {
Kernel.MinusEq (x, r2);
} else {
BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
+2004-12-03 Sebastien Pouliot <sebastien@ximian.com>
+
+ * BigInteger.cs: Fix issue #70169 in ModPow when modulus is a power of
+ two.
+
2004-10-19 Sebastien Pouliot <sebastien@ximian.com>
* BigInteger.cs: Fix issue #68452 when Randomize was being called on a
+2004-12-02 Duncan Mak <duncan@ximian.com>
+
+ * cs0122-7.cs:
+ * cs0122-8.cs: Added test cases for events, from bug #70129.
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ * cs1589.inc : plus one.
+ * Makefile : remove dummy.xml (in case of error test failures)
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ * cs1570.cs, cs1570-2.cs, cs1570-3.cs, cs1570-4.cs, cs1570-5.cs,
+ cs1570-6.cs, cs1570-7.cs, cs1570-8.cs, cs1570-9.cs, cs1570-10.cs,
+ cs1570-11.cs, cs1571.cs, cs1572.cs, cs1573.cs, cs1574.cs,
+ cs1574-2.cs, cs1574-3.cs, cs1574-4.cs, cs1574-5.cs, cs1580.cs,
+ cs1580-2.cs, cs1581.cs, cs1581-2.cs, cs1584.cs, cs1584-2.cs,
+ cs1584-3.cs, cs1584-4.cs, cs1587.cs, cs1587-2.cs, cs1587-3.cs,
+ cs1587-4.cs, cs1587-5.cs, cs1587-6.cs, cs1587-7.cs, cs1587-8.cs,
+ cs1587-9.cs, cs1587-10.cs, cs1587-11.cs, cs1587-12.cs, cs1587-13.cs,
+ cs1587-14.cs, cs1587-15.cs, cs1587-16.cs, cs1587-17.cs, cs1587-18.cs,
+ cs1587-19.cs, cs1587-20.cs, cs1587-21.cs, cs1587-22.cs, cs1587-23.cs,
+ cs1587-24.cs, cs1587-25.cs, cs1587-26.cs, cs1587-27.cs, cs1587-28.cs,
+ cs1589.cs, cs1590.cs, cs1590-2.cs, cs1590-3.cs, cs1591.cs,
+ cs1591-2.cs, cs1591-3.cs, cs1591-4.cs, cs1591-5.cs, cs1591-6.cs,
+ cs1591-7.cs, cs1591-8.cs, cs1591-9.cs, cs1591-10.cs, cs1591-11.cs,
+ cs1591-12.cs, cs1591-13.cs, cs1591-14.cs, cs1591-15.cs, cs1591-16.cs,
+ cs1591-17.cs, cs1591-18.cs, cs1592.cs : added tests for /doc feature.
+
2004-11-26 Raja R Harinath <rharinath@novell.com>
* Makefile (DISTFILES): Add do-tests.pl.
rm -f *.dll
rm -f *.log
rm -f *.mdb
+ rm -f dummy.xml
dist-local: dist-default
--- /dev/null
+// error CS0122: 'BB.AnEvent' is inaccessible due to its protection level
+
+using System;
+
+class X
+{
+ static void Main ()
+ {
+ BB b = new BB ();
+ b.AnEvent += DoIt;
+ }
+
+ public static void DoIt (object sender, EventArgs args) {}
+}
+
+public class BB
+{
+ event EventHandler AnEvent;
+}
+
--- /dev/null
+// error CS0122: 'A.AnEvent' is inaccessible due to its protection level
+//
+// NOTE: if `member' were a field or a property, this'd be CS1540
+
+using System;
+
+class A
+{
+ protected event EventHandler member;
+}
+
+class B : A
+{
+ static void Main ()
+ {
+ A a = new A ();
+ a.member += Handler;
+ }
+
+ static void Handler (object sender, EventArgs args) {}
+}
+
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for private field
+ /// </summary>
+ private string PrivateField;
+
+ /// <summary>
+ /// incorrect markup comment for private field
+ /// </incorrect>
+ private string PrivateField2;
+
+ /**
+ <summary>
+ Javadoc comment for private field
+ </summary>
+ */
+ private string PrivateField3;
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for public property
+ /// </summary>
+ public string PublicProperty {
+ /// <summary>
+ /// On public getter - no effect
+ /// </summary>
+ get { return null; }
+ /// <summary>
+ /// On public setter - no effect
+ /// </summary>
+ set { }
+ }
+
+ /// <summary>
+ /// incorrect comment for public property
+ /// </incorrect>
+ public string PublicProperty2 {
+ get { return null; }
+ }
+
+ /**
+ <summary>
+ Javadoc comment for public property
+ </summary>
+ */
+ public string PublicProperty3 {
+ /**
+ <summary>
+ On public getter - no effect
+ </summary>
+ */
+ get { return null; }
+ /**
+ <summary>
+ On public setter - no effect
+ </summary>
+ */
+ set { }
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment on class
+ /// </summary>
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+
+ /// <summary>
+ /// Incorrect comment markup.
+ /// </incorrect>
+ public class Test2
+ {
+ }
+
+ /**
+ <summary>
+ another Java-style documentation style
+ </summary>
+ */
+ public class Test3
+ {
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for struct
+ /// </summary>
+ public struct StructTest
+ {
+ }
+
+ /// <summary>
+ /// incorrect markup comment for struct
+ /// </incorrect>
+ public struct StructTest2
+ {
+ }
+
+ /**
+ <summary>
+ Java style commet
+ </summary>
+ */
+ public struct StructTest3
+ {
+ }
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for interface
+ /// </summary>
+ public interface InterfaceTest
+ {
+ }
+
+ /// <summary>
+ /// incorrect markup comment for interface
+ /// </incorrect>
+ public interface InterfaceTest2
+ {
+ }
+
+ /**
+ <summary>
+ Java style comment for interface
+ </summary>
+ */
+ public interface InterfaceTest3
+ {
+ }
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for enum type
+ /// </incorrect>
+ enum EnumTest2
+ {
+ Foo,
+ Bar,
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for delegate type
+ /// </summary>
+ public delegate void MyDelegate (object o, EventArgs e);
+
+ /// <summary>
+ /// comment for delegate type
+ /// </incorrect>
+ public delegate void MyDelegate2 (object o, EventArgs e);
+
+ /**
+ <summary>
+ Javadoc comment for delegate type
+ </summary>
+ */
+ public delegate void MyDelegate3 (object o, EventArgs e);
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ /// comment without markup on class - it is allowed
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+
+ /// <6roken> broken markup
+ public class Test2
+ {
+ }
+
+ /// <dont-forget-close-tag>
+ public class Test3
+ {
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ /// <summary>
+ /// comment for const declaration
+ /// </summary>
+ const string Constant = "CONSTANT STRING";
+
+ /// <summary>
+ /// invalid comment for const declaration
+ /// </invalid>
+ const string Constant2 = "CONSTANT STRING";
+
+ /**
+ <summary>
+ Javaism comment for const declaration
+ </summary>
+ */
+ const string Constant3 = "CONSTANT STRING";
+
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:1 -warnaserror
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ /// <summary>
+ /// comment for public field
+ /// </summary>
+ public string PublicField;
+
+ /// <summary>
+ /// comment for public field
+ /// </invalid>
+ public string PublicField2;
+
+ /**
+ <summary>
+ Javadoc comment for public field
+ </summary>
+ */
+ public string PublicField3;
+
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment on class
+ /// </summary>
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+
+ /// <summary>
+ /// Incorrect comment markup.
+ /// </incorrect>
+ public class Test2
+ {
+ }
+
+ /**
+ <summary>
+ another Java-style documentation style
+ </summary>
+ */
+ public class Test3
+ {
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:2 -warnaserror
+namespace Testing
+{
+ /// test class
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <param>anonymous</param>
+ public void Foo (int i) {}
+
+ /// <param name='i'>correct</param>
+ /// <param name='i'>duplicate</param>
+ public void Bar (int i) {}
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:2 -warnaserror
+namespace Testing
+{
+ /// test class
+ public class Test
+ {
+ /// <param name='mismatch'>mismatch</param>
+ public void Baz (int i) {}
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warn:4 -warnaserror
+namespace Testing
+{
+ /// test class
+ public class Test
+ {
+ /// <param name='i'>correct</param>
+ public void Baz (int i, int j) {}
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+/// <seealso cref="Method(System.String)"/>
+public class Test
+{
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+/// <see cref="Test.Foo(int)"/> Test has Foo, but is property that has no args.
+public class Test
+{
+ string Foo {
+ get { return null; }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -noconfig
+using System;
+
+/// <seealso cref="System.Xml.XmlDocument"/>
+/// with /noconfig, it cannot be resolved.
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+/// <see cref="Goo"/> ... does not exist
+public class Test
+{
+ string Foo {
+ get { return null; }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <seealso cref="explicit operator int (bool)"/>
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <see cref="Method(x,y)"/>
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <seealso cref="Foo(x)"/>
+public class Test
+{
+ int Foo ()
+ {
+ return 0;
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <seealso cref="explicit operator int (Test)"/>
+public class Test
+{
+ /// operator.
+ public static explicit operator int [] (Test t)
+ {
+ return new int [0];
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <seealso cref="explicit operator intp (Test)"/>
+public class Test
+{
+ /// operator.
+ public static explicit operator int (Test t)
+ {
+ return 0;
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+/// <see cref="" />
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+
+/// <see cref="." />
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <see cref="Mai()n" />
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:1
+using System;
+/// <seealso cref="operator foo(int,Test)"/>
+public class Test
+{
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ [Flags/** here is also incorrect comment */]
+ enum Enum2 {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ namespace ChildNS {
+ [Flags]
+ /// comment after attribute
+ enum Enum2 {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ enum Enum3 {
+ Foo /** invalid comment between enum identifier and comma */,
+ Bar
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ namespace ChildNS {
+ enum Enum3 {
+ }
+ /// invalid here
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ internal /** comment */ /** comment2 */ class Hoge
+ {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ internal class Hoge
+ {
+ /// invalid comment
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ string this [string bar] {
+ /// incorrect
+ get { return ""; }
+ set { }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ string this [string bar] {
+ get { /** incorrect */ return ""; }
+ set { }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ string this [string bar] {
+ get { return ""; }
+ /// incorrect
+ set { }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ string this [string bar] {
+ get { return ""; }
+ set { /** incorrect */ }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+/// invalid comment on global attributes.
+[assembly:System.CLSCompliant (true)]
+
+enum Foo {
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ public /// incorrect
+ void FooBar (string foo)
+ {
+ }
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ void /// incorrect
+ FooBar (string foo)
+ {
+ }
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ Foo /** incorrect */ ()
+ {
+ }
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ static /// incorrect
+ Foo ()
+ {
+ }
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ Foo (/** incorrect doccomment*/ string foo)
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ Foo (string foo)
+ {
+ /** incorrect doccomment*/
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ public /** invalid comment in field decl */ int field;
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ class Foo
+ {
+ public /** invalid comment in property decl */ int prop {
+ get { return 0; }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ abstract class AFoo
+ {
+ internal abstract int Prop { get; }
+ }
+
+ class Foo : AFoo
+ {
+ sealed /** is "sealed" checked? */ internal override int Prop {
+ get { return 0; }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+[Flags]
+/// invalid comment between attributes and type declaration.
+enum Foo {
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+/// invalid comment placed on namespace.
+namespace TopNS
+{
+ class Foo
+ {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+/// invalid comment on using directive inside namespace.
+using System.Xml;
+
+ enum Foo {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+/// invalid comment on using alias directive.
+using Hoge = System.Xml.XmlDocument;
+
+namespace TopNS
+{
+
+ enum Foo {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+/// invalid comment on using alias directive inside namespace.
+using Hoge = System.Xml.XmlDocument;
+
+ enum Foo {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+ /// more invalid comment on namespace; inside namespace
+ namespace ChildNS {
+ class Test {
+ }
+ }
+
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+using System;
+
+namespace TopNS
+{
+}
+
+/// EOF
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:2
+/// invalid comment placed on namespace.
+using System;
+enum Foo {
+}
--- /dev/null
+// Compiler options: -doc:xml-025.xml -warn:1 -warnaserror
+
+namespace Testing
+{
+ /// <include file='cs1589.inc' path='/foo' />
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <include file='cs1589.inc' path='/root/@attr'/>
+ public string S3;
+ }
+}
+
--- /dev/null
+<root attr='is attribute allowed?'>
+ includes XML markup.
+ <child>test</child>
+ <child>test2</child>
+</root>
--- /dev/null
+// Compiler options: -doc:xml-024.xml -warn:1 -warnaserror
+// Invalid XML 'include' element; Missing 'path' attribute
+
+namespace Testing
+{
+ /// comment
+ public class Test
+ {
+ /// <include file='a' />
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:xml-024.xml -warn:1 -warnaserror
+// Invalid XML 'include' element; Missing 'file' attribute
+
+namespace Testing
+{
+ /// comment
+ public class Test
+ {
+ /// comment
+ public static void Main ()
+ {
+ }
+
+ /// <include path='/foo/bar' />
+ public void Bar (int x)
+ {
+ }
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:xml-024.xml -warn:1 -warnaserror
+// CS1590: Invalid XML 'include' element; Missing 'file' attribute.
+
+namespace Testing
+{
+ /// <include/>
+ public class Test
+ {
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public static void Foo ()
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for interface IFoo
+ /// </summary>
+ public interface IFoo
+ {
+ void Foo ();
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for interface IFoo
+ /// </summary>
+ public interface IFoo
+ {
+ string Foo { get; }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public string this [int i] {
+ get { return null; }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public static bool operator ! (Test t)
+ {
+ return false;
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public Test ()
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ ~Test ()
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ protected class InternalClass
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public struct InternalStruct
+ {
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ public interface InterfaceTest
+ {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ public enum Foo
+ {
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// comment is here.
+ public enum Foo
+ {
+ Foo,
+ /// required for all enum members
+ Bar
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ public delegate void MyDelegate (object o, EventArgs e);
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public const string Constant = "CONSTANT STRING";
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public string PublicField;
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public string PublicProperty {
+ get { return null; }
+ }
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ public event EventHandler MyEvent;
+ }
+}
--- /dev/null
+// Compiler options: -doc:dummy.xml -warnaserror -warn:4
+using System;
+
+namespace Testing
+{
+ public class TestClass
+ {
+ }
+}
+
--- /dev/null
+// Compiler options: -doc:xml-024.xml -warn:1 -warnaserror
+// Badly formed XML in included comments file -- 'there-is-no-such-file'
+
+namespace Testing
+{
+ /// blah
+ public class Test
+ {
+ // warning
+ /// <include file='there-is-no-such-file' path='/foo/bar' />
+ public void Baz (int x)
+ {
+ }
+ }
+}
+
gcs0308-2.cs
gcs0308-3.cs
gcs0308.cs
+gcs0080.cs
+gcs0305-4.cs
+gcs0692.cs
+gcs0694.cs
+gcs1644-2.cs
cs0576.cs
cs0580.cs
-cs0647-3.cs #64225
-
#
# These bugs are new in gmcs
#
cs0162.cs
cs0249.cs
cs0541.cs
-cs0560.cs
cs0611-2.cs
cs0611.cs
-cs0647-2.cs
cs0652.cs
cs1035.cs
cs1040.cs
cs2023.cs
+cs1570-10.cs
+cs1570-11.cs
+cs1570-2.cs
+cs1570-3.cs
+cs1570-4.cs
+cs1570-6.cs
+cs1570-7.cs
+cs1570-8.cs
+cs1570-9.cs
+cs1570.cs
+cs1571.cs
+cs1589.cs
+cs1590-2.cs
+cs1590-3.cs
+cs1650.cs
+cs1660.cs
+cs1690-2.cs
+cs1690-3.cs
+cs1690.cs
cs0548-3.cs
cs0548-4.cs
cs0590-2.cs
-cs0610-3.cs
cs0620-2.cs
cs0620.cs
-cs0637.cs
cs0650.cs
cs0681.cs
cs1013.cs
cs0214-6.cs
cs0056.cs
cs0591.cs
-cs0715.cs
+cs0208-3.cs
+cs0260.cs
+cs0261.cs
+cs0262.cs
+cs0275.cs
+cs0538-2.cs
+cs0538.cs
+cs0560.cs
+cs0657-19.cs
+cs0664-2.cs
+cs1570-5.cs
+cs1572.cs
+cs1573.cs
+cs1574-2.cs
+cs1574-3.cs
+cs1574-4.cs
+cs1574-5.cs
+cs1574.cs
+cs1580-2.cs
+cs1580.cs
+cs1581-2.cs
+cs1581.cs
+cs1584-2.cs
+cs1584-3.cs
+cs1584-4.cs
+cs1584.cs
+cs1587-10.cs
+cs1587-11.cs
+cs1587-12.cs
+cs1587-13.cs
+cs1587-14.cs
+cs1587-15.cs
+cs1587-16.cs
+cs1587-17.cs
+cs1587-18.cs
+cs1587-19.cs
+cs1587-2.cs
+cs1587-20.cs
+cs1587-21.cs
+cs1587-22.cs
+cs1587-23.cs
+cs1587-24.cs
+cs1587-25.cs
+cs1587-26.cs
+cs1587-27.cs
+cs1587-28.cs
+cs1587-3.cs
+cs1587-4.cs
+cs1587-5.cs
+cs1587-6.cs
+cs1587-7.cs
+cs1587-8.cs
+cs1587-9.cs
+cs1587.cs
+cs1590.cs
+cs1591-10.cs
+cs1591-11.cs
+cs1591-12.cs
+cs1591-13.cs
+cs1591-14.cs
+cs1591-15.cs
+cs1591-16.cs
+cs1591-17.cs
+cs1591-18.cs
+cs1591-2.cs
+cs1591-3.cs
+cs1591-4.cs
+cs1591-5.cs
+cs1591-6.cs
+cs1591-7.cs
+cs1591-8.cs
+cs1591-9.cs
+cs1591.cs
+cs1592.cs
+cs1632.cs
+cs1648.cs
+cs1667-5.cs
+cs1721.cs
+cs1722.cs
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ all things are for /doc support:
+
+ * doc.cs: new file that supports XML documentation generation.
+ * mcs.exe.sources: added doc.cs.
+ * driver.cs:
+ Handle /doc command line option.
+ Report error 2006 instead of 5 for missing file name for /doc.
+ Generate XML documentation when required, after type resolution.
+ * cs-tokenizer.cs:
+ Added support for picking up documentation (/// and /** ... */),
+ including a new XmlCommentState enumeration.
+ * cs-parser.jay:
+ Added lines to fill Documentation element for field, constant,
+ property, indexer, method, constructor, destructor, operator, event
+ and class, struct, interface, delegate, enum.
+ Added lines to warn incorrect comment.
+ * rootcontext.cs :
+ Added Documentation field (passed only when /doc was specified).
+ * decl.cs:
+ Added DocComment, DocCommentHeader, GenerateDocComment() and
+ OnGenerateDocComment() and some supporting private members for
+ /doc feature to MemberCore.
+ * class.cs:
+ Added GenerateDocComment() on TypeContainer, MethodCore and Operator.
+ * delegate.cs:
+ Added overriden DocCommentHeader.
+ * enum.cs:
+ Added overriden DocCommentHeader and GenerateDocComment().
+
+2004-12-01 Miguel de Icaza <miguel@ximian.com>
+
+ * cfold.cs (ConstantFold.DoConstantNumericPromotions): After
+ unwrapping the enumeration values, chain to
+ DoConstantNumericPromotions again, so we can promote things to the
+ fundamental types (takes care of enums that are bytes, sbytes).
+
+ Fixes bug #62054.
+
+2004-12-01 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType): Remove complain flag.
+ Fix long-standing bug in type-lookup. Use FindType instead of
+ LookupType when ec.ResolvingTypeTree.
+ (Attribute.ResolveType, Attribute.Resolve)
+ (Attribute.DefinePInvokeMethod,GlobalAttribute.CheckAttributeType):
+ Update to changes.
+ (Attributes.Search): Remove internal version. Update.
+ (Attributes.SearchMulti): Update.
+ (Attributes.GetClsCompliantAttribute): Remove.
+ (Attributes.GetIndexerNameAttribute): Remove.
+ * decl.cs (MemberCore.GetClsCompliantAttributeValue): Update to changes.
+ (DeclSpace.GetClsCompliantAttributeValue): Likewise.
+ * class.cs (Indexer.Define): Likewise.
+
+2004-12-01 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #68790
+ * ecore.cs: CheckMarshallByRefAccess new virtual method for testing
+ MarshallByReference members access.
+
+ * expression.cs: Use CheckMarshallByRefAccess;
+ Better error CS0197 message.
+
+ * report.cs: Print whole related error message.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ * class (GetClassBases): Better error 60 report.
+ (EventProperty): Disabled warning 67 detection.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #60324
+ * cfold.cs (Assign.DoResolve): Add subtraction for DecimalConstant.
+
+ * constant.cs (DecimalConstant.Emit): Don't use int ctor for
+ precise values.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #49488
+ * assign.cs (Assign.DoResolve): Add error 1648, 1650 report.
+
+ * decl.cs (MemberCore.MemberName): Error 1648 in compiler.
+
+2004-11-26 Miguel de Icaza <miguel@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): Refine error reporting and
+ report a cs0117 if the identifier does not exist, to distinguish
+ from 0617 which is a miss-use of the actual identifier.
+
+ * ecore.cs (EventExpr.Emit): Refine error report and distinguish
+ between cs0070 and cs0079.
+
+ * class.cs (MemberBase.DoDefine): When reporting a wrong
+ accessibility level, we use MethodCore to compare instead of
+ Method (this was a regression in some refactoring effort).
+
+ So now we correctly report cs0056 again.
+
+ * convert.cs (ImplicitReferenceConversion): Corrected typo, I was
+ testing the target_type (which was known to be object_type) and
+ not the source type (which is anonymous_method).
+
+ Fixed reporting of error cs1660.
+
+ * expression.cs (UserCast.Source): Expose the underlying cast.
+
+ * statement.cs (Switch.SwitchGoverningType): Sort the list of
+ allowed types to find a match to int32 first (most common).
+
+ In addition, it ignores any ImplicitUserConversions that did an
+ internal implicit conversion (as the switch statement allows only
+ one integral conversion to exist).
+
+ * class.cs (PartialContainer.Create): rename `name' to
+ `member_name' for clarity. Then replace the string calls with a
+ call to MemberName.GetPartialName, as now using
+ MemberName.ToString is an error (this is due to the side effects
+ it had, that were fixed in the past).
+
+ This will restore the error reporting on a number of partial class
+ errors that were missusing this (and getting an exception as a
+ results, which is now just a plain textual warning, because
+ yyparse debug output would crash otherwise).
+
+2004-11-26 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (PROGRAM_INSTALL_DIR): Remove.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * rootcontext.cs (LookupType): Make sure to cache lookups that
+ don't give us a negative result. This saves about 5% of corlib
+ compilation time.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * report.cs (AbstractMessage.Print): messages are sent to stderr
+
+ * class.cs (TypeContainer.GetClassBases): It is an error to have a
+ non-interface in the list of interfaces (at this point, either
+ parent was properly set, or a base class is being listed in the
+ interfaces section).
+
+ This flags error 1722, and resolves the crash from bug 69259.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * statement.cs (Using.EmitExpressionFinally): make this work right
+ for valuetypes. Fixes 69926.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * const.cs (Const.ChangeType): Cope with the "0 literal can be
+ converted to an enum" here, before we try to change the underlying
+ type. This code exists, but it is a different code path than the
+ one used while encoding constants.
+
+ (ImplicitReferenceConversionExists): In addition, resynchronized
+ the code here, so it matches the same code in
+ ImplicitReferenceConversionExists for the `from any class-type S
+ to any interface-type T'.
+
+2004-11-25 Marek Safar <marek.safar@seznam.cz>
+
+ * cfold.cs (BinaryFold): Add addition for DecimalConstant.
+
+2004-11-24 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Use verbosity accordingly.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Unary.ResolveOperator): Do not report warning;
+ AddressOf reads from variable.
+
+ (LocalVariableReferences.DoResolveBase): Improved my previous fix.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69462
+
+ * attribute.cs (Attributable): Removed CheckTargets.
+ (Attributes.Emit): Explicit attribute targets are tested here.
+
+ * class.cs (EventField.ValidAttributeTargets): Explicit target "field" is
+ not enabled for interfaces.
+
+ * codegen.cs (CommonAssemblyModulClass.AddAttributes): Removed CheckTargets.
+ (GetAssemblyName): Ouch next bug there.
+
+2004-11-23 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * expression.cs: Error 275 added.
+
+2004-11-23 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69177 (Implemented decimal constant support)
+
+ * cfold.cs (DoConstantNumericPromotions: Add DecimalConstant.
+ (BinaryFold): Add DecimalConstant.
+
+ * const.cs (Define): Decimal constant
+ (is not constant.
+ (ChangeType): Add decimal type handling.
+ (LookupConstantValue): Don't set value for decimal type but
+ emit DecimalConstantAttribute. Needed for constant optimization.
+
+ * constant.cs (ToDecimal): New method.
+ (ConvertToDecimal): New method.
+ (IntConstant): Implemented ConvertToDecimal.
+ (DecimalConstant.Emit): Emit optimized version for decimals in
+ int range.
+
+ * expression.cs (ResolveOperator): Changed order of constant
+ reduction to work correctly with native types which have
+ overloaded operators.
+ (ResolveMemberAccess): Extract constant value from attribute
+ for decimal type.
+
+ * rootcontext.cs (ResolveCore): Add DecimalConstantAttribute.
+
+ * typemanager.cs (TypeManager): Add decimal_constant_attribute_type,
+ void_decimal_ctor_int_arg, decimal_constant_attribute_ctor.
+ (ChangeType): Decimal is special.
+ (TypeToCoreType): Add decimal type.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * convert.cs (ImplicitConversionRequired): Add error cs0642 for
+ decimal types.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (EventField.ApplyAttributeBuilder): Fix error
+ test cs1667-5.cs.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MemberBase.DoDefine): Fix error cs0508 report.
+
+ * pending.cs (PendingImplementation): Grab only interfaces.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * statement.cs (ForeachHelperMethods): Add location member and
+ error 202 detection.
+
+2004-11-18 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (DoResolveBase): Fixed wrong warning for out
+ variables.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.TypeParameter_to_Null): Use the constraints
+ to check whether the conversion is ok.
+
+ * typemanager.cs (TypeManager.GetTypeArguments): Just return
+ `Type.EmptyTypes' if we're not a generic TypeContainer.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ImplicitReferenceConversionExists): A surprisingly
+ old bug: when converting from the null literal to a pointer,
+ return an EmptyCast, not the NullLiteral.
+
+ This fixes #69921, the recent null_type changes probably made this
+ bug more prominent.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, call AnonymousMethod.Compatible() on it.
+
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (FieldBase): Use an unused bit field from the field to
+ encode the `has_offset' property from the FieldMember. This saves
+ a couple of Ks on bootstrap compilation.
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, return the AnonymousMethod resolved
+ expression.
+
+ * expression.cs (New.DoResolve): Allow return values from
+ NewDelegate to also include AnonymousMethods.
+
+ Fixes #70150.
+
2004-11-29 Raja R Harinath <rharinath@novell.com>
* decl.cs (MemberCore.MemberName): Remove readonly to fix an error
}
}
+ FieldExpr field_exp = target as FieldExpr;
+ if (field_exp != null && !ec.IsConstructor && !ec.IsFieldInitializer) {
+ field_exp = field_exp.InstanceExpression as FieldExpr;
+ if (field_exp != null && field_exp.FieldInfo.IsInitOnly) {
+ if (field_exp.IsStatic) {
+ Report.Error (1650, loc, "Members of static readonly field '{0}' cannot be assigned to " +
+ "(except in a static constructor or a variable initializer)", TypeManager.GetFullNameSignature (field_exp.FieldInfo));
+ } else {
+ Report.Error (1648, loc, "Members of readonly field '{0}' cannot be assigned to " +
+ "(except in a constructor or a variable initializer)", TypeManager.GetFullNameSignature (field_exp.FieldInfo));
+ }
+ return null;
+ }
+ }
+
if (!(target is IAssignMethod) && (target.eclass != ExprClass.EventAccess)) {
Report.Error (131, loc,
"Left hand of an assignment must be a variable, " +
/// </summary>
Attributes attributes;
- public Attributable(Attributes attrs)
+ public Attributable (Attributes attrs)
{
attributes = attrs;
- if (attributes != null)
- attributes.CheckTargets (this);
}
public Attributes OptAttributes
}
set {
attributes = value;
- if (attributes != null)
- attributes.CheckTargets (this);
}
}
void Error_InvalidNamedArgument (string name)
{
- Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
- "argument. Named attribute arguments must be fields which are not " +
- "readonly, static or const, or read-write properties which are not static.");
+ Report.Error (617, Location, "Invalid attribute argument: '{0}'. Argument must be fields " +
+ "fields which are not readonly, static or const; or read-write instance properties.",
+ Name);
}
static void Error_AttributeArgumentNotValid (Location loc)
/// <summary>
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
/// </summary>
- protected virtual Type CheckAttributeType (EmitContext ec, bool complain)
+ protected virtual Type CheckAttributeType (EmitContext ec)
{
- Type t1 = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
+ string NameAttribute = Name + "Attribute";
+ Type t1 = ec.ResolvingTypeTree
+ ? ec.DeclSpace.FindType (Location, Name)
+ : RootContext.LookupType (ec.DeclSpace, Name, true, Location);
+
// FIXME: Shouldn't do this for quoted attributes: [@A]
- Type t2 = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
+ Type t2 = ec.ResolvingTypeTree
+ ? ec.DeclSpace.FindType (Location, NameAttribute)
+ : RootContext.LookupType (ec.DeclSpace, NameAttribute, true, Location);
String err0616 = null;
if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
if (t2 != null && ! t2.IsSubclassOf (TypeManager.attribute_type)) {
t2 = null;
err0616 = (err0616 != null)
- ? "Neither '" + Name + "' nor '" + Name + "Attribute' is an attribute class"
+ ? "Neither '" + Name + "' nor '" + NameAttribute +"' is an attribute class"
: "'" + Name + "Attribute': is not an attribute class";
}
if (t1 != null && t2 != null) {
Report.Error(1614, Location, "'" + Name + "': is ambiguous; "
- + " use either '@" + Name + "' or '" + Name + "Attribute'");
+ + " use either '@" + Name + "' or '" + NameAttribute + "'");
return null;
}
if (t1 != null)
return null;
}
- if (complain)
- Report.Error (246, Location,
- "Could not find attribute '" + Name
- + "' (are you missing a using directive or an assembly reference ?)");
+ Report.Error (246, Location,
+ "Could not find attribute '" + Name
+ + "' (are you missing a using directive or an assembly reference ?)");
+
return null;
}
- public Type ResolveType (EmitContext ec, bool complain)
+ public Type ResolveType (EmitContext ec)
{
if (Type == null)
- Type = CheckAttributeType (ec, complain);
+ Type = CheckAttributeType (ec);
return Type;
}
Type oldType = Type;
// Sanity check.
- Type = CheckAttributeType (ec, true);
+ Type = CheckAttributeType (ec);
if (oldType == null && Type == null)
return null;
}
}
- if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
+ if (member == null){
+ Report.Error (117, Location, "Attribute `{0}' does not contain a definition for `{1}'",
+ Type, member_name);
+ return null;
+ }
+
+ if (!(member is PropertyExpr || member is FieldExpr)) {
Error_InvalidNamedArgument (member_name);
return null;
}
return null;
}
- ResolveType (ec, true);
+ ResolveType (ec);
if (Type == null)
return null;
ns = container.NamespaceEntry;
}
- protected override Type CheckAttributeType (EmitContext ec, bool complain)
+ protected override Type CheckAttributeType (EmitContext ec)
{
NamespaceEntry old = ec.DeclSpace.NamespaceEntry;
if (old == null || old.NS == null || old.NS == Namespace.Root)
ec.DeclSpace.NamespaceEntry = ns;
- return base.CheckAttributeType (ec, complain);
+ return base.CheckAttributeType (ec);
}
}
/// <summary>
/// Checks whether attribute target is valid for the current element
/// </summary>
- public void CheckTargets (Attributable member)
+ public bool CheckTargets (Attributable member)
{
string[] valid_targets = member.ValidAttributeTargets;
foreach (Attribute a in Attrs) {
sb.Append (", ");
}
sb.Remove (sb.Length - 2, 2);
- Report.Error (657, a.Location, "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'", a.Target, sb.ToString ());
+ Report.Error (657, a.Location, "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'", a.ExplicitTarget, sb.ToString ());
+ return false;
}
+ return true;
}
- private Attribute Search (Type t, EmitContext ec, bool complain)
+ public Attribute Search (Type t, EmitContext ec)
{
foreach (Attribute a in Attrs) {
- if (a.ResolveType (ec, complain) == t)
+ if (a.ResolveType (ec) == t)
return a;
}
return null;
}
- public Attribute Search (Type t, EmitContext ec)
- {
- return Search (t, ec, true);
- }
-
/// <summary>
/// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
/// </summary>
ArrayList ar = null;
foreach (Attribute a in Attrs) {
- if (a.ResolveType (ec, false) == t) {
+ if (a.ResolveType (ec) == t) {
if (ar == null)
ar = new ArrayList ();
ar.Add (a);
public void Emit (EmitContext ec, Attributable ias)
{
+ if (!CheckTargets (ias))
+ return;
+
ListDictionary ld = new ListDictionary ();
foreach (Attribute a in Attrs)
{
return Search (t, ec) != null;
}
-
- public Attribute GetClsCompliantAttribute (EmitContext ec)
- {
- return Search (TypeManager.cls_compliant_attribute_type, ec, false);
- }
-
- /// <summary>
- /// Pulls the IndexerName attribute from an Indexer if it exists.
- /// </summary>
- public Attribute GetIndexerNameAttribute (EmitContext ec)
- {
- Attribute a = Search (TypeManager.indexer_name_type, ec, false);
- if (a == null)
- return null;
-
- // Remove the attribute from the list because it is not emitted
- Attrs.Remove (a);
- return a;
- }
-
}
/// <summary>
}
return;
+ } else if (left is DecimalConstant || right is DecimalConstant) {
+ if (!(left is DecimalConstant))
+ left = left.ToDecimal (loc);
+ else if (!(right is DecimalConstant))
+ right = right.ToDecimal (loc);
+ return;
} else if (left is EnumConstant || right is EnumConstant){
//
// If either operand is an enum constant, the other one must
left = ((EnumConstant) left).Child;
if (right is EnumConstant)
right = ((EnumConstant) right).Child;
+
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
return;
} else {
DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
if (left == null || right == null)
return null;
-
+
if (left is IntConstant){
IntConstant v;
int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
((IntConstant) right).Value);
result = new IntConstant (res);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+
+ result = new DecimalConstant (res);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected addition input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
((IntConstant) right).Value);
result = new IntConstant (res);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected subtraction input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
if (ec.ConstantCheckState)
res = checked (((DoubleConstant) left).Value *
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
else
res = unchecked (((DoubleConstant) left).Value *
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
return new DoubleConstant (res);
} else if (left is FloatConstant){
if (ec.ConstantCheckState)
res = checked (((FloatConstant) left).Value *
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
else
res = unchecked (((FloatConstant) left).Value *
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
return new FloatConstant (res);
} else if (left is ULongConstant){
if (ec.ConstantCheckState)
res = checked (((ULongConstant) left).Value *
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
else
res = unchecked (((ULongConstant) left).Value *
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
return new ULongConstant (res);
} else if (left is LongConstant){
if (ec.ConstantCheckState)
res = checked (((LongConstant) left).Value *
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
else
res = unchecked (((LongConstant) left).Value *
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
return new LongConstant (res);
} else if (left is UIntConstant){
if (ec.ConstantCheckState)
res = checked (((UIntConstant) left).Value *
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
else
res = unchecked (((UIntConstant) left).Value *
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
return new UIntConstant (res);
} else if (left is IntConstant){
if (ec.ConstantCheckState)
res = checked (((IntConstant) left).Value *
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
else
res = unchecked (((IntConstant) left).Value *
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
return new IntConstant (res);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected multiply input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
if (ec.ConstantCheckState)
res = checked (((DoubleConstant) left).Value /
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
else
res = unchecked (((DoubleConstant) left).Value /
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
return new DoubleConstant (res);
} else if (left is FloatConstant){
if (ec.ConstantCheckState)
res = checked (((FloatConstant) left).Value /
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
else
res = unchecked (((FloatConstant) left).Value /
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
return new FloatConstant (res);
} else if (left is ULongConstant){
if (ec.ConstantCheckState)
res = checked (((ULongConstant) left).Value /
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
else
res = unchecked (((ULongConstant) left).Value /
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
return new ULongConstant (res);
} else if (left is LongConstant){
if (ec.ConstantCheckState)
res = checked (((LongConstant) left).Value /
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
else
res = unchecked (((LongConstant) left).Value /
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
return new LongConstant (res);
} else if (left is UIntConstant){
if (ec.ConstantCheckState)
res = checked (((UIntConstant) left).Value /
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
else
res = unchecked (((UIntConstant) left).Value /
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
return new UIntConstant (res);
} else if (left is IntConstant){
if (ec.ConstantCheckState)
res = checked (((IntConstant) left).Value /
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
else
res = unchecked (((IntConstant) left).Value /
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
return new IntConstant (res);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected division input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
return new IntConstant (res);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected modulus input: " + left);
}
} catch (DivideByZeroException){
Report.Error (020, loc, "Division by constant zero");
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
//
//
// 2002-10-11 Miguel de Icaza <miguel@ximian.com>
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
+using System.Xml;
using Mono.CompilerServices.SymbolWriter;
return null;
}
- if (!parent.AsAccessible (this, ModFlags))
- Report.Error (60, Location,
- "Inconsistent accessibility: base class `" +
- parent.Name + "' is less accessible than class `" +
- Name + "'");
+ if (!parent.AsAccessible (this, ModFlags)) {
+ Report.SymbolRelatedToPreviousError (parent.Type);
+ Report.Error (60, Location, "Inconsistent accessibility: base class '{0}' is less accessible than class '{1}'",
+ TypeManager.CSharpName (parent.Type), GetSignatureForError ());
+ }
}
if (parent != null)
}
if (iface.IsClass) {
- if (parent != null){
- Report.Error (527, Location,
- "In Class `{0}', `{1}' is not " +
- "an interface", Name, iface.Name);
- error = true;
- return null;
- }
+ Report.Error (1722, Location,
+ "In Class `{0}', `{1}' is not " +
+ "an interface, a base class must be listed first", Name, iface.Name);
+ error = true;
+ return null;
}
for (int x = 0; x < i; x++) {
}
}
+ public Constructor DefaultStaticConstructor {
+ get { return default_static_constructor; }
+ }
+
protected override bool VerifyClsCompliance (DeclSpace ds)
{
if (!base.VerifyClsCompliance (ds))
return FindMembers (mt, new_bf, null, null);
}
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal override void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateTypeDocComment (this, ds);
+ }
+
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
+
public virtual MemberCache ParentCache {
get {
return parent_cache;
public readonly TypeAttributes DefaultTypeAttributes;
static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
- MemberName name, int mod_flags, Kind kind,
+ MemberName member_name, int mod_flags, Kind kind,
Location loc)
{
PartialContainer pc;
- string full_name = name.GetName (true);
+ string full_name = member_name.GetName (true);
DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
if (ds != null) {
pc = ds as PartialContainer;
260, ds.Location, "Missing partial modifier " +
"on declaration of type `{0}'; another " +
"partial implementation of this type exists",
- name);
+ member_name.GetPartialName());
Report.LocationOfPreviousError (loc);
return null;
Report.Error (
261, loc, "Partial declarations of `{0}' " +
"must be all classes, all structs or " +
- "all interfaces", name);
+ "all interfaces", member_name.GetPartialName ());
return null;
}
Report.Error (
262, loc, "Partial declarations of `{0}' " +
"have conflicting accessibility modifiers",
- name);
+ member_name.GetPartialName ());
return null;
}
return pc;
}
- pc = new PartialContainer (ns, parent, name, mod_flags, kind, loc);
+ pc = new PartialContainer (ns, parent, member_name, mod_flags, kind, loc);
RootContext.Tree.RecordDecl (full_name, pc);
parent.AddType (pc);
pc.Register ();
return false;
}
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public override string GetDocCommentName (DeclSpace ds)
+ {
+ return DocUtil.GetMethodDocCommentName (this, ds);
+ }
+
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ // FIXME: with a few effort, it could be done with XmlReader,
+ // that means removal of DOM use.
+ //
+ internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
+ {
+ DocUtil.OnMethodGenerateDocComment (this, ds, el);
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "M:"; }
+ }
+
protected override void VerifyObsoleteAttribute()
{
base.VerifyObsoleteAttribute ();
"Inconsistent accessibility: indexer return type `" +
TypeManager.CSharpName (MemberType) + "' is less " +
"accessible than indexer `" + Name + "'");
- else if (this is Method) {
- if (((Method) this).IsOperator)
+ else if (this is MethodCore) {
+ if (this is Operator)
Report.Error (56, Location,
"Inconsistent accessibility: return type `" +
TypeManager.CSharpName (MemberType) + "' is less " +
"Inconsistent accessibility: return type `" +
TypeManager.CSharpName (MemberType) + "' is less " +
"accessible than method `" + Name + "'");
- } else
+ } else {
Report.Error (52, Location,
"Inconsistent accessibility: field type `" +
TypeManager.CSharpName (MemberType) + "' is less " +
"accessible than field `" + Name + "'");
+ }
return false;
}
InterfaceType = iface_texpr.Type;
- if (InterfaceType.IsClass) {
- Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
+ if (!InterfaceType.IsInterface) {
+ Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
return false;
}
[Flags]
public enum Status : byte {
ASSIGNED = 1,
- USED = 2
+ USED = 2,
+ HAS_OFFSET = 4 // Used by FieldMember.
}
static string[] attribute_targets = new string [] { "field" };
public abstract class FieldMember: FieldBase
{
- bool has_field_offset = false;
+
protected FieldMember (TypeContainer parent, Expression type, int mod,
int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
{
if (a.Type == TypeManager.field_offset_attribute_type)
{
- has_field_offset = true;
+ status |= Status.HAS_OFFSET;
if (!Parent.HasExplicitLayout) {
Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
public override void Emit ()
{
- if (Parent.HasExplicitLayout && !has_field_offset && (ModFlags & Modifiers.STATIC) == 0) {
+ if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
}
base.Emit ();
}
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "F:"; }
+ }
}
//
{
if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
a.Type == TypeManager.conditional_attribute_type) {
- Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on '{1}' declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
+ Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on {1} declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
return;
}
public override bool Define()
{
- return false;
+ throw new NotSupportedException ();
}
public virtual void Emit (TypeContainer container)
}
}
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
+ }
+
protected override void VerifyObsoleteAttribute()
{
}
return attribute_targets;
}
}
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "P:"; }
+ }
}
public class Property : PropertyBase, IIteratorContainer {
{
Add = new AddDelegateMethod (this, add);
Remove = new RemoveDelegateMethod (this, remove);
+
+ // For this event syntax we don't report error CS0067
+ // because it is hard to do it.
+ SetAssigned ();
}
public override string[] ValidAttributeTargets {
public class EventField: Event {
static string[] attribute_targets = new string [] { "event", "field", "method" };
+ static string[] attribute_targets_interface = new string[] { "event", "method" };
public EventField (TypeContainer parent, Expression type, int mod_flags,
bool is_iface, MemberName name, Object init,
}
if (a.Target == AttributeTargets.Method) {
- AddBuilder.SetCustomAttribute (cb);
- RemoveBuilder.SetCustomAttribute (cb);
+ Add.ApplyAttributeBuilder (a, cb);
+ Remove.ApplyAttributeBuilder (a, cb);
return;
}
public override string[] ValidAttributeTargets {
get {
- return attribute_targets;
+ return IsInterface ? attribute_targets_interface : attribute_targets;
}
}
}
return TypeManager.GetFullNameSignature (EventBuilder);
}
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "E:"; }
+ }
}
return false;
if (OptAttributes != null) {
- Attribute indexer_attr = OptAttributes.GetIndexerNameAttribute (ec);
+ Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
if (indexer_attr != null) {
+ // Remove the attribute from the list because it is not emitted
+ OptAttributes.Attrs.Remove (indexer_attr);
+
ShortName = indexer_attr.GetIndexerAttributeValue (ec);
if (IsExplicitImpl) {
return;
}
OptAttributes.AddAttributes (attrs);
- OptAttributes.CheckTargets (this);
}
public virtual void Emit (TypeContainer tc)
}
}
+ // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way.
public AssemblyName GetAssemblyName (string name, string output)
{
if (OptAttributes != null) {
foreach (Attribute a in OptAttributes.Attrs) {
- if (a.Target != AttributeTargets.Assembly)
- continue;
+ // cannot rely on any resolve-based members before you call Resolve
+ if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly")
+ continue;
+
// TODO: This code is buggy: comparing Attribute name without resolving it is wrong.
// However, this is invoked by CodeGen.Init, at which time none of the namespaces
// are loaded yet.
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
//
// (C) 2001 Ximian, Inc.
//
ModFlags |= Modifiers.STATIC;
}
- public FieldAttributes FieldAttr {
- get {
- return FieldAttributes.Literal | FieldAttributes.Static |
- Modifiers.FieldAttr (ModFlags) ;
- }
- }
-
#if DEBUG
void dump_tree (Type t)
{
return false;
}
- FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, FieldAttr);
+ FieldAttributes field_attr = FieldAttributes.Static | Modifiers.FieldAttr (ModFlags);
+ // I don't know why but they emit decimal constant as InitOnly
+ if (ttype == TypeManager.decimal_type) {
+ field_attr |= FieldAttributes.InitOnly;
+ }
+ else {
+ field_attr |= FieldAttributes.Literal;
+ }
+
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, field_attr);
TypeManager.RegisterConstant (FieldBuilder, this);
Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
return null;
}
+
+ // Special-case: The 0 literal can be converted to an enum value,
+ // and ImplicitStandardConversionExists will return true in that case.
+ if (expr.Type == TypeManager.int32_type && TypeManager.IsEnumType (type)){
+ if (expr is IntLiteral && ((IntLiteral) expr).Value == 0)
+ return new EnumConstant (expr, type);
+ }
object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail);
if (fail){
retval = new CharConstant ((char) constant_value);
else if (type == TypeManager.bool_type)
retval = new BoolConstant ((bool) constant_value);
+ else if (type == TypeManager.decimal_type)
+ retval = new DecimalConstant ((decimal) constant_value);
else
throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
}
}
- FieldBuilder.SetConstant (ConstantValue);
+ if (ce is DecimalConstant) {
+ Decimal d = ((DecimalConstant)ce).Value;
+ int[] bits = Decimal.GetBits (d);
+ object[] args = new object[] { (byte)(bits [3] >> 16), (byte)(bits [3] >> 31), (uint)bits [2], (uint)bits [1], (uint)bits [0] };
+ CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.decimal_constant_attribute_ctor, args);
+ FieldBuilder.SetCustomAttribute (cab);
+ }
+ else{
+ FieldBuilder.SetConstant (ConstantValue);
+ }
if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
throw new Exception ("Cannot register const value");
return c;
}
+
+ public DecimalConstant ToDecimal (Location loc)
+ {
+ DecimalConstant c = ConvertToDecimal ();
+
+ if (c == null)
+ Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
+
+ return c;
+ }
+
+ public virtual DecimalConstant ConvertToDecimal ()
+ {
+ return null;
+ }
public virtual DoubleConstant ConvertToDouble ()
{
return Value;
}
+ public override DecimalConstant ConvertToDecimal()
+ {
+ return new DecimalConstant (Value);
+ }
+
public override DoubleConstant ConvertToDouble ()
{
return new DoubleConstant (Value);
public override void Emit (EmitContext ec)
{
+ ILGenerator ig = ec.ig;
+
int [] words = Decimal.GetBits (Value);
+ int power = (words [3] >> 16) & 0xff;
+
+ if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
+ {
+ IntConstant.EmitInt (ig, (int)Value);
+ ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
+ return;
+ }
+
//
// FIXME: we could optimize this, and call a better
// constructor
//
- ILGenerator ig = ec.ig;
-
IntConstant.EmitInt (ig, words [0]);
IntConstant.EmitInt (ig, words [1]);
IntConstant.EmitInt (ig, words [2]);
IntConstant.EmitInt (ig, words [3] >> 31);
// power
- IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
+ IntConstant.EmitInt (ig, power);
ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
}
static bool TypeParameter_to_Null (Type target_type)
{
- if ((target_type.BaseType == null) ||
- (target_type.BaseType == TypeManager.value_type) ||
- target_type.BaseType.IsValueType)
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+ if (gc == null)
return false;
- return true;
+ if (gc.HasReferenceTypeConstraint)
+ return true;
+ if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
+ return true;
+
+ return false;
}
static Type TypeParam_EffectiveBaseType (EmitContext ec, Type t)
if (TypeManager.IsValueType (expr_type))
return new BoxedCast (expr);
if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
- if (target_type == TypeManager.anonymous_method_type)
+ if (expr_type == TypeManager.anonymous_method_type)
return null;
return new EmptyCast (expr, target_type);
}
// from the null type to any reference-type.
if (expr_type == TypeManager.null_type){
if (target_type.IsPointer)
- return NullPointer.Null;
+ return new EmptyCast (expr, target_type);
if (!target_type.IsValueType)
return new NullCast (expr, target_type);
// from any class-type S to any interface-type T.
if (target_type.IsInterface) {
+ if (target_type != TypeManager.iconvertible_type &&
+ expr_type.IsValueType && (expr is Constant) &&
+ !(expr is IntLiteral || expr is BoolLiteral ||
+ expr is FloatLiteral || expr is DoubleLiteral ||
+ expr is LongLiteral || expr is CharLiteral ||
+ expr is StringLiteral || expr is DecimalLiteral ||
+ expr is UIntLiteral || expr is ULongLiteral)) {
+ return false;
+ }
+
if (TypeManager.ImplementsInterface (expr_type, target_type))
return true;
}
return true;
// from the null type to any reference-type.
- if (expr_type == TypeManager.null_type && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
- return true;
+ if (expr_type == TypeManager.null_type){
+ if (target_type.IsPointer)
+ return true;
+
+ if (!target_type.IsValueType)
+ return true;
+ }
// from a generic type definition to a generic instance.
if (TypeManager.IsEqual (expr_type, target_type))
//
// Possibly, we need to create a different 0 literal before passing
// to EnumConstant
- //n
+ //
if (underlying == TypeManager.int64_type)
e = new LongLiteral (0);
else if (underlying == TypeManager.uint64_type)
if (e != null)
return e;
- if (source is DoubleLiteral && target_type == TypeManager.float_type){
- Report.Error (664, loc,
- "Double literal cannot be implicitly converted to " +
- "float type, use F suffix to create a float literal");
+ if (source is DoubleLiteral) {
+ if (target_type == TypeManager.float_type) {
+ Error_664 (loc, "float", "f");
+ return null;
+ }
+ if (target_type == TypeManager.decimal_type) {
+ Error_664 (loc, "decimal", "m");
+ return null;
+ }
}
if (source is Constant){
return null;
}
+ static void Error_664 (Location loc, string type, string suffix) {
+ Report.Error (664, loc,
+ "Literal of type double cannot be implicitly converted to type '{0}'. Add suffix '{1}' to create a literal of this type",
+ type, suffix);
+ }
+
/// <summary>
/// Performs the explicit numeric conversions
/// </summary>
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
//
// TODO:
// (1) Figure out why error productions dont work. `type-declaration' is a
/// The current file.
///
SourceFile file;
+
+ ///
+ /// Temporary Xml documentation cache.
+ /// For enum types, we need one more temporary store.
+ ///
+ string tmpComment;
+ string enumTypeComment;
+
/// Current attribute target
opt_EOF
: /* empty */
+ {
+ Lexer.check_incorrect_doc_comment ();
+ }
| EOF
+ {
+ Lexer.check_incorrect_doc_comment ();
+ }
;
outer_declarations
using_directive
: using_alias_directive
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
| using_namespace_directive
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
;
using_alias_directive
namespace_body
: OPEN_BRACE
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
opt_using_directives
opt_namespace_member_declarations
CLOSE_BRACE
} else {
$$ = new Attributes (sect);
}
+ if ($$ == null) {
+ if (RootContext.Documentation != null) {
+ Lexer.check_incorrect_doc_comment ();
+ Lexer.doc_state =
+ XmlCommentState.Allowed;
+ }
+ }
} else {
$$ = new Attributes (sect);
}
current_class.SetParameterInfo ((ArrayList) $8);
+ if (RootContext.Documentation != null)
+ current_class.DocComment = Lexer.consume_doc_comment ();
+
current_class.Register ();
}
struct_body
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
opt_semicolon
{
$$ = current_class;
;
struct_body
- : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
+ : OPEN_BRACE
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+ opt_struct_member_declarations CLOSE_BRACE
;
opt_struct_member_declarations
(Expression) constant.expression_or_array_initializer, modflags,
(Attributes) $1, l);
+ if (RootContext.Documentation != null) {
+ c.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
current_container.AddConstant (c);
}
}
var.expression_or_array_initializer,
(Attributes) $1, l);
+ if (RootContext.Documentation != null) {
+ field.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
current_container.AddField (field);
}
}
method_declaration
: method_header {
iterator_container = (IIteratorContainer) $1;
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.NotAllowed;
}
method_body
{
current_local_parameters = null;
iterator_container = null;
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
;
current_local_parameters = (Parameters) $6;
+ if (RootContext.Documentation != null)
+ method.DocComment = Lexer.consume_doc_comment ();
+
$$ = method;
}
| opt_attributes
lexer.Location);
current_local_parameters = (Parameters) $6;
+
+ if (RootContext.Documentation != null)
+ method.DocComment = Lexer.consume_doc_comment ();
+
$$ = method;
}
| opt_attributes
lexer.Location);
current_local_parameters = (Parameters) $6;
+
+ if (RootContext.Documentation != null)
+ method.DocComment = Lexer.consume_doc_comment ();
+
$$ = method;
}
;
property_declaration
: opt_attributes
opt_modifiers
- type namespace_or_type_name
+ type
+ namespace_or_type_name
+ {
+ if (RootContext.Documentation != null)
+ tmpComment = Lexer.consume_doc_comment ();
+ }
OPEN_BRACE
{
implicit_value_parameter_type = (Expression) $3;
CLOSE_BRACE
{
Property prop;
- Pair pair = (Pair) $7;
+ Pair pair = (Pair) $8;
Accessor get_block = (Accessor) pair.First;
Accessor set_block = (Accessor) pair.Second;
- Location loc = (Location) $6;
+ Location loc = (Location) $7;
MemberName name = (MemberName) $4;
if (name.TypeArguments != null)
current_container.AddProperty (prop);
implicit_value_parameter_type = null;
iterator_container = null;
+
+ if (RootContext.Documentation != null)
+ prop.DocComment = ConsumeStoredComment ();
+
}
;
$$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location);
current_local_parameters = null;
lexer.PropertyParsing = true;
+
+ if (RootContext.Documentation != null)
+ if (Lexer.doc_state == XmlCommentState.Error)
+ Lexer.doc_state = XmlCommentState.NotAllowed;
}
;
$$ = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, lexer.Location);
current_local_parameters = null;
lexer.PropertyParsing = true;
+
+ if (RootContext.Documentation != null
+ && Lexer.doc_state == XmlCommentState.Error)
+ Lexer.doc_state = XmlCommentState.NotAllowed;
}
;
current_class.SetParameterInfo ((ArrayList) $8);
+ if (RootContext.Documentation != null) {
+ current_class.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
current_class.Register ();
}
interface_body opt_semicolon
{
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+ opt_semicolon
+ {
$$ = current_class;
current_container = current_container.Parent;
Method m = (Method) $1;
current_container.AddMethod (m);
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_property_declaration
{
Property p = (Property) $1;
current_container.AddProperty (p);
- }
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
| interface_event_declaration
{
if ($1 != null){
Event e = (Event) $1;
current_container.AddEvent (e);
}
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_indexer_declaration
{
Indexer i = (Indexer) $1;
current_container.AddIndexer (i);
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
;
$$ = new Method (current_class, generic, (Expression) $3, (int) $2, true, name,
(Parameters) $6, (Attributes) $1, lexer.Location);
+ if (RootContext.Documentation != null)
+ ((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new VOID namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
$$ = new Method (current_class, generic, TypeManager.system_void_expr, (int) $2,
true, name, (Parameters) $6, (Attributes) $1, lexer.Location);
+ if (RootContext.Documentation != null)
+ ((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
;
$$ = new Property (current_class, (Expression) $3, (int) $2, true,
new MemberName ((string) $4), (Attributes) $1,
pinfo.Get, pinfo.Set, lexer.Location);
+ if (RootContext.Documentation != null)
+ ((Property) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes
opt_new
;
interface_accessors
- : opt_attributes GET SEMICOLON { $$ = new InterfaceAccessorInfo (true, false, (Attributes) $1, null, lexer.Location, lexer.Location); }
- | opt_attributes SET SEMICOLON { $$ = new InterfaceAccessorInfo (false, true, null, (Attributes) $1, lexer.Location, lexer.Location); }
- | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
- { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $1, (Attributes) $3, lexer.Location, lexer.Location); }
- | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
- { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $3, (Attributes) $1, lexer.Location, lexer.Location); }
+ : opt_attributes opt_modifiers GET SEMICOLON
+ { $$ = new InterfaceAccessorInfo (true, false, (Attributes) $1, null, (int) $2, 0, lexer.Location, lexer.Location); }
+ | opt_attributes opt_modifiers SET SEMICOLON
+ { $$ = new InterfaceAccessorInfo (false, true, null, (Attributes) $1, 0, (int) $2, lexer.Location, lexer.Location); }
+ | opt_attributes opt_modifiers GET SEMICOLON opt_attributes opt_modifiers SET SEMICOLON
+ { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $1, (Attributes) $5, (int) $2, (int) $6, lexer.Location, lexer.Location); }
+ | opt_attributes opt_modifiers SET SEMICOLON opt_attributes opt_modifiers GET SEMICOLON
+ { $$ = new InterfaceAccessorInfo (true, true, (Attributes) $5, (Attributes) $1, (int) $6, (int) $2, lexer.Location, lexer.Location); }
;
interface_event_declaration
$$ = new EventField (current_class, (Expression) $4, (int) $2, true,
new MemberName ((string) $5), null,
(Attributes) $1, lexer.Location);
+ if (RootContext.Documentation != null)
+ ((EventField) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new EVENT type error {
CheckIdentifierToken (yyToken);
new MemberName (TypeContainer.DefaultIndexerName),
(int) $2, true, (Parameters) $6, (Attributes) $1,
info.Get, info.Set, lexer.Location);
+ if (RootContext.Documentation != null)
+ ((Indexer) $$).DocComment = ConsumeStoredComment ();
}
;
new Parameters (param_list, null, decl.location),
(ToplevelBlock) $5, (Attributes) $1, decl.location);
+ if (RootContext.Documentation != null)
+ op.DocComment = ConsumeStoredComment ();
+
if (SimpleIteratorContainer.Simple.Yields)
op.SetYields ();
op = Operator.OpType.UnaryNegation;
Parameter [] pars = new Parameter [1];
+ Expression type = (Expression) $5;
- pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
+ pars [0] = new Parameter (type, (string) $6, Parameter.Modifier.NONE, null);
current_local_parameters = new Parameters (pars, null, lexer.Location);
- $$ = new OperatorDeclaration (op, (Expression) $1, (Expression) $5, (string) $6,
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
+ $$ = new OperatorDeclaration (op, (Expression) $1, type, (string) $6,
null, null, lexer.Location);
}
| type OPERATOR overloadable_operator
type IDENTIFIER
CLOSE_PARENS
{
- CheckBinaryOperator ((Operator.OpType) $3);
+ CheckBinaryOperator ((Operator.OpType) $3);
+
+ Parameter [] pars = new Parameter [2];
- Parameter [] pars = new Parameter [2];
+ Expression typeL = (Expression) $5;
+ Expression typeR = (Expression) $8;
- pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
- pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
+ pars [0] = new Parameter (typeL, (string) $6, Parameter.Modifier.NONE, null);
+ pars [1] = new Parameter (typeR, (string) $9, Parameter.Modifier.NONE, null);
current_local_parameters = new Parameters (pars, null, lexer.Location);
+
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
$$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1,
- (Expression) $5, (string) $6,
- (Expression) $8, (string) $9, lexer.Location);
+ typeL, (string) $6,
+ typeR, (string) $9, lexer.Location);
}
| conversion_operator_declarator
;
c.OptAttributes = (Attributes) $1;
c.ModFlags = (int) $2;
+ if (RootContext.Documentation != null)
+ c.DocComment = ConsumeStoredComment ();
+
if (c.Name == current_container.Basename){
if ((c.ModFlags & Modifiers.STATIC) != 0){
if ((c.ModFlags & Modifiers.Accessibility) != 0){
current_container.AddConstructor (c);
current_local_parameters = null;
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
;
constructor_declarator
- : IDENTIFIER
+ : IDENTIFIER
+ {
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+ }
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
oob_stack.Push (lexer.Location);
- current_local_parameters = (Parameters) $3;
+ current_local_parameters = (Parameters) $4;
}
opt_constructor_initializer
{
Location l = (Location) oob_stack.Pop ();
- $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $3,
- (ConstructorInitializer) $6, l);
+ $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $4,
+ (ConstructorInitializer) $7, l);
}
;
;
destructor_declaration
- : opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
+ : opt_attributes opt_finalizer TILDE
+ {
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.NotAllowed;
+ }
+ }
+ IDENTIFIER OPEN_PARENS CLOSE_PARENS block
{
- if ((string) $4 != current_container.Basename){
+ if ((string) $5 != current_container.Basename){
Report.Error (574, lexer.Location, "Name of destructor must match name of class");
} else if (!(current_container is Class)){
Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
Method d = new Destructor (
current_class, TypeManager.system_void_expr, m, "Finalize",
new Parameters (null, null, l), (Attributes) $1, l);
+ if (RootContext.Documentation != null)
+ d.DocComment = ConsumeStoredComment ();
- d.Block = (ToplevelBlock) $7;
+ d.Block = (ToplevelBlock) $8;
current_container.AddMethod (d);
}
}
lexer.Location);
current_container.AddEvent (e);
-
+
+ if (RootContext.Documentation != null) {
+ e.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
}
}
| opt_attributes
current_class, (Expression) $4, (int) $2, false, name, null,
(Attributes) $1, (Accessor) pair.First, (Accessor) pair.Second,
loc);
-
+ if (RootContext.Documentation != null) {
+ e.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
current_container.AddEvent (e);
implicit_value_parameter_type = null;
}
Report.Error (71, lexer.Location, "Explicit implementation of events requires property syntax");
else
Report.Error (71, lexer.Location, "Event declaration should use property syntax");
+
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
}
;
indexer = new Indexer (current_class, decl.type, name,
(int) $2, false, decl.param_list, (Attributes) $1,
get_block, set_block, loc);
+ if (RootContext.Documentation != null)
+ indexer.DocComment = ConsumeStoredComment ();
current_container.AddIndexer (indexer);
} else if (pars.FixedParameters == null && pars.ArrayParameter == null){
Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
}
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
$$ = new IndexerDeclaration ((Expression) $1, null, pars);
}
} else if (pars.FixedParameters == null && pars.ArrayParameter == null){
Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
}
+
MemberName name = (MemberName) $2;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "an indexer can't have type arguments");
$$ = new IndexerDeclaration ((Expression) $1, name, pars);
+
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
}
;
: opt_attributes
opt_modifiers
ENUM IDENTIFIER
- opt_enum_base
+ opt_enum_base {
+ if (RootContext.Documentation != null)
+ enumTypeComment = Lexer.consume_doc_comment ();
+ }
enum_body
opt_semicolon
{
Enum e = new Enum (current_namespace, current_container, (Expression) $5, (int) $2,
full_name, (Attributes) $1, enum_location);
- foreach (VariableDeclaration ev in (ArrayList) $6) {
+ if (RootContext.Documentation != null)
+ e.DocComment = enumTypeComment;
+
+ foreach (VariableDeclaration ev in (ArrayList) $7) {
e.AddEnumMember (ev.identifier,
(Expression) ev.expression_or_array_initializer,
- ev.Location, ev.OptAttributes);
+ ev.Location, ev.OptAttributes,
+ ev.DocComment);
}
string name = full_name.GetName ();
;
enum_body
- : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
+ : OPEN_BRACE
{
- $$ = $2;
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+ opt_enum_member_declarations
+ {
+ // here will be evaluated after CLOSE_BLACE is consumed.
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+ CLOSE_BRACE
+ {
+ $$ = $3;
}
;
enum_member_declaration
: opt_attributes IDENTIFIER
{
- $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
+ VariableDeclaration vd = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
+
+ if (RootContext.Documentation != null) {
+ vd.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
+ $$ = vd;
}
| opt_attributes IDENTIFIER
{
- $$ = lexer.Location;
+ $$ = lexer.Location;
+ if (RootContext.Documentation != null) {
+ tmpComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.NotAllowed;
+ }
}
ASSIGN expression
{
- $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
+ VariableDeclaration vd = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
+
+ if (RootContext.Documentation != null)
+ vd.DocComment = ConsumeStoredComment ();
+
+ $$ = vd;
}
;
Delegate del = new Delegate (current_namespace, current_container, (Expression) $4,
(int) $2, name, (Parameters) $7, (Attributes) $1, l);
+ if (RootContext.Documentation != null) {
+ del.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
current_container.AddDelegate (del);
RootContext.Tree.RecordDecl (name.GetName (true), del);
TypeManager.system_void_expr, (int) $2, name,
(Parameters) $7, (Attributes) $1, l);
+ if (RootContext.Documentation != null) {
+ del.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
current_container.AddDelegate (del);
RootContext.Tree.RecordDecl (name.GetName (true), del);
current_class.SetParameterInfo ((ArrayList) $8);
+ if (RootContext.Documentation != null) {
+ current_class.DocComment = Lexer.consume_doc_comment ();
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
+
current_class.Register ();
}
- class_body
+ class_body
+ {
+ if (RootContext.Documentation != null)
+ Lexer.doc_state = XmlCommentState.Allowed;
+ }
opt_semicolon
{
$$ = current_class;
public object expression_or_array_initializer;
public Location Location;
public Attributes OptAttributes;
+ public string DocComment;
public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
{
public readonly Accessor Get, Set;
public InterfaceAccessorInfo (bool has_get, bool has_set,
- Attributes get_attrs, Attributes set_attrs, Location get_loc, Location set_loc)
+ Attributes get_attrs, Attributes set_attrs, int get_mod, int set_mod, Location get_loc, Location set_loc)
{
+ if (get_mod != 0)
+ Report.Error (275, get_loc, "Accessibility modifiers can not be used on accessors in interfaces");
+ if (set_mod != 0)
+ Report.Error (275, set_loc, "Accessibility modifiers can not be used on accessors in interfaces");
+
if (has_get)
Get = new Accessor (null, 0, get_attrs, get_loc);
if (has_set)
Set = new Accessor (null, 0, set_attrs, set_loc);
}
+
}
CheckToken (1041, yyToken, "Identifier expected");
}
+string ConsumeStoredComment ()
+{
+ string s = tmpComment;
+ tmpComment = null;
+ Lexer.doc_state = XmlCommentState.Allowed;
+ return s;
+}
+
/* end end end */
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
//
/*
bool handle_constraints = false;
bool handle_typeof = false;
+ //
+ // XML documentation buffer. The save point is used to divide
+ // comments on types and comments on members.
+ //
+ StringBuilder xml_comment_buffer;
+
+ //
+ // See comment on XmlCommentState enumeration.
+ //
+ XmlCommentState xmlDocState = XmlCommentState.Allowed;
+
//
// Whether tokens have been seen on this line
//
handle_typeof = value;
}
}
-
+
+ public XmlCommentState doc_state {
+ get { return xmlDocState; }
+ set {
+ if (value == XmlCommentState.Allowed) {
+ check_incorrect_doc_comment ();
+ consume_doc_comment ();
+ }
+ xmlDocState = value;
+ }
+ }
+
//
// Class variables
//
define (def);
}
+ xml_comment_buffer = new StringBuilder ();
+
//
// FIXME: This could be `Location.Push' but we have to
// find out why the MS compiler allows this
case '}':
return Token.CLOSE_BRACE;
case '[':
+ // To block doccomment inside attribute declaration.
+ if (doc_state == XmlCommentState.Allowed)
+ doc_state = XmlCommentState.NotAllowed;
return Token.OPEN_BRACKET;
case ']':
return Token.CLOSE_BRACKET;
{
int res = consume_identifier (s, false);
+ if (doc_state == XmlCommentState.Allowed)
+ doc_state = XmlCommentState.NotAllowed;
+ switch (res) {
+ case Token.USING:
+ case Token.NAMESPACE:
+ check_incorrect_doc_comment ();
+ break;
+ }
+
if (res == Token.PARTIAL) {
// Save current position and parse next token.
int old = reader.Position;
if (d == '/'){
getChar ();
+ if (RootContext.Documentation != null && peekChar () == '/') {
+ getChar ();
+ // Allow only ///ws.
+ // Don't allow ////.
+ if ((d = peekChar ()) == ' ' || d == '\t') {
+ if (doc_state == XmlCommentState.Allowed)
+ handle_one_line_xml_comment ();
+ else if (doc_state == XmlCommentState.NotAllowed)
+ warn_incorrect_doc_comment ();
+ }
+ }
while ((d = getChar ()) != -1 && (d != '\n') && d != '\r')
col++;
if (d == '\n'){
continue;
} else if (d == '*'){
getChar ();
+ bool docAppend = false;
+ if (RootContext.Documentation != null && peekChar () == '*') {
+ getChar ();
+ // But when it is /**/, just do nothing.
+ if (peekChar () == '/') {
+ getChar ();
+ continue;
+ }
+ if (doc_state == XmlCommentState.Allowed)
+ docAppend = true;
+ else if (doc_state == XmlCommentState.NotAllowed)
+ warn_incorrect_doc_comment ();
+ }
+
+ int currentCommentStart = 0;
+ if (docAppend) {
+ currentCommentStart = xml_comment_buffer.Length;
+ xml_comment_buffer.Append (Environment.NewLine);
+ }
while ((d = getChar ()) != -1){
if (d == '*' && peekChar () == '/'){
col++;
break;
}
+ if (docAppend)
+ xml_comment_buffer.Append ((char) d);
+
if (d == '\n'){
line++;
ref_line++;
tokens_seen = false;
}
}
+ if (docAppend)
+ update_formatted_doc_comment (currentCommentStart);
continue;
}
goto is_punct_label;
return Token.ERROR;
}
+ //
+ // Handles one line xml comment
+ //
+ private void handle_one_line_xml_comment ()
+ {
+ int c;
+ while ((c = peekChar ()) == ' ')
+ getChar (); // skip heading whitespaces.
+ while ((c = peekChar ()) != -1 && c != '\n' && c != '\r') {
+ col++;
+ xml_comment_buffer.Append ((char) getChar ());
+ }
+ if (c == '\r' || c == '\n')
+ xml_comment_buffer.Append (Environment.NewLine);
+ }
+
+ //
+ // Remove heading "*" in Javadoc-like xml documentation.
+ //
+ private void update_formatted_doc_comment (int currentCommentStart)
+ {
+ int length = xml_comment_buffer.Length - currentCommentStart;
+ string [] lines = xml_comment_buffer.ToString (
+ currentCommentStart,
+ length).Replace ("\r", "").Split ('\n');
+ // The first line starts with /**, thus it is not target
+ // for the format check.
+ for (int i = 1; i < lines.Length; i++) {
+ string s = lines [i];
+ int idx = s.IndexOf ('*');
+ string head = null;
+ if (idx < 0) {
+ if (i < lines.Length - 1)
+ return;
+ head = s;
+ }
+ else
+ head = s.Substring (0, idx);
+ foreach (char c in head)
+ if (c != ' ')
+ return;
+ lines [i] = s.Substring (idx + 1);
+ }
+ xml_comment_buffer.Remove (currentCommentStart, length);
+ xml_comment_buffer.Insert (
+ currentCommentStart,
+ String.Join (Environment.NewLine, lines));
+ }
+
+ //
+ // Checks if there was incorrect doc comments and raise
+ // warnings.
+ //
+ public void check_incorrect_doc_comment ()
+ {
+ if (xml_comment_buffer.Length > 0)
+ warn_incorrect_doc_comment ();
+ }
+
+ //
+ // Raises a warning when tokenizer found incorrect doccomment
+ // markup.
+ //
+ private void warn_incorrect_doc_comment ()
+ {
+ doc_state = XmlCommentState.Error;
+ // in csc, it is 'XML comment is not placed on a valid
+ // language element'. But that does not make sense.
+ Report.Warning (1587, 2, Location, "XML comment is placed on an invalid language element which can not accept it.");
+ }
+
+ //
+ // Consumes the saved xml comment lines (if any)
+ // as for current target member or type.
+ //
+ public string consume_doc_comment ()
+ {
+ if (xml_comment_buffer.Length > 0) {
+ string ret = xml_comment_buffer.ToString ();
+ xml_comment_buffer.Length = 0;
+ return ret;
+ }
+ return null;
+ }
+
public void cleanup ()
{
if (ifstack != null && ifstack.Count >= 1) {
}
}
+
+ //
+ // Indicates whether it accepts XML documentation or not.
+ //
+ public enum XmlCommentState {
+ // comment is allowed in this state.
+ Allowed,
+ // comment is not allowed in this state.
+ NotAllowed,
+ // once comments appeared when it is NotAllowed, then the
+ // state is changed to it, until the state is changed to
+ // .Allowed.
+ Error
+ }
}
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
//
// TODO: Move the method verification stuff from the class.cs and interface.cs here
//
using System.Globalization;
using System.Reflection.Emit;
using System.Reflection;
+using System.Xml;
namespace Mono.CSharp {
}
}
+ // Is not readonly because of IndexerName attribute
public MemberName MemberName;
/// <summary>
/// </summary>
public readonly Location Location;
+ /// <summary>
+ /// XML documentation comment
+ /// </summary>
+ public string DocComment;
+
+ /// <summary>
+ /// Represents header string for documentation comment
+ /// for each member types.
+ /// </summary>
+ public abstract string DocCommentHeader { get; }
+
[Flags]
public enum Flags {
Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet
/// <summary>
/// Returns true when MemberCore is exposed from assembly.
/// </summary>
- protected bool IsExposedFromAssembly (DeclSpace ds)
+ public bool IsExposedFromAssembly (DeclSpace ds)
{
if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
return false;
bool GetClsCompliantAttributeValue (DeclSpace ds)
{
if (OptAttributes != null) {
- Attribute cls_attribute = OptAttributes.GetClsCompliantAttribute (ds.EmitContext);
+ Attribute cls_attribute = OptAttributes.Search (
+ TypeManager.cls_compliant_attribute_type, ds.EmitContext);
if (cls_attribute != null) {
caching_flags |= Flags.HasClsCompliantAttribute;
return cls_attribute.GetClsCompliantAttributeValue (ds);
protected abstract void VerifyObsoleteAttribute ();
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ internal virtual void OnGenerateDocComment (DeclSpace ds, XmlElement intermediateNode)
+ {
+ }
+
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public virtual string GetDocCommentName (DeclSpace ds)
+ {
+ if (ds == null || this is DeclSpace)
+ return DocCommentHeader + Name;
+ else
+ return String.Concat (DocCommentHeader, ds.Name, ".", Name);
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal virtual void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateDocComment (this, ds);
+ }
}
/// <summary>
caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
if (OptAttributes != null) {
- Attribute cls_attribute = OptAttributes.GetClsCompliantAttribute (ec);
+ Attribute cls_attribute = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, ec);
if (cls_attribute != null) {
caching_flags |= Flags.HasClsCompliantAttribute;
if (cls_attribute.GetClsCompliantAttributeValue (this)) {
IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
while (it.MoveNext ()) {
hash [it.Key] = ((ArrayList) it.Value).Clone ();
- }
+ }
return hash;
}
}
}
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
+
protected override void VerifyObsoleteAttribute()
{
CheckUsageOfObsoleteAttribute (ret_type);
Expression e = a.Expr;
+ if (e is AnonymousMethod)
+ return ((AnonymousMethod) e).Compatible (ec, type, false);
+
MethodGroupExpr mg = e as MethodGroupExpr;
if (mg != null)
return ResolveMethodGroupExpr (ec, mg);
--- /dev/null
+//
+// doc.cs: Support for XML documentation comment.
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2004 Novell, Inc.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Text;
+using System.Xml;
+
+using Mono.CompilerServices.SymbolWriter;
+
+namespace Mono.CSharp {
+
+ //
+ // Support class for XML documentation.
+ //
+ public class DocUtil
+ {
+ // TypeContainer
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal static void GenerateTypeDocComment (TypeContainer t,
+ DeclSpace ds)
+ {
+ GenerateDocComment (t, ds);
+
+ if (t.DefaultStaticConstructor != null)
+ t.DefaultStaticConstructor.GenerateDocComment (t);
+
+ if (t.InstanceConstructors != null)
+ foreach (Constructor c in t.InstanceConstructors)
+ c.GenerateDocComment (t);
+
+ if (t.Types != null)
+ foreach (TypeContainer tc in t.Types)
+ tc.GenerateDocComment (t);
+
+ if (t.Parts != null) {
+ IDictionary comments = RootContext.Documentation.PartialComments;
+ foreach (ClassPart cp in t.Parts) {
+ if (cp.DocComment == null)
+ continue;
+ comments [cp] = cp;
+ }
+ }
+
+ if (t.Enums != null)
+ foreach (Enum en in t.Enums)
+ en.GenerateDocComment (t);
+
+ if (t.Constants != null)
+ foreach (Const c in t.Constants)
+ c.GenerateDocComment (t);
+
+ if (t.Fields != null)
+ foreach (Field f in t.Fields)
+ f.GenerateDocComment (t);
+
+ if (t.Events != null)
+ foreach (Event e in t.Events)
+ e.GenerateDocComment (t);
+
+ if (t.Indexers != null)
+ foreach (Indexer ix in t.Indexers)
+ ix.GenerateDocComment (t);
+
+ if (t.Properties != null)
+ foreach (Property p in t.Properties)
+ p.GenerateDocComment (t);
+
+ if (t.Methods != null)
+ foreach (Method m in t.Methods)
+ m.GenerateDocComment (t);
+
+ if (t.Operators != null)
+ foreach (Operator o in t.Operators)
+ o.GenerateDocComment (t);
+ }
+
+ // MemberCore
+ private static readonly string lineHead =
+ Environment.NewLine + " ";
+
+ private static XmlNode GetDocCommentNode (MemberCore mc,
+ string name)
+ {
+ // FIXME: It could be even optimizable as not
+ // to use XmlDocument. But anyways the nodes
+ // are not kept in memory.
+ XmlDocument doc = RootContext.Documentation.XmlDocumentation;
+ try {
+ XmlElement el = doc.CreateElement ("member");
+ el.SetAttribute ("name", name);
+ string normalized = mc.DocComment;
+ el.InnerXml = normalized;
+ // csc keeps lines as written in the sources
+ // and inserts formatting indentation (which
+ // is different from XmlTextWriter.Formatting
+ // one), but when a start tag contains an
+ // endline, it joins the next line. We don't
+ // have to follow such a hacky behavior.
+ string [] split =
+ normalized.Split ('\n');
+ int j = 0;
+ for (int i = 0; i < split.Length; i++) {
+ string s = split [i].TrimEnd ();
+ if (s.Length > 0)
+ split [j++] = s;
+ }
+ el.InnerXml = lineHead + String.Join (
+ lineHead, split, 0, j);
+ return el;
+ } catch (XmlException ex) {
+ Report.Warning (1570, 1, mc.Location, "XML comment on '{0}' has non-well-formed XML ({1}).", name, ex.Message);
+ XmlComment com = doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
+ return com;
+ }
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal static void GenerateDocComment (MemberCore mc,
+ DeclSpace ds)
+ {
+ if (mc.DocComment != null) {
+ string name = mc.GetDocCommentName (ds);
+
+ XmlNode n = GetDocCommentNode (mc, name);
+
+ XmlElement el = n as XmlElement;
+ if (el != null) {
+ mc.OnGenerateDocComment (ds, el);
+
+ // FIXME: it could be done with XmlReader
+ foreach (XmlElement inc in n.SelectNodes (".//include"))
+ HandleInclude (mc, inc);
+
+ // FIXME: it could be done with XmlReader
+ DeclSpace dsTarget = mc as DeclSpace;
+ if (dsTarget == null)
+ dsTarget = ds;
+
+ foreach (XmlElement see in n.SelectNodes (".//see"))
+ HandleSee (mc, dsTarget, see);
+ foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
+ HandleSeeAlso (mc, dsTarget, seealso);
+ foreach (XmlElement see in n.SelectNodes (".//exception"))
+ HandleException (mc, dsTarget, see);
+ }
+
+ n.WriteTo (RootContext.Documentation.XmlCommentOutput);
+ }
+ else if (mc.IsExposedFromAssembly (ds) &&
+ // There are no warnings when the container also
+ // misses documentations.
+ (ds == null || ds.DocComment != null))
+ {
+ Report.Warning (1591, 4, mc.Location,
+ "Missing XML comment for publicly visible type or member '{0}'", mc.GetSignatureForError ());
+ }
+ }
+
+ //
+ // Processes "include" element. Check included file and
+ // embed the document content inside this documentation node.
+ //
+ private static void HandleInclude (MemberCore mc, XmlElement el)
+ {
+ string file = el.GetAttribute ("file");
+ string path = el.GetAttribute ("path");
+ if (file == "") {
+ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'file' attribute.");
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
+ }
+ else if (path == "") {
+ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'path' attribute.");
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
+ }
+ else {
+ XmlDocument doc = RootContext.Documentation.StoredDocuments [file] as XmlDocument;
+ if (doc == null) {
+ try {
+ doc = new XmlDocument ();
+ doc.Load (file);
+ RootContext.Documentation.StoredDocuments.Add (file, doc);
+ } catch (Exception) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file '{0}': cannot be included ", file)), el);
+ Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- '{0}'", file);
+ }
+ }
+ bool keepIncludeNode = false;
+ if (doc != null) {
+ try {
+ XmlNodeList nl = doc.SelectNodes (path);
+ if (nl.Count == 0) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el);
+
+ keepIncludeNode = true;
+ }
+ foreach (XmlNode n in nl)
+ el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el);
+ } catch (Exception ex) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el);
+ Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment '{0}' of file {1} -- {2}.", path, file, ex.Message);
+ }
+ }
+ if (!keepIncludeNode)
+ el.ParentNode.RemoveChild (el);
+ }
+ }
+
+ //
+ // Handles <see> elements.
+ //
+ private static void HandleSee (MemberCore mc,
+ DeclSpace ds, XmlElement see)
+ {
+ HandleXrefCommon (mc, ds, see);
+ }
+
+ //
+ // Handles <seealso> elements.
+ //
+ private static void HandleSeeAlso (MemberCore mc,
+ DeclSpace ds, XmlElement seealso)
+ {
+ HandleXrefCommon (mc, ds, seealso);
+ }
+
+ //
+ // Handles <exception> elements.
+ //
+ private static void HandleException (MemberCore mc,
+ DeclSpace ds, XmlElement seealso)
+ {
+ HandleXrefCommon (mc, ds, seealso);
+ }
+
+ static readonly char [] wsChars =
+ new char [] {' ', '\t', '\n', '\r'};
+
+ //
+ // returns a full runtime type name from a name which might
+ // be C# specific type name.
+ //
+ private static Type FindDocumentedType (MemberCore mc,
+ string name, DeclSpace ds, bool allowAlias)
+ {
+ bool isArray = false;
+ string identifier = name;
+ if (name [name.Length - 1] == ']') {
+ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
+ if (tmp [tmp.Length - 1] == '[') {
+ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
+ isArray = true;
+ }
+ }
+ Type t = FindDocumentedTypeNonArray (mc, identifier,
+ ds, allowAlias);
+ if (t != null && isArray)
+ t = Array.CreateInstance (t, 0).GetType ();
+ return t;
+ }
+
+ private static Type FindDocumentedTypeNonArray (MemberCore mc,
+ string identifier, DeclSpace ds, bool allowAlias)
+ {
+ switch (identifier) {
+ case "int":
+ return typeof (int);
+ case "uint":
+ return typeof (uint);
+ case "short":
+ return typeof (short);
+ case "ushort":
+ return typeof (ushort);
+ case "long":
+ return typeof (long);
+ case "ulong":
+ return typeof (ulong);
+ case "float":
+ return typeof (float);
+ case "double":
+ return typeof (double);
+ case "char":
+ return typeof (char);
+ case "decimal":
+ return typeof (decimal);
+ case "byte":
+ return typeof (byte);
+ case "sbyte":
+ return typeof (sbyte);
+ case "object":
+ return typeof (object);
+ case "bool":
+ return typeof (bool);
+ case "string":
+ return typeof (string);
+ case "void":
+ return typeof (void);
+ }
+ if (allowAlias) {
+ string alias = ds.LookupAlias (identifier);
+ if (alias != null)
+ identifier = alias;
+ }
+ Type t = ds.FindType (mc.Location, identifier);
+ if (t == null)
+ t = TypeManager.LookupTypeDirect (identifier);
+ return t;
+ }
+
+ //
+ // Returns a MemberInfo that is referenced in XML documentation
+ // (by "see" or "seealso" elements).
+ //
+ private static MemberInfo FindDocumentedMember (MemberCore mc,
+ Type type, string memberName, Type [] paramList,
+ DeclSpace ds, out int warningType, string cref)
+ {
+ warningType = 0;
+ MethodSignature msig = new MethodSignature (memberName, null, paramList);
+ MemberInfo [] mis = type.FindMembers (
+ MemberTypes.All,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
+ MethodSignature.method_signature_filter,
+ msig);
+ if (mis.Length > 0)
+ return mis [0];
+
+ if (paramList.Length == 0) {
+ // search for fields/events etc.
+ mis = type.FindMembers (
+ MemberTypes.All,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
+ Type.FilterName,
+ memberName);
+ return (mis.Length > 0) ? mis [0] : null;
+ }
+
+ // search for operators (whose parameters exactly
+ // matches with the list) and possibly report CS1581.
+ string oper = null;
+ string returnTypeName = null;
+ if (memberName.StartsWith ("implicit operator ")) {
+ oper = "op_Implicit";
+ returnTypeName = memberName.Substring (18).Trim (wsChars);
+ }
+ else if (memberName.StartsWith ("explicit operator ")) {
+ oper = "op_Explicit";
+ returnTypeName = memberName.Substring (18).Trim (wsChars);
+ }
+ else if (memberName.StartsWith ("operator ")) {
+ oper = memberName.Substring (9).Trim (wsChars);
+ switch (oper) {
+ // either unary or binary
+ case "+":
+ oper = paramList.Length == 2 ?
+ Binary.oper_names [(int) Binary.Operator.Addition] :
+ Unary.oper_names [(int) Unary.Operator.UnaryPlus];
+ break;
+ case "-":
+ oper = paramList.Length == 2 ?
+ Binary.oper_names [(int) Binary.Operator.Subtraction] :
+ Unary.oper_names [(int) Unary.Operator.UnaryNegation];
+ break;
+ // unary
+ case "!":
+ oper = Unary.oper_names [(int) Unary.Operator.LogicalNot]; break;
+ case "~":
+ oper = Unary.oper_names [(int) Unary.Operator.OnesComplement]; break;
+
+ case "++":
+ oper = "op_Increment"; break;
+ case "--":
+ oper = "op_Decrement"; break;
+ case "true":
+ oper = "op_True"; break;
+ case "false":
+ oper = "op_False"; break;
+ // binary
+ case "*":
+ oper = Binary.oper_names [(int) Binary.Operator.Multiply]; break;
+ case "/":
+ oper = Binary.oper_names [(int) Binary.Operator.Division]; break;
+ case "%":
+ oper = Binary.oper_names [(int) Binary.Operator.Modulus]; break;
+ case "&":
+ oper = Binary.oper_names [(int) Binary.Operator.BitwiseAnd]; break;
+ case "|":
+ oper = Binary.oper_names [(int) Binary.Operator.BitwiseOr]; break;
+ case "^":
+ oper = Binary.oper_names [(int) Binary.Operator.ExclusiveOr]; break;
+ case "<<":
+ oper = Binary.oper_names [(int) Binary.Operator.LeftShift]; break;
+ case ">>":
+ oper = Binary.oper_names [(int) Binary.Operator.RightShift]; break;
+ case "==":
+ oper = Binary.oper_names [(int) Binary.Operator.Equality]; break;
+ case "!=":
+ oper = Binary.oper_names [(int) Binary.Operator.Inequality]; break;
+ case "<":
+ oper = Binary.oper_names [(int) Binary.Operator.LessThan]; break;
+ case ">":
+ oper = Binary.oper_names [(int) Binary.Operator.GreaterThan]; break;
+ case "<=":
+ oper = Binary.oper_names [(int) Binary.Operator.LessThanOrEqual]; break;
+ case ">=":
+ oper = Binary.oper_names [(int) Binary.Operator.GreaterThanOrEqual]; break;
+ default:
+ warningType = 1584;
+ Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", paramList.Length == 2 ? "binary" : "unary");
+ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
+ return null;
+ }
+ }
+ // here we still does not consider return type (to
+ // detect CS1581 or CS1002+CS1584).
+ msig = new MethodSignature (oper, null, paramList);
+ mis = type.FindMembers (
+ MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static,
+ MethodSignature.method_signature_filter,
+ msig);
+ if (mis.Length == 0)
+ return null; // CS1574
+ MemberInfo mi = mis [0];
+ Type expected = mi is MethodInfo ?
+ ((MethodInfo) mi).ReturnType :
+ mi is PropertyInfo ?
+ ((PropertyInfo) mi).PropertyType :
+ null;
+ if (returnTypeName != null) {
+ Type returnType = FindDocumentedType (mc, returnTypeName, ds, true);
+ if (returnType == null || returnType != expected) {
+ warningType = 1581;
+ Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute '{0}'", cref);
+ return null;
+ }
+ }
+ return mis [0];
+ }
+
+ private static Type [] emptyParamList = new Type [0];
+
+ //
+ // Processes "see" or "seealso" elements.
+ // Checks cref attribute.
+ //
+ private static void HandleXrefCommon (MemberCore mc,
+ DeclSpace ds, XmlElement xref)
+ {
+ string cref = xref.GetAttribute ("cref").Trim (wsChars);
+ // when, XmlReader, "if (cref == null)"
+ if (!xref.HasAttribute ("cref"))
+ return;
+ if (cref.Length == 0)
+ Report.Warning (1001, 1, mc.Location, "Identifier expected");
+ // ... and continue until CS1584.
+
+ string signature; // "x:" are stripped
+ string name; // method invokation "(...)" are removed
+ string identifiers; // array indexer "[]" are removed
+ string parameters; // method parameter list
+
+ // strip 'T:' 'M:' 'F:' 'P:' 'E:' etc.
+ // Here, MS ignores its member kind. No idea why.
+ if (cref.Length > 2 && cref [1] == ':')
+ signature = cref.Substring (2).Trim (wsChars);
+ else
+ signature = cref;
+
+ int parensPos = signature.IndexOf ('(');
+ if (parensPos > 0 && signature [signature.Length - 1] == ')') {
+ name = signature.Substring (0, parensPos).Trim (wsChars);
+ parameters = signature.Substring (parensPos + 1, signature.Length - parensPos - 2);
+ }
+ else {
+ name = signature;
+ parameters = String.Empty;
+ }
+
+ string identifier = name;
+
+ if (name.Length > 0 && name [name.Length - 1] == ']') {
+ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
+ if (tmp [tmp.Length - 1] == '[')
+ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
+ }
+
+ // Check if identifier is valid.
+ // This check is not necessary to mark as error, but
+ // csc specially reports CS1584 for wrong identifiers.
+ foreach (string nameElem in identifier.Split ('.')) {
+ if (!Tokenizer.IsValidIdentifier (nameElem)
+ && nameElem.IndexOf ("operator") < 0) {
+ if (nameElem.EndsWith ("[]") &&
+ Tokenizer.IsValidIdentifier (
+ nameElem.Substring (
+ 0, nameElem.Length - 2)))
+ continue;
+
+ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
+ xref.SetAttribute ("cref", "!:" + signature);
+ return;
+ }
+ }
+
+ // check if parameters are valid
+ Type [] parameterTypes = emptyParamList;
+ if (parameters.Length > 0) {
+ string [] paramList = parameters.Split (',');
+ ArrayList plist = new ArrayList ();
+ for (int i = 0; i < paramList.Length; i++) {
+ string paramTypeName = paramList [i].Trim (wsChars);
+ Type paramType = FindDocumentedType (mc, paramTypeName, ds, true);
+ if (paramType == null) {
+ Report.Warning (1580, 1, mc.Location, "Invalid type for parameter '{0}' in XML comment cref attribute '{1}'", i + 1, cref);
+ return;
+ }
+ plist.Add (paramType);
+ }
+ parameterTypes = plist.ToArray (typeof (Type)) as Type [];
+ StringBuilder sb = new StringBuilder ();
+ sb.Append ('(');
+ for (int i = 0; i < parameterTypes.Length; i++) {
+ Type t = parameterTypes [i];
+ if (sb.Length > 1)
+ sb.Append (',');
+ sb.Append (t.FullName.Replace ('+', '.'));
+ }
+ sb.Append (')');
+ parameters = sb.ToString ();
+ }
+
+ Type type = FindDocumentedType (mc, name, ds, true);
+ if (type != null) {
+ xref.SetAttribute ("cref", "T:" + type.FullName.Replace ("+", "."));
+ return; // a type
+ }
+
+ // don't use identifier here. System[] is not alloed.
+ if (Namespace.IsNamespace (name)) {
+ xref.SetAttribute ("cref", "N:" + name);
+ return; // a namespace
+ }
+
+ int period = name.LastIndexOf ('.');
+ if (period > 0) {
+ string typeName = name.Substring (0, period);
+ string memberName = name.Substring (period + 1);
+ type = FindDocumentedType (mc, typeName, ds, false);
+ int warnResult;
+ if (type != null) {
+ MemberInfo mi = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref);
+ if (warnResult > 0)
+ return;
+ if (mi != null) {
+ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + type.FullName.Replace ("+", ".") + "." + memberName + parameters);
+ return; // a member of a type
+ }
+ }
+ }
+ else {
+ int warnResult;
+ MemberInfo mi = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref);
+ if (warnResult > 0)
+ return;
+ if (mi != null) {
+ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + ds.TypeBuilder.FullName.Replace ("+", ".") + "." + name);
+ return; // local member name
+ }
+ }
+
+ Report.Warning (1574, 1, mc.Location, "XML comment on '{0}' has cref attribute '{1}' that could not be resolved in '{2}'.", mc.GetSignatureForError (), cref, ds.GetSignatureForError ());
+
+ xref.SetAttribute ("cref", "!:" + name);
+ }
+
+ //
+ // Get a prefix from member type for XML documentation (used
+ // to formalize cref target name).
+ //
+ static string GetMemberDocHead (MemberTypes type)
+ {
+ switch (type) {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ return "M:";
+ case MemberTypes.Event:
+ return "E:";
+ case MemberTypes.Field:
+ return "F:";
+ case MemberTypes.NestedType:
+ case MemberTypes.TypeInfo:
+ return "T:";
+ case MemberTypes.Property:
+ return "P:";
+ }
+ return "!:";
+ }
+
+ // MethodCore
+
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public static string GetMethodDocCommentName (MethodCore mc, DeclSpace ds)
+ {
+ Parameter [] plist = mc.Parameters.FixedParameters;
+ Parameter parr = mc.Parameters.ArrayParameter;
+ string paramSpec = String.Empty;
+ if (plist != null) {
+ StringBuilder psb = new StringBuilder ();
+ foreach (Parameter p in plist) {
+ psb.Append (psb.Length != 0 ? "," : "(");
+ psb.Append (p.ParameterType.FullName.Replace ("+", "."));
+ }
+ paramSpec = psb.ToString ();
+ }
+ if (parr != null)
+ paramSpec += String.Concat (
+ paramSpec == String.Empty ? "(" : ",",
+ parr.ParameterType.FullName.Replace ("+", "."));
+
+ if (paramSpec.Length > 0)
+ paramSpec += ")";
+
+ string name = mc is Constructor ? "#ctor" : mc.Name;
+ return String.Concat (mc.DocCommentHeader, ds.Name, ".", name, paramSpec);
+ }
+
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ // FIXME: with a few effort, it could be done with XmlReader,
+ // that means removal of DOM use.
+ //
+ internal static void OnMethodGenerateDocComment (
+ MethodCore mc, DeclSpace ds, XmlElement el)
+ {
+ Hashtable paramTags = new Hashtable ();
+ foreach (XmlElement pelem in el.SelectNodes ("param")) {
+ int i;
+ string xname = pelem.GetAttribute ("name");
+ if (xname == "")
+ continue; // really? but MS looks doing so
+ if (xname != "" && mc.Parameters.GetParameterByName (xname, out i) == null)
+ Report.Warning (1572, 2, mc.Location, "XML comment on '{0}' has a 'param' tag for '{1}', but there is no such parameter.", mc.Name, xname);
+ else if (paramTags [xname] != null)
+ Report.Warning (1571, 2, mc.Location, "XML comment on '{0}' has a duplicate param tag for '{1}'", mc.Name, xname);
+ paramTags [xname] = xname;
+ }
+ Parameter [] plist = mc.Parameters.FixedParameters;
+ Parameter parr = mc.Parameters.ArrayParameter;
+ if (plist != null) {
+ foreach (Parameter p in plist) {
+ if (paramTags.Count > 0 && paramTags [p.Name] == null)
+ Report.Warning (1573, 4, mc.Location, "Parameter '{0}' has no matching param tag in the XML comment for '{1}' (but other parameters do)", mc.Name, p.Name);
+ }
+ }
+ }
+
+ // Enum
+ public static void GenerateEnumDocComment (Enum e, DeclSpace ds)
+ {
+ GenerateDocComment (e, ds);
+ foreach (string name in e.ordered_enums) {
+ MemberCore mc = e.GetDefinition (name);
+ GenerateDocComment (mc, e);
+ }
+ }
+ }
+
+ //
+ // Implements XML documentation generation.
+ //
+ public class Documentation
+ {
+ public Documentation (string xml_output_filename)
+ {
+ docfilename = xml_output_filename;
+ XmlDocumentation = new XmlDocument ();
+ XmlDocumentation.PreserveWhitespace = false;
+ }
+
+ private string docfilename;
+
+ //
+ // Used to create element which helps well-formedness checking.
+ //
+ public XmlDocument XmlDocumentation;
+
+ //
+ // The output for XML documentation.
+ //
+ public XmlWriter XmlCommentOutput;
+
+ //
+ // Stores XmlDocuments that are included in XML documentation.
+ // Keys are included filenames, values are XmlDocuments.
+ //
+ public Hashtable StoredDocuments = new Hashtable ();
+
+ //
+ // Stores comments on partial types (should handle uniquely).
+ // Keys are PartialContainers, values are comment strings
+ // (didn't use StringBuilder; usually we have just 2 or more).
+ //
+ public IDictionary PartialComments = new ListDictionary ();
+
+ //
+ // Outputs XML documentation comment from tokenized comments.
+ //
+ public bool OutputDocComment (string asmfilename)
+ {
+ XmlTextWriter w = null;
+ try {
+ w = new XmlTextWriter (docfilename, null);
+ w.Indentation = 4;
+ w.Formatting = Formatting.Indented;
+ w.WriteStartDocument ();
+ w.WriteStartElement ("doc");
+ w.WriteStartElement ("assembly");
+ w.WriteStartElement ("name");
+ w.WriteString (Path.ChangeExtension (asmfilename, null));
+ w.WriteEndElement (); // name
+ w.WriteEndElement (); // assembly
+ w.WriteStartElement ("members");
+ XmlCommentOutput = w;
+ GenerateDocComment ();
+ w.WriteFullEndElement (); // members
+ w.WriteEndElement ();
+ w.WriteWhitespace (Environment.NewLine);
+ w.WriteEndDocument ();
+ return true;
+ } catch (Exception ex) {
+ Report.Error (1569, "Error generating XML documentation file '{0}' ('{1}')", docfilename, ex.Message);
+ return false;
+ } finally {
+ if (w != null)
+ w.Close ();
+ }
+ }
+
+ //
+ // Fixes full type name of each documented types/members up.
+ //
+ public void GenerateDocComment ()
+ {
+ TypeContainer root = RootContext.Tree.Types;
+ if (root.Interfaces != null)
+ foreach (Interface i in root.Interfaces)
+ DocUtil.GenerateTypeDocComment (i, null);
+
+ if (root.Types != null)
+ foreach (TypeContainer tc in root.Types)
+ DocUtil.GenerateTypeDocComment (tc, null);
+
+ if (root.Parts != null) {
+ IDictionary comments = PartialComments;
+ foreach (ClassPart cp in root.Parts) {
+ if (cp.DocComment == null)
+ continue;
+ comments [cp] = cp;
+ }
+ }
+
+ if (root.Delegates != null)
+ foreach (Delegate d in root.Delegates)
+ DocUtil.GenerateDocComment (d, null);
+
+ if (root.Enums != null)
+ foreach (Enum e in root.Enums)
+ DocUtil.GenerateEnumDocComment (e, null);
+
+ IDictionary table = new ListDictionary ();
+ foreach (ClassPart cp in PartialComments.Keys) {
+ table [cp.PartialContainer] += cp.DocComment;
+ }
+ foreach (PartialContainer pc in table.Keys) {
+ pc.DocComment = table [pc] as string;
+ DocUtil.GenerateDocComment (pc, null);
+ }
+ }
+ }
+}
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
//
namespace Mono.CSharp
using System.IO;
using System.Text;
using System.Globalization;
+ using System.Xml;
+ using System.Diagnostics;
public enum Target {
Library, Exe, Module, WinExe
" -nostdlib[+|-] Does not load core libraries\n" +
" -nowarn:W1[,W2] Disables one or more warnings\n" +
" -out:FNAME Specifies output file\n" +
+ " -doc:XMLFILE Generates xml documentation into specified file\n" +
" -pkg:P1[,Pn] References packages P1..Pn\n" +
" --expect-error X Expect that error X will be encountered\n" +
" -recurse:SPEC Recursively compiles the files in SPEC ([dir]/file)\n" +
}
case "/doc": {
if (value == ""){
- Report.Error (5, arg + " requires an argument");
+ Report.Error (2006, arg + " requires an argument");
Environment.Exit (1);
}
- // TODO handle the /doc argument to generate xml doc
+ RootContext.Documentation = new Documentation (value);
return true;
}
case "/lib": {
if (timestamps)
ShowTime ("Resolving tree");
RootContext.ResolveTree ();
+
if (Report.Errors > 0)
return false;
if (timestamps)
RootContext.PopulateTypes ();
RootContext.DefineTypes ();
+ if (RootContext.Documentation != null &&
+ !RootContext.Documentation.OutputDocComment (
+ output_file))
+ return false;
+
TypeManager.InitCodeHelpers ();
//
#endif
return (Report.Errors == 0);
}
-
}
//
Report.Warning (code, loc, format, args);
}
+ // Not nice but we have broken hierarchy
+ public virtual void CheckMarshallByRefAccess (Type container) {}
+
/// <summary>
/// Tests presence of ObsoleteAttribute and report proper error
/// </summary>
return new CharConstant ((char)v);
else if (t == TypeManager.bool_type)
return new BoolConstant ((bool) v);
+ else if (t == TypeManager.decimal_type)
+ return new DecimalConstant ((decimal) v);
else if (TypeManager.IsEnumType (t)){
Type real_type = TypeManager.TypeToCoreType (v.GetType ());
if (real_type == t)
return null;
}
+ public override void CheckMarshallByRefAccess (Type container)
+ {
+ if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ Report.Error (1690, loc, "Cannot call '{0}' method, property, or indexer because it is a value type member of a marshal-by-reference class", Name);
+ }
+ }
+
public bool VerifyFixed (bool is_expression)
{
IVariable variable = instance_expr as IVariable;
{
Emit (ec, false);
}
-
+
public void AddressOf (EmitContext ec, AddressOp mode)
{
ILGenerator ig = ec.ig;
instance_expr = instance_expr.DoResolve (ec);
if (instance_expr == null)
return false;
+
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
}
if (must_do_cs1540_check && (instance_expr != null)) {
public override void Emit (EmitContext ec)
{
- Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)");
+ if (instance_expr is This)
+ Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=, try calling the actual delegate");
+ else
+ Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
+ "(except on the defining type)", Name);
}
public void EmitAddOrRemove (EmitContext ec, Expression source)
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;
+using System.Xml;
namespace Mono.CSharp {
protected override void VerifyObsoleteAttribute()
{
}
+
+ public override string DocCommentHeader {
+ get { return "F:"; }
+ }
}
/// <summary>
/// Enumeration container
/// </summary>
public class Enum : DeclSpace {
- ArrayList ordered_enums;
+ public ArrayList ordered_enums;
public Expression BaseType;
/// Adds @name to the enumeration space, with @expr
/// being its definition.
/// </summary>
- public void AddEnumMember (string name, Expression expr, Location loc, Attributes opt_attrs)
+ public void AddEnumMember (string name, Expression expr, Location loc, Attributes opt_attrs, string documentation)
{
if (name == "value__") {
Report.Error (76, loc, "An item in an enumeration can't have an identifier `value__'");
}
EnumMember em = new EnumMember (this, expr, name, loc, opt_attrs);
+ em.DocComment = documentation;
if (!AddToContainer (em, false, name, ""))
return;
{
// UnderlyingType is never obsolete
}
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal override void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateEnumDocComment (this, ds);
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
}
}
Expression ResolveOperator (EmitContext ec)
{
- Type expr_type = Expr.Type;
+ //
+ // Step 1: Default operations on CLI native types.
+ //
+
+ // Attempt to use a constant folding operation.
+ if (Expr is Constant){
+ Expression result;
+
+ if (Reduce (ec, (Constant) Expr, out result))
+ return result;
+ }
//
- // Step 1: Perform Operator Overload location
+ // Step 2: Perform Operator Overload location
//
+ Type expr_type = Expr.Type;
Expression mg;
string op_name;
if (expr_type == null)
return null;
- //
- // Step 2: Default operations on CLI native types.
- //
-
- // Attempt to use a constant folding operation.
- if (Expr is Constant){
- Expression result;
-
- if (Reduce (ec, (Constant) Expr, out result))
- return result;
- }
-
switch (Oper){
case Operator.LogicalNot:
if (expr_type != TypeManager.bool_type) {
return null;
}
lr.local_info.AddressTaken = true;
+ lr.local_info.Used = true;
}
// According to the specs, a variable is considered definitely assigned if you take
{
if (local_info == null) {
local_info = Block.GetLocalInfo (Name);
+
+ // is out param
+ if (lvalue_right_side == EmptyExpression.Null)
+ local_info.Used = true;
+
is_readonly = local_info.ReadOnly;
}
if (instance.GetType () != typeof (This)){
if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
- Report.Error (197, loc,
- "Can not pass a type that derives from MarshalByRefObject with out or ref");
+ Report.SymbolRelatedToPreviousError (fe.InstanceExpression.Type);
+ Report.Error (197, loc, "Cannot pass '{0}' as ref or out or take its address because it is a member of a marshal-by-reference class",
+ fe.Name);
return false;
}
}
}
}
+ if (mg.InstanceExpression != null)
+ mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
+
eclass = ExprClass.Value;
return this;
}
if (IsDelegate){
RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
if (RequestedType != null)
- if (!(RequestedType is NewDelegate))
+ if (!(RequestedType is DelegateCreation))
throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
return RequestedType;
}
return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
}
+ // TODO: possible optimalization
+ // Cache resolved constant result in FieldBuilder <-> expresion map
public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
Expression left, Location loc,
Expression left_original)
FieldInfo fi = fe.FieldInfo.Mono_GetGenericFieldDefinition ();
Type decl_type = fi.DeclaringType;
- if (fi is FieldBuilder) {
+ bool is_emitted = fi is FieldBuilder;
+ Type t = fi.FieldType;
+
+ if (is_emitted) {
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
if (c != null) {
object real_value = ((Constant) c.Expr).GetValue ();
- return Constantify (real_value, fi.FieldType);
+ return Constantify (real_value, t);
}
}
+ // IsInitOnly is because of MS compatibility, I don't know why but they emit decimal constant as InitOnly
+ if (fi.IsInitOnly && !is_emitted && t == TypeManager.decimal_type) {
+ object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+ if (attrs.Length == 1)
+ return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+ }
+
if (fi.IsLiteral) {
- Type t = fi.FieldType;
-
object o;
- if (fi is FieldBuilder)
+ if (is_emitted)
o = TypeManager.GetValue ((FieldBuilder) fi);
else
o = fi.GetValue (fi);
return exp;
}
- if (fi.FieldType.IsPointer && !ec.InUnsafe){
+ if (t.IsPointer && !ec.InUnsafe){
UnsafeError (loc);
return null;
}
UnsafeError (loc);
return null;
}
+
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
eclass = ExprClass.IndexerAccess;
return this;
}
}
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+
eclass = ExprClass.IndexerAccess;
return this;
}
loc = l;
}
+ public Expression Source {
+ get {
+ return source;
+ }
+ }
+
public override Expression DoResolve (EmitContext ec)
{
//
MethodInfo [] mi;
Type t = missing.Type;
+ if (!t.IsInterface)
+ continue;
+
if (t is TypeBuilder){
TypeContainer iface;
for (i = 0; i < top; i++){
Type type = pending_implementations [i].type;
int j = 0;
-
+
foreach (MethodInfo mi in pending_implementations [i].methods){
if (mi == null)
continue;
if (pending_implementations [i].found [j]) {
string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
- Report.Error (536, container.Location, "'{0}' does not implement interface member '{1}'. '{2}.{3}' is either static, not public, or has the wrong return type",
- container.Name, TypeManager.CSharpSignature (mi), container.Name, methodLabel[methodLabel.Length - 1]);
+ Report.Error (536, container.Location,
+ "'{0}' does not implement interface member '{1}'. '{2}.{3}' " +
+ "is either static, not public, or has the wrong return type",
+ container.Name, TypeManager.CSharpSignature (mi),
+ container.Name, methodLabel[methodLabel.Length - 1]);
}
else {
Report.Error (535, container.Location, "'{0}' does not implement interface member '{1}'",
/// <summary>
/// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
/// </summary>
- static StringCollection related_symbols = new StringCollection ();
+ static StringCollection extra_information = new StringCollection ();
abstract class AbstractMessage {
msg.Append (' ');
}
msg.AppendFormat ("{0} CS{1:0000}: {2}", MessageType, code, text);
- Console.WriteLine (msg.ToString ());
+ Console.Error.WriteLine (msg.ToString ());
- foreach (string s in related_symbols) {
- Console.WriteLine (String.Concat (s, MessageType, ')'));
- }
- related_symbols.Clear ();
+ foreach (string s in extra_information)
+ Console.Error.WriteLine (s + MessageType + ")");
+
+ extra_information.Clear ();
if (Stacktrace)
Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
public override void Print(int code, string location, string text)
{
if (!IsEnabled (code)) {
- related_symbols.Clear ();
+ extra_information.Clear ();
return;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// IF YOU ADD A NEW WARNING YOU HAVE TO DUPLICATE ITS ID HERE
+ //
public static bool IsValidWarning (int code)
{
- int[] all_warnings = new int[] { 28, 67, 78, 105, 108, 109, 114, 192, 168, 169, 183, 184, 219, 251, 612, 618, 626, 628, 642, 649,
- 659, 660, 661, 672, 1030, 1522, 1616, 1691, 1692, 1901, 2002, 2023, 3012, 3019, 8024, 8028
- };
+ int[] all_warnings = new int[] {
+ 28, 67, 78, 105, 108, 109, 114, 192, 168, 169, 183, 184, 219, 251, 612, 618, 626, 628, 642, 649,
+ 659, 660, 661, 672, 1030, 1522, 1616, 1691, 1692, 1901, 2002, 2023, 3012, 3019, 8024, 8028
+ };
+
foreach (int i in all_warnings) {
if (i == code)
return true;
static public void LocationOfPreviousError (Location loc)
{
- Console.WriteLine (String.Format ("{0}({1}) (Location of symbol related to previous error)", loc.Name, loc.Row));
+ Console.Error.WriteLine (String.Format ("{0}({1}) (Location of symbol related to previous error)", loc.Name, loc.Row));
}
static public void RuntimeMissingSupport (Location loc, string feature)
static void SymbolRelatedToPreviousError (string loc, string symbol)
{
- related_symbols.Add (String.Format ("{0}: '{1}' (name of symbol related to previous ", loc, symbol));
+ extra_information.Add (String.Format ("{0}: '{1}' (name of symbol related to previous ", loc, symbol));
+ }
+
+ public static void ExtraInformation (Location loc, string msg)
+ {
+ extra_information.Add (String.Format ("{0}({1}) {2}", loc.Name, loc.Row, msg));
}
public static WarningRegions RegisterWarningRegion (Location location)
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
+using System.Xml;
namespace Mono.CSharp {
public static string StrongNameKeyContainer;
public static bool StrongNameDelaySign = false;
+ //
+ // If set, enable XML documentation generation
+ //
+ public static Documentation Documentation;
+
//
// Constructor
//
"System.Security.UnverifiableCodeAttribute",
"System.Security.Permissions.SecurityAttribute",
"System.Runtime.CompilerServices.IndexerNameAttribute",
+ "System.Runtime.CompilerServices.DecimalConstantAttribute",
"System.Runtime.InteropServices.InAttribute",
"System.Runtime.InteropServices.StructLayoutAttribute",
"System.Runtime.InteropServices.FieldOffsetAttribute",
}
t = NamespaceLookup (ds, name, num_type_params, loc);
- if (t != null){
+ if (!silent || t != null){
ds.Cache [name] = t;
return t;
}
if (allowed_types == null){
allowed_types = new Type [] {
+ TypeManager.int32_type,
+ TypeManager.uint32_type,
TypeManager.sbyte_type,
TypeManager.byte_type,
TypeManager.short_type,
TypeManager.ushort_type,
- TypeManager.int32_type,
- TypeManager.uint32_type,
TypeManager.int64_type,
TypeManager.uint64_type,
TypeManager.char_type,
if (e == null)
continue;
+ //
+ // Ignore over-worked ImplicitUserConversions that do
+ // an implicit conversion in addition to the user conversion.
+ //
+ if (e is UserCast){
+ UserCast ue = e as UserCast;
+
+ if (ue.Source != Expr)
+ e = null;
+ }
+
if (converted != null){
- Report.Error (-12, loc, "More than one conversion to an integral " +
- " type exists for type `" +
- TypeManager.CSharpName (Expr.Type)+"'");
+ Report.ExtraInformation (
+ loc,
+ String.Format ("reason: more than one conversion to an integral type exist for type {0}",
+ TypeManager.CSharpName (Expr.Type)));
return null;
- } else
+ } else {
converted = e;
+ }
}
return converted;
}
void EmitExpressionFinally (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Label skip = ig.DefineLabel ();
- ig.Emit (OpCodes.Ldloc, local_copy);
- ig.Emit (OpCodes.Brfalse, skip);
- ig.Emit (OpCodes.Ldloc, local_copy);
- ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
- ig.MarkLabel (skip);
+ if (!local_copy.LocalType.IsValueType) {
+ Label skip = ig.DefineLabel ();
+ ig.Emit (OpCodes.Ldloc, local_copy);
+ ig.Emit (OpCodes.Brfalse, skip);
+ ig.Emit (OpCodes.Ldloc, local_copy);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ ig.MarkLabel (skip);
+ } else {
+ Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, local_copy.LocalType, "Dispose", Mono.CSharp.Location.Null);
+
+ if (!(ml is MethodGroupExpr)) {
+ ig.Emit (OpCodes.Ldloc, local_copy);
+ ig.Emit (OpCodes.Box, local_copy.LocalType);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ } else {
+ MethodInfo mi = null;
+
+ foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+ if (TypeManager.GetArgumentTypes (mk).Length == 0) {
+ mi = mk;
+ break;
+ }
+ }
+
+ if (mi == null) {
+ Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+ return;
+ }
+
+ ig.Emit (OpCodes.Ldloca, local_copy);
+ ig.Emit (OpCodes.Call, mi);
+ }
+ }
}
public override bool Resolve (EmitContext ec)
static public Type runtime_argument_handle_type;
static public Type attribute_type;
static public Type attribute_usage_type;
+ static public Type decimal_constant_attribute_type;
static public Type dllimport_type;
static public Type unverifiable_code_type;
static public Type methodimpl_attr_type;
static public ConstructorInfo object_ctor;
static public ConstructorInfo cons_param_array_attribute;
static public ConstructorInfo void_decimal_ctor_five_args;
+ static public ConstructorInfo void_decimal_ctor_int_arg;
static public ConstructorInfo unverifiable_code_ctor;
static public ConstructorInfo invalid_operation_ctor;
static public ConstructorInfo default_member_ctor;
+ static public ConstructorInfo decimal_constant_attribute_ctor;
// <remarks>
// Holds the Array of Assemblies that have been loaded
typed_reference_type = CoreLookupType ("System.TypedReference");
arg_iterator_type = CoreLookupType ("System.ArgIterator");
mbr_type = CoreLookupType ("System.MarshalByRefObject");
+ decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
//
// Sigh. Remove this before the release. Wonder what versions of Mono
void_decimal_ctor_five_args = GetConstructor (
decimal_type, dec_arg);
+ void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
+
//
// Attributes
//
unverifiable_code_ctor = GetConstructor (
unverifiable_code_type, void_arg);
+ decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
+ { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
+
default_member_ctor = GetConstructor (default_member_type, string_);
//
DeclSpace tc = LookupDeclSpace (t);
if (tc != null) {
if (!tc.IsGeneric)
- throw new InvalidOperationException ();
+ return Type.EmptyTypes;
TypeParameter[] tparam = tc.TypeParameters;
Type[] ret = new Type [tparam.Length];
public static Type[] ExpandInterfaces (EmitContext ec, TypeExpr [] base_interfaces)
{
ArrayList new_ifaces = new ArrayList ();
-
+
foreach (TypeExpr iface in base_interfaces){
TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
if (texpr == null)
return (object)(convert_value.ToChar (nf_provider));
else if (conversionType.Equals (typeof (DateTime)))
return (object)(convert_value.ToDateTime (nf_provider));
- else if (conversionType.Equals (typeof (Decimal)))
+ else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
return (object)(convert_value.ToDecimal (nf_provider));
else if (conversionType.Equals (typeof (Double)))
return (object)(convert_value.ToDouble (nf_provider));
return TypeManager.int64_type;
case TypeCode.UInt64:
return TypeManager.uint64_type;
- case TypeCode.Single:
- return TypeManager.float_type;
- case TypeCode.Double:
- return TypeManager.double_type;
+ case TypeCode.Single:
+ return TypeManager.float_type;
+ case TypeCode.Double:
+ return TypeManager.double_type;
case TypeCode.String:
return TypeManager.string_type;
+ case TypeCode.Decimal:
+ return TypeManager.decimal_type;
default:
if (t == typeof (void))
return TypeManager.void_type;
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * CodeGen.cs: Correctly compute the name of a nested class,
+ currently it was ignoring anything above level 1.
+
2004-07-27 Jackson Harper <jackson@ximian.com>
* Driver.cs: Make debug switch compatible with MS's add debug to
+2004-12-02 Jackson Harper <jackson@ximian.com>
+
+ * ExternTypeRefInst.cs: When converting to arrays we loose our valuetypedness.
+
+2004-12-02 Jackson Harper <jackson@ximian.com>
+
+ * MethodDef.cs: Abstract methods don't get bodies. Even if there
+ are bodies there.
+
+2004-12-02 Jackson Harper <jackson@ximian.com>
+
+ * MethodDef.cs: If the type is an interface auto set fields to
+ static (and give a warning if they are not static), and set
+ methods to abstract virtual (and give warning if they were not already).
+ * FieldDef.cs:
+ * TypeDef.cs: Accessors and convience properties for getting and
+ setting the method/field attributes.
+
+
+2004-12-02 Jackson Harper <jackson@ximian.com>
+
+ * FieldDef.cs: Set the underlying type for bytearray data constants. This
+ fixes bug #70153 and #70154 which my previous fix caused.
+
2004-08-01 Atsushi Enomoto <atsushi@ximian.com>
* DebuggingInfo.cs : csc build fix (see bug #62230).
using System.Collections;\r
using System.Reflection;\r
using System.Reflection.Emit;\r
+using System.Text;\r
\r
namespace Mono.ILASM {\r
\r
private string current_namespace;\r
private TypeDef current_typedef;\r
private MethodDef current_methoddef;\r
- private Stack typedef_stack;\r
+ private ArrayList typedef_stack;\r
+ private int typedef_stack_top;\r
private SymbolWriter symwriter;\r
\r
private byte [] assembly_public_key;\r
\r
type_manager = new TypeManager (this);\r
extern_table = new ExternTable ();\r
- typedef_stack = new Stack ();\r
+ typedef_stack = new ArrayList ();\r
+ typedef_stack_top = 0;\r
global_field_table = new Hashtable ();\r
global_method_table = new Hashtable ();\r
\r
TypeDef outer = null;\r
string cache_name = CacheName (name);\r
\r
- if (typedef_stack.Count > 0) {\r
- outer = (TypeDef) typedef_stack.Peek ();\r
- cache_name = CacheName (outer.Name + '/' + name);\r
+ if (typedef_stack_top > 0) {\r
+ StringBuilder sb = new StringBuilder ();\r
+ \r
+ for (int i = 0; i < typedef_stack_top; i++){\r
+ outer = (TypeDef) typedef_stack [i];\r
+ sb.Append (outer.Name);\r
+ sb.Append ("/");\r
+ }\r
+ sb.Append (name);\r
+ cache_name = CacheName (sb.ToString ());\r
}\r
\r
TypeDef typedef = type_manager[cache_name];\r
if (typedef != null) {\r
// Class head is allready defined, we are just reopening the class\r
current_typedef = typedef;\r
- typedef_stack.Push (current_typedef);\r
+ typedef_stack.Add (current_typedef);\r
+ typedef_stack_top++;\r
return;\r
}\r
\r
\r
type_manager[cache_name] = typedef;\r
current_typedef = typedef;\r
- typedef_stack.Push (typedef);\r
+ typedef_stack.Add (typedef);\r
+ typedef_stack_top++;\r
}\r
\r
public void AddFieldDef (FieldDef fielddef)\r
\r
public void EndTypeDef ()\r
{\r
- typedef_stack.Pop ();\r
+ typedef_stack_top--;\r
+ typedef_stack.RemoveAt (typedef_stack_top);\r
\r
- if (typedef_stack.Count > 0)\r
- current_typedef = (TypeDef) typedef_stack.Peek ();\r
+ if (typedef_stack_top > 0)\r
+ current_typedef = (TypeDef) typedef_stack [typedef_stack_top-1];\r
else\r
current_typedef = null;\r
\r
public void MakeArray ()
{
+ is_valuetypeinst = false;
type_ref.MakeArray ();
}
public void MakeBoundArray (ArrayList bounds)
{
+ is_valuetypeinst = false;
type_ref.MakeBoundArray (bounds);
}
get { return field_def; }
}
+ public bool IsStatic {
+ get { return (attr & PEAPI.FieldAttr.Static) != 0; }
+ }
+
+ public PEAPI.FieldAttr Attributes {
+ get { return attr; }
+ set { attr = value; }
+ }
+
public void SetOffset (uint val)
{
offset_set = true;
if (offset_set)
field_def.SetOffset (offset);
- if (value_set)
- field_def.AddValue (constant);
+ if (value_set) {
+ PEAPI.ByteArrConst dc = constant as PEAPI.ByteArrConst;
+ if (dc != null)
+ dc.Type = type.PeapiType;
+ field_def.AddValue (constant);
+ }
if (at_data_id != null) {
PEAPI.DataConstant dc = code_gen.GetDataConst (at_data_id);
get { return methoddef; }
}
+ public PEAPI.MethAttr Attributes {
+ get { return meth_attr; }
+ set { meth_attr = value; }
+ }
+
public bool IsVararg {
get { return (call_conv & PEAPI.CallConv.Vararg) != 0; }
}
get { return (meth_attr & PEAPI.MethAttr.Static) != 0; }
}
+ public bool IsVirtual {
+ get { return (meth_attr & PEAPI.MethAttr.Virtual) != 0; }
+ }
+
+ public bool IsAbstract {
+ get { return (meth_attr & PEAPI.MethAttr.Abstract) != 0; }
+ }
+
public ITypeRef[] ParamTypeList () {
if (param_list == null)
WriteCode (code_gen, methoddef);
- code_gen.Report.Message (String.Format ("Assembled method '<Module>'::{0}", name));
+ //code_gen.Report.Message (String.Format ("Assembled method '<Module>'::{0}", name));
is_defined = true;
}
Resolve (code_gen, (PEAPI.ClassDef) typedef.ClassDef);
WriteCode (code_gen, methoddef);
- code_gen.Report.Message (String.Format ("Assembled method {0}::{1}", typedef.FullName, name)); is_defined = true;
+ //code_gen.Report.Message (String.Format ("Assembled method {0}::{1}", typedef.FullName, name)); is_defined = true;
}
public void AddInstr (IInstr instr)
protected void WriteCode (CodeGen code_gen, PEAPI.MethodDef methoddef)
{
+ if (IsAbstract)
+ return;
+
if (entry_point)
methoddef.DeclareEntryPoint ();
get { return current_property; }
}
+ public bool IsInterface {
+ get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
+ }
public void AddOverride (MethodDef body, ITypeRef parent, string name)
{
public void AddFieldDef (FieldDef fielddef)
{
+ if (IsInterface && !fielddef.IsStatic) {
+ Console.WriteLine ("warning -- Non-static field in interface, set to such");
+ fielddef.Attributes |= PEAPI.FieldAttr.Static;
+ }
+
field_table.Add (fielddef.Name, fielddef);
field_list.Add (fielddef);
}
public void AddMethodDef (MethodDef methoddef)
{
+ if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
+ Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
+ methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
+ }
+
method_table.Add (methoddef.Signature, methoddef);
}
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * ILParser.jay: Added D_STACKRESERVE token.
+
+ (prop_head, event_head): Allow it to take a compound name (for explicit
+ interface implementations of properties).
+
2004-07-21 Jackson Harper <jackson@ximian.com>
* ILParser.jay: Clones ExternTypeRefInsts as well as
%token D_REMOVEON\r
%token D_SET\r
%token D_SIZE\r
+%token D_STACKRESERVE\r
%token D_SUBSYSTEM\r
%token D_TITLE\r
%token D_TRY\r
}\r
;\r
\r
-event_head : D_EVENT event_attr type_spec id\r
+event_head : D_EVENT event_attr type_spec comp_name\r
{\r
EventDef event_def = new EventDef ((FeatureAttr) $2,\r
(ITypeRef) $3, (string) $4);\r
}\r
;\r
\r
-prop_head : D_PROPERTY prop_attr type id OPEN_PARENS type_list CLOSE_PARENS init_opt\r
+prop_head : D_PROPERTY prop_attr type comp_name OPEN_PARENS type_list CLOSE_PARENS init_opt\r
{\r
PropertyDef prop_def = new PropertyDef ((FeatureAttr) $2, (ITypeRef) $3,\r
(string) $4, (ArrayList) $6);\r
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * ILTable.cs: Add new .stackreserve token.
+
2004-07-27 Martin Baulig <martin@ximian.com>
* ILTokenizer.cs (ILTokenizer.Location): New public property.
directives [".removeon"] = new ILToken (Token.D_REMOVEON, ".removeon");\r
directives [".set"] = new ILToken (Token.D_SET, ".set");\r
directives [".size"] = new ILToken (Token.D_SIZE, ".size");\r
+ directives [".stackreserve"] = new ILToken (Token.D_STACKRESERVE, ".stackreserve");\r
directives [".subsystem"] = new ILToken (Token.D_SUBSYSTEM, ".subsystem");\r
directives [".title"] = new ILToken (Token.D_TITLE, ".title");\r
directives [".try"] = new ILToken (Token.D_TRY, ".try");\r
+2004-12-03 Miguel de Icaza <miguel@ximian.com>
+
+ * delegate.cs: Only allow this on new versions of the language.
+
+2004-12-02 Duncan Mak <duncan@ximian.com>
+
+ * ecore.cs (PropertyExpr.IsAccessorAccessible): Moved to
+ Expression class.
+ (Expression.IsAccessorAccessible): Moved from the PropertyExpr to
+ here as a static method. Take an additional bool out parameter
+ `must_do_cs1540_check' for signaling to InstanceResolve.
+ (PropertyExpr.InstanceResolve): Removed the `must_do_cs1540_check'
+ member field from PropertyExpr class and made it an argument of
+ the method instead.
+ (EventExpr.InstanceResolve): Copied from PropertyExpr, removed the
+ check for MarshalByRefObject, and report CS0122 instead of CS1540.
+ (EventExpr.DoResolve): Call IsAccessorAccessible on `add_accessor'
+ and `remove_accessor' as well as InstanceResolve: report CS0122
+ where applicable.
+
+ Fixes #70129.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ Fix test-327.cs, test-328.cs, and put in early infrastructure
+ for eventually fixing #52697.
+ * namespace.cs (NamespaceEntry.LookupForUsing): New method.
+ (NamespaceEntry.LookupNamespaceOrType): New method, refactored
+ from other methods.
+ (NamespaceEntry.Lookup): Remove 'ignore_using' flag.
+ (AliasEntry.Resolve, UsingEntry.Resolve): Use 'LookupForUsing'.
+ (VerifyUsing, error246): Update.
+ * rootcontext.cs (RootContext.NamespaceLookup): Just use
+ 'NamespaceEntry.LookupNamespaceOrType'.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, call AnonymousMethod.Compatible() on it.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ Disable XML documentation support in 'basic' profile.
+ * decl.cs, class.cs [BOOTSTRAP_WITH_OLDLIB]: Don't import System.Xml.
+ Redirect XmlElement to System.Object.
+ * driver.cs, enum.cs, rootcontext.cs: Don't reference System.Xml.
+ * doc.cs [BOOTSTRAP_WITH_OLDLIB]: Disable compile.
+ * mcs.exe.sources: Add doc-bootstrap.cs.
+ * doc-bootstrap.cs: New file. Contains empty stub implementation
+ of doc.cs.
+
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * cs-tokenizer.cs : Only '////' is rejected. Other non-whitespace
+ comments are allowed.
+
+2004-12-03 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * delegate.cs: Add checks for subtypes in paramaters and return values
+ in VerifyMethod () to add support for Covariance/Contravariance
+ in delegates.
+
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * report.cs: Remove extra closing parenthesis.
+
+ * convert.cs (Error_CannotImplicitConversion): If the name of the
+ types are the same, provide some extra information.
+
+ * class.cs (FieldBase): Use an unused bit field from the field to
+ encode the `has_offset' property from the FieldMember. This saves
+ a couple of Ks on bootstrap compilation.
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, return the AnonymousMethod resolved
+ expression.
+
+ * expression.cs (New.DoResolve): Allow return values from
+ NewDelegate to also include AnonymousMethods.
+
+ Fixes #70150.
+
+2004-12-02 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #70102
+ * attribute.cs (Resolve): Improved implementation of params
+ attribute arguments.
+
+ * support.cs (ParameterData): Add HasParams to be faster.
+
2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
all things are for /doc support:
return null;
}
-
+
if (target_type == source_type){
if (source is New && target_type.IsValueType &&
(target.eclass != ExprClass.IndexerAccess) && (target.eclass != ExprClass.PropertyAccess)){
ParameterData pd = Invocation.GetParameterData (constructor);
- int group_in_params_array = Int32.MaxValue;
- int pc = pd.Count;
- if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
- group_in_params_array = pc-1;
+ int last_real_param = pd.Count;
+ if (pd.HasParams) {
+ // When the params is not filled we need to put one
+ if (last_real_param > pos_arg_count) {
+ object [] new_pos_values = new object [pos_arg_count + 1];
+ pos_values.CopyTo (new_pos_values, 0);
+ new_pos_values [pos_arg_count] = new object [] {} ;
+ pos_values = new_pos_values;
+ }
+ last_real_param--;
+ }
for (int j = 0; j < pos_arg_count; ++j) {
Argument a = (Argument) pos_args [j];
return null;
}
- if (j < group_in_params_array)
+ if (j < last_real_param)
continue;
- if (j == group_in_params_array){
- object v = pos_values [j];
- int count = pos_arg_count - j;
-
- object [] array = new object [count];
+ if (j == last_real_param) {
+ object [] array = new object [pos_arg_count - last_real_param];
+ array [0] = pos_values [j];
pos_values [j] = array;
- array [0] = v;
- } else {
- object [] array = (object []) pos_values [group_in_params_array];
-
- array [j - group_in_params_array] = pos_values [j];
+ continue;
}
+
+ object [] params_array = (object []) pos_values [last_real_param];
+ params_array [j - last_real_param] = pos_values [j];
}
- //
// Adjust the size of the pos_values if it had params
- //
- if (group_in_params_array != Int32.MaxValue){
- int argc = group_in_params_array+1;
- object [] new_pos_values = new object [argc];
-
- for (int p = 0; p < argc; p++)
- new_pos_values [p] = pos_values [p];
+ if (last_real_param != pos_arg_count) {
+ object [] new_pos_values = new object [last_real_param + 1];
+ Array.Copy (pos_values, new_pos_values, last_real_param + 1);
pos_values = new_pos_values;
}
using System.Security;
using System.Security.Permissions;
using System.Text;
+
+#if BOOTSTRAP_WITH_OLDLIB
+using XmlElement = System.Object;
+#else
using System.Xml;
+#endif
using Mono.CompilerServices.SymbolWriter;
[Flags]
public enum Status : byte {
ASSIGNED = 1,
- USED = 2
+ USED = 2,
+ HAS_OFFSET = 4 // Used by FieldMember.
}
static string[] attribute_targets = new string [] { "field" };
public abstract class FieldMember: FieldBase
{
- bool has_field_offset = false;
+
protected FieldMember (TypeContainer parent, Expression type, int mod,
int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
{
if (a.Type == TypeManager.field_offset_attribute_type)
{
- has_field_offset = true;
+ status |= Status.HAS_OFFSET;
if (!Parent.HasExplicitLayout) {
Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
public override void Emit ()
{
- if (Parent.HasExplicitLayout && !has_field_offset && (ModFlags & Modifiers.STATIC) == 0) {
+ if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
}
static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
{
+ if (source.Name == target.Name){
+ Report.ExtraInformation (loc,
+ String.Format (
+ "The type {0} has two conflicting definitons, one comes from {0} and the other from {1}",
+ source.Assembly.FullName, target.Assembly.FullName));
+
+ }
Report.Error (29, loc, "Cannot convert implicitly from {0} to `{1}'",
source == TypeManager.anonymous_method_type ?
"anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
getChar ();
if (RootContext.Documentation != null && peekChar () == '/') {
getChar ();
- // Allow only ///ws.
// Don't allow ////.
- if ((d = peekChar ()) == ' ' || d == '\t') {
+ if ((d = peekChar ()) != '/') {
if (doc_state == XmlCommentState.Allowed)
handle_one_line_xml_comment ();
else if (doc_state == XmlCommentState.NotAllowed)
using System.Globalization;
using System.Reflection.Emit;
using System.Reflection;
+
+#if BOOTSTRAP_WITH_OLDLIB
+using XmlElement = System.Object;
+#else
using System.Xml;
+#endif
namespace Mono.CSharp {
for (int i = pd_count; i > 0; ) {
i--;
- if (invoke_pd.ParameterType (i) == pd.ParameterType (i) &&
- invoke_pd.ParameterModifier (i) == pd.ParameterModifier (i))
+ Type invoke_pd_type = invoke_pd.ParameterType (i);
+ Type pd_type = pd.ParameterType (i);
+ Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);
+ Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);
+
+ if (invoke_pd_type == pd_type &&
+ invoke_pd_type_mod == pd_type_mod)
continue;
- else {
- return null;
- }
+
+ if (invoke_pd_type.IsSubclassOf (pd_type) &&
+ invoke_pd_type_mod == pd_type_mod)
+ if (RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (loc, "contravariance");
+ return null;
+ } else
+ continue;
+
+ return null;
}
- if (((MethodInfo) invoke_mb).ReturnType == ((MethodInfo) mb).ReturnType)
+ Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;
+ Type mb_retval = ((MethodInfo) mb).ReturnType;
+ if (invoke_mb_retval == mb_retval)
return mb;
- else
- return null;
+
+ if (mb_retval.IsSubclassOf (invoke_mb_retval))
+ if (RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (loc, "covariance");
+ return null;
+ }
+ else
+ return mb;
+
+ return null;
}
// <summary>
Expression e = a.Expr;
+ if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
+ return ((AnonymousMethod) e).Compatible (ec, type, false);
+
MethodGroupExpr mg = e as MethodGroupExpr;
if (mg != null)
return ResolveMethodGroupExpr (ec, mg);
--- /dev/null
+//
+// doc-bootstrap.cs: Stub support for XML documentation.
+//
+// Author:
+// Raja R Harinath <rharinath@novell.com>
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2004 Novell, Inc.
+//
+//
+
+#if BOOTSTRAP_WITH_OLDLIB
+
+using XmlElement = System.Object;
+
+namespace Mono.CSharp {
+ public class DocUtil
+ {
+ internal static void GenerateTypeDocComment (TypeContainer t, DeclSpace ds)
+ {
+ }
+
+ internal static void GenerateDocComment (MemberCore mc, DeclSpace ds)
+ {
+ }
+
+ public static string GetMethodDocCommentName (MethodCore mc, DeclSpace ds)
+ {
+ return "";
+ }
+
+ internal static void OnMethodGenerateDocComment (MethodCore mc, DeclSpace ds, XmlElement el)
+ {
+ }
+
+ public static void GenerateEnumDocComment (Enum e, DeclSpace ds)
+ {
+ }
+ }
+
+ public class Documentation
+ {
+ public Documentation (string xml_output_filename)
+ {
+ }
+
+ public bool OutputDocComment (string asmfilename)
+ {
+ return true;
+ }
+
+ public void GenerateDocComment ()
+ {
+ }
+ }
+}
+
+#endif
// (C) 2004 Novell, Inc.
//
//
+
+#if ! BOOTSTRAP_WITH_OLDLIB
using System;
using System.Collections;
using System.Collections.Specialized;
}
}
}
+
+#endif
using System.IO;
using System.Text;
using System.Globalization;
- using System.Xml;
using System.Diagnostics;
public enum Target {
AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
}
+ public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
+ {
+ MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+ must_do_cs1540_check = false; // by default we do not check for this
+
+ //
+ // If only accessible to the current class or children
+ //
+ if (ma == MethodAttributes.Private) {
+ Type declaring_type = mi.DeclaringType;
+
+ if (invocation_type != declaring_type)
+ return TypeManager.IsSubclassOrNestedChildOf (invocation_type, declaring_type);
+
+ return true;
+ }
+ //
+ // FamAndAssem requires that we not only derivate, but we are on the
+ // same assembly.
+ //
+ if (ma == MethodAttributes.FamANDAssem){
+ return (mi.DeclaringType.Assembly != invocation_type.Assembly);
+ }
+
+ // Assembly and FamORAssem succeed if we're in the same assembly.
+ if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
+ if (mi.DeclaringType.Assembly == invocation_type.Assembly)
+ return true;
+ }
+
+ // We already know that we aren't in the same assembly.
+ if (ma == MethodAttributes.Assembly)
+ return false;
+
+ // Family and FamANDAssem require that we derive.
+ if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+ if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
+ return false;
+
+ if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
+ must_do_cs1540_check = true;
+
+ return true;
+ }
+
+ return true;
+ }
+
/// <summary>
/// Performs semantic analysis on the Expression
/// </summary>
public bool IsBase;
MethodInfo getter, setter;
bool is_static;
- bool must_do_cs1540_check;
Expression instance_expr;
LocalTemporary temp;
}
}
- bool IsAccessorAccessible (Type invocation_type, MethodInfo mi)
- {
- MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
-
- //
- // If only accessible to the current class or children
- //
- if (ma == MethodAttributes.Private) {
- Type declaring_type = mi.DeclaringType;
-
- if (invocation_type != declaring_type)
- return TypeManager.IsSubclassOrNestedChildOf (invocation_type, declaring_type);
-
- return true;
- }
- //
- // FamAndAssem requires that we not only derivate, but we are on the
- // same assembly.
- //
- if (ma == MethodAttributes.FamANDAssem){
- return (mi.DeclaringType.Assembly != invocation_type.Assembly);
- }
-
- // Assembly and FamORAssem succeed if we're in the same assembly.
- if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
- if (mi.DeclaringType.Assembly == invocation_type.Assembly)
- return true;
- }
-
- // We already know that we aren't in the same assembly.
- if (ma == MethodAttributes.Assembly)
- return false;
-
- // Family and FamANDAssem require that we derive.
- if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
- if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
- return false;
-
- if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
- must_do_cs1540_check = true;
-
- return true;
- }
-
- return true;
- }
-
//
// We also perform the permission checking here, as the PropertyInfo does not
// hold the information for the accessibility of its setter/getter
is_static = getter != null ? getter.IsStatic : setter.IsStatic;
}
- bool InstanceResolve (EmitContext ec)
+ bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
{
if ((instance_expr == null) && ec.IsStatic && !is_static) {
SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
return null;
}
- if (!IsAccessorAccessible (ec.ContainerType, getter)) {
+ bool must_do_cs1540_check;
+ if (!IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
Report.Error (122, loc, "'{0}.get' is inaccessible due to its protection level", PropertyInfo.Name);
return null;
}
- if (!InstanceResolve (ec))
+ if (!InstanceResolve (ec, must_do_cs1540_check))
return null;
//
return null;
}
- if (!IsAccessorAccessible (ec.ContainerType, setter)) {
+ bool must_do_cs1540_check;
+ if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
Report.Error (122, loc, "'{0}.set' is inaccessible due to its protection level", PropertyInfo.Name);
return null;
}
- if (!InstanceResolve (ec))
+ if (!InstanceResolve (ec, must_do_cs1540_check))
return null;
//
}
}
+ bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
+ {
+ if ((instance_expr == null) && ec.IsStatic && !is_static) {
+ SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
+ return false;
+ }
+
+ if (instance_expr != null) {
+ instance_expr = instance_expr.DoResolve (ec);
+ if (instance_expr == null)
+ return false;
+ }
+
+ //
+ // This is using the same mechanism as the CS1540 check in PropertyExpr.
+ // However, in the Event case, we reported a CS0122 instead.
+ //
+ if (must_do_cs1540_check && (instance_expr != null)) {
+ if ((instance_expr.Type != ec.ContainerType) &&
+ ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+ DeclaringType.Name + "." + EventInfo.Name);
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
if (instance_expr != null) {
return null;
}
+ bool must_do_cs1540_check;
+ if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check)
+ && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+ DeclaringType.Name + "." + EventInfo.Name);
+ return null;
+ }
+
+ if (!InstanceResolve (ec, must_do_cs1540_check))
+ return null;
return this;
- }
+ }
public override void Emit (EmitContext ec)
{
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;
-using System.Xml;
namespace Mono.CSharp {
if (IsDelegate){
RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
if (RequestedType != null)
- if (!(RequestedType is NewDelegate))
+ if (!(RequestedType is DelegateCreation))
throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
return RequestedType;
}
decl.cs
delegate.cs
doc.cs
+doc-bootstrap.cs
enum.cs
ecore.cs
expression.cs
if (resolved_ns != null)
return resolved_ns;
- Namespace curr_ns = NamespaceEntry.NS;
- while ((curr_ns != null) && (resolved_ns == null)) {
- resolved_ns = curr_ns.GetNamespace (Name, false);
-
- if (resolved_ns == null)
- curr_ns = curr_ns.Parent;
- }
-
+ object resolved = NamespaceEntry.LookupForUsing (Name, Location);
+ resolved_ns = resolved as Namespace;
return resolved_ns;
}
}
string alias = Alias.GetPartialName ();
- // According to section 16.3.1, the namespace-or-type-name is resolved
- // as if the immediately containing namespace body has no using-directives.
- resolved = NamespaceEntry.Lookup (null, alias, true, Location);
-
- NamespaceEntry curr_ns = NamespaceEntry.Parent;
-
- while ((curr_ns != null) && (resolved == null)) {
- resolved = curr_ns.Lookup (null, alias, false, Location);
-
- if (resolved == null)
- curr_ns = curr_ns.Parent;
- }
-
+ resolved = NamespaceEntry.LookupForUsing (alias, Location);
return resolved;
}
}
return ((Type) resolved).FullName;
}
- public object Lookup (DeclSpace ds, string name, bool ignore_using, Location loc)
+ //
+ // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ public object LookupForUsing (string dotted_name, Location loc)
+ {
+ int pos = dotted_name.IndexOf ('.');
+ string simple_name = dotted_name;
+ string rest = null;
+ if (pos >= 0) {
+ simple_name = dotted_name.Substring (0, pos);
+ rest = dotted_name.Substring (pos + 1);
+ }
+
+ object o = NS.Lookup (null, simple_name);
+ if (o == null && ImplicitParent != null)
+ o = ImplicitParent.LookupNamespaceOrType (null, simple_name, loc);
+
+ if (o == null || rest == null)
+ return o;
+
+ Namespace ns = o as Namespace;
+ if (ns != null)
+ return ns.Lookup (null, rest);
+
+ Type nested = TypeManager.LookupType ((((Type) o).Name + "." + rest));
+ return nested;
+ }
+
+ public object LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
+ {
+ object resolved = null;
+ for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
+ break;
+ }
+ return resolved;
+ }
+
+ private object Lookup (DeclSpace ds, string name, Location loc)
{
object o;
Namespace ns;
//
// If name is of the form `N.I', first lookup `N', then search a member `I' in it.
//
+ // FIXME: Remove this block. Only simple names should come here.
+ // The bug: The loop in LookupNamespaceOrType continues if
+ // the lookup for N succeeds but the nested lookup for I fails.
+ // This is one part of #52697.
+ //
int pos = name.IndexOf ('.');
if (pos >= 0) {
string first = name.Substring (0, pos);
string last = name.Substring (pos + 1);
- o = Lookup (ds, first, ignore_using, loc);
+ o = Lookup (ds, first, loc);
if (o == null)
return null;
}
//
- // Check whether it's a namespace.
+ // Check whether it's in the namespace.
//
o = NS.Lookup (ds, name);
if (o != null)
return o;
- if (ignore_using)
- return null;
-
//
// Check aliases.
//
protected void error246 (Location loc, string name)
{
- if (TypeManager.LookupType (name) != null)
- Report.Error (138, loc, "The using keyword only lets you specify a namespace, " +
- "`" + name + "' is a class not a namespace.");
- else {
- Report.Error (246, loc, "The namespace `" + name +
- "' can not be found (missing assembly reference?)");
-
- switch (name){
- case "Gtk": case "GtkSharp":
- MsgtryPkg ("gtk-sharp");
- break;
-
- case "Gdk": case "GdkSharp":
- MsgtryPkg ("gdk-sharp");
- break;
-
- case "Glade": case "GladeSharp":
- MsgtryPkg ("glade-sharp");
- break;
-
- case "System.Drawing":
- MsgtryRef ("System.Drawing");
- break;
-
- case "System.Web.Services":
- MsgtryRef ("System.Web.Services");
- break;
-
- case "System.Web":
- MsgtryRef ("System.Web");
- break;
-
- case "System.Data":
- MsgtryRef ("System.Data");
- break;
-
- case "System.Windows.Forms":
- MsgtryRef ("System.Windows.Forms");
- break;
- }
+ Report.Error (246, loc, "The namespace `" + name +
+ "' can not be found (missing assembly reference?)");
+
+ switch (name) {
+ case "Gtk": case "GtkSharp":
+ MsgtryPkg ("gtk-sharp");
+ break;
+
+ case "Gdk": case "GdkSharp":
+ MsgtryPkg ("gdk-sharp");
+ break;
+
+ case "Glade": case "GladeSharp":
+ MsgtryPkg ("glade-sharp");
+ break;
+
+ case "System.Drawing":
+ case "System.Web.Services":
+ case "System.Web":
+ case "System.Data":
+ case "System.Windows.Forms":
+ MsgtryRef (name);
+ break;
}
}
if (ue.Resolve () != null)
continue;
- error246 (ue.Location, ue.Name);
+ if (LookupForUsing (ue.Name, ue.Location) == null)
+ error246 (ue.Location, ue.Name);
+ else
+ Report.Error (138, ue.Location, "The using keyword only lets you specify a namespace, " +
+ "`" + ue.Name + "' is a class not a namespace.");
+
}
}
Console.Error.WriteLine (msg.ToString ());
foreach (string s in extra_information)
- Console.Error.WriteLine (s + MessageType + ")");
+ Console.Error.WriteLine (s + MessageType);
extra_information.Clear ();
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
-using System.Xml;
namespace Mono.CSharp {
static Type NamespaceLookup (DeclSpace ds, string name, Location loc)
{
- //
- // Try in the current namespace and all its implicit parents
- //
- for (NamespaceEntry ns = ds.NamespaceEntry; ns != null; ns = ns.ImplicitParent) {
- object result = ns.Lookup (ds, name, false, loc);
- if (result == null)
- continue;
-
- if (result is Type)
- return (Type) result;
-
+ object result = ds.NamespaceEntry.LookupNamespaceOrType (ds, name, loc);
+ if (result == null)
return null;
- }
+
+ if (result is Type)
+ return (Type) result;
return null;
}
public interface ParameterData {
Type ParameterType (int pos);
int Count { get; }
+ bool HasParams { get; }
string ParameterName (int pos);
string ParameterDesc (int pos);
Parameter.Modifier ParameterModifier (int pos);
return is_varargs ? pi.Length + 1 : pi.Length;
}
}
+
+ public bool HasParams {
+ get {
+ return this.last_arg_is_params;
+ }
+ }
}
}
}
+ public bool HasParams {
+ get {
+ return Parameters.ArrayParameter != null;
+ }
+ }
+
Parameter GetParameter (int pos)
{
Parameter [] fixed_pars = Parameters.FixedParameters;
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XmlResultVisitor.cs : ... was still broken.
+
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XmlResultVisitor.cs : Local fix - don't use WriteCData() which
+ cannot escape invalid characters. It broke VB unit test. See also:
+ http://sourceforge.net/tracker/?group_id=10749&atid=110749&func=detail&aid=1073539
+
2004-11-23 Raja R Harinath <rharinath@novell.com>
* Makefile (NO_INSTALL) [PROFILE=net_2_0]: Don't install dll.
xmlWriter.WriteStartElement("error");
xmlWriter.WriteStartElement("message");
- xmlWriter.WriteCData( EncodeCData( caseResult.Message ) );
+ xmlWriter.WriteString( caseResult.Message );
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("stack-trace");
if(caseResult.StackTrace != null)
- xmlWriter.WriteCData( EncodeCData( StackTraceFilter.Filter( caseResult.StackTrace ) ) );
+ xmlWriter.WriteString( StackTraceFilter.Filter( caseResult.StackTrace ) );
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * gen-116.cs: New test for #69781.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * gen-115.cs: New test for #58305.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (NEW_TEST_SOURCES_common): Add test-327 and test-328.
+
+ * test-326.cs (Main): Set return type to int, not void.
+
+2004-12-02 Marek Safar <marek.safar@seznam.cz>
+
+ * test-325.cs: New test for #70102.
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ * xml-025.inc : was missing.
+
+2004-12-02 Marek Safar <marek.safar@seznam.cz>
+
+ * test-324.cs: New test.
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Makefile : added lines for /doc test files.
+ * harness.nk : added xmldoc test lines.
+ * xmldocdiff.cs : small test tool for verifying /doc output.
+ * xml-001.cs, xml-001-ref.xml, xml-002.cs, xml-002-ref.xml,
+ xml-003.cs, xml-003-ref.xml, xml-004.cs, xml-004-ref.xml,
+ xml-005.cs, xml-005-ref.xml, xml-006.cs, xml-006-ref.xml,
+ xml-007.cs, xml-007-ref.xml, xml-008.cs, xml-008-ref.xml,
+ xml-009.cs, xml-009-ref.xml, xml-010.cs, xml-010-ref.xml,
+ xml-011.cs, xml-011-ref.xml, xml-012.cs, xml-012-ref.xml,
+ xml-013.cs, xml-013-ref.xml, xml-014.cs, xml-014-ref.xml,
+ xml-015.cs, xml-015-ref.xml, xml-016.cs, xml-016-ref.xml,
+ xml-017.cs, xml-017-ref.xml, xml-018.cs, xml-018-ref.xml,
+ xml-019.cs, xml-019-ref.xml, xml-020.cs, xml-020-ref.xml,
+ xml-021.cs, xml-021-ref.xml, xml-022.cs, xml-022-ref.xml,
+ xml-023.cs, xml-023-ref.xml, xml-024.cs, xml-024-ref.xml,
+ xml-025.cs, xml-025-ref.xml, xml-026.cs, xml-026-ref.xml,
+ xml-027.cs, xml-027-ref.xml, xml-028.cs, xml-028-ref.xml,
+ xml-029.cs, xml-029-ref.xml, xml-030.cs, xml-030-ref.xml,
+ xml-031.cs, xml-031-ref.xml, xml-032.cs, xml-032-ref.xml :
+ tests for /doc feature.
+
2004-11-30 Martin Baulig <martin@ximian.com>
* Makefile: Enable gen-110; it's about virtual generic methods and
# He may also move some to TEST_EXCLUDE_net_2_0 if some of the merges are inappropriate for GMCS.
#
NEW_TEST_SOURCES_common = test-294 test-304 test-305 test-306 test-307 test-318 mtest-5-dll mtest-5-exe \
- test-319-dll test-319-exe test-320 test-323 test-40
+ test-319-dll test-319-exe test-320 test-323 test-324 test-325 test-326 \
+ test-327 test-328 test-40 \
+ covariance-1 covariance-2 covariance-3 \
+ $(TEST_SOURCES_XML)
#
# Please do _not_ add any tests here - all new tests should go into NEW_TEST_SOURCES_common
gen-81 gen-82 gen-83 gen-84 gen-85 gen-86 gen-87 gen-88 gen-89 gen-90 \
gen-91 gen-92 gen-93 gen-94 gen-95 gen-96 gen-97 gen-100 \
gen-101 gen-102 gen-103 gen-104 gen-105 gen-106 gen-107 gen-108 gen-109 gen-110 \
- gen-111 gen-112
+ gen-111 gen-112 gen-113 gen-114 gen-115 gen-116
TEST_EXCLUDES_net_2_0 = $(NEW_TEST_SOURCES_common)
endif
.PHONY: test-harness test-harness-run
-test-harness:
+test-harness: xmldocdiff.exe
@$(MAKE) -s test-harness-run
exe_tests := $(filter %-exe, $(TEST_SOURCES))
$(INTERNAL_ILASM) /dll property-il.il
$(CSCOMPILE) /r:property-il.dll property-main.cs /out:property-main.exe
$(TEST_RUNTIME) property-main.exe
+
+
+#
+# Test for /doc option; need to compare result documentation files.
+#
+
+TEST_SOURCES_XML = \
+ xml-001 xml-002 xml-003 xml-004 xml-005 xml-006 xml-007 xml-008 xml-009 xml-010 \
+ xml-011 xml-012 xml-013 xml-014 xml-015 xml-016 xml-017 xml-018 xml-019 xml-020 \
+ xml-021 xml-022 xml-023 xml-024 xml-025 xml-026 xml-028 xml-029 xml-030
+
+# currently no formalization on 'cref' attribute was found, so there are some
+# differences between MS.NET and mono.
+TEST_SOURCES_XML_PENDING = xml-027
+
+xml-doc-tests := $(filter xml-%, $(TEST_SOURCES))
+
+xmldocdiff.exe:
+ $(CSCOMPILE) xmldocdiff.cs
--- /dev/null
+// Compiler options: -langversion:default
+// Test for covariance support in delegates
+//
+
+using System;
+
+ public class A {
+ protected string name;
+
+ public A (string name)
+ {
+ this.name = "A::" + name;
+ }
+
+ public A ()
+ {
+ }
+
+ public string Name {
+ get {
+ return name;
+ }
+ }
+ }
+
+ public class B : A {
+ public B (string name)
+ {
+ this.name = "B::" + name;
+ }
+
+ public B ()
+ {
+ }
+ }
+
+ public class C : B {
+ public C (string name)
+ {
+ this.name = "C::" + name;
+ }
+ }
+
+ public class Tester {
+
+ delegate A MethodHandler (string name);
+
+ static A MethodSampleA (string name)
+ {
+ return new A (name);
+ }
+
+ static B MethodSampleB (string name)
+ {
+ return new B (name);
+ }
+
+ static C MethodSampleC (string name)
+ {
+ return new C (name);
+ }
+
+ static void Main ()
+ {
+ MethodHandler a = MethodSampleA;
+ MethodHandler b = MethodSampleB;
+ MethodHandler c = MethodSampleC;
+
+ A instance1 = a ("Hello");
+ A instance2 = b ("World");
+ A instance3 = c ("!");
+
+ Console.WriteLine (instance1.Name);
+ Console.WriteLine (instance2.Name);
+ Console.WriteLine (instance3.Name);
+ }
+
+ }
+
--- /dev/null
+// Compiler options: -langversion:default
+//
+// Test for contravariance support in delegates
+//
+
+using System;
+
+ public class A {
+ protected string name;
+
+ public A (string name)
+ {
+ this.name = "A::" + name;
+ }
+
+ public A ()
+ {
+ }
+
+ public string Name {
+ get {
+ return name;
+ }
+ }
+ }
+
+ public class B : A {
+ public B (string name)
+ {
+ this.name = "B::" + name;
+ }
+
+ public B ()
+ {
+ }
+ }
+
+ public class C : B {
+ string value;
+
+ public C (string name, string value)
+ {
+ this.name = "C::" + name;
+ this.value = value;
+ }
+
+ public string Value {
+ get {
+ return value;
+ }
+ }
+ }
+
+ public class Tester {
+
+ delegate string MethodHandler (C c);
+
+ static string MethodSampleA (A value)
+ {
+ return value.Name;
+ }
+
+ static string MethodSampleB (B value)
+ {
+ return value.Name;
+ }
+
+ static string MethodSampleC (C value)
+ {
+ return value.Name + " " + value.Value;
+ }
+
+ static void Main ()
+ {
+ MethodHandler da = MethodSampleA;
+ MethodHandler db = MethodSampleB;
+ MethodHandler dc = MethodSampleC;
+
+ C a = new C ("Hello", "hello");
+ C b = new C ("World", "world");
+ C c = new C ("!", "!!!");
+
+ Console.WriteLine (da (a));
+ Console.WriteLine (db (b));
+ Console.WriteLine (dc (c));
+ }
+
+ }
+
--- /dev/null
+// Compiler options: -langversion:default
+//
+// Test for contravariance support in delegates
+//
+
+using System;
+
+ public class A {
+ protected string name;
+
+ public A (string name)
+ {
+ this.name = "A::" + name;
+ }
+
+ public A ()
+ {
+ }
+
+ public string Name {
+ get {
+ return name;
+ }
+ }
+ }
+
+ public class B : A {
+ public B (string name)
+ {
+ this.name = "B::" + name;
+ }
+
+ public B ()
+ {
+ }
+ }
+
+ public class C : B {
+ string value;
+
+ public C (string name, string value)
+ {
+ this.name = "C::" + name;
+ this.value = value;
+ }
+
+ public string Value {
+ get {
+ return value;
+ }
+ }
+ }
+
+ public class Tester {
+
+ delegate void MethodHandler (C c1, C c2, C c3);
+
+ static void MethodSample (B b, A a, C c)
+ {
+ Console.WriteLine ("b = {0}", b.Name);
+ Console.WriteLine ("a = {0}", a.Name);
+ Console.WriteLine ("c = {0}, {1}", c.Name, c.Value);
+ }
+
+ static void Main ()
+ {
+ MethodHandler mh = MethodSample;
+
+ C a = new C ("Hello", "hello");
+ C b = new C ("World", "world");
+ C c = new C ("!", "!!!");
+
+ mh (b, a, c);
+ }
+
+ }
+
--- /dev/null
+using System;
+
+public delegate V Mapper<T,V> (T item);
+
+public class List<T>
+{
+ public void Map<V> (Mapper<T,V> mapper)
+ { }
+}
+
+class X
+{
+ static void Main ()
+ {
+ List<int> list = new List<int> ();
+ list.Map (new Mapper<int,double> (delegate (int i) { return i/10.0; }));
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+public class NaturalComparer<T> : IComparer<T>
+ where T: IComparable<T>
+{
+ public int Compare (T a, T b)
+ {
+ return a.CompareTo (b);
+ }
+}
+
+public class X
+{
+ class Test : IComparable<Test>
+ {
+ public int CompareTo (Test that)
+ {
+ return 0;
+ }
+
+ public bool Equals (Test that)
+ {
+ return false;
+ }
+ }
+
+ static void Main ()
+ {
+ IComparer<Test> cmp = new NaturalComparer<Test> ();
+ Test a = new Test ();
+ Test b = new Test ();
+ cmp.Compare (a, b);
+ }
+}
--- /dev/null
+//-- ex-gen-class-linkedlist
+//-- ex-anonymous-method-linkedlist
+//-- ex-gen-printable
+//-- ex-gen-interface-ilist
+//-- ex-gen-linkedlist-map
+//-- ex-gen-linkedlistenumerator
+//-- ex-gen-delegate-fun
+
+// A generic LinkedList class
+
+using System;
+using System.IO; // TextWriter
+using System.Collections.Generic; // IEnumerable<T>, IEnumerator<T>
+
+public delegate R Mapper<A,R>(A x);
+
+public interface IMyList<T> : IEnumerable<T> {
+ int Count { get; } // Number of elements
+ T this[int i] { get; set; } // Get or set element at index i
+ void Add(T item); // Add element at end
+ void Insert(int i, T item); // Insert element at index i
+ void RemoveAt(int i); // Remove element at index i
+ IMyList<U> Map<U>(Mapper<T,U> f); // Map f over all elements
+}
+
+public class LinkedList<T> : IMyList<T> {
+ protected int size; // Number of elements in the list
+ protected Node first, last; // Invariant: first==null iff last==null
+
+ protected class Node {
+ public Node prev, next;
+ public T item;
+
+ public Node(T item) {
+ this.item = item;
+ }
+
+ public Node(T item, Node prev, Node next) {
+ this.item = item; this.prev = prev; this.next = next;
+ }
+ }
+
+ public LinkedList() {
+ first = last = null;
+ size = 0;
+ }
+
+ public LinkedList(params T[] arr) : this() {
+ foreach (T x in arr)
+ Add(x);
+ }
+
+ public int Count {
+ get { return size; }
+ }
+
+ public T this[int i] {
+ get { return get(i).item; }
+ set { get(i).item = value; }
+ }
+
+ private Node get(int n) {
+ if (n < 0 || n >= size)
+ throw new IndexOutOfRangeException();
+ else if (n < size/2) { // Closer to front
+ Node node = first;
+ for (int i=0; i<n; i++)
+ node = node.next;
+ return node;
+ } else { // Closer to end
+ Node node = last;
+ for (int i=size-1; i>n; i--)
+ node = node.prev;
+ return node;
+ }
+ }
+
+ public void Add(T item) {
+ Insert(size, item);
+ }
+
+ public void Insert(int i, T item) {
+ if (i == 0) {
+ if (first == null) // and thus last == null
+ first = last = new Node(item);
+ else {
+ Node tmp = new Node(item, null, first);
+ first.prev = tmp;
+ first = tmp;
+ }
+ size++;
+ } else if (i == size) {
+ if (last == null) // and thus first = null
+ first = last = new Node(item);
+ else {
+ Node tmp = new Node(item, last, null);
+ last.next = tmp;
+ last = tmp;
+ }
+ size++;
+ } else {
+ Node node = get(i);
+ // assert node.prev != null;
+ Node newnode = new Node(item, node.prev, node);
+ node.prev.next = newnode;
+ node.prev = newnode;
+ size++;
+ }
+ }
+
+ public void RemoveAt(int i) {
+ Node node = get(i);
+ if (node.prev == null)
+ first = node.next;
+ else
+ node.prev.next = node.next;
+ if (node.next == null)
+ last = node.prev;
+ else
+ node.next.prev = node.prev;
+ size--;
+ }
+
+ public override bool Equals(Object that) {
+ if (that != null && GetType() == that.GetType()
+ && this.size == ((IMyList<T>)that).Count) {
+ Node thisnode = this.first;
+ IEnumerator<T> thatenm = ((IMyList<T>)that).GetEnumerator();
+ while (thisnode != null) {
+ if (!thatenm.MoveNext())
+ throw new ApplicationException("Impossible: LinkedList<T>.Equals");
+ // assert MoveNext() was true (because of the above size test)
+ if (!thisnode.item.Equals(thatenm.Current))
+ return false;
+ thisnode = thisnode.next;
+ }
+ // assert !MoveNext(); // because of the size test
+ return true;
+ } else
+ return false;
+ }
+
+ public override int GetHashCode() {
+ int hash = 0;
+ foreach (T x in this)
+ hash ^= x.GetHashCode();
+ return hash;
+ }
+
+ public static explicit operator LinkedList<T>(T[] arr) {
+ return new LinkedList<T>(arr);
+ }
+
+ public static LinkedList<T> operator +(LinkedList<T> xs1, LinkedList<T> xs2) {
+ LinkedList<T> res = new LinkedList<T>();
+ foreach (T x in xs1)
+ res.Add(x);
+ foreach (T x in xs2)
+ res.Add(x);
+ return res;
+ }
+
+ public IMyList<U> Map<U>(Mapper<T,U> f) {
+ LinkedList<U> res = new LinkedList<U>();
+ foreach (T x in this)
+ res.Add(f(x));
+ return res;
+ }
+
+ public IEnumerator<T> GetEnumerator() {
+ return new LinkedListEnumerator(this);
+ }
+
+ private class LinkedListEnumerator : IEnumerator<T> {
+ T curr; // The enumerator's current element
+ bool valid; // Is the current element valid?
+ Node next; // Node holding the next element, or null
+
+ public LinkedListEnumerator(LinkedList<T> lst) {
+ next = lst.first; valid = false;
+ }
+
+ public T Current {
+ get {
+ if (valid)
+ return curr;
+ else
+ throw new InvalidOperationException();
+ }
+ }
+
+ public bool MoveNext() {
+ if (next != null) {
+ curr = next.item; next = next.next; valid = true;
+ } else
+ valid = false;
+ return valid;
+ }
+
+ public void Dispose() {
+ curr = default(T); next = null; valid = false;
+ }
+ }
+}
+
+class SortedList<T> : LinkedList<T> where T : IComparable<T> {
+ // Sorted insertion
+ public void Insert(T x) {
+ Node node = first;
+ while (node != null && x.CompareTo(node.item) > 0)
+ node = node.next;
+ if (node == null) // x > all elements; insert at end
+ Add(x);
+ else { // x <= node.item; insert before node
+ Node newnode = new Node(x);
+ if (node.prev == null) // insert as first element
+ first = newnode;
+ else
+ node.prev.next = newnode;
+ newnode.next = node;
+ newnode.prev = node.prev;
+ node.prev = newnode;
+ }
+ }
+}
+
+interface IPrintable {
+ void Print(TextWriter fs);
+}
+class PrintableLinkedList<T> : LinkedList<T>, IPrintable where T : IPrintable {
+ public void Print(TextWriter fs) {
+ bool firstElement = true;
+ foreach (T x in this) {
+ x.Print(fs);
+ if (firstElement)
+ firstElement = false;
+ else
+ fs.Write(", ");
+ }
+ }
+}
+
+class MyString : IComparable<MyString> {
+ private readonly String s;
+ public MyString(String s) {
+ this.s = s;
+ }
+ public int CompareTo(MyString that) {
+ return String.Compare(that.Value, s); // Reverse ordering
+ }
+ public bool Equals(MyString that) {
+ return that.Value == s;
+ }
+ public String Value {
+ get { return s; }
+ }
+}
+
+class MyTest {
+ public static void Main(String[] args) {
+ LinkedList<double> dLst = new LinkedList<double>(7.0, 9.0, 13.0, 0.0);
+ foreach (double d in dLst)
+ Console.Write("{0} ", d);
+ Console.WriteLine();
+ IMyList<int> iLst =
+ dLst.Map<int>(new Mapper<double, int>(Math.Sign));
+ foreach (int i in iLst)
+ Console.Write("{0} ", i);
+ Console.WriteLine();
+ IMyList<String> sLst =
+ dLst.Map<String>(delegate(double d) { return "s" + d; });
+ foreach (String s in sLst)
+ Console.Write("{0} ", s);
+ Console.WriteLine();
+ // Testing SortedList<MyString>
+ SortedList<MyString> sortedLst = new SortedList<MyString>();
+ sortedLst.Insert(new MyString("New York"));
+ sortedLst.Insert(new MyString("Rome"));
+ sortedLst.Insert(new MyString("Dublin"));
+ sortedLst.Insert(new MyString("Riyadh"));
+ sortedLst.Insert(new MyString("Tokyo"));
+ foreach (MyString s in sortedLst)
+ Console.Write("{0} ", s.Value);
+ Console.WriteLine();
+ }
+}
--- /dev/null
+using System;
+
+namespace Slow
+{
+ public interface ITest
+ {
+ void DoNothing<T>()
+ where T : class;
+ }
+
+ public class Test : ITest
+ {
+ public void DoNothing<T>()
+ where T : class
+ {
+ T x = null;
+ }
+ }
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ const int iterations = 10000;
+
+ Test test = new Test ();
+
+ DateTime start = DateTime.Now;
+ Console.Write ("Calling Test.DoNothing<Program>() on an object reference... ");
+ for (int i = 0; i < iterations; ++i)
+ {
+ test.DoNothing<Program> ();
+ }
+ DateTime end = DateTime.Now;
+ TimeSpan duration = end - start;
+ Console.WriteLine ("Took " + duration.TotalMilliseconds + " ms.");
+
+ ITest testInterface = test;
+
+ start = DateTime.Now;
+ Console.Write ("Calling Test.DoNothing<Program>() on an interface reference... ");
+ for (int i = 0; i < iterations; ++i)
+ {
+ testInterface.DoNothing<Program> ();
+ }
+ end = DateTime.Now;
+ duration = end - start;
+ Console.WriteLine ("Took " + duration.TotalMilliseconds + " ms.");
+ }
+ }
+}
MCS = MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_MCS)
endif
+XMLDOCDIFF = $(TEST_RUNTIME) ../xmldocdiff.exe
+
all-local $(STD_TARGETS:=-local):
%.res:
if test -f $*.exe; then \
echo '*** $(TEST_RUNTIME) -O=-all ./$*.exe' >> $$testlogfile ; \
if $(TEST_RUNTIME) -O=-all ./$*.exe >> $$testlogfile 2>&1 ; then \
- echo "PASS: $*" > $@ ; \
- rm -f $$testlogfile ; \
+ if test -f $*.xml; then \
+ if $(XMLDOCDIFF) ../$*-ref.xml $*.xml >> $$testlogfile ; then \
+ echo "PASS: $*: xml comparison" > $@ ; \
+ rm -f $$testlogfile ; \
+ else \
+ echo "FAIL: $*: xml comparison" > $@ ; \
+ fi \
+ else \
+ echo "PASS: $*" > $@ ; \
+ rm -f $$testlogfile ; \
+ fi \
else \
echo "Exit code: $$?" >> $$testlogfile ; \
echo "FAIL: $*" > $@ ; \
--- /dev/null
+using System;
+
+public class A {
+ public void DoStuff ()
+ {
+ Console.WriteLine ("stuff");
+ }
+}
+
+public struct B {
+ public bool Val {
+ get {
+ return false;
+ }
+ }
+}
+
+public class T : MarshalByRefObject {
+ internal static A a = new A ();
+ public static B b;
+}
+
+public class Driver {
+
+ public static void Main ()
+ {
+ T.a.DoStuff ();
+ bool b = T.b.Val;
+ }
+}
--- /dev/null
+using System;
+
+public class RequestAttribute: Attribute {
+ public RequestAttribute(string a, string b, params string[] c)
+ {
+
+ }
+}
+
+public class MyClass {
+ [Request("somereq", "result")]
+ public static int SomeRequest()
+ {
+ return 0;
+ }
+
+ public static void Main()
+ {
+ SomeRequest();
+ }
+}
--- /dev/null
+// Compiler options: -langversion:default
+// Anonymous method fix, implicit conversion inside an old-style constructor
+// Bug 70150
+using System;
+public delegate double Mapper (int item);
+
+class X
+{
+ static int Main ()
+ {
+ Mapper mapper = new Mapper (delegate (int i){
+ return i * 12; });
+
+ if (mapper (3) == 36)
+ return 0;
+
+ // Failure
+ return 1;
+ }
+}
--- /dev/null
+class X2 {}
+namespace A {
+ enum X1 { x1 };
+ enum X2 { x2 };
+}
+namespace A.B {
+ using Y1 = X1;
+ using Y2 = X2;
+ class Tester {
+ internal static Y1 y1 = Y1.x1;
+ internal static Y2 y2 = Y2.x2;
+ static void Main() { }
+ }
+}
--- /dev/null
+namespace X {
+ enum Z { x };
+}
+namespace A {
+ using Y = X;
+ namespace B {
+ using Y;
+ class Tester {
+ internal static Z z = Z.x;
+ static void Main() { }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-001</name>\r
+ </assembly>\r
+ <members>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-001.xml
+using System;
+
+/// <summary>
+/// xml comment on namespace ... is not allowed.
+/// </summary>
+namespace Testing
+{
+ public class A
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-002</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ <summary>
+ comment on class
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.Test2" -->\r
+ <member name="T:Testing.Test3">\r
+ <summary>
+ another Java-style documentation style
+ </summary>
+ </member>\r
+ <member name="T:Testing.Test4">\r
+ indentation level test <seealso
+ cref="T:Testing.Test" />.
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-002.xml
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment on class
+ /// </summary>
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+
+ /// <summary>
+ /// Incorrect comment markup. See <see cref="T:Testing.Test" /> too.
+ /// </incorrect>
+ public class Test2
+ {
+ }
+
+ /**
+ <summary>
+ another Java-style documentation style
+ </summary>
+ */
+ public class Test3
+ {
+ }
+
+ /// indentation level test <seealso
+ /// cref="T:Testing.Test" />.
+public class Test4
+{
+}
+
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-003</name>\r
+ </assembly>\r
+ <members>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-003.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ /// here is an extraneous comment
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-004</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.StructTest">\r
+ <summary>
+ comment for struct
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.StructTest2" -->\r
+ <member name="T:Testing.StructTest3">\r
+ <summary>
+ Java style commet
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-004.xml
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for struct
+ /// </summary>
+ public struct StructTest
+ {
+ }
+
+ /// <summary>
+ /// incorrect markup comment for struct
+ /// </incorrect>
+ public struct StructTest2
+ {
+ }
+
+ /**
+ <summary>
+ Java style commet
+ </summary>
+ */
+ public struct StructTest3
+ {
+ }
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-005</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.InterfaceTest">\r
+ <summary>
+ comment for interface
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.InterfaceTest2" -->\r
+ <member name="T:Testing.InterfaceTest3">\r
+ <summary>
+ Java style comment for interface
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-005.xml
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for interface
+ /// </summary>
+ public interface InterfaceTest
+ {
+ }
+
+ /// <summary>
+ /// incorrect markup comment for interface
+ /// </incorrect>
+ public interface InterfaceTest2
+ {
+ }
+
+ /**
+ <summary>
+ Java style comment for interface
+ </summary>
+ */
+ public interface InterfaceTest3
+ {
+ }
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-006</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.EnumTest">\r
+ <summary>
+ comment for enum type
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.EnumTest2" -->\r
+ <member name="T:Testing.EnumTest3">\r
+ <summary>
+ Java style comment for enum type
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-006.xml
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for enum type
+ /// </summary>
+ public enum EnumTest
+ {
+ Foo,
+ Bar,
+ }
+
+ /// <summary>
+ /// comment for enum type
+ /// </incorrect>
+ public enum EnumTest2
+ {
+ Foo,
+ Bar,
+ }
+
+ /**
+ <summary>
+ Java style comment for enum type
+ </summary>
+ */
+ public enum EnumTest3
+ {
+ Foo,
+ Bar,
+ }
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-007</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.MyDelegate">\r
+ <summary>
+ comment for delegate type
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.MyDelegate2" -->\r
+ <member name="T:Testing.MyDelegate3">\r
+ <summary>
+ Javadoc comment for delegate type
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-007.xml
+using System;
+
+namespace Testing
+{
+ /// <summary>
+ /// comment for delegate type
+ /// </summary>
+ public delegate void MyDelegate (object o, EventArgs e);
+
+ /// <summary>
+ /// comment for delegate type
+ /// </incorrect>
+ public delegate void MyDelegate2 (object o, EventArgs e);
+
+ /**
+ <summary>
+ Javadoc comment for delegate type
+ </summary>
+ */
+ public delegate void MyDelegate3 (object o, EventArgs e);
+
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-008</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ comment without markup on class - it is allowed
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.Test2" -->\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.Test3" -->\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-008.xml
+using System;
+
+namespace Testing
+{
+ /// comment without markup on class - it is allowed
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+
+ /// <6roken> broken markup
+ public class Test2
+ {
+ }
+
+ /// <dont-forget-close-tag>
+ public class Test3
+ {
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-009</name>\r
+ </assembly>\r
+ <members>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-009.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ /// inside method - not allowed.
+ }
+ }
+
+ public class Test2
+ {
+ /// no target
+ }
+
+ public class Test3
+ {
+ }
+ /// no target case 2.
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-010</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="F:Testing.Test.Constant">\r
+ <summary>
+ comment for const declaration
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "F:Testing.Test.Constant2" -->\r
+ <member name="F:Testing.Test.Constant3">\r
+ <summary>
+ Javaism comment for const declaration
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-010.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ /// <summary>
+ /// comment for const declaration
+ /// </summary>
+ const string Constant = "CONSTANT STRING";
+
+ /// <summary>
+ /// invalid comment for const declaration
+ /// </invalid>
+ const string Constant2 = "CONSTANT STRING";
+
+ /**
+ <summary>
+ Javaism comment for const declaration
+ </summary>
+ */
+ const string Constant3 = "CONSTANT STRING";
+
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-011</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="F:Testing.Test.PublicField">\r
+ <summary>
+ comment for public field
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "F:Testing.Test.PublicField2" -->\r
+ <member name="F:Testing.Test.PublicField3">\r
+ <summary>
+ Javadoc comment for public field
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-011.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ /// <summary>
+ /// comment for public field
+ /// </summary>
+ public string PublicField;
+
+ /// <summary>
+ /// comment for public field
+ /// </invalid>
+ public string PublicField2;
+
+ /**
+ <summary>
+ Javadoc comment for public field
+ </summary>
+ */
+ public string PublicField3;
+
+ public static void Main ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-012</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="F:Testing.Test.PrivateField">\r
+ <summary>
+ comment for private field
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "F:Testing.Test.PrivateField2" -->\r
+ <member name="F:Testing.Test.PrivateField3">\r
+ <summary>
+ Javadoc comment for private field
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-012.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for private field
+ /// </summary>
+ private string PrivateField;
+
+ /// <summary>
+ /// incorrect markup comment for private field
+ /// </incorrect>
+ private string PrivateField2;
+
+ /**
+ <summary>
+ Javadoc comment for private field
+ </summary>
+ */
+ private string PrivateField3;
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-013</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="P:Testing.Test.PublicProperty">\r
+ <summary>
+ comment for public property
+ </summary>
+ </member>\r
+ <!-- Badly formed XML comment ignored for member "P:Testing.Test.PublicProperty2" -->\r
+ <member name="P:Testing.Test.PublicProperty3">\r
+ <summary>
+ Javadoc comment for public property
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-013.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for public property
+ /// </summary>
+ public string PublicProperty {
+ /// <summary>
+ /// On public getter - no effect
+ /// </summary>
+ get { return null; }
+ /// <summary>
+ /// On public setter - no effect
+ /// </summary>
+ set { }
+ }
+
+ /// <summary>
+ /// incorrect comment for public property
+ /// </incorrect>
+ public string PublicProperty2 {
+ get { return null; }
+ }
+
+ /**
+ <summary>
+ Javadoc comment for public property
+ </summary>
+ */
+ public string PublicProperty3 {
+ /**
+ <summary>
+ On public getter - no effect
+ </summary>
+ */
+ get { return null; }
+ /**
+ <summary>
+ On public setter - no effect
+ </summary>
+ */
+ set { }
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-014</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="P:Testing.Test.PrivateProperty">\r
+ <summary>
+ comment for private property
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-014.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for private property
+ /// </summary>
+ private string PrivateProperty {
+ get { return null; }
+ set { }
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-015</name>\r
+ </assembly>\r
+ <members>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-015.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ private string PrivateProperty {
+ get { return null; }
+ /// <summary>
+ /// comment for private property setter - no effect
+ /// </summary>
+ set { }
+ }
+
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-016</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="E:Testing.Test.MyEvent">\r
+ <summary>
+ public event EventHandler MyEvent
+ </summary>
+ </member>\r
+ <member name="E:Testing.Test.MyEvent2">\r
+ private event EventHandler MyEvent; without markup - it is OK.
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-016.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// public event EventHandler MyEvent
+ /// </summary>
+ public event EventHandler MyEvent;
+
+ /// private event EventHandler MyEvent; without markup - it is OK.
+ private event EventHandler MyEvent2;
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-017</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Testing.Test.Foo">\r
+ comment on method without parameter
+ </member>\r
+ <member name="M:Testing.Test.Foo(System.Int64,Testing.Test,System.Collections.ArrayList)">\r
+ here is a documentation with parameters (and has same name)
+ </member>\r
+ <member name="M:Testing.Test.Foo(System.String[])">\r
+ here is a documentation with parameters (and has same name)
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-017.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// comment on method without parameter
+ public static void Foo ()
+ {
+ }
+
+ /// here is a documentation with parameters (and has same name)
+ public static void Foo (long l, Test t, System.Collections.ArrayList al)
+ {
+ }
+
+ /// here is a documentation with parameters (and has same name)
+ public static void Foo (params string [] param)
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-018</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="P:Testing.Test.Item(System.Int32)">\r
+ <summary>
+ comment for indexer
+ </summary>
+ </member>\r
+ <member name="P:Testing.Test.Item(System.String)">\r
+ <summary>
+ comment for indexer
+ </summary>
+ </member>\r
+ <member name="P:Testing.Test.Item(System.Int32,Testing.Test)">\r
+ <summary>
+ comment for indexer wit multiple parameters
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-018.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for indexer
+ /// </summary>
+ public string this [int i] {
+ get { return null; }
+ }
+
+ /// <summary>
+ /// comment for indexer
+ /// </summary>
+ public string this [string s] {
+ get { return null; }
+ }
+
+ /// <summary>
+ /// comment for indexer wit multiple parameters
+ /// </summary>
+ public string this [int i, Test t] {
+ get { return null; }
+ }
+
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-019</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Testing.Test.op_LogicalNot(Testing.Test)">\r
+ <summary>
+ comment for unary operator
+ </summary>
+ </member>\r
+ <member name="M:Testing.Test.op_Addition(Testing.Test,System.Int32)">\r
+ <summary>
+ comment for binary operator
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-019.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// comment for unary operator
+ /// </summary>
+ public static bool operator ! (Test t)
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// comment for binary operator
+ /// </summary>
+ public static int operator + (Test t, int b)
+ {
+ return b;
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-020</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Testing.Test.#ctor">\r
+ comment for constructor
+ </member>\r
+ <member name="M:Testing.Test.Finalize">\r
+ comment for destructor
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-020.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// comment for constructor
+ public Test ()
+ {
+ }
+
+ /// comment for destructor
+ ~Test ()
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-021</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test.InternalClass">\r
+ comment for internal class
+ </member>\r
+ <member name="T:Testing.Test.InternalStruct">\r
+ comment for internal struct
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-021.xml
+using System;
+
+namespace Testing
+{
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// comment for internal class
+ public class InternalClass
+ {
+ }
+
+ /// comment for internal struct
+ public struct InternalStruct
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-022</name>\r
+ </assembly>\r
+ <members>\r
+ <!-- Badly formed XML comment ignored for member "T:Testing.Test2" -->\r
+ <member name="M:Testing.Test2.Foo">\r
+ another documentation style (Java-mimic)
+ </member>\r
+ <member name="T:Testing.StructTest">\r
+ testing indentation <summary> test test ;-)
+ comment for struct
+ </summary>
+ </member>\r
+ <member name="T:Testing.InterfaceTest">\r
+ <summary>
+ comment for interface
+ </summary>
+ </member>\r
+ <member name="T:Testing.EnumTest">\r
+ <summary>
+ comment for enum type
+ </summary>
+ </member>\r
+ <member name="F:Testing.EnumTest.Foo">\r
+ <summary>
+ comment for enum field
+ </summary>
+ </member>\r
+ <member name="T:Testing.Dummy">\r
+ <summary>
+ comment for dummy type
+ </summary>
+ </member>\r
+ <member name="T:Testing.MyDelegate">\r
+ <summary>
+ comment for delegate type
+ </summary>
+ </member>\r
+ <member name="T:Testing.Test">\r
+ <summary>
+ description for class Test
+ </summary>
+ </member>\r
+ <member name="F:Testing.Test.Constant">\r
+ comment for const declaration
+ </member>\r
+ <member name="F:Testing.Test.BadPublicField">\r
+ comment for public field
+ </member>\r
+ <member name="F:Testing.Test.PrivateField">\r
+ comment for private field
+ </member>\r
+ <member name="M:Testing.Test.Foo">\r
+ here is a documentation!!!
+ </member>\r
+ <member name="M:Testing.Test.Foo(System.Int64,Testing.Test,System.Collections.ArrayList)">\r
+ here is a documentation with parameters
+ </member>\r
+ <member name="M:Testing.Test.op_LogicalNot(Testing.Test)">\r
+ <summary>
+ comment for unary operator
+ </summary>
+ </member>\r
+ <member name="M:Testing.Test.op_Addition(Testing.Test,System.Int32)">\r
+ <summary>
+ comment for binary operator
+ </summary>
+ </member>\r
+ <member name="M:Testing.Test.Finalize">\r
+ comment for destructor
+ </member>\r
+ <member name="M:Testing.Test.#ctor">\r
+ comment for .ctor()
+ </member>\r
+ <member name="M:Testing.Test.#ctor(System.String,System.String[])">\r
+ comment for .ctor(string arg, string [] args)
+ </member>\r
+ <member name="P:Testing.Test.PublicProperty">\r
+ comment for public property
+ </member>\r
+ <member name="P:Testing.Test.PrivateProperty">\r
+ comment for private property
+ </member>\r
+ <member name="E:Testing.Test.MyEvent">\r
+ public event EventHandler MyEvent ;-)
+ </member>\r
+ <member name="P:Testing.Test.Item(System.Int32)">\r
+ comment for indexer
+ </member>\r
+ <member name="P:Testing.Test.Item(System.Int32,Testing.Test)">\r
+ comment for indexer wit multiple parameters
+ </member>\r
+ <member name="T:Testing.Test.InternalClass">\r
+ comment for internal class
+ </member>\r
+ <member name="T:Testing.Test.InternalStruct">\r
+ comment for internal struct
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-022.xml
+//
+// Combined tests (for detecting incorrect markup targeting).
+//
+using System;
+
+/// <summary>
+/// xml comment is not allowed here.
+/// </summary>
+namespace Testing
+{
+ /// <summary>
+ /// </incorrect>
+ public class Test2
+ {
+ /**
+ another documentation style (Java-mimic)
+ */
+ public static void Foo ()
+ {
+ /// here is an extraneous comment
+ }
+
+ public static void Main ()
+ {
+ }
+ }
+
+ /// testing indentation <summary> test test ;-)
+ /// comment for struct
+ /// </summary>
+ public struct StructTest
+ {
+ }
+
+ /// <summary>
+ /// comment for interface
+ /// </summary>
+ public interface InterfaceTest
+ {
+ }
+
+ /// <summary>
+ /// comment for enum type
+ /// </summary>
+ public enum EnumTest
+ {
+ /// <summary>
+ /// comment for enum field
+ /// </summary>
+ Foo,
+ Bar,
+ }
+
+ /// <summary>
+ /// comment for dummy type
+ /// </summary>
+ public class Dummy {}
+
+ /// <summary>
+ /// comment for delegate type
+ /// </summary>
+ public delegate void MyDelegate (object o, EventArgs e);
+
+ /// <summary>
+ /// description for class Test
+ /// </summary>
+ public class Test
+ {
+ /// comment for const declaration
+ const string Constant = "CONSTANT STRING";
+
+ /// comment for public field
+ public string BadPublicField;
+
+ /// comment for private field
+ private string PrivateField;
+
+ /// comment for public property
+ public string PublicProperty {
+ /// comment for private property getter
+ get { return null; }
+ }
+
+ /// comment for private property
+ private string PrivateProperty {
+ get { return null; }
+ /// comment for private property setter
+ set { }
+ }
+
+ int x;
+
+ /// public event EventHandler MyEvent ;-)
+ public event EventHandler MyEvent;
+
+ int y;
+
+ /// here is a documentation!!!
+ public static void Foo ()
+ {
+ }
+
+ /// here is a documentation with parameters
+ public static void Foo (long l, Test t, System.Collections.ArrayList al)
+ {
+ }
+
+ /// comment for indexer
+ public string this [int i] {
+ get { return null; }
+ }
+
+ /// comment for indexer wit multiple parameters
+ public string this [int i, Test t] {
+ get { return null; }
+ }
+
+ /// <summary>
+ /// comment for unary operator
+ /// </summary>
+ public static bool operator ! (Test t)
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// comment for binary operator
+ /// </summary>
+ public static int operator + (Test t, int b)
+ {
+ return b;
+ }
+
+ /// comment for destructor
+ ~Test ()
+ {
+ }
+
+ /// comment for .ctor()
+ public Test ()
+ {
+ }
+
+ /// comment for .ctor(string arg, string [] args)
+ public Test (string arg, string [] args)
+ {
+ }
+
+ /// comment for internal class
+ public class InternalClass
+ {
+ }
+
+ /// comment for internal struct
+ public struct InternalStruct
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-023</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Test.Foo(Test.A,System.Int32)">\r
+ here is a documentation
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-023.xml
+ public class Test
+ {
+ public class A {}
+
+ public static void Main ()
+ {
+ }
+
+ /// here is a documentation
+ public static void Foo (A a, int x)
+ {
+ }
+ }
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-024</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ <!-- Include tag is invalid --><include/>\r
+ </member>\r
+ <member name="M:Testing.Test.Main">\r
+ <!-- Include tag is invalid --><include file="a"/>\r
+ </member>\r
+ <member name="M:Testing.Test.Bar(System.Int32)">\r
+ <!-- Include tag is invalid --><include path="/foo/bar"/>\r
+ </member>\r
+ <member name="M:Testing.Test.Baz(System.Int32)">\r
+ <!-- Badly formed XML file "c:\cygwin\home\_\cvs\mcs\tests\there-is-no-such-file" cannot be included -->\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-024.xml
+
+namespace Testing
+{
+ /// <include/>
+ public class Test
+ {
+ // warning
+ /// <include file='a' />
+ public static void Main ()
+ {
+ }
+
+ // warning
+ /// <include path='/foo/bar' />
+ public void Bar (int x)
+ {
+ }
+
+ // warning
+ /// <include file='there-is-no-such-file' path='/foo/bar' />
+ public void Baz (int x)
+ {
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-025</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ <!-- No matching elements were found for the following include tag --><include file="../xml-025.inc" path="/foo"/>\r
+ </member>\r
+ <member name="F:Testing.Test.S1">\r
+ <root attr="is attribute allowed?">\r
+ includes XML markup.\r
+ <child>test</child>\r
+ <child>test2</child>\r
+</root>\r
+ </member>\r
+ <member name="F:Testing.Test.S2">\r
+ <child>test</child><child>test2</child>\r
+ </member>\r
+ <member name="F:Testing.Test.S3">\r
+ <!-- Failed to insert some or all of included XML -->\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-025.xml
+// Note that it could not be compiled to generate reference output as it is.
+// csc needs '\\' instead of '/' for file specification.
+
+namespace Testing
+{
+ /// <include file='../xml-025.inc' path='/foo' />
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <include file='../xml-025.inc' path='/root'/>
+ public string S1;
+
+ /// <include file='../xml-025.inc' path='/root/child'/>
+ public string S2;
+
+ /// <include file='../xml-025.inc' path='/root/@attr'/>
+ public string S3;
+ }
+}
+
--- /dev/null
+<root attr='is attribute allowed?'>
+ includes XML markup.
+ <child>test</child>
+ <child>test2</child>
+</root>
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-026</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ test class
+ </member>\r
+ <member name="M:Testing.Test.Foo(System.Int32)">\r
+ <param>anonymous</param>
+ </member>\r
+ <member name="M:Testing.Test.Bar(System.Int32)">\r
+ <param name='i'>correct</param>
+ <param name='i'>duplicate</param>
+ </member>\r
+ <member name="M:Testing.Test.Baz(System.Int32)">\r
+ <param name='mismatch'>mismatch</param>
+ </member>\r
+ <member name="M:Testing.Test.Var(System.Int32[])">\r
+ <param name='arr'>varargs</param>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-026.xml
+namespace Testing
+{
+ /// test class
+ public class Test
+ {
+ public static void Main ()
+ {
+ }
+
+ /// <param>anonymous</param>
+ public void Foo (int i) {}
+
+ /// <param name='i'>correct</param>
+ /// <param name='i'>duplicate</param>
+ public void Bar (int i) {}
+
+ /// <param name='mismatch'>mismatch</param>
+ public void Baz (int i) {}
+
+ /// <param name='arr'>varargs</param>
+ public void Var (params int [] arr) {}
+ }
+}
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-027</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Testing.Test">\r
+ <summary>\r
+ <see/>\r
+ <see cref="!:!!!!!"/>\r
+ <see cref="!:nonexist"/>\r
+ <see cref="T:Testing.Test"/>\r
+ <see cref="T:Testing.Test"/>\r
+ <see cref="T:Test"/>\r
+ <see cref="_:Test"/>\r
+ <see cref="P:Bar"/>\r
+ <see cref="F:Bar"/>\r
+ <see cref="F:Testing.Test.Bar"/>\r
+ <see cref="P:Baz"/>\r
+ <see cref="F:Baz"/>\r
+ <see cref="P:Testing.Test.Baz"/>\r
+ <see cref="!:nonexist.Foo()"/>\r
+ <see cref="M:Testing.Test.Foo"/>\r
+ <see cref="M:Testing.Test.Foo"/>\r
+ <see cref="!:Test.Bar()"/>\r
+ <see cref="!:Test.Foo(System.Int32)"/>\r
+ </summary>\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-027.xml
+using ZZZ = Testing.Test;
+
+namespace Testing
+{
+ /// <summary>
+ /// <see />
+ /// <see cref='!!!!!' />
+ /// <see cref='nonexist' />
+ /// <see cref='Test' />
+ /// <see cref='ZZZ' />
+ /// <see cref='T:Test' />
+ /// <see cref='_:Test' />
+ /// <see cref='P:Bar' />
+ /// <see cref='F:Bar' />
+ /// <see cref='Bar' />
+ /// <see cref='P:Baz' />
+ /// <see cref='F:Baz' />
+ /// <see cref='Baz' />
+ /// <see cref='nonexist.Foo()' />
+ /// <see cref='Test.Foo()' />
+ /// <see cref='ZZZ.Foo()' />
+ /// <see cref='Test.Bar()' />
+ /// <see cref='Test.Foo(System.Int32)' />
+ /// </summary>
+ class Test
+ {
+ public static void Main () { System.Console.Error.WriteLine ("xml-027 is running fine ;-)"); }
+
+ // I don't put any documentation here, but cref still works.
+ public void Foo () {}
+
+ public string Bar;
+
+ public string Baz { get { return ""; } }
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-028</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="T:Test">\r
+ <summary>\r
+ Partial comment #2\r
+ Partial comment #1\r
+ </summary>\r
+ </member>\r
+ <member name="T:Test.Inner">\r
+ <summary>\r
+ Partial inner class!\r
+ ... is still available.\r
+ </summary>\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-028.xml
+using System;
+
+/// <summary>
+/// Partial comment #2
+public partial class Test
+{
+ string Bar;
+
+ public static void Main () {}
+
+ /// <summary>
+ /// Partial inner class!
+ internal partial class Inner
+ {
+ public string Hoge;
+ }
+}
+
+/// Partial comment #1
+/// </summary>
+public partial class Test
+{
+ public string Foo;
+
+ /// ... is still available.
+ /// </summary>
+ internal partial class Inner
+ {
+ string Fuga;
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-029</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Test1.Foo">\r
+ <summary>
+ Some test documentation
+ </summary>
+ </member>\r
+ <member name="T:ITest2">\r
+ <summary>
+ Publicly available interface
+ </summary>
+ </member>\r
+ <member name="M:ITest2.Foo">\r
+ <summary>
+ Some test documentation
+ </summary>
+ </member>\r
+ <member name="P:ITest2.Bar">\r
+ <summary>
+ Some test documentation
+ </summary>
+ </member>\r
+ <member name="E:ITest2.EventRaised">\r
+ <summary>
+ Some test documentation
+ </summary>
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-029.xml
+using System;
+
+class Test1 {
+ /// <summary>
+ /// Some test documentation
+ /// </summary>
+ void Foo(){}
+
+ public static void Main () {}
+}
+
+/// <summary>
+/// Publicly available interface
+/// </summary>
+public interface ITest2 {
+
+ /// <summary>
+ /// Some test documentation
+ /// </summary>
+ void Foo();
+
+ /// <summary>
+ /// Some test documentation
+ /// </summary>
+ long Bar { get; }
+
+ /// <summary>
+ /// Some test documentation
+ /// </summary>
+ event EventHandler EventRaised;
+}
+
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-030</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Test.foo2">\r
+ <summary>\r
+ some summary\r
+ </summary>\r
+ <value>\r
+ <see cref="T:Test[]"/>\r
+ <see cref="T:System.Text.RegularExpressions.Regex"/>\r
+ <see cref="T:System.Text.RegularExpressions.Regex"/>\r
+ <see cref="N:System.Text.RegularExpressions"/>\r
+ <see cref="T:System.Text.RegularExpressions.Regex[]"/>\r
+ </value>\r
+ </member>\r
+ <member name="M:Test.foo3(System.String,System.Object[])">\r
+ <summary>\r
+ <see cref="M:System.String.Format(System.String,System.Object[])"/>.\r
+ <see cref="M:System.String.Format(System.String,System.Object[])"/>.\r
+ <see cref="M:System.String.Format(System.String,System.Object[])"/>.\r
+ <see cref="M:System.String.Format(System.String,System.Object[])"/>.\r
+ </summary>\r
+ <param name="line">The formatting string.</param>\r
+ <param name="args">The object array to write into format string.</param>\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-030.xml -warn:4 -warnaserror
+using System;
+
+class Test
+{
+ static void Main () {}
+
+ /// <summary>
+ /// some summary
+ /// </summary>
+ /// <value>
+ /// <see cref="T:Test[]"/>
+ /// <see cref="T:System.Text.RegularExpressions.Regex"/>
+ /// <see cref="System.Text.RegularExpressions.Regex"/>
+ /// <see cref="System.Text.RegularExpressions"/>
+ /// <see cref="T:System.Text.RegularExpressions.Regex[]"/>
+ /// </value>
+ //
+ // <see cref="T:System.Text.RegularExpressions"/> .. csc incorrectly allows it
+ // <see cref="System.Text.RegularExpressions.Regex[]"/> ... csc does not allow it.
+ //
+ public void foo2() {
+ }
+
+ /// <summary>
+ /// <see cref="String.Format(string, object[])" />.
+ /// <see cref="string.Format(string, object[])" />.
+ /// <see cref="String.Format(string, object [ ])" />.
+ /// <see cref="string.Format(string, object [ ])" />.
+ /// </summary>
+ /// <param name="line">The formatting string.</param>
+ /// <param name="args">The object array to write into format string.</param>
+ public void foo3(string line, params object[] args) {
+ }
+}
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-031</name>\r
+ </assembly>\r
+ <members>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-031.xml -warn:4 -warnaserror
+//// Some comment
+////how about this line?
+using System;
+using System.IO;
+
+class Test
+{
+ public static void Main ()
+ {
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>\r
+<doc>\r
+ <assembly>\r
+ <name>xml-032</name>\r
+ </assembly>\r
+ <members>\r
+ <member name="M:Test.#ctor(System.String)">\r
+ <exception cref="T:System.ArgumentNullException"><paramref name="wrongref"/> is <see langword="null"/>.</exception>\r
+ <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="wrongRefAgain"/> is a zero-length <see cref="T:System.String"/>.</exception>\r
+ </member>\r
+ </members>\r
+</doc>\r
--- /dev/null
+// Compiler options: -doc:xml-032.xml -warn:4 -warnaserror
+using System;
+
+class Test
+{
+ /// <exception cref="ArgumentNullException"><paramref name="wrongref" /> is <see langword="null" />.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="wrongRefAgain" /> is a zero-length <see cref="string" />.</exception>
+ protected Test(string name)
+ {
+ }
+
+ static void Main () {}
+}
+
--- /dev/null
+using System;
+using System.Collections;
+using System.Xml;
+
+public class Test
+{
+ public class ComparisonException : Exception
+ {
+ public ComparisonException (string message)
+ : base (message)
+ {
+ }
+ }
+
+ static bool debug = false;
+ static bool error = false;
+
+ public static void Main (string [] args)
+ {
+ if (args.Length < 2) {
+ Console.Error.WriteLine ("Usage: xmldocdiff [reference_output.xml] [actual_output.xml]");
+ return;
+ }
+ if (args.Length > 2 && args [2].EndsWith ("-debug"))
+ debug = true;
+
+ try {
+ Run (args);
+ } catch (Exception ex) {
+ Console.WriteLine ("FAIL: " + args [1]);
+ throw ex;
+ }
+ Console.WriteLine ("PASS: " + args [1]);
+ }
+
+ private static void Run (string [] args)
+ {
+ XmlDocument doc1 = new XmlDocument ();
+ doc1.Load (args [0]);
+ XmlDocument doc2 = new XmlDocument ();
+ doc2.Load (args [1]);
+
+ XmlNodeList memberList1 = doc1.SelectNodes ("/doc/members/member");
+ XmlNodeList memberList2 = doc2.SelectNodes ("/doc/members/member");
+
+ Hashtable namedItems = new Hashtable ();
+
+ foreach (XmlElement el in memberList1)
+ namedItems.Add (el.GetAttribute ("name"), el);
+ foreach (XmlElement el2 in memberList2) {
+ string name = el2.GetAttribute ("name");
+ XmlElement el1 = namedItems [name] as XmlElement;
+ if (el1 == null) {
+ Report ("Extraneous element found. Name is '{0}'", name);
+ continue;
+ }
+ namedItems.Remove (name);
+
+ CompareNodes (el1, el2);
+
+ }
+ foreach (string name in namedItems.Keys)
+ Report ("Expected comment was not found. Name is {0}, XML is {1}", name, ((XmlElement) namedItems [name]).OuterXml);
+
+ // finally, check other nodes than members
+ doc1.SelectSingleNode ("/doc/members").RemoveAll ();
+ doc2.SelectSingleNode ("/doc/members").RemoveAll ();
+ string xml1 = doc1.OuterXml.Replace ("\r", "").Trim ();
+ string xml2 = doc2.OuterXml.Replace ("\r", "").Trim ();
+ if (xml1 != xml2)
+ Report (@"Either of doc, assembly, name, members elements are different.
+doc1: {0}
+doc2: {1}", xml1, xml2);
+ }
+
+ private static void CompareNodes (XmlNode n1, XmlNode n2)
+ {
+ if (n2 == null) {
+ Report (@"Nodes does not exist:
+Node1: {0}", n1.OuterXml);
+ return;
+ }
+ if (n1.NodeType != n2.NodeType) {
+ Report (@"Nodes differ:
+Node1: {0}
+Node2: {1}", n1.OuterXml, n2.OuterXml);
+ return;
+ }
+ if (n1.Name != n2.Name) {
+ Report (@"Node names differ:
+Node1: {0}
+Node2: {1}", n1.OuterXml, n2.OuterXml);
+ return;
+ }
+ if (n1 is XmlElement) {
+ for (int i = 0; i < n1.Attributes.Count; i++)
+ CompareNodes (n1.Attributes [i],
+ n2.Attributes [i]);
+ for (int i = 0; i < n1.ChildNodes.Count; i++)
+ CompareNodes (n1.ChildNodes [i],
+ n2.ChildNodes [i]);
+ }
+ if (n1.NodeType != XmlNodeType.Comment && n1.Value != null) {
+ string v1 = n1.Value.Trim ().Replace ("\r", "");
+ string v2 = n2.Value.Trim ().Replace ("\r", "");
+ if (v1 != v2)
+ Report (@"Node values differ:
+Node1: {0}
+Node2: {1}", v1, v2);
+ }
+ }
+
+ static void Report (string format, params object [] args)
+ {
+ error = true;
+ if (debug)
+ Console.WriteLine (format, args);
+ else
+ throw new ComparisonException (String.Format (format, args));
+ }
+}
+
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * monop.cs : csc build fix. See bug #70185 for details.
+
2004-11-30 Duncan Mak <duncan@ximian.com>
* monop.cs (GetAssemblyNamesFromGAC): New method, calls out to
return;
}
+ string message = null;
string tname = args [i];
Type t = GetType (tname);
}
}
- string message = null;
if (t == null) {
foreach (string assm in GetAssemblyNamesFromGAC ()) {
try {
# the handles dir doesn't apply to windows
-if PLATFORM_WIN32
-SUBDIRS = utils io-layer monoburg os metadata cil dis \
- arch monograph interpreter mini tests benchmark profiler
-else
-SUBDIRS = utils io-layer monoburg os metadata cil dis \
- arch monograph interpreter mini tests benchmark handles profiler
+if ! PLATFORM_WIN32
+HANDLES = handles
endif
+
+SUBDIRS = utils io-layer monoburg os cil metadata dis \
+ arch monograph interpreter mini tests benchmark $(HANDLES) profiler
|\r
| Author: Sergey Chaban\r
|\r
- | $Id: make-opcode-def.xsl,v 1.1 2001/07/13 01:04:23 miguel Exp $\r
+ | $Id$\r
-->\r
\r
\r
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * main.c: Rename compilercontrolled to privatescope
+
+ * get.c (get_class_name): Correct implementation that correctly
+ handles nested classes.
+
2004-11-26 Miguel de Icaza <miguel@ximian.com>
* main.c: Better implementation of the quote keyword, list all of
return retval;
}
+static char *
+get_class_name (MonoClass *c)
+{
+ if (c->nested_in){
+ char *part_a = get_class_name (c->nested_in);
+ char *result;
+
+ result = g_strdup_printf ("%s/%s", part_a, c->name);
+ g_free (part_a);
+ return result;
+ }
+ if (*c->name_space)
+ return g_strdup_printf ("%s.%s", c->name_space, c->name);
+ else
+ return g_strdup (c->name);
+}
+
char *
dis_stringify_object_with_class (MonoImage *m, MonoClass *c, gboolean prefix)
{
/* FIXME: handle MONO_TYPE_OBJECT ... */
const char *otype = c->byval_arg.type == MONO_TYPE_VALUETYPE ? "valuetype" : "class" ;
char *assemblyref = NULL, *result, *esname, *generic = NULL;
+
if (m != c->image) {
if (c->image->assembly_name) {
/* we cheat */
}
}
- if (c->nested_in) {
- result = g_strdup_printf ("%s%s%s/%s", c->nested_in->name_space,
- *c->nested_in->name_space?".":"", c->nested_in->name,
- c->name);
- } else {
- result = g_strdup_printf ("%s%s%s", c->name_space,
- *c->name_space?".":"", c->name);
- }
+ result = get_class_name (c);
esname = get_escaped_name (result);
g_free (result);
}
static dis_map_t field_access_map [] = {
- { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
+ { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "privatescope " },
{ FIELD_ATTRIBUTE_PRIVATE, "private " },
{ FIELD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem " },
{ FIELD_ATTRIBUTE_ASSEMBLY, "assembly " },
}
static dis_map_t method_access_map [] = {
- { METHOD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
+ { METHOD_ATTRIBUTE_COMPILER_CONTROLLED, "privatescope " },
{ METHOD_ATTRIBUTE_PRIVATE, "private " },
{ METHOD_ATTRIBUTE_FAM_AND_ASSEM, "famandassem " },
{ METHOD_ATTRIBUTE_ASSEM, "assembly " },
+2004-12-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * interp.c: fix the build. Dunno if it's correct.
+
+2004-12-02 Bernie Solomon <bernard@ugsolutions.com>
+
+ * mintops.def:
+ * transform.c:
+ * interp.c: cope with new thread interruption icall
+
2004-11-12 Ben Maurer <bmaurer@ximian.com>
* transform.c: Fix bug with delegates in interp.
context->managed_code = 0;
switch (op) {
+ case MINT_ICALL_V_V: {
+ void (*func)() = ptr;
+ func ();
+ break;
+ }
case MINT_ICALL_P_V: {
void (*func)(gpointer) = ptr;
func (sp [-1].data.p);
}
goto handle_finally;
MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ICALL_V_V)
MINT_IN_CASE(MINT_ICALL_P_V)
MINT_IN_CASE(MINT_ICALL_P_P)
MINT_IN_CASE(MINT_ICALL_PP_V)
mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
mono_add_internal_call ("System.Delegate::CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal);
+ mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", mono_create_icall_signature ("void"), FALSE);
+
mono_runtime_init (domain, NULL, NULL);
+
mono_thread_attach (domain);
return domain;
}
OPDEF(MINT_STRLEN, "strlen", 1, MintOpNoArgs)
OPDEF(MINT_ARRAY_RANK, "array_rank", 1, MintOpNoArgs)
-OPDEF(MINT_ICALL_P_V, "mono_icall_p_v", 2, MintOpClassToken) /* not really */
+OPDEF(MINT_ICALL_V_V, "mono_icall_v_v", 2, MintOpClassToken) /* not really */
+OPDEF(MINT_ICALL_P_V, "mono_icall_p_v", 2, MintOpClassToken)
OPDEF(MINT_ICALL_P_P, "mono_icall_p_p", 2, MintOpClassToken)
OPDEF(MINT_ICALL_PP_V, "mono_icall_pp_v", 2, MintOpClassToken)
OPDEF(MINT_ICALL_PI_V, "mono_icall_pi_v", 2, MintOpClassToken)
CHECK_STACK (&td, info->sig->param_count);
switch (info->sig->param_count) {
+ case 0:
+ if (MONO_TYPE_IS_VOID (info->sig->ret))
+ ADD_CODE (&td,MINT_ICALL_V_V);
+ else
+ g_assert_not_reached();
+ break;
case 1:
if (MONO_TYPE_IS_VOID (info->sig->ret))
ADD_CODE (&td,MINT_ICALL_P_V);
+2004-12-04 Zoltan Varga <vargaz@freemail.hu>
+
+ * image.c: Add unbox_wrapper_cache.
+
+ * class-internals.h debug-helpers.c: Add MONO_WRAPPER_UNBOX.
+
+ * marshal.h marshal.c (mono_marshal_get_unbox_wrapper): New wrapper
+ function generator.
+
+ * object.c (mono_delegate_ctor): Call unbox wrapper if neccesary.
+ Fixes #70173.
+
+ * metadata-internals.h image.c: Add MonoImage->unbox_wrapper_cache.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * loader.c (mono_method_get_signature_full): New public function;
+ like mono_method_get_signature(), but with an additional
+ `MonoGenericContext *' argument.
+
+ * class.c (mono_class_inflate_generic_signature): Formerly known
+ as inflate_generic_signature(); make this public.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * metadata.c
+ (mono_metadata_parse_type_full): Take a `MonoGenericContext *'
+ instead of a `MonoGenericContainer *'.
+ (mono_metadata_parse_array_full): Likewise.
+ (mono_metadata_parse_signature_full): Likewise.
+ (mono_metadata_parse_method_signature_full): Likewise.
+ (mono_metadata_parse_generic_inst): Likewise.
+ (mono_metadata_parse_generic_param): Likewise.
+ (mono_metadata_parse_mh_full): Likewise.
+ (mono_type_create_from_typespec_full): Likewise.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * class-internals.h (MonoGenericContainer): Replaced the
+ `MonoGenericContext * pointer with a `MonoGenericContext'
+ structure and made it the first element.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * class.c
+ (inflate_generic_type): Set the `context->container' when creating
+ a new MonoGenericContext.
+ (mono_class_inflate_generic_method): Likewise.
+ (mono_class_create_from_typespec): Just use `context->container'
+ to get the container.
+
+ * loader.c (method_from_methodspec): Set `context->parent' from
+ `context->container' - and if that's a method container, use its
+ parent. Also set the `context->container' when creating a new
+ MonoGenericContext.
+ (mono_get_method_from_token): Use just `context->container' to get
+ the container.
+
+ * metadata.c (do_mono_metadata_parse_generic_class): Also set
+ `gclass->context->container'.
+
+ * reflection.c (do_mono_reflection_bind_generic_parameters): Set
+ the `context->container' when creating a new MonoGenericContext.
+
+2004-12-03 Zoltan Varga <vargaz@freemail.hu>
+
+ * reflection.c (compare_genericparam): Sort params with identical
+ owner by their number. Fixes gen-111 on sparc.
+
2004-12-02 Zoltan Varga <vargaz@freemail.hu>
* threadpool.c (async_invoke_thread): Call push/pop_appdomain_ref
* reflection.c: Fix some memory leaks.
+2004-12-02 Martin Baulig <martin@ximian.com>
+
+ * metadata-internals.h (MonoImage): Removed `generic_class_cache'.
+
+ * metadata.c (generic_class_cache): New static hashtable.
+ (mono_metadata_lookup_generic_class): New public method.
+
+2004-12-02 Martin Baulig <martin@ximian.com>
+
+ * class.c (mono_class_create_from_typedef): Call
+ mono_class_setup_parent() and mono_class_create_mono_type() before
+ parsing the interfaces.
+
2004-12-02 Martin Baulig <martin@ximian.com>
* metadata.c (generic_inst_cache): New static hashtable.
MONO_WRAPPER_CASTCLASS,
MONO_WRAPPER_PROXY_ISINST,
MONO_WRAPPER_STELEMREF,
+ MONO_WRAPPER_UNBOX,
MONO_WRAPPER_UNKNOWN
} MonoWrapperType;
};
struct _MonoGenericContainer {
+ MonoGenericContext context;
MonoGenericContainer *parent;
- MonoGenericContext *context;
GHashTable *method_hash;
MonoClass *klass;
int type_argc : 6;
MonoJitICallInfo *
mono_find_jit_icall_by_addr (gconstpointer addr);
+MonoMethodSignature*
+mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context);
+
#endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */
ngclass->klass = NULL;
ngclass->context = g_new0 (MonoGenericContext, 1);
+ ngclass->context->container = ngclass->container;
ngclass->context->gclass = ngclass;
- mono_loader_lock ();
- cached = g_hash_table_lookup (ogclass->klass->image->generic_class_cache, ngclass);
+ ngclass->dynamic_info = NULL;
+ ngclass->initialized = FALSE;
+ mono_loader_lock ();
+ cached = mono_metadata_lookup_generic_class (ngclass);
if (cached) {
g_free (ngclass);
mono_loader_unlock ();
return nt;
}
- ngclass->dynamic_info = NULL;
- ngclass->initialized = FALSE;
-
mono_class_create_generic (ngclass);
mono_class_create_generic_2 (ngclass);
nt = dup_type (type, type);
nt->data.generic_class = ngclass;
- g_hash_table_insert (ogclass->klass->image->generic_class_cache, ngclass, ngclass);
mono_loader_unlock ();
return nt;
}
return inflated;
}
-static MonoMethodSignature*
-inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
- MonoGenericContext *context)
+MonoMethodSignature*
+mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context)
{
MonoMethodSignature *res;
gboolean is_open;
rklass = result->nmethod.method.klass = mono_class_from_mono_type (declaring);
}
- result->nmethod.method.signature = inflate_generic_signature (
+ result->nmethod.method.signature = mono_class_inflate_generic_signature (
method->klass->image, method->signature, context);
if (context->gmethod) {
result->context = g_new0 (MonoGenericContext, 1);
+ result->context->container = context->gmethod->container;
result->context->gmethod = context->gmethod;
result->context->gclass = rklass->generic_class;
container = class->generic_class->container;
}
field->type = mono_metadata_parse_type_full (
- m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
+ cols [MONO_FIELD_FLAGS], sig + 1, &sig);
if (mono_field_is_deleted (field))
continue;
if (class->generic_class) {
if (cols [MONO_TYPEDEF_EXTENDS])
parent = mono_class_get_full (
image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+
+ mono_class_setup_parent (class, parent);
+
+ mono_class_setup_mono_type (class);
+
interfaces = mono_metadata_interfaces_from_typedef_full (image, type_token, &icount, context);
class->interfaces = interfaces;
/*g_print ("Load class %s\n", name);*/
- mono_class_setup_parent (class, parent);
-
- mono_class_setup_mono_type (class);
-
/*
* Compute the field and method lists
*/
MonoGenericContext *context)
{
MonoType *type, *inflated;
- MonoGenericContainer *container = NULL;
MonoClass *class;
- if (context) {
- if (context->gmethod && context->gmethod->container) {
- g_assert (context->gmethod->container);
- container = context->gmethod->container;
- } else if (context->gclass) {
- g_assert (context->gclass->container);
- container = context->gclass->container;
- } else if (context->container)
- container = context->container;
- }
-
- type = mono_type_create_from_typespec_full (image, container, type_spec);
+ type = mono_type_create_from_typespec_full (image, context, type_spec);
switch (type->type) {
case MONO_TYPE_ARRAY:
"cancast",
"proxy_isinst",
"stelemref",
+ "unbox",
"unknown"
};
image->native_wrapper_cache = g_hash_table_new (NULL, NULL);
image->remoting_invoke_cache = g_hash_table_new (NULL, NULL);
image->synchronized_cache = g_hash_table_new (NULL, NULL);
+ image->unbox_wrapper_cache = g_hash_table_new (NULL, NULL);
image->typespec_cache = g_hash_table_new (NULL, NULL);
image->memberref_signatures = g_hash_table_new (NULL, NULL);
image->helper_signatures = g_hash_table_new (g_str_hash, g_str_equal);
-
- image->generic_class_cache =
- g_hash_table_new ((GHashFunc)mono_metadata_generic_class_hash,
- (GCompareFunc)mono_metadata_generic_class_equal);
}
static MonoImage *
g_hash_table_foreach (image->remoting_invoke_cache, free_remoting_wrappers, NULL);
g_hash_table_destroy (image->remoting_invoke_cache);
g_hash_table_destroy (image->runtime_invoke_cache);
+ g_hash_table_destroy (image->synchronized_cache);
+ g_hash_table_destroy (image->unbox_wrapper_cache);
g_hash_table_destroy (image->typespec_cache);
- g_hash_table_destroy (image->generic_class_cache);
g_hash_table_foreach (image->memberref_signatures, free_mr_signatures, NULL);
g_hash_table_destroy (image->memberref_signatures);
g_hash_table_foreach (image->helper_signatures, free_mr_signatures, NULL);
* token is the method_ref or method_def token used in a call IL instruction.
*/
MonoMethodSignature*
-mono_method_get_signature (MonoMethod *method, MonoImage *image, guint32 token)
+mono_method_get_signature_full (MonoMethod *method, MonoImage *image, guint32 token, MonoGenericContext *context)
{
int table = mono_metadata_token_table (token);
int idx = mono_metadata_token_index (token);
ptr = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
mono_metadata_decode_blob_size (ptr, &ptr);
- sig = mono_metadata_parse_method_signature (image, 0, ptr, NULL);
+ sig = mono_metadata_parse_method_signature_full (image, context, 0, ptr, NULL);
g_hash_table_insert (image->memberref_signatures, GUINT_TO_POINTER (token), sig);
}
+ sig = mono_class_inflate_generic_signature (image, sig, context);
+
return sig;
}
+MonoMethodSignature*
+mono_method_get_signature (MonoMethod *method, MonoImage *image, guint32 token)
+{
+ return mono_method_get_signature_full (method, image, token, NULL);
+}
+
static MonoMethod *
method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *context)
{
ptr = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
mono_metadata_decode_blob_size (ptr, &ptr);
- sig = mono_metadata_parse_method_signature_full (image, container, 0, ptr, NULL);
+ sig = mono_metadata_parse_method_signature_full (image, (MonoGenericContext *) container, 0, ptr, NULL);
switch (class) {
case MONO_MEMBERREF_PARENT_TYPEREF:
g_assert (container && container->is_method);
if (context) {
- if (context->gclass) {
- g_assert (context->gclass->container);
- container->parent = context->gclass->container;
- } else
- container->parent = context->container;
+ g_assert (context->container);
+ container->parent = context->container;
+ if (container->parent->is_method)
+ container->parent = container->parent->parent;
}
gmethod = g_new0 (MonoGenericMethod, 1);
gmethod->container = container;
- gmethod->inst = mono_metadata_parse_generic_inst (image, container, param_count, ptr, &ptr);
+ gmethod->inst = mono_metadata_parse_generic_inst (
+ image, (MonoGenericContext *) container, param_count, ptr, &ptr);
+
if (context)
gmethod->inst = mono_metadata_inflate_generic_inst (gmethod->inst, context);
if (!context) {
new_context = g_new0 (MonoGenericContext, 1);
+ new_context->container = container;
new_context->gmethod = gmethod;
context = new_context;
} else {
new_context = g_new0 (MonoGenericContext, 1);
+ new_context->container = container;
new_context->gmethod = gmethod;
new_context->gclass = context->gclass;
if (table != MONO_TABLE_METHOD) {
MonoGenericContainer *generic_container = NULL;
if (context) {
- if (context->gclass) {
- g_assert (context->gclass->container);
- generic_container = context->gclass->container;
- } else
- generic_container = context->container;
+ g_assert (context->container);
+ generic_container = context->container;
}
if (table == MONO_TABLE_METHODSPEC)
return method_from_methodspec (image, context, idx);
if (!sig) /* already taken from the methodref */
sig = mono_metadata_blob_heap (image, cols [4]);
size = mono_metadata_decode_blob_size (sig, &sig);
- result->signature = mono_metadata_parse_method_signature_full (image, container, idx, sig, NULL);
+ result->signature = mono_metadata_parse_method_signature_full (
+ image, (MonoGenericContext *) container, idx, sig, NULL);
if (!result->klass) {
guint32 type = mono_metadata_typedef_from_method (image, token);
!(result->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) && container) {
gpointer loc = mono_image_rva_map (image, cols [0]);
g_assert (loc);
- ((MonoMethodNormal *) result)->header = mono_metadata_parse_mh_full (image, container, loc);
+ ((MonoMethodNormal *) result)->header = mono_metadata_parse_mh_full (
+ image, (MonoGenericContext *) container, loc);
}
((MonoMethodNormal *) result)->generic_container = generic_container;
g_assert (loc);
- mn->header = mono_metadata_parse_mh_full (img, mn->generic_container, loc);
+ mn->header = mono_metadata_parse_mh_full (img, (MonoGenericContext *) mn->generic_container, loc);
mono_loader_unlock ();
return mn->header;
return res;
}
+
+/*
+ * the returned method calls 'method' unboxing the this argument
+ */
+MonoMethod *
+mono_marshal_get_unbox_wrapper (MonoMethod *method)
+{
+ MonoMethodSignature *sig = method->signature;
+ int i;
+ MonoMethodBuilder *mb;
+ MonoMethod *res;
+ GHashTable *cache;
+
+ cache = method->klass->image->unbox_wrapper_cache;
+ if ((res = mono_marshal_find_in_cache (cache, method)))
+ return res;
+
+ mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNBOX);
+
+ g_assert (sig->hasthis);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_icon (mb, sizeof (MonoObject));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ for (i = 0; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_managed_call (mb, method, NULL);
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ res = mono_mb_create_and_cache (cache, method,
+ mb, sig, sig->param_count + 16);
+ mono_mb_free (mb);
+
+ /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
+
+ return res;
+}
+
MonoMethod*
mono_marshal_get_stelemref ()
{
MonoMethod *
mono_marshal_get_synchronized_wrapper (MonoMethod *method);
+MonoMethod *
+mono_marshal_get_unbox_wrapper (MonoMethod *method);
+
MonoMethod *
mono_marshal_get_isinst (MonoClass *klass);
GHashTable *memberref_signatures;
GHashTable *helper_signatures;
- /*
- * Indexed by MonoGenericClass.
- */
- GHashTable *generic_class_cache;
-
/*
* Indexes namespaces to hash tables that map class name to typedef token.
*/
GHashTable *native_wrapper_cache;
GHashTable *remoting_invoke_cache;
GHashTable *synchronized_cache;
+ GHashTable *unbox_wrapper_cache;
void *reflection_info;
MonoArrayType *
mono_metadata_parse_array_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
const char *ptr,
const char **rptr);
MonoType *
mono_metadata_parse_type_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
MonoParseTypeMode mode,
short opt_attrs,
const char *ptr,
MonoType *
mono_type_create_from_typespec_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
guint32 type_spec);
MonoMethodSignature *
mono_metadata_parse_signature_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
guint32 token);
MonoMethodSignature *
mono_metadata_parse_method_signature_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
int def,
const char *ptr,
const char **rptr);
MonoMethodHeader *
mono_metadata_parse_mh_full (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
const char *ptr);
guint
MonoGenericInst *
mono_metadata_parse_generic_inst (MonoImage *image,
- MonoGenericContainer *generic_container,
+ MonoGenericContext *generic_context,
int count,
const char *ptr,
const char **rptr);
MonoGenericInst *
mono_metadata_lookup_generic_inst (MonoGenericInst *ginst);
+MonoGenericClass *
+mono_metadata_lookup_generic_class (MonoGenericClass *gclass);
+
MonoGenericInst *
mono_metadata_inflate_generic_inst (MonoGenericInst *ginst,
MonoGenericContext *context);
#include "private.h"
#include "class.h"
-static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
const char *ptr, const char **rptr);
static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
+static gboolean _mono_metadata_generic_class_equal (MonoGenericClass *g1, MonoGenericClass *g2,
+ gboolean signature_only);
/*
* Encoding of the "description" argument:
* and dimensions.
*/
MonoArrayType *
-mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
const char *ptr, const char **rptr)
{
int i;
MonoArrayType *array = g_new0 (MonoArrayType, 1);
MonoType *etype;
- etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
array->eklass = mono_class_from_mono_type (etype);
array->rank = mono_metadata_decode_value (ptr, &ptr);
static GHashTable *type_cache = NULL;
static GHashTable *generic_inst_cache = NULL;
+static GHashTable *generic_class_cache = NULL;
static int next_generic_inst_id = 0;
/*
return TRUE;
}
+static guint
+mono_generic_class_hash (gconstpointer data)
+{
+ const MonoGenericClass *gclass = (const MonoGenericClass *) data;
+ return mono_metadata_type_hash (gclass->generic_type);
+}
+
+static gboolean
+mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
+{
+ const MonoGenericClass *a = (const MonoGenericClass *) ka;
+ const MonoGenericClass *b = (const MonoGenericClass *) kb;
+
+ return _mono_metadata_generic_class_equal (a, b, FALSE);
+}
+
/**
* mono_metadata_init:
*
type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
generic_inst_cache = g_hash_table_new (mono_generic_inst_hash, mono_generic_inst_equal);
+ generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
for (i = 0; i < NBUILTIN_TYPES (); ++i)
g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
* Returns: a #MonoType structure representing the decoded type.
*/
MonoType*
-mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *generic_container, MonoParseTypeMode mode,
+mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
short opt_attrs, const char *ptr, const char **rptr)
{
MonoType *type, *cached;
type->byref = byref;
type->pinned = pinned ? 1 : 0;
- do_mono_metadata_parse_type (type, m, generic_container, ptr, &ptr);
+ do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
if (rptr)
*rptr = ptr;
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
-mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
+mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
{
MonoTableInfo *tables = image->tables;
guint32 idx = mono_metadata_token_index (token);
ptr = mono_metadata_blob_heap (image, sig);
mono_metadata_decode_blob_size (ptr, &ptr);
- return mono_metadata_parse_method_signature_full (image, generic_container, FALSE, ptr, NULL);
+ return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL);
}
MonoMethodSignature *
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
-mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
int def, const char *ptr, const char **rptr)
{
MonoMethodSignature *method;
guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
guint32 gen_param_count = 0;
gboolean is_open = FALSE;
- MonoGenericContainer *container = NULL;
+ MonoGenericContext *context = NULL;
if (*ptr & 0x10)
gen_param_count = 1;
if (gen_param_count)
method->has_type_parameters = 1;
- if (gen_param_count && (!generic_container || !generic_container->is_method)) {
- container = g_new0 (MonoGenericContainer, 1);
- container->parent = generic_container;
+ if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
+ MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
+
+ if (generic_context)
+ container->parent = generic_context->container;
container->is_signature = 1;
- container->context = g_new0 (MonoGenericContext, 1);
- container->context->container = container;
+ context = &container->context;
+ container->context.container = container;
container->type_argc = gen_param_count;
container->type_params = g_new0 (MonoGenericParam, gen_param_count);
container->type_params [i].num = i;
}
} else
- container = generic_container;
+ context = generic_context;
if (call_convention != 0xa) {
- method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+ method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
is_open = mono_class_is_open_constructed_type (method->ret);
}
ptr++;
}
method->params [i] = mono_metadata_parse_type_full (
- m, container, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+ m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
if (!is_open)
is_open = mono_class_is_open_constructed_type (method->params [i]);
}
return ginst;
}
+MonoGenericClass *
+mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
+{
+ MonoGenericClass *cached;
+ int i;
+
+ cached = g_hash_table_lookup (generic_class_cache, gclass);
+ if (cached)
+ return cached;
+
+ g_hash_table_insert (generic_class_cache, gclass, gclass);
+ return NULL;
+}
+
MonoGenericInst *
mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
{
}
MonoGenericInst *
-mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
int count, const char *ptr, const char **rptr)
{
MonoGenericInst *ginst;
ginst->type_argv = g_new0 (MonoType*, count);
for (i = 0; i < ginst->type_argc; i++) {
- MonoType *t = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
ginst->type_argv [i] = t;
if (!ginst->is_open)
}
static void
-do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
const char *ptr, const char **rptr)
{
MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
gclass->klass = g_new0 (MonoClass, 1);
- gclass->generic_type = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ gclass->generic_type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
gklass = mono_class_from_mono_type (gclass->generic_type);
- g_assert ((gclass->container = gklass->generic_container) != NULL);
+ g_assert ((gclass->context->container = gclass->container = gklass->generic_container) != NULL);
count = mono_metadata_decode_value (ptr, &ptr);
mono_class_create_generic (gclass);
- gclass->inst = mono_metadata_parse_generic_inst (m, generic_container, count, ptr, &ptr);
+ gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
mono_class_create_generic_2 (gclass);
* type.
*/
- cached = g_hash_table_lookup (m->generic_class_cache, gclass);
+ cached = g_hash_table_lookup (generic_class_cache, gclass);
if (cached) {
g_free (gclass->klass);
g_free (gclass);
type->data.generic_class = cached;
return;
} else {
- g_hash_table_insert (m->generic_class_cache, gclass, gclass);
+ g_hash_table_insert (generic_class_cache, gclass, gclass);
mono_stats.generic_instance_count++;
mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
* Internal routine to parse a generic type parameter.
*/
static MonoGenericParam *
-mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
gboolean is_mvar, const char *ptr, const char **rptr)
{
+ MonoGenericContainer *generic_container;
int index;
index = mono_metadata_decode_value (ptr, &ptr);
if (rptr)
*rptr = ptr;
+ g_assert (generic_context);
+ generic_container = generic_context->container;
+
if (!is_mvar) {
g_assert (generic_container);
if (generic_container->parent) {
* This extracts a Type as specified in Partition II (22.2.12)
*/
static void
-do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
const char *ptr, const char **rptr)
{
type->type = mono_metadata_decode_value (ptr, &ptr);
break;
}
case MONO_TYPE_SZARRAY: {
- MonoType *etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
type->data.klass = mono_class_from_mono_type (etype);
mono_metadata_free_type (etype);
break;
}
case MONO_TYPE_PTR:
- type->data.type = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
break;
case MONO_TYPE_FNPTR:
- type->data.method = mono_metadata_parse_method_signature_full (m, generic_container, 0, ptr, &ptr);
+ type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
break;
case MONO_TYPE_ARRAY:
- type->data.array = mono_metadata_parse_array_full (m, generic_container, ptr, &ptr);
+ type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
break;
case MONO_TYPE_MVAR:
- type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, TRUE, ptr, &ptr);
+ type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
break;
case MONO_TYPE_VAR:
- type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, FALSE, ptr, &ptr);
+ type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
break;
case MONO_TYPE_GENERICINST:
- do_mono_metadata_parse_generic_class (type, m, generic_container, ptr, &ptr);
+ do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
break;
default:
* Returns: a MonoMethodHeader.
*/
MonoMethodHeader *
-mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *generic_container, const char *ptr)
+mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
{
MonoMethodHeader *mh;
unsigned char flags = *(const unsigned char *) ptr;
mh->num_locals = len;
for (i = 0; i < len; ++i)
mh->locals [i] = mono_metadata_parse_type_full (
- m, generic_container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+ m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
} else {
mh = g_new0 (MonoMethodHeader, 1);
}
return MONO_TYPE_ISSTRUCT (gclass->generic_type);
}
-guint
-mono_metadata_generic_class_hash (MonoGenericClass *gclass)
-{
- return mono_metadata_type_hash (gclass->generic_type);
-}
-
static gboolean
_mono_metadata_generic_class_equal (MonoGenericClass *g1, MonoGenericClass *g2, gboolean signature_only)
{
return TRUE;
}
-gboolean
-mono_metadata_generic_class_equal (MonoGenericClass *g1, MonoGenericClass *g2)
-{
- return _mono_metadata_generic_class_equal (g1, g2, FALSE);
-}
-
guint
mono_metadata_generic_method_hash (MonoGenericMethod *gmethod)
{
case MONO_TYPE_ARRAY:
return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
case MONO_TYPE_GENERICINST:
- return ((hash << 5) - hash) ^ mono_metadata_generic_class_hash (t1->data.generic_class);
+ return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
}
return hash;
}
* token.
*/
MonoType *
-mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 type_spec)
+mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
{
guint32 idx = mono_metadata_token_index (type_spec);
MonoTableInfo *t;
ptr++;
}
- do_mono_metadata_parse_type (type, image, generic_container, ptr, &ptr);
+ do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
mono_loader_unlock ();
container->type_argc = n;
container->type_params = params;
- container->context = g_new0 (MonoGenericContext, 1);
- container->context->container = container;
+ container->context.container = container;
for (i = 0; i < n; i++)
- params [i].constraints = get_constraints (image, i + 1, container->context);
+ params [i].constraints = get_constraints (image, i + 1, &container->context);
return container;
}
gpointer
mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *real_proxy);
+MonoMethodSignature*
+mono_method_get_signature_full (MonoMethod *method, MonoImage *image, guint32 token, MonoGenericContext *context);
+
#endif /* __MONO_OBJECT_INTERNALS_H__ */
for (i = 0; i < class->vtable_size; ++i) {
MonoMethod *cm;
- if (cm = class->vtable [i]) {
+ if ((cm = class->vtable [i])) {
if (cm->signature->generic_param_count)
vt->vtable [i] = cm;
else
method = mono_marshal_get_remoting_invoke (method);
delegate->method_ptr = mono_compile_method (method);
delegate->target = target;
+ } else if (method->signature->hasthis && method->klass->valuetype) {
+ method = mono_marshal_get_unbox_wrapper (method);
+ delegate->method_ptr = mono_compile_method (method);
+ delegate->target = target;
} else {
delegate->method_ptr = addr;
delegate->target = target;
const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
- return (*b_entry)->owner - (*a_entry)->owner;
+ if ((*b_entry)->owner == (*a_entry)->owner)
+ return
+ (*a_entry)->gparam->type.type->data.generic_param->num -
+ (*b_entry)->gparam->type.type->data.generic_param->num;
+ else
+ return (*b_entry)->owner - (*a_entry)->owner;
}
static int
tb->generic_container = g_new0 (MonoGenericContainer, 1);
tb->generic_container->klass = klass;
- tb->generic_container->context = g_new0 (MonoGenericContext, 1);
- tb->generic_container->context->container = tb->generic_container;
+ tb->generic_container->context.container = tb->generic_container;
}
/*
MonoGenericClass *ogclass = gclass;
ogclass->context = g_new0 (MonoGenericContext, 1);
+ ogclass->context->container = ogclass->container;
ogclass->context->gclass = ogclass;
gclass = g_new0 (MonoGenericClass, 1);
geninst = g_new0 (MonoType, 1);
geninst->type = MONO_TYPE_GENERICINST;
- cached = g_hash_table_lookup (klass->image->generic_class_cache, gclass);
+ cached = mono_metadata_lookup_generic_class (gclass);
if (cached) {
g_free (gclass);
mono_loader_unlock ();
gclass->parent = parent;
gclass->context = g_new0 (MonoGenericContext, 1);
+ gclass->context->container = gclass->container;
gclass->context->gclass = gclass;
if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
mono_class_create_generic (gclass);
mono_class_create_generic_2 (gclass);
- g_hash_table_insert (klass->image->generic_class_cache, gclass, gclass);
-
mono_loader_unlock ();
return geninst;
ginst = mono_metadata_lookup_generic_inst (ginst);
gmethod = g_new0 (MonoGenericMethod, 1);
+ gmethod->container = container;
gmethod->inst = ginst;
inflated = g_hash_table_lookup (container->method_hash, gmethod);
gmethod->reflection_info = rmethod;
context = g_new0 (MonoGenericContext, 1);
+ context->container = container;
context->gclass = method->klass->generic_class;
context->gmethod = gmethod;
}
context = g_new0 (MonoGenericContext, 1);
+ context->container = gclass->container;
context->gclass = gclass;
context->gmethod = gmethod;
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * mini.c (mono_method_to_ir): In CEE_CALLVIRT, use the new
+ mono_method_get_signature_full().
+
+2004-12-03 Massimiliano Mantione <massi@ximian.com>
+
+ * mini.c: Added removal of critical edges (prerequisite for SSAPRE),
+ and some utility functions (always for SSAPRE), integrated SSAPRE.
+ * mini.h: Likewise.
+ * driver.c: Added ssapre option.
+ * ssa.c: Small fix on OP_ARG handling.
+ * ssapre.c, ssapre.h: Added files containing SSAPRE implementation.
+ * Makefile.am: Likewise.
+
2004-12-02 Zoltan Varga <vargaz@freemail.hu>
* tramp-x86.c (mono_arch_create_jit_trampoline): Remove code which is
ssa.c \
abcremoval.c \
abcremoval.h \
+ ssapre.c \
+ ssapre.h \
driver.c \
debug-mini.c \
linear-scan.c \
$(sparc_sources) inssel-sparc.brg cpu-sparc.md \
$(s390_sources) inssel-s390.brg cpu-s390.md \
$(s390x_sources) inssel-s390x.brg cpu-s390x.md
-
{"leaf", "Leaf procedures optimizations"},
{"aot", "Usage of Ahead Of Time compiled code"},
{"precomp", "Precompile all methods before executing Main"},
- {"abcrem", "Array bound checks removal"}
+ {"abcrem", "Array bound checks removal"},
+ {"ssapre", "SSA based Partial Redundancy Elimination"}
};
#define DEFAULT_OPTIMIZATIONS ( \
MONO_OPT_LINEARS | \
MONO_OPT_INTRINS | \
MONO_OPT_LOOP | \
- MONO_OPT_AOT)
+ MONO_OPT_AOT)
#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSAPRE,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM | MONO_OPT_SHARED
};
{
mini_cleanup (domain);
}
-
-
return inst;
}
+/*
+ * Transform a MonoInst into a load from the variable of index var_index.
+ */
+void
+mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index) {
+ memset (dest, 0, sizeof (MonoInst));
+ dest->ssa_op = MONO_SSA_LOAD;
+ dest->inst_i0 = cfg->varinfo [var_index];
+ dest->opcode = mono_type_to_ldind (dest->inst_i0->inst_vtype);
+ type_to_eval_stack_type (dest->inst_i0->inst_vtype, dest);
+ dest->klass = dest->inst_i0->klass;
+}
+
+/*
+ * Create a MonoInst that is a load from the variable of index var_index.
+ */
+MonoInst*
+mono_compile_create_var_load (MonoCompile *cfg, gssize var_index) {
+ MonoInst *dest;
+ NEW_TEMPLOAD (cfg,dest,var_index);
+ return dest;
+}
+
+/*
+ * Create a MonoInst that is a store of the given value into the variable of index var_index.
+ */
+MonoInst*
+mono_compile_create_var_store (MonoCompile *cfg, gssize var_index, MonoInst *value) {
+ MonoInst *dest;
+ NEW_TEMPSTORE (cfg, dest, var_index, value);
+ return dest;
+}
+
static MonoType*
type_from_stack_type (MonoInst *ins) {
switch (ins->type) {
return NULL;
}
+MonoType*
+mono_type_from_stack_type (MonoInst *ins) {
+ return type_from_stack_type (ins);
+}
+
static MonoClass*
array_access_to_klass (int opcode)
{
return NULL;
}
-static void
+void
mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst)
{
MonoInst *prev;
if (method->signature->is_inflated)
generic_context = ((MonoMethodInflated *) method)->context;
else if (generic_container)
- generic_context = generic_container->context;
+ generic_context = &generic_container->context;
g_assert (!method->signature->has_type_parameters);
MonoMethod *wrapper = mono_marshal_get_native_wrapper (cmethod);
fsig = wrapper->signature;
} else {
- fsig = mono_method_get_signature (cmethod, image, token);
+ fsig = mono_method_get_signature_full (cmethod, image, token, generic_context);
}
n = fsig->param_count + fsig->hasthis;
printf ("[%s] <- [%s + 0x%x]", mono_arch_regname (tree->dreg), mono_arch_regname (tree->inst_basereg), tree->inst_offset);
break;
case CEE_BR:
+ case OP_CALL_HANDLER:
printf ("[B%d]", tree->inst_target_bb->block_num);
break;
case CEE_SWITCH:
if (sig->hasthis)
mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG);
- for (i = 0; i < sig->param_count; ++i)
+ for (i = 0; i < sig->param_count; ++i) {
mono_compile_create_var (cfg, sig->params [i], OP_ARG);
+ if (sig->params [i]->byref) {
+ cfg->disable_ssa = TRUE;
+ }
+ }
cfg->locals_start = cfg->num_varinfo;
}
}
+static void
+remove_critical_edges (MonoCompile *cfg) {
+ MonoBasicBlock *bb;
+
+ if (cfg->verbose_level > 3) {
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ int i;
+ printf ("remove_critical_edges %s, BEFORE BB%d (in:", mono_method_full_name (cfg->method, TRUE), bb->block_num);
+ for (i = 0; i < bb->in_count; i++) {
+ printf (" %d", bb->in_bb [i]->block_num);
+ }
+ printf (") (out:");
+ for (i = 0; i < bb->out_count; i++) {
+ printf (" %d", bb->out_bb [i]->block_num);
+ }
+ printf (")");
+ if (bb->last_ins != NULL) {
+ printf (" ");
+ mono_print_tree (bb->last_ins);
+ }
+ printf ("\n");
+ }
+ }
+
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ if (bb->out_count > 1) {
+ int out_bb_index;
+ for (out_bb_index = 0; out_bb_index < bb->out_count; out_bb_index++) {
+ MonoBasicBlock *out_bb = bb->out_bb [out_bb_index];
+ if (out_bb->in_count > 1) {
+ MonoInst *inst;
+ MonoBasicBlock *new_bb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+ new_bb->block_num = cfg->num_bblocks++;
+ new_bb->next_bb = bb->next_bb;
+ bb->next_bb = new_bb;
+ new_bb->in_bb = mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*));
+ new_bb->in_bb [0] = bb;
+ new_bb->in_count = 1;
+ new_bb->out_bb = mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*));
+ new_bb->out_bb [0] = out_bb;
+ new_bb->out_count = 1;
+ replace_out_block (bb, out_bb, new_bb);
+ replace_in_block (out_bb, bb, new_bb);
+ for (inst = bb->code; inst != NULL; inst = inst->next) {
+ if (inst->opcode == OP_CALL_HANDLER) {
+ if (inst->inst_target_bb == out_bb) {
+ inst->inst_target_bb = new_bb;
+ }
+ }
+ }
+ if (bb->last_ins != NULL) {
+ switch (bb->last_ins->opcode) {
+ case CEE_BR:
+ if (bb->last_ins->inst_target_bb == out_bb) {
+ bb->last_ins->inst_target_bb = new_bb;
+ }
+ break;
+ case CEE_SWITCH: {
+ int i;
+ int n = GPOINTER_TO_INT (bb->last_ins->klass);
+ for (i = 0; i < n; i++ ) {
+ if (bb->last_ins->inst_many_bb [i] == out_bb) {
+ bb->last_ins->inst_many_bb [i] = new_bb;
+ break;
+ }
+ }
+ break;
+ }
+ case CEE_BNE_UN:
+ case CEE_BEQ:
+ case CEE_BLT:
+ case CEE_BLT_UN:
+ case CEE_BGT:
+ case CEE_BGT_UN:
+ case CEE_BGE:
+ case CEE_BGE_UN:
+ case CEE_BLE:
+ case CEE_BLE_UN:
+ if (bb->last_ins->inst_true_bb == out_bb) {
+ bb->last_ins->inst_true_bb = new_bb;
+ }
+ if (bb->last_ins->inst_false_bb == out_bb) {
+ bb->last_ins->inst_false_bb = new_bb;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+// new_bb->real_offset = bb->real_offset;
+ new_bb->region = bb->region;
+
+ if (new_bb->next_bb != out_bb) {
+ MonoInst *jump;
+ MONO_INST_NEW (cfg, jump, CEE_BR);
+ MONO_ADD_INS (new_bb, jump);
+ jump->cil_code = bb->cil_code;
+ jump->inst_target_bb = out_bb;
+ }
+
+ if (cfg->verbose_level > 2) {
+ printf ("remove_critical_edges %s, removed critical edge from BB%d to BB%d (added BB%d)\n", mono_method_full_name (cfg->method, TRUE), bb->block_num, out_bb->block_num, new_bb->block_num);
+ }
+ }
+ }
+ }
+ }
+
+ if (cfg->verbose_level > 3) {
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ int i;
+ printf ("remove_critical_edges %s, AFTER BB%d (in:", mono_method_full_name (cfg->method, TRUE), bb->block_num);
+ for (i = 0; i < bb->in_count; i++) {
+ printf (" %d", bb->in_bb [i]->block_num);
+ }
+ printf (") (out:");
+ for (i = 0; i < bb->out_count; i++) {
+ printf (" %d", bb->out_bb [i]->block_num);
+ }
+ printf (")");
+ if (bb->last_ins != NULL) {
+ printf (" ");
+ mono_print_tree (bb->last_ins);
+ }
+ printf ("\n");
+ }
+ }
+}
+
+
MonoCompile*
mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, int parts)
{
}
/*g_print ("numblocks = %d\n", cfg->num_bblocks);*/
- /* Depth-first ordering on basic blocks */
- cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
-
if (cfg->opt & MONO_OPT_BRANCH)
optimize_branches (cfg);
+ if ((cfg->opt & MONO_OPT_SSAPRE) && ! (cfg->opt & (MONO_OPT_CONSPROP|MONO_OPT_COPYPROP))) {
+ remove_critical_edges (cfg);
+ }
+
+ /* Depth-first ordering on basic blocks */
+ cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
+
df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
if (cfg->num_bblocks != dfn + 1) {
MonoBasicBlock *bb;
#else
/* fixme: add all optimizations which requires SSA */
- if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM)) {
+ if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
if (!(cfg->comp_done & MONO_COMP_SSA) && !header->num_clauses && !cfg->disable_ssa) {
mono_local_cprop (cfg);
mono_ssa_compute (cfg);
if (parts == 2)
return cfg;
- if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
+ if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
if (cfg->comp_done & MONO_COMP_SSA) {
mono_ssa_cprop (cfg);
} else {
if ((cfg->flags & MONO_CFG_HAS_LDELEMA) && (cfg->opt & MONO_OPT_ABCREM))
mono_perform_abc_removal (cfg);
-
+
+ if ((cfg->opt & MONO_OPT_SSAPRE) && ! (cfg->opt & (MONO_OPT_CONSPROP|MONO_OPT_COPYPROP)))
+ mono_perform_ssapre (cfg);
+
mono_ssa_remove (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
MONO_OPT_LEAF = 1 << 15,
MONO_OPT_AOT = 1 << 16,
MONO_OPT_PRECOMP = 1 << 17,
- MONO_OPT_ABCREM = 1 << 18
+ MONO_OPT_ABCREM = 1 << 18,
+ MONO_OPT_SSAPRE = 1 << 19
};
/* Bit-fields in the MonoBasicBlock.region */
int mono_is_power_of_two (guint32 val);
void mono_cprop_local (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **acp, int acp_size);
MonoInst* mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode);
+void mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index);
+MonoInst* mono_compile_create_var_load (MonoCompile *cfg, gssize var_index);
+MonoInst* mono_compile_create_var_store (MonoCompile *cfg, gssize var_index, MonoInst *value);
+MonoType* mono_type_from_stack_type (MonoInst *ins);
void mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom);
void mono_print_tree (MonoInst *tree);
void mono_print_tree_nl (MonoInst *tree);
void mono_arch_register_lowlevel_calls (void);
void mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options);
void mono_add_varcopy_to_end (MonoCompile *cfg, MonoBasicBlock *bb, int src, int dest);
+void mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst);
int mono_find_method_opcode (MonoMethod *method);
MonoJitICallInfo *mono_find_jit_icall_by_name (const char *name);
extern void
mono_perform_abc_removal (MonoCompile *cfg);
+extern void
+mono_perform_ssapre (MonoCompile *cfg);
-#endif /* __MONO_MINI_H__ */
+#endif /* __MONO_MINI_H__ */
arity = mono_burg_arity [inst->opcode];
if (inst->ssa_op == MONO_SSA_LOAD &&
- (inst->inst_i0->opcode == OP_LOCAL /*|| inst->inst_i0->opcode == OP_ARG*/)) {
+ (inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
return 1;
} else {
if (arity) {
--- /dev/null
+/*
+ * ssapre.h: SSA Partial Redundancy Elimination
+ *
+ * Author:
+ * Massimiliano Mantione (massi@ximian.com)
+ *
+ * (C) 2004 Novell, Inc. http://www.novell.com
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/opcodes.h>
+
+#include "inssel.h"
+
+#include "ssapre.h"
+
+extern guint8 mono_burg_arity [];
+
+/* Logging conditions */
+#define DUMP_LEVEL (4)
+#define TRACE_LEVEL (3)
+#define STATISTICS_LEVEL (2)
+#define LOG_LEVEL (1)
+#define DUMP_SSAPRE (area->cfg->verbose_level >= DUMP_LEVEL)
+#define TRACE_SSAPRE (area->cfg->verbose_level >= TRACE_LEVEL)
+#define STATISTICS_SSAPRE (area->cfg->verbose_level >= STATISTICS_LEVEL)
+#define LOG_SSAPRE (area->cfg->verbose_level >= LOG_LEVEL)
+
+/* "Bottom" symbol definition (see paper) */
+#define BOTTOM_REDUNDANCY_CLASS (-1)
+
+/* Various printing functions... */
+static void
+print_argument (MonoSsapreExpressionArgument *argument) {
+ switch (argument->type) {
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY:
+ printf ("ANY");
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT:
+ printf ("NONE");
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE:
+ printf ("ORIGINAL_VARIABLE %d", argument->argument.original_variable);
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE:
+ printf ("SSA_VARIABLE %d", argument->argument.ssa_variable);
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT:
+ printf ("INTEGER_CONSTANT %d", argument->argument.integer_constant);
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT:
+ printf ("LONG_COSTANT %lld", *(argument->argument.long_constant));
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT:
+ printf ("FLOAT_COSTANT %f", *(argument->argument.float_constant));
+ break;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT:
+ printf ("DOUBLE_COSTANT %f", *(argument->argument.double_constant));
+ break;
+ default:
+ printf ("UNKNOWN: %d", argument->type);
+ }
+}
+
+
+static void
+print_expression_description (MonoSsapreExpressionDescription *expression_description) {
+ if (expression_description->opcode != 0) {
+ printf ("%s ([", mono_inst_name (expression_description->opcode) );
+ print_argument (&(expression_description->left_argument));
+ printf ("],[");
+ print_argument (&(expression_description->right_argument));
+ printf ("])");
+ } else {
+ printf ("ANY");
+ }
+}
+
+#define GBOOLEAN_TO_STRING(b) ((b)?"TRUE":"FALSE")
+
+static void
+print_expression_occurrence (MonoSsapreExpressionOccurrence *occurrence, int number) {
+ printf (" ([%d][bb %d [ID %d]][class %d]: ", number, occurrence->bb_info->cfg_dfn, occurrence->bb_info->bb->block_num, occurrence->redundancy_class);
+ print_expression_description (&(occurrence->description));
+ if (occurrence->is_first_in_bb) {
+ printf (" [FIRST in BB]");
+ }
+ if (occurrence->is_last_in_bb) {
+ printf (" [LAST in BB]");
+ }
+ printf (" (save = %s)", GBOOLEAN_TO_STRING (occurrence->save));
+ printf (" (reload = %s)", GBOOLEAN_TO_STRING (occurrence->reload));
+ printf ("\n");
+ occurrence = occurrence->next;
+}
+
+static void
+print_expression_occurrences (MonoSsapreExpressionOccurrence *occurrences) {
+ int i = 0;
+ while (occurrences != NULL) {
+ i++;
+ print_expression_occurrence (occurrences, i);
+ occurrences = occurrences->next;
+ }
+}
+
+static void
+print_worklist (MonoSsapreExpression *expression) {
+ if (expression != NULL) {
+ print_worklist (expression->previous);
+
+ printf ("{%d}: ", expression->tree_size);
+ print_expression_description (&(expression->description));
+ printf ("\n");
+ print_expression_occurrences (expression->occurrences);
+
+ print_worklist (expression->next);
+ }
+}
+
+static void
+print_bb_info (MonoSsapreBBInfo *bb_info, gboolean print_occurrences) {
+ int i;
+ MonoSsapreExpressionOccurrence *current_occurrence = bb_info->first_expression_in_bb;
+
+ printf ("bb %d [ID %d]: IN { ", bb_info->cfg_dfn, bb_info->bb->block_num);
+ for (i = 0; i < bb_info->in_count; i++) {
+ printf ("%d [ID %d] ", bb_info->in_bb [i]->cfg_dfn, bb_info->in_bb [i]->bb->block_num);
+ }
+ printf ("}, OUT {");
+ for (i = 0; i < bb_info->out_count; i++) {
+ printf ("%d [ID %d] ", bb_info->out_bb [i]->cfg_dfn, bb_info->out_bb [i]->bb->block_num);
+ }
+ printf ("}");
+ if (bb_info->next_interesting_bb != NULL) {
+ printf (", NEXT %d [ID %d]", bb_info->next_interesting_bb->cfg_dfn, bb_info->next_interesting_bb->bb->block_num);
+ }
+ printf ("\n");
+ if (bb_info->has_phi) {
+ printf (" PHI, class %d [ ", bb_info->phi_redundancy_class);
+ for (i = 0; i < bb_info->in_count; i++) {
+ int argument_class = bb_info->phi_arguments_classes [i];
+ if (argument_class != BOTTOM_REDUNDANCY_CLASS) {
+ printf ("%d ", argument_class);
+ } else {
+ printf ("BOTTOM ");
+ }
+ }
+ printf ("]\n(phi_defines_a_real_occurrence:%s) (phi_is_down_safe:%s) (phi_can_be_available:%s) (phi_is_later:%s)\n",
+ GBOOLEAN_TO_STRING (bb_info->phi_defines_a_real_occurrence), GBOOLEAN_TO_STRING (bb_info->phi_is_down_safe),
+ GBOOLEAN_TO_STRING (bb_info->phi_can_be_available), GBOOLEAN_TO_STRING (bb_info->phi_is_later));
+ }
+ if (print_occurrences) {
+ i = 0;
+ while ((current_occurrence != NULL) && (current_occurrence->bb_info == bb_info)) {
+ print_expression_occurrence (current_occurrence, i);
+ current_occurrence = current_occurrence->next;
+ i++;
+ }
+ }
+ if (bb_info->has_phi_argument) {
+ printf (" PHI ARGUMENT, class ");
+ if (bb_info->phi_argument_class != BOTTOM_REDUNDANCY_CLASS) {
+ printf ("%d ", bb_info->phi_argument_class);
+ } else {
+ printf ("BOTTOM ");
+ }
+ if (bb_info->phi_argument_defined_by_real_occurrence != NULL) {
+ printf ("(Defined by real occurrence %d)", bb_info->phi_argument_defined_by_real_occurrence->redundancy_class);
+ } else if (bb_info->phi_argument_defined_by_phi != NULL) {
+ printf ("(Defined by phi %d)", bb_info->phi_argument_defined_by_phi->phi_redundancy_class);
+ } else {
+ printf ("(Undefined)");
+ }
+ printf (" (real occurrence arguments: left ");
+ if (bb_info->phi_argument_left_argument_version != BOTTOM_REDUNDANCY_CLASS) {
+ printf ("%d ", bb_info->phi_argument_left_argument_version);
+ } else {
+ printf ("NONE ");
+ }
+ printf (", right ");
+ if (bb_info->phi_argument_right_argument_version != BOTTOM_REDUNDANCY_CLASS) {
+ printf ("%d ", bb_info->phi_argument_right_argument_version);
+ } else {
+ printf ("NONE ");
+ }
+ printf (")\n(phi_argument_has_real_use:%s) (phi_argument_needs_insert:%s) (phi_argument_has_been_processed:%s)\n",
+ GBOOLEAN_TO_STRING (bb_info->phi_argument_has_real_use), GBOOLEAN_TO_STRING (bb_info->phi_argument_needs_insert),
+ GBOOLEAN_TO_STRING (bb_info->phi_argument_has_been_processed));
+ }
+}
+
+static void
+print_bb_infos (MonoSsapreWorkArea *area) {
+ int i;
+ for (i = 0; i < area->num_bblocks; i++) {
+ MonoSsapreBBInfo *bb_info = &(area->bb_infos [i]);
+ print_bb_info (bb_info, TRUE);
+ }
+}
+
+static void
+print_interesting_bb_infos (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ print_bb_info (current_bb, FALSE);
+ }
+}
+
+static void dump_code (MonoSsapreWorkArea *area) {
+ int i;
+
+ for (i = 0; i < area->num_bblocks; i++) {
+ MonoSsapreBBInfo *current_bb = &(area->bb_infos [i]);
+ MonoInst *current_inst;
+
+ print_bb_info (current_bb, TRUE);
+ for (current_inst = current_bb->bb->code; current_inst != NULL; current_inst = current_inst->next) {
+ mono_print_tree_nl (current_inst);
+ }
+ }
+}
+
+/*
+ * Given a MonoInst, it tries to describe it as an expression argument.
+ * If this is not possible, the result will be of type
+ * MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY.
+ */
+static void
+analyze_argument (MonoInst *argument, MonoSsapreExpressionArgument *result) {
+ switch (argument->opcode) {
+ case CEE_LDIND_I1:
+ case CEE_LDIND_U1:
+ case CEE_LDIND_I2:
+ case CEE_LDIND_U2:
+ case CEE_LDIND_I4:
+ case CEE_LDIND_U4:
+ case CEE_LDIND_I8:
+ case CEE_LDIND_I:
+ case CEE_LDIND_R4:
+ case CEE_LDIND_R8:
+ case CEE_LDIND_REF:
+ analyze_argument (argument->inst_left, result);
+ break;
+ case OP_ICONST:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT;
+ result->argument.integer_constant = argument->inst_c0;
+ break;
+ case OP_I8CONST:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT;
+ result->argument.long_constant = &(argument->inst_l);
+ break;
+ case OP_R4CONST:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT;
+ result->argument.float_constant = (float*)argument->inst_p0;
+ break;
+ case OP_R8CONST:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT;
+ result->argument.double_constant = (double*)argument->inst_p0;
+ break;
+ case OP_ARG:
+ case OP_LOCAL:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE;
+ result->argument.ssa_variable = argument->inst_c0;
+ break;
+ default:
+ result->type = MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY;
+ }
+}
+
+/*
+ * Given a MonoInst, it tries to describe it as an expression.
+ * If this is not possible, the result will have opcode 0.
+ */
+static void
+analyze_expression (MonoInst *expression, MonoSsapreExpressionDescription *result) {
+ switch (expression->opcode) {
+ case CEE_LDIND_I1:
+ case CEE_LDIND_U1:
+ case CEE_LDIND_I2:
+ case CEE_LDIND_U2:
+ case CEE_LDIND_I4:
+ case CEE_LDIND_U4:
+ case CEE_LDIND_I8:
+ case CEE_LDIND_I:
+ case CEE_LDIND_R4:
+ case CEE_LDIND_R8:
+ case CEE_LDIND_REF:
+ analyze_expression (expression->inst_left, result);
+ break;
+ case CEE_SWITCH:
+ case CEE_ISINST:
+ case CEE_CASTCLASS:
+ case OP_OUTARG:
+ case OP_CALL_REG:
+ case OP_FCALL_REG:
+ case OP_LCALL_REG:
+ case OP_VCALL_REG:
+ case OP_VOIDCALL_REG:
+ case CEE_CALL:
+ case CEE_CALLVIRT:
+ case OP_FCALL:
+ case OP_FCALLVIRT:
+ case OP_LCALL:
+ case OP_LCALLVIRT:
+ case OP_VCALL:
+ case OP_VCALLVIRT:
+ case OP_VOIDCALL:
+ case OP_VOIDCALLVIRT:
+ case OP_RENAME:
+ case OP_RETARG:
+// case OP_OUTARG:
+ case OP_OUTARG_REG:
+ case OP_OUTARG_IMM:
+ case OP_OUTARG_R4:
+ case OP_OUTARG_R8:
+ case OP_OUTARG_VT:
+ case CEE_NOP:
+ case CEE_JMP:
+ case CEE_BREAK:
+ case OP_COMPARE:
+ case OP_COMPARE_IMM:
+ case OP_FCOMPARE:
+ case OP_LCOMPARE:
+ case OP_ICOMPARE:
+ case OP_ICOMPARE_IMM:
+ result->opcode = 0;
+ break;
+ default:
+ if ( (expression->type == STACK_I4) ||
+ (expression->type == STACK_I8) ||
+ (expression->type == STACK_R8) ) {
+ if (mono_burg_arity [expression->opcode] > 0) {
+ analyze_argument (expression->inst_left, &(result->left_argument));
+ if (result->left_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY) {
+ if (mono_burg_arity [expression->opcode] > 1) {
+ analyze_argument (expression->inst_right, &(result->right_argument));
+ if (result->right_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY) {
+ result->opcode = expression->opcode;
+ } else {
+ result->opcode = 0;
+ }
+ } else {
+ result->right_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT;
+ result->opcode = expression->opcode;
+ }
+ } else {
+ result->opcode = 0;
+ }
+ } else {
+ result->opcode = 0;
+ }
+ } else {
+ result->opcode = 0;
+ }
+ }
+}
+
+/*
+ * Given an expression description, if any of its arguments has type
+ * MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE it transforms it to a
+ * MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE, converting the
+ * variable index to its "original" one.
+ * The resulting description is OK for a "MonoSsapreExpression" (the
+ * initial description came from a "MonoSsapreExpressionOccurrence").
+ */
+static void
+convert_ssa_variables_to_original_names (MonoSsapreExpressionDescription *result, MonoSsapreExpressionDescription *expression, MonoCompile *cfg) {
+ gssize original_variable;
+
+ result->opcode = expression->opcode;
+ if (expression->left_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) {
+ result->left_argument = expression->left_argument;
+ } else {
+ result->left_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE;
+ original_variable = cfg->vars [expression->left_argument.argument.ssa_variable]->reg;
+ if (original_variable >= 0) {
+ result->left_argument.argument.original_variable = original_variable;
+ } else {
+ result->left_argument.argument.original_variable = expression->left_argument.argument.ssa_variable;
+ }
+ }
+ if (expression->right_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) {
+ result->right_argument = expression->right_argument;
+ } else {
+ result->right_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE;
+ original_variable = cfg->vars [expression->right_argument.argument.ssa_variable]->reg;
+ if (original_variable >= 0) {
+ result->right_argument.argument.original_variable = original_variable;
+ } else {
+ result->right_argument.argument.original_variable = expression->right_argument.argument.ssa_variable;
+ }
+ }
+}
+
+/*
+ * Given a MonoInst, checks if it is a phi definition.
+ */
+static gboolean
+is_phi_definition (MonoInst *definition) {
+ if (definition != NULL) {
+ switch (definition->opcode) {
+ case CEE_STIND_REF:
+ case CEE_STIND_I:
+ case CEE_STIND_I4:
+ case CEE_STIND_I1:
+ case CEE_STIND_I2:
+ case CEE_STIND_I8:
+ case CEE_STIND_R4:
+ case CEE_STIND_R8:
+ if ((definition->inst_left->opcode == OP_LOCAL) &&
+ (definition->inst_right->opcode == OP_PHI)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ default:
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ * Given a variable index, checks if it is a phi definition
+ * (it assumes the "area" is visible).
+ */
+#define IS_PHI_DEFINITION(v) is_phi_definition (area->cfg->vars [v]->def)
+
+/*
+ * Given a variable index, checks if it is a phi definition.
+ * If it is so, it returns the array of integers pointed to by the phi MonoInst
+ * (the one containing the length and the phi arguments), otherwise returns NULL.
+ */
+static int*
+get_phi_definition (MonoCompile *cfg, gssize variable) {
+ MonoInst *definition = cfg->vars [variable]->def;
+ if (is_phi_definition (definition) && (definition->inst_left->inst_c0 == variable)) {
+ return definition->inst_right->inst_phi_args;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Given a variable index, returns the BB where the variable is defined.
+ * If the variable appears to have no definition, it returns the entry BB
+ * (the logic is that if it has no definition it is an argument, or a sort
+ * of constant, and in both cases it is defined in the entry BB).
+ */
+static MonoSsapreBBInfo*
+get_bb_info_of_definition (MonoSsapreWorkArea *area, gssize variable) {
+ MonoBasicBlock *def_bb = area->cfg->vars [variable]->def_bb;
+ if (def_bb != NULL) {
+ return area->bb_infos_in_cfg_dfn_order [def_bb->dfn];
+ } else {
+ return area->bb_infos;
+ }
+}
+
+/*
+ * Given:
+ * - a variable index,
+ * - a BB (the "current" BB), and
+ * - a "phi argument index" (or index in the "in_bb" of the current BB),
+ * it checks if the variable is a phi.
+ * If it is so, it returns the variable index at the in_bb corresponding to
+ * the given index, otherwise it return the variable index unchanged.
+ * The logic is to return the variable version at the given predecessor BB.
+ */
+static gssize
+get_variable_version_at_predecessor_bb (MonoSsapreWorkArea *area, gssize variable, MonoSsapreBBInfo *current_bb, int phi_operand) {
+ MonoSsapreBBInfo *definition_bb = get_bb_info_of_definition (area, variable);
+ int *phi_definition = get_phi_definition (area->cfg, variable);
+ if ((definition_bb == current_bb) && (phi_definition != NULL)) {
+ return phi_definition [phi_operand + 1];
+ } else {
+ return variable;
+ }
+}
+
+/*
+ * Adds an expression to an autobalancing binary tree of expressions.
+ * Returns the new tree root (it can be different from "tree" because of the
+ * autobalancing).
+ */
+static MonoSsapreExpression*
+add_expression_to_tree (MonoSsapreExpression *tree, MonoSsapreExpression *expression) {
+ MonoSsapreExpression *subtree;
+ MonoSsapreExpression **subtree_reference;
+ int comparison;
+ gssize max_tree_depth, max_subtree_size;
+
+ if (tree == NULL) {
+ expression->previous = NULL;
+ expression->next = NULL;
+ expression->tree_size = 1;
+ return expression;
+ }
+
+ tree->tree_size++;
+
+ comparison = MONO_COMPARE_SSAPRE_EXPRESSION_DESCRIPTIONS (expression->description, tree->description);
+ if (comparison > 0) {
+ if (tree->next != NULL) {
+ subtree = tree->next;
+ subtree_reference = &(tree->next);
+ } else {
+ tree->next = expression;
+ expression->father = tree;
+ expression->previous = NULL;
+ expression->next = NULL;
+ expression->tree_size = 1;
+ return tree;
+ }
+ } else if (comparison < 0) {
+ if (tree->previous != NULL) {
+ subtree = tree->previous;
+ subtree_reference = &(tree->previous);
+ } else {
+ tree->previous = expression;
+ expression->father = tree;
+ expression->previous = NULL;
+ expression->next = NULL;
+ expression->tree_size = 1;
+ return tree;
+ }
+ } else {
+ g_assert_not_reached ();
+ return NULL;
+ }
+
+ MONO_SSAPRE_MAX_TREE_DEPTH (tree->tree_size, max_tree_depth);
+ max_subtree_size = (1 << max_tree_depth) -1;
+
+ if (subtree->tree_size < max_subtree_size) {
+ *subtree_reference = add_expression_to_tree (subtree, expression);
+ (*subtree_reference)->father = tree;
+ return tree;
+ } else {
+ MonoSsapreExpression *other_subtree;
+ MonoSsapreExpression *border_expression;
+ MonoSsapreExpression *border_expression_subtree;
+ MonoSsapreExpression **border_expression_reference_from_father;
+ int comparison_with_border;
+
+ border_expression = subtree;
+ if (comparison > 0) {
+ other_subtree = tree->previous;
+ MONO_SSAPRE_GOTO_FIRST_EXPRESSION (border_expression);
+ border_expression_subtree = border_expression->next;
+ border_expression_reference_from_father = &(border_expression->father->previous);
+ } else if (comparison < 0) {
+ other_subtree = tree->next;
+ MONO_SSAPRE_GOTO_LAST_EXPRESSION (border_expression);
+ border_expression_subtree = border_expression->previous;
+ border_expression_reference_from_father = &(border_expression->father->next);
+ } else {
+ g_assert_not_reached ();
+ return NULL;
+ }
+ comparison_with_border = MONO_COMPARE_SSAPRE_EXPRESSION_DESCRIPTIONS (expression->description, border_expression->description);
+
+ if ((comparison + comparison_with_border) != 0) {
+ MonoSsapreExpression *border_expression_iterator = border_expression->father;
+ while (border_expression_iterator != tree) {
+ border_expression_iterator->tree_size--;
+ border_expression_iterator = border_expression_iterator->father;
+ }
+
+ if (border_expression != subtree) {
+ *border_expression_reference_from_father = border_expression_subtree;
+ } else {
+ subtree = border_expression_subtree;
+ }
+ if (border_expression_subtree != NULL) {
+ border_expression_subtree->father = border_expression->father;
+ }
+
+ if (comparison > 0) {
+ border_expression->previous = add_expression_to_tree (other_subtree, tree);
+ border_expression->next = add_expression_to_tree (subtree, expression);
+ } else if (comparison < 0) {
+ border_expression->previous = add_expression_to_tree (subtree, expression);
+ border_expression->next = add_expression_to_tree (other_subtree, tree);
+ } else {
+ g_assert_not_reached ();
+ return NULL;
+ }
+ border_expression->tree_size = 1 + border_expression->previous->tree_size + border_expression->next->tree_size;
+ return border_expression;
+ } else {
+ if (comparison > 0) {
+ expression->previous = add_expression_to_tree (other_subtree, tree);
+ expression->next = subtree;
+ } else if (comparison < 0) {
+ expression->previous = subtree;
+ expression->next = add_expression_to_tree (other_subtree, tree);
+ } else {
+ g_assert_not_reached ();
+ return NULL;
+ }
+ expression->tree_size = 1 + expression->previous->tree_size + expression->next->tree_size;
+ return expression;
+ }
+ }
+}
+
+/*
+ * Adds an expression to the worklist (putting the given occurrence as first
+ * occurrence of this expression).
+ */
+static void
+add_expression_to_worklist (MonoSsapreWorkArea *area, MonoSsapreExpressionOccurrence *occurrence) {
+ MonoSsapreExpression *expression;
+
+ expression = (MonoSsapreExpression*) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreExpression));
+
+ convert_ssa_variables_to_original_names (&(expression->description), &(occurrence->description), area->cfg);
+ expression->type = mono_type_from_stack_type (occurrence->occurrence);
+ expression->occurrences = NULL;
+ expression->last_occurrence = NULL;
+ MONO_SSAPRE_ADD_EXPRESSION_OCCURRANCE (expression, occurrence);
+
+ area->worklist = add_expression_to_tree (area->worklist, expression);
+ area->worklist->father = NULL;
+}
+
+/*
+ * Adds an expression occurrence to the worklist.
+ * If its expression is not yet in the worklist, it is created.
+ */
+static void
+add_occurrence_to_worklist (MonoSsapreWorkArea *area, MonoSsapreExpressionOccurrence *occurrence) {
+ MonoSsapreExpressionDescription description;
+ MonoSsapreExpression *current_expression;
+ int comparison;
+
+ convert_ssa_variables_to_original_names (&description, &(occurrence->description), area->cfg);
+ current_expression = area->worklist;
+
+ do {
+ if (current_expression != NULL) {
+ comparison = MONO_COMPARE_SSAPRE_EXPRESSION_DESCRIPTIONS (description, current_expression->description);
+
+ if (comparison > 0) {
+ current_expression = current_expression->next;
+ } else if (comparison < 0) {
+ current_expression = current_expression->previous;
+ } else {
+ MONO_SSAPRE_ADD_EXPRESSION_OCCURRANCE (current_expression, occurrence);
+ }
+ } else {
+ add_expression_to_worklist (area, occurrence);
+ comparison = 0;
+ }
+ } while (comparison != 0);
+}
+
+/*
+ * Process a MonoInst, and of it is a valid expression add it to the worklist.
+ */
+static MonoSsapreExpressionOccurrence*
+process_inst (MonoSsapreWorkArea *area, MonoInst* inst, MonoInst* previous_inst, MonoSsapreBBInfo *bb_info, MonoSsapreExpressionOccurrence *current_occurrence) {
+
+ /* Ugly hack to fix missing variable definitions */
+ /* (the SSA construction code should have done it already!) */
+ switch (inst->opcode) {
+ case CEE_STIND_REF:
+ case CEE_STIND_I:
+ case CEE_STIND_I4:
+ case CEE_STIND_I1:
+ case CEE_STIND_I2:
+ case CEE_STIND_I8:
+ case CEE_STIND_R4:
+ case CEE_STIND_R8:
+ if ((inst->inst_left->opcode == OP_LOCAL) || (inst->inst_left->opcode == OP_ARG)) {
+ int variable_index = inst->inst_left->inst_c0;
+
+ if (area->cfg->vars [variable_index]->def_bb == NULL) {
+ if (area->cfg->verbose_level >= 4) {
+ printf ("SSAPRE WARNING: variable %d has no definition, fixing.\n", variable_index);
+ }
+ area->cfg->vars [variable_index]->def_bb = bb_info->bb;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (mono_burg_arity [inst->opcode] > 0) {
+ current_occurrence = process_inst (area, inst->inst_left, previous_inst, bb_info, current_occurrence);
+ if (mono_burg_arity [inst->opcode] > 1) {
+ current_occurrence = process_inst (area, inst->inst_right, previous_inst, bb_info, current_occurrence);
+ }
+ }
+
+ analyze_expression (inst, &(current_occurrence->description));
+ if (current_occurrence->description.opcode != 0) {
+ current_occurrence->occurrence = inst;
+ current_occurrence->previous_tree = previous_inst;
+ current_occurrence->bb_info = bb_info;
+ current_occurrence->is_first_in_bb = FALSE;
+ current_occurrence->is_last_in_bb = FALSE;
+ add_occurrence_to_worklist (area, current_occurrence);
+ current_occurrence = (MonoSsapreExpressionOccurrence*) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreExpressionOccurrence));
+ }
+
+ return current_occurrence;
+}
+
+/*
+ * Process a BB, and (recursively) all its children in the dominator tree.
+ * The result is that all the expressions end up in the worklist, and the
+ * auxiliary MonoSsapreBBInfo fields (dt_dfn, dt_descendants) are initialized
+ * (with all the info that comes from the MonoBasicBlock).
+ */
+static MonoSsapreExpressionOccurrence*
+process_bb (MonoSsapreWorkArea *area, MonoBasicBlock *bb, int *dt_dfn, int *upper_descendants, MonoSsapreExpressionOccurrence *current_occurrence) {
+ MonoSsapreBBInfo *bb_info;
+ int descendants;
+ GList *dominated_bb;
+ MonoInst* current_inst;
+ MonoInst* previous_inst;
+
+ bb_info = &(area->bb_infos [*dt_dfn]);
+ bb_info->dt_dfn = *dt_dfn;
+ (*dt_dfn)++;
+ bb_info->cfg_dfn = bb->dfn;
+ area->bb_infos_in_cfg_dfn_order [bb->dfn] = bb_info;
+ bb_info->in_count = bb->in_count;
+ bb_info->out_count = bb->out_count;
+ bb_info->dfrontier = bb->dfrontier;
+ bb_info->bb = bb;
+ bb_info->in_bb = (MonoSsapreBBInfo**) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreBBInfo*) * (bb->in_count));
+ bb_info->out_bb = (MonoSsapreBBInfo**) mono_mempool_alloc (area->mempool, sizeof (MonoSsapreBBInfo*) * (bb->out_count));
+ bb_info->phi_arguments_classes = (gssize*) mono_mempool_alloc (area->mempool, sizeof (gssize) * (bb->in_count));
+
+ bb_info->phi_insertion_point = NULL;
+
+ current_inst = bb->code;
+ previous_inst = NULL;
+ while (current_inst != NULL) {
+ if (is_phi_definition (current_inst)) {
+ bb_info->phi_insertion_point = current_inst;
+ }
+ current_occurrence = process_inst (area, current_inst, previous_inst, bb_info, current_occurrence);
+ previous_inst = current_inst;
+ current_inst = current_inst->next;
+ }
+
+ descendants = 0;
+ for (dominated_bb = g_list_first (bb->dominated); dominated_bb != NULL; dominated_bb = g_list_next (dominated_bb)) {
+ current_occurrence = process_bb (area, (MonoBasicBlock*) (dominated_bb->data), dt_dfn, &descendants, current_occurrence);
+ }
+ bb_info->dt_descendants = descendants;
+ *upper_descendants += (descendants + 1);
+
+ return current_occurrence;
+}
+
+/*
+ * Reset the MonoSsapreBBInfo fields that must be recomputed for each expression.
+ */
+static void
+clean_bb_infos (MonoSsapreWorkArea *area) {
+ int i;
+ for (i = 0; i < area->num_bblocks; i++) {
+ MonoSsapreBBInfo *bb_info = &(area->bb_infos [i]);
+ bb_info->has_phi = FALSE;
+ bb_info->phi_defines_a_real_occurrence = FALSE;
+ bb_info->phi_is_down_safe = FALSE;
+ bb_info->phi_can_be_available = FALSE;
+ bb_info->phi_is_later = FALSE;
+ bb_info->phi_redundancy_class = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->phi_variable_index = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->has_phi_argument = FALSE;
+ bb_info->phi_argument_has_real_use = FALSE;
+ bb_info->phi_argument_needs_insert = FALSE;
+ bb_info->phi_argument_has_been_processed = FALSE;
+ bb_info->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->phi_argument_variable_index = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->phi_argument_defined_by_real_occurrence = NULL;
+ bb_info->phi_argument_defined_by_phi = NULL;
+ bb_info->phi_argument_left_argument_version = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->phi_argument_right_argument_version = BOTTOM_REDUNDANCY_CLASS;
+ bb_info->first_expression_in_bb = NULL;
+ bb_info->next_interesting_bb = NULL;
+ bb_info->next_in_renaming_stack = NULL;
+ bb_info->top_of_local_renaming_stack = NULL;
+ }
+}
+
+/*
+ * Reset the MonoSsapreWorkArea fields that must be recomputed for each expression.
+ */
+static void
+clean_area_infos (MonoSsapreWorkArea *area) {
+ mono_bitset_clear_all (area->left_argument_bb_bitset);
+ mono_bitset_clear_all (area->right_argument_bb_bitset);
+ area->num_vars = area->cfg->num_varinfo;
+ area->top_of_renaming_stack = NULL;
+ area->bb_on_top_of_renaming_stack = NULL;
+ area->first_interesting_bb = NULL;
+ area->saved_occurrences = 0;
+ area->reloaded_occurrences = 0;
+ area->inserted_occurrences = 0;
+ area->unaltered_occurrences = 0;
+ area->added_phis = 0;
+ clean_bb_infos (area);
+}
+
+/*
+ * Utility function to combine the dominance frontiers of a set of BBs.
+ */
+static void
+compute_combined_dfrontier (MonoSsapreWorkArea *area, MonoBitSet* result, MonoBitSet *bblocks)
+{
+ int i;
+ mono_bitset_clear_all (result);
+ mono_bitset_foreach_bit (bblocks, i, area->num_bblocks) {
+ mono_bitset_union (result, area->bb_infos_in_cfg_dfn_order [i]->dfrontier);
+ }
+}
+
+/*
+ * Utility function to compute the combined dominance frontier of a set of BBs.
+ */
+static void
+compute_combined_iterated_dfrontier (MonoSsapreWorkArea *area, MonoBitSet *result, MonoBitSet *bblocks, MonoBitSet *buffer)
+{
+ gboolean change = TRUE;
+
+ compute_combined_dfrontier (area, result, bblocks);
+ do {
+ change = FALSE;
+ compute_combined_dfrontier (area, buffer, result);
+ mono_bitset_union (buffer, result);
+
+ if (!mono_bitset_equal (buffer, result)) {
+ mono_bitset_copyto (buffer, result);
+ change = TRUE;
+ }
+ } while (change);
+}
+
+/*
+ * See paper, figure 18, function Set_var_phis
+ */
+static void process_phi_variable_in_phi_insertion (MonoSsapreWorkArea *area, gssize variable, MonoBitSet *phi_bbs) {
+ int* phi_definition = get_phi_definition (area->cfg, variable);
+
+ if (phi_definition != NULL) {
+ int definition_bb = area->cfg->vars [variable]->def_bb->dfn;
+ if (! mono_bitset_test (phi_bbs, definition_bb)) {
+ int i;
+ mono_bitset_set (phi_bbs, definition_bb);
+ for (i = 0; i < *phi_definition; i++) {
+ process_phi_variable_in_phi_insertion (area, phi_definition [i+1], phi_bbs);
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 18, function phi_insertion
+ */
+static void
+phi_insertion (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
+ MonoSsapreExpressionOccurrence *current_expression = NULL;
+ MonoSsapreExpressionOccurrence *previous_expression = NULL;
+ MonoSsapreBBInfo *current_bb = NULL;
+ MonoSsapreBBInfo *previous_interesting_bb = NULL;
+ int i, j, current_bb_dt_dfn;
+
+ mono_bitset_clear_all (area->expression_occurrences_buffer);
+ for (current_expression = expression->occurrences; current_expression != NULL; current_expression = current_expression->next) {
+ mono_bitset_set (area->expression_occurrences_buffer, current_expression->bb_info->cfg_dfn);
+ if (current_expression->description.left_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) {
+ process_phi_variable_in_phi_insertion (area, current_expression->description.left_argument.argument.ssa_variable, area->left_argument_bb_bitset);
+ }
+ if (current_expression->description.right_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) {
+ process_phi_variable_in_phi_insertion (area, current_expression->description.right_argument.argument.ssa_variable, area->right_argument_bb_bitset);
+ }
+
+ if (previous_expression != NULL) {
+ if (previous_expression->bb_info != current_expression->bb_info) {
+ previous_expression->is_last_in_bb = TRUE;
+ current_expression->is_first_in_bb = TRUE;
+ current_expression->bb_info->first_expression_in_bb = current_expression;
+ }
+ } else {
+ current_expression->is_first_in_bb = TRUE;
+ current_expression->bb_info->first_expression_in_bb = current_expression;
+ }
+
+ previous_expression = current_expression;
+ }
+ previous_expression->is_last_in_bb = TRUE;
+
+ compute_combined_iterated_dfrontier (area, area->iterated_dfrontier_buffer, area->expression_occurrences_buffer, area->bb_iteration_buffer);
+
+ mono_bitset_union (area->iterated_dfrontier_buffer, area->left_argument_bb_bitset);
+ mono_bitset_union (area->iterated_dfrontier_buffer, area->right_argument_bb_bitset);
+
+ mono_bitset_foreach_bit (area->iterated_dfrontier_buffer, i, area->num_bblocks) {
+ area->bb_infos_in_cfg_dfn_order [i]->has_phi = TRUE;
+ area->bb_infos_in_cfg_dfn_order [i]->phi_can_be_available = TRUE;
+ for (j = 0; j < area->bb_infos_in_cfg_dfn_order [i]->in_count; j++) {
+ area->bb_infos_in_cfg_dfn_order [i]->in_bb [j]->has_phi_argument = TRUE;
+ }
+ }
+
+ for (current_bb = area->bb_infos, current_bb_dt_dfn = 0; current_bb_dt_dfn < area->num_bblocks; current_bb++, current_bb_dt_dfn++) {
+ if ((current_bb->first_expression_in_bb != NULL) || (current_bb->has_phi) || (current_bb->has_phi_argument)) {
+ if (previous_interesting_bb != NULL) {
+ previous_interesting_bb->next_interesting_bb = current_bb;
+ } else {
+ area->first_interesting_bb = current_bb;
+ }
+ previous_interesting_bb = current_bb;
+ }
+ }
+}
+
+/*
+ * Macro that pushes a real occurrence on the stack
+ */
+#define PUSH_REAL_OCCURRENCE(o) do{\
+ if (area->bb_on_top_of_renaming_stack != (o)->bb_info) { \
+ (o)->bb_info->next_in_renaming_stack = area->bb_on_top_of_renaming_stack; \
+ area->bb_on_top_of_renaming_stack =(o)->bb_info; \
+ (o)->next_in_renaming_stack = NULL; \
+ } else { \
+ (o)->next_in_renaming_stack = area->top_of_renaming_stack; \
+ } \
+ (o)->bb_info->top_of_local_renaming_stack = (o); \
+ area->top_of_renaming_stack = (o); \
+ area->bb_on_top_of_renaming_stack->phi_argument_has_real_use = FALSE; \
+ } while(0)
+
+/*
+ * Macro that pushes a PHI occurrence on the stack
+ */
+#define PUSH_PHI_OCCURRENCE(b) do{\
+ if (area->bb_on_top_of_renaming_stack != (b)) { \
+ (b)->next_in_renaming_stack = area->bb_on_top_of_renaming_stack; \
+ area->bb_on_top_of_renaming_stack = (b); \
+ } \
+ (b)->top_of_local_renaming_stack = NULL; \
+ area->top_of_renaming_stack = NULL; \
+ area->bb_on_top_of_renaming_stack->phi_argument_has_real_use = FALSE; \
+ } while(0)
+
+/*
+ * See paper, section 5.1, definition of "Dominate"
+ */
+static gboolean
+dominates (MonoSsapreBBInfo *dominator, MonoSsapreBBInfo *dominated) {
+ if ((dominator->dt_dfn <= dominated->dt_dfn) && (dominated->dt_dfn <= (dominator->dt_dfn + dominator->dt_descendants))) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ * See paper, section 5.4.
+ * The two passes are coded sequentially (no separate "rename1" and "rename2" functions).
+ */
+static void
+renaming_pass (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+ MonoSsapreBBInfo *previous_bb = NULL;
+ MonoSsapreExpressionOccurrence *current_expression = NULL;
+ gssize current_class = 0;
+
+ /* This loop is "rename1" */
+ for (current_bb = area->first_interesting_bb, previous_bb = NULL; current_bb != NULL; previous_bb = current_bb, current_bb = current_bb->next_interesting_bb) {
+ if ((previous_bb != NULL) && ! dominates (previous_bb, current_bb)) {
+ if ((area->bb_on_top_of_renaming_stack != NULL) && (area->top_of_renaming_stack == NULL) && (previous_bb->phi_argument_has_real_use == FALSE)) {
+ if (TRACE_SSAPRE) {
+ printf ("Clearing down safe in PHI %d because of backtracking (previous block is [bb %d [ID %d]])\n",
+ area->bb_on_top_of_renaming_stack->phi_redundancy_class, previous_bb->cfg_dfn, previous_bb->bb->block_num);
+ }
+ area->bb_on_top_of_renaming_stack->phi_is_down_safe = FALSE;
+ }
+ while ((area->bb_on_top_of_renaming_stack != NULL) && ! dominates (area->bb_on_top_of_renaming_stack, current_bb)) {
+ MonoSsapreBBInfo *top_bb = area->bb_on_top_of_renaming_stack;
+ if (top_bb->next_in_renaming_stack != NULL) {
+ area->top_of_renaming_stack = top_bb->next_in_renaming_stack->top_of_local_renaming_stack;
+ } else {
+ area->top_of_renaming_stack = NULL;
+ }
+ area->bb_on_top_of_renaming_stack = top_bb->next_in_renaming_stack;
+ }
+ }
+ if (current_bb->idominator != NULL) {
+ current_bb->phi_argument_has_real_use = current_bb->idominator->phi_argument_has_real_use;
+ } else {
+ current_bb->phi_argument_has_real_use = FALSE;
+ }
+
+ if (current_bb->has_phi) {
+ current_bb->phi_is_down_safe = TRUE;
+ current_bb->phi_redundancy_class = current_class;
+ current_class++;
+ PUSH_PHI_OCCURRENCE (current_bb);
+ }
+
+ for (current_expression = current_bb->first_expression_in_bb; (current_expression != NULL) && (current_expression->bb_info == current_bb); current_expression = current_expression->next) {
+ if (area->top_of_renaming_stack != NULL) {
+ MonoSsapreExpressionOccurrence *top = area->top_of_renaming_stack;
+
+ if (((current_expression->description.left_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) ||
+ (current_expression->description.left_argument.argument.ssa_variable == top->description.left_argument.argument.ssa_variable)) &&
+ ((current_expression->description.right_argument.type != MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE) ||
+ (current_expression->description.right_argument.argument.ssa_variable == top->description.right_argument.argument.ssa_variable))) {
+ current_expression->redundancy_class = top->redundancy_class;
+ current_expression->defined_by_real_occurrence = top;
+ } else {
+ current_expression->redundancy_class = current_class;
+ current_class++;
+ current_expression->defined_by_real_occurrence = NULL;
+ PUSH_REAL_OCCURRENCE (current_expression);
+ }
+ current_expression->defined_by_phi = NULL;
+ } else if (area->bb_on_top_of_renaming_stack != NULL) {
+ MonoSsapreBBInfo *phi_bb = area->bb_on_top_of_renaming_stack;
+ gssize left_argument_version = ((current_expression->description.left_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE)?
+ (current_expression->description.left_argument.argument.ssa_variable):BOTTOM_REDUNDANCY_CLASS);
+ gssize right_argument_version = ((current_expression->description.right_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE)?
+ (current_expression->description.right_argument.argument.ssa_variable):BOTTOM_REDUNDANCY_CLASS);
+
+ /* See remark in section 5.4 about the dominance relation between PHI */
+ /* occurrences and phi definitions */
+ MonoSsapreBBInfo *left_argument_definition_bb = ((left_argument_version != BOTTOM_REDUNDANCY_CLASS)?
+ (get_bb_info_of_definition (area, left_argument_version)):NULL);
+ MonoSsapreBBInfo *right_argument_definition_bb = ((right_argument_version != BOTTOM_REDUNDANCY_CLASS)?
+ (get_bb_info_of_definition (area, right_argument_version)):NULL);
+
+ gboolean left_same_class_condition = ((left_argument_definition_bb == NULL) || ((left_argument_definition_bb != phi_bb) ? dominates (left_argument_definition_bb, phi_bb) :
+ (IS_PHI_DEFINITION (left_argument_version) ? TRUE : FALSE)));
+ gboolean right_same_class_condition = ((right_argument_definition_bb == NULL) || ((right_argument_definition_bb != phi_bb) ? dominates (right_argument_definition_bb, phi_bb) :
+ (IS_PHI_DEFINITION (right_argument_version) ? TRUE : FALSE)));
+
+ if (left_same_class_condition && right_same_class_condition) {
+ int phi_argument;
+
+ phi_bb->phi_defines_a_real_occurrence = TRUE;
+ current_bb->phi_argument_has_real_use = TRUE;
+ current_expression->redundancy_class = phi_bb->phi_redundancy_class;
+ current_expression->defined_by_phi = phi_bb;
+
+ /*
+ * Major difference from the paper here...
+ * Instead of maintaining "set_for_rename2" (see figure 20), we just
+ * compute "phi_argument_left_argument_version" (and right) here, and
+ * use that in rename2, saving us the hassle of maintaining a set
+ * data structure (and the related allocations).
+ */
+ for (phi_argument = 0; phi_argument < phi_bb->in_count; phi_argument++) {
+ MonoSsapreBBInfo *previous_bb = phi_bb->in_bb [phi_argument];
+ if (left_argument_version != BOTTOM_REDUNDANCY_CLASS) {
+ previous_bb->phi_argument_left_argument_version = get_variable_version_at_predecessor_bb (area,
+ left_argument_version, phi_bb, phi_argument);
+ }
+ if (right_argument_version != BOTTOM_REDUNDANCY_CLASS) {
+ previous_bb->phi_argument_right_argument_version = get_variable_version_at_predecessor_bb (area,
+ right_argument_version, phi_bb, phi_argument);
+ }
+ }
+ } else {
+ current_expression->redundancy_class = current_class;
+ current_class++;
+ current_expression->defined_by_phi = NULL;
+ PUSH_REAL_OCCURRENCE (current_expression);
+ phi_bb->phi_is_down_safe = FALSE;
+ if (TRACE_SSAPRE) {
+ printf ("Clearing down safe in PHI %d because of real occurrence %d\n",
+ phi_bb->phi_redundancy_class, current_expression->redundancy_class);
+ }
+ }
+ current_expression->defined_by_real_occurrence = NULL;
+ } else {
+ current_expression->redundancy_class = current_class;
+ current_class++;
+ current_expression->defined_by_real_occurrence = NULL;
+ current_expression->defined_by_phi = NULL;
+ PUSH_REAL_OCCURRENCE (current_expression);
+ }
+ }
+
+ if (current_bb->has_phi_argument) {
+ if (area->top_of_renaming_stack != NULL) {
+ current_bb->phi_argument_defined_by_real_occurrence = area->top_of_renaming_stack;
+ current_bb->phi_argument_class = area->top_of_renaming_stack->redundancy_class;
+ } else if (area->bb_on_top_of_renaming_stack != NULL) {
+ current_bb->phi_argument_defined_by_phi = area->bb_on_top_of_renaming_stack;
+ current_bb->phi_argument_class = area->bb_on_top_of_renaming_stack->phi_redundancy_class;
+ } else {
+ current_bb->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ }
+ }
+ }
+ if ((area->bb_on_top_of_renaming_stack != NULL) && (area->top_of_renaming_stack == NULL) && (previous_bb->phi_argument_has_real_use == FALSE)) {
+ if (TRACE_SSAPRE) {
+ printf ("Clearing down safe in PHI %d because of backtracking (previous block is [bb %d [ID %d]])\n",
+ area->bb_on_top_of_renaming_stack->phi_redundancy_class, previous_bb->cfg_dfn, previous_bb->bb->block_num);
+ }
+ area->bb_on_top_of_renaming_stack->phi_is_down_safe = FALSE;
+ }
+ area->number_of_classes = current_class;
+
+ /* This loop is "rename2" */
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi_argument) {
+ if ((current_bb->phi_argument_left_argument_version != BOTTOM_REDUNDANCY_CLASS) || (current_bb->phi_argument_right_argument_version != BOTTOM_REDUNDANCY_CLASS)) {
+ if (current_bb->phi_argument_defined_by_real_occurrence != NULL) {
+ if (((current_bb->phi_argument_left_argument_version != BOTTOM_REDUNDANCY_CLASS) &&
+ (current_bb->phi_argument_left_argument_version != current_bb->phi_argument_defined_by_real_occurrence->description.left_argument.argument.ssa_variable)) ||
+ ((current_bb->phi_argument_right_argument_version != BOTTOM_REDUNDANCY_CLASS) &&
+ (current_bb->phi_argument_right_argument_version != current_bb->phi_argument_defined_by_real_occurrence->description.right_argument.argument.ssa_variable))) {
+ current_bb->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ }
+ } else if (current_bb->phi_argument_defined_by_phi != NULL) {
+ MonoSsapreBBInfo *phi_bb = current_bb->phi_argument_defined_by_phi;
+ MonoSsapreBBInfo *left_argument_definition_bb = (current_bb->phi_argument_left_argument_version != BOTTOM_REDUNDANCY_CLASS) ?
+ get_bb_info_of_definition (area, current_bb->phi_argument_left_argument_version) : NULL;
+ MonoSsapreBBInfo *right_argument_definition_bb = (current_bb->phi_argument_right_argument_version != BOTTOM_REDUNDANCY_CLASS) ?
+ get_bb_info_of_definition (area, current_bb->phi_argument_right_argument_version) : NULL;
+ /* See remark in section 5.4 about the dominance relation between PHI */
+ /* occurrences and phi definitions */
+ gboolean left_bottom_condition = ((left_argument_definition_bb != NULL) && ! ((left_argument_definition_bb != phi_bb) ? dominates (left_argument_definition_bb, phi_bb) :
+ (IS_PHI_DEFINITION (current_bb->phi_argument_left_argument_version) ? TRUE : FALSE)));
+ gboolean right_bottom_condition = ((right_argument_definition_bb != NULL) && ! ((right_argument_definition_bb != phi_bb) ? dominates (right_argument_definition_bb, phi_bb) :
+ (IS_PHI_DEFINITION (current_bb->phi_argument_right_argument_version) ? TRUE : FALSE)));
+
+ if (left_bottom_condition || right_bottom_condition) {
+ current_bb->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ }
+ } else {
+ current_bb->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ }
+ } else {
+ current_bb->phi_argument_class = BOTTOM_REDUNDANCY_CLASS;
+ }
+
+ if (current_bb->phi_argument_class == BOTTOM_REDUNDANCY_CLASS) {
+ if ((current_bb->phi_argument_defined_by_phi != NULL) && (! current_bb->phi_argument_has_real_use)) {
+ if (TRACE_SSAPRE) {
+ printf ("Clearing down safe in PHI %d because PHI argument in block [bb %d [ID %d]] is BOTTOM\n",
+ current_bb->phi_argument_defined_by_phi->phi_redundancy_class, current_bb->cfg_dfn, current_bb->bb->block_num);
+ }
+ current_bb->phi_argument_defined_by_phi->phi_is_down_safe = FALSE;
+ }
+ current_bb->phi_argument_has_real_use = FALSE;
+ }
+ }
+ }
+
+ /* Final quick pass to copy the result of "rename2" into PHI nodes */
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ int i;
+ for (i = 0; i < current_bb->in_count; i++) {
+ current_bb->phi_arguments_classes [i] = current_bb->in_bb [i]->phi_argument_class;
+ }
+ }
+ }
+}
+
+#undef PUSH_REAL_OCCURRENCE
+#undef PUSH_PHI_OCCURRENCE
+
+/*
+ * See paper, figure 8
+ */
+static void
+reset_down_safe (MonoSsapreBBInfo *phi_argument) {
+ if ((phi_argument->phi_argument_class != BOTTOM_REDUNDANCY_CLASS) && (! phi_argument->phi_argument_has_real_use) && (phi_argument->phi_argument_defined_by_phi != NULL) && (phi_argument->phi_argument_defined_by_phi->phi_is_down_safe)) {
+ int i;
+ MonoSsapreBBInfo *phi = phi_argument->phi_argument_defined_by_phi;
+// if (TRACE_SSAPRE) {
+// printf ("Clearing down safe in PHI %d inside reset_down_safe\n", phi->phi_redundancy_class);
+// }
+ phi->phi_is_down_safe = FALSE;
+ for (i = 0; i < phi->in_count; i++) {
+ reset_down_safe (phi->in_bb [i]);
+ }
+ }
+}
+
+/*
+ * See paper, figure 8
+ */
+static void
+down_safety (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ if (! current_bb->phi_is_down_safe) {
+ int i;
+ for (i = 0; i < current_bb->in_count; i++) {
+ reset_down_safe (current_bb->in_bb [i]);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 10
+ */
+static void
+reset_can_be_available (MonoSsapreWorkArea *area, MonoSsapreBBInfo *phi) {
+ MonoSsapreBBInfo *current_bb = NULL;
+
+ phi->phi_can_be_available = FALSE;
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ gboolean phi_is_interesting = FALSE;
+ int i;
+
+ for (i = 0; i < current_bb->in_count; i++) {
+ MonoSsapreBBInfo *phi_argument = current_bb->in_bb [i];
+ if ((phi_argument->phi_argument_class == current_bb->phi_redundancy_class) && (! phi_argument->phi_argument_has_real_use)) {
+ phi_is_interesting = TRUE;
+ break;
+ }
+ }
+
+ if (phi_is_interesting && (! current_bb->phi_is_down_safe) && (current_bb->phi_can_be_available)) {
+ reset_can_be_available (area, current_bb);
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 10
+ */
+static void
+compute_can_be_available (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ if ((! current_bb->phi_is_down_safe) && (current_bb->phi_can_be_available)) {
+ gboolean phi_is_interesting = FALSE;
+ int i;
+
+ for (i = 0; i < current_bb->in_count; i++) {
+ if (current_bb->phi_arguments_classes [i] == BOTTOM_REDUNDANCY_CLASS) {
+ phi_is_interesting = TRUE;
+ break;
+ }
+ }
+
+ if (phi_is_interesting) {
+ reset_can_be_available (area, current_bb);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 10
+ */
+static void
+reset_later (MonoSsapreWorkArea *area, MonoSsapreBBInfo *phi) {
+ MonoSsapreBBInfo *current_bb = NULL;
+
+ if (phi->phi_is_later) {
+ phi->phi_is_later = FALSE;
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ gboolean phi_is_interesting = FALSE;
+ int i;
+
+ for (i = 0; i < current_bb->in_count; i++) {
+ MonoSsapreBBInfo *phi_argument = current_bb->in_bb [i];
+ if (phi_argument->phi_argument_class == current_bb->phi_redundancy_class) {
+ phi_is_interesting = TRUE;
+ break;
+ }
+ }
+
+ if (phi_is_interesting) {
+ reset_later (area, current_bb);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 10
+ */
+static void
+compute_later (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ current_bb->phi_is_later = current_bb->phi_can_be_available;
+ }
+ }
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ if (current_bb->phi_is_later) {
+ gboolean phi_is_interesting = FALSE;
+ int i;
+
+ for (i = 0; i < current_bb->in_count; i++) {
+ MonoSsapreBBInfo *phi_argument = current_bb->in_bb [i];
+ if ((phi_argument->phi_argument_class != BOTTOM_REDUNDANCY_CLASS) && (phi_argument->phi_argument_has_real_use)) {
+ phi_is_interesting = TRUE;
+ break;
+ }
+ }
+
+ if (phi_is_interesting) {
+ reset_later (area, current_bb);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 12, function Finalize_1
+ */
+static void finalize_availability_and_reload (MonoSsapreWorkArea *area, MonoSsapreAvailabilityTableElement *availability_table) {
+ MonoSsapreBBInfo *current_bb = NULL;
+ MonoSsapreExpressionOccurrence *current_expression = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->has_phi) {
+ if (current_bb->phi_can_be_available && ! current_bb->phi_is_later) {
+ availability_table [current_bb->phi_redundancy_class].class_defined_by_phi = current_bb;
+ }
+ }
+
+ for (current_expression = current_bb->first_expression_in_bb; (current_expression != NULL) && (current_expression->bb_info == current_bb); current_expression = current_expression->next) {
+ MonoSsapreBBInfo *defining_bb = availability_table [current_expression->redundancy_class].class_defined_by_phi;
+ if (defining_bb == NULL && availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence != NULL) {
+ defining_bb = availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence->bb_info;
+ }
+ if (defining_bb != NULL) {
+ if (! dominates (defining_bb, current_bb)) {
+ defining_bb = NULL;
+ }
+ }
+
+ if (defining_bb == NULL) {
+ current_expression->reload = FALSE;
+ availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence = current_expression;
+ } else {
+ current_expression->reload = TRUE;
+ current_expression->defined_by_phi = availability_table [current_expression->redundancy_class].class_defined_by_phi;
+ current_expression->defined_by_real_occurrence = availability_table [current_expression->redundancy_class].class_defined_by_real_occurrence;
+ }
+
+ current_expression->save = FALSE;
+ }
+
+ if (current_bb->has_phi_argument) {
+ MonoSsapreBBInfo *phi_bb = current_bb->out_bb [0];
+ if (((phi_bb->phi_can_be_available) && (! phi_bb->phi_is_later)) &&
+ ((current_bb->phi_argument_class == BOTTOM_REDUNDANCY_CLASS) ||
+ ((current_bb->phi_argument_has_real_use == FALSE) && (current_bb->phi_argument_defined_by_phi != NULL) &&
+ (! ((current_bb->phi_argument_defined_by_phi->phi_can_be_available) && (! current_bb->phi_argument_defined_by_phi->phi_is_later)))
+ ))) {
+ current_bb->phi_argument_needs_insert = TRUE;
+ current_bb->phi_argument_defined_by_real_occurrence = NULL;
+ current_bb->phi_argument_defined_by_phi = NULL;
+ } else {
+ current_bb->phi_argument_needs_insert = FALSE;
+ if (current_bb->phi_argument_class != BOTTOM_REDUNDANCY_CLASS) {
+ current_bb->phi_argument_defined_by_real_occurrence = availability_table [current_bb->phi_argument_class].class_defined_by_real_occurrence;
+ current_bb->phi_argument_defined_by_phi = availability_table [current_bb->phi_argument_class].class_defined_by_phi;
+ }
+ }
+
+ current_bb->phi_argument_has_been_processed = FALSE;
+ }
+ }
+}
+
+/*
+ * See paper, figure 13, function Set_save
+ */
+static void set_save (MonoSsapreBBInfo *phi_occurrance, MonoSsapreExpressionOccurrence *real_occurrance) {
+ if (real_occurrance != NULL) {
+ real_occurrance->save = TRUE;
+ } else if (phi_occurrance != NULL) {
+ int i;
+ for (i = 0; i < phi_occurrance->in_count; i++) {
+ MonoSsapreBBInfo *phi_argument = phi_occurrance->in_bb [i];
+ if (! phi_argument->phi_argument_has_been_processed) {
+ phi_argument->phi_argument_has_been_processed = TRUE;
+ set_save (phi_argument->phi_argument_defined_by_phi, phi_argument->phi_argument_defined_by_real_occurrence);
+ }
+ }
+ }
+}
+
+/*
+ * See paper, figure 13, function Finalize_2 (note that we still don't do
+ * extraneous PHI elimination, see function Set_replacement)
+ */
+static void finalize_save (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+ MonoSsapreExpressionOccurrence *current_expression = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ for (current_expression = current_bb->first_expression_in_bb; (current_expression != NULL) && (current_expression->bb_info == current_bb); current_expression = current_expression->next) {
+ if (current_expression->reload) {
+ set_save (current_expression->defined_by_phi, current_expression->defined_by_real_occurrence);
+ }
+ }
+
+ if ((current_bb->has_phi_argument) &&
+ (! current_bb->phi_argument_needs_insert) &&
+ (current_bb->phi_argument_class != BOTTOM_REDUNDANCY_CLASS) &&
+ (current_bb->phi_argument_defined_by_real_occurrence != NULL)) {
+ current_bb->phi_argument_defined_by_real_occurrence->save = TRUE;
+ }
+ }
+}
+
+/*
+ * Perform all "finalize" steps
+ */
+static void finalize (MonoSsapreWorkArea *area) {
+ MonoSsapreAvailabilityTableElement *availability_table = alloca (sizeof (MonoSsapreAvailabilityTableElement) * (area->number_of_classes));
+ int i;
+
+ for (i = 0; i < area->number_of_classes; i++) {
+ availability_table[i].class_defined_by_phi = NULL;
+ availability_table[i].class_defined_by_real_occurrence = NULL;
+ }
+
+ finalize_availability_and_reload (area, availability_table);
+ finalize_save (area);
+}
+
+/*
+ * Macros that help in creating constants
+ */
+#define NEW_INST(dest,op) do { \
+ (dest) = mono_mempool_alloc0 (area->cfg->mempool, sizeof (MonoInst)); \
+ (dest)->opcode = (op); \
+ } while (0)
+
+#define NEW_I4(dest,val) do { \
+ NEW_INST ((dest), OP_ICONST); \
+ (dest)->inst_c0 = (val); \
+ (dest)->type = STACK_I4; \
+ } while (0)
+
+#define NEW_I8(dest,val) do { \
+ NEW_INST ((dest), OP_I8CONST); \
+ (dest)->inst_l = (val); \
+ (dest)->type = STACK_I8; \
+ } while (0)
+
+#define NEW_R4(dest,f) do { \
+ NEW_INST ((dest), OP_R4CONST); \
+ (dest)->inst_p0 = f; \
+ (dest)->type = STACK_R8; \
+ } while (0)
+
+#define NEW_R8(dest,d) do { \
+ NEW_INST ((dest), OP_R8CONST); \
+ (dest)->inst_p0 = d; \
+ (dest)->type = STACK_R8; \
+ } while (0)
+
+/*
+ * Create a MonoInst that represents an expression argument
+ */
+static MonoInst*
+create_expression_argument (MonoSsapreWorkArea *area, MonoSsapreExpressionArgument *argument) {
+ MonoInst *result;
+
+ switch (argument->type) {
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT:
+ return NULL;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE:
+ return mono_compile_create_var_load (area->cfg, argument->argument.ssa_variable);
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT:
+ NEW_I4 (result, argument->argument.integer_constant);
+ return result;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT:
+ NEW_I8 (result, *(argument->argument.long_constant));
+ return result;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT:
+ NEW_R4 (result, argument->argument.float_constant);
+ return result;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT:
+ NEW_R8 (result, argument->argument.double_constant);
+ return result;
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE:
+ case MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY:
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+}
+
+/*
+ * Create a MonoInst that represents an expression
+ */
+static MonoInst*
+create_expression (MonoSsapreWorkArea *area, MonoSsapreExpressionDescription *expression) {
+ MonoInst *result;
+ NEW_INST (result, expression->opcode);
+ result->inst_left = create_expression_argument (area, &(expression->left_argument));
+ result->inst_right = create_expression_argument (area, &(expression->right_argument));
+ return result;
+}
+
+/*
+ * See paper, section 3.6
+ */
+static void code_motion (MonoSsapreWorkArea *area) {
+ MonoSsapreBBInfo *current_bb = NULL;
+ MonoSsapreExpressionOccurrence *current_expression = NULL;
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if ((current_bb->has_phi) && (current_bb->phi_can_be_available && ! current_bb->phi_is_later)) {
+ MonoInst *new_var = mono_compile_create_var (area->cfg, area->current_expression->type, OP_LOCAL);
+ current_bb->phi_variable_index = new_var->inst_c0;
+ } else {
+ current_bb->phi_variable_index = BOTTOM_REDUNDANCY_CLASS;
+ }
+
+ for (current_expression = current_bb->first_expression_in_bb; (current_expression != NULL) && (current_expression->bb_info == current_bb); current_expression = current_expression->next) {
+ if (current_expression->save) {
+ MonoInst *new_var = mono_compile_create_var (area->cfg, area->current_expression->type, OP_LOCAL);
+ current_expression->variable_index = new_var->inst_c0;
+ } else {
+ current_expression->variable_index = BOTTOM_REDUNDANCY_CLASS;
+ }
+ }
+
+ if ((current_bb->has_phi_argument) && (current_bb->phi_argument_needs_insert)) {
+ MonoInst *new_var = mono_compile_create_var (area->cfg, area->current_expression->type, OP_LOCAL);
+ current_bb->phi_argument_variable_index = new_var->inst_c0;
+ } else {
+ current_bb->phi_argument_variable_index = BOTTOM_REDUNDANCY_CLASS;
+ }
+ }
+
+ for (current_bb = area->first_interesting_bb; current_bb != NULL; current_bb = current_bb->next_interesting_bb) {
+ if (current_bb->phi_variable_index != BOTTOM_REDUNDANCY_CLASS) {
+ MonoInst *phi;
+ MonoInst *store;
+ int in_bb;
+
+ NEW_INST (phi, OP_PHI);
+ phi->inst_phi_args = mono_mempool_alloc (area->cfg->mempool, (sizeof (int) * ((current_bb->in_count) + 1)));
+ phi->inst_phi_args [0] = current_bb->in_count;
+ for (in_bb = 0; in_bb < current_bb->in_count; in_bb++) {
+ gssize phi_argument_variable_index = current_bb->in_bb [in_bb]->phi_argument_variable_index;
+ if (phi_argument_variable_index == BOTTOM_REDUNDANCY_CLASS) {
+ MonoSsapreBBInfo *phi_argument_bb = current_bb->in_bb [in_bb];
+ if (phi_argument_bb->phi_argument_defined_by_phi !=NULL) {
+ phi_argument_variable_index = phi_argument_bb->phi_argument_defined_by_phi->phi_variable_index;
+ } else if (phi_argument_bb->phi_argument_defined_by_real_occurrence !=NULL) {
+ phi_argument_variable_index = phi_argument_bb->phi_argument_defined_by_real_occurrence->variable_index;
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+ phi->inst_phi_args [in_bb + 1] = phi_argument_variable_index;
+ }
+ store = mono_compile_create_var_store (area->cfg, current_bb->phi_variable_index, phi);
+ if (current_bb->phi_insertion_point != NULL) {
+ store->next = current_bb->phi_insertion_point->next;
+ current_bb->phi_insertion_point->next = store;
+ } else {
+ store->next = current_bb->bb->code;
+ current_bb->bb->code = store;
+ }
+ current_bb->phi_insertion_point = store;
+
+ area->added_phis ++;
+ }
+
+ for (current_expression = current_bb->first_expression_in_bb; (current_expression != NULL) && (current_expression->bb_info == current_bb); current_expression = current_expression->next) {
+ gboolean altered = FALSE;
+ if (current_expression->reload) {
+ gssize variable_index;
+ if (current_expression->defined_by_phi != NULL) {
+ variable_index = current_expression->defined_by_phi->phi_variable_index;
+ } else if (current_expression->defined_by_real_occurrence != NULL) {
+ variable_index = current_expression->defined_by_real_occurrence->variable_index;
+ } else {
+ variable_index = BOTTOM_REDUNDANCY_CLASS;
+ g_assert_not_reached ();
+ }
+ mono_compile_make_var_load (area->cfg, current_expression->occurrence, variable_index);
+
+ area->reloaded_occurrences ++;
+ altered = TRUE;
+ }
+ if (current_expression->save) {
+ MonoInst *store;
+ MonoInst *moved_expression = mono_mempool_alloc (area->cfg->mempool, sizeof (MonoInst));
+ *moved_expression = *(current_expression->occurrence);
+ store = mono_compile_create_var_store (area->cfg, current_expression->variable_index, moved_expression);
+ if (current_expression->previous_tree != NULL) {
+ store->next = current_expression->previous_tree->next;
+ current_expression->previous_tree->next = store;
+ } else {
+ store->next = current_bb->bb->code;
+ current_bb->bb->code = store;
+ }
+ mono_compile_make_var_load (area->cfg, current_expression->occurrence, current_expression->variable_index);
+
+ area->saved_occurrences ++;
+ altered = TRUE;
+ }
+ if (! altered) {
+ area->unaltered_occurrences ++;
+ }
+ }
+
+ if (current_bb->phi_argument_variable_index != BOTTOM_REDUNDANCY_CLASS) {
+ MonoSsapreExpressionDescription expression_description;
+ MonoInst *inserted_expression;
+ MonoInst *store;
+
+ expression_description = area->current_expression->description;
+ if (expression_description.left_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE) {
+ expression_description.left_argument.argument.ssa_variable = current_bb->phi_argument_left_argument_version;
+ expression_description.left_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE;
+ }
+ if (expression_description.right_argument.type == MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE) {
+ expression_description.right_argument.argument.ssa_variable = current_bb->phi_argument_right_argument_version;
+ expression_description.right_argument.type = MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE;
+ }
+
+ inserted_expression = create_expression (area, &expression_description);
+ store = mono_compile_create_var_store (area->cfg, current_bb->phi_argument_variable_index, inserted_expression);
+ store->next = NULL;
+ mono_add_ins_to_end (current_bb->bb, store);
+
+ area->inserted_occurrences ++;
+ }
+ }
+}
+
+/*
+ * Perform all SSAPRE steps for an expression
+ */
+static void
+process_expression (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
+ if (area->cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("SSAPRE STARTS PROCESSING EXPRESSION ");
+ print_expression_description (&(expression->description));
+ printf ("\n");
+ }
+
+ clean_area_infos (area);
+
+ area->current_expression = expression;
+ phi_insertion (area, expression);
+ renaming_pass (area);
+
+ if (area->cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("START SUMMARY OF BB INFOS\n");
+ print_bb_infos (area);
+ printf ("END SUMMARY OF BB INFOS\n");
+ }
+
+ down_safety (area);
+ compute_can_be_available (area);
+ compute_later (area);
+ finalize (area);
+ code_motion (area);
+
+ if (area->cfg->verbose_level >= DUMP_LEVEL) {
+ printf ("START DUMP OF BB INFOS\n");
+ dump_code (area);
+ printf ("END DUMP OF BB INFOS\n");
+ } else if (area->cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("START SUMMARY OF BB INFOS\n");
+ print_interesting_bb_infos (area);
+ printf ("END SUMMARY OF BB INFOS\n");
+ }
+
+ if (area->cfg->verbose_level >= STATISTICS_LEVEL) {
+ printf ("STATISTICS: saved_occurrences = %d, reloaded_occurrences = %d, inserted_occurrences = %d, unaltered_occurrences = %d, added_phis = %d\n",
+ area->saved_occurrences, area->reloaded_occurrences, area->inserted_occurrences, area->unaltered_occurrences, area->added_phis);
+ }
+
+ if (area->cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("SSAPRE ENDS PROCESSING EXPRESSION ");
+ print_expression_description (&(expression->description));
+ printf ("\n");
+ }
+}
+
+/*
+ * Perform all SSAPRE steps for all the expressions in the worklist
+ */
+static void
+process_worklist (MonoSsapreWorkArea *area, MonoSsapreExpression *expression) {
+ if (expression != NULL) {
+ process_worklist (area, expression->previous);
+ process_expression (area, expression);
+ process_worklist (area, expression->next);
+ }
+}
+
+/*
+ * Hack to apply SSAPRE only to a given method (invaluable in debugging)
+ */
+#define APPLY_SSAPRE_TO_SINGLE_METHOD 0
+#if (APPLY_SSAPRE_TO_SINGLE_METHOD)
+static char *mono_ssapre_method_name = NULL;
+static gboolean check_ssapre_method_name (MonoCompile *cfg) {
+ if (mono_ssapre_method_name == NULL) {
+ mono_ssapre_method_name = getenv ("MONO_SSAPRE_METHOD_NAME");
+ }
+ if (mono_ssapre_method_name != NULL) {
+ char *method_name = mono_method_full_name (cfg->method, TRUE);
+ if (strstr (mono_ssapre_method_name, method_name) != NULL) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return TRUE;
+ }
+}
+#endif
+
+/*
+ * Apply SSAPRE to a MonoCompile
+ */
+void
+mono_perform_ssapre (MonoCompile *cfg) {
+ MonoSsapreWorkArea area;
+ MonoSsapreExpressionOccurrence *current_occurrence;
+ int dt_dfn, descendants, block, i;
+
+#if (APPLY_SSAPRE_TO_SINGLE_METHOD)
+ if (! check_ssapre_method_name (cfg)) return;
+#endif
+
+ area.cfg = cfg;
+ area.mempool = mono_mempool_new ();
+
+ area.num_bblocks = cfg->num_bblocks;
+ area.bb_infos = (MonoSsapreBBInfo*) mono_mempool_alloc (area.mempool, sizeof (MonoSsapreBBInfo) * (cfg->num_bblocks));
+ area.bb_infos_in_cfg_dfn_order = (MonoSsapreBBInfo**) mono_mempool_alloc (area.mempool, sizeof (MonoSsapreBBInfo*) * (cfg->num_bblocks));
+
+ area.sizeof_bb_bitset = mono_bitset_alloc_size (cfg->num_bblocks, 0);
+ area.expression_occurrences_buffer = mono_bitset_mem_new (mono_mempool_alloc (area.mempool, area.sizeof_bb_bitset), area.num_bblocks, 0);
+ area.bb_iteration_buffer = mono_bitset_mem_new (mono_mempool_alloc (area.mempool, area.sizeof_bb_bitset), area.num_bblocks, 0);
+ area.iterated_dfrontier_buffer = mono_bitset_mem_new (mono_mempool_alloc (area.mempool, area.sizeof_bb_bitset), area.num_bblocks, 0);
+ area.left_argument_bb_bitset = mono_bitset_mem_new (mono_mempool_alloc (area.mempool, area.sizeof_bb_bitset), area.num_bblocks, 0);
+ area.right_argument_bb_bitset = mono_bitset_mem_new (mono_mempool_alloc (area.mempool, area.sizeof_bb_bitset), area.num_bblocks, 0);
+
+ area.worklist = NULL;
+
+ if (area.cfg->verbose_level >= LOG_LEVEL) {
+ printf ("SSAPRE STARTS PROCESSING METHOD %s\n", mono_method_full_name (cfg->method, TRUE));
+ }
+
+ current_occurrence = (MonoSsapreExpressionOccurrence*) mono_mempool_alloc (area.mempool, sizeof (MonoSsapreExpressionOccurrence));
+ dt_dfn = 0;
+ descendants = 0;
+ process_bb (&area, cfg->bblocks [0], &dt_dfn, &descendants, current_occurrence);
+ for (block = 0; block < area.num_bblocks; block++) {
+ MonoSsapreBBInfo *bb_info = &(area.bb_infos [block]);
+ MonoBasicBlock *bb = bb_info->bb;
+ if (bb->idom != NULL) {
+ bb_info->idominator = area.bb_infos_in_cfg_dfn_order [bb->idom->dfn];
+ } else {
+ bb_info->idominator = NULL;
+ }
+ for (i = 0; i < bb->in_count; i++) {
+ bb_info->in_bb [i] = area.bb_infos_in_cfg_dfn_order [bb->in_bb [i]->dfn];
+ }
+ for (i = 0; i < bb->out_count; i++) {
+ bb_info->out_bb [i] = area.bb_infos_in_cfg_dfn_order [bb->out_bb [i]->dfn];
+ }
+ }
+
+ if (area.cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("SSAPRE START WORKLIST\n");
+ print_worklist (area.worklist);
+ printf ("SSAPRE END WORKLIST\n");
+ }
+
+ process_worklist (&area, area.worklist);
+
+ if (area.cfg->verbose_level >= TRACE_LEVEL) {
+ printf ("SSAPRE ENDS PROCESSING METHOD %s\n", mono_method_full_name (cfg->method, TRUE));
+ }
+
+ mono_mempool_destroy (area.mempool);
+}
--- /dev/null
+/*
+ * ssapre.h: SSA Partial Redundancy Elimination
+ *
+ * Author:
+ * Massimiliano Mantione (massi@ximian.com)
+ *
+ * (C) 2004 Novell, Inc. http://www.novell.com
+ */
+
+#ifndef __MONO_SSAPRE_H__
+#define __MONO_SSAPRE_H__
+
+
+#include "mini.h"
+#include <mono/metadata/mempool.h>
+
+/*
+ * All the different kind of arguments we can handle.
+ * "ANY" means the argument is unknown or cannot be handled, and "NOT_PRESENT"
+ * that the expression does not have this argument (has not "enough" arity).
+ */
+typedef enum {
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT,
+ MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT
+} MonoSsapreExpressionArgumentType;
+
+/*
+ * A struct representing an expression argument (the used branch in the
+ * union depends on the value of the type field).
+ */
+typedef struct MonoSsapreExpressionArgument {
+ MonoSsapreExpressionArgumentType type;
+ union {
+ gssize original_variable;
+ gssize ssa_variable;
+ gssize integer_constant;
+ gint64* long_constant;
+ float* float_constant;
+ double* double_constant;
+ } argument;
+} MonoSsapreExpressionArgument;
+
+/*
+ * Macros used when comparing expression arguments, which return -1,0 or 1.
+ */
+#define MONO_COMPARE_SSAPRE_DIRECT_VALUES(v1,v2) (((v2)>(v1)?(1):((v2)<(v1)?(-1):(0))))
+#define MONO_COMPARE_SSAPRE_POINTER_VALUES(p1,p2) (((*p2)>(*p1)?(1):((*p2)<(*p1)?(-1):(0))))
+
+#define MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENT_VALUES(t,v1,v2) (\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE?\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).original_variable,(v2).original_variable):(\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE?\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).ssa_variable,(v2).ssa_variable):(\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT?\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).integer_constant,(v2).integer_constant):(\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT?\
+ MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).long_constant,(v2).long_constant):(\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT?\
+ MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).float_constant,(v2).float_constant):(\
+ (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT?\
+ MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).double_constant,(v2).double_constant):(\
+ 0)))))))
+
+#define MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS(a1,a2) (\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((a1).type,(a2).type)!=0?\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((a1).type,(a2).type):\
+ MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENT_VALUES ((a1).type,(a1).argument,(a2).argument) )
+
+
+/*
+ * A struct representing an expression, with its opcode and two arguments
+ * (if the opcode has arity 1 right_argument is MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT).
+ */
+typedef struct MonoSsapreExpressionDescription {
+ guint16 opcode;
+ MonoSsapreExpressionArgument left_argument;
+ MonoSsapreExpressionArgument right_argument;
+} MonoSsapreExpressionDescription;
+
+/*
+ * Macro that compares two expression descriptions (returns -1, 0 or 1).
+ */
+#define MONO_COMPARE_SSAPRE_EXPRESSION_DESCRIPTIONS(d1,d2) (\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((d1).opcode,(d2).opcode)!=0?\
+ MONO_COMPARE_SSAPRE_DIRECT_VALUES ((d1).opcode,(d2).opcode):(\
+ MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).left_argument,(d2).left_argument)!=0?\
+ MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).left_argument,(d2).left_argument):(\
+ MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).right_argument,(d2).right_argument)!=0?\
+ MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).right_argument,(d2).right_argument):(\
+ 0))))
+
+/*
+ * Struct that contains all the information related to a BB.
+ * Some of them are taken from the corresponding MonoBasicBlock, some are
+ * constant during the compilation of the whole method, others must be
+ * recomputed for each expression.
+ */
+typedef struct MonoSsapreBBInfo {
+ /* Information constant during the compilation of the whole method: */
+
+ /* Depth First Number relative to a traversal of the dominator tree */
+ gint32 dt_dfn;
+ /* Depth First Number relative to a traversal of the CFG */
+ gint32 cfg_dfn;
+ /* Number of descendants in the dominator tree (is equal to the number of strictly dominated BBs) */
+ int dt_descendants;
+ /* In and out count (taken from the corresponding MonoBasicBlock) */
+ gint16 in_count, out_count;
+ /* Idominator (taken from the corresponding MonoBasicBlock, but pointing */
+ /* to the MonoSsapreBBInfo for convenience) */
+ struct MonoSsapreBBInfo *idominator;
+ /* In and out BBs (taken from the corresponding MonoBasicBlock, but pointing */
+ /* to the MonoSsapreBBInfo for convenience) */
+ struct MonoSsapreBBInfo **in_bb;
+ struct MonoSsapreBBInfo **out_bb;
+ /* Dominance frontier (taken from the corresponding MonoBasicBlock) */
+ MonoBitSet *dfrontier;
+
+ /* MonoInst where new phi definitions must be added in the BB */
+ /* (the last existing phi definition, or NULL if there is none) */
+ MonoInst *phi_insertion_point;
+
+ /* Information reused during the analysis of each expression: */
+
+ /* True if this BB has a PHI occurrence */
+ gboolean has_phi;
+ /* True if this PHI defines a real occurrence */
+ gboolean phi_defines_a_real_occurrence;
+ /* True if this PHI is down safe */
+ gboolean phi_is_down_safe;
+ /* True if this PHI can be available */
+ gboolean phi_can_be_available;
+ /* True if this PHI is "later" */
+ gboolean phi_is_later;
+ /* The PHI class number */
+ gssize phi_redundancy_class;
+ /* The index of this PHI in the cfg->vars array */
+ gssize phi_variable_index;
+ /* Array of the class numbers of the PHI arguments (has "in_count" elements) */
+ gssize *phi_arguments_classes;
+
+
+ /* True if this BB has a PHI argument */
+ gboolean has_phi_argument;
+ /* True if this PHI argument "has real use" */
+ gboolean phi_argument_has_real_use;
+ /* True if this PHI argument needs the insertion of a new occurrence */
+ gboolean phi_argument_needs_insert;
+ /* True if this PHI argument has been processed (see "set_save") */
+ gboolean phi_argument_has_been_processed;
+ /* The PHI argument class number */
+ gssize phi_argument_class;
+ /* The index of this PHI argument in the cfg->vars array */
+ gssize phi_argument_variable_index;
+ /* Points to the real occurrence defining this PHI argument (NULL otherwise) */
+ struct MonoSsapreExpressionOccurrence *phi_argument_defined_by_real_occurrence;
+ /* Points to the BB containing the PHI defining this PHI argument (NULL otherwise) */
+ struct MonoSsapreBBInfo *phi_argument_defined_by_phi;
+ /* Variable version of the left argument og the PHI argument "expected" at */
+ /* the PHI (or BOTTOM_REDUNDANCY_CLASS otherwise), see "renaming_pass" */
+ gssize phi_argument_left_argument_version;
+ /* As above, but for the right argument */
+ gssize phi_argument_right_argument_version;
+
+ /* The first real occurrence in this BB (NULL if there is none) */
+ struct MonoSsapreExpressionOccurrence *first_expression_in_bb;
+ /* Next BB which has either a real occurrence, a PHI or a PHI argument */
+ /* (NULL if there is none, BBs are in dominator tree depth first preorder) */
+ struct MonoSsapreBBInfo *next_interesting_bb;
+
+ /* Used in maintaining the renaming stack */
+ struct MonoSsapreBBInfo *next_in_renaming_stack;
+ struct MonoSsapreExpressionOccurrence *top_of_local_renaming_stack;
+
+ /* MonoBasicBlock representing this BB in the CFG (this is obviously constant) */
+ MonoBasicBlock *bb;
+} MonoSsapreBBInfo;
+
+
+/*
+ * A "real" occurrence.
+ */
+typedef struct MonoSsapreExpressionOccurrence {
+ /* The occurrence in the CFG */
+ MonoInst *occurrence;
+ /* The tree just before the occurrence in the CFG (if the occurrence must */
+ /* saved into a temporary, the definition will be placed just after that tree) */
+ MonoInst *previous_tree;
+ /* The BB where this occurrence is found */
+ MonoSsapreBBInfo *bb_info;
+ /* The description of the occurrence */
+ MonoSsapreExpressionDescription description;
+ /* Next occurrence of this expression */
+ struct MonoSsapreExpressionOccurrence *next;
+ /* Previois occurrence of this expression */
+ struct MonoSsapreExpressionOccurrence *previous;
+ /* True if this occurrence is the first in its BB */
+ gboolean is_first_in_bb;
+ /* True if this occurrence is the last in its BB */
+ gboolean is_last_in_bb;
+ /* "reload" flag (see "finalize") */
+ gboolean reload;
+ /* "save" flag (see "finalize") */
+ gboolean save;
+
+ /* Used in maintaining the renaming stack */
+ struct MonoSsapreExpressionOccurrence *next_in_renaming_stack;
+
+ /* Class number of this occurrence */
+ gssize redundancy_class;
+ /* The index of the temporary of this occurrence in the cfg->vars array */
+ gssize variable_index;
+ /* Points to the real occurrence defining this occurrence (NULL otherwise) */
+ struct MonoSsapreExpressionOccurrence *defined_by_real_occurrence;
+ /* Points to the BB containing the PHI defining this occurrence (NULL otherwise) */
+ struct MonoSsapreBBInfo *defined_by_phi;
+} MonoSsapreExpressionOccurrence;
+
+
+/*
+ * An expression to be processed (in the worklist).
+ */
+typedef struct MonoSsapreExpression {
+ /* The description of the expression */
+ MonoSsapreExpressionDescription description;
+ /* The type to use when creating values of this expression */
+ MonoType *type;
+ /* The list of expression occurrences */
+ MonoSsapreExpressionOccurrence *occurrences;
+ /* The last expression occurrence in the list */
+ MonoSsapreExpressionOccurrence *last_occurrence;
+
+ /* Used in maintaining the worklist (an autobalancing binary tree) */
+ struct MonoSsapreExpression *father;
+ struct MonoSsapreExpression *previous;
+ struct MonoSsapreExpression *next;
+ gssize tree_size;
+} MonoSsapreExpression;
+
+/*
+ * Macros used to maintain the worklist
+ */
+#define MONO_SSAPRE_GOTO_FIRST_EXPRESSION(e) do{\
+ while ((e)->previous != NULL) (e) = (e)->previous;\
+ } while (0)
+#define MONO_SSAPRE_REMOVE_FIRST_EXPRESSION(e) do{\
+ if ((e)->father != NULL) {\
+ (e)->father->previous = (e)->next;\
+ }\
+ } while (0)
+#define MONO_SSAPRE_GOTO_LAST_EXPRESSION(e) do{\
+ while ((e)->next != NULL) (e) = (e)->next;\
+ } while (0)
+#define MONO_SSAPRE_REMOVE_LAST_EXPRESSION(e) do{\
+ if ((e)->father != NULL) {\
+ (e)->father->next = (e)->previous;\
+ }\
+ } while (0)
+
+#define MONO_SSAPRE_MAX_TREE_DEPTH(size,depth) do{\
+ unsigned __mask__ = ~1;\
+ (depth) = 1;\
+ while (((size)&__mask__)!=0) {\
+ __mask__ <<= 1;\
+ (depth)++;\
+ }\
+ } while (0)
+
+#define MONO_SSAPRE_ADD_EXPRESSION_OCCURRANCE(e,o) do{\
+ if ((e)->occurrences == NULL) {\
+ (e)->occurrences = (o);\
+ } else {\
+ (e)->last_occurrence->next = (o);\
+ }\
+ (o)->next = NULL;\
+ (o)->previous = (e)->last_occurrence;\
+ (e)->last_occurrence = (o);\
+ } while (0)
+#define MONO_SSAPRE_REMOVE_EXPRESSION_OCCURRANCE(e,o) do{\
+ if ((e)->occurrences == (o)) {\
+ (e)->occurrences = (o)->next;\
+ }\
+ if ((e)->last_occurrence == (o)) {\
+ (e)->last_occurrence = (o)->previous;\
+ }\
+ if ((o)->previous != NULL) {\
+ (o)->previous->next = (o)->next;\
+ }\
+ if ((o)->next != NULL) {\
+ (o)->next->previous = (o)->previous;\
+ }\
+ (o)->next = NULL;\
+ (o)->previous = NULL;\
+ } while (0)
+
+
+/*
+ * Availability table element (see "finalize"), one for each redundancy class
+ */
+typedef struct MonoSsapreAvailabilityTableElement {
+ /* Points to the real occurrence defining this redundancy class (NULL otherwise) */
+ struct MonoSsapreExpressionOccurrence *class_defined_by_real_occurrence;
+ /* Points to the BB containing the PHI defining this redundancy class (NULL otherwise) */
+ struct MonoSsapreBBInfo *class_defined_by_phi;
+} MonoSsapreAvailabilityTableElement;
+
+/*
+ * The "main" work area for the algorithm.
+ */
+typedef struct MonoSsapreWorkArea {
+ /* The CFG */
+ MonoCompile *cfg;
+ /* The SSAPRE specific mempool */
+ MonoMemPool *mempool;
+
+ /* Number of BBs in the CFG (from cfg) */
+ int num_bblocks;
+ /* BB information, in dominator tree depth first preorder */
+ MonoSsapreBBInfo *bb_infos;
+ /* Pointers to BB information, in CFG depth first preorder */
+ MonoSsapreBBInfo **bb_infos_in_cfg_dfn_order;
+
+ /* Number of variables in the CFG */
+ int num_vars;
+ /* Size of bitset for BBs */
+ int sizeof_bb_bitset;
+ /* Various bitsets used when working with iterated dfrontiers */
+ MonoBitSet *expression_occurrences_buffer;
+ MonoBitSet *bb_iteration_buffer;
+ MonoBitSet *iterated_dfrontier_buffer;
+ MonoBitSet *left_argument_bb_bitset;
+ MonoBitSet *right_argument_bb_bitset;
+
+ /* The expression worklist */
+ MonoSsapreExpression *worklist;
+
+ /* The expression being processed */
+ MonoSsapreExpression *current_expression;
+
+ /* The BB on top of the renaming stack (if "top_of_renaming_stack" is NULL */
+ /* but this is not, then the top of the stack is the PHI in this BB) */
+ struct MonoSsapreBBInfo *bb_on_top_of_renaming_stack;
+ /* The top of the renaming stack */
+ struct MonoSsapreExpressionOccurrence *top_of_renaming_stack;
+
+ /* The head of the list of "interesting" BBs */
+ struct MonoSsapreBBInfo *first_interesting_bb;
+
+ /* The number of generated class numbers */
+ int number_of_classes;
+
+ /* Statistics fields (per expression) */
+ int saved_occurrences;
+ int reloaded_occurrences;
+ int inserted_occurrences;
+ int unaltered_occurrences;
+ int added_phis;
+} MonoSsapreWorkArea;
+
+
+#endif /* __MONO_SSAPRE_H__ */
+2004-12-04 Zoltan Varga <vargaz@freemail.hu>
+
+ * delegate.cs: Add test for unboxing and delegates.
+
2004-12-02 Zoltan Varga <vargaz@freemail.hu>
+ * appdomain-unload.cs: Add tests for unloading an appdomain from inside
+ the appdomain.
+
* appdomain-unload.cs: Stop the foreground thread created by one of the
tests.
-// $Id: ackermann.cs,v 1.3 2002/05/23 13:03:04 lupus Exp $
+// $Id$
// http://www.bagley.org/~doug/shootout/
public class ackermann {
return 1;
}
+ public static void DoUnload (object state) {
+ AppDomain.Unload (AppDomain.CurrentDomain);
+ }
+
+ public static void Callback () {
+ Console.WriteLine (AppDomain.CurrentDomain);
+ WaitCallback unloadDomainCallback = new WaitCallback (DoUnload);
+ ThreadPool.QueueUserWorkItem (unloadDomainCallback);
+ }
+
+ public static int test_0_unload_inside_appdomain_async () {
+ AppDomain domain = AppDomain.CreateDomain ("Test3");
+
+ domain.DoCallBack (new CrossAppDomainDelegate (Callback));
+
+ return 0;
+ }
+
+ public static void SyncCallback () {
+ AppDomain.Unload (AppDomain.CurrentDomain);
+ }
+
+ public static int test_0_unload_inside_appdomain_sync () {
+ AppDomain domain = AppDomain.CreateDomain ("Test3");
+
+ try {
+ domain.DoCallBack (new CrossAppDomainDelegate (SyncCallback));
+ }
+ catch (Exception ex) {
+ /* Should throw a ThreadAbortException */
+ Thread.ResetAbort ();
+ }
+
+ return 0;
+ }
+
// FIXME: This does not work yet, because the thread is finalized too
// early
/*
delegate void SimpleDelegate ();
delegate string NotSimpleDelegate (int a);
delegate int AnotherDelegate (string s);
+
+ delegate string StringDelegate ();
public int data;
Console.WriteLine (d4.Method);
Console.WriteLine (d4.Method.Name);
Console.WriteLine (d4.Method.DeclaringType);
+
+ // Check unboxing of this argument
+ int x = 10;
+ StringDelegate d5 = new StringDelegate (x.ToString);
+ if (d5 () != "10")
+ return 1;
return 0;
/* -*- mode: c -*-
- * $Id: sieve.cs,v 1.2 2003/07/18 13:06:43 lupus Exp $
+ * $Id$
* http://www.bagley.org/~doug/shootout/
*/
# override automake
install-exec:
- d=`pwd`; cd $(mcs_topdir) && $(MAKE) RUNTIME=$$d/mono-wrapper prefix=$(exec_prefix) PROFILES='$(build_profiles)' install-profiles
+ d=`pwd`; \
+ cd $(mcs_topdir) && $(MAKE) prefix='$(exec_prefix)' PROFILES='$(build_profiles)' \
+ RUNTIME=$$d/mono-wrapper RUNTIME_HAS_CONSISTENT_GACDIR=yes install-profiles
# override automake
install-data:
TEST_SUPPORT_FILES = $(tmpinst)/bin/mcs $(tmpinst)/bin/mbas $(tmpinst)/bin/ilasm
endif
-check-local:
+if ENABLE_NUNIT_TESTS
+test_select =
+else
+test_select = TEST_SUBDIRS='tests errors'
+endif
+
+mcs-do-test-profiles:
+ d=`pwd`; cd $(mcs_topdir) && $(MAKE) RUNTIME=$$d/mono-wrapper PROFILES='$(build_profiles)' test-profiles
+
+mcs-do-run-test-profiles:
$(mkinstalldirs) $(tmpinst)/bin
$(MAKE) $(TEST_SUPPORT_FILES)
d=`pwd`; PATH=$$d/$(tmpinst)/bin:$$PATH ; export PATH ; \
( cd $(mcs_topdir) && $(MAKE) RUNTIME=$$d/mono-wrapper PROFILES='$(build_profiles)' run-test-profiles ) || ret=false ; \
rm -fr $(tmpinst) ; $$ret
+check-local: mcs-do-test-profiles
+ $(MAKE) $(test_select) mcs-do-run-test-profiles
+
$(tmpinst)/bin/mcs:
$(MAKE) test-support-file target=$@ file=class/lib/default/mcs.exe
This mechanism works very well for GNOME and other projects.
-Q: Should I use any of the special RCS keywords like $Id: devel-faq,v 1.1 2001/07/31 21:13:05 miguel Exp $, $Author: miguel $,
- $Date: 2001/07/31 21:13:05 $, or $Revision: 1.1 $?
+Q: Should I use any of the special RCS keywords like $Id$, $Author$,
+ $Date$, or $Revision: 1.1 $?
A: Please avoid using those in the source code in the CVS. They
are not really useful, and they cause a lot of conflicts when