+2009-08-18 Zoltan Varga <vargaz@gmail.com>
+
+ * scripts/Makefile.am: Applied patch from Hib Eris (hib@hiberis.nl).
+ Add $(SCRIPT_SUFFIX) to the name of the 'mod' tool.
+
2009-08-04 Miguel de Icaza <miguel@novell.com>
* Start the split between PLATFORM_WIN32 and TARGET_WIN32.
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * DefaultWsdlHelpGenerator.aspx: the 'Message Layout' can now handle
+ self-referencing types. Fixes bug #529353.
+
2009-08-05 Atsushi Enomoto <atsushi@ximian.com>
* web.config: add WCF assemblies as references at compilation.
--%>
<%@ Import Namespace="System.Collections" %>
+<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml" %>
if (elem == null) throw new InvalidOperationException ("Element not found: " + qname);
WriteElementSample (xtw, qname.Namespace, elem);
}
-
+
void WriteElementSample (XmlTextWriter xtw, string ns, XmlSchemaElement elem)
{
bool sharedAnnType = false;
{
WriteAttributes (xtw, stype.Attributes, stype.AnyAttribute);
}
-
+
+ Dictionary<XmlSchemaComplexType,int> recursed_types = new Dictionary<XmlSchemaComplexType,int> ();
void WriteComplexTypeElements (XmlTextWriter xtw, string ns, XmlSchemaComplexType stype)
{
+ int prev = 0;
+ if (recursed_types.ContainsKey (stype))
+ prev = recursed_types [stype];
+
+ if (prev > 1)
+ return;
+ recursed_types [stype] = ++prev;
+
if (stype.Particle != null)
WriteParticleComplexContent (xtw, ns, stype.Particle);
else
else if (stype.ContentModel is XmlSchemaComplexContent)
WriteComplexContent (xtw, ns, (XmlSchemaComplexContent)stype.ContentModel);
}
+ prev = recursed_types [stype];
+ recursed_types [stype] = --prev;
}
void WriteAttributes (XmlTextWriter xtw, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat)
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Consts.cs.in: Add BOOTSTRAP_NET_4_0.
+
2009-07-18 Michael Barker <mike@middlesoft.co.uk>
* Consts.cs.in: Added constant for Mono.Messaging.RabbitMQ.
public const string AssemblySystem_ServiceProcess = "System.ServiceProcess, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
public const string AssemblySystem_Web = "System.Web, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
public const string AssemblySystem_Windows_Forms = "System.Windows.Forms, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089";
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
public const string AssemblySystemCore_3_5 = "System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
#endif
}
+2009-08-13 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Makefile: add System.Json to net_4_0 profile.
+
2009-07-20 Jb Evain <jbevain@novell.com>
* Makefile: set monotouch_SUBDIRS to the net_2_1 assemblies set.
net_4_0_dirs := \
System.Dynamic \
+ System.Json \
Microsoft.CSharp
net_1_1_bootstrap_SUBDIRS := $(bootstrap_dirs) PEAPI
private object state;
private bool completed;
private object return_value;
+ private Exception exception;
public AsyncMethodResult ()
{
public object EndInvoke ()
{
lock (this) {
- if (completed)
- return return_value;
+ if (completed) {
+ if (exception == null)
+ return return_value;
+ else
+ throw exception;
+ }
}
handle.WaitOne ();
+
+ if (exception != null)
+ throw exception;
+
return return_value;
}
handle.Set ();
}
}
+
+ public void CompleteWithException (Exception ex)
+ {
+ lock (this) {
+ completed = true;
+ exception = ex;
+ handle.Set ();
+ }
+ }
}
}
+2009-08-17 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * ToolStripItem.cs: When the owner changes its Font, call the
+ OnFontChanged event, so we let our users know that we likely have a
+ new font - since Font is an ambient property.
+ * ToolStripDropDownItem.cs: When our Font changes, propagate that
+ information to our DropDown control, if any.
+ Fixes #531515.
+
+2009-08-17 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs:
+ * ThemeWin32Classic.cs: When the user clicks on a new cell, we should reset any
+ previous selection, just like .net does. Also, in the cases where a
+ cell is being edited and it keeps the selected status, use the normal
+ colors for it, and use the selected colors for the rest of the columns of
+ that row.
+ Fixes the remaining bits of #323051.
+
+2009-08-16 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs: When getting ProcessKeyPreview fired, call Edit() if we
+ are not editing already - so the edition is actually active on our
+ column style textbox. Also, it seems the code handling process the
+ grid keys is repeated, but instead of removing it, just comment it for
+ now.
+ Fixes part of #323051.
+
+2009-08-13 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * AsyncMethodResult.cs: Store a exception field in case the called
+ method actually caused an exception. This way we can throw it later.
+ * XplatUIDriver.cs: Check if the async method result has an exception
+ - throw it if needed.
+ The idea is that Control.Invoke throws the exception from the thread
+ that called it, not the main MWF thread.
+ Patch by Tom Spink <tspink@gmail.com>. Fixes #497175.
+
+2009-08-12 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs: In mouse move we need to shift the selection in case
+ the pointer is on the row headers.
+ Fixes #323052.
+
+2009-08-11 Ivan N. Zlatev <contact@i-nz.net>
+
+ * SplitContainer.cs: Avoid updating the splitter distance if it hasn't
+ moved. Updating the distance was causing a re-layout which was resetting
+ the clicks counter and preventing DoubleClick from every firing.
+ [Fixes bug #521387]
+
+2009-08-11 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs: When a new TableStyle is added, don't create new
+ columns for it unless it is empty - this is the correct way to both
+ respect the columns if they were provided by our user, or create them
+ for him in case the column collection is empty.
+ Fixes #323111.
+
+2009-08-10 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs: Actually call BindColumns in the handler for
+ ListManager.MetaDataChanged, since the current code is already taking
+ into account the scenario when a custom table style is used - this was
+ confusing us before, and that's why we commented the call to
+ BindColumns. Also call CallAreasAndInvalidate, to properly reflect the
+ changes as needed.
+ Fixes #465021.
+
+2009-08-10 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGrid.cs: When setting the data source, if we have a user
+ provided table style available, force a complete bind in case the
+ column styles for that table style is empty.
+
+2009-08-09 Ivan N. Zlatev <contact@i-nz.net>
+
+ * DataGridViewCell.cs: Handle null and DBNull values.
+
2009-08-07 Rodrigo Kumpera <rkumpera@novell.com>
* ListBindingHelper.cs: Fix the 1.0 build by making this type available
/* editing state */
bool cursor_in_add_row;
bool add_row_changed;
- bool is_editing; // Current cell is edit mode
+ internal bool is_editing; // Current cell is edit mode
bool is_changing;
internal Stack data_source_stack;
base.OnHandleDestroyed (e);
}
+ // It seems we have repeated code with ProcessKeyPreview, specifically
+ // the call to ProcessGridKey. In practice it seems this event is *never* fired
+ // since the key events are handled by the current column's textbox.
+ // We are keeping commented anyway, in case we need to actually call it.
protected override void OnKeyDown (KeyEventArgs ke)
{
base.OnKeyDown (ke);
- if (ProcessGridKey (ke) == true)
+ /*if (ProcessGridKey (ke) == true)
ke.Handled = true;
- /* TODO: we probably don't need this check,
- * since current_cell wouldn't have been set
- * to something invalid */
+ // TODO: we probably don't need this check,
+ // since current_cell wouldn't have been set
+ // to something invalid
if (CurrentTableStyle.GridColumnStyles.Count > 0) {
CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
(ke, current_cell.RowNumber, current_cell.ColumnNumber);
- }
+ }*/
}
protected override void OnKeyPress (KeyPressEventArgs kpe)
DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
+ ResetSelection ();
CurrentCell = new_cell;
Edit ();
} else {
}
}
+ Cursor = Cursors.Default;
+ break;
+ case HitTestType.RowHeader:
+ if (e.Button == MouseButtons.Left)
+ ShiftSelection (testinfo.Row);
+
Cursor = Cursors.Default;
break;
default:
KeyEventArgs ke = new KeyEventArgs (key);
if (ProcessGridKey (ke))
return true;
+
+ // if we receive a key event, make sure that input is actually
+ // taken into account.
+ if (!is_editing) {
+ Edit ();
+ InvalidateRow (current_cell.RowNumber);
+ return true;
+ }
}
return base.ProcessKeyPreview (ref m);
} else if (CurrentTableStyle == grid_style ||
CurrentTableStyle.MappingName != list_name) {
// If the style has been defined by the user, use it
+ // Also, if the user provided style is empty,
+ // force a bind for it
CurrentTableStyle = styles_collection[list_name];
- current_style.CreateColumnsForTable (true);
+ current_style.CreateColumnsForTable (current_style.GridColumnStyles.Count > 0);
} else {
current_style.CreateColumnsForTable (true);
}
private void OnListManagerMetaDataChanged (object sender, EventArgs e)
{
- // XXX
-
- //we need to rethink this, as in 2.0 we get this event when a column is added to a table.
- // forcing a rebind of columns means that we fail bug #80422. disable this for now.
- //
- // BindColumns ();
+ BindColumns ();
+ CalcAreasAndInvalidate ();
}
private void OnListManagerPositionChanged (object sender, EventArgs e)
case CollectionChangeAction.Add:
if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
CurrentTableStyle = (DataGridTableStyle)e.Element;
- ((DataGridTableStyle) e.Element).CreateColumnsForTable (false);
+ // force to auto detect columns in case the new style is completely empty
+ ((DataGridTableStyle) e.Element).CreateColumnsForTable (CurrentTableStyle.GridColumnStyles.Count > 0);
}
break;
case CollectionChangeAction.Remove:
value = e.Value;
}
+ if (value == null || (cellStyle != null && value == cellStyle.DataSourceNullValue)) {
+ if (FormattedValueType == typeof (string))
+ return String.Empty;
+ }
+
if (FormattedValueType == typeof(string) && value is IFormattable && !String.IsNullOrEmpty (cellStyle.Format))
return ((IFormattable) value).ToString (cellStyle.Format, cellStyle.FormatProvider);
if (value != null && FormattedValueType.IsAssignableFrom (value.GetType()))
if (DataGridView != null && (RowIndex < 0 || RowIndex >= DataGridView.Rows.Count))
throw new ArgumentOutOfRangeException ("rowIndex", "Specified argument was out of the range of valid values.");
- if (DataProperty != null)
+ if (OwningRow != null && OwningRow.Index == DataGridView.NewRowIndex)
+ return DefaultNewRowValue;
+
+ if (DataProperty != null && OwningRow.DataBoundItem != null)
return DataProperty.GetValue (OwningRow.DataBoundItem);
if (valuex != null)
private int splitter_increment;
private Rectangle splitter_rectangle;
private Rectangle splitter_rectangle_moving;
+ private Rectangle splitter_rectangle_before_move;
private bool splitter_fixed;
private bool splitter_dragging;
private int splitter_prev_move;
{
splitter_prev_move = orientation == Orientation.Vertical ? location.X : location.Y;
splitter_rectangle_moving = splitter_rectangle;
+ splitter_rectangle_before_move = splitter_rectangle;
}
private void SplitterMove (Point location)
private void SplitterEndMove (Point location, bool cancel)
{
if (!cancel) {
- splitter_rectangle = splitter_rectangle_moving;
- UpdateSplitter ();
+ // Prevent updating the splitter distance if the user changes it in e.g. the
+ // DoubleClick handler, but no delta move has happened in our drag-handling.
+ // We don't compare to splitter_rectangle for exactly that reason here
+ // (if it gets changed externally) and compare to a cached value.
+ //
+ if (splitter_rectangle_before_move != splitter_rectangle_moving) {
+ splitter_rectangle = splitter_rectangle_moving;
+ UpdateSplitter ();
+ }
}
SplitterEventArgs args = new SplitterEventArgs (location.X, location.Y,
splitter_rectangle.X, splitter_rectangle.Y);
// PaintCells at row, column
int column_cnt = grid.FirstVisibleColumn + grid.VisibleColumnCount;
+ DataGridCell current_cell = grid.CurrentCell;
if (column_cnt > 0) {
Region prev_clip = g.Clip;
current_clip.Intersect (prev_clip);
g.Clip = current_clip;
+ Brush colBackBrush = backBrush;
+ Brush colForeBrush = foreBrush;
+
+ // If we are in the precise cell we are editing, then use the normal colors
+ // even if we are selected.
+ if (grid.is_editing && column == current_cell.ColumnNumber && row == current_cell.RowNumber) {
+ colBackBrush = ResPool.GetSolidBrush (grid.BackColor);
+ colForeBrush = ResPool.GetSolidBrush (grid.ForeColor);
+ }
+
if (is_newrow) {
grid.CurrentTableStyle.GridColumnStyles[column].PaintNewRow (g, rect_cell,
- backBrush,
- foreBrush);
+ colBackBrush,
+ colForeBrush);
} else {
grid.CurrentTableStyle.GridColumnStyles[column].Paint (g, rect_cell, grid.ListManager, row,
- backBrush,
- foreBrush,
+ colBackBrush,
+ colForeBrush,
grid.RightToLeft == RightToLeft.Yes);
}
protected override void OnFontChanged (EventArgs e)
{
base.OnFontChanged (e);
+
+ // don't use DropDown directly, since doing that
+ // would created the DropDown control
+ if (drop_down != null)
+ drop_down.Font = Font;
}
protected override void OnRightToLeftChanged (EventArgs e)
protected internal virtual void OnOwnerFontChanged (EventArgs e)
{
this.CalculateAutoSize ();
+ OnFontChanged (EventArgs.Empty);
}
protected virtual void OnPaint (PaintEventArgs e)
{
AsyncMethodData data = (AsyncMethodData) state;
AsyncMethodResult result = data.Result;
- object ret = data.Method.DynamicInvoke (data.Args);
+
+ object ret;
+ try {
+ ret = data.Method.DynamicInvoke (data.Args);
+ } catch (Exception ex) {
+ if (result != null) {
+ result.CompleteWithException (ex);
+ return;
+ }
+
+ throw;
+ }
+
if (result != null) {
result.Complete (ret);
}
}
#endif
+ AsyncMethodResult result = data.Result;
+ object ret;
+
try {
- AsyncMethodResult result = data.Result;
- object ret = data.Method.DynamicInvoke (data.Args);
+ ret = data.Method.DynamicInvoke (data.Args);
result.Complete (ret);
- }
- finally {
+ } catch (Exception ex) {
+ result.CompleteWithException (ex);
+ return;
+ } finally {
#if !MWF_ON_MSRUNTIME
if (data.Stack != null) {
// whatever occurs we must revert to the original compressed
+2009-08-10 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGridTest.cs: Don't use DataGrid.Rows.Add() for our latest test,
+ since it is 2.0. Use DataGrid.NewRow() instead.
+
+2009-08-10 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * DataGridTest.cs: New test for the interaction between DataSource and
+ TableStyles.
+
2009-08-03 Carlos Alberto Cortez <calberto.cortez@gmail.com>
* GridColumnStylesCollectionTest.cs: New test for #465019. Also make
dg.DataSource = ds;
Assert.AreEqual (0, data_source_changed_count, "A3");
}
+
+ [Test]
+ public void TestManagerSetDataSourceWithEmptyStyle ()
+ {
+ TestDataGrid dg = new TestDataGrid ();
+ dg.BindingContext = new BindingContext ();
+
+ DataSet ds = new DataSet ("DataSet");
+ DataTable dt = new DataTable ("MyTable");
+ dt.Columns.Add ("A", typeof (string));
+ dt.NewRow ();
+ ds.Tables.Add (dt);
+
+ // Add the style for the table we have, but leave it empty
+ // - this is, no column styles
+ DataGridTableStyle table_style = new DataGridTableStyle ();
+ table_style.MappingName = "MyTable";
+ dg.TableStyles.Add (table_style);
+
+ Assert.AreEqual (0, table_style.GridColumnStyles.Count, "#A1");
+
+ dg.DataSource = dt;
+
+ Assert.AreEqual (1, table_style.GridColumnStyles.Count, "#B1");
+ }
}
}
protected void Init ()
{
// all referenced item lists
- consumedItemsByName = new Dictionary<string, BuildItemGroup> ();
+ consumedItemsByName = new Dictionary<string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
// all referenced metadata
consumedMetadataReferences = new List<MetadataReference> ();
protected void BatchAndPrepareBuckets ()
{
- batchedItemsByName = new Dictionary<string, BuildItemGroup> ();
+ batchedItemsByName = new Dictionary<string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
// These will passed as is for every batch
- commonItemsByName = new Dictionary<string, BuildItemGroup> ();
+ commonItemsByName = new Dictionary<string, BuildItemGroup> (StringComparer.InvariantCultureIgnoreCase);
ValidateUnqualifiedMetadataReferences ();
ICollection<Dictionary<string, BuildItemGroup>> Bucketize ()
{
- Dictionary<string, Dictionary<string, BuildItemGroup>> buckets =
- new Dictionary<string, Dictionary<string, BuildItemGroup>> ();
+ var buckets = new Dictionary<string, Dictionary<string, BuildItemGroup>> (
+ StringComparer.InvariantCultureIgnoreCase);
// For each item list represented in "BatchedItemNames", and then for each item
// within that list, get the values for that item for each of the metadata in
Dictionary<string, BuildItemGroup> bucket;
if (!buckets.TryGetValue (bucket_key, out bucket))
// new bucket
- buckets [bucket_key] = bucket = new Dictionary<string, BuildItemGroup> ();
+ buckets [bucket_key] = bucket = new Dictionary<string, BuildItemGroup> (
+ StringComparer.InvariantCultureIgnoreCase);
string itemGroup_key = item.Name;
BuildItemGroup itemGroup;
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * BatchingImplBase.cs: Make the item name lookups and metadata be case
+ insensitive.
+ * TaskDatabase.cs: Likewise.
+ * TaskEngine.cs: Make property name looks, case insensitive.
+
+2009-08-09 Miguel de Icaza <miguel@novell.com>
+
+ * ConsoleLogger.cs: Change the format of the error and warnings
+ strings to work when invoked inside Emacs by not rendering the
+ column if available, by using lowercase "error"/"warning" strings
+ instead of camelcased versions and to not have unnecessary padding.
+
2009-07-31 Ankit Jain <jankit@novell.com>
* ConsoleLogger.cs: Keep track of all the errors and warnings
public virtual void Shutdown ()
{
}
+
+ static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
private string FormatErrorEvent (BuildErrorEventArgs args)
{
- // FIXME: show more complicated args
- if (args.LineNumber != 0 && args.ColumnNumber != 0) {
- return String.Format ("{0}({1},{2}): {3} Error {4}: {5}", args.File, args.LineNumber, args.ColumnNumber,
- args.Subcategory, args.Code, args.Message);
+ // For some reason we get an 1-char empty string as Subcategory somtimes.
+ string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
+ string subcat = subprefix == "" ? "" : args.Subcategory;
+
+ if (args.LineNumber != 0){
+ if (args.ColumnNumber != 0 && !InEmacs)
+ return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
+ args.File, args.LineNumber, args.ColumnNumber,
+ subprefix, subcat, args.Code, args.Message);
+
+ return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
+ args.File, args.LineNumber,
+ subprefix, subcat, args.Code, args.Message);
} else {
- return String.Format ("{0}: {1} Error {2}: {3}", args.File, args.Subcategory, args.Code,
+ return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
args.Message);
}
}
private string FormatWarningEvent (BuildWarningEventArgs args)
{
+ // For some reason we get an 1-char empty string as Subcategory somtimes.
+ string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
+ string subcat = subprefix == "" ? "" : args.Subcategory;
+
// FIXME: show more complicated args
- if (args.LineNumber != 0 && args.ColumnNumber != 0) {
- return String.Format ("{0}({1},{2}): {3} Warning {4}: {5}", args.File, args.LineNumber, args.ColumnNumber,
- args.Subcategory, args.Code, args.Message);
+ if (args.LineNumber != 0){
+
+ if (args.ColumnNumber != 0 && !InEmacs) {
+ return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
+ args.File, args.LineNumber, args.ColumnNumber,
+ subprefix, subcat, args.Code, args.Message);
+ }
+ return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
+ args.File, args.LineNumber,
+ subprefix, subcat, args.Code, args.Message);
} else {
- return String.Format ("{0}: {1} Warning {2}: {3}", args.File, args.Subcategory, args.Code,
+ return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
args.Message);
}
}
public TaskDatabase ()
{
assemblyInformation = new Dictionary <string, AssemblyLoadInfo> ();
- typesByFullName = new Dictionary <string, Type> ();
- typesByShortName = new Dictionary <string, Type> ();
- usingTasksByFullName = new Dictionary <string, UsingTaskInfo> ();
+ typesByFullName = new Dictionary <string, Type> (StringComparer.InvariantCultureIgnoreCase);
+ typesByShortName = new Dictionary <string, Type> (StringComparer.InvariantCultureIgnoreCase);
+ usingTasksByFullName = new Dictionary <string, UsingTaskInfo> (StringComparer.InvariantCultureIgnoreCase);
}
public void RegisterTask (string classname, AssemblyLoadInfo assemblyLoadInfo)
if (is_shortname) {
// Linear search UsingTaskInfo objects for short name match
foreach (UsingTaskInfo ut_info in usingTasksByFullName.Values) {
- if (String.Compare (ut_info.ShortName, classname) == 0) {
+ if (String.Compare (ut_info.ShortName, classname, true) == 0) {
info = ut_info;
break;
}
this.task = task;
this.taskElement = taskElement;
this.taskType = taskType;
- values = new Dictionary <string, object> ();
+ values = new Dictionary <string, object> (StringComparer.InvariantCultureIgnoreCase);
foreach (KeyValuePair <string, string> de in parameters) {
- currentProperty = taskType.GetProperty (de.Key);
+ currentProperty = taskType.GetProperty (de.Key, BindingFlags.Public | BindingFlags.Instance
+ | BindingFlags.IgnoreCase);
if (currentProperty == null)
throw new InvalidProjectFileException (String.Format ("Task does not have property \"{0}\" defined",
de.Key));
itemName = xmlElement.GetAttribute ("ItemName");
propertyName = xmlElement.GetAttribute ("PropertyName");
- propertyInfo = taskType.GetProperty (taskParameter);
+ propertyInfo = taskType.GetProperty (taskParameter, BindingFlags.Public | BindingFlags.Instance |
+ BindingFlags.IgnoreCase);
if (propertyInfo == null)
throw new Exception (String.Format (
"The parameter '{0}' was not found for the '{1}' task.", taskParameter, taskElement.Name));
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * ProjectTest.cs (TestCaseSensitivityOfProjectElements): New.
+
2009-07-30 Ankit Jain <jankit@novell.com>
* EngineTest.cs (TestNewProject): Disable. Invalid for
Assert.AreEqual ("count: 0", group [0].FinalItemSpec, "A3");
}
+ [Test]
+ public void TestCaseSensitivityOfProjectElements ()
+ {
+ string projectXml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
+ <ItemGroup>
+ <Abc Include=""foo"">
+ <MetaDaTA1>md1</MetaDaTA1>
+ <METadata2>md2</METadata2>
+ </Abc>
+ <Abc Include=""FOO"">
+ <MetaDaTA1>MD1 caps</MetaDaTA1>
+ <METadata2>MD2 caps</METadata2>
+ </Abc>
+ <Abc Include=""hmm"">
+ <MetaDaTA1>Md1 CAPS</MetaDaTA1>
+ <METadata2>MD2 CAPS</METadata2>
+ </Abc>
+ <Abc Include=""bar"">
+ <MeTAdata1>md3</MeTAdata1>
+ <Metadata2>md4</Metadata2>
+ </Abc>
+ </ItemGroup>
+ <PropertyGroup><ProP1>ValueProp</ProP1></PropertyGroup>
+ <Target Name=""Main"">
+ <MesSAGE Text=""Full item: @(ABC)""/>
+ <MEssaGE Text=""metadata1 :%(AbC.MetaDATA1) metadata2: %(ABC.MetaDaTa2)""/>
+ <MEssaGE Text=""metadata2 : %(AbC.MetaDAta2)""/>
+ <MEssaGE Text=""Abc identity: %(ABC.IDENTitY)""/>
+ <MEssaGE Text=""prop1 : $(pROp1)""/>
+ </Target>
+</Project>
+";
+ Engine engine = new Engine (Consts.BinPath);
+ Project project = engine.CreateNewProject ();
+ MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+ new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+ engine.RegisterLogger (logger);
+
+ project.LoadXml (projectXml);
+ bool result = project.Build ("Main");
+ if (!result) {
+ logger.DumpMessages ();
+ Assert.Fail ("A1: Build failed");
+ }
+ logger.DumpMessages ();
+
+ logger.CheckLoggedMessageHead ("Full item: foo;FOO;hmm;bar", "#A2");
+ logger.CheckLoggedMessageHead ("metadata1 :md1 metadata2: md2", "#A3");
+ logger.CheckLoggedMessageHead ("metadata1 :MD1 caps metadata2: MD2 caps", "#A4");
+ logger.CheckLoggedMessageHead ("metadata1 :md3 metadata2: md4", "#A5");
+ logger.CheckLoggedMessageHead ("metadata2 : md2", "#A6");
+ logger.CheckLoggedMessageHead ("metadata2 : MD2 caps", "#A7");
+ logger.CheckLoggedMessageHead ("metadata2 : md4", "#A8");
+ logger.CheckLoggedMessageHead ("Abc identity: foo", "#A9");
+ logger.CheckLoggedMessageHead ("Abc identity: hmm", "#A10");
+ logger.CheckLoggedMessageHead ("Abc identity: bar", "#A11");
+ logger.CheckLoggedMessageHead ("prop1 : ValueProp", "#A12");
+
+ Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
+
+ }
+
// full solution test
//[Test]
public void TestBuildSolutionProject ()
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * Microsoft.Build.Tasks_test.dll.sources: Added
+ PcFileCache.cs from md.
+
2009-07-23 Ankit Jain <jankit@novell.com>
* Microsoft.Build.Tasks_test.dll.sources: Added
Microsoft.Build.Tasks/ManagedCompiler.cs
Microsoft.Build.Tasks/Message.cs
Microsoft.Build.Tasks/MSBuild.cs
+Microsoft.Build.Tasks/PcFileCache.cs
Microsoft.Build.Tasks/ReadLinesFromFile.cs
Microsoft.Build.Tasks/RegisterAssembly.cs
Microsoft.Build.Tasks/RemoveDir.cs
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Security;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
+using Mono.PkgConfig;
namespace Microsoft.Build.Tasks {
internal class AssemblyResolver {
TaskLoggingHelper log;
StringWriter sw;
+ static PcFileCache cache;
+
public AssemblyResolver ()
{
gac = new Dictionary<string, Dictionary<Version, string>> ();
KeyValuePair<AssemblyName, string> pair;
if (gac_asm.NameToAssemblyNameCache.TryGetValue (key_aname.Name, out pair)) {
- if (AssemblyNamesCompatible (key_aname, pair.Key, specific_version)) {
+ if (AssemblyNamesCompatible (key_aname, pair.Key, specific_version, true)) {
// gac and tgt frmwk refs are not copied private
return GetResolvedReference (reference, pair.Value, pair.Key, false,
SearchPath.TargetFrameworkDirectory);
return GetResolvedReference (reference, gac [name.Name] [highest], name, false, SearchPath.Gac);
}
+ public ResolvedReference ResolvePkgConfigReference (ITaskItem reference, bool specific_version)
+ {
+ PackageAssemblyInfo pkg = null;
+
+ if (specific_version) {
+ pkg = PcCache.GetAssemblyLocation (reference.ItemSpec);
+ } else {
+ // if not specific version, then just match simple name
+ string name = reference.ItemSpec;
+ if (name.IndexOf (',') > 0)
+ name = name.Substring (0, name.IndexOf (','));
+ pkg = PcCache.ResolveAssemblyName (name).FirstOrDefault ();
+ }
+
+ if (pkg == null) {
+ SearchLogger.WriteLine ("Considered {0}, but could not find in any pkg-config files.",
+ reference.ItemSpec);
+ return null;
+ }
+
+ ResolvedReference rr = GetResolvedReference (reference, pkg.File, new AssemblyName (pkg.FullName),
+ false, SearchPath.PkgConfig);
+ rr.FoundInSearchPathAsString = String.Format ("{{PkgConfig}} provided by package named {0}",
+ pkg.ParentPackage.Name);
+
+ return rr;
+ }
+
public ResolvedReference ResolveHintPathReference (ITaskItem reference, bool specific_version)
{
AssemblyName name = new AssemblyName (reference.ItemSpec);
internal static bool AssemblyNamesCompatible (AssemblyName a, AssemblyName b, bool specificVersion)
{
- if (a.Name != b.Name)
+ return AssemblyNamesCompatible (a, b, specificVersion, false);
+ }
+
+ // if @specificVersion is true then match full name, else just the simple name
+ internal static bool AssemblyNamesCompatible (AssemblyName a, AssemblyName b, bool specificVersion,
+ bool ignoreCase)
+ {
+ if (String.Compare (a.Name, b.Name, ignoreCase) != 0)
return false;
+ if (!specificVersion)
+ // ..and simple names match
+ return true;
+
if (a.CultureInfo != null && !a.CultureInfo.Equals (b.CultureInfo))
return false;
- if (specificVersion && a.Version != null && a.Version != b.Version)
+ if (a.Version != null && a.Version != b.Version)
return false;
byte [] a_bytes = a.GetPublicKeyToken ();
byte [] b_bytes = b.GetPublicKeyToken ();
- if (specificVersion) {
- bool a_is_empty = (a_bytes == null || a_bytes.Length == 0);
- bool b_is_empty = (b_bytes == null || b_bytes.Length == 0);
+ bool a_is_empty = (a_bytes == null || a_bytes.Length == 0);
+ bool b_is_empty = (b_bytes == null || b_bytes.Length == 0);
- if (a_is_empty && b_is_empty)
- return true;
+ if (a_is_empty && b_is_empty)
+ return true;
- if (a_is_empty || b_is_empty)
- return false;
+ if (a_is_empty || b_is_empty)
+ return false;
- for (int i = 0; i < a_bytes.Length; i++)
- if (a_bytes [i] != b_bytes [i])
- return false;
- }
+ for (int i = 0; i < a_bytes.Length; i++)
+ if (a_bytes [i] != b_bytes [i])
+ return false;
return true;
}
// FIXME: to get default values of CopyLocal, compare with TargetFrameworkDirectories
- // If metadata 'Private' is present then use that or use @default_value
+ // If metadata 'Private' is present then use that or use @default_copy_local_value
// as the value for CopyLocal
internal ResolvedReference GetResolvedReference (ITaskItem reference, string filename,
- AssemblyName aname, bool default_value, SearchPath search_path)
+ AssemblyName aname, bool default_copy_local_value, SearchPath search_path)
{
string pvt = reference.GetMetadata ("Private");
- bool copy_local = default_value;
+ bool copy_local = default_copy_local_value;
if (!String.IsNullOrEmpty (pvt))
//FIXME: log a warning for invalid value
Boolean.TryParse (pvt, out copy_local);
}
public TaskLoggingHelper Log {
- set { log = value; }
+ set {
+ log = value;
+ PcFileCacheContext.Log = value;
+ }
+ }
+
+ static PcFileCache PcCache {
+ get {
+ if (cache == null) {
+ PcFileCacheContext context = new PcFileCacheContext ();
+ cache = new PcFileCache (context);
+ cache.Update ();
+ }
+
+ return cache;
+ }
}
}
public TargetFrameworkAssemblies (string path)
{
this.Path = path;
- NameToAssemblyNameCache = new Dictionary<string, KeyValuePair<AssemblyName, string>> ();
+ NameToAssemblyNameCache = new Dictionary<string, KeyValuePair<AssemblyName, string>> (
+ StringComparer.InvariantCultureIgnoreCase);
+ }
+ }
+
+ class PcFileCacheContext : IPcFileCacheContext
+ {
+ public static TaskLoggingHelper Log;
+
+ // In the implementation of this method, the host application can extract
+ // information from the pc file and store it in the PackageInfo object
+ public void StoreCustomData (PcFile pcfile, PackageInfo pkg)
+ {
+ }
+
+ // Should return false if the provided package does not have required
+ // custom data
+ public bool IsCustomDataComplete (string pcfile, PackageInfo pkg)
+ {
+ return true;
+ }
+
+ // Called to report errors
+ public void ReportError (string message, Exception ex)
+ {
+ Log.LogMessage (MessageImportance.Low, "Error loading pkg-config files: {0} : {1}",
+ message, ex.ToString ());
}
}
CandidateAssemblies,
HintPath,
Directory,
- RawFileName
+ RawFileName,
+ PkgConfig
}
}
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * TaskLoggingHelperExtensios.cs (.ctor): Mark internal.
+
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * PcFileCache.cs (PackageInfo): Mark internal.
+
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * AssemblyResolver.cs (FindInTargetFramework): Perform case insensitive
+ assembly name comparison. Use the new AssemblyNamesCompatible api.
+ (AssemblyNamesCompatible): Add new overload with a 'ignoreCase' param.
+
+2009-08-17 Ankit Jain <jankit@novell.com>
+
+ * AssemblyResolver.cs (TargetFrameworkAssemblies..ctor): Make assembly
+ name lookups for target framework assemblies, case insensitive. Helps
+ with cases like "System.configuration", which vs.net is known to emit.
+
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * PcFileCache.cs: New. From monodevelop.
+ * AssemblyResolver.cs (ResolvePkgConfigReference): New. Use PcFileCache
+ to resolve assembly references.
+ (AssemblyNamesCompatible): If SpecificVersion is false, then compare
+ only simple names.
+ (GetResolvedReference): Rename default_value to default_copy_local_value.
+ (Cache): New.
+ (PcFileCacheContext): New.
+ (SearchPath): Add 'PkgConfig' to the enum.
+ * ResolveAssemblyReference.cs: Add support for '{PkgConfig}'. Update
+ messages.
+ * ResolvedReference.cs (FoundInSearchPathToString): Create from ..
+ (FoundInSearchPathAsString): .. this. Change this to a property to
+ allow custom "found in .. " messages.
+
2009-07-31 Ankit Jain <jankit@novell.com>
* MSBuild.cs (Execute): Log error if the file doesn't exist.
--- /dev/null
+//
+// PcFileCache.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2009 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.
+
+using System;
+using System.Text;
+using System.Xml;
+using System.IO;
+using System.Collections.Generic;
+
+namespace Mono.PkgConfig
+{
+ internal interface IPcFileCacheContext
+ {
+ // In the implementation of this method, the host application can extract
+ // information from the pc file and store it in the PackageInfo object
+ void StoreCustomData (PcFile pcfile, PackageInfo pkg);
+
+ // Should return false if the provided package does not have required
+ // custom data
+ bool IsCustomDataComplete (string pcfile, PackageInfo pkg);
+
+ // Called to report errors
+ void ReportError (string message, Exception ex);
+ }
+
+ internal class PcFileCache
+ {
+ const string CACHE_VERSION = "2";
+
+ Dictionary<string, PackageInfo> infos = new Dictionary<string, PackageInfo> ();
+ Dictionary<string, PackageAssemblyInfo> assemblyLocations;
+ string cacheFile;
+ bool hasChanges;
+ IPcFileCacheContext ctx;
+
+ public PcFileCache (IPcFileCacheContext ctx)
+ {
+ this.ctx = ctx;
+ try {
+ string path = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
+ path = Path.Combine (path, "xbuild");
+ if (!Directory.Exists (path))
+ Directory.CreateDirectory (path);
+ cacheFile = Path.Combine (path, "pkgconfig-cache-" + CACHE_VERSION + ".xml");
+
+ if (File.Exists (cacheFile))
+ Load ();
+
+ } catch (Exception ex) {
+ ctx.ReportError ("pc file cache could not be loaded.", ex);
+ }
+ }
+
+ // Updates the pkg-config index, using the default search directories
+ public void Update ()
+ {
+ string pkgConfigPath = Environment.GetEnvironmentVariable ("PKG_CONFIG_PATH");
+ string pkgConfigDir = Environment.GetEnvironmentVariable ("PKG_CONFIG_LIBDIR");
+ Update (GetPkgconfigPaths (null, pkgConfigPath, pkgConfigDir));
+ }
+
+ // Updates the pkg-config index, looking for .pc files in the provided directories
+ public void Update (IEnumerable<string> pkgConfigDirs)
+ {
+ foreach (string pcdir in pkgConfigDirs) {
+ foreach (string pcfile in Directory.GetFiles (pcdir, "*.pc"))
+ GetPackageInfo (pcfile);
+ }
+ Save ();
+ }
+
+ // Returns the location of an assembly, given the full name
+ public PackageAssemblyInfo GetAssemblyLocation (string fullName)
+ {
+ lock (infos) {
+ if (assemblyLocations == null) {
+ // Populate on demand
+ assemblyLocations = new Dictionary<string, PackageAssemblyInfo> ();
+ foreach (PackageInfo info in infos.Values) {
+ if (info.IsValidPackage) {
+ foreach (PackageAssemblyInfo asm in info.Assemblies)
+ assemblyLocations [NormalizeAsmName (asm.FullName)] = asm;
+ }
+ }
+ }
+ }
+ // This collection is read-only once built, so there is no need for a lock
+ PackageAssemblyInfo pasm;
+ assemblyLocations.TryGetValue (NormalizeAsmName (fullName), out pasm);
+ return pasm;
+ }
+
+ public IEnumerable<PackageAssemblyInfo> ResolveAssemblyName (string name)
+ {
+ foreach (PackageInfo pinfo in infos.Values) {
+ if (pinfo.IsValidPackage) {
+ foreach (PackageAssemblyInfo asm in pinfo.Assemblies) {
+ if (asm.Name == name)
+ yield return asm;
+ }
+ }
+ }
+ }
+
+ // Returns information about a .pc file
+ public PackageInfo GetPackageInfo (string file)
+ {
+ PackageInfo info;
+ file = Path.GetFullPath (file);
+
+ DateTime wtime = File.GetLastWriteTime (file);
+
+ lock (infos) {
+ if (infos.TryGetValue (file, out info)) {
+ if (info.LastWriteTime == wtime)
+ return info;
+ }
+ }
+
+ try {
+ info = ParsePackageInfo (file);
+ } catch (Exception ex) {
+ ctx.ReportError ("Error while parsing .pc file", ex);
+ info = new PackageInfo ();
+ }
+
+ lock (infos) {
+ if (!info.IsValidPackage)
+ info = new PackageInfo (); // Create a default empty instance
+ info.LastWriteTime = wtime;
+ infos [file] = info;
+ hasChanges = true;
+ }
+
+ return info;
+ }
+
+ FileStream OpenFile (FileAccess access)
+ {
+ int retries = 6;
+ FileMode mode = access == FileAccess.Read ? FileMode.Open : FileMode.Create;
+ Exception lastException = null;
+
+ while (retries > 0) {
+ try {
+ return new FileStream (cacheFile, mode, access, FileShare.None);
+ } catch (Exception ex) {
+ // the file may be locked by another app. Wait a bit and try again
+ lastException = ex;
+ System.Threading.Thread.Sleep (200);
+ retries--;
+ }
+ }
+ ctx.ReportError ("File could not be opened: " + cacheFile, lastException);
+ return null;
+ }
+
+ void Load ()
+ {
+ // The serializer can't be used because this file is reused in xbuild
+ using (FileStream fs = OpenFile (FileAccess.Read)) {
+ if (fs == null)
+ return;
+ XmlTextReader xr = new XmlTextReader (fs);
+ xr.MoveToContent ();
+ xr.ReadStartElement ();
+ xr.MoveToContent ();
+
+ while (xr.NodeType == XmlNodeType.Element)
+ ReadPackage (xr);
+ }
+ }
+
+ public void Save ()
+ {
+ // The serializer can't be used because this file is reused in xbuild
+ lock (infos) {
+ if (!hasChanges)
+ return;
+
+ using (FileStream fs = OpenFile (FileAccess.Write)) {
+ if (fs == null)
+ return;
+ XmlTextWriter tw = new XmlTextWriter (new StreamWriter (fs));
+ tw.Formatting = Formatting.Indented;
+
+ tw.WriteStartElement ("PcFileCache");
+ foreach (KeyValuePair<string,PackageInfo> file in infos) {
+ WritePackage (tw, file.Key, file.Value);
+ }
+ tw.WriteEndElement (); // PcFileCache
+ tw.Flush ();
+
+ hasChanges = false;
+ }
+ }
+ }
+
+ void WritePackage (XmlTextWriter tw, string file, PackageInfo pinfo)
+ {
+ tw.WriteStartElement ("File");
+ tw.WriteAttributeString ("path", file);
+ tw.WriteAttributeString ("lastWriteTime", XmlConvert.ToString (pinfo.LastWriteTime, XmlDateTimeSerializationMode.Local));
+
+ if (pinfo.IsValidPackage) {
+ if (pinfo.Name != null)
+ tw.WriteAttributeString ("name", pinfo.Name);
+ if (pinfo.Version != null)
+ tw.WriteAttributeString ("version", pinfo.Version);
+ if (!string.IsNullOrEmpty (pinfo.Description))
+ tw.WriteAttributeString ("description", pinfo.Description);
+ if (!pinfo.IsGacPackage)
+ tw.WriteAttributeString ("gacPackage", "false");
+ if (pinfo.CustomData != null) {
+ foreach (KeyValuePair<string,string> cd in pinfo.CustomData)
+ tw.WriteAttributeString (cd.Key, cd.Value);
+ }
+ foreach (PackageAssemblyInfo asm in pinfo.Assemblies) {
+ tw.WriteStartElement ("Assembly");
+ tw.WriteAttributeString ("name", asm.Name);
+ tw.WriteAttributeString ("version", asm.Version);
+ tw.WriteAttributeString ("culture", asm.Culture);
+ tw.WriteAttributeString ("publicKeyToken", asm.PublicKeyToken);
+ tw.WriteAttributeString ("file", asm.File);
+ tw.WriteEndElement (); // Assembly
+ }
+ }
+ tw.WriteEndElement (); // File
+ }
+
+ void ReadPackage (XmlReader tr)
+ {
+ PackageInfo pinfo = new PackageInfo ();
+ string file = null;
+
+ tr.MoveToFirstAttribute ();
+ do {
+ switch (tr.LocalName) {
+ case "path": file = tr.Value; break;
+ case "lastWriteTime": pinfo.LastWriteTime = XmlConvert.ToDateTime (tr.Value, XmlDateTimeSerializationMode.Local); break;
+ case "name": pinfo.Name = tr.Value; break;
+ case "version": pinfo.Version = tr.Value; break;
+ case "description": pinfo.Description = tr.Value; break;
+ case "gacPackage": pinfo.IsGacPackage = tr.Value != "false"; break;
+ default: pinfo.SetData (tr.LocalName, tr.Value); break;
+ }
+ } while (tr.MoveToNextAttribute ());
+
+ tr.MoveToElement ();
+
+ if (!tr.IsEmptyElement) {
+ tr.ReadStartElement ();
+ tr.MoveToContent ();
+ while (tr.NodeType == XmlNodeType.Element) {
+ PackageAssemblyInfo asm = new PackageAssemblyInfo ();
+ asm.Name = tr.GetAttribute ("name");
+ asm.Version = tr.GetAttribute ("version");
+ asm.Culture = tr.GetAttribute ("culture");
+ asm.PublicKeyToken = tr.GetAttribute ("publicKeyToken");
+ asm.File = tr.GetAttribute ("file");
+ if (pinfo.Assemblies == null)
+ pinfo.Assemblies = new List<PackageAssemblyInfo> ();
+ asm.ParentPackage = pinfo;
+ pinfo.Assemblies.Add (asm);
+ tr.Read ();
+ tr.MoveToContent ();
+ }
+ tr.MoveToContent ();
+ tr.ReadEndElement ();
+ } else
+ tr.Read ();
+ tr.MoveToContent ();
+
+ if (!pinfo.IsValidPackage || ctx.IsCustomDataComplete (file, pinfo))
+ infos [file] = pinfo;
+ }
+
+ public object SyncRoot {
+ get { return infos; }
+ }
+
+
+ PackageInfo ParsePackageInfo (string pcfile)
+ {
+ PackageInfo pinfo = new PackageInfo ();
+ pinfo.Name = Path.GetFileNameWithoutExtension (pcfile);
+ List<string> fullassemblies = null;
+ bool gacPackageSet = false;
+
+ PcFile file = new PcFile ();
+ file.Load (pcfile);
+
+ if (file.HasErrors)
+ return pinfo;
+
+ if (file.Libs != null && file.Libs.IndexOf (".dll") != -1) {
+ if (file.Libs.IndexOf ("-lib:") != -1 || file.Libs.IndexOf ("/lib:") != -1) {
+ fullassemblies = GetAssembliesWithLibInfo (file.Libs);
+ } else {
+ fullassemblies = GetAssembliesWithoutLibInfo (file.Libs);
+ }
+ }
+
+ string value = file.GetVariable ("Libraries");
+ if (!string.IsNullOrEmpty (value))
+ fullassemblies = GetAssembliesFromLibrariesVar (value);
+
+ pinfo.Version = file.Version;
+ pinfo.Description = file.Description;
+
+ value = file.GetVariable ("GacPackage");
+ if (value != null) {
+ value = value.ToLower ();
+ pinfo.IsGacPackage = value == "yes" || value == "true";
+ gacPackageSet = true;
+ }
+
+ if (fullassemblies == null)
+ return pinfo;
+
+ string pcDir = Path.GetDirectoryName (pcfile);
+ string monoPrefix = Path.GetDirectoryName (Path.GetDirectoryName (pcDir));
+ monoPrefix = Path.GetFullPath (monoPrefix + Path.DirectorySeparatorChar + "lib" + Path.DirectorySeparatorChar + "mono" + Path.DirectorySeparatorChar);
+
+ List<PackageAssemblyInfo> list = new List<PackageAssemblyInfo> ();
+ foreach (string assembly in fullassemblies) {
+ string asm;
+ if (Path.IsPathRooted (assembly))
+ asm = Path.GetFullPath (assembly);
+ else {
+ if (Path.GetDirectoryName (assembly).Length == 0) {
+ asm = assembly;
+ } else {
+ asm = Path.GetFullPath (Path.Combine (pcDir, assembly));
+ }
+ }
+ if (File.Exists (asm)) {
+ PackageAssemblyInfo pi = new PackageAssemblyInfo ();
+ pi.File = asm;
+ pi.ParentPackage = pinfo;
+ pi.UpdateFromFile (pi.File);
+ list.Add (pi);
+ if (!gacPackageSet && !asm.StartsWith (monoPrefix) && Path.IsPathRooted (asm)) {
+ // Assembly installed outside $(prefix)/lib/mono. It is most likely not a gac package.
+ gacPackageSet = true;
+ pinfo.IsGacPackage = false;
+ }
+ }
+ }
+ pinfo.Assemblies = list;
+ ctx.StoreCustomData (file, pinfo);
+
+ return pinfo;
+ }
+
+ private List<string> GetAssembliesWithLibInfo (string line)
+ {
+ List<string> references = new List<string> ();
+ List<string> libdirs = new List<string> ();
+ List<string> retval = new List<string> ();
+ foreach (string piece in line.Split (' ')) {
+ if (piece.ToLower ().Trim ().StartsWith ("/r:") || piece.ToLower ().Trim ().StartsWith ("-r:")) {
+ references.Add (piece.Substring (3).Trim ());
+ } else if (piece.ToLower ().Trim ().StartsWith ("/lib:") || piece.ToLower ().Trim ().StartsWith ("-lib:")) {
+ libdirs.Add (piece.Substring (5).Trim ());
+ }
+ }
+
+ foreach (string refrnc in references) {
+ foreach (string libdir in libdirs) {
+ if (File.Exists (libdir + Path.DirectorySeparatorChar + refrnc)) {
+ retval.Add (libdir + Path.DirectorySeparatorChar + refrnc);
+ }
+ }
+ }
+
+ return retval;
+ }
+
+ List<string> GetAssembliesFromLibrariesVar (string line)
+ {
+ List<string> references = new List<string> ();
+ foreach (string reference in line.Split (' ')) {
+ if (!string.IsNullOrEmpty (reference))
+ references.Add (reference);
+ }
+ return references;
+ }
+
+ private List<string> GetAssembliesWithoutLibInfo (string line)
+ {
+ List<string> references = new List<string> ();
+ foreach (string reference in line.Split (' ')) {
+ if (reference.ToLower ().Trim ().StartsWith ("/r:") || reference.ToLower ().Trim ().StartsWith ("-r:")) {
+ string final_ref = reference.Substring (3).Trim ();
+ references.Add (final_ref);
+ }
+ }
+ return references;
+ }
+
+ public IEnumerable<string> GetPkgconfigPaths (string prefix, string pkgConfigPath, string pkgConfigLibdir)
+ {
+ char[] sep = new char[] { Path.PathSeparator };
+
+ string[] pkgConfigPaths = null;
+ if (!String.IsNullOrEmpty (pkgConfigPath)) {
+ pkgConfigPaths = pkgConfigPath.Split (sep, StringSplitOptions.RemoveEmptyEntries);
+ if (pkgConfigPaths.Length == 0)
+ pkgConfigPaths = null;
+ }
+
+ string[] pkgConfigLibdirs = null;
+ if (!String.IsNullOrEmpty (pkgConfigLibdir)) {
+ pkgConfigLibdirs = pkgConfigLibdir.Split (sep, StringSplitOptions.RemoveEmptyEntries);
+ if (pkgConfigLibdirs.Length == 0)
+ pkgConfigLibdirs = null;
+ }
+
+ if (prefix == null)
+ prefix = PathUp (typeof (int).Assembly.Location, 4);
+
+ IEnumerable<string> paths = GetUnfilteredPkgConfigDirs (pkgConfigPaths, pkgConfigLibdirs, new string [] { prefix });
+ return NormaliseAndFilterPaths (paths, Environment.CurrentDirectory);
+ }
+
+ IEnumerable<string> GetUnfilteredPkgConfigDirs (IEnumerable<string> pkgConfigPaths, IEnumerable<string> pkgConfigLibdirs, IEnumerable<string> systemPrefixes)
+ {
+ if (pkgConfigPaths != null) {
+ foreach (string dir in pkgConfigPaths)
+ yield return dir;
+ }
+
+ if (pkgConfigLibdirs != null) {
+ foreach (string dir in pkgConfigLibdirs)
+ yield return dir;
+ } else if (systemPrefixes != null) {
+ string[] suffixes = new string [] {
+ Path.Combine ("lib", "pkgconfig"),
+ Path.Combine ("lib64", "pkgconfig"),
+ Path.Combine ("libdata", "pkgconfig"),
+ Path.Combine ("share", "pkgconfig"),
+ };
+ foreach (string prefix in systemPrefixes)
+ foreach (string suffix in suffixes)
+ yield return Path.Combine (prefix, suffix);
+ }
+ }
+
+ IEnumerable<string> NormaliseAndFilterPaths (IEnumerable<string> paths, string workingDirectory)
+ {
+ HashSet<string> filtered = new HashSet<string> ();
+ foreach (string p in paths) {
+ string path = p;
+ if (!Path.IsPathRooted (path))
+ path = Path.Combine (workingDirectory, path);
+ path = Path.GetFullPath (path);
+ if (!filtered.Add (path))
+ continue;
+ try {
+ if (!Directory.Exists (path))
+ continue;
+ } catch (IOException ex) {
+ ctx.ReportError ("Error checking for directory '" + path + "'.", ex);
+ }
+ yield return path;
+ }
+ }
+
+ static string PathUp (string path, int up)
+ {
+ if (up == 0)
+ return path;
+ for (int i = path.Length -1; i >= 0; i--) {
+ if (path[i] == Path.DirectorySeparatorChar) {
+ up--;
+ if (up == 0)
+ return path.Substring (0, i);
+ }
+ }
+ return null;
+ }
+
+ public static string NormalizeAsmName (string name)
+ {
+ int i = name.ToLower ().IndexOf (", publickeytoken=null");
+ if (i != -1)
+ name = name.Substring (0, i).Trim ();
+ i = name.ToLower ().IndexOf (", processorarchitecture=");
+ if (i != -1)
+ name = name.Substring (0, i).Trim ();
+ return name;
+ }
+ }
+
+ internal class PcFile
+ {
+ Dictionary<string,string> variables = new Dictionary<string, string> ();
+
+ public string FilePath { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public string Version { get; set; }
+ public string Libs { get; set; }
+ public bool HasErrors { get; set; }
+
+ public string GetVariable (string varName)
+ {
+ string val;
+ variables.TryGetValue (varName, out val);
+ return val;
+ }
+
+ public void Load (string pcfile)
+ {
+ FilePath = pcfile;
+ variables.Add ("pcfiledir", Path.GetDirectoryName (pcfile));
+ using (StreamReader reader = new StreamReader (pcfile)) {
+ string line;
+ while ((line = reader.ReadLine ()) != null) {
+ int i = line.IndexOf (':');
+ int j = line.IndexOf ('=');
+ int k = System.Math.Min (i != -1 ? i : int.MaxValue, j != -1 ? j : int.MaxValue);
+ if (k == int.MaxValue)
+ continue;
+ string var = line.Substring (0, k).Trim ();
+ string value = line.Substring (k + 1).Trim ();
+ value = Evaluate (value);
+
+ if (k == j) {
+ // Is variable
+ variables [var] = value;
+ }
+ else {
+ switch (var) {
+ case "Name": Name = value; break;
+ case "Description": Description = value; break;
+ case "Version": Version = value; break;
+ case "Libs": Libs = value; break;
+ }
+ }
+ }
+ }
+ }
+
+ string Evaluate (string value)
+ {
+ int i = value.IndexOf ("${");
+ if (i == -1)
+ return value;
+
+ StringBuilder sb = new StringBuilder ();
+ int last = 0;
+ while (i != -1 && i < value.Length) {
+ sb.Append (value.Substring (last, i - last));
+ if (i == 0 || value [i - 1] != '$') {
+ // Evaluate if var is not escaped
+ i += 2;
+ int n = value.IndexOf ('}', i);
+ if (n == -1 || n == i) {
+ // Closing bracket not found or empty name
+ HasErrors = true;
+ return value;
+ }
+ string rname = value.Substring (i, n - i);
+ string rval;
+ if (variables.TryGetValue (rname, out rval))
+ sb.Append (rval);
+ else {
+ HasErrors = true;
+ return value;
+ }
+ i = n + 1;
+ last = i;
+ } else
+ last = i++;
+
+ if (i < value.Length - 1)
+ i = value.IndexOf ("${", i);
+ }
+ sb.Append (value.Substring (last, value.Length - last));
+ return sb.ToString ();
+ }
+ }
+
+ internal class PackageInfo
+ {
+ Dictionary<string,string> customData;
+
+ public PackageInfo ()
+ {
+ IsGacPackage = true;
+ }
+
+ public string Name { get; set; }
+
+ public bool IsGacPackage { get; set; }
+
+ public string Version { get; set; }
+
+ public string Description { get; set; }
+
+ internal List<PackageAssemblyInfo> Assemblies { get; set; }
+
+ public string GetData (string name)
+ {
+ if (customData == null)
+ return null;
+ string res;
+ customData.TryGetValue (name, out res);
+ return res;
+ }
+
+ public void SetData (string name, string value)
+ {
+ if (customData == null)
+ customData = new Dictionary<string, string> ();
+ customData [name] = value;
+ }
+
+ internal Dictionary<string,string> CustomData {
+ get { return customData; }
+ }
+
+ internal DateTime LastWriteTime { get; set; }
+
+ internal bool IsValidPackage {
+ get { return Assemblies != null && Assemblies.Count > 0; }
+ }
+
+ internal bool HasCustomData {
+ get { return customData != null && customData.Count > 0; }
+ }
+ }
+
+ class PackageAssemblyInfo
+ {
+ public string File { get; set; }
+
+ public string Name;
+
+ public string Version;
+
+ public string Culture;
+
+ public string PublicKeyToken;
+
+ public string FullName {
+ get {
+ string fn = Name + ", Version=" + Version;
+ if (!string.IsNullOrEmpty (Culture))
+ fn += ", Culture=" + Culture;
+ if (!string.IsNullOrEmpty (PublicKeyToken))
+ fn += ", PublicKeyToken=" + PublicKeyToken;
+ return fn;
+ }
+ }
+
+ public PackageInfo ParentPackage { get; set; }
+
+ public void UpdateFromFile (string file)
+ {
+ Update (System.Reflection.AssemblyName.GetAssemblyName (file));
+ }
+
+ public void Update (System.Reflection.AssemblyName aname)
+ {
+ Name = aname.Name;
+ Version = aname.Version.ToString ();
+ if (aname.CultureInfo != null) {
+ if (aname.CultureInfo.LCID == System.Globalization.CultureInfo.InvariantCulture.LCID)
+ Culture = "neutral";
+ else
+ Culture = aname.CultureInfo.Name;
+ }
+ string fn = aname.ToString ();
+ string key = "publickeytoken=";
+ int i = fn.ToLower().IndexOf (key) + key.Length;
+ int j = fn.IndexOf (',', i);
+ if (j == -1) j = fn.Length;
+ PublicKeyToken = fn.Substring (i, j - i);
+ }
+ }
+}
resolved_ref.TaskItem.GetMetadata ("CopyLocal"));
Log.LogMessage (MessageImportance.Low,
- "\tReference found at search path '{0}'",
- resolved_ref.FoundInSearchPathAsString ());
+ "\tReference found at search path {0}",
+ resolved_ref.FoundInSearchPathAsString);
if (TryAddNewReference (tempResolvedFiles, resolved_ref) &&
!IsFromGacOrTargetFramework (resolved_ref)) {
} else if (String.Compare (spath, "{CandidateAssemblyFiles}") == 0) {
assembly_resolver.SearchLogger.WriteLine (
"Warning: {CandidateAssemblyFiles} not supported currently");
+ } else if (String.Compare (spath, "{PkgConfig}") == 0) {
+ resolved = assembly_resolver.ResolvePkgConfigReference (item, specific_version);
} else {
resolved = assembly_resolver.FindInDirectory (
item, spath,
aname, resolved_ref.TaskItem.ItemSpec);
Log.LogMessage (MessageImportance.Low,
- "\tReference found at search path '{0}'",
- resolved_ref.FoundInSearchPathAsString ());
+ "\tReference found at search path {0}",
+ resolved_ref.FoundInSearchPathAsString);
if (resolved_ref.FoundInSearchPath == SearchPath.Directory) {
// override CopyLocal with parent's val
} else {
//gac or tgtfmwk
Log.LogMessage (MessageImportance.Low,
- "\tThis is CopyLocal {0} as it is in the gac or one " +
- "of the target framework directories",
+ "\tThis is CopyLocal {0} as it is in the gac," +
+ "target framework directory or provided by a package.",
copy_local);
TryAddNewReference (tempResolvedFiles, resolved_ref);
public bool CopyLocal;
public bool IsPrimary; //default: true
+ string found_search_path_string;
+
public ResolvedReference (ITaskItem item, AssemblyName asm_name, bool copy_local, SearchPath search_path,
string original_item_spec)
{
FoundInSearchPath = search_path;
TaskItem.SetMetadata ("OriginalItemSpec", original_item_spec);
- TaskItem.SetMetadata ("ResolvedFrom", FoundInSearchPathAsString ());
+ TaskItem.SetMetadata ("ResolvedFrom", FoundInSearchPathToString ());
+ }
+
+ public string FoundInSearchPathAsString {
+ get {
+ if (found_search_path_string == null)
+ return FoundInSearchPathToString ();
+ else
+ return found_search_path_string;
+ }
+ set { found_search_path_string = value; }
}
- public string FoundInSearchPathAsString ()
+ string FoundInSearchPathToString ()
{
switch (FoundInSearchPath) {
case SearchPath.Gac:
return "{RawFileName}";
case SearchPath.Directory:
return TaskItem.ItemSpec;
+ case SearchPath.PkgConfig:
+ return "{PkgConfig}";
default:
throw new NotImplementedException (String.Format (
"Implement me for SearchPath: {0}", FoundInSearchPath));
namespace Microsoft.Build.Tasks {
public class TaskLoggingHelperExtension : TaskLoggingHelper {
- public TaskLoggingHelperExtension ()
+ internal TaskLoggingHelperExtension ()
: base (null)
{
}
--- /dev/null
+//
+// CSharpBinder.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright (C) 2009 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.
+//
+
+using System;
+using System.Dynamic;
+using System.Linq.Expressions;
+
+namespace Microsoft.CSharp.RuntimeBinder
+{
+ class CSharpBinder
+ {
+ public static DynamicMetaObject Bind (DynamicMetaObject target, DynamicMetaObject errorSuggestion, DynamicMetaObject[] args)
+ {
+ return Bind (target, errorSuggestion);
+ }
+
+ public static DynamicMetaObject Bind (DynamicMetaObject target, DynamicMetaObject errorSuggestion)
+ {
+ return errorSuggestion ??
+ new DynamicMetaObject(
+ Expression.Constant(new object ()),
+ target.Restrictions.Merge(
+ BindingRestrictions.GetTypeRestriction(
+ target.Expression, target.LimitType)));
+ }
+ }
+}
return base.GetHashCode ();
}
- [MonoTODO]
public override DynamicMetaObject FallbackGetMember (DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
- throw new NotImplementedException ();
+ return CSharpBinder.Bind (target, errorSuggestion);
}
}
}
return base.GetHashCode ();
}
- [MonoTODO]
public override DynamicMetaObject FallbackInvoke (DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
- throw new NotImplementedException ();
+ return CSharpBinder.Bind (target, errorSuggestion, args);
}
}
}
return base.GetHashCode ();
}
- [MonoTODO]
public override DynamicMetaObject FallbackInvoke (DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
- throw new NotImplementedException ();
+ var b = new CSharpInvokeBinder (flags, callingContext, argumentInfo);
+
+ // TODO: Is errorSuggestion ever used?
+ return b.Defer (target, args);
}
- [MonoTODO]
public override DynamicMetaObject FallbackInvokeMember (DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
- throw new NotImplementedException ();
+ return CSharpBinder.Bind (target, errorSuggestion, args);
}
public IList<Type> TypeArguments {
+2009-08-10 Marek Safar <marek.safar@gmail.com>
+
+ * CSharpInvokeBinder.cs, CSharpGetMemberBinder.cs,
+ CSharpInvokeMemberBinder.cs: Defer fallback for now.
+
2009-08-07 Marek Safar <marek.safar@gmail.com>
* CSharpInvokeBinder.cs, CSharpGetIndexBinder.cs, Extensions.cs,
Microsoft.CSharp.RuntimeBinder/Extensions.cs
Microsoft.CSharp.RuntimeBinder/RuntimeBinderException.cs
Microsoft.CSharp.RuntimeBinder/RuntimeBinderInternalCompilerException.cs
+Microsoft.CSharp.RuntimeBinder/CSharpBinder.cs
+2009-08-18 Michael Hutchinson <mhutchinson@novell.com>
+
+ * Mono.Cecil/BaseAssemblyResolver.cs: Search GACs specified in the
+ MONO_GAC_PREFIX environment variable.
+
2009-08-06 Jb Evain <jbevain@novell.com>
* Mono.Cecil/BaseAssemblyResolver.cs:
public abstract class BaseAssemblyResolver : IAssemblyResolver {
ArrayList m_directories;
+ string[] m_monoGacPaths;
public void AddSearchDirectory (string directory)
{
return typeof (object).Assembly.GetType ("System.MonoType", false) != null;
}
- static AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
+ string[] MonoGacPaths {
+ get {
+ if (m_monoGacPaths == null)
+ m_monoGacPaths = GetDefaultMonoGacPaths ();
+ return m_monoGacPaths;
+ }
+ }
+
+ static string[] GetDefaultMonoGacPaths ()
{
- if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
- return null;
+ ArrayList paths = new ArrayList ();
+ string s = GetCurrentGacPath ();
+ if (s != null)
+ paths.Add (s);
+ string gacPathsEnv = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX");
+ if (gacPathsEnv != null && gacPathsEnv.Length > 0) {
+ string[] gacPrefixes = gacPathsEnv.Split (Path.PathSeparator);
+ foreach (string gacPrefix in gacPrefixes) {
+ if (gacPrefix != null && gacPrefix.Length > 0) {
+ string gac = Path.Combine (Path.Combine (Path.Combine (gacPrefix, "lib"), "mono"), "gac");
+ if (Directory.Exists (gac) && !paths.Contains (gac))
+ paths.Add (gac);
+ }
+ }
+ }
+ return (string[]) paths.ToArray (typeof (String));
+ }
- string currentGac = GetCurrentGacPath ();
- if (currentGac == null)
+ AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
+ {
+ if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
return null;
if (OnMono ()) {
- string s = GetAssemblyFile (reference, currentGac);
- if (File.Exists (s))
- return AssemblyFactory.GetAssembly (s);
+ foreach (string gacpath in MonoGacPaths) {
+ string s = GetAssemblyFile (reference, gacpath);
+ if (File.Exists (s))
+ return AssemblyFactory.GetAssembly (s);
+ }
} else {
+ string currentGac = GetCurrentGacPath ();
+ if (currentGac == null)
+ return null;
+
string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"};
for (int i = 0; i < gacs.Length; i++) {
string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]);
+2009-08-17 Veerapuram Varadhan <vvaradhan@novell.com>
+
+ ** Fixes #381151 NRE
+ * Tds.cs (ProcessColumnInfo): Use Columns instead of creating a new list.
+ * TdsDataColumnCollection.cs (Clear, Add): New utility methods
+ * Tdsxx.cs: ProcessColumnInfo definition changes.
+
2009-07-25 Veerapuram Varadhan <vvaradhan@novell.com>
* Tds70.cs (ProcessColumnInfo): Update the new DataTypeName property.
}
}
}
-
+
private void SkipRow ()
{
SkipToColumnIndex (Columns.Count);
this.tdsVersion = tdsVersion;
this.packetSize = packetSize;
this.dataSource = dataSource;
+ this.columns = new TdsDataColumnCollection ();
comm = new TdsComm (dataSource, port, packetSize, timeout, tdsVersion);
}
}
}
- protected abstract TdsDataColumnCollection ProcessColumnInfo ();
+ protected abstract void ProcessColumnInfo ();
protected void ProcessColumnNames ()
{
database = newDB;
break;
case TdsEnvPacketSubType.CollationInfo:
+ //Console.WriteLine ("ProcessEnvironmentChange::Got collation info");
cLen = comm.GetByte ();
collation = comm.GetBytes (cLen, true);
lcid = TdsCollation.LCID (collation);
uint srvVersion = 0;
GetSubPacketLength ();
+ //Console.WriteLine ("ProcessLoginAck: B4 tdsVersion:{0}", tdsVersion);
// Valid only for a Login7 request
if (tdsVersion >= TdsVersion.tds70) {
comm.Skip (1);
tdsVersion = TdsVersion.tds90;
break;
}
+ //Console.WriteLine ("ProcessLoginAck: after tdsVersion:{0}", tdsVersion);
}
if (tdsVersion >= TdsVersion.tds70) {
case TdsPacketSubType.ColumnInfo: // TDS 4.2
case TdsPacketSubType.ColumnMetadata: // TDS 7.0
case TdsPacketSubType.RowFormat: // TDS 5.0
- columns = ProcessColumnInfo ();
+ Columns.Clear ();
+ ProcessColumnInfo ();
break;
case TdsPacketSubType.ColumnDetail:
ProcessColumnDetail ();
return IsConnected;
}
- protected override TdsDataColumnCollection ProcessColumnInfo ()
+ protected override void ProcessColumnInfo ()
{
byte precision;
byte scale;
int totalLength = Comm.GetTdsShort ();
int bytesRead = 0;
- TdsDataColumnCollection result = new TdsDataColumnCollection ();
-
while (bytesRead < totalLength) {
scale = 0;
precision = 0;
}
TdsDataColumn col = new TdsDataColumn ();
- int index = result.Add (col);
+ int index = Columns.Add (col);
#if NET_2_0
col.ColumnType = columnType;
col.ColumnSize = bufLength;
col["AllowDBNull"] = nullable;
#endif
}
-
- return result;
}
#endregion // Methods
return id;
}
- protected override TdsDataColumnCollection ProcessColumnInfo ()
+ protected override void ProcessColumnInfo ()
{
isSelectQuery = true;
- TdsDataColumnCollection result = new TdsDataColumnCollection ();
/*int totalLength = */Comm.GetTdsShort ();
int count = Comm.GetTdsShort ();
for (int i = 0; i < count; i += 1) {
Comm.Skip (Comm.GetTdsShort ()); // Class ID
TdsDataColumn col = new TdsDataColumn ();
- result.Add (col);
+ Columns.Add (col);
#if NET_2_0
col.ColumnType = columnType;
col.ColumnName = columnName;
col ["IsHidden"] = hidden;
#endif
}
- return result;
}
private void SendParamFormat ()
//Comm.Append (empty, 3, pad);
//byte[] version = {0x00, 0x0, 0x0, 0x71};
+ //Console.WriteLine ("Version: {0}", ClientVersion[3]);
Comm.Append (ClientVersion); // TDS Version 7
Comm.Append ((int)this.PacketSize); // Set the Block Size
Comm.Append (empty, 3, pad);
Comm.Append (param.Scale);
}
+
+ /* VARADHAN: TDS 8 Debugging */
/*
- * VARADHAN: TDS 8 Debugging *
if (Collation != null) {
Console.WriteLine ("Collation is not null");
Console.WriteLine ("Column Type: {0}", colType);
Console.WriteLine ("Collation bytes: {0} {1} {2} {3} {4}", Collation[0], Collation[1], Collation[2],
Collation[3], Collation[4]);
+ } else {
+ Console.WriteLine ("Collation is null");
}
*/
//return ColumnValues [0].ToString ();
}
- protected override TdsDataColumnCollection ProcessColumnInfo ()
+ protected override void ProcessColumnInfo ()
{
- TdsDataColumnCollection result = new TdsDataColumnCollection ();
int numColumns = Comm.GetTdsShort ();
for (int i = 0; i < numColumns; i += 1) {
byte[] flagData = new byte[4];
string columnName = Comm.GetString (Comm.GetByte ());
TdsDataColumn col = new TdsDataColumn ();
- result.Add (col);
+ Columns.Add (col);
#if NET_2_0
col.ColumnType = columnType;
col.ColumnName = columnName;
col ["DataTypeName"] = Enum.GetName (typeof (TdsColumnType), xColumnType);
#endif
}
- return result;
}
public override void Unprepare (string statementId)
public override bool Connect (TdsConnectionParameters connectionParameters)
{
+ //Console.WriteLine ("Tds80::Connect");
return base.Connect (connectionParameters);
}
- protected override TdsDataColumnCollection ProcessColumnInfo ()
+ protected override void ProcessColumnInfo ()
{
// We are connected to a Sql 7.0 server
- if (TdsVersion < TdsVersion.tds80)
- return base.ProcessColumnInfo ();
+ if (TdsVersion < TdsVersion.tds80) {
+ base.ProcessColumnInfo ();
+ return;
+ }
// VARADHAN: TDS 8 Debugging
//Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... entry");
- TdsDataColumnCollection result = new TdsDataColumnCollection ();
int numColumns = Comm.GetTdsShort ();
//Console.WriteLine ("Column count={0}", numColumns); TDS 8 Debugging
for (int i = 0; i < numColumns; i += 1) {
string columnName = Comm.GetString (Comm.GetByte ());
TdsDataColumn col = new TdsDataColumn ();
- result.Add (col);
+ Columns.Add (col);
#if NET_2_0
col.ColumnType = columnType;
col.ColumnName = columnName;
#endif
}
//Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... exit"); TDS 8 Debugging
- return result;
}
protected override void ProcessOutputParam ()
public virtual Tds CreateConnection (TdsConnectionInfo info)
{
+ //Console.WriteLine ("CreateConnection: TdsVersion:{0}", version);
switch (version)
{
case TdsVersion.tds42:
return index;
}
+ public void Add (TdsDataColumnCollection columns)
+ {
+ foreach (TdsDataColumn col in columns)
+ Add (col);
+ }
+
public IEnumerator GetEnumerator ()
{
return list.GetEnumerator ();
}
+ public void Clear ()
+ {
+ list.Clear ();
+ }
+
#endregion // Methods
}
}
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * System.Core.dll.sources : added a couple of sys.io.pipes files.
+
2009-07-20 Jb Evain <jbevain@novell.com>
* Makefile: filter the valid profile on the framework version,
--- /dev/null
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * SafePipeHandle.cs : initial code.
--- /dev/null
+//
+// SafePipeHandle.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+ public sealed class SafePipeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ public SafePipeHandle (IntPtr preexistingHandle, bool ownsHandle)
+ : base (ownsHandle)
+ {
+ handle = preexistingHandle;
+ }
+
+ protected override bool ReleaseHandle ()
+ {
+ try {
+ Marshal.FreeHGlobal (handle);
+ return true;
+ } catch (ArgumentException) {
+ return false;
+ }
+ }
+ }
+}
+
System.Threading/LockRecursionException.cs
System.Threading/LockRecursionPolicy.cs
System.Threading/ReaderWriterLockSlim.cs
+Microsoft.Win32.SafeHandles/SafePipeHandle.cs
+System.IO.Pipes/AnonymousPipeClientStream.cs
+System.IO.Pipes/AnonymousPipeServerStream.cs
+System.IO.Pipes/NamedPipeClientStream.cs
+System.IO.Pipes/NamedPipeServerStream.cs
+System.IO.Pipes/PipeAccessRights.cs
+System.IO.Pipes/PipeAccessRule.cs
+System.IO.Pipes/PipeAuditRule.cs
+System.IO.Pipes/PipeDirection.cs
+System.IO.Pipes/PipeInterfaces.cs
+System.IO.Pipes/PipeOptions.cs
+System.IO.Pipes/PipeSecurity.cs
+System.IO.Pipes/PipeStream.cs
+System.IO.Pipes/PipeStreamImpersonationWorker.cs
+System.IO.Pipes/PipeTransmissionMode.cs
+System.IO.Pipes/PipeUnix.cs
+System.IO.Pipes/PipeWin32.cs
+System.IO/HandleInheritability.cs
--- /dev/null
+//
+// AnonymousPipeClientStream.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ [MonoTODO ("Anonymous pipes are not working even on win32, due to some access authorization issue")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class AnonymousPipeClientStream : PipeStream
+ {
+ static SafePipeHandle ToSafePipeHandle (string pipeHandleAsString)
+ {
+ if (pipeHandleAsString == null)
+ throw new ArgumentNullException ("pipeHandleAsString");
+ // We use int64 for safety
+ return new SafePipeHandle (new IntPtr (long.Parse (pipeHandleAsString, NumberFormatInfo.InvariantInfo)), false);
+ }
+
+ //IAnonymousPipeClient impl;
+
+ public AnonymousPipeClientStream (string pipeHandleAsString)
+ : this (PipeDirection.In, pipeHandleAsString)
+ {
+ }
+
+ public AnonymousPipeClientStream (PipeDirection direction, string pipeHandleAsString)
+ : this (direction, ToSafePipeHandle (pipeHandleAsString))
+ {
+ }
+
+ public AnonymousPipeClientStream (PipeDirection direction,SafePipeHandle safePipeHandle)
+ : base (direction, DefaultBufferSize)
+ {
+ /*
+ if (IsWindows)
+ impl = new Win32AnonymousPipeClient (this, safePipeHandle);
+ else
+ impl = new UnixAnonymousPipeClient (this, safePipeHandle);
+ */
+
+ InitializeHandle (safePipeHandle, false, false);
+ IsConnected = true;
+ }
+
+ public override PipeTransmissionMode ReadMode {
+ set {
+ if (value == PipeTransmissionMode.Message)
+ throw new NotSupportedException ();
+ }
+ }
+
+ public override PipeTransmissionMode TransmissionMode {
+ get { return PipeTransmissionMode.Byte; }
+ }
+ }
+}
--- /dev/null
+//
+// AnonymousPipeServerStream.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ [MonoTODO ("Anonymous pipes are not working even on win32, due to some access authorization issue")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class AnonymousPipeServerStream : PipeStream
+ {
+ public AnonymousPipeServerStream ()
+ : this (PipeDirection.Out)
+ {
+ }
+
+ public AnonymousPipeServerStream (PipeDirection direction)
+ : this (direction, HandleInheritability.None)
+ {
+ }
+
+ public AnonymousPipeServerStream (PipeDirection direction, HandleInheritability inheritability)
+ : this (direction, inheritability, DefaultBufferSize)
+ {
+ }
+
+ public AnonymousPipeServerStream (PipeDirection direction, HandleInheritability inheritability, int bufferSize)
+ : this (direction, inheritability, bufferSize, null)
+ {
+ }
+
+ public AnonymousPipeServerStream (PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity)
+ : base (direction, bufferSize)
+ {
+ if (pipeSecurity != null)
+ throw ThrowACLException ();
+
+ if (direction == PipeDirection.InOut)
+ throw new NotSupportedException ("Anonymous pipe direction can only be either in or out.");
+
+ if (IsWindows)
+ impl = new Win32AnonymousPipeServer (this,direction, inheritability, bufferSize);
+ else
+ impl = new UnixAnonymousPipeServer (this,direction, inheritability, bufferSize);
+
+ InitializeHandle (impl.Handle, false, false);
+ IsConnected = true;
+ }
+
+ [MonoTODO]
+ public AnonymousPipeServerStream (PipeDirection direction, SafePipeHandle serverSafePipeHandle, SafePipeHandle clientSafePipeHandle)
+ : base (direction, DefaultBufferSize)
+ {
+ if (serverSafePipeHandle == null)
+ throw new ArgumentNullException ("serverSafePipeHandle");
+ if (clientSafePipeHandle == null)
+ throw new ArgumentNullException ("clientSafePipeHandle");
+
+ if (direction == PipeDirection.InOut)
+ throw new NotSupportedException ("Anonymous pipe direction can only be either in or out.");
+
+ if (IsWindows)
+ impl = new Win32AnonymousPipeServer (this, serverSafePipeHandle, clientSafePipeHandle);
+ else
+ impl = new UnixAnonymousPipeServer (this, serverSafePipeHandle, clientSafePipeHandle);
+
+ InitializeHandle (serverSafePipeHandle, true, false);
+ IsConnected = true;
+
+ ClientSafePipeHandle = clientSafePipeHandle;
+ }
+
+ IAnonymousPipeServer impl;
+
+ [MonoTODO]
+ public SafePipeHandle ClientSafePipeHandle { get; private set; }
+
+ public override PipeTransmissionMode ReadMode {
+ set {
+ if (value == PipeTransmissionMode.Message)
+ throw new NotSupportedException ();
+ }
+ }
+
+ public override PipeTransmissionMode TransmissionMode {
+ get { return PipeTransmissionMode.Byte; }
+ }
+
+ [MonoTODO]
+ public void DisposeLocalCopyOfClientHandle ()
+ {
+ impl.DisposeLocalCopyOfClientHandle ();
+ }
+
+ public string GetClientHandleAsString ()
+ {
+ // We use int64 for safety.
+ return impl.Handle.DangerousGetHandle ().ToInt64 ().ToString (NumberFormatInfo.InvariantInfo);
+ }
+ }
+}
--- /dev/null
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * AnonymousPipeClientStream.cs, AnonymousPipeServerStream.cs,
+ NamedPipeClientStream.cs, NamedPipeServerStream.cs
+ PipeAccessRights.cs, PipeAccessRule.cs, PipeAuditRule.cs,
+ PipeDirection.cs, PipeInterfaces.cs, PipeOptions.cs,
+ PipeSecurity.cs, PipeStream.cs, PipeStreamImpersonationWorker.cs,
+ PipeTransmissionMode.cs, PipeUnix.cs, PipeWin32.cs :
+ initial implementation, so far with win32 impl.
--- /dev/null
+//
+// NamedPipeClientStream.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+using System.Text;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ [MonoTODO ("working only on win32 right now")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class NamedPipeClientStream : PipeStream
+ {
+ public NamedPipeClientStream (string pipeName)
+ : this (".", pipeName)
+ {
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName)
+ : this (serverName, pipeName, PipeDirection.InOut)
+ {
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName, PipeDirection direction)
+ : this (serverName, pipeName, direction, PipeOptions.None)
+ {
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName, PipeDirection direction, PipeOptions options)
+ : this (serverName, pipeName, direction, options, TokenImpersonationLevel.None)
+ {
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel)
+ : this (serverName, pipeName, direction, options, impersonationLevel, HandleInheritability.None)
+ {
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability)
+ : this (serverName, pipeName, ToAccessRights (direction), options, impersonationLevel, inheritability)
+ {
+ }
+
+ public NamedPipeClientStream (PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle)
+ : base (direction, DefaultBufferSize)
+ {
+ if (IsWindows)
+ impl = new Win32NamedPipeClient (this, safePipeHandle);
+ else
+ impl = new UnixNamedPipeClient (this, safePipeHandle);
+ IsConnected = isConnected;
+ InitializeHandle (safePipeHandle, true, isAsync);
+ }
+
+ public NamedPipeClientStream (string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability)
+ : base (ToDirection (desiredAccessRights), DefaultBufferSize)
+ {
+ if (impersonationLevel != TokenImpersonationLevel.None ||
+ inheritability != HandleInheritability.None)
+ throw ThrowACLException ();
+
+ if (IsWindows)
+ impl = new Win32NamedPipeClient (this, serverName, pipeName, desiredAccessRights, options, inheritability);
+ else
+ impl = new UnixNamedPipeClient (this, serverName, pipeName, desiredAccessRights, options, inheritability);
+ }
+
+ INamedPipeClient impl;
+
+ public void Connect ()
+ {
+ impl.Connect ();
+ InitializeHandle (impl.Handle, false, impl.IsAsync);
+ IsConnected = true;
+ }
+
+ public void Connect (int timeout)
+ {
+ impl.Connect (timeout);
+ InitializeHandle (impl.Handle, false, impl.IsAsync);
+ IsConnected = true;
+ }
+
+ public int NumberOfServerInstances {
+ get {
+ CheckPipePropertyOperations ();
+ return impl.NumberOfServerInstances;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// NamedPipeServerStream.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.IO.Pipes
+{
+ [MonoTODO ("working only on win32 right now")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class NamedPipeServerStream : PipeStream
+ {
+ [MonoTODO]
+ public const int MaxAllowedServerInstances = 1;
+
+ public NamedPipeServerStream (string pipeName)
+ : this (pipeName, PipeDirection.InOut)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction)
+ : this (pipeName, direction, 1)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances)
+ : this (pipeName, direction, maxNumberOfServerInstances, PipeTransmissionMode.Byte)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode)
+ : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, PipeOptions.None)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options)
+ : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, DefaultBufferSize, DefaultBufferSize)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize)
+ : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, null)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity)
+ : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity, HandleInheritability.None)
+ {
+ }
+
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability)
+ : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity, inheritability, PipeAccessRights.ReadData | PipeAccessRights.WriteData)
+ {
+ }
+
+ [MonoTODO]
+ public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
+ : base (direction, transmissionMode, outBufferSize)
+ {
+ if (pipeSecurity != null)
+ throw ThrowACLException ();
+ var rights = ToAccessRights (direction) | additionalAccessRights;
+ // FIXME: reject some rights declarations (for ACL).
+
+ if (IsWindows)
+ impl = new Win32NamedPipeServer (this, pipeName, maxNumberOfServerInstances, transmissionMode, rights, options, inBufferSize, outBufferSize, inheritability);
+ else
+ impl = new UnixNamedPipeServer (this, pipeName, maxNumberOfServerInstances, transmissionMode, rights, options, inBufferSize, outBufferSize, inheritability);
+
+ InitializeHandle (impl.Handle, false, (options & PipeOptions.Asynchronous) != PipeOptions.None);
+ }
+
+ public NamedPipeServerStream (PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle)
+ : base (direction, DefaultBufferSize)
+ {
+ if (IsWindows)
+ impl = new Win32NamedPipeServer (this, safePipeHandle);
+ else
+ impl = new UnixNamedPipeServer (this, safePipeHandle);
+ IsConnected = isConnected;
+ InitializeHandle (safePipeHandle, true, isAsync);
+ }
+
+ INamedPipeServer impl;
+
+ public void Disconnect ()
+ {
+ impl.Disconnect ();
+ }
+
+ [MonoTODO]
+ [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)]
+ public void RunAsClient (PipeStreamImpersonationWorker impersonationWorker)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void WaitForConnection ()
+ {
+ impl.WaitForConnection ();
+ IsConnected = true;
+ }
+
+ [MonoTODO]
+ [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)]
+ public string GetImpersonationUserName ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ // async operations
+
+ Action wait_connect_delegate;
+
+ [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
+ public IAsyncResult BeginWaitForConnection (AsyncCallback callback, object state)
+ {
+ if (wait_connect_delegate == null)
+ wait_connect_delegate = new Action (WaitForConnection);
+ return wait_connect_delegate.BeginInvoke (callback, state);
+ }
+
+ public void EndWaitForConnection (IAsyncResult asyncResult)
+ {
+ wait_connect_delegate.EndInvoke (asyncResult);
+ }
+ }
+}
--- /dev/null
+namespace System.IO.Pipes
+{
+ [Flags]
+ public enum PipeAccessRights
+ {
+ // FIXME: values are not verified at all
+ ReadData = 1,
+ WriteData = 2,
+ ReadAttributes = 4,
+ WriteAttributes = 8,
+ ReadExtendedAttributes = 16,
+ WriteExtendedAttributes = 32,
+ CreateNewInstance = 64,
+ Delete = 128,
+ ReadPermissions = 256,
+ ChangePermissions = 512,
+ TakeOwnership = 1024,
+ Synchronize = 2048,
+ FullControl = ReadWrite | AccessSystemSecurity,
+ Read = ReadData | ReadAttributes | ReadExtendedAttributes | ReadPermissions,
+ Write = WriteData | WriteAttributes | WriteExtendedAttributes | ChangePermissions,
+ ReadWrite = Read | Write,
+ AccessSystemSecurity = ReadPermissions | ChangePermissions | TakeOwnership
+ }
+}
--- /dev/null
+//
+// PipeAccessRule.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.IO.Pipes
+{
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class PipeAccessRule : AccessRule
+ {
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAccessRule (IdentityReference identity, PipeAccessRights rights, AccessControlType type)
+ : base (identity, 0, false, InheritanceFlags.None, PropagationFlags.None, type)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAccessRule (string identity, PipeAccessRights rights, AccessControlType type)
+ : this ((IdentityReference) null, rights, type)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAccessRights PipeAccessRights { get; private set; }
+ }
+}
--- /dev/null
+//
+// PipeAuditRule.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.IO.Pipes
+{
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public sealed class PipeAuditRule : AuditRule
+ {
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAuditRule (IdentityReference identity, PipeAccessRights rights, AuditFlags flags)
+ : base (identity, 0, false, InheritanceFlags.None, PropagationFlags.None, flags)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAuditRule (string identity, PipeAccessRights rights, AuditFlags flags)
+ : this ((IdentityReference) null, rights, flags)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeAccessRights PipeAccessRights { get; private set; }
+ }
+}
--- /dev/null
+namespace System.IO.Pipes
+{
+ [Serializable]
+ public enum PipeDirection
+ {
+ In = 1,
+ Out = 2,
+ InOut = 3
+ }
+}
--- /dev/null
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ // Common interfaces
+
+ interface IPipe
+ {
+ SafePipeHandle Handle { get; }
+ void WaitForPipeDrain ();
+ }
+
+ interface IAnonymousPipeClient : IPipe
+ {
+ }
+
+ interface IAnonymousPipeServer : IPipe
+ {
+ SafePipeHandle ClientHandle { get; }
+ void DisposeLocalCopyOfClientHandle ();
+ }
+
+ interface INamedPipeClient : IPipe
+ {
+ void Connect ();
+ void Connect (int timeout);
+ int NumberOfServerInstances { get; }
+ bool IsAsync { get; }
+ }
+
+ interface INamedPipeServer : IPipe
+ {
+ void Disconnect ();
+ void WaitForConnection ();
+ }
+}
--- /dev/null
+namespace System.IO.Pipes
+{
+ [Serializable]
+ [Flags]
+ public enum PipeOptions
+ {
+ None = 0,
+ WriteThrough,
+ Asynchronous
+ }
+}
--- /dev/null
+//
+// PipeSecurity.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.IO.Pipes
+{
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public class PipeSecurity : NativeObjectSecurity
+ {
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeSecurity ()
+ : base (false, ResourceType.FileObject)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ public override Type AccessRightType {
+ get { return typeof (PipeAccessRights); }
+ }
+
+ public override Type AccessRuleType {
+ get { return typeof (PipeAccessRule); }
+ }
+
+ public override Type AuditRuleType {
+ get { return typeof (PipeAuditRule); }
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public override AccessRule AccessRuleFactory (IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void AddAccessRule (PipeAccessRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void AddAuditRule (PipeAuditRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public override sealed AuditRule AuditRuleFactory (IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
+ protected internal void Persist (SafeHandle handle)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ [SecurityPermission (SecurityAction.Assert, UnmanagedCode = true)]
+ protected internal void Persist (string name)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public bool RemoveAccessRule (PipeAccessRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void RemoveAccessRuleSpecific (PipeAccessRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public bool RemoveAuditRule (PipeAuditRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void RemoveAuditRuleAll (PipeAuditRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void RemoveAuditRuleSpecific (PipeAuditRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void ResetAccessRule (PipeAccessRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void SetAccessRule (PipeAccessRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void SetAuditRule (PipeAuditRule rule)
+ {
+ throw new NotImplementedException ("ACL is not supported in Mono");
+ }
+ }
+}
--- /dev/null
+//
+// PipeStream.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.IO.Pipes
+{
+ [PermissionSet (SecurityAction.InheritanceDemand, Name = "FullTrust")]
+ [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
+ public abstract class PipeStream : Stream
+ {
+ // FIXME: not precise.
+ internal const int DefaultBufferSize = 0x400;
+
+ internal static bool IsWindows {
+ get { return Win32Marshal.IsWindows; }
+ }
+
+ internal Exception ThrowACLException ()
+ {
+ return new NotImplementedException ("ACL is not supported in Mono");
+ }
+
+ internal static PipeAccessRights ToAccessRights (PipeDirection direction)
+ {
+ switch (direction) {
+ case PipeDirection.In:
+ return PipeAccessRights.ReadData;
+ case PipeDirection.Out:
+ return PipeAccessRights.WriteData;
+ case PipeDirection.InOut:
+ return PipeAccessRights.ReadData | PipeAccessRights.WriteData;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ internal static PipeDirection ToDirection (PipeAccessRights rights)
+ {
+ bool r = (rights & PipeAccessRights.ReadData) != 0;
+ bool w = (rights & PipeAccessRights.WriteData) != 0;
+ if (r) {
+ if (w)
+ return PipeDirection.InOut;
+ else
+ return PipeDirection.In;
+ } else {
+ if (w)
+ return PipeDirection.Out;
+ else
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ protected PipeStream (PipeDirection direction, int bufferSize)
+ : this (direction, PipeTransmissionMode.Byte, bufferSize)
+ {
+ }
+
+ protected PipeStream (PipeDirection direction, PipeTransmissionMode transmissionMode, int outBufferSize)
+ {
+ this.direction = direction;
+ this.transmission_mode = transmissionMode;
+ read_trans_mode = transmissionMode;
+ if (outBufferSize <= 0)
+ throw new ArgumentOutOfRangeException ("bufferSize must be greater than 0");
+ buffer_size = outBufferSize;
+ }
+
+ PipeDirection direction;
+ PipeTransmissionMode transmission_mode, read_trans_mode;
+ int buffer_size;
+ SafePipeHandle handle;
+ FileStream stream;
+
+ public override bool CanRead {
+ get { return (direction & PipeDirection.In) != 0; }
+ }
+
+ public override bool CanSeek {
+ get { return false; }
+ }
+
+ public override bool CanWrite {
+ get { return (direction & PipeDirection.Out) != 0; }
+ }
+
+ public virtual int InBufferSize {
+ get { return buffer_size; }
+ }
+
+ public bool IsAsync { get; private set; }
+
+ public bool IsConnected { get; protected set; }
+
+ private Stream Stream {
+ get {
+ if (!IsConnected)
+ throw new InvalidOperationException ("Pipe is not connected");
+ if (stream == null)
+ stream = new FileStream (handle.DangerousGetHandle (), CanRead ? (CanWrite ? FileAccess.ReadWrite : FileAccess.Read) : FileAccess.Write, true, buffer_size, IsAsync);
+ return stream;
+ }
+ }
+
+ protected bool IsHandleExposed { get; private set; }
+
+ [MonoTODO]
+ public bool IsMessageComplete { get; private set; }
+
+ [MonoTODO]
+ public virtual int OutBufferSize {
+ get { return buffer_size; }
+ }
+
+ public virtual PipeTransmissionMode ReadMode {
+ get {
+ CheckPipePropertyOperations ();
+ return read_trans_mode;
+ }
+ set {
+ CheckPipePropertyOperations ();
+ read_trans_mode = value;
+ }
+ }
+
+ public SafePipeHandle SafePipeHandle {
+ get {
+ CheckPipePropertyOperations ();
+ return handle;
+ }
+ }
+
+ public virtual PipeTransmissionMode TransmissionMode {
+ get {
+ CheckPipePropertyOperations ();
+ return transmission_mode;
+ }
+ }
+
+ // initialize/dispose/state check
+
+ [MonoTODO]
+ protected internal virtual void CheckPipePropertyOperations ()
+ {
+ }
+
+ [MonoTODO]
+ protected internal void CheckReadOperations ()
+ {
+ if (!IsConnected)
+ throw new InvalidOperationException ("Pipe is not connected");
+ if (!CanRead)
+ throw new NotSupportedException ("The pipe stream does not support read operations");
+ }
+
+ [MonoTODO]
+ protected internal void CheckWriteOperations ()
+ {
+ if (!IsConnected)
+ throw new InvalidOperationException ("Pipe us not connected");
+ if (!CanWrite)
+ throw new NotSupportedException ("The pipe stream does not support write operations");
+ }
+
+ protected void InitializeHandle (SafePipeHandle handle, bool isExposed, bool isAsync)
+ {
+ this.handle = handle;
+ this.IsHandleExposed = isExposed;
+ this.IsAsync = isAsync;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (handle != null && disposing)
+ handle.Dispose ();
+ }
+
+ // not supported
+
+ public override long Length {
+ get { throw new NotSupportedException (); }
+ }
+
+ public override long Position {
+ get { return 0; }
+ set { throw new NotSupportedException (); }
+ }
+
+ public override void SetLength (long value)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException ();
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public PipeSecurity GetAccessControl ()
+ {
+ throw ThrowACLException ();
+ }
+
+ [MonoNotSupported ("ACL is not supported in Mono")]
+ public void SetAccessControl (PipeSecurity pipeSecurity)
+ {
+ throw ThrowACLException ();
+ }
+
+ // pipe I/O
+
+ public void WaitForPipeDrain ()
+ {
+ }
+
+ [MonoTODO]
+ public override int Read (byte [] buffer, int offset, int count)
+ {
+ CheckReadOperations ();
+
+ return Stream.Read (buffer, offset, count);
+ }
+
+ [MonoTODO]
+ public override int ReadByte ()
+ {
+ CheckReadOperations ();
+
+ return Stream.ReadByte ();
+ }
+
+ [MonoTODO]
+ public override void Write (byte [] buffer, int offset, int count)
+ {
+ CheckWriteOperations ();
+
+ Stream.Write (buffer, offset, count);
+ }
+
+ [MonoTODO]
+ public override void WriteByte (byte value)
+ {
+ CheckWriteOperations ();
+
+ Stream.WriteByte (value);
+ }
+
+ [MonoTODO]
+ public override void Flush ()
+ {
+ CheckWriteOperations ();
+
+ Stream.Flush ();
+ }
+
+ // async
+
+ Func<byte [],int,int,int> read_delegate;
+
+ [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
+ public override IAsyncResult BeginRead (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (read_delegate == null)
+ read_delegate = new Func<byte[],int,int,int> (Read);
+ return read_delegate.BeginInvoke (buffer, offset, count, callback, state);
+ }
+
+ Action<byte[],int,int> write_delegate;
+
+ [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
+ public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (write_delegate == null)
+ write_delegate = new Action<byte[],int,int> (Write);
+ return write_delegate.BeginInvoke (buffer, offset, count, callback, state);
+ }
+
+ public override int EndRead (IAsyncResult asyncResult)
+ {
+ return read_delegate.EndInvoke (asyncResult);
+ }
+
+ public override void EndWrite (IAsyncResult asyncResult)
+ {
+ write_delegate.EndInvoke (asyncResult);
+ }
+ }
+}
--- /dev/null
+namespace System.IO.Pipes
+{
+ public delegate void PipeStreamImpersonationWorker ();
+}
--- /dev/null
+namespace System.IO.Pipes
+{
+ [Serializable]
+ public enum PipeTransmissionMode
+ {
+ Byte,
+ Message
+ }
+}
--- /dev/null
+//
+// PipeUnix.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+using System.Text;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ abstract class UnixAnonymousPipe : IPipe
+ {
+ protected UnixAnonymousPipe ()
+ {
+ }
+
+ public abstract SafePipeHandle Handle { get; }
+
+ public void WaitForPipeDrain ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ class UnixAnonymousPipeClient : UnixAnonymousPipe, IAnonymousPipeClient
+ {
+ // AnonymousPipeClientStream owner;
+
+ public UnixAnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
+ {
+ // this.owner = owner;
+
+ this.handle = handle;
+ }
+
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+ }
+
+ class UnixAnonymousPipeServer : UnixAnonymousPipe, IAnonymousPipeServer
+ {
+ // AnonymousPipeServerStream owner;
+
+ public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
+ {
+ // this.owner = owner;
+
+ throw new NotImplementedException ();
+ }
+
+ public UnixAnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
+ {
+ // this.owner = owner;
+
+ this.server_handle = serverHandle;
+ this.client_handle = clientHandle;
+
+ throw new NotImplementedException ();
+ }
+
+ SafePipeHandle server_handle, client_handle;
+
+ public override SafePipeHandle Handle {
+ get { return server_handle; }
+ }
+
+ public SafePipeHandle ClientHandle {
+ get { return client_handle; }
+ }
+
+ public void DisposeLocalCopyOfClientHandle ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ abstract class UnixNamedPipe : IPipe
+ {
+ public abstract SafePipeHandle Handle { get; }
+
+ public void WaitForPipeDrain ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ class UnixNamedPipeClient : UnixNamedPipe, INamedPipeClient
+ {
+ // .ctor with existing handle
+ public UnixNamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
+ {
+ throw new NotImplementedException ();
+ }
+
+ // .ctor without handle - create new
+ public UnixNamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
+ {
+ throw new NotImplementedException ();
+ }
+
+ bool is_async;
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+
+ public void Connect ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Connect (int timeout)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool IsAsync {
+ get { return is_async; }
+ }
+
+ public int NumberOfServerInstances {
+ get { throw new NotImplementedException (); }
+ }
+ }
+
+ class UnixNamedPipeServer : UnixNamedPipe, INamedPipeServer
+ {
+ //NamedPipeServerStream owner;
+
+ // .ctor with existing handle
+ public UnixNamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
+ {
+ this.handle = safePipeHandle;
+ //this.owner = owner;
+ }
+
+ // .ctor without handle - create new
+ public UnixNamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability)
+ {
+ throw new NotImplementedException ();
+ }
+
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+
+ public void Disconnect ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void WaitForConnection ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
--- /dev/null
+//
+// PipeWin32.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.AccessControl;
+using System.Security.Permissions;
+using System.Security.Principal;
+using System.Text;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.IO.Pipes
+{
+ abstract class Win32AnonymousPipe : IPipe
+ {
+ protected Win32AnonymousPipe ()
+ {
+ }
+
+ public abstract SafePipeHandle Handle { get; }
+
+ public void WaitForPipeDrain ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ class Win32AnonymousPipeClient : Win32AnonymousPipe, IAnonymousPipeClient
+ {
+ // AnonymousPipeClientStream owner;
+
+ public Win32AnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
+ {
+ // this.owner = owner;
+
+ this.handle = handle;
+ }
+
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+ }
+
+ class Win32AnonymousPipeServer : Win32AnonymousPipe, IAnonymousPipeServer
+ {
+ // AnonymousPipeServerStream owner;
+
+ public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
+ {
+ IntPtr r, w;
+ SecurityAttributesHack att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
+ if (!Win32Marshal.CreatePipe (out r, out w, ref att, bufferSize))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+
+ var rh = new SafePipeHandle (r, true);
+ var wh = new SafePipeHandle (w, true);
+
+ if (direction == PipeDirection.Out) {
+ server_handle = wh;
+ client_handle = rh;
+ } else {
+ server_handle = rh;
+ client_handle = wh;
+ }
+ }
+
+ public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
+ {
+ // this.owner = owner;
+ this.server_handle = serverHandle;
+ this.client_handle = clientHandle;
+ }
+
+ SafePipeHandle server_handle, client_handle;
+
+ public override SafePipeHandle Handle {
+ get { return server_handle; }
+ }
+
+ public SafePipeHandle ClientHandle {
+ get { return client_handle; }
+ }
+
+ public void DisposeLocalCopyOfClientHandle ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ abstract class Win32NamedPipe : IPipe
+ {
+ string name_cache;
+
+ public string Name {
+ get {
+ if (name_cache != null)
+ return name_cache;
+
+ int s, c, m, t;
+ byte [] un = new byte [200];
+ while (true) {
+ if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, un.Length)) {
+ var xxx = Marshal.GetLastWin32Error ();
+ throw new Win32Exception (xxx);
+ }
+ if (un [un.Length - 1] == 0)
+ break;
+ un = new byte [un.Length * 10];
+ }
+ name_cache = Encoding.Default.GetString (un);
+ return name_cache;
+ }
+ }
+
+ public abstract SafePipeHandle Handle { get; }
+
+ public void WaitForPipeDrain ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ class Win32NamedPipeClient : Win32NamedPipe, INamedPipeClient
+ {
+ NamedPipeClientStream owner;
+
+ // .ctor with existing handle
+ public Win32NamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
+ {
+ this.handle = safePipeHandle;
+ this.owner = owner;
+
+ // FIXME: retrieve is_async from state?
+ }
+
+ // .ctor without handle - create new
+ public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
+ {
+ name = String.Format ("\\\\{0}\\pipe\\{1}", serverName, pipeName);
+ var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
+ is_async = (options & PipeOptions.Asynchronous) != PipeOptions.None;
+
+ opener = delegate {
+ var ret = Win32Marshal.CreateFile (name, desiredAccessRights, 0, ref att, 3, 0, IntPtr.Zero);
+ if (ret == new IntPtr (-1L))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+
+ return new SafePipeHandle (ret, true);
+ };
+ this.owner = owner;
+ }
+
+ Func<SafePipeHandle> opener;
+ bool is_async;
+ string name;
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+
+ public bool IsAsync {
+ get { return is_async; }
+ }
+
+ public void Connect ()
+ {
+ if (owner.IsConnected)
+ throw new InvalidOperationException ("The named pipe is already connected");
+
+ handle = opener ();
+ }
+
+ public void Connect (int timeout)
+ {
+ if (owner.IsConnected)
+ throw new InvalidOperationException ("The named pipe is already connected");
+
+ if (!Win32Marshal.WaitNamedPipe (name, timeout))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+ Connect ();
+ }
+
+ public int NumberOfServerInstances {
+ get {
+ int s, c, m, t;
+ byte [] un = null;
+ if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, 0))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+ return c;
+ }
+ }
+ }
+
+ class Win32NamedPipeServer : Win32NamedPipe, INamedPipeServer
+ {
+ //NamedPipeServerStream owner;
+
+ // .ctor with existing handle
+ public Win32NamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
+ {
+ handle = safePipeHandle;
+ //this.owner = owner;
+ }
+
+ // .ctor without handle - create new
+ public Win32NamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability)
+ {
+ string name = String.Format ("\\\\.\\pipe\\{0}", pipeName);
+
+ uint openMode = 0;
+ if ((rights & PipeAccessRights.ReadData) != 0)
+ openMode |= 1;
+ if ((rights & PipeAccessRights.WriteData) != 0)
+ openMode |= 2;
+ if ((options & PipeOptions.WriteThrough) != 0)
+ openMode |= 0x80000000;
+ int pipeMode = 0;
+ if ((owner.TransmissionMode & PipeTransmissionMode.Message) != 0)
+ pipeMode |= 4;
+ //if ((readTransmissionMode & PipeTransmissionMode.Message) != 0)
+ // pipeMode |= 2;
+ if ((options & PipeOptions.Asynchronous) != 0)
+ pipeMode |= 1;
+
+ // FIXME: is nDefaultTimeout = 0 ok?
+ var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
+ var ret = Win32Marshal.CreateNamedPipe (name, openMode, pipeMode, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref att, IntPtr.Zero);
+ if (ret == new IntPtr (-1L))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+ handle = new SafePipeHandle (ret, true);
+ }
+
+ SafePipeHandle handle;
+
+ public override SafePipeHandle Handle {
+ get { return handle; }
+ }
+
+ public void Disconnect ()
+ {
+ Win32Marshal.DisconnectNamedPipe (Handle);
+ }
+
+ public void WaitForConnection ()
+ {
+ if (!Win32Marshal.ConnectNamedPipe (Handle, IntPtr.Zero))
+ throw new Win32Exception (Marshal.GetLastWin32Error ());
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct SecurityAttributesHack
+ {
+ public readonly int Length;
+ public readonly IntPtr SecurityDescriptor;
+ public readonly bool Inheritable;
+
+ public SecurityAttributesHack (bool inheritable)
+ {
+ Length = 0;
+ SecurityDescriptor = IntPtr.Zero;
+ Inheritable = inheritable;
+ }
+ }
+
+ static class Win32Marshal
+ {
+ internal static bool IsWindows {
+ get {
+ switch (Environment.OSVersion.Platform) {
+ case PlatformID.Win32S:
+ case PlatformID.Win32Windows:
+ case PlatformID.Win32NT:
+ case PlatformID.WinCE:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ // http://msdn.microsoft.com/en-us/library/aa365152%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern bool CreatePipe (out IntPtr readHandle, out IntPtr writeHandle, ref SecurityAttributesHack pipeAtts, int size);
+
+ // http://msdn.microsoft.com/en-us/library/aa365150%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern IntPtr CreateNamedPipe (string name, uint openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SecurityAttributesHack securityAttributes, IntPtr atts);
+
+ // http://msdn.microsoft.com/en-us/library/aa365146%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern bool ConnectNamedPipe (SafePipeHandle handle, IntPtr overlapped);
+
+ // http://msdn.microsoft.com/en-us/library/aa365166%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern bool DisconnectNamedPipe (SafePipeHandle handle);
+
+ // http://msdn.microsoft.com/en-us/library/aa365443%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern bool GetNamedPipeHandleState (SafePipeHandle handle, out int state, out int curInstances, out int maxCollectionCount, out int collectDateTimeout, byte [] userName, int maxUserNameSize);
+
+ // http://msdn.microsoft.com/en-us/library/aa365800%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern bool WaitNamedPipe (string name, int timeout);
+
+ // http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
+ [DllImport ("kernel32")]
+ internal static extern IntPtr CreateFile (string name, PipeAccessRights desiredAccess, FileShare fileShare, ref SecurityAttributesHack atts, int creationDisposition, int flags, IntPtr templateHandle);
+
+ }
+}
--- /dev/null
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * HandleInheritability.cs : initial code.
--- /dev/null
+namespace System.IO
+{
+ public enum HandleInheritability
+ {
+ None,
+ Inheritable
+ }
+}
+2009-08-17 Veerapuram Varadhan <vvaradhan@novell.com>
+
+ * System.Data_test.dll.sources: Added
+ Mono.Data.SqlExpressions/DateComparisonTest.cs.
+
2009-07-15 Veerapuram Varadhan <vvaradhan@novell.com>
* System.Data.dll.sources: Added TableAdapterSchemaInfo.cs.
+2009-07-23 Adam Wendt <adam@awendtconsulting.com>
+
+ * Comparison.cs (Compare): Parse string if other object is DateTime
+ regardless of which side the DateTime is on.
+
2008-08-18 Marek Habersack <mhabersack@novell.com>
* Numeric.cs: Max/Min operations do not convert string
if (o1 is DateTime && o2 is string && Thread.CurrentThread.CurrentCulture != CultureInfo.InvariantCulture) {
// DateTime is always CultureInfo.InvariantCulture
o2 = (IComparable) DateTime.Parse ((string)o2, CultureInfo.InvariantCulture);
+ } else if (o2 is DateTime && o1 is string &&
+ Thread.CurrentThread.CurrentCulture != CultureInfo.InvariantCulture) {
+ // DateTime is always CultureInfo.InvariantCulture
+ o1 = (IComparable) DateTime.Parse ((string)o1, CultureInfo.InvariantCulture);
}
if (o1.GetType () != o2.GetType ())
+2009-08-17 Veerapuram Varadhan <vvaradhan@novell.com>
+
+ ** Fixes #525306
+ * SqlConnection.cs (Open): Use Tds80 also in case of non-pooling
+ connections.
+
2009-08-01 Gert Driesen <drieseng@users.sourceforge.net>
* SqlParameter.cs (ConvertToFrameworkType): Only wrap FormatException
if (!pooling) {
if(!ParseDataSource (dataSource, out port, out serverName))
throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
- tds = new Tds70 (serverName, port, PacketSize, ConnectionTimeout);
+ tds = new Tds80 (serverName, port, PacketSize, ConnectionTimeout);
tds.Pooling = false;
}
else {
System.Data.SqlClient/SqlDataAdapterTest.cs
System.Data.SqlClient/SqlParameterTest.cs
Mono.Data.SqlExpressions/DataColumnExpressionTest.cs
+Mono.Data.SqlExpressions/DateComparisonTest.cs
+
+2009-08-18 Veerapuram Varadhan <vvaradhan@novell.com>
+
+ * DateComparisonTest.cs: Fix test-data xml path.
+
+2009-07-23 Adam Wendt <adam@awendtconsulting.com>
+
+ * DateComparisonTest.cs
+ (TestDateComparisonRight, TestDateComparisonLeft): Test case to
+ check that comparison of date and string works regardless of which
+ side the existing date is.
+
2007-06-06 Nagappan A <anagappan@novell.com>
* DataColumnExpressionTest.cs (DataColumnCharTest): Test case to
--- /dev/null
+using System;
+using System.Data;
+using NUnit.Framework;
+
+namespace Monotests_Mono.Data.SqlExpressions
+{
+ [TestFixture]
+ public class DateComparisonTest
+ {
+ private DataSet dataSet;
+
+ [SetUp]
+ public void SetUp()
+ {
+ dataSet = new DataSet();
+ dataSet.ReadXml("Test/Mono.Data.SqlExpressions/dateComparisonTest.xml",
+ XmlReadMode.InferSchema);
+ }
+
+ [Test]
+ public void TestDateComparisonRight()
+ {
+ DataView dataView = new DataView(dataSet.Tables["thing"], "#2009-07-19 00:01:00# = start", "", DataViewRowState.CurrentRows);
+ Assert.AreEqual (1, dataView.Count);
+ }
+
+ [Test]
+ public void TestDateComparisonLeft()
+ {
+ DataView dataView = new DataView(dataSet.Tables["thing"], "start = #2009-07-19 00:01:00#", "", DataViewRowState.CurrentRows);
+ Assert.AreEqual (1, dataView.Count);
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<things>
+<thing>
+ <title>bar</title>
+ <start>2009-07-19 00:01</start>
+</thing>
+<thing>
+ <title>foo</title>
+ <start>2009-08-19 00:01</start>
+</thing>
+</things>
+2009-08-11 Gert Driesen <drieseng@users.sourceforge.net>
+
+ * sqlserver7.sql: Added script for SQL Server 7.0, with unicode
+ encoding (as isql7 does not deal well with utf-8).
+
2008-12-31 Gert Driesen <drieseng@users.sourceforge.net>
* MySQL_5.sql: Added numeric and decimal colums with different
+2009-08-13 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Makefile : update profile check.
+
2008-06-10 Atsushi Enomoto <atsushi@ximian.com>
* System.Json.dll.sources, Makefile : initial checkin.
EXTRA_DISTFILES =
-ifneq (net_2_1, $(PROFILE))
+VALID_PROFILE := $(filter 2.1 4.0, $(FRAMEWORK_VERSION))
+ifndef VALID_PROFILE
LIBRARY_NAME = dummy-System.Json.dll
NO_INSTALL = yes
NO_SIGN_ASSEMBLY = yes
+2009-08-17 Sebastien Pouliot <sebastien@ximian.com>
+
+ * net_2_1_raw_System.Net.dll.sources: Add some existing System.dll
+ files required for SL3 and some new files.
+
2009-07-20 Jb Evain <jbevain@novell.com>
* Makefile: filter the valid profile on the framework version,
--- /dev/null
+2009-08-17 Sebastien Pouliot <sebastien@ximian.com>
+
+ * NetworkChange_2_1.cs: New. Minimal SL3 version
+ * NetworkInterface_2_1.cs: New. Minimal SL3 version
+
--- /dev/null
+//
+// System.Net.NetworkInformation.NetworkChange
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2006, 2009 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_1
+namespace System.Net.NetworkInformation {
+ public abstract class NetworkChange {
+ protected NetworkChange ()
+ {
+ }
+
+ // Disable the warnings about the events not being used.
+#pragma warning disable 67
+ public static event NetworkAddressChangedEventHandler NetworkAddressChanged;
+#pragma warning restore
+ }
+}
+#endif
+
--- /dev/null
+//
+// System.Net.NetworkInformation.NetworkInterface
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+// Atsushi Enomoto (atsushi@ximian.com)
+// Miguel de Icaza (miguel@novell.com)
+// Eric Butler (eric@extremeboredom.net)
+// Marek Habersack (mhabersack@novell.com)
+//
+// Copyright (c) 2006-2009 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_1
+
+namespace System.Net.NetworkInformation {
+
+ public abstract class NetworkInterface {
+
+ protected NetworkInterface ()
+ {
+ }
+
+ [MonoTODO("Always returns true")]
+ public static bool GetIsNetworkAvailable ()
+ {
+ return true;
+ }
+ }
+}
+
+#endif
+
System.Net.Sockets/ProtocolType_2_1.cs
System.Net.Sockets/SocketAsyncOperation_2_1.cs
System.Net.Sockets/SocketType_2_1.cs
+System.Net.NetworkInformation/NetworkChange_2_1.cs
+System.Net.NetworkInformation/NetworkInterface_2_1.cs
+../System/System.Net/Cookie.cs
+../System/System.Net/CookieCollection.cs
+../System/System.Net/CookieContainer.cs
+../System/System.Net/CookieException.cs
../System/System.Net/Dns.cs
../System/System.Net/EndPoint.cs
../System/System.Net/HttpRequestHeader.cs
../System/System.Net/HttpResponseHeader.cs
+../System/System.Net/ICredentialLookup.cs
../System/System.Net/IPAddress.cs
../System/System.Net/IPEndPoint.cs
../System/System.Net/IPHostEntry.cs
../System/System.Net/IPv6Address.cs
../System/System.Net/IWebRequestCreate.cs
+../System/System.Net/NetworkCredential.cs
../System/System.Net/ProtocolViolationException.cs
../System/System.Net/SocketAddress.cs
../System/System.Net.Sockets/LingerOption.cs
../System/System.Net/UploadProgressChangedEventHandler.cs
../System/System.Net/UploadStringCompletedEventArgs.cs
../System/System.Net/UploadStringCompletedEventHandler.cs
+../System/System.Net.NetworkInformation/NetworkAddressChangedEventHandler.cs
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * WebChannelFactory.cs : added missing constructors.
+
2009-07-28 Atsushi Enomoto <atsushi@ximian.com>
* OutgoingWebRequestContext.cs : implement.
}
public WebChannelFactory (Uri remoteAddress)
- : base ()
+ : this (String.Empty, remoteAddress)
{
- Endpoint.Address = new EndpointAddress (remoteAddress);
}
- public WebChannelFactory (string configurationName, Uri remoteAddress)
- : this (configurationName)
+ public WebChannelFactory (string endpointConfigurationName, Uri remoteAddress)
+ : base (endpointConfigurationName)
{
Endpoint.Address = new EndpointAddress (remoteAddress);
}
public WebChannelFactory (Binding binding, Uri remoteAddress)
- : this (new ServiceEndpoint (ContractDescription.GetContract (typeof (TChannel)), binding, new EndpointAddress (remoteAddress)))
+ : base (binding, new EndpointAddress (remoteAddress))
{
}
+2009-08-11 Astushi Enomoto <atsushi@ximian.com>
+
+ * System.ServiceModel.dll.sources: add DefaultOperationInvoker.cs.
+
2009-08-07 Astushi Enomoto <atsushi@ximian.com>
* System.ServiceModel.dll.sources: add ServiceProxyGenerator.cs.
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
-// Copyright (C) 2005 Novell, Inc. http://www.novell.com
+// Copyright (C) 2005,2009 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
//
using System;
using System.Collections.ObjectModel;
+using System.IO;
using System.Runtime.Serialization;
using System.Xml;
OnWriteBodyContents (writer);
}
- [MonoTODO]
+ [MonoTODO ("use maxBufferSize somewhere")]
protected virtual BodyWriter OnCreateBufferedCopy (
int maxBufferSize)
{
- throw new NotImplementedException ();
+ var s = new XmlWriterSettings ();
+ s.OmitXmlDeclaration = true;
+ s.ConformanceLevel = ConformanceLevel.Auto;
+ StringWriter sw = new StringWriter ();
+ using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw, s)))
+ WriteBodyContents (w);
+ return new XmlReaderBodyWriter (sw.ToString ());
}
- [MonoTODO]
protected abstract void OnWriteBodyContents (
XmlDictionaryWriter writer);
}
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Message.cs, MessageImpl.cs, BodyWriter.cs :
+ Implement BodyWriter.OnCreateBufferedCopy() and use it.
+
+2009-08-18 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ReplyChannelBase.cs : initialize field.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ReplyChannelBase.cs, DuplexChannelBase.cs, RequestChannelBase.cs:
+ implement GetProperty<T>() and return its channel manager.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * PeerDuplexChannel.cs : ongoing implementation. Fix wrong peer
+ destination address in Connect() request. To repeat sending
+ request, use buffered copy. Set some peer-channel specific
+ header items. (todo: and consume them.)
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Message.cs : state is set only after WriteBodyContents().
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageHeaders.cs : eliminate wrong use of
+ ReadElementContentAsString() (it is not always simple string).
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageHeaders.cs : when the value is null, do not try to
+ deserialize EndpointAddress.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageHeader.cs : add Value property. (Forgot dependent change.)
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageHeaders.cs : GetHeader<T>() could mostly skip extra
+ serialization and deserialization of values.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * PeerDuplexChannel.cs : handle Welcome and Refuse at client side.
+ Now simply use connector contract.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * PeerDuplexChannel.cs : handle Disconnect(). Fix URLs a bit.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * TcpChannelListener.cs : do not try to compare dead connection's
+ IPEndPoint (it raises an error).
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageHeaders.cs : allow null header value on each specific setter.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DuplexChannelBase.cs, TcpDuplexSessionChannel.cs :
+ get local and remote address of connected counterpart to get
+ callback channel connected.
+ * PeerDuplexChannel.cs : remove FIXME wrt above.
+
2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
* PeerDuplexChannel.cs : add fixme comment and remove extra FIXME.
{
internal abstract class DuplexChannelBase : ChannelBase, IDuplexChannel
{
- //ChannelFactoryBase channel_factory_base;
- //ChannelListenerBase channel_listener_base;
+ ChannelFactoryBase channel_factory_base;
+ ChannelListenerBase channel_listener_base;
EndpointAddress local_address;
EndpointAddress remote_address;
Uri via;
public DuplexChannelBase (ChannelFactoryBase factory, EndpointAddress remoteAddress, Uri via) : base (factory)
{
- //channel_factory_base = factory;
+ channel_factory_base = factory;
remote_address = remoteAddress;
this.via = via;
SetupDelegates ();
public DuplexChannelBase (ChannelListenerBase listener) : base (listener)
{
- //channel_listener_base = listener;
+ channel_listener_base = listener;
local_address = new EndpointAddress (listener.Uri);
SetupDelegates ();
}
- public EndpointAddress LocalAddress {
+ public virtual EndpointAddress LocalAddress {
get { return local_address; }
}
- public EndpointAddress RemoteAddress {
+ public virtual EndpointAddress RemoteAddress {
get { return remote_address; }
}
try_receive_handler = new TryReceiveHandler (TryReceive);
}
+ public override T GetProperty<T> ()
+ {
+ if (typeof (T) == typeof (IChannelFactory))
+ return (T) (object) channel_factory_base;
+ if (typeof (T) == typeof (IChannelListener))
+ return (T) (object) channel_listener_base;
+ return base.GetProperty<T> ();
+ }
+
// Open
Action<TimeSpan> open_handler;
OnWriteBodyContents (writer);
else if (Version.Envelope == EnvelopeVersion.None)
WriteXsiNil (writer);
+ State = MessageState.Written;
}
public void WriteMessage (XmlDictionaryWriter writer)
{
if (State != MessageState.Created)
throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
- State = MessageState.Written;
OnWriteMessage (writer);
}
public void WriteStartBody (XmlDictionaryWriter writer)
{
- if (State != MessageState.Created && State != MessageState.Written)
+ if (State != MessageState.Created)
throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
- State = MessageState.Written;
OnWriteStartBody (writer);
}
public void WriteStartEnvelope (XmlDictionaryWriter writer)
{
- if (State != MessageState.Created && State != MessageState.Written)
+ if (State != MessageState.Created)
throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
- State = MessageState.Written;
OnWriteStartEnvelope (writer);
}
{
}
+ [MonoTODO ("use maxBufferSize")]
protected virtual MessageBuffer OnCreateBufferedCopy (
int maxBufferSize)
{
this.formatter.WriteObjectContent (writer, value);
}
+ public object Value { get { return value; } }
+
public override string Actor { get { return actor; }}
public override bool IsReferenceParameter { get { return is_ref; }}
public T GetHeader<T> (int index)
{
+ if (l.Count <= index)
+ throw new ArgumentOutOfRangeException ("index");
+ var dmh = l [index] as MessageHeader.DefaultMessageHeader;
+ if (dmh != null && dmh.Value != null && typeof (T).IsAssignableFrom (dmh.Value.GetType ()))
+ return (T) dmh.Value;
if (typeof (T) == typeof (EndpointAddress)) {
XmlDictionaryReader r = GetReaderAtHeader (index);
- return (T) (object) new EndpointAddress (r.ReadElementContentAsString ());
+ return r.NodeType != XmlNodeType.Element ? default (T) : (T) (object) EndpointAddress.ReadFrom (r);
}
else
return GetHeader<T> (index, GetSerializer<T> (index));
}
set {
RemoveAll ("Action", version.Addressing.Namespace);
- Add (MessageHeader.CreateHeader ("Action", version.Addressing.Namespace, value, true));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("Action", version.Addressing.Namespace, value, true));
}
}
throw new InvalidOperationException ("WS-Addressing header is not allowed for AddressingVersion.None");
RemoveAll ("FaultTo", Constants.WSA1);
- Add (MessageHeader.CreateHeader (
- "FaultTo",
- Constants.WSA1,
- EndpointAddress10.FromEndpointAddress (value)));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("FaultTo", Constants.WSA1, EndpointAddress10.FromEndpointAddress (value)));
}
}
throw new InvalidOperationException ("WS-Addressing header is not allowed for AddressingVersion.None");
RemoveAll ("From", Constants.WSA1);
- Add (MessageHeader.CreateHeader (
- "From",
- Constants.WSA1,
- EndpointAddress10.FromEndpointAddress (value)));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("From", Constants.WSA1, EndpointAddress10.FromEndpointAddress (value)));
}
}
#endif
throw new InvalidOperationException ("WS-Addressing header is not allowed for AddressingVersion.None");
RemoveAll ("MessageID", Constants.WSA1);
- Add (MessageHeader.CreateHeader (
- "MessageID",
- Constants.WSA1,
- value.ToString ()));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("MessageID", Constants.WSA1, value.ToString ()));
}
}
throw new InvalidOperationException ("WS-Addressing header is not allowed for AddressingVersion.None");
RemoveAll ("MessageID", Constants.WSA1);
- Add (MessageHeader.CreateHeader (
- "RelatesTo",
- Constants.WSA1,
- value.ToString ()));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("RelatesTo", Constants.WSA1, value.ToString ()));
}
}
throw new InvalidOperationException ("WS-Addressing header is not allowed for AddressingVersion.None");
RemoveAll ("ReplyTo", Constants.WSA1);
- Add (MessageHeader.CreateHeader (
- "ReplyTo",
- Constants.WSA1,
- EndpointAddress10.FromEndpointAddress (value)));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("ReplyTo", Constants.WSA1, EndpointAddress10.FromEndpointAddress (value)));
}
}
#endif
}
set {
RemoveAll ("To", version.Addressing.Namespace);
- Add (MessageHeader.CreateHeader (
- "To",
- version.Addressing.Namespace,
- value.AbsoluteUri,
- true));
+ if (value != null)
+ Add (MessageHeader.CreateHeader ("To", version.Addressing.Namespace, value.AbsoluteUri, true));
}
}
{
body.WriteBodyContents (writer);
}
+
+ protected override MessageBuffer OnCreateBufferedCopy (
+ int maxBufferSize)
+ {
+ var headers = new MessageHeaders (Headers);
+ var props = new MessageProperties (Properties);
+ return new DefaultMessageBuffer (maxBufferSize, headers, props, body.CreateBufferedCopy (maxBufferSize), false);
+ }
}
}
using System.ServiceModel.PeerResolvers;
using System.ServiceModel.Security;
using System.Threading;
+using System.Xml;
namespace System.ServiceModel.Channels
{
public IPeerConnectorClient Channel { get; set; }
}
- class LocalPeerReceiver : IPeerReceiverContract
+ class LocalPeerReceiver : IPeerConnectorContract
{
public LocalPeerReceiver (PeerDuplexChannel owner)
{
{
if (connect == null)
throw new ArgumentNullException ("connect");
-try {
var ch = OperationContext.Current.GetCallbackChannel<IPeerConnectorContract> ();
-// FIXME: so, this duplex channel, when created by a listener, lacks RemoteAddress to send callback. Get it from somewhere.
-Console.WriteLine ("FIXME FIXME:" + ((IContextChannel) ch).RemoteAddress);
+ // FIXME: wrong destination
// FIXME: check and reject if inappropriate.
ch.Welcome (new WelcomeInfo () { NodeId = connect.NodeId });
+ }
-} catch (Exception ex) {
-Console.WriteLine ("Exception during Connect()");
-Console.WriteLine (ex);
-throw;
-}
-
+ public void Disconnect (DisconnectInfo disconnect)
+ {
+ if (disconnect == null)
+ throw new ArgumentNullException ("disconnect");
+ // Console.WriteLine ("DisconnectInfo.Reason: " + disconnect.Reason);
+ // FIXME: handle disconnection in practice. So far I see nothing to do.
}
public void Welcome (WelcomeInfo welcome)
{
+ owner.HandleWelcomeResponse (welcome);
}
public void Refuse (RefuseInfo refuse)
{
+ owner.HandleRefuseResponse (refuse);
+ }
+
+ public void LinkUtility (LinkUtilityInfo linkUtility)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Ping ()
+ {
+ throw new NotImplementedException ();
}
public void SendMessage (Message msg)
ServiceHost listener_host;
TcpChannelInfo info;
List<RemotePeerConnection> peers = new List<RemotePeerConnection> ();
+ PeerNodeAddress local_node_address;
public PeerDuplexChannel (IPeerChannelManager factory, EndpointAddress address, Uri via, PeerResolver resolver)
: base ((ChannelFactoryBase) factory, address, via)
channel_factory = new ChannelFactory<IPeerConnectorClient> (binding);
}
- return channel_factory.CreateChannel (new EndpointAddress ("net.p2p://" + node.MeshId), pna.EndpointAddress.Uri);
+ return channel_factory.CreateChannel (new EndpointAddress ("net.p2p://" + node.MeshId + "/"), pna.EndpointAddress.Uri);
}
+ public void HandleWelcomeResponse (WelcomeInfo welcome)
+ {
+ last_connect_response = welcome;
+ connect_handle.Set ();
+ }
+
+ public void HandleRefuseResponse (RefuseInfo refuse)
+ {
+ last_connect_response = refuse;
+ connect_handle.Set ();
+ }
+
+ AutoResetEvent connect_handle = new AutoResetEvent (false);
+ object last_connect_response;
+
public override void Send (Message message, TimeSpan timeout)
{
ThrowIfDisposedOrNotOpen ();
DateTime start = DateTime.Now;
-
+
+ // FIXME: give max buffer size
+ var mb = message.CreateBufferedCopy (0x10000);
+
foreach (var pc in peers) {
+ message = mb.CreateMessage ();
+
if (pc.Status == RemotePeerStatus.None) {
+ pc.Status = RemotePeerStatus.Error; // prepare for cases that it resulted in an error in the middle.
var inner = CreateInnerClient (pc.Address);
pc.Channel = inner;
inner.Open (timeout - (DateTime.Now - start));
inner.OperationTimeout = timeout - (DateTime.Now - start);
- inner.Connect (new ConnectInfo () { PeerNodeAddress = pc.Address, NodeId = (uint) node.NodeId });
+ inner.Connect (new ConnectInfo () { Address = local_node_address, NodeId = (uint) node.NodeId });
// FIXME: wait for Welcome or Reject and take further action.
- throw new NotImplementedException ();
+/*
+Console.WriteLine ("WAITING FOR Welcome or Refuse");
+ if (!connect_handle.WaitOne (timeout - (DateTime.Now - start)))
+ throw new TimeoutException ();
+Console.WriteLine ("got signaled");
+ if (last_connect_response is RefuseInfo)
+ throw new CommunicationException ("Peer neighbor connection was refused");
+*/
+ pc.Status = RemotePeerStatus.Connected;
}
pc.Channel.OperationTimeout = timeout - (DateTime.Now - start);
+
+ if (message.Headers.MessageId == null)
+ message.Headers.MessageId = new UniqueId ();
+ message.Headers.Add (MessageHeader.CreateHeader ("PeerTo", String.Empty, RemoteAddress));
+ message.Headers.Add (MessageHeader.CreateHeader ("PeerVia", String.Empty, RemoteAddress));
pc.Channel.SendMessage (message);
}
}
sba.InstanceContextMode = InstanceContextMode.Single;
sba.IncludeExceptionDetailInFaults = true;
- var se = listener_host.AddServiceEndpoint (typeof (IPeerReceiverContract), binding, "net.p2p://" + node.MeshId);
+ var se = listener_host.AddServiceEndpoint (typeof (IPeerConnectorContract).FullName, binding, "net.p2p://" + node.MeshId + "/");
se.ListenUri = uri;
listener_host.Open (timeout - (DateTime.Now - start));
var nid = new Random ().Next (0, int.MaxValue);
var ea = new EndpointAddress (uri);
var pna = new PeerNodeAddress (ea, new ReadOnlyCollection<IPAddress> (Dns.GetHostEntry (name).AddressList));
+ local_node_address = pna;
node.RegisteredId = resolver.Register (node.MeshId, pna, timeout - (DateTime.Now - start));
node.NodeId = nid;
public ReplyChannelBase (ChannelListenerBase listener)
: base (listener)
{
+ this.listener = listener;
}
+ ChannelListenerBase listener;
+
public abstract EndpointAddress LocalAddress { get; }
+ public override T GetProperty<T> ()
+ {
+ if (typeof (T) == typeof (IChannelListener))
+ return (T) (object) listener;
+ return base.GetProperty<T> ();
+ }
+
protected override void OnAbort ()
{
OnClose (TimeSpan.Zero);
get { return via ?? RemoteAddress.Uri; }
}
+ public override T GetProperty<T> ()
+ {
+ if (typeof (T) == typeof (IChannelFactory))
+ return (T) (object) channel_factory;
+ return base.GetProperty<T> ();
+ }
+
// Request
public Message Request (Message message)
if (client != null) {
foreach (var ch in accepted_channels) {
var dch = ch as TcpDuplexSessionChannel;
- if (dch == null || dch.TcpClient == null)
+ if (dch == null || dch.TcpClient == null && !dch.TcpClient.Connected)
continue;
if (((IPEndPoint) dch.TcpClient.Client.RemoteEndPoint).Equals (client.Client.RemoteEndPoint))
// ... then it should be handled in another BeginTryReceive/EndTryReceive loop in ChannelDispatcher.
bool is_service_side;
TcpBinaryFrameManager frame;
TcpDuplexSession session; // do not use this directly. Use Session instead.
+ EndpointAddress counterpart_address;
public TcpDuplexSessionChannel (ChannelFactoryBase factory, TcpChannelInfo info, EndpointAddress address, Uri via)
: base (factory, address, via)
// make sure to acquire TcpClient here.
int explicitPort = Via.Port;
client = new TcpClient (Via.Host, explicitPort <= 0 ? TcpTransportBindingElement.DefaultPort : explicitPort);
+ counterpart_address = GetEndpointAddressFromTcpClient (client);
}
public TcpDuplexSessionChannel (ChannelListenerBase listener, TcpChannelInfo info, TcpClient client)
is_service_side = true;
this.client = client;
this.info = info;
+ counterpart_address = GetEndpointAddressFromTcpClient (client);
}
-
+
+ EndpointAddress GetEndpointAddressFromTcpClient (TcpClient client)
+ {
+ IPEndPoint ep = (IPEndPoint) client.Client.RemoteEndPoint;
+ return new EndpointAddress (new Uri ("net.tcp://" + ep));
+ }
+
public MessageEncoder Encoder {
get { return info.MessageEncoder; }
}
+ public override EndpointAddress RemoteAddress {
+ get { return base.RemoteAddress ?? counterpart_address; }
+ }
+
+ public override EndpointAddress LocalAddress {
+ get { return base.LocalAddress ?? counterpart_address; }
+ }
+
public IDuplexSession Session {
get {
if (session == null)
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * DataContractSerializerOperationBehavior.cs : add missing members.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MetadataExchangeClient.cs : add missing async methods.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MetadataResolver.cs : added remaining methods.
+ * MetadataExchangeClient.cs : a bit of required changes for above.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceDebugBehavior.cs, ServiceMetadataBehavior.cs :
+ add Binding properties. Properties are now auto.
+ * ServiceMetadataExtension.cs : take Binding too to build dispatcher.
+
+2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceContractGenerator.cs : removed ChannelBase proxy stuff,
+ which will be moved to svcutil source.
+ The targets for extension should be the interface, not the client
+ class.
+
+2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceContractGenerator.cs,
+ OperationContractGenerationContext.cs : support extensions i.e.
+ IServiceContractGenerationExtension and IOperation...(ditto) .
+
+2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceContractGenerator.cs : first step to add moonlight-based
+ client proxy generator (it is not supported in 3.5. needs to be
+ enabled by some hook, such as reflection-based hack).
+
+2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ContractDescription.cs : wcf & 2.1 is specially annoying land :(
+
2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
* ContractDescriptionGenerator.cs : add new contract getter to
foreach (OperationDescription od in Operations) {
if (!proxy.Operations.Contains (od.Name))
PopulateClientOperation (proxy, od);
+#if !NET_2_1
foreach (IOperationBehavior ob in od.Behaviors)
ob.ApplyClientBehavior (od, proxy.Operations [od.Name]);
+#endif
}
return proxy;
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
+using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
+using System.Xml;
namespace System.ServiceModel.Description
{
{
format = new DataContractFormatAttribute ();
this.operation = operation;
+ MaxItemsInObjectGraph = int.MaxValue;
}
public DataContractSerializerOperationBehavior (
{
this.format = dataContractFormatAttribute;
this.operation = operation;
+ MaxItemsInObjectGraph = int.MaxValue;
}
public DataContractFormatAttribute DataContractFormatAttribute {
get { return format; }
}
+ public bool IgnoreExtensionDataObject { get; set; }
+
+ public int MaxItemsInObjectGraph { get; set; }
+
+ public IDataContractSurrogate DataContractSurrogate { get; set; }
+
+ public virtual XmlObjectSerializer CreateSerializer (Type type, string name, string ns, IList<Type> knownTypes)
+ {
+ return new DataContractSerializer (type, name, ns, knownTypes, MaxItemsInObjectGraph, IgnoreExtensionDataObject, false, DataContractSurrogate);
+ }
+
+ public virtual XmlObjectSerializer CreateSerializer (Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
+ {
+ return new DataContractSerializer (type, name, ns, knownTypes, MaxItemsInObjectGraph, IgnoreExtensionDataObject, false, DataContractSurrogate);
+ }
+
void IOperationBehavior.AddBindingParameters (
OperationDescription description,
BindingParameterCollection parameters)
{
- throw new NotImplementedException ();
}
void IOperationBehavior.ApplyDispatchBehavior (
namespace System.ServiceModel.Description
{
- [MonoTODO]
+ [MonoTODO ("MetadataExchangeClientMode is not considered")]
public class MetadataExchangeClient
{
string scheme;
EndpointAddress address;
SMBinding binding;
+ MetadataExchangeClientMode mode = MetadataExchangeClientMode.MetadataExchange;
+ // constructors
+
+ [MonoTODO ("use empty configuration")]
public MetadataExchangeClient ()
{
- //FIXME: Look for config element, implementing
- // IMetadataExchange contract
- // Use Channel<IMetadataExchange> .. ?
-
- throw new NotImplementedException ();
}
public MetadataExchangeClient (SMBinding mexBinding)
public MetadataExchangeClient (Uri address, MetadataExchangeClientMode mode)
{
this.address = new EndpointAddress (address.AbsoluteUri);
+ this.mode = mode;
}
+ // sync methods
+
public MetadataSet GetMetadata ()
{
return GetMetadata (address);
public MetadataSet GetMetadata (EndpointAddress address)
{
//FIXME: default mode?
- return GetMetadataInternal (address, MetadataExchangeClientMode.MetadataExchange);
+ return GetMetadataInternal (address, mode);
}
public MetadataSet GetMetadata (Uri address, MetadataExchangeClientMode mode)
return GetMetadataInternal (new EndpointAddress (address.AbsoluteUri), mode);
}
- MetadataSet GetMetadataInternal (EndpointAddress address, MetadataExchangeClientMode mode)
+ internal MetadataSet GetMetadataInternal (EndpointAddress address, MetadataExchangeClientMode mode)
{
if (binding == null)
binding = MetadataExchangeBindings.CreateMexHttpBinding ();
return MetadataSet.ReadFrom (ret.GetReaderAtBodyContents ());
}
+
+ // async methods
+
+ Func<Func<MetadataSet>,MetadataSet> getter;
+
+ void PrepareGetter ()
+ {
+ if (getter == null)
+ getter = new Func<Func<MetadataSet>,MetadataSet> (GetMetadata);
+ }
+
+ public MetadataSet EndGetMetadata (IAsyncResult result)
+ {
+ return getter.EndInvoke (result);
+ }
+
+ MetadataSet GetMetadata (Func<MetadataSet> func)
+ {
+ return func ();
+ }
+
+ public IAsyncResult BeginGetMetadata (AsyncCallback callback, object asyncState)
+ {
+ PrepareGetter ();
+ return getter.BeginInvoke (() => GetMetadata (), callback, asyncState);
+ }
+
+ public IAsyncResult BeginGetMetadata (EndpointAddress address, AsyncCallback callback, object asyncState)
+ {
+ PrepareGetter ();
+ return getter.BeginInvoke (() => GetMetadata (address), callback, asyncState);
+ }
+
+ public IAsyncResult BeginGetMetadata (Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
+ {
+ PrepareGetter ();
+ return getter.BeginInvoke (() => GetMetadata (address, mode), callback, asyncState);
+ }
}
internal class MetadataProxy : ClientBase<IMetadataExchange>, IMetadataExchange
[MonoTODO]
public static class MetadataResolver
{
- public static ServiceEndpointCollection Resolve (
- Type contract,
- EndpointAddress address)
+ static IEnumerable<ContractDescription> ToContracts (Type contract)
{
if (contract == null)
throw new ArgumentNullException ("contract");
+ yield return ContractDescription.GetContract (contract);
+ }
+
+ public static IAsyncResult BeginResolve (Type contract, EndpointAddress address, AsyncCallback callback, object asyncState)
+ {
+ return BeginResolve (ToContracts (contract), address, callback, asyncState);
+ }
+
+ public static IAsyncResult BeginResolve (IEnumerable<ContractDescription> contracts, EndpointAddress address, AsyncCallback callback, object asyncState)
+ {
+ return BeginResolve (contracts, address, MetadataExchangeClientMode.MetadataExchange, callback, asyncState);
+ }
+
+ public static IAsyncResult BeginResolve (Type contract, Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
+ {
+ return BeginResolve (ToContracts (contract), new EndpointAddress (address), mode, callback, asyncState);
+ }
+
+ public static IAsyncResult BeginResolve (IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
+ {
+ return BeginResolve (contracts, address, mode, new MetadataExchangeClient (), callback, asyncState);
+ }
+
+ public static IAsyncResult BeginResolve (Type contract, EndpointAddress address, MetadataExchangeClient client, AsyncCallback callback, object asyncState)
+ {
+ return resolver.BeginInvoke (ToContracts (contract), () => client.GetMetadata (address), callback, asyncState);
+ }
+
+ public static IAsyncResult BeginResolve (IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClientMode mode, MetadataExchangeClient client, AsyncCallback callback, object asyncState)
+ {
+ return resolver.BeginInvoke (contracts, () => client.GetMetadataInternal (address, mode), callback, asyncState);
+ }
+
+ delegate ServiceEndpointCollection Resolver (IEnumerable<ContractDescription> contracts, Func<MetadataSet> metadataGetter);
+
+ static readonly Resolver resolver = new Resolver (ResolveContracts);
- return ResolveContracts (
- new ContractDescription [] {ContractDescription.GetContract (contract)},
- address,
- MetadataExchangeClientMode.MetadataExchange);
+ public static ServiceEndpointCollection EndResolve (IAsyncResult result)
+ {
+ return resolver.EndInvoke (result);
+ }
+
+ public static ServiceEndpointCollection Resolve (
+ Type contract,
+ EndpointAddress address)
+ {
+ return Resolve (ToContracts (contract), address);
}
public static ServiceEndpointCollection Resolve (
Uri address,
MetadataExchangeClientMode mode)
{
- return ResolveContracts (
- new ContractDescription [] {ContractDescription.GetContract (contract)},
- address,
- mode);
+ return Resolve (ToContracts (contract), address, mode);
}
public static ServiceEndpointCollection Resolve (
IEnumerable<ContractDescription> contracts,
EndpointAddress address)
{
- return ResolveContracts (contracts, address, MetadataExchangeClientMode.MetadataExchange);
+ return Resolve (contracts, address, new MetadataExchangeClient ());
}
public static ServiceEndpointCollection Resolve (
Uri address,
MetadataExchangeClientMode mode)
{
- return ResolveContracts (contracts, address, mode);
+ return Resolve (contracts, new EndpointAddress (address), new MetadataExchangeClient (address, mode));
}
public static ServiceEndpointCollection Resolve (
if (client == null)
throw new ArgumentNullException ("client");
- /* FIXME: client is used for what? */
- return ResolveContracts (contracts, address, MetadataExchangeClientMode.MetadataExchange);
+ return ResolveContracts (contracts, () => client.GetMetadata (address));
}
/* FIXME: What is the mode/client used for here?
if (client == null)
throw new ArgumentNullException ("client");
- return ResolveContracts (contracts, address, mode);
+ return ResolveContracts (contracts, () => new MetadataExchangeClient ().GetMetadata (address, mode));
}
private static ServiceEndpointCollection ResolveContracts (
IEnumerable<ContractDescription> contracts,
- Uri address,
- MetadataExchangeClientMode mode)
- {
- if (address == null)
- throw new ArgumentNullException ("address");
-
- return ResolveContracts (contracts, new EndpointAddress (address), mode);
- }
-
- private static ServiceEndpointCollection ResolveContracts (
- IEnumerable<ContractDescription> contracts,
- EndpointAddress address,
- MetadataExchangeClientMode mode)
+ Func<MetadataSet> metadataGetter)
{
if (contracts == null)
throw new ArgumentNullException ("contracts");
if (list.Count == 0)
throw new ArgumentException ("There must be atleast one ContractDescription", "contracts");
- if (address == null)
- throw new ArgumentNullException ("address");
-
- MetadataExchangeClient client = new MetadataExchangeClient (address);
- MetadataSet metadata = client.GetMetadata ();
+ MetadataSet metadata = metadataGetter ();
WsdlImporter importer = new WsdlImporter (metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints ();
CodeTypeDeclaration declaringType,
CodeMemberMethod method)
: this (serviceContractGenerator, contract, operation,
- declaringType, false, method, null)
+ declaringType, method, null, null)
{
}
ServiceContractGenerationContext contract,
OperationDescription operation,
CodeTypeDeclaration declaringType,
+ CodeMemberMethod method,
CodeMemberMethod beginMethod,
CodeMemberMethod endMethod)
- : this (serviceContractGenerator, contract, operation,
- declaringType, true, beginMethod, endMethod)
- {
- }
-
- private OperationContractGenerationContext (
- ServiceContractGenerator serviceContractGenerator,
- ServiceContractGenerationContext contract,
- OperationDescription operation,
- CodeTypeDeclaration declaringType,
- bool isAsync,
- CodeMemberMethod method, // sync
- CodeMemberMethod endMethod) // async
{
generator = serviceContractGenerator;
this.contract = contract;
this.operation = operation;
declaring_type = declaringType;
this.method = method;
+ this.begin_method = beginMethod;
this.end_method = endMethod;
- is_async = isAsync;
}
- bool is_async;
ServiceContractGenerator generator;
ServiceContractGenerationContext contract;
OperationDescription operation;
CodeTypeDeclaration declaring_type;
- CodeMemberMethod method;
- CodeMemberMethod end_method;
+ CodeMemberMethod method, begin_method, end_method;
public ServiceContractGenerator ServiceContractGenerator {
get { return generator; }
public CodeTypeDeclaration DeclaringType {
get { return declaring_type; }
}
- public CodeMemberMethod Method {
+ public CodeMemberMethod SyncMethod {
get { return method; }
}
+ public CodeMemberMethod BeginMethod {
+ get { return begin_method; }
+ }
public CodeMemberMethod EndMethod {
get { return end_method; }
}
public bool IsAsync {
- get { return is_async; }
+ get { return begin_method != null; }
}
}
}
using ConfigurationType = System.Configuration.Configuration;
using QName = System.Xml.XmlQualifiedName;
+using OPair = System.Collections.Generic.KeyValuePair<System.ServiceModel.Description.IOperationContractGenerationExtension,System.ServiceModel.Description.OperationContractGenerationContext>;
namespace System.ServiceModel.Description
{
= new Dictionary<ContractDescription,Type> ();
ServiceContractGenerationOptions options;
Dictionary<QName, QName> imported_names = null;
+ ServiceContractGenerationContext contract_context;
+ List<OPair> operation_contexts = new List<OPair> ();
public ServiceContractGenerator ()
: this (null, null)
{
CodeNamespace cns = GetNamespace (contractDescription.Namespace);
imported_names = new Dictionary<QName, QName> ();
- try {
- return ExportInterface (contractDescription, cns);
- } finally {
- if ((Options & ServiceContractGenerationOptions.ClientClass) != 0)
- GenerateProxyClass (contractDescription, cns);
-
- if ((Options & ServiceContractGenerationOptions.ChannelInterface) != 0)
- GenerateChannelInterface (contractDescription, cns);
+ var ret = ExportInterface (contractDescription, cns);
+
+ // FIXME: handle duplex callback
+
+ if ((Options & ServiceContractGenerationOptions.ChannelInterface) != 0)
+ GenerateChannelInterface (contractDescription, cns);
+
+ if ((Options & ServiceContractGenerationOptions.ClientClass) != 0)
+ GenerateProxyClass (contractDescription, cns);
+
+ // Process extensions. Class first, then methods.
+ // (built-in ones must present before processing class extensions).
+ foreach (var cb in contractDescription.Behaviors) {
+ var gex = cb as IServiceContractGenerationExtension;
+ if (gex != null)
+ gex.GenerateContract (contract_context);
}
+ foreach (var opair in operation_contexts)
+ opair.Key.GenerateOperation (opair.Value);
+
+ return ret;
}
CodeNamespace GetNamespace (string ns)
type.Members.Add (ctor);
// service contract methods
- AddImplementationMethods (type, cd);
+ AddImplementationClientMethods (type, cd);
}
void GenerateChannelInterface (ContractDescription cd, CodeNamespace cns)
typeof (ServiceContractAttribute)));
ad.Arguments.Add (new CodeAttributeArgument ("Namespace", new CodePrimitiveExpression (cd.Namespace)));
type.CustomAttributes.Add (ad);
+ contract_context = new ServiceContractGenerationContext (this, cd, type);
+
AddOperationMethods (type, cd);
return new CodeTypeReference (type.Name);
void AddOperationMethods (CodeTypeDeclaration type, ContractDescription cd)
{
foreach (OperationDescription od in cd.Operations) {
+ CodeMemberMethod syncMethod = null, beginMethod = null, endMethod = null;
+
CodeMemberMethod cm = new CodeMemberMethod ();
type.Members.Add (cm);
- if (GenerateAsync)
+ if (GenerateAsync) {
cm.Name = "Begin" + od.Name;
- else
+ beginMethod = cm;
+ } else {
cm.Name = od.Name;
+ syncMethod = cm;
+ }
CodeTypeReference returnTypeFromMessageContract = null;
if (od.SyncMethod != null) {
cm.CustomAttributes.Add (ad);
// For async mode, add EndXxx() too.
- if (!GenerateAsync)
- return;
+ if (GenerateAsync) {
- cm = new CodeMemberMethod ();
- type.Members.Add (cm);
- cm.Name = "End" + od.Name;
+ cm = new CodeMemberMethod ();
+ type.Members.Add (cm);
+ cm.Name = "End" + od.Name;
+ endMethod = cm;
- var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
- cm.Parameters.Add (res);
+ var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
+ cm.Parameters.Add (res);
- if (od.SyncMethod != null) // FIXME: it depends on sync method!
- cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
- else
- cm.ReturnType = returnTypeFromMessageContract;
+ if (od.SyncMethod != null) // FIXME: it depends on sync method!
+ cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
+ else
+ cm.ReturnType = returnTypeFromMessageContract;
+ }
+
+ foreach (var ob in od.Behaviors) {
+ var gex = ob as IOperationContractGenerationExtension;
+ if (gex != null)
+ operation_contexts.Add (new OPair (gex, new OperationContractGenerationContext (this, contract_context, od, type, syncMethod, beginMethod, endMethod)));
+ }
}
}
pi.Name));
}
- void AddImplementationMethods (CodeTypeDeclaration type, ContractDescription cd)
+ void AddImplementationClientMethods (CodeTypeDeclaration type, ContractDescription cd)
{
foreach (OperationDescription od in cd.Operations) {
CodeMemberMethod cm = new CodeMemberMethod ();
// EndXxx() implementation
cm = new CodeMemberMethod ();
+ cm.Attributes = MemberAttributes.Public
+ | MemberAttributes.Final;
type.Members.Add (cm);
cm.Name = "End" + od.Name;
{
throw new NotImplementedException ();
}
-
+
private void ExportDataContract (XmlTypeMapping mapping)
{
if (mapping == null)
{
public class ServiceDebugBehavior : IServiceBehavior
{
- bool inc_details;
- bool http_help_enabled = true;
- bool https_help_enabled = true;
- Uri http_help_url, https_help_url;
-
public ServiceDebugBehavior ()
{
}
- public bool IncludeExceptionDetailInFaults {
- get { return inc_details; }
- set { inc_details = value; }
- }
+ public bool IncludeExceptionDetailInFaults { get; set; }
- public bool HttpHelpPageEnabled {
- get { return http_help_enabled; }
- set { http_help_enabled = value; }
- }
+ public bool HttpHelpPageEnabled { get; set; }
- public Uri HttpHelpPageUrl {
- get { return http_help_url; }
- set { http_help_url = value; }
- }
+ public Uri HttpHelpPageUrl { get; set; }
- public bool HttpsHelpPageEnabled {
- get { return https_help_enabled; }
- set { https_help_enabled = value; }
- }
+ public bool HttpsHelpPageEnabled { get; set; }
- public Uri HttpsHelpPageUrl {
- get { return https_help_url; }
- set { https_help_url = value; }
- }
+ public Uri HttpsHelpPageUrl { get; set; }
+
+ public Binding HttpHelpPageBinding { get; set; }
+
+ public Binding HttpsHelpPageBinding { get; set; }
void IServiceBehavior.AddBindingParameters (
ServiceDescription description,
if (HttpHelpPageEnabled) {
Uri uri = serviceHostBase.CreateUri ("http", HttpHelpPageUrl);
if (uri != null)
- ServiceMetadataExtension.EnsureServiceMetadataHttpChanelDispatcher (description, serviceHostBase, sme, uri);
+ ServiceMetadataExtension.EnsureServiceMetadataHttpChanelDispatcher (description, serviceHostBase, sme, uri, HttpHelpPageBinding);
}
if (HttpsHelpPageEnabled) {
Uri uri = serviceHostBase.CreateUri ("https", HttpsHelpPageUrl);
if (uri != null)
- ServiceMetadataExtension.EnsureServiceMetadataHttpsChanelDispatcher (description, serviceHostBase, sme, uri);
+ ServiceMetadataExtension.EnsureServiceMetadataHttpsChanelDispatcher (description, serviceHostBase, sme, uri, HttpsHelpPageBinding);
}
}
{
public const string MexContractName = "IMetadataExchange";
- bool enable_http, enable_https;
- Uri http_url, https_url, location;
MetadataExporter exporter;
public ServiceMetadataBehavior ()
{
}
- public bool HttpGetEnabled {
- get { return enable_http; }
- set { enable_http = value; }
- }
+ public bool HttpGetEnabled { get; set; }
- public bool HttpsGetEnabled {
- get { return enable_https; }
- set { enable_https = value; }
- }
+ public bool HttpsGetEnabled { get; set; }
public MetadataExporter MetadataExporter {
get { return exporter ?? (exporter = new WsdlExporter ()); }
set { exporter = value; }
}
- public Uri ExternalMetadataLocation {
- get { return location; }
- set { location = value; }
- }
+ public Uri ExternalMetadataLocation { get; set; }
- public Uri HttpGetUrl {
- get { return http_url; }
- set { http_url = value; }
- }
+ public Uri HttpGetUrl { get; set; }
- public Uri HttpsGetUrl {
- get { return https_url; }
- set { https_url = value; }
- }
+ public Uri HttpsGetUrl { get; set; }
+
+ public Binding HttpGetBinding { get; set; }
+
+ public Binding HttpsGetBinding { get; set; }
- [MonoTODO]
void IServiceBehavior.AddBindingParameters (
ServiceDescription description,
ServiceHostBase serviceHostBase,
if (HttpGetEnabled) {
Uri uri = serviceHostBase.CreateUri ("http", HttpGetUrl);
if (uri != null)
- ServiceMetadataExtension.EnsureServiceMetadataHttpChanelDispatcher (description, serviceHostBase, sme, uri);
+ ServiceMetadataExtension.EnsureServiceMetadataHttpChanelDispatcher (description, serviceHostBase, sme, uri, HttpGetBinding);
}
if (HttpsGetEnabled) {
Uri uri = serviceHostBase.CreateUri ("https", HttpsGetUrl);
if (uri != null)
- ServiceMetadataExtension.EnsureServiceMetadataHttpsChanelDispatcher (description, serviceHostBase, sme, uri);
+ ServiceMetadataExtension.EnsureServiceMetadataHttpsChanelDispatcher (description, serviceHostBase, sme, uri, HttpsGetBinding);
}
}
using WSServiceDescription = System.Web.Services.Description.ServiceDescription;
using WSMessage = System.Web.Services.Description.Message;
using SMMessage = System.ServiceModel.Channels.Message;
-
+using WCFBinding = System.ServiceModel.Channels.Binding;
namespace System.ServiceModel.Description
{
return sme;
}
- internal static void EnsureServiceMetadataHttpChanelDispatcher (ServiceDescription description, ServiceHostBase serviceHostBase, ServiceMetadataExtension sme, Uri uri) {
+ internal static void EnsureServiceMetadataHttpChanelDispatcher (ServiceDescription description, ServiceHostBase serviceHostBase, ServiceMetadataExtension sme, Uri uri, WCFBinding binding)
+ {
+ EnsureServiceMetadataDispatcher (description, serviceHostBase, sme, uri, binding ?? MetadataExchangeBindings.CreateMexHttpBinding ());
+ }
+
+ internal static void EnsureServiceMetadataHttpsChanelDispatcher (ServiceDescription description, ServiceHostBase serviceHostBase, ServiceMetadataExtension sme, Uri uri, WCFBinding binding)
+ {
+ // same as http now.
+ EnsureServiceMetadataDispatcher (description, serviceHostBase, sme, uri, binding ?? MetadataExchangeBindings.CreateMexHttpsBinding ());
+ }
+ static void EnsureServiceMetadataDispatcher (ServiceDescription description, ServiceHostBase serviceHostBase, ServiceMetadataExtension sme, Uri uri, WCFBinding binding)
+ {
if (sme._serviceMetadataChanelDispatchers == null)
sme._serviceMetadataChanelDispatchers = new Dictionary<Uri, ChannelDispatcherBase> ();
else if (sme._serviceMetadataChanelDispatchers.ContainsKey (uri))
return;
- CustomBinding cb = new CustomBinding (new BasicHttpBinding ())
+ CustomBinding cb = new CustomBinding (binding)
{
Name = ServiceMetadataBehaviorHttpGetBinding,
};
serviceHostBase.ChannelDispatchers.Add (channelDispatcher);
}
- internal static void EnsureServiceMetadataHttpsChanelDispatcher (ServiceDescription description, ServiceHostBase serviceHostBase, ServiceMetadataExtension sme, Uri uri) {
- throw new NotImplementedException ();
- }
-
void IExtension<ServiceHostBase>.Attach (ServiceHostBase owner)
{
this.owner = owner;
{
int index = 0;
foreach (ParameterInfo pi in requestMethodParams)
- if (!pi.IsOut)
- parameters [pi.Position] = parts [index++];
+ if (!pi.IsOut) {
+ parameters [index] = parts [index];
+ index++;
+ }
}
}
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * EndpointDispatcher.cs : do not try to create wrong filter.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ChannelDispatcher.cs : EndpointNotFoundException message could
+ be a bit kindful.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IOperationInvoker.cs : fix interface.
+ * DefaultOperationInvoker.cs : refresh implementation of the above.
+ * BaseMessagesFormatter.cs, OperationInvokerHandler.cs :
+ dependent changes for above.
+
2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
* InputOrReplyRequestProcessor.cs : now it could return an instance
}
}
if (candidate == null)
- throw new EndpointNotFoundException (String.Format ("The request message has the target '{0}' which is not reachable in this service contract", message.Headers.To));
+ throw new EndpointNotFoundException (String.Format ("The request message has the target '{0}' with action '{1}' which is not reachable in this service contract", message.Headers.To, message.Headers.Action));
return candidate;
}
}
--- /dev/null
+//
+// DefaultOperationInvoker.cs
+//
+// Author: Atsushi Enomoto (atsushi@ximian.com)
+//
+// Copyright (C) 2009 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.
+//
+
+using System;
+using System.Collections.Generic;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.Reflection;
+using System.Threading;
+
+namespace System.ServiceModel.Dispatcher
+{
+ class DefaultOperationInvoker : IOperationInvoker
+ {
+ readonly OperationDescription od;
+ readonly ParameterInfo [] in_params, out_params;
+
+ public DefaultOperationInvoker (OperationDescription od)
+ {
+ this.od = od;
+ var mi = od.SyncMethod ?? od.BeginMethod;
+ var il = new List<ParameterInfo> ();
+ var ol = new List<ParameterInfo> ();
+ var pl = mi.GetParameters ();
+ int count = mi == od.BeginMethod ? pl.Length - 2 : pl.Length;
+ for (int i = 0; i < count; i++) {
+ var pi = pl [i];
+ if (!pi.IsOut)
+ il.Add (pi);
+ if (pi.IsOut)
+ ol.Add (pi);
+ }
+ in_params = il.ToArray ();
+ out_params = ol.ToArray ();
+ }
+
+ public bool IsSynchronous {
+ get { return true; }
+ }
+
+ public object [] AllocateInputs ()
+ {
+ return new object [in_params.Length];
+ }
+
+ public object Invoke (object instance, object [] inputs, out object [] outputs)
+ {
+ var arr = new object [in_params.Length + out_params.Length];
+ for (int i = 0; i < in_params.Length; i++)
+ arr [in_params [i].Position] = inputs [i];
+
+ var ret = od.SyncMethod.Invoke (instance, arr);
+
+ outputs = new object [out_params.Length];
+ for (int i = 0; i < out_params.Length; i++)
+ outputs [i] = arr [out_params [i].Position];
+
+ return ret;
+ }
+
+ public IAsyncResult InvokeBegin (object instance, object [] inputs, AsyncCallback callback, object state)
+ {
+ var arr = new object [in_params.Length + out_params.Length + 2];
+ for (int i = 0; i < in_params.Length; i++)
+ arr [in_params [i].Position] = inputs [i];
+ arr [arr.Length - 2] = callback;
+ arr [arr.Length - 1] = state;
+ return new InvokeAsyncResult (arr, (IAsyncResult) od.BeginMethod.Invoke (instance, arr));
+ }
+
+ public object InvokeEnd (object instance, out object [] outputs, IAsyncResult result)
+ {
+ var r = (InvokeAsyncResult) result;
+ var ret = od.EndMethod.Invoke (instance, new object [] {r.Source});
+ var arr = r.Parameters;
+ outputs = new object [out_params.Length];
+ for (int i = 0; i < out_params.Length; i++)
+ outputs [i] = arr [out_params [i].Position];
+ return ret;
+ }
+
+ class InvokeAsyncResult : IAsyncResult
+ {
+ public InvokeAsyncResult (object [] parameters, IAsyncResult source)
+ {
+ Source = source;
+ Parameters = parameters;
+ }
+
+ public IAsyncResult Source;
+ public object [] Parameters;
+
+ public WaitHandle AsyncWaitHandle {
+ get { return Source.AsyncWaitHandle; }
+ }
+ public bool CompletedSynchronously {
+ get { return Source.CompletedSynchronously; }
+ }
+ public bool IsCompleted {
+ get { return Source.IsCompleted; }
+ }
+ public object AsyncState {
+ get { return Source.AsyncState; }
+ }
+ }
+ }
+}
}
public MessageFilter AddressFilter {
- get { return address_filter ?? (address_filter = new EndpointAddressMessageFilter (EndpointAddress)); }
+ get { return address_filter; }
set {
if (value == null)
throw new ArgumentNullException ("value");
public interface IOperationInvoker
{
bool IsSynchronous { get; }
- object [] AllocateParameters ();
- object Invoke (object instance, object [] inputs);
+ object [] AllocateInputs ();
+ object Invoke (object instance, object [] inputs, out object [] outputs);
IAsyncResult InvokeBegin (object instance, object [] inputs,
AsyncCallback callback, object state);
object InvokeEnd (object instance, out object [] outputs, IAsyncResult result);
DispatchOperation operation = mrc.Operation;
Message req = mrc.IncomingMessage;
object instance = mrc.InstanceContext.GetServiceInstance(req);
- object [] parameters;
+ object [] parameters, outParams;
BuildInvokeParams (mrc, out parameters);
if (operation.Invoker.IsSynchronous) {
- object result = operation.Invoker.Invoke (instance, parameters);
- HandleInvokeResult (mrc, parameters, result);
+ object result = operation.Invoker.Invoke (instance, parameters, out outParams);
+ HandleInvokeResult (mrc, outParams, result);
} else {// asynchronous
InvokeAsynchronous (mrc, instance, parameters);
}
EnsureValid (operation);
if (operation.DeserializeRequest) {
- parameters = operation.Invoker.AllocateParameters ();
+ parameters = operation.Invoker.AllocateInputs ();
operation.Formatter.DeserializeRequest (mrc.IncomingMessage, parameters);
} else
parameters = new object [] { mrc.IncomingMessage };
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IPeerConnectorContract.cs : use wildcard for the actual message
+ transfer operation.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IPeerConnectorContract.cs : fix internal member name to get
+ serialized correctly.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IPeerConnectorContract.cs : add itself as CallbackContract.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IPeerConnectorContract.cs : remove receiver contract.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * IPeerConnectorContract.cs : add Disconnect() to receiver contract.
+
2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
* IPeerConnectorContract.cs : add callback contract.
public const string Namespace = "http://schemas.microsoft.com/net/2006/05/peer";
}
- [ServiceContract (Namespace = Consts.Namespace, SessionMode = SessionMode.Allowed)]
+ [ServiceContract (Namespace = Consts.Namespace, SessionMode = SessionMode.Allowed, CallbackContract = typeof (IPeerConnectorContract))]
internal interface IPeerConnectorContract
{
[OperationContract (Action = Consts.Namespace + "/Connect", IsOneWay = true)]
[OperationContract (Action = Consts.Namespace + "/Ping", IsOneWay = true)]
void Ping ();
- [OperationContract (IsOneWay = true)]
- void SendMessage (Message msg);
- }
-
- [ServiceContract (Namespace = Consts.Namespace, SessionMode = SessionMode.Allowed, CallbackContract = typeof (IPeerConnectorContract))]
- internal interface IPeerReceiverContract
- {
- [OperationContract (Action = Consts.Namespace + "/Connect", IsOneWay = true)]
- void Connect (ConnectInfo connect);
-
- [OperationContract (IsOneWay = true)]
+ [OperationContract (Action = "*", IsOneWay = true)]
void SendMessage (Message msg);
}
internal class ConnectInfoDC
{
[DataMember]
- public PeerNodeAddress PeerNodeAddress { get; set; }
+ public PeerNodeAddress Address { get; set; }
[DataMember]
public ulong NodeId { get; set; }
}
[MessageBodyMember (Name = "Connect", Namespace = Consts.Namespace)]
ConnectInfoDC dc;
- public PeerNodeAddress PeerNodeAddress {
- get { return dc.PeerNodeAddress; }
- set { dc.PeerNodeAddress = value; }
+ public PeerNodeAddress Address {
+ get { return dc.Address; }
+ set { dc.Address = value; }
}
public ulong NodeId {
System.ServiceModel.Dispatcher/ClientRuntime.cs
System.ServiceModel.Dispatcher/DataContractSerializerServiceBehavior.cs
System.ServiceModel.Dispatcher/DefaultInstanceContextProvider.cs
+System.ServiceModel.Dispatcher/DefaultOperationInvoker.cs
System.ServiceModel.Dispatcher/DispatchOperation.cs
System.ServiceModel.Dispatcher/DispatchRuntime.cs
System.ServiceModel.Dispatcher/EndpointAddressMessageFilter.cs
namespace System.ServiceModel
{
+ public enum AddressFilterMode
+ {
+ Exact,
+ Prefix,
+ Any
+ }
+
public enum AuditLevel
{
None,
LaxTimestampLast,
}
+ public enum SupportedAddressingMode
+ {
+ Anonymous,
+ NonAnonymous,
+ Mixed
+ }
+
public enum TransferSession
{
None,
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceHostBase.cs : wildcard action support was not working
+ for one-way channels.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceHostBase.cs : set expected AddressFilter.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * EndpointAddress.cs : #if !NET_2_1 is removing code too much.
+
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceRuntimeChannel.cs : made some properties in duplex context
+ channel dispatching to internal client.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * OperationContextScope.cs : check null arg.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceRuntimeChannel.cs : return timeouts that are set at
+ dispatch runtime later than its .ctor(). Provide ListenUri too.
+
+2009-08-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * AllEnums.cs : add AddressFilterMode and SupportedAddressingMode.
+ * ServiceBehaviorAttribute.cs : added missing properties.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ClientBase.cs : (ChannelBase) now ClientRuntimeChannel demands an
+ explicit address.
+
+2009-08-11 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ServiceHostBase.cs : use new IOperationInvoker implementation.
+
2009-08-07 Atsushi Enomoto <atsushi@ximian.com>
* ServiceRuntimeChannel.cs : change .ctor() args.
internal ClientRuntimeChannel Inner {
get {
if (inner_channel == null)
- inner_channel = new ClientRuntimeChannel (endpoint, factory, null, null);
+ inner_channel = new ClientRuntimeChannel (endpoint, factory, endpoint.Address, null);
return inner_channel;
}
}
return ! (address1 == address2);
}
-#if !NET_2_1
+//#if !NET_2_1
[MonoTODO]
public static EndpointAddress ReadFrom (
XmlDictionaryReader reader)
AddressingVersion addressingVersion, XmlReader reader)
{
Uri uri = null;
- MetadataSet metadata = null;
EndpointIdentity identity = null;
reader.MoveToContent ();
if (reader.LocalName == "Address" &&
addressingVersion.Namespace, reader.LocalName, reader.NamespaceURI));
reader.MoveToContent ();
+#if !NET_2_1
+ MetadataSet metadata = null;
if (reader.LocalName == "Metadata" &&
reader.NamespaceURI == addressingVersion.Namespace &&
!reader.IsEmptyElement) {
// FIXME: implement
reader.Skip ();
}
+#endif
if (addressingVersion == AddressingVersion.WSAddressing10 && uri == w3c_anonymous)
uri = anonymous_role;
+#if NET_2_1
+ return new EndpointAddress (uri, identity);
+#else
if (metadata == null)
return new EndpointAddress (uri, identity);
return new EndpointAddress (uri, identity,
AddressHeader.CreateAddressHeader (metadata));
- }
#endif
+ }
public override string ToString ()
{
public OperationContextScope (OperationContext context)
{
+ if (context == null)
+ throw new ArgumentNullException ("context");
previous = OperationContext.Current;
OperationContext.Current = context;
}
string tx_timeout;
object singleton;
+ [MonoTODO]
+ public string Name { get; set; }
+ [MonoTODO]
+ public string Namespace { get; set; }
+ [MonoTODO]
+ public string ConfigurationName { get; set; }
+
+ [MonoTODO]
+ public AddressFilterMode AddressFilterMode { get; set; }
+
[MonoTODO]
public bool AutomaticSessionShutdown { get; set; }
}
- internal ChannelDispatcher BuildChannelDispatcher (ServiceEndpoint se, BindingParameterCollection commonParams) {
-
+ internal ChannelDispatcher BuildChannelDispatcher (ServiceEndpoint se, BindingParameterCollection commonParams)
+ {
//User the binding parameters to build the channel listener and Dispatcher
IChannelListener lf = BuildListener (se, commonParams);
ChannelDispatcher cd = new ChannelDispatcher (
new EndpointDispatcher (se.Address, se.Contract.Name, se.Contract.Namespace);
endpoint_dispatcher.DispatchRuntime.Type = Description.ServiceType;
endpoint_dispatcher.ContractFilter = GetContractFilter (se.Contract);
+ endpoint_dispatcher.AddressFilter = new EndpointAddressMessageFilter (se.Address);
endpoint_dispatcher.ChannelDispatcher = cd;
cd.Endpoints.Add (endpoint_dispatcher);
od.IsOneWay ?
new DispatchOperation (db, od.Name, reqA) :
new DispatchOperation (db, od.Name, reqA, resA);
- bool has_void_reply = false;
+ bool no_serialized_reply = od.IsOneWay;
foreach (MessageDescription md in od.Messages) {
if (md.Direction == MessageDirection.Input &&
md.Body.Parts.Count == 1 &&
if (md.Body.ReturnValue.Type == typeof (Message))
o.SerializeReply = false;
else if (md.Body.ReturnValue.Type == typeof (void))
- has_void_reply = true;
+ no_serialized_reply = true;
}
}
// Setup Invoker
- // FIXME: support async method
- if (od.SyncMethod != null)
- o.Invoker = new SyncMethodInvoker (od.SyncMethod);
- else
- o.Invoker = new AsyncMethodInvoker (od.BeginMethod, od.EndMethod);
+ o.Invoker = new DefaultOperationInvoker (od);
// Setup Formater
o.Formatter = BaseMessagesFormatter.Create (od);
- if (o.Action == "*" && o.ReplyAction == "*") {
+ if (o.Action == "*" && (o.IsOneWay || o.ReplyAction == "*")) {
//Signature : Message (Message)
// : void (Message)
//FIXME: void (IChannel)
- if (!o.DeserializeRequest && (!o.SerializeReply || has_void_reply))
+ if (!o.DeserializeRequest && (!o.SerializeReply || no_serialized_reply)) // what is this double-ish check for?
db.UnhandledDispatchOperation = o;
}
Close ();
}
+ /*
class SyncMethodInvoker : IOperationInvoker
{
readonly MethodInfo _methodInfo;
#endregion
}
+ */
}
+
}
ClientRuntimeChannel client;
+ public override bool AllowOutputBatching {
+ get { return client.AllowOutputBatching; }
+ set { client.AllowOutputBatching = value; }
+ }
+
+ public virtual TimeSpan OperationTimeout {
+ get { return client.OperationTimeout; }
+ set { client.OperationTimeout = value; }
+ }
+
public bool AutomaticInputSessionShutdown {
get { throw new NotImplementedException (); }
set { throw new NotImplementedException (); }
internal class ServiceRuntimeChannel : CommunicationObject, IServiceChannel
{
IExtensionCollection<IContextChannel> extensions;
- readonly IChannel channel;
- readonly TimeSpan _openTimeout;
- readonly TimeSpan _closeTimeout;
+ readonly IChannel channel;
+ readonly DispatchRuntime runtime;
public ServiceRuntimeChannel (IChannel channel, DispatchRuntime runtime)
{
this.channel = channel;
- this._openTimeout = runtime.ChannelDispatcher.DefaultOpenTimeout;
- this._closeTimeout = runtime.ChannelDispatcher.DefaultCloseTimeout;
+ this.runtime = runtime;
}
#region IContextChannel
[MonoTODO]
- public bool AllowOutputBatching { get; set; }
+ public virtual bool AllowOutputBatching { get; set; }
public IInputSession InputSession {
get {
}
[MonoTODO]
- public TimeSpan OperationTimeout { get; set; }
+ public virtual TimeSpan OperationTimeout { get; set; }
public IOutputSession OutputSession {
get {
// CommunicationObject
protected internal override TimeSpan DefaultOpenTimeout {
- get { return _openTimeout; }
+ get { return runtime.ChannelDispatcher.DefaultOpenTimeout; }
}
protected internal override TimeSpan DefaultCloseTimeout {
- get { return _closeTimeout; }
+ get { return runtime.ChannelDispatcher.DefaultCloseTimeout; }
}
protected override void OnAbort ()
}
public Uri ListenUri {
- get { throw new NotImplementedException (); }
+ get { return runtime.ChannelDispatcher.Listener.Uri; }
}
#region IDisposable Members
+2009-08-17 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MessageTest.cs : added test for State.
+
2009-06-08 Atsushi Enomoto <atsushi@ximian.com>
* CommunicationObjectTest.cs : added a couple of close/abort tests
m = Message.CreateMessage (MessageVersion.Default, new FaultCode ("ActionNotSupported", "urn:myfault"), "I dunno", "urn:myaction");
Assert.IsTrue (m.IsFault, "#2");
}
+
+ [Test]
+ public void State ()
+ {
+ var msg = Message.CreateMessage (MessageVersion.Soap11, "urn:foo", (object) null);
+ var xw = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (TextWriter.Null));
+ msg.WriteStartEnvelope (xw);
+ Assert.AreEqual (MessageState.Created, msg.State, "#1");
+ msg.WriteStartBody (xw);
+ Assert.AreEqual (MessageState.Created, msg.State, "#2");
+ }
}
}
--- /dev/null
+2009-08-17 Marek Habersack <mhabersack@novell.com>
+
+ * ScriptingJsonSerializationSection.cs: MaxJsonLength default
+ value is 2097152 for .NET 3.5+
+
}
}
+#if NET_3_5
+ [ConfigurationPropertyAttribute ("maxJsonLength", DefaultValue = 2097152)]
+#else
[ConfigurationPropertyAttribute ("maxJsonLength", DefaultValue = 102400)]
+#endif
public int MaxJsonLength {
get {
return (int) this ["maxJsonLength"];
+2009-08-18 Marek Habersack <mhabersack@novell.com>
+
+ * JavaScriptSerializer.cs: read converters from the config only if
+ explicitly requested.
+
+2009-08-17 Marek Habersack <mhabersack@novell.com>
+
+ * JsonSerializer.cs: serialize fields before properties.
+
+ * JavaScriptSerializer.cs: MaxJsonLength default value for .NET
+ 3.5 is 2097152
+
2009-03-17 Marek Habersack <mhabersack@novell.com>
* JavaScriptSerializer.cs: if conversion of IDictionary or
int _maxJsonLength;
int _recursionLimit;
JavaScriptTypeResolver _typeResolver;
- internal static readonly JavaScriptSerializer DefaultSerializer = new JavaScriptSerializer ();
+ internal static readonly JavaScriptSerializer DefaultSerializer = new JavaScriptSerializer (null, false);
- public JavaScriptSerializer ()
- : this(null)
+ public JavaScriptSerializer () : this (null, false)
{
}
- public JavaScriptSerializer (JavaScriptTypeResolver resolver)
+ public JavaScriptSerializer (JavaScriptTypeResolver resolver) : this (resolver, false)
+ {
+ }
+
+ internal JavaScriptSerializer (JavaScriptTypeResolver resolver, bool registerConverters)
{
_typeResolver = resolver;
ScriptingJsonSerializationSection section = (ScriptingJsonSerializationSection) ConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/jsonSerialization");
if (section == null) {
+#if NET_3_5
+ _maxJsonLength = 2097152;
+#else
_maxJsonLength = 102400;
+#endif
_recursionLimit = 100;
- }
- else {
+ } else {
_maxJsonLength = section.MaxJsonLength;
_recursionLimit = section.RecursionLimit;
+
+ if (registerConverters) {
+ ConvertersCollection converters = section.Converters;
+ if (converters != null && converters.Count > 0) {
+ var cvtlist = new List <JavaScriptConverter> ();
+ Type type;
+ string typeName;
+ JavaScriptConverter jsc;
+
+ foreach (Converter cvt in converters) {
+ typeName = cvt != null ? cvt.Type : null;
+ if (typeName == null)
+ continue;
+
+ type = HttpApplication.LoadType (typeName, true);
+ if (type == null || !typeof (JavaScriptConverter).IsAssignableFrom (type))
+ continue;
+
+ jsc = Activator.CreateInstance (type) as JavaScriptConverter;
+ cvtlist.Add (jsc);
+ }
+
+ RegisterConverters (cvtlist);
+ }
+ }
}
}
+
public int MaxJsonLength {
get {
return _maxJsonLength;
bool ShouldIgnoreMember (MemberInfo mi, out MethodInfo getMethod)
{
getMethod = null;
+ if (mi == null)
+ return true;
+
if (mi.IsDefined (typeof (ScriptIgnoreAttribute), true))
return true;
PropertyInfo pi = mi as PropertyInfo;
if (pi == null)
return true;
-
+
getMethod = pi.GetGetMethod ();
if (getMethod == null || getMethod.GetParameters ().Length > 0) {
getMethod = null;
}
}
- MemberInfo[] members = type.GetMembers (BindingFlags.Public | BindingFlags.Instance);
+ SerializeMembers <FieldInfo> (type.GetFields (BindingFlags.Public | BindingFlags.Instance), obj, output, ref first);
+ SerializeMembers <PropertyInfo> (type.GetProperties (BindingFlags.Public | BindingFlags.Instance), obj, output, ref first);
+
+ StringBuilderExtensions.AppendCount (output, maxJsonLength, "}");
+ }
+
+ void SerializeMembers <T> (T[] members, object obj, StringBuilder output, ref bool first) where T: MemberInfo
+ {
MemberInfo member;
MethodInfo getMethod;
string name;
- foreach (MemberInfo mi in members) {
- if (ShouldIgnoreMember (mi, out getMethod))
+ foreach (T mi in members) {
+ if (ShouldIgnoreMember (mi as MemberInfo, out getMethod))
continue;
name = mi.Name;
if (first)
first = false;
}
-
- StringBuilderExtensions.AppendCount (output, maxJsonLength, "}");
}
void SerializeEnumerable (StringBuilder output, IEnumerable enumerable)
+2009-08-15 Marek Habersack <mhabersack@novell.com>
+
+ * LogicalTypeInfo.cs: make sure JavaScriptSerializer instance used
+ here reads custom converters from web.config. Fixes bug #525589
+
2009-06-14 Robert Jordan <robertj@gmx.net>
* ScriptHandlerFactory.cs: handle precompiled web services.
readonly Hashtable _methodMap;
readonly Type _type;
readonly string _proxy;
- static readonly JavaScriptSerializer JSSerializer = new JavaScriptSerializer ();
+ static readonly JavaScriptSerializer JSSerializer = new JavaScriptSerializer (null, true);
private LogicalTypeInfo (Type t, string filePath) {
_type = t;
+2009-08-17 Marek Habersack <mhabersack@novell.com>
+
+ * JavaScriptSerializerTest.cs: fixed broken tests
+
2009-06-18 Marek Habersack <mhabersack@novell.com>
* JavaScriptSerializerTest.cs: added comparison with the
[Category ("NotDotNet")]
public void TestDefaults () {
JavaScriptSerializer ser = new JavaScriptSerializer ();
+#if NET_3_5
+ Assert.AreEqual (2097152, ser.MaxJsonLength);
+#else
Assert.AreEqual (102400, ser.MaxJsonLength);
+#endif
Assert.AreEqual (100, ser.RecursionLimit);
//List<JavaScriptConverter> l = new List<JavaScriptConverter> ();
//l.Add (new MyJavaScriptConverter ());
x.Init ();
string s = ser.Serialize (x);
- Console.WriteLine (s);
Assert.AreEqual ("{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+X, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"z\":8,\"ch\":\"v\",\"ch_null\":null,\"str\":\"vwF59g\",\"b\":253,\"sb\":-48,\"sh\":-32740,\"ush\":65511,\"i\":-234235453,\"ui\":4294733061,\"l\":-9223372036854775780,\"ul\":18446744073709551612,\"f\":NaN,\"f1\":-Infinity,\"f2\":Infinity,\"f3\":-3.40282347E+38,\"f4\":3.40282347E+38,\"d\":NaN,\"d1\":-Infinity,\"d2\":Infinity,\"d3\":-1.7976931348623157E+308,\"d4\":1.7976931348623157E+308,\"de\":-1,\"de1\":0,\"de2\":1,\"de3\":-79228162514264337593543950335,\"de4\":79228162514264337593543950335,\"g\":\"000000ea-0002-0162-0102-030405060708\",\"nb\":null,\"dbn\":null,\"uri\":\"http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d\",\"hash\":{\"mykey\":{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"BB\":10}},\"point\":{\"__type\":\"System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\",\"IsEmpty\":false,\"X\":150,\"Y\":150},\"MyEnum\":[1,10,345],\"MyEnum1\":[1,10,345],\"AA\":5,\"AA1\":[{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"BB\":10},{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"BB\":10}],\"BB\":18446744073709551610,\"YY\":[{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"BB\":10},{\"__type\":\"MonoTests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, System.Web.Extensions_test_net_2_0, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\",\"BB\":10}]}", s, "#A1");
X x2 = ser.Deserialize<X> (s);
+2009-08-13 Marek Habersack <mhabersack@novell.com>
+
+ * Makefile: build only in the 2.0 profile, or otherwise we'll end
+ up with the resulting assembly referencing the 4.0 corlib.
+
2009-04-21 Marek Habersack <mhabersack@novell.com>
* Makefile: fixed resource ID generation.
EXTRA_DISTFILES = $(RESX_DIST)
-# This is a .NET 3.5+ assembly
-VALID_PROFILE := $(filter net_2_0 net_4_0, $(PROFILE))
+# This is a .NET 3.5+ assembly - it must be built ONLY in the 2.0 profile
+VALID_PROFILE := $(filter net_2_0, $(PROFILE))
ifndef VALID_PROFILE
LIBRARY_NAME = dummy-System.Web.Mvc.dll
NO_INSTALL = yes
+2009-08-18 Marek Habersack <mhabersack@novell.com>
+
+ * Makefile (TEST_RESOURCE_FILES): added
+ Test/mainsoft/NunitWebResources/DuplicateControlsInClientComment.aspx
+
+2009-08-15 Marek Habersack <mhabersack@novell.com>
+
+ * Makefile (TEST_RESOURCE_FILES): added
+ Test/mainsoft/NunitWebResources/NewlineInCodeExpression.aspx
+
2009-07-30 Raja R Harinath <harinath@hurrynot.org>
* Makefile ($(build_lib)): Move cyclic dependencies onto this.
OTHER_RES = $(RESOURCE_FILES_1)
TEST_RESOURCE_FILES = \
Test/mainsoft/NunitWeb/NunitWeb/Resources/Global.asax \
- Test/mainsoft/NunitWeb/NunitWeb/Resources/Global.asax.cs \
Test/mainsoft/NunitWeb/NunitWeb/Resources/My.ashx \
Test/mainsoft/NunitWeb/NunitWeb/Resources/My.master \
Test/mainsoft/NunitWeb/NunitWeb/Resources/MyPage.aspx \
Test/mainsoft/NunitWebResources/PreprocessorDirectivesInMarkup.aspx \
Test/mainsoft/NunitWebResources/UnquotedAngleBrackets.aspx \
Test/mainsoft/NunitWebResources/FullTagsInText.aspx \
- Test/mainsoft/NunitWebResources/TagsExpressionsAndCommentsInText.aspx
+ Test/mainsoft/NunitWebResources/TagsExpressionsAndCommentsInText.aspx \
+ Test/mainsoft/NunitWebResources/NewlineInCodeExpression.aspx \
+ Test/mainsoft/NunitWebResources/DuplicateControlsInClientComment.aspx
RESX_DIST = resources/TranslationResources.resx
ifneq (1, $(FRAMEWORK_VERSION_MAJOR))
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Marek Habersack <mhabersack@novell.com>
//
// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
-// Copyright (c) 2004,2006 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2004-2009 Novell, Inc (http://www.novell.com)
//
//
public BuilderLocation (ControlBuilder builder, ILocation location)
{
this.Builder = builder;
- this.Location = location;
+ this.Location = new Location (location);
}
}
}
}
+ enum TextBlockType
+ {
+ Verbatim,
+ Expression,
+ Tag,
+ Comment
+ }
+
+ sealed class TextBlock
+ {
+ public string Content;
+ public readonly TextBlockType Type;
+ public readonly int Length;
+
+ public TextBlock (TextBlockType type, string content)
+ {
+ Content = content;
+ Type = type;
+ Length = content.Length;
+ }
+
+ public override string ToString ()
+ {
+ return this.GetType ().FullName + " [" + this.Type + "]";
+ }
+ }
+
class AspGenerator
{
#if NET_2_0
internal static Regex DirectiveRegex = new Regex (@"<%\s*@(\s*(?<attrname>\w[\w:]*(?=\W))(\s*(?<equal>=)\s*""(?<attrval>[^""]*)""|\s*(?<equal>=)\s*'(?<attrval>[^']*)'|\s*(?<equal>=)\s*(?<attrval>[^\s%>]*)|(?<equal>)(?<attrval>\s*?)))*\s*?%>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
#endif
+ static readonly Regex runatServer = new Regex (@"<[\w:\.]+.*?runat=[""']?server[""']?.*?/?>",
+ RegexOptions.Compiled | RegexOptions.Singleline |
+ RegexOptions.Multiline | RegexOptions.IgnoreCase |
+ RegexOptions.CultureInvariant);
+
+ static readonly Regex endOfTag = new Regex (@"</[\w:\.]+\s*?>",
+ RegexOptions.Compiled | RegexOptions.Singleline |
+ RegexOptions.Multiline | RegexOptions.IgnoreCase |
+ RegexOptions.CultureInvariant);
+
+ static readonly Regex expressionRegex = new Regex (@"<%.*?%>",
+ RegexOptions.Compiled | RegexOptions.Singleline |
+ RegexOptions.Multiline | RegexOptions.IgnoreCase |
+ RegexOptions.CultureInvariant);
+
+ static readonly Regex clientCommentRegex = new Regex (@"<!--(.|\s)*?-->",
+ RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase |
+ RegexOptions.CultureInvariant);
+
ParserStack pstack;
BuilderLocationStack stack;
TemplateParser tparser;
return type;
}
+#if NET_2_0
Parse ();
-
+#else
+ try {
+ Parse ();
+ } catch (ParseException ex) {
+ throw new HttpException ("Compilation failed.", ex);
+ }
+#endif
BaseCompiler compiler = GetCompilerFromType ();
type = compiler.GetCompiledType ();
// The kludge supports only self-closing tags inside attributes.
//
// KLUDGE WARNING!!
- static readonly Regex runatServer=new Regex (@"<[\w:\.]+.*?runat=[""']?server[""']?.*?/>",
- RegexOptions.Compiled | RegexOptions.Singleline |
- RegexOptions.Multiline | RegexOptions.IgnoreCase |
- RegexOptions.CultureInvariant);
bool ProcessTagsInAttributes (ILocation location, string tagid, TagAttributes attributes, TagType type)
{
if (attributes == null || attributes.Count == 0)
TextParsed (location, String.Format (" {0}=\"{1}", key, index > 0 ? value.Substring (0, index) : String.Empty));;
FlushText ();
- ParseAttributeTag (group.Value);
+ ParseAttributeTag (group.Value, location);
if (index + length < value.Length)
TextParsed (location, value.Substring (index + length) + "\"");
else
return retval;
}
- void ParseAttributeTag (string code)
+ void ParseAttributeTag (string code, ILocation location)
{
- AspParser parser = new AspParser ("@@attribute_tag@@", new StringReader (code));
+ AspParser parser = new AspParser ("@@attribute_tag@@", new StringReader (code), location.BeginLine - 1, location as AspParser);
parser.Error += new ParseErrorHandler (ParseError);
parser.TagParsed += new TagParsedHandler (TagParsed);
parser.TextParsed += new TextParsedHandler (TextParsed);
return Path.GetFullPath (Path.Combine (basedir, filename));
}
+
+ delegate bool CheckBlockEnd (string text);
- void TextParsed (ILocation location, string text)
+ bool CheckTagEndNeeded (string text)
{
- if (ignore_text)
- return;
-
- // Another gross hack - get rid of comments in the parsed text
- int textLen = text.Length;
- int textMaxIndex = textLen - 1;
- int commentStart = text.IndexOf ("<!--");
- int commentLastStart = 0;
+ return !text.EndsWith ("/>");
+ }
+
#if NET_2_0
- List <int> commentRanges = null;
+ List <TextBlock>
#else
- ArrayList commentRanges = null;
+ ArrayList
#endif
-
- while (commentStart != -1) {
- int commentEnd = text.IndexOf ("-->", commentStart);
-
- if (commentEnd == -1) {
- if (commentStart == 0)
- return;
- commentEnd = textMaxIndex;
- }
-
- if (commentRanges == null) {
+ FindRegexBlocks (Regex rxStart, Regex rxEnd, CheckBlockEnd checkEnd, IList blocks, TextBlockType typeForMatches, bool discardBlocks)
+ {
#if NET_2_0
- commentRanges = new List <int> ();
+ var ret = new List <TextBlock> ();
#else
- commentRanges = new ArrayList ();
+ ArrayList ret = new ArrayList ();
#endif
+
+ foreach (TextBlock block in blocks) {
+ if (block.Type != TextBlockType.Verbatim) {
+ ret.Add (block);
+ continue;
}
- if (commentStart > commentLastStart) {
- commentRanges.Add (commentLastStart);
- commentRanges.Add (commentStart);
- }
+ int lastIndex = 0, index;
+ MatchCollection matches = rxStart.Matches (block.Content);
+ bool foundMatches = matches.Count > 0;
+ foreach (Match match in matches) {
+ foundMatches = true;
+ index = match.Index;
+ if (lastIndex < index)
+ ret.Add (new TextBlock (TextBlockType.Verbatim, block.Content.Substring (lastIndex, index - lastIndex)));
- if (commentEnd == textMaxIndex)
- break;
-
- commentLastStart = commentEnd + 3;
- if (commentLastStart > textMaxIndex)
- break;
-
- commentStart = text.IndexOf ("<!--", commentLastStart);
- if (commentStart == -1) {
- int tailLength = textMaxIndex - commentLastStart;
- if (tailLength > 0) {
- commentRanges.Add (commentLastStart);
- commentRanges.Add (tailLength);
+ string value = match.Value;
+ if (rxEnd != null && checkEnd (value)) {
+ int startFrom = index + value.Length;
+ Match m = rxEnd.Match (block.Content, startFrom);
+ if (m.Success)
+ value += block.Content.Substring (startFrom, m.Index - startFrom) + m.Value;
}
- break;
+
+ if (!discardBlocks)
+ ret.Add (new TextBlock (typeForMatches, value));
+ lastIndex = index + value.Length;
}
+
+ if (lastIndex > 0 && lastIndex < block.Content.Length)
+ ret.Add (new TextBlock (TextBlockType.Verbatim, block.Content.Substring (lastIndex)));
+
+ if (!foundMatches)
+ ret.Add (block);
}
- if (commentRanges != null) {
- if (commentRanges.Count == 0)
- return;
-
- StringBuilder sb = new StringBuilder ();
- for (int i = 0; i < commentRanges.Count; i += 2) {
+ return ret;
+ }
+
+ IList SplitTextIntoBlocks (string text)
+ {
#if NET_2_0
- sb.Append (text.Substring (commentRanges [i], commentRanges [i + 1]));
+ var ret = new List <TextBlock> ();
#else
- sb.Append (text.Substring ((int)commentRanges [i], (int)commentRanges [i + 1]));
+ ArrayList ret = new ArrayList ();
#endif
- }
- string noComments = sb.ToString ().Trim ();
- if (noComments.Length == 0)
- return;
+ ret.Add (new TextBlock (TextBlockType.Verbatim, text));
+ ret = FindRegexBlocks (clientCommentRegex, null, null, ret, TextBlockType.Comment, false);
+ ret = FindRegexBlocks (runatServer, endOfTag, CheckTagEndNeeded, ret, TextBlockType.Tag, false);
+ ret = FindRegexBlocks (expressionRegex, null, null, ret, TextBlockType.Expression, false);
- text = noComments;
- }
+ return ret;
+ }
- // And again... the first one wins - if we have expressions and server-side
- // controls together in one block of plain text, tough luck...
- if (text.IndexOf ("<%") != -1 && !inScript) {
- if (this.text.Length > 0)
- FlushText (true);
- CodeRenderParser r = new CodeRenderParser (text, stack.Builder);
- r.AddChildren (this);
+ void TextParsed (ILocation location, string text)
+ {
+ if (ignore_text)
+ return;
+
+ if (inScript) {
+ this.text.Append (text);
+ FlushText (true);
return;
}
+
+ IList blocks = SplitTextIntoBlocks (text);
+ foreach (TextBlock block in blocks) {
+ switch (block.Type) {
+ case TextBlockType.Verbatim:
+ this.text.Append (block.Content);
+ break;
- int startIndex = 0, index = 0;
- Match match;
+ case TextBlockType.Expression:
+ if (this.text.Length > 0)
+ FlushText (true);
+ CodeRenderParser r = new CodeRenderParser (block.Content, stack.Builder, location);
+ r.AddChildren (this);
+ break;
- while (index > -1 && startIndex < textLen) {
- match = runatServer.Match (text, index);
-
- if (match.Success) {
- string value = match.Value;
- index = match.Index;
- if (index > startIndex)
- this.text.Append (text.Substring (startIndex, index - startIndex));
- ParseAttributeTag (value);
- index += value.Length;
- startIndex = index;
- } else
- break;
+ case TextBlockType.Tag:
+ ParseAttributeTag (block.Content, location);
+ break;
- if (index < textLen)
- index = text.IndexOf ('<', index);
- else
- break;
+ case TextBlockType.Comment: {
+ this.text.Append ("<!--");
+ FlushText (true);
+ AspParser parser = new AspParser ("@@comment_code@@",
+ new StringReader (block.Content.Substring (4, block.Length - 7)),
+ location.BeginLine - 1,
+ location as AspParser);
+ parser.Error += new ParseErrorHandler (ParseError);
+ parser.TagParsed += new TagParsedHandler (TagParsed);
+ parser.TextParsed += new TextParsedHandler (TextParsed);
+ parser.Parse ();
+ this.text.Append ("-->");
+ FlushText (true);
+ break;
+ }
+ }
}
-
- this.text.Append (text.Substring (startIndex));
- //PrintLocation (location);
}
void FlushText ()
CheckLanguage (language);
string src = (string) attributes ["src"];
if (src != null) {
- if (src == "")
+ if (src.Length == 0)
throw new ParseException (Parser,
"src cannot be an empty string");
string str;
ControlBuilder builder;
AspGenerator generator;
+ ILocation location;
- public CodeRenderParser (string str, ControlBuilder builder)
+ public CodeRenderParser (string str, ControlBuilder builder, ILocation location)
{
this.str = str;
this.builder = builder;
+ this.location = location;
}
public void AddChildren (AspGenerator generator)
void DoParseExpressions (string str)
{
int startIndex = 0, index = 0;
- Regex codeDirective = new Regex ("(<%(?!@)(?<code>.*?)%>)|(<[\\w:\\.]+.*?runat=[\"']?server[\"']?.*?/>)",
+ Regex codeDirective = new Regex ("(<%(?!@)(?<code>(.|\\s)*?)%>)|(<[\\w:\\.]+.*?runat=[\"']?server[\"']?.*?/>)",
RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.CultureInvariant);
Match match;
int strLen = str.Length;
void DoParse (string str)
{
- AspParser parser = new AspParser ("@@nested_tag@@", new StringReader (str));
+ AspParser parser = new AspParser ("@@code_render@@", new StringReader (str), location.BeginLine - 1, location as AspParser);
parser.Error += new ParseErrorHandler (ParseError);
parser.TagParsed += new TagParsedHandler (TagParsed);
parser.TextParsed += new TextParsedHandler (TextParsed);
string verbatimID;
string fileText;
StringReader fileReader;
+ bool _internal;
+ int _internalLineOffset;
+ AspParser outer;
EventHandlerList events = new EventHandlerList ();
this.filename = filename;
this.fileText = input.ReadToEnd ();
this.fileReader = new StringReader (this.fileText);
+ this._internalLineOffset = 0;
tokenizer = new AspTokenizer (this.fileReader);
}
+ public AspParser (string filename, TextReader input, int startLineOffset, AspParser outer)
+ : this (filename, input)
+ {
+ this._internal = true;
+ this._internalLineOffset = startLineOffset;
+ this.outer = outer;
+ }
+
#if NET_2_0
public byte[] MD5Checksum {
get {
#endif
public int BeginLine {
- get { return beginLine; }
+ get {
+ if (Internal)
+ return beginLine + InternalLineOffset;
+
+ return beginLine;
+ }
}
public int BeginColumn {
}
public int EndLine {
- get { return endLine; }
+ get {
+ if (Internal)
+ return endLine + InternalLineOffset;
+ return endLine;
+ }
}
public int EndColumn {
get { return endColumn; }
}
+ public bool Internal {
+ get { return _internal; }
+ set { _internal = value; }
+ }
+
+ public int InternalLineOffset {
+ get { return _internalLineOffset; }
+ set { _internalLineOffset = value; }
+ }
+
public string FileText {
get {
- if (fileText != null)
- return fileText;
+ string ret = null;
- return null;
+ if (Internal && outer != null)
+ ret = outer.FileText;
+
+ if (ret == null && fileText != null)
+ ret = fileText;
+
+ return ret;
}
}
if (beginPosition >= endPosition || fileText == null)
return null;
- return fileText.Substring (beginPosition, endPosition - beginPosition);
+ string text = FileText;
+ int start, len;
+
+ if (Internal && outer != null) {
+ start = beginPosition + InternalLineOffset;
+ len = (endPosition + InternalLineOffset) - start;
+ } else {
+ start = beginPosition;
+ len = endPosition - beginPosition;
+ }
+
+ if (text != null)
+ return text.Substring (start, len);
+
+ return null;
}
}
public string Filename {
- get { return filename; }
+ get {
+ if (Internal && outer != null)
+ return outer.Filename;
+
+ return filename;
+ }
}
public string VerbatimID {
var cache = new Dictionary <string, bool> (dictionaryComparer);
AddVirtualDir (GetVirtualDirectory (virtualPath.Absolute), bpcoll, cache);
cache = null;
+ if (buildProviders == null || buildProviders.Count == 0)
+ AddVirtualFile (GetVirtualFile (virtualPath.Absolute), bpcoll);
}
if (buildProviders == null || buildProviders.Count == 0)
- return null;
+ return null;
var buildProviderGroups = new List <BuildProviderGroup> ();
foreach (BuildProvider bp in buildProviders.Values)
{
if (!vpp.DirectoryExists (VirtualPathUtility.GetDirectory (virtualPath)))
return null;
-
+
return vpp.GetDirectory (virtualPath);
}
+2009-08-18 Marek Habersack <mhabersack@novell.com>
+
+ * AspParser.cs: added a constructor which creates an internal
+ parser, nested within the outer one, and adjusts its ILocation
+ members to report correct locations in the outer parser for better
+ error reporting. Inner parser also returns the outer's FileText,
+ if available.
+
+ * AspGenerator.cs: restored part of r138474 reverted in r138657,
+ r138658 and r138659 to fix bug #525104
+ BuilderLocation creates a copy of Location for its own use (since
+ the ILocation passed is actually AspParser, the line numbers
+ change between creating a BuilderLocation and using its Location
+ member).
+ The end of tag, expression and client comment regular expressions
+ now use lazy quantifiers. This fixes bugs #525104 and #517656
+ Client side comment blocks aren't ignored anymore, they are parsed
+ just as the other parts of the document. Fixes bug #524358
+
+2009-08-15 Marek Habersack <mhabersack@novell.com>
+
+ * AspGenerator.cs: CodeRenderParser.DoParseExpressions - match
+ newline characters inside expressions. Fixes bug #526449
+
+2009-08-14 Marek Habersack <mhabersack@novell.com>
+
+ * BuildManagerDirectoryBuilder.cs: when VirtualPathProvider
+ reports a virtual directory doesn't exist, try to get the
+ requested virtual path using VirtualPathProvider.GetFile. Fixes
+ #525974
+
2009-07-30 Gonzalo Paniagua Javier <gonzalo@novell.com>
* BuildManager.cs: path fixup should work now for /foo running on
+2009-08-18 Marek Habersack <mhabersack@novell.com>
+
+ * ControlBuilder.cs: Location property makes a copy of assigned
+ ILocation now.
+
+2009-08-14 Marek Habersack <mhabersack@novell.com>
+
+ * ControlBuilder.cs: when CreateSubBuilder is called on a builder
+ which is supposed to treat its children as properties and the
+ default property builder is defined, first check if the tag which
+ has just been parsed isn't a template property. If it is, don't
+ use the default property builder, instead create a template
+ property builder directly. Fixes bug #527753
+
2009-07-23 Marek Habersack <mhabersack@novell.com>
* ControlBuilder.cs: added an internal helper property
using System.IO;
using System.Web.UI.WebControls;
+using _Location = System.Web.Compilation.Location;
+
namespace System.Web.UI {
// CAS
internal ILocation Location {
get { return location; }
- set { location = value; }
+ set { location = new _Location (value); }
}
internal ArrayList OtherTags {
{
this.parser = parser;
if (parser != null)
- this.location = parser.Location;
+ this.Location = parser.Location;
this.parentBuilder = parentBuilder;
this.type = type;
// builder call.
defaultPropertyBuilder = null;
childBuilder = CreatePropertyBuilder (tagid, parser, atts);
- } else
- childBuilder = defaultPropertyBuilder.CreateSubBuilder (tagid, atts,
- null, parser,
- location);
+ } else {
+ Type ct = ControlType;
+ MemberInfo[] mems = ct != null ? ct.GetMember (tagid, MemberTypes.Property, FlagsNoCase) : null;
+ PropertyInfo prop = mems != null && mems.Length > 0 ? mems [0] as PropertyInfo : null;
+
+ if (prop != null && typeof (ITemplate).IsAssignableFrom (prop.PropertyType)) {
+ childBuilder = CreatePropertyBuilder (tagid, parser, atts);
+ defaultPropertyBuilder = null;
+ } else
+ childBuilder = defaultPropertyBuilder.CreateSubBuilder (tagid, atts, null, parser, location);
+ }
}
return childBuilder;
mainsoft/NunitWeb/NunitWeb/CustomSection.cs
mainsoft/NunitWeb/NunitWeb/FakeMembershipProvider.cs
mainsoft/NunitWeb/NunitWeb/FormRequest.cs
+mainsoft/NunitWeb/NunitWeb/Global.asax.cs
mainsoft/NunitWeb/NunitWeb/IForeignData.cs
mainsoft/NunitWeb/NunitWeb/HandlerInvoker.cs
mainsoft/NunitWeb/NunitWeb/MyHandler.cs
+2009-08-18 Marek Habersack <mhabersack@novell.com>
+
+ * TemplateControlCompilerTest.cs: added test for bug #525104 and
+ improved test for bug #517656
+
2009-07-08 Marek Habersack <mhabersack@novell.com>
* TemplateControlCompilerTest.cs: added test for bug #520024
WebTest.CopyResource (GetType (), "UnquotedAngleBrackets.aspx", "UnquotedAngleBrackets.aspx");
WebTest.CopyResource (GetType (), "FullTagsInText.aspx", "FullTagsInText.aspx");
WebTest.CopyResource (GetType (), "TagsExpressionsAndCommentsInText.aspx", "TagsExpressionsAndCommentsInText.aspx");
+ WebTest.CopyResource (GetType (), "NewlineInCodeExpression.aspx", "NewlineInCodeExpression.aspx");
+ WebTest.CopyResource (GetType (), "DuplicateControlsInClientComment.aspx", "DuplicateControlsInClientComment.aspx");
#if NET_2_0
WebTest.CopyResource (GetType (), "InvalidPropertyBind1.aspx", "InvalidPropertyBind1.aspx");
WebTest.CopyResource (GetType (), "InvalidPropertyBind2.aspx", "InvalidPropertyBind2.aspx");
// Just test if it doesn't throw an exception
new WebTest ("PreprocessorDirectivesInMarkup.aspx").Run ();
}
-#endif
+ [Test (Description="Bug #526449")]
+ public void NewlineInCodeExpression ()
+ {
+ string pageHtml = new WebTest ("NewlineInCodeExpression.aspx").Run ();
+ string renderedHtml = HtmlDiff.GetControlFromPageHtml (pageHtml);
+ string originalHtml = "<a href=\"test\">bla</a>";
+ HtmlDiff.AssertAreEqual (originalHtml, renderedHtml, "#A1");
+ }
+
+ [Test (Description="Bug #524358")]
+ [ExpectedException (typeof (HttpException))]
+ public void DuplicateControlsInClientComment ()
+ {
+ // Just test if it throws an exception
+ new WebTest ("DuplicateControlsInClientComment.aspx").Run ();
+ }
+#endif
+
[Test (Description="Bug #517656")]
public void ServerControlInClientSideComment ()
{
- // We just test if it doesn't throw an exception
- new WebTest ("ServerControlInClientSideComment.aspx").Run ();
+ string pageHtml = new WebTest ("ServerControlInClientSideComment.aspx").Run ();
+ string renderedHtml = HtmlDiff.GetControlFromPageHtml (pageHtml);
+ string originalHtml = @"<!-- comment start
+ <input id=""testBox"" type=""checkbox"" name=""testBox"" />
+comment end -->";
+ HtmlDiff.AssertAreEqual (originalHtml, renderedHtml, "#A1");
}
[Test]
--- /dev/null
+using System;\r
+\r
+namespace MainsoftWebApp\r
+{\r
+ public partial class Global : System.Web.HttpApplication\r
+ {\r
+#if NET_2_0\r
+ protected void Application_Error (object sender, EventArgs e)\r
+ {\r
+ // Code that runs when an unhandled error occurs\r
+ Exception objErr = Server.GetLastError ().GetBaseException ();\r
+ MonoTests.SystemWeb.Framework.WebTest.RegisterException (objErr);\r
+ Server.ClearError ();\r
+ }\r
+\r
+ protected void Application_OnEndRequest (object sender, EventArgs e) {\r
+ // Ensure the headers are sent\r
+ MonoTests.SystemWeb.Framework.WebTest.CurrentTest.SendHeaders ();\r
+ }\r
+#endif\r
+ }\r
+}\r
-<%@ Application Language="C#" Inherits="MainsoftWebApp20.Global" CodeFile="Global.asax.cs" %>\r
+<%@ Application Language="C#" Inherits="MainsoftWebApp.Global" %>
+++ /dev/null
-using System;\r
-\r
-namespace MainsoftWebApp20\r
-{\r
- public partial class Global : System.Web.HttpApplication\r
- {\r
- protected void Application_Error (object sender, EventArgs e)\r
- {\r
- // Code that runs when an unhandled error occurs\r
- Exception objErr = Server.GetLastError ().GetBaseException ();\r
- MonoTests.SystemWeb.Framework.WebTest.RegisterException (objErr);\r
- Server.ClearError ();\r
- }\r
-\r
- protected void Application_OnEndRequest (object sender, EventArgs e) {\r
- // Ensure the headers are sent\r
- MonoTests.SystemWeb.Framework.WebTest.CurrentTest.SendHeaders ();\r
- }\r
- }\r
-}\r
--- /dev/null
+<%@ Page Language="C#" AutoEventWireup="true" %>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head runat="server">
+ <title></title>
+</head>
+<body>
+ <form id="form1" runat="server">
+ <div>
+ Hello World of mono lovers
+ <!-- <asp:Literal ID="form1" runat="server" />
+
+ <br> -->
+ </div>
+ <asp:Repeater runat="server" id="r1">
+ <ItemTemplate>
+ <asp:Literal ID="form2" runat="server" />
+ </ItemTemplate>
+ </asp:Repeater>
+ </form>
+</body>
+</html>
--- /dev/null
+<%@ Page Language="C#" AutoEventWireup="true" %>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head runat="server">
+ <title></title>
+</head>
+<body>
+ <form id="form1" runat="server">
+ <div>
+ <%= MonoTests.stand_alone.WebHarness.HtmlDiff.BEGIN_TAG %><a href="<%= "test"
+ %>">bla</a><%= MonoTests.stand_alone.WebHarness.HtmlDiff.END_TAG %>
+ </div>
+ </form>
+</body>
+</html>
<%@ Page Language = "C#" %>
<html><head><title>Bug 517656</title><head><body>
+<form runat="server">
+<%= MonoTests.stand_alone.WebHarness.HtmlDiff.BEGIN_TAG %><!-- comment start
+ <asp:Checkbox id="testBox" runat="server" />
+comment end --><%= MonoTests.stand_alone.WebHarness.HtmlDiff.END_TAG %>
<p>ASP.NET repeater control to follow...</p>
<asp:Repeater id="censusRepeater" runat="server">
<HeaderTemplate />
</ItemTemplate>
<FooterTemplate />
</asp:Repeater>
+</form>
</body></html>
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * System.dll.sources: Adding ParallelFx files.
+ * System_test.dll.sources: Adding ParallelFx test files.
+
2009-07-26 Raja R Harinath <harinath@hurrynot.org>
* Makefile ($(build_lib)): Make CYCLIC_DEP_FILES depend on this.
+2009-08-13 Marek Habersack <mhabersack@novell.com>
+
+ * CodeTypeReference.cs: generic types specialized on arrays must
+ not be treated as array declarations. Fixes bug #523341
+
2008-02-10 Juraj Skripsky <js@hotfeet.ch>
* CodeObject.cs: Add empty Visit method implementation.
return;
}
+ int lastAngle = baseType.LastIndexOf ('>');
+ if (lastAngle != -1 && lastAngle > array_end) {
+ this.baseType = baseType;
+ return;
+ }
+
string[] args = baseType.Substring (array_start + 1, array_end - array_start - 1).Split (',');
if ((array_end - array_start) != args.Length) {
--- /dev/null
+#if NET_4_0
+// BlockingCollection.cs
+//
+// Copyright (c) 2008 Jérémie "Garuma" Laval
+//
+// 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.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, IDisposable
+ {
+ readonly IProducerConsumerCollection<T> underlyingColl;
+ readonly int upperBound;
+
+ readonly SpinWait sw = new SpinWait ();
+
+ AtomicBoolean isComplete;
+ long completeId;
+
+ long addId = long.MinValue;
+ long removeId = long.MinValue;
+
+ #region ctors
+ public BlockingCollection ()
+ : this (new ConcurrentQueue<T> (), -1)
+ {
+ }
+
+ public BlockingCollection (int upperBound)
+ : this (new ConcurrentQueue<T> (), upperBound)
+ {
+ }
+
+ public BlockingCollection (IProducerConsumerCollection<T> underlyingColl)
+ : this (underlyingColl, -1)
+ {
+ }
+
+ public BlockingCollection (IProducerConsumerCollection<T> underlyingColl, int upperBound)
+ {
+ this.underlyingColl = underlyingColl;
+ this.upperBound = upperBound;
+ this.isComplete = new AtomicBoolean ();
+ }
+ #endregion
+
+ #region Add & Remove (+ Try)
+ public void Add (T item)
+ {
+ Add (item, null);
+ }
+
+ public void Add (T item, CancellationToken token)
+ {
+ Add (item, () => token.IsCancellationRequested);
+ }
+
+ void Add (T item, Func<bool> cancellationFunc)
+ {
+ while (true) {
+ long cachedAddId = addId;
+ long cachedRemoveId = removeId;
+
+ if (upperBound != -1) {
+ if (cachedAddId - cachedRemoveId > upperBound) {
+ Block ();
+ continue;
+ }
+ }
+
+ // Check our transaction id against completed stored one
+ if (isComplete.Value && cachedAddId >= completeId)
+ throw new InvalidOperationException ("The BlockingCollection<T> has"
+ + " been marked as complete with regards to additions.");
+
+ if (Interlocked.CompareExchange (ref addId, cachedAddId + 1, cachedAddId) == cachedAddId)
+ break;
+
+ if (cancellationFunc != null && cancellationFunc ())
+ throw new OperationCanceledException ("CancellationToken triggered");
+ }
+
+
+ if (!underlyingColl.TryAdd (item))
+ throw new InvalidOperationException ("The underlying collection didn't accept the item.");
+ }
+
+ public T Take ()
+ {
+ return Take (null);
+ }
+
+ public T Take (CancellationToken token)
+ {
+ return Take (() => token.IsCancellationRequested);
+ }
+
+ T Take (Func<bool> cancellationFunc)
+ {
+ while (true) {
+ long cachedRemoveId = removeId;
+ long cachedAddId = addId;
+
+ // Empty case
+ if (cachedRemoveId == cachedAddId) {
+ if (isComplete.Value && cachedRemoveId >= completeId)
+ throw new OperationCanceledException ("The BlockingCollection<T> has"
+ + " been marked as complete with regards to additions.");
+
+ Block ();
+ continue;
+ }
+
+ if (Interlocked.CompareExchange (ref removeId, cachedRemoveId + 1, cachedRemoveId) == cachedRemoveId)
+ break;
+
+ if (cancellationFunc != null && cancellationFunc ())
+ throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
+ }
+
+ T item;
+ while (!underlyingColl.TryTake (out item));
+
+ return item;
+ }
+
+ public bool TryAdd (T item)
+ {
+ return TryAdd (item, null, null);
+ }
+
+ bool TryAdd (T item, Func<bool> contFunc, CancellationToken? token)
+ {
+ do {
+ if (token.HasValue && token.Value.IsCancellationRequested)
+ throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
+
+ long cachedAddId = addId;
+ long cachedRemoveId = removeId;
+
+ if (upperBound != -1) {
+ if (cachedAddId - cachedRemoveId > upperBound) {
+ continue;
+ }
+ }
+
+ // Check our transaction id against completed stored one
+ if (isComplete.Value && cachedAddId >= completeId)
+ throw new InvalidOperationException ("The BlockingCollection<T> has"
+ + " been marked as complete with regards to additions.");
+
+ if (Interlocked.CompareExchange (ref addId, cachedAddId + 1, cachedAddId) != cachedAddId)
+ continue;
+
+ if (!underlyingColl.TryAdd (item))
+ throw new InvalidOperationException ("The underlying collection didn't accept the item.");
+
+ return true;
+ } while (contFunc != null && contFunc ());
+
+ return false;
+ }
+
+ public bool TryAdd (T item, TimeSpan ts)
+ {
+ return TryAdd (item, (int)ts.TotalMilliseconds);
+ }
+
+ public bool TryAdd (T item, int millisecondsTimeout)
+ {
+ Stopwatch sw = Stopwatch.StartNew ();
+ return TryAdd (item, () => sw.ElapsedMilliseconds < millisecondsTimeout, null);
+ }
+
+ public bool TryAdd (T item, int millisecondsTimeout, CancellationToken token)
+ {
+ Stopwatch sw = Stopwatch.StartNew ();
+ return TryAdd (item, () => sw.ElapsedMilliseconds < millisecondsTimeout, token);
+ }
+
+ public bool TryTake (out T item)
+ {
+ return TryTake (out item, null, null);
+ }
+
+ bool TryTake (out T item, Func<bool> contFunc, CancellationToken? token)
+ {
+ item = default (T);
+
+ do {
+ if (token.HasValue && token.Value.IsCancellationRequested)
+ throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
+
+ long cachedRemoveId = removeId;
+ long cachedAddId = addId;
+
+ // Empty case
+ if (cachedRemoveId == cachedAddId) {
+ if (isComplete.Value && cachedRemoveId >= completeId)
+ continue;
+
+ continue;
+ }
+
+ if (Interlocked.CompareExchange (ref removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId)
+ continue;
+
+ return underlyingColl.TryTake (out item);
+ } while (contFunc != null && contFunc ());
+
+ return false;
+ }
+
+ public bool TryTake (out T item, TimeSpan ts)
+ {
+ return TryTake (out item, (int)ts.TotalMilliseconds);
+ }
+
+ public bool TryTake (out T item, int millisecondsTimeout)
+ {
+ item = default (T);
+ Stopwatch sw = Stopwatch.StartNew ();
+
+ return TryTake (out item, () => sw.ElapsedMilliseconds < millisecondsTimeout, null);
+ }
+
+ public bool TryTake (out T item, int millisecondsTimeout, CancellationToken token)
+ {
+ item = default (T);
+ Stopwatch sw = Stopwatch.StartNew ();
+
+ return TryTake (out item, () => sw.ElapsedMilliseconds < millisecondsTimeout, token);
+ }
+ #endregion
+
+ #region static methods
+ static void CheckArray (BlockingCollection<T>[] collections)
+ {
+ if (collections == null)
+ throw new ArgumentNullException ("collections");
+ if (collections.Length == 0 || IsThereANullElement (collections))
+ throw new ArgumentException ("The collections argument is a 0-length array or contains a null element.", "collections");
+ }
+
+ static bool IsThereANullElement (BlockingCollection<T>[] collections)
+ {
+ foreach (BlockingCollection<T> e in collections)
+ if (e == null)
+ return true;
+ return false;
+ }
+
+ public static int AddToAny (BlockingCollection<T>[] collections, T item)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ try {
+ coll.Add (item);
+ return index;
+ } catch {}
+ index++;
+ }
+ return -1;
+ }
+
+ public static int AddToAny (BlockingCollection<T>[] collections, T item, CancellationToken token)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ try {
+ coll.Add (item, token);
+ return index;
+ } catch {}
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryAddToAny (BlockingCollection<T>[] collections, T item)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryAdd (item))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryAddToAny (BlockingCollection<T>[] collections, T item, TimeSpan ts)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryAdd (item, ts))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryAddToAny (BlockingCollection<T>[] collections, T item, int millisecondsTimeout)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryAdd (item, millisecondsTimeout))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryAddToAny (BlockingCollection<T>[] collections, T item, int millisecondsTimeout,
+ CancellationToken token)
+ {
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryAdd (item, millisecondsTimeout, token))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TakeFromAny (BlockingCollection<T>[] collections, out T item)
+ {
+ item = default (T);
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ try {
+ item = coll.Take ();
+ return index;
+ } catch {}
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TakeFromAny (BlockingCollection<T>[] collections, out T item, CancellationToken token)
+ {
+ item = default (T);
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ try {
+ item = coll.Take (token);
+ return index;
+ } catch {}
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryTakeFromAny (BlockingCollection<T>[] collections, out T item)
+ {
+ item = default (T);
+
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryTake (out item))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryTakeFromAny (BlockingCollection<T>[] collections, out T item, TimeSpan ts)
+ {
+ item = default (T);
+
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryTake (out item, ts))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryTakeFromAny (BlockingCollection<T>[] collections, out T item, int millisecondsTimeout)
+ {
+ item = default (T);
+
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryTake (out item, millisecondsTimeout))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+ public static int TryTakeFromAny (BlockingCollection<T>[] collections, out T item, int millisecondsTimeout,
+ CancellationToken token)
+ {
+ item = default (T);
+
+ CheckArray (collections);
+ int index = 0;
+ foreach (var coll in collections) {
+ if (coll.TryTake (out item, millisecondsTimeout, token))
+ return index;
+ index++;
+ }
+ return -1;
+ }
+ #endregion
+
+ public void CompleteAdding ()
+ {
+ // No further add beside that point
+ completeId = addId;
+ isComplete.Value = true;
+ }
+
+ void ICollection.CopyTo (Array array, int index)
+ {
+ underlyingColl.CopyTo (array, index);
+ }
+
+ public void CopyTo (T[] array, int index)
+ {
+ underlyingColl.CopyTo (array, index);
+ }
+
+ public IEnumerable<T> GetConsumingEnumerable ()
+ {
+ return GetConsumingEnumerable (Take);
+ }
+
+ public IEnumerable<T> GetConsumingEnumerable (CancellationToken token)
+ {
+ return GetConsumingEnumerable (() => Take (token));
+ }
+
+ IEnumerable<T> GetConsumingEnumerable (Func<T> getFunc)
+ {
+ while (true) {
+ T item = default (T);
+
+ try {
+ item = getFunc ();
+ } catch {
+ break;
+ }
+
+ yield return item;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return ((IEnumerable)underlyingColl).GetEnumerator ();
+ }
+
+ IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+ {
+ return ((IEnumerable<T>)underlyingColl).GetEnumerator ();
+ }
+
+ public void Dispose ()
+ {
+
+ }
+
+ protected virtual void Dispose (bool managedRes)
+ {
+
+ }
+
+ public T[] ToArray ()
+ {
+ return underlyingColl.ToArray ();
+ }
+
+ // Method used to stall the thread for a limited period of time before retrying an operation
+ void Block ()
+ {
+ sw.SpinOnce ();
+ }
+
+ public int BoundedCapacity {
+ get {
+ return upperBound;
+ }
+ }
+
+ public int Count {
+ get {
+ return underlyingColl.Count;
+ }
+ }
+
+ public bool IsAddingCompleted {
+ get {
+ return isComplete.Value;
+ }
+ }
+
+ public bool IsCompleted {
+ get {
+ return isComplete.Value && addId == removeId;
+ }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ return underlyingColl.SyncRoot;
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get {
+ return underlyingColl.IsSynchronized;
+ }
+ }
+ }
+}
+#endif
--- /dev/null
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * BlockingCollection.cs: Rewrite to use a transaction id
+ based approach. Ported to 4.0 API. Fix GetConsumingEnumerable.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * BlockingCollection.cs: New addition.
+2009-08-17 Geoff Norton <gnorton@novell.com>
+
+ * NtlmClient.cs: Mono.Http does not exist on monotouch
+
+2009-08-17 Sebastien Pouliot <sebastien@ximian.com>
+
+ * CookieCollection.cs: Seal class for NET_2_1 (SL3)
+ * CookieContainer.cs: Seal class for NET_2_1 (SL3)
+ * NetworkCredential.cs: Use in NET_2_1 (SL3) but without implementing
+ ICredentialsByHost
+
+2009-08-13 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * HttpWebRequest.cs:
+ * WebConnectionStream.cs: if there's an error writing the headers from
+ a buffered request, propagate the error instead of hiding it and
+ causing a different one later (ie, ObjectDisposedException instead of
+ the original WebException). This happened when posting without
+ Content-Length set to an HTTPS url without validating the server
+ certificate.
+
2009-07-28 Gonzalo Paniagua Javier <gonzalo@novell.com>
* WebClient.cs: rethrow WebExceptions instead of creating a new one
namespace System.Net
{
[Serializable]
- public class CookieCollection : ICollection, IEnumerable
- {
+#if NET_2_1
+ public sealed class CookieCollection : ICollection, IEnumerable {
+#else
+ public class CookieCollection : ICollection, IEnumerable {
+#endif
class CookieCollectionPathComparer : IComparer
{
int IComparer.Compare (object p1, object p2)
{
[Serializable]
[MonoTODO ("Need to remove older/unused cookies if it reaches the maximum capacity")]
- public class CookieContainer
- {
+#if NET_2_1
+ public sealed class CookieContainer {
+#else
+ public class CookieContainer {
+#endif
public const int DefaultCookieLengthLimit = 4096;
public const int DefaultCookieLimit = 300;
public const int DefaultPerDomainCookieLimit = 20;
usedPreAuth = true;
}
- internal void SetWriteStreamError (WebExceptionStatus status)
- {
- SetWriteStreamError (status, null);
- }
-
internal void SetWriteStreamError (WebExceptionStatus status, Exception exc)
{
if (Aborted)
}
}
- internal void SendRequestHeaders ()
+ internal void SendRequestHeaders (bool propagate_error)
{
StringBuilder req = new StringBuilder ();
string query;
try {
writeStream.SetHeaders (bytes);
} catch (WebException wexc) {
- SetWriteStreamError (wexc.Status);
- } catch (Exception) {
- SetWriteStreamError (WebExceptionStatus.SendFailure);
+ SetWriteStreamError (wexc.Status, wexc);
+ if (propagate_error)
+ throw;
+ } catch (Exception exc) {
+ SetWriteStreamError (WebExceptionStatus.SendFailure, exc);
+ if (propagate_error)
+ throw;
}
}
writeStream.SendChunked = false;
}
- SendRequestHeaders ();
+ SendRequestHeaders (false);
haveRequest = true;
namespace System.Net
{
public class NetworkCredential : ICredentials
-#if NET_2_0
+#if NET_2_0 && !NET_2_1
, ICredentialsByHost
#endif
{
return this;
}
-#if NET_2_0
+#if NET_2_0 && !NET_2_1
public NetworkCredential GetCredential (string host, int port, string authenticationType)
{
return this;
static NtlmClient ()
{
+#if !MONOTOUCH
Assembly ass = Assembly.Load (Consts.AssemblyMono_Http);
if (ass != null)
ntlmAuthType = ass.GetType ("Mono.Http.NtlmClient", false);
+#endif
}
public NtlmClient ()
method == "TRACE" || method == "DELETE");
if (!no_writestream)
request.InternalContentLength = length;
- request.SendRequestHeaders ();
+ request.SendRequestHeaders (true);
}
WriteHeaders ();
if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100)
+2009-08-18 Raja R Harinath <harinath@hurrynot.org>
+
+ * parser.cs (GetMapping): Extend duplicate check for numeric
+ groups too.
+
+2009-08-17 Raja R Harinath <harinath@hurrynot.org>
+
+ * parser.cs (ResolveReferences): Handle some cases of
+ explicitly-named numeric groups.
+
+2009-08-17 Raja R Harinath <harinath@hurrynot.org>
+
+ * parser.cs (ResolveReferences): Rearrange slightly to prepare for
+ future changes.
+
+2009-08-17 Raja R Harinath <harinath@hurrynot.org>
+
+ * Regex.cs (GetGroupNumbers): List group numbers in ascending order.
+ (GetGroupNames): List names in order of group number.
+
+2009-08-12 Raja R Harinath <harinath@hurrynot.org>
+
+ * syntax.cs (BackslashNumber.ResolveReference): Improve ECMAScript
+ semantics. Handle cases like "group 43 exists but group 4 doesn't".
+
+2009-08-10 Raja R Harinath <harinath@hurrynot.org>
+
+ * syntax.cs (BackslashNumber.ResolveReference): Implement fallback
+ to octal numbers, and ECMAScript semantics.
+ * parser.cs (ResolveReferences): Use it.
+
+2009-08-10 Raja R Harinath <harinath@hurrynot.org>
+
+ * syntax.cs (BackslashNumber): New class.
+ * parser.cs (ParseSpecial): Create it instead of 'Reference' if a
+ numeric backreference is seen.
+
+2009-08-10 Raja R Harinath <harinath@hurrynot.org>
+
+ * parser.cs (ResolveReferences): Allow named groups to be
+ referred-to by their group numbers too.
+
2009-04-23 Sebastien Pouliot <sebastien@ximian.com>
* Regex.cs: Remove Compiler-related support for NET_2_1
public string [] GetGroupNames ()
{
- string [] names = new string [mapping.Count];
- mapping.Keys.CopyTo (names, 0);
-
+ string [] names = new string [1 + group_count];
+ Array.Copy (_groupNumberToNameMap, names, 1 + group_count);
return names;
}
public int[] GetGroupNumbers ()
{
- int[] numbers = new int [mapping.Count];
- mapping.Values.CopyTo (numbers, 0);
-
+ int[] numbers = new int [1 + group_count];
+ for (int i = 0; i <= group_count; ++i)
+ numbers [i] = i;
+ // FIXME: needs to handle arbitrarily numbered groups '(?<43>abc)'
return numbers;
}
mapping.Add ("0", 0);
for (int i = 0; i < end; i++) {
CapturingGroup group = (CapturingGroup) caps [i];
- if (group.Name != null) {
- if (mapping.Contains (group.Name)) {
- if ((int) mapping [group.Name] != group.Number)
- throw new SystemException ("invalid state");
- continue;
- }
- mapping.Add (group.Name, group.Number);
- } else {
- mapping.Add (group.Number.ToString (), group.Number);
+ string name = group.Name != null ? group.Name : group.Number.ToString ();
+ if (mapping.Contains (name)) {
+ if ((int) mapping [name] != group.Number)
+ throw new SystemException ("invalid state");
+ continue;
}
+ mapping.Add (name, group.Number);
}
return mapping;
// FIXME test if number is within number of assigned groups
// this may present a problem for right-to-left matching
- Reference reference = new Reference (IsIgnoreCase (options));
+ Reference reference = new BackslashNumber (IsIgnoreCase (options), ecma);
refs.Add (reference, n.ToString ());
expr = reference;
break;
return result.ToString ();
}
- private void ResolveReferences () {
+ private void ResolveReferences ()
+ {
int gid = 1;
Hashtable dict = new Hashtable ();
// number unnamed groups
foreach (CapturingGroup group in caps) {
- if (group.Name == null) {
- dict.Add (gid.ToString (), group);
- group.Number = gid ++;
+ if (group.Name != null)
+ continue;
- ++ num_groups;
- }
+ dict.Add (gid.ToString (), group);
+ group.Number = gid ++;
+ ++ num_groups;
}
// number named groups
foreach (CapturingGroup group in caps) {
- if (group.Name != null) {
- if (!dict.Contains (group.Name)) {
- dict.Add (group.Name, group);
- group.Number = gid ++;
+ if (group.Name == null)
+ continue;
+ if (dict.Contains (group.Name)) {
+ CapturingGroup prev = (CapturingGroup) dict [group.Name];
+ group.Number = prev.Number;
+ continue;
+ }
+
+ if (Char.IsDigit (group.Name [0])) {
+ int ptr = 0;
+ int group_gid = ParseDecimal (group.Name, ref ptr);
+ if (ptr == group.Name.Length) {
+ // FIXME: Handle non-contiguous groups
+ group.Number = group_gid;
+ dict.Add (group.Name, group);
++ num_groups;
- }
- else {
- CapturingGroup prev = (CapturingGroup)dict[group.Name];
- group.Number = prev.Number;
+ continue;
}
}
+
+ string gid_s = gid.ToString ();
+ while (dict.Contains (gid_s))
+ gid_s = (++gid).ToString ();
+
+ dict.Add (gid_s, group);
+ dict.Add (group.Name, group);
+ group.Number = gid ++;
+ ++ num_groups;
}
// resolve references
foreach (Expression expr in refs.Keys) {
- string name = (string)refs[expr];
+ string name = (string) refs [expr];
if (!dict.Contains (name)) {
if (expr is CaptureAssertion && !Char.IsDigit (name [0]))
continue;
+ BackslashNumber bn = expr as BackslashNumber;
+ if (bn != null && bn.ResolveReference (name, dict))
+ continue;
throw NewParseException ("Reference to undefined group " +
(Char.IsDigit (name[0]) ? "number " : "name ") +
name);
set { ignore = value; }
}
- public override void Compile (ICompiler cmp, bool reverse) {
+ public static void CompileLiteral (string str, ICompiler cmp, bool ignore, bool reverse)
+ {
if (str.Length == 0)
return;
cmp.EmitString (str, ignore, reverse);
}
+ public override void Compile (ICompiler cmp, bool reverse)
+ {
+ CompileLiteral (str, cmp, ignore, reverse);
+ }
+
public override void GetWidth (out int min, out int max) {
min = max = str.Length;
}
private bool ignore;
}
+ class BackslashNumber : Reference {
+ string literal;
+ bool ecma;
+
+ public BackslashNumber (bool ignore, bool ecma)
+ : base (ignore)
+ {
+ this.ecma = ecma;
+ }
+
+ // Precondition: groups [num_str] == null
+ public bool ResolveReference (string num_str, Hashtable groups)
+ {
+ if (ecma) {
+ int last_i = 0;
+ for (int i = 1; i < num_str.Length; ++i) {
+ if (groups [num_str.Substring (0, i)] != null)
+ last_i = i;
+ }
+ if (last_i != 0) {
+ CapturingGroup = (CapturingGroup) groups [num_str.Substring (0, last_i)];
+ literal = num_str.Substring (last_i);
+ return true;
+ }
+ } else {
+ if (num_str.Length == 1)
+ return false;
+ }
+
+ int ptr = 0;
+ int as_octal = Parser.ParseOctal (num_str, ref ptr);
+ // Since ParseOctal reads at most 3 digits, as_octal <= octal 0777
+ if (as_octal == -1)
+ return false;
+ if (as_octal > 0xff && ecma) {
+ as_octal /= 8;
+ --ptr;
+ }
+ as_octal &= 0xff;
+ literal = ((char) as_octal) + num_str.Substring (ptr);
+ return true;
+ }
+
+ public override void Compile (ICompiler cmp, bool reverse)
+ {
+ if (CapturingGroup != null)
+ base.Compile (cmp, reverse);
+ if (literal != null)
+ Literal.CompileLiteral (literal, cmp, IgnoreCase, reverse);
+ }
+ }
+
class CharacterClass : Expression {
public CharacterClass (bool negate, bool ignore) {
this.negate = negate;
--- /dev/null
+#if NET_4_0
+//
+// Barrier.cs
+//
+// Author:
+// Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2009 Jérémie "Garuma" Laval
+//
+// 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;
+
+namespace System.Threading
+{
+ public class Barrier
+ {
+ readonly Action<Barrier> postPhaseAction;
+
+ int participants;
+ CountdownEvent cntd;
+ AtomicBoolean cleaned = new AtomicBoolean ();
+ int phase;
+
+ public Barrier (int participants) : this (participants, null)
+ {
+ }
+
+ public Barrier (int participants, Action<Barrier> postPhaseAction)
+ {
+ this.participants = participants;
+ this.postPhaseAction = postPhaseAction;
+
+ InitCountdownEvent ();
+ }
+
+ void InitCountdownEvent ()
+ {
+ cleaned = new AtomicBoolean ();
+ cntd = new CountdownEvent (participants);
+ }
+
+ public int AddParticipant ()
+ {
+ return AddParticipants (1);
+ }
+
+ public int AddParticipants (int participantCount)
+ {
+ // Basically, we try to add ourselves and return
+ // the phase. If the call return false, we repeatdly try
+ // to add ourselves for the next phase
+ do {
+ if (cntd.TryAddCount (participantCount)) {
+ Interlocked.Add (ref participants, participantCount);
+ return phase;
+ }
+ } while (true);
+ }
+
+ public void RemoveParticipant ()
+ {
+ RemoveParticipants (1);
+ }
+
+ public void RemoveParticipants (int participantCount)
+ {
+ cntd.Signal (participantCount);
+ Interlocked.Add (ref participants, -participantCount);
+ }
+
+ public void SignalAndWait ()
+ {
+ SignalAndWait ((c) => { c.Wait (); return true; });
+ }
+
+ public bool SignalAndWait (int millisecondTimeout)
+ {
+ return SignalAndWait ((c) => c.Wait (millisecondTimeout));
+ }
+
+ public bool SignalAndWait (TimeSpan ts)
+ {
+ return SignalAndWait ((c) => c.Wait (ts));
+ }
+
+ public bool SignalAndWait (int millisecondTimeout, CancellationToken token)
+ {
+ return SignalAndWait ((c) => c.Wait (millisecondTimeout, token));
+ }
+
+ public bool SignalAndWait (TimeSpan ts, CancellationToken token)
+ {
+ return SignalAndWait ((c) => c.Wait (ts, token));
+ }
+
+ bool SignalAndWait (Func<CountdownEvent, bool> associate)
+ {
+ bool result;
+ AtomicBoolean cl = cleaned;
+ CountdownEvent temp = cntd;
+
+ if (!temp.Signal ()) {
+ result = Wait (associate, temp, cl);
+ } else {
+ result = true;
+ PostPhaseAction (cl);
+ phase++;
+ }
+
+ return result;
+ }
+
+ bool Wait (Func<CountdownEvent, bool> associate, CountdownEvent temp, AtomicBoolean cl)
+ {
+ if (!associate (temp))
+ return false;
+
+ SpinWait sw = new SpinWait ();
+ while (!cl.Value) {
+ //Console.WriteLine (cleaned);
+ sw.SpinOnce ();
+ }
+
+ return true;
+ }
+
+ void PostPhaseAction (AtomicBoolean cl)
+ {
+ postPhaseAction (this);
+
+ InitCountdownEvent ();
+
+ cl.Value = true;
+ }
+
+ public int CurrentPhaseNumber {
+ get {
+ return phase;
+ }
+ }
+
+ public int ParticipantCount {
+ get {
+ return participants;
+ }
+ }
+ }
+}
+#endif
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Barrier.cs: Fix Barrier to be really thread-safe.
+ Remove deadlocking.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Barrier.cs: added.
+
2006-09-28 Andrew Skiba <andrews@mainsoft.com>
* Semaphore.cs: TARGET_JVM
System.Threading/SemaphoreFullException.cs
System.Threading/ThreadExceptionEventArgs.cs
System.Threading/ThreadExceptionEventHandler.cs
+System.Threading/Barrier.cs
System.Timers/ElapsedEventArgs.cs
System.Timers/ElapsedEventHandler.cs
System.Timers/Timer.cs
System.Runtime.InteropServices.ComTypes/TYMED.cs
System/IUriData.cs
System/UriData.cs
+System.Collections.Concurrent/BlockingCollection.cs
+../corlib/System.Threading/AtomicBoolean.cs
System.Timers/TimerCas.cs
System.Web/AspNetHostingPermissionCas.cs
System.Web/AspNetHostingPermissionAttributeCas.cs
+System.Collections.Concurrent/BlockingCollectionTests.cs
+2009-08-13 Marek Habersack <mhabersack@novell.com>
+
+ * CodeTypeReferenceTest.cs: added test for bug #523341
+
2007-01-25 Ilya Kharmatsky <ilyak -at- mainsoft.com>
* CodeTypeReferenceTest.cs :
Assert.IsNotNull (reference.TypeArguments, "#5");
Assert.AreEqual (0, reference.TypeArguments.Count, "#6");
}
+
+ [Test (Description="Bug #523341")]
+ public void GenericTypeTest6 ()
+ {
+ CodeTypeReference reference = new CodeTypeReference ("System.Collections.List<System.Globalization.CultureInfo[]>");
+ Assert.AreEqual ("System.Collections.List<System.Globalization.CultureInfo[]>", reference.BaseType, "#1");
+ Assert.AreEqual (0, reference.ArrayRank, "#2");
+ Assert.IsNull (reference.ArrayElementType, "#3");
+ Assert.AreEqual (0, (int) reference.Options, "#4");
+ Assert.IsNotNull (reference.TypeArguments, "#5");
+ Assert.AreEqual (0, reference.TypeArguments.Count, "#6");
+ }
#endif
// bug #76535
--- /dev/null
+#if NET_4_0
+// BlockingCollectionTests.cs
+//
+// Copyright (c) 2008 Jérémie "Garuma" Laval
+//
+// 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.Threading;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+
+namespace ParallelFxTests
+{
+ [TestFixture()]
+ public class BlockingCollectionTests
+ {
+ BlockingCollection<int> defaultCollection;
+ BlockingCollection<int> boundedCollection;
+
+ [SetUpAttribute]
+ public void Setup()
+ {
+ defaultCollection = new BlockingCollection<int>();
+ boundedCollection = new BlockingCollection<int>(10);
+ }
+
+ [TestAttribute]
+ public void DefaultAddTestCase()
+ {
+ defaultCollection.Add(1);
+ defaultCollection.Add(2);
+ Assert.AreEqual(2, defaultCollection.Count, "#1");
+
+ }
+
+ [TestAttribute]
+ public void BoundedAddTestCase()
+ {
+ boundedCollection.Add(1);
+ boundedCollection.Add(2);
+ Assert.AreEqual(2, boundedCollection.Count, "#1");
+ }
+
+ [TestAttribute]
+ public void BoundedIsFullTestCase()
+ {
+ boundedCollection.Add(1);
+ boundedCollection.Add(2);
+ boundedCollection.Add(3);
+ boundedCollection.Add(4);
+ boundedCollection.Add(5);
+ boundedCollection.Add(6);
+ boundedCollection.Add(7);
+ boundedCollection.Add(8);
+ boundedCollection.Add(9);
+ boundedCollection.Add(10);
+ Assert.AreEqual(boundedCollection.BoundedCapacity, boundedCollection.Count, "#1");
+ }
+
+ [TestAttribute]
+ public void TakeTestCase()
+ {
+ defaultCollection.Add(1);
+ defaultCollection.Add(2);
+ boundedCollection.Add(1);
+ boundedCollection.Add(2);
+
+ int value = defaultCollection.Take();
+ Assert.AreEqual(1, value, "#1");
+ value = boundedCollection.Take();
+ Assert.AreEqual(1, value, "#2");
+ }
+
+ [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
+ public void DefaultAddCompletedTestCase()
+ {
+ defaultCollection.Add(1);
+ defaultCollection.Add(2);
+ defaultCollection.CompleteAdding();
+ Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
+
+ defaultCollection.Add(3);
+ }
+
+ [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
+ public void BoundedAddCompletedTestCase()
+ {
+ boundedCollection.Add(1);
+ boundedCollection.Add(2);
+ boundedCollection.Add(3);
+ boundedCollection.Add(4);
+ boundedCollection.Add(5);
+ boundedCollection.Add(6);
+ boundedCollection.Add(7);
+ boundedCollection.Add(8);
+ boundedCollection.Add(9);
+ boundedCollection.Add(10);
+ boundedCollection.CompleteAdding();
+ Assert.IsTrue(boundedCollection.IsAddingCompleted, "#1");
+
+ boundedCollection.Add(3);
+ }
+
+ [TestAttribute]
+ public void IsCompletedTestCase()
+ {
+ defaultCollection.Add(1);
+ defaultCollection.Add(2);
+
+ defaultCollection.CompleteAdding();
+ Assert.IsFalse(defaultCollection.IsCompleted, "#3");
+
+ defaultCollection.Take();
+ defaultCollection.Take();
+
+ Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
+ Assert.AreEqual(0, defaultCollection.Count, "#2");
+ Assert.IsTrue(defaultCollection.IsCompleted, "#4");
+ }
+
+ [TestAttribute]
+ public void ConsumingEnumerableTestCase()
+ {
+ defaultCollection.Add(1);
+ defaultCollection.Add(2);
+ defaultCollection.Add(3);
+ defaultCollection.Add(4);
+ defaultCollection.Add(5);
+ defaultCollection.Add(6);
+ defaultCollection.CompleteAdding ();
+
+ IEnumerable<int> enumerable = defaultCollection.GetConsumingEnumerable();
+ Assert.IsNotNull(enumerable, "#1");
+ int i = 1;
+ foreach (int j in enumerable) {
+ int temp = i++;
+ Assert.AreEqual(temp, j, "#" + temp);
+ }
+ Assert.AreEqual(0, defaultCollection.Count, "#" + i);
+ }
+ }
+}
+#endif
--- /dev/null
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * BlockingCollectionTests.cs: track API changes
+
+2009-08-17 Raja R Harinath <harinath@hurrynot.org>
+
+ * RegexMatchTests.cs (RegexTrial0061): New.
+
+2009-08-17 Raja R Harinath <harinath@hurrynot.org>
+
+ * RegexTrial.cs (Execute): Prepare to handle dis-contiguous group numbers.
+
+2009-08-10 Raja R Harinath <harinath@hurrynot.org>
+
+ * RegexMatchTests.cs (RegexTrial0054..60): New.
+
+2009-08-10 Raja R Harinath <harinath@hurrynot.org>
+
+ * RegexMatchTests.cs (RegexTrial0053): New.
+
2009-02-27 Jonathan Pryor <jpryor@novell.com>
* RegexReplace.cs: Add null argument checks for Regex.Replace().
new RegexTrial (@"abc*(?!c{1,})", RegexOptions.None, "abcc", "Pass. Group[0]=(0,4)"),//50
new RegexTrial (@"(a)(?<1>b)(?'1'c)", RegexOptions.ExplicitCapture, "abc", "Pass. Group[0]=(0,3) Group[1]=(1,1)(2,1)"),//51
new RegexTrial (@"(?>a*).", RegexOptions.ExplicitCapture, "aaaa", "Fail."),//52
+
+ new RegexTrial (@"(?<ab>ab)c\1", RegexOptions.None, "abcabc", "Pass. Group[0]=(0,5) Group[1]=(0,2)"),//53
+ new RegexTrial (@"\1", RegexOptions.ECMAScript, "-", "Fail."),//54
+ new RegexTrial (@"\2", RegexOptions.ECMAScript, "-", "Fail."),//55
+ new RegexTrial (@"(a)|\2", RegexOptions.ECMAScript, "-", "Fail."),//56
+ new RegexTrial (@"\4400", RegexOptions.None, "asdf 012", "Pass. Group[0]=(4,2)"),//57
+ new RegexTrial (@"\4400", RegexOptions.ECMAScript, "asdf 012", "Fail."),//58
+ new RegexTrial (@"\4400", RegexOptions.None, "asdf$0012", "Fail."),//59
+ new RegexTrial (@"\4400", RegexOptions.ECMAScript, "asdf$0012", "Pass. Group[0]=(4,3)"),//60
+ new RegexTrial (@"(?<2>ab)(?<c>c)(?<d>d)", RegexOptions.None, "abcd", "Pass. Group[0]=(0,4) Group[1]=(2,1) Group[2]=(0,2) Group[3]=(3,1)"),// 61
+ new RegexTrial (@"(?<1>ab)(c)", RegexOptions.None, "abc", "Pass. Group[0]=(0,3) Group[1]=(0,2)(2,1)"),//62
};
[Test]
[Test] public void RegexJvmTrial0050 () { trials [50].Execute (); }
[Test] public void RegexJvmTrial0051 () { trials [51].Execute (); }
[Test] public void RegexJvmTrial0052 () { trials [52].Execute (); }
+
+ [Test] public void RegexTrial0053 () { trials [53].Execute (); }
+ [Test] public void RegexTrial0054 () { trials [54].Execute (); }
+ [Test] public void RegexTrial0055 () { trials [55].Execute (); }
+ [Test] public void RegexTrial0056 () { trials [56].Execute (); }
+ [Test] public void RegexTrial0057 () { trials [57].Execute (); }
+ [Test] public void RegexTrial0058 () { trials [58].Execute (); }
+ [Test] public void RegexTrial0059 () { trials [59].Execute (); }
+ [Test] public void RegexTrial0060 () { trials [60].Execute (); }
+ [Test] public void RegexTrial0061 () { trials [61].Execute (); }
+ [Test] public void RegexTrial0062 () { trials [62].Execute (); }
}
}
RegexOptions real_options = (compiled == 1) ? (options | RegexOptions.Compiled) : options;
try {
Regex re = new Regex (pattern, real_options);
+ int [] group_nums = re.GetGroupNumbers ();
Match m = re.Match (input);
if (m.Success) {
result = "Pass.";
-
+
for (int i = 0; i < m.Groups.Count; ++ i) {
- Group group = m.Groups [i];
+ int gid = group_nums [i];
+ Group group = m.Groups [gid];
- result += " Group[" + i + "]=";
+ result += " Group[" + gid + "]=";
foreach (Capture cap in group.Captures)
result += "(" + cap.Index + "," + cap.Length + ")";
}
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * corlib.dll.sources: Update with moved files.
+ * corlib_test.dll.source: Updated with moved files.
+
2009-07-31 Jérémie Laval <jeremie.laval@gmail.com>
* corlib.dll.sources: Added TaskCompletionSource
+++ /dev/null
-#if NET_4_0
-// BlockingCollection.cs
-//
-// Copyright (c) 2008 Jérémie "Garuma" Laval
-//
-// 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.Threading;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Collections.Concurrent
-{
- public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, IDisposable
- {
- readonly IProducerConsumerCollection<T> underlyingColl;
- readonly int upperBound;
- readonly Func<bool> isFull;
-
- readonly SpinWait sw = new SpinWait ();
-
- AtomicBoolean isComplete;
-
- #region ctors
- public BlockingCollection ()
- : this (new ConcurrentQueue<T> (), -1)
- {
- }
-
- public BlockingCollection (int upperBound)
- : this (new ConcurrentQueue<T> (), upperBound)
- {
- }
-
- public BlockingCollection (IProducerConsumerCollection<T> underlyingColl)
- : this (underlyingColl, -1)
- {
- }
-
- public BlockingCollection (IProducerConsumerCollection<T> underlyingColl, int upperBound)
- {
- this.underlyingColl = underlyingColl;
- this.upperBound = upperBound;
- this.isComplete = new AtomicBoolean ();
-
- if (upperBound == -1)
- isFull = FalseIsFull;
- else
- isFull = CountBasedIsFull;
- }
-
- static bool FalseIsFull ()
- {
- return false;
- }
-
- bool CountBasedIsFull ()
- {
- return underlyingColl.Count >= upperBound;
- }
- #endregion
-
- #region Add & Remove (+ Try)
- public void Add (T item)
- {
- while (true) {
- while (isFull ()) {
- if (isComplete.Value)
- throw new InvalidOperationException ("The BlockingCollection<T>"
- + " has been marked as complete with regards to additions.");
- Block ();
- }
- // Extra check. The status might have changed after Block() or if isFull() is always false
- if (isComplete.Value)
- throw new InvalidOperationException ("The BlockingCollection<T> has"
- + " been marked as complete with regards to additions.");
- // Go back in main waiting loop
- if (isFull ())
- continue;
-
- if (underlyingColl.TryAdd (item))
- break;
- }
- }
-
- public T Remove ()
- {
- T item;
-
- while (underlyingColl.Count == 0 || !underlyingColl.TryTake (out item)) {
- if (isComplete.Value)
- throw new OperationCanceledException ("The BlockingCollection<T> is empty and has been marked as complete with regards to additions.");
- Block ();
- }
-
- return item;
- }
-
- public bool TryAdd (T item)
- {
- if (isComplete.Value || isFull ()) {
- return false;
- }
-
- return underlyingColl.TryAdd (item);
- }
-
- public bool TryAdd (T item, TimeSpan ts)
- {
- return TryAdd (item, (int)ts.TotalMilliseconds);
- }
-
- public bool TryAdd (T item, int millisecondsTimeout)
- {
- Watch sw = Watch.StartNew ();
- while (isFull ()) {
- if (isComplete.Value || sw.ElapsedMilliseconds > millisecondsTimeout) {
- sw.Stop ();
- return false;
- }
- Block ();
- }
- return TryAdd (item);
- }
-
- public bool TryRemove (out T item)
- {
- return underlyingColl.TryTake (out item);
- }
-
- public bool TryRemove (out T item, TimeSpan ts)
- {
- return TryRemove (out item, (int)ts.TotalMilliseconds);
- }
-
- public bool TryRemove (out T item, int millisecondsTimeout)
- {
- Watch sw = Watch.StartNew ();
- while (underlyingColl.Count == 0) {
- if (isComplete.Value || sw.ElapsedMilliseconds > millisecondsTimeout) {
- item = default (T);
- return false;
- }
-
- Block ();
- }
- return TryRemove (out item);
- }
- #endregion
-
- #region static methods
- static void CheckArray (BlockingCollection<T>[] collections)
- {
- if (collections == null)
- throw new ArgumentNullException ("collections");
- if (collections.Length == 0 || IsThereANullElement (collections))
- throw new ArgumentException ("The collections argument is a 0-length array or contains a null element.", "collections");
- }
-
- static bool IsThereANullElement (BlockingCollection<T>[] collections)
- {
- foreach (BlockingCollection<T> e in collections)
- if (e == null)
- return true;
- return false;
- }
-
- public static int AddAny (BlockingCollection<T>[] collections, T item)
- {
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- try {
- coll.Add (item);
- return index;
- } catch {}
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny (BlockingCollection<T>[] collections, T item)
- {
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd (item))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny (BlockingCollection<T>[] collections, T item, TimeSpan ts)
- {
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd (item, ts))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny (BlockingCollection<T>[] collections, T item, int millisecondsTimeout)
- {
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd (item, millisecondsTimeout))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int RemoveAny (BlockingCollection<T>[] collections, out T item)
- {
- item = default (T);
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- try {
- item = coll.Remove ();
- return index;
- } catch {}
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny (BlockingCollection<T>[] collections, out T item)
- {
- item = default (T);
-
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove (out item))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny (BlockingCollection<T>[] collections, out T item, TimeSpan ts)
- {
- item = default (T);
-
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove (out item, ts))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny (BlockingCollection<T>[] collections, out T item, int millisecondsTimeout)
- {
- item = default (T);
-
- CheckArray (collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove (out item, millisecondsTimeout))
- return index;
- index++;
- }
- return -1;
- }
- #endregion
-
- public void CompleteAdding ()
- {
- isComplete.Value = true;
- }
-
- void ICollection.CopyTo (Array array, int index)
- {
- underlyingColl.CopyTo (array, index);
- }
-
- public void CopyTo (T[] array, int index)
- {
- underlyingColl.CopyTo (array, index);
- }
-
- public IEnumerable<T> GetConsumingEnumerable ()
- {
- T item;
- while (underlyingColl.TryTake (out item)) {
- yield return item;
- }
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return ((IEnumerable)underlyingColl).GetEnumerator ();
- }
-
- IEnumerator<T> IEnumerable<T>.GetEnumerator ()
- {
- return ((IEnumerable<T>)underlyingColl).GetEnumerator ();
- }
-
- public IEnumerator<T> GetEnumerator ()
- {
- return ((IEnumerable<T>)underlyingColl).GetEnumerator ();
- }
-
- public void Dispose ()
- {
- }
-
- public T[] ToArray ()
- {
- return underlyingColl.ToArray ();
- }
-
- // Method used to stall the thread for a limited period of time before retrying an operation
- void Block ()
- {
- sw.SpinOnce ();
- }
-
- public int BoundedCapacity {
- get {
- return upperBound;
- }
- }
-
- public int Count {
- get {
- return underlyingColl.Count;
- }
- }
-
- public bool IsAddingCompleted {
- get {
- return isComplete.Value;
- }
- }
-
- public bool IsCompleted {
- get {
- return isComplete.Value && underlyingColl.Count == 0;
- }
- }
-
- object ICollection.SyncRoot {
- get {
- return underlyingColl.SyncRoot;
- }
- }
-
- bool ICollection.IsSynchronized {
- get {
- return underlyingColl.IsSynchronized;
- }
- }
- }
-}
-#endif
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Partitioner.cs: Fix infinite recursion when calling Create
+ with a IList.
+ * Partitionners/ListPartitioner.cs: Fix bad splitting for the
+ last partition.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * ConcurrentQueue.cs:
+ * IProducerConsumerCollection.cs: Add BOOTSTRAP_NET_4_0.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * BlockingCollection.cs: Moved type.
+
+
2009-08-04 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary: Fix compilation issue
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
// ConcurrentQueue.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
// IConcurrentCollection.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
{
IList<TSource> tempIList = source as IList<TSource>;
if (tempIList != null)
- return Create (tempIList);
+ return Create (tempIList, true);
return new EnumerablePartitioner<TSource> (source);
}
public static OrderablePartitioner<TSource> Create<TSource> (TSource[] source, bool loadBalance)
{
- return Create ((IList<TSource>)source);
+ return Create ((IList<TSource>)source, loadBalance);
}
public static OrderablePartitioner<TSource> Create<TSource> (IList<TSource> source, bool loadBalance)
if (i != enumerators.Length - 1)
enumerators[i] = GetEnumeratorForRange (i * count, i * count + count);
else
- enumerators[i] = GetEnumeratorForRange (i * count, source.Count - i * count);
+ enumerators[i] = GetEnumeratorForRange (i * count, source.Count);
}
return enumerators;
}
- IEnumerator<KeyValuePair<long, T>> GetEnumeratorForRange (int startIndex, int count)
+ IEnumerator<KeyValuePair<long, T>> GetEnumeratorForRange (int startIndex, int lastIndex)
{
if (startIndex >= source.Count)
return GetEmpty ();
- return GetEnumeratorForRangeInternal (startIndex, count);
+ return GetEnumeratorForRangeInternal (startIndex, lastIndex);
}
IEnumerator<KeyValuePair<long, T>> GetEmpty ()
yield break;
}
- IEnumerator<KeyValuePair<long, T>> GetEnumeratorForRangeInternal (int startIndex, int count)
+ IEnumerator<KeyValuePair<long, T>> GetEnumeratorForRangeInternal (int startIndex, int lastIndex)
{
- for (int i = startIndex; i < count; i++) {
+ for (int i = startIndex; i < lastIndex; i++) {
yield return new KeyValuePair<long, T> (i, source[i]);
}
}
+2009-08-18 Zoltan Varga <vargaz@gmail.com>
+
+ * MonoGenericClass.cs: Use StringComparison.Ordinal when calling
+ String.EndsWith ().
+
+2009-08-07 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * MonoGenericClass.cs: Implement almost all methods required
+ to move to inherit from System.Type. The only missing methods
+ are Is(Array|Pointer|ByRef)Impl and GetElementType since the
+ runtime still generates weird instances for generics instances
+ of non-SRE types with SRE types as generic arguments.
+
2009-08-06 Rodrigo Kumpera <rkumpera@novell.com>
* MonoGenericClass.cs (InflateType): Add support to inflate
if (type.IsArray) {
if (type.GetArrayRank () > 1)
return InflateType (type.GetElementType (), method_args).MakeArrayType (type.GetArrayRank ());
- if (type.ToString ().EndsWith ("[*]")) /*FIXME, the reflection API doesn't offer a way around this*/
+#if BOOTSTRAP_NET_2_0
+ if (type.ToString ().EndsWith ("[*]"))
+#else
+ if (type.ToString ().EndsWith ("[*]", StringComparison.Ordinal)) /*FIXME, the reflection API doesn't offer a way around this*/
+#endif
return InflateType (type.GetElementType (), method_args).MakeArrayType (1);
return InflateType (type.GetElementType (), method_args).MakeArrayType ();
}
return new PointerType (this);
}
+ /*public override Type GetElementType ()
+ {
+ throw new NotSupportedException ();
+ }*/
+
protected override bool IsCOMObjectImpl ()
{
return false;
{
return false;
}
+
+ /*
+ protected override bool IsArrayImpl ()
+ {
+ return false;
+ }
+
+ protected override bool IsByRefImpl ()
+ {
+ return false;
+ }
+
+ protected override bool IsPointerImpl ()
+ {
+ return false;
+ }*/
+
+ protected override TypeAttributes GetAttributeFlagsImpl ()
+ {
+ return generic_type.Attributes;
+ }
+
+ //stuff that throws
+ public override Type GetInterface (string name, bool ignoreCase)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
+ {
+ if (!generic_type.IsCompilerContext)
+ throw new NotSupportedException ();
+ foreach (var evt in GetEvents (bindingAttr)) {
+ if (evt.Name == name)
+ return evt;
+ }
+ return null;
+ }
+
+ public override FieldInfo GetField( string name, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override Type GetNestedType (string name, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override object InvokeMember (string name, BindingFlags invokeAttr,
+ Binder binder, object target, object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture, string[] namedParameters)
+ {
+ throw new NotSupportedException ();
+ }
+
+ protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder,
+ CallingConventions callConvention, Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException ();
+ }
+
+ protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException ();
+ }
+
+ protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException ();
+ }
+
+ //MemberInfo
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override object [] GetCustomAttributes (bool inherit)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override object [] GetCustomAttributes (Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException ();
+ }
}
}
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * TypeForwardedFromAttribute.cs: Add BOOTSTRAP_NET_4_0.
+
2009-07-02 Marek Safar <marek.safar@gmail.com>
* ConditionalWeakTable.cs: New file.
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
namespace System.Runtime.CompilerServices
{
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Task.cs: Refactor Wait methods.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Future.cs: Add static to Factory property
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Task.cs: Make WaitAny uses general continuation
+ framework.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * TaskFactory.cs: Fix methods signature.
+
2009-08-05 Jérémie Laval <jeremie.laval@gmail.com>
* Future.cs: Fix for Future, when using TaskCompletionSource
public class Task<TResult>: Task
{
TResult value;
- TaskFactory<TResult> factory = new TaskFactory<TResult> ();
+ static TaskFactory<TResult> factory = new TaskFactory<TResult> ();
Func<object, TResult> function;
object state;
}
}
- public new TaskFactory<TResult> Factory {
+ public static TaskFactory<TResult> Factory {
get {
return factory;
}
}
internal void ContinueWithCore (Task continuation, TaskContinuationOptions kind,
- TaskScheduler scheduler, Func<bool> predicate)
+ TaskScheduler scheduler, Func<bool> predicate)
{
// Already set the scheduler so that user can call Wait and that sort of stuff
continuation.taskScheduler = scheduler;
if (exception != null && !(exception is TaskCanceledException))
throw exception;
}
-
- [MonoTODO ("Refactor")]
+
public void Wait (CancellationToken token)
{
- if (scheduler == null)
- throw new InvalidOperationException ("The Task hasn't been Started and thus can't be waited on");
-
- Watch sw = Watch.StartNew ();
- scheduler.ParticipateUntil (this, delegate {
- return token.IsCancellationRequested;
- });
- sw.Stop ();
-
- if (exception != null && !(exception is TaskCanceledException))
- throw exception;
-
+ Wait (null, token);
}
public bool Wait (TimeSpan ts)
public bool Wait (int millisecondsTimeout)
{
- if (scheduler == null)
- throw new InvalidOperationException ("The Task hasn't been Started and thus can't be waited on");
-
Watch sw = Watch.StartNew ();
- bool result = scheduler.ParticipateUntil (this, delegate {
- return sw.ElapsedMilliseconds >= millisecondsTimeout;
- });
- sw.Stop ();
-
- if (exception != null && !(exception is TaskCanceledException))
- throw exception;
-
- return !result;
+ return Wait (() => sw.ElapsedMilliseconds >= millisecondsTimeout, null);
}
- [MonoTODO ("Refactor")]
public bool Wait (int millisecondsTimeout, CancellationToken token)
+ {
+ Watch sw = Watch.StartNew ();
+ return Wait (() => sw.ElapsedMilliseconds >= millisecondsTimeout, token);
+ }
+
+ bool Wait (Func<bool> stopFunc, CancellationToken? token)
{
if (scheduler == null)
throw new InvalidOperationException ("The Task hasn't been Started and thus can't be waited on");
- Watch sw = Watch.StartNew ();
bool result = scheduler.ParticipateUntil (this, delegate {
- return sw.ElapsedMilliseconds >= millisecondsTimeout || token.IsCancellationRequested;
+ if (token.HasValue && token.Value.IsCancellationRequested)
+ throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
+
+
+ return (stopFunc != null) ? stopFunc () : false;
});
- sw.Stop ();
-
+
if (exception != null && !(exception is TaskCanceledException))
throw exception;
}
public static int WaitAny (params Task[] tasks)
+ {
+ return WaitAny (tasks, null, null);
+ }
+
+ static int WaitAny (Task[] tasks, Func<bool> stopFunc, CancellationToken? token)
{
if (tasks == null)
throw new ArgumentNullException ("tasks");
int index = 0;
foreach (Task t in tasks) {
- if (t.IsCompleted) {
- return index;
- }
- t.completed += delegate (object sender, EventArgs e) {
+ t.ContinueWith (delegate {
+ int indexResult = index;
int result = Interlocked.Increment (ref numFinished);
// Check if we are the first to have finished
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex (tasks, (elem) => elem == target);
- }
- };
+ if (result == 1)
+ indexFirstFinished = indexResult;
+ });
index++;
}
+ // One task already finished
+ if (indexFirstFinished != -1)
+ return indexFirstFinished;
+
// All tasks are supposed to use the same TaskManager
tasks[0].scheduler.ParticipateUntil (delegate {
+ if (stopFunc != null && stopFunc ())
+ return true;
+
+ if (token.HasValue && token.Value.IsCancellationRequested)
+ throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
+
return numFinished >= 1;
});
{
if (millisecondsTimeout < -1)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
- if (tasks == null)
- throw new ArgumentNullException ("tasks");
if (millisecondsTimeout == -1)
return WaitAny (tasks);
- int numFinished = 0;
- int indexFirstFinished = -1;
-
- foreach (Task t in tasks) {
- t.completed += delegate (object sender, EventArgs e) {
- int result = Interlocked.Increment (ref numFinished);
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex (tasks, (elem) => elem == target);
- }
- };
- }
-
Watch sw = Watch.StartNew ();
- tasks[0].scheduler.ParticipateUntil (delegate {
- if (sw.ElapsedMilliseconds > millisecondsTimeout)
- return true;
- return numFinished >= 1;
- });
- sw.Stop ();
-
- return indexFirstFinished;
+ return WaitAny (tasks, () => sw.ElapsedMilliseconds > millisecondsTimeout, null);
}
-
- [MonoTODO ("Refactor")]
+
public static int WaitAny (Task[] tasks, int millisecondsTimeout, CancellationToken token)
- {
+ {
if (millisecondsTimeout < -1)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
- if (tasks == null)
- throw new ArgumentNullException ("tasks");
if (millisecondsTimeout == -1)
return WaitAny (tasks);
- int numFinished = 0;
- int indexFirstFinished = -1;
-
- foreach (Task t in tasks) {
- t.completed += delegate (object sender, EventArgs e) {
- int result = Interlocked.Increment (ref numFinished);
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex (tasks, (elem) => elem == target);
- }
- };
- }
-
Watch sw = Watch.StartNew ();
- tasks[0].scheduler.ParticipateUntil (delegate {
- if (sw.ElapsedMilliseconds > millisecondsTimeout || token.IsCancellationRequested)
- return true;
- return numFinished >= 1;
- });
- sw.Stop ();
-
- return indexFirstFinished;
+ return WaitAny (tasks, () => sw.ElapsedMilliseconds > millisecondsTimeout, token);
}
- [MonoTODO ("Refactor")]
public static int WaitAny (Task[] tasks, CancellationToken token)
- {
- if (tasks == null)
- throw new ArgumentNullException ("tasks");
- if (tasks.Length == 0)
- throw new ArgumentException ("tasks is empty", "tasks");
-
- int numFinished = 0;
- int indexFirstFinished = -1;
- int index = 0;
-
- foreach (Task t in tasks) {
- if (t.IsCompleted) {
- return index;
- }
- t.completed += delegate (object sender, EventArgs e) {
- int result = Interlocked.Increment (ref numFinished);
- // Check if we are the first to have finished
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex (tasks, (elem) => elem == target);
- }
- };
- index++;
- }
-
- // All tasks are supposed to use the same TaskManager
- tasks[0].scheduler.ParticipateUntil (delegate {
- if (token.IsCancellationRequested)
- return true;
-
- return numFinished >= 1;
- });
-
- return indexFirstFinished;
+ {
+ return WaitAny (tasks, null, token);
}
#endregion
[MonoTODO]
public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions,
- TaskScheduler scheduler)
+ TaskScheduler scheduler)
{
- return null;
+ throw new NotImplementedException ();
}
[MonoTODO]
[MonoTODO]
public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationAction,
- TaskContinuationOptions continuationOptions)
+ TaskContinuationOptions continuationOptions)
{
return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
}
TaskContinuationOptions continuationOptions,
TaskScheduler scheduler)
{
- return null;
+ throw new NotImplementedException ();
}
public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction)
}
public Task<TResult> StartNew (Func<object, TResult> function, object state, TaskCreationOptions options,
- TaskScheduler scheduler)
+ TaskScheduler scheduler)
{
return parent.StartNew<TResult> (function, state, options, scheduler);
}
TaskContinuationOptions continuationOptions,
TaskScheduler scheduler)
{
- return null;
+ throw new NotImplementedException ();
}
[MonoTODO]
- public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task, TNewResult> continuationAction)
+ public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction)
{
return ContinueWhenAny (tasks, continuationAction, contOptions);
}
[MonoTODO]
- public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task, TNewResult> continuationAction,
- TaskContinuationOptions continuationOptions)
+ public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction,
+ TaskContinuationOptions continuationOptions)
{
return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
}
[MonoTODO]
- public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task, TNewResult> continuationAction,
- TaskContinuationOptions continuationOptions,
- TaskScheduler scheduler)
+ public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction,
+ TaskContinuationOptions continuationOptions,
+ TaskScheduler scheduler)
{
- return null;
+ throw new NotImplementedException ();
}
public Task ContinueWhenAll (Task<TResult>[] tasks, Action<Task<TResult>[]> continuationFunction)
}
public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
- Func<Task<TNewResult>[], TNewResult> continuationFunction)
+ Func<Task<TResult>[], TNewResult> continuationFunction)
{
return ContinueWhenAll (tasks, continuationFunction, contOptions);
}
public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
- Func<Task<TNewResult>[], TNewResult> continuationFunction,
+ Func<Task<TResult>[], TNewResult> continuationFunction,
TaskContinuationOptions continuationOptions)
{
return ContinueWhenAll (tasks, continuationFunction, continuationOptions, scheduler);
}
public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
- Func<Task<TNewResult>[], TNewResult> continuationFunction,
+ Func<Task<TResult>[], TNewResult> continuationFunction,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
CountdownEvent evt = new CountdownEvent (tasks.Length);
+++ /dev/null
-#if NET_4_0
-// AggregateException.cs
-//
-// Copyright (c) 2008 Jérémie "Garuma" Laval
-//
-// 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.ObjectModel;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace System.Threading
-{
- [System.SerializableAttribute]
- public class AggregateException : Exception
- {
- List<Exception> innerExceptions;
-
- public AggregateException (): base()
- {
- }
-
- public AggregateException (string message): base (message, null)
- {
- }
-
- public AggregateException (string message, Exception e): base (message, e)
- {
- }
-
- public AggregateException (SerializationInfo info, StreamingContext ctx)
- : base (info, ctx)
- {
- }
-
- public AggregateException (params Exception[] innerExceptions)
- : this (string.Empty, innerExceptions)
- {
- }
-
- public AggregateException (string message, params Exception[] innerExceptions)
- : this (message, (IEnumerable<Exception>)innerExceptions)
- {
- }
-
- public AggregateException (IEnumerable<Exception> innerExceptions)
- : this (string.Empty, innerExceptions)
- {
- }
-
- public AggregateException (string message, IEnumerable<Exception> inner)
- : base(GetFormattedMessage(message, inner))
- {
- this.innerExceptions = new List<Exception> (inner);
- }
-
- public AggregateException Flatten ()
- {
- List<Exception> inner = new List<Exception> ();
-
- foreach (Exception e in innerExceptions) {
- AggregateException aggEx = e as AggregateException;
- if (aggEx != null) {
- inner.AddRange (aggEx.Flatten ().InnerExceptions);
- } else {
- inner.Add (e);
- }
- }
-
- return new AggregateException (inner);
- }
-
- public void Handle (Func<Exception, bool> handler)
- {
- List<Exception> failed = new List<Exception> ();
- foreach (var e in innerExceptions) {
- try {
- if (!handler (e))
- failed.Add (e);
- } catch {
- throw new AggregateException (failed);
- }
- }
- if (failed.Count > 0)
- throw new AggregateException (failed);
- }
-
- public ReadOnlyCollection<Exception> InnerExceptions {
- get {
- return innerExceptions.AsReadOnly ();
- }
- }
-
- public override string ToString ()
- {
- return this.Message;
- }
-
- const string baseMessage = "Exception(s) occurred while inside the Parallel loop. {0}.";
- static string GetFormattedMessage (string customMessage, IEnumerable<Exception> inner)
- {
- System.Text.StringBuilder finalMessage
- = new System.Text.StringBuilder (string.Format (baseMessage, customMessage));
- foreach (Exception e in inner) {
- finalMessage.Append (Environment.NewLine);
- finalMessage.Append ("[ ");
- finalMessage.Append (e.ToString ());
- finalMessage.Append (" ]");
- finalMessage.Append (Environment.NewLine);
- }
- return finalMessage.ToString ();
- }
- }
-}
-#endif
namespace System.Threading
{
- internal struct AtomicBoolean
+ internal class AtomicBoolean
{
int flag;
const int UnSet = 0;
return temp;
}
+ public bool TrySet ()
+ {
+ return !Exchange (true);
+ }
+
public bool Exchange (bool newVal)
{
int newTemp = newVal ? Set : UnSet;
+++ /dev/null
-#if NET_4_0
-//
-// Barrier.cs
-//
-// Author:
-// Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
-//
-// Copyright (c) 2009 Jérémie "Garuma" Laval
-//
-// 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;
-
-namespace System.Threading
-{
- public class Barrier
- {
- readonly Action<Barrier> postPhaseAction;
-
- int participants;
- CountdownEvent cntd;
- int phase;
-
- public Barrier (int participants) : this (participants, null)
- {
- }
-
- public Barrier (int participants, Action<Barrier> postPhaseAction)
- {
- this.participants = participants;
- this.postPhaseAction = postPhaseAction;
-
- InitCountdownEvent ();
- }
-
- void InitCountdownEvent ()
- {
- cntd = new CountdownEvent (participants);
- }
-
- public int AddParticipant ()
- {
- return AddParticipants (1);
- }
-
- public int AddParticipants (int participantCount)
- {
- // Basically, we try to add ourselves and return
- // the phase. If the call return false, we repeatdly try
- // to add ourselves for the next phase
- do {
- if (cntd.TryAddCount (participantCount)) {
- Interlocked.Add (ref participants, participantCount);
- return phase;
- }
- } while (true);
- }
-
- public void RemoveParticipant ()
- {
- RemoveParticipants (1);
- }
-
- public void RemoveParticipants (int participantCount)
- {
- cntd.Signal (participantCount);
- Interlocked.Add (ref participants, -participantCount);
- }
-
- public void SignalAndWait ()
- {
- SignalAndWait (() => { cntd.Wait (); return true; });
- }
-
- public bool SignalAndWait (int millisecondTimeout)
- {
- return SignalAndWait (() => cntd.Wait (millisecondTimeout));
- }
-
- public bool SignalAndWait (TimeSpan ts)
- {
- return SignalAndWait (() => cntd.Wait (ts));
- }
-
- public bool SignalAndWait (int millisecondTimeout, CancellationToken token)
- {
- return SignalAndWait (() => cntd.Wait (millisecondTimeout, token));
- }
-
- public bool SignalAndWait (TimeSpan ts, CancellationToken token)
- {
- return SignalAndWait (() => cntd.Wait (ts, token));
- }
-
- bool SignalAndWait (Func<bool> associate)
- {
- bool result;
-
- if (!cntd.Signal ()) {
- result = associate ();
- } else {
- result = true;
- postPhaseAction (this);
- phase++;
- }
-
- return result;
- }
-
- public int CurrentPhaseNumber {
- get {
- return phase;
- }
- }
-
- public int ParticipantCount {
- get {
- return participants;
- }
- }
- }
-}
-#endif
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
//
// CancellationToken.cs
//
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
//
// CancellationTokenRegistration.cs
//
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
//
// CancellationTokenSource.cs
//
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * ParallelLoopState.cs: Take in account that
+ AtomicBoolean is a class.
+
+2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * AtomicBoolean.cs: Turn it into a class
+ * CountdownEvent.cs: Work on cached variable. Make sure
+ count doesn't go under 0.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Watch.cs:
+ * SpinWait.cs:
+ * CountdownEvent.cs:
+ * CancellationToken.cs:
+ * ICancelableOperation.cs:
+ * CancellationTokenSource.cs:
+ * CancellationTokenRegistration.cs: Add BOOTSTRAP_NET_4_0.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Parallel.cs: Disable While method.
+ * CountdownEvent.cs: Fix method signature.
+ * Barrier.cs: Moved type.
+ * AggregateException.cs: Moved type.
+
2009-08-04 Jérémie Laval <jeremie.laval@gmail.com>
* SpinLock: Remove unused private methods.
* ThreadLocal.cs:
* SemaphoreSlim.cs:
* CountdownEvent.cs:
- * ManualResetEventSlim.cs:
+ * ManualResetEventSlim.cs
* CancellationTokenSource.cs: Various 4.0 b1 API mismatch fixes.
2009-07-30 Jérémie Laval <jeremie.laval@gmail.com>
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
// CountdownEvent.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
public bool Signal (int num)
{
- if (num < 0)
+ if (num <= 0)
throw new ArgumentOutOfRangeException ("num");
Action<int> check = delegate (int value) {
if (!ApplyOperation (-num, check, out newValue))
throw new InvalidOperationException ("The event is already set");
- if (newValue <= 0) {
+ if (newValue == 0) {
evt.Set ();
return true;
}
if (num < 0)
throw new ArgumentOutOfRangeException ("num");
- Action<int> check = delegate (int value) { };
-
- return ApplyOperation (num, check);
+ return ApplyOperation (num, null);
}
bool ApplyOperation (int num, Action<int> doCheck)
newValue = 0;
do {
- if (IsSet)
+ oldCount = count;
+ if (oldCount == 0)
return false;
- oldCount = count;
newValue = oldCount + num;
- doCheck (newValue);
-
+ if (doCheck != null)
+ doCheck (newValue);
} while (Interlocked.CompareExchange (ref count, newValue, oldCount) != oldCount);
return true;
}
}
- public bool Wait (CancellationToken token)
+ public void Wait (CancellationToken token)
{
- return Wait (() => token.IsCancellationRequested);
+ Wait (() => token.IsCancellationRequested);
}
public bool Wait (int timeoutMilli)
public bool IsSet {
get {
- return count <= 0;
+ return count == 0;
}
}
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
//
// ICancelableOperation.cs
//
}
#endregion
+ /* Disabled as this is an API addition
#region While
public static void While (Func<bool> predicate, Action body)
{
}
#endregion
+ */
#region Invoke
public static void Invoke (params Action[] actions)
{
internal class ExternalInfos
{
- public AtomicBoolean IsStopped;
- public AtomicBoolean IsBroken;
+ public AtomicBoolean IsStopped = new AtomicBoolean ();
+ public AtomicBoolean IsBroken = new AtomicBoolean ();
public volatile bool IsExceptional;
public long? LowestBreakIteration;
}
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
// SpinWait.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
// Task.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
namespace System
{
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
public delegate void Action ();
--- /dev/null
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+// AggregateException.cs
+//
+// Copyright (c) 2008 Jérémie "Garuma" Laval
+//
+// 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.ObjectModel;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace System
+{
+ [System.SerializableAttribute]
+ public class AggregateException : Exception
+ {
+ List<Exception> innerExceptions;
+
+ public AggregateException (): base()
+ {
+ }
+
+ public AggregateException (string message): base (message, null)
+ {
+ }
+
+ public AggregateException (string message, Exception e): base (message, e)
+ {
+ }
+
+ public AggregateException (SerializationInfo info, StreamingContext ctx)
+ : base (info, ctx)
+ {
+ }
+
+ public AggregateException (params Exception[] innerExceptions)
+ : this (string.Empty, innerExceptions)
+ {
+ }
+
+ public AggregateException (string message, params Exception[] innerExceptions)
+ : this (message, (IEnumerable<Exception>)innerExceptions)
+ {
+ }
+
+ public AggregateException (IEnumerable<Exception> innerExceptions)
+ : this (string.Empty, innerExceptions)
+ {
+ }
+
+ public AggregateException (string message, IEnumerable<Exception> inner)
+ : base(GetFormattedMessage(message, inner))
+ {
+ this.innerExceptions = new List<Exception> (inner);
+ }
+
+ public AggregateException Flatten ()
+ {
+ List<Exception> inner = new List<Exception> ();
+
+ foreach (Exception e in innerExceptions) {
+ AggregateException aggEx = e as AggregateException;
+ if (aggEx != null) {
+ inner.AddRange (aggEx.Flatten ().InnerExceptions);
+ } else {
+ inner.Add (e);
+ }
+ }
+
+ return new AggregateException (inner);
+ }
+
+ public void Handle (Func<Exception, bool> handler)
+ {
+ List<Exception> failed = new List<Exception> ();
+ foreach (var e in innerExceptions) {
+ try {
+ if (!handler (e))
+ failed.Add (e);
+ } catch {
+ throw new AggregateException (failed);
+ }
+ }
+ if (failed.Count > 0)
+ throw new AggregateException (failed);
+ }
+
+ public ReadOnlyCollection<Exception> InnerExceptions {
+ get {
+ return innerExceptions.AsReadOnly ();
+ }
+ }
+
+ public override string ToString ()
+ {
+ return this.Message;
+ }
+
+ const string baseMessage = "Exception(s) occurred while inside the Parallel loop. {0}.";
+ static string GetFormattedMessage (string customMessage, IEnumerable<Exception> inner)
+ {
+ System.Text.StringBuilder finalMessage
+ = new System.Text.StringBuilder (string.Format (baseMessage, customMessage));
+ foreach (Exception e in inner) {
+ finalMessage.Append (Environment.NewLine);
+ finalMessage.Append ("[ ");
+ finalMessage.Append (e.ToString ());
+ finalMessage.Append (" ]");
+ finalMessage.Append (Environment.NewLine);
+ }
+ return finalMessage.ToString ();
+ }
+ }
+}
+#endif
+2009-08-14 Marek Safar <marek.safar@gmail.com>
+
+ * Type.cs: Made IsClass work under compiler context.
+
+2009-08-12 Zoltan Varga <vargaz@gmail.com>
+
+ * ResolveEventArgs.cs: Add net 4.0 RequestingAssembly property.
+
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * Funcs.cs:
+ * Action.cs:
+ * AggregateException.cs: Add BOOTSTRAP_NET_4_0.
+
2009-08-07 Marek Safar <marek.safar@gmail.com>
* AppDomain.cs: IsHomogenous always returns true for now.
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
//
-#if NET_4_0
+#if NET_4_0 || BOOTSTRAP_NET_4_0
using System.Runtime.CompilerServices;
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Runtime.InteropServices;
+using System.Reflection;
namespace System
{
public class ResolveEventArgs : EventArgs
{
private string m_Name;
+#if NET_4_0
+ private Assembly m_Requesting;
+#endif
public ResolveEventArgs (string name)
{
m_Name = name;
}
+#if NET_4_0
+ public ResolveEventArgs (string name, Assembly requestingAssembly) {
+ this.m_Name = name;
+ this.m_Requesting = requestingAssembly;
+ }
+#endif
+
public string Name {
get {
return m_Name;
}
}
+
+#if NET_4_0
+ public Assembly RequestingAssembly {
+ get {
+ return m_Requesting;
+ }
+ }
+#endif
}
}
}
}
-#endif
\ No newline at end of file
+#endif
if (IsInterface)
return false;
- return !IsSubclassOf (typeof (ValueType));
+ return !IsValueType;
}
}
+++ /dev/null
-#if NET_4_0
-// BlockingCollectionTests.cs
-//
-// Copyright (c) 2008 Jérémie "Garuma" Laval
-//
-// 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.Threading;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture()]
- public class BlockingCollectionTests
- {
- BlockingCollection<int> defaultCollection;
- BlockingCollection<int> boundedCollection;
-
- [SetUpAttribute]
- public void Setup()
- {
- defaultCollection = new BlockingCollection<int>();
- boundedCollection = new BlockingCollection<int>(10);
- }
-
- [TestAttribute]
- public void DefaultAddTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- Assert.AreEqual(2, defaultCollection.Count, "#1");
-
- }
-
- [TestAttribute]
- public void BoundedAddTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- Assert.AreEqual(2, boundedCollection.Count, "#1");
- }
-
- [TestAttribute]
- public void BoundedIsFullTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- boundedCollection.Add(3);
- boundedCollection.Add(4);
- boundedCollection.Add(5);
- boundedCollection.Add(6);
- boundedCollection.Add(7);
- boundedCollection.Add(8);
- boundedCollection.Add(9);
- boundedCollection.Add(10);
- Assert.AreEqual(boundedCollection.BoundedCapacity, boundedCollection.Count, "#1");
- }
-
- [TestAttribute]
- public void RemoveTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- boundedCollection.Add(1);
- boundedCollection.Add(2);
-
- int value = defaultCollection.Remove();
- Assert.AreEqual(1, value, "#1");
- value = boundedCollection.Remove();
- Assert.AreEqual(1, value, "#2");
- }
-
- [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
- public void DefaultAddCompletedTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- defaultCollection.CompleteAdding();
- Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
-
- defaultCollection.Add(3);
- }
-
- [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
- public void BoundedAddCompletedTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- boundedCollection.Add(3);
- boundedCollection.Add(4);
- boundedCollection.Add(5);
- boundedCollection.Add(6);
- boundedCollection.Add(7);
- boundedCollection.Add(8);
- boundedCollection.Add(9);
- boundedCollection.Add(10);
- boundedCollection.CompleteAdding();
- Assert.IsTrue(boundedCollection.IsAddingCompleted, "#1");
-
- boundedCollection.Add(3);
- }
-
- [TestAttribute]
- public void IsCompletedTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
-
- defaultCollection.CompleteAdding();
- Assert.IsFalse(defaultCollection.IsCompleted, "#3");
-
- defaultCollection.Remove();
- defaultCollection.Remove();
-
- Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
- Assert.AreEqual(0, defaultCollection.Count, "#2");
- Assert.IsTrue(defaultCollection.IsCompleted, "#4");
- }
-
- [TestAttribute]
- public void ConsumingEnumerableTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- defaultCollection.Add(3);
- defaultCollection.Add(4);
- defaultCollection.Add(5);
- defaultCollection.Add(6);
-
- IEnumerable<int> enumerable = defaultCollection.GetConsumingEnumerable();
- Assert.IsNotNull(enumerable, "#1");
- int i = 1;
- foreach (int j in enumerable) {
- int temp = i++;
- Assert.AreEqual(temp, j, "#" + temp);
- }
- Assert.AreEqual(0, defaultCollection.Count, "#" + i);
- }
- }
-}
-#endif
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * BlockingCollectionTests.cs: Moved file.
+
2009-08-05 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionaryTests.cs: Re-enable ConcurrentDictionary unit
+2009-08-07 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * MonoGenericClassTest.cs: Test for methods that must
+ throw.
+
2009-08-04 Rodrigo Kumpera <rkumpera@novell.com>
* MonoGenericClassTest.cs: New file.
}
[SetUp]
- protected void SetUp ()
+ public void SetUp ()
+ {
+ SetUp (AssemblyBuilderAccess.RunAndSave);
+ }
+
+ void SetUp (AssemblyBuilderAccess access)
{
AssemblyName assemblyName = new AssemblyName ();
assemblyName.Name = ASSEMBLY_NAME;
assembly =
Thread.GetDomain ().DefineDynamicAssembly (
- assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ());
+ assemblyName, access, Path.GetTempPath ());
module = assembly.DefineDynamicModule ("module1");
typeCount = 0;
Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], MonoTests.System.Reflection.Emit.MonoGenericClassTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", inst.AssemblyQualifiedName, "#4");
Assert.AreEqual ("foo.type[System.Double,System.String]", inst.ToString (), "#5");
}
+
+ [Test]
+ [Category ("NotDotNet")]
+ public void GetEventMustWorkUnderCompilerContext ()
+ {
+ SetUp (AssemblyBuilderAccess.RunAndSave | (AssemblyBuilderAccess)0x800);
+ var tb = module.DefineType ("foo.type");
+ tb.DefineGenericParameters ("T");
+
+ var ginst = tb.MakeGenericType (typeof (double));
+
+ try {
+ ginst.GetEvent ("foo", BindingFlags.Public | BindingFlags.Instance);
+ } catch (NotSupportedException) {
+ Assert.Fail ("#1");
+ }
+ }
+
+ [Test]
+ public void MethodsThatRaiseNotSupported ()
+ {
+ var tb = module.DefineType ("foo.type");
+ tb.DefineGenericParameters ("T");
+
+ var ginst = tb.MakeGenericType (typeof (double));
+
+ /*try { //FIXME this doesn't work yet
+ ginst.GetElementType ();
+ Assert.Fail ("#1");
+ } catch (NotSupportedException) { }*/
+ try {
+ ginst.GetInterface ("foo", true);
+ Assert.Fail ("#2");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetEvent ("foo", BindingFlags.Public | BindingFlags.Instance);
+ Assert.Fail ("#3");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetField ("foo", BindingFlags.Public | BindingFlags.Instance);
+ Assert.Fail ("#4");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetMembers (BindingFlags.Public | BindingFlags.Instance);
+ Assert.Fail ("#5");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetMethod ("Foo");
+ Assert.Fail ("#6");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetNestedType ("foo", BindingFlags.Public | BindingFlags.Instance);
+ Assert.Fail ("#7");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetProperty ("foo");
+ Assert.Fail ("#8");
+ } catch (NotSupportedException) { }
+ try {
+ var x = ginst.TypeInitializer;
+ Assert.Fail ("#9");
+ } catch (NotSupportedException) { }
+ try {
+ var x = ginst.InvokeMember ("foo", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, null, null);
+ Assert.Fail ("#10");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.IsDefined (typeof (int), true);
+ Assert.Fail ("#11");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetCustomAttributes (true);
+ Assert.Fail ("#12");
+ } catch (NotSupportedException) { }
+ try {
+ ginst.GetCustomAttributes (typeof (int), true);
+ Assert.Fail ("#13");
+ } catch (NotSupportedException) { }
+ }
}
#endif
}
+2009-08-13 Zoltan Varga <vargaz@gmail.com>
+
+ * GCHandleTest.cs: Add a test for null GC handles with type
+ WeakTrackResurrection.
+
2009-06-20 Zoltan Varga <vargaz@gmail.com>
* *.cs: Convert all tests to new-style nunit classes/methods.
GCHandle gch = (GCHandle)ptr;
}
+ [Test]
+ public void AllocNullWeakTrack ()
+ {
+ GCHandle gch = GCHandle.Alloc(null, GCHandleType.WeakTrackResurrection);
+ }
+
[Test]
[ExpectedException (typeof (InvalidOperationException))]
public void AddrOfPinnedObjectNormal ()
+++ /dev/null
-#if NET_4_0
-// AggregateExceptionTests.cs
-//
-// Copyright (c) 2008 Jérémie "Garuma" Laval
-//
-// 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.Linq;
-using System.Threading;
-
-using NUnit;
-using NUnit.Core;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture()]
- public class AggregateExceptionTests
- {
- AggregateException e;
-
- [SetUpAttribute]
- public void Setup()
- {
- e = new AggregateException(new Exception("foo"), new AggregateException(new Exception("bar"), new Exception("foobar")));
- }
-
- [TestAttribute]
- public void FlattenTestCase()
- {
- AggregateException ex = e.Flatten();
-
- Assert.AreEqual(3, ex.InnerExceptions.Count, "#1");
- Assert.AreEqual(3, ex.InnerExceptions.Where((exception) => !(exception is AggregateException)).Count(), "#2");
- }
- }
-}
-#endif
+2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * ParallelTests.cs: Remove While test case.
+ * AggregateExceptionTests.cs: Moved file.
+
2009-07-30 Jérémie Laval <jeremie.laval@gmail.com>
* System.Threading.Tasks/TaskTest.cs:
Parallel.ForEach (e, delegate (int element) { throw new Exception ("foo"); });
}
+ /* Disabled as this is an API addition
[Test]
public void ParallelWhileTestCase()
{
Assert.Greater(i, 10, "#1");
Assert.AreEqual(10, count, "#2");
});
- }
+ }*/
}
}
#endif
--- /dev/null
+#if NET_4_0
+// AggregateExceptionTests.cs
+//
+// Copyright (c) 2008 Jérémie "Garuma" Laval
+//
+// 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.Linq;
+using System.Threading;
+
+using NUnit;
+using NUnit.Core;
+using NUnit.Framework;
+
+namespace ParallelFxTests
+{
+
+ [TestFixture()]
+ public class AggregateExceptionTests
+ {
+ AggregateException e;
+
+ [SetUpAttribute]
+ public void Setup()
+ {
+ e = new AggregateException(new Exception("foo"), new AggregateException(new Exception("bar"), new Exception("foobar")));
+ }
+
+ [TestAttribute]
+ public void FlattenTestCase()
+ {
+ AggregateException ex = e.Flatten();
+
+ Assert.AreEqual(3, ex.InnerExceptions.Count, "#1");
+ Assert.AreEqual(3, ex.InnerExceptions.Where((exception) => !(exception is AggregateException)).Count(), "#2");
+ }
+ }
+}
+#endif
System.Threading.Tasks/Task.cs
System.Threading.Tasks/TaskCompletionSource.cs
System.Threading.Tasks/TaskSchedulerException.cs
-System.Collections.Concurrent/BlockingCollection.cs
System.Collections.Concurrent/OrderablePartitioner.cs
System.Collections.Concurrent/ConcurrentDictionary.cs
System.Collections.Concurrent/Partitioner.cs
System.Threading/Snzi.cs
System.Threading/CancellationToken.cs
System.Threading/ICancelableOperation.cs
-System.Threading/Barrier.cs
System.Threading/ParallelLoopResult.cs
System.Threading/CSnzi.cs
-System.Threading/AggregateException.cs
System.Threading/SpinWait.cs
System.Threading/SemaphoreSlim.cs
System.Threading/CancellationTokenRegistration.cs
System.Threading/ManualResetEventSlim.cs
System.Threading/ThreadLocal.cs
System.Threading/Watch.cs
+System/AggregateException.cs
System.Collections.Concurrent/ConcurrentQueueTests.cs
System.Collections.Concurrent/ConcurrentBagTests.cs
System.Collections.Concurrent/ConcurrentStackTests.cs
-System.Collections.Concurrent/BlockingCollectionTests.cs
System.Collections.Concurrent/ConcurrentDictionaryTests.cs
System.Collections.Concurrent/CollectionStressTestHelper.cs
System.Collections.Concurrent/ParallelConcurrentQueueTests.cs
System.Threading/SemaphoreSlimTests.cs
System.Threading/ParallelTests.cs
System.Threading/CountdownEventTests.cs
-System.Threading/AggregateExceptionTests.cs
+System/AggregateExceptionTests.cs
System.Threading/ThreadLazyTests.cs
System.Threading/ParallelTestHelper.cs
+++ /dev/null
-// CS0026: Keyword `this' is not valid in a static property, static method, or static field initializer
-// Line: 7
-
-class A : B
-{
- public A ()
- : base (this)
- {
- }
-}
-
-class B
-{
- public B (B b)
- {
- }
-}
\ No newline at end of file
--- /dev/null
+// CS0007: Keyword `this' is not available in the current context
+// Line: 14
+
+class B
+{
+ public B (object o)
+ {
+ }
+}
+
+class C : B
+{
+ public C ()
+ : base (this)
+ {
+ }
+}
+
--- /dev/null
+// CS0027: Keyword `this' is not available in the current context
+// Line: 6
+
+class Program
+{
+ const object y = this;
+}
--- /dev/null
+// CS0120: An object reference is required to access non-static member `C.i'
+// Line: 16
+
+class B
+{
+ public B (object o)
+ {
+ }
+}
+
+class C : B
+{
+ int i;
+
+ public C ()
+ : base (i)
+ {
+ }
+}
+
--- /dev/null
+// CS0120: An object reference is required to access non-static member `C.Enum()'
+// Line: 20
+
+using System;
+
+enum Enum
+{
+ Test
+}
+
+class A : Attribute
+{
+ public A (object e)
+ {
+ }
+}
+
+class C
+{
+ [A (Enum.Test)]
+ int Enum ()
+ {
+ return 0;
+ }
+}
--- /dev/null
+// CS0206: A property or indexer may not be passed as an out or ref parameter
+// Line: 22
+
+using System;
+
+namespace N
+{
+ public class Test
+ {
+ public double this[int i]
+ {
+ get { return 1; }
+ }
+
+ public static void WriteOutData(out double d)
+ {
+ d = 5.0;
+ }
+
+ public static void Main(string[] args)
+ {
+ Test test = new Test();
+ WriteOutData(out test[1]);
+ }
+ }
+}
+
--- /dev/null
+// CS0432: Alias `Sa' not found
+// Line: 6
+
+using S = System;
+
+[assembly: Sa::CLSCompliantAttribute (false)]
--- /dev/null
+// CS0533: `B.MyEvent' hides inherited abstract member `A.MyEvent'
+// Line: 11
+
+using System;
+
+abstract class A {
+ public abstract event EventHandler MyEvent;
+}
+
+class B : A {
+ public event EventHandler MyEvent;
+}
+++ /dev/null
-// CS0534: `B' does not implement inherited abstract member `A.MyEvent.add'
-// Line: 11
-
-using System;
-
-abstract class A {
- public abstract event EventHandler MyEvent;
-}
-
-class B : A {
- public event EventHandler MyEvent;
-}
--- /dev/null
+// CS1967: A constraint cannot be the dynamic type
+// Line: 4
+
+class C<T> where T : dynamic
+{
+}
+2009-08-19 Marek Safar <marek.safar@gmail.com>
+
+ * generic.cs, iterators.cs, expression.cs, statement.cs, ecore.cs,
+ cs-parser.jay, attribute.cs, codegen.cs: Better error reports.
+
+2009-08-18 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Removed boolean fields from EmitContext.
+
+2009-08-18 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Add IResolveContext::IsStatic.
+
+2009-08-18 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Moved TopBlock's methods from EmitContext to TopBlock.
+
+2009-08-17 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Removed DeclContainer from EmitContext.
+
+2009-08-17 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Add IResolveContext::CurrentTypeParameters.
+
+2009-08-14 Marek Safar <marek.safar@gmail.com>
+
+ * *.cs: Removed TypeContainer and ContainerType from EmitContext.
+
+2009-08-14 Marek Safar <marek.safar@gmail.com>
+
+ * decl.cs, expression.cs, namespace.cs, ecore.cs, class.cs,
+ codegen.cs: Add IResolveContext::LookupExtensionMethod.
+
+2009-08-13 Marek Safar <marek.safar@gmail.com>
+
+ * decl.cs: Look in PartialContainer for parent type parameters.
+
+2009-08-13 Marek Safar <marek.safar@gmail.com>
+
+ * decl.cs, namespace.cs, ecore.cs, class.cs, attribute.cs,
+ codegen.cs: Add IResolveContext::LookupTypeParameter.
+
+2009-08-13 Marek Safar <marek.safar@gmail.com>
+
+ * lambda.cs, expression.cs, statement.cs, namespace.cs, ecore.cs:
+ Moved resolved logic from Emit to Resolve.
+
+2009-08-13 Marek Safar <marek.safar@gmail.com>
+
+ * parameter.cs, decl.cs, roottypes.cs, class.cs, attribute.cs,
+ codegen.cs: Reworked atttributes handling of ResolveContext.
+
+2009-08-12 Marek Safar <marek.safar@gmail.com>
+
+ * decl.cs, ecore.cs, class.cs, attribute.cs, codegen.cs: Pushed
+ LookupNamespaceOrType to ResolveContext.
+
+2009-08-12 Marek Safar <marek.safar@gmail.com>
+
+ * typemanager.cs, decl.cs, expression.cs, namespace.cs, ecore.cs,
+ class.cs: Removed unused parameters and methods.
+
+2009-08-11 Marek Safar <marek.safar@gmail.com>
+
+ * generic.cs, lambda.cs, anonymous.cs, statement.cs, generic-mcs.cs,
+ codegen.cs: Finding the best common type of a set of expressions for
+ lambda statements.
+
2009-08-07 Marek Safar <marek.safar@gmail.com>
* dynamic.cs, expression.cs: More dynamic conversions.
// Local variable which holds this storey instance
public LocalTemporary Instance;
- public AnonymousMethodStorey (Block block, DeclSpace parent, MemberBase host, GenericMethod generic, string name)
+ public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, GenericMethod generic, string name)
: base (parent, generic, MakeMemberName (host, name, generic, block.StartLocation), Modifiers.PRIVATE)
{
Parent = parent;
public void AddCapturedThisField (EmitContext ec)
{
- TypeExpr type_expr = new TypeExpression (ec.ContainerType, Location);
+ TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
Field f = AddCompilerGeneratedField ("<>f__this", type_expr);
f.Define ();
hoisted_this = new HoistedThis (this, f);
TypeArguments targs = new TypeArguments ();
if (tparams.Length < CountTypeParameters) {
- TypeParameter[] parent_tparams = ec.DeclContainer.Parent.PartialContainer.TypeParameters;
+ TypeParameter[] parent_tparams = ec.GenericDeclContainer.Parent.PartialContainer.TypeParameters;
for (int i = 0; i < parent_tparams.Length; ++i)
targs.Add (new TypeParameterExpr (parent_tparams[i], Location));
}
public AnonymousMethodStorey GetGenericStorey ()
{
DeclSpace storey = this;
- while (storey != null && storey.CurrentTypeParameters.Length == 0)
+ while (storey != null && storey.CurrentTypeParameters == null)
storey = storey.Parent;
return storey as AnonymousMethodStorey;
//
public Type MutateGenericArgument (Type type)
{
- foreach (TypeParameter tp in CurrentTypeParameters) {
- if (tp.Name == type.Name) {
+ if (CurrentTypeParameters != null) {
+ TypeParameter tp = TypeParameter.FindTypeParameter (CurrentTypeParameters, type.Name);
+ if (tp != null)
return tp.Type;
- }
}
return type;
//
public bool ImplicitStandardConversionExists (EmitContext ec, Type delegate_type)
{
- using (ec.With (EmitContext.Flags.InferReturnType, false)) {
- using (ec.Set (EmitContext.Flags.ProbingMode)) {
+ using (ec.With (EmitContext.Options.InferReturnType, false)) {
+ using (ec.Set (EmitContext.Options.ProbingMode)) {
return Compatible (ec, delegate_type) != null;
}
}
public Type InferReturnType (EmitContext ec, TypeInferenceContext tic, Type delegate_type)
{
AnonymousMethodBody am;
- using (ec.Set (EmitContext.Flags.ProbingMode | EmitContext.Flags.InferReturnType)) {
- am = CompatibleMethod (ec, tic, TypeManager.null_type, delegate_type);
+ using (ec.Set (EmitContext.Options.ProbingMode | EmitContext.Options.InferReturnType)) {
+ am = CompatibleMethod (ec, tic, InternalType.Arglist, delegate_type);
}
if (am == null)
return null;
- // Stop referencing gmcs NullLiteral type
- if (am.ReturnType == TypeManager.null_type)
- am.ReturnType = null;
-
return am.ReturnType;
}
//
MethodInfo invoke_mb = Delegate.GetInvokeMethod (
- ec.ContainerType, delegate_type);
+ ec.CurrentType, delegate_type);
Type return_type = TypeManager.TypeToCoreType (invoke_mb.ReturnType);
#if MS_COMPATIBLE
public override Expression DoResolve (EmitContext ec)
{
- if (!ec.IsAnonymousMethodAllowed) {
+ if (ec.HasSet (EmitContext.Options.ConstantScope)) {
Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
return null;
}
Block = am.Block;
}
- public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
+ public override EmitContext CreateEmitContext (ILGenerator ig)
{
EmitContext aec = AnonymousMethod.aec;
aec.ig = ig;
- aec.IsStatic = (ModFlags & Modifiers.STATIC) != 0;
+ aec.AnonymousStatic = (ModFlags & Modifiers.STATIC) != 0;
return aec;
}
{
// TODO: Implement clone
aec = new EmitContext (
- ec.ResolveContext, ec.TypeContainer, ec.DeclContainer,
- Location, null, ReturnType,
- (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
+ ec.ResolveContext, ec.GenericDeclContainer,
+ null, ReturnType);
aec.CurrentAnonymousMethod = this;
- aec.IsStatic = ec.IsStatic;
IDisposable aec_dispose = null;
- EmitContext.Flags flags = 0;
- if (ec.InferReturnType)
- flags |= EmitContext.Flags.InferReturnType;
+ EmitContext.Options flags = 0;
+ if (ec.HasSet (EmitContext.Options.InferReturnType)) {
+ flags |= EmitContext.Options.InferReturnType;
+ aec.ReturnTypeInference = new TypeInferenceContext ();
+ }
if (ec.IsInProbingMode)
- flags |= EmitContext.Flags.ProbingMode;
+ flags |= EmitContext.Options.ProbingMode;
- if (ec.IsInFieldInitializer)
- flags |= EmitContext.Flags.InFieldInitializer;
+ if (ec.HasSet (EmitContext.Options.FieldInitializerScope))
+ flags |= EmitContext.Options.FieldInitializerScope;
- if (ec.IsInUnsafeScope)
- flags |= EmitContext.Flags.InUnsafe;
+ if (ec.InUnsafe)
+ flags |= EmitContext.Options.UnsafeScope;
// HACK: Flag with 0 cannot be set
if (flags != 0)
aec_dispose = aec.Set (flags);
- bool unreachable;
- bool res = aec.ResolveTopBlock (ec, Block, Block.Parameters, null, out unreachable);
+ bool res = Block.Resolve (ec.CurrentBranching, aec, Block.Parameters, null);
- if (ec.InferReturnType)
- ReturnType = aec.ReturnType;
+ if (ec.HasSet (EmitContext.Options.InferReturnType)) {
+ aec.ReturnTypeInference.FixAllTypes ();
+ ReturnType = aec.ReturnTypeInference.InferredTypeArguments [0];
+ }
if (aec_dispose != null) {
aec_dispose.Dispose ();
modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
}
- DeclSpace parent = storey != null ? storey : ec.TypeContainer;
+ TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition;
MemberCore mc = ec.ResolveContext as MemberCore;
string name = CompilerGeneratedClass.MakeName (parent != storey ? mc.Name : null,
new TypeExpression (ReturnType, Location), parameters);
ArrayList list = new ArrayList ();
- foreach (TypeParameter tparam in ((IMethodData)mc).GenericMethod.CurrentTypeParameters) {
+ foreach (TypeParameter tparam in ec.CurrentTypeParameters) {
if (tparam.Constraints != null)
list.Add (tparam.Constraints.Clone ());
}
ig.Emit (OpCodes.Ldftn, delegate_method);
- ConstructorInfo constructor_method = Delegate.GetConstructor (ec.ContainerType, type);
+ ConstructorInfo constructor_method = Delegate.GetConstructor (ec.CurrentType, type);
#if MS_COMPATIBLE
if (type.IsGenericType && type is TypeBuilder)
constructor_method = TypeBuilder.GetConstructor (type, constructor_method);
if (Expr == EmptyExpression.Null)
return;
- using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
+ using (ec.With (EmitContext.Options.DoFlowAnalysis, true)) {
// Verify that the argument is readable
if (ArgType != AType.Out)
Expr = Expr.Resolve (ec);
return null;
}
- if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) {
- source.Error_UnexpectedKind (ec.DeclContainer, "variable or value", loc);
- return null;
- } else if ((RootContext.Version == LanguageVersion.ISO_1) &&
+ if ((RootContext.Version == LanguageVersion.ISO_1) &&
(source is MethodGroupExpr)){
((MethodGroupExpr) source).ReportUsageError ();
return null;
//
// TODO: Use ResolveContext only
- EmitContext f_ec = new EmitContext (rc, rc.DeclContainer, loc, null, TypeManager.void_type, 0, true);
- f_ec.IsStatic = ec.IsStatic;
+ EmitContext f_ec = new EmitContext (rc, rc.GenericDeclContainer, null, TypeManager.void_type);
f_ec.CurrentBlock = ec.CurrentBlock;
- EmitContext.Flags flags = EmitContext.Flags.InFieldInitializer;
- if (ec.IsInUnsafeScope)
- flags |= EmitContext.Flags.InUnsafe;
-
- f_ec.Set (flags);
+ EmitContext.Options flags = EmitContext.Options.FieldInitializerScope | EmitContext.Options.ConstructorScope;
+ if (ec.InUnsafe)
+ flags |= EmitContext.Options.UnsafeScope;
- resolved = base.DoResolve (f_ec) as ExpressionStatement;
+ using (f_ec.Set (flags)) {
+ resolved = base.DoResolve (f_ec) as ExpressionStatement;
+ }
}
return resolved;
return null;
MemberAccess ma = target as MemberAccess;
- using (ec.Set (EmitContext.Flags.InCompoundAssignment)) {
+ using (ec.Set (EmitContext.Options.CompoundAssignmentScope)) {
target = target.Resolve (ec);
}
/// Base class for objects that can have Attributes applied to them.
/// </summary>
public abstract class Attributable {
- /// <summary>
- /// Attributes for this type
- /// </summary>
+ //
+ // Holds all attributes attached to this element
+ //
protected Attributes attributes;
- public Attributable (Attributes attrs)
+ public void AddAttributes (Attributes attrs, IResolveContext context)
{
- if (attrs != null)
- OptAttributes = attrs;
+ if (attrs == null)
+ return;
+
+ if (attributes == null)
+ attributes = attrs;
+ else
+ throw new NotImplementedException ();
+
+ attributes.AttachTo (this, context);
}
- public Attributes OptAttributes
- {
+ public Attributes OptAttributes {
get {
return attributes;
}
set {
attributes = value;
-
- if (attributes != null) {
- attributes.AttachTo (this);
- }
}
}
/// </summary>
public abstract AttributeTargets AttributeTargets { get; }
- public abstract IResolveContext ResolveContext { get; }
-
public abstract bool IsClsComplianceRequired ();
/// <summary>
public class Attribute : Expression
{
- //
- // Wraps owner resolve context, the owner is an attribute
- // parent and the rest is exactly same
- //
- struct AttributeResolveContext : IResolveContext
- {
- readonly IResolveContext rc;
-
- public AttributeResolveContext (IResolveContext rc)
- {
- this.rc = rc;
- }
-
- #region IResolveContext Members
-
- public DeclSpace DeclContainer {
- get {
- DeclSpace ds = rc as DeclSpace;
- if (ds == null)
- return rc.DeclContainer;
-
- return ds;
- }
- }
-
- public bool IsInObsoleteScope {
- get { return rc.IsInObsoleteScope; }
- }
-
- public bool IsInUnsafeScope {
- get { return rc.IsInUnsafeScope; }
- }
-
- public DeclSpace GenericDeclContainer {
- get { return rc.GenericDeclContainer; }
- }
-
- #endregion
- }
-
public readonly string ExplicitTarget;
public AttributeTargets Target;
-
- // TODO: remove this member
- public readonly string Name;
- public readonly Expression LeftExpr;
- public readonly string Identifier;
+ readonly ATypeNameExpression expression;
Arguments PosArguments;
Arguments NamedArguments;
bool resolve_error;
readonly bool nameEscaped;
- // It can contain more onwers when the attribute is applied to multiple fiels.
- protected Attributable[] owners;
+ //
+ // An attribute can be attached to multiple targets (e.g. multiple fields)
+ //
+ protected Attributable[] targets;
+
+ //
+ // A member context for the attribute, it's much easier to hold it here
+ // than trying to pull it during resolve
+ //
+ IResolveContext context;
static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
static Assembly orig_sec_assembly;
// Cache for parameter-less attributes
static PtrHashtable att_cache;
- public Attribute (string target, Expression left_expr, string identifier, Arguments[] args, Location loc, bool nameEscaped)
+ public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
{
- LeftExpr = left_expr;
- Identifier = identifier;
- Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
+ //LeftExpr = left_expr;
+ //Identifier = identifier;
+ //Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
+
+ this.expression = expr;
if (args != null) {
PosArguments = args [0];
NamedArguments = args [1];
public Attribute Clone ()
{
- Attribute a = new Attribute (ExplicitTarget, LeftExpr, Identifier, null, loc, nameEscaped);
+ Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
a.PosArguments = PosArguments;
a.NamedArguments = NamedArguments;
return a;
att_cache = new PtrHashtable ();
}
- public virtual void AttachTo (Attributable owner)
+ //
+ // When the same attribute is attached to multiple fiels
+ // we use @target field as a list of targets. The attribute
+ // has to be resolved only once but emitted for each target.
+ //
+ public virtual void AttachTo (Attributable target, IResolveContext context)
{
- if (this.owners == null) {
- this.owners = new Attributable[1] { owner };
+ if (this.targets == null) {
+ this.targets = new Attributable[] { target };
+ this.context = context;
return;
}
- // When the same attribute is attached to multiple fiels
- // we use this extra_owners as a list of owners. The attribute
- // then can be removed because will be emitted when first owner
- // is served
- Attributable[] new_array = new Attributable [this.owners.Length + 1];
- owners.CopyTo (new_array, 0);
- new_array [owners.Length] = owner;
- this.owners = new_array;
- owner.OptAttributes = null;
+ // Resize target array
+ Attributable[] new_array = new Attributable [this.targets.Length + 1];
+ targets.CopyTo (new_array, 0);
+ new_array [targets.Length] = target;
+ this.targets = new_array;
+
+ // No need to update context, different targets cannot have
+ // different contexts, it's enough to remove same attributes
+ // from secondary members.
+
+ target.OptAttributes = null;
}
void Error_InvalidNamedArgument (NamedArgument name)
"expression or array creation expression");
}
- static void Error_TypeParameterInAttribute (Location loc)
- {
- Report.Error (
- -202, loc, "Can not use a type parameter in an attribute");
- }
-
public void Error_MissingGuidAttribute ()
{
Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
Attributable Owner {
get {
- return owners [0];
+ return targets [0];
}
}
- protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
+ protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec)
{
- return expr.ResolveAsTypeTerminal (ec, silent);
+ return expr.ResolveAsTypeTerminal (ec, false);
}
- Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
+ Type ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
{
- IResolveContext rc = new AttributeResolveContext (Owner.ResolveContext);
-
- TypeExpr te;
- if (LeftExpr == null) {
- te = ResolveAsTypeTerminal (new SimpleName (name, Location), rc, silent);
- } else {
- te = ResolveAsTypeTerminal (new MemberAccess (LeftExpr, name), rc, silent);
- }
-
+ TypeExpr te = ResolveAsTypeTerminal (expr, context);
if (te == null)
return null;
Type t = te.Type;
if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
is_attr = true;
- } else if (!silent) {
+ } else {
Report.SymbolRelatedToPreviousError (t);
Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
}
/// </summary>
void ResolveAttributeType ()
{
+ Report.IMessageRecorder msg_recorder = new Report.MessageRecorder ();
+ Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder);
+ int errors = Report.Errors;
+
bool t1_is_attr = false;
- Type t1 = ResolvePossibleAttributeType (Identifier, true, ref t1_is_attr);
+ Type t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
bool t2_is_attr = false;
- Type t2 = nameEscaped ? null :
- ResolvePossibleAttributeType (Identifier + "Attribute", true, ref t2_is_attr);
+ Type t2;
+ ATypeNameExpression expanded = null;
+
+ if (nameEscaped) {
+ t2 = null;
+ } else {
+ expanded = (ATypeNameExpression) expression.Clone (null);
+ expanded.Name += "Attribute";
+
+ t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
+ }
+
+ msg_recorder.EndSession ();
+ Report.SetMessageRecorder (prev_recorder);
+ Report.Errors = errors;
if (t1_is_attr && t2_is_attr) {
- Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. " +
- "Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());
+ Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
+ GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
resolve_error = true;
return;
}
return;
}
- if (t1 == null && t2 == null)
- ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
- if (t1 != null)
- ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
- if (t2 != null)
- ResolvePossibleAttributeType (Identifier + "Attribute", false, ref t2_is_attr);
-
+ msg_recorder.PrintMessages ();
resolve_error = true;
}
if (Type != null)
return TypeManager.CSharpName (Type);
- return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;
+ return expression.GetSignatureForError ();
}
public bool HasSecurityAttribute {
t == TypeManager.type_type;
}
+ // TODO: Don't use this ambiguous value
+ public string Name {
+ get { return expression.Name; }
+ }
+
void ApplyModuleCharSet ()
{
if (Type != PredefinedAttributes.Get.DllImport)
}
}
- Attributable owner = Owner;
- DeclSpace ds = owner.ResolveContext as DeclSpace;
- if (ds == null)
- ds = owner.ResolveContext.DeclContainer;
-
- EmitContext ec = new EmitContext (owner.ResolveContext, ds, ds,
- Location, null, typeof (Attribute), ds.ModFlags, false);
- ec.IsAnonymousMethodAllowed = false;
+ DeclSpace ds = context.GenericDeclContainer;
+ EmitContext ec = new EmitContext (context, ds,
+ null, typeof (Attribute));
+ ec.Set (EmitContext.Options.ConstantScope);
ConstructorInfo ctor = ResolveConstructor (ec);
if (ctor == null) {
throw new NotImplementedException ("dynamic");
}
- MethodGroupExpr mg = MemberLookupFinal (ec, ec.ContainerType,
+ MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
Location) as MethodGroupExpr;
a.Resolve (ec);
Expression member = Expression.MemberLookup (
- ec.ContainerType, Type, name,
+ ec.CurrentType, Type, name,
MemberTypes.All,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
Location);
if (member == null) {
- member = Expression.MemberLookup (ec.ContainerType, Type, name,
+ member = Expression.MemberLookup (ec.CurrentType, Type, name,
MemberTypes.All, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
Location);
return false;
}
- if (a.Expr is TypeParameterExpr){
- Error_TypeParameterInAttribute (Location);
- return false;
- }
-
ObsoleteAttribute obsolete_attr;
if (member is PropertyExpr) {
field_infos.Add (fi);
}
- if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
+ if (obsolete_attr != null && !context.IsInObsoleteScope)
AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
}
}
try {
- foreach (Attributable owner in owners)
- owner.ApplyAttributeBuilder (this, cb, PredefinedAttributes.Get);
- }
- catch (Exception e) {
+ foreach (Attributable target in targets)
+ target.ApplyAttributeBuilder (this, cb, PredefinedAttributes.Get);
+ } catch (Exception e) {
Error_AttributeEmitError (e.Message);
return;
}
{
public readonly NamespaceEntry ns;
- public GlobalAttribute (NamespaceEntry ns, string target,
- Expression left_expr, string identifier, Arguments[] args, Location loc, bool nameEscaped):
- base (target, left_expr, identifier, args, loc, nameEscaped)
+ public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
+ Arguments[] args, Location loc, bool nameEscaped):
+ base (target, expression, args, loc, nameEscaped)
{
this.ns = ns;
- this.owners = new Attributable[1];
}
- public override void AttachTo (Attributable owner)
+ public override void AttachTo (Attributable target, IResolveContext context)
{
if (ExplicitTarget == "assembly") {
- owners [0] = CodeGen.Assembly;
+ base.AttachTo (CodeGen.Assembly, context);
return;
}
+
if (ExplicitTarget == "module") {
- owners [0] = RootContext.ToplevelTypes;
+ base.AttachTo (RootContext.ToplevelTypes, context);
return;
}
+
throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
}
RootContext.ToplevelTypes.NamespaceEntry = null;
}
- protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
+ protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec)
{
try {
Enter ();
- return base.ResolveAsTypeTerminal (expr, ec, silent);
+ return base.ResolveAsTypeTerminal (expr, ec);
}
finally {
Leave ();
Attrs.AddRange (attrs);
}
- public void AttachTo (Attributable attributable)
+ public void AttachTo (Attributable attributable, IResolveContext context)
{
foreach (Attribute a in Attrs)
- a.AttachTo (attributable);
+ a.AttachTo (attributable, context);
}
public Attributes Clone ()
// During an enum evaluation, none of the rules are valid
// Not sure whether it is bug in csc or in documentation
//
- if (ec.InEnumContext){
+ if (ec.HasSet (EmitContext.Options.EnumScope)){
if (left is EnumConstant)
left = ((EnumConstant) left).Child;
}
}
+ //
+ // Different context is needed when resolving type container base
+ // types. Type names come from the parent scope but type parameter
+ // names from the container scope.
+ //
+ struct BaseContext : IResolveContext
+ {
+ TypeContainer tc;
+
+ public BaseContext (TypeContainer tc)
+ {
+ this.tc = tc;
+ }
+
+ #region IResolveContext Members
+
+ public Type CurrentType {
+ get { return tc.Parent.CurrentType; }
+ }
+
+ public TypeParameter[] CurrentTypeParameters {
+ get { return tc.PartialContainer.CurrentTypeParameters; }
+ }
+
+ public TypeContainer CurrentTypeDefinition {
+ get { return tc.Parent.CurrentTypeDefinition; }
+ }
+
+ public DeclSpace DeclContainer {
+ get { return tc.Parent; }
+ }
+
+ public bool IsInObsoleteScope {
+ get { return tc.IsInObsoleteScope; }
+ }
+
+ public bool IsInUnsafeScope {
+ get { return tc.IsInUnsafeScope; }
+ }
+
+ public bool IsStatic {
+ get { return tc.IsStatic; }
+ }
+
+ public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
+ {
+ return null;
+ }
+
+ public FullNamedExpression LookupNamespaceAlias (string name)
+ {
+ return tc.Parent.LookupNamespaceAlias (name);
+ }
+
+ public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+ {
+ TypeParameter[] tp = CurrentTypeParameters;
+ if (tp != null) {
+ TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
+ if (t != null)
+ return new TypeParameterExpr (t, loc);
+ }
+
+ return tc.Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ }
+
+ public DeclSpace GenericDeclContainer {
+ get { return tc.GenericDeclContainer; }
+ }
+
+ #endregion
+ }
+
[Flags]
enum CachedMethods
{
}
}
- //
- // Emits the instance field initializers
- //
- public bool EmitFieldInitializers (EmitContext ec)
- {
- if (partial_parts != null) {
- foreach (TypeContainer part in partial_parts)
- part.EmitFieldInitializers (ec);
- }
-
- ArrayList fields;
-
- if (ec.IsStatic){
- fields = initialized_static_fields;
- } else {
- fields = initialized_fields;
- }
-
- if (fields == null)
- return true;
-
- foreach (FieldInitializer f in fields) {
- f.EmitStatement (ec);
- }
- return true;
- }
-
public override string DocComment {
get {
return comment;
int count = type_bases.Count;
TypeExpr [] ifaces = null;
+ IResolveContext base_context = new BaseContext (this);
for (int i = 0, j = 0; i < count; i++){
FullNamedExpression fne = (FullNamedExpression) type_bases [i];
// it does ObsoleteAttribute and constraint checks which require
// base type to be set
//
- TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (this, false);
+ TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (base_context, false);
if (fne_resolved == null)
continue;
if (base_class == TypeManager.system_object_expr)
base_class = new_base_class;
else {
- if (new_base_class != null && !new_base_class.Equals (base_class)) {
+ if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
Report.SymbolRelatedToPreviousError (base_class.Location, "");
Report.Error (263, part.Location,
"Partial declarations of `{0}' must not specify different base classes",
#if GMCS_SOURCE
GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
- int offset = CountTypeParameters - CurrentTypeParameters.Length;
+ int offset = CountTypeParameters;
+ if (CurrentTypeParameters != null)
+ offset -= CurrentTypeParameters.Length;
+
if (offset > 0) {
nested_gen_params = new GenericTypeParameterBuilder [offset];
Array.Copy (gen_params, nested_gen_params, offset);
void UpdateTypeParameterConstraints (TypeContainer part)
{
- TypeParameter[] current_params = CurrentTypeParameters;
+ TypeParameter[] current_params = type_params;
for (int i = 0; i < current_params.Length; i++) {
- Constraints c = part.CurrentTypeParameters [i].Constraints;
+ Constraints c = part.type_params [i].Constraints;
if (c == null)
continue;
throw new InternalErrorException ();
TypeExpr current_type = null;
-
- foreach (TypeParameter type_param in CurrentTypeParameters) {
- if (!type_param.Resolve (this)) {
- error = true;
- return false;
+ if (CurrentTypeParameters != null) {
+ foreach (TypeParameter type_param in CurrentTypeParameters) {
+ if (!type_param.Resolve (this)) {
+ error = true;
+ return false;
+ }
}
- }
- if (partial_parts != null && is_generic) {
- foreach (TypeContainer part in partial_parts)
- UpdateTypeParameterConstraints (part);
+ if (partial_parts != null) {
+ foreach (TypeContainer part in partial_parts)
+ UpdateTypeParameterConstraints (part);
+ }
}
for (int i = 0; i < TypeParameters.Length; ++i) {
return false;
}
- CurrentType = current_type.Type;
+ currentType = current_type.Type;
return true;
}
return true;
}
+ public override TypeParameter[] CurrentTypeParameters {
+ get {
+ return PartialContainer.type_params;
+ }
+ }
+
/// <summary>
/// Populates our TypeBuilder with fields and methods
/// </summary>
public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
{
- return NamespaceEntry.LookupExtensionMethod (extensionType, this, name, loc);
+ DeclSpace top_level = Parent;
+ if (top_level != null) {
+ while (top_level.Parent != null)
+ top_level = top_level.Parent;
+
+ ArrayList candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name);
+ if (candidates != null)
+ return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
+ }
+
+ return NamespaceEntry.LookupExtensionMethod (extensionType, name, loc);
}
protected override TypeAttributes TypeAttr {
else if (Name != "System.Object")
base_class = TypeManager.system_object_expr;
} else {
- if (Kind == Kind.Class && base_class is TypeParameterExpr){
+ if (Kind == Kind.Class && TypeManager.IsGenericParameter (base_class.Type)){
Report.Error (
689, base_class.Location,
"Cannot derive from `{0}' because it is a type parameter",
return true;
}
- bool IsStatic {
- get {
- return (ModFlags & Modifiers.STATIC) != 0;
- }
- }
-
//
// FIXME: How do we deal with the user specifying a different
// layout?
protected bool DefineParameters (ParametersCompiled parameters)
{
- IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
-
- if (!parameters.Resolve (rc))
+ if (!parameters.Resolve (this))
return false;
bool error = false;
return Parent.MemberCache.CheckExistingMembersOverloads (this, name, Parameters);
}
- public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
+ public virtual EmitContext CreateEmitContext (ILGenerator ig)
{
return new EmitContext (
- this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
+ this, this.ds, ig, MemberType);
}
protected override bool ResolveMemberType ()
(Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
}
+ public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+ {
+ TypeParameter[] tp = CurrentTypeParameters;
+ if (tp != null) {
+ TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
+ if (t != null)
+ return new TypeParameterExpr (t, loc);
+ }
+
+ return base.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ }
+
public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
if (a.Type == pa.Conditional) {
return true;
}
+ public override TypeParameter[] CurrentTypeParameters {
+ get {
+ if (GenericMethod != null)
+ return GenericMethod.CurrentTypeParameters;
+
+ return null;
+ }
+ }
+
//
// Creates the type
//
throw new NotSupportedException ("ET");
}
- public ExpressionStatement Resolve (ConstructorBuilder caller_builder, EmitContext ec)
+ public override Expression DoResolve (EmitContext ec)
{
+ eclass = ExprClass.Value;
+
+ // TODO: ec.GetSignatureForError ()
+ ConstructorBuilder caller_builder = ((Constructor) ec.ResolveContext).ConstructorBuilder;
+
if (argument_list != null) {
bool dynamic;
- argument_list.Resolve (ec, out dynamic);
+
+ //
+ // Spec mandates that constructor initializer will not have `this' access
+ //
+ using (ec.Set (EmitContext.Options.BaseInitializer)) {
+ argument_list.Resolve (ec, out dynamic);
+ }
+
if (dynamic) {
SimpleName ctor = new SimpleName (ConstructorBuilder.ConstructorName, loc);
return new DynamicInvocation (ctor, argument_list, loc).Resolve (ec) as ExpressionStatement;
}
}
+ type = ec.CurrentType;
if (this is ConstructorBaseInitializer) {
- if (ec.ContainerType.BaseType == null)
+ if (ec.CurrentType.BaseType == null)
return this;
- type = ec.ContainerType.BaseType;
- if (TypeManager.IsStruct (ec.ContainerType)) {
+ type = ec.CurrentType.BaseType;
+ if (TypeManager.IsStruct (ec.CurrentType)) {
Report.Error (522, loc,
"`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
return this;
//
// struct D { public D (int a) : this () {}
//
- if (TypeManager.IsStruct (ec.ContainerType) && argument_list == null)
- return this;
-
- type = ec.ContainerType;
+ if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
+ return this;
}
base_constructor_group = MemberLookupFinal (
if (base_constructor_group == null)
return this;
+
+ if (!ec.IsStatic)
+ base_constructor_group.InstanceExpression = ec.GetThis (loc);
ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
-
+
if (base_ctor == caller_builder){
Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
}
return this;
}
- public override Expression DoResolve (EmitContext ec)
- {
- throw new NotSupportedException ();
- }
-
public override void Emit (EmitContext ec)
{
// It can be null for static initializers
return;
ec.Mark (loc);
- if (!ec.IsStatic)
- base_constructor_group.InstanceExpression = ec.GetThis (loc);
-
+
base_constructor_group.EmitCall (ec, argument_list);
}
base.Emit ();
- EmitContext ec = CreateEmitContext (null, null);
+ EmitContext ec = CreateEmitContext (null);
//
// If we use a "this (...)" constructor initializer, then
((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
block.AddThisVariable (Parent, Location);
- if (!block.ResolveMeta (ec, Parameters))
- block = null;
-
if (block != null && (ModFlags & Modifiers.STATIC) == 0){
if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
Initializer = new GeneratedBaseInitializer (Location);
- //
- // Spec mandates that Initializers will not have `this' access
- //
if (Initializer != null) {
- ec.IsStatic = true;
- ExpressionStatement expr = Initializer.Resolve (ConstructorBuilder, ec);
- ec.IsStatic = false;
- block.AddScopeStatement (new StatementExpression (expr));
+ block.AddScopeStatement (new StatementExpression (Initializer));
}
}
}
Parameters.ApplyAttributes (ConstructorBuilder);
-
- SourceMethod source = null;
- if (block == null)
- ec.OmitDebuggingInfo = true;
- else
- source = SourceMethod.Create (Parent, ConstructorBuilder, block);
-
- bool unreachable = false;
- if (block != null) {
- if (!ec.ResolveTopBlock (null, block, Parameters, this, out unreachable))
- return;
- ec.EmitMeta (block);
+ SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
- if (Report.Errors > 0)
- return;
-
- ec.EmitResolvedTopBlock (block, unreachable);
+ if (block != null) {
+ if (block.Resolve (null, ec, Parameters, this)) {
+ block.Emit (ec);
+ }
}
if (source != null)
}
}
- public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
+ public EmitContext CreateEmitContext (ILGenerator ig)
{
ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
- EmitContext ec = new EmitContext (this, Parent, Location, ig_, TypeManager.void_type, ModFlags, true);
+ EmitContext ec = new EmitContext (this, Parent, ig_, TypeManager.void_type);
ec.CurrentBlock = block;
+ ec.Set (EmitContext.Options.ConstructorScope);
return ec;
}
Attributes OptAttributes { get; }
ToplevelBlock Block { get; set; }
- EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
+ EmitContext CreateEmitContext (ILGenerator ig);
ObsoleteAttribute GetObsoleteAttribute ();
string GetSignatureForError ();
bool IsExcluded ();
if (implementing != null)
parent_method = implementing;
- EmitContext ec = method.CreateEmitContext (container, null);
+ EmitContext ec = method.CreateEmitContext (null);
if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
return false;
}
//
public void Emit (DeclSpace parent)
{
- ToplevelBlock block = method.Block;
-
- EmitContext ec;
- if (block != null)
- ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
- else
- ec = method.CreateEmitContext (parent, null);
-
method.ParameterInfo.ApplyAttributes (MethodBuilder);
if (GenericMethod != null)
SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
- ec.EmitTopBlock (method, block);
+ ToplevelBlock block = method.Block;
+ if (block != null) {
+ EmitContext ec = method.CreateEmitContext (builder.GetILGenerator ());
+ if (block.Resolve (null, ec, method.ParameterInfo, method)) {
+ block.Emit (ec);
+ }
+ }
if (source != null) {
method.EmitExtraSymbolInfo (source);
public override void Emit()
{
- EmitContext ec = new EmitContext (this, Parent, Location, null, TypeManager.void_type, ModFlags);
+ EmitContext ec = new EmitContext (this, Parent, null, TypeManager.void_type);
Constant c = size_expr.ResolveAsConstant (ec, this);
if (c == null)
return;
public abstract ParametersCompiled ParameterInfo { get ; }
public abstract Type ReturnType { get; }
- public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
+ public abstract EmitContext CreateEmitContext (ILGenerator ig);
#endregion
public override MethodBuilder Define (DeclSpace parent)
{
- parameters.Resolve (ResolveContext);
+ parameters.Resolve (this);
base.Define (parent);
}
}
- public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
+ public override EmitContext CreateEmitContext (ILGenerator ig)
{
return new EmitContext (this,
- ds, method.ds, method.Location, ig, ReturnType,
- method.ModFlags, false);
+ method.ds, ig, ReturnType);
}
public override ObsoleteAttribute GetObsoleteAttribute ()
}
}
- public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
+ public override EmitContext CreateEmitContext (ILGenerator ig)
{
return new EmitContext (
- this, method.Parent, Location, ig, ReturnType,
- method.ModFlags, false);
+ this, method.Parent, ig, ReturnType);
}
public override ObsoleteAttribute GetObsoleteAttribute ()
public override MethodBuilder Define (DeclSpace parent)
{
- parameters.Resolve (ResolveContext);
+ parameters.Resolve (this);
return base.Define (parent);
}
/// </summary>
public interface IResolveContext
{
- DeclSpace DeclContainer { get; }
+ //
+ // A scope type context, it can be inflated for generic types
+ //
+ Type CurrentType { get; }
+
+ //
+ // A scope type parameters either VAR or MVAR
+ //
+ TypeParameter[] CurrentTypeParameters { get; }
+
+ //
+ // A type definition of the type context. For partial types definition use
+ // CurrentTypeDefinition.PartialContainer otherwise the context is local
+ //
+ // TODO: CurrentType.Definition
+ //
+ TypeContainer CurrentTypeDefinition { get; }
+
bool IsInObsoleteScope { get; }
bool IsInUnsafeScope { get; }
+ bool IsStatic { get; }
+
+ ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc);
+ FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104);
+ FullNamedExpression LookupNamespaceAlias (string name);
// the declcontainer to lookup for type-parameters. Should only use LookupGeneric on it.
//
/// </summary>
public class EmitContext : IResolveContext {
- //
- // Holds a varible used during collection or object initialization.
- //
- public Expression CurrentInitializerVariable;
-
- DeclSpace decl_space;
-
- public DeclSpace TypeContainer;
- public ILGenerator ig;
-
[Flags]
- public enum Flags : int {
+ public enum Options
+ {
/// <summary>
/// This flag tracks the `checked' state of the compilation,
/// it controls whether we should generate code that does overflow
/// checked/unchecked statements or expressions. Contrast this with
/// the ConstantCheckState flag.
/// </summary>
- CheckState = 1 << 0,
+ CheckedScope = 1 << 0,
/// <summary>
/// The constant check state is always set to `true' and cant be changed
/// </summary>
ConstantCheckState = 1 << 1,
- AllCheckStateFlags = CheckState | ConstantCheckState,
+ AllCheckStateFlags = CheckedScope | ConstantCheckState,
- /// <summary>
- /// Whether we are inside an unsafe block
- /// </summary>
- InUnsafe = 1 << 2,
+ //
+ // unsafe { ... } scope
+ //
+ UnsafeScope = 1 << 2,
+ CatchScope = 1 << 3,
+ FinallyScope = 1 << 4,
+ FieldInitializerScope = 1 << 5,
+ CompoundAssignmentScope = 1 << 6,
+ FixedInitializerScope = 1 << 7,
+ BaseInitializer = 1 << 8,
- InCatch = 1 << 3,
- InFinally = 1 << 4,
+ //
+ // Inside an enum definition, we do not resolve enumeration values
+ // to their enumerations, but rather to the underlying type/value
+ // This is so EnumVal + EnumValB can be evaluated.
+ //
+ // There is no "E operator + (E x, E y)", so during an enum evaluation
+ // we relax the rules
+ //
+ EnumScope = 1 << 9,
+
+ ConstantScope = 1 << 10,
+
+ ConstructorScope = 1 << 11,
/// <summary>
/// Whether control flow analysis is enabled
/// </summary>
- DoFlowAnalysis = 1 << 5,
+ DoFlowAnalysis = 1 << 20,
/// <summary>
/// Whether control flow analysis is disabled on structs
/// (only meaningful when DoFlowAnalysis is set)
/// </summary>
- OmitStructFlowAnalysis = 1 << 6,
+ OmitStructFlowAnalysis = 1 << 21,
///
/// Indicates the current context is in probing mode, no errors are reported.
///
- ProbingMode = 1 << 7,
+ ProbingMode = 1 << 22,
//
- // Inside field intializer expression
+ // Return and ContextualReturn statements will set the ReturnType
+ // value based on the expression types of each return statement
+ // instead of the method return type which is initially null.
//
- InFieldInitializer = 1 << 8,
-
- InferReturnType = 1 << 9,
-
- InCompoundAssignment = 1 << 10,
+ InferReturnType = 1 << 23,
- OmitDebuggingInfo = 1 << 11
+ OmitDebuggingInfo = 1 << 24
}
- Flags flags;
+ // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
+ // it's public so that we can use a struct at the callsite
+ public struct FlagsHandle : IDisposable
+ {
+ EmitContext ec;
+ readonly Options invmask, oldval;
- /// <summary>
- /// Whether we are emitting code inside a static or instance method
- /// </summary>
- public bool IsStatic;
+ public FlagsHandle (EmitContext ec, Options flagsToSet)
+ : this (ec, flagsToSet, flagsToSet)
+ {
+ }
- /// <summary>
- /// Whether the actual created method is static or instance method.
- /// Althoug the method might be declared as `static', if an anonymous
- /// method is involved, we might turn this into an instance method.
- ///
- /// So this reflects the low-level staticness of the method, while
- /// IsStatic represents the semantic, high-level staticness.
- /// </summary>
- //public bool MethodIsStatic;
+ internal FlagsHandle (EmitContext ec, Options mask, Options val)
+ {
+ this.ec = ec;
+ invmask = ~mask;
+ oldval = ec.flags & mask;
+ ec.flags = (ec.flags & invmask) | (val & mask);
+
+ if ((mask & Options.ProbingMode) != 0)
+ Report.DisableReporting ();
+ }
+
+ public void Dispose ()
+ {
+ if ((invmask & Options.ProbingMode) == 0)
+ Report.EnableReporting ();
+
+ ec.flags = (ec.flags & invmask) | oldval;
+ }
+ }
+
+ Options flags;
+
+ //
+ // Holds a varible used during collection or object initialization.
+ //
+ public Expression CurrentInitializerVariable;
+
+ DeclSpace decl_space;
+
+ public ILGenerator ig;
/// <summary>
/// The value that is allowed to be returned or NULL if there is no
/// </summary>
Type return_type;
- /// <summary>
- /// Points to the Type (extracted from the TypeContainer) that
- /// declares this body of code
- /// </summary>
- public readonly Type ContainerType;
-
- /// <summary>
- /// Whether this is generating code for a constructor
- /// </summary>
- public bool IsConstructor;
-
/// <summary>
/// Keeps track of the Type to LocalBuilder temporary storage created
/// to store structures (used to compute the address of the structure
public Block CurrentBlock;
- public int CurrentFile;
-
/// <summary>
/// The location where we store the return value.
/// </summary>
- LocalBuilder return_value;
+ public LocalBuilder return_value;
/// <summary>
/// The location where return has to jump to return the
/// </summary>
public bool HasReturnLabel;
- /// <summary>
- /// Whether we are in a `fixed' initialization
- /// </summary>
- public bool InFixedInitializer;
-
/// <summary>
/// Whether we are inside an anonymous method.
/// </summary>
public AnonymousExpression CurrentAnonymousMethod;
- /// <summary>
- /// Location for this EmitContext
- /// </summary>
- public Location loc;
-
- /// <summary>
- /// Inside an enum definition, we do not resolve enumeration values
- /// to their enumerations, but rather to the underlying type/value
- /// This is so EnumVal + EnumValB can be evaluated.
- ///
- /// There is no "E operator + (E x, E y)", so during an enum evaluation
- /// we relax the rules
- /// </summary>
- public bool InEnumContext;
-
public readonly IResolveContext ResolveContext;
/// <summary>
get { return CurrentAnonymousMethod as Iterator; }
}
- /// <summary>
- /// Whether we are in the resolving stage or not
- /// </summary>
- enum Phase {
- Created,
- Resolving,
- Emitting
- }
-
- bool isAnonymousMethodAllowed = true;
-
- Phase current_phase;
FlowBranching current_flow_branching;
- static int next_id = 0;
- int id = ++next_id;
+ public TypeInferenceContext ReturnTypeInference;
- public override string ToString ()
- {
- return String.Format ("EmitContext ({0}:{1})", id,
- CurrentAnonymousMethod, loc);
- }
-
- public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
- Type return_type, int code_flags, bool is_constructor)
+// static int next_id = 0;
+// int id = ++next_id;
+
+ public EmitContext (IResolveContext rc, DeclSpace ds, ILGenerator ig,
+ Type return_type)
{
this.ResolveContext = rc;
this.ig = ig;
- TypeContainer = parent;
this.decl_space = ds;
+
+ //
+ // The default setting comes from the command line option
+ //
if (RootContext.Checked)
- flags |= Flags.CheckState;
- flags |= Flags.ConstantCheckState;
+ flags |= Options.CheckedScope;
+
+ //
+ // The constant check state is always set to true
+ //
+ flags |= Options.ConstantCheckState;
if (return_type == null)
throw new ArgumentNullException ("return_type");
- IsStatic = (code_flags & Modifiers.STATIC) != 0;
ReturnType = return_type;
- IsConstructor = is_constructor;
- CurrentBlock = null;
- CurrentFile = 0;
- current_phase = Phase.Created;
-
- if (parent != null){
- // Can only be null for the ResolveType contexts.
- ContainerType = parent.TypeBuilder;
- if (rc.IsInUnsafeScope)
- flags |= Flags.InUnsafe;
- }
- loc = l;
}
- public EmitContext (IResolveContext rc, DeclSpace ds, Location l, ILGenerator ig,
- Type return_type, int code_flags, bool is_constructor)
- : this (rc, ds, ds, l, ig, return_type, code_flags, is_constructor)
- {
+ public Type CurrentType {
+ get { return ResolveContext.CurrentType; }
}
- public EmitContext (IResolveContext rc, DeclSpace ds, Location l, ILGenerator ig,
- Type return_type, int code_flags)
- : this (rc, ds, ds, l, ig, return_type, code_flags, false)
- {
+ public TypeParameter[] CurrentTypeParameters {
+ get { return ResolveContext.CurrentTypeParameters; }
}
- // IResolveContext.DeclContainer
- public DeclSpace DeclContainer {
- get { return decl_space; }
- set { decl_space = value; }
+ public TypeContainer CurrentTypeDefinition {
+ get { return ResolveContext.CurrentTypeDefinition; }
}
// IResolveContext.GenericDeclContainer
public DeclSpace GenericDeclContainer {
- get { return DeclContainer; }
- }
-
- public bool CheckState {
- get { return (flags & Flags.CheckState) != 0; }
+ get { return decl_space; }
}
public bool ConstantCheckState {
- get { return (flags & Flags.ConstantCheckState) != 0; }
+ get { return (flags & Options.ConstantCheckState) != 0; }
}
public bool InUnsafe {
- get { return (flags & Flags.InUnsafe) != 0; }
- }
-
- public bool InCatch {
- get { return (flags & Flags.InCatch) != 0; }
- }
-
- public bool InFinally {
- get { return (flags & Flags.InFinally) != 0; }
+ get { return HasSet (Options.UnsafeScope) || ResolveContext.IsInUnsafeScope; }
}
public bool DoFlowAnalysis {
- get { return (flags & Flags.DoFlowAnalysis) != 0; }
+ get { return (flags & Options.DoFlowAnalysis) != 0; }
}
public bool OmitStructFlowAnalysis {
- get { return (flags & Flags.OmitStructFlowAnalysis) != 0; }
+ get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
}
- // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
- // it's public so that we can use a struct at the callsite
- public struct FlagsHandle : IDisposable
+ public bool HasSet (Options options)
{
- EmitContext ec;
- readonly Flags invmask, oldval;
-
- public FlagsHandle (EmitContext ec, Flags flagsToSet)
- : this (ec, flagsToSet, flagsToSet)
- {
- }
-
- internal FlagsHandle (EmitContext ec, Flags mask, Flags val)
- {
- this.ec = ec;
- invmask = ~mask;
- oldval = ec.flags & mask;
- ec.flags = (ec.flags & invmask) | (val & mask);
-
- if ((mask & Flags.ProbingMode) != 0)
- Report.DisableReporting ();
- }
-
- public void Dispose ()
- {
- if ((invmask & Flags.ProbingMode) == 0)
- Report.EnableReporting ();
+ return (this.flags & options) == options;
+ }
- ec.flags = (ec.flags & invmask) | oldval;
- }
+ public bool HasAny (Options options)
+ {
+ return (this.flags & options) != 0;
}
// Temporarily set all the given flags to the given value. Should be used in an 'using' statement
- public FlagsHandle Set (Flags flagsToSet)
+ public FlagsHandle Set (Options options)
{
- return new FlagsHandle (this, flagsToSet);
+ return new FlagsHandle (this, options);
}
- public FlagsHandle With (Flags bits, bool enable)
+ public FlagsHandle With (Options options, bool enable)
{
- return new FlagsHandle (this, bits, enable ? bits : 0);
+ return new FlagsHandle (this, options, enable ? options : 0);
}
public FlagsHandle WithFlowAnalysis (bool do_flow_analysis, bool omit_struct_analysis)
{
- Flags newflags =
- (do_flow_analysis ? Flags.DoFlowAnalysis : 0) |
- (omit_struct_analysis ? Flags.OmitStructFlowAnalysis : 0);
- return new FlagsHandle (this, Flags.DoFlowAnalysis | Flags.OmitStructFlowAnalysis, newflags);
+ Options newflags =
+ (do_flow_analysis ? Options.DoFlowAnalysis : 0) |
+ (omit_struct_analysis ? Options.OmitStructFlowAnalysis : 0);
+ return new FlagsHandle (this, Options.DoFlowAnalysis | Options.OmitStructFlowAnalysis, newflags);
}
- /// <summary>
- /// If this is true, then Return and ContextualReturn statements
- /// will set the ReturnType value based on the expression types
- /// of each return statement instead of the method return type
- /// (which is initially null).
- /// </summary>
- public bool InferReturnType {
- get { return (flags & Flags.InferReturnType) != 0; }
- }
-
// IResolveContext.IsInObsoleteScope
public bool IsInObsoleteScope {
get {
}
public bool IsInProbingMode {
- get { return (flags & Flags.ProbingMode) != 0; }
+ get { return (flags & Options.ProbingMode) != 0; }
}
- // IResolveContext.IsInUnsafeScope
- public bool IsInUnsafeScope {
- get { return InUnsafe || ResolveContext.IsInUnsafeScope; }
+ bool IResolveContext.IsInUnsafeScope {
+ get { return InUnsafe; }
}
- public bool IsAnonymousMethodAllowed {
- get { return isAnonymousMethodAllowed; }
- set { isAnonymousMethodAllowed = value; }
- }
-
- public bool IsInFieldInitializer {
- get { return (flags & Flags.InFieldInitializer) != 0; }
- }
-
- public bool IsInCompoundAssignment {
- get { return (flags & Flags.InCompoundAssignment) != 0; }
+ // TODO: Hopefully temporary hack for anonyous methods, ResolveContext != EmitContext
+ public object AnonymousStatic;
+ public bool IsStatic {
+ get { return AnonymousStatic != null ? (bool) AnonymousStatic : ResolveContext.IsStatic; }
}
public bool IsVariableCapturingRequired {
}
public bool OmitDebuggingInfo {
- get { return (flags & Flags.OmitDebuggingInfo) != 0; }
+ get { return (flags & Options.OmitDebuggingInfo) != 0; }
set {
if (value)
- flags |= Flags.OmitDebuggingInfo;
+ flags |= Options.OmitDebuggingInfo;
else
- flags &= ~Flags.OmitDebuggingInfo;
+ flags &= ~Options.OmitDebuggingInfo;
}
}
// </summary>
public FlowBranching StartFlowBranching (Block block)
{
- flags |= Flags.DoFlowAnalysis;
+ flags |= Options.DoFlowAnalysis;
current_flow_branching = FlowBranching.CreateBranching (
CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation);
return branching;
}
- public FlowBranchingToplevel StartFlowBranching (ToplevelBlock stmt)
+ public FlowBranchingToplevel StartFlowBranching (ToplevelBlock stmt, FlowBranching parent)
{
- FlowBranchingToplevel branching = new FlowBranchingToplevel (CurrentBranching, stmt);
+ FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt);
current_flow_branching = branching;
return branching;
}
return local.Block.Toplevel != CurrentBlock.Toplevel;
}
- public void EmitMeta (ToplevelBlock b)
- {
- b.EmitMeta (this);
-
- if (HasReturnLabel)
- ReturnLabel = ig.DefineLabel ();
- }
-
- //
- // Here until we can fix the problem with Mono.CSharp.Switch, which
- // currently can not cope with ig == null during resolve (which must
- // be fixed for switch statements to work on anonymous methods).
- //
- public void EmitTopBlock (IMethodData md, ToplevelBlock block)
- {
- if (block == null)
- return;
-
- bool unreachable;
-
- if (ResolveTopBlock (null, block, md.ParameterInfo, md, out unreachable)){
- if (Report.Errors > 0)
- return;
-
- EmitMeta (block);
-
- current_phase = Phase.Emitting;
-#if PRODUCTION
- try {
-#endif
- EmitResolvedTopBlock (block, unreachable);
-#if PRODUCTION
- } catch (Exception e){
- Console.WriteLine ("Exception caught by the compiler while emitting:");
- Console.WriteLine (" Block that caused the problem begin at: " + block.loc);
-
- Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
- throw;
- }
-#endif
- }
- }
-
- bool resolved;
- bool unreachable;
-
- public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
- ParametersCompiled ip, IMethodData md, out bool unreachable)
- {
- if (resolved) {
- unreachable = this.unreachable;
- return true;
- }
-
- current_phase = Phase.Resolving;
- unreachable = false;
-
- if (!loc.IsNull)
- CurrentFile = loc.File;
-
-#if PRODUCTION
- try {
-#endif
- if (!block.ResolveMeta (this, ip))
- return false;
-
- using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
- FlowBranchingToplevel top_level;
- if (anonymous_method_host != null)
- top_level = new FlowBranchingToplevel (anonymous_method_host.CurrentBranching, block);
- else
- top_level = block.TopLevelBranching;
-
- current_flow_branching = top_level;
- bool ok = block.Resolve (this);
- current_flow_branching = null;
-
- if (!ok)
- return false;
-
- bool flow_unreachable = top_level.End ();
- if (flow_unreachable)
- this.unreachable = unreachable = true;
- }
-#if PRODUCTION
- } catch (Exception e) {
- Console.WriteLine ("Exception caught by the compiler while compiling:");
- Console.WriteLine (" Block that caused the problem begin at: " + loc);
-
- if (CurrentBlock != null){
- Console.WriteLine (" Block being compiled: [{0},{1}]",
- CurrentBlock.StartLocation, CurrentBlock.EndLocation);
- }
- Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
- throw;
- }
-#endif
-
- if (return_type != TypeManager.void_type && !unreachable) {
- if (CurrentAnonymousMethod == null) {
- Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
- return false;
- } else if (!CurrentAnonymousMethod.IsIterator) {
- Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
- CurrentAnonymousMethod.GetSignatureForError ());
- return false;
- }
- }
-
- resolved = true;
- return true;
- }
-
public Type ReturnType {
set {
return_type = value;
}
}
- public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
- {
- if (block != null)
- block.Emit (this);
-
- if (HasReturnLabel)
- ig.MarkLabel (ReturnLabel);
-
- if (return_value != null){
- ig.Emit (OpCodes.Ldloc, return_value);
- ig.Emit (OpCodes.Ret);
- } else {
- //
- // If `HasReturnLabel' is set, then we already emitted a
- // jump to the end of the method, so we must emit a `ret'
- // there.
- //
- // Unfortunately, System.Reflection.Emit automatically emits
- // a leave to the end of a finally block. This is a problem
- // if no code is following the try/finally block since we may
- // jump to a point after the end of the method.
- // As a workaround, we're always creating a return label in
- // this case.
- //
-
- if (HasReturnLabel || !unreachable) {
- if (return_type != TypeManager.void_type)
- ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
- ig.Emit (OpCodes.Ret);
- }
- }
- }
-
/// <summary>
/// This is called immediately before emitting an IL opcode to tell the symbol
/// writer to which source line this opcode belongs.
/// </summary>
public void NeedReturnLabel ()
{
- if (current_phase != Phase.Resolving){
+// if (current_phase != Phase.Resolving){
//
// The reason is that the `ReturnLabel' is declared between
// resolution and emission
//
- throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");
- }
+// throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");
+// }
if (!HasReturnLabel)
HasReturnLabel = true;
return my_this;
}
- }
+ #region IResolveContext Members
- public abstract class CommonAssemblyModulClass : Attributable, IResolveContext {
+ public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
+ {
+ return ResolveContext.LookupExtensionMethod (extensionType, name, loc);
+ }
- protected CommonAssemblyModulClass ():
- base (null)
+ public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
{
+ return ResolveContext.LookupNamespaceOrType (name, loc, ignore_cs0104);
}
- public void AddAttributes (ArrayList attrs)
+ public FullNamedExpression LookupNamespaceAlias (string name)
+ {
+ return ResolveContext.LookupNamespaceAlias (name);
+ }
+
+ #endregion
+ }
+
+
+ public abstract class CommonAssemblyModulClass : Attributable, IResolveContext
+ {
+ public void AddAttributes (ArrayList attrs, IResolveContext context)
{
foreach (Attribute a in attrs)
- a.AttachTo (this);
+ a.AttachTo (this, context);
if (attributes == null) {
attributes = new Attributes (attrs);
return a;
}
- public override IResolveContext ResolveContext {
- get { return this; }
+ #region IResolveContext Members
+
+ public Type CurrentType {
+ get { return null; }
}
- #region IResolveContext Members
+ public TypeParameter[] CurrentTypeParameters {
+ get { return null; }
+ }
+
+ public TypeContainer CurrentTypeDefinition {
+ get { throw new InternalErrorException ("No TypeContainer in module context"); }
+ }
public DeclSpace DeclContainer {
get { return RootContext.ToplevelTypes; }
get { return false; }
}
+ public bool IsStatic {
+ get { return false; }
+ }
+
+ public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+ {
+ return RootContext.ToplevelTypes.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ }
+
+ public FullNamedExpression LookupNamespaceAlias (string name)
+ {
+ return null;
+ }
+
#endregion
}
Arguments named = new Arguments (1);
named.Add (new NamedArgument (new LocatedToken (loc, "SkipVerification"), (new BoolLiteral (true, loc))));
- GlobalAttribute g = new GlobalAttribute (new NamespaceEntry (null, null, null), "assembly", system_security_permissions,
- "SecurityPermissionAttribute", new Arguments[] { pos, named }, loc, false);
- g.AttachTo (this);
+ GlobalAttribute g = new GlobalAttribute (new NamespaceEntry (null, null, null), "assembly",
+ new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"),
+ new Arguments[] { pos, named }, loc, false);
+ g.AttachTo (this, this);
if (g.Resolve () != null) {
declarative_security = new ListDictionary ();
case "AssemblyKeyFileAttribute":
case "System.Reflection.AssemblyKeyFileAttribute":
if (RootContext.StrongNameKeyFile != null) {
- Report.SymbolRelatedToPreviousError (a.Location, a.Name);
+ Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
"keyfile", "System.Reflection.AssemblyKeyFileAttribute");
} else {
case "AssemblyKeyNameAttribute":
case "System.Reflection.AssemblyKeyNameAttribute":
if (RootContext.StrongNameKeyContainer != null) {
- Report.SymbolRelatedToPreviousError (a.Location, a.Name);
+ Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
"keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
} else {
ArrayList results = new ArrayList ();
AppendResults (results, Prefix, Evaluator.GetVarNames ());
- AppendResults (results, Prefix, ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, Prefix));
+ AppendResults (results, Prefix, ec.CurrentTypeDefinition.NamespaceEntry.CompletionGetTypesStartingWith (Prefix));
AppendResults (results, Prefix, Evaluator.GetUsingList ());
throw new CompletionResult (Prefix, (string []) results.ToArray (typeof (string)));
CompletionSimpleName.AppendResults (
results,
partial_name,
- ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial));
+ ec.CurrentTypeDefinition.NamespaceEntry.CompletionGetTypesStartingWith (namespaced_partial));
} else {
MemberInfo [] result = expr_type.FindMembers (
MemberTypes.All, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
in_transit = true;
// TODO: IResolveContext here
EmitContext ec = new EmitContext (
- this, Parent, Location, null, MemberType, ModFlags);
- ec.InEnumContext = this is EnumMember;
- ec.IsAnonymousMethodAllowed = false;
- value = DoResolveValue (ec);
+ this, Parent, null, MemberType);
+
+ EmitContext.Options opt = EmitContext.Options.ConstantScope;
+ if (this is EnumMember)
+ opt |= EmitContext.Options.EnumScope;
+
+ using (ec.Set (opt)) {
+ value = DoResolveValue (ec);
+ }
+
in_transit = false;
resolved = true;
return value != null;
// Use string.Empty for both literals and constants even if
// it's not allowed at language level
//
- if (Value.Length == 0 && RootContext.Optimize && ec.TypeContainer.TypeBuilder != TypeManager.string_type) {
+ if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
if (TypeManager.string_empty == null)
TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
if ($1 != null) {
Attributes attrs = (Attributes)$1;
if (global_attrs_enabled) {
- CodeGen.Assembly.AddAttributes (attrs.Attrs);
+ CodeGen.Assembly.AddAttributes (attrs.Attrs, current_namespace);
} else {
foreach (Attribute a in attrs.Attrs) {
Report.Error (1730, a.Location, "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations");
current_container.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target != null && current_attr_target.Length > 0) {
- CodeGen.Assembly.AddAttributes (sect);
+ CodeGen.Assembly.AddAttributes (sect, current_namespace);
$$ = null;
} else {
$$ = new Attributes (sect);
current_container.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target == "assembly") {
- CodeGen.Assembly.AddAttributes (sect);
+ CodeGen.Assembly.AddAttributes (sect, current_namespace);
$$ = null;
} else {
if (attrs == null)
}
Arguments [] arguments = (Arguments []) $3;
- MemberName left = mname.Left;
- string identifier = mname.Name;
-
- Expression left_expr = left == null ? null : left.GetTypeExpression ();
+ ATypeNameExpression expr = mname.GetTypeExpression ();
if (current_attr_target == String.Empty)
$$ = null;
else if (global_attrs_enabled && (current_attr_target == "assembly" || current_attr_target == "module"))
// FIXME: supply "nameEscaped" parameter here.
$$ = new GlobalAttribute (current_namespace, current_attr_target,
- left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
+ expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
else
- $$ = new Attribute (current_attr_target, left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
+ $$ = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
}
;
internal Flags caching_flags;
public MemberCore (DeclSpace parent, MemberName name, Attributes attrs)
- : base (attrs)
{
this.Parent = parent;
member_name = name;
caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
+ AddAttributes (attrs, this);
}
protected virtual void SetMemberName (MemberName new_name)
return true;
}
+ public virtual ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
+ {
+ return Parent.LookupExtensionMethod (extensionType, name, loc);
+ }
+
+ public virtual FullNamedExpression LookupNamespaceAlias (string name)
+ {
+ return Parent.NamespaceEntry.LookupNamespaceAlias (name);
+ }
+
+ public virtual FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+ {
+ return Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ }
+
/// <summary>
/// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
/// If no is attribute exists then assembly CLSCompliantAttribute is returned.
}
}
- public override IResolveContext ResolveContext {
- get { return this; }
+ #region IResolveContext Members
+
+ public virtual Type CurrentType {
+ get { return Parent.CurrentType; }
}
- #region IResolveContext Members
+ public virtual TypeContainer CurrentTypeDefinition {
+ get { return Parent.CurrentTypeDefinition; }
+ }
+
+ public virtual TypeParameter[] CurrentTypeParameters {
+ get { return null; }
+ }
public DeclSpace DeclContainer {
get { return Parent; }
}
}
+ public bool IsStatic {
+ get { return (ModFlags & Modifiers.STATIC) != 0; }
+ }
+
#endregion
}
/// currently defining. We need to lookup members on this
/// instead of the TypeBuilder.
/// </summary>
- public Type CurrentType;
+ protected Type currentType;
//
// This is the namespace in which this typecontainer
if (TypeManager.HasElementType (check_type))
return CheckAccessLevel (TypeManager.GetElementType (check_type));
+ if (TypeManager.IsGenericParameter (check_type))
+ return true;
+
TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask;
switch (check_attr){
return null;
}
- public virtual ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
- {
- return null;
- }
-
//
// Public function used to locate types.
//
//
// Returns: Type or null if they type can not be found.
//
- public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+ public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
{
if (Cache.Contains (name))
return (FullNamedExpression) Cache [name];
- FullNamedExpression e;
+ FullNamedExpression e = null;
int errors = Report.Errors;
- Type t = LookupNestedTypeInHierarchy (name);
- if (t != null)
- e = new TypeExpression (t, Location.Null);
- else if (Parent != null)
- e = Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
- else
- e = NamespaceEntry.LookupNamespaceOrType (this, name, loc, ignore_cs0104);
+
+ TypeParameter[] tp = CurrentTypeParameters;
+ if (tp != null) {
+ TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name);
+ if (tparam != null)
+ e = new TypeParameterExpr (tparam, Location.Null);
+ }
+
+ if (e == null) {
+ Type t = LookupNestedTypeInHierarchy (name);
+
+ if (t != null)
+ e = new TypeExpression (t, Location.Null);
+ else if (Parent != null)
+ e = Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ else
+ e = NamespaceEntry.LookupNamespaceOrType (name, loc, ignore_cs0104);
+ }
if (errors == Report.Errors)
Cache [name] = e;
ArrayList list = new ArrayList ();
if (the_parent != null && the_parent.IsGeneric) {
// FIXME: move generics info out of DeclSpace
- TypeParameter[] parent_params = the_parent.PartialContainer.TypeParameters;
+ TypeParameter[] parent_params = the_parent.TypeParameters;
list.AddRange (parent_params);
}
for (int i = 0; i < count; i++) {
TypeParameter param = type_params [i];
list.Add (param);
- if (Parent.IsGeneric) {
- foreach (TypeParameter tp in Parent.PartialContainer.CurrentTypeParameters) {
+ if (Parent.CurrentTypeParameters != null) {
+ foreach (TypeParameter tp in Parent.CurrentTypeParameters) {
if (tp.Name != param.Name)
continue;
}
}
- public TypeParameter[] CurrentTypeParameters {
- get {
- if (!IsGeneric)
- throw new InvalidOperationException ();
-
- // TODO: Something is seriously broken here
- if (type_params == null)
- return new TypeParameter [0];
+ public override Type CurrentType {
+ get { return currentType != null ? currentType : TypeBuilder; }
+ }
- return type_params;
- }
+ public override TypeContainer CurrentTypeDefinition {
+ get { return PartialContainer; }
}
public int CountTypeParameters {
}
}
- public TypeParameterExpr LookupGeneric (string name, Location loc)
- {
- if (!IsGeneric)
- return null;
-
- TypeParameter [] current_params;
- if (this is TypeContainer)
- current_params = PartialContainer.CurrentTypeParameters;
- else
- current_params = CurrentTypeParameters;
-
- foreach (TypeParameter type_param in current_params) {
- if (type_param.Name == name)
- return new TypeParameterExpr (type_param, loc);
- }
-
- if (Parent != null)
- return Parent.LookupGeneric (name, loc);
-
- return null;
- }
-
// Used for error reporting only
public virtual Type LookupAnyGeneric (string typeName)
{
base.ApplyAttributeBuilder (a, cb, pa);
}
+ public override TypeParameter[] CurrentTypeParameters {
+ get {
+ return base.type_params;
+ }
+ }
+
public override TypeBuilder DefineType ()
{
if (TypeBuilder != null)
GenericTypeParameterBuilder[] gen_params;
gen_params = TypeBuilder.DefineGenericParameters (param_names);
- int offset = CountTypeParameters - CurrentTypeParameters.Length;
+ int offset = CountTypeParameters;
+ if (CurrentTypeParameters != null)
+ offset -= CurrentTypeParameters.Length;
for (int i = offset; i < gen_params.Length; i++)
CurrentTypeParameters [i - offset].Define (gen_params [i]);
- foreach (TypeParameter type_param in CurrentTypeParameters) {
- if (!type_param.Resolve (this))
- return null;
+ if (CurrentTypeParameters != null) {
+ foreach (TypeParameter type_param in CurrentTypeParameters) {
+ if (!type_param.Resolve (this))
+ return null;
+ }
}
Expression current = new SimpleName (
if (current == null)
return null;
- CurrentType = current.Type;
+ currentType = current.Type;
}
#endif
else
arg_count = args.Count;
- MethodBase mb = GetInvokeMethod (ec.ContainerType, delegate_type);
+ MethodBase mb = GetInvokeMethod (ec.CurrentType, delegate_type);
MethodGroupExpr me = new MethodGroupExpr (new MemberInfo [] { mb }, delegate_type, loc);
AParametersCollection pd = TypeManager.GetParameterData (mb);
public override Expression DoResolve (EmitContext ec)
{
- constructor_method = Delegate.GetConstructor (ec.ContainerType, type);
+ constructor_method = Delegate.GetConstructor (ec.CurrentType, type);
- MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type);
+ MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.CurrentType, type);
method_group.DelegateType = type;
method_group.CustomErrorHandler = this;
void Error_ConversionFailed (EmitContext ec, MethodBase method, Expression return_type)
{
- MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type);
+ MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.CurrentType, type);
string member_name = delegate_instance_expression != null ?
Delegate.FullDelegateDesc (method) :
TypeManager.GetFullNameSignature (method);
//
delegate_instance_expression = e;
method_group = new MethodGroupExpr (new MemberInfo [] {
- Delegate.GetInvokeMethod (ec.ContainerType, e.Type) }, e.Type, loc);
+ Delegate.GetInvokeMethod (ec.CurrentType, e.Type) }, e.Type, loc);
}
return base.DoResolve (ec);
if (!Delegate.VerifyApplicability (ec, del_type, ref Arguments, loc))
return null;
- method = Delegate.GetInvokeMethod (ec.ContainerType, del_type);
+ method = Delegate.GetInvokeMethod (ec.CurrentType, del_type);
type = TypeManager.TypeToCoreType (method.ReturnType);
eclass = ExprClass.Value;
MemberAccess binder = GetBinderNamespace (loc);
binder_args.Add (new Argument (new StringLiteral (name, loc)));
- binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.ContainerType, loc), loc)));
+ binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
return new New (new MemberAccess (binder, "CSharpIsEventBinder", loc), binder_args, loc);
}
binder_args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
binder_args.Add (new Argument (new MemberAccess (new MemberAccess (binder, "CSharpConversionKind", loc),
is_explicit ? "ExplicitConversion" : "ImplicitConversion", loc)));
- binder_args.Add (new Argument (new BoolLiteral (ec.CheckState, loc)));
+ binder_args.Add (new Argument (new BoolLiteral (ec.HasSet (EmitContext.Options.CheckedScope), loc)));
return new New (new MemberAccess (binder, "CSharpConvertBinder", loc), binder_args, loc);
}
Arguments binder_args = new Arguments (2);
MemberAccess binder = GetBinderNamespace (loc);
- binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.ContainerType, loc), loc)));
+ binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (), loc)));
return new New (new MemberAccess (binder, isSet ? "CSharpSetIndexBinder" : "CSharpGetIndexBinder", loc), binder_args, loc);
if (is_member_access)
binder_args.Add (new Argument (new StringLiteral (member.Name, member.Location)));
- binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.ContainerType, loc), loc)));
+ binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
if (member != null && member.HasTypeArguments) {
TypeArguments ta = member.TypeArguments;
MemberAccess binder = GetBinderNamespace (loc);
binder_args.Add (new Argument (new StringLiteral (name, loc)));
- binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.ContainerType, loc), loc)));
+ binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (), loc)));
return new New (new MemberAccess (binder, isSet ? "CSharpSetMemberBinder" : "CSharpGetMemberBinder", loc), binder_args, loc);
MemberAccess binder = GetBinderNamespace (loc);
binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc)));
- binder_args.Add (new Argument (new BoolLiteral (ec.CheckState, loc)));
+ binder_args.Add (new Argument (new BoolLiteral (ec.HasSet (EmitContext.Options.CheckedScope), loc)));
binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (), loc)));
return new New (new MemberAccess (binder, "CSharpUnaryOperationBinder", loc), binder_args, loc);
GenericTypeExpr ct = te as GenericTypeExpr;
if (ct != null) {
- // Skip constrains check for overrides and explicit implementations
- // TODO: they should use different overload
- GenericMethod gm = ec.GenericDeclContainer as GenericMethod;
+ //
+ // TODO: Constrained type parameters check for parameters of generic method overrides is broken
+ // There are 2 solutions.
+ // 1, Skip this check completely when we are in override/explicit impl scope
+ // 2, Copy type parameters constraints from base implementation and pass (they have to be emitted anyway)
+ //
+ MemberCore gm = ec as GenericMethod;
+ if (gm == null)
+ gm = ec as Method;
if (gm != null && ((gm.ModFlags & Modifiers.OVERRIDE) != 0 || gm.MemberName.Left != null)) {
te.loc = loc;
return te;
Expression e;
int errors = Report.Errors;
- e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
+ e = MemberLookup (ec.CurrentType, qualifier_type, queried_type, name, mt, bf, loc);
if (e != null || errors != Report.Errors)
return e;
// No errors were reported by MemberLookup, but there was an error.
- return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type,
+ return Error_MemberLookupFailed (ec.CurrentType, qualifier_type, queried_type,
name, null, mt, bf);
}
// Although a derived class can access protected members of
// its base class it cannot do so through an instance of the
// base class (CS1540). If the qualifier_type is a base of the
- // ec.ContainerType and the lookup succeeds with the latter one,
+ // ec.CurrentType and the lookup succeeds with the latter one,
// then we are in this situation.
Error_CannotAccessProtected (loc, mi, qualifier_type, container_type);
} else {
{
MethodGroupExpr operator_group;
string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
- operator_group = MethodLookup (ec.ContainerType, e.Type, mname, loc) as MethodGroupExpr;
+ operator_group = MethodLookup (ec.CurrentType, e.Type, mname, loc) as MethodGroupExpr;
if (operator_group == null)
return null;
/// <summary>
/// Reports that we were expecting `expr' to be of class `expected'
/// </summary>
- public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
+ public void Error_UnexpectedKind (MemberCore mc, string expected, Location loc)
{
- Error_UnexpectedKind (ds, expected, ExprClassName, loc);
+ Error_UnexpectedKind (mc, expected, ExprClassName, loc);
}
- public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
+ public void Error_UnexpectedKind (MemberCore mc, string expected, string was, Location loc)
{
- string name = GetSignatureForError ();
- if (ds != null)
- name = ds.GetSignatureForError () + '.' + name;
+ string name;
+ if (mc != null)
+ name = mc.GetSignatureForError ();
+ else
+ name = GetSignatureForError ();
Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
name, was, expected);
Expression converted;
- using (ec.With (EmitContext.Flags.CheckState, true)) {
+ using (ec.Set (EmitContext.Options.CheckedScope)) {
converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc);
if (converted == null)
converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc);
if (type.IsPointer || child.Type.IsPointer)
Error_PointerInsideExpressionTree ();
- return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
+ return CreateExpressionFactoryCall (ec.HasSet (EmitContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
}
public override Expression DoResolve (EmitContext ec)
base.Emit (ec);
- if (ec.CheckState){
+ if (ec.HasSet (EmitContext.Options.CheckedScope)){
switch (mode){
case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
//
public abstract class ATypeNameExpression : FullNamedExpression
{
- public readonly string Name;
+ string name;
protected TypeArguments targs;
protected ATypeNameExpression (string name, Location l)
{
- Name = name;
+ this.name = name;
loc = l;
}
protected ATypeNameExpression (string name, TypeArguments targs, Location l)
{
- Name = name;
+ this.name = name;
this.targs = targs;
loc = l;
}
return Name;
}
+ public string Name {
+ get {
+ return name;
+ }
+ set {
+ name = value;
+ }
+ }
+
public TypeArguments TypeArguments {
get {
return targs;
public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
{
- if (ec.IsInFieldInitializer)
+ if (ec.HasSet (EmitContext.Options.FieldInitializerScope))
Report.Error (236, l,
"A field initializer cannot reference the nonstatic field, method, or property `{0}'",
name);
name);
}
- public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
+ public bool IdenticalNameAndTypeName (IResolveContext mc, Expression resolved_to, Location loc)
{
return resolved_to != null && resolved_to.Type != null &&
resolved_to.Type.Name == Name &&
- (ec.DeclContainer.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
+ (mc.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
}
public override Expression DoResolve (EmitContext ec)
if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
return null;
- DeclSpace ds = ec.DeclContainer;
+ if (ec.CurrentType == null)
+ return null;
+
+ DeclSpace ds = ec.CurrentTypeDefinition;
while (ds != null && !IsNestedChild (t, ds.TypeBuilder))
ds = ds.Parent;
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
- FullNamedExpression fne = ec.GenericDeclContainer.LookupGeneric (Name, loc);
- if (fne != null)
- return fne.ResolveAsTypeStep (ec, silent);
-
int errors = Report.Errors;
- fne = ec.DeclContainer.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
+ FullNamedExpression fne = ec.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
if (fne != null) {
if (fne.Type == null)
protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec)
{
- MemberCore mc = ec.DeclContainer.GetDefinition (Name);
- if (mc != null) {
- Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
- return;
- }
+ if (ec.CurrentType != null) {
+ if (ec.CurrentTypeDefinition != null) {
+ MemberCore mc = ec.CurrentTypeDefinition.GetDefinition (Name);
+ if (mc != null) {
+ Error_UnexpectedKind (mc, "type", GetMemberType (mc), loc);
+ return;
+ }
+ }
- string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
- string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
- foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
- Type type = a.GetType (fullname);
- if (type != null) {
- Report.SymbolRelatedToPreviousError (type);
- Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type));
- return;
+ string ns = ec.CurrentType.Namespace;
+ string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
+ foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
+ Type type = a.GetType (fullname);
+ if (type != null) {
+ Report.SymbolRelatedToPreviousError (type);
+ Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type));
+ return;
+ }
}
- }
- Type t = ec.DeclContainer.LookupAnyGeneric (Name);
- if (t != null) {
- Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
- return;
+ if (ec.CurrentTypeDefinition != null) {
+ Type t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
+ if (t != null) {
+ Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
+ return;
+ }
+ }
}
if (targs != null) {
- FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
+ FullNamedExpression retval = ec.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
if (retval != null) {
Namespace.Error_TypeArgumentsCannotBeUsed (retval, loc);
return;
Type almost_matched_type = null;
ArrayList almost_matched = null;
- for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) {
- // either RootDeclSpace or GenericMethod
- if (lookup_ds.TypeBuilder == null)
- continue;
-
- e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
+ for (Type lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) {
+ e = MemberLookup (ec.CurrentType, lookup_ds, Name, loc);
if (e != null) {
PropertyExpr pe = e as PropertyExpr;
if (pe != null) {
// since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
// it doesn't know which accessor to check permissions against
- if (param.IsEmpty && pe.IsAccessibleFrom (ec.ContainerType, right_side != null))
+ if (param.IsEmpty && pe.IsAccessibleFrom (ec.CurrentType, right_side != null))
break;
} else if (e is EventExpr) {
- if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType))
+ if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType))
break;
} else if (targs != null && e is TypeExpression) {
e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false);
}
if (almost_matched == null && almost_matched_members.Count > 0) {
- almost_matched_type = lookup_ds.TypeBuilder;
+ almost_matched_type = lookup_ds;
almost_matched = (ArrayList) almost_matched_members.Clone ();
}
}
if (e == null) {
if (almost_matched == null && almost_matched_members.Count > 0) {
- almost_matched_type = ec.ContainerType;
+ almost_matched_type = ec.CurrentType;
almost_matched = (ArrayList) almost_matched_members.Clone ();
}
e = ResolveAsTypeStep (ec, true);
if (almost_matched != null)
almost_matched_members = almost_matched;
if (almost_matched_type == null)
- almost_matched_type = ec.ContainerType;
- return Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name,
- ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags);
+ almost_matched_type = ec.CurrentType;
+
+ string type_name = ec.ResolveContext.CurrentType == null ? null : ec.ResolveContext.CurrentType.Name;
+ return Error_MemberLookupFailed (ec.CurrentType, null, almost_matched_type, Name,
+ type_name, AllMemberTypes, AllBindingFlags);
}
if (e is MemberExpr) {
Expression left;
if (me.IsInstance) {
- if (ec.IsStatic || ec.IsInFieldInitializer) {
+ if (ec.IsStatic || ec.HasAny (EmitContext.Options.FieldInitializerScope | EmitContext.Options.BaseInitializer | EmitContext.Options.ConstantScope)) {
//
// Note that an MemberExpr can be both IsInstance and IsStatic.
// An unresolved MethodGroupExpr can contain both kinds of methods
left = ec.GetThis (loc);
}
} else {
- left = new TypeExpression (ec.ContainerType, loc);
+ left = new TypeExpression (ec.CurrentType, loc);
}
me = me.ResolveMemberAccess (ec, left, loc, null);
//
if (type == null) {
Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, false);
- FullNamedExpression fne = ns.Lookup (null, name, loc);
+ FullNamedExpression fne = ns.Lookup (name, loc);
if (fne != null)
type = fne.Type;
}
return null;
// Search continues
- ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name, loc);
+ ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, loc);
if (e == null)
return base.OverloadResolve (ec, ref arguments, false, loc);
// not an extension method. We start extension methods lookup from here
//
if (InstanceExpression != null) {
- ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name, loc);
+ ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
if (ex_method_lookup != null) {
ex_method_lookup.ExtensionExpression = InstanceExpression;
ex_method_lookup.SetTypeArguments (type_arguments);
}
if (has_inaccessible_candidates_only) {
- if (InstanceExpression != null && type != ec.ContainerType && TypeManager.IsNestedFamilyAccessible (ec.ContainerType, best_candidate.DeclaringType)) {
+ if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
// Although a derived class can access protected members of
// its base class it cannot do so through an instance of the
// base class (CS1540). If the qualifier_type is a base of the
- // ec.ContainerType and the lookup succeeds with the latter one,
+ // ec.CurrentType and the lookup succeeds with the latter one,
// then we are in this situation.
- Error_CannotAccessProtected (loc, best_candidate, queried_type, ec.ContainerType);
+ Error_CannotAccessProtected (loc, best_candidate, queried_type, ec.CurrentType);
} else {
Report.SymbolRelatedToPreviousError (best_candidate);
ErrorIsInaccesible (loc, GetSignatureForError ());
// "a.b" is initialized, not whether the whole struct "a" is initialized.
if (lvalue_instance) {
- using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) {
+ using (ec.With (EmitContext.Options.DoFlowAnalysis, false)) {
Expression right_side =
out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
if (InstanceExpression == null)
return null;
- using (ec.Set (EmitContext.Flags.OmitStructFlowAnalysis)) {
+ using (ec.Set (EmitContext.Options.OmitStructFlowAnalysis)) {
InstanceExpression.CheckMarshalByRefAccess (ec);
}
}
if (fb != null) {
IFixedExpression fe = InstanceExpression as IFixedExpression;
- if (!ec.InFixedInitializer && (fe == null || !fe.IsFixed)) {
+ if (!ec.HasSet (EmitContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
}
if (FieldInfo.IsInitOnly) {
// InitOnly fields can only be assigned in constructors or initializers
- if (!ec.IsInFieldInitializer && !ec.IsConstructor)
+ if (!ec.HasAny (EmitContext.Options.FieldInitializerScope | EmitContext.Options.ConstructorScope))
return Report_AssignToReadonly (right_side);
- if (ec.IsConstructor) {
- Type ctype = ec.TypeContainer.CurrentType;
- if (ctype == null)
- ctype = ec.ContainerType;
+ if (ec.HasSet (EmitContext.Options.ConstructorScope)) {
+ Type ctype = ec.CurrentType;
// InitOnly fields cannot be assigned-to in a different constructor from their declaring type
if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
// Optimization for build-in types
// TODO: Iterators don't set current container
- if (TypeManager.IsStruct (type) && type == ec.DeclContainer.TypeBuilder && ec.CurrentIterator == null) {
+ if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.ResolveContext.CurrentType) && ec.CurrentIterator == null) {
LoadFromPtr (ig, type);
} else {
IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
ILGenerator ig = ec.ig;
- if (is_readonly && !ec.IsConstructor){
+ if (is_readonly && !ec.HasSet (EmitContext.Options.ConstructorScope)){
Report_AssignToReadonly (source);
return;
}
bool need_copy;
if (FieldInfo.IsInitOnly){
need_copy = true;
- if (ec.IsConstructor){
+ if (ec.HasSet (EmitContext.Options.ConstructorScope)){
if (FieldInfo.IsStatic){
if (ec.IsStatic)
need_copy = false;
InstanceExpression.CheckMarshalByRefAccess (ec);
if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
- !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) &&
- !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) &&
- !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) {
+ !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
+ !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
+ !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
Report.SymbolRelatedToPreviousError (PropertyInfo);
- Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
+ Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.CurrentType);
return false;
}
bool must_do_cs1540_check = false;
if (getter != null &&
- !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
+ !IsAccessorAccessible (ec.CurrentType, getter, out must_do_cs1540_check)) {
PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
if (pm != null && pm.HasCustomAccessModifier) {
Report.SymbolRelatedToPreviousError (pm);
}
bool must_do_cs1540_check;
- if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
+ if (!IsAccessorAccessible (ec.CurrentType, setter, out must_do_cs1540_check)) {
PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
if (pm != null && pm.HasCustomAccessModifier) {
Report.SymbolRelatedToPreviousError (pm);
// If the event is local to this class, we transform ourselves into a FieldExpr
//
- if (EventInfo.DeclaringType == ec.ContainerType ||
- TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
+ if (EventInfo.DeclaringType == ec.CurrentType ||
+ TypeManager.IsNestedChildOf(ec.CurrentType, EventInfo.DeclaringType)) {
EventField mi = TypeManager.GetEventField (EventInfo);
if (mi != null) {
if (!ec.IsInObsoleteScope)
mi.CheckObsoleteness (loc);
- if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.IsInCompoundAssignment)
+ if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (EmitContext.Options.CompoundAssignmentScope))
Error_AssignmentEventOnly ();
FieldExpr ml = new FieldExpr (mi.BackingField.FieldBuilder, loc);
return ml.ResolveMemberAccess (ec, left, loc, original);
}
}
-
- if (left is This && !ec.IsInCompoundAssignment)
+
+ if (left is This && !ec.HasSet (EmitContext.Options.CompoundAssignmentScope))
Error_AssignmentEventOnly ();
return base.ResolveMemberAccess (ec, left, loc, original);
// TODO: Exact copy from PropertyExpr
//
if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
- !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) &&
- !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) &&
- !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) {
+ !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
+ !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
+ !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
Report.SymbolRelatedToPreviousError (EventInfo);
ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
return false;
public override Expression DoResolve (EmitContext ec)
{
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))) {
+ if (!(IsAccessorAccessible (ec.CurrentType, add_accessor, out must_do_cs1540_check) &&
+ IsAccessorAccessible (ec.CurrentType, remove_accessor, out must_do_cs1540_check))) {
Report.SymbolRelatedToPreviousError (EventInfo);
ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
return null;
if (!InstanceResolve (ec, must_do_cs1540_check))
return null;
- if (!ec.IsInCompoundAssignment) {
+ if (!ec.HasSet (EmitContext.Options.CompoundAssignmentScope)) {
Error_CannotAssign ();
return null;
}
if (method == null)
throw new InternalErrorException ("did not find the the Host method");
- EmitContext ec = method.CreateEmitContext (method.Parent, null);
- bool unreach;
+ EmitContext ec = method.CreateEmitContext (null);
try {
- ec.ResolveTopBlock (null, method.Block, method.ParameterInfo, method, out unreach);
+ method.Block.Resolve (null, ec, method.ParameterInfo, method);
} catch (CompletionResult cr){
prefix = cr.BaseText;
return cr.Result;
Error_PointerInsideExpressionTree ();
return null;
case Operator.UnaryNegation:
- if (ec.CheckState && user_op == null && !IsFloat (type))
+ if (ec.HasSet (EmitContext.Options.CheckedScope) && user_op == null && !IsFloat (type))
method_name = "NegateChecked";
else
method_name = "Negate";
break;
case Operator.UnaryNegation:
- if (ec.CheckState && !IsFloat (type)) {
+ if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) {
ig.Emit (OpCodes.Ldc_I4_0);
if (type == TypeManager.int64_type)
ig.Emit (OpCodes.Conv_U8);
is_fixed = fe != null && fe.IsFixed;
}
- if (!is_fixed && !ec.InFixedInitializer) {
+ if (!is_fixed && !ec.HasSet (EmitContext.Options.FixedInitializerScope)) {
Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
}
}
string op_name = CSharp.Operator.GetMetadataName (op_type);
- MethodGroupExpr user_op = MemberLookup (ec.ContainerType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
+ MethodGroupExpr user_op = MemberLookup (ec.CurrentType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
if (user_op == null)
return null;
else
op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
- mg = MemberLookup (ec.ContainerType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+ mg = MemberLookup (ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
if (mg != null) {
Arguments args = new Arguments (1);
Binary.EmitOperatorOpcode (ec, op, t);
if (t == TypeManager.sbyte_type){
- if (ec.CheckState)
+ if (ec.HasSet (EmitContext.Options.CheckedScope))
ig.Emit (OpCodes.Conv_Ovf_I1);
else
ig.Emit (OpCodes.Conv_I1);
} else if (t == TypeManager.byte_type){
- if (ec.CheckState)
+ if (ec.HasSet (EmitContext.Options.CheckedScope))
ig.Emit (OpCodes.Conv_Ovf_U1);
else
ig.Emit (OpCodes.Conv_U1);
} else if (t == TypeManager.short_type){
- if (ec.CheckState)
+ if (ec.HasSet (EmitContext.Options.CheckedScope))
ig.Emit (OpCodes.Conv_Ovf_I2);
else
ig.Emit (OpCodes.Conv_I2);
} else if (t == TypeManager.ushort_type || t == TypeManager.char_type){
- if (ec.CheckState)
+ if (ec.HasSet (EmitContext.Options.CheckedScope))
ig.Emit (OpCodes.Conv_Ovf_U2);
else
ig.Emit (OpCodes.Conv_U2);
Type etype = expr.Type;
if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
- if (probe_type_expr is TypeParameterExpr) {
+ if (TypeManager.IsGenericParameter (type)) {
Report.Error (413, loc,
"The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint",
probe_type_expr.GetSignatureForError ());
//
// Start a new concat expression using converted expression
//
- return new StringConcat (ec, b.loc, b.left, b.right).Resolve (ec);
+ return new StringConcat (b.loc, b.left, b.right).Resolve (ec);
}
}
switch (oper){
case Operator.Multiply:
- if (ec.CheckState){
+ if (ec.HasSet (EmitContext.Options.CheckedScope)){
if (l == TypeManager.int32_type || l == TypeManager.int64_type)
opcode = OpCodes.Mul_Ovf;
else if (!IsFloat (l))
break;
case Operator.Addition:
- if (ec.CheckState){
+ if (ec.HasSet (EmitContext.Options.CheckedScope)){
if (l == TypeManager.int32_type || l == TypeManager.int64_type)
opcode = OpCodes.Add_Ovf;
else if (!IsFloat (l))
break;
case Operator.Subtraction:
- if (ec.CheckState){
+ if (ec.HasSet (EmitContext.Options.CheckedScope)){
if (l == TypeManager.int32_type || l == TypeManager.int64_type)
opcode = OpCodes.Sub_Ovf;
else if (!IsFloat (l))
Constant rc = right as Constant;
// The conversion rules are ignored in enum context but why
- if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
+ if (!ec.HasSet (EmitContext.Options.EnumScope) && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
lc = EnumLiftUp (ec, lc, rc, loc);
if (lc != null)
rc = EnumLiftUp (ec, rc, lc, loc);
string op = GetOperatorMetadataName (user_oper);
- MethodGroupExpr left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+ MethodGroupExpr left_operators = MemberLookup (ec.CurrentType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
MethodGroupExpr right_operators = null;
if (!TypeManager.IsEqual (r, l)) {
- right_operators = MemberLookup (ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+ right_operators = MemberLookup (ec.CurrentType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
if (right_operators == null && left_operators == null)
return null;
} else if (left_operators == null) {
public override void EmitSideEffect (EmitContext ec)
{
if ((oper & Operator.LogicalMask) != 0 ||
- (ec.CheckState && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) {
+ (ec.HasSet (EmitContext.Options.CheckedScope) && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) {
base.EmitSideEffect (ec);
} else {
left.EmitSideEffect (ec);
MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc);
binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
- binder_args.Add (new Argument (new BoolLiteral (ec.CheckState, loc)));
+ binder_args.Add (new Argument (new BoolLiteral (ec.HasSet (EmitContext.Options.CheckedScope), loc)));
bool member_access = left is DynamicMemberBinder || right is DynamicMemberBinder;
binder_args.Add (new Argument (new BoolLiteral (member_access, loc)));
switch (oper) {
case Operator.Addition:
- if (method == null && ec.CheckState && !IsFloat (type))
+ if (method == null && ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type))
method_name = "AddChecked";
else
method_name = "Add";
method_name = "Modulo";
break;
case Operator.Multiply:
- if (method == null && ec.CheckState && !IsFloat (type))
+ if (method == null && ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type))
method_name = "MultiplyChecked";
else
method_name = "Multiply";
method_name = "RightShift";
break;
case Operator.Subtraction:
- if (method == null && ec.CheckState && !IsFloat (type))
+ if (method == null && ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type))
method_name = "SubtractChecked";
else
method_name = "Subtract";
public class StringConcat : Expression {
Arguments arguments;
- public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+ public StringConcat (Location loc, Expression left, Expression right)
{
this.loc = loc;
type = TypeManager.string_type;
eclass = ExprClass.Value;
arguments = new Arguments (2);
- Append (ec, left);
- Append (ec, right);
+ Append (left);
+ Append (right);
}
public override Expression CreateExpressionTree (EmitContext ec)
return this;
}
- public void Append (EmitContext ec, Expression operand)
+ public void Append (Expression operand)
{
//
// Constant folding
return null;
}
- mg = ec.TypeContainer.LookupExtensionMethod (me.Type, me.Name, loc);
+ mg = ec.LookupExtensionMethod (me.Type, me.Name, loc);
if (mg == null) {
Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
expr_resolved.GetSignatureForError ());
method = ml as MethodGroupExpr;
if (method == null) {
- ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
+ ml.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
return null;
}
{
eclass = ExprClass.Variable;
if (type == null)
- type = ec.ContainerType;
+ type = ec.CurrentType;
return this;
}
public static bool IsThisAvailable (EmitContext ec)
{
- if (ec.IsStatic || ec.IsInFieldInitializer)
+ if (ec.IsStatic || ec.HasAny (EmitContext.Options.FieldInitializerScope | EmitContext.Options.BaseInitializer | EmitContext.Options.ConstantScope))
return false;
if (ec.CurrentAnonymousMethod == null)
return true;
- if (ec.TypeContainer is Struct && ec.CurrentIterator == null)
+ if (ec.CurrentType.IsValueType && ec.CurrentIterator == null)
return false;
return true;
return true;
eclass = ExprClass.Variable;
-
- if (ec.TypeContainer.CurrentType != null)
- type = ec.TypeContainer.CurrentType;
- else
- type = ec.ContainerType;
+ type = ec.CurrentType;
if (!IsThisAvailable (ec)) {
- if (ec.IsStatic) {
+ if (ec.IsStatic && !ec.HasSet (EmitContext.Options.ConstantScope)) {
Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer");
- } else {
+ } else if (ec.CurrentAnonymousMethod != null) {
Report.Error (1673, loc,
"Anonymous methods inside structs cannot access instance members of `this'. " +
"Consider copying `this' to a local variable outside the anonymous method and using the local instead");
+ } else {
+ Error (27, "Keyword `this' is not available in the current context");
}
}
- is_struct = ec.TypeContainer is Struct;
+ is_struct = type.IsValueType;
if (block != null) {
if (block.Toplevel.ThisVariable != null)
public override Expression DoResolve (EmitContext ec)
{
- if (!ResolveBase (ec))
- return null;
-
-
- if (ec.IsInFieldInitializer) {
- Error (27, "Keyword `this' is not available in the current context");
- return null;
- }
-
+ ResolveBase (ec);
return this;
}
if (variable_info != null)
variable_info.SetAssigned (ec);
- if (ec.TypeContainer is Class){
+ if (ec.CurrentType.IsClass){
if (right_side == EmptyExpression.UnaryAddress)
Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
else if (right_side == EmptyExpression.OutAccess)
eclass = ExprClass.Variable;
type = TypeManager.runtime_argument_handle_type;
- if (ec.IsInFieldInitializer || !ec.CurrentBlock.Toplevel.Parameters.HasArglist)
- {
+ if (ec.HasSet (EmitContext.Options.FieldInitializerScope) || !ec.CurrentBlock.Toplevel.Parameters.HasArglist) {
Error (190, "The __arglist construct is valid only within " +
"a variable argument method");
- return this;
}
return this;
}
int errors = Report.Errors;
- expr = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
+ expr = ec.LookupNamespaceAlias (alias);
if (expr == null) {
if (errors == Report.Errors)
Report.Error (432, loc, "Alias `{0}' not found", alias);
Namespace ns = expr_resolved as Namespace;
if (ns != null) {
- FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc);
+ FullNamedExpression retval = ns.Lookup (LookupIdentifier, loc);
if (retval == null)
- ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, LookupIdentifier);
+ ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier);
else if (targs != null)
retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false);
Expression member_lookup;
member_lookup = MemberLookup (
- ec.ContainerType, expr_type, expr_type, Name, loc);
+ ec.CurrentType, expr_type, expr_type, Name, loc);
if (member_lookup == null && targs != null) {
member_lookup = MemberLookup (
- ec.ContainerType, expr_type, expr_type, LookupIdentifier, loc);
+ ec.CurrentType, expr_type, expr_type, LookupIdentifier, loc);
}
if (member_lookup == null) {
if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable ||
expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess ||
expr_eclass == ExprClass.EventAccess) {
- ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (expr_type, Name, loc);
+ ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc);
if (ex_method_lookup != null) {
ex_method_lookup.ExtensionExpression = expr_resolved;
expr = expr_resolved;
member_lookup = Error_MemberLookupFailed (
- ec.ContainerType, expr_type, expr_type, Name, null,
+ ec.CurrentType, expr_type, expr_type, Name, null,
AllMemberTypes, AllBindingFlags);
if (member_lookup == null)
return null;
return null;
}
- if (!texpr.CheckAccessLevel (ec.DeclContainer)) {
+ if (!texpr.CheckAccessLevel (ec.GenericDeclContainer)) {
Report.SymbolRelatedToPreviousError (member_lookup.Type);
ErrorIsInaccesible (loc, TypeManager.CSharpName (member_lookup.Type));
return null;
Namespace ns = expr_resolved as Namespace;
if (ns != null) {
- FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc);
+ FullNamedExpression retval = ns.Lookup (LookupIdentifier, loc);
if (retval == null && !silent)
- ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier);
+ ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier);
else if (targs != null)
retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent);
if (tnew_expr == null)
return null;
- if (tnew_expr is TypeParameterExpr) {
+ Type expr_type = tnew_expr.Type;
+ if (TypeManager.IsGenericParameter (expr_type)) {
Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'",
tnew_expr.GetSignatureForError ());
return null;
}
- Type expr_type = tnew_expr.Type;
Expression member_lookup = MemberLookup (
- rc.DeclContainer.TypeBuilder, expr_type, expr_type, LookupIdentifier,
+ rc.CurrentType, expr_type, expr_type, LookupIdentifier,
MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
if (member_lookup == null) {
if (silent)
protected virtual void Error_IdentifierNotFound (IResolveContext rc, FullNamedExpression expr_type, string identifier)
{
Expression member_lookup = MemberLookup (
- rc.DeclContainer.TypeBuilder, expr_type.Type, expr_type.Type, SimpleName.RemoveGenericArity (identifier),
+ rc.CurrentType, expr_type.Type, expr_type.Type, SimpleName.RemoveGenericArity (identifier),
MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
if (member_lookup != null) {
}
member_lookup = MemberLookup (
- rc.DeclContainer.TypeBuilder, expr_type.Type, expr_type.Type, identifier,
+ rc.CurrentType, expr_type.Type, expr_type.Type, identifier,
MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc);
if (member_lookup == null) {
public override Expression CreateExpressionTree (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
return Expr.CreateExpressionTree (ec);
}
public override Expression DoResolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
Expr = Expr.Resolve (ec);
if (Expr == null)
public override void Emit (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
Expr.Emit (ec);
}
public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
Expr.EmitBranchable (ec, target, on_true);
}
public override Expression CreateExpressionTree (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
return Expr.CreateExpressionTree (ec);
}
public override Expression DoResolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
Expr = Expr.Resolve (ec);
if (Expr == null)
public override void Emit (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
Expr.Emit (ec);
}
public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
Expr.EmitBranchable (ec, target, on_true);
}
protected virtual void CommonResolve (EmitContext ec)
{
indexer_type = instance_expr.Type;
- current_type = ec.ContainerType;
+ current_type = ec.CurrentType;
}
public override Expression DoResolve (EmitContext ec)
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
if (right_side == EmptyExpression.OutAccess) {
- Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
- GetSignatureForError ());
+ Report.Error (206, loc,
+ "A property or indexer may not be passed as an out or ref parameter");
return null;
}
}
bool must_do_cs1540_check;
- if (!IsAccessorAccessible (ec.ContainerType, accessor, out must_do_cs1540_check)) {
+ if (!IsAccessorAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) {
if (set == null)
set = pi.GetSetMethod (true);
else
Expression CommonResolve (EmitContext ec)
{
Expression member_lookup;
- Type current_type = ec.ContainerType;
+ Type current_type = ec.CurrentType;
Type base_type = current_type.BaseType;
if (!This.IsThisAvailable (ec)) {
return null;
}
- member_lookup = MemberLookup (ec.ContainerType, null, base_type, Identifier,
+ member_lookup = MemberLookup (ec.CurrentType, null, base_type, Identifier,
AllMemberTypes, AllBindingFlags, loc);
if (member_lookup == null) {
- Error_MemberLookupFailed (ec.ContainerType, base_type, base_type, Identifier,
+ Error_MemberLookupFailed (ec.CurrentType, base_type, base_type, Identifier,
null, AllMemberTypes, AllBindingFlags);
return null;
}
{
instance_expr = ec.GetThis (loc);
- current_type = ec.ContainerType.BaseType;
+ current_type = ec.CurrentType.BaseType;
indexer_type = current_type;
}
return null;
}
- if (ec.InCatch || ec.InFinally) {
+ if (ec.HasAny (EmitContext.Options.CatchScope | EmitContext.Options.FinallyScope)) {
Error (255, "Cannot use stackalloc in finally or catch");
return null;
}
{
AnonymousTypeClass anonymous_type;
- if (!ec.IsAnonymousMethodAllowed) {
+ if (ec.HasSet (EmitContext.Options.ConstantScope)) {
Report.Error (836, loc, "Anonymous types cannot be used in this expression");
return null;
}
public void ErrorInvalidVariance (MemberCore mc, Variance v)
{
}
+
+ public static TypeParameter FindTypeParameter (TypeParameter[] all, string name)
+ {
+ throw new NotImplementedException ();
+ }
//
// MemberContainer
public class TypeInferenceContext
{
+ public Type[] InferredTypeArguments;
+
+ public void AddCommonTypeBound (Type type)
+ {
+ throw new NotImplementedException ();
+ }
+
public void ExactInference (Type u, Type v)
{
throw new NotImplementedException ();
{
throw new NotImplementedException ();
}
+
+ public bool FixAllTypes ()
+ {
+ return false;
+ }
}
partial class TypeManager
return false;
}
- TypeParameterExpr texpr = expr as TypeParameterExpr;
- if (texpr != null)
+ if (TypeManager.IsGenericParameter (expr.Type))
type_param_constraints.Add (expr);
else if (expr.IsInterface)
iface_constraints.Add (expr);
list.Add (iface_constraint.Type);
}
- foreach (TypeParameterExpr expr in type_param_constraints) {
+ foreach (TypeExpr expr in type_param_constraints) {
foreach (Type type in list) {
if (!type.Equals (expr.Type))
continue;
TypeManager.CSharpName (class_constraint_type));
return false;
}
+
+ if (TypeManager.IsDynamicType (class_constraint_type)) {
+ Report.Error (1967, loc, "A constraint cannot be the dynamic type");
+ return false;
+ }
}
if (class_constraint_type != null)
return true;
}
- bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
+ bool CheckTypeParameterConstraints (Type tparam, ref TypeExpr prevConstraint, ArrayList seen)
{
seen.Add (tparam);
- Constraints constraints = tparam.Constraints;
+ Constraints constraints = TypeManager.LookupTypeParameter (tparam).Constraints;
if (constraints == null)
return true;
if (constraints.type_param_constraints == null)
return true;
- foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
- if (seen.Contains (expr.TypeParameter)) {
+ foreach (TypeExpr expr in constraints.type_param_constraints) {
+ if (seen.Contains (expr.Type)) {
Report.Error (454, loc, "Circular constraint " +
"dependency involving `{0}' and `{1}'",
tparam.Name, expr.GetSignatureForError ());
return false;
}
- if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
+ if (!CheckTypeParameterConstraints (expr.Type, ref prevConstraint, seen))
return false;
}
if (type_param_constraints.Count != 0) {
ArrayList seen = new ArrayList ();
TypeExpr prev_constraint = class_constraint;
- foreach (TypeParameterExpr expr in type_param_constraints) {
- if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prev_constraint, seen))
+ foreach (TypeExpr expr in type_param_constraints) {
+ if (!CheckTypeParameterConstraints (expr.Type, ref prev_constraint, seen))
return false;
seen.Clear ();
}
return true;
}
+ public static TypeParameter FindTypeParameter (TypeParameter[] tparams, string name)
+ {
+ foreach (var tp in tparams) {
+ if (tp.Name == name)
+ return tp;
+ }
+
+ return null;
+ }
+
public void SetConstraints (GenericTypeParameterBuilder type)
{
GenericParameterAttributes attr = GenericParameterAttributes.None;
/// A TypeExpr which already resolved to a type parameter.
/// </summary>
public class TypeParameterExpr : TypeExpr {
- TypeParameter type_parameter;
-
- public TypeParameter TypeParameter {
- get {
- return type_parameter;
- }
- }
public TypeParameterExpr (TypeParameter type_parameter, Location loc)
{
- this.type_parameter = type_parameter;
+ this.type = type_parameter.Type;
+ this.eclass = ExprClass.TypeParameter;
this.loc = loc;
}
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
- type = type_parameter.Type;
- eclass = ExprClass.TypeParameter;
return this;
}
this.parameters = parameters;
}
+ public override TypeParameter[] CurrentTypeParameters {
+ get {
+ return base.type_params;
+ }
+ }
+
public override TypeBuilder DefineType ()
{
throw new Exception ();
}
}
+ //
+ // Used together with AddCommonTypeBound fo implement
+ // 7.4.2.13 Finding the best common type of a set of expressions
+ //
+ public TypeInferenceContext ()
+ {
+ fixed_types = new Type [1];
+ unfixed_types = new Type [1];
+ unfixed_types[0] = InternalType.Arglist; // it can be any internal type
+ bounds = new ArrayList [1];
+ }
+
public Type[] InferredTypeArguments {
get {
return fixed_types;
}
}
+ public void AddCommonTypeBound (Type type)
+ {
+ AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
+ }
+
void AddToBounds (BoundInfo bound, int index)
{
//
if (candidates.Count == 1) {
unfixed_types[i] = null;
- fixed_types[i] = ((BoundInfo) candidates[0]).Type;
+ Type t = ((BoundInfo) candidates[0]).Type;
+ if (t == TypeManager.null_type)
+ return false;
+
+ fixed_types [i] = t;
return true;
}
public static bool CheckContext (EmitContext ec, Location loc)
{
- for (Block block = ec.CurrentBlock; block != null; block = block.Parent) {
- if (!block.Unsafe)
- continue;
-
- Report.Error (1629, loc, "Unsafe code may not appear in iterators");
- return false;
- }
-
//
// We can't use `ec.InUnsafe' here because it's allowed to have an iterator
// inside an unsafe class. See test-martin-29.cs for an example.
Block = new ToplevelBlock (host.Iterator.Container.Toplevel, ParametersCompiled.EmptyReadOnlyParameters, Location);
}
- public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
+ public override EmitContext CreateEmitContext (ILGenerator ig)
{
EmitContext ec = new EmitContext (
- this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
+ this, this.ds, ig, MemberType);
ec.CurrentAnonymousMethod = host.Iterator;
return ec;
//
public class ContextualReturn : Return
{
+ ExpressionStatement statement;
+
public ContextualReturn (Expression expr)
: base (expr, expr.Location)
{
public override void Emit (EmitContext ec)
{
- if (ec.ReturnType == TypeManager.void_type) {
- ((ExpressionStatement) Expr).EmitStatement (ec);
+ if (statement != null) {
+ statement.EmitStatement (ec);
ec.ig.Emit (OpCodes.Ret);
return;
}
}
protected override bool DoResolve (EmitContext ec)
- {
+ {
//
// When delegate returns void, only expression statements can be used
//
Expr = Expr.Resolve (ec);
if (Expr == null)
return false;
-
- if (Expr is ExpressionStatement)
- return true;
-
- Expr.Error_InvalidExpressionStatement ();
- return false;
+
+ statement = Expr as ExpressionStatement;
+ if (statement == null)
+ Expr.Error_InvalidExpressionStatement ();
+
+ return true;
}
return base.DoResolve (ec);
{
}
- protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, LocatedToken name, Expression init)
+ protected static Expression CreateRangeVariableType (ToplevelBlock block, IResolveContext context, LocatedToken name, Expression init)
{
ArrayList args = new ArrayList (2);
args.Add (new AnonymousTypeParameter (block.Parameters [0]));
args.Add (new RangeAnonymousTypeParameter (init, name));
- return new AnonymousTypeDeclaration (args, container, name.Location);
+ return new AnonymousTypeDeclaration (args, context.CurrentTypeDefinition, name.Location);
}
}
result_selector_expr = next.expr;
next = next.next;
} else {
- result_selector_expr = CreateRangeVariableType (block, (TypeContainer) ec.TypeContainer, into_variable,
+ result_selector_expr = CreateRangeVariableType (block, ec.ResolveContext, into_variable,
new SimpleName (into_variable.Value, into_variable.Location));
}
result_selector_expr = next.expr;
next = next.next;
} else {
- result_selector_expr = CreateRangeVariableType (block, (TypeContainer)ec.TypeContainer, lt, new SimpleName (lt.Value, lt.Location));
+ result_selector_expr = CreateRangeVariableType (block, ec.ResolveContext, lt, new SimpleName (lt.Value, lt.Location));
}
LambdaExpression result_selector = new LambdaExpression (lt.Location);
retval.AddAssemblyReference (assembly);
}
- public override void Error_NamespaceDoesNotExist(DeclSpace ds, Location loc, string name)
+ public override void Error_NamespaceDoesNotExist(Location loc, string name)
{
Report.Error (400, loc, "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
name);
return this;
}
- public virtual void Error_NamespaceDoesNotExist (DeclSpace ds, Location loc, string name)
+ public virtual void Error_NamespaceDoesNotExist (Location loc, string name)
{
if (name.IndexOf ('`') > 0) {
- FullNamedExpression retval = Lookup (ds, SimpleName.RemoveGenericArity (name), loc);
+ FullNamedExpression retval = Lookup (SimpleName.RemoveGenericArity (name), loc);
if (retval != null) {
Error_TypeArgumentsCannotBeUsed (retval, loc);
return;
return null;
}
- public FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
+ public FullNamedExpression Lookup (string name, Location loc)
{
if (namespaces.Contains (name))
return (Namespace) namespaces [name];
//
// Completes types with the given `prefix' and stores the results in `result'
//
- public void CompletionGetTypesStartingWith (DeclSpace ds, string prefix, Hashtable result)
+ public void CompletionGetTypesStartingWith (string prefix, Hashtable result)
{
int l = fullname.Length + 1;
ICollection res = root.CompletionGetTypesStartingWith (fullname + "." + prefix);
return null;
}
- TypeExpr te = resolved as TypeExpr;
- if (te != null) {
- if (!te.CheckAccessLevel (rc.DeclContainer)) {
- Report.SymbolRelatedToPreviousError (te.Type);
- Expression.ErrorIsInaccesible (resolved.Location, resolved.GetSignatureForError ());
- }
- }
+ if (resolved is TypeExpr)
+ resolved = resolved.ResolveAsBaseTerminal (rc, false);
return resolved;
}
/// Does extension methods look up to find a method which matches name and extensionType.
/// Search starts from this namespace and continues hierarchically up to top level.
///
- public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, ClassOrStruct currentClass, string name, Location loc)
+ public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
{
ArrayList candidates = null;
- if (currentClass != null) {
- candidates = ns.LookupExtensionMethod (extensionType, currentClass, name);
- if (candidates != null)
- return new ExtensionMethodGroupExpr (candidates, this, extensionType, loc);
- }
-
foreach (Namespace n in GetUsingTable ()) {
ArrayList a = n.LookupExtensionMethod (extensionType, null, name);
if (a == null)
//
// Continue in parent scope
//
- return parent.LookupExtensionMethod (extensionType, currentClass, name, loc);
+ return parent.LookupExtensionMethod (extensionType, name, loc);
}
- public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
+ public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
{
// Precondition: Only simple names (no dots) will be looked up with this function.
FullNamedExpression resolved = null;
for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
- if ((resolved = curr_ns.Lookup (ds, name, loc, ignore_cs0104)) != null)
+ if ((resolved = curr_ns.Lookup (name, loc, ignore_cs0104)) != null)
break;
}
return resolved;
}
- public ICollection CompletionGetTypesStartingWith (DeclSpace ds, string prefix)
+ public ICollection CompletionGetTypesStartingWith (string prefix)
{
Hashtable result = new Hashtable ();
if (ld != -1){
string rest = prefix.Substring (ld+1);
- using_ns.CompletionGetTypesStartingWith (ds, rest, result);
+ using_ns.CompletionGetTypesStartingWith (rest, result);
}
}
- using_ns.CompletionGetTypesStartingWith (ds, prefix, result);
+ using_ns.CompletionGetTypesStartingWith (prefix, result);
}
}
}
// Looks-up a alias named @name in this and surrounding namespace declarations
- public FullNamedExpression LookupAlias (string name)
+ public FullNamedExpression LookupNamespaceAlias (string name)
{
for (NamespaceEntry n = this; n != null; n = n.ImplicitParent) {
if (n.using_aliases == null)
return null;
}
- private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc, bool ignore_cs0104)
+ private FullNamedExpression Lookup (string name, Location loc, bool ignore_cs0104)
{
//
// Check whether it's in the namespace.
//
- FullNamedExpression fne = ns.Lookup (ds, name, loc);
+ FullNamedExpression fne = ns.Lookup (name, loc);
//
// Check aliases.
//
FullNamedExpression match = null;
foreach (Namespace using_ns in GetUsingTable ()) {
- match = using_ns.Lookup (ds, name, loc);
+ match = using_ns.Lookup (name, loc);
if (match == null || !(match is TypeExpr))
continue;
if (fne != null) {
#region IResolveContext Members
+ public Type CurrentType {
+ get { return SlaveDeclSpace.CurrentType; }
+ }
+
+ public TypeContainer CurrentTypeDefinition {
+ get { return SlaveDeclSpace.CurrentTypeDefinition; }
+ }
+
+ public TypeParameter[] CurrentTypeParameters {
+ get { return SlaveDeclSpace.CurrentTypeParameters; }
+ }
+
public DeclSpace DeclContainer {
get { return SlaveDeclSpace; }
}
get { return SlaveDeclSpace.IsInUnsafeScope; }
}
+ public bool IsStatic {
+ get { return SlaveDeclSpace.IsStatic; }
+ }
+
public DeclSpace GenericDeclContainer {
get { return SlaveDeclSpace; }
}
/// <summary>
/// Abstract Base class for parameters of a method.
/// </summary>
- public abstract class ParameterBase : Attributable {
-
+ public abstract class ParameterBase : Attributable
+ {
protected ParameterBuilder builder;
- protected ParameterBase (Attributes attrs)
- : base (attrs)
- {
- }
-
public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
#if !NET_2_0
/// Class for applying custom attributes on the return type
/// </summary>
public class ReturnParameter : ParameterBase {
- public ReturnParameter (MethodBuilder mb, Location location):
- base (null)
+ public ReturnParameter (MethodBuilder mb, Location location)
{
try {
builder = mb.DefineParameter (0, ParameterAttributes.None, "");
pa.EmitAttribute (builder, loc);
}
- public override IResolveContext ResolveContext {
- get {
- throw new NotSupportedException ();
- }
- }
-
/// <summary>
/// Is never called
/// </summary>
///
// TODO: should use more code from Parameter.ApplyAttributeBuilder
public class ImplicitParameter : ParameterBase {
- public ImplicitParameter (MethodBuilder mb):
- base (null)
+ public ImplicitParameter (MethodBuilder mb)
{
builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
}
}
}
- public override IResolveContext ResolveContext {
- get {
- throw new NotSupportedException ();
- }
- }
-
/// <summary>
/// Is never called
/// </summary>
int idx;
public bool HasAddressTaken;
- IResolveContext resolve_context;
LocalVariableReference expr_tree_variable;
static TypeExpr parameter_expr_tree_type;
public HoistedVariable HoistedVariableReference;
public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
- : base (attrs)
{
if (type == TypeManager.system_void_expr)
Report.Error (1536, loc, "Invalid parameter type `void'");
modFlags = mod;
Location = loc;
TypeName = type;
+
+ // Only assign, attributes will be attached during resolve
+ base.attributes = attrs;
}
public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
return member.IsAccessibleAs (parameter_type);
}
- public override IResolveContext ResolveContext {
- get {
- return resolve_context;
- }
- }
-
// <summary>
// Resolve is used in method definitions
// </summary>
public virtual Type Resolve (IResolveContext rc)
{
- // HACK: to resolve attributes correctly
- this.resolve_context = rc;
-
if (parameter_type != null)
return parameter_type;
+ if (attributes != null)
+ attributes.AttachTo (this, rc);
+
TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
if (texpr == null)
return null;
return parameter_type;
if (default_expr != null) {
- EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, Location, null, parameter_type, 0);
+ EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, null, parameter_type);
default_expr = default_expr.Resolve (ec);
if (default_expr != null) {
Constant value = default_expr as Constant;
(modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
rc as MemberCore);
- if (texpr is TypeParameterExpr)
+ if (TypeManager.IsGenericParameter (parameter_type))
return parameter_type;
if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
public Parameter Clone ()
{
Parameter p = (Parameter) MemberwiseClone ();
- if (attributes != null) {
+ if (attributes != null)
p.attributes = attributes.Clone ();
- p.attributes.AttachTo (p);
- }
return p;
}
public void AddAttributes (ArrayList attrs)
{
foreach (Attribute a in attrs)
- a.AttachTo (this);
+ a.AttachTo (this, CodeGen.Assembly);
if (attributes == null) {
attributes = new Attributes (attrs);
}
}
- public override IResolveContext ResolveContext {
- get { return this; }
- }
-
protected override bool AddMemberType (DeclSpace ds)
{
if (!AddToContainer (ds, ds.Name))
{
return PartialContainer.IsClsComplianceRequired ();
}
+
+ public override FullNamedExpression LookupNamespaceAlias (string name)
+ {
+ return NamespaceEntry.LookupNamespaceAlias (name);
+ }
}
}
public override bool Resolve (EmitContext ec)
{
- if (expr != null)
+ if (expr != null && expr.eclass == ExprClass.Invalid)
expr = expr.ResolveStatement (ec);
return expr != null;
}
if (Expr == null)
return false;
+ if (ec.HasSet (EmitContext.Options.InferReturnType)) {
+ ec.ReturnTypeInference.AddCommonTypeBound (Expr.Type);
+ return true;
+ }
+
if (Expr.Type != ec.ReturnType) {
- if (ec.InferReturnType) {
- //
- // void cannot be used in contextual return
- //
- if (Expr.Type == TypeManager.void_type)
- return false;
+ Expr = Convert.ImplicitConversionRequired (ec, Expr, ec.ReturnType, loc);
- ec.ReturnType = Expr.Type;
- } else {
- Expr = Convert.ImplicitConversionRequired (
- ec, Expr, ec.ReturnType, loc);
-
- if (Expr == null) {
- if (am != null) {
- Report.Error (1662, loc,
- "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
- am.ContainerType, am.GetSignatureForError ());
- }
- return false;
+ if (Expr == null) {
+ if (am != null) {
+ Report.Error (1662, loc,
+ "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
+ am.ContainerType, am.GetSignatureForError ());
}
+ return false;
}
}
ec.DefineLocalVariable (Name, builder);
}
- public bool IsThisAssigned (EmitContext ec)
+ public bool IsThisAssigned (EmitContext ec, Block block)
{
if (VariableInfo == null)
throw new Exception ();
if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
return true;
- return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, ec.loc);
+ return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, block.StartLocation);
}
public bool IsAssigned (EmitContext ec)
ec.CurrentBlock = this;
Expression e;
- using (ec.With (EmitContext.Flags.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
+ using (ec.With (EmitContext.Options.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
e = cv.Resolve (ec);
}
if (e == null)
// If some parent block was unsafe, we remain unsafe even if this block
// isn't explicitly marked as such.
- using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
+ using (ec.With (EmitContext.Options.UnsafeScope, ec.InUnsafe | Unsafe)) {
flags |= Flags.VariablesInitialized;
if (variables != null) {
Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+ //
+ // Compiler generated scope statements
+ //
+ if (scope_initializers != null) {
+ foreach (Statement s in scope_initializers)
+ s.Resolve (ec);
+ }
+
//
// This flag is used to notate nested statements as unreachable from the beginning of this block.
// For the purposes of this resolution, it doesn't matter that the whole block is unreachable
{
SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
- using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) {
+ using (ec.Set (EmitContext.Options.OmitDebuggingInfo)) {
foreach (Statement s in scope_initializers)
s.Emit (ec);
}
//
// Creates anonymous method storey for this block
//
- am_storey = new AnonymousMethodStorey (this, ec.TypeContainer, mc, gm, "AnonStorey");
+ am_storey = new AnonymousMethodStorey (this, ec.CurrentTypeDefinition, mc, gm, "AnonStorey");
}
return am_storey;
if (child == null)
return null;
- block.ResolveMeta (ec, ParametersCompiled.EmptyReadOnlyParameters);
child = child.Resolve (ec);
if (child == null)
return null;
}
GenericMethod generic;
- FlowBranchingToplevel top_level_branching;
protected ParametersCompiled parameters;
ToplevelParameterInfo[] parameter_info;
LocalInfo this_variable;
+ bool resolved;
+ bool unreachable;
public HoistedVariable HoistedThisVariable;
return iterator_storey;
}
- public FlowBranchingToplevel TopLevelBranching {
- get { return top_level_branching; }
- }
-
//
// Returns a parameter reference expression for the given name,
// or null if there is no such parameter
public bool IsThisAssigned (EmitContext ec)
{
- return this_variable == null || this_variable.IsThisAssigned (ec);
+ return this_variable == null || this_variable.IsThisAssigned (ec, this);
+ }
+
+ public bool Resolve (FlowBranching parent, EmitContext rc, ParametersCompiled ip, IMethodData md)
+ {
+ if (resolved)
+ return true;
+
+ resolved = true;
+
+ try {
+ if (!ResolveMeta (rc, ip))
+ return false;
+
+ using (rc.With (EmitContext.Options.DoFlowAnalysis, true)) {
+ FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent);
+
+ if (!Resolve (rc))
+ return false;
+
+ unreachable = top_level.End ();
+ }
+ } catch (Exception) {
+#if PRODUCTION
+ if (rc.CurrentBlock != null) {
+ Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: Phase Resolve");
+ } else {
+ Report.Error (587, "Internal compiler error: Phase Resolve");
+ }
+#endif
+ throw;
+ }
+
+ if (rc.ReturnType != TypeManager.void_type && !unreachable) {
+ if (rc.CurrentAnonymousMethod == null) {
+ Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+ return false;
+ } else if (!rc.CurrentAnonymousMethod.IsIterator) {
+ Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
+ rc.CurrentAnonymousMethod.GetSignatureForError ());
+ return false;
+ }
+ }
+
+ return true;
}
- public bool ResolveMeta (EmitContext ec, ParametersCompiled ip)
+ bool ResolveMeta (EmitContext ec, ParametersCompiled ip)
{
int errors = Report.Errors;
int orig_count = parameters.Count;
- if (top_level_branching != null)
- return true;
-
if (ip != null)
parameters = ip;
ResolveMeta (ec, offset);
- top_level_branching = ec.StartFlowBranching (this);
-
return Report.Errors == errors;
}
}
}
+ public override void Emit (EmitContext ec)
+ {
+ if (Report.Errors > 0)
+ return;
+
+#if PRODUCTION
+ try {
+#endif
+ EmitMeta (ec);
+
+ if (ec.HasReturnLabel)
+ ec.ReturnLabel = ec.ig.DefineLabel ();
+
+ base.Emit (ec);
+
+ ec.Mark (EndLocation);
+
+ if (ec.HasReturnLabel)
+ ec.ig.MarkLabel (ec.ReturnLabel);
+
+ if (ec.return_value != null) {
+ ec.ig.Emit (OpCodes.Ldloc, ec.return_value);
+ ec.ig.Emit (OpCodes.Ret);
+ } else {
+ //
+ // If `HasReturnLabel' is set, then we already emitted a
+ // jump to the end of the method, so we must emit a `ret'
+ // there.
+ //
+ // Unfortunately, System.Reflection.Emit automatically emits
+ // a leave to the end of a finally block. This is a problem
+ // if no code is following the try/finally block since we may
+ // jump to a point after the end of the method.
+ // As a workaround, we're always creating a return label in
+ // this case.
+ //
+
+ if (ec.HasReturnLabel || !unreachable) {
+ if (ec.ReturnType != TypeManager.void_type)
+ ec.ig.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
+ ec.ig.Emit (OpCodes.Ret);
+ }
+ }
+
+#if PRODUCTION
+ } catch (Exception e){
+ Console.WriteLine ("Exception caught by the compiler while emitting:");
+ Console.WriteLine (" Block that caused the problem begin at: " + block.loc);
+
+ Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
+ throw;
+ }
+#endif
+ }
+
public override void EmitMeta (EmitContext ec)
{
parameters.ResolveVariable ();
base.EmitSymbolInfo (ec);
}
-
- public override void Emit (EmitContext ec)
- {
- base.Emit (ec);
- ec.Mark (EndLocation);
- }
}
public class SwitchLabel {
string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
}
- Field field = new Field (ec.TypeContainer, string_dictionary_type,
+ Field field = new Field (ec.CurrentTypeDefinition, string_dictionary_type,
Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null);
if (!field.Define ())
return;
- ec.TypeContainer.PartialContainer.AddField (field);
+ ec.CurrentTypeDefinition.PartialContainer.AddField (field);
ArrayList init = new ArrayList ();
int counter = 0;
public override bool Resolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
return Block.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
Block.Emit (ec);
}
public override bool Resolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
return Block.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+ using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
Block.Emit (ec);
}
{
Block = b;
Block.Unsafe = true;
+ loc = b.StartLocation;
}
public override bool Resolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.InUnsafe, true))
+ if (ec.CurrentIterator != null)
+ Report.Error (1629, loc, "Unsafe code may not appear in iterators");
+
+ using (ec.With (EmitContext.Options.UnsafeScope, true))
return Block.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.InUnsafe, true))
+ using (ec.With (EmitContext.Options.UnsafeScope, true))
Block.Emit (ec);
}
pinned_string.Pinned = true;
}
+ public StringEmitter Resolve (EmitContext rc)
+ {
+ pinned_string.Resolve (rc);
+
+ if (TypeManager.int_get_offset_to_string_data == null) {
+ TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
+ TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
+ }
+
+ return this;
+ }
+
public override void Emit (EmitContext ec)
{
- pinned_string.Resolve (ec);
pinned_string.ResolveVariable (ec);
converted.Emit (ec);
pinned_string.EmitAssign (ec);
- PropertyInfo p = TypeManager.int_get_offset_to_string_data;
- if (p == null) {
- // TODO: Move to resolve
- p = TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
- TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
-
- if (p == null)
- return;
- }
-
// TODO: Should use Binary::Add
pinned_string.Emit (ec);
ec.ig.Emit (OpCodes.Conv_I);
- PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, p, pinned_string.Location);
+ PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, TypeManager.int_get_offset_to_string_data, pinned_string.Location);
//pe.InstanceExpression = pinned_string;
pe.Resolve (ec).Emit (ec);
return false;
}
- ec.InFixedInitializer = true;
- e = e.Resolve (ec);
- ec.InFixedInitializer = false;
+ using (ec.Set (EmitContext.Options.FixedInitializerScope)) {
+ e = e.Resolve (ec);
+ }
+
if (e == null)
return false;
// Case 3: string
//
if (e.Type == TypeManager.string_type){
- data [i] = new StringEmitter (e, vi, loc);
+ data [i] = new StringEmitter (e, vi, loc).Resolve (ec);
i++;
continue;
}
public override bool Resolve (EmitContext ec)
{
- using (ec.With (EmitContext.Flags.InCatch, true)) {
+ using (ec.With (EmitContext.Options.CatchScope, true)) {
if (type_expr != null) {
TypeExpr te = type_expr.ResolveAsTypeTerminal (ec, false);
if (te == null)
if (ok)
ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally);
- using (ec.With (EmitContext.Flags.InFinally, true)) {
+ using (ec.With (EmitContext.Options.FinallyScope, true)) {
if (!fini.Resolve (ec))
ok = false;
}
}
Expression ml = Expression.MemberLookup (
- ec.ContainerType, TypeManager.idisposable_type, expr_type,
+ ec.CurrentType, TypeManager.idisposable_type, expr_type,
"Dispose", Location.Null);
if (!(ml is MethodGroupExpr)) {
enumerator_type = return_type;
if (!FetchGetCurrent (ec, return_type))
get_current = new PropertyExpr (
- ec.ContainerType, TypeManager.ienumerator_getcurrent, loc);
+ ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
if (!FetchMoveNext (return_type))
move_next = TypeManager.bool_movenext_void;
return true;
enumerator_type = return_type;
move_next = TypeManager.bool_movenext_void;
get_current = new PropertyExpr (
- ec.ContainerType, TypeManager.ienumerator_getcurrent, loc);
+ ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
return true;
}
} else {
bool FetchGetCurrent (EmitContext ec, Type t)
{
PropertyExpr pe = Expression.MemberLookup (
- ec.ContainerType, t, "Current", MemberTypes.Property,
+ ec.CurrentType, t, "Current", MemberTypes.Property,
Expression.AllBindingFlags, loc) as PropertyExpr;
if (pe == null)
return false;
bool TryType (EmitContext ec, Type t)
{
MethodGroupExpr mg = Expression.MemberLookup (
- ec.ContainerType, t, "GetEnumerator", MemberTypes.Method,
+ ec.CurrentType, t, "GetEnumerator", MemberTypes.Method,
Expression.AllBindingFlags, loc) as MethodGroupExpr;
if (mg == null)
return false;
public static Type CoreLookupType (string ns_name, string name, Kind type_kind, bool required)
{
Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, true);
- Expression expr = ns.Lookup (RootContext.ToplevelTypes, name, Location.Null);
+ Expression expr = ns.Lookup (name, Location.Null);
if (expr == null) {
if (required) {
--- /dev/null
+using System;
+
+class G<T>
+{
+ public struct S
+ {
+ public string Test ()
+ {
+ return GetType ().ToString ();
+ }
+ }
+}
+
+class C
+{
+ public static int Main ()
+ {
+ string s = new G<int>.S ().Test ();
+ if (s != "G`1+S[System.Int32]")
+ return 1;
+
+ return 0;
+ }
+}
--- /dev/null
+using System;
+
+class C
+{
+ static U Test<T, U>(T[] args, Func<T, U> f)
+ {
+ return f (args [1]);
+ }
+
+ public static int Main ()
+ {
+ var s = new string [] { "aaa", "bbb" };
+ var foo = Test (s, i => { try { return i; } catch { return null; } });
+ if (foo != s [1])
+ return 1;
+
+ return 0;
+ }
+}
--- /dev/null
+using System;
+
+class B<U>
+{
+}
+
+partial class C<T> : B<T>
+{
+ T t1;
+}
+
+partial class C<T> : B<T>
+{
+ T t2;
+}
+
+class Test
+{
+ public static void Main ()
+ {
+ }
+}
test-416.cs bug #504085
test-418.cs bug #504085
+test-682.cs bug #530861
test-704.cs IGNORE #472845
test-416.cs bug #504085
test-418.cs bug #504085
+test-682.cs bug #530861
test-704.cs IGNORE #472845
# csXXXX.cs IGNORE : adds test to ignore list
test-xml-027.cs
+test-682.cs Bug #530861
test-704.cs IGNORE #472845
<method name="Void .ctor()">
<size>7</size>
</method>
- <method name="Int32 SetEnum(System.String, Enum)">
- <size>2</size>
- </method>
- <method name="Int32 SetEnum(Int32, Enum)">
- <size>2</size>
- </method>
</type>
<type name="Test">
<method name="Void .ctor()">
<size>31</size>
</method>
</type>
+ <type name="TestThing">
+ <method name="Int32 SetEnum(System.String, System.Enum)">
+ <size>2</size>
+ </method>
+ <method name="Int32 SetEnum(Int32, System.Enum)">
+ <size>2</size>
+ </method>
+ </type>
</test>
<test name="gtest-352.cs">
<type name="T">
</method>
</type>
</test>
+ <test name="gtest-456.cs">
+ <type name="G`1[T]">
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="G`1+S[T]">
+ <method name="System.String Test()">
+ <size>22</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Int32 Main()">
+ <size>36</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-anon-1.cs">
<type name="X">
<method name="Void .ctor()">
</method>
</type>
</test>
+ <test name="gtest-lambda-23.cs">
+ <type name="C">
+ <method name="U Test[T,U](T[], System.Func`2[T,U])">
+ <size>14</size>
+ </method>
+ <method name="Int32 Main()">
+ <size>77</size>
+ </method>
+ <method name="System.String <Main>m__0(System.String)">
+ <size>27</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-linq-01.cs">
<type name="from.C">
<method name="Void .ctor()">
</method>
</type>
</test>
+ <test name="gtest-partial-01.cs">
+ <type name="B`1[U]">
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C`1[T]">
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="Test">
+ <method name="Void Main()">
+ <size>1</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-var-04.cs">
<type name="Test">
<method name="Void .ctor()">
<method name="Void .ctor()">
<size>7</size>
</method>
- <method name="Boolean EnumInSet(Enum, System.Enum[])">
- <size>37</size>
- </method>
<method name="Void Main()">
<size>1</size>
</method>
+ <method name="Boolean EnumInSet(System.Enum, System.Enum[])">
+ <size>37</size>
+ </method>
</type>
</test>
<test name="test-281.cs">
<method name="System.Object get_Val()">
<size>7</size>
</method>
- <method name="Enum get_Val2()">
+ <method name="System.Enum get_Val2()">
<size>7</size>
</method>
</type>
+2009-08-12 Jonathan Pryor <jpryor@novell.com>
+
+ * Test/DocTest-v1.cs: Add a comment which uses <format/>, to test html
+ escaping behavior.
+ * Resources/monodoc-ecma.xsd: Permit <format/> in various elements.
+ * Test/en.expected.importslashdoc/Mono.DocTest/DocAttribute.xml,
+ Test/html.expected/Mono.DocTest/DocAttribute.html,
+ Test/msxdoc-expected.importslashdoc.xml: Flush.
+
+2009-08-12 Jonathan Pryor <jpryor@novell.com>
+
+ * Makefile: Add ../monodoc/Resources/mdoc-html-format.xsl as a resource.
+
2009-08-06 Jonathan Pryor <jpryor@novell.com>
* mdoc.exe.sources: Add ../../build/common/Consts.cs to the build.
include ../../build/rules.make
LOCAL_MCS_FLAGS = \
+ /resource:../monodoc/Resources/mdoc-html-format.xsl,mdoc-html-format.xsl \
/resource:../monodoc/Resources/mdoc-html-utils.xsl,mdoc-html-utils.xsl \
/resource:../monodoc/Resources/mdoc-sections-css.xsl,mdoc-sections-css.xsl \
/resource:../monodoc/Resources/mono-ecma-css.xsl,mono-ecma-css.xsl \
<xs:element ref="block" />
<xs:element ref="c" />
<xs:element ref="code" />
+ <xs:element ref="format" />
<xs:element ref="list" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element name="example">
<xs:complexType mixed="true">
<xs:choice maxOccurs="unbounded">
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="code" />
<xs:element ref="c" />
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
</xs:complexType>
</xs:element>
+ <xs:element name="format">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any minOccurs="0" processContents="lax" />
+ </xs:sequence>
+ <xs:attribute ref="type" />
+ </xs:complexType>
+ </xs:element>
+
<xs:element name="interface">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
+ <xs:element ref="format" />
<xs:element ref="see" />
<xs:element ref="list" />
<xs:element ref="link" />
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="c" />
+ <xs:element ref="format" />
<xs:element ref="see" />
<xs:element ref="block" />
<xs:element ref="paramref" />
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
<xs:element ref="block" />
<xs:element ref="c" />
<xs:element ref="code" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
<xs:element name="returns">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="format" />
<xs:element ref="list" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
<xs:element ref="c" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
<xs:element ref="c" />
+ <xs:element ref="format" />
<xs:element ref="see" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="block" />
<xs:element ref="c" />
+ <xs:element ref="format" />
<xs:element ref="para" />
<xs:element ref="paramref" />
<xs:element ref="see" />
/// <para>
/// cref=<c>T:Mono.DocTest.DocAttribute</c>.
/// </para>
+ /// <format type="text/html">
+ /// <table width="100%">
+ /// <tr>
+ /// <td style="color:red">red</td>
+ /// <td style="color:blue">blue</td>
+ /// <td style="color:green">green</td>
+ /// </tr>
+ /// </table>
+ /// </format>
/// <code lang="C#" src="../DocTest.cs#DocAttribute Example" />
/// </remarks>
[AttributeUsage (AttributeTargets.All)]
<para>
cref=<c>T:Mono.DocTest.DocAttribute</c>.
</para>
+ <format type="text/html">
+ <table width="100%">
+ <tr>
+ <td style="color:red">red</td>
+ <td style="color:blue">blue</td>
+ <td style="color:green">green</td>
+ </tr>
+ </table>
+ </format>
<code lang="C#" src="../DocTest.cs#DocAttribute Example">[Doc ("documented class")]
class Example {
[Doc ("documented field")] public string field;
<p>
cref=<tt>T:Mono.DocTest.DocAttribute</tt>.
</p>
+ <table width="100%">
+ <tr>
+ <td style="color:red">red</td>
+ <td style="color:blue">blue</td>
+ <td style="color:green">green</td>
+ </tr>
+ </table>
<table class="CodeExampleTable">
<tr>
<td>
<para>
cref=<c>T:Mono.DocTest.DocAttribute</c>.
</para>
+ <format type="text/html">
+ <table width="100%">
+ <tr>
+ <td style="color:red">red</td>
+ <td style="color:blue">blue</td>
+ <td style="color:green">green</td>
+ </tr>
+ </table>
+ </format>
<code lang="C#" src="../DocTest.cs#DocAttribute Example">[Doc ("documented class")]
class Example {
[Doc ("documented field")] public string field;
+2009-08-13 Jonathan Pryor <jpryor@novell.com>
+
+ * Monodoc/provider.cs: Add a RootTree.AddSource(string) method, so that
+ additional directories can be checked for .source file loading.
+
+2009-08-13 Jonathan Pryor <jpryor@novell.com>
+
+ * Monodoc/provider.cs: Make RootTree.LoadTree() just call
+ RootTree.LoadTree(null), and move the .config-file parsing into
+ .LoadTree(string) (for when basedir==null). This will simplify the
+ logic of monodoc, as we want to add the ability to monodoc to use
+ any arbitrary directory, and this will remove the need to do
+ `if (d==null) RootTree.LoadTree(); else RootTree.LoadTree(d)`.
+ This also conforms to FxDG guidelines.
+
+2009-08-12 Jonathan Pryor <jpryor@novell.com>
+
+ * Resources/mdoc-html-format: Added; XSLT file to match
+ "//format[@type='text/html']//*", to support "pass-through"
+ semantics. This allows you to use actual HTML within your
+ documentation and have it visible to HTML-supporting output formats.
+ WARNING: Use as a "last resort" -- this is primarily intended for
+ importing existing HTML w/o needing lots of extra logic to convert
+ into mdoc format XML first (with a corresponding loss of fidelity).
+ However, it means that if (when) we get non-HTML output format
+ support, the <format type="text/html" /> blocks WILL be skipped for
+ that non-HTML output format.
+
+ For example, the forever-on-the-back-burner ROFF output support --
+ to remove the use of lynx, as no one ever has it installed --
+ wouldn't be able to support HTML format, so it would skip these
+ <format type="text/html"/> blocks.
+
+ Consider <format /> the moral equivalent of Perl POD's
+ '=begin formatname' block; see perlpod(1).
+ * Resources/mdoc-html-utils.xsl: <xsl:import/> mdoc-html-format.xsl.
+ It *must* be imported (NOT included) so that it will have a lower
+ priority than other <template/>s, thus allowing the HTML formatter
+ to <xsl:apply-templates/> which then use the "normal" rules. This
+ allows:
+ <format type="text/html">
+ <p><see cref="T:System.String" /></p>
+ </format>
+ to work as expected.
+ * Makefile: Add mdoc-html-format.xsl as a resource.
+
2009-04-16 Jonathan Pryor <jpryor@novell.com>
* Monodoc/man-provider.cs: NEVER return a non-null string from
Resources/home.html \
Resources/Lminus.gif \
Resources/Lplus.gif \
+ Resources/mdoc-html-format.xsl \
Resources/mdoc-html-utils.xsl \
Resources/mdoc-sections-css.xsl \
Resources/mdoc-sections.xsl \
/resource:Resources/home.html,home.html \
/resource:Resources/Lminus.gif,Lminus.gif \
/resource:Resources/Lplus.gif,Lplus.gif \
+ /resource:Resources/mdoc-html-format.xsl,mdoc-html-format.xsl \
/resource:Resources/mdoc-html-utils.xsl,mdoc-html-utils.xsl \
/resource:Resources/mdoc-sections-css.xsl,mdoc-sections-css.xsl \
/resource:Resources/mdoc-sections.xsl,mdoc-sections.xsl \
public static RootTree LoadTree ()
{
- string basedir;
- string myPath = System.Reflection.Assembly.GetExecutingAssembly ().Location;
- string cfgFile = myPath + ".config";
- if (!File.Exists (cfgFile)) {
- basedir = ".";
- return LoadTree (basedir);
- }
-
- XmlDocument d = new XmlDocument ();
- d.Load (cfgFile);
- basedir = d.SelectSingleNode ("config/path").Attributes ["docsPath"].Value;
-
- return LoadTree (basedir);
+ return LoadTree (null);
}
//
//
public static RootTree LoadTree (string basedir)
{
+ if (basedir == null) {
+ string myPath = System.Reflection.Assembly.GetExecutingAssembly ().Location;
+ string cfgFile = myPath + ".config";
+ if (!File.Exists (cfgFile)) {
+ basedir = ".";
+ }
+ else {
+ XmlDocument d = new XmlDocument ();
+ d.Load (cfgFile);
+ basedir = d.SelectSingleNode ("config/path").Attributes ["docsPath"].Value;
+ }
+ }
XmlDocument doc = new XmlDocument ();
RootTree root = new RootTree ();
//
// Load the sources
//
- string sources_dir = Path.Combine (basedir, "sources");
+ root.AddSource (Path.Combine (basedir, "sources"));
+ foreach (string path in UncompiledHelpSources) {
+ EcmaUncompiledHelpSource hs = new EcmaUncompiledHelpSource(path);
+ hs.RootTree = root;
+ root.help_sources.Add (hs);
+ string epath = "extra-help-source-" + hs.Name;
+ Node hsn = root.CreateNode (hs.Name, "root:/" + epath);
+ root.name_to_hs [epath] = hs;
+ hsn.EnsureNodes ();
+ foreach (Node n in hs.Tree.Nodes){
+ hsn.AddNode (n);
+ }
+ }
+
+ // Clean the tree
+ PurgeNode(root);
+
+ root.Sort ();
+
+ return root;
+ }
+
+ public void AddSource (string sources_dir)
+ {
+ Node third_party = LookupEntryPoint ("various") ?? this;
+
string [] files = Directory.GetFiles (sources_dir);
+
foreach (string file in files){
if (!file.EndsWith (".source"))
continue;
- doc = new XmlDocument ();
+ XmlDocument doc = new XmlDocument ();
try {
doc.Load (file);
} catch {
XmlNodeList extra_nodes = doc.SelectNodes ("/monodoc/node");
if (extra_nodes.Count > 0)
- root.Populate (third_party, extra_nodes);
+ Populate (third_party, extra_nodes);
XmlNodeList sources = doc.SelectNodes ("/monodoc/source");
if (sources == null){
HelpSource hs = GetHelpSource (provider, basefilepath);
if (hs == null)
continue;
- hs.RootTree = root;
- root.help_sources.Add (hs);
- root.name_to_hs [path] = hs;
+ hs.RootTree = this;
+ help_sources.Add (hs);
+ name_to_hs [path] = hs;
- Node parent = root.LookupEntryPoint (path);
+ Node parent = LookupEntryPoint (path);
if (parent == null){
Console.Error.WriteLine ("node `{0}' is not defined on the documentation map", path);
parent = third_party;
parent.Sort ();
}
}
-
- foreach (string path in UncompiledHelpSources) {
- EcmaUncompiledHelpSource hs = new EcmaUncompiledHelpSource(path);
- hs.RootTree = root;
- root.help_sources.Add (hs);
- string epath = "extra-help-source-" + hs.Name;
- Node hsn = root.CreateNode (hs.Name, "root:/" + epath);
- root.name_to_hs [epath] = hs;
- hsn.EnsureNodes ();
- foreach (Node n in hs.Tree.Nodes){
- hsn.AddNode (n);
- }
- }
-
- // Clean the tree
- PurgeNode(root);
-
- root.Sort ();
-
- return root;
}
// Delete nodes which does not have documentaiton (source)
--- /dev/null
+<?xml version="1.0"?>
+
+<!--
+ mdoc-html-format.xsl: HTML pass-through formatting support
+
+ Author: Jonathan Pryor (jpryor@novell.com)
+
+-->
+
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+
+ <!-- pass-through any other elements unchanged - they may be HTML -->
+ <xsl:template match="//format[@type='text/html']//*">
+ <xsl:copy>
+ <xsl:copy-of select="@*" />
+ <xsl:apply-templates select="*|node()" />
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
+
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
+ <xsl:import href="mdoc-html-format.xsl" />
<!-- TEMPLATE PARAMETERS -->
<xsl:param name="language" select="'C#'"/>
+2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
+
+ * MoonlightChannelBaseExtension.cs : fixed a couple of generated
+ code to compile on .NET (not in mcs yet; some nested generics bug).
+
+2009-08-10 Atsushi Enomoto <atsushi@ximian.com>
+
+ * Driver.cs, CommandLineOptions.cs : add moonlight proxy generator
+ support.
+ * MoonlightChannelBaseExtension.cs : new, moonlight proxy generator.
+ Implemented as I[Service|Operation]ContractGenerationExtension.
+ * svcutil.exe.sources : add above.
+
2006-10-19 Ankit Jain <jankit@novell.com>
* Driver.cs: Try to use HTTP GET to get wsdl, if it fails then try
[Option ("Generate typed messages.", "typedMessage", "tm")]
public bool GenerateTypedMessages;
+ bool generate_moonlight_proxy;
+
+ [Option ("Generate moonlight client. (This option may vanish.)", "moonlight")]
+ public bool GenerateMoonlightProxy {
+ get { return generate_moonlight_proxy; }
+ set {
+ if (!value)
+ return;
+ generate_moonlight_proxy = true;
+ GenerateAsync = true;
+ }
+ }
+
[Option ("Generate types as internal.", 'i', "internal")]
public bool GenerateTypesAsInternal;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
+using System.ServiceModel.Dispatcher;
using System.Collections.ObjectModel;
using System.Xml;
using System.Xml.Schema;
generator.GenerateServiceContractType (se.Contract);*/
Collection<ContractDescription> contracts = importer.ImportAllContracts ();
- foreach (ContractDescription cd in contracts)
- generator.GenerateServiceContractType (cd);
+ foreach (ContractDescription cd in contracts) {
+ if (co.GenerateMoonlightProxy) {
+ var moonctx = new MoonlightChannelBaseContext ();
+ cd.Behaviors.Add (new MoonlightChannelBaseContractExtension (moonctx));
+ foreach (var od in cd.Operations)
+ od.Behaviors.Add (new MoonlightChannelBaseOperationExtension (moonctx));
+ generator.GenerateServiceContractType (cd);
+ moonctx.Fixup ();
+ }
+ else
+ generator.GenerateServiceContractType (cd);
+ }
/*if (cns.Types.Count == 0) {
Console.Error.WriteLine ("Argument assemblies have no types.");
--- /dev/null
+//
+// MoonlightChannelBaseExtension.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2009 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.
+//
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Reflection;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+using System.ServiceModel.Dispatcher;
+
+namespace Mono.ServiceContractTool
+{
+ class MoonlightChannelBaseContext
+ {
+ public MoonlightChannelBaseContractExtension Contract;
+ public List<MoonlightChannelBaseOperationExtension> Operations = new List<MoonlightChannelBaseOperationExtension> ();
+
+ public CodeTypeDeclaration ClientType { get; set; }
+ public CodeTypeDeclaration ChannelType { get; set; }
+
+ public void FindClientType (ServiceContractGenerationContext context)
+ {
+ var cd = context.Contract;
+ string name = cd.Name + "Client";
+ if (name [0] == 'I')
+ name = name.Substring (1);
+
+ foreach (CodeNamespace cns in context.ServiceContractGenerator.TargetCompileUnit.Namespaces)
+ foreach (CodeTypeDeclaration ct in cns.Types)
+ if (ct == context.ContractType)
+ foreach (CodeTypeDeclaration ct2 in cns.Types)
+ if (ct2.Name == name) {
+ ClientType = ct2;
+ return;
+ }
+ throw new Exception (String.Format ("Contract '{0}' not found", name));
+ }
+
+ public void Fixup ()
+ {
+ Contract.Fixup ();
+ foreach (var op in Operations)
+ op.Fixup ();
+ }
+ }
+
+ class MoonlightChannelBaseContractExtension : IContractBehavior, IServiceContractGenerationExtension
+ {
+ public MoonlightChannelBaseContractExtension (MoonlightChannelBaseContext mlContext)
+ {
+ ml_context = mlContext;
+ }
+
+ MoonlightChannelBaseContext ml_context;
+
+ // IContractBehavior
+ public void AddBindingParameters (ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void ApplyClientBehavior (
+ ContractDescription description,
+ ServiceEndpoint endpoint,
+ ClientRuntime proxy)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void ApplyDispatchBehavior (
+ ContractDescription description,
+ ServiceEndpoint endpoint,
+ DispatchRuntime dispatch)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void Validate (
+ ContractDescription description,
+ ServiceEndpoint endpoint)
+ {
+ throw new NotSupportedException ();
+ }
+
+ // IServiceContractGenerationExtensions
+
+ public void GenerateContract (
+ ServiceContractGenerationContext context)
+ {
+ this.context = context;
+ ml_context.Contract = this;
+ }
+
+ ServiceContractGenerationContext context;
+
+ public void Fixup ()
+ {
+ ContractDescription cd = context.Contract;
+ ml_context.FindClientType (context);
+ var parentClass = ml_context.ClientType;
+
+ string name = cd.Name + "Channel";
+ if (name [0] == 'I')
+ name = name.Substring (1);
+
+ var gt = new CodeTypeReference (cd.Name);
+ var clientBaseType = new CodeTypeReference ("System.ServiceModel.ClientBase", gt);
+ // this omits namespace, but should compile
+ var channelBase = new CodeTypeReference ("ChannelBase", gt);
+ var type = new CodeTypeDeclaration (name);
+ parentClass.Members.Add (type);
+ type.BaseTypes.Add (channelBase);
+ type.BaseTypes.Add (new CodeTypeReference (cd.Name));
+ type.TypeAttributes |= TypeAttributes.NestedPrivate;
+
+ ml_context.ChannelType = type;
+
+ // .ctor(ClientBase<T> client)
+ var ctor = new CodeConstructor ();
+ ctor.Attributes = MemberAttributes.Public;
+ ctor.Parameters.Add (
+ new CodeParameterDeclarationExpression (
+ clientBaseType, "client"));
+ ctor.BaseConstructorArgs.Add (
+ new CodeArgumentReferenceExpression ("client"));
+ type.Members.Add (ctor);
+ }
+ }
+
+ class MoonlightChannelBaseOperationExtension : IOperationBehavior, IOperationContractGenerationExtension
+ {
+ public MoonlightChannelBaseOperationExtension (MoonlightChannelBaseContext mlContext)
+ {
+ ml_context = mlContext;
+ }
+
+ MoonlightChannelBaseContext ml_context;
+
+ // IOperationBehavior
+
+ public void AddBindingParameters (
+ OperationDescription description,
+ BindingParameterCollection parameters)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void ApplyDispatchBehavior (
+ OperationDescription description,
+ DispatchOperation dispatch)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void ApplyClientBehavior (
+ OperationDescription description,
+ ClientOperation proxy)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void Validate (
+ OperationDescription description)
+ {
+ throw new NotSupportedException ();
+ }
+
+ // IOperationContractGenerationContext
+
+ public void GenerateOperation (OperationContractGenerationContext context)
+ {
+ this.context = context;
+ ml_context.Operations.Add (this);
+ }
+
+ OperationContractGenerationContext context;
+
+ public void Fixup ()
+ {
+ var type = ml_context.ChannelType;
+ var od = context.Operation;
+
+ CodeMemberMethod cm = new CodeMemberMethod ();
+ type.Members.Add (cm);
+ cm.Name = "Begin" + od.Name;
+ cm.Attributes = MemberAttributes.Public
+ | MemberAttributes.Final;
+
+ var inArgs = new List<CodeParameterDeclarationExpression > ();
+ var outArgs = new List<CodeParameterDeclarationExpression > ();
+
+ foreach (CodeParameterDeclarationExpression p in context.BeginMethod.Parameters) {
+ inArgs.Add (p);
+ cm.Parameters.Add (p);
+ }
+ inArgs.RemoveAt (inArgs.Count - 1);
+ inArgs.RemoveAt (inArgs.Count - 1);
+
+// cm.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (AsyncCallback)), "asyncCallback"));
+// cm.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (object)), "userState"));
+ cm.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
+
+ var argsDecl = new CodeVariableDeclarationStatement (
+ typeof (object []),
+ "args",
+ new CodeArrayCreateExpression (typeof (object), inArgs.ConvertAll<CodeExpression> (decl => new CodeArgumentReferenceExpression (decl.Name)).ToArray ()));
+ cm.Statements.Add (argsDecl);
+
+ var args = new List<CodeExpression> ();
+ args.Add (new CodePrimitiveExpression (od.Name));
+ args.Add (new CodeVariableReferenceExpression ("args"));
+ args.Add (new CodeArgumentReferenceExpression ("asyncCallback"));
+ args.Add (new CodeArgumentReferenceExpression ("userState"));
+
+ CodeExpression call = new CodeMethodInvokeExpression (
+ new CodeBaseReferenceExpression (),
+ "BeginInvoke",
+ args.ToArray ());
+
+ if (cm.ReturnType.BaseType == "System.Void")
+ cm.Statements.Add (new CodeExpressionStatement (call));
+ else
+ cm.Statements.Add (new CodeMethodReturnStatement (call));
+
+ // EndXxx() implementation
+
+ cm = new CodeMemberMethod ();
+ cm.Attributes = MemberAttributes.Public
+ | MemberAttributes.Final;
+ type.Members.Add (cm);
+ cm.Name = "End" + od.Name;
+
+ var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
+ cm.Parameters.Add (res);
+
+ cm.ReturnType = context.EndMethod.ReturnType;
+
+ string resultArgName = "result";
+ argsDecl = new CodeVariableDeclarationStatement (
+ typeof (object []),
+ "args",
+ new CodeArrayCreateExpression (typeof (object), new CodePrimitiveExpression (outArgs.Count)));
+ cm.Statements.Add (argsDecl);
+
+ call = new CodeCastExpression (
+ context.EndMethod.ReturnType,
+ new CodeMethodInvokeExpression (
+ new CodeBaseReferenceExpression (),
+ "EndInvoke",
+ new CodePrimitiveExpression (od.Name),
+ new CodeVariableReferenceExpression ("args"),
+ new CodeArgumentReferenceExpression (resultArgName)));
+
+ if (cm.ReturnType.BaseType == "System.Void")
+ cm.Statements.Add (new CodeExpressionStatement (call));
+ else
+ cm.Statements.Add (new CodeMethodReturnStatement (call));
+ }
+ }
+}
Driver.cs
CommandLineOptions.cs
+MoonlightChannelBaseExtension.cs
+2009-08-13 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yProcessor.cs: Don't whitelist SC
+ attribs for base methods that are on our assembly.
+ This finally makes a11y work without security disabled. The
+ summary of the troubles encountered:
+ - GetHashCode() -> base method not SC. (r139589+r139649)
+ - Dispose() -> interface method not SC. (r139796)
+ - get_Handle() -> interface method SC while impl not SC. (this
+ commit)
+
+2009-08-12 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yProcessor.cs: Look for base methods
+ in interfaces as well.
+
+2009-08-11 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yDescriptorGenerator.cs: Yet another
+ blacklisted element (SW.dll is not linked).
+
+2009-08-11 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yDescriptorGenerator.cs: Blacklist
+ more stuff.
+
+2009-08-11 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yDescriptorGenerator.cs: Blacklist
+ our bridge.
+
+2009-08-10 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yProcessor.cs: Move FIXME to a better
+ place. Fix NRE.
+
+2009-08-07 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/MoonlightA11yProcessor.cs: Don't use var.
+ Remove debug spew.
+
+2009-08-07 Andrés G. Aragoneses <aaragoneses@novell.com>
+
+ * Mono.Tuner/InjectSecurityAttributes.cs: Make an enum
+ and a method protected.
+
+ * Mono.Tuner/MoonlightA11yProcessor.cs: Prevent
+ Type*Exceptions because of badly placed SC attrib on
+ methods.
+
+ * Mono.Tuner/MoonlightA11yDescriptorGenerator.cs: Typo in
+ comment.
+
2009-07-02 Jb Evain <jbevain@novell.com>
* Makefile: fix cecil's location.
Method,
}
- enum AttributeType {
+ protected enum AttributeType {
Critical,
SafeCritical,
}
}
}
- static bool HasSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
+ protected static bool HasSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
{
if (!provider.HasCustomAttributes)
return false;
XmlTextWriter writer = null;
protected override void ProcessAssembly (AssemblyDefinition assembly)
{
+ if (assembly.Name.Name == "MoonAtkBridge" || assembly.Name.Name == "System.Windows" ||
+ assembly.Name.Name.Contains ("Dummy"))
+ return;
+
if (writer == null) {
writer = new XmlTextWriter (System.Console.Out);
writer.Formatting = Formatting.Indented;
return @params;
}
- Hashtable /*Dictionary<TypeDefinition,List<IAnnotationProvider>>*/ ScanAssembly (AssemblyDefinition assembly)
+ Hashtable /*Dictionary<TypeDefinition,List<IAnnotationProvider>*/ ScanAssembly (AssemblyDefinition assembly)
{
if (Annotations.GetAction (assembly) != AssemblyAction.Link)
return null;
AddCriticalAttribute (ctor);
if (type.HasMethods)
- foreach (MethodDefinition method in type.Methods)
- AddCriticalAttribute (method);
+ foreach (MethodDefinition method in type.Methods) {
+ MethodDefinition parent = null;
+
+ //TODO: take in account generic params
+ if (!method.HasGenericParameters) {
+
+ /*
+ * we need to scan base methods because the CoreCLR complains about SC attribs added
+ * to overriden methods whose base (virtual or interface) method is not marked as SC
+ * with TypeLoadExceptions
+ */
+ parent = GetBaseMethod (type, method);
+ }
+
+ //if there's no base method
+ if (parent == null ||
+
+ //if it's our bridge assembly, we're sure it will (finally, at the end of the linking process) have the SC attrib
+ _assembly.MainModule.Types.Contains (parent.DeclaringType) ||
+
+ //if the type is in the moonlight assemblies, check if it has the SC attrib
+ HasSecurityAttribute (parent, AttributeType.Critical))
+
+ AddCriticalAttribute (method);
+ }
+
+ }
+ }
+
+ MethodDefinition GetBaseMethod (TypeDefinition finalType, MethodDefinition final)
+ {
+ // both GetOverridenMethod and GetInterfaceMethod return null if there is no base method
+ return GetOverridenMethod (finalType, final) ?? GetInterfaceMethod (finalType, final);
+ }
+
+ //note: will not return abstract methods
+ MethodDefinition GetOverridenMethod (TypeDefinition finalType, MethodDefinition final)
+ {
+ TypeReference baseType = finalType.BaseType;
+ while (baseType != null && baseType.Resolve () != null) {
+ foreach (MethodDefinition method in baseType.Resolve ().Methods) {
+ if (!method.IsVirtual || method.Name != final.Name)
+ continue;
+
+ //TODO: should we discard them?
+ if (method.IsAbstract)
+ continue;
+
+ if (HasSameSignature (method, final))
+ return method;
+ }
+ baseType = baseType.Resolve().BaseType;
}
+ return null;
}
+
+ MethodDefinition GetInterfaceMethod (TypeDefinition finalType, MethodDefinition final)
+ {
+ TypeDefinition baseType = finalType;
+ while (baseType != null) {
+ if (baseType.HasInterfaces)
+ foreach (TypeReference @interface in baseType.Interfaces)
+ foreach (MethodDefinition method in @interface.Resolve ().Methods)
+ if (method.Name == final.Name && HasSameSignature (method, final))
+ return method;
+
+ baseType = baseType.BaseType == null ? null : baseType.BaseType.Resolve ();
+ }
+ return null;
+ }
+
+ bool HasSameSignature (MethodDefinition method1, MethodDefinition method2)
+ {
+ if (method1.ReturnType.ReturnType.FullName != method2.ReturnType.ReturnType.FullName)
+ return false;
+
+ if (method1.Parameters.Count != method2.Parameters.Count)
+ return false;
+ for (int i = 0; i < method1.Parameters.Count; i++) {
+ if (method1.Parameters [i].ParameterType.FullName !=
+ method2.Parameters [i].ParameterType.FullName)
+ return false;
+ }
+
+ return true;
+ }
}
}
+2009-08-19 Ankit Jain <jankit@novell.com>
+
+ * xbuild/Microsoft.Common.targets (ResolveAssemblyReference):
+ Make SearchPaths get value from a property (AssemblySearchPaths)
+ to allow it to be overridden.
+
+2009-08-18 Ankit Jain <jankit@novell.com>
+
+ * SolutionParser.cs (ParseSolution): Project reference in a project
+ file, but not found in .sln file is ignored. Also, add dependencies
+ specified in the .sln file.
+
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ Fix bug #530368.
+ * SolutionParser.cs (AddProjectTargets): If a project name matches one
+ of the targets that we emit (Build/Clean etc), then rename to
+ "Solution:<project name>".
+
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * xbuild/Microsoft.Common.targets (AllowUnsafeBlocks): Don't set any
+ default value.
+ (OutputPath): Set a default value.
+ (DeployOutputFiles): Copy only if something available to copy.
+
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * SolutionParser.cs (ProjectInfo.Dependencies): Change to a dictionary
+ to keep track of corresponding ProjectInfo objects.
+ (ParseSolution): Refactor to populate the ProjectInfo.Dependencies
+ dictionary. Use AddBuildLevels to emit build levels to allow
+ parallel builds.
+ (AddProjectTargets): Dependency's projectInfo is directly available now.
+ (AddBuildLevels): New. Emit items named BuildLevelN, where each level
+ has projects that can be built in parallel. Lower levels represent
+ dependencies for higher levels.
+ (AddSolutionTargets): Instead of using CallTarget, directly use MSBuild
+ task with the new BuildLevelN stuff. Also tell the user about disabled
+ projects or missing project configs.
+ (TopologicalSort): New.
+ (Insert): New. Based on code from monodevelop.
+
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * xbuild/Microsoft.Common.targets (ResolveAssemblyReference): Add
+ '{PkgConfig}' to SearchPaths.
+
2009-07-31 Ankit Jain <jankit@novell.com>
* ErrorUtilities.cs (ShowUsage): Implement.
static string[] version = {
String.Format ("XBuild Engine Version {0}", Consts.MonoVersion),
String.Format ("Mono, Version {0}", Consts.MonoVersion),
- "Copyright (C) Marek Sieradzki 2005. All rights reserved.",
+ "Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2009.",
};
//
// Author:
// Jonathan Chambers (joncham@gmail.com)
+// Ankit Jain <jankit@novell.com>
+// Lluis Sanchez Gual <lluis@novell.com>
//
// (C) 2009 Jonathan Chambers
+// Copyright 2008, 2009 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
}
public Dictionary<TargetInfo, TargetInfo> TargetMap = new Dictionary<TargetInfo, TargetInfo> ();
- public List<Guid> Dependencies = new List<Guid> ();
+ public Dictionary<Guid, ProjectInfo> Dependencies = new Dictionary<Guid, ProjectInfo> ();
}
struct TargetInfo {
projectInfos.Add (new Guid (m.Groups[4].Value), projectInfo);
- Project currentProject = p.ParentEngine.CreateNewProject ();
- currentProject.Load (Path.Combine (solutionDir,
- projectInfo.FileName.Replace ('\\', Path.DirectorySeparatorChar)));
-
- foreach (BuildItem bi in currentProject.GetEvaluatedItemsByName ("ProjectReference")) {
- string projectReferenceGuid = bi.GetEvaluatedMetadata ("Project");
- projectInfo.Dependencies.Add (new Guid (projectReferenceGuid));
- }
-
Match projectSectionMatch = projectDependenciesRegex.Match (m.Groups[6].Value);
while (projectSectionMatch.Success) {
Match projectDependencyMatch = projectDependencyRegex.Match (projectSectionMatch.Value);
while (projectDependencyMatch.Success) {
- projectInfo.Dependencies.Add (new Guid (projectDependencyMatch.Groups[1].Value));
+ // we might not have projectInfo available right now, so
+ // set it to null, and fill it in later
+ projectInfo.Dependencies [new Guid (projectDependencyMatch.Groups[1].Value)] = null;
projectDependencyMatch = projectDependencyMatch.NextMatch ();
}
projectSectionMatch = projectSectionMatch.NextMatch ();
m = m.NextMatch ();
}
+ foreach (ProjectInfo projectInfo in projectInfos.Values) {
+ Project currentProject = p.ParentEngine.CreateNewProject ();
+ currentProject.Load (Path.Combine (solutionDir,
+ projectInfo.FileName.Replace ('\\', Path.DirectorySeparatorChar)));
+
+ foreach (BuildItem bi in currentProject.GetEvaluatedItemsByName ("ProjectReference")) {
+ string projectReferenceGuid = bi.GetEvaluatedMetadata ("Project");
+ Guid guid = new Guid (projectReferenceGuid);
+ ProjectInfo info = projectInfos [guid];
+ if (info != null)
+ // ignore if not found
+ projectInfo.Dependencies [guid] = info;
+ }
+ }
+
+ // fill in the project info for deps found in the .sln file
+ foreach (ProjectInfo projectInfo in projectInfos.Values) {
+ List<Guid> missingInfos = new List<Guid> ();
+ foreach (KeyValuePair<Guid, ProjectInfo> dependency in projectInfo.Dependencies) {
+ if (dependency.Value == null)
+ missingInfos.Add (dependency.Key);
+ }
+
+ foreach (Guid guid in missingInfos) {
+ ProjectInfo info;
+ if (projectInfos.TryGetValue (guid, out info))
+ projectInfo.Dependencies [guid] = info;
+ else
+ projectInfo.Dependencies.Remove (guid);
+ }
+ }
+
Match globalMatch = globalRegex.Match (line);
Match globalSectionMatch = globalSectionRegex.Match (globalMatch.Groups[1].Value);
while (globalSectionMatch.Success) {
globalSectionMatch = globalSectionMatch.NextMatch ();
}
+ int num_levels = AddBuildLevels (p, solutionTargets, projectInfos);
+
AddCurrentSolutionConfigurationContents (p, solutionTargets, projectInfos);
AddValidateSolutionConfiguration (p);
AddProjectTargets (p, solutionTargets, projectInfos);
- AddSolutionTargets (p, projectInfos);
-
+ AddSolutionTargets (p, num_levels);
}
void AddGeneralSettings (string solutionFile, Project p)
foreach (KeyValuePair<Guid, ProjectInfo> projectInfo in projectInfos) {
ProjectInfo project = projectInfo.Value;
foreach (string buildTarget in buildTargets) {
- Target target = p.Targets.AddNewTarget (project.Name + (buildTarget == "Build" ? string.Empty : ":" + buildTarget));
+ string target_name = project.Name +
+ (buildTarget == "Build" ? string.Empty : ":" + buildTarget);
+
+ if (IsBuildTargetName (project.Name))
+ target_name = "Solution:" + target_name;
+
+ Target target = p.Targets.AddNewTarget (target_name);
target.Condition = "'$(CurrentSolutionConfigurationContents)' != ''";
- string dependencies = string.Empty;
- foreach (Guid dependency in project.Dependencies) {
- ProjectInfo dependentInfo;
- if (projectInfos.TryGetValue (dependency, out dependentInfo)) {
+
+ if (project.Dependencies.Count > 0) {
+ StringBuilder dependencies = new StringBuilder ();
+ foreach (ProjectInfo dependentInfo in project.Dependencies.Values) {
if (dependencies.Length > 0)
- dependencies += ";";
- dependencies += dependentInfo.Name;
+ dependencies.Append (";");
+ if (IsBuildTargetName (dependentInfo.Name))
+ dependencies.Append ("Solution:");
+ dependencies.Append (dependentInfo.Name);
if (buildTarget != "Build")
- dependencies += ":" + buildTarget;
+ dependencies.Append (":" + buildTarget);
}
+ target.DependsOnTargets = dependencies.ToString ();
}
- if (dependencies != string.Empty)
- target.DependsOnTargets = dependencies;
foreach (TargetInfo targetInfo in solutionTargets) {
BuildTask task = null;
if (projectTargetInfo.Build) {
task = target.AddNewTask ("MSBuild");
task.SetParameterValue ("Projects", project.FileName);
-
+
if (buildTarget != "Build")
task.SetParameterValue ("Targets", buildTarget);
task.SetParameterValue ("Properties", string.Format ("Configuration={0}; Platform={1}; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)", projectTargetInfo.Configuration, projectTargetInfo.Platform));
}
}
- void AddSolutionTargets (Project p, Dictionary<Guid, ProjectInfo> projectInfos)
+ bool IsBuildTargetName (string name)
+ {
+ foreach (string tgt in buildTargets)
+ if (name == tgt)
+ return true;
+ return false;
+ }
+
+ // returns number of levels
+ int AddBuildLevels (Project p, List<TargetInfo> solutionTargets, Dictionary<Guid, ProjectInfo> projectInfos)
+ {
+ List<ProjectInfo>[] infosByLevel = TopologicalSort<ProjectInfo> (projectInfos.Values);
+
+ foreach (TargetInfo targetInfo in solutionTargets) {
+ BuildItemGroup big = p.AddNewItemGroup ();
+ big.Condition = String.Format (" ('$(Configuration)' == '{0}') and ('$(Platform)' == '{1}') ",
+ targetInfo.Configuration, targetInfo.Platform);
+
+ //FIXME: every level has projects that can be built in parallel.
+ // levels are ordered on the basis of the dependency graph
+
+ for (int i = 0; i < infosByLevel.Length; i ++) {
+ string build_level = String.Format ("BuildLevel{0}", i);
+ string skip_level = String.Format ("SkipLevel{0}", i);
+ string missing_level = String.Format ("MissingConfigLevel{0}", i);
+
+ foreach (ProjectInfo projectInfo in infosByLevel [i]) {
+ TargetInfo projectTargetInfo;
+ if (!projectInfo.TargetMap.TryGetValue (targetInfo, out projectTargetInfo)) {
+ // missing project config
+ big.AddNewItem (missing_level, projectInfo.Name);
+ continue;
+ }
+
+ if (projectTargetInfo.Build) {
+ BuildItem item = big.AddNewItem (build_level, projectInfo.FileName);
+ item.SetMetadata ("Configuration", projectTargetInfo.Configuration);
+ item.SetMetadata ("Platform", projectTargetInfo.Platform);
+ } else {
+ // build disabled
+ big.AddNewItem (skip_level, projectInfo.Name);
+ }
+ }
+ }
+ }
+
+ return infosByLevel.Length;
+ }
+
+ void AddSolutionTargets (Project p, int num_levels)
{
foreach (string buildTarget in buildTargets) {
Target t = p.Targets.AddNewTarget (buildTarget);
t.Condition = "'$(CurrentSolutionConfigurationContents)' != ''";
- BuildTask task = t.AddNewTask ("CallTarget");
- string targets = string.Empty;
- foreach (KeyValuePair<Guid, ProjectInfo> projectInfo in projectInfos) {
- if (targets.Length > 0)
- targets += ";";
- targets += projectInfo.Value.Name;
+
+ for (int i = 0; i < num_levels; i ++) {
+ string level_str = String.Format ("BuildLevel{0}", i);
+ BuildTask task = t.AddNewTask ("MSBuild");
+ task.SetParameterValue ("Condition", String.Format ("'@({0})' != ''", level_str));
+ task.SetParameterValue ("Projects", String.Format ("@({0})", level_str));
+ task.SetParameterValue ("Properties",
+ string.Format ("Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)"));
if (buildTarget != "Build")
- targets += ":" + buildTarget;
+ task.SetParameterValue ("Targets", buildTarget);
+ //FIXME: change this to BuildInParallel=true, when parallel
+ // build support gets added
+ task.SetParameterValue ("RunEachTargetSeparately", "true");
+
+ level_str = String.Format ("SkipLevel{0}", i);
+ task = t.AddNewTask ("Message");
+ task.Condition = String.Format ("'@({0})' != ''", level_str);
+ task.SetParameterValue ("Text",
+ String.Format ("The project '%({0}.Identity)' is disabled for solution " +
+ "configuration '$(Configuration)|$(Platform)'.", level_str));
+
+ level_str = String.Format ("MissingConfigLevel{0}", i);
+ task = t.AddNewTask ("Warning");
+ task.Condition = String.Format ("'@({0})' != ''", level_str);
+ task.SetParameterValue ("Text",
+ String.Format ("The project configuration for project '%({0}.Identity)' " +
+ "corresponding to the solution configuration " +
+ "'$(Configuration)|$(Platform)' was not found.", level_str));
}
- task.SetParameterValue ("Targets", targets);
- task.SetParameterValue ("RunEachTargetSeparately", "true");
}
}
+
+ // Sorts the ProjectInfo dependency graph, to obtain
+ // a series of build levels with projects. Projects
+ // in each level can be run parallel (no inter-dependency).
+ static List<T>[] TopologicalSort<T> (IEnumerable<T> items) where T: ProjectInfo
+ {
+ IList<T> allItems;
+ allItems = items as IList<T>;
+ if (allItems == null)
+ allItems = new List<T> (items);
+
+ bool[] inserted = new bool[allItems.Count];
+ bool[] triedToInsert = new bool[allItems.Count];
+ int[] levels = new int [allItems.Count];
+
+ int maxdepth = 0;
+ for (int i = 0; i < allItems.Count; ++i) {
+ int d = Insert<T> (i, allItems, levels, inserted, triedToInsert);
+ if (d > maxdepth)
+ maxdepth = d;
+ }
+
+ // Separate out the project infos by build level
+ List<T>[] infosByLevel = new List<T>[maxdepth];
+ for (int i = 0; i < levels.Length; i ++) {
+ int level = levels [i] - 1;
+ if (infosByLevel [level] == null)
+ infosByLevel [level] = new List<T> ();
+
+ infosByLevel [level].Add (allItems [i]);
+ }
+
+ return infosByLevel;
+ }
+
+ // returns level# for the project
+ static int Insert<T> (int index, IList<T> allItems, int[] levels, bool[] inserted, bool[] triedToInsert)
+ where T: ProjectInfo
+ {
+ if (inserted [index])
+ return levels [index];
+
+ if (triedToInsert[index])
+ throw new InvalidOperationException ("Cyclic dependency found in the project dependency graph");
+
+ triedToInsert[index] = true;
+ ProjectInfo insertItem = allItems[index];
+
+ int maxdepth = 0;
+ foreach (ProjectInfo dependency in insertItem.Dependencies.Values) {
+ for (int j = 0; j < allItems.Count; ++j) {
+ ProjectInfo checkItem = allItems [j];
+ if (dependency.FileName == checkItem.FileName) {
+ int d = Insert (j, allItems, levels, inserted, triedToInsert);
+ maxdepth = d > maxdepth ? d : maxdepth;
+ break;
+ }
+ }
+ }
+ levels [index] = maxdepth + 1;
+ inserted [index] = true;
+
+ return levels [index];
+ }
}
}
+2009-08-14 Ankit Jain <jankit@novell.com>
+
+ * standalone/Project01: Update .sln.proj file.
+
2009-07-30 Ankit Jain <jankit@novell.com>
* standalone/Project01/final-outputs.txt: Update to include obj/
<SolutionName>Project01</SolutionName>
<SolutionPath>/home/radical/w1/mcs/tools/xbuild/tests/standalone/Project01/Project01.sln</SolutionPath>
</PropertyGroup>
+ <ItemGroup Condition=" ('$(Configuration)' == 'Debug') and ('$(Platform)' == 'Any CPU') ">
+ <BuildLevel0 Include="Lib3\Lib3.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel0>
+ <BuildLevel0 Include="Lib4\Lib4.csproj">
+ <Configuration>Debug</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel0>
+ <BuildLevel1 Include="Lib2\Lib2.csproj">
+ <Configuration>Debug</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel1>
+ <BuildLevel2 Include="Lib1\Lib1.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel2>
+ <BuildLevel3 Include="Project01\Main.csproj">
+ <Configuration>Debug</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel3>
+ </ItemGroup>
+ <ItemGroup Condition=" ('$(Configuration)' == 'Release') and ('$(Platform)' == 'Any CPU') ">
+ <BuildLevel0 Include="Lib3\Lib3.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel0>
+ <BuildLevel0 Include="Lib4\Lib4.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel0>
+ <BuildLevel1 Include="Lib2\Lib2.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel1>
+ <BuildLevel2 Include="Lib1\Lib1.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel2>
+ <BuildLevel3 Include="Project01\Main.csproj">
+ <Configuration>Release</Configuration>
+ <Platform>AnyCPU</Platform>
+ </BuildLevel3>
+ </ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == '' ">
<Configuration>Debug</Configuration>
</PropertyGroup>
<MSBuild Projects="Lib4\Lib4.csproj" Targets="Publish" Properties="Configuration=Release; Platform=AnyCPU; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Condition=" ('$(Configuration)' == 'Release') and ('$(Platform)' == 'Any CPU') " />
</Target>
<Target Name="Build" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
- <CallTarget Targets="Main;Lib1;Lib2;Lib3;Lib4" RunEachTargetSeparately="true" />
+ <MSBuild Condition="'@(BuildLevel0)' != ''" Projects="@(BuildLevel0)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel0)' != ''" Text="The project '%(SkipLevel0.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel0)' != ''" Text="The project configuration for project '%(MissingConfigLevel0.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel1)' != ''" Projects="@(BuildLevel1)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel1)' != ''" Text="The project '%(SkipLevel1.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel1)' != ''" Text="The project configuration for project '%(MissingConfigLevel1.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel2)' != ''" Projects="@(BuildLevel2)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel2)' != ''" Text="The project '%(SkipLevel2.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel2)' != ''" Text="The project configuration for project '%(MissingConfigLevel2.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel3)' != ''" Projects="@(BuildLevel3)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel3)' != ''" Text="The project '%(SkipLevel3.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel3)' != ''" Text="The project configuration for project '%(MissingConfigLevel3.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
</Target>
<Target Name="Clean" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
- <CallTarget Targets="Main:Clean;Lib1:Clean;Lib2:Clean;Lib3:Clean;Lib4:Clean" RunEachTargetSeparately="true" />
+ <MSBuild Condition="'@(BuildLevel0)' != ''" Projects="@(BuildLevel0)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Clean" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel0)' != ''" Text="The project '%(SkipLevel0.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel0)' != ''" Text="The project configuration for project '%(MissingConfigLevel0.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel1)' != ''" Projects="@(BuildLevel1)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Clean" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel1)' != ''" Text="The project '%(SkipLevel1.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel1)' != ''" Text="The project configuration for project '%(MissingConfigLevel1.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel2)' != ''" Projects="@(BuildLevel2)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Clean" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel2)' != ''" Text="The project '%(SkipLevel2.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel2)' != ''" Text="The project configuration for project '%(MissingConfigLevel2.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel3)' != ''" Projects="@(BuildLevel3)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Clean" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel3)' != ''" Text="The project '%(SkipLevel3.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel3)' != ''" Text="The project configuration for project '%(MissingConfigLevel3.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
</Target>
<Target Name="Rebuild" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
- <CallTarget Targets="Main:Rebuild;Lib1:Rebuild;Lib2:Rebuild;Lib3:Rebuild;Lib4:Rebuild" RunEachTargetSeparately="true" />
+ <MSBuild Condition="'@(BuildLevel0)' != ''" Projects="@(BuildLevel0)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Rebuild" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel0)' != ''" Text="The project '%(SkipLevel0.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel0)' != ''" Text="The project configuration for project '%(MissingConfigLevel0.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel1)' != ''" Projects="@(BuildLevel1)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Rebuild" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel1)' != ''" Text="The project '%(SkipLevel1.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel1)' != ''" Text="The project configuration for project '%(MissingConfigLevel1.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel2)' != ''" Projects="@(BuildLevel2)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Rebuild" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel2)' != ''" Text="The project '%(SkipLevel2.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel2)' != ''" Text="The project configuration for project '%(MissingConfigLevel2.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel3)' != ''" Projects="@(BuildLevel3)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Rebuild" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel3)' != ''" Text="The project '%(SkipLevel3.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel3)' != ''" Text="The project configuration for project '%(MissingConfigLevel3.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
</Target>
<Target Name="Publish" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
- <CallTarget Targets="Main:Publish;Lib1:Publish;Lib2:Publish;Lib3:Publish;Lib4:Publish" RunEachTargetSeparately="true" />
+ <MSBuild Condition="'@(BuildLevel0)' != ''" Projects="@(BuildLevel0)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Publish" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel0)' != ''" Text="The project '%(SkipLevel0.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel0)' != ''" Text="The project configuration for project '%(MissingConfigLevel0.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel1)' != ''" Projects="@(BuildLevel1)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Publish" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel1)' != ''" Text="The project '%(SkipLevel1.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel1)' != ''" Text="The project configuration for project '%(MissingConfigLevel1.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel2)' != ''" Projects="@(BuildLevel2)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Publish" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel2)' != ''" Text="The project '%(SkipLevel2.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel2)' != ''" Text="The project configuration for project '%(MissingConfigLevel2.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
+ <MSBuild Condition="'@(BuildLevel3)' != ''" Projects="@(BuildLevel3)" Properties="Configuration=%(Configuration); Platform=%(Platform); BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Targets="Publish" RunEachTargetSeparately="true" />
+ <Message Condition="'@(SkipLevel3)' != ''" Text="The project '%(SkipLevel3.Identity)' is disabled for solution configuration '$(Configuration)|$(Platform)'." />
+ <Warning Condition="'@(MissingConfigLevel3)' != ''" Text="The project configuration for project '%(MissingConfigLevel3.Identity)' corresponding to the solution configuration '$(Configuration)|$(Platform)' was not found." />
</Target>
</Project>
\ No newline at end of file
</PropertyGroup>
<PropertyGroup>
- <AllowUnsafeBlocks Condition="'$(AllowUnsafeBlocks)' == ''">false</AllowUnsafeBlocks>
<AssemblyName Condition="'$(AssemblyName)' == ''">$(RootNamespace)</AssemblyName>
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
+ <OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
</PropertyGroup>
<AllowedReferenceRelatedFileExtensions Condition=" '$(AllowedReferenceRelatedFileExtensions)' == '' ">
.mdb
</AllowedReferenceRelatedFileExtensions>
+
+ <AssemblySearchPaths Condition="'$(AssemblySearchPaths)' == ''">
+ {CandidateAssemblyFiles};
+ {HintPathFromItem};
+ {TargetFrameworkDirectory};
+ {PkgConfig};
+ {GAC};
+ {RawFileName};
+ $(OutDir)
+ </AssemblySearchPaths>
</PropertyGroup>
<Target Name="ResolveAssemblyReferences">
<ResolveAssemblyReference
Assemblies="@(Reference)"
AssemblyFiles="@(ChildProjectReferences)"
- SearchPaths="{CandidateAssemblyFiles};{HintPathFromItem};{TargetFrameworkDirectory};{GAC};{RawFileName};$(OutDir)"
+ SearchPaths="$(AssemblySearchPaths)"
CandidateAssemblyFiles="@(Content);@(None)"
TargetFrameworkDirectories="$(TargetFrameworkPath)"
AllowedAssemblyExtensions="$(AllowedReferenceAssemblyFileExtensions)"
<Copy
SourceFiles = "@(IntermediateSatelliteAssemblies)"
DestinationFiles = "@(IntermediateSatelliteAssemblies->'$(OutDir)\%(Culture)\$(AssemblyName).resources.dll')"
+ Condition = "'@(IntermediateSatelliteAssemblies)' != ''"
SkipUnchangedFiles="true">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
<Copy SourceFiles="@(ItemsToCopyToOutputDirectoryAlways)"
DestinationFiles="@(ItemsToCopyToOutputDirectoryAlways->'$(OutDir)%(TargetPath)')">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
- <Output TaskParameter="DestinationFiles" ItemName="FileWrites2"/>
</Copy>
</Target>
+2009-08-14 Zoltan Varga <vargaz@gmail.com>
+
+ * arm/arm-codegen.h: Add armv6 MOVW/MOVT.
+
2009-07-03 Jerry Maine <crashfourit@gmail.com>
Contributed under the terms of the MIT/X11 license by
arminstr_t raw;
} ARMInstr;
+/* ARMv6t2 */
+
+#define ARM_MOVW_REG_IMM_COND(p, rd, imm16, cond) ARM_EMIT(p, (((cond) << 28) | (3 << 24) | (0 << 20) | ((((guint32)(imm16)) >> 12) << 16) | ((rd) << 12) | (((guint32)(imm16)) & 0xfff)))
+#define ARM_MOVW_REG_IMM(p, rd, imm16) ARM_MOVW_REG_IMM_COND ((p), (rd), (imm16), ARMCOND_AL)
+
+#define ARM_MOVT_REG_IMM_COND(p, rd, imm16, cond) ARM_EMIT(p, (((cond) << 28) | (3 << 24) | (4 << 20) | ((((guint32)(imm16)) >> 12) << 16) | ((rd) << 12) | (((guint32)(imm16)) & 0xfff)))
+#define ARM_MOVT_REG_IMM(p, rd, imm16) ARM_MOVT_REG_IMM_COND ((p), (rd), (imm16), ARMCOND_AL)
#ifdef __cplusplus
}
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * dis-cil.c:
+ * main.c: Fix printf warnings.
+
2009-07-16 Raja R Harinath <harinath@hurrynot.org>
* get.c (get_type): Make robust to invalid types.
fprintf (output, "(00 00 00 00 00 00 f8 ff)"); /* NaN */
else {
char *str = stringify_double (r);
- fprintf (output, str);
+ fprintf (output, "%s", str);
g_free (str);
}
ptr += 8;
fprintf (output, "(00 00 c0 ff)"); /* NaN */
else {
char *str = stringify_double ((double) f);
- fprintf (output, str);
+ fprintf (output, "%s", str);
g_free (str);
}
ptr += 4;
param = get_generic_param (m, container);
if (param) {
- fprintf (output, param);
+ fprintf (output, "%s", param);
g_free (param);
}
fprintf (output, "\n");
param = get_generic_param (m, container);
if (param) {
- fprintf (output, param);
+ fprintf (output, "%s", param);
g_free (param);
}
fprintf (output, "\n");
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * wthreads.c: Roll back change for thread-id as it "embraces
+ and extends" the api by passing word-size for thread id on
+ s390 and amd64.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * security.c:
+ * processes.c:
+ * wthreads.c: Be explicit when we are changing word sizes.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * processes.c: Fix method declaration warnings.
+ * sockets.c: getsockopt() wants socklen_t for size.
+
2009-08-04 Miguel de Icaza <miguel@novell.com>
* posix.c (_wapi_stdhandle_create): Split this into a new file to
* arm-apple-darwin9. We'll manually define the symbol on Apple as it does
* in fact exist on all implementations (so far)
*/
-gchar ***_NSGetEnviron();
+gchar ***_NSGetEnviron(void);
#define environ (*_NSGetEnviron())
#else
extern char **environ;
static int osx_10_5_or_higher;
static void
-detect_osx_10_5_or_higher ()
+detect_osx_10_5_or_higher (void)
{
struct utsname u;
char *p;
}
static gboolean
-is_macos_10_5_or_higher ()
+is_macos_10_5_or_higher (void)
{
if (osx_10_5_or_higher == 0)
detect_osx_10_5_or_higher ();
/* Return a pseudo handle for processes we
* don't have handles for
*/
- return((gpointer)(_WAPI_PROCESS_UNHANDLED + pid));
+ return GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + pid);
} else {
#ifdef DEBUG
g_message ("%s: Can't find pid %d", __func__, pid);
#ifdef PLATFORM_MACOSX
#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
-static GSList *load_modules ()
+static GSList *load_modules (void)
{
GSList *ret = NULL;
WapiProcModule *mod;
sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
mod = g_new0 (WapiProcModule, 1);
- mod->address_start = sec->addr;
- mod->address_end = sec->addr+sec->size;
+ mod->address_start = GINT_TO_POINTER (sec->addr);
+ mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
mod->perms = g_strdup ("r--p");
mod->address_offset = 0;
mod->device = makedev (0, 0);
gboolean
ImpersonateLoggedOnUser (gpointer handle)
{
- uid_t token = (uid_t) handle;
+ uid_t token = (uid_t) GPOINTER_TO_INT (handle);
#ifdef HAVE_SETRESUID
if (setresuid (-1, token, getuid ()) < 0)
return FALSE;
/* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
int type;
- int type_len = sizeof (type);
+ socklen_t type_len = sizeof (type);
if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
if (type == SOCK_DGRAM)
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * class.c (mono_class_get_field_idx): Add fixme for broken
+ behavior for types with multiple fields with the same name.
+ I would rather fix it, but have no idea on how to generate
+ such artifact for testing.
+
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * verify.c (verifier_load_field): We should allow references to
+ fields to be made using the generic type definition. It's up to
+ the loader system to fail invalid ops.
+
+ * verify.c (get_boxable_mono_type): Only uninstantiated GTDs
+ are invalid.
+
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * class.c: Fix usage of mono_metadata_interfaces_from_typedef_full.
+
+ * metadata-internals.h: Fix declaration of
+ mono_metadata_interfaces_from_typedef_full.
+
+ * metadata.c (mono_metadata_interfaces_from_typedef_full): Add extra
+ heap_alloc_result parameter that controls if the result should be
+ g_malloc'd.
+
+ * metadata.c (mono_metadata_interfaces_from_typedef): Let the resulting
+ array be g_malloc'd and properly document this public API function.
+
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * cil-coff.h: Fix METHOD_HEADER_FORMAT_MASK to be 2 bits and
+ remove METHOD_HEADER_TINY_FORMAT1.
+
+ * reflection.c: Remove reference to METHOD_HEADER_TINY_FORMAT1.
+
+ * metadata.c (mono_metadata_parse_mh_full): Kill tiny format1.
+
+ Both spec and MS uses only 2 bits to enumerate the kind of header.
+ So given that 0x6 and 0x2 are equal under a 2 bits mask, tiny format1
+ is superfluous, only used for tiny headers with odd code lengths.
+
+ This change also make sure that mono doesn't wronly interpret bit 2
+ of fat header flags, which is currently reserved.
+
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * metadata.c (do_mono_metadata_parse_type): Do error
+ checking for element types. Don't abort if presented
+ with a broken type kind.
+
+2009-08-18 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * metadata.c (mono_metadata_parse_method_signature_full):
+ Gracefully fail bad vararg signatures.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * profiler.c:
+ * class.c: Fix warnings for uninitialized variables.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * icall.c: Fix _NSGetEnviron method declaration warning.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * icall.c:
+ * reflection.c: Make bitwise checks explicit.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * debug-helpers.c:
+ * marshal.c: Fix printf warnings.
+
+2009-08-18 Zoltan Varga <vargaz@gmail.com>
+
+ * reflection.c (encode_cattr_value): Fix a warning.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * metadata.c (mono_metadata_parse_array_full): Fix memory leak
+ of array bounds.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_method_signature): Don't assert on broken
+ signature. Print a more useful error message.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_method_get_marshal_info): Assert if
+ signature is invalid. Bounds check stores to the
+ mspecs array;
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (field_from_memberref): Fix warning.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_method_get_param_names): Check if signature
+ is null. Don't store beyond the size of the name array.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_get_method_constrained): Check if signature
+ is null.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_loader_set_error_bad_image): Improve
+ error messages.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_get_method_full): Convert an assertion
+ into a loader error.
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * class-internals.h, class.c: Better naming and documentation.
+
+2009-08-17 Zoltan Varga <vargaz@gmail.com>
+
+ * boehm-gc.c (mono_gc_add_weak_track_handle): Don't do any work if
+ obj is NULL.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_method_get_signature_full): Fail gracefully if signature
+ parsing fails.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (mono_loader_error_prepare_exception): Handle missing field
+ errors with no class set.
+
+ * loader.c (field_from_memberref): If the field signature is of the wrong
+ type fail with a MissingFieldException instead of a BadImageException as
+ this is the behavior observed on MS.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * loader.c (field_from_memberref): Don't crash if either the field
+ signature or the typespec class are invalid.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * verify.c (verifier_load_field): Don't allow field related
+ ops to reference fields on generic type definition.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * metadata-verify.c: Add new warning level for errors specified
+ by ECMA 335 but that MS ignores.
+
+ * metadata-verify.c (verify_method_table): Make compiler controled
+ visibility + (rt)specialname error a warning as MS ignores this. Ignoring
+ this check is safe because the end result will only be some visibility
+ exceptions been thrown.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * verify.c (get_boxable_mono_type): Don't allow the
+ use of the generic type definition on boxed type positions.
+
+ Fixes #531237.
+
+2009-08-14 Mark Probst <mark.probst@gmail.com>
+
+ * threadpool.c: Make sure no cross-domain references remain in
+ ares_htable or the arrays that are thrown away when resizing.
+
+2009-08-14 Mark Probst <mark.probst@gmail.com>
+
+ * appdomain.c, metadata-internals.h, image.c: In MonoImage add a
+ list of classes for which we have to unregister reflection_info
+ with the GC and which are not in the namespace cache.
+
+ * reflection.c (mono_reflection_initialize_generic_parameter): Add
+ the class to the list.
+
+2009-08-14 Mark Probst <mark.probst@gmail.com>
+
+ * domain.c (mono_domain_free): Unregister the GC roots in
+ MonoDomain.
+
+2009-08-12 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * reflection.c (mono_reflection_type_get_handle): Fix typo.
+
+2009-08-12 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * class.c: Add mono_class_get_field_from_name_full which does
+ the same as mono_class_get_field_from_name but does check field
+ signature as well.
+
+ * class-internals.h: Export mono_class_get_field_from_name_full as
+ part of the internal API.
+
+ * loader.c (field_from_memberref): Search fields by name and signature
+ as it's valid to have two fields with same name but different types.
+
+ Fixes #528055.
+
+2009-08-10 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * icall-def.h: Add a bunch of temporary icalls to MonoGenericClass.
+
+ * reflection.c (mono_reflection_type_get_handle): Handle MonoGenericClass.
+
+ * reflection.c (encode_cattr_value): Use mono_reflection_type_get_handle to encode
+ System.Type.
+
+2009-08-13 Zoltan Varga <vargaz@gmail.com>
+
+ * gc.c (GCHandle_CheckCurrentDomain): Moved this here from icall.c.
+
+ * boehm-gc.c (mono_gc_add_weak_track_handle): Handle nulls.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * sgen-gc.c, sgen-scan-object.h: Object scanning code factored out
+ to sgen-scan-object.h, which can be included and parameterized via
+ macros.
+
+ * Makefile.am: sgen-scan-object.h added.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * gc.c: #define GC_dont_gc if we're compiling with SGen.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * domain.c (mono_domain_free): Free a domain's mono_g_hash_tables
+ before clearing a domain in the GC.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * exception.c (mono_exception_from_name_domain): Actually create
+ the exception in the specified domain.
+
+ * appdomain.c (mono_domain_create_appdomain_internal): Create the
+ OutOfMemoryException a bit later so that the domain is inialized
+ "enough" that it works.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * threads.c (thread_cleanup): Clean up the cached_culture_info
+ array to prevent cross-domain references.
+
+Tue Aug 11 14:38:57 CEST 2009 Paolo Molaro <lupus@ximian.com>
+
+ * metadata.c: more documentation for MonoType accessors.
+
+2009-08-11 Raja R Harinath <harinath@hurrynot.org>
+
+ Fix incorrect size definitions where the tail array isn't a list
+ of pointers
+ * class-internals.h (MONO_SIZEOF_MARSHAL_TYPE): Use offsetof to
+ define size.
+ * domain-internals.h (MONO_SIZEOF_JIT_INFO): Likewise.
+ * metadata.h (MONO_SIZEOF_TYPE): Likewise.
+ * reflection.h (MONO_SIZEOF_CUSTOM_ATTR_INFO): Likewise.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * reflection.h:
+ * reflection.c: MONO_SIZEOF_CUSTOM_ATTR_INFO.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * metadata.c:
+ * loader.c:
+ * metadata-internals.h:
+ * method-builder.c:
+ * reflection.c: use MONO_SIZEOF_METHOD_HEADER.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * cominterop.c:
+ * metadata.c:
+ * metadata.h:
+ * loader.c:
+ * marshal.c:
+ * reflection.c: #define for sizeof in MonoType and
+ MonoMethodSignature.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * domain.c:
+ * domain-internals.h: add and use #define's instead of sizeof()
+ for MonoJitInfo and MonoJitInfoTable.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * object.c:
+ * class.h: use #define instead of sizeof() for MonoRemoteClass.
+
+2009-08-10 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * metadata.c:
+ * metadata.h:
+ * object.c:
+ * class-internals.h:
+ * generic-sharing.c:
+ * marshal.c: use a #define instead of sizeof() for a few
+ structures that use a zero-length array.
+
2009-08-06 Rodrigo Kumpera <rkumpera@novell.com>
* object-internals.h (MonoReflectionMethodOnTypeBuilderInst): Add new fields
sgen-gc.c \
sgen-gc.h \
sgen-archdep.h \
+ sgen-scan-object.h \
string-icalls.c \
string-icalls.h \
sysmath.h \
data->domain = ad;
data->setup = setup;
data->friendly_name = g_strdup (friendly_name);
- // FIXME: The ctor runs in the current domain
- // FIXME: Initialize null_reference_ex and stack_overflow_ex
- data->out_of_memory_ex = mono_exception_from_name_domain (data, mono_defaults.corlib, "System", "OutOfMemoryException");
if (!setup->application_base) {
/* Inherit from the root domain since MS.NET does this */
mono_debugger_event_create_appdomain (data, shadow_location);
g_free (shadow_location);
#endif
-
+
+ // FIXME: Initialize null_reference_ex and stack_overflow_ex
+ data->out_of_memory_ex = mono_exception_from_name_domain (data, mono_defaults.corlib, "System", "OutOfMemoryException");
+
return ad;
}
g_hash_table_foreach (value, deregister_reflection_info_roots_nspace_table, user_data);
}
+static void
+deregister_reflection_info_roots_from_list (MonoImage *image)
+{
+ GSList *list = image->reflection_info_unregister_classes;
+
+ while (list) {
+ MonoClass *class = list->data;
+
+ g_assert (class->reflection_info);
+ mono_gc_deregister_root ((char*) &class->reflection_info);
+
+ list = list->next;
+ }
+
+ g_slist_free (image->reflection_info_unregister_classes);
+ image->reflection_info_unregister_classes = NULL;
+}
+
static void
deregister_reflection_info_roots (MonoDomain *domain)
{
/*No need to take the image lock here since dynamic images are appdomain bound and at this point the mutator is gone.*/
if (image->dynamic && image->name_cache)
g_hash_table_foreach (image->name_cache, deregister_reflection_info_roots_name_space, image);
+ deregister_reflection_info_roots_from_list (image);
for (i = 0; i < image->module_count; ++i) {
MonoImage *module = image->modules [i];
- if (module && module->dynamic && module->name_cache)
- g_hash_table_foreach (module->name_cache, deregister_reflection_info_roots_name_space, module);
+ if (module) {
+ if (module->dynamic && module->name_cache) {
+ g_hash_table_foreach (module->name_cache,
+ deregister_reflection_info_roots_name_space, module);
+ }
+ deregister_reflection_info_roots_from_list (module);
+ }
}
}
mono_domain_assemblies_unlock (domain);
void
mono_gc_add_weak_track_handle (MonoObject *obj, guint32 handle)
{
- MonoDomain *domain = mono_object_get_domain (obj);
+ MonoDomain *domain;
+
+ if (!obj)
+ return;
+
+ domain = mono_object_get_domain (obj);
mono_domain_finalizers_lock (domain);
/*
* 25.2.1: Method header type values
*/
-#define METHOD_HEADER_FORMAT_MASK 7
+#define METHOD_HEADER_FORMAT_MASK 3
#define METHOD_HEADER_TINY_FORMAT 2
-#define METHOD_HEADER_TINY_FORMAT1 6
#define METHOD_HEADER_FAT_FORMAT 3
/*
MonoMarshalField fields [MONO_ZERO_LEN_ARRAY];
} MonoMarshalType;
+#define MONO_SIZEOF_MARSHAL_TYPE (offsetof (MonoMarshalType, fields))
+
struct _MonoProperty {
MonoClass *parent;
const char *name;
MonoVTable *domain_vtables [MONO_ZERO_LEN_ARRAY];
} MonoClassRuntimeInfo;
+#define MONO_SIZEOF_CLASS_RUNTIME_INFO (sizeof (MonoClassRuntimeInfo) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
enum {
MONO_RGCTX_INFO_STATIC_DATA,
MONO_RGCTX_INFO_KLASS,
gpointer infos [MONO_ZERO_LEN_ARRAY];
} MonoMethodRuntimeGenericContext;
+#define MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT (sizeof (MonoMethodRuntimeGenericContext) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
#define MONO_RGCTX_SLOT_MAKE_RGCTX(i) (i)
#define MONO_RGCTX_SLOT_MAKE_MRGCTX(i) ((i) | 0x80000000)
#define MONO_RGCTX_SLOT_INDEX(s) ((s) & 0x7fffffff)
gpointer vtable [MONO_ZERO_LEN_ARRAY];
};
+#define MONO_SIZEOF_VTABLE (sizeof (MonoVTable) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
#define MONO_VTABLE_IMPLEMENTS_INTERFACE(vt,uiid) (((uiid) <= (vt)->max_interface_id) && ((vt)->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7))))
/*
MonoType *type_argv [MONO_ZERO_LEN_ARRAY];
};
+#define MONO_SIZEOF_GENERIC_INST (sizeof (MonoGenericInst) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
/*
* The generic context: an instantiation of a set of class and method generic parameters.
*
void
mono_class_setup_interfaces (MonoClass *klass) MONO_INTERNAL;
+MonoClassField*
+mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type) MONO_INTERNAL;
+
#endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */
if (!class->enumtype) {
if (!mono_metadata_interfaces_from_typedef_full (
- image, type_token, &interfaces, &icount, context)){
+ image, type_token, &interfaces, &icount, FALSE, context)){
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
return NULL;
MonoImage *image;
MonoClass *class;
MonoClass *parent = NULL;
- GSList *list, *rootlist;
+ GSList *list, *rootlist = NULL;
int nsize;
char *name;
gboolean corlib_type = FALSE;
* class->field.first points to the FieldPtr table, while idx points into the
* Field table, so we have to do a search.
*/
+ /*FIXME this is broken for types with multiple fields with the same name.*/
const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
int i;
*/
MonoClassField *
mono_class_get_field_from_name (MonoClass *klass, const char *name)
+{
+ return mono_class_get_field_from_name_full (klass, name, NULL);
+}
+
+/**
+ * mono_class_get_field_from_name_full:
+ * @klass: the class to lookup the field.
+ * @name: the field name
+ * @type: the type of the fields. This optional.
+ *
+ * Search the class @klass and it's parents for a field with the name @name and type @type.
+ *
+ * If @klass is an inflated generic type, the type comparison is done with the equivalent field
+ * of its generic type definition.
+ *
+ * Returns: the MonoClassField pointer of the named field or NULL
+ */
+MonoClassField *
+mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
{
int i;
mono_class_setup_fields_locking (klass);
while (klass) {
for (i = 0; i < klass->field.count; ++i) {
- if (strcmp (name, mono_field_get_name (&klass->fields [i])) == 0)
- return &klass->fields [i];
+ MonoClassField *field = &klass->fields [i];
+
+ if (strcmp (name, mono_field_get_name (field)) != 0)
+ continue;
+
+ if (type) {
+ MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
+ if (!mono_metadata_type_equal_full (type, field_type, TRUE))
+ continue;
+ }
+ return field;
}
klass = klass->parent;
}
MonoClass *interfaces [MONO_ZERO_LEN_ARRAY];
} MonoRemoteClass;
+#define MONO_SIZEOF_REMOTE_CLASS (sizeof (MonoRemoteClass) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
MonoClass *
mono_class_get (MonoImage *image, guint32 type_token);
param_count++;
res = mono_metadata_signature_alloc (image, param_count);
- sigsize = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *));
+ sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
memcpy (res, sig, sigsize);
// now move args forward one
{
if (klass->nested_in) {
print_name_space (klass->nested_in);
- g_print (klass->nested_in->name);
+ g_print ("%s", klass->nested_in->name);
return "/";
}
if (klass->name_space [0]) {
- g_print (klass->name_space);
+ g_print ("%s", klass->name_space);
return ".";
}
return "";
MonoJitInfoTableChunk *chunks [MONO_ZERO_LEN_ARRAY];
};
+#define MONO_SIZEOF_JIT_INFO_TABLE (sizeof (struct _MonoJitInfoTable) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
typedef GArray MonoAotModuleInfoTable;
typedef struct {
/* There is an optional MonoGenericJitInfo after the clauses */
};
+#define MONO_SIZEOF_JIT_INFO (offsetof (struct _MonoJitInfo, clauses))
+
struct _MonoAppContext {
MonoObject obj;
gint32 domain_id;
static MonoJitInfoTable *
jit_info_table_new (MonoDomain *domain)
{
- MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*));
+ MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
table->domain = domain;
table->num_chunks = 1;
required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
- new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks);
+ new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
new->domain = old->domain;
new->num_chunks = num_chunks;
static MonoJitInfoTable*
jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
{
- MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
+ MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
int i, j;
static MonoJitInfoTable*
jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
{
- MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable)
+ MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
int i, j;
mono_debug_domain_unload (domain);
- mono_gc_clear_domain (domain);
-
mono_appdomains_lock ();
appdomains_list [domain->domain_id] = NULL;
mono_appdomains_unlock ();
+ /*
+ * We must destroy all these hash tables here because they
+ * contain references to managed objects belonging to the
+ * domain. Once we let the GC clear the domain there must be
+ * no more such references, or we'll crash if a collection
+ * occurs.
+ */
+ mono_g_hash_table_destroy (domain->ldstr_table);
+ domain->ldstr_table = NULL;
+
+ mono_g_hash_table_destroy (domain->env);
+ domain->env = NULL;
+
+ mono_reflection_cleanup_domain (domain);
+
+ if (domain->type_hash) {
+ mono_g_hash_table_destroy (domain->type_hash);
+ domain->type_hash = NULL;
+ }
+ if (domain->type_init_exception_hash) {
+ mono_g_hash_table_destroy (domain->type_init_exception_hash);
+ domain->type_init_exception_hash = NULL;
+ }
+
+ for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
+ MonoAssembly *ass = tmp->data;
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
+ mono_assembly_close (ass);
+ }
+ g_slist_free (domain->domain_assemblies);
+ domain->domain_assemblies = NULL;
+
+ mono_gc_clear_domain (domain);
+
/* FIXME: free delegate_hash_table when it's used */
if (domain->search_path) {
g_strfreev (domain->search_path);
g_hash_table_destroy (domain->special_static_fields);
domain->special_static_fields = NULL;
}
- for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
- MonoAssembly *ass = tmp->data;
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
- mono_assembly_close (ass);
- }
- g_slist_free (domain->domain_assemblies);
- domain->domain_assemblies = NULL;
g_free (domain->friendly_name);
domain->friendly_name = NULL;
- mono_g_hash_table_destroy (domain->env);
- domain->env = NULL;
g_hash_table_destroy (domain->class_vtable_hash);
domain->class_vtable_hash = NULL;
g_hash_table_destroy (domain->proxy_vtable_hash);
domain->static_data_array = NULL;
}
mono_internal_hash_table_destroy (&domain->jit_code_hash);
- mono_g_hash_table_destroy (domain->ldstr_table);
- domain->ldstr_table = NULL;
/*
* There might still be jit info tables of this domain which
domain->code_mp = NULL;
#endif
- mono_reflection_cleanup_domain (domain);
-
- if (domain->type_hash) {
- mono_g_hash_table_destroy (domain->type_hash);
- domain->type_hash = NULL;
- }
- if (domain->type_init_exception_hash) {
- mono_g_hash_table_destroy (domain->type_init_exception_hash);
- domain->type_init_exception_hash = NULL;
- }
g_hash_table_destroy (domain->finalizable_objects_hash);
domain->finalizable_objects_hash = NULL;
#ifndef HAVE_SGEN_GC
DeleteCriticalSection (&domain->lock);
domain->setup = NULL;
+ mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
+
/* FIXME: anything else required ? */
mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
{
MonoClass *klass;
MonoObject *o;
+ MonoDomain *caller_domain = mono_domain_get ();
klass = mono_class_from_name (image, name_space, name);
o = mono_object_new (domain, klass);
g_assert (o != NULL);
-
+
+ if (domain != caller_domain)
+ mono_domain_set_internal (domain);
mono_runtime_object_init (o);
+ if (domain != caller_domain)
+ mono_domain_set_internal (caller_domain);
return (MonoException *)o;
}
GSList* mono_gc_remove_weak_track_object (MonoDomain *domain, MonoObject *obj) MONO_INTERNAL;
#endif
+MonoBoolean
+GCHandle_CheckCurrentDomain (guint32 gchandle) MONO_INTERNAL;
+
/* simple interface for data structures needed in the runtime */
void* mono_gc_make_descr_from_bitmap (gsize *bitmap, int numbits) MONO_INTERNAL;
}
+MonoBoolean
+GCHandle_CheckCurrentDomain (guint32 gchandle)
+{
+ return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
+}
+
#ifndef HAVE_NULL_GC
#ifdef MONO_HAS_SEMAPHORES
return 0;
}
+#ifdef HAVE_SGEN_GC
+#define GC_dont_gc 0
+#endif
+
void
mono_gc_init (void)
{
first_slot = 0;
size = mono_class_rgctx_get_array_size (0, method_inst != NULL);
if (method_inst)
- size -= sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ size -= MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
for (i = 0; ; ++i) {
int offset;
if (method_inst && i == 0)
- offset = sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ offset = MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
else
offset = 0;
ICALL(MGENCL_2, "GetCorrespondingInflatedConstructor", ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor)
ICALL(MGENCL_3, "GetCorrespondingInflatedField", ves_icall_MonoGenericClass_GetCorrespondingInflatedField)
ICALL(MGENCL_4, "GetCorrespondingInflatedMethod", ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod)
+ICALL(MGENCL_16, "GetElementType", ves_icall_MonoType_GetElementType)
ICALL(MGENCL_5, "GetEvents_internal", ves_icall_MonoGenericClass_GetEvents)
ICALL(MGENCL_6, "GetFields_internal", ves_icall_MonoGenericClass_GetFields)
ICALL(MGENCL_7, "GetInterfaces_internal", ves_icall_MonoGenericClass_GetInterfaces)
ICALL(MGENCL_9, "GetParentType", ves_icall_MonoGenericClass_GetParentType)
ICALL(MGENCL_10, "GetProperties_internal", ves_icall_MonoGenericClass_GetProperties)
ICALL(MGENCL_12, "InflateType_internal", ves_icall_MonoGenericClass_InflateType)
+ICALL(MGENCL_13, "IsByRefImpl", ves_icall_type_isbyref)
+ICALL(MGENCL_14, "IsPointerImpl", ves_icall_type_ispointer)
+ICALL(MGENCL_15, "IsPrimitiveImpl", ves_icall_type_isprimitive)
ICALL(MGENCL_11, "initialize", mono_reflection_generic_class_initialize)
/* note this is the same as above: unify */
const char *scope = NULL;
guint32 flags;
- if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
return NULL;
if (!DllImportAttributeClass) {
* arm-apple-darwin9. We'll manually define the symbol on Apple as it does
* in fact exist on all implementations (so far)
*/
-gchar ***_NSGetEnviron();
+gchar ***_NSGetEnviron(void);
#define environ (*_NSGetEnviron())
#else
extern
}
}
-static MonoBoolean
-GCHandle_CheckCurrentDomain (guint32 gchandle)
-{
- return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
-}
-
static MonoString*
ves_icall_Mono_Runtime_GetDisplayName (void)
{
if (image->property_hash)
mono_property_hash_destroy (image->property_hash);
+ g_slist_free (image->reflection_info_unregister_classes);
+
if (image->interface_bitset) {
mono_unload_interface_ids (image->interface_bitset);
mono_bitset_free (image->interface_bitset);
}
case MONO_EXCEPTION_MISSING_FIELD: {
- char *cnspace = g_strdup (*error->klass->name_space ? error->klass->name_space : "");
- char *cname = g_strdup (error->klass->name);
+ char *cnspace = g_strdup ((error->klass && *error->klass->name_space) ? error->klass->name_space : "");
+ char *cname = g_strdup (error->klass ? error->klass->name : "");
char *cmembername = g_strdup (error->member_name);
char *class_name;
MonoGenericContext *context)
{
MonoClass *klass;
- MonoClassField *field, *sig_field = NULL;
+ MonoClassField *field;
MonoTableInfo *tables = image->tables;
MonoType *sig_type;
guint32 cols[6];
/* we may want to check the signature here... */
if (*ptr++ != 0x6) {
- mono_loader_set_error_bad_image (g_strdup_printf ("Bad field signature class token %08x field name %s token %08x", class, fname, token));
+ g_warning ("Bad field signature class token %08x field name %s token %08x", class, fname, token);
+ mono_loader_set_error_field_load (NULL, fname);
return NULL;
}
/* FIXME: This needs a cache, especially for generic instances, since
sig_type = find_cached_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE]);
if (!sig_type) {
sig_type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ if (sig_type == NULL) {
+ mono_loader_set_error_field_load (NULL, fname);
+ return NULL;
+ }
sig_type = cache_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE], sig_type);
}
mono_class_init (klass);
if (retklass)
*retklass = klass;
- sig_field = field = mono_class_get_field_from_name (klass, fname);
+ field = mono_class_get_field_from_name_full (klass, fname, sig_type);
break;
case MONO_MEMBERREF_PARENT_TYPEREF:
klass = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | nindex);
mono_class_init (klass);
if (retklass)
*retklass = klass;
- sig_field = field = mono_class_get_field_from_name (klass, fname);
+ field = mono_class_get_field_from_name_full (klass, fname, sig_type);
break;
case MONO_MEMBERREF_PARENT_TYPESPEC: {
klass = mono_class_get_full (image, MONO_TOKEN_TYPE_SPEC | nindex, context);
- //FIXME can't klass be null?
+ if (!klass) {
+ char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_REF | nindex);
+ g_warning ("missing field %s in class %s (typeref index %d)", fname, name, nindex);
+ mono_loader_set_error_type_load (name, image->assembly_name);
+ g_free (name);
+ return NULL;
+ }
mono_class_init (klass);
if (retklass)
*retklass = klass;
- field = mono_class_get_field_from_name (klass, fname);
- if (field)
- sig_field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
+ field = mono_class_get_field_from_name_full (klass, fname, sig_type);
break;
}
default:
if (!field)
mono_loader_set_error_field_load (klass, fname);
- else if (sig_field && !mono_metadata_type_equal_full (sig_type, sig_field->type, TRUE)) {
- mono_loader_set_error_field_load (klass, fname);
- return NULL;
- }
return field;
}
if (!context)
return sig;
- res = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ res = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)sig->param_count) * sizeof (MonoType*));
res->param_count = sig->param_count;
res->sentinelpos = -1;
res->ret = mono_class_inflate_generic_type (sig->ret, context);
{
MonoMethodHeader *res;
int i;
- res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
+ res = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals);
res->code = header->code;
res->code_size = header->code_size;
res->max_stack = header->max_stack;
}
/*
- * token is the method_ref or method_def token used in a call IL instruction.
+ * token is the method_ref/def/spec token used in a call IL instruction.
*/
MonoMethodSignature*
mono_method_get_signature_full (MonoMethod *method, MonoImage *image, guint32 token, MonoGenericContext *context)
ptr = mono_metadata_blob_heap (image, sig_idx);
mono_metadata_decode_blob_size (ptr, &ptr);
sig = mono_metadata_parse_method_signature (image, 0, ptr, NULL);
-
+ if (!sig)
+ return NULL;
sig = cache_memberref_sig (image, sig_idx, sig);
}
result = mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
// This checks the memberref type as well
if (result && handle_class != mono_defaults.methodhandle_class) {
- mono_loader_set_error_bad_image (g_strdup ("Bad method token."));
+ mono_loader_set_error_bad_image (g_strdup_printf ("Bad method token 0x%08x on image %s.", token, image->name));
return NULL;
}
return result;
if (used_context) *used_context = TRUE;
return method_from_methodspec (image, context, idx);
}
- if (table != MONO_TABLE_MEMBERREF)
- g_print("got wrong token: 0x%08x\n", token);
- g_assert (table == MONO_TABLE_MEMBERREF);
+ if (table != MONO_TABLE_MEMBERREF) {
+ g_warning ("got wrong token: 0x%08x\n", token);
+ mono_loader_set_error_bad_image (g_strdup_printf ("Bad method token 0x%08x on image %s.", token, image->name));
+ return NULL;
+ }
return method_from_memberref (image, idx, context, used_context);
}
if (used_context) *used_context = FALSE;
if (idx > image->tables [MONO_TABLE_METHOD].rows) {
- mono_loader_set_error_bad_image (g_strdup ("Bad method token."));
+ mono_loader_set_error_bad_image (g_strdup_printf ("Bad method token 0x%08x on image %s.", token, image->name));
return NULL;
}
mono_class_init (constrained_class);
method = *cil_method;
original_sig = sig = mono_method_signature (method);
+ if (sig == NULL)
+ return NULL;
if (method->is_inflated && sig->generic_param_count) {
MonoMethodInflated *imethod = (MonoMethodInflated *) method;
- sig = mono_method_signature (imethod->declaring);
+ sig = mono_method_signature (imethod->declaring); /*We assume that if the inflated method signature is valid, the declaring method is too*/
method_context = mono_method_get_context (method);
original_sig = sig;
/*
* We must inflate the signature with the class instantiation to work on
* cases where a class inherit from a generic type and the override replaces
- * and type argument which a concrete type. See #325283.
+ * any type argument which a concrete type. See #325283.
*/
if (method_context->class_inst) {
MonoGenericContext ctx;
ctx.class_inst = method_context->class_inst;
sig = inflate_generic_signature (method->klass->image, sig, &ctx);
+ if (sig == NULL)
+ return NULL;
}
}
MonoClass *klass;
MonoTableInfo *methodt;
MonoTableInfo *paramt;
+ MonoMethodSignature *signature;
guint32 idx;
if (method->is_inflated)
method = ((MonoMethodInflated *) method)->declaring;
- if (!mono_method_signature (method)->param_count)
+ signature = mono_method_signature (method);
+ /*FIXME this check is somewhat redundant since the caller usally will have to get the signature to figure out the
+ number of arguments and allocate a properly sized array. */
+ if (signature == NULL)
+ return;
+
+ if (!signature->param_count)
return;
- for (i = 0; i < mono_method_signature (method)->param_count; ++i)
+
+ for (i = 0; i < signature->param_count; ++i)
names [i] = "";
klass = method->klass;
lastp = paramt->rows + 1;
for (i = param_index; i < lastp; ++i) {
mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE);
- if (cols [MONO_PARAM_SEQUENCE]) /* skip return param spec */
+ if (cols [MONO_PARAM_SEQUENCE] && cols [MONO_PARAM_SEQUENCE] <= signature->param_count) /* skip return param spec and bounds check*/
names [cols [MONO_PARAM_SEQUENCE] - 1] = mono_metadata_string_heap (klass->image, cols [MONO_PARAM_NAME]);
}
- return;
}
}
MonoClass *klass = method->klass;
MonoTableInfo *methodt;
MonoTableInfo *paramt;
+ MonoMethodSignature *signature;
guint32 idx;
- for (i = 0; i < mono_method_signature (method)->param_count + 1; ++i)
+ signature = mono_method_signature (method);
+ g_assert (signature); /*FIXME there is no way to signal error from this function*/
+
+ for (i = 0; i < signature->param_count + 1; ++i)
mspecs [i] = NULL;
if (method->klass->image->dynamic) {
((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
if (method_aux && method_aux->param_marshall) {
MonoMarshalSpec **dyn_specs = method_aux->param_marshall;
- for (i = 0; i < mono_method_signature (method)->param_count + 1; ++i)
+ for (i = 0; i < signature->param_count + 1; ++i)
if (dyn_specs [i]) {
mspecs [i] = g_new0 (MonoMarshalSpec, 1);
memcpy (mspecs [i], dyn_specs [i], sizeof (MonoMarshalSpec));
for (i = param_index; i < lastp; ++i) {
mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE);
- if (cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) {
+ if (cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL && cols [MONO_PARAM_SEQUENCE] <= signature->param_count) {
const char *tp;
tp = mono_metadata_get_marshal_info (klass->image, i - 1, FALSE);
g_assert (tp);
/* Verify metadata consistency */
if (signature->generic_param_count) {
- if (!container || !container->is_method)
- g_error ("Signature claims method has generic parameters, but generic_params table says it doesn't");
- if (container->type_argc != signature->generic_param_count)
- g_error ("Inconsistent generic parameter count. Signature says %d, generic_params table says %d",
- signature->generic_param_count, container->type_argc);
- } else if (container && container->is_method && container->type_argc)
- g_error ("generic_params table claims method has generic parameters, but signature says it doesn't");
-
+ if (!container || !container->is_method) {
+ g_warning ("Signature claims method has generic parameters, but generic_params table says it doesn't for method 0x%08x from image %s", idx, img->name);
+ return NULL;
+ }
+ if (container->type_argc != signature->generic_param_count) {
+ g_warning ("Inconsistent generic parameter count. Signature says %d, generic_params table says %dfor method 0x%08x from image %s",
+ signature->generic_param_count, container->type_argc, idx, img->name);
+ return NULL;
+ }
+ } else if (container && container->is_method && container->type_argc) {
+ g_warning ("generic_params table claims method has generic parameters, but signature says it doesn't for method 0x%08x from image %s", idx, img->name);
+ return NULL;
+ }
if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
signature->pinvoke = 1;
else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
case PINVOKE_ATTRIBUTE_CALL_CONV_GENERIC:
case PINVOKE_ATTRIBUTE_CALL_CONV_GENERICINST:
default:
- g_warning ("unsupported calling convention : 0x%04x", piinfo->piflags);
- g_assert_not_reached ();
+ g_warning ("unsupported calling convention : 0x%04x for method 0x%08x from image %s", piinfo->piflags, idx, img->name);
+ return NULL;
}
signature->call_convention = conv;
}
int sigsize;
res = mono_metadata_signature_alloc (image, sig->param_count);
- sigsize = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *));
+ sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
memcpy (res, sig, sigsize);
return res;
default: {
char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
MonoException *exc = mono_get_exception_not_implemented (msg);
- g_warning (msg);
+ g_warning ("%s", msg);
g_free (msg);
mono_raise_exception (exc);
}
int i;
res = mono_metadata_signature_alloc (klass->image, sig->param_count + 1);
- memcpy (res, sig, sizeof (MonoMethodSignature));
+ memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
res->param_count = sig->param_count + 1;
res->hasthis = FALSE;
for (i = sig->param_count - 1; i >= 0; i --)
if (conv == -1) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
MonoException *exc = mono_get_exception_not_implemented (msg);
- g_warning (msg);
+ g_warning ("%s", msg);
g_free (msg);
mono_raise_exception (exc);
}
else {
char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
MonoException *exc = mono_get_exception_not_implemented (msg);
- g_warning (msg);
+ g_warning ("%s", msg);
g_free (msg);
mono_raise_exception (exc);
}
if (conv == -1) {
char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
MonoException *exc = mono_get_exception_not_implemented (msg);
- g_warning (msg);
+ g_warning ("%s", msg);
g_free (msg);
mono_raise_exception (exc);
}
layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
/* The mempool is protected by the loader lock */
- info = mono_image_alloc0 (klass->image, sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
+ info = mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
info->num_fields = count;
/* Try to find a size for this type in metadata */
/* dup & extend signature */
csig = mono_metadata_signature_alloc (image, param_count);
- sig_size = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *));
+ sig_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
memcpy (csig, sig, sig_size);
csig->param_count = param_count;
csig->hasthis = 0;
/* interfaces IDs from this image */
MonoBitSet *interface_bitset;
+ GSList *reflection_info_unregister_classes;
+
/*
* No other runtime locks must be taken while holding this lock.
* It's meant to be used only to mutate and query structures part of this image.
MonoType *locals [MONO_ZERO_LEN_ARRAY];
};
+#define MONO_SIZEOF_METHOD_HEADER (sizeof (struct _MonoMethodHeader) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
/* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
guint mono_aligned_addr_hash (gconstpointer ptr) MONO_INTERNAL;
guint32 table_index,
MonoClass ***interfaces,
guint *count,
+ gboolean heap_alloc_result,
MonoGenericContext *context) MONO_INTERNAL;
MonoArrayType *
int valid;
MonoImage *image;
gboolean report_error;
+ gboolean report_warning;
int stage;
DataDirectory data_directories [16];
(__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
} while (0)
+#define ADD_WARNING(__ctx, __msg) \
+ do { \
+ if ((__ctx)->report_warning) \
+ ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
+ (__ctx)->valid = 0; \
+ return; \
+ } while (0)
#define ADD_ERROR(__ctx, __msg) \
do { \
}
if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
- ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
+ ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
memset (ctx, 0, sizeof (VerifyContext));
ctx->image = image;
ctx->report_error = error_list != NULL;
+ ctx->report_warning = FALSE; //export this setting in the API
ctx->valid = 1;
ctx->size = image->raw_data_len;
ctx->data = image->raw_data;
mono_metadata_locate (MonoImage *meta, int table, int idx)
{
/* idx == 0 refers always to NULL */
- g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
+ g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
}
const char *
mono_metadata_blob_heap (MonoImage *meta, guint32 index)
{
- g_return_val_if_fail (index < meta->heap_blob.size, "");
+ g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
return meta->heap_blob.data + index;
}
array->numsizes = mono_metadata_decode_value (ptr, &ptr);
if (array->numsizes)
- array->sizes = g_new0 (int, array->numsizes);
+ array->sizes = mono_image_alloc0 (m, sizeof (int) * array->numsizes);
for (i = 0; i < array->numsizes; ++i)
array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
if (array->numlobounds)
- array->lobounds = g_new0 (int, array->numlobounds);
+ array->lobounds = mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
for (i = 0; i < array->numlobounds; ++i)
array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
}
if (count) {
- type = mono_image_alloc0 (m, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+ type = mono_image_alloc0 (m, MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod));
type->num_mods = count;
if (count > 64)
g_warning ("got more than 64 modifiers in type");
} else {
type = &stype;
- memset (type, 0, sizeof (MonoType));
+ memset (type, 0, MONO_SIZEOF_TYPE);
}
/* Parse pinned, byref and custom modifiers */
/* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
if (type == &stype) {
- type = mono_image_alloc (m, sizeof (MonoType));
- memcpy (type, &stype, sizeof (MonoType));
+ type = mono_image_alloc (m, MONO_SIZEOF_TYPE);
+ memcpy (type, &stype, MONO_SIZEOF_TYPE);
}
return type;
}
{
MonoMethodSignature *sig;
- sig = mono_image_alloc0 (m, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
sig->param_count = nparams;
sig->sentinelpos = -1;
{
int sigsize;
MonoMethodSignature *ret;
- sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
+ sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
if (image) {
ret = mono_image_alloc (image, sigsize);
guint32
mono_metadata_signature_size (MonoMethodSignature *sig)
{
- return sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
+ return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
}
/*
for (i = 0; i < method->param_count; ++i) {
if (*ptr == MONO_TYPE_SENTINEL) {
- if (method->call_convention != MONO_CALL_VARARG || def)
- g_error ("found sentinel for methoddef or no vararg method");
- if (method->sentinelpos >= 0)
- g_error ("found sentinel twice in the same signature");
+ if (method->call_convention != MONO_CALL_VARARG || def) {
+ g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
+ g_free (pattrs);
+ return NULL;
+ }
+ if (method->sentinelpos >= 0) {
+ g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
+ g_free (pattrs);
+ return NULL;
+ }
method->sentinelpos = i;
ptr++;
}
MonoGenericInst *ginst;
gboolean is_open;
int i;
- int size = sizeof (MonoGenericInst) + (type_argc - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
+ int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
for (i = 0; i < type_argc; ++i)
if (mono_class_is_open_constructed_type (type_argv [i]))
if (!etype)
return FALSE;
type->data.klass = mono_class_from_mono_type (etype);
+ if (!type->data.klass)
+ return FALSE;
break;
}
case MONO_TYPE_PTR:
break;
case MONO_TYPE_FNPTR:
type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
+ if (!type->data.method)
+ return FALSE;
break;
case MONO_TYPE_ARRAY:
type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
+ if (!type->data.array)
+ return FALSE;
break;
case MONO_TYPE_MVAR:
if (container && !container->is_method)
return FALSE;
case MONO_TYPE_VAR:
type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
+ if (!type->data.generic_param)
+ return FALSE;
break;
case MONO_TYPE_GENERICINST:
ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
break;
default:
- g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
+ g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name);
+ return FALSE;
}
if (rptr)
switch (format) {
case METHOD_HEADER_TINY_FORMAT:
- mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
- ptr++;
- mh->max_stack = 8;
- local_var_sig_tok = 0;
- mh->code_size = flags >> 2;
- mh->code = (unsigned char*)ptr;
- return mh;
- case METHOD_HEADER_TINY_FORMAT1:
- mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
+ mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
ptr++;
mh->max_stack = 8;
local_var_sig_tok = 0;
-
- /*
- * The spec claims 3 bits, but the Beta2 is
- * incorrect
- */
mh->code_size = flags >> 2;
mh->code = (unsigned char*)ptr;
return mh;
g_warning ("wrong signature for locals blob");
locals_ptr++;
len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
- mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*));
mh->num_locals = len;
for (i = 0; i < len; ++i) {
mh->locals [i] = mono_metadata_parse_type_full (
}
}
} else {
- mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
+ mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER);
}
mh->code = code;
mh->code_size = code_size;
* mono_metadata_interfaces_from_typedef_full:
* @meta: metadata context
* @index: typedef token
+ * @interfaces: Out parameter used to store the interface array
+ * @count: Out parameter used to store the number of interfaces
+ * @heap_alloc_result: if TRUE the result array will be g_malloc'd
+ * @context: The generic context
*
* The array of interfaces that the @index typedef token implements is returned in
- * @interfaces. The number of elemnts in the array is returned in @count.
+ * @interfaces. The number of elements in the array is returned in @count.
*
* LOCKING: Assumes the loader lock is held.
*
* Returns: TRUE on success, FALSE on failure.
*/
gboolean
-mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, MonoGenericContext *context)
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
{
MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
locator_t loc;
++pos;
}
- result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
+ if (heap_alloc_result)
+ result = g_new0 (MonoClass*, pos - start);
+ else
+ result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
pos = start;
while (pos < tdef->rows) {
return TRUE;
}
+/*
+ * @meta: metadata context
+ * @index: typedef token
+ * @count: Out parameter used to store the number of interfaces
+ *
+ * The array of interfaces that the @index typedef token implements is returned in
+ * @interfaces. The number of elements in the array is returned in @count. The returned
+ * array is g_malloc'd and the caller must free it.
+ *
+ * LOCKING: Acquires the loader lock .
+ *
+ * Returns: the interface array on success, NULL on failure.
+ */
+
MonoClass**
mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
{
gboolean rv;
mono_loader_lock ();
- rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
+ rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
mono_loader_unlock ();
if (rv)
return interfaces;
mono_metadata_type_dup (MonoImage *image, const MonoType *o)
{
MonoType *r = NULL;
- int sizeof_o = sizeof (MonoType);
+ int sizeof_o = MONO_SIZEOF_TYPE;
if (o->num_mods)
- sizeof_o += (o->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
+ sizeof_o += o->num_mods * sizeof (MonoCustomMod);
r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o);
len = mono_metadata_decode_value (ptr, &ptr);
- type = mono_image_alloc0 (image, sizeof (MonoType));
+ type = mono_image_alloc0 (image, MONO_SIZEOF_TYPE);
if (*ptr == MONO_TYPE_BYREF) {
type->byref = 1;
return nginst;
}
+/**
+ * mono_type_is_byref:
+ * @type: the MonoType operated on
+ *
+ * Returns: #TRUE if @type represents a type passed by reference,
+ * #FALSE otherwise.
+ */
gboolean
mono_type_is_byref (MonoType *type)
{
return type->byref;
}
+/**
+ * mono_type_get_type:
+ * @type: the MonoType operated on
+ *
+ * Returns: the IL type value for @type. This is one of the MonoTypeEnum
+ * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
+ */
int
mono_type_get_type (MonoType *type)
{
return type->type;
}
-/* For MONO_TYPE_FNPTR */
+/**
+ * mono_type_get_signature:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
+ *
+ * Returns: the MonoMethodSignature pointer that describes the signature
+ * of the function pointer @type represents.
+ */
MonoMethodSignature*
mono_type_get_signature (MonoType *type)
{
+ g_assert (type->type == MONO_TYPE_FNPTR);
return type->data.method;
}
-/* For MONO_TYPE_CLASS, VALUETYPE */
+/**
+ * mono_type_get_class:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
+ * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
+ * instead
+ *
+ * Returns: the MonoClass pointer that describes the class that @type represents.
+ */
MonoClass*
mono_type_get_class (MonoType *type)
{
+ /* FIXME: review the runtime users before adding the assert here */
return type->data.klass;
}
-/* For MONO_TYPE_ARRAY */
+/**
+ * mono_type_get_array_type:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
+ *
+ * Returns: a MonoArrayType struct describing the array type that @type
+ * represents. The info includes details such as rank, array element type
+ * and the sizes and bounds of multidimensional arrays.
+ */
MonoArrayType*
mono_type_get_array_type (MonoType *type)
{
return type->data.array;
}
-/* For MONO_TYPE_PTR */
+/**
+ * mono_type_get_ptr_type:
+ * @type: the MonoType operated on
+ *
+ * It is only valid to call this function if @type is a MONO_TYPE_PTR.
+ * instead
+ *
+ * Returns: the MonoType pointer that describes the type that @type
+ * represents a pointer to.
+ */
MonoType*
mono_type_get_ptr_type (MonoType *type)
{
+ g_assert (type->type == MONO_TYPE_PTR);
return type->data.type;
}
G_BEGIN_DECLS
+/*
+ * When embedding, you have to define MONO_ZERO_LEN_ARRAY before including any
+ * other Mono header file if you use a different compiler from the one used to
+ * build Mono.
+ */
+#ifndef MONO_ZERO_LEN_ARRAY
#ifdef __GNUC__
#define MONO_ZERO_LEN_ARRAY 0
#else
#define MONO_ZERO_LEN_ARRAY 1
#endif
+#endif
#define MONO_TYPE_ISSTRUCT(t) (!(t)->byref && (((t)->type == MONO_TYPE_VALUETYPE && \
!(t)->data.klass->enumtype) || ((t)->type == MONO_TYPE_TYPEDBYREF) || \
MonoCustomMod modifiers [MONO_ZERO_LEN_ARRAY]; /* this may grow */
};
+#define MONO_SIZEOF_TYPE (offsetof (struct _MonoType, modifiers))
+
/*
* This structure is an internal runtime detail: use the mono_signature_*
* accessors below, because it will go away from the public header.
MonoType *params [MONO_ZERO_LEN_ARRAY];
};
+#define MONO_SIZEOF_METHOD_SIGNATURE (sizeof (struct _MonoMethodSignature) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
+
typedef struct _MonoMethodHeader MonoMethodHeader;
typedef enum {
method->dynamic = TRUE;
((MonoMethodNormal *)method)->header = header = (MonoMethodHeader *)
- g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
+ g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
header->code = mb->code;
method->name = mono_image_strdup (image, mb->name);
((MonoMethodNormal *)method)->header = header = (MonoMethodHeader *)
- mono_image_alloc0 (image, sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
+ mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
header->code = mono_image_alloc (image, mb->pos);
memcpy ((char*)header->code, mb->code, mb->pos);
}
if (ARCH_USE_IMT) {
- vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ vtable_size = MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
if (class->interface_offsets_count) {
imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE);
vtable_size += sizeof (gpointer) * (MONO_IMT_SIZE);
}
} else {
vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
- sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
}
mono_stats.used_class_count++;
/* this is a bounded memory retention issue: may want to
* handle it differently when we'll have a rcu-like system.
*/
- runtime_info = mono_image_alloc0 (class->image, sizeof (MonoClassRuntimeInfo) + new_size * sizeof (gpointer));
+ runtime_info = mono_image_alloc0 (class->image, MONO_SIZEOF_CLASS_RUNTIME_INFO + new_size * sizeof (gpointer));
runtime_info->max_domain = new_size - 1;
/* copy the stuff from the older info */
if (old_info) {
mono_stats.imt_number_of_tables++;
mono_stats.imt_tables_size += (sizeof (gpointer) * MONO_IMT_SIZE);
vtsize = sizeof (gpointer) * (MONO_IMT_SIZE) +
- sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
} else {
vtsize = sizeof (gpointer) * (max_interface_id + 1) +
- sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
}
mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
pvt = (MonoVTable*) (interface_offsets + MONO_IMT_SIZE);
else
pvt = (MonoVTable*) (interface_offsets + max_interface_id + 1);
- memcpy (pvt, vt, sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
+ memcpy (pvt, vt, MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer));
pvt->klass = mono_defaults.transparent_proxy_class;
/* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
key = mp_key;
if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
- rc = mono_domain_alloc (domain, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
+ rc = mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
rc->interface_count = 1;
rc->interfaces [0] = proxy_class;
rc->proxy_class = mono_defaults.marshalbyrefobject_class;
} else {
- rc = mono_domain_alloc (domain, sizeof(MonoRemoteClass));
+ rc = mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS);
rc->interface_count = 0;
rc->proxy_class = proxy_class;
}
if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
int i,j;
- rc = mono_domain_alloc (domain, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
+ rc = mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*) * (remote_class->interface_count + 1));
rc->proxy_class = remote_class->proxy_class;
rc->interface_count = remote_class->interface_count + 1;
rc->interfaces [j] = extra_class;
} else {
// Replace the old class. The interface array is the same
- rc = mono_domain_alloc (domain, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * remote_class->interface_count);
+ rc = mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*) * remote_class->interface_count);
rc->proxy_class = extra_class;
rc->interface_count = remote_class->interface_count;
if (rc->interface_count > 0)
}
#endif
{
- MonoDl *pmodule;
+ MonoDl *pmodule = NULL;
const char* col = strchr (desc, ':');
char* libname;
char* path;
if (!res)
return NULL;
- return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
+ return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
}
static gboolean
}
count -= not_visible;
- ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
+ ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
ainfo->image = image;
ainfo->num_attrs = count;
if (count == 0)
return mono_metadata_type_dup (NULL, type);
- len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
+ len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
t = g_malloc (len);
- memcpy (t, type, sizeof (MonoType));
+ memcpy (t, type, MONO_SIZEOF_TYPE);
t->num_mods = count;
pos = 0;
name = mono_string_to_utf8 (m->name);
nparams = mono_array_length (m->parameters);
- sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
+ sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
sig->hasthis = 1;
sig->sentinelpos = -1;
sig->call_convention = reflection_cc_to_file (m->call_conv);
format = flags & METHOD_HEADER_FORMAT_MASK;
switch (format){
case METHOD_HEADER_TINY_FORMAT:
- case METHOD_HEADER_TINY_FORMAT1:
local_var_sig_token = 0;
break;
case METHOD_HEADER_FAT_FORMAT:
mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
paramseq = param_cols [MONO_PARAM_SEQUENCE];
- if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
+ if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
continue;
crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
len = g_list_length (list);
if (!len)
return NULL;
- ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
+ ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
ainfo->num_attrs = len;
ainfo->image = image;
for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
/* Need to copy since it will be freed later */
ainfo = aux->param_cattr [param];
- size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
+ size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
res = g_malloc0 (size);
memcpy (res, ainfo, size);
return res;
check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
}
+static gboolean
+is_sre_generic_instance (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
+}
+
MonoType*
mono_reflection_type_get_handle (MonoReflectionType* ref)
{
res = &mono_ptr_class_get (base)->byval_arg;
sre_pointer->type.type = res;
return res;
+ } else if (is_sre_generic_instance (class)) {
+ MonoType *res, **types;
+ MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
+ int i, count;
+
+ count = mono_array_length (gclass->type_arguments);
+ types = g_new0 (MonoType*, count);
+ for (i = 0; i < count; ++i) {
+ MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
+ types [i] = mono_reflection_type_get_handle (t);
+ }
+
+ res = mono_reflection_bind_generic_parameters ((MonoReflectionType*)gclass->generic_type, count, types);
+ g_free (types);
+ g_assert (res);
+ gclass->type.type = res;
+ return res;
}
g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
count = parameters? mono_array_length (parameters): 0;
- sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
+ sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
sig->param_count = count;
sig->sentinelpos = -1; /* FIXME */
for (i = 0; i < count; ++i)
case MONO_TYPE_CLASS: {
char *str;
guint32 slen;
- MonoClass *k;
if (!arg) {
*p++ = 0xFF;
break;
}
- k = mono_object_class (arg);
- if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
- (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
- MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
- MonoClass *rtc;
-
- if (rt && (rtc = mono_object_class (rt)) &&
- (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
- !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
- arg = (MonoObject *) rt;
- k = rtc;
- } else
- g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
- }
handle_type:
- str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
+ str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
slen = strlen (str);
if ((p-buffer) + 10 + slen >= *buflen) {
char *newbuf;
}
}
- header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
- (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
header->code_size = code_size;
header->code = image_g_malloc (image, code_size);
memcpy ((char*)header->code, code, code_size);
mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
header->locals [i] = image_g_new0 (image, MonoType, 1);
- memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), sizeof (MonoType));
+ memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
}
header->num_clauses = num_clauses;
MOVING_GC_REGISTER (&pklass->reflection_info);
pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
+ mono_image_lock (image);
+ image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
+ mono_image_unlock (image);
}
MonoArray *
MonoCustomAttrEntry attrs [MONO_ZERO_LEN_ARRAY];
} MonoCustomAttrInfo;
+#define MONO_SIZEOF_CUSTOM_ATTR_INFO (offsetof (MonoCustomAttrInfo, attrs))
+
/*
* Information which isn't in the MonoMethod structure is stored here for
* dynamic methods.
* This section of code deals with detecting the objects no longer in use
* and reclaiming the memory.
*/
+
+#define COUNT_OBJECT_TYPES do { \
+ switch (desc & 0x7) { \
+ case DESC_TYPE_STRING: type_str++; break; \
+ case DESC_TYPE_RUN_LENGTH: type_rlen++; break; \
+ case DESC_TYPE_ARRAY: case DESC_TYPE_VECTOR: type_vector++; break; \
+ case DESC_TYPE_SMALL_BITMAP: type_bitmap++; break; \
+ case DESC_TYPE_LARGE_BITMAP: type_lbit++; break; \
+ case DESC_TYPE_COMPLEX: type_complex++; break; \
+ case DESC_TYPE_COMPLEX_ARR: type_complex++; break; \
+ default: g_assert_not_reached (); \
+ } \
+ } while (0)
+
static void __attribute__((noinline))
scan_area (char *start, char *end)
{
GCVTable *vt;
- size_t skip_size;
- int type;
int type_str = 0, type_rlen = 0, type_bitmap = 0, type_vector = 0, type_lbit = 0, type_complex = 0;
- mword desc;
new_obj_references = 0;
obj_references_checked = 0;
while (start < end) {
MonoObject *obj = (MonoObject*)start;
g_print ("found at %p (0x%zx): %s.%s\n", start, vt->desc, obj->vtable->klass->name_space, obj->vtable->klass->name);
}
- desc = vt->desc;
- type = desc & 0x7;
- if (type == DESC_TYPE_STRING) {
- STRING_SIZE (skip_size, start);
- start += skip_size;
- type_str++;
- continue;
- } else if (type == DESC_TYPE_RUN_LENGTH) {
- OBJ_RUN_LEN_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- OBJ_RUN_LEN_FOREACH_PTR (desc,start);
- start += skip_size;
- type_rlen++;
- continue;
- } else if (type == DESC_TYPE_VECTOR) { // includes ARRAY, too
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_VECTOR_FOREACH_PTR (vt, start);
- start += skip_size;
- type_vector++;
- continue;
- } else if (type == DESC_TYPE_SMALL_BITMAP) {
- OBJ_BITMAP_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- OBJ_BITMAP_FOREACH_PTR (desc,start);
- start += skip_size;
- type_bitmap++;
- continue;
- } else if (type == DESC_TYPE_LARGE_BITMAP) {
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start);
- start += skip_size;
- type_lbit++;
- continue;
- } else if (type == DESC_TYPE_COMPLEX) {
- /* this is a complex object */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_COMPLEX_FOREACH_PTR (vt, start);
- start += skip_size;
- type_complex++;
- continue;
- } else if (type == DESC_TYPE_COMPLEX_ARR) {
- /* this is an array of complex structs */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start);
- start += skip_size;
- type_complex++;
- continue;
- } else {
- g_assert (0);
- }
+
+#define SCAN_OBJECT_ACTION COUNT_OBJECT_TYPES
+#include "sgen-scan-object.h"
}
/*printf ("references to new nursery %p-%p (size: %dk): %d, checked: %d\n", old_start, end, (end-old_start)/1024, new_obj_references, obj_references_checked);
printf ("\tstrings: %d, runl: %d, vector: %d, bitmaps: %d, lbitmaps: %d, complex: %d\n",
scan_area_for_domain (MonoDomain *domain, char *start, char *end)
{
GCVTable *vt;
- size_t skip_size;
- int type;
gboolean remove;
- mword desc;
while (start < end) {
if (!*(void**)start) {
if (dislink)
mono_gc_register_disappearing_link (NULL, dislink, FALSE);
}
- desc = vt->desc;
- type = desc & 0x7;
- if (type == DESC_TYPE_STRING) {
- STRING_SIZE (skip_size, start);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_RUN_LENGTH) {
- OBJ_RUN_LEN_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_VECTOR) { // includes ARRAY, too
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_SMALL_BITMAP) {
- OBJ_BITMAP_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_LARGE_BITMAP) {
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_COMPLEX) {
- /* this is a complex object */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else if (type == DESC_TYPE_COMPLEX_ARR) {
- /* this is an array of complex structs */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- if (remove) memset (start, 0, skip_size);
- start += skip_size;
- continue;
- } else {
- g_assert (0);
- }
+
+#define SCAN_OBJECT_NOSCAN
+#define SCAN_OBJECT_ACTION do { if (remove) memset (start, 0, skip_size); } while (0)
+#include "sgen-scan-object.h"
}
}
static char*
scan_object (char *start, char* from_start, char* from_end)
{
- GCVTable *vt;
- size_t skip_size;
- mword desc;
-
- vt = (GCVTable*)LOAD_VTABLE (start);
- //type = vt->desc & 0x7;
+#include "sgen-scan-object.h"
- /* gcc should be smart enough to remove the bounds check, but it isn't:( */
- desc = vt->desc;
- switch (desc & 0x7) {
- //if (type == DESC_TYPE_STRING) {
- case DESC_TYPE_STRING:
- STRING_SIZE (skip_size, start);
- return start + skip_size;
- //} else if (type == DESC_TYPE_RUN_LENGTH) {
- case DESC_TYPE_RUN_LENGTH:
- OBJ_RUN_LEN_FOREACH_PTR (desc,start);
- OBJ_RUN_LEN_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- return start + skip_size;
- //} else if (type == DESC_TYPE_VECTOR) { // includes ARRAY, too
- case DESC_TYPE_ARRAY:
- case DESC_TYPE_VECTOR:
- OBJ_VECTOR_FOREACH_PTR (vt, start);
- skip_size = safe_object_get_size ((MonoObject*)start);
-#if 0
- skip_size = (vt->desc >> LOW_TYPE_BITS) & MAX_ELEMENT_SIZE;
- skip_size *= mono_array_length ((MonoArray*)start);
- skip_size += sizeof (MonoArray);
-#endif
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- //} else if (type == DESC_TYPE_SMALL_BITMAP) {
- case DESC_TYPE_SMALL_BITMAP:
- OBJ_BITMAP_FOREACH_PTR (desc,start);
- OBJ_BITMAP_SIZE (skip_size, desc, start);
- return start + skip_size;
- //} else if (type == DESC_TYPE_LARGE_BITMAP) {
- case DESC_TYPE_LARGE_BITMAP:
- OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start);
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- //} else if (type == DESC_TYPE_COMPLEX) {
- case DESC_TYPE_COMPLEX:
- OBJ_COMPLEX_FOREACH_PTR (vt, start);
- /* this is a complex object */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- //} else if (type == DESC_TYPE_COMPLEX_ARR) {
- case DESC_TYPE_COMPLEX_ARR:
- OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start);
- /* this is an array of complex structs */
- skip_size = safe_object_get_size ((MonoObject*)start);
-#if 0
- skip_size = mono_array_element_size (((MonoObject*)start)->vtable->klass);
- skip_size *= mono_array_length ((MonoArray*)start);
- skip_size += sizeof (MonoArray);
-#endif
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- }
- g_assert_not_reached ();
- return NULL;
+ return start;
}
/*
check_remsets_for_area (char *start, char *end)
{
GCVTable *vt;
- size_t skip_size;
- int type;
int type_str = 0, type_rlen = 0, type_bitmap = 0, type_vector = 0, type_lbit = 0, type_complex = 0;
- mword desc;
new_obj_references = 0;
obj_references_checked = 0;
while (start < end) {
MonoObject *obj = (MonoObject*)start;
g_print ("found at %p (0x%lx): %s.%s\n", start, (long)vt->desc, obj->vtable->klass->name_space, obj->vtable->klass->name);
}
- desc = vt->desc;
- type = desc & 0x7;
- if (type == DESC_TYPE_STRING) {
- STRING_SIZE (skip_size, start);
- start += skip_size;
- type_str++;
- continue;
- } else if (type == DESC_TYPE_RUN_LENGTH) {
- OBJ_RUN_LEN_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- OBJ_RUN_LEN_FOREACH_PTR (desc,start);
- start += skip_size;
- type_rlen++;
- continue;
- } else if (type == DESC_TYPE_VECTOR) { // includes ARRAY, too
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_VECTOR_FOREACH_PTR (vt, start);
- start += skip_size;
- type_vector++;
- continue;
- } else if (type == DESC_TYPE_SMALL_BITMAP) {
- OBJ_BITMAP_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- OBJ_BITMAP_FOREACH_PTR (desc,start);
- start += skip_size;
- type_bitmap++;
- continue;
- } else if (type == DESC_TYPE_LARGE_BITMAP) {
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start);
- start += skip_size;
- type_lbit++;
- continue;
- } else if (type == DESC_TYPE_COMPLEX) {
- /* this is a complex object */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_COMPLEX_FOREACH_PTR (vt, start);
- start += skip_size;
- type_complex++;
- continue;
- } else if (type == DESC_TYPE_COMPLEX_ARR) {
- /* this is an array of complex structs */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start);
- start += skip_size;
- type_complex++;
- continue;
- } else {
- g_assert (0);
- }
+
+#define SCAN_OBJECT_ACTION COUNT_OBJECT_TYPES
+#include "sgen-scan-object.h"
}
}
char*
check_object (char *start)
{
- GCVTable *vt;
- size_t skip_size;
- mword desc;
-
if (!start)
return NULL;
- vt = (GCVTable*)LOAD_VTABLE (start);
- //type = vt->desc & 0x7;
+#include "sgen-scan-object.h"
- desc = vt->desc;
- switch (desc & 0x7) {
- case DESC_TYPE_STRING:
- STRING_SIZE (skip_size, start);
- return start + skip_size;
- case DESC_TYPE_RUN_LENGTH:
- OBJ_RUN_LEN_FOREACH_PTR (desc,start);
- OBJ_RUN_LEN_SIZE (skip_size, desc, start);
- g_assert (skip_size);
- return start + skip_size;
- case DESC_TYPE_ARRAY:
- case DESC_TYPE_VECTOR:
- OBJ_VECTOR_FOREACH_PTR (vt, start);
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- case DESC_TYPE_SMALL_BITMAP:
- OBJ_BITMAP_FOREACH_PTR (desc,start);
- OBJ_BITMAP_SIZE (skip_size, desc, start);
- return start + skip_size;
- case DESC_TYPE_LARGE_BITMAP:
- OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start);
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- case DESC_TYPE_COMPLEX:
- OBJ_COMPLEX_FOREACH_PTR (vt, start);
- /* this is a complex object */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- case DESC_TYPE_COMPLEX_ARR:
- OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start);
- /* this is an array of complex structs */
- skip_size = safe_object_get_size ((MonoObject*)start);
- skip_size += (ALLOC_ALIGN - 1);
- skip_size &= ~(ALLOC_ALIGN - 1);
- return start + skip_size;
- }
- g_assert_not_reached ();
- return NULL;
+ return start;
}
/*
--- /dev/null
+/*
+ * Scans one object, using the OBJ_XXX macros. The start of the
+ * object must be given in the variable "char* start". Afterwards,
+ * "start" will point to the start of the next object.
+ *
+ * Modifiers (automatically undefined):
+ *
+ * SCAN_OBJECT_NOSCAN - if defined, don't actually scan the object,
+ * i.e. don't invoke the OBJ_XXX macros.
+ *
+ * SCAN_OBJECT_ACTION - is invoked after an object has been scanned.
+ * The object's start is "start", its length in bytes (including
+ * padding at the end) is "skip_size". "desc" is the object's GC
+ * descriptor.
+ */
+
+#ifndef SCAN_OBJECT_ACTION
+#define SCAN_OBJECT_ACTION
+#endif
+
+{
+ GCVTable *vt;
+ size_t skip_size;
+ mword desc;
+
+ vt = (GCVTable*)LOAD_VTABLE (start);
+ //type = vt->desc & 0x7;
+
+ /* gcc should be smart enough to remove the bounds check, but it isn't:( */
+ desc = vt->desc;
+ switch (desc & 0x7) {
+ case DESC_TYPE_STRING:
+ STRING_SIZE (skip_size, start);
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_RUN_LENGTH:
+ OBJ_RUN_LEN_SIZE (skip_size, desc, start);
+ g_assert (skip_size);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_RUN_LEN_FOREACH_PTR (desc, start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_ARRAY:
+ case DESC_TYPE_VECTOR:
+ skip_size = safe_object_get_size ((MonoObject*)start);
+ skip_size += (ALLOC_ALIGN - 1);
+ skip_size &= ~(ALLOC_ALIGN - 1);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_VECTOR_FOREACH_PTR (vt, start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_SMALL_BITMAP:
+ OBJ_BITMAP_SIZE (skip_size, desc, start);
+ g_assert (skip_size);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_BITMAP_FOREACH_PTR (desc, start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_LARGE_BITMAP:
+ skip_size = safe_object_get_size ((MonoObject*)start);
+ skip_size += (ALLOC_ALIGN - 1);
+ skip_size &= ~(ALLOC_ALIGN - 1);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_LARGE_BITMAP_FOREACH_PTR (vt,start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_COMPLEX:
+ /* this is a complex object */
+ skip_size = safe_object_get_size ((MonoObject*)start);
+ skip_size += (ALLOC_ALIGN - 1);
+ skip_size &= ~(ALLOC_ALIGN - 1);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_COMPLEX_FOREACH_PTR (vt, start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ case DESC_TYPE_COMPLEX_ARR:
+ /* this is an array of complex structs */
+ skip_size = safe_object_get_size ((MonoObject*)start);
+ skip_size += (ALLOC_ALIGN - 1);
+ skip_size &= ~(ALLOC_ALIGN - 1);
+#ifndef SCAN_OBJECT_NOSCAN
+ OBJ_COMPLEX_ARR_FOREACH_PTR (vt, start);
+#endif
+ SCAN_OBJECT_ACTION;
+ start += skip_size;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+#undef SCAN_OBJECT_NOSCAN
+#undef SCAN_OBJECT_ACTION
ares = mono_async_result_new (domain, NULL, ac->state, NULL, (MonoObject*)ac);
MONO_OBJECT_SETREF (ares, async_delegate, target);
- if (domain->state == MONO_APPDOMAIN_UNLOADED || domain->state == MONO_APPDOMAIN_UNLOADING)
- return ares;
-
EnterCriticalSection (&ares_lock);
+ if (domain->state == MONO_APPDOMAIN_UNLOADED || domain->state == MONO_APPDOMAIN_UNLOADING) {
+ LeaveCriticalSection (&ares_lock);
+ return ares;
+ }
mono_g_hash_table_insert (ares_htable, ares, ares);
LeaveCriticalSection (&ares_lock);
socket_io_cleanup (&socket_io_data);
}
+static void
+null_array (MonoArray *a, int first, int last)
+{
+ /* We must null the old array because it might
+ contain cross-appdomain references, which
+ will crash the GC when the domains are
+ unloaded. */
+ memset (mono_array_addr (a, MonoObject*, first), 0, sizeof (MonoObject*) * (last - first));
+}
+
static void
append_job (CRITICAL_SECTION *cs, TPQueue *list, MonoObject *ar)
{
threadpool_jobs_inc (ar);
EnterCriticalSection (cs);
+ if (ar->vtable->domain->state == MONO_APPDOMAIN_UNLOADING ||
+ ar->vtable->domain->state == MONO_APPDOMAIN_UNLOADED) {
+ LeaveCriticalSection (cs);
+ return;
+ }
if (list->array && (list->next_elem < mono_array_length (list->array))) {
mono_array_setref (list->array, list->next_elem, ar);
list->next_elem++;
/* slide the array or create a larger one if it's full */
if (list->first_elem) {
mono_array_memcpy_refs (list->array, 0, list->array, list->first_elem, count);
+ null_array (list->array, count, list->next_elem);
} else {
+ MonoArray *olda = list->array;
MonoArray *newa = mono_array_new_cached (mono_get_root_domain (), mono_defaults.object_class, mono_array_length (list->array) * 2);
mono_array_memcpy_refs (newa, 0, list->array, list->first_elem, count);
list->array = newa;
+ null_array (olda, list->first_elem, list->next_elem);
}
list->first_elem = 0;
list->next_elem = count;
LeaveCriticalSection (cs);
}
+static GSList *clear_ares_htable_entries = NULL;
+
+static void
+check_ares_htable_entry_for_domain (gpointer key, gpointer value, gpointer user_data)
+{
+ MonoObject *obj = key;
+ MonoDomain *domain = user_data;
+
+ g_assert (key == value);
+ if (obj->vtable->domain == domain)
+ clear_ares_htable_entries = g_slist_prepend (clear_ares_htable_entries, obj);
+}
+
/*
* Clean up the threadpool of all domain jobs.
* Can only be called as part of the domain unloading process as
HANDLE sem_handle;
int result = TRUE;
guint32 start_time = 0;
+ GSList *list;
+
+ g_assert (domain->state == MONO_APPDOMAIN_UNLOADING);
clear_queue (&mono_delegate_section, &async_call_queue, domain);
clear_queue (&io_queue_lock, &async_io_queue, domain);
domain->cleanup_semaphore = NULL;
CloseHandle (sem_handle);
+
+ EnterCriticalSection (&ares_lock);
+ g_assert (!clear_ares_htable_entries);
+ mono_g_hash_table_foreach (ares_htable, check_ares_htable_entry_for_domain, domain);
+ for (list = clear_ares_htable_entries; list; list = list->next)
+ mono_g_hash_table_remove (ares_htable, list->data);
+ g_slist_free (clear_ares_htable_entries);
+ clear_ares_htable_entries = NULL;
+ LeaveCriticalSection (&ares_lock);
+
return result;
}
count = list->next_elem - list->first_elem;
/* reduce the size of the array if it's mostly empty */
if (mono_array_length (list->array) > 16 && count < (mono_array_length (list->array) / 3)) {
+ MonoArray *olda = list->array;
MonoArray *newa = mono_array_new_cached (mono_get_root_domain (), mono_defaults.object_class, mono_array_length (list->array) / 2);
mono_array_memcpy_refs (newa, 0, list->array, list->first_elem, count);
list->array = newa;
+ null_array (olda, list->first_elem, list->next_elem);
list->first_elem = 0;
list->next_elem = count;
}
static void
free_queue (TPQueue *list)
{
+ if (list->array)
+ null_array (list->array, list->first_elem, list->next_elem);
list->array = NULL;
list->first_elem = list->next_elem = 0;
}
thread->abort_exc = NULL;
thread->current_appcontext = NULL;
+ /*
+ * This is necessary because otherwise we might have
+ * cross-domain references which will not get cleaned up when
+ * the target domain is unloaded.
+ */
+ if (thread->cached_culture_info) {
+ int i;
+ for (i = 0; i < NUM_CACHED_CULTURES * 2; ++i)
+ mono_array_set (thread->cached_culture_info, MonoObject*, i, NULL);
+ }
+
/* if the thread is not in the hash it has been removed already */
if (!handle_remove (thread))
return;
static MonoClassField*
-verifier_load_field (VerifyContext *ctx, int token, MonoClass **klass, const char *opcode) {
+verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const char *opcode) {
MonoClassField *field;
-
+ MonoClass *klass = NULL;
+
if (!IS_FIELD_DEF_OR_REF (token) || !token_bounds_check (ctx->image, token)) {
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid field token 0x%x08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
return NULL;
}
- field = mono_field_from_token (ctx->image, token, klass, ctx->generic_context);
- if (!field || !field->parent) {
+ field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
+ if (!field || !field->parent || !klass) {
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load field from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
return NULL;
}
- if (!mono_type_is_valid_in_context (ctx, &field->parent->byval_arg))
+ if (!mono_type_is_valid_in_context (ctx, &klass->byval_arg))
return NULL;
+ *out_klass = klass;
return field;
}
get_boxable_mono_type (VerifyContext* ctx, int token, const char *opcode)
{
MonoType *type;
-
+ MonoClass *class;
if (!(type = verifier_load_type (ctx, token, opcode)))
return NULL;
if (type->type == MONO_TYPE_TYPEDBYREF)
CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid use of typedbyref for %s at 0x%04x", opcode, ctx->ip_offset));
+ if (!(class = mono_class_from_mono_type (type)))
+ ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not retrieve type token for %s at 0x%04x", opcode, ctx->ip_offset));
+
+ if (class->generic_container && type->type != MONO_TYPE_GENERICINST)
+ CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the generic type definition in a boxable type position for %s at 0x%04x", opcode, ctx->ip_offset));
+
check_unverifiable_type (ctx, type);
return type;
}
+2009-08-18 Zoltan Varga <vargaz@gmail.com>
+
+ * aot-compiler.c (add_generic_instances): Fix the net 1.1 build.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * method-to-ir.c: Fix warnings for uninitialized variables.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * mini-exceptions.c:
+ * aot-compiler.c: Fix printf warnings.
+
+2009-08-18 Zoltan Varga <vargaz@gmail.com>
+
+ * aot-compiler.c (add_generic_instances): Add string[] wrapper methods.
+ Add GetGenericValueImpl<string>.
+
+ * aot-compiler.c (add_generic_instances): Add instances of
+ GenericEqualityComparer<T> for primitive types. Only emit the array
+ wrappers into the mscorlib image.
+
+2009-08-15 Zoltan Varga <vargaz@gmail.com>
+
+ * aot-runtime.c (load_method): Rename 'aot_module' -> 'amodule'. Allocate
+ the methods_loaded array using amodule->info->nmethods.
+
+ * mini.h (MonoAotFileInfo): Add an 'nmethods' field.
+ (MONO_AOT_FILE_VERSION): Bump this.
+
+ * aot-compiler.c: Emit more generic instances allowing some parts of linq
+ to work.
+
+ * aot-runtime.c (mono_aot_get_unwind_info): Handle the case when the
+ MonoJitInfo doesn't belong to its methods aot image.
+
+2009-08-14 Zoltan Varga <vargaz@gmail.com>
+
+ * mini-arm.c (mono_arch_allocate_vars): Use SP as the default frame reg.
+
+ * mini-arm.c: Fix warnings.
+
+ * mini-arm.c (mono_arm_emit_load_imm): Only emit a movt if needed.
+
+ * mini-arm.c (mono_arm_emit_load_imm): Use movt/movw if the cpu
+ supports it.
+
+2009-08-12 Zoltan Varga <vargaz@gmail.com>
+
+ * aot-compiler.c (arch_emit_imt_thunk): Rework the arm code to
+ avoid clobbering IP.
+
+ * mini-trampolines.c (mono_magic_trampoline): Allocate a local to
+ hold the trampoline argument, so its initial value is available during
+ debugging.
+
+2009-08-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * exceptions-arm.c:
+ * exceptions-hppa.c:
+ * mini.c:
+ * exceptions-s390x.c:
+ * exceptions-mips.c:
+ * exceptions-ppc.c:
+ * exceptions-sparc.c:
+ * exceptions-alpha.c:
+ * aot-runtime.c:
+ * mini-trampolines.c:
+ * exceptions-x86.c:
+ * exceptions-s390.c: add and use #define's instead of sizeof()
+ for MonoJitInfo and MonoJitInfoTable.
+
+2009-08-10 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * tramp-arm.c:
+ * tramp-amd64.c:
+ * tramp-ppc.c:
+ * tramp-x86.c: use a #define instead of sizeof() for a few
+ structures that use a zero-length array.
+
2009-08-07 Rodrigo Kumpera <rkumpera@novell.com>
* method-to-ir.c (mono_method_to_ir/CEE_CONSTRAINED_): Handle the
/* The IMT method is in v5 */
- /* Only IP is available, but we need at least two free registers */
- ARM_PUSH1 (code, ARMREG_R1);
+ /* Need at least two free registers, plus a slot for storing the pc */
+ ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2));
labels [0] = code;
/* Load the parameter from the GOT */
- ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
- ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
+ ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+ ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0);
labels [1] = code;
- ARM_LDR_IMM (code, ARMREG_R1, ARMREG_IP, 0);
+ ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0);
ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5);
labels [2] = code;
ARM_B_COND (code, ARMCOND_EQ, 0);
ARM_B_COND (code, ARMCOND_EQ, 0);
/* Loop footer */
- ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, sizeof (gpointer) * 2);
+ ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (gpointer) * 2);
labels [4] = code;
ARM_B (code, 0);
arm_patch (labels [4], labels [1]);
/* Match */
arm_patch (labels [2], code);
- ARM_POP1 (code, ARMREG_R1);
- ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 4);
- ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, 0);
+ ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4);
+ ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0);
+ /* Save it to the third stack slot */
+ ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8);
+ /* Restore the registers and branch */
+ ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC));
/* No match */
arm_patch (labels [3], code);
/* Fixup offset */
code2 = labels [0];
- ARM_LDR_IMM (code2, ARMREG_IP, ARMREG_PC, (code - (labels [0] + 8)));
+ ARM_LDR_IMM (code2, ARMREG_R0, ARMREG_PC, (code - (labels [0] + 8)));
emit_bytes (acfg, buf, code - buf);
emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4);
add_extra_method (acfg, method);
}
+ if (klass->delegate) {
+ method = mono_get_delegate_invoke (klass);
+
+ method = mono_marshal_get_delegate_invoke (method, NULL);
+
+ add_method (acfg, method);
+ }
+
/*
* For ICollection<T>, where T is a vtype, add instances of the helper methods
* in Array, since a T[] could be cast to ICollection<T>.
}
}
+static void
+add_array_wrappers (MonoAotCompile *acfg, MonoClass *klass)
+{
+ int i;
+
+ mono_class_setup_methods (klass);
+ for (i = 0; i < klass->method.count; ++i) {
+ if (klass->methods [i]->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED)
+ add_extra_method (acfg, klass->methods [i]);
+ }
+}
+
/*
* add_generic_instances:
*
ctx.class_inst = mono_metadata_get_generic_inst (1, args);
add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
}
+
+ /* Add GenericEqualityComparer<T> instances for primitive types */
+ klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
+
+ if (klass) {
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ args [0] = &mono_defaults.byte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.sbyte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+ }
+
+ /* Emit the array wrapper methods for arrays of primitive types */
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.byte_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.sbyte_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int16_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint16_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int32_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint32_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int64_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.single_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.double_class, 1));
+ /* These are not handled by generic sharing */
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.object_class, 1));
+ add_array_wrappers (acfg, mono_array_class_get (mono_defaults.string_class, 1));
+
+ /* Add instances of Array.GetGenericValueImpl */
+ {
+ MonoGenericContext ctx;
+ MonoType *args [16];
+ MonoMethod *method;
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ /*
+ * managed-to-native wrappers are not shared, so have to generate
+ * these for ref types too.
+ */
+ klass = mono_array_class_get (mono_defaults.int_class, 1)->parent;
+ method = mono_class_get_method_from_name (klass, "GetGenericValueImpl", 2);
+
+ if (method) {
+ /* String */
+ args [0] = &mono_defaults.string_class->byval_arg;
+ ctx.method_inst = mono_metadata_get_generic_inst (1, args);
+ add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (method, &ctx), TRUE, TRUE));
+ }
+ }
}
}
}
break;
}
+ case MONO_PATCH_INFO_VTABLE: {
+ MonoClass *klass = patch_info->data.klass;
+
+ if (klass->generic_class && !mono_generic_context_is_sharable (&klass->generic_class->context, FALSE))
+ add_generic_class (acfg, klass);
+ break;
+ }
default:
break;
}
char symbol [256];
/* Don't make GOT global so accesses to it don't need relocations */
- sprintf (symbol, acfg->got_symbol);
+ sprintf (symbol, "%s", acfg->got_symbol);
emit_section_change (acfg, ".bss", 0);
emit_alignment (acfg, 8);
emit_local_symbol (acfg, symbol, "got_end", FALSE);
emit_int32 (acfg, acfg->plt_got_offset_base);
emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
emit_int32 (acfg, acfg->plt_offset);
+ emit_int32 (acfg, acfg->nmethods);
for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
emit_int32 (acfg, acfg->num_trampolines [i]);
*/
static GHashTable *static_aot_modules;
+/*
+ * Maps MonoJitInfo* to the aot module they belong to, this can be different
+ * from ji->method->klass->image's aot module for generic instances.
+ */
+static GHashTable *ji_to_amodule;
+
/*
* Whenever to AOT compile loaded assemblies on demand and store them in
* a cache under $HOME/.mono/aot-cache.
* LOCKING: Acquires the domain lock.
*/
static MonoJitInfo*
-decode_exception_debug_info (MonoAotModule *aot_module, MonoDomain *domain,
+decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
MonoMethod *method, guint8* ex_info, guint8 *code)
{
int i, buf_len;
/* Exception table */
if (header && header->num_clauses) {
jinfo =
- mono_domain_alloc0 (domain, sizeof (MonoJitInfo) + (sizeof (MonoJitExceptionInfo) * header->num_clauses) + generic_info_size);
+ mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * header->num_clauses) + generic_info_size);
jinfo->num_clauses = header->num_clauses;
for (i = 0; i < header->num_clauses; ++i) {
}
}
else {
- jinfo = mono_domain_alloc0 (domain, sizeof (MonoJitInfo) + generic_info_size);
+ jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + generic_info_size);
}
jinfo->code_size = code_len;
/* This currently contains no data */
gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
- jinfo->method = decode_method_ref_2 (aot_module, p, &p);
+ jinfo->method = decode_method_ref_2 (amodule, p, &p);
}
/* Load debug info */
buf_len = decode_value (p, &p);
mono_debug_add_aot_method (domain, method, code, p, buf_len);
+
+ if (amodule != jinfo->method->klass->image->aot_module) {
+ mono_aot_lock ();
+ if (!ji_to_amodule)
+ ji_to_amodule = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (ji_to_amodule, jinfo, amodule);
+ mono_aot_unlock ();
+ }
return jinfo;
}
{
MonoAotModule *amodule = ji->method->klass->image->aot_module;
guint8 *p;
+ guint8 *code = ji->code_start;
g_assert (amodule);
g_assert (ji->from_aot);
+ if (!(code >= amodule->code && code <= amodule->code_end)) {
+ /* ji belongs to a different aot module than amodule */
+ mono_aot_lock ();
+ g_assert (ji_to_amodule);
+ amodule = g_hash_table_lookup (ji_to_amodule, ji);
+ g_assert (amodule);
+ g_assert (code >= amodule->code && code <= amodule->code_end);
+ }
+
p = amodule->unwind_info + ji->used_regs;
*unwind_info_len = decode_value (p, &p);
return p;
* METHOD might not be set if the caller only has the image/token info.
*/
static gpointer
-load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
+load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
{
MonoClass *klass;
gboolean from_plt = method == NULL;
if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE)
return NULL;
- if ((domain != mono_get_root_domain ()) && (!(aot_module->opts & MONO_OPT_SHARED)))
+ if ((domain != mono_get_root_domain ()) && (!(amodule->opts & MONO_OPT_SHARED)))
/* Non shared AOT code can't be used in other appdomains */
return NULL;
- if (aot_module->out_of_date)
+ if (amodule->out_of_date)
return NULL;
- if (aot_module->code_offsets [method_index] == 0xffffffff) {
+ if (amodule->code_offsets [method_index] == 0xffffffff) {
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
char *full_name;
return NULL;
}
- code = &aot_module->code [aot_module->code_offsets [method_index]];
- info = &aot_module->method_info [aot_module->method_info_offsets [method_index]];
+ code = &amodule->code [amodule->code_offsets [method_index]];
+ info = &amodule->method_info [amodule->method_info_offsets [method_index]];
mono_aot_lock ();
- if (!aot_module->methods_loaded)
- aot_module->methods_loaded = g_new0 (guint32, image->tables [MONO_TABLE_METHOD].rows + 1);
+ if (!amodule->methods_loaded)
+ amodule->methods_loaded = g_new0 (guint32, amodule->info.nmethods + 1);
mono_aot_unlock ();
- if ((aot_module->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
+ if ((amodule->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
return code;
if (mono_last_aot_method != -1) {
if (method) {
klass = method->klass;
- decode_klass_ref (aot_module, p, &p);
+ decode_klass_ref (amodule, p, &p);
} else {
- klass = decode_klass_ref (aot_module, p, &p);
+ klass = decode_klass_ref (amodule, p, &p);
}
- if (aot_module->opts & MONO_OPT_SHARED)
+ if (amodule->opts & MONO_OPT_SHARED)
used_strings = decode_value (p, &p);
else
used_strings = 0;
mono_ldstr (mono_get_root_domain (), image, mono_metadata_token_index (token));
}
- if (aot_module->opts & MONO_OPT_SHARED)
+ if (amodule->opts & MONO_OPT_SHARED)
keep_patches = FALSE;
n_patches = decode_value (p, &p);
else
mp = mono_mempool_new ();
- patches = load_patch_info (aot_module, mp, n_patches, &got_slots, p, &p);
+ patches = load_patch_info (amodule, mp, n_patches, &got_slots, p, &p);
if (patches == NULL)
goto cleanup;
for (pindex = 0; pindex < n_patches; ++pindex) {
MonoJumpInfo *ji = &patches [pindex];
- if (!aot_module->got [got_slots [pindex]]) {
- aot_module->got [got_slots [pindex]] = mono_resolve_patch_target (method, domain, code, ji, TRUE);
+ if (!amodule->got [got_slots [pindex]]) {
+ amodule->got [got_slots [pindex]] = mono_resolve_patch_target (method, domain, code, ji, TRUE);
if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
- aot_module->got [got_slots [pindex]] = mono_create_ftnptr (domain, aot_module->got [got_slots [pindex]]);
+ amodule->got [got_slots [pindex]] = mono_create_ftnptr (domain, amodule->got [got_slots [pindex]]);
if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
- register_jump_target_got_slot (domain, ji->data.method, &(aot_module->got [got_slots [pindex]]));
+ register_jump_target_got_slot (domain, ji->data.method, &(amodule->got [got_slots [pindex]]));
}
ji->type = MONO_PATCH_INFO_NONE;
}
full_name = mono_method_full_name (method, TRUE);
if (!jinfo) {
- ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [method_index]];
- jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
+ ex_info = &amodule->ex_info [amodule->ex_info_offsets [method_index]];
+ jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, code);
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", full_name, code, code + jinfo->code_size, info);
mono_jit_stats.methods_aot++;
- aot_module->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
+ amodule->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
- init_plt (aot_module);
+ init_plt (amodule);
if (method && method->wrapper_type)
- g_hash_table_insert (aot_module->method_to_code, method, code);
+ g_hash_table_insert (amodule->method_to_code, method, code);
mono_aot_unlock ();
cleanup:
/* FIXME: The space in domain->mp is wasted */
- if (aot_module->opts & MONO_OPT_SHARED)
+ if (amodule->opts & MONO_OPT_SHARED)
/* No need to cache patches */
mono_mempool_destroy (mp);
sizeof (MonoDebuggerMetadataInfo),
sizeof (MonoDefaults),
&mono_defaults,
- sizeof (MonoType),
+ MONO_SIZEOF_TYPE,
sizeof (MonoArrayType),
sizeof (MonoClass),
sizeof (MonoThread),
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
} else {
if (!(*lmf)->method)
return (gpointer)-1;
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
memcpy (&new_ctx->sc_regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
if (!(*lmf)->method)
return (gpointer)-1;
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->ip))) {
} else {
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
/* Top LMF entry */
return (gpointer)-1;
/* Trampoline lmf frame */
- memset (res, 0, sizeof (MonoJitInfo));
+ memset (res, 0, MONO_SIZEOF_JIT_INFO);
res->method = (*lmf)->method;
}
mono_emit_rgctx_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig,
MonoInst **args, MonoInst *this, MonoInst *imt_arg, MonoInst *vtable_arg)
{
- int rgctx_reg;
+ int rgctx_reg = 0;
MonoInst *ins;
MonoCallInst *call;
cfg->cbb = bb;
for (; ins; ins = ins->next) {
const char *spec = INS_INFO (ins->opcode);
- int regtype, regindex;
+ int regtype = 0, regindex;
gint32 prev_bb;
if (G_UNLIKELY (cfg->verbose_level > 2))
g_assert (ins->opcode >= MONO_CEE_LAST);
for (regindex = 0; regindex < 4; regindex ++) {
- int vreg;
+ int vreg = 0;
if (regindex == 0) {
regtype = spec [MONO_INST_DEST];
static CRITICAL_SECTION mini_arch_mutex;
static int v5_supported = 0;
+static int v7_supported = 0;
static int thumb_supported = 0;
/*
if (((ldr >> 23) & 1) == 0) /*U bit, 0 means negative and 1 positive*/
offset = -offset;
/*g_print ("found vcall at r%d + %d for code at %p 0x%x\n", reg, offset, code, *code);*/
- o = regs [reg];
+ o = (gpointer)regs [reg];
*displacement = offset;
return o;
while ((line = fgets (buf, 512, file))) {
if (strncmp (line, "Processor", 9) == 0) {
char *ver = strstr (line, "(v");
- if (ver && (ver [2] == '5' || ver [2] == '6' || ver [2] == '7')) {
+ if (ver && (ver [2] == '5' || ver [2] == '6' || ver [2] == '7'))
v5_supported = TRUE;
- }
+ if (ver && (ver [2] == '7'))
+ v7_supported = TRUE;
continue;
}
if (strncmp (line, "Features", 8) == 0) {
MonoMethodHeader *header;
MonoInst *inst;
int i, offset, size, align, curinst;
- int frame_reg = ARMREG_FP;
+ int frame_reg = ARMREG_SP;
/* FIXME: this will change when we use FP as gcc does */
cfg->flags |= MONO_CFG_HAS_SPILLUP;
mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
{
MonoInst *ins;
- int vreg;
if (long_ins->opcode == OP_LNEG) {
ins = long_ins;
} else if ((imm8 = mono_arm_is_rotated_imm8 (~val, &rot_amount)) >= 0) {
ARM_MVN_REG_IMM (code, dreg, imm8, rot_amount);
} else {
+ if (v7_supported) {
+ ARM_MOVW_REG_IMM (code, dreg, val & 0xffff);
+ if (val >> 16)
+ ARM_MOVT_REG_IMM (code, dreg, (val >> 16) & 0xffff);
+ return code;
+ }
if (val & 0xFF) {
ARM_MOV_REG_IMM8 (code, dreg, (val & 0xFF));
if (val & 0xFF00) {
break;
case OP_LCONV_TO_OVF_I:
case OP_LCONV_TO_OVF_I4_2: {
- guint32 *high_bit_not_set, *valid_negative, *invalid_negative, *valid_positive;
+ guint8 *high_bit_not_set, *valid_negative, *invalid_negative, *valid_positive;
/*
* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000
*/
printf ("\t<Stack traces in thread dumps not supported on this platform>\n");
#endif
- fprintf (stdout, text->str);
+ fprintf (stdout, "%s", text->str);
g_string_free (text, TRUE);
fflush (stdout);
}
* This trampoline handles calls from JITted code.
*/
gpointer
-mono_magic_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tramp)
+mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp)
{
gpointer addr;
gpointer *vtable_slot;
gboolean generic_shared = FALSE;
+ MonoMethod *m;
MonoMethod *declaring = NULL;
MonoMethod *generic_virtual = NULL;
int context_used;
gboolean proxy = FALSE;
gboolean need_rgctx_tramp = FALSE;
+ m = arg;
+
if (m == MONO_FAKE_VTABLE_METHOD) {
int displacement;
MonoVTable *vt = mono_arch_get_vcall_slot (code, regs, &displacement);
code = mono_create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get (), &code_size);
g_assert (code_size);
- ji = mono_domain_alloc0 (domain, sizeof (MonoJitInfo));
+ ji = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
ji->code_start = code;
ji->code_size = code_size;
ji->method = method;
generic_info_size = 0;
if (cfg->method->dynamic) {
- jinfo = g_malloc0 (sizeof (MonoJitInfo) + (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
+ jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
generic_info_size);
} else {
- jinfo = mono_domain_alloc0 (cfg->domain, sizeof (MonoJitInfo) +
+ jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
(header->num_clauses * sizeof (MonoJitExceptionInfo)) +
generic_info_size);
}
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "57"
+#define MONO_AOT_FILE_VERSION "58"
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
guint32 plt_got_offset_base;
guint32 got_size;
guint32 plt_size;
+ guint32 nmethods;
guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
gpointer mono_create_llvm_vcall_trampoline (MonoMethod *method) MONO_INTERNAL;
MonoVTable* mono_find_class_init_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
guint32 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
-gpointer mono_magic_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tramp) MONO_INTERNAL;
+gpointer mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp) MONO_INTERNAL;
gpointer mono_generic_virtual_remoting_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8 *tramp) MONO_INTERNAL;
gpointer mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp) MONO_INTERNAL;
gpointer mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
if (mrgctx)
- index += sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
for (depth = 0; ; ++depth) {
int size = mono_class_rgctx_get_array_size (depth, mrgctx);
for (i = 0; i < depth; ++i) {
/* load ptr to next array */
if (mrgctx && i == 0)
- amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, sizeof (MonoMethodRuntimeGenericContext), 8);
+ amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 8);
else
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RAX, 0, 8);
/* is the ptr null? */
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
if (mrgctx)
- index += sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
for (depth = 0; ; ++depth) {
int size = mono_class_rgctx_get_array_size (depth, mrgctx);
for (i = 0; i < depth; ++i) {
/* load ptr to next array */
if (mrgctx && i == 0) {
- g_assert (arm_is_imm12 (sizeof (MonoMethodRuntimeGenericContext)));
- ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R1, sizeof (MonoMethodRuntimeGenericContext));
+ g_assert (arm_is_imm12 (MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT));
+ ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
} else {
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R1, 0);
}
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
if (mrgctx)
- index += sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
for (depth = 0; ; ++depth) {
int size = mono_class_rgctx_get_array_size (depth, mrgctx);
for (i = 0; i < depth; ++i) {
/* load ptr to next array */
if (mrgctx && i == 0)
- ppc_ldptr (code, ppc_r4, sizeof (MonoMethodRuntimeGenericContext), ppc_r4);
+ ppc_ldptr (code, ppc_r4, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, ppc_r4);
else
ppc_ldptr (code, ppc_r4, 0, ppc_r4);
/* is the ptr null? */
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
if (mrgctx)
- index += sizeof (MonoMethodRuntimeGenericContext) / sizeof (gpointer);
+ index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
for (depth = 0; ; ++depth) {
int size = mono_class_rgctx_get_array_size (depth, mrgctx);
for (i = 0; i < depth; ++i) {
/* load ptr to next array */
if (mrgctx && i == 0)
- x86_mov_reg_membase (buf, X86_EAX, X86_EAX, sizeof (MonoMethodRuntimeGenericContext), 4);
+ x86_mov_reg_membase (buf, X86_EAX, X86_EAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 4);
else
x86_mov_reg_membase (buf, X86_EAX, X86_EAX, 0, 4);
/* is the ptr null? */
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * monograph.c: Fix printf warnings.
Mon Sep 10 15:03:06 CEST 2007 Paolo Molaro <lupus@ximian.com>
next = tmp->data;
if (!next->dfn) {
if (!bb->cil_code)
- fprintf (output, "\t\"DF entry\" -> \"IL_%04x (%d)\"\n", next->cil_code - code, *dfn + 1);
+ fprintf (output, "\t\"DF entry\" -> \"IL_%04x (%d)\"\n", (unsigned int)(next->cil_code - code), *dfn + 1);
else
- fprintf (output, "\t\"IL_%04x (%d)\" -> \"IL_%04x (%d)\"\n", bb->cil_code - code, bb->dfn, next->cil_code - code, *dfn + 1);
+ fprintf (output, "\t\"IL_%04x (%d)\" -> \"IL_%04x (%d)\"\n", (unsigned int)(bb->cil_code - code), bb->dfn, (unsigned int)(next->cil_code - code), *dfn + 1);
df_visit (next, dfn, code);
}
}
fprintf (output, "\tB%p [shape=record,label=\"end\"]\n", bb);
else {
code = mono_disasm_code (&graph_dh, method, bb->cil_code, bb->cil_code + bb->cil_length);
- fprintf (output, "\tB%p [shape=record,label=\"IL_%04x\\n%s\"]\n", bb, bb->cil_code - il_code, code);
+ fprintf (output, "\tB%p [shape=record,label=\"IL_%04x\\n%s\"]\n", bb, (unsigned int)(bb->cil_code - il_code), code);
g_free (code);
}
}
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * mono-profiler-aot.c:
+ * mono-cov.c: Add missing method declarations.
+
+2009-08-14 Massimiliano Mantione <massi@ximian.com>
+ * mono-profiler-logging.c (disable_profiler):
+ Flush buffers synchronously so the GUI knows when we are done.
+
+2009-08-14 Massimiliano Mantione <massi@ximian.com>
+ * mono-profiler-logging.c:
+ - Added user thread reading commands from a local tcp port.
+ - Fixed file flushing after writing a block.
+ - Force full buffer flushing after disabling the profiler.
+
2009-08-06 Massimiliano Mantione <massi@ximian.com>
* mono-profiler-logging.c:
- Avoid registering the writer thread with the runtime unless when
{
}
+void
+mono_profiler_startup (const char *desc);
+
/* the entry point */
void
mono_profiler_startup (const char *desc)
data->methods = g_list_append (data->methods, method);
}
+void
+mono_profiler_startup (const char *desc);
+
/* the entry point */
void
mono_profiler_startup (const char *desc)
#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
#define HAS_OPROFILE 0
#if (HAS_OPROFILE)
#define THREAD_TYPE pthread_t
#define CREATE_WRITER_THREAD(f) pthread_create (&(profiler->data_writer_thread), NULL, ((void*(*)(void*))f), NULL)
+#define CREATE_USER_THREAD(f) pthread_create (&(profiler->user_thread), NULL, ((void*(*)(void*))f), NULL)
#define EXIT_THREAD() pthread_exit (NULL);
#define WAIT_WRITER_THREAD() do {\
if (CHECK_WRITER_THREAD ()) {\
#define OPEN_FILE() profiler->file = fopen (profiler->file_name, "wb");
#define WRITE_BUFFER(b,s) fwrite ((b), 1, (s), profiler->file)
#define FLUSH_FILE() fflush (profiler->file)
-#define CLOSE_FILE() fclose (profiler->file);
+#define CLOSE_FILE() fclose (profiler->file)
#else
#define FILE_HANDLE_TYPE int
#define OPEN_FILE() profiler->file = open (profiler->file_name, O_WRONLY|O_CREAT|O_TRUNC, 0664);
#define WRITE_BUFFER(b,s) write (profiler->file, (b), (s))
-#define FLUSH_FILE()
-#define CLOSE_FILE() close (profiler->file);
+#define FLUSH_FILE() fsync (profiler->file)
+#define CLOSE_FILE() close (profiler->file)
#endif
#else
ProfilerCodeChunks code_chunks;
THREAD_TYPE data_writer_thread;
+ THREAD_TYPE user_thread;
EVENT_TYPE enable_data_writer_event;
EVENT_TYPE wake_data_writer_event;
EVENT_TYPE done_data_writer_event;
ProfilerHeapShotWriteJob *heap_shot_write_jobs;
ProfilerHeapShotHeapBuffers heap;
+ int command_port;
+
char *heap_shot_command_file_name;
int dump_next_heap_snapshots;
guint64 heap_shot_command_file_access_time;
profiler->profiler_enabled = TRUE;
}
+static void flush_everything (void);
+
static void
disable_profiler (void) {
profiler->profiler_enabled = FALSE;
+ flush_everything ();
}
#define DEBUG_CLASS_BITMAPS 0
#define DEBUG_STATISTICAL_PROFILER 0
#define DEBUG_WRITER_THREAD 0
+#define DEBUG_USER_THREAD 0
#define DEBUG_FILE_WRITES 0
#if (DEBUG_LOGGING_PROFILER || DEBUG_STATISTICAL_PROFILER || DEBUG_HEAP_PROFILER || DEBUG_WRITER_THREAD || DEBUG_FILE_WRITES)
#define LOG_WRITER_THREAD(m) printf ("WRITER-THREAD-LOG %s\n", m)
#else
#define LOG_WRITER_THREAD(m)
#endif
+#if (DEBUG_LOGGING_PROFILER || DEBUG_STATISTICAL_PROFILER || DEBUG_HEAP_PROFILER || DEBUG_USER_THREAD || DEBUG_FILE_WRITES)
+#define LOG_USER_THREAD(m) printf ("USER-THREAD-LOG %s\n", m)
+#else
+#define LOG_USER_THREAD(m)
+#endif
#if DEBUG_LOGGING_PROFILER
static int event_counter = 0;
LOG_WRITER_THREAD ("runtime_initialized: initialized internal calls.\n");
}
+
+#define MAX_COMMAND_LENGTH (1024)
+static int server_socket;
+static int command_socket;
+
+static void
+write_user_response (const char *response) {
+ LOG_USER_THREAD ("write_user_response: writing response:");
+ LOG_USER_THREAD (response);
+ send (command_socket, response, strlen (response), 0);
+}
+
+static void
+execute_user_command (char *command) {
+ char *line_feed;
+
+ LOG_USER_THREAD ("execute_user_command: executing command:");
+ LOG_USER_THREAD (command);
+
+ /* Ignore leading and trailing '\r' */
+ line_feed = strchr (command, '\r');
+ if (line_feed == command) {
+ command ++;
+ line_feed = strchr (command, '\r');
+ }
+ if ((line_feed != NULL) && (* (line_feed + 1) == 0)) {
+ *line_feed = 0;
+ }
+
+ if (strcmp (command, "enable") == 0) {
+ LOG_USER_THREAD ("execute_user_command: enabling profiler");
+ enable_profiler ();
+ write_user_response ("DONE\n");
+ } else if (strcmp (command, "disable") == 0) {
+ LOG_USER_THREAD ("execute_user_command: disabling profiler");
+ disable_profiler ();
+ write_user_response ("DONE\n");
+ } else {
+ LOG_USER_THREAD ("execute_user_command: command not recognized");
+ write_user_response ("ERROR\n");
+ }
+}
+
+static gboolean
+process_user_commands (void) {
+ char *command_buffer = malloc (MAX_COMMAND_LENGTH);
+ int command_buffer_current_index = 0;
+ gboolean loop = TRUE;
+ gboolean result = TRUE;
+
+ while (loop) {
+ int unprocessed_characters;
+
+ LOG_USER_THREAD ("process_user_commands: reading from socket...");
+ unprocessed_characters = recv (command_socket, command_buffer + command_buffer_current_index, MAX_COMMAND_LENGTH - command_buffer_current_index, 0);
+
+ if (unprocessed_characters > 0) {
+ char *command_end = NULL;
+
+ LOG_USER_THREAD ("process_user_commands: received characters.");
+
+ do {
+ if (command_end != NULL) {
+ *command_end = 0;
+ execute_user_command (command_buffer);
+ unprocessed_characters -= (((command_end - command_buffer) - command_buffer_current_index) + 1);
+
+ if (unprocessed_characters > 0) {
+ memmove (command_buffer, command_end + 1, unprocessed_characters);
+ }
+ command_buffer_current_index = 0;
+ }
+
+ command_end = memchr (command_buffer, '\n', command_buffer_current_index + unprocessed_characters);
+ } while (command_end != NULL);
+
+ command_buffer_current_index += unprocessed_characters;
+
+ } else if (unprocessed_characters == 0) {
+ LOG_USER_THREAD ("process_user_commands: received no character.");
+ result = TRUE;
+ loop = FALSE;
+ } else {
+ LOG_USER_THREAD ("process_user_commands: received error.");
+ result = FALSE;
+ loop = FALSE;
+ }
+ }
+
+ free (command_buffer);
+ return result;
+}
+
+static guint32
+user_thread (gpointer nothing) {
+ struct sockaddr_in server_address;
+
+ server_socket = -1;
+ command_socket = -1;
+
+ LOG_USER_THREAD ("user_thread: starting up...");
+
+ server_socket = socket (AF_INET, SOCK_STREAM, 0);
+ if (server_socket < 0) {
+ LOG_USER_THREAD ("user_thread: error creating socket.");
+ return 0;
+ }
+ memset (& server_address, 0, sizeof (server_address));
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_addr.s_addr = INADDR_ANY;
+ if ((profiler->command_port < 1023) || (profiler->command_port > 65535)) {
+ LOG_USER_THREAD ("user_thread: invalid port number.");
+ return 0;
+ }
+ server_address.sin_port = htons (profiler->command_port);
+
+ if (bind (server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
+ LOG_USER_THREAD ("user_thread: error binding socket.");
+ close (server_socket);
+ return 0;
+ }
+
+ LOG_USER_THREAD ("user_thread: listening...\n");
+ listen (server_socket, 1);
+ command_socket = accept (server_socket, NULL, NULL);
+ if (command_socket < 0) {
+ LOG_USER_THREAD ("user_thread: error accepting socket.");
+ close (server_socket);
+ return 0;
+ }
+
+ LOG_USER_THREAD ("user_thread: processing user commands...");
+ process_user_commands ();
+
+ LOG_USER_THREAD ("user_thread: exiting cleanly.");
+ close (server_socket);
+ close (command_socket);
+ return 0;
+}
+
+
/* called at the end of the program */
static void
profiler_shutdown (MonoProfiler *prof)
if (strlen (equals + 1) > 0) {
profiler->dump_next_heap_snapshots = atoi (equals + 1);
}
+ } else if (! (strncmp (argument, "command-port", equals_position) && strncmp (argument, "cp", equals_position))) {
+ FAIL_IF_HAS_MINUS;
+ if (strlen (equals + 1) > 0) {
+ profiler->command_port = atoi (equals + 1);
+ }
#ifndef PLATFORM_WIN32
} else if (! (strncmp (argument, "toggle-signal", equals_position) && strncmp (argument, "ts", equals_position))) {
FAIL_IF_HAS_MINUS;
UNLOCK_PROFILER ();
LOG_WRITER_THREAD ("data_writer_thread: wrote data and released lock");
+ } else {
+ LOG_WRITER_THREAD ("data_writer_thread: acquiring lock and flushing buffers");
+ LOCK_PROFILER ();
+ LOG_WRITER_THREAD ("data_writer_thread: lock acquired, flushing buffers");
+ flush_everything ();
+ UNLOCK_PROFILER ();
+ LOG_WRITER_THREAD ("data_writer_thread: flushed buffers and released lock");
}
if (profiler->terminate_writer_thread) {
LOG_WRITER_THREAD ("mono_profiler_startup: creating writer thread");
CREATE_WRITER_THREAD (data_writer_thread);
LOG_WRITER_THREAD ("mono_profiler_startup: created writer thread");
+ if ((profiler->command_port >= 1024) && (profiler->command_port <= 65535)) {
+ LOG_USER_THREAD ("mono_profiler_startup: creating user thread");
+ CREATE_USER_THREAD (user_thread);
+ LOG_USER_THREAD ("mono_profiler_startup: created user thread");
+ } else {
+ LOG_USER_THREAD ("mono_profiler_startup: skipping user thread creation");
+ }
ALLOCATE_PROFILER_THREAD_DATA ();
+2009-08-12 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * bug-528055.il: Regression test for #528055.
+
2009-08-04 Atsushi Enomoto <atsushi@ximian.com>
* make_imt_test.sh: fix freebsd build by Makoto Kishimoto
bug445361.il \
bug-463303.il \
bug469742.2.il \
+ bug-528055.il \
bug-481403.il
# bug-318677.il
--- /dev/null
+.assembly extern mscorlib
+{
+ .ver 2:0:0:0
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+}
+.assembly 'simple_assembly'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module simple_assembly.exe
+
+.class sealed public auto ansi beforefieldinit Generic`1<T>
+{
+ .method public hidebysig specialname rtspecialname instance default void '.ctor' ()
+ {
+ .maxstack 8
+ ldarg.0
+ call instance void object::'.ctor'()
+ ret
+ }
+
+ .field public !T a
+ .field public int32 a
+}
+
+
+.class sealed public auto ansi beforefieldinit Regular
+{
+ .method public hidebysig specialname rtspecialname instance default void '.ctor' ()
+ {
+ .maxstack 8
+ ldarg.0
+ call instance void object::'.ctor'()
+ ret
+ }
+
+ .field public float32 a
+ .field public int32 a
+}
+
+.class public auto ansi beforefieldinit Program
+{
+ .method public static int32 Main () cil managed
+ {
+ .entrypoint
+ .maxstack 8
+ .locals init (class Generic`1<float32> V_0, class Regular V_1)
+
+ newobj instance void class Generic`1<float32>::'.ctor'()
+ stloc.0
+ ldloc.0
+ ldc.r4 2.
+ stfld !0 class Generic`1<float32>::a
+ ldloc.0
+ ldc.i4.s 0x0a
+ stfld int32 class Generic`1<float32>::a
+ ldloc.0
+ ldfld !0 class Generic`1<float32>::a
+ ldc.r4 2.
+ beq TEST_2
+
+ ldc.i4.1
+ ret
+TEST_2:
+ ldloc.0
+ ldfld int32 class Generic`1<float32>::a
+ ldc.i4.s 0x0a
+ beq TEST_3
+
+ ldc.i4.2
+ ret
+TEST_3:
+ newobj instance void class Regular::'.ctor'()
+ stloc.1
+ ldloc.1
+ ldc.r4 2.
+ stfld float32 Regular::a
+ ldloc.1
+ ldc.i4.s 0x0a
+ stfld int32 Regular::a
+ ldloc.1
+ ldfld float32 Regular::a
+ ldc.r4 2.
+ beq TEST_4
+
+ ldc.i4.3
+ ret
+TEST_4:
+ ldloc.1
+ ldfld int32 Regular::a
+ ldc.i4.s 0x0a
+ beq GOOD
+
+ ldc.i4.4
+ ret
+GOOD:
+ ldc.i4.0
+ ret
+ }
+}
+
+2009-08-17 Rodrigo Kumpera <rkumpera@novell.com>
+
+ * valid_generic_type_definition_on_boxing_position.cs: Valid encoding of GTD on
+ box position.
+
+2009-08-14 Rodrigo Kumpera <rkumpera@novell.com>
+
+ *unverifiable_ldobj_with_generic_type_definition.il: Regression test for
+ bug #531237.
+
2009-07-20 Rodrigo Kumpera <rkumpera@novell.com>
* Makefile: Add support for new test kind badmd for tests with broken
--- /dev/null
+\r
+// Microsoft (R) .NET Framework IL Disassembler. Version 2.0.50727.42\r
+// Copyright (c) Microsoft Corporation. All rights reserved.\r
+\r
+\r
+\r
+// Metadata version: v2.0.50727\r
+.assembly extern mscorlib\r
+{\r
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..\r
+ .ver 2:0:0:0\r
+}\r
+.assembly 'bug-new'\r
+{\r
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx\r
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.\r
+ .hash algorithm 0x00008004\r
+ .ver 0:0:0:0\r
+}\r
+.module 'bug-new.exe'\r
+// MVID: {6822252F-C77F-4A9B-9396-C53036CCD72E}\r
+.imagebase 0x00400000\r
+.file alignment 0x00000200\r
+.stackreserve 0x00100000\r
+.subsystem 0x0003 // WINDOWS_CUI\r
+.corflags 0x00000001 // ILONLY\r
+// Image base: 0x02E80000\r
+\r
+\r
+// =============== CLASS MEMBERS DECLARATION ===================\r
+\r
+.class private auto ansi beforefieldinit G`1<T>\r
+ extends [mscorlib]System.Object\r
+{\r
+ .class sequential ansi sealed nested public beforefieldinit S<T>\r
+ extends [mscorlib]System.ValueType\r
+ {\r
+ .pack 0\r
+ .size 1\r
+ .method public hidebysig instance void \r
+ Test() cil managed\r
+ {\r
+ // Code size 22 (0x16)\r
+ .maxstack 8\r
+ IL_0000: ldarg.0\r
+ IL_0001: ldobj G`1/S\r
+ IL_0006: box G`1/S\r
+ IL_000b: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()\r
+ IL_0010: call void [mscorlib]System.Console::WriteLine(object)\r
+ IL_0015: ret\r
+ } // end of method S::Test\r
+\r
+ } // end of class S\r
+\r
+ .method public hidebysig specialname rtspecialname \r
+ instance void .ctor() cil managed\r
+ {\r
+ // Code size 7 (0x7)\r
+ .maxstack 8\r
+ IL_0000: ldarg.0\r
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()\r
+ IL_0006: ret\r
+ } // end of method G`1::.ctor\r
+\r
+} // end of class G`1\r
+\r
+.class private auto ansi beforefieldinit C\r
+ extends [mscorlib]System.Object\r
+{\r
+ .method public hidebysig specialname rtspecialname \r
+ instance void .ctor() cil managed\r
+ {\r
+ // Code size 7 (0x7)\r
+ .maxstack 8\r
+ IL_0000: ldarg.0\r
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()\r
+ IL_0006: ret\r
+ } // end of method C::.ctor\r
+\r
+ .method public hidebysig static void Main() cil managed\r
+ {\r
+ .entrypoint\r
+ // Code size 16 (0x10)\r
+ .maxstack 2\r
+ .locals init (valuetype G`1/S<int32> V_0)\r
+ IL_0000: ldloca.s V_0\r
+ IL_0002: initobj valuetype G`1/S<int32>\r
+ IL_0008: ldloca.s V_0\r
+ IL_000a: call instance void valuetype G`1/S<int32>::Test()\r
+ IL_000f: ret\r
+ } // end of method C::Main\r
+\r
+} // end of class C\r
+\r
+\r
+// =============================================================\r
+\r
+// *********** DISASSEMBLY COMPLETE ***********************\r
--- /dev/null
+using System;
+
+public class Bar<T> {
+ public int Z {get;set;}
+}
+
+public class Foo<T> {
+ public T Test {get;set;}
+ public int Z (Bar<T> t) {
+ return t.Z;
+ }
+}
+
+public struct Cat<T> {
+ T t;
+ public void Test () {
+ Console.WriteLine (GetType ());
+ }
+}
+
+
+class Driver {
+ static void Main () {
+ Cat<int> c = new Cat<int> ();
+ c.Test ();
+ new Foo<double> ().Z(new Bar<double>());
+ }
+}
\ No newline at end of file
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * strtod.c: Fix warnings for uninitialized variables.
+
+2009-08-18 Christian Hergert <chris@dronelabs.com>
+
+ * mono-proclib.c:
+ * mono-counters.c: Fix printf warnings.
+
+2009-08-12 Mark Probst <mark.probst@gmail.com>
+
+ * mono-hash.c (mono_g_hash_mark): If the keys are managed objects,
+ rehash the table after marking.
+
+2009-08-10 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+ * monobitset.h: add comment.
+
2009-08-01 Zoltan Varga <vargaz@gmail.com>
* mono-sigcontext.h (UCONTEXT_GREGS): Fix freebsd definition.
int64val = ((LongFunc)counter->addr) ();
else
int64val = *(gint64*)counter->addr;
- fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, int64val);
+ fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (long long)int64val);
break;
case MONO_COUNTER_ULONG:
if (counter->type & MONO_COUNTER_CALLBACK)
uint64val = ((ULongFunc)counter->addr) ();
else
uint64val = *(guint64*)counter->addr;
- fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, uint64val);
+ fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, (unsigned long long)uint64val);
break;
case MONO_COUNTER_WORD:
if (counter->type & MONO_COUNTER_CALLBACK)
#if SIZEOF_VOID_P == 8
fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (gint64)wordval);
#else
- fprintf (outfile, ENTRY_FMT "%d\n", counter->name, wordval);
+ fprintf (outfile, ENTRY_FMT "%d\n", counter->name, (gint)wordval);
#endif
break;
case MONO_COUNTER_DOUBLE:
}
}
}
+
+ if (table->gc_type == MONO_HASH_KEY_GC || table->gc_type == MONO_HASH_KEY_VALUE_GC)
+ g_hash_table_resize (table);
}
#endif
#if USE_SYSCTL
int mib [4];
int res;
- char *p;
size_t data_len = sizeof (struct kinfo_proc);
struct kinfo_proc processi;
#include <glib.h>
+/*
+ * When embedding, you have to define MONO_ZERO_LEN_ARRAY before including any
+ * other Mono header file if you use a different compiler from the one used to
+ * build Mono.
+ */
#ifndef MONO_ZERO_LEN_ARRAY
#ifdef __GNUC__
#define MONO_ZERO_LEN_ARRAY 0
double aadj, aadj1, adj, rv, rv0;
Long L;
ULong y, z;
- Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+ Bigint *bb = NULL, *bb1, *bd = NULL, *bd0, *bs = NULL, *delta = NULL;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
$(scripts_rpmhelpers) \
$(MDOC_SUBCOMMANDS) \
$(MDOC_COMPAT) \
- mod \
+ mod$(SCRIPT_SUFFIX) \
mono-test-install
if INSTALL_4_0
$(REWRITE2_DEBUG) -e 's,@''exe_name@,nunit-console,g' $(srcdir)/$(SCRIPT_IN) | $(FILTER) > $@.tmp
mv $@.tmp $@
+#FIXME: this is not the correct rule for mod.bat.
mod$(SCRIPT_SUFFIX): mod.in Makefile
$(REWRITE1) -e "s,@""exe_name@,mod,g" $(srcdir)/mod.in > $@.tmp
mv $@.tmp $@
$(REWRITE1) -e 's,@''exe_name@,$@,g' $(srcdir)/$(SCRIPT_IN) | $(FILTER) > $@.tmp
mv $@.tmp $@
+#FIXME: this is not the correct rule for bat files.
$(scripts_1_0_umask): script_umask.in Makefile
$(REWRITE1) -e 's,@''exe_name@,$@,g' $(srcdir)/script_umask.in > $@.tmp
mv $@.tmp $@
#define MONO_XEN_OPT 1
/* Length of zero length arrays */
-/* #undef MONO_ZERO_ARRAY_LENGTH */
+#define MONO_ZERO_LEN_ARRAY 1
/* Name of /dev/random */
#define NAME_DEV_RANDOM ""